Calculating balances on Algorand
Account balance on Algorand
Algorand blockchain keeps both transaction (block) history as well as the current account state for all non-zero balance addresses.
Getting the balance of tokens on an account is just a single call/lookup on the Algorand Indexer SQL schema or native node API. But what if we are interested in historical data?
How quickly can we get data that shows
- balance history for an account
- token distribution amongst holders at some round/block
- a snapshot of account balance at some point in the past
We get there by going through all transactions on the accounts up to the specified point in time and adding all token inflows and outflows.
Limited “time-travel” functionality is provided by Algorand Indexer API but does not work for accounts with any kind of smart contract activity on them.
Accounting events that affect balance
Let’s find out what inflows and outflows are possible on Algorand
Outflows:
- native payment or ASA token transfer
- transaction fee (if covered by the account)
- account close (native or ASA)
- token clawback
- token destroy (creator account only)
Inflows:
- native payment or ASA token transfer
- receiving end of account close operation (native or ASA)
- rewards (native token only)
- token clawback
- token mint
Notice that the transaction fee might be covered by another entity (eg smart contract) when the transaction is part of a group.
Rewards are no longer live on Algorand and as optimization are stored separately from TX history in Allo DW schema.
This article will focus on native tokens only. Queries that work with ASA are left as an exercise for the reader. :)
Finding an interesting account
We are interested in an account that had all types of transactions (except being closed out) over a long period of time.
This will pick the top account by the number of transactions that has at least 1M inbound and 1M outbound payment transactions spanning at least 10M rounds.
Note that Allo DW transaction type annotation differentiates between a payment transaction (‘acc_payment’) to an account that already existed and ‘acc_payment_create’ transaction that initially funded an account.
Allo DW schema stores accounts as UInt64 IDs with a separate map between IDs and full Algorand 58 character address encoding.
The one chosen is AACCDJ…LTEN4A with ID: 1740798472
Getting Algo balance history for an account
To calculate daily Algo holdings for an account we construct a union query that aggregates all daily deltas from rewards, inflows, outflows and calculate a running sum over the output.
Note that we calculate using Int128 to prevent overflow while keeping full precision in micro Algos. The result is finally shifted by 6 decimals to arrive at the Algo value.
This method ignores the initial balance of genesis accounts. One needs to add genesis data stored separately in Allo DW to get the correct results for this particular set of accounts.
Finding an interesting account … take 2
This time let’s find an account with the highest daily delta variance and over a minimum of 100-day time span.
Crunching quick daily balance deltas across 1.1 billion transactions takes less than 10 seconds with the following results:
Let’s graph the balance of V3ZJHY…3P5IIA :
Take 3
This time let’s find the most popular account where the popularity metric is going to be defined as a product of unique inflow addresses and unique outflow addresses.
The popularity contest winner is … BINANCE with account id 3907164
address SP745J…MDCZVM
The same principle can be applied to calculate ASA token or online stake distribution at specific block but we’ll explore this idea in another article.
A single pass (no unions) query is possible using ClickHouse dynamic arrays but would be harder to deconstruct in the article. Also the union version already executes in under 15 seconds over all accounts across over a billion of transactions.
All examples use commercial Allo.info Algorand Self Service BI offering.
Please contact [email protected] for a custom quote.
🔬_Note that researchers get free access to the platform._ 🔬