1- import { ResponseCache } from '@chainlink/external-adapter-framework/cache/response'
21import { TransportDependencies } from '@chainlink/external-adapter-framework/transports'
2+ import { ResponseCache } from '@chainlink/external-adapter-framework/cache/response'
33import { Requester } from '@chainlink/external-adapter-framework/util/requester'
44
5+ import { BaseEndpointTypes , inputParameters } from '../endpoint/price'
6+ import { ethers , utils } from 'ethers'
7+ import { SubscriptionTransport } from '@chainlink/external-adapter-framework/transports/abstract/subscription'
58import {
69 EndpointContext ,
710 LwbaResponseDataFields ,
811} from '@chainlink/external-adapter-framework/adapter'
9- import { SubscriptionTransport } from '@chainlink/external-adapter-framework/transports/abstract/subscription'
1012import { AdapterResponse , makeLogger , sleep } from '@chainlink/external-adapter-framework/util'
11- import { AdapterDataProviderError } from '@chainlink/external-adapter-framework/validation/error'
12- import { ethers , utils } from 'ethers'
13- import { BaseEndpointTypes , ChainKey , inputParameters } from '../endpoint/price'
13+ import {
14+ decimals ,
15+ toFixed ,
16+ median ,
17+ PriceData ,
18+ SIGNED_PRICE_DECIMALS ,
19+ tokenAddresses ,
20+ Source ,
21+ } from './utils'
1422import abi from './../config/readerAbi.json'
15- import { TokenResolver } from './token-resolver'
16- import { median , PriceData , SIGNED_PRICE_DECIMALS , Source , toFixed , unwrapAsset } from './utils'
23+ import { AdapterDataProviderError } from '@chainlink/external-adapter-framework/validation/error'
1724
1825const logger = makeLogger ( 'GMToken' )
1926
@@ -25,11 +32,10 @@ export class GmTokenTransport extends SubscriptionTransport<GmTokenTransportType
2532 name ! : string
2633 responseCache ! : ResponseCache < GmTokenTransportTypes >
2734 requester ! : Requester
35+ provider ! : ethers . providers . JsonRpcProvider
36+ readerContract ! : ethers . Contract
2837 abiEncoder ! : utils . AbiCoder
2938 settings ! : GmTokenTransportTypes [ 'Settings' ]
30- tokenResolver ! : TokenResolver
31- private providers : Partial < Record < ChainKey , ethers . providers . JsonRpcProvider > > = { }
32- private readers : Partial < Record < ChainKey , ethers . Contract > > = { }
3339
3440 async initialize (
3541 dependencies : TransportDependencies < GmTokenTransportTypes > ,
@@ -39,8 +45,16 @@ export class GmTokenTransport extends SubscriptionTransport<GmTokenTransportType
3945 ) : Promise < void > {
4046 await super . initialize ( dependencies , adapterSettings , endpointName , transportName )
4147 this . settings = adapterSettings
48+ this . provider = new ethers . providers . JsonRpcProvider (
49+ adapterSettings . ARBITRUM_RPC_URL ,
50+ adapterSettings . ARBITRUM_CHAIN_ID ,
51+ )
52+ this . readerContract = new ethers . Contract (
53+ adapterSettings . READER_CONTRACT_ADDRESS ,
54+ abi ,
55+ this . provider ,
56+ )
4257 this . requester = dependencies . requester
43- this . tokenResolver = new TokenResolver ( this . requester , this . settings )
4458 }
4559
4660 async backgroundHandler ( context : EndpointContext < BaseEndpointTypes > , entries : RequestParams [ ] ) {
@@ -71,40 +85,35 @@ export class GmTokenTransport extends SubscriptionTransport<GmTokenTransportType
7185 async _handleRequest (
7286 param : RequestParams ,
7387 ) : Promise < AdapterResponse < GmTokenTransportTypes [ 'Response' ] > > {
74- const { index, long, short, market, chain } = param
88+ const { index, long, short, market } = param
7589
7690 const assets = [ index , long , short ]
7791
7892 const providerDataRequestedUnixMs = Date . now ( )
7993
80- const [ indexToken , longToken , shortToken ] = await Promise . all ( [
81- this . tokenResolver . getToken ( chain , index ) ,
82- this . tokenResolver . getToken ( chain , long ) ,
83- this . tokenResolver . getToken ( chain , short ) ,
84- ] )
85- const decimalsMap = new Map (
86- [ indexToken , longToken , shortToken ] . map ( ( t ) => [ t . symbol , t . decimals ] ) ,
87- )
88-
8994 const {
9095 prices : [ indexPrices , longPrices , shortPrices ] ,
9196 sources,
92- } = await this . fetchPrices ( assets , providerDataRequestedUnixMs , decimalsMap )
97+ } = await this . fetchPrices ( assets , providerDataRequestedUnixMs )
98+
99+ const indexToken = tokenAddresses . arbitrum [ index as keyof typeof tokenAddresses . arbitrum ]
100+ const longToken = tokenAddresses . arbitrum [ long as keyof typeof tokenAddresses . arbitrum ]
101+ const shortToken = tokenAddresses . arbitrum [ short as keyof typeof tokenAddresses . arbitrum ]
93102
94103 const tokenPriceContractParams = [
95- this . getDatastoreContractAddress ( chain as ChainKey ) ,
96- [ market , indexToken . address , longToken . address , shortToken . address ] ,
104+ this . settings . DATASTORE_CONTRACT_ADDRESS ,
105+ [ market , indexToken , longToken , shortToken ] ,
97106 [ indexPrices . ask , indexPrices . bid ] ,
98107 [ longPrices . ask , longPrices . bid ] ,
99108 [ shortPrices . ask , shortPrices . bid ] ,
100109 utils . keccak256 ( utils . defaultAbiCoder . encode ( [ 'string' ] , [ this . settings . PNL_FACTOR_TYPE ] ) ) ,
101110 ]
102- const readerContract = this . getReaderContract ( chain )
111+
103112 // Prices have a spread from min to max. The last param (maximize-true/false) decides whether to maximize the market token price
104113 // or not. We get both values and return the median.
105114 const [ [ maximizedValue ] , [ minimizedValue ] ] = await Promise . all ( [
106- readerContract . getMarketTokenPrice ( ...tokenPriceContractParams , true ) ,
107- readerContract . getMarketTokenPrice ( ...tokenPriceContractParams , false ) ,
115+ this . readerContract . getMarketTokenPrice ( ...tokenPriceContractParams , true ) ,
116+ this . readerContract . getMarketTokenPrice ( ...tokenPriceContractParams , false ) ,
108117 ] )
109118
110119 const maximizedPrice = Number ( utils . formatUnits ( maximizedValue , SIGNED_PRICE_DECIMALS ) )
@@ -127,11 +136,7 @@ export class GmTokenTransport extends SubscriptionTransport<GmTokenTransportType
127136 }
128137
129138 // Fetches the lwba price info from multiple source EAs, calculates the median for bids and asks per asset and fixes the price precision
130- private async fetchPrices (
131- assets : string [ ] ,
132- dataRequestedTimestamp : number ,
133- decimals : Map < string , number > ,
134- ) {
139+ private async fetchPrices ( assets : string [ ] , dataRequestedTimestamp : number ) {
135140 // priceData holds raw bid/ask values per asset from source EAs response
136141 const priceData = { } as PriceData
137142
@@ -150,7 +155,7 @@ export class GmTokenTransport extends SubscriptionTransport<GmTokenTransportType
150155 const source = sources [ i ]
151156
152157 const assetPromises = assets . map ( async ( asset ) => {
153- const base = unwrapAsset ( asset )
158+ const base = this . unwrapAsset ( asset )
154159 const requestConfig = {
155160 url : source . url ,
156161 method : 'POST' ,
@@ -197,17 +202,11 @@ export class GmTokenTransport extends SubscriptionTransport<GmTokenTransportType
197202
198203 const medianValues = this . calculateMedian ( assets , priceData )
199204
200- const prices = medianValues . map ( ( v ) => {
201- const decimal = decimals . get ( v . asset )
202- if ( ! decimal ) {
203- throw new Error ( `Missing token decimals for '${ v . asset } '` )
204- }
205- return {
206- ...v ,
207- ask : toFixed ( v . ask , decimal ) ,
208- bid : toFixed ( v . bid , decimal ) ,
209- }
210- } )
205+ const prices = medianValues . map ( ( v ) => ( {
206+ ...v ,
207+ ask : toFixed ( v . ask , decimals [ v . asset as keyof typeof decimals ] ) ,
208+ bid : toFixed ( v . bid , decimals [ v . asset as keyof typeof decimals ] ) ,
209+ } ) )
211210
212211 return {
213212 prices,
@@ -224,6 +223,16 @@ export class GmTokenTransport extends SubscriptionTransport<GmTokenTransportType
224223 } )
225224 }
226225
226+ private unwrapAsset ( asset : string ) {
227+ if ( asset === 'WBTC.b' ) {
228+ return 'BTC'
229+ }
230+ if ( asset === 'WETH' ) {
231+ return 'ETH'
232+ }
233+ return asset
234+ }
235+
227236 /*
228237 For every asset check that we received responses from the required number of source EAs to accurately calculate the median price of the asset.
229238 */
@@ -249,7 +258,7 @@ export class GmTokenTransport extends SubscriptionTransport<GmTokenTransportType
249258 }
250259
251260 assets . forEach ( ( asset ) => {
252- const base = unwrapAsset ( asset )
261+ const base = this . unwrapAsset ( asset )
253262 const respondedSources = priceProviders [ base ]
254263
255264 if ( respondedSources . length < this . settings . MIN_REQUIRED_SOURCE_SUCCESS ) {
@@ -273,39 +282,6 @@ export class GmTokenTransport extends SubscriptionTransport<GmTokenTransportType
273282 } )
274283 }
275284
276- private getProvider ( chain : ChainKey ) : ethers . providers . JsonRpcProvider {
277- if ( this . providers [ chain ] ) return this . providers [ chain ] !
278- const p =
279- chain === 'botanix'
280- ? new ethers . providers . JsonRpcProvider (
281- this . settings . BOTANIX_RPC_URL ,
282- this . settings . BOTANIX_CHAIN_ID ,
283- )
284- : new ethers . providers . JsonRpcProvider (
285- this . settings . ARBITRUM_RPC_URL ,
286- this . settings . ARBITRUM_CHAIN_ID ,
287- )
288- this . providers [ chain ] = p
289- return p
290- }
291-
292- private getReaderContract ( chain : ChainKey ) : ethers . Contract {
293- if ( this . readers [ chain ] ) return this . readers [ chain ] !
294- const addr =
295- chain === 'botanix'
296- ? this . settings . BOTANIX_READER_CONTRACT_ADDRESS
297- : this . settings . READER_CONTRACT_ADDRESS
298- const reader = new ethers . Contract ( addr , abi , this . getProvider ( chain ) )
299- this . readers [ chain ] = reader
300- return reader
301- }
302-
303- private getDatastoreContractAddress ( chain : ChainKey ) : string {
304- return chain === 'botanix'
305- ? this . settings . BOTANIX_DATASTORE_CONTRACT_ADDRESS
306- : this . settings . DATASTORE_CONTRACT_ADDRESS
307- }
308-
309285 getSubscriptionTtlFromConfig ( adapterSettings : BaseEndpointTypes [ 'Settings' ] ) : number {
310286 return adapterSettings . WARMUP_SUBSCRIPTION_TTL
311287 }
0 commit comments