on d6291a2 help sign in
bridge/src/lib/txn.js
228 lines 4.9 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 {
10 WALLET_NAMES,
11 addHexPrefix
12 } from '../lib/wallet'
15const TXN_PURPOSE = {
16 SET_MANAGEMENT_PROXY: Symbol('SET_MANAGEMENT_PROXY'),
17 SET_TRANSFER_PROXY: Symbol('SET_TRANSFER_PROXY'),
18 SET_SPAWN_PROXY: Symbol('SET_SPAWN_PROXY'),
19 CREATE_GALAXY: Symbol('CREATE_GALAXY'),
20 ISSUE_CHILD: Symbol('ISSUE_CHILD'),
21 SET_KEYS: Symbol('SET_KEYS'),
22 TRANSFER: Symbol('TRANSFER'),
23 CANCEL_TRANSFER: Symbol('CANCEL_TRANSFER')
26const renderTxnPurpose = (purpose) =>
27 purpose === TXN_PURPOSE.SET_MANAGEMENT_PROXY
28 ? 'set this management proxy'
29 : purpose === TXN_PURPOSE.SET_SPAWN_PROXY
30 ? 'set this spawn proxy'
31 : purpose === TXN_PURPOSE.SET_TRANSFER_PROXY
32 ? 'set this transfer proxy'
33 : purpose === TXN_PURPOSE.CREATE_GALAXY
34 ? 'create this galaxy'
35 : purpose === TXN_PURPOSE.ISSUE_CHILD
36 ? 'issue this point'
37 : purpose === TXN_PURPOSE.SET_KEYS
38 ? 'set these network keys'
39 : purpose === TXN_PURPOSE.TRANSFER
40 ? 'transfer this point'
41 : purpose === TXN_PURPOSE.CANCEL_TRANSFER
42 ? 'cancel this transfer'
43 : 'perform this transaction'
49// const createUnsignedTxn = config => {
50// const {
51// contracts,
52// galaxyName,
53// add,
54// setTxn
55// } = config
56//
57// const ctrcs = contracts.matchWith({
58// Just: (cs) => cs.value,
59// Nothing: () => {
60// throw BRIDGE_ERROR.MISSING_CONTRACTS
61// }
62// })
63//
64// const galaxy = parseInt(ob.patp2dec(galaxyName), 10)
65//
66// const txn = isValidGalaxy(galaxyName) && isValidAddress(galaxyOwner)
67// ? Maybe.Just(azimuth.ecliptic.createGalaxy(ctrcs, galaxy, galaxyOwner))
68// : Maybe.Nothing()
69//
70// setTxn(txn)
71// }
74const signTransaction = async config => {
76 let {
77 wallet,
78 walletType,
79 txn,
80 setStx,
81 nonce,
82 chainId,
83 gasPrice,
84 gasLimit
85 } = config
87 nonce = toHex(nonce)
88 chainId = toHex(chainId)
89 gasPrice = toHex(toWei(gasPrice, 'gwei'))
90 gasLimit = toHex(gasLimit)
92 const wal = wallet.matchWith({
93 Just: (w) => w.value,
94 Nothing: () => {
95 throw BRIDGE_ERROR.MISSING_WALLET
96 }
97 })
99 const sec = wal.privateKey
101 const utx = txn.matchWith({
102 Just: (tx) =>
103 Object.assign(tx.value, { nonce, chainId, gasPrice, gasLimit }),
104 Nothing: () => {
105 throw BRIDGE_ERROR.MISSING_TXN
106 }
107 })
109 const stx = new Tx(utx)
111 if (walletType === WALLET_NAMES.LEDGER) {
112 await ledgerSignTransaction(stx)
113 } else {
114 stx.sign(sec)
115 }
117 setStx(Maybe.Just(stx))
122const sendSignedTransaction = (web3, stx) => {
123 const txn = stx.matchWith({
124 Just: (tx) => tx.value,
125 Nothing: () => {
126 throw BRIDGE_ERROR.MISSING_TXN
127 }
128 })
130 const serializedTx = addHexPrefix(txn.serialize().toString('hex'))
132 return new Promise((resolve, reject) => {
133 web3.eth.sendSignedTransaction(serializedTx)
134 .on('receipt', txn =>
135 resolve(Maybe.Just(Result.Ok(txn)))
136 )
137 .on('error', err => {
138 reject(Maybe.Just(Result.Error(err.message)))
139 })
140 })
143const hexify = val => addHexPrefix(val.toString('hex'))
145const renderSignedTx = stx => ({
146 messageHash: hexify(stx.hash()),
147 v: hexify(stx.v),
148 s: hexify(stx.s),
149 r: hexify(stx.r),
150 rawTransaction: hexify(stx.serialize())
151})
153const getTxnInfo = async (web3, addr) => {
154 let nonce = await web3.eth.getTransactionCount(addr)
155 let chainId = await web3.eth.net.getId()
156 let gasPrice = await web3.eth.getGasPrice()
157 return {
158 nonce: nonce,
159 chainId: chainId,
160 gasPrice: fromWei(gasPrice, 'gwei')
161 }
164const dummy = new Web3()
165const toHex = dummy.utils.toHex
166const toWei = dummy.utils.toWei
167const fromWei = dummy.utils.fromWei
170// const confirmShipAvailability = (point, contracts) => {
171//
172// if (canDecodePatp(point) === true) {
173//
174// const pointDec = ob.patp2dec(point)
175//
176// contracts.matchWith({
177// Nothing: () => {
178// throw BRIDGE_ERROR.MISSING_CONTRACTS
179// },
180// Just: async (contracts) => {
181// const owner = await azimuth.azimuth.getOwner(contracts.value, point)
182// if (eqAddr(owner, ETH_ZERO_ADDR)) return true
183// return false
184// }
185// })
186// }
187// return false
188// }
191const canDecodePatp = p => {
192 try {
193 ob.patp2dec(p)
194 return true
195 } catch (_) {
196 return false
197 }
204// const bridgeAPI = {
205// shipAvailability: {
206// planet: planet => {},
207// star: star => {},
208// galaxy: galaxy => {},
209// },
210// // dummyWeb3: {
211// //
212// // }
213// }
215export {
216 signTransaction,
217 sendSignedTransaction,
218 TXN_PURPOSE,
219 getTxnInfo,
220 renderTxnPurpose,
221 hexify,
222 renderSignedTx,
223 toHex,
224 toWei,
225 fromWei,
226 canDecodePatp,
227 // confirmShipAvailability,