Skip to Content

Scan a Wallet

Fetch all burnable assets in a wallet and display them grouped by type.

Backend: create a session

import { BurnerClient, SessionScope } from '@burnandclaim/sdk' const server = new BurnerClient({ apiKey: process.env.BURNER_API_KEY, }) export async function createReadSession(walletAddress: string) { return server.createSession({ walletAddress, scopes: [SessionScope.WalletRead], ttlSeconds: 300, }) }

Frontend: fetch and display assets

import { BurnerClient } from '@burnandclaim/sdk' import type { WalletAssets, WalletItem, WalletItemType } from '@burnandclaim/sdk' async function scanWallet( sessionToken: string, walletAddress: string ) { const client = new BurnerClient({ sessionToken }) const assets = await client.getWalletAssets(walletAddress) displayAssets(assets) } function displayAssets(assets: WalletAssets) { console.log(`Wallet: ${assets.walletAddress}`) console.log(`Total items: ${assets.items.length}`) console.log() // Group by type const grouped = groupByType(assets.items) for (const [type, items] of Object.entries(grouped)) { console.log(`--- ${formatType(type as WalletItemType)} (${items.length}) ---`) for (const item of items) { const label = item.name ?? item.symbol ?? item.address.slice(0, 12) + '...' const actions = item.actions.join(', ') if (item.type === 'empty_account') { const rentSol = (item.lamports ?? 0) / 1e9 console.log(` ${label} - reclaimable: ${rentSol.toFixed(6)} SOL [${actions}]`) } else if (item.uiBalance !== undefined) { console.log(` ${label} - balance: ${item.uiBalance} [${actions}]`) } else { console.log(` ${label} [${actions}]`) } } console.log() } // Summary console.log('Counts by type:') for (const [type, count] of Object.entries(assets.counts)) { if (count > 0) { console.log(` ${formatType(type as WalletItemType)}: ${count}`) } } } function groupByType( items: WalletItem[] ): Record<string, WalletItem[]> { const groups: Record<string, WalletItem[]> = {} for (const item of items) { const list = groups[item.type] ?? [] list.push(item) groups[item.type] = list } return groups } function formatType(type: WalletItemType): string { const labels: Record<WalletItemType, string> = { empty_account: 'Empty Accounts', token: 'Tokens', nft: 'NFTs', fungible_asset: 'Fungible Assets', zk_compressed_token: 'ZK Compressed Tokens', cnft: 'Compressed NFTs', } return labels[type] ?? type }

Streaming variant for large wallets

If the wallet has hundreds of accounts, use streaming to render items as they arrive:

import { BurnerClient, SessionScope } from '@burnandclaim/sdk' import type { WalletItem } from '@burnandclaim/sdk' async function scanWalletStreaming( sessionToken: string, walletAddress: string ) { const client = new BurnerClient({ sessionToken }) const allItems: WalletItem[] = [] for await (const chunk of client.streamWalletAssets(walletAddress)) { allItems.push(...chunk.items) // Update a progress indicator const total = Object.values(chunk.counts).reduce((a, b) => a + b, 0) console.log(`Chunk ${chunk.chunkIndex}: ${allItems.length}/${total} items...`) // Render items incrementally renderItemList(allItems) } console.log(`Scan complete: ${allItems.length} items`) }

Note: streaming requires the wallet:stream scope on the session token.

Last updated on