Skip to content

Commit

Permalink
Merge pull request #232 from mrgnlabs/man0s/stake
Browse files Browse the repository at this point in the history
Man0s/stake
  • Loading branch information
losman0s authored Sep 21, 2023
2 parents 615766f + 41ead1b commit 67c1c85
Show file tree
Hide file tree
Showing 43 changed files with 1,875 additions and 143 deletions.
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

3 comments on commit 67c1c85

@vercel
Copy link

@vercel vercel bot commented on 67c1c85 Sep 21, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Successfully deployed to the following URLs:

omni – ./apps/omni

omni.marginfi.com
omni-mrgn.vercel.app
omni-one.vercel.app
omni-git-production-mrgn.vercel.app

@vercel
Copy link

@vercel vercel bot commented on 67c1c85 Sep 21, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Successfully deployed to the following URLs:

marginfi-landing-page – ./apps/marginfi-landing-page

marginfi-landing-page.vercel.app
marginfi-landing-page-git-production-mrgn.vercel.app
marginfi-landing-page-mrgn.vercel.app
www.marginfi.com
marginfi.com

@vercel
Copy link

@vercel vercel bot commented on 67c1c85 Sep 21, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.