From 988b65bc417a294a69e81cbf9b1a111c209cb6e5 Mon Sep 17 00:00:00 2001 From: Anton Cheng Date: Fri, 6 Dec 2024 22:05:30 +0800 Subject: [PATCH 1/3] chore: switch chain --- app/positions/components/RebalanceModal.tsx | 2 -- .../components/onboarding/SetupPositions.tsx | 27 ++++++++++++++++++- src/components/supplyModal.tsx | 2 -- src/hooks/useRebalance.ts | 3 +++ 4 files changed, 29 insertions(+), 5 deletions(-) diff --git a/app/positions/components/RebalanceModal.tsx b/app/positions/components/RebalanceModal.tsx index 808e3ce1..ad579967 100644 --- a/app/positions/components/RebalanceModal.tsx +++ b/app/positions/components/RebalanceModal.tsx @@ -230,8 +230,6 @@ export function RebalanceModal({ [chainId, groupedPosition.chainId], ); - console.log('needSwitchChain', needSwitchChain); - const handleExecuteRebalance = useCallback(async () => { if (needSwitchChain) { try { diff --git a/app/positions/components/onboarding/SetupPositions.tsx b/app/positions/components/onboarding/SetupPositions.tsx index 39dd010d..1d4cc12d 100644 --- a/app/positions/components/onboarding/SetupPositions.tsx +++ b/app/positions/components/onboarding/SetupPositions.tsx @@ -13,9 +13,12 @@ import { formatBalance, formatReadable } from '@/utils/balance'; import { parseOracleVendors } from '@/utils/oracle'; import { findToken } from '@/utils/tokens'; import { useOnboarding } from './OnboardingContext'; +import { useChainId, useSwitchChain } from 'wagmi'; +import { toast } from 'react-toastify'; export function SetupPositions() { const router = useRouter(); + const chainId = useChainId() const { selectedToken, selectedMarkets } = useOnboarding(); const { balances } = useUserBalances(); const [useEth] = useLocalStorage('useEth', false); @@ -27,6 +30,13 @@ export function SetupPositions() { const [error, setError] = useState(null); const [isSupplying, setIsSupplying] = useState(false); + const needSwitchChain = useMemo( + () => chainId !== selectedToken?.network, + [chainId, selectedToken], + ); + + const { switchChain } = useSwitchChain(); + // Redirect if no token selected useEffect(() => { if (!selectedToken) { @@ -222,7 +232,22 @@ export function SetupPositions() { } = useMultiMarketSupply(selectedToken!, supplies, useEth, usePermit2Setting); const handleSupply = async () => { - if (isSupplying) return; + if (isSupplying) { + toast.info('Supplying in progress') + return; + }; + + if (needSwitchChain && selectedToken) { + try { + switchChain({ chainId: selectedToken.network }); + toast.info('Network changed, please click again to execute') + return; + } catch (error) { + console.error('Failed to switch network:', error); + toast.error('Failed to switch network'); + return; + } + } setIsSupplying(true); try { diff --git a/src/components/supplyModal.tsx b/src/components/supplyModal.tsx index df833667..809e2619 100644 --- a/src/components/supplyModal.tsx +++ b/src/components/supplyModal.tsx @@ -76,8 +76,6 @@ export function SupplyModal({ market, onClose }: SupplyModalProps): JSX.Element tokenSymbol: market.loanAsset.symbol, }); - console.log('isApproved', isApproved); - const needSwitchChain = useMemo( () => chainId !== market.morphoBlue.chain.id, [chainId, market.morphoBlue.chain.id], diff --git a/src/hooks/useRebalance.ts b/src/hooks/useRebalance.ts index 431bceea..1abc56e2 100644 --- a/src/hooks/useRebalance.ts +++ b/src/hooks/useRebalance.ts @@ -204,6 +204,9 @@ export const useRebalance = (groupedPosition: GroupedPosition, onRebalance?: () const shares = groupedPosition.markets.find( (m) => m.market.uniqueKey === actions[0].fromMarket.uniqueKey, )?.supplyShares; + + console.log('shares', shares); + if (isWithdrawMax && shares === undefined) { throw new Error('No share found for max withdraw'); } From a73dc3c9a082d2e8684a0a9fbe5a1110b653ce1b Mon Sep 17 00:00:00 2001 From: Anton Cheng Date: Fri, 6 Dec 2024 22:43:53 +0800 Subject: [PATCH 2/3] feat: show portfolio avatar --- app/positions/components/PositionsContent.tsx | 63 +++++++++++++++---- .../components/PositionsSummaryTable.tsx | 19 +++++- .../components/onboarding/SetupPositions.tsx | 16 ++--- src/components/Avatar/Avatar.tsx | 5 +- 4 files changed, 79 insertions(+), 24 deletions(-) diff --git a/app/positions/components/PositionsContent.tsx b/app/positions/components/PositionsContent.tsx index d587003b..bcf0be9c 100644 --- a/app/positions/components/PositionsContent.tsx +++ b/app/positions/components/PositionsContent.tsx @@ -1,9 +1,12 @@ 'use client'; -import { useState } from 'react'; +import { useMemo, useState } from 'react'; +import { Name } from '@coinbase/onchainkit/identity'; import Link from 'next/link'; import { useParams } from 'next/navigation'; -import { FaHistory, FaGift, FaPlus } from 'react-icons/fa'; +import { FaHistory, FaGift, FaPlus, FaCircle } from 'react-icons/fa'; +import { useAccount } from 'wagmi'; +import { Avatar } from '@/components/Avatar/Avatar'; import Header from '@/components/layout/header/Header'; import EmptyScreen from '@/components/Status/EmptyScreen'; import LoadingScreen from '@/components/Status/LoadingScreen'; @@ -19,6 +22,12 @@ export default function Positions() { const [selectedPosition, setSelectedPosition] = useState(null); const { account } = useParams<{ account: string }>(); + const { address, isConnected } = useAccount(); + + const isOwner = useMemo(() => { + if (!account) return false; + return account === address; + }, [account, address]); const { loading, isRefetching, data: marketPositions, refetch } = useUserPositions(account); @@ -28,8 +37,32 @@ export default function Positions() {
+
+

Portfolio

+
-

Portfolio

+
+
+ + {isConnected && account === address && ( +
+
+ +
+
+ )} +
+
+ +
+
- + {isOwner && ( + + + + )}
@@ -102,6 +138,7 @@ export default function Positions() { ) : (
void; setShowSupplyModal: (show: boolean) => void; @@ -40,6 +42,7 @@ export function PositionsSummaryTable({ setSelectedPosition, refetch, isRefetching, + account, }: PositionsSummaryTableProps) { const [expandedRows, setExpandedRows] = useState>(new Set()); const [showRebalanceModal, setShowRebalanceModal] = useState(false); @@ -47,6 +50,12 @@ export function PositionsSummaryTable({ null, ); const [earningsPeriod, setEarningsPeriod] = useState(EarningsPeriod.Day); + const { address } = useAccount(); + + const isOwner = useMemo(() => { + if (!account) return false; + return account === address; + }, [marketPositions, address]); const getEarningsForPeriod = (position: MarketPosition) => { if (!position.earned) return '0'; @@ -355,8 +364,16 @@ export function PositionsSummaryTable({
From bcc0de39b7a7368a3aadc04e58ae3ef173fa601b Mon Sep 17 00:00:00 2001 From: Anton Cheng Date: Fri, 6 Dec 2024 23:03:10 +0800 Subject: [PATCH 3/3] chore: styling --- .../components/PositionsSummaryTable.tsx | 45 ++++++++++--------- .../components/onboarding/AssetSelection.tsx | 2 +- app/settings/faq/page.tsx | 2 +- 3 files changed, 25 insertions(+), 24 deletions(-) diff --git a/app/positions/components/PositionsSummaryTable.tsx b/app/positions/components/PositionsSummaryTable.tsx index ca19082f..81c198e7 100644 --- a/app/positions/components/PositionsSummaryTable.tsx +++ b/app/positions/components/PositionsSummaryTable.tsx @@ -1,5 +1,5 @@ import React, { useMemo, useState, useEffect } from 'react'; -import { Dropdown, DropdownTrigger, DropdownMenu, DropdownItem } from '@nextui-org/react'; +import { Dropdown, DropdownTrigger, DropdownMenu, DropdownItem, Button } from '@nextui-org/react'; import { ChevronDownIcon, ChevronUpIcon } from '@radix-ui/react-icons'; import { motion, AnimatePresence } from 'framer-motion'; import Image from 'next/image'; @@ -227,17 +227,18 @@ export function PositionsSummaryTable({
- + setEarningsPeriod(key as EarningsPeriod)} > {Object.entries(periodLabels).map(([period, label]) => ( @@ -245,14 +246,15 @@ export function PositionsSummaryTable({ ))} - +
@@ -360,14 +362,13 @@ export function PositionsSummaryTable({ /> - diff --git a/app/positions/components/onboarding/AssetSelection.tsx b/app/positions/components/onboarding/AssetSelection.tsx index 486d84d8..89241e18 100644 --- a/app/positions/components/onboarding/AssetSelection.tsx +++ b/app/positions/components/onboarding/AssetSelection.tsx @@ -114,7 +114,7 @@ export function AssetSelection() { role="button" key={`${token.symbol}-${token.network}`} onClick={() => handleTokenSelect(token)} - className="group relative flex items-start gap-4 rounded-lg border border-gray-200 bg-white p-4 text-left transition-all duration-300 hover:border-primary hover:shadow-lg dark:border-gray-700 dark:bg-gray-800/50 dark:hover:bg-gray-800" + className="group relative flex items-start gap-4 rounded border border-gray-200 bg-white p-4 text-left transition-all duration-300 hover:border-primary hover:shadow-lg dark:border-gray-700 dark:bg-gray-800/50 dark:hover:bg-gray-800" whileHover={{ scale: 1.02 }} transition={{ type: 'spring', stiffness: 300, damping: 20 }} > diff --git a/app/settings/faq/page.tsx b/app/settings/faq/page.tsx index bedae538..dbf09020 100644 --- a/app/settings/faq/page.tsx +++ b/app/settings/faq/page.tsx @@ -43,7 +43,7 @@ function FAQPage() {

Frequently Asked Questions

{faqs.map((faq, index) => ( -
+

{faq.question}

{faq.answer}

-
- +