Skip to main content

Overview

Different blockchains use different decimal places and units for their native assets and tokens. This reference provides conversion formulas and utilities for accurate amount handling across all supported chains.

Common Conversion Formulas

Base Units to Display Units

function toDisplayUnits(amount, decimals) {
  return amount / Math.pow(10, decimals);
}

// Examples
toDisplayUnits(100000000, 8);  // 1.0 BTC
toDisplayUnits(1000000, 6);    // 1.0 USDC
toDisplayUnits(1000000000000000000, 18); // 1.0 ETH

Display Units to Base Units

function toBaseUnits(amount, decimals) {
  return Math.floor(amount * Math.pow(10, decimals));
}

// Examples
toBaseUnits(1.0, 8);   // 100000000 satoshis
toBaseUnits(1.0, 6);   // 1000000 (USDC)
toBaseUnits(1.0, 18);  // 1000000000000000000 wei

Safe Conversion with BigInt

For JavaScript environments supporting BigInt:
function toBaseUnitsSafe(amount, decimals) {
  const [whole, fraction = ''] = amount.toString().split('.');
  const paddedFraction = fraction.padEnd(decimals, '0').slice(0, decimals);
  return BigInt(whole + paddedFraction);
}

// Examples
toBaseUnitsSafe('1.0', 18);     // 1000000000000000000n
toBaseUnitsSafe('0.5', 18);     // 500000000000000000n
toBaseUnitsSafe('1.23456789', 8); // 123456789n

Bitcoin & UTXO Chains

Bitcoin (BTC)

Decimals: 8 Base Unit: Satoshi Conversion: 1 BTC = 100,000,000 satoshis
// Satoshis to BTC
const btc = satoshis / 100000000;
// Or
const btc = satoshis / 1e8;

// BTC to Satoshis
const satoshis = btc * 100000000;
// Or
const satoshis = Math.floor(btc * 1e8);

// Examples
100000000 // satoshis → 1.0 BTC
50000000  // satoshis → 0.5 BTC
1234567   // satoshis → 0.01234567 BTC

Litecoin (LTC)

Decimals: 8 Base Unit: Litoshi Conversion: 1 LTC = 100,000,000 litoshis
// Same as Bitcoin
const ltc = litoshis / 1e8;
const litoshis = Math.floor(ltc * 1e8);

Dogecoin (DOGE)

Decimals: 8 Base Unit: Shibe Conversion: 1 DOGE = 100,000,000 shibes
const doge = shibes / 1e8;
const shibes = Math.floor(doge * 1e8);

// Important: DOGE dust limit
const DOGE_DUST_LIMIT = 100000000; // 1 DOGE
if (shibes < DOGE_DUST_LIMIT) {
  console.warn('Amount below dust limit');
}

Dash (DASH)

Decimals: 8 Base Unit: Duff Conversion: 1 DASH = 100,000,000 duffs
const dash = duffs / 1e8;
const duffs = Math.floor(dash * 1e8);

Bitcoin Cash (BCH)

Decimals: 8 Base Unit: Satoshi Conversion: 1 BCH = 100,000,000 satoshis
const bch = satoshis / 1e8;
const satoshis = Math.floor(bch * 1e8);

Zcash (ZEC)

Decimals: 8 Base Unit: Zatoshi Conversion: 1 ZEC = 100,000,000 zatoshis
const zec = zatoshis / 1e8;
const zatoshis = Math.floor(zec * 1e8);

Ethereum & EVM Chains

Ethereum (ETH)

Decimals: 18 Base Unit: Wei Conversion: 1 ETH = 1,000,000,000,000,000,000 wei
// Wei to ETH
const eth = wei / 1000000000000000000;
// Or
const eth = wei / 1e18;

// Using ethers.js library
import { ethers } from 'ethers';
const eth = ethers.utils.formatEther(wei);
const wei = ethers.utils.parseEther(eth);

