@b3dotfun/sdk 0.0.1-alpha.2 → 0.0.1-alpha.21

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 (115) hide show
  1. package/README.md +328 -230
  2. package/dist/cjs/anyspend/index.native.d.ts +13 -0
  3. package/dist/cjs/anyspend/index.native.js +35 -0
  4. package/dist/cjs/anyspend/react/components/AnySpend.d.ts +2 -1
  5. package/dist/cjs/anyspend/react/components/AnySpend.js +4 -4
  6. package/dist/cjs/anyspend/react/components/AnySpendBuySpin.d.ts +2 -1
  7. package/dist/cjs/anyspend/react/components/AnySpendBuySpin.js +123 -50
  8. package/dist/cjs/anyspend/react/components/common/OrderHistoryItem.js +5 -1
  9. package/dist/cjs/anyspend/react/components/common/TokenBalance.js +1 -1
  10. package/dist/cjs/anyspend/utils/chain.js +3 -0
  11. package/dist/cjs/global-account/react/components/B3DynamicModal.js +2 -2
  12. package/dist/cjs/global-account/react/components/{B3Provider.d.ts → B3Provider/B3Provider.d.ts} +3 -29
  13. package/dist/cjs/global-account/react/components/{B3Provider.js → B3Provider/B3Provider.js} +6 -34
  14. package/dist/cjs/global-account/react/components/{B3Provider.native.d.ts → B3Provider/B3Provider.native.d.ts} +2 -25
  15. package/dist/cjs/global-account/react/components/{B3Provider.native.js → B3Provider/B3Provider.native.js} +5 -28
  16. package/dist/cjs/global-account/react/components/B3Provider/types.d.ts +25 -0
  17. package/dist/cjs/global-account/react/components/B3Provider/types.js +20 -0
  18. package/dist/cjs/global-account/react/components/B3Provider/useB3.d.ts +5 -0
  19. package/dist/cjs/global-account/react/components/B3Provider/useB3.js +17 -0
  20. package/dist/cjs/global-account/react/components/StyleRoot.js +2 -2
  21. package/dist/cjs/global-account/react/components/index.d.ts +8 -6
  22. package/dist/cjs/global-account/react/components/index.js +18 -16
  23. package/dist/cjs/global-account/react/hooks/index.d.ts +1 -1
  24. package/dist/cjs/global-account/react/hooks/index.js +2 -1
  25. package/dist/cjs/global-account/react/hooks/useBestTransactionPath.js +3 -3
  26. package/dist/cjs/global-account/react/hooks/useTokenBalance.js +1 -1
  27. package/dist/cjs/global-account/react/index.native.d.ts +7 -0
  28. package/dist/cjs/global-account/react/index.native.js +21 -0
  29. package/dist/cjs/global-account/react/stores/useModalStore.d.ts +2 -0
  30. package/dist/cjs/global-account/types/chain-networks.d.ts +34 -34
  31. package/dist/cjs/global-account/types/feature-flags.d.ts +5 -5
  32. package/dist/cjs/shared/constants/chains/b3Chain.d.ts +1 -1
  33. package/dist/cjs/shared/constants/chains/supported.d.ts +8 -7
  34. package/dist/cjs/shared/constants/chains/supported.js +8 -1
  35. package/dist/cjs/shared/utils/chains.js +4 -0
  36. package/dist/cjs/shared/utils/number.js +1 -1
  37. package/dist/esm/anyspend/index.native.d.ts +13 -0
  38. package/dist/esm/anyspend/index.native.js +19 -0
  39. package/dist/esm/anyspend/react/components/AnySpend.d.ts +2 -1
  40. package/dist/esm/anyspend/react/components/AnySpend.js +4 -4
  41. package/dist/esm/anyspend/react/components/AnySpendBuySpin.d.ts +2 -1
  42. package/dist/esm/anyspend/react/components/AnySpendBuySpin.js +123 -50
  43. package/dist/esm/anyspend/react/components/common/OrderHistoryItem.js +5 -1
  44. package/dist/esm/anyspend/react/components/common/TokenBalance.js +1 -1
  45. package/dist/esm/anyspend/utils/chain.js +3 -0
  46. package/dist/esm/global-account/react/components/B3DynamicModal.js +1 -1
  47. package/dist/esm/global-account/react/components/{B3Provider.d.ts → B3Provider/B3Provider.d.ts} +3 -29
  48. package/dist/esm/global-account/react/components/{B3Provider.js → B3Provider/B3Provider.js} +5 -32
  49. package/dist/esm/global-account/react/components/{B3Provider.native.d.ts → B3Provider/B3Provider.native.d.ts} +2 -25
  50. package/dist/esm/global-account/react/components/{B3Provider.native.js → B3Provider/B3Provider.native.js} +5 -26
  51. package/dist/esm/global-account/react/components/B3Provider/types.d.ts +25 -0
  52. package/dist/esm/global-account/react/components/B3Provider/types.js +17 -0
  53. package/dist/esm/global-account/react/components/B3Provider/useB3.d.ts +5 -0
  54. package/dist/esm/global-account/react/components/B3Provider/useB3.js +14 -0
  55. package/dist/esm/global-account/react/components/StyleRoot.js +1 -1
  56. package/dist/esm/global-account/react/components/index.d.ts +8 -6
  57. package/dist/esm/global-account/react/components/index.js +7 -5
  58. package/dist/esm/global-account/react/hooks/index.d.ts +1 -1
  59. package/dist/esm/global-account/react/hooks/index.js +1 -1
  60. package/dist/esm/global-account/react/hooks/useBestTransactionPath.js +3 -3
  61. package/dist/esm/global-account/react/hooks/useTokenBalance.js +1 -1
  62. package/dist/esm/global-account/react/index.native.d.ts +7 -0
  63. package/dist/esm/global-account/react/index.native.js +11 -0
  64. package/dist/esm/global-account/react/stores/useModalStore.d.ts +2 -0
  65. package/dist/esm/global-account/types/chain-networks.d.ts +34 -34
  66. package/dist/esm/global-account/types/feature-flags.d.ts +5 -5
  67. package/dist/esm/shared/constants/chains/b3Chain.d.ts +1 -1
  68. package/dist/esm/shared/constants/chains/supported.d.ts +8 -7
  69. package/dist/esm/shared/constants/chains/supported.js +7 -0
  70. package/dist/esm/shared/utils/chains.js +4 -0
  71. package/dist/esm/shared/utils/number.js +1 -1
  72. package/dist/styles/index.css +1 -1
  73. package/dist/types/anyspend/index.native.d.ts +13 -0
  74. package/dist/types/anyspend/react/components/AnySpend.d.ts +2 -1
  75. package/dist/types/anyspend/react/components/AnySpendBuySpin.d.ts +2 -1
  76. package/dist/types/global-account/react/components/{B3Provider.d.ts → B3Provider/B3Provider.d.ts} +2 -28
  77. package/dist/types/global-account/react/components/{B3Provider.native.d.ts → B3Provider/B3Provider.native.d.ts} +1 -24
  78. package/dist/types/global-account/react/components/B3Provider/types.d.ts +25 -0
  79. package/dist/types/global-account/react/components/B3Provider/useB3.d.ts +5 -0
  80. package/dist/types/global-account/react/components/index.d.ts +8 -6
  81. package/dist/types/global-account/react/hooks/index.d.ts +1 -1
  82. package/dist/types/global-account/react/index.native.d.ts +7 -0
  83. package/dist/types/global-account/react/stores/useModalStore.d.ts +2 -0
  84. package/dist/types/global-account/types/chain-networks.d.ts +34 -34
  85. package/dist/types/global-account/types/feature-flags.d.ts +5 -5
  86. package/dist/types/shared/constants/chains/b3Chain.d.ts +1 -1
  87. package/dist/types/shared/constants/chains/supported.d.ts +8 -7
  88. package/package.json +26 -24
  89. package/src/anyspend/index.native.ts +24 -0
  90. package/src/anyspend/react/components/AnySpend.tsx +6 -5
  91. package/src/anyspend/react/components/AnySpendBuySpin.tsx +232 -179
  92. package/src/anyspend/react/components/common/OrderHistoryItem.tsx +5 -1
  93. package/src/anyspend/react/components/common/TokenBalance.tsx +1 -1
  94. package/src/anyspend/utils/chain.ts +3 -0
  95. package/src/global-account/react/components/B3DynamicModal.tsx +1 -1
  96. package/src/global-account/react/components/{B3Provider.native.tsx → B3Provider/B3Provider.native.tsx} +4 -45
  97. package/src/global-account/react/components/{B3Provider.tsx → B3Provider/B3Provider.tsx} +4 -53
  98. package/src/global-account/react/components/B3Provider/types.ts +40 -0
  99. package/src/global-account/react/components/B3Provider/useB3.ts +17 -0
  100. package/src/global-account/react/components/StyleRoot.tsx +1 -1
  101. package/src/global-account/react/components/index.ts +8 -6
  102. package/src/global-account/react/hooks/index.ts +1 -1
  103. package/src/global-account/react/hooks/useBestTransactionPath.tsx +3 -3
  104. package/src/global-account/react/hooks/useTokenBalance.tsx +1 -1
  105. package/src/global-account/react/index.native.ts +14 -0
  106. package/src/global-account/react/stores/useModalStore.ts +2 -0
  107. package/src/shared/constants/chains/supported.ts +12 -4
  108. package/src/shared/utils/chains.ts +4 -1
  109. package/src/shared/utils/number.ts +1 -1
  110. package/dist/cjs/styles/index.d.ts +0 -20
  111. package/dist/cjs/styles/index.js +0 -22
  112. package/dist/esm/styles/index.d.ts +0 -20
  113. package/dist/esm/styles/index.js +0 -20
  114. package/dist/types/styles/index.d.ts +0 -20
  115. package/src/styles/index.ts +0 -24
