1import * as ob from 'urbit-ob';
2import { Just } from 'folktale/maybe';
3import Tx from 'ethereumjs-tx';
4import { toWei, fromWei, toHex } from 'web3-utils';
6import { BRIDGE_ERROR } from './error';
7import { NETWORK_TYPES } from './network';
8import { ledgerSignTransaction } from './ledger';
9import { trezorSignTransaction } from './trezor';
10import { WALLET_TYPES, addHexPrefix } from './wallet';
13 SET_MANAGEMENT_PROXY: Symbol('SET_MANAGEMENT_PROXY'),
14 SET_TRANSFER_PROXY: Symbol('SET_TRANSFER_PROXY'),
15 SET_SPAWN_PROXY: Symbol('SET_SPAWN_PROXY'),
16 CREATE_GALAXY: Symbol('CREATE_GALAXY'),
17 ISSUE_CHILD: Symbol('ISSUE_CHILD'),
18 SET_KEYS: Symbol('SET_KEYS'),
19 TRANSFER: Symbol('TRANSFER'),
20 CANCEL_TRANSFER: Symbol('CANCEL_TRANSFER'),
23const renderTxnPurpose = purpose =>
24 purpose === TXN_PURPOSE.SET_MANAGEMENT_PROXY
25 ? 'set this management proxy'
26 : purpose === TXN_PURPOSE.SET_SPAWN_PROXY
27 ? 'set this spawn proxy'
28 : purpose === TXN_PURPOSE.SET_TRANSFER_PROXY
29 ? 'set this transfer proxy'
30 : purpose === TXN_PURPOSE.CREATE_GALAXY
31 ? 'create this galaxy'
32 : purpose === TXN_PURPOSE.ISSUE_CHILD
34 : purpose === TXN_PURPOSE.SET_KEYS
35 ? 'set these network keys'
36 : purpose === TXN_PURPOSE.TRANSFER
37 ? 'transfer this point'
38 : purpose === TXN_PURPOSE.CANCEL_TRANSFER
39 ? 'cancel this transfer'
40 : 'perform this transaction';
42const signTransaction = async config => {
57 chainId = toHex(chainId);
58 gasPrice = toHex(toWei(gasPrice, 'gwei'));
59 gasLimit = toHex(gasLimit);
61 const txParams = { nonce, chainId, gasPrice, gasLimit };
65 // Ledger does not seem to handle EIP-155 automatically. When using a Ledger,
66 // if the block number is at least FORK_BLKNUM = 2675000, one needs to
67 // pre-set the ECDSA signature parameters with r = 0, s = 0, and v = chainId
70 // The easiest way to handle this is to just branch on the network, since
71 // mainnet and Ropsten have obviously passed FORK_BLKNUM. This is somewhat
72 // awkward when dealing with offline transactions, since we might want to
73 // test them on a local network as well.
75 // The best thing to do is probably to add an 'advanced' tab to offline
76 // transaction generation where one can disable the defaulted-on EIP-155
77 // settings in this case. This is pretty low-priority, but is a
78 // comprehensive solution.
82 // See https://github.com/LedgerHQ/ledgerjs/issues/43#issuecomment-366984725
84 // https://github.com/ethereum/EIPs/blob/master/EIPS/eip-155.md
86 const eip155Params = {
92 const defaultEip155Networks = [
93 NETWORK_TYPES.MAINNET,
94 NETWORK_TYPES.ROPSTEN,
95 NETWORK_TYPES.OFFLINE,
98 const needEip155Params =
99 walletType === WALLET_TYPES.LEDGER &&
100 defaultEip155Networks.includes(networkType);
102 const signingParams = needEip155Params
103 ? Object.assign(txParams, eip155Params)
106 const wal = wallet.matchWith({
109 throw BRIDGE_ERROR.MISSING_WALLET;
113 const sec = wal.privateKey;
115 const utx = txn.matchWith({
116 Just: tx => Object.assign(tx.value, signingParams),
118 throw BRIDGE_ERROR.MISSING_TXN;
122 const stx = new Tx(utx);
124 if (walletType === WALLET_TYPES.LEDGER) {
125 await ledgerSignTransaction(stx, walletHdPath);
126 } else if (walletType === WALLET_TYPES.TREZOR) {
127 await trezorSignTransaction(stx, walletHdPath);
136const sendSignedTransaction = (web3, stx, doubtNonceError, confirmationCb) => {
137 const txn = stx.matchWith({
138 Just: tx => tx.value,
140 throw BRIDGE_ERROR.MISSING_TXN;
144 const rawTx = addHexPrefix(txn.serialize().toString('hex'));
146 return new Promise(async (resolve, reject) => {
148 .sendSignedTransaction(rawTx)
149 .on('transactionHash', hash => {
152 //TODO do we also reach this if network is slow? web3 only tries a set
153 // amount of times... should we instead do waitForTransactionConfirm
154 // in on-transactionHash? we don't care (much) about additional
156 .on('confirmation', (confirmationNum, txn) => {
157 confirmationCb(txn.transactionHash, confirmationNum + 1);
158 resolve(txn.transactionHash);
160 .on('error', err => {
161 // if there's a nonce error, but we used the gas tank, it's likely
162 // that it's because the tank already submitted our transaction.
163 // we just wait for first confirmation here.
164 console.log('sent and got error', err);
167 (err.message || '').includes("the tx doesn't have the correct nonce.")
169 console.log('nonce error, likely from gas tank submission, ignoring');
170 const txHash = web3.utils.keccak256(rawTx);
171 //TODO can we do does-exists check first?
172 //TODO max wait time before assume fail?
173 waitForTransactionConfirm(web3, txHash).then(res => {
176 confirmationCb(txHash, 1);
178 reject('Unexpected tx failure');
188// returns a Promise<bool>, where the bool indicates tx success/failure
189const waitForTransactionConfirm = (web3, txHash) => {
190 return new Promise((resolve, reject) => {
191 const checkForConfirm = async () => {
192 console.log('checking for confirm', txHash);
193 const receipt = await web3.eth.getTransactionReceipt(txHash);
194 console.log('tried, got', receipt);
195 let confirmed = receipt !== null;
196 if (confirmed) resolve(receipt.status === true);
197 else setTimeout(checkForConfirm, 13000);
203const isTransactionConfirmed = async (web3, txHash) => {
204 const receipt = await web3.eth.getTransactionReceipt(txHash);
205 console.log('got confirm state', receipt !== null, receipt.confirmations);
206 return receipt !== null;
209const hexify = val => addHexPrefix(val.toString('hex'));
211const renderSignedTx = stx => ({
212 messageHash: hexify(stx.hash()),
216 rawTransaction: hexify(stx.serialize()),
219const getTxnInfo = async (web3, addr) => {
220 let nonce = await web3.eth.getTransactionCount(addr);
221 let chainId = await web3.eth.net.getId();
222 let gasPrice = await web3.eth.getGasPrice();
226 gasPrice: fromWei(gasPrice, 'gwei'),
230const canDecodePatp = p => {
241 sendSignedTransaction,
242 waitForTransactionConfirm,
243 isTransactionConfirmed,
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