diff --git a/apps/marginfi-v2-ui/package.json b/apps/marginfi-v2-ui/package.json index 20136124ee..9bdb731c75 100644 --- a/apps/marginfi-v2-ui/package.json +++ b/apps/marginfi-v2-ui/package.json @@ -14,6 +14,8 @@ "@coral-xyz/borsh": "^0.28.0", "@emotion/react": "^11.10.5", "@emotion/styled": "^11.10.5", + "@jup-ag/api": "^6.0.6", + "@jup-ag/react-hook": "^6.0.0-beta.2", "@mrgnlabs/lip-client": "*", "@mrgnlabs/marginfi-client-v2": "*", "@mrgnlabs/marginfi-v2-ui-state": "*", diff --git a/apps/marginfi-v2-ui/src/components/Staking/StakingCard/StakingCard.tsx b/apps/marginfi-v2-ui/src/components/Staking/StakingCard/StakingCard.tsx index c0a8432b28..19c9d36b64 100644 --- a/apps/marginfi-v2-ui/src/components/Staking/StakingCard/StakingCard.tsx +++ b/apps/marginfi-v2-ui/src/components/Staking/StakingCard/StakingCard.tsx @@ -1,4 +1,4 @@ -import { Dispatch, FC, SetStateAction, use, useCallback, useMemo, useState } from "react"; +import { Dispatch, FC, SetStateAction, use, useCallback, useEffect, useMemo, useState } from "react"; import { TextField, Typography } from "@mui/material"; import * as solanaStakePool from "@solana/spl-stake-pool"; import { WalletIcon } from "./WalletIcon"; @@ -12,6 +12,12 @@ import Image from "next/image"; import { NumberFormatValues, NumericFormat } from "react-number-format"; import { Connection, PublicKey, Transaction } from "@solana/web3.js"; import { useConnection } from "@solana/wallet-adapter-react"; +import { useJupiter } from "@jup-ag/react-hook"; +import { TokenListProvider, TokenInfo } from "@solana/spl-token-registry"; +import { useJupiterStore } from "~/store"; +import { QuoteResponse, createJupiterApiClient } from "@jup-ag/api"; + +import JSBI from "jsbi"; type SupportedToken = "SOL"; @@ -19,16 +25,41 @@ const TOKEN_URL_MAP: Record = { SOL: "info_icon.png", }; +const SUPPORTED_TOKENS = [ + "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v", + "J1toso1uCk3RLmjorhTtrVwY9HJ7X8V9yYac6Y7kGCPn", + // continue the list as you please +]; + export const StakingCard: FC = () => { const { connection } = useConnection(); const { connected, wallet } = useWalletContext(); const [lstData, userData] = useLstStore((state) => [state.lstData, state.userData]); + const jupiterQuoteApi = createJupiterApiClient(); + + // tokenMap are mints and icons & tokenAccountMap contains your token accounts mapped to their mint + const [tokenMap, tokenAccountMap] = useJupiterStore((state) => [state.tokenMap, state.tokenAccountMap]); + const [quoteMap, setQuoteMap] = useState>(new Map()); const [depositAmount, setDepositAmount] = useState(0); const [selectedToken, setSelectedToken] = useState("SOL"); const maxDeposit = useMemo(() => userData?.availableSolBalance ?? 0, [userData]); + const calculateRoutes = async () => { + // calculates the routes + if (depositAmount) { + for (let token of SUPPORTED_TOKENS) { + const result = await jupiterQuoteApi.quoteGet({ + inputMint: token, + outputMint: "So11111111111111111111111111111111111111112", + amount: depositAmount, + }); + setQuoteMap(quoteMap.set(token, result)); + } + } + }; + const onChange = useCallback( (event: NumberFormatValues) => setDepositAmount(event.floatValue ?? 0), [setDepositAmount] @@ -46,19 +77,19 @@ export const StakingCard: FC = () => { return ( <> -
+
Deposit {connected && ( -
-
+
+
- - {userData ? numeralFormatter(userData.availableSolBalance) : "-"} + + {userData ? `${numeralFormatter(userData.availableSolBalance)} SOL` : "-"} setDepositAmount(maxDeposit)} @@ -145,7 +176,6 @@ interface DropDownButtonProps { const DropDownButton: FC = ({ selectedToken, disabled }) => { const [isModalOpen, setIsModalOpen] = useState(false); - return ( <>
{ const { wallet } = useWalletContext(); const { connection } = useConnection(); - - const [ - fetchLstState, - setIsRefreshingStore, -] = useLstStore((state) => [ - state.fetchLstState, - state.setIsRefreshingStore, - state.userDataFetched, -]); + + const [fetchLstState, setIsRefreshingStore] = useLstStore((state) => [ + state.fetchLstState, + state.setIsRefreshingStore, + state.userDataFetched, + ]); + + const [fetchJupiterState] = useJupiterStore((state) => [state.fetchJupiterState]); + + useEffect(() => { + fetchJupiterState({ connection, wallet }).catch(console.error); + const id = setInterval(() => { + setIsRefreshingStore(true); + fetchJupiterState().catch(console.error); + }, 100_000); + return () => clearInterval(id); + }, [wallet]); + useEffect(() => { setIsRefreshingStore(true); fetchLstState({ connection, wallet }).catch(console.error); diff --git a/apps/marginfi-v2-ui/src/store/index.ts b/apps/marginfi-v2-ui/src/store/index.ts index 257b567cc1..812136f583 100644 --- a/apps/marginfi-v2-ui/src/store/index.ts +++ b/apps/marginfi-v2-ui/src/store/index.ts @@ -1,12 +1,15 @@ import { MrgnlendState, UserProfileState, + JupiterState, createPersistentMrgnlendStore, createUserProfileStore, + createJupiterStore, } from "@mrgnlabs/marginfi-v2-ui-state"; import { UseBoundStore, StoreApi } from "zustand"; const useMrgnlendStore: UseBoundStore> = createPersistentMrgnlendStore(); +const useJupiterStore: UseBoundStore> = createJupiterStore(); const useUserProfileStore: UseBoundStore> = createUserProfileStore(); -export { useMrgnlendStore, useUserProfileStore }; +export { useMrgnlendStore, useJupiterStore, useUserProfileStore }; diff --git a/yarn.lock b/yarn.lock index 446aa0e0dd..06e623e351 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3815,6 +3815,11 @@ resolved "https://registry.yarnpkg.com/@jup-ag/api/-/api-4.0.1-alpha.0.tgz#6c9fd02e607830206802b5e372fd0c2ec5a6a0c1" integrity sha512-H9hyf9K7sXMPd0++/hQ5Fs2eVgi2w9wtJP0YmGFLJMjF8zHYDYqQ0ZCdgmLLSp/vrEjmOHbbiLJT2psuV5W+bw== +"@jup-ag/api@^6.0.6", "@jup-ag/api@~6.0.6": + version "6.0.6" + resolved "https://registry.yarnpkg.com/@jup-ag/api/-/api-6.0.6.tgz#f0f838aaf8ca5964d7cb9ff24535599bf4d03813" + integrity sha512-wGp3FjT+WNdd5TzsWaKr2a2rQ2FgIyaV6sq8L76R8KVYxH7TfCY/BZwhcij6YhxHGjxrF8j7qI6ZPpmUTICpnA== + "@jup-ag/common@4.0.0-beta.21": version "4.0.0-beta.21" resolved "https://registry.yarnpkg.com/@jup-ag/common/-/common-4.0.0-beta.21.tgz#416b3fc75a3e0a3055dfb5fc404cb71edcd6a60b" @@ -3830,7 +3835,7 @@ bs58 "^4.0.1" jsbi "4.3.0" -"@jup-ag/common@^6.0.0-beta.2": +"@jup-ag/common@6.0.0-beta.2", "@jup-ag/common@^6.0.0-beta.2": version "6.0.0-beta.2" resolved "https://registry.yarnpkg.com/@jup-ag/common/-/common-6.0.0-beta.2.tgz#64cce00a04299b8047c1fa5e0c821b0328cef591" integrity sha512-KHXKs+6aE+Y4rtzisIeZcC2j4iRVJeS0mX8H3wIBQ2D/FQtVrZp1mI6A/kA3ifPad1jmjWTLPLTwLAcf1Y/Fjw== @@ -4066,6 +4071,17 @@ "@solana/spl-token" "0.1.8" cross-fetch "3.1.5" +"@jup-ag/react-hook@^6.0.0-beta.2": + version "6.0.0-beta.2" + resolved "https://registry.yarnpkg.com/@jup-ag/react-hook/-/react-hook-6.0.0-beta.2.tgz#1effec260c488d862474a1b33c7324f4ca5ee2c4" + integrity sha512-vWvjn/uy54ri2bJ/086NlRM7hkL92ZU5iFiLlL5V1v21ZdmKwof6J30hShf/l3fTbv8IjUWIsLpU3EUVyuO26w== + dependencies: + "@jup-ag/api" "~6.0.6" + "@jup-ag/common" "6.0.0-beta.2" + "@mercurial-finance/optimist" "0.3.0" + "@solana/spl-token" "0.1.8" + superstruct "~1.0.3" + "@jup-ag/whirlpools-sdk@0.7.2": version "0.7.2" resolved "https://registry.yarnpkg.com/@jup-ag/whirlpools-sdk/-/whirlpools-sdk-0.7.2.tgz#c4cc2fa601686e5cb5f1020b8c50acf38c9fb529" @@ -20746,7 +20762,7 @@ superstruct@^0.15.4: resolved "https://registry.yarnpkg.com/superstruct/-/superstruct-0.15.5.tgz#0f0a8d3ce31313f0d84c6096cd4fa1bfdedc9dab" integrity sha512-4AOeU+P5UuE/4nOUkmcQdW5y7i9ndt1cQd/3iUe+LTz3RxESf/W/5lg4B74HbDMMv8PHnPnGCQFH45kBcrQYoQ== -superstruct@^1.0.3: +superstruct@^1.0.3, superstruct@~1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/superstruct/-/superstruct-1.0.3.tgz#de626a5b49c6641ff4d37da3c7598e7a87697046" integrity sha512-8iTn3oSS8nRGn+C2pgXSKPI3jmpm6FExNazNpjvqS6ZUJQCej3PUXEKM8NjHBOs54ExM+LPW/FBRhymrdcCiSg==