@oasisprotocol/privana-sdk 0.5.7 → 0.5.8
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/README.md +88 -7
- package/dist/{chunk-FFYLKZ7J.cjs → chunk-EXFISDHQ.cjs} +1223 -101
- package/dist/chunk-EXFISDHQ.cjs.map +1 -0
- package/dist/{chunk-4VOTSHNC.js → chunk-ONXJGUOH.js} +1215 -103
- package/dist/chunk-ONXJGUOH.js.map +1 -0
- package/dist/index.cjs +767 -300
- package/dist/index.cjs.map +1 -1
- package/dist/index.css +1 -1
- package/dist/index.css.map +1 -1
- package/dist/index.d.cts +12 -4
- package/dist/index.d.ts +12 -4
- package/dist/index.js +530 -63
- package/dist/index.js.map +1 -1
- package/dist/on-ramp.cjs +11 -3
- package/dist/on-ramp.d.cts +61 -7
- package/dist/on-ramp.d.ts +61 -7
- package/dist/on-ramp.js +1 -1
- package/dist/{pending-lock-BIMYw4gd.d.cts → pending-lock-DIL2jCaT.d.cts} +33 -1
- package/dist/{pending-lock-BIMYw4gd.d.ts → pending-lock-DIL2jCaT.d.ts} +33 -1
- package/package.json +1 -1
- package/dist/chunk-4VOTSHNC.js.map +0 -1
- package/dist/chunk-FFYLKZ7J.cjs.map +0 -1
package/dist/index.js
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
"use client";
|
|
2
|
-
import { usePrivanaContext, createHostedAuthPendingStorageKey, clearHostedAuthPendingTransaction, HostedAuthRequiredError, HostedAuthError, createPkceVerifier, createPkceChallenge, createHostedAuthState, persistHostedAuthPendingTransaction, parseHostedAuthCallback, readHostedAuthPendingTransaction, HostedAuthStateMismatchError, buildHostedAuthSession, useSafePrivanaContext, usePrivateReadRequest, formatTokenAmount, submitPendingLock, PostDepositLockError, useDepositVerification, useEnsureCorrectChain, getTransactionReceipt, getBlockNumber, waitForTransactionReceipt, canUseBrowserStorage, clampLockAmount, requireDepositLockOwner, getWalletClient, createSignedLockRequest, requireServiceAddress, signWithdrawMessage, signLockMessage, signTransferMessage, signTransferLockedMessage, signModifyLockMessage, cn, stripHostedAuthCallbackParams, AccountingApiError, getBrowserStorageItem, removeBrowserStorageItem, isSignedLockUsable, setBrowserStorageItem, canUseSharedBrowserStorage, DEFAULT_LOCK_DURATION_SECONDS, parseTokenAmount, Skeleton, shortenAddress, formatCountdown,
|
|
3
|
-
export { AccountingApiError, Button, DEFAULT_LOCK_DURATION_SECONDS, DEFAULT_ONRAMP_LOCK_BUFFER, HOSTED_AUTH_CLOCK_SKEW_MS, HostedAuthError, HostedAuthRequiredError, HostedAuthStateMismatchError, HttpClient, LOCK_TYPES, MODIFY_LOCK_TYPES, NETWORK_CONFIG, NetworkError, PostDepositLockError, PrivanaClient, PrivanaProvider, SUPPORTED_CHAINS, SiweAuthProvider, Skeleton, TRANSFER_LOCKED_TYPES, TRANSFER_TYPES, ValidationError, WITHDRAW_FROM_LOCK_TYPES, WITHDRAW_TYPES, applyLockBuffer, applyRefreshResponse, buildHostedAuthSession, buildSiweStatement, buttonVariants, clampLockAmount, clearHostedAuthPendingTransaction, clearPendingLock, createDomain, createHostedAuthPendingStorageKey, createHostedAuthState, createHostedAuthStorageKey, createLockExpiry, createPkceChallenge, createPkceVerifier, createSignedLockRequest, getAccountingContract, getApiUrl, getChainById, getChainId, getExplorerAddressUrl, getExplorerLabel, isHostedAuthRefreshActive, isHostedAuthSessionActive, isSignedLockUsable, loadPendingLock, normalizeAddress, normalizeHex, parseHostedAuthCallback, persistHostedAuthPendingTransaction, readHostedAuthPendingTransaction, readStoredHostedAuthSession, requireDepositLockOwner, requireServiceAddress, savePendingLock, signLockMessage, signModifyLockMessage, signTransferLockedMessage, signTransferMessage, signWithdrawFromLockMessage, signWithdrawMessage, stripHostedAuthCallbackParams, submitPendingLock, syncHostedAuthSessionToClient, useDepositVerification, usePrivanaContext, useSafeAccount, useSafePrivanaContext, useSiweAuth } from './chunk-
|
|
2
|
+
import { usePrivanaContext, createHostedAuthPendingStorageKey, clearHostedAuthPendingTransaction, HostedAuthRequiredError, HostedAuthError, createPkceVerifier, createPkceChallenge, createHostedAuthState, persistHostedAuthPendingTransaction, parseHostedAuthCallback, readHostedAuthPendingTransaction, HostedAuthStateMismatchError, buildHostedAuthSession, useSafePrivanaContext, usePrivateReadRequest, formatTokenAmount, submitPendingLock, PostDepositLockError, useDepositVerification, useEnsureCorrectChain, getTransactionReceipt, getBlockNumber, waitForTransactionReceipt, canUseBrowserStorage, clampLockAmount, requireDepositLockOwner, getWalletClient, createSignedLockRequest, requireServiceAddress, signWithdrawMessage, signLockMessage, signTransferMessage, signTransferLockedMessage, signModifyLockMessage, cn, stripHostedAuthCallbackParams, AccountingApiError, getBrowserStorageItem, removeBrowserStorageItem, isSignedLockUsable, setBrowserStorageItem, resolveProductOnRamp, matchesProductOnRampScope, createProductOnRampOutcomeCallbacks, canUseSharedBrowserStorage, DEFAULT_LOCK_DURATION_SECONDS, isMoonPayProductOnRamp, parseTokenAmount, createProductOnRampFlowSnapshot, Skeleton, shortenAddress, formatCountdown, getExplorerAddressUrl, getExplorerLabel, formatTimeRemaining, getSharedBrowserStorageItem, removeSharedBrowserStorageItem, setSharedBrowserStorageItem, matchesOnRampTransaction, useTransakOnRamp, getTransakMinimumTargetBaseUnits, matchesFrozenOnRampToken, Button, canRetryOnRampVerification, FiatOnRampForm } from './chunk-ONXJGUOH.js';
|
|
3
|
+
export { AccountingApiError, Button, DEFAULT_LOCK_DURATION_SECONDS, DEFAULT_ONRAMP_LOCK_BUFFER, HOSTED_AUTH_CLOCK_SKEW_MS, HostedAuthError, HostedAuthRequiredError, HostedAuthStateMismatchError, HttpClient, LOCK_TYPES, MODIFY_LOCK_TYPES, NETWORK_CONFIG, NetworkError, PostDepositLockError, PrivanaClient, PrivanaProvider, SUPPORTED_CHAINS, SiweAuthProvider, Skeleton, TRANSFER_LOCKED_TYPES, TRANSFER_TYPES, ValidationError, WITHDRAW_FROM_LOCK_TYPES, WITHDRAW_TYPES, applyLockBuffer, applyRefreshResponse, buildHostedAuthSession, buildSiweStatement, buttonVariants, clampLockAmount, clearHostedAuthPendingTransaction, clearPendingLock, createDomain, createHostedAuthPendingStorageKey, createHostedAuthState, createHostedAuthStorageKey, createLockExpiry, createPkceChallenge, createPkceVerifier, createSignedLockRequest, getAccountingContract, getApiUrl, getChainById, getChainId, getExplorerAddressUrl, getExplorerLabel, isHostedAuthRefreshActive, isHostedAuthSessionActive, isSignedLockUsable, loadPendingLock, normalizeAddress, normalizeHex, parseHostedAuthCallback, persistHostedAuthPendingTransaction, readHostedAuthPendingTransaction, readStoredHostedAuthSession, requireDepositLockOwner, requireServiceAddress, savePendingLock, signLockMessage, signModifyLockMessage, signTransferLockedMessage, signTransferMessage, signWithdrawFromLockMessage, signWithdrawMessage, stripHostedAuthCallbackParams, submitPendingLock, syncHostedAuthSessionToClient, useDepositVerification, usePrivanaContext, useSafeAccount, useSafePrivanaContext, useSiweAuth } from './chunk-ONXJGUOH.js';
|
|
4
4
|
import { useState, useRef, useMemo, useCallback, useContext, useEffect, useId } from 'react';
|
|
5
5
|
import { QueryClientContext, useQuery, useQueryClient, useMutation, keepPreviousData } from '@tanstack/react-query';
|
|
6
6
|
import { useAccount, useWalletClient, useConfig, useWriteContract, useSendTransaction, useBalance as useBalance$1, useReadContract } from 'wagmi';
|
|
7
|
-
import { zeroAddress, erc20Abi, formatUnits } from 'viem';
|
|
7
|
+
import { zeroAddress, erc20Abi, formatUnits, parseUnits } from 'viem';
|
|
8
8
|
import { MoonPayProvider, MoonPayContext } from '@moonpay/moonpay-react';
|
|
9
9
|
import * as DialogPrimitive from '@radix-ui/react-dialog';
|
|
10
|
-
import { XIcon } from 'lucide-react';
|
|
10
|
+
import { XIcon, CircleCheckIcon, Loader2 } from 'lucide-react';
|
|
11
11
|
import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
|
|
12
12
|
import { toast } from 'sonner';
|
|
13
13
|
import { QRCodeSVG } from 'qrcode.react';
|
|
@@ -2455,15 +2455,356 @@ function TokenSelectorView({ selectedTokenId, onSelect }) {
|
|
|
2455
2455
|
enabledTokens.length === 0 && /* @__PURE__ */ jsx("p", { className: "text-muted-foreground px-3 py-6 text-center text-sm", children: "No tokens available" })
|
|
2456
2456
|
] }) });
|
|
2457
2457
|
}
|
|
2458
|
+
function assertTransakCheckoutPreconditions({
|
|
2459
|
+
activeIntentId,
|
|
2460
|
+
canOpen,
|
|
2461
|
+
canRecreateSession
|
|
2462
|
+
}) {
|
|
2463
|
+
if (activeIntentId && !canRecreateSession) {
|
|
2464
|
+
throw new Error("Continue signed-intent recovery instead of reopening this checkout");
|
|
2465
|
+
}
|
|
2466
|
+
if (!canOpen) {
|
|
2467
|
+
throw new Error("Card checkout is unavailable; close this purchase and start again");
|
|
2468
|
+
}
|
|
2469
|
+
}
|
|
2470
|
+
function TransakCardWidgetView({
|
|
2471
|
+
token,
|
|
2472
|
+
providerAssetCode,
|
|
2473
|
+
amount,
|
|
2474
|
+
allowance,
|
|
2475
|
+
lockServiceAddress,
|
|
2476
|
+
onCredited,
|
|
2477
|
+
onLockSubmitted,
|
|
2478
|
+
onLockFailed,
|
|
2479
|
+
onLeave,
|
|
2480
|
+
onUnsafeToCloseChange,
|
|
2481
|
+
onActiveFlowChange,
|
|
2482
|
+
useOnRamp = useTransakOnRamp
|
|
2483
|
+
}) {
|
|
2484
|
+
const [actionError, setActionError] = useState(null);
|
|
2485
|
+
const [rowError, setRowError] = useState(null);
|
|
2486
|
+
const [lockSettled, setLockSettled] = useState(false);
|
|
2487
|
+
const [lockError, setLockError] = useState(null);
|
|
2488
|
+
const [ownedTerminal, setOwnedTerminal] = useState(false);
|
|
2489
|
+
const ownedIntentIdRef = useRef(null);
|
|
2490
|
+
const postDepositLock = useMemo(
|
|
2491
|
+
() => allowance ? {
|
|
2492
|
+
serviceAddress: lockServiceAddress,
|
|
2493
|
+
maxAmount: BigInt(allowance.value),
|
|
2494
|
+
lockDuration: allowance.lockDuration
|
|
2495
|
+
} : void 0,
|
|
2496
|
+
[allowance, lockServiceAddress]
|
|
2497
|
+
);
|
|
2498
|
+
const ownsRecord = useCallback(
|
|
2499
|
+
(record) => Boolean(
|
|
2500
|
+
ownedIntentIdRef.current && matchesOnRampTransaction(record, ownedIntentIdRef.current)
|
|
2501
|
+
),
|
|
2502
|
+
[]
|
|
2503
|
+
);
|
|
2504
|
+
const {
|
|
2505
|
+
status,
|
|
2506
|
+
activeIntentId,
|
|
2507
|
+
pending,
|
|
2508
|
+
activeVerificationId,
|
|
2509
|
+
error,
|
|
2510
|
+
finalityProgress,
|
|
2511
|
+
depositAddress,
|
|
2512
|
+
minDepositBaseUnits,
|
|
2513
|
+
selectedToken,
|
|
2514
|
+
isLaunching,
|
|
2515
|
+
isWidgetOpen,
|
|
2516
|
+
canRecreateSession,
|
|
2517
|
+
widget,
|
|
2518
|
+
launch,
|
|
2519
|
+
recreateSession,
|
|
2520
|
+
closeWidget,
|
|
2521
|
+
finishPendingVerification,
|
|
2522
|
+
refreshPending
|
|
2523
|
+
} = useOnRamp({
|
|
2524
|
+
tokenId: token.id,
|
|
2525
|
+
postDepositLock,
|
|
2526
|
+
iframeTitle: "Card checkout",
|
|
2527
|
+
iframeClassName: "h-[680px] w-full border-0",
|
|
2528
|
+
onCredited: (_depositTxHash, record) => {
|
|
2529
|
+
if (!ownsRecord(record)) return;
|
|
2530
|
+
onCredited?.();
|
|
2531
|
+
if (!postDepositLock) {
|
|
2532
|
+
setOwnedTerminal(true);
|
|
2533
|
+
onActiveFlowChange?.(false);
|
|
2534
|
+
}
|
|
2535
|
+
},
|
|
2536
|
+
onLockSubmitted: (_response, record) => {
|
|
2537
|
+
if (!ownsRecord(record)) return;
|
|
2538
|
+
setLockError(null);
|
|
2539
|
+
setLockSettled(true);
|
|
2540
|
+
setOwnedTerminal(true);
|
|
2541
|
+
onActiveFlowChange?.(false);
|
|
2542
|
+
onLockSubmitted?.();
|
|
2543
|
+
},
|
|
2544
|
+
onLockFailed: (nextError, record) => {
|
|
2545
|
+
if (!ownsRecord(record)) return;
|
|
2546
|
+
setLockError(nextError);
|
|
2547
|
+
setOwnedTerminal(true);
|
|
2548
|
+
onActiveFlowChange?.(false);
|
|
2549
|
+
onLockFailed?.(nextError);
|
|
2550
|
+
}
|
|
2551
|
+
});
|
|
2552
|
+
const ownedIntentId = ownedIntentIdRef.current ?? activeIntentId;
|
|
2553
|
+
useEffect(() => {
|
|
2554
|
+
if (activeIntentId && !ownedIntentIdRef.current) {
|
|
2555
|
+
ownedIntentIdRef.current = activeIntentId;
|
|
2556
|
+
}
|
|
2557
|
+
}, [activeIntentId]);
|
|
2558
|
+
let amountBaseUnits;
|
|
2559
|
+
try {
|
|
2560
|
+
amountBaseUnits = parseUnits(amount, token.decimals);
|
|
2561
|
+
} catch {
|
|
2562
|
+
}
|
|
2563
|
+
const minimumTargetBaseUnits = minDepositBaseUnits === void 0 ? void 0 : getTransakMinimumTargetBaseUnits(minDepositBaseUnits);
|
|
2564
|
+
const belowMinimum = amountBaseUnits !== void 0 && minimumTargetBaseUnits !== void 0 && amountBaseUnits < minimumTargetBaseUnits;
|
|
2565
|
+
const minimumUnknown = minimumTargetBaseUnits === void 0;
|
|
2566
|
+
const tokenMismatch = !matchesFrozenOnRampToken(token, selectedToken);
|
|
2567
|
+
const isSettling = status === "awaiting-delivery" || status === "verifying";
|
|
2568
|
+
const lockPending = !!allowance && status === "credited" && !lockSettled && !lockError;
|
|
2569
|
+
const ownedPending = ownedIntentId ? pending.filter((record) => matchesOnRampTransaction(record, ownedIntentId)) : [];
|
|
2570
|
+
const ownedFlowActive = !ownedTerminal && (Boolean(activeIntentId && activeIntentId === ownedIntentId) || ownedPending.length > 0 || lockPending);
|
|
2571
|
+
const canOpen = Boolean(selectedToken && depositAddress && amountBaseUnits && amountBaseUnits > 0n) && !tokenMismatch && !minimumUnknown && !belowMinimum && !isLaunching && !isWidgetOpen && !isSettling && status !== "credited" && (!activeIntentId || canRecreateSession);
|
|
2572
|
+
useEffect(() => {
|
|
2573
|
+
onActiveFlowChange?.(ownedFlowActive);
|
|
2574
|
+
}, [onActiveFlowChange, ownedFlowActive]);
|
|
2575
|
+
const unsafeToClose = isLaunching || lockPending;
|
|
2576
|
+
useEffect(() => {
|
|
2577
|
+
onUnsafeToCloseChange?.(unsafeToClose);
|
|
2578
|
+
return () => onUnsafeToCloseChange?.(false);
|
|
2579
|
+
}, [onUnsafeToCloseChange, unsafeToClose]);
|
|
2580
|
+
const runCheckout = useCallback(async () => {
|
|
2581
|
+
setActionError(null);
|
|
2582
|
+
try {
|
|
2583
|
+
assertTransakCheckoutPreconditions({ activeIntentId, canOpen, canRecreateSession });
|
|
2584
|
+
setLockError(null);
|
|
2585
|
+
setLockSettled(false);
|
|
2586
|
+
setOwnedTerminal(false);
|
|
2587
|
+
if (!activeIntentId) ownedIntentIdRef.current = null;
|
|
2588
|
+
if (activeIntentId) await recreateSession();
|
|
2589
|
+
else await launch({ providerAssetCode, quoteCurrencyAmount: amount });
|
|
2590
|
+
} catch (nextError) {
|
|
2591
|
+
setActionError(
|
|
2592
|
+
nextError instanceof Error ? nextError : new Error("Failed to open card checkout")
|
|
2593
|
+
);
|
|
2594
|
+
}
|
|
2595
|
+
}, [
|
|
2596
|
+
activeIntentId,
|
|
2597
|
+
amount,
|
|
2598
|
+
canOpen,
|
|
2599
|
+
canRecreateSession,
|
|
2600
|
+
launch,
|
|
2601
|
+
providerAssetCode,
|
|
2602
|
+
recreateSession
|
|
2603
|
+
]);
|
|
2604
|
+
const handleClose = useCallback(async () => {
|
|
2605
|
+
setActionError(null);
|
|
2606
|
+
try {
|
|
2607
|
+
await closeWidget();
|
|
2608
|
+
} catch (nextError) {
|
|
2609
|
+
setActionError(
|
|
2610
|
+
nextError instanceof Error ? nextError : new Error("Failed to close card checkout")
|
|
2611
|
+
);
|
|
2612
|
+
}
|
|
2613
|
+
}, [closeWidget]);
|
|
2614
|
+
const handleLeave = useCallback(() => {
|
|
2615
|
+
setActionError(null);
|
|
2616
|
+
onActiveFlowChange?.(false);
|
|
2617
|
+
onLeave?.();
|
|
2618
|
+
}, [onActiveFlowChange, onLeave]);
|
|
2619
|
+
return /* @__PURE__ */ jsxs("div", { className: "bg-muted flex flex-col gap-4 rounded-[10px] p-5", children: [
|
|
2620
|
+
/* @__PURE__ */ jsxs("div", { children: [
|
|
2621
|
+
/* @__PURE__ */ jsx("h2", { className: "text-foreground text-[28px] leading-8 font-medium", children: "Complete your purchase" }),
|
|
2622
|
+
/* @__PURE__ */ jsxs("p", { className: "text-muted-foreground mt-1 text-sm", children: [
|
|
2623
|
+
"Buy ",
|
|
2624
|
+
token.symbol,
|
|
2625
|
+
" and deposit it directly into your Privana balance."
|
|
2626
|
+
] })
|
|
2627
|
+
] }),
|
|
2628
|
+
/* @__PURE__ */ jsxs("div", { className: "border-border bg-card rounded-lg border p-3 text-sm", children: [
|
|
2629
|
+
/* @__PURE__ */ jsxs("p", { className: "text-foreground font-medium", children: [
|
|
2630
|
+
"Target receipt: at least ",
|
|
2631
|
+
amount,
|
|
2632
|
+
" ",
|
|
2633
|
+
token.symbol
|
|
2634
|
+
] }),
|
|
2635
|
+
/* @__PURE__ */ jsx("p", { className: "text-muted-foreground mt-1", children: "In Transak, adjust the fiat amount until \u201CYou receive\u201D is at least this target." }),
|
|
2636
|
+
allowance && /* @__PURE__ */ jsx("p", { className: "text-muted-foreground mt-1", children: "The pre-signed lock is 98% of the target, capped by the service allowance." })
|
|
2637
|
+
] }),
|
|
2638
|
+
widget ? /* @__PURE__ */ jsxs("div", { className: "border-border bg-card overflow-hidden rounded-xl border", children: [
|
|
2639
|
+
/* @__PURE__ */ jsxs("div", { className: "border-border flex items-center justify-between border-b px-4 py-2 text-sm", children: [
|
|
2640
|
+
/* @__PURE__ */ jsx("span", { className: "font-medium", children: "Card checkout" }),
|
|
2641
|
+
/* @__PURE__ */ jsx(Button, { type: "button", variant: "outline", size: "sm", onClick: () => void handleClose(), children: "Close" })
|
|
2642
|
+
] }),
|
|
2643
|
+
widget
|
|
2644
|
+
] }) : status === "credited" && !lockPending && !lockError ? /* @__PURE__ */ jsxs("div", { className: "flex flex-col items-center gap-2 py-8 text-center", children: [
|
|
2645
|
+
/* @__PURE__ */ jsx(CircleCheckIcon, { className: "text-primary size-8", "aria-hidden": true }),
|
|
2646
|
+
/* @__PURE__ */ jsx("p", { className: "text-foreground text-sm font-medium", children: "Purchase credited" }),
|
|
2647
|
+
/* @__PURE__ */ jsxs("p", { className: "text-muted-foreground text-sm", children: [
|
|
2648
|
+
"Your ",
|
|
2649
|
+
token.symbol,
|
|
2650
|
+
" deposit is now available in your balance."
|
|
2651
|
+
] })
|
|
2652
|
+
] }) : !activeIntentId || canRecreateSession ? /* @__PURE__ */ jsxs(Button, { type: "button", disabled: !canOpen, onClick: () => void runCheckout(), children: [
|
|
2653
|
+
isLaunching && /* @__PURE__ */ jsx(Loader2, { className: "animate-spin", "aria-hidden": true }),
|
|
2654
|
+
isLaunching ? "Opening checkout\u2026" : activeIntentId ? "Reopen card checkout" : allowance ? "Sign policy and open checkout" : "Open card checkout"
|
|
2655
|
+
] }) : /* @__PURE__ */ jsx("p", { className: "text-muted-foreground text-sm", children: "This signed purchase is in recovery. Do not open another checkout for it." }),
|
|
2656
|
+
!depositAddress && !error && !actionError && /* @__PURE__ */ jsx("p", { className: "text-muted-foreground text-sm", children: "Preparing your secure deposit address\u2026" }),
|
|
2657
|
+
tokenMismatch && /* @__PURE__ */ jsx("p", { className: "text-destructive text-sm", role: "alert", children: "The token configuration changed. Close this purchase and start again." }),
|
|
2658
|
+
!tokenMismatch && depositAddress && minimumUnknown && !error && !actionError && /* @__PURE__ */ jsx("p", { className: "text-destructive text-sm", role: "alert", children: "The minimum purchase amount is unavailable. Close this purchase and try again." }),
|
|
2659
|
+
belowMinimum && minimumTargetBaseUnits !== void 0 && /* @__PURE__ */ jsxs("p", { className: "text-destructive text-sm", role: "alert", children: [
|
|
2660
|
+
"Minimum target is ",
|
|
2661
|
+
formatUnits(minimumTargetBaseUnits, token.decimals),
|
|
2662
|
+
" ",
|
|
2663
|
+
token.symbol,
|
|
2664
|
+
", including a 5% delivery buffer."
|
|
2665
|
+
] }),
|
|
2666
|
+
isSettling && pending.length === 0 && /* @__PURE__ */ jsxs("p", { className: "text-muted-foreground flex items-center gap-2 text-sm", children: [
|
|
2667
|
+
/* @__PURE__ */ jsx(Loader2, { className: "size-4 animate-spin", "aria-hidden": true }),
|
|
2668
|
+
"Verifying your purchase\u2026"
|
|
2669
|
+
] }),
|
|
2670
|
+
lockPending && /* @__PURE__ */ jsxs("p", { className: "text-muted-foreground flex items-center gap-2 text-sm", children: [
|
|
2671
|
+
/* @__PURE__ */ jsx(Loader2, { className: "size-4 animate-spin", "aria-hidden": true }),
|
|
2672
|
+
"Purchase credited. Locking your funds\u2026"
|
|
2673
|
+
] }),
|
|
2674
|
+
pending.length > 0 && /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-2", children: [
|
|
2675
|
+
/* @__PURE__ */ jsx("p", { className: "text-foreground text-sm font-medium", children: "Validating purchases" }),
|
|
2676
|
+
pending.map((record) => {
|
|
2677
|
+
const isActivelyVerifying = record.transaction_id === activeVerificationId;
|
|
2678
|
+
const progress = parseFinalityProgress(finalityProgress[record.transaction_id]);
|
|
2679
|
+
const showRetry = canRetryOnRampVerification(record, activeVerificationId);
|
|
2680
|
+
return /* @__PURE__ */ jsxs(
|
|
2681
|
+
"div",
|
|
2682
|
+
{
|
|
2683
|
+
className: "border-border flex flex-col gap-2 rounded-md border p-2",
|
|
2684
|
+
children: [
|
|
2685
|
+
/* @__PURE__ */ jsxs("p", { className: "text-muted-foreground flex items-center gap-1 text-xs", children: [
|
|
2686
|
+
/* @__PURE__ */ jsx(Loader2, { className: "size-3 animate-spin", "aria-hidden": true }),
|
|
2687
|
+
record.on_chain_tx_hash ? progress ?? (isActivelyVerifying ? "Verifying\u2026" : "Ready to verify") : "Waiting for provider delivery\u2026"
|
|
2688
|
+
] }),
|
|
2689
|
+
rowError?.id === record.transaction_id && /* @__PURE__ */ jsx("p", { className: "text-destructive text-xs", children: rowError.message }),
|
|
2690
|
+
showRetry && /* @__PURE__ */ jsx(
|
|
2691
|
+
Button,
|
|
2692
|
+
{
|
|
2693
|
+
type: "button",
|
|
2694
|
+
variant: "outline",
|
|
2695
|
+
size: "sm",
|
|
2696
|
+
onClick: async () => {
|
|
2697
|
+
setRowError(null);
|
|
2698
|
+
try {
|
|
2699
|
+
await finishPendingVerification(record);
|
|
2700
|
+
} catch (nextError) {
|
|
2701
|
+
setRowError({
|
|
2702
|
+
id: record.transaction_id,
|
|
2703
|
+
message: nextError instanceof Error ? nextError.message : "Verification failed"
|
|
2704
|
+
});
|
|
2705
|
+
}
|
|
2706
|
+
},
|
|
2707
|
+
children: "Retry verification"
|
|
2708
|
+
}
|
|
2709
|
+
),
|
|
2710
|
+
!record.on_chain_tx_hash && /* @__PURE__ */ jsx(
|
|
2711
|
+
Button,
|
|
2712
|
+
{
|
|
2713
|
+
type: "button",
|
|
2714
|
+
variant: "outline",
|
|
2715
|
+
size: "sm",
|
|
2716
|
+
onClick: () => void refreshPending(),
|
|
2717
|
+
children: "Refresh delivery"
|
|
2718
|
+
}
|
|
2719
|
+
)
|
|
2720
|
+
]
|
|
2721
|
+
},
|
|
2722
|
+
record.transaction_id
|
|
2723
|
+
);
|
|
2724
|
+
})
|
|
2725
|
+
] }),
|
|
2726
|
+
onLeave && ownedFlowActive && !unsafeToClose && /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-1", children: [
|
|
2727
|
+
/* @__PURE__ */ jsx(Button, { type: "button", variant: "outline", onClick: handleLeave, children: "Leave checkout" }),
|
|
2728
|
+
/* @__PURE__ */ jsx("p", { className: "text-muted-foreground text-xs", children: "Privana will keep this signed purchase available for exact recovery." })
|
|
2729
|
+
] }),
|
|
2730
|
+
(actionError ?? error) && /* @__PURE__ */ jsx("p", { className: "text-destructive text-sm", role: "alert", children: (actionError ?? error)?.message }),
|
|
2731
|
+
lockError && /* @__PURE__ */ jsxs("p", { className: "text-destructive text-sm", role: "alert", children: [
|
|
2732
|
+
"Purchase credited, but locking the funds failed: ",
|
|
2733
|
+
lockError.message
|
|
2734
|
+
] })
|
|
2735
|
+
] });
|
|
2736
|
+
}
|
|
2737
|
+
function parseFinalityProgress(message) {
|
|
2738
|
+
if (!message) return null;
|
|
2739
|
+
const match = message.match(/(\d+\/\d+)\s+confirmations/i);
|
|
2740
|
+
return match ? `${match[1]} confirmations` : null;
|
|
2741
|
+
}
|
|
2458
2742
|
function CreditCardWidgetView({
|
|
2459
2743
|
token,
|
|
2744
|
+
onRamp,
|
|
2460
2745
|
amount,
|
|
2461
2746
|
allowance,
|
|
2747
|
+
lockServiceAddress,
|
|
2462
2748
|
onCredited,
|
|
2463
2749
|
onLockSubmitted,
|
|
2464
|
-
onLockFailed
|
|
2750
|
+
onLockFailed,
|
|
2751
|
+
onLeave,
|
|
2752
|
+
onUnsafeToCloseChange,
|
|
2753
|
+
onActiveFlowChange
|
|
2754
|
+
}) {
|
|
2755
|
+
if (onRamp.unavailableReason || !token || !onRamp.provider || !onRamp.providerAssetCode) {
|
|
2756
|
+
return /* @__PURE__ */ jsxs("div", { className: "bg-muted flex flex-col gap-2 rounded-[10px] p-5", children: [
|
|
2757
|
+
/* @__PURE__ */ jsx("h2", { className: "text-foreground text-[28px] leading-8 font-medium", children: "Card purchases unavailable" }),
|
|
2758
|
+
/* @__PURE__ */ jsx("p", { className: "text-destructive text-sm", children: onRamp.unavailableReason ?? "The card on-ramp is not configured for this token." })
|
|
2759
|
+
] });
|
|
2760
|
+
}
|
|
2761
|
+
if (onRamp.provider === "transak") {
|
|
2762
|
+
return /* @__PURE__ */ jsx(
|
|
2763
|
+
TransakCardWidgetView,
|
|
2764
|
+
{
|
|
2765
|
+
token,
|
|
2766
|
+
providerAssetCode: onRamp.providerAssetCode,
|
|
2767
|
+
amount,
|
|
2768
|
+
allowance,
|
|
2769
|
+
lockServiceAddress,
|
|
2770
|
+
onCredited,
|
|
2771
|
+
onLockSubmitted,
|
|
2772
|
+
onLockFailed,
|
|
2773
|
+
onLeave,
|
|
2774
|
+
onUnsafeToCloseChange,
|
|
2775
|
+
onActiveFlowChange
|
|
2776
|
+
}
|
|
2777
|
+
);
|
|
2778
|
+
}
|
|
2779
|
+
return /* @__PURE__ */ jsx(
|
|
2780
|
+
MoonPayCardWidgetView,
|
|
2781
|
+
{
|
|
2782
|
+
token,
|
|
2783
|
+
amount,
|
|
2784
|
+
allowance,
|
|
2785
|
+
lockServiceAddress,
|
|
2786
|
+
onCredited,
|
|
2787
|
+
onLockSubmitted,
|
|
2788
|
+
onLockFailed,
|
|
2789
|
+
onLeaveFlow: onLeave,
|
|
2790
|
+
onUnsafeToCloseChange,
|
|
2791
|
+
onActiveFlowChange
|
|
2792
|
+
}
|
|
2793
|
+
);
|
|
2794
|
+
}
|
|
2795
|
+
function MoonPayCardWidgetView({
|
|
2796
|
+
token,
|
|
2797
|
+
amount,
|
|
2798
|
+
allowance,
|
|
2799
|
+
lockServiceAddress,
|
|
2800
|
+
onCredited,
|
|
2801
|
+
onLockSubmitted,
|
|
2802
|
+
onLockFailed,
|
|
2803
|
+
onLeaveFlow,
|
|
2804
|
+
onUnsafeToCloseChange,
|
|
2805
|
+
onActiveFlowChange
|
|
2465
2806
|
}) {
|
|
2466
|
-
const moonpayCurrencyCode = token
|
|
2807
|
+
const moonpayCurrencyCode = token.moonpayCurrencyCode;
|
|
2467
2808
|
const containerRef = useRef(null);
|
|
2468
2809
|
const [widgetTheme, setWidgetTheme] = useState();
|
|
2469
2810
|
useEffect(() => {
|
|
@@ -2471,26 +2812,32 @@ function CreditCardWidgetView({
|
|
|
2471
2812
|
}, []);
|
|
2472
2813
|
return /* @__PURE__ */ jsxs("div", { ref: containerRef, className: "bg-muted flex flex-col gap-6 rounded-[10px] p-5", children: [
|
|
2473
2814
|
/* @__PURE__ */ jsx("h2", { className: "text-foreground text-[28px] leading-8 font-medium", children: "Complete your purchase" }),
|
|
2474
|
-
|
|
2815
|
+
moonpayCurrencyCode ? /* @__PURE__ */ jsx(
|
|
2475
2816
|
FiatOnRampForm,
|
|
2476
2817
|
{
|
|
2477
2818
|
tokenId: token.id,
|
|
2819
|
+
frozenToken: token,
|
|
2478
2820
|
currencyCode: moonpayCurrencyCode,
|
|
2479
2821
|
quoteCurrencyAmount: amount || void 0,
|
|
2480
2822
|
lockAmount: true,
|
|
2481
2823
|
variant: "embedded",
|
|
2482
2824
|
autoStart: true,
|
|
2483
2825
|
theme: widgetTheme,
|
|
2826
|
+
onlyRouteActiveIntentCallbacks: true,
|
|
2827
|
+
onUnsafeToCloseChange,
|
|
2828
|
+
onActiveFlowChange,
|
|
2484
2829
|
postDepositLock: allowance ? {
|
|
2830
|
+
serviceAddress: lockServiceAddress,
|
|
2485
2831
|
maxAmount: BigInt(allowance.value),
|
|
2486
2832
|
lockDuration: allowance.lockDuration
|
|
2487
2833
|
} : void 0,
|
|
2488
2834
|
onCredited,
|
|
2489
2835
|
onLockSubmitted,
|
|
2490
|
-
onLockFailed
|
|
2836
|
+
onLockFailed,
|
|
2837
|
+
onLeaveFlow
|
|
2491
2838
|
}
|
|
2492
2839
|
) : /* @__PURE__ */ jsxs("p", { className: "text-muted-foreground text-sm", children: [
|
|
2493
|
-
token
|
|
2840
|
+
token.symbol,
|
|
2494
2841
|
" isn\u2019t available for card purchases yet."
|
|
2495
2842
|
] })
|
|
2496
2843
|
] });
|
|
@@ -2799,7 +3146,7 @@ function CopyIcon() {
|
|
|
2799
3146
|
}
|
|
2800
3147
|
);
|
|
2801
3148
|
}
|
|
2802
|
-
function
|
|
3149
|
+
function CircleCheckIcon2() {
|
|
2803
3150
|
return /* @__PURE__ */ jsxs("svg", { width: "20", height: "20", viewBox: "0 0 20 20", fill: "none", children: [
|
|
2804
3151
|
/* @__PURE__ */ jsx("circle", { cx: "10", cy: "10", r: "9", stroke: "currentColor", strokeWidth: "1.5" }),
|
|
2805
3152
|
/* @__PURE__ */ jsx(
|
|
@@ -2918,7 +3265,7 @@ function PolicyTermRow({
|
|
|
2918
3265
|
"mt-0.5 shrink-0",
|
|
2919
3266
|
kind === "permission" ? "text-emerald-500" : "text-orange-500"
|
|
2920
3267
|
),
|
|
2921
|
-
children: kind === "permission" ? /* @__PURE__ */ jsx(
|
|
3268
|
+
children: kind === "permission" ? /* @__PURE__ */ jsx(CircleCheckIcon2, {}) : /* @__PURE__ */ jsx(CircleXIcon, {})
|
|
2922
3269
|
}
|
|
2923
3270
|
),
|
|
2924
3271
|
/* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-1", children: [
|
|
@@ -2978,6 +3325,7 @@ function AllowancePolicySection({
|
|
|
2978
3325
|
function DepositView({
|
|
2979
3326
|
source,
|
|
2980
3327
|
selectedToken,
|
|
3328
|
+
onRamp,
|
|
2981
3329
|
amount,
|
|
2982
3330
|
allowance,
|
|
2983
3331
|
externalMinimum,
|
|
@@ -2996,6 +3344,8 @@ function DepositView({
|
|
|
2996
3344
|
const isConnectedSource = source === "connected";
|
|
2997
3345
|
const isExternal = source === "external";
|
|
2998
3346
|
const isCreditCard = source === "credit-card";
|
|
3347
|
+
const isMoonPayCard = isCreditCard && isMoonPayProductOnRamp(onRamp);
|
|
3348
|
+
const isTransakCard = isCreditCard && onRamp.provider === "transak";
|
|
2999
3349
|
const isNative = selectedToken?.contract === zeroAddress;
|
|
3000
3350
|
const { data: nativeBalanceData } = useBalance$1({
|
|
3001
3351
|
address,
|
|
@@ -3019,15 +3369,15 @@ function DepositView({
|
|
|
3019
3369
|
} = useMoonpayLimits({
|
|
3020
3370
|
currencyCode: selectedToken?.moonpayCurrencyCode,
|
|
3021
3371
|
apiBaseUrl: networkConfig.moonpayApiUrl,
|
|
3022
|
-
enabled:
|
|
3372
|
+
enabled: isMoonPayCard
|
|
3023
3373
|
});
|
|
3024
3374
|
const hasValidAmount = !!amount && parseFloat(amount) > 0;
|
|
3025
|
-
const maxAmountDecimals =
|
|
3375
|
+
const maxAmountDecimals = isMoonPayCard ? 2 : selectedToken?.decimals;
|
|
3026
3376
|
const tooManyDecimals = hasValidAmount && maxAmountDecimals != null && amount.includes(".") && amount.split(".")[1].length > maxAmountDecimals;
|
|
3027
3377
|
const exceedsBalance = isConnectedSource && hasValidAmount && !tooManyDecimals && !!selectedToken && walletBalance != null && parseTokenAmount(amount, selectedToken.decimals) > walletBalance;
|
|
3028
|
-
const belowMoonpayMin =
|
|
3029
|
-
const moonpayLimitsUnready =
|
|
3030
|
-
const creditCardUnavailable = isCreditCard && !!
|
|
3378
|
+
const belowMoonpayMin = isMoonPayCard && hasValidAmount && moonpayMinBuy != null && parseFloat(amount) < moonpayMinBuy;
|
|
3379
|
+
const moonpayLimitsUnready = isMoonPayCard && !!onRamp.providerAssetCode && moonpayMinBuy == null;
|
|
3380
|
+
const creditCardUnavailable = isCreditCard && !!onRamp.unavailableReason;
|
|
3031
3381
|
const externalTokenUnavailable = isExternal && !!selectedToken && isNative;
|
|
3032
3382
|
const externalMinimumRequired = isExternal && !!allowance && !!selectedToken;
|
|
3033
3383
|
const externalMinimumLoading = externalMinimumRequired && externalMinimum === void 0;
|
|
@@ -3042,8 +3392,8 @@ function DepositView({
|
|
|
3042
3392
|
};
|
|
3043
3393
|
return /* @__PURE__ */ jsxs("div", { className: "bg-muted flex flex-col gap-6 rounded-[10px] p-5", children: [
|
|
3044
3394
|
isCreditCard ? /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-2", children: [
|
|
3045
|
-
/* @__PURE__ */ jsx("h2", { className: "text-foreground text-[28px] leading-8 font-medium", children: "Buy with
|
|
3046
|
-
/* @__PURE__ */ jsx("p", { className: "text-muted-foreground text-sm", children: "Enter your deposit amount and proceed to sign a policy." })
|
|
3395
|
+
/* @__PURE__ */ jsx("h2", { className: "text-foreground text-[28px] leading-8 font-medium", children: "Buy with card and deposit" }),
|
|
3396
|
+
/* @__PURE__ */ jsx("p", { className: "text-muted-foreground text-sm", children: isTransakCard ? "Enter your target deposit amount and continue." : "Enter your deposit amount and proceed to sign a policy." })
|
|
3047
3397
|
] }) : /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-2", children: [
|
|
3048
3398
|
/* @__PURE__ */ jsxs("h2", { className: "text-foreground text-[28px] leading-8 font-medium", children: [
|
|
3049
3399
|
"Deposit from ",
|
|
@@ -3058,7 +3408,7 @@ function DepositView({
|
|
|
3058
3408
|
{
|
|
3059
3409
|
type: "button",
|
|
3060
3410
|
onClick: onSelectToken,
|
|
3061
|
-
disabled: isSubmitting,
|
|
3411
|
+
disabled: isSubmitting || isCreditCard && onRamp.tokenSelectionLocked,
|
|
3062
3412
|
className: "border-border bg-input flex w-full cursor-pointer items-center gap-3 rounded-lg border p-3 text-left disabled:cursor-not-allowed disabled:opacity-50",
|
|
3063
3413
|
children: [
|
|
3064
3414
|
selectedToken ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
@@ -3071,7 +3421,7 @@ function DepositView({
|
|
|
3071
3421
|
] })
|
|
3072
3422
|
] })
|
|
3073
3423
|
] }) : /* @__PURE__ */ jsx("span", { className: "text-muted-foreground flex-1 text-sm", children: "Select token" }),
|
|
3074
|
-
/* @__PURE__ */ jsx("div", { className: "text-muted-foreground flex h-5 w-5 items-center justify-center", children: /* @__PURE__ */ jsx(ChevronRightIcon, {}) })
|
|
3424
|
+
(!isCreditCard || !onRamp.tokenSelectionLocked) && /* @__PURE__ */ jsx("div", { className: "text-muted-foreground flex h-5 w-5 items-center justify-center", children: /* @__PURE__ */ jsx(ChevronRightIcon, {}) })
|
|
3075
3425
|
]
|
|
3076
3426
|
}
|
|
3077
3427
|
)
|
|
@@ -3141,12 +3491,9 @@ function DepositView({
|
|
|
3141
3491
|
] }),
|
|
3142
3492
|
externalMinimumLoading && /* @__PURE__ */ jsx("p", { className: "text-muted-foreground text-sm", children: "Checking minimum deposit\u2026" }),
|
|
3143
3493
|
externalMinimumUnavailable && /* @__PURE__ */ jsx("p", { className: "text-destructive text-sm", children: "Couldn\u2019t load the minimum deposit. Please try again." }),
|
|
3144
|
-
|
|
3145
|
-
|
|
3146
|
-
creditCardUnavailable && /* @__PURE__ */
|
|
3147
|
-
selectedToken?.symbol ?? "This token",
|
|
3148
|
-
" isn\u2019t available for card purchases yet."
|
|
3149
|
-
] }),
|
|
3494
|
+
isMoonPayCard && moonpayLimitsError && /* @__PURE__ */ jsx("p", { className: "text-destructive text-sm", children: "Couldn\u2019t load purchase limits. Please try again." }),
|
|
3495
|
+
isMoonPayCard && moonpayLimitsLoading && /* @__PURE__ */ jsx("p", { className: "text-muted-foreground text-sm", children: "Checking purchase limits\u2026" }),
|
|
3496
|
+
creditCardUnavailable && /* @__PURE__ */ jsx("p", { className: "text-destructive text-sm", children: onRamp.unavailableReason }),
|
|
3150
3497
|
externalTokenUnavailable && /* @__PURE__ */ jsxs("p", { className: "text-destructive text-sm", children: [
|
|
3151
3498
|
selectedToken?.symbol ?? "This token",
|
|
3152
3499
|
" can\u2019t be used for external deposits. Choose an ERC20 token."
|
|
@@ -3173,7 +3520,7 @@ function DepositView({
|
|
|
3173
3520
|
if (selectedToken) onSubmit({ source, tokenId: selectedToken.id, amount });
|
|
3174
3521
|
},
|
|
3175
3522
|
className: "bg-primary text-primary-foreground hover:bg-primary/90 flex h-10 w-full cursor-pointer items-center justify-center rounded-[10px] px-3 py-2 text-sm font-medium transition-colors disabled:cursor-not-allowed disabled:opacity-50",
|
|
3176
|
-
children: needsConnect ? "Connect Wallet" : allowance ? "Sign Policy and Deposit" : "Deposit"
|
|
3523
|
+
children: needsConnect ? "Connect Wallet" : isTransakCard ? "Continue" : allowance ? "Sign Policy and Deposit" : "Deposit"
|
|
3177
3524
|
}
|
|
3178
3525
|
)
|
|
3179
3526
|
] });
|
|
@@ -3485,9 +3832,11 @@ function ExternalDepositView({
|
|
|
3485
3832
|
] })
|
|
3486
3833
|
] });
|
|
3487
3834
|
}
|
|
3488
|
-
function MoonPayGate({
|
|
3489
|
-
|
|
3490
|
-
|
|
3835
|
+
function MoonPayGate({
|
|
3836
|
+
enabled,
|
|
3837
|
+
apiKey,
|
|
3838
|
+
children
|
|
3839
|
+
}) {
|
|
3491
3840
|
if (!enabled || !apiKey) return /* @__PURE__ */ jsx(Fragment, { children });
|
|
3492
3841
|
return /* @__PURE__ */ jsx(MoonPayProvider, { apiKey, children });
|
|
3493
3842
|
}
|
|
@@ -3574,15 +3923,52 @@ function DepositModalContent({
|
|
|
3574
3923
|
onCloseBlockedChange,
|
|
3575
3924
|
onExit
|
|
3576
3925
|
}) {
|
|
3577
|
-
const {
|
|
3926
|
+
const {
|
|
3927
|
+
serviceName,
|
|
3928
|
+
enabledTokens,
|
|
3929
|
+
defaultToken,
|
|
3930
|
+
hostedAuthConfig,
|
|
3931
|
+
serviceAddress,
|
|
3932
|
+
getChainById: getChainById2,
|
|
3933
|
+
getTokenById,
|
|
3934
|
+
networkConfig,
|
|
3935
|
+
onRamp
|
|
3936
|
+
} = usePrivanaContext();
|
|
3578
3937
|
const { address } = useAccount();
|
|
3938
|
+
const { privateReadQueryScope } = usePrivateReadRequest();
|
|
3939
|
+
const [privateReadApiUrl, accountingChainId, beneficiaryAddress] = privateReadQueryScope;
|
|
3579
3940
|
const appName = serviceName ?? "Privana";
|
|
3580
3941
|
const [activeTab, setActiveTab] = useState(defaultTab);
|
|
3581
3942
|
const [view, setView] = useState("method");
|
|
3582
3943
|
const [source, setSource] = useState("connected");
|
|
3583
3944
|
const [selectedTokenId, setSelectedTokenId] = useState(defaultToken?.id ?? "");
|
|
3584
3945
|
const [amount, setAmount] = useState("");
|
|
3585
|
-
const
|
|
3946
|
+
const [cardFlow, setCardFlow] = useState(null);
|
|
3947
|
+
const [cardFlowActive, setCardFlowActive] = useState(false);
|
|
3948
|
+
const [cardUnsafeToClose, setCardUnsafeToClose] = useState(false);
|
|
3949
|
+
const nextCardFlowId = useRef(0);
|
|
3950
|
+
const stateSelectedToken = enabledTokens.find((t) => t.id === selectedTokenId) ?? defaultToken;
|
|
3951
|
+
const cardOnRamp = useMemo(
|
|
3952
|
+
() => resolveProductOnRamp({
|
|
3953
|
+
config: onRamp,
|
|
3954
|
+
enabledTokens,
|
|
3955
|
+
legacyToken: stateSelectedToken,
|
|
3956
|
+
moonpayApiKey: networkConfig.moonpayApiKey
|
|
3957
|
+
}),
|
|
3958
|
+
[enabledTokens, networkConfig.moonpayApiKey, onRamp, stateSelectedToken]
|
|
3959
|
+
);
|
|
3960
|
+
const cardOnRampScope = useMemo(
|
|
3961
|
+
() => ({
|
|
3962
|
+
apiUrl: privateReadApiUrl,
|
|
3963
|
+
accountingChainId,
|
|
3964
|
+
accountingContract: networkConfig.accountingContract,
|
|
3965
|
+
beneficiaryAddress
|
|
3966
|
+
}),
|
|
3967
|
+
[accountingChainId, beneficiaryAddress, networkConfig.accountingContract, privateReadApiUrl]
|
|
3968
|
+
);
|
|
3969
|
+
const mountedCardFlow = cardFlow && matchesProductOnRampScope(cardFlow.scope, cardOnRampScope) ? cardFlow : null;
|
|
3970
|
+
const displayedCardOnRamp = view === "credit-card-widget" && mountedCardFlow ? mountedCardFlow.selection : cardOnRamp;
|
|
3971
|
+
const selectedToken = source === "credit-card" ? displayedCardOnRamp.token : stateSelectedToken;
|
|
3586
3972
|
const externalDepositAddress = useDepositAddress({
|
|
3587
3973
|
enabled: source === "external" && (view === "deposit" || view === "external-deposit")
|
|
3588
3974
|
});
|
|
@@ -3596,6 +3982,9 @@ function DepositModalContent({
|
|
|
3596
3982
|
setView("method");
|
|
3597
3983
|
setAmount("");
|
|
3598
3984
|
setSelectedTokenId("");
|
|
3985
|
+
setCardFlow(null);
|
|
3986
|
+
setCardFlowActive(false);
|
|
3987
|
+
setCardUnsafeToClose(false);
|
|
3599
3988
|
}
|
|
3600
3989
|
}, [address, hostedAuthConfig]);
|
|
3601
3990
|
const openDeposit = (next) => {
|
|
@@ -3618,9 +4007,33 @@ function DepositModalContent({
|
|
|
3618
4007
|
}
|
|
3619
4008
|
};
|
|
3620
4009
|
const finishCardPurchase = () => {
|
|
4010
|
+
setCardFlowActive(false);
|
|
4011
|
+
setCardUnsafeToClose(false);
|
|
3621
4012
|
setAmount("");
|
|
3622
4013
|
onDepositSuccess?.();
|
|
3623
4014
|
};
|
|
4015
|
+
const leaveCardPurchase = useCallback(() => {
|
|
4016
|
+
setCardFlow(null);
|
|
4017
|
+
setCardFlowActive(false);
|
|
4018
|
+
setCardUnsafeToClose(false);
|
|
4019
|
+
setAmount("");
|
|
4020
|
+
setView("deposit");
|
|
4021
|
+
}, []);
|
|
4022
|
+
useEffect(() => {
|
|
4023
|
+
if (cardFlow && !matchesProductOnRampScope(cardFlow.scope, cardOnRampScope)) {
|
|
4024
|
+
leaveCardPurchase();
|
|
4025
|
+
}
|
|
4026
|
+
}, [cardFlow, cardOnRampScope, leaveCardPurchase]);
|
|
4027
|
+
const cardOutcomeCallbacks = mountedCardFlow ? createProductOnRampOutcomeCallbacks({
|
|
4028
|
+
requiresLock: mountedCardFlow.requiresLock,
|
|
4029
|
+
onComplete: finishCardPurchase,
|
|
4030
|
+
onLockFailed: (err) => {
|
|
4031
|
+
setCardFlowActive(false);
|
|
4032
|
+
setCardUnsafeToClose(false);
|
|
4033
|
+
setLockFailure(err);
|
|
4034
|
+
onLockFailed?.(err);
|
|
4035
|
+
}
|
|
4036
|
+
}) : null;
|
|
3624
4037
|
const {
|
|
3625
4038
|
txHash,
|
|
3626
4039
|
isGettingAddress,
|
|
@@ -3690,7 +4103,7 @@ function DepositModalContent({
|
|
|
3690
4103
|
setView("deposit");
|
|
3691
4104
|
}
|
|
3692
4105
|
}, [allowance, externalLock.session, view]);
|
|
3693
|
-
const isUnsafeToClose = (isGettingAddress || isSendingTransaction) && !cancelled || externalLock.isSigning || externalLock.isSubmittingLock;
|
|
4106
|
+
const isUnsafeToClose = (isGettingAddress || isSendingTransaction) && !cancelled || externalLock.isSigning || externalLock.isSubmittingLock || cardUnsafeToClose;
|
|
3694
4107
|
useEffect(() => {
|
|
3695
4108
|
onCloseBlockedChange?.(isUnsafeToClose);
|
|
3696
4109
|
}, [isUnsafeToClose, onCloseBlockedChange]);
|
|
@@ -3733,6 +4146,28 @@ function DepositModalContent({
|
|
|
3733
4146
|
return;
|
|
3734
4147
|
}
|
|
3735
4148
|
if (args.source === "credit-card") {
|
|
4149
|
+
if (cardFlow && cardFlowActive) {
|
|
4150
|
+
setView("credit-card-widget");
|
|
4151
|
+
return;
|
|
4152
|
+
}
|
|
4153
|
+
try {
|
|
4154
|
+
setCardFlow(
|
|
4155
|
+
createProductOnRampFlowSnapshot({
|
|
4156
|
+
id: ++nextCardFlowId.current,
|
|
4157
|
+
selection: cardOnRamp,
|
|
4158
|
+
amount: args.amount,
|
|
4159
|
+
allowance,
|
|
4160
|
+
lockServiceAddress: serviceAddress,
|
|
4161
|
+
moonpayApiKey: networkConfig.moonpayApiKey,
|
|
4162
|
+
scope: cardOnRampScope
|
|
4163
|
+
})
|
|
4164
|
+
);
|
|
4165
|
+
} catch (error) {
|
|
4166
|
+
toast.error(error instanceof Error ? error.message : "Card purchase is unavailable");
|
|
4167
|
+
return;
|
|
4168
|
+
}
|
|
4169
|
+
setCardFlowActive(false);
|
|
4170
|
+
setCardUnsafeToClose(false);
|
|
3736
4171
|
setView("credit-card-widget");
|
|
3737
4172
|
return;
|
|
3738
4173
|
}
|
|
@@ -3810,6 +4245,12 @@ function DepositModalContent({
|
|
|
3810
4245
|
setCancelled(false);
|
|
3811
4246
|
resetDeposit();
|
|
3812
4247
|
if (view === "external-deposit") setView("deposit");
|
|
4248
|
+
if (view === "credit-card-widget") {
|
|
4249
|
+
setCardFlow(null);
|
|
4250
|
+
setCardFlowActive(false);
|
|
4251
|
+
setCardUnsafeToClose(false);
|
|
4252
|
+
setView("deposit");
|
|
4253
|
+
}
|
|
3813
4254
|
};
|
|
3814
4255
|
const handleExternalLockRetry = () => {
|
|
3815
4256
|
externalLock.retryAfterCredit().catch((err) => {
|
|
@@ -3833,12 +4274,20 @@ function DepositModalContent({
|
|
|
3833
4274
|
retryVerification().catch(() => {
|
|
3834
4275
|
});
|
|
3835
4276
|
};
|
|
3836
|
-
const back = view === "external-deposit" ? { to: "deposit", label: "Deposit from External Wallet" } : view === "credit-card-widget" ? { to: "deposit", label: "Buy with
|
|
4277
|
+
const back = view === "external-deposit" ? { to: "deposit", label: "Deposit from External Wallet" } : view === "credit-card-widget" ? { to: "deposit", label: "Buy with card and deposit" } : view === "select-token" ? { to: "deposit", label: "Deposit" } : { to: "method", label: "Deposit Method" };
|
|
3837
4278
|
const goBack = () => {
|
|
3838
4279
|
if (view === "external-deposit" && externalLock.session) {
|
|
3839
4280
|
toast.error("Cancel the active deposit from the address screen before going back");
|
|
3840
4281
|
return;
|
|
3841
4282
|
}
|
|
4283
|
+
if (view === "credit-card-widget" && (cardUnsafeToClose || cardFlowActive)) {
|
|
4284
|
+
toast.error("Finish or recover the active card purchase before going back");
|
|
4285
|
+
return;
|
|
4286
|
+
}
|
|
4287
|
+
if (view === "credit-card-widget") {
|
|
4288
|
+
setCardFlow(null);
|
|
4289
|
+
setCardUnsafeToClose(false);
|
|
4290
|
+
}
|
|
3842
4291
|
if (back.to === "method") {
|
|
3843
4292
|
setAmount("");
|
|
3844
4293
|
setSelectedTokenId("");
|
|
@@ -3924,8 +4373,8 @@ function DepositModalContent({
|
|
|
3924
4373
|
] }),
|
|
3925
4374
|
activeView === "method" && /* @__PURE__ */ jsxs("div", { className: "bg-muted flex flex-col gap-6 rounded-[10px] p-5", children: [
|
|
3926
4375
|
/* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-2", children: [
|
|
3927
|
-
/* @__PURE__ */ jsx("h2", { className: "text-foreground text-[28px] leading-8 font-medium", children: activeTab === "crypto" ? "Choose the deposit method" : "Buy with
|
|
3928
|
-
/* @__PURE__ */ jsx("p", { className: "text-muted-foreground text-sm", children: activeTab === "crypto" ? "Choose the deposit method." : "
|
|
4376
|
+
/* @__PURE__ */ jsx("h2", { className: "text-foreground text-[28px] leading-8 font-medium", children: activeTab === "crypto" ? "Choose the deposit method" : "Buy with card and deposit" }),
|
|
4377
|
+
/* @__PURE__ */ jsx("p", { className: "text-muted-foreground text-sm", children: activeTab === "crypto" ? "Choose the deposit method." : "Buy crypto by card and deposit it into your account." })
|
|
3929
4378
|
] }),
|
|
3930
4379
|
/* @__PURE__ */ jsx(MethodTabs, { activeTab, onTabChange: setActiveTab }),
|
|
3931
4380
|
activeTab === "crypto" ? /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-3", children: [
|
|
@@ -3954,8 +4403,8 @@ function DepositModalContent({
|
|
|
3954
4403
|
] }) : /* @__PURE__ */ jsx("div", { className: "flex flex-col gap-3", children: /* @__PURE__ */ jsx(
|
|
3955
4404
|
MethodOption,
|
|
3956
4405
|
{
|
|
3957
|
-
title: "
|
|
3958
|
-
description: "
|
|
4406
|
+
title: "Buy with card",
|
|
4407
|
+
description: "Purchase and deposit directly into your account.",
|
|
3959
4408
|
onClick: () => {
|
|
3960
4409
|
onSelectCreditCard?.();
|
|
3961
4410
|
openDeposit("credit-card");
|
|
@@ -3963,21 +4412,29 @@ function DepositModalContent({
|
|
|
3963
4412
|
}
|
|
3964
4413
|
) })
|
|
3965
4414
|
] }),
|
|
3966
|
-
activeView === "deposit" && /* @__PURE__ */ jsx(
|
|
3967
|
-
|
|
4415
|
+
activeView === "deposit" && /* @__PURE__ */ jsx(
|
|
4416
|
+
MoonPayGate,
|
|
3968
4417
|
{
|
|
3969
|
-
source,
|
|
3970
|
-
|
|
3971
|
-
|
|
3972
|
-
|
|
3973
|
-
|
|
3974
|
-
|
|
3975
|
-
|
|
3976
|
-
|
|
3977
|
-
|
|
3978
|
-
|
|
4418
|
+
enabled: source === "credit-card" && cardOnRamp.provider === "moonpay" && !cardOnRamp.unavailableReason,
|
|
4419
|
+
apiKey: networkConfig.moonpayApiKey,
|
|
4420
|
+
children: /* @__PURE__ */ jsx(
|
|
4421
|
+
DepositView,
|
|
4422
|
+
{
|
|
4423
|
+
source,
|
|
4424
|
+
selectedToken,
|
|
4425
|
+
onRamp: cardOnRamp,
|
|
4426
|
+
amount,
|
|
4427
|
+
allowance,
|
|
4428
|
+
externalMinimum,
|
|
4429
|
+
onAmountChange: setAmount,
|
|
4430
|
+
onSelectToken: () => setView("select-token"),
|
|
4431
|
+
onConnectWallet,
|
|
4432
|
+
onSubmit: handleSubmit,
|
|
4433
|
+
isSubmitting: isPending || externalLock.isSigning || externalLock.isSubmittingLock
|
|
4434
|
+
}
|
|
4435
|
+
)
|
|
3979
4436
|
}
|
|
3980
|
-
)
|
|
4437
|
+
),
|
|
3981
4438
|
activeView === "select-token" && /* @__PURE__ */ jsx(
|
|
3982
4439
|
TokenSelectorView,
|
|
3983
4440
|
{
|
|
@@ -3999,20 +4456,30 @@ function DepositModalContent({
|
|
|
3999
4456
|
lock: externalLock.session ? externalLock : void 0
|
|
4000
4457
|
}
|
|
4001
4458
|
),
|
|
4002
|
-
activeView === "credit-card-widget" &&
|
|
4003
|
-
|
|
4459
|
+
activeView === "credit-card-widget" && mountedCardFlow && /* @__PURE__ */ jsx(
|
|
4460
|
+
MoonPayGate,
|
|
4004
4461
|
{
|
|
4005
|
-
|
|
4006
|
-
|
|
4007
|
-
|
|
4008
|
-
|
|
4009
|
-
|
|
4010
|
-
|
|
4011
|
-
|
|
4012
|
-
|
|
4013
|
-
|
|
4462
|
+
enabled: mountedCardFlow.selection.provider === "moonpay",
|
|
4463
|
+
apiKey: mountedCardFlow.moonpayApiKey,
|
|
4464
|
+
children: /* @__PURE__ */ jsx(
|
|
4465
|
+
CreditCardWidgetView,
|
|
4466
|
+
{
|
|
4467
|
+
token: mountedCardFlow.selection.token,
|
|
4468
|
+
onRamp: mountedCardFlow.selection,
|
|
4469
|
+
amount: mountedCardFlow.amount,
|
|
4470
|
+
allowance: mountedCardFlow.allowance,
|
|
4471
|
+
lockServiceAddress: mountedCardFlow.lockServiceAddress,
|
|
4472
|
+
onUnsafeToCloseChange: setCardUnsafeToClose,
|
|
4473
|
+
onActiveFlowChange: setCardFlowActive,
|
|
4474
|
+
onCredited: cardOutcomeCallbacks?.onCredited,
|
|
4475
|
+
onLockSubmitted: cardOutcomeCallbacks?.onLockSubmitted,
|
|
4476
|
+
onLockFailed: cardOutcomeCallbacks?.onLockFailed,
|
|
4477
|
+
onLeave: leaveCardPurchase
|
|
4478
|
+
},
|
|
4479
|
+
mountedCardFlow.id
|
|
4480
|
+
)
|
|
4014
4481
|
}
|
|
4015
|
-
)
|
|
4482
|
+
)
|
|
4016
4483
|
] });
|
|
4017
4484
|
}
|
|
4018
4485
|
function DepositModal({ open, onClose, ...handlers }) {
|