on master help sign in
Move ensureFundsFor and related helpers into /lib/tank
d2c43d4Fang
src/bridge/lib/invite.js+17−70
@@ -169,6 +169,13 @@ async function startTransactions(args) {
169 let { realPointM, web3M, contractsM,
169 let { realPointM, web3M, contractsM,
170 inviteWalletM, realWalletM, setUrbitWallet, updateProgress } = args
170 inviteWalletM, realWalletM, setUrbitWallet, updateProgress } = args
171
171
172+ const askForFunding = (address, amount, current) => {
173+ updateProgress({
174+ type: "notify",
175+ value: `Please make sure ${address} has at least ${amount} wei, we'll continue once that's true. Current balance: ${current}. Waiting`
176+ });
177+ }
178+
172 if (Nothing.hasInstance(web3M)) {
179 if (Nothing.hasInstance(web3M)) {
173 throw BRIDGE_ERROR.MISSING_WEB3;
180 throw BRIDGE_ERROR.MISSING_WEB3;
174 }
181 }
@@ -217,7 +224,11 @@ async function startTransactions(args) {
217 let rawTransferStx = '0x'+transferStx.serialize().toString('hex');
224 let rawTransferStx = '0x'+transferStx.serialize().toString('hex');
218
225
219 const transferCost = transferTx.gas * transferTx.gasPrice;
226 const transferCost = transferTx.gas * transferTx.gasPrice;
227+ updateProgress({
228+ type: "progress",
229+ value: TRANSACTION_STATES.FUNDING_INVITE
230+ });
220− await ensureFundsFor(web3, point, inviteAddress, transferCost, [rawTransferStx], updateProgress, true);
231+ await tank.ensureFundsFor(web3, point, inviteAddress, transferCost, [rawTransferStx], askForFunding);
221
232
222 updateProgress({
233 updateProgress({
223 type: "progress",
234 type: "progress",
@@ -281,7 +292,11 @@ async function startTransactions(args) {
281 return '0x'+stx.serialize().toString('hex');
292 return '0x'+stx.serialize().toString('hex');
282 });
293 });
283
294
295+ updateProgress({
296+ type: "progress",
297+ value: TRANSACTION_STATES.FUNDING_RECIPIENT
298+ });
284− await ensureFundsFor(web3, point, newAddress, totalCost, rawStxs, updateProgress, false);
299+ await tank.ensureFundsFor(web3, point, newAddress, totalCost, rawStxs, askForFunding);
285
300
286 updateProgress({
301 updateProgress({
287 type: "progress",
302 type: "progress",
@@ -328,67 +343,6 @@ async function startTransactions(args) {
328 setUrbitWallet(Just(realWallet));
343 setUrbitWallet(Just(realWallet));
329}
344}
330
345
331−async function ensureFundsFor(web3, point, address, cost, signedTxs, updateProgress, firstTx) {
332− let fundingState = firstTx? TRANSACTION_STATES.FUNDING_INVITE : TRANSACTION_STATES.FUNDING_RECIPIENT
333−
334− updateProgress({
335− type: "progress",
336− value: fundingState
337− });
338−
339− let balance = await web3.eth.getBalance(address);
340−
341− if (cost > balance) {
342−
343− try {
344−
345− const fundsRemaining = await tank.remainingTransactions(point);
346− if (fundsRemaining < signedTxs.length) {
347− throw new Error('request invalid');
348− }
349−
350− const res = await tank.fundTransactions(signedTxs);
351− if (!res.success) {
352− throw new Error('request rejected');
353− } else {
354− await waitForTransactionConfirm(web3, res.txHash);
355− let newBalance = await web3.eth.getBalance(address);
356− console.log('funds have confirmed', balance >= cost, balance, newBalance);
357− }
358−
359− } catch (e) {
360−
361− console.log('funding failed', e);
362− await waitForBalance(web3, address, cost, updateProgress);
363−
364− }
365−
366− } else {
367− console.log('already have sufficient funds');
368− }
369−}
370−
371−// resolves when address has at least minBalance
372−//
373−async function waitForBalance(web3, address, minBalance, updateProgress) {
374− console.log('awaiting balance', address, minBalance);
375− return new Promise((resolve, reject) => {
376− let oldBalance = null;
377− const checkForBalance = async () => {
378− const balance = await web3.eth.getBalance(address);
379− if (balance >= minBalance) {
380− resolve();
381− } else {
382− if (balance !== oldBalance) {
383− askForFunding(address, minBalance, balance, updateProgress);
384− }
385− setTimeout(checkForBalance, 13000);
386− }
387− };
388− checkForBalance();
389− });
390−}
391−
392//TODO replace with txn.sendSignedTransaction? it can doubt nonce errors too
346//TODO replace with txn.sendSignedTransaction? it can doubt nonce errors too
393async function sendAndAwaitConfirm(web3, signedTxs) {
347async function sendAndAwaitConfirm(web3, signedTxs) {
394 await Promise.all(signedTxs.map(tx => {
348 await Promise.all(signedTxs.map(tx => {
@@ -421,13 +375,6 @@ async function sendAndAwaitConfirm(web3, signedTxs) {
421 }));
375 }));
422}
376}
423
377
424−function askForFunding(address, amount, current, updateProgress) {
425− updateProgress({
426− type: "notify",
427− value: `Please make sure ${address} has at least ${amount} wei, we'll continue once that's true. Current balance: ${current}. Waiting`
428− });
429−}
430−
431export {
378export {
432 generateWallet,
379 generateWallet,
433 downloadWallet,
380 downloadWallet,
src/bridge/lib/tank.js+62−1
@@ -1,3 +1,7 @@
1+// /lib/tank: functions for funding transactions
2+
3+import { waitForTransactionConfirm } from './txn'
4+
1//NOTE if accessing this in a localhost configuration fails with "CORS request
5//NOTE if accessing this in a localhost configuration fails with "CORS request
2// did not succeed", you might need to visit localhost:3001 or whatever
6// did not succeed", you might need to visit localhost:3001 or whatever
3// explicitly and tell your browser that's safe to access.
7// explicitly and tell your browser that's safe to access.
@@ -34,8 +38,65 @@ const fundTransactions = signedTxs => {
34 return sendRequest('/request', {txs:signedTxs});
38 return sendRequest('/request', {txs:signedTxs});
35};
39};
36
40
41+const ensureFundsFor = async (web3, point, address, cost, signedTxs, askForFunding) => {
42+ let balance = await web3.eth.getBalance(address);
43+
44+ if (cost > balance) {
45+
46+ try {
47+
48+ const fundsRemaining = await remainingTransactions(point);
49+ if (fundsRemaining < signedTxs.length) {
50+ throw new Error('tank: request invalid');
51+ }
52+
53+ const res = await fundTransactions(signedTxs);
54+ if (!res.success) {
55+ throw new Error('tank: request rejected');
56+ } else {
57+ await waitForTransactionConfirm(web3, res.txHash);
58+ let newBalance = await web3.eth.getBalance(address);
59+ console.log('tank: funds have confirmed', balance >= cost, balance, newBalance);
60+ }
61+
62+ } catch (e) {
63+
64+ console.log('tank: funding failed', e);
65+ await waitForBalance(web3, address, cost, askForFunding);
66+
67+ }
68+
69+ } else {
70+ console.log('tank: already have sufficient funds');
71+ }
72+};
73+
74+// resolves when address has at least minBalance
75+//
76+// askForFunding: callback that takes (address, requiredBalance, currentBalance)
77+// and tells the user to get that address the required balance
78+async function waitForBalance(web3, address, minBalance, askForFunding) {
79+ console.log('tank: awaiting balance', address, minBalance);
80+ return new Promise((resolve, reject) => {
81+ let oldBalance = null;
82+ const checkForBalance = async () => {
83+ const balance = await web3.eth.getBalance(address);
84+ if (balance >= minBalance) {
85+ resolve();
86+ } else {
87+ if (balance !== oldBalance) {
88+ askForFunding(address, minBalance, balance);
89+ }
90+ setTimeout(checkForBalance, 13000);
91+ }
92+ };
93+ checkForBalance();
94+ });
95+}
96+
37export {
97export {
38 remainingTransactions,
98 remainingTransactions,
39− fundTransactions
99+ fundTransactions,
100+ ensureFundsFor
40}
101}
41
102