on master help sign in
Merge branch 'mino' into feat/final-form
39bc817Matt Condon (shrugs)
src/lib/reticket.js+6−3
@@ -10,7 +10,8 @@ import {
10} from './keys';
10} from './keys';
11import { addHexPrefix } from './wallet';
11import { addHexPrefix } from './wallet';
12import { sendAndAwaitAll } from './txn';
12import { sendAndAwaitAll } from './txn';
13+import { getSuggestedGasPrice } from './useSuggestedGasPrice';
13−import { GAS_LIMITS, DEFAULT_GAS_PRICE_GWEI } from './constants';
14+import { GAS_LIMITS } from './constants';
14import { toWei } from 'web3-utils';
15import { toWei } from 'web3-utils';
15
16
16// the initial network key revision is always 1
17// the initial network key revision is always 1
@@ -31,6 +32,7 @@ export async function reticketPointBetweenWallets({
31 point,
32 point,
32 web3,
33 web3,
33 contracts,
34 contracts,
35+ networkType,
34 onUpdate,
36 onUpdate,
35 transferEth = false,
37 transferEth = false,
36 nextRevision = INITIAL_NETWORK_KEY_REVISION,
38 nextRevision = INITIAL_NETWORK_KEY_REVISION,
@@ -140,12 +142,14 @@ export async function reticketPointBetweenWallets({
140
142
141 progress(TRANSACTION_PROGRESS.SIGNING);
143 progress(TRANSACTION_PROGRESS.SIGNING);
142
144
145+ const suggestedGasPrice = await getSuggestedGasPrice(networkType);
146+ const gasPrice = parseInt(toWei(suggestedGasPrice.toFixed(), 'gwei'), 10);
143 let totalCost = 0;
147 let totalCost = 0;
144 let inviteNonce = await web3.eth.getTransactionCount(fromWallet.address);
148 let inviteNonce = await web3.eth.getTransactionCount(fromWallet.address);
145 txs = txs.map(tx => {
149 txs = txs.map(tx => {
146 tx.from = fromWallet.address;
150 tx.from = fromWallet.address;
147 tx.nonce = inviteNonce++;
151 tx.nonce = inviteNonce++;
148− tx.gasPrice = parseInt(toWei(DEFAULT_GAS_PRICE_GWEI.toFixed(), 'gwei'), 10);
152+ tx.gasPrice = gasPrice;
149 totalCost = totalCost + tx.gasPrice * tx.gas;
153 totalCost = totalCost + tx.gasPrice * tx.gas;
150 return tx;
154 return tx;
151 });
155 });
@@ -191,7 +195,6 @@ export async function reticketPointBetweenWallets({
191
195
192 // if non-trivial eth left in invite wallet, transfer to new ownership
196 // if non-trivial eth left in invite wallet, transfer to new ownership
193 let balance = await web3.eth.getBalance(fromWallet.address);
197 let balance = await web3.eth.getBalance(fromWallet.address);
194− const gasPrice = parseInt(toWei(DEFAULT_GAS_PRICE_GWEI.toFixed(), 'gwei'));
195 const gasLimit = GAS_LIMITS.SEND_ETH;
198 const gasLimit = GAS_LIMITS.SEND_ETH;
196 const sendEthCost = gasPrice * gasLimit;
199 const sendEthCost = gasPrice * gasLimit;
197 if (transferEth && balance > sendEthCost) {
200 if (transferEth && balance > sendEthCost) {
src/lib/useEthereumTransaction.js+21−7
@@ -5,6 +5,7 @@ import { fromWei, toWei } from 'web3-utils';
5import { useNetwork } from 'store/network';
5import { useNetwork } from 'store/network';
6import { useWallet } from 'store/wallet';
6import { useWallet } from 'store/wallet';
7import { usePointCursor } from 'store/pointCursor';
7import { usePointCursor } from 'store/pointCursor';
8+import { useSuggestedGasPrice } from 'lib/useSuggestedGasPrice';
8
9
9import { GAS_LIMITS } from './constants';
10import { GAS_LIMITS } from './constants';
10import {
11import {
@@ -60,6 +61,7 @@ export default function useEthereumTransaction(
60 const [nonce, setNonce] = useState();
61 const [nonce, setNonce] = useState();
61 const [gasPrice, setGasPrice] = useState(initialGasPrice); // gwei
62 const [gasPrice, setGasPrice] = useState(initialGasPrice); // gwei
62 const [suggestedGasPrice, setSuggestedGasPrice] = useState(gasPrice); // gwei
63 const [suggestedGasPrice, setSuggestedGasPrice] = useState(gasPrice); // gwei
64+ const { gasPrice: estimatedGasPrice } = useSuggestedGasPrice();
63 const [gasLimit] = useState(initialGasLimit);
65 const [gasLimit] = useState(initialGasLimit);
64 const [unsignedTransaction, setUnsignedTransaction] = useState();
66 const [unsignedTransaction, setUnsignedTransaction] = useState();
65 const [signedTransaction, setSignedTransaction] = useState();
67 const [signedTransaction, setSignedTransaction] = useState();
@@ -188,6 +190,15 @@ export default function useEthereumTransaction(
188 suggestedGasPrice,
190 suggestedGasPrice,
189 ]);
191 ]);
190
192
193+ useEffect(() => {
194+ const gasPrice = parseInt(
195+ fromWei(estimatedGasPrice.toString(), 'gwei'),
196+ 10
197+ );
198+ setSuggestedGasPrice(gasPrice);
199+ setGasPrice(gasPrice);
200+ }, [estimatedGasPrice]);
201+
191 useEffect(() => {
202 useEffect(() => {
192 let mounted = true;
203 let mounted = true;
193 // if nonce or chainId is undefined, re-fetch on-chain info
204 // if nonce or chainId is undefined, re-fetch on-chain info
@@ -198,29 +209,32 @@ export default function useEthereumTransaction(
198 (async () => {
209 (async () => {
199 try {
210 try {
200 setError(undefined);
211 setError(undefined);
201− const [nonce, chainId, estimatedGasPrice] = await Promise.all([
212+ const [nonce, chainId] = await Promise.all([
202 _web3.eth.getTransactionCount(_wallet.address),
213 _web3.eth.getTransactionCount(_wallet.address),
203 _web3.eth.net.getId(),
214 _web3.eth.net.getId(),
204− _web3.eth.getGasPrice(),
205 ]);
215 ]);
206
216
207− const gasPrice = parseInt(fromWei(estimatedGasPrice, 'gwei'), 10);
208−
209 if (!mounted) {
217 if (!mounted) {
210 return;
218 return;
211 }
219 }
212
220
213 setNonce(nonce);
221 setNonce(nonce);
214 setChainId(chainId);
222 setChainId(chainId);
215− setSuggestedGasPrice(gasPrice);
216− setGasPrice(gasPrice);
217 } catch (error) {
223 } catch (error) {
218 setError(error);
224 setError(error);
219 }
225 }
220 })();
226 })();
221
227
222 return () => (mounted = false);
228 return () => (mounted = false);
229+ }, [
230+ _wallet,
231+ _web3,
223− }, [_wallet, _web3, setError, nonce, chainId]);
232+ setError,
233+ nonce,
234+ chainId,
235+ networkType,
236+ estimatedGasPrice,
237+ ]);
224
238
225 useEffect(() => {
239 useEffect(() => {
226 let mounted = true;
240 let mounted = true;
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 }) {
45 const { replaceWith, names } = useHistory();
45 const { replaceWith, names } = useHistory();
46 const { setUrbitWallet } = useWallet();
46 const { setUrbitWallet } = useWallet();
47 const { setPointCursor } = usePointCursor();
47 const { setPointCursor } = usePointCursor();
48− const { web3, contracts } = useNetwork();
48+ const { web3, contracts, networkType } = useNetwork();
49 const {
49 const {
50 derivedWallet,
50 derivedWallet,
51 derivedPoint,
51 derivedPoint,
@@ -112,6 +112,7 @@ export default function PassportTransfer({ className, resetActivateRouter }) {
112 point: _point,
112 point: _point,
113 web3: _web3,
113 web3: _web3,
114 contracts: _contracts,
114 contracts: _contracts,
115+ networkType,
115 onUpdate: handleUpdate,
116 onUpdate: handleUpdate,
116 transferEth: true,
117 transferEth: true,
117 });
118 });
@@ -133,6 +134,7 @@ export default function PassportTransfer({ className, resetActivateRouter }) {
133 derivedPoint,
134 derivedPoint,
134 web3,
135 web3,
135 contracts,
136 contracts,
137+ networkType,
136 setUrbitWallet,
138 setUrbitWallet,
137 setPointCursor,
139 setPointCursor,
138 handleUpdate,
140 handleUpdate,
src/views/Admin/Reticket/ReticketExecute.js+2−1
@@ -42,7 +42,7 @@ const labelForProgress = progress => {
42
42
43export default function ReticketExecute({ newWallet, setNewWallet }) {
43export default function ReticketExecute({ newWallet, setNewWallet }) {
44 const { popTo, names, reset } = useHistory();
44 const { popTo, names, reset } = useHistory();
45− const { web3, contracts } = useNetwork();
45+ const { web3, contracts, networkType } = useNetwork();
46 const { wallet, setWalletType, resetWallet, setUrbitWallet } = useWallet();
46 const { wallet, setWalletType, resetWallet, setUrbitWallet } = useWallet();
47 const { pointCursor } = usePointCursor();
47 const { pointCursor } = usePointCursor();
48 const { getDetails } = usePointCache();
48 const { getDetails } = usePointCache();
@@ -65,6 +65,7 @@ export default function ReticketExecute({ newWallet, setNewWallet }) {
65 point: point,
65 point: point,
66 web3: need.web3(web3),
66 web3: need.web3(web3),
67 contracts: need.contracts(contracts),
67 contracts: need.contracts(contracts),
68+ networkType,
68 onUpdate: handleUpdate,
69 onUpdate: handleUpdate,
69 nextRevision: networkRevision + 1,
70 nextRevision: networkRevision + 1,
70 });
71 });
src/views/Invite/InviteEmail.js+16−8
@@ -34,7 +34,8 @@ import {
34 hexify,
34 hexify,
35} from 'lib/txn';
35} from 'lib/txn';
36import * as tank from 'lib/tank';
36import * as tank from 'lib/tank';
37−import { MIN_PLANET, GAS_LIMITS, DEFAULT_GAS_PRICE_GWEI } from 'lib/constants';
37+import { MIN_PLANET, GAS_LIMITS } from 'lib/constants';
38+import { useSuggestedGasPrice } from 'lib/useSuggestedGasPrice';
38import * as need from 'lib/need';
39import * as need from 'lib/need';
39import * as wg from 'lib/walletgen';
40import * as wg from 'lib/walletgen';
40import useSetState from 'lib/useSetState';
41import useSetState from 'lib/useSetState';
@@ -59,10 +60,6 @@ import FormError from 'form/FormError';
59const INITIAL_VALUES = { emails: [''] };
60const INITIAL_VALUES = { emails: [''] };
60
61
61const GAS_LIMIT = GAS_LIMITS.GIFT_PLANET;
62const GAS_LIMIT = GAS_LIMITS.GIFT_PLANET;
62−const INVITE_COST = toWei(
63− (DEFAULT_GAS_PRICE_GWEI * GAS_LIMIT).toString(),
64− 'gwei'
65−);
66const HAS_RECEIVED_TEXT = 'This email has already received an invite.';
63const HAS_RECEIVED_TEXT = 'This email has already received an invite.';
67
64
68const STATUS = {
65const STATUS = {
@@ -106,6 +103,7 @@ export default function InviteEmail() {
106 const { pointCursor } = usePointCursor();
103 const { pointCursor } = usePointCursor();
107 const point = need.point(pointCursor);
104 const point = need.point(pointCursor);
108 const { getHasReceived, sendMail } = useMailer();
105 const { getHasReceived, sendMail } = useMailer();
106+ const { gasPrice } = useSuggestedGasPrice(networkType);
109
107
110 const cachedEmails = useRef([]);
108 const cachedEmails = useRef([]);
111
109
@@ -245,7 +243,7 @@ export default function InviteEmail() {
245 nonce: nonce + i,
243 nonce: nonce + i,
246 // TODO: ^ make a useTransactionSigner to encapsulate this logic
244 // TODO: ^ make a useTransactionSigner to encapsulate this logic
247 txn: inviteTx,
245 txn: inviteTx,
248− gasPrice: DEFAULT_GAS_PRICE_GWEI.toString(),
246+ gasPrice: gasPrice.toString(),
249 gasLimit: GAS_LIMIT.toString(),
247 gasLimit: GAS_LIMIT.toString(),
250 });
248 });
251
249
@@ -278,6 +276,7 @@ export default function InviteEmail() {
278 walletType,
276 walletType,
279 walletHdPath,
277 walletHdPath,
280 networkType,
278 networkType,
279+ gasPrice,
281 addInvite,
280 addInvite,
282 ]
281 ]
283 );
282 );
@@ -295,7 +294,7 @@ export default function InviteEmail() {
295 _web3,
294 _web3,
296 point,
295 point,
297 _wallet.address,
296 _wallet.address,
298− INVITE_COST * emails.length,
297+ toWei((gasPrice * GAS_LIMIT * emails.length).toString(), 'gwei'),
299 emails.map(email => invites[email].rawTx),
298 emails.map(email => invites[email].rawTx),
300 (address, minBalance, balance) =>
299 (address, minBalance, balance) =>
301 setNeedFunds({ address, minBalance, balance }),
300 setNeedFunds({ address, minBalance, balance }),
@@ -361,7 +360,16 @@ export default function InviteEmail() {
361 if (errorString !== '') {
360 if (errorString !== '') {
362 throw new Error(errorString);
361 throw new Error(errorString);
363 }
362 }
364− }, [web3, addReceipt, clearReceipts, invites, point, wallet, sendMail]);
363+ }, [
364+ web3,
365+ wallet,
366+ point,
367+ gasPrice,
368+ clearReceipts,
369+ invites,
370+ addReceipt,
371+ sendMail,
372+ ]);
365
373
366 const onSubmit = useCallback(
374 const onSubmit = useCallback(
367 async values => {
375 async values => {