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

Develop #991

Merged
merged 26 commits into from
Dec 7, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
5316d75
fix: update catch clause when creating account
borcherd Dec 2, 2024
b9aad32
chore: cleanup callback deps
borcherd Dec 2, 2024
2a084b9
fix: change disabled styling loop max button
borcherd Dec 3, 2024
19e37ed
chore: text-center on actioncomplete title
borcherd Dec 3, 2024
bcd013b
fix: update catch clause when creating account
borcherd Dec 2, 2024
0d4cdc3
chore: cleanup callback deps
borcherd Dec 2, 2024
a9d06ac
feat: initial work
borcherd Dec 2, 2024
9dac1bc
feat: update tx logic & remove logs
borcherd Dec 2, 2024
30727b7
chore: QA implementation
borcherd Dec 2, 2024
115a0d7
chore: add creata ata ix when needed
borcherd Dec 2, 2024
c86c4d1
feat: move account label fetching to ui store and pass into wallet
borcherd Nov 29, 2024
e6cc98c
chore: PR comments implementation
borcherd Dec 2, 2024
019a7c3
chore: PR changes
borcherd Dec 2, 2024
5a17d7a
fix: hydration error on the arena
borcherd Dec 3, 2024
fcfb485
feat: implement react-focus-on package for command input
borcherd Dec 4, 2024
c1c56f0
chore: remove superfluous code
borcherd Dec 4, 2024
6bdbacc
fix: enable add account button on portfolio
borcherd Dec 4, 2024
86a4972
fix: show settings
borcherd Dec 4, 2024
0544c15
fix: issues with mrgnlend provider fetching
k0beLeenders Dec 4, 2024
3c4a12e
feat: add sorting to account labels & suggest correct account label
borcherd Dec 5, 2024
b236a86
chore: add focusOn comment
borcherd Dec 5, 2024
ee83c98
chore: update account label fallback
borcherd Dec 6, 2024
898552e
fix: not enough tokens disabled on looper
k0beLeenders Dec 6, 2024
93b3034
fix: default to dialog version token dropdown on ios pwa
chambaz Dec 7, 2024
31a1144
fix: command input mobile styles
chambaz Dec 7, 2024
8b504c0
chore: remove focus-on package
chambaz Dec 7, 2024
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
2 changes: 1 addition & 1 deletion apps/marginfi-v2-trading/src/pages/_app.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ export default function MrgnApp({ Component, pageProps, path, bank }: AppProps &
</ConnectionProvider>
)}
<Tutorial />
{process.env.NEXT_PUBLIC_ANALYTICS === "true" && (
{process.env.NEXT_PUBLIC_ANALYTICS === "true" && ready && (
<>
<GoogleAnalytics gaId="G-T5B2WRLKL9" />
<GoogleTagManager gtmId="GTM-WFBC4RZ7" />
Expand Down
35 changes: 24 additions & 11 deletions apps/marginfi-v2-ui/src/components/common/Navbar/Navbar.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { FC } from "react";
import React, { FC } from "react";

import Link from "next/link";
import Image from "next/image";
Expand Down Expand Up @@ -45,16 +45,27 @@ export const Navbar: FC = () => {
state.fetchMrgnlendState,
]);

const { isOraclesStale, priorityType, broadcastType, priorityFees, maxCap, maxCapType, setTransactionSettings } =
useUiStore((state) => ({
isOraclesStale: state.isOraclesStale,
priorityType: state.priorityType,
broadcastType: state.broadcastType,
priorityFees: state.priorityFees,
maxCap: state.maxCap,
maxCapType: state.maxCapType,
setTransactionSettings: state.setTransactionSettings,
}));
const {
isOraclesStale,
priorityType,
broadcastType,
priorityFees,
maxCap,
maxCapType,
setTransactionSettings,
accountLabels,
fetchAccountLabels,
} = useUiStore((state) => ({
isOraclesStale: state.isOraclesStale,
priorityType: state.priorityType,
broadcastType: state.broadcastType,
priorityFees: state.priorityFees,
maxCap: state.maxCap,
maxCapType: state.maxCapType,
setTransactionSettings: state.setTransactionSettings,
accountLabels: state.accountLabels,
fetchAccountLabels: state.fetchAccountLabels,
}));

const [userPointsData] = useUserProfileStore((state) => [state.userPointsData]);

Expand Down Expand Up @@ -200,6 +211,8 @@ export const Navbar: FC = () => {
...priorityFees,
broadcastType,
}}
accountLabels={accountLabels}
fetchAccountLabels={fetchAccountLabels}
/>
</div>
)}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -162,7 +162,16 @@ export const MovePositionDialog = ({
} finally {
setIsExecutionLoading(false);
}
}, [marginfiClient, accountToMoveTo, actionTxns, broadcastType, priorityFees, fetchMrgnlendState, setIsOpen]);
}, [
marginfiClient,
accountToMoveTo,
actionTxns,
broadcastType,
priorityFees,
selectedAccount?.address,
fetchMrgnlendState,
setIsOpen,
]);

