From 494df5f1398517d9af9b3f7d0a786b44c5f0cf86 Mon Sep 17 00:00:00 2001 From: Uncle Fatso Date: Wed, 29 Oct 2025 14:29:14 +0300 Subject: [PATCH] support for native reserve added; e.g. mordor testnet Signed-off-by: Uncle Fatso --- package.json | 2 +- src/App.jsx | 8 +- src/abi/GhostTreasury.json | 2 +- src/abi/WETH9.json | 1 + src/components/Sidebar/NavContent.jsx | 8 +- src/components/Token/Token.jsx | 3 + src/config.js | 25 +- src/constants.ts | 19 ++ src/constants/addresses.js | 20 ++ src/constants/dexes.js | 7 + src/containers/Dex/TokenModal.jsx | 3 +- .../components/TokenInfo.jsx | 3 +- src/containers/WethWrapper/WethWrapper.jsx | 260 ++++++++++++++++++ src/hooks/helpers.js | 11 + src/hooks/prices/index.js | 75 ++++- src/hooks/tokens/index.js | 50 ++++ src/hooks/treasury/index.js | 19 +- 17 files changed, 503 insertions(+), 13 deletions(-) create mode 100644 src/abi/WETH9.json create mode 100644 src/containers/WethWrapper/WethWrapper.jsx diff --git a/package.json b/package.json index b195eb0..00b438e 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "ghost-dao-interface", "private": true, - "version": "0.2.16", + "version": "0.3.0", "type": "module", "scripts": { "dev": "vite", diff --git a/src/App.jsx b/src/App.jsx index c199696..3363c68 100644 --- a/src/App.jsx +++ b/src/App.jsx @@ -14,7 +14,7 @@ import Sidebar from "./components/Sidebar/Sidebar"; import TopBar from "./components/TopBar/TopBar"; import { shouldTriggerSafetyCheck } from "./helpers"; -import { isNetworkAvailable } from "./constants"; +import { isNetworkAvailable, isNetworkLegacy } from "./constants"; import useTheme from "./hooks/useTheme"; import { useUnstableProvider } from "./hooks/ghost"; 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 TreasuryDashboard = lazy(() => import("./containers/TreasuryDashboard/TreasuryDashboard")); const Faucet = lazy(() => import("./containers/Faucet/Faucet")); +const Wrapper = lazy(() => import("./containers/WethWrapper/WethWrapper")); const Dex = lazy(() => import("./containers/Dex/Dex")); const Bridge = lazy(() => import("./containers/Bridge/Bridge")); const NotFound = lazy(() => import("./containers/NotFound/NotFound")); @@ -206,7 +207,10 @@ function App() { } /> } /> } /> - } /> + {isNetworkLegacy(chainId) + ? } /> + : } /> + } } /> } /> diff --git a/src/abi/GhostTreasury.json b/src/abi/GhostTreasury.json index 4a5c5ea..297b5ca 100644 --- a/src/abi/GhostTreasury.json +++ b/src/abi/GhostTreasury.json @@ -1 +1 @@ -{"abi":[{"inputs":[{"internalType":"address","name":"_ftso","type":"address"},{"internalType":"uint256","name":"_timelock","type":"uint256"},{"internalType":"address","name":"_authority","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"ActionExecuted","type":"error"},{"inputs":[],"name":"ActionNullified","type":"error"},{"inputs":[{"internalType":"address","name":"target","type":"address"}],"name":"AddressEmptyCode","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"AddressInsufficientBalance","type":"error"},{"inputs":[],"name":"AlreadyInitialized","type":"error"},{"inputs":[],"name":"EmptyAddress","type":"error"},{"inputs":[],"name":"FailedInnerCall","type":"error"},{"inputs":[],"name":"InsufficientReserves","type":"error"},{"inputs":[],"name":"InvalidToken","type":"error"},{"inputs":[],"name":"NotAccepted","type":"error"},{"inputs":[],"name":"NotApproved","type":"error"},{"inputs":[],"name":"OnlyQueueTimelock","type":"error"},{"inputs":[{"internalType":"address","name":"token","type":"address"}],"name":"SafeERC20FailedOperation","type":"error"},{"inputs":[],"name":"TimelockDisabled","type":"error"},{"inputs":[],"name":"TimelockNotComplete","type":"error"},{"inputs":[],"name":"TreasuryExceeds","type":"error"},{"inputs":[],"name":"Unauthorized","type":"error"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"authority","type":"address"}],"name":"AuthorityUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"debtor","type":"address"},{"indexed":true,"internalType":"address","name":"token","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"CreateDebt","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"token","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Deposit","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"token","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Managed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"caller","type":"address"},{"indexed":true,"internalType":"address","name":"recipient","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Minted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"enum ITreasury.STATUS","name":"status","type":"uint8"},{"indexed":false,"internalType":"address","name":"queued","type":"address"}],"name":"PermissionQueued","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"addr","type":"address"},{"indexed":true,"internalType":"enum ITreasury.STATUS","name":"status","type":"uint8"},{"indexed":false,"internalType":"bool","name":"result","type":"bool"}],"name":"Permissioned","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"debtor","type":"address"},{"indexed":true,"internalType":"address","name":"token","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"RepayDebt","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"totalReserves","type":"uint256"}],"name":"ReservesAudited","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"token","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Withdrawal","type":"event"},{"inputs":[],"name":"auditReserves","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"authority","outputs":[{"internalType":"contract IGhostAuthority","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"baseSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"blocksNeededForQueue","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"bondCalculator","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"debtLimit","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"profit","type":"uint256"}],"name":"deposit","outputs":[{"internalType":"uint256","name":"send","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"enum ITreasury.STATUS","name":"status","type":"uint8"},{"internalType":"address","name":"toDisable","type":"address"}],"name":"disable","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"enum ITreasury.STATUS","name":"status","type":"uint8"},{"internalType":"address","name":"someAddress","type":"address"},{"internalType":"address","name":"calculatorAddress","type":"address"}],"name":"enable","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"excessReserves","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"idx","type":"uint256"}],"name":"execute","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"ftso","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"ftsoDebt","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"incurDebt","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"someAddress","type":"address"},{"internalType":"enum ITreasury.STATUS","name":"status","type":"uint8"}],"name":"indexInRegistry","outputs":[{"internalType":"bool","name":"","type":"bool"},{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"manage","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"mint","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"idx","type":"uint256"}],"name":"nullify","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"onChainGovernanceTimelock","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"permissionQueue","outputs":[{"internalType":"enum ITreasury.STATUS","name":"managing","type":"uint8"},{"internalType":"address","name":"toPermit","type":"address"},{"internalType":"address","name":"calculator","type":"address"},{"internalType":"uint256","name":"timelockEnd","type":"uint256"},{"internalType":"bool","name":"nullify","type":"bool"},{"internalType":"bool","name":"executed","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"enum ITreasury.STATUS","name":"","type":"uint8"},{"internalType":"address","name":"","type":"address"}],"name":"permissions","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"enum ITreasury.STATUS","name":"status","type":"uint8"},{"internalType":"address","name":"someAddress","type":"address"},{"internalType":"address","name":"calculatorAddress","type":"address"}],"name":"queueTimelock","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"enum ITreasury.STATUS","name":"","type":"uint8"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"registry","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"repayDebtWithFtso","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"repayDebtWithReserves","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newAuthority","type":"address"}],"name":"setAuthority","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"who","type":"address"},{"internalType":"uint256","name":"limit","type":"uint256"}],"name":"setDebtLimit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"stnk","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"timelockEnabled","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"toggleTimelock","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"tokenValue","outputs":[{"internalType":"uint256","name":"value","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalDebt","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalReserves","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"withdraw","outputs":[],"stateMutability":"nonpayable","type":"function"}]} +{"abi":[{"inputs":[{"internalType":"address","name":"_ftso","type":"address"},{"internalType":"uint256","name":"_timelock","type":"uint256"},{"internalType":"address","name":"_authority","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"ActionExecuted","type":"error"},{"inputs":[],"name":"ActionNullified","type":"error"},{"inputs":[{"internalType":"address","name":"target","type":"address"}],"name":"AddressEmptyCode","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"AddressInsufficientBalance","type":"error"},{"inputs":[],"name":"AlreadyInitialized","type":"error"},{"inputs":[],"name":"EmptyAddress","type":"error"},{"inputs":[],"name":"FailedInnerCall","type":"error"},{"inputs":[],"name":"InsufficientReserves","type":"error"},{"inputs":[],"name":"InvalidToken","type":"error"},{"inputs":[],"name":"NotAccepted","type":"error"},{"inputs":[],"name":"NotApproved","type":"error"},{"inputs":[],"name":"OnlyQueueTimelock","type":"error"},{"inputs":[{"internalType":"address","name":"token","type":"address"}],"name":"SafeERC20FailedOperation","type":"error"},{"inputs":[],"name":"TimelockDisabled","type":"error"},{"inputs":[],"name":"TimelockNotComplete","type":"error"},{"inputs":[],"name":"TreasuryExceeds","type":"error"},{"inputs":[],"name":"Unauthorized","type":"error"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"authority","type":"address"}],"name":"AuthorityUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"debtor","type":"address"},{"indexed":true,"internalType":"address","name":"token","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"CreateDebt","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"token","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Deposit","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"token","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Managed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"caller","type":"address"},{"indexed":true,"internalType":"address","name":"recipient","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Minted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"enum ITreasury.STATUS","name":"status","type":"uint8"},{"indexed":false,"internalType":"address","name":"queued","type":"address"}],"name":"PermissionQueued","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"addr","type":"address"},{"indexed":true,"internalType":"enum ITreasury.STATUS","name":"status","type":"uint8"},{"indexed":false,"internalType":"bool","name":"result","type":"bool"}],"name":"Permissioned","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"debtor","type":"address"},{"indexed":true,"internalType":"address","name":"token","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"RepayDebt","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"totalReserves","type":"uint256"}],"name":"ReservesAudited","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"token","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Withdrawal","type":"event"},{"inputs":[],"name":"auditReserves","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"authority","outputs":[{"internalType":"contract IGhostAuthority","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"baseSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"blocksNeededForQueue","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"bondCalculator","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"debtLimit","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"profit","type":"uint256"}],"name":"deposit","outputs":[{"internalType":"uint256","name":"send","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"enum ITreasury.STATUS","name":"status","type":"uint8"},{"internalType":"address","name":"toDisable","type":"address"}],"name":"disable","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"enum ITreasury.STATUS","name":"status","type":"uint8"},{"internalType":"address","name":"someAddress","type":"address"},{"internalType":"address","name":"calculatorAddress","type":"address"}],"name":"enable","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"excessReserves","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"idx","type":"uint256"}],"name":"execute","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"router","type":"address"},{"internalType":"uint256","name":"liquidity","type":"uint256"},{"internalType":"bool","name":"destroyerMode","type":"bool"}],"name":"forfeitReserves","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"ftso","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"ftsoDebt","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"incurDebt","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"someAddress","type":"address"},{"internalType":"enum ITreasury.STATUS","name":"status","type":"uint8"}],"name":"indexInRegistry","outputs":[{"internalType":"bool","name":"","type":"bool"},{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"manage","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"mint","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"idx","type":"uint256"}],"name":"nullify","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"onChainGovernanceTimelock","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"originalCoefficient","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"permissionQueue","outputs":[{"internalType":"enum ITreasury.STATUS","name":"managing","type":"uint8"},{"internalType":"address","name":"toPermit","type":"address"},{"internalType":"address","name":"calculator","type":"address"},{"internalType":"uint256","name":"timelockEnd","type":"uint256"},{"internalType":"bool","name":"nullify","type":"bool"},{"internalType":"bool","name":"executed","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"enum ITreasury.STATUS","name":"","type":"uint8"},{"internalType":"address","name":"","type":"address"}],"name":"permissions","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"enum ITreasury.STATUS","name":"status","type":"uint8"},{"internalType":"address","name":"someAddress","type":"address"},{"internalType":"address","name":"calculatorAddress","type":"address"}],"name":"queueTimelock","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"router","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"redeemReserve","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"enum ITreasury.STATUS","name":"","type":"uint8"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"registry","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"repayDebtWithFtso","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"repayDebtWithReserves","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newAuthority","type":"address"}],"name":"setAuthority","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"who","type":"address"},{"internalType":"uint256","name":"limit","type":"uint256"}],"name":"setDebtLimit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"stnk","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"timelockEnabled","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"toggleTimelock","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"tokenValue","outputs":[{"internalType":"uint256","name":"value","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalDebt","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalReserves","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"withdraw","outputs":[],"stateMutability":"nonpayable","type":"function"}]} diff --git a/src/abi/WETH9.json b/src/abi/WETH9.json new file mode 100644 index 0000000..6984e0a --- /dev/null +++ b/src/abi/WETH9.json @@ -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"}]} diff --git a/src/components/Sidebar/NavContent.jsx b/src/components/Sidebar/NavContent.jsx index 1e08614..79aa61a 100644 --- a/src/components/Sidebar/NavContent.jsx +++ b/src/components/Sidebar/NavContent.jsx @@ -37,7 +37,7 @@ import BondIcon from "../Icon/BondIcon"; import StakeIcon from "../Icon/StakeIcon"; import WrapIcon from "../Icon/WrapIcon"; -import { isNetworkAvailable } from "../../constants"; +import { isNetworkAvailable, isNetworkLegacy } from "../../constants"; import { AVAILABLE_DEXES } from "../../constants/dexes"; import { ECOSYSTEM } from "../../constants/ecosystem"; import { DecimalBigNumber } from "../../helpers/DecimalBigNumber"; @@ -46,6 +46,7 @@ import BondDiscount from "../../containers/Bond/components/BondDiscount"; import DashboardIcon from '@mui/icons-material/Dashboard'; import ShowerIcon from '@mui/icons-material/Shower'; +import WifiProtectedSetupIcon from '@mui/icons-material/WifiProtectedSetup'; import { useTokenSymbol } from "../../hooks/tokens"; import { useFtsoPrice, useGhstPrice, useGhostedSupplyPrice } from "../../hooks/prices"; @@ -148,7 +149,10 @@ const NavContent = ({ chainId, addressChainId }) => { } /> - + {isNetworkLegacy(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; switch (chainId) { case 11155111: diff --git a/src/constants/addresses.js b/src/constants/addresses.js index c22cc5c..4d836dc 100644 --- a/src/constants/addresses.js +++ b/src/constants/addresses.js @@ -3,78 +3,98 @@ import { NetworkId } from "../constants"; export const STAKING_ADDRESSES = { [NetworkId.TESTNET_SEPOLIA]: "0xd90E63E88282596E1ea33765b41Ba3d650f4aD52", [NetworkId.TESTNET_HOODI]: "0x25F62eDc6C89FF84E957C22336A35d2dfc861a86", + [NetworkId.TESTNET_MORDOR]: "0xC25C9C56a89ebd6ef291b415d00ACfa7913c55e7", }; export const BOND_DEPOSITORY_ADDRESSES = { [NetworkId.TESTNET_SEPOLIA]: "0xdcE486113280e49ca2fB200258E5Ee1B2D21D495", [NetworkId.TESTNET_HOODI]: "0x6Ad50B1E293E68B2fC230c576220a93A9D311571", + [NetworkId.TESTNET_MORDOR]: "0x7C85cDEddBAd0f50453d373F7332BEa11ECa7BAf", }; export const DAO_TREASURY_ADDRESSES = { [NetworkId.TESTNET_SEPOLIA]: "0x93dd30f819403710de7933B79A74C4A42438458D", [NetworkId.TESTNET_HOODI]: "0x1a1b29b18f714fac9dDabEf530dFc4f85b56A6e8", + [NetworkId.TESTNET_MORDOR]: "0x5883C8e2259556B534036c7fDF4555E09dE9f243", }; export const FTSO_DAI_LP_ADDRESSES = { [NetworkId.TESTNET_SEPOLIA]: "0x1394dC3f7bABaa2F0CA80353648087DAB1BF3fd6", [NetworkId.TESTNET_HOODI]: "0xf7B2d44209E70782d93A70F7D8eC50010dF7ae50", + [NetworkId.TESTNET_MORDOR]: "0xE6546D12665dB5B22Cb92FB9e0221aE51A57aeaa", }; export const FTSO_STNK_LP_ADDRESSES = { [NetworkId.TESTNET_SEPOLIA]: "0x0000000000000000000000000000000000000000", // TBD [NetworkId.TESTNET_SEPOLIA]: "0x0000000000000000000000000000000000000000", + [NetworkId.TESTNET_MORDOR]: "0x0000000000000000000000000000000000000000", } export const DAI_ADDRESSES = { [NetworkId.TESTNET_SEPOLIA]: "0x5f63a27a9214a0352F2EF8dAF1eD4974d713192B", [NetworkId.TESTNET_HOODI]: "0x80c6676c334BCcE60b3CC852085B72143379CE58", + [NetworkId.TESTNET_MORDOR]: "0x6af91B3763b5d020E0985f85555EB50e5852d7AC", }; export const WETH_ADDRESSES = { [NetworkId.TESTNET_SEPOLIA]: "0xfff9976782d46cc05630d1f6ebab18b2324d6b14", [NetworkId.TESTNET_HOODI]: "0xE69a5c6dd88cA798b93c3C92fc50c51Fd5305eB4", + [NetworkId.TESTNET_MORDOR]: "0x6af91B3763b5d020E0985f85555EB50e5852d7AC", }; export const GHST_ADDRESSES = { [NetworkId.TESTNET_SEPOLIA]: "0xdf2e5306A3dCcfA4e21bbF4226C17Ff5B008dDC4", [NetworkId.TESTNET_HOODI]: "0xE98f7426457E6533B206e91B7EcA97aa8A258B46", + [NetworkId.TESTNET_MORDOR]: "0x14b5787F8a1E62786F50A7998A9b14aa24298423", }; export const STNK_ADDRESSES = { [NetworkId.TESTNET_SEPOLIA]: "0x02C296A27eA779d5a16F934337c12062C5E3c0D9", [NetworkId.TESTNET_HOODI]: "0xF07e9303A9f16Afd82f4f57Fd6fca68Aa0AB6D7F", + [NetworkId.TESTNET_MORDOR]: "0x137bA9403885D8ECEa95AaFBb8734F5a16121bAC", }; export const FTSO_ADDRESSES = { [NetworkId.TESTNET_SEPOLIA]: "0xcFedFFEB3FdeCd2196820Ba3b71f3F84A1255f93", [NetworkId.TESTNET_HOODI]: "0xb184e423811b644A1924334E63985c259F5D0033", + [NetworkId.TESTNET_MORDOR]: "0xeA170CC0faceC531a6a9e93a28C4330Ac50343a1", }; export const DISTRIBUTOR_ADDRESSES = { [NetworkId.TESTNET_SEPOLIA]: "0x8fbF8eB4Fcd451EF62Aee33508D46FE120963194", [NetworkId.TESTNET_HOODI]: "0xdF49dC81c457c6f92e26cf6d686C7a8715255842", + [NetworkId.TESTNET_MORDOR]: "0xaf5e76706520db7fb01096E322940206bf3fce57", }; export const GHOST_GOVERNANCE_ADDRESSES = { [NetworkId.TESTNET_SEPOLIA]: "0xDab0c51918E6990d8763FAC8a04AE159e44e0c4f", [NetworkId.TESTNET_HOODI]: "0x1B96B792840d4d19d5097ee007392Ed4d851e64F", + [NetworkId.TESTNET_MORDOR]: "0x3dD438416D9593A58193fC52850E588efAa3D57E", }; export const BONDING_CALCULATOR_ADDRESSES = { [NetworkId.TESTNET_SEPOLIA]: "0x4896bFc6256A57Df826d7144E48c9633d51d6319", [NetworkId.TESTNET_HOODI]: "0x2635d526Ad24b98082563937f7b996075052c6Fd", + [NetworkId.TESTNET_MORDOR]: "0x0c4C7C49a173E2a3f9Eed93125F3F146D8e17bCb", } export const GATEKEEPER_ADDRESSES = { [NetworkId.TESTNET_SEPOLIA]: "0xc85129A097773B7F8970a7364c928C05f265E6A1", + [NetworkId.TESTNET_MORDOR]: "0xA59cB4ff90bE2206121aE61eEB68d0AeC7BA095f", } export const UNISWAP_V2_ROUTER = { [NetworkId.TESTNET_SEPOLIA]: "0xee567fe1712faf6149d80da1e6934e354124cfe3", [NetworkId.TESTNET_HOODI]: "0xD41daF947c6FFEf344754B99ad09466FBCBb7583", + [NetworkId.TESTNET_MORDOR]: "0x90ecf6a29798E3cf31EB7DCE64a372AC40d83F83", }; export const UNISWAP_V2_FACTORY = { [NetworkId.TESTNET_SEPOLIA]: "0xF62c03E08ada871A0bEb309762E260a7a6a880E6", [NetworkId.TESTNET_HOODI]: "0xF140342cB5C29C1468d91Aee408d7b7271C48b5A", + [NetworkId.TESTNET_MORDOR]: "0x909f96C1a436B3386E9962e30f3Ce753070ff524", }; + +export const CEX_TICKERS = { + [NetworkId.TESTNET_MORDOR]: "ETCUSDT", +} diff --git a/src/constants/dexes.js b/src/constants/dexes.js index 24fdcbf..bd988fd 100644 --- a/src/constants/dexes.js +++ b/src/constants/dexes.js @@ -18,4 +18,11 @@ export const AVAILABLE_DEXES = { viewBox: "0 0 195 230", }, ], + [NetworkId.TESTNET_MORDOR]: [ + { + name: "Uniswap", + icon: UniswapIcon, + viewBox: "0 0 195 230", + }, + ], }; diff --git a/src/containers/Dex/TokenModal.jsx b/src/containers/Dex/TokenModal.jsx index fc0642d..180008a 100644 --- a/src/containers/Dex/TokenModal.jsx +++ b/src/containers/Dex/TokenModal.jsx @@ -19,6 +19,7 @@ import TokenStack from "../../components/TokenStack/TokenStack"; import { DecimalBigNumber } from "../../helpers/DecimalBigNumber"; import { formatNumber } from "../../helpers/"; import { useBalance, useTokenSymbol } from "../../hooks/tokens"; +import { isNetworkLegacy } from "../../constants"; import { DAI_ADDRESSES, FTSO_ADDRESSES, STNK_ADDRESSES, GHST_ADDRESSES } from "../../constants/addresses"; const TokenModal = ({ chainId, account, listOpen, setListOpen, setTokenAddress }) => { @@ -60,7 +61,7 @@ const TokenModal = ({ chainId, account, listOpen, setListOpen, setTokenAddress } return [ { name: daiSymbol, - icons: ["GDAI"], + icons: isNetworkLegacy(chainId) ? ["GDAI"] : ["WETH"], balance: daiBalance, address: DAI_ADDRESSES[chainId] }, diff --git a/src/containers/TreasuryDashboard/components/TokenInfo.jsx b/src/containers/TreasuryDashboard/components/TokenInfo.jsx index 739a419..ab90c9d 100644 --- a/src/containers/TreasuryDashboard/components/TokenInfo.jsx +++ b/src/containers/TreasuryDashboard/components/TokenInfo.jsx @@ -6,6 +6,7 @@ import Token from "../../../components/Token/Token"; import { SecondaryButton } from "../../../components/Button"; import { formatNumber, formatCurrency } from "../../../helpers"; import { DecimalBigNumber } from "../../../helpers/DecimalBigNumber"; +import { isNetworkLegacy } from "../../../constants" import { useBalance, useTokenSymbol } from "../../../hooks/tokens"; import { @@ -133,7 +134,7 @@ const TokenInfo = ({ chainId, isMobileScreen }) => { /> { + 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 ( + + + ghostWrapper | WETH9 + + + + + + + + + + + + + + + + + + + + + + + changeIsMinted(view === 0)} + TabIndicatorProps={{ style: { display: "none" } }} + > + + + + {!isSemiSmallScreen && + Check on {scanInfo.name} + } + + } + enableBackground + fullWidth + > + + {isMint && } + info={`${isSemiSmallScreen ? "" : "Balance: "}${formatCurrency(balance.toString(), 4, nativeInfo.symbol)}`} + value={amount} + onChange={event => setAmount(event.currentTarget.value)} + inputProps={{ "data-testid": "fromInput" }} + />} + {!isMint && } + info={`${formatCurrency(daiBalance.toString(), 4, faucetSymbol)}`} + value={amount} + onChange={event => setAmount(event.currentTarget.value)} + inputProps={{ "data-testid": "fromInput" }} + endString={"Max"} + endStringOnClick={() => setAmount(daiBalance.toString())} + />} + + {isMint && ( + <> + + {!isVerySmallScreen && You will get:} + {formatCurrency(estimatedAmountIn, 5, faucetSymbol)} + + + {!isVerySmallScreen && Your {faucetSymbol} balance:} + {formatCurrency(daiBalance, 5, faucetSymbol)} + + + )} + {!isMint && ( + <> + + {!isVerySmallScreen && You will get:} + {formatCurrency(estimatedAmountOut, 5, nativeInfo.symbol)} + + + {!isVerySmallScreen && Your {nativeInfo.symbol} balance:} + {formatCurrency(balance, 5, nativeInfo.symbol)} + + + )} + + actionOrConnect()} + > + {address === "" ? + "Connect" + : + isMint ? "Mint" : "Burn" + } + + + + + + + ) +} + +export default WethWrapper; diff --git a/src/hooks/helpers.js b/src/hooks/helpers.js index 76c891c..34a6b30 100644 --- a/src/hooks/helpers.js +++ b/src/hooks/helpers.js @@ -4,6 +4,7 @@ import { STNK_ADDRESSES, GHST_ADDRESSES, FTSO_DAI_LP_ADDRESSES, + WETH_ADDRESSES, } from "../constants/addresses"; 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 GhostAbi } from "../abi/Ghost.json"; import { abi as Erc20Abi } from "../abi/ERC20.json"; +import { abi as WethAbi } from "../abi/WETH9.json"; // TBD: should be extended on new tokens export const getTokenAbi = (name) => { @@ -40,6 +42,9 @@ export const getTokenAbi = (name) => { case "CSPR": abi = GhostAbi; break; + case "WETH": + abi = WethAbi; + break; } return abi; } @@ -72,6 +77,9 @@ export const getTokenDecimals = (name) => { case "CSPR": decimals = 18; break; + case "WETH": + decimals = 18; + break; } return decimals; } @@ -107,6 +115,9 @@ export const getTokenAddress = (chainId, name) => { case "GDAI_FTSO": address = FTSO_DAI_LP_ADDRESSES[chainId]; break; + case "WETH": + address = WETH_ADDRESSES[chainId]; + break; } return address; } diff --git a/src/hooks/prices/index.js b/src/hooks/prices/index.js index ee53e2b..19f476d 100644 --- a/src/hooks/prices/index.js +++ b/src/hooks/prices/index.js @@ -1,12 +1,79 @@ +import { useState, useEffect } from "react"; import { useReadContract } from "wagmi"; import { useCurrentIndex, useGhostedSupply } from "../staking"; import { useUniswapV2PairReserves } from "../uniswapv2"; import { DecimalBigNumber } from "../../helpers/DecimalBigNumber"; -import { FTSO_DAI_LP_ADDRESSES, DAI_ADDRESSES, FTSO_ADDRESSES } from "../../constants/addresses"; +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) => { - 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; }; @@ -20,6 +87,7 @@ export const useFtsoPrice = (chainId) => { "GDAI", ); + const reservePrice = useDaiPrice(chainId); const reserveAddress = DAI_ADDRESSES[chainId]; const ftsoAddress = FTSO_ADDRESSES[chainId]; if (!reserveAddress || !ftsoAddress) { @@ -37,8 +105,9 @@ export const useFtsoPrice = (chainId) => { let price = 0n if (ftsoReserves > 0n) price = stableReserves / ftsoReserves; + price = price * reservePrice._value; - return new DecimalBigNumber(price, 9); + return new DecimalBigNumber(price, 27); }; export const useStnkPrice = (chainId) => { diff --git a/src/hooks/tokens/index.js b/src/hooks/tokens/index.js index 5f78445..fbb8795 100644 --- a/src/hooks/tokens/index.js +++ b/src/hooks/tokens/index.js @@ -229,3 +229,53 @@ export const burnDai = async (chainId, account, value) => { 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.") + } +} diff --git a/src/hooks/treasury/index.js b/src/hooks/treasury/index.js index 7315adb..4464dcd 100644 --- a/src/hooks/treasury/index.js +++ b/src/hooks/treasury/index.js @@ -3,9 +3,23 @@ import { useReadContract } from "wagmi"; import { DAO_TREASURY_ADDRESSES } from "../../constants/addresses"; import { abi as TreasuryAbi } from "../../abi/GhostTreasury.json"; +import { useDaiPrice } from "../prices/index"; + import { DecimalBigNumber } from "../../helpers/DecimalBigNumber"; 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) => { const { data: totalReservesRaw } = useReadContract({ abi: TreasuryAbi, @@ -15,10 +29,13 @@ export const useTotalReserves = (chainId) => { chainId: chainId, }); + const original = useOrinalCoefficient(chainId); + const price = useDaiPrice(chainId); + const totalReservesPrepared = totalReservesRaw ? totalReservesRaw : 0n; const totalReserves = new DecimalBigNumber(totalReservesPrepared, 9); - return totalReserves; + return totalReserves.mul(price).div(original); }; export const useLpValuation = (chainId, pairAddress, pairSupply) => {