diff --git a/src/components/tokens/token-card.tsx b/src/components/tokens/token-card.tsx
index c2d4d5b..f1011e6 100644
--- a/src/components/tokens/token-card.tsx
+++ b/src/components/tokens/token-card.tsx
@@ -3,14 +3,7 @@ import { Card } from "../ui/card";
import { TokenSelect } from "./token-select";
import { Token } from "@/types";
import { NumericFormat } from "react-number-format";
-import {
- format,
- cn,
- ErrorCodes,
- useTokensWithBalances,
- useTokenBalance,
- toExactAmount,
-} from "@/lib";
+import { format, cn, ErrorCodes, useTokenBalance, toExactAmount } from "@/lib";
import { Skeleton } from "../ui/skeleton";
import { Button } from "../ui/button";
import { useToExactAmount } from "@/trade/hooks";
@@ -50,7 +43,7 @@ export function TokenCard({
amountLoading,
inputError,
}: TokenCardProps) {
- const balance = useTokenBalance(selectedToken?.address);
+ const { balance } = useTokenBalance(selectedToken?.address);
const balanceError = inputError === ErrorCodes.InsufficientBalance;
const balanceDisplay = selectedToken
? format.crypto(Number(toExactAmount(balance, selectedToken.decimals)))
diff --git a/src/components/tokens/token-select.tsx b/src/components/tokens/token-select.tsx
index fd919e2..110ed72 100644
--- a/src/components/tokens/token-select.tsx
+++ b/src/components/tokens/token-select.tsx
@@ -13,7 +13,16 @@ import { Avatar, AvatarFallback, AvatarImage } from "../ui/avatar";
import { Token } from "@/types";
import { Card } from "../ui/card";
import { useMemo, useState } from "react";
-import { format, toExactAmount, useTokensWithBalances } from "@/lib";
+import {
+ eqIgnoreCase,
+ format,
+ usePriceUsd,
+ useSortedTokens,
+ useTokenBalance,
+} from "@/lib";
+import { useToExactAmount } from "@/trade/hooks";
+import { Skeleton } from "../ui/skeleton";
+import { Virtuoso } from "react-virtuoso";
import BN from "bignumber.js";
type TokenSelectProps = {
@@ -26,49 +35,19 @@ export function TokenSelect({
onSelectToken,
}: TokenSelectProps) {
const [open, setOpen] = useState(false);
- const tokens = useTokensWithBalances().tokensWithBalances
+ const tokens = useSortedTokens();
const [filterInput, setFilterInput] = useState("");
- const SortedTokens = useMemo(() => {
- if(!tokens) return null;
- return Object.values(tokens)
- .filter((t) => {
- return (
- t.token.symbol.toLowerCase().includes(filterInput.toLowerCase()) ||
- t.token.address.toLowerCase().includes(filterInput.toLowerCase())
- );
- })
- .sort((a, b) => {
-
- const balanceA = BN(toExactAmount(a.balance.toString(), a.token.decimals));
- const balanceB = BN(toExactAmount(b.balance.toString(), b.token.decimals));
- return balanceB.minus(balanceA).toNumber();
- })
- .map((t) => (
-
{
- onSelectToken(t.token);
- setOpen(false);
- }}
- >
-
-
-
-
- {t.token.symbol.charAt(0)}
-
-
-
-
{t.token.symbol}
-
{t.token.name}
-
-
- {format.crypto(Number(toExactAmount(t.balance.toString(), t.token.decimals) || '0'))}
-
- ));
- }, [filterInput, onSelectToken, tokens]);
+ const filteredTokens = useMemo(() => {
+ if (!filterInput) return tokens || [];
+ return (
+ tokens?.filter(
+ (t) =>
+ eqIgnoreCase(t.address, filterInput) ||
+ t.symbol.toLowerCase().includes(filterInput.toLowerCase())
+ ) || []
+ );
+ }, [tokens, filterInput]);
return (
);
}
+
+const TokenDisplay = ({
+ token: t,
+ onSelect,
+}: {
+ token: Token;
+ onSelect: () => void;
+}) => {
+ const { balance, isLoading } = useTokenBalance(t.address);
+ const usd = usePriceUsd(t.address).data || 0;
+ const balanceUi = useToExactAmount(balance, t.decimals) || "0";
+ const usdAmount = BN(balanceUi).multipliedBy(usd).toFixed()
+
+ return (
+
+
+
+
+
+ {t.symbol.charAt(0)}
+
+
+
+
{t.symbol}
+
{t.name}
+
+
+ {isLoading ? (
+
+ ) : (
+
+
{format.crypto(Number(balanceUi))}
+
${format.crypto(Number(usdAmount))}
+
+ )}
+
+ );
+};
diff --git a/src/lib/index.ts b/src/lib/index.ts
index 76d4dcb..1e4a570 100644
--- a/src/lib/index.ts
+++ b/src/lib/index.ts
@@ -3,11 +3,11 @@ export * from './networks'
export * from './useGetRequiresApproval'
export * from './utils'
export * from './useHandleInputError'
-export * from './useTokensWithBalances'
+export * from './useTokens'
export * from './useDefaultTokens'
export * from './useDebounce'
export * from './useParaswap'
export * from './wagmi-config'
-export * from './useTokenList'
+export * from './useTokens'
export * from './useWrapOrUnwrapOnly'
export * from './usePriceUsd'
diff --git a/src/lib/networks.ts b/src/lib/networks.ts
index 472acc1..7eb1307 100644
--- a/src/lib/networks.ts
+++ b/src/lib/networks.ts
@@ -1,54 +1,383 @@
-import { zeroAddress } from 'viem'
+import { zeroAddress } from "viem";
export const networks = {
+ eth: {
+ id: 1,
+ name: "Ethereum",
+ shortname: "eth",
+ native: {
+ address: zeroAddress,
+ symbol: "ETH",
+ decimals: 18,
+ logoUrl: "https://app.1inch.io/assets/images/network-logos/ethereum.svg",
+ },
+ wToken: {
+ symbol: "WETH",
+ address: "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2",
+ decimals: 18,
+ weth: true,
+ logoUrl:
+ "https://tokens-data.1inch.io/images/0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2.png",
+ },
+ publicRpcUrl: "https://eth.llamarpc.com",
+ logoUrl: "https://app.1inch.io/assets/images/network-logos/ethereum.svg",
+ explorer: "https://etherscan.io",
+ eip1559: true,
+ baseAssets: [
+ "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2",
+ "0x2260FAC5E5542a773Aa44fBCfeDf7C193bc2C599",
+ "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48",
+ "0xdAC17F958D2ee523a2206206994597C13D831ec7",
+ "0x6B175474E89094C44Da98b954EedeAC495271d0F",
+ "0x5f98805A4E8be255a32880FDeC7F6728C6568bA0",
+ "0x853d955aCEf822Db058eb8505911ED77F175b99e",
+ "0xff56Cc6b1E6dEd347aA0B7676C85AB0B3D08B0FA",
+ ],
+ },
+ bsc: {
+ id: 56,
+ name: "BinanceSmartChain",
+ shortname: "bsc",
+ native: {
+ address: zeroAddress,
+ symbol: "BNB",
+ decimals: 18,
+ logoUrl: "https://app.1inch.io/assets/images/network-logos/bsc_2.svg",
+ },
+ wToken: {
+ symbol: "WBNB",
+ address: "0xbb4CdB9CBd36B01bD1cBaEBF2De08d9173bc095c",
+ decimals: 18,
+ weth: true,
+ logoUrl:
+ "https://tokens-data.1inch.io/images/0xbb4cdb9cbd36b01bd1cbaebf2de08d9173bc095c.png",
+ },
+ publicRpcUrl: "https://bsc-dataseed.binance.org",
+ logoUrl: "https://app.1inch.io/assets/images/network-logos/bsc_2.svg",
+ explorer: "https://bscscan.com",
+ eip1559: false,
+ baseAssets: [
+ "0xbb4CdB9CBd36B01bD1cBaEBF2De08d9173bc095c",
+ "0x7130d2A12B9BCbFAe4f2634d864A1Ee1Ce3Ead9c",
+ "0x8AC76a51cc950d9822D68b83fE1Ad97B32Cd580d",
+ "0x55d398326f99059fF775485246999027B3197955",
+ "0x1AF3F329e8BE154074D8769D1FFa4eE058B1DBc3",
+ "0xe9e7CEA3DedcA5984780Bafc599bD69ADd087D56",
+ "0x2170Ed0880ac9A755fd29B2688956BD959F933F8",
+ "0xeBd49b26169e1b52c04cFd19FCf289405dF55F80",
+ ],
+ },
poly: {
id: 137,
- name: 'Polygon',
- shortname: 'poly',
+ name: "Polygon",
+ shortname: "poly",
native: {
address: zeroAddress,
- symbol: 'MATIC',
+ symbol: "MATIC",
decimals: 18,
- logoUrl: 'https://app.1inch.io/assets/images/network-logos/polygon.svg',
+ logoUrl: "https://app.1inch.io/assets/images/network-logos/polygon.svg",
},
wToken: {
- symbol: 'WMATIC',
- address: '0x0d500B1d8E8eF31E21C99d1Db9A6444d3ADf1270',
+ symbol: "WMATIC",
+ address: "0x0d500B1d8E8eF31E21C99d1Db9A6444d3ADf1270",
decimals: 18,
weth: true,
logoUrl:
- 'https://tokens-data.1inch.io/images/0x0d500b1d8e8ef31e21c99d1db9a6444d3adf1270.png',
+ "https://tokens-data.1inch.io/images/0x0d500b1d8e8ef31e21c99d1db9a6444d3adf1270.png",
},
- publicRpcUrl: 'https://polygon-rpc.com',
- logoUrl: 'https://app.1inch.io/assets/images/network-logos/polygon.svg',
- explorer: 'https://polygonscan.com',
+ publicRpcUrl: "https://polygon-rpc.com",
+ logoUrl: "https://app.1inch.io/assets/images/network-logos/polygon.svg",
+ explorer: "https://polygonscan.com",
eip1559: true,
+ baseAssets: [
+ "0x0d500B1d8E8eF31E21C99d1Db9A6444d3ADf1270",
+ "0x3A58a54C066FdC0f2D55FC9C89F0415C92eBf3C4",
+ "0x1BFD67037B42Cf73acF2047067bd4F2C47D9BfD6",
+ "0x2791Bca1f2de4661ED88A30C99A7a9449Aa84174",
+ "0xc2132D05D31c914a87C6611C10748AEb04B58e8F",
+ "0x8f3Cf7ad23Cd3CaDbD9735AFf958023239c6A063",
+ "0x7ceb23fd6bc0add59e62ac25578270cff1b9f619",
+ "0xdAb529f40E671A1D4bF91361c21bf9f0C9712ab7",
+ "0x614389EaAE0A6821DC49062D56BDA3d9d45Fa2ff",
+ ],
+ },
+ arb: {
+ id: 42161,
+ name: "Arbitrum",
+ shortname: "arb",
+ native: {
+ address: zeroAddress,
+ symbol: "ETH",
+ decimals: 18,
+ logoUrl: "https://app.1inch.io/assets/images/network-logos/ethereum.svg",
+ },
+ wToken: {
+ symbol: "WETH",
+ address: "0x82af49447d8a07e3bd95bd0d56f35241523fbab1",
+ decimals: 18,
+ weth: true,
+ logoUrl:
+ "https://tokens-data.1inch.io/images/0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2.png",
+ },
+ publicRpcUrl: "https://arb1.arbitrum.io/rpc",
+ logoUrl: "https://app.1inch.io/assets/images/network-logos/arbitrum.svg",
+ explorer: "https://arbiscan.io",
+ eip1559: true,
+ baseAssets: [
+ "0x82af49447d8a07e3bd95bd0d56f35241523fbab1",
+ "0x2f2a2543b76a4166549f7aab2e75bef0aefc5b0f",
+ "0xFF970A61A04b1cA14834A43f5dE4533eBDDB5CC8",
+ "0xfd086bc7cd5c481dcc9c85ebe478a1c0b69fcbb9",
+ "0xDA10009cBd5D07dd0CeCc66161FC93D7c9000da1",
+ "0x912CE59144191C1204E64559FE8253a0e49E6548",
+ "0x17FC002b466eEc40DaE837Fc4bE5c67993ddBd6F",
+ "0x4D15a3A2286D883AF0AA1B3f21367843FAc63E07",
+ ],
+ },
+ avax: {
+ id: 43114,
+ name: "Avalanche",
+ shortname: "avax",
+ native: {
+ address: zeroAddress,
+ symbol: "AVAX",
+ decimals: 18,
+ logoUrl: "https://app.1inch.io/assets/images/network-logos/avalanche.svg",
+ },
+ wToken: {
+ symbol: "WAVAX",
+ address: "0xB31f66AA3C1e785363F0875A1B74E27b85FD66c7",
+ decimals: 18,
+ weth: true,
+ logoUrl:
+ "https://tokens-data.1inch.io/images/0xb31f66aa3c1e785363f0875a1b74e27b85fd66c7.png",
+ },
+ publicRpcUrl: "https://api.avax.network/ext/bc/C/rpc",
+ logoUrl: "https://app.1inch.io/assets/images/network-logos/avalanche.svg",
+ explorer: "https://snowtrace.io",
+ eip1559: true,
+ baseAssets: [
+ "0xB31f66AA3C1e785363F0875A1B74E27b85FD66c7",
+ "0x50b7545627a5162F82A992c33b87aDc75187B218",
+ "0xB97EF9Ef8734C71904D8002F8b6Bc66Dd9c48a6E",
+ "0xA7D7079b0FEaD91F3e65f86E8915Cb59c1a4C664",
+ "0x9702230A8Ea53601f5cD2dc00fDBc13d4dF4A8c7",
+ "0xc7198437980c041c805A1EDcbA50c1Ce5db95118",
+ "0x19860CCB0A68fd4213aB9D8266F7bBf05A8dDe98",
+ "0x49D5c2BdFfac6CE2BFdB6640F4F80f226bc10bAB",
+ "0xd586E7F844cEa2F87f50152665BCbc2C279D8d70",
+ "0x340fE1D898ECCAad394e2ba0fC1F93d27c7b717A",
+ ],
+ },
+ oeth: {
+ id: 10,
+ name: "Optimism",
+ shortname: "oeth",
+ native: {
+ address: zeroAddress,
+ symbol: "ETH",
+ decimals: 18,
+ logoUrl: "https://app.1inch.io/assets/images/network-logos/ethereum.svg",
+ },
+ wToken: {
+ symbol: "WETH",
+ address: "0x4200000000000000000000000000000000000006",
+ decimals: 18,
+ weth: true,
+ logoUrl:
+ "https://tokens-data.1inch.io/images/0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2.png",
+ },
+ publicRpcUrl: "https://mainnet.optimism.io",
+ logoUrl: "https://app.1inch.io/assets/images/network-logos/optimism.svg",
+ explorer: "https://optimistic.etherscan.io",
+ eip1559: true,
+ baseAssets: [
+ "0x4200000000000000000000000000000000000006",
+ "0x68f180fcCe6836688e9084f035309E29Bf0A2095",
+ "0x7F5c764cBc14f9669B88837ca1490cCa17c31607",
+ "0x94b008aA00579c1307B0EF2c499aD98a8ce58e58",
+ "0xDA10009cBd5D07dd0CeCc66161FC93D7c9000da1",
+ "0x4200000000000000000000000000000000000042",
+ "0x2E3D870790dC77A83DD1d18184Acc7439A53f475",
+ ],
+ },
+ ftm: {
+ id: 250,
+ name: "Fantom",
+ shortname: "ftm",
+ native: {
+ address: zeroAddress,
+ symbol: "FTM",
+ decimals: 18,
+ logoUrl: "https://app.1inch.io/assets/images/network-logos/fantom.svg",
+ },
+ wToken: {
+ symbol: "WFTM",
+ address: "0x21be370D5312f44cB42ce377BC9b8a0cEF1A4C83",
+ decimals: 18,
+ weth: true,
+ logoUrl:
+ "https://tokens-data.1inch.io/images/0x4e15361fd6b4bb609fa63c81a2be19d873717870.png",
+ },
+ publicRpcUrl: "https://rpc.ftm.tools",
+ logoUrl: "https://app.1inch.io/assets/images/network-logos/fantom.svg",
+ explorer: "https://ftmscan.com",
+ eip1559: true,
+ baseAssets: [
+ "0x21be370D5312f44cB42ce377BC9b8a0cEF1A4C83",
+ "0x321162Cd933E2Be498Cd2267a90534A804051b11",
+ "0x74b23882a30290451A17c44f4F05243b6b58C76d",
+ "0x04068DA6C83AFCFA0e13ba15A6696662335D5B75",
+ "0x8D11eC38a3EB5E956B052f67Da8Bdc9bef8Abf3E",
+ "0xdc301622e621166BD8E82f2cA0A26c13Ad0BE355",
+ "0x3E01B7E242D5AF8064cB9A8F9468aC0f8683617c",
+ ],
+ },
+ base: {
+ id: 8453,
+ name: "Base",
+ shortname: "base",
+ native: {
+ address: zeroAddress,
+ symbol: "ETH",
+ decimals: 18,
+ logoUrl: "https://app.1inch.io/assets/images/network-logos/ethereum.svg",
+ },
+ wToken: {
+ symbol: "WETH",
+ address: "0x4200000000000000000000000000000000000006",
+ decimals: 18,
+ weth: true,
+ logoUrl:
+ "https://tokens-data.1inch.io/images/0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2.png",
+ },
+ publicRpcUrl: "https://mainnet.base.org",
+ logoUrl: "https://app.1inch.io/assets/images/network-logos/base.svg",
+ explorer: "https://basescan.org",
+ eip1559: false,
+ baseAssets: [
+ "0x4200000000000000000000000000000000000006",
+ "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
+ "0x50c5725949A6F0c72E6C4a641F24049A917DB0Cb",
+ ],
+ },
+ linea: {
+ id: 59144,
+ name: "Linea",
+ shortname: "linea",
+ native: {
+ address: zeroAddress,
+ symbol: "ETH",
+ decimals: 18,
+ logoUrl: "https://app.1inch.io/assets/images/network-logos/ethereum.svg",
+ },
+ wToken: {
+ symbol: "WETH",
+ address: "0xe5D7C2a44FfDDf6b295A15c148167daaAf5Cf34f",
+ decimals: 18,
+ weth: true,
+ logoUrl:
+ "https://tokens-data.1inch.io/images/0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2.png",
+ },
+ publicRpcUrl: "https://rpc.linea.build",
+ logoUrl: "https://lineascan.build/images/logo.svg",
+ explorer: "https://lineascan.build",
+ eip1559: false,
+ baseAssets: [
+ "0xe5D7C2a44FfDDf6b295A15c148167daaAf5Cf34f",
+ "0x176211869cA2b568f2A7D4EE941E073a821EE1ff",
+ "0x4AF15ec2A0BD43Db75dd04E62FAA3B8EF36b00d5",
+ ],
+ },
+ zksync: {
+ id: 324,
+ name: "zksync",
+ shortname: "zksync",
+ native: {
+ address: zeroAddress,
+ symbol: "ETH",
+ decimals: 18,
+ logoUrl: "https://app.1inch.io/assets/images/network-logos/ethereum.svg",
+ },
+ wToken: {
+ symbol: "WETH",
+ address: "0x5AEa5775959fBC2557Cc8789bC1bf90A239D9a91",
+ decimals: 18,
+ weth: true,
+ logoUrl:
+ "https://tokens-data.1inch.io/images/0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2.png",
+ },
+ publicRpcUrl: "https://mainnet.era.zksync.io",
+ logoUrl:
+ "https://raw.githubusercontent.com/matter-labs/zksync/0a4ca2145a0c95b5bafa84c2f095c644907a8825/zkSyncLogo.svg",
+ explorer: "https://explorer.zksync.io/",
+ eip1559: true,
+ baseAssets: [
+ "0x5AEa5775959fBC2557Cc8789bC1bf90A239D9a91",
+ "0x3355df6d4c9c3035724fd0e3914de96a5a83aaf4",
+ "0x4b9eb6c0b6ea15176bbf62841c6b2a8a398cb656",
+ ],
+ },
+ zkevm: {
+ id: 1101,
+ name: "zkevm",
+ shortname: "zkevm",
+ native: {
+ address: zeroAddress,
+ symbol: "ETH",
+ decimals: 18,
+ logoUrl: "https://app.1inch.io/assets/images/network-logos/ethereum.svg",
+ },
+ wToken: {
+ symbol: "WETH",
+ address: "0x4F9A0e7FD2Bf6067db6994CF12E4495Df938E6e9",
+ decimals: 18,
+ weth: true,
+ logoUrl:
+ "https://tokens-data.1inch.io/images/0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2.png",
+ },
+ publicRpcUrl: "https://zkevm-rpc.com",
+ logoUrl:
+ "https://user-images.githubusercontent.com/18598517/235932702-bc47eae5-d672-4dd9-9da2-8ea8f51a93f3.png",
+ explorer: "https://zkevm.polygonscan.com/",
+ eip1559: true,
+ baseAssets: [
+ "0x4F9A0e7FD2Bf6067db6994CF12E4495Df938E6e9",
+ "0xA8CE8aee21bC2A48a5EF670afCc9274C7bbbC035",
+ "0xC5015b9d9161Dca7e18e32f6f25C4aD850731Fd4",
+ ],
},
-}
-
-export const network = {
- 137: {
- id: 137,
- name: 'Polygon',
- shortname: 'poly',
+ blast: {
+ id: 81457,
+ name: "blast",
+ shortname: "blast",
native: {
address: zeroAddress,
- symbol: 'MATIC',
+ symbol: "ETH",
decimals: 18,
- logoUrl: 'https://app.1inch.io/assets/images/network-logos/polygon.svg',
+ logoUrl: "https://icons.llamao.fi/icons/chains/rsz_blast",
},
wToken: {
- symbol: 'WMATIC',
- address: '0x0d500B1d8E8eF31E21C99d1Db9A6444d3ADf1270',
+ symbol: "WETH",
+ address: "0x4300000000000000000000000000000000000004",
decimals: 18,
weth: true,
logoUrl:
- 'https://tokens-data.1inch.io/images/0x0d500b1d8e8ef31e21c99d1db9a6444d3adf1270.png',
+ "https://tokens-data.1inch.io/images/0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2.png",
},
- publicRpcUrl: 'https://polygon-rpc.com',
- logoUrl: 'https://app.1inch.io/assets/images/network-logos/polygon.svg',
- explorer: 'https://polygonscan.com',
+ publicRpcUrl: "https://rpc.ankr.com/blast",
+ logoUrl: "https://icons.llamao.fi/icons/chains/rsz_blast",
+ explorer: "https://blastscan.io/",
eip1559: true,
+ baseAssets: [
+ "0x4300000000000000000000000000000000000004",
+ "0x4300000000000000000000000000000000000003",
+ ],
},
-}
\ No newline at end of file
+};
+
+export const getNetwork = (chainId: number) => {
+ return Object.values(networks).find((network) => network.id === chainId);
+};
+
diff --git a/src/lib/useBalances.ts b/src/lib/useBalances.ts
deleted file mode 100644
index 15f870f..0000000
--- a/src/lib/useBalances.ts
+++ /dev/null
@@ -1,121 +0,0 @@
-import { useQuery } from '@tanstack/react-query'
-import { getBalance, multicall } from '@wagmi/core'
-import { Config, serialize, useBalance, useConfig } from 'wagmi'
-import { GetBalanceReturnType } from 'wagmi/actions'
-import { Token, TokensWithBalances } from '@/types'
-import { erc20Abi, isAddress, Address } from 'viem'
-import { zeroAddress } from '@orbs-network/liquidity-hub-sdk'
-
-interface QueryBalanceParams {
- chainId: number | undefined
- tokens: Token[]
- account: string | undefined
- nativeBalance?: GetBalanceReturnType
- config: Config
-}
-
-export const queryFnUseBalances = async ({
- chainId,
- tokens,
- account,
- nativeBalance,
- config,
-}: QueryBalanceParams) => {
- if (!account || !chainId || !tokens) return null
-
- let native = nativeBalance
- if (typeof native === 'undefined') {
- native = await getBalance(config, {
- address: account as Address,
- chainId,
- })
- }
-
- const [validatedTokens, validatedTokenAddresses] = tokens.reduce<
- [Token[], Address[]]
- >(
- (acc, tokens) => {
- if (chainId && tokens && isAddress(tokens.address)) {
- acc[0].push(tokens)
- acc[1].push(tokens.address as Address)
- }
-
- return acc
- },
- [[], []]
- )
-
- const data = await multicall(config, {
- contracts: validatedTokenAddresses.map(
- (token) =>
- ({
- chainId,
- address: token,
- abi: erc20Abi,
- functionName: 'balanceOf',
- args: [account],
- } as const)
- ),
- })
-
- const _data = data.reduce
((acc, _cur, i) => {
- const amount = data[i].result
- if (typeof amount === 'bigint') {
- acc[validatedTokens[i].address] = {
- token: validatedTokens[i],
- balance: amount,
- }
- }
- return acc
- }, {})
-
- _data[zeroAddress] = {
- token: validatedTokens[0],
- balance: native.value,
- }
-
- return _data
-}
-
-interface UseBalanceParams {
- chainId: number | undefined
- tokens: Token[]
- account: Address | undefined
- enabled?: boolean
-}
-
-export const useBalances = ({
- chainId,
- tokens,
- account,
- enabled = true,
-}: UseBalanceParams) => {
- const { data: nativeBalance, queryKey } = useBalance({
- chainId,
- address: account,
- query: { enabled, refetchInterval: 10000, staleTime: 10000 },
- })
-
- const config = useConfig()
-
- return {
- query: useQuery({
- queryKey: [
- 'useBalances',
- { chainId, tokens, account, nativeBalance: serialize(nativeBalance) },
- ],
- queryFn: () =>
- queryFnUseBalances({
- chainId,
- tokens,
- account,
- nativeBalance,
- config,
- }),
- refetchInterval: 10000,
- staleTime: 10000,
- enabled: Boolean(chainId && account && enabled && tokens),
- }),
- queryKey: [...queryKey, 'useBalances'],
- }
-}
diff --git a/src/lib/useDefaultTokens.ts b/src/lib/useDefaultTokens.ts
index 96b5024..fa44c93 100644
--- a/src/lib/useDefaultTokens.ts
+++ b/src/lib/useDefaultTokens.ts
@@ -1,48 +1,14 @@
-import { Token, TokensWithBalances } from '@/types'
-import { zeroAddress } from '@orbs-network/liquidity-hub-sdk'
-import { useEffect, useMemo } from 'react'
-
-/* Sets default tokens */
-type UseDefaultTokens = {
- inToken: Token | null
- outToken: Token | null
- tokensWithBalances: TokensWithBalances | null | undefined
- setInToken: (token: Token) => void
- setOutToken: (token: Token) => void
-}
-export function useDefaultTokens({
- tokensWithBalances,
- inToken,
- outToken,
- setInToken,
- setOutToken,
-}: UseDefaultTokens) {
- const defaultTokens = useMemo(() => {
- if (!tokensWithBalances) return []
-
- return [
- tokensWithBalances[zeroAddress].token,
- Object.values(tokensWithBalances).find((t) => t.token.symbol === 'USDT')
- ?.token || null,
- ].filter(Boolean) as Token[]
- }, [tokensWithBalances])
-
- useEffect(() => {
- if (!inToken && tokensWithBalances) {
- setInToken(defaultTokens[0])
- }
-
- if (!outToken && tokensWithBalances) {
- setOutToken(defaultTokens[1])
- }
- }, [
- inToken,
- defaultTokens,
- outToken,
- setInToken,
- setOutToken,
- tokensWithBalances,
- ])
-
- return defaultTokens
+import { useMemo } from "react";
+import { useSortedTokens } from "./useTokens";
+
+export function useDefaultTokens() {
+ const tokens = useSortedTokens();
+
+ return useMemo(() => {
+ if (!tokens) return;
+ return {
+ inToken: tokens[0],
+ outToken: tokens[1],
+ };
+ }, [tokens]);
}
diff --git a/src/lib/useGetRequiresApproval.ts b/src/lib/useGetRequiresApproval.ts
index 8d0988b..788ced4 100644
--- a/src/lib/useGetRequiresApproval.ts
+++ b/src/lib/useGetRequiresApproval.ts
@@ -3,7 +3,7 @@ import { Address, erc20Abi } from 'viem'
/* Determines whether user needs tp approve allowance for quoted token */
export function useGetRequiresApproval(
- contractAddress?: Address,
+ contractAddress?: any,
inTokenAddress = '',
inAmount = ''
) {
diff --git a/src/lib/useHandleInputError.ts b/src/lib/useHandleInputError.ts
index 2ee712a..750341d 100644
--- a/src/lib/useHandleInputError.ts
+++ b/src/lib/useHandleInputError.ts
@@ -1,10 +1,10 @@
-import { ErrorCodes, toExactAmount } from "@/lib/utils";
+import { ErrorCodes } from "@/lib/utils";
import { Token } from "@/types";
import { useMemo } from "react";
-import {
- useTokenBalance,
-} from "./useTokensWithBalances";
import BN from "bignumber.js";
+import { useTokenBalance } from "./useTokens";
+import { useToRawAmount } from "@/trade/hooks";
+
/* Handles amount input errors */
@@ -15,15 +15,18 @@ export function useInputError({
inToken: Token | null;
inputAmount: string;
}) {
- const tokenBalance = useTokenBalance(inToken?.address);
+ const {balance} = useTokenBalance(inToken?.address);
+ const parsedInputAmount = useToRawAmount(inputAmount, inToken?.decimals)
return useMemo(() => {
- if (!inputAmount) {
+ if(BN(inputAmount || '0').lte(0)) {
+ return ErrorCodes.EnterAmount;
+ }
+ if (!balance) {
return ErrorCodes.EnterAmount;
}
- const balance = toExactAmount(tokenBalance, inToken?.decimals);
- if (BN(inputAmount).gt(balance)) {
+ if (BN(parsedInputAmount).gt(balance)) {
return ErrorCodes.InsufficientBalance;
}
- }, [inputAmount, inToken, tokenBalance]);
+ }, [inputAmount, inToken, balance, parsedInputAmount]);
}
diff --git a/src/lib/useParaswap.ts b/src/lib/useParaswap.ts
index 47eb488..cd716ea 100644
--- a/src/lib/useParaswap.ts
+++ b/src/lib/useParaswap.ts
@@ -2,19 +2,11 @@ import { useCallback, useMemo } from 'react'
import {
getMinAmountOut,
isNativeAddress,
- resolveNativeTokenAddress,
- waitForConfirmations,
} from '@/lib/utils'
import { constructSimpleSDK, OptimalRate, SwapSide } from '@paraswap/sdk'
-import { useMutation, useQuery } from '@tanstack/react-query'
+import { useQuery } from '@tanstack/react-query'
import { useAccount } from 'wagmi'
-import { wagmiConfig } from './wagmi-config'
-import { estimateGas, sendTransaction } from 'wagmi/actions'
-import { Address } from 'viem'
-import { SwapStatus } from '@orbs-network/swap-ui'
-import { SwapSteps } from '@/types'
-import { approveAllowance } from './approveAllowance'
-import { getRequiresApproval } from './getRequiresApproval'
+
const PARASWAP_NATIVE_ADDRESS = '0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE'
diff --git a/src/lib/usePriceUsd.ts b/src/lib/usePriceUsd.ts
index e81a13d..c273a39 100644
--- a/src/lib/usePriceUsd.ts
+++ b/src/lib/usePriceUsd.ts
@@ -1,4 +1,4 @@
-import { networks, isNativeAddress } from '@/lib'
+import { isNativeAddress, getNetwork } from '@/lib'
import { useQuery } from '@tanstack/react-query'
import { useAccount } from 'wagmi'
@@ -6,14 +6,14 @@ export const usePriceUsd = (address?: string) => {
const {chainId} = useAccount()
return useQuery({
queryKey: ['usePriceUSD', chainId, address],
- queryFn: async () => {
+ queryFn: async () => {
if (!address || !chainId) {
return 0
}
return (await fetchLLMAPrice(address, chainId)).priceUsd
},
- refetchInterval: 10_000,
+ refetchInterval: 30_000,
enabled: !!address && !!chainId,
})
}
@@ -40,7 +40,7 @@ export async function fetchLLMAPrice(token: string, chainId: number) {
const chainName = chainIdToName[chainId] || 'Unknown Chain'
if (isNativeAddress(token)) {
- token = networks.poly.wToken.address
+ token = getNetwork(chainId)?.wToken.address || ''
}
const tokenAddressWithChainId = `${chainName}:${token}`
const url = `https://coins.llama.fi/prices/current/${tokenAddressWithChainId}`
@@ -49,10 +49,10 @@ export async function fetchLLMAPrice(token: string, chainId: number) {
return nullPrice
}
const data = await response.json()
- const coin = data.coins[tokenAddressWithChainId]
+ const coin = data.coins[tokenAddressWithChainId]
return {
- priceUsd: coin.price,
- priceNative: coin.price,
+ priceUsd: !coin ? 0 : coin.price,
+ priceNative: !coin ? 0 : coin.price,
timestamp: Date.now(),
}
} catch (error) {
diff --git a/src/lib/useTokenList.ts b/src/lib/useTokenList.ts
deleted file mode 100644
index f887dcd..0000000
--- a/src/lib/useTokenList.ts
+++ /dev/null
@@ -1,79 +0,0 @@
-import { networks } from '@/lib/networks'
-import { Token } from '@/types'
-import { zeroAddress } from '@orbs-network/liquidity-hub-sdk'
-import { useQuery } from '@tanstack/react-query'
-
-type PolygonToken = {
- address: string
- chainId: number
- decimals: number
- logoURI: string
- name?: string
- symbol: string
-}
-
-const getPolygonTokens = async (): Promise => {
- const res = await fetch(
- 'https://unpkg.com/quickswap-default-token-list@1.3.16/build/quickswap-default.tokenlist.json'
- )
-
- if (!res.ok) {
- throw new Error('Failed to fetch tokens')
- }
-
- const polyTokens = (await res.json()).tokens as PolygonToken[]
-
- const tokens = polyTokens.filter((it) => it.chainId === networks.poly.id)
-
- const candiesAddresses = [
- zeroAddress,
- '0x0d500B1d8E8eF31E21C99d1Db9A6444d3ADf1270',
- '0x3A58a54C066FdC0f2D55FC9C89F0415C92eBf3C4',
- '0x1BFD67037B42Cf73acF2047067bd4F2C47D9BfD6',
- '0x2791Bca1f2de4661ED88A30C99A7a9449Aa84174',
- '0xc2132D05D31c914a87C6611C10748AEb04B58e8F',
- '0x8f3Cf7ad23Cd3CaDbD9735AFf958023239c6A063',
- '0x7ceB23fD6bC0adD59E62ac25578270cFf1b9f619',
- '0xdAb529f40E671A1D4bF91361c21bf9f0C9712ab7',
- '0x614389EaAE0A6821DC49062D56BDA3d9d45Fa2ff',
- ]
-
- const sorted = tokens.sort((a, b) => {
- const indexA = candiesAddresses.indexOf(a.address)
- const indexB = candiesAddresses.indexOf(b.address)
- return indexB - indexA
- })
-
- return [
- {
- address: zeroAddress,
- symbol: 'MATIC',
- decimals: 18,
- logoURI: 'https://app.1inch.io/assets/images/network-logos/polygon.svg',
- name: 'MATIC',
- },
- ...sorted,
- ].map((token) => {
- return {
- address: token.address,
- symbol: token.symbol,
- decimals: token.decimals,
- logoUrl: token.logoURI?.replace('/logo_24.png', '/logo_48.png'),
- name: token.name,
- }
- })
-}
-
-
-
-export function useTokensList() {
- const chainId = networks.poly.id
-
- return useQuery({
- queryFn: async () => {
- return getPolygonTokens() || []
- },
- queryKey: ['tokens-list', chainId],
- staleTime: Infinity,
- })
-}
diff --git a/src/lib/useTokens.ts b/src/lib/useTokens.ts
new file mode 100644
index 0000000..ebf63e7
--- /dev/null
+++ b/src/lib/useTokens.ts
@@ -0,0 +1,205 @@
+import { Token } from "@/types";
+import { getNetwork, networks } from "./networks";
+import { useQuery } from "@tanstack/react-query";
+import { getBalance, multicall } from "@wagmi/core";
+import { useAccount, useConfig } from "wagmi";
+import { erc20Abi, Address } from "viem";
+import { zeroAddress } from "@orbs-network/liquidity-hub-sdk";
+import { eqIgnoreCase } from "./utils";
+import { useMemo } from "react";
+
+const getFantomTokens = async (signal?: AbortSignal): Promise => {
+ const res = await fetch(
+ "https://raw.githubusercontent.com/viaprotocol/tokenlists/main/tokenlists/ftm.json",
+ { signal }
+ );
+ const data = await res.json();
+ return data.map((token: any) => {
+ return {
+ address: token.address,
+ symbol: token.symbol,
+ decimals: token.decimals,
+ logoUrl: token.logoURI,
+ name: token.name,
+ };
+ });
+};
+
+const getSushiTokens = async (
+ chainId: number,
+ signal?: AbortSignal
+): Promise => {
+ const tokens = await fetch("https://token-list.sushi.com/", { signal }).then(
+ (res) =>
+ res
+ .json()
+ .then((it) => it.tokens.filter((it: any) => it.chainId === chainId))
+ );
+
+ return Object.values(tokens).map((token: any) => {
+ return {
+ address: token.address,
+ symbol: token.symbol,
+ decimals: token.decimals,
+ logoUrl: token.logoURI,
+ name: token.name,
+ };
+ });
+};
+
+const getLineaTokens = async (signal?: AbortSignal): Promise => {
+ const tokens = await fetch("https://api.lynex.fi/api/v1/assets", { signal })
+ .then((res) => res.json())
+ .then((res) => res.data);
+ return tokens.map((token: any) => {
+ return {
+ address: token.address,
+ symbol: token.symbol,
+ decimals: token.decimals,
+ logoUrl: token.logoURI,
+ name: token.name,
+ };
+ });
+};
+
+const fetchTokens = async (
+ chainId: number,
+ signal?: AbortSignal
+): Promise => {
+ let tokens: Token[] = [];
+ if (chainId === networks.linea.id) {
+ tokens = await getLineaTokens(signal);
+ } else if (chainId === networks.ftm.id) {
+ tokens = await getFantomTokens(signal);
+ } else {
+ tokens = await getSushiTokens(chainId, signal);
+ }
+ const network = getNetwork(chainId);
+ if (network) {
+ const nativeToken: Token = {
+ address: network.native.address,
+ symbol: network.native.symbol,
+ decimals: network.native.decimals,
+ logoUrl: network.native.logoUrl,
+ };
+
+ tokens = [nativeToken, ...tokens];
+ }
+
+ const baseAssets = getNetwork(chainId)?.baseAssets;
+ if (!baseAssets) {
+ return tokens;
+ }
+ const sortedTokens = tokens.sort((a, b) => {
+ const aPriority = baseAssets.includes(a.address) ? 0 : 1;
+ const bPriority = baseAssets.includes(b.address) ? 0 : 1;
+ if (aPriority !== bPriority) {
+ return aPriority - bPriority;
+ }
+ return a.address.localeCompare(b.address);
+ });
+
+ return sortedTokens;
+};
+
+const useTokensList = () => {
+ const chainId = useAccount().chainId;
+
+ return useQuery({
+ queryFn: async ({ signal }) => {
+ const response = await fetchTokens(chainId!, signal);
+ return response;
+ },
+ queryKey: ["useTokensList", chainId],
+ staleTime: Infinity,
+ enabled: !!chainId,
+ });
+};
+
+type BalancesReponse = Record;
+
+export const useTokenBalaces = () => {
+ const { data: tokens } = useTokensList();
+ const { address: account, chainId } = useAccount();
+
+ const config = useConfig();
+
+ return useQuery({
+ queryKey: ["useBalances", chainId, account, tokens?.map((t) => t.address)],
+ queryFn: async () => {
+ if (!tokens) return {};
+ let native = await getBalance(config, {
+ address: account as Address,
+ chainId,
+ });
+
+ const addresses = tokens
+ .map((token) => token.address)
+ .filter((it) => !eqIgnoreCase(it, zeroAddress));
+
+ const multicallResponse = await (multicall as any)(config, {
+ contracts: addresses.map(
+ (address) =>
+ ({
+ chainId,
+ address,
+ abi: erc20Abi,
+ functionName: "balanceOf",
+ args: [account],
+ } as const)
+ ),
+ });
+
+
+ const balances = addresses.reduce(
+ (acc: any, address: any, index: number) => {
+ acc[address] = multicallResponse[index].result?.toString() || '0';
+ return acc;
+ },
+ {}
+ );
+
+ balances[zeroAddress] = native.value.toString();
+
+ return balances;
+ },
+ refetchInterval: 20_000,
+ staleTime: Infinity,
+ enabled: Boolean(chainId && account && tokens?.length),
+ });
+};
+
+export const useTokenBalance = (tokenAddress?: string) => {
+ const { data: balances, isLoading } = useTokenBalaces();
+ return useMemo(() => {
+ if (!tokenAddress) {
+ return {
+ isLoading,
+ balance: "0",
+ };
+ }
+ return {
+ isLoading,
+ balance: balances?.[tokenAddress] || "0",
+ };
+ }, [balances, tokenAddress, isLoading]);
+};
+
+export const useSortedTokens = () => {
+ const { data: tokens } = useTokensList();
+ const { data: balances } = useTokenBalaces();
+ return useMemo(() => {
+ const sorted = tokens?.sort((a, b) => {
+ const balanceA = BigInt(balances?.[a.address] || "0");
+ const balanceB = BigInt(balances?.[b.address] || "0");
+ return balanceB > balanceA ? 1 : balanceB < balanceA ? -1 : 0;
+ });
+
+ const native = sorted?.find((it) => eqIgnoreCase(it.address, zeroAddress));
+ if (native) {
+ sorted?.splice(sorted.indexOf(native), 1);
+ sorted?.unshift(native);
+ }
+ return sorted;
+ }, [tokens, balances]);
+};
diff --git a/src/lib/useTokensWithBalances.ts b/src/lib/useTokensWithBalances.ts
deleted file mode 100644
index c1d2bdc..0000000
--- a/src/lib/useTokensWithBalances.ts
+++ /dev/null
@@ -1,32 +0,0 @@
-import { useAccount } from "wagmi";
-import { useTokensList } from "./useTokenList";
-import { useBalances } from "./useBalances";
-import { TokensWithBalances } from "@/types";
-
-export function useTokensWithBalances() {
- const { address, chainId } = useAccount();
- const { data: tokens, isLoading: tokensLoading } = useTokensList();
- const {
- query: { data: balances, isLoading: balancesLoading, refetch },
- queryKey,
- } = useBalances({
- chainId,
- tokens: tokens || [],
- account: address,
- enabled: Boolean(tokens && address && chainId),
- });
-
- return {
- isLoading: tokensLoading || balancesLoading,
- tokensWithBalances: balances as TokensWithBalances,
- queryKey,
- refetch,
- };
-}
-
-export const useTokenBalance = (tokenAddress?: string) => {
- const { tokensWithBalances } = useTokensWithBalances();
- return !tokenAddress
- ? ""
- : tokensWithBalances?.[tokenAddress]?.balance.toString();
-};
diff --git a/src/lib/utils.ts b/src/lib/utils.ts
index 58f6527..d832aae 100644
--- a/src/lib/utils.ts
+++ b/src/lib/utils.ts
@@ -21,7 +21,7 @@ export const toExactAmount = (
if (decimalScale) {
return result.toFixed(decimalScale);
}
- return result.toString();
+ return result.toFixed();
};
export const toRawAmount = (amount?: string, decimals?: number) => {
if (!decimals || !amount) return "";
@@ -72,7 +72,6 @@ export const format = {
};
export const getMinAmountOut = (slippage: number, _destAmount: string) => {
- console.log(_destAmount);
const slippageFactor = BigInt(1000 - Math.floor(slippage * 10)); // 0.5% becomes 995
diff --git a/src/lib/wagmi-config.ts b/src/lib/wagmi-config.ts
index 68cb342..2db44ed 100644
--- a/src/lib/wagmi-config.ts
+++ b/src/lib/wagmi-config.ts
@@ -1,10 +1,14 @@
import { getDefaultConfig } from '@rainbow-me/rainbowkit'
-import { polygon } from 'viem/chains'
+import { http } from 'viem'
+import { polygon, mainnet, arbitrum, bsc, fantom, blast, linea } from 'viem/chains'
const walletConnectProjectId = import.meta.env.VITE_WALLET_CONNECT_PROJECT_ID
export const wagmiConfig = getDefaultConfig({
appName: 'DEX Playground',
projectId: walletConnectProjectId,
- chains: [polygon],
+ chains: [polygon, mainnet, arbitrum, bsc, fantom, blast, linea],
+ transports: {
+ [mainnet.id]: http(`https://rpcman.orbs.network/rpc?chainId=1&appId=dex-playground`)
+ }
})
diff --git a/src/store.ts b/src/store.ts
new file mode 100644
index 0000000..a663c4b
--- /dev/null
+++ b/src/store.ts
@@ -0,0 +1,18 @@
+import { create } from "zustand";
+import { persist } from "zustand/middleware";
+
+interface AppStore {
+ slippage: number;
+ setSlippage: (slippage: number) => void;
+}
+export const useAppState = create(
+ persist(
+ (set) => ({
+ slippage: 0.5,
+ setSlippage: (slippage: number) => set({ slippage }),
+ }),
+ {
+ name: "main-store",
+ }
+ )
+);
diff --git a/src/tokens.json b/src/tokens.json
new file mode 100644
index 0000000..e69de29
diff --git a/src/trade/hooks.ts b/src/trade/hooks.ts
index 9681e40..9cb69f1 100644
--- a/src/trade/hooks.ts
+++ b/src/trade/hooks.ts
@@ -1,4 +1,4 @@
-import { network, toExactAmount, toRawAmount } from "@/lib";
+import { getNetwork, toExactAmount, toRawAmount } from "@/lib";
import { useMemo } from "react";
import { useChainId } from "wagmi";
@@ -15,7 +15,7 @@ export const useNetwork = () => {
return useMemo(() => {
if (!chainId) return;
- return network[chainId as keyof typeof network];
+ return getNetwork(chainId);
}, [chainId]);
};
diff --git a/src/trade/liquidity-hub/context.tsx b/src/trade/liquidity-hub/context.tsx
index 948b1ab..0780cee 100644
--- a/src/trade/liquidity-hub/context.tsx
+++ b/src/trade/liquidity-hub/context.tsx
@@ -1,107 +1,119 @@
-import { useDefaultTokens, useTokensWithBalances } from "@/lib";
+import { useDefaultTokens } from "@/lib";
import { Token } from "@/types";
-import { constructSDK, LiquidityHubSDK, Quote } from "@orbs-network/liquidity-hub-sdk";
-import { useContext, ReactNode, useReducer, useCallback, useMemo, createContext } from "react";
+import {
+ constructSDK,
+ LiquidityHubSDK,
+ Quote,
+} from "@orbs-network/liquidity-hub-sdk";
+import {
+ useContext,
+ ReactNode,
+ useReducer,
+ useCallback,
+ useMemo,
+ createContext,
+} from "react";
import { useAccount } from "wagmi";
import { useToRawAmount } from "../hooks";
const initialState: State = {
- inToken: null,
- outToken: null,
- inputAmount: "",
- acceptedQuote: undefined,
- liquidityHubDisabled: false,
- slippage: 0.5,
- forceLiquidityHub: false,
- showConfirmation: false,
- };
-
- interface State {
- inToken: Token | null;
- outToken: Token | null;
- inputAmount: string;
- acceptedQuote: Quote | undefined;
- liquidityHubDisabled: boolean;
- slippage: number;
- forceLiquidityHub: boolean;
- showConfirmation: boolean;
- signature?: string;
- isLiquidityHubTrade?: boolean;
- }
-
- type Action = { type: "UPDATE"; payload: Partial } | { type: "RESET" };
-
- const reducer = (state: State, action: Action): State => {
- switch (action.type) {
- case "UPDATE":
- return { ...state, ...action.payload };
- case "RESET":
- return initialState;
- default:
- return state;
- }
- };
-
- interface ContextType {
- state: State;
- updateState: (payload: Partial) => void;
- resetState: () => void;
- sdk: LiquidityHubSDK;
- parsedInputAmount?: string;
+ inToken: null,
+ outToken: null,
+ inputAmount: "",
+ acceptedQuote: undefined,
+ liquidityHubDisabled: false,
+ forceLiquidityHub: false,
+ showConfirmation: false,
+};
+
+interface State {
+ inToken: Token | null;
+ outToken: Token | null;
+ inputAmount: string;
+ acceptedQuote: Quote | undefined;
+ liquidityHubDisabled: boolean;
+ forceLiquidityHub: boolean;
+ showConfirmation: boolean;
+ signature?: string;
+ isLiquidityHubTrade?: boolean;
+}
+
+type Action = { type: "UPDATE"; payload: Partial } | { type: "RESET" };
+
+const reducer = (state: State, action: Action): State => {
+ switch (action.type) {
+ case "UPDATE":
+ return { ...state, ...action.payload };
+ case "RESET":
+ return initialState;
+ default:
+ return state;
}
-
- const Context = createContext({} as ContextType);
- export const useLiquidityHubSwapContext = () => {
- return useContext(Context);
- };
-
+};
+
+interface ContextType {
+ state: State;
+ updateState: (payload: Partial) => void;
+ resetState: () => void;
+ sdk: LiquidityHubSDK;
+ parsedInputAmount?: string;
+}
+
+const Context = createContext({} as ContextType);
+export const useLiquidityHubSwapContext = () => {
+ return useContext(Context);
+};
+
+export const LiquidityHubSwapProvider = ({
+ children,
+}: {
+ children: ReactNode;
+}) => {
+ const [_state, dispatch] = useReducer(reducer, initialState);
+ const defaultTokens = useDefaultTokens();
+
+ const state = useMemo(() => {
+ return {
+ ..._state,
+ inToken: _state.inToken || defaultTokens?.inToken || null,
+ outToken: _state.outToken || defaultTokens?.outToken || null,
+ };
+ }, [_state, defaultTokens]);
+
+ const { chainId } = useAccount();
+
+ const parsedInputAmount = useToRawAmount(
+ state.inputAmount,
+ state.inToken?.decimals
+ );
+
+ const updateState = useCallback(
+ (payload: Partial) => {
+ dispatch({ type: "UPDATE", payload });
+ },
+ [dispatch]
+ );
+
+ const resetState = useCallback(() => {
+ dispatch({ type: "RESET" });
+ }, [dispatch]);
+
+ const sdk = useMemo(
+ () => constructSDK({ partner: "widget", chainId }),
+ [chainId]
+ );
- export const LiquidityHubSwapProvider = ({ children }: { children: ReactNode }) => {
- const [state, dispatch] = useReducer(reducer, initialState);
- const { chainId } = useAccount();
- const { tokensWithBalances, refetch: refetchBalances } =
- useTokensWithBalances();
- const parsedInputAmount = useToRawAmount(
- state.inputAmount,
- state.inToken?.decimals
- );
-
- const updateState = useCallback(
- (payload: Partial) => {
- dispatch({ type: "UPDATE", payload });
- },
- [dispatch]
- );
-
- const resetState = useCallback(() => {
- dispatch({ type: "RESET" });
- refetchBalances();
- }, [dispatch, refetchBalances]);
-
- const sdk = useMemo(
- () => constructSDK({ partner: "widget", chainId }),
- [chainId]
- );
-
- useDefaultTokens({
- inToken: state.inToken,
- outToken: state.outToken,
- tokensWithBalances,
- setInToken: (token) => updateState({ inToken: token }),
- setOutToken: (token) => updateState({ outToken: token }),
- });
-
- return (
-
- {children}
-
- );
- };
\ No newline at end of file
+ return (
+
+ {children}
+
+ );
+};
diff --git a/src/trade/liquidity-hub/hooks.ts b/src/trade/liquidity-hub/hooks.ts
index 54a8e34..5f3ede3 100644
--- a/src/trade/liquidity-hub/hooks.ts
+++ b/src/trade/liquidity-hub/hooks.ts
@@ -5,10 +5,10 @@ import {
useInputError,
getMinAmountOut,
useGetRequiresApproval,
- network,
networks,
isNativeAddress,
} from "@/lib";
+import { useAppState } from "@/store";
import { permit2Address } from "@orbs-network/liquidity-hub-sdk";
import { useQueryClient, useQuery } from "@tanstack/react-query";
import { useMemo, useCallback } from "react";
@@ -19,9 +19,7 @@ import { useLiquidityHubSwapContext } from "./context";
export const QUOTE_REFETCH_INTERVAL = 20_000;
export const useParaswapMinAmountOut = () => {
- const {
- state: { slippage },
- } = useLiquidityHubSwapContext();
+ const { slippage } = useAppState();
const optimalRate = useOptimalRate().data;
return useMemo(() => {
return getMinAmountOut(slippage, optimalRate?.destAmount || "0");
@@ -31,8 +29,10 @@ export const useParaswapMinAmountOut = () => {
export function useLiquidityHubQuote() {
const queryClient = useQueryClient();
const { chainId, address: account } = useAccount();
+ const { slippage } = useAppState();
+
const {
- state: { inToken, outToken, liquidityHubDisabled, slippage },
+ state: { inToken, outToken, liquidityHubDisabled },
sdk,
parsedInputAmount,
} = useLiquidityHubSwapContext();
@@ -144,6 +144,7 @@ export const useLiquidityHubInputError = () => {
const {
state: { inToken, inputAmount },
} = useLiquidityHubSwapContext();
+
return useInputError({
inputAmount,
inToken,
diff --git a/src/trade/liquidity-hub/liquidity-hub-confirmation-dialog.tsx b/src/trade/liquidity-hub/liquidity-hub-confirmation-dialog.tsx
index 80d8237..f5e1a78 100644
--- a/src/trade/liquidity-hub/liquidity-hub-confirmation-dialog.tsx
+++ b/src/trade/liquidity-hub/liquidity-hub-confirmation-dialog.tsx
@@ -10,6 +10,7 @@ import {
getErrorMessage,
getLiquidityProviderName,
getSteps,
+ isNativeAddress,
promiseWithTimeout,
toExactAmount,
useParaswapBuildTxCallback,
@@ -39,7 +40,8 @@ import { _TypedDataEncoder } from "@ethersproject/hash";
import { permit2Address, Quote } from "@orbs-network/liquidity-hub-sdk";
import { TransactionParams } from "@paraswap/sdk";
import { toast } from "sonner";
-import { useToExactAmount } from "../hooks";
+import { useNetwork, useToExactAmount } from "../hooks";
+import { useAppState } from "@/store";
// Construct steps for swap to display in UI
const useSteps = (steps?: number[]) => {
@@ -107,9 +109,9 @@ export function LiquidityHubConfirmationDialog({
const approvalLoading = isLiquidityHubTrade
? liquidityHubApproval.approvalLoading
: paraswapApproval.approvalLoading;
+
const onSubmit = useCallback(async () => {
if (!isLiquidityHubTrade) {
- console.log("Proceeding with Liquidity Hub");
swapWithParaswap();
} else {
swapWithLiquidityHub();
@@ -241,23 +243,24 @@ const Details = () => {
const {
state: { outToken, isLiquidityHubTrade },
} = useLiquidityHubSwapContext();
- const outAmountUsd = optimalRate?.destUSD;
- const outAmount = isLiquidityHubTrade
- ? quote?.outAmount
- : optimalRate?.destAmount;
+ const outTokenUsd = usePriceUsd(outToken?.address).data;
const gasPrice = useMemo(() => {
- const gasAmountOut = isLiquidityHubTrade
- ? toExactAmount(quote?.gasAmountOut, outToken?.decimals)
- : BN(optimalRate?.gasCost || 0)
- .dividedBy(1e18)
- .toString();
-
- if (!outAmountUsd || !gasAmountOut || !outToken) return 0;
- const gas = toExactAmount(gasAmountOut, outToken.decimals);
- const usd = Number(outAmountUsd) / Number(outAmount);
- return Number(gas) * usd;
- }, [outAmountUsd, outToken, outAmount, quote, isLiquidityHubTrade]);
+ if (!isLiquidityHubTrade) {
+ return Number(optimalRate?.gasCostUSD || "0");
+ }
+
+ if (!outToken || !outTokenUsd) return 0;
+ const gas = toExactAmount(quote?.gasAmountOut, outToken.decimals);
+
+ return Number(gas) * outTokenUsd;
+ }, [
+ isLiquidityHubTrade,
+ optimalRate?.gasCostUSD,
+ outToken,
+ outTokenUsd,
+ quote?.gasAmountOut,
+ ]);
return (
@@ -293,10 +296,12 @@ export const useParaswapSwapCallback = (
const buildParaswapTxCallback = useParaswapBuildTxCallback();
const optimalRate = useOptimalRate().data;
const {
- state: { slippage, inToken },
+ state: { inToken },
} = useLiquidityHubSwapContext();
+ const { slippage } = useAppState();
+ const wToken = useNetwork()?.wToken.address;
const requiresApproval = useParaswapApproval().requiresApproval;
-
+
const { address } = useAccount();
return useMutation({
@@ -312,6 +317,9 @@ export const useParaswapSwapCallback = (
if (!optimalRate) {
throw new Error("No optimal rate found");
}
+ if (!wToken) {
+ throw new Error("WToken not found");
+ }
try {
updateSwapProgressState({ swapStatus: SwapStatus.LOADING });
@@ -326,7 +334,7 @@ export const useParaswapSwapCallback = (
updateSwapProgressState({ currentStep: SwapSteps.Approve });
await approveAllowance(
address,
- optimalRate.srcToken,
+ isNativeAddress(inToken.address) ? wToken : inToken.address,
optimalRate.tokenTransferProxy as Address
);
}
@@ -453,7 +461,7 @@ async function signTransaction(quote: Quote, analyticsEvents: AnalyticsEvents) {
// Sign transaction and get signature
const signature = await promiseWithTimeout
(
- signTypedData(wagmiConfig, payload),
+ (signTypedData as any)(wagmiConfig, payload),
40_000
);
@@ -476,9 +484,11 @@ export function useLiquidityHubSwapCallback(
) {
const {
sdk: liquidityHub,
- state: { inToken, slippage },
+ state: { inToken },
updateState,
} = useLiquidityHubSwapContext();
+ const { slippage } = useAppState();
+
const buildParaswapTxCallback = useParaswapBuildTxCallback();
const optimalRate = useOptimalRate().data;
const { getLatestQuote, data: quote } = useLiquidityHubQuote();
diff --git a/src/trade/liquidity-hub/liquidity-hub-swap.tsx b/src/trade/liquidity-hub/liquidity-hub-swap.tsx
index f9780d3..9f8322f 100644
--- a/src/trade/liquidity-hub/liquidity-hub-swap.tsx
+++ b/src/trade/liquidity-hub/liquidity-hub-swap.tsx
@@ -6,24 +6,9 @@ import { Button } from "@/components/ui/button";
import { _TypedDataEncoder } from "@ethersproject/hash";
import { SwapStatus } from "@orbs-network/swap-ui";
import { Token } from "@/types";
-import {
- ErrorCodes,
- format,
- getLiquidityProviderName,
- getMinAmountOut,
- getQuoteErrorMessage,
- toExactAmount,
-} from "@/lib";
+import { ErrorCodes } from "@/lib";
import "../style.css";
import { useConnectModal } from "@rainbow-me/rainbowkit";
-import { SettingsIcon } from "lucide-react";
-import {
- Popover,
- PopoverContent,
- PopoverTrigger,
-} from "@/components/ui/popover";
-import { Label } from "@/components/ui/label";
-import { Input } from "@/components/ui/input";
import BN from "bignumber.js";
import {
LiquidityHubSwapProvider,
@@ -37,8 +22,7 @@ import {
useOptimalRate,
useParaswapMinAmountOut,
} from "./hooks";
-import { DataDetails } from "@/components/ui/data-details";
-import { Separator } from "@radix-ui/react-dropdown-menu";
+import { SwapDetails } from "./swap-details";
export const useIsLiquidityHubTrade = () => {
const {
@@ -47,8 +31,6 @@ export const useIsLiquidityHubTrade = () => {
const liquidityHubQuote = useLiquidityHubQuote().data;
const paraswapMinAmountOut = useParaswapMinAmountOut();
- console.log(liquidityHubQuote?.minAmountOut, paraswapMinAmountOut);
-
return useMemo(() => {
// Choose between liquidity hub and dex swap based on the min amount out
if (liquidityHubDisabled) return false;
@@ -64,28 +46,11 @@ export const useIsLiquidityHubTrade = () => {
};
function SwapPanel() {
- const {
- state: { inToken, outToken },
- updateState,
- } = useLiquidityHubSwapContext();
-
- // Handle Token Switch
- const handleSwitch = useCallback(() => {
- updateState({
- inToken: outToken,
- outToken: inToken,
- inputAmount: "",
- });
- }, [inToken, outToken, updateState]);
-
return (
-
-
-
-
+
@@ -94,40 +59,23 @@ function SwapPanel() {
);
}
-const Settings = () => {
+const Switch = () => {
const {
- state: { slippage },
+ state: { inToken, outToken },
updateState,
} = useLiquidityHubSwapContext();
+
+ const handleSwitch = useCallback(() => {
+ updateState({
+ inToken: outToken,
+ outToken: inToken,
+ inputAmount: "",
+ });
+ }, [inToken, outToken, updateState]);
+
return (
-
-
-
-
-
-
-
-
-
-
-
- updateState({ slippage: e.target.valueAsNumber })
- }
- value={slippage}
- step={0.1}
- className="text-right w-16 [&::-webkit-inner-spin-button]:appearance-none p-2 h-7"
- />
-
%
-
-
-
-
-
+
+
);
};
@@ -138,6 +86,7 @@ const ConfirmationModal = () => {
const { data: liquidityHubQuote } = useLiquidityHubQuote();
const { data: optimalRate, isLoading: optimalRateLoading } = useOptimalRate();
const inputError = useLiquidityHubInputError();
+
const isLiquidityHubTrade = useIsLiquidityHubTrade();
const {
state: { inputAmount },
@@ -157,11 +106,6 @@ const ConfirmationModal = () => {
text: "Enter amount",
};
}
- if (inputAmount && optimalRateLoading) {
- return {
- text: "Fetching quote...",
- };
- }
if (!optimalRate && inputAmount) {
return {
@@ -191,7 +135,7 @@ const ConfirmationModal = () => {
setIsOpen(false);
updateState({ isLiquidityHubTrade: false });
if (status === SwapStatus.SUCCESS) {
- updateState({inputAmount: ''});
+ updateState({ inputAmount: "" });
}
},
[resetState]
@@ -215,61 +159,6 @@ const ConfirmationModal = () => {
);
};
-export function SwapDetails() {
- const isLiquidityHubTrade = useIsLiquidityHubTrade();
- const optimalRate = useOptimalRate().data;
- const account = useAccount().address;
- const {
- state: { outToken, inToken },
- } = useLiquidityHubSwapContext();
- const minAmountOut = useParaswapMinAmountOut();
- const inPriceUsd = useMemo(() => {
- if (!optimalRate) return 0;
- const amount = toExactAmount(optimalRate.srcAmount, inToken?.decimals);
- return Number(optimalRate.srcUSD) / Number(amount);
- }, [optimalRate, inToken]);
-
- const minOutAmount = useToExactAmount(minAmountOut, outToken?.decimals);
- const outAmount = useToExactAmount(
- optimalRate?.destAmount,
- outToken?.decimals
- );
-
- const outPriceUsd = useMemo(() => {
- if (!optimalRate) return 0;
- const amount = toExactAmount(optimalRate.destAmount, outToken?.decimals);
- return Number(optimalRate.destUSD) / Number(amount);
- }, [optimalRate, outToken]);
-
- if (!inToken || !outToken || !account || !optimalRate) return null;
-
- const rate = inPriceUsd / outPriceUsd;
-
- let data: Record
= {
- Rate: `1 ${inToken.symbol} ≈ ${format.crypto(rate)} ${outToken.symbol}`,
- };
-
- data = {
- ...data,
- "Est. Received": `${format.crypto(Number(outAmount))} ${outToken.symbol}`,
- "Min. Received": `${format.crypto(Number(minOutAmount))} ${
- outToken.symbol
- }`,
- "Routing source": getLiquidityProviderName(isLiquidityHubTrade),
- };
-
- return (
-
-
-
-
-
Recepient
-
{format.address(account)}
-
-
- );
-}
-
const InTokenCard = () => {
const {
state: { inputAmount, inToken },
@@ -336,7 +225,7 @@ const OutTokenCard = () => {
);
};
-export const Swap = () => {
+export const SwapLiquidityHub = () => {
return (
diff --git a/src/trade/liquidity-hub/swap-details.tsx b/src/trade/liquidity-hub/swap-details.tsx
new file mode 100644
index 0000000..059eb23
--- /dev/null
+++ b/src/trade/liquidity-hub/swap-details.tsx
@@ -0,0 +1,64 @@
+import { DataDetails } from "@/components/ui/data-details";
+import { toExactAmount, getLiquidityProviderName, format } from "@/lib";
+import { Separator } from "@radix-ui/react-dropdown-menu";
+import { useMemo } from "react";
+import { useAccount } from "wagmi";
+import { useToExactAmount } from "../hooks";
+import { useLiquidityHubSwapContext } from "./context";
+import { useOptimalRate, useParaswapMinAmountOut } from "./hooks";
+import { useIsLiquidityHubTrade } from "./liquidity-hub-swap";
+
+ export function SwapDetails() {
+ const isLiquidityHubTrade = useIsLiquidityHubTrade();
+ const optimalRate = useOptimalRate().data;
+ const account = useAccount().address;
+ const {
+ state: { outToken, inToken },
+ } = useLiquidityHubSwapContext();
+ const minAmountOut = useParaswapMinAmountOut();
+ const inPriceUsd = useMemo(() => {
+ if (!optimalRate) return 0;
+ const amount = toExactAmount(optimalRate.srcAmount, inToken?.decimals);
+ return Number(optimalRate.srcUSD) / Number(amount);
+ }, [optimalRate, inToken]);
+
+ const minOutAmount = useToExactAmount(minAmountOut, outToken?.decimals);
+ const outAmount = useToExactAmount(
+ optimalRate?.destAmount,
+ outToken?.decimals
+ );
+
+ const outPriceUsd = useMemo(() => {
+ if (!optimalRate) return 0;
+ const amount = toExactAmount(optimalRate.destAmount, outToken?.decimals);
+ return Number(optimalRate.destUSD) / Number(amount);
+ }, [optimalRate, outToken]);
+
+ if (!inToken || !outToken || !account || !optimalRate) return null;
+
+ const rate = inPriceUsd / outPriceUsd;
+
+ let data: Record = {
+ Rate: `1 ${inToken.symbol} ≈ ${format.crypto(rate)} ${outToken.symbol}`,
+ };
+
+ data = {
+ ...data,
+ "Est. Received": `${format.crypto(Number(outAmount))} ${outToken.symbol}`,
+ "Min. Received": `${format.crypto(Number(minOutAmount))} ${
+ outToken.symbol
+ }`,
+ "Routing source": getLiquidityProviderName(isLiquidityHubTrade),
+ };
+
+ return (
+
+
+
+
+
Recepient
+
{format.address(account)}
+
+
+ );
+ }
\ No newline at end of file
diff --git a/src/trade/settings.tsx b/src/trade/settings.tsx
new file mode 100644
index 0000000..7f93379
--- /dev/null
+++ b/src/trade/settings.tsx
@@ -0,0 +1,43 @@
+import { Button } from "@/components/ui/button";
+import { Input } from "@/components/ui/input";
+import { Label } from "@/components/ui/label";
+import {
+ Popover,
+ PopoverContent,
+ PopoverTrigger,
+} from "@/components/ui/popover";
+import { useAppState } from "@/store";
+import { SettingsIcon } from "lucide-react";
+
+export const Settings = () => {
+ const { slippage, setSlippage } = useAppState();
+ return (
+
+
+
+
+
+
+
+
+
+
+
setSlippage(e.target.valueAsNumber)}
+ value={slippage}
+ step={0.1}
+ className="text-right w-16 [&::-webkit-inner-spin-button]:appearance-none p-2 h-7"
+ />
+
%
+
+
+
+
+
+
+ );
+};
diff --git a/src/trade/trade.tsx b/src/trade/trade.tsx
deleted file mode 100644
index aa8f880..0000000
--- a/src/trade/trade.tsx
+++ /dev/null
@@ -1,28 +0,0 @@
-import { Tabs, TabsContent, TabsList, TabsTrigger } from '@/components/ui/tabs'
-import { Swap } from './liquidity-hub/liquidity-hub-swap'
-import { Twap } from './twap/twap'
-
-export function Trade() {
- return (
-
-
Trade
-
-
-
- Swap
- TWAP
- Limit
-
-
-
-
-
-
-
-
-
-
-
-
- )
-}
diff --git a/src/trade/twap/components/inputs.tsx b/src/trade/twap/components/inputs.tsx
index e5819f4..6908c5f 100644
--- a/src/trade/twap/components/inputs.tsx
+++ b/src/trade/twap/components/inputs.tsx
@@ -12,7 +12,7 @@ import { TimeUnit } from "@orbs-network/twap-sdk";
import { useMemo } from "react";
import { NumericFormat } from "react-number-format";
import { useDerivedTwapSwapData } from "../hooks";
-import { useTwapContext } from "../twap-context";
+import { useTwapContext } from "../context";
const options: { text: string; unit: TimeUnit }[] = [
{
diff --git a/src/trade/twap/components/limit-price-input.tsx b/src/trade/twap/components/limit-price-input.tsx
index 0a17a62..2357ede 100644
--- a/src/trade/twap/components/limit-price-input.tsx
+++ b/src/trade/twap/components/limit-price-input.tsx
@@ -2,11 +2,9 @@ import { Token } from "@/types";
import { NumericFormat } from "react-number-format";
import {
format,
- networks,
toExactAmount,
toRawAmount,
usePriceUsd,
- useTokensWithBalances,
} from "@/lib";
import { Card } from "@/components/ui/card";
import { Skeleton } from "@/components/ui/skeleton";
@@ -16,7 +14,7 @@ import { Button } from "@/components/ui/button";
import BN from "bignumber.js";
import { ArrowUpDown, X } from "lucide-react";
import { Avatar, AvatarImage } from "@/components/ui/avatar";
-import { useTwapContext } from "../twap-context";
+import { useTwapContext } from "../context";
import { useMarketPrice, useTradePrice } from "../hooks";
const useMarketPriceUI = () => {
diff --git a/src/trade/twap/components/price-toggle.tsx b/src/trade/twap/components/price-toggle.tsx
index 32c9c14..6fdb938 100644
--- a/src/trade/twap/components/price-toggle.tsx
+++ b/src/trade/twap/components/price-toggle.tsx
@@ -1,6 +1,6 @@
import { Switch } from "@/components/ui/switch";
import{ useCallback } from "react";
-import { useTwapContext } from "../twap-context";
+import { useTwapContext } from "../context";
export function PriceToggle() {
const {
diff --git a/src/trade/twap/components/src-chunk-size.tsx b/src/trade/twap/components/src-chunk-size.tsx
index 7866f23..3c7d472 100644
--- a/src/trade/twap/components/src-chunk-size.tsx
+++ b/src/trade/twap/components/src-chunk-size.tsx
@@ -1,7 +1,7 @@
import { usePriceUsd } from "@/lib";
import { useToExactAmount } from "@/trade/hooks";
import { useDerivedTwapSwapData } from "../hooks";
-import { useTwapContext } from "../twap-context";
+import { useTwapContext } from "../context";
export function SrcChunkSize() {
const { state } = useTwapContext();
diff --git a/src/trade/twap/twap-context.tsx b/src/trade/twap/context.tsx
similarity index 89%
rename from src/trade/twap/twap-context.tsx
rename to src/trade/twap/context.tsx
index 29a9e53..a73686f 100644
--- a/src/trade/twap/twap-context.tsx
+++ b/src/trade/twap/context.tsx
@@ -1,3 +1,4 @@
+import { useDefaultTokens } from "@/lib";
import { Token } from "@/types";
import {
Configs,
@@ -61,12 +62,24 @@ type TwapState = {
const initialState = {typedAmount: ''} as TwapState;
const useTwapState = () => {
- const [values, dispatch] = useReducer(
+ const [_values, dispatch] = useReducer(
(state: TwapState, action: Action) =>
reducer(state, action, initialState),
initialState
);
+ const defaultTokens = useDefaultTokens();
+
+
+ const values = useMemo(() => {
+ return {
+ ..._values,
+ inToken: _values.inToken || defaultTokens?.inToken || null,
+ outToken: _values.outToken || defaultTokens?.outToken || null,
+ }
+ }, [_values, defaultTokens?.inToken, defaultTokens?.outToken])
+
+
const updateState = useCallback(
(payload: Partial) => {
dispatch({ type: "UPDATE_STATE", payload });
diff --git a/src/trade/twap/hooks.ts b/src/trade/twap/hooks.ts
index d2c323f..d012b23 100644
--- a/src/trade/twap/hooks.ts
+++ b/src/trade/twap/hooks.ts
@@ -5,7 +5,7 @@ import {
usePriceUsd,
} from "@/lib";
import { useMemo } from "react";
-import { useTwapContext } from "./twap-context";
+import { useTwapContext } from "./context";
import BN from "bignumber.js";
import { useToExactAmount, useToRawAmount } from "../hooks";
import {
diff --git a/src/trade/twap/orders/orders.tsx b/src/trade/twap/orders/orders.tsx
index d346732..fb24845 100644
--- a/src/trade/twap/orders/orders.tsx
+++ b/src/trade/twap/orders/orders.tsx
@@ -18,7 +18,7 @@ import {
eqIgnoreCase,
format,
makeElipsisAddress,
- useTokensList,
+ useSortedTokens,
wagmiConfig,
waitForConfirmations,
} from "@/lib";
@@ -33,7 +33,7 @@ import { useGroupedOrders, useOrdersQuery } from "./use-orders-query";
import { useExplorer, useToExactAmount } from "@/trade/hooks";
import moment from "moment";
import { useMutation } from "@tanstack/react-query";
-import { useTwapContext } from "../twap-context";
+import { useTwapContext } from "../context";
import {
writeContract,
simulateContract,
@@ -118,11 +118,11 @@ const OrdersMenu = () => {
};
const useToken = (tokenAddress?: string) => {
- const { data } = useTokensList();
+ const tokens = useSortedTokens()
return useMemo(
- () => data?.find((it) => eqIgnoreCase(it.address, tokenAddress || "")),
- [data, tokenAddress]
+ () => tokens?.find((it) => eqIgnoreCase(it.address, tokenAddress || "")),
+ [tokens, tokenAddress]
);
};
diff --git a/src/trade/twap/orders/use-orders-query.ts b/src/trade/twap/orders/use-orders-query.ts
index 8bf6649..217feb2 100644
--- a/src/trade/twap/orders/use-orders-query.ts
+++ b/src/trade/twap/orders/use-orders-query.ts
@@ -2,7 +2,7 @@ import { groupOrdersByStatus } from "@orbs-network/twap-sdk";
import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
import { useMemo } from "react";
import { useAccount } from "wagmi";
-import { useTwapContext } from "../twap-context";
+import { useTwapContext } from "../context";
const useOrdersQueryKey = () => {
const { address } = useAccount();
diff --git a/src/trade/twap/twap-confirmation-dialog.tsx b/src/trade/twap/twap-confirmation-dialog.tsx
index bf162a4..46afa3c 100644
--- a/src/trade/twap/twap-confirmation-dialog.tsx
+++ b/src/trade/twap/twap-confirmation-dialog.tsx
@@ -8,7 +8,7 @@ import {
useInTokenUsd,
useOutTokenUsd,
} from "./hooks";
-import { useTwapContext } from "./twap-context";
+import { useTwapContext } from "./context";
import {
format,
resolveNativeTokenAddress,
diff --git a/src/trade/twap/twap.tsx b/src/trade/twap/twap.tsx
index 5b14fb7..0ce5a53 100644
--- a/src/trade/twap/twap.tsx
+++ b/src/trade/twap/twap.tsx
@@ -3,27 +3,15 @@ import { SwitchButton } from "@/components/ui/switch-button";
import { useCallback, useState } from "react";
import { useAccount } from "wagmi";
import { Button } from "@/components/ui/button";
-import {
- useDefaultTokens,
- useTokensWithBalances,
- useTokenBalance,
-} from "@/lib";
+import { useTokenBalaces } from "@/lib";
import "../style.css";
import { useConnectModal } from "@rainbow-me/rainbowkit";
-import { SettingsIcon } from "lucide-react";
-import {
- Popover,
- PopoverContent,
- PopoverTrigger,
-} from "@/components/ui/popover";
-import { Label } from "@/components/ui/label";
-import { Input } from "@/components/ui/input";
import { LimitPriceInput } from "./components/limit-price-input";
import {
TwapContextProvider,
useTwapContext,
useTwapStateActions,
-} from "./twap-context";
+} from "./context";
import {
useDerivedTwapSwapData,
useInputLabels,
@@ -40,29 +28,17 @@ import { SwapStatus } from "@orbs-network/swap-ui";
import { Orders } from "./orders/orders";
export function Panel() {
- const { tokensWithBalances, refetch: refetchBalances } =
- useTokensWithBalances();
- const [slippage, setSlippage] = useState(0.5);
+ const { refetch: refetchBalances } = useTokenBalaces();
// Get wagmi account
const account = useAccount();
const { state } = useTwapContext();
const {
- updateState,
resetState,
values: { inToken, outToken, typedAmount },
} = state;
- // Set Initial Tokens
- const defaultTokens = useDefaultTokens({
- inToken,
- outToken,
- tokensWithBalances,
- setInToken: (token) => updateState({ inToken: token }),
- setOutToken: (token) => updateState({ outToken: token }),
- });
-
const inputError = useTwapInputError();
const { setInToken, setInputAmount, setOutToken, onSwitchTokens } =
useTwapStateActions();
@@ -92,33 +68,6 @@ export function Panel() {
const amountLoading = Boolean(inToken && !marketPrice);
return (
-
-
-
-
-
-
-
-
-
-
-
setSlippage(e.target.valueAsNumber)}
- value={slippage}
- step={0.1}
- className="text-right w-16 [&::-webkit-inner-spin-button]:appearance-none p-2 h-7"
- />
-
%
-
-
-
-
-
-
@@ -126,7 +75,7 @@ export function Panel() {
label={inputLabel}
amount={typedAmount}
amountUsd={inAmountUsd}
- selectedToken={inToken || defaultTokens[0]}
+ selectedToken={inToken}
onSelectToken={setInToken}
onValueChange={setInputAmount}
inputError={inputError}
@@ -138,7 +87,7 @@ export function Panel() {
label={outputLabel}
amount={destAmount ?? ""}
amountUsd={outAmountUsd}
- selectedToken={outToken || defaultTokens[1]}
+ selectedToken={outToken}
onSelectToken={setOutToken}
isAmountEditable={false}
amountLoading={amountLoading}
@@ -167,10 +116,15 @@ export function Panel() {
);
}
-export const Twap = ({ isLimitPanel }: { isLimitPanel?: boolean }) => {
+export const SwapTwap = ({ isLimitPanel }: { isLimitPanel?: boolean }) => {
return (
);
};
+
+
+export const SwapLimit = () => {
+ return
+}
\ No newline at end of file
diff --git a/tsconfig.app.tsbuildinfo b/tsconfig.app.tsbuildinfo
index f7a97e0..c14af47 100644
--- a/tsconfig.app.tsbuildinfo
+++ b/tsconfig.app.tsbuildinfo
@@ -1 +1 @@
-{"root":["./src/app.tsx","./src/main.tsx","./src/root.tsx","./src/types.ts","./src/vite-env.d.ts","./src/components/header.tsx","./src/components/order-details.tsx","./src/components/spinner.tsx","./src/components/swap-details.tsx","./src/components/theme-toggle.tsx","./src/components/tokens/token-card.tsx","./src/components/tokens/token-select.tsx","./src/components/ui/avatar.tsx","./src/components/ui/button.tsx","./src/components/ui/card.tsx","./src/components/ui/data-details.tsx","./src/components/ui/dialog.tsx","./src/components/ui/dropdown-menu.tsx","./src/components/ui/input.tsx","./src/components/ui/label.tsx","./src/components/ui/popover.tsx","./src/components/ui/separator.tsx","./src/components/ui/skeleton.tsx","./src/components/ui/sonner.tsx","./src/components/ui/switch-button.tsx","./src/components/ui/switch.tsx","./src/components/ui/tabs.tsx","./src/components/ui/tooltip.tsx","./src/lib/abis.ts","./src/lib/approveallowance.ts","./src/lib/getrequiresapproval.ts","./src/lib/index.ts","./src/lib/networks.ts","./src/lib/usebalances.ts","./src/lib/usedebounce.ts","./src/lib/usedefaulttokens.ts","./src/lib/usegetrequiresapproval.ts","./src/lib/usehandleinputerror.ts","./src/lib/useparaswap.ts","./src/lib/usepriceusd.ts","./src/lib/usetokenlist.ts","./src/lib/usetokenswithbalances.ts","./src/lib/usewraporunwraponly.ts","./src/lib/utils.ts","./src/lib/wagmi-config.ts","./src/lib/wraptoken.ts","./src/providers/rainbow-provider.tsx","./src/providers/theme-provider.tsx","./src/trade/hooks.ts","./src/trade/swap-confirmation-dialog.tsx","./src/trade/trade.tsx","./src/trade/use-swap-state.ts","./src/trade/liquidity-hub/liquidity-hub-confirmation-dialog.tsx","./src/trade/liquidity-hub/liquidity-hub-swap.tsx","./src/trade/liquidity-hub/useliquidityhubquote.ts","./src/trade/liquidity-hub/useliquidityhubsdk.ts","./src/trade/liquidity-hub/useliquidityhubswapcallback.ts","./src/trade/twap/hooks.ts","./src/trade/twap/twap-confirmation-dialog.tsx","./src/trade/twap/twap-context.tsx","./src/trade/twap/twap.tsx","./src/trade/twap/utils.ts","./src/trade/twap/components/inputs.tsx","./src/trade/twap/components/limit-price-input.tsx","./src/trade/twap/components/price-toggle.tsx","./src/trade/twap/components/src-chunk-size.tsx","./src/trade/twap/orders/orders-context.tsx","./src/trade/twap/orders/orders.tsx","./src/trade/twap/orders/use-orders-query.ts"],"version":"5.6.3"}
\ No newline at end of file
+{"root":["./src/app.tsx","./src/main.tsx","./src/root.tsx","./src/store.ts","./src/types.ts","./src/vite-env.d.ts","./src/components/header.tsx","./src/components/order-details.tsx","./src/components/spinner.tsx","./src/components/theme-toggle.tsx","./src/components/tokens/token-card.tsx","./src/components/tokens/token-select.tsx","./src/components/ui/avatar.tsx","./src/components/ui/button.tsx","./src/components/ui/card.tsx","./src/components/ui/data-details.tsx","./src/components/ui/dialog.tsx","./src/components/ui/dropdown-menu.tsx","./src/components/ui/input.tsx","./src/components/ui/label.tsx","./src/components/ui/popover.tsx","./src/components/ui/separator.tsx","./src/components/ui/skeleton.tsx","./src/components/ui/sonner.tsx","./src/components/ui/switch-button.tsx","./src/components/ui/switch.tsx","./src/components/ui/tabs.tsx","./src/components/ui/tooltip.tsx","./src/lib/abis.ts","./src/lib/approveallowance.ts","./src/lib/getrequiresapproval.ts","./src/lib/index.ts","./src/lib/networks.ts","./src/lib/usedebounce.ts","./src/lib/usedefaulttokens.ts","./src/lib/usegetrequiresapproval.ts","./src/lib/usehandleinputerror.ts","./src/lib/useparaswap.ts","./src/lib/usepriceusd.ts","./src/lib/usetokens.ts","./src/lib/usewraporunwraponly.ts","./src/lib/utils.ts","./src/lib/wagmi-config.ts","./src/lib/wraptoken.ts","./src/providers/rainbow-provider.tsx","./src/providers/theme-provider.tsx","./src/trade/hooks.ts","./src/trade/settings.tsx","./src/trade/swap-confirmation-dialog.tsx","./src/trade/liquidity-hub/context.tsx","./src/trade/liquidity-hub/hooks.ts","./src/trade/liquidity-hub/liquidity-hub-confirmation-dialog.tsx","./src/trade/liquidity-hub/liquidity-hub-swap.tsx","./src/trade/liquidity-hub/swap-details.tsx","./src/trade/twap/context.tsx","./src/trade/twap/hooks.ts","./src/trade/twap/twap-confirmation-dialog.tsx","./src/trade/twap/twap.tsx","./src/trade/twap/utils.ts","./src/trade/twap/components/inputs.tsx","./src/trade/twap/components/limit-price-input.tsx","./src/trade/twap/components/price-toggle.tsx","./src/trade/twap/components/src-chunk-size.tsx","./src/trade/twap/orders/orders-context.tsx","./src/trade/twap/orders/orders.tsx","./src/trade/twap/orders/use-orders-query.ts"],"version":"5.6.3"}
\ No newline at end of file
diff --git a/yarn.lock b/yarn.lock
index 883989b..156aa9d 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -983,10 +983,10 @@
"@nodelib/fs.scandir" "2.1.5"
fastq "^1.6.0"
-"@orbs-network/liquidity-hub-sdk@^1.0.41":
- version "1.0.41"
- resolved "https://registry.yarnpkg.com/@orbs-network/liquidity-hub-sdk/-/liquidity-hub-sdk-1.0.41.tgz#9d19adf60df4a546217eb2f08f9691856bd8416e"
- integrity sha512-dYDtvCwYI6y0zXYQs8VgrlR+XlFyxgG4a+FOtOHcHCX8ZlPyp7DiwppFl9ly4qMEKM0IFxlnny1fyOTWAHYmuA==
+"@orbs-network/liquidity-hub-sdk@^1.0.44":
+ version "1.0.44"
+ resolved "https://registry.yarnpkg.com/@orbs-network/liquidity-hub-sdk/-/liquidity-hub-sdk-1.0.44.tgz#244c4e26bbeef75d48a8ca041fa730c5885e6a17"
+ integrity sha512-5IpPDNUVdnzv2+4MdLDFHjJQfPqn+NWj1EqBcdKgZ3YLELwYrgJ8O+38Tuy7iU1fS/OR07f7BvRyczywkGPRJA==
"@orbs-network/swap-ui@^0.0.14":
version "0.0.14"