@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.
- package/README.md +328 -230
- package/dist/cjs/anyspend/index.native.d.ts +13 -0
- package/dist/cjs/anyspend/index.native.js +35 -0
- package/dist/cjs/anyspend/react/components/AnySpend.d.ts +2 -1
- package/dist/cjs/anyspend/react/components/AnySpend.js +4 -4
- package/dist/cjs/anyspend/react/components/AnySpendBuySpin.d.ts +2 -1
- package/dist/cjs/anyspend/react/components/AnySpendBuySpin.js +123 -50
- package/dist/cjs/anyspend/react/components/common/OrderHistoryItem.js +5 -1
- package/dist/cjs/anyspend/react/components/common/TokenBalance.js +1 -1
- package/dist/cjs/anyspend/utils/chain.js +3 -0
- package/dist/cjs/global-account/react/components/B3DynamicModal.js +2 -2
- package/dist/cjs/global-account/react/components/{B3Provider.d.ts → B3Provider/B3Provider.d.ts} +3 -29
- package/dist/cjs/global-account/react/components/{B3Provider.js → B3Provider/B3Provider.js} +6 -34
- package/dist/cjs/global-account/react/components/{B3Provider.native.d.ts → B3Provider/B3Provider.native.d.ts} +2 -25
- package/dist/cjs/global-account/react/components/{B3Provider.native.js → B3Provider/B3Provider.native.js} +5 -28
- package/dist/cjs/global-account/react/components/B3Provider/types.d.ts +25 -0
- package/dist/cjs/global-account/react/components/B3Provider/types.js +20 -0
- package/dist/cjs/global-account/react/components/B3Provider/useB3.d.ts +5 -0
- package/dist/cjs/global-account/react/components/B3Provider/useB3.js +17 -0
- package/dist/cjs/global-account/react/components/StyleRoot.js +2 -2
- package/dist/cjs/global-account/react/components/index.d.ts +8 -6
- package/dist/cjs/global-account/react/components/index.js +18 -16
- package/dist/cjs/global-account/react/hooks/index.d.ts +1 -1
- package/dist/cjs/global-account/react/hooks/index.js +2 -1
- package/dist/cjs/global-account/react/hooks/useBestTransactionPath.js +3 -3
- package/dist/cjs/global-account/react/hooks/useTokenBalance.js +1 -1
- package/dist/cjs/global-account/react/index.native.d.ts +7 -0
- package/dist/cjs/global-account/react/index.native.js +21 -0
- package/dist/cjs/global-account/react/stores/useModalStore.d.ts +2 -0
- package/dist/cjs/global-account/types/chain-networks.d.ts +34 -34
- package/dist/cjs/global-account/types/feature-flags.d.ts +5 -5
- package/dist/cjs/shared/constants/chains/b3Chain.d.ts +1 -1
- package/dist/cjs/shared/constants/chains/supported.d.ts +8 -7
- package/dist/cjs/shared/constants/chains/supported.js +8 -1
- package/dist/cjs/shared/utils/chains.js +4 -0
- package/dist/cjs/shared/utils/number.js +1 -1
- package/dist/esm/anyspend/index.native.d.ts +13 -0
- package/dist/esm/anyspend/index.native.js +19 -0
- package/dist/esm/anyspend/react/components/AnySpend.d.ts +2 -1
- package/dist/esm/anyspend/react/components/AnySpend.js +4 -4
- package/dist/esm/anyspend/react/components/AnySpendBuySpin.d.ts +2 -1
- package/dist/esm/anyspend/react/components/AnySpendBuySpin.js +123 -50
- package/dist/esm/anyspend/react/components/common/OrderHistoryItem.js +5 -1
- package/dist/esm/anyspend/react/components/common/TokenBalance.js +1 -1
- package/dist/esm/anyspend/utils/chain.js +3 -0
- package/dist/esm/global-account/react/components/B3DynamicModal.js +1 -1
- package/dist/esm/global-account/react/components/{B3Provider.d.ts → B3Provider/B3Provider.d.ts} +3 -29
- package/dist/esm/global-account/react/components/{B3Provider.js → B3Provider/B3Provider.js} +5 -32
- package/dist/esm/global-account/react/components/{B3Provider.native.d.ts → B3Provider/B3Provider.native.d.ts} +2 -25
- package/dist/esm/global-account/react/components/{B3Provider.native.js → B3Provider/B3Provider.native.js} +5 -26
- package/dist/esm/global-account/react/components/B3Provider/types.d.ts +25 -0
- package/dist/esm/global-account/react/components/B3Provider/types.js +17 -0
- package/dist/esm/global-account/react/components/B3Provider/useB3.d.ts +5 -0
- package/dist/esm/global-account/react/components/B3Provider/useB3.js +14 -0
- package/dist/esm/global-account/react/components/StyleRoot.js +1 -1
- package/dist/esm/global-account/react/components/index.d.ts +8 -6
- package/dist/esm/global-account/react/components/index.js +7 -5
- package/dist/esm/global-account/react/hooks/index.d.ts +1 -1
- package/dist/esm/global-account/react/hooks/index.js +1 -1
- package/dist/esm/global-account/react/hooks/useBestTransactionPath.js +3 -3
- package/dist/esm/global-account/react/hooks/useTokenBalance.js +1 -1
- package/dist/esm/global-account/react/index.native.d.ts +7 -0
- package/dist/esm/global-account/react/index.native.js +11 -0
- package/dist/esm/global-account/react/stores/useModalStore.d.ts +2 -0
- package/dist/esm/global-account/types/chain-networks.d.ts +34 -34
- package/dist/esm/global-account/types/feature-flags.d.ts +5 -5
- package/dist/esm/shared/constants/chains/b3Chain.d.ts +1 -1
- package/dist/esm/shared/constants/chains/supported.d.ts +8 -7
- package/dist/esm/shared/constants/chains/supported.js +7 -0
- package/dist/esm/shared/utils/chains.js +4 -0
- package/dist/esm/shared/utils/number.js +1 -1
- package/dist/styles/index.css +1 -1
- package/dist/types/anyspend/index.native.d.ts +13 -0
- package/dist/types/anyspend/react/components/AnySpend.d.ts +2 -1
- package/dist/types/anyspend/react/components/AnySpendBuySpin.d.ts +2 -1
- package/dist/types/global-account/react/components/{B3Provider.d.ts → B3Provider/B3Provider.d.ts} +2 -28
- package/dist/types/global-account/react/components/{B3Provider.native.d.ts → B3Provider/B3Provider.native.d.ts} +1 -24
- package/dist/types/global-account/react/components/B3Provider/types.d.ts +25 -0
- package/dist/types/global-account/react/components/B3Provider/useB3.d.ts +5 -0
- package/dist/types/global-account/react/components/index.d.ts +8 -6
- package/dist/types/global-account/react/hooks/index.d.ts +1 -1
- package/dist/types/global-account/react/index.native.d.ts +7 -0
- package/dist/types/global-account/react/stores/useModalStore.d.ts +2 -0
- package/dist/types/global-account/types/chain-networks.d.ts +34 -34
- package/dist/types/global-account/types/feature-flags.d.ts +5 -5
- package/dist/types/shared/constants/chains/b3Chain.d.ts +1 -1
- package/dist/types/shared/constants/chains/supported.d.ts +8 -7
- package/package.json +26 -24
- package/src/anyspend/index.native.ts +24 -0
- package/src/anyspend/react/components/AnySpend.tsx +6 -5
- package/src/anyspend/react/components/AnySpendBuySpin.tsx +232 -179
- package/src/anyspend/react/components/common/OrderHistoryItem.tsx +5 -1
- package/src/anyspend/react/components/common/TokenBalance.tsx +1 -1
- package/src/anyspend/utils/chain.ts +3 -0
- package/src/global-account/react/components/B3DynamicModal.tsx +1 -1
- package/src/global-account/react/components/{B3Provider.native.tsx → B3Provider/B3Provider.native.tsx} +4 -45
- package/src/global-account/react/components/{B3Provider.tsx → B3Provider/B3Provider.tsx} +4 -53
- package/src/global-account/react/components/B3Provider/types.ts +40 -0
- package/src/global-account/react/components/B3Provider/useB3.ts +17 -0
- package/src/global-account/react/components/StyleRoot.tsx +1 -1
- package/src/global-account/react/components/index.ts +8 -6
- package/src/global-account/react/hooks/index.ts +1 -1
- package/src/global-account/react/hooks/useBestTransactionPath.tsx +3 -3
- package/src/global-account/react/hooks/useTokenBalance.tsx +1 -1
- package/src/global-account/react/index.native.ts +14 -0
- package/src/global-account/react/stores/useModalStore.ts +2 -0
- package/src/shared/constants/chains/supported.ts +12 -4
- package/src/shared/utils/chains.ts +4 -1
- package/src/shared/utils/number.ts +1 -1
- package/dist/cjs/styles/index.d.ts +0 -20
- package/dist/cjs/styles/index.js +0 -22
- package/dist/esm/styles/index.d.ts +0 -20
- package/dist/esm/styles/index.js +0 -20
- package/dist/types/styles/index.d.ts +0 -20
- package/src/styles/index.ts +0 -24
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { B3_TOKEN, OrderType } from "@b3dotfun/sdk/anyspend";
|
|
2
|
+
import { baseMainnet } from "@b3dotfun/sdk/shared/constants/chains/supported";
|
|
2
3
|
import { EthIcon } from "./icons/EthIcon";
|
|
3
4
|
import { SolIcon } from "./icons/SolIcon";
|
|
4
5
|
import { UsdcIcon } from "./icons/USDCIcon";
|
|
@@ -19,7 +20,6 @@ import { ArrowRight, Loader2 } from "lucide-react";
|
|
|
19
20
|
import { useCallback, useEffect, useState } from "react";
|
|
20
21
|
import { toast } from "sonner";
|
|
21
22
|
import { createPublicClient, encodeFunctionData, erc20Abi, formatUnits, http } from "viem";
|
|
22
|
-
import { base } from "viem/chains";
|
|
23
23
|
import { useAccount, useWaitForTransactionReceipt, useWriteContract } from "wagmi";
|
|
24
24
|
import { AnySpendCustom } from "./AnySpendCustom";
|
|
25
25
|
|
|
@@ -52,6 +52,20 @@ const SPIN_WHEEL_ABI = [
|
|
|
52
52
|
outputs: [],
|
|
53
53
|
stateMutability: "payable",
|
|
54
54
|
type: "function"
|
|
55
|
+
},
|
|
56
|
+
{
|
|
57
|
+
inputs: [],
|
|
58
|
+
name: "getWheelInfo",
|
|
59
|
+
outputs: [
|
|
60
|
+
{ internalType: "address", name: "creator_", type: "address" },
|
|
61
|
+
{ internalType: "uint256", name: "startTime_", type: "uint256" },
|
|
62
|
+
{ internalType: "uint256", name: "endTime_", type: "uint256" },
|
|
63
|
+
{ internalType: "uint256", name: "totalPrizesAvailable_", type: "uint256" },
|
|
64
|
+
{ internalType: "uint256", name: "prizesRequestedCount_", type: "uint256" },
|
|
65
|
+
{ internalType: "enum SpinWheelV2.WheelState", name: "state_", type: "uint8" }
|
|
66
|
+
],
|
|
67
|
+
stateMutability: "view",
|
|
68
|
+
type: "function"
|
|
55
69
|
}
|
|
56
70
|
] as const;
|
|
57
71
|
|
|
@@ -62,6 +76,37 @@ interface PaymentConfig {
|
|
|
62
76
|
entryModule: string;
|
|
63
77
|
}
|
|
64
78
|
|
|
79
|
+
interface WheelInfo {
|
|
80
|
+
creator_: string;
|
|
81
|
+
startTime_: bigint;
|
|
82
|
+
endTime_: bigint;
|
|
83
|
+
totalPrizesAvailable_: bigint;
|
|
84
|
+
prizesRequestedCount_: bigint;
|
|
85
|
+
state_: number;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
type WheelStatus = "not_started" | "active" | "ended" | "sold_out";
|
|
89
|
+
|
|
90
|
+
function getWheelStatus(wheelInfo: WheelInfo): WheelStatus {
|
|
91
|
+
const now = BigInt(Math.floor(Date.now() / 1000));
|
|
92
|
+
console.log("@@anyspend-buy-spin:now:", now);
|
|
93
|
+
console.log("@@anyspend-buy-spin:wheelInfo:", wheelInfo);
|
|
94
|
+
|
|
95
|
+
if (now < wheelInfo.startTime_) {
|
|
96
|
+
return "not_started";
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
if (now > wheelInfo.endTime_) {
|
|
100
|
+
return "ended";
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
if (wheelInfo.totalPrizesAvailable_ <= wheelInfo.prizesRequestedCount_) {
|
|
104
|
+
return "sold_out";
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
return "active";
|
|
108
|
+
}
|
|
109
|
+
|
|
65
110
|
function generateEncodedDataForBuyEntriesAndSpin(user: string, quantity: string): string {
|
|
66
111
|
invariant(BigInt(quantity) > 0, "Quantity must be greater than zero");
|
|
67
112
|
console.log("@@anyspend-buy-spin:encoded-data:", { user, quantity });
|
|
@@ -74,7 +119,7 @@ function generateEncodedDataForBuyEntriesAndSpin(user: string, quantity: string)
|
|
|
74
119
|
}
|
|
75
120
|
|
|
76
121
|
const basePublicClient = createPublicClient({
|
|
77
|
-
chain:
|
|
122
|
+
chain: baseMainnet,
|
|
78
123
|
transport: http()
|
|
79
124
|
});
|
|
80
125
|
|
|
@@ -85,6 +130,7 @@ export function AnySpendBuySpin({
|
|
|
85
130
|
spinwheelContractAddress,
|
|
86
131
|
chainId,
|
|
87
132
|
recipientAddress,
|
|
133
|
+
prefillQuantity,
|
|
88
134
|
onSuccess
|
|
89
135
|
}: {
|
|
90
136
|
isMainnet?: boolean;
|
|
@@ -93,6 +139,7 @@ export function AnySpendBuySpin({
|
|
|
93
139
|
spinwheelContractAddress: string;
|
|
94
140
|
chainId: number;
|
|
95
141
|
recipientAddress: string;
|
|
142
|
+
prefillQuantity?: string;
|
|
96
143
|
onSuccess?: (txHash?: string) => void;
|
|
97
144
|
}) {
|
|
98
145
|
const hasMounted = useHasMounted();
|
|
@@ -102,6 +149,7 @@ export function AnySpendBuySpin({
|
|
|
102
149
|
const [paymentConfig, setPaymentConfig] = useState<PaymentConfig | null>(null);
|
|
103
150
|
const [isLoadingConfig, setIsLoadingConfig] = useState(true);
|
|
104
151
|
const [configError, setConfigError] = useState<string>("");
|
|
152
|
+
const [wheelInfo, setWheelInfo] = useState<WheelInfo | null>(null);
|
|
105
153
|
|
|
106
154
|
// Fetch B3 token balance
|
|
107
155
|
const {
|
|
@@ -120,24 +168,34 @@ export function AnySpendBuySpin({
|
|
|
120
168
|
// State for direct buying flow (when user has B3 tokens)
|
|
121
169
|
const [isBuying, setIsBuying] = useState(false);
|
|
122
170
|
const [buyingTxHash, setBuyingTxHash] = useState<string>("");
|
|
123
|
-
const
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
171
|
+
const {
|
|
172
|
+
isLoading: isTxPending,
|
|
173
|
+
isSuccess: isTxSuccess,
|
|
174
|
+
isError: isTxError,
|
|
175
|
+
error: txError
|
|
176
|
+
} = useWaitForTransactionReceipt({
|
|
127
177
|
hash: buyingTxHash as `0x${string}`,
|
|
128
178
|
query: {
|
|
129
179
|
structuralSharing: false
|
|
130
180
|
}
|
|
131
181
|
});
|
|
132
182
|
|
|
133
|
-
//
|
|
183
|
+
// Handle transaction status
|
|
134
184
|
useEffect(() => {
|
|
135
|
-
if (
|
|
136
|
-
|
|
137
|
-
|
|
185
|
+
if (!buyingTxHash) return;
|
|
186
|
+
|
|
187
|
+
if (isTxSuccess) {
|
|
188
|
+
setB3ModalOpen(false);
|
|
189
|
+
onSuccess?.(buyingTxHash);
|
|
190
|
+
toast.success("Spin purchase transaction confirmed!");
|
|
191
|
+
setIsBuying(false);
|
|
192
|
+
} else if (isTxError) {
|
|
193
|
+
console.error("@@anyspend-buy-spin:tx-error:", txError);
|
|
194
|
+
toast.error("Transaction failed. Please try again.");
|
|
195
|
+
setB3ModalOpen(false);
|
|
138
196
|
setIsBuying(false);
|
|
139
197
|
}
|
|
140
|
-
}, [isTxSuccess, buyingTxHash]);
|
|
198
|
+
}, [isTxSuccess, isTxError, buyingTxHash, onSuccess, setB3ModalOpen, txError]);
|
|
141
199
|
|
|
142
200
|
// Spin quantity state
|
|
143
201
|
const [userSpinQuantity, setUserSpinQuantity] = useState<string>("");
|
|
@@ -146,12 +204,21 @@ export function AnySpendBuySpin({
|
|
|
146
204
|
const [validationError, setValidationError] = useState<string>("");
|
|
147
205
|
const [displayQuantity, setDisplayQuantity] = useState<string>("");
|
|
148
206
|
const [debouncedQuantity, setDebouncedQuantity] = useState<string>("");
|
|
207
|
+
const [debouncedUserSpinQuantity, setDebouncedUserSpinQuantity] = useState<string>("");
|
|
208
|
+
|
|
209
|
+
useEffect(() => {
|
|
210
|
+
if (prefillQuantity && wheelInfo) {
|
|
211
|
+
const remainingSpins = wheelInfo.totalPrizesAvailable_ - wheelInfo.prizesRequestedCount_;
|
|
212
|
+
const adjustedQuantity = BigInt(prefillQuantity) > remainingSpins ? remainingSpins.toString() : prefillQuantity;
|
|
213
|
+
validateAndSetQuantity(adjustedQuantity);
|
|
214
|
+
}
|
|
215
|
+
}, [prefillQuantity, wheelInfo]);
|
|
149
216
|
|
|
150
217
|
// Calculate total cost
|
|
151
218
|
const totalCost =
|
|
152
219
|
paymentConfig && userSpinQuantity ? paymentConfig.pricePerEntry * BigInt(userSpinQuantity) : BigInt(0);
|
|
153
220
|
|
|
154
|
-
// Fetch payment configuration
|
|
221
|
+
// Fetch payment configuration and wheel info
|
|
155
222
|
const fetchPaymentConfig = useCallback(async () => {
|
|
156
223
|
if (!basePublicClient || !spinwheelContractAddress) return;
|
|
157
224
|
|
|
@@ -161,7 +228,7 @@ export function AnySpendBuySpin({
|
|
|
161
228
|
|
|
162
229
|
console.log("@@anyspend-buy-spin:fetch-config:", { spinwheelContractAddress, chainId });
|
|
163
230
|
|
|
164
|
-
const [config, entryModuleAddress] = await Promise.all([
|
|
231
|
+
const [config, entryModuleAddress, wheelInfo] = await Promise.all([
|
|
165
232
|
basePublicClient.readContract({
|
|
166
233
|
address: spinwheelContractAddress as `0x${string}`,
|
|
167
234
|
abi: SPIN_WHEEL_ABI,
|
|
@@ -171,6 +238,11 @@ export function AnySpendBuySpin({
|
|
|
171
238
|
address: spinwheelContractAddress as `0x${string}`,
|
|
172
239
|
abi: SPIN_WHEEL_ABI,
|
|
173
240
|
functionName: "entryModule"
|
|
241
|
+
}),
|
|
242
|
+
basePublicClient.readContract({
|
|
243
|
+
address: spinwheelContractAddress as `0x${string}`,
|
|
244
|
+
abi: SPIN_WHEEL_ABI,
|
|
245
|
+
functionName: "getWheelInfo"
|
|
174
246
|
})
|
|
175
247
|
]);
|
|
176
248
|
|
|
@@ -181,13 +253,17 @@ export function AnySpendBuySpin({
|
|
|
181
253
|
entryModule: entryModuleAddress
|
|
182
254
|
};
|
|
183
255
|
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
256
|
+
const wheelInfoData: WheelInfo = {
|
|
257
|
+
creator_: wheelInfo[0],
|
|
258
|
+
startTime_: wheelInfo[1],
|
|
259
|
+
endTime_: wheelInfo[2],
|
|
260
|
+
totalPrizesAvailable_: wheelInfo[3],
|
|
261
|
+
prizesRequestedCount_: wheelInfo[4],
|
|
262
|
+
state_: wheelInfo[5]
|
|
263
|
+
};
|
|
264
|
+
|
|
190
265
|
setPaymentConfig(paymentConfig);
|
|
266
|
+
setWheelInfo(wheelInfoData);
|
|
191
267
|
} catch (error) {
|
|
192
268
|
console.error("@@anyspend-buy-spin:config-error:", error);
|
|
193
269
|
setConfigError("Failed to load spin wheel configuration");
|
|
@@ -206,6 +282,7 @@ export function AnySpendBuySpin({
|
|
|
206
282
|
useEffect(() => {
|
|
207
283
|
const timer = setTimeout(() => {
|
|
208
284
|
setDebouncedQuantity(displayQuantity);
|
|
285
|
+
setDebouncedUserSpinQuantity(userSpinQuantity);
|
|
209
286
|
}, 500);
|
|
210
287
|
|
|
211
288
|
return () => clearTimeout(timer);
|
|
@@ -245,6 +322,16 @@ export function AnySpendBuySpin({
|
|
|
245
322
|
return;
|
|
246
323
|
}
|
|
247
324
|
|
|
325
|
+
// Check if quantity exceeds remaining entries
|
|
326
|
+
if (wheelInfo && BigInt(numValue) > wheelInfo.totalPrizesAvailable_ - wheelInfo.prizesRequestedCount_) {
|
|
327
|
+
setIsQuantityValid(false);
|
|
328
|
+
setUserSpinQuantity("");
|
|
329
|
+
setValidationError(
|
|
330
|
+
`Only ${(wheelInfo.totalPrizesAvailable_ - wheelInfo.prizesRequestedCount_).toString()} spins remaining`
|
|
331
|
+
);
|
|
332
|
+
return;
|
|
333
|
+
}
|
|
334
|
+
|
|
248
335
|
setUserSpinQuantity(value);
|
|
249
336
|
setIsQuantityValid(true);
|
|
250
337
|
setValidationError("");
|
|
@@ -299,7 +386,7 @@ export function AnySpendBuySpin({
|
|
|
299
386
|
} catch (error) {
|
|
300
387
|
console.error("@@anyspend-buy-spin:error:", error);
|
|
301
388
|
toast.error("Spin purchase failed. Please try again.");
|
|
302
|
-
|
|
389
|
+
setB3ModalOpen(false);
|
|
303
390
|
} finally {
|
|
304
391
|
setIsBuying(false);
|
|
305
392
|
}
|
|
@@ -378,6 +465,40 @@ export function AnySpendBuySpin({
|
|
|
378
465
|
// Render quantity input prompt
|
|
379
466
|
if (showAmountPrompt) {
|
|
380
467
|
const pricePerEntry = formatUnits(paymentConfig.pricePerEntry, 18);
|
|
468
|
+
const remainingEntries = wheelInfo ? wheelInfo.totalPrizesAvailable_ - wheelInfo.prizesRequestedCount_ : 0n;
|
|
469
|
+
const wheelStatus = wheelInfo ? getWheelStatus(wheelInfo) : null;
|
|
470
|
+
const isSoldOut = wheelStatus === "sold_out";
|
|
471
|
+
const isActive = wheelStatus === "active";
|
|
472
|
+
|
|
473
|
+
const getStatusMessage = () => {
|
|
474
|
+
if (!wheelInfo) return null;
|
|
475
|
+
|
|
476
|
+
const formatDate = (timestamp: bigint) => {
|
|
477
|
+
return new Date(Number(timestamp) * 1000).toLocaleString();
|
|
478
|
+
};
|
|
479
|
+
|
|
480
|
+
switch (wheelStatus) {
|
|
481
|
+
case "not_started":
|
|
482
|
+
return {
|
|
483
|
+
title: "Spin Wheel Not Started",
|
|
484
|
+
message: `Starts at ${formatDate(wheelInfo.startTime_)}`
|
|
485
|
+
};
|
|
486
|
+
case "ended":
|
|
487
|
+
return {
|
|
488
|
+
title: "Spin Wheel Ended",
|
|
489
|
+
message: `Ended at ${formatDate(wheelInfo.endTime_)}`
|
|
490
|
+
};
|
|
491
|
+
case "sold_out":
|
|
492
|
+
return {
|
|
493
|
+
title: "All Spins Have Been Claimed",
|
|
494
|
+
message: "Stay tuned for the next spin wheel event!"
|
|
495
|
+
};
|
|
496
|
+
default:
|
|
497
|
+
return null;
|
|
498
|
+
}
|
|
499
|
+
};
|
|
500
|
+
|
|
501
|
+
const statusInfo = getStatusMessage();
|
|
381
502
|
|
|
382
503
|
return (
|
|
383
504
|
<StyleRoot>
|
|
@@ -391,7 +512,7 @@ export function AnySpendBuySpin({
|
|
|
391
512
|
filter: hasMounted ? "blur(0px)" : "blur(10px)"
|
|
392
513
|
}}
|
|
393
514
|
transition={{ duration: 0.3, delay: 0, ease: "easeInOut" }}
|
|
394
|
-
className="mb-4
|
|
515
|
+
className={`flex justify-center ${isActive ? "mb-4" : ""}`}
|
|
395
516
|
>
|
|
396
517
|
<img
|
|
397
518
|
alt="B3 Token"
|
|
@@ -413,15 +534,33 @@ export function AnySpendBuySpin({
|
|
|
413
534
|
transition={{ duration: 0.3, delay: 0.1, ease: "easeInOut" }}
|
|
414
535
|
className="text-center"
|
|
415
536
|
>
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
537
|
+
{isActive ? (
|
|
538
|
+
<>
|
|
539
|
+
<h2 className="font-sf-rounded text-as-primary mb-4 text-2xl font-bold">
|
|
540
|
+
{(() => {
|
|
541
|
+
const hasEnoughBalance = b3RawBalance && totalCost <= b3RawBalance;
|
|
542
|
+
return hasEnoughBalance || !debouncedQuantity ? "Buy Spins" : `Swap & Buy Spins`;
|
|
543
|
+
})()}
|
|
544
|
+
</h2>
|
|
545
|
+
{wheelInfo && (
|
|
546
|
+
<div className="inline-flex items-center gap-2">
|
|
547
|
+
<div className="bg-as-brand/10 border-as-brand/10 inline-flex items-center rounded-full border px-3 py-1">
|
|
548
|
+
<p className="text-as-brand text-sm font-medium">{pricePerEntry} $B3 per spin</p>
|
|
549
|
+
</div>
|
|
550
|
+
<div className="bg-as-brand/10 border-as-brand/10 inline-flex items-center rounded-full border px-3 py-1">
|
|
551
|
+
<p className="text-as-brand text-sm font-medium">{remainingEntries.toString()} remaining</p>
|
|
552
|
+
</div>
|
|
553
|
+
</div>
|
|
554
|
+
)}
|
|
555
|
+
</>
|
|
556
|
+
) : (
|
|
557
|
+
statusInfo && (
|
|
558
|
+
<div className="text-center">
|
|
559
|
+
<p className="text-as-primary text-lg font-semibold">{statusInfo.title}</p>
|
|
560
|
+
<p className="text-as-primary/70 mt-2 text-sm">{statusInfo.message}</p>
|
|
561
|
+
</div>
|
|
562
|
+
)
|
|
563
|
+
)}
|
|
425
564
|
</motion.div>
|
|
426
565
|
</div>
|
|
427
566
|
|
|
@@ -435,163 +574,77 @@ export function AnySpendBuySpin({
|
|
|
435
574
|
transition={{ duration: 0.3, delay: 0.2, ease: "easeInOut" }}
|
|
436
575
|
className="bg-b3-react-background w-full p-6"
|
|
437
576
|
>
|
|
438
|
-
|
|
439
|
-
<div className="
|
|
440
|
-
<
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
577
|
+
{isActive ? (
|
|
578
|
+
<div className="space-y-4">
|
|
579
|
+
<div className="flex items-center justify-between">
|
|
580
|
+
<p className="text-as-primary/70 text-sm font-medium">Number of spins</p>
|
|
581
|
+
<span className="text-as-primary/50 flex items-center gap-1 text-sm">
|
|
582
|
+
Available: {isBalanceLoading ? <Loader2 className="h-3 w-3 animate-spin" /> : `${b3Balance} B3`}
|
|
583
|
+
</span>
|
|
584
|
+
</div>
|
|
445
585
|
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
586
|
+
<div className="relative">
|
|
587
|
+
<Input
|
|
588
|
+
onFocus={onFocusQuantityInput}
|
|
589
|
+
type="text"
|
|
590
|
+
placeholder="1"
|
|
591
|
+
value={displayQuantity}
|
|
592
|
+
onChange={e => validateAndSetQuantity(e.target.value)}
|
|
593
|
+
className={`h-14 px-4 pr-20 text-lg ${!isQuantityValid && displayQuantity ? "border-as-red" : "border-b3-react-border"}`}
|
|
594
|
+
/>
|
|
595
|
+
<div className="font-pack absolute right-4 top-1/2 -translate-y-1/2 text-lg font-medium text-blue-500/70">
|
|
596
|
+
{displayQuantity === "1" ? "Spin" : "Spins"}
|
|
597
|
+
</div>
|
|
457
598
|
</div>
|
|
458
|
-
</div>
|
|
459
599
|
|
|
460
|
-
|
|
600
|
+
{!isQuantityValid && displayQuantity && <p className="text-as-red text-sm">{validationError}</p>}
|
|
461
601
|
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
602
|
+
<div className="bg-as-on-surface-2/30 rounded-lg border border-white/10 p-4 backdrop-blur-sm">
|
|
603
|
+
<div className="flex items-center justify-between">
|
|
604
|
+
<span className="text-as-primary/70 text-sm font-medium">Total Cost:</span>
|
|
605
|
+
<div className="flex items-center gap-2">
|
|
606
|
+
<span className="text-as-primary text-lg font-bold">
|
|
607
|
+
{displayQuantity && isQuantityValid ? formatUnits(totalCost, 18) : "0"} B3
|
|
608
|
+
</span>
|
|
609
|
+
</div>
|
|
469
610
|
</div>
|
|
470
611
|
</div>
|
|
471
|
-
</div>
|
|
472
|
-
</div>
|
|
473
|
-
|
|
474
|
-
<div className="mt-4">
|
|
475
|
-
{(() => {
|
|
476
|
-
const hasEnoughBalance = b3RawBalance && totalCost <= b3RawBalance;
|
|
477
|
-
|
|
478
|
-
if (!hasEnoughBalance && debouncedQuantity) {
|
|
479
|
-
return (
|
|
480
|
-
<div className="bg-as-brand/10 flex flex-col items-center gap-2 rounded-lg p-4 pb-5">
|
|
481
|
-
<div className="flex items-center justify-center gap-2">
|
|
482
|
-
<span className="text-as-primary text-sm font-semibold">Swap & buy from any token</span>
|
|
483
|
-
<TextLoop>
|
|
484
|
-
<EthIcon className="h-8 w-8" />
|
|
485
|
-
<SolIcon className="h-8 w-8" />
|
|
486
|
-
<UsdcIcon className="h-8 w-8" />
|
|
487
|
-
</TextLoop>
|
|
488
|
-
<ArrowRight className="text-as-primary h-4 w-4" />
|
|
489
|
-
<img src="https://cdn.b3.fun/b3-coin-3d.png" className="h-7 w-7" alt="B3 Token" />
|
|
490
|
-
</div>
|
|
491
|
-
<p className="text-as-primary/50 text-sm font-medium">
|
|
492
|
-
No problem, we'll help you swap to B3 for your spins!
|
|
493
|
-
</p>
|
|
494
|
-
</div>
|
|
495
|
-
);
|
|
496
|
-
}
|
|
497
|
-
})()}
|
|
498
|
-
</div>
|
|
499
|
-
|
|
500
|
-
<Button
|
|
501
|
-
onClick={confirmQuantity}
|
|
502
|
-
disabled={!isQuantityValid || !displayQuantity || isBuying || isTxPending}
|
|
503
|
-
className="bg-as-brand hover:bg-as-brand/90 text-as-primary mt-4 h-14 w-full rounded-xl text-lg font-medium"
|
|
504
|
-
>
|
|
505
|
-
{isBuying ? "Buying..." : isTxPending ? "Confirming..." : "Continue"}
|
|
506
|
-
</Button>
|
|
507
|
-
</motion.div>
|
|
508
|
-
</div>
|
|
509
|
-
</StyleRoot>
|
|
510
|
-
);
|
|
511
|
-
}
|
|
512
612
|
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
className="size-full shrink-0 bg-transparent text-transparent"
|
|
539
|
-
src="https://cdn.b3.fun/b3-coin-3d.png"
|
|
540
|
-
/>
|
|
541
|
-
<div className="absolute inset-0 rounded-[50%] border border-white/20"></div>
|
|
542
|
-
</GlareCardRounded>
|
|
543
|
-
</motion.div>
|
|
544
|
-
<motion.div
|
|
545
|
-
initial={false}
|
|
546
|
-
animate={{
|
|
547
|
-
opacity: hasMounted ? 1 : 0,
|
|
548
|
-
y: hasMounted ? 0 : 20,
|
|
549
|
-
filter: hasMounted ? "blur(0px)" : "blur(10px)"
|
|
550
|
-
}}
|
|
551
|
-
transition={{ duration: 0.3, delay: 0.1, ease: "easeInOut" }}
|
|
552
|
-
className="text-center"
|
|
553
|
-
>
|
|
554
|
-
<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">
|
|
555
|
-
🎉 Purchase Complete!
|
|
556
|
-
</h2>
|
|
557
|
-
<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">
|
|
558
|
-
<span className="text-as-primary/80 text-sm font-medium">
|
|
559
|
-
{userSpinQuantity} Spin{userSpinQuantity !== "1" ? "s" : ""} • {formatUnits(totalCost, 18)} B3
|
|
560
|
-
</span>
|
|
561
|
-
</div>
|
|
562
|
-
</motion.div>
|
|
563
|
-
</div>
|
|
613
|
+
<div className="mt-4">
|
|
614
|
+
{(() => {
|
|
615
|
+
const hasEnoughBalance = b3RawBalance && totalCost <= b3RawBalance;
|
|
616
|
+
|
|
617
|
+
if (!hasEnoughBalance && debouncedQuantity) {
|
|
618
|
+
return (
|
|
619
|
+
<div className="bg-as-brand/10 flex flex-col items-center gap-2 rounded-lg p-4 pb-5">
|
|
620
|
+
<div className="flex items-center justify-center gap-2">
|
|
621
|
+
<span className="text-as-primary text-sm font-semibold">Swap & buy from any token</span>
|
|
622
|
+
<TextLoop>
|
|
623
|
+
<EthIcon className="h-8 w-8" />
|
|
624
|
+
<SolIcon className="h-8 w-8" />
|
|
625
|
+
<UsdcIcon className="h-8 w-8" />
|
|
626
|
+
</TextLoop>
|
|
627
|
+
<ArrowRight className="text-as-primary h-4 w-4" />
|
|
628
|
+
<img src="https://cdn.b3.fun/b3-coin-3d.png" className="h-7 w-7" alt="B3 Token" />
|
|
629
|
+
</div>
|
|
630
|
+
<p className="text-as-primary/50 text-sm font-medium">
|
|
631
|
+
No problem, we'll help you swap to B3 for your spins!
|
|
632
|
+
</p>
|
|
633
|
+
</div>
|
|
634
|
+
);
|
|
635
|
+
}
|
|
636
|
+
})()}
|
|
637
|
+
</div>
|
|
564
638
|
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
>
|
|
575
|
-
<div className="mb-6">
|
|
576
|
-
<a
|
|
577
|
-
href={`https://basescan.org/tx/${buyingTxHash}`}
|
|
578
|
-
target="_blank"
|
|
579
|
-
rel="noopener noreferrer"
|
|
580
|
-
className="text-as-primary/70 hover:text-as-primary block break-all text-center font-mono text-sm underline transition-colors"
|
|
581
|
-
>
|
|
582
|
-
View transaction
|
|
583
|
-
</a>
|
|
584
|
-
</div>
|
|
585
|
-
|
|
586
|
-
<Button
|
|
587
|
-
onClick={() => {
|
|
588
|
-
setB3ModalOpen(false);
|
|
589
|
-
onSuccess?.(buyingTxHash);
|
|
590
|
-
}}
|
|
591
|
-
className="bg-as-brand hover:bg-as-brand/90 text-as-primary h-14 w-full rounded-xl text-lg font-medium"
|
|
592
|
-
>
|
|
593
|
-
Done
|
|
594
|
-
</Button>
|
|
639
|
+
<Button
|
|
640
|
+
onClick={confirmQuantity}
|
|
641
|
+
disabled={!isQuantityValid || !displayQuantity || isBuying || isTxPending}
|
|
642
|
+
className="bg-as-brand hover:bg-as-brand/90 text-as-primary mt-4 h-14 w-full rounded-xl text-lg font-medium"
|
|
643
|
+
>
|
|
644
|
+
{isBuying ? "Buying..." : isTxPending ? "Confirming..." : "Continue"}
|
|
645
|
+
</Button>
|
|
646
|
+
</div>
|
|
647
|
+
) : null}
|
|
595
648
|
</motion.div>
|
|
596
649
|
</div>
|
|
597
650
|
</StyleRoot>
|
|
@@ -155,7 +155,11 @@ export function OrderHistoryItem({ order, onSelectOrder, mode }: OrderHistoryIte
|
|
|
155
155
|
<img src={dstToken.metadata.logoURI} alt={dstToken.symbol} className="h-6 w-6 rounded-full" />
|
|
156
156
|
<div className="text-as-primary overflow-hidden text-ellipsis whitespace-nowrap text-xl font-semibold">
|
|
157
157
|
{formatTokenAmount(
|
|
158
|
-
actualDstAmount
|
|
158
|
+
actualDstAmount
|
|
159
|
+
? BigInt(actualDstAmount)
|
|
160
|
+
: expectedDstAmount
|
|
161
|
+
? BigInt(expectedDstAmount)
|
|
162
|
+
: BigInt(0),
|
|
159
163
|
dstToken.decimals
|
|
160
164
|
)}{" "}
|
|
161
165
|
{dstToken.symbol}
|
|
@@ -21,7 +21,7 @@ export function TokenBalance({
|
|
|
21
21
|
|
|
22
22
|
// Calculate the amount based on percentage of balance
|
|
23
23
|
// Multiply first, then divide to avoid BigInt truncation
|
|
24
|
-
const amount = percentage === 100 ? rawBalance : (rawBalance * BigInt(percentage)) /
|
|
24
|
+
const amount = percentage === 100 ? rawBalance : (rawBalance * BigInt(percentage)) / BigInt(100);
|
|
25
25
|
|
|
26
26
|
onChangeInput(formatUnits(amount, token.decimals));
|
|
27
27
|
};
|
|
@@ -311,6 +311,9 @@ export function getPaymentUrl(address: string, amount: bigint, currency: string)
|
|
|
311
311
|
}
|
|
312
312
|
|
|
313
313
|
export function getExplorerTxUrl(chainId: number, txHash: string) {
|
|
314
|
+
if (chainId === b3.id) {
|
|
315
|
+
return "https://explorer.b3.fun/b3/tx/" + txHash;
|
|
316
|
+
}
|
|
314
317
|
if (EVM_CHAINS[chainId]) {
|
|
315
318
|
return EVM_CHAINS[chainId].viem.blockExplorers?.default.url + "/tx/" + txHash;
|
|
316
319
|
}
|
|
@@ -8,7 +8,7 @@ import {
|
|
|
8
8
|
} from "@b3dotfun/sdk/anyspend/react";
|
|
9
9
|
import { useIsMobile, useModalStore } from "@b3dotfun/sdk/global-account/react";
|
|
10
10
|
import { debugB3React } from "@b3dotfun/sdk/shared/utils/debug";
|
|
11
|
-
import { useB3 } from "./B3Provider";
|
|
11
|
+
import { useB3 } from "./B3Provider/useB3";
|
|
12
12
|
import { ManageAccount } from "./ManageAccount/ManageAccount";
|
|
13
13
|
import { RequestPermissions } from "./RequestPermissions/RequestPermissions";
|
|
14
14
|
import { SignInWithB3Flow } from "./SignInWithB3/SignInWithB3Flow";
|