From a149e544fe812b928b160f65ad1f27e7f5931bda Mon Sep 17 00:00:00 2001 From: borcherd Date: Mon, 10 Feb 2025 11:09:42 -0300 Subject: [PATCH] feat: cleanup & improvements --- .../src/components/common/Navbar/Navbar.tsx | 6 +- .../common/Portfolio/lending-portfolio.tsx | 58 ++--- .../global-actionbox-portal.tsx | 7 +- apps/marginfi-v2-ui/src/store/uiStore copy.ts | 214 ------------------ apps/marginfi-v2-ui/src/store/uiStore.ts | 15 +- .../components/action-box-v2/action-box.tsx | 3 - .../components/action-input/action-input.tsx | 6 +- .../actions/lend-box/lend-box.tsx | 3 +- .../src/components/wallet-v2/wallet.tsx | 3 +- 9 files changed, 37 insertions(+), 278 deletions(-) delete mode 100644 apps/marginfi-v2-ui/src/store/uiStore copy.ts diff --git a/apps/marginfi-v2-ui/src/components/common/Navbar/Navbar.tsx b/apps/marginfi-v2-ui/src/components/common/Navbar/Navbar.tsx index f9366e42f..0da1440e0 100644 --- a/apps/marginfi-v2-ui/src/components/common/Navbar/Navbar.tsx +++ b/apps/marginfi-v2-ui/src/components/common/Navbar/Navbar.tsx @@ -16,7 +16,6 @@ import { useConnection } from "~/hooks/use-connection"; import { Popover, PopoverContent, PopoverTrigger } from "~/components/ui/popover"; import { Button } from "~/components/ui/button"; import { IconMrgn } from "~/components/ui/icons"; -import { Input } from "~/components/ui/input"; // @todo implement second pretty navbar row export const Navbar: FC = () => { @@ -185,9 +184,8 @@ export const Navbar: FC = () => { }} className="hidden sm:flex py-2 px-4 border border-background-gray-hover flex-row items-center justify-between w-48 text-muted-foreground cursor-pointer " > -
Search pools...
- -
⌘ K
+ Search pools... + ⌘ K diff --git a/apps/marginfi-v2-ui/src/components/common/Portfolio/lending-portfolio.tsx b/apps/marginfi-v2-ui/src/components/common/Portfolio/lending-portfolio.tsx index 94e0d2555..0092f29d6 100644 --- a/apps/marginfi-v2-ui/src/components/common/Portfolio/lending-portfolio.tsx +++ b/apps/marginfi-v2-ui/src/components/common/Portfolio/lending-portfolio.tsx @@ -1,15 +1,13 @@ import React from "react"; import Link from "next/link"; -import { useRouter } from "next/router"; -import { VersionedTransaction } from "@solana/web3.js"; import { IconInfoCircle, IconX } from "@tabler/icons-react"; import { Id, toast } from "react-toastify"; import { numeralFormatter, SolanaTransaction } from "@mrgnlabs/mrgn-common"; import { usdFormatter, usdFormatterDyn } from "@mrgnlabs/mrgn-common"; import { ActionType, ActiveBankInfo } from "@mrgnlabs/marginfi-v2-ui-state"; -import { cn, LendingModes, usePrevious } from "@mrgnlabs/mrgn-utils"; +import { cn, usePrevious } from "@mrgnlabs/mrgn-utils"; import { useMrgnlendStore, useUiStore, useUserProfileStore } from "~/store"; @@ -17,6 +15,7 @@ import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from "~/comp import { WalletAuthAccounts, WalletButton } from "~/components/wallet-v2"; import { useWallet } from "~/components/wallet-v2/hooks/use-wallet.hook"; import { Loader } from "~/components/ui/loader"; + import { RewardsDialog } from "./components/rewards"; import { PortfolioAssetCard, PortfolioAssetCardSkeleton, PortfolioUserStats } from "./components"; @@ -34,7 +33,6 @@ const initialRewardsState: RewardsType = { }; export const LendingPortfolio = () => { - const router = useRouter(); const { connected } = useWallet(); const [walletConnectionDelay, setWalletConnectionDelay] = React.useState(false); const [ @@ -56,23 +54,15 @@ export const LendingPortfolio = () => { state.marginfiAccounts, state.fetchMrgnlendState, ]); - const [ - setLendingMode, - priorityFees, - broadcastType, - accountLabels, - fetchAccountLabels, - setGlobalActionBoxProps, - globalActionBoxProps, - ] = useUiStore((state) => [ - state.setLendingMode, - state.priorityFees, - state.broadcastType, - state.accountLabels, - state.fetchAccountLabels, - state.setGlobalActionBoxProps, - state.globalActionBoxProps, - ]); + const [priorityFees, broadcastType, accountLabels, setGlobalActionBoxProps, globalActionBoxProps] = useUiStore( + (state) => [ + state.priorityFees, + state.broadcastType, + state.accountLabels, + state.setGlobalActionBoxProps, + state.globalActionBoxProps, + ] + ); const [userPointsData] = useUserProfileStore((state) => [state.userPointsData]); // Rewards @@ -246,9 +236,9 @@ export const LendingPortfolio = () => { return ; } - // if (isLoading) { - // return ; - // } + if (isLoading) { + return ; + } if (isStoreInitialized && connected && !hasMultipleAccount) { if (!lendingBanks.length && !borrowingBanks.length) { @@ -409,13 +399,11 @@ export const LendingPortfolio = () => { ))} ) : ( -
+
No lending positions found. - {" "} + {" "} to lend assets.
) @@ -450,18 +438,16 @@ export const LendingPortfolio = () => { ))}
) : ( -
+
No borrow positions found.{" "} - {" "} + {" "} and open a new borrow.
) diff --git a/apps/marginfi-v2-ui/src/components/common/global-actionbox-portal/global-actionbox-portal.tsx b/apps/marginfi-v2-ui/src/components/common/global-actionbox-portal/global-actionbox-portal.tsx index 5825e2030..491a7a2c3 100644 --- a/apps/marginfi-v2-ui/src/components/common/global-actionbox-portal/global-actionbox-portal.tsx +++ b/apps/marginfi-v2-ui/src/components/common/global-actionbox-portal/global-actionbox-portal.tsx @@ -3,11 +3,9 @@ import React from "react"; import * as RadixPortal from "@radix-ui/react-portal"; import { ActionBox } from "@mrgnlabs/mrgn-ui"; -import { ActionType } from "@mrgnlabs/marginfi-v2-ui-state"; import { useWallet } from "~/components/wallet-v2/hooks/use-wallet.hook"; import { capture } from "@mrgnlabs/mrgn-utils"; import { useMrgnlendStore, useUiStore } from "~/store"; -import { Button } from "~/components/ui/button"; export const GlobalActionBoxPortal = () => { const { connected, walletContextState } = useWallet(); @@ -22,10 +20,7 @@ export const GlobalActionBoxPortal = () => { return ( -
+
; - displaySettings: boolean; - jupiterOptions: JupiterOptions; - - // Actions - setIsMenuDrawerOpen: (isOpen: boolean) => void; - setIsFetchingData: (isOpen: boolean) => void; - setIsFilteredUserPositions: (isFilteredUserPositions: boolean) => void; - setIsOraclesStale: (isOraclesStale: boolean) => void; - setLendingMode: (lendingMode: LendingModes) => void; - setPoolFilter: (poolType: PoolTypes) => void; - setSortOption: (sortOption: SortAssetOption) => void; - setAssetListSearch: (search: string) => void; - setTransactionSettings: (settings: TransactionSettings, connection: Connection) => void; - fetchPriorityFee: (connection: Connection, settings?: TransactionSettings) => void; - fetchAccountLabels: (accounts: MarginfiAccountWrapper[]) => Promise; - setDisplaySettings: (displaySettings: boolean) => void; - setJupiterOptions: (jupiterOptions: JupiterOptions) => void; -} - -interface NonPersistentUiState { - isActionBoxSearchOpen: boolean; - setIsActionBoxSearchOpen: (isOpen: boolean) => void; -} - -// Persistent State -const usePersistentUiStore = create()( - persist( - (set, get) => ({ - // State - isMenuDrawerOpen: false, - isFetchingData: false, - isFilteredUserPositions: false, - isOraclesStale: false, - lendingMode: LendingModes.LEND, - poolFilter: PoolTypes.ALL, - sortOption: SORT_OPTIONS_MAP[SortType.TVL_DESC], - assetListSearch: "", - priorityFees: {}, - accountLabels: {}, - ...DEFAULT_PRIORITY_SETTINGS, - displaySettings: false, - jupiterOptions: defaultJupiterOptions, - - // Actions - setIsMenuDrawerOpen: (isOpen: boolean) => set({ isMenuDrawerOpen: isOpen }), - setIsFetchingData: (isFetchingData: boolean) => set({ isFetchingData }), - setIsFilteredUserPositions: (isFilteredUserPositions: boolean) => - set({ isFilteredUserPositions: isFilteredUserPositions }), - setLendingMode: (lendingMode: LendingModes) => - set({ - lendingMode: lendingMode, - }), - setIsOraclesStale: (isOraclesStale: boolean) => set({ isOraclesStale: isOraclesStale }), - setPoolFilter: (poolType: PoolTypes) => set({ poolFilter: poolType }), - setSortOption: (sortOption: SortAssetOption) => set({ sortOption: sortOption }), - setAssetListSearch: (search: string) => set({ assetListSearch: search }), - setTransactionSettings: (settings: TransactionSettings, connection: Connection) => { - const { broadcastType, priorityType, maxCapType } = settings; - set({ broadcastType, priorityType, maxCapType }); - get().fetchPriorityFee(connection, settings); - }, - fetchPriorityFee: async (connection: Connection, settings?: TransactionSettings) => { - const { priorityType, broadcastType, maxCapType } = settings ?? get(); - - let manualMaxCap; - - if (maxCapType === "MANUAL") { - manualMaxCap = settings?.maxCap ?? get().priorityFees.maxCapUi; - } else { - manualMaxCap = 0; - } - - try { - const priorityFees = await fetchPriorityFee(broadcastType, priorityType, connection, maxCapType); - set({ - priorityFees: { - ...priorityFees, - maxCapUi: manualMaxCap, - }, - }); - } catch (error) { - console.error(error); - } - }, - fetchAccountLabels: async (accounts: MarginfiAccountWrapper[]) => { - const labels: Record = {}; - - const fetchLabel = async (account: MarginfiAccountWrapper) => { - try { - const response = await fetch(`/api/user/account-label?account=${account.address.toBase58()}`); - if (!response.ok) throw new Error(`Error fetching account label for ${account.address.toBase58()}`); - - const { data } = await response.json(); - return data.label || `Account`; - } catch (error) { - console.error(error); - return `Account`; - } - }; - - const accountLabelsWithAddresses = await Promise.all( - accounts.map(async (account) => { - const label = await fetchLabel(account); - return { address: account.address.toBase58(), label }; - }) - ); - - // Sort labels by order: first anything that is not starting with "Account", then "Account 1", "Account 2", ... - accountLabelsWithAddresses.sort((a, b) => { - const isAAccountLabel = /^Account (\d+)$/.test(a.label); - const isBAccountLabel = /^Account (\d+)$/.test(b.label); - - if (!isAAccountLabel && isBAccountLabel) return -1; - if (isAAccountLabel && !isBAccountLabel) return 1; - - if (isAAccountLabel && isBAccountLabel) { - const numA = parseInt(a.label.match(/^Account (\d+)$/)[1], 10); - const numB = parseInt(b.label.match(/^Account (\d+)$/)[1], 10); - return numA - numB; - } - - return a.label.localeCompare(b.label, undefined, { sensitivity: "base" }); - }); - - accountLabelsWithAddresses.forEach(({ address, label }) => { - labels[address] = label; - }); - - set({ accountLabels: labels }); - }, - setDisplaySettings: (displaySettings: boolean) => set({ displaySettings }), - setJupiterOptions: (jupiterOptions: JupiterOptions) => { - set({ jupiterOptions: { ...jupiterOptions, slippageBps: jupiterOptions.slippageBps * 100 } }); - }, - }), - { - name: "uiStore", - } - ) -); - -// Non-Persistent State -const useNonPersistentUiStore = create((set) => ({ - isActionBoxSearchOpen: false, - setIsActionBoxSearchOpen: (isOpen: boolean) => { - console.log("isOpen", isOpen); - set({ isActionBoxSearchOpen: isOpen }); - }, -})); - -// Create the store, merging both persistent and non-persistent state - -export { usePersistentUiStore, useNonPersistentUiStore, SORT_OPTIONS_MAP }; -export type { PersistentUiState, NonPersistentUiState }; diff --git a/apps/marginfi-v2-ui/src/store/uiStore.ts b/apps/marginfi-v2-ui/src/store/uiStore.ts index 7062151a5..8a30bb3ac 100644 --- a/apps/marginfi-v2-ui/src/store/uiStore.ts +++ b/apps/marginfi-v2-ui/src/store/uiStore.ts @@ -44,6 +44,11 @@ const SORT_OPTIONS_MAP: { [key in SortType]: SortAssetOption } = { }, }; +type GlobalActionBoxProps = { + isOpen: boolean; + actionType: ActionType; +}; + interface UiState { // State isMenuDrawerOpen: boolean; @@ -61,11 +66,7 @@ interface UiState { accountLabels: Record; displaySettings: boolean; jupiterOptions: JupiterOptions; - globalActionBoxProps: { - isOpen: boolean; - isTokenSelectorOpen: boolean; - actionType: ActionType; - }; + globalActionBoxProps: GlobalActionBoxProps; // Actions setIsMenuDrawerOpen: (isOpen: boolean) => void; @@ -81,7 +82,7 @@ interface UiState { fetchAccountLabels: (accounts: MarginfiAccountWrapper[]) => Promise; setDisplaySettings: (displaySettings: boolean) => void; setJupiterOptions: (jupiterOptions: JupiterOptions) => void; - setGlobalActionBoxProps: (props: { isOpen: boolean; isTokenSelectorOpen: boolean; actionType: ActionType }) => void; + setGlobalActionBoxProps: (props: GlobalActionBoxProps) => void; } function createUiStore() { @@ -99,7 +100,6 @@ function createUiStore() { if (state?.globalActionBoxProps) { state.globalActionBoxProps = { isOpen: false, - isTokenSelectorOpen: true, actionType: ActionType.Deposit, }; } // Rehydrating this to ensure the global action box doesnt open on render @@ -125,7 +125,6 @@ const stateCreator: StateCreator = (set, get) => ({ jupiterOptions: defaultJupiterOptions, globalActionBoxProps: { isOpen: false, - isTokenSelectorOpen: true, actionType: ActionType.Deposit, }, diff --git a/packages/mrgn-ui/src/components/action-box-v2/action-box.tsx b/packages/mrgn-ui/src/components/action-box-v2/action-box.tsx index 86dc02ef4..045f4218c 100644 --- a/packages/mrgn-ui/src/components/action-box-v2/action-box.tsx +++ b/packages/mrgn-ui/src/components/action-box-v2/action-box.tsx @@ -31,8 +31,6 @@ const ActionBox: ActionBoxComponent = (props) => { if (isDialogWrapperProps(props)) { const dialogProps = props.dialogProps; - console.log("dialogProps", dialogProps); - return ( <> { const contextProps = useActionBoxContext(); const [selectedAction, setSelectedAction] = React.useState(ActionType.Deposit); - const { lendProps, useProvider, ...actionBoxProps } = props; React.useEffect(() => { diff --git a/packages/mrgn-ui/src/components/action-box-v2/actions/lend-box/components/action-input/action-input.tsx b/packages/mrgn-ui/src/components/action-box-v2/actions/lend-box/components/action-input/action-input.tsx index 4ca6d29ef..843e4f7c5 100644 --- a/packages/mrgn-ui/src/components/action-box-v2/actions/lend-box/components/action-input/action-input.tsx +++ b/packages/mrgn-ui/src/components/action-box-v2/actions/lend-box/components/action-input/action-input.tsx @@ -24,7 +24,7 @@ type ActionInputProps = { showTokenSelectionGroups?: boolean; isMini?: boolean; - isTokenSelectorOpen?: boolean; + searchMode?: boolean; onCloseDialog?: () => void; setAmountRaw: (amount: string) => void; @@ -45,7 +45,7 @@ export const ActionInput = ({ amount, selectedBank, lendMode, - isTokenSelectorOpen, + searchMode, onCloseDialog, setAmountRaw, setSelectedBank, @@ -103,7 +103,7 @@ export const ActionInput = ({ nativeSolBalance={nativeSolBalance} lendMode={lendMode} connected={connected} - isInitialOpen={isTokenSelectorOpen} + isInitialOpen={searchMode} onCloseDialog={() => { selectedBank === null && onCloseDialog?.(); }} diff --git a/packages/mrgn-ui/src/components/action-box-v2/actions/lend-box/lend-box.tsx b/packages/mrgn-ui/src/components/action-box-v2/actions/lend-box/lend-box.tsx index 47f856288..fcd30a68b 100644 --- a/packages/mrgn-ui/src/components/action-box-v2/actions/lend-box/lend-box.tsx +++ b/packages/mrgn-ui/src/components/action-box-v2/actions/lend-box/lend-box.tsx @@ -69,7 +69,6 @@ export type LendBoxProps = { hidePoolStats?: HidePoolStats; stakeAccounts?: ValidatorStakeGroup[]; - isTokenSelectorOpen?: boolean; searchMode?: boolean; onCloseDialog?: () => void; setShouldBeHidden?: (hidden: boolean) => void; @@ -585,7 +584,7 @@ export const LendBox = ({ showTokenSelectionGroups={showTokenSelectionGroups} setAmountRaw={setAmountRaw} setSelectedBank={setSelectedBank} - isTokenSelectorOpen={searchMode} + searchMode={searchMode} onCloseDialog={() => { searchMode && onCloseDialog?.(); }} diff --git a/packages/mrgn-ui/src/components/wallet-v2/wallet.tsx b/packages/mrgn-ui/src/components/wallet-v2/wallet.tsx index 65a523c8d..c6d1bfa26 100644 --- a/packages/mrgn-ui/src/components/wallet-v2/wallet.tsx +++ b/packages/mrgn-ui/src/components/wallet-v2/wallet.tsx @@ -18,7 +18,6 @@ import { IconCreditCardPay, IconInfoCircleFilled, IconArrowDown, - IconSparkles, } from "@tabler/icons-react"; import { MarginfiAccountWrapper, MarginfiClient, ProcessTransactionsClientOpts } from "@mrgnlabs/marginfi-client-v2"; @@ -216,7 +215,7 @@ const Wallet = ({ {userDataFetched && wallet?.publicKey ? ( <> -
+
{shortenAddress(wallet?.publicKey)}
{accountLabels?.[selectedAccount?.address.toBase58() ?? "Account"]}