Skip to content

Commit

Permalink
feat: add retry for GetExchangeRateFromBinanceApi and change mode to …
Browse files Browse the repository at this point in the history
…string
  • Loading branch information
yiweichi committed Oct 11, 2024
1 parent 93adbea commit 722f36b
Show file tree
Hide file tree
Showing 4 changed files with 57 additions and 70 deletions.
35 changes: 4 additions & 31 deletions rollup/internal/config/relayer.go
Original file line number Diff line number Diff line change
@@ -1,37 +1,10 @@
package config

import (
"fmt"
"strings"

"github.com/scroll-tech/go-ethereum/common"
"github.com/scroll-tech/go-ethereum/rpc"
)

const (
FIXED ExchangeRateMode = "Fixed"
BINANCE_API ExchangeRateMode = "BinanceApi"
UNISWAP ExchangeRateMode = "Uniswap"
)

// ExchangeRateMode the mode to retrieve exchange rate
type ExchangeRateMode string

func (m *ExchangeRateMode) UnmarshalText(data []byte) error {
candidates := []string{
string(FIXED),
string(BINANCE_API),
// string(UNISWAP), not supported yet
}
for _, i := range candidates {
if string(data) == i {
*m = ExchangeRateMode(i)
return nil
}
}
return fmt.Errorf("invalid mode: %s, must be one of %s", string(data), strings.Join(candidates, ","))
}

