on 6ecd461 help sign in
bridge/src/components/InlineEthereumTransaction.js
214 lines 5.8 kB history raw
1import React, { useEffect } from 'react';
2import cn from 'classnames';
3import {
4 Grid,
5 ToggleInput,
6 ErrorText,
7 Flex,
8 LinkButton,
9 H5,
10 Text,
11 HelpText,
12} from 'indigo-react';
13import { fromWei } from 'web3-utils';
15import { useCheckboxInput } from 'lib/useInputs';
16import { useExploreTxUrl } from 'lib/explorer';
17import { hexify } from 'lib/txn';
19import { GenerateButton, ForwardButton, RestartButton } from './Buttons';
20import WarningBox from './WarningBox';
22export default function InlineEthereumTransaction({
23 // from useEthereumTransaction.bind
24 initializing,
25 canSign,
26 generateAndSign,
27 signed,
28 broadcast,
29 broadcasted,
30 confirmed,
31 reset,
32 error,
33 gasPrice,
34 setGasPrice,
35 resetGasPrice,
36 txHash,
37 nonce,
38 chainId,
39 needFunds,
40 signedTransaction,
42 // additional from parent
43 label = 'Generate & Sign Transaction',
44 className,
45 onReturn,
46}) {
47 // show receipt after successful broadcast
48 const showReceipt = broadcasted || confirmed;
49 // show configure controls pre-broadcast
50 const showConfigureInput = !(signed || broadcasted || confirmed);
51 // show signed tx only when signing (for offline usage)
52 const showSignedTx = signed;
54 const exploreTxUrl = useExploreTxUrl(txHash);
55 const [advancedInput, { data: advancedOpen }] = useCheckboxInput({
56 name: 'advanced',
57 label: 'Advanced Configuration',
58 inverseLabel: 'Cancel Advanced Configuration',
59 disabled: !showConfigureInput,
60 });
62 const [
63 viewSignedTransaction,
64 { data: signedTransactionOpen },
65 ] = useCheckboxInput({
66 name: 'viewsigned',
67 label: 'View Signed Transaction',
68 inverseLabel: 'Hide Signed Transaction',
69 disabled: !showSignedTx,
70 });
72 // reset gas price when closing advanced configuration
73 useEffect(() => {
74 if (!advancedOpen) {
75 resetGasPrice();
76 }
77 }, [advancedOpen, resetGasPrice]);
79 const renderPrimaryButton = () => {
80 if (error) {
81 return (
82 <Grid.Item full as={RestartButton} solid onClick={() => reset()}>
83 Reset Transaction
84 </Grid.Item>
85 );
86 } else if (confirmed) {
87 return (
88 <>
89 <Grid.Divider />
90 <Grid.Item full as={RestartButton} onClick={onReturn}>
91 Return
92 </Grid.Item>
93 </>
94 );
95 } else if (signed || broadcasted) {
96 return (
97 <Grid.Item
98 full
99 as={ForwardButton}
100 solid
101 success
102 disabled={broadcasted || needFunds}
103 loading={broadcasted || needFunds}
104 onClick={() => broadcast()}>
105 Send Transaction
106 </Grid.Item>
107 );
108 } else {
109 return (
110 <Grid.Item
111 full
112 as={GenerateButton}
113 onClick={generateAndSign}
114 disabled={!canSign}
115 loading={!canSign && initializing}>
116 {label}
117 </Grid.Item>
118 );
119 }
120 };
122 return (
123 <Grid className={cn(className, 'mt1')}>
124 {renderPrimaryButton()}
126 {error && (
127 <Grid.Item full as={ErrorText} className="mt1">
128 {error.message}
129 </Grid.Item>
130 )}
132 {needFunds && (
133 <Grid.Item full as={WarningBox} className="mt3">
134 The address {needFunds.address} needs at least{' '}
135 {fromWei(needFunds.minBalance)} ETH and currently has{' '}
136 {fromWei(needFunds.balance)} ETH. Waiting until the account has enough
137 funds.
138 </Grid.Item>
139 )}
141 {showConfigureInput && (
142 <>
143 <Grid.Item full as={ToggleInput} {...advancedInput} />
144 {advancedOpen && (
145 <>
146 <Grid.Item full as={Flex} row justify="between" className="mt2">
147 <Flex.Item as={H5}>Gas Price</Flex.Item>
148 <Flex.Item as={H5}>{gasPrice} Gwei</Flex.Item>
149 </Grid.Item>
150 {/* TODO(shrugs): move to indigo/RangeInput */}
151 <Grid.Item
152 full
153 as="input"
154 type="range"
155 min="1"
156 max="100"
157 value={gasPrice}
158 onChange={e => setGasPrice(parseInt(e.target.value, 10))}
159 />
160 <Grid.Item
161 full
162 as={Flex}
163 row
164 justify="between"
165 className="f6 mt1">
166 <Flex.Item as={Text}>Cheap</Flex.Item>
167 <Flex.Item as={Text}>Fast</Flex.Item>
168 </Grid.Item>
169 <Grid.Item full as={HelpText} className="mt3">
170 Nonce: {nonce}
171 </Grid.Item>
172 <Grid.Item full as={HelpText} className="mt1">
173 Chain ID: {chainId}
174 </Grid.Item>
175 <Grid.Divider className="mt3" />
176 </>
177 )}
178 </>
179 )}
181 {showSignedTx && (
182 <>
183 <Grid.Item full as={ToggleInput} {...viewSignedTransaction} />
184 {signedTransactionOpen && (
185 <Grid.Item full as="code" className="f6 mono gray4 wrap">
186 {hexify(signedTransaction.serialize())}
187 </Grid.Item>
188 )}
189 </>
190 )}
192 {showReceipt && (
193 <>
194 <Grid.Divider />
195 <Grid.Item full as={Flex} col className="pv4">
196 <Flex.Item as={Flex} row justify="between">
197 <Flex.Item as={H5}>Transaction Hash</Flex.Item>
198 <Flex.Item as={LinkButton} href={exploreTxUrl}>
199 Etherscan↗
200 </Flex.Item>
201 </Flex.Item>
202 <Flex.Item as={Flex}>
203 <Flex.Item flex as="code" className="f6 mono gray4 wrap">
204 {txHash}
205 </Flex.Item>
206 <Flex.Item flex />
207 </Flex.Item>
208 </Grid.Item>
209 <Grid.Divider />
210 </>
211 )}
212 </Grid>
213 );