@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
@@ -8,26 +8,37 @@ export var FiatPaymentMethod;
8
8
  FiatPaymentMethod["NONE"] = "none";
9
9
  FiatPaymentMethod["COINBASE_PAY"] = "coinbase_pay";
10
10
  FiatPaymentMethod["STRIPE"] = "stripe";
11
+ FiatPaymentMethod["STRIPE_WEB2"] = "stripe_web2";
11
12
  })(FiatPaymentMethod || (FiatPaymentMethod = {}));
13
+ // Shared display config for fiat payment methods
14
+ export const FIAT_PAYMENT_METHOD_DISPLAY = {
15
+ [FiatPaymentMethod.COINBASE_PAY]: { icon: "C", label: "Coinbase Pay" },
16
+ [FiatPaymentMethod.STRIPE]: { icon: "S", label: "Pay via Stripe" },
17
+ [FiatPaymentMethod.STRIPE_WEB2]: { icon: "S", label: "Pay with Card" },
18
+ [FiatPaymentMethod.NONE]: null,
19
+ };
12
20
  export function FiatPaymentMethodComponent({ selectedPaymentMethod, setSelectedPaymentMethod, onBack, onSelectPaymentMethod, srcAmountOnRamp, }) {
21
+ // Load geo-based onramp options like in PanelOnramp
22
+ const { coinbaseAvailablePaymentMethods, stripeOnrampSupport, stripeWeb2Support, isLoading: isLoadingGeoOnramp, } = useGeoOnrampOptions(srcAmountOnRamp);
13
23
  // Helper function to get fees from API data
14
24
  const getFeeFromApi = (paymentMethod) => {
15
25
  switch (paymentMethod) {
16
26
  case FiatPaymentMethod.COINBASE_PAY:
17
27
  // Coinbase doesn't provide fee info in API, return null
18
28
  return null;
19
- case FiatPaymentMethod.STRIPE:
20
- // Get fee from Stripe API response
29
+ case FiatPaymentMethod.STRIPE_WEB2:
30
+ // Get fee from Stripe Web2 API response
21
31
  if (stripeWeb2Support && "formattedFeeUsd" in stripeWeb2Support) {
22
32
  return stripeWeb2Support.formattedFeeUsd;
23
33
  }
24
34
  return null;
35
+ case FiatPaymentMethod.STRIPE:
36
+ // Stripe redirect doesn't have fee info from API
37
+ return null;
25
38
  default:
26
39
  return null; // No fee when no payment method selected
27
40
  }
28
41
  };
29
- // Load geo-based onramp options like in PanelOnramp
30
- const { coinbaseAvailablePaymentMethods, stripeWeb2Support, isLoading: isLoadingGeoOnramp, } = useGeoOnrampOptions(srcAmountOnRamp);
31
42
  // Generate payment methods based on geo availability (like in PanelOnrampPayment)
32
43
  const availablePaymentMethods = [];
33
44
  // Add Coinbase Pay if available
@@ -42,15 +53,27 @@ export function FiatPaymentMethodComponent({ selectedPaymentMethod, setSelectedP
42
53
  available: true,
43
54
  });
44
55
  }
