@b3dotfun/sdk 0.0.79 → 0.0.80-alpha.1
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.js +23 -10
- package/dist/cjs/anyspend/react/components/AnySpendCollectorClubPurchase.js +9 -2
- package/dist/cjs/anyspend/react/components/AnySpendCustom.d.ts +2 -0
- package/dist/cjs/anyspend/react/components/AnySpendCustom.js +75 -19
- package/dist/cjs/anyspend/react/components/AnySpendNFT.js +6 -9
- package/dist/cjs/anyspend/react/components/common/CryptoReceiveSection.js +1 -3
- package/dist/cjs/anyspend/react/components/common/FiatPaymentMethod.d.ts +6 -1
- package/dist/cjs/anyspend/react/components/common/FiatPaymentMethod.js +40 -13
- package/dist/cjs/anyspend/react/components/common/PanelOnramp.js +13 -7
- package/dist/cjs/anyspend/react/components/common/PanelOnrampPayment.js +5 -3
- package/dist/cjs/anyspend/react/hooks/useGeoOnrampOptions.d.ts +2 -8
- package/dist/cjs/anyspend/react/hooks/useGeoOnrampOptions.js +4 -2
- package/dist/cjs/anyspend/react/hooks/useStripeSupport.d.ts +1 -0
- package/dist/cjs/anyspend/react/hooks/useStripeSupport.js +1 -0
- package/dist/cjs/global-account/react/components/IPFSMediaRenderer/IPFSMediaRenderer.js +5 -3
- package/dist/cjs/shared/utils/ipfs.d.ts +3 -3
- package/dist/cjs/shared/utils/ipfs.js +8 -8
- package/dist/esm/anyspend/react/components/AnySpend.js +23 -10
- package/dist/esm/anyspend/react/components/AnySpendCollectorClubPurchase.js +9 -2
- package/dist/esm/anyspend/react/components/AnySpendCustom.d.ts +2 -0
- package/dist/esm/anyspend/react/components/AnySpendCustom.js +76 -20
- package/dist/esm/anyspend/react/components/AnySpendNFT.js +7 -10
- package/dist/esm/anyspend/react/components/common/CryptoReceiveSection.js +1 -3
- package/dist/esm/anyspend/react/components/common/FiatPaymentMethod.d.ts +6 -1
- package/dist/esm/anyspend/react/components/common/FiatPaymentMethod.js +39 -12
- package/dist/esm/anyspend/react/components/common/PanelOnramp.js +14 -8
- package/dist/esm/anyspend/react/components/common/PanelOnrampPayment.js +5 -3
- package/dist/esm/anyspend/react/hooks/useGeoOnrampOptions.d.ts +2 -8
- package/dist/esm/anyspend/react/hooks/useGeoOnrampOptions.js +4 -2
- package/dist/esm/anyspend/react/hooks/useStripeSupport.d.ts +1 -0
- package/dist/esm/anyspend/react/hooks/useStripeSupport.js +1 -0
- package/dist/esm/global-account/react/components/IPFSMediaRenderer/IPFSMediaRenderer.js +5 -3
- package/dist/esm/shared/utils/ipfs.d.ts +3 -3
- package/dist/esm/shared/utils/ipfs.js +8 -8
- package/dist/styles/index.css +1 -1
- package/dist/types/anyspend/react/components/AnySpendCustom.d.ts +2 -0
- package/dist/types/anyspend/react/components/common/FiatPaymentMethod.d.ts +6 -1
- package/dist/types/anyspend/react/hooks/useGeoOnrampOptions.d.ts +2 -8
- package/dist/types/anyspend/react/hooks/useStripeSupport.d.ts +1 -0
- package/dist/types/shared/utils/ipfs.d.ts +3 -3
- package/package.json +1 -1
- package/src/anyspend/react/components/AnySpend.tsx +24 -10
- package/src/anyspend/react/components/AnySpendCollectorClubPurchase.tsx +9 -1
- package/src/anyspend/react/components/AnySpendCustom.tsx +113 -59
- package/src/anyspend/react/components/AnySpendNFT.tsx +49 -48
- package/src/anyspend/react/components/common/CryptoReceiveSection.tsx +1 -4
- package/src/anyspend/react/components/common/FiatPaymentMethod.tsx +53 -21
- package/src/anyspend/react/components/common/PanelOnramp.tsx +36 -40
- package/src/anyspend/react/components/common/PanelOnrampPayment.tsx +53 -16
- package/src/anyspend/react/hooks/useGeoOnrampOptions.ts +5 -2
- package/src/anyspend/react/hooks/useStripeSupport.ts +1 -0
- package/src/global-account/react/components/IPFSMediaRenderer/IPFSMediaRenderer.tsx +5 -7
- package/src/shared/utils/ipfs.ts +8 -8
|
@@ -18,7 +18,7 @@ function PanelOnrampPayment(props) {
|
|
|
18
18
|
}
|
|
19
19
|
function PanelOnrampPaymentInner(props) {
|
|
20
20
|
const { srcAmountOnRamp, recipientAddress, isBuyMode, destinationTokenChainId, destinationTokenAddress, selectedDstChainId, selectedDstToken, anyspendQuote, globalAddress, onOrderCreated, onBack, orderType, nft, tournament, payload, recipientEnsName, recipientImageUrl, } = props;
|
|
21
|
-
const { geoData, coinbaseOnrampOptions, coinbaseAvailablePaymentMethods, stripeWeb2Support, isLoading: isLoadingGeoOnramp, } = (0, react_1.useGeoOnrampOptions)(srcAmountOnRamp);
|
|
21
|
+
const { geoData, coinbaseOnrampOptions, coinbaseAvailablePaymentMethods, stripeOnrampSupport, stripeWeb2Support, isLoading: isLoadingGeoOnramp, } = (0, react_1.useGeoOnrampOptions)(srcAmountOnRamp);
|
|
22
22
|
const isLoading = isLoadingGeoOnramp;
|
|
23
23
|
const { createOrder, isCreatingOrder } = (0, react_1.useAnyspendCreateOnrampOrder)({
|
|
24
24
|
onSuccess: data => {
|
|
@@ -97,7 +97,9 @@ function PanelOnrampPaymentInner(props) {
|
|
|
97
97
|
? "Receive NFT at"
|
|
98
98
|
: orderType === "join_tournament"
|
|
99
99
|
? "Join for"
|
|
100
|
-
: "Recipient" }), (0, jsx_runtime_1.jsxs)("div", { className: "flex items-center gap-2", children: [recipientImageUrl && ((0, jsx_runtime_1.jsx)("img", { src: recipientImageUrl, alt: recipientImageUrl, className: "bg-b3-react-foreground size-7 rounded-full object-cover opacity-100" })), (0, jsx_runtime_1.jsxs)("div", { className: "flex flex-col items-end gap-1", children: [recipientEnsName && (0, jsx_runtime_1.jsxs)("span", { className: "text-b3-react-foreground/80", children: ["@", recipientEnsName] }), (0, jsx_runtime_1.jsx)("span", { className: "text-b3-react-foreground/80", children: (0, centerTruncate_1.default)(recipientAddress) })] })] })] })), (0, jsx_runtime_1.jsx)("div", { className: "border-b3-react-border border-t pt-3", children: (0, jsx_runtime_1.jsxs)("div", { className: "flex items-center justify-between", children: [(0, jsx_runtime_1.jsx)("p", { className: "text-b3-react-foreground font-semibold", children: "Amount" }), (0, jsx_runtime_1.jsxs)("div", { className: "flex flex-col items-end gap-0.5", children: [(0, jsx_runtime_1.jsxs)("p", { className: "text-b3-react-foreground hover:text-b3-react-foreground/80 cursor-pointer text-xl font-semibold transition-colors", onClick: onBack, children: ["$", parseFloat(srcAmountOnRamp).toFixed(2)] }), anyspendQuote?.data?.fee?.type === "standard_fee" &&
|
|
100
|
+
: "Recipient" }), (0, jsx_runtime_1.jsxs)("div", { className: "flex items-center gap-2", children: [recipientImageUrl && ((0, jsx_runtime_1.jsx)("img", { src: recipientImageUrl, alt: recipientImageUrl, className: "bg-b3-react-foreground size-7 rounded-full object-cover opacity-100" })), (0, jsx_runtime_1.jsxs)("div", { className: "flex flex-col items-end gap-1", children: [recipientEnsName && (0, jsx_runtime_1.jsxs)("span", { className: "text-b3-react-foreground/80", children: ["@", recipientEnsName] }), (0, jsx_runtime_1.jsx)("span", { className: "text-b3-react-foreground/80", children: (0, centerTruncate_1.default)(recipientAddress) })] })] })] })), (0, jsx_runtime_1.jsx)("div", { className: "border-b3-react-border border-t pt-3", children: (0, jsx_runtime_1.jsxs)("div", { className: "flex items-center justify-between", children: [(0, jsx_runtime_1.jsx)("p", { className: "text-b3-react-foreground font-semibold", children: "Amount" }), (0, jsx_runtime_1.jsxs)("div", { className: "flex flex-col items-end gap-0.5", children: [(0, jsx_runtime_1.jsxs)("p", { className: "text-b3-react-foreground hover:text-b3-react-foreground/80 cursor-pointer text-xl font-semibold transition-colors", onClick: onBack, children: ["$", parseFloat(srcAmountOnRamp).toFixed(2)] }), anyspendQuote?.data?.fee?.type === "standard_fee" &&
|
|
101
|
+
anyspendQuote.data.currencyIn?.amountUsd &&
|
|
102
|
+
anyspendQuote.data.fee.finalFeeBps > 0 && ((0, jsx_runtime_1.jsxs)("p", { className: "text-b3-react-foreground/60 text-xs", children: ["incl. $", ((Number(anyspendQuote.data.currencyIn.amountUsd) * anyspendQuote.data.fee.finalFeeBps) /
|
|
101
103
|
10000).toFixed(2), " ", "fee"] }))] })] }) })] })] }), isCreatingOrder ? ((0, jsx_runtime_1.jsxs)("div", { className: "bg-b3-react-background border-b3-react-border flex items-center justify-center gap-3 rounded-lg border p-6", children: [(0, jsx_runtime_1.jsx)(lucide_react_1.Loader2, { className: "h-4 w-4 animate-spin" }), (0, jsx_runtime_1.jsx)("span", { className: "text-as-primary/70", children: "Creating onramp order..." })] })) : isLoading ? ((0, jsx_runtime_1.jsxs)("div", { className: "bg-b3-react-background border-b3-react-border flex items-center justify-center gap-3 rounded-lg border p-6", children: [(0, jsx_runtime_1.jsx)(lucide_react_1.Loader2, { className: "h-4 w-4 animate-spin" }), (0, jsx_runtime_1.jsx)("span", { className: "text-as-primary/70", children: "Loading payment options..." })] })) : ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsxs)("div", { className: "mb-3 flex items-center justify-between", children: [(0, jsx_runtime_1.jsx)("h2", { className: "text-lg font-semibold", children: "Payment method" }), (0, jsx_runtime_1.jsx)("div", { className: "flex items-center gap-1", children: coinbaseAvailablePaymentMethods.length > 0 &&
|
|
102
104
|
(() => {
|
|
103
105
|
const hasCard = coinbaseAvailablePaymentMethods.some(m => m.id === "CARD");
|
|
@@ -108,5 +110,5 @@ function PanelOnrampPaymentInner(props) {
|
|
|
108
110
|
(() => {
|
|
109
111
|
const method = coinbaseAvailablePaymentMethods[0];
|
|
110
112
|
return ((0, jsx_runtime_1.jsxs)("button", { onClick: () => handlePaymentMethodClick("coinbase", method.id), disabled: isCreatingOrder, className: "bg-b3-react-background border-b3-react-border hover:border-as-brand disabled:hover:border-b3-react-border group flex w-full items-center justify-between gap-4 rounded-xl border p-5 transition-all duration-200 hover:shadow-md disabled:cursor-not-allowed disabled:opacity-50", children: [(0, jsx_runtime_1.jsxs)("div", { className: "flex items-center gap-4", children: [(0, jsx_runtime_1.jsx)("div", { className: "flex h-12 w-12 items-center justify-center rounded-full bg-blue-50", children: (0, jsx_runtime_1.jsx)("img", { src: "https://cdn.b3.fun/coinbase-wordmark-blue.svg", alt: "Coinbase", className: "h-6" }) }), (0, jsx_runtime_1.jsxs)("div", { className: "flex flex-col items-start text-left", children: [(0, jsx_runtime_1.jsx)("h4", { className: "text-b3-react-foreground text-lg font-semibold", children: "Coinbase Pay" }), (0, jsx_runtime_1.jsxs)("p", { className: "text-b3-react-foreground/60 text-sm", children: [method.id === "CARD" && "Debit card, bank account, or Coinbase Account", method.id === "FIAT_WALLET" && "Pay with your Coinbase account balance", method.id === "APPLE_PAY" && "Quick payment with Apple Pay", method.id === "ACH_BANK_ACCOUNT" && "Direct bank account transfer"] }), (0, jsx_runtime_1.jsx)("div", { className: "mt-1 flex items-center gap-1", children: (0, jsx_runtime_1.jsx)("span", { className: "text-xs font-medium text-green-600", children: "Free" }) })] })] }), (0, jsx_runtime_1.jsx)(lucide_react_1.ChevronRight, { className: "text-b3-react-foreground/40 group-hover:text-b3-react-foreground/60 h-5 w-5 transition-colors" })] }));
|
|
111
|
-
})(),
|
|
113
|
+
})(), stripeOnrampSupport && ((0, jsx_runtime_1.jsxs)("button", { onClick: () => handlePaymentMethodClick("stripe"), className: "bg-b3-react-background border-b3-react-border hover:border-as-brand group flex w-full items-center justify-between gap-4 rounded-xl border p-5 transition-all duration-200 hover:shadow-md", children: [(0, jsx_runtime_1.jsxs)("div", { className: "flex items-center gap-4", children: [(0, jsx_runtime_1.jsx)("div", { className: "flex h-12 w-12 items-center justify-center rounded-full bg-purple-50", children: (0, jsx_runtime_1.jsx)("img", { src: "https://raw.githubusercontent.com/stripe/stripe.github.io/455f506a628dc3f6c505e3001db45a64e29e9fc3/images/stripe-logo.svg", alt: "Stripe", className: "h-5" }) }), (0, jsx_runtime_1.jsxs)("div", { className: "flex flex-col items-start text-left", children: [(0, jsx_runtime_1.jsx)("h4", { className: "text-b3-react-foreground text-lg font-semibold", children: "Credit/Debit Card" }), (0, jsx_runtime_1.jsx)("p", { className: "text-b3-react-foreground/60 text-sm", children: "Pay via Stripe checkout" }), stripeWeb2Support?.isSupport && stripeWeb2Support.formattedFeeUsd && ((0, jsx_runtime_1.jsx)("div", { className: "mt-1", children: (0, jsx_runtime_1.jsxs)("span", { className: "text-xs text-gray-500", children: ["$", Number(stripeWeb2Support.formattedFeeUsd).toFixed(2), " fee"] }) }))] })] }), (0, jsx_runtime_1.jsx)(lucide_react_1.ChevronRight, { className: "text-b3-react-foreground/40 group-hover:text-b3-react-foreground/60 h-5 w-5 transition-colors" })] })), stripeWeb2Support.isSupport && ((0, jsx_runtime_1.jsxs)("button", { onClick: () => handlePaymentMethodClick("stripe-web2"), className: "bg-b3-react-background border-b3-react-border hover:border-as-brand group flex w-full items-center justify-between gap-4 rounded-xl border p-5 transition-all duration-200 hover:shadow-md", children: [(0, jsx_runtime_1.jsxs)("div", { className: "flex items-center gap-4", children: [(0, jsx_runtime_1.jsx)("div", { className: "flex h-12 w-12 items-center justify-center rounded-full bg-purple-50", children: (0, jsx_runtime_1.jsx)("img", { src: "https://raw.githubusercontent.com/stripe/stripe.github.io/455f506a628dc3f6c505e3001db45a64e29e9fc3/images/stripe-logo.svg", alt: "Stripe", className: "h-5" }) }), (0, jsx_runtime_1.jsxs)("div", { className: "flex flex-col items-start text-left", children: [(0, jsx_runtime_1.jsx)("h4", { className: "text-b3-react-foreground text-lg font-semibold", children: "Quick Pay" }), (0, jsx_runtime_1.jsx)("p", { className: "text-b3-react-foreground/60 text-sm", children: "Credit or debit card" }), stripeWeb2Support.formattedFeeUsd && ((0, jsx_runtime_1.jsx)("div", { className: "mt-1", children: (0, jsx_runtime_1.jsxs)("span", { className: "text-xs text-gray-500", children: ["$", Number(stripeWeb2Support.formattedFeeUsd).toFixed(2), " fee"] }) }))] })] }), (0, jsx_runtime_1.jsx)(lucide_react_1.ChevronRight, { className: "text-b3-react-foreground/40 group-hover:text-b3-react-foreground/60 h-5 w-5 transition-colors" })] })), (0, jsx_runtime_1.jsxs)(react_2.Button, { variant: "link", onClick: onBack, className: "text-b3-react-foreground/70 hover:text-b3-react-foreground/90 mt-2 w-full", children: [(0, jsx_runtime_1.jsx)(lucide_react_1.ChevronLeft, { className: "mr-2 h-4 w-4" }), "Back"] })] })] }))] }));
|
|
112
114
|
}
|
|
@@ -30,6 +30,7 @@ export declare function useGeoOnrampOptions(srcFiatAmount: string): {
|
|
|
30
30
|
min?: string;
|
|
31
31
|
max?: string;
|
|
32
32
|
}[];
|
|
33
|
+
stripeOnrampSupport: boolean;
|
|
33
34
|
stripeWeb2Support: {
|
|
34
35
|
isSupport: false;
|
|
35
36
|
} | {
|
|
@@ -38,14 +39,7 @@ export declare function useGeoOnrampOptions(srcFiatAmount: string): {
|
|
|
38
39
|
formattedOnrampUsd: string;
|
|
39
40
|
formattedFeeUsd: string;
|
|
40
41
|
};
|
|
41
|
-
isOnrampSupported:
|
|
42
|
-
isSupport: false;
|
|
43
|
-
} | {
|
|
44
|
-
isSupport: true;
|
|
45
|
-
formattedTotalUsd: string;
|
|
46
|
-
formattedOnrampUsd: string;
|
|
47
|
-
formattedFeeUsd: string;
|
|
48
|
-
};
|
|
42
|
+
isOnrampSupported: boolean;
|
|
49
43
|
isLoading: boolean | undefined;
|
|
50
44
|
isLoadingGeo: boolean;
|
|
51
45
|
isLoadingCoinbaseOnrampOptions: boolean;
|
|
@@ -16,7 +16,7 @@ function useGeoOnrampOptions(srcFiatAmount) {
|
|
|
16
16
|
// Use existing hooks
|
|
17
17
|
const { geoData, loading: isLoadingGeo, error: geoError } = (0, useGetGeo_1.useGetGeo)();
|
|
18
18
|
const { coinbaseOnrampOptions, isLoadingCoinbaseOnrampOptions, coinbaseOnrampOptionsError } = (0, useCoinbaseOnrampOptions_1.useCoinbaseOnrampOptions)(geoData?.country, visitorData);
|
|
19
|
-
const { stripeWeb2Support, isLoadingStripeSupport, stripeSupportError } = (0, useStripeSupport_1.useStripeSupport)(srcFiatAmount, visitorData);
|
|
19
|
+
const { stripeOnrampSupport, stripeWeb2Support, isLoadingStripeSupport, stripeSupportError } = (0, useStripeSupport_1.useStripeSupport)(srcFiatAmount, visitorData);
|
|
20
20
|
// Calculate available payment methods based on the amount
|
|
21
21
|
const coinbaseAvailablePaymentMethods = (0, react_1.useMemo)(() => {
|
|
22
22
|
if (!coinbaseOnrampOptions?.paymentCurrencies?.[0]?.limits || !srcFiatAmount)
|
|
@@ -34,8 +34,9 @@ function useGeoOnrampOptions(srcFiatAmount) {
|
|
|
34
34
|
geoData,
|
|
35
35
|
coinbaseOnrampOptions,
|
|
36
36
|
coinbaseAvailablePaymentMethods,
|
|
37
|
+
stripeOnrampSupport,
|
|
37
38
|
stripeWeb2Support,
|
|
38
|
-
isOnrampSupported: coinbaseAvailablePaymentMethods.length > 0 || stripeWeb2Support,
|
|
39
|
+
isOnrampSupported: coinbaseAvailablePaymentMethods.length > 0 || stripeOnrampSupport || stripeWeb2Support.isSupport,
|
|
39
40
|
isLoading: isLoadingGeo || isLoadingCoinbaseOnrampOptions || isLoadingStripeSupport || isLoadingVisitorData,
|
|
40
41
|
isLoadingGeo,
|
|
41
42
|
isLoadingCoinbaseOnrampOptions,
|
|
@@ -47,6 +48,7 @@ function useGeoOnrampOptions(srcFiatAmount) {
|
|
|
47
48
|
geoData,
|
|
48
49
|
coinbaseOnrampOptions,
|
|
49
50
|
coinbaseAvailablePaymentMethods,
|
|
51
|
+
stripeOnrampSupport,
|
|
50
52
|
stripeWeb2Support,
|
|
51
53
|
isLoadingGeo,
|
|
52
54
|
isLoadingCoinbaseOnrampOptions,
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { VisitorData } from "../../../anyspend/types/fingerprint";
|
|
2
2
|
export declare function useStripeSupport(usdAmount?: string, visitorData?: VisitorData, isLoadingVisitorData?: boolean): {
|
|
3
|
+
stripeOnrampSupport: boolean;
|
|
3
4
|
stripeWeb2Support: {
|
|
4
5
|
isSupport: false;
|
|
5
6
|
} | {
|
|
@@ -11,6 +11,7 @@ function useStripeSupport(usdAmount, visitorData, isLoadingVisitorData) {
|
|
|
11
11
|
enabled: !isLoadingVisitorData,
|
|
12
12
|
});
|
|
13
13
|
return (0, react_1.useMemo)(() => ({
|
|
14
|
+
stripeOnrampSupport: data?.stripeOnramp || false,
|
|
14
15
|
stripeWeb2Support: data?.stripeWeb2 || { isSupport: false },
|
|
15
16
|
isLoadingStripeSupport: isLoading,
|
|
16
17
|
stripeSupportError: error,
|
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4
4
|
exports.IPFSMediaRenderer = IPFSMediaRenderer;
|
|
5
5
|
const jsx_runtime_1 = require("react/jsx-runtime");
|
|
6
|
+
const ipfs_1 = require("../../../../shared/utils/ipfs");
|
|
6
7
|
const thirdweb_1 = require("../../../../shared/utils/thirdweb");
|
|
7
8
|
const react_1 = require("thirdweb/react");
|
|
8
9
|
/**
|
|
@@ -28,7 +29,8 @@ function IPFSMediaRenderer({ src, alt = "Media", className, client = thirdweb_1.
|
|
|
28
29
|
if (!src) {
|
|
29
30
|
return ((0, jsx_runtime_1.jsx)("div", { className: className, style: style, "aria-label": alt, children: (0, jsx_runtime_1.jsx)("div", { className: "bg-b3-primary-wash flex h-full w-full items-center justify-center rounded-full", children: (0, jsx_runtime_1.jsx)("span", { className: "text-b3-grey font-neue-montreal-semibold text-xs", children: alt.charAt(0).toUpperCase() }) }) }));
|
|
30
31
|
}
|
|
31
|
-
// Convert IPFS URLs to HTTP gateway URLs
|
|
32
|
-
// This
|
|
33
|
-
|
|
32
|
+
// Convert IPFS URLs to HTTP gateway URLs using our preferred gateway
|
|
33
|
+
// This avoids Thirdweb's default cloudflare-ipfs.com which can be unreliable
|
|
34
|
+
const resolvedSrc = src.startsWith("ipfs://") ? (0, ipfs_1.getIpfsUrl)(src) : src;
|
|
35
|
+
return ((0, jsx_runtime_1.jsx)(react_1.MediaRenderer, { src: resolvedSrc, client: client, alt: alt, className: className, width: width ? width.toString() : undefined, height: height ? height.toString() : undefined, controls: controls, style: style }));
|
|
34
36
|
}
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Converts an IPFS URL to a gateway URL
|
|
3
3
|
* @param ipfsUrl - URL in format ipfs://CID/path or just the CID
|
|
4
|
-
* @param gatewayIndex - Optional index to specify which gateway to use (0:
|
|
4
|
+
* @param gatewayIndex - Optional index to specify which gateway to use (0: dweb.link, 1: w3s.link, etc.)
|
|
5
5
|
* @returns HTTP URL using the specified IPFS gateway
|
|
6
6
|
* @example
|
|
7
|
-
* // returns 'https://
|
|
7
|
+
* // returns 'https://dweb.link/ipfs/QmUbJ4p.../2.png'
|
|
8
8
|
* getIpfsUrl('ipfs://QmUbJ4pnHMNXGeWWhBFFSEqCGuc6cEtDyz35wQfv7k2TXy/2.png')
|
|
9
|
-
* // returns 'https://
|
|
9
|
+
* // returns 'https://w3s.link/ipfs/QmUbJ4p.../2.png'
|
|
10
10
|
* getIpfsUrl('ipfs://QmUbJ4pnHMNXGeWWhBFFSEqCGuc6cEtDyz35wQfv7k2TXy/2.png', 1)
|
|
11
11
|
*/
|
|
12
12
|
export declare function getIpfsUrl(ipfsUrl: string, gatewayIndex?: number): string;
|
|
@@ -6,22 +6,22 @@ exports.getIpfsUrl = getIpfsUrl;
|
|
|
6
6
|
* These gateways must match the allowed list in profileDisplay.ts validateImageUrl()
|
|
7
7
|
*/
|
|
8
8
|
const IPFS_GATEWAYS = [
|
|
9
|
-
"https://
|
|
9
|
+
"https://dweb.link/ipfs", // Primary gateway - Protocol Labs maintained
|
|
10
|
+
"https://w3s.link/ipfs", // web3.storage gateway - reliable
|
|
11
|
+
"https://nftstorage.link/ipfs", // NFT.storage gateway
|
|
12
|
+
"https://gateway.pinata.cloud/ipfs", // Pinata gateway
|
|
10
13
|
"https://ipfs.io/ipfs", // Fallback gateway
|
|
11
|
-
"https://
|
|
12
|
-
"https://dweb.link/ipfs", // Additional option
|
|
13
|
-
"https://nftstorage.link/ipfs", // Additional option
|
|
14
|
-
"https://w3s.link/ipfs", // Additional option
|
|
14
|
+
"https://cloudflare-ipfs.com/ipfs", // Cloudflare gateway (can be slow/unreliable)
|
|
15
15
|
];
|
|
16
16
|
/**
|
|
17
17
|
* Converts an IPFS URL to a gateway URL
|
|
18
18
|
* @param ipfsUrl - URL in format ipfs://CID/path or just the CID
|
|
19
|
-
* @param gatewayIndex - Optional index to specify which gateway to use (0:
|
|
19
|
+
* @param gatewayIndex - Optional index to specify which gateway to use (0: dweb.link, 1: w3s.link, etc.)
|
|
20
20
|
* @returns HTTP URL using the specified IPFS gateway
|
|
21
21
|
* @example
|
|
22
|
-
* // returns 'https://
|
|
22
|
+
* // returns 'https://dweb.link/ipfs/QmUbJ4p.../2.png'
|
|
23
23
|
* getIpfsUrl('ipfs://QmUbJ4pnHMNXGeWWhBFFSEqCGuc6cEtDyz35wQfv7k2TXy/2.png')
|
|
24
|
-
* // returns 'https://
|
|
24
|
+
* // returns 'https://w3s.link/ipfs/QmUbJ4p.../2.png'
|
|
25
25
|
* getIpfsUrl('ipfs://QmUbJ4pnHMNXGeWWhBFFSEqCGuc6cEtDyz35wQfv7k2TXy/2.png', 1)
|
|
26
26
|
*/
|
|
27
27
|
function getIpfsUrl(ipfsUrl, gatewayIndex = 0) {
|
|
@@ -355,18 +355,18 @@ function AnySpendInner({ destinationTokenAddress, destinationTokenChainId, mode
|
|
|
355
355
|
isBalanceLoading,
|
|
356
356
|
});
|
|
357
357
|
// Get geo-based onramp options for fiat payments
|
|
358
|
-
const { geoData, coinbaseAvailablePaymentMethods, stripeWeb2Support } = useGeoOnrampOptions(srcAmountOnRamp);
|
|
358
|
+
const { geoData, coinbaseAvailablePaymentMethods, stripeOnrampSupport, stripeWeb2Support } = useGeoOnrampOptions(srcAmountOnRamp);
|
|
359
359
|
// Helper function to map payment method to onramp vendor
|
|
360
360
|
const getOnrampVendor = (paymentMethod) => {
|
|
361
361
|
switch (paymentMethod) {
|
|
362
362
|
case FiatPaymentMethod.COINBASE_PAY:
|
|
363
363
|
return "coinbase";
|
|
364
364
|
case FiatPaymentMethod.STRIPE:
|
|
365
|
-
//
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
return undefined;
|
|
365
|
+
// Stripe redirect flow (one-click URL)
|
|
366
|
+
return stripeOnrampSupport ? "stripe" : undefined;
|
|
367
|
+
case FiatPaymentMethod.STRIPE_WEB2:
|
|
368
|
+
// Stripe embedded payment form
|
|
369
|
+
return stripeWeb2Support?.isSupport ? "stripe-web2" : undefined;
|
|
370
370
|
default:
|
|
371
371
|
return undefined;
|
|
372
372
|
}
|
|
@@ -511,7 +511,9 @@ function AnySpendInner({ destinationTokenAddress, destinationTokenChainId, mode
|
|
|
511
511
|
}, [activeTab, selectedSrcChainId, selectedDstChainId, selectedSrcToken.address, selectedDstToken.address]);
|
|
512
512
|
// Determine button state and text
|
|
513
513
|
const btnInfo = useMemo(() => {
|
|
514
|
-
|
|
514
|
+
// For fiat tab, check srcAmountOnRamp; for crypto tab, check activeInputAmountInWei
|
|
515
|
+
const hasAmount = activeTab === "fiat" ? srcAmountOnRamp && parseFloat(srcAmountOnRamp) > 0 : activeInputAmountInWei !== "0";
|
|
516
|
+
if (!hasAmount)
|
|
515
517
|
return { text: "Enter an amount", disable: true, error: false, loading: false };
|
|
516
518
|
if (isSameChainSameToken)
|
|
517
519
|
return { text: "Select a different token or chain", disable: true, error: false, loading: false };
|
|
@@ -562,6 +564,7 @@ function AnySpendInner({ destinationTokenAddress, destinationTokenChainId, mode
|
|
|
562
564
|
activeTab,
|
|
563
565
|
effectiveCryptoPaymentMethod,
|
|
564
566
|
selectedFiatPaymentMethod,
|
|
567
|
+
srcAmountOnRamp,
|
|
565
568
|
]);
|
|
566
569
|
// Handle main button click
|
|
567
570
|
const onMainButtonClick = async () => {
|
|
@@ -676,11 +679,21 @@ function AnySpendInner({ destinationTokenAddress, destinationTokenChainId, mode
|
|
|
676
679
|
paymentMethodString = coinbaseAvailablePaymentMethods[0]?.id || ""; // Use first available payment method ID
|
|
677
680
|
}
|
|
678
681
|
else if (paymentMethod === FiatPaymentMethod.STRIPE) {
|
|
679
|
-
|
|
680
|
-
|
|
682
|
+
// Stripe redirect flow (one-click URL)
|
|
683
|
+
if (!stripeOnrampSupport) {
|
|
684
|
+
toast.error("Credit/Debit Card not available");
|
|
685
|
+
return;
|
|
686
|
+
}
|
|
687
|
+
vendor = "stripe";
|
|
688
|
+
paymentMethodString = "";
|
|
689
|
+
}
|
|
690
|
+
else if (paymentMethod === FiatPaymentMethod.STRIPE_WEB2) {
|
|
691
|
+
// Stripe embedded payment form
|
|
692
|
+
if (!stripeWeb2Support.isSupport) {
|
|
693
|
+
toast.error("Pay with Card not available");
|
|
681
694
|
return;
|
|
682
695
|
}
|
|
683
|
-
vendor =
|
|
696
|
+
vendor = "stripe-web2";
|
|
684
697
|
paymentMethodString = "";
|
|
685
698
|
}
|
|
686
699
|
else {
|
|
@@ -26,11 +26,12 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
|
26
26
|
* ```
|
|
27
27
|
*/
|
|
28
28
|
import { USDC_BASE } from "../../../anyspend/constants/index.js";
|
|
29
|
+
import { formatUnits } from "../../../shared/utils/number.js";
|
|
29
30
|
import { useMemo } from "react";
|
|
30
31
|
import { encodeFunctionData } from "viem";
|
|
31
32
|
import { AnySpendCustom } from "./AnySpendCustom.js";
|
|
32
33
|
// Collector Club Shop contract on Base
|
|
33
|
-
const CC_SHOP_ADDRESS = "
|
|
34
|
+
const CC_SHOP_ADDRESS = "0x23887D10c81118A9a2E3Af59C423e2f4ee4Cc7Cf";
|
|
34
35
|
const BASE_CHAIN_ID = 8453;
|
|
35
36
|
// ABI for buyPacksFor function only
|
|
36
37
|
const BUY_PACKS_FOR_ABI = {
|
|
@@ -55,6 +56,12 @@ export function AnySpendCollectorClubPurchase({ loadOrder, mode = "modal", activ
|
|
|
55
56
|
return "0";
|
|
56
57
|
}
|
|
57
58
|
}, [pricePerPack, packAmount]);
|
|
59
|
+
// Calculate fiat amount (totalAmount in USD, assuming USDC with 6 decimals)
|
|
60
|
+
const srcFiatAmount = useMemo(() => {
|
|
61
|
+
if (!totalAmount || totalAmount === "0")
|
|
62
|
+
return "0";
|
|
63
|
+
return formatUnits(totalAmount, USDC_BASE.decimals);
|
|
64
|
+
}, [totalAmount]);
|
|
58
65
|
// Encode the buyPacksFor function call
|
|
59
66
|
const encodedData = useMemo(() => {
|
|
60
67
|
try {
|
|
@@ -77,5 +84,5 @@ export function AnySpendCollectorClubPurchase({ loadOrder, mode = "modal", activ
|
|
|
77
84
|
pricePerPack,
|
|
78
85
|
vendingMachineId,
|
|
79
86
|
packType,
|
|
80
|
-
}, header: header || defaultHeader, onSuccess: onSuccess, showRecipient: showRecipient }));
|
|
87
|
+
}, header: header || defaultHeader, onSuccess: onSuccess, showRecipient: showRecipient, srcFiatAmount: srcFiatAmount }));
|
|
81
88
|
}
|
|
@@ -21,4 +21,6 @@ export declare function AnySpendCustom(props: {
|
|
|
21
21
|
onSuccess?: (txHash?: string) => void;
|
|
22
22
|
showRecipient?: boolean;
|
|
23
23
|
onShowPointsDetail?: () => void;
|
|
24
|
+
/** Fiat amount in USD for fiat payments */
|
|
25
|
+
srcFiatAmount?: string;
|
|
24
26
|
}): import("react/jsx-runtime").JSX.Element;
|
|
@@ -13,14 +13,13 @@ import { ChevronRight, ChevronRightCircle, Info, Loader2 } from "lucide-react";
|
|
|
13
13
|
import { motion } from "motion/react";
|
|
14
14
|
import React, { useCallback, useEffect, useMemo, useState } from "react";
|
|
15
15
|
import { base } from "viem/chains";
|
|
16
|
-
import { useFeatureFlags } from "../contexts/FeatureFlagsContext.js";
|
|
17
16
|
import { useAutoSetActiveWalletFromWagmi } from "../hooks/useAutoSetActiveWalletFromWagmi.js";
|
|
18
17
|
import { useCryptoPaymentMethodState } from "../hooks/useCryptoPaymentMethodState.js";
|
|
19
18
|
import { useRecipientAddressState } from "../hooks/useRecipientAddressState.js";
|
|
20
19
|
import { AnySpendFingerprintWrapper, getFingerprintConfig } from "./AnySpendFingerprintWrapper.js";
|
|
21
20
|
import { CryptoPaymentMethod, CryptoPaymentMethodType } from "./common/CryptoPaymentMethod.js";
|
|
22
21
|
import { FeeBreakDown } from "./common/FeeBreakDown.js";
|
|
23
|
-
import { FiatPaymentMethod, FiatPaymentMethodComponent } from "./common/FiatPaymentMethod.js";
|
|
22
|
+
import { FIAT_PAYMENT_METHOD_DISPLAY, FiatPaymentMethod, FiatPaymentMethodComponent } from "./common/FiatPaymentMethod.js";
|
|
24
23
|
import { OrderDetails } from "./common/OrderDetails.js";
|
|
25
24
|
import { OrderHistory } from "./common/OrderHistory.js";
|
|
26
25
|
import { OrderToken } from "./common/OrderToken.js";
|
|
@@ -108,9 +107,8 @@ export function AnySpendCustom(props) {
|
|
|
108
107
|
const fingerprintConfig = getFingerprintConfig();
|
|
109
108
|
return (_jsx(AnySpendFingerprintWrapper, { fingerprint: fingerprintConfig, children: _jsx(AnySpendCustomInner, { ...props }) }));
|
|
110
109
|
}
|
|
111
|
-
function AnySpendCustomInner({ loadOrder, mode = "modal", activeTab: activeTabProps = "crypto", recipientAddress: recipientAddressProps, spenderAddress, orderType, dstChainId, dstToken, dstAmount, contractAddress, encodedData, metadata, header, onSuccess, showRecipient = true, onShowPointsDetail, }) {
|
|
110
|
+
function AnySpendCustomInner({ loadOrder, mode = "modal", activeTab: activeTabProps = "crypto", recipientAddress: recipientAddressProps, spenderAddress, orderType, dstChainId, dstToken, dstAmount, contractAddress, encodedData, metadata, header, onSuccess, showRecipient = true, onShowPointsDetail, srcFiatAmount: srcFiatAmountProps, }) {
|
|
112
111
|
const hasMounted = useHasMounted();
|
|
113
|
-
const featureFlags = useFeatureFlags();
|
|
114
112
|
const searchParams = useSearchParamsSSR();
|
|
115
113
|
const router = useRouter();
|
|
116
114
|
// Auto-set active wallet from wagmi
|
|
@@ -199,7 +197,11 @@ function AnySpendCustomInner({ loadOrder, mode = "modal", activeTab: activeTabPr
|
|
|
199
197
|
contractType: orderType === "mint_nft" ? metadata?.nftContract?.type : undefined,
|
|
200
198
|
encodedData: encodedData,
|
|
201
199
|
spenderAddress: spenderAddress,
|
|
202
|
-
onrampVendor: selectedFiatPaymentMethod === FiatPaymentMethod.STRIPE
|
|
200
|
+
onrampVendor: selectedFiatPaymentMethod === FiatPaymentMethod.STRIPE
|
|
201
|
+
? "stripe"
|
|
202
|
+
: selectedFiatPaymentMethod === FiatPaymentMethod.STRIPE_WEB2
|
|
203
|
+
? "stripe-web2"
|
|
204
|
+
: undefined,
|
|
203
205
|
});
|
|
204
206
|
}, [
|
|
205
207
|
activeTab,
|
|
@@ -243,9 +245,29 @@ function AnySpendCustomInner({ loadOrder, mode = "modal", activeTab: activeTabPr
|
|
|
243
245
|
}
|
|
244
246
|
}, [activeTab, anyspendQuote?.data]);
|
|
245
247
|
const formattedSrcAmount = srcAmount ? formatTokenAmount(srcAmount, srcToken.decimals, 6, false) : null;
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
248
|
+
// Calculate fiat amount for geo check (regardless of activeTab) to determine tab availability
|
|
249
|
+
const srcFiatAmountForGeoCheck = useMemo(() => {
|
|
250
|
+
// Use prop if provided
|
|
251
|
+
if (srcFiatAmountProps) {
|
|
252
|
+
return srcFiatAmountProps;
|
|
253
|
+
}
|
|
254
|
+
// Fallback to dstAmount if destination token is USDC
|
|
255
|
+
if (dstAmount && dstToken.address.toLowerCase() === USDC_BASE.address.toLowerCase()) {
|
|
256
|
+
return formatUnits(dstAmount, USDC_BASE.decimals);
|
|
257
|
+
}
|
|
258
|
+
// Use srcAmount if available (from quote)
|
|
259
|
+
if (srcAmount) {
|
|
260
|
+
return formatUnits(srcAmount.toString(), USDC_BASE.decimals);
|
|
261
|
+
}
|
|
262
|
+
return "0";
|
|
263
|
+
}, [srcAmount, srcFiatAmountProps, dstAmount, dstToken.address]);
|
|
264
|
+
const srcFiatAmount = useMemo(() => {
|
|
265
|
+
if (activeTab !== "fiat")
|
|
266
|
+
return "0";
|
|
267
|
+
return srcFiatAmountForGeoCheck;
|
|
268
|
+
}, [activeTab, srcFiatAmountForGeoCheck]);
|
|
269
|
+
// Get geo data and onramp options (use srcFiatAmountForGeoCheck to check availability regardless of activeTab)
|
|
270
|
+
const { geoData, isOnrampSupported, coinbaseAvailablePaymentMethods, stripeOnrampSupport, stripeWeb2Support } = useGeoOnrampOptions(srcFiatAmountForGeoCheck);
|
|
249
271
|
useEffect(() => {
|
|
250
272
|
if (oat?.data?.order.status === "executed" && !onSuccessCalled.current) {
|
|
251
273
|
console.log("Calling onSuccess");
|
|
@@ -340,9 +362,13 @@ function AnySpendCustomInner({ loadOrder, mode = "modal", activeTab: activeTabPr
|
|
|
340
362
|
invariant((activeTab === "fiat" ? base.id : srcChainId) === base.id, "Selected src chain is not base");
|
|
341
363
|
// Get the current geo data from the hook
|
|
342
364
|
const currentGeoData = geoData;
|
|
365
|
+
// Use total amount from quote (includes fees) for onramp, fallback to srcFiatAmount
|
|
366
|
+
const onrampAmount = anyspendQuote?.data?.currencyIn?.amountUsd
|
|
367
|
+
? anyspendQuote.data.currencyIn.amountUsd.toString()
|
|
368
|
+
: srcFiatAmount;
|
|
343
369
|
void createOnrampOrder({
|
|
344
370
|
...createOrderParams,
|
|
345
|
-
srcFiatAmount:
|
|
371
|
+
srcFiatAmount: onrampAmount,
|
|
346
372
|
onramp: {
|
|
347
373
|
vendor: onramp.vendor,
|
|
348
374
|
paymentMethod: onramp.paymentMethod,
|
|
@@ -412,12 +438,22 @@ function AnySpendCustomInner({ loadOrder, mode = "modal", activeTab: activeTabPr
|
|
|
412
438
|
vendor = "coinbase";
|
|
413
439
|
paymentMethodString = coinbaseAvailablePaymentMethods[0]?.id || "";
|
|
414
440
|
}
|
|
415
|
-
else if (paymentMethod === FiatPaymentMethod.
|
|
441
|
+
else if (paymentMethod === FiatPaymentMethod.STRIPE_WEB2) {
|
|
442
|
+
// Stripe Web2 embedded payment
|
|
416
443
|
if (!stripeWeb2Support || !stripeWeb2Support.isSupport) {
|
|
417
|
-
toast.error("Stripe not available");
|
|
444
|
+
toast.error("Stripe embedded payment not available");
|
|
418
445
|
return;
|
|
419
446
|
}
|
|
420
|
-
vendor =
|
|
447
|
+
vendor = "stripe-web2";
|
|
448
|
+
paymentMethodString = "";
|
|
449
|
+
}
|
|
450
|
+
else if (paymentMethod === FiatPaymentMethod.STRIPE) {
|
|
451
|
+
// Stripe redirect (one-click buy URL)
|
|
452
|
+
if (!stripeOnrampSupport) {
|
|
453
|
+
toast.error("Stripe redirect payment not available");
|
|
454
|
+
return;
|
|
455
|
+
}
|
|
456
|
+
vendor = "stripe";
|
|
421
457
|
paymentMethodString = "";
|
|
422
458
|
}
|
|
423
459
|
else {
|
|
@@ -464,7 +500,7 @@ function AnySpendCustomInner({ loadOrder, mode = "modal", activeTab: activeTabPr
|
|
|
464
500
|
const loadingView = (_jsxs("div", { className: cn("mx-auto flex w-full flex-col items-center gap-4 p-5", mode === "modal" && "bg-b3-react-background"), children: [_jsxs(Badge, { variant: "default", className: "bg-b3-react-muted/30 border-b3-react-border hover:bg-b3-react-muted/50 flex items-center gap-3 px-4 py-1 text-base transition-all", children: [_jsx(Loader2, { className: "text-b3-react-foreground size-4 animate-spin" }), _jsx(TextShimmer, { duration: 1, className: "font-sf-rounded text-base font-semibold", children: "Loading..." })] }), _jsxs("div", { className: "flex w-full flex-1 flex-col", children: [_jsxs("div", { className: "mb-4 flex flex-col gap-1", children: [_jsx(Skeleton, { className: "h-4 w-24" }), _jsxs("div", { className: "mt-2 flex items-center gap-2", children: [_jsx(Skeleton, { className: "h-8 w-48" }), _jsx(Skeleton, { className: "ml-4 h-8 w-32" })] }), _jsx(Skeleton, { className: "mt-4 h-8 w-24" })] }), _jsx(Skeleton, { className: "mb-4 h-12 w-full" }), _jsxs("div", { className: "flex w-full items-center justify-between gap-4", children: [_jsxs(Skeleton, { className: "rounded-lg bg-white/5 p-6 pb-3", children: [_jsx("div", { className: "size-[200px]" }), _jsx("div", { className: "mt-3 flex items-center justify-center gap-2", children: _jsx("div", { className: "size-5 rounded-full" }) })] }), _jsx("div", { className: "flex flex-1 flex-col gap-2", children: [1, 2, 3].map(i => (_jsx(Skeleton, { className: "h-10 w-full" }, i))) })] })] }), _jsxs("div", { className: "bg-b3-react-muted/30 mt-8 w-full rounded-lg p-4", children: [_jsx(Skeleton, { className: "mb-3 h-4 w-48" }), _jsxs("div", { className: "flex items-center gap-4", children: [_jsx(Skeleton, { className: "h-10 flex-1" }), _jsx(Skeleton, { className: "h-10 flex-1" })] })] }), _jsx("div", { className: "flex w-full flex-col gap-3", children: [1, 2, 3, 4, 5].map(i => (_jsxs("div", { className: "flex w-full justify-between", children: [_jsx(Skeleton, { className: "h-4 w-24" }), _jsx(Skeleton, { className: "h-4 w-32" })] }, i))) }), _jsx(Skeleton, { className: "h-10 w-full" }), mode === "page" && _jsx("div", { className: "h-12" })] }));
|
|
465
501
|
// Render points badge if conditions are met
|
|
466
502
|
const renderPointsBadge = () => {
|
|
467
|
-
if (
|
|
503
|
+
if (anyspendQuote?.data?.pointsAmount && anyspendQuote.data.pointsAmount > 0) {
|
|
468
504
|
return (_jsx(PointsBadge, { pointsAmount: anyspendQuote.data.pointsAmount, pointsMultiplier: anyspendQuote.data.pointsMultiplier, onClick: () => {
|
|
469
505
|
onShowPointsDetail?.();
|
|
470
506
|
setActivePanel(PanelView.POINTS_DETAIL);
|
|
@@ -507,12 +543,26 @@ function AnySpendCustomInner({ loadOrder, mode = "modal", activeTab: activeTabPr
|
|
|
507
543
|
opacity: hasMounted ? 1 : 0,
|
|
508
544
|
y: hasMounted ? 0 : 20,
|
|
509
545
|
filter: hasMounted ? "blur(0px)" : "blur(10px)",
|
|
510
|
-
}, transition: { duration: 0.3, delay: 0, ease: "easeInOut" }, className: "relative flex w-full items-center justify-between", children: [_jsx("div", { className: "text-as-tertiarry flex h-7 items-center text-sm", children: "Pay with" }), _jsx("button", { className: "text-as-tertiarry flex flex-wrap items-center justify-end gap-2 text-sm transition-colors hover:text-blue-700", onClick: () => setActivePanel(PanelView.FIAT_PAYMENT_METHOD), children:
|
|
546
|
+
}, transition: { duration: 0.3, delay: 0, ease: "easeInOut" }, className: "relative flex w-full items-center justify-between", children: [_jsx("div", { className: "text-as-tertiarry flex h-7 items-center text-sm", children: "Pay with" }), _jsx("button", { className: "text-as-tertiarry flex flex-wrap items-center justify-end gap-2 text-sm transition-colors hover:text-blue-700", onClick: () => setActivePanel(PanelView.FIAT_PAYMENT_METHOD), children: (() => {
|
|
547
|
+
const config = FIAT_PAYMENT_METHOD_DISPLAY[selectedFiatPaymentMethod];
|
|
548
|
+
if (config) {
|
|
549
|
+
return (_jsxs(_Fragment, { children: [_jsxs("div", { className: "flex items-center gap-2 whitespace-nowrap", children: [_jsx("div", { className: "flex h-5 w-5 shrink-0 items-center justify-center rounded-full bg-blue-600", children: _jsx("span", { className: "text-xs font-bold text-white", children: config.icon }) }), config.label] }), _jsx(ChevronRight, { className: "h-4 w-4 shrink-0" })] }));
|
|
550
|
+
}
|
|
551
|
+
return (_jsxs(_Fragment, { children: [_jsx("span", { className: "whitespace-nowrap", children: "Select payment method" }), _jsx(ChevronRight, { className: "h-4 w-4 shrink-0" })] }));
|
|
552
|
+
})() })] }), _jsx("div", { className: "divider w-full" }), recipientSection, _jsx("div", { className: "divider w-full" }), _jsxs(motion.div, { initial: false, animate: {
|
|
511
553
|
opacity: hasMounted ? 1 : 0,
|
|
512
554
|
y: hasMounted ? 0 : 20,
|
|
513
555
|
filter: hasMounted ? "blur(0px)" : "blur(10px)",
|
|
514
|
-
}, transition: { duration: 0.3, delay: 0.1, ease: "easeInOut" }, className: "relative flex w-full items-center justify-between gap-4", children: [_jsxs("span", { className: "text-as-tertiarry flex flex-wrap items-center gap-1.5 text-sm", children: [_jsxs("span", { className: "whitespace-nowrap", children: ["Total ", _jsx("span", { className: "text-as-tertiarry", children: "(USD)" })] }), anyspendQuote?.data?.fee && (_jsx(TooltipProvider, { children: _jsxs(Tooltip, { children: [_jsx(TooltipTrigger, { asChild: true, children: _jsx("button", { className: "text-as-primary/40 hover:text-as-primary/60 transition-colors", children: _jsx(Info, { className: "h-4 w-4" }) }) }), _jsx(TooltipContent, { side: "top", children: _jsx(FeeBreakDown, { fee: anyspendQuote.data.fee }) })] }) }))] }), _jsxs("div", { className: "flex flex-col items-end gap-0.5", children: [_jsxs("div", { className: "flex flex-wrap items-center justify-end gap-2", children: [renderPointsBadge(),
|
|
515
|
-
|
|
556
|
+
}, transition: { duration: 0.3, delay: 0.1, ease: "easeInOut" }, className: "relative flex w-full items-center justify-between gap-4", children: [_jsxs("span", { className: "text-as-tertiarry flex flex-wrap items-center gap-1.5 text-sm", children: [_jsxs("span", { className: "whitespace-nowrap", children: ["Total ", _jsx("span", { className: "text-as-tertiarry", children: "(USD)" })] }), anyspendQuote?.data?.fee && (_jsx(TooltipProvider, { children: _jsxs(Tooltip, { children: [_jsx(TooltipTrigger, { asChild: true, children: _jsx("button", { className: "text-as-primary/40 hover:text-as-primary/60 transition-colors", children: _jsx(Info, { className: "h-4 w-4" }) }) }), _jsx(TooltipContent, { side: "top", children: _jsx(FeeBreakDown, { fee: anyspendQuote.data.fee }) })] }) }))] }), _jsxs("div", { className: "flex flex-col items-end gap-0.5", children: [_jsxs("div", { className: "flex flex-wrap items-center justify-end gap-2", children: [renderPointsBadge(), isLoadingAnyspendQuote ? (_jsx("div", { className: "bg-as-surface-secondary h-7 w-16 animate-pulse rounded" })) : (_jsx("span", { className: "text-as-primary whitespace-nowrap text-xl font-semibold", children: anyspendQuote?.data?.currencyIn?.amountUsd ? (`$${Number(anyspendQuote.data.currencyIn.amountUsd).toFixed(2)}`) : (_jsxs(_Fragment, { children: ["$", parseFloat(srcFiatAmount || "0").toFixed(2), _jsx("span", { className: "text-as-tertiarry text-base", children: "+" })] })) }))] }), (() => {
|
|
557
|
+
if (anyspendQuote?.data?.fee?.type === "stripeweb2_fee" && anyspendQuote.data.fee.originalAmount) {
|
|
558
|
+
const fee = (Number(anyspendQuote.data.fee.originalAmount) - Number(anyspendQuote.data.fee.finalAmount)) /
|
|
559
|
+
1e6;
|
|
560
|
+
if (fee > 0) {
|
|
561
|
+
return _jsxs("span", { className: "text-as-secondary text-xs", children: ["incl. $", fee.toFixed(2), " fee"] });
|
|
562
|
+
}
|
|
563
|
+
}
|
|
564
|
+
return null;
|
|
565
|
+
})()] })] })] }), _jsx("div", { className: cn("flex w-full flex-col items-center justify-between gap-2"), children: _jsx(motion.div, { initial: false, animate: {
|
|
516
566
|
opacity: hasMounted ? 1 : 0,
|
|
517
567
|
y: hasMounted ? 0 : 20,
|
|
518
568
|
filter: hasMounted ? "blur(0px)" : "blur(10px)",
|
|
@@ -539,11 +589,17 @@ function AnySpendCustomInner({ loadOrder, mode = "modal", activeTab: activeTabPr
|
|
|
539
589
|
setSelectedCryptoPaymentMethod(method);
|
|
540
590
|
setActivePanel(PanelView.CONFIRM_ORDER);
|
|
541
591
|
} }) }));
|
|
592
|
+
// Stable callback for fiat payment method selection
|
|
593
|
+
const handleFiatPaymentMethodSelect = useCallback((method) => {
|
|
594
|
+
setSelectedFiatPaymentMethod(method);
|
|
595
|
+
setActivePanel(PanelView.CONFIRM_ORDER);
|
|
596
|
+
}, []);
|
|
597
|
+
// Stable callback for navigating back to confirm order
|
|
598
|
+
const handleBackToConfirmOrder = useCallback(() => {
|
|
599
|
+
setActivePanel(PanelView.CONFIRM_ORDER);
|
|
600
|
+
}, []);
|
|
542
601
|
// Fiat payment method view
|
|
543
|
-
const fiatPaymentMethodView = (_jsx("div", { className: cn("bg-as-surface-primary mx-auto w-[460px] max-w-full rounded-xl p-4"), children: _jsx(FiatPaymentMethodComponent, { selectedPaymentMethod: selectedFiatPaymentMethod, setSelectedPaymentMethod: setSelectedFiatPaymentMethod, onBack:
|
|
544
|
-
setSelectedFiatPaymentMethod(method);
|
|
545
|
-
setActivePanel(PanelView.CONFIRM_ORDER);
|
|
546
|
-
}, srcAmountOnRamp: srcFiatAmount }) }));
|
|
602
|
+
const fiatPaymentMethodView = (_jsx("div", { className: cn("bg-as-surface-primary mx-auto w-[460px] max-w-full rounded-xl p-4"), children: _jsx(FiatPaymentMethodComponent, { selectedPaymentMethod: selectedFiatPaymentMethod, setSelectedPaymentMethod: setSelectedFiatPaymentMethod, onBack: handleBackToConfirmOrder, onSelectPaymentMethod: handleFiatPaymentMethodSelect, srcAmountOnRamp: srcFiatAmount }) }));
|
|
547
603
|
// Points detail view
|
|
548
604
|
const pointsDetailView = (_jsx("div", { className: cn("bg-as-surface-primary mx-auto w-[460px] max-w-full rounded-xl p-4"), children: _jsx(PointsDetailPanel, { pointsAmount: anyspendQuote?.data?.pointsAmount || 0, onBack: () => setActivePanel(PanelView.CONFIRM_ORDER) }) }));
|
|
549
605
|
// Return the TransitionPanel with all views
|
|
@@ -6,7 +6,7 @@ import { getIpfsUrl } from "../../../shared/utils/ipfs.js";
|
|
|
6
6
|
import { formatDisplayNumber, formatTokenAmount } from "../../../shared/utils/number.js";
|
|
7
7
|
import { MoreVertical } from "lucide-react";
|
|
8
8
|
import { AnimatePresence } from "motion/react";
|
|
9
|
-
import { useEffect, useState } from "react";
|
|
9
|
+
import { useCallback, useEffect, useRef, useState } from "react";
|
|
10
10
|
import { b3 } from "viem/chains";
|
|
11
11
|
import { AnySpendCustom } from "./AnySpendCustom.js";
|
|
12
12
|
// ABI for contractURI and uri functions
|
|
@@ -28,16 +28,16 @@ const CONTRACT_URI_ABI = [
|
|
|
28
28
|
];
|
|
29
29
|
export function AnySpendNFT({ loadOrder, mode = "modal", recipientAddress, nftContract, onSuccess, onShowPointsDetail, }) {
|
|
30
30
|
const [imageUrlWithFallback, setFallbackImageUrl] = useState(nftContract.imageUrl);
|
|
31
|
-
const
|
|
31
|
+
const hasFetchedRef = useRef(false);
|
|
32
32
|
// Fetch contract metadata when imageUrl is empty
|
|
33
33
|
useEffect(() => {
|
|
34
34
|
async function fetchContractMetadata() {
|
|
35
35
|
// fetch image Uri if not provided
|
|
36
|
-
if (nftContract.imageUrl ||
|
|
36
|
+
if (nftContract.imageUrl || hasFetchedRef.current) {
|
|
37
37
|
return;
|
|
38
38
|
}
|
|
39
|
+
hasFetchedRef.current = true;
|
|
39
40
|
try {
|
|
40
|
-
setIsLoadingFallback(true);
|
|
41
41
|
// Use the chainIdToPublicClient utility function
|
|
42
42
|
const publicClient = chainIdToPublicClient(nftContract.chainId);
|
|
43
43
|
let metadataURI;
|
|
@@ -74,15 +74,12 @@ export function AnySpendNFT({ loadOrder, mode = "modal", recipientAddress, nftCo
|
|
|
74
74
|
catch (error) {
|
|
75
75
|
console.error("Error fetching contract metadata:", error);
|
|
76
76
|
}
|
|
77
|
-
finally {
|
|
78
|
-
setIsLoadingFallback(false);
|
|
79
|
-
}
|
|
80
77
|
}
|
|
81
78
|
fetchContractMetadata();
|
|
82
|
-
}, [nftContract.contractAddress, nftContract.chainId, nftContract.imageUrl, nftContract.tokenId
|
|
83
|
-
const header = ({ anyspendPrice, isLoadingAnyspendPrice, }) => (_jsxs(_Fragment, { children: [_jsxs("div", { className: "relative size-[200px]", children: [_jsx("div", { className: "absolute inset-0 scale-95 bg-black/30 blur-md" }), _jsxs(GlareCard, { className: "overflow-hidden", children: [imageUrlWithFallback && (_jsx("img", { src: imageUrlWithFallback, alt: nftContract.name, className: "size-full object-cover" })), _jsx("div", { className: "absolute inset-0 rounded-xl border border-white/10" })] }), _jsx(DropdownMenu, { nftContract: nftContract })] }), _jsxs("div", { className: "from-b3-react-background to-as-on-surface-1 -mb-5 mt-[-100px] w-full rounded-t-lg bg-gradient-to-t", children: [_jsx("div", { className: "h-[100px] w-full" }), _jsxs("div", { className: "mb-1 flex w-full flex-col items-center gap-2 p-5", children: [_jsx("span", { className: "font-sf-rounded text-2xl font-semibold", children: nftContract.name }), _jsx("div", { className: "flex w-fit items-center gap-1", children: anyspendPrice ? (_jsx(AnimatePresence, { mode: "wait", children: _jsx("div", { className: cn("text-as-primary group flex items-center text-3xl font-semibold transition-all", {
|
|
79
|
+
}, [nftContract.contractAddress, nftContract.chainId, nftContract.imageUrl, nftContract.tokenId]);
|
|
80
|
+
const header = useCallback(({ anyspendPrice, isLoadingAnyspendPrice, }) => (_jsxs(_Fragment, { children: [_jsxs("div", { className: "relative size-[200px]", children: [_jsx("div", { className: "absolute inset-0 scale-95 bg-black/30 blur-md" }), _jsxs(GlareCard, { className: "overflow-hidden", children: [imageUrlWithFallback && (_jsx("img", { src: imageUrlWithFallback, alt: nftContract.name, className: "size-full object-cover" })), _jsx("div", { className: "absolute inset-0 rounded-xl border border-white/10" })] }), _jsx(DropdownMenu, { nftContract: nftContract })] }), _jsxs("div", { className: "from-b3-react-background to-as-on-surface-1 -mb-5 mt-[-100px] w-full rounded-t-lg bg-gradient-to-t", children: [_jsx("div", { className: "h-[100px] w-full" }), _jsxs("div", { className: "mb-1 flex w-full flex-col items-center gap-2 p-5", children: [_jsx("span", { className: "font-sf-rounded text-2xl font-semibold", children: nftContract.name }), _jsx("div", { className: "flex w-fit items-center gap-1", children: anyspendPrice ? (_jsx(AnimatePresence, { mode: "wait", children: _jsx("div", { className: cn("text-as-primary group flex items-center text-3xl font-semibold transition-all", {
|
|
84
81
|
"opacity-0": isLoadingAnyspendPrice,
|
|
85
|
-
}), children: formatDisplayNumber(anyspendPrice?.data?.currencyIn?.amountUsd, { style: "currency" }) }) })) : (_jsx("div", { className: "h-[36px] w-full" })) })] })] })] }));
|
|
82
|
+
}), children: formatDisplayNumber(anyspendPrice?.data?.currencyIn?.amountUsd, { style: "currency" }) }) })) : (_jsx("div", { className: "h-[36px] w-full" })) })] })] })] })), [imageUrlWithFallback, nftContract]);
|
|
86
83
|
return (_jsx(AnySpendCustom, { loadOrder: loadOrder, mode: mode, activeTab: "fiat", recipientAddress: recipientAddress, orderType: "mint_nft", dstChainId: nftContract.chainId, dstToken: nftContract.currency, dstAmount: nftContract.price, contractAddress: nftContract.contractAddress, encodedData: "0x", metadata: {
|
|
87
84
|
type: "mint_nft",
|
|
88
85
|
nftContract: nftContract,
|
|
@@ -5,11 +5,9 @@ import { shortenAddress } from "../../../../shared/utils/formatAddress.js";
|
|
|
5
5
|
import { formatDisplayNumber } from "../../../../shared/utils/number.js";
|
|
6
6
|
import { ChevronRight, Info } from "lucide-react";
|
|
7
7
|
import { motion } from "motion/react";
|
|
8
|
-
import { useFeatureFlags } from "../../contexts/FeatureFlagsContext.js";
|
|
9
8
|
import { OrderTokenAmount } from "./OrderTokenAmount.js";
|
|
10
9
|
import { PointsBadge } from "./PointsBadge.js";
|
|
11
10
|
export function CryptoReceiveSection({ isDepositMode = false, isBuyMode = false, effectiveRecipientAddress, recipientName, onSelectRecipient, dstAmount, dstToken, selectedDstChainId, setSelectedDstChainId, setSelectedDstToken, isSrcInputDirty, onChangeDstAmount, anyspendQuote, dstTokenSymbol, dstTokenLogoURI, onShowPointsDetail, onShowFeeDetail, }) {
|
|
12
|
-
const featureFlags = useFeatureFlags();
|
|
13
11
|
return (_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.1, ease: "easeInOut" }, className: "receive-section bg-as-surface-secondary border-as-border-secondary relative flex w-full flex-col gap-2 rounded-2xl border p-4 sm:p-6", children: [_jsxs("div", { className: "flex w-full items-center justify-between", children: [_jsxs("div", { className: "text-as-primary/50 flex h-7 items-center gap-1.5 text-sm", children: [isDepositMode ? "Deposit" : "Receive", isSrcInputDirty && anyspendQuote?.data?.fee && onShowFeeDetail && (_jsx("button", { onClick: onShowFeeDetail, className: "text-as-primary/40 hover:text-as-primary/60 transition-colors", children: _jsx(Info, { className: "h-4 w-4" }) }))] }), effectiveRecipientAddress ? (_jsx("button", { className: cn("text-as-tertiarry flex h-7 items-center gap-2 rounded-lg"), onClick: onSelectRecipient, children: _jsxs(_Fragment, { children: [_jsx("span", { className: "text-as-tertiarry flex items-center gap-1 text-sm", children: recipientName ? formatUsername(recipientName) : shortenAddress(effectiveRecipientAddress || "") }), _jsx(ChevronRight, { className: "h-4 w-4" })] }) })) : (_jsx("button", { className: "text-as-primary/70 flex items-center gap-1 rounded-lg", onClick: onSelectRecipient, children: _jsx("div", { className: "text-sm font-medium", children: "Select recipient" }) }))] }), isBuyMode || isDepositMode ? (
|
|
14
12
|
// Fixed destination token display for buy mode and deposit mode
|
|
15
13
|
_jsxs("div", { className: "flex items-center justify-between", children: [_jsx("div", { className: "text-as-primary text-2xl font-bold", children: dstAmount || "0" }), _jsxs("div", { className: "bg-as-brand/10 border-as-brand/30 flex items-center gap-3 rounded-xl border px-4 py-3", children: [(dstTokenLogoURI || dstToken.metadata?.logoURI) && (_jsx("img", { src: dstTokenLogoURI || dstToken.metadata?.logoURI, alt: dstTokenSymbol || dstToken.symbol, className: "h-8 w-8 rounded-full" })), _jsx("span", { className: "text-as-brand text-lg font-bold", children: dstTokenSymbol || dstToken.symbol })] })] })) : (
|
|
@@ -55,5 +53,5 @@ export function CryptoReceiveSection({ isDepositMode = false, isBuyMode = false,
|
|
|
55
53
|
}
|
|
56
54
|
// Using inline style to ensure color displays
|
|
57
55
|
return (_jsxs("span", { className: "ml-2", style: { color: actualSlippage >= redThreshold ? "red" : "#FFD700" }, children: ["(", isNegative ? "-" : "", percentage, "%)"] }));
|
|
58
|
-
})()] }),
|
|
56
|
+
})()] }), anyspendQuote?.data?.pointsAmount > 0 && (_jsx(PointsBadge, { pointsAmount: anyspendQuote.data.pointsAmount, pointsMultiplier: anyspendQuote.data.pointsMultiplier, onClick: () => onShowPointsDetail?.() }))] })] }));
|
|
59
57
|
}
|
|
@@ -1,8 +1,13 @@
|
|
|
1
1
|
export declare enum FiatPaymentMethod {
|
|
2
2
|
NONE = "none",
|
|
3
3
|
COINBASE_PAY = "coinbase_pay",
|
|
4
|
-
STRIPE = "stripe"
|
|
4
|
+
STRIPE = "stripe",// Stripe redirect (one-click buy URL)
|
|
5
|
+
STRIPE_WEB2 = "stripe_web2"
|
|
5
6
|
}
|
|
7
|
+
export declare const FIAT_PAYMENT_METHOD_DISPLAY: Record<FiatPaymentMethod, {
|
|
8
|
+
icon: string;
|
|
9
|
+
label: string;
|
|
10
|
+
} | null>;
|
|
6
11
|
interface FiatPaymentMethodProps {
|
|
7
12
|
selectedPaymentMethod: FiatPaymentMethod;
|
|
8
13
|
setSelectedPaymentMethod: (method: FiatPaymentMethod) => void;
|