@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.
Files changed (53) hide show
  1. package/dist/cjs/anyspend/react/components/AnySpend.js +23 -10
  2. package/dist/cjs/anyspend/react/components/AnySpendCollectorClubPurchase.js +9 -2
  3. package/dist/cjs/anyspend/react/components/AnySpendCustom.d.ts +2 -0
  4. package/dist/cjs/anyspend/react/components/AnySpendCustom.js +75 -19
  5. package/dist/cjs/anyspend/react/components/AnySpendNFT.js +6 -9
  6. package/dist/cjs/anyspend/react/components/common/CryptoReceiveSection.js +1 -3
  7. package/dist/cjs/anyspend/react/components/common/FiatPaymentMethod.d.ts +6 -1
  8. package/dist/cjs/anyspend/react/components/common/FiatPaymentMethod.js +40 -13
  9. package/dist/cjs/anyspend/react/components/common/PanelOnramp.js +13 -7
  10. package/dist/cjs/anyspend/react/components/common/PanelOnrampPayment.js +5 -3
  11. package/dist/cjs/anyspend/react/hooks/useGeoOnrampOptions.d.ts +2 -8
  12. package/dist/cjs/anyspend/react/hooks/useGeoOnrampOptions.js +4 -2
  13. package/dist/cjs/anyspend/react/hooks/useStripeSupport.d.ts +1 -0
  14. package/dist/cjs/anyspend/react/hooks/useStripeSupport.js +1 -0
  15. package/dist/cjs/global-account/react/components/IPFSMediaRenderer/IPFSMediaRenderer.js +5 -3
  16. package/dist/cjs/shared/utils/ipfs.d.ts +3 -3
  17. package/dist/cjs/shared/utils/ipfs.js +8 -8
  18. package/dist/esm/anyspend/react/components/AnySpend.js +23 -10
  19. package/dist/esm/anyspend/react/components/AnySpendCollectorClubPurchase.js +9 -2
  20. package/dist/esm/anyspend/react/components/AnySpendCustom.d.ts +2 -0
  21. package/dist/esm/anyspend/react/components/AnySpendCustom.js +76 -20
  22. package/dist/esm/anyspend/react/components/AnySpendNFT.js +7 -10
  23. package/dist/esm/anyspend/react/components/common/CryptoReceiveSection.js +1 -3
  24. package/dist/esm/anyspend/react/components/common/FiatPaymentMethod.d.ts +6 -1
  25. package/dist/esm/anyspend/react/components/common/FiatPaymentMethod.js +39 -12
  26. package/dist/esm/anyspend/react/components/common/PanelOnramp.js +14 -8
  27. package/dist/esm/anyspend/react/components/common/PanelOnrampPayment.js +5 -3
  28. package/dist/esm/anyspend/react/hooks/useGeoOnrampOptions.d.ts +2 -8
  29. package/dist/esm/anyspend/react/hooks/useGeoOnrampOptions.js +4 -2
  30. package/dist/esm/anyspend/react/hooks/useStripeSupport.d.ts +1 -0
  31. package/dist/esm/anyspend/react/hooks/useStripeSupport.js +1 -0
  32. package/dist/esm/global-account/react/components/IPFSMediaRenderer/IPFSMediaRenderer.js +5 -3
  33. package/dist/esm/shared/utils/ipfs.d.ts +3 -3
  34. package/dist/esm/shared/utils/ipfs.js +8 -8
  35. package/dist/styles/index.css +1 -1
  36. package/dist/types/anyspend/react/components/AnySpendCustom.d.ts +2 -0
  37. package/dist/types/anyspend/react/components/common/FiatPaymentMethod.d.ts +6 -1
  38. package/dist/types/anyspend/react/hooks/useGeoOnrampOptions.d.ts +2 -8
  39. package/dist/types/anyspend/react/hooks/useStripeSupport.d.ts +1 -0
  40. package/dist/types/shared/utils/ipfs.d.ts +3 -3
  41. package/package.json +1 -1
  42. package/src/anyspend/react/components/AnySpend.tsx +24 -10
  43. package/src/anyspend/react/components/AnySpendCollectorClubPurchase.tsx +9 -1
  44. package/src/anyspend/react/components/AnySpendCustom.tsx +113 -59
  45. package/src/anyspend/react/components/AnySpendNFT.tsx +49 -48
  46. package/src/anyspend/react/components/common/CryptoReceiveSection.tsx +1 -4
  47. package/src/anyspend/react/components/common/FiatPaymentMethod.tsx +53 -21
  48. package/src/anyspend/react/components/common/PanelOnramp.tsx +36 -40
  49. package/src/anyspend/react/components/common/PanelOnrampPayment.tsx +53 -16
  50. package/src/anyspend/react/hooks/useGeoOnrampOptions.ts +5 -2
  51. package/src/anyspend/react/hooks/useStripeSupport.ts +1 -0
  52. package/src/global-account/react/components/IPFSMediaRenderer/IPFSMediaRenderer.tsx +5 -7
  53. 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" && anyspendQuote.data.currencyIn?.amountUsd && ((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) /
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
- })(), 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: "Stripe" }), (0, jsx_runtime_1.jsx)("p", { className: "text-b3-react-foreground/60 text-sm", children: "Credit or debit card payment" }), (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-orange-600", children: "Fee Applied" }) })] })] }), (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"] })] })] }))] }));
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: true | {
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 if needed
32
- // This handles both ipfs:// URLs and existing HTTP gateway URLs
33
- return ((0, jsx_runtime_1.jsx)(react_1.MediaRenderer, { src: src, client: client, alt: alt, className: className, width: width ? width.toString() : undefined, height: height ? height.toString() : undefined, controls: controls, style: style }));
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: Cloudflare, 1: ipfs.io)
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://cloudflare-ipfs.com/ipfs/QmUbJ4p.../2.png'
7
+ * // returns 'https://dweb.link/ipfs/QmUbJ4p.../2.png'
8
8
  * getIpfsUrl('ipfs://QmUbJ4pnHMNXGeWWhBFFSEqCGuc6cEtDyz35wQfv7k2TXy/2.png')
