diff --git a/.gitignore b/.gitignore index da16fbfe..66726c25 100644 --- a/.gitignore +++ b/.gitignore @@ -4,6 +4,7 @@ /coverage /build .DS_Store +.idea .env.local .env.development.local .env.test.local diff --git a/src/index.tsx b/src/Swap.tsx similarity index 80% rename from src/index.tsx rename to src/Swap.tsx index ecc7109f..b4363d7d 100644 --- a/src/index.tsx +++ b/src/Swap.tsx @@ -1,33 +1,18 @@ import { ReactElement } from "react"; -import { PublicKey } from "@solana/web3.js"; -import { TokenListContainer } from "@solana/spl-token-registry"; -import { Provider } from "@project-serum/anchor"; import { Swap as SwapClient } from "@project-serum/swap"; import { createMuiTheme, ThemeOptions, ThemeProvider, } from "@material-ui/core/styles"; -import { - SwapContextProvider, - useSwapContext, - useSwapFair, -} from "./context/Swap"; -import { - DexContextProvider, - useBbo, - useFairRoute, - useMarketName, -} from "./context/Dex"; -import { TokenListContextProvider, useTokenMap } from "./context/TokenList"; -import { TokenContextProvider, useMint } from "./context/Token"; -import SwapCard, { - ArrowButton, - SwapButton, - SwapHeader, - SwapTokenForm, -} from "./components/Swap"; -import TokenDialog from "./components/TokenDialog"; +import { TokenListContextProvider } from "./context/TokenList"; +import { TokenContextProvider } from "./context/Token"; +import { DexContextProvider } from "./context/Dex"; +import { SwapContextProvider } from "./context/Swap"; +import SwapCard from "./components/Swap"; +import { Provider } from "@project-serum/anchor"; +import { TokenListContainer } from "@solana/spl-token-registry"; +import { PublicKey } from "@solana/web3.js"; /** * A`Swap` component that can be embedded into applications. To use, @@ -166,30 +151,3 @@ export type SwapProps = { */ swapTokenContainerStyle?: any; }; - -export { - // Components. - Swap, - SwapCard, - SwapHeader, - SwapTokenForm, - ArrowButton, - SwapButton, - TokenDialog, - // Providers and context. - // Swap. - SwapContextProvider, - useSwapContext, - useSwapFair, - // TokenList. - TokenListContextProvider, - useTokenMap, - // Token. - TokenContextProvider, - useMint, - // Dex. - DexContextProvider, - useFairRoute, - useMarketName, - useBbo, -}; diff --git a/src/context/Dex.tsx b/src/context/Dex.tsx index 3f7508e2..90b64355 100644 --- a/src/context/Dex.tsx +++ b/src/context/Dex.tsx @@ -156,7 +156,7 @@ export function DexContextProvider(props: any) { }); }, [ swapClient.program.provider.connection, - swapClient.program.provider.wallet.publicKey, + swapClient.program.provider.wallet.publicKey?.toString(), swapClient.program.provider.opts, ]); return ( diff --git a/src/context/Swap.tsx b/src/context/Swap.tsx index ed0c011e..16f91e9b 100644 --- a/src/context/Swap.tsx +++ b/src/context/Swap.tsx @@ -20,7 +20,7 @@ import { SPL_REGISTRY_SOLLET_TAG, SPL_REGISTRY_WORM_TAG, } from "./TokenList"; -import { useOwnedTokenAccount } from "../context/Token"; +import { useMint, useOwnedTokenAccount } from "../context/Token"; const DEFAULT_SLIPPAGE_PERCENT = 0.5; @@ -184,6 +184,15 @@ export function useCanSwap(): boolean { const fromWallet = useOwnedTokenAccount(fromMint); const fair = useSwapFair(); const route = useRouteVerbose(fromMint, toMint); + + const fromTokenAccount = useOwnedTokenAccount(fromMint); + const fromMintAccount = useMint(fromMint); + const fromBalance = + fromTokenAccount && + fromMintAccount && + fromTokenAccount.account.amount.toNumber() / 10 ** fromMintAccount.decimals; + const hasFromBalance = (fromBalance || 0) >= fromAmount; + if (route === null) { return false; } @@ -202,6 +211,8 @@ export function useCanSwap(): boolean { // Trade amounts greater than zero. fromAmount > 0 && toAmount > 0 && + // From token account has enougth balance + hasFromBalance && // Trade route exists. route !== null && // Wormhole <-> native markets must have the wormhole token as the diff --git a/src/context/Token.tsx b/src/context/Token.tsx index e381dc66..06706475 100644 --- a/src/context/Token.tsx +++ b/src/context/Token.tsx @@ -58,7 +58,7 @@ export function TokenContextProvider(props: any) { setRefresh((r) => r + 1); } }); - }, [provider.wallet.publicKey, provider.connection]); + }, [provider.wallet.publicKey?.toString(), provider.connection]); return ( <_TokenContext.Provider @@ -143,7 +143,7 @@ export function useOwnedTokenAccount( provider.connection.removeAccountChangeListener(listener); } }; - }, [provider.connection, tokenAccount]); + }, [provider.connection, tokenAccount?.publicKey.toString()]); if (mint === undefined) { return undefined; @@ -176,7 +176,7 @@ export function useMint(mint?: PublicKey): MintInfo | undefined | null { const mintInfo = mintClient.getMintInfo(); _MINT_CACHE.set(mint.toString(), mintInfo); return mintInfo; - }, [provider.connection, mint]); + }, [provider.connection, mint?.toString()]); if (asyncMintInfo.result) { return asyncMintInfo.result; diff --git a/src/index.ts b/src/index.ts new file mode 100644 index 00000000..10f33dc9 --- /dev/null +++ b/src/index.ts @@ -0,0 +1,78 @@ +import { + SwapContextProvider, + useSwapContext, + useSwapFair, + useCanSwap, + useReferral, +} from "./context/Swap"; +import { + DexContextProvider, + useDexContext, + useOpenOrders, + useFairRoute, + useRouteVerbose, + useMarketName, + useMarket, + useBbo, + FEE_MULTIPLIER, +} from "./context/Dex"; +import { + TokenListContextProvider, + useSwappableTokens, + useTokenMap, +} from "./context/TokenList"; +import { + TokenContextProvider, + useOwnedTokenAccount, + useMint, +} from "./context/Token"; +import SwapCard, { + ArrowButton, + SwapButton, + SwapHeader, + SwapTokenForm, +} from "./components/Swap"; +import TokenDialog from "./components/TokenDialog"; +import Swap from "./Swap"; +import { SOL_MINT, WRAPPED_SOL_MINT } from "./utils/pubkeys"; + +export default Swap; + +export { + // Components. + Swap, + SwapCard, + SwapHeader, + SwapTokenForm, + ArrowButton, + SwapButton, + TokenDialog, + // Providers and context. + // Swap. + SwapContextProvider, + useSwapContext, + useSwapFair, + useCanSwap, + useReferral, + // TokenList. + TokenListContextProvider, + useTokenMap, + useSwappableTokens, + // Token. + TokenContextProvider, + useOwnedTokenAccount, + useMint, + // Dex. + DexContextProvider, + useDexContext, + useOpenOrders, + useFairRoute, + useRouteVerbose, + useMarketName, + useMarket, + useBbo, + FEE_MULTIPLIER, + // Utils + SOL_MINT, + WRAPPED_SOL_MINT, +};