on 616e621 help sign in
bridge/src/lib/txn.js
232 lines 5.1 kB history raw
1import * as ob from 'urbit-ob'
2import Maybe from 'folktale/maybe'
3import Result from 'folktale/result'
4import Tx from 'ethereumjs-tx'
5import Web3 from 'web3'
7import { BRIDGE_ERROR } from '../lib/error'
8import { ledgerSignTransaction } from '../lib/ledger'
9import { trezorSignTransaction } from '../lib/trezor'
10import {
11 WALLET_NAMES,
12 addHexPrefix
13 } from '../lib/wallet'
16const TXN_PURPOSE = {
17 SET_MANAGEMENT_PROXY: Symbol('SET_MANAGEMENT_PROXY'),
18 SET_TRANSFER_PROXY: Symbol('SET_TRANSFER_PROXY'),
19 SET_SPAWN_PROXY: Symbol('SET_SPAWN_PROXY'),
20 CREATE_GALAXY: Symbol('CREATE_GALAXY'),
21 ISSUE_CHILD: Symbol('ISSUE_CHILD'),
22 SET_KEYS: Symbol('SET_KEYS'),
23 TRANSFER: Symbol('TRANSFER'),
24 CANCEL_TRANSFER: Symbol('CANCEL_TRANSFER')
27const renderTxnPurpose = (purpose) =>
28 purpose === TXN_PURPOSE.SET_MANAGEMENT_PROXY
29 ? 'set this management proxy'
30 : purpose === TXN_PURPOSE.SET_SPAWN_PROXY
31 ? 'set this spawn proxy'
32 : purpose === TXN_PURPOSE.SET_TRANSFER_PROXY
33 ? 'set this transfer proxy'
34 : purpose === TXN_PURPOSE.CREATE_GALAXY
35 ? 'create this galaxy'
36 : purpose === TXN_PURPOSE.ISSUE_CHILD
37 ? 'issue this point'
38 : purpose === TXN_PURPOSE.SET_KEYS
39 ? 'set these network keys'
40 : purpose === TXN_PURPOSE.TRANSFER
41 ? 'transfer this point'
42 : purpose === TXN_PURPOSE.CANCEL_TRANSFER
43 ? 'cancel this transfer'
44 : 'perform this transaction'
50// const createUnsignedTxn = config => {
51// const {
52// contracts,
53// galaxyName,
54// add,
55// setTxn
56// } = config
57//
58// const ctrcs = contracts.matchWith({
59// Just: (cs) => cs.value,
60// Nothing: () => {
61// throw BRIDGE_ERROR.MISSING_CONTRACTS
62// }
63// })
64//
65// const galaxy = parseInt(ob.patp2dec(galaxyName), 10)
66//
67// const txn = isValidGalaxy(galaxyName) && isValidAddress(galaxyOwner)
68// ? Maybe.Just(azimuth.ecliptic.createGalaxy(ctrcs, galaxy, galaxyOwner))
69// : Maybe.Nothing()
70//
71// setTxn(txn)
72// }
75const signTransaction = async config => {
77 let {
78 wallet,
79 walletType,
80 walletHdPath,
81 txn,
82 setStx,
83 nonce,
84 chainId,
85 gasPrice,
86 gasLimit
87 } = config
89 nonce = toHex(nonce)
90 chainId = toHex(chainId)
91 gasPrice = toHex(toWei(gasPrice, 'gwei'))
92 gasLimit = toHex(gasLimit)
94 const wal = wallet.matchWith({
95 Just: (w) => w.value,
96 Nothing: () => {
97 throw BRIDGE_ERROR.MISSING_WALLET
98 }
99 })
101 const sec = wal.privateKey
103 const utx = txn.matchWith({
104 Just: (tx) =>
105 Object.assign(tx.value, { nonce, chainId, gasPrice, gasLimit }),
106 Nothing: () => {
107 throw BRIDGE_ERROR.MISSING_TXN
108 }
109 })
111 const stx = new Tx(utx)
113 if (walletType === WALLET_NAMES.LEDGER) {
114 await ledgerSignTransaction(stx, walletHdPath)
115 } else if (walletType === WALLET_NAMES.TREZOR) {
116 await trezorSignTransaction(stx, walletHdPath)
117 } else {
118 stx.sign(sec)
119 }
121 setStx(Maybe.Just(stx))
126const sendSignedTransaction = (web3, stx) => {
127 const txn = stx.matchWith({
128 Just: (tx) => tx.value,
129 Nothing: () => {
130 throw BRIDGE_ERROR.MISSING_TXN
131 }
132 })
134 const serializedTx = addHexPrefix(txn.serialize().toString('hex'))
136 return new Promise((resolve, reject) => {
137 web3.eth.sendSignedTransaction(serializedTx)
138 .on('receipt', txn =>
139 resolve(Maybe.Just(Result.Ok(txn)))
140 )
141 .on('error', err => {
142 reject(Maybe.Just(Result.Error(err.message)))
143 })
144 })
147const hexify = val => addHexPrefix(val.toString('hex'))
149const renderSignedTx = stx => ({
150 messageHash: hexify(stx.hash()),
151 v: hexify(stx.v),
152 s: hexify(stx.s),
153 r: hexify(stx.r),
154 rawTransaction: hexify(stx.serialize())
155})
157const getTxnInfo = async (web3, addr) => {
158 let nonce = await web3.eth.getTransactionCount(addr)
159 let chainId = await web3.eth.net.getId()
160 let gasPrice = await web3.eth.getGasPrice()
161 return {
162 nonce: nonce,
163 chainId: chainId,
164 gasPrice: fromWei(gasPrice, 'gwei')
165 }
168const dummy = new Web3()
169const toHex = dummy.utils.toHex
170const toWei = dummy.utils.toWei
171const fromWei = dummy.utils.fromWei
174// const confirmShipAvailability = (point, contracts) => {
175//
176// if (canDecodePatp(point) === true) {
177//
178// const pointDec = ob.patp2dec(point)
179//
180// contracts.matchWith({
181// Nothing: () => {
182// throw BRIDGE_ERROR.MISSING_CONTRACTS
183// },
184// Just: async (contracts) => {
185// const owner = await azimuth.azimuth.getOwner(contracts.value, point)
186// if (eqAddr(owner, ETH_ZERO_ADDR)) return true
187// return false
188// }
189// })
190// }
191// return false
192// }
195const canDecodePatp = p => {
196 try {
197 ob.patp2dec(p)
198 return true
199 } catch (_) {
200 return false
201 }
208// const bridgeAPI = {
209// shipAvailability: {
210// planet: planet => {},
211// star: star => {},
212// galaxy: galaxy => {},
213// },
214// // dummyWeb3: {
215// //
216// // }
217// }
219export {
220 signTransaction,
221 sendSignedTransaction,
222 TXN_PURPOSE,
223 getTxnInfo,
224 renderTxnPurpose,
225 hexify,
226 renderSignedTx,
227 toHex,
228 toWei,
229 fromWei,
230 canDecodePatp,
231 // confirmShipAvailability,