diff options
-rw-r--r-- | packages/instant/public/index.html | 58 | ||||
-rw-r--r-- | packages/instant/src/components/buy_button.tsx | 5 | ||||
-rw-r--r-- | packages/instant/src/components/zero_ex_instant.tsx | 7 | ||||
-rw-r--r-- | packages/instant/src/constants.ts | 2 | ||||
-rw-r--r-- | packages/instant/src/util/coinbase_api.ts | 7 | ||||
-rw-r--r-- | packages/instant/src/util/gas_price_estimator.ts | 44 |
6 files changed, 90 insertions, 33 deletions
diff --git a/packages/instant/public/index.html b/packages/instant/public/index.html index dc172e6e4..62532dad9 100644 --- a/packages/instant/public/index.html +++ b/packages/instant/public/index.html @@ -35,37 +35,39 @@ DECIMAL_PLACES: 78, }); const providedOrders = [ + // Order selling REP { - "senderAddress": "0x0000000000000000000000000000000000000000", - "makerAddress": "0x34a745008a643eebc58920eaa29fb1165b4a288e", - "takerAddress": "0x0000000000000000000000000000000000000000", - "makerFee": new BigNumber("0"), - "takerFee": new BigNumber("0"), - "makerAssetAmount": new BigNumber("400000000000000000000"), - "takerAssetAmount": new BigNumber("40000000000000000000"), - "makerAssetData": "0xf47261b00000000000000000000000008cb3971b8eb709c14616bd556ff6683019e90d9c", - "takerAssetData": "0xf47261b0000000000000000000000000d0a1e359811322d97991e03f863a0c30c2cf029c", - "expirationTimeSeconds": new BigNumber("1543046400"), - "feeRecipientAddress": "0x0000000000000000000000000000000000000000", - "salt": new BigNumber("47929252863126413473766089649682650973189811771354566206928245255479607883031"), - "signature": "0x1c0bf8ba709ceb5b32e6b0b5a8bb7f07e9d19aba88d8530715f8a298d12188e3862fcc0a30ddfad4062b30459f2859323c064052f12cc687466c457934b9419a1b03", - "exchangeAddress": "0x35dd2932454449b14cee11a94d3674a936d5d7b2" + senderAddress: '0x0000000000000000000000000000000000000000', + makerAddress: '0x34a745008a643eebc58920eaa29fb1165b4a288e', + takerAddress: '0x0000000000000000000000000000000000000000', + makerFee: new BigNumber('0'), + takerFee: new BigNumber('0'), + makerAssetAmount: new BigNumber('400000000000000000000'), + takerAssetAmount: new BigNumber('40000000000000000000'), + makerAssetData: '0xf47261b00000000000000000000000008cb3971b8eb709c14616bd556ff6683019e90d9c', + takerAssetData: '0xf47261b0000000000000000000000000d0a1e359811322d97991e03f863a0c30c2cf029c', + expirationTimeSeconds: new BigNumber('1543046400'), + feeRecipientAddress: '0x0000000000000000000000000000000000000000', + salt: new BigNumber('47929252863126413473766089649682650973189811771354566206928245255479607883031'), + signature: '0x1c0bf8ba709ceb5b32e6b0b5a8bb7f07e9d19aba88d8530715f8a298d12188e3862fcc0a30ddfad4062b30459f2859323c064052f12cc687466c457934b9419a1b03', + exchangeAddress: '0x35dd2932454449b14cee11a94d3674a936d5d7b2' }, + // Order selling ZRX { - "senderAddress": "0x0000000000000000000000000000000000000000", - "makerAddress": "0x34a745008a643eebc58920eaa29fb1165b4a288e", - "takerAddress": "0x0000000000000000000000000000000000000000", - "makerFee": new BigNumber("0"), - "takerFee": new BigNumber("0"), - "makerAssetAmount": new BigNumber("300000000000000000000"), - "takerAssetAmount": new BigNumber("31000000000000000000"), - "makerAssetData": "0xf47261b00000000000000000000000002002d3812f58e35f0ea1ffbf80a75a38c32175fa", - "takerAssetData": "0xf47261b0000000000000000000000000d0a1e359811322d97991e03f863a0c30c2cf029c", - "expirationTimeSeconds": new BigNumber("2524636800"), - "feeRecipientAddress": "0x0000000000000000000000000000000000000000", - "salt": new BigNumber("64592004666704945574675477805199411288137454783320798602050822322450089238268"), - "signature": "0x1c13cacddca8d7d8248e91f412377e68f8f1f9891a59a6c1b2eea9f7b33558c30c4fb86a448e08ab7def40a28fb3a3062dcb33bb3c45302447fce5c4288b7c7f5b03", - "exchangeAddress": "0x35dd2932454449b14cee11a94d3674a936d5d7b2" + senderAddress: '0x0000000000000000000000000000000000000000', + makerAddress: '0x34a745008a643eebc58920eaa29fb1165b4a288e', + takerAddress: '0x0000000000000000000000000000000000000000', + makerFee: new BigNumber('0'), + takerFee: new BigNumber('0'), + makerAssetAmount: new BigNumber('300000000000000000000'), + takerAssetAmount: new BigNumber('31000000000000000000'), + makerAssetData: '0xf47261b00000000000000000000000002002d3812f58e35f0ea1ffbf80a75a38c32175fa', + takerAssetData: '0xf47261b0000000000000000000000000d0a1e359811322d97991e03f863a0c30c2cf029c', + expirationTimeSeconds: new BigNumber('2524636800'), + feeRecipientAddress: '0x0000000000000000000000000000000000000000', + salt: new BigNumber('64592004666704945574675477805199411288137454783320798602050822322450089238268'), + signature: '0x1c13cacddca8d7d8248e91f412377e68f8f1f9891a59a6c1b2eea9f7b33558c30c4fb86a448e08ab7def40a28fb3a3062dcb33bb3c45302447fce5c4288b7c7f5b03', + exchangeAddress: '0x35dd2932454449b14cee11a94d3674a936d5d7b2' } ]; const queryParams = new Uri(window.location.search); 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<BuyButtonProps> { } 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..d54dfc153 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,12 @@ export class ZeroExInstant extends React.Component<ZeroExInstantProps> { public componentDidMount(): void { // tslint:disable-next-line:no-floating-promises asyncData.fetchAndDispatchToStore(this._store); + + // 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(); } 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..faac8d82d 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'; +import { BigNumber, fetchAsync } from '@0x/utils'; + +import { COINBASE_API_BASE_URL } from '../constants'; -const baseEndpoint = 'https://api.coinbase.com/v2'; export const coinbaseApi = { getEthUsdPrice: async (): Promise<BigNumber> => { - const res = await fetch(`${baseEndpoint}/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); }, 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..336c4a3fa --- /dev/null +++ b/packages/instant/src/util/gas_price_estimator.ts @@ -0,0 +1,44 @@ +import { BigNumber, fetchAsync } from '@0x/utils'; + +import { DEFAULT_GAS_PRICE, ETH_GAS_STATION_API_BASE_URL, GWEI_IN_WEI } from '../constants'; + +interface EthGasStationResult { + average: number; + fastestWait: number; + fastWait: number; + fast: number; + safeLowWait: number; + blockNum: number; + avgWait: number; + block_time: number; + speed: number; + fastest: number; + safeLow: number; +} + +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(GWEI_IN_WEI); +}; + +export class GasPriceEstimator { + private _lastFetched?: BigNumber; + public async getFastAmountInWeiAsync(): Promise<BigNumber> { + let fetchedAmount: BigNumber | undefined; + try { + fetchedAmount = await fetchFastAmountInWeiAsync(); + } catch { + fetchedAmount = undefined; + } + + if (fetchedAmount) { + this._lastFetched = fetchedAmount; + } + + return fetchedAmount || this._lastFetched || DEFAULT_GAS_PRICE; + } +} +export const gasPriceEstimator = new GasPriceEstimator(); |