Menu
Documentation
API reference Token amounts

Token amounts

Preserve exact integer quantities from your calculation through the transfer.

All API token quantities are decimal strings of integer base units. Never send a JavaScript number, floating-point token value, or formatted currency amount.

json
{
  "amountBaseUnits": "1000000"
}

For a token with six decimals, this represents one whole token. It does not represent one dollar unless your own calculation has explicitly established that allocation.

Convert with the campaign's decimals#

For token decimals d:

text
base units = token units × 10^d

Read asset.decimals from the approved campaign. Do not assume 18 decimals or infer decimals from the symbol.

Token decimalsToken amountBase-unit string
61"1000000"
60.25"250000"
181"1000000000000000000"
180.000001"1000000000000"

Exact string conversion#

Prefer storing already-calculated base-unit strings in your reward records. When accepting a decimal token string in your own configuration, convert it without floating-point arithmetic:

ts
function toBaseUnits(value: string, decimals: number): string {
  if (!Number.isInteger(decimals) || decimals < 0 || decimals > 255) {
    throw new Error("Invalid decimals");
  }
  if (value.length > 512 || !/^(0|[1-9][0-9]*)(\.[0-9]+)?$/.test(value)) {
    throw new Error("Use a plain nonnegative decimal token string");
  }
  const [whole, fraction = ""] = value.split(".");
  if (fraction.length > decimals) {
    throw new Error("Too many fractional digits; choose an explicit rounding policy");
  }
  const units = BigInt(whole + fraction.padEnd(decimals, "0"));
  const maximum = (1n << 256n) - 1n;
  if (units <= 0n || units > maximum) {
    throw new Error("Reward amount is outside the positive uint256 range");
  }
  return units.toString();
}

console.log(toBaseUnits("0.25", 6)); // "250000"

This helper only converts representation. It does not enforce campaign limits, price a token, or establish whether the recipient earned the amount.

Accepted and rejected formats#

ValueAccepted as an issuance amount?
"1"Yes, subject to campaign limits.
"1000000"Yes, subject to campaign limits.
1000000No: JSON number.
"0"No: issuance must be positive.
"01"No: leading zero.
"1.5"No: fractional base units.
"1e6"No: scientific notation.
"+1", "-1", " 1 "No: signs or whitespace.

The maximum representable API quantity is 2^256 - 1. Runtime validation enforces the actual bound, not just a 78-digit length limit. Campaign limits, and the operator's wallet balance, are far lower.

Response fields representing balances or delivered quantities can be "0". The positive issuance rule does not apply to every quantity field.

Net entitlement and display#

The issued amount is net of the Slices fee, which the operator's wallet pays as a separate transfer. Do not deduct a fee from it later.

Format for display from the integer string and decimals. Keep the original string available for exact inspection and copying. Do not use Number(amountBaseUnits) for accounting, comparison, totals, or serialization.

Do not silently round an overprecise decimal reward. Define that policy in your application, calculate once, and persist the final integer allocation before issuing.

Related: Grant a reward, Assets, and Funding and budgets.