Skip to content
Algorand Developer Portal

Asset Lookup

← Back to Indexer Client

This example demonstrates how to lookup and search for assets using the IndexerClient lookupAssetById() and searchForAssets() methods.

  • LocalNet running (via algokit localnet start)

From the repository root:

Terminal window
cd examples
npm run example indexer_client/08-asset-lookup.ts

View source on GitHub

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);
});