on master help sign in
fix reticket flow to handle noncustodial wallets
20e49fcLiam Fitzgerald
src/lib/reticket.js+57−26
@@ -1,4 +1,3 @@
1−import Tx from 'ethereumjs-tx';
2import * as azimuth from 'azimuth-js';
1import * as azimuth from 'azimuth-js';
3import * as tank from './tank';
2import * as tank from './tank';
4
3
@@ -9,7 +8,11 @@ import {
9 CRYPTO_SUITE_VERSION,
8 CRYPTO_SUITE_VERSION,
10} from './keys';
9} from './keys';
11import { addHexPrefix } from './wallet';
10import { addHexPrefix } from './wallet';
11+import {
12+ sendAndAwaitAllSerial,
13+ signTransaction,
14+ sendSignedTransaction,
12−import { sendAndAwaitAll } from './txn';
15+} from './txn';
13import getSuggestedGasPrice from './getSuggestedGasPrice';
16import getSuggestedGasPrice from './getSuggestedGasPrice';
14import { GAS_LIMITS } from './constants';
17import { GAS_LIMITS } from './constants';
15import { toWei, toBN } from 'web3-utils';
18import { toWei, toBN } from 'web3-utils';
@@ -28,6 +31,8 @@ export const TRANSACTION_PROGRESS = {
28
31
29export async function reticketPointBetweenWallets({
32export async function reticketPointBetweenWallets({
30 fromWallet,
33 fromWallet,
34+ fromWalletType,
35+ fromWalletHdPath,
31 toWallet,
36 toWallet,
32 point,
37 point,
33 web3,
38 web3,
@@ -143,26 +148,44 @@ export async function reticketPointBetweenWallets({
143 progress(TRANSACTION_PROGRESS.SIGNING);
148 progress(TRANSACTION_PROGRESS.SIGNING);
144
149
145 const suggestedGasPrice = await getSuggestedGasPrice(networkType);
150 const suggestedGasPrice = await getSuggestedGasPrice(networkType);
151+ const chainId = await web3.eth.net.getId();
146 const gasPrice = toWei(suggestedGasPrice.toFixed(), 'gwei');
152 const gasPrice = toWei(suggestedGasPrice.toFixed(), 'gwei');
153+ console.log(suggestedGasPrice.toFixed());
147 const gasPriceBN = toBN(gasPrice);
154 const gasPriceBN = toBN(gasPrice);
148− let totalCost = toBN(0);
155+ console.log(gasPrice);
149 let inviteNonce = await web3.eth.getTransactionCount(fromWallet.address);
156 let inviteNonce = await web3.eth.getTransactionCount(fromWallet.address);
150− txs = txs.map(tx => {
157+ console.log(txs);
151− tx.from = fromWallet.address;
158+ const totalCost = txs.reduce(
152− tx.nonce = inviteNonce++;
153− tx.gasPrice = gasPriceBN;
154− totalCost = totalCost.add(gasPriceBN.mul(toBN(tx.gas)));
159+ (acc, tx) => acc.add(gasPriceBN.mul(toBN(tx.gas))),
155− return tx;
160+ toBN(0)
156− });
161+ );
157
162
163+ console.log(txs);
164+
165+ let txPairs = await Promise.all(
158− let txPairs = txs.map(tx => {
166+ txs.map(async (tx, idx) => {
159− let stx = new Tx(tx);
167+ const stx = await signTransaction({
160− stx.sign(Buffer.from(fromWallet.privateKey, 'hex'));
168+ wallet: fromWallet,
169+ walletType: fromWalletType,
170+ walletHdPath: fromWalletHdPath,
171+ networkType,
172+ txn: tx,
173+ nonce: inviteNonce + idx,
174+ chainId,
175+ gasPrice: suggestedGasPrice.toFixed(),
176+ gasLimit: tx.gas,
177+ });
178+ if (!stx) {
179+ debugger;
180+ }
161− return {
181+ return {
162− raw: hexify(stx.serialize()),
182+ raw: hexify(stx.serialize()),
163− signed: stx,
183+ signed: stx,
184+ };
164− };
185+ })
165− });
186+ );
187+
188+ inviteNonce = inviteNonce + txs.length;
166
189
167 //
190 //
168 // ensuring funding for transactions
191 // ensuring funding for transactions
@@ -186,7 +209,8 @@ export async function reticketPointBetweenWallets({
186
209
187 progress(TRANSACTION_PROGRESS.TRANSFERRING);
210 progress(TRANSACTION_PROGRESS.TRANSFERRING);
188
211
212+ console.log(txPairs);
189− await sendAndAwaitAll(web3, txPairs.map(p => p.signed), usedTank);
213+ await sendAndAwaitAllSerial(web3, txPairs.map(p => p.signed), usedTank);
190
214
191 //
215 //
192 // move leftover eth
216 // move leftover eth
@@ -200,17 +224,24 @@ export async function reticketPointBetweenWallets({
200 const sendEthCost = gasPriceBN.mul(toBN(gasLimit));
224 const sendEthCost = gasPriceBN.mul(toBN(gasLimit));
201 if (transferEth && balance.gt(sendEthCost)) {
225 if (transferEth && balance.gt(sendEthCost)) {
202 const value = balance.sub(sendEthCost);
226 const value = balance.sub(sendEthCost);
203− const tx = {
227+ const txn = {
204 to: toWallet.ownership.keys.address,
228 to: toWallet.ownership.keys.address,
205 value: value,
229 value: value,
230+ };
231+ const stx = signTransaction({
232+ wallet: fromWallet,
233+ walletType: fromWalletType,
234+ walletHdPath: fromWalletHdPath,
235+ txn,
236+ chainId,
237+ networkType,
206 gasPrice: gasPriceBN,
238 gasPrice: gasPriceBN,
207− gas: gasLimit,
239+ gasLimit,
208 nonce: inviteNonce++,
240 nonce: inviteNonce++,
209− };
241+ });
210− let stx = new Tx(tx);
242+ // let stx = new Tx(tx);
211− stx.sign(fromWallet.privateKey);
243+ // stx.sign(fromWallet.privateKey);
212− const rawTx = hexify(stx.serialize());
244+ sendSignedTransaction(web3, stx).catch(err => {
213− web3.eth.sendSignedTransaction(rawTx).catch(err => {
214 console.log('error sending value tx, who cares', err);
245 console.log('error sending value tx, who cares', err);
215 });
246 });
216 }
247 }
src/lib/txn.js+12
@@ -172,6 +172,17 @@ const sendAndAwaitAll = (web3, stxs, doubtNonceError) => {
172 );
172 );
173};
173};
174
174
175+const sendAndAwaitAllSerial = (web3, stxs, doubtNonceError) => {
176+ return stxs.reduce(
177+ (promise, stx) =>
178+ promise.then(async () => {
179+ const txHash = await sendSignedTransaction(web3, stx, doubtNonceError);
180+ await waitForTransactionConfirm(web3, txHash);
181+ }),
182+ Promise.resolve()
183+ );
184+};
185+
175const sendTransactionsAndAwaitConfirm = async (web3, signedTxs, usedTank) =>
186const sendTransactionsAndAwaitConfirm = async (web3, signedTxs, usedTank) =>
176 Promise.all(signedTxs.map(tx => sendSignedTransaction(web3, tx, usedTank)));
187 Promise.all(signedTxs.map(tx => sendSignedTransaction(web3, tx, usedTank)));
177
188
@@ -214,6 +225,7 @@ export {
214 waitForTransactionConfirm,
225 waitForTransactionConfirm,
215 sendTransactionsAndAwaitConfirm,
226 sendTransactionsAndAwaitConfirm,
216 sendAndAwaitAll,
227 sendAndAwaitAll,
228+ sendAndAwaitAllSerial,
217 getTxnInfo,
229 getTxnInfo,
218 hexify,
230 hexify,
219 renderSignedTx,
231 renderSignedTx,
src/views/Admin/Reticket/ReticketExecute.js+11−1
@@ -44,7 +44,14 @@ const labelForProgress = progress => {
44export default function ReticketExecute({ newWallet, setNewWallet }) {
44export default function ReticketExecute({ newWallet, setNewWallet }) {
45 const { popTo, names, reset } = useHistory();
45 const { popTo, names, reset } = useHistory();
46 const { web3, contracts, networkType } = useNetwork();
46 const { web3, contracts, networkType } = useNetwork();
47− const { wallet, setWalletType, resetWallet, setUrbitWallet } = useWallet();
47+ const {
48+ wallet,
49+ setWalletType,
50+ resetWallet,
51+ setUrbitWallet,
52+ walletType,
53+ walletHdPath,
54+ } = useWallet();
48 const { pointCursor } = usePointCursor();
55 const { pointCursor } = usePointCursor();
49 const { getDetails } = usePointCache();
56 const { getDetails } = usePointCache();
50
57
@@ -64,6 +71,8 @@ export default function ReticketExecute({ newWallet, setNewWallet }) {
64 try {
71 try {
65 await reticketPointBetweenWallets({
72 await reticketPointBetweenWallets({
66 fromWallet: need.wallet(wallet),
73 fromWallet: need.wallet(wallet),
74+ fromWalletType: walletType,
75+ fromWalletHdPath: walletHdPath,
67 toWallet: newWallet.value.wallet,
76 toWallet: newWallet.value.wallet,
68 point: point,
77 point: point,
69 web3: need.web3(web3),
78 web3: need.web3(web3),
@@ -73,6 +82,7 @@ export default function ReticketExecute({ newWallet, setNewWallet }) {
73 nextRevision: networkRevision + 1,
82 nextRevision: networkRevision + 1,
74 });
83 });
75 } catch (err) {
84 } catch (err) {
85+ console.error(err);
76 setGeneralError(err);
86 setGeneralError(err);
77 }
87 }
78 })();
88 })();