Skip to content

BigQuery dataset

This dataset is subject to change without notice.
Please provide feedback on missing features to be included in the final ETL.

Public dataset

Nodely maintains a public BigQuery dataset with Algorand mainnet contents:

  • snapshot only (daily updates once schema is finalized)
  • schema inspired by Google public blockchain datasets (ETH, …)
  • dataset is public but not free - Google charges for data read from this dataset
  • contact [email protected] for datasets and/or SelfService BI with hourly or 5m incremental loads.

Quick start

Go to Algorand dataset @ BigQuery and start playing ;D

Reading list

Schema

Base tables

CREATE TABLE `algonode.algorand_mainnet_dev.transactions`
(
block_number INT64 NOT NULL -- Block number in which this transaction is located
block_timestamp TIMESTAMP NOT NULL -- Unix timestamp when the block was assembled
block_index INT64 NOT NULL -- Transaction's index position in the block
transaction_hash STRING NOT NULL -- Hash of the transaction
transaction_group BYTES -- Parent atomic group id (binary)
transaction_type STRING NOT NULL -- One of
-- acc_payment : simple transfer of Algo to account with non-zero balance
-- acc_payment_create : transfer of Algo to zero balance (nonexisting/closed) account
-- acc_close : transfer of Algo with a secondary transfer of the remider balance
-- app_call : smart contract call
-- app_clear : call "clear-state" part of the SC, clear local SC state
-- app_close : call the SC, clear local SC state
-- app_delete : call the SC, delete the SC
-- app_optin : allocate local state, call th SC
-- app_update : call the SC, replace SC code
-- asa_transfer : simple transfer of Token/NFT
-- asa_config : token/NFT reconfiguraion (of allowed fields)
-- asa_create : token/NFT mint
-- asa_optin asa_optout : allocate/remove minimal balance on the account for the token
-- asa_clawback : force withdraw token from the account
-- asa_destroy : destroy token/NFT completly
-- asa_freeze asa_unfreeze : freeze/unfreeze token/NFT in the account
-- key_reg key_unreg : un/register participation key
-- stpf : state proof transaction
from_address_id INT64 -- Sender address id - join with v_accounts_last_state to get address / state
to_address_id INT64 -- Recipient address id - join with v_accounts_last_state to get address / state
value_float FLOAT64 NOT NULL -- Decimal adjusted amount of Algo or token (lossy floating point)
value_int NUMERIC(20) NOT NULL-- Integer amount of Algo or Token without decimal shift
-- (raw value, needs decimal shift as in v_tokens_last_state)
close_to_address_id INT64 -- Address id of recipient of the closing balance
close_value_float FLOAT64 NOT NULL -- Closing balance amount, decimal adjusted
close_value_int NUMERIC(20) NOT NULL-- Closing balance amount without decimal shift
gas INT64 NOT NULL -- Transaction free in microAlgos
note STRING -- Optional note (up to 1KB)
rekey_to_address_id INT64 -- Account rekey to address id
auth_by_address_id INT64 -- Transaction authorized by this address id (if sender is rekeyed)
has_inners BOOL NOT NULL -- Transaction has inner transactions
is_inner BOOL NOT NULL -- Transaction is an inner transaction issued by smart contract
clawback_from_address_id INT64 -- Address id of the account the token is clawed back from
token_cfg STRUCT<list ARRAY<STRUCT<element INT64>>> NOT NULL -- clawback,freeze,manager,reserve address id in random order
token_id INT64 -- Asset id (token/nft) - join with v_assets_last_state
token_total NUMERIC(20) -- Total number of assets minted
token_unit_name STRING -- Asset unit name
contract_id INT64 -- ID of the contract called
input STRING -- Extra TX data / app call input")
)
PARTITION BY TIMESTAMP_TRUNC(block_timestamp, MONTH)
CLUSTER BY block_number,block_index
OPTIONS (
description="Algorand mainnet transactions, updated every hour. See: https://nodely.io/docs/public/bigquery",
1labels=[("status", "development")]
);

Base views

