Skip to content

Commit

Permalink
Merge pull request #906 from mrgnlabs/feature/stake-box
Browse files Browse the repository at this point in the history
feat(mfi-v2-ui): improved stake page & stake box
  • Loading branch information
k0beLeenders authored Oct 21, 2024
2 parents 985032a + 53a486e commit e2ce633
Show file tree
Hide file tree
Showing 49 changed files with 2,155 additions and 193 deletions.
27 changes: 14 additions & 13 deletions apps/marginfi-v2-ui/src/components/common/ActionBox/ActionBox.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -552,19 +552,20 @@ export const ActionBox = ({
});
}

const txnSig = await executeLstAction({
actionMode,
marginfiClient: mfiClient,
amount,
connection,
wallet,
lstData,
bank: selectedBank,
nativeSolBalance,
selectedStakingAccount,
quoteResponseMeta: lstQuoteMeta as any, // TODO: fix type
priorityFee,
});
// const txnSig = await executeLstAction({
// actionMode,
// marginfiClient: mfiClient,
// amount,
// connection,
// wallet,
// lstData,
// bank: selectedBank,
// nativeSolBalance,
// selectedStakingAccount,
// quoteResponseMeta: lstQuoteMeta as any, // TODO: fix type
// priorityFee,
// }); // TODO: This was causing build errors but since this is deprecated code I've commented it out
let txnSig = "";

console.log("executer loop action");

Expand Down
81 changes: 41 additions & 40 deletions apps/marginfi-v2-ui/src/components/common/Mint/MintCardWrapper.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,14 @@ import { IconCheck, IconBell } from "@tabler/icons-react";

import { MintCardProps } from "~/utils";
import { useMrgnlendStore } from "~/store";
import { ActionBox } from "@mrgnlabs/mrgn-ui";
import { capture } from "@mrgnlabs/mrgn-utils";

import { Button } from "~/components/ui/button";
import { Card, CardContent, CardHeader, CardTitle } from "~/components/ui/card";
import { ActionBoxDialog } from "~/components/common/ActionBox";
import { LST_MINT } from "~/store/lstStore";
import { useWallet } from "~/components/wallet-v2/hooks/use-wallet.hook";

