Skip to content

sup.blockchain

The sup.blockchain package provides read-only access to EVM-compatible blockchain data. It supports Ethereum mainnet and major Layer 2 networks including Base, Optimism, Arbitrum, Polygon, and Zora.

Example sup.blockchain Usage
// Get current block number
const blockNum = sup.blockchain.eth.blockNumber();
// Get ETH balance (vitalik.eth)
const balance = sup.blockchain.eth.balance('0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045');
const formatted = sup.blockchain.eth.format(balance);
// Get token price
const ethPrice = sup.blockchain.eth.price('ETH');
console.log('ETH price:', ethPrice.toString());
// Read from a smart contract
const usdc = sup.blockchain.eth.erc20('0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48');
const symbol = usdc.symbol(); // "USDC"
const decimals = usdc.decimals(); // 6
// Use other chains
const baseBalance = sup.blockchain.eth.chain('base').balance('0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045');

Security Notice

All blockchain operations are read-only. There is no transaction signing, private key handling, or write operations. This API is designed for safely querying blockchain data without any risk of funds movement.


Properties

sup.blockchain.eth

SupBlockchainChain

The primary interface for Ethereum mainnet operations. All methods are available directly on this object.


Chain Information

sup.blockchain.eth.blockNumber()

→ string

const blockNum = sup.blockchain.eth.blockNumber();
console.log('Current block:', blockNum);

Returns the current block number for the chain as a string.


Balances

sup.blockchain.eth.balance()

(address: string, token?: string) → string

// Get native ETH balance (vitalik.eth)
const ethBalance = sup.blockchain.eth.balance('0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045');
console.log('ETH:', sup.blockchain.eth.format(ethBalance));
// Get ERC20 token balance
const usdcBalance = sup.blockchain.eth.balance(
'0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045',
'0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48'
);
console.log('USDC:', sup.blockchain.eth.format(usdcBalance, 6));

Get wallet balance for native token (ETH) or any ERC20 token. Returns the balance as a string in the smallest unit (wei for ETH, or token’s base unit).

Parameters:

  • address (string): Wallet address to query
  • token (string, optional): ERC20 token contract address. Omit for native token.

Returns: Balance as string in wei/smallest unit


Token Prices

sup.blockchain.eth.price()

(contractOrTicker: string) → SupBigNumber

// Get price by ticker symbol
const ethPrice = sup.blockchain.eth.price('ETH');
console.log('ETH price:', ethPrice.toString());
// Get price by contract address
const usdcPrice = sup.blockchain.eth.price('0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48');
console.log('USDC price:', usdcPrice.toFixed(6));
// Perform calculations with precision
const doubled = ethPrice.times(2);
const ethAmount = new SupBigNumber('1.5');
const totalValue = ethAmount.times(ethPrice);
console.log('Value of 1.5 ETH:', totalValue.toFixed(2), 'USD');

Get current USD price for a token from DeFiLlama. Returns a SupBigNumber with 18 decimal precision for mathematical operations.

Parameters:

  • contractOrTicker (string): Either a contract address (starting with 0x) or a ticker symbol (like ETH, USDC, BTC)

Returns: SupBigNumber with the USD price

See the SupBigNumber documentation for available operations.


Smart Contract Reads

sup.blockchain.eth.contract()

(address: string, abi: any[], functionName: string, args?: any[]) → any

const balance = sup.blockchain.eth.contract(
'0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48',
[
{
"constant": true,
"inputs": [{"name": "_owner", "type": "address"}],
"name": "balanceOf",
"outputs": [{"name": "balance", "type": "uint256"}],
"type": "function"
}
],
'balanceOf',
['0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045']
);

Read data from any smart contract by providing the ABI and function details.

Parameters:

  • address (string): Contract address
  • abi (any[]): Array containing the function ABI
  • functionName (string): Name of the function to call
  • args (any[], optional): Array of arguments to pass to the function

Returns: The function’s return value (type depends on the contract function)


ERC20 Tokens

sup.blockchain.eth.erc20()

(address: string) → SupERC20

const usdc = sup.blockchain.eth.erc20('0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48');
// Get token info
const symbol = usdc.symbol(); // "USDC"
const name = usdc.name(); // "USD Coin"
const decimals = usdc.decimals(); // 6
const supply = usdc.totalSupply(); // Total supply in base units
// Check balances
const balance = usdc.balanceOf('0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045');
// Check allowances
const allowance = usdc.allowance(
'0xOwnerAddress...',
'0xSpenderAddress...'
);

Convenience wrapper for ERC20 token operations. Returns an object with methods that automatically use the ERC20 ABI.

