bump version and apply changes in order to match latest ghost-node and ghost-dao functionality
Signed-off-by: Uncle Fatso <uncle.fatso@ghostchain.io>
This commit is contained in:
parent
1143a3d491
commit
bc5f88d572
@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "ghost-dao-interface",
|
||||
"private": true,
|
||||
"version": "0.1.6",
|
||||
"version": "0.2.0",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"dev": "vite",
|
||||
@ -18,6 +18,8 @@
|
||||
"@mui/icons-material": "^6.4.7",
|
||||
"@mui/material": "^6.4.7",
|
||||
"@mui/utils": "^6.4.6",
|
||||
"@polkadot-api/utils": "~0.1.2",
|
||||
"@polkadot-labs/hdkd-helpers": "^0.0.20",
|
||||
"@tanstack/react-query": "^5.67.2",
|
||||
"@tanstack/react-query-devtools": "^5.67.2",
|
||||
"@wagmi/core": "^2.17.3",
|
||||
|
@ -32,6 +32,12 @@ importers:
|
||||
'@mui/utils':
|
||||
specifier: ^6.4.6
|
||||
version: 6.4.6(@types/react@19.0.10)(react@19.0.0)
|
||||
'@polkadot-api/utils':
|
||||
specifier: 0.1.2
|
||||
version: 0.1.2
|
||||
'@polkadot-labs/hdkd-helpers':
|
||||
specifier: ^0.0.20
|
||||
version: 0.0.20
|
||||
'@tanstack/react-query':
|
||||
specifier: ^5.67.2
|
||||
version: 5.67.2(react@19.0.0)
|
||||
@ -723,6 +729,10 @@ packages:
|
||||
resolution: {integrity: sha512-HxngEd2XUcg9xi20JkwlLCtYwfoFw4JGkuZpT+WlsPD4gB/cxkvTD8fSsoAnphGZhFdZYKeQIPCuFlWPm1uE0g==}
|
||||
engines: {node: ^14.21.3 || >=16}
|
||||
|
||||
'@noble/curves@1.9.6':
|
||||
resolution: {integrity: sha512-GIKz/j99FRthB8icyJQA51E8Uk5hXmdyThjgQXRKiv9h0zeRlzSCLIzFw6K1LotZ3XuB7yzlf76qk7uBmTdFqA==}
|
||||
engines: {node: ^14.21.3 || >=16}
|
||||
|
||||
'@noble/hashes@1.4.0':
|
||||
resolution: {integrity: sha512-V1JJ1WTRUqHHrOSh597hURcMqVKVGL/ea3kv0gSnEdsEZ0/+VyPghM1lMNGc00z7CIQorSvbKpuJkxvuHbvdbg==}
|
||||
engines: {node: '>= 16'}
|
||||
@ -743,6 +753,12 @@ packages:
|
||||
resolution: {integrity: sha512-IHnV6A+zxU7XwmKFinmYjUcwlyK9+xkG3/s9KcQhI9BjQKycrJ1JRO+FbNYPwZiPKW3je/DR0k7w8/gLa5eaxQ==}
|
||||
deprecated: 'The package is now available as "qr": npm install qr'
|
||||
|
||||
'@polkadot-api/utils@0.1.2':
|
||||
resolution: {integrity: sha512-yhs5k2a8N1SBJcz7EthZoazzLQUkZxbf+0271Xzu42C5AEM9K9uFLbsB+ojzHEM72O5X8lPtSwGKNmS7WQyDyg==}
|
||||
|
||||
'@polkadot-labs/hdkd-helpers@0.0.20':
|
||||
resolution: {integrity: sha512-P3o1FpPqLACaHhDT/J6O3xYQIBdOs0FDJtZQI8/LGotgIGp85mKDnH/cSSK3QC2i67ZY/d/POs8K0jEspLMiGg==}
|
||||
|
||||
'@popperjs/core@2.11.8':
|
||||
resolution: {integrity: sha512-P1st0aksCrn9sGZhp8GMYwBnQsbvAWsZAX44oXNNvLHGqAOcoVxmjZiohstwQ7SqKnbR47akdNi+uleWD8+g6A==}
|
||||
|
||||
@ -913,6 +929,9 @@ packages:
|
||||
'@scure/bip39@1.6.0':
|
||||
resolution: {integrity: sha512-+lF0BbLiJNwVlev4eKelw1WWLaiKXw7sSl8T6FvBlWkdX+94aGJ4o8XjUdlyhTCjd8c+B3KT3JfS8P0bLRNU6A==}
|
||||
|
||||
'@scure/sr25519@0.2.0':
|
||||
resolution: {integrity: sha512-uUuLP7Z126XdSizKtrCGqYyR3b3hYtJ6Fg/XFUXmc2//k2aXHDLqZwFeXxL97gg4XydPROPVnuaHGF2+xriSKg==}
|
||||
|
||||
'@socket.io/component-emitter@3.1.2':
|
||||
resolution: {integrity: sha512-9BCxFwvbGg/RsZK9tjXd8s4UcwR0MWeFQ1XEKIQVVvAGJyINdrqKMcTRyLoK8Rse1GjzLV9cwjWV1olXRWEXVA==}
|
||||
|
||||
@ -2375,6 +2394,9 @@ packages:
|
||||
engines: {node: '>=16.0.0'}
|
||||
hasBin: true
|
||||
|
||||
scale-ts@1.6.1:
|
||||
resolution: {integrity: sha512-PBMc2AWc6wSEqJYBDPcyCLUj9/tMKnLX70jLOSndMtcUoLQucP/DM0vnQo1wJAYjTrQiq8iG9rD0q6wFzgjH7g==}
|
||||
|
||||
scheduler@0.25.0:
|
||||
resolution: {integrity: sha512-xFVuu11jh+xcO7JOAGJNOXld8/TcEHK/4CituBUeUb5hqxJLj9YuemAEuvm9gQ/+pgXYfbQuqAkiYu+u7YEsNA==}
|
||||
|
||||
@ -3556,6 +3578,10 @@ snapshots:
|
||||
dependencies:
|
||||
'@noble/hashes': 1.8.0
|
||||
|
||||
'@noble/curves@1.9.6':
|
||||
dependencies:
|
||||
'@noble/hashes': 1.8.0
|
||||
|
||||
'@noble/hashes@1.4.0': {}
|
||||
|
||||
'@noble/hashes@1.7.0': {}
|
||||
@ -3566,6 +3592,16 @@ snapshots:
|
||||
|
||||
'@paulmillr/qr@0.2.1': {}
|
||||
|
||||
'@polkadot-api/utils@0.1.2': {}
|
||||
|
||||
'@polkadot-labs/hdkd-helpers@0.0.20':
|
||||
dependencies:
|
||||
'@noble/curves': 1.9.6
|
||||
'@noble/hashes': 1.8.0
|
||||
'@scure/base': 1.2.6
|
||||
'@scure/sr25519': 0.2.0
|
||||
scale-ts: 1.6.1
|
||||
|
||||
'@popperjs/core@2.11.8': {}
|
||||
|
||||
'@reown/appkit-common@1.7.8(bufferutil@4.0.9)(utf-8-validate@5.0.10)(zod@3.22.4)':
|
||||
@ -3936,6 +3972,11 @@ snapshots:
|
||||
'@noble/hashes': 1.8.0
|
||||
'@scure/base': 1.2.6
|
||||
|
||||
'@scure/sr25519@0.2.0':
|
||||
dependencies:
|
||||
'@noble/curves': 1.9.6
|
||||
'@noble/hashes': 1.8.0
|
||||
|
||||
'@socket.io/component-emitter@3.1.2': {}
|
||||
|
||||
'@svgr/babel-plugin-add-jsx-attribute@8.0.0(@babel/core@7.26.9)':
|
||||
@ -5471,8 +5512,8 @@ snapshots:
|
||||
ox@0.6.7(zod@3.22.4):
|
||||
dependencies:
|
||||
'@adraffy/ens-normalize': 1.11.0
|
||||
'@noble/curves': 1.8.1
|
||||
'@noble/hashes': 1.7.1
|
||||
'@noble/curves': 1.9.2
|
||||
'@noble/hashes': 1.8.0
|
||||
'@scure/bip32': 1.6.2
|
||||
'@scure/bip39': 1.5.4
|
||||
abitype: 1.0.8(zod@3.22.4)
|
||||
@ -5842,6 +5883,8 @@ snapshots:
|
||||
sass-embedded-win32-ia32: 1.85.1
|
||||
sass-embedded-win32-x64: 1.85.1
|
||||
|
||||
scale-ts@1.6.1: {}
|
||||
|
||||
scheduler@0.25.0: {}
|
||||
|
||||
scss@0.2.4:
|
||||
|
@ -27,6 +27,7 @@ const StakeContainer = lazy(() => import("./containers/Stake/StakeContainer"));
|
||||
const TreasuryDashboard = lazy(() => import("./containers/TreasuryDashboard/TreasuryDashboard"));
|
||||
const Faucet = lazy(() => import("./containers/Faucet/Faucet"));
|
||||
const Dex = lazy(() => import("./containers/Dex/Dex"));
|
||||
const Bridge = lazy(() => import("./containers/Bridge/Bridge"));
|
||||
const NotFound = lazy(() => import("./containers/NotFound/NotFound"));
|
||||
|
||||
const PREFIX = "App";
|
||||
@ -187,6 +188,7 @@ function App() {
|
||||
<Route path="/bonds/:id" element={<BondModalContainer connect={tryConnectInjected} address={address} chainId={addressChainId ? addressChainId : chainId} />} />
|
||||
<Route path="/stake" element={<StakeContainer connect={tryConnectInjected} address={address} chainId={addressChainId ? addressChainId : chainId}/>} />
|
||||
<Route path="/faucet" element={<Faucet config={config} connect={tryConnectInjected} address={address} chainId={addressChainId ? addressChainId : chainId} />} />
|
||||
<Route path="/bridge" element={<Bridge config={config} connect={tryConnectInjected} address={address} chainId={addressChainId ? addressChainId : chainId} />} />
|
||||
<Route path="/dex/:name" element={<Dex connect={tryConnectInjected} address={address} chainId={addressChainId ? addressChainId : chainId} />} />
|
||||
</>
|
||||
}
|
||||
|
@ -132,6 +132,7 @@ const NavItem = ({
|
||||
const LinkItem = () => (
|
||||
<Link {...linkProps} {...props} underline="hover">
|
||||
<Box
|
||||
sx={{ fontFamily: "Ubuntu" }}
|
||||
display="flex"
|
||||
flexDirection="row"
|
||||
alignItems="center"
|
||||
|
@ -48,7 +48,7 @@ import DashboardIcon from '@mui/icons-material/Dashboard';
|
||||
import ShowerIcon from '@mui/icons-material/Shower';
|
||||
|
||||
import { useTokenSymbol } from "../../hooks/tokens";
|
||||
import { useFtsoPrice, useGhstPrice } from "../../hooks/prices";
|
||||
import { useFtsoPrice, useGhstPrice, useGhostedSupplyPrice } from "../../hooks/prices";
|
||||
import { useLiveBonds } from "../../hooks/bonds/index";
|
||||
|
||||
const PREFIX = "NavContent";
|
||||
@ -67,6 +67,7 @@ const NavContent = ({ chainId, addressChainId }) => {
|
||||
const { liveBonds: ghostBonds } = useLiveBonds(chainId);
|
||||
const ftsoPrice = useFtsoPrice(chainId);
|
||||
const ghstPrice = useGhstPrice(chainId);
|
||||
const ghostedSupplyPrice = useGhostedSupplyPrice(chainId);
|
||||
|
||||
const { symbol: ftsoSymbol } = useTokenSymbol(chainId, "FTSO");
|
||||
const { symbol: ghstSymbol } = useTokenSymbol(chainId, "GHST");
|
||||
@ -91,6 +92,9 @@ const NavContent = ({ chainId, addressChainId }) => {
|
||||
<Box fontSize="12px" fontWeight="500" lineHeight="15px">
|
||||
{ghstSymbol} Price: {formatCurrency(ghstPrice, 2)}
|
||||
</Box>
|
||||
<Box fontSize="12px" fontWeight="500" lineHeight={"15px"}>
|
||||
Ghosted Supply: {formatCurrency(ghostedSupplyPrice, 2)}
|
||||
</Box>
|
||||
</Box>
|
||||
</Box>
|
||||
|
||||
@ -141,6 +145,7 @@ const NavContent = ({ chainId, addressChainId }) => {
|
||||
/>
|
||||
<NavItem icon={StakeIcon} label={`Stake`} to="/stake" />
|
||||
<NavItem icon={ShowerIcon} label={`Faucet`} to="/faucet" />
|
||||
<NavItem icon={PublicIcon} label={`Bridge`} to="/bridge" />
|
||||
<NavItem
|
||||
icon={CurrencyExchangeIcon}
|
||||
label={`Dex`}
|
||||
@ -171,7 +176,6 @@ const NavContent = ({ chainId, addressChainId }) => {
|
||||
</>
|
||||
}
|
||||
|
||||
<NavItem icon={PublicIcon} label={`Bridge`} href="https://bridge.ghostchain.io/" />
|
||||
<NavItem
|
||||
to=''
|
||||
icon={PublicIcon}
|
||||
|
@ -28,14 +28,14 @@ const StyledArrow = styled(Box)(
|
||||
},
|
||||
);
|
||||
|
||||
const SwapCollection = ({ UpperSwapCard, LowerSwapCard, arrowOnClick }) => {
|
||||
const SwapCollection = ({ UpperSwapCard, LowerSwapCard, arrowOnClick, iconNotNeeded }) => {
|
||||
const theme = useTheme();
|
||||
|
||||
return (
|
||||
<Box display="flex" flexDirection="column" maxWidth="476px">
|
||||
{UpperSwapCard}
|
||||
<Box display="flex" flexDirection="row" justifyContent="center">
|
||||
<StyledArrow
|
||||
{!iconNotNeeded && (<StyledArrow
|
||||
width="21px"
|
||||
height="21px"
|
||||
borderRadius="6px"
|
||||
@ -55,7 +55,8 @@ const SwapCollection = ({ UpperSwapCard, LowerSwapCard, arrowOnClick }) => {
|
||||
}}
|
||||
/>
|
||||
</Box>
|
||||
</StyledArrow>
|
||||
</StyledArrow>)}
|
||||
{iconNotNeeded && <Box height="21px" />}
|
||||
</Box>
|
||||
<Box marginTop="-7px">{LowerSwapCard}</Box>
|
||||
</Box>
|
||||
|
@ -152,7 +152,7 @@ function InitialWalletView({ address, chainId, onClose }) {
|
||||
fullWidth
|
||||
onClick={() => onBtnClick("uniswap", DAI_ADDRESSES[chainId], FTSO_ADDRESSES[chainId])}
|
||||
>
|
||||
<Typography>FTSO-gDAI on Uniswap</Typography>
|
||||
<Typography>{`${tokens?.ftso?.symbol}-${tokens?.dai?.symbol} on Uniswap`}</Typography>
|
||||
</SecondaryButton>
|
||||
</Box>
|
||||
|
||||
|
@ -6,7 +6,6 @@ export const config = createConfig({
|
||||
transports: {
|
||||
[sepolia.id]: fallback([
|
||||
http('https://ethereum-sepolia-rpc.publicnode.com'),
|
||||
http('https://rpc-sepolia.rockx.com/'),
|
||||
http('https://1rpc.io/sepolia'),
|
||||
http('https://eth-sepolia.public.blastapi.io'),
|
||||
http('https://0xrpc.io/sep'),
|
||||
|
@ -1,32 +1,32 @@
|
||||
import { NetworkId } from "../constants";
|
||||
|
||||
export const STAKING_ADDRESSES = {
|
||||
[NetworkId.TESTNET_SEPOLIA]: "0x47b662aC17937938ff8938Fe9513beF38e60E40C",
|
||||
[NetworkId.TESTNET_SEPOLIA]: "0xd90E63E88282596E1ea33765b41Ba3d650f4aD52",
|
||||
[NetworkId.TESTNET_HOODI]: "0x25F62eDc6C89FF84E957C22336A35d2dfc861a86",
|
||||
};
|
||||
|
||||
export const BOND_DEPOSITORY_ADDRESSES = {
|
||||
[NetworkId.TESTNET_SEPOLIA]: "0xcBdad2E86a60fcfF4ecD88D7067D403710D82340",
|
||||
[NetworkId.TESTNET_SEPOLIA]: "0xdcE486113280e49ca2fB200258E5Ee1B2D21D495",
|
||||
[NetworkId.TESTNET_HOODI]: "0x6Ad50B1E293E68B2fC230c576220a93A9D311571",
|
||||
};
|
||||
|
||||
export const DAO_TREASURY_ADDRESSES = {
|
||||
[NetworkId.TESTNET_SEPOLIA]: "0xed487AF8a6d1d1334e4b899FEb3f39402637Bc85",
|
||||
[NetworkId.TESTNET_SEPOLIA]: "0x93dd30f819403710de7933B79A74C4A42438458D",
|
||||
[NetworkId.TESTNET_HOODI]: "0x1a1b29b18f714fac9dDabEf530dFc4f85b56A6e8",
|
||||
};
|
||||
|
||||
export const FTSO_DAI_LP_ADDRESSES = {
|
||||
[NetworkId.TESTNET_SEPOLIA]: "0x0000000000000000000000000000000000000000", // TBD
|
||||
[NetworkId.TESTNET_SEPOLIA]: "0x1394dC3f7bABaa2F0CA80353648087DAB1BF3fd6",
|
||||
[NetworkId.TESTNET_HOODI]: "0xf7B2d44209E70782d93A70F7D8eC50010dF7ae50",
|
||||
};
|
||||
|
||||
export const FTSO_STNK_LP_ADDRESSES = {
|
||||
[NetworkId.TESTNET_SEPOLIA]: "0x29965676fc00C3eA9717B2A02739d294399a382e",
|
||||
[NetworkId.TESTNET_SEPOLIA]: "0x0000000000000000000000000000000000000000", // TBD
|
||||
[NetworkId.TESTNET_SEPOLIA]: "0x0000000000000000000000000000000000000000",
|
||||
}
|
||||
|
||||
export const DAI_ADDRESSES = {
|
||||
[NetworkId.TESTNET_SEPOLIA]: "0x1E392913CB9CeFAd0466D1525a9Ee144E74a233A",
|
||||
[NetworkId.TESTNET_SEPOLIA]: "0x5f63a27a9214a0352F2EF8dAF1eD4974d713192B",
|
||||
[NetworkId.TESTNET_HOODI]: "0x80c6676c334BCcE60b3CC852085B72143379CE58",
|
||||
};
|
||||
|
||||
@ -36,35 +36,39 @@ export const WETH_ADDRESSES = {
|
||||
};
|
||||
|
||||
export const GHST_ADDRESSES = {
|
||||
[NetworkId.TESTNET_SEPOLIA]: "0xfd210d7ac18Bc7dcE7d72ffd99a20a9F3b44d4F4",
|
||||
[NetworkId.TESTNET_SEPOLIA]: "0xdf2e5306A3dCcfA4e21bbF4226C17Ff5B008dDC4",
|
||||
[NetworkId.TESTNET_HOODI]: "0xE98f7426457E6533B206e91B7EcA97aa8A258B46",
|
||||
};
|
||||
|
||||
export const STNK_ADDRESSES = {
|
||||
[NetworkId.TESTNET_SEPOLIA]: "0x0cC9868D981852C804C610176b519c48808C26a9",
|
||||
[NetworkId.TESTNET_SEPOLIA]: "0x02C296A27eA779d5a16F934337c12062C5E3c0D9",
|
||||
[NetworkId.TESTNET_HOODI]: "0xF07e9303A9f16Afd82f4f57Fd6fca68Aa0AB6D7F",
|
||||
};
|
||||
|
||||
export const FTSO_ADDRESSES = {
|
||||
[NetworkId.TESTNET_SEPOLIA]: "0x730EEf44f2a676d4081a2F3B53D10d5e4c15C2Bc",
|
||||
[NetworkId.TESTNET_SEPOLIA]: "0xcFedFFEB3FdeCd2196820Ba3b71f3F84A1255f93",
|
||||
[NetworkId.TESTNET_HOODI]: "0xb184e423811b644A1924334E63985c259F5D0033",
|
||||
};
|
||||
|
||||
export const DISTRIBUTOR_ADDRESSES = {
|
||||
[NetworkId.TESTNET_SEPOLIA]: "0x1A848562b86DB7Be5558C1fa8D85326b163c2fFA",
|
||||
[NetworkId.TESTNET_SEPOLIA]: "0x8fbF8eB4Fcd451EF62Aee33508D46FE120963194",
|
||||
[NetworkId.TESTNET_HOODI]: "0xdF49dC81c457c6f92e26cf6d686C7a8715255842",
|
||||
};
|
||||
|
||||
export const GHOST_GOVERNANCE_ADDRESSES = {
|
||||
[NetworkId.TESTNET_SEPOLIA]: "0xc19f2680B1d64A507B7f3498E9B83B0A069C68Cc",
|
||||
[NetworkId.TESTNET_SEPOLIA]: "0xDab0c51918E6990d8763FAC8a04AE159e44e0c4f",
|
||||
[NetworkId.TESTNET_HOODI]: "0x1B96B792840d4d19d5097ee007392Ed4d851e64F",
|
||||
};
|
||||
|
||||
export const BONDING_CALCULATOR_ADDRESSES = {
|
||||
[NetworkId.TESTNET_SEPOLIA]: "0xAbE29450bAC493c6D25C467E0f809301084B6a27",
|
||||
[NetworkId.TESTNET_SEPOLIA]: "0x4896bFc6256A57Df826d7144E48c9633d51d6319",
|
||||
[NetworkId.TESTNET_HOODI]: "0x2635d526Ad24b98082563937f7b996075052c6Fd",
|
||||
}
|
||||
|
||||
export const GATEKEEPER_ADDRESSES = {
|
||||
[NetworkId.TESTNET_SEPOLIA]: "0xc85129A097773B7F8970a7364c928C05f265E6A1",
|
||||
}
|
||||
|
||||
export const UNISWAP_V2_ROUTER = {
|
||||
[NetworkId.TESTNET_SEPOLIA]: "0xee567fe1712faf6149d80da1e6934e354124cfe3",
|
||||
[NetworkId.TESTNET_HOODI]: "0xD41daF947c6FFEf344754B99ad09466FBCBb7583",
|
||||
|
662
src/containers/Bridge/Bridge.jsx
Normal file
662
src/containers/Bridge/Bridge.jsx
Normal file
@ -0,0 +1,662 @@
|
||||
import { useEffect, useState, useMemo, useCallback } from "react";
|
||||
|
||||
import {
|
||||
Box,
|
||||
Container,
|
||||
Typography,
|
||||
Link,
|
||||
Table,
|
||||
TableBody,
|
||||
TableCell,
|
||||
TableHead,
|
||||
TableRow,
|
||||
TableContainer,
|
||||
useMediaQuery,
|
||||
useTheme
|
||||
} from "@mui/material";
|
||||
import { ss58Decode } from "@polkadot-labs/hdkd-helpers";
|
||||
import { toHex } from "@polkadot-api/utils";
|
||||
import { useBlockNumber, useTransactionConfirmations } from "wagmi";
|
||||
|
||||
import PendingActionsIcon from '@mui/icons-material/PendingActions';
|
||||
import PublicIcon from '@mui/icons-material/Public';
|
||||
import ArrowRightIcon from '@mui/icons-material/ArrowRight';
|
||||
import HourglassBottomIcon from '@mui/icons-material/HourglassBottom';
|
||||
import ThumbUpIcon from '@mui/icons-material/ThumbUp';
|
||||
import ThumbDownAltIcon from '@mui/icons-material/ThumbDownAlt';
|
||||
import CheckCircleIcon from '@mui/icons-material/CheckCircle';
|
||||
import CheckIcon from '@mui/icons-material/Check';
|
||||
|
||||
import PageTitle from "../../components/PageTitle/PageTitle";
|
||||
import Paper from "../../components/Paper/Paper";
|
||||
import SwapCard from "../../components/Swap/SwapCard";
|
||||
import SwapCollection from "../../components/Swap/SwapCollection";
|
||||
import TokenStack from "../../components/TokenStack/TokenStack";
|
||||
import GhostStyledIcon from "../../components/Icon/GhostIcon";
|
||||
import Modal from "../../components/Modal/Modal";
|
||||
import { PrimaryButton } from "../../components/Button";
|
||||
|
||||
import { GATEKEEPER_ADDRESSES } from "../../constants/addresses";
|
||||
import { DecimalBigNumber } from "../../helpers/DecimalBigNumber";
|
||||
import { formatCurrency } from "../../helpers";
|
||||
|
||||
import { useTokenSymbol, useBalance } from "../../hooks/tokens";
|
||||
import { useGatekeeperAddress, ghost } from "../../hooks/staking";
|
||||
|
||||
const STORAGE_PREFIX = "storedTransactions"
|
||||
|
||||
const Bridge = ({ chainId, address, config, connect }) => {
|
||||
const theme = useTheme();
|
||||
const isSmallScreen = useMediaQuery("(max-width: 650px)");
|
||||
const isSemiSmallScreen = useMediaQuery("(max-width: 480px)");
|
||||
const isVerySmallScreen = useMediaQuery("(max-width: 379px)");
|
||||
|
||||
const [isPending, setIsPending] = useState(false);
|
||||
const [bridgeAction, setBridgeAction] = useState(true);
|
||||
const [activeTxIndex, setActiveTxIndex] = useState(-1);
|
||||
const [txStep, setTxStep] = useState(0);
|
||||
const [receiver, setReceiver] = useState("");
|
||||
const [convertedReceiver, setConvertedReceiver] = useState(undefined);
|
||||
const [amount, setAmount] = useState("");
|
||||
|
||||
// ReceivedClaps && ApplausesForTransaction
|
||||
// session_index
|
||||
// transaction_hash
|
||||
// keccak256(receiver, amount, chain_id)
|
||||
|
||||
// const initialStoredTransactions = sessionStorage.getItem(STORAGE_PREFIX);
|
||||
const initialStoredTransactions = JSON.stringify([
|
||||
{
|
||||
sessionIndex: 23,
|
||||
transactionHash: "0x11111111111111111",
|
||||
receiver: "sfAasdadasasads",
|
||||
amount: "2312323232223232",
|
||||
chainId: 11155111,
|
||||
timestamp: Date.now()
|
||||
},
|
||||
{
|
||||
sessionIndex: 23,
|
||||
transactionHash: "0x2222222222222222222",
|
||||
receiver: "sfAasdadasasads",
|
||||
amount: "1122232232",
|
||||
chainId: 1,
|
||||
timestamp: Date.now()
|
||||
},
|
||||
{
|
||||
sessionIndex: 24,
|
||||
transactionHash: "0x333333333333333333",
|
||||
receiver: "sfAasdadasasads",
|
||||
amount: "99999999999999992",
|
||||
chainId: 11155111,
|
||||
timestamp: Date.now()
|
||||
},
|
||||
{
|
||||
sessionIndex: 23,
|
||||
transactionHash: "0x4444444444444444444",
|
||||
receiver: "sfAasdadasasads",
|
||||
amount: "2312323232223232",
|
||||
chainId: 11155111,
|
||||
timestamp: Date.now()
|
||||
},
|
||||
{
|
||||
sessionIndex: 23,
|
||||
transactionHash: "0x555555555555555555555",
|
||||
receiver: "sfAasdadasasads",
|
||||
amount: "1122232232",
|
||||
chainId: 1,
|
||||
timestamp: Date.now()
|
||||
},
|
||||
{
|
||||
sessionIndex: 24,
|
||||
transactionHash: "0x66666666666666666666666666",
|
||||
receiver: "sfAasdadasasads",
|
||||
amount: "99999999999999992",
|
||||
chainId: 11155111,
|
||||
timestamp: Date.now()
|
||||
},
|
||||
{
|
||||
sessionIndex: 23,
|
||||
transactionHash: "0x77777777777777777777777777",
|
||||
receiver: "sfAasdadasasads",
|
||||
amount: "2312323232223232",
|
||||
chainId: 11155111,
|
||||
timestamp: Date.now()
|
||||
},
|
||||
{
|
||||
sessionIndex: 23,
|
||||
transactionHash: "0x888888888888888888888888888",
|
||||
receiver: "sfAasdadasasads",
|
||||
amount: "1122232232",
|
||||
chainId: 1,
|
||||
timestamp: Date.now()
|
||||
},
|
||||
{
|
||||
sessionIndex: 24,
|
||||
transactionHash: "0x999999999999999999999",
|
||||
receiver: "sfAasdadasasads",
|
||||
amount: "99999999999999992",
|
||||
chainId: 11155111,
|
||||
timestamp: Date.now()
|
||||
},
|
||||
{
|
||||
sessionIndex: 23,
|
||||
transactionHash: "0x10101010101010101010",
|
||||
receiver: "sfAasdadasasads",
|
||||
amount: "2312323232223232",
|
||||
chainId: 11155111,
|
||||
timestamp: Date.now()
|
||||
},
|
||||
{
|
||||
sessionIndex: 23,
|
||||
transactionHash: "0x12121212121212212",
|
||||
receiver: "sfAasdadasasads",
|
||||
amount: "1122232232",
|
||||
chainId: 1,
|
||||
timestamp: Date.now()
|
||||
},
|
||||
{
|
||||
sessionIndex: 24,
|
||||
transactionHash: "0x1313131313131313131",
|
||||
receiver: "sfAasdadasasads",
|
||||
amount: "99999999999999992",
|
||||
chainId: 11155111,
|
||||
timestamp: Date.now()
|
||||
}
|
||||
]);
|
||||
const [storedTransactions, setStoredTransactions] = useState(
|
||||
initialStoredTransactions ? JSON.parse(initialStoredTransactions) : []
|
||||
);
|
||||
|
||||
const incomingCommission = new DecimalBigNumber(69n, 100);
|
||||
const validators = ["first", "second", "third"];
|
||||
const clappedValidators = 1;
|
||||
|
||||
const { data: blockNumber } = useBlockNumber({ watch: true });
|
||||
// const { data: txtx } = useTransactionConfirmations({
|
||||
// hash: "0xdb30adfa3bfc58539bc3a9a92f0dcace8f251af90f8a4f525b57d95d28103afc",
|
||||
// refetchInterval: 5000
|
||||
// });
|
||||
// console.log(txtx)
|
||||
const { gatekeeperAddress } = useGatekeeperAddress(chainId);
|
||||
const { symbol: ghstSymbol } = useTokenSymbol(chainId, "GHST");
|
||||
const {
|
||||
balance: ghstBalance,
|
||||
refetch: ghstBalanceRefetch
|
||||
} = useBalance(chainId, "GHST", address);
|
||||
|
||||
useEffect(() => {
|
||||
try {
|
||||
const [publicKey, prefix] = ss58Decode(receiver);
|
||||
if (prefix !== 1995 && prefix !== 1996) {
|
||||
throw new Error("bad prefix");
|
||||
}
|
||||
setConvertedReceiver(toHex(publicKey));
|
||||
} catch {
|
||||
setConvertedReceiver(undefined);
|
||||
}
|
||||
}, [receiver])
|
||||
|
||||
const chainExplorerUrl = useMemo(() => {
|
||||
const client = config?.getClient();
|
||||
return client?.chain?.blockExplorers?.default?.url;
|
||||
}, [config]);
|
||||
|
||||
const chainName = useMemo(() => {
|
||||
const client = config?.getClient();
|
||||
return client?.chain?.name;
|
||||
}, [config]);
|
||||
|
||||
const currentRecord = useMemo(() => {
|
||||
if (activeTxIndex === -1) return undefined
|
||||
return storedTransactions.at(activeTxIndex)
|
||||
}, [activeTxIndex, storedTransactions]);
|
||||
|
||||
const gatekeeperAddressEmpty = useMemo(() => {
|
||||
if (gatekeeperAddress === "0x0000000000000000000000000000000000000000") {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}, [gatekeeperAddress]);
|
||||
|
||||
const preparedAmount = useMemo(() => {
|
||||
try {
|
||||
return BigInt(parseFloat(amount) * Math.pow(10, 18));
|
||||
} catch {
|
||||
return 0n;
|
||||
}
|
||||
}, [amount])
|
||||
|
||||
const filteredStoredTransactions = useMemo(() => {
|
||||
return storedTransactions.filter(obj => obj.chainId === chainId);
|
||||
}, [storedTransactions, chainId]);
|
||||
|
||||
const removeStoredRecord = useCallback(() => {
|
||||
const newStoredTransactions = storedTransactions.filter((_, index) => index !== activeTxIndex)
|
||||
setStoredTransactions(newStoredTransactions);
|
||||
sessionStorage.setItem(STORAGE_PREFIX, JSON.stringify(newStoredTransactions));
|
||||
setActiveTxIndex(-1);
|
||||
}, [storedTransactions, activeTxIndex, setStoredTransactions, setActiveTxIndex]);
|
||||
|
||||
const handleMouseEnter = (index) => {
|
||||
setTxStep(index);
|
||||
}
|
||||
|
||||
const ghostOrConnect = async () => {
|
||||
if (address === "") {
|
||||
connect();
|
||||
} else {
|
||||
setIsPending(true);
|
||||
|
||||
const txHash = await ghost(chainId, address, convertedReceiver, preparedAmount);
|
||||
|
||||
await ghstBalanceRefetch();
|
||||
setReceiver("");
|
||||
setAmount("");
|
||||
setIsPending(false);
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<Box height="calc(100vh - 43px)">
|
||||
<PageTitle name="GHOST Bridge" subtitle="The only pure Web3 decentralized bridge." />
|
||||
<Container
|
||||
style={{
|
||||
paddingLeft: isSmallScreen || isVerySmallScreen ? "0" : "3.3rem",
|
||||
paddingRight: isSmallScreen || isVerySmallScreen ? "0" : "3.3rem",
|
||||
display: "flex",
|
||||
justifyContent: "center",
|
||||
alignItems: "center",
|
||||
height: "calc(100vh - 153px)"
|
||||
}}
|
||||
>
|
||||
<Modal
|
||||
data-testid="transaction-details-modal"
|
||||
maxWidth="476px"
|
||||
headerContent={
|
||||
<Box display="flex" flexDirection="row">
|
||||
<Typography variant="h5">
|
||||
TX Hash
|
||||
<Link
|
||||
sx={{
|
||||
margin: "0px",
|
||||
font: "inherit",
|
||||
letterSpacing: "inherit",
|
||||
textDecoration: "underline",
|
||||
color: theme.colors.gray[10],
|
||||
textUnderlineOffset: "0.23rem",
|
||||
cursor: "pointer",
|
||||
textDecorationThickness: "3px",
|
||||
"&:hover": {
|
||||
textDecoration: "underline",
|
||||
}
|
||||
}}
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
href={currentRecord
|
||||
? `${chainExplorerUrl}/tx/${currentRecord.transactionHash}`
|
||||
: ""
|
||||
}
|
||||
>
|
||||
{currentRecord?.transactionHash.slice(0, 9)}...{currentRecord?.transactionHash.slice(-9)}
|
||||
</Link>
|
||||
</Typography>
|
||||
</Box>
|
||||
}
|
||||
open={activeTxIndex > -1}
|
||||
onClose={() => setActiveTxIndex(-1)}
|
||||
minHeight={"100px"}
|
||||
>
|
||||
<Box display="flex" gap="1.5rem" flexDirection="column" marginTop=".8rem">
|
||||
<Box display="flex" flexDirection="row" justifyContent="space-between" alignItems="center">
|
||||
<Box
|
||||
sx={{
|
||||
transition: "all 0.2s ease",
|
||||
transform: txStep === 0 && "scale(1.1)",
|
||||
color: txStep === 0 && theme.colors.primary[300]
|
||||
}}
|
||||
width="120px"
|
||||
display="flex"
|
||||
flexDirection="column"
|
||||
justifyContent="start"
|
||||
alignItems="center"
|
||||
onMouseEnter={() => handleMouseEnter(0)}
|
||||
>
|
||||
<GhostStyledIcon
|
||||
sx={{ width: "35px", height: "35px" }}
|
||||
viewBox="0 0 25 25"
|
||||
component={HourglassBottomIcon}
|
||||
/>
|
||||
<Typography variant="caption">Finalization</Typography>
|
||||
<Typography variant="caption">{blockNumber?.toString()} blocks left</Typography>
|
||||
</Box>
|
||||
|
||||
<GhostStyledIcon
|
||||
sx={{ transition: "all 0.2s ease", opacity: txStep < 1 && "0.2" }}
|
||||
component={ArrowRightIcon}
|
||||
/>
|
||||
|
||||
<Box
|
||||
sx={{
|
||||
transition: "all 0.2s ease",
|
||||
opacity: txStep < 1 && "0.2",
|
||||
transform: txStep === 1 && "scale(1.1)",
|
||||
color: txStep === 1 && theme.colors.primary[300]
|
||||
}}
|
||||
width="120px"
|
||||
display="flex"
|
||||
flexDirection="column"
|
||||
justifyContent="start"
|
||||
alignItems="center"
|
||||
onMouseEnter={() => handleMouseEnter(1)}
|
||||
>
|
||||
<Box display="flex" flexDirection="row" justifyContent="center" alignItems="center">
|
||||
<GhostStyledIcon
|
||||
sx={{ width: "35px", height: "35px" }}
|
||||
viewBox="0 0 25 25"
|
||||
component={ThumbUpIcon}
|
||||
/>
|
||||
<GhostStyledIcon
|
||||
sx={{ width: "35px", height: "35px" }}
|
||||
viewBox="0 0 25 25"
|
||||
component={ThumbDownAltIcon}
|
||||
/>
|
||||
</Box>
|
||||
<Box display="flex" flexDirection="column" justifyContent="center" alignItems="center">
|
||||
<Typography variant="caption">Slow claps</Typography>
|
||||
<Typography variant="caption">{clappedValidators} / {validators.length}</Typography>
|
||||
</Box>
|
||||
</Box>
|
||||
|
||||
<GhostStyledIcon
|
||||
sx={{ transition: "all 0.2s ease", opacity: txStep < 2 && "0.2" }}
|
||||
component={ArrowRightIcon}
|
||||
/>
|
||||
|
||||
<Box
|
||||
sx={{
|
||||
transition: "all 0.2s ease",
|
||||
opacity: txStep < 2 && "0.2",
|
||||
transform: txStep === 2 && "scale(1.1)",
|
||||
color: txStep === 2 && theme.colors.primary[300]
|
||||
}}
|
||||
width="120px"
|
||||
display="flex"
|
||||
flexDirection="column"
|
||||
justifyContent="start"
|
||||
alignItems="center"
|
||||
onMouseEnter={() => handleMouseEnter(2)}
|
||||
>
|
||||
<GhostStyledIcon
|
||||
sx={{ width: "35px", height: "35px" }}
|
||||
viewBox="0 0 25 25"
|
||||
component={CheckCircleIcon}
|
||||
/>
|
||||
<Typography variant="caption">Applaused</Typography>
|
||||
<Typography variant="caption">Check Receiver</Typography>
|
||||
</Box>
|
||||
</Box>
|
||||
|
||||
<Box display="flex" flexDirection="column" gap="5px" padding="0.6rem 0">
|
||||
<Box display="flex" flexDirection="row" justifyContent="space-between">
|
||||
<Typography variant="body2">Session Index:</Typography>
|
||||
<Typography variant="body2">{currentRecord?.sessionIndex}</Typography>
|
||||
</Box>
|
||||
<Box display="flex" flexDirection="row" justifyContent="space-between">
|
||||
<Typography variant="body2">Receiver Address:</Typography>
|
||||
<Typography variant="body2">{currentRecord?.receiver}</Typography>
|
||||
</Box>
|
||||
<Box display="flex" flexDirection="row" justifyContent="space-between">
|
||||
<Typography variant="body2">Sent Amount:</Typography>
|
||||
<Typography variant="body2">{formatCurrency(
|
||||
new DecimalBigNumber(
|
||||
BigInt(currentRecord ? currentRecord.amount : "0"),
|
||||
18
|
||||
).toString(), 9, ghstSymbol)
|
||||
}</Typography>
|
||||
</Box>
|
||||
<Box display="flex" flexDirection="row" justifyContent="space-between">
|
||||
<Typography variant="body2">Executed at:</Typography>
|
||||
<Typography variant="body2">{
|
||||
new Date(currentRecord ? currentRecord.timestamp : 0).toLocaleString('en-US')
|
||||
}</Typography>
|
||||
</Box>
|
||||
</Box>
|
||||
|
||||
|
||||
<Box display="flex" flexDirection="column" gap="5px">
|
||||
<PrimaryButton
|
||||
fullWidth
|
||||
disabled={address === ""}
|
||||
loading={false}
|
||||
onClick={() => removeStoredRecord()}
|
||||
>
|
||||
Erase Record
|
||||
</PrimaryButton>
|
||||
|
||||
<Typography variant="body2" sx={{ fontStyle: "italic" }}>
|
||||
This will remove the transaction record from the session storage, but it will not cancel the bridge transaction.
|
||||
</Typography>
|
||||
</Box>
|
||||
</Box>
|
||||
</Modal>
|
||||
<Box width="100%" maxWidth="476px" display="flex" alignItems="center" justifyContent="center" flexDirection="column">
|
||||
<Paper
|
||||
headerContent={
|
||||
<Box alignItems="center" justifyContent="space-between" display="flex" width="100%">
|
||||
<Typography variant="h4">{
|
||||
bridgeAction
|
||||
? `Bridge $${ghstSymbol}`
|
||||
: "Transaction history"
|
||||
}</Typography>
|
||||
</Box>
|
||||
}
|
||||
topRight={
|
||||
<GhostStyledIcon
|
||||
component={bridgeAction ? PendingActionsIcon : PublicIcon}
|
||||
viewBox="0 0 23 23"
|
||||
style={{ display: "flex", alignItems: "center", cursor: "pointer" }}
|
||||
onClick={() => setBridgeAction(!bridgeAction)}
|
||||
/>
|
||||
}
|
||||
|
||||
enableBackground
|
||||
fullWidth
|
||||
>
|
||||
<Box minHeight="300px" display="flex" flexDirection="column" gap="5px">
|
||||
{bridgeAction && (
|
||||
<>
|
||||
<SwapCollection
|
||||
iconNotNeeded
|
||||
UpperSwapCard={<SwapCard
|
||||
id={`bridge-token-receiver`}
|
||||
inputWidth={isVerySmallScreen ? "100px" : isSemiSmallScreen ? "180px" : "250px"}
|
||||
value={receiver}
|
||||
onChange={event => setReceiver(event.currentTarget.value)}
|
||||
inputProps={{ "data-testid": "fromInput" }}
|
||||
placeholder="Ghost address (sf prefixed)"
|
||||
type="text"
|
||||
/>}
|
||||
LowerSwapCard={<SwapCard
|
||||
id={`bridge-token-amount`}
|
||||
inputWidth={isVerySmallScreen ? "100px" : isSemiSmallScreen ? "180px" : "250px"}
|
||||
info={`${formatCurrency(ghstBalance.toString(), 4, ghstSymbol)}`}
|
||||
value={amount}
|
||||
onChange={event => setAmount(event.currentTarget.value)}
|
||||
inputProps={{ "data-testid": "fromInput" }}
|
||||
endString={"Max"}
|
||||
endStringOnClick={() => setAmount(ghstBalance.toString())}
|
||||
/>}
|
||||
/>
|
||||
<Box
|
||||
mb="20px"
|
||||
mt="20px"
|
||||
flexDirection="column"
|
||||
display="flex"
|
||||
gap="10px"
|
||||
justifyContent="space-between"
|
||||
>
|
||||
<Box display="flex" justifyContent={isVerySmallScreen ? "end" : "space-between"}>
|
||||
{gatekeeperAddressEmpty && (
|
||||
<Box maxWidth="416px" display="flex" justifyContent={isVerySmallScreen ? "end" : "space-between"}>
|
||||
<Typography mr="10px" variant="body2" color="textSecondary">
|
||||
<em>
|
||||
There is no connected gatekeeper on {chainName} network. Propose gatekeeper on this network to make validators listen to it.
|
||||
</em>
|
||||
</Typography>
|
||||
</Box>
|
||||
)}
|
||||
{!gatekeeperAddressEmpty && (
|
||||
<>
|
||||
{!isVerySmallScreen && <Typography fontSize="12px" lineHeight="15px">Gatekeeper:</Typography>}
|
||||
<Link
|
||||
fontSize="12px"
|
||||
lineHeight="15px"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
href={`${chainExplorerUrl}/token/${gatekeeperAddress}`}
|
||||
>
|
||||
{gatekeeperAddress.slice(0, 10) + "..." + gatekeeperAddress.slice(-8)}
|
||||
</Link>
|
||||
</>
|
||||
)}
|
||||
</Box>
|
||||
{incomingCommission && validators?.length ? (
|
||||
<Box maxWidth="416px" display="flex" justifyContent={isVerySmallScreen ? "end" : "space-between"}>
|
||||
<Typography mr="10px" variant="body2" color="textSecondary">
|
||||
<em>
|
||||
GHOST Wallet is not detected on your browser. Download
|
||||
<Link
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
href="https://git.ghostchain.io/ghostchain/ghost-extension-wallet/releases"
|
||||
>
|
||||
GHOST Wallet
|
||||
</Link> to see full detalization for bridge transaction.
|
||||
</em>
|
||||
</Typography>
|
||||
</Box>
|
||||
)
|
||||
: (
|
||||
<Box display="flex" flexDirection="column" gap="0px">
|
||||
<Box maxWidth="416px" display="flex" justifyContent={isVerySmallScreen ? "end" : "space-between"}>
|
||||
{!isVerySmallScreen && <Typography fontSize="12px" lineHeight="15px">Est. Commission:</Typography>}
|
||||
<Typography fontSize="12px" lineHeight="15px">unknown</Typography>
|
||||
</Box>
|
||||
<Box maxWidth="416px" display="flex" justifyContent={isVerySmallScreen ? "end" : "space-between"}>
|
||||
{!isVerySmallScreen && <Typography fontSize="12px" lineHeight="15px">Number of validators:</Typography>}
|
||||
<Typography fontSize="12px" lineHeight="15px">unknown</Typography>
|
||||
</Box>
|
||||
</Box>
|
||||
)}
|
||||
|
||||
</Box>
|
||||
<PrimaryButton
|
||||
fullWidth
|
||||
disabled={
|
||||
address === "" || gatekeeperAddressEmpty || !convertedReceiver ||
|
||||
preparedAmount === 0n || ghstBalance._value < preparedAmount
|
||||
}
|
||||
loading={isPending}
|
||||
onClick={() => ghostOrConnect()}
|
||||
>
|
||||
{address === "" ?
|
||||
"Connect"
|
||||
:
|
||||
"Bridge"
|
||||
}
|
||||
</PrimaryButton>
|
||||
</>
|
||||
)}
|
||||
{!bridgeAction && (
|
||||
<Box>
|
||||
<Box display="grid" gridTemplateColumns="1fr 1fr 60px" sx={{ padding: "0.6rem", borderBottom: "1px solid" }}>
|
||||
<Typography variant="subtitle1" sx={{ fontWeight: "bold" }}>Amount</Typography>
|
||||
<Typography variant="subtitle1" sx={{ fontWeight: "bold" }}>Datetime</Typography>
|
||||
<Typography variant="subtitle1" sx={{ justifySelf: "center", fontWeight: "bold" }}>Status</Typography>
|
||||
</Box>
|
||||
<Box display="flex" flexDirection="column" sx={{
|
||||
height: "250px",
|
||||
overflowY: "scroll",
|
||||
"-ms-overflow-style": "thin !important",
|
||||
"scrollbar-width": "thin !important",
|
||||
}}>
|
||||
{filteredStoredTransactions
|
||||
.map((obj, idx) => (
|
||||
<Box
|
||||
display="grid"
|
||||
gridTemplateColumns="1fr 1fr 60px"
|
||||
sx={{
|
||||
borderBottom: "1px solid",
|
||||
padding: "0.6rem",
|
||||
paddingTop: "1.2rem",
|
||||
cursor: 'pointer',
|
||||
'&:hover': {
|
||||
background: theme.colors.paper.cardHover
|
||||
}
|
||||
}}
|
||||
key={obj.transactionHash}
|
||||
onClick={() => setActiveTxIndex(idx)}
|
||||
>
|
||||
<Box display="flex" flexDirection="column" justifyContent="center">
|
||||
<Typography variant="subtitle2">
|
||||
{formatCurrency(
|
||||
new DecimalBigNumber(BigInt(obj.amount), 18).toString(),
|
||||
3,
|
||||
ghstSymbol
|
||||
)}
|
||||
</Typography>
|
||||
</Box>
|
||||
|
||||
<Box display="flex" flexDirection="column">
|
||||
<Typography variant="subtitle2">
|
||||
{new Date(obj.timestamp).toLocaleDateString('en-US')}
|
||||
</Typography>
|
||||
<Typography variant="subtitle2">
|
||||
{new Date(obj.timestamp).toLocaleTimeString('en-US')}
|
||||
</Typography>
|
||||
</Box>
|
||||
|
||||
<Box display="flex" justifyContent="center" alignItems="center">
|
||||
<Box
|
||||
display="flex"
|
||||
justifyContent="center"
|
||||
alignItems="center"
|
||||
sx={{
|
||||
width: "25px",
|
||||
height: "25px",
|
||||
background: idx % 2 === 0
|
||||
? theme.colors.feedback.warning
|
||||
: theme.colors.feedback.success,
|
||||
borderRadius: "100%",
|
||||
boxShadow: "0px 0px 1px black"
|
||||
}}
|
||||
>
|
||||
{idx % 2 === 0 ?
|
||||
<GhostStyledIcon
|
||||
sx={{ width: "20px", height: "20px" }}
|
||||
viewBox="0 0 25 25"
|
||||
component={HourglassBottomIcon}
|
||||
/>
|
||||
:
|
||||
<GhostStyledIcon
|
||||
sx={{ width: "20px", height: "20px" }}
|
||||
viewBox="0 0 25 25"
|
||||
component={CheckIcon}
|
||||
/>
|
||||
}
|
||||
</Box>
|
||||
</Box>
|
||||
</Box>
|
||||
))}
|
||||
</Box>
|
||||
</Box>
|
||||
)}
|
||||
</Box>
|
||||
</Paper>
|
||||
</Box>
|
||||
</Container>
|
||||
</Box>
|
||||
)
|
||||
}
|
||||
|
||||
export default Bridge;
|
@ -68,9 +68,6 @@ const PoolContainer = ({
|
||||
);
|
||||
|
||||
const onSwap = () => {
|
||||
// const oldAmountTop = amountTop;
|
||||
// const oldAmountBottom = amountBottom;
|
||||
// setAmountBottom(oldAmountTop);
|
||||
setAmountTop(amountBottom);
|
||||
onCardsSwap();
|
||||
}
|
||||
|
@ -30,14 +30,6 @@ const Faucet = ({ chainId, address, config, connect }) => {
|
||||
const isSemiSmallScreen = useMediaQuery("(max-width: 480px)");
|
||||
const isVerySmallScreen = useMediaQuery("(max-width: 379px)");
|
||||
|
||||
const daiConversionRate = useConversionRate(chainId, "GDAI");
|
||||
const accumulatedDonation = useAccumulatedDonation(chainId, "GDAI");
|
||||
const { balance: daiBalance, refetch: daiBalanceRefetch } = useTokenBalance(chainId, "GDAI", address);
|
||||
const { data: nativeBalance, refetch: balanceRefetch } = useBalance({ address });
|
||||
const { data: contractBalance, refetch: contractBalanceRefetch } = useBalance({ address });
|
||||
const { totalSupply: reserveTotalSupply, refetch: refetchReserveTotalSupply } = useTotalSupply(chainId, "GDAI");
|
||||
const { symbol: faucetSymbol } = useTokenSymbol(chainId, "GDAI");
|
||||
|
||||
const [isMint, setIsMint] = useState(true);
|
||||
const [isPending, setIsPending] = useState(false);
|
||||
const [balance, setBalance] = useState(new DecimalBigNumber(0, 0));
|
||||
@ -52,6 +44,15 @@ const Faucet = ({ chainId, address, config, connect }) => {
|
||||
symbol: "",
|
||||
})
|
||||
|
||||
const daiConversionRate = useConversionRate(chainId, "GDAI");
|
||||
const accumulatedDonation = useAccumulatedDonation(chainId, "GDAI");
|
||||
|
||||
const { balance: daiBalance, refetch: daiBalanceRefetch } = useTokenBalance(chainId, "GDAI", address);
|
||||
const { data: nativeBalance, refetch: balanceRefetch } = useBalance({ address });
|
||||
const { data: contractBalance, refetch: contractBalanceRefetch } = useBalance({ address: DAI_ADDRESSES[chainId] });
|
||||
const { totalSupply: reserveTotalSupply, refetch: refetchReserveTotalSupply } = useTotalSupply(chainId, "GDAI");
|
||||
const { symbol: faucetSymbol } = useTokenSymbol(chainId, "GDAI");
|
||||
|
||||
useEffect(() => {
|
||||
ReactGA.send({ hitType: "pageview", page: "/faucet" });
|
||||
}, [])
|
||||
@ -98,11 +99,11 @@ const Faucet = ({ chainId, address, config, connect }) => {
|
||||
}, [amount, daiConversionRate, nativeInfo]);
|
||||
|
||||
const contractBalanceFree = useMemo(() => {
|
||||
const realContractBalance = contractBalance ? contractBalance : 0n;
|
||||
const realContractBalance = contractBalance ? contractBalance.value : 0n;
|
||||
const preparedContractBalance = new DecimalBigNumber(realContractBalance, nativeInfo.decimals);
|
||||
const preparedAccumulatedDonation = new DecimalBigNumber(
|
||||
accumulatedDonation._value,
|
||||
accumulatedDonation._decimals + nativeInfo.decimals - 18
|
||||
nativeInfo.decimals && 18
|
||||
);
|
||||
return preparedContractBalance.sub(preparedAccumulatedDonation);
|
||||
}, [contractBalance, accumulatedDonation]);
|
||||
@ -212,10 +213,12 @@ const Faucet = ({ chainId, address, config, connect }) => {
|
||||
inputWidth={isVerySmallScreen ? "100px" : isSemiSmallScreen ? "180px" : "250px"}
|
||||
tokenName={faucetSymbol}
|
||||
token={<TokenStack tokens={[faucetSymbol]} sx={{ fontSize: "21px" }} />}
|
||||
info={`${isSemiSmallScreen ? "" : "Balance: "}${formatCurrency(daiBalance.toString(), 4, faucetSymbol)}`}
|
||||
info={`${formatCurrency(daiBalance.toString(), 4, faucetSymbol)}`}
|
||||
value={amount}
|
||||
onChange={event => setAmount(event.currentTarget.value)}
|
||||
inputProps={{ "data-testid": "fromInput" }}
|
||||
endString={"Max"}
|
||||
endStringOnClick={() => setAmount(daiBalance.toString())}
|
||||
/>}
|
||||
<Box
|
||||
mb="20px"
|
||||
@ -244,7 +247,7 @@ const Faucet = ({ chainId, address, config, connect }) => {
|
||||
<>
|
||||
<Box maxWidth="416px" display="flex" justifyContent={isVerySmallScreen ? "end" : "space-between"}>
|
||||
{!isVerySmallScreen && <Typography fontSize="12px" lineHeight="15px">Accumulated {nativeInfo.symbol}:</Typography>}
|
||||
<Typography fontSize="12px" lineHeight="15px">{formatNumber(contractBalanceFree, 5)}</Typography>
|
||||
<Typography fontSize="12px" lineHeight="15px">{formatCurrency(contractBalanceFree, 5, nativeInfo.symbol)}</Typography>
|
||||
</Box>
|
||||
<Box maxWidth="416px" display="flex" justifyContent={isVerySmallScreen ? "end" : "space-between"}>
|
||||
{!isVerySmallScreen && <Typography fontSize="12px" lineHeight="15px">You will get:</Typography>}
|
||||
|
@ -1,6 +1,6 @@
|
||||
import { useReadContract } from "wagmi";
|
||||
|
||||
import { useCurrentIndex } from "../staking";
|
||||
import { useCurrentIndex, useGhostedSupply } from "../staking";
|
||||
import { useUniswapV2PairReserves } from "../uniswapv2";
|
||||
import { DecimalBigNumber } from "../../helpers/DecimalBigNumber";
|
||||
import { FTSO_DAI_LP_ADDRESSES, DAI_ADDRESSES, FTSO_ADDRESSES } from "../../constants/addresses";
|
||||
@ -20,13 +20,19 @@ export const useFtsoPrice = (chainId) => {
|
||||
"GDAI",
|
||||
);
|
||||
|
||||
const stableReserves = DAI_ADDRESSES[chainId].toUpperCase() === tokens.token0.toUpperCase()
|
||||
? reserves.reserve0._value
|
||||
: DAI_ADDRESSES[chainId].toUpperCase() === tokens.token1.toUpperCase() ? reserves.reserve1._value : 0n;
|
||||
const reserveAddress = DAI_ADDRESSES[chainId];
|
||||
const ftsoAddress = FTSO_ADDRESSES[chainId];
|
||||
if (!reserveAddress || !ftsoAddress) {
|
||||
return new DecimalBigNumber(0n, 9);
|
||||
}
|
||||
|
||||
const ftsoReserves = FTSO_ADDRESSES[chainId].toUpperCase() === tokens.token0.toUpperCase()
|
||||
const stableReserves = reserveAddress.toUpperCase() === tokens.token0.toUpperCase()
|
||||
? reserves.reserve0._value
|
||||
: FTSO_ADDRESSES[chainId].toUpperCase() === tokens.token1.toUpperCase() ? reserves.reserve1._value : 0n;
|
||||
: reserveAddress.toUpperCase() === tokens.token1.toUpperCase() ? reserves.reserve1._value : 0n;
|
||||
|
||||
const ftsoReserves = ftsoAddress.toUpperCase() === tokens.token0.toUpperCase()
|
||||
? reserves.reserve0._value
|
||||
: ftsoAddress.toUpperCase() === tokens.token1.toUpperCase() ? reserves.reserve1._value : 0n;
|
||||
|
||||
let price = 0n
|
||||
if (ftsoReserves > 0n)
|
||||
@ -46,3 +52,10 @@ export const useGhstPrice = (chainId) => {
|
||||
|
||||
return ftsoPrice.mul(currentIndex);
|
||||
};
|
||||
|
||||
export const useGhostedSupplyPrice = (chainId) => {
|
||||
const ghstPrice = useGhstPrice(chainId);
|
||||
const ghostedSupply = useGhostedSupply(chainId);
|
||||
|
||||
return ghstPrice.mul(ghostedSupply);
|
||||
}
|
||||
|
@ -83,6 +83,36 @@ export const useWarmupInfo = (chainId, address) => {
|
||||
return { warmupInfo, refetch }
|
||||
}
|
||||
|
||||
export const useGatekeeperAddress = (chainId) => {
|
||||
const { data: info, refetch } = useReadContract({
|
||||
abi: StakingAbi,
|
||||
address: STAKING_ADDRESSES[chainId],
|
||||
functionName: "gatekeeper",
|
||||
scopeKey: `gatekeeper-${chainId}`,
|
||||
chainId: chainId,
|
||||
});
|
||||
|
||||
const gatekeeperAddress = info ? info : "0x0000000000000000000000000000000000000000";
|
||||
return { gatekeeperAddress, refetch };
|
||||
}
|
||||
|
||||
export const useGhostedSupply = (chainId) => {
|
||||
const { data: info, refetch } = useReadContract({
|
||||
abi: StakingAbi,
|
||||
address: STAKING_ADDRESSES[chainId],
|
||||
functionName: "ghostedSupply",
|
||||
scopeKey: `ghostedSupply-${chainId}`,
|
||||
chainId: chainId,
|
||||
});
|
||||
|
||||
const ghostedSupply = new DecimalBigNumber(
|
||||
info ? info : 0n,
|
||||
18
|
||||
);
|
||||
|
||||
return ghostedSupply;
|
||||
}
|
||||
|
||||
export const stake = async (chainId, account, amount, isRebase, isClaim) => {
|
||||
const args = [
|
||||
amount,
|
||||
@ -186,6 +216,24 @@ export const wrap = async (chainId, account, amount) => {
|
||||
);
|
||||
}
|
||||
|
||||
export const ghost = async (chainId, account, receiver, amount) => {
|
||||
const messages = {
|
||||
replacedMsg: "Bridge transaction was replaced. Wait for inclusion please.",
|
||||
successMsg: `Amount successfully bridged! Check tx hash status or wait for slow clap finalization.`,
|
||||
errorMsg: "Bridge transaction failed. Check logs for error detalization.",
|
||||
};
|
||||
|
||||
const txHash = await executeOnChainTransaction(
|
||||
chainId,
|
||||
"ghost",
|
||||
[receiver, amount],
|
||||
account,
|
||||
messages
|
||||
);
|
||||
|
||||
return txHash;
|
||||
}
|
||||
|
||||
const executeOnChainTransaction = async (
|
||||
chainId,
|
||||
functionName,
|
||||
@ -211,8 +259,11 @@ const executeOnChainTransaction = async (
|
||||
});
|
||||
|
||||
toast.success(messages.successMsg);
|
||||
|
||||
return txHash;
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
toast.error(messages.errorMsg)
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
|
@ -14,7 +14,6 @@ const queryClient = new QueryClient();
|
||||
const TRACKING_ID = import.meta.env.VITE_APP_TRACKING_ID;
|
||||
ReactGA.initialize(TRACKING_ID);
|
||||
|
||||
|
||||
ReactDOM.createRoot(document.getElementById('root')).render(
|
||||
<>
|
||||
<BackgroundCanvas />
|
||||
|
@ -18,7 +18,7 @@ export const darkPalette = {
|
||||
success: "#60C45B", // idk where this is - done
|
||||
userFeedback: "#49A1F2", // idk where this is
|
||||
error: "#F06F73", // red negative % - done
|
||||
warning: "#F06F73", // idk where this is - done
|
||||
warning: "#49A1F2", // idk where this is - done
|
||||
pnlGain: "#60C45B", // green positive % - done
|
||||
},
|
||||
gray: {
|
||||
|
Loading…
Reference in New Issue
Block a user