@@ -25,8 +25,9 @@ export const getMainnetPrice = async (ctx: Context, height: number, base: Mainne
2525 base = translateMainnetSymbol ( base )
2626 quote = translateMainnetSymbol ( quote )
2727
28- const getPrice = priceMap [ `${ base } _${ quote } ` ]
29- if ( getPrice ) {
28+ const priceEntry = priceMap [ `${ base } _${ quote } ` ]
29+ if ( priceEntry ) {
30+ const [ getPrice ] = priceEntry
3031 return getPrice ( ctx , height )
3132 }
3233 throw new Error ( `No price for ${ base } _${ quote } ` )
@@ -148,25 +149,46 @@ export const translateMainnetSymbol = (symbol: MainnetCurrency): MainnetCurrency
148149 return symbol
149150}
150151
152+ export const derived = < Base extends MainnetCurrencySymbol , Quote extends MainnetCurrencySymbol > (
153+ base : Base ,
154+ quote : Quote ,
155+ connections : { base : MainnetCurrencySymbol ; quote : MainnetCurrencySymbol } [ ] ,
156+ decimals : number = 18 ,
157+ ) => {
158+ return twoWay (
159+ base ,
160+ quote ,
161+ async ( ctx : Context , height : number ) => {
162+ const baseExponent = 10n ** BigInt ( decimals )
163+ const rates = await Promise . all ( connections . map ( ( { base, quote } ) => getMainnetPrice ( ctx , height , base , quote ) ) )
164+ return rates . reduce ( ( acc , rate ) => ( acc * rate ) / baseExponent , baseExponent )
165+ } ,
166+ decimals ,
167+ )
168+ }
151169export const invertRate = ( rate : bigint , decimals = 18 ) => ( rate > 0n ? 10n ** BigInt ( 2 * decimals ) / rate : 0n )
152- export const twoWay = < Base extends CurrencySymbol , Quote extends CurrencySymbol > (
170+ export const twoWay = < Base extends MainnetCurrencySymbol , Quote extends MainnetCurrencySymbol > (
153171 base : Base ,
154172 quote : Quote ,
155173 getPrice : ( ctx : Context , height : number ) => Promise < bigint > ,
174+ decimals : number = 18 ,
156175) =>
157176 ( {
158- [ `${ base } _${ quote } ` ] : async ( ctx : Context , height : number ) => getPrice ( ctx , height ) ,
159- [ `${ quote } _${ base } ` ] : async ( ctx : Context , height : number ) => getPrice ( ctx , height ) . then ( invertRate ) ,
160- } ) as Record < `${Base } _${Quote } ` | `${Quote } _${Base } `, ( ctx : Context , height : number ) => Promise < bigint > >
177+ [ `${ base } _${ quote } ` ] : [ async ( ctx : Context , height : number ) => getPrice ( ctx , height ) , decimals ] ,
178+ [ `${ quote } _${ base } ` ] : [
179+ async ( ctx : Context , height : number ) => getPrice ( ctx , height ) . then ( ( rate ) => invertRate ( rate , decimals ) ) ,
180+ decimals ,
181+ ] ,
182+ } ) as Record < `${Base } _${Quote } ` | `${Quote } _${Base } `, [ ( ctx : Context , height : number ) => Promise < bigint > , number ] >
161183
162184export const priceMap : Partial <
163- Record < `${CurrencySymbol } _${CurrencySymbol } `, ( ctx : Context , height : number ) => Promise < bigint > >
185+ Record < `${CurrencySymbol } _${CurrencySymbol } `, [ ( ctx : Context , height : number ) => Promise < bigint > , number ] >
164186> = {
165- ETH_WETH : async ( ) => 1_000_000_000_000_000_000n ,
166- WETH_ETH : async ( ) => 1_000_000_000_000_000_000n ,
167- ETH_ETH : async ( ) => 1_000_000_000_000_000_000n ,
168- ETH_OETH : getETHOETHPrice ,
169- OETH_ETH : getOETHETHPrice ,
187+ ETH_WETH : [ async ( ) => 1_000_000_000_000_000_000n , 18 ] ,
188+ WETH_ETH : [ async ( ) => 1_000_000_000_000_000_000n , 18 ] ,
189+ ETH_ETH : [ async ( ) => 1_000_000_000_000_000_000n , 18 ] ,
190+ ETH_OETH : [ getETHOETHPrice , 18 ] ,
191+ OETH_ETH : [ getOETHETHPrice , 18 ] ,
170192 ...twoWay ( 'ETH' , 'sfrxETH' , getStakedFraxPrice ) ,
171193 ...twoWay ( 'ETH' , 'rETH' , getRETHPrice ) ,
172194 ...twoWay ( 'ETH' , 'frxETH' , getFrxEthPrice ) ,
@@ -175,6 +197,19 @@ export const priceMap: Partial<
175197 ...twoWay ( 'OUSD' , 'ETH' , getPrice_OUSD_ETH ) ,
176198 ...twoWay ( 'ETH' , 'stETH' , ( ctx , height ) => getOethOraclePrice ( ctx , height , 'stETH' ) ) ,
177199 ...twoWay ( 'OETH' , 'USD' , getPrice_OETH_USD ) ,
178- ETH_USD : ( ctx , height ) => getChainlinkPrice ( ctx , height , 'ETH' , 'USD' ) ,
179- // ...twoWay('ETH', 'USD', (ctx, height) => getChainlinkPrice(ctx, height, 'ETH', 'USD').then((p) => p * 10n ** 10n)),
180- } as const
200+ ...twoWay ( 'ETH' , 'USD' , ( ctx , height ) => getChainlinkPrice ( ctx , height , 'ETH' , 'USD' ) , 8 ) ,
201+ ...twoWay ( 'DAI' , 'USD' , ( ctx , height ) => getChainlinkPrice ( ctx , height , 'DAI' , 'USD' ) , 8 ) ,
202+ ...twoWay ( 'USDC' , 'USD' , ( ctx , height ) => getChainlinkPrice ( ctx , height , 'USDC' , 'USD' ) , 8 ) ,
203+ ...twoWay ( 'USDT' , 'USD' , ( ctx , height ) => getChainlinkPrice ( ctx , height , 'USDT' , 'USD' ) , 8 ) ,
204+ ...derived (
205+ 'DAI' ,
206+ 'ETH' ,
207+ [
208+ { base : 'DAI' , quote : 'USD' } ,
209+ { base : 'USD' , quote : 'ETH' } ,
210+ ] ,
211+ 8 ,
212+ ) ,
213+ ...twoWay ( 'USDC' , 'ETH' , ( ctx , height ) => getChainlinkPrice ( ctx , height , 'USDC' , 'ETH' ) ) ,
214+ ...twoWay ( 'USDT' , 'ETH' , ( ctx , height ) => getChainlinkPrice ( ctx , height , 'USDT' , 'ETH' ) ) ,
215+ }
0 commit comments