-- Simple non zero Algo / NFT / Token flows
-- Each transaction creates 2 or more flows , +close_to, +clawback
-- Caveats:
-- * Clawback not rendered yet
-- * An NFT is a token with a total number or units == 1
--
create view `algorand_mainnet_dev.v_flows_simple` as
with flows as (
-- no clawback
select
block_timestamp
, from_address_id addr_id
, to_address_id other_addr_id
, 'outflow' as dir
, value_float as flow_value
, gas / pow(10,6) gas_algo
, case when t.transaction_type like 'acc%' then 'algo' when token_total = 1 then 'nft' else 'token' end xfer
, token_id
, t.is_inner
, t.transaction_type
from
`algorand_mainnet_dev.transactions` t
where
(t.transaction_type like 'acc%' or t.transaction_type like 'asa%')
UNION ALL
select
block_timestamp
, from_address_id addr_id
, close_to_address_id other_addr_id
, 'outflow' as dir
, close_value_float as flow_value
, 0 gas_algo
, case when t.transaction_type like 'acc%' then 'algo' when token_total = 1 then 'nft' else 'token' end xfer
, token_id
, t.is_inner
, t.transaction_type
from
`algorand_mainnet_dev.transactions` t
where
(t.transaction_type like 'acc%' or t.transaction_type like 'asa%')
and close_to_address_id IS NOT NULL
UNION ALL
select
block_timestamp
, to_address_id addr_id
, from_address_id other_addr_id
, 'inflow' as dir
, value_float as flow_value
, 0 gas_algo
, case when t.transaction_type like 'acc%' then 'algo' when token_total = 1 then 'nft' else 'token' end xfer
, token_id
, t.is_inner
, t.transaction_type
from
`algorand_mainnet_dev.transactions` t
where
(t.transaction_type like 'acc%' or t.transaction_type like 'asa%')
UNION ALL
select
block_timestamp
, close_to_address_id addr_id
, from_address_id other_addr_id
, 'inflow' as dir
, close_value_float as flow_value
, 0 gas_algo
, case when t.transaction_type like 'acc%' then 'algo' when token_total = 1 then 'nft' else 'token' end xfer
, token_id
, t.is_inner
, t.transaction_type
from
`algorand_mainnet_dev.transactions` t
where
(t.transaction_type like 'acc%' or t.transaction_type like 'asa%')
and close_to_address_id IS NOT NULL
) select * from flows where flow_value > 0;

Aux tables

CREATE TABLE `algonode.algorand_mainnet_dev.token_prices`
(
token_id INT64 NOT NULL -- id of the token
token_name STRING NOT NULL -- token name
token_ticker STRING NOT NULL -- token ticker
algo_value FLOAT64 NOT NULL -- token current value in Algo
market_cap FLOAT64 NOT NULL -- token current MC in Algo
first_block_number INT64 NOT NULL -- first block with price data")
)
CLUSTER BY token_id
OPTIONS(
description="Token prices, updated every hour. See: https://nodely.io/docs/public/bigquery",
labels=[("status", "development")]
);

Example queries

Accounts

Addresses created monthly

-- <1 GB processed
SELECT
TIMESTAMP_TRUNC(bs.block_timestamp, MONTH) ts
, sum(addresses_new_count) addresses_created
FROM
`algorand_mainnet_dev.blocks` bs
GROUP BY
ts
ORDER BY
ts

Daily discinct addresses stats

-- no clawback
select
TIMESTAMP_TRUNC(flows.block_timestamp, DAY) ts
,count(distinct(flows.addr_id)) uniq_addresses
,countIf(dir = 'outflow' and transaction_type = 'acc_payment_create') new_addresses
,count(distinct(case when dir = 'outflow' then flows.addr_id else NULL end)) uniq_senders
,count(distinct(case when dir = 'outflow' and xfer='algo' and flow_value > 100 then flows.addr_id else NULL end)) uniq_algo_senders_over_100A
,count(distinct(case when dir = 'inflow' then flows.addr_id else NULL end)) uniq_reveicers
,count(distinct(case when dir = 'inflow' and xfer='algo' and flow_value > 100 then flows.addr_id else NULL end)) uniq_algo_receivers_over_100A
,count(distinct(case when dir = 'inflow' then flows.addr_id || ':' || other_addr_id else NULL end)) uniq_pairs
from
`algorand_mainnet_dev.v_flows_simple` flows
where
flows.block_timestamp between '2024-04-01' and '2024-04-30'
group by ts
order by ts

Top 10

-- White Stars (spawning new accounts)
-- ~10GB
WITH whiteStars AS (
SELECT
from_address_id addr_id,
count(distinct(to_address_id)) spread
FROM `algorand_mainnet_dev.transactions`
WHERE
block_timestamp > CURRENT_TIMESTAMP() - INTERVAL 7 DAY
AND transaction_type = 'acc_payment_create'
AND value_int > 0
GROUP BY from_address_id
ORDER BY spread DESC
LIMIT 10
) SELECT
address , spread as new_accounts
FROM
whiteStars JOIN `algorand_mainnet_dev.v_accounts_last_state` acc USING (addr_id)
ORDER BY new_accounts DESC

Token value

-- Circulating (non clawback, non reserve, not burned) tokens value in USD
DECLARE algousdc FLOAT64 DEFAULT 0;
SET (algousdc) = (
SELECT AS STRUCT algo_value
FROM `algorand_mainnet_dev.token_prices`
WHERE token_id = 31566704 /* USDC */
);
SELECT
sum(th.balance_float * algo_value) / algousdc MC_USD
FROM
`algorand_mainnet_dev.v_token_holdings_last_state` th
JOIN `algorand_mainnet_dev.token_prices` tp using (token_id)
WHERE
is_circulating
and th.addr_id not in (2853884730,1970085357,2451993965,1970086565,2451993800,2451993961,3579003880) /* skip known reserve */

ToDo

  • Base tables
    • contracts
    • account_tokens
    • account_contracts
  • Aux tables
    • Account labels
    • NFD labels
  • Virtual transaction tables
    • Genesis
    • Legacy rewards
    • 2024+ block rewards
  • Transformation
    • Creator account = non circulating