@@ -1,52 +1,8 @@
1−import Tx from 'ethereumjs-tx';
2−import * as azimuth from 'azimuth-js';
31import * as wg from './walletgen';
4−import * as tank from './tank';
52
63import JSZip from 'jszip';
74import saveAs from 'file-saver';
85
9−import { hexify } from './txn';
10−import { deriveNetworkSeedFromUrbitWallet, deriveNetworkKeys } from './keys';
11−import { addHexPrefix } from './wallet';
12−import { sendAndAwaitAll } from './txn';
13−import {
14− GAS_LIMITS,
15− DEFAULT_GAS_PRICE_GWEI,
16− CRYPTO_SUITE_VERSION,
17−} from './constants';
18−import { toWei } from 'web3-utils';
19−
20−// the initial network key revision is always 1
21−const INITIAL_NETWORK_KEY_REVISION = 1;
22−
23−const TRANSACTION_STATES = {
24− GENERATING: {
25− label: 'Generating Transactions...',
26− progress: 0.0,
27− },
28− SIGNING: {
29− label: 'Signing Transactions...',
30− progress: 0.15,
31− },
32− FUNDING: {
33− label: 'Funding Transactions...',
34− progress: 0.3,
35− },
36− TRANSFERRING: {
37− label: 'Transferring Point...',
38− progress: 0.55,
39− },
40− CLEANING: {
41− label: 'Cleaning Up...',
42− progress: 0.95,
43− },
44− DONE: {
45− label: 'Done',
46− progress: 1.0,
47− },
48−};
49−
506export async function generateWallet(point) {
517 const ticket = await wg.makeTicket(point);
528 const wallet = await wg.generateWallet(point, ticket);
@@ -83,194 +39,3 @@ export async function downloadWallet(paper) {
8339 });
8440 });
8541}
86−
87−export async function reticketPointBetweenWallets({
88− fromWallet,
89− toWallet,
90− point,
91− web3,
92− contracts,
93− onUpdate,
94− transferEth = false,
95−}) {
96− const askForFunding = (address, minBalance, balance) =>
97− onUpdate({
98− type: 'askFunding',
99− value: { address, minBalance, balance },
100− });
101−
102− const gotFunding = () => onUpdate({ type: 'gotFunding' });
103− const progress = state => onUpdate({ type: 'progress', state });
104−
105− //
106− // generate transactions
107− //
108−
109− progress(TRANSACTION_STATES.GENERATING);
110−
111− // transfer to invite wallet, so it can configure
112− //NOTE doing this in the invite wallet instead of the final wallet makes
113− // failure cases "solvable" by just telling the user to fully retry.
114− // in other words, the invite flow is effectively idempotent.
115−
116− //TODO no harm done if we already owned it, but should still get a bool arg
117− // for skipping this, if it isn't too big a burden for callers
118− const transferTmpTx = azimuth.ecliptic.transferPoint(
119− contracts,
120− point,
121− fromWallet.address,
122− false
123− );
124− transferTmpTx.gas = GAS_LIMITS.TRANSFER;
125−
126− // configure networking public keys
127− const seed = await deriveNetworkSeedFromUrbitWallet(
128− toWallet,
129− INITIAL_NETWORK_KEY_REVISION
130− );
131−
132− const networkSeed = seed.matchWith({
133− Nothing: () => {
134− throw new Error('network seed not derived');
135− },
136− Just: p => p.value,
137− });
138−
139− const networkKeys = deriveNetworkKeys(networkSeed);
140−
141− const keysTx = azimuth.ecliptic.configureKeys(
142− contracts,
143− point,
144− addHexPrefix(networkKeys.crypt.public),
145− addHexPrefix(networkKeys.auth.public),
146− CRYPTO_SUITE_VERSION,
147− /* discontinuous */ false
148− );
149− keysTx.gas = GAS_LIMITS.CONFIGURE_KEYS;
150−
151− // configure management proxy
152−
153− const managementTx = azimuth.ecliptic.setManagementProxy(
154− contracts,
155− point,
156− toWallet.management.keys.address
157− );
158− managementTx.gas = GAS_LIMITS.SET_PROXY;
159−
160− // set spawn & voting proxies situationally
161−
162− let txs = [transferTmpTx, keysTx, managementTx];
163− if (
164− azimuth.azimuth.getPointSize(point) !== azimuth.azimuth.PointSize.Planet
165− ) {
166− const spawnTx = azimuth.ecliptic.setSpawnProxy(
167− contracts,
168− point,
169− toWallet.spawn.keys.address
170− );
171− spawnTx.gas = GAS_LIMITS.SET_PROXY;
172− txs.push(spawnTx);
173−
174− if (
175− azimuth.azimuth.getPointSize(point) === azimuth.azimuth.PointSize.Galaxy
176− ) {
177− const votingTx = azimuth.ecliptic.setVotingProxy(
178− contracts,
179− point,
180− toWallet.voting.keys.address
181− );
182− votingTx.gas = GAS_LIMITS.SET_PROXY;
183− txs.push(votingTx);
184− }
185− }
186−
187− // transfer configured point to user's new wallet
188−
189− const transferFinalTx = azimuth.ecliptic.transferPoint(
190− contracts,
191− point,
192− toWallet.ownership.keys.address,
193− false
194− );
195− transferFinalTx.gas = GAS_LIMITS.TRANSFER;
196− txs.push(transferFinalTx);
197−
198− //
199− // finalizing & signing transactions
200− //
201−
202− progress(TRANSACTION_STATES.SIGNING);
203−
204− let totalCost = 0;
205− let inviteNonce = await web3.eth.getTransactionCount(fromWallet.address);
206− txs = txs.map(tx => {
207− tx.from = fromWallet.address;
208− tx.nonce = inviteNonce++;
209− tx.gasPrice = parseInt(toWei(DEFAULT_GAS_PRICE_GWEI.toFixed(), 'gwei'), 10);
210− totalCost = totalCost + tx.gasPrice * tx.gas;
211− return tx;
212− });
213−
214− let txPairs = txs.map(tx => {
215− let stx = new Tx(tx);
216− stx.sign(Buffer.from(fromWallet.privateKey, 'hex'));
217− return {
218− raw: hexify(stx.serialize()),
219− signed: stx,
220− };
221− });
222−
223− //
224− // ensuring funding for transactions
225− //
226−
227− progress(TRANSACTION_STATES.FUNDING);
228−
229− const usedTank = await tank.ensureFundsFor(
230− web3,
231− point,
232− fromWallet.address,
233− totalCost,
234− txPairs.map(p => p.raw),
235− askForFunding,
236− gotFunding
237− );
238−
239− //
240− // sending and awaiting transactions
241− //
242−
243− progress(TRANSACTION_STATES.TRANSFERRING);
244−
245− await sendAndAwaitAll(web3, txPairs.map(p => p.signed), usedTank);
246−
247− //
248− // move leftover eth
249− //
250−
251− progress(TRANSACTION_STATES.CLEANING);
252−
253− // if non-trivial eth left in invite wallet, transfer to new ownership
254− let balance = await web3.eth.getBalance(fromWallet.address);
255− const gasPrice = parseInt(toWei(DEFAULT_GAS_PRICE_GWEI.toFixed(), 'gwei'));
256− const gasLimit = GAS_LIMITS.SEND_ETH;
257− const sendEthCost = gasPrice * gasLimit;
258− if (transferEth && balance > sendEthCost) {
259− const value = balance - sendEthCost;
260− const tx = {
261− to: toWallet.ownership.keys.address,
262− value: value,
263− gasPrice: gasPrice,
264− gas: gasLimit,
265− nonce: inviteNonce++,
266− };
267− let stx = new Tx(tx);
268− stx.sign(fromWallet.privateKey);
269− const rawTx = hexify(stx.serialize());
270− web3.eth.sendSignedTransaction(rawTx).catch(err => {
271− console.log('error sending value tx, who cares', err);
272− });
273− }
274−
275− progress(TRANSACTION_STATES.DONE);
276−}