@b3dotfun/sdk 0.0.8-alpha.1 → 0.0.8-alpha.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -129,8 +129,10 @@ function AnySpendBondKit({ mode = "modal", recipientAddress, contractAddress, mi
129
129
  setQuote(null);
130
130
  return;
131
131
  }
132
- // Only allow numbers and one decimal point
133
- if (!/^\d*\.?\d*$/.test(value)) {
132
+ // Only allow valid number format (no leading zeros unless decimal)
133
+ if (!/^(0|[1-9]\d*)?\.?\d*$/.test(value)) {
134
+ setIsAmountValid(false);
135
+ setValidationError("Please enter a valid number");
134
136
  return;
135
137
  }
136
138
  // Prevent multiple decimal points
@@ -142,9 +144,27 @@ function AnySpendBondKit({ mode = "modal", recipientAddress, contractAddress, mi
142
144
  if (parts[1] && parts[1].length > 18) {
143
145
  return;
144
146
  }
145
- setEthAmount(value);
147
+ // Clean the input - remove leading zeros if not decimal
148
+ const cleanedValue = value.startsWith("0") && !value.startsWith("0.") ? value.replace(/^0+/, "0") : value;
149
+ setEthAmount(cleanedValue);
150
+ try {
151
+ const parsedAmount = (0, viem_1.parseEther)(cleanedValue);
152
+ if (parsedAmount <= BigInt(0)) {
153
+ setIsAmountValid(false);
154
+ setValidationError("Amount must be greater than 0");
155
+ return;
156
+ }
157
+ setIsAmountValid(true);
158
+ setValidationError("");
159
+ debouncedGetQuote(cleanedValue);
160
+ }
161
+ catch (error) {
162
+ console.error("Error validating amount:", error);
163
+ setIsAmountValid(false);
164
+ setValidationError("Please enter a valid amount");
165
+ }
146
166
  };
147
- const header = () => ((0, jsx_runtime_1.jsx)("div", { className: "w-full px-6 py-4", children: (0, jsx_runtime_1.jsxs)("div", { className: "flex w-full flex-col items-center space-y-6", children: [(0, jsx_runtime_1.jsxs)("h2", { className: "text-[28px] font-bold", children: [tokenName, " (", tokenSymbol, ")"] }), (0, jsx_runtime_1.jsxs)("div", { className: "flex w-full flex-col items-center space-y-2", children: [(0, jsx_runtime_1.jsxs)("span", { className: "text-[28px] font-bold", children: [ethAmount, " ETH"] }), quote && ((0, jsx_runtime_1.jsxs)("span", { className: "text-lg", children: ["\u2248 ", formatNumberWithCommas(parseFloat(quote).toFixed(4)), " ", tokenSymbol] }))] })] }) }));
167
+ const header = () => ((0, jsx_runtime_1.jsx)("div", { className: "w-full px-6 py-4", children: (0, jsx_runtime_1.jsxs)("div", { className: "flex w-full flex-col items-center space-y-6", children: [(0, jsx_runtime_1.jsxs)("h2", { className: "text-[28px] font-bold", children: ["Buy ", tokenName, " (", tokenSymbol, ")"] }), (0, jsx_runtime_1.jsxs)("div", { className: "flex w-full flex-col items-center space-y-2", children: [(0, jsx_runtime_1.jsxs)("span", { className: "text-[28px] font-bold", children: [ethAmount, " ETH"] }), quote && ((0, jsx_runtime_1.jsxs)("span", { className: "text-lg", children: ["\u2248 ", formatNumberWithCommas(parseFloat(quote).toFixed(4)), " ", tokenSymbol] }))] })] }) }));
148
168
  // Show loading state while fetching token data
149
169
  if (isLoading) {
150
170
  return ((0, jsx_runtime_1.jsx)(react_1.StyleRoot, { children: (0, jsx_runtime_1.jsx)("div", { className: "b3-root b3-modal bg-b3-react-background flex w-full flex-col items-center p-8", children: (0, jsx_runtime_1.jsx)("p", { className: "text-as-primary/70 text-center text-sm", children: "Loading payment information..." }) }) }));
@@ -166,7 +186,7 @@ function AnySpendBondKit({ mode = "modal", recipientAddress, contractAddress, mi
166
186
  opacity: hasMounted ? 1 : 0,
167
187
  y: hasMounted ? 0 : 20,
168
188
  filter: hasMounted ? "blur(0px)" : "blur(10px)",
169
- }, transition: { duration: 0.3, delay: 0.2, ease: "easeInOut" }, className: "bg-b3-react-background w-full p-6", children: (0, jsx_runtime_1.jsxs)("div", { className: "space-y-4", children: [(0, jsx_runtime_1.jsx)("div", { className: "flex items-center justify-between", children: (0, jsx_runtime_1.jsx)("p", { className: "text-as-primary/70 text-sm font-medium", children: "Amount in ETH" }) }), (0, jsx_runtime_1.jsx)("div", { className: "relative", children: (0, jsx_runtime_1.jsx)(react_1.Input, { type: "text", inputMode: "decimal", placeholder: "0.1", value: ethAmount, onChange: e => validateAndSetAmount(e.target.value), className: `h-14 px-4 text-lg ${!isAmountValid && ethAmount ? "border-as-red" : "border-b3-react-border"}` }) }), !isAmountValid && ethAmount && (0, jsx_runtime_1.jsx)("p", { className: "text-as-red text-sm", children: validationError }), (0, jsx_runtime_1.jsxs)("div", { className: "bg-as-on-surface-2/30 rounded-lg border border-white/10 p-4 backdrop-blur-sm", children: [(0, jsx_runtime_1.jsxs)("div", { className: "flex items-center justify-between", children: [(0, jsx_runtime_1.jsx)("span", { className: "text-as-primary/70 text-sm font-medium", children: "Total Cost:" }), (0, jsx_runtime_1.jsx)("div", { className: "flex items-center gap-2", children: (0, jsx_runtime_1.jsxs)("span", { className: "text-as-primary text-lg font-bold", children: [ethAmount || "0", " ETH"] }) })] }), isLoadingQuote ? ((0, jsx_runtime_1.jsx)("div", { className: "mt-2 text-center", children: (0, jsx_runtime_1.jsx)("span", { className: "text-as-primary/70 text-sm", children: "Calculating tokens..." }) })) : quote ? ((0, jsx_runtime_1.jsxs)("div", { className: "mt-2 flex items-center justify-between", children: [(0, jsx_runtime_1.jsx)("span", { className: "text-as-primary/70 text-sm font-medium", children: "You'll receive:" }), (0, jsx_runtime_1.jsxs)("span", { className: "text-as-primary text-sm font-medium", children: ["\u2248 ", formatNumberWithCommas(parseFloat(quote).toFixed(4)), " ", tokenSymbol] })] })) : null] }), (0, jsx_runtime_1.jsx)(react_1.Button, { onClick: () => {
189
+ }, transition: { duration: 0.3, delay: 0.2, ease: "easeInOut" }, className: "bg-b3-react-background w-full p-6", children: (0, jsx_runtime_1.jsxs)("div", { className: "space-y-4", children: [(0, jsx_runtime_1.jsx)("div", { className: "flex items-center justify-between", children: (0, jsx_runtime_1.jsx)("p", { className: "text-as-primary/70 text-sm font-medium", children: "ETH Amount" }) }), (0, jsx_runtime_1.jsx)("div", { className: "relative", children: (0, jsx_runtime_1.jsx)(react_1.Input, { type: "text", inputMode: "decimal", placeholder: "0.1", value: ethAmount, onChange: e => validateAndSetAmount(e.target.value), className: `h-14 px-4 text-lg ${!isAmountValid && ethAmount ? "border-as-red" : "border-b3-react-border"}` }) }), !isAmountValid && ethAmount && (0, jsx_runtime_1.jsx)("p", { className: "text-as-red text-sm", children: validationError }), (0, jsx_runtime_1.jsxs)("div", { className: "bg-as-on-surface-2/30 rounded-lg border border-white/10 p-4 backdrop-blur-sm", children: [(0, jsx_runtime_1.jsxs)("div", { className: "flex items-center justify-between", children: [(0, jsx_runtime_1.jsx)("span", { className: "text-as-primary/70 text-sm font-medium", children: "Total Cost:" }), (0, jsx_runtime_1.jsx)("div", { className: "flex items-center gap-2", children: (0, jsx_runtime_1.jsxs)("span", { className: "text-as-primary text-lg font-bold", children: [ethAmount || "0", " ETH"] }) })] }), isLoadingQuote ? ((0, jsx_runtime_1.jsx)("div", { className: "mt-2 text-center", children: (0, jsx_runtime_1.jsx)("span", { className: "text-as-primary/70 text-sm", children: "Calculating tokens..." }) })) : quote ? ((0, jsx_runtime_1.jsxs)("div", { className: "mt-2 flex items-center justify-between", children: [(0, jsx_runtime_1.jsx)("span", { className: "text-as-primary/70 text-sm font-medium", children: "You'll receive:" }), (0, jsx_runtime_1.jsxs)("span", { className: "text-as-primary text-sm font-medium", children: ["\u2248 ", formatNumberWithCommas(parseFloat(quote).toFixed(4)), " ", tokenSymbol] })] })) : null] }), (0, jsx_runtime_1.jsx)(react_1.Button, { onClick: () => {
170
190
  if (isAmountValid && ethAmount) {
171
191
  setShowAmountPrompt(false);
172
192
  }
@@ -338,7 +338,7 @@ function AnySpendCustom({ isMainnet = true, loadOrder, mode = "modal", recipient
338
338
  blockExplorers: [{ name: "B3 Explorer", url: "https://explorer.b3.fun/" }],
339
339
  testnet: undefined,
340
340
  },
341
- partnerId: String(process.env.NEXT_PUBLIC_GLOBAL_ACCOUNTS_PARTNER_ID),
341
+ partnerId: String(process.env.NEXT_PUBLIC_THIRDWEB_PARTNER_ID),
342
342
  type: "signInWithB3",
343
343
  showBackButton: false,
344
344
  });
@@ -1,13 +1,28 @@
1
1
  "use strict";
2
- var __importDefault = (this && this.__importDefault) || function (mod) {
3
- return (mod && mod.__esModule) ? mod : { "default": mod };
4
- };
5
2
  Object.defineProperty(exports, "__esModule", { value: true });
6
3
  exports.useAnyspendOrderAndTransactions = useAnyspendOrderAndTransactions;
7
4
  const anyspend_1 = require("../../../anyspend/services/anyspend");
8
5
  const react_query_1 = require("@tanstack/react-query");
9
- const isEqual_js_1 = __importDefault(require("lodash/isEqual.js"));
10
6
  const react_1 = require("react");
7
+ // Custom deep equality function that handles BigInt
8
+ function customDeepEqual(oldData, newData) {
9
+ // Handle BigInt comparison
10
+ if (typeof oldData === "bigint" && typeof newData === "bigint") {
11
+ return oldData === newData;
12
+ }
13
+ // Handle arrays
14
+ if (Array.isArray(oldData) && Array.isArray(newData)) {
15
+ return oldData.length === newData.length && oldData.every((item, index) => customDeepEqual(item, newData[index]));
16
+ }
17
+ // Handle objects
18
+ if (oldData && newData && typeof oldData === "object" && typeof newData === "object") {
19
+ const keys1 = Object.keys(oldData);
20
+ const keys2 = Object.keys(newData);
21
+ return keys1.length === keys2.length && keys1.every(key => customDeepEqual(oldData[key], newData[key]));
22
+ }
23
+ // Handle primitive values
24
+ return oldData === newData;
25
+ }
11
26
  // Hook to fetch and auto-refresh order status and transaction details
12
27
  function useAnyspendOrderAndTransactions(isMainnet, orderId) {
13
28
  const selectFn = (0, react_1.useCallback)((data) => {
@@ -18,12 +33,12 @@ function useAnyspendOrderAndTransactions(isMainnet, orderId) {
18
33
  const { data, isLoading, refetch, error } = (0, react_query_1.useQuery)({
19
34
  queryKey: ["getAnyspendOrderAndTransactions", orderId],
20
35
  queryFn: () => anyspend_1.anyspendService.getOrderAndTransactions(isMainnet, orderId),
21
- enabled: Boolean(orderId),
36
+ enabled: !!orderId,
22
37
  refetchInterval: 3000,
23
38
  staleTime: 1000,
24
39
  select: selectFn,
25
40
  structuralSharing: (oldData, newData) => {
26
- if ((0, isEqual_js_1.default)(oldData, newData))
41
+ if (customDeepEqual(oldData, newData))
27
42
  return oldData;
28
43
  return newData;
29
44
  },
@@ -18,7 +18,7 @@ function SignIn(props) {
18
18
  const { automaticallySetFirstEoa } = (0, react_1.useB3)();
19
19
  const { wallet, address: globalAddress, ensName, connectedSmartWallet, connectedEOAWallet, isActiveSmartWallet, isActiveEOAWallet, smartWalletIcon, eoaWalletIcon, } = (0, react_1.useAccountWallet)();
20
20
  const isMobile = (0, react_1.useIsMobile)();
21
- const { logout } = (0, react_1.useAuthentication)(String(process.env.NEXT_PUBLIC_GLOBAL_ACCOUNTS_PARTNER_ID));
21
+ const { logout } = (0, react_1.useAuthentication)(String(process.env.NEXT_PUBLIC_THIRDWEB_PARTNER_ID));
22
22
  const onDisconnect = async () => {
23
23
  await logout();
24
24
  };
@@ -1,4 +1,4 @@
1
- import { ReactNode } from "react";
1
+ import React, { ReactNode } from "react";
2
2
  interface TabsRootProps {
3
3
  value: string;
4
4
  onValueChange: (value: string) => void;
@@ -18,7 +18,7 @@ interface TabTriggerProps {
18
18
  icon?: ReactNode;
19
19
  disabled?: boolean;
20
20
  }
21
- export declare function TabTrigger({ value, children, icon, disabled }: TabTriggerProps): import("react/jsx-runtime").JSX.Element;
21
+ export declare const TabTrigger: React.ForwardRefExoticComponent<TabTriggerProps & React.RefAttributes<HTMLButtonElement>>;
22
22
  interface TabsContentProps {
23
23
  value: string;
24
24
  children: ReactNode;
@@ -34,14 +34,14 @@ var __importStar = (this && this.__importStar) || (function () {
34
34
  };
35
35
  })();
36
36
  Object.defineProperty(exports, "__esModule", { value: true });
37
+ exports.TabTrigger = void 0;
37
38
  exports.Tabs = Tabs;
38
39
  exports.TabsList = TabsList;
39
- exports.TabTrigger = TabTrigger;
40
40
  exports.TabsContent = TabsContent;
41
41
  exports.TabsTransitionWrapper = TabsTransitionWrapper;
42
42
  const jsx_runtime_1 = require("react/jsx-runtime");
43
- const cn_1 = require("../../../../shared/utils/cn");
44
43
  const react_1 = require("../../../../global-account/react");
44
+ const cn_1 = require("../../../../shared/utils/cn");
45
45
  const framer_motion_1 = require("framer-motion");
46
46
  const react_2 = __importStar(require("react"));
47
47
  const TabsContext = (0, react_2.createContext)(undefined);
@@ -51,14 +51,14 @@ function Tabs({ value, onValueChange, children, className = "" }) {
51
51
  function TabsList({ children, className = "", hideGradient = false }) {
52
52
  return ((0, jsx_runtime_1.jsxs)("div", { className: "relative w-full", children: [(0, jsx_runtime_1.jsx)("div", { role: "tablist", className: (0, cn_1.cn)("no-scrollbar relative mb-4 flex items-center gap-2 whitespace-nowrap", className), children: children }), (0, jsx_runtime_1.jsx)(framer_motion_1.AnimatePresence, { mode: "wait", children: !hideGradient && ((0, jsx_runtime_1.jsxs)(framer_motion_1.motion.div, { initial: { opacity: 0 }, animate: { opacity: 1 }, exit: { opacity: 0 }, transition: { duration: 0.2, delay: 0.2 }, children: [(0, jsx_runtime_1.jsx)("div", { className: "pointer-events-none absolute bottom-0 left-0 top-0 z-10 w-8 bg-gradient-to-r from-[#15121c] to-transparent md:hidden" }), (0, jsx_runtime_1.jsx)("div", { className: "pointer-events-none absolute bottom-0 right-0 top-0 z-10 w-8 bg-gradient-to-l from-[#15121c] to-transparent md:hidden" })] }, "gradients-container")) })] }));
53
53
  }
54
- function TabTrigger({ value, children, icon, disabled = false }) {
54
+ exports.TabTrigger = react_2.default.forwardRef(({ value, children, icon, disabled = false }, ref) => {
55
55
  const context = (0, react_2.useContext)(TabsContext);
56
56
  if (!context)
57
57
  throw new Error("TabTrigger must be used within Tabs");
58
58
  const { selectedTab, onTabChange } = context;
59
59
  const isSelected = selectedTab === value;
60
- return ((0, jsx_runtime_1.jsxs)("button", { role: "tab", "aria-selected": isSelected, "aria-controls": `panel-${value}`, id: `tab-${value}`, onClick: () => onTabChange(value), className: `relative rounded-full px-4 py-2 text-sm text-white transition-all duration-200 hover:text-white focus:outline-none`, disabled: disabled, children: [(0, jsx_runtime_1.jsxs)("span", { className: `${isSelected ? "opacity-100" : "opacity-50"} relative z-10 flex items-center gap-2 font-semibold uppercase`, children: [children, icon] }), isSelected && ((0, jsx_runtime_1.jsx)(framer_motion_1.motion.span, { layoutId: "activeTab", transition: { type: "spring", duration: 0.4 }, className: "from-as-light-brand to-as-brand/10 border-as-brand/30 absolute inset-0 z-0 rounded-full border border-t-white/15 bg-gradient-to-b shadow-lg" }))] }));
61
- }
60
+ return ((0, jsx_runtime_1.jsxs)("button", { ref: ref, role: "tab", "aria-selected": isSelected, "aria-controls": `panel-${value}`, id: `tab-${value}`, onClick: () => onTabChange(value), className: `relative rounded-full px-4 py-2 text-sm text-white transition-all duration-200 hover:text-white focus:outline-none`, disabled: disabled, children: [(0, jsx_runtime_1.jsxs)("span", { className: `${isSelected ? "opacity-100" : "opacity-50"} relative z-10 flex items-center gap-2 font-semibold uppercase`, children: [children, icon] }), isSelected && ((0, jsx_runtime_1.jsx)(framer_motion_1.motion.span, { layoutId: "activeTab", transition: { type: "spring", duration: 0.4 }, className: "from-as-light-brand to-as-brand/10 border-as-brand/30 absolute inset-0 z-0 rounded-full border border-t-white/15 bg-gradient-to-b shadow-lg" }))] }));
61
+ });
62
62
  function TabsContent({ value, children }) {
63
63
  const context = (0, react_2.useContext)(TabsContext);
64
64
  if (!context)
@@ -126,8 +126,10 @@ export function AnySpendBondKit({ mode = "modal", recipientAddress, contractAddr
126
126
  setQuote(null);
127
127
  return;
128
128
  }
129
- // Only allow numbers and one decimal point
130
- if (!/^\d*\.?\d*$/.test(value)) {
129
+ // Only allow valid number format (no leading zeros unless decimal)
130
+ if (!/^(0|[1-9]\d*)?\.?\d*$/.test(value)) {
131
+ setIsAmountValid(false);
132
+ setValidationError("Please enter a valid number");
131
133
  return;
132
134
  }
133
135
  // Prevent multiple decimal points
@@ -139,9 +141,27 @@ export function AnySpendBondKit({ mode = "modal", recipientAddress, contractAddr
139
141
  if (parts[1] && parts[1].length > 18) {
140
142
  return;
141
143
  }
142
- setEthAmount(value);
144
+ // Clean the input - remove leading zeros if not decimal
145
+ const cleanedValue = value.startsWith("0") && !value.startsWith("0.") ? value.replace(/^0+/, "0") : value;
146
+ setEthAmount(cleanedValue);
147
+ try {
148
+ const parsedAmount = parseEther(cleanedValue);
149
+ if (parsedAmount <= BigInt(0)) {
150
+ setIsAmountValid(false);
151
+ setValidationError("Amount must be greater than 0");
152
+ return;
153
+ }
154
+ setIsAmountValid(true);
155
+ setValidationError("");
156
+ debouncedGetQuote(cleanedValue);
157
+ }
158
+ catch (error) {
159
+ console.error("Error validating amount:", error);
160
+ setIsAmountValid(false);
161
+ setValidationError("Please enter a valid amount");
162
+ }
143
163
  };
144
- const header = () => (_jsx("div", { className: "w-full px-6 py-4", children: _jsxs("div", { className: "flex w-full flex-col items-center space-y-6", children: [_jsxs("h2", { className: "text-[28px] font-bold", children: [tokenName, " (", tokenSymbol, ")"] }), _jsxs("div", { className: "flex w-full flex-col items-center space-y-2", children: [_jsxs("span", { className: "text-[28px] font-bold", children: [ethAmount, " ETH"] }), quote && (_jsxs("span", { className: "text-lg", children: ["\u2248 ", formatNumberWithCommas(parseFloat(quote).toFixed(4)), " ", tokenSymbol] }))] })] }) }));
164
+ const header = () => (_jsx("div", { className: "w-full px-6 py-4", children: _jsxs("div", { className: "flex w-full flex-col items-center space-y-6", children: [_jsxs("h2", { className: "text-[28px] font-bold", children: ["Buy ", tokenName, " (", tokenSymbol, ")"] }), _jsxs("div", { className: "flex w-full flex-col items-center space-y-2", children: [_jsxs("span", { className: "text-[28px] font-bold", children: [ethAmount, " ETH"] }), quote && (_jsxs("span", { className: "text-lg", children: ["\u2248 ", formatNumberWithCommas(parseFloat(quote).toFixed(4)), " ", tokenSymbol] }))] })] }) }));
145
165
  // Show loading state while fetching token data
146
166
  if (isLoading) {
147
167
  return (_jsx(StyleRoot, { children: _jsx("div", { className: "b3-root b3-modal bg-b3-react-background flex w-full flex-col items-center p-8", children: _jsx("p", { className: "text-as-primary/70 text-center text-sm", children: "Loading payment information..." }) }) }));
@@ -163,7 +183,7 @@ export function AnySpendBondKit({ mode = "modal", recipientAddress, contractAddr
163
183
  opacity: hasMounted ? 1 : 0,
164
184
  y: hasMounted ? 0 : 20,
165
185
  filter: hasMounted ? "blur(0px)" : "blur(10px)",
166
- }, transition: { duration: 0.3, delay: 0.2, ease: "easeInOut" }, className: "bg-b3-react-background w-full p-6", children: _jsxs("div", { className: "space-y-4", children: [_jsx("div", { className: "flex items-center justify-between", children: _jsx("p", { className: "text-as-primary/70 text-sm font-medium", children: "Amount in ETH" }) }), _jsx("div", { className: "relative", children: _jsx(Input, { type: "text", inputMode: "decimal", placeholder: "0.1", value: ethAmount, onChange: e => validateAndSetAmount(e.target.value), className: `h-14 px-4 text-lg ${!isAmountValid && ethAmount ? "border-as-red" : "border-b3-react-border"}` }) }), !isAmountValid && ethAmount && _jsx("p", { className: "text-as-red text-sm", children: validationError }), _jsxs("div", { className: "bg-as-on-surface-2/30 rounded-lg border border-white/10 p-4 backdrop-blur-sm", children: [_jsxs("div", { className: "flex items-center justify-between", children: [_jsx("span", { className: "text-as-primary/70 text-sm font-medium", children: "Total Cost:" }), _jsx("div", { className: "flex items-center gap-2", children: _jsxs("span", { className: "text-as-primary text-lg font-bold", children: [ethAmount || "0", " ETH"] }) })] }), isLoadingQuote ? (_jsx("div", { className: "mt-2 text-center", children: _jsx("span", { className: "text-as-primary/70 text-sm", children: "Calculating tokens..." }) })) : quote ? (_jsxs("div", { className: "mt-2 flex items-center justify-between", children: [_jsx("span", { className: "text-as-primary/70 text-sm font-medium", children: "You'll receive:" }), _jsxs("span", { className: "text-as-primary text-sm font-medium", children: ["\u2248 ", formatNumberWithCommas(parseFloat(quote).toFixed(4)), " ", tokenSymbol] })] })) : null] }), _jsx(Button, { onClick: () => {
186
+ }, transition: { duration: 0.3, delay: 0.2, ease: "easeInOut" }, className: "bg-b3-react-background w-full p-6", children: _jsxs("div", { className: "space-y-4", children: [_jsx("div", { className: "flex items-center justify-between", children: _jsx("p", { className: "text-as-primary/70 text-sm font-medium", children: "ETH Amount" }) }), _jsx("div", { className: "relative", children: _jsx(Input, { type: "text", inputMode: "decimal", placeholder: "0.1", value: ethAmount, onChange: e => validateAndSetAmount(e.target.value), className: `h-14 px-4 text-lg ${!isAmountValid && ethAmount ? "border-as-red" : "border-b3-react-border"}` }) }), !isAmountValid && ethAmount && _jsx("p", { className: "text-as-red text-sm", children: validationError }), _jsxs("div", { className: "bg-as-on-surface-2/30 rounded-lg border border-white/10 p-4 backdrop-blur-sm", children: [_jsxs("div", { className: "flex items-center justify-between", children: [_jsx("span", { className: "text-as-primary/70 text-sm font-medium", children: "Total Cost:" }), _jsx("div", { className: "flex items-center gap-2", children: _jsxs("span", { className: "text-as-primary text-lg font-bold", children: [ethAmount || "0", " ETH"] }) })] }), isLoadingQuote ? (_jsx("div", { className: "mt-2 text-center", children: _jsx("span", { className: "text-as-primary/70 text-sm", children: "Calculating tokens..." }) })) : quote ? (_jsxs("div", { className: "mt-2 flex items-center justify-between", children: [_jsx("span", { className: "text-as-primary/70 text-sm font-medium", children: "You'll receive:" }), _jsxs("span", { className: "text-as-primary text-sm font-medium", children: ["\u2248 ", formatNumberWithCommas(parseFloat(quote).toFixed(4)), " ", tokenSymbol] })] })) : null] }), _jsx(Button, { onClick: () => {
167
187
  if (isAmountValid && ethAmount) {
168
188
  setShowAmountPrompt(false);
169
189
  }
@@ -332,7 +332,7 @@ export function AnySpendCustom({ isMainnet = true, loadOrder, mode = "modal", re
332
332
  blockExplorers: [{ name: "B3 Explorer", url: "https://explorer.b3.fun/" }],
333
333
  testnet: undefined,
334
334
  },
335
- partnerId: String(process.env.NEXT_PUBLIC_GLOBAL_ACCOUNTS_PARTNER_ID),
335
+ partnerId: String(process.env.NEXT_PUBLIC_THIRDWEB_PARTNER_ID),
336
336
  type: "signInWithB3",
337
337
  showBackButton: false,
338
338
  });
@@ -1,7 +1,25 @@
1
1
  import { anyspendService } from "../../../anyspend/services/anyspend.js";
2
2
  import { useQuery } from "@tanstack/react-query";
3
- import isEqual from "lodash/isEqual.js";
4
3
  import { useCallback, useMemo } from "react";
4
+ // Custom deep equality function that handles BigInt
5
+ function customDeepEqual(oldData, newData) {
6
+ // Handle BigInt comparison
7
+ if (typeof oldData === "bigint" && typeof newData === "bigint") {
8
+ return oldData === newData;
9
+ }
10
+ // Handle arrays
11
+ if (Array.isArray(oldData) && Array.isArray(newData)) {
12
+ return oldData.length === newData.length && oldData.every((item, index) => customDeepEqual(item, newData[index]));
13
+ }
14
+ // Handle objects
15
+ if (oldData && newData && typeof oldData === "object" && typeof newData === "object") {
16
+ const keys1 = Object.keys(oldData);
17
+ const keys2 = Object.keys(newData);
18
+ return keys1.length === keys2.length && keys1.every(key => customDeepEqual(oldData[key], newData[key]));
19
+ }
20
+ // Handle primitive values
21
+ return oldData === newData;
22
+ }
5
23
  // Hook to fetch and auto-refresh order status and transaction details
6
24
  export function useAnyspendOrderAndTransactions(isMainnet, orderId) {
7
25
  const selectFn = useCallback((data) => {
@@ -12,12 +30,12 @@ export function useAnyspendOrderAndTransactions(isMainnet, orderId) {
12
30
  const { data, isLoading, refetch, error } = useQuery({
13
31
  queryKey: ["getAnyspendOrderAndTransactions", orderId],
14
32
  queryFn: () => anyspendService.getOrderAndTransactions(isMainnet, orderId),
15
- enabled: Boolean(orderId),
33
+ enabled: !!orderId,
16
34
  refetchInterval: 3000,
17
35
  staleTime: 1000,
18
36
  select: selectFn,
19
37
  structuralSharing: (oldData, newData) => {
20
- if (isEqual(oldData, newData))
38
+ if (customDeepEqual(oldData, newData))
21
39
  return oldData;
22
40
  return newData;
23
41
  },
@@ -12,7 +12,7 @@ export function SignIn(props) {
12
12
  const { automaticallySetFirstEoa } = useB3();
13
13
  const { wallet, address: globalAddress, ensName, connectedSmartWallet, connectedEOAWallet, isActiveSmartWallet, isActiveEOAWallet, smartWalletIcon, eoaWalletIcon, } = useAccountWallet();
14
14
  const isMobile = useIsMobile();
15
- const { logout } = useAuthentication(String(process.env.NEXT_PUBLIC_GLOBAL_ACCOUNTS_PARTNER_ID));
15
+ const { logout } = useAuthentication(String(process.env.NEXT_PUBLIC_THIRDWEB_PARTNER_ID));
16
16
  const onDisconnect = async () => {
17
17
  await logout();
18
18
  };
@@ -1,4 +1,4 @@
1
- import { ReactNode } from "react";
1
+ import React, { ReactNode } from "react";
2
2
  interface TabsRootProps {
3
3
  value: string;
4
4
  onValueChange: (value: string) => void;
@@ -18,7 +18,7 @@ interface TabTriggerProps {
18
18
  icon?: ReactNode;
19
19
  disabled?: boolean;
20
20
  }
21
- export declare function TabTrigger({ value, children, icon, disabled }: TabTriggerProps): import("react/jsx-runtime").JSX.Element;
21
+ export declare const TabTrigger: React.ForwardRefExoticComponent<TabTriggerProps & React.RefAttributes<HTMLButtonElement>>;
22
22
  interface TabsContentProps {
23
23
  value: string;
24
24
  children: ReactNode;
@@ -1,7 +1,7 @@
1
1
  "use client";
2
2
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
- import { cn } from "../../../../shared/utils/cn.js";
4
3
  import { TransitionPanel } from "../../../../global-account/react/index.js";
4
+ import { cn } from "../../../../shared/utils/cn.js";
5
5
  import { AnimatePresence, motion } from "framer-motion";
6
6
  import React, { createContext, useContext } from "react";
7
7
  const TabsContext = createContext(undefined);
@@ -11,14 +11,14 @@ export function Tabs({ value, onValueChange, children, className = "" }) {
11
11
  export function TabsList({ children, className = "", hideGradient = false }) {
12
12
  return (_jsxs("div", { className: "relative w-full", children: [_jsx("div", { role: "tablist", className: cn("no-scrollbar relative mb-4 flex items-center gap-2 whitespace-nowrap", className), children: children }), _jsx(AnimatePresence, { mode: "wait", children: !hideGradient && (_jsxs(motion.div, { initial: { opacity: 0 }, animate: { opacity: 1 }, exit: { opacity: 0 }, transition: { duration: 0.2, delay: 0.2 }, children: [_jsx("div", { className: "pointer-events-none absolute bottom-0 left-0 top-0 z-10 w-8 bg-gradient-to-r from-[#15121c] to-transparent md:hidden" }), _jsx("div", { className: "pointer-events-none absolute bottom-0 right-0 top-0 z-10 w-8 bg-gradient-to-l from-[#15121c] to-transparent md:hidden" })] }, "gradients-container")) })] }));
13
13
  }
14
- export function TabTrigger({ value, children, icon, disabled = false }) {
14
+ export const TabTrigger = React.forwardRef(({ value, children, icon, disabled = false }, ref) => {
15
15
  const context = useContext(TabsContext);
16
16
  if (!context)
17
17
  throw new Error("TabTrigger must be used within Tabs");
18
18
  const { selectedTab, onTabChange } = context;
19
19
  const isSelected = selectedTab === value;
20
- return (_jsxs("button", { role: "tab", "aria-selected": isSelected, "aria-controls": `panel-${value}`, id: `tab-${value}`, onClick: () => onTabChange(value), className: `relative rounded-full px-4 py-2 text-sm text-white transition-all duration-200 hover:text-white focus:outline-none`, disabled: disabled, children: [_jsxs("span", { className: `${isSelected ? "opacity-100" : "opacity-50"} relative z-10 flex items-center gap-2 font-semibold uppercase`, children: [children, icon] }), isSelected && (_jsx(motion.span, { layoutId: "activeTab", transition: { type: "spring", duration: 0.4 }, className: "from-as-light-brand to-as-brand/10 border-as-brand/30 absolute inset-0 z-0 rounded-full border border-t-white/15 bg-gradient-to-b shadow-lg" }))] }));
21
- }
20
+ return (_jsxs("button", { ref: ref, role: "tab", "aria-selected": isSelected, "aria-controls": `panel-${value}`, id: `tab-${value}`, onClick: () => onTabChange(value), className: `relative rounded-full px-4 py-2 text-sm text-white transition-all duration-200 hover:text-white focus:outline-none`, disabled: disabled, children: [_jsxs("span", { className: `${isSelected ? "opacity-100" : "opacity-50"} relative z-10 flex items-center gap-2 font-semibold uppercase`, children: [children, icon] }), isSelected && (_jsx(motion.span, { layoutId: "activeTab", transition: { type: "spring", duration: 0.4 }, className: "from-as-light-brand to-as-brand/10 border-as-brand/30 absolute inset-0 z-0 rounded-full border border-t-white/15 bg-gradient-to-b shadow-lg" }))] }));
21
+ });
22
22
  export function TabsContent({ value, children }) {
23
23
  const context = useContext(TabsContext);
24
24
  if (!context)
@@ -1,4 +1,4 @@
1
- import { ReactNode } from "react";
1
+ import React, { ReactNode } from "react";
2
2
  interface TabsRootProps {
3
3
  value: string;
4
4
  onValueChange: (value: string) => void;
@@ -18,7 +18,7 @@ interface TabTriggerProps {
18
18
  icon?: ReactNode;
19
19
  disabled?: boolean;
20
20
  }
21
- export declare function TabTrigger({ value, children, icon, disabled }: TabTriggerProps): import("react/jsx-runtime").JSX.Element;
21
+ export declare const TabTrigger: React.ForwardRefExoticComponent<TabTriggerProps & React.RefAttributes<HTMLButtonElement>>;
22
22
  interface TabsContentProps {
23
23
  value: string;
24
24
  children: ReactNode;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@b3dotfun/sdk",
3
- "version": "0.0.8-alpha.1",
3
+ "version": "0.0.8-alpha.2",
4
4
  "source": "src/index.ts",
5
5
  "main": "./dist/cjs/index.js",
6
6
  "react-native": "./dist/cjs/index.native.js",
@@ -155,8 +155,10 @@ export function AnySpendBondKit({
155
155
  return;
156
156
  }
157
157
 
158
- // Only allow numbers and one decimal point
159
- if (!/^\d*\.?\d*$/.test(value)) {
158
+ // Only allow valid number format (no leading zeros unless decimal)
159
+ if (!/^(0|[1-9]\d*)?\.?\d*$/.test(value)) {
160
+ setIsAmountValid(false);
161
+ setValidationError("Please enter a valid number");
160
162
  return;
161
163
  }
162
164
 
@@ -171,14 +173,33 @@ export function AnySpendBondKit({
171
173
  return;
172
174
  }
173
175
 
174
- setEthAmount(value);
176
+ // Clean the input - remove leading zeros if not decimal
177
+ const cleanedValue = value.startsWith("0") && !value.startsWith("0.") ? value.replace(/^0+/, "0") : value;
178
+ setEthAmount(cleanedValue);
179
+
180
+ try {
181
+ const parsedAmount = parseEther(cleanedValue);
182
+ if (parsedAmount <= BigInt(0)) {
183
+ setIsAmountValid(false);
184
+ setValidationError("Amount must be greater than 0");
185
+ return;
186
+ }
187
+
188
+ setIsAmountValid(true);
189
+ setValidationError("");
190
+ debouncedGetQuote(cleanedValue);
191
+ } catch (error) {
192
+ console.error("Error validating amount:", error);
193
+ setIsAmountValid(false);
194
+ setValidationError("Please enter a valid amount");
195
+ }
175
196
  };
176
197
 
177
198
  const header = () => (
178
199
  <div className="w-full px-6 py-4">
179
200
  <div className="flex w-full flex-col items-center space-y-6">
180
201
  <h2 className="text-[28px] font-bold">
181
- {tokenName} ({tokenSymbol})
202
+ Buy {tokenName} ({tokenSymbol})
182
203
  </h2>
183
204
  <div className="flex w-full flex-col items-center space-y-2">
184
205
  <span className="text-[28px] font-bold">{ethAmount} ETH</span>
@@ -267,7 +288,7 @@ export function AnySpendBondKit({
267
288
  >
268
289
  <div className="space-y-4">
269
290
  <div className="flex items-center justify-between">
270
- <p className="text-as-primary/70 text-sm font-medium">Amount in ETH</p>
291
+ <p className="text-as-primary/70 text-sm font-medium">ETH Amount</p>
271
292
  </div>
272
293
 
273
294
  <div className="relative">
@@ -488,7 +488,7 @@ export function AnySpendCustom({
488
488
  blockExplorers: [{ name: "B3 Explorer", url: "https://explorer.b3.fun/" }],
489
489
  testnet: undefined,
490
490
  },
491
- partnerId: String(process.env.NEXT_PUBLIC_GLOBAL_ACCOUNTS_PARTNER_ID),
491
+ partnerId: String(process.env.NEXT_PUBLIC_THIRDWEB_PARTNER_ID),
492
492
  type: "signInWithB3",
493
493
  showBackButton: false,
494
494
  });
@@ -1,9 +1,31 @@
1
1
  import { anyspendService } from "@b3dotfun/sdk/anyspend/services/anyspend";
2
2
  import { GetOrderAndTxsResponse } from "@b3dotfun/sdk/anyspend/types";
3
3
  import { useQuery } from "@tanstack/react-query";
4
- import isEqual from "lodash/isEqual.js";
5
4
  import { useCallback, useMemo } from "react";
6
5
 
6
+ // Custom deep equality function that handles BigInt
7
+ function customDeepEqual(oldData: any, newData: any): boolean {
8
+ // Handle BigInt comparison
9
+ if (typeof oldData === "bigint" && typeof newData === "bigint") {
10
+ return oldData === newData;
11
+ }
12
+
13
+ // Handle arrays
14
+ if (Array.isArray(oldData) && Array.isArray(newData)) {
15
+ return oldData.length === newData.length && oldData.every((item, index) => customDeepEqual(item, newData[index]));
16
+ }
17
+
18
+ // Handle objects
19
+ if (oldData && newData && typeof oldData === "object" && typeof newData === "object") {
20
+ const keys1 = Object.keys(oldData);
21
+ const keys2 = Object.keys(newData);
22
+ return keys1.length === keys2.length && keys1.every(key => customDeepEqual(oldData[key], newData[key]));
23
+ }
24
+
25
+ // Handle primitive values
26
+ return oldData === newData;
27
+ }
28
+
7
29
  // Hook to fetch and auto-refresh order status and transaction details
8
30
  export function useAnyspendOrderAndTransactions(isMainnet: boolean, orderId: string | undefined) {
9
31
  const selectFn = useCallback((data: any) => {
@@ -13,13 +35,13 @@ export function useAnyspendOrderAndTransactions(isMainnet: boolean, orderId: str
13
35
 
14
36
  const { data, isLoading, refetch, error } = useQuery<GetOrderAndTxsResponse>({
15
37
  queryKey: ["getAnyspendOrderAndTransactions", orderId],
16
- queryFn: () => anyspendService.getOrderAndTransactions(isMainnet, orderId),
17
- enabled: Boolean(orderId),
38
+ queryFn: () => anyspendService.getOrderAndTransactions(isMainnet, orderId!),
39
+ enabled: !!orderId,
18
40
  refetchInterval: 3000,
19
41
  staleTime: 1000,
20
42
  select: selectFn,
21
43
  structuralSharing: (oldData, newData) => {
22
- if (isEqual(oldData, newData)) return oldData;
44
+ if (customDeepEqual(oldData, newData)) return oldData;
23
45
  return newData;
24
46
  },
25
47
  });
@@ -43,7 +43,7 @@ export function SignIn(props: SignInWithB3Props) {
43
43
  } = useAccountWallet();
44
44
 
45
45
  const isMobile = useIsMobile();
46
- const { logout } = useAuthentication(String(process.env.NEXT_PUBLIC_GLOBAL_ACCOUNTS_PARTNER_ID));
46
+ const { logout } = useAuthentication(String(process.env.NEXT_PUBLIC_THIRDWEB_PARTNER_ID));
47
47
  const onDisconnect = async () => {
48
48
  await logout();
49
49
  };
@@ -1,7 +1,7 @@
1
1
  "use client";
2
2
 
3
- import { cn } from "@b3dotfun/sdk/shared/utils/cn";
4
3
  import { TransitionPanel } from "@b3dotfun/sdk/global-account/react";
4
+ import { cn } from "@b3dotfun/sdk/shared/utils/cn";
5
5
  import { AnimatePresence, motion } from "framer-motion";
6
6
  import React, { ReactNode, createContext, useContext } from "react";
7
7
 
@@ -67,39 +67,42 @@ interface TabTriggerProps {
67
67
  disabled?: boolean;
68
68
  }
69
69
 
70
- export function TabTrigger({ value, children, icon, disabled = false }: TabTriggerProps) {
71
- const context = useContext(TabsContext);
72
- if (!context) throw new Error("TabTrigger must be used within Tabs");
73
-
74
- const { selectedTab, onTabChange } = context;
75
- const isSelected = selectedTab === value;
76
-
77
- return (
78
- <button
79
- role="tab"
80
- aria-selected={isSelected}
81
- aria-controls={`panel-${value}`}
82
- id={`tab-${value}`}
83
- onClick={() => onTabChange(value)}
84
- className={`relative rounded-full px-4 py-2 text-sm text-white transition-all duration-200 hover:text-white focus:outline-none`}
85
- disabled={disabled}
86
- >
87
- <span
88
- className={`${isSelected ? "opacity-100" : "opacity-50"} relative z-10 flex items-center gap-2 font-semibold uppercase`}
70
+ export const TabTrigger = React.forwardRef<HTMLButtonElement, TabTriggerProps>(
71
+ ({ value, children, icon, disabled = false }, ref) => {
72
+ const context = useContext(TabsContext);
73
+ if (!context) throw new Error("TabTrigger must be used within Tabs");
74
+
75
+ const { selectedTab, onTabChange } = context;
76
+ const isSelected = selectedTab === value;
77
+
78
+ return (
79
+ <button
80
+ ref={ref}
81
+ role="tab"
82
+ aria-selected={isSelected}
83
+ aria-controls={`panel-${value}`}
84
+ id={`tab-${value}`}
85
+ onClick={() => onTabChange(value)}
86
+ className={`relative rounded-full px-4 py-2 text-sm text-white transition-all duration-200 hover:text-white focus:outline-none`}
87
+ disabled={disabled}
89
88
  >
90
- {children}
91
- {icon}
92
- </span>
93
- {isSelected && (
94
- <motion.span
95
- layoutId="activeTab"
96
- transition={{ type: "spring", duration: 0.4 }}
97
- className="from-as-light-brand to-as-brand/10 border-as-brand/30 absolute inset-0 z-0 rounded-full border border-t-white/15 bg-gradient-to-b shadow-lg"
98
- />
99
- )}
100
- </button>
101
- );
102
- }
89
+ <span
90
+ className={`${isSelected ? "opacity-100" : "opacity-50"} relative z-10 flex items-center gap-2 font-semibold uppercase`}
91
+ >
92
+ {children}
93
+ {icon}
94
+ </span>
95
+ {isSelected && (
96
+ <motion.span
97
+ layoutId="activeTab"
98
+ transition={{ type: "spring", duration: 0.4 }}
99
+ className="from-as-light-brand to-as-brand/10 border-as-brand/30 absolute inset-0 z-0 rounded-full border border-t-white/15 bg-gradient-to-b shadow-lg"
100
+ />
101
+ )}
102
+ </button>
103
+ );
104
+ },
105
+ );
103
106
 
104
107
  interface TabsContentProps {
105
108
  value: string;