on d6291a2 help sign in
bridge/src/components/Transaction/StatelessSigner.js
194 lines 4.9 kB history raw
1import Tx from 'ethereumjs-tx'
2import React from 'react'
3import Web3 from 'web3'
4import { Button } from '../Base'
5import { Input, InnerLabel } from '../Base'
7import { ledgerSignTransaction } from '../../lib/ledger'
8import { WALLET_NAMES, addressFromSecp256k1Public } from '../../lib/wallet'
9import { BRIDGE_ERROR } from '../../lib/error'
11class Signer extends React.Component {
12 constructor(props) {
13 super(props)
15 // this.state = {
16 // nonce: '',
17 // gasPrice: '5',
18 // chainId: '',
19 // gasLimit: '600000'
20 // }
22 const dummy = new Web3()
23 this.toHex = dummy.utils.toHex
24 this.toWei = dummy.utils.toWei
25 this.fromWei = dummy.utils.fromWei
27 this.handleNonceInput = this.handleNonceInput.bind(this)
28 this.handleChainIdInput = this.handleChainIdInput.bind(this)
29 this.handleGasPriceInput = this.handleGasPriceInput.bind(this)
30 this.handleGasLimitInput = this.handleGasLimitInput.bind(this)
31 this.signTransaction = this.signTransaction.bind(this)
32 }
34 componentDidMount() {
35 const { web3, wallet } = this.props
37 const addr = wallet.matchWith({
38 Just: (wal) => addressFromSecp256k1Public(wal.value.publicKey),
39 Nothing: () => {
40 throw BRIDGE_ERROR.MISSING_WALLET
41 }
42 })
44 web3.map(w3 =>
45 this.getTxnInfo(w3, addr)
46 .then(txInfo => this.setState(txInfo))
47 )
48 }
50 getTxnInfo = async (web3, addr) => {
51 let nonce = await web3.eth.getTransactionCount(addr)
52 let chainId = await web3.eth.net.getId()
53 let gasPrice = await web3.eth.getGasPrice()
54 return {
55 nonce: nonce,
56 chainId: chainId,
57 gasPrice: this.fromWei(gasPrice, 'gwei')
58 }
59 }
61 handleNonceInput(nonce) {
62 this.setState({ nonce })
63 }
65 handleChainIdInput(chainId) {
66 this.setState({ chainId })
67 }
69 handleGasPriceInput(gasPrice) {
70 this.setState({ gasPrice })
71 }
73 handleGasLimitInput(gasLimit) {
74 this.setState({ gasLimit })
75 }
77 async signTransaction(signingArgs) {
78 const { wallet, walletType, txn, setSignedTransaction } = this.props
80 let { nonce, chainId, gasPrice, gasLimit } = signingArgs
81 nonce = this.toHex(nonce)
82 chainId = this.toHex(chainId)
83 gasPrice = this.toHex(this.toWei(gasPrice, 'gwei'))
84 gasLimit = this.toHex(gasLimit)
86 const wal = wallet.matchWith({
87 Just: (w) => w.value,
88 Nothing: () => {
89 throw BRIDGE_ERROR.MISSING_WALLET
90 }
91 })
93 const sec = wal.privateKey
95 const utx = txn.matchWith({
96 Just: (tx) =>
97 Object.assign(tx.value, { nonce, chainId, gasPrice, gasLimit }),
98 Nothing: () => {
99 throw BRIDGE_ERROR.MISSING_TXN
100 }
101 })
103 const stx = new Tx(utx)
105 if (walletType === WALLET_NAMES.LEDGER) {
106 await ledgerSignTransaction(stx)
107 } else {
108 stx.sign(sec)
109 }
111 setSignedTransaction(stx)
112 }
114 render() {
116 const { state, props } = this
118 const signingArgs = {
119 nonce: props.nonce,
120 gasPrice: props.gasPrice,
121 gasLimit: props.gasLimit,
122 chainId: props.chainId,
123 }
127 return (
128 <React.Fragment>
129 <Input
130 className='mono mt-4'
131 prop-size='md'
132 prop-format='innerLabel'
133 value={ props.gasPrice }
134 onChange={ v => this.handleGasPriceInput(v) }>
135 <InnerLabel>
136 { 'Gas Price (gwei)' }
137 </InnerLabel>
138 </Input>
140 <Input
141 className='mono mt-4'
142 prop-size='md'
143 prop-format='innerLabel'
144 value={ props.gasLimit }
145 onChange={ v => this.handleGasLimitInput(v) }>
146 <InnerLabel>
147 { 'Gas Limit' }
148 </InnerLabel>
149 </Input>
151 {
152 props.web3.matchWith({
153 Just: () => <div />,
154 Nothing: () =>
155 <React.Fragment>
156 <Input
157 className='mono'
158 prop-size='md'
159 prop-format='innerLabel'
160 value={ props.nonce }
161 onChange={ v => this.handleNonceInput(v) }>
162 <InnerLabel>
163 { 'Nonce' }
164 </InnerLabel>
165 </Input>
167 <Input
168 className='mono mt-4 mb-8'
169 prop-size='md'
170 prop-format='innerLabel'
171 value={ props.chainId }
172 onChange={ v => this.handleChainIdInput(v) }>
173 <InnerLabel>
174 { 'Chain ID' }
175 </InnerLabel>
176 </Input>
178 </React.Fragment>
179 })
180 }
182 <Button
183 disabled={ props.disabled }
184 prop-size={'lg wide'}
185 prop-color={this.props['prop-color']}
186 onClick={ () => this.signTransaction(signingArgs) }>
187 { 'Sign Transaction' }
188 </Button>
189 </React.Fragment>
190 )
191 }
194export default Signer