Compare commits

..

No commits in common. "8d23d55ae2021a1d042186d589f675d30f3f9922" and "86291f933ba29bf8f0fdcc031c49e8efd1234470" have entirely different histories.

16 changed files with 113 additions and 358 deletions

View File

@ -1,7 +1,7 @@
{ {
"name": "ghost-dao-interface", "name": "ghost-dao-interface",
"private": true, "private": true,
"version": "0.6.5", "version": "0.6.3",
"type": "module", "type": "module",
"scripts": { "scripts": {
"dev": "vite", "dev": "vite",

View File

@ -215,7 +215,7 @@ function App() {
: <Route path="/wrapper" element={<Wrapper 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 config={config} connect={tryConnectInjected} address={address} chainId={addressChainId ? addressChainId : chainId} />} /> <Route path="/dex/:name" element={<Dex connect={tryConnectInjected} address={address} chainId={addressChainId ? addressChainId : chainId} />} />
{isGovernanceAvailable(chainId, addressChainId) && <Route path="/governance" element={<Governance config={config} connect={tryConnectInjected} address={address} chainId={addressChainId ? addressChainId : chainId} />} />} {isGovernanceAvailable(chainId, addressChainId) && <Route path="/governance" element={<Governance config={config} connect={tryConnectInjected} address={address} chainId={addressChainId ? addressChainId : chainId} />} />}
{isGovernanceAvailable(chainId, addressChainId) && <Route path="/governance/:id" element={<ProposalDetails config={config} connect={tryConnectInjected} address={address} chainId={addressChainId ? addressChainId : chainId} />} />} {isGovernanceAvailable(chainId, addressChainId) && <Route path="/governance/:id" element={<ProposalDetails config={config} connect={tryConnectInjected} address={address} chainId={addressChainId ? addressChainId : chainId} />} />}
{isGovernanceAvailable(chainId, addressChainId) && <Route path="/governance/create" element={<NewProposal config={config} connect={tryConnectInjected} address={address} chainId={addressChainId ? addressChainId : chainId} />} />} {isGovernanceAvailable(chainId, addressChainId) && <Route path="/governance/create" element={<NewProposal config={config} connect={tryConnectInjected} address={address} chainId={addressChainId ? addressChainId : chainId} />} />}

View File

@ -58,7 +58,6 @@ export const TokenAllowanceGuard = ({
height = "auto", height = "auto",
spendAmount, spendAmount,
tokenName, tokenName,
isNative,
owner, owner,
spender, spender,
decimals, decimals,
@ -89,7 +88,7 @@ export const TokenAllowanceGuard = ({
); );
} }
if (!isNative && allowance && spendAmount && allowance.lt(spendAmount)) if (allowance && spendAmount && allowance.lt(spendAmount))
return ( return (
<Grid container alignItems="center"> <Grid container alignItems="center">
<Grid item xs={12} sm={isVertical ? 12 : 8}> <Grid item xs={12} sm={isVertical ? 12 : 8}>

View File

@ -9,14 +9,13 @@ import {
useTheme, useTheme,
} from "@mui/material"; } from "@mui/material";
import ExpandMoreIcon from '@mui/icons-material/ExpandMore'; import ExpandMoreIcon from '@mui/icons-material/ExpandMore';
import { ChangeEvent, useState, useMemo, useEffect } from "react"; import { ChangeEvent, useState, useEffect } from "react";
import { useNavigate, createSearchParams } from "react-router-dom"; import { useNavigate, createSearchParams } from "react-router-dom";
import { useQuery } from "react-query"; import { useQuery } from "react-query";
import { formatCurrency, formatNumber } from "../../../helpers"; import { formatCurrency, formatNumber } from "../../../helpers";
import { DecimalBigNumber } from "../../../helpers/DecimalBigNumber" import { DecimalBigNumber } from "../../../helpers/DecimalBigNumber"
import { tokenNameConverter } from "../../../helpers/tokenConverter"; import { tokenNameConverter } from "../../../helpers/tokenConverter";
import { isNetworkLegacy } from "../../../constants"; import { isNetworkLegacy } from "../../../constants";
import { EMPTY_ADDRESS } from "../../../constants/addresses";
import GhostStyledIcon from "../../Icon/GhostIcon"; import GhostStyledIcon from "../../Icon/GhostIcon";
import TokenStack from "../../TokenStack/TokenStack"; import TokenStack from "../../TokenStack/TokenStack";
@ -31,8 +30,6 @@ import {
useGhstPrice useGhstPrice
} from "../../../hooks/prices"; } from "../../../hooks/prices";
import { useLpValuation } from "../../../hooks/treasury"; import { useLpValuation } from "../../../hooks/treasury";
import { useUniswapV2PairReserves } from "../../../hooks/uniswapv2";
import { getTokenIcons } from "../../../hooks/helpers";
import { useAccount, useBalance as useNativeBalance, useConfig } from "wagmi"; import { useAccount, useBalance as useNativeBalance, useConfig } from "wagmi";
const addTokenToWallet = async (token, userAddress) => { const addTokenToWallet = async (token, userAddress) => {
@ -74,7 +71,6 @@ export const Token = (props) => {
const { const {
isNative, isNative,
symbol, symbol,
faucetPath,
icons, icons,
address, address,
price = 0, price = 0,
@ -90,8 +86,8 @@ export const Token = (props) => {
const navigate = useNavigate(); const navigate = useNavigate();
const useLink = (symbol, fromAddress, toAddress, isPool) => { const useLink = (symbol, fromAddress, toAddress, isPool) => {
if (faucetPath) { if (symbol.toUpperCase() === "RESERVE") {
navigate({ pathname: faucetPath }) navigate({ pathname: "/faucet" })
} else { } else {
navigate({ navigate({
pathname: "/dex/uniswap", pathname: "/dex/uniswap",
@ -150,7 +146,7 @@ export const Token = (props) => {
onClick={() => useLink(symbol, reserveAddress, address, isPool)} onClick={() => useLink(symbol, reserveAddress, address, isPool)}
fullWidth fullWidth
> >
<Typography>Get {faucetPath ? "for Free" : "on DEX"}</Typography> <Typography>Get on {symbol?.toUpperCase() === "RESERVE" ? "Faucet" : "Uniswap"}</Typography>
</SecondaryButton> </SecondaryButton>
</Box> </Box>
</Box> </Box>
@ -193,9 +189,6 @@ export const useWallet = (chainId, userAddress) => {
refetch: lpReserveFtsoRefetch, refetch: lpReserveFtsoRefetch,
contractAddress: lpReserveFtsoBalanceAddress, contractAddress: lpReserveFtsoBalanceAddress,
} = useBalance(chainId, "RESERVE_FTSO", userAddress); } = useBalance(chainId, "RESERVE_FTSO", userAddress);
const {
tokens: lpReserveFtsoTokens,
} = useUniswapV2PairReserves(chainId, "RESERVE_FTSO");
const nativePrice = useNativePrice(chainId); const nativePrice = useNativePrice(chainId);
const reservePrice = useReservePrice(chainId); const reservePrice = useReservePrice(chainId);
@ -213,29 +206,13 @@ export const useWallet = (chainId, userAddress) => {
const { symbol: ghstSymbol } = useTokenSymbol(chainId, "GHST"); const { symbol: ghstSymbol } = useTokenSymbol(chainId, "GHST");
const { symbol: lpReserveFtsoSymbol } = useTokenSymbol(chainId, "RESERVE_FTSO"); const { symbol: lpReserveFtsoSymbol } = useTokenSymbol(chainId, "RESERVE_FTSO");
const lpReserveFtsoTokenNames = useMemo(() => {
const token0 = getTokenIcons(chainId, lpReserveFtsoTokens?.token0 ?? []);
const token1 = getTokenIcons(chainId, lpReserveFtsoTokens?.token1 ?? []);
let tokenAddresses = [lpReserveFtsoTokens?.token1, lpReserveFtsoTokens?.token0];
let tokenNames = [...token1, ...token0];
if (token0?.at(0) === reserveSymbol) {
tokenAddresses = [lpReserveFtsoTokens?.token0, lpReserveFtsoTokens?.token1];
let tokenNames = [...token0, ...token1];
}
return { tokenAddresses, tokenNames }
}, [chainId, reserveSymbol, lpReserveFtsoTokens]);
const tokens = { const tokens = {
native: { native: {
symbol: nativeSymbol, symbol: nativeSymbol,
icons: [nativeSymbol], icons: [nativeSymbol],
balance: nativeBalance, balance: nativeBalance,
price: nativePrice, price: nativePrice,
refetch: nativeBalanceRefetch, refetch: nativeBalanceRefetch
faucetPath: isNetworkLegacy(chainId) ? "/faucet" : "/wrapper",
}, },
reserve: { reserve: {
symbol: reserveSymbol, symbol: reserveSymbol,
@ -247,7 +224,6 @@ export const useWallet = (chainId, userAddress) => {
? "https://ghostchain.io/wp-content/uploads/2025/03/gDAI.svg" ? "https://ghostchain.io/wp-content/uploads/2025/03/gDAI.svg"
: "https://ghostchain.io/wp-content/uploads/2025/11/6A-Classic-ETC-Token.svg", : "https://ghostchain.io/wp-content/uploads/2025/11/6A-Classic-ETC-Token.svg",
refetch: reserveRefetch, refetch: reserveRefetch,
faucetPath: isNetworkLegacy(chainId) ? "/faucet" : "/wrapper",
}, },
ftso: { ftso: {
symbol: ftsoSymbol, symbol: ftsoSymbol,
@ -279,10 +255,10 @@ export const useWallet = (chainId, userAddress) => {
reserveFtso: { reserveFtso: {
isPool: true, isPool: true,
symbol: lpReserveFtsoSymbol, symbol: lpReserveFtsoSymbol,
address: lpReserveFtsoTokenNames?.tokenAddresses.at(1) ?? "", address: lpReserveFtsoBalanceAddress,
balance: lpReserveFtsoBalance, balance: lpReserveFtsoBalance,
price: lpReserveFtsoPrice, price: lpReserveFtsoPrice,
icons: lpReserveFtsoTokenNames?.tokenNames, icons: ["FTSO", isNetworkLegacy(chainId) ? "GDAI" : tokenNameConverter(chainId, reserveSymbol)],
externalUrl: "https://ghostchain.io/wp-content/uploads/2025/03/uni-v2.svg", externalUrl: "https://ghostchain.io/wp-content/uploads/2025/03/uni-v2.svg",
refetch: lpReserveFtsoRefetch, refetch: lpReserveFtsoRefetch,
} }
@ -306,7 +282,7 @@ export const Tokens = ({ address, tokens, onClose }) => {
const tokenProps = (token) => ({ const tokenProps = (token) => ({
...token, ...token,
expanded: expanded === token.symbol, expanded: expanded === token.symbol,
reserveAddress: EMPTY_ADDRESS, reserveAddress: tokens.reserve.address,
onChangeExpanded: (e, isExpanded) => setExpanded(isExpanded ? token.symbol : null), onChangeExpanded: (e, isExpanded) => setExpanded(isExpanded ? token.symbol : null),
onAddTokenToWallet: () => addTokenToWallet(token, address), onAddTokenToWallet: () => addTokenToWallet(token, address),
onClose: () => onClose(), onClose: () => onClose(),

View File

@ -1,7 +1,5 @@
import { NetworkId } from "../constants"; import { NetworkId } from "../constants";
export const EMPTY_ADDRESS = "0x0000000000000000000000000000000000000000";
export const STAKING_ADDRESSES = { export const STAKING_ADDRESSES = {
[NetworkId.TESTNET_SEPOLIA]: "0xC2C579631Bf6daA93252154080fecfd68c6aa506", [NetworkId.TESTNET_SEPOLIA]: "0xC2C579631Bf6daA93252154080fecfd68c6aa506",
[NetworkId.TESTNET_HOODI]: "0x25F62eDc6C89FF84E957C22336A35d2dfc861a86", [NetworkId.TESTNET_HOODI]: "0x25F62eDc6C89FF84E957C22336A35d2dfc861a86",

View File

@ -10,7 +10,7 @@ import {
useTheme, useTheme,
} from "@mui/material"; } from "@mui/material";
import SettingsIcon from '@mui/icons-material/Settings'; import SettingsIcon from '@mui/icons-material/Settings';
import { useEffect, useMemo, useState } from "react"; import { useEffect, useState } from "react";
import { useParams, useLocation, useSearchParams } from "react-router-dom"; import { useParams, useLocation, useSearchParams } from "react-router-dom";
import { Helmet } from "react-helmet"; import { Helmet } from "react-helmet";
import ReactGA from "react-ga4"; import ReactGA from "react-ga4";
@ -28,17 +28,14 @@ import {
UNISWAP_V2_FACTORY, UNISWAP_V2_FACTORY,
RESERVE_ADDRESSES, RESERVE_ADDRESSES,
FTSO_ADDRESSES, FTSO_ADDRESSES,
EMPTY_ADDRESS,
WETH_ADDRESSES,
} from "../../constants/addresses"; } from "../../constants/addresses";
import { useTokenSymbol } from "../../hooks/tokens"; import { useTokenSymbol } from "../../hooks/tokens";
import { getTokenAddress } from "../../hooks/helpers";
import PoolContainer from "./PoolContainer"; import PoolContainer from "./PoolContainer";
import SwapContainer from "./SwapContainer"; import SwapContainer from "./SwapContainer";
import TokenModal from "./TokenModal"; import TokenModal from "./TokenModal";
const Dex = ({ chainId, address, connect, config }) => { const Dex = ({ chainId, address, connect }) => {
const location = useLocation(); const location = useLocation();
const pathname = useParams(); const pathname = useParams();
@ -61,44 +58,11 @@ const Dex = ({ chainId, address, connect, config }) => {
const [actualDestinationAddress, setActualDestinationAddress] = useState(localStorage.getItem("dex-destination")); const [actualDestinationAddress, setActualDestinationAddress] = useState(localStorage.getItem("dex-destination"));
const [destinationAddress, setDestinationAddress] = useState(actualDestinationAddress); const [destinationAddress, setDestinationAddress] = useState(actualDestinationAddress);
const [tokenAddressTop, setTokenAddressTop] = useState(EMPTY_ADDRESS); const [tokenAddressTop, setTokenAddressTop] = useState(RESERVE_ADDRESSES[chainId]);
const [tokenAddressBottom, setTokenAddressBottom] = useState(FTSO_ADDRESSES[chainId]); const [tokenAddressBottom, setTokenAddressBottom] = useState(FTSO_ADDRESSES[chainId]);
const { symbol: tokenNameTopInner } = useTokenSymbol(chainId, tokenAddressTop); const { symbol: tokenNameTop } = useTokenSymbol(chainId, tokenAddressTop);
const { symbol: tokenNameBottomInner } = useTokenSymbol(chainId, tokenAddressBottom); const { symbol: tokenNameBottom } = useTokenSymbol(chainId, tokenAddressBottom);
const chainSymbol = useMemo(() => {
const chainSymbol = config?.getClient()?.chain?.nativeCurrency?.symbol;
if (chainSymbol) return chainSymbol;
return "WTF";
}, [config])
const tokenNameTop = useMemo(() => {
if (chainSymbol && tokenAddressTop === EMPTY_ADDRESS) {
return chainSymbol;
}
return tokenNameTopInner;
}, [tokenAddressTop, tokenNameTopInner, chainSymbol]);
const tokenNameBottom = useMemo(() => {
const chainSymbol = config?.getClient()?.chain?.nativeCurrency?.symbol;
if (chainSymbol && tokenAddressBottom === EMPTY_ADDRESS) {
return chainSymbol;
}
return tokenNameBottomInner;
}, [tokenAddressBottom, tokenNameBottomInner, config]);
const isWrapping = useMemo(() => {
const isNative = tokenAddressTop === EMPTY_ADDRESS;
const isWrappedNative = tokenAddressBottom === WETH_ADDRESSES[chainId];
return isNative && isWrappedNative;
}, [chainId, tokenAddressTop, tokenAddressBottom]);
const isUnwrapping = useMemo(() => {
const isWrappedNative = tokenAddressTop === WETH_ADDRESSES[chainId];
const isNative = tokenAddressBottom === EMPTY_ADDRESS;
return isNative && isWrappedNative;
}, [chainId, tokenAddressTop, tokenAddressBottom]);
useEffect(() => { useEffect(() => {
if (currentQueryParameters.has("pool")) { if (currentQueryParameters.has("pool")) {
@ -113,8 +77,8 @@ const Dex = ({ chainId, address, connect, config }) => {
setTokenAddressTop(currentQueryParameters.get("from")); setTokenAddressTop(currentQueryParameters.get("from"));
newQueryParameters.set("from", currentQueryParameters.get("from")); newQueryParameters.set("from", currentQueryParameters.get("from"));
} else { } else {
setTokenAddressTop(EMPTY_ADDRESS); setTokenAddressTop(RESERVE_ADDRESSES[chainId]);
newQueryParameters.set("from", EMPTY_ADDRESS); newQueryParameters.set("from", RESERVE_ADDRESSES[chainId]);
} }
if (currentQueryParameters.has("to")) { if (currentQueryParameters.has("to")) {
@ -130,7 +94,7 @@ const Dex = ({ chainId, address, connect, config }) => {
useEffect(() => { useEffect(() => {
ReactGA.send({ hitType: "pageview", page: location.pathname + location.search }); ReactGA.send({ hitType: "pageview", page: location.pathname + location.search });
}, [location]); }, [location])
const dexAddresses = { const dexAddresses = {
router: UNISWAP_V2_ROUTER[chainId], router: UNISWAP_V2_ROUTER[chainId],
@ -151,7 +115,7 @@ const Dex = ({ chainId, address, connect, config }) => {
} }
const changeSwapTab = (swap) => { const changeSwapTab = (swap) => {
if (swap || (isWrapping || isUnwrapping)) newQueryParameters.delete("pool"); if (swap) newQueryParameters.delete("pool");
else newQueryParameters.set("pool", true); else newQueryParameters.set("pool", true);
newQueryParameters.set("from", currentQueryParameters.get("from")); newQueryParameters.set("from", currentQueryParameters.get("from"));
newQueryParameters.set("to", currentQueryParameters.get("to")); newQueryParameters.set("to", currentQueryParameters.get("to"));
@ -351,7 +315,6 @@ const Dex = ({ chainId, address, connect, config }) => {
</Modal> </Modal>
<TokenModal <TokenModal
chainSymbol={chainSymbol}
account={address} account={address}
chainId={chainId} chainId={chainId}
listOpen={topTokenListOpen} listOpen={topTokenListOpen}
@ -359,7 +322,6 @@ const Dex = ({ chainId, address, connect, config }) => {
setTokenAddress={setInnerTokenAddressTop} setTokenAddress={setInnerTokenAddressTop}
/> />
<TokenModal <TokenModal
chainSymbol={chainSymbol}
account={address} account={address}
chainId={chainId} chainId={chainId}
listOpen={bottomTokenListOpen} listOpen={bottomTokenListOpen}
@ -411,8 +373,6 @@ const Dex = ({ chainId, address, connect, config }) => {
setBottomTokenListOpen={setBottomTokenListOpen} setBottomTokenListOpen={setBottomTokenListOpen}
setIsSwap={setIsSwap} setIsSwap={setIsSwap}
formatDecimals={formatDecimals} formatDecimals={formatDecimals}
isWrapping={isWrapping}
isUnwrapping={isUnwrapping}
/> />
: :
<PoolContainer <PoolContainer

View File

@ -12,12 +12,7 @@ import { DecimalBigNumber } from "../../helpers/DecimalBigNumber";
import { formatNumber, formatCurrency, bigIntSqrt } from "../../helpers"; import { formatNumber, formatCurrency, bigIntSqrt } from "../../helpers";
import { useBalance, useTotalSupply } from "../../hooks/tokens"; import { useBalance, useTotalSupply } from "../../hooks/tokens";
import { import { useUniswapV2Pair, useUniswapV2PairReserves, addLiquidity } from "../../hooks/uniswapv2";
useUniswapV2Pair,
useUniswapV2PairReserves,
addLiquidity,
addLiquidityETH,
} from "../../hooks/uniswapv2";
const PoolContainer = ({ const PoolContainer = ({
tokenNameTop, tokenNameTop,
@ -32,7 +27,7 @@ const PoolContainer = ({
secondsToWait, secondsToWait,
setTopTokenListOpen, setTopTokenListOpen,
setBottomTokenListOpen, setBottomTokenListOpen,
formatDecimals, formatDecimals
}) => { }) => {
const theme = useTheme(); const theme = useTheme();
const isSmallScreen = useMediaQuery("(max-width: 456px)"); const isSmallScreen = useMediaQuery("(max-width: 456px)");
@ -45,13 +40,11 @@ const PoolContainer = ({
balance: balanceTop, balance: balanceTop,
refetch: balanceRefetchTop, refetch: balanceRefetchTop,
contractAddress: addressTop, contractAddress: addressTop,
isNative: topIsNative,
} = useBalance(chainId, tokenNameTop, address); } = useBalance(chainId, tokenNameTop, address);
const { const {
balance: balanceBottom, balance: balanceBottom,
refetch: balanceRefetchBottom, refetch: balanceRefetchBottom,
contractAddress: addressBottom, contractAddress: addressBottom,
isNative: bottomIsNative,
} = useBalance(chainId, tokenNameBottom, address); } = useBalance(chainId, tokenNameBottom, address);
const { const {
@ -149,7 +142,7 @@ const PoolContainer = ({
const amountAMin = amountADesired * bigIntSlippage / one; const amountAMin = amountADesired * bigIntSlippage / one;
const amountBMin = amountBDesired * bigIntSlippage / one; const amountBMin = amountBDesired * bigIntSlippage / one;
const params = { await addLiquidity(
chainId, chainId,
tokenNameTop, tokenNameTop,
tokenNameBottom, tokenNameBottom,
@ -157,16 +150,9 @@ const PoolContainer = ({
amountBDesired, amountBDesired,
amountAMin, amountAMin,
amountBMin, amountBMin,
address,
destination, destination,
deadline, deadline,
} );
if (topIsNative || bottomIsNative) {
await addLiquidityETH(params)
} else {
await addLiquidity(params);
}
await balanceRefetchTop(); await balanceRefetchTop();
await balanceRefetchBottom(); await balanceRefetchBottom();
@ -247,7 +233,6 @@ const PoolContainer = ({
owner={address} owner={address}
spender={dexAddresses.router} spender={dexAddresses.router}
decimals={balanceTop._decimals} decimals={balanceTop._decimals}
isNative={topIsNative}
approvalText={"Approve " + tokenNameTop} approvalText={"Approve " + tokenNameTop}
approvalPendingText={"Approving..."} approvalPendingText={"Approving..."}
connect={connect} connect={connect}
@ -260,7 +245,6 @@ const PoolContainer = ({
owner={address} owner={address}
spender={dexAddresses.router} spender={dexAddresses.router}
decimals={balanceBottom._decimals} decimals={balanceBottom._decimals}
isNative={bottomIsNative}
approvalText={"Approve " + tokenNameBottom} approvalText={"Approve " + tokenNameBottom}
approvalPendingText={"Approving..."} approvalPendingText={"Approving..."}
connect={connect} connect={connect}

View File

@ -1,4 +1,4 @@
import { useState, useMemo, useEffect } from "react"; import { useState, useEffect } from "react";
import { Box, Typography, useTheme, useMediaQuery } from "@mui/material"; import { Box, Typography, useTheme, useMediaQuery } from "@mui/material";
import toast from "react-hot-toast"; import toast from "react-hot-toast";
@ -13,16 +13,8 @@ import { DecimalBigNumber } from "../../helpers/DecimalBigNumber";
import { prettifySecondsInDays } from "../../helpers/timeUtil"; import { prettifySecondsInDays } from "../../helpers/timeUtil";
import { getTokenAddress } from "../../hooks/helpers"; import { getTokenAddress } from "../../hooks/helpers";
import { useBalance, depositNative, withdrawWeth } from "../../hooks/tokens"; import { useBalance } from "../../hooks/tokens";
import { import { useUniswapV2Pair, useUniswapV2PairReserves, swapExactTokensForTokens } from "../../hooks/uniswapv2";
useUniswapV2Pair,
useUniswapV2PairReserves,
swapExactTokensForTokens,
swapExactETHForTokens,
swapExactTokensForETH,
} from "../../hooks/uniswapv2";
import { EMPTY_ADDRESS } from "../../constants/addresses";
const SwapContainer = ({ const SwapContainer = ({
tokenNameTop, tokenNameTop,
@ -38,9 +30,7 @@ const SwapContainer = ({
destination, destination,
secondsToWait, secondsToWait,
setIsSwap, setIsSwap,
formatDecimals, formatDecimals
isWrapping,
isUnwrapping,
}) => { }) => {
const theme = useTheme(); const theme = useTheme();
const isSmallScreen = useMediaQuery("(max-width: 456px)"); const isSmallScreen = useMediaQuery("(max-width: 456px)");
@ -56,14 +46,12 @@ const SwapContainer = ({
balance: balanceTop, balance: balanceTop,
refetch: balanceRefetchTop, refetch: balanceRefetchTop,
contractAddress: addressTop, contractAddress: addressTop,
isNative: topIsNative,
} = useBalance(chainId, tokenNameTop, address); } = useBalance(chainId, tokenNameTop, address);
const { const {
balance: balanceBottom, balance: balanceBottom,
refetch: balanceRefetchBottom, refetch: balanceRefetchBottom,
contractAddress: addressBottom, contractAddress: addressBottom,
isNative: bottomIsNative,
} = useBalance(chainId, tokenNameBottom, address); } = useBalance(chainId, tokenNameBottom, address);
const { const {
@ -87,18 +75,14 @@ const SwapContainer = ({
const setMax = () => setAmountTop(balanceTop.toString()); const setMax = () => setAmountTop(balanceTop.toString());
useEffect(() => { useEffect(() => {
if (isWrapping || isUnwrapping) {
setAmountBottom(amountTop.toString());
setNextPrice("1");
setCurrentPrice("1");
return;
}
const zero = new DecimalBigNumber(0n, 0); const zero = new DecimalBigNumber(0n, 0);
const raw = new DecimalBigNumber(amountTop, balanceTop._decimals); const raw = new DecimalBigNumber(amountTop, balanceTop._decimals);
const amountInRaw = new DecimalBigNumber(raw._value.toBigInt(), balanceTop._decimals); const amountInRaw = new DecimalBigNumber(raw._value.toBigInt(), balanceTop._decimals);
const amountInWithFee = amountInRaw.mul(new DecimalBigNumber(997n, 3)); const amountInWithFee = amountInRaw.mul(new DecimalBigNumber(997n, 3));
const topAddress = getTokenAddress(chainId, tokenNameTop);
const bottomAddress = getTokenAddress(chainId, tokenNameBottom);
const amountIn = addressTop.toUpperCase() === tokenAddresses.token0.toUpperCase() ? pairReserves.reserve0 : pairReserves.reserve1; const amountIn = addressTop.toUpperCase() === tokenAddresses.token0.toUpperCase() ? pairReserves.reserve0 : pairReserves.reserve1;
const amountOut = addressBottom.toUpperCase() === tokenAddresses.token1.toUpperCase() ? pairReserves.reserve1 : pairReserves.reserve0; const amountOut = addressBottom.toUpperCase() === tokenAddresses.token1.toUpperCase() ? pairReserves.reserve1 : pairReserves.reserve0;
@ -119,15 +103,7 @@ const SwapContainer = ({
setAmountBottom(amountOut.sub(newAmountOut).toString()); setAmountBottom(amountOut.sub(newAmountOut).toString());
setNextPrice(denominator.div(newAmountOut).toString()) setNextPrice(denominator.div(newAmountOut).toString())
} }
}, [amountTop, addressTop, isWrapping, isUnwrapping]); }, [amountTop, addressTop]);
const buttonText = useMemo(() => {
let text = "Swap";
if (isWrapping) text = "Wrap";
else if (isUnwrapping) text = "Unwrap";
else if (pairAddress === EMPTY_ADDRESS) text = "Create Pool";
return text;
}, [isWrapping, isUnwrapping, pairAddress]);
const swapTokens = async () => { const swapTokens = async () => {
setIsPending(true); setIsPending(true);
@ -144,30 +120,14 @@ const SwapContainer = ({
const amountBDesired = BigInt(Math.round(parseFloat(amountBottom) * Math.pow(10, balanceBottom._decimals))); const amountBDesired = BigInt(Math.round(parseFloat(amountBottom) * Math.pow(10, balanceBottom._decimals)));
const amountBMin = amountBDesired * bigIntSlippage / one; const amountBMin = amountBDesired * bigIntSlippage / one;
if (isWrapping) { await swapExactTokensForTokens(
await depositNative(chainId, address, amountADesired);
} else if (isUnwrapping) {
await withdrawWeth(chainId, address, amountADesired);
} else {
const params = {
chainId, chainId,
amountADesired, amountADesired,
amountBMin, amountBMin,
tokenNameTop, [tokenNameTop, tokenNameBottom],
tokenNameBottom,
destination, destination,
address,
deadline deadline
}; );
if (topIsNative) {
await swapExactETHForTokens(params)
} else if (bottomIsNative) {
await swapExactTokensForETH(params)
} else {
await swapExactTokensForTokens(params);
}
}
await balanceRefetchTop(); await balanceRefetchTop();
await balanceRefetchBottom(); await balanceRefetchBottom();
@ -244,7 +204,6 @@ const SwapContainer = ({
owner={address} owner={address}
spender={dexAddresses.router} spender={dexAddresses.router}
decimals={balanceTop._decimals} decimals={balanceTop._decimals}
isNative={topIsNative}
approvalText={"Approve " + tokenNameTop} approvalText={"Approve " + tokenNameTop}
approvalPendingText={"Approving..."} approvalPendingText={"Approving..."}
connect={connect} connect={connect}
@ -264,10 +223,17 @@ const SwapContainer = ({
onClick={() => address === "" ? onClick={() => address === "" ?
connect() connect()
: :
(!isWrapping && !isUnwrapping) && pairAddress === EMPTY_ADDRESS ? setIsSwap(false) : swapTokens() pairAddress === "0x0000000000000000000000000000000000000000" ? setIsSwap(false) : swapTokens()
} }
> >
{address === "" ? "Connect" : buttonText } {address === "" ?
"Connect"
:
pairAddress === "0x0000000000000000000000000000000000000000" ?
"Create Pool"
:
"Swap"
}
</SecondaryButton> </SecondaryButton>
</TokenAllowanceGuard> </TokenAllowanceGuard>
</Box> </Box>

View File

@ -21,15 +21,9 @@ 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 { isNetworkLegacy } from "../../constants";
import { import { RESERVE_ADDRESSES, FTSO_ADDRESSES, STNK_ADDRESSES, GHST_ADDRESSES } from "../../constants/addresses";
RESERVE_ADDRESSES,
FTSO_ADDRESSES,
STNK_ADDRESSES,
GHST_ADDRESSES,
EMPTY_ADDRESS
} from "../../constants/addresses";
const TokenModal = ({ chainId, account, chainSymbol, listOpen, setListOpen, setTokenAddress }) => { const TokenModal = ({ chainId, account, listOpen, setListOpen, setTokenAddress }) => {
const isSmallScreen = useMediaQuery("(max-width: 599px)"); const isSmallScreen = useMediaQuery("(max-width: 599px)");
const isVerySmallScreen = useMediaQuery("(max-width: 425px)"); const isVerySmallScreen = useMediaQuery("(max-width: 425px)");
@ -45,7 +39,6 @@ const TokenModal = ({ chainId, account, chainSymbol, listOpen, setListOpen, setT
const { symbol: searchSymbol } = useTokenSymbol(chainId, address); const { symbol: searchSymbol } = useTokenSymbol(chainId, address);
const { balance: searchBalance } = useBalance(chainId, address, account); const { balance: searchBalance } = useBalance(chainId, address, account);
const { balance: nativeBalance } = useBalance(chainId, chainSymbol, account);
const { balance: reserveBalance } = useBalance(chainId, "RESERVE", account); const { balance: reserveBalance } = useBalance(chainId, "RESERVE", account);
const { balance: ftsoBalance } = useBalance(chainId, "FTSO", account); const { balance: ftsoBalance } = useBalance(chainId, "FTSO", account);
const { balance: stnkBalance } = useBalance(chainId, "STNK", account); const { balance: stnkBalance } = useBalance(chainId, "STNK", account);
@ -56,6 +49,9 @@ const TokenModal = ({ chainId, account, chainSymbol, listOpen, setListOpen, setT
const { symbol: stnkSymbol } = useTokenSymbol(chainId, "STNK"); const { symbol: stnkSymbol } = useTokenSymbol(chainId, "STNK");
const { symbol: ghstSymbol } = useTokenSymbol(chainId, "GHST"); const { symbol: ghstSymbol } = useTokenSymbol(chainId, "GHST");
const config = useConfig();
const nativeSymbol = config?.getClient()?.chain?.nativeCurrency?.symbol;
const searchToken = useMemo(() => { const searchToken = useMemo(() => {
return [{ return [{
name: searchSymbol, name: searchSymbol,
@ -67,15 +63,9 @@ const TokenModal = ({ chainId, account, chainSymbol, listOpen, setListOpen, setT
const knownTokens = useMemo(() => { const knownTokens = useMemo(() => {
return [ return [
{
name: chainSymbol,
icons: [chainSymbol],
balance: nativeBalance,
address: EMPTY_ADDRESS,
},
{ {
name: reserveSymbol, name: reserveSymbol,
icons: isNetworkLegacy(chainId) ? ["GDAI"] : [chainSymbol], icons: isNetworkLegacy(chainId) ? ["GDAI"] : [nativeSymbol],
balance: reserveBalance, balance: reserveBalance,
address: RESERVE_ADDRESSES[chainId] address: RESERVE_ADDRESSES[chainId]
}, },

View File

@ -22,7 +22,7 @@ import { isNetworkLegacy } from "../../../constants";
import { useLpValuation } from "../../../hooks/treasury"; import { useLpValuation } from "../../../hooks/treasury";
import { useTotalSupply, useTokenSymbol } from "../../../hooks/tokens"; import { useTotalSupply, useTokenSymbol } from "../../../hooks/tokens";
import { EMPTY_ADDRESS, FTSO_ADDRESSES } from "../../../constants/addresses"; import { RESERVE_ADDRESSES, FTSO_ADDRESSES } from "../../../constants/addresses";
const FarmPools = ({ chainId }) => { const FarmPools = ({ chainId }) => {
const isSmallScreen = useMediaQuery("(max-width: 775px)"); const isSmallScreen = useMediaQuery("(max-width: 775px)");
@ -42,7 +42,7 @@ const FarmPools = ({ chainId }) => {
tvl: reserveFtsoUniValuation, tvl: reserveFtsoUniValuation,
params: createSearchParams({ params: createSearchParams({
pool: "true", pool: "true",
from: `${EMPTY_ADDRESS}`, from: `${RESERVE_ADDRESSES[chainId]}`,
to: `${FTSO_ADDRESSES[chainId]}`, to: `${FTSO_ADDRESSES[chainId]}`,
}) })
}, },

View File

@ -1,4 +1,4 @@
export const tokenNameConverter = (chainId, name, address) => { export const tokenNameConverter = (chainId, name) => {
if (name?.toUpperCase() === "WETH") { if (name?.toUpperCase() === "WETH") {
switch (chainId) { switch (chainId) {
case 63: case 63:

View File

@ -142,12 +142,6 @@ export const getTokenAddress = (chainId, name) => {
case "WMETC": case "WMETC":
address = WETH_ADDRESSES[chainId]; address = WETH_ADDRESSES[chainId];
break; break;
case "ETH":
address = undefined;
break;
case "METC":
address = undefined;
break;
} }
return address; return address;
} }
@ -170,8 +164,6 @@ export const getTokenIcons = (chainId, address) => {
case FTSO_DAI_LP_ADDRESSES[chainId]: case FTSO_DAI_LP_ADDRESSES[chainId]:
icons = ["FTSO", "WETH"]; icons = ["FTSO", "WETH"];
break; break;
default:
icons = [""]
} }
return icons; return icons;
} }

View File

@ -9,7 +9,6 @@ import { DecimalBigNumber } from "../../helpers/DecimalBigNumber";
import { shorten } from "../../helpers"; import { shorten } from "../../helpers";
import { tokenNameConverter } from "../../helpers/tokenConverter"; import { tokenNameConverter } from "../../helpers/tokenConverter";
import { config } from "../../config"; import { config } from "../../config";
import { WETH_ADDRESSES } from "../../constants/addresses";
export const usePastVotes = (chainId, name, timepoint, address) => { export const usePastVotes = (chainId, name, timepoint, address) => {
const decimals = getTokenDecimals(name); const decimals = getTokenDecimals(name);
@ -61,29 +60,20 @@ export const useTotalSupply = (chainId, name) => {
}; };
export const useBalance = (chainId, name, address) => { export const useBalance = (chainId, name, address) => {
let contractAddress = getTokenAddress(chainId, name); const contractAddress = getTokenAddress(chainId, name);
let isNative = false; const { data, refetch, error } = useInnerBalance({
let requestObj = {
address, address,
chainId, chainId,
scopeKey: `balance-${contractAddress}-${address}-${chainId}`, scopeKey: `balance-${contractAddress}-${address}-${chainId}`,
}; token: contractAddress,
});
if (contractAddress !== undefined) {
requestObj.token = contractAddress;
} else {
contractAddress = WETH_ADDRESSES[chainId];
isNative = true;
}
const { data, refetch, error } = useInnerBalance(requestObj);
const balancePrepared = data ? data.value : 0n; const balancePrepared = data ? data.value : 0n;
const decimals = data ? data.decimals : getTokenDecimals(name); const decimals = data ? data.decimals : getTokenDecimals(name);
const balance = new DecimalBigNumber(balancePrepared, decimals); const balance = new DecimalBigNumber(balancePrepared, decimals);
return { balance, refetch, contractAddress, isNative }; return { balance, refetch, contractAddress };
} }
export const useAllowance = (chainId, name, owner, spender, decimals) => { export const useAllowance = (chainId, name, owner, spender, decimals) => {
@ -106,7 +96,6 @@ export const useAllowance = (chainId, name, owner, spender, decimals) => {
export const useTokenSymbol = (chainId, name) => { export const useTokenSymbol = (chainId, name) => {
const contractAddress = getTokenAddress(chainId, name); const contractAddress = getTokenAddress(chainId, name);
const { data, refetch } = useReadContract({ const { data, refetch } = useReadContract({
abi: getTokenAbi(name), abi: getTokenAbi(name),
address: contractAddress, address: contractAddress,

View File

@ -4,12 +4,14 @@ import { abi as UniswapV2Factory } from "../../abi/UniswapV2Factory.json";
import { UNISWAP_V2_FACTORY } from "../../constants/addresses"; import { UNISWAP_V2_FACTORY } from "../../constants/addresses";
export const useUniswapV2Pair = (chainId, factoryAddress, token0, token1) => { export const useUniswapV2Pair = (chainId, factoryAddress, token0, token1) => {
const t0 = token0 > token1 ? token0 : token1;
const t1 = token0 > token1 ? token1 : token0;
const { data, refetch } = useReadContract({ const { data, refetch } = useReadContract({
abi: UniswapV2Factory, abi: UniswapV2Factory,
address: factoryAddress, address: factoryAddress,
functionName: "getPair", functionName: "getPair",
args: [token0, token1], args: [token0, token1],
scopeKey: `getPair-${token0}-${token1}-${chainId}`, scopeKey: `getPair-${t0}-${t1}-${chainId}`,
chainId: chainId, chainId: chainId,
}); });

View File

@ -6,9 +6,7 @@ import { abi as Erc20Abi } from "../../abi/ERC20.json";
import { getTokenAddress } from "../helpers"; import { getTokenAddress } from "../helpers";
export const useUniswapV2PairReserves = (chainId, rawContractAddress) => { export const useUniswapV2PairReserves = (chainId, contractAddress) => {
const contractAddress = getTokenAddress(chainId, rawContractAddress);
const { data: pairReserves, refetch: pairReservesRefetch } = useReadContract({ const { data: pairReserves, refetch: pairReservesRefetch } = useReadContract({
abi: UniswapV2Pair, abi: UniswapV2Pair,
address: contractAddress, address: contractAddress,

View File

@ -2,189 +2,91 @@ import { simulateContract, writeContract, waitForTransactionReceipt } from "@wag
import toast from "react-hot-toast"; import toast from "react-hot-toast";
import { isNetworkLegacyType } from "../../constants"; import { isNetworkLegacyType } from "../../constants";
import { UNISWAP_V2_ROUTER, WETH_ADDRESSES } from "../../constants/addresses"; import { UNISWAP_V2_ROUTER } from "../../constants/addresses";
import { abi as RouterAbi } from "../../abi/UniswapV2Router.json"; import { abi as RouterAbi } from "../../abi/UniswapV2Router.json";
import { getTokenAddress } from "../helpers"; import { getTokenAddress } from "../helpers";
import { config } from "../../config"; import { config } from "../../config";
const swapMessages = { export const swapExactTokensForTokens = async (
chainId,
amountDesired,
amountMin,
pathRaw,
destination,
deadline
) => {
const path = pathRaw.map(tokenName => getTokenAddress(chainId, tokenName));
const args = [
amountDesired,
amountMin,
path,
destination,
deadline
];
const messages = {
replacedMsg: "Swap transaction was replaced. Wait for inclusion please.", replacedMsg: "Swap transaction was replaced. Wait for inclusion please.",
successMsg: "Swap executed successfully! Wait for balances update.", successMsg: "Swap executed successfully! Wait for balances update.",
errorMsg: "Swap tokens failed. Check logs for error detalization.", errorMsg: "Swap tokens failed. Check logs for error detalization.",
}; };
const addMessages = { await executeOnChainTransaction(
chainId,
"swapExactTokensForTokens",
args,
destination,
messages
);
}
export const addLiquidity = async (
chainId,
tokenA,
tokenB,
amountADesired,
amountBDesired,
amountAMin,
amountBMin,
to,
deadline,
) => {
const token1 = getTokenAddress(chainId, tokenA);
const token2 = getTokenAddress(chainId, tokenB);
const args = [
token1,
token2,
amountADesired,
amountBDesired,
amountAMin,
amountBMin,
to,
deadline
];
const messages = {
replacedMsg: "Add liquidity transaction was replaced. Wait for inclusion please.", replacedMsg: "Add liquidity transaction was replaced. Wait for inclusion please.",
successMsg: "Liquidity added successfully! You should get LP tokens to your wallet.", successMsg: "Liquidity added successfully! You should get LP tokens to your wallet.",
errorMsg: "Adding liquidity failed. Check logs for error detalization.", errorMsg: "Adding liquidity failed. Check logs for error detalization.",
}; };
export const swapExactETHForTokens = async ({ await executeOnChainTransaction(
chainId, chainId,
amountADesired, "addLiquidity",
amountBMin,
tokenNameTop,
tokenNameBottom,
destination,
deadline
}) => {
const args = [
amountBMin,
[WETH_ADDRESSES[chainId], getTokenAddress(chainId, tokenNameBottom)],
destination,
deadline
];
await executeOnChainTransaction({
chainId,
functionName: "swapExactETHForTokens",
args, args,
account: destination, to,
messages: swapMessages, messages
value: amountADesired, );
});
} }
export const swapExactTokensForETH = async ({ const executeOnChainTransaction = async (
chainId,
amountADesired,
amountBMin,
tokenNameTop,
tokenNameBottom,
destination,
address,
deadline
}) => {
const args = [
amountADesired,
amountBMin,
[getTokenAddress(chainId, tokenNameTop), WETH_ADDRESSES[chainId]],
destination,
deadline
];
await executeOnChainTransaction({
chainId,
functionName: "swapExactTokensForETH",
args,
account: address,
messages: swapMessages,
});
}
export const swapExactTokensForTokens = async ({
chainId,
amountADesired,
amountBMin,
tokenNameTop,
tokenNameBottom,
destination,
address,
deadline
}) => {
const args = [
amountADesired,
amountBMin,
[getTokenAddress(chainId, tokenNameTop), getTokenAddress(chainId, tokenNameBottom)],
destination,
deadline
];
await executeOnChainTransaction({
chainId,
functionName: "swapExactTokensForTokens",
args,
account: address,
messages: swapMessages
});
}
export const addLiquidity = async ({
chainId,
tokenNameTop,
tokenNameBottom,
amountADesired,
amountBDesired,
amountAMin,
amountBMin,
address,
destination,
deadline,
}) => {
const args = [
getTokenAddress(chainId, tokenNameTop),
getTokenAddress(chainId, tokenNameBottom),
amountADesired,
amountBDesired,
amountAMin,
amountBMin,
destination,
deadline
];
await executeOnChainTransaction({
chainId,
functionName: "addLiquidity",
args,
account: address,
messages: addMessages
});
}
export const addLiquidityETH = async ({
chainId,
tokenNameTop,
tokenNameBottom,
amountADesired,
amountBDesired,
amountAMin,
amountBMin,
address,
destination,
deadline,
}) => {
let token = getTokenAddress(chainId, tokenNameTop);
let amountTokenDesired = amountADesired;
let amountETHDesired = amountBDesired;
let amountTokenMin = amountAMin;
let amountETHMin = amountBMin;
if (token === undefined) {
token = getTokenAddress(chainId, tokenNameBottom);
amountTokenDesired = amountBDesired;
amountETHDesired = amountADesired;
amountTokenMin = amountBMin;
amountETHMin = amountAMin;
}
const args = [
token,
amountTokenDesired,
amountTokenMin,
amountETHMin,
destination,
deadline
];
await executeOnChainTransaction({
chainId,
functionName: "addLiquidityETH",
args,
account: address,
messages: addMessages,
value: amountETHDesired,
});
}
const executeOnChainTransaction = async ({
chainId, chainId,
functionName, functionName,
args, args,
account, account,
messages, messages
value, ) => {
}) => {
try { try {
const { request } = await simulateContract(config, { const { request } = await simulateContract(config, {
abi: RouterAbi, abi: RouterAbi,
@ -194,7 +96,6 @@ const executeOnChainTransaction = async ({
account, account,
chainId, chainId,
type: isNetworkLegacyType(chainId) ? 'legacy' : 'eip1559', type: isNetworkLegacyType(chainId) ? 'legacy' : 'eip1559',
value: value ?? 0n,
}); });
const txHash = await writeContract(config, request); const txHash = await writeContract(config, request);