SettleMint
Developer guidesAPI integration

Asset decimals

Understand how asset amounts work with scaled integers and dnum format.

Asset amounts in the API use scaled integers, not decimal numbers. This guide explains why and how to work with them correctly.

Quick summary

  • Amounts are integers scaled by 10^decimals (no floating-point)
  • API accepts plain strings OR dnum tuples for input
  • API responses return decimal strings: "1.000000" (locale-independent, trailing zeros preserve precision)
  • Formula: scaled_value = human_amount × 10^decimals

Why scaled integers?

Computers can't do reliable decimal math. Try this in any programming language:

0.1 + 0.2 = 0.30000000000000004

For financial calculations, this is unacceptable. The solution: store everything as integers.

Think of it like storing money as cents instead of dollars:

  • $10.50 becomes 1050 cents
  • No decimal point, no rounding errors

Blockchains use the same approach. The decimals field tells you how to convert:

  • 0 decimals = whole units (like shares)
  • 2 decimals = cents (like USD)
  • 18 decimals = standard for most tokens

The dnum format

The platform uses dnum (decimal number) tuples to represent amounts:

[scaled_value, decimals]

Examples:

  • 100 shares (0 decimals): ["100", 0]
  • $10.50 (2 decimals): ["1050", 2]
  • 1.5 tokens (18 decimals): ["1500000000000000000", 18]

The first element is a BigInt in code. Over JSON/HTTP, it serializes as a string to preserve precision.

Sending API requests

The API accepts two formats for amounts:

Option 1: Plain string (simpler)

Just send the scaled value as a string:

{
  "amounts": "1500000000000000000"
}

Pairs the value with decimals—matches the response format:

{
  "amounts": ["1500000000000000000", 18]
}

Batch operations

For multiple amounts, use arrays:

{
  "amounts": [
    ["1500000000000000000", 18],
    ["500000000000000000", 18]
  ]
}

Reading API responses

Responses return locale-independent decimal strings. Trailing zeros encode the precision so the round-trip is lossless:

{
  "totalSupply": "1000.000000000000000000",
  "basePrice": "100.00"
}

To convert back to human-readable, parse the decimal string directly — no division required:

"1000.000000000000000000" → 1000 tokens (18 decimal places of precision)
"100.00" → $100.00 (2 decimal places)

Legacy format (backward compatibility)

Older API versions returned dnum tuples. Both the SDK and direct callers handle this transparently:

{
  "totalSupply": ["1000000000000000000000", 18]
}

If you interact with a mix of old and new API versions during a rolling deployment, the deserializer accepts both formats automatically.

Quick reference

You want to sendDecimalsPlain stringDnum tuple
100 shares0"100"["100", 0]
10.50 dollars2"1050"["1050", 2]
1.5 tokens18"1500000000000000000"["1500000000000000000", 18]
0.001 tokens18"1000000000000000"["1000000000000000", 18]

Converting amounts

Human-readable to API format

To convert "1.5" with 18 decimals:

1. Split at decimal point: whole = "1", fraction = "5"
2. Pad fraction to 18 chars: "500000000000000000"
3. Concatenate: "1" + "500000000000000000" = "1500000000000000000"
4. Result: ["1500000000000000000", 18]

API response to human-readable

Responses now return a locale-independent decimal string like "1.500000000000000000". Parse the decimal point directly — no division required. The number of digits after the decimal point tells you the precision.

If you receive a legacy tuple ["1500000000000000000", 18] (from an older server during a rolling deployment):

1. Divide: 1500000000000000000 ÷ 10^18 = 1 (whole part)
2. Remainder: 1500000000000000000 % 10^18 = 500000000000000000
3. Format: "1.500000000000000000"

Use BigInt libraries

Never use floating-point for these calculations. Use your language's arbitrary precision integer library (BigInt, BigInteger, bcmath, etc.) to avoid precision loss.

Checking asset decimals

Asset detail showing contract-level decimal configuration

Always check the asset's decimals before sending amounts:

curl -X GET "https://your-platform.example.com/api/token/0x9459D52E60edBD3178f00F9055f6C117a21b4220" \
  -H "X-Api-Key: YOUR_API_KEY"

Response:

{
  "name": "ACME Holdings Common Stock",
  "symbol": "ACME",
  "decimals": 0,
  "totalSupply": "1000000"
}

Common mistakes

MistakeProblemFix
"amounts": "1.5"Sends 15 smallest units, not 1.5 tokensMultiply by 10^decimals first
Using float/doublePrecision loss on large numbersUse BigInt/BigInteger
"1.5e18"Scientific notation may not parseUse full integer string
Forgetting to check decimalsWrong scale for the assetAlways GET the asset first

Full example

# Step 1: Get asset info (including decimals)
curl -X GET "https://your-platform.example.com/api/token/0x1234..." \
  -H "X-Api-Key: YOUR_API_KEY"

# Response shows decimals: 18

# Step 2: Calculate amount for 1.5 tokens
# 1.5 × 10^18 = 1500000000000000000

# Step 3: Mint using dnum tuple (recommended)
curl -X POST "https://your-platform.example.com/api/token/0x1234.../mint" \
  -H "X-Api-Key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "recipients": ["0xABCD..."],
    "amounts": ["1500000000000000000", 18],
    "walletVerification": {
      "verificationType": "PINCODE",
      "secretVerificationCode": "123456"
    }
  }'

On this page