@b3dotfun/sdk 0.0.16-alpha.1 → 0.0.16-alpha.3

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.
@@ -162,8 +162,8 @@ function AnySpendCustom({ isMainnet = true, loadOrder, mode = "modal", recipient
162
162
  const getRelayQuoteRequest = (0, react_4.useMemo)(() => {
163
163
  return generateGetRelayQuoteRequest({
164
164
  orderType: orderType,
165
- srcChainId: srcChainId,
166
- srcToken: srcToken,
165
+ srcChainId: activeTab === "fiat" ? chains_1.base.id : srcChainId,
166
+ srcToken: activeTab === "fiat" ? constants_1.USDC_BASE : srcToken,
167
167
  dstChainId: dstChainId,
168
168
  dstToken: dstToken,
169
169
  dstAmount: dstAmount,
@@ -174,20 +174,21 @@ function AnySpendCustom({ isMainnet = true, loadOrder, mode = "modal", recipient
174
174
  spenderAddress: spenderAddress,
175
175
  });
176
176
  }, [
177
+ activeTab,
177
178
  contractAddress,
178
179
  dstAmount,
179
180
  dstChainId,
180
181
  dstToken,
181
182
  encodedData,
182
- metadata,
183
+ metadata.nftContract.tokenId,
184
+ metadata.nftContract.type,
185
+ metadata.type,
183
186
  orderType,
184
187
  spenderAddress,
185
188
  srcChainId,
186
189
  srcToken,
187
190
  ]);
188
191
  const { anyspendQuote, isLoadingAnyspendQuote } = (0, react_1.useAnyspendQuote)(isMainnet, getRelayQuoteRequest);
189
- // Get geo data and onramp options (after quote is available)
190
- const { geoData, isOnrampSupported } = (0, react_1.useGeoOnrampOptions)(isMainnet, anyspendQuote?.data?.currencyIn?.amountUsd || "0");
191
192
  const { orderAndTransactions: oat } = (0, react_1.useAnyspendOrderAndTransactions)(isMainnet, orderId);
192
193
  const onSelectOrder = (selectedOrderId) => {
193
194
  setActivePanel(PanelView.ORDER_DETAILS);
@@ -197,30 +198,25 @@ function AnySpendCustom({ isMainnet = true, loadOrder, mode = "modal", recipient
197
198
  params.set("orderId", selectedOrderId);
198
199
  router.push(`${window.location.pathname}?${params.toString()}`);
199
200
  };
200
- const [srcAmount, setSrcAmount] = (0, react_4.useState)(null);
201
- const formattedSrcAmount = srcAmount ? (0, number_1.formatTokenAmount)(srcAmount, srcToken.decimals, 6, false) : null;
202
- // Update the selected src token to USDC and chain to base when the active tab is fiat,
203
- // also force not to update srcToken by setting dirtySelectSrcToken to true.
204
- (0, react_4.useEffect)(() => {
205
- if (activeTab === "fiat") {
206
- setSrcChainId(chains_1.base.id);
207
- setSrcToken(constants_1.USDC_BASE);
208
- setDirtySelectSrcToken(true);
209
- }
210
- }, [activeTab]);
211
201
  // Update dependent amount when relay price changes
212
- (0, react_4.useEffect)(() => {
213
- if (anyspendQuote?.data &&
214
- anyspendQuote.data.currencyIn?.amount &&
215
- anyspendQuote.data.currencyIn?.currency?.decimals) {
216
- // Use toPrecision instead of toSignificant
217
- const amount = anyspendQuote.data.currencyIn.amount;
218
- setSrcAmount(BigInt(amount));
202
+ const srcAmount = (0, react_4.useMemo)(() => {
203
+ if (!anyspendQuote?.data ||
204
+ !anyspendQuote?.data?.currencyIn?.amount ||
205
+ !anyspendQuote?.data?.currencyIn?.currency?.decimals)
206
+ return null;
207
+ const amount = anyspendQuote.data.currencyIn.amount;
208
+ if (activeTab === "fiat") {
209
+ const roundUpAmount = (0, anyspend_1.roundUpUSDCBaseAmountToNearest)(amount);
210
+ return BigInt(roundUpAmount);
219
211
  }
220
212
  else {
221
- setSrcAmount(null);
213
+ return BigInt(amount);
222
214
  }
223
- }, [anyspendQuote?.data]);
215
+ }, [activeTab, anyspendQuote?.data]);
216
+ const formattedSrcAmount = srcAmount ? (0, number_1.formatTokenAmount)(srcAmount, srcToken.decimals, 6, false) : null;
217
+ const srcFiatAmount = (0, react_4.useMemo)(() => (activeTab === "fiat" && srcAmount ? (0, number_1.formatUnits)(srcAmount.toString(), constants_1.USDC_BASE.decimals) : "0"), [activeTab, srcAmount]);
218
+ // Get geo data and onramp options (after quote is available)
219
+ const { geoData, isOnrampSupported } = (0, react_1.useGeoOnrampOptions)(isMainnet, srcFiatAmount);
224
220
  (0, react_4.useEffect)(() => {
225
221
  if (oat?.data?.order.status === "executed") {
226
222
  console.log("Calling onSuccess");
@@ -254,9 +250,9 @@ function AnySpendCustom({ isMainnet = true, loadOrder, mode = "modal", recipient
254
250
  const createOrderParams = {
255
251
  isMainnet: isMainnet,
256
252
  orderType: orderType,
257
- srcChain: srcChainId,
253
+ srcChain: activeTab === "fiat" ? chains_1.base.id : srcChainId,
258
254
  dstChain: dstChainId,
259
- srcToken: srcToken,
255
+ srcToken: activeTab === "fiat" ? constants_1.USDC_BASE : srcToken,
260
256
  dstToken: dstToken,
261
257
  srcAmount: srcAmount.toString(),
262
258
  recipientAddress,
@@ -305,7 +301,7 @@ function AnySpendCustom({ isMainnet = true, loadOrder, mode = "modal", recipient
305
301
  (0, invariant_1.default)(srcChainId === chains_1.base.id, "Selected src chain is not base");
306
302
  void createOnrampOrder({
307
303
  ...createOrderParams,
308
- srcFiatAmount: anyspendQuote?.data?.currencyIn?.amountUsd || "0",
304
+ srcFiatAmount: srcFiatAmount,
309
305
  onramp: {
310
306
  vendor: onramp.vendor,
311
307
  paymentMethod: onramp.paymentMethod,
@@ -394,7 +390,7 @@ function AnySpendCustom({ isMainnet = true, loadOrder, mode = "modal", recipient
394
390
  opacity: hasMounted ? 1 : 0,
395
391
  y: hasMounted ? 0 : 20,
396
392
  filter: hasMounted ? "blur(0px)" : "blur(10px)",
397
- }, transition: { duration: 0.3, delay: 0.3, ease: "easeInOut" }, className: "flex w-full flex-col gap-2", children: (0, jsx_runtime_1.jsx)(react_2.ShinyButton, { accentColor: "hsl(var(--as-brand))", textColor: "text-white", disabled: isCreatingOrder || isLoadingAnyspendQuote || !anyspendQuote || !recipientAddress, onClick: () => handleConfirmOrder(), className: "relative w-full", children: isCreatingOrder ? ((0, jsx_runtime_1.jsxs)("div", { className: "flex items-center gap-2", children: [(0, jsx_runtime_1.jsx)(lucide_react_1.Loader2, { className: "size-4 animate-spin" }), (0, jsx_runtime_1.jsx)("span", { children: "Creating order..." })] })) : isLoadingAnyspendQuote ? ((0, jsx_runtime_1.jsxs)("div", { className: "flex items-center gap-2", children: [(0, jsx_runtime_1.jsx)(lucide_react_1.Loader2, { className: "size-4 animate-spin" }), (0, jsx_runtime_1.jsx)("span", { children: "Loading quote..." })] })) : anyspendQuote && recipientAddress ? ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsx)("span", { children: "Checkout" }), (0, jsx_runtime_1.jsx)(lucide_react_1.ChevronRightCircle, { className: "absolute right-0 top-1/2 size-6 -translate-y-1/2 opacity-70" })] })) : recipientAddress ? ("No quote found") : ("Please select a recipient") }) }) })] }) }), (0, jsx_runtime_1.jsx)(react_2.TabsContent, { value: "fiat", children: (0, jsx_runtime_1.jsx)("div", { className: "mt-6 flex w-full flex-col gap-6", children: (0, jsx_runtime_1.jsx)(PanelOnrampPayment_1.PanelOnrampPayment, { srcAmountOnRamp: (0, anyspend_1.roundUpUsdAmountToNearest)(anyspendQuote?.data?.currencyIn?.amountUsd || "0"), recipientName: recipientEnsName, recipientAddress: recipientAddress, isMainnet: isMainnet, isBuyMode: false, selectedDstChainId: dstChainId, selectedDstToken: dstToken, anyspendQuote: anyspendQuote, globalAddress: currentWallet?.wallet?.address, onOrderCreated: (orderId) => setOrderId(orderId), onBack: () => setActiveTab("crypto"), orderType: orderType, nft: metadata.type === "mint_nft"
393
+ }, transition: { duration: 0.3, delay: 0.3, ease: "easeInOut" }, className: "flex w-full flex-col gap-2", children: (0, jsx_runtime_1.jsx)(react_2.ShinyButton, { accentColor: "hsl(var(--as-brand))", textColor: "text-white", disabled: isCreatingOrder || isLoadingAnyspendQuote || !anyspendQuote || !recipientAddress, onClick: () => handleConfirmOrder(), className: "relative w-full", children: isCreatingOrder ? ((0, jsx_runtime_1.jsxs)("div", { className: "flex items-center gap-2", children: [(0, jsx_runtime_1.jsx)(lucide_react_1.Loader2, { className: "size-4 animate-spin" }), (0, jsx_runtime_1.jsx)("span", { children: "Creating order..." })] })) : isLoadingAnyspendQuote ? ((0, jsx_runtime_1.jsxs)("div", { className: "flex items-center gap-2", children: [(0, jsx_runtime_1.jsx)(lucide_react_1.Loader2, { className: "size-4 animate-spin" }), (0, jsx_runtime_1.jsx)("span", { children: "Loading quote..." })] })) : anyspendQuote && recipientAddress ? ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsx)("span", { children: "Checkout" }), (0, jsx_runtime_1.jsx)(lucide_react_1.ChevronRightCircle, { className: "absolute right-0 top-1/2 size-6 -translate-y-1/2 opacity-70" })] })) : recipientAddress ? ("No quote found") : ("Please select a recipient") }) }) })] }) }), (0, jsx_runtime_1.jsx)(react_2.TabsContent, { value: "fiat", children: (0, jsx_runtime_1.jsx)("div", { className: "mt-6 flex w-full flex-col gap-6", children: (0, jsx_runtime_1.jsx)(PanelOnrampPayment_1.PanelOnrampPayment, { srcAmountOnRamp: srcAmount ? (0, number_1.formatUnits)(srcAmount.toString(), constants_1.USDC_BASE.decimals) : "0", recipientName: recipientEnsName, recipientAddress: recipientAddress, isMainnet: isMainnet, isBuyMode: false, selectedDstChainId: dstChainId, selectedDstToken: dstToken, anyspendQuote: anyspendQuote, globalAddress: currentWallet?.wallet?.address, onOrderCreated: (orderId) => setOrderId(orderId), onBack: () => setActiveTab("crypto"), orderType: orderType, nft: metadata.type === "mint_nft"
398
394
  ? metadata.nftContract.type === "erc1155"
399
395
  ? {
400
396
  type: "erc1155",
@@ -11,7 +11,6 @@ const centerTruncate_1 = __importDefault(require("../../../../shared/utils/cente
11
11
  const invariant_1 = __importDefault(require("invariant"));
12
12
  const lucide_react_1 = require("lucide-react");
13
13
  const react_3 = require("motion/react");
14
- const react_4 = require("react");
15
14
  const sonner_1 = require("sonner");
16
15
  const AnySpendFingerprintWrapper_1 = require("../AnySpendFingerprintWrapper");
17
16
  function PanelOnrampPayment(props) {
@@ -20,17 +19,7 @@ function PanelOnrampPayment(props) {
20
19
  }
21
20
  function PanelOnrampPaymentInner(props) {
22
21
  const { srcAmountOnRamp, recipientAddress, isMainnet, isBuyMode, destinationTokenChainId, destinationTokenAddress, selectedDstChainId, selectedDstToken, anyspendQuote, globalAddress, onOrderCreated, onBack, orderType, nft, tournament, payload, recipientEnsName, recipientImageUrl, } = props;
23
- // Use a stable amount for geo onramp options to prevent unnecessary refetches
24
- const [stableAmountForGeo, setStableAmountForGeo] = (0, react_4.useState)(srcAmountOnRamp);
25
- const hasInitialized = (0, react_4.useRef)(false);
26
- // Only update the stable amount on first render or when explicitly needed
27
- (0, react_4.useEffect)(() => {
28
- if (!hasInitialized.current && srcAmountOnRamp) {
29
- setStableAmountForGeo(srcAmountOnRamp);
30
- hasInitialized.current = true;
31
- }
32
- }, [srcAmountOnRamp]);
33
- const { geoData, coinbaseOnrampOptions, coinbaseAvailablePaymentMethods, isStripeOnrampSupported, stripeWeb2Support, isLoading: isLoadingGeoOnramp, } = (0, react_1.useGeoOnrampOptions)(isMainnet, stableAmountForGeo);
22
+ const { geoData, coinbaseOnrampOptions, coinbaseAvailablePaymentMethods, isStripeOnrampSupported, stripeWeb2Support, isLoading: isLoadingGeoOnramp, } = (0, react_1.useGeoOnrampOptions)(isMainnet, srcAmountOnRamp);
34
23
  const isLoading = isLoadingGeoOnramp;
35
24
  const { createOrder, isCreatingOrder } = (0, react_1.useAnyspendCreateOnrampOrder)({
36
25
  onSuccess: data => {
@@ -91,18 +91,9 @@ function StripePaymentForm({ order, onPaymentSuccess, }) {
91
91
  } }) })), error && ((0, jsx_runtime_1.jsx)("div", { className: "mt-4 rounded-lg border border-red-200 bg-red-50 p-3 text-sm text-red-600", children: error })), (0, jsx_runtime_1.jsx)("button", { type: "submit", disabled: !stripe || isProcessing, className: "mt-6 w-full rounded-xl bg-blue-600 px-4 py-3 font-medium text-white hover:bg-blue-700 disabled:cursor-not-allowed disabled:opacity-50", children: isProcessing ? ((0, jsx_runtime_1.jsxs)("div", { className: "flex items-center justify-center gap-2", children: [(0, jsx_runtime_1.jsx)(lucide_react_1.Loader2, { className: "h-5 w-5 animate-spin" }), (0, jsx_runtime_1.jsx)("span", { children: "Processing..." })] })) : ((0, jsx_runtime_1.jsx)("span", { children: "Complete Payment" })) })] }) }) }));
92
92
  }