// Gwei to ETH (for gas prices)
const ethFromGwei = gwei / 1000000000;
// Or
const ethFromGwei = gwei / 1e9;

// Wei to Gwei
const gwei = wei / 1e9;

// Examples
1000000000000000000 // wei → 1.0 ETH
1000000000          // wei → 1.0 gwei
25500000000         // wei → 25.5 gwei (typical gas price)

Gas Price Conversions

// Gwei to Wei
function gweiToWei(gwei) {
  return Math.floor(gwei * 1e9);
}

// Wei to Gwei
function weiToGwei(wei) {
  return wei / 1e9;
}

// Examples
gweiToWei(25.5);    // 25500000000 wei
weiToGwei(25500000000); // 25.5 gwei

ERC-20 Tokens

Different ERC-20 tokens use different decimal places:
TokenDecimalsExample Conversion
USDC61000000 → 1.0 USDC
USDT61000000 → 1.0 USDT
DAI181000000000000000000 → 1.0 DAI
WBTC8100000000 → 1.0 WBTC
LINK181000000000000000000 → 1.0 LINK
// Generic ERC-20 conversion
function convertToken(amount, decimals) {
  return amount / Math.pow(10, decimals);
}

// Examples
convertToken(1000000, 6);      // 1.0 USDC
convertToken(1000000000000000000, 18); // 1.0 DAI
convertToken(100000000, 8);    // 1.0 WBTC

Cosmos Chains

THORChain (THOR)

Decimals: 8 Base Unit: Tor (1/100,000,000 RUNE) Conversion: 1 RUNE = 100,000,000 tor
const rune = tor / 1e8;
const tor = Math.floor(rune * 1e8);

// Fixed fee
const THOR_FIXED_FEE = 2000000; // 0.02 RUNE

MAYAChain (MAYA)

CRITICAL: CACAO uses 10 decimals, not 8! Decimals: 10 (for CACAO), 8 (for other assets) Base Unit: Smallest CACAO unit Conversion: 1 CACAO = 10,000,000,000 base units
// CACAO conversion (10 decimals)
const cacao = baseUnits / 1e10;
const baseUnits = Math.floor(cacao * 1e10);

// Normalize CACAO to standard 1e8 format
function normalizeCacao(amount) {
  return (amount / 1e10) * 1e8;
}

// Examples
10000000000   // → 1.0 CACAO (10 decimals)
100000000000  // → 10.0 CACAO (10 decimals)

// Normalization
normalizeCacao(10000000000);  // → 100000000 (standard 1e8)
Important: Always check if asset is MAYA.CACAO:
function getDecimals(asset) {
  return asset === 'MAYA.CACAO' ? 10 : 8;
}

Cosmos Hub (GAIA)

Decimals: 6 Base Unit: uatom (micro-ATOM) Conversion: 1 ATOM = 1,000,000 uatom
const atom = uatom / 1e6;
const uatom = Math.floor(atom * 1e6);

// Examples
1000000  // uatom → 1.0 ATOM
500000   // uatom → 0.5 ATOM

Kujira (KUJI)

Decimals: 6 Base Unit: ukuji (micro-KUJI) Conversion: 1 KUJI = 1,000,000 ukuji
const kuji = ukuji / 1e6;
const ukuji = Math.floor(kuji * 1e6);

NEAR Protocol

Decimals: 24 Base Unit: YoctoNEAR Conversion: 1 NEAR = 1,000,000,000,000,000,000,000,000 yoctoNEAR
// YoctoNEAR to NEAR
const near = yoctoNEAR / 1e24;
// Or
const near = yoctoNEAR / 1000000000000000000000000;

// NEAR to YoctoNEAR
const yoctoNEAR = Math.floor(near * 1e24);

// Examples
1000000000000000000000000  // → 1.0 NEAR
5000000000000000000000000  // → 5.0 NEAR

// Using NEAR API library
import { utils } from 'near-api-js';
const near = utils.format.formatNearAmount(yoctoNEAR);
const yoctoNEAR = utils.format.parseNearAmount(near);

