@b3dotfun/sdk 0.1.66-alpha.0 → 0.1.66-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/checkout/AnySpendCheckout.d.ts +50 -0
- package/dist/cjs/anyspend/react/components/checkout/AnySpendCheckout.js +30 -0
- package/dist/cjs/anyspend/react/components/checkout/AnySpendCheckoutTrigger.d.ts +47 -0
- package/dist/cjs/anyspend/react/components/checkout/AnySpendCheckoutTrigger.js +45 -0
- package/dist/cjs/anyspend/react/components/checkout/CartItemRow.d.ts +8 -0
- package/dist/cjs/anyspend/react/components/checkout/CartItemRow.js +9 -0
- package/dist/cjs/anyspend/react/components/checkout/CartSummary.d.ts +8 -0
- package/dist/cjs/anyspend/react/components/checkout/CartSummary.js +9 -0
- package/dist/cjs/anyspend/react/components/checkout/CheckoutCartPanel.d.ts +12 -0
- package/dist/cjs/anyspend/react/components/checkout/CheckoutCartPanel.js +19 -0
- package/dist/cjs/anyspend/react/components/checkout/CheckoutLayout.d.ts +10 -0
- package/dist/cjs/anyspend/react/components/checkout/CheckoutLayout.js +25 -0
- package/dist/cjs/anyspend/react/components/checkout/CheckoutPaymentPanel.d.ts +20 -0
- package/dist/cjs/anyspend/react/components/checkout/CheckoutPaymentPanel.js +45 -0
- package/dist/cjs/anyspend/react/components/checkout/CheckoutSuccess.d.ts +10 -0
- package/dist/cjs/anyspend/react/components/checkout/CheckoutSuccess.js +11 -0
- package/dist/cjs/anyspend/react/components/checkout/CoinbaseCheckoutPanel.d.ts +16 -0
- package/dist/cjs/anyspend/react/components/checkout/CoinbaseCheckoutPanel.js +27 -0
- package/dist/cjs/anyspend/react/components/checkout/CryptoCheckoutPanel.d.ts +33 -0
- package/dist/cjs/anyspend/react/components/checkout/CryptoCheckoutPanel.js +317 -0
- package/dist/cjs/anyspend/react/components/checkout/FiatCheckoutPanel.d.ts +16 -0
- package/dist/cjs/anyspend/react/components/checkout/FiatCheckoutPanel.js +233 -0
- package/dist/cjs/anyspend/react/components/checkout/PoweredByBranding.d.ts +8 -0
- package/dist/cjs/anyspend/react/components/checkout/PoweredByBranding.js +9 -0
- package/dist/cjs/anyspend/react/components/checkout/QRCheckoutPanel.d.ts +17 -0
- package/dist/cjs/anyspend/react/components/checkout/QRCheckoutPanel.js +148 -0
- package/dist/cjs/anyspend/react/components/index.d.ts +5 -1
- package/dist/cjs/anyspend/react/components/index.js +6 -1
- package/dist/cjs/anyspend/react/components/types/classes.d.ts +32 -0
- package/dist/cjs/app.shared.js +8 -0
- package/dist/cjs/global-account/react/components/B3DynamicModal.js +5 -1
- package/dist/cjs/global-account/react/components/WalletImage/WalletImage.d.ts +1 -1
- package/dist/cjs/global-account/react/components/ui/command.d.ts +7 -7
- package/dist/cjs/global-account/react/hooks/useAuth.d.ts +1 -1
- package/dist/cjs/global-account/react/hooks/useAuthentication.d.ts +1 -1
- package/dist/cjs/global-account/react/hooks/useFirstEOA.d.ts +4 -4
- package/dist/cjs/global-account/react/hooks/useUser.d.ts +1 -1
- package/dist/cjs/global-account/react/hooks/useUserQuery.d.ts +1 -1
- package/dist/cjs/global-account/react/stores/useModalStore.d.ts +53 -1
- package/dist/cjs/shared/constants/chains/b3Chain.d.ts +2 -2
- package/dist/cjs/shared/constants/chains/supported.d.ts +3 -3
- package/dist/esm/anyspend/react/components/checkout/AnySpendCheckout.d.ts +50 -0
- package/dist/esm/anyspend/react/components/checkout/AnySpendCheckout.js +27 -0
- package/dist/esm/anyspend/react/components/checkout/AnySpendCheckoutTrigger.d.ts +47 -0
- package/dist/esm/anyspend/react/components/checkout/AnySpendCheckoutTrigger.js +42 -0
- package/dist/esm/anyspend/react/components/checkout/CartItemRow.d.ts +8 -0
- package/dist/esm/anyspend/react/components/checkout/CartItemRow.js +6 -0
- package/dist/esm/anyspend/react/components/checkout/CartSummary.d.ts +8 -0
- package/dist/esm/anyspend/react/components/checkout/CartSummary.js +6 -0
- package/dist/esm/anyspend/react/components/checkout/CheckoutCartPanel.d.ts +12 -0
- package/dist/esm/anyspend/react/components/checkout/CheckoutCartPanel.js +16 -0
- package/dist/esm/anyspend/react/components/checkout/CheckoutLayout.d.ts +10 -0
- package/dist/esm/anyspend/react/components/checkout/CheckoutLayout.js +22 -0
- package/dist/esm/anyspend/react/components/checkout/CheckoutPaymentPanel.d.ts +20 -0
- package/dist/esm/anyspend/react/components/checkout/CheckoutPaymentPanel.js +42 -0
- package/dist/esm/anyspend/react/components/checkout/CheckoutSuccess.d.ts +10 -0
- package/dist/esm/anyspend/react/components/checkout/CheckoutSuccess.js +8 -0
- package/dist/esm/anyspend/react/components/checkout/CoinbaseCheckoutPanel.d.ts +16 -0
- package/dist/esm/anyspend/react/components/checkout/CoinbaseCheckoutPanel.js +24 -0
- package/dist/esm/anyspend/react/components/checkout/CryptoCheckoutPanel.d.ts +33 -0
- package/dist/esm/anyspend/react/components/checkout/CryptoCheckoutPanel.js +313 -0
- package/dist/esm/anyspend/react/components/checkout/FiatCheckoutPanel.d.ts +16 -0
- package/dist/esm/anyspend/react/components/checkout/FiatCheckoutPanel.js +230 -0
- package/dist/esm/anyspend/react/components/checkout/PoweredByBranding.d.ts +8 -0
- package/dist/esm/anyspend/react/components/checkout/PoweredByBranding.js +6 -0
- package/dist/esm/anyspend/react/components/checkout/QRCheckoutPanel.d.ts +17 -0
- package/dist/esm/anyspend/react/components/checkout/QRCheckoutPanel.js +145 -0
- package/dist/esm/anyspend/react/components/index.d.ts +5 -1
- package/dist/esm/anyspend/react/components/index.js +3 -0
- package/dist/esm/anyspend/react/components/types/classes.d.ts +32 -0
- package/dist/esm/app.shared.js +8 -0
- package/dist/esm/global-account/react/components/B3DynamicModal.js +5 -1
- package/dist/esm/global-account/react/components/WalletImage/WalletImage.d.ts +1 -1
- package/dist/esm/global-account/react/components/ui/command.d.ts +7 -7
- package/dist/esm/global-account/react/hooks/useAuth.d.ts +1 -1
- package/dist/esm/global-account/react/hooks/useAuthentication.d.ts +1 -1
- package/dist/esm/global-account/react/hooks/useFirstEOA.d.ts +4 -4
- package/dist/esm/global-account/react/hooks/useUser.d.ts +1 -1
- package/dist/esm/global-account/react/hooks/useUserQuery.d.ts +1 -1
- package/dist/esm/global-account/react/stores/useModalStore.d.ts +53 -1
- package/dist/esm/shared/constants/chains/b3Chain.d.ts +2 -2
- package/dist/esm/shared/constants/chains/supported.d.ts +3 -3
- package/dist/styles/index.css +1 -1
- package/dist/types/anyspend/react/components/checkout/AnySpendCheckout.d.ts +50 -0
- package/dist/types/anyspend/react/components/checkout/AnySpendCheckoutTrigger.d.ts +47 -0
- package/dist/types/anyspend/react/components/checkout/CartItemRow.d.ts +8 -0
- package/dist/types/anyspend/react/components/checkout/CartSummary.d.ts +8 -0
- package/dist/types/anyspend/react/components/checkout/CheckoutCartPanel.d.ts +12 -0
- package/dist/types/anyspend/react/components/checkout/CheckoutLayout.d.ts +10 -0
- package/dist/types/anyspend/react/components/checkout/CheckoutPaymentPanel.d.ts +20 -0
- package/dist/types/anyspend/react/components/checkout/CheckoutSuccess.d.ts +10 -0
- package/dist/types/anyspend/react/components/checkout/CoinbaseCheckoutPanel.d.ts +16 -0
- package/dist/types/anyspend/react/components/checkout/CryptoCheckoutPanel.d.ts +33 -0
- package/dist/types/anyspend/react/components/checkout/FiatCheckoutPanel.d.ts +16 -0
- package/dist/types/anyspend/react/components/checkout/PoweredByBranding.d.ts +8 -0
- package/dist/types/anyspend/react/components/checkout/QRCheckoutPanel.d.ts +17 -0
- package/dist/types/anyspend/react/components/index.d.ts +5 -1
- package/dist/types/anyspend/react/components/types/classes.d.ts +32 -0
- package/dist/types/global-account/react/components/WalletImage/WalletImage.d.ts +1 -1
- package/dist/types/global-account/react/components/ui/command.d.ts +7 -7
- package/dist/types/global-account/react/hooks/useAuth.d.ts +1 -1
- package/dist/types/global-account/react/hooks/useAuthentication.d.ts +1 -1
- package/dist/types/global-account/react/hooks/useFirstEOA.d.ts +4 -4
- package/dist/types/global-account/react/hooks/useUser.d.ts +1 -1
- package/dist/types/global-account/react/hooks/useUserQuery.d.ts +1 -1
- package/dist/types/global-account/react/stores/useModalStore.d.ts +53 -1
- package/dist/types/shared/constants/chains/b3Chain.d.ts +2 -2
- package/dist/types/shared/constants/chains/supported.d.ts +3 -3
- package/package.json +1 -1
- package/src/anyspend/react/components/checkout/AnySpendCheckout.tsx +127 -0
- package/src/anyspend/react/components/checkout/AnySpendCheckoutTrigger.tsx +166 -0
- package/src/anyspend/react/components/checkout/CartItemRow.tsx +43 -0
- package/src/anyspend/react/components/checkout/CartSummary.tsx +23 -0
- package/src/anyspend/react/components/checkout/CheckoutCartPanel.tsx +60 -0
- package/src/anyspend/react/components/checkout/CheckoutLayout.tsx +72 -0
- package/src/anyspend/react/components/checkout/CheckoutPaymentPanel.tsx +320 -0
- package/src/anyspend/react/components/checkout/CheckoutSuccess.tsx +91 -0
- package/src/anyspend/react/components/checkout/CoinbaseCheckoutPanel.tsx +90 -0
- package/src/anyspend/react/components/checkout/CryptoCheckoutPanel.tsx +643 -0
- package/src/anyspend/react/components/checkout/FiatCheckoutPanel.tsx +568 -0
- package/src/anyspend/react/components/checkout/PoweredByBranding.tsx +32 -0
- package/src/anyspend/react/components/checkout/QRCheckoutPanel.tsx +320 -0
- package/src/anyspend/react/components/index.ts +7 -0
- package/src/anyspend/react/components/types/classes.ts +48 -0
- package/src/app.shared.ts +11 -0
- package/src/global-account/react/components/B3DynamicModal.tsx +5 -0
- package/src/global-account/react/stores/useModalStore.ts +52 -1
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import { useTokenData } from "@b3dotfun/sdk/global-account/react";
|
|
4
|
+
import { formatTokenAmount } from "@b3dotfun/sdk/shared/utils/number";
|
|
5
|
+
import { cn } from "@b3dotfun/sdk/shared/utils/cn";
|
|
6
|
+
import { useMemo } from "react";
|
|
7
|
+
import { AnySpendFingerprintWrapper, getFingerprintConfig } from "../AnySpendFingerprintWrapper";
|
|
8
|
+
import type { AnySpendCheckoutClasses } from "../types/classes";
|
|
9
|
+
import type { CheckoutItem } from "./AnySpendCheckout";
|
|
10
|
+
import { CheckoutCartPanel } from "./CheckoutCartPanel";
|
|
11
|
+
import { CheckoutPaymentPanel } from "./CheckoutPaymentPanel";
|
|
12
|
+
import { PoweredByBranding } from "./PoweredByBranding";
|
|
13
|
+
|
|
14
|
+
export interface AnySpendCheckoutTriggerProps {
|
|
15
|
+
/** Payment recipient address (hex) */
|
|
16
|
+
recipientAddress: string;
|
|
17
|
+
/** Destination token address */
|
|
18
|
+
destinationTokenAddress: string;
|
|
19
|
+
/** Destination chain ID */
|
|
20
|
+
destinationTokenChainId: number;
|
|
21
|
+
/** Line items to display in the cart (optional — if omitted, only the payment panel is shown) */
|
|
22
|
+
items?: CheckoutItem[];
|
|
23
|
+
/** Total amount in wei — required when items are not provided */
|
|
24
|
+
totalAmount?: string;
|
|
25
|
+
/** Organization name */
|
|
26
|
+
organizationName?: string;
|
|
27
|
+
/** Organization logo URL */
|
|
28
|
+
organizationLogo?: string;
|
|
29
|
+
/** Theme color (hex) */
|
|
30
|
+
themeColor?: string;
|
|
31
|
+
/** Custom button text */
|
|
32
|
+
buttonText?: string;
|
|
33
|
+
/** Workflow ID to trigger on payment */
|
|
34
|
+
workflowId?: string;
|
|
35
|
+
/** Organization ID that owns the workflow */
|
|
36
|
+
orgId?: string;
|
|
37
|
+
/** Optional callback metadata merged into the order */
|
|
38
|
+
callbackMetadata?: {
|
|
39
|
+
/** Passed as trigger result inputs — accessible via {{root.result.inputs.*}} */
|
|
40
|
+
inputs?: Record<string, unknown>;
|
|
41
|
+
} & Record<string, unknown>;
|
|
42
|
+
/** Called on successful payment */
|
|
43
|
+
onSuccess?: (result: { txHash?: string; orderId?: string }) => void;
|
|
44
|
+
/** Called on payment error */
|
|
45
|
+
onError?: (error: Error) => void;
|
|
46
|
+
/** URL to redirect to after payment */
|
|
47
|
+
returnUrl?: string;
|
|
48
|
+
/** Label for the return button */
|
|
49
|
+
returnLabel?: string;
|
|
50
|
+
/** Custom class names */
|
|
51
|
+
classes?: AnySpendCheckoutClasses;
|
|
52
|
+
/** Display mode — set automatically when used inside B3DynamicModal */
|
|
53
|
+
mode?: "modal" | "page";
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
export function AnySpendCheckoutTrigger({
|
|
57
|
+
recipientAddress,
|
|
58
|
+
destinationTokenAddress,
|
|
59
|
+
destinationTokenChainId,
|
|
60
|
+
items,
|
|
61
|
+
totalAmount: totalAmountOverride,
|
|
62
|
+
organizationName,
|
|
63
|
+
organizationLogo,
|
|
64
|
+
themeColor,
|
|
65
|
+
buttonText = "Pay",
|
|
66
|
+
workflowId,
|
|
67
|
+
orgId,
|
|
68
|
+
callbackMetadata,
|
|
69
|
+
onSuccess,
|
|
70
|
+
onError,
|
|
71
|
+
returnUrl,
|
|
72
|
+
returnLabel,
|
|
73
|
+
classes,
|
|
74
|
+
}: AnySpendCheckoutTriggerProps) {
|
|
75
|
+
// Merge workflowId + orgId into callbackMetadata
|
|
76
|
+
const mergedMetadata = useMemo(() => {
|
|
77
|
+
if (!workflowId && !orgId && !callbackMetadata) return undefined;
|
|
78
|
+
return {
|
|
79
|
+
...(workflowId ? { workflowId } : {}),
|
|
80
|
+
...(orgId ? { orgId } : {}),
|
|
81
|
+
...callbackMetadata,
|
|
82
|
+
};
|
|
83
|
+
}, [workflowId, orgId, callbackMetadata]);
|
|
84
|
+
|
|
85
|
+
// Compute total from items or use override
|
|
86
|
+
const computedTotal = useMemo(() => {
|
|
87
|
+
if (totalAmountOverride) return totalAmountOverride;
|
|
88
|
+
if (!items || items.length === 0) return "0";
|
|
89
|
+
let total = BigInt(0);
|
|
90
|
+
for (const item of items) {
|
|
91
|
+
total += BigInt(item.amount) * BigInt(item.quantity);
|
|
92
|
+
}
|
|
93
|
+
return total.toString();
|
|
94
|
+
}, [items, totalAmountOverride]);
|
|
95
|
+
|
|
96
|
+
// Get destination token metadata
|
|
97
|
+
const { data: tokenData } = useTokenData(destinationTokenChainId, destinationTokenAddress);
|
|
98
|
+
const tokenSymbol = tokenData?.symbol || "";
|
|
99
|
+
const tokenDecimals = tokenData?.decimals || 18;
|
|
100
|
+
|
|
101
|
+
const formattedTotal = useMemo(
|
|
102
|
+
() => formatTokenAmount(BigInt(computedTotal || "0"), tokenDecimals),
|
|
103
|
+
[computedTotal, tokenDecimals],
|
|
104
|
+
);
|
|
105
|
+
|
|
106
|
+
const hasItems = items && items.length > 0;
|
|
107
|
+
const fingerprint = getFingerprintConfig();
|
|
108
|
+
|
|
109
|
+
return (
|
|
110
|
+
<AnySpendFingerprintWrapper fingerprint={fingerprint}>
|
|
111
|
+
<div className="anyspend-checkout-trigger flex flex-col">
|
|
112
|
+
{/* Cart summary with items */}
|
|
113
|
+
{hasItems && (
|
|
114
|
+
<div className="border-b border-gray-200 p-5 dark:border-gray-700">
|
|
115
|
+
<CheckoutCartPanel
|
|
116
|
+
items={items}
|
|
117
|
+
totalAmount={computedTotal}
|
|
118
|
+
tokenSymbol={tokenSymbol}
|
|
119
|
+
tokenDecimals={tokenDecimals}
|
|
120
|
+
organizationName={organizationName}
|
|
121
|
+
organizationLogo={organizationLogo}
|
|
122
|
+
classes={classes}
|
|
123
|
+
/>
|
|
124
|
+
</div>
|
|
125
|
+
)}
|
|
126
|
+
|
|
127
|
+
{/* Total-only header when no items */}
|
|
128
|
+
{!hasItems && (
|
|
129
|
+
<div className="border-b border-gray-200 p-5 dark:border-gray-700">
|
|
130
|
+
<div className="flex flex-col gap-3">
|
|
131
|
+
<div className={cn("flex items-center justify-between", classes?.cartSummary)}>
|
|
132
|
+
<span className="text-base font-semibold text-gray-900 dark:text-gray-100">Total</span>
|
|
133
|
+
<span className={cn("text-base font-semibold text-gray-900 dark:text-gray-100", classes?.cartTotal)}>
|
|
134
|
+
{formattedTotal} {tokenSymbol}
|
|
135
|
+
</span>
|
|
136
|
+
</div>
|
|
137
|
+
<PoweredByBranding
|
|
138
|
+
organizationName={organizationName}
|
|
139
|
+
organizationLogo={organizationLogo}
|
|
140
|
+
classes={classes}
|
|
141
|
+
/>
|
|
142
|
+
</div>
|
|
143
|
+
</div>
|
|
144
|
+
)}
|
|
145
|
+
|
|
146
|
+
{/* Payment methods */}
|
|
147
|
+
<div className="p-5">
|
|
148
|
+
<CheckoutPaymentPanel
|
|
149
|
+
recipientAddress={recipientAddress}
|
|
150
|
+
destinationTokenAddress={destinationTokenAddress}
|
|
151
|
+
destinationTokenChainId={destinationTokenChainId}
|
|
152
|
+
totalAmount={computedTotal}
|
|
153
|
+
buttonText={buttonText}
|
|
154
|
+
themeColor={themeColor}
|
|
155
|
+
returnUrl={returnUrl}
|
|
156
|
+
returnLabel={returnLabel}
|
|
157
|
+
onSuccess={onSuccess}
|
|
158
|
+
onError={onError}
|
|
159
|
+
callbackMetadata={mergedMetadata}
|
|
160
|
+
classes={classes}
|
|
161
|
+
/>
|
|
162
|
+
</div>
|
|
163
|
+
</div>
|
|
164
|
+
</AnySpendFingerprintWrapper>
|
|
165
|
+
);
|
|
166
|
+
}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import { cn } from "@b3dotfun/sdk/shared/utils/cn";
|
|
4
|
+
import type { CheckoutItem, AnySpendCheckoutClasses } from "./AnySpendCheckout";
|
|
5
|
+
|
|
6
|
+
interface CartItemRowProps {
|
|
7
|
+
item: CheckoutItem;
|
|
8
|
+
formattedPrice: string;
|
|
9
|
+
classes?: AnySpendCheckoutClasses;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export function CartItemRow({ item, formattedPrice, classes }: CartItemRowProps) {
|
|
13
|
+
return (
|
|
14
|
+
<div className={cn("flex items-start gap-3 py-3", classes?.cartItemRow)}>
|
|
15
|
+
{item.imageUrl && (
|
|
16
|
+
<div className={cn("h-14 w-14 shrink-0 overflow-hidden rounded-lg bg-gray-100", classes?.cartItemImage)}>
|
|
17
|
+
<img src={item.imageUrl} alt={item.name} className="h-full w-full object-cover" />
|
|
18
|
+
</div>
|
|
19
|
+
)}
|
|
20
|
+
<div className="flex min-w-0 flex-1 items-start justify-between">
|
|
21
|
+
<div className="min-w-0 flex-1">
|
|
22
|
+
<p className={cn("text-sm font-medium text-gray-900 dark:text-gray-100", classes?.cartItemName)}>
|
|
23
|
+
{item.name}
|
|
24
|
+
</p>
|
|
25
|
+
{item.description && (
|
|
26
|
+
<p
|
|
27
|
+
className={cn(
|
|
28
|
+
"mt-0.5 line-clamp-2 text-xs text-gray-500 dark:text-gray-400",
|
|
29
|
+
classes?.cartItemDescription,
|
|
30
|
+
)}
|
|
31
|
+
>
|
|
32
|
+
{item.description}
|
|
33
|
+
</p>
|
|
34
|
+
)}
|
|
35
|
+
{item.quantity > 1 && <p className="mt-0.5 text-xs text-gray-400 dark:text-gray-500">Qty: {item.quantity}</p>}
|
|
36
|
+
</div>
|
|
37
|
+
<p className={cn("ml-3 text-sm font-medium text-gray-900 dark:text-gray-100", classes?.cartItemPrice)}>
|
|
38
|
+
{formattedPrice}
|
|
39
|
+
</p>
|
|
40
|
+
</div>
|
|
41
|
+
</div>
|
|
42
|
+
);
|
|
43
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import { cn } from "@b3dotfun/sdk/shared/utils/cn";
|
|
4
|
+
import type { AnySpendCheckoutClasses } from "./AnySpendCheckout";
|
|
5
|
+
|
|
6
|
+
interface CartSummaryProps {
|
|
7
|
+
total: string;
|
|
8
|
+
tokenSymbol?: string;
|
|
9
|
+
classes?: AnySpendCheckoutClasses;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export function CartSummary({ total, tokenSymbol, classes }: CartSummaryProps) {
|
|
13
|
+
return (
|
|
14
|
+
<div className={cn("border-t border-gray-200 pt-3 dark:border-gray-700", classes?.cartSummary)}>
|
|
15
|
+
<div className="flex items-center justify-between">
|
|
16
|
+
<span className="text-base font-semibold text-gray-900 dark:text-gray-100">Total</span>
|
|
17
|
+
<span className={cn("text-base font-semibold text-gray-900 dark:text-gray-100", classes?.cartTotal)}>
|
|
18
|
+
{total} {tokenSymbol}
|
|
19
|
+
</span>
|
|
20
|
+
</div>
|
|
21
|
+
</div>
|
|
22
|
+
);
|
|
23
|
+
}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import { cn } from "@b3dotfun/sdk/shared/utils/cn";
|
|
4
|
+
import { formatTokenAmount } from "@b3dotfun/sdk/shared/utils/number";
|
|
5
|
+
import { useMemo } from "react";
|
|
6
|
+
import type { CheckoutItem, AnySpendCheckoutClasses } from "./AnySpendCheckout";
|
|
7
|
+
import { CartItemRow } from "./CartItemRow";
|
|
8
|
+
import { CartSummary } from "./CartSummary";
|
|
9
|
+
import { PoweredByBranding } from "./PoweredByBranding";
|
|
10
|
+
|
|
11
|
+
interface CheckoutCartPanelProps {
|
|
12
|
+
items: CheckoutItem[];
|
|
13
|
+
totalAmount: string;
|
|
14
|
+
tokenSymbol?: string;
|
|
15
|
+
tokenDecimals?: number;
|
|
16
|
+
organizationName?: string;
|
|
17
|
+
organizationLogo?: string;
|
|
18
|
+
classes?: AnySpendCheckoutClasses;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export function CheckoutCartPanel({
|
|
22
|
+
items,
|
|
23
|
+
totalAmount,
|
|
24
|
+
tokenSymbol = "",
|
|
25
|
+
tokenDecimals = 18,
|
|
26
|
+
organizationName,
|
|
27
|
+
organizationLogo,
|
|
28
|
+
classes,
|
|
29
|
+
}: CheckoutCartPanelProps) {
|
|
30
|
+
const formattedTotal = useMemo(
|
|
31
|
+
() => formatTokenAmount(BigInt(totalAmount), tokenDecimals),
|
|
32
|
+
[totalAmount, tokenDecimals],
|
|
33
|
+
);
|
|
34
|
+
|
|
35
|
+
return (
|
|
36
|
+
<div className={cn("anyspend-cart-panel flex flex-col", classes?.cartPanel)}>
|
|
37
|
+
<h2
|
|
38
|
+
className={cn(
|
|
39
|
+
"anyspend-cart-title mb-4 text-lg font-semibold text-gray-900 dark:text-gray-100",
|
|
40
|
+
classes?.cartTitle,
|
|
41
|
+
)}
|
|
42
|
+
>
|
|
43
|
+
Order Summary
|
|
44
|
+
</h2>
|
|
45
|
+
|
|
46
|
+
<div className="anyspend-cart-items divide-y divide-gray-100 dark:divide-gray-800">
|
|
47
|
+
{items.map((item, index) => {
|
|
48
|
+
const itemTotal = BigInt(item.amount) * BigInt(item.quantity);
|
|
49
|
+
const formattedPrice = `${formatTokenAmount(itemTotal, tokenDecimals)} ${tokenSymbol}`;
|
|
50
|
+
|
|
51
|
+
return <CartItemRow key={item.id || index} item={item} formattedPrice={formattedPrice} classes={classes} />;
|
|
52
|
+
})}
|
|
53
|
+
</div>
|
|
54
|
+
|
|
55
|
+
<CartSummary total={formattedTotal} tokenSymbol={tokenSymbol} classes={classes} />
|
|
56
|
+
|
|
57
|
+
<PoweredByBranding organizationName={organizationName} organizationLogo={organizationLogo} classes={classes} />
|
|
58
|
+
</div>
|
|
59
|
+
);
|
|
60
|
+
}
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import { cn } from "@b3dotfun/sdk/shared/utils/cn";
|
|
4
|
+
import type { ReactNode } from "react";
|
|
5
|
+
import type { AnySpendCheckoutClasses } from "./AnySpendCheckout";
|
|
6
|
+
|
|
7
|
+
interface CheckoutLayoutProps {
|
|
8
|
+
mode: "page" | "embedded";
|
|
9
|
+
paymentPanel: ReactNode;
|
|
10
|
+
cartPanel: ReactNode;
|
|
11
|
+
classes?: AnySpendCheckoutClasses;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export function CheckoutLayout({ mode, paymentPanel, cartPanel, classes }: CheckoutLayoutProps) {
|
|
15
|
+
const rightColumnWidth = mode === "page" ? 380 : 340;
|
|
16
|
+
|
|
17
|
+
return (
|
|
18
|
+
<div
|
|
19
|
+
className={cn("anyspend-checkout mx-auto w-full", classes?.root)}
|
|
20
|
+
style={mode === "page" ? { maxWidth: 1100, padding: "2rem 1rem" } : undefined}
|
|
21
|
+
>
|
|
22
|
+
{/*
|
|
23
|
+
Use CSS Grid with inline styles to ensure 2-column layout works
|
|
24
|
+
regardless of host app's Tailwind configuration.
|
|
25
|
+
On screens < 768px: single column (cart on top, payment below).
|
|
26
|
+
On screens >= 768px: two columns (payment left, cart right).
|
|
27
|
+
*/}
|
|
28
|
+
<style
|
|
29
|
+
dangerouslySetInnerHTML={{
|
|
30
|
+
__html: `
|
|
31
|
+
.anyspend-checkout-grid {
|
|
32
|
+
display: grid;
|
|
33
|
+
gap: 2rem;
|
|
34
|
+
grid-template-columns: 1fr;
|
|
35
|
+
}
|
|
36
|
+
@media (min-width: 768px) {
|
|
37
|
+
.anyspend-checkout-grid {
|
|
38
|
+
grid-template-columns: 1fr ${rightColumnWidth}px;
|
|
39
|
+
}
|
|
40
|
+
.anyspend-checkout-grid > .anyspend-payment-col { order: 1; }
|
|
41
|
+
.anyspend-checkout-grid > .anyspend-cart-col { order: 2; }
|
|
42
|
+
}
|
|
43
|
+
`,
|
|
44
|
+
}}
|
|
45
|
+
/>
|
|
46
|
+
<div className={cn("anyspend-checkout-grid", classes?.layout)}>
|
|
47
|
+
{/* LEFT: Payment Methods (appears second on mobile, first on desktop) */}
|
|
48
|
+
<div
|
|
49
|
+
className={cn(
|
|
50
|
+
"anyspend-payment-col order-2",
|
|
51
|
+
"rounded-2xl border border-gray-200 bg-white p-6 shadow-sm dark:border-gray-700 dark:bg-gray-900",
|
|
52
|
+
classes?.paymentColumn,
|
|
53
|
+
)}
|
|
54
|
+
>
|
|
55
|
+
{paymentPanel}
|
|
56
|
+
</div>
|
|
57
|
+
|
|
58
|
+
{/* RIGHT: Cart / Invoice (appears first on mobile, second on desktop) */}
|
|
59
|
+
<div
|
|
60
|
+
className={cn(
|
|
61
|
+
"anyspend-cart-col order-1",
|
|
62
|
+
"rounded-2xl border border-gray-200 bg-gray-50 p-6 dark:border-gray-700 dark:bg-gray-800/50",
|
|
63
|
+
classes?.cartColumn,
|
|
64
|
+
)}
|
|
65
|
+
style={{ position: "sticky", top: 32, alignSelf: "start" }}
|
|
66
|
+
>
|
|
67
|
+
{cartPanel}
|
|
68
|
+
</div>
|
|
69
|
+
</div>
|
|
70
|
+
</div>
|
|
71
|
+
);
|
|
72
|
+
}
|
|
@@ -0,0 +1,320 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import { cn } from "@b3dotfun/sdk/shared/utils/cn";
|
|
4
|
+
import { QrCode, Wallet } from "lucide-react";
|
|
5
|
+
import { AnimatePresence, motion } from "motion/react";
|
|
6
|
+
import { useState } from "react";
|
|
7
|
+
import type { AnySpendCheckoutClasses } from "./AnySpendCheckout";
|
|
8
|
+
import { CheckoutSuccess } from "./CheckoutSuccess";
|
|
9
|
+
import { CoinbaseCheckoutPanel } from "./CoinbaseCheckoutPanel";
|
|
10
|
+
import { CryptoCheckoutPanel } from "./CryptoCheckoutPanel";
|
|
11
|
+
import { FiatCheckoutPanel } from "./FiatCheckoutPanel";
|
|
12
|
+
import { QRCheckoutPanel } from "./QRCheckoutPanel";
|
|
13
|
+
|
|
14
|
+
type PaymentMethod = "crypto" | "qr" | "card" | "coinbase";
|
|
15
|
+
|
|
16
|
+
interface CheckoutPaymentPanelProps {
|
|
17
|
+
recipientAddress: string;
|
|
18
|
+
destinationTokenAddress: string;
|
|
19
|
+
destinationTokenChainId: number;
|
|
20
|
+
totalAmount: string;
|
|
21
|
+
buttonText?: string;
|
|
22
|
+
themeColor?: string;
|
|
23
|
+
returnUrl?: string;
|
|
24
|
+
returnLabel?: string;
|
|
25
|
+
onSuccess?: (result: { txHash?: string; orderId?: string }) => void;
|
|
26
|
+
onError?: (error: Error) => void;
|
|
27
|
+
callbackMetadata?: Record<string, unknown>;
|
|
28
|
+
classes?: AnySpendCheckoutClasses;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
function RadioCircle({ selected, themeColor }: { selected: boolean; themeColor?: string }) {
|
|
32
|
+
return (
|
|
33
|
+
<div
|
|
34
|
+
className={cn(
|
|
35
|
+
"flex h-[18px] w-[18px] shrink-0 items-center justify-center rounded-full border-2 transition-colors",
|
|
36
|
+
selected ? "border-blue-600" : "border-gray-300 dark:border-gray-600",
|
|
37
|
+
)}
|
|
38
|
+
style={selected && themeColor ? { borderColor: themeColor } : undefined}
|
|
39
|
+
>
|
|
40
|
+
{selected && (
|
|
41
|
+
<div
|
|
42
|
+
className="h-2 w-2 rounded-full bg-blue-600"
|
|
43
|
+
style={themeColor ? { backgroundColor: themeColor } : undefined}
|
|
44
|
+
/>
|
|
45
|
+
)}
|
|
46
|
+
</div>
|
|
47
|
+
);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/** Card brand logos - all use consistent 32x20 viewBox */
|
|
51
|
+
function VisaLogo() {
|
|
52
|
+
return (
|
|
53
|
+
<svg viewBox="0 0 32 20" style={{ width: 32, height: 20 }} aria-label="Visa">
|
|
54
|
+
<rect width="32" height="20" rx="3" fill="#1A1F71" />
|
|
55
|
+
<text
|
|
56
|
+
x="16"
|
|
57
|
+
y="13.5"
|
|
58
|
+
textAnchor="middle"
|
|
59
|
+
fill="white"
|
|
60
|
+
fontSize="9"
|
|
61
|
+
fontWeight="bold"
|
|
62
|
+
fontFamily="sans-serif"
|
|
63
|
+
fontStyle="italic"
|
|
64
|
+
>
|
|
65
|
+
VISA
|
|
66
|
+
</text>
|
|
67
|
+
</svg>
|
|
68
|
+
);
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
function MastercardLogo() {
|
|
72
|
+
return (
|
|
73
|
+
<svg viewBox="0 0 32 20" style={{ width: 32, height: 20 }} aria-label="Mastercard">
|
|
74
|
+
<rect width="32" height="20" rx="3" fill="#252525" />
|
|
75
|
+
<circle cx="12.5" cy="10" r="6" fill="#EB001B" />
|
|
76
|
+
<circle cx="19.5" cy="10" r="6" fill="#F79E1B" />
|
|
77
|
+
<path d="M16 5.6a6 6 0 0 1 0 8.8 6 6 0 0 1 0-8.8z" fill="#FF5F00" />
|
|
78
|
+
</svg>
|
|
79
|
+
);
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
function AmexLogo() {
|
|
83
|
+
return (
|
|
84
|
+
<svg viewBox="0 0 32 20" style={{ width: 32, height: 20 }} aria-label="Amex">
|
|
85
|
+
<rect width="32" height="20" rx="3" fill="#006FCF" />
|
|
86
|
+
<text x="16" y="13" textAnchor="middle" fill="white" fontSize="7" fontWeight="bold" fontFamily="sans-serif">
|
|
87
|
+
AMEX
|
|
88
|
+
</text>
|
|
89
|
+
</svg>
|
|
90
|
+
);
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
/** Coinbase mark */
|
|
94
|
+
function CoinbaseLogo() {
|
|
95
|
+
return (
|
|
96
|
+
<svg viewBox="0 0 24 24" style={{ width: 20, height: 20 }} aria-label="Coinbase">
|
|
97
|
+
<circle cx="12" cy="12" r="12" fill="#0052FF" />
|
|
98
|
+
<path
|
|
99
|
+
d="M12 4.5a7.5 7.5 0 1 0 0 15 7.5 7.5 0 0 0 0-15zm-1.8 4.8h3.6c.33 0 .6.27.6.6v4.2c0 .33-.27.6-.6.6h-3.6a.6.6 0 0 1-.6-.6V9.9c0-.33.27-.6.6-.6z"
|
|
100
|
+
fill="white"
|
|
101
|
+
/>
|
|
102
|
+
</svg>
|
|
103
|
+
);
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
export function CheckoutPaymentPanel({
|
|
107
|
+
recipientAddress,
|
|
108
|
+
destinationTokenAddress,
|
|
109
|
+
destinationTokenChainId,
|
|
110
|
+
totalAmount,
|
|
111
|
+
buttonText,
|
|
112
|
+
themeColor,
|
|
113
|
+
returnUrl,
|
|
114
|
+
returnLabel,
|
|
115
|
+
onSuccess,
|
|
116
|
+
onError,
|
|
117
|
+
callbackMetadata,
|
|
118
|
+
classes,
|
|
119
|
+
}: CheckoutPaymentPanelProps) {
|
|
120
|
+
const [paymentMethod, setPaymentMethod] = useState<PaymentMethod>("crypto");
|
|
121
|
+
const [paymentResult, setPaymentResult] = useState<{ txHash?: string; orderId?: string } | null>(null);
|
|
122
|
+
|
|
123
|
+
const handleSuccess = (result: { txHash?: string; orderId?: string }) => {
|
|
124
|
+
setPaymentResult(result);
|
|
125
|
+
onSuccess?.(result);
|
|
126
|
+
};
|
|
127
|
+
|
|
128
|
+
if (paymentResult) {
|
|
129
|
+
return (
|
|
130
|
+
<CheckoutSuccess
|
|
131
|
+
txHash={paymentResult.txHash}
|
|
132
|
+
orderId={paymentResult.orderId}
|
|
133
|
+
returnUrl={returnUrl}
|
|
134
|
+
returnLabel={returnLabel}
|
|
135
|
+
classes={classes}
|
|
136
|
+
/>
|
|
137
|
+
);
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
const accordionButtonClass = (active: boolean) =>
|
|
141
|
+
cn(
|
|
142
|
+
"anyspend-payment-method-btn flex w-full items-center gap-3 px-4 py-4 text-left transition-colors",
|
|
143
|
+
active ? "bg-white dark:bg-gray-900" : "bg-white hover:bg-gray-50 dark:bg-gray-900 dark:hover:bg-gray-800",
|
|
144
|
+
classes?.paymentMethodButton,
|
|
145
|
+
);
|
|
146
|
+
|
|
147
|
+
const expandedPanelClass = cn(
|
|
148
|
+
"anyspend-payment-method-panel border-t border-gray-100 bg-white px-4 py-4 dark:border-gray-800 dark:bg-gray-900",
|
|
149
|
+
);
|
|
150
|
+
|
|
151
|
+
return (
|
|
152
|
+
<div className={cn("anyspend-payment-panel flex flex-col gap-5", classes?.paymentPanel)}>
|
|
153
|
+
<h2
|
|
154
|
+
className={cn(
|
|
155
|
+
"anyspend-payment-title text-lg font-semibold text-gray-900 dark:text-gray-100",
|
|
156
|
+
classes?.paymentTitle,
|
|
157
|
+
)}
|
|
158
|
+
>
|
|
159
|
+
Payment
|
|
160
|
+
</h2>
|
|
161
|
+
|
|
162
|
+
{/* Accordion-style payment methods */}
|
|
163
|
+
<div
|
|
164
|
+
className={cn(
|
|
165
|
+
"anyspend-payment-methods divide-y divide-gray-200 overflow-hidden rounded-xl border border-gray-200 dark:divide-gray-700 dark:border-gray-700",
|
|
166
|
+
classes?.paymentMethodSelector,
|
|
167
|
+
)}
|
|
168
|
+
>
|
|
169
|
+
{/* Crypto Wallet */}
|
|
170
|
+
<div className="anyspend-method-crypto">
|
|
171
|
+
<button
|
|
172
|
+
onClick={() => setPaymentMethod("crypto")}
|
|
173
|
+
className={accordionButtonClass(paymentMethod === "crypto")}
|
|
174
|
+
>
|
|
175
|
+
<RadioCircle selected={paymentMethod === "crypto"} themeColor={themeColor} />
|
|
176
|
+
<Wallet className="h-5 w-5 text-gray-700 dark:text-gray-300" />
|
|
177
|
+
<span className="text-sm font-medium text-gray-900 dark:text-gray-100">Crypto wallet</span>
|
|
178
|
+
</button>
|
|
179
|
+
<AnimatePresence initial={false}>
|
|
180
|
+
{paymentMethod === "crypto" && (
|
|
181
|
+
<motion.div
|
|
182
|
+
key="crypto-panel"
|
|
183
|
+
initial={{ height: 0, opacity: 0 }}
|
|
184
|
+
animate={{ height: "auto", opacity: 1 }}
|
|
185
|
+
exit={{ height: 0, opacity: 0 }}
|
|
186
|
+
transition={{ duration: 0.2, ease: "easeOut" }}
|
|
187
|
+
style={{ overflow: "hidden" }}
|
|
188
|
+
>
|
|
189
|
+
<div className={expandedPanelClass}>
|
|
190
|
+
<CryptoCheckoutPanel
|
|
191
|
+
recipientAddress={recipientAddress}
|
|
192
|
+
destinationTokenAddress={destinationTokenAddress}
|
|
193
|
+
destinationTokenChainId={destinationTokenChainId}
|
|
194
|
+
totalAmount={totalAmount}
|
|
195
|
+
buttonText={buttonText}
|
|
196
|
+
themeColor={themeColor}
|
|
197
|
+
onSuccess={handleSuccess}
|
|
198
|
+
onError={onError}
|
|
199
|
+
callbackMetadata={callbackMetadata}
|
|
200
|
+
classes={classes}
|
|
201
|
+
/>
|
|
202
|
+
</div>
|
|
203
|
+
</motion.div>
|
|
204
|
+
)}
|
|
205
|
+
</AnimatePresence>
|
|
206
|
+
</div>
|
|
207
|
+
|
|
208
|
+
{/* QR Code */}
|
|
209
|
+
<div className="anyspend-method-qr">
|
|
210
|
+
<button onClick={() => setPaymentMethod("qr")} className={accordionButtonClass(paymentMethod === "qr")}>
|
|
211
|
+
<RadioCircle selected={paymentMethod === "qr"} themeColor={themeColor} />
|
|
212
|
+
<QrCode className="h-5 w-5 text-gray-700 dark:text-gray-300" />
|
|
213
|
+
<span className="text-sm font-medium text-gray-900 dark:text-gray-100">QR code</span>
|
|
214
|
+
</button>
|
|
215
|
+
<AnimatePresence initial={false}>
|
|
216
|
+
{paymentMethod === "qr" && (
|
|
217
|
+
<motion.div
|
|
218
|
+
key="qr-panel"
|
|
219
|
+
initial={{ height: 0, opacity: 0 }}
|
|
220
|
+
animate={{ height: "auto", opacity: 1 }}
|
|
221
|
+
exit={{ height: 0, opacity: 0 }}
|
|
222
|
+
transition={{ duration: 0.2, ease: "easeOut" }}
|
|
223
|
+
style={{ overflow: "hidden" }}
|
|
224
|
+
>
|
|
225
|
+
<div className={expandedPanelClass}>
|
|
226
|
+
<QRCheckoutPanel
|
|
227
|
+
recipientAddress={recipientAddress}
|
|
228
|
+
destinationTokenAddress={destinationTokenAddress}
|
|
229
|
+
destinationTokenChainId={destinationTokenChainId}
|
|
230
|
+
totalAmount={totalAmount}
|
|
231
|
+
themeColor={themeColor}
|
|
232
|
+
onSuccess={handleSuccess}
|
|
233
|
+
onError={onError}
|
|
234
|
+
callbackMetadata={callbackMetadata}
|
|
235
|
+
classes={classes}
|
|
236
|
+
/>
|
|
237
|
+
</div>
|
|
238
|
+
</motion.div>
|
|
239
|
+
)}
|
|
240
|
+
</AnimatePresence>
|
|
241
|
+
</div>
|
|
242
|
+
|
|
243
|
+
{/* Credit or Debit Card */}
|
|
244
|
+
<div className="anyspend-method-card">
|
|
245
|
+
<button onClick={() => setPaymentMethod("card")} className={accordionButtonClass(paymentMethod === "card")}>
|
|
246
|
+
<RadioCircle selected={paymentMethod === "card"} themeColor={themeColor} />
|
|
247
|
+
<span className="text-sm font-medium text-gray-900 dark:text-gray-100">Credit or debit card</span>
|
|
248
|
+
<div className="ml-auto flex items-center gap-1">
|
|
249
|
+
<VisaLogo />
|
|
250
|
+
<MastercardLogo />
|
|
251
|
+
<AmexLogo />
|
|
252
|
+
</div>
|
|
253
|
+
</button>
|
|
254
|
+
<AnimatePresence initial={false}>
|
|
255
|
+
{paymentMethod === "card" && (
|
|
256
|
+
<motion.div
|
|
257
|
+
key="card-panel"
|
|
258
|
+
initial={{ height: 0, opacity: 0 }}
|
|
259
|
+
animate={{ height: "auto", opacity: 1 }}
|
|
260
|
+
exit={{ height: 0, opacity: 0 }}
|
|
261
|
+
transition={{ duration: 0.2, ease: "easeOut" }}
|
|
262
|
+
style={{ overflow: "hidden" }}
|
|
263
|
+
>
|
|
264
|
+
<div className={expandedPanelClass}>
|
|
265
|
+
<FiatCheckoutPanel
|
|
266
|
+
recipientAddress={recipientAddress}
|
|
267
|
+
destinationTokenAddress={destinationTokenAddress}
|
|
268
|
+
destinationTokenChainId={destinationTokenChainId}
|
|
269
|
+
totalAmount={totalAmount}
|
|
270
|
+
themeColor={themeColor}
|
|
271
|
+
onSuccess={handleSuccess}
|
|
272
|
+
onError={onError}
|
|
273
|
+
classes={classes}
|
|
274
|
+
/>
|
|
275
|
+
</div>
|
|
276
|
+
</motion.div>
|
|
277
|
+
)}
|
|
278
|
+
</AnimatePresence>
|
|
279
|
+
</div>
|
|
280
|
+
|
|
281
|
+
{/* Coinbase Pay */}
|
|
282
|
+
<div className="anyspend-method-coinbase">
|
|
283
|
+
<button
|
|
284
|
+
onClick={() => setPaymentMethod("coinbase")}
|
|
285
|
+
className={accordionButtonClass(paymentMethod === "coinbase")}
|
|
286
|
+
>
|
|
287
|
+
<RadioCircle selected={paymentMethod === "coinbase"} themeColor={themeColor} />
|
|
288
|
+
<CoinbaseLogo />
|
|
289
|
+
<span className="text-sm font-medium text-gray-900 dark:text-gray-100">Coinbase Pay</span>
|
|
290
|
+
</button>
|
|
291
|
+
<AnimatePresence initial={false}>
|
|
292
|
+
{paymentMethod === "coinbase" && (
|
|
293
|
+
<motion.div
|
|
294
|
+
key="coinbase-panel"
|
|
295
|
+
initial={{ height: 0, opacity: 0 }}
|
|
296
|
+
animate={{ height: "auto", opacity: 1 }}
|
|
297
|
+
exit={{ height: 0, opacity: 0 }}
|
|
298
|
+
transition={{ duration: 0.2, ease: "easeOut" }}
|
|
299
|
+
style={{ overflow: "hidden" }}
|
|
300
|
+
>
|
|
301
|
+
<div className={expandedPanelClass}>
|
|
302
|
+
<CoinbaseCheckoutPanel
|
|
303
|
+
recipientAddress={recipientAddress}
|
|
304
|
+
destinationTokenAddress={destinationTokenAddress}
|
|
305
|
+
destinationTokenChainId={destinationTokenChainId}
|
|
306
|
+
totalAmount={totalAmount}
|
|
307
|
+
themeColor={themeColor}
|
|
308
|
+
onSuccess={handleSuccess}
|
|
309
|
+
onError={onError}
|
|
310
|
+
classes={classes}
|
|
311
|
+
/>
|
|
312
|
+
</div>
|
|
313
|
+
</motion.div>
|
|
314
|
+
)}
|
|
315
|
+
</AnimatePresence>
|
|
316
|
+
</div>
|
|
317
|
+
</div>
|
|
318
|
+
</div>
|
|
319
|
+
);
|
|
320
|
+
}
|