Learn how to analyze token activity and distribution on Spark. This guide covers querying transaction history and understanding token metrics.
Query Token Transactions
Retrieve detailed transaction history for your token with flexible filtering options.
queryTokenTransactions(params)
Retrieves token transactions from the network with flexible filtering options.
const transactions = await wallet . queryTokenTransactions ({
ownerPublicKeys: [ "spark1..." ],
issuerPublicKeys: [ "spark1..." ],
tokenIdentifiers: [ "btkn1..." ]
});
console . log ( "Token transactions:" , transactions );
(Optional) Array of owner public keys to filter by
(Optional) Array of issuer public keys to filter by
(Optional) Array of token transaction hashes to filter by
(Optional) Array of Bech32m token identifiers to filter by
(Optional) Array of output IDs to filter by
transactions
TokenTransactionWithStatus[]
required
Array of token transactions with status information
Transaction Status Values
Status Meaning TOKEN_TRANSACTION_STARTEDTransaction created but not yet signed TOKEN_TRANSACTION_SIGNEDTransaction signed by all required parties TOKEN_TRANSACTION_REVEALEDTransaction revealed on-chain, awaiting finalization TOKEN_TRANSACTION_FINALIZEDTransaction confirmed and finalized TOKEN_TRANSACTION_STARTED_CANCELLEDTransaction cancelled before signing TOKEN_TRANSACTION_SIGNED_CANCELLEDTransaction cancelled after signing TOKEN_TRANSACTION_UNKNOWNUnknown or unexpected state
Query Examples
All Token Transactions
// Get all transactions for your token
const tokenIdentifier = await wallet . getIssuerTokenIdentifier ();
const allTransactions = await wallet . queryTokenTransactions ({
tokenIdentifiers: [ tokenIdentifier ]
});
console . log ( `Found ${ allTransactions . length } transactions for your token` );
Transactions by Specific Owner
// Get transactions involving a specific address
const ownerAddress = "spark1..." ;
const ownerTransactions = await wallet . queryTokenTransactions ({
ownerPublicKeys: [ ownerAddress ],
tokenIdentifiers: [ tokenIdentifier ]
});
console . log ( `Found ${ ownerTransactions . length } transactions for address ${ ownerAddress } ` );
Issuer-Initiated Transactions
// Get transactions created by the issuer
const metadata = await wallet . getIssuerTokenMetadata ();
const issuerPublicKey = metadata . tokenPublicKey ;
const issuerTransactions = await wallet . queryTokenTransactions ({
issuerPublicKeys: [ issuerPublicKey ]
});
console . log ( `Found ${ issuerTransactions . length } issuer-initiated transactions` );
Filter by Transaction Status
// Get only finalized transactions
const allTransactions = await wallet . queryTokenTransactions ({
tokenIdentifiers: [ tokenIdentifier ]
});
const finalizedTransactions = allTransactions . filter (
tx => tx . status === "TOKEN_TRANSACTION_FINALIZED"
);
console . log ( `Found ${ finalizedTransactions . length } finalized transactions` );
Get Token Distribution
Get insights into how your token is distributed across the network.
getIssuerTokenDistribution()
Gets the token distribution information for the token associated with this issuer wallet.
This feature is currently under development and will be available in a future release of Spark.
const distribution = await wallet . getIssuerTokenDistribution ();
console . log ( "Token distribution:" , distribution );
distribution
TokenDistribution
required
Object containing token distribution metrics
Total circulating supply of the token
Total number of tokens ever minted
Number of unique addresses holding the token
Number of confirmed transactions involving this token
Distribution Analysis Examples
const distribution = await wallet . getIssuerTokenDistribution ();
console . log ( "=== Token Distribution Analysis ===" );
console . log ( "Circulating Supply:" , distribution . totalCirculatingSupply . toString ());
console . log ( "Total Issued:" , distribution . totalIssued . toString ());
console . log ( "Total Burned:" , distribution . totalBurned . toString ());
console . log ( "Unique Holders:" , distribution . numHoldingAddress );
console . log ( "Confirmed Transactions:" , distribution . numConfirmedTransactions );
// Calculate burn rate
const burnRate = ( Number ( distribution . totalBurned ) / Number ( distribution . totalIssued )) * 100 ;
console . log ( `Burn Rate: ${ burnRate . toFixed ( 2 ) } %` );
// Calculate average holdings per address
const avgHoldings = Number ( distribution . totalCirculatingSupply ) / distribution . numHoldingAddress ;
console . log ( `Average Holdings per Address: ${ avgHoldings . toFixed ( 2 ) } base units` );
Transaction Analysis
Analyze transaction patterns and trends for your token.
Transaction Volume Analysis
// Get all transactions for analysis
const transactions = await wallet . queryTokenTransactions ({
tokenIdentifiers: [ tokenIdentifier ]
});
// Group by status
const statusCounts = {};
transactions . forEach ( tx => {
const status = tx . status ;
statusCounts [ status ] = ( statusCounts [ status ] || 0 ) + 1 ;
});
console . log ( "Transaction status breakdown:" , statusCounts );
// Calculate success rate
const totalTransactions = transactions . length ;
const successfulTransactions = statusCounts [ "TOKEN_TRANSACTION_FINALIZED" ] || 0 ;
const successRate = ( successfulTransactions / totalTransactions ) * 100 ;
console . log ( `Success rate: ${ successRate . toFixed ( 2 ) } %` );
Recent Activity Analysis
// Analyze recent transaction activity
const recentTransactions = await wallet . queryTokenTransactions ({
tokenIdentifiers: [ tokenIdentifier ]
});
// Sort by timestamp (if available) and get recent ones
const sortedTransactions = recentTransactions . sort (( a , b ) => {
// Sort by transaction timestamp if available
return new Date ( b . tokenTransaction . timestamp ) - new Date ( a . tokenTransaction . timestamp );
});
const last24Hours = sortedTransactions . filter ( tx => {
const txTime = new Date ( tx . tokenTransaction . timestamp );
const now = new Date ();
const hoursDiff = ( now - txTime ) / ( 1000 * 60 * 60 );
return hoursDiff <= 24 ;
});
console . log ( `Transactions in last 24 hours: ${ last24Hours . length } ` );
Holder Analysis
// Analyze token holders
const transactions = await wallet . queryTokenTransactions ({
tokenIdentifiers: [ tokenIdentifier ]
});
// Extract unique addresses from transactions
const uniqueAddresses = new Set ();
transactions . forEach ( tx => {
// Add addresses from transaction inputs and outputs
tx . tokenTransaction . inputs ?. forEach ( input => {
if ( input . ownerPublicKey ) {
uniqueAddresses . add ( input . ownerPublicKey );
}
});
tx . tokenTransaction . outputs ?. forEach ( output => {
if ( output . ownerPublicKey ) {
uniqueAddresses . add ( output . ownerPublicKey );
}
});
});
console . log ( `Unique addresses involved: ${ uniqueAddresses . size } ` );
Best Practices
Query Optimization
Use Specific Filters : Apply relevant filters to reduce query response times
Paginate Results : For large datasets, implement pagination to manage memory usage
Cache Results : Store frequently accessed transaction data locally
Analysis Techniques
Batch Processing : Process large transaction sets in batches to avoid memory issues
Data Validation : Validate transaction data before analysis
Error Handling : Handle missing or malformed transaction data gracefully
Limit Query Scope : Use specific filters to limit the number of transactions returned
Async Processing : Use async/await for better performance with large datasets
Memory Management : Monitor memory usage when processing large transaction sets
Complete Example
import { IssuerSparkWallet } from "@buildonspark/issuer-sdk" ;
async function demonstrateTokenAnalytics () {
try {
// 1. Initialize issuer wallet
const { wallet } = await IssuerSparkWallet . initialize ({
options: { network: "REGTEST" }
});
console . log ( "Issuer wallet initialized for analytics" );
// 2. Get token metadata
const metadata = await wallet . getIssuerTokenMetadata ();
const tokenIdentifier = metadata . bech32mTokenIdentifier ;
console . log ( "Analyzing token:" , metadata . tokenName , "(" , metadata . tokenSymbol , ")" );
// 3. Query all transactions
const allTransactions = await wallet . queryTokenTransactions ({
tokenIdentifiers: [ tokenIdentifier ]
});
console . log ( `Found ${ allTransactions . length } total transactions` );
// 4. Analyze transaction statuses
const statusCounts = {};
allTransactions . forEach ( tx => {
const status = tx . status ;
statusCounts [ status ] = ( statusCounts [ status ] || 0 ) + 1 ;
});
console . log ( "Transaction status breakdown:" , statusCounts );
// 5. Calculate success rate
const totalTransactions = allTransactions . length ;
const successfulTransactions = statusCounts [ "TOKEN_TRANSACTION_FINALIZED" ] || 0 ;
const successRate = totalTransactions > 0 ? ( successfulTransactions / totalTransactions ) * 100 : 0 ;
console . log ( `Success rate: ${ successRate . toFixed ( 2 ) } %` );
// 6. Get issuer-specific transactions
const issuerTransactions = await wallet . queryTokenTransactions ({
issuerPublicKeys: [ metadata . tokenPublicKey ]
});
console . log ( `Issuer-initiated transactions: ${ issuerTransactions . length } ` );
// 7. Try to get distribution data (when available)
try {
const distribution = await wallet . getIssuerTokenDistribution ();
console . log ( "=== Token Distribution ===" );
console . log ( "Circulating Supply:" , distribution . totalCirculatingSupply . toString ());
console . log ( "Total Issued:" , distribution . totalIssued . toString ());
console . log ( "Total Burned:" , distribution . totalBurned . toString ());
console . log ( "Unique Holders:" , distribution . numHoldingAddress );
console . log ( "Confirmed Transactions:" , distribution . numConfirmedTransactions );
// Calculate metrics
const burnRate = Number ( distribution . totalBurned ) / Number ( distribution . totalIssued ) * 100 ;
const avgHoldings = Number ( distribution . totalCirculatingSupply ) / distribution . numHoldingAddress ;
console . log ( `Burn Rate: ${ burnRate . toFixed ( 2 ) } %` );
console . log ( `Average Holdings: ${ avgHoldings . toFixed ( 2 ) } base units` );
} catch ( error ) {
console . log ( "Token distribution not yet available:" , error . message );
}
} catch ( error ) {
console . error ( "Token analytics error:" , error );
}
}
demonstrateTokenAnalytics (). catch ( console . error );