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