Asset Lookup
Description
Section titled “Description”This example demonstrates how to lookup and search for assets using the IndexerClient lookupAssetById() and searchForAssets() methods.
Prerequisites
Section titled “Prerequisites”- LocalNet running (via
algokit localnet start)
Run This Example
Section titled “Run This Example”From the repository root:
cd examplesnpm run example indexer_client/08-asset-lookup.ts/** * Example: Asset Lookup * * This example demonstrates how to lookup and search for assets using * the IndexerClient lookupAssetById() and searchForAssets() methods. * * Prerequisites: * - LocalNet running (via `algokit localnet start`) */
import { createAlgorandClient, createIndexerClient, printError, printHeader, printInfo, printStep, printSuccess, shortenAddress,} from '../shared/utils.js';
async function main() { printHeader('Asset Lookup Example');
// Create clients const indexer = createIndexerClient(); const algorand = createAlgorandClient();
// ========================================================================= // Step 1: Get a funded account from LocalNet // ========================================================================= printStep(1, 'Getting a funded account from LocalNet');
let creatorAddress: string;
try { const dispenser = await algorand.account.dispenserFromEnvironment(); creatorAddress = dispenser.addr.toString(); printSuccess(`Using dispenser account: ${shortenAddress(creatorAddress)}`); } catch (error) { printError( `Failed to get dispenser account: ${error instanceof Error ? error.message : String(error)}`, ); printInfo(''); printInfo('Make sure LocalNet is running: algokit localnet start'); printInfo('If issues persist, try: algokit localnet reset'); return; }
// ========================================================================= // Step 2: Create test assets using AlgorandClient // ========================================================================= printStep(2, 'Creating test assets for demonstration');
let assetId1: bigint; let assetId2: bigint;
try { // Create first test asset with full configuration printInfo('Creating first test asset: AlphaToken (ALPHA)...'); const result1 = await algorand.send.assetCreate({ sender: creatorAddress, total: 1_000_000_000_000n, // 1,000,000 units with 6 decimals decimals: 6, assetName: 'AlphaToken', unitName: 'ALPHA', url: 'https://example.com/alpha', defaultFrozen: false, manager: creatorAddress, reserve: creatorAddress, freeze: creatorAddress, clawback: creatorAddress, }); assetId1 = result1.assetId; printSuccess(`Created AlphaToken with Asset ID: ${assetId1}`);
// Create second test asset with different unit name printInfo('Creating second test asset: BetaCoin (BETA)...'); const result2 = await algorand.send.assetCreate({ sender: creatorAddress, total: 500_000_000n, // 500,000 units with 3 decimals decimals: 3, assetName: 'BetaCoin', unitName: 'BETA', url: 'https://example.com/beta', defaultFrozen: false, }); assetId2 = result2.assetId; printSuccess(`Created BetaCoin with Asset ID: ${assetId2}`); printInfo(''); } catch (error) { printError( `Failed to create test assets: ${error instanceof Error ? error.message : String(error)}`, ); printInfo(''); printInfo('If LocalNet errors occur, try: algokit localnet reset'); return; }
// ========================================================================= // Step 3: Lookup asset by ID with lookupAssetById() // ========================================================================= printStep(3, 'Looking up asset by ID with lookupAssetById()');
try { // lookupAssetById() returns detailed asset information const assetResult = await indexer.lookupAssetById(assetId1);
printSuccess(`Found asset with ID: ${assetResult.asset.id}`); printInfo('');
// Display asset params const params = assetResult.asset.params; printInfo('Asset Parameters:'); printInfo(` - index: ${assetResult.asset.id}`); printInfo(` - creator: ${shortenAddress(params.creator)}`); printInfo(` - total: ${params.total.toLocaleString('en-US')}`); printInfo(` - decimals: ${params.decimals}`); printInfo(` - name: ${params.name ?? '(not set)'}`); printInfo(` - unitName: ${params.unitName ?? '(not set)'}`); printInfo(` - url: ${params.url ?? '(not set)'}`); printInfo( ` - metadataHash: ${params.metadataHash ? Buffer.from(params.metadataHash).toString('hex') : '(not set)'}`, ); printInfo(` - defaultFrozen: ${params.defaultFrozen ?? false}`); printInfo('');
// Display manager addresses printInfo('Manager Addresses:'); printInfo(` - manager: ${params.manager ? shortenAddress(params.manager) : '(not set)'}`); printInfo(` - reserve: ${params.reserve ? shortenAddress(params.reserve) : '(not set)'}`); printInfo(` - freeze: ${params.freeze ? shortenAddress(params.freeze) : '(not set)'}`); printInfo(` - clawback: ${params.clawback ? shortenAddress(params.clawback) : '(not set)'}`); printInfo('');
// Display creation/destruction info if (assetResult.asset.createdAtRound !== undefined) { printInfo(`Created at round: ${assetResult.asset.createdAtRound}`); } if (assetResult.asset.destroyedAtRound !== undefined) { printInfo(`Destroyed at round: ${assetResult.asset.destroyedAtRound}`); } if (assetResult.asset.deleted !== undefined) { printInfo(`Deleted: ${assetResult.asset.deleted}`); }
printInfo(`Query performed at round: ${assetResult.currentRound}`); } catch (error) { printError(`lookupAssetById failed: ${error instanceof Error ? error.message : String(error)}`); }
// ========================================================================= // Step 4: Search for assets with searchForAssets() // ========================================================================= printStep(4, 'Searching for assets with searchForAssets()');
try { // searchForAssets() returns a list of assets matching the criteria const searchResult = await indexer.searchForAssets({ limit: 10 });
printSuccess(`Found ${searchResult.assets.length} asset(s)`); printInfo('');
if (searchResult.assets.length > 0) { printInfo('Assets found:'); for (const asset of searchResult.assets.slice(0, 5)) { printInfo(` Asset ID: ${asset.id}`); printInfo(` - name: ${asset.params.name ?? '(not set)'}`); printInfo(` - unitName: ${asset.params.unitName ?? '(not set)'}`); printInfo(` - creator: ${shortenAddress(asset.params.creator)}`); printInfo(''); } if (searchResult.assets.length > 5) { printInfo(` ... and ${searchResult.assets.length - 5} more`); } }
printInfo(`Query performed at round: ${searchResult.currentRound}`); } catch (error) { printError(`searchForAssets failed: ${error instanceof Error ? error.message : String(error)}`); }
// ========================================================================= // Step 5: Filter by name // ========================================================================= printStep(5, 'Filtering assets by name');
try { // Search for assets with a specific name printInfo('Searching for assets with name "Alpha"...'); const nameResult = await indexer.searchForAssets({ name: 'Alpha' });
printSuccess(`Found ${nameResult.assets.length} asset(s) matching name "Alpha"`); if (nameResult.assets.length > 0) { for (const asset of nameResult.assets) { printInfo(` - Asset ID ${asset.id}: ${asset.params.name} (${asset.params.unitName})`); } } } catch (error) { printError(`Filter by name failed: ${error instanceof Error ? error.message : String(error)}`); }
// ========================================================================= // Step 6: Filter by unit name // ========================================================================= printStep(6, 'Filtering assets by unit name');
try { // Search for assets with a specific unit name printInfo('Searching for assets with unit "BETA"...'); const unitResult = await indexer.searchForAssets({ unit: 'BETA' });
printSuccess(`Found ${unitResult.assets.length} asset(s) matching unit "BETA"`); if (unitResult.assets.length > 0) { for (const asset of unitResult.assets) { printInfo(` - Asset ID ${asset.id}: ${asset.params.name} (${asset.params.unitName})`); } } } catch (error) { printError(`Filter by unit failed: ${error instanceof Error ? error.message : String(error)}`); }
// ========================================================================= // Step 7: Filter by creator // ========================================================================= printStep(7, 'Filtering assets by creator');
try { // Search for assets created by a specific account printInfo(`Searching for assets created by ${shortenAddress(creatorAddress)}...`); const creatorResult = await indexer.searchForAssets({ creator: creatorAddress });
printSuccess(`Found ${creatorResult.assets.length} asset(s) created by this account`); if (creatorResult.assets.length > 0) { for (const asset of creatorResult.assets) { printInfo( ` - Asset ID ${asset.id}: ${asset.params.name ?? '(unnamed)'} (${asset.params.unitName ?? 'N/A'})`, ); } } } catch (error) { printError( `Filter by creator failed: ${error instanceof Error ? error.message : String(error)}`, ); }
// ========================================================================= // Step 8: Filter by asset ID for exact match // ========================================================================= printStep(8, 'Filtering by assetId for exact match');
try { // Use assetId parameter for exact matching printInfo(`Searching for exact asset ID ${assetId2}...`); const exactResult = await indexer.searchForAssets({ assetId: assetId2 });
if (exactResult.assets.length > 0) { const asset = exactResult.assets[0]; printSuccess(`Found exact match for Asset ID ${assetId2}`); printInfo(` - name: ${asset.params.name ?? '(not set)'}`); printInfo(` - unitName: ${asset.params.unitName ?? '(not set)'}`); printInfo(` - total: ${asset.params.total.toLocaleString('en-US')}`); } else { printInfo(`No asset found with ID ${assetId2}`); } } catch (error) { printError( `Exact match search failed: ${error instanceof Error ? error.message : String(error)}`, ); }
// ========================================================================= // Step 9: Handle asset not found // ========================================================================= printStep(9, 'Handling asset not found');
try { // Try to look up a non-existent asset ID const nonExistentId = 999999999n; printInfo(`Looking up non-existent asset ID ${nonExistentId}...`);
await indexer.lookupAssetById(nonExistentId); printInfo('Asset found (unexpected)'); } catch (error) { const message = error instanceof Error ? error.message : String(error); if ( message.includes('no asset found') || message.includes('not found') || message.includes('404') ) { printSuccess('Asset not found error handled correctly'); printInfo(` Error message: ${message}`); } else { printError(`Unexpected error: ${message}`); } }
// ========================================================================= // Step 10: Include deleted assets with includeAll // ========================================================================= printStep(10, 'Including deleted/destroyed assets with includeAll');
try { // The includeAll parameter includes assets that have been deleted/destroyed printInfo('Searching with includeAll=true to include deleted assets...'); const allAssetsResult = await indexer.searchForAssets({ creator: creatorAddress, includeAll: true, });
printSuccess(`Found ${allAssetsResult.assets.length} asset(s) (including any deleted)`); for (const asset of allAssetsResult.assets) { const status = asset.deleted ? ' [DELETED]' : ''; printInfo(` - Asset ID ${asset.id}: ${asset.params.name ?? '(unnamed)'}${status}`); } } catch (error) { printError( `Include all search failed: ${error instanceof Error ? error.message : String(error)}`, ); }
// ========================================================================= // Summary // ========================================================================= printHeader('Summary'); printInfo('This example demonstrated:'); printInfo(' 1. Creating test assets using AlgorandClient.send.assetCreate()'); printInfo(' 2. lookupAssetById(assetId) - Get detailed asset information'); printInfo(' 3. searchForAssets() - Search for assets with various filters'); printInfo(' 4. Filtering by name, unit, and creator'); printInfo(' 5. Filtering by assetId for exact match'); printInfo(' 6. Handling asset not found errors'); printInfo(' 7. Including deleted assets with includeAll parameter'); printInfo(''); printInfo('Key Asset fields:'); printInfo(' - id: Unique asset identifier (bigint)'); printInfo(' - deleted: Whether asset is deleted (optional boolean)'); printInfo(' - createdAtRound: Round when created (optional bigint)'); printInfo(' - destroyedAtRound: Round when destroyed (optional bigint)'); printInfo(''); printInfo('Key AssetParams fields:'); printInfo(' - creator: Address that created the asset'); printInfo(' - total: Total supply in base units (bigint)'); printInfo(' - decimals: Number of decimal places (0-19)'); printInfo(' - name: Full asset name (optional)'); printInfo(' - unitName: Short unit name like "ALGO" (optional)'); printInfo(' - url: URL for more info (optional)'); printInfo(' - metadataHash: 32-byte metadata hash (optional)'); printInfo(''); printInfo('Manager address fields:'); printInfo(' - manager: Can reconfigure or destroy the asset'); printInfo(' - reserve: Holds non-minted units'); printInfo(' - freeze: Can freeze/unfreeze holdings'); printInfo(' - clawback: Can revoke holdings'); printInfo(''); printInfo('Search filter parameters:'); printInfo(' - name: Filter by asset name (prefix match)'); printInfo(' - unit: Filter by unit name (prefix match)'); printInfo(' - creator: Filter by creator address'); printInfo(' - assetId: Filter by exact asset ID'); printInfo(' - includeAll: Include deleted/destroyed assets'); printInfo(' - limit/next: Pagination parameters');}
main().catch(error => { console.error('Fatal error:', error); process.exit(1);});