support for native reserve added; e.g. mordor testnet
Signed-off-by: Uncle Fatso <uncle.fatso@ghostchain.io>
This commit is contained in:
parent
e6ed1596ef
commit
494df5f139
@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "ghost-dao-interface",
|
"name": "ghost-dao-interface",
|
||||||
"private": true,
|
"private": true,
|
||||||
"version": "0.2.16",
|
"version": "0.3.0",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "vite",
|
"dev": "vite",
|
||||||
|
|||||||
@ -14,7 +14,7 @@ import Sidebar from "./components/Sidebar/Sidebar";
|
|||||||
import TopBar from "./components/TopBar/TopBar";
|
import TopBar from "./components/TopBar/TopBar";
|
||||||
|
|
||||||
import { shouldTriggerSafetyCheck } from "./helpers";
|
import { shouldTriggerSafetyCheck } from "./helpers";
|
||||||
import { isNetworkAvailable } from "./constants";
|
import { isNetworkAvailable, isNetworkLegacy } from "./constants";
|
||||||
import useTheme from "./hooks/useTheme";
|
import useTheme from "./hooks/useTheme";
|
||||||
import { useUnstableProvider } from "./hooks/ghost";
|
import { useUnstableProvider } from "./hooks/ghost";
|
||||||
import { dark as darkTheme } from "./themes/dark.js";
|
import { dark as darkTheme } from "./themes/dark.js";
|
||||||
@ -27,6 +27,7 @@ const BondModalContainer = lazy(() => import("./containers/Bond/BondModal"));
|
|||||||
const StakeContainer = lazy(() => import("./containers/Stake/StakeContainer"));
|
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 Wrapper = lazy(() => import("./containers/WethWrapper/WethWrapper"));
|
||||||
const Dex = lazy(() => import("./containers/Dex/Dex"));
|
const Dex = lazy(() => import("./containers/Dex/Dex"));
|
||||||
const Bridge = lazy(() => import("./containers/Bridge/Bridge"));
|
const Bridge = lazy(() => import("./containers/Bridge/Bridge"));
|
||||||
const NotFound = lazy(() => import("./containers/NotFound/NotFound"));
|
const NotFound = lazy(() => import("./containers/NotFound/NotFound"));
|
||||||
@ -206,7 +207,10 @@ function App() {
|
|||||||
<Route path="/bonds" element={<Bonds connect={tryConnectInjected} address={address} chainId={addressChainId ? addressChainId : chainId} />} />
|
<Route path="/bonds" element={<Bonds connect={tryConnectInjected} address={address} chainId={addressChainId ? addressChainId : chainId} />} />
|
||||||
<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} />} />
|
{isNetworkLegacy(chainId)
|
||||||
|
? <Route path="/faucet" element={<Faucet config={config} connect={tryConnectInjected} address={address} chainId={addressChainId ? addressChainId : chainId} />} />
|
||||||
|
: <Route path="/wrapper" element={<Wrapper 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="/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
1
src/abi/WETH9.json
Normal file
1
src/abi/WETH9.json
Normal file
@ -0,0 +1 @@
|
|||||||
|
{"abi":[{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"src","type":"address"},{"indexed":true,"internalType":"address","name":"guy","type":"address"},{"indexed":false,"internalType":"uint256","name":"wad","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"dst","type":"address"},{"indexed":false,"internalType":"uint256","name":"wad","type":"uint256"}],"name":"Deposit","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"src","type":"address"},{"indexed":true,"internalType":"address","name":"dst","type":"address"},{"indexed":false,"internalType":"uint256","name":"wad","type":"uint256"}],"name":"Transfer","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"src","type":"address"},{"indexed":false,"internalType":"uint256","name":"wad","type":"uint256"}],"name":"Withdrawal","type":"event"},{"stateMutability":"payable","type":"fallback"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"}],"name":"allowance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"guy","type":"address"},{"internalType":"uint256","name":"wad","type":"uint256"}],"name":"approve","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"decimals","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"deposit","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"dst","type":"address"},{"internalType":"uint256","name":"wad","type":"uint256"}],"name":"transfer","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"src","type":"address"},{"internalType":"address","name":"dst","type":"address"},{"internalType":"uint256","name":"wad","type":"uint256"}],"name":"transferFrom","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"wad","type":"uint256"}],"name":"withdraw","outputs":[],"stateMutability":"nonpayable","type":"function"},{"stateMutability":"payable","type":"receive"}]}
|
||||||
@ -37,7 +37,7 @@ import BondIcon from "../Icon/BondIcon";
|
|||||||
import StakeIcon from "../Icon/StakeIcon";
|
import StakeIcon from "../Icon/StakeIcon";
|
||||||
import WrapIcon from "../Icon/WrapIcon";
|
import WrapIcon from "../Icon/WrapIcon";
|
||||||
|
|
||||||
import { isNetworkAvailable } from "../../constants";
|
import { isNetworkAvailable, isNetworkLegacy } from "../../constants";
|
||||||
import { AVAILABLE_DEXES } from "../../constants/dexes";
|
import { AVAILABLE_DEXES } from "../../constants/dexes";
|
||||||
import { ECOSYSTEM } from "../../constants/ecosystem";
|
import { ECOSYSTEM } from "../../constants/ecosystem";
|
||||||
import { DecimalBigNumber } from "../../helpers/DecimalBigNumber";
|
import { DecimalBigNumber } from "../../helpers/DecimalBigNumber";
|
||||||
@ -46,6 +46,7 @@ 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 WifiProtectedSetupIcon from '@mui/icons-material/WifiProtectedSetup';
|
||||||
|
|
||||||
import { useTokenSymbol } from "../../hooks/tokens";
|
import { useTokenSymbol } from "../../hooks/tokens";
|
||||||
import { useFtsoPrice, useGhstPrice, useGhostedSupplyPrice } from "../../hooks/prices";
|
import { useFtsoPrice, useGhstPrice, useGhostedSupplyPrice } from "../../hooks/prices";
|
||||||
@ -148,7 +149,10 @@ 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" />
|
{isNetworkLegacy(chainId)
|
||||||
|
? <NavItem icon={ShowerIcon} label={`Faucet`} to="/faucet" />
|
||||||
|
: <NavItem icon={WifiProtectedSetupIcon} label={`Wrapper`} to="/wrapper" />
|
||||||
|
}
|
||||||
<NavItem icon={PublicIcon} label={`Bridge`} to="/bridge" />
|
<NavItem icon={PublicIcon} label={`Bridge`} to="/bridge" />
|
||||||
<NavItem
|
<NavItem
|
||||||
icon={CurrencyExchangeIcon}
|
icon={CurrencyExchangeIcon}
|
||||||
|
|||||||
@ -57,6 +57,9 @@ const Token = ({ name, viewBox = "0 0 260 260", fontSize = "large", ...props })
|
|||||||
case "WETH":
|
case "WETH":
|
||||||
icon = WethIcon;
|
icon = WethIcon;
|
||||||
break;
|
break;
|
||||||
|
case "METC":
|
||||||
|
icon = WethIcon;
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
icon = UnknownIcon;
|
icon = UnknownIcon;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,8 +1,28 @@
|
|||||||
|
import { defineChain } from 'viem'
|
||||||
import { http, fallback, createConfig } from 'wagmi'
|
import { http, fallback, createConfig } from 'wagmi'
|
||||||
import { sepolia, hoodi } from 'wagmi/chains'
|
import { sepolia, hoodi } from 'wagmi/chains'
|
||||||
|
|
||||||
|
const mordor = defineChain({
|
||||||
|
id: 63,
|
||||||
|
name: 'Mordor',
|
||||||
|
nativeCurrency: {
|
||||||
|
decimals: 18,
|
||||||
|
name: 'METC',
|
||||||
|
symbol: 'METC',
|
||||||
|
},
|
||||||
|
rpcUrls: {
|
||||||
|
default: { http: ['https://rpc.mordor.etccooperative.org'] },
|
||||||
|
},
|
||||||
|
blockExplorers: {
|
||||||
|
default: {
|
||||||
|
name: 'Blockscout',
|
||||||
|
url: 'https://etc-mordor.blockscout.com/'
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
export const config = createConfig({
|
export const config = createConfig({
|
||||||
chains: [sepolia, hoodi],
|
chains: [sepolia, hoodi, mordor],
|
||||||
transports: {
|
transports: {
|
||||||
[sepolia.id]: fallback([
|
[sepolia.id]: fallback([
|
||||||
http('https://ethereum-sepolia-rpc.publicnode.com'),
|
http('https://ethereum-sepolia-rpc.publicnode.com'),
|
||||||
@ -16,6 +36,9 @@ export const config = createConfig({
|
|||||||
[hoodi.id]: fallback([
|
[hoodi.id]: fallback([
|
||||||
http('https://rpc.hoodi.ethpandaops.io'),
|
http('https://rpc.hoodi.ethpandaops.io'),
|
||||||
http('https://0xrpc.io/hoodi'),
|
http('https://0xrpc.io/hoodi'),
|
||||||
|
]),
|
||||||
|
[mordor.id]: fallback([
|
||||||
|
http('https://rpc.mordor.etccooperative.org'),
|
||||||
])
|
])
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|||||||
@ -1,10 +1,29 @@
|
|||||||
export enum NetworkId {
|
export enum NetworkId {
|
||||||
TESTNET_SEPOLIA = 11155111,
|
TESTNET_SEPOLIA = 11155111,
|
||||||
TESTNET_HOODI = 560048,
|
TESTNET_HOODI = 560048,
|
||||||
|
TESTNET_MORDOR = 63,
|
||||||
}
|
}
|
||||||
|
|
||||||
export const isNetworkAvailable = (chainId, addressChainId) => {
|
export const isNetworkAvailable = (chainId, addressChainId) => {
|
||||||
chainId = addressChainId ? addressChainId : chainId;
|
chainId = addressChainId ? addressChainId : chainId;
|
||||||
|
let exists = false;
|
||||||
|
switch (chainId) {
|
||||||
|
case 11155111:
|
||||||
|
exists = true
|
||||||
|
break;
|
||||||
|
case 560048:
|
||||||
|
exists = true
|
||||||
|
break;
|
||||||
|
case 63:
|
||||||
|
exists = true
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return exists;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const isNetworkLegacy = (chainId) => {
|
||||||
let exists = false;
|
let exists = false;
|
||||||
switch (chainId) {
|
switch (chainId) {
|
||||||
case 11155111:
|
case 11155111:
|
||||||
|
|||||||
@ -3,78 +3,98 @@ import { NetworkId } from "../constants";
|
|||||||
export const STAKING_ADDRESSES = {
|
export const STAKING_ADDRESSES = {
|
||||||
[NetworkId.TESTNET_SEPOLIA]: "0xd90E63E88282596E1ea33765b41Ba3d650f4aD52",
|
[NetworkId.TESTNET_SEPOLIA]: "0xd90E63E88282596E1ea33765b41Ba3d650f4aD52",
|
||||||
[NetworkId.TESTNET_HOODI]: "0x25F62eDc6C89FF84E957C22336A35d2dfc861a86",
|
[NetworkId.TESTNET_HOODI]: "0x25F62eDc6C89FF84E957C22336A35d2dfc861a86",
|
||||||
|
[NetworkId.TESTNET_MORDOR]: "0xC25C9C56a89ebd6ef291b415d00ACfa7913c55e7",
|
||||||
};
|
};
|
||||||
|
|
||||||
export const BOND_DEPOSITORY_ADDRESSES = {
|
export const BOND_DEPOSITORY_ADDRESSES = {
|
||||||
[NetworkId.TESTNET_SEPOLIA]: "0xdcE486113280e49ca2fB200258E5Ee1B2D21D495",
|
[NetworkId.TESTNET_SEPOLIA]: "0xdcE486113280e49ca2fB200258E5Ee1B2D21D495",
|
||||||
[NetworkId.TESTNET_HOODI]: "0x6Ad50B1E293E68B2fC230c576220a93A9D311571",
|
[NetworkId.TESTNET_HOODI]: "0x6Ad50B1E293E68B2fC230c576220a93A9D311571",
|
||||||
|
[NetworkId.TESTNET_MORDOR]: "0x7C85cDEddBAd0f50453d373F7332BEa11ECa7BAf",
|
||||||
};
|
};
|
||||||
|
|
||||||
export const DAO_TREASURY_ADDRESSES = {
|
export const DAO_TREASURY_ADDRESSES = {
|
||||||
[NetworkId.TESTNET_SEPOLIA]: "0x93dd30f819403710de7933B79A74C4A42438458D",
|
[NetworkId.TESTNET_SEPOLIA]: "0x93dd30f819403710de7933B79A74C4A42438458D",
|
||||||
[NetworkId.TESTNET_HOODI]: "0x1a1b29b18f714fac9dDabEf530dFc4f85b56A6e8",
|
[NetworkId.TESTNET_HOODI]: "0x1a1b29b18f714fac9dDabEf530dFc4f85b56A6e8",
|
||||||
|
[NetworkId.TESTNET_MORDOR]: "0x5883C8e2259556B534036c7fDF4555E09dE9f243",
|
||||||
};
|
};
|
||||||
|
|
||||||
export const FTSO_DAI_LP_ADDRESSES = {
|
export const FTSO_DAI_LP_ADDRESSES = {
|
||||||
[NetworkId.TESTNET_SEPOLIA]: "0x1394dC3f7bABaa2F0CA80353648087DAB1BF3fd6",
|
[NetworkId.TESTNET_SEPOLIA]: "0x1394dC3f7bABaa2F0CA80353648087DAB1BF3fd6",
|
||||||
[NetworkId.TESTNET_HOODI]: "0xf7B2d44209E70782d93A70F7D8eC50010dF7ae50",
|
[NetworkId.TESTNET_HOODI]: "0xf7B2d44209E70782d93A70F7D8eC50010dF7ae50",
|
||||||
|
[NetworkId.TESTNET_MORDOR]: "0xE6546D12665dB5B22Cb92FB9e0221aE51A57aeaa",
|
||||||
};
|
};
|
||||||
|
|
||||||
export const FTSO_STNK_LP_ADDRESSES = {
|
export const FTSO_STNK_LP_ADDRESSES = {
|
||||||
[NetworkId.TESTNET_SEPOLIA]: "0x0000000000000000000000000000000000000000", // TBD
|
[NetworkId.TESTNET_SEPOLIA]: "0x0000000000000000000000000000000000000000", // TBD
|
||||||
[NetworkId.TESTNET_SEPOLIA]: "0x0000000000000000000000000000000000000000",
|
[NetworkId.TESTNET_SEPOLIA]: "0x0000000000000000000000000000000000000000",
|
||||||
|
[NetworkId.TESTNET_MORDOR]: "0x0000000000000000000000000000000000000000",
|
||||||
}
|
}
|
||||||
|
|
||||||
export const DAI_ADDRESSES = {
|
export const DAI_ADDRESSES = {
|
||||||
[NetworkId.TESTNET_SEPOLIA]: "0x5f63a27a9214a0352F2EF8dAF1eD4974d713192B",
|
[NetworkId.TESTNET_SEPOLIA]: "0x5f63a27a9214a0352F2EF8dAF1eD4974d713192B",
|
||||||
[NetworkId.TESTNET_HOODI]: "0x80c6676c334BCcE60b3CC852085B72143379CE58",
|
[NetworkId.TESTNET_HOODI]: "0x80c6676c334BCcE60b3CC852085B72143379CE58",
|
||||||
|
[NetworkId.TESTNET_MORDOR]: "0x6af91B3763b5d020E0985f85555EB50e5852d7AC",
|
||||||
};
|
};
|
||||||
|
|
||||||
export const WETH_ADDRESSES = {
|
export const WETH_ADDRESSES = {
|
||||||
[NetworkId.TESTNET_SEPOLIA]: "0xfff9976782d46cc05630d1f6ebab18b2324d6b14",
|
[NetworkId.TESTNET_SEPOLIA]: "0xfff9976782d46cc05630d1f6ebab18b2324d6b14",
|
||||||
[NetworkId.TESTNET_HOODI]: "0xE69a5c6dd88cA798b93c3C92fc50c51Fd5305eB4",
|
[NetworkId.TESTNET_HOODI]: "0xE69a5c6dd88cA798b93c3C92fc50c51Fd5305eB4",
|
||||||
|
[NetworkId.TESTNET_MORDOR]: "0x6af91B3763b5d020E0985f85555EB50e5852d7AC",
|
||||||
};
|
};
|
||||||
|
|
||||||
export const GHST_ADDRESSES = {
|
export const GHST_ADDRESSES = {
|
||||||
[NetworkId.TESTNET_SEPOLIA]: "0xdf2e5306A3dCcfA4e21bbF4226C17Ff5B008dDC4",
|
[NetworkId.TESTNET_SEPOLIA]: "0xdf2e5306A3dCcfA4e21bbF4226C17Ff5B008dDC4",
|
||||||
[NetworkId.TESTNET_HOODI]: "0xE98f7426457E6533B206e91B7EcA97aa8A258B46",
|
[NetworkId.TESTNET_HOODI]: "0xE98f7426457E6533B206e91B7EcA97aa8A258B46",
|
||||||
|
[NetworkId.TESTNET_MORDOR]: "0x14b5787F8a1E62786F50A7998A9b14aa24298423",
|
||||||
};
|
};
|
||||||
|
|
||||||
export const STNK_ADDRESSES = {
|
export const STNK_ADDRESSES = {
|
||||||
[NetworkId.TESTNET_SEPOLIA]: "0x02C296A27eA779d5a16F934337c12062C5E3c0D9",
|
[NetworkId.TESTNET_SEPOLIA]: "0x02C296A27eA779d5a16F934337c12062C5E3c0D9",
|
||||||
[NetworkId.TESTNET_HOODI]: "0xF07e9303A9f16Afd82f4f57Fd6fca68Aa0AB6D7F",
|
[NetworkId.TESTNET_HOODI]: "0xF07e9303A9f16Afd82f4f57Fd6fca68Aa0AB6D7F",
|
||||||
|
[NetworkId.TESTNET_MORDOR]: "0x137bA9403885D8ECEa95AaFBb8734F5a16121bAC",
|
||||||
};
|
};
|
||||||
|
|
||||||
export const FTSO_ADDRESSES = {
|
export const FTSO_ADDRESSES = {
|
||||||
[NetworkId.TESTNET_SEPOLIA]: "0xcFedFFEB3FdeCd2196820Ba3b71f3F84A1255f93",
|
[NetworkId.TESTNET_SEPOLIA]: "0xcFedFFEB3FdeCd2196820Ba3b71f3F84A1255f93",
|
||||||
[NetworkId.TESTNET_HOODI]: "0xb184e423811b644A1924334E63985c259F5D0033",
|
[NetworkId.TESTNET_HOODI]: "0xb184e423811b644A1924334E63985c259F5D0033",
|
||||||
|
[NetworkId.TESTNET_MORDOR]: "0xeA170CC0faceC531a6a9e93a28C4330Ac50343a1",
|
||||||
};
|
};
|
||||||
|
|
||||||
export const DISTRIBUTOR_ADDRESSES = {
|
export const DISTRIBUTOR_ADDRESSES = {
|
||||||
[NetworkId.TESTNET_SEPOLIA]: "0x8fbF8eB4Fcd451EF62Aee33508D46FE120963194",
|
[NetworkId.TESTNET_SEPOLIA]: "0x8fbF8eB4Fcd451EF62Aee33508D46FE120963194",
|
||||||
[NetworkId.TESTNET_HOODI]: "0xdF49dC81c457c6f92e26cf6d686C7a8715255842",
|
[NetworkId.TESTNET_HOODI]: "0xdF49dC81c457c6f92e26cf6d686C7a8715255842",
|
||||||
|
[NetworkId.TESTNET_MORDOR]: "0xaf5e76706520db7fb01096E322940206bf3fce57",
|
||||||
};
|
};
|
||||||
|
|
||||||
export const GHOST_GOVERNANCE_ADDRESSES = {
|
export const GHOST_GOVERNANCE_ADDRESSES = {
|
||||||
[NetworkId.TESTNET_SEPOLIA]: "0xDab0c51918E6990d8763FAC8a04AE159e44e0c4f",
|
[NetworkId.TESTNET_SEPOLIA]: "0xDab0c51918E6990d8763FAC8a04AE159e44e0c4f",
|
||||||
[NetworkId.TESTNET_HOODI]: "0x1B96B792840d4d19d5097ee007392Ed4d851e64F",
|
[NetworkId.TESTNET_HOODI]: "0x1B96B792840d4d19d5097ee007392Ed4d851e64F",
|
||||||
|
[NetworkId.TESTNET_MORDOR]: "0x3dD438416D9593A58193fC52850E588efAa3D57E",
|
||||||
};
|
};
|
||||||
|
|
||||||
export const BONDING_CALCULATOR_ADDRESSES = {
|
export const BONDING_CALCULATOR_ADDRESSES = {
|
||||||
[NetworkId.TESTNET_SEPOLIA]: "0x4896bFc6256A57Df826d7144E48c9633d51d6319",
|
[NetworkId.TESTNET_SEPOLIA]: "0x4896bFc6256A57Df826d7144E48c9633d51d6319",
|
||||||
[NetworkId.TESTNET_HOODI]: "0x2635d526Ad24b98082563937f7b996075052c6Fd",
|
[NetworkId.TESTNET_HOODI]: "0x2635d526Ad24b98082563937f7b996075052c6Fd",
|
||||||
|
[NetworkId.TESTNET_MORDOR]: "0x0c4C7C49a173E2a3f9Eed93125F3F146D8e17bCb",
|
||||||
}
|
}
|
||||||
|
|
||||||
export const GATEKEEPER_ADDRESSES = {
|
export const GATEKEEPER_ADDRESSES = {
|
||||||
[NetworkId.TESTNET_SEPOLIA]: "0xc85129A097773B7F8970a7364c928C05f265E6A1",
|
[NetworkId.TESTNET_SEPOLIA]: "0xc85129A097773B7F8970a7364c928C05f265E6A1",
|
||||||
|
[NetworkId.TESTNET_MORDOR]: "0xA59cB4ff90bE2206121aE61eEB68d0AeC7BA095f",
|
||||||
}
|
}
|
||||||
|
|
||||||
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",
|
||||||
|
[NetworkId.TESTNET_MORDOR]: "0x90ecf6a29798E3cf31EB7DCE64a372AC40d83F83",
|
||||||
};
|
};
|
||||||
|
|
||||||
export const UNISWAP_V2_FACTORY = {
|
export const UNISWAP_V2_FACTORY = {
|
||||||
[NetworkId.TESTNET_SEPOLIA]: "0xF62c03E08ada871A0bEb309762E260a7a6a880E6",
|
[NetworkId.TESTNET_SEPOLIA]: "0xF62c03E08ada871A0bEb309762E260a7a6a880E6",
|
||||||
[NetworkId.TESTNET_HOODI]: "0xF140342cB5C29C1468d91Aee408d7b7271C48b5A",
|
[NetworkId.TESTNET_HOODI]: "0xF140342cB5C29C1468d91Aee408d7b7271C48b5A",
|
||||||
|
[NetworkId.TESTNET_MORDOR]: "0x909f96C1a436B3386E9962e30f3Ce753070ff524",
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const CEX_TICKERS = {
|
||||||
|
[NetworkId.TESTNET_MORDOR]: "ETCUSDT",
|
||||||
|
}
|
||||||
|
|||||||
@ -18,4 +18,11 @@ export const AVAILABLE_DEXES = {
|
|||||||
viewBox: "0 0 195 230",
|
viewBox: "0 0 195 230",
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
[NetworkId.TESTNET_MORDOR]: [
|
||||||
|
{
|
||||||
|
name: "Uniswap",
|
||||||
|
icon: UniswapIcon,
|
||||||
|
viewBox: "0 0 195 230",
|
||||||
|
},
|
||||||
|
],
|
||||||
};
|
};
|
||||||
|
|||||||
@ -19,6 +19,7 @@ import TokenStack from "../../components/TokenStack/TokenStack";
|
|||||||
import { DecimalBigNumber } from "../../helpers/DecimalBigNumber";
|
import { DecimalBigNumber } from "../../helpers/DecimalBigNumber";
|
||||||
import { formatNumber } from "../../helpers/";
|
import { formatNumber } from "../../helpers/";
|
||||||
import { useBalance, useTokenSymbol } from "../../hooks/tokens";
|
import { useBalance, useTokenSymbol } from "../../hooks/tokens";
|
||||||
|
import { isNetworkLegacy } from "../../constants";
|
||||||
import { DAI_ADDRESSES, FTSO_ADDRESSES, STNK_ADDRESSES, GHST_ADDRESSES } from "../../constants/addresses";
|
import { DAI_ADDRESSES, FTSO_ADDRESSES, STNK_ADDRESSES, GHST_ADDRESSES } from "../../constants/addresses";
|
||||||
|
|
||||||
const TokenModal = ({ chainId, account, listOpen, setListOpen, setTokenAddress }) => {
|
const TokenModal = ({ chainId, account, listOpen, setListOpen, setTokenAddress }) => {
|
||||||
@ -60,7 +61,7 @@ const TokenModal = ({ chainId, account, listOpen, setListOpen, setTokenAddress }
|
|||||||
return [
|
return [
|
||||||
{
|
{
|
||||||
name: daiSymbol,
|
name: daiSymbol,
|
||||||
icons: ["GDAI"],
|
icons: isNetworkLegacy(chainId) ? ["GDAI"] : ["WETH"],
|
||||||
balance: daiBalance,
|
balance: daiBalance,
|
||||||
address: DAI_ADDRESSES[chainId]
|
address: DAI_ADDRESSES[chainId]
|
||||||
},
|
},
|
||||||
|
|||||||
@ -6,6 +6,7 @@ import Token from "../../../components/Token/Token";
|
|||||||
import { SecondaryButton } from "../../../components/Button";
|
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 { isNetworkLegacy } from "../../../constants"
|
||||||
|
|
||||||
import { useBalance, useTokenSymbol } from "../../../hooks/tokens";
|
import { useBalance, useTokenSymbol } from "../../../hooks/tokens";
|
||||||
import {
|
import {
|
||||||
@ -133,7 +134,7 @@ const TokenInfo = ({ chainId, isMobileScreen }) => {
|
|||||||
/>
|
/>
|
||||||
<TokenTab
|
<TokenTab
|
||||||
isMobileScreen={isMobileScreen}
|
isMobileScreen={isMobileScreen}
|
||||||
tokenUrl="/faucet"
|
tokenUrl={isNetworkLegacy(chainId) ? "/faucet" : "/wrapper"}
|
||||||
tokenUrlParams=""
|
tokenUrlParams=""
|
||||||
theme={theme}
|
theme={theme}
|
||||||
tokenName={daiSymbol}
|
tokenName={daiSymbol}
|
||||||
|
|||||||
260
src/containers/WethWrapper/WethWrapper.jsx
Normal file
260
src/containers/WethWrapper/WethWrapper.jsx
Normal file
@ -0,0 +1,260 @@
|
|||||||
|
import { useState, useEffect, useMemo } from "react";
|
||||||
|
import { Box, Container, Typography, useMediaQuery } from "@mui/material";
|
||||||
|
import { useConfig, useBalance } from "wagmi";
|
||||||
|
import { Helmet } from "react-helmet";
|
||||||
|
import ReactGA from "react-ga4";
|
||||||
|
|
||||||
|
import PageTitle from "../../components/PageTitle/PageTitle";
|
||||||
|
import Paper from "../../components/Paper/Paper";
|
||||||
|
import SwapCard from "../../components/Swap/SwapCard";
|
||||||
|
import TokenStack from "../../components/TokenStack/TokenStack";
|
||||||
|
import { PrimaryButton } from "../../components/Button";
|
||||||
|
import { Tab, Tabs } from "../../components/Tabs/Tabs";
|
||||||
|
|
||||||
|
import { DAI_ADDRESSES } from "../../constants/addresses";
|
||||||
|
import { DecimalBigNumber } from "../../helpers/DecimalBigNumber";
|
||||||
|
import { formatCurrency, formatNumber } from "../../helpers";
|
||||||
|
|
||||||
|
import {
|
||||||
|
useBalance as useTokenBalance,
|
||||||
|
useTokenSymbol,
|
||||||
|
useTotalSupply,
|
||||||
|
useConversionRate,
|
||||||
|
useAccumulatedDonation,
|
||||||
|
depositNative,
|
||||||
|
withdrawWeth
|
||||||
|
} from "../../hooks/tokens";
|
||||||
|
|
||||||
|
const WethWrapper = ({ chainId, address, config, connect }) => {
|
||||||
|
const isSmallScreen = useMediaQuery("(max-width: 650px)");
|
||||||
|
const isSemiSmallScreen = useMediaQuery("(max-width: 480px)");
|
||||||
|
const isVerySmallScreen = useMediaQuery("(max-width: 379px)");
|
||||||
|
|
||||||
|
const [chainName, setChainName] = useState("");
|
||||||
|
const [isMint, setIsMint] = useState(true);
|
||||||
|
const [isPending, setIsPending] = useState(false);
|
||||||
|
const [balance, setBalance] = useState(new DecimalBigNumber(0, 0));
|
||||||
|
const [amount, setAmount] = useState("");
|
||||||
|
const [scanInfo, setScanInfo] = useState({
|
||||||
|
name: "",
|
||||||
|
url: "",
|
||||||
|
});
|
||||||
|
const [nativeInfo, setNativeInfo] = useState({
|
||||||
|
decimals: 18,
|
||||||
|
name: "",
|
||||||
|
symbol: "",
|
||||||
|
})
|
||||||
|
|
||||||
|
const { balance: daiBalance, refetch: daiBalanceRefetch } = useTokenBalance(chainId, "GDAI", address);
|
||||||
|
const { data: nativeBalance, refetch: balanceRefetch } = useBalance({ address });
|
||||||
|
const { symbol: faucetSymbol } = useTokenSymbol(chainId, "GDAI");
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
ReactGA.send({ hitType: "pageview", page: "/faucet" });
|
||||||
|
}, [])
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const value = nativeBalance ? nativeBalance.value : 0n;
|
||||||
|
const decimals = nativeBalance ? nativeBalance.decimals : 18;
|
||||||
|
setBalance(new DecimalBigNumber(value, decimals));
|
||||||
|
}, [nativeBalance]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
let scanName = "";
|
||||||
|
let scanUrl = "";
|
||||||
|
|
||||||
|
const client = config?.getClient();
|
||||||
|
scanName = client?.chain?.blockExplorers?.default?.name;
|
||||||
|
scanUrl = client?.chain?.blockExplorers?.default?.url;
|
||||||
|
|
||||||
|
setScanInfo({
|
||||||
|
name: scanName,
|
||||||
|
url: scanUrl,
|
||||||
|
})
|
||||||
|
|
||||||
|
setChainName(client?.chain?.name);
|
||||||
|
|
||||||
|
setNativeInfo(client?.chain?.nativeCurrency)
|
||||||
|
}, [chainId]);
|
||||||
|
|
||||||
|
const changeIsMinted = (value) => {
|
||||||
|
setAmount("");
|
||||||
|
setIsMint(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
const preparedAmount = useMemo(() => {
|
||||||
|
if (address === "") new DecimalBigNumber("0", 0);
|
||||||
|
const decimals = isMint ? nativeInfo.decimals : 18;
|
||||||
|
return new DecimalBigNumber(amount, decimals);
|
||||||
|
}, [amount, balance, nativeInfo])
|
||||||
|
|
||||||
|
const estimatedAmountIn = useMemo(() => {
|
||||||
|
return new DecimalBigNumber(amount, nativeInfo.decimals);
|
||||||
|
}, [amount, nativeInfo]);
|
||||||
|
|
||||||
|
const estimatedAmountOut = useMemo(() => {
|
||||||
|
return new DecimalBigNumber(amount, nativeInfo.decimals);
|
||||||
|
}, [amount, nativeInfo]);
|
||||||
|
|
||||||
|
const actionOrConnect = async () => {
|
||||||
|
if (address === "") {
|
||||||
|
connect();
|
||||||
|
} else {
|
||||||
|
setIsPending(true);
|
||||||
|
|
||||||
|
if (isMint) {
|
||||||
|
await depositNative(chainId, address, preparedAmount._value.toString());
|
||||||
|
} else {
|
||||||
|
await withdrawWeth(chainId, address, preparedAmount._value.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
await balanceRefetch();
|
||||||
|
await daiBalanceRefetch();
|
||||||
|
setAmount("");
|
||||||
|
setIsPending(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Box height="calc(100vh - 43px)">
|
||||||
|
<Helmet>
|
||||||
|
<title>ghostWrapper | WETH9</title>
|
||||||
|
<meta name="description" content="Standard WETH9 wrapper. Convert native coin to WETH9 representation directly to your wallet." />
|
||||||
|
<meta name="keywords" content="weth, weth9, ghostFaucet, web3 faucet, ethereum, sepolia, polygon, bnb, bsc, AVAX" />
|
||||||
|
|
||||||
|
<meta property="og:image" content="https://ghostchain.io/wp-content/uploads/2025/03/ghostFaucet-Featured_Image.png" />
|
||||||
|
<meta property="og:title" content="ghostDAO | The DeFi 2.0 cross-chain reserve currency" />
|
||||||
|
<meta property="og:image:type" content="image/png" />
|
||||||
|
<meta property="og:image:width" content="1200" />
|
||||||
|
<meta property="og:image:height" content="630" />
|
||||||
|
<meta property="og:type" content="website" />
|
||||||
|
<meta property="og:description" content="Standard WETH9 wrapper. Convert native coin to WETH9 representation directly to your wallet." />
|
||||||
|
|
||||||
|
<meta name="twitter:card" content="summary" />
|
||||||
|
<meta name="twitter:site" content="@realGhostChain" />
|
||||||
|
<meta name="twitter:title" content="ghostDAO | The DeFi 2.0 cross-chain reserve currency" />
|
||||||
|
<meta name="twitter:description" content="Standard WETH9 wrapper. Convert native coin to WETH9 representation directly to your wallet." />
|
||||||
|
<meta name="twitter:image" content="https://ghostchain.io/wp-content/uploads/2025/03/ghostFaucet-Featured_Image.png" />
|
||||||
|
</Helmet>
|
||||||
|
|
||||||
|
<PageTitle name={`${faucetSymbol} Faucet`} subtitle={`Swap ${chainName} ${nativeInfo.symbol} for ${faucetSymbol}.`} />
|
||||||
|
<Container
|
||||||
|
style={{
|
||||||
|
paddingLeft: isSmallScreen || isVerySmallScreen ? "0" : "3.3rem",
|
||||||
|
paddingRight: isSmallScreen || isVerySmallScreen ? "0" : "3.3rem",
|
||||||
|
display: "flex",
|
||||||
|
justifyContent: "center",
|
||||||
|
alignItems: "center",
|
||||||
|
height: "calc(100vh - 153px)"
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<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%">
|
||||||
|
<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" }} />
|
||||||
|
<Tab aria-label="faucet-burn-button" label="Burn" style={{ fontSize: "1.5rem" }} />
|
||||||
|
</Tabs>
|
||||||
|
{!isSemiSmallScreen && <PrimaryButton
|
||||||
|
variant="text"
|
||||||
|
href={`${scanInfo.url}/token/${DAI_ADDRESSES[chainId]}`}
|
||||||
|
>
|
||||||
|
Check on {scanInfo.name}
|
||||||
|
</PrimaryButton>}
|
||||||
|
</Box>
|
||||||
|
}
|
||||||
|
enableBackground
|
||||||
|
fullWidth
|
||||||
|
>
|
||||||
|
<Box>
|
||||||
|
{isMint && <SwapCard
|
||||||
|
id={`faucet-sepolia-eth`}
|
||||||
|
inputWidth={isVerySmallScreen ? "100px" : isSemiSmallScreen ? "180px" : "250px"}
|
||||||
|
tokenName={nativeInfo.symbol}
|
||||||
|
token={<TokenStack tokens={[nativeInfo.symbol]} sx={{ fontSize: "21px" }} />}
|
||||||
|
info={`${isSemiSmallScreen ? "" : "Balance: "}${formatCurrency(balance.toString(), 4, nativeInfo.symbol)}`}
|
||||||
|
value={amount}
|
||||||
|
onChange={event => setAmount(event.currentTarget.value)}
|
||||||
|
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
|
||||||
|
mb="20px"
|
||||||
|
mt="20px"
|
||||||
|
flexDirection="column"
|
||||||
|
display="flex"
|
||||||
|
justifyContent="space-between"
|
||||||
|
>
|
||||||
|
{isMint && (
|
||||||
|
<>
|
||||||
|
<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(estimatedAmountIn, 5, faucetSymbol)}</Typography>
|
||||||
|
</Box>
|
||||||
|
<Box display="flex" justifyContent={isVerySmallScreen ? "end" : "space-between"}>
|
||||||
|
{!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">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>
|
||||||
|
<PrimaryButton
|
||||||
|
fullWidth
|
||||||
|
disabled={
|
||||||
|
address !== "" && (
|
||||||
|
preparedAmount?._value === 0n ||
|
||||||
|
isPending ||
|
||||||
|
(isMint && balance?.lt(preparedAmount)) ||
|
||||||
|
(!isMint && daiBalance?.lt(preparedAmount))
|
||||||
|
)
|
||||||
|
}
|
||||||
|
loading={isPending}
|
||||||
|
onClick={() => actionOrConnect()}
|
||||||
|
>
|
||||||
|
{address === "" ?
|
||||||
|
"Connect"
|
||||||
|
:
|
||||||
|
isMint ? "Mint" : "Burn"
|
||||||
|
}
|
||||||
|
</PrimaryButton>
|
||||||
|
</Box>
|
||||||
|
</Paper>
|
||||||
|
</Box>
|
||||||
|
</Container>
|
||||||
|
</Box>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default WethWrapper;
|
||||||
@ -4,6 +4,7 @@ import {
|
|||||||
STNK_ADDRESSES,
|
STNK_ADDRESSES,
|
||||||
GHST_ADDRESSES,
|
GHST_ADDRESSES,
|
||||||
FTSO_DAI_LP_ADDRESSES,
|
FTSO_DAI_LP_ADDRESSES,
|
||||||
|
WETH_ADDRESSES,
|
||||||
} from "../constants/addresses";
|
} from "../constants/addresses";
|
||||||
|
|
||||||
import { abi as DaiAbi } from "../abi/Reserve.json";
|
import { abi as DaiAbi } from "../abi/Reserve.json";
|
||||||
@ -11,6 +12,7 @@ import { abi as FatsoAbi } from "../abi/Fatso.json";
|
|||||||
import { abi as StinkyAbi } from "../abi/Stinky.json";
|
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";
|
||||||
|
import { abi as WethAbi } from "../abi/WETH9.json";
|
||||||
|
|
||||||
// TBD: should be extended on new tokens
|
// TBD: should be extended on new tokens
|
||||||
export const getTokenAbi = (name) => {
|
export const getTokenAbi = (name) => {
|
||||||
@ -40,6 +42,9 @@ export const getTokenAbi = (name) => {
|
|||||||
case "CSPR":
|
case "CSPR":
|
||||||
abi = GhostAbi;
|
abi = GhostAbi;
|
||||||
break;
|
break;
|
||||||
|
case "WETH":
|
||||||
|
abi = WethAbi;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
return abi;
|
return abi;
|
||||||
}
|
}
|
||||||
@ -72,6 +77,9 @@ export const getTokenDecimals = (name) => {
|
|||||||
case "CSPR":
|
case "CSPR":
|
||||||
decimals = 18;
|
decimals = 18;
|
||||||
break;
|
break;
|
||||||
|
case "WETH":
|
||||||
|
decimals = 18;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
return decimals;
|
return decimals;
|
||||||
}
|
}
|
||||||
@ -107,6 +115,9 @@ export const getTokenAddress = (chainId, name) => {
|
|||||||
case "GDAI_FTSO":
|
case "GDAI_FTSO":
|
||||||
address = FTSO_DAI_LP_ADDRESSES[chainId];
|
address = FTSO_DAI_LP_ADDRESSES[chainId];
|
||||||
break;
|
break;
|
||||||
|
case "WETH":
|
||||||
|
address = WETH_ADDRESSES[chainId];
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
return address;
|
return address;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,12 +1,79 @@
|
|||||||
|
import { useState, useEffect } from "react";
|
||||||
import { useReadContract } from "wagmi";
|
import { useReadContract } from "wagmi";
|
||||||
|
|
||||||
import { useCurrentIndex, useGhostedSupply } 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,
|
||||||
|
CEX_TICKERS
|
||||||
|
} from "../../constants/addresses";
|
||||||
|
|
||||||
|
const cexPriceGetters = new Map();
|
||||||
|
|
||||||
|
function callWithCacheTTL(fn, ttlMs = 5000) {
|
||||||
|
let lastFetchTime = 0;
|
||||||
|
let cachedValue;
|
||||||
|
let inFlight = null;
|
||||||
|
|
||||||
|
return function(...args) {
|
||||||
|
const now = Date.now();
|
||||||
|
|
||||||
|
if ((now - lastFetchTime) < ttlMs) {
|
||||||
|
return inFlight ? inFlight : Promise.resolve(cachedValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
lastFetchTime = now;
|
||||||
|
inFlight = Promise.resolve(fn(...args))
|
||||||
|
.then(res => {
|
||||||
|
cachedValue = res;
|
||||||
|
inFlight = null;
|
||||||
|
return res;
|
||||||
|
})
|
||||||
|
.catch(err => {
|
||||||
|
inFlight = null;
|
||||||
|
throw err;
|
||||||
|
});
|
||||||
|
|
||||||
|
return inFlight;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
export const useDaiPrice = (chainId) => {
|
export const useDaiPrice = (chainId) => {
|
||||||
const daiPrice = new DecimalBigNumber(1000000000000000000n, 18);
|
const [daiPrice, setDaiPrice] = useState(new DecimalBigNumber(1000000000000000000n, 18));
|
||||||
|
const cexTicker = CEX_TICKERS[chainId];
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (!cexTicker) {
|
||||||
|
setDaiPrice(new DecimalBigNumber(1000000000000000000n, 18));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let getCexPriceCached = cexPriceGetters.get(chainId);
|
||||||
|
if (!getCexPriceCached) {
|
||||||
|
getCexPriceCached = callWithCacheTTL(() => {
|
||||||
|
return fetch(`https://api.binance.com/api/v3/ticker/price?symbol=${cexTicker}`)
|
||||||
|
.then(res => {
|
||||||
|
if (!res.ok) throw new Error(`HTTP ${res.status}`);
|
||||||
|
return res.json();
|
||||||
|
});
|
||||||
|
}, 5000);
|
||||||
|
cexPriceGetters.set(chainId, getCexPriceCached);
|
||||||
|
}
|
||||||
|
|
||||||
|
getCexPriceCached()
|
||||||
|
.then(price => {
|
||||||
|
const coinPrice = Number(price?.price ?? 0.0);
|
||||||
|
const priceInWei = Math.floor(coinPrice * 1e18)
|
||||||
|
setDaiPrice(new DecimalBigNumber(BigInt(priceInWei), 18));
|
||||||
|
})
|
||||||
|
.catch(error => {
|
||||||
|
setDaiPrice(new DecimalBigNumber(0n, 18));
|
||||||
|
});
|
||||||
|
}, [chainId, cexTicker])
|
||||||
|
|
||||||
return daiPrice;
|
return daiPrice;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -20,6 +87,7 @@ export const useFtsoPrice = (chainId) => {
|
|||||||
"GDAI",
|
"GDAI",
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const reservePrice = useDaiPrice(chainId);
|
||||||
const reserveAddress = DAI_ADDRESSES[chainId];
|
const reserveAddress = DAI_ADDRESSES[chainId];
|
||||||
const ftsoAddress = FTSO_ADDRESSES[chainId];
|
const ftsoAddress = FTSO_ADDRESSES[chainId];
|
||||||
if (!reserveAddress || !ftsoAddress) {
|
if (!reserveAddress || !ftsoAddress) {
|
||||||
@ -37,8 +105,9 @@ export const useFtsoPrice = (chainId) => {
|
|||||||
let price = 0n
|
let price = 0n
|
||||||
if (ftsoReserves > 0n)
|
if (ftsoReserves > 0n)
|
||||||
price = stableReserves / ftsoReserves;
|
price = stableReserves / ftsoReserves;
|
||||||
|
price = price * reservePrice._value;
|
||||||
|
|
||||||
return new DecimalBigNumber(price, 9);
|
return new DecimalBigNumber(price, 27);
|
||||||
};
|
};
|
||||||
|
|
||||||
export const useStnkPrice = (chainId) => {
|
export const useStnkPrice = (chainId) => {
|
||||||
|
|||||||
@ -229,3 +229,53 @@ export const burnDai = async (chainId, account, value) => {
|
|||||||
toast.error("Burning gDAI from the faucet failed. Check logs for error detalization.")
|
toast.error("Burning gDAI from the faucet failed. Check logs for error detalization.")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const depositNative = async (chainId, account, value) => {
|
||||||
|
try {
|
||||||
|
const { request } = await simulateContract(config, {
|
||||||
|
abi: getTokenAbi("WETH"),
|
||||||
|
address: getTokenAddress(chainId, "WETH"),
|
||||||
|
functionName: 'deposit',
|
||||||
|
account: account,
|
||||||
|
chainId: chainId,
|
||||||
|
value: value
|
||||||
|
});
|
||||||
|
|
||||||
|
const txHash = await writeContract(config, request);
|
||||||
|
await waitForTransactionReceipt(config, {
|
||||||
|
hash: txHash,
|
||||||
|
onReplaced: () => toast("WETH9 deposit transaction was replaced. Wait for inclusion please."),
|
||||||
|
chainId
|
||||||
|
});
|
||||||
|
|
||||||
|
toast.success("WETH9 successfully minted to your wallet! Check your wallet balance.");
|
||||||
|
} catch (err) {
|
||||||
|
console.error(err);
|
||||||
|
toast.error("WETH9 wrapping failed. Check logs for error detalization.")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export const withdrawWeth = async (chainId, account, value) => {
|
||||||
|
try {
|
||||||
|
const { request } = await simulateContract(config, {
|
||||||
|
abi: getTokenAbi("WETH"),
|
||||||
|
address: getTokenAddress(chainId, "WETH"),
|
||||||
|
functionName: 'withdraw',
|
||||||
|
args: [value],
|
||||||
|
account: account,
|
||||||
|
chainId: chainId
|
||||||
|
});
|
||||||
|
|
||||||
|
const txHash = await writeContract(config, request);
|
||||||
|
await waitForTransactionReceipt(config, {
|
||||||
|
hash: txHash,
|
||||||
|
onReplaced: () => toast("WETH9 withdraw transaction was replaced. Wait for inclusion please."),
|
||||||
|
chainId
|
||||||
|
});
|
||||||
|
|
||||||
|
toast.success("WETH9 successfully burned for native coins! Check your wallet balance.");
|
||||||
|
} catch (err) {
|
||||||
|
console.error(err);
|
||||||
|
toast.error("WETH9 unwrapping failed. Check logs for error detalization.")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@ -3,9 +3,23 @@ import { useReadContract } from "wagmi";
|
|||||||
import { DAO_TREASURY_ADDRESSES } from "../../constants/addresses";
|
import { DAO_TREASURY_ADDRESSES } from "../../constants/addresses";
|
||||||
import { abi as TreasuryAbi } from "../../abi/GhostTreasury.json";
|
import { abi as TreasuryAbi } from "../../abi/GhostTreasury.json";
|
||||||
|
|
||||||
|
import { useDaiPrice } from "../prices/index";
|
||||||
|
|
||||||
import { DecimalBigNumber } from "../../helpers/DecimalBigNumber";
|
import { DecimalBigNumber } from "../../helpers/DecimalBigNumber";
|
||||||
import { getTokenAddress } from "../helpers";
|
import { getTokenAddress } from "../helpers";
|
||||||
|
|
||||||
|
export const useOrinalCoefficient = (chainId) => {
|
||||||
|
const { data: original } = useReadContract({
|
||||||
|
abi: TreasuryAbi,
|
||||||
|
address: DAO_TREASURY_ADDRESSES[chainId],
|
||||||
|
functionName: "originalCoefficient",
|
||||||
|
scopeKey: `originalCoefficient-${chainId}`,
|
||||||
|
chainId: chainId
|
||||||
|
});
|
||||||
|
|
||||||
|
return new DecimalBigNumber(original ? original : 1000000000000000000n, 18);
|
||||||
|
}
|
||||||
|
|
||||||
export const useTotalReserves = (chainId) => {
|
export const useTotalReserves = (chainId) => {
|
||||||
const { data: totalReservesRaw } = useReadContract({
|
const { data: totalReservesRaw } = useReadContract({
|
||||||
abi: TreasuryAbi,
|
abi: TreasuryAbi,
|
||||||
@ -15,10 +29,13 @@ export const useTotalReserves = (chainId) => {
|
|||||||
chainId: chainId,
|
chainId: chainId,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const original = useOrinalCoefficient(chainId);
|
||||||
|
const price = useDaiPrice(chainId);
|
||||||
|
|
||||||
const totalReservesPrepared = totalReservesRaw ? totalReservesRaw : 0n;
|
const totalReservesPrepared = totalReservesRaw ? totalReservesRaw : 0n;
|
||||||
const totalReserves = new DecimalBigNumber(totalReservesPrepared, 9);
|
const totalReserves = new DecimalBigNumber(totalReservesPrepared, 9);
|
||||||
|
|
||||||
return totalReserves;
|
return totalReserves.mul(price).div(original);
|
||||||
};
|
};
|
||||||
|
|
||||||
export const useLpValuation = (chainId, pairAddress, pairSupply) => {
|
export const useLpValuation = (chainId, pairAddress, pairSupply) => {
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user