45
- // Add Stripe if available
46
- if (stripeWeb2Support && stripeWeb2Support.isSupport) {
47
- const stripeFee = getFeeFromApi(FiatPaymentMethod.STRIPE);
56
+ // Add Stripe redirect (one-click) if available - redirects to Stripe checkout
57
+ if (stripeOnrampSupport) {
58
+ const stripeFee = getFeeFromApi(FiatPaymentMethod.STRIPE_WEB2); // Use same fee estimate
48
59
  availablePaymentMethods.push({
49
60
  id: FiatPaymentMethod.STRIPE,
50
- name: "Stripe",
51
- description: "Credit or debit card payment",
52
- badge: stripeFee ? `$${Number(stripeFee).toFixed(2)} fee` : "Standard Fee",
53
- badgeColor: "bg-yellow-100 text-yellow-800",
61
+ name: "Pay via Stripe",
62
+ description: "Redirects to Stripe checkout",
63
+ badge: stripeFee ? `$${Number(stripeFee).toFixed(2)} fee` : undefined,
64
+ badgeColor: "bg-gray-100 text-gray-800",
65
+ available: true,
66
+ });
67
+ }
68
+ // Add Stripe Web2 (embedded) if available - embedded card form
69
+ if (stripeWeb2Support && stripeWeb2Support.isSupport) {
70
+ const stripeFee = getFeeFromApi(FiatPaymentMethod.STRIPE_WEB2);
71
+ availablePaymentMethods.push({
72
+ id: FiatPaymentMethod.STRIPE_WEB2,
73
+ name: "Pay with Card",
74
+ description: "Fast checkout",
75
+ badge: stripeFee ? `$${Number(stripeFee).toFixed(2)} fee` : undefined,
76
+ badgeColor: "bg-gray-100 text-gray-800",
54
77
  available: true,
55
78
  });
56
79
  }
@@ -63,5 +86,9 @@ export function FiatPaymentMethodComponent({ selectedPaymentMethod, setSelectedP
63
86
  onSelectPaymentMethod(method.id);
64
87
  }, className: cn("fiat-payment-method-item bg-as-surface-secondary border-as-border-secondary flex w-full items-center gap-4 rounded-2xl border p-4 transition-all duration-200", selectedPaymentMethod === method.id
65
88
  ? "border-as-brand bg-as-brand/10"
66
- : "hover:border-as-brand/50 hover:bg-as-brand/5"), children: [_jsx("div", { className: "flex h-12 w-12 items-center justify-center rounded-full bg-blue-600 text-2xl text-white", children: method.id === FiatPaymentMethod.COINBASE_PAY ? "C" : "S" }), _jsxs("div", { className: "flex flex-1 flex-col items-start text-left", children: [_jsxs("div", { className: "flex items-center gap-2", children: [_jsx("span", { className: "text-as-primary text-base font-semibold", children: method.name }), _jsx("span", { className: cn("rounded-full px-2 py-1 text-xs font-medium", method.badgeColor), children: method.badge })] }), _jsx("span", { className: "text-as-primary/60 text-sm", children: method.description })] }), selectedPaymentMethod === method.id && _jsx(ChevronRight, { className: "text-as-brand h-5 w-5" })] }, method.id)))) })] }) }));
89
+ : "hover:border-as-brand/50 hover:bg-as-brand/5"), children: [_jsx("div", { className: "flex h-12 w-12 items-center justify-center rounded-full bg-blue-600 text-2xl text-white", children: method.id === FiatPaymentMethod.COINBASE_PAY
90
+ ? "C"
91
+ : method.id === FiatPaymentMethod.STRIPE || method.id === FiatPaymentMethod.STRIPE_WEB2
92
+ ? "S"
93
+ : "?" }), _jsxs("div", { className: "flex flex-1 flex-col items-start text-left", children: [_jsxs("div", { className: "flex items-center gap-2", children: [_jsx("span", { className: "text-as-primary text-base font-semibold", children: method.name }), method.badge && (_jsx("span", { className: cn("rounded-full px-2 py-1 text-xs font-medium", method.badgeColor), children: method.badge }))] }), _jsx("span", { className: "text-as-primary/60 text-sm", children: method.description })] }), selectedPaymentMethod === method.id && _jsx(ChevronRight, { className: "text-as-brand h-5 w-5" })] }, method.id)))) })] }) }));
67
94
  }
@@ -6,13 +6,11 @@ import { cn, formatUsername } from "../../../../shared/utils/index.js";
6
6
  import { formatAddress } from "../../../../shared/utils/formatAddress.js";
7
7
  import { ChevronRight, Info, Wallet } from "lucide-react";
8
8
  import { useRef } from "react";
9
- import { useFeatureFlags } from "../../contexts/FeatureFlagsContext.js";
10
- import { FiatPaymentMethod } from "./FiatPaymentMethod.js";
9
+ import { FIAT_PAYMENT_METHOD_DISPLAY, FiatPaymentMethod } from "./FiatPaymentMethod.js";
11
10
  import { OrderTokenAmountFiat } from "./OrderTokenAmountFiat.js";
12
11
  import { PointsBadge } from "./PointsBadge.js";
13
12
  const ONE_CHAR_WIDTH = 30;
