Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Man0s/stake #232

Merged
merged 33 commits into from
Sep 21, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
33 commits
Select commit Hold shift + click to select a range
48a991c
fix(mfi-v2-ui): added lst page design
k0beLeenders Sep 11, 2023
d1dd529
feat(mfi-v2-ui): LST staking mobile design
k0beLeenders Sep 12, 2023
a94c287
fix(mfi-v2-ui): updated navbar
k0beLeenders Sep 12, 2023
2bd924a
feat(mfi-v2-ui): functional LST staking
losman0s Sep 12, 2023
d1f8ca0
checkpoint
losman0s Sep 13, 2023
a016edf
checkpoint
losman0s Sep 13, 2023
fb2dcf6
checkpoint
losman0s Sep 13, 2023
f2065cc
checkpoint
losman0s Sep 13, 2023
793b65b
checkpoint
losman0s Sep 13, 2023
c87575e
checkpoint
losman0s Sep 15, 2023
f8e492d
checkpoint
losman0s Sep 15, 2023
e4d4d42
tune header
losman0s Sep 15, 2023
046984c
fix header
losman0s Sep 15, 2023
9efc305
feat(mfi-v2-ui): added slippage modal & icon
k0beLeenders Sep 15, 2023
aaf96b2
fix LST out decimals
losman0s Sep 15, 2023
7ef7960
fix type
losman0s Sep 15, 2023
f64fd7e
fix slippage unit
losman0s Sep 15, 2023
3c4a947
sort tokens by holdings
losman0s Sep 16, 2023
a7231f6
typo
losman0s Sep 16, 2023
e379bd6
checkpoint
losman0s Sep 16, 2023
2d84f59
percent fix
losman0s Sep 16, 2023
cb10de5
styling
losman0s Sep 17, 2023
26a090e
fix over-zealous stake pool lib check
losman0s Sep 17, 2023
fff8d07
remove useless function
losman0s Sep 17, 2023
0573015
price movement checks
losman0s Sep 17, 2023
f4b1b8f
checkpoint
losman0s Sep 17, 2023
3457f72
use stake pool proxy
losman0s Sep 18, 2023
20b857d
prevent excess stake amount
losman0s Sep 19, 2023
843e15d
fix(mfi-v2-ui): 2-step signature for LST minting
losman0s Sep 19, 2023
c6dff2b
feat(mfi-v2-ui): clearer 2-step status
losman0s Sep 20, 2023
06a1127
feat(mfi-v2-ui): spinner when refreshing quotes
losman0s Sep 20, 2023
33dc991
feat(mfi-v2-ui): feature gates
losman0s Sep 21, 2023
41ead1b
fix(mfi-v2-ui): fix withdraw emissions
losman0s Sep 21, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions apps/marginfi-v2-ui/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -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": "*",
Expand All @@ -23,6 +25,8 @@
"@next/bundle-analyzer": "^13.4.19",
"@next/font": "13.1.1",
"@socialgouv/matomo-next": "^1.4.0",
"@solana/spl-stake-pool": "^0.6.5",
"@solana/spl-token-registry": "^0.2.4574",
"@solana/wallet-adapter-base": "^0.9.20",
"@solana/wallet-adapter-react": "^0.15.28",
"@solana/wallet-adapter-react-ui": "^0.9.27",
Expand All @@ -34,6 +38,7 @@
"bs58": "^5.0.0",
"firebase": "^9.22.1",
"firebase-admin": "^11.9.0",
"jsbi": "^4.3.0",
"next": "13.4.19",
"react": "18.2.0",
"react-dom": "18.2.0",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ import { useWalletContext } from "~/components/useWalletContext";

