@b3dotfun/sdk 0.0.7-alpha.16 → 0.0.7-alpha.18
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/anyspend/react/components/AnySpendCustom.js +28 -25
- package/dist/cjs/anyspend/react/components/common/OrderDetails.js +26 -7
- package/dist/cjs/anyspend/react/components/modals/EnterRecipientModal.js +5 -5
- package/dist/cjs/global-account/react/hooks/useAccountWallet.js +4 -4
- package/dist/cjs/global-account/react/hooks/useTokenFromUrl.js +4 -4
- package/dist/cjs/shared/react/hooks/index.d.ts +1 -0
- package/dist/cjs/shared/react/hooks/index.js +17 -0
- package/dist/cjs/shared/react/hooks/useNavigation.d.ts +17 -0
- package/dist/cjs/shared/react/hooks/useNavigation.js +57 -0
- package/dist/cjs/shared/react/index.d.ts +1 -0
- package/dist/cjs/shared/react/index.js +17 -0
- package/dist/esm/anyspend/react/components/AnySpendCustom.js +29 -26
- package/dist/esm/anyspend/react/components/common/OrderDetails.js +24 -5
- package/dist/esm/anyspend/react/components/modals/EnterRecipientModal.js +1 -1
- package/dist/esm/global-account/react/hooks/useAccountWallet.js +4 -4
- package/dist/esm/global-account/react/hooks/useTokenFromUrl.js +3 -3
- package/dist/esm/shared/react/hooks/index.d.ts +1 -0
- package/dist/esm/shared/react/hooks/index.js +1 -0
- package/dist/esm/shared/react/hooks/useNavigation.d.ts +17 -0
- package/dist/esm/shared/react/hooks/useNavigation.js +52 -0
- package/dist/esm/shared/react/index.d.ts +1 -0
- package/dist/esm/shared/react/index.js +1 -0
- package/dist/types/shared/react/hooks/index.d.ts +1 -0
- package/dist/types/shared/react/hooks/useNavigation.d.ts +17 -0
- package/dist/types/shared/react/index.d.ts +1 -0
- package/package.json +1 -1
- package/src/anyspend/react/components/AnySpendCustom.tsx +44 -9
- package/src/anyspend/react/components/common/OrderDetails.tsx +30 -7
- package/src/anyspend/react/components/modals/EnterRecipientModal.tsx +1 -1
- package/src/global-account/react/hooks/useAccountWallet.tsx +4 -4
- package/src/global-account/react/hooks/useTokenFromUrl.tsx +3 -3
- package/src/shared/react/hooks/index.ts +1 -0
- package/src/shared/react/hooks/useNavigation.ts +61 -0
- package/src/shared/react/index.ts +1 -0
|
@@ -95,14 +95,15 @@ function AnySpendCustom({ isMainnet = true, loadOrder, mode = "modal", recipient
|
|
|
95
95
|
const [activeTab, setActiveTab] = (0, react_2.useState)("crypto");
|
|
96
96
|
// Get current user's wallet
|
|
97
97
|
const currentWallet = (0, react_1.useAccountWallet)();
|
|
98
|
-
|
|
99
|
-
const
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
const
|
|
104
|
-
|
|
105
|
-
|
|
98
|
+
// Add state for recipient modal
|
|
99
|
+
const [isRecipientModalOpen, setIsRecipientModalOpen] = (0, react_2.useState)(false);
|
|
100
|
+
// Add state for custom recipient
|
|
101
|
+
const [customRecipientAddress, setCustomRecipientAddress] = (0, react_2.useState)(recipientAddressProps);
|
|
102
|
+
// Update recipient logic to use custom recipient
|
|
103
|
+
const recipientAddress = customRecipientAddress || currentWallet.address;
|
|
104
|
+
const recipientPropsProfile = (0, react_1.useBsmntProfile)({ address: recipientAddress });
|
|
105
|
+
const recipientEnsName = recipientPropsProfile.data?.username?.replaceAll(".b3.fun", "");
|
|
106
|
+
const recipientImageUrl = recipientPropsProfile.data?.avatar || currentWallet.wallet.meta?.icon;
|
|
106
107
|
const [orderId, setOrderId] = (0, react_2.useState)(loadOrder);
|
|
107
108
|
const [srcChainId, setSrcChainId] = (0, react_2.useState)(isMainnet ? chains_1.base.id : chains_1.baseSepolia.id);
|
|
108
109
|
// Get token list for token balance check
|
|
@@ -350,7 +351,7 @@ function AnySpendCustom({ isMainnet = true, loadOrder, mode = "modal", recipient
|
|
|
350
351
|
? "Receive NFT at"
|
|
351
352
|
: orderType === anyspend_1.OrderType.JoinTournament
|
|
352
353
|
? "Join for"
|
|
353
|
-
: "Recipient" }), (0, jsx_runtime_1.jsx)("div", { children: (0, jsx_runtime_1.jsxs)(react_1.Button, { variant: "outline", className: "w-full justify-between border-none p-0", children: [(0, jsx_runtime_1.jsxs)("div", { className: "flex items-center gap-2", children: [recipientImageUrl && ((0, jsx_runtime_1.jsx)("img", { src: recipientImageUrl, alt: recipientImageUrl, className: "bg-b3-react-foreground size-7 rounded-full object-cover opacity-100" })), (0, jsx_runtime_1.jsxs)("div", { className: "flex flex-col items-start gap-1", children: [recipientEnsName && (0, jsx_runtime_1.jsxs)("span", { children: ["@", recipientEnsName] }), (0, jsx_runtime_1.jsx)("span", { children: (0, centerTruncate_1.default)(recipientAddress) })] })] }), (0, jsx_runtime_1.jsx)(lucide_react_1.ChevronRightCircle, { className: "ml-2 size-4 shrink-0 opacity-50" })] }) })] })) : null;
|
|
354
|
+
: "Recipient" }), (0, jsx_runtime_1.jsx)("div", { children: (0, jsx_runtime_1.jsxs)(react_1.Button, { variant: "outline", className: "w-full justify-between border-none p-0", onClick: () => setIsRecipientModalOpen(true), children: [(0, jsx_runtime_1.jsxs)("div", { className: "flex items-center gap-2", children: [recipientImageUrl && ((0, jsx_runtime_1.jsx)("img", { src: recipientImageUrl, alt: recipientImageUrl, className: "bg-b3-react-foreground size-7 rounded-full object-cover opacity-100" })), (0, jsx_runtime_1.jsxs)("div", { className: "flex flex-col items-start gap-1", children: [recipientEnsName && (0, jsx_runtime_1.jsxs)("span", { children: ["@", recipientEnsName] }), (0, jsx_runtime_1.jsx)("span", { children: (0, centerTruncate_1.default)(recipientAddress) })] })] }), (0, jsx_runtime_1.jsx)(lucide_react_1.ChevronRightCircle, { className: "ml-2 size-4 shrink-0 opacity-50" })] }) })] })) : null;
|
|
354
355
|
const historyView = ((0, jsx_runtime_1.jsx)("div", { className: (0, utils_1.cn)("mx-auto flex w-full max-w-2xl flex-col items-center p-5", mode === "modal" && "bg-b3-react-background"), children: (0, jsx_runtime_1.jsx)(OrderHistory_1.OrderHistory, { mode: mode, onBack: () => {
|
|
355
356
|
setActivePanel(PanelView.HISTORY);
|
|
356
357
|
}, onSelectOrder: onSelectOrder }) }));
|
|
@@ -408,20 +409,22 @@ function AnySpendCustom({ isMainnet = true, loadOrder, mode = "modal", recipient
|
|
|
408
409
|
}
|
|
409
410
|
: undefined, recipientEnsName: recipientEnsName, recipientImageUrl: recipientImageUrl }) }) })] })] }));
|
|
410
411
|
// Return the TransitionPanel with all views
|
|
411
|
-
return ((0, jsx_runtime_1.
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
412
|
+
return ((0, jsx_runtime_1.jsxs)(react_1.StyleRoot, { children: [(0, jsx_runtime_1.jsx)(react_1.TransitionPanel, { activeIndex: orderId
|
|
413
|
+
? oat
|
|
414
|
+
? PanelView.ORDER_DETAILS
|
|
415
|
+
: PanelView.LOADING
|
|
416
|
+
: activePanel === PanelView.ORDER_DETAILS
|
|
417
|
+
? PanelView.CONFIRM_ORDER
|
|
418
|
+
: activePanel, className: (0, utils_1.cn)("w-full"), variants: {
|
|
419
|
+
enter: { x: 300, opacity: 0 },
|
|
420
|
+
center: { x: 0, opacity: 1 },
|
|
421
|
+
exit: { x: -300, opacity: 0 },
|
|
422
|
+
}, transition: { type: "spring", stiffness: 300, damping: 30 }, children: [
|
|
423
|
+
(0, jsx_runtime_1.jsx)("div", { className: "w-full", children: confirmOrderView }, "edit-recipient-view"),
|
|
424
|
+
(0, jsx_runtime_1.jsx)("div", { className: "w-full", children: historyView }, "history-view"),
|
|
425
|
+
(0, jsx_runtime_1.jsx)("div", { className: "w-full", children: orderDetailsView }, "order-details-view"),
|
|
426
|
+
(0, jsx_runtime_1.jsx)("div", { className: "w-full", children: loadingView }, "loading-view"),
|
|
427
|
+
] }), (0, jsx_runtime_1.jsx)(react_1.Dialog, { open: isRecipientModalOpen, onOpenChange: setIsRecipientModalOpen, children: (0, jsx_runtime_1.jsx)(react_1.DialogContent, { className: "w-[420px] max-w-[calc(100vw-32px)] rounded-2xl p-3.5", children: (0, jsx_runtime_1.jsxs)("div", { className: "flex flex-col gap-3", children: [(0, jsx_runtime_1.jsx)("div", { className: "text-as-primary font-semibold", children: "To address" }), (0, jsx_runtime_1.jsx)(react_1.Input, { value: customRecipientAddress || "", onChange: e => setCustomRecipientAddress(e.target.value), placeholder: "Enter address", className: "h-12 rounded-lg", spellCheck: false }), (0, jsx_runtime_1.jsx)(react_1.ShinyButton, { accentColor: "hsl(var(--as-brand))", textColor: "text-white", className: "w-full rounded-lg", onClick: () => {
|
|
428
|
+
setIsRecipientModalOpen(false);
|
|
429
|
+
}, children: "Save" })] }) }) })] }));
|
|
427
430
|
}
|
|
@@ -8,6 +8,7 @@ exports.OrderDetailsLoadingView = exports.OrderDetails = void 0;
|
|
|
8
8
|
const jsx_runtime_1 = require("react/jsx-runtime");
|
|
9
9
|
const anyspend_1 = require("../../../../anyspend");
|
|
10
10
|
const react_1 = require("../../../../global-account/react");
|
|
11
|
+
const hooks_1 = require("../../../../shared/react/hooks");
|
|
11
12
|
const utils_1 = require("../../../../shared/utils");
|
|
12
13
|
const centerTruncate_1 = __importDefault(require("../../../../shared/utils/centerTruncate"));
|
|
13
14
|
const number_1 = require("../../../../shared/utils/number");
|
|
@@ -15,7 +16,6 @@ const react_2 = require("@chakra-ui/react");
|
|
|
15
16
|
const react_3 = require("@web3icons/react");
|
|
16
17
|
const framer_motion_1 = require("framer-motion");
|
|
17
18
|
const lucide_react_1 = require("lucide-react");
|
|
18
|
-
const navigation_1 = require("next/navigation");
|
|
19
19
|
const qrcode_react_1 = require("qrcode.react");
|
|
20
20
|
const react_4 = require("react");
|
|
21
21
|
const react_timeago_1 = __importDefault(require("react-timeago"));
|
|
@@ -121,8 +121,8 @@ function roundTokenAmount(amount) {
|
|
|
121
121
|
return `${wholePart}.${roundedDecimalPart}`;
|
|
122
122
|
}
|
|
123
123
|
exports.OrderDetails = (0, react_4.memo)(function OrderDetails({ isMainnet, mode = "modal", order, depositTxs, relayTx, executeTx, refundTxs, onBack, }) {
|
|
124
|
-
const router = (0,
|
|
125
|
-
const searchParams = (0,
|
|
124
|
+
const router = (0, hooks_1.useRouter)();
|
|
125
|
+
const searchParams = (0, hooks_1.useSearchParams)();
|
|
126
126
|
const setB3ModalOpen = (0, react_1.useModalStore)(state => state.setB3ModalOpen);
|
|
127
127
|
const srcToken = anyspend_1.zToken.parse(order.metadata.srcToken);
|
|
128
128
|
const dstToken = anyspend_1.zToken.parse(order.metadata.dstToken);
|
|
@@ -227,6 +227,25 @@ exports.OrderDetails = (0, react_4.memo)(function OrderDetails({ isMainnet, mode
|
|
|
227
227
|
params.set("waitingForDeposit", "true");
|
|
228
228
|
router.push(`?${params}`);
|
|
229
229
|
}, [router, searchParams]);
|
|
230
|
+
// Clean up URL parameters before closing modal or navigating back
|
|
231
|
+
const cleanupUrlParams = (0, react_4.useCallback)(() => {
|
|
232
|
+
const params = new URLSearchParams(searchParams.toString());
|
|
233
|
+
params.delete("waitingForDeposit");
|
|
234
|
+
params.delete("orderId");
|
|
235
|
+
// Only update URL if params were actually removed
|
|
236
|
+
if (params.toString() !== searchParams.toString()) {
|
|
237
|
+
router.push(`?${params}`);
|
|
238
|
+
}
|
|
239
|
+
}, [router, searchParams]);
|
|
240
|
+
// Helper functions that clean up URL params before executing actions
|
|
241
|
+
const handleCloseModal = (0, react_4.useCallback)(() => {
|
|
242
|
+
cleanupUrlParams();
|
|
243
|
+
setB3ModalOpen(false);
|
|
244
|
+
}, [cleanupUrlParams, setB3ModalOpen]);
|
|
245
|
+
const handleBack = (0, react_4.useCallback)(() => {
|
|
246
|
+
cleanupUrlParams();
|
|
247
|
+
onBack?.();
|
|
248
|
+
}, [cleanupUrlParams, onBack]);
|
|
230
249
|
(0, react_4.useEffect)(() => {
|
|
231
250
|
if (txSuccess) {
|
|
232
251
|
sonner_1.toast.success("Transaction successful! We are processing your order.", { duration: 10000 });
|
|
@@ -279,7 +298,7 @@ exports.OrderDetails = (0, react_4.memo)(function OrderDetails({ isMainnet, mode
|
|
|
279
298
|
: `Received ${(0, number_1.formatTokenAmount)(BigInt(dTx.amount), srcToken.decimals)} ${srcToken.symbol}`, chainId: order.srcChain, tx: dTx, isProcessing: false }, dTx.txHash)))
|
|
280
299
|
: null, refundTxs
|
|
281
300
|
? refundTxs.map(rTx => ((0, jsx_runtime_1.jsx)(TransactionDetails, { title: `Refunded ${(0, number_1.formatTokenAmount)(BigInt(rTx.amount), srcToken.decimals)} ${srcToken.symbol}`, chainId: order.srcChain, tx: rTx, isProcessing: false }, rTx.txHash)))
|
|
282
|
-
: null] }), order.errorDetails && ((0, jsx_runtime_1.jsx)("div", { className: "flex justify-center", children: (0, jsx_runtime_1.jsx)("span", { className: "text-as-primary/50 text-center text-sm", style: { maxWidth: "40ch" }, children: (0, anyspend_1.getErrorDisplay)(order.errorDetails) }) })), (0, jsx_runtime_1.jsx)("button", { className: "bg-as-on-surface-2 text-as-secondary flex w-full items-center justify-center gap-2 rounded-lg p-2", onClick: mode === "page" ?
|
|
301
|
+
: null] }), order.errorDetails && ((0, jsx_runtime_1.jsx)("div", { className: "flex justify-center", children: (0, jsx_runtime_1.jsx)("span", { className: "text-as-primary/50 text-center text-sm", style: { maxWidth: "40ch" }, children: (0, anyspend_1.getErrorDisplay)(order.errorDetails) }) })), (0, jsx_runtime_1.jsx)("button", { className: "bg-as-on-surface-2 text-as-secondary flex w-full items-center justify-center gap-2 rounded-lg p-2", onClick: mode === "page" ? handleBack : handleCloseModal, children: mode === "page" ? ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: ["Return to Home ", (0, jsx_runtime_1.jsx)(lucide_react_1.Home, { className: "ml-2 h-4 w-4" })] })) : ("Close") })] }));
|
|
283
302
|
}
|
|
284
303
|
if (executeTx) {
|
|
285
304
|
return ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsxs)("div", { className: "relative mt-4 flex w-full flex-col gap-4", children: [(0, jsx_runtime_1.jsx)("div", { className: "bg-b3-react-background absolute bottom-2 left-4 top-2 z-[5] w-2", children: (0, jsx_runtime_1.jsx)(framer_motion_1.motion.div, { className: "from-as-brand/50 absolute left-[2px] top-0 z-10 w-[3px] bg-gradient-to-b from-20% via-purple-500/50 via-80% to-transparent", initial: { height: "0%" }, animate: { height: "100%" }, transition: { duration: 1.5, ease: "easeInOut" } }) }), depositTxs
|
|
@@ -301,7 +320,7 @@ exports.OrderDetails = (0, react_4.memo)(function OrderDetails({ isMainnet, mode
|
|
|
301
320
|
dstToken,
|
|
302
321
|
recipientName,
|
|
303
322
|
centerTruncate: centerTruncate_1.default,
|
|
304
|
-
}), (0, jsx_runtime_1.jsx)(lucide_react_1.ExternalLink, { className: "ml-2 h-4 w-4" })] }) }) }), order.type === anyspend_1.OrderType.JoinTournament && order.status === anyspend_1.OrderStatus.Executed && ((0, jsx_runtime_1.jsxs)(react_1.ShinyButton, { accentColor: "hsl(var(--as-brand))", textColor: "text-white", className: "flex w-full items-center gap-2", disabled: txLoading || isSwitchingOrExecuting, onClick:
|
|
323
|
+
}), (0, jsx_runtime_1.jsx)(lucide_react_1.ExternalLink, { className: "ml-2 h-4 w-4" })] }) }) }), order.type === anyspend_1.OrderType.JoinTournament && order.status === anyspend_1.OrderStatus.Executed && ((0, jsx_runtime_1.jsxs)(react_1.ShinyButton, { accentColor: "hsl(var(--as-brand))", textColor: "text-white", className: "flex w-full items-center gap-2", disabled: txLoading || isSwitchingOrExecuting, onClick: handleCloseModal, children: [(0, jsx_runtime_1.jsx)("span", { className: "pl-4", children: "Continue to Tournament" }), (0, jsx_runtime_1.jsx)(lucide_react_1.ChevronRight, { className: "h-4 w-4" })] })), order.status === anyspend_1.OrderStatus.Executed && ((0, jsx_runtime_1.jsx)("button", { className: "bg-as-on-surface-2 text-as-secondary flex w-full items-center justify-center gap-2 rounded-lg p-2", onClick: mode === "page" ? handleBack : handleCloseModal, children: mode === "page" ? ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: ["Return to Home ", (0, jsx_runtime_1.jsx)(lucide_react_1.Home, { className: "ml-2 h-4 w-4" })] })) : ("Close") }))] }));
|
|
305
324
|
}
|
|
306
325
|
if (relayTx && relayTx.status === "success") {
|
|
307
326
|
return ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsxs)("div", { className: "relative mt-4 flex w-full flex-col gap-4", children: [(0, jsx_runtime_1.jsx)("div", { className: "bg-b3-react-background absolute bottom-2 left-4 top-2 z-[5] w-2", children: (0, jsx_runtime_1.jsx)(framer_motion_1.motion.div, { className: "from-as-brand/50 absolute left-[2px] top-0 z-10 w-[3px] bg-gradient-to-b from-20% via-purple-500/50 via-80% to-transparent", initial: { height: "0%" }, animate: { height: "100%" }, transition: { duration: 1.5, ease: "easeInOut" } }) }), depositTxs
|
|
@@ -331,7 +350,7 @@ exports.OrderDetails = (0, react_4.memo)(function OrderDetails({ isMainnet, mode
|
|
|
331
350
|
dstToken,
|
|
332
351
|
recipientName,
|
|
333
352
|
centerTruncate: centerTruncate_1.default,
|
|
334
|
-
}), (0, jsx_runtime_1.jsx)(lucide_react_1.ExternalLink, { className: "ml-2 h-4 w-4" })] }) }) }), order.type === anyspend_1.OrderType.JoinTournament && order.status === anyspend_1.OrderStatus.Executed && ((0, jsx_runtime_1.jsxs)(react_1.ShinyButton, { accentColor: "hsl(var(--as-brand))", textColor: "text-white", className: "flex w-full items-center gap-2", disabled: txLoading || isSwitchingOrExecuting, onClick:
|
|
353
|
+
}), (0, jsx_runtime_1.jsx)(lucide_react_1.ExternalLink, { className: "ml-2 h-4 w-4" })] }) }) }), order.type === anyspend_1.OrderType.JoinTournament && order.status === anyspend_1.OrderStatus.Executed && ((0, jsx_runtime_1.jsxs)(react_1.ShinyButton, { accentColor: "hsl(var(--as-brand))", textColor: "text-white", className: "flex w-full items-center gap-2", disabled: txLoading || isSwitchingOrExecuting, onClick: handleCloseModal, children: [(0, jsx_runtime_1.jsx)("span", { className: "pl-4", children: "Continue to Tournament" }), (0, jsx_runtime_1.jsx)(lucide_react_1.ChevronRight, { className: "h-4 w-4" })] })), order.status === anyspend_1.OrderStatus.Executed && ((0, jsx_runtime_1.jsx)("button", { className: "bg-as-on-surface-2 text-as-secondary flex w-full items-center justify-center gap-2 rounded-lg p-2", onClick: mode === "page" ? handleBack : handleCloseModal, children: mode === "page" ? ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: ["Return to Home ", (0, jsx_runtime_1.jsx)(lucide_react_1.Home, { className: "ml-2 h-4 w-4" })] })) : ("Close") }))] }));
|
|
335
354
|
}
|
|
336
355
|
// This boolean indicates that user finish payment, and waiting for the deposit to be confirmed. We get this from query params (waitingForDeposit=true)
|
|
337
356
|
const waitingForDeposit = new URLSearchParams(window.location.search).get("waitingForDeposit") === "true";
|
|
@@ -381,7 +400,7 @@ exports.OrderDetails = (0, react_4.memo)(function OrderDetails({ isMainnet, mode
|
|
|
381
400
|
: "Contract execution"
|
|
382
401
|
: "" }), (0, jsx_runtime_1.jsxs)("div", { className: "flex items-end gap-2", children: [order.type === anyspend_1.OrderType.Swap ? (`~${formattedExpectedDstAmount} ${dstToken.symbol}`) : order.type === anyspend_1.OrderType.MintNFT ? ((0, jsx_runtime_1.jsxs)("div", { className: "flex items-center gap-2", children: [(0, jsx_runtime_1.jsx)("img", { src: nft?.imageUrl, alt: nft?.name || "NFT", className: "h-5 w-5" }), (0, jsx_runtime_1.jsx)("div", { children: nft?.name || "NFT" })] })) : order.type === anyspend_1.OrderType.JoinTournament || order.type === anyspend_1.OrderType.FundTournament ? ((0, jsx_runtime_1.jsxs)("div", { className: "flex items-center gap-2", children: [(0, jsx_runtime_1.jsx)("img", { src: tournament?.imageUrl, alt: tournament?.name || "Tournament", className: "h-5 w-5" }), (0, jsx_runtime_1.jsx)("div", { children: tournament?.name || "Tournament" })] })) : null, (0, jsx_runtime_1.jsxs)("div", { className: "text-as-primary/50 flex items-center gap-2", children: [(0, jsx_runtime_1.jsxs)("span", { children: ["on ", order.dstChain !== chains_1.b3.id && (0, anyspend_1.getChainName)(order.dstChain)] }), (0, jsx_runtime_1.jsx)("img", { src: anyspend_1.ALL_CHAINS[order.dstChain].logoUrl, alt: (0, anyspend_1.getChainName)(order.dstChain), className: (0, utils_1.cn)("h-3", order.dstChain !== chains_1.b3.id && "w-3 rounded-full", order.dstChain === chains_1.b3.id && "h-4") })] })] })] }), (0, jsx_runtime_1.jsx)("div", { className: "divider w-full" }), (0, jsx_runtime_1.jsxs)("div", { className: "flex w-full justify-between gap-4", children: [(0, jsx_runtime_1.jsx)("div", { className: "text-as-primary/30", children: "Order ID" }), (0, jsx_runtime_1.jsx)("div", { className: "text-as-primary overflow-hidden text-ellipsis whitespace-nowrap", children: order.id })] }), (0, jsx_runtime_1.jsx)("div", { className: "divider w-full" }), (0, jsx_runtime_1.jsxs)("div", { className: "flex w-full justify-between gap-4", children: [(0, jsx_runtime_1.jsx)("div", { className: "text-as-primary/30", children: "Recipient" }), (0, jsx_runtime_1.jsxs)("div", { className: "flex flex-col items-end gap-1", children: [recipientName && (0, jsx_runtime_1.jsx)("div", { className: "text-as-primary font-semibold", children: recipientName }), (0, jsx_runtime_1.jsx)(react_1.CopyToClipboard, { text: order.recipientAddress, onCopy: () => {
|
|
383
402
|
sonner_1.toast.success("Copied recipient address to clipboard");
|
|
384
|
-
}, children: (0, jsx_runtime_1.jsxs)("div", { className: "text-as-primary flex items-center gap-2", children: [(0, centerTruncate_1.default)(order.recipientAddress, 10), (0, jsx_runtime_1.jsx)(lucide_react_1.Copy, { className: "text-as-primary/50 hover:text-as-primary h-4 w-4 cursor-pointer transition-all duration-200" })] }) })] })] })] }) })) : ((0, jsx_runtime_1.jsxs)("div", { className: "flex w-full items-center", children: [(0, jsx_runtime_1.jsx)("div", { className: "divider w-full" }), (0, jsx_runtime_1.jsx)("button", { className: "whitespace-nowrap text-sm", onClick: () => setShowOrderDetails(true), children: "Order Details" }), (0, jsx_runtime_1.jsx)(lucide_react_1.ChevronDown, { className: "text-as-primary mx-1 h-4 min-h-4 w-4 min-w-4" }), (0, jsx_runtime_1.jsx)("div", { className: "divider w-full" })] })), (0, jsx_runtime_1.jsxs)("button", { className: "bg-as-on-surface-2 text-as-secondary flex w-full items-center justify-center gap-2 rounded-lg p-2", onClick:
|
|
403
|
+
}, children: (0, jsx_runtime_1.jsxs)("div", { className: "text-as-primary flex items-center gap-2", children: [(0, centerTruncate_1.default)(order.recipientAddress, 10), (0, jsx_runtime_1.jsx)(lucide_react_1.Copy, { className: "text-as-primary/50 hover:text-as-primary h-4 w-4 cursor-pointer transition-all duration-200" })] }) })] })] })] }) })) : ((0, jsx_runtime_1.jsxs)("div", { className: "flex w-full items-center", children: [(0, jsx_runtime_1.jsx)("div", { className: "divider w-full" }), (0, jsx_runtime_1.jsx)("button", { className: "whitespace-nowrap text-sm", onClick: () => setShowOrderDetails(true), children: "Order Details" }), (0, jsx_runtime_1.jsx)(lucide_react_1.ChevronDown, { className: "text-as-primary mx-1 h-4 min-h-4 w-4 min-w-4" }), (0, jsx_runtime_1.jsx)("div", { className: "divider w-full" })] })), (0, jsx_runtime_1.jsxs)("button", { className: "bg-as-on-surface-2 text-as-secondary flex w-full items-center justify-center gap-2 rounded-lg p-2", onClick: handleBack, children: ["Cancel and start over ", (0, jsx_runtime_1.jsx)(lucide_react_1.RefreshCcw, { className: "ml-2 h-4 w-4" })] })] }));
|
|
385
404
|
});
|
|
386
405
|
function TransactionDetails({ title, chainId, tx, isProcessing, delay, }) {
|
|
387
406
|
return ((0, jsx_runtime_1.jsxs)("div", { className: "relative flex w-full flex-1 items-center justify-between gap-4", children: [(0, jsx_runtime_1.jsxs)("div", { className: "flex grow items-center gap-4", children: [(0, jsx_runtime_1.jsx)(framer_motion_1.motion.div, { className: "bg-b3-react-background relative h-10 w-10 rounded-full", children: isProcessing ? ((0, jsx_runtime_1.jsx)(framer_motion_1.motion.div, { initial: { opacity: 0, scale: 0.3 }, animate: { opacity: 1, scale: 1 }, transition: { duration: 0.5, ease: "easeInOut", delay }, className: "absolute z-10 m-2 flex h-6 w-6 items-center justify-center rounded-full bg-black/70 shadow-lg backdrop-blur-sm", children: (0, jsx_runtime_1.jsx)(lucide_react_1.Loader2, { className: "text-as-primary h-4 w-4 animate-spin" }) })) : ((0, jsx_runtime_1.jsx)(framer_motion_1.motion.div, { initial: { opacity: 0, scale: 0.3 }, animate: { opacity: 1, scale: 1 }, transition: { duration: 0.5, ease: "easeOut", delay }, className: "bg-as-brand/70 absolute z-10 m-2 flex h-6 w-6 items-center justify-center rounded-full border border-white/30 shadow-lg shadow-purple-500/30 backdrop-blur-sm", style: {
|
|
@@ -2,14 +2,14 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.EnterRecipientModal = EnterRecipientModal;
|
|
4
4
|
const jsx_runtime_1 = require("react/jsx-runtime");
|
|
5
|
-
const react_1 = require("react");
|
|
6
|
-
const react_2 = require("
|
|
5
|
+
const react_1 = require("../../../../global-account/react");
|
|
6
|
+
const react_2 = require("react");
|
|
7
7
|
function EnterRecipientModal({ isOpenPasteRecipientAddress, setIsOpenPasteRecipientAddress, recipientAddress, setRecipientAddress, }) {
|
|
8
|
-
const [modalRecipientAddress, setModalRecipientAddress] = (0,
|
|
9
|
-
(0,
|
|
8
|
+
const [modalRecipientAddress, setModalRecipientAddress] = (0, react_2.useState)(recipientAddress || "");
|
|
9
|
+
(0, react_2.useEffect)(() => {
|
|
10
10
|
setModalRecipientAddress(recipientAddress || "");
|
|
11
11
|
}, [recipientAddress]);
|
|
12
|
-
return ((0, jsx_runtime_1.jsx)(
|
|
12
|
+
return ((0, jsx_runtime_1.jsx)(react_1.Dialog, { open: isOpenPasteRecipientAddress, onOpenChange: setIsOpenPasteRecipientAddress, children: (0, jsx_runtime_1.jsx)(react_1.DialogContent, { className: "w-[420px] max-w-[calc(100vw-32px)] rounded-2xl p-3.5", children: (0, jsx_runtime_1.jsxs)("div", { className: "flex flex-col gap-3", children: [(0, jsx_runtime_1.jsx)("div", { className: "text-as-primary font-semibold", children: "To address" }), (0, jsx_runtime_1.jsx)(react_1.Input, { value: modalRecipientAddress, onChange: e => setModalRecipientAddress(e.target.value), placeholder: "Enter address", className: "h-12 rounded-lg", spellCheck: false }), (0, jsx_runtime_1.jsx)(react_1.ShinyButton, { accentColor: "hsl(var(--as-brand))", textColor: "text-white", className: "w-full rounded-lg", onClick: () => {
|
|
13
13
|
setIsOpenPasteRecipientAddress(false);
|
|
14
14
|
setRecipientAddress(modalRecipientAddress);
|
|
15
15
|
}, children: "Save" })] }) }) }));
|
|
@@ -62,9 +62,9 @@ function useAccountWallet() {
|
|
|
62
62
|
smartWalletIcon,
|
|
63
63
|
walletImage,
|
|
64
64
|
]);
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
65
|
+
(0, react_2.useEffect)(() => {
|
|
66
|
+
console.log(`account`, account);
|
|
67
|
+
console.log(`useAccountWallet`, res);
|
|
68
|
+
}, [account, res]);
|
|
69
69
|
return res;
|
|
70
70
|
}
|
|
@@ -4,8 +4,8 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
4
4
|
exports.useTokenFromUrl = useTokenFromUrl;
|
|
5
5
|
exports.useTokenFromAddress = useTokenFromAddress;
|
|
6
6
|
const supported_1 = require("../../../shared/constants/chains/supported");
|
|
7
|
+
const hooks_1 = require("../../../shared/react/hooks");
|
|
7
8
|
const react_query_1 = require("@tanstack/react-query");
|
|
8
|
-
const navigation_1 = require("next/navigation");
|
|
9
9
|
async function fetchTokenInfo(network, address) {
|
|
10
10
|
const response = await fetch("https://api.b3.fun/tokens", {
|
|
11
11
|
method: "POST",
|
|
@@ -28,10 +28,10 @@ async function fetchTokenInfo(network, address) {
|
|
|
28
28
|
* Looks for parameters: [prefix]Currency
|
|
29
29
|
*/
|
|
30
30
|
function useTokenFromUrl({ defaultToken, prefix }) {
|
|
31
|
-
const searchParams = (0,
|
|
31
|
+
const searchParams = (0, hooks_1.useSearchParams)();
|
|
32
32
|
// Get parameters from URL
|
|
33
|
-
const currencyParam = searchParams
|
|
34
|
-
const chainIdParam = searchParams
|
|
33
|
+
const currencyParam = searchParams.get(`${prefix}Currency`);
|
|
34
|
+
const chainIdParam = searchParams.get(`${prefix}ChainId`);
|
|
35
35
|
// Determine if we should fetch token info
|
|
36
36
|
const shouldFetchToken = Boolean(currencyParam && chainIdParam && currencyParam.toLowerCase() !== defaultToken.address.toLowerCase());
|
|
37
37
|
// Determine network based on chainId
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from "./useNavigation";
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
+
};
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
__exportStar(require("./useNavigation"), exports);
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Framework-agnostic hook for reading URL search parameters
|
|
3
|
+
* Works with Next.js, Vite, and other React applications
|
|
4
|
+
*/
|
|
5
|
+
export declare function useSearchParams(): URLSearchParams;
|
|
6
|
+
/**
|
|
7
|
+
* Framework-agnostic navigation utility
|
|
8
|
+
* Works with Next.js, Vite, and other React applications
|
|
9
|
+
*/
|
|
10
|
+
export declare function useRouter(): {
|
|
11
|
+
push: (url: string) => void;
|
|
12
|
+
};
|
|
13
|
+
/**
|
|
14
|
+
* Direct utility function for getting search params without a hook
|
|
15
|
+
* Useful for server-side or one-time usage
|
|
16
|
+
*/
|
|
17
|
+
export declare function getSearchParams(): URLSearchParams | null;
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.useSearchParams = useSearchParams;
|
|
4
|
+
exports.useRouter = useRouter;
|
|
5
|
+
exports.getSearchParams = getSearchParams;
|
|
6
|
+
const react_1 = require("react");
|
|
7
|
+
/**
|
|
8
|
+
* Framework-agnostic hook for reading URL search parameters
|
|
9
|
+
* Works with Next.js, Vite, and other React applications
|
|
10
|
+
*/
|
|
11
|
+
function useSearchParams() {
|
|
12
|
+
const [searchParams, setSearchParams] = (0, react_1.useState)(() => {
|
|
13
|
+
if (typeof window !== "undefined") {
|
|
14
|
+
return new URLSearchParams(window.location.search);
|
|
15
|
+
}
|
|
16
|
+
return new URLSearchParams();
|
|
17
|
+
});
|
|
18
|
+
(0, react_1.useEffect)(() => {
|
|
19
|
+
if (typeof window !== "undefined") {
|
|
20
|
+
const params = new URLSearchParams(window.location.search);
|
|
21
|
+
setSearchParams(params);
|
|
22
|
+
// Listen for URL changes (for client-side routing)
|
|
23
|
+
const handlePopState = () => {
|
|
24
|
+
setSearchParams(new URLSearchParams(window.location.search));
|
|
25
|
+
};
|
|
26
|
+
window.addEventListener("popstate", handlePopState);
|
|
27
|
+
return () => window.removeEventListener("popstate", handlePopState);
|
|
28
|
+
}
|
|
29
|
+
}, []);
|
|
30
|
+
return searchParams;
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Framework-agnostic navigation utility
|
|
34
|
+
* Works with Next.js, Vite, and other React applications
|
|
35
|
+
*/
|
|
36
|
+
function useRouter() {
|
|
37
|
+
const push = (url) => {
|
|
38
|
+
if (typeof window !== "undefined") {
|
|
39
|
+
// For client-side routing frameworks, we should use history.pushState
|
|
40
|
+
// This will work for most SPA frameworks
|
|
41
|
+
window.history.pushState({}, "", url);
|
|
42
|
+
// Dispatch a custom event that components can listen to
|
|
43
|
+
window.dispatchEvent(new PopStateEvent("popstate"));
|
|
44
|
+
}
|
|
45
|
+
};
|
|
46
|
+
return { push };
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Direct utility function for getting search params without a hook
|
|
50
|
+
* Useful for server-side or one-time usage
|
|
51
|
+
*/
|
|
52
|
+
function getSearchParams() {
|
|
53
|
+
if (typeof window !== "undefined") {
|
|
54
|
+
return new URLSearchParams(window.location.search);
|
|
55
|
+
}
|
|
56
|
+
return null;
|
|
57
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from "./hooks";
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
+
};
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
__exportStar(require("./hooks"), exports);
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
2
2
|
import { eqci, getDefaultToken, isCustomTxMetadata, isNftMetadata, isTournamentMetadata, NftType, OrderStatus, OrderType, RELAY_ETH_ADDRESS, USDC_BASE, useAnyspendCreateOnrampOrder, useAnyspendCreateOrder, useAnyspendOrderAndTransactions, useAnyspendQuote, useAnyspendTokenList, useGeoOnrampOptions, } from "../../../anyspend/index.js";
|
|
3
|
-
import { Badge, Button, ShinyButton, Skeleton, StyleRoot, Tabs, TabsContent, TabsList, TabTrigger, TextShimmer, TransitionPanel, useAccountWallet, useB3, useBsmntProfile, useHasMounted, useModalStore, useRouter, useSearchParamsSSR, useTokenBalancesByChain, } from "../../../global-account/react/index.js";
|
|
3
|
+
import { Badge, Button, ShinyButton, Skeleton, StyleRoot, Tabs, TabsContent, TabsList, TabTrigger, TextShimmer, TransitionPanel, useAccountWallet, useB3, useBsmntProfile, useHasMounted, useModalStore, useRouter, useSearchParamsSSR, useTokenBalancesByChain, Dialog, DialogContent, Input, } from "../../../global-account/react/index.js";
|
|
4
4
|
import { cn } from "../../../shared/utils/index.js";
|
|
5
5
|
import centerTruncate from "../../../shared/utils/centerTruncate.js";
|
|
6
6
|
import { formatTokenAmount } from "../../../shared/utils/number.js";
|
|
@@ -89,14 +89,15 @@ export function AnySpendCustom({ isMainnet = true, loadOrder, mode = "modal", re
|
|
|
89
89
|
const [activeTab, setActiveTab] = useState("crypto");
|
|
90
90
|
// Get current user's wallet
|
|
91
91
|
const currentWallet = useAccountWallet();
|
|
92
|
-
|
|
93
|
-
const
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
const
|
|
98
|
-
|
|
99
|
-
|
|
92
|
+
// Add state for recipient modal
|
|
93
|
+
const [isRecipientModalOpen, setIsRecipientModalOpen] = useState(false);
|
|
94
|
+
// Add state for custom recipient
|
|
95
|
+
const [customRecipientAddress, setCustomRecipientAddress] = useState(recipientAddressProps);
|
|
96
|
+
// Update recipient logic to use custom recipient
|
|
97
|
+
const recipientAddress = customRecipientAddress || currentWallet.address;
|
|
98
|
+
const recipientPropsProfile = useBsmntProfile({ address: recipientAddress });
|
|
99
|
+
const recipientEnsName = recipientPropsProfile.data?.username?.replaceAll(".b3.fun", "");
|
|
100
|
+
const recipientImageUrl = recipientPropsProfile.data?.avatar || currentWallet.wallet.meta?.icon;
|
|
100
101
|
const [orderId, setOrderId] = useState(loadOrder);
|
|
101
102
|
const [srcChainId, setSrcChainId] = useState(isMainnet ? base.id : baseSepolia.id);
|
|
102
103
|
// Get token list for token balance check
|
|
@@ -344,7 +345,7 @@ export function AnySpendCustom({ isMainnet = true, loadOrder, mode = "modal", re
|
|
|
344
345
|
? "Receive NFT at"
|
|
345
346
|
: orderType === OrderType.JoinTournament
|
|
346
347
|
? "Join for"
|
|
347
|
-
: "Recipient" }), _jsx("div", { children: _jsxs(Button, { variant: "outline", className: "w-full justify-between border-none p-0", children: [_jsxs("div", { className: "flex items-center gap-2", children: [recipientImageUrl && (_jsx("img", { src: recipientImageUrl, alt: recipientImageUrl, className: "bg-b3-react-foreground size-7 rounded-full object-cover opacity-100" })), _jsxs("div", { className: "flex flex-col items-start gap-1", children: [recipientEnsName && _jsxs("span", { children: ["@", recipientEnsName] }), _jsx("span", { children: centerTruncate(recipientAddress) })] })] }), _jsx(ChevronRightCircle, { className: "ml-2 size-4 shrink-0 opacity-50" })] }) })] })) : null;
|
|
348
|
+
: "Recipient" }), _jsx("div", { children: _jsxs(Button, { variant: "outline", className: "w-full justify-between border-none p-0", onClick: () => setIsRecipientModalOpen(true), children: [_jsxs("div", { className: "flex items-center gap-2", children: [recipientImageUrl && (_jsx("img", { src: recipientImageUrl, alt: recipientImageUrl, className: "bg-b3-react-foreground size-7 rounded-full object-cover opacity-100" })), _jsxs("div", { className: "flex flex-col items-start gap-1", children: [recipientEnsName && _jsxs("span", { children: ["@", recipientEnsName] }), _jsx("span", { children: centerTruncate(recipientAddress) })] })] }), _jsx(ChevronRightCircle, { className: "ml-2 size-4 shrink-0 opacity-50" })] }) })] })) : null;
|
|
348
349
|
const historyView = (_jsx("div", { className: cn("mx-auto flex w-full max-w-2xl flex-col items-center p-5", mode === "modal" && "bg-b3-react-background"), children: _jsx(OrderHistory, { mode: mode, onBack: () => {
|
|
349
350
|
setActivePanel(PanelView.HISTORY);
|
|
350
351
|
}, onSelectOrder: onSelectOrder }) }));
|
|
@@ -402,20 +403,22 @@ export function AnySpendCustom({ isMainnet = true, loadOrder, mode = "modal", re
|
|
|
402
403
|
}
|
|
403
404
|
: undefined, recipientEnsName: recipientEnsName, recipientImageUrl: recipientImageUrl }) }) })] })] }));
|
|
404
405
|
// Return the TransitionPanel with all views
|
|
405
|
-
return (
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
406
|
+
return (_jsxs(StyleRoot, { children: [_jsx(TransitionPanel, { activeIndex: orderId
|
|
407
|
+
? oat
|
|
408
|
+
? PanelView.ORDER_DETAILS
|
|
409
|
+
: PanelView.LOADING
|
|
410
|
+
: activePanel === PanelView.ORDER_DETAILS
|
|
411
|
+
? PanelView.CONFIRM_ORDER
|
|
412
|
+
: activePanel, className: cn("w-full"), variants: {
|
|
413
|
+
enter: { x: 300, opacity: 0 },
|
|
414
|
+
center: { x: 0, opacity: 1 },
|
|
415
|
+
exit: { x: -300, opacity: 0 },
|
|
416
|
+
}, transition: { type: "spring", stiffness: 300, damping: 30 }, children: [
|
|
417
|
+
_jsx("div", { className: "w-full", children: confirmOrderView }, "edit-recipient-view"),
|
|
418
|
+
_jsx("div", { className: "w-full", children: historyView }, "history-view"),
|
|
419
|
+
_jsx("div", { className: "w-full", children: orderDetailsView }, "order-details-view"),
|
|
420
|
+
_jsx("div", { className: "w-full", children: loadingView }, "loading-view"),
|
|
421
|
+
] }), _jsx(Dialog, { open: isRecipientModalOpen, onOpenChange: setIsRecipientModalOpen, children: _jsx(DialogContent, { className: "w-[420px] max-w-[calc(100vw-32px)] rounded-2xl p-3.5", children: _jsxs("div", { className: "flex flex-col gap-3", children: [_jsx("div", { className: "text-as-primary font-semibold", children: "To address" }), _jsx(Input, { value: customRecipientAddress || "", onChange: e => setCustomRecipientAddress(e.target.value), placeholder: "Enter address", className: "h-12 rounded-lg", spellCheck: false }), _jsx(ShinyButton, { accentColor: "hsl(var(--as-brand))", textColor: "text-white", className: "w-full rounded-lg", onClick: () => {
|
|
422
|
+
setIsRecipientModalOpen(false);
|
|
423
|
+
}, children: "Save" })] }) }) })] }));
|
|
421
424
|
}
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
3
3
|
import { ALL_CHAINS, capitalizeFirstLetter, EVM_CHAINS, getChainName, getErrorDisplay, getExplorerTxUrl, getPaymentUrl, getStatusDisplay, isNativeToken, OnrampVendor, OrderStatus, OrderType, RELAY_ETH_ADDRESS, zNft, zToken, zTournament, } from "../../../../anyspend/index.js";
|
|
4
4
|
import { Badge, Button, CopyToClipboard, ShinyButton, Skeleton, TextLoop, TextShimmer, useAccountWallet, useChainSwitchWithAction, useModalStore, useOnchainName, } from "../../../../global-account/react/index.js";
|
|
5
|
+
import { useRouter, useSearchParams } from "../../../../shared/react/hooks/index.js";
|
|
5
6
|
import { cn } from "../../../../shared/utils/index.js";
|
|
6
7
|
import centerTruncate from "../../../../shared/utils/centerTruncate.js";
|
|
7
8
|
import { formatTokenAmount } from "../../../../shared/utils/number.js";
|
|
@@ -9,7 +10,6 @@ import { useColorMode } from "@chakra-ui/react";
|
|
|
9
10
|
import { WalletCoinbase, WalletMetamask, WalletPhantom, WalletTrust, WalletWalletConnect } from "@web3icons/react";
|
|
10
11
|
import { motion } from "framer-motion";
|
|
11
12
|
import { CheckIcon, ChevronDown, ChevronRight, Copy, ExternalLink, Home, Loader2, RefreshCcw, SquareArrowOutUpRight, } from "lucide-react";
|
|
12
|
-
import { useRouter, useSearchParams } from "next/navigation";
|
|
13
13
|
import { QRCodeSVG } from "qrcode.react";
|
|
14
14
|
import { memo, useCallback, useEffect, useMemo, useState } from "react";
|
|
15
15
|
import TimeAgo from "react-timeago";
|
|
@@ -221,6 +221,25 @@ export const OrderDetails = memo(function OrderDetails({ isMainnet, mode = "moda
|
|
|
221
221
|
params.set("waitingForDeposit", "true");
|
|
222
222
|
router.push(`?${params}`);
|
|
223
223
|
}, [router, searchParams]);
|
|
224
|
+
// Clean up URL parameters before closing modal or navigating back
|
|
225
|
+
const cleanupUrlParams = useCallback(() => {
|
|
226
|
+
const params = new URLSearchParams(searchParams.toString());
|
|
227
|
+
params.delete("waitingForDeposit");
|
|
228
|
+
params.delete("orderId");
|
|
229
|
+
// Only update URL if params were actually removed
|
|
230
|
+
if (params.toString() !== searchParams.toString()) {
|
|
231
|
+
router.push(`?${params}`);
|
|
232
|
+
}
|
|
233
|
+
}, [router, searchParams]);
|
|
234
|
+
// Helper functions that clean up URL params before executing actions
|
|
235
|
+
const handleCloseModal = useCallback(() => {
|
|
236
|
+
cleanupUrlParams();
|
|
237
|
+
setB3ModalOpen(false);
|
|
238
|
+
}, [cleanupUrlParams, setB3ModalOpen]);
|
|
239
|
+
const handleBack = useCallback(() => {
|
|
240
|
+
cleanupUrlParams();
|
|
241
|
+
onBack?.();
|
|
242
|
+
}, [cleanupUrlParams, onBack]);
|
|
224
243
|
useEffect(() => {
|
|
225
244
|
if (txSuccess) {
|
|
226
245
|
toast.success("Transaction successful! We are processing your order.", { duration: 10000 });
|
|
@@ -273,7 +292,7 @@ export const OrderDetails = memo(function OrderDetails({ isMainnet, mode = "moda
|
|
|
273
292
|
: `Received ${formatTokenAmount(BigInt(dTx.amount), srcToken.decimals)} ${srcToken.symbol}`, chainId: order.srcChain, tx: dTx, isProcessing: false }, dTx.txHash)))
|
|
274
293
|
: null, refundTxs
|
|
275
294
|
? refundTxs.map(rTx => (_jsx(TransactionDetails, { title: `Refunded ${formatTokenAmount(BigInt(rTx.amount), srcToken.decimals)} ${srcToken.symbol}`, chainId: order.srcChain, tx: rTx, isProcessing: false }, rTx.txHash)))
|
|
276
|
-
: null] }), order.errorDetails && (_jsx("div", { className: "flex justify-center", children: _jsx("span", { className: "text-as-primary/50 text-center text-sm", style: { maxWidth: "40ch" }, children: getErrorDisplay(order.errorDetails) }) })), _jsx("button", { className: "bg-as-on-surface-2 text-as-secondary flex w-full items-center justify-center gap-2 rounded-lg p-2", onClick: mode === "page" ?
|
|
295
|
+
: null] }), order.errorDetails && (_jsx("div", { className: "flex justify-center", children: _jsx("span", { className: "text-as-primary/50 text-center text-sm", style: { maxWidth: "40ch" }, children: getErrorDisplay(order.errorDetails) }) })), _jsx("button", { className: "bg-as-on-surface-2 text-as-secondary flex w-full items-center justify-center gap-2 rounded-lg p-2", onClick: mode === "page" ? handleBack : handleCloseModal, children: mode === "page" ? (_jsxs(_Fragment, { children: ["Return to Home ", _jsx(Home, { className: "ml-2 h-4 w-4" })] })) : ("Close") })] }));
|
|
277
296
|
}
|
|
278
297
|
if (executeTx) {
|
|
279
298
|
return (_jsxs(_Fragment, { children: [_jsxs("div", { className: "relative mt-4 flex w-full flex-col gap-4", children: [_jsx("div", { className: "bg-b3-react-background absolute bottom-2 left-4 top-2 z-[5] w-2", children: _jsx(motion.div, { className: "from-as-brand/50 absolute left-[2px] top-0 z-10 w-[3px] bg-gradient-to-b from-20% via-purple-500/50 via-80% to-transparent", initial: { height: "0%" }, animate: { height: "100%" }, transition: { duration: 1.5, ease: "easeInOut" } }) }), depositTxs
|
|
@@ -295,7 +314,7 @@ export const OrderDetails = memo(function OrderDetails({ isMainnet, mode = "moda
|
|
|
295
314
|
dstToken,
|
|
296
315
|
recipientName,
|
|
297
316
|
centerTruncate,
|
|
298
|
-
}), _jsx(ExternalLink, { className: "ml-2 h-4 w-4" })] }) }) }), order.type === OrderType.JoinTournament && order.status === OrderStatus.Executed && (_jsxs(ShinyButton, { accentColor: "hsl(var(--as-brand))", textColor: "text-white", className: "flex w-full items-center gap-2", disabled: txLoading || isSwitchingOrExecuting, onClick:
|
|
317
|
+
}), _jsx(ExternalLink, { className: "ml-2 h-4 w-4" })] }) }) }), order.type === OrderType.JoinTournament && order.status === OrderStatus.Executed && (_jsxs(ShinyButton, { accentColor: "hsl(var(--as-brand))", textColor: "text-white", className: "flex w-full items-center gap-2", disabled: txLoading || isSwitchingOrExecuting, onClick: handleCloseModal, children: [_jsx("span", { className: "pl-4", children: "Continue to Tournament" }), _jsx(ChevronRight, { className: "h-4 w-4" })] })), order.status === OrderStatus.Executed && (_jsx("button", { className: "bg-as-on-surface-2 text-as-secondary flex w-full items-center justify-center gap-2 rounded-lg p-2", onClick: mode === "page" ? handleBack : handleCloseModal, children: mode === "page" ? (_jsxs(_Fragment, { children: ["Return to Home ", _jsx(Home, { className: "ml-2 h-4 w-4" })] })) : ("Close") }))] }));
|
|
299
318
|
}
|
|
300
319
|
if (relayTx && relayTx.status === "success") {
|
|
301
320
|
return (_jsxs(_Fragment, { children: [_jsxs("div", { className: "relative mt-4 flex w-full flex-col gap-4", children: [_jsx("div", { className: "bg-b3-react-background absolute bottom-2 left-4 top-2 z-[5] w-2", children: _jsx(motion.div, { className: "from-as-brand/50 absolute left-[2px] top-0 z-10 w-[3px] bg-gradient-to-b from-20% via-purple-500/50 via-80% to-transparent", initial: { height: "0%" }, animate: { height: "100%" }, transition: { duration: 1.5, ease: "easeInOut" } }) }), depositTxs
|
|
@@ -325,7 +344,7 @@ export const OrderDetails = memo(function OrderDetails({ isMainnet, mode = "moda
|
|
|
325
344
|
dstToken,
|
|
326
345
|
recipientName,
|
|
327
346
|
centerTruncate,
|
|
328
|
-
}), _jsx(ExternalLink, { className: "ml-2 h-4 w-4" })] }) }) }), order.type === OrderType.JoinTournament && order.status === OrderStatus.Executed && (_jsxs(ShinyButton, { accentColor: "hsl(var(--as-brand))", textColor: "text-white", className: "flex w-full items-center gap-2", disabled: txLoading || isSwitchingOrExecuting, onClick:
|
|
347
|
+
}), _jsx(ExternalLink, { className: "ml-2 h-4 w-4" })] }) }) }), order.type === OrderType.JoinTournament && order.status === OrderStatus.Executed && (_jsxs(ShinyButton, { accentColor: "hsl(var(--as-brand))", textColor: "text-white", className: "flex w-full items-center gap-2", disabled: txLoading || isSwitchingOrExecuting, onClick: handleCloseModal, children: [_jsx("span", { className: "pl-4", children: "Continue to Tournament" }), _jsx(ChevronRight, { className: "h-4 w-4" })] })), order.status === OrderStatus.Executed && (_jsx("button", { className: "bg-as-on-surface-2 text-as-secondary flex w-full items-center justify-center gap-2 rounded-lg p-2", onClick: mode === "page" ? handleBack : handleCloseModal, children: mode === "page" ? (_jsxs(_Fragment, { children: ["Return to Home ", _jsx(Home, { className: "ml-2 h-4 w-4" })] })) : ("Close") }))] }));
|
|
329
348
|
}
|
|
330
349
|
// This boolean indicates that user finish payment, and waiting for the deposit to be confirmed. We get this from query params (waitingForDeposit=true)
|
|
331
350
|
const waitingForDeposit = new URLSearchParams(window.location.search).get("waitingForDeposit") === "true";
|
|
@@ -375,7 +394,7 @@ export const OrderDetails = memo(function OrderDetails({ isMainnet, mode = "moda
|
|
|
375
394
|
: "Contract execution"
|
|
376
395
|
: "" }), _jsxs("div", { className: "flex items-end gap-2", children: [order.type === OrderType.Swap ? (`~${formattedExpectedDstAmount} ${dstToken.symbol}`) : order.type === OrderType.MintNFT ? (_jsxs("div", { className: "flex items-center gap-2", children: [_jsx("img", { src: nft?.imageUrl, alt: nft?.name || "NFT", className: "h-5 w-5" }), _jsx("div", { children: nft?.name || "NFT" })] })) : order.type === OrderType.JoinTournament || order.type === OrderType.FundTournament ? (_jsxs("div", { className: "flex items-center gap-2", children: [_jsx("img", { src: tournament?.imageUrl, alt: tournament?.name || "Tournament", className: "h-5 w-5" }), _jsx("div", { children: tournament?.name || "Tournament" })] })) : null, _jsxs("div", { className: "text-as-primary/50 flex items-center gap-2", children: [_jsxs("span", { children: ["on ", order.dstChain !== b3.id && getChainName(order.dstChain)] }), _jsx("img", { src: ALL_CHAINS[order.dstChain].logoUrl, alt: getChainName(order.dstChain), className: cn("h-3", order.dstChain !== b3.id && "w-3 rounded-full", order.dstChain === b3.id && "h-4") })] })] })] }), _jsx("div", { className: "divider w-full" }), _jsxs("div", { className: "flex w-full justify-between gap-4", children: [_jsx("div", { className: "text-as-primary/30", children: "Order ID" }), _jsx("div", { className: "text-as-primary overflow-hidden text-ellipsis whitespace-nowrap", children: order.id })] }), _jsx("div", { className: "divider w-full" }), _jsxs("div", { className: "flex w-full justify-between gap-4", children: [_jsx("div", { className: "text-as-primary/30", children: "Recipient" }), _jsxs("div", { className: "flex flex-col items-end gap-1", children: [recipientName && _jsx("div", { className: "text-as-primary font-semibold", children: recipientName }), _jsx(CopyToClipboard, { text: order.recipientAddress, onCopy: () => {
|
|
377
396
|
toast.success("Copied recipient address to clipboard");
|
|
378
|
-
}, children: _jsxs("div", { className: "text-as-primary flex items-center gap-2", children: [centerTruncate(order.recipientAddress, 10), _jsx(Copy, { className: "text-as-primary/50 hover:text-as-primary h-4 w-4 cursor-pointer transition-all duration-200" })] }) })] })] })] }) })) : (_jsxs("div", { className: "flex w-full items-center", children: [_jsx("div", { className: "divider w-full" }), _jsx("button", { className: "whitespace-nowrap text-sm", onClick: () => setShowOrderDetails(true), children: "Order Details" }), _jsx(ChevronDown, { className: "text-as-primary mx-1 h-4 min-h-4 w-4 min-w-4" }), _jsx("div", { className: "divider w-full" })] })), _jsxs("button", { className: "bg-as-on-surface-2 text-as-secondary flex w-full items-center justify-center gap-2 rounded-lg p-2", onClick:
|
|
397
|
+
}, children: _jsxs("div", { className: "text-as-primary flex items-center gap-2", children: [centerTruncate(order.recipientAddress, 10), _jsx(Copy, { className: "text-as-primary/50 hover:text-as-primary h-4 w-4 cursor-pointer transition-all duration-200" })] }) })] })] })] }) })) : (_jsxs("div", { className: "flex w-full items-center", children: [_jsx("div", { className: "divider w-full" }), _jsx("button", { className: "whitespace-nowrap text-sm", onClick: () => setShowOrderDetails(true), children: "Order Details" }), _jsx(ChevronDown, { className: "text-as-primary mx-1 h-4 min-h-4 w-4 min-w-4" }), _jsx("div", { className: "divider w-full" })] })), _jsxs("button", { className: "bg-as-on-surface-2 text-as-secondary flex w-full items-center justify-center gap-2 rounded-lg p-2", onClick: handleBack, children: ["Cancel and start over ", _jsx(RefreshCcw, { className: "ml-2 h-4 w-4" })] })] }));
|
|
379
398
|
});
|
|
380
399
|
function TransactionDetails({ title, chainId, tx, isProcessing, delay, }) {
|
|
381
400
|
return (_jsxs("div", { className: "relative flex w-full flex-1 items-center justify-between gap-4", children: [_jsxs("div", { className: "flex grow items-center gap-4", children: [_jsx(motion.div, { className: "bg-b3-react-background relative h-10 w-10 rounded-full", children: isProcessing ? (_jsx(motion.div, { initial: { opacity: 0, scale: 0.3 }, animate: { opacity: 1, scale: 1 }, transition: { duration: 0.5, ease: "easeInOut", delay }, className: "absolute z-10 m-2 flex h-6 w-6 items-center justify-center rounded-full bg-black/70 shadow-lg backdrop-blur-sm", children: _jsx(Loader2, { className: "text-as-primary h-4 w-4 animate-spin" }) })) : (_jsx(motion.div, { initial: { opacity: 0, scale: 0.3 }, animate: { opacity: 1, scale: 1 }, transition: { duration: 0.5, ease: "easeOut", delay }, className: "bg-as-brand/70 absolute z-10 m-2 flex h-6 w-6 items-center justify-center rounded-full border border-white/30 shadow-lg shadow-purple-500/30 backdrop-blur-sm", style: {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
-
import { useEffect, useState } from "react";
|
|
3
2
|
import { Dialog, DialogContent, Input, ShinyButton } from "../../../../global-account/react/index.js";
|
|
3
|
+
import { useEffect, useState } from "react";
|
|
4
4
|
export function EnterRecipientModal({ isOpenPasteRecipientAddress, setIsOpenPasteRecipientAddress, recipientAddress, setRecipientAddress, }) {
|
|
5
5
|
const [modalRecipientAddress, setModalRecipientAddress] = useState(recipientAddress || "");
|
|
6
6
|
useEffect(() => {
|
|
@@ -59,9 +59,9 @@ export function useAccountWallet() {
|
|
|
59
59
|
smartWalletIcon,
|
|
60
60
|
walletImage,
|
|
61
61
|
]);
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
62
|
+
useEffect(() => {
|
|
63
|
+
console.log(`account`, account);
|
|
64
|
+
console.log(`useAccountWallet`, res);
|
|
65
|
+
}, [account, res]);
|
|
66
66
|
return res;
|
|
67
67
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { getCoingeckoChainInfo } from "../../../shared/constants/chains/supported.js";
|
|
3
|
+
import { useSearchParams } from "../../../shared/react/hooks/index.js";
|
|
3
4
|
import { useQuery } from "@tanstack/react-query";
|
|
4
|
-
import { useSearchParams } from "next/navigation";
|
|
5
5
|
async function fetchTokenInfo(network, address) {
|
|
6
6
|
const response = await fetch("https://api.b3.fun/tokens", {
|
|
7
7
|
method: "POST",
|
|
@@ -26,8 +26,8 @@ async function fetchTokenInfo(network, address) {
|
|
|
26
26
|
export function useTokenFromUrl({ defaultToken, prefix }) {
|
|
27
27
|
const searchParams = useSearchParams();
|
|
28
28
|
// Get parameters from URL
|
|
29
|
-
const currencyParam = searchParams
|
|
30
|
-
const chainIdParam = searchParams
|
|
29
|
+
const currencyParam = searchParams.get(`${prefix}Currency`);
|
|
30
|
+
const chainIdParam = searchParams.get(`${prefix}ChainId`);
|
|
31
31
|
// Determine if we should fetch token info
|
|
32
32
|
const shouldFetchToken = Boolean(currencyParam && chainIdParam && currencyParam.toLowerCase() !== defaultToken.address.toLowerCase());
|
|
33
33
|
// Determine network based on chainId
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from "./useNavigation";
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from "./useNavigation.js";
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Framework-agnostic hook for reading URL search parameters
|
|
3
|
+
* Works with Next.js, Vite, and other React applications
|
|
4
|
+
*/
|
|
5
|
+
export declare function useSearchParams(): URLSearchParams;
|
|
6
|
+
/**
|
|
7
|
+
* Framework-agnostic navigation utility
|
|
8
|
+
* Works with Next.js, Vite, and other React applications
|
|
9
|
+
*/
|
|
10
|
+
export declare function useRouter(): {
|
|
11
|
+
push: (url: string) => void;
|
|
12
|
+
};
|
|
13
|
+
/**
|
|
14
|
+
* Direct utility function for getting search params without a hook
|
|
15
|
+
* Useful for server-side or one-time usage
|
|
16
|
+
*/
|
|
17
|
+
export declare function getSearchParams(): URLSearchParams | null;
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { useEffect, useState } from "react";
|
|
2
|
+
/**
|
|
3
|
+
* Framework-agnostic hook for reading URL search parameters
|
|
4
|
+
* Works with Next.js, Vite, and other React applications
|
|
5
|
+
*/
|
|
6
|
+
export function useSearchParams() {
|
|
7
|
+
const [searchParams, setSearchParams] = useState(() => {
|
|
8
|
+
if (typeof window !== "undefined") {
|
|
9
|
+
return new URLSearchParams(window.location.search);
|
|
10
|
+
}
|
|
11
|
+
return new URLSearchParams();
|
|
12
|
+
});
|
|
13
|
+
useEffect(() => {
|
|
14
|
+
if (typeof window !== "undefined") {
|
|
15
|
+
const params = new URLSearchParams(window.location.search);
|
|
16
|
+
setSearchParams(params);
|
|
17
|
+
// Listen for URL changes (for client-side routing)
|
|
18
|
+
const handlePopState = () => {
|
|
19
|
+
setSearchParams(new URLSearchParams(window.location.search));
|
|
20
|
+
};
|
|
21
|
+
window.addEventListener("popstate", handlePopState);
|
|
22
|
+
return () => window.removeEventListener("popstate", handlePopState);
|
|
23
|
+
}
|
|
24
|
+
}, []);
|
|
25
|
+
return searchParams;
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Framework-agnostic navigation utility
|
|
29
|
+
* Works with Next.js, Vite, and other React applications
|
|
30
|
+
*/
|
|
31
|
+
export function useRouter() {
|
|
32
|
+
const push = (url) => {
|
|
33
|
+
if (typeof window !== "undefined") {
|
|
34
|
+
// For client-side routing frameworks, we should use history.pushState
|
|
35
|
+
// This will work for most SPA frameworks
|
|
36
|
+
window.history.pushState({}, "", url);
|
|
37
|
+
// Dispatch a custom event that components can listen to
|
|
38
|
+
window.dispatchEvent(new PopStateEvent("popstate"));
|
|
39
|
+
}
|
|
40
|
+
};
|
|
41
|
+
return { push };
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Direct utility function for getting search params without a hook
|
|
45
|
+
* Useful for server-side or one-time usage
|
|
46
|
+
*/
|
|
47
|
+
export function getSearchParams() {
|
|
48
|
+
if (typeof window !== "undefined") {
|
|
49
|
+
return new URLSearchParams(window.location.search);
|
|
50
|
+
}
|
|
51
|
+
return null;
|
|
52
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from "./hooks";
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from "./hooks/index.js";
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from "./useNavigation";
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Framework-agnostic hook for reading URL search parameters
|
|
3
|
+
* Works with Next.js, Vite, and other React applications
|
|
4
|
+
*/
|
|
5
|
+
export declare function useSearchParams(): URLSearchParams;
|
|
6
|
+
/**
|
|
7
|
+
* Framework-agnostic navigation utility
|
|
8
|
+
* Works with Next.js, Vite, and other React applications
|
|
9
|
+
*/
|
|
10
|
+
export declare function useRouter(): {
|
|
11
|
+
push: (url: string) => void;
|
|
12
|
+
};
|
|
13
|
+
/**
|
|
14
|
+
* Direct utility function for getting search params without a hook
|
|
15
|
+
* Useful for server-side or one-time usage
|
|
16
|
+
*/
|
|
17
|
+
export declare function getSearchParams(): URLSearchParams | null;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from "./hooks";
|
package/package.json
CHANGED
|
@@ -43,6 +43,9 @@ import {
|
|
|
43
43
|
useRouter,
|
|
44
44
|
useSearchParamsSSR,
|
|
45
45
|
useTokenBalancesByChain,
|
|
46
|
+
Dialog,
|
|
47
|
+
DialogContent,
|
|
48
|
+
Input,
|
|
46
49
|
} from "@b3dotfun/sdk/global-account/react";
|
|
47
50
|
import { cn } from "@b3dotfun/sdk/shared/utils";
|
|
48
51
|
import centerTruncate from "@b3dotfun/sdk/shared/utils/centerTruncate";
|
|
@@ -203,15 +206,17 @@ export function AnySpendCustom({
|
|
|
203
206
|
// Get current user's wallet
|
|
204
207
|
const currentWallet = useAccountWallet();
|
|
205
208
|
|
|
206
|
-
|
|
209
|
+
// Add state for recipient modal
|
|
210
|
+
const [isRecipientModalOpen, setIsRecipientModalOpen] = useState(false);
|
|
207
211
|
|
|
208
|
-
|
|
209
|
-
const
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
const
|
|
213
|
-
|
|
214
|
-
|
|
212
|
+
// Add state for custom recipient
|
|
213
|
+
const [customRecipientAddress, setCustomRecipientAddress] = useState<string | undefined>(recipientAddressProps);
|
|
214
|
+
|
|
215
|
+
// Update recipient logic to use custom recipient
|
|
216
|
+
const recipientAddress = customRecipientAddress || currentWallet.address;
|
|
217
|
+
const recipientPropsProfile = useBsmntProfile({ address: recipientAddress });
|
|
218
|
+
const recipientEnsName = recipientPropsProfile.data?.username?.replaceAll(".b3.fun", "");
|
|
219
|
+
const recipientImageUrl = recipientPropsProfile.data?.avatar || currentWallet.wallet.meta?.icon;
|
|
215
220
|
|
|
216
221
|
const [orderId, setOrderId] = useState<string | undefined>(loadOrder);
|
|
217
222
|
|
|
@@ -505,7 +510,11 @@ export function AnySpendCustom({
|
|
|
505
510
|
: "Recipient"}
|
|
506
511
|
</div>
|
|
507
512
|
<div>
|
|
508
|
-
<Button
|
|
513
|
+
<Button
|
|
514
|
+
variant="outline"
|
|
515
|
+
className="w-full justify-between border-none p-0"
|
|
516
|
+
onClick={() => setIsRecipientModalOpen(true)}
|
|
517
|
+
>
|
|
509
518
|
<div className="flex items-center gap-2">
|
|
510
519
|
{recipientImageUrl && (
|
|
511
520
|
<img
|
|
@@ -864,6 +873,32 @@ export function AnySpendCustom({
|
|
|
864
873
|
</div>,
|
|
865
874
|
]}
|
|
866
875
|
</TransitionPanel>
|
|
876
|
+
|
|
877
|
+
{/* Add EnterRecipientModal */}
|
|
878
|
+
<Dialog open={isRecipientModalOpen} onOpenChange={setIsRecipientModalOpen}>
|
|
879
|
+
<DialogContent className="w-[420px] max-w-[calc(100vw-32px)] rounded-2xl p-3.5">
|
|
880
|
+
<div className="flex flex-col gap-3">
|
|
881
|
+
<div className="text-as-primary font-semibold">To address</div>
|
|
882
|
+
<Input
|
|
883
|
+
value={customRecipientAddress || ""}
|
|
884
|
+
onChange={e => setCustomRecipientAddress(e.target.value)}
|
|
885
|
+
placeholder="Enter address"
|
|
886
|
+
className="h-12 rounded-lg"
|
|
887
|
+
spellCheck={false}
|
|
888
|
+
/>
|
|
889
|
+
<ShinyButton
|
|
890
|
+
accentColor={"hsl(var(--as-brand))"}
|
|
891
|
+
textColor="text-white"
|
|
892
|
+
className="w-full rounded-lg"
|
|
893
|
+
onClick={() => {
|
|
894
|
+
setIsRecipientModalOpen(false);
|
|
895
|
+
}}
|
|
896
|
+
>
|
|
897
|
+
Save
|
|
898
|
+
</ShinyButton>
|
|
899
|
+
</div>
|
|
900
|
+
</DialogContent>
|
|
901
|
+
</Dialog>
|
|
867
902
|
</StyleRoot>
|
|
868
903
|
);
|
|
869
904
|
}
|
|
@@ -36,6 +36,7 @@ import {
|
|
|
36
36
|
useModalStore,
|
|
37
37
|
useOnchainName,
|
|
38
38
|
} from "@b3dotfun/sdk/global-account/react";
|
|
39
|
+
import { useRouter, useSearchParams } from "@b3dotfun/sdk/shared/react/hooks";
|
|
39
40
|
import { cn } from "@b3dotfun/sdk/shared/utils";
|
|
40
41
|
import centerTruncate from "@b3dotfun/sdk/shared/utils/centerTruncate";
|
|
41
42
|
import { formatTokenAmount } from "@b3dotfun/sdk/shared/utils/number";
|
|
@@ -53,7 +54,6 @@ import {
|
|
|
53
54
|
RefreshCcw,
|
|
54
55
|
SquareArrowOutUpRight,
|
|
55
56
|
} from "lucide-react";
|
|
56
|
-
import { useRouter, useSearchParams } from "next/navigation";
|
|
57
57
|
import { QRCodeSVG } from "qrcode.react";
|
|
58
58
|
import { memo, useCallback, useEffect, useMemo, useState } from "react";
|
|
59
59
|
import TimeAgo from "react-timeago";
|
|
@@ -340,6 +340,29 @@ export const OrderDetails = memo(function OrderDetails({
|
|
|
340
340
|
router.push(`?${params}`);
|
|
341
341
|
}, [router, searchParams]);
|
|
342
342
|
|
|
343
|
+
// Clean up URL parameters before closing modal or navigating back
|
|
344
|
+
const cleanupUrlParams = useCallback(() => {
|
|
345
|
+
const params = new URLSearchParams(searchParams.toString());
|
|
346
|
+
params.delete("waitingForDeposit");
|
|
347
|
+
params.delete("orderId");
|
|
348
|
+
|
|
349
|
+
// Only update URL if params were actually removed
|
|
350
|
+
if (params.toString() !== searchParams.toString()) {
|
|
351
|
+
router.push(`?${params}`);
|
|
352
|
+
}
|
|
353
|
+
}, [router, searchParams]);
|
|
354
|
+
|
|
355
|
+
// Helper functions that clean up URL params before executing actions
|
|
356
|
+
const handleCloseModal = useCallback(() => {
|
|
357
|
+
cleanupUrlParams();
|
|
358
|
+
setB3ModalOpen(false);
|
|
359
|
+
}, [cleanupUrlParams, setB3ModalOpen]);
|
|
360
|
+
|
|
361
|
+
const handleBack = useCallback(() => {
|
|
362
|
+
cleanupUrlParams();
|
|
363
|
+
onBack?.();
|
|
364
|
+
}, [cleanupUrlParams, onBack]);
|
|
365
|
+
|
|
343
366
|
useEffect(() => {
|
|
344
367
|
if (txSuccess) {
|
|
345
368
|
toast.success("Transaction successful! We are processing your order.", { duration: 10000 });
|
|
@@ -446,7 +469,7 @@ export const OrderDetails = memo(function OrderDetails({
|
|
|
446
469
|
)}
|
|
447
470
|
<button
|
|
448
471
|
className="bg-as-on-surface-2 text-as-secondary flex w-full items-center justify-center gap-2 rounded-lg p-2"
|
|
449
|
-
onClick={mode === "page" ?
|
|
472
|
+
onClick={mode === "page" ? handleBack : handleCloseModal}
|
|
450
473
|
>
|
|
451
474
|
{mode === "page" ? (
|
|
452
475
|
<>
|
|
@@ -539,7 +562,7 @@ export const OrderDetails = memo(function OrderDetails({
|
|
|
539
562
|
textColor="text-white"
|
|
540
563
|
className="flex w-full items-center gap-2"
|
|
541
564
|
disabled={txLoading || isSwitchingOrExecuting}
|
|
542
|
-
onClick={
|
|
565
|
+
onClick={handleCloseModal}
|
|
543
566
|
>
|
|
544
567
|
<span className="pl-4">Continue to Tournament</span>
|
|
545
568
|
<ChevronRight className="h-4 w-4" />
|
|
@@ -549,7 +572,7 @@ export const OrderDetails = memo(function OrderDetails({
|
|
|
549
572
|
{order.status === OrderStatus.Executed && (
|
|
550
573
|
<button
|
|
551
574
|
className="bg-as-on-surface-2 text-as-secondary flex w-full items-center justify-center gap-2 rounded-lg p-2"
|
|
552
|
-
onClick={mode === "page" ?
|
|
575
|
+
onClick={mode === "page" ? handleBack : handleCloseModal}
|
|
553
576
|
>
|
|
554
577
|
{mode === "page" ? (
|
|
555
578
|
<>
|
|
@@ -667,7 +690,7 @@ export const OrderDetails = memo(function OrderDetails({
|
|
|
667
690
|
textColor="text-white"
|
|
668
691
|
className="flex w-full items-center gap-2"
|
|
669
692
|
disabled={txLoading || isSwitchingOrExecuting}
|
|
670
|
-
onClick={
|
|
693
|
+
onClick={handleCloseModal}
|
|
671
694
|
>
|
|
672
695
|
<span className="pl-4">Continue to Tournament</span>
|
|
673
696
|
<ChevronRight className="h-4 w-4" />
|
|
@@ -677,7 +700,7 @@ export const OrderDetails = memo(function OrderDetails({
|
|
|
677
700
|
{order.status === OrderStatus.Executed && (
|
|
678
701
|
<button
|
|
679
702
|
className="bg-as-on-surface-2 text-as-secondary flex w-full items-center justify-center gap-2 rounded-lg p-2"
|
|
680
|
-
onClick={mode === "page" ?
|
|
703
|
+
onClick={mode === "page" ? handleBack : handleCloseModal}
|
|
681
704
|
>
|
|
682
705
|
{mode === "page" ? (
|
|
683
706
|
<>
|
|
@@ -1075,7 +1098,7 @@ export const OrderDetails = memo(function OrderDetails({
|
|
|
1075
1098
|
|
|
1076
1099
|
<button
|
|
1077
1100
|
className="bg-as-on-surface-2 text-as-secondary flex w-full items-center justify-center gap-2 rounded-lg p-2"
|
|
1078
|
-
onClick={
|
|
1101
|
+
onClick={handleBack}
|
|
1079
1102
|
>
|
|
1080
1103
|
Cancel and start over <RefreshCcw className="ml-2 h-4 w-4" />
|
|
1081
1104
|
</button>
|
|
@@ -101,10 +101,10 @@ export function useAccountWallet(): {
|
|
|
101
101
|
],
|
|
102
102
|
);
|
|
103
103
|
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
104
|
+
useEffect(() => {
|
|
105
|
+
console.log(`account`, account);
|
|
106
|
+
console.log(`useAccountWallet`, res);
|
|
107
|
+
}, [account, res]);
|
|
108
108
|
|
|
109
109
|
return res;
|
|
110
110
|
}
|
|
@@ -2,8 +2,8 @@
|
|
|
2
2
|
|
|
3
3
|
import { Token } from "@b3dotfun/sdk/anyspend";
|
|
4
4
|
import { getCoingeckoChainInfo } from "@b3dotfun/sdk/shared/constants/chains/supported";
|
|
5
|
+
import { useSearchParams } from "@b3dotfun/sdk/shared/react/hooks";
|
|
5
6
|
import { useQuery } from "@tanstack/react-query";
|
|
6
|
-
import { useSearchParams } from "next/navigation";
|
|
7
7
|
|
|
8
8
|
interface UseTokenFromUrlOptions {
|
|
9
9
|
/**
|
|
@@ -56,8 +56,8 @@ export function useTokenFromUrl({ defaultToken, prefix }: UseTokenFromUrlOptions
|
|
|
56
56
|
const searchParams = useSearchParams();
|
|
57
57
|
|
|
58
58
|
// Get parameters from URL
|
|
59
|
-
const currencyParam = searchParams
|
|
60
|
-
const chainIdParam = searchParams
|
|
59
|
+
const currencyParam = searchParams.get(`${prefix}Currency`);
|
|
60
|
+
const chainIdParam = searchParams.get(`${prefix}ChainId`);
|
|
61
61
|
|
|
62
62
|
// Determine if we should fetch token info
|
|
63
63
|
const shouldFetchToken = Boolean(
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from "./useNavigation";
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { useEffect, useState } from "react";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Framework-agnostic hook for reading URL search parameters
|
|
5
|
+
* Works with Next.js, Vite, and other React applications
|
|
6
|
+
*/
|
|
7
|
+
export function useSearchParams() {
|
|
8
|
+
const [searchParams, setSearchParams] = useState<URLSearchParams>(() => {
|
|
9
|
+
if (typeof window !== "undefined") {
|
|
10
|
+
return new URLSearchParams(window.location.search);
|
|
11
|
+
}
|
|
12
|
+
return new URLSearchParams();
|
|
13
|
+
});
|
|
14
|
+
|
|
15
|
+
useEffect(() => {
|
|
16
|
+
if (typeof window !== "undefined") {
|
|
17
|
+
const params = new URLSearchParams(window.location.search);
|
|
18
|
+
setSearchParams(params);
|
|
19
|
+
|
|
20
|
+
// Listen for URL changes (for client-side routing)
|
|
21
|
+
const handlePopState = () => {
|
|
22
|
+
setSearchParams(new URLSearchParams(window.location.search));
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
window.addEventListener("popstate", handlePopState);
|
|
26
|
+
return () => window.removeEventListener("popstate", handlePopState);
|
|
27
|
+
}
|
|
28
|
+
}, []);
|
|
29
|
+
|
|
30
|
+
return searchParams;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Framework-agnostic navigation utility
|
|
35
|
+
* Works with Next.js, Vite, and other React applications
|
|
36
|
+
*/
|
|
37
|
+
export function useRouter() {
|
|
38
|
+
const push = (url: string) => {
|
|
39
|
+
if (typeof window !== "undefined") {
|
|
40
|
+
// For client-side routing frameworks, we should use history.pushState
|
|
41
|
+
// This will work for most SPA frameworks
|
|
42
|
+
window.history.pushState({}, "", url);
|
|
43
|
+
|
|
44
|
+
// Dispatch a custom event that components can listen to
|
|
45
|
+
window.dispatchEvent(new PopStateEvent("popstate"));
|
|
46
|
+
}
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
return { push };
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* Direct utility function for getting search params without a hook
|
|
54
|
+
* Useful for server-side or one-time usage
|
|
55
|
+
*/
|
|
56
|
+
export function getSearchParams(): URLSearchParams | null {
|
|
57
|
+
if (typeof window !== "undefined") {
|
|
58
|
+
return new URLSearchParams(window.location.search);
|
|
59
|
+
}
|
|
60
|
+
return null;
|
|
61
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from "./hooks";
|