From e1464ee599af734d3ee19ef9a4b7aed3b2bfb50d Mon Sep 17 00:00:00 2001 From: zhl Date: Wed, 24 May 2023 17:42:29 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E6=9F=A5=E8=AF=A2gas?= =?UTF-8?q?=E4=BB=B7=E6=A0=BC=E7=9A=84=E6=96=B9=E6=B3=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/chain/BlockChain.ts | 11 +++--- src/chain/allchain.ts | 3 +- src/controllers/token.controllers.ts | 27 ++++++++++++- src/service/chain.service.ts | 6 --- src/service/price.service.ts | 58 ++++++++++++++++------------ 5 files changed, 65 insertions(+), 40 deletions(-) diff --git a/src/chain/BlockChain.ts b/src/chain/BlockChain.ts index ec14a17..e2a1af9 100644 --- a/src/chain/BlockChain.ts +++ b/src/chain/BlockChain.ts @@ -13,11 +13,11 @@ import { AllChains } from './allchain' import assert from 'assert' import { IPriceData } from 'structs/PriceData' import { IChainData } from 'structs/ChainData' -import { queryEthPrice } from 'service/chain.service' +import { PriceSvr } from 'service/price.service' @singleton export class BlockChain { - private web3: Web3 + public web3: Web3 instanceCacheMap: Map private accountMaster: AddedAccount private currentChain: IChainData @@ -112,12 +112,11 @@ export class BlockChain { } public async generateGasShow(gas: any): Promise { - let price = await this.web3.eth.getGasPrice() + let price = await new PriceSvr().refreshGasPrice() let ehtBN = safeNumberToBN(price).mul(safeNumberToBN(gas)) - let leagelSymbol = 'USD' let ethSymbol = this.currentChain.type !== 'Testnet' ? this.currentChain.symbol : 'ETH' - let leagelPriceData = await queryEthPrice(ethSymbol, leagelSymbol) - let leagelPriceBN = safeNumberToBN(leagelPriceData[leagelSymbol] * 100) + let leagelPrice = await new PriceSvr().queryEthPrice(ethSymbol) + let leagelPriceBN = safeNumberToBN(leagelPrice) let leagel = fromTokenMinimalUnit(ehtBN.mul(leagelPriceBN), 20) let eth = fromTokenMinimalUnit(ehtBN, 18) return { gas, price, eth, leagel } diff --git a/src/chain/allchain.ts b/src/chain/allchain.ts index bdea6da..d4d3cee 100644 --- a/src/chain/allchain.ts +++ b/src/chain/allchain.ts @@ -210,7 +210,7 @@ export const AllChains = [ { name: 'Arbitrum One', type: 'Mainnet', - rpc: 'https://rpc.ankr.com/arbitrum', + rpc: 'https://endpoints.omniatech.io/v1/arbitrum/one/public|https://rpc.ankr.com/arbitrum', id: 42161, symbol: 'ETH', explorerurl: 'https://arbiscan.io/', @@ -261,7 +261,6 @@ export const AllChains = [ rpc: 'https://goerli-rollup.arbitrum.io/rpc|https://endpoints.omniatech.io/v1/arbitrum/goerli/public', id: 421613, symbol: 'AGOR', - symbol2: 'ETH', explorerurl: 'https://goerli-rollup-explorer.arbitrum.io', }, { diff --git a/src/controllers/token.controllers.ts b/src/controllers/token.controllers.ts index e153253..a5df3e5 100644 --- a/src/controllers/token.controllers.ts +++ b/src/controllers/token.controllers.ts @@ -1,3 +1,4 @@ +import { BlockChain } from 'chain/BlockChain' import BaseController from 'common/base.controller' import { role, router } from 'decorators/router' import { PriceSvr } from 'service/price.service' @@ -5,9 +6,31 @@ import { PriceSvr } from 'service/price.service' class TokenController extends BaseController { @role('anon') @router('post /chain/estimate_transfer_gas') - async calcGasPrice(req, res) { + async calcTransPrice(req, res) { const { address } = req.params - let data = await new PriceSvr().getTokenTransferPrice(address) + const bc = new BlockChain() + const account = bc.currentAccount + let gas = await bc.erc20Reactor.transfer({ + address: address + '', + to: account, + amount: 0, + estimate: true, + }) + let data = bc.generateGasShow(gas) + return data + } + + @role('anon') + @router('post /chain/estimate_gas') + async calcGasPrice(req, res) { + let { gas } = req.params + if (!gas) + gas = await new BlockChain().web3.eth.estimateGas({ + from: '0x84f165521886642D24c55FACc886ab5986AD2d8b', + to: '0x84f165521886642D24c55FACc886ab5986AD2d8b', + value: '0', + }) + let data = new BlockChain().generateGasShow(gas) return data } } diff --git a/src/service/chain.service.ts b/src/service/chain.service.ts index e61800c..a9ce27b 100644 --- a/src/service/chain.service.ts +++ b/src/service/chain.service.ts @@ -1,4 +1,3 @@ -import axios from 'axios' import logger from 'logger/logger' import { ChainTask } from 'models/ChainTask' import { RequestTask } from 'models/RequestTask' @@ -16,8 +15,3 @@ export async function restartAllUnFinishedTask() { } } } - -export async function queryEthPrice(eth: string, usd: string = 'USD') { - const url = `https://min-api.cryptocompare.com/data/price?fsym=${eth}&tsyms=${usd}` - return axios.get(url).then(res => res.data) -} diff --git a/src/service/price.service.ts b/src/service/price.service.ts index 965a4ce..bd3eeb5 100644 --- a/src/service/price.service.ts +++ b/src/service/price.service.ts @@ -1,44 +1,54 @@ import { BlockChain } from 'chain/BlockChain' import { singleton } from 'decorators/singleton' -import { IPriceData } from 'structs/PriceData' import * as schedule from 'node-schedule' import logger from 'logger/logger' +import axios from 'axios' +export interface IPriceCache { + price: string + expired: number +} @singleton export class PriceSvr { - private priceMap: Map = new Map() + private priceMap: Map = new Map() - public async getTokenTransferPrice(token: string, refresh: boolean = false) { - logger.debug(`get price for ${token}, refresh: ${refresh}`) - const key = `token_transfer_price|${token}` + public async refreshGasPrice(refresh: boolean = false) { + const key = `gasprice` let data = this.priceMap.get(key) if (!data || data.expired < Date.now() || refresh) { - logger.debug(`need update price for ${token}`) - let account = new BlockChain().currentAccount - try { - let gas = await new BlockChain().erc20Reactor.transfer({ - address: token, - to: account, - amount: 0, - estimate: true, - }) - let data = await new BlockChain().generateGasShow(gas) - data = { ...data, ...{ expired: Date.now() + 1000 * 60 } } - this.priceMap.set(key, data) - } catch (e) { - logger.log(e) - } + let price = await new BlockChain().web3.eth.getGasPrice() + this.priceMap.set(key, { price, expired: Date.now() + 1000 * 60 }) } - return this.priceMap.get(key) + return this.priceMap.get(key).price } + + public async queryEthPrice(eth: string, refresh: boolean = false) { + const usd = 'USD' + const key = `crypto_usd|${eth}` + let data = this.priceMap.get(key) + if (!data || data.expired < Date.now() || refresh) { + const url = `https://min-api.cryptocompare.com/data/price?fsym=${eth}&tsyms=${usd}` + let priceData = await axios.get(url).then(res => res.data) + let price = priceData[usd] * 100 + '' + this.priceMap.set(key, { price, expired: Date.now() + 1000 * 60 }) + } + return this.priceMap.get(key).price + } + private async refreshAll() { for (let key of this.priceMap.keys()) { let [type, token] = key.split('|') - if (type == 'token_transfer_price') { + if (type == 'gasprice') { try { - this.getTokenTransferPrice(token, true) + await this.refreshGasPrice(true) } catch (e) { - logger.info(`error refresh price of token: ${token}`, e.message || e) + logger.info(`error refresh gas price `, e.message || e) + } + } else if (type == 'crypto_usd') { + try { + await this.queryEthPrice(token, true) + } catch (e) { + logger.info(`error refresh crypto price: ${token}`, e.message || e) } } }