diff --git a/package.json b/package.json
index ed76c59..312b5a3 100644
--- a/package.json
+++ b/package.json
@@ -1,7 +1,7 @@
{
"name": "ghost-dao-interface",
"private": true,
- "version": "0.6.4",
+ "version": "0.6.5",
"type": "module",
"scripts": {
"dev": "vite",
diff --git a/src/App.jsx b/src/App.jsx
index 145201c..2a94595 100644
--- a/src/App.jsx
+++ b/src/App.jsx
@@ -215,7 +215,7 @@ function App() {
: } />
}
} />
- } />
+ } />
{isGovernanceAvailable(chainId, addressChainId) && } />}
{isGovernanceAvailable(chainId, addressChainId) && } />}
{isGovernanceAvailable(chainId, addressChainId) && } />}
diff --git a/src/components/TokenAllowanceGuard/TokenAllowanceGuard.jsx b/src/components/TokenAllowanceGuard/TokenAllowanceGuard.jsx
index 6e29b00..6da3955 100644
--- a/src/components/TokenAllowanceGuard/TokenAllowanceGuard.jsx
+++ b/src/components/TokenAllowanceGuard/TokenAllowanceGuard.jsx
@@ -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 (
diff --git a/src/components/TopBar/Wallet/Token.tsx b/src/components/TopBar/Wallet/Token.tsx
index 7b5bd29..4605a21 100644
--- a/src/components/TopBar/Wallet/Token.tsx
+++ b/src/components/TopBar/Wallet/Token.tsx
@@ -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(),
diff --git a/src/constants/addresses.js b/src/constants/addresses.js
index 616741b..451edc8 100644
--- a/src/constants/addresses.js
+++ b/src/constants/addresses.js
@@ -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",
diff --git a/src/containers/Dex/Dex.jsx b/src/containers/Dex/Dex.jsx
index 06c61df..35602e3 100644
--- a/src/containers/Dex/Dex.jsx
+++ b/src/containers/Dex/Dex.jsx
@@ -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 }) => {
{
setTokenAddress={setInnerTokenAddressTop}
/>
{
setBottomTokenListOpen={setBottomTokenListOpen}
setIsSwap={setIsSwap}
formatDecimals={formatDecimals}
+ isWrapping={isWrapping}
+ isUnwrapping={isUnwrapping}
/>
:
{
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}
diff --git a/src/containers/Dex/SwapContainer.jsx b/src/containers/Dex/SwapContainer.jsx
index 180de50..36566a0 100644
--- a/src/containers/Dex/SwapContainer.jsx
+++ b/src/containers/Dex/SwapContainer.jsx
@@ -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 }
diff --git a/src/containers/Dex/TokenModal.jsx b/src/containers/Dex/TokenModal.jsx
index 2345c7e..7bb847e 100644
--- a/src/containers/Dex/TokenModal.jsx
+++ b/src/containers/Dex/TokenModal.jsx
@@ -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]
},
diff --git a/src/containers/Stake/components/FarmPools.jsx b/src/containers/Stake/components/FarmPools.jsx
index e56943a..5b68d7e 100644
--- a/src/containers/Stake/components/FarmPools.jsx
+++ b/src/containers/Stake/components/FarmPools.jsx
@@ -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]}`,
})
},
diff --git a/src/helpers/tokenConverter.js b/src/helpers/tokenConverter.js
index b6120f7..bd66ce6 100644
--- a/src/helpers/tokenConverter.js
+++ b/src/helpers/tokenConverter.js
@@ -1,4 +1,4 @@
-export const tokenNameConverter = (chainId, name) => {
+export const tokenNameConverter = (chainId, name, address) => {
if (name?.toUpperCase() === "WETH") {
switch (chainId) {
case 63:
diff --git a/src/hooks/helpers.js b/src/hooks/helpers.js
index c365879..c477967 100644
--- a/src/hooks/helpers.js
+++ b/src/hooks/helpers.js
@@ -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;
}
diff --git a/src/hooks/tokens/index.js b/src/hooks/tokens/index.js
index 0e4b62c..da97e1c 100644
--- a/src/hooks/tokens/index.js
+++ b/src/hooks/tokens/index.js
@@ -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,
diff --git a/src/hooks/uniswapv2/UniswapV2Factory.js b/src/hooks/uniswapv2/UniswapV2Factory.js
index 0c73640..626f10f 100644
--- a/src/hooks/uniswapv2/UniswapV2Factory.js
+++ b/src/hooks/uniswapv2/UniswapV2Factory.js
@@ -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,
});
diff --git a/src/hooks/uniswapv2/UniswapV2Router.js b/src/hooks/uniswapv2/UniswapV2Router.js
index e4b1f3b..0ff83da 100644
--- a/src/hooks/uniswapv2/UniswapV2Router.js
+++ b/src/hooks/uniswapv2/UniswapV2Router.js
@@ -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);