11import { FetchOptions , FetchResultV2 , SimpleAdapter } from "../../adapters/types" ;
2- import { CHAIN } from "../../helpers/chains" ;
2+ import {
3+ BlockRange ,
4+ VaultMetadata ,
5+ ChainConfig ,
6+ VaultQuery ,
7+ config ,
8+ v2Deposit ,
9+ v1_1Deposit ,
10+ v1Deposit ,
11+ } from "./interfaces" ;
312
413const WAD = 10n ** 18n ;
514
6- const vaultParams = "tuple(address owner,address vaultBatchManager,address linkedToken,address investmentToken,address aggregator,bytes32 priceFeed,uint256 expiry,uint256 linkedPrice,int256 linkedOraclePrice,uint256 yieldValue,bool isBuyLow,uint256 quantity,uint256 depositDeadline,uint64 minConfidenceRatio,address collateralPool,uint256 tradingFeeRate,address feeReceiver,int256 oraclePriceAtCreation,address signer)" ;
7- const legacyVaultParams = "tuple(address owner,address vaultBatchManager,address linkedToken,address investmentToken,address aggregator,bytes32 priceFeed,uint256 expiry,uint256 linkedPrice,int256 linkedOraclePrice,uint256 yieldValue,bool isBuyLow,uint256 quantity,uint256 depositDeadline,uint64 minConfidenceRatio,address collateralPool,uint256 tradingFeeRate,address feeReceiver,int256 oraclePriceAtCreation)" ;
8-
9- const eventAbis = {
10- vaultCreated : `event VaultCreated(address indexed owner,address indexed baseToken,address indexed quoteToken,address vaultAddress,${ vaultParams } vaultParams,uint8 vaultSeriesVersion)` ,
11- legacyVaultCreatedWithParams : `event VaultCreated(address indexed owner,address indexed baseToken,address indexed quoteToken,address vaultAddress,${ legacyVaultParams } vaultParams)` ,
12- legacyVaultCreated : "event VaultCreated(address indexed owner,address indexed baseToken,address indexed quoteToken,address vaultAddress,uint256 expiry,uint256 linkedPrice,int256 linkedOraclePrice,uint256 yieldValue,bool isBuyLow,uint256 quantity,uint256 depositDeadline,uint256 tradingFeeRate,uint256 cancellationFeeRate,int256 oraclePriceAtCreation)" ,
13- deposit : "event Deposit(address indexed user,uint256 depositAmount,int256 oraclePriceAtDeposit,uint256 yieldValue)" ,
14- legacyDeposit : "event Deposit(address indexed user,uint256 depositAmount,int256 oraclePriceAtDeposit)" ,
15- } ;
16-
17- type ChainConfig = {
18- factory : string ;
19- startBlock : number ;
20- // Factory upgrade boundaries (topic0 0x1fdc1341...ceed42):
21- // [startBlock, legacyVaultCreatedWithParamsStartBlock) -> legacyVaultCreated
22- // [legacyVaultCreatedWithParamsStartBlock, currentVaultCreatedStartBlock) -> legacyVaultCreatedWithParams
23- // [currentVaultCreatedStartBlock, +inf) -> vaultCreated
24- legacyVaultCreatedWithParamsStartBlock : number ;
25- currentVaultCreatedStartBlock : number ;
26- // Deposit gained the yieldValue field at currentDepositStartBlock:
27- // [startBlock, currentDepositStartBlock) -> legacyDeposit (3-arg)
28- // [currentDepositStartBlock, +inf) -> deposit (4-arg w/ yieldValue)
29- currentDepositStartBlock : number ;
30- start : string ;
31- } ;
32-
33- const config : Record < string , ChainConfig > = {
34- [ CHAIN . ETHEREUM ] : {
35- factory : "0xAC2a612C49f29e26858Df1a53f7623180bcc3753" ,
36- startBlock : 23831175 ,
37- legacyVaultCreatedWithParamsStartBlock : 23831175 , // No flat legacy VaultCreated events on Ethereum
38- currentVaultCreatedStartBlock : 24036992 , // Upgrade to v8 which added vaultSeriesVersion field in VaultCreated event
39- currentDepositStartBlock : 23831175 , // No legacy deposits on Ethereum; the initial Deposit implementation already emitted yieldValue field
40- start : "2025-11-19"
41- } ,
42- [ CHAIN . BASE ] : {
43- factory : "0xFE198B51cfb1F96b56c63fe323a934BEAAA3b281" ,
44- startBlock : 22133150 ,
45- legacyVaultCreatedWithParamsStartBlock : 30509116 , // Upgrade to v4 with vaultParams tuple in VaultCreated event
46- currentVaultCreatedStartBlock : 39795788 , // Upgrade to v8 which added vaultSeriesVersion field in VaultCreated event
47- currentDepositStartBlock : 30509116 , // Upgrade to v4 which added yieldValue field in Deposit event
48- start : "2024-11-08"
49- } ,
50- [ CHAIN . BERACHAIN ] : {
51- factory : "0x29ca87b2f744127606ada4564da8219be6498ca1" ,
52- startBlock : 804138 ,
53- legacyVaultCreatedWithParamsStartBlock : 5297670 , // Upgrade to v4 with vaultParams tuple in VaultCreated event
54- currentVaultCreatedStartBlock : 14682550 , // Upgrade to v8 which added vaultSeriesVersion field in VaultCreated event
55- currentDepositStartBlock : 5297670 , // Upgrade to v4 which added yieldValue field in Deposit event
56- start : "2025-02-07"
57- } ,
58- } ;
59-
60- const vaultMetadataCache = new Map < string , { toBlock : number ; metadata : Map < string , VaultMetadata > } > ( ) ;
61-
62- type BlockRange = { fromBlock : number ; toBlock : number } ;
63-
64- type VaultMetadata = {
65- investmentToken : string ;
66- yieldValue : bigint ;
67- } ;
68-
6915function intersectRange (
7016 fromBlock : number ,
7117 toBlock : number ,
@@ -88,92 +34,16 @@ function addVaultMetadata(
8834 vaults : Map < string , VaultMetadata > ,
8935 vaultAddress : string ,
9036 investmentToken : string ,
37+ quantity : any ,
9138 yieldValue : any ,
9239) {
93- if ( ! vaultAddress || ! investmentToken || yieldValue === null || yieldValue === undefined ) return ;
40+ if ( ! vaultAddress || ! investmentToken || quantity === null || quantity === undefined ) return ;
9441
9542 vaults . set ( vaultAddress . toLowerCase ( ) , {
96- investmentToken,
97- yieldValue : toBigInt ( yieldValue ) ,
98- } ) ;
99- }
100-
101- async function fetch ( options : FetchOptions ) : Promise < FetchResultV2 > {
102- const chainConfig = config [ options . chain ] ;
103- const dailyNotionalVolume = options . createBalances ( ) ;
104- const dailyPremiumVolume = options . createBalances ( ) ;
105-
106- const fetchFromBlock = await options . getFromBlock ( ) ;
107- const fetchToBlock = await options . getToBlock ( ) ;
108- const legacyDepositRange = intersectRange ( fetchFromBlock , fetchToBlock , chainConfig . startBlock , chainConfig . currentDepositStartBlock - 1 ) ;
109- const currentDepositRange = intersectRange ( fetchFromBlock , fetchToBlock , chainConfig . currentDepositStartBlock , fetchToBlock ) ;
110- const vaultMetadata = await getVaultMetadataFromEvents ( options , chainConfig , fetchToBlock ) ;
111- const vaultAddresses = [ ...vaultMetadata . keys ( ) ] ;
112-
113- if ( vaultAddresses . length === 0 ) {
114- return { dailyNotionalVolume, dailyPremiumVolume } ;
115- }
116-
117- let combinedDepositLogs : any [ ] = [ ] ;
118-
119- if ( currentDepositRange ) {
120- const currentDepositLogs = await options . getLogs ( {
121- noTarget : true , // there are 40K+ vaults, so no target and filter later is more optimal
122- eventAbi : eventAbis . deposit ,
123- entireLog : true ,
124- parseLog : true ,
125- } )
126- combinedDepositLogs . push ( ...currentDepositLogs )
127- }
128- if ( legacyDepositRange ) {
129- const legacyDepositLogs = await options . getLogs ( {
130- noTarget : true , // there are 40K+ vaults, so no target and filter later is more optimal
131- eventAbi : eventAbis . legacyDeposit ,
132- entireLog : true ,
133- parseLog : true ,
134- } )
135- combinedDepositLogs . push ( ...legacyDepositLogs )
136- }
137-
138- combinedDepositLogs . forEach ( log => {
139- const metadata = vaultMetadata . get ( log . address . toLowerCase ( ) )
140- if ( ! metadata ) return ;
141- const yieldValue = log . args . yieldValue ?? metadata . yieldValue ;
142- const premiumAmount = BigInt ( log . args . depositAmount ) * yieldValue / WAD ;
143- dailyNotionalVolume . add ( metadata . investmentToken , log . args . depositAmount ) ;
144- dailyPremiumVolume . add ( metadata . investmentToken , premiumAmount ) ;
145- } )
146-
147- return {
148- dailyNotionalVolume,
149- dailyPremiumVolume,
150- } ;
151- }
152-
153- async function getVaultMetadataFromEvents (
154- options : FetchOptions ,
155- chainConfig : ChainConfig ,
156- toBlock : number ,
157- ) : Promise < Map < string , VaultMetadata > > {
158- const cached = vaultMetadataCache . get ( options . chain ) ;
159- if ( cached && cached . toBlock >= toBlock ) return cached . metadata ;
160-
161- const fromBlock = cached ? cached . toBlock + 1 : chainConfig . startBlock ;
162- const metadata = cached ? new Map ( cached . metadata ) : new Map < string , VaultMetadata > ( ) ;
163- if ( fromBlock > toBlock ) return metadata ;
164-
165- const freshMetadata = await fetchVaultMetadataRange ( options , chainConfig , fromBlock , toBlock ) ;
166- freshMetadata . forEach ( ( value , vault ) => {
167- metadata . set ( vault , value ) ;
43+ token : investmentToken . toLowerCase ( ) ,
44+ quantity : toBigInt ( quantity ) ,
45+ yieldValue : toBigInt ( yieldValue ?? 0 ) ,
16846 } ) ;
169-
170- const latestCached = vaultMetadataCache . get ( options . chain ) ;
171- if ( ! latestCached || latestCached . toBlock < toBlock ) {
172- vaultMetadataCache . set ( options . chain , { toBlock, metadata } ) ;
173- return metadata ;
174- }
175-
176- return latestCached . metadata ;
17747}
17848
17949async function fetchVaultMetadataRange (
@@ -184,65 +54,60 @@ async function fetchVaultMetadataRange(
18454) : Promise < Map < string , VaultMetadata > > {
18555 const vaults = new Map < string , VaultMetadata > ( ) ;
18656
187- const legacyRange = intersectRange (
57+ const v2Range = intersectRange (
18858 fromBlock ,
18959 toBlock ,
190- chainConfig . startBlock ,
191- chainConfig . legacyVaultCreatedWithParamsStartBlock - 1 ,
60+ chainConfig . v2StartBlock ,
61+ toBlock ,
19262 ) ;
193- const legacyWithParamsRange = intersectRange (
63+ const v1_1Range = intersectRange (
19464 fromBlock ,
19565 toBlock ,
196- chainConfig . legacyVaultCreatedWithParamsStartBlock ,
197- chainConfig . currentVaultCreatedStartBlock - 1 ,
66+ chainConfig . v1_1StartBlock ,
67+ chainConfig . v2StartBlock - 1 ,
19868 ) ;
199- const currentRange = intersectRange (
69+ const v1Range = intersectRange (
20070 fromBlock ,
20171 toBlock ,
202- chainConfig . currentVaultCreatedStartBlock ,
203- toBlock ,
72+ chainConfig . v1StartBlock ,
73+ chainConfig . v1_1StartBlock - 1 ,
20474 ) ;
20575
206- type VaultQuery =
207- | { kind : "current" ; logs : Promise < any [ ] > }
208- | { kind : "legacyWithParams" ; logs : Promise < any [ ] > }
209- | { kind : "legacy" ; logs : Promise < any [ ] > } ;
210-
21176 const queries : VaultQuery [ ] = [ ] ;
21277
213- if ( currentRange ) {
78+ if ( v2Range ) {
21479 queries . push ( {
215- kind : "current " ,
80+ kind : "v2 " ,
21681 logs : options . getLogs ( {
21782 target : chainConfig . factory ,
218- eventAbi : eventAbis . vaultCreated ,
219- fromBlock : currentRange . fromBlock ,
83+ eventAbi : v2Deposit ,
84+ fromBlock : v2Range . fromBlock ,
22085 cacheInCloud : true ,
22186 } ) ,
22287 } ) ;
22388 }
22489
225- if ( legacyWithParamsRange ) {
90+ if ( v1_1Range ) {
22691 queries . push ( {
227- kind : "legacyWithParams " ,
92+ kind : "v1_1 " ,
22893 logs : options . getLogs ( {
22994 target : chainConfig . factory ,
230- eventAbi : eventAbis . legacyVaultCreatedWithParams ,
231- fromBlock : legacyWithParamsRange . fromBlock ,
232- toBlock : legacyWithParamsRange . toBlock ,
95+ eventAbi : v1_1Deposit ,
96+ fromBlock : v1_1Range . fromBlock ,
97+ toBlock : v1_1Range . toBlock ,
23398 cacheInCloud : true ,
23499 } ) ,
235100 } ) ;
236101 }
237102
238- if ( legacyRange ) {
103+ if ( v1Range ) {
239104 queries . push ( {
240- kind : "legacy " ,
105+ kind : "v1 " ,
241106 logs : options . getLogs ( {
242107 target : chainConfig . factory ,
243- eventAbi : eventAbis . legacyVaultCreated ,
244- fromBlock : legacyRange . fromBlock ,
245- toBlock : legacyRange . toBlock ,
108+ eventAbi : v1Deposit ,
109+ fromBlock : v1Range . fromBlock ,
110+ toBlock : v1Range . toBlock ,
246111 cacheInCloud : true ,
247112 } ) ,
248113 } ) ;
@@ -252,29 +117,49 @@ async function fetchVaultMetadataRange(
252117
253118 resolved . forEach ( ( logs , idx ) => {
254119 const kind = queries [ idx ] . kind ;
255- if ( kind === "current " || kind === "legacyWithParams " ) {
120+ if ( kind === "v2 " || kind === "v1_1 " ) {
256121 logs . forEach ( ( log : any ) => {
257- addVaultMetadata ( vaults , log . vaultAddress , log . vaultParams . investmentToken , log . vaultParams . yieldValue ) ;
122+ addVaultMetadata ( vaults , log . vaultAddress , log . vaultParams . investmentToken , log . vaultParams . quantity , log . vaultParams . yieldValue ) ;
258123 } ) ;
259124 } else {
260125 logs . forEach ( ( log : any ) => {
261126 const investmentToken = log . isBuyLow ? log . quoteToken : log . baseToken ;
262- addVaultMetadata ( vaults , log . vaultAddress , investmentToken , log . yieldValue ) ;
127+ addVaultMetadata ( vaults , log . vaultAddress , investmentToken , log . quantity , log . yieldValue ) ;
263128 } ) ;
264129 }
265130 } ) ;
266131
267132 return vaults ;
268133}
269134
135+ async function fetch ( options : FetchOptions ) : Promise < FetchResultV2 > {
136+ const chainConfig = config [ options . chain ] ;
137+ const dailyNotionalVolume = options . createBalances ( ) ;
138+ const dailyPremiumVolume = options . createBalances ( ) ;
139+
140+ const fetchFromBlock = await options . getFromBlock ( ) ;
141+ const fetchToBlock = await options . getToBlock ( ) ;
142+
143+ const dayVaults = await fetchVaultMetadataRange ( options , chainConfig , fetchFromBlock , fetchToBlock ) ;
144+ dayVaults . forEach ( ( metadata ) => {
145+ dailyNotionalVolume . add ( metadata . token , metadata . quantity ) ;
146+ dailyPremiumVolume . add ( metadata . token , ( metadata . quantity * metadata . yieldValue ) / WAD ) ;
147+ } ) ;
148+
149+ return {
150+ dailyNotionalVolume,
151+ dailyPremiumVolume,
152+ } ;
153+ }
154+
270155const adapter : SimpleAdapter = {
271156 version : 2 ,
272157 pullHourly : true ,
273158 fetch,
274159 adapter : config ,
275160 methodology : {
276- NotionalVolume : "Notional volume is the principal deposited into Prodigy.Fi DCI vaults, counted in each vault's investment token when the on-chain Deposit event is emitted ." ,
277- PremiumVolume : "Premium volume is computed from each on-chain Deposit event as deposited principal multiplied by the vault yieldValue, denominated in the same investment token ." ,
161+ NotionalVolume : "The total value of the underlying asset in an option or derivative contract ." ,
162+ PremiumVolume : "The price paid up front to buy or sell option or derivative contract ." ,
278163 } ,
279164} ;
280165
0 commit comments