From 8ab8c279989114662d6dce4b5b998ad8fd88fc1a Mon Sep 17 00:00:00 2001 From: Steve Klebanoff Date: Mon, 29 Oct 2018 15:19:48 -0700 Subject: gas price estimator --- packages/instant/src/components/buy_button.tsx | 5 ++- .../instant/src/components/zero_ex_instant.tsx | 2 + packages/instant/src/util/gas_price_estimator.ts | 45 ++++++++++++++++++++++ 3 files changed, 50 insertions(+), 2 deletions(-) create mode 100644 packages/instant/src/util/gas_price_estimator.ts (limited to 'packages/instant') diff --git a/packages/instant/src/components/buy_button.tsx b/packages/instant/src/components/buy_button.tsx index e65e62e47..58575b1b3 100644 --- a/packages/instant/src/components/buy_button.tsx +++ b/packages/instant/src/components/buy_button.tsx @@ -7,6 +7,7 @@ import { ColorOption } from '../style/theme'; import { ZeroExInstantError } from '../types'; import { getBestAddress } from '../util/address'; import { balanceUtil } from '../util/balance'; +import { gasPriceEstimator } from '../util/gas_price_estimator'; import { util } from '../util/util'; import { web3Wrapper } from '../util/web3_wrapper'; @@ -56,9 +57,9 @@ export class BuyButton extends React.Component { } let txHash: string | undefined; + const gasPrice = await gasPriceEstimator.getFastAmountInWeiAsync(); try { - const gasPrice = DEFAULT_GAS_PRICE; - txHash = await assetBuyer.executeBuyQuoteAsync(buyQuote, { gasPrice, takerAddress }); + txHash = await assetBuyer.executeBuyQuoteAsync(buyQuote, { takerAddress, gasPrice }); } catch (e) { if (e instanceof Error) { if (e.message === AssetBuyerError.SignatureRequestDenied) { diff --git a/packages/instant/src/components/zero_ex_instant.tsx b/packages/instant/src/components/zero_ex_instant.tsx index 19a2d6b9b..6a5846963 100644 --- a/packages/instant/src/components/zero_ex_instant.tsx +++ b/packages/instant/src/components/zero_ex_instant.tsx @@ -13,6 +13,7 @@ import { AssetMetaData, Network } from '../types'; import { assetUtils } from '../util/asset'; import { BigNumberInput } from '../util/big_number_input'; import { errorFlasher } from '../util/error_flasher'; +import { gasPriceEstimator } from '../util/gas_price_estimator'; import { getProvider } from '../util/provider'; import { web3Wrapper } from '../util/web3_wrapper'; @@ -78,6 +79,7 @@ export class ZeroExInstant extends React.Component { public componentDidMount(): void { // tslint:disable-next-line:no-floating-promises asyncData.fetchAndDispatchToStore(this._store); + gasPriceEstimator.getFastAmountInWeiAsync(); // tslint:disable-next-line:no-floating-promises this._flashErrorIfWrongNetwork(); } diff --git a/packages/instant/src/util/gas_price_estimator.ts b/packages/instant/src/util/gas_price_estimator.ts new file mode 100644 index 000000000..bd81ea05f --- /dev/null +++ b/packages/instant/src/util/gas_price_estimator.ts @@ -0,0 +1,45 @@ +import { BigNumber } from '@0x/utils'; + +// TODO: merge development and move to constants +const ENDPOINT_URL = 'https://ethgasstation.info/json/ethgasAPI.json'; +const DEFAULT_GAS_PRICE_WEI = new BigNumber(20000000000); + +interface GasStationResult { + average: number; + fastestWait: number; + fastWait: number; + fast: number; + safeLowWait: number; + blockNum: number; + avgWait: number; + block_time: number; + speed: number; + fastest: number; + safeLow: number; +} + +const fetchFastAmountInWei = async () => { + const res = await fetch(ENDPOINT_URL); + const gasInfo = (await res.json()) as GasStationResult; + const gasPriceInGwei = new BigNumber(gasInfo.fast / 10); + return gasPriceInGwei.mul(1000000000); +}; + +export class GasPriceEstimator { + private _lastFetched?: BigNumber; + public async getFastAmountInWeiAsync(): Promise { + let fetchedAmount: BigNumber | undefined; + try { + fetchedAmount = await fetchFastAmountInWei(); + } catch { + fetchedAmount = undefined; + } + + if (fetchedAmount) { + this._lastFetched = fetchedAmount; + } + + return fetchedAmount || this._lastFetched || DEFAULT_GAS_PRICE_WEI; + } +} +export const gasPriceEstimator = new GasPriceEstimator(); -- cgit From 9610ada4467472318db0de17f794737ada42836b Mon Sep 17 00:00:00 2001 From: Steve Klebanoff Date: Mon, 29 Oct 2018 15:23:16 -0700 Subject: Use constant that exists now --- packages/instant/src/util/gas_price_estimator.ts | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) (limited to 'packages/instant') diff --git a/packages/instant/src/util/gas_price_estimator.ts b/packages/instant/src/util/gas_price_estimator.ts index bd81ea05f..9eccfe510 100644 --- a/packages/instant/src/util/gas_price_estimator.ts +++ b/packages/instant/src/util/gas_price_estimator.ts @@ -1,8 +1,6 @@ import { BigNumber } from '@0x/utils'; -// TODO: merge development and move to constants -const ENDPOINT_URL = 'https://ethgasstation.info/json/ethgasAPI.json'; -const DEFAULT_GAS_PRICE_WEI = new BigNumber(20000000000); +import { DEFAULT_GAS_PRICE } from '../constants'; interface GasStationResult { average: number; @@ -18,8 +16,9 @@ interface GasStationResult { safeLow: number; } +const endpointUrl = 'https://ethgasstation.info/json/ethgasAPI.json'; const fetchFastAmountInWei = async () => { - const res = await fetch(ENDPOINT_URL); + const res = await fetch(endpointUrl); const gasInfo = (await res.json()) as GasStationResult; const gasPriceInGwei = new BigNumber(gasInfo.fast / 10); return gasPriceInGwei.mul(1000000000); @@ -39,7 +38,7 @@ export class GasPriceEstimator { this._lastFetched = fetchedAmount; } - return fetchedAmount || this._lastFetched || DEFAULT_GAS_PRICE_WEI; + return fetchedAmount || this._lastFetched || DEFAULT_GAS_PRICE; } } export const gasPriceEstimator = new GasPriceEstimator(); -- cgit From cd419edf69ae13c6eb7eb1daadcfa73bd731e6f4 Mon Sep 17 00:00:00 2001 From: Steve Klebanoff Date: Mon, 29 Oct 2018 15:37:30 -0700 Subject: linting --- packages/instant/src/components/buy_button.tsx | 2 +- packages/instant/src/components/zero_ex_instant.tsx | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) (limited to 'packages/instant') diff --git a/packages/instant/src/components/buy_button.tsx b/packages/instant/src/components/buy_button.tsx index 58575b1b3..93bd8e635 100644 --- a/packages/instant/src/components/buy_button.tsx +++ b/packages/instant/src/components/buy_button.tsx @@ -2,7 +2,7 @@ import { AssetBuyer, AssetBuyerError, BuyQuote } from '@0x/asset-buyer'; import * as _ from 'lodash'; import * as React from 'react'; -import { DEFAULT_GAS_PRICE, WEB_3_WRAPPER_TRANSACTION_FAILED_ERROR_MSG_PREFIX } from '../constants'; +import { WEB_3_WRAPPER_TRANSACTION_FAILED_ERROR_MSG_PREFIX } from '../constants'; import { ColorOption } from '../style/theme'; import { ZeroExInstantError } from '../types'; import { getBestAddress } from '../util/address'; diff --git a/packages/instant/src/components/zero_ex_instant.tsx b/packages/instant/src/components/zero_ex_instant.tsx index 6a5846963..87069bb6f 100644 --- a/packages/instant/src/components/zero_ex_instant.tsx +++ b/packages/instant/src/components/zero_ex_instant.tsx @@ -79,6 +79,7 @@ export class ZeroExInstant extends React.Component { public componentDidMount(): void { // tslint:disable-next-line:no-floating-promises asyncData.fetchAndDispatchToStore(this._store); + // tslint:disable-next-line:no-floating-promises gasPriceEstimator.getFastAmountInWeiAsync(); // tslint:disable-next-line:no-floating-promises this._flashErrorIfWrongNetwork(); -- cgit From a49fc27042f9797f7a035e5471e572b148679456 Mon Sep 17 00:00:00 2001 From: Steve Klebanoff Date: Mon, 29 Oct 2018 16:49:13 -0700 Subject: Comment for warming up cache --- packages/instant/src/components/zero_ex_instant.tsx | 2 ++ 1 file changed, 2 insertions(+) (limited to 'packages/instant') diff --git a/packages/instant/src/components/zero_ex_instant.tsx b/packages/instant/src/components/zero_ex_instant.tsx index 87069bb6f..63c2c9072 100644 --- a/packages/instant/src/components/zero_ex_instant.tsx +++ b/packages/instant/src/components/zero_ex_instant.tsx @@ -80,6 +80,8 @@ export class ZeroExInstant extends React.Component { // tslint:disable-next-line:no-floating-promises asyncData.fetchAndDispatchToStore(this._store); // tslint:disable-next-line:no-floating-promises + // warm up the gas price estimator cache just in case we can't + // grab the gas price estimate when submitting the transaction gasPriceEstimator.getFastAmountInWeiAsync(); // tslint:disable-next-line:no-floating-promises this._flashErrorIfWrongNetwork(); -- cgit From 274e4b3bcd1633e8fe78a33528d63b7567355f9e Mon Sep 17 00:00:00 2001 From: Steve Klebanoff Date: Mon, 29 Oct 2018 16:53:18 -0700 Subject: Introduce constants for eth gas station and coinbase --- packages/instant/src/constants.ts | 2 ++ packages/instant/src/util/coinbase_api.ts | 5 +++-- packages/instant/src/util/gas_price_estimator.ts | 9 ++++----- 3 files changed, 9 insertions(+), 7 deletions(-) (limited to 'packages/instant') diff --git a/packages/instant/src/constants.ts b/packages/instant/src/constants.ts index 47cb2eaeb..424f35ecb 100644 --- a/packages/instant/src/constants.ts +++ b/packages/instant/src/constants.ts @@ -5,3 +5,5 @@ export const DEFAULT_ZERO_EX_CONTAINER_SELECTOR = '#zeroExInstantContainer'; export const WEB_3_WRAPPER_TRANSACTION_FAILED_ERROR_MSG_PREFIX = 'Transaction failed'; export const GWEI_IN_WEI = new BigNumber(1000000000); export const DEFAULT_GAS_PRICE = GWEI_IN_WEI.mul(6); +export const ETH_GAS_STATION_API_BASE_URL = 'https://ethgasstation.info'; +export const COINBASE_API_BASE_URL = 'https://api.coinbase.com/v2'; diff --git a/packages/instant/src/util/coinbase_api.ts b/packages/instant/src/util/coinbase_api.ts index 080421f98..32401e423 100644 --- a/packages/instant/src/util/coinbase_api.ts +++ b/packages/instant/src/util/coinbase_api.ts @@ -1,9 +1,10 @@ import { BigNumber } from '@0x/utils'; -const baseEndpoint = 'https://api.coinbase.com/v2'; +import { COINBASE_API_BASE_URL } from '../constants'; + export const coinbaseApi = { getEthUsdPrice: async (): Promise => { - const res = await fetch(`${baseEndpoint}/prices/ETH-USD/buy`); + const res = await fetch(`${COINBASE_API_BASE_URL}/prices/ETH-USD/buy`); const resJson = await res.json(); return new BigNumber(resJson.data.amount); }, diff --git a/packages/instant/src/util/gas_price_estimator.ts b/packages/instant/src/util/gas_price_estimator.ts index 9eccfe510..818bf6f92 100644 --- a/packages/instant/src/util/gas_price_estimator.ts +++ b/packages/instant/src/util/gas_price_estimator.ts @@ -1,8 +1,8 @@ import { BigNumber } from '@0x/utils'; -import { DEFAULT_GAS_PRICE } from '../constants'; +import { DEFAULT_GAS_PRICE, ETH_GAS_STATION_API_BASE_URL } from '../constants'; -interface GasStationResult { +interface EthGasStationResult { average: number; fastestWait: number; fastWait: number; @@ -16,10 +16,9 @@ interface GasStationResult { safeLow: number; } -const endpointUrl = 'https://ethgasstation.info/json/ethgasAPI.json'; const fetchFastAmountInWei = async () => { - const res = await fetch(endpointUrl); - const gasInfo = (await res.json()) as GasStationResult; + const res = await fetch(`${ETH_GAS_STATION_API_BASE_URL}/json/ethgasAPI.json`); + const gasInfo = (await res.json()) as EthGasStationResult; const gasPriceInGwei = new BigNumber(gasInfo.fast / 10); return gasPriceInGwei.mul(1000000000); }; -- cgit From 30454fe46746b8c1caf47cb35f39b46d0749a224 Mon Sep 17 00:00:00 2001 From: Steve Klebanoff Date: Mon, 29 Oct 2018 17:11:02 -0700 Subject: async suffix and use polyfill fetch util --- packages/instant/src/util/gas_price_estimator.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'packages/instant') diff --git a/packages/instant/src/util/gas_price_estimator.ts b/packages/instant/src/util/gas_price_estimator.ts index 818bf6f92..33eeb932d 100644 --- a/packages/instant/src/util/gas_price_estimator.ts +++ b/packages/instant/src/util/gas_price_estimator.ts @@ -1,4 +1,4 @@ -import { BigNumber } from '@0x/utils'; +import { BigNumber, fetchAsync } from '@0x/utils'; import { DEFAULT_GAS_PRICE, ETH_GAS_STATION_API_BASE_URL } from '../constants'; @@ -16,8 +16,8 @@ interface EthGasStationResult { safeLow: number; } -const fetchFastAmountInWei = async () => { - const res = await fetch(`${ETH_GAS_STATION_API_BASE_URL}/json/ethgasAPI.json`); +const fetchFastAmountInWeiAsync = async () => { + const res = await fetchAsync(`${ETH_GAS_STATION_API_BASE_URL}/json/ethgasAPI.json`); const gasInfo = (await res.json()) as EthGasStationResult; const gasPriceInGwei = new BigNumber(gasInfo.fast / 10); return gasPriceInGwei.mul(1000000000); @@ -28,7 +28,7 @@ export class GasPriceEstimator { public async getFastAmountInWeiAsync(): Promise { let fetchedAmount: BigNumber | undefined; try { - fetchedAmount = await fetchFastAmountInWei(); + fetchedAmount = await fetchFastAmountInWeiAsync(); } catch { fetchedAmount = undefined; } -- cgit From 2ad2644b6bcb3c1f4da5891d79856af46e808eab Mon Sep 17 00:00:00 2001 From: Steve Klebanoff Date: Mon, 29 Oct 2018 17:11:15 -0700 Subject: Use polyfilled fetch from utils --- packages/instant/src/util/coinbase_api.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'packages/instant') diff --git a/packages/instant/src/util/coinbase_api.ts b/packages/instant/src/util/coinbase_api.ts index 32401e423..faac8d82d 100644 --- a/packages/instant/src/util/coinbase_api.ts +++ b/packages/instant/src/util/coinbase_api.ts @@ -1,10 +1,10 @@ -import { BigNumber } from '@0x/utils'; +import { BigNumber, fetchAsync } from '@0x/utils'; import { COINBASE_API_BASE_URL } from '../constants'; export const coinbaseApi = { getEthUsdPrice: async (): Promise => { - const res = await fetch(`${COINBASE_API_BASE_URL}/prices/ETH-USD/buy`); + const res = await fetchAsync(`${COINBASE_API_BASE_URL}/prices/ETH-USD/buy`); const resJson = await res.json(); return new BigNumber(resJson.data.amount); }, -- cgit From 09ee7d84f70418e128a445bf3a11b813ac1c7d2e Mon Sep 17 00:00:00 2001 From: Steve Klebanoff Date: Mon, 29 Oct 2018 17:17:04 -0700 Subject: Add comment and use constant --- packages/instant/src/util/gas_price_estimator.ts | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'packages/instant') diff --git a/packages/instant/src/util/gas_price_estimator.ts b/packages/instant/src/util/gas_price_estimator.ts index 33eeb932d..336c4a3fa 100644 --- a/packages/instant/src/util/gas_price_estimator.ts +++ b/packages/instant/src/util/gas_price_estimator.ts @@ -1,6 +1,6 @@ import { BigNumber, fetchAsync } from '@0x/utils'; -import { DEFAULT_GAS_PRICE, ETH_GAS_STATION_API_BASE_URL } from '../constants'; +import { DEFAULT_GAS_PRICE, ETH_GAS_STATION_API_BASE_URL, GWEI_IN_WEI } from '../constants'; interface EthGasStationResult { average: number; @@ -19,8 +19,9 @@ interface EthGasStationResult { const fetchFastAmountInWeiAsync = async () => { const res = await fetchAsync(`${ETH_GAS_STATION_API_BASE_URL}/json/ethgasAPI.json`); const gasInfo = (await res.json()) as EthGasStationResult; + // Eth Gas Station result is gwei * 10 const gasPriceInGwei = new BigNumber(gasInfo.fast / 10); - return gasPriceInGwei.mul(1000000000); + return gasPriceInGwei.mul(GWEI_IN_WEI); }; export class GasPriceEstimator { -- cgit From 5901ee7e963a4413f49fffdd9477085229e7623f Mon Sep 17 00:00:00 2001 From: Steve Klebanoff Date: Mon, 29 Oct 2018 17:18:56 -0700 Subject: Move tslint disable line --- packages/instant/src/components/zero_ex_instant.tsx | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'packages/instant') diff --git a/packages/instant/src/components/zero_ex_instant.tsx b/packages/instant/src/components/zero_ex_instant.tsx index 63c2c9072..d54dfc153 100644 --- a/packages/instant/src/components/zero_ex_instant.tsx +++ b/packages/instant/src/components/zero_ex_instant.tsx @@ -79,10 +79,12 @@ export class ZeroExInstant extends React.Component { public componentDidMount(): void { // tslint:disable-next-line:no-floating-promises asyncData.fetchAndDispatchToStore(this._store); - // tslint:disable-next-line:no-floating-promises + // warm up the gas price estimator cache just in case we can't // grab the gas price estimate when submitting the transaction + // tslint:disable-next-line:no-floating-promises gasPriceEstimator.getFastAmountInWeiAsync(); + // tslint:disable-next-line:no-floating-promises this._flashErrorIfWrongNetwork(); } -- cgit