πŸ“ŠSample Dashboard

This page will help you understand and create a dashboard using the Top Ledger platform.

Introduction

Top Ledger allows Web3 growth, analytics & data science teams to create powerful dashboards from decoded solana program data. Our backend infra pulls in raw data from the Solana blockchain and labels and indexes them into different tables on a daily basis.

Let’s take an example of a project called β€˜Project X’. Project X is a major DeFi project on Solana. We will calculate some important metrics for Project X and add them in a dashboard.

Sample SQL Query

with cte_markets as (
    select 
        pd.input_accounts.market, 
        pd.input_accounts.baseMint,
        pd.input_accounts.quoteMint, 
        ts_base.symbol as baseMintName,
        ts_quote.symbol as quoteMintName,
        ts_quote.decimals
    from phoenix.parsed pd
    join token.solana_token ts_base on ts_base.address = pd.input_accounts.baseMint
    join token.solana_token ts_quote on ts_quote.address = pd.input_accounts.quoteMint
    where 1=1
    and pd.instruction_type = 'InitializeMarket'
)
, 
market_names as (
    select 
        market,
        baseMint,
        quoteMint,
        baseMintName || ' - ' || quoteMintName as marketName,
        decimals
    from cte_markets
)

select block_date,market, marketName, trades, sum(trades) over(order by block_date) as cum_trades
from 
(
select block_date,market, marketName,  count(distinct tx_id) as trades
from phoenix.parsed as p 
cross join unnest(args.market_events) as market_event
join market_names as m on p.args.header_fields.header.market = m.market
where 1=1
and instruction_type = 'Log'
and market_event = 'FillSummary'
and p.args.header_fields.header.market = '{{market}}'
and market_event.fields.total_quote_lots_filled > 0
group by 1,2,3
) as a 
order by 1 desc

Trades

We will start with calculating number of trades on daily basis and weekly top five pools based on number of trades. The below widget shows total number of trades for project X.

Also, in the widgets shown below you can see Trade trends along with weekly top 5 pools based on the number of trades for the project. On 11th Dec there was a spike in user activity which could be related to some internal or external event.

It also shows all time top 5 pools based on number of trades.

Let's go through the SQL code for the widgets you have seen so far. The query runs on parsed table available in the TL platform.

with cte_markets as (
    select 
        pd.input_accounts.market, 
        pd.input_accounts.baseMint,
        pd.input_accounts.quoteMint, 
        ts_base.symbol as baseMintName,
        ts_quote.symbol as quoteMintName,
        ts_quote.decimals
    from phoenix.parsed pd
    join token.solana_token ts_base on ts_base.address = pd.input_accounts.baseMint
    join token.solana_token ts_quote on ts_quote.address = pd.input_accounts.quoteMint
    where 1=1
    and pd.instruction_type = 'InitializeMarket'
)
,


market_names as (
    select 
        market,
        baseMint,
        quoteMint,
        baseMintName || ' - ' || quoteMintName as marketName,
        decimals
    from cte_markets
)
, 

daily_volumes_fees as (
    select  
        p.partition_0,
        p.args.header_fields.header.market as market,
        mn.marketName,
        mn.baseMint,
        mn.quoteMint,
        count(tx_id) as trades,
        sum(market_event.fields.total_quote_lots_filled / pow(10, mn.decimals)) as daily_volume,
        sum(market_event.fields.total_fee_in_quote_lots / pow(10, mn.decimals)) as daily_fees
    from phoenix.parsed as p
    cross join unnest(p.args.market_events) as market_event
    join market_names mn on mn.market = p.args.header_fields.header.market
    where 1=1
    and instruction_type =  'Log' 
    and market_event = 'FillSummary'
    and market_event.fields.total_quote_lots_filled > 0
    group by 1, 2, 3, 4,5
), 
volume_fees_in_usd as (
    select 
        date(dv.partition_0) as block_date,
        dv.market,
        dv.marketName,
        dv.baseMint,
        dv.quoteMint,
        trades,
        dv.daily_volume,
        dv.daily_fees,
        case 
            when dv.quoteMint in ('EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v', 'Es9vMFrzaCERmJfrF4H2FYD4KCoNkY11McCe8BenwNYB') then dv.daily_volume
            else dv.daily_volume * tp.price_in_usd
        end as daily_volume_usd,
        case 
            when dv.quoteMint in ('EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v', 'Es9vMFrzaCERmJfrF4H2FYD4KCoNkY11McCe8BenwNYB') then dv.daily_fees
            else dv.daily_fees * tp.price_in_usd
        end as daily_fees_usd
    from daily_volumes_fees dv
    left join tl_solana.prices tp on dv.quoteMint = tp.mint and date(dv.partition_0) = tp.block_date
), 

