import { useMemo, useState, useEffect } from "react";
import {
Box,
Typography,
Link,
Skeleton,
TableContainer,
Table,
Paper,
TableHead,
TableBody,
TableRow,
TableCell,
Modal,
useTheme,
useMediaQuery,
} from "@mui/material";
import { useConfig } from "wagmi";
import { ss58Decode } from "@polkadot-labs/hdkd-helpers";
import { toHex } from "@polkadot-api/utils";
import { PrimaryButton } from "../../components/Button";
import GhostStyledIcon from "../../components/Icon/GhostIcon";
import SwapCard from "../../components/Swap/SwapCard";
import SwapCollection from "../../components/Swap/SwapCollection";
import { ghost } from "../../hooks/staking";
import { useBalance } from "../../hooks/tokens";
import CheckIcon from '@mui/icons-material/Check';
import HourglassBottomIcon from '@mui/icons-material/HourglassBottom';
import CheckCircleIcon from '@mui/icons-material/CheckCircle';
import { DecimalBigNumber } from "../../helpers/DecimalBigNumber";
import { formatNumber, formatCurrency, timeConverter } from "../../helpers";
import { BridgeRoute } from "./BridgeRoute";
const sliceString = (string, first, second) => {
if (!string) return "";
return string.slice(0, first) + "..." + string.slice(second);
}
export const BridgeCardAction = ({
isVerySmallScreen,
isSemiSmallScreen,
chainId,
address,
ghstSymbol,
gatekeeperAddressEmpty,
gatekeeperAddress,
evmNetwork,
connect,
isConfirmed,
setIsConfirmed,
openBridgeModal,
storeTransactionHash,
}) => {
const [isPending, setIsPending] = useState(false);
const [receiver, setReceiver] = useState("");
const [convertedReceiver, setConvertedReceiver] = useState(undefined);
const [amount, setAmount] = useState("");
const config = useConfig();
const incomingFee = Number(evmNetwork?.incoming_fee ?? 0n) / 10000000;
const {
balance: ghstBalance,
refetch: ghstBalanceRefetch
} = useBalance(chainId, "GHST", address);
const chainName = useMemo(() => {
const client = config?.getClient();
return client?.chain?.name;
}, [config]);
const chainNativeCurrency = useMemo(() => {
const client = config?.getClient();
return client?.chain?.nativeCurrency?.symbol;
}, [config]);
const chainExplorerUrl = useMemo(() => {
const client = config?.getClient();
return client?.chain?.blockExplorers?.default?.url;
}, [config]);
const preparedAmount = useMemo(() => {
try {
const result = BigInt(parseFloat(amount) * Math.pow(10, 18));
if (result > ghstBalance._value) {
return ghstBalance._value;
}
return result;
} catch {
return 0n;
}
}, [amount]);
const amountAfterFee = useMemo(() => {
const convertedAmount = parseFloat(amount);
if (!convertedAmount) {
return 0;
}
return convertedAmount * (1 - incomingFee / 100);
}, [amount, incomingFee]);
const isDisabled = useMemo(() => {
let isDisabled = isPending || gatekeeperAddressEmpty;
if (address !== "") {
isDisabled = isDisabled
|| !convertedReceiver
|| preparedAmount === 0n
|| ghstBalance._value < preparedAmount;
}
return isDisabled;
}, [isPending, gatekeeperAddressEmpty, address, convertedReceiver, preparedAmount, ghstBalance]);
const ghostFunds = async () => {
setIsPending(true);
try {
const txHash = await ghost(chainId, address, convertedReceiver, preparedAmount);
if (txHash) {
storeTransactionHash(txHash, receiver, preparedAmount.toString());
}
} finally {
await ghstBalanceRefetch();
setReceiver("");
setAmount("");
setIsPending(false);
}
}
useEffect(() => {
if (isConfirmed) {
setIsConfirmed(false);
ghostFunds();
}
}, [isConfirmed]);
const ghostOrConnect = async () => {
if (address === "") {
connect();
} else if (!isConfirmed) {
openBridgeModal();
}
}
useEffect(() => {
try {
const [publicKey, prefix] = ss58Decode(receiver);
if (prefix !== 1995 && prefix !== 1996) {
throw new Error("bad prefix");
}
setConvertedReceiver(toHex(publicKey));
} catch {
setConvertedReceiver(undefined);
}
}, [receiver])
return (
setReceiver(convertedReceiver ? "" : event.currentTarget.value)}
inputProps={{ "data-testid": "fromInput" }}
placeholder="GHOST address (sf prefixed)"
endString={convertedReceiver
?
: undefined
}
type="text"
maxWidth="100%"
/>}
LowerSwapCard={ setAmount(event.currentTarget.value)}
inputProps={{ "data-testid": "fromInput" }}
endString={"Max"}
endStringOnClick={() => setAmount(ghstBalance.toString())}
maxWidth="100%"
/>}
/>
{gatekeeperAddressEmpty && (
There is no connected gatekeeper on {chainName} network yet.
)}
{!gatekeeperAddressEmpty && (
{!isVerySmallScreen && Gatekeeper:}
{sliceString(gatekeeperAddress, 10, -8)}
)}
{!isVerySmallScreen && Bridge Fee:}
{incomingFee
? {`${incomingFee.toFixed(4)}%`}
:
}
{!isVerySmallScreen && You will get:}
{incomingFee
? {amountAfterFee.toFixed(4)} {ghstSymbol}
:
}
ghostOrConnect()}
>
{address === "" ? "Connect" : isPending ? "Bridging..." : "Bridge" }
)
}
export const BridgeCardHistory = ({
isSemiSmallScreen,
isBigScreen,
filteredStoredTransactions,
ghstSymbol,
blockNumber,
finalityDelay,
setActiveTxIndex
}) => {
const isVeryBigScreen = useMediaQuery("(max-width: 1360px)");
const theme = useTheme();
const background = (index) => {
return index % 2 === 1 ? "" : theme.colors.gray[750];
}
return (
{!(isBigScreen ^ isVeryBigScreen) &&
Transaction
}
Datetime
Status
{filteredStoredTransactions?.map((obj, idx) => (
setActiveTxIndex(idx)}
>
{!(isBigScreen ^ isVeryBigScreen) &&
{formatCurrency(
new DecimalBigNumber(BigInt(obj.amount), 18).toString(),
isSemiSmallScreen ? 3 : 8,
ghstSymbol
)}
{sliceString(
obj.receiverAddress,
isSemiSmallScreen ? 5 : 10,
isSemiSmallScreen ? -3 : -8
)}
}
{new Date(obj.timestamp).toLocaleDateString('en-US')}
{new Date(obj.timestamp).toLocaleTimeString('en-US')}
{Number(blockNumber) - (obj.blockNumber + finalityDelay) < 0 ?
:
}
))}
)
}