const CLOSE_BALANCE_TOAST_ID = "close-balance";
const BORROW_OR_LEND_TOAST_ID = "borrow-or-lend";
const EMISSION_MINT_INFO_MAP = new Map<string, { tokenSymbol: string; tokenLogoUri: string }>([
export const EMISSION_MINT_INFO_MAP = new Map<string, { tokenSymbol: string; tokenLogoUri: string }>([
[
"UXD",
{
Expand Down
18 changes: 9 additions & 9 deletions apps/marginfi-v2-ui/src/components/CampaignWizard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ const CampaignWizardInputBox: FC<CampaignWizardInputBox> = ({
);
};

interface CampaignWizardProps { }
interface CampaignWizardProps {}

const CampaignWizard: FC<CampaignWizardProps> = () => {
const [guaranteedApy, setGuaranteedApy] = useState(0);
Expand Down Expand Up @@ -271,7 +271,7 @@ const CampaignWizard: FC<CampaignWizardProps> = () => {
<CampaignWizardInputBox
value={guaranteedApy * 100}
setValue={(value) => setGuaranteedApy(value / 100)}
loadingSafetyCheck={() => { }}
loadingSafetyCheck={() => {}}
maxDecimals={2}
disabled={!walletContext.connected}
/>
Expand All @@ -282,7 +282,7 @@ const CampaignWizard: FC<CampaignWizardProps> = () => {
<CampaignWizardInputBox
value={lockupPeriodInDays}
setValue={setLockupPeriodInDays}
loadingSafetyCheck={() => { }}
loadingSafetyCheck={() => {}}
maxDecimals={4}
disabled={!walletContext.connected}
/>
Expand All @@ -293,7 +293,7 @@ const CampaignWizard: FC<CampaignWizardProps> = () => {
<CampaignWizardInputBox
value={depositCapacity}
setValue={setDepositCapacity}
loadingSafetyCheck={() => { }}
loadingSafetyCheck={() => {}}
maxDecimals={3}
disabled={!walletContext.connected}
/>
Expand Down Expand Up @@ -343,12 +343,12 @@ const CampaignWizard: FC<CampaignWizardProps> = () => {
>
{campaignBank
? percentFormatterDyn.format(
computeGuaranteedApy(
contractInputs.lockupPeriod.toNumber(),
contractInputs.maxDeposits.toNumber(),
contractInputs.maxRewards.toNumber()
computeGuaranteedApy(
contractInputs.lockupPeriod.toNumber(),
contractInputs.maxDeposits.toNumber(),
contractInputs.maxRewards.toNumber()
)
)
)
: 0}
</span>
</div>
Expand Down
3 changes: 1 addition & 2 deletions apps/marginfi-v2-ui/src/components/Earn/index.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import React, { FC, MouseEventHandler, ReactNode, useCallback, useEffect, useMemo, useState } from "react";
import { useConnection, useWallet } from "@solana/wallet-adapter-react";
import { useConnection } from "@solana/wallet-adapter-react";
import { PageHeader } from "~/components/PageHeader";
import { useLipClient } from "~/context";
import Button from "@mui/material/Button";
Expand Down Expand Up @@ -210,7 +210,6 @@ const Earn = () => {

return (
<>
<PageHeader />
<div className="h-full flex flex-col justify-start items-center content-start py-[48px] w-4/5 max-w-7xl gap-4">
<div className="w-[360px] flex flex-col items-center gap-6">
<div className="w-[300px] h-[100px] flex flex-col gap-5 justify-center">
Expand Down
20 changes: 16 additions & 4 deletions apps/marginfi-v2-ui/src/components/Footer/Footer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -64,13 +64,19 @@ const HotkeysInfo: FC = () => {
};

const LendZoomControl: FC = () => {
const [lendZoomLevel, setLendZoomLevel] = useUserProfileStore((state) => [state.lendZoomLevel, state.setLendZoomLevel]);
const [lendZoomLevel, setLendZoomLevel] = useUserProfileStore((state) => [
state.lendZoomLevel,
state.setLendZoomLevel,
]);

return (
<div className="flex gap-4 items-center justify-center border-r border-[#4E5257] pr-4">
<div className="flex items-center h-full">
<SvgIcon onClick={() => setLendZoomLevel(1)} viewBox="0 0 17 17">
<svg fill="#868E95" className={`cursor-pointer ${lendZoomLevel === 1 && "fill-[#DCE85D]"} hover:fill-[#DCE85D] text-lg`}>
<svg
fill="#868E95"
className={`cursor-pointer ${lendZoomLevel === 1 && "fill-[#DCE85D]"} hover:fill-[#DCE85D] text-lg`}
>
<path
strokeWidth={1.5}
d="M1 1h3v3h-3v-3zM5 4h3v-3h-3v3zM9 4h3v-3h-3v3zM13 1v3h3v-3h-3zM1 8h3v-3h-3v3zM5 8h3v-3h-3v3zM9 8h3v-3h-3v3zM13 8h3v-3h-3v3zM1 12h3v-3h-3v3zM5 12h3v-3h-3v3zM9 12h3v-3h-3v3zM13 12h3v-3h-3v3zM1 16h3v-3h-3v3zM5 16h3v-3h-3v3zM9 16h3v-3h-3v3zM13 16h3v-3h-3v3z"
Expand All @@ -80,7 +86,10 @@ const LendZoomControl: FC = () => {
</div>
<div className="flex items-center h-full">
<SvgIcon onClick={() => setLendZoomLevel(2)} viewBox="0 0 16 16">
<svg fill="#868E95" className={`cursor-pointer ${lendZoomLevel === 2 && "fill-[#DCE85D]"} hover:fill-[#DCE85D] text-lg`}>
<svg
fill="#868E95"
className={`cursor-pointer ${lendZoomLevel === 2 && "fill-[#DCE85D]"} hover:fill-[#DCE85D] text-lg`}
>
<path
strokeWidth={1.5}
d="M1 2a1 1 0 0 1 1-1h2a1 1 0 0 1 1 1v2a1 1 0 0 1-1 1H2a1 1 0 0 1-1-1V2zm5 0a1 1 0 0 1 1-1h2a1 1 0 0 1 1 1v2a1 1 0 0 1-1 1H7a1 1 0 0 1-1-1V2zm5 0a1 1 0 0 1 1-1h2a1 1 0 0 1 1 1v2a1 1 0 0 1-1 1h-2a1 1 0 0 1-1-1V2zM1 7a1 1 0 0 1 1-1h2a1 1 0 0 1 1 1v2a1 1 0 0 1-1 1H2a1 1 0 0 1-1-1V7zm5 0a1 1 0 0 1 1-1h2a1 1 0 0 1 1 1v2a1 1 0 0 1-1 1H7a1 1 0 0 1-1-1V7zm5 0a1 1 0 0 1 1-1h2a1 1 0 0 1 1 1v2a1 1 0 0 1-1 1h-2a1 1 0 0 1-1-1V7zM1 12a1 1 0 0 1 1-1h2a1 1 0 0 1 1 1v2a1 1 0 0 1-1 1H2a1 1 0 0 1-1-1v-2zm5 0a1 1 0 0 1 1-1h2a1 1 0 0 1 1 1v2a1 1 0 0 1-1 1H7a1 1 0 0 1-1-1v-2zm5 0a1 1 0 0 1 1-1h2a1 1 0 0 1 1 1v2a1 1 0 0 1-1 1h-2a1 1 0 0 1-1-1v-2z"
Expand All @@ -90,7 +99,10 @@ const LendZoomControl: FC = () => {
</div>
<div className="flex items-center h-full">
<SvgIcon onClick={() => setLendZoomLevel(3)} viewBox="0 0 16 16">
<svg fill="#868E95" className={`cursor-pointer ${lendZoomLevel === 3 && "fill-[#DCE85D]"} hover:fill-[#DCE85D] text-lg`}>
<svg
fill="#868E95"
className={`cursor-pointer ${lendZoomLevel === 3 && "fill-[#DCE85D]"} hover:fill-[#DCE85D] text-lg`}
>
<path
strokeWidth={1.5}
d="M1 2.5A1.5 1.5 0 0 1 2.5 1h3A1.5 1.5 0 0 1 7 2.5v3A1.5 1.5 0 0 1 5.5 7h-3A1.5 1.5 0 0 1 1 5.5v-3zm8 0A1.5 1.5 0 0 1 10.5 1h3A1.5 1.5 0 0 1 15 2.5v3A1.5 1.5 0 0 1 13.5 7h-3A1.5 1.5 0 0 1 9 5.5v-3zm-8 8A1.5 1.5 0 0 1 2.5 9h3A1.5 1.5 0 0 1 7 10.5v3A1.5 1.5 0 0 1 5.5 15h-3A1.5 1.5 0 0 1 1 13.5v-3zm8 0A1.5 1.5 0 0 1 10.5 9h3a1.5 1.5 0 0 1 1.5 1.5v3a1.5 1.5 0 0 1-1.5 1.5h-3A1.5 1.5 0 0 1 9 13.5v-3z"
Expand Down
4 changes: 1 addition & 3 deletions apps/marginfi-v2-ui/src/components/Navbar/AirdropZone.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -60,9 +60,7 @@ const AirdropZone: FC = () => {

return (
<div>
<span onClick={open}>
Airdrop
</span>
<span onClick={open}>Airdrop</span>
<Modal open={isOpen} onClose={close} aria-labelledby="title" aria-describedby="description">
<div id={styles["container"]}>
<div id={styles["overlay"]}>
Expand Down
87 changes: 70 additions & 17 deletions apps/marginfi-v2-ui/src/components/Navbar/Navbar.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { FC, useEffect, useState } from "react";
import { FC, useEffect, useMemo, useState } from "react";
import Link from "next/link";
import Image from "next/image";
import AirdropZone from "./AirdropZone";
Expand All @@ -11,14 +11,20 @@ import { useRouter } from "next/router";
import { HotkeysEvent } from "react-hotkeys-hook/dist/types";
import { Badge } from "@mui/material";
import { useFirebaseAccount } from "../useFirebaseAccount";
import { groupedNumberFormatterDyn, numeralFormatter } from "@mrgnlabs/mrgn-common";
import { groupedNumberFormatterDyn, processTransaction } from "@mrgnlabs/mrgn-common";
import { useWalletContext } from "../useWalletContext";
import { Features, isActive } from "~/utils/featureGates";
import { EMISSION_MINT_INFO_MAP } from "../AssetsList/AssetRow/AssetRow";
import { PublicKey, Transaction } from "@solana/web3.js";
import { useConnection } from "@solana/wallet-adapter-react";
import { toast } from "react-toastify";

// @todo implement second pretty navbar row
const Navbar: FC = () => {
useFirebaseAccount();

const { connected, walletAddress } = useWalletContext();
const { connection } = useConnection();
const { connected, walletAddress, wallet } = useWalletContext();
const router = useRouter();
const [accountSummary, selectedAccount, extendedBankInfos] = useMrgnlendStore((state) => [
state.accountSummary,
Expand All @@ -36,6 +42,16 @@ const Navbar: FC = () => {
const [isHotkeyMode, setIsHotkeyMode] = useState(false);
const [currentRoute, setCurrentRoute] = useState(router.pathname);

const bankAddressesWithEmissions: PublicKey[] = useMemo(() => {
if (!selectedAccount) return [];
return [...EMISSION_MINT_INFO_MAP.keys()]
.map((bankMintSymbol) => {
const uxdBankInfo = extendedBankInfos?.find((b) => b.isActive && b.meta.tokenSymbol === bankMintSymbol);
return uxdBankInfo?.address;
})
.filter((address) => address !== undefined) as PublicKey[];
}, [selectedAccount, extendedBankInfos]);

useEffect(() => {
if (!walletAddress) return;
fetchPoints(walletAddress.toBase58()).catch(console.error);
Expand Down Expand Up @@ -143,6 +159,30 @@ const Navbar: FC = () => {
</Link>
</Badge>

{isActive(Features.STAKE) && (
<Badge
anchorOrigin={{
vertical: "bottom",
horizontal: "right",
}}
sx={{
"& .MuiBadge-badge": {
backgroundColor: "rgb(220, 232, 93)",
color: "#1C2125",
},
}}
badgeContent={"e"}
invisible={!showBadges}
>
<Link
href={"/stake"}
className={router.pathname === "/stake" ? "hover-underline-static" : "hover-underline-animation"}
>
stake
</Link>
</Badge>
)}

<Badge
anchorOrigin={{
vertical: "bottom",
Expand All @@ -159,7 +199,9 @@ const Navbar: FC = () => {
>
<Link
href={"/swap"}
className={`${router.pathname === "/swap" ? "hover-underline-static" : "hover-underline-animation"}`}
className={`${
router.pathname === "/swap" ? "hover-underline-static" : "hover-underline-animation"
} hidden md:block`}
>
swap
</Link>
Expand All @@ -180,7 +222,9 @@ const Navbar: FC = () => {
>
<Link
href={"/bridge"}
className={`${router.pathname === "/bridge" ? "hover-underline-static" : "hover-underline-animation"}`}
className={`${
router.pathname === "/bridge" ? "hover-underline-static" : "hover-underline-animation"
} hidden md:block`}
>
bridge
</Link>
Expand Down Expand Up @@ -234,22 +278,31 @@ const Navbar: FC = () => {
</div>
<div className="h-full w-1/2 flex justify-end items-center z-10 gap-4 lg:gap-8 text-[#868E95]">
<div
className="whitespace-nowrap cursor-pointer hidden md:block"
onClick={() => {
if (selectedAccount && extendedBankInfos?.find((b) => b.meta.tokenSymbol === "UXD")?.info.rawBank) {
selectedAccount!.withdrawEmissions(
extendedBankInfos.find((b) => b.meta.tokenSymbol === "UXD")!.address
);
}

if (selectedAccount && extendedBankInfos?.find((b) => b.meta.tokenSymbol === "bSOL")?.info.rawBank) {
selectedAccount!.withdrawEmissions(
extendedBankInfos.find((b) => b.meta.tokenSymbol === "bSOL")!.address
);
className={`whitespace-nowrap hidden md:inline-flex ${
bankAddressesWithEmissions.length > 0 ? "cursor-pointer hover:text-[#AAA]" : "cursor-not-allowed"
}`}
onClick={async () => {
if (!wallet || !selectedAccount || bankAddressesWithEmissions.length === 0) return;
const tx = new Transaction();
const ixs = [];
const signers = [];
for (const bankAddress of bankAddressesWithEmissions) {
const ix = await selectedAccount.makeWithdrawEmissionsIx(bankAddress);
ixs.push(...ix.instructions);
signers.push(ix.keys);
}
tx.add(...ixs);
await processTransaction(connection, wallet, tx);
toast.success("Withdrawal successful");
}}
>
withdraw all rewards
{bankAddressesWithEmissions.length > 0 && (
<span className="relative flex h-1 w-1">
<span className="animate-ping absolute inline-flex h-full w-full rounded-full bg-[#DCE85D] opacity-75"></span>
<span className="relative inline-flex rounded-full h-1 w-1 bg-[#DCE85DAA]"></span>
</span>
)}
</div>

<Link
Expand Down
56 changes: 6 additions & 50 deletions apps/marginfi-v2-ui/src/components/PageHeader.tsx
Original file line number Diff line number Diff line change
@@ -1,59 +1,15 @@
import { FC } from "react";
import { FC, ReactNode } from "react";

interface PageHeaderProps {
text?: string;
children: ReactNode;
}

const PageHeader: FC<PageHeaderProps> = ({ text = "mrgnlend" }) => {
const PageHeader: FC<PageHeaderProps> = ({ children }) => {
return (
<div className="hidden sm:flex w-full flex-row justify-center border-solid border-[#1C2125] border-y-[1px]">
<div
className={
"h-[64px] w-full w-[90%] max-w-7xl pl-[60px] flex flex-row items-center py-1 font-aeonik font-normal text-3xl bg-[url('/WaveBG3.png')]"
}
>
{text}
</div>
<div className="hidden sm:flex w-full h-[60px] justify-center items-center border-solid border-[#1C2125] border-y-[1px] bg-[url('/WaveBG3.png')]">
<div className="w-4/5 max-w-7xl flex-row border-solid font-aeonik font-normal text-3xl">{children}</div>
</div>
);
};

const PageHeaderSwap: FC = () => {
return (
<div className="hidden sm:flex w-full flex-row justify-center border-solid border-[#1C2125] border-y-[1px]">
<div
className={
"h-[64px] w-full w-[90%] max-w-7xl pl-[60px] flex flex-row items-center py-1 font-aeonik font-normal text-3xl bg-[url('/WaveBG3.png')] gap-1"
}
>
swap
<span className="text-sm h-[48px] pt-[32px] bg-white bg-clip-text text-transparent">Powered</span>
{/* Different components here by word so spacing can be the same */}
<span className="text-sm h-[48px] pt-[32px] bg-white bg-clip-text text-transparent">by</span>
<span className="text-sm h-[48px] pt-[32px] bg-jup-gradient-colors bg-clip-text text-transparent">Jupiter</span>
</div>
</div>
);
};

const PageHeaderBridge: FC = () => {
return (
<div className="hidden sm:flex w-full flex-row justify-center border-solid border-[#1C2125] border-y-[1px]">
<div
className={
"h-[64px] w-full w-[90%] max-w-7xl pl-[60px] flex flex-row items-center py-1 font-aeonik font-normal text-3xl bg-[url('/WaveBG3.png')] gap-1"
}
>
bridge
<span className="text-sm h-[48px] pt-[32px] bg-white bg-clip-text text-transparent">Powered</span>
{/* Different components here by word so spacing can be the same */}
<span className="text-sm h-[48px] pt-[32px] bg-white bg-clip-text text-transparent">by</span>
<span className="text-sm mt-[6px] h-[54px] pt-[32px] bg-mayan-gradient-colors bg-clip-text text-transparent z-100">
Mayan
</span>
</div>
</div>
);
};

export { PageHeader, PageHeaderSwap, PageHeaderBridge };
export { PageHeader };
13 changes: 13 additions & 0 deletions apps/marginfi-v2-ui/src/components/Spinner.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
export const Spinner = () => ( <svg
className="animate-spin ml-1 mr-3 h-5 w-5 text-white"
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
>
<circle width="opacity-10" cx="12" cy="12" r="10" stroke="#aaa" strokeWidth="4"></circle>
<path
width="opacity-100"
fill="#DCE85D"
d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"
></path>
</svg>)
Loading