diff --git a/apps/marginfi-v2-ui/src/components/Staking/StakingCard/SettingsIcon.tsx b/apps/marginfi-v2-ui/src/components/Staking/StakingCard/SettingsIcon.tsx new file mode 100644 index 0000000000..384c7ab2dd --- /dev/null +++ b/apps/marginfi-v2-ui/src/components/Staking/StakingCard/SettingsIcon.tsx @@ -0,0 +1,15 @@ +import React from "react"; + +export const SettingsIcon: React.FC> = ({ width = "12", height = "12" }) => { + return ( + + + + ); +}; diff --git a/apps/marginfi-v2-ui/src/components/Staking/StakingCard/SettingsModal.tsx b/apps/marginfi-v2-ui/src/components/Staking/StakingCard/SettingsModal.tsx new file mode 100644 index 0000000000..c15d198b0c --- /dev/null +++ b/apps/marginfi-v2-ui/src/components/Staking/StakingCard/SettingsModal.tsx @@ -0,0 +1,74 @@ +import { Typography, Modal, SvgIcon } from "@mui/material"; +import { Dispatch, FC, SetStateAction, useEffect, useMemo, useState } from "react"; +import { Close } from "@mui/icons-material"; +import { TokenData } from "./StakingCard"; +import Image from "next/image"; +import { PublicKey } from "@solana/web3.js"; +import { NumberFormatValues, NumericFormat } from "react-number-format"; +import { PrimaryButton } from "./PrimaryButton"; + +interface SettingsModalProps { + isOpen: boolean; + handleClose: () => void; + setSelectedSlippage: Dispatch>; + selectedSlippage: number; +} + +const SLIPPAGE_PRESET = [0.1, 0.5, 1.0, 5.0]; + +export const SettingsModal: FC = ({ + isOpen, + handleClose, + selectedSlippage, + setSelectedSlippage, +}) => { + const [localSlippage, setLocalSlippage] = useState(); + useEffect(() => setLocalSlippage(selectedSlippage), [selectedSlippage]); + + const onSaveSettings = () => { + setSelectedSlippage(localSlippage); + handleClose(); + }; + + return ( + +
+
+ Swap Settings +
+ +
+
+ Slippage Settings +
+ {SLIPPAGE_PRESET.map((slippage, idx) => { + const displayText = Number(slippage) + "%"; + const isHighlighted = localSlippage === slippage; + return ( + { + setLocalSlippage(slippage); + }} + > +
+ {displayText} +
+
+ ); + })} +
+ onSaveSettings()}>Save +
+
+ ); +}; diff --git a/apps/marginfi-v2-ui/src/components/Staking/StakingCard/StakingCard.tsx b/apps/marginfi-v2-ui/src/components/Staking/StakingCard/StakingCard.tsx index 15778455b7..d22d0d048e 100644 --- a/apps/marginfi-v2-ui/src/components/Staking/StakingCard/StakingCard.tsx +++ b/apps/marginfi-v2-ui/src/components/Staking/StakingCard/StakingCard.tsx @@ -17,9 +17,10 @@ import JSBI from "jsbi"; import { usePrevious } from "~/utils"; import { createJupiterApiClient, instanceOfSwapResponse } from "@jup-ag/api"; import { toast } from "react-toastify"; +import { SettingsModal } from "./SettingsModal"; +import { SettingsIcon } from "./SettingsIcon"; const SOL_MINT = new PublicKey("So11111111111111111111111111111111111111112"); -const SLIPPAGE_BPS = 5; // 0.5% slippage export interface TokenData { mint: PublicKey; @@ -45,6 +46,8 @@ export const StakingCard: FC = () => { const [swapping, setSwapping] = useState(false); const [depositAmount, setDepositAmount] = useState(null); const [selectedMint, setSelectedMint] = useState(SOL_MINT); + const [isSettingsModalOpen, setIsSettingsModalOpen] = useState(false); + const [selectedSlippage, setSelectedSlippage] = useState(0.5); const prevWalletAddress = usePrevious(walletAddress); useEffect(() => { @@ -90,7 +93,7 @@ export const StakingCard: FC = () => { inputMint: selectedMint, outputMint: SOL_MINT, swapMode: SwapMode.ExactIn, - slippageBps: SLIPPAGE_BPS, // 0.5% slippage + slippageBps: selectedSlippage, // 0.5% slippage debounceTime: 250, // debounce ms time before refresh }); @@ -147,14 +150,14 @@ export const StakingCard: FC = () => { throw new Error("Route not calculated yet"); } const outAmount = JSBI.toNumber(quoteResponseMeta.quoteResponse.outAmount); - const finalAmount = Math.floor(outAmount * (1 - SLIPPAGE_BPS / 1000)); + const finalAmount = Math.floor(outAmount * (1 - selectedSlippage / 1000)); const avoidSlippageIssues = await jupiterApiClient.quoteGet({ amount: finalAmount, // add slippage inputMint: selectedMint.toBase58(), outputMint: SOL_MINT.toBase58(), swapMode: SwapMode.ExactOut, - slippageBps: SLIPPAGE_BPS, + slippageBps: selectedSlippage, }); const swapResult = await jupiterApiClient.swapPost({ @@ -246,6 +249,15 @@ export const StakingCard: FC = () => { Deposit {connected && selectedMintInfo && (
+
setIsSettingsModalOpen(true)} + > + + + {isNaN(selectedSlippage) ? "0" : selectedSlippage}% + +
@@ -350,6 +362,12 @@ export const StakingCard: FC = () => { 0%
+ setIsSettingsModalOpen(false)} + selectedSlippage={selectedSlippage} + setSelectedSlippage={setSelectedSlippage} + /> ); };