Returns: Object with the following methods:

SupERC20 Methods

  • balanceOf(account: string)string - Get token balance for an address
  • totalSupply()string - Get total token supply
  • decimals()number - Get number of decimals
  • symbol()string - Get token symbol
  • name()string - Get token name
  • allowance(owner: string, spender: string)string - Get approved spending amount

sup.blockchain.eth.token()

(address: string) → TokenMetadata

const metadata = sup.blockchain.eth.token('0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48');
console.log(`${metadata.symbol}: ${metadata.name}`);
console.log(`Decimals: ${metadata.decimals}`);
console.log(`Total Supply: ${metadata.totalSupply}`);

Get comprehensive metadata for an ERC20 token in a single call.

Returns: Object with:

  • name (string): Token name
  • symbol (string): Token symbol
  • decimals (number): Number of decimals
  • totalSupply (string): Total supply in base units

ERC721 NFTs

sup.blockchain.eth.erc721()

(address: string) → SupERC721

const blitmap = sup.blockchain.eth.erc721('0x8d04a8c79cEB0889Bdd12acdF3Fa9D207eD3Ff63');
// Get NFT info
const name = blitmap.name(); // "Blitmap"
const symbol = blitmap.symbol(); // "BLIT"
const supply = blitmap.totalSupply(); // "1700"
// Check ownership
const owner = blitmap.ownerOf(1); // Owner address of token #1
const balance = blitmap.balanceOf('0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045');
// Get metadata
const uri = blitmap.tokenURI(1); // Metadata URI for token #1
// Check approvals
const approved = blitmap.getApproved(1); // Address approved for token #1
const isApproved = blitmap.isApprovedForAll('0xOwner...', '0xOperator...');

Convenience wrapper for ERC721 NFT operations.

Returns: Object with the following methods:

SupERC721 Methods

  • balanceOf(owner: string)string - Get NFT count for an address
  • ownerOf(tokenId: number | string)string - Get owner of a specific token
  • tokenURI(tokenId: number | string)string - Get metadata URI
  • name()string - Get collection name
  • symbol()string - Get collection symbol
  • totalSupply()string - Get total number of tokens
  • getApproved(tokenId: number | string)string - Get approved address for token
  • isApprovedForAll(owner: string, operator: string)boolean - Check operator approval

ERC1155 Multi-Tokens

sup.blockchain.eth.erc1155()

(address: string) → SupERC1155

const nft = sup.blockchain.eth.erc1155('0x495f947276749ce646f68ac8c248420045cb7b5e');
// Check balance for specific token ID
const balance = nft.balanceOf('0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb', 1);
// Check multiple balances at once
const balances = nft.balanceOfBatch(
['0xAddress1...', '0xAddress2...'],
[1, 2]
);
// Get metadata URI
const uri = nft.uri(1);
// Check approvals
const isApproved = nft.isApprovedForAll('0xOwner...', '0xOperator...');

Convenience wrapper for ERC1155 multi-token operations.

Returns: Object with the following methods:

SupERC1155 Methods

  • balanceOf(account: string, id: number | string)string - Get balance for specific token ID
  • balanceOfBatch(accounts: string[], ids: (number | string)[])string[] - Get multiple balances
  • uri(id: number | string)string - Get metadata URI for token ID
  • isApprovedForAll(owner: string, operator: string)boolean - Check operator approval

Transactions

sup.blockchain.eth.tx()

(hash: string) → Transaction

const tx = sup.blockchain.eth.tx('0x123...');
console.log('From:', tx.from);
console.log('To:', tx.to);
console.log('Value:', tx.value);
console.log('Block:', tx.blockNumber);

Get details about a transaction by its hash.

Returns: Transaction object with properties like from, to, value, gas, blockNumber, etc.


Utility Functions

sup.blockchain.eth.format()

(value: string | number, decimals?: number) → number

const balance = sup.blockchain.eth.balance(address);
const formatted = sup.blockchain.eth.format(balance, 18);
console.log('Balance:', formatted, 'ETH');
// USDC has 6 decimals
const usdcBalance = sup.blockchain.eth.balance(address, usdcAddress);
const usdcFormatted = sup.blockchain.eth.format(usdcBalance, 6);
console.log('Balance:', usdcFormatted, 'USDC');

Convert from wei/smallest unit to human-readable value.

Parameters:

  • value (string | number): Value in wei or smallest unit
  • decimals (number, optional): Token decimals (default: 18 for ETH)

Returns: Formatted value as JavaScript number

