|
| 1 | +import { FetchOptions, SimpleAdapter } from "../../adapters/types"; |
| 2 | +import { CHAIN } from "../../helpers/chains"; |
| 3 | +import { addOneToken } from "../../helpers/prices"; |
| 4 | +import { METRIC } from "../../helpers/metrics"; |
| 5 | + |
| 6 | +const CURVE_PMM = "0x6Ccc8223532fff07f47EF4311BEB3647326894Ab"; |
| 7 | + |
| 8 | +const swapEvent = |
| 9 | + "event SwapExecuted(address recipient, bool xToY, uint256 dx, uint256 dy, uint256 fee)"; |
| 10 | + |
| 11 | +const fetch = async (options: FetchOptions) => { |
| 12 | + const dailyVolume = options.createBalances(); |
| 13 | + const dailyFees = options.createBalances(); |
| 14 | + const dailySupplySideRevenue = options.createBalances(); |
| 15 | + const dailyProtocolRevenue = options.createBalances(); |
| 16 | + |
| 17 | + const [tokenX, tokenY, treasuryShareBps, BPS] = await Promise.all([ |
| 18 | + options.api.call({ target: CURVE_PMM, abi: "address:X" }), |
| 19 | + options.api.call({ target: CURVE_PMM, abi: "address:Y" }), |
| 20 | + options.api.call({ target: CURVE_PMM, abi: "uint24:treasuryShareBps" }), |
| 21 | + options.api.call({ target: CURVE_PMM, abi: "uint256:BPS" }), |
| 22 | + ]); |
| 23 | + |
| 24 | + const logs = await options.getLogs({ |
| 25 | + target: CURVE_PMM, |
| 26 | + eventAbi: swapEvent, |
| 27 | + }); |
| 28 | + |
| 29 | + const tBps = Number(treasuryShareBps); |
| 30 | + const totalBps = Number(BPS); |
| 31 | + |
| 32 | + for (const log of logs) { |
| 33 | + const { xToY, dx, dy, fee } = log; |
| 34 | + addOneToken({ chain: options.chain, balances: dailyVolume, token0: tokenX, token1: tokenY, amount0: dx, amount1: dy }); |
| 35 | + |
| 36 | + // Fee is taken from the output side: xToY → fee in Y, yToX → fee in X |
| 37 | + const feeToken = xToY ? tokenY : tokenX; |
| 38 | + const feeBig = BigInt(fee); |
| 39 | + dailyFees.add(feeToken, feeBig, METRIC.SWAP_FEES); |
| 40 | + |
| 41 | + // Split: treasury gets treasuryShareBps/BPS, LPs get the rest |
| 42 | + const protocolFee = totalBps > 0 ? (feeBig * BigInt(tBps)) / BigInt(totalBps) : 0n; |
| 43 | + const supplySideFee = feeBig - protocolFee; |
| 44 | + dailyProtocolRevenue.add(feeToken, protocolFee, METRIC.SWAP_FEES); |
| 45 | + dailySupplySideRevenue.add(feeToken, supplySideFee, METRIC.SWAP_FEES); |
| 46 | + } |
| 47 | + |
| 48 | + return { |
| 49 | + dailyVolume, |
| 50 | + dailyFees, |
| 51 | + dailyUserFees: dailyFees, |
| 52 | + dailySupplySideRevenue, |
| 53 | + dailyProtocolRevenue, |
| 54 | + dailyRevenue: dailyProtocolRevenue, |
| 55 | + }; |
| 56 | +}; |
| 57 | + |
| 58 | +const methodology = { |
| 59 | + Volume: "The amount of tokens that are swapped through the protocol.", |
| 60 | + Fees: "Fees that are collected for each swap transaction.", |
| 61 | + UserFees: "Fees that are paid by the users", |
| 62 | + SupplySideRevenue: "The portion of fees that goes to the liquidity providers.", |
| 63 | + Revenue: "The portion of fees that going to the protocol.", |
| 64 | + ProtocolRevenue: "All the revenue goes to the protocol.", |
| 65 | +}; |
| 66 | + |
| 67 | +const breakdownMethodology = { |
| 68 | + Fees: { |
| 69 | + [METRIC.SWAP_FEES]: "Fees that are collected for each swap transaction.", |
| 70 | + }, |
| 71 | + UserFees: { |
| 72 | + [METRIC.SWAP_FEES]: "Swap fees that are paid by the users.", |
| 73 | + }, |
| 74 | + SupplySideRevenue: { |
| 75 | + [METRIC.SWAP_FEES]: "Swap fees that goes to the liquidity providers.", |
| 76 | + }, |
| 77 | + ProtocolRevenue: { |
| 78 | + [METRIC.SWAP_FEES]: "Swap fees that goes to the protocol.", |
| 79 | + }, |
| 80 | + Revenue: { |
| 81 | + [METRIC.SWAP_FEES]: "Swap fees that going to the protocol.", |
| 82 | + }, |
| 83 | +}; |
| 84 | +const adapter: SimpleAdapter = { |
| 85 | + version: 2, |
| 86 | + pullHourly: true, |
| 87 | + fetch, |
| 88 | + chains: [CHAIN.BASE], |
| 89 | + start: "2026-03-19", |
| 90 | + methodology, |
| 91 | + breakdownMethodology, |
| 92 | +}; |
| 93 | + |
| 94 | +export default adapter; |
0 commit comments