on 433bf9e help sign in
bridge/src/components/InlineEthereumTransaction.js
293 lines 8.7 kB history raw
1import React, { useMemo, useCallback } from 'react';
2import cn from 'classnames';
3import {
4 Grid,
5 ToggleInput,
6 ErrorText,
7 Flex,
8 LinkButton,
9 H5,
10 Text,
11} from 'indigo-react';
12import { fromWei } from 'web3-utils';
14import { useExploreTxUrl } from 'lib/explorer';
15import { hexify } from 'lib/txn';
17import { composeValidator, buildCheckboxValidator } from 'form/validators';
18import BridgeForm from 'form/BridgeForm';
19import Condition from 'form/Condition';
21import { GenerateButton, ForwardButton, RestartButton } from './Buttons';
22import WarningBox from './WarningBox';
23import CopyButton from './CopyButton';
24import ProgressButton from './ProgressButton';
25import CopiableAddress from './CopiableAddress';
26import convertToInt from 'lib/convertToInt';
28export default function InlineEthereumTransaction({
29 // from useEthereumTransaction.bind
30 initializing,
31 canSign,
32 generateAndSign,
33 signed,
34 broadcast,
35 broadcasted,
36 confirmed,
37 completed,
38 reset,
39 error,
40 gasPrice,
41 setGasPrice,
42 resetGasPrice,
43 txHash,
44 nonce,
45 chainId,
46 needFunds,
47 signedTransaction,
48 confirmationProgress,
50 // additional from parent
51 label = 'Generate & Sign Transaction',
52 className,
53 onReturn,
54}) {
55 // show receipt after successful broadcast
56 const showReceipt = broadcasted || confirmed || completed;
57 // show configure controls pre-broadcast
58 const showConfigureInput = !(signed || broadcasted || confirmed || completed);
59 // show the send/loading button while signed, broadcasting, or confirme
60 const showBroadcastButton = signed;
61 const showLoadingButton = broadcasted || confirmed;
62 const canBroadcast = signed && !needFunds;
63 // show signed tx only when signing (for offline usage)
64 const showSignedTx = signed;
66 const exploreTxUrl = useExploreTxUrl(txHash);
68 const validate = useMemo(
69 () =>
70 composeValidator({
71 useAdvanced: buildCheckboxValidator(),
72 viewSigned: buildCheckboxValidator(),
73 }),
74 []
75 );
77 const onValues = useCallback(
78 ({ valid, values, form }) => {
79 if (!values.useAdvanced) {
80 resetGasPrice();
81 }
82 },
83 [resetGasPrice]
84 );
86 const renderPrimarySection = () => {
87 if (error) {
88 return (
89 <Grid.Item full as={RestartButton} solid onClick={() => reset()}>
90 Reset Transaction
91 </Grid.Item>
92 );
93 } else if (completed) {
94 return (
95 <Grid.Item full className="pv4 black f5">
96 Transaction Complete
97 </Grid.Item>
98 );
99 } else if (showBroadcastButton) {
100 return (
101 <Grid.Item
102 full
103 as={ForwardButton}
104 solid
105 success
106 disabled={!canBroadcast}
107 onClick={() => broadcast()}>
108 Send Transaction
109 </Grid.Item>
110 );
111 } else if (showLoadingButton) {
112 return (
113 <Grid.Item
114 full
115 as={ProgressButton}
116 success
117 disabled
118 progress={confirmationProgress}>
119 Sending Transaction
120 </Grid.Item>
121 );
122 } else {
123 return (
124 <Grid.Item
125 full
126 as={GenerateButton}
127 onClick={generateAndSign}
128 disabled={!canSign}
129 loading={!canSign && initializing}>
130 {label}
131 </Grid.Item>
132 );
133 }
134 };
136 const serializedTxHex = useMemo(
137 () => signedTransaction && hexify(signedTransaction.serialize()),
138 [signedTransaction]
139 );
141 return (
142 <Grid className={cn(className, 'mt1')}>
143 <BridgeForm validate={validate} onValues={onValues}>
144 {() => (
145 <>
146 {renderPrimarySection()}
148 {error && (
149 <Grid.Item full as={ErrorText} className="mv1">
150 {error.message}
151 </Grid.Item>
152 )}
154 {needFunds && (
155 <Grid.Item full as={WarningBox} className="mt3">
156 The address{' '}
157 <CopiableAddress>{needFunds.address}</CopiableAddress> needs at
158 least {fromWei(needFunds.minBalance)} ETH and currently has{' '}
159 {fromWei(needFunds.balance)} ETH. Waiting until the account has
160 enough funds.
161 </Grid.Item>
162 )}
164 {showConfigureInput && (
165 <>
166 <Grid.Item
167 full
168 as={ToggleInput}
169 name="useAdvanced"
170 label="Advanced"
171 inverseLabel="Back to Defaults"
172 inverseColor="red3"
173 disabled={!showConfigureInput || initializing}
174 />
176 <Condition when="useAdvanced" is={true}>
177 <Grid.Divider />
178 <Grid.Item
179 full
180 as={Flex}
181 row
182 justify="between"
183 className="mt2">
184 <Flex.Item as={H5}>Gas Price</Flex.Item>
185 <Flex.Item as={H5}>{gasPrice} Gwei</Flex.Item>
186 </Grid.Item>
187 {/* TODO(shrugs): move to indigo/RangeInput */}
188 <Grid.Item
189 full
190 as="input"
191 type="range"
192 min="1"
193 max="100"
194 value={gasPrice}
195 onChange={e =>
196 setGasPrice(convertToInt(e.target.value, 10))
197 }
198 />
199 <Grid.Item
200 full
201 as={Flex}
202 row
203 justify="between"
204 className="f6 mt1">
205 <Flex.Item as={Text}>Cheap</Flex.Item>
206 <Flex.Item as={Text}>Fast</Flex.Item>
207 </Grid.Item>
208 <Grid.Divider className="mt4" />
209 </Condition>
210 </>
211 )}
213 {showSignedTx && (
214 <>
215 <Grid.Item
216 full
217 as={ToggleInput}
218 name="viewSigned"
219 label="Signed Transaction"
220 inverseLabel="Hide"
221 disabled={!showSignedTx}
222 />
223 <Condition when="viewSigned" is={true}>
224 <Grid.Divider />
225 <Grid.Item
226 full
227 as={Flex}
228 justify="between"
229 className="pv4 black f5">
230 <Flex.Item>Nonce</Flex.Item>
231 <Flex.Item>{nonce}</Flex.Item>
232 </Grid.Item>
233 <Grid.Divider />
234 <Grid.Item
235 full
236 as={Flex}
237 justify="between"
238 className="pv4 black f5">
239 <Flex.Item>Gas Price</Flex.Item>
240 <Flex.Item>{gasPrice.toFixed()} Gwei</Flex.Item>
241 </Grid.Item>
242 <Grid.Divider />
243 <Grid.Item
244 full
245 as={Flex}
246 justify="between"
247 className="mt3 mb2">
248 <Flex.Item as={H5}>Signed Transaction Hex</Flex.Item>
249 <Flex.Item as={CopyButton} text={serializedTxHex} />
250 </Grid.Item>
251 <Grid.Item full as="code" className="mb4 f6 mono gray4 wrap">
252 {serializedTxHex}
253 </Grid.Item>
254 <Grid.Divider />
255 </Condition>
256 </>
257 )}
259 {showReceipt && (
260 <>
261 <Grid.Divider />
262 <Grid.Item full as={Flex} col className="pv4">
263 <Flex.Item as={Flex} row justify="between">
264 <Flex.Item as={H5}>Transaction Hash</Flex.Item>
265 <Flex.Item as={LinkButton} href={exploreTxUrl}>
266 Etherscan↗
267 </Flex.Item>
268 </Flex.Item>
269 <Flex.Item as={Flex}>
270 <Flex.Item flex as="code" className="f6 mono gray4 wrap">
271 {txHash}
272 </Flex.Item>
273 <Flex.Item flex />
274 </Flex.Item>
275 </Grid.Item>
276 <Grid.Divider />
277 </>
278 )}
280 {completed && (
281 <>
282 <Grid.Item full as={RestartButton} onClick={onReturn}>
283 Return
284 </Grid.Item>
285 <Grid.Divider />
286 </>
287 )}
288 </>
289 )}
290 </BridgeForm>
291 </Grid>
292 );