Compare commits
5 Commits
856bf01ffe
...
bc5f88d572
Author | SHA1 | Date | |
---|---|---|---|
bc5f88d572 | |||
1143a3d491 | |||
ad4b539961 | |||
f64570eea5 | |||
5dffd62c5a |
@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "ghost-dao-interface",
|
"name": "ghost-dao-interface",
|
||||||
"private": true,
|
"private": true,
|
||||||
"version": "0.1.2",
|
"version": "0.2.0",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "vite",
|
"dev": "vite",
|
||||||
@ -18,6 +18,8 @@
|
|||||||
"@mui/icons-material": "^6.4.7",
|
"@mui/icons-material": "^6.4.7",
|
||||||
"@mui/material": "^6.4.7",
|
"@mui/material": "^6.4.7",
|
||||||
"@mui/utils": "^6.4.6",
|
"@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": "^5.67.2",
|
||||||
"@tanstack/react-query-devtools": "^5.67.2",
|
"@tanstack/react-query-devtools": "^5.67.2",
|
||||||
"@wagmi/core": "^2.17.3",
|
"@wagmi/core": "^2.17.3",
|
||||||
|
@ -32,6 +32,12 @@ importers:
|
|||||||
'@mui/utils':
|
'@mui/utils':
|
||||||
specifier: ^6.4.6
|
specifier: ^6.4.6
|
||||||
version: 6.4.6(@types/react@19.0.10)(react@19.0.0)
|
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':
|
'@tanstack/react-query':
|
||||||
specifier: ^5.67.2
|
specifier: ^5.67.2
|
||||||
version: 5.67.2(react@19.0.0)
|
version: 5.67.2(react@19.0.0)
|
||||||
@ -723,6 +729,10 @@ packages:
|
|||||||
resolution: {integrity: sha512-HxngEd2XUcg9xi20JkwlLCtYwfoFw4JGkuZpT+WlsPD4gB/cxkvTD8fSsoAnphGZhFdZYKeQIPCuFlWPm1uE0g==}
|
resolution: {integrity: sha512-HxngEd2XUcg9xi20JkwlLCtYwfoFw4JGkuZpT+WlsPD4gB/cxkvTD8fSsoAnphGZhFdZYKeQIPCuFlWPm1uE0g==}
|
||||||
engines: {node: ^14.21.3 || >=16}
|
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':
|
'@noble/hashes@1.4.0':
|
||||||
resolution: {integrity: sha512-V1JJ1WTRUqHHrOSh597hURcMqVKVGL/ea3kv0gSnEdsEZ0/+VyPghM1lMNGc00z7CIQorSvbKpuJkxvuHbvdbg==}
|
resolution: {integrity: sha512-V1JJ1WTRUqHHrOSh597hURcMqVKVGL/ea3kv0gSnEdsEZ0/+VyPghM1lMNGc00z7CIQorSvbKpuJkxvuHbvdbg==}
|
||||||
engines: {node: '>= 16'}
|
engines: {node: '>= 16'}
|
||||||
@ -743,6 +753,12 @@ packages:
|
|||||||
resolution: {integrity: sha512-IHnV6A+zxU7XwmKFinmYjUcwlyK9+xkG3/s9KcQhI9BjQKycrJ1JRO+FbNYPwZiPKW3je/DR0k7w8/gLa5eaxQ==}
|
resolution: {integrity: sha512-IHnV6A+zxU7XwmKFinmYjUcwlyK9+xkG3/s9KcQhI9BjQKycrJ1JRO+FbNYPwZiPKW3je/DR0k7w8/gLa5eaxQ==}
|
||||||
deprecated: 'The package is now available as "qr": npm install qr'
|
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':
|
'@popperjs/core@2.11.8':
|
||||||
resolution: {integrity: sha512-P1st0aksCrn9sGZhp8GMYwBnQsbvAWsZAX44oXNNvLHGqAOcoVxmjZiohstwQ7SqKnbR47akdNi+uleWD8+g6A==}
|
resolution: {integrity: sha512-P1st0aksCrn9sGZhp8GMYwBnQsbvAWsZAX44oXNNvLHGqAOcoVxmjZiohstwQ7SqKnbR47akdNi+uleWD8+g6A==}
|
||||||
|
|
||||||
@ -913,6 +929,9 @@ packages:
|
|||||||
'@scure/bip39@1.6.0':
|
'@scure/bip39@1.6.0':
|
||||||
resolution: {integrity: sha512-+lF0BbLiJNwVlev4eKelw1WWLaiKXw7sSl8T6FvBlWkdX+94aGJ4o8XjUdlyhTCjd8c+B3KT3JfS8P0bLRNU6A==}
|
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':
|
'@socket.io/component-emitter@3.1.2':
|
||||||
resolution: {integrity: sha512-9BCxFwvbGg/RsZK9tjXd8s4UcwR0MWeFQ1XEKIQVVvAGJyINdrqKMcTRyLoK8Rse1GjzLV9cwjWV1olXRWEXVA==}
|
resolution: {integrity: sha512-9BCxFwvbGg/RsZK9tjXd8s4UcwR0MWeFQ1XEKIQVVvAGJyINdrqKMcTRyLoK8Rse1GjzLV9cwjWV1olXRWEXVA==}
|
||||||
|
|
||||||
@ -2375,6 +2394,9 @@ packages:
|
|||||||
engines: {node: '>=16.0.0'}
|
engines: {node: '>=16.0.0'}
|
||||||
hasBin: true
|
hasBin: true
|
||||||
|
|
||||||
|
scale-ts@1.6.1:
|
||||||
|
resolution: {integrity: sha512-PBMc2AWc6wSEqJYBDPcyCLUj9/tMKnLX70jLOSndMtcUoLQucP/DM0vnQo1wJAYjTrQiq8iG9rD0q6wFzgjH7g==}
|
||||||
|
|
||||||
scheduler@0.25.0:
|
scheduler@0.25.0:
|
||||||
resolution: {integrity: sha512-xFVuu11jh+xcO7JOAGJNOXld8/TcEHK/4CituBUeUb5hqxJLj9YuemAEuvm9gQ/+pgXYfbQuqAkiYu+u7YEsNA==}
|
resolution: {integrity: sha512-xFVuu11jh+xcO7JOAGJNOXld8/TcEHK/4CituBUeUb5hqxJLj9YuemAEuvm9gQ/+pgXYfbQuqAkiYu+u7YEsNA==}
|
||||||
|
|
||||||
@ -3556,6 +3578,10 @@ snapshots:
|
|||||||
dependencies:
|
dependencies:
|
||||||
'@noble/hashes': 1.8.0
|
'@noble/hashes': 1.8.0
|
||||||
|
|
||||||
|
'@noble/curves@1.9.6':
|
||||||
|
dependencies:
|
||||||
|
'@noble/hashes': 1.8.0
|
||||||
|
|
||||||
'@noble/hashes@1.4.0': {}
|
'@noble/hashes@1.4.0': {}
|
||||||
|
|
||||||
'@noble/hashes@1.7.0': {}
|
'@noble/hashes@1.7.0': {}
|
||||||
@ -3566,6 +3592,16 @@ snapshots:
|
|||||||
|
|
||||||
'@paulmillr/qr@0.2.1': {}
|
'@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': {}
|
'@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)':
|
'@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
|
'@noble/hashes': 1.8.0
|
||||||
'@scure/base': 1.2.6
|
'@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': {}
|
'@socket.io/component-emitter@3.1.2': {}
|
||||||
|
|
||||||
'@svgr/babel-plugin-add-jsx-attribute@8.0.0(@babel/core@7.26.9)':
|
'@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):
|
ox@0.6.7(zod@3.22.4):
|
||||||
dependencies:
|
dependencies:
|
||||||
'@adraffy/ens-normalize': 1.11.0
|
'@adraffy/ens-normalize': 1.11.0
|
||||||
'@noble/curves': 1.8.1
|
'@noble/curves': 1.9.2
|
||||||
'@noble/hashes': 1.7.1
|
'@noble/hashes': 1.8.0
|
||||||
'@scure/bip32': 1.6.2
|
'@scure/bip32': 1.6.2
|
||||||
'@scure/bip39': 1.5.4
|
'@scure/bip39': 1.5.4
|
||||||
abitype: 1.0.8(zod@3.22.4)
|
abitype: 1.0.8(zod@3.22.4)
|
||||||
@ -5842,6 +5883,8 @@ snapshots:
|
|||||||
sass-embedded-win32-ia32: 1.85.1
|
sass-embedded-win32-ia32: 1.85.1
|
||||||
sass-embedded-win32-x64: 1.85.1
|
sass-embedded-win32-x64: 1.85.1
|
||||||
|
|
||||||
|
scale-ts@1.6.1: {}
|
||||||
|
|
||||||
scheduler@0.25.0: {}
|
scheduler@0.25.0: {}
|
||||||
|
|
||||||
scss@0.2.4:
|
scss@0.2.4:
|
||||||
|
@ -27,6 +27,7 @@ const StakeContainer = lazy(() => import("./containers/Stake/StakeContainer"));
|
|||||||
const TreasuryDashboard = lazy(() => import("./containers/TreasuryDashboard/TreasuryDashboard"));
|
const TreasuryDashboard = lazy(() => import("./containers/TreasuryDashboard/TreasuryDashboard"));
|
||||||
const Faucet = lazy(() => import("./containers/Faucet/Faucet"));
|
const Faucet = lazy(() => import("./containers/Faucet/Faucet"));
|
||||||
const Dex = lazy(() => import("./containers/Dex/Dex"));
|
const Dex = lazy(() => import("./containers/Dex/Dex"));
|
||||||
|
const Bridge = lazy(() => import("./containers/Bridge/Bridge"));
|
||||||
const NotFound = lazy(() => import("./containers/NotFound/NotFound"));
|
const NotFound = lazy(() => import("./containers/NotFound/NotFound"));
|
||||||
|
|
||||||
const PREFIX = "App";
|
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="/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="/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="/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} />} />
|
<Route path="/dex/:name" element={<Dex connect={tryConnectInjected} address={address} chainId={addressChainId ? addressChainId : chainId} />} />
|
||||||
</>
|
</>
|
||||||
}
|
}
|
||||||
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
Before Width: | Height: | Size: 3.0 KiB After Width: | Height: | Size: 3.0 KiB |
Before Width: | Height: | Size: 10 KiB After Width: | Height: | Size: 10 KiB |
@ -132,6 +132,7 @@ const NavItem = ({
|
|||||||
const LinkItem = () => (
|
const LinkItem = () => (
|
||||||
<Link {...linkProps} {...props} underline="hover">
|
<Link {...linkProps} {...props} underline="hover">
|
||||||
<Box
|
<Box
|
||||||
|
sx={{ fontFamily: "Ubuntu" }}
|
||||||
display="flex"
|
display="flex"
|
||||||
flexDirection="row"
|
flexDirection="row"
|
||||||
alignItems="center"
|
alignItems="center"
|
||||||
|
@ -2,7 +2,7 @@ import { Box, Typography, useMediaQuery, useTheme } from "@mui/material";
|
|||||||
|
|
||||||
const PageTitle = ({ name, subtitle, noMargin }) => {
|
const PageTitle = ({ name, subtitle, noMargin }) => {
|
||||||
const theme = useTheme();
|
const theme = useTheme();
|
||||||
const mobile = useMediaQuery(theme.breakpoints.down("sm"));
|
const mobile = useMediaQuery(theme.breakpoints.down("700"));
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Box
|
<Box
|
||||||
|
@ -47,7 +47,8 @@ import BondDiscount from "../../containers/Bond/components/BondDiscount";
|
|||||||
import DashboardIcon from '@mui/icons-material/Dashboard';
|
import DashboardIcon from '@mui/icons-material/Dashboard';
|
||||||
import ShowerIcon from '@mui/icons-material/Shower';
|
import ShowerIcon from '@mui/icons-material/Shower';
|
||||||
|
|
||||||
import { useFtsoPrice, useGhstPrice } from "../../hooks/prices";
|
import { useTokenSymbol } from "../../hooks/tokens";
|
||||||
|
import { useFtsoPrice, useGhstPrice, useGhostedSupplyPrice } from "../../hooks/prices";
|
||||||
import { useLiveBonds } from "../../hooks/bonds/index";
|
import { useLiveBonds } from "../../hooks/bonds/index";
|
||||||
|
|
||||||
const PREFIX = "NavContent";
|
const PREFIX = "NavContent";
|
||||||
@ -66,6 +67,10 @@ const NavContent = ({ chainId, addressChainId }) => {
|
|||||||
const { liveBonds: ghostBonds } = useLiveBonds(chainId);
|
const { liveBonds: ghostBonds } = useLiveBonds(chainId);
|
||||||
const ftsoPrice = useFtsoPrice(chainId);
|
const ftsoPrice = useFtsoPrice(chainId);
|
||||||
const ghstPrice = useGhstPrice(chainId);
|
const ghstPrice = useGhstPrice(chainId);
|
||||||
|
const ghostedSupplyPrice = useGhostedSupplyPrice(chainId);
|
||||||
|
|
||||||
|
const { symbol: ftsoSymbol } = useTokenSymbol(chainId, "FTSO");
|
||||||
|
const { symbol: ghstSymbol } = useTokenSymbol(chainId, "GHST");
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Paper className="dapp-sidebar">
|
<Paper className="dapp-sidebar">
|
||||||
@ -82,16 +87,19 @@ const NavContent = ({ chainId, addressChainId }) => {
|
|||||||
</Link>
|
</Link>
|
||||||
<Box display="flex" flexDirection="column" mt="10px">
|
<Box display="flex" flexDirection="column" mt="10px">
|
||||||
<Box fontSize="12px" fontWeight="500" lineHeight={"15px"}>
|
<Box fontSize="12px" fontWeight="500" lineHeight={"15px"}>
|
||||||
FTSO Price: {formatCurrency(ftsoPrice, 2)}
|
{ftsoSymbol} Price: {formatCurrency(ftsoPrice, 2)}
|
||||||
</Box>
|
</Box>
|
||||||
<Box fontSize="12px" fontWeight="500" lineHeight="15px">
|
<Box fontSize="12px" fontWeight="500" lineHeight="15px">
|
||||||
GHST Price: {formatCurrency(ghstPrice, 2)}
|
{ghstSymbol} Price: {formatCurrency(ghstPrice, 2)}
|
||||||
|
</Box>
|
||||||
|
<Box fontSize="12px" fontWeight="500" lineHeight={"15px"}>
|
||||||
|
Ghosted Supply: {formatCurrency(ghostedSupplyPrice, 2)}
|
||||||
</Box>
|
</Box>
|
||||||
</Box>
|
</Box>
|
||||||
</Box>
|
</Box>
|
||||||
|
|
||||||
<Box className="menu-divider">
|
<Box className="menu-divider">
|
||||||
<Divider />
|
<Divider />
|
||||||
</Box>
|
</Box>
|
||||||
|
|
||||||
<div className="dapp-menu-links">
|
<div className="dapp-menu-links">
|
||||||
@ -137,6 +145,7 @@ const NavContent = ({ chainId, addressChainId }) => {
|
|||||||
/>
|
/>
|
||||||
<NavItem icon={StakeIcon} label={`Stake`} to="/stake" />
|
<NavItem icon={StakeIcon} label={`Stake`} to="/stake" />
|
||||||
<NavItem icon={ShowerIcon} label={`Faucet`} to="/faucet" />
|
<NavItem icon={ShowerIcon} label={`Faucet`} to="/faucet" />
|
||||||
|
<NavItem icon={PublicIcon} label={`Bridge`} to="/bridge" />
|
||||||
<NavItem
|
<NavItem
|
||||||
icon={CurrencyExchangeIcon}
|
icon={CurrencyExchangeIcon}
|
||||||
label={`Dex`}
|
label={`Dex`}
|
||||||
@ -167,7 +176,6 @@ const NavContent = ({ chainId, addressChainId }) => {
|
|||||||
</>
|
</>
|
||||||
}
|
}
|
||||||
|
|
||||||
<NavItem icon={PublicIcon} label={`Bridge`} href="https://bridge.ghostchain.io/" />
|
|
||||||
<NavItem
|
<NavItem
|
||||||
to=''
|
to=''
|
||||||
icon={PublicIcon}
|
icon={PublicIcon}
|
||||||
|
@ -28,14 +28,14 @@ const StyledArrow = styled(Box)(
|
|||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
const SwapCollection = ({ UpperSwapCard, LowerSwapCard, arrowOnClick }) => {
|
const SwapCollection = ({ UpperSwapCard, LowerSwapCard, arrowOnClick, iconNotNeeded }) => {
|
||||||
const theme = useTheme();
|
const theme = useTheme();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Box display="flex" flexDirection="column" maxWidth="476px">
|
<Box display="flex" flexDirection="column" maxWidth="476px">
|
||||||
{UpperSwapCard}
|
{UpperSwapCard}
|
||||||
<Box display="flex" flexDirection="row" justifyContent="center">
|
<Box display="flex" flexDirection="row" justifyContent="center">
|
||||||
<StyledArrow
|
{!iconNotNeeded && (<StyledArrow
|
||||||
width="21px"
|
width="21px"
|
||||||
height="21px"
|
height="21px"
|
||||||
borderRadius="6px"
|
borderRadius="6px"
|
||||||
@ -55,7 +55,8 @@ const SwapCollection = ({ UpperSwapCard, LowerSwapCard, arrowOnClick }) => {
|
|||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
</Box>
|
</Box>
|
||||||
</StyledArrow>
|
</StyledArrow>)}
|
||||||
|
{iconNotNeeded && <Box height="21px" />}
|
||||||
</Box>
|
</Box>
|
||||||
<Box marginTop="-7px">{LowerSwapCard}</Box>
|
<Box marginTop="-7px">{LowerSwapCard}</Box>
|
||||||
</Box>
|
</Box>
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
import { SvgIcon } from "@mui/material";
|
import { SvgIcon } from "@mui/material";
|
||||||
import { styled } from "@mui/material/styles";
|
import { styled } from "@mui/material/styles";
|
||||||
|
|
||||||
import FtsoIcon from "../../assets/tokens/eGHST.svg?react";
|
import FtsoIcon from "../../assets/tokens/FTSO.svg?react";
|
||||||
import StnkIcon from "../../assets/tokens/sGHST.svg?react";
|
import StnkIcon from "../../assets/tokens/STNK.svg?react";
|
||||||
import GhstIcon from "../../assets/tokens/GHST.svg?react";
|
import GhstIcon from "../../assets/tokens/GHST.svg?react";
|
||||||
import DaiIcon from "../../assets/tokens/DAI.svg?react";
|
import DaiIcon from "../../assets/tokens/DAI.svg?react";
|
||||||
import WethIcon from "../../assets/tokens/wETH.svg?react";
|
import WethIcon from "../../assets/tokens/wETH.svg?react";
|
||||||
@ -30,15 +30,27 @@ const Token = ({ name, viewBox = "0 0 260 260", fontSize = "large", ...props })
|
|||||||
case "FTSO":
|
case "FTSO":
|
||||||
icon = FtsoIcon;
|
icon = FtsoIcon;
|
||||||
break;
|
break;
|
||||||
|
case "ECSPR":
|
||||||
|
icon = FtsoIcon;
|
||||||
|
break;
|
||||||
case "STNK":
|
case "STNK":
|
||||||
icon = StnkIcon;
|
icon = StnkIcon;
|
||||||
break;
|
break;
|
||||||
|
case "SCSPR":
|
||||||
|
icon = StnkIcon;
|
||||||
|
break;
|
||||||
case "GHST":
|
case "GHST":
|
||||||
icon = GhstIcon;
|
icon = GhstIcon;
|
||||||
break;
|
break;
|
||||||
|
case "CSPR":
|
||||||
|
icon = GhstIcon;
|
||||||
|
break;
|
||||||
case "GDAI":
|
case "GDAI":
|
||||||
icon = DaiIcon;
|
icon = DaiIcon;
|
||||||
break;
|
break;
|
||||||
|
case "DAI":
|
||||||
|
icon = DaiIcon;
|
||||||
|
break;
|
||||||
case "ETH":
|
case "ETH":
|
||||||
icon = WethIcon;
|
icon = WethIcon;
|
||||||
break;
|
break;
|
||||||
|
@ -14,7 +14,7 @@ import EthIcon from "../../assets/tokens/ETH.svg?react";
|
|||||||
import { useSwitchChain } from 'wagmi';
|
import { useSwitchChain } from 'wagmi';
|
||||||
import toast from "react-hot-toast";
|
import toast from "react-hot-toast";
|
||||||
|
|
||||||
function SelectNetwork({ chainId, wrongNetworkToastId, setWrongNetworkToastId }) {
|
function SelectNetwork({ chainId, wrongNetworkToastId, setWrongNetworkToastId, small }) {
|
||||||
const theme = useTheme();
|
const theme = useTheme();
|
||||||
const { chains, switchChain } = useSwitchChain();
|
const { chains, switchChain } = useSwitchChain();
|
||||||
|
|
||||||
@ -37,7 +37,7 @@ function SelectNetwork({ chainId, wrongNetworkToastId, setWrongNetworkToastId })
|
|||||||
}
|
}
|
||||||
|
|
||||||
return(
|
return(
|
||||||
<FormControl sx={{ width: "155px" }}>
|
<FormControl sx={{ width: small ? "100px" : "155px" }}>
|
||||||
<Select
|
<Select
|
||||||
labelId="network-select-helper-label"
|
labelId="network-select-helper-label"
|
||||||
id="network-select-helper"
|
id="network-select-helper"
|
||||||
@ -58,7 +58,7 @@ function SelectNetwork({ chainId, wrongNetworkToastId, setWrongNetworkToastId })
|
|||||||
<MenuItem key={chain.name} value={chain.id}>
|
<MenuItem key={chain.name} value={chain.id}>
|
||||||
<Box gap="10px" display="flex" flexDirection="row" alignItems="center">
|
<Box gap="10px" display="flex" flexDirection="row" alignItems="center">
|
||||||
<SvgIcon component={EthIcon} viewBox="0 0 32 32" />
|
<SvgIcon component={EthIcon} viewBox="0 0 32 32" />
|
||||||
<Typography>{chain.name}</Typography>
|
{!small && <Typography>{chain.name}</Typography>}
|
||||||
</Box>
|
</Box>
|
||||||
</MenuItem>
|
</MenuItem>
|
||||||
)
|
)
|
||||||
|
@ -23,6 +23,7 @@ function TopBar({
|
|||||||
}) {
|
}) {
|
||||||
const themeColor = useTheme();
|
const themeColor = useTheme();
|
||||||
const desktop = useMediaQuery(themeColor.breakpoints.up(1048));
|
const desktop = useMediaQuery(themeColor.breakpoints.up(1048));
|
||||||
|
const small = useMediaQuery(themeColor.breakpoints.down(400));
|
||||||
return (
|
return (
|
||||||
<Box
|
<Box
|
||||||
display="flex"
|
display="flex"
|
||||||
@ -32,11 +33,12 @@ function TopBar({
|
|||||||
marginRight={desktop ? "33px" : "0px"}
|
marginRight={desktop ? "33px" : "0px"}
|
||||||
>
|
>
|
||||||
<Box display="flex" alignItems="center">
|
<Box display="flex" alignItems="center">
|
||||||
<Box display="flex" justifyContent="space-between" alignItems="center" width="320px">
|
<Box display="flex" justifyContent="space-between" alignItems="center" width={small ? "calc(100vw - 78px)" : "320px"}>
|
||||||
<SelectNetwork
|
<SelectNetwork
|
||||||
wrongNetworkToastId={wrongNetworkToastId}
|
wrongNetworkToastId={wrongNetworkToastId}
|
||||||
setWrongNetworkToastId={setWrongNetworkToastId}
|
setWrongNetworkToastId={setWrongNetworkToastId}
|
||||||
chainId={chainId}
|
chainId={chainId}
|
||||||
|
small={small}
|
||||||
/>
|
/>
|
||||||
<Wallet address={address} connect={connect} chainId={chainId} />
|
<Wallet address={address} connect={connect} chainId={chainId} />
|
||||||
</Box>
|
</Box>
|
||||||
|
@ -152,7 +152,7 @@ function InitialWalletView({ address, chainId, onClose }) {
|
|||||||
fullWidth
|
fullWidth
|
||||||
onClick={() => onBtnClick("uniswap", DAI_ADDRESSES[chainId], FTSO_ADDRESSES[chainId])}
|
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>
|
</SecondaryButton>
|
||||||
</Box>
|
</Box>
|
||||||
|
|
||||||
|
@ -18,7 +18,7 @@ import GhostStyledIcon from "../../Icon/GhostIcon";
|
|||||||
import TokenStack from "../../TokenStack/TokenStack";
|
import TokenStack from "../../TokenStack/TokenStack";
|
||||||
import { PrimaryButton, SecondaryButton } from "../../Button";
|
import { PrimaryButton, SecondaryButton } from "../../Button";
|
||||||
|
|
||||||
import { useBalance } from "../../../hooks/tokens";
|
import { useBalance, useTokenSymbol } from "../../../hooks/tokens";
|
||||||
import { useDaiPrice, useFtsoPrice, useStnkPrice, useGhstPrice } from "../../../hooks/prices";
|
import { useDaiPrice, useFtsoPrice, useStnkPrice, useGhstPrice } from "../../../hooks/prices";
|
||||||
import { useLpValuation } from "../../../hooks/treasury";
|
import { useLpValuation } from "../../../hooks/treasury";
|
||||||
import { useAccount } from "wagmi";
|
import { useAccount } from "wagmi";
|
||||||
@ -76,7 +76,7 @@ export const Token = (props) => {
|
|||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
|
|
||||||
const useLink = (symbol, fromAddress, toAddress, isPool) => {
|
const useLink = (symbol, fromAddress, toAddress, isPool) => {
|
||||||
if (symbol === "GDAI") {
|
if (symbol.toUpperCase() === "GDAI") {
|
||||||
navigate({ pathname: "/faucet" })
|
navigate({ pathname: "/faucet" })
|
||||||
} else {
|
} else {
|
||||||
navigate({
|
navigate({
|
||||||
@ -133,7 +133,7 @@ export const Token = (props) => {
|
|||||||
onClick={() => useLink(symbol, daiAddress, address, isPool)}
|
onClick={() => useLink(symbol, daiAddress, address, isPool)}
|
||||||
fullWidth
|
fullWidth
|
||||||
>
|
>
|
||||||
<Typography>Get on {symbol === "GDAI" ? "Faucet" : "Uniswap"}</Typography>
|
<Typography>Get on {symbol.toUpperCase() === "GDAI" ? "Faucet" : "Uniswap"}</Typography>
|
||||||
</SecondaryButton>
|
</SecondaryButton>
|
||||||
</Box>
|
</Box>
|
||||||
</Box>
|
</Box>
|
||||||
@ -178,9 +178,15 @@ export const useWallet = (chainId, userAddress) => {
|
|||||||
const ghstPrice = useGhstPrice(chainId);
|
const ghstPrice = useGhstPrice(chainId);
|
||||||
const lpDaiFtsoPrice = useLpValuation(chainId, "GDAI_FTSO", 1000000000000000000n);
|
const lpDaiFtsoPrice = useLpValuation(chainId, "GDAI_FTSO", 1000000000000000000n);
|
||||||
|
|
||||||
|
const { symbol: daiSymbol } = useTokenSymbol(chainId, "GDAI");
|
||||||
|
const { symbol: ftsoSymbol } = useTokenSymbol(chainId, "FTSO");
|
||||||
|
const { symbol: stnkSymbol } = useTokenSymbol(chainId, "STNK");
|
||||||
|
const { symbol: ghstSymbol } = useTokenSymbol(chainId, "GHST");
|
||||||
|
const { symbol: lpDaiFtsoSymbol } = useTokenSymbol(chainId, "GDAI_FTSO");
|
||||||
|
|
||||||
const tokens = {
|
const tokens = {
|
||||||
dai: {
|
dai: {
|
||||||
symbol: "GDAI",
|
symbol: daiSymbol,
|
||||||
address: daiAddress,
|
address: daiAddress,
|
||||||
balance: daiBalance,
|
balance: daiBalance,
|
||||||
price: daiPrice,
|
price: daiPrice,
|
||||||
@ -188,7 +194,7 @@ export const useWallet = (chainId, userAddress) => {
|
|||||||
externalUrl: "https://ghostchain.io/wp-content/uploads/2025/03/gDAI.svg",
|
externalUrl: "https://ghostchain.io/wp-content/uploads/2025/03/gDAI.svg",
|
||||||
},
|
},
|
||||||
ftso: {
|
ftso: {
|
||||||
symbol: "FTSO",
|
symbol: ftsoSymbol,
|
||||||
address: ftsoAddress,
|
address: ftsoAddress,
|
||||||
balance: ftsoBalance,
|
balance: ftsoBalance,
|
||||||
price: ftsoPrice,
|
price: ftsoPrice,
|
||||||
@ -196,7 +202,7 @@ export const useWallet = (chainId, userAddress) => {
|
|||||||
externalUrl: "https://ghostchain.io/wp-content/uploads/2025/03/eGHST.svg",
|
externalUrl: "https://ghostchain.io/wp-content/uploads/2025/03/eGHST.svg",
|
||||||
},
|
},
|
||||||
stnk: {
|
stnk: {
|
||||||
symbol: "STNK",
|
symbol: stnkSymbol,
|
||||||
address: stnkAddress,
|
address: stnkAddress,
|
||||||
balance: stnkBalance,
|
balance: stnkBalance,
|
||||||
price: stnkPrice,
|
price: stnkPrice,
|
||||||
@ -204,7 +210,7 @@ export const useWallet = (chainId, userAddress) => {
|
|||||||
externalUrl: "https://ghostchain.io/wp-content/uploads/2025/03/sGHST.svg",
|
externalUrl: "https://ghostchain.io/wp-content/uploads/2025/03/sGHST.svg",
|
||||||
},
|
},
|
||||||
ghst: {
|
ghst: {
|
||||||
symbol: "GHST",
|
symbol: ghstSymbol,
|
||||||
address: ghstAddress,
|
address: ghstAddress,
|
||||||
balance: ghstBalance,
|
balance: ghstBalance,
|
||||||
price: ghstPrice,
|
price: ghstPrice,
|
||||||
@ -213,7 +219,7 @@ export const useWallet = (chainId, userAddress) => {
|
|||||||
},
|
},
|
||||||
daiFtso: {
|
daiFtso: {
|
||||||
isPool: true,
|
isPool: true,
|
||||||
symbol: "UNI-V2",
|
symbol: lpDaiFtsoSymbol,
|
||||||
address: lpDaiFtsoBalanceAddress,
|
address: lpDaiFtsoBalanceAddress,
|
||||||
balance: lpDaiFtsoBalance,
|
balance: lpDaiFtsoBalance,
|
||||||
price: lpDaiFtsoPrice,
|
price: lpDaiFtsoPrice,
|
||||||
@ -248,8 +254,8 @@ export const Tokens = ({ address, tokens, onClose }) => {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
{alwaysShowTokens.map(token => (
|
{alwaysShowTokens.map((token, i) => (
|
||||||
<Token key={token.symbol} {...tokenProps(token)} />
|
<Token key={i} {...tokenProps(token)} />
|
||||||
))}
|
))}
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
|
@ -6,7 +6,6 @@ export const config = createConfig({
|
|||||||
transports: {
|
transports: {
|
||||||
[sepolia.id]: fallback([
|
[sepolia.id]: fallback([
|
||||||
http('https://ethereum-sepolia-rpc.publicnode.com'),
|
http('https://ethereum-sepolia-rpc.publicnode.com'),
|
||||||
http('https://rpc-sepolia.rockx.com/'),
|
|
||||||
http('https://1rpc.io/sepolia'),
|
http('https://1rpc.io/sepolia'),
|
||||||
http('https://eth-sepolia.public.blastapi.io'),
|
http('https://eth-sepolia.public.blastapi.io'),
|
||||||
http('https://0xrpc.io/sep'),
|
http('https://0xrpc.io/sep'),
|
||||||
|
@ -1,32 +1,32 @@
|
|||||||
import { NetworkId } from "../constants";
|
import { NetworkId } from "../constants";
|
||||||
|
|
||||||
export const STAKING_ADDRESSES = {
|
export const STAKING_ADDRESSES = {
|
||||||
[NetworkId.TESTNET_SEPOLIA]: "0xb22Ad3b4a23EaEA8c06CD151D7C0e3758d0FB580",
|
[NetworkId.TESTNET_SEPOLIA]: "0xd90E63E88282596E1ea33765b41Ba3d650f4aD52",
|
||||||
[NetworkId.TESTNET_HOODI]: "0x25F62eDc6C89FF84E957C22336A35d2dfc861a86",
|
[NetworkId.TESTNET_HOODI]: "0x25F62eDc6C89FF84E957C22336A35d2dfc861a86",
|
||||||
};
|
};
|
||||||
|
|
||||||
export const BOND_DEPOSITORY_ADDRESSES = {
|
export const BOND_DEPOSITORY_ADDRESSES = {
|
||||||
[NetworkId.TESTNET_SEPOLIA]: "0x8773AC3258b31D3ACfc99Ffd13768ccB170fcF9f",
|
[NetworkId.TESTNET_SEPOLIA]: "0xdcE486113280e49ca2fB200258E5Ee1B2D21D495",
|
||||||
[NetworkId.TESTNET_HOODI]: "0x6Ad50B1E293E68B2fC230c576220a93A9D311571",
|
[NetworkId.TESTNET_HOODI]: "0x6Ad50B1E293E68B2fC230c576220a93A9D311571",
|
||||||
};
|
};
|
||||||
|
|
||||||
export const DAO_TREASURY_ADDRESSES = {
|
export const DAO_TREASURY_ADDRESSES = {
|
||||||
[NetworkId.TESTNET_SEPOLIA]: "0x2AAd1EA51044e69756880f580C13a92D910af238",
|
[NetworkId.TESTNET_SEPOLIA]: "0x93dd30f819403710de7933B79A74C4A42438458D",
|
||||||
[NetworkId.TESTNET_HOODI]: "0x1a1b29b18f714fac9dDabEf530dFc4f85b56A6e8",
|
[NetworkId.TESTNET_HOODI]: "0x1a1b29b18f714fac9dDabEf530dFc4f85b56A6e8",
|
||||||
};
|
};
|
||||||
|
|
||||||
export const FTSO_DAI_LP_ADDRESSES = {
|
export const FTSO_DAI_LP_ADDRESSES = {
|
||||||
[NetworkId.TESTNET_SEPOLIA]: "0x64B19626bd074cf7B1019798846c363bbA8A0d53",
|
[NetworkId.TESTNET_SEPOLIA]: "0x1394dC3f7bABaa2F0CA80353648087DAB1BF3fd6",
|
||||||
[NetworkId.TESTNET_HOODI]: "0xf7B2d44209E70782d93A70F7D8eC50010dF7ae50", // TBD
|
[NetworkId.TESTNET_HOODI]: "0xf7B2d44209E70782d93A70F7D8eC50010dF7ae50",
|
||||||
};
|
};
|
||||||
|
|
||||||
export const FTSO_STNK_LP_ADDRESSES = {
|
export const FTSO_STNK_LP_ADDRESSES = {
|
||||||
[NetworkId.TESTNET_SEPOLIA]: "0x29965676fc00C3eA9717B2A02739d294399a382e",
|
|
||||||
[NetworkId.TESTNET_SEPOLIA]: "0x0000000000000000000000000000000000000000", // TBD
|
[NetworkId.TESTNET_SEPOLIA]: "0x0000000000000000000000000000000000000000", // TBD
|
||||||
|
[NetworkId.TESTNET_SEPOLIA]: "0x0000000000000000000000000000000000000000",
|
||||||
}
|
}
|
||||||
|
|
||||||
export const DAI_ADDRESSES = {
|
export const DAI_ADDRESSES = {
|
||||||
[NetworkId.TESTNET_SEPOLIA]: "0xc7Afd3bC4c74f6E07880447b1759d5d639F2525F",
|
[NetworkId.TESTNET_SEPOLIA]: "0x5f63a27a9214a0352F2EF8dAF1eD4974d713192B",
|
||||||
[NetworkId.TESTNET_HOODI]: "0x80c6676c334BCcE60b3CC852085B72143379CE58",
|
[NetworkId.TESTNET_HOODI]: "0x80c6676c334BCcE60b3CC852085B72143379CE58",
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -36,35 +36,39 @@ export const WETH_ADDRESSES = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export const GHST_ADDRESSES = {
|
export const GHST_ADDRESSES = {
|
||||||
[NetworkId.TESTNET_SEPOLIA]: "0x4643076087234d9B81974beF1eC9c25F3A0202B9",
|
[NetworkId.TESTNET_SEPOLIA]: "0xdf2e5306A3dCcfA4e21bbF4226C17Ff5B008dDC4",
|
||||||
[NetworkId.TESTNET_HOODI]: "0xE98f7426457E6533B206e91B7EcA97aa8A258B46",
|
[NetworkId.TESTNET_HOODI]: "0xE98f7426457E6533B206e91B7EcA97aa8A258B46",
|
||||||
};
|
};
|
||||||
|
|
||||||
export const STNK_ADDRESSES = {
|
export const STNK_ADDRESSES = {
|
||||||
[NetworkId.TESTNET_SEPOLIA]: "0x84060da636f5a83f2668ad238f09f8c667a1ec8b",
|
[NetworkId.TESTNET_SEPOLIA]: "0x02C296A27eA779d5a16F934337c12062C5E3c0D9",
|
||||||
[NetworkId.TESTNET_HOODI]: "0xF07e9303A9f16Afd82f4f57Fd6fca68Aa0AB6D7F",
|
[NetworkId.TESTNET_HOODI]: "0xF07e9303A9f16Afd82f4f57Fd6fca68Aa0AB6D7F",
|
||||||
};
|
};
|
||||||
|
|
||||||
export const FTSO_ADDRESSES = {
|
export const FTSO_ADDRESSES = {
|
||||||
[NetworkId.TESTNET_SEPOLIA]: "0x0eF2E888710E9f1d5E734f9ce30FAD40c832D5F3",
|
[NetworkId.TESTNET_SEPOLIA]: "0xcFedFFEB3FdeCd2196820Ba3b71f3F84A1255f93",
|
||||||
[NetworkId.TESTNET_HOODI]: "0xb184e423811b644A1924334E63985c259F5D0033",
|
[NetworkId.TESTNET_HOODI]: "0xb184e423811b644A1924334E63985c259F5D0033",
|
||||||
};
|
};
|
||||||
|
|
||||||
export const DISTRIBUTOR_ADDRESSES = {
|
export const DISTRIBUTOR_ADDRESSES = {
|
||||||
[NetworkId.TESTNET_SEPOLIA]: "0xE433D078a555163dC6B53968E72418B6a1618f04",
|
[NetworkId.TESTNET_SEPOLIA]: "0x8fbF8eB4Fcd451EF62Aee33508D46FE120963194",
|
||||||
[NetworkId.TESTNET_HOODI]: "0xdF49dC81c457c6f92e26cf6d686C7a8715255842",
|
[NetworkId.TESTNET_HOODI]: "0xdF49dC81c457c6f92e26cf6d686C7a8715255842",
|
||||||
};
|
};
|
||||||
|
|
||||||
export const GHOST_GOVERNANCE_ADDRESSES = {
|
export const GHOST_GOVERNANCE_ADDRESSES = {
|
||||||
[NetworkId.TESTNET_SEPOLIA]: "0xD40E6442Ee01c234CD8AaF335122CfbB2aec8548",
|
[NetworkId.TESTNET_SEPOLIA]: "0xDab0c51918E6990d8763FAC8a04AE159e44e0c4f",
|
||||||
[NetworkId.TESTNET_HOODI]: "0x1B96B792840d4d19d5097ee007392Ed4d851e64F",
|
[NetworkId.TESTNET_HOODI]: "0x1B96B792840d4d19d5097ee007392Ed4d851e64F",
|
||||||
};
|
};
|
||||||
|
|
||||||
export const BONDING_CALCULATOR_ADDRESSES = {
|
export const BONDING_CALCULATOR_ADDRESSES = {
|
||||||
[NetworkId.TESTNET_SEPOLIA]: "0x29a6bb5De7a1049632E107544CaEF05e518451e7",
|
[NetworkId.TESTNET_SEPOLIA]: "0x4896bFc6256A57Df826d7144E48c9633d51d6319",
|
||||||
[NetworkId.TESTNET_HOODI]: "0x2635d526Ad24b98082563937f7b996075052c6Fd",
|
[NetworkId.TESTNET_HOODI]: "0x2635d526Ad24b98082563937f7b996075052c6Fd",
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const GATEKEEPER_ADDRESSES = {
|
||||||
|
[NetworkId.TESTNET_SEPOLIA]: "0xc85129A097773B7F8970a7364c928C05f265E6A1",
|
||||||
|
}
|
||||||
|
|
||||||
export const UNISWAP_V2_ROUTER = {
|
export const UNISWAP_V2_ROUTER = {
|
||||||
[NetworkId.TESTNET_SEPOLIA]: "0xee567fe1712faf6149d80da1e6934e354124cfe3",
|
[NetworkId.TESTNET_SEPOLIA]: "0xee567fe1712faf6149d80da1e6934e354124cfe3",
|
||||||
[NetworkId.TESTNET_HOODI]: "0xD41daF947c6FFEf344754B99ad09466FBCBb7583",
|
[NetworkId.TESTNET_HOODI]: "0xD41daF947c6FFEf344754B99ad09466FBCBb7583",
|
||||||
|
@ -17,6 +17,7 @@ import { ClaimBonds } from "./components/ClaimBonds";
|
|||||||
import { useLiveBonds } from "../../hooks/bonds";
|
import { useLiveBonds } from "../../hooks/bonds";
|
||||||
import { useTotalReserves } from "../../hooks/treasury";
|
import { useTotalReserves } from "../../hooks/treasury";
|
||||||
import { useFtsoPrice } from "../../hooks/prices";
|
import { useFtsoPrice } from "../../hooks/prices";
|
||||||
|
import { useTokenSymbol } from "../../hooks/tokens";
|
||||||
|
|
||||||
const Bonds = ({ chainId, address, connect }) => {
|
const Bonds = ({ chainId, address, connect }) => {
|
||||||
const [isZoomed] = useState(false);
|
const [isZoomed] = useState(false);
|
||||||
@ -34,6 +35,8 @@ const Bonds = ({ chainId, address, connect }) => {
|
|||||||
const totalReserves = useTotalReserves(chainId);
|
const totalReserves = useTotalReserves(chainId);
|
||||||
const ftsoPrice = useFtsoPrice(chainId);
|
const ftsoPrice = useFtsoPrice(chainId);
|
||||||
|
|
||||||
|
const { symbol: ftsoSymbol } = useTokenSymbol(chainId, "FTSO");
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const interval = setInterval(() => {
|
const interval = setInterval(() => {
|
||||||
const date = Math.round(Date.now() / 1000);
|
const date = Math.round(Date.now() / 1000);
|
||||||
@ -44,7 +47,7 @@ const Bonds = ({ chainId, address, connect }) => {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<Box>
|
<Box>
|
||||||
<PageTitle name={"Protocol Bonding"} subtitle="Buy FTSO from the protocol at a discount" />
|
<PageTitle name={"Protocol Bonding"} subtitle={`Buy ${ftsoSymbol} from the protocol at a discount`} />
|
||||||
<Container
|
<Container
|
||||||
style={{
|
style={{
|
||||||
paddingLeft: isSmallScreen || isVerySmallScreen ? "0" : "3.3rem",
|
paddingLeft: isSmallScreen || isVerySmallScreen ? "0" : "3.3rem",
|
||||||
@ -64,7 +67,7 @@ const Bonds = ({ chainId, address, connect }) => {
|
|||||||
isLoading={false}
|
isLoading={false}
|
||||||
/>
|
/>
|
||||||
<Metric
|
<Metric
|
||||||
label={`FTSO price`}
|
label={`${ftsoSymbol} price`}
|
||||||
metric={formatCurrency(ftsoPrice, 2)}
|
metric={formatCurrency(ftsoPrice, 2)}
|
||||||
isLoading={false}
|
isLoading={false}
|
||||||
/>
|
/>
|
||||||
|
@ -9,7 +9,7 @@ const BondInfoText = () => {
|
|||||||
fontSize="0.875em"
|
fontSize="0.875em"
|
||||||
lineHeight="15px"
|
lineHeight="15px"
|
||||||
>
|
>
|
||||||
Important: Bonding is the act of selling “naked” assets such as gDAI (reserve bonds) or liquidity tokens such as gDAI-FTSO SLP (liquidity bonds) for FTSO at a discount.
|
Important: Bonding is the act of selling “naked” assets or liquidity tokens for ghostDAO native token at a discount.
|
||||||
<Link
|
<Link
|
||||||
color={theme.colors.primary[300]}
|
color={theme.colors.primary[300]}
|
||||||
href="https://ghostchain.io/ghostdao_litepaper"
|
href="https://ghostchain.io/ghostdao_litepaper"
|
||||||
|
@ -37,6 +37,9 @@ const BondInputArea = ({
|
|||||||
const { currentIndex } = useCurrentIndex(chainId);
|
const { currentIndex } = useCurrentIndex(chainId);
|
||||||
const { balance } = useBalance(chainId, bond.quoteToken.quoteTokenAddress, address);
|
const { balance } = useBalance(chainId, bond.quoteToken.quoteTokenAddress, address);
|
||||||
|
|
||||||
|
const { symbol: ftsoSymbol } = useTokenSymbol(chainId, "FTSO");
|
||||||
|
const { symbol: ghstSymbol } = useTokenSymbol(chainId, "GHST");
|
||||||
|
|
||||||
const [amount, setAmount] = useState("");
|
const [amount, setAmount] = useState("");
|
||||||
const [checked, setChecked] = useState(false);
|
const [checked, setChecked] = useState(false);
|
||||||
const [confirmOpen, setConfirmOpen] = useState(false);
|
const [confirmOpen, setConfirmOpen] = useState(false);
|
||||||
@ -164,11 +167,11 @@ const BondInputArea = ({
|
|||||||
title={"You Will Get"}
|
title={"You Will Get"}
|
||||||
balance={
|
balance={
|
||||||
<span>
|
<span>
|
||||||
{formatCurrency(amountInBaseToken, formatDecimals, "FTSO")}
|
{formatCurrency(amountInBaseToken, formatDecimals, ftsoSymbol)}
|
||||||
{" "}
|
{" "}
|
||||||
{!!currentIndex && (
|
{!!currentIndex && (
|
||||||
<span>
|
<span>
|
||||||
(≈{formatCurrency(amountInBaseToken.div(currentIndex), formatDecimals, "GHST")})
|
(≈{formatCurrency(amountInBaseToken.div(currentIndex), formatDecimals, ghstSymbol)})
|
||||||
</span>
|
</span>
|
||||||
)}
|
)}
|
||||||
</span>
|
</span>
|
||||||
@ -182,8 +185,8 @@ const BondInputArea = ({
|
|||||||
balance={
|
balance={
|
||||||
<span>
|
<span>
|
||||||
{bond.baseToken.tokenAddress.toUpperCase() === bond.quoteToken.quoteTokenAddress.toUpperCase()
|
{bond.baseToken.tokenAddress.toUpperCase() === bond.quoteToken.quoteTokenAddress.toUpperCase()
|
||||||
? `${formatCurrency(baseTokenString, formatDecimals, "FTSO")}`
|
? `${formatCurrency(baseTokenString, formatDecimals, ftsoSymbol)}`
|
||||||
: `${formatCurrency(baseTokenString, formatDecimals, "FTSO")} (≈${formatCurrency(baseTokenString.div(currentIndex), formatDecimals, "GHST")})`}
|
: `${formatCurrency(baseTokenString, formatDecimals, ftsoSymbol)} (≈${formatCurrency(baseTokenString.div(currentIndex), formatDecimals, ghstSymbol)})`}
|
||||||
</span>
|
</span>
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
@ -191,7 +194,7 @@ const BondInputArea = ({
|
|||||||
<DataRow
|
<DataRow
|
||||||
title="Discount"
|
title="Discount"
|
||||||
balance={<BondDiscount discount={bond.discount} textOnly />}
|
balance={<BondDiscount discount={bond.discount} textOnly />}
|
||||||
tooltip="The bond discount is the percentage difference between FTSO market value and the bond's price"
|
tooltip={`The bond discount is the percentage difference between ${ftsoSymbol} market value and the bond's price`}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<DataRow
|
<DataRow
|
||||||
|
@ -170,7 +170,7 @@ const payoutTokenCapacity = (bond) => {
|
|||||||
const payoutTokenCapacity = bond.maxPayout.inBaseToken.lt(bond.capacity.inBaseToken)
|
const payoutTokenCapacity = bond.maxPayout.inBaseToken.lt(bond.capacity.inBaseToken)
|
||||||
? bond.maxPayout.inBaseToken
|
? bond.maxPayout.inBaseToken
|
||||||
: bond.capacity.inBaseToken;
|
: bond.capacity.inBaseToken;
|
||||||
return `${formatNumber(payoutTokenCapacity, 4)} FTSO`;
|
return `${formatNumber(payoutTokenCapacity, 4)} ${bond.baseToken.name}`;
|
||||||
};
|
};
|
||||||
|
|
||||||
const BondRow = ({ bond, secondsTo }) => {
|
const BondRow = ({ bond, secondsTo }) => {
|
||||||
|
@ -19,6 +19,7 @@ import { formatCurrency } from "../../../helpers";
|
|||||||
|
|
||||||
import { useCurrentIndex, useEpoch, useWarmupLength, useWarmupInfo } from "../../../hooks/staking";
|
import { useCurrentIndex, useEpoch, useWarmupLength, useWarmupInfo } from "../../../hooks/staking";
|
||||||
import { useNotes, redeem } from "../../../hooks/bonds";
|
import { useNotes, redeem } from "../../../hooks/bonds";
|
||||||
|
import { useTokenSymbol } from "../../../hooks/tokens";
|
||||||
|
|
||||||
export const ClaimBonds = ({ chainId, address, secondsTo }) => {
|
export const ClaimBonds = ({ chainId, address, secondsTo }) => {
|
||||||
const isSmallScreen = useScreenSize("md");
|
const isSmallScreen = useScreenSize("md");
|
||||||
@ -37,6 +38,10 @@ export const ClaimBonds = ({ chainId, address, secondsTo }) => {
|
|||||||
const { currentIndex, refetch: currentIndexRefetch } = useCurrentIndex(chainId);
|
const { currentIndex, refetch: currentIndexRefetch } = useCurrentIndex(chainId);
|
||||||
const { notes, refetch: notesRefetch } = useNotes(chainId, address);
|
const { notes, refetch: notesRefetch } = useNotes(chainId, address);
|
||||||
|
|
||||||
|
const { symbol: ftsoSymbol } = useTokenSymbol(chainId, "FTSO");
|
||||||
|
const { symbol: stnkSymbol } = useTokenSymbol(chainId, "STNK");
|
||||||
|
const { symbol: ghstSymbol } = useTokenSymbol(chainId, "GHST");
|
||||||
|
|
||||||
if (!notes || notes.length === 0) return null;
|
if (!notes || notes.length === 0) return null;
|
||||||
|
|
||||||
const totalClaimableBalance = new DecimalBigNumber(
|
const totalClaimableBalance = new DecimalBigNumber(
|
||||||
@ -91,8 +96,8 @@ export const ClaimBonds = ({ chainId, address, secondsTo }) => {
|
|||||||
onChange={(_, view) => setIsPayoutGhstInner(view === 1)}
|
onChange={(_, view) => setIsPayoutGhstInner(view === 1)}
|
||||||
TabIndicatorProps={{ style: { display: "none" } }}
|
TabIndicatorProps={{ style: { display: "none" } }}
|
||||||
>
|
>
|
||||||
<Tab aria-label="payout-stnk-button" label="STNK" style={{ fontSize: "1rem" }} />
|
<Tab aria-label="payout-stnk-button" label={stnkSymbol} style={{ fontSize: "1rem" }} />
|
||||||
<Tab aria-label="payout-ghst-button" label="GHST" style={{ fontSize: "1rem" }} />
|
<Tab aria-label="payout-ghst-button" label={ghstSymbol} style={{ fontSize: "1rem" }} />
|
||||||
</Tabs>
|
</Tabs>
|
||||||
</Box>
|
</Box>
|
||||||
|
|
||||||
@ -105,8 +110,8 @@ export const ClaimBonds = ({ chainId, address, secondsTo }) => {
|
|||||||
<Box mt="4px" mb="8px">
|
<Box mt="4px" mb="8px">
|
||||||
<Typography variant="h4" align="center">
|
<Typography variant="h4" align="center">
|
||||||
{isPayoutGhst
|
{isPayoutGhst
|
||||||
? formatCurrency(totalClaimableBalance, 5, "GHST")
|
? formatCurrency(totalClaimableBalance, 5, ghstSymbol)
|
||||||
: formatCurrency(currentIndex.mul(totalClaimableBalance), 5, "STNK")
|
: formatCurrency(currentIndex.mul(totalClaimableBalance), 5, stnkSymbol)
|
||||||
}
|
}
|
||||||
</Typography>
|
</Typography>
|
||||||
</Box>
|
</Box>
|
||||||
@ -152,8 +157,8 @@ export const ClaimBonds = ({ chainId, address, secondsTo }) => {
|
|||||||
<Typography>Payout</Typography>
|
<Typography>Payout</Typography>
|
||||||
<Typography>
|
<Typography>
|
||||||
{isPayoutGhst
|
{isPayoutGhst
|
||||||
? formatCurrency(note.payout, 5, "GHST")
|
? formatCurrency(note.payout, 5, ghstSymbol)
|
||||||
: formatCurrency(currentIndex.mul(note.payout), 5, "STNK")
|
: formatCurrency(currentIndex.mul(note.payout), 5, stnkSymbol)
|
||||||
}
|
}
|
||||||
</Typography>
|
</Typography>
|
||||||
</Box>
|
</Box>
|
||||||
@ -208,8 +213,8 @@ export const ClaimBonds = ({ chainId, address, secondsTo }) => {
|
|||||||
<TableCell style={{ padding: "8px 0" }}>
|
<TableCell style={{ padding: "8px 0" }}>
|
||||||
<Typography>
|
<Typography>
|
||||||
{isPayoutGhst
|
{isPayoutGhst
|
||||||
? formatCurrency(note.payout, 5, "GHST")
|
? formatCurrency(note.payout, 5, ghstSymbol)
|
||||||
: formatCurrency(currentIndex.mul(note.payout), 5, "STNK")
|
: formatCurrency(currentIndex.mul(note.payout), 5, stnkSymbol)
|
||||||
}
|
}
|
||||||
</Typography>
|
</Typography>
|
||||||
</TableCell>
|
</TableCell>
|
||||||
|
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 onSwap = () => {
|
||||||
// const oldAmountTop = amountTop;
|
|
||||||
// const oldAmountBottom = amountBottom;
|
|
||||||
// setAmountBottom(oldAmountTop);
|
|
||||||
setAmountTop(amountBottom);
|
setAmountTop(amountBottom);
|
||||||
onCardsSwap();
|
onCardsSwap();
|
||||||
}
|
}
|
||||||
|
@ -42,6 +42,11 @@ const TokenModal = ({ chainId, account, listOpen, setListOpen, setTokenAddress }
|
|||||||
const { balance: stnkBalance } = useBalance(chainId, "STNK", account);
|
const { balance: stnkBalance } = useBalance(chainId, "STNK", account);
|
||||||
const { balance: ghstBalance } = useBalance(chainId, "GHST", account);
|
const { balance: ghstBalance } = useBalance(chainId, "GHST", account);
|
||||||
|
|
||||||
|
const { symbol: daiSymbol } = useTokenSymbol(chainId, "GDAI");
|
||||||
|
const { symbol: ftsoSymbol } = useTokenSymbol(chainId, "FTSO");
|
||||||
|
const { symbol: stnkSymbol } = useTokenSymbol(chainId, "STNK");
|
||||||
|
const { symbol: ghstSymbol } = useTokenSymbol(chainId, "GHST");
|
||||||
|
|
||||||
const searchToken = useMemo(() => {
|
const searchToken = useMemo(() => {
|
||||||
return [{
|
return [{
|
||||||
name: searchSymbol,
|
name: searchSymbol,
|
||||||
@ -54,31 +59,31 @@ const TokenModal = ({ chainId, account, listOpen, setListOpen, setTokenAddress }
|
|||||||
const knownTokens = useMemo(() => {
|
const knownTokens = useMemo(() => {
|
||||||
return [
|
return [
|
||||||
{
|
{
|
||||||
name: "gDAI",
|
name: daiSymbol,
|
||||||
icons: ["GDAI"],
|
icons: ["GDAI"],
|
||||||
balance: daiBalance,
|
balance: daiBalance,
|
||||||
address: DAI_ADDRESSES[chainId]
|
address: DAI_ADDRESSES[chainId]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "FTSO",
|
name: ftsoSymbol,
|
||||||
icons: ["FTSO"],
|
icons: ["FTSO"],
|
||||||
balance: ftsoBalance,
|
balance: ftsoBalance,
|
||||||
address: FTSO_ADDRESSES[chainId]
|
address: FTSO_ADDRESSES[chainId]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "STNK",
|
name: stnkSymbol,
|
||||||
icons: ["STNK"],
|
icons: ["STNK"],
|
||||||
balance: stnkBalance,
|
balance: stnkBalance,
|
||||||
address: STNK_ADDRESSES[chainId]
|
address: STNK_ADDRESSES[chainId]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "GHST",
|
name: ghstSymbol,
|
||||||
icons: ["GHST"],
|
icons: ["GHST"],
|
||||||
balance: ghstBalance,
|
balance: ghstBalance,
|
||||||
address: GHST_ADDRESSES[chainId]
|
address: GHST_ADDRESSES[chainId]
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}, [daiBalance, ghstBalance, stnkBalance, ghstBalance]);
|
}, [daiSymbol, ftsoSymbol, stnkSymbol, ghstSymbol, daiBalance, ftsoBalance, stnkBalance, ghstBalance]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (isAddress(userInput)) {
|
if (isAddress(userInput)) {
|
||||||
|
@ -9,33 +9,49 @@ import Paper from "../../components/Paper/Paper";
|
|||||||
import SwapCard from "../../components/Swap/SwapCard";
|
import SwapCard from "../../components/Swap/SwapCard";
|
||||||
import TokenStack from "../../components/TokenStack/TokenStack";
|
import TokenStack from "../../components/TokenStack/TokenStack";
|
||||||
import { PrimaryButton } from "../../components/Button";
|
import { PrimaryButton } from "../../components/Button";
|
||||||
|
import { Tab, Tabs } from "../../components/Tabs/Tabs";
|
||||||
|
|
||||||
import { DAI_ADDRESSES } from "../../constants/addresses";
|
import { DAI_ADDRESSES } from "../../constants/addresses";
|
||||||
import { DecimalBigNumber } from "../../helpers/DecimalBigNumber";
|
import { DecimalBigNumber } from "../../helpers/DecimalBigNumber";
|
||||||
import { formatCurrency, formatNumber } from "../../helpers";
|
import { formatCurrency, formatNumber } from "../../helpers";
|
||||||
|
|
||||||
import { useBalance as useTokenBalance, useConversionRate, mintDai } from "../../hooks/tokens";
|
import {
|
||||||
|
useBalance as useTokenBalance,
|
||||||
|
useTokenSymbol,
|
||||||
|
useTotalSupply,
|
||||||
|
useConversionRate,
|
||||||
|
useAccumulatedDonation,
|
||||||
|
mintDai,
|
||||||
|
burnDai
|
||||||
|
} from "../../hooks/tokens";
|
||||||
|
|
||||||
const Faucet = ({ chainId, address, config, connect }) => {
|
const Faucet = ({ chainId, address, config, connect }) => {
|
||||||
const isSmallScreen = useMediaQuery("(max-width: 650px)");
|
const isSmallScreen = useMediaQuery("(max-width: 650px)");
|
||||||
const isSemiSmallScreen = useMediaQuery("(max-width: 480px)");
|
const isSemiSmallScreen = useMediaQuery("(max-width: 480px)");
|
||||||
const isVerySmallScreen = useMediaQuery("(max-width: 379px)");
|
const isVerySmallScreen = useMediaQuery("(max-width: 379px)");
|
||||||
|
|
||||||
const daiConversionRate = useConversionRate(chainId, "GDAI");
|
const [isMint, setIsMint] = useState(true);
|
||||||
const { balance: daiBalance, refetch: daiBalanceRefetch } = useTokenBalance(chainId, "GDAI", address);
|
|
||||||
const { data: nativeBalance, refetch: balanceRefetch } = useBalance({ address });
|
|
||||||
|
|
||||||
const [isPending, setIsPending] = useState(false);
|
const [isPending, setIsPending] = useState(false);
|
||||||
const [balance, setBalance] = useState(new DecimalBigNumber(0, 0));
|
const [balance, setBalance] = useState(new DecimalBigNumber(0, 0));
|
||||||
const [amount, setAmount] = useState("");
|
const [amount, setAmount] = useState("");
|
||||||
const [faucetToken, setFaucetToken] = useState({
|
|
||||||
name: "",
|
|
||||||
address: "",
|
|
||||||
});
|
|
||||||
const [scanInfo, setScanInfo] = useState({
|
const [scanInfo, setScanInfo] = useState({
|
||||||
name: "",
|
name: "",
|
||||||
url: "",
|
url: "",
|
||||||
});
|
});
|
||||||
|
const [nativeInfo, setNativeInfo] = useState({
|
||||||
|
decimals: 18,
|
||||||
|
name: "",
|
||||||
|
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(() => {
|
useEffect(() => {
|
||||||
ReactGA.send({ hitType: "pageview", page: "/faucet" });
|
ReactGA.send({ hitType: "pageview", page: "/faucet" });
|
||||||
@ -51,44 +67,71 @@ const Faucet = ({ chainId, address, config, connect }) => {
|
|||||||
let scanName = "";
|
let scanName = "";
|
||||||
let scanUrl = "";
|
let scanUrl = "";
|
||||||
|
|
||||||
const tokenName = "gDAI";
|
|
||||||
const tokenAddress = DAI_ADDRESSES[chainId];
|
|
||||||
|
|
||||||
const client = config?.getClient();
|
const client = config?.getClient();
|
||||||
scanName = client?.chain?.blockExplorers?.default?.name;
|
scanName = client?.chain?.blockExplorers?.default?.name;
|
||||||
scanUrl = client?.chain?.blockExplorers?.default?.url;
|
scanUrl = client?.chain?.blockExplorers?.default?.url;
|
||||||
|
|
||||||
setFaucetToken({
|
|
||||||
name: tokenName,
|
|
||||||
address: tokenAddress,
|
|
||||||
});
|
|
||||||
|
|
||||||
setScanInfo({
|
setScanInfo({
|
||||||
name: scanName,
|
name: scanName,
|
||||||
url: scanUrl,
|
url: scanUrl,
|
||||||
})
|
})
|
||||||
|
|
||||||
|
setNativeInfo(client?.chain?.nativeCurrency)
|
||||||
}, [chainId]);
|
}, [chainId]);
|
||||||
|
|
||||||
|
const changeIsMinted = (value) => {
|
||||||
|
if (accumulatedDonation) {
|
||||||
|
setAmount("");
|
||||||
|
setIsMint(value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const preparedAmount = useMemo(() => {
|
const preparedAmount = useMemo(() => {
|
||||||
if (address === "") new DecimalBigNumber("0", 0);
|
if (address === "") new DecimalBigNumber("0", 0);
|
||||||
return new DecimalBigNumber(amount, 18);
|
const decimals = isMint ? nativeInfo.decimals : 18;
|
||||||
}, [amount, balance])
|
return new DecimalBigNumber(amount, decimals);
|
||||||
|
}, [amount, balance, nativeInfo])
|
||||||
|
|
||||||
const estimatedAmount = useMemo(() => {
|
const estimatedAmountIn = useMemo(() => {
|
||||||
const rate = new DecimalBigNumber(daiConversionRate.toString(), 0);
|
const rate = new DecimalBigNumber(daiConversionRate.toString(), 0);
|
||||||
const value = new DecimalBigNumber(amount, 18);
|
const value = new DecimalBigNumber(amount, nativeInfo.decimals);
|
||||||
return value.mul(rate);
|
return value.mul(rate);
|
||||||
}, [amount, daiConversionRate])
|
}, [amount, daiConversionRate, nativeInfo]);
|
||||||
|
|
||||||
const mintOrConnect = async () => {
|
const contractBalanceFree = useMemo(() => {
|
||||||
|
const realContractBalance = contractBalance ? contractBalance.value : 0n;
|
||||||
|
const preparedContractBalance = new DecimalBigNumber(realContractBalance, nativeInfo.decimals);
|
||||||
|
const preparedAccumulatedDonation = new DecimalBigNumber(
|
||||||
|
accumulatedDonation._value,
|
||||||
|
nativeInfo.decimals && 18
|
||||||
|
);
|
||||||
|
return preparedContractBalance.sub(preparedAccumulatedDonation);
|
||||||
|
}, [contractBalance, accumulatedDonation]);
|
||||||
|
|
||||||
|
const estimatedAmountOut = useMemo(() => {
|
||||||
|
const value = new DecimalBigNumber(amount, nativeInfo.decimals);
|
||||||
|
if (reserveTotalSupply._value > 0n) {
|
||||||
|
return value.mul(contractBalanceFree).div(reserveTotalSupply);
|
||||||
|
}
|
||||||
|
return new DecimalBigNumber(0n, nativeInfo.decimals);
|
||||||
|
}, [amount, contractBalanceFree, reserveTotalSupply, nativeInfo]);
|
||||||
|
|
||||||
|
const actionOrConnect = async () => {
|
||||||
if (address === "") {
|
if (address === "") {
|
||||||
connect();
|
connect();
|
||||||
} else {
|
} else {
|
||||||
setIsPending(true);
|
setIsPending(true);
|
||||||
await mintDai(chainId, address, preparedAmount._value.toString());
|
|
||||||
|
if (isMint) {
|
||||||
|
await mintDai(chainId, address, preparedAmount._value.toString());
|
||||||
|
} else {
|
||||||
|
await burnDai(chainId, address, preparedAmount._value.toString());
|
||||||
|
}
|
||||||
|
|
||||||
await balanceRefetch();
|
await balanceRefetch();
|
||||||
await daiBalanceRefetch();
|
await daiBalanceRefetch();
|
||||||
|
await contractBalanceRefetch();
|
||||||
|
await refetchReserveTotalSupply();
|
||||||
setAmount("");
|
setAmount("");
|
||||||
setIsPending(false);
|
setIsPending(false);
|
||||||
}
|
}
|
||||||
@ -116,7 +159,7 @@ const Faucet = ({ chainId, address, config, connect }) => {
|
|||||||
<meta name="twitter:image" content="https://ghostchain.io/wp-content/uploads/2025/03/ghostFaucet-Featured_Image.png" />
|
<meta name="twitter:image" content="https://ghostchain.io/wp-content/uploads/2025/03/ghostFaucet-Featured_Image.png" />
|
||||||
</Helmet>
|
</Helmet>
|
||||||
|
|
||||||
<PageTitle name={"gDAI Faucet"} subtitle="Swap Sepolia ETH for gDAI." />
|
<PageTitle name={`${faucetSymbol} Faucet`} subtitle={`Swap Sepolia ${nativeInfo.symbol} for ${faucetSymbol}.`} />
|
||||||
<Container
|
<Container
|
||||||
style={{
|
style={{
|
||||||
paddingLeft: isSmallScreen || isVerySmallScreen ? "0" : "3.3rem",
|
paddingLeft: isSmallScreen || isVerySmallScreen ? "0" : "3.3rem",
|
||||||
@ -131,10 +174,21 @@ const Faucet = ({ chainId, address, config, connect }) => {
|
|||||||
<Paper
|
<Paper
|
||||||
headerContent={
|
headerContent={
|
||||||
<Box alignItems="center" justifyContent="space-between" display="flex" width="100%">
|
<Box alignItems="center" justifyContent="space-between" display="flex" width="100%">
|
||||||
<Typography variant="h4">Get {faucetToken.name}</Typography>
|
<Tabs
|
||||||
|
centered
|
||||||
|
textColor="primary"
|
||||||
|
indicatorColor="primary"
|
||||||
|
value={isMint ? 0 : 1}
|
||||||
|
aria-label="Faucet menu"
|
||||||
|
onChange={(_, view) => changeIsMinted(view === 0)}
|
||||||
|
TabIndicatorProps={{ style: { display: "none" } }}
|
||||||
|
>
|
||||||
|
<Tab aria-label="faucet-mint-button" label="Mint" style={{ fontSize: "1.5rem" }} />
|
||||||
|
{accumulatedDonation && <Tab aria-label="faucet-burn-button" label="Burn" style={{ fontSize: "1.5rem" }} />}
|
||||||
|
</Tabs>
|
||||||
{!isSemiSmallScreen && <PrimaryButton
|
{!isSemiSmallScreen && <PrimaryButton
|
||||||
variant="text"
|
variant="text"
|
||||||
href={`${scanInfo.url}/token/${faucetToken.address}`}
|
href={`${scanInfo.url}/token/${DAI_ADDRESSES[chainId]}`}
|
||||||
>
|
>
|
||||||
Check on {scanInfo.name}
|
Check on {scanInfo.name}
|
||||||
</PrimaryButton>}
|
</PrimaryButton>}
|
||||||
@ -144,16 +198,28 @@ const Faucet = ({ chainId, address, config, connect }) => {
|
|||||||
fullWidth
|
fullWidth
|
||||||
>
|
>
|
||||||
<Box>
|
<Box>
|
||||||
<SwapCard
|
{isMint && <SwapCard
|
||||||
id={`faucet-sepolia-eth`}
|
id={`faucet-sepolia-eth`}
|
||||||
inputWidth={isVerySmallScreen ? "100px" : isSemiSmallScreen ? "180px" : "250px"}
|
inputWidth={isVerySmallScreen ? "100px" : isSemiSmallScreen ? "180px" : "250px"}
|
||||||
tokenName={"ETH"}
|
tokenName={nativeInfo.symbol}
|
||||||
token={<TokenStack tokens={["ETH"]} sx={{ fontSize: "21px" }} />}
|
token={<TokenStack tokens={[nativeInfo.symbol]} sx={{ fontSize: "21px" }} />}
|
||||||
info={`${isSemiSmallScreen ? "" : "Balance: "}${formatCurrency(balance.toString(), 4, "ETH")}`}
|
info={`${isSemiSmallScreen ? "" : "Balance: "}${formatCurrency(balance.toString(), 4, nativeInfo.symbol)}`}
|
||||||
value={amount}
|
value={amount}
|
||||||
onChange={event => setAmount(event.currentTarget.value)}
|
onChange={event => setAmount(event.currentTarget.value)}
|
||||||
inputProps={{ "data-testid": "fromInput" }}
|
inputProps={{ "data-testid": "fromInput" }}
|
||||||
/>
|
/>}
|
||||||
|
{!isMint && <SwapCard
|
||||||
|
id={`faucet-sepolia-eth`}
|
||||||
|
inputWidth={isVerySmallScreen ? "100px" : isSemiSmallScreen ? "180px" : "250px"}
|
||||||
|
tokenName={faucetSymbol}
|
||||||
|
token={<TokenStack tokens={[faucetSymbol]} sx={{ fontSize: "21px" }} />}
|
||||||
|
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
|
<Box
|
||||||
mb="20px"
|
mb="20px"
|
||||||
mt="20px"
|
mt="20px"
|
||||||
@ -161,35 +227,56 @@ const Faucet = ({ chainId, address, config, connect }) => {
|
|||||||
display="flex"
|
display="flex"
|
||||||
justifyContent="space-between"
|
justifyContent="space-between"
|
||||||
>
|
>
|
||||||
<Box maxWidth="416px" display="flex" justifyContent={isVerySmallScreen ? "end" : "space-between"}>
|
{isMint && (
|
||||||
{!isVerySmallScreen && <Typography fontSize="12px" lineHeight="15px">ETH multiplier:</Typography>}
|
<>
|
||||||
<Typography fontSize="12px" lineHeight="15px">{formatNumber(daiConversionRate, 2)}</Typography>
|
<Box maxWidth="416px" display="flex" justifyContent={isVerySmallScreen ? "end" : "space-between"}>
|
||||||
</Box>
|
{!isVerySmallScreen && <Typography fontSize="12px" lineHeight="15px">{nativeInfo.symbol} multiplier:</Typography>}
|
||||||
<Box maxWidth="416px" display="flex" justifyContent={isVerySmallScreen ? "end" : "space-between"}>
|
<Typography fontSize="12px" lineHeight="15px">{formatNumber(daiConversionRate, 2)}</Typography>
|
||||||
{!isVerySmallScreen && <Typography fontSize="12px" lineHeight="15px">You will get:</Typography>}
|
</Box>
|
||||||
<Typography fontSize="12px" lineHeight="15px">{formatCurrency(estimatedAmount, 5, faucetToken.name)}</Typography>
|
<Box maxWidth="416px" display="flex" justifyContent={isVerySmallScreen ? "end" : "space-between"}>
|
||||||
</Box>
|
{!isVerySmallScreen && <Typography fontSize="12px" lineHeight="15px">You will get:</Typography>}
|
||||||
<Box display="flex" justifyContent={isVerySmallScreen ? "end" : "space-between"}>
|
<Typography fontSize="12px" lineHeight="15px">{formatCurrency(estimatedAmountIn, 5, faucetSymbol)}</Typography>
|
||||||
{!isVerySmallScreen && <Typography fontSize="12px" lineHeight="15px">Your {faucetToken.name} balance:</Typography>}
|
</Box>
|
||||||
<Typography fontSize="12px" lineHeight="15px">{formatCurrency(daiBalance, 5, faucetToken.name)}</Typography>
|
<Box display="flex" justifyContent={isVerySmallScreen ? "end" : "space-between"}>
|
||||||
</Box>
|
{!isVerySmallScreen && <Typography fontSize="12px" lineHeight="15px">Your {faucetSymbol} balance:</Typography>}
|
||||||
|
<Typography fontSize="12px" lineHeight="15px">{formatCurrency(daiBalance, 5, faucetSymbol)}</Typography>
|
||||||
|
</Box>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
{!isMint && (
|
||||||
|
<>
|
||||||
|
<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">{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>}
|
||||||
|
<Typography fontSize="12px" lineHeight="15px">{formatCurrency(estimatedAmountOut, 5, nativeInfo.symbol)}</Typography>
|
||||||
|
</Box>
|
||||||
|
<Box display="flex" justifyContent={isVerySmallScreen ? "end" : "space-between"}>
|
||||||
|
{!isVerySmallScreen && <Typography fontSize="12px" lineHeight="15px">Your {nativeInfo.symbol} balance:</Typography>}
|
||||||
|
<Typography fontSize="12px" lineHeight="15px">{formatCurrency(balance, 5, nativeInfo.symbol)}</Typography>
|
||||||
|
</Box>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
</Box>
|
</Box>
|
||||||
<PrimaryButton
|
<PrimaryButton
|
||||||
fullWidth
|
fullWidth
|
||||||
disabled={
|
disabled={
|
||||||
address !== "" && (
|
address !== "" && (
|
||||||
preparedAmount?.eq(new DecimalBigNumber(0, 18)) ||
|
preparedAmount?._value === 0n ||
|
||||||
balance?.lt(preparedAmount) ||
|
isPending ||
|
||||||
isPending
|
(isMint && balance?.lt(preparedAmount)) ||
|
||||||
|
(!isMint && daiBalance?.lt(preparedAmount))
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
loading={isPending}
|
loading={isPending}
|
||||||
onClick={() => mintOrConnect()}
|
onClick={() => actionOrConnect()}
|
||||||
>
|
>
|
||||||
{address === "" ?
|
{address === "" ?
|
||||||
"Connect"
|
"Connect"
|
||||||
:
|
:
|
||||||
"Mint"
|
isMint ? "Mint" : "Burn"
|
||||||
}
|
}
|
||||||
</PrimaryButton>
|
</PrimaryButton>
|
||||||
</Box>
|
</Box>
|
||||||
|
@ -28,21 +28,39 @@ const Stake = ({ chainId, address, isOpened, closeModal, connect }) => {
|
|||||||
case (upperToken === "FTSO" && bottomToken === "STNK"):
|
case (upperToken === "FTSO" && bottomToken === "STNK"):
|
||||||
setAction("STAKE")
|
setAction("STAKE")
|
||||||
break;
|
break;
|
||||||
|
case (upperToken === "eCSPR" && bottomToken === "sCSPR"):
|
||||||
|
setAction("STAKE")
|
||||||
|
break;
|
||||||
case (upperToken === "FTSO" && bottomToken === "GHST"):
|
case (upperToken === "FTSO" && bottomToken === "GHST"):
|
||||||
setAction("STAKE")
|
setAction("STAKE")
|
||||||
break;
|
break;
|
||||||
|
case (upperToken === "eCSPR" && bottomToken === "CSPR"):
|
||||||
|
setAction("STAKE")
|
||||||
|
break;
|
||||||
case (upperToken === "STNK" && bottomToken === "FTSO"):
|
case (upperToken === "STNK" && bottomToken === "FTSO"):
|
||||||
setAction("UNSTAKE")
|
setAction("UNSTAKE")
|
||||||
break;
|
break;
|
||||||
|
case (upperToken === "sCSPR" && bottomToken === "eCSPR"):
|
||||||
|
setAction("UNSTAKE")
|
||||||
|
break;
|
||||||
case (upperToken === "GHST" && bottomToken === "FTSO"):
|
case (upperToken === "GHST" && bottomToken === "FTSO"):
|
||||||
setAction("UNSTAKE")
|
setAction("UNSTAKE")
|
||||||
break;
|
break;
|
||||||
|
case (upperToken === "CSPR" && bottomToken === "eCSPR"):
|
||||||
|
setAction("UNSTAKE")
|
||||||
|
break;
|
||||||
case (upperToken === "STNK" && bottomToken === "GHST"):
|
case (upperToken === "STNK" && bottomToken === "GHST"):
|
||||||
setAction("WRAP")
|
setAction("WRAP")
|
||||||
break;
|
break;
|
||||||
|
case (upperToken === "sCSPR" && bottomToken === "CSPR"):
|
||||||
|
setAction("WRAP")
|
||||||
|
break;
|
||||||
case (upperToken === "GHST" && bottomToken === "STNK"):
|
case (upperToken === "GHST" && bottomToken === "STNK"):
|
||||||
setAction("UNWRAP")
|
setAction("UNWRAP")
|
||||||
break;
|
break;
|
||||||
|
case (upperToken === "CSPR" && bottomToken === "sCSPR"):
|
||||||
|
setAction("UNWRAP")
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
setAction("STAKE")
|
setAction("STAKE")
|
||||||
}
|
}
|
||||||
|
@ -16,6 +16,7 @@ import { ClaimsArea } from "./components/ClaimsArea";
|
|||||||
import { Apy, CurrentIndex, TotalDeposit } from "./components/Metric";
|
import { Apy, CurrentIndex, TotalDeposit } from "./components/Metric";
|
||||||
|
|
||||||
import { useEpoch } from "../../hooks/staking";
|
import { useEpoch } from "../../hooks/staking";
|
||||||
|
import { useTokenSymbol } from "../../hooks/tokens";
|
||||||
|
|
||||||
export const StakeContainer = ({ chainId, address, connect }) => {
|
export const StakeContainer = ({ chainId, address, connect }) => {
|
||||||
const [isModalOpened, handleModal] = useState(false);
|
const [isModalOpened, handleModal] = useState(false);
|
||||||
@ -24,6 +25,9 @@ export const StakeContainer = ({ chainId, address, connect }) => {
|
|||||||
const isSmallScreen = useMediaQuery("(max-width: 650px)");
|
const isSmallScreen = useMediaQuery("(max-width: 650px)");
|
||||||
const isVerySmallScreen = useMediaQuery("(max-width: 379px)");
|
const isVerySmallScreen = useMediaQuery("(max-width: 379px)");
|
||||||
|
|
||||||
|
const { symbol: ftsoSymbol } = useTokenSymbol(chainId, "FTSO");
|
||||||
|
const { symbol: stnkSymbol } = useTokenSymbol(chainId, "STNK");
|
||||||
|
|
||||||
const { epoch, refetch: refetchEpoch } = useEpoch(chainId);
|
const { epoch, refetch: refetchEpoch } = useEpoch(chainId);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@ -44,7 +48,7 @@ export const StakeContainer = ({ chainId, address, connect }) => {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<Box >
|
<Box >
|
||||||
<PageTitle name="Protocol Staking" subtitle="Stake your FTSO to earn rebase yields" />
|
<PageTitle name="Protocol Staking" subtitle={`Stake your ${ftsoSymbol} to earn rebase yields`} />
|
||||||
<Container
|
<Container
|
||||||
style={{
|
style={{
|
||||||
paddingLeft: isSmallScreen || isVerySmallScreen ? "0" : "3.3rem",
|
paddingLeft: isSmallScreen || isVerySmallScreen ? "0" : "3.3rem",
|
||||||
@ -71,13 +75,13 @@ export const StakeContainer = ({ chainId, address, connect }) => {
|
|||||||
>
|
>
|
||||||
<Grid container spacing={1}>
|
<Grid container spacing={1}>
|
||||||
<Grid item xs={isSmallScreen ? 12 : 4}>
|
<Grid item xs={isSmallScreen ? 12 : 4}>
|
||||||
<Apy distribute={epoch.distribute} chainId={chainId} />
|
<Apy stnkSymbol={stnkSymbol} distribute={epoch.distribute} chainId={chainId} />
|
||||||
</Grid>
|
</Grid>
|
||||||
<Grid item xs={isSmallScreen ? 12 : 4}>
|
<Grid item xs={isSmallScreen ? 12 : 4}>
|
||||||
<TotalDeposit chainId={chainId} />
|
<TotalDeposit stnkSymbol={stnkSymbol} chainId={chainId} />
|
||||||
</Grid>
|
</Grid>
|
||||||
<Grid item xs={isSmallScreen ? 12 : 4}>
|
<Grid item xs={isSmallScreen ? 12 : 4}>
|
||||||
<CurrentIndex chainId={chainId} />
|
<CurrentIndex ftsoSymbol={ftsoSymbol} chainId={chainId} />
|
||||||
</Grid>
|
</Grid>
|
||||||
</Grid>
|
</Grid>
|
||||||
|
|
||||||
|
@ -22,7 +22,7 @@ const ClaimConfirmationModal = (props) => {
|
|||||||
await forfeit(props.chainId, props.receiver);
|
await forfeit(props.chainId, props.receiver);
|
||||||
break;
|
break;
|
||||||
case "CLAIM":
|
case "CLAIM":
|
||||||
await claim(props.chainId, props.receiver, props.outputToken === "STNK");
|
await claim(props.chainId, props.receiver, props.outputToken === "STNK" || props.outputToken === "sCSPR");
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
console.log("Unknown action")
|
console.log("Unknown action")
|
||||||
@ -55,7 +55,7 @@ const ClaimConfirmationModal = (props) => {
|
|||||||
/>
|
/>
|
||||||
<Box display="flex" flexDirection="row" justifyContent="center">
|
<Box display="flex" flexDirection="row" justifyContent="center">
|
||||||
<Typography>
|
<Typography>
|
||||||
{props.outputToken}
|
{props.outputTokenName}
|
||||||
</Typography>
|
</Typography>
|
||||||
</Box>
|
</Box>
|
||||||
</Box>
|
</Box>
|
||||||
|
@ -28,7 +28,7 @@ import { prettifySecondsInDays } from "../../../helpers/timeUtil";
|
|||||||
import { formatNumber } from "../../../helpers";
|
import { formatNumber } from "../../../helpers";
|
||||||
import { STAKING_ADDRESSES } from "../../../constants/addresses";
|
import { STAKING_ADDRESSES } from "../../../constants/addresses";
|
||||||
import { useCurrentIndex, useWarmupInfo } from "../../../hooks/staking";
|
import { useCurrentIndex, useWarmupInfo } from "../../../hooks/staking";
|
||||||
import { useBalanceForShares } from "../../../hooks/tokens";
|
import { useBalanceForShares, useTokenSymbol } from "../../../hooks/tokens";
|
||||||
|
|
||||||
import ClaimConfirmationModal from "./ClaimConfirmationModal";
|
import ClaimConfirmationModal from "./ClaimConfirmationModal";
|
||||||
|
|
||||||
@ -61,6 +61,10 @@ export const ClaimsArea = ({ chainId, address, epoch }) => {
|
|||||||
const { currentIndex, refetch: currentIndexRefetch } = useCurrentIndex(chainId);
|
const { currentIndex, refetch: currentIndexRefetch } = useCurrentIndex(chainId);
|
||||||
const { balanceForShares } = useBalanceForShares(chainId, "STNK", claim.shares);
|
const { balanceForShares } = useBalanceForShares(chainId, "STNK", claim.shares);
|
||||||
|
|
||||||
|
const { symbol: ftsoSymbol } = useTokenSymbol(chainId, "FTSO");
|
||||||
|
const { symbol: stnkSymbol } = useTokenSymbol(chainId, "STNK");
|
||||||
|
const { symbol: ghstSymbol } = useTokenSymbol(chainId, "GHST");
|
||||||
|
|
||||||
const closeConfirmationModal = () => {
|
const closeConfirmationModal = () => {
|
||||||
setConfirmationModalOpen(false);
|
setConfirmationModalOpen(false);
|
||||||
claimRefetch();
|
claimRefetch();
|
||||||
@ -85,6 +89,7 @@ export const ClaimsArea = ({ chainId, address, epoch }) => {
|
|||||||
receiver={address}
|
receiver={address}
|
||||||
receiveAmount={claim.expiry > epoch.number ? claim.deposit : isPayoutGhst ? balanceForShares.div(currentIndex) : balanceForShares}
|
receiveAmount={claim.expiry > epoch.number ? claim.deposit : isPayoutGhst ? balanceForShares.div(currentIndex) : balanceForShares}
|
||||||
outputToken={claim.expiry > epoch.number ? "FTSO" : isPayoutGhst ? "GHST" : "STNK"}
|
outputToken={claim.expiry > epoch.number ? "FTSO" : isPayoutGhst ? "GHST" : "STNK"}
|
||||||
|
outputTokenName={claim.expiry > epoch.number ? ftsoSymbol : isPayoutGhst ? ghstSymbol : stnkSymbol}
|
||||||
action={claim.expiry > epoch.number ? "forfeit" : "claim"}
|
action={claim.expiry > epoch.number ? "forfeit" : "claim"}
|
||||||
chainId={chainId}
|
chainId={chainId}
|
||||||
/>
|
/>
|
||||||
@ -98,7 +103,7 @@ export const ClaimsArea = ({ chainId, address, epoch }) => {
|
|||||||
justifyContent="space-between"
|
justifyContent="space-between"
|
||||||
flexDirection={isSmallScreen ? "column" : "row"}
|
flexDirection={isSmallScreen ? "column" : "row"}
|
||||||
>
|
>
|
||||||
<Typography variant="h6">Your active {isPayoutGhst ? "GHST" : "STNK"} claim</Typography>
|
<Typography variant="h6">Your active {isPayoutGhst ? ghstSymbol : stnkSymbol} claim</Typography>
|
||||||
<Tabs
|
<Tabs
|
||||||
centered
|
centered
|
||||||
textColor="primary"
|
textColor="primary"
|
||||||
@ -108,8 +113,8 @@ export const ClaimsArea = ({ chainId, address, epoch }) => {
|
|||||||
onChange={(_, view) => setIsPayoutGhstInner(view === 1)}
|
onChange={(_, view) => setIsPayoutGhstInner(view === 1)}
|
||||||
TabIndicatorProps={{ style: { display: "none" } }}
|
TabIndicatorProps={{ style: { display: "none" } }}
|
||||||
>
|
>
|
||||||
<Tab aria-label="payout-stnk-button" label="STNK" style={{ fontSize: "1rem" }} />
|
<Tab aria-label="payout-stnk-button" label={stnkSymbol} style={{ fontSize: "1rem" }} />
|
||||||
<Tab aria-label="payout-ghst-button" label="GHST" style={{ fontSize: "1rem" }} />
|
<Tab aria-label="payout-ghst-button" label={ghstSymbol} style={{ fontSize: "1rem" }} />
|
||||||
</Tabs>
|
</Tabs>
|
||||||
</Box>
|
</Box>
|
||||||
}
|
}
|
||||||
@ -124,6 +129,8 @@ export const ClaimsArea = ({ chainId, address, epoch }) => {
|
|||||||
claim={claim}
|
claim={claim}
|
||||||
epoch={epoch}
|
epoch={epoch}
|
||||||
isClaimable={claim.expiry > epoch.number}
|
isClaimable={claim.expiry > epoch.number}
|
||||||
|
stnkSymbol={stnkSymbol}
|
||||||
|
ghstSymbol={ghstSymbol}
|
||||||
/>
|
/>
|
||||||
) : (
|
) : (
|
||||||
<Table>
|
<Table>
|
||||||
@ -142,6 +149,8 @@ export const ClaimsArea = ({ chainId, address, epoch }) => {
|
|||||||
claim={claim}
|
claim={claim}
|
||||||
epoch={epoch}
|
epoch={epoch}
|
||||||
isClaimable={claim.expiry > epoch.number}
|
isClaimable={claim.expiry > epoch.number}
|
||||||
|
stnkSymbol={stnkSymbol}
|
||||||
|
ghstSymbol={ghstSymbol}
|
||||||
/>
|
/>
|
||||||
</Table>
|
</Table>
|
||||||
|
|
||||||
@ -151,21 +160,21 @@ export const ClaimsArea = ({ chainId, address, epoch }) => {
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
const ClaimInfo = ({ setConfirmationModalOpen, prepareBalance, claim, epoch, isClaimable, isPayoutGhst }) => {
|
const ClaimInfo = ({ setConfirmationModalOpen, prepareBalance, claim, epoch, isClaimable, isPayoutGhst, stnkSymbol, ghstSymbol }) => {
|
||||||
return (
|
return (
|
||||||
<TableBody>
|
<TableBody>
|
||||||
<TableRow>
|
<TableRow>
|
||||||
<TableCell style={{ padding: "8px 8px 8px 0" }}>
|
<TableCell style={{ padding: "8px 8px 8px 0" }}>
|
||||||
<Box display="flex" flexDirection="row" alignItems="center" style={{ whiteSpace: "nowrap" }}>
|
<Box display="flex" flexDirection="row" alignItems="center" style={{ whiteSpace: "nowrap" }}>
|
||||||
<Token key={isPayoutGhst ? "GHST" : "STNK"} name={isPayoutGhst ? "GHST" : "STNK"} />
|
<Token key={isPayoutGhst ? ghstSymbol : stnkSymbol} name={isPayoutGhst ? ghstSymbol : stnkSymbol} />
|
||||||
<Box marginLeft="14px" marginRight="10px">
|
<Box marginLeft="14px" marginRight="10px">
|
||||||
<Typography>{isPayoutGhst ? "GHST" : "STNK"}</Typography>
|
<Typography>{isPayoutGhst ? ghstSymbol : stnkSymbol}</Typography>
|
||||||
</Box>
|
</Box>
|
||||||
</Box>
|
</Box>
|
||||||
</TableCell>
|
</TableCell>
|
||||||
<TableCell style={{ padding: "8px 8px 8px 0" }}>
|
<TableCell style={{ padding: "8px 8px 8px 0" }}>
|
||||||
<Typography gutterBottom={false} style={{ lineHeight: 1.4 }}>
|
<Typography gutterBottom={false} style={{ lineHeight: 1.4 }}>
|
||||||
{`${formatNumber(prepareBalance, 5)} ${isPayoutGhst ? "GHST" : "STNK"}`}
|
{`${formatNumber(prepareBalance, 5)} ${isPayoutGhst ? ghstSymbol : stnkSymbol}`}
|
||||||
</Typography>
|
</Typography>
|
||||||
</TableCell>
|
</TableCell>
|
||||||
<TableCell style={{ padding: "8px 8px 8px 0" }}>
|
<TableCell style={{ padding: "8px 8px 8px 0" }}>
|
||||||
@ -182,13 +191,13 @@ const ClaimInfo = ({ setConfirmationModalOpen, prepareBalance, claim, epoch, isC
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
const MobileClaimInfo = ({ setConfirmationModalOpen, prepareBalance, epoch, claim, isPayoutGhst, isClaimable }) => {
|
const MobileClaimInfo = ({ setConfirmationModalOpen, prepareBalance, epoch, claim, isPayoutGhst, isClaimable, ghstSymbol, stnkSymbol }) => {
|
||||||
return (
|
return (
|
||||||
<Box mt="10px">
|
<Box mt="10px">
|
||||||
<Box display="flex" flexDirection="row" alignItems="center" style={{ whiteSpace: "nowrap" }}>
|
<Box display="flex" flexDirection="row" alignItems="center" style={{ whiteSpace: "nowrap" }}>
|
||||||
<Token key={isPayoutGhst ? "GHST" : "STNK"} name={isPayoutGhst ? "GHST" : "STNK"} />
|
<Token key={isPayoutGhst ? ghstSymbol : stnkSymbol} name={isPayoutGhst ? ghstSymbol : stnkSymbol} />
|
||||||
<Box marginLeft="14px" marginRight="10px">
|
<Box marginLeft="14px" marginRight="10px">
|
||||||
<Typography>{isPayoutGhst ? "GHST" : "STNK"}</Typography>
|
<Typography>{isPayoutGhst ? ghstSymbol : stnkSymbol}</Typography>
|
||||||
</Box>
|
</Box>
|
||||||
</Box>
|
</Box>
|
||||||
|
|
||||||
|
@ -18,7 +18,7 @@ import { DecimalBigNumber } from "../../../helpers/DecimalBigNumber";
|
|||||||
import { formatCurrency } from "../../../helpers";
|
import { formatCurrency } from "../../../helpers";
|
||||||
|
|
||||||
import { useLpValuation } from "../../../hooks/treasury";
|
import { useLpValuation } from "../../../hooks/treasury";
|
||||||
import { useTotalSupply } from "../../../hooks/tokens";
|
import { useTotalSupply, useTokenSymbol } from "../../../hooks/tokens";
|
||||||
|
|
||||||
import {
|
import {
|
||||||
DAI_ADDRESSES,
|
DAI_ADDRESSES,
|
||||||
@ -31,10 +31,13 @@ const FarmPools = ({ chainId }) => {
|
|||||||
const { totalSupply: daiFtsoUniTotalSupply } = useTotalSupply(chainId, "GDAI_FTSO");
|
const { totalSupply: daiFtsoUniTotalSupply } = useTotalSupply(chainId, "GDAI_FTSO");
|
||||||
const daiFtsoUniValuation = useLpValuation(chainId, "GDAI_FTSO", daiFtsoUniTotalSupply._value);
|
const daiFtsoUniValuation = useLpValuation(chainId, "GDAI_FTSO", daiFtsoUniTotalSupply._value);
|
||||||
|
|
||||||
|
const { symbol: daiSymbol } = useTokenSymbol(chainId, "GDAI");
|
||||||
|
const { symbol: ftsoSymbol } = useTokenSymbol(chainId, "FTSO");
|
||||||
|
|
||||||
const pools = [
|
const pools = [
|
||||||
{
|
{
|
||||||
icons: ["FTSO", "GDAI"],
|
icons: ["FTSO", "GDAI"],
|
||||||
name: "FTSO-gDAI",
|
name: `${ftsoSymbol}-${daiSymbol}`,
|
||||||
dex: "Uniswap V2",
|
dex: "Uniswap V2",
|
||||||
url: "/dex/uniswap",
|
url: "/dex/uniswap",
|
||||||
tvl: daiFtsoUniValuation,
|
tvl: daiFtsoUniValuation,
|
||||||
@ -61,7 +64,7 @@ const FarmPools = ({ chainId }) => {
|
|||||||
return (
|
return (
|
||||||
<Paper headerText="Farm Pools" fullWidth enableBackground>
|
<Paper headerText="Farm Pools" fullWidth enableBackground>
|
||||||
<TableContainer>
|
<TableContainer>
|
||||||
<Table aria-label="Available bonds" style={{ tableLayout: "fixed" }}>
|
<Table aria-label="Farm pools" style={{ tableLayout: "fixed" }}>
|
||||||
<TableHead>
|
<TableHead>
|
||||||
<TableRow>
|
<TableRow>
|
||||||
<TableCell style={{ padding: "8px 0", width: "30%" }}>Asset</TableCell>
|
<TableCell style={{ padding: "8px 0", width: "30%" }}>Asset</TableCell>
|
||||||
|
@ -13,7 +13,7 @@ export const CurrentIndex = props => {
|
|||||||
const _props = {
|
const _props = {
|
||||||
...props,
|
...props,
|
||||||
label: `Current Index`,
|
label: `Current Index`,
|
||||||
tooltip: `The current index indicates the amount of FTSO a holder would possess if they had staked and maintained 1 FTSO since its launch.`,
|
tooltip: `The current index indicates the amount of ${props.ftsoSymbol} a holder would possess if they had staked and maintained 1 ${props.ftsoSymbol} since its launch.`,
|
||||||
};
|
};
|
||||||
|
|
||||||
if (currentIndex) _props.metric = `${formatNumber(currentIndex, 2)}`;
|
if (currentIndex) _props.metric = `${formatNumber(currentIndex, 2)}`;
|
||||||
@ -35,7 +35,7 @@ export const Apy = props => {
|
|||||||
const _props = {
|
const _props = {
|
||||||
...props,
|
...props,
|
||||||
label: "APY",
|
label: "APY",
|
||||||
tooltip: "The annualized rate of return, accounting for compounding from STNK’s exponential rebasing.",
|
tooltip: `The annualized rate of return, accounting for compounding from ${props.stnkSymbol}’s exponential rebasing.`,
|
||||||
};
|
};
|
||||||
|
|
||||||
if (apy) _props.metric = `${formatNumber(apy, 2)}${apy === Infinity ? "" : "%"}`;
|
if (apy) _props.metric = `${formatNumber(apy, 2)}${apy === Infinity ? "" : "%"}`;
|
||||||
@ -52,7 +52,7 @@ export const TotalDeposit = props => {
|
|||||||
const _props = {
|
const _props = {
|
||||||
...props,
|
...props,
|
||||||
label: "Total Deposit",
|
label: "Total Deposit",
|
||||||
tooltip: "The total stablecoin reserves in the ghostDAO treasury backing the entire circulating supply of STNK.",
|
tooltip: `The total stablecoin reserves in the ghostDAO treasury backing the entire circulating supply of ${props.stnkSymbol}.`,
|
||||||
};
|
};
|
||||||
|
|
||||||
if (deposit) _props.metric = `${formatCurrency(deposit, 2)}`;
|
if (deposit) _props.metric = `${formatCurrency(deposit, 2)}`;
|
||||||
|
@ -39,7 +39,7 @@ const StakeConfirmationModal = (props) => {
|
|||||||
checkedIcon={<CheckBoxOutlined viewBox="0 0 24 24" />}
|
checkedIcon={<CheckBoxOutlined viewBox="0 0 24 24" />}
|
||||||
/>
|
/>
|
||||||
}
|
}
|
||||||
label={`I understand the FTSO (eGHST) I’m staking will only be available to claim ${warmupLength.toString()} epochs after my transaction is confirmed`}
|
label={`I understand the ${props.ftsoSymbol} I’m staking will only be available to claim ${warmupLength.toString()} epochs after my transaction is confirmed`}
|
||||||
/>
|
/>
|
||||||
</Box>
|
</Box>
|
||||||
</>
|
</>
|
||||||
@ -115,7 +115,7 @@ const StakeConfirmationModal = (props) => {
|
|||||||
/>
|
/>
|
||||||
<Box display="flex" flexDirection="row" justifyContent="center">
|
<Box display="flex" flexDirection="row" justifyContent="center">
|
||||||
<Typography>
|
<Typography>
|
||||||
{props.upperToken}
|
{props.upperToken === "FTSO" ? props.ftsoSymbol : props.upperToken === "STNK" ? props.stnkSymbol : props.ghstSymbol}
|
||||||
</Typography>
|
</Typography>
|
||||||
</Box>
|
</Box>
|
||||||
</Box>
|
</Box>
|
||||||
@ -127,7 +127,7 @@ const StakeConfirmationModal = (props) => {
|
|||||||
/>
|
/>
|
||||||
<Box display="flex" flexDirection="row" justifyContent="center">
|
<Box display="flex" flexDirection="row" justifyContent="center">
|
||||||
<Typography>
|
<Typography>
|
||||||
{props.bottomToken}
|
{props.bottomToken === "FTSO" ? props.ftsoSymbol : props.bottomToken === "STNK" ? props.stnkSymbol : props.ghstSymbol}
|
||||||
</Typography>
|
</Typography>
|
||||||
</Box>
|
</Box>
|
||||||
</Box>
|
</Box>
|
||||||
@ -141,7 +141,7 @@ const StakeConfirmationModal = (props) => {
|
|||||||
owner={props.address}
|
owner={props.address}
|
||||||
spender={STAKING_ADDRESSES[props.chainId]}
|
spender={STAKING_ADDRESSES[props.chainId]}
|
||||||
decimals={props.spendDecimals}
|
decimals={props.spendDecimals}
|
||||||
approvalText={"Approve " + props.upperToken}
|
approvalText={"Approve " + props.upperToken === "FTSO" ? props.ftsoSymbol : props.upperToken === "STNK" ? props.stnkSymbol : props.ghstSymbol}
|
||||||
approvalPendingText={"Approving..."}
|
approvalPendingText={"Approving..."}
|
||||||
connect={props.connect}
|
connect={props.connect}
|
||||||
isVertical
|
isVertical
|
||||||
|
@ -23,7 +23,7 @@ import {
|
|||||||
STAKING_ADDRESSES,
|
STAKING_ADDRESSES,
|
||||||
} from "../../../constants/addresses";
|
} from "../../../constants/addresses";
|
||||||
import { useCurrentIndex } from "../../../hooks/staking";
|
import { useCurrentIndex } from "../../../hooks/staking";
|
||||||
import { useBalance } from "../../../hooks/tokens";
|
import { useBalance, useTokenSymbol } from "../../../hooks/tokens";
|
||||||
import { formatNumber } from "../../../helpers";
|
import { formatNumber } from "../../../helpers";
|
||||||
|
|
||||||
const PREFIX = "StakeInputArea";
|
const PREFIX = "StakeInputArea";
|
||||||
@ -106,6 +106,10 @@ export const StakeInputArea = ({
|
|||||||
const { balance: stnkBalance, refetch: stnkRefetch } = useBalance(chainId, "STNK", address);
|
const { balance: stnkBalance, refetch: stnkRefetch } = useBalance(chainId, "STNK", address);
|
||||||
const { balance: ghstBalance, refetch: ghstRefetch } = useBalance(chainId, "GHST", address);
|
const { balance: ghstBalance, refetch: ghstRefetch } = useBalance(chainId, "GHST", address);
|
||||||
|
|
||||||
|
const { symbol: ftsoSymbol } = useTokenSymbol(chainId, "FTSO");
|
||||||
|
const { symbol: stnkSymbol } = useTokenSymbol(chainId, "STNK");
|
||||||
|
const { symbol: ghstSymbol } = useTokenSymbol(chainId, "GHST");
|
||||||
|
|
||||||
const setIsClaimInner = (value) => {
|
const setIsClaimInner = (value) => {
|
||||||
setIsClaim(value);
|
setIsClaim(value);
|
||||||
localStorage.setItem("stake-isClaim", value);
|
localStorage.setItem("stake-isClaim", value);
|
||||||
@ -181,15 +185,37 @@ export const StakeInputArea = ({
|
|||||||
}
|
}
|
||||||
|
|
||||||
const SwapCardTemplate = (tokenName, tokenAmount, isUpper, handleModal) => {
|
const SwapCardTemplate = (tokenName, tokenAmount, isUpper, handleModal) => {
|
||||||
const balance = tokenName === "STNK" ?
|
const balance = tokenName === "STNK" || tokenName === "sCSPR" ?
|
||||||
stnkBalance : tokenName === "FTSO" ?
|
stnkBalance : tokenName === "FTSO" || tokenName === "eCSPR" ?
|
||||||
ftsoBalance : ghstBalance;
|
ftsoBalance : ghstBalance;
|
||||||
|
|
||||||
|
let realTokenName = "";
|
||||||
|
switch (tokenName.toUpperCase()) {
|
||||||
|
case "FTSO":
|
||||||
|
realTokenName = ftsoSymbol;
|
||||||
|
break;
|
||||||
|
case "ECSPR":
|
||||||
|
realTokenName = ftsoSymbol;
|
||||||
|
break;
|
||||||
|
case "STNK":
|
||||||
|
realTokenName = stnkSymbol;
|
||||||
|
break;
|
||||||
|
case "SCSPR":
|
||||||
|
realTokenName = stnkSymbol;
|
||||||
|
break;
|
||||||
|
case "GHST":
|
||||||
|
realTokenName = ghstSymbol;
|
||||||
|
break;
|
||||||
|
case "CSPR":
|
||||||
|
realTokenName = ghstSymbol;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<SwapCard
|
<SwapCard
|
||||||
id={`${tokenName.toLowerCase()}-input`}
|
id={`${tokenName.toLowerCase()}-input`}
|
||||||
token={tokenName}
|
token={tokenName}
|
||||||
tokenName={tokenName}
|
tokenName={realTokenName}
|
||||||
tokenOnClick={() => handleModal(true)}
|
tokenOnClick={() => handleModal(true)}
|
||||||
inputProps={{ "data-testid": `${tokenName.toLowerCase()}-input`, min: "0" }}
|
inputProps={{ "data-testid": `${tokenName.toLowerCase()}-input`, min: "0" }}
|
||||||
value={tokenAmount}
|
value={tokenAmount}
|
||||||
@ -228,24 +254,30 @@ export const StakeInputArea = ({
|
|||||||
{upperTokenModalOpen && (
|
{upperTokenModalOpen && (
|
||||||
<TokenModal
|
<TokenModal
|
||||||
open={upperTokenModalOpen}
|
open={upperTokenModalOpen}
|
||||||
handleSelect={data => handleTokenModalInput(data.name, data.isUpper)}
|
handleSelect={data => handleTokenModalInput(data.token, data.isUpper)}
|
||||||
handleClose={() => setUpperTokenModalOpen(false)}
|
handleClose={() => setUpperTokenModalOpen(false)}
|
||||||
ftsoBalance={formatNumber(ftsoBalance, formatDecimals)}
|
ftsoBalance={formatNumber(ftsoBalance, formatDecimals)}
|
||||||
stnkBalance={formatNumber(stnkBalance, formatDecimals)}
|
stnkBalance={formatNumber(stnkBalance, formatDecimals)}
|
||||||
ghstBalance={formatNumber(ghstBalance, formatDecimals)}
|
ghstBalance={formatNumber(ghstBalance, formatDecimals)}
|
||||||
isUpper={true}
|
isUpper={true}
|
||||||
|
ftsoSymbol={ftsoSymbol}
|
||||||
|
stnkSymbol={stnkSymbol}
|
||||||
|
ghstSymbol={ghstSymbol}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
{bottomTokenModalOpen && (
|
{bottomTokenModalOpen && (
|
||||||
<TokenModal
|
<TokenModal
|
||||||
open={bottomTokenModalOpen}
|
open={bottomTokenModalOpen}
|
||||||
handleSelect={data => handleTokenModalInput(data.name, data.isUpper)}
|
handleSelect={data => handleTokenModalInput(data.token, data.isUpper)}
|
||||||
handleClose={() => setBottomTokenModalOpen(false)}
|
handleClose={() => setBottomTokenModalOpen(false)}
|
||||||
ftsoBalance={formatNumber(ftsoBalance, formatDecimals)}
|
ftsoBalance={formatNumber(ftsoBalance, formatDecimals)}
|
||||||
stnkBalance={formatNumber(stnkBalance, formatDecimals)}
|
stnkBalance={formatNumber(stnkBalance, formatDecimals)}
|
||||||
ghstBalance={formatNumber(ghstBalance, formatDecimals)}
|
ghstBalance={formatNumber(ghstBalance, formatDecimals)}
|
||||||
tokenToExclude={upperToken}
|
tokenToExclude={upperToken}
|
||||||
isUpper={false}
|
isUpper={false}
|
||||||
|
ftsoSymbol={ftsoSymbol}
|
||||||
|
stnkSymbol={stnkSymbol}
|
||||||
|
ghstSymbol={ghstSymbol}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
@ -292,6 +324,9 @@ export const StakeInputArea = ({
|
|||||||
receiveDecimals={bottomToken === "GHST" ? 18 : 9}
|
receiveDecimals={bottomToken === "GHST" ? 18 : 9}
|
||||||
isClaim={isClaim}
|
isClaim={isClaim}
|
||||||
isTrigger={isTrigger}
|
isTrigger={isTrigger}
|
||||||
|
ftsoSymbol={ftsoSymbol}
|
||||||
|
stnkSymbol={stnkSymbol}
|
||||||
|
ghstSymbol={ghstSymbol}
|
||||||
/>
|
/>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
|
@ -13,20 +13,23 @@ const TokenModal = ({
|
|||||||
ghstBalance = "0.00",
|
ghstBalance = "0.00",
|
||||||
tokenToExclude,
|
tokenToExclude,
|
||||||
isUpper,
|
isUpper,
|
||||||
|
ftsoSymbol,
|
||||||
|
stnkSymbol,
|
||||||
|
ghstSymbol
|
||||||
}) => {
|
}) => {
|
||||||
const theme = useTheme();
|
const theme = useTheme();
|
||||||
|
|
||||||
const TokenItem = ({ name, exclude, isUpper, balance = "0", icon, address = "", price, decimals, ...props }) => {
|
const TokenItem = ({ token, name, exclude, isUpper, balance = "0", icon, address = "", price, decimals, ...props }) => {
|
||||||
if (name === exclude) {
|
if (name === exclude) {
|
||||||
return <></>;
|
return <></>;
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ListItem
|
<ListItem
|
||||||
key={name}
|
key={token}
|
||||||
button
|
button="true"
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
handleSelect({name, isUpper});
|
handleSelect({token, isUpper});
|
||||||
handleClose();
|
handleClose();
|
||||||
}}
|
}}
|
||||||
sx={{ borderBottom: `1px solid ${theme.colors.gray[500]}` }}
|
sx={{ borderBottom: `1px solid ${theme.colors.gray[500]}` }}
|
||||||
@ -35,7 +38,7 @@ const TokenModal = ({
|
|||||||
{icon ? (
|
{icon ? (
|
||||||
<Avatar src={icon} sx={{ width: "15px", height: "15px" }} />
|
<Avatar src={icon} sx={{ width: "15px", height: "15px" }} />
|
||||||
) : (
|
) : (
|
||||||
<Token name={name} sx={{ fontSize: "15px" }} />
|
<Token name={token} sx={{ fontSize: "15px" }} />
|
||||||
)}
|
)}
|
||||||
|
|
||||||
<ListItemText
|
<ListItemText
|
||||||
@ -66,9 +69,9 @@ const TokenModal = ({
|
|||||||
</Link>
|
</Link>
|
||||||
</Box>
|
</Box>
|
||||||
<List>
|
<List>
|
||||||
{<TokenItem isUpper={isUpper} exclude={tokenToExclude} name="FTSO" balance={ftsoBalance} />}
|
{<TokenItem isUpper={isUpper} exclude={tokenToExclude} token="FTSO" name={ftsoSymbol} balance={ftsoBalance} />}
|
||||||
{<TokenItem isUpper={isUpper} exclude={tokenToExclude} name="STNK" balance={stnkBalance} />}
|
{<TokenItem isUpper={isUpper} exclude={tokenToExclude} token="STNK" name={stnkSymbol} balance={stnkBalance} />}
|
||||||
{<TokenItem isUpper={isUpper} exclude={tokenToExclude} name="GHST" balance={ghstBalance} />}
|
{<TokenItem isUpper={isUpper} exclude={tokenToExclude} token="GHST" name={ghstSymbol} balance={ghstBalance} />}
|
||||||
</List>
|
</List>
|
||||||
</Box>
|
</Box>
|
||||||
</Dialog>
|
</Dialog>
|
||||||
|
@ -17,11 +17,17 @@ import Paper from "../../components/Paper/Paper";
|
|||||||
import PageTitle from "../../components/PageTitle/PageTitle";
|
import PageTitle from "../../components/PageTitle/PageTitle";
|
||||||
import SafariFooter from "../../components/SafariFooter/SafariFooter";
|
import SafariFooter from "../../components/SafariFooter/SafariFooter";
|
||||||
|
|
||||||
|
import { useTokenSymbol } from "../../hooks/tokens";
|
||||||
|
|
||||||
const MetricsDashboard = ({ chainId }) => {
|
const MetricsDashboard = ({ chainId }) => {
|
||||||
const theme = useTheme();
|
const theme = useTheme();
|
||||||
const isMobileScreen = useMediaQuery("(max-width: 885px)");
|
const isMobileScreen = useMediaQuery("(max-width: 885px)");
|
||||||
const isVeryMobileScreen = useMediaQuery("(max-width: 560px)");
|
const isVeryMobileScreen = useMediaQuery("(max-width: 560px)");
|
||||||
|
|
||||||
|
const { symbol: ftsoSymbol } = useTokenSymbol(chainId, "FTSO");
|
||||||
|
const { symbol: stnkSymbol } = useTokenSymbol(chainId, "STNK");
|
||||||
|
const { symbol: ghstSymbol } = useTokenSymbol(chainId, "GHST");
|
||||||
|
|
||||||
const xsCalculator = useMemo(() => {
|
const xsCalculator = useMemo(() => {
|
||||||
return isMobileScreen ? isVeryMobileScreen ? 12 : 6 : 4;
|
return isMobileScreen ? isVeryMobileScreen ? 12 : 6 : 4;
|
||||||
}, [isMobileScreen, isVeryMobileScreen])
|
}, [isMobileScreen, isVeryMobileScreen])
|
||||||
@ -33,22 +39,22 @@ const MetricsDashboard = ({ chainId }) => {
|
|||||||
<Paper fullWidth enableBackground>
|
<Paper fullWidth enableBackground>
|
||||||
<Grid container spacing={2}>
|
<Grid container spacing={2}>
|
||||||
<Grid item xs={xsCalculator}>
|
<Grid item xs={xsCalculator}>
|
||||||
<TreasuryMarketCap chainId={chainId} />
|
<TreasuryMarketCap ftsoSymbol={ftsoSymbol} chainId={chainId} />
|
||||||
</Grid>
|
</Grid>
|
||||||
<Grid item xs={xsCalculator}>
|
<Grid item xs={xsCalculator}>
|
||||||
<FatsoPrice chainId={chainId} />
|
<FatsoPrice ftsoSymbol={ftsoSymbol} chainId={chainId} />
|
||||||
</Grid>
|
</Grid>
|
||||||
<Grid item xs={xsCalculator}>
|
<Grid item xs={xsCalculator}>
|
||||||
<GhostPrice chainId={chainId} />
|
<GhostPrice ghstSymbol={ghstSymbol} ftsoSymbol={ftsoSymbol} chainId={chainId} />
|
||||||
</Grid>
|
</Grid>
|
||||||
<Grid item xs={xsCalculator}>
|
<Grid item xs={xsCalculator}>
|
||||||
<CirculatingSupply chainId={chainId} />
|
<CirculatingSupply stnkSymbol={stnkSymbol} chainId={chainId} />
|
||||||
</Grid>
|
</Grid>
|
||||||
<Grid item xs={xsCalculator}>
|
<Grid item xs={xsCalculator}>
|
||||||
<FatsoBacking chainId={chainId} />
|
<FatsoBacking ftsoSymbol={ftsoSymbol} chainId={chainId} />
|
||||||
</Grid>
|
</Grid>
|
||||||
<Grid item xs={xsCalculator}>
|
<Grid item xs={xsCalculator}>
|
||||||
<CurrentIndex chainId={chainId} />
|
<CurrentIndex ftsoSymbol={ftsoSymbol} chainId={chainId} />
|
||||||
</Grid>
|
</Grid>
|
||||||
</Grid>
|
</Grid>
|
||||||
</Paper>
|
</Paper>
|
||||||
|
@ -15,10 +15,10 @@ export const CurrentIndex = props => {
|
|||||||
const _props = {
|
const _props = {
|
||||||
...props,
|
...props,
|
||||||
label: `Current Index`,
|
label: `Current Index`,
|
||||||
tooltip: `The current index indicates the amount of FTSO a holder would possess if they had staked and maintained 1 FTSO since its launch.`,
|
tooltip: `The current index indicates the amount of ${props.ftsoSymbol} a holder would possess if they had staked and maintained 1 ${props.ftsoSymbol} since its launch.`,
|
||||||
};
|
};
|
||||||
|
|
||||||
if (currentIndex) _props.metric = `${formatNumber(currentIndex, 2)} FTSO`;
|
if (currentIndex) _props.metric = `${formatNumber(currentIndex, 2)} ${props.ftsoSymbol}`;
|
||||||
else _props.isLoading = true;
|
else _props.isLoading = true;
|
||||||
|
|
||||||
return <Metric {..._props} />;
|
return <Metric {..._props} />;
|
||||||
@ -31,8 +31,8 @@ export const GhostPrice = props => {
|
|||||||
|
|
||||||
const _props = {
|
const _props = {
|
||||||
...props,
|
...props,
|
||||||
label: "GHST " + `Price`,
|
label: `${props.ghstSymbol} Price`,
|
||||||
tooltip: "1 GHST = 1 FTSO x Current Index",
|
tooltip: `1 ${props.ghstSymbol} = 1 ${props.ftsoSymbol} x Current Index`,
|
||||||
};
|
};
|
||||||
|
|
||||||
if (ghstPrice) _props.metric = formatCurrency(ghstPrice, 2);
|
if (ghstPrice) _props.metric = formatCurrency(ghstPrice, 2);
|
||||||
@ -46,8 +46,8 @@ export const FatsoPrice = props => {
|
|||||||
|
|
||||||
const _props = {
|
const _props = {
|
||||||
...props,
|
...props,
|
||||||
label: "FTSO " + `Price`,
|
label: `${props.ftsoSymbol} Price`,
|
||||||
tooltip: `Weighted FTSO Price Across V2 DEXs on the chosen EVM Chain`,
|
tooltip: `Weighted ${props.ftsoSymbol} Price Across V2 DEXs on the chosen EVM Chain`,
|
||||||
};
|
};
|
||||||
|
|
||||||
if (ftsoPrice) _props.metric = formatCurrency(ftsoPrice, 2);
|
if (ftsoPrice) _props.metric = formatCurrency(ftsoPrice, 2);
|
||||||
@ -63,7 +63,7 @@ export const CirculatingSupply = props => {
|
|||||||
const _props = {
|
const _props = {
|
||||||
...props,
|
...props,
|
||||||
label: `Circulating / Total`,
|
label: `Circulating / Total`,
|
||||||
tooltip: `Circulating supply refers to the amount of STNK in circulation, excluding those held by the protocol in its treasury. However, STNK allocated to Protocol-Owned Liquidity is considered part of the circulating supply.`,
|
tooltip: `Circulating supply refers to the amount of ${props.stnkSymbol} in circulation, excluding those held by the protocol in its treasury. However, ${props.stnkSymbol} allocated to Protocol-Owned Liquidity is considered part of the circulating supply.`,
|
||||||
};
|
};
|
||||||
|
|
||||||
if (circulatingSupply && totalSupply) _props.metric = `${formatNumber(circulatingSupply, 0)}/${formatNumber(totalSupply, 0)}`;
|
if (circulatingSupply && totalSupply) _props.metric = `${formatNumber(circulatingSupply, 0)}/${formatNumber(totalSupply, 0)}`;
|
||||||
@ -83,8 +83,8 @@ export const FatsoBacking = props => {
|
|||||||
|
|
||||||
const _props = {
|
const _props = {
|
||||||
...props,
|
...props,
|
||||||
label: `Backing per FTSO`,
|
label: `Backing per ${props.ftsoSymbol}`,
|
||||||
tooltip: `The total amount of stablecoins held by the ghostDAO treasury to support the value of each FTSO in circulation.`
|
tooltip: `The total amount of stablecoins held by the ghostDAO treasury to support the value of each ${props.ftsoSymbol} in circulation.`
|
||||||
};
|
};
|
||||||
|
|
||||||
if (backing) _props.metric = formatCurrency(backing, 2);
|
if (backing) _props.metric = formatCurrency(backing, 2);
|
||||||
@ -101,7 +101,7 @@ export const TreasuryMarketCap = props => {
|
|||||||
const _props = {
|
const _props = {
|
||||||
...props,
|
...props,
|
||||||
label: `Market Cap`,
|
label: `Market Cap`,
|
||||||
tooltip: `Market Cap = FTSO Price × FTSO Total Supply`
|
tooltip: `Market Cap = ${props.ftsoSymbol} Price × ${props.ftsoSymbol} Total Supply`
|
||||||
};
|
};
|
||||||
|
|
||||||
if (marketCap) _props.metric = formatCurrency(marketCap, 2);
|
if (marketCap) _props.metric = formatCurrency(marketCap, 2);
|
||||||
|
@ -7,7 +7,7 @@ import { SecondaryButton } from "../../../components/Button";
|
|||||||
import { formatNumber, formatCurrency } from "../../../helpers";
|
import { formatNumber, formatCurrency } from "../../../helpers";
|
||||||
import { DecimalBigNumber } from "../../../helpers/DecimalBigNumber";
|
import { DecimalBigNumber } from "../../../helpers/DecimalBigNumber";
|
||||||
|
|
||||||
import { useBalance } from "../../../hooks/tokens";
|
import { useBalance, useTokenSymbol } from "../../../hooks/tokens";
|
||||||
import {
|
import {
|
||||||
useFtsoPrice,
|
useFtsoPrice,
|
||||||
useStnkPrice,
|
useStnkPrice,
|
||||||
@ -79,6 +79,11 @@ const TokenInfo = ({ chainId, isMobileScreen }) => {
|
|||||||
const ghstPrice = useGhstPrice(chainId);
|
const ghstPrice = useGhstPrice(chainId);
|
||||||
const daiPrice = useDaiPrice(chainId);
|
const daiPrice = useDaiPrice(chainId);
|
||||||
|
|
||||||
|
const { symbol: daiSymbol } = useTokenSymbol(chainId, "GDAI");
|
||||||
|
const { symbol: ftsoSymbol } = useTokenSymbol(chainId, "FTSO");
|
||||||
|
const { symbol: stnkSymbol } = useTokenSymbol(chainId, "STNK");
|
||||||
|
const { symbol: ghstSymbol } = useTokenSymbol(chainId, "GHST");
|
||||||
|
|
||||||
const { balance: ftsoBalance, contractAddress: ftsoAddress } = useBalance(chainId, "FTSO", address);
|
const { balance: ftsoBalance, contractAddress: ftsoAddress } = useBalance(chainId, "FTSO", address);
|
||||||
const { balance: stnkBalance, contractAddress: stnkAddress } = useBalance(chainId, "STNK", address);
|
const { balance: stnkBalance, contractAddress: stnkAddress } = useBalance(chainId, "STNK", address);
|
||||||
const { balance: ghstBalance, contractAddress: ghstAddress } = useBalance(chainId, "GHST", address);
|
const { balance: ghstBalance, contractAddress: ghstAddress } = useBalance(chainId, "GHST", address);
|
||||||
@ -95,10 +100,10 @@ const TokenInfo = ({ chainId, isMobileScreen }) => {
|
|||||||
to: `${ftsoAddress}`,
|
to: `${ftsoAddress}`,
|
||||||
})}
|
})}
|
||||||
theme={theme}
|
theme={theme}
|
||||||
tokenName="FTSO"
|
tokenName={ftsoSymbol}
|
||||||
balance={ftsoBalance}
|
balance={ftsoBalance}
|
||||||
price={ftsoPrice}
|
price={ftsoPrice}
|
||||||
description="FTSO is the native token of the ghostDAO protocol, fully backed by stablecoin reserves held in the ghostDAO treasury."
|
description={`${ftsoSymbol} is the native token of the ghostDAO protocol, fully backed by stablecoin reserves held in the ghostDAO treasury.`}
|
||||||
/>
|
/>
|
||||||
<TokenTab
|
<TokenTab
|
||||||
isMobileScreen={isMobileScreen}
|
isMobileScreen={isMobileScreen}
|
||||||
@ -108,10 +113,10 @@ const TokenInfo = ({ chainId, isMobileScreen }) => {
|
|||||||
to: `${stnkAddress}`,
|
to: `${stnkAddress}`,
|
||||||
})}
|
})}
|
||||||
theme={theme}
|
theme={theme}
|
||||||
tokenName="STNK"
|
tokenName={stnkSymbol}
|
||||||
balance={stnkBalance}
|
balance={stnkBalance}
|
||||||
price={stnkPrice}
|
price={stnkPrice}
|
||||||
description="STNK is a receipt for staked FTSO, growing with staking rewards. When unstaked, it’s burned for FTSO at a 1:1 ratio."
|
description={`${stnkSymbol} is a receipt for staked ${ftsoSymbol}, growing with staking rewards. When unstaked, it’s burned for ${ftsoSymbol} at a 1:1 ratio.`}
|
||||||
/>
|
/>
|
||||||
<TokenTab
|
<TokenTab
|
||||||
isMobileScreen={isMobileScreen}
|
isMobileScreen={isMobileScreen}
|
||||||
@ -121,20 +126,20 @@ const TokenInfo = ({ chainId, isMobileScreen }) => {
|
|||||||
to: `${ghstAddress}`,
|
to: `${ghstAddress}`,
|
||||||
})}
|
})}
|
||||||
theme={theme}
|
theme={theme}
|
||||||
tokenName="GHST"
|
tokenName={ghstSymbol}
|
||||||
balance={ghstBalance}
|
balance={ghstBalance}
|
||||||
price={ghstPrice}
|
price={ghstPrice}
|
||||||
description="GHST enables ghostDAO to have on-chain governance and to be truly cross-chain. GHST Price = FTSO Price x Current Index."
|
description={`${ghstSymbol} enables ghostDAO to have on-chain governance and to be truly cross-chain. ${ghstSymbol} Price = ${ftsoSymbol} Price x Current Index.`}
|
||||||
/>
|
/>
|
||||||
<TokenTab
|
<TokenTab
|
||||||
isMobileScreen={isMobileScreen}
|
isMobileScreen={isMobileScreen}
|
||||||
tokenUrl="/faucet"
|
tokenUrl="/faucet"
|
||||||
tokenUrlParams=""
|
tokenUrlParams=""
|
||||||
theme={theme}
|
theme={theme}
|
||||||
tokenName="gDAI"
|
tokenName={daiSymbol}
|
||||||
balance={daiBalance}
|
balance={daiBalance}
|
||||||
price={daiPrice}
|
price={daiPrice}
|
||||||
description="FTSO is backed by a treasury reserve of crypto assets, with gDAI being the primary and most liquid asset."
|
description={`${ftsoSymbol} is backed by a treasury reserve of crypto assets, with ${daiSymbol} being the primary and most liquid asset.`}
|
||||||
/>
|
/>
|
||||||
</Box>
|
</Box>
|
||||||
</Grid>
|
</Grid>
|
||||||
|
@ -14,7 +14,8 @@ import { abi as TreasuryAbi } from "../../abi/GhostTreasury.json";
|
|||||||
import { abi as BondingCalculatorAbi } from "../../abi/GhostBondingCalculator.json";
|
import { abi as BondingCalculatorAbi } from "../../abi/GhostBondingCalculator.json";
|
||||||
|
|
||||||
import { useFtsoPrice } from "../prices";
|
import { useFtsoPrice } from "../prices";
|
||||||
import { getTokenAddress, getTokenIcons, getTokenName, getBondNameDisplayName, getTokenPurchaseLink } from "../helpers";
|
import { useTokenSymbol, useTokenSymbols } from "../tokens";
|
||||||
|
import { getTokenAddress, getTokenIcons, getBondNameDisplayName, getTokenPurchaseLink } from "../helpers";
|
||||||
import { DecimalBigNumber } from "../../helpers/DecimalBigNumber";
|
import { DecimalBigNumber } from "../../helpers/DecimalBigNumber";
|
||||||
import { shorten } from "../../helpers";
|
import { shorten } from "../../helpers";
|
||||||
|
|
||||||
@ -104,6 +105,9 @@ export const useLiveBonds = (chainId) => {
|
|||||||
})
|
})
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const { symbols: quoteTokenSymbols } = useTokenSymbols(chainId, markets?.map(m => m.result?.at(1)));
|
||||||
|
const { symbol: baseTokenSymbol } = useTokenSymbol(chainId, "FTSO");
|
||||||
|
|
||||||
const liveBonds = liveIndexesRaw ? liveIndexesRaw.map((bondIndex, index) => {
|
const liveBonds = liveIndexesRaw ? liveIndexesRaw.map((bondIndex, index) => {
|
||||||
const id = Number(bondIndex);
|
const id = Number(bondIndex);
|
||||||
|
|
||||||
@ -119,6 +123,7 @@ export const useLiveBonds = (chainId) => {
|
|||||||
const markdown = markdowns?.at(index).result
|
const markdown = markdowns?.at(index).result
|
||||||
? new DecimalBigNumber(markdowns.at(index).result, quoteTokenDecimals)
|
? new DecimalBigNumber(markdowns.at(index).result, quoteTokenDecimals)
|
||||||
: new DecimalBigNumber(1n, 0);
|
: new DecimalBigNumber(1n, 0);
|
||||||
|
const quoteTokenSymbol = quoteTokenSymbols?.at(index).result ? quoteTokenSymbols.at(index).result : "";
|
||||||
|
|
||||||
const quoteTokenPerBaseToken = new DecimalBigNumber(marketPrice, 9);
|
const quoteTokenPerBaseToken = new DecimalBigNumber(marketPrice, 9);
|
||||||
const priceInUsd = quoteTokenPerUsd.mul(quoteTokenPerBaseToken).mul(markdown);
|
const priceInUsd = quoteTokenPerUsd.mul(quoteTokenPerBaseToken).mul(markdown);
|
||||||
@ -140,19 +145,20 @@ export const useLiveBonds = (chainId) => {
|
|||||||
);
|
);
|
||||||
|
|
||||||
const zero = new DecimalBigNumber(0n, 0);
|
const zero = new DecimalBigNumber(0n, 0);
|
||||||
|
const bondName = `${baseTokenSymbol}/${quoteTokenSymbol}`;
|
||||||
|
|
||||||
return {
|
return {
|
||||||
id,
|
id,
|
||||||
discount,
|
discount,
|
||||||
displayName: getBondNameDisplayName(chainId, markets?.at(index).result?.at(1)),
|
displayName: getBondNameDisplayName(chainId, bondName, quoteTokenAddress),
|
||||||
baseToken: {
|
baseToken: {
|
||||||
name: "FTSO",
|
name: quoteTokenSymbol,
|
||||||
purchaseUrl: getTokenPurchaseLink(chainId, ""),
|
purchaseUrl: getTokenPurchaseLink(chainId, ""),
|
||||||
icons: ["FTSO"],
|
icons: ["FTSO"],
|
||||||
tokenAddress: getTokenAddress(chainId, "FTSO")
|
tokenAddress: getTokenAddress(chainId, "FTSO")
|
||||||
},
|
},
|
||||||
quoteToken: {
|
quoteToken: {
|
||||||
name: getTokenName(chainId, quoteTokenAddress),
|
name: quoteTokenName,
|
||||||
purchaseUrl: getTokenPurchaseLink(chainId, quoteTokenAddress),
|
purchaseUrl: getTokenPurchaseLink(chainId, quoteTokenAddress),
|
||||||
icons: getTokenIcons(chainId, quoteTokenAddress),
|
icons: getTokenIcons(chainId, quoteTokenAddress),
|
||||||
decimals: quoteTokenDecimals,
|
decimals: quoteTokenDecimals,
|
||||||
@ -229,14 +235,17 @@ export const useNotes = (chainId, address) => {
|
|||||||
}),
|
}),
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const { symbols: quoteTokenSymbols } = useTokenSymbols(chainId, markets?.map(m => m.result?.at(1)));
|
||||||
|
|
||||||
const notes = indexesFor ? indexesFor.map((noteIndex, index) => {
|
const notes = indexesFor ? indexesFor.map((noteIndex, index) => {
|
||||||
const id = Number(noteIndex);
|
const id = Number(noteIndex);
|
||||||
const quoteTokenAddress = markets?.at(index).result?.at(1) ? markets.at(index).result.at(1) : "";
|
const quoteTokenAddress = markets?.at(index).result?.at(1) ? markets.at(index).result.at(1) : "";
|
||||||
|
const quoteTokenSymbol = quoteTokenSymbols?.at(index).result ? quoteTokenSymbols.at(index).result : "";
|
||||||
|
|
||||||
return {
|
return {
|
||||||
id,
|
id,
|
||||||
quoteToken: {
|
quoteToken: {
|
||||||
name: getTokenName(chainId, quoteTokenAddress),
|
name: quoteTokenSymbol,
|
||||||
icons: getTokenIcons(chainId, quoteTokenAddress),
|
icons: getTokenIcons(chainId, quoteTokenAddress),
|
||||||
},
|
},
|
||||||
vesting: terms?.at(index).result?.at(2) ? terms.at(index).result.at(2) : 0,
|
vesting: terms?.at(index).result?.at(2) ? terms.at(index).result.at(2) : 0,
|
||||||
|
@ -12,59 +12,98 @@ import { abi as StinkyAbi } from "../abi/Stinky.json";
|
|||||||
import { abi as GhostAbi } from "../abi/Ghost.json";
|
import { abi as GhostAbi } from "../abi/Ghost.json";
|
||||||
import { abi as Erc20Abi } from "../abi/ERC20.json";
|
import { abi as Erc20Abi } from "../abi/ERC20.json";
|
||||||
|
|
||||||
|
// TBD: should be extended on new tokens
|
||||||
export const getTokenAbi = (name) => {
|
export const getTokenAbi = (name) => {
|
||||||
let abi = Erc20Abi;
|
let abi = Erc20Abi;
|
||||||
switch (name?.toUpperCase()) {
|
switch (name?.toUpperCase()) {
|
||||||
|
case "DAI":
|
||||||
|
abi = DaiAbi;
|
||||||
|
break;
|
||||||
case "GDAI":
|
case "GDAI":
|
||||||
abi = DaiAbi;
|
abi = DaiAbi;
|
||||||
break;
|
break;
|
||||||
case "FTSO":
|
case "FTSO":
|
||||||
abi = FatsoAbi;
|
abi = FatsoAbi;
|
||||||
break;
|
break;
|
||||||
|
case "ECSPR":
|
||||||
|
abi = FatsoAbi;
|
||||||
|
break;
|
||||||
case "STNK":
|
case "STNK":
|
||||||
abi = StinkyAbi;
|
abi = StinkyAbi;
|
||||||
break;
|
break;
|
||||||
|
case "SCSPR":
|
||||||
|
abi = StinkyAbi;
|
||||||
|
break;
|
||||||
case "GHST":
|
case "GHST":
|
||||||
abi = GhostAbi;
|
abi = GhostAbi;
|
||||||
break;
|
break;
|
||||||
|
case "CSPR":
|
||||||
|
abi = GhostAbi;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
return abi;
|
return abi;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TBD: should be extended on new tokens
|
||||||
export const getTokenDecimals = (name) => {
|
export const getTokenDecimals = (name) => {
|
||||||
let decimals = 18;
|
let decimals = 18;
|
||||||
switch (name?.toUpperCase()) {
|
switch (name?.toUpperCase()) {
|
||||||
|
case "DAI":
|
||||||
|
decimals = 18;
|
||||||
|
break;
|
||||||
case "GDAI":
|
case "GDAI":
|
||||||
decimals = 18;
|
decimals = 18;
|
||||||
break;
|
break;
|
||||||
case "FTSO":
|
case "FTSO":
|
||||||
decimals = 9;
|
decimals = 9;
|
||||||
break;
|
break;
|
||||||
|
case "ECSPR":
|
||||||
|
decimals = 9;
|
||||||
|
break;
|
||||||
case "STNK":
|
case "STNK":
|
||||||
decimals = 9;
|
decimals = 9;
|
||||||
break;
|
break;
|
||||||
|
case "SCSPR":
|
||||||
|
decimals = 9;
|
||||||
|
break;
|
||||||
case "GHST":
|
case "GHST":
|
||||||
decimals = 18;
|
decimals = 18;
|
||||||
break;
|
break;
|
||||||
|
case "CSPR":
|
||||||
|
decimals = 18;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
return decimals;
|
return decimals;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TBD: should be extended on new tokens
|
||||||
export const getTokenAddress = (chainId, name) => {
|
export const getTokenAddress = (chainId, name) => {
|
||||||
let address = name;
|
let address = name;
|
||||||
switch (name?.toUpperCase()) {
|
switch (name?.toUpperCase()) {
|
||||||
|
case "DAI":
|
||||||
|
address = DAI_ADDRESSES[chainId];
|
||||||
|
break;
|
||||||
case "GDAI":
|
case "GDAI":
|
||||||
address = DAI_ADDRESSES[chainId];
|
address = DAI_ADDRESSES[chainId];
|
||||||
break;
|
break;
|
||||||
case "FTSO":
|
case "FTSO":
|
||||||
address = FTSO_ADDRESSES[chainId];
|
address = FTSO_ADDRESSES[chainId];
|
||||||
break;
|
break;
|
||||||
|
case "ECSPR":
|
||||||
|
address = FTSO_ADDRESSES[chainId];
|
||||||
|
break;
|
||||||
case "STNK":
|
case "STNK":
|
||||||
address = STNK_ADDRESSES[chainId];
|
address = STNK_ADDRESSES[chainId];
|
||||||
break;
|
break;
|
||||||
|
case "SCSPR":
|
||||||
|
address = STNK_ADDRESSES[chainId];
|
||||||
|
break;
|
||||||
case "GHST":
|
case "GHST":
|
||||||
address = GHST_ADDRESSES[chainId];
|
address = GHST_ADDRESSES[chainId];
|
||||||
break;
|
break;
|
||||||
|
case "CSPR":
|
||||||
|
address = GHST_ADDRESSES[chainId];
|
||||||
|
break;
|
||||||
case "GDAI_FTSO":
|
case "GDAI_FTSO":
|
||||||
address = FTSO_DAI_LP_ADDRESSES[chainId];
|
address = FTSO_DAI_LP_ADDRESSES[chainId];
|
||||||
break;
|
break;
|
||||||
@ -72,6 +111,7 @@ export const getTokenAddress = (chainId, name) => {
|
|||||||
return address;
|
return address;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TBD: should be extended on new tokens
|
||||||
export const getTokenIcons = (chainId, address) => {
|
export const getTokenIcons = (chainId, address) => {
|
||||||
let icons = [""];
|
let icons = [""];
|
||||||
switch (address) {
|
switch (address) {
|
||||||
@ -94,39 +134,11 @@ export const getTokenIcons = (chainId, address) => {
|
|||||||
return icons;
|
return icons;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const getTokenName = (chainId, address) => {
|
export const getBondNameDisplayName = (chainId, stringValue, tokenAddress) => {
|
||||||
let name = "";
|
if (tokenAddress.toUpperCase() === FTSO_DAI_LP_ADDRESSES[chainId].toUpperCase()) {
|
||||||
switch (address) {
|
stringValue = `LP ${stringValue}`;
|
||||||
case DAI_ADDRESSES[chainId]:
|
|
||||||
name = "gDAI";
|
|
||||||
break;
|
|
||||||
case FTSO_ADDRESSES[chainId]:
|
|
||||||
name = "FTSO";
|
|
||||||
break;
|
|
||||||
case STNK_ADDRESSES[chainId]:
|
|
||||||
name = "STNK";
|
|
||||||
break;
|
|
||||||
case GHST_ADDRESSES[chainId]:
|
|
||||||
name = "GHST";
|
|
||||||
break;
|
|
||||||
case FTSO_DAI_LP_ADDRESSES[chainId]:
|
|
||||||
name = "UNI-V2";
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
return name;
|
return stringValue;
|
||||||
}
|
|
||||||
|
|
||||||
export const getBondNameDisplayName = (chainId, tokenAddress) => {
|
|
||||||
let bondName = "";
|
|
||||||
switch (tokenAddress) {
|
|
||||||
case DAI_ADDRESSES[chainId]:
|
|
||||||
bondName = "FTSO/gDAI";
|
|
||||||
break;
|
|
||||||
case FTSO_DAI_LP_ADDRESSES[chainId]:
|
|
||||||
bondName = "LP FTSO/gDAI"
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
return bondName;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export const getTokenPurchaseLink = (chainId, tokenAddress) => {
|
export const getTokenPurchaseLink = (chainId, tokenAddress) => {
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import { useReadContract } from "wagmi";
|
import { useReadContract } from "wagmi";
|
||||||
|
|
||||||
import { useCurrentIndex } from "../staking";
|
import { useCurrentIndex, useGhostedSupply } from "../staking";
|
||||||
import { useUniswapV2PairReserves } from "../uniswapv2";
|
import { useUniswapV2PairReserves } from "../uniswapv2";
|
||||||
import { DecimalBigNumber } from "../../helpers/DecimalBigNumber";
|
import { DecimalBigNumber } from "../../helpers/DecimalBigNumber";
|
||||||
import { FTSO_DAI_LP_ADDRESSES, DAI_ADDRESSES, FTSO_ADDRESSES } from "../../constants/addresses";
|
import { FTSO_DAI_LP_ADDRESSES, DAI_ADDRESSES, FTSO_ADDRESSES } from "../../constants/addresses";
|
||||||
@ -20,13 +20,19 @@ export const useFtsoPrice = (chainId) => {
|
|||||||
"GDAI",
|
"GDAI",
|
||||||
);
|
);
|
||||||
|
|
||||||
const stableReserves = DAI_ADDRESSES[chainId].toUpperCase() === tokens.token0.toUpperCase()
|
const reserveAddress = DAI_ADDRESSES[chainId];
|
||||||
? reserves.reserve0._value
|
const ftsoAddress = FTSO_ADDRESSES[chainId];
|
||||||
: DAI_ADDRESSES[chainId].toUpperCase() === tokens.token1.toUpperCase() ? reserves.reserve1._value : 0n;
|
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
|
? 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
|
let price = 0n
|
||||||
if (ftsoReserves > 0n)
|
if (ftsoReserves > 0n)
|
||||||
@ -46,3 +52,10 @@ export const useGhstPrice = (chainId) => {
|
|||||||
|
|
||||||
return ftsoPrice.mul(currentIndex);
|
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 }
|
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) => {
|
export const stake = async (chainId, account, amount, isRebase, isClaim) => {
|
||||||
const args = [
|
const args = [
|
||||||
amount,
|
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 (
|
const executeOnChainTransaction = async (
|
||||||
chainId,
|
chainId,
|
||||||
functionName,
|
functionName,
|
||||||
@ -211,8 +259,11 @@ const executeOnChainTransaction = async (
|
|||||||
});
|
});
|
||||||
|
|
||||||
toast.success(messages.successMsg);
|
toast.success(messages.successMsg);
|
||||||
|
|
||||||
|
return txHash;
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error(err);
|
console.error(err);
|
||||||
toast.error(messages.errorMsg)
|
toast.error(messages.errorMsg)
|
||||||
|
return undefined;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import { useReadContract, useToken, useBalance as useInnerBalance } from "wagmi";
|
import { useReadContract, useReadContracts, useToken, useBalance as useInnerBalance } from "wagmi";
|
||||||
import { simulateContract, writeContract, waitForTransactionReceipt } from "@wagmi/core";
|
import { simulateContract, writeContract, waitForTransactionReceipt } from "@wagmi/core";
|
||||||
import toast from "react-hot-toast";
|
import toast from "react-hot-toast";
|
||||||
|
|
||||||
@ -72,6 +72,23 @@ export const useTokenSymbol = (chainId, name) => {
|
|||||||
return { symbol, refetch };
|
return { symbol, refetch };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const useTokenSymbols = (chainId, names) => {
|
||||||
|
const { data: symbols } = useReadContracts({
|
||||||
|
contracts: names?.map((name) => {
|
||||||
|
const contractAddress = getTokenAddress(chainId, name);
|
||||||
|
return {
|
||||||
|
abi: getTokenAbi(name),
|
||||||
|
address: contractAddress,
|
||||||
|
functionName: "symbol",
|
||||||
|
scopeKey: `symbol-${contractAddress}-${chainId}`,
|
||||||
|
chainId: chainId,
|
||||||
|
}
|
||||||
|
})
|
||||||
|
});
|
||||||
|
|
||||||
|
return { symbols };
|
||||||
|
}
|
||||||
|
|
||||||
export const useConversionRate = (chainId, name) => {
|
export const useConversionRate = (chainId, name) => {
|
||||||
const contractAddress = getTokenAddress(chainId, name);
|
const contractAddress = getTokenAddress(chainId, name);
|
||||||
const { data: rateRaw } = useReadContract({
|
const { data: rateRaw } = useReadContract({
|
||||||
@ -88,6 +105,22 @@ export const useConversionRate = (chainId, name) => {
|
|||||||
return rate;
|
return rate;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const useAccumulatedDonation = (chainId, name) => {
|
||||||
|
const contractAddress = getTokenAddress(chainId, name);
|
||||||
|
const { data: donationRaw } = useReadContract({
|
||||||
|
abi: getTokenAbi(name),
|
||||||
|
address: contractAddress,
|
||||||
|
functionName: "accumulatedDonation",
|
||||||
|
scopeKey: `accumulatedDonation-${contractAddress}-${chainId}`,
|
||||||
|
chainId: chainId,
|
||||||
|
});
|
||||||
|
|
||||||
|
const preparedDonationRaw = donationRaw ? donationRaw : 0n;
|
||||||
|
const accumulatedDonation = new DecimalBigNumber(preparedDonationRaw, 0);
|
||||||
|
|
||||||
|
return accumulatedDonation;
|
||||||
|
}
|
||||||
|
|
||||||
export const useCirculatingSupply = (chainId, name) => {
|
export const useCirculatingSupply = (chainId, name) => {
|
||||||
const contractAddress = getTokenAddress(chainId, name);
|
const contractAddress = getTokenAddress(chainId, name);
|
||||||
const { data: circulatingSupplyRaw } = useReadContract({
|
const { data: circulatingSupplyRaw } = useReadContract({
|
||||||
@ -171,3 +204,28 @@ export const mintDai = async (chainId, account, value) => {
|
|||||||
toast.error("Minting gDAI from the faucet failed. Check logs for error detalization.")
|
toast.error("Minting gDAI from the faucet failed. Check logs for error detalization.")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const burnDai = async (chainId, account, value) => {
|
||||||
|
try {
|
||||||
|
const { request } = await simulateContract(config, {
|
||||||
|
abi: getTokenAbi("GDAI"),
|
||||||
|
address: getTokenAddress(chainId, "GDAI"),
|
||||||
|
functionName: 'burn',
|
||||||
|
args: [value],
|
||||||
|
account: account,
|
||||||
|
chainId: chainId
|
||||||
|
});
|
||||||
|
|
||||||
|
const txHash = await writeContract(config, request);
|
||||||
|
await waitForTransactionReceipt(config, {
|
||||||
|
hash: txHash,
|
||||||
|
onReplaced: () => toast("Burn transaction was replaced. Wait for inclusion please."),
|
||||||
|
chainId
|
||||||
|
});
|
||||||
|
|
||||||
|
toast.success("gDAI successfully burned for native coins! Check your wallet balance.");
|
||||||
|
} catch (err) {
|
||||||
|
console.error(err);
|
||||||
|
toast.error("Burning gDAI from the faucet failed. Check logs for error detalization.")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -14,7 +14,6 @@ const queryClient = new QueryClient();
|
|||||||
const TRACKING_ID = import.meta.env.VITE_APP_TRACKING_ID;
|
const TRACKING_ID = import.meta.env.VITE_APP_TRACKING_ID;
|
||||||
ReactGA.initialize(TRACKING_ID);
|
ReactGA.initialize(TRACKING_ID);
|
||||||
|
|
||||||
|
|
||||||
ReactDOM.createRoot(document.getElementById('root')).render(
|
ReactDOM.createRoot(document.getElementById('root')).render(
|
||||||
<>
|
<>
|
||||||
<BackgroundCanvas />
|
<BackgroundCanvas />
|
||||||
|
@ -18,7 +18,7 @@ export const darkPalette = {
|
|||||||
success: "#60C45B", // idk where this is - done
|
success: "#60C45B", // idk where this is - done
|
||||||
userFeedback: "#49A1F2", // idk where this is
|
userFeedback: "#49A1F2", // idk where this is
|
||||||
error: "#F06F73", // red negative % - done
|
error: "#F06F73", // red negative % - done
|
||||||
warning: "#F06F73", // idk where this is - done
|
warning: "#49A1F2", // idk where this is - done
|
||||||
pnlGain: "#60C45B", // green positive % - done
|
pnlGain: "#60C45B", // green positive % - done
|
||||||
},
|
},
|
||||||
gray: {
|
gray: {
|
||||||
|
Loading…
Reference in New Issue
Block a user