From 3f724a0e3a99983142724b14f019da790578f7c3 Mon Sep 17 00:00:00 2001 From: saurabh Date: Tue, 28 Oct 2025 21:02:40 +0530 Subject: [PATCH 1/3] added exotic markets volume tracking --- options/exotic-markets/index.ts | 115 ++++++++++++++++++++++++++++++++ 1 file changed, 115 insertions(+) create mode 100644 options/exotic-markets/index.ts diff --git a/options/exotic-markets/index.ts b/options/exotic-markets/index.ts new file mode 100644 index 0000000000..7ec9e1b40e --- /dev/null +++ b/options/exotic-markets/index.ts @@ -0,0 +1,115 @@ +import { SimpleAdapter } from "../../adapters/types"; +import { CHAIN } from "../../helpers/chains"; +import { Dependencies, FetchOptions } from "../../adapters/types"; +import { queryDuneSql } from "../../helpers/dune"; +import fetchURL from "../../utils/fetchURL"; + +const PROGRAM_ID = 'exomt54Csh4fvkUiyV5h6bjNqxDqLdpgHJmLd4eqynk'; +const VAULT_SNAPSHOT_URL = "https://raw.githubusercontent.com/DefiLlama/DefiLlama-Adapters/master/projects/exotic-markets/vaults.json"; + +let cachedVaultAccountsPromise: Promise | undefined; + +async function getVaultTokenAccounts(): Promise { + if (!cachedVaultAccountsPromise) { + cachedVaultAccountsPromise = fetchURL(VAULT_SNAPSHOT_URL) + .then((data: any) => Array.isArray(data?.tokenAccounts) ? data.tokenAccounts : []) + .catch(() => []); + } + return cachedVaultAccountsPromise; +} +const fetch = async (_a: any, _b: any, options: FetchOptions) => { + const dailyNotionalVolume = options.createBalances(); + const dailyPremiumVolume = options.createBalances(); + + const vaultTokenAccounts = await getVaultTokenAccounts(); + if (!vaultTokenAccounts.length) + return { dailyNotionalVolume, dailyPremiumVolume }; + + const vaultAddressList = vaultTokenAccounts + .map((address) => `'${address}'`) + .join(",\n "); + + const volumeQuery = ` + WITH exotic_txs AS ( + SELECT DISTINCT + tx_id + FROM solana.instruction_calls + WHERE executing_account = '${PROGRAM_ID}' + AND block_time >= from_unixtime(${options.startTimestamp}) + AND block_time <= from_unixtime(${options.endTimestamp}) + AND tx_success = true + ), + premium_transfers AS ( + SELECT + t.token_mint_address, + SUM(t.amount) AS premium_amount + FROM tokens_solana.transfers t + INNER JOIN exotic_txs e ON t.tx_id = e.tx_id + WHERE t.block_time >= from_unixtime(${options.startTimestamp}) + AND t.block_time <= from_unixtime(${options.endTimestamp}) + AND t.token_mint_address IS NOT NULL + AND t.amount > 0 + AND t.to_token_account IN ( + ${vaultAddressList} + ) + GROUP BY t.token_mint_address + ), + notional_transfers AS ( + SELECT + t.token_mint_address, + SUM(t.amount) AS notional_amount + FROM tokens_solana.transfers t + INNER JOIN exotic_txs e ON t.tx_id = e.tx_id + WHERE t.block_time >= from_unixtime(${options.startTimestamp}) + AND t.block_time <= from_unixtime(${options.endTimestamp}) + AND t.token_mint_address IS NOT NULL + AND t.amount > 0 + AND t.from_token_account IN ( + ${vaultAddressList} + ) + GROUP BY t.token_mint_address + ) + SELECT + COALESCE(p.token_mint_address, n.token_mint_address) AS token_mint_address, + COALESCE(p.premium_amount, 0) AS premium_amount, + COALESCE(n.notional_amount, 0) AS notional_amount + FROM premium_transfers p + FULL OUTER JOIN notional_transfers n ON p.token_mint_address = n.token_mint_address + `; + + const volumeResults = await queryDuneSql(options, volumeQuery); + + for (const row of volumeResults) { + const mint = row.token_mint_address; + if (!mint) continue; + + const premiumAmount = row.premium_amount ?? '0'; + const notionalAmount = row.notional_amount ?? '0'; + + if (premiumAmount !== '0') dailyPremiumVolume.add(mint, premiumAmount); + if (notionalAmount !== '0') dailyNotionalVolume.add(mint, notionalAmount); + } + + return { + dailyNotionalVolume, + dailyPremiumVolume, + }; +}; + +const adapter: SimpleAdapter = { + version: 1, + dependencies: [Dependencies.DUNE], + adapter: { + [CHAIN.SOLANA]: { + fetch, + start: '2024-01-01', + }, + }, + isExpensiveAdapter: true, + methodology: { + PremiumVolume: "Sum of token inflows into Exotic Markets vault token accounts identified in vaults.json; these represent option premiums paid by users", + NotionalVolume: "Sum of token outflows from the same vault token accounts; these represent payouts/settlements to users", + }, +}; + +export default adapter; From 8307d543b2f576de43b4aea0406b8184f1a5daf2 Mon Sep 17 00:00:00 2001 From: saurabh Date: Wed, 29 Oct 2025 16:51:46 +0530 Subject: [PATCH 2/3] changes --- options/exotic-markets/index.ts | 40 +++++++++------------------------ 1 file changed, 11 insertions(+), 29 deletions(-) diff --git a/options/exotic-markets/index.ts b/options/exotic-markets/index.ts index 7ec9e1b40e..dc5ef785e4 100644 --- a/options/exotic-markets/index.ts +++ b/options/exotic-markets/index.ts @@ -19,11 +19,10 @@ async function getVaultTokenAccounts(): Promise { } const fetch = async (_a: any, _b: any, options: FetchOptions) => { const dailyNotionalVolume = options.createBalances(); - const dailyPremiumVolume = options.createBalances(); const vaultTokenAccounts = await getVaultTokenAccounts(); if (!vaultTokenAccounts.length) - return { dailyNotionalVolume, dailyPremiumVolume }; + return { dailyNotionalVolume }; const vaultAddressList = vaultTokenAccounts .map((address) => `'${address}'`) @@ -39,10 +38,10 @@ const fetch = async (_a: any, _b: any, options: FetchOptions) => { AND block_time <= from_unixtime(${options.endTimestamp}) AND tx_success = true ), - premium_transfers AS ( + deposit_transfers AS ( SELECT t.token_mint_address, - SUM(t.amount) AS premium_amount + SUM(t.amount) AS deposit_amount FROM tokens_solana.transfers t INNER JOIN exotic_txs e ON t.tx_id = e.tx_id WHERE t.block_time >= from_unixtime(${options.startTimestamp}) @@ -52,29 +51,15 @@ const fetch = async (_a: any, _b: any, options: FetchOptions) => { AND t.to_token_account IN ( ${vaultAddressList} ) - GROUP BY t.token_mint_address - ), - notional_transfers AS ( - SELECT - t.token_mint_address, - SUM(t.amount) AS notional_amount - FROM tokens_solana.transfers t - INNER JOIN exotic_txs e ON t.tx_id = e.tx_id - WHERE t.block_time >= from_unixtime(${options.startTimestamp}) - AND t.block_time <= from_unixtime(${options.endTimestamp}) - AND t.token_mint_address IS NOT NULL - AND t.amount > 0 - AND t.from_token_account IN ( + AND t.from_token_account NOT IN ( ${vaultAddressList} ) GROUP BY t.token_mint_address ) SELECT - COALESCE(p.token_mint_address, n.token_mint_address) AS token_mint_address, - COALESCE(p.premium_amount, 0) AS premium_amount, - COALESCE(n.notional_amount, 0) AS notional_amount - FROM premium_transfers p - FULL OUTER JOIN notional_transfers n ON p.token_mint_address = n.token_mint_address + d.token_mint_address, + d.deposit_amount + FROM deposit_transfers d `; const volumeResults = await queryDuneSql(options, volumeQuery); @@ -83,16 +68,13 @@ const fetch = async (_a: any, _b: any, options: FetchOptions) => { const mint = row.token_mint_address; if (!mint) continue; - const premiumAmount = row.premium_amount ?? '0'; - const notionalAmount = row.notional_amount ?? '0'; + const depositAmount = row.deposit_amount ?? '0'; - if (premiumAmount !== '0') dailyPremiumVolume.add(mint, premiumAmount); - if (notionalAmount !== '0') dailyNotionalVolume.add(mint, notionalAmount); + if (depositAmount !== '0') dailyNotionalVolume.add(mint, depositAmount); } return { dailyNotionalVolume, - dailyPremiumVolume, }; }; @@ -107,8 +89,8 @@ const adapter: SimpleAdapter = { }, isExpensiveAdapter: true, methodology: { - PremiumVolume: "Sum of token inflows into Exotic Markets vault token accounts identified in vaults.json; these represent option premiums paid by users", - NotionalVolume: "Sum of token outflows from the same vault token accounts; these represent payouts/settlements to users", + PremiumVolume: "Not reported – Exotic Markets vaults do not charge a separate option premium", + NotionalVolume: "Sum of token deposits into Exotic Markets vault token accounts identified in vaults.json; these deposits represent the notional value of structured products initiated by users", }, }; From cd5715476f6277a8f13e84dda058c1eba23280d0 Mon Sep 17 00:00:00 2001 From: saurabh Date: Thu, 30 Oct 2025 01:01:37 +0530 Subject: [PATCH 3/3] according changes --- options/exotic-markets/index.ts | 44 +++++++++++++++++++++++++-------- 1 file changed, 34 insertions(+), 10 deletions(-) diff --git a/options/exotic-markets/index.ts b/options/exotic-markets/index.ts index dc5ef785e4..5c218ab893 100644 --- a/options/exotic-markets/index.ts +++ b/options/exotic-markets/index.ts @@ -19,10 +19,11 @@ async function getVaultTokenAccounts(): Promise { } const fetch = async (_a: any, _b: any, options: FetchOptions) => { const dailyNotionalVolume = options.createBalances(); + const dailyPremiumVolume = options.createBalances(); const vaultTokenAccounts = await getVaultTokenAccounts(); if (!vaultTokenAccounts.length) - return { dailyNotionalVolume }; + return { dailyNotionalVolume, dailyPremiumVolume }; const vaultAddressList = vaultTokenAccounts .map((address) => `'${address}'`) @@ -38,10 +39,10 @@ const fetch = async (_a: any, _b: any, options: FetchOptions) => { AND block_time <= from_unixtime(${options.endTimestamp}) AND tx_success = true ), - deposit_transfers AS ( + premium_transfers AS ( SELECT t.token_mint_address, - SUM(t.amount) AS deposit_amount + SUM(t.amount) AS premium_amount FROM tokens_solana.transfers t INNER JOIN exotic_txs e ON t.tx_id = e.tx_id WHERE t.block_time >= from_unixtime(${options.startTimestamp}) @@ -55,11 +56,31 @@ const fetch = async (_a: any, _b: any, options: FetchOptions) => { ${vaultAddressList} ) GROUP BY t.token_mint_address + ), + notional_transfers AS ( + SELECT + t.token_mint_address, + SUM(t.amount) AS notional_amount + FROM tokens_solana.transfers t + INNER JOIN exotic_txs e ON t.tx_id = e.tx_id + WHERE t.block_time >= from_unixtime(${options.startTimestamp}) + AND t.block_time <= from_unixtime(${options.endTimestamp}) + AND t.token_mint_address IS NOT NULL + AND t.amount > 0 + AND t.from_token_account IN ( + ${vaultAddressList} + ) + AND t.to_token_account NOT IN ( + ${vaultAddressList} + ) + GROUP BY t.token_mint_address ) SELECT - d.token_mint_address, - d.deposit_amount - FROM deposit_transfers d + COALESCE(p.token_mint_address, n.token_mint_address) AS token_mint_address, + COALESCE(p.premium_amount, 0) AS premium_amount, + COALESCE(n.notional_amount, 0) AS notional_amount + FROM premium_transfers p + FULL OUTER JOIN notional_transfers n ON p.token_mint_address = n.token_mint_address `; const volumeResults = await queryDuneSql(options, volumeQuery); @@ -68,13 +89,16 @@ const fetch = async (_a: any, _b: any, options: FetchOptions) => { const mint = row.token_mint_address; if (!mint) continue; - const depositAmount = row.deposit_amount ?? '0'; + const premiumAmount = row.premium_amount ?? '0'; + const notionalAmount = row.notional_amount ?? '0'; - if (depositAmount !== '0') dailyNotionalVolume.add(mint, depositAmount); + if (premiumAmount !== '0') dailyPremiumVolume.add(mint, premiumAmount); + if (notionalAmount !== '0') dailyNotionalVolume.add(mint, notionalAmount); } return { dailyNotionalVolume, + dailyPremiumVolume, }; }; @@ -89,8 +113,8 @@ const adapter: SimpleAdapter = { }, isExpensiveAdapter: true, methodology: { - PremiumVolume: "Not reported – Exotic Markets vaults do not charge a separate option premium", - NotionalVolume: "Sum of token deposits into Exotic Markets vault token accounts identified in vaults.json; these deposits represent the notional value of structured products initiated by users", + PremiumVolume: "Sum of token inflows from external accounts into the Exotic Markets vault token accounts listed in vaults.json; these correspond to option premiums paid", + NotionalVolume: "Sum of token outflows from the same vault accounts to external addresses; these represent the notional value settled or traded", }, };