with token_pairs as (selectcoalesce(k1.symbol, 'AGI') ||'-'||coalesce(k2.symbol, 'AGI') as pair_name, p.pair, p.evt_block_time, p.token0, p.token1, p.stablefrom auragi_arbitrum.PairFactory_evt_PairCreated pleft join tokens.erc20 k1 on p.token0 = k1.contract_address and k1.blockchain ='arbitrum'left join tokens.erc20 k2 on p.token1 = k1.contract_address and k2.blockchain ='arbitrum'),token_transfer_detail as (select date_trunc('minute', evt_block_time) as block_date, evt_tx_hash as tx_hash, contract_address,"to" as user_address,cast(value as decimal(38, 0)) as amount_rawfrom erc20_arbitrum.evt_Transferwhere"to"in (select pair from token_pairs)and evt_block_time >=date('2023-04-04')union allselect date_trunc('minute', evt_block_time) as block_date, evt_tx_hash as tx_hash, contract_address,"from" as user_address,-1*cast(value as decimal(38, 0)) as amount_rawfrom erc20_arbitrum.evt_Transferwhere"from"in (select pair from token_pairs)and evt_block_time >=date('2023-04-04')),token_price as (select date_trunc('minute', minute) as block_date, contract_address, decimals, symbol,avg(price) as pricefrom prices.usdwhere blockchain ='arbitrum'and contract_address in (select distinct contract_address from token_transfer_detail)andminute>=date('2023-04-04')group by1, 2, 3, 4union all-- AGI price from swap tradeselect date_trunc('minute', block_time) as block_date, 0xFF191514A9baba76BfD19e3943a4d37E8ec9a111 as contract_address,18 as decimals,'AGI' as symbol,avg(casewhen token_in_address = 0xFF191514A9baba76BfD19e3943a4d37E8ec9a111 then token_in_price else token_out_price end) as pricefrom query_2337808group by1, 2, 3, 4)select p.symbol, d.block_date, d.tx_hash, d.user_address, d.contract_address, d.amount_raw, (d.amount_raw /power(10, p.decimals) * p.price) as amount_usdfrom token_transfer_detail dinner join token_price p on d.contract_address = p.contract_address and d.block_date = p.block_date
上面的查询逻辑如下:
先在token_pairs中得到这个项目的所有交易对(Pair)。
结合evt_Transfer表,查询出每一个交易对的资金转入转出详情。
在token_price中计算出哥哥Token的当前价格。因为这个是一个比较新的Token,Dune可能没有它的价格数据,所以我们使用了交易数据来换算价格。交易数据的详细列表在另外一个查询中,这里使用Query of Query的方式来引用。
最后,我们将时间序列和每一个小时的累积余额进行关联,补足缺失交易数据的时间段的值。请注意这里的关联条件:inner join date_series d on p.block_date <= d.block_date and d.block_date < p.next_date。这里使用了两个条件,限定累计余额的日期时间必须小于等于日期序列的日期时间值,同时序列的日期时间值必须小于下一个有记录的余额的日期时间值。这是一个很常见的处理技巧。因为并不是所有的Token在每一个时间段都有交易,如果遇到没有发生交易的时间段,我们需要用前一个时间段的余额来代表其在当前时间段的余额。这个应该不难理解,因为“当前时间段”内没有发生新的变化,所以余额自然跟上一个时间段相同。
查询代码如下:
with date_series as (select block_datefrom unnest(sequence(timestamp'2023-04-01 00:00:00', localtimestamp, interval '1'hour)) as tbl(block_date)),pool_balance_change as (select symbol, date_trunc('hour', block_date) as block_date,sum(amount_usd) as amountfrom query_2339248group by1, 2),pool_balance_summary as (select symbol, block_date,sum(amount) over (partitionby symbol order by block_date) as balance_amount,lead(block_date, 1, current_date) over (partitionby symbol order by block_date) as next_datefrom pool_balance_changeorder by1, 2)select d.block_date, p.symbol, p.balance_amountfrom pool_balance_summary pinner join date_series d on p.block_date <= d.block_date and d.block_date < p.next_dateorder by1, 2
SELECT SUM(50/POWER(2, ROUND(height/210000))) as Supply, SUM(50/POWER(2, ROUND(height/210000)) * p.price) /POWER(10, 9) AS"Market Cap"FROM bitcoin.blocksINNER JOIN ( SELECT price FROM prices.usd_latest WHERE symbol='BTC' AND contract_address IS NULL) p ON TRUE
今天学习的下一个指标是日/月活跃用户 (Daily/Monthly Active User,DAU/MAU)。相对于绝对交易数额,活跃用户的数目更能反应一个协议受欢迎程度。由于少数用户的大额交互就可以拉高交易数额,活跃的用户数可以更客观的描述该协议的热度。它的计算方式比较简单,我们只要找出与某个合约交易的钱包地址,并按天/月统计频数即可得出。 我们以最近比较热门的Lens为例:
with daily_count as (select date_trunc('day', block_time) as block_date,count(*) as transaction_count,count(distinct"from") as user_countfrompolygon.transactionswhere"to"= 0xdb46d1dc155634fbc732f92e853b10b288ad5a1d -- LensHuband block_time >=date('2022-05-16') -- contract creation dategroup by1order by1)select block_date, transaction_count, user_count,sum(transaction_count) over (order by block_date) as accumulate_transaction_count,sum(user_count) over (order by block_date) as accumulate_user_countfrom daily_countorder by block_date
with optimism_new_users as ( SELECT "from" as address,min(block_time) as start_time FROM optimism.transactions GROUP BY 1)SELECT date_trunc('day', start_time) as block_date,count(n.address) as new_users_countFROM optimism_new_users nWHERE start_time >=date('2022-10-01')GROUP BY 1