Note: Since this returns a JavaScript Number, precision may be lost for very large values. For precise calculations, use SupBigNumber operations instead.


sup.blockchain.eth.parse()

(value: number, decimals?: number) → string

const amount = sup.blockchain.eth.parse(1.5, 18);
console.log('1.5 ETH in wei:', amount);
const usdcAmount = sup.blockchain.eth.parse(100, 6);
console.log('100 USDC in base units:', usdcAmount);

Convert from human-readable value to wei/smallest unit.

Parameters:

  • value (number): Human-readable value
  • decimals (number, optional): Token decimals (default: 18 for ETH)

Returns: Value in wei/smallest unit as string


sup.blockchain.eth.isAddress()

(address: string) → boolean

if (sup.blockchain.eth.isAddress(userInput)) {
const balance = sup.blockchain.eth.balance(userInput);
// ...
} else {
return "Invalid Ethereum address";
}

Validate Ethereum address format (checks for 0x prefix and 40 hex characters).

Parameters:

  • address (string): Address to validate

Returns: true if valid Ethereum address format, false otherwise


Multi-Chain Support

sup.blockchain.eth.chain()

(chainName: string) → SupBlockchainChain

// Access Base L2
const baseBalance = sup.blockchain.eth.chain('base').balance(address);
const baseBlock = sup.blockchain.eth.chain('base').blockNumber();
// Access Optimism
const opUsdc = sup.blockchain.eth.chain('optimism').erc20('0x0b2C639c533813f4Aa9D7837CAf62653d097Ff85');
const symbol = opUsdc.symbol();
// Access Arbitrum
const arbPrice = sup.blockchain.eth.chain('arbitrum').price('ETH');
// Access Polygon
const polyBalance = sup.blockchain.eth.chain('polygon').balance(address);
// Access Zora
const zoraBlock = sup.blockchain.eth.chain('zora').blockNumber();

Access Layer 2 and other EVM-compatible chains with the same API interface.

Supported chains:

  • base - Base
  • optimism - Optimism
  • arbitrum - Arbitrum One
  • polygon - Polygon PoS
  • zora - Zora

Returns: Chain-specific blockchain operations with the same API as sup.blockchain.eth

All methods available on sup.blockchain.eth are also available on the returned chain object:

  • blockNumber()
  • balance(address, token?)
  • price(contractOrTicker)
  • contract(address, abi, functionName, args?)
  • erc20(address)
  • erc721(address)
  • erc1155(address)
  • token(address)
  • tx(hash)
  • format(value, decimals?)
  • parse(value, decimals?)
  • isAddress(address)

SupBigNumber

The SupBigNumber class is returned by price() and provides precision-safe mathematical operations for financial calculations.

Why SupBigNumber?

JavaScript’s native Number type loses precision with large numbers or many decimal places. For financial data like token prices, this can lead to incorrect calculations. SupBigNumber uses JavaScript’s native bigint for fixed-point arithmetic to maintain exact values within a specified decimal precision (default 18 decimals).

// Problem with native numbers:
const price = 0.999663;
const amount = 1000000;
console.log(price * amount); // 999663.0000000001 ❌
// Solution with SupBigNumber:
const price = sup.blockchain.eth.price('USDC');
const amount = new SupBigNumber('1000000');
console.log(price.times(amount).toString()); // Exact result ✓

Constructor

// Create from various sources
const bn1 = new SupBigNumber('123.456');
const bn2 = new SupBigNumber(123.456);
const bn3 = new SupBigNumber('1000000000000000000', 18); // With decimals
// From price API (returns SupBigNumber)
const ethPrice = sup.blockchain.eth.price('ETH');

Methods

Arithmetic Operations

const a = new SupBigNumber('10.5');
const b = new SupBigNumber('2.25');
a.plus(b); // Addition: 12.75
a.minus(b); // Subtraction: 8.25
a.times(b); // Multiplication: 23.625
a.div(b); // Division: 4.666...

Conversion & Formatting

const num = new SupBigNumber('123.456789');
num.toString(); // "123.456789"
num.toFixed(2); // "123.46"
num.toFixed(0); // "123"
num.toNumber(); // 123.456789 (JavaScript number)

Comparisons

const a = new SupBigNumber('10');
const b = new SupBigNumber('20');
a.gt(b); // false (greater than)
a.gte(b); // false (greater than or equal)
a.lt(b); // true (less than)
a.lte(b); // true (less than or equal)
a.eq(b); // false (equal)

Example: Calculate Portfolio Value