weekly as 
(
select date_trunc('week', block_date) as week,
       market, marketName,
       sum(trades) as weekly_trades,
       sum(daily_volume_usd) as weekly_volume_usd,
       sum(daily_fees_usd) as weekly_fees_usd
from volume_fees_in_usd
group by 1,2,3
)
,
ranked_markets as 
(
    select *,
        rank() over (partition by week order by weekly_volume_usd desc) as rank
    from weekly
)

select * 
from ranked_markets
where rank <= 5
order by week desc, weekly_volume_usd desc

We need to begin with extracting and organizing market details, such as base and quote tokens. Subsequently, it concatenates token names for clarity. Then we calculates daily trading volumes and fees for each market, considering the associated token decimals. These daily metrics are further converted into USD values based on token prices.

The data is then aggregated on a weekly basis, summing up trades, volume, and fees. Finally, the markets are ranked weekly by trading volume in USD, and the top 5 markets are selected and displayed. This comprehensive analysis offers a snapshot of the most active markets on Solana, providing valuable insights into their weekly performance.

Trade Volume and Fees

Now let’s calculate how much trade volume Project X is making. We will check the total volume and fees for trades per day and cumulative amount of the two metrics. We can infer a lot of insights by relating this metric with real world events and can measure the impact.

Here, we see 6 widgets. 1) Total trade volume, 2) daily trade volume, 3) cumulative trade volume, 4) total trade fees, 5) daily fees for trades, and 6)cumulative fees for trades. We can infer that the volume of fees is quite high and which in a way is a sign of good health and profits for the liquidity provider and for the projectX.

with cte_markets as (
    select 
        pd.input_accounts.market, 
        pd.input_accounts.baseMint,
        pd.input_accounts.quoteMint, 
        ts_base.symbol as baseMintName,
        ts_quote.symbol as quoteMintName,
        ts_quote.decimals
    from phoenix.parsed pd
    join token.solana_token ts_base on ts_base.address = pd.input_accounts.baseMint
    join token.solana_token ts_quote on ts_quote.address = pd.input_accounts.quoteMint
    where 1=1
    and pd.instruction_type = 'InitializeMarket'
)
, 
market_names as (
    select 
        market,
        baseMint,
        quoteMint,
        baseMintName || ' - ' || quoteMintName as marketName,
        decimals
    from cte_markets
), 

volumes_fees as (
    select  
        p.partition_0,
        quoteMint,
        count(tx_id) as trades,
        sum(market_event.fields.total_quote_lots_filled / pow(10, mn.decimals)) as daily_volume,
        sum(market_event.fields.total_fee_in_quote_lots / pow(10, mn.decimals)) as daily_fees
    from phoenix.parsed p
    cross join unnest(p.args.market_events) as market_event
    join market_names mn on mn.market = p.args.header_fields.header.market
    where 1=1
    and p.instruction_type = 'Log'
    and market_event = 'FillSummary'
    group by 1,2
), 
volume_fees_in_usd as (
    select 
        dv.partition_0,
        trades,
        dv.daily_volume,
        dv.daily_fees,
        case 
            when dv.quoteMint in ('EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v', 'Es9vMFrzaCERmJfrF4H2FYD4KCoNkY11McCe8BenwNYB') then dv.daily_volume
            else dv.daily_volume * tp.price_in_usd
        end as daily_volume_usd,
        case 
            when dv.quoteMint in ('EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v', 'Es9vMFrzaCERmJfrF4H2FYD4KCoNkY11McCe8BenwNYB') then dv.daily_fees
            else dv.daily_fees * tp.price_in_usd
        end as daily_fees_usd
    from volumes_fees dv
    left join tl_solana.prices tp on dv.quoteMint = tp.mint and date(dv.partition_0) = tp.block_date
)
,
daily_volume_fee_usd as 
(
select partition_0, 
      sum(trades) as trades,
      sum(daily_volume_usd) as daily_volume_usd,
      sum(daily_fees_usd) as daily_fees_usd
from volume_fees_in_usd
group by 1 
)



    select 
        partition_0,
        trades,
        daily_volume_usd,
        daily_fees_usd,
        sum(trades) over(order by partition_0) as cumulative_trades,
        sum(daily_volume_usd) over (order by partition_0) as cumulative_volume_usd,
        sum(daily_fees_usd) over (order by partition_0) as cumulative_fees_usd
    from daily_volume_fee_usd
    order by 1 desc
    
    

