Docs

suix_getCoinMetadata - Get Coin Metadata

Get comprehensive metadata for any coin type on Sui blockchain including decimals, symbol, name, and icon URL using Dwellir's high-performance Sui RPC infrastructure.

Retrieves comprehensive metadata for any coin type on the Sui network, including name, symbol, decimal places, and display information.

Overview

The suix_getCoinMetadata method is essential for applications that handle multiple coin types on Sui. It provides standardized metadata that enables proper formatting of coin balances, display of coin information in user interfaces, and integration with external systems. This method is crucial for wallets, DEX interfaces, portfolio trackers, and any application that needs to present coin information in a user-friendly format.

Code Examples

Common Use Cases

1. Balance Formatting in Wallets

JavaScript
async function displayWalletBalances(balances) {
  const metadataCache = new CoinMetadataCache(client);
  
  const formattedBalances = await Promise.all(
    balances.map(async (balance) => {
      const metadata = await metadataCache.getMetadata(balance.coinType);
      const amount = Number(balance.totalBalance) / Math.pow(10, metadata.decimals);
      
      return {
        symbol: metadata.symbol,
        name: metadata.name,
        amount: amount.toFixed(4),
        icon: metadata.iconUrl,
        fiatValue: amount * (await getPriceUSD(balance.coinType)) // External price API
      };
    })
  );
  
  return formattedBalances.sort((a, b) => b.fiatValue - a.fiatValue);
}

2. DEX Interface Token Selection

JavaScript
async function buildTokenList(supportedCoinTypes) {
  const tokens = [];
  
  for (const coinType of supportedCoinTypes) {
    try {
      const metadata = await getCoinMetadata(coinType);
      tokens.push({
        address: coinType,
        symbol: metadata.symbol,
        name: metadata.name,
        decimals: metadata.decimals,
        logoURI: metadata.iconUrl,
        tags: inferTokenTags(metadata) // Custom logic
      });
    } catch (error) {
      console.warn(`Failed to load metadata for ${coinType}:`, error);
    }
  }
  
  return tokens.sort((a, b) => a.symbol.localeCompare(b.symbol));
}

function inferTokenTags(metadata) {
  const tags = [];
  
  if (metadata.symbol === 'SUI') tags.push('native');
  if (['USDC', 'USDT', 'DAI'].includes(metadata.symbol)) tags.push('stablecoin');
  if (metadata.description?.toLowerCase().includes('test')) tags.push('testnet');
  
  return tags;
}

3. Cross-chain Bridge Interface

JavaScript
async function prepareBridgeTransaction(fromCoinType, toCoinType, amount) {
  const [fromMetadata, toMetadata] = await Promise.all([
    getCoinMetadata(fromCoinType),
    getCoinMetadata(toCoinType)
  ]);
  
  // Normalize amounts for comparison
  const fromAmount = Number(amount) / Math.pow(10, fromMetadata.decimals);
  const expectedToAmount = fromAmount * await getExchangeRate(fromCoinType, toCoinType);
  const toAmountRaw = Math.floor(expectedToAmount * Math.pow(10, toMetadata.decimals));
  
  return {
    fromToken: {
      symbol: fromMetadata.symbol,
      amount: fromAmount,
      decimals: fromMetadata.decimals
    },
    toToken: {
      symbol: toMetadata.symbol,
      expectedAmount: expectedToAmount,
      expectedAmountRaw: toAmountRaw.toString(),
      decimals: toMetadata.decimals
    },
    bridgeFee: await calculateBridgeFee(fromCoinType, toCoinType, amount)
  };
}

4. Analytics and Reporting

JavaScript
async function generateTokenReport(coinTypes) {
  const metadataList = await Promise.all(
    coinTypes.map(async (coinType) => {
      try {
        return await getCoinMetadata(coinType);
      } catch {
        return null;
      }
    })
  );
  
  const validMetadata = metadataList.filter(Boolean);
  
  const report = {
    totalTokens: validMetadata.length,
    byDecimals: {},
    bySymbolLength: {},
    hasIcons: validMetadata.filter(m => m.iconUrl).length,
    commonSymbols: {},
    longestName: '',
    shortestName: ''
  };
  
  validMetadata.forEach(metadata => {
    // Group by decimals
    report.byDecimals[metadata.decimals] = (report.byDecimals[metadata.decimals] || 0) + 1;
    
    // Group by symbol length
    const symbolLen = metadata.symbol.length;
    report.bySymbolLength[symbolLen] = (report.bySymbolLength[symbolLen] || 0) + 1;
    
    // Track common symbols
    report.commonSymbols[metadata.symbol] = (report.commonSymbols[metadata.symbol] || 0) + 1;
    
    // Track name lengths
    if (metadata.name.length > report.longestName.length) {
      report.longestName = metadata.name;
    }
    if (!report.shortestName || metadata.name.length < report.shortestName.length) {
      report.shortestName = metadata.name;
    }
  });
  
  return report;
}

Best Practices

1. Caching Strategy

JavaScript
// Implement aggressive caching for metadata as it rarely changes
const metadataCache = new Map();
const CACHE_TTL = 24 * 60 * 60 * 1000; // 24 hours

async function getCachedMetadata(coinType) {
  const cached = metadataCache.get(coinType);
  
  if (cached && Date.now() - cached.timestamp < CACHE_TTL) {
    return cached.metadata;
  }
  
  const metadata = await client.getCoinMetadata({ coinType });
  
  metadataCache.set(coinType, {
    metadata,
    timestamp: Date.now()
  });
  
  return metadata;
}

2. Error Handling

JavaScript
async function safeFormatBalance(coinType, balance) {
  try {
    const metadata = await getCoinMetadata(coinType);
    const formatted = Number(balance) / Math.pow(10, metadata.decimals);
    
    return {
      success: true,
      formatted: formatted,
      display: `${formatted.toFixed(4)} ${metadata.symbol}`,
      metadata: metadata
    };
  } catch (error) {
    // Fallback for unknown tokens
    return {
      success: false,
      formatted: Number(balance),
      display: `${balance} UNKNOWN`,
      error: error.message
    };
  }
}

3. Batch Loading

JavaScript
// Load metadata for multiple tokens efficiently
async function preloadMetadata(coinTypes) {
  const batchSize = 10;
  const results = [];
  
  for (let i = 0; i < coinTypes.length; i += batchSize) {
    const batch = coinTypes.slice(i, i + batchSize);
    const batchResults = await Promise.allSettled(
      batch.map(coinType => getCoinMetadata(coinType))
    );
    results.push(...batchResults);
    
    // Small delay to prevent overwhelming the RPC
    if (i + batchSize < coinTypes.length) {
      await new Promise(resolve => setTimeout(resolve, 100));
    }
  }
  
  return results;
}

Notes

  • Metadata is immutable once set for a coin type
  • Cache aggressively as metadata rarely changes
  • Handle missing metadata gracefully for unknown tokens
  • Use proper decimal precision to avoid floating point errors
  • Icon URLs may be external and should be validated before use

Need help? Contact our support team or check the Sui documentation.