on master help sign in
Merge pull request #239 from urbit/mino-bignum-mvp

Use BNs for comparisons in tank lib

commit71170566ae8fa2f68dc277329e1f351e2ca8b07d authorFang <Fang-@users.noreply.github.com> dateMon 26 Aug 2019, 16:01 (7 years ago) parent43a012a79bacf2
4 files changed+41−28
src/lib/reticket.js+11−10 src/lib/tank.js+22−14 src/lib/useEthereumTransaction.js+3−2 src/views/Invite/InviteEmail.js+5−2
src/lib/reticket.js+11−10
@@ -12,7 +12,7 @@ import { addHexPrefix } from './wallet';
1212import { sendAndAwaitAll } from './txn';
1313import getSuggestedGasPrice from './getSuggestedGasPrice';
1414import { GAS_LIMITS } from './constants';
15−import { toWei } from 'web3-utils';
15+import { toWei, toBN } from 'web3-utils';
1616
1717// the initial network key revision is always 1
1818const INITIAL_NETWORK_KEY_REVISION = 1;
@@ -143,14 +143,15 @@ export async function reticketPointBetweenWallets({
143143 progress(TRANSACTION_PROGRESS.SIGNING);
144144
145145 const suggestedGasPrice = await getSuggestedGasPrice(networkType);
146− const gasPrice = parseInt(toWei(suggestedGasPrice.toFixed(), 'gwei'), 10);
147− let totalCost = 0;
146+ const gasPrice = toWei(suggestedGasPrice.toFixed(), 'gwei');
147+ const gasPriceBN = toBN(gasPrice);
148+ let totalCost = toBN(0);
148149 let inviteNonce = await web3.eth.getTransactionCount(fromWallet.address);
149150 txs = txs.map(tx => {
150151 tx.from = fromWallet.address;
151152 tx.nonce = inviteNonce++;
152− tx.gasPrice = gasPrice;
153− totalCost = totalCost + tx.gasPrice * tx.gas;
153+ tx.gasPrice = gasPriceBN;
154+ totalCost = totalCost.add(gasPriceBN.mul(toBN(tx.gas)));
154155 return tx;
155156 });
156157
@@ -194,15 +195,15 @@ export async function reticketPointBetweenWallets({
194195 progress(TRANSACTION_PROGRESS.CLEANING);
195196
196197 // if non-trivial eth left in invite wallet, transfer to new ownership
197− let balance = await web3.eth.getBalance(fromWallet.address);
198+ let balance = toBN(await web3.eth.getBalance(fromWallet.address));
198199 const gasLimit = GAS_LIMITS.SEND_ETH;
199− const sendEthCost = gasPrice * gasLimit;
200− if (transferEth && balance > sendEthCost) {
201− const value = balance - sendEthCost;
200+ const sendEthCost = gasPriceBN.mul(toBN(gasLimit));
201+ if (transferEth && balance.gt(sendEthCost)) {
202+ const value = balance.sub(sendEthCost);
202203 const tx = {
203204 to: toWallet.ownership.keys.address,
204205 value: value,
205− gasPrice: gasPrice,
206+ gasPrice: gasPriceBN,
206207 gas: gasLimit,
207208 nonce: inviteNonce++,
208209 };
src/lib/tank.js+22−14
@@ -1,6 +1,7 @@
11// /lib/tank: functions for funding transactions
22
33import retry from 'async-retry';
4+import { toBN } from 'web3-utils';
45import { RETRY_OPTIONS, waitForTransactionConfirm } from './txn';
56
67//NOTE if accessing this in a localhost configuration fails with "CORS request
@@ -53,9 +54,10 @@ const ensureFundsFor = async (
5354 askForFunding,
5455 gotFunding
5556) => {
56− let balance = await web3.eth.getBalance(address);
57+ let balance = toBN(await web3.eth.getBalance(address));
58+ cost = toBN(cost);
5759
58− if (cost > balance) {
60+ if (cost.gt(balance)) {
5961 try {
6062 if (point !== null) {
6163 const fundsRemaining = await remainingTransactions(point);
@@ -77,36 +79,42 @@ const ensureFundsFor = async (
7779 let newBalance = await web3.eth.getBalance(address);
7880 console.log(
7981 'tank: funds have confirmed',
80− balance >= cost,
81− balance,
82+ balance.toString(),
8283 newBalance
8384 );
8485 return true;
8586 }
8687 } catch (e) {
8788 console.log('tank: funding failed', e);
88− await waitForBalance(web3, address, cost, askForFunding, gotFunding);
89+ await waitForBalance(
90+ web3,
91+ address,
92+ cost.toString(),
93+ askForFunding,
94+ gotFunding
95+ );
8996 }
9097 } else {
91− console.log('tank: already have sufficient funds', cost, address, balance);
98+ console.log(
99+ 'tank: already have sufficient funds',
100+ cost.toString(),
101+ address,
102+ balance.toString()
103+ );
92104 }
93105 return false;
94106};
95107
96108// returns a promise that resolves when address has at least minBalance
97109function waitForBalance(web3, address, minBalance, askForFunding, gotFunding) {
110+ minBalance = toBN(minBalance);
98111 return retry(async (bail, n) => {
99− const balance = await web3.eth.getBalance(address);
100− if (balance >= minBalance) {
112+ const balance = toBN(await web3.eth.getBalance(address));
113+ if (balance.gte(minBalance)) {
101114 gotFunding && gotFunding();
102115 return;
103116 } else {
104− // TODO: minBalance is a `number` type
105− // but we want to display ETH, which will never accept a number
106− // but instead wants string or BN/BigNumber.
107− // this will be heavily refactored to correctly do BN math, but until
108− // then we'll manually convert this number to an integer string
109− askForFunding(address, minBalance.toFixed(), balance);
117+ askForFunding(address, minBalance, balance);
110118 throw new Error('retrying');
111119 }
112120 }, RETRY_OPTIONS);
src/lib/useEthereumTransaction.js+3−2
@@ -1,6 +1,6 @@
11import { useCallback, useEffect, useState } from 'react';
22import { Just } from 'folktale/maybe';
3−import { toWei } from 'web3-utils';
3+import { toWei, toBN } from 'web3-utils';
44
55import { useNetwork } from 'store/network';
66import { useWallet } from 'store/wallet';
@@ -136,7 +136,8 @@ export default function useEthereumTransaction(
136136 setError(undefined);
137137
138138 const rawTx = hexify(signedTransaction.serialize());
139− const cost = toWei(gasPrice.toFixed(0), 'gwei') * gasLimit;
139+ const costGwei = toBN(gasLimit).mul(toBN(gasPrice));
140+ const cost = toWei(costGwei.toString(), 'gwei');
140141
141142 let usedTank = false;
142143 // if this ethereum transaction is being executed by a specific point
src/views/Invite/InviteEmail.js+5−2
@@ -18,7 +18,7 @@ import {
1818 AccessoryIcon,
1919} from 'indigo-react';
2020import { uniq } from 'lodash';
21−import { fromWei, toWei } from 'web3-utils';
21+import { fromWei, toWei, toBN } from 'web3-utils';
2222import { FieldArray } from 'react-final-form-arrays';
2323
2424import { usePointCursor } from 'store/pointCursor';
@@ -306,11 +306,14 @@ export default function InviteEmail() {
306306 }
307307
308308 setStatus(STATUS.FUNDING);
309+ const totalCost = toBN(GAS_LIMIT)
310+ .mul(toBN(gasPrice))
311+ .mul(toBN(emails.length));
309312 const tankWasUsed = await tank.ensureFundsFor(
310313 _web3,
311314 point,
312315 _wallet.address,
313− toWei((gasPrice * GAS_LIMIT * emails.length).toFixed(), 'gwei'),
316+ toWei(totalCost.toString(), 'gwei'),
314317 names.map(name => invites[name].rawTx),
315318 (address, minBalance, balance) =>
316319 setNeedFunds({ address, minBalance, balance }),