React.useEffect(() => {
if (!accountToMoveTo) return;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,9 @@ import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogDescription } f
import { Button } from "~/components/ui/button";
import { IconLoader } from "~/components/ui/icons";

import { rewardsType } from "../../types";
import { RewardsType } from "../../types";
interface RewardsDialogProps extends DialogProps {
availableRewards: rewardsType | null;
availableRewards: RewardsType;
onClose: () => void;
onCollect: () => void;
isLoading: boolean;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,50 +3,90 @@ import React from "react";
import { PublicKey, VersionedTransaction } from "@solana/web3.js";

import { MarginfiAccountWrapper, MarginfiClient } from "@mrgnlabs/marginfi-client-v2";
import { ActionMessageType, captureSentryException, TOKEN_2022_MINTS } from "@mrgnlabs/mrgn-utils";
import {
ActionMessageType,
captureSentryException,
EMISSION_MINT_INFO_MAP,
TOKEN_2022_MINTS,
} from "@mrgnlabs/mrgn-utils";
import { ExtendedBankInfo } from "@mrgnlabs/marginfi-v2-ui-state";
import {
AccountLayout,
getAssociatedTokenAddressSync,
nativeToUi,
numeralFormatter,
SolanaTransaction,
TOKEN_2022_PROGRAM_ID,
TOKEN_PROGRAM_ID,
} from "@mrgnlabs/mrgn-common";

import { rewardsType } from "../types";
import { RewardsType } from "../types";

type RewardSimulationProps = {
simulationResult: rewardsType | null;
actionTxn: VersionedTransaction | null;
simulationResult: RewardsType | null;
marginfiClient: MarginfiClient | null;
selectedAccount: MarginfiAccountWrapper | null;
extendedBankInfos: ExtendedBankInfo[];

setSimulationResult: (result: rewardsType | null) => void;
setActionTxn: (actionTxn: VersionedTransaction | null) => void;
setSimulationResult: (result: RewardsType) => void;
setActionTxn: (actionTxn: SolanaTransaction) => void;
setErrorMessage: (error: ActionMessageType | null) => void;
};

export const useRewardSimulation = ({
actionTxn,
marginfiClient,
selectedAccount,
extendedBankInfos,
setSimulationResult,
setActionTxn,
}: RewardSimulationProps) => {
const bankAddressesWithEmissions: PublicKey[] = React.useMemo(() => {
if (!extendedBankInfos) return [];
return extendedBankInfos.filter((bank) => bank.info.state.emissionsRate > 0).map((bank) => bank.meta.address);
}, [extendedBankInfos]);
const generateTxn = async (
banksWithEmissions: ExtendedBankInfo[],
selectedAccount: MarginfiAccountWrapper
): Promise<SolanaTransaction | undefined> => {
try {
const bankAddressesWithEmissions = banksWithEmissions.map((bank) => bank.meta.address);
const tx = await selectedAccount?.makeWithdrawEmissionsTx(bankAddressesWithEmissions);
if (!tx) return;
return tx;
} catch (error) {
console.error("Error generating emissions transaction", error);
}
};

const handleSimulation = React.useCallback(async () => {
try {
if (!actionTxn || !marginfiClient || !selectedAccount) {
if (!marginfiClient || !selectedAccount) {
setSimulationResult({
state: "ERROR",
tooltipContent: "Error fetching rewards",
rewards: [],
totalReward: 0,
totalRewardAmount: 0,
});
return;
}

const banksWithEmissions = extendedBankInfos.filter((bank) => bank.info.state.emissionsRate > 0);
if (!banksWithEmissions.length) {
setSimulationResult({
state: "NO_REWARDS",
tooltipContent: "There are currently no banks that are outputting rewards.",
rewards: [],
totalRewardAmount: 0,
});
return;
}

const txns = await generateTxn(banksWithEmissions, selectedAccount);

if (!txns) {
setSimulationResult({
state: "NO_REWARDS",
tooltipContent: `You do not have any outstanding rewards. Deposit into a bank with emissions to earn additional rewards on top of yield. Banks with emissions: ${[
...banksWithEmissions.map((bank) => bank.meta.tokenSymbol),
].join(", ")}`,
rewards: [],
totalRewardAmount: 0,
});
return;
}
Expand All @@ -56,13 +96,12 @@ export const useRewardSimulation = ({

const atas: PublicKey[] = [];

for (let bankAddress of bankAddressesWithEmissions) {
const bank = marginfiClient.getBankByPk(bankAddress);
for (let bank of banksWithEmissions) {
if (!bank) continue;

const tokenMint = bank.emissionsMint;
const tokenSymbol = bank.tokenSymbol ?? "";
const mintDecimals = bank.mintDecimals;
const tokenMint = bank.info.rawBank.emissionsMint;
const tokenSymbol = bank.info.rawBank.tokenSymbol ?? "";
const mintDecimals = bank.info.rawBank.mintDecimals;
if (!tokenMint) continue;

const programId = TOKEN_2022_MINTS.includes(tokenMint.toString()) ? TOKEN_2022_PROGRAM_ID : TOKEN_PROGRAM_ID;
Expand All @@ -71,28 +110,32 @@ export const useRewardSimulation = ({
atas.push(ata);

const originData = await marginfiClient.provider.connection.getAccountInfo(ata);
if (!originData) continue;
let beforeAmount = "0";
if (originData) {
beforeAmount = AccountLayout.decode(originData.data).amount.toString();
}

const beforeAmount = AccountLayout.decode(originData.data).amount.toString();
beforeAmounts.set(bankAddress, { amount: beforeAmount, tokenSymbol, mintDecimals });
beforeAmounts.set(bank.meta.address, { amount: beforeAmount, tokenSymbol, mintDecimals });
}

if (beforeAmounts.size === 0) {
setSimulationResult({
totalReward: 0,
state: "NO_REWARDS",
tooltipContent: "",
rewards: [],
totalRewardAmount: 0,
});
return;
}

const previewAtas = await marginfiClient.simulateTransactions([actionTxn], atas);
const previewAtas = await marginfiClient.simulateTransactions([txns], atas);
if (!previewAtas[0]) return;

previewAtas.forEach((ata, index) => {
if (!ata) return;

const afterAmount = AccountLayout.decode(ata).amount.toString();
const bankAddress = bankAddressesWithEmissions[index];
const bankAddress = banksWithEmissions[index].meta.address;
const beforeData = beforeAmounts.get(bankAddress);

if (beforeData) {
Expand All @@ -104,9 +147,11 @@ export const useRewardSimulation = ({
}
});

let rewards: rewardsType = {
totalReward: 0,
let rewards: RewardsType = {
state: "REWARDS_FETCHED",
tooltipContent: "",
rewards: [],
totalRewardAmount: 0,
};

beforeAmounts.forEach((beforeData, bankAddress) => {
Expand All @@ -122,45 +167,29 @@ export const useRewardSimulation = ({
bank: beforeData.tokenSymbol,
amount: rewardAmount < 0.01 ? "<0.01" : numeralFormatter(rewardAmount),
});
rewards.totalReward += rewardAmount;
rewards.totalRewardAmount += rewardAmount;
}
}
});

setSimulationResult(rewards);
setActionTxn(txns);
} catch (error) {
console.error("Error simulating emissions transactions", error);
captureSentryException(error, "Error simulating emissions transactions", {
action: "rewardSimulation",
walletAddress: selectedAccount?.address.toBase58(),
});
setSimulationResult({
totalReward: 0,
state: "NO_REWARDS",
tooltipContent: "",
rewards: [],
totalRewardAmount: 0,
});
}
}, [actionTxn, bankAddressesWithEmissions, marginfiClient, selectedAccount, setSimulationResult]);

const generateTxn = React.useCallback(async () => {
try {
if (!bankAddressesWithEmissions.length) return;
const tx = await selectedAccount?.makeWithdrawEmissionsTx(bankAddressesWithEmissions);
if (!tx) return;
setActionTxn(tx);
} catch (error) {
setActionTxn(null);
}
}, [bankAddressesWithEmissions, selectedAccount, setActionTxn]);

React.useEffect(() => {
if (bankAddressesWithEmissions.length) {
generateTxn();
}
}, [bankAddressesWithEmissions, generateTxn]);
}, [extendedBankInfos, marginfiClient, selectedAccount, setActionTxn, setSimulationResult]);

return {
handleSimulation,
generateTxn,
bankAddressesWithEmissions,
};
};
Loading
Loading