GetCoinInfo - Query Coin Metadata
Retrieve comprehensive metadata for Sui coin types including name, symbol, decimals, and supply information via gRPC. Essential for token displays and DeFi applications with Dwellir.
Query Coin Type Metadata
The GetCoinInfo method retrieves comprehensive metadata for a specific coin type on Sui, including the token's name, symbol, decimals, description, and icon URI. This information is essential for displaying tokens correctly in wallets, exchanges, and DeFi applications.
Overview
Every fungible token on Sui is backed by a CoinMetadata object that stores human-readable information about the token: its name, trading symbol, decimal precision, description, and optional icon URL. The GetCoinInfo method provides direct access to this metadata, along with treasury and regulation information when available.
Token metadata is critical for any application that displays balances to users. Without knowing that SUI has 9 decimal places and USDC has 6, raw balance values are meaningless. Beyond display formatting, coin metadata is used for portfolio trackers, DEX interfaces, token listing validation, and compliance checks for regulated tokens.
Key Capabilities
- Display Formatting: Retrieve decimal precision to convert raw balances to human-readable amounts
- Token Identity: Access name, symbol, and icon URL for wallet and exchange UIs
- Supply Information: Query total supply and treasury cap details when available
- Regulation Status: Check whether a coin is regulated (e.g., can be globally paused)
- Token Validation: Verify that a coin type has valid metadata before listing or trading
Method Signature
Service: sui.rpc.v2.StateService
Method: GetCoinInfo
Type: Unary RPC
Use Cases
Token Display in Wallet
interface TokenDisplay {
name: string;
symbol: string;
iconUrl: string;
formattedBalance: string;
}
async function formatTokenForDisplay(
coinType: string,
rawBalance: string
): Promise<TokenDisplay> {
const info = await getCoinInfo(coinType);
// Convert raw balance to human-readable format
const balance = Number(rawBalance) / Math.pow(10, info.decimals);
return {
name: info.name,
symbol: info.symbol,
iconUrl: info.icon_url,
formattedBalance: balance.toFixed(info.decimals)
};
}
// Usage
const display = await formatTokenForDisplay(
'0x2::sui::SUI',
'5000000000' // 5 SUI in MIST
);
console.log(`${display.formattedBalance} ${display.symbol}`); // "5.000000000 SUI"Multi-Token Portfolio Display
interface PortfolioToken {
coinType: string;
balance: string;
metadata: any;
}
async function enrichPortfolio(
tokens: PortfolioToken[]
): Promise<any[]> {
// Fetch all coin metadata in parallel
const metadataPromises = tokens.map(token =>
getCoinInfo(token.coinType)
.catch(err => {
console.warn(`Failed to get info for ${token.coinType}:`, err.message);
return null;
})
);
const metadataList = await Promise.all(metadataPromises);
return tokens.map((token, index) => {
const metadata = metadataList[index];
if (!metadata) {
return {
...token,
name: 'Unknown Token',
symbol: '???',
decimals: 0
};
}
const balance = Number(token.balance) / Math.pow(10, metadata.decimals);
return {
coinType: token.coinType,
name: metadata.name,
symbol: metadata.symbol,
iconUrl: metadata.icon_url,
rawBalance: token.balance,
formattedBalance: balance.toFixed(metadata.decimals),
decimals: metadata.decimals
};
});
}Token Validation
async function validateTokenContract(coinType: string): Promise<boolean> {
try {
const info = await getCoinInfo(coinType);
// Basic validation checks
if (!info.name || !info.symbol) {
console.warn('Invalid token: missing name or symbol');
return false;
}
if (info.decimals < 0 || info.decimals > 18) {
console.warn('Invalid token: decimals out of range');
return false;
}
return true;
} catch (error) {
console.error('Token validation failed:', error);
return false;
}
}Caching Strategy
class CoinInfoCache {
private cache = new Map<string, any>();
private ttl = 3600000; // 1 hour
async get(coinType: string): Promise<any> {
const cached = this.cache.get(coinType);
if (cached && Date.now() - cached.timestamp < this.ttl) {
return cached.data;
}
const info = await getCoinInfo(coinType);
this.cache.set(coinType, {
data: info,
timestamp: Date.now()
});
return info;
}
clear(): void {
this.cache.clear();
}
}
// Usage
const cache = new CoinInfoCache();
const info = await cache.get('0x2::sui::SUI'); // Fetches from network
const info2 = await cache.get('0x2::sui::SUI'); // Returns cached valueBest Practices
Metadata Caching
Coin metadata rarely changes, making it ideal for aggressive caching:
// Cache for entire application lifecycle
const METADATA_CACHE = new Map<string, any>();
async function getCachedCoinInfo(coinType: string): Promise<any> {
if (METADATA_CACHE.has(coinType)) {
return METADATA_CACHE.get(coinType);
}
const info = await getCoinInfo(coinType);
METADATA_CACHE.set(coinType, info);
return info;
}Error Handling
async function getCoinInfoSafe(coinType: string): Promise<any | null> {
try {
return await getCoinInfo(coinType);
} catch (error: any) {
if (error.code === grpc.status.NOT_FOUND) {
console.warn(`Coin type not found: ${coinType}`);
return null;
}
if (error.code === grpc.status.INVALID_ARGUMENT) {
console.error(`Invalid coin type format: ${coinType}`);
return null;
}
// Re-throw unexpected errors
throw error;
}
}Decimal Conversion Utility
function convertToHumanReadable(
rawAmount: string | bigint,
decimals: number
): string {
const amount = BigInt(rawAmount);
const divisor = BigInt(10 ** decimals);
const whole = amount / divisor;
const fraction = amount % divisor;
const fractionStr = fraction.toString().padStart(decimals, '0');
return `${whole}.${fractionStr}`;
}
// Usage with coin info
const info = await getCoinInfo('0x2::sui::SUI');
const readable = convertToHumanReadable('5000000000', info.decimals);
console.log(readable); // "5.000000000"Performance Characteristics
| Metric | Value |
|---|---|
| Typical Latency | 10-20ms |
| Response Size | ~200-500 bytes |
| Cache Recommended | Yes (long TTL) |
| Rate Limit Impact | Very low |
Common Errors
| Error Code | Scenario | Solution |
|---|---|---|
NOT_FOUND | Coin type doesn't exist | Verify coin type address |
INVALID_ARGUMENT | Malformed coin type | Check type format: package::module::type |
UNAUTHENTICATED | Missing/invalid token | Verify x-api-key header |
Related Methods
- GetBalance - Query coin balances
- ListBalances - List all balances for an address
Need help? Contact support@dwellir.com or check the gRPC overview.
GetBalance
Query Sui coin balances efficiently using the gRPC GetBalance method. Check SUI and custom token balances with high-performance binary serialization through Dwellir's Sui infrastructure.
ListBalances
Retrieve all token balances for a Sui address via gRPC including multiple coin types. Essential for portfolio displays and multi-token wallets with Dwellir.