9
- * // returns 'https://ipfs.io/ipfs/QmUbJ4p.../2.png'
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://cloudflare-ipfs.com/ipfs", // Primary gateway - fast and reliable
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://gateway.pinata.cloud/ipfs", // Additional option
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: Cloudflare, 1: ipfs.io)
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://cloudflare-ipfs.com/ipfs/QmUbJ4p.../2.png'
22
+ * // returns 'https://dweb.link/ipfs/QmUbJ4p.../2.png'
23
23
  * getIpfsUrl('ipfs://QmUbJ4pnHMNXGeWWhBFFSEqCGuc6cEtDyz35wQfv7k2TXy/2.png')
24
- * // returns 'https://ipfs.io/ipfs/QmUbJ4p.../2.png'
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
- // Determine if it's stripe onramp or stripe-web2 based on support
366
- if (stripeWeb2Support?.isSupport) {
367
- return "stripe-web2";
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
- if (activeInputAmountInWei === "0")
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
- if (!stripeWeb2Support || !stripeWeb2Support.isSupport) {
680
- toast.error("Stripe not available");
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 = stripeWeb2Support && stripeWeb2Support.isSupport ? "stripe-web2" : "stripe";
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 = "0x4eE0190e37E8A13740c4777D1c9de65E79D8f751";
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 ? "stripe-web2" : undefined,
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
- const srcFiatAmount = useMemo(() => (activeTab === "fiat" && srcAmount ? formatUnits(srcAmount.toString(), USDC_BASE.decimals) : "0"), [activeTab, srcAmount]);
247
- // Get geo data and onramp options (after quote is available)
248
- const { geoData, isOnrampSupported, coinbaseAvailablePaymentMethods, stripeWeb2Support } = useGeoOnrampOptions(srcFiatAmount);
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: 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.STRIPE) {
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 = stripeWeb2Support && stripeWeb2Support.isSupport ? "stripe-web2" : "stripe";
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 (featureFlags.showPoints && anyspendQuote?.data?.pointsAmount && anyspendQuote.data.pointsAmount > 0) {
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: selectedFiatPaymentMethod === FiatPaymentMethod.COINBASE_PAY ? (_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: "C" }) }), "Coinbase Pay"] }), _jsx(ChevronRight, { className: "h-4 w-4 shrink-0" })] })) : selectedFiatPaymentMethod === FiatPaymentMethod.STRIPE ? (_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: "S" }) }), "Credit/Debit Card"] }), _jsx(ChevronRight, { className: "h-4 w-4 shrink-0" })] })) : (_jsxs(_Fragment, { children: [_jsx("span", { className: "whitespace-nowrap", children: "Select payment method" }), _jsx(ChevronRight, { className: "h-4 w-4 shrink-0" })] })) })] }), _jsx("div", { className: "divider w-full" }), recipientSection, _jsx("div", { className: "divider w-full" }), _jsxs(motion.div, { initial: false, animate: {
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(), _jsxs("span", { className: "text-as-primary whitespace-nowrap text-xl font-semibold", children: ["$", srcFiatAmount || "0.00"] })] }), anyspendQuote?.data?.fee?.type === "stripeweb2_fee" && anyspendQuote.data.fee.originalAmount && (_jsxs("span", { className: "text-as-secondary text-xs", children: ["incl. $", ((Number(anyspendQuote.data.fee.originalAmount) - Number(anyspendQuote.data.fee.finalAmount)) /
515
- 1e6).toFixed(2), " ", "fee"] }))] })] })] }), _jsx("div", { className: cn("flex w-full flex-col items-center justify-between gap-2"), children: _jsx(motion.div, { initial: false, animate: {
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: () => setActivePanel(PanelView.CONFIRM_ORDER), onSelectPaymentMethod: (method) => {
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 [isLoadingFallback, setIsLoadingFallback] = useState(false);
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 || isLoadingFallback) {
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, isLoadingFallback]);
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
- })()] }), featureFlags.showPoints && anyspendQuote?.data?.pointsAmount > 0 && (_jsx(PointsBadge, { pointsAmount: anyspendQuote.data.pointsAmount, pointsMultiplier: anyspendQuote.data.pointsMultiplier, onClick: () => onShowPointsDetail?.() }))] })] }));
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;