function main() {
// Get current prices
const ethPrice = sup.blockchain.eth.price('ETH');
const btcPrice = sup.blockchain.eth.price('BTC');
// Define holdings
const ethHolding = new SupBigNumber('2.5');
const btcHolding = new SupBigNumber('0.1');
// Calculate values
const ethValue = ethPrice.times(ethHolding);
const btcValue = btcPrice.times(btcHolding);
const totalValue = ethValue.plus(btcValue);
return [
`ETH: ${ethHolding.toString()} × $${ethPrice.toFixed(2)} = $${ethValue.toFixed(2)}`,
`BTC: ${btcHolding.toString()} × $${btcPrice.toFixed(2)} = $${btcValue.toFixed(2)}`,
`Total: $${totalValue.toFixed(2)}`
];
}

Complete Examples

Check Multiple Token Balances

function main() {
const address = sup.input.text;
if (!sup.blockchain.eth.isAddress(address)) {
return "Please provide a valid Ethereum address";
}
// Native ETH
const ethBalance = sup.blockchain.eth.balance(address);
const ethFormatted = sup.blockchain.eth.format(ethBalance);
// USDC
const usdcAddress = '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48';
const usdcBalance = sup.blockchain.eth.balance(address, usdcAddress);
const usdcFormatted = sup.blockchain.eth.format(usdcBalance, 6);
// USDT
const usdtAddress = '0xdAC17F958D2ee523a2206206994597C13D831ec7';
const usdtBalance = sup.blockchain.eth.balance(address, usdtAddress);
const usdtFormatted = sup.blockchain.eth.format(usdtBalance, 6);
return [
`Address: ${address}`,
`ETH: ${ethFormatted.toFixed(4)}`,
`USDC: ${usdcFormatted.toFixed(2)}`,
`USDT: ${usdtFormatted.toFixed(2)}`
];
}

Track Token Price

function main() {
const ticker = sup.input.text || 'ETH';
try {
const price = sup.blockchain.eth.price(ticker);
const priceNum = price.toNumber();
// Store historical data
const history = sup.get('priceHistory') || [];
history.push({
ticker,
price: price.toString(),
timestamp: Date.now()
});
// Keep last 10 prices
if (history.length > 10) history.shift();
sup.set('priceHistory', history);
// Calculate change if we have previous data
let change = '';
if (history.length > 1) {
const prev = new SupBigNumber(history[history.length - 2].price);
const diff = price.minus(prev);
const pct = diff.div(prev).times(100);
change = ` (${pct.toFixed(2)}%)`;
}
return `${ticker}: $${price.toFixed(priceNum < 10 ? 4 : 2)}${change}`;
} catch (error) {
return `Could not find price for ${ticker}`;
}
}

Multi-Chain Balance Checker

function main() {
const address = sup.input.text;
if (!sup.blockchain.eth.isAddress(address)) {
return "Invalid address";
}
const chains = [
{ name: 'Ethereum', chain: null },
{ name: 'Base', chain: 'base' },
{ name: 'Optimism', chain: 'optimism' },
{ name: 'Arbitrum', chain: 'arbitrum' },
{ name: 'Polygon', chain: 'polygon' }
];
const results = chains.map(({ name, chain }) => {
try {
const balance = chain
? sup.blockchain.eth.chain(chain).balance(address)
: sup.blockchain.eth.balance(address);
const formatted = sup.blockchain.eth.format(balance);
return `${name}: ${formatted.toFixed(4)} ETH`;
} catch (error) {
return `${name}: Error`;
}
});
return ['Balance across chains:', ...results];
}

NFT Ownership Checker

function main() {
const [collection, tokenId] = (sup.input.text || '').split('/');
if (!collection || !tokenId) {
return "Usage: <collection-address>/<token-id>";
}
if (!sup.blockchain.eth.isAddress(collection)) {
return "Invalid collection address";
}
try {
const nft = sup.blockchain.eth.erc721(collection);
const name = nft.name();
const symbol = nft.symbol();
const owner = nft.ownerOf(tokenId);
const uri = nft.tokenURI(tokenId);
return [
`Collection: ${name} (${symbol})`,
`Token ID: ${tokenId}`,
`Owner: ${owner}`,
`Metadata: ${uri}`
];
} catch (error) {
return `Error: ${error.message}`;
}
}

Notes

  • All operations are read-only - no transaction signing or private keys
  • Prices are fetched from DeFiLlama’s price API
  • Price data is stored with 18 decimal precision
  • Use SupBigNumber for precise financial calculations
  • format() returns JavaScript Number which may lose precision for very large values
  • Contract reads require valid ABI definitions
  • Address validation only checks format, not if the address exists on-chain