NEAR Token Conversions

NEP-141 tokens have variable decimals:
// Must fetch decimals from token metadata
async function getNEP141Decimals(contractId) {
  const metadata = await contract.ft_metadata();
  return metadata.decimals;
}

// Example: USDC on NEAR
const NEAR_USDC_DECIMALS = 6;
const usdc = amount / 1e6;

NEAR Gas Units

// TGas (TeraGas) conversions
const TGAS = 1000000000000; // 1 TGas = 10^12 gas

// Standard ft_transfer gas
const FT_TRANSFER_GAS = 30 * TGAS; // 30 TGas

// Attached deposit (always 1 yoctoNEAR for tokens)
const ATTACHED_DEPOSIT = '1';

Other Chains

Ripple (XRP)

Decimals: 6 Base Unit: Drop Conversion: 1 XRP = 1,000,000 drops
const xrp = drops / 1e6;
const drops = Math.floor(xrp * 1e6);

// Reserve requirement
const XRP_RESERVE = 10000000; // 10 XRP in drops

Solana (SOL)

Decimals: 9 Base Unit: Lamport Conversion: 1 SOL = 1,000,000,000 lamports
const sol = lamports / 1e9;
const lamports = Math.floor(sol * 1e9);

// Using Solana web3.js
import { LAMPORTS_PER_SOL } from '@solana/web3.js';
const sol = lamports / LAMPORTS_PER_SOL;
const lamports = sol * LAMPORTS_PER_SOL;

Tron (TRON)

Decimals: 6 Base Unit: Sun Conversion: 1 TRX = 1,000,000 sun
const trx = sun / 1e6;
const sun = Math.floor(trx * 1e6);

Cardano (ADA)

Decimals: 6 Base Unit: Lovelace Conversion: 1 ADA = 1,000,000 lovelace
const ada = lovelace / 1e6;
const lovelace = Math.floor(ada * 1e6);

Basis Points (BPS) Conversions

Basis points are commonly used for fees and slippage.
// BPS to Percentage
function bpsToPercent(bps) {
  return bps / 100;
}

// BPS to Decimal
function bpsToDecimal(bps) {
  return bps / 10000;
}

// Percentage to BPS
function percentToBps(percent) {
  return percent * 100;
}

// Examples
bpsToPercent(150);    // 1.5%
bpsToDecimal(150);    // 0.015
percentToBps(1.5);    // 150 BPS

// Apply BPS fee to amount
function applyBpsFee(amount, feeBps) {
  return Math.floor(amount * feeBps / 10000);
}

applyBpsFee(100000000, 30);  // 300000 (0.3% of 1 BTC)

Decimal Handling Best Practices

Avoiding Floating Point Errors

// ❌ Bad: Floating point precision issues
const result = 0.1 + 0.2; // 0.30000000000000004

// ✅ Good: Use integer arithmetic
function add(a, b, decimals) {
  const aInt = Math.floor(a * Math.pow(10, decimals));
  const bInt = Math.floor(b * Math.pow(10, decimals));
  return (aInt + bInt) / Math.pow(10, decimals);
}

add(0.1, 0.2, 8); // 0.3 (exact)

Using Big Number Libraries

// Using bignumber.js
import BigNumber from 'bignumber.js';

const amount = new BigNumber('1.23456789');
const baseUnits = amount.times(1e8).integerValue();
// 123456789

// Using ethers.js for Ethereum
import { ethers } from 'ethers';

const eth = '1.5';
const wei = ethers.utils.parseEther(eth);
// BigNumber { _hex: '0x14d1120d7b160000' }

const ethBack = ethers.utils.formatEther(wei);
// '1.5'

Rounding Strategies

// Floor (always round down)
Math.floor(1.9999 * 1e8) / 1e8; // 1.99990000

// Ceil (always round up)
Math.ceil(1.0001 * 1e8) / 1e8;  // 1.00010000

