integrate native coin into dex
Signed-off-by: Uncle Fatso <uncle.fatso@ghostchain.io>
This commit is contained in:
parent
7be03aaa9f
commit
8d23d55ae2
@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "ghost-dao-interface",
|
||||
"private": true,
|
||||
"version": "0.6.4",
|
||||
"version": "0.6.5",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"dev": "vite",
|
||||
|
||||
@ -215,7 +215,7 @@ function App() {
|
||||
: <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="/dex/:name" element={<Dex connect={tryConnectInjected} address={address} chainId={addressChainId ? addressChainId : chainId} />} />
|
||||
<Route path="/dex/:name" element={<Dex 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/create" element={<NewProposal config={config} connect={tryConnectInjected} address={address} chainId={addressChainId ? addressChainId : chainId} />} />}
|
||||
|
||||
@ -58,6 +58,7 @@ export const TokenAllowanceGuard = ({
|
||||
height = "auto",
|
||||
spendAmount,
|
||||
tokenName,
|
||||
isNative,
|
||||
owner,
|
||||
spender,
|
||||
decimals,
|
||||
@ -88,7 +89,7 @@ export const TokenAllowanceGuard = ({
|
||||
);
|
||||
}
|
||||
|
||||
if (allowance && spendAmount && allowance.lt(spendAmount))
|
||||
if (!isNative && allowance && spendAmount && allowance.lt(spendAmount))
|
||||
return (
|
||||
<Grid container alignItems="center">
|
||||
<Grid item xs={12} sm={isVertical ? 12 : 8}>
|
||||
|
||||
@ -16,6 +16,7 @@ import { formatCurrency, formatNumber } from "../../../helpers";
|
||||
import { DecimalBigNumber } from "../../../helpers/DecimalBigNumber"
|
||||
import { tokenNameConverter } from "../../../helpers/tokenConverter";
|
||||
import { isNetworkLegacy } from "../../../constants";
|
||||
import { EMPTY_ADDRESS } from "../../../constants/addresses";
|
||||
|
||||
import GhostStyledIcon from "../../Icon/GhostIcon";
|
||||
import TokenStack from "../../TokenStack/TokenStack";
|
||||
@ -305,7 +306,7 @@ export const Tokens = ({ address, tokens, onClose }) => {
|
||||
const tokenProps = (token) => ({
|
||||
...token,
|
||||
expanded: expanded === token.symbol,
|
||||
reserveAddress: tokens.reserve.address,
|
||||
reserveAddress: EMPTY_ADDRESS,
|
||||
onChangeExpanded: (e, isExpanded) => setExpanded(isExpanded ? token.symbol : null),
|
||||
onAddTokenToWallet: () => addTokenToWallet(token, address),
|
||||
onClose: () => onClose(),
|
||||
|
||||
@ -1,5 +1,7 @@
|
||||
import { NetworkId } from "../constants";
|
||||
|
||||
export const EMPTY_ADDRESS = "0x0000000000000000000000000000000000000000";
|
||||
|
||||
export const STAKING_ADDRESSES = {
|
||||
[NetworkId.TESTNET_SEPOLIA]: "0xC2C579631Bf6daA93252154080fecfd68c6aa506",
|
||||
[NetworkId.TESTNET_HOODI]: "0x25F62eDc6C89FF84E957C22336A35d2dfc861a86",
|
||||
|
||||
@ -10,7 +10,7 @@ import {
|
||||
useTheme,
|
||||
} from "@mui/material";
|
||||
import SettingsIcon from '@mui/icons-material/Settings';
|
||||
import { useEffect, useState } from "react";
|
||||
import { useEffect, useMemo, useState } from "react";
|
||||
import { useParams, useLocation, useSearchParams } from "react-router-dom";
|
||||
import { Helmet } from "react-helmet";
|
||||
import ReactGA from "react-ga4";
|
||||
@ -28,14 +28,17 @@ import {
|
||||
UNISWAP_V2_FACTORY,
|
||||
RESERVE_ADDRESSES,
|
||||
FTSO_ADDRESSES,
|
||||
EMPTY_ADDRESS,
|
||||
WETH_ADDRESSES,
|
||||
} from "../../constants/addresses";
|
||||
import { useTokenSymbol } from "../../hooks/tokens";
|
||||
import { getTokenAddress } from "../../hooks/helpers";
|
||||
|
||||
import PoolContainer from "./PoolContainer";
|
||||
import SwapContainer from "./SwapContainer";
|
||||
import TokenModal from "./TokenModal";
|
||||
|
||||
const Dex = ({ chainId, address, connect }) => {
|
||||
const Dex = ({ chainId, address, connect, config }) => {
|
||||
const location = useLocation();
|
||||
const pathname = useParams();
|
||||
|
||||
@ -58,11 +61,44 @@ const Dex = ({ chainId, address, connect }) => {
|
||||
const [actualDestinationAddress, setActualDestinationAddress] = useState(localStorage.getItem("dex-destination"));
|
||||
const [destinationAddress, setDestinationAddress] = useState(actualDestinationAddress);
|
||||
|
||||
const [tokenAddressTop, setTokenAddressTop] = useState(RESERVE_ADDRESSES[chainId]);
|
||||
const [tokenAddressTop, setTokenAddressTop] = useState(EMPTY_ADDRESS);
|
||||
const [tokenAddressBottom, setTokenAddressBottom] = useState(FTSO_ADDRESSES[chainId]);
|
||||
|
||||
const { symbol: tokenNameTop } = useTokenSymbol(chainId, tokenAddressTop);
|
||||
const { symbol: tokenNameBottom } = useTokenSymbol(chainId, tokenAddressBottom);
|
||||
const { symbol: tokenNameTopInner } = useTokenSymbol(chainId, tokenAddressTop);
|
||||
const { symbol: tokenNameBottomInner } = 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(() => {
|
||||
if (currentQueryParameters.has("pool")) {
|
||||
@ -77,8 +113,8 @@ const Dex = ({ chainId, address, connect }) => {
|
||||
setTokenAddressTop(currentQueryParameters.get("from"));
|
||||
newQueryParameters.set("from", currentQueryParameters.get("from"));
|
||||
} else {
|
||||
setTokenAddressTop(RESERVE_ADDRESSES[chainId]);
|
||||
newQueryParameters.set("from", RESERVE_ADDRESSES[chainId]);
|
||||
setTokenAddressTop(EMPTY_ADDRESS);
|
||||
newQueryParameters.set("from", EMPTY_ADDRESS);
|
||||
}
|
||||
|
||||
if (currentQueryParameters.has("to")) {
|
||||
@ -94,7 +130,7 @@ const Dex = ({ chainId, address, connect }) => {
|
||||
|
||||
useEffect(() => {
|
||||
ReactGA.send({ hitType: "pageview", page: location.pathname + location.search });
|
||||
}, [location])
|
||||
}, [location]);
|
||||
|
||||
const dexAddresses = {
|
||||
router: UNISWAP_V2_ROUTER[chainId],
|
||||
@ -115,7 +151,7 @@ const Dex = ({ chainId, address, connect }) => {
|
||||
}
|
||||
|
||||
const changeSwapTab = (swap) => {
|
||||
if (swap) newQueryParameters.delete("pool");
|
||||
if (swap || (isWrapping || isUnwrapping)) newQueryParameters.delete("pool");
|
||||
else newQueryParameters.set("pool", true);
|
||||
newQueryParameters.set("from", currentQueryParameters.get("from"));
|
||||
newQueryParameters.set("to", currentQueryParameters.get("to"));
|
||||
@ -315,6 +351,7 @@ const Dex = ({ chainId, address, connect }) => {
|
||||
</Modal>
|
||||
|
||||
<TokenModal
|
||||
chainSymbol={chainSymbol}
|
||||
account={address}
|
||||
chainId={chainId}
|
||||
listOpen={topTokenListOpen}
|
||||
@ -322,6 +359,7 @@ const Dex = ({ chainId, address, connect }) => {
|
||||
setTokenAddress={setInnerTokenAddressTop}
|
||||
/>
|
||||
<TokenModal
|
||||
chainSymbol={chainSymbol}
|
||||
account={address}
|
||||
chainId={chainId}
|
||||
listOpen={bottomTokenListOpen}
|
||||
@ -373,6 +411,8 @@ const Dex = ({ chainId, address, connect }) => {
|
||||
setBottomTokenListOpen={setBottomTokenListOpen}
|
||||
setIsSwap={setIsSwap}
|
||||
formatDecimals={formatDecimals}
|
||||
isWrapping={isWrapping}
|
||||
isUnwrapping={isUnwrapping}
|
||||
/>
|
||||
:
|
||||
<PoolContainer
|
||||
|
||||
@ -12,7 +12,12 @@ import { DecimalBigNumber } from "../../helpers/DecimalBigNumber";
|
||||
import { formatNumber, formatCurrency, bigIntSqrt } from "../../helpers";
|
||||
|
||||
import { useBalance, useTotalSupply } from "../../hooks/tokens";
|
||||
import { useUniswapV2Pair, useUniswapV2PairReserves, addLiquidity } from "../../hooks/uniswapv2";
|
||||
import {
|
||||
useUniswapV2Pair,
|
||||
useUniswapV2PairReserves,
|
||||
addLiquidity,
|
||||
addLiquidityETH,
|
||||
} from "../../hooks/uniswapv2";
|
||||
|
||||
const PoolContainer = ({
|
||||
tokenNameTop,
|
||||
@ -27,7 +32,7 @@ const PoolContainer = ({
|
||||
secondsToWait,
|
||||
setTopTokenListOpen,
|
||||
setBottomTokenListOpen,
|
||||
formatDecimals
|
||||
formatDecimals,
|
||||
}) => {
|
||||
const theme = useTheme();
|
||||
const isSmallScreen = useMediaQuery("(max-width: 456px)");
|
||||
@ -40,11 +45,13 @@ const PoolContainer = ({
|
||||
balance: balanceTop,
|
||||
refetch: balanceRefetchTop,
|
||||
contractAddress: addressTop,
|
||||
isNative: topIsNative,
|
||||
} = useBalance(chainId, tokenNameTop, address);
|
||||
const {
|
||||
balance: balanceBottom,
|
||||
refetch: balanceRefetchBottom,
|
||||
contractAddress: addressBottom,
|
||||
isNative: bottomIsNative,
|
||||
} = useBalance(chainId, tokenNameBottom, address);
|
||||
|
||||
const {
|
||||
@ -142,7 +149,7 @@ const PoolContainer = ({
|
||||
const amountAMin = amountADesired * bigIntSlippage / one;
|
||||
const amountBMin = amountBDesired * bigIntSlippage / one;
|
||||
|
||||
await addLiquidity(
|
||||
const params = {
|
||||
chainId,
|
||||
tokenNameTop,
|
||||
tokenNameBottom,
|
||||
@ -150,9 +157,16 @@ const PoolContainer = ({
|
||||
amountBDesired,
|
||||
amountAMin,
|
||||
amountBMin,
|
||||
address,
|
||||
destination,
|
||||
deadline,
|
||||
);
|
||||
}
|
||||
|
||||
if (topIsNative || bottomIsNative) {
|
||||
await addLiquidityETH(params)
|
||||
} else {
|
||||
await addLiquidity(params);
|
||||
}
|
||||
|
||||
await balanceRefetchTop();
|
||||
await balanceRefetchBottom();
|
||||
@ -233,6 +247,7 @@ const PoolContainer = ({
|
||||
owner={address}
|
||||
spender={dexAddresses.router}
|
||||
decimals={balanceTop._decimals}
|
||||
isNative={topIsNative}
|
||||
approvalText={"Approve " + tokenNameTop}
|
||||
approvalPendingText={"Approving..."}
|
||||
connect={connect}
|
||||
@ -245,6 +260,7 @@ const PoolContainer = ({
|
||||
owner={address}
|
||||
spender={dexAddresses.router}
|
||||
decimals={balanceBottom._decimals}
|
||||
isNative={bottomIsNative}
|
||||
approvalText={"Approve " + tokenNameBottom}
|
||||
approvalPendingText={"Approving..."}
|
||||
connect={connect}
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import { useState, useEffect } from "react";
|
||||
import { useState, useMemo, useEffect } from "react";
|
||||
import { Box, Typography, useTheme, useMediaQuery } from "@mui/material";
|
||||
import toast from "react-hot-toast";
|
||||
|
||||
@ -13,8 +13,16 @@ import { DecimalBigNumber } from "../../helpers/DecimalBigNumber";
|
||||
import { prettifySecondsInDays } from "../../helpers/timeUtil";
|
||||
|
||||
import { getTokenAddress } from "../../hooks/helpers";
|
||||
import { useBalance } from "../../hooks/tokens";
|
||||
import { useUniswapV2Pair, useUniswapV2PairReserves, swapExactTokensForTokens } from "../../hooks/uniswapv2";
|
||||
import { useBalance, depositNative, withdrawWeth } from "../../hooks/tokens";
|
||||
import {
|
||||
useUniswapV2Pair,
|
||||
useUniswapV2PairReserves,
|
||||
swapExactTokensForTokens,
|
||||
swapExactETHForTokens,
|
||||
swapExactTokensForETH,
|
||||
} from "../../hooks/uniswapv2";
|
||||
|
||||
import { EMPTY_ADDRESS } from "../../constants/addresses";
|
||||
|
||||
const SwapContainer = ({
|
||||
tokenNameTop,
|
||||
@ -30,7 +38,9 @@ const SwapContainer = ({
|
||||
destination,
|
||||
secondsToWait,
|
||||
setIsSwap,
|
||||
formatDecimals
|
||||
formatDecimals,
|
||||
isWrapping,
|
||||
isUnwrapping,
|
||||
}) => {
|
||||
const theme = useTheme();
|
||||
const isSmallScreen = useMediaQuery("(max-width: 456px)");
|
||||
@ -46,12 +56,14 @@ const SwapContainer = ({
|
||||
balance: balanceTop,
|
||||
refetch: balanceRefetchTop,
|
||||
contractAddress: addressTop,
|
||||
isNative: topIsNative,
|
||||
} = useBalance(chainId, tokenNameTop, address);
|
||||
|
||||
const {
|
||||
balance: balanceBottom,
|
||||
refetch: balanceRefetchBottom,
|
||||
contractAddress: addressBottom,
|
||||
isNative: bottomIsNative,
|
||||
} = useBalance(chainId, tokenNameBottom, address);
|
||||
|
||||
const {
|
||||
@ -75,14 +87,18 @@ const SwapContainer = ({
|
||||
const setMax = () => setAmountTop(balanceTop.toString());
|
||||
|
||||
useEffect(() => {
|
||||
if (isWrapping || isUnwrapping) {
|
||||
setAmountBottom(amountTop.toString());
|
||||
setNextPrice("1");
|
||||
setCurrentPrice("1");
|
||||
return;
|
||||
}
|
||||
|
||||
const zero = new DecimalBigNumber(0n, 0);
|
||||
const raw = new DecimalBigNumber(amountTop, balanceTop._decimals);
|
||||
const amountInRaw = new DecimalBigNumber(raw._value.toBigInt(), balanceTop._decimals);
|
||||
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 amountOut = addressBottom.toUpperCase() === tokenAddresses.token1.toUpperCase() ? pairReserves.reserve1 : pairReserves.reserve0;
|
||||
|
||||
@ -103,7 +119,15 @@ const SwapContainer = ({
|
||||
setAmountBottom(amountOut.sub(newAmountOut).toString());
|
||||
setNextPrice(denominator.div(newAmountOut).toString())
|
||||
}
|
||||
}, [amountTop, addressTop]);
|
||||
}, [amountTop, addressTop, isWrapping, isUnwrapping]);
|
||||
|
||||
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 () => {
|
||||
setIsPending(true);
|
||||
@ -120,14 +144,30 @@ const SwapContainer = ({
|
||||
const amountBDesired = BigInt(Math.round(parseFloat(amountBottom) * Math.pow(10, balanceBottom._decimals)));
|
||||
const amountBMin = amountBDesired * bigIntSlippage / one;
|
||||
|
||||
await swapExactTokensForTokens(
|
||||
chainId,
|
||||
amountADesired,
|
||||
amountBMin,
|
||||
[tokenNameTop, tokenNameBottom],
|
||||
destination,
|
||||
deadline
|
||||
);
|
||||
if (isWrapping) {
|
||||
await depositNative(chainId, address, amountADesired);
|
||||
} else if (isUnwrapping) {
|
||||
await withdrawWeth(chainId, address, amountADesired);
|
||||
} else {
|
||||
const params = {
|
||||
chainId,
|
||||
amountADesired,
|
||||
amountBMin,
|
||||
tokenNameTop,
|
||||
tokenNameBottom,
|
||||
destination,
|
||||
address,
|
||||
deadline
|
||||
};
|
||||
|
||||
if (topIsNative) {
|
||||
await swapExactETHForTokens(params)
|
||||
} else if (bottomIsNative) {
|
||||
await swapExactTokensForETH(params)
|
||||
} else {
|
||||
await swapExactTokensForTokens(params);
|
||||
}
|
||||
}
|
||||
|
||||
await balanceRefetchTop();
|
||||
await balanceRefetchBottom();
|
||||
@ -204,6 +244,7 @@ const SwapContainer = ({
|
||||
owner={address}
|
||||
spender={dexAddresses.router}
|
||||
decimals={balanceTop._decimals}
|
||||
isNative={topIsNative}
|
||||
approvalText={"Approve " + tokenNameTop}
|
||||
approvalPendingText={"Approving..."}
|
||||
connect={connect}
|
||||
@ -223,17 +264,10 @@ const SwapContainer = ({
|
||||
onClick={() => address === "" ?
|
||||
connect()
|
||||
:
|
||||
pairAddress === "0x0000000000000000000000000000000000000000" ? setIsSwap(false) : swapTokens()
|
||||
(!isWrapping && !isUnwrapping) && pairAddress === EMPTY_ADDRESS ? setIsSwap(false) : swapTokens()
|
||||
}
|
||||
>
|
||||
{address === "" ?
|
||||
"Connect"
|
||||
:
|
||||
pairAddress === "0x0000000000000000000000000000000000000000" ?
|
||||
"Create Pool"
|
||||
:
|
||||
"Swap"
|
||||
}
|
||||
{address === "" ? "Connect" : buttonText }
|
||||
</SecondaryButton>
|
||||
</TokenAllowanceGuard>
|
||||
</Box>
|
||||
|
||||
@ -21,9 +21,15 @@ import { DecimalBigNumber } from "../../helpers/DecimalBigNumber";
|
||||
import { formatNumber } from "../../helpers/";
|
||||
import { useBalance, useTokenSymbol } from "../../hooks/tokens";
|
||||
import { isNetworkLegacy } from "../../constants";
|
||||
import { RESERVE_ADDRESSES, FTSO_ADDRESSES, STNK_ADDRESSES, GHST_ADDRESSES } from "../../constants/addresses";
|
||||
import {
|
||||
RESERVE_ADDRESSES,
|
||||
FTSO_ADDRESSES,
|
||||
STNK_ADDRESSES,
|
||||
GHST_ADDRESSES,
|
||||
EMPTY_ADDRESS
|
||||
} from "../../constants/addresses";
|
||||
|
||||
const TokenModal = ({ chainId, account, listOpen, setListOpen, setTokenAddress }) => {
|
||||
const TokenModal = ({ chainId, account, chainSymbol, listOpen, setListOpen, setTokenAddress }) => {
|
||||
const isSmallScreen = useMediaQuery("(max-width: 599px)");
|
||||
const isVerySmallScreen = useMediaQuery("(max-width: 425px)");
|
||||
|
||||
@ -39,6 +45,7 @@ const TokenModal = ({ chainId, account, listOpen, setListOpen, setTokenAddress }
|
||||
const { symbol: searchSymbol } = useTokenSymbol(chainId, address);
|
||||
const { balance: searchBalance } = useBalance(chainId, address, account);
|
||||
|
||||
const { balance: nativeBalance } = useBalance(chainId, chainSymbol, account);
|
||||
const { balance: reserveBalance } = useBalance(chainId, "RESERVE", account);
|
||||
const { balance: ftsoBalance } = useBalance(chainId, "FTSO", account);
|
||||
const { balance: stnkBalance } = useBalance(chainId, "STNK", account);
|
||||
@ -49,9 +56,6 @@ const TokenModal = ({ chainId, account, listOpen, setListOpen, setTokenAddress }
|
||||
const { symbol: stnkSymbol } = useTokenSymbol(chainId, "STNK");
|
||||
const { symbol: ghstSymbol } = useTokenSymbol(chainId, "GHST");
|
||||
|
||||
const config = useConfig();
|
||||
const nativeSymbol = config?.getClient()?.chain?.nativeCurrency?.symbol;
|
||||
|
||||
const searchToken = useMemo(() => {
|
||||
return [{
|
||||
name: searchSymbol,
|
||||
@ -63,9 +67,15 @@ const TokenModal = ({ chainId, account, listOpen, setListOpen, setTokenAddress }
|
||||
|
||||
const knownTokens = useMemo(() => {
|
||||
return [
|
||||
{
|
||||
name: chainSymbol,
|
||||
icons: [chainSymbol],
|
||||
balance: nativeBalance,
|
||||
address: EMPTY_ADDRESS,
|
||||
},
|
||||
{
|
||||
name: reserveSymbol,
|
||||
icons: isNetworkLegacy(chainId) ? ["GDAI"] : [nativeSymbol],
|
||||
icons: isNetworkLegacy(chainId) ? ["GDAI"] : [chainSymbol],
|
||||
balance: reserveBalance,
|
||||
address: RESERVE_ADDRESSES[chainId]
|
||||
},
|
||||
|
||||
@ -22,7 +22,7 @@ import { isNetworkLegacy } from "../../../constants";
|
||||
import { useLpValuation } from "../../../hooks/treasury";
|
||||
import { useTotalSupply, useTokenSymbol } from "../../../hooks/tokens";
|
||||
|
||||
import { RESERVE_ADDRESSES, FTSO_ADDRESSES } from "../../../constants/addresses";
|
||||
import { EMPTY_ADDRESS, FTSO_ADDRESSES } from "../../../constants/addresses";
|
||||
|
||||
const FarmPools = ({ chainId }) => {
|
||||
const isSmallScreen = useMediaQuery("(max-width: 775px)");
|
||||
@ -42,7 +42,7 @@ const FarmPools = ({ chainId }) => {
|
||||
tvl: reserveFtsoUniValuation,
|
||||
params: createSearchParams({
|
||||
pool: "true",
|
||||
from: `${RESERVE_ADDRESSES[chainId]}`,
|
||||
from: `${EMPTY_ADDRESS}`,
|
||||
to: `${FTSO_ADDRESSES[chainId]}`,
|
||||
})
|
||||
},
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
export const tokenNameConverter = (chainId, name) => {
|
||||
export const tokenNameConverter = (chainId, name, address) => {
|
||||
if (name?.toUpperCase() === "WETH") {
|
||||
switch (chainId) {
|
||||
case 63:
|
||||
|
||||
@ -142,6 +142,12 @@ export const getTokenAddress = (chainId, name) => {
|
||||
case "WMETC":
|
||||
address = WETH_ADDRESSES[chainId];
|
||||
break;
|
||||
case "ETH":
|
||||
address = undefined;
|
||||
break;
|
||||
case "METC":
|
||||
address = undefined;
|
||||
break;
|
||||
}
|
||||
return address;
|
||||
}
|
||||
|
||||
@ -9,6 +9,7 @@ import { DecimalBigNumber } from "../../helpers/DecimalBigNumber";
|
||||
import { shorten } from "../../helpers";
|
||||
import { tokenNameConverter } from "../../helpers/tokenConverter";
|
||||
import { config } from "../../config";
|
||||
import { WETH_ADDRESSES } from "../../constants/addresses";
|
||||
|
||||
export const usePastVotes = (chainId, name, timepoint, address) => {
|
||||
const decimals = getTokenDecimals(name);
|
||||
@ -60,20 +61,29 @@ export const useTotalSupply = (chainId, name) => {
|
||||
};
|
||||
|
||||
export const useBalance = (chainId, name, address) => {
|
||||
const contractAddress = getTokenAddress(chainId, name);
|
||||
const { data, refetch, error } = useInnerBalance({
|
||||
let contractAddress = getTokenAddress(chainId, name);
|
||||
let isNative = false;
|
||||
|
||||
let requestObj = {
|
||||
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 decimals = data ? data.decimals : getTokenDecimals(name);
|
||||
|
||||
const balance = new DecimalBigNumber(balancePrepared, decimals);
|
||||
|
||||
return { balance, refetch, contractAddress };
|
||||
return { balance, refetch, contractAddress, isNative };
|
||||
}
|
||||
|
||||
export const useAllowance = (chainId, name, owner, spender, decimals) => {
|
||||
@ -96,6 +106,7 @@ export const useAllowance = (chainId, name, owner, spender, decimals) => {
|
||||
|
||||
export const useTokenSymbol = (chainId, name) => {
|
||||
const contractAddress = getTokenAddress(chainId, name);
|
||||
|
||||
const { data, refetch } = useReadContract({
|
||||
abi: getTokenAbi(name),
|
||||
address: contractAddress,
|
||||
|
||||
@ -4,14 +4,12 @@ import { abi as UniswapV2Factory } from "../../abi/UniswapV2Factory.json";
|
||||
import { UNISWAP_V2_FACTORY } from "../../constants/addresses";
|
||||
|
||||
export const useUniswapV2Pair = (chainId, factoryAddress, token0, token1) => {
|
||||
const t0 = token0 > token1 ? token0 : token1;
|
||||
const t1 = token0 > token1 ? token1 : token0;
|
||||
const { data, refetch } = useReadContract({
|
||||
abi: UniswapV2Factory,
|
||||
address: factoryAddress,
|
||||
functionName: "getPair",
|
||||
args: [token0, token1],
|
||||
scopeKey: `getPair-${t0}-${t1}-${chainId}`,
|
||||
scopeKey: `getPair-${token0}-${token1}-${chainId}`,
|
||||
chainId: chainId,
|
||||
});
|
||||
|
||||
|
||||
@ -2,91 +2,189 @@ import { simulateContract, writeContract, waitForTransactionReceipt } from "@wag
|
||||
import toast from "react-hot-toast";
|
||||
|
||||
import { isNetworkLegacyType } from "../../constants";
|
||||
import { UNISWAP_V2_ROUTER } from "../../constants/addresses";
|
||||
import { UNISWAP_V2_ROUTER, WETH_ADDRESSES } from "../../constants/addresses";
|
||||
import { abi as RouterAbi } from "../../abi/UniswapV2Router.json";
|
||||
import { getTokenAddress } from "../helpers";
|
||||
|
||||
import { config } from "../../config";
|
||||
|
||||
export const swapExactTokensForTokens = async (
|
||||
const swapMessages = {
|
||||
replacedMsg: "Swap transaction was replaced. Wait for inclusion please.",
|
||||
successMsg: "Swap executed successfully! Wait for balances update.",
|
||||
errorMsg: "Swap tokens failed. Check logs for error detalization.",
|
||||
};
|
||||
|
||||
const addMessages = {
|
||||
replacedMsg: "Add liquidity transaction was replaced. Wait for inclusion please.",
|
||||
successMsg: "Liquidity added successfully! You should get LP tokens to your wallet.",
|
||||
errorMsg: "Adding liquidity failed. Check logs for error detalization.",
|
||||
};
|
||||
|
||||
export const swapExactETHForTokens = async ({
|
||||
chainId,
|
||||
amountDesired,
|
||||
amountMin,
|
||||
pathRaw,
|
||||
amountADesired,
|
||||
amountBMin,
|
||||
tokenNameTop,
|
||||
tokenNameBottom,
|
||||
destination,
|
||||
deadline
|
||||
) => {
|
||||
|
||||
const path = pathRaw.map(tokenName => getTokenAddress(chainId, tokenName));
|
||||
}) => {
|
||||
const args = [
|
||||
amountDesired,
|
||||
amountMin,
|
||||
path,
|
||||
amountBMin,
|
||||
[WETH_ADDRESSES[chainId], getTokenAddress(chainId, tokenNameBottom)],
|
||||
destination,
|
||||
deadline
|
||||
];
|
||||
|
||||
const messages = {
|
||||
replacedMsg: "Swap transaction was replaced. Wait for inclusion please.",
|
||||
successMsg: "Swap executed successfully! Wait for balances update.",
|
||||
errorMsg: "Swap tokens failed. Check logs for error detalization.",
|
||||
};
|
||||
|
||||
await executeOnChainTransaction(
|
||||
await executeOnChainTransaction({
|
||||
chainId,
|
||||
"swapExactTokensForTokens",
|
||||
functionName: "swapExactETHForTokens",
|
||||
args,
|
||||
destination,
|
||||
messages
|
||||
);
|
||||
account: destination,
|
||||
messages: swapMessages,
|
||||
value: amountADesired,
|
||||
});
|
||||
}
|
||||
|
||||
export const addLiquidity = async (
|
||||
export const swapExactTokensForETH = async ({
|
||||
chainId,
|
||||
tokenA,
|
||||
tokenB,
|
||||
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,
|
||||
to,
|
||||
address,
|
||||
destination,
|
||||
deadline,
|
||||
) => {
|
||||
const token1 = getTokenAddress(chainId, tokenA);
|
||||
const token2 = getTokenAddress(chainId, tokenB);
|
||||
|
||||
}) => {
|
||||
const args = [
|
||||
token1,
|
||||
token2,
|
||||
getTokenAddress(chainId, tokenNameTop),
|
||||
getTokenAddress(chainId, tokenNameBottom),
|
||||
amountADesired,
|
||||
amountBDesired,
|
||||
amountAMin,
|
||||
amountBMin,
|
||||
to,
|
||||
destination,
|
||||
deadline
|
||||
];
|
||||
const messages = {
|
||||
replacedMsg: "Add liquidity transaction was replaced. Wait for inclusion please.",
|
||||
successMsg: "Liquidity added successfully! You should get LP tokens to your wallet.",
|
||||
errorMsg: "Adding liquidity failed. Check logs for error detalization.",
|
||||
};
|
||||
|
||||
await executeOnChainTransaction(
|
||||
await executeOnChainTransaction({
|
||||
chainId,
|
||||
"addLiquidity",
|
||||
functionName: "addLiquidity",
|
||||
args,
|
||||
to,
|
||||
messages
|
||||
);
|
||||
account: address,
|
||||
messages: addMessages
|
||||
});
|
||||
}
|
||||
|
||||
const executeOnChainTransaction = async (
|
||||
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,
|
||||
functionName,
|
||||
args,
|
||||
account,
|
||||
messages
|
||||
) => {
|
||||
messages,
|
||||
value,
|
||||
}) => {
|
||||
try {
|
||||
const { request } = await simulateContract(config, {
|
||||
abi: RouterAbi,
|
||||
@ -96,6 +194,7 @@ const executeOnChainTransaction = async (
|
||||
account,
|
||||
chainId,
|
||||
type: isNetworkLegacyType(chainId) ? 'legacy' : 'eip1559',
|
||||
value: value ?? 0n,
|
||||
});
|
||||
|
||||
const txHash = await writeContract(config, request);
|
||||
|
||||
Loading…
Reference in New Issue
Block a user