diff --git a/package.json b/package.json index d3d10b4..02d0e39 100644 --- a/package.json +++ b/package.json @@ -8,7 +8,7 @@ "dependencies": { "@fontsource/roboto": "^4.3.0", "@project-serum/serum": "^0.13.34", - "@project-serum/swap": "^0.1.0-alpha.15", + "@project-serum/swap": "^0.1.0-alpha.20", "@solana/spl-token": "^0.1.4" }, "peerDependencies": { @@ -41,7 +41,7 @@ "@project-serum/anchor": "^0.7.0", "@project-serum/serum": "^0.13.34", "@project-serum/sol-wallet-adapter": "^0.2.0", - "@project-serum/swap": "^0.1.0-alpha.15", + "@project-serum/swap": "^0.1.0-alpha.20", "@solana/spl-token": "^0.1.4", "@solana/spl-token-registry": "^0.2.86", "@solana/web3.js": "^1.10.1", diff --git a/src/components/OpenOrdersDialog.tsx b/src/components/OpenOrdersDialog.tsx index 6518e20..54167ea 100644 --- a/src/components/OpenOrdersDialog.tsx +++ b/src/components/OpenOrdersDialog.tsx @@ -25,6 +25,7 @@ import { Close } from "@material-ui/icons"; import { useMarket, useOpenOrders, useDexContext } from "../context/Dex"; import { useTokenMap } from "../context/TokenList"; import { useMint, useOwnedTokenAccount } from "../context/Token"; +import { DEX_PID } from "../utils/pubkeys"; const useStyles = makeStyles((theme) => ({ table: {}, @@ -170,9 +171,15 @@ function OpenOrdersRow({ }; const closeOpenOrders = async () => { - // TODO. - // - // Blocked by https://github.com/project-serum/serum-dex/pull/112. + await swapClient.program.rpc.closeAccount({ + accounts: { + openOrders: ooAccount.address, + authority: swapClient.program.provider.wallet.publicKey, + destination: swapClient.program.provider.wallet.publicKey, + market: marketClient!.address, + dexProgram: DEX_PID, + }, + }); }; return ( diff --git a/src/components/Swap.tsx b/src/components/Swap.tsx index d0f710d..21ce349 100644 --- a/src/components/Swap.tsx +++ b/src/components/Swap.tsx @@ -303,8 +303,14 @@ function TokenName({ mint, style }: { mint: PublicKey; style: any }) { function SwapButton() { const styles = useStyles(); - const { fromMint, toMint, fromAmount, slippage, isClosingNewAccounts } = - useSwapContext(); + const { + fromMint, + toMint, + fromAmount, + slippage, + isClosingNewAccounts, + isStrict, + } = useSwapContext(); const { swapClient } = useDexContext(); const fromMintInfo = useMint(fromMint); const toMintInfo = useMint(toMint); @@ -321,6 +327,7 @@ function SwapButton() { const fair = useSwapFair(); const fromWallet = useOwnedTokenAccount(fromMint); const toWallet = useOwnedTokenAccount(toMint); + const quoteMint = useMint(fromMarket && fromMarket.quoteMintAddress); // Click handler. const sendSwapTransaction = async () => { @@ -330,15 +337,19 @@ function SwapButton() { if (!fair) { throw new Error("Invalid fair"); } - const amount = new BN(fromAmount).mul( - new BN(10).pow(new BN(fromMintInfo.decimals)) - ); + if (!quoteMint) { + throw new Error("Quote mint not found"); + } + const amount = new BN(fromAmount * 10 ** fromMintInfo.decimals); const minExchangeRate = { - rate: new BN(10 ** toMintInfo.decimals * (1 - BASE_TAKER_FEE_BPS)) - .divn(fair) + rate: new BN( + (10 ** toMintInfo.decimals * (1 - BASE_TAKER_FEE_BPS)) / fair + ) .muln(100 - slippage) .divn(100), - decimals: fromMintInfo.decimals, + fromDecimals: fromMintInfo.decimals, + quoteDecimals: quoteMint.decimals, + strict: isStrict, }; const fromOpenOrders = fromMarket ? openOrders.get(fromMarket?.address.toString()) diff --git a/src/context/Swap.tsx b/src/context/Swap.tsx index dc429a7..c78e4bd 100644 --- a/src/context/Swap.tsx +++ b/src/context/Swap.tsx @@ -56,6 +56,15 @@ export type SwapContext = { // True if all newly created market accounts should be closed in the // same user flow (ideally in the same transaction). isClosingNewAccounts: boolean; + + // True if the swap exchange rate should be a function of nothing but the + // from and to tokens, ignoring any quote tokens that may have been + // accumulated by performing the swap. + // + // Always false (for now). + isStrict: boolean; + setIsStrict: (isStrict: boolean) => void; + setIsClosingNewAccounts: (b: boolean) => void; }; const _SwapContext = React.createContext(null); @@ -66,6 +75,7 @@ export function SwapContextProvider(props: any) { const [fromAmount, _setFromAmount] = useState(props.fromAmount ?? 0); const [toAmount, _setToAmount] = useState(props.toAmount ?? 0); const [isClosingNewAccounts, setIsClosingNewAccounts] = useState(false); + const [isStrict, setIsStrict] = useState(false); const [slippage, setSlippage] = useState(DEFAULT_SLIPPAGE_PERCENT); const [fairOverride, setFairOverride] = useState(null); const fair = _useSwapFair(fromMint, toMint, fairOverride); @@ -117,6 +127,8 @@ export function SwapContextProvider(props: any) { fairOverride, setFairOverride, isClosingNewAccounts, + isStrict, + setIsStrict, setIsClosingNewAccounts, referral, }} diff --git a/yarn.lock b/yarn.lock index 9685b21..32aa16a 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1654,10 +1654,10 @@ bs58 "^4.0.1" eventemitter3 "^4.0.4" -"@project-serum/swap@^0.1.0-alpha.15": - version "0.1.0-alpha.15" - resolved "https://registry.yarnpkg.com/@project-serum/swap/-/swap-0.1.0-alpha.15.tgz#3650294c579e99c60dd502ce6bdea5ac55a90f3d" - integrity sha512-/388h8vXzhZ5koeXjeXIJk8gErbGdDqVzhH/W09XLKl7p//eiJ7DWdFUKVPZxUaHe8XhYrWoRzbWdBOvUXmdYA== +"@project-serum/swap@^0.1.0-alpha.20": + version "0.1.0-alpha.20" + resolved "https://registry.yarnpkg.com/@project-serum/swap/-/swap-0.1.0-alpha.20.tgz#0d5a57d2d6e507b3375cfb8965bb85fc7bdda9cf" + integrity sha512-Q2schT1I/gSj3k9crlefxv9qdeWSPYPtF39Ga518cKlakdXt8FZgfmAgJs7YN389GkOo5FcNBSVvVO47H4mBAg== dependencies: "@project-serum/serum" "^0.13.34" "@solana/spl-token" "^0.1.3"