import React, { useMemo, useCallback, useState } from 'react';
import cn from 'classnames';
import {
Grid,
ToggleInput,
ErrorText,
Flex,
LinkButton,
H5,
Button,
} from 'indigo-react';
import { toBN } from 'web3-utils';
import { useExploreTxUrls } from 'lib/explorer';
import { hexify } from 'lib/txn';
import { safeFromWei, gweiToWei } from 'lib/lib';
import { composeValidator, buildCheckboxValidator } from 'form/validators';
import BridgeForm from 'form/BridgeForm';
import Condition from 'form/Condition';
import { GenerateButton, ForwardButton, RestartButton } from './Buttons';
import ProgressButton from './ProgressButton';
import NeedFundsNotice from './NeedFundsNotice';
import NoticeBox from './NoticeBox';
import FeeDropdown from './L2/Dropdowns/FeeDropdown';
import CopyButton from './copiable/CopyButton';
import './InlineEthereumTransaction.scss';
import { useRollerStore } from 'store/rollerStore';
export default function InlineEthereumTransaction({
// from useEthereumTransaction.bind
initializing,
canSign,
generateAndSign,
signed,
fakeSigned,
broadcast,
broadcasted,
confirmed,
completed,
reset,
error,
gasPrice, // Type: GasPriceData
setGasPrice, // Type: (g: GasPriceData) => void
resetGasPrice,
txHashes,
nonce,
chainId,
needFunds,
signedTransactions,
confirmationProgress,
gasLimit,
unsignedTransactions,
finalCost,
// additional from parent
label = 'Generate & Sign Transaction',
className,
onReturn,
}) {
const { ethBalance } = useRollerStore();
// show receipt after successful broadcast
const [showReceipt, setShowReceipt] = useState(false);
const toggleShowReceipt = useCallback(() => setShowReceipt(!showReceipt), [
setShowReceipt,
showReceipt,
]);
// show configure controls pre-broadcast
const showConfigureInput = !(signed || broadcasted || confirmed || completed);
// show the send/loading button while signed, broadcasting, or confirme
const showBroadcastButton = signed;
const showLoadingButton = broadcasted || confirmed;
const canBroadcast = signed && !needFunds;
// show signed tx only when signing (for offline usage)
const showSignedTx = signed;
const validate = useMemo(
() =>
composeValidator({
useAdvanced: buildCheckboxValidator(),
viewSigned: buildCheckboxValidator(),
}),
[]
);
const onValues = useCallback(
({ valid, values, form }) => {
if (!values.useAdvanced) {
resetGasPrice();
}
},
[resetGasPrice]
);
const serializedTxsHex = useMemo(
() =>
signedTransactions &&
signedTransactions.map(stx => hexify(stx.serialize())),
[signedTransactions]
);
const numTxs = useMemo(() => (unsignedTransactions || []).length || 1, [
unsignedTransactions,
]);
const maxCost = useMemo(
() =>
safeFromWei(
toBN(gasLimit)
.mul(gweiToWei(gasPrice.price))
.mul(toBN(numTxs)),
'ether'
),
[gasLimit, gasPrice, numTxs]
);
const insufficientEth = useMemo(
() => Number(maxCost) > Number(ethBalance.toString()),
[maxCost, ethBalance]
);
const renderPrimarySection = () => {
if (error) {
return (
reset()}>
Reset Transaction
);
} else if (completed) {
return (
<>
Return
{showReceipt && (
)}
{!showReceipt && (
View Receipt
)}
>
);
} else if (insufficientEth) {
return (
Insufficient ETH
);
} else if (showBroadcastButton) {
return (
broadcast()}>
Send Transaction
);
} else if (showLoadingButton) {
return (
Sending Transaction
);
} else {
return (
{label}
);
}
};
return (
{() => (
<>
{showConfigureInput && (
<>
Gas Fee
Max Transaction Cost
{maxCost} ETH
>
)}
{renderPrimarySection()}
{error && (
{error.message}
)}
{needFunds && (
)}
{showSignedTx && fakeSigned && (
<>
Your wallet will sign the transaction upon sending it.
>
)}
{showSignedTx && !fakeSigned && (
<>
>
)}
>
)}
);
}
function SignedTransactionList({ serializedTxsHex, nonce, maxCost }) {
return serializedTxsHex.map((serializedTxHex, i) => (
Nonce
{nonce + i}
Transaction Cost
{maxCost} ETH
Signed Transaction Hex
{serializedTxHex}
));
}
function TransactionReceipt({ txHashes, finalCost, onClose }) {
const txUrls = useExploreTxUrls(txHashes);
return (
<>
Receipt
Close
Transaction Cost
{finalCost} ETH
Receipt
{txHashes &&
txHashes.map((txHash, i) => (
<>
{txHash}
Etherscan↗
>
))}
>
);
}