@b3dotfun/sdk 0.0.87-alpha.0 → 0.0.87-alpha.2
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/AnySpend.d.ts +5 -0
- package/dist/cjs/anyspend/react/components/AnySpend.js +77 -73
- package/dist/cjs/anyspend/react/components/AnySpendCustomExactIn.d.ts +1 -1
- package/dist/cjs/anyspend/react/components/AnySpendCustomExactIn.js +1 -2
- package/dist/cjs/anyspend/react/components/AnySpendDeposit.d.ts +122 -0
- package/dist/cjs/anyspend/react/components/AnySpendDeposit.js +190 -0
- package/dist/cjs/anyspend/react/components/QRDeposit.d.ts +43 -0
- package/dist/cjs/anyspend/react/components/QRDeposit.js +146 -0
- package/dist/cjs/anyspend/react/components/common/OrderDetails.js +17 -12
- package/dist/cjs/anyspend/react/components/common/OrderDetailsCollapsible.d.ts +2 -0
- package/dist/cjs/anyspend/react/components/common/OrderDetailsCollapsible.js +12 -5
- package/dist/cjs/anyspend/react/components/common/OrderStatus.js +2 -2
- package/dist/cjs/anyspend/react/components/common/WarningText.d.ts +32 -0
- package/dist/cjs/anyspend/react/components/common/WarningText.js +36 -0
- package/dist/cjs/anyspend/react/components/icons/CreditCardIcon.d.ts +6 -0
- package/dist/cjs/anyspend/react/components/icons/CreditCardIcon.js +6 -0
- package/dist/cjs/anyspend/react/components/icons/QrCodeIcon.d.ts +6 -0
- package/dist/cjs/anyspend/react/components/icons/QrCodeIcon.js +6 -0
- package/dist/cjs/anyspend/react/components/index.d.ts +2 -0
- package/dist/cjs/anyspend/react/components/index.js +3 -1
- package/dist/cjs/anyspend/react/hooks/index.d.ts +1 -0
- package/dist/cjs/anyspend/react/hooks/index.js +1 -0
- package/dist/cjs/anyspend/react/hooks/useAnyspendFlow.d.ts +2 -2
- package/dist/cjs/anyspend/react/hooks/useAnyspendFlow.js +35 -11
- package/dist/cjs/anyspend/react/hooks/useCreateDepositFirstOrder.d.ts +24 -0
- package/dist/cjs/anyspend/react/hooks/useCreateDepositFirstOrder.js +86 -0
- package/dist/cjs/anyspend/utils/format.js +28 -5
- package/dist/cjs/global-account/react/stores/useModalStore.d.ts +4 -0
- package/dist/esm/anyspend/react/components/AnySpend.d.ts +5 -0
- package/dist/esm/anyspend/react/components/AnySpend.js +77 -73
- package/dist/esm/anyspend/react/components/AnySpendCustomExactIn.d.ts +1 -1
- package/dist/esm/anyspend/react/components/AnySpendCustomExactIn.js +1 -2
- package/dist/esm/anyspend/react/components/AnySpendDeposit.d.ts +122 -0
- package/dist/esm/anyspend/react/components/AnySpendDeposit.js +187 -0
- package/dist/esm/anyspend/react/components/QRDeposit.d.ts +43 -0
- package/dist/esm/anyspend/react/components/QRDeposit.js +143 -0
- package/dist/esm/anyspend/react/components/common/OrderDetails.js +17 -12
- package/dist/esm/anyspend/react/components/common/OrderDetailsCollapsible.d.ts +2 -0
- package/dist/esm/anyspend/react/components/common/OrderDetailsCollapsible.js +12 -5
- package/dist/esm/anyspend/react/components/common/OrderStatus.js +2 -2
- package/dist/esm/anyspend/react/components/common/WarningText.d.ts +32 -0
- package/dist/esm/anyspend/react/components/common/WarningText.js +32 -0
- package/dist/esm/anyspend/react/components/icons/CreditCardIcon.d.ts +6 -0
- package/dist/esm/anyspend/react/components/icons/CreditCardIcon.js +2 -0
- package/dist/esm/anyspend/react/components/icons/QrCodeIcon.d.ts +6 -0
- package/dist/esm/anyspend/react/components/icons/QrCodeIcon.js +2 -0
- package/dist/esm/anyspend/react/components/index.d.ts +2 -0
- package/dist/esm/anyspend/react/components/index.js +1 -0
- package/dist/esm/anyspend/react/hooks/index.d.ts +1 -0
- package/dist/esm/anyspend/react/hooks/index.js +1 -0
- package/dist/esm/anyspend/react/hooks/useAnyspendFlow.d.ts +2 -2
- package/dist/esm/anyspend/react/hooks/useAnyspendFlow.js +35 -11
- package/dist/esm/anyspend/react/hooks/useCreateDepositFirstOrder.d.ts +24 -0
- package/dist/esm/anyspend/react/hooks/useCreateDepositFirstOrder.js +83 -0
- package/dist/esm/anyspend/utils/format.js +28 -5
- package/dist/esm/global-account/react/stores/useModalStore.d.ts +4 -0
- package/dist/styles/index.css +1 -1
- package/dist/types/anyspend/react/components/AnySpend.d.ts +5 -0
- package/dist/types/anyspend/react/components/AnySpendCustomExactIn.d.ts +1 -1
- package/dist/types/anyspend/react/components/AnySpendDeposit.d.ts +122 -0
- package/dist/types/anyspend/react/components/QRDeposit.d.ts +43 -0
- package/dist/types/anyspend/react/components/common/OrderDetailsCollapsible.d.ts +2 -0
- package/dist/types/anyspend/react/components/common/WarningText.d.ts +32 -0
- package/dist/types/anyspend/react/components/icons/CreditCardIcon.d.ts +6 -0
- package/dist/types/anyspend/react/components/icons/QrCodeIcon.d.ts +6 -0
- package/dist/types/anyspend/react/components/index.d.ts +2 -0
- package/dist/types/anyspend/react/hooks/index.d.ts +1 -0
- package/dist/types/anyspend/react/hooks/useAnyspendFlow.d.ts +2 -2
- package/dist/types/anyspend/react/hooks/useCreateDepositFirstOrder.d.ts +24 -0
- package/dist/types/global-account/react/stores/useModalStore.d.ts +4 -0
- package/package.json +1 -1
- package/src/anyspend/react/components/AnySpend.tsx +105 -85
- package/src/anyspend/react/components/AnySpendCustomExactIn.tsx +2 -3
- package/src/anyspend/react/components/AnySpendDeposit.tsx +578 -0
- package/src/anyspend/react/components/QRDeposit.tsx +348 -0
- package/src/anyspend/react/components/common/OrderDetails.tsx +26 -8
- package/src/anyspend/react/components/common/OrderDetailsCollapsible.tsx +20 -8
- package/src/anyspend/react/components/common/OrderStatus.tsx +2 -2
- package/src/anyspend/react/components/common/WarningText.tsx +52 -0
- package/src/anyspend/react/components/icons/CreditCardIcon.tsx +25 -0
- package/src/anyspend/react/components/icons/QrCodeIcon.tsx +25 -0
- package/src/anyspend/react/components/icons/credit-card.svg +5 -0
- package/src/anyspend/react/components/icons/qr-code.svg +5 -0
- package/src/anyspend/react/components/index.ts +2 -0
- package/src/anyspend/react/hooks/index.ts +1 -0
- package/src/anyspend/react/hooks/useAnyspendFlow.ts +37 -12
- package/src/anyspend/react/hooks/useCreateDepositFirstOrder.ts +110 -0
- package/src/anyspend/utils/format.ts +33 -5
- package/src/global-account/react/stores/useModalStore.ts +4 -0
- package/src/styles/index.css +2 -0
|
@@ -50,7 +50,7 @@ export function AnySpend(props) {
|
|
|
50
50
|
const fingerprintConfig = getFingerprintConfig();
|
|
51
51
|
return (_jsx(AnySpendFingerprintWrapper, { fingerprint: fingerprintConfig, children: _jsx(AnySpendInner, { ...props }) }));
|
|
52
52
|
}
|
|
53
|
-
function AnySpendInner({ destinationTokenAddress, destinationTokenChainId, mode = "modal", defaultActiveTab = "crypto", loadOrder, hideTransactionHistoryButton, recipientAddress: recipientAddressFromProps, onTokenSelect, onSuccess, customUsdInputValues, }) {
|
|
53
|
+
function AnySpendInner({ sourceChainId, destinationTokenAddress, destinationTokenChainId, mode = "modal", defaultActiveTab = "crypto", loadOrder, hideTransactionHistoryButton, recipientAddress: recipientAddressFromProps, onTokenSelect, onSuccess, customUsdInputValues, hideHeader, hideBottomNavigation = false, disableUrlParamManagement = false, }) {
|
|
54
54
|
const searchParams = useSearchParamsSSR();
|
|
55
55
|
const router = useRouter();
|
|
56
56
|
const { partnerId } = useB3();
|
|
@@ -90,7 +90,7 @@ function AnySpendInner({ destinationTokenAddress, destinationTokenChainId, mode
|
|
|
90
90
|
// const [newRecipientAddress, setNewRecipientAddress] = useState("");
|
|
91
91
|
// const recipientInputRef = useRef<HTMLInputElement>(null);
|
|
92
92
|
// Get initial chain IDs from URL or defaults
|
|
93
|
-
const initialSrcChainId = parseInt(searchParams.get("fromChainId") || "0") || mainnet.id;
|
|
93
|
+
const initialSrcChainId = sourceChainId || parseInt(searchParams.get("fromChainId") || "0") || mainnet.id;
|
|
94
94
|
const initialDstChainId = parseInt(searchParams.get("toChainId") || "0") || (isBuyMode ? destinationTokenChainId : base.id);
|
|
95
95
|
// State for source chain/token selection
|
|
96
96
|
const [selectedSrcChainId, setSelectedSrcChainId] = useState(initialSrcChainId);
|
|
@@ -183,8 +183,8 @@ function AnySpendInner({ destinationTokenAddress, destinationTokenChainId, mode
|
|
|
183
183
|
}, [selectedDstToken.address, selectedDstToken.chainId]);
|
|
184
184
|
// Load swap configuration from URL on initial render
|
|
185
185
|
useEffect(() => {
|
|
186
|
-
// Skip if we've already processed the URL
|
|
187
|
-
if (initialUrlProcessed.current || loadOrder)
|
|
186
|
+
// Skip if we've already processed the URL, if we have an order to load, or if URL param management is disabled
|
|
187
|
+
if (initialUrlProcessed.current || loadOrder || disableUrlParamManagement)
|
|
188
188
|
return;
|
|
189
189
|
try {
|
|
190
190
|
const tabParam = searchParams.get("tab");
|
|
@@ -217,7 +217,7 @@ function AnySpendInner({ destinationTokenAddress, destinationTokenChainId, mode
|
|
|
217
217
|
}
|
|
218
218
|
// Mark that we've processed the initial URL
|
|
219
219
|
initialUrlProcessed.current = true;
|
|
220
|
-
}, [searchParams, loadOrder]);
|
|
220
|
+
}, [searchParams, loadOrder, disableUrlParamManagement]);
|
|
221
221
|
// Update URL when swap configuration changes - but not on initial load
|
|
222
222
|
const updateSwapParamsInURL = useCallback(() => {
|
|
223
223
|
// Skip if:
|
|
@@ -228,7 +228,8 @@ function AnySpendInner({ destinationTokenAddress, destinationTokenChainId, mode
|
|
|
228
228
|
activePanel !== PanelView.MAIN ||
|
|
229
229
|
!initialUrlProcessed.current ||
|
|
230
230
|
searchParams.has("orderId") ||
|
|
231
|
-
mode === "modal"
|
|
231
|
+
mode === "modal" ||
|
|
232
|
+
disableUrlParamManagement)
|
|
232
233
|
return;
|
|
233
234
|
// Create a representation of the current state
|
|
234
235
|
const currentState = {
|
|
@@ -288,6 +289,7 @@ function AnySpendInner({ destinationTokenAddress, destinationTokenChainId, mode
|
|
|
288
289
|
dstAmount,
|
|
289
290
|
router,
|
|
290
291
|
srcAmountOnRamp,
|
|
292
|
+
disableUrlParamManagement,
|
|
291
293
|
]);
|
|
292
294
|
// Update URL when relevant state changes - but only after initial render
|
|
293
295
|
useEffect(() => {
|
|
@@ -473,20 +475,20 @@ function AnySpendInner({ destinationTokenAddress, destinationTokenChainId, mode
|
|
|
473
475
|
setOrderId(orderId);
|
|
474
476
|
// setNewRecipientAddress("");
|
|
475
477
|
navigateToPanel(PanelView.ORDER_DETAILS, "forward");
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
478
|
+
if (!disableUrlParamManagement) {
|
|
479
|
+
// Debug: Check payment method before setting URL
|
|
480
|
+
console.log("Creating order - selectedCryptoPaymentMethod:", selectedCryptoPaymentMethod);
|
|
481
|
+
// Add orderId and payment method to URL for persistence
|
|
482
|
+
const params = new URLSearchParams(searchParams.toString()); // Preserve existing params
|
|
483
|
+
params.set("orderId", orderId);
|
|
484
|
+
if (effectiveCryptoPaymentMethod !== CryptoPaymentMethodType.NONE) {
|
|
485
|
+
params.set("cryptoPaymentMethod", effectiveCryptoPaymentMethod);
|
|
486
|
+
}
|
|
487
|
+
else {
|
|
488
|
+
console.log("Payment method is NONE, not setting in URL");
|
|
489
|
+
}
|
|
490
|
+
router.push(`${window.location.pathname}?${params.toString()}`);
|
|
487
491
|
}
|
|
488
|
-
console.log("Final URL params:", params.toString());
|
|
489
|
-
router.push(`${window.location.pathname}?${params.toString()}`);
|
|
490
492
|
},
|
|
491
493
|
onError: error => {
|
|
492
494
|
console.error(error);
|
|
@@ -499,11 +501,13 @@ function AnySpendInner({ destinationTokenAddress, destinationTokenChainId, mode
|
|
|
499
501
|
const orderId = data.data.id;
|
|
500
502
|
setOrderId(orderId);
|
|
501
503
|
navigateToPanel(PanelView.ORDER_DETAILS, "forward");
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
504
|
+
if (!disableUrlParamManagement) {
|
|
505
|
+
// Add orderId and payment method to URL for persistence
|
|
506
|
+
const params = new URLSearchParams(searchParams.toString());
|
|
507
|
+
params.set("orderId", orderId);
|
|
508
|
+
params.set("paymentMethod", "fiat");
|
|
509
|
+
router.push(`${window.location.pathname}?${params.toString()}`);
|
|
510
|
+
}
|
|
507
511
|
},
|
|
508
512
|
onError: error => {
|
|
509
513
|
console.error(error);
|
|
@@ -631,11 +635,13 @@ function AnySpendInner({ destinationTokenAddress, destinationTokenChainId, mode
|
|
|
631
635
|
type: "anySpendOrderHistory",
|
|
632
636
|
showBackButton: false,
|
|
633
637
|
});
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
638
|
+
if (!disableUrlParamManagement) {
|
|
639
|
+
// Remove orderId and paymentMethod from URL when going back to history
|
|
640
|
+
const params = new URLSearchParams(searchParams.toString());
|
|
641
|
+
params.delete("orderId");
|
|
642
|
+
params.delete("paymentMethod");
|
|
643
|
+
router.push(`${window.location.pathname}?${params.toString()}`);
|
|
644
|
+
}
|
|
639
645
|
};
|
|
640
646
|
// Handle crypto swap creation
|
|
641
647
|
const handleCryptoSwap = async (method) => {
|
|
@@ -744,22 +750,24 @@ function AnySpendInner({ destinationTokenAddress, destinationTokenChainId, mode
|
|
|
744
750
|
// const setDynamicModalContentType = useModalStore(state => state.setB3ModalContentType);
|
|
745
751
|
// Update useEffect for URL parameter to not override loadOrder
|
|
746
752
|
useEffect(() => {
|
|
747
|
-
if (loadOrder)
|
|
748
|
-
return; // Skip if we have a loadOrder
|
|
753
|
+
if (loadOrder || disableUrlParamManagement)
|
|
754
|
+
return; // Skip if we have a loadOrder or URL param management is disabled
|
|
749
755
|
const orderIdParam = searchParams.get("orderId");
|
|
750
756
|
if (orderIdParam) {
|
|
751
757
|
setOrderId(orderIdParam);
|
|
752
758
|
setActivePanel(PanelView.ORDER_DETAILS);
|
|
753
759
|
}
|
|
754
|
-
}, [searchParams, loadOrder]);
|
|
760
|
+
}, [searchParams, loadOrder, disableUrlParamManagement]);
|
|
755
761
|
const onSelectOrder = (selectedOrderId) => {
|
|
756
762
|
setOrderId(selectedOrderId);
|
|
757
763
|
navigateToPanel(PanelView.ORDER_DETAILS, "forward");
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
764
|
+
if (!disableUrlParamManagement) {
|
|
765
|
+
// Update URL with the new orderId and preserve existing parameters
|
|
766
|
+
const params = new URLSearchParams(searchParams.toString());
|
|
767
|
+
params.set("orderId", selectedOrderId);
|
|
768
|
+
// Keep existing paymentMethod if present
|
|
769
|
+
router.push(`${window.location.pathname}?${params.toString()}`);
|
|
770
|
+
}
|
|
763
771
|
};
|
|
764
772
|
// Save custom recipients to local storage when they change
|
|
765
773
|
useEffect(() => {
|
|
@@ -811,7 +819,7 @@ function AnySpendInner({ destinationTokenAddress, destinationTokenChainId, mode
|
|
|
811
819
|
// Reset payment methods when going back
|
|
812
820
|
resetPaymentMethods();
|
|
813
821
|
} })) }) }));
|
|
814
|
-
const mainView = (_jsxs("div", { className: "mx-auto flex w-[460px] max-w-full flex-col items-center gap-2 pt-5", children: [_jsxs("div", { className: "flex w-full max-w-full flex-col items-center gap-2 px-5", children: [isBuyMode && (_jsxs("div", { className: "mb-4 flex flex-col items-center gap-3 text-center", children: [selectedDstToken.metadata?.logoURI && (_jsx("div", { className: "relative", children: _jsx("img", { src: selectedDstToken.metadata.logoURI, alt: selectedDstToken.symbol, className: "border-as-stroke h-12 w-12 rounded-full border-2 shadow-md" }) })), _jsx("div", { children: _jsxs("h1", { className: "text-as-primary text-xl font-bold", children: ["Buy ", selectedDstToken.symbol] }) })] })), _jsx(TabSection, { activeTab: activeTab, setActiveTab: tab => {
|
|
822
|
+
const mainView = (_jsxs("div", { className: "mx-auto flex w-[460px] max-w-full flex-col items-center gap-2 pt-5", children: [_jsxs("div", { className: "flex w-full max-w-full flex-col items-center gap-2 px-5", children: [isBuyMode && !hideHeader && (_jsxs("div", { className: "mb-4 flex flex-col items-center gap-3 text-center", children: [selectedDstToken.metadata?.logoURI && (_jsx("div", { className: "relative", children: _jsx("img", { src: selectedDstToken.metadata.logoURI, alt: selectedDstToken.symbol, className: "border-as-stroke h-12 w-12 rounded-full border-2 shadow-md" }) })), _jsx("div", { children: _jsxs("h1", { className: "text-as-primary text-xl font-bold", children: ["Buy ", selectedDstToken.symbol] }) })] })), _jsx(TabSection, { activeTab: activeTab, setActiveTab: tab => {
|
|
815
823
|
setActiveTab(tab);
|
|
816
824
|
// Reset payment methods when switching tabs
|
|
817
825
|
resetPaymentMethods();
|
|
@@ -825,30 +833,24 @@ function AnySpendInner({ destinationTokenAddress, destinationTokenChainId, mode
|
|
|
825
833
|
else {
|
|
826
834
|
setActivePanel(panelIndex);
|
|
827
835
|
}
|
|
828
|
-
}, _recipientAddress: effectiveRecipientAddress, destinationToken: selectedDstToken, destinationChainId: selectedDstChainId, destinationAmount: dstAmount, onDestinationTokenChange: setSelectedDstToken, onDestinationChainChange: setSelectedDstChainId, fiatPaymentMethodIndex: PanelView.FIAT_PAYMENT_METHOD, recipientSelectionPanelIndex: PanelView.RECIPIENT_SELECTION, hideDstToken: isBuyMode, anyspendQuote: anyspendQuote, onShowPointsDetail: () => navigateToPanel(PanelView.POINTS_DETAIL, "forward"), onShowFeeDetail: () => navigateToPanel(PanelView.FEE_DETAIL, "forward"), customUsdInputValues: customUsdInputValues }) })), _jsx(Button, { variant: "ghost", className: cn("border-as-stroke bg-as-surface-primary
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
// Swap amounts
|
|
847
|
-
const tempSrcAmount = srcAmount;
|
|
848
|
-
const tempDstAmount = dstAmount;
|
|
849
|
-
setSrcAmount(tempDstAmount);
|
|
850
|
-
setDstAmount(tempSrcAmount);
|
|
851
|
-
}, children: _jsx("div", { className: "relative flex items-center justify-center transition-opacity", children: _jsx(ArrowDown, { className: "text-as-primary/50 h-5 w-5" }) }) }), activeTab === "crypto" && (_jsx(CryptoReceiveSection, { isDepositMode: false, isBuyMode: isBuyMode, effectiveRecipientAddress: effectiveRecipientAddress, recipientName: recipientName || undefined, onSelectRecipient: () => navigateToPanel(PanelView.RECIPIENT_SELECTION, "forward"), dstAmount: dstAmount, dstToken: selectedDstToken, selectedDstChainId: selectedDstChainId, setSelectedDstChainId: setSelectedDstChainId, setSelectedDstToken: setSelectedDstToken, isSrcInputDirty: isSrcInputDirty, onChangeDstAmount: value => {
|
|
836
|
+
}, _recipientAddress: effectiveRecipientAddress, destinationToken: selectedDstToken, destinationChainId: selectedDstChainId, destinationAmount: dstAmount, onDestinationTokenChange: setSelectedDstToken, onDestinationChainChange: setSelectedDstChainId, fiatPaymentMethodIndex: PanelView.FIAT_PAYMENT_METHOD, recipientSelectionPanelIndex: PanelView.RECIPIENT_SELECTION, hideDstToken: isBuyMode, anyspendQuote: anyspendQuote, onShowPointsDetail: () => navigateToPanel(PanelView.POINTS_DETAIL, "forward"), onShowFeeDetail: () => navigateToPanel(PanelView.FEE_DETAIL, "forward"), customUsdInputValues: customUsdInputValues }) })), activeTab === "crypto" && (_jsx("div", { className: "z-10 -my-6 flex justify-center", children: _jsx(Button, { variant: "ghost", className: cn("border-as-stroke bg-as-surface-primary h-10 w-10 rounded-xl border-2 sm:h-8 sm:w-8 sm:rounded-xl", isBuyMode && "cursor-default", selectedDstChainId === HYPERLIQUID_CHAIN_ID && "cursor-not-allowed opacity-50"), onClick: () => {
|
|
837
|
+
if (isBuyMode) {
|
|
838
|
+
return;
|
|
839
|
+
}
|
|
840
|
+
// Prevent swapping if destination is Hyperliquid (only supported as destination, not source)
|
|
841
|
+
if (selectedDstChainId === HYPERLIQUID_CHAIN_ID) {
|
|
842
|
+
return;
|
|
843
|
+
}
|
|
844
|
+
// Swap chain selections
|
|
845
|
+
setSelectedSrcChainId(selectedDstChainId);
|
|
846
|
+
setSelectedDstChainId(selectedSrcChainId);
|
|
847
|
+
// Swap token selections
|
|
848
|
+
setSelectedSrcToken(selectedDstToken);
|
|
849
|
+
setSelectedDstToken(selectedSrcToken);
|
|
850
|
+
// Swap amounts
|
|
851
|
+
setSrcAmount(dstAmount);
|
|
852
|
+
setDstAmount(srcAmount);
|
|
853
|
+
}, children: _jsx("div", { className: "relative flex items-center justify-center transition-opacity", children: _jsx(ArrowDown, { className: "text-as-primary/50 h-5 w-5" }) }) }) })), activeTab === "crypto" && (_jsx(CryptoReceiveSection, { isDepositMode: false, isBuyMode: isBuyMode, effectiveRecipientAddress: effectiveRecipientAddress, recipientName: recipientName || undefined, onSelectRecipient: () => navigateToPanel(PanelView.RECIPIENT_SELECTION, "forward"), dstAmount: dstAmount, dstToken: selectedDstToken, selectedDstChainId: selectedDstChainId, setSelectedDstChainId: setSelectedDstChainId, setSelectedDstToken: setSelectedDstToken, isSrcInputDirty: isSrcInputDirty, onChangeDstAmount: value => {
|
|
852
854
|
setIsSrcInputDirty(false);
|
|
853
855
|
setDstAmount(value);
|
|
854
856
|
}, anyspendQuote: anyspendQuote, onShowPointsDetail: () => navigateToPanel(PanelView.POINTS_DETAIL, "forward"), onShowFeeDetail: () => navigateToPanel(PanelView.FEE_DETAIL, "forward") }))] }), _jsxs(motion.div, { initial: { opacity: 0, y: 20, filter: "blur(10px)" }, animate: { opacity: 1, y: 0, filter: "blur(0px)" }, transition: { duration: 0.3, delay: 0.2, ease: "easeInOut" }, className: cn("mt-4 flex w-full max-w-[460px] flex-col gap-2"), children: [_jsx(ShinyButton, { accentColor: "hsl(var(--as-brand))", disabled: btnInfo.disable, onClick: onMainButtonClick, className: cn("as-main-button relative w-full", btnInfo.error ? "!bg-as-red" : btnInfo.disable ? "!bg-as-on-surface-2" : "!bg-as-brand"), textClassName: cn(btnInfo.error ? "text-white" : btnInfo.disable ? "text-as-secondary" : "text-white"), children: _jsxs("div", { className: "flex items-center justify-center gap-2", children: [btnInfo.loading && _jsx(Loader2, { className: "h-4 w-4 animate-spin" }), btnInfo.text] }) }), !hideTransactionHistoryButton && (globalAddress || effectiveRecipientAddress) ? (_jsxs(Button, { variant: "link", onClick: onClickHistory, className: "text-as-primary/50 hover:text-as-primary flex items-center gap-1 transition-colors", children: [_jsx(HistoryIcon, { className: "h-4 w-4" }), " ", _jsx("span", { className: "pr-4", children: "Transaction History" })] })) : null] })] }), _jsx("div", { className: "w-full", children: _jsx(TabsPrimitive, { defaultValue: "swap", onValueChange: value => {
|
|
@@ -866,21 +868,23 @@ function AnySpendInner({ destinationTokenAddress, destinationTokenChainId, mode
|
|
|
866
868
|
type: "anySpend",
|
|
867
869
|
});
|
|
868
870
|
}
|
|
869
|
-
}, children: mode !== "page" && _jsx(BottomNavigation, {}) }) })] }));
|
|
871
|
+
}, children: mode !== "page" && !hideBottomNavigation && _jsx(BottomNavigation, {}) }) })] }));
|
|
870
872
|
const onrampPaymentView = (_jsx(PanelOnrampPayment, { srcAmountOnRamp: srcAmountOnRamp, recipientName: recipientName || undefined, recipientAddress: effectiveRecipientAddress, isBuyMode: isBuyMode, destinationTokenChainId: destinationTokenChainId, destinationTokenAddress: destinationTokenAddress, selectedDstChainId: selectedDstChainId, selectedDstToken: selectedDstToken, orderType: "swap", anyspendQuote: anyspendQuote, globalAddress: globalAddress, onOrderCreated: orderId => {
|
|
871
873
|
setOrderId(orderId);
|
|
872
874
|
navigateToPanel(PanelView.ORDER_DETAILS, "forward");
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
|
|
875
|
+
if (!disableUrlParamManagement) {
|
|
876
|
+
// Add orderId and payment method to URL for persistence
|
|
877
|
+
const params = new URLSearchParams(searchParams.toString()); // Preserve existing params
|
|
878
|
+
params.set("orderId", orderId);
|
|
879
|
+
// For fiat payments, the payment method is always fiat (but we use the active tab context)
|
|
880
|
+
if (activeTab === "fiat") {
|
|
881
|
+
params.set("paymentMethod", "fiat");
|
|
882
|
+
}
|
|
883
|
+
else if (selectedCryptoPaymentMethod !== CryptoPaymentMethodType.NONE) {
|
|
884
|
+
params.set("paymentMethod", selectedCryptoPaymentMethod);
|
|
885
|
+
}
|
|
886
|
+
router.push(`${window.location.pathname}?${params.toString()}`);
|
|
882
887
|
}
|
|
883
|
-
router.push(`${window.location.pathname}?${params.toString()}`);
|
|
884
888
|
}, onBack: navigateBack, recipientEnsName: globalWallet?.ensName, recipientImageUrl: globalWalletImage }));
|
|
885
889
|
const recipientSelectionView = (_jsx(RecipientSelection, { initialValue: effectiveRecipientAddress || "", onBack: navigateBack, onConfirm: address => {
|
|
886
890
|
// User manually selected a recipient
|
|
@@ -26,7 +26,7 @@ export interface AnySpendCustomExactInProps {
|
|
|
26
26
|
customUsdInputValues?: string[];
|
|
27
27
|
preferEoa?: boolean;
|
|
28
28
|
customExactInConfig?: CustomExactInConfig;
|
|
29
|
-
orderType?: "hype_duel" | "custom_exact_in";
|
|
29
|
+
orderType?: "hype_duel" | "custom_exact_in" | "swap";
|
|
30
30
|
minDestinationAmount?: number;
|
|
31
31
|
header?: ({ anyspendPrice, isLoadingAnyspendPrice, }: {
|
|
32
32
|
anyspendPrice: GetQuoteResponse | undefined;
|
|
@@ -35,7 +35,6 @@ function AnySpendCustomExactInInner({ loadOrder, mode = "modal", recipientAddres
|
|
|
35
35
|
paymentType,
|
|
36
36
|
recipientAddress,
|
|
37
37
|
loadOrder,
|
|
38
|
-
isDepositMode: true,
|
|
39
38
|
onTransactionSuccess: onSuccess,
|
|
40
39
|
sourceTokenAddress,
|
|
41
40
|
sourceTokenChainId,
|
|
@@ -176,7 +175,7 @@ function AnySpendCustomExactInInner({ loadOrder, mode = "modal", recipientAddres
|
|
|
176
175
|
}
|
|
177
176
|
};
|
|
178
177
|
const headerContent = header ? (header({ anyspendPrice: anyspendQuote, isLoadingAnyspendPrice: isLoadingAnyspendQuote })) : (_jsx("div", { className: "mb-4 flex flex-col items-center gap-3 text-center", children: _jsxs("div", { children: [_jsx("h1", { className: "text-as-primary text-xl font-bold", children: actionLabel }), _jsx("p", { className: "text-as-secondary text-sm", children: "Pay from any token to execute a custom exact-in transaction." })] }) }));
|
|
179
|
-
const mainView = (_jsxs("div", { className: "mx-auto flex w-[460px] max-w-full flex-col items-center gap-2", children: [headerContent, _jsx("div", { className: "relative flex w-full max-w-[calc(100vw-32px)] flex-col gap-2", children: _jsxs("div", { className: "relative flex w-full max-w-[calc(100vw-32px)] flex-col gap-2", children: [paymentType === "crypto" ? (_jsx(CryptoPaySection, { selectedSrcChainId: selectedSrcChainId, setSelectedSrcChainId: setSelectedSrcChainId, selectedSrcToken: selectedSrcToken, setSelectedSrcToken: setSelectedSrcToken, srcAmount: srcAmount, setSrcAmount: setSrcAmount, isSrcInputDirty: isSrcInputDirty, setIsSrcInputDirty: setIsSrcInputDirty, selectedCryptoPaymentMethod: effectiveCryptoPaymentMethod, onSelectCryptoPaymentMethod: () => setActivePanel(PanelView.CRYPTO_PAYMENT_METHOD), anyspendQuote: anyspendQuote, onTokenSelect: onTokenSelect })) : (_jsx(motion.div, { initial: { opacity: 0, y: 20, filter: "blur(10px)" }, animate: { opacity: 1, y: 0, filter: "blur(0px)" }, transition: { duration: 0.3, delay: 0, ease: "easeInOut" }, children: _jsx(PanelOnramp, { srcAmountOnRamp: srcAmount, setSrcAmountOnRamp: setSrcAmount, selectedPaymentMethod: selectedFiatPaymentMethod, setActivePanel: setActivePanel, _recipientAddress: selectedRecipientOrDefault, destinationToken: selectedDstToken, destinationChainId: selectedDstChainId, dstTokenSymbol: DESTINATION_TOKEN_DETAILS.SYMBOL, hideDstToken: true, destinationAmount: dstAmount, onDestinationTokenChange: () => { }, onDestinationChainChange: () => { }, fiatPaymentMethodIndex: PanelView.FIAT_PAYMENT_METHOD, recipientSelectionPanelIndex: PanelView.RECIPIENT_SELECTION, anyspendQuote: anyspendQuote, onShowPointsDetail: () => setActivePanel(PanelView.POINTS_DETAIL), onShowFeeDetail: () => setActivePanel(PanelView.FEE_DETAIL), customUsdInputValues: customUsdInputValues }) })), _jsx("div", { className: cn("relative -my-1 flex h-0 items-center justify-center", paymentType === "fiat" && "hidden"), children: _jsx(Button, { variant: "ghost", className: cn("swap-direction-button border-as-stroke bg-as-surface-primary z-10 h-10 w-10 cursor-default rounded-xl border-2 sm:h-8 sm:w-8 sm:rounded-xl"), children: _jsx("div", { className: "relative flex items-center justify-center transition-opacity", children: _jsx(ArrowDown, { className: "text-as-primary/50 h-5 w-5" }) }) }) }), paymentType === "crypto" && (_jsx(CryptoReceiveSection, { isDepositMode: false, isBuyMode: true, effectiveRecipientAddress: selectedRecipientOrDefault, recipientName: recipientName || undefined, onSelectRecipient: () => setActivePanel(PanelView.RECIPIENT_SELECTION), dstAmount: dstAmount, dstToken: selectedDstToken, dstTokenSymbol: DESTINATION_TOKEN_DETAILS.SYMBOL, dstTokenLogoURI: DESTINATION_TOKEN_DETAILS.LOGO_URI, selectedDstChainId: selectedDstChainId, setSelectedDstChainId: () => { }, setSelectedDstToken: () => { }, isSrcInputDirty: isSrcInputDirty, onChangeDstAmount: value => {
|
|
178
|
+
const mainView = (_jsxs("div", { className: "anyspend-custom-exact-in-container mx-auto flex w-[460px] max-w-full flex-col items-center gap-2", children: [headerContent, _jsx("div", { className: "relative flex w-full max-w-[calc(100vw-32px)] flex-col gap-2", children: _jsxs("div", { className: "relative flex w-full max-w-[calc(100vw-32px)] flex-col gap-2", children: [paymentType === "crypto" ? (_jsx(CryptoPaySection, { selectedSrcChainId: selectedSrcChainId, setSelectedSrcChainId: setSelectedSrcChainId, selectedSrcToken: selectedSrcToken, setSelectedSrcToken: setSelectedSrcToken, srcAmount: srcAmount, setSrcAmount: setSrcAmount, isSrcInputDirty: isSrcInputDirty, setIsSrcInputDirty: setIsSrcInputDirty, selectedCryptoPaymentMethod: effectiveCryptoPaymentMethod, onSelectCryptoPaymentMethod: () => setActivePanel(PanelView.CRYPTO_PAYMENT_METHOD), anyspendQuote: anyspendQuote, onTokenSelect: onTokenSelect })) : (_jsx(motion.div, { initial: { opacity: 0, y: 20, filter: "blur(10px)" }, animate: { opacity: 1, y: 0, filter: "blur(0px)" }, transition: { duration: 0.3, delay: 0, ease: "easeInOut" }, children: _jsx(PanelOnramp, { srcAmountOnRamp: srcAmount, setSrcAmountOnRamp: setSrcAmount, selectedPaymentMethod: selectedFiatPaymentMethod, setActivePanel: setActivePanel, _recipientAddress: selectedRecipientOrDefault, destinationToken: selectedDstToken, destinationChainId: selectedDstChainId, dstTokenSymbol: DESTINATION_TOKEN_DETAILS.SYMBOL, hideDstToken: true, destinationAmount: dstAmount, onDestinationTokenChange: () => { }, onDestinationChainChange: () => { }, fiatPaymentMethodIndex: PanelView.FIAT_PAYMENT_METHOD, recipientSelectionPanelIndex: PanelView.RECIPIENT_SELECTION, anyspendQuote: anyspendQuote, onShowPointsDetail: () => setActivePanel(PanelView.POINTS_DETAIL), onShowFeeDetail: () => setActivePanel(PanelView.FEE_DETAIL), customUsdInputValues: customUsdInputValues }) })), _jsx("div", { className: cn("relative -my-1 flex h-0 items-center justify-center", paymentType === "fiat" && "hidden"), children: _jsx(Button, { variant: "ghost", className: cn("swap-direction-button border-as-stroke bg-as-surface-primary z-10 h-10 w-10 cursor-default rounded-xl border-2 sm:h-8 sm:w-8 sm:rounded-xl"), children: _jsx("div", { className: "relative flex items-center justify-center transition-opacity", children: _jsx(ArrowDown, { className: "text-as-primary/50 h-5 w-5" }) }) }) }), paymentType === "crypto" && (_jsx(CryptoReceiveSection, { isDepositMode: false, isBuyMode: true, effectiveRecipientAddress: selectedRecipientOrDefault, recipientName: recipientName || undefined, onSelectRecipient: () => setActivePanel(PanelView.RECIPIENT_SELECTION), dstAmount: dstAmount, dstToken: selectedDstToken, dstTokenSymbol: DESTINATION_TOKEN_DETAILS.SYMBOL, dstTokenLogoURI: DESTINATION_TOKEN_DETAILS.LOGO_URI, selectedDstChainId: selectedDstChainId, setSelectedDstChainId: () => { }, setSelectedDstToken: () => { }, isSrcInputDirty: isSrcInputDirty, onChangeDstAmount: value => {
|
|
180
179
|
setIsSrcInputDirty(false);
|
|
181
180
|
setSrcAmount(value);
|
|
182
181
|
}, anyspendQuote: anyspendQuote, onShowPointsDetail: () => setActivePanel(PanelView.POINTS_DETAIL), onShowFeeDetail: () => setActivePanel(PanelView.FEE_DETAIL) }))] }) }), _jsx(motion.div, { initial: { opacity: 0, y: 20, filter: "blur(10px)" }, animate: { opacity: 1, y: 0, filter: "blur(0px)" }, transition: { duration: 0.3, delay: 0.2, ease: "easeInOut" }, className: cn("mt-4 flex w-full max-w-[460px] flex-col gap-2"), children: _jsx(ShinyButton, { accentColor: "hsl(var(--as-brand))", disabled: btnInfo.disable, onClick: onMainButtonClick, className: cn("as-main-button relative w-full", btnInfo.error ? "!bg-as-red" : btnInfo.disable ? "!bg-as-on-surface-2" : "!bg-as-brand"), textClassName: cn(btnInfo.error ? "text-white" : btnInfo.disable ? "text-as-secondary" : "text-white"), children: _jsxs("div", { className: "flex items-center justify-center gap-2", children: [btnInfo.loading && _jsx(Loader2, { className: "h-4 w-4 animate-spin" }), btnInfo.text] }) }) }), mainFooter ? mainFooter : null] }));
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
import { components } from "../../../anyspend/types/api";
|
|
2
|
+
import { GetQuoteResponse } from "../../../anyspend/types/api_req_res";
|
|
3
|
+
export interface DepositContractConfig {
|
|
4
|
+
/** Custom function ABI JSON string */
|
|
5
|
+
functionAbi: string;
|
|
6
|
+
/** The function name to call */
|
|
7
|
+
functionName: string;
|
|
8
|
+
/** Custom function arguments. Use "{{amount_out}}" for the deposit amount placeholder */
|
|
9
|
+
functionArgs: string[];
|
|
10
|
+
/** The contract address to deposit to */
|
|
11
|
+
to: string;
|
|
12
|
+
/** Optional spender address if different from contract address */
|
|
13
|
+
spenderAddress?: string;
|
|
14
|
+
/** Custom action label */
|
|
15
|
+
action?: string;
|
|
16
|
+
}
|
|
17
|
+
export interface ChainConfig {
|
|
18
|
+
/** Chain ID */
|
|
19
|
+
id: number;
|
|
20
|
+
/** Display name */
|
|
21
|
+
name: string;
|
|
22
|
+
/** Optional icon URL */
|
|
23
|
+
iconUrl?: string;
|
|
24
|
+
}
|
|
25
|
+
export interface AnySpendDepositProps {
|
|
26
|
+
/** Order ID to load an existing order */
|
|
27
|
+
loadOrder?: string;
|
|
28
|
+
/** Display mode */
|
|
29
|
+
mode?: "modal" | "page";
|
|
30
|
+
/** The recipient address for the deposit */
|
|
31
|
+
recipientAddress: string;
|
|
32
|
+
/** Payment type - crypto or fiat. If not set, shows chain selection first */
|
|
33
|
+
paymentType?: "crypto" | "fiat";
|
|
34
|
+
/** Source token address to pre-select */
|
|
35
|
+
sourceTokenAddress?: string;
|
|
36
|
+
/** Source chain ID to pre-select. If not provided, shows chain selection */
|
|
37
|
+
sourceTokenChainId?: number;
|
|
38
|
+
/** The destination token to receive */
|
|
39
|
+
destinationToken: components["schemas"]["Token"];
|
|
40
|
+
/** The destination chain ID */
|
|
41
|
+
destinationChainId: number;
|
|
42
|
+
/** Callback when deposit succeeds */
|
|
43
|
+
onSuccess?: (amount: string) => void;
|
|
44
|
+
/** Callback for opening a custom modal (e.g., for special token handling) */
|
|
45
|
+
onOpenCustomModal?: () => void;
|
|
46
|
+
/** Custom footer content */
|
|
47
|
+
mainFooter?: React.ReactNode;
|
|
48
|
+
/** Called when a token is selected. Call event.preventDefault() to prevent default behavior */
|
|
49
|
+
onTokenSelect?: (token: components["schemas"]["Token"], event: {
|
|
50
|
+
preventDefault: () => void;
|
|
51
|
+
}) => void;
|
|
52
|
+
/** Custom USD input value presets for fiat payment */
|
|
53
|
+
customUsdInputValues?: string[];
|
|
54
|
+
/** Whether to prefer using connected EOA wallet */
|
|
55
|
+
preferEoa?: boolean;
|
|
56
|
+
/** Minimum destination amount required */
|
|
57
|
+
minDestinationAmount?: number;
|
|
58
|
+
/** Custom header component */
|
|
59
|
+
header?: ({ anyspendPrice, isLoadingAnyspendPrice, }: {
|
|
60
|
+
anyspendPrice: GetQuoteResponse | undefined;
|
|
61
|
+
isLoadingAnyspendPrice: boolean;
|
|
62
|
+
}) => React.JSX.Element;
|
|
63
|
+
/** Order type for the deposit */
|
|
64
|
+
orderType?: "hype_duel" | "custom_exact_in" | "swap";
|
|
65
|
+
/** Custom action label displayed on buttons */
|
|
66
|
+
actionLabel?: string;
|
|
67
|
+
/** Configuration for depositing to a custom contract.
|
|
68
|
+
* If provided, creates a custom_exact_in order that calls the contract.
|
|
69
|
+
* If not provided, creates a simple hype_duel order for direct deposits.
|
|
70
|
+
*/
|
|
71
|
+
depositContractConfig?: DepositContractConfig;
|
|
72
|
+
/** Whether to show chain selection step. Defaults to true if sourceTokenChainId is not provided */
|
|
73
|
+
showChainSelection?: boolean;
|
|
74
|
+
/** Custom list of supported chains. If not provided, uses default chains */
|
|
75
|
+
supportedChains?: ChainConfig[];
|
|
76
|
+
/** Minimum pool size for filtering tokens (default: 1,000,000) */
|
|
77
|
+
minPoolSize?: number;
|
|
78
|
+
/** Custom title for chain selection step */
|
|
79
|
+
chainSelectionTitle?: string;
|
|
80
|
+
/** Custom description for chain selection step */
|
|
81
|
+
chainSelectionDescription?: string;
|
|
82
|
+
/** Number of top chains to show (default: 3) */
|
|
83
|
+
topChainsCount?: number;
|
|
84
|
+
/** Callback when close button is clicked */
|
|
85
|
+
onClose?: () => void;
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* A flexible deposit component that wraps AnySpendCustomExactIn with optional chain selection.
|
|
89
|
+
*
|
|
90
|
+
* @example
|
|
91
|
+
* // Simple deposit with chain selection
|
|
92
|
+
* <AnySpendDeposit
|
|
93
|
+
* recipientAddress={userAddress}
|
|
94
|
+
* destinationToken={myToken}
|
|
95
|
+
* destinationChainId={base.id}
|
|
96
|
+
* onSuccess={(amount) => console.log(`Deposited ${amount}`)}
|
|
97
|
+
* />
|
|
98
|
+
*
|
|
99
|
+
* @example
|
|
100
|
+
* // Skip chain selection by providing sourceTokenChainId
|
|
101
|
+
* <AnySpendDeposit
|
|
102
|
+
* recipientAddress={userAddress}
|
|
103
|
+
* destinationToken={myToken}
|
|
104
|
+
* destinationChainId={base.id}
|
|
105
|
+
* sourceTokenChainId={base.id}
|
|
106
|
+
* onSuccess={(amount) => console.log(`Deposited ${amount}`)}
|
|
107
|
+
* />
|
|
108
|
+
*
|
|
109
|
+
* @example
|
|
110
|
+
* // Deposit with custom contract
|
|
111
|
+
* <AnySpendDeposit
|
|
112
|
+
* recipientAddress={userAddress}
|
|
113
|
+
* destinationToken={myToken}
|
|
114
|
+
* destinationChainId={base.id}
|
|
115
|
+
* depositContractConfig={{
|
|
116
|
+
* contractAddress: "0x...",
|
|
117
|
+
* functionName: "depositFor",
|
|
118
|
+
* }}
|
|
119
|
+
* onSuccess={(amount) => console.log(`Deposited ${amount}`)}
|
|
120
|
+
* />
|
|
121
|
+
*/
|
|
122
|
+
export declare function AnySpendDeposit({ loadOrder, mode, recipientAddress, paymentType: initialPaymentType, sourceTokenAddress, sourceTokenChainId: initialSourceChainId, destinationToken, destinationChainId, onSuccess, onOpenCustomModal, mainFooter, onTokenSelect, customUsdInputValues, preferEoa, minDestinationAmount, header, orderType, depositContractConfig, showChainSelection, supportedChains, minPoolSize, topChainsCount, onClose, }: AnySpendDepositProps): import("react/jsx-runtime").JSX.Element | null;
|
|
@@ -0,0 +1,187 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { HYPERLIQUID_CHAIN_ID } from "../../../anyspend/index.js";
|
|
3
|
+
import { Skeleton, useAccountWallet, useSimBalance } from "../../../global-account/react/index.js";
|
|
4
|
+
import { cn } from "../../../shared/utils/cn.js";
|
|
5
|
+
import { NetworkArbitrumOne, NetworkBase, NetworkBinanceSmartChain, NetworkEthereum, NetworkOptimism, NetworkPolygonPos, } from "@web3icons/react";
|
|
6
|
+
import { ChevronRight } from "lucide-react";
|
|
7
|
+
import { useMemo, useState } from "react";
|
|
8
|
+
import { AnySpend } from "./AnySpend.js";
|
|
9
|
+
import { AnySpendCustomExactIn } from "./AnySpendCustomExactIn.js";
|
|
10
|
+
import { ChainWarningText } from "./common/WarningText.js";
|
|
11
|
+
import { CreditCardIcon } from "./icons/CreditCardIcon.js";
|
|
12
|
+
import { QrCodeIcon } from "./icons/QrCodeIcon.js";
|
|
13
|
+
import { QRDeposit } from "./QRDeposit.js";
|
|
14
|
+
// Default supported chains
|
|
15
|
+
const DEFAULT_SUPPORTED_CHAINS = [
|
|
16
|
+
{ id: 8453, name: "Base" },
|
|
17
|
+
{ id: 1, name: "Ethereum" },
|
|
18
|
+
{ id: 42161, name: "Arbitrum" },
|
|
19
|
+
{ id: 10, name: "Optimism" },
|
|
20
|
+
{ id: 137, name: "Polygon" },
|
|
21
|
+
{ id: 56, name: "BNB Chain" },
|
|
22
|
+
];
|
|
23
|
+
// Minimum pool size to filter out low liquidity tokens
|
|
24
|
+
const DEFAULT_MIN_POOL_SIZE = 1000000;
|
|
25
|
+
function formatUsd(value) {
|
|
26
|
+
return new Intl.NumberFormat("en-US", {
|
|
27
|
+
style: "currency",
|
|
28
|
+
currency: "USD",
|
|
29
|
+
minimumFractionDigits: 0,
|
|
30
|
+
maximumFractionDigits: value >= 100 ? 0 : 2,
|
|
31
|
+
}).format(value);
|
|
32
|
+
}
|
|
33
|
+
function formatDecimal(value) {
|
|
34
|
+
return new Intl.NumberFormat("en-US", {
|
|
35
|
+
style: "decimal",
|
|
36
|
+
minimumFractionDigits: 0,
|
|
37
|
+
maximumFractionDigits: value >= 100 ? 0 : 2,
|
|
38
|
+
}).format(value);
|
|
39
|
+
}
|
|
40
|
+
// Chain icon component
|
|
41
|
+
function ChainIcon({ chainId, className }) {
|
|
42
|
+
const iconProps = {
|
|
43
|
+
variant: "branded",
|
|
44
|
+
className: cn("anyspend-deposit-chain-icon", className),
|
|
45
|
+
};
|
|
46
|
+
switch (chainId) {
|
|
47
|
+
case 1:
|
|
48
|
+
return _jsx(NetworkEthereum, { ...iconProps });
|
|
49
|
+
case 8453:
|
|
50
|
+
return _jsx(NetworkBase, { ...iconProps });
|
|
51
|
+
case 137:
|
|
52
|
+
return _jsx(NetworkPolygonPos, { ...iconProps });
|
|
53
|
+
case 42161:
|
|
54
|
+
return _jsx(NetworkArbitrumOne, { ...iconProps });
|
|
55
|
+
case 10:
|
|
56
|
+
return _jsx(NetworkOptimism, { ...iconProps });
|
|
57
|
+
case 56:
|
|
58
|
+
return _jsx(NetworkBinanceSmartChain, { ...iconProps });
|
|
59
|
+
default:
|
|
60
|
+
return null;
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* A flexible deposit component that wraps AnySpendCustomExactIn with optional chain selection.
|
|
65
|
+
*
|
|
66
|
+
* @example
|
|
67
|
+
* // Simple deposit with chain selection
|
|
68
|
+
* <AnySpendDeposit
|
|
69
|
+
* recipientAddress={userAddress}
|
|
70
|
+
* destinationToken={myToken}
|
|
71
|
+
* destinationChainId={base.id}
|
|
72
|
+
* onSuccess={(amount) => console.log(`Deposited ${amount}`)}
|
|
73
|
+
* />
|
|
74
|
+
*
|
|
75
|
+
* @example
|
|
76
|
+
* // Skip chain selection by providing sourceTokenChainId
|
|
77
|
+
* <AnySpendDeposit
|
|
78
|
+
* recipientAddress={userAddress}
|
|
79
|
+
* destinationToken={myToken}
|
|
80
|
+
* destinationChainId={base.id}
|
|
81
|
+
* sourceTokenChainId={base.id}
|
|
82
|
+
* onSuccess={(amount) => console.log(`Deposited ${amount}`)}
|
|
83
|
+
* />
|
|
84
|
+
*
|
|
85
|
+
* @example
|
|
86
|
+
* // Deposit with custom contract
|
|
87
|
+
* <AnySpendDeposit
|
|
88
|
+
* recipientAddress={userAddress}
|
|
89
|
+
* destinationToken={myToken}
|
|
90
|
+
* destinationChainId={base.id}
|
|
91
|
+
* depositContractConfig={{
|
|
92
|
+
* contractAddress: "0x...",
|
|
93
|
+
* functionName: "depositFor",
|
|
94
|
+
* }}
|
|
95
|
+
* onSuccess={(amount) => console.log(`Deposited ${amount}`)}
|
|
96
|
+
* />
|
|
97
|
+
*/
|
|
98
|
+
export function AnySpendDeposit({ loadOrder, mode = "modal", recipientAddress, paymentType: initialPaymentType, sourceTokenAddress, sourceTokenChainId: initialSourceChainId, destinationToken, destinationChainId, onSuccess, onOpenCustomModal, mainFooter, onTokenSelect, customUsdInputValues, preferEoa, minDestinationAmount, header, orderType, depositContractConfig, showChainSelection, supportedChains = DEFAULT_SUPPORTED_CHAINS, minPoolSize = DEFAULT_MIN_POOL_SIZE, topChainsCount = 3, onClose, }) {
|
|
99
|
+
const { connectedEOAWallet } = useAccountWallet();
|
|
100
|
+
const eoaAddress = connectedEOAWallet?.getAccount()?.address;
|
|
101
|
+
// Determine if we should show chain selection
|
|
102
|
+
const shouldShowChainSelection = showChainSelection ?? (!initialSourceChainId && !initialPaymentType);
|
|
103
|
+
const [step, setStep] = useState(shouldShowChainSelection ? "select-chain" : "deposit");
|
|
104
|
+
const [selectedChainId, setSelectedChainId] = useState(initialSourceChainId);
|
|
105
|
+
const [paymentType, setPaymentType] = useState(initialPaymentType ?? "crypto");
|
|
106
|
+
// Fetch balances for EOA wallet
|
|
107
|
+
const { data: balanceData, isLoading: isBalanceLoading } = useSimBalance(shouldShowChainSelection ? eoaAddress : undefined, supportedChains.map(c => c.id));
|
|
108
|
+
// Group balances by chain and calculate total USD value per chain
|
|
109
|
+
const chainBalances = useMemo(() => {
|
|
110
|
+
if (!balanceData?.balances)
|
|
111
|
+
return {};
|
|
112
|
+
const filteredBalances = balanceData.balances.filter(token => token.address === "native" || (token.pool_size && token.pool_size > minPoolSize));
|
|
113
|
+
return filteredBalances.reduce((acc, token) => {
|
|
114
|
+
const chainId = token.chain_id;
|
|
115
|
+
if (!acc[chainId]) {
|
|
116
|
+
acc[chainId] = {
|
|
117
|
+
chainId,
|
|
118
|
+
chainName: token.chain,
|
|
119
|
+
totalUsdValue: 0,
|
|
120
|
+
tokenCount: 0,
|
|
121
|
+
};
|
|
122
|
+
}
|
|
123
|
+
acc[chainId].totalUsdValue += token.value_usd || 0;
|
|
124
|
+
acc[chainId].tokenCount += 1;
|
|
125
|
+
return acc;
|
|
126
|
+
}, {});
|
|
127
|
+
}, [balanceData, minPoolSize]);
|
|
128
|
+
// Sort chains by USD value (highest first)
|
|
129
|
+
const sortedChains = useMemo(() => {
|
|
130
|
+
return supportedChains
|
|
131
|
+
.map(chain => ({
|
|
132
|
+
...chain,
|
|
133
|
+
balance: chainBalances[chain.id]?.totalUsdValue || 0,
|
|
134
|
+
tokenCount: chainBalances[chain.id]?.tokenCount || 0,
|
|
135
|
+
}))
|
|
136
|
+
.sort((a, b) => b.balance - a.balance);
|
|
137
|
+
}, [supportedChains, chainBalances]);
|
|
138
|
+
// Get top chains with balance
|
|
139
|
+
const topChainsWithBalance = useMemo(() => {
|
|
140
|
+
return sortedChains.filter(chain => chain.balance > 0).slice(0, topChainsCount);
|
|
141
|
+
}, [sortedChains, topChainsCount]);
|
|
142
|
+
// Calculate total balance across all chains
|
|
143
|
+
const totalBalance = useMemo(() => {
|
|
144
|
+
return Object.values(chainBalances).reduce((sum, chain) => sum + chain.totalUsdValue, 0);
|
|
145
|
+
}, [chainBalances]);
|
|
146
|
+
if (!recipientAddress)
|
|
147
|
+
return null;
|
|
148
|
+
const tokenSymbol = destinationToken.symbol ?? "TOKEN";
|
|
149
|
+
// Determine order type based on config
|
|
150
|
+
const effectiveOrderType = orderType ?? (depositContractConfig ? "custom_exact_in" : "swap");
|
|
151
|
+
// Default header if not provided
|
|
152
|
+
const defaultHeader = () => (_jsx("div", { className: "anyspend-deposit-header mb-4 flex flex-col items-center gap-3 text-center", children: _jsx("div", { children: _jsx("h1", { className: "anyspend-deposit-title text-as-primary text-xl font-bold", children: paymentType === "crypto" ? `Deposit ${tokenSymbol}` : "Fund with Fiat" }) }) }));
|
|
153
|
+
const handleSelectChain = (chainId) => {
|
|
154
|
+
setSelectedChainId(chainId);
|
|
155
|
+
setPaymentType("crypto");
|
|
156
|
+
setStep("deposit");
|
|
157
|
+
};
|
|
158
|
+
const handleSelectCrypto = () => {
|
|
159
|
+
setPaymentType("crypto");
|
|
160
|
+
setSelectedChainId(undefined);
|
|
161
|
+
setStep("deposit");
|
|
162
|
+
};
|
|
163
|
+
const handleSelectFiat = () => {
|
|
164
|
+
setPaymentType("fiat");
|
|
165
|
+
setSelectedChainId(undefined);
|
|
166
|
+
setStep("deposit");
|
|
167
|
+
};
|
|
168
|
+
const handleBack = () => {
|
|
169
|
+
setStep("select-chain");
|
|
170
|
+
setSelectedChainId(undefined);
|
|
171
|
+
};
|
|
172
|
+
const handleSelectQrDeposit = () => {
|
|
173
|
+
setStep("qr-deposit");
|
|
174
|
+
};
|
|
175
|
+
// Chain selection view
|
|
176
|
+
if (step === "select-chain") {
|
|
177
|
+
return (_jsxs("div", { className: cn("anyspend-deposit anyspend-deposit-chain-selection font-inter bg-as-surface-primary relative mx-auto w-full max-w-[460px]", mode === "page" && "border-as-border-secondary overflow-hidden rounded-2xl border shadow-xl"), children: [onClose && (_jsx("button", { onClick: onClose, className: "anyspend-deposit-close-button text-as-secondary hover:text-as-primary absolute right-4 top-4 z-10", children: _jsx("svg", { className: "h-6 w-6", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: _jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M6 18L18 6M6 6l12 12" }) }) })), _jsxs("div", { className: "anyspend-deposit-balance-header border-secondary border-b p-5", children: [!isBalanceLoading && totalBalance > 0 && (_jsxs("div", { className: "anyspend-deposit-balance", children: [_jsx("p", { className: "anyspend-deposit-balance-label text-as-secondary text-sm", children: "Your Balance" }), _jsxs("p", { className: "anyspend-deposit-balance-value text-as-primary text-3xl font-semibold", children: [formatDecimal(totalBalance), " ", _jsx("span", { className: "text-sm", children: "USD" })] })] })), isBalanceLoading && (_jsxs("div", { className: "anyspend-deposit-balance-skeleton", children: [_jsx(Skeleton, { className: "mb-2 h-4 w-24" }), _jsx(Skeleton, { className: "h-8 w-32" })] }))] }), _jsxs("div", { className: "anyspend-deposit-options flex flex-col gap-2 p-6", children: [isBalanceLoading && (_jsx("div", { className: "anyspend-deposit-chains-skeleton flex flex-col gap-2", children: [...Array(topChainsCount)].map((_, i) => (_jsxs("div", { className: "border-border-primary flex items-center justify-between rounded-xl border p-4", children: [_jsxs("div", { className: "flex items-center gap-3", children: [_jsx(Skeleton, { className: "h-6 w-6 rounded-full" }), _jsxs("div", { className: "flex flex-col gap-1", children: [_jsx(Skeleton, { className: "h-4 w-32" }), _jsx(Skeleton, { className: "h-3 w-20" })] })] }), _jsx(Skeleton, { className: "h-5 w-5" })] }, i))) })), topChainsWithBalance.length > 0 && (_jsx("div", { className: "anyspend-deposit-chains flex flex-col gap-2", children: topChainsWithBalance.map(chain => (_jsxs("button", { onClick: () => handleSelectChain(chain.id), className: "anyspend-deposit-chain-button border-border-primary hover:border-as-brand hover:bg-as-surface-secondary flex w-full items-center justify-between rounded-xl border p-4 text-left shadow-sm transition-all", children: [_jsx("div", { className: "anyspend-deposit-chain-content", children: _jsxs("div", { className: "anyspend-deposit-chain-info", children: [_jsxs("span", { className: "anyspend-deposit-chain-name text-as-primary flex items-center gap-1.5 font-medium", children: ["Deposit from ", chain.name, _jsx(ChainIcon, { chainId: chain.id, className: "h-5 w-5" })] }), _jsxs("p", { className: "anyspend-deposit-chain-balance text-as-secondary text-xs", children: [formatUsd(chain.balance), " available"] })] }) }), _jsx(ChevronRight, { className: "anyspend-deposit-chain-chevron text-as-secondary h-5 w-5" })] }, chain.id))) })), _jsxs("div", { className: "anyspend-deposit-general-options flex flex-col gap-2", children: [_jsxs("button", { onClick: handleSelectCrypto, className: "anyspend-deposit-option-button anyspend-deposit-crypto-button border-border-primary hover:border-as-brand hover:bg-as-surface-secondary flex w-full items-center justify-between rounded-xl border p-4 text-left shadow-sm transition-all", children: [_jsx("div", { className: "anyspend-deposit-option-content", children: _jsxs("div", { className: "anyspend-deposit-option-info", children: [_jsx("span", { className: "anyspend-deposit-option-title text-as-primary font-medium", children: "Deposit Crypto" }), _jsx("p", { className: "anyspend-deposit-option-description text-as-secondary text-xs", children: "Swap from any token on any chain" })] }) }), _jsx(ChevronRight, { className: "anyspend-deposit-option-chevron text-as-secondary h-5 w-5" })] }), _jsxs("div", { className: "anyspend-deposit-divider flex items-center gap-3", children: [_jsx("div", { className: "bg-as-stroke h-px flex-1" }), _jsx("span", { className: "anyspend-deposit-divider-text text-as-secondary text-sm", children: "More options" }), _jsx("div", { className: "bg-as-stroke h-px flex-1" })] }), _jsxs("button", { onClick: handleSelectQrDeposit, className: "anyspend-deposit-option-button anyspend-deposit-qr-button border-border-primary hover:border-as-brand hover:bg-as-surface-secondary flex w-full items-center justify-between rounded-xl border p-4 text-left shadow-sm transition-all", children: [_jsxs("div", { className: "anyspend-deposit-option-content flex items-center gap-3", children: [_jsx(QrCodeIcon, { className: "anyspend-deposit-option-icon h-10 w-10" }), _jsxs("div", { className: "anyspend-deposit-option-info", children: [_jsx("span", { className: "anyspend-deposit-option-title text-as-primary font-medium", children: "Deposit with QR Code" }), _jsx("p", { className: "anyspend-deposit-option-description text-as-secondary text-xs", children: "Send tokens directly to deposit address" })] })] }), _jsx(ChevronRight, { className: "anyspend-deposit-option-chevron text-as-secondary h-5 w-5" })] }), _jsxs("button", { onClick: handleSelectFiat, className: "anyspend-deposit-option-button anyspend-deposit-fiat-button border-border-primary hover:border-as-brand hover:bg-as-surface-secondary flex w-full items-center justify-between rounded-xl border p-4 text-left transition-all", children: [_jsxs("div", { className: "anyspend-deposit-option-content flex items-center gap-3", children: [_jsx(CreditCardIcon, { className: "anyspend-deposit-option-icon h-10 w-10" }), _jsxs("div", { className: "anyspend-deposit-option-info", children: [_jsx("span", { className: "anyspend-deposit-option-title text-as-primary font-medium", children: "Fund with Fiat" }), _jsx("p", { className: "anyspend-deposit-option-description text-as-secondary text-xs", children: "Pay with card or bank transfer" })] })] }), _jsx(ChevronRight, { className: "anyspend-deposit-option-chevron text-as-secondary h-5 w-5" })] })] }), _jsx(ChainWarningText, { chainId: destinationChainId, className: "mt-2" })] })] }));
|
|
178
|
+
}
|
|
179
|
+
// QR Deposit view
|
|
180
|
+
if (step === "qr-deposit") {
|
|
181
|
+
return (_jsx(QRDeposit, { mode: mode, recipientAddress: recipientAddress, destinationToken: destinationToken, destinationChainId: destinationChainId, depositContractConfig: depositContractConfig, onBack: handleBack, onClose: onClose ?? handleBack }));
|
|
182
|
+
}
|
|
183
|
+
// Check if destination is Hyperliquid
|
|
184
|
+
const isHyperliquidDeposit = destinationChainId === HYPERLIQUID_CHAIN_ID;
|
|
185
|
+
// Deposit view
|
|
186
|
+
return (_jsxs("div", { className: "anyspend-deposit anyspend-deposit-form relative", children: [shouldShowChainSelection && (_jsxs("button", { onClick: handleBack, className: "anyspend-deposit-back-button text-as-secondary hover:text-as-primary absolute left-4 top-4 z-10 flex items-center gap-1", children: [_jsx("svg", { className: "anyspend-deposit-back-icon h-5 w-5", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: _jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M15 19l-7-7 7-7" }) }), _jsx("span", { className: "anyspend-deposit-back-text text-sm", children: "Back" })] })), onClose && (_jsx("button", { onClick: onClose, className: "anyspend-deposit-close-button text-as-secondary hover:text-as-primary absolute right-4 top-4 z-10", children: _jsx("svg", { className: "h-6 w-6", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: _jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M6 18L18 6M6 6l12 12" }) }) })), _jsx("div", { className: cn("anyspend-deposit-form-content", shouldShowChainSelection && "pt-8"), children: isHyperliquidDeposit ? (_jsx(AnySpend, { loadOrder: loadOrder, mode: mode, defaultActiveTab: paymentType, recipientAddress: recipientAddress, sourceChainId: selectedChainId, destinationTokenAddress: destinationToken.address, destinationTokenChainId: destinationChainId, onSuccess: txHash => onSuccess?.(txHash ?? ""), onTokenSelect: onTokenSelect, customUsdInputValues: customUsdInputValues, hideHeader: true, hideBottomNavigation: true, disableUrlParamManagement: true })) : (_jsx(AnySpendCustomExactIn, { loadOrder: loadOrder, mode: mode, recipientAddress: recipientAddress, paymentType: paymentType, sourceTokenAddress: sourceTokenAddress, sourceTokenChainId: selectedChainId, destinationToken: destinationToken, destinationChainId: destinationChainId, orderType: effectiveOrderType, minDestinationAmount: minDestinationAmount, header: header ?? defaultHeader, onSuccess: onSuccess, onOpenCustomModal: onOpenCustomModal, mainFooter: mainFooter, onTokenSelect: onTokenSelect, customUsdInputValues: customUsdInputValues, preferEoa: preferEoa, customExactInConfig: depositContractConfig })) }), _jsx(ChainWarningText, { chainId: destinationChainId, className: "px-4 pb-4" })] }));
|
|
187
|
+
}
|