on master help sign in
Merge pull request #222 from urbit/mino-gas-station

For mainnet, get suggested gas price from ethgasstation.info

commitd04c2c1e9fc84c3f51bbeca224c248685a1648d5 authorFang <Fang-@users.noreply.github.com> dateMon 5 Aug 2019, 18:09 (7 years ago) parent87a9d762ccee1f
6 files changed+71−18
src/lib/reticket.js+6−3 src/lib/useEthereumTransaction.js+13−6 src/lib/useSuggestedGasPrice.js+40 src/views/Activate/PassportTransfer.js+3−1 src/views/Admin/Reticket/ReticketExecute.js+2−1 src/views/Invite/InviteEmail.js+7−7
src/lib/reticket.js+6−3
@@ -10,7 +10,8 @@ import {
1010} from './keys';
1111import { addHexPrefix } from './wallet';
1212import { sendAndAwaitAll } from './txn';
13−import { GAS_LIMITS, DEFAULT_GAS_PRICE_GWEI } from './constants';
13+import { getSuggestedGasPrice } from './useSuggestedGasPrice';
14+import { GAS_LIMITS } from './constants';
1415import { toWei } from 'web3-utils';
1516
1617// the initial network key revision is always 1
@@ -31,6 +32,7 @@ export async function reticketPointBetweenWallets({
3132 point,
3233 web3,
3334 contracts,
35+ networkType,
3436 onUpdate,
3537 transferEth = false,
3638 nextRevision = INITIAL_NETWORK_KEY_REVISION,
@@ -140,12 +142,14 @@ export async function reticketPointBetweenWallets({
140142
141143 progress(TRANSACTION_PROGRESS.SIGNING);
142144
145+ const suggestedGasPrice = await getSuggestedGasPrice(networkType);
146+ const gasPrice = parseInt(toWei(suggestedGasPrice.toFixed(), 'gwei'), 10);
143147 let totalCost = 0;
144148 let inviteNonce = await web3.eth.getTransactionCount(fromWallet.address);
145149 txs = txs.map(tx => {
146150 tx.from = fromWallet.address;
147151 tx.nonce = inviteNonce++;
148− tx.gasPrice = parseInt(toWei(DEFAULT_GAS_PRICE_GWEI.toFixed(), 'gwei'), 10);
152+ tx.gasPrice = gasPrice;
149153 totalCost = totalCost + tx.gasPrice * tx.gas;
150154 return tx;
151155 });
@@ -191,7 +195,6 @@ export async function reticketPointBetweenWallets({
191195
192196 // if non-trivial eth left in invite wallet, transfer to new ownership
193197 let balance = await web3.eth.getBalance(fromWallet.address);
194− const gasPrice = parseInt(toWei(DEFAULT_GAS_PRICE_GWEI.toFixed(), 'gwei'));
195198 const gasLimit = GAS_LIMITS.SEND_ETH;
196199 const sendEthCost = gasPrice * gasLimit;
197200 if (transferEth && balance > sendEthCost) {
src/lib/useEthereumTransaction.js+13−6
@@ -5,6 +5,7 @@ import { fromWei, toWei } from 'web3-utils';
55import { useNetwork } from 'store/network';
66import { useWallet } from 'store/wallet';
77import { usePointCursor } from 'store/pointCursor';
8+import { useSuggestedGasPrice } from 'lib/useSuggestedGasPrice';
89
910import { GAS_LIMITS } from './constants';
1011import {
@@ -60,6 +61,7 @@ export default function useEthereumTransaction(
6061 const [nonce, setNonce] = useState();
6162 const [gasPrice, setGasPrice] = useState(initialGasPrice); // gwei
6263 const [suggestedGasPrice, setSuggestedGasPrice] = useState(gasPrice); // gwei
64+ const { gasPrice: estimatedGasPrice } = useSuggestedGasPrice();
6365 const [gasLimit] = useState(initialGasLimit);
6466 const [unsignedTransaction, setUnsignedTransaction] = useState();
6567 const [signedTransaction, setSignedTransaction] = useState();
@@ -188,6 +190,15 @@ export default function useEthereumTransaction(
188190 suggestedGasPrice,
189191 ]);
190192
193+ useEffect(() => {
194+ const gasPrice = parseInt(
195+ fromWei(estimatedGasPrice.toString(), 'gwei'),
196+ 10
197+ );
198+ setSuggestedGasPrice(gasPrice);
199+ setGasPrice(gasPrice);
200+ }, [estimatedGasPrice]);
201+
191202 useEffect(() => {
192203 // if nonce or chainId is undefined, re-fetch on-chain info
193204 if (!(nonce === undefined || chainId === undefined)) {
@@ -197,22 +208,18 @@ export default function useEthereumTransaction(
197208 (async () => {
198209 try {
199210 setError(undefined);
200− const [nonce, chainId, estimatedGasPrice] = await Promise.all([
211+ const [nonce, chainId] = await Promise.all([
201212 _web3.eth.getTransactionCount(_wallet.address),
202213 _web3.eth.net.getId(),
203− _web3.eth.getGasPrice(),
204214 ]);
205215
206216 setNonce(nonce);
207217 setChainId(chainId);
208− const gasPrice = parseInt(fromWei(estimatedGasPrice, 'gwei'), 10);
209− setSuggestedGasPrice(gasPrice);
210− setGasPrice(gasPrice);
211218 } catch (error) {
212219 setError(error);
213220 }
214221 })();
215− }, [_wallet, _web3, setError, nonce, chainId]);
222+ }, [_wallet, _web3, setError, nonce, chainId, networkType]);
216223
217224 useEffect(() => {
218225 let cancelled = false;
src/lib/useSuggestedGasPrice.jsnew file+40
@@ -0,0 +1,40 @@
1+import { useState, useEffect } from 'react';
2+import { NETWORK_TYPES } from './network';
3+import { DEFAULT_GAS_PRICE_GWEI } from './constants';
4+
5+async function getSuggestedGasPrice(networkType) {
6+ switch (networkType) {
7+ case NETWORK_TYPES.ROPSTEN:
8+ return 10;
9+ case NETWORK_TYPES.OFFLINE:
10+ return DEFAULT_GAS_PRICE_GWEI;
11+ default:
12+ try {
13+ const response = await fetch(
14+ 'https://ethgasstation.info/json/ethgasAPI.json',
15+ {
16+ method: 'GET',
17+ cache: 'no-cache',
18+ }
19+ );
20+ const json = await response.json();
21+ return Math.min(json.fast / 10, 20); // to gwei
22+ } catch (e) {
23+ return DEFAULT_GAS_PRICE_GWEI;
24+ }
25+ }
26+}
27+
28+function useSuggestedGasPrice(networkType) {
29+ const [gasPrice, _setGasPrice] = useState(DEFAULT_GAS_PRICE_GWEI);
30+
31+ useEffect(() => {
32+ (async () => {
33+ _setGasPrice(await getSuggestedGasPrice(networkType));
34+ })();
35+ }, [networkType]);
36+
37+ return { gasPrice };
38+}
39+
40+export { getSuggestedGasPrice, useSuggestedGasPrice };
src/views/Activate/PassportTransfer.js+3−1
@@ -45,7 +45,7 @@ export default function PassportTransfer({ className, resetActivateRouter }) {
4545 const { replaceWith, names } = useHistory();
4646 const { setUrbitWallet } = useWallet();
4747 const { setPointCursor } = usePointCursor();
48− const { web3, contracts } = useNetwork();
48+ const { web3, contracts, networkType } = useNetwork();
4949 const {
5050 derivedWallet,
5151 derivedPoint,
@@ -112,6 +112,7 @@ export default function PassportTransfer({ className, resetActivateRouter }) {
112112 point: _point,
113113 web3: _web3,
114114 contracts: _contracts,
115+ networkType,
115116 onUpdate: handleUpdate,
116117 transferEth: true,
117118 });
@@ -133,6 +134,7 @@ export default function PassportTransfer({ className, resetActivateRouter }) {
133134 derivedPoint,
134135 web3,
135136 contracts,
137+ networkType,
136138 setUrbitWallet,
137139 setPointCursor,
138140 handleUpdate,
src/views/Admin/Reticket/ReticketExecute.js+2−1
@@ -42,7 +42,7 @@ const labelForProgress = progress => {
4242
4343export default function ReticketExecute({ newWallet, setNewWallet }) {
4444 const { popTo, names, reset } = useHistory();
45− const { web3, contracts } = useNetwork();
45+ const { web3, contracts, networkType } = useNetwork();
4646 const { wallet, setWalletType, resetWallet, setUrbitWallet } = useWallet();
4747 const { pointCursor } = usePointCursor();
4848 const { getDetails } = usePointCache();
@@ -65,6 +65,7 @@ export default function ReticketExecute({ newWallet, setNewWallet }) {
6565 point: point,
6666 web3: need.web3(web3),
6767 contracts: need.contracts(contracts),
68+ networkType,
6869 onUpdate: handleUpdate,
6970 nextRevision: networkRevision + 1,
7071 });
src/views/Invite/InviteEmail.js+7−7
@@ -29,9 +29,10 @@ import {
2929 hexify,
3030} from 'lib/txn';
3131import * as tank from 'lib/tank';
32+import { useSuggestedGasPrice } from 'lib/useSuggestedGasPrice';
3233import useArray from 'lib/useArray';
3334import { buildEmailInputConfig } from 'lib/useInputs';
34−import { MIN_PLANET, GAS_LIMITS, DEFAULT_GAS_PRICE_GWEI } from 'lib/constants';
35+import { MIN_PLANET, GAS_LIMITS } from 'lib/constants';
3536import * as need from 'lib/need';
3637import * as wg from 'lib/walletgen';
3738import useSetState from 'lib/useSetState';
@@ -42,10 +43,6 @@ import LoadableButton from 'components/LoadableButton';
4243import Highlighted from 'components/Highlighted';
4344
4445const GAS_LIMIT = GAS_LIMITS.GIFT_PLANET;
45−const INVITE_COST = toWei(
46− (DEFAULT_GAS_PRICE_GWEI * GAS_LIMIT).toString(),
47− 'gwei'
48−);
4946const HAS_RECEIVED_TEXT = 'This email has already received an invite.';
5047
5148const STATUS = {
@@ -100,6 +97,7 @@ export default function InviteEmail() {
10097 const { pointCursor } = usePointCursor();
10198 const point = need.point(pointCursor);
10299 const { getHasReceived, syncHasReceivedForEmail, sendMail } = useMailer();
100+ const { gasPrice } = useSuggestedGasPrice(networkType);
103101
104102 const { availableInvites } = getInvites(point);
105103 const maxInvitesToSend = availableInvites.matchWith({
@@ -257,7 +255,7 @@ export default function InviteEmail() {
257255 networkType,
258256 // TODO: ^ make a useTransactionSigner to encapsulate this logic
259257 txn: inviteTx,
260− gasPrice: DEFAULT_GAS_PRICE_GWEI.toString(),
258+ gasPrice: gasPrice.toString(),
261259 gasLimit: GAS_LIMIT.toString(),
262260 nonce: nonce + i,
263261 chainId,
@@ -283,6 +281,7 @@ export default function InviteEmail() {
283281 }, [
284282 contracts,
285283 web3,
284+ gasPrice,
286285 wallet,
287286 inputs,
288287 point,
@@ -308,7 +307,7 @@ export default function InviteEmail() {
308307 _web3,
309308 point,
310309 _wallet.address,
311− INVITE_COST * inputs.length,
310+ toWei((gasPrice * GAS_LIMIT * inputs.length).toString(), 'gwei'),
312311 inputs.map(input => invites[input.name].rawTx),
313312 (address, minBalance, balance) =>
314313 setNeedFunds({ address, minBalance, balance }),
@@ -377,6 +376,7 @@ export default function InviteEmail() {
377376 }
378377 }, [
379378 web3,
379+ gasPrice,
380380 inputs,
381381 addReceipt,
382382 clearReceipts,