93
93
  function WebviewOnrampPaymentInner({ srcAmountOnRamp, recipientAddress, destinationToken, anyspendQuote, onPaymentSuccess, userId, partnerId, }) {
94
- const [stableAmountForGeo, setStableAmountForGeo] = (0, react_3.useState)(srcAmountOnRamp);
95
- const hasInitialized = (0, react_3.useRef)(false);
96
94
  const [createdOrder, setCreatedOrder] = (0, react_3.useState)(null);
97
95
  const orderCreationAttempted = (0, react_3.useRef)(false);
98
- // Only update the stable amount on first render or when explicitly needed
99
- (0, react_3.useEffect)(() => {
100
- if (!hasInitialized.current && srcAmountOnRamp) {
101
- setStableAmountForGeo(srcAmountOnRamp);
102
- hasInitialized.current = true;
103
- }
104
- }, [srcAmountOnRamp]);
105
- const { geoData, stripeWeb2Support, isLoading: isLoadingGeoOnramp } = (0, react_1.useGeoOnrampOptions)(true, stableAmountForGeo);
96
+ const { geoData, stripeWeb2Support, isLoading: isLoadingGeoOnramp } = (0, react_1.useGeoOnrampOptions)(true, srcAmountOnRamp);
106
97
  const { createOrder, isCreatingOrder } = (0, react_1.useAnyspendCreateOnrampOrder)({
107
98
  onSuccess: data => {
108
99
  setCreatedOrder(data.data);
@@ -1,11 +1,11 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
- import { eqci, getDefaultToken, roundUpUsdAmountToNearest } from "../../../anyspend/index.js";
2
+ import { eqci, getDefaultToken, roundUpUSDCBaseAmountToNearest } from "../../../anyspend/index.js";
3
3
  import { RELAY_ETH_ADDRESS, USDC_BASE } from "../../../anyspend/constants/index.js";
4
4
  import { useAnyspendCreateOnrampOrder, useAnyspendCreateOrder, useAnyspendOrderAndTransactions, useAnyspendQuote, useAnyspendTokenList, useGeoOnrampOptions, } from "../../../anyspend/react/index.js";
5
5
  import { Badge, Button, Dialog, DialogContent, Input, ShinyButton, Skeleton, StyleRoot, Tabs, TabsContent, TabsList, TabTrigger, TextShimmer, Tooltip, TooltipContent, TooltipTrigger, TransitionPanel, useAccountWallet, useHasMounted, useProfile, useRouter, useSearchParamsSSR, useTokenBalancesByChain, } from "../../../global-account/react/index.js";
6
6
  import { cn } from "../../../shared/utils/index.js";
7
7
  import centerTruncate from "../../../shared/utils/centerTruncate.js";
8
- import { formatTokenAmount } from "../../../shared/utils/number.js";
8
+ import { formatTokenAmount, formatUnits } from "../../../shared/utils/number.js";
9
9
  import { simpleHashChainToChainName } from "../../../shared/utils/simplehash.js";
10
10
  import invariant from "invariant";
11
11
  import { ChevronRightCircle, Loader2 } from "lucide-react";
@@ -156,8 +156,8 @@ export function AnySpendCustom({ isMainnet = true, loadOrder, mode = "modal", re
156
156
  const getRelayQuoteRequest = useMemo(() => {
157
157
  return generateGetRelayQuoteRequest({
158
158
  orderType: orderType,
159
- srcChainId: srcChainId,
160
- srcToken: srcToken,
159
+ srcChainId: activeTab === "fiat" ? base.id : srcChainId,
160
+ srcToken: activeTab === "fiat" ? USDC_BASE : srcToken,
161
161
  dstChainId: dstChainId,
162
162
  dstToken: dstToken,
163
163
  dstAmount: dstAmount,
@@ -168,20 +168,21 @@ export function AnySpendCustom({ isMainnet = true, loadOrder, mode = "modal", re
168
168
  spenderAddress: spenderAddress,
169
169
  });
170
170
  }, [
171
+ activeTab,
171
172
  contractAddress,
172
173
  dstAmount,
173
174
  dstChainId,
174
175
  dstToken,
175
176
  encodedData,
176
- metadata,
177
+ metadata.nftContract.tokenId,
178
+ metadata.nftContract.type,
179
+ metadata.type,
177
180
  orderType,
178
181
  spenderAddress,
179
182
  srcChainId,
180
183
  srcToken,
181
184
  ]);
182
185
  const { anyspendQuote, isLoadingAnyspendQuote } = useAnyspendQuote(isMainnet, getRelayQuoteRequest);
183
- // Get geo data and onramp options (after quote is available)
184
- const { geoData, isOnrampSupported } = useGeoOnrampOptions(isMainnet, anyspendQuote?.data?.currencyIn?.amountUsd || "0");
185
186
  const { orderAndTransactions: oat } = useAnyspendOrderAndTransactions(isMainnet, orderId);
186
187
  const onSelectOrder = (selectedOrderId) => {
187
188
  setActivePanel(PanelView.ORDER_DETAILS);
@@ -191,30 +192,25 @@ export function AnySpendCustom({ isMainnet = true, loadOrder, mode = "modal", re
191
192
  params.set("orderId", selectedOrderId);
192
193
  router.push(`${window.location.pathname}?${params.toString()}`);
193
194
  };
194
- const [srcAmount, setSrcAmount] = useState(null);
195
- const formattedSrcAmount = srcAmount ? formatTokenAmount(srcAmount, srcToken.decimals, 6, false) : null;
196
- // Update the selected src token to USDC and chain to base when the active tab is fiat,
197
- // also force not to update srcToken by setting dirtySelectSrcToken to true.
198
- useEffect(() => {
199
- if (activeTab === "fiat") {
200
- setSrcChainId(base.id);
201
- setSrcToken(USDC_BASE);
202
- setDirtySelectSrcToken(true);
203
- }
204
- }, [activeTab]);
205
195
  // Update dependent amount when relay price changes
206
- useEffect(() => {
207
- if (anyspendQuote?.data &&
208
- anyspendQuote.data.currencyIn?.amount &&
209
- anyspendQuote.data.currencyIn?.currency?.decimals) {
210
- // Use toPrecision instead of toSignificant
211
- const amount = anyspendQuote.data.currencyIn.amount;
212
- setSrcAmount(BigInt(amount));
196
+ const srcAmount = useMemo(() => {
197
+ if (!anyspendQuote?.data ||
198
+ !anyspendQuote?.data?.currencyIn?.amount ||
199
+ !anyspendQuote?.data?.currencyIn?.currency?.decimals)
200
+ return null;
201
+ const amount = anyspendQuote.data.currencyIn.amount;
202
+ if (activeTab === "fiat") {
203
+ const roundUpAmount = roundUpUSDCBaseAmountToNearest(amount);
204
+ return BigInt(roundUpAmount);
213
205
  }
214
206
  else {
215
- setSrcAmount(null);
207
+ return BigInt(amount);
216
208
  }
217
- }, [anyspendQuote?.data]);
209
+ }, [activeTab, anyspendQuote?.data]);
210
+ const formattedSrcAmount = srcAmount ? formatTokenAmount(srcAmount, srcToken.decimals, 6, false) : null;
211
+ const srcFiatAmount = useMemo(() => (activeTab === "fiat" && srcAmount ? formatUnits(srcAmount.toString(), USDC_BASE.decimals) : "0"), [activeTab, srcAmount]);
212
+ // Get geo data and onramp options (after quote is available)
213
+ const { geoData, isOnrampSupported } = useGeoOnrampOptions(isMainnet, srcFiatAmount);
218
214
  useEffect(() => {
219
215
  if (oat?.data?.order.status === "executed") {
220
216
  console.log("Calling onSuccess");
@@ -248,9 +244,9 @@ export function AnySpendCustom({ isMainnet = true, loadOrder, mode = "modal", re
248
244
  const createOrderParams = {
249
245
  isMainnet: isMainnet,
250
246
  orderType: orderType,
251
- srcChain: srcChainId,
247
+ srcChain: activeTab === "fiat" ? base.id : srcChainId,
252
248
  dstChain: dstChainId,
253
- srcToken: srcToken,
249
+ srcToken: activeTab === "fiat" ? USDC_BASE : srcToken,
254
250
  dstToken: dstToken,
255
251
  srcAmount: srcAmount.toString(),
256
252
  recipientAddress,
@@ -299,7 +295,7 @@ export function AnySpendCustom({ isMainnet = true, loadOrder, mode = "modal", re
299
295
  invariant(srcChainId === base.id, "Selected src chain is not base");
300
296
  void createOnrampOrder({
301
297
  ...createOrderParams,
302
- srcFiatAmount: anyspendQuote?.data?.currencyIn?.amountUsd || "0",
298
+ srcFiatAmount: srcFiatAmount,
303
299
  onramp: {
304
300
  vendor: onramp.vendor,
305
301
  paymentMethod: onramp.paymentMethod,
@@ -388,7 +384,7 @@ export function AnySpendCustom({ isMainnet = true, loadOrder, mode = "modal", re
388
384
  opacity: hasMounted ? 1 : 0,
389
385
  y: hasMounted ? 0 : 20,
390
386
  filter: hasMounted ? "blur(0px)" : "blur(10px)",
391
- }, transition: { duration: 0.3, delay: 0.3, ease: "easeInOut" }, className: "flex w-full flex-col gap-2", children: _jsx(ShinyButton, { accentColor: "hsl(var(--as-brand))", textColor: "text-white", disabled: isCreatingOrder || isLoadingAnyspendQuote || !anyspendQuote || !recipientAddress, onClick: () => handleConfirmOrder(), className: "relative w-full", children: isCreatingOrder ? (_jsxs("div", { className: "flex items-center gap-2", children: [_jsx(Loader2, { className: "size-4 animate-spin" }), _jsx("span", { children: "Creating order..." })] })) : isLoadingAnyspendQuote ? (_jsxs("div", { className: "flex items-center gap-2", children: [_jsx(Loader2, { className: "size-4 animate-spin" }), _jsx("span", { children: "Loading quote..." })] })) : anyspendQuote && recipientAddress ? (_jsxs(_Fragment, { children: [_jsx("span", { children: "Checkout" }), _jsx(ChevronRightCircle, { className: "absolute right-0 top-1/2 size-6 -translate-y-1/2 opacity-70" })] })) : recipientAddress ? ("No quote found") : ("Please select a recipient") }) }) })] }) }), _jsx(TabsContent, { value: "fiat", children: _jsx("div", { className: "mt-6 flex w-full flex-col gap-6", children: _jsx(PanelOnrampPayment, { srcAmountOnRamp: roundUpUsdAmountToNearest(anyspendQuote?.data?.currencyIn?.amountUsd || "0"), recipientName: recipientEnsName, recipientAddress: recipientAddress, isMainnet: isMainnet, isBuyMode: false, selectedDstChainId: dstChainId, selectedDstToken: dstToken, anyspendQuote: anyspendQuote, globalAddress: currentWallet?.wallet?.address, onOrderCreated: (orderId) => setOrderId(orderId), onBack: () => setActiveTab("crypto"), orderType: orderType, nft: metadata.type === "mint_nft"
387
+ }, transition: { duration: 0.3, delay: 0.3, ease: "easeInOut" }, className: "flex w-full flex-col gap-2", children: _jsx(ShinyButton, { accentColor: "hsl(var(--as-brand))", textColor: "text-white", disabled: isCreatingOrder || isLoadingAnyspendQuote || !anyspendQuote || !recipientAddress, onClick: () => handleConfirmOrder(), className: "relative w-full", children: isCreatingOrder ? (_jsxs("div", { className: "flex items-center gap-2", children: [_jsx(Loader2, { className: "size-4 animate-spin" }), _jsx("span", { children: "Creating order..." })] })) : isLoadingAnyspendQuote ? (_jsxs("div", { className: "flex items-center gap-2", children: [_jsx(Loader2, { className: "size-4 animate-spin" }), _jsx("span", { children: "Loading quote..." })] })) : anyspendQuote && recipientAddress ? (_jsxs(_Fragment, { children: [_jsx("span", { children: "Checkout" }), _jsx(ChevronRightCircle, { className: "absolute right-0 top-1/2 size-6 -translate-y-1/2 opacity-70" })] })) : recipientAddress ? ("No quote found") : ("Please select a recipient") }) }) })] }) }), _jsx(TabsContent, { value: "fiat", children: _jsx("div", { className: "mt-6 flex w-full flex-col gap-6", children: _jsx(PanelOnrampPayment, { srcAmountOnRamp: srcAmount ? formatUnits(srcAmount.toString(), USDC_BASE.decimals) : "0", recipientName: recipientEnsName, recipientAddress: recipientAddress, isMainnet: isMainnet, isBuyMode: false, selectedDstChainId: dstChainId, selectedDstToken: dstToken, anyspendQuote: anyspendQuote, globalAddress: currentWallet?.wallet?.address, onOrderCreated: (orderId) => setOrderId(orderId), onBack: () => setActiveTab("crypto"), orderType: orderType, nft: metadata.type === "mint_nft"
392
388
  ? metadata.nftContract.type === "erc1155"
393
389
  ? {
394
390
  type: "erc1155",
@@ -5,7 +5,6 @@ import centerTruncate from "../../../../shared/utils/centerTruncate.js";
5
5
  import invariant from "invariant";
6
6
  import { ChevronLeft, ChevronRight, Landmark, Loader2 } from "lucide-react";
7
7
  import { motion } from "motion/react";
8
- import { useEffect, useRef, useState } from "react";
9
8
  import { toast } from "sonner";
10
9
  import { AnySpendFingerprintWrapper, getFingerprintConfig } from "../AnySpendFingerprintWrapper.js";
11
10
  export function PanelOnrampPayment(props) {
@@ -14,17 +13,7 @@ export function PanelOnrampPayment(props) {
14
13
  }
15
14
  function PanelOnrampPaymentInner(props) {
16
15
  const { srcAmountOnRamp, recipientAddress, isMainnet, isBuyMode, destinationTokenChainId, destinationTokenAddress, selectedDstChainId, selectedDstToken, anyspendQuote, globalAddress, onOrderCreated, onBack, orderType, nft, tournament, payload, recipientEnsName, recipientImageUrl, } = props;
17
- // Use a stable amount for geo onramp options to prevent unnecessary refetches
18
- const [stableAmountForGeo, setStableAmountForGeo] = useState(srcAmountOnRamp);
19
- const hasInitialized = useRef(false);
20
- // Only update the stable amount on first render or when explicitly needed
21
- useEffect(() => {
22
- if (!hasInitialized.current && srcAmountOnRamp) {
23
- setStableAmountForGeo(srcAmountOnRamp);
24
- hasInitialized.current = true;
25
- }
26
- }, [srcAmountOnRamp]);
27
- const { geoData, coinbaseOnrampOptions, coinbaseAvailablePaymentMethods, isStripeOnrampSupported, stripeWeb2Support, isLoading: isLoadingGeoOnramp, } = useGeoOnrampOptions(isMainnet, stableAmountForGeo);
16
+ const { geoData, coinbaseOnrampOptions, coinbaseAvailablePaymentMethods, isStripeOnrampSupported, stripeWeb2Support, isLoading: isLoadingGeoOnramp, } = useGeoOnrampOptions(isMainnet, srcAmountOnRamp);
28
17
  const isLoading = isLoadingGeoOnramp;
29
18
  const { createOrder, isCreatingOrder } = useAnyspendCreateOnrampOrder({
30
19
  onSuccess: data => {
@@ -85,18 +85,9 @@ function StripePaymentForm({ order, onPaymentSuccess, }) {
85
85
  } }) })), error && (_jsx("div", { className: "mt-4 rounded-lg border border-red-200 bg-red-50 p-3 text-sm text-red-600", children: error })), _jsx("button", { type: "submit", disabled: !stripe || isProcessing, className: "mt-6 w-full rounded-xl bg-blue-600 px-4 py-3 font-medium text-white hover:bg-blue-700 disabled:cursor-not-allowed disabled:opacity-50", children: isProcessing ? (_jsxs("div", { className: "flex items-center justify-center gap-2", children: [_jsx(Loader2, { className: "h-5 w-5 animate-spin" }), _jsx("span", { children: "Processing..." })] })) : (_jsx("span", { children: "Complete Payment" })) })] }) }) }));
86
86
  }
87
87
  function WebviewOnrampPaymentInner({ srcAmountOnRamp, recipientAddress, destinationToken, anyspendQuote, onPaymentSuccess, userId, partnerId, }) {
88
- const [stableAmountForGeo, setStableAmountForGeo] = useState(srcAmountOnRamp);
89
- const hasInitialized = useRef(false);
90
88
  const [createdOrder, setCreatedOrder] = useState(null);
91
89
  const orderCreationAttempted = useRef(false);
92
- // Only update the stable amount on first render or when explicitly needed
93
- useEffect(() => {
94
- if (!hasInitialized.current && srcAmountOnRamp) {
95
- setStableAmountForGeo(srcAmountOnRamp);
96
- hasInitialized.current = true;
97
- }
98
- }, [srcAmountOnRamp]);
99
- const { geoData, stripeWeb2Support, isLoading: isLoadingGeoOnramp } = useGeoOnrampOptions(true, stableAmountForGeo);
90
+ const { geoData, stripeWeb2Support, isLoading: isLoadingGeoOnramp } = useGeoOnrampOptions(true, srcAmountOnRamp);
100
91
  const { createOrder, isCreatingOrder } = useAnyspendCreateOnrampOrder({
101
92
  onSuccess: data => {
102
93
  setCreatedOrder(data.data);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@b3dotfun/sdk",
3
- "version": "0.0.16-alpha.1",
3
+ "version": "0.0.16-alpha.3",
4
4
  "source": "src/index.ts",
5
5
  "main": "./dist/cjs/index.js",
6
6
  "react-native": "./dist/cjs/index.native.js",
@@ -1,4 +1,4 @@
1
- import { eqci, getDefaultToken, roundUpUsdAmountToNearest } from "@b3dotfun/sdk/anyspend";
1
+ import { eqci, getDefaultToken, roundUpUSDCBaseAmountToNearest } from "@b3dotfun/sdk/anyspend";
2
2
  import { RELAY_ETH_ADDRESS, USDC_BASE } from "@b3dotfun/sdk/anyspend/constants";
3
3
  import {
4
4
  CreateOrderParams,
@@ -38,7 +38,7 @@ import {
38
38
  } from "@b3dotfun/sdk/global-account/react";
39
39
  import { cn } from "@b3dotfun/sdk/shared/utils";
40
40
  import centerTruncate from "@b3dotfun/sdk/shared/utils/centerTruncate";
41
- import { formatTokenAmount } from "@b3dotfun/sdk/shared/utils/number";
41
+ import { formatTokenAmount, formatUnits } from "@b3dotfun/sdk/shared/utils/number";
42
42
  import { simpleHashChainToChainName } from "@b3dotfun/sdk/shared/utils/simplehash";
43
43
  import invariant from "invariant";
44
44
  import { ChevronRightCircle, Loader2 } from "lucide-react";
@@ -274,8 +274,8 @@ export function AnySpendCustom({
274
274
  const getRelayQuoteRequest = useMemo(() => {
275
275
  return generateGetRelayQuoteRequest({
276
276
  orderType: orderType,
277
- srcChainId: srcChainId,
278
- srcToken: srcToken,
277
+ srcChainId: activeTab === "fiat" ? base.id : srcChainId,
278
+ srcToken: activeTab === "fiat" ? USDC_BASE : srcToken,
279
279
  dstChainId: dstChainId,
280
280
  dstToken: dstToken,
281
281
  dstAmount: dstAmount,
@@ -286,12 +286,15 @@ export function AnySpendCustom({
286
286
  spenderAddress: spenderAddress,
287
287
  });
288
288
  }, [
289
+ activeTab,
289
290
  contractAddress,
290
291
  dstAmount,
291
292
  dstChainId,
292
293
  dstToken,
293
294
  encodedData,
294
- metadata,
295
+ metadata.nftContract.tokenId,
296
+ metadata.nftContract.type,
297
+ metadata.type,
295
298
  orderType,
296
299
  spenderAddress,
297
300
  srcChainId,
@@ -299,12 +302,6 @@ export function AnySpendCustom({
299
302
  ]);
300
303
  const { anyspendQuote, isLoadingAnyspendQuote } = useAnyspendQuote(isMainnet, getRelayQuoteRequest);
301
304
 
302
- // Get geo data and onramp options (after quote is available)
303
- const { geoData, isOnrampSupported } = useGeoOnrampOptions(
304
- isMainnet,
305
- anyspendQuote?.data?.currencyIn?.amountUsd || "0",
306
- );
307
-
308
305
  const { orderAndTransactions: oat } = useAnyspendOrderAndTransactions(isMainnet, orderId);
309
306
 
310
307
  const onSelectOrder = (selectedOrderId: string) => {
@@ -316,33 +313,31 @@ export function AnySpendCustom({
316
313
  router.push(`${window.location.pathname}?${params.toString()}`);
317
314
  };
318
315
 
319
- const [srcAmount, setSrcAmount] = useState<bigint | null>(null);
320
- const formattedSrcAmount = srcAmount ? formatTokenAmount(srcAmount, srcToken.decimals, 6, false) : null;
321
-
322
- // Update the selected src token to USDC and chain to base when the active tab is fiat,
323
- // also force not to update srcToken by setting dirtySelectSrcToken to true.
324
- useEffect(() => {
325
- if (activeTab === "fiat") {
326
- setSrcChainId(base.id);
327
- setSrcToken(USDC_BASE);
328
- setDirtySelectSrcToken(true);
329
- }
330
- }, [activeTab]);
331
-
332
316
  // Update dependent amount when relay price changes
333
- useEffect(() => {
317
+ const srcAmount = useMemo(() => {
334
318
  if (
335
- anyspendQuote?.data &&
336
- anyspendQuote.data.currencyIn?.amount &&
337
- anyspendQuote.data.currencyIn?.currency?.decimals
338
- ) {
339
- // Use toPrecision instead of toSignificant
340
- const amount = anyspendQuote.data.currencyIn.amount;
341
- setSrcAmount(BigInt(amount));
319
+ !anyspendQuote?.data ||
320
+ !anyspendQuote?.data?.currencyIn?.amount ||
321
+ !anyspendQuote?.data?.currencyIn?.currency?.decimals
322
+ )
323
+ return null;
324
+
325
+ const amount = anyspendQuote.data.currencyIn.amount;
326
+ if (activeTab === "fiat") {
327
+ const roundUpAmount = roundUpUSDCBaseAmountToNearest(amount);
328
+ return BigInt(roundUpAmount);
342
329
  } else {
343
- setSrcAmount(null);
330
+ return BigInt(amount);
344
331
  }
345
- }, [anyspendQuote?.data]);
332
+ }, [activeTab, anyspendQuote?.data]);
333
+ const formattedSrcAmount = srcAmount ? formatTokenAmount(srcAmount, srcToken.decimals, 6, false) : null;
334
+ const srcFiatAmount = useMemo(
335
+ () => (activeTab === "fiat" && srcAmount ? formatUnits(srcAmount.toString(), USDC_BASE.decimals) : "0"),
336
+ [activeTab, srcAmount],
337
+ );
338
+
339
+ // Get geo data and onramp options (after quote is available)
340
+ const { geoData, isOnrampSupported } = useGeoOnrampOptions(isMainnet, srcFiatAmount);
346
341
 
347
342
  useEffect(() => {
348
343
  if (oat?.data?.order.status === "executed") {
@@ -385,9 +380,9 @@ export function AnySpendCustom({
385
380
  const createOrderParams = {
386
381
  isMainnet: isMainnet,
387
382
  orderType: orderType,
388
- srcChain: srcChainId,
383
+ srcChain: activeTab === "fiat" ? base.id : srcChainId,
389
384
  dstChain: dstChainId,
390
- srcToken: srcToken,
385
+ srcToken: activeTab === "fiat" ? USDC_BASE : srcToken,
391
386
  dstToken: dstToken,
392
387
  srcAmount: srcAmount.toString(),
393
388
  recipientAddress,
@@ -440,7 +435,7 @@ export function AnySpendCustom({
440
435
  invariant(srcChainId === base.id, "Selected src chain is not base");
441
436
  void createOnrampOrder({
442
437
  ...createOrderParams,
443
- srcFiatAmount: anyspendQuote?.data?.currencyIn?.amountUsd || "0",
438
+ srcFiatAmount: srcFiatAmount,
444
439
  onramp: {
445
440
  vendor: onramp.vendor,
446
441
  paymentMethod: onramp.paymentMethod,
@@ -816,7 +811,7 @@ export function AnySpendCustom({
816
811
  <TabsContent value="fiat">
817
812
  <div className="mt-6 flex w-full flex-col gap-6">
818
813
  <PanelOnrampPayment
819
- srcAmountOnRamp={roundUpUsdAmountToNearest(anyspendQuote?.data?.currencyIn?.amountUsd || "0")}
814
+ srcAmountOnRamp={srcAmount ? formatUnits(srcAmount.toString(), USDC_BASE.decimals) : "0"}
820
815
  recipientName={recipientEnsName}
821
816
  recipientAddress={recipientAddress}
822
817
  isMainnet={isMainnet}
@@ -6,7 +6,6 @@ import centerTruncate from "@b3dotfun/sdk/shared/utils/centerTruncate";
6
6
  import invariant from "invariant";
7
7
  import { ChevronLeft, ChevronRight, Landmark, Loader2 } from "lucide-react";
8
8
  import { motion } from "motion/react";
9
- import { useEffect, useRef, useState } from "react";
10
9
  import { toast } from "sonner";
11
10
  import { AnySpendFingerprintWrapper, getFingerprintConfig } from "../AnySpendFingerprintWrapper";
12
11
 
@@ -64,18 +63,6 @@ function PanelOnrampPaymentInner(props: PanelOnrampPaymentProps) {
64
63
  recipientImageUrl,
65
64
  } = props;
66
65
 
67
- // Use a stable amount for geo onramp options to prevent unnecessary refetches
68
- const [stableAmountForGeo, setStableAmountForGeo] = useState(srcAmountOnRamp);
69
- const hasInitialized = useRef(false);
70
-
71
- // Only update the stable amount on first render or when explicitly needed
72
- useEffect(() => {
73
- if (!hasInitialized.current && srcAmountOnRamp) {
74
- setStableAmountForGeo(srcAmountOnRamp);
75
- hasInitialized.current = true;
76
- }
77
- }, [srcAmountOnRamp]);
78
-
79
66
  const {
80
67
  geoData,
81
68
  coinbaseOnrampOptions,
@@ -83,7 +70,7 @@ function PanelOnrampPaymentInner(props: PanelOnrampPaymentProps) {
83
70
  isStripeOnrampSupported,
84
71
  stripeWeb2Support,
85
72
  isLoading: isLoadingGeoOnramp,
86
- } = useGeoOnrampOptions(isMainnet, stableAmountForGeo);
73
+ } = useGeoOnrampOptions(isMainnet, srcAmountOnRamp);
87
74
 
88
75
  const isLoading = isLoadingGeoOnramp;
89
76
 
@@ -159,20 +159,10 @@ function WebviewOnrampPaymentInner({
159
159
  userId,
160
160
  partnerId,
161
161
  }: WebviewOnrampPaymentProps) {
162
- const [stableAmountForGeo, setStableAmountForGeo] = useState(srcAmountOnRamp);
163
- const hasInitialized = useRef(false);
164
162
  const [createdOrder, setCreatedOrder] = useState<components["schemas"]["Order"] | null>(null);
165
163
  const orderCreationAttempted = useRef(false);
166
164
 
167
- // Only update the stable amount on first render or when explicitly needed
168
- useEffect(() => {
169
- if (!hasInitialized.current && srcAmountOnRamp) {
170
- setStableAmountForGeo(srcAmountOnRamp);
171
- hasInitialized.current = true;
172
- }
173
- }, [srcAmountOnRamp]);
174
-
175
- const { geoData, stripeWeb2Support, isLoading: isLoadingGeoOnramp } = useGeoOnrampOptions(true, stableAmountForGeo);
165
+ const { geoData, stripeWeb2Support, isLoading: isLoadingGeoOnramp } = useGeoOnrampOptions(true, srcAmountOnRamp);
176
166
 
177
167
  const { createOrder, isCreatingOrder } = useAnyspendCreateOnrampOrder({
178
168
  onSuccess: data => {