on master help sign in
Use async-retry for chain update waiting
d82c74cFang
package-lock.json+13
@@ -2573,6 +2573,14 @@
2573 "resolved": "https://registry.npmjs.org/async-limiter/-/async-limiter-1.0.0.tgz",
2573 "resolved": "https://registry.npmjs.org/async-limiter/-/async-limiter-1.0.0.tgz",
2574 "integrity": "sha512-jp/uFnooOiO+L211eZOoSyzpOITMXx1rBITauYykG3BRYPu8h0UcxsPNB04RR5vo4Tyz3+ay17tR6JVf9qzYWg=="
2574 "integrity": "sha512-jp/uFnooOiO+L211eZOoSyzpOITMXx1rBITauYykG3BRYPu8h0UcxsPNB04RR5vo4Tyz3+ay17tR6JVf9qzYWg=="
2575 },
2575 },
2576+ "async-retry": {
2577+ "version": "1.2.3",
2578+ "resolved": "https://registry.npmjs.org/async-retry/-/async-retry-1.2.3.tgz",
2579+ "integrity": "sha512-tfDb02Th6CE6pJUF2gjW5ZVjsgwlucVXOEQMvEX9JgSJMs9gAX+Nz3xRuJBKuUYjTSYORqvDBORdAQ3LU59g7Q==",
2580+ "requires": {
2581+ "retry": "0.12.0"
2582+ }
2583+ },
2576 "asynckit": {
2584 "asynckit": {
2577 "version": "0.4.0",
2585 "version": "0.4.0",
2578 "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
2586 "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
@@ -14927,6 +14935,11 @@
14927 "resolved": "https://registry.npmjs.org/ret/-/ret-0.1.15.tgz",
14935 "resolved": "https://registry.npmjs.org/ret/-/ret-0.1.15.tgz",
14928 "integrity": "sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg=="
14936 "integrity": "sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg=="
14929 },
14937 },
14938+ "retry": {
14939+ "version": "0.12.0",
14940+ "resolved": "https://registry.npmjs.org/retry/-/retry-0.12.0.tgz",
14941+ "integrity": "sha1-G0KmJmoh8HQh0bC1S33BZ7AcATs="
14942+ },
14930 "rgb-regex": {
14943 "rgb-regex": {
14931 "version": "1.0.1",
14944 "version": "1.0.1",
14932 "resolved": "https://registry.npmjs.org/rgb-regex/-/rgb-regex-1.0.1.tgz",
14945 "resolved": "https://registry.npmjs.org/rgb-regex/-/rgb-regex-1.0.1.tgz",
package.json+1
@@ -18,6 +18,7 @@
18 "@ledgerhq/hw-app-eth": "^4.61.0",
18 "@ledgerhq/hw-app-eth": "^4.61.0",
19 "@ledgerhq/hw-transport-u2f": "^4.61.0",
19 "@ledgerhq/hw-transport-u2f": "^4.61.0",
20 "PaperCollateralRenderer": "github:urbit/PaperCollateralRenderer",
20 "PaperCollateralRenderer": "github:urbit/PaperCollateralRenderer",
21+ "async-retry": "^1.2.3",
21 "azimuth-js": "^0.15.0",
22 "azimuth-js": "^0.15.0",
22 "azimuth-solidity": "^1.2.0",
23 "azimuth-solidity": "^1.2.0",
23 "bip32": "^1.0.2",
24 "bip32": "^1.0.2",
src/lib/tank.js+24−35
@@ -1,6 +1,7 @@
1// /lib/tank: functions for funding transactions
1// /lib/tank: functions for funding transactions
2
2
3+import * as retry from 'async-retry';
3−import { waitForTransactionConfirm } from './txn';
4+import { RETRY_OPTIONS, waitForTransactionConfirm } from './txn';
4
5
5//NOTE if accessing this in a localhost configuration fails with "CORS request
6//NOTE if accessing this in a localhost configuration fails with "CORS request
6// did not succeed", you might need to visit localhost:3001 or whatever
7// did not succeed", you might need to visit localhost:3001 or whatever
@@ -92,41 +93,29 @@ const ensureFundsFor = async (
92 return false;
93 return false;
93};
94};
94
95
95−// resolves when address has at least minBalance
96+// returns a promise that resolves when address has at least minBalance
96−//
97−//TODO should maybe do a "we got it" callback also, so clients can hide msg?
98−async function waitForBalance(
97+function waitForBalance(web3, address, minBalance, askForFunding, gotFunding) {
99− web3,
98+ let oldBalance = null;
100− address,
99+ return retry(async (bail, n) => {
101− minBalance,
102− askForFunding,
103− gotFunding
104−) {
105− console.log('tank: awaiting balance', address, minBalance);
106− return new Promise((resolve, reject) => {
107− let oldBalance = null;
108− const checkForBalance = async () => {
109− const balance = await web3.eth.getBalance(address);
100+ const balance = await web3.eth.getBalance(address);
110− if (balance >= minBalance) {
101+ if (balance >= minBalance) {
111− // if we ever asked for funding, retract that request now
102+ // if we ever asked for funding, retract that request now
112− if (gotFunding && oldBalance !== null) {
103+ if (gotFunding && oldBalance !== null) {
113− gotFunding();
104+ gotFunding();
114− }
115− resolve();
116− } else {
117− if (balance !== oldBalance) {
118− // TODO: minBalance is a `number` type
119− // but we want to display ETH, which will never accept a number
120− // but instead wants string or BN/BigNumber.
121− // this will be heavily refactored to correctly do BN math, but until
122− // then we'll manually convert this number to an integer string
123− askForFunding(address, minBalance.toFixed(), balance);
124− }
125− setTimeout(checkForBalance, 13000);
126 }
105 }
127− };
106+ return;
128− checkForBalance();
107+ } else {
129− });
108+ if (balance !== oldBalance) {
109+ // TODO: minBalance is a `number` type
110+ // but we want to display ETH, which will never accept a number
111+ // but instead wants string or BN/BigNumber.
112+ // this will be heavily refactored to correctly do BN math, but until
113+ // then we'll manually convert this number to an integer string
114+ askForFunding(address, minBalance.toFixed(), balance);
115+ }
116+ throw new Error('retrying');
117+ }
118+ }, RETRY_OPTIONS);
130}
119}
131
120
132export { remainingTransactions, fundTransactions, ensureFundsFor };
121export { remainingTransactions, fundTransactions, ensureFundsFor };
src/lib/txn.js+15−11
@@ -2,6 +2,7 @@ import * as ob from 'urbit-ob';
2import { Just } from 'folktale/maybe';
2import { Just } from 'folktale/maybe';
3import Tx from 'ethereumjs-tx';
3import Tx from 'ethereumjs-tx';
4import { toWei, fromWei, toHex } from 'web3-utils';
4import { toWei, fromWei, toHex } from 'web3-utils';
5+import * as retry from 'async-retry';
5
6
6import { BRIDGE_ERROR } from './error';
7import { BRIDGE_ERROR } from './error';
7import { NETWORK_TYPES } from './network';
8import { NETWORK_TYPES } from './network';
@@ -12,6 +13,13 @@ import { WALLET_TYPES, addHexPrefix } from './wallet';
12const CHECK_BLOCK_EVERY_MS =
13const CHECK_BLOCK_EVERY_MS =
13 process.env.NODE_ENV === 'development' ? 1000 : 5000;
14 process.env.NODE_ENV === 'development' ? 1000 : 5000;
14
15
16+const RETRY_OPTIONS = {
17+ retries: 99999,
18+ factor: 1,
19+ minTimeout: CHECK_BLOCK_EVERY_MS,
20+ randomize: false,
21+};
22+
15const TXN_PURPOSE = {
23const TXN_PURPOSE = {
16 SET_MANAGEMENT_PROXY: Symbol('SET_MANAGEMENT_PROXY'),
24 SET_MANAGEMENT_PROXY: Symbol('SET_MANAGEMENT_PROXY'),
17 SET_TRANSFER_PROXY: Symbol('SET_TRANSFER_PROXY'),
25 SET_TRANSFER_PROXY: Symbol('SET_TRANSFER_PROXY'),
@@ -178,17 +186,12 @@ const sendSignedTransaction = (web3, stx, doubtNonceError) => {
178
186
179// returns a Promise<bool>, where the bool indicates tx success/failure
187// returns a Promise<bool>, where the bool indicates tx success/failure
180const waitForTransactionConfirm = (web3, txHash) => {
188const waitForTransactionConfirm = (web3, txHash) => {
181− return new Promise((resolve, reject) => {
189+ return retry(async (bail, n) => {
182− const checkForConfirm = async () => {
183− console.log('checking for confirm', txHash);
184− const receipt = await web3.eth.getTransactionReceipt(txHash);
190+ const receipt = await web3.eth.getTransactionReceipt(txHash);
185− console.log('tried, got', receipt);
186− let confirmed = receipt !== null;
191+ let confirmed = receipt !== null;
187− if (confirmed) resolve(receipt.status === true);
192+ if (confirmed) return receipt.status === true;
188− else setTimeout(checkForConfirm, CHECK_BLOCK_EVERY_MS);
193+ else throw new Error('retrying');
189− };
194+ }, RETRY_OPTIONS);
190− checkForConfirm();
191− });
192};
195};
193
196
194const sendAndAwaitAll = async (web3, stxs, doubtNonceError) => {
197const sendAndAwaitAll = async (web3, stxs, doubtNonceError) => {
@@ -234,6 +237,7 @@ const canDecodePatp = p => {
234};
237};
235
238
236export {
239export {
240+ RETRY_OPTIONS,
237 signTransaction,
241 signTransaction,
238 sendSignedTransaction,
242 sendSignedTransaction,
239 waitForTransactionConfirm,
243 waitForTransactionConfirm,