// SenderConfig The config for transaction sender
type SenderConfig struct {
// The RPC endpoint of the ethereum or scroll public node.
Expand Down Expand Up @@ -97,10 +70,10 @@ type RelayerConfig struct {

// AlternativeGasTokenConfig The configuration for handling token exchange rates when updating the gas price oracle.
type AlternativeGasTokenConfig struct {
Enabled bool `json:"enabled"`
Mode ExchangeRateMode `json:"mode"`
FixedExchangeRate float64 `json:"fixed_exchange_rate"` // fixed exchange rate of L2 gas token / L1 gas token
TokenSymbolPair string `json:"token_symbol_pair"` // The pair should be L2 gas token symbol + L1 gas token symbol
Enabled bool `json:"enabled"`
Mode string `json:"mode"`
FixedExchangeRate float64 `json:"fixed_exchange_rate"` // fixed exchange rate of L2 gas token / L1 gas token
TokenSymbolPair string `json:"token_symbol_pair"` // The pair should be L2 gas token symbol + L1 gas token symbol
}

// GasOracleConfig The config for updating gas price oracle.
Expand Down
9 changes: 4 additions & 5 deletions rollup/internal/controller/relayer/l1_relayer.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,11 @@ import (
"scroll-tech/common/types"
"scroll-tech/common/utils"

rutils "scroll-tech/rollup/internal/utils"

bridgeAbi "scroll-tech/rollup/abi"
"scroll-tech/rollup/internal/config"
"scroll-tech/rollup/internal/controller/sender"
"scroll-tech/rollup/internal/orm"
rutils "scroll-tech/rollup/internal/utils"
)

// Layer1Relayer is responsible for updating L1 gas price oracle contract on L2.
Expand Down Expand Up @@ -158,10 +157,10 @@ func (r *Layer1Relayer) ProcessGasPriceOracle() {
// The exchange rate represent the number of native token on L1 required to exchange for 1 native token on L2.
var exchangeRate float64
switch r.cfg.GasOracleConfig.AlternativeGasTokenConfig.Mode {
case config.FIXED:
case "Fixed":
exchangeRate = r.cfg.GasOracleConfig.AlternativeGasTokenConfig.FixedExchangeRate
case config.BINANCE_API:
exchangeRate, err = rutils.GetExchangeRateFromBinanceApi(r.cfg.GasOracleConfig.AlternativeGasTokenConfig.TokenSymbolPair)
case "BinanceApi":
exchangeRate, err = rutils.GetExchangeRateFromBinanceApi(r.cfg.GasOracleConfig.AlternativeGasTokenConfig.TokenSymbolPair, 5)
if err != nil {
log.Error("Failed to get gas token exchange rate from Binance api", "tokenSymbolPair", r.cfg.GasOracleConfig.AlternativeGasTokenConfig.TokenSymbolPair, "err", err)
return
Expand Down
7 changes: 3 additions & 4 deletions rollup/internal/controller/relayer/l2_relayer.go
Original file line number Diff line number Diff line change
Expand Up @@ -331,15 +331,14 @@ func (r *Layer2Relayer) ProcessGasPriceOracle() {
// The exchange rate represent the number of native token on L1 required to exchange for 1 native token on L2.
var exchangeRate float64
switch r.cfg.GasOracleConfig.AlternativeGasTokenConfig.Mode {
case config.FIXED:
case "Fixed":
exchangeRate = r.cfg.GasOracleConfig.AlternativeGasTokenConfig.FixedExchangeRate
case config.BINANCE_API:
exchangeRate, err = rutils.GetExchangeRateFromBinanceApi(r.cfg.GasOracleConfig.AlternativeGasTokenConfig.TokenSymbolPair)
case "BinanceApi":
exchangeRate, err = rutils.GetExchangeRateFromBinanceApi(r.cfg.GasOracleConfig.AlternativeGasTokenConfig.TokenSymbolPair, 5)
if err != nil {
log.Error("Failed to get gas token exchange rate from Binance api", "tokenSymbolPair", r.cfg.GasOracleConfig.AlternativeGasTokenConfig.TokenSymbolPair, "err", err)
return
}

default:
log.Error("Invalid alternative gas token mode", "mode", r.cfg.GasOracleConfig.AlternativeGasTokenConfig.Mode)
return
Expand Down
76 changes: 46 additions & 30 deletions rollup/internal/utils/exchange_rate.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (
"io"
"net/http"
"strconv"
"time"

"github.com/scroll-tech/go-ethereum/log"
)
Expand All @@ -16,42 +17,57 @@ type BinanceResponse struct {
Price string `json:"price"`
}

func GetExchangeRateFromBinanceApi(tokenSymbolPair string) (float64, error) {
// make HTTP GET request
resp, err := http.Get(fmt.Sprintf(BinanceApiEndpoint, tokenSymbolPair))
if err != nil {
return 0, fmt.Errorf("error making HTTP request: %w", err)
}
defer func() {
err = resp.Body.Close()
func GetExchangeRateFromBinanceApi(tokenSymbolPair string, maxRetries int) (float64, error) {
for i := 0; i < maxRetries; i++ {
if i > 0 {
time.Sleep(5 * time.Second)
}

// make HTTP GET request
resp, err := http.Get(fmt.Sprintf(BinanceApiEndpoint, tokenSymbolPair))
if err != nil {
log.Error("error closing response body", "err", err)
log.Error("error making HTTP request", "err", err)
continue
}
}()
defer func() {
err = resp.Body.Close()
if err != nil {
log.Error("error closing response body", "err", err)
}
}()

// check for successful response
if resp.StatusCode != http.StatusOK {
return 0, fmt.Errorf("unexpected status code: %d", resp.StatusCode)
}
// check for successful response
if resp.StatusCode != http.StatusOK {
log.Error("unexpected status code", "code", resp.StatusCode)
continue
}

// read response body
body, err := io.ReadAll(resp.Body)
if err != nil {
return 0, fmt.Errorf("error reading response body: %w", err)
}
// read response body
body, err := io.ReadAll(resp.Body)
if err != nil {
log.Error("error reading response body", "err", err)
continue
}

// unmarshal JSON response
var data BinanceResponse
err = json.Unmarshal(body, &data)
if err != nil {
return 0, fmt.Errorf("error unmarshaling JSON: %w", err)
}
// unmarshal JSON response
var data BinanceResponse
err = json.Unmarshal(body, &data)
if err != nil {
log.Error("error unmarshaling JSON", "err", err)
continue
}

// convert price string to float64
price, err := strconv.ParseFloat(data.Price, 64)
if err != nil {
log.Error("error parsing price string", "err", err)
continue
}

// convert price string to float64
price, err := strconv.ParseFloat(data.Price, 64)
if err != nil {
return 0, fmt.Errorf("error parsing price string: %w", err)
// successful response, return price
return price, nil
}

return price, nil
// all retries failed, return error
return 0, fmt.Errorf("failed to get exchange rate after %d retries", maxRetries)
}

0 comments on commit 722f36b

Please sign in to comment.