on master help sign in
fix reticket flow to handle noncustodial wallets

Reticket doesn't work when we don't have control of the private key. This change makes the reticket flow use the signTransaction and sendSignedTransaction helpers, which have special cases for handling wallets where we don't have custody of the private key. Addresses #293 #353

commit20e49fc7b1d27321fb4ddf9faeaad26c5b67e170 authorLiam Fitzgerald <liam@urizen.co> dateTue 14 Jan 2020, 14:32 (7 years ago) parent8cbf321
3 files changed+80−27
src/lib/reticket.js+57−26 src/lib/txn.js+12 src/views/Admin/Reticket/ReticketExecute.js+11−1
src/lib/reticket.js+57−26
@@ -1,4 +1,3 @@
1−import Tx from 'ethereumjs-tx';
21import * as azimuth from 'azimuth-js';
32import * as tank from './tank';
43
@@ -9,7 +8,11 @@ import {
98 CRYPTO_SUITE_VERSION,
109} from './keys';
1110import { addHexPrefix } from './wallet';
12−import { sendAndAwaitAll } from './txn';
11+import {
12+ sendAndAwaitAllSerial,
13+ signTransaction,
14+ sendSignedTransaction,
15+} from './txn';
1316import getSuggestedGasPrice from './getSuggestedGasPrice';
1417import { GAS_LIMITS } from './constants';
1518import { toWei, toBN } from 'web3-utils';
@@ -28,6 +31,8 @@ export const TRANSACTION_PROGRESS = {
2831
2932export async function reticketPointBetweenWallets({
3033 fromWallet,
34+ fromWalletType,
35+ fromWalletHdPath,
3136 toWallet,
3237 point,
3338 web3,
@@ -143,26 +148,44 @@ export async function reticketPointBetweenWallets({
143148 progress(TRANSACTION_PROGRESS.SIGNING);
144149
145150 const suggestedGasPrice = await getSuggestedGasPrice(networkType);
151+ const chainId = await web3.eth.net.getId();
146152 const gasPrice = toWei(suggestedGasPrice.toFixed(), 'gwei');
153+ console.log(suggestedGasPrice.toFixed());
147154 const gasPriceBN = toBN(gasPrice);
148− let totalCost = toBN(0);
155+ console.log(gasPrice);
149156 let inviteNonce = await web3.eth.getTransactionCount(fromWallet.address);
150− txs = txs.map(tx => {
151− tx.from = fromWallet.address;
152− tx.nonce = inviteNonce++;
153− tx.gasPrice = gasPriceBN;
154− totalCost = totalCost.add(gasPriceBN.mul(toBN(tx.gas)));
155− return tx;
156− });
157+ console.log(txs);
158+ const totalCost = txs.reduce(
159+ (acc, tx) => acc.add(gasPriceBN.mul(toBN(tx.gas))),
160+ toBN(0)
161+ );
157162
158− let txPairs = txs.map(tx => {
159− let stx = new Tx(tx);
160− stx.sign(Buffer.from(fromWallet.privateKey, 'hex'));
161− return {
162− raw: hexify(stx.serialize()),
163− signed: stx,
164− };
165− });
163+ console.log(txs);
164+
165+ let txPairs = await Promise.all(
166+ txs.map(async (tx, idx) => {
167+ const stx = await signTransaction({
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+ }
181+ return {
182+ raw: hexify(stx.serialize()),
183+ signed: stx,
184+ };
185+ })
186+ );
187+
188+ inviteNonce = inviteNonce + txs.length;
166189
167190 //
168191 // ensuring funding for transactions
@@ -186,7 +209,8 @@ export async function reticketPointBetweenWallets({
186209
187210 progress(TRANSACTION_PROGRESS.TRANSFERRING);
188211
189− await sendAndAwaitAll(web3, txPairs.map(p => p.signed), usedTank);
212+ console.log(txPairs);
213+ await sendAndAwaitAllSerial(web3, txPairs.map(p => p.signed), usedTank);
190214
191215 //
192216 // move leftover eth
@@ -200,17 +224,24 @@ export async function reticketPointBetweenWallets({
200224 const sendEthCost = gasPriceBN.mul(toBN(gasLimit));
201225 if (transferEth && balance.gt(sendEthCost)) {
202226 const value = balance.sub(sendEthCost);
203− const tx = {
227+ const txn = {
204228 to: toWallet.ownership.keys.address,
205229 value: value,
230+ };
231+ const stx = signTransaction({
232+ wallet: fromWallet,
233+ walletType: fromWalletType,
234+ walletHdPath: fromWalletHdPath,
235+ txn,
236+ chainId,
237+ networkType,
206238 gasPrice: gasPriceBN,
207− gas: gasLimit,
239+ gasLimit,
208240 nonce: inviteNonce++,
209− };
210− let stx = new Tx(tx);
211− stx.sign(fromWallet.privateKey);
212− const rawTx = hexify(stx.serialize());
213− web3.eth.sendSignedTransaction(rawTx).catch(err => {
241+ });
242+ // let stx = new Tx(tx);
243+ // stx.sign(fromWallet.privateKey);
244+ sendSignedTransaction(web3, stx).catch(err => {
214245 console.log('error sending value tx, who cares', err);
215246 });
216247 }
src/lib/txn.js+12
@@ -172,6 +172,17 @@ const sendAndAwaitAll = (web3, stxs, doubtNonceError) => {
172172 );
173173};
174174
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+
175186const sendTransactionsAndAwaitConfirm = async (web3, signedTxs, usedTank) =>
176187 Promise.all(signedTxs.map(tx => sendSignedTransaction(web3, tx, usedTank)));
177188
@@ -214,6 +225,7 @@ export {
214225 waitForTransactionConfirm,
215226 sendTransactionsAndAwaitConfirm,
216227 sendAndAwaitAll,
228+ sendAndAwaitAllSerial,
217229 getTxnInfo,
218230 hexify,
219231 renderSignedTx,
src/views/Admin/Reticket/ReticketExecute.js+11−1
@@ -44,7 +44,14 @@ const labelForProgress = progress => {
4444export default function ReticketExecute({ newWallet, setNewWallet }) {
4545 const { popTo, names, reset } = useHistory();
4646 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();
4855 const { pointCursor } = usePointCursor();
4956 const { getDetails } = usePointCache();
5057
@@ -64,6 +71,8 @@ export default function ReticketExecute({ newWallet, setNewWallet }) {
6471 try {
6572 await reticketPointBetweenWallets({
6673 fromWallet: need.wallet(wallet),
74+ fromWalletType: walletType,
75+ fromWalletHdPath: walletHdPath,
6776 toWallet: newWallet.value.wallet,
6877 point: point,
6978 web3: need.web3(web3),
@@ -73,6 +82,7 @@ export default function ReticketExecute({ newWallet, setNewWallet }) {
7382 nextRevision: networkRevision + 1,
7483 });
7584 } catch (err) {
85+ console.error(err);
7686 setGeneralError(err);
7787 }
7888 })();