Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 9 additions & 8 deletions benchmarks/solana-unique-traders.yml
Original file line numberDiff line numberDiff line change
Expand Up@@ -30,13 +30,14 @@ seo_intro: |

abstract: |
The harness wraps the Dune Analytics API. A single saved query counts distinct
fee_payer addresses in solana.transactions that touched each platform's known fee
wallet addresses in the rolling 24-hour window, joined from solana.account_activity
for efficiency. All platforms including pump.fun use the same fee wallet attribution
approach against solana.account_activity (standard Dune tier). The harness re-executes
the query every hour, polls for completion, then updates the Prometheus gauge
solana_platform_unique_traders_24h per platform. Between executions it serves the
latest cached result every 15 minutes.
tx_id values from solana.account_activity where the fee wallet address received
a native SOL inflow (post_balance > pre_balance) or a USDC/WSOL token inflow
(post_token_balance > pre_token_balance via token_balance_owner) in the rolling
24-hour window. All platforms use the same inflow-only attribution against
solana.account_activity (standard Dune tier, no trace API required). The harness
re-executes the query every hour, polls for completion, then updates the Prometheus
gauge solana_platform_unique_traders_24h per platform. Between executions it serves
the latest cached result every 15 minutes.

methodology:
- "Source: Dune Analytics (dune.com). Query updated hourly, results fetched every 15 min."
Expand All@@ -62,7 +63,7 @@ prometheus:

faq:
- q: "What does unique daily traders measure?"
a: "Unique daily traders counts the number of distinct wallet addresses (fee_payer in Solana transactions) that executed at least one trade through a platform in the rolling 24-hour window. It measures user breadth, not volume or frequency. A wallet that trades 1000 times counts as 1 unique trader."
a: "Unique daily traders counts the number of distinct fee-touching transactions (tx_id) in solana.account_activity where a platform fee wallet received SOL or USDC/WSOL in the rolling 24-hour window. It is a proxy for user breadth: the actual unique-wallet count is typically 3-10x lower since active traders execute multiple transactions per day. A wallet that trades 1000 times generates up to 1000 counted transactions."
- q: "Why does pump.fun have so many more unique traders than GMGN?"
a: "pump.fun is the default entry point for new Solana users and meme coin traders. Its bonding curve launch mechanic triggers massive multi-wallet bot activity as snipers race to buy newly created tokens. GMGN serves a more deliberate, power-trader segment that skews toward fewer unique wallets but larger position sizes."
- q: "Is this apple-to-apple between pump.fun and the others?"
Expand Down
44 changes: 32 additions & 12 deletions harnesses/solana-unique-traders/cmd/script/dune.go
Original file line numberDiff line numberDiff line change
Expand Up@@ -9,12 +9,12 @@ import (
"time"
)

// querySQL counts unique fee-touching transactions per Solana trading platform.
// Source: solana.account_activity filtered to known fee wallet addresses.
// Count distinct tx_ids per platform as a proxy for daily active traders.
// pump_fun_solana.trades (Dune Spellbook) is unavailable on our API tier.
// Since pump.fun cut bonding-curve trading fees to 0% on 2026-08-07,
// its count reflects only transactions generating graduation/creator fees.
// querySQL counts unique fee-generating transactions per Solana trading platform.
// Mirrors bench 203: only rows where the fee wallet actually received SOL
// (post_balance > pre_balance) or USDC/WSOL tokens (token_balance_owner match,
// post > pre). Avoids counting txs where fee wallet addresses appear as
// program IDs or read-only accounts without any balance change.
// Fomo uses R4rN... (owner wallet) for token_balance_owner matching.
const querySQL = `
WITH fee_wallets AS (
SELECT address, platform FROM (VALUES
Expand DownExpand Up@@ -56,7 +56,7 @@ WITH fee_wallets AS (
('Hbj6XdxX6eV4nfbYTseysibp4zZJtVRRPn2J3BhGRuK9','axiom'),
('846ah7iBSu9ApuCyEhA5xpnjHHX7d4QJKetWLbwzmJZ8','axiom'),
('5BqYhuD4q1YD3DMAYkc1FeTu9vqQVYYdfBAmkZjamyZg','axiom'),
('HrTf9CzXR1dRH4Sof5QrpmGWwpwAf3qZzwCsEjQpXcSq','fomo'),
('R4rNJHaffSUotNmqSKNEfDcJE8A7zJUkaoM5Jkd7cYX','fomo'),
('9yMwSPk9mrXSN7yDHUuZurAh1sjbJsfpUqjZ7SvVtdco','trojan'),
('92Med3qeK7duC5iiYsHX38H2f2twJfRsSx93oNrza2VH','trojan'),
('2jwHNxavSoMZMEDbT1eV9PcPt5dDcayCqM6MkgaPpmWQ','trojan'),
Expand All@@ -67,12 +67,32 @@ WITH fee_wallets AS (
('MaestroUL88UBnZr3wfoN7hqmNWFi3ZYCGqZoJJHE36','maestro'),
('FRMxAnZgkW58zbYcE7Bxqsg99VWpJh6sMP5xLzAWNabN','maestro')
) AS t(address, platform)
),
fee_activity AS (
SELECT fw.platform, a.tx_id
FROM solana.account_activity a
JOIN fee_wallets fw ON a.address = fw.address
WHERE a.block_time >= NOW() - INTERVAL '1' DAY
AND a.token_mint_address IS NULL
AND a.post_balance > a.pre_balance
UNION
SELECT fw.platform, a.tx_id
FROM solana.account_activity a
JOIN fee_wallets fw ON a.token_balance_owner = fw.address
WHERE a.block_time >= NOW() - INTERVAL '1' DAY
AND a.token_mint_address = 'EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v'
AND a.post_token_balance > a.pre_token_balance
UNION
SELECT fw.platform, a.tx_id
FROM solana.account_activity a
JOIN fee_wallets fw ON a.token_balance_owner = fw.address
WHERE a.block_time >= NOW() - INTERVAL '1' DAY
AND a.token_mint_address = 'So11111111111111111111111111111111111111112'
AND a.post_token_balance > a.pre_token_balance
)
SELECT fw.platform, COUNT(DISTINCT a.tx_id) AS unique_traders_24h
FROM solana.account_activity a
JOIN fee_wallets fw ON a.address = fw.address
WHERE a.block_time >= NOW() - INTERVAL '1' DAY
GROUP BY fw.platform
SELECT platform, COUNT(DISTINCT tx_id) AS unique_traders_24h
FROM fee_activity
GROUP BY platform
ORDER BY unique_traders_24h DESC
`

Expand Down
Loading