From 9f2bc02ed377c7e957ecb737ace545dd4b698ce9 Mon Sep 17 00:00:00 2001 From: cherry <60910788+cherry-yl-sh@users.noreply.github.com> Date: Tue, 9 Jul 2024 19:58:31 +0800 Subject: [PATCH] Price optimize (#31) --- cmd/server/main.go | 3 +- common/price_compoent/price_util.go | 136 ++++++++++++++--------- common/price_compoent/price_util_test.go | 11 +- docs/docs.go | 16 +++ docs/swagger.json | 16 +++ docs/swagger.yaml | 10 ++ rpc_server/api/v1/sponsor.go | 13 +++ rpc_server/routers/routers_map.go | 2 + 8 files changed, 147 insertions(+), 60 deletions(-) diff --git a/cmd/server/main.go b/cmd/server/main.go index 8118cf09..ce8a02a6 100644 --- a/cmd/server/main.go +++ b/cmd/server/main.go @@ -1,6 +1,7 @@ package main import ( + "AAStarCommunity/EthPaymaster_BackService/common/price_compoent" "AAStarCommunity/EthPaymaster_BackService/config" "AAStarCommunity/EthPaymaster_BackService/envirment" "AAStarCommunity/EthPaymaster_BackService/rpc_server/routers" @@ -52,7 +53,6 @@ func main() { } initEngine(strategyPath, basicConfigPath, secretPath) port := runMode() - os.Getenv("secret_config_path") _ = Engine.Run(port) } @@ -68,5 +68,6 @@ func initEngine(strategyPath string, basicConfigPath string, secretPath string) sponsor_manager.Init() logrus.Infof("Environment: %s", envirment.Environment.Name) logrus.Infof("Debugger: %v", envirment.Environment.Debugger) + price_compoent.Init() Engine = routers.SetRouters() } diff --git a/common/price_compoent/price_util.go b/common/price_compoent/price_util.go index 8fb3e99c..491255b4 100644 --- a/common/price_compoent/price_util.go +++ b/common/price_compoent/price_util.go @@ -3,22 +3,18 @@ package price_compoent import ( "AAStarCommunity/EthPaymaster_BackService/common/global_const" "AAStarCommunity/EthPaymaster_BackService/config" + "encoding/json" "fmt" + "github.com/sirupsen/logrus" "golang.org/x/xerrors" "io" - "io/ioutil" - "log" "math/big" "net/http" - "net/url" - "os" - "strconv" - "strings" + "time" ) var ( - URLMap = map[global_const.TokenType]string{} - httpClient = &http.Client{} + URLMap = map[global_const.TokenType]string{} ) type Price struct { @@ -26,10 +22,65 @@ type Price struct { func init() { URLMap = make(map[global_const.TokenType]string) - URLMap[global_const.TokenTypeETH] = "https://api.coingecko.com/api/v3/simple/price?ids=ethereum&vs_currencies=usd" - URLMap[global_const.TokenTypeOP] = "https://api.coingecko.com/api/v3/simple/price?ids=optimism&vs_currencies=usd" + template := "https://api.coingecko.com/api/v3/simple/price?ids=%s&vs_currencies=usd" + for token, tokenSymbol := range TokenSymbolMap { + URLMap[token] = fmt.Sprintf(template, tokenSymbol) + } + +} + +var globalPriceMap = make(map[global_const.TokenType]float64) + +var TokenSymbolMap = map[global_const.TokenType]string{ + global_const.TokenTypeETH: "ethereum", + global_const.TokenTypeOP: "optimism", } +func Init() { + go func() { + for { + GetConfigTokenPrice() + time.Sleep(60 * time.Second) + } + }() +} + +func GetGlobalPriceMap() map[global_const.TokenType]float64 { + return globalPriceMap +} + +func GetConfigTokenPrice() { + priceNetworkMap := make(map[global_const.TokenType]float64) + for token, tokenUrl := range URLMap { + + req, err := http.NewRequest("GET", tokenUrl, nil) + if err != nil { + logrus.Error(xerrors.Errorf("[Price Thread ERROR] http request error: %w", err)) + continue + } + req.Header.Add("x-cg-demo-api-key", config.GetPriceOracleApiKey()) + + res, err := http.DefaultClient.Do(req) + if err != nil { + logrus.Error(xerrors.Errorf("[Price Thread ERROR] http request error: %w", err)) + continue + } + defer res.Body.Close() + body, _ := io.ReadAll(res.Body) + priceMap := make(map[string]map[string]float64) + err = json.Unmarshal(body, &priceMap) + if err != nil { + logrus.Error(xerrors.Errorf("[Price Thread ERROR] json unmarshal error: %w", err)) + continue + } + tokenSymPol := TokenSymbolMap[token] + price := priceMap[tokenSymPol]["usd"] + priceNetworkMap[token] = price + + } + globalPriceMap = priceNetworkMap + logrus.Infof("[Price Thread] Update price map: %v", priceNetworkMap) +} func GetTokenCostInUsd(tokenType global_const.TokenType, amount *big.Float) (*big.Float, error) { price, err := GetPriceUsd(tokenType) if err != nil { @@ -40,29 +91,14 @@ func GetTokenCostInUsd(tokenType global_const.TokenType, amount *big.Float) (*bi } func GetPriceUsd(tokenType global_const.TokenType) (float64, error) { - if global_const.IsStableToken(tokenType) { return 1, nil } - if tokenType == global_const.TokenTypeETH { - return 3500, nil - } - tokenUrl, ok := URLMap[tokenType] + price, ok := globalPriceMap[tokenType] if !ok { return 0, xerrors.Errorf("tokens type [%w] not found", tokenType) } - req, _ := http.NewRequest("GET", tokenUrl, nil) - //TODO remove APIKey - req.Header.Add("x-cg-demo-api-key", config.GetPriceOracleApiKey()) - - res, _ := http.DefaultClient.Do(req) - - defer res.Body.Close() - body, _ := io.ReadAll(res.Body) - bodystr := string(body) - strarr := strings.Split(bodystr, ":") - usdstr := strings.TrimRight(strarr[2], "}}") - return strconv.ParseFloat(usdstr, 64) + return price, nil } // GetToken Get The FromToken/ToToken Ratew @@ -76,26 +112,26 @@ func GetToken(fromToken global_const.TokenType, toToken global_const.TokenType) return formTokenPrice / toTokenPrice, nil } -func GetCoinMarketPrice() { - req, err := http.NewRequest("GET", "https://pro-api.coinmarketcap.com/v2/tools/price-conversion", nil) - if err != nil { - log.Print(err) - os.Exit(1) - } - q := url.Values{} - q.Add("amount", "2") - q.Add("symbol", "BTC") - q.Add("convert", "USD") - - req.Header.Set("Accepts", "application/json") - req.Header.Add("X-CMC_PRO_API_KEY", "a1441679-b8fd-49a0-aa47-51f88f7d3d52") - req.URL.RawQuery = q.Encode() - resp, err := httpClient.Do(req) - if err != nil { - fmt.Println("Error sending request to server") - os.Exit(1) - } - fmt.Println(resp.Status) - respBody, _ := ioutil.ReadAll(resp.Body) - fmt.Println(string(respBody)) -} +//func GetCoinMarketPrice() { +// req, err := http.NewRequest("GET", "https://pro-api.coinmarketcap.com/v2/tools/price-conversion", nil) +// if err != nil { +// log.Print(err) +// os.Exit(1) +// } +// q := url.Values{} +// q.Add("amount", "2") +// q.Add("symbol", "BTC") +// q.Add("convert", "USD") +// +// req.Header.Set("Accepts", "application/json") +// req.Header.Add("X-CMC_PRO_API_KEY", "a1441679-b8fd-49a0-aa47-51f88f7d3d52") +// req.URL.RawQuery = q.Encode() +// resp, err := httpClient.Do(req) +// if err != nil { +// fmt.Println("Error sending request to server") +// os.Exit(1) +// } +// fmt.Println(resp.Status) +// respBody, _ := ioutil.ReadAll(resp.Body) +// fmt.Println(string(respBody)) +//} diff --git a/common/price_compoent/price_util_test.go b/common/price_compoent/price_util_test.go index 9f104f77..7211d590 100644 --- a/common/price_compoent/price_util_test.go +++ b/common/price_compoent/price_util_test.go @@ -3,8 +3,6 @@ package price_compoent import ( "AAStarCommunity/EthPaymaster_BackService/common/global_const" "AAStarCommunity/EthPaymaster_BackService/config" - "fmt" - "strconv" "testing" ) @@ -43,11 +41,6 @@ func testGetPriceUsd(t *testing.T, tokenType global_const.TokenType) { t.Logf("price:%v", price) } -func TestDemo(t *testing.T) { - str := "0000000000000000000000000000000000000000000000000000000000000002" - fmt.Printf(strconv.Itoa(len(str))) -} - -func TestGetCoinMarketPrice(t *testing.T) { - GetCoinMarketPrice() +func TestGetCoinGeckoPrice(t *testing.T) { + GetConfigTokenPrice() } diff --git a/docs/docs.go b/docs/docs.go index 83e7d3ab..c385d59a 100644 --- a/docs/docs.go +++ b/docs/docs.go @@ -114,6 +114,22 @@ const docTemplate = `{ } } }, + "/api/v1/paymaster_sponsor/token_price": { + "get": { + "description": "Get Token Price", + "consumes": [ + "application/json" + ], + "tags": [ + "Sponsor" + ], + "responses": { + "200": { + "description": "OK" + } + } + } + }, "/api/v1/paymaster_sponsor/withdraw": { "post": { "description": "Withdraw Sponsor", diff --git a/docs/swagger.json b/docs/swagger.json index 35e5da73..7653e4d4 100644 --- a/docs/swagger.json +++ b/docs/swagger.json @@ -104,6 +104,22 @@ } } }, + "/api/v1/paymaster_sponsor/token_price": { + "get": { + "description": "Get Token Price", + "consumes": [ + "application/json" + ], + "tags": [ + "Sponsor" + ], + "responses": { + "200": { + "description": "OK" + } + } + } + }, "/api/v1/paymaster_sponsor/withdraw": { "post": { "description": "Withdraw Sponsor", diff --git a/docs/swagger.yaml b/docs/swagger.yaml index 50125224..924c104f 100644 --- a/docs/swagger.yaml +++ b/docs/swagger.yaml @@ -109,6 +109,16 @@ paths: description: OK tags: - DepositSponsor + /api/v1/paymaster_sponsor/token_price: + get: + consumes: + - application/json + description: Get Token Price + responses: + "200": + description: OK + tags: + - Sponsor /api/v1/paymaster_sponsor/withdraw: post: consumes: diff --git a/rpc_server/api/v1/sponsor.go b/rpc_server/api/v1/sponsor.go index a217bee2..c98c0d8b 100644 --- a/rpc_server/api/v1/sponsor.go +++ b/rpc_server/api/v1/sponsor.go @@ -192,6 +192,19 @@ func GetInfoByHash(txHash string, client *ethclient.Client) (*types.Transaction, return tx, nil } +// GetTokenPrice +// @Tags Sponsor +// @Description Get Token Price +// @Accept json +// @Product json +// @Router /api/v1/paymaster_sponsor/token_price [get] +// @Success 200 +func GetTokenPrice(ctx *gin.Context) { + response := model.GetResponse() + result := price_compoent.GetGlobalPriceMap() + response.WithDataSuccess(ctx, result) +} + // WithdrawSponsor // @Tags Sponsor // @Description Withdraw Sponsor diff --git a/rpc_server/routers/routers_map.go b/rpc_server/routers/routers_map.go index 92d397b5..c323ee04 100644 --- a/rpc_server/routers/routers_map.go +++ b/rpc_server/routers/routers_map.go @@ -14,6 +14,7 @@ func init() { PublicRouterMaps = append(PublicRouterMaps, RouterMap{string(Healthz), []RestfulMethod{GET, HEAD, OPTIONS}, api.Healthz}) PublicRouterMaps = append(PublicRouterMaps, RouterMap{string(DepositSponsor), []RestfulMethod{POST}, v1.DepositSponsor}) PublicRouterMaps = append(PublicRouterMaps, RouterMap{string(WithdrawSponsor), []RestfulMethod{POST}, v1.WithdrawSponsor}) + PublicRouterMaps = append(PublicRouterMaps, RouterMap{string(GetTokenPrice), []RestfulMethod{GET}, v1.GetTokenPrice}) } type Path string @@ -25,4 +26,5 @@ const ( DepositSponsor Path = "api/v1/paymaster_sponsor/deposit" WithdrawSponsor Path = "api/v1/paymaster_sponsor/withdraw" GetSponsorData Path = "api/v1/paymaster_sponsor/data" + GetTokenPrice Path = "api/v1/paymaster_sponsor/token_price" )