// Round (banker's rounding)
Math.round(1.5555 * 1e8) / 1e8; // 1.55550000

// Truncate decimals
function truncate(amount, decimals) {
  const multiplier = Math.pow(10, decimals);
  return Math.floor(amount * multiplier) / multiplier;
}

truncate(1.23456789, 6); // 1.234567

Display Formatting

Human-Readable Amounts

function formatAmount(amount, decimals, displayDecimals = 6) {
  const converted = amount / Math.pow(10, decimals);
  return converted.toFixed(displayDecimals);
}

formatAmount(100000000, 8, 2);  // "1.00"
formatAmount(123456789, 8, 4);  // "1.2346"
formatAmount(1000000, 6, 2);    // "1.00"

Compact Notation

function formatCompact(amount, decimals) {
  const value = amount / Math.pow(10, decimals);

  if (value >= 1e9) return (value / 1e9).toFixed(2) + 'B';
  if (value >= 1e6) return (value / 1e6).toFixed(2) + 'M';
  if (value >= 1e3) return (value / 1e3).toFixed(2) + 'K';
  return value.toFixed(2);
}

formatCompact(100000000000000, 8); // "1000000.00" or "1.00M"
formatCompact(1000000000, 6);      // "1000.00" or "1.00K"

Currency Formatting

function formatCurrency(amount, decimals, currency = 'USD') {
  const value = amount / Math.pow(10, decimals);
  return new Intl.NumberFormat('en-US', {
    style: 'currency',
    currency: currency,
    minimumFractionDigits: 2,
    maximumFractionDigits: 2
  }).format(value);
}

formatCurrency(9850000000, 6, 'USD'); // "$9,850.00"

Validation

Amount Range Validation

function validateAmount(amount, decimals, min = 0, max = Infinity) {
  const value = amount / Math.pow(10, decimals);
  return value >= min && value <= max;
}

// Validate minimum swap amount
validateAmount(100000000, 8, 0.01, 100); // true (1 BTC)
validateAmount(100000, 8, 0.01, 100);    // false (0.001 BTC < min)

Dust Threshold Checks

const DUST_LIMITS = {
  'BTC': 546,      // satoshis
  'LTC': 546,      // litoshis
  'DOGE': 100000000, // shibes (1 DOGE)
  'BCH': 546       // satoshis
};

function isDust(amount, chain) {
  return amount < (DUST_LIMITS[chain] || 0);
}

isDust(500, 'BTC');  // true (below 546 sats)
isDust(1000, 'BTC'); // false

Quick Reference Table

ChainDecimalsBase Unit1 Unit in BaseExample
BTC8satoshi100,000,0001 BTC = 100M sats
ETH18wei1,000,000,000,000,000,0001 ETH = 1e18 wei
USDC6base1,000,0001 USDC = 1M
NEAR24yoctoNEAR1e241 NEAR = 1e24 yocto
THOR.RUNE8tor100,000,0001 RUNE = 100M tor
MAYA.CACAO10base10,000,000,0001 CACAO = 10B
GAIA.ATOM6uatom1,000,0001 ATOM = 1M uatom
SOL9lamport1,000,000,0001 SOL = 1B lamports
XRP6drop1,000,0001 XRP = 1M drops

Common Conversion Patterns

Convert Quote Amounts

function convertQuoteAmount(quote) {
  const fromDecimals = getAssetDecimals(quote.from_asset);
  const toDecimals = getAssetDecimals(quote.to_asset);

  return {
    input: quote.amount / Math.pow(10, fromDecimals),
    output: quote.expected_amount_out / Math.pow(10, toDecimals)
  };
}

Calculate Exchange Rate

function calculateRate(inputAmount, outputAmount, inputDecimals, outputDecimals) {
  const input = inputAmount / Math.pow(10, inputDecimals);
  const output = outputAmount / Math.pow(10, outputDecimals);
  return output / input;
}

// Example: 1 BTC → 65,000 USDC
calculateRate(100000000, 65000000000, 8, 6); // 65000