Skip to content

Application Information

← Back to Algod Client

This example demonstrates how to retrieve application information using the AlgodClient method: applicationById()

  • LocalNet running (via algokit localnet start)

From the repository root:

Terminal window
cd examples
npm run example algod_client/10-application-info.ts

View source on GitHub

10-application-info.ts
/**
* Example: Application Information
*
* This example demonstrates how to retrieve application information using
* the AlgodClient method: applicationById()
*
* Prerequisites:
* - LocalNet running (via `algokit localnet start`)
*/
import {
createAlgodClient,
createAlgorandClient,
getFundedAccount,
loadTealSource,
printError,
printHeader,
printInfo,
printStep,
printSuccess,
shortenAddress,
} from '../shared/utils.js';
/** Decode a TEAL value for display */
function decodeTealValue(value: { type: number; bytes: Uint8Array; uint: bigint }): string {
if (value.type === 2) {
// uint
return `${value.uint} (uint)`
} else if (value.type === 1) {
// bytes
// Try to decode as UTF-8 string, fall back to hex
try {
const str = new TextDecoder().decode(value.bytes)
// Check if it's a printable string
if (/^[\x20-\x7E]*$/.test(str) && str.length > 0) {
return `"${str}" (bytes)`
}
} catch {
// Ignore decode errors
}
return `0x${Buffer.from(value.bytes).toString('hex')} (bytes)`
}
return '(unknown type)'
}
async function main() {
printHeader('Application Information Example')
// Create an Algod client connected to LocalNet
const algod = createAlgodClient()
// Create an AlgorandClient for application deployment
const algorand = createAlgorandClient()
// =========================================================================
// Step 1: Get a Funded Account from LocalNet
// =========================================================================
printStep(1, 'Getting a funded account from LocalNet')
let creator: Awaited<ReturnType<typeof getFundedAccount>>
try {
creator = await getFundedAccount(algorand)
printSuccess(`Got funded account: ${shortenAddress(creator.addr.toString())}`)
} catch (error) {
printError(`Failed to get funded account: ${error instanceof Error ? error.message : String(error)}`)
printInfo('Make sure LocalNet is running with `algokit localnet start`')
printInfo('If issues persist, try `algokit localnet reset`')
process.exit(1)
}
// =========================================================================
// Step 2: Deploy a Test Application using AlgorandClient
// =========================================================================
printStep(2, 'Deploying a test application')
// Load approval program from shared artifacts
// - Accepts all ApplicationCall transactions
// - Stores a counter in global state on each call
// - Has one global uint and one global bytes slot
const approvalSource = loadTealSource('approval-counter-message.teal')
// Load clear state program from shared artifacts
const clearSource = loadTealSource('clear-state-approve.teal')
try {
printInfo('Compiling TEAL programs...')
const approvalCompiled = await algod.tealCompile(approvalSource)
const clearCompiled = await algod.tealCompile(clearSource)
printSuccess(`Approval program hash: ${approvalCompiled.hash}`)
printSuccess(`Clear program hash: ${clearCompiled.hash}`)
printInfo('Deploying application...')
const result = await algorand.send.appCreate({
sender: creator.addr,
approvalProgram: Buffer.from(approvalCompiled.result, 'base64'),
clearStateProgram: Buffer.from(clearCompiled.result, 'base64'),
schema: {
globalInts: 1,
globalByteSlices: 1,
localInts: 0,
localByteSlices: 0,
},
})
const appId = result.appId
printSuccess(`Application deployed with ID: ${appId}`)
printInfo('')
// =========================================================================
// Step 3: Get Application Information using applicationById()
// =========================================================================
printStep(3, 'Getting application information with applicationById()')
const app = await algod.applicationById(appId)
printSuccess('Application information retrieved successfully!')
printInfo('')
// =========================================================================
// Step 4: Display Application Params
// =========================================================================
printStep(4, 'Displaying application parameters')
printInfo('Application Identification:')
printInfo(` Application ID: ${app.id}`)
printInfo('')
printInfo('Application Parameters:')
printInfo(` Creator: ${app.params.creator}`)
printInfo(` ${shortenAddress(app.params.creator.toString())} (shortened)`)
printInfo('')
// Display approval program info
printInfo('Approval Program:')
printInfo(` Size: ${app.params.approvalProgram.length} bytes`)
const approvalPreview = Buffer.from(app.params.approvalProgram.slice(0, 20)).toString('hex')
printInfo(` Preview: ${approvalPreview}... (first 20 bytes, hex)`)
printInfo('The approval program runs when the app is called')
printInfo('')
// Display clear state program info
printInfo('Clear State Program:')
printInfo(` Size: ${app.params.clearStateProgram.length} bytes`)
const clearPreview = Buffer.from(app.params.clearStateProgram.slice(0, 20)).toString('hex')
printInfo(` Preview: ${clearPreview}... (first 20 bytes, hex)`)
printInfo('The clear state program runs when an account clears its local state')
printInfo('')
// Display extra program pages if any
if (app.params.extraProgramPages !== undefined && app.params.extraProgramPages > 0) {
printInfo(` Extra Pages: ${app.params.extraProgramPages}`)
printInfo('Extra program pages allow for larger smart contracts')
}
// Display version if available
if (app.params.version !== undefined) {
printInfo(` Version: ${app.params.version}`)
printInfo('Version tracks number of program updates')
}
printInfo('')
// =========================================================================
// Step 5: Display State Schema
// =========================================================================
printStep(5, 'Displaying state schema')
printInfo('Global State Schema:')
if (app.params.globalStateSchema) {
printInfo(` Uint Slots: ${app.params.globalStateSchema.numUints}`)
printInfo(` Byte Slice Slots: ${app.params.globalStateSchema.numByteSlices}`)
printInfo('Global state is shared across all accounts')
} else {
printInfo(` (no global state schema)`)
}
printInfo('')
printInfo('Local State Schema:')
if (app.params.localStateSchema) {
printInfo(` Uint Slots: ${app.params.localStateSchema.numUints}`)
printInfo(` Byte Slice Slots: ${app.params.localStateSchema.numByteSlices}`)
printInfo('Local state is per-account and requires opt-in')
} else {
printInfo(` (no local state schema)`)
}
printInfo('')
// =========================================================================
// Step 6: Display Global State
// =========================================================================
printStep(6, 'Displaying global state')
if (app.params.globalState && app.params.globalState.length > 0) {
printInfo('Global State Values:')
for (const kv of app.params.globalState) {
// Decode the key (it's a Uint8Array)
const keyStr = new TextDecoder().decode(kv.key)
const valueStr = decodeTealValue(kv.value)
printInfo(` "${keyStr}": ${valueStr}`)
}
printInfo('')
printInfo('Global state is stored on-chain and costs MBR')
} else {
printInfo(' (no global state values)')
printInfo('This application has no global state set')
}
printInfo('')
// =========================================================================
// Step 7: Call the Application to Update Global State
// =========================================================================
printStep(7, 'Calling application to update global state')
printInfo('Calling the application to increment the counter...')
await algorand.send.appCall({
sender: creator.addr,
appId: appId,
})
// Fetch updated application info
const updatedApp = await algod.applicationById(appId)
printInfo('Updated Global State:')
if (updatedApp.params.globalState && updatedApp.params.globalState.length > 0) {
for (const kv of updatedApp.params.globalState) {
const keyStr = new TextDecoder().decode(kv.key)
const valueStr = decodeTealValue(kv.value)
printInfo(` "${keyStr}": ${valueStr}`)
}
}
printSuccess('Counter was incremented from 0 to 1')
printInfo('')
// =========================================================================
// Step 8: Handle Application Not Found
// =========================================================================
printStep(8, 'Demonstrating error handling for non-existent application')
const nonExistentAppId = BigInt(999999999)
try {
printInfo(`Querying non-existent application ID: ${nonExistentAppId}`)
await algod.applicationById(nonExistentAppId)
printError('Expected an error but none was thrown')
} catch (error) {
printSuccess('Correctly caught error for non-existent application')
if (error instanceof Error) {
printInfo(` Error message: ${error.message}`)
}
printInfo('Always handle the case where an application may not exist or has been deleted')
}
printInfo('')
// =========================================================================
// Step 9: Note about Round Information
// =========================================================================
printStep(9, 'Note about data validity')
printInfo('The applicationById() method returns the current application state.')
printInfo('Unlike some other endpoints, it does not include a round field.')
printInfo('To get the current round, use status() or other round-aware methods.')
// Get current round for reference
const status = await algod.status()
printInfo(` Current network round: ${status.lastRound.toLocaleString('en-US')}`)
printInfo('')
} catch (error) {
printError(`Failed to deploy or query application: ${error instanceof Error ? error.message : String(error)}`)
printInfo('If LocalNet errors occur, try `algokit localnet reset`')
process.exit(1)
}
// =========================================================================
// Summary
// =========================================================================
printHeader('Summary')
printInfo('This example demonstrated:')
printInfo(' 1. Deploying a test application using AlgorandClient.send.appCreate()')
printInfo(' 2. applicationById(appId) - Get complete application information')
printInfo(' 3. Application params: creator, approvalProgram, clearStateProgram')
printInfo(' 4. State schema: globalStateSchema, localStateSchema')
printInfo(' 5. Displaying global state values with TEAL key-value decoding')
printInfo(' 6. Calling the application and observing state changes')
printInfo(' 7. Error handling for non-existent applications')
printInfo('')
printInfo('Key Application fields:')
printInfo(' - id: Unique application identifier (bigint)')
printInfo(' - params.creator: Address that deployed the application')
printInfo(' - params.approvalProgram: Bytecode for app calls (Uint8Array)')
printInfo(' - params.clearStateProgram: Bytecode for clear state (Uint8Array)')
printInfo(' - params.globalStateSchema: { numUints, numByteSlices }')
printInfo(' - params.localStateSchema: { numUints, numByteSlices }')
printInfo(' - params.globalState: TealKeyValue[] (current global state)')
printInfo(' - params.extraProgramPages: Additional program space (optional)')
printInfo(' - params.version: Number of updates to the program (optional)')
printInfo('')
printInfo('Global State (TealKeyValue) structure:')
printInfo(' - key: Uint8Array (state key, often UTF-8 string)')
printInfo(' - value.type: 1 = bytes, 2 = uint')
printInfo(' - value.bytes: Uint8Array (for bytes type)')
printInfo(' - value.uint: bigint (for uint type)')
printInfo('')
printInfo('Use cases:')
printInfo(' - Verify application creator and code before interaction')
printInfo(' - Read current global state values')
printInfo(' - Check state schema to understand storage limits')
printInfo(' - Display application information in explorers/wallets')
}
main().catch((error) => {
console.error('Fatal error:', error)
process.exit(1)
})