interface MintCardWrapperProps {
mintCard: MintCardProps;
Expand All @@ -19,16 +22,10 @@ interface MintCardWrapperProps {
export const MintCardWrapper: React.FC<MintCardWrapperProps> = ({ mintCard, ...props }) => {
const [extendedBankInfos] = useMrgnlendStore((state) => [state.extendedBankInfos]);

const [requestedAction, setRequestedAction] = React.useState<ActionType>(ActionType.MintLST);

const transformedActionGate = React.useMemo(() => getBlockedActions(), []);

const requestedBank = React.useMemo(
() =>
extendedBankInfos.find((bank) => bank?.info?.state?.mint.equals && bank?.info?.state?.mint.equals(LST_MINT)) ??
null,
[extendedBankInfos]
);
const { connected } = useWallet();

return (
<Card variant="default" className="relative">
<CardHeader className="pt-8">
Expand Down Expand Up @@ -71,33 +68,41 @@ export const MintCardWrapper: React.FC<MintCardWrapperProps> = ({ mintCard, ...p
)}

{mintCard.title === "LST" ? (
<ActionBoxDialog
requestedAction={requestedAction}
requestedBank={requestedAction === ActionType.UnstakeLST ? requestedBank : null}
>
<div className="flex items-center gap-2">
<Button
variant="secondary"
size="lg"
className="mt-4"
onClick={() => {
setRequestedAction(ActionType.MintLST);
}}
>
Stake {mintCard.title}
</Button>
<Button
variant="outline-dark"
size="lg"
className="mt-4 hover:text-primary"
onClick={() => {
setRequestedAction(ActionType.UnstakeLST);
}}
>
Unstake {mintCard.title}
</Button>
</div>
</ActionBoxDialog>
<div className="flex items-center gap-2">
<ActionBox.Stake
isDialog={true}
useProvider={true}
stakeProps={{
connected: connected,
requestedActionType: ActionType.MintLST,
}}
dialogProps={{
trigger: (
<Button variant="secondary" size="lg" className="mt-4">
Mint {mintCard.title}
</Button>
),
title: "Mint LST",
}}
/>
<ActionBox.Stake
isDialog={true}
useProvider={true}
stakeProps={{
connected: connected,
requestedActionType: ActionType.UnstakeLST,
requestedBank: extendedBankInfos.find((bank) => bank?.info?.state?.mint.equals(LST_MINT)),
}}
dialogProps={{
trigger: (
<Button variant="outline-dark" size="lg" className="mt-4 hover:text-primary">
Unstake {mintCard.title}
</Button>
),
title: "Unstake LST",
}}
/>
</div>
) : transformedActionGate?.find((value) => value === ActionType.MintYBX) ? (
<div className="flex items-center gap-2">
<Button
Expand All @@ -114,11 +119,7 @@ export const MintCardWrapper: React.FC<MintCardWrapperProps> = ({ mintCard, ...p
</Button>
</div>
) : (
<ActionBoxDialog
requestedAction={ActionType.MintYBX}
requestedBank={null}
//requestedToken={new PublicKey("2s37akK2eyBbp8DZgCm7RtsaEz8eJP3Nxd4urLHQv7yB")}
>
<ActionBoxDialog requestedAction={ActionType.MintYBX} requestedBank={null}>
<div className="flex items-center gap-2">
<Button variant="secondary" size="lg" className="mt-4">
Stake
Expand Down
205 changes: 81 additions & 124 deletions apps/marginfi-v2-ui/src/pages/stake.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,10 @@
import React from "react";

import { JupiterProvider } from "@jup-ag/react-hook";

import { groupedNumberFormatterDyn, clampedNumeralFormatter, usdFormatter } from "@mrgnlabs/mrgn-common";

import { useConnection } from "~/hooks/use-connection";
import { useWallet } from "~/components/wallet-v2/hooks/use-wallet.hook";
import { useLstStore, useMrgnlendStore, useUiStore } from "~/store";
import { useMrgnlendStore, useUiStore } from "~/store";
import { LST_MINT } from "~/store/lstStore";

import { ActionComplete } from "~/components/common/ActionComplete";
Expand All @@ -22,6 +20,7 @@ import {
} from "~/components/common/Mint";
import { IntegrationsData, MintCardProps, MintOverview, MintPageState, fetchMintOverview } from "~/utils";
import { PageHeading } from "~/components/common/PageHeading";
import { StakeBoxProvider } from "@mrgnlabs/mrgn-ui";

export default function MintPage() {
const { connection } = useConnection();
Expand All @@ -37,12 +36,6 @@ export default function MintPage() {

const [previousTxn] = useUiStore((state) => [state.previousTxn]);

const [fetchLstState, initialized, setIsRefreshingStore] = useLstStore((state) => [
state.fetchLstState,
state.initialized,
state.setIsRefreshingStore,
]);

const [extendedBankInfos] = useMrgnlendStore((state) => [state.extendedBankInfos]);

const lstBank = React.useMemo(
Expand All @@ -63,37 +56,6 @@ export default function MintPage() {
}
};

React.useEffect(() => {
const fetchData = () => {
setIsRefreshingStore(true);
fetchLstState({ connection, wallet }).catch(console.error);
};

if (debounceId.current) {
clearTimeout(debounceId.current);
}

debounceId.current = setTimeout(() => {
fetchData();

const id = setInterval(() => {
setIsRefreshingStore(true);
fetchLstState().catch(console.error);
}, 30_000);

return () => {
clearInterval(id);
clearTimeout(debounceId.current!);
};
}, 1000);

return () => {
if (debounceId.current) {
clearTimeout(debounceId.current);
}
};
}, [wallet]); // eslint-disable-line react-hooks/exhaustive-deps

const cards = React.useMemo(
() => [
{
Expand Down Expand Up @@ -146,90 +108,85 @@ export default function MintPage() {
}, []);

return (
<>
<JupiterProvider connection={connection} wrapUnwrapSOL={false} platformFeeAndAccounts={undefined}>
<div className="w-full max-w-8xl mx-auto px-4 md:px-8 space-y-20 pb-28">
{!initialized && <Loader label="Loading YBX / LST..." className="mt-8" />}
{initialized && (
<>
<div className="w-full max-w-4xl mx-auto px-4 md:px-0">
<PageHeading
heading={
<>
<span className="leading-normal">Inflation protected</span>
<div className="text-3xl leading-normal flex items-center gap-2 pb-2 justify-center">
<IconSol size={32} />
<p>SOL</p>
<p className="mx-2">and</p>
<IconUsd size={32} />
<p>USD</p>
</div>
</>
}
body={
<p>
The two most important assets on Solana are SOL and USD.
<br className="hidden lg:block" /> Capture inflation automatically with LST and YBX.
</p>
}
/>

<div className="grid grid-cols-1 sm:grid-cols-2 gap-8 md:gap-11 mt-8">
{cards.map((item, idx) => (
<MintCardWrapper mintCard={item} key={idx} />
))}
</div>
</div>

<div className="w-full py-4 px-4 md:px-10 xl:px-16 text-center">
<h2 className="text-3xl font-medium mb-3">Integrations</h2>
<p className="text-muted-foreground">
Ready to integrate YBX?{" "}
<button
className="border-b border-primary text-primary transition-colors hover:text-chartreuse hover:border-chartreuse"
onClick={() => setYbxPartnerDialogOpen(true)}
>
Become a launch partner.
</button>
<StakeBoxProvider>
<div className="w-full max-w-8xl mx-auto px-4 md:px-8 space-y-20 pb-28">
<>
<div className="w-full max-w-4xl mx-auto px-4 md:px-0">
<PageHeading
heading={
<>
<span className="leading-normal">Inflation protected</span>
<div className="text-3xl leading-normal flex items-center gap-2 pb-2 justify-center">
<IconSol size={32} />
<p>SOL</p>
<p className="mx-2">and</p>
<IconUsd size={32} />
<p>USD</p>
</div>
</>
}
body={
<p>
The two most important assets on Solana are SOL and USD.
<br className="hidden lg:block" /> Capture inflation automatically with LST and YBX.
</p>
<div className="flex items-center justify-center flex-wrap gap-8 mt-10 w-full">
{lstBank?.length > 0 ? (
<>
<BankIntegrationCard bank={lstBank[0]} isInLendingMode={true} />
</>
) : (
<IntegrationCardSkeleton />
)}
{integrations?.length > 0
? integrations.map((item, i) => <IntegrationCard integrationsData={item} key={i} />)
: [...new Array(5)].map((_, index) => <IntegrationCardSkeleton key={index} />)}
</div>
</div>
</>
)}
</div>
<YbxDialogNotifications
onClose={() => setYbxNotificationsDialogOpen(false)}
mintPageState={mintPageState}
onHandleChangeMintPage={(state) => setMintPageState(state)}
open={ybxNotificationsDialogOpen}
onOpenChange={(open) => {
setMintPageState(MintPageState.DEFAULT);
setYbxNotificationsDialogOpen(open);
}}
/>
<YbxDialogPartner
onClose={() => setYbxPartnerDialogOpen(false)}
mintPageState={mintPageState}
onHandleChangeMintPage={(state) => setMintPageState(state)}
open={ybxPartnerDialogOpen}
onOpenChange={(open) => {
setMintPageState(MintPageState.DEFAULT);
setYbxPartnerDialogOpen(open);
}}
/>
</JupiterProvider>
{initialized && previousTxn && <ActionComplete />}
</>
}
/>

<div className="grid grid-cols-1 sm:grid-cols-2 gap-8 md:gap-11 mt-8">
{cards.map((item, idx) => (
<MintCardWrapper mintCard={item} key={idx} />
))}
</div>
</div>

<div className="w-full py-4 px-4 md:px-10 xl:px-16 text-center">
<h2 className="text-3xl font-medium mb-3">Integrations</h2>
<p className="text-muted-foreground">
Ready to integrate YBX?{" "}
<button
className="border-b border-primary text-primary transition-colors hover:text-chartreuse hover:border-chartreuse"
onClick={() => setYbxPartnerDialogOpen(true)}
>
Become a launch partner.
</button>
</p>
<div className="flex items-center justify-center flex-wrap gap-8 mt-10 w-full">
{lstBank?.length > 0 ? (
<>
<BankIntegrationCard bank={lstBank[0]} isInLendingMode={true} />
</>
) : (
<IntegrationCardSkeleton />
)}
{integrations?.length > 0
? integrations.map((item, i) => <IntegrationCard integrationsData={item} key={i} />)
: [...new Array(5)].map((_, index) => <IntegrationCardSkeleton key={index} />)}
</div>
</div>
</>
</div>
<YbxDialogNotifications
onClose={() => setYbxNotificationsDialogOpen(false)}
mintPageState={mintPageState}
onHandleChangeMintPage={(state) => setMintPageState(state)}
open={ybxNotificationsDialogOpen}
onOpenChange={(open) => {
setMintPageState(MintPageState.DEFAULT);
setYbxNotificationsDialogOpen(open);
}}
/>
<YbxDialogPartner
onClose={() => setYbxPartnerDialogOpen(false)}
mintPageState={mintPageState}
onHandleChangeMintPage={(state) => setMintPageState(state)}
open={ybxPartnerDialogOpen}
onOpenChange={(open) => {
setMintPageState(MintPageState.DEFAULT);
setYbxPartnerDialogOpen(open);
}}
/>
{previousTxn && <ActionComplete />}
</StakeBoxProvider>
);
}
Loading

0 comments on commit e2ce633

Please sign in to comment.