@@ -21,16 +21,11 @@ type PriceUpdater struct {
2121 registryContract * bindings.L2TokenRegistry
2222 priceFeed client.PriceFeed
2323 txManager * TxManager
24- tokenIDs []uint16
2524 tokenMapping map [uint16 ]string // tokenID -> trading pair (e.g. 1 -> "BTCUSDT")
2625 interval time.Duration
2726 priceThreshold uint64
28-
29- // Cache of last updated prices
30- lastPrices map [uint16 ]* big.Int
31- mu sync.RWMutex
32- stopChan chan struct {}
33- stopOnce sync.Once // ensures stopChan is closed only once
27+ stopChan chan struct {}
28+ stopOnce sync.Once // ensures stopChan is closed only once
3429}
3530
3631// NewPriceUpdater creates a new price updater
@@ -39,7 +34,6 @@ func NewPriceUpdater(
3934 registryContract * bindings.L2TokenRegistry ,
4035 priceFeed client.PriceFeed ,
4136 txManager * TxManager ,
42- tokenIDs []uint16 ,
4337 tokenMapping map [uint16 ]string ,
4438 interval time.Duration ,
4539 priceThreshold uint64 ,
@@ -49,11 +43,9 @@ func NewPriceUpdater(
4943 registryContract : registryContract ,
5044 priceFeed : priceFeed ,
5145 txManager : txManager ,
52- tokenIDs : tokenIDs ,
5346 tokenMapping : tokenMapping ,
5447 interval : interval ,
5548 priceThreshold : priceThreshold ,
56- lastPrices : make (map [uint16 ]* big.Int ),
5749 stopChan : make (chan struct {}),
5850 }
5951}
@@ -65,25 +57,6 @@ func (u *PriceUpdater) Start(ctx context.Context) error {
6557 ticker := time .NewTicker (u .interval )
6658 defer ticker .Stop ()
6759
68- // Fetch token IDs from contract if not configured
69- // TODO: Uncomment when contract has getSupportedIDList method
70- // if len(u.tokenIDs) == 0 {
71- // log.Info("No tokenIDs configured, fetching from contract...")
72- // if err := u.fetchTokenIDsFromContract(ctx); err != nil {
73- // log.Error("Failed to fetch tokenIDs from contract, price updater will not start")
74- // return
75- // }
76- // }
77-
78- // Filter tokenIDs to only those in tokenMapping
79- u .filterTokenIDsByMapping ()
80-
81- log .Info ("Price updater started" ,
82- "token_ids" , u .tokenIDs ,
83- "token_mapping" , u .tokenMapping ,
84- "interval" , u .interval ,
85- "price_threshold" , u .priceThreshold )
86-
8760 if err := u .update (ctx ); err != nil {
8861 log .Error ("Initial price update failed" )
8962 }
@@ -125,10 +98,12 @@ func (u *PriceUpdater) update(ctx context.Context) error {
12598 }
12699 }()
127100
128- // Snapshot tokenIDs under lock to avoid race conditions
129- u .mu .RLock ()
130- tokenIDs := append ([]uint16 (nil ), u .tokenIDs ... )
131- u .mu .RUnlock ()
101+ // Fetch token IDs from contract if not configured
102+ tokenIDs , err := u .fetchTokenIDsFromContract (ctx )
103+ if err != nil {
104+ log .Error ("Failed to fetch tokenIDs from contract, price updater will not start" )
105+ return err
106+ }
132107
133108 if len (tokenIDs ) == 0 {
134109 log .Warn ("No tokens to update, skipping price update cycle" )
@@ -211,27 +186,30 @@ func (u *PriceUpdater) update(ctx context.Context) error {
211186 log .Info ("Updating token prices" ,
212187 "token_count" , len (tokenIDsToUpdate ),
213188 "token_ids" , tokenIDsToUpdate ,
214- "total_tokens" , len (u . tokenIDs ))
189+ "total_tokens" , len (tokenIDs ))
215190
216191 // Step 3: Update prices on L2
217192 receipt , err := u .txManager .SendTransaction (ctx , func (auth * bind.TransactOpts ) (* types.Transaction , error ) {
218193 return u .registryContract .BatchUpdatePrices (auth , tokenIDsToUpdate , pricesToUpdate )
219194 })
195+
220196 if err != nil {
197+ log .Error ("Failed to send transaction" , "error" , err )
221198 return fmt .Errorf ("failed to send batch update prices transaction: %w" , err )
222199 }
223200
224- if receipt . Status == 0 {
225- log .Error ("Transaction failed" , "tx_hash" , receipt . TxHash . Hex () )
226- return fmt .Errorf ("transaction failed on-chain: %s" , receipt . TxHash . Hex () )
201+ if receipt == nil {
202+ log .Error ("Received nil receipt" )
203+ return fmt .Errorf ("received nil receipt" )
227204 }
228205
229- // Step 4: Update cache with new prices
230- u .mu .Lock ()
231- for i , tokenID := range tokenIDsToUpdate {
232- u .lastPrices [tokenID ] = pricesToUpdate [i ]
206+ if receipt .Status != types .ReceiptStatusSuccessful {
207+ log .Error ("Transaction failed on-chain" ,
208+ "tx_hash" , receipt .TxHash .Hex (),
209+ "status" , receipt .Status ,
210+ "gas_used" , receipt .GasUsed )
211+ return fmt .Errorf ("transaction failed on-chain: %s" , receipt .TxHash .Hex ())
233212 }
234- u .mu .Unlock ()
235213
236214 log .Info ("Successfully updated token prices" ,
237215 "tx_hash" , receipt .TxHash .Hex (),
@@ -397,111 +375,10 @@ func (u *PriceUpdater) shouldUpdatePrice(lastPrice, newPrice *big.Int) bool {
397375 return percentage .Cmp (thresholdBig ) >= 0
398376}
399377
400- // UpdateTokenList updates the list of tokens to monitor
401- // The input slice is copied to prevent external modifications
402- func (u * PriceUpdater ) UpdateTokenList (tokenIDs []uint16 ) {
403- u .mu .Lock ()
404- defer u .mu .Unlock ()
405-
406- // Create a defensive copy to prevent external modifications
407- u .tokenIDs = append ([]uint16 (nil ), tokenIDs ... )
408- log .Info ("Updated token list" , "token_ids" , u .tokenIDs )
409- }
410-
411- // GetTokenList returns a copy of the current token list
412- func (u * PriceUpdater ) GetTokenList () []uint16 {
413- u .mu .RLock ()
414- defer u .mu .RUnlock ()
415-
416- // Return a copy to prevent external modifications
417- out := make ([]uint16 , len (u .tokenIDs ))
418- copy (out , u .tokenIDs )
419- return out
420- }
421-
422- // GetLastPrice returns the last updated price for a token
423- func (u * PriceUpdater ) GetLastPrice (tokenID uint16 ) * big.Int {
424- u .mu .RLock ()
425- defer u .mu .RUnlock ()
426-
427- if price , exists := u .lastPrices [tokenID ]; exists {
428- return new (big.Int ).Set (price )
429- }
430- return nil
431- }
432-
433- // GetAllLastPrices returns a copy of all cached prices
434- func (u * PriceUpdater ) GetAllLastPrices () map [uint16 ]* big.Int {
435- u .mu .RLock ()
436- defer u .mu .RUnlock ()
437-
438- result := make (map [uint16 ]* big.Int )
439- for tokenID , price := range u .lastPrices {
440- result [tokenID ] = new (big.Int ).Set (price )
441- }
442- return result
443- }
444-
445378// fetchTokenIDsFromContract fetches supported token IDs from L2TokenRegistry contract
446- func (u * PriceUpdater ) fetchTokenIDsFromContract (ctx context.Context ) error {
379+ func (u * PriceUpdater ) fetchTokenIDsFromContract (ctx context.Context ) ([] uint16 , error ) {
447380 callOpts := & bind.CallOpts {Context : ctx }
448381
449382 // Call getSupportedIDList() on the contract
450- tokenIDs , err := u .registryContract .GetSupportedIDList (callOpts )
451- if err != nil {
452- return fmt .Errorf ("failed to call getSupportedIDList: %w" , err )
453- }
454-
455- if len (tokenIDs ) == 0 {
456- log .Warn ("Contract returned empty token ID list" )
457- return nil
458- }
459-
460- u .mu .Lock ()
461- u .tokenIDs = tokenIDs
462- u .mu .Unlock ()
463-
464- log .Info ("Fetched token IDs from contract" ,
465- "token_ids" , tokenIDs ,
466- "count" , len (tokenIDs ))
467-
468- return nil
469- }
470-
471- // filterTokenIDsByMapping filters tokenIDs to only include those that have a mapping configured
472- func (u * PriceUpdater ) filterTokenIDsByMapping () {
473- // Always acquire lock before modifying u.tokenIDs to prevent race conditions
474- u .mu .Lock ()
475- defer u .mu .Unlock ()
476-
477- // Check if token mapping is configured
478- if len (u .tokenMapping ) == 0 {
479- log .Error ("No token mapping configured for current price feed type, price updater will not work. Please configure the appropriate token-mapping flag (e.g., --token-mapping-bitget, --token-mapping-binance)" )
480- u .tokenIDs = []uint16 {}
481- return
482- }
483-
484- var filtered []uint16
485- var unmapped []uint16
486- for _ , tokenID := range u .tokenIDs {
487- if _ , exists := u .tokenMapping [tokenID ]; exists {
488- filtered = append (filtered , tokenID )
489- } else {
490- unmapped = append (unmapped , tokenID )
491- log .Warn ("Token ID not in mapping, skipping price update for this token" ,
492- "token_id" , tokenID )
493- }
494- }
495-
496- u .tokenIDs = filtered
497-
498- if len (unmapped ) > 0 {
499- log .Warn ("Some token IDs from contract are not mapped to trading pairs. Please update token mapping configuration if needed." ,
500- "unmapped_token_ids" , unmapped ,
501- "mapped_token_ids" , filtered )
502- }
503-
504- log .Info ("Filtered token IDs by mapping" ,
505- "filtered_count" , len (filtered ),
506- "token_ids" , filtered )
383+ return u .registryContract .GetSupportedIDList (callOpts )
507384}
0 commit comments