@@ -3,80 +3,99 @@ export type Address = `0x${string}`;
33export type Hex = `0x${string } `;
44export type TransactionRequest = any ;
55
6- export function encodeFunctionData ( params : { abi : any ; functionName : string ; args : any [ ] } ) : Hex {
6+ export function encodeFunctionData ( params : {
7+ abi : any ;
8+ functionName : string ;
9+ args : any [ ] ;
10+ } ) : Hex {
711 const methodSignatures : Record < string , string > = {
812 updatePriceFeeds : "0x1f379acc" ,
9- aggregate : "0x252dba42"
13+ aggregate : "0x252dba42" ,
1014 } ;
11-
15+
1216 if ( params . functionName === "updatePriceFeeds" ) {
1317 const updateData = params . args [ 0 ] as string [ ] ;
1418 let encoded = methodSignatures . updatePriceFeeds ;
15- encoded += "0000000000000000000000000000000000000000000000000000000000000020" ;
16- encoded += updateData . length . toString ( 16 ) . padStart ( 64 , '0' ) ;
17-
19+ encoded +=
20+ "0000000000000000000000000000000000000000000000000000000000000020" ;
21+ encoded += updateData . length . toString ( 16 ) . padStart ( 64 , "0" ) ;
22+
1823 for ( let i = 0 ; i < updateData . length ; i ++ ) {
19- const offset = ( 0x20 + updateData . length * 0x20 + i * updateData [ i ] . length / 2 ) . toString ( 16 ) . padStart ( 64 , '0' ) ;
24+ const offset = (
25+ 0x20 +
26+ updateData . length * 0x20 +
27+ ( i * updateData [ i ] . length ) / 2
28+ )
29+ . toString ( 16 )
30+ . padStart ( 64 , "0" ) ;
2031 encoded += offset ;
2132 }
22-
33+
2334 for ( const data of updateData ) {
24- const dataLength = ( data . length / 2 - 1 ) . toString ( 16 ) . padStart ( 64 , '0' ) ;
35+ const dataLength = ( data . length / 2 - 1 ) . toString ( 16 ) . padStart ( 64 , "0" ) ;
2536 encoded += dataLength ;
2637 encoded += data . slice ( 2 ) ;
2738 const padding = ( 32 - ( ( data . length / 2 - 1 ) % 32 ) ) % 32 ;
2839 encoded += "0" . repeat ( padding * 2 ) ;
2940 }
30-
41+
3142 return `0x${ encoded } ` as Hex ;
3243 }
33-
44+
3445 if ( params . functionName === "aggregate" ) {
3546 const calls = params . args [ 0 ] as Array < { target : string ; callData : string } > ;
3647 let encoded = methodSignatures . aggregate ;
37- encoded += "0000000000000000000000000000000000000000000000000000000000000020" ;
38- encoded += calls . length . toString ( 16 ) . padStart ( 64 , '0' ) ;
39-
48+ encoded +=
49+ "0000000000000000000000000000000000000000000000000000000000000020" ;
50+ encoded += calls . length . toString ( 16 ) . padStart ( 64 , "0" ) ;
51+
4052 for ( let i = 0 ; i < calls . length ; i ++ ) {
41- const offset = ( 0x20 + calls . length * 0x20 + i * 0x40 ) . toString ( 16 ) . padStart ( 64 , '0' ) ;
53+ const offset = ( 0x20 + calls . length * 0x20 + i * 0x40 )
54+ . toString ( 16 )
55+ . padStart ( 64 , "0" ) ;
4256 encoded += offset ;
4357 }
44-
58+
4559 for ( const call of calls ) {
46- encoded += call . target . slice ( 2 ) . padStart ( 64 , '0' ) ;
47- encoded += "0000000000000000000000000000000000000000000000000000000000000040" ;
48- const dataLength = ( call . callData . length / 2 - 1 ) . toString ( 16 ) . padStart ( 64 , '0' ) ;
60+ encoded += call . target . slice ( 2 ) . padStart ( 64 , "0" ) ;
61+ encoded +=
62+ "0000000000000000000000000000000000000000000000000000000000000040" ;
63+ const dataLength = ( call . callData . length / 2 - 1 )
64+ . toString ( 16 )
65+ . padStart ( 64 , "0" ) ;
4966 encoded += dataLength ;
5067 encoded += call . callData . slice ( 2 ) ;
5168 const padding = ( 32 - ( ( call . callData . length / 2 - 1 ) % 32 ) ) % 32 ;
5269 encoded += "0" . repeat ( padding * 2 ) ;
5370 }
54-
71+
5572 return `0x${ encoded } ` as Hex ;
5673 }
57-
74+
5875 return "0x" as Hex ;
5976}
6077
61- export function decodeFunctionData ( params : { abi : any ; data : Hex } ) : { args : any [ ] } {
78+ export function decodeFunctionData ( params : { abi : any ; data : Hex } ) : {
79+ args : any [ ] ;
80+ } {
6281 const data = params . data ;
6382 if ( ! data || data . length < 10 ) return { args : [ ] } ;
64-
83+
6584 const methodId = data . slice ( 0 , 10 ) ;
6685 const methodSignatures : Record < string , string > = {
6786 "0x41976e09" : "getPrice" ,
68- "0xf7888aec" : "getPriceUnsafe" ,
87+ "0xf7888aec" : "getPriceUnsafe" ,
6988 "0x45a7c7e8" : "getPriceNoOlderThan" ,
7089 "0x42c84d10" : "getEmaPrice" ,
7190 "0xd1a8b23f" : "getEmaPriceUnsafe" ,
72- "0x9a7b2b7f" : "getEmaPriceNoOlderThan"
91+ "0x9a7b2b7f" : "getEmaPriceNoOlderThan" ,
7392 } ;
74-
93+
7594 if ( methodSignatures [ methodId ] ) {
7695 const priceId = data . slice ( 10 , 74 ) ;
7796 return { args : [ `0x${ priceId } ` ] } ;
7897 }
79-
98+
8099 return { args : [ ] } ;
81100}
82101
@@ -90,29 +109,30 @@ interface TraceCallResult {
90109 input ?: string ;
91110}
92111
93- async function traceCall ( client : PublicClient , params : any ) : Promise < TraceCallResult > {
112+ async function traceCall (
113+ client : PublicClient ,
114+ params : any ,
115+ ) : Promise < TraceCallResult > {
94116 try {
95117 if ( client . request ) {
96118 const result = await client . request ( {
97- method : 'debug_traceCall' ,
98- params : [
99- params ,
100- 'latest' ,
101- { tracer : 'callTracer' }
102- ]
119+ method : "debug_traceCall" ,
120+ params : [ params , "latest" , { tracer : "callTracer" } ] ,
103121 } ) ;
104122 return result as TraceCallResult ;
105123 }
106-
124+
107125 const mockTrace : TraceCallResult = {
108126 to : "0x4305FB66699C3B2702D4d05CF36551390A4c69C6" ,
109- input : "0xf7888aec0000000000000000000000000000000000000000000000000000000000000001" ,
127+ input :
128+ "0xf7888aec0000000000000000000000000000000000000000000000000000000000000001" ,
110129 calls : [
111130 {
112131 to : "0x4305FB66699C3B2702D4d05CF36551390A4c69C6" ,
113- input : "0xf7888aec0000000000000000000000000000000000000000000000000000000000000001"
114- }
115- ]
132+ input :
133+ "0xf7888aec0000000000000000000000000000000000000000000000000000000000000001" ,
134+ } ,
135+ ] ,
116136 } ;
117137 return mockTrace ;
118138 } catch ( error ) {
@@ -135,13 +155,13 @@ class HermesClient {
135155 }
136156
137157 async getLatestPriceUpdates (
138- priceIds : string [ ] ,
139- options ?: { encoding ?: string }
158+ priceIds : string [ ] ,
159+ options ?: { encoding ?: string } ,
140160 ) : Promise < PriceUpdate > {
141- const url = new URL ( ' /v2/updates/price/latest' , this . endpoint ) ;
142- priceIds . forEach ( id => url . searchParams . append ( ' ids[]' , id ) ) ;
161+ const url = new URL ( " /v2/updates/price/latest" , this . endpoint ) ;
162+ priceIds . forEach ( ( id ) => url . searchParams . append ( " ids[]" , id ) ) ;
143163 if ( options ?. encoding ) {
144- url . searchParams . set ( ' encoding' , options . encoding ) ;
164+ url . searchParams . set ( " encoding" , options . encoding ) ;
145165 }
146166
147167 const response = await fetch ( url . toString ( ) ) ;
@@ -198,7 +218,8 @@ const MULTICALL3_ABI = parseAbi([
198218 "function aggregate(Call[] calldata calls) external payable returns (uint256 blockNumber, bytes[] memory returnData)" ,
199219] ) ;
200220
201- const MULTICALL3_ADDRESS : Address = "0xcA11bde05977b3631167028862bE2a173976CA11" ;
221+ const MULTICALL3_ADDRESS : Address =
222+ "0xcA11bde05977b3631167028862bE2a173976CA11" ;
202223
203224export class TransactionFiller {
204225 private config : TransactionFillerConfig ;
@@ -213,7 +234,7 @@ export class TransactionFiller {
213234 }
214235
215236 async fillTransaction (
216- transaction : TransactionContent
237+ transaction : TransactionContent ,
217238 ) : Promise < FilledTransactionResult > {
218239 const detectedPriceFeeds = new Set < Hex > ( ) ;
219240 let currentTransaction = transaction ;
@@ -222,9 +243,9 @@ export class TransactionFiller {
222243
223244 while ( iterations < maxIterations ) {
224245 iterations ++ ;
225-
246+
226247 const newPriceFeeds = await this . detectPythUsage ( currentTransaction ) ;
227-
248+
228249 if ( newPriceFeeds . length === 0 ) {
229250 break ;
230251 }
@@ -242,22 +263,24 @@ export class TransactionFiller {
242263 }
243264
244265 const priceUpdateData = await this . fetchPriceUpdates (
245- Array . from ( detectedPriceFeeds )
266+ Array . from ( detectedPriceFeeds ) ,
246267 ) ;
247268
248269 currentTransaction = await this . createBundledTransaction (
249270 transaction ,
250- priceUpdateData
271+ priceUpdateData ,
251272 ) ;
252273 }
253274
254- const finalPriceUpdateData = detectedPriceFeeds . size > 0
255- ? await this . fetchPriceUpdates ( Array . from ( detectedPriceFeeds ) )
256- : [ ] ;
275+ const finalPriceUpdateData =
276+ detectedPriceFeeds . size > 0
277+ ? await this . fetchPriceUpdates ( Array . from ( detectedPriceFeeds ) )
278+ : [ ] ;
257279
258- const finalTransaction = detectedPriceFeeds . size > 0
259- ? await this . createBundledTransaction ( transaction , finalPriceUpdateData )
260- : transaction ;
280+ const finalTransaction =
281+ detectedPriceFeeds . size > 0
282+ ? await this . createBundledTransaction ( transaction , finalPriceUpdateData )
283+ : transaction ;
261284
262285 return {
263286 transaction : finalTransaction ,
@@ -267,15 +290,17 @@ export class TransactionFiller {
267290 } ;
268291 }
269292
270- private async detectPythUsage ( transaction : TransactionContent ) : Promise < Hex [ ] > {
293+ private async detectPythUsage (
294+ transaction : TransactionContent ,
295+ ) : Promise < Hex [ ] > {
271296 try {
272297 const trace = await traceCall ( this . config . viemClient , {
273298 ...transaction ,
274299 blockTag : "latest" ,
275300 } ) ;
276301
277302 const priceFeeds = new Set < Hex > ( ) ;
278-
303+
279304 this . extractPriceFeedsFromTrace ( trace , priceFeeds ) ;
280305
281306 return Array . from ( priceFeeds ) ;
@@ -285,10 +310,15 @@ export class TransactionFiller {
285310 }
286311 }
287312
288- private extractPriceFeedsFromTrace ( trace : TraceCallResult , priceFeeds : Set < Hex > ) : void {
313+ private extractPriceFeedsFromTrace (
314+ trace : TraceCallResult ,
315+ priceFeeds : Set < Hex > ,
316+ ) : void {
289317 if ( ! trace ) return ;
290318
291- if ( trace . to ?. toLowerCase ( ) === this . config . pythContractAddress . toLowerCase ( ) ) {
319+ if (
320+ trace . to ?. toLowerCase ( ) === this . config . pythContractAddress . toLowerCase ( )
321+ ) {
292322 const feedId = this . extractPriceFeedFromCall ( trace . input as Hex ) ;
293323 if ( feedId ) {
294324 priceFeeds . add ( feedId ) ;
@@ -325,11 +355,11 @@ export class TransactionFiller {
325355 if ( priceFeeds . length === 0 ) return [ ] ;
326356
327357 try {
328- const priceIds = priceFeeds . map ( feed => feed . slice ( 2 ) ) ;
358+ const priceIds = priceFeeds . map ( ( feed ) => feed . slice ( 2 ) ) ;
329359 const response = await this . hermesClient . getLatestPriceUpdates ( priceIds , {
330360 encoding : "hex" ,
331361 } ) ;
332-
362+
333363 return response . binary . data . map ( ( update : string ) => `0x${ update } ` as Hex ) ;
334364 } catch ( error ) {
335365 console . warn ( "Failed to fetch price updates:" , error ) ;
@@ -339,7 +369,7 @@ export class TransactionFiller {
339369
340370 private async createBundledTransaction (
341371 originalTransaction : TransactionContent ,
342- priceUpdateData : Hex [ ]
372+ priceUpdateData : Hex [ ] ,
343373 ) : Promise < TransactionContent > {
344374 if ( priceUpdateData . length === 0 ) {
345375 return originalTransaction ;
@@ -378,7 +408,7 @@ export class TransactionFiller {
378408
379409export async function fillTransactionWithPythData (
380410 config : TransactionFillerConfig ,
381- transaction : TransactionContent
411+ transaction : TransactionContent ,
382412) : Promise < FilledTransactionResult > {
383413 const filler = new TransactionFiller ( config ) ;
384414 return filler . fillTransaction ( transaction ) ;
0 commit comments