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