1import React, { useMemo, useCallback, useState } from 'react';
2import cn from 'classnames';
12import { toBN } from 'web3-utils';
14import { ReactComponent as InfoIcon } from 'assets/info.svg';
16import { useExploreTxUrls } from 'lib/explorer';
17import { hexify } from 'lib/txn';
18import { safeFromWei, safeToWei } from 'lib/lib';
20import { composeValidator, buildCheckboxValidator } from 'form/validators';
21import BridgeForm from 'form/BridgeForm';
22import Condition from 'form/Condition';
24import { GenerateButton, ForwardButton, RestartButton } from './Buttons';
25import CopyButton from './CopyButton';
26import ProgressButton from './ProgressButton';
27import { convertToInt } from 'lib/convertToInt';
28import NeedFundsNotice from './NeedFundsNotice';
29import NoticeBox from './NoticeBox';
31export default function InlineEthereumTransaction({
32 // from useEthereumTransaction.bind
57 // additional from parent
58 label = 'Generate & Sign Transaction',
62 // show receipt after successful broadcast
63 const [showReceipt, setShowReceipt] = useState(false);
64 const toggleShowReceipt = useCallback(() => setShowReceipt(!showReceipt), [
68 // show configure controls pre-broadcast
69 const showConfigureInput = !(signed || broadcasted || confirmed || completed);
70 // show the send/loading button while signed, broadcasting, or confirme
71 const showBroadcastButton = signed;
72 const showLoadingButton = broadcasted || confirmed;
73 const canBroadcast = signed && !needFunds;
74 // show signed tx only when signing (for offline usage)
75 const showSignedTx = signed;
77 const [showGasDetails, _setShowGasDetails] = useState(false);
78 const toggleGasDetails = useCallback(
79 () => _setShowGasDetails(!showGasDetails),
80 [_setShowGasDetails, showGasDetails]
83 const validate = useMemo(
86 useAdvanced: buildCheckboxValidator(),
87 viewSigned: buildCheckboxValidator(),
92 const onValues = useCallback(
93 ({ valid, values, form }) => {
94 if (!values.useAdvanced) {
101 const renderPrimarySection = () => {
104 <Grid.Item full as={RestartButton} solid onClick={() => reset()}>
108 } else if (completed) {
112 <Grid.Item full as={RestartButton} onClick={onReturn}>
119 finalCost={finalCost}
120 onClose={toggleShowReceipt}
126 className="underline mv2 pointer"
128 onClick={toggleShowReceipt}>
134 } else if (showBroadcastButton) {
141 disabled={!canBroadcast}
142 onClick={() => broadcast()}>
146 } else if (showLoadingButton) {
153 progress={confirmationProgress}>
162 onClick={generateAndSign}
164 loading={!canSign && initializing}>
171 const serializedTxsHex = useMemo(
173 signedTransactions &&
174 signedTransactions.map(stx => hexify(stx.serialize())),
178 const numTxs = useMemo(() => (unsignedTransactions || []).length || 1, [
179 unsignedTransactions,
181 const maxCost = useMemo(
192 [gasLimit, gasPrice, numTxs]
195 const gasInfo = useMemo(() => {
196 const extra = numTxs === 1 ? '' : `* ${numTxs} txs`;
197 return showGasDetails
198 ? `${gasPrice} Gwei * ${gasLimit} ${extra} = ${maxCost} ETH`
200 }, [showGasDetails, maxCost, gasPrice, gasLimit, numTxs]);
203 <Grid className={cn(className, 'mt1')}>
204 <BridgeForm validate={validate} onValues={onValues}>
207 {renderPrimarySection()}
210 <Grid.Item full as={ErrorText} className="mv1">
224 {showConfigureInput && (
231 inverseLabel="Back to Defaults"
233 disabled={!showConfigureInput || initializing}
236 <Condition when="useAdvanced" is={true}>
237 <Grid.Item full className="mb2"></Grid.Item>
245 <Flex.Item as={H5}>Transaction Fee</Flex.Item>
251 onClick={toggleGasDetails}
256 {/* TODO(shrugs): move to indigo/RangeInput */}
265 setGasPrice(convertToInt(e.target.value, 10))
274 <Flex.Item as={Text}>Cheap</Flex.Item>
275 <Flex.Item as={Text}>Fast</Flex.Item>
277 <Grid.Divider className="mt4" />
282 {showSignedTx && fakeSigned && (
284 <Grid.Item full as={NoticeBox} className="mt2">
285 Your wallet will sign the transaction upon sending it.
290 {showSignedTx && !fakeSigned && (
296 label="Signed Transaction"
298 disabled={!showSignedTx}
300 <Condition when="viewSigned" is={true}>
301 <SignedTransactionList
302 serializedTxsHex={serializedTxsHex}
316function SignedTransactionList({ serializedTxsHex, nonce, maxCost }) {
317 return serializedTxsHex.map((serializedTxHex, i) => (
318 <React.Fragment key={i}>
320 <Grid.Item full as={Flex} justify="between" className="pv4 black f5">
321 <Flex.Item>Nonce</Flex.Item>
322 <Flex.Item>{nonce + i}</Flex.Item>
325 <Grid.Item full as={Flex} justify="between" className="pv4 black f5">
326 <Flex.Item>Transaction Cost</Flex.Item>
327 <Flex.Item>{maxCost} ETH</Flex.Item>
330 <Grid.Item full as={Flex} justify="between" className="mt3 mb2">
331 <Flex.Item as={H5}>Signed Transaction Hex</Flex.Item>
332 <Flex.Item as={CopyButton} text={serializedTxHex} />
334 <Grid.Item full as="code" className="mb4 f6 mono gray4 wrap">
342function TransactionReceipt({ txHashes, finalCost, onClose }) {
343 const txUrls = useExploreTxUrls(txHashes);
346 <Grid.Item full as={Flex} justify="between" className="pv2 black f5">
347 <Flex.Item>Receipt</Flex.Item>
348 <Flex.Item onClick={onClose} className="underline pointer">
352 <Grid.Item full as={Flex} justify="between" className="pv2 black f5">
353 <Flex.Item>Transaction Cost</Flex.Item>
354 <Flex.Item className="mono">{finalCost} ETH</Flex.Item>
357 <Grid.Item full as={Flex} col className="pv4">
358 <Flex.Item as={H5}>Receipt</Flex.Item>
361 txHashes.map((txHash, i) => (
362 <Flex.Item as={Flex} className="mv3">
368 className="f6 mono gray4 wrap ">
371 <Flex.Item className="ml8" as={LinkButton} href={txUrls[i]}>
keysesc to close
- j k
- move down, up
- enter
- open
- esc
- back, or up a level
- 1 2 3 4
- readme, files, commits, refs
- /
- filter
- y
- copy the clone command
- c
- compare the chosen commit with another (or shift-click both)
- ?
- show or hide this list