Here we starts with extracting and processing data related to ProjectX markets. It involves several common table expressions (CTEs) to organize and aggregate the information. Then it calculates daily trade metrics, including the number of trades, daily volume, and daily fees in both native and USD denominations. Additionally, it computes cumulative metrics over time, providing a comprehensive view of market activity. The query draws data from various tables, such as phoenix.parsed, token.solana_token, and tl_solana.prices, utilizing their relationships to derive meaningful insights into ProjectX market performance.

Market Analysis

As many platforms wants, here we will add some key metrics regarding specific markets provided to users by the ProjectX. This includes total number of trades, trade volume, fees generated, users participated in a particular market. As shown in the widget below are the numbers for SOL-USDC market on the ProjectX.

Let’s go through the SQL code for how to calculate volume for Project X.

WITH
  buys AS (
        SELECT
        id,
        block_date,
        pre_balances,
        post_balances, 
        account_keys[1] as unique_wallet
        FROM "tl-solana-merged-data"."transactions"
            CROSS JOIN UNNEST(instructions) AS instruction
        WHERE 1=1
            AND success = True
            AND block_date >= date_trunc('day', now() - interval '30' day) 
            AND ( 
                    instruction.executing_account = 'JUP4Fb2cqiRUcaTHdrPC8h2gNsA2ETXiPDD33WcGuJB' -- program address of project X
        
                    --check in inner_instructions
                    OR  contains(transform(CAST(instruction.inner_instructions AS array<JSON>), x -> json_extract_scalar(x, '$.executing_account')), 'JUP4Fb2cqiRUcaTHdrPC8h2gNsA2ETXiPDD33WcGuJB') 
            )
        GROUP BY 1,2,3,4,5
    ),
buys_summed AS (
    SELECT
        id,
        block_date,
        SUM(IF(
            post_balances[i] - pre_balances[i] > 0,
            post_balances[i] - pre_balances[i],
            0
        )) * 1.0 / 1e9 AS sol_approx, -- 1 SOL = 10^9 lamports
        unique_wallet
    FROM buys
        CROSS JOIN UNNEST(pre_balances) WITH ORDINALITY AS b (pre_balance, i)
    GROUP BY id, block_date, unique_wallet
    ), vol_raw AS (
                    SELECT
                      date_trunc('day', block_date)  AS day,
                      SUM(sol_approx) AS sol,
                      COUNT(distinct unique_wallet) as unique_wallets
                    FROM buys_summed 
                    GROUP BY 1
        )
SELECT day
     , sol
     , unique_wallets
     , SUM(sol) over (order by day asc rows between unbounded preceding and current row) 
       AS cumulative_sol
FROM vol_raw
ORDER BY 1 DESC

Once again we will start with extracting and processing data related to ProjectX markets. It begins by identifying markets and their associated details, including base and quote tokens. Subsequently, it calculates daily trading volumes and fees for each market, converting them into USD based on token prices. The final result provides a comprehensive summary of daily and cumulative trading metrics for the specified markets, offering insights into market activity over time.

Here is the link to the detailed dashboard for your reference -

https://analytics.topledger.xyz/tl/public/dashboards/knoPmkT1W0deT8txVQYw1daqqepjITZRZbvz1oft

Last updated