1import * as azimuth from 'azimuth-js';
2import * as tank from './tank';
4import { hexify } from './txn';
6 deriveNetworkSeedFromUrbitWallet,
10import { addHexPrefix } from './wallet';
12 sendAndAwaitAllSerial,
14 sendSignedTransaction,
16import getSuggestedGasPrice from './getSuggestedGasPrice';
17import { GAS_LIMITS } from './constants';
18import { toBN } from 'web3-utils';
19import { safeToWei } from './lib';
21// the initial network key revision is always 1
22const INITIAL_NETWORK_KEY_REVISION = 1;
24export const TRANSACTION_PROGRESS = {
33export async function reticketPointBetweenWallets({
44 nextRevision = INITIAL_NETWORK_KEY_REVISION,
46 const askForFunding = (address, minBalance, balance) =>
49 value: { address, minBalance, balance },
52 const gotFunding = () => onUpdate({ type: 'gotFunding' });
53 const progress = state => onUpdate({ type: 'progress', state });
56 // generate transactions
59 progress(TRANSACTION_PROGRESS.GENERATING);
61 // transfer to invite wallet, so it can configure
62 //NOTE doing this in the invite wallet instead of the final wallet makes
63 // failure cases "solvable" by just telling the user to fully retry.
64 // in other words, the invite flow is effectively idempotent.
66 //TODO no harm done if we already owned it, but should still get a bool arg
67 // for skipping this, if it isn't too big a burden for callers
68 const transferTmpTx = azimuth.ecliptic.transferPoint(
74 transferTmpTx.gas = GAS_LIMITS.TRANSFER;
76 // configure networking public keys
77 const seed = await deriveNetworkSeedFromUrbitWallet(toWallet, nextRevision);
79 const networkSeed = seed.matchWith({
81 throw new Error('network seed not derived');
86 const networkKeys = deriveNetworkKeys(networkSeed);
88 const keysTx = azimuth.ecliptic.configureKeys(
91 addHexPrefix(networkKeys.crypt.public),
92 addHexPrefix(networkKeys.auth.public),
94 /* discontinuous */ false
96 keysTx.gas = GAS_LIMITS.CONFIGURE_KEYS;
98 // configure management proxy
100 const managementTx = azimuth.ecliptic.setManagementProxy(
103 toWallet.management.keys.address
105 managementTx.gas = GAS_LIMITS.SET_PROXY;
107 // set spawn & voting proxies situationally
109 let txs = [transferTmpTx, keysTx, managementTx];
111 azimuth.azimuth.getPointSize(point) !== azimuth.azimuth.PointSize.Planet
113 const spawnTx = azimuth.ecliptic.setSpawnProxy(
116 toWallet.spawn.keys.address
118 spawnTx.gas = GAS_LIMITS.SET_PROXY;
122 azimuth.azimuth.getPointSize(point) === azimuth.azimuth.PointSize.Galaxy
124 const votingTx = azimuth.ecliptic.setVotingProxy(
127 toWallet.voting.keys.address
129 votingTx.gas = GAS_LIMITS.SET_PROXY;
134 // transfer configured point to user's new wallet
136 const transferFinalTx = azimuth.ecliptic.transferPoint(
139 toWallet.ownership.keys.address,
142 transferFinalTx.gas = GAS_LIMITS.TRANSFER;
143 txs.push(transferFinalTx);
146 // finalizing & signing transactions
149 progress(TRANSACTION_PROGRESS.SIGNING);
151 const gasPriceGwei = (await getSuggestedGasPrice(networkType)).toFixed();
152 const chainId = await web3.eth.net.getId();
153 const gasPriceWeiBN = toBN(safeToWei(gasPriceGwei, 'gwei'));
154 let inviteNonce = await web3.eth.getTransactionCount(fromWallet.address);
155 const totalCost = txs.reduce(
156 (acc, tx) => acc.add(gasPriceWeiBN.mul(toBN(tx.gas))),
162 // Must be done in serial else hardware will give nonce errors
163 for (let i = 0; i < txs.length; i++) {
164 const stx = await signTransaction({
166 walletType: fromWalletType,
167 walletHdPath: fromWalletHdPath,
170 nonce: inviteNonce + i,
172 gasPrice: gasPriceGwei,
173 gasLimit: txs[i].gas,
176 raw: hexify(stx.serialize()),
181 inviteNonce = inviteNonce + txs.length;
184 // ensuring funding for transactions
187 progress(TRANSACTION_PROGRESS.FUNDING);
189 const usedTank = await tank.ensureFundsFor(
195 txPairs.map(p => p.raw),
201 // sending and awaiting transactions
204 progress(TRANSACTION_PROGRESS.TRANSFERRING);
206 await sendAndAwaitAllSerial(web3, txPairs.map(p => p.signed), usedTank);
212 progress(TRANSACTION_PROGRESS.CLEANING);
214 // if non-trivial eth left in invite wallet, transfer to new ownership
215 let balance = toBN(await web3.eth.getBalance(fromWallet.address));
216 const gasLimit = GAS_LIMITS.SEND_ETH;
217 const sendEthCost = gasPriceWeiBN.mul(toBN(gasLimit));
218 if (transferEth && balance.gt(sendEthCost)) {
220 const value = balance.sub(sendEthCost);
222 to: toWallet.ownership.keys.address,
225 const stx = await signTransaction({
227 walletType: fromWalletType,
228 walletHdPath: fromWalletHdPath,
232 gasPrice: gasPriceGwei,
236 sendSignedTransaction(web3, stx);
238 console.log('error sending value tx, safely ignored:');
243 progress(TRANSACTION_PROGRESS.DONE);
keysesc to close
- j k
- move down, up
- enter
- open
- esc
- back, or up a level
- 1 2 3 4
- readme, files, commits, refs
- /
- filter
- y
- copy the clone command
- c
- compare the chosen commit with another (or shift-click both)
- ?
- show or hide this list