📝オンチェーン分析のためのプラットフォーム. チェーンに対して📝SQLでクエリを発行できる.
Dune
- url: https://dune.com/
- Dune AnalyticsはDuneに2022/04に名称変更.
Basics
- raw table: チェーンの生データ.
- decorded table: 後処理済みのもの. Program/Funcitonごととか.
Dune API
Pricing
- free
- 2500credits
- analyst
- 月額50ドルの課金でAPIからのquery実行可能
- 4000credits
毎月2500 creditsの無料枠あり. 2500を超えたら10 creditsごとに0.3ドル=50円くらい.
- execitions: 10 credits
- datapoints: 1 credits
datapoints
rowsとcolsまたはデータ量から算出される値.
A datapoint can in most cases be thought of rows * columns with an additional limit of 100 avg bytes per cell in a set of results. This can be expressed as:
Datapoints = max(rows*columns, ceil(totalbytes/100))
https://dune.com/docs/api/faq/?h=datapoint#whats-a-datapoint
1000datapoints = 1 credits.
https://dune.com/docs/api/?h=credit#api-pricing
APIからのクエリ実行は無料でできない
defaultでperformanceがmedium=10credits消費する. 毎月2500 creditsが無料枠である.
You cannot run API executions on the free tier. Result returns an execution_id for the specified request.
クエリ実行をUIから手動実行してその結果をAPIで取得というものもある(自動化はできない).
ref. https://dune.com/docs/api/api-reference/execute-queries/execute-query-id/
Topics
export機能(csv/json)
課金しないとUIからのcsv exportはできない. APIの無料creditsの範囲でquery resultsをapiをつかってjson/csv保存. クエリ画面のエディタの右上のAPIを押すとurlがでてくる.
自動化するにはquery_idを指定してAPIでクエリを実行し, 結果をhttp getで取得する. SDKでもいけるけど簡単なのはcurlとか. importData
関数でGoogle Spreadsheetにもいける.
downloadではdatapoints でcreditsが消費する. credits=(rows * cols)/1000.
via curl
$ curl "https://api.dune.com/api/v1/query/<query_id>/results/csv?api_key=<api_key>" -o "output.csv"
API制限
- 1回のAPI callで1GBまでDownload可能.
- There is currently a 1GB limit, but there is a chance we reduce this overall or based on varying paid plan types.
- defaultで2500000 datapointsまでの制限がかっている. optionsで制限を外すことはできる.
- This api request would exceed your configured limits per request. Please visit your settings on dune.com and adjust your limits to continue usage.
Dune SQL
もともとDuneはPostgresをつかっていたが, 最適化のために独自DSLであるDune SQLを開発した.
普通のSQLでうまく動かなかったらドキュメント参照.
- DuneSQL Overview - Dune Docs
- Syntax Differences - Dune Docs
- migration: https://dune.com/docs/migrations/#migration
- released: Introducing Dune SQL
無料版と課金の比較
subscriptionsとcreditsがある. subscriptionは400ドルからなので大抵はcreditsで必要なだけ課金.
- https://dune.com/pricing
- https://dune.com/docs/learning/how-tos/credit-system-on-dune/#managing-your-credits
- ダッシュボードは無料版だと1つのみprivateであとはpublic. 課金するとprivateたくさん.
- 無料枠でのクエリは2分でタイムアウトする.
Dune with Solana
https://dune.com/docs/data-tables/raw/solana/
Solana Analytics Starter Guide (Part 1): Solana Instructions
solana.transacitons
ref. https://dune.com/docs/data-tables/raw/solana/transactions/
- id: signaturesの先頭. signatureと同じ値.
- balancesはカンマ区切りの文字列で変える
- rawデータで情報量が多いので絞り込みが必要. logとかもはいってる.
- solana.account_activityが処理された結果なのでこっちがいいかも.
solana.account_activity
ref. https://dune.com/docs/data-tables/raw/solana/account-activity/
- address: Signer
- token_balance_owner: associated account owner.
- documentだとtoken_owner_addressとなってる. 仕様変更?
- token_mint_address: mint address.
- block_timeはTIMESTAMP型, block_dateはDATE型.
- addressを指定すると一応 associated accountの取引も含めて関連するtxはすべて取得できる.
- なぜならばSPL Tokensの取引の手数料で5000 lamportsが消費されるので.
- ただし, token_balance_change, post_token_balanceは空なので損益計算では不向き.
- 損益計算用途ではなく取引履歴の保存が目的ならばtxのリストは取得できるので最悪これでもいい.
- solana.transactionsテーブルでsignerでもいい.
- ただtransactionsテーブルは情報が多すぎる上にrawデータなので, block_time, signature, signer程度のSELECTがいい.
- addressではなくtoken_balance_ownerを指定するととてもクエリが遅い.
- addressカラムにはindexやなんらかの最適化がなされている可能性がある.
- tx_idを指定してもとても遅い. tx_idの絞り込みはsolana.transactionsテーブルを使ったほうがいい.
SOL transactions
確定申告の帳簿保存用.
- SOLはlamportで数値が表示されるのでdecimals=9で割る.
- SOLの場合は tx_succss = falseでもトランザクション手数料がかかる.
SELECT
block_time AS time,
balance_change / 1e9 AS sol_change,
post_balance / 1e9 AS sol_balance,
address,
tx_id
FROM
solana.account_activity
WHERE
(
address = ''
OR address = ''
OR address = ''
)
AND block_date > DATE '2023-11-21'
ORDER BY
1
SPL transactions
確定申告の帳簿保存用.
- tx_success = TRUEを指定して成功したtxのみ絞り込み.
- wSOLのtoken_balance_changeとSOLのbalance_change/1e9が一致する.
- wSOL post_token_balanceとSOL post_balance/1e9とは一致しない.
- addressの部分をtoken_owner_addressにするとwallet addressに紐づくassociated accountのtxがすべて取得可能. ただしクエリがおそすぎて実用的でない. addressを すべて列挙するのがいい.
SELECT
block_time AS time,
token_balance_change AS token_change,
token_mint_address AS mint_address,
token_balance_owner AS owner_address,
address AS token_address,
tx_id
FROM
solana.account_activity
WHERE
(
address = ''
OR address = ''
OR address = ''
OR address = ''
)
AND tx_success = TRUE
AND block_date BETWEEN DATE '2023-11-20' AND DATE '2023-11-26'
ORDER BY
1
2024版
- 毎月のデータ量だとapi downloadできない(たぶん8MBの制限), 週次にわけてdownload.
- credit消費はcolumn数に対して計算されるので可能な限りcolumn数を削減
- blocktime
- txid
- change
- SOL/USDCでわけてダウンロードすることでカラム削減. ファイル名でsol/usdcを区別.
SOL
SELECT
block_time AS time,
-- token_balance_change AS change,
balance_change / 1e9 AS change,
tx_id
FROM
solana.account_activity
WHERE
(
-- address = 'hoge' -- SOL
-- address = 'hoge2' -- wSOL
address = 'hoge3' -- USDC
)
AND tx_success = TRUE
AND block_date BETWEEN DATE '2024-11-25' AND DATE '2024-12-01'
ORDER BY
1
USDC
SELECT
block_time AS time,
-- token_balance_change AS change,
balance_change / 1e9 AS change,
tx_id
FROM
solana.account_activity
WHERE
(
address = 'hoge' -- SOL
OR address = 'hoge2' -- wSOL
-- address = 'hoge3' -- USDC
)
AND tx_success = TRUE
AND block_date BETWEEN DATE '2024-11-25' AND DATE '2024-12-01'
ORDER BY
1
2025検討
無料枠の範囲でDuneをつかってあとはStakeTaxをつかう二刀流戦略. 月額49ドルはちょっと高いかな…
SELECT
block_time AS time,
balance_change AS sol_change,
token_balance_change AS spl_change, -- AS change,
-- token_mint_address AS mint_address,
tx_id
FROM
solana.account_activity
WHERE
tx_success = TRUE
AND address = '' -- SOL for jito tip
-- AND address = '' -- WSOL for arb
-- AND address = '' -- USDC for arb
AND block_date = DATE '2025-01-01'
-- AND block_date BETWEEN DATE '2025-01-01' AND DATE '2025-01-01'
ORDER BY
1
downloadデータ削減のためにcolumn厳選して、Python Scriptで変換によって補う方針.
- address を SOL/WSOL/USDCの3つに分けることで、token_mint_addressは不要.
- SOL aka. jito tipの場合は balance_changeに jito tip feeが入る.
- WSOL/USDC はtoken_balance_changeの arb利益が入る.
Daily PnL
block_dateが20xx-xx-xxのDATE型になっている. たぶんインデックス処理もされていてこのカラムを活用するのが高速.
post_balance, post_token_balanceは日付をまたぐ判定が煩雑だったり, 大きな資金移動できれいなbarチャートにならないので外した.
SELECT
DATE(block_time) AS date,
SUM(balance_change) / 1e9 AS sol_change
FROM solana.account_activity
WHERE
address = ''
GROUP BY
DATE(block_date)
SELECT
DATE(block_time) AS date,
SUM(token_balance_change) AS token_change
ssFROM solana.account_activity
WHERE
address = ''
AND tx_success = TRUE
GROUP BY
DATE(block_date)
Daily balance
https://dune.com/data/solana_utils.daily_balances
SELECT
*
FROM solana_utils.daily_balances
WHERE
address = TRY_CAST('wallet address' AS VARCHAR)
ORDER BY
1 DESC
Solana MEV Daily PnL for クリプタクト
for 💡クリプタクトカスタムファイル
この方式だとDEXに閉じたリバランスや資金移動は問題ないけど, CEX<->DEXのやりとりだとPnLでおかしなことになってしまう. この場合はTransfer Txを除外する必要があるものの, solana.account_activityでfilterに使えそうな情報はtx_idくらいしかないので, 送金したidを覚えておく必要がありそう. いい方法を検討中.
SOL
SELECT
CONCAT(CAST(block_date AS VARCHAR), ' 23:59:59') AS Timestamp,
CASE
WHEN SUM(balance_change) >= 0 THEN 'BONUS'
ELSE 'LOSS'
END AS Action,
'solana' AS Source,
'SOL' AS Base,
SUM(balance_change) / 1e9 AS Volume,
'' AS Price,
'JPY' AS Counter,
0 AS Fee,
'JPY' AS FeeCcy,
'Solana MEV Daily SOL PnL' AS Comment
FROM
solana.account_activity
WHERE
(
address = ''
OR address = ''
OR address = ''
)
AND block_date BETWEEN DATE '2023-11-18' AND DATE '2023-11-26'
GROUP BY
block_date
ORDER BY
1
SPL
SELECT
CONCAT(CAST(block_date AS VARCHAR), ' 23:59:59') AS Timestamp,
CASE
WHEN SUM(token_balance_change) >= 0 THEN 'BONUS'
ELSE 'LOSS'
END AS Action,
'solana' AS Source,
CASE
WHEN token_mint_address = 'So11111111111111111111111111111111111111112'
THEN 'SOL'
WHEN token_mint_address = 'EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v'
THEN 'USDC'
WHEN token_mint_address = 'Es9vMFrzaCERmJfrF4H2FYD4KCoNkY11McCe8BenwNYB'
THEN 'USDT'
ELSE token_mint_address
END AS Base,
SUM(token_balance_change) AS Volume,
'' AS Price,
'JPY' AS Counter,
0 AS Fee,
'JPY' AS FeeCcy,
'Solana MEV Daily SPL PnL' AS Comment
FROM solana.account_activity
WHERE
(
address = ''
OR address = ''
OR address = ''
OR address = ''
)
AND tx_success = TRUE
AND block_date BETWEEN TRY_CAST('2023-11-18' AS DATE) AND TRY_CAST('2023-11-26' AS DATE)
GROUP BY
block_date,
token_mint_address
ORDER BY
block_date
🔗References
- Dune Analyticsに入門してみよう | ビビドット
- [8.17] 形で覚えるDune使い方講座<初級> - by ta1suke
- 徹底入門!完全初心者でも分かるオンチェーン分析【SQLだけでWeb3分析@Dune Analytics】 - Stir Lab
- Dune Analytics: A Guide for Complete Beginners — 0xPhillan