14
13
  export function PanelOnramp({ srcAmountOnRamp, setSrcAmountOnRamp, selectedPaymentMethod, setActivePanel, _recipientAddress, destinationToken, destinationChainId, destinationAmount, onDestinationTokenChange, onDestinationChainChange, fiatPaymentMethodIndex, recipientSelectionPanelIndex, dstTokenSymbol, hideDstToken = false, anyspendQuote, onShowPointsDetail, onShowFeeDetail, customUsdInputValues = ["5", "10", "20", "25"], }) {
15
- const featureFlags = useFeatureFlags();
16
14
  // Helper function to get fees from anyspend quote
17
15
  const getFeeFromApi = (paymentMethod) => {
18
16
  // Try to get fee from anyspend quote first (most accurate)
@@ -38,10 +36,14 @@ export function PanelOnramp({ srcAmountOnRamp, setSrcAmountOnRamp, selectedPayme
38
36
  // Helper function to get total amount from API (for Stripe) or calculate it (for others)
39
37
  const getTotalAmount = (paymentMethod) => {
40
38
  const baseAmount = parseFloat(srcAmountOnRamp) || 5;
41
- // Try to get from anyspend quote first (most accurate)
39
+ // For stripeweb2_fee, use the originalAmount
42
40
  if (anyspendQuote?.data?.fee?.type === "stripeweb2_fee") {
43
41
  return Number(anyspendQuote.data.fee.originalAmount) / 1e6; // Convert from wei to USD
44
42
  }
43
+ // Use currencyIn.amountUsd from quote when available (includes fees, most accurate for custom orders)
44
+ if (anyspendQuote?.data?.currencyIn?.amountUsd) {
45
+ return Number(anyspendQuote.data.currencyIn.amountUsd);
46
+ }
45
47
  const fee = getFeeFromApi(paymentMethod);
46
48
  // For Coinbase or when fee is available, calculate manually
47
49
  if (fee !== null) {
@@ -73,15 +75,19 @@ export function PanelOnramp({ srcAmountOnRamp, setSrcAmountOnRamp, selectedPayme
73
75
  const handleQuickAmount = (value) => {
74
76
  setSrcAmountOnRamp(value);
75
77
  };
76
- return (_jsxs("div", { className: "panel-onramp bg-as-surface-primary flex w-full flex-col", children: [_jsxs("div", { className: "border-as-border-secondary bg-as-surface-secondary relative flex w-full flex-col rounded-2xl border p-4", children: [_jsxs("div", { className: "flex h-7 w-full items-center justify-between", children: [_jsx("span", { className: "text-as-tertiarry flex items-center text-sm font-bold", children: "Pay" }), _jsx("button", { className: "text-as-tertiarry flex h-7 items-center gap-1 text-sm", onClick: () => setActivePanel(fiatPaymentMethodIndex), children: selectedPaymentMethod === FiatPaymentMethod.COINBASE_PAY ? (_jsxs(_Fragment, { children: [_jsxs("div", { className: "flex items-center gap-2", children: [_jsx("div", { className: "flex h-5 w-5 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" })] })) : selectedPaymentMethod === FiatPaymentMethod.STRIPE ? (_jsxs(_Fragment, { children: [_jsxs("div", { className: "flex items-center gap-2", children: [_jsx("div", { className: "flex h-5 w-5 items-center justify-center rounded-full bg-blue-600", children: _jsx("span", { className: "text-xs font-bold text-white", children: "S" }) }), "Stripe"] }), _jsx(ChevronRight, { className: "h-4 w-4" })] })) : (_jsxs(_Fragment, { children: ["Select payment method", _jsx(ChevronRight, { className: "h-4 w-4" })] })) })] }), _jsx("div", { className: "flex items-center justify-center pb-2 pt-8", children: _jsxs("div", { className: "flex gap-1", children: [_jsx("span", { className: "text-as-tertiarry text-2xl font-bold", children: "$" }), _jsx(Input, { ref: amountInputRef, type: "text", value: srcAmountOnRamp, onChange: handleAmountChange, placeholder: "5", className: "text-as-primary placeholder:text-as-primary/50 h-auto border-0 bg-transparent p-0 px-1 pt-1 text-4xl font-bold focus-visible:ring-0 focus-visible:ring-offset-0", style: {
78
+ return (_jsxs("div", { className: "panel-onramp bg-as-surface-primary flex w-full flex-col", children: [_jsxs("div", { className: "border-as-border-secondary bg-as-surface-secondary relative flex w-full flex-col rounded-2xl border p-4", children: [_jsxs("div", { className: "flex h-7 w-full items-center justify-between", children: [_jsx("span", { className: "text-as-tertiarry flex items-center text-sm font-bold", children: "Pay" }), _jsx("button", { className: "text-as-tertiarry flex h-7 items-center gap-1 text-sm", onClick: () => setActivePanel(fiatPaymentMethodIndex), children: (() => {
79
+ const config = selectedPaymentMethod ? FIAT_PAYMENT_METHOD_DISPLAY[selectedPaymentMethod] : null;
80
+ if (config) {
81
+ return (_jsxs(_Fragment, { children: [_jsxs("div", { className: "flex items-center gap-2", children: [_jsx("div", { className: "flex h-5 w-5 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" })] }));
82
+ }
83
+ return (_jsxs(_Fragment, { children: ["Select payment method", _jsx(ChevronRight, { className: "h-4 w-4" })] }));
84
+ })() })] }), _jsx("div", { className: "flex items-center justify-center pb-2 pt-8", children: _jsxs("div", { className: "flex gap-1", children: [_jsx("span", { className: "text-as-tertiarry text-2xl font-bold", children: "$" }), _jsx(Input, { ref: amountInputRef, type: "text", value: srcAmountOnRamp, onChange: handleAmountChange, placeholder: "5", className: "text-as-primary placeholder:text-as-primary/50 h-auto border-0 bg-transparent p-0 px-1 pt-1 text-4xl font-bold focus-visible:ring-0 focus-visible:ring-offset-0", style: {
77
85
  width: `${Math.max(ONE_CHAR_WIDTH, srcAmountOnRamp.length * ONE_CHAR_WIDTH)}px`,
78
86
  } })] }) }), _jsx("div", { className: cn("mx-auto mb-6 flex justify-center gap-2", hideDstToken && "mb-0"), children: customUsdInputValues
79
87
  .filter(v => !isNaN(Number(v)))
80
88
  .map(value => (_jsxs("button", { onClick: () => handleQuickAmount(value), className: `bg-as-surface-secondary border-as-border-secondary hover:border-as-border-secondary h-7 w-14 rounded-lg border text-sm font-medium transition-all duration-200 ${srcAmountOnRamp === value
81
89
  ? "border-as-border-secondary bg-as-surface-secondary"
82
- : "bg-as-surface-secondary hover:bg-as-surface-secondary"}`, children: ["$", value] }, value))) }), destinationToken && destinationChainId && !hideDstToken && (_jsx(OrderTokenAmountFiat, { address: _recipientAddress, context: "to", inputValue: destinationAmount || "0", onChangeInput: () => { }, chainId: destinationChainId, setChainId: onDestinationChainChange || (() => { }), token: destinationToken, setToken: onDestinationTokenChange || (() => { }) }))] }), _jsxs("div", { className: "border-as-border-secondary bg-as-surface-secondary mt-4 flex w-full flex-col gap-3 rounded-xl border p-4", children: [_jsxs("div", { className: "flex w-full items-center justify-between gap-2", children: [_jsx("span", { className: "text-as-tertiarry flex items-center text-sm", children: "Recipient" }), _recipientAddress ? (_jsxs("button", { className: "text-as-tertiarry flex h-7 items-center gap-1 text-sm transition-colors hover:text-blue-700", onClick: () => setActivePanel(recipientSelectionPanelIndex), children: [_jsx("span", { className: "text-sm", children: recipientName ? formatUsername(recipientName) : formatAddress(_recipientAddress) }), _jsx(ChevronRight, { size: 16 })] })) : (_jsxs("button", { className: "text-as-tertiarry flex h-7 items-center gap-1 text-sm transition-colors hover:text-blue-700", onClick: () => setActivePanel(5), children: [_jsx(Wallet, { className: "text-as-brand", size: 16 }), "Select recipient", _jsx(ChevronRight, { size: 16 })] }))] }), _jsx("div", { className: "divider w-full" }), _jsxs("div", { className: "flex items-center justify-between gap-4", children: [_jsx("span", { className: "text-as-tertiarry text-sm", children: "Expected to receive" }), _jsxs("div", { className: "flex flex-wrap items-center justify-end gap-1", children: [_jsxs("span", { className: "text-as-primary font-semibold", children: [destinationAmount || "0", " ", dstTokenSymbol || destinationToken?.symbol || ""] }), _jsxs("div", { className: "flex items-center gap-1", children: [_jsxs("span", { className: "text-as-tertiarry text-sm", children: ["on ", destinationChainId ? ALL_CHAINS[destinationChainId]?.name : ""] }), destinationToken && destinationChainId && destinationToken.metadata?.logoURI && (_jsx("img", { src: ALL_CHAINS[destinationChainId]?.logoUrl, alt: "Chain", className: "h-4 w-4 rounded-full" }))] })] })] }), _jsx("div", { className: "divider w-full" }), _jsx("div", { className: "", children: _jsxs("div", { className: "flex items-center justify-between", children: [_jsxs("div", { className: "flex items-center gap-1.5", children: [_jsx("span", { className: "text-as-tertiarry text-sm", children: "Total" }), 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" }) })), featureFlags.showPoints &&
83
- anyspendQuote?.data?.pointsAmount &&
84
- anyspendQuote?.data?.pointsAmount > 0 && (_jsx(PointsBadge, { pointsAmount: anyspendQuote.data.pointsAmount, pointsMultiplier: anyspendQuote.data.pointsMultiplier, onClick: () => onShowPointsDetail?.() }))] }), _jsxs("div", { className: "flex flex-col items-end gap-0.5", children: [_jsxs("span", { className: "text-as-primary font-semibold", children: ["$", getTotalAmount(selectedPaymentMethod || FiatPaymentMethod.NONE).toFixed(2)] }), (() => {
90
+ : "bg-as-surface-secondary hover:bg-as-surface-secondary"}`, children: ["$", value] }, value))) }), destinationToken && destinationChainId && !hideDstToken && (_jsx(OrderTokenAmountFiat, { address: _recipientAddress, context: "to", inputValue: destinationAmount || "0", onChangeInput: () => { }, chainId: destinationChainId, setChainId: onDestinationChainChange || (() => { }), token: destinationToken, setToken: onDestinationTokenChange || (() => { }) }))] }), _jsxs("div", { className: "border-as-border-secondary bg-as-surface-secondary mt-4 flex w-full flex-col gap-3 rounded-xl border p-4", children: [_jsxs("div", { className: "flex w-full items-center justify-between gap-2", children: [_jsx("span", { className: "text-as-tertiarry flex items-center text-sm", children: "Recipient" }), _recipientAddress ? (_jsxs("button", { className: "text-as-tertiarry flex h-7 items-center gap-1 text-sm transition-colors hover:text-blue-700", onClick: () => setActivePanel(recipientSelectionPanelIndex), children: [_jsx("span", { className: "text-sm", children: recipientName ? formatUsername(recipientName) : formatAddress(_recipientAddress) }), _jsx(ChevronRight, { size: 16 })] })) : (_jsxs("button", { className: "text-as-tertiarry flex h-7 items-center gap-1 text-sm transition-colors hover:text-blue-700", onClick: () => setActivePanel(5), children: [_jsx(Wallet, { className: "text-as-brand", size: 16 }), "Select recipient", _jsx(ChevronRight, { size: 16 })] }))] }), _jsx("div", { className: "divider w-full" }), _jsxs("div", { className: "flex items-center justify-between gap-4", children: [_jsx("span", { className: "text-as-tertiarry text-sm", children: "Expected to receive" }), _jsxs("div", { className: "flex flex-wrap items-center justify-end gap-1", children: [_jsxs("span", { className: "text-as-primary font-semibold", children: [destinationAmount || "0", " ", dstTokenSymbol || destinationToken?.symbol || ""] }), _jsxs("div", { className: "flex items-center gap-1", children: [_jsxs("span", { className: "text-as-tertiarry text-sm", children: ["on ", destinationChainId ? ALL_CHAINS[destinationChainId]?.name : ""] }), destinationToken && destinationChainId && destinationToken.metadata?.logoURI && (_jsx("img", { src: ALL_CHAINS[destinationChainId]?.logoUrl, alt: "Chain", className: "h-4 w-4 rounded-full" }))] })] })] }), _jsx("div", { className: "divider w-full" }), _jsx("div", { className: "", children: _jsxs("div", { className: "flex items-center justify-between", children: [_jsxs("div", { className: "flex items-center gap-1.5", children: [_jsx("span", { className: "text-as-tertiarry text-sm", children: "Total" }), 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" }) })), anyspendQuote?.data?.pointsAmount && anyspendQuote?.data?.pointsAmount > 0 && (_jsx(PointsBadge, { pointsAmount: anyspendQuote.data.pointsAmount, pointsMultiplier: anyspendQuote.data.pointsMultiplier, onClick: () => onShowPointsDetail?.() }))] }), _jsxs("div", { className: "flex flex-col items-end gap-0.5", children: [_jsxs("span", { className: "text-as-primary font-semibold", children: ["$", getTotalAmount(selectedPaymentMethod || FiatPaymentMethod.NONE).toFixed(2)] }), (() => {
85
91
  // For fiat payments, show the fee from the payment method
86
92
  const fiatFee = getFeeFromApi(selectedPaymentMethod || FiatPaymentMethod.NONE);
87
93
  if (fiatFee !== null && fiatFee > 0) {
@@ -12,7 +12,7 @@ export function PanelOnrampPayment(props) {
12
12
  }
13
13
  function PanelOnrampPaymentInner(props) {
14
14
  const { srcAmountOnRamp, recipientAddress, isBuyMode, destinationTokenChainId, destinationTokenAddress, selectedDstChainId, selectedDstToken, anyspendQuote, globalAddress, onOrderCreated, onBack, orderType, nft, tournament, payload, recipientEnsName, recipientImageUrl, } = props;
15
- const { geoData, coinbaseOnrampOptions, coinbaseAvailablePaymentMethods, stripeWeb2Support, isLoading: isLoadingGeoOnramp, } = useGeoOnrampOptions(srcAmountOnRamp);
15
+ const { geoData, coinbaseOnrampOptions, coinbaseAvailablePaymentMethods, stripeOnrampSupport, stripeWeb2Support, isLoading: isLoadingGeoOnramp, } = useGeoOnrampOptions(srcAmountOnRamp);
16
16
  const isLoading = isLoadingGeoOnramp;
17
17
  const { createOrder, isCreatingOrder } = useAnyspendCreateOnrampOrder({
18
18
  onSuccess: data => {
@@ -91,7 +91,9 @@ function PanelOnrampPaymentInner(props) {
91
91
  ? "Receive NFT at"
92
92
  : orderType === "join_tournament"
93
93
  ? "Join for"
94
- : "Recipient" }), _jsxs("div", { className: "flex items-center gap-2", children: [recipientImageUrl && (_jsx("img", { src: recipientImageUrl, alt: recipientImageUrl, className: "bg-b3-react-foreground size-7 rounded-full object-cover opacity-100" })), _jsxs("div", { className: "flex flex-col items-end gap-1", children: [recipientEnsName && _jsxs("span", { className: "text-b3-react-foreground/80", children: ["@", recipientEnsName] }), _jsx("span", { className: "text-b3-react-foreground/80", children: centerTruncate(recipientAddress) })] })] })] })), _jsx("div", { className: "border-b3-react-border border-t pt-3", children: _jsxs("div", { className: "flex items-center justify-between", children: [_jsx("p", { className: "text-b3-react-foreground font-semibold", children: "Amount" }), _jsxs("div", { className: "flex flex-col items-end gap-0.5", children: [_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 && (_jsxs("p", { className: "text-b3-react-foreground/60 text-xs", children: ["incl. $", ((Number(anyspendQuote.data.currencyIn.amountUsd) * anyspendQuote.data.fee.finalFeeBps) /
94
+ : "Recipient" }), _jsxs("div", { className: "flex items-center gap-2", children: [recipientImageUrl && (_jsx("img", { src: recipientImageUrl, alt: recipientImageUrl, className: "bg-b3-react-foreground size-7 rounded-full object-cover opacity-100" })), _jsxs("div", { className: "flex flex-col items-end gap-1", children: [recipientEnsName && _jsxs("span", { className: "text-b3-react-foreground/80", children: ["@", recipientEnsName] }), _jsx("span", { className: "text-b3-react-foreground/80", children: centerTruncate(recipientAddress) })] })] })] })), _jsx("div", { className: "border-b3-react-border border-t pt-3", children: _jsxs("div", { className: "flex items-center justify-between", children: [_jsx("p", { className: "text-b3-react-foreground font-semibold", children: "Amount" }), _jsxs("div", { className: "flex flex-col items-end gap-0.5", children: [_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" &&
95
+ anyspendQuote.data.currencyIn?.amountUsd &&
96
+ anyspendQuote.data.fee.finalFeeBps > 0 && (_jsxs("p", { className: "text-b3-react-foreground/60 text-xs", children: ["incl. $", ((Number(anyspendQuote.data.currencyIn.amountUsd) * anyspendQuote.data.fee.finalFeeBps) /
95
97
  10000).toFixed(2), " ", "fee"] }))] })] }) })] })] }), isCreatingOrder ? (_jsxs("div", { className: "bg-b3-react-background border-b3-react-border flex items-center justify-center gap-3 rounded-lg border p-6", children: [_jsx(Loader2, { className: "h-4 w-4 animate-spin" }), _jsx("span", { className: "text-as-primary/70", children: "Creating onramp order..." })] })) : isLoading ? (_jsxs("div", { className: "bg-b3-react-background border-b3-react-border flex items-center justify-center gap-3 rounded-lg border p-6", children: [_jsx(Loader2, { className: "h-4 w-4 animate-spin" }), _jsx("span", { className: "text-as-primary/70", children: "Loading payment options..." })] })) : (_jsxs(_Fragment, { children: [_jsxs("div", { className: "mb-3 flex items-center justify-between", children: [_jsx("h2", { className: "text-lg font-semibold", children: "Payment method" }), _jsx("div", { className: "flex items-center gap-1", children: coinbaseAvailablePaymentMethods.length > 0 &&
96
98
  (() => {
97
99
  const hasCard = coinbaseAvailablePaymentMethods.some(m => m.id === "CARD");
@@ -102,5 +104,5 @@ function PanelOnrampPaymentInner(props) {
102
104
  (() => {
103
105
  const method = coinbaseAvailablePaymentMethods[0];
104
106
  return (_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: [_jsxs("div", { className: "flex items-center gap-4", children: [_jsx("div", { className: "flex h-12 w-12 items-center justify-center rounded-full bg-blue-50", children: _jsx("img", { src: "https://cdn.b3.fun/coinbase-wordmark-blue.svg", alt: "Coinbase", className: "h-6" }) }), _jsxs("div", { className: "flex flex-col items-start text-left", children: [_jsx("h4", { className: "text-b3-react-foreground text-lg font-semibold", children: "Coinbase Pay" }), _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"] }), _jsx("div", { className: "mt-1 flex items-center gap-1", children: _jsx("span", { className: "text-xs font-medium text-green-600", children: "Free" }) })] })] }), _jsx(ChevronRight, { className: "text-b3-react-foreground/40 group-hover:text-b3-react-foreground/60 h-5 w-5 transition-colors" })] }));
105
- })(), stripeWeb2Support.isSupport && (_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: [_jsxs("div", { className: "flex items-center gap-4", children: [_jsx("div", { className: "flex h-12 w-12 items-center justify-center rounded-full bg-purple-50", children: _jsx("img", { src: "https://raw.githubusercontent.com/stripe/stripe.github.io/455f506a628dc3f6c505e3001db45a64e29e9fc3/images/stripe-logo.svg", alt: "Stripe", className: "h-5" }) }), _jsxs("div", { className: "flex flex-col items-start text-left", children: [_jsx("h4", { className: "text-b3-react-foreground text-lg font-semibold", children: "Stripe" }), _jsx("p", { className: "text-b3-react-foreground/60 text-sm", children: "Credit or debit card payment" }), _jsx("div", { className: "mt-1 flex items-center gap-1", children: _jsx("span", { className: "text-xs font-medium text-orange-600", children: "Fee Applied" }) })] })] }), _jsx(ChevronRight, { className: "text-b3-react-foreground/40 group-hover:text-b3-react-foreground/60 h-5 w-5 transition-colors" })] })), _jsxs(Button, { variant: "link", onClick: onBack, className: "text-b3-react-foreground/70 hover:text-b3-react-foreground/90 mt-2 w-full", children: [_jsx(ChevronLeft, { className: "mr-2 h-4 w-4" }), "Back"] })] })] }))] }));
107
+ })(), stripeOnrampSupport && (_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: [_jsxs("div", { className: "flex items-center gap-4", children: [_jsx("div", { className: "flex h-12 w-12 items-center justify-center rounded-full bg-purple-50", children: _jsx("img", { src: "https://raw.githubusercontent.com/stripe/stripe.github.io/455f506a628dc3f6c505e3001db45a64e29e9fc3/images/stripe-logo.svg", alt: "Stripe", className: "h-5" }) }), _jsxs("div", { className: "flex flex-col items-start text-left", children: [_jsx("h4", { className: "text-b3-react-foreground text-lg font-semibold", children: "Credit/Debit Card" }), _jsx("p", { className: "text-b3-react-foreground/60 text-sm", children: "Pay via Stripe checkout" }), stripeWeb2Support?.isSupport && stripeWeb2Support.formattedFeeUsd && (_jsx("div", { className: "mt-1", children: _jsxs("span", { className: "text-xs text-gray-500", children: ["$", Number(stripeWeb2Support.formattedFeeUsd).toFixed(2), " fee"] }) }))] })] }), _jsx(ChevronRight, { className: "text-b3-react-foreground/40 group-hover:text-b3-react-foreground/60 h-5 w-5 transition-colors" })] })), stripeWeb2Support.isSupport && (_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: [_jsxs("div", { className: "flex items-center gap-4", children: [_jsx("div", { className: "flex h-12 w-12 items-center justify-center rounded-full bg-purple-50", children: _jsx("img", { src: "https://raw.githubusercontent.com/stripe/stripe.github.io/455f506a628dc3f6c505e3001db45a64e29e9fc3/images/stripe-logo.svg", alt: "Stripe", className: "h-5" }) }), _jsxs("div", { className: "flex flex-col items-start text-left", children: [_jsx("h4", { className: "text-b3-react-foreground text-lg font-semibold", children: "Quick Pay" }), _jsx("p", { className: "text-b3-react-foreground/60 text-sm", children: "Credit or debit card" }), stripeWeb2Support.formattedFeeUsd && (_jsx("div", { className: "mt-1", children: _jsxs("span", { className: "text-xs text-gray-500", children: ["$", Number(stripeWeb2Support.formattedFeeUsd).toFixed(2), " fee"] }) }))] })] }), _jsx(ChevronRight, { className: "text-b3-react-foreground/40 group-hover:text-b3-react-foreground/60 h-5 w-5 transition-colors" })] })), _jsxs(Button, { variant: "link", onClick: onBack, className: "text-b3-react-foreground/70 hover:text-b3-react-foreground/90 mt-2 w-full", children: [_jsx(ChevronLeft, { className: "mr-2 h-4 w-4" }), "Back"] })] })] }))] }));
106
108
  }
@@ -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;
@@ -13,7 +13,7 @@ export function useGeoOnrampOptions(srcFiatAmount) {
13
13
  // Use existing hooks
14
14
  const { geoData, loading: isLoadingGeo, error: geoError } = useGetGeo();
15
15
  const { coinbaseOnrampOptions, isLoadingCoinbaseOnrampOptions, coinbaseOnrampOptionsError } = useCoinbaseOnrampOptions(geoData?.country, visitorData);
16
- const { stripeWeb2Support, isLoadingStripeSupport, stripeSupportError } = useStripeSupport(srcFiatAmount, visitorData);
16
+ const { stripeOnrampSupport, stripeWeb2Support, isLoadingStripeSupport, stripeSupportError } = useStripeSupport(srcFiatAmount, visitorData);
17
17
  // Calculate available payment methods based on the amount
18
18
  const coinbaseAvailablePaymentMethods = useMemo(() => {
19
19
  if (!coinbaseOnrampOptions?.paymentCurrencies?.[0]?.limits || !srcFiatAmount)
@@ -31,8 +31,9 @@ export function useGeoOnrampOptions(srcFiatAmount) {
31
31
  geoData,
32
32
  coinbaseOnrampOptions,
33
33
  coinbaseAvailablePaymentMethods,
34
+ stripeOnrampSupport,
34
35
  stripeWeb2Support,
35
- isOnrampSupported: coinbaseAvailablePaymentMethods.length > 0 || stripeWeb2Support,
36
+ isOnrampSupported: coinbaseAvailablePaymentMethods.length > 0 || stripeOnrampSupport || stripeWeb2Support.isSupport,
36
37
  isLoading: isLoadingGeo || isLoadingCoinbaseOnrampOptions || isLoadingStripeSupport || isLoadingVisitorData,
37
38
  isLoadingGeo,
38
39
  isLoadingCoinbaseOnrampOptions,
@@ -44,6 +45,7 @@ export function useGeoOnrampOptions(srcFiatAmount) {
44
45
  geoData,
45
46
  coinbaseOnrampOptions,
46
47
  coinbaseAvailablePaymentMethods,
48
+ stripeOnrampSupport,
47
49
  stripeWeb2Support,
48
50
  isLoadingGeo,
49
51
  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
  } | {
@@ -8,6 +8,7 @@ export function useStripeSupport(usdAmount, visitorData, isLoadingVisitorData) {
8
8
  enabled: !isLoadingVisitorData,
9
9
  });
10
10
  return useMemo(() => ({
11
+ stripeOnrampSupport: data?.stripeOnramp || false,
11
12
  stripeWeb2Support: data?.stripeWeb2 || { isSupport: false },
12
13
  isLoadingStripeSupport: isLoading,
13
14
  stripeSupportError: error,
@@ -1,5 +1,6 @@
1
1
  "use client";
2
2
  import { jsx as _jsx } from "react/jsx-runtime";
3
+ import { getIpfsUrl } from "../../../../shared/utils/ipfs.js";
3
4
  import { client as defaultClient } from "../../../../shared/utils/thirdweb.js";
4
5
  import { MediaRenderer } from "thirdweb/react";
5
6
  /**
@@ -25,7 +26,8 @@ export function IPFSMediaRenderer({ src, alt = "Media", className, client = defa
25
26
  if (!src) {
26
27
  return (_jsx("div", { className: className, style: style, "aria-label": alt, children: _jsx("div", { className: "bg-b3-primary-wash flex h-full w-full items-center justify-center rounded-full", children: _jsx("span", { className: "text-b3-grey font-neue-montreal-semibold text-xs", children: alt.charAt(0).toUpperCase() }) }) }));
27
28
  }
28
- // Convert IPFS URLs to HTTP gateway URLs if needed
29
- // This handles both ipfs:// URLs and existing HTTP gateway URLs
30
- return (_jsx(MediaRenderer, { src: src, client: client, alt: alt, className: className, width: width ? width.toString() : undefined, height: height ? height.toString() : undefined, controls: controls, style: style }));
29
+ // Convert IPFS URLs to HTTP gateway URLs using our preferred gateway
30
+ // This avoids Thirdweb's default cloudflare-ipfs.com which can be unreliable
31
+ const resolvedSrc = src.startsWith("ipfs://") ? getIpfsUrl(src) : src;
32
+ return (_jsx(MediaRenderer, { src: resolvedSrc, client: client, alt: alt, className: className, width: width ? width.toString() : undefined, height: height ? height.toString() : undefined, controls: controls, style: style }));
31
33
  }
@@ -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;
@@ -3,22 +3,22 @@
3
3
  * These gateways must match the allowed list in profileDisplay.ts validateImageUrl()
4
4
  */
5
5
  const IPFS_GATEWAYS = [
6
- "https://cloudflare-ipfs.com/ipfs", // Primary gateway - fast and reliable
6
+ "https://dweb.link/ipfs", // Primary gateway - Protocol Labs maintained
7
+ "https://w3s.link/ipfs", // web3.storage gateway - reliable
8
+ "https://nftstorage.link/ipfs", // NFT.storage gateway
9
+ "https://gateway.pinata.cloud/ipfs", // Pinata gateway
7
10
  "https://ipfs.io/ipfs", // Fallback gateway
8
- "https://gateway.pinata.cloud/ipfs", // Additional option
9
- "https://dweb.link/ipfs", // Additional option
10
- "https://nftstorage.link/ipfs", // Additional option
11
- "https://w3s.link/ipfs", // Additional option
11
+ "https://cloudflare-ipfs.com/ipfs", // Cloudflare gateway (can be slow/unreliable)
12
12
  ];
13
13
  /**
14
14
  * Converts an IPFS URL to a gateway URL
15
15
  * @param ipfsUrl - URL in format ipfs://CID/path or just the CID
16
- * @param gatewayIndex - Optional index to specify which gateway to use (0: Cloudflare, 1: ipfs.io)
16
+ * @param gatewayIndex - Optional index to specify which gateway to use (0: dweb.link, 1: w3s.link, etc.)
17
17
  * @returns HTTP URL using the specified IPFS gateway
18
18
  * @example
19
- * // returns 'https://cloudflare-ipfs.com/ipfs/QmUbJ4p.../2.png'
19
+ * // returns 'https://dweb.link/ipfs/QmUbJ4p.../2.png'
20
20
  * getIpfsUrl('ipfs://QmUbJ4pnHMNXGeWWhBFFSEqCGuc6cEtDyz35wQfv7k2TXy/2.png')
21
- * // returns 'https://ipfs.io/ipfs/QmUbJ4p.../2.png'
21
+ * // returns 'https://w3s.link/ipfs/QmUbJ4p.../2.png'
22
22
  * getIpfsUrl('ipfs://QmUbJ4pnHMNXGeWWhBFFSEqCGuc6cEtDyz35wQfv7k2TXy/2.png', 1)
23
23
  */
24
24
  export function getIpfsUrl(ipfsUrl, gatewayIndex = 0) {