From f3577209a70f42ce9d56ac8d9e6adbc7c51463dd Mon Sep 17 00:00:00 2001 From: Mudit Mahajan Date: Thu, 4 Apr 2024 12:15:46 +0530 Subject: [PATCH 1/8] Refactor cancel and confirm escrow functions, add retry logic, and improve error handling --- src/api/marketplace/orders/tasks.py | 40 ++++++++++++++++++++--------- src/api/marketplace/orders/views.py | 34 ++++++++++++++++-------- 2 files changed, 52 insertions(+), 22 deletions(-) diff --git a/src/api/marketplace/orders/tasks.py b/src/api/marketplace/orders/tasks.py index 66edcb5e..6c2ce7a9 100644 --- a/src/api/marketplace/orders/tasks.py +++ b/src/api/marketplace/orders/tasks.py @@ -96,23 +96,29 @@ def cancel_escrow(order_id: str, status: str): on_chain_transaction.save() # After the above task is finished successfully, update the order status to cancelled - order.status = status - order.save() - create_order_tracking(order=order, status=status) - create_notification_for_order(order=order, old_status='accepted', new_status=status) + if on_chain_transaction.is_confirmed: - escrow.status = "cancelled" - escrow.save() + order.status = status + order.save() - return True + create_order_tracking(order=order, status=status) + create_notification_for_order( + order=order, old_status='accepted', new_status=status) + + escrow.status = "cancelled" + escrow.save() + + return True + else: + return False except Exception as e: logger.error('Error in cancelling escrow: %s', str(e)) return False -@celery_app.task(base=QueueOnce, once={'graceful': True}) +@celery_app.task(base=QueueOnce, once={'graceful': True}, autoretry_for=(Exception,), retry_kwargs={'max_retries': 3}) def confirm_escrow(order_id: str): try: # Get order and corresponding escrow @@ -169,11 +175,21 @@ def confirm_escrow(order_id: str): on_chain_transaction.save() - order.status = 'completed' - order.save() + if on_chain_transaction.is_confirmed: + order.status = 'completed' + order.save() - escrow.status = "delivered" - escrow.save() + create_order_tracking(order=order, status=order.status) + create_notification_for_order( + order=order, old_status='accepted', new_status='completed') + + escrow.status = "delivered" + escrow.save() + + return True + + else: + return False except Exception as e: raise Exception('Error in confirming escrow', str(e)) diff --git a/src/api/marketplace/orders/views.py b/src/api/marketplace/orders/views.py index a74dafe7..53ca156b 100644 --- a/src/api/marketplace/orders/views.py +++ b/src/api/marketplace/orders/views.py @@ -740,7 +740,7 @@ def put(self, request, pk): status=status.HTTP_400_BAD_REQUEST, ) else: - if not on_chain_transaction.err: + if not on_chain_transaction.err and on_chain_transaction.created_at > timezone.now() - timezone.timedelta(minutes=5): action = "cancellation" if request.user_account.id == order.buyer.id else "rejection" return Response( { @@ -752,15 +752,29 @@ def put(self, request, pk): status=status.HTTP_400_BAD_REQUEST, ) else: - return Response( - { - "isSuccess": False, - "message": "Order cancellation failed", - "data": None, - "errors": "Order cancellation failed", - }, - status=status.HTTP_400_BAD_REQUEST, - ) + # Retry the transaction + res = cancel_escrow(pk, order_status) + if res: + # Cancel all order items + order_items.update(status=order_status) + return Response( + { + "isSuccess": True, + "data": None, + "message": "Order cancelled successfully", + }, + status=status.HTTP_200_OK, + ) + else: + return Response( + { + "isSuccess": False, + "message": "Order cancellation failed", + "data": None, + "errors": "Order cancellation failed", + }, + status=status.HTTP_400_BAD_REQUEST, + ) # Create an on chain transaction else: self.create_on_chain_transaction(order) From 968c441ae2e63f2a112de58e6cc6bc715c9b2a30 Mon Sep 17 00:00:00 2001 From: Mudit Mahajan Date: Thu, 4 Apr 2024 12:16:07 +0530 Subject: [PATCH 2/8] Add WalletConnectModal component and setConnectWallet state --- src/ui/app/business/dashboard/page.tsx | 13 ++++++++++++- .../web3Components/cancelEscrow/index.tsx | 4 ++++ 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/src/ui/app/business/dashboard/page.tsx b/src/ui/app/business/dashboard/page.tsx index caa5a9f2..fc0defc7 100644 --- a/src/ui/app/business/dashboard/page.tsx +++ b/src/ui/app/business/dashboard/page.tsx @@ -65,6 +65,7 @@ import CheckCircleIcon from "@mui/icons-material/CheckCircle"; import CancelIcon from "@mui/icons-material/Cancel"; import RuleOutlinedIcon from "@mui/icons-material/RuleOutlined"; import ManualVerifyModal from "@/src/components/dashboardComponents/manualVerifyModal"; +import WalletConnectModal from "@/src/components/web3Components/walletConnectModal"; const tabs = [ { @@ -82,6 +83,7 @@ const tabs = [ ]; export default function BusinessDashboardPage() { const router = useRouter(); + const [connectWallet, setConnectWallet] = useState(false); const searchParams = useSearchParams(); const [selectedOrder, setSelectedOrder] = useState(null); const [loading, setLoading] = useState(false); @@ -858,7 +860,11 @@ export default function BusinessDashboardPage() { transaction.transaction_type === TRANSACTION_TYPE.CANCEL_ESCROW )?.length === 0 && ( - + )} {(params?.row?.status === ORDER_STATUS.ACCEPTED || params?.row?.status === ORDER_STATUS.PENDING) && @@ -1530,6 +1536,11 @@ export default function BusinessDashboardPage() { /> ) : null} + ); } diff --git a/src/ui/src/components/web3Components/cancelEscrow/index.tsx b/src/ui/src/components/web3Components/cancelEscrow/index.tsx index 806678ff..0786916e 100644 --- a/src/ui/src/components/web3Components/cancelEscrow/index.tsx +++ b/src/ui/src/components/web3Components/cancelEscrow/index.tsx @@ -24,6 +24,7 @@ import { notification } from "../../shared/notification"; type CancelEscrowProps = { order: OrderType; updateStatus: () => void; + setConnectWallet: (value: boolean) => void; }; const programId = new PublicKey(idl.metadata.address); @@ -31,6 +32,7 @@ const programId = new PublicKey(idl.metadata.address); export default function CancelEscrow({ updateStatus, order, + setConnectWallet, }: CancelEscrowProps) { const [localLoading, setLocalLoading] = useState(false); const connection = new Connection(`https://api.devnet.solana.com`, { @@ -86,12 +88,14 @@ export default function CancelEscrow({ // Check if wallet is connected if (!connection || !publicKey) { notification("Please connect your wallet first", "error"); + setConnectWallet(true); return; } // Check that the correct wallet is connected if (publicKey?.toBase58() !== order?.buyer_wallet?.wallet_address_id) { notification("Please connect the correct wallet", "error"); + setConnectWallet(true); return; } From 24344b68330b5ba568deae1ff6a19b5519a45a66 Mon Sep 17 00:00:00 2001 From: Mudit Mahajan Date: Thu, 4 Apr 2024 12:16:13 +0530 Subject: [PATCH 3/8] Add WalletConnectModal component and setConnectWallet state --- src/ui/app/influencer/dashboard/page.tsx | 17 ++++++++++++++--- .../web3Components/claimEscrow/index.tsx | 4 ++++ 2 files changed, 18 insertions(+), 3 deletions(-) diff --git a/src/ui/app/influencer/dashboard/page.tsx b/src/ui/app/influencer/dashboard/page.tsx index 757f91ec..f32ae6b8 100644 --- a/src/ui/app/influencer/dashboard/page.tsx +++ b/src/ui/app/influencer/dashboard/page.tsx @@ -55,6 +55,7 @@ import MessageIcon from "@mui/icons-material/Message"; import Joyride, { ACTIONS, EVENTS, STATUS } from "react-joyride"; import XfluencerLogo from "@/public/svg/Xfluencer_Logo_Beta.svg"; import { DriveEta } from "@mui/icons-material"; +import WalletConnectModal from "@/src/components/web3Components/walletConnectModal"; const tabs = [ { @@ -90,6 +91,7 @@ const getProfileCompletedStatus: (businessDetails: any) => string = ( export default function BusinessDashboardPage() { const router = useRouter(); const searchParams = useSearchParams(); + const [connectWallet, setConnectWallet] = useState(false); const [selectedOrder, setSelectedOrder] = useState(null); const [loading, setLoading] = useState(false); const [orders, setOrders] = useState([]); @@ -178,8 +180,8 @@ export default function BusinessDashboardPage() { Customized filters. - Advanced filters for orders based on the services, date, order ID, and - businesses. + Advanced filters for orders based on the services, date, order ID, + and businesses. ), @@ -853,7 +855,11 @@ export default function BusinessDashboardPage() { (transaction: TransactionType) => transaction.transaction_type === TRANSACTION_TYPE.CLAIM_ESCROW )?.length === 0 && ( - + )} ); @@ -1452,6 +1458,11 @@ export default function BusinessDashboardPage() { /> ) : null} + ); } diff --git a/src/ui/src/components/web3Components/claimEscrow/index.tsx b/src/ui/src/components/web3Components/claimEscrow/index.tsx index dcc6ac13..12c3bc0d 100644 --- a/src/ui/src/components/web3Components/claimEscrow/index.tsx +++ b/src/ui/src/components/web3Components/claimEscrow/index.tsx @@ -24,6 +24,7 @@ import { notification } from "../../shared/notification"; type CreateEscrowProps = { order: OrderType; updateStatus: () => void; + setConnectWallet: (value: boolean) => void; }; const programId = new PublicKey(idl.metadata.address); @@ -31,6 +32,7 @@ const programId = new PublicKey(idl.metadata.address); export default function ClaimEscrow({ updateStatus, order, + setConnectWallet, }: CreateEscrowProps) { const [localLoading, setLocalLoading] = useState(false); const connection = new Connection(`https://api.devnet.solana.com`, { @@ -82,6 +84,7 @@ export default function ClaimEscrow({ // Check if wallet is connected if (!connection || !publicKey) { notification("Please connect your wallet first", "error"); + setConnectWallet(true); return; } @@ -90,6 +93,7 @@ export default function ClaimEscrow({ publicKey?.toBase58() !== order?.influencer_wallet?.wallet_address_id ) { notification("Please connect the correct wallet", "error"); + setConnectWallet(true); return; } From 913029c00988f2f5a6b2bc081ccc86d5d6e93182 Mon Sep 17 00:00:00 2001 From: Mudit Mahajan Date: Thu, 4 Apr 2024 12:16:16 +0530 Subject: [PATCH 4/8] Add LOGIN_METHODS import to walletsTable component --- src/ui/src/components/walletsTable/index.tsx | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/ui/src/components/walletsTable/index.tsx b/src/ui/src/components/walletsTable/index.tsx index 750339ea..cd1ab1ff 100644 --- a/src/ui/src/components/walletsTable/index.tsx +++ b/src/ui/src/components/walletsTable/index.tsx @@ -23,6 +23,7 @@ import Image from "next/image"; import { useEffect, useState } from "react"; import { ConfirmDelete } from "../shared/confirmDeleteModal"; import { notification } from "../shared/notification"; +import { LOGIN_METHODS } from "@/src/utils/consts"; type Props = { walletOpen: boolean; @@ -114,7 +115,10 @@ export default function WalletsTable({ walletOpen }: Props) { const disConnectWallet = async () => { try { - if (connectedWallet?.wallet_address_id === user?.user?.username) { + if ( + connectedWallet?.wallet_address_id === user?.user?.username && + user?.user?.login_method === LOGIN_METHODS.WALLET + ) { await logoutTwitterUser(); return; } From 26aabe703f1a6e71ba1d09ee877aec3e443862e1 Mon Sep 17 00:00:00 2001 From: Mudit Mahajan Date: Thu, 4 Apr 2024 12:37:34 +0530 Subject: [PATCH 5/8] Refactor Navbar component --- src/ui/app/components/navbar/index.tsx | 33 +++----------------------- 1 file changed, 3 insertions(+), 30 deletions(-) diff --git a/src/ui/app/components/navbar/index.tsx b/src/ui/app/components/navbar/index.tsx index 724bebec..3859cbe3 100644 --- a/src/ui/app/components/navbar/index.tsx +++ b/src/ui/app/components/navbar/index.tsx @@ -38,11 +38,6 @@ import NextLink from "next/link"; import SavedProfileIcon from "@/public/svg/Saved.svg"; import SavedProfileDisabledIcon from "@/public/svg/Saved_disabled.svg"; -type NavbarProps = { - setCategoryOpen: React.Dispatch>; - categoryOpen: boolean; -}; - const MENU_ITEMS: { [key: string]: { label: string; @@ -71,7 +66,7 @@ const MENU_ITEMS: { }, Dashboard: { label: "Dashboard", - route: "/dashboard?tab=orders", + route: "/dashboard", icon: DashboardIcon, disabledIcon: DashboardDisabledIcon, }, @@ -228,13 +223,8 @@ const MenuItemsComponent = ({ items }: { items: string[] }) => { ) : null; }; -export default function Navbar({ setCategoryOpen, categoryOpen }: NavbarProps) { - const { - isTwitterUserLoggedIn, - logoutTwitterUser, - isAccountSetupComplete, - checkAccountSetup, - } = useTwitterAuth(); +export default function Navbar() { + const { isTwitterUserLoggedIn, logoutTwitterUser } = useTwitterAuth(); const router = useRouter(); const pathname = usePathname(); @@ -260,23 +250,6 @@ export default function Navbar({ setCategoryOpen, categoryOpen }: NavbarProps) { } }, [isTwitterUserLoggedIn]); - useEffect(() => { - const status = params.get("authenticationStatus"); - if ( - isTwitterUserLoggedIn && - !isAccountSetupComplete && - status === "success" - ) { - setCategoryOpen(true); - } - }, [isTwitterUserLoggedIn, isAccountSetupComplete]); - - useEffect(() => { - if (!categoryOpen) { - checkAccountSetup(); - } - }, [categoryOpen]); - const handleConnect = () => { const roleQueryParams = pathname.includes("business") ? "Business" From 63b6cd35b5429c83498c63f242c524d10261d962 Mon Sep 17 00:00:00 2001 From: Mudit Mahajan Date: Thu, 4 Apr 2024 12:37:39 +0530 Subject: [PATCH 6/8] Remove unused components and state variables --- src/ui/app/layout.tsx | 23 ++--------------------- 1 file changed, 2 insertions(+), 21 deletions(-) diff --git a/src/ui/app/layout.tsx b/src/ui/app/layout.tsx index afc41f1e..36f7d58e 100644 --- a/src/ui/app/layout.tsx +++ b/src/ui/app/layout.tsx @@ -1,13 +1,10 @@ "use client"; -import CategorySelectionModal from "@/src/components/categorySelectionModal"; -import EmailLoginModal from "@/src/components/emailLoginModal"; import WalletContextProvider from "@/src/components/shared/walletContextProvider"; -import WalletConnectModal from "@/src/components/web3Components/walletConnectModal"; import { AppStore, makeStore } from "@/src/store"; import { Inter } from "next/font/google"; import { SnackbarProvider } from "notistack"; -import { useRef, useState } from "react"; +import { useRef } from "react"; import { Provider } from "react-redux"; import { persistStore } from "redux-persist"; import { PersistGate } from "redux-persist/integration/react"; @@ -29,10 +26,6 @@ export default function RootLayout({ } const persistor = persistStore(storeRef.current); - const [emailOpen, setEmailOpen] = useState(false); - const [categoryOpen, setCategoryOpen] = useState(false); - const [walletOpen, setWalletOpen] = useState(false); - return ( @@ -52,20 +45,8 @@ export default function RootLayout({ - + {children} - - - From 721c0ef371fea615cbf7b0601faa5c62f4f62ef9 Mon Sep 17 00:00:00 2001 From: Mudit Mahajan Date: Thu, 4 Apr 2024 12:37:44 +0530 Subject: [PATCH 7/8] Update current page size in Services component --- src/ui/app/influencer/profile/[id]/_services/index.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/ui/app/influencer/profile/[id]/_services/index.tsx b/src/ui/app/influencer/profile/[id]/_services/index.tsx index 56eecdf0..84c11186 100644 --- a/src/ui/app/influencer/profile/[id]/_services/index.tsx +++ b/src/ui/app/influencer/profile/[id]/_services/index.tsx @@ -43,7 +43,7 @@ const Services = ({ total_data_count: 0, total_page_count: 0, current_page_number: 1, - current_page_size: 10, + current_page_size: 9, }); const [loading, setLoading] = React.useState(true); const [openModal, setOpenModal] = React.useState(false); @@ -65,7 +65,7 @@ const Services = ({ page_size: id === loggedInUser?.id ? pagination.current_page_size - : pagination.current_page_size, + : pagination.current_page_size + 1, influencer: id, status: id === loggedInUser?.id ? type : "published", } From a6cdef4abe438380f8dc604e59e8ae2a79181053 Mon Sep 17 00:00:00 2001 From: Mudit Mahajan Date: Thu, 4 Apr 2024 12:37:47 +0530 Subject: [PATCH 8/8] Refactor useTwitterAuth hook --- src/ui/src/hooks/useTwitterAuth.ts | 36 ------------------------------ 1 file changed, 36 deletions(-) diff --git a/src/ui/src/hooks/useTwitterAuth.ts b/src/ui/src/hooks/useTwitterAuth.ts index def6e9eb..a666a516 100644 --- a/src/ui/src/hooks/useTwitterAuth.ts +++ b/src/ui/src/hooks/useTwitterAuth.ts @@ -22,20 +22,12 @@ export default function useTwitterAuth() { // State to track whether the user is logged in via X const [isTwitterUserLoggedIn, setTwitterUserLoggedIn] = useState(false); - const [isAccountSetupComplete, setIsAccountSetupComplete] = useState(true); const [userDetails, setUserDetails] = useState(null); - const [categoriesAdded, setCategoriesAdded] = useState(false); useEffect(() => { checkTwitterUserAuthentication(); }, []); - useEffect(() => { - if (isTwitterUserLoggedIn) { - checkAccountSetup(); - } - }, [isTwitterUserLoggedIn]); - // Function to initiate X user authentication const startTwitterAuthentication = async ({ role = "", @@ -103,39 +95,11 @@ export default function useTwitterAuth() { } }; - const checkAccountSetup = async () => { - try { - if ( - isTwitterUserLoggedIn && - userDetails?.role?.name === ROLE_NAME.INFLUENCER && - !categoriesAdded - ) { - const { isSuccess, data } = await getService( - "account/account-category/" - ); - if (isSuccess) { - if (data?.data?.length > 0) { - setIsAccountSetupComplete(true); - setCategoriesAdded(true); - } else if (data?.data?.length === 0) { - setIsAccountSetupComplete(false); - setCategoriesAdded(false); - } - } - } - } catch (error) { - console.error("Error during account setup check:", error); - } - }; - return { isTwitterUserLoggedIn, startTwitterAuthentication, logoutTwitterUser, checkTwitterUserAuthentication, - isAccountSetupComplete, userDetails, - categoriesAdded, - checkAccountSetup, }; }