@@ -0,0 +1,19 @@
1
+ // Export all hooks
2
+ export * from "./react/hooks";
3
+ // Providers
4
+ export * from "./react/providers/AnyspendProvider";
5
+ // Types
6
+ export * from "./types";
7
+ // Utils
8
+ export * from "./utils/address";
9
+ export * from "./utils/chain";
10
+ export * from "./utils/format";
11
+ export * from "./utils/json";
12
+ export * from "./utils/number";
13
+ export * from "./utils/string";
14
+ export * from "./utils/token";
15
+ // Constants
16
+ export * from "./constants";
17
+ // Abis
18
+ export * from "./abis/abi-usdc-base";
19
+ export * from "./abis/erc20-staking";
@@ -11,7 +11,7 @@ export declare enum PanelView {
11
11
  LOADING = 3,
12
12
  FIAT_PAYMENT = 4
13
13
  }
14
- export declare function AnySpend({ destinationTokenAddress, destinationTokenChainId, isMainnet, mode, defaultActiveTab, loadOrder, hideTransactionHistoryButton }: {
14
+ export declare function AnySpend({ destinationTokenAddress, destinationTokenChainId, isMainnet, mode, defaultActiveTab, loadOrder, hideTransactionHistoryButton, recipientAddress: recipientAddressFromProps }: {
15
15
  destinationTokenAddress?: string;
16
16
  destinationTokenChainId?: number;
17
17
  isMainnet?: boolean;
@@ -19,4 +19,5 @@ export declare function AnySpend({ destinationTokenAddress, destinationTokenChai
19
19
  defaultActiveTab?: "crypto" | "fiat";
20
20
  loadOrder?: string;
21
21
  hideTransactionHistoryButton?: boolean;
22
+ recipientAddress?: string;
22
23
  }): import("react/jsx-runtime").JSX.Element;
@@ -2,8 +2,8 @@
2
2
  import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
3
3
  import { getDefaultToken, OrderType, TradeType, USDC_BASE, useAnyspendCreateOrder, useAnyspendOrderAndTransactions, useAnyspendQuote } from "../../../anyspend";
4
4
  import { Button, ShinyButton, StyleRoot, TransitionPanel, useAccountWallet, useOnchainName, useRouter, useSearchParamsSSR, useTokenData, useTokenFromUrl } from "../../../global-account/react";
5
- import { shortenAddress } from "../../../shared/utils/formatAddress";
6
5
  import { cn } from "../../../shared/utils/cn";
6
+ import { shortenAddress } from "../../../shared/utils/formatAddress";
7
7
  import { formatDisplayNumber, formatTokenAmount } from "../../../shared/utils/number";
8
8
  import { motion } from "framer-motion";
9
9
  import invariant from "invariant";
@@ -29,7 +29,7 @@ export var PanelView;
29
29
  PanelView[PanelView["FIAT_PAYMENT"] = 4] = "FIAT_PAYMENT";
30
30
  })(PanelView || (PanelView = {}));
31
31
  const ANYSPEND_RECIPIENTS_KEY = "anyspend_recipients";
32
- export function AnySpend({ destinationTokenAddress, destinationTokenChainId, isMainnet = true, mode = "modal", defaultActiveTab = "crypto", loadOrder, hideTransactionHistoryButton }) {
32
+ export function AnySpend({ destinationTokenAddress, destinationTokenChainId, isMainnet = true, mode = "modal", defaultActiveTab = "crypto", loadOrder, hideTransactionHistoryButton, recipientAddress: recipientAddressFromProps }) {
33
33
  const searchParams = useSearchParamsSSR();
34
34
  const router = useRouter();
35
35
  // Determine if we're in "buy mode" based on whether destination token props are provided
@@ -272,8 +272,8 @@ export function AnySpend({ destinationTokenAddress, destinationTokenChainId, isM
272
272
  const { address: globalAddress, wallet: globalWallet } = useAccountWallet();
273
273
  // Set default recipient address when wallet changes
274
274
  useEffect(() => {
275
- setRecipientAddress(globalAddress);
276
- }, [globalAddress]);
275
+ setRecipientAddress(recipientAddressFromProps || globalAddress);
276
+ }, [recipientAddressFromProps, globalAddress]);
277
277
  // Get anyspend price
278
278
  const activeInputAmountInWei = isSrcInputDirty
279
279
  ? parseUnits(srcAmount.replaceAll(",", ""), selectedSrcToken.decimals).toString()
@@ -1,9 +1,10 @@
1
- export declare function AnySpendBuySpin({ isMainnet, loadOrder, mode, spinwheelContractAddress, chainId, recipientAddress, onSuccess }: {
1
+ export declare function AnySpendBuySpin({ isMainnet, loadOrder, mode, spinwheelContractAddress, chainId, recipientAddress, prefillQuantity, onSuccess }: {
2
2
  isMainnet?: boolean;
3
3
  loadOrder?: string;
4
4
  mode?: "modal" | "page";
5
5
  spinwheelContractAddress: string;
6
6
  chainId: number;
7
7
  recipientAddress: string;
8
+ prefillQuantity?: string;
8
9
  onSuccess?: (txHash?: string) => void;
9
10
  }): import("react/jsx-runtime").JSX.Element;
@@ -1,5 +1,6 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
2
  import { B3_TOKEN, OrderType } from "../../../anyspend";
3
+ import { baseMainnet } from "../../../shared/constants/chains/supported";
3
4
  import { EthIcon } from "./icons/EthIcon";
4
5
  import { SolIcon } from "./icons/SolIcon";
5
6
  import { UsdcIcon } from "./icons/USDCIcon";
@@ -11,7 +12,6 @@ import { ArrowRight, Loader2 } from "lucide-react";
11
12
  import { useCallback, useEffect, useState } from "react";
12
13
  import { toast } from "sonner";
13
14
  import { createPublicClient, encodeFunctionData, erc20Abi, formatUnits, http } from "viem";
14
- import { base } from "viem/chains";
15
15
  import { useAccount, useWaitForTransactionReceipt, useWriteContract } from "wagmi";
16
16
  import { AnySpendCustom } from "./AnySpendCustom";
17
17
  const SPIN_WHEEL_ABI = [
@@ -43,8 +43,37 @@ const SPIN_WHEEL_ABI = [
43
43
  outputs: [],
44
44
  stateMutability: "payable",
45
45
  type: "function"
46
+ },
47
+ {
48
+ inputs: [],
49
+ name: "getWheelInfo",
50
+ outputs: [
51
+ { internalType: "address", name: "creator_", type: "address" },
52
+ { internalType: "uint256", name: "startTime_", type: "uint256" },
53
+ { internalType: "uint256", name: "endTime_", type: "uint256" },
54
+ { internalType: "uint256", name: "totalPrizesAvailable_", type: "uint256" },
55
+ { internalType: "uint256", name: "prizesRequestedCount_", type: "uint256" },
56
+ { internalType: "enum SpinWheelV2.WheelState", name: "state_", type: "uint8" }
57
+ ],
58
+ stateMutability: "view",
59
+ type: "function"
46
60
  }
47
61
  ];
62
+ function getWheelStatus(wheelInfo) {
63
+ const now = BigInt(Math.floor(Date.now() / 1000));
64
+ console.log("@@anyspend-buy-spin:now:", now);
65
+ console.log("@@anyspend-buy-spin:wheelInfo:", wheelInfo);
66
+ if (now < wheelInfo.startTime_) {
67
+ return "not_started";
68
+ }
69
+ if (now > wheelInfo.endTime_) {
70
+ return "ended";
71
+ }
72
+ if (wheelInfo.totalPrizesAvailable_ <= wheelInfo.prizesRequestedCount_) {
73
+ return "sold_out";
74
+ }
75
+ return "active";
76
+ }
48
77
  function generateEncodedDataForBuyEntriesAndSpin(user, quantity) {
49
78
  invariant(BigInt(quantity) > 0, "Quantity must be greater than zero");
50
79
  console.log("@@anyspend-buy-spin:encoded-data:", { user, quantity });
@@ -56,16 +85,17 @@ function generateEncodedDataForBuyEntriesAndSpin(user, quantity) {
56
85
  return encodedData;
57
86
  }
58
87
  const basePublicClient = createPublicClient({
59
- chain: base,
88
+ chain: baseMainnet,
60
89
  transport: http()
61
90
  });
62
- export function AnySpendBuySpin({ isMainnet = true, loadOrder, mode = "modal", spinwheelContractAddress, chainId, recipientAddress, onSuccess }) {
91
+ export function AnySpendBuySpin({ isMainnet = true, loadOrder, mode = "modal", spinwheelContractAddress, chainId, recipientAddress, prefillQuantity, onSuccess }) {
63
92
  const hasMounted = useHasMounted();
64
93
  const { setB3ModalOpen } = useModalStore();
65
94
  // Payment config state
66
95
  const [paymentConfig, setPaymentConfig] = useState(null);
67
96
  const [isLoadingConfig, setIsLoadingConfig] = useState(true);
68
97
  const [configError, setConfigError] = useState("");
98
+ const [wheelInfo, setWheelInfo] = useState(null);
69
99
  // Fetch B3 token balance
70
100
  const { formattedBalance: b3Balance, isLoading: isBalanceLoading, rawBalance: b3RawBalance } = useTokenBalance({
71
101
  token: B3_TOKEN
@@ -77,22 +107,29 @@ export function AnySpendBuySpin({ isMainnet = true, loadOrder, mode = "modal", s
77
107
  // State for direct buying flow (when user has B3 tokens)
78
108
  const [isBuying, setIsBuying] = useState(false);
79
109
  const [buyingTxHash, setBuyingTxHash] = useState("");
80
- const [showSuccessModal, setShowSuccessModal] = useState(false);
81
- // Wait for transaction confirmation
82
- const { isLoading: isTxPending, isSuccess: isTxSuccess } = useWaitForTransactionReceipt({
110
+ const { isLoading: isTxPending, isSuccess: isTxSuccess, isError: isTxError, error: txError } = useWaitForTransactionReceipt({
83
111
  hash: buyingTxHash,
84
112
  query: {
85
113
  structuralSharing: false
86
114
  }
87
115
  });
88
- // Show success modal when transaction is confirmed
116
+ // Handle transaction status
89
117
  useEffect(() => {
90
- if (isTxSuccess && buyingTxHash) {
91
- setShowAmountPrompt(false);
92
- setShowSuccessModal(true);
118
+ if (!buyingTxHash)
119
+ return;
120
+ if (isTxSuccess) {
121
+ setB3ModalOpen(false);
122
+ onSuccess?.(buyingTxHash);
123
+ toast.success("Spin purchase transaction confirmed!");
124
+ setIsBuying(false);
125
+ }
126
+ else if (isTxError) {
127
+ console.error("@@anyspend-buy-spin:tx-error:", txError);
128
+ toast.error("Transaction failed. Please try again.");
129
+ setB3ModalOpen(false);
93
130
  setIsBuying(false);
94
131
  }
95
- }, [isTxSuccess, buyingTxHash]);
132
+ }, [isTxSuccess, isTxError, buyingTxHash, onSuccess, setB3ModalOpen, txError]);
96
133
  // Spin quantity state
97
134
  const [userSpinQuantity, setUserSpinQuantity] = useState("");
98
135
  const [showAmountPrompt, setShowAmountPrompt] = useState(true);
@@ -100,9 +137,17 @@ export function AnySpendBuySpin({ isMainnet = true, loadOrder, mode = "modal", s
100
137
  const [validationError, setValidationError] = useState("");
101
138
  const [displayQuantity, setDisplayQuantity] = useState("");
102
139
  const [debouncedQuantity, setDebouncedQuantity] = useState("");
140
+ const [debouncedUserSpinQuantity, setDebouncedUserSpinQuantity] = useState("");
141
+ useEffect(() => {
142
+ if (prefillQuantity && wheelInfo) {
143
+ const remainingSpins = wheelInfo.totalPrizesAvailable_ - wheelInfo.prizesRequestedCount_;
144
+ const adjustedQuantity = BigInt(prefillQuantity) > remainingSpins ? remainingSpins.toString() : prefillQuantity;
145
+ validateAndSetQuantity(adjustedQuantity);
146
+ }
147
+ }, [prefillQuantity, wheelInfo]);
103
148
  // Calculate total cost
104
149
  const totalCost = paymentConfig && userSpinQuantity ? paymentConfig.pricePerEntry * BigInt(userSpinQuantity) : BigInt(0);
105
- // Fetch payment configuration
150
+ // Fetch payment configuration and wheel info
106
151
  const fetchPaymentConfig = useCallback(async () => {
107
152
  if (!basePublicClient || !spinwheelContractAddress)
108
153
  return;
@@ -110,7 +155,7 @@ export function AnySpendBuySpin({ isMainnet = true, loadOrder, mode = "modal", s
110
155
  setIsLoadingConfig(true);
111
156
  setConfigError("");
112
157
  console.log("@@anyspend-buy-spin:fetch-config:", { spinwheelContractAddress, chainId });
113
- const [config, entryModuleAddress] = await Promise.all([
158
+ const [config, entryModuleAddress, wheelInfo] = await Promise.all([
114
159
  basePublicClient.readContract({
115
160
  address: spinwheelContractAddress,
116
161
  abi: SPIN_WHEEL_ABI,
@@ -120,6 +165,11 @@ export function AnySpendBuySpin({ isMainnet = true, loadOrder, mode = "modal", s
120
165
  address: spinwheelContractAddress,
121
166
  abi: SPIN_WHEEL_ABI,
122
167
  functionName: "entryModule"
168
+ }),
169
+ basePublicClient.readContract({
170
+ address: spinwheelContractAddress,
171
+ abi: SPIN_WHEEL_ABI,
172
+ functionName: "getWheelInfo"
123
173
  })
124
174
  ]);
125
175
  const paymentConfig = {
@@ -128,13 +178,16 @@ export function AnySpendBuySpin({ isMainnet = true, loadOrder, mode = "modal", s
128
178
  paymentRecipient: config[3],
129
179
  entryModule: entryModuleAddress
130
180
  };
131
- console.log("@@anyspend-buy-spin:config-fetched:", {
132
- pricePerEntry: paymentConfig.pricePerEntry.toString(),
133
- maxEntriesPerUser: paymentConfig.maxEntriesPerUser.toString(),
134
- paymentRecipient: paymentConfig.paymentRecipient,
135
- entryModule: paymentConfig.entryModule
136
- });
181
+ const wheelInfoData = {
182
+ creator_: wheelInfo[0],
183
+ startTime_: wheelInfo[1],
184
+ endTime_: wheelInfo[2],
185
+ totalPrizesAvailable_: wheelInfo[3],
186
+ prizesRequestedCount_: wheelInfo[4],
187
+ state_: wheelInfo[5]
188
+ };
137
189
  setPaymentConfig(paymentConfig);
190
+ setWheelInfo(wheelInfoData);
138
191
  }
139
192
  catch (error) {
140
193
  console.error("@@anyspend-buy-spin:config-error:", error);
@@ -153,6 +206,7 @@ export function AnySpendBuySpin({ isMainnet = true, loadOrder, mode = "modal", s
153
206
  useEffect(() => {
154
207
  const timer = setTimeout(() => {
155
208
  setDebouncedQuantity(displayQuantity);
209
+ setDebouncedUserSpinQuantity(userSpinQuantity);
156
210
  }, 500);
157
211
  return () => clearTimeout(timer);
158
212
  }, [displayQuantity, userSpinQuantity]);
@@ -184,6 +238,13 @@ export function AnySpendBuySpin({ isMainnet = true, loadOrder, mode = "modal", s
184
238
  setValidationError(`Maximum ${paymentConfig.maxEntriesPerUser.toString()} spins allowed`);
185
239
  return;
186
240
  }
241
+ // Check if quantity exceeds remaining entries
242
+ if (wheelInfo && BigInt(numValue) > wheelInfo.totalPrizesAvailable_ - wheelInfo.prizesRequestedCount_) {
243
+ setIsQuantityValid(false);
244
+ setUserSpinQuantity("");
245
+ setValidationError(`Only ${(wheelInfo.totalPrizesAvailable_ - wheelInfo.prizesRequestedCount_).toString()} spins remaining`);
246
+ return;
247
+ }
187
248
  setUserSpinQuantity(value);
188
249
  setIsQuantityValid(true);
189
250
  setValidationError("");
@@ -233,7 +294,7 @@ export function AnySpendBuySpin({ isMainnet = true, loadOrder, mode = "modal", s
233
294
  catch (error) {
234
295
  console.error("@@anyspend-buy-spin:error:", error);
235
296
  toast.error("Spin purchase failed. Please try again.");
236
- setShowSuccessModal(false);
297
+ setB3ModalOpen(false);
237
298
  }
238
299
  finally {
239
300
  setIsBuying(false);
@@ -271,46 +332,58 @@ export function AnySpendBuySpin({ isMainnet = true, loadOrder, mode = "modal", s
271
332
  // Render quantity input prompt
272
333
  if (showAmountPrompt) {
273
334
  const pricePerEntry = formatUnits(paymentConfig.pricePerEntry, 18);
335
+ const remainingEntries = wheelInfo ? wheelInfo.totalPrizesAvailable_ - wheelInfo.prizesRequestedCount_ : 0n;
336
+ const wheelStatus = wheelInfo ? getWheelStatus(wheelInfo) : null;
337
+ const isSoldOut = wheelStatus === "sold_out";
338
+ const isActive = wheelStatus === "active";
339
+ const getStatusMessage = () => {
340
+ if (!wheelInfo)
341
+ return null;
342
+ const formatDate = (timestamp) => {
343
+ return new Date(Number(timestamp) * 1000).toLocaleString();
344
+ };
345
+ switch (wheelStatus) {
346
+ case "not_started":
347
+ return {
348
+ title: "Spin Wheel Not Started",
349
+ message: `Starts at ${formatDate(wheelInfo.startTime_)}`
350
+ };
351
+ case "ended":
352
+ return {
353
+ title: "Spin Wheel Ended",
354
+ message: `Ended at ${formatDate(wheelInfo.endTime_)}`
355
+ };
356
+ case "sold_out":
357
+ return {
358
+ title: "All Spins Have Been Claimed",
359
+ message: "Stay tuned for the next spin wheel event!"
360
+ };
361
+ default:
362
+ return null;
363
+ }
364
+ };
365
+ const statusInfo = getStatusMessage();
274
366
  return (_jsx(StyleRoot, { children: _jsxs("div", { className: "bg-b3-react-background flex w-full flex-col items-center", children: [_jsxs("div", { className: "w-full px-4 pb-2 pt-4", children: [_jsx(motion.div, { initial: false, animate: {
275
367
  opacity: hasMounted ? 1 : 0,
276
368
  y: hasMounted ? 0 : 20,
277
369
  filter: hasMounted ? "blur(0px)" : "blur(10px)"
278
- }, transition: { duration: 0.3, delay: 0, ease: "easeInOut" }, className: "mb-4 flex justify-center", children: _jsx("img", { alt: "B3 Token", loading: "lazy", width: "64", height: "64", decoding: "async", className: "rounded-full", src: "https://cdn.b3.fun/b3-coin-3d.png" }) }), _jsxs(motion.div, { initial: false, animate: {
279
- opacity: hasMounted ? 1 : 0,
280
- y: hasMounted ? 0 : 20,
281
- filter: hasMounted ? "blur(0px)" : "blur(10px)"
282
- }, transition: { duration: 0.3, delay: 0.1, ease: "easeInOut" }, className: "text-center", children: [_jsx("h2", { className: "font-sf-rounded text-as-primary mb-2 text-2xl font-bold", children: (() => {
283
- const hasEnoughBalance = b3RawBalance && totalCost <= b3RawBalance;
284
- return hasEnoughBalance || !debouncedQuantity ? "Buy Spins" : `Swap & Buy Spins`;
285
- })() }), _jsx("div", { className: "bg-as-on-surface-2/50 inline-flex items-center gap-2 rounded-full border border-white/10 px-3 py-1 backdrop-blur-sm", children: _jsxs("p", { className: "text-as-primary/80 text-sm", children: [pricePerEntry, " $B3 per spin"] }) })] })] }), _jsxs(motion.div, { initial: false, animate: {
286
- opacity: hasMounted ? 1 : 0,
287
- y: hasMounted ? 0 : 20,
288
- filter: hasMounted ? "blur(0px)" : "blur(10px)"
289
- }, 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: [_jsxs("div", { className: "flex items-center justify-between", children: [_jsx("p", { className: "text-as-primary/70 text-sm font-medium", children: "Number of spins" }), _jsxs("span", { className: "text-as-primary/50 flex items-center gap-1 text-sm", children: ["Available: ", isBalanceLoading ? _jsx(Loader2, { className: "h-3 w-3 animate-spin" }) : `${b3Balance} B3`] })] }), _jsxs("div", { className: "relative", children: [_jsx(Input, { onFocus: onFocusQuantityInput, type: "text", placeholder: "1", value: displayQuantity, onChange: e => validateAndSetQuantity(e.target.value), className: `h-14 px-4 pr-20 text-lg ${!isQuantityValid && displayQuantity ? "border-as-red" : "border-b3-react-border"}` }), _jsx("div", { className: "font-pack absolute right-4 top-1/2 -translate-y-1/2 text-lg font-medium text-blue-500/70", children: displayQuantity === "1" ? "Spin" : "Spins" })] }), !isQuantityValid && displayQuantity && _jsx("p", { className: "text-as-red text-sm", children: validationError }), _jsx("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: [displayQuantity && isQuantityValid ? formatUnits(totalCost, 18) : "0", " B3"] }) })] }) })] }), _jsx("div", { className: "mt-4", children: (() => {
290
- const hasEnoughBalance = b3RawBalance && totalCost <= b3RawBalance;
291
- if (!hasEnoughBalance && debouncedQuantity) {
292
- return (_jsxs("div", { className: "bg-as-brand/10 flex flex-col items-center gap-2 rounded-lg p-4 pb-5", children: [_jsxs("div", { className: "flex items-center justify-center gap-2", children: [_jsx("span", { className: "text-as-primary text-sm font-semibold", children: "Swap & buy from any token" }), _jsxs(TextLoop, { children: [_jsx(EthIcon, { className: "h-8 w-8" }), _jsx(SolIcon, { className: "h-8 w-8" }), _jsx(UsdcIcon, { className: "h-8 w-8" })] }), _jsx(ArrowRight, { className: "text-as-primary h-4 w-4" }), _jsx("img", { src: "https://cdn.b3.fun/b3-coin-3d.png", className: "h-7 w-7", alt: "B3 Token" })] }), _jsx("p", { className: "text-as-primary/50 text-sm font-medium", children: "No problem, we'll help you swap to B3 for your spins!" })] }));
293
- }
294
- })() }), _jsx(Button, { onClick: confirmQuantity, disabled: !isQuantityValid || !displayQuantity || isBuying || isTxPending, className: "bg-as-brand hover:bg-as-brand/90 text-as-primary mt-4 h-14 w-full rounded-xl text-lg font-medium", children: isBuying ? "Buying..." : isTxPending ? "Confirming..." : "Continue" })] })] }) }));
295
- }
296
- // Success Modal for Direct Buying
297
- if (showSuccessModal) {
298
- return (_jsx(StyleRoot, { children: _jsxs("div", { className: "bg-b3-react-background flex w-full flex-col items-center", children: [_jsxs("div", { className: "w-full p-4", children: [_jsxs(motion.div, { initial: false, animate: {
299
- opacity: hasMounted ? 1 : 0,
300
- y: hasMounted ? 0 : 20,
301
- filter: hasMounted ? "blur(0px)" : "blur(10px)"
302
- }, transition: { duration: 0.3, delay: 0, ease: "easeInOut" }, className: "relative mx-auto mb-4 size-[120px]", children: [_jsx("div", { className: "absolute inset-0 scale-95 rounded-[50%] bg-gradient-to-br from-green-500/30 to-blue-500/30 blur-xl" }), _jsxs(GlareCardRounded, { className: "overflow-hidden rounded-full border-none bg-gradient-to-br from-green-500/10 to-blue-500/10 backdrop-blur-sm", children: [_jsx("img", { alt: "B3 Token", loading: "lazy", width: "120", height: "120", decoding: "async", "data-nimg": "1", className: "size-full shrink-0 bg-transparent text-transparent", src: "https://cdn.b3.fun/b3-coin-3d.png" }), _jsx("div", { className: "absolute inset-0 rounded-[50%] border border-white/20" })] })] }), _jsxs(motion.div, { initial: false, animate: {
370
+ }, transition: { duration: 0.3, delay: 0, ease: "easeInOut" }, className: `flex justify-center ${isActive ? "mb-4" : ""}`, children: _jsx("img", { alt: "B3 Token", loading: "lazy", width: "64", height: "64", decoding: "async", className: "rounded-full", src: "https://cdn.b3.fun/b3-coin-3d.png" }) }), _jsx(motion.div, { initial: false, animate: {
303
371
  opacity: hasMounted ? 1 : 0,
304
372
  y: hasMounted ? 0 : 20,
305
373
  filter: hasMounted ? "blur(0px)" : "blur(10px)"
306
- }, transition: { duration: 0.3, delay: 0.1, ease: "easeInOut" }, className: "text-center", children: [_jsx("h2", { className: "font-sf-rounded mb-3 bg-gradient-to-r from-green-400 to-blue-500 bg-clip-text text-3xl font-bold text-transparent", children: "\uD83C\uDF89 Purchase Complete!" }), _jsx("div", { className: "bg-as-on-surface-2/50 inline-flex items-center gap-2 rounded-full border border-white/10 px-4 py-2 backdrop-blur-sm", children: _jsxs("span", { className: "text-as-primary/80 text-sm font-medium", children: [userSpinQuantity, " Spin", userSpinQuantity !== "1" ? "s" : "", " \u2022 ", formatUnits(totalCost, 18), " B3"] }) })] })] }), _jsxs(motion.div, { initial: false, animate: {
374
+ }, transition: { duration: 0.3, delay: 0.1, ease: "easeInOut" }, className: "text-center", children: isActive ? (_jsxs(_Fragment, { children: [_jsx("h2", { className: "font-sf-rounded text-as-primary mb-4 text-2xl font-bold", children: (() => {
375
+ const hasEnoughBalance = b3RawBalance && totalCost <= b3RawBalance;
376
+ return hasEnoughBalance || !debouncedQuantity ? "Buy Spins" : `Swap & Buy Spins`;
377
+ })() }), wheelInfo && (_jsxs("div", { className: "inline-flex items-center gap-2", children: [_jsx("div", { className: "bg-as-brand/10 border-as-brand/10 inline-flex items-center rounded-full border px-3 py-1", children: _jsxs("p", { className: "text-as-brand text-sm font-medium", children: [pricePerEntry, " $B3 per spin"] }) }), _jsx("div", { className: "bg-as-brand/10 border-as-brand/10 inline-flex items-center rounded-full border px-3 py-1", children: _jsxs("p", { className: "text-as-brand text-sm font-medium", children: [remainingEntries.toString(), " remaining"] }) })] }))] })) : (statusInfo && (_jsxs("div", { className: "text-center", children: [_jsx("p", { className: "text-as-primary text-lg font-semibold", children: statusInfo.title }), _jsx("p", { className: "text-as-primary/70 mt-2 text-sm", children: statusInfo.message })] }))) })] }), _jsx(motion.div, { initial: false, animate: {
307
378
  opacity: hasMounted ? 1 : 0,
308
379
  y: hasMounted ? 0 : 20,
309
380
  filter: hasMounted ? "blur(0px)" : "blur(10px)"
310
- }, transition: { duration: 0.3, delay: 0.2, ease: "easeInOut" }, className: "bg-b3-react-background w-full p-6", children: [_jsx("div", { className: "mb-6", children: _jsx("a", { href: `https://basescan.org/tx/${buyingTxHash}`, target: "_blank", rel: "noopener noreferrer", className: "text-as-primary/70 hover:text-as-primary block break-all text-center font-mono text-sm underline transition-colors", children: "View transaction" }) }), _jsx(Button, { onClick: () => {
311
- setB3ModalOpen(false);
312
- onSuccess?.(buyingTxHash);
313
- }, className: "bg-as-brand hover:bg-as-brand/90 text-as-primary h-14 w-full rounded-xl text-lg font-medium", children: "Done" })] })] }) }));
381
+ }, transition: { duration: 0.3, delay: 0.2, ease: "easeInOut" }, className: "bg-b3-react-background w-full p-6", children: isActive ? (_jsxs("div", { className: "space-y-4", children: [_jsxs("div", { className: "flex items-center justify-between", children: [_jsx("p", { className: "text-as-primary/70 text-sm font-medium", children: "Number of spins" }), _jsxs("span", { className: "text-as-primary/50 flex items-center gap-1 text-sm", children: ["Available: ", isBalanceLoading ? _jsx(Loader2, { className: "h-3 w-3 animate-spin" }) : `${b3Balance} B3`] })] }), _jsxs("div", { className: "relative", children: [_jsx(Input, { onFocus: onFocusQuantityInput, type: "text", placeholder: "1", value: displayQuantity, onChange: e => validateAndSetQuantity(e.target.value), className: `h-14 px-4 pr-20 text-lg ${!isQuantityValid && displayQuantity ? "border-as-red" : "border-b3-react-border"}` }), _jsx("div", { className: "font-pack absolute right-4 top-1/2 -translate-y-1/2 text-lg font-medium text-blue-500/70", children: displayQuantity === "1" ? "Spin" : "Spins" })] }), !isQuantityValid && displayQuantity && _jsx("p", { className: "text-as-red text-sm", children: validationError }), _jsx("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: [displayQuantity && isQuantityValid ? formatUnits(totalCost, 18) : "0", " B3"] }) })] }) }), _jsx("div", { className: "mt-4", children: (() => {
382
+ const hasEnoughBalance = b3RawBalance && totalCost <= b3RawBalance;
383
+ if (!hasEnoughBalance && debouncedQuantity) {
384
+ return (_jsxs("div", { className: "bg-as-brand/10 flex flex-col items-center gap-2 rounded-lg p-4 pb-5", children: [_jsxs("div", { className: "flex items-center justify-center gap-2", children: [_jsx("span", { className: "text-as-primary text-sm font-semibold", children: "Swap & buy from any token" }), _jsxs(TextLoop, { children: [_jsx(EthIcon, { className: "h-8 w-8" }), _jsx(SolIcon, { className: "h-8 w-8" }), _jsx(UsdcIcon, { className: "h-8 w-8" })] }), _jsx(ArrowRight, { className: "text-as-primary h-4 w-4" }), _jsx("img", { src: "https://cdn.b3.fun/b3-coin-3d.png", className: "h-7 w-7", alt: "B3 Token" })] }), _jsx("p", { className: "text-as-primary/50 text-sm font-medium", children: "No problem, we'll help you swap to B3 for your spins!" })] }));
385
+ }
386
+ })() }), _jsx(Button, { onClick: confirmQuantity, disabled: !isQuantityValid || !displayQuantity || isBuying || isTxPending, className: "bg-as-brand hover:bg-as-brand/90 text-as-primary mt-4 h-14 w-full rounded-xl text-lg font-medium", children: isBuying ? "Buying..." : isTxPending ? "Confirming..." : "Continue" })] })) : null })] }) }));
314
387
  }
315
388
  // AnySpend flow for when user needs to swap to B3
316
389
  const encodedData = generateEncodedDataForBuyEntriesAndSpin(address || "", userSpinQuantity);
@@ -26,5 +26,9 @@ export function OrderHistoryItem({ order, onSelectOrder, mode }) {
26
26
  : order.payload.expectedDstAmount;
27
27
  const { text: orderStatusText, status: orderDisplayStatus } = getStatusDisplay(order);
28
28
  const isSmallView = useIsMobile() || mode === "modal";
29
- return (_jsxs("div", { className: cn("bg-as-light-brand/20 rounded-lg border p-4", onSelectOrder && "hover:bg-as-light-brand/30 hover:border-as-brand cursor-pointer transition-colors"), onClick: () => onSelectOrder?.(order.id), children: [_jsxs("div", { className: "flex items-center justify-between", children: [_jsx(Badge, { className: cn("px-3 py-1 text-xs", orderDisplayStatus === "processing" && "bg-yellow-500/10 text-yellow-500", orderDisplayStatus === "success" && "bg-green-500/10 text-green-500", orderDisplayStatus === "failure" && "bg-red-500/10 text-red-500"), children: orderStatusText }), _jsx("div", { className: "flex items-center gap-2", children: _jsx("span", { className: "text-nano label-style text-as-primary/30", children: _jsx(TimeAgo, { date: new Date(order.createdAt) }) }) })] }), order.oneClickBuyUrl ? (_jsx("div", { className: "mb-3 mt-4 flex items-center gap-1", children: _jsxs("div", { className: "bg-b3-react-background flex flex-1 flex-col gap-1 rounded-lg border p-4 px-5", children: [_jsxs("h3", { className: "text-as-primary/50 flex items-center gap-2 text-xl font-semibold", children: [_jsxs("span", { children: ["Buy ", _jsxs("span", { className: "text-as-primary", children: ["$", formatTokenAmount(BigInt(order.srcAmount), order.metadata.srcToken.decimals)] }), ` of`] }), _jsxs("span", { className: "text-as-primary flex items-center gap-2", children: [nft ? (_jsx("img", { src: nft.imageUrl, alt: nft.name, className: "h-6 w-6" })) : tournament ? (_jsx("img", { src: tournament.imageUrl, alt: tournament.name, className: "h-6 w-6" })) : (_jsx("img", { src: dstToken.metadata.logoURI, alt: dstToken.symbol, className: "h-6 w-6" })), nft ? nft.name : tournament ? tournament.name : dstToken.symbol] }), _jsxs("span", { className: "flex items-center gap-2", children: [` on `, _jsxs("span", { className: "text-as-primary flex items-center gap-2", children: [_jsx("img", { src: ALL_CHAINS[order.dstChain]?.logoUrl, alt: getChainName(order.dstChain), className: "h-4" }), order.dstChain !== b3.id && getChainName(order.dstChain)] })] })] }), _jsxs("p", { className: "label-style text-as-primary/30 mt-1 flex items-center gap-2 text-xs", children: ["Paying via", " ", _jsx("img", { src: "https://cdn.b3.fun/coinbase-wordmark-blue.svg", alt: "Coinbase", className: "-mt-1 h-3" })] })] }) })) : (_jsxs("div", { className: cn("mb-3 mt-4 flex items-center gap-1", isSmallView && "flex-col"), children: [_jsxs("div", { className: "bg-b3-react-background flex w-full flex-1 flex-col gap-1 overflow-hidden rounded-lg border p-4 px-5", children: [_jsxs("div", { className: "flex items-center gap-2", children: [_jsx("img", { src: order.metadata.srcToken.metadata.logoURI, alt: order.metadata.srcToken.symbol, className: "h-6 w-6 rounded-full" }), _jsxs("div", { className: "text-as-primary flex items-center gap-2 overflow-hidden text-ellipsis whitespace-nowrap text-xl font-semibold", children: [formatTokenAmount(BigInt(order.srcAmount), order.metadata.srcToken.decimals), " ", order.metadata.srcToken.symbol] })] }), _jsxs("div", { className: "label-style text-as-primary/50 flex items-center gap-2 text-sm", children: ["from", _jsx("img", { src: ALL_CHAINS[order.srcChain]?.logoUrl, alt: getChainName(order.srcChain), className: cn("h-4", order.srcChain !== b3.id && "w-4 rounded-full", order.srcChain === b3.id && "h-3") }), getChainName(order.srcChain)] })] }), _jsx("div", { className: cn("h-8 w-8 shrink-0 -rotate-90 opacity-30", isSmallView && "rotate-0"), children: _jsx(ChevronDown, { className: "h-8 w-8" }) }), _jsxs("div", { className: "bg-b3-react-background flex w-full flex-1 flex-col gap-1 overflow-hidden rounded-lg border p-4 px-5", children: [_jsx("div", { className: "flex items-center gap-2", children: nft ? (_jsxs(_Fragment, { children: [_jsx("img", { src: nft.imageUrl, alt: nft.name, className: "h-6 w-6 rounded-full" }), _jsx("div", { className: "text-as-primary overflow-hidden text-ellipsis whitespace-nowrap text-xl font-semibold", children: nft.name })] })) : tournament ? (_jsxs(_Fragment, { children: [_jsx("img", { src: tournament.imageUrl, alt: tournament.name, className: "h-6 w-6 rounded-full" }), _jsx("div", { className: "text-as-primary overflow-hidden text-ellipsis whitespace-nowrap text-xl font-semibold", children: tournament.name })] })) : (_jsxs(_Fragment, { children: [_jsx("img", { src: dstToken.metadata.logoURI, alt: dstToken.symbol, className: "h-6 w-6 rounded-full" }), _jsxs("div", { className: "text-as-primary overflow-hidden text-ellipsis whitespace-nowrap text-xl font-semibold", children: [formatTokenAmount(actualDstAmount ? BigInt(actualDstAmount) : expectedDstAmount ? BigInt(expectedDstAmount) : 0n, dstToken.decimals), " ", dstToken.symbol] })] })) }), _jsxs("div", { className: "label-style text-as-primary/50 flex items-center gap-2 text-sm", children: ["to", _jsx("img", { src: ALL_CHAINS[order.dstChain]?.logoUrl, alt: getChainName(order.dstChain), className: cn("h-4", order.dstChain !== b3.id && "w-4 rounded-full", order.dstChain === b3.id && "h-3") }), getChainName(order.dstChain)] })] })] })), _jsx("div", { className: "flex items-center justify-end", children: _jsxs(Button, { variant: "link", size: "sm", className: "h-auto", onClick: () => onSelectOrder?.(order.id), children: [orderDisplayStatus === "processing" ? "Proceed with payment" : "Details", " ", _jsx(ArrowRight, { className: "ml-2 h-3 w-3" })] }) })] }, `anyspend-${order.id}`));
29
+ return (_jsxs("div", { className: cn("bg-as-light-brand/20 rounded-lg border p-4", onSelectOrder && "hover:bg-as-light-brand/30 hover:border-as-brand cursor-pointer transition-colors"), onClick: () => onSelectOrder?.(order.id), children: [_jsxs("div", { className: "flex items-center justify-between", children: [_jsx(Badge, { className: cn("px-3 py-1 text-xs", orderDisplayStatus === "processing" && "bg-yellow-500/10 text-yellow-500", orderDisplayStatus === "success" && "bg-green-500/10 text-green-500", orderDisplayStatus === "failure" && "bg-red-500/10 text-red-500"), children: orderStatusText }), _jsx("div", { className: "flex items-center gap-2", children: _jsx("span", { className: "text-nano label-style text-as-primary/30", children: _jsx(TimeAgo, { date: new Date(order.createdAt) }) }) })] }), order.oneClickBuyUrl ? (_jsx("div", { className: "mb-3 mt-4 flex items-center gap-1", children: _jsxs("div", { className: "bg-b3-react-background flex flex-1 flex-col gap-1 rounded-lg border p-4 px-5", children: [_jsxs("h3", { className: "text-as-primary/50 flex items-center gap-2 text-xl font-semibold", children: [_jsxs("span", { children: ["Buy ", _jsxs("span", { className: "text-as-primary", children: ["$", formatTokenAmount(BigInt(order.srcAmount), order.metadata.srcToken.decimals)] }), ` of`] }), _jsxs("span", { className: "text-as-primary flex items-center gap-2", children: [nft ? (_jsx("img", { src: nft.imageUrl, alt: nft.name, className: "h-6 w-6" })) : tournament ? (_jsx("img", { src: tournament.imageUrl, alt: tournament.name, className: "h-6 w-6" })) : (_jsx("img", { src: dstToken.metadata.logoURI, alt: dstToken.symbol, className: "h-6 w-6" })), nft ? nft.name : tournament ? tournament.name : dstToken.symbol] }), _jsxs("span", { className: "flex items-center gap-2", children: [` on `, _jsxs("span", { className: "text-as-primary flex items-center gap-2", children: [_jsx("img", { src: ALL_CHAINS[order.dstChain]?.logoUrl, alt: getChainName(order.dstChain), className: "h-4" }), order.dstChain !== b3.id && getChainName(order.dstChain)] })] })] }), _jsxs("p", { className: "label-style text-as-primary/30 mt-1 flex items-center gap-2 text-xs", children: ["Paying via", " ", _jsx("img", { src: "https://cdn.b3.fun/coinbase-wordmark-blue.svg", alt: "Coinbase", className: "-mt-1 h-3" })] })] }) })) : (_jsxs("div", { className: cn("mb-3 mt-4 flex items-center gap-1", isSmallView && "flex-col"), children: [_jsxs("div", { className: "bg-b3-react-background flex w-full flex-1 flex-col gap-1 overflow-hidden rounded-lg border p-4 px-5", children: [_jsxs("div", { className: "flex items-center gap-2", children: [_jsx("img", { src: order.metadata.srcToken.metadata.logoURI, alt: order.metadata.srcToken.symbol, className: "h-6 w-6 rounded-full" }), _jsxs("div", { className: "text-as-primary flex items-center gap-2 overflow-hidden text-ellipsis whitespace-nowrap text-xl font-semibold", children: [formatTokenAmount(BigInt(order.srcAmount), order.metadata.srcToken.decimals), " ", order.metadata.srcToken.symbol] })] }), _jsxs("div", { className: "label-style text-as-primary/50 flex items-center gap-2 text-sm", children: ["from", _jsx("img", { src: ALL_CHAINS[order.srcChain]?.logoUrl, alt: getChainName(order.srcChain), className: cn("h-4", order.srcChain !== b3.id && "w-4 rounded-full", order.srcChain === b3.id && "h-3") }), getChainName(order.srcChain)] })] }), _jsx("div", { className: cn("h-8 w-8 shrink-0 -rotate-90 opacity-30", isSmallView && "rotate-0"), children: _jsx(ChevronDown, { className: "h-8 w-8" }) }), _jsxs("div", { className: "bg-b3-react-background flex w-full flex-1 flex-col gap-1 overflow-hidden rounded-lg border p-4 px-5", children: [_jsx("div", { className: "flex items-center gap-2", children: nft ? (_jsxs(_Fragment, { children: [_jsx("img", { src: nft.imageUrl, alt: nft.name, className: "h-6 w-6 rounded-full" }), _jsx("div", { className: "text-as-primary overflow-hidden text-ellipsis whitespace-nowrap text-xl font-semibold", children: nft.name })] })) : tournament ? (_jsxs(_Fragment, { children: [_jsx("img", { src: tournament.imageUrl, alt: tournament.name, className: "h-6 w-6 rounded-full" }), _jsx("div", { className: "text-as-primary overflow-hidden text-ellipsis whitespace-nowrap text-xl font-semibold", children: tournament.name })] })) : (_jsxs(_Fragment, { children: [_jsx("img", { src: dstToken.metadata.logoURI, alt: dstToken.symbol, className: "h-6 w-6 rounded-full" }), _jsxs("div", { className: "text-as-primary overflow-hidden text-ellipsis whitespace-nowrap text-xl font-semibold", children: [formatTokenAmount(actualDstAmount
30
+ ? BigInt(actualDstAmount)
31
+ : expectedDstAmount
32
+ ? BigInt(expectedDstAmount)
33
+ : BigInt(0), dstToken.decimals), " ", dstToken.symbol] })] })) }), _jsxs("div", { className: "label-style text-as-primary/50 flex items-center gap-2 text-sm", children: ["to", _jsx("img", { src: ALL_CHAINS[order.dstChain]?.logoUrl, alt: getChainName(order.dstChain), className: cn("h-4", order.dstChain !== b3.id && "w-4 rounded-full", order.dstChain === b3.id && "h-3") }), getChainName(order.dstChain)] })] })] })), _jsx("div", { className: "flex items-center justify-end", children: _jsxs(Button, { variant: "link", size: "sm", className: "h-auto", onClick: () => onSelectOrder?.(order.id), children: [orderDisplayStatus === "processing" ? "Proceed with payment" : "Details", " ", _jsx(ArrowRight, { className: "ml-2 h-3 w-3" })] }) })] }, `anyspend-${order.id}`));
30
34
  }
@@ -11,7 +11,7 @@ export function TokenBalance({ token, walletAddress, onChangeInput }) {
11
11
  return;
12
12
  // Calculate the amount based on percentage of balance
13
13
  // Multiply first, then divide to avoid BigInt truncation
14
- const amount = percentage === 100 ? rawBalance : (rawBalance * BigInt(percentage)) / 100n;
14
+ const amount = percentage === 100 ? rawBalance : (rawBalance * BigInt(percentage)) / BigInt(100);
15
15
  onChangeInput(formatUnits(amount, token.decimals));
16
16
  };
17
17
  return (_jsx("div", { className: "flex h-7 items-center justify-end gap-1", children: !isLoading && (_jsxs(_Fragment, { children: [_jsx("div", { className: "text-as-primary/50 inline-flex rounded-lg text-sm", children: rawBalance ? `Balance: ${formattedBalance}` : `Balance: 0` }), !!rawBalance && (_jsxs(_Fragment, { children: [_jsx("button", { onClick: () => handlePercentageClick(20), className: "text-as-primary/50 bg-as-on-surface-2 hover:bg-as-on-surface-3 inline-flex rounded-lg px-2 py-1 text-xs transition-colors sm:hidden", children: "20%" }), _jsx("button", { onClick: () => handlePercentageClick(50), className: "text-as-primary/50 bg-as-on-surface-2 hover:bg-as-on-surface-3 inline-flex rounded-lg px-2 py-1 text-xs transition-colors", children: "50%" }), _jsx("button", { onClick: () => handlePercentageClick(100), className: "text-as-primary/50 bg-as-on-surface-2 hover:bg-as-on-surface-3 inline-flex rounded-lg px-2 py-1 text-xs transition-colors", children: "MAX" })] }))] })) }, `balance-${token.address}-${token.chainId}`));
@@ -244,6 +244,9 @@ export function getPaymentUrl(address, amount, currency) {
244
244
  return `ethereum:${address}`;
245
245
  }
246
246
  export function getExplorerTxUrl(chainId, txHash) {
247
+ if (chainId === b3.id) {
248
+ return "https://explorer.b3.fun/b3/tx/" + txHash;
249
+ }
247
250
  if (EVM_CHAINS[chainId]) {
248
251
  return EVM_CHAINS[chainId].viem.blockExplorers?.default.url + "/tx/" + txHash;
249
252
  }
@@ -2,7 +2,7 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import { AnySpend, AnySpendBuySpin, AnySpendNFT, AnySpendStakeB3, AnySpendTournament, OrderHistory } from "../../../anyspend/react";
3
3
  import { useIsMobile, useModalStore } from "../../../global-account/react";
4
4
  import { debugB3React } from "../../../shared/utils/debug";
5
- import { useB3 } from "./B3Provider";
5
+ import { useB3 } from "./B3Provider/useB3";
6
6
  import { ManageAccount } from "./ManageAccount/ManageAccount";
7
7
  import { RequestPermissions } from "./RequestPermissions/RequestPermissions";
8
8
  import { SignInWithB3Flow } from "./SignInWithB3/SignInWithB3Flow";
@@ -1,34 +1,8 @@
1
- import { User } from "../../../global-account/types/b3-api.types";
2
- import { PermissionsConfig } from "../../../global-account/types/permissions";
3
- import { Account, Wallet } from "thirdweb/wallets";
1
+ import { PermissionsConfig } from "../../../../global-account/types/permissions";
2
+ import { Account } from "thirdweb/wallets";
4
3
  import "@reservoir0x/relay-kit-ui/styles.css";
4
+ import { B3ContextType } from "./types";
5
5
  export declare const wagmiConfig: import("wagmi").Config<readonly [import("viem").Chain, ...import("viem").Chain[]], any, readonly import("wagmi").CreateConnectorFn[]>;
6
- /**
7
- * Context type for B3Provider
8
- */
9
- export interface B3ContextType {
10
- account?: Account;
11
- automaticallySetFirstEoa: boolean;
12
- user?: User;
13
- setAccount: (account: Account) => void;
14
- setWallet: (wallet: Wallet) => void;
15
- wallet?: Wallet;
16
- setUser: (user?: User) => void;
17
- initialized: boolean;
18
- ready: boolean;
19
- environment?: "development" | "production";
20
- defaultPermissions?: PermissionsConfig;
21
- theme: "light" | "dark";
22
- }
23
- /**
24
- * Context for B3 provider
25
- */
26
- export declare const B3Context: import("react").Context<B3ContextType>;
27
- /**
28
- * Hook to access the B3 context
29
- * @throws Error if used outside a B3Provider
30
- */
31
- export declare function useB3(): B3ContextType;
32
6
  /**
33
7
  * Main B3Provider component
34
8
  */
@@ -1,13 +1,14 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
- import { supportedChains } from "../../../shared/constants/chains/supported";
2
+ import { supportedChains } from "../../../../shared/constants/chains/supported";
3
3
  import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
4
- import { createContext, useContext, useEffect, useMemo, useState } from "react";
4
+ import { useEffect, useState } from "react";
5
5
  import { Toaster } from "sonner";
6
6
  import { ThirdwebProvider, useActiveAccount, useConnectedWallets, useSetActiveWallet } from "thirdweb/react";
7
7
  import { createConfig, http, WagmiProvider } from "wagmi";
8
- import { RelayKitProviderWrapper } from "./RelayKitProviderWrapper";
9
- import { StyleRoot } from "./StyleRoot";
8
+ import { RelayKitProviderWrapper } from "../RelayKitProviderWrapper";
9
+ import { StyleRoot } from "../StyleRoot";
10
10
  import "@reservoir0x/relay-kit-ui/styles.css";
11
+ import { B3Context } from "./types";
11
12
  /**
12
13
  * Default permissions configuration for B3 provider
13
14
  */
@@ -21,34 +22,6 @@ export const wagmiConfig = createConfig({
21
22
  chains: [supportedChains[0], ...supportedChains.slice(1)],
22
23
  transports: Object.fromEntries(supportedChains.map(chain => [chain.id, http()]))
23
24
  });
24
- /**
25
- * Context for B3 provider
26
- */
27
- export const B3Context = createContext({
28
- account: undefined,
29
- automaticallySetFirstEoa: false,
30
- user: undefined,
31
- setAccount: () => { },
32
- setWallet: () => { },
33
- wallet: undefined,
34
- setUser: () => { },
35
- initialized: false,
36
- ready: false,
37
- environment: "development",
38
- theme: "light"
39
- });
40
- /**
41
- * Hook to access the B3 context
42
- * @throws Error if used outside a B3Provider
43
- */
44
- export function useB3() {
45
- const context = useContext(B3Context);
46
- if (!context.initialized) {
47
- throw new Error("useB3 must be used within a B3Provider");
48
- }
49
- // Return a stable reference
50
- return useMemo(() => context, [context]);
51
- }
52
25
  // Create queryClient instance
53
26
  const queryClient = new QueryClient();
54
27
  /**
@@ -1,29 +1,6 @@
1
- import { PermissionsConfig } from "../../../global-account/types/permissions";
1
+ import { PermissionsConfig } from "../../../../global-account/types/permissions";
2
2
  import { Account } from "thirdweb/wallets";
3
- import { User } from "../../../global-account/types/b3-api.types";
4
- /**
5
- * Context type for B3Provider
6
- */
7
- export interface B3ContextType {
8
- account?: Account;
9
- user?: User;
10
- setAccount: (account: Account) => void;
11
- setUser: (user?: User) => void;
12
- initialized: boolean;
13
- ready: boolean;
14
- environment?: "development" | "production";
15
- defaultPermissions?: PermissionsConfig;
16
- theme: "light" | "dark";
17
- }
18
- /**
19
- * Context for B3 provider
20
- */
21
- export declare const B3Context: import("react").Context<B3ContextType>;
22
- /**
23
- * Hook to access the B3 context
24
- * @throws Error if used outside a B3Provider
25
- */
26
- export declare function useB3(): B3ContextType;
3
+ import { B3ContextType } from "./types";
27
4
  /**
28
5
  * Main B3Provider component
29
6
  */