access-layers-wallet 1.0.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.
package/dist/index.mjs ADDED
@@ -0,0 +1,3346 @@
1
+ "use client";
2
+ var __defProp = Object.defineProperty;
3
+ var __defProps = Object.defineProperties;
4
+ var __getOwnPropDescs = Object.getOwnPropertyDescriptors;
5
+ var __getOwnPropSymbols = Object.getOwnPropertySymbols;
6
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
7
+ var __propIsEnum = Object.prototype.propertyIsEnumerable;
8
+ var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
9
+ var __spreadValues = (a, b) => {
10
+ for (var prop in b || (b = {}))
11
+ if (__hasOwnProp.call(b, prop))
12
+ __defNormalProp(a, prop, b[prop]);
13
+ if (__getOwnPropSymbols)
14
+ for (var prop of __getOwnPropSymbols(b)) {
15
+ if (__propIsEnum.call(b, prop))
16
+ __defNormalProp(a, prop, b[prop]);
17
+ }
18
+ return a;
19
+ };
20
+ var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b));
21
+ var __objRest = (source, exclude) => {
22
+ var target = {};
23
+ for (var prop in source)
24
+ if (__hasOwnProp.call(source, prop) && exclude.indexOf(prop) < 0)
25
+ target[prop] = source[prop];
26
+ if (source != null && __getOwnPropSymbols)
27
+ for (var prop of __getOwnPropSymbols(source)) {
28
+ if (exclude.indexOf(prop) < 0 && __propIsEnum.call(source, prop))
29
+ target[prop] = source[prop];
30
+ }
31
+ return target;
32
+ };
33
+
34
+ // src/components/ConnectWalletHandler.tsx
35
+ import { useEffect as useEffect2, useState as useState2, useCallback as useCallback2 } from "react";
36
+
37
+ // components/ui/dialog.tsx
38
+ import * as React from "react";
39
+ import * as DialogPrimitive from "@radix-ui/react-dialog";
40
+ import { X } from "lucide-react";
41
+
42
+ // lib/utils.ts
43
+ import { clsx } from "clsx";
44
+ import { twMerge } from "tailwind-merge";
45
+ function cn(...inputs) {
46
+ return twMerge(clsx(inputs));
47
+ }
48
+
49
+ // components/ui/dialog.tsx
50
+ import { jsx, jsxs } from "react/jsx-runtime";
51
+ var Dialog = DialogPrimitive.Root;
52
+ var DialogPortal = DialogPrimitive.Portal;
53
+ var DialogOverlay = React.forwardRef((_a, ref) => {
54
+ var _b = _a, { className } = _b, props = __objRest(_b, ["className"]);
55
+ return /* @__PURE__ */ jsx(DialogPortal, { children: /* @__PURE__ */ jsx(
56
+ DialogPrimitive.Overlay,
57
+ __spreadValues({
58
+ ref,
59
+ className: cn(
60
+ "fixed inset-0 z-50 bg-black/80 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0",
61
+ className
62
+ )
63
+ }, props)
64
+ ) });
65
+ });
66
+ DialogOverlay.displayName = DialogPrimitive.Overlay.displayName;
67
+ var DialogContent = React.forwardRef((_a, ref) => {
68
+ var _b = _a, { className, children } = _b, props = __objRest(_b, ["className", "children"]);
69
+ return /* @__PURE__ */ jsxs(DialogPortal, { children: [
70
+ /* @__PURE__ */ jsx(DialogOverlay, {}),
71
+ /* @__PURE__ */ jsxs(
72
+ DialogPrimitive.Content,
73
+ __spreadProps(__spreadValues({
74
+ ref,
75
+ className: cn(
76
+ "fixed left-[50%] top-[50%] z-50 grid w-full max-w-lg translate-x-[-50%] translate-y-[-50%] gap-4 border bg-background p-6 shadow-lg duration-200 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[state=closed]:slide-out-to-left-1/2 data-[state=closed]:slide-out-to-top-[48%] data-[state=open]:slide-in-from-left-1/2 data-[state=open]:slide-in-from-top-[48%] sm:rounded-lg",
77
+ className
78
+ )
79
+ }, props), {
80
+ children: [
81
+ children,
82
+ /* @__PURE__ */ jsxs(DialogPrimitive.Close, { className: "absolute right-4 top-4 rounded-sm opacity-70 ring-offset-background transition-opacity hover:opacity-100 focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 disabled:pointer-events-none data-[state=open]:bg-accent data-[state=open]:text-muted-foreground", children: [
83
+ /* @__PURE__ */ jsx(X, { className: "h-4 w-4" }),
84
+ /* @__PURE__ */ jsx("span", { className: "sr-only", children: "Close" })
85
+ ] })
86
+ ]
87
+ })
88
+ )
89
+ ] });
90
+ });
91
+ DialogContent.displayName = DialogPrimitive.Content.displayName;
92
+ var DialogHeader = (_a) => {
93
+ var _b = _a, {
94
+ className
95
+ } = _b, props = __objRest(_b, [
96
+ "className"
97
+ ]);
98
+ return /* @__PURE__ */ jsx(
99
+ "div",
100
+ __spreadValues({
101
+ className: cn(
102
+ "flex flex-col space-y-1.5 text-center sm:text-left",
103
+ className
104
+ )
105
+ }, props)
106
+ );
107
+ };
108
+ DialogHeader.displayName = "DialogHeader";
109
+ var DialogFooter = (_a) => {
110
+ var _b = _a, {
111
+ className
112
+ } = _b, props = __objRest(_b, [
113
+ "className"
114
+ ]);
115
+ return /* @__PURE__ */ jsx(
116
+ "div",
117
+ __spreadValues({
118
+ className: cn(
119
+ "flex flex-col-reverse sm:flex-row sm:justify-end sm:space-x-2",
120
+ className
121
+ )
122
+ }, props)
123
+ );
124
+ };
125
+ DialogFooter.displayName = "DialogFooter";
126
+ var DialogTitle = React.forwardRef((_a, ref) => {
127
+ var _b = _a, { className } = _b, props = __objRest(_b, ["className"]);
128
+ return /* @__PURE__ */ jsx(
129
+ DialogPrimitive.Title,
130
+ __spreadValues({
131
+ ref,
132
+ className: cn(
133
+ "text-lg font-semibold leading-none tracking-tight",
134
+ className
135
+ )
136
+ }, props)
137
+ );
138
+ });
139
+ DialogTitle.displayName = DialogPrimitive.Title.displayName;
140
+ var DialogDescription = React.forwardRef((_a, ref) => {
141
+ var _b = _a, { className } = _b, props = __objRest(_b, ["className"]);
142
+ return /* @__PURE__ */ jsx(
143
+ DialogPrimitive.Description,
144
+ __spreadValues({
145
+ ref,
146
+ className: cn("text-sm text-muted-foreground", className)
147
+ }, props)
148
+ );
149
+ });
150
+ DialogDescription.displayName = DialogPrimitive.Description.displayName;
151
+
152
+ // src/components/ConnectWalletHandler.tsx
153
+ import { VisuallyHidden } from "@radix-ui/react-visually-hidden";
154
+ import { toast as toast2 } from "sonner";
155
+
156
+ // components/ui/button.tsx
157
+ import * as React2 from "react";
158
+ import { Slot } from "@radix-ui/react-slot";
159
+ import { cva } from "class-variance-authority";
160
+ import { jsx as jsx2 } from "react/jsx-runtime";
161
+ var buttonVariants = cva(
162
+ "inline-flex items-center justify-center whitespace-nowrap rounded-md text-sm font-medium ring-offset-background transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50",
163
+ {
164
+ variants: {
165
+ variant: {
166
+ default: "bg-primary text-primary-foreground hover:bg-primary/90",
167
+ destructive: "bg-destructive text-destructive-foreground hover:bg-destructive/90",
168
+ outline: "border border-input bg-background hover:bg-accent hover:text-accent-foreground",
169
+ secondary: "bg-secondary text-secondary-foreground hover:bg-secondary/80",
170
+ ghost: "hover:bg-accent hover:text-accent-foreground",
171
+ link: "text-primary underline-offset-4 hover:underline"
172
+ },
173
+ size: {
174
+ default: "h-10 px-4 py-2",
175
+ sm: "h-9 rounded-md px-3",
176
+ lg: "h-11 rounded-md px-8",
177
+ icon: "h-10 w-10"
178
+ }
179
+ },
180
+ defaultVariants: {
181
+ variant: "default",
182
+ size: "default"
183
+ }
184
+ }
185
+ );
186
+ var Button = React2.forwardRef(
187
+ (_a, ref) => {
188
+ var _b = _a, { className, variant, size, asChild = false } = _b, props = __objRest(_b, ["className", "variant", "size", "asChild"]);
189
+ const Comp = asChild ? Slot : "button";
190
+ return /* @__PURE__ */ jsx2(
191
+ Comp,
192
+ __spreadValues({
193
+ className: cn(buttonVariants({ variant, size, className })),
194
+ ref
195
+ }, props)
196
+ );
197
+ }
198
+ );
199
+ Button.displayName = "Button";
200
+
201
+ // src/components/ConnectWalletHandler.tsx
202
+ import { motion } from "framer-motion";
203
+ import {
204
+ Loader2,
205
+ X as X2,
206
+ ExternalLink
207
+ } from "lucide-react";
208
+
209
+ // hooks/useSupraMultiWallet.ts
210
+ import { useState, useEffect, useCallback } from "react";
211
+ import nacl from "tweetnacl";
212
+ import { useRouter } from "next/navigation";
213
+ import { toast } from "sonner";
214
+ import {
215
+ SupraChainId,
216
+ initSdk
217
+ } from "ribbit-wallet-connect";
218
+
219
+ // lib/logger.ts
220
+ var Logger = class {
221
+ constructor() {
222
+ this.isDevelopment = process.env.NODE_ENV === "development";
223
+ }
224
+ log(level, message, context, error) {
225
+ if (!this.isDevelopment && level === "debug") {
226
+ return;
227
+ }
228
+ const entry = {
229
+ level,
230
+ message,
231
+ timestamp: Date.now(),
232
+ context,
233
+ error
234
+ };
235
+ const logMethod = level === "error" ? console.error : level === "warn" ? console.warn : console.log;
236
+ if (error) {
237
+ logMethod(`[${level.toUpperCase()}] ${message}`, __spreadProps(__spreadValues({}, context), {
238
+ error: {
239
+ name: error.name,
240
+ message: error.message,
241
+ stack: error.stack
242
+ }
243
+ }));
244
+ } else {
245
+ logMethod(`[${level.toUpperCase()}] ${message}`, context || {});
246
+ }
247
+ }
248
+ debug(message, context) {
249
+ this.log("debug", message, context);
250
+ }
251
+ info(message, context) {
252
+ this.log("info", message, context);
253
+ }
254
+ warn(message, context) {
255
+ this.log("warn", message, context);
256
+ }
257
+ error(message, error, context) {
258
+ this.log("error", message, context, error);
259
+ }
260
+ };
261
+ var logger = new Logger();
262
+
263
+ // lib/errors.ts
264
+ var WalletError = class _WalletError extends Error {
265
+ constructor(message, code, cause) {
266
+ super(message);
267
+ this.code = code;
268
+ this.cause = cause;
269
+ this.name = "WalletError";
270
+ Object.setPrototypeOf(this, _WalletError.prototype);
271
+ }
272
+ };
273
+ var WalletConnectionError = class _WalletConnectionError extends WalletError {
274
+ constructor(message, cause) {
275
+ super(message, "WALLET_CONNECTION_ERROR", cause);
276
+ this.name = "WalletConnectionError";
277
+ Object.setPrototypeOf(this, _WalletConnectionError.prototype);
278
+ }
279
+ };
280
+ var TransactionError = class _TransactionError extends WalletError {
281
+ constructor(message, txHash, cause) {
282
+ super(message, "TRANSACTION_ERROR", cause);
283
+ this.txHash = txHash;
284
+ this.name = "TransactionError";
285
+ Object.setPrototypeOf(this, _TransactionError.prototype);
286
+ }
287
+ };
288
+ var SignMessageError = class _SignMessageError extends WalletError {
289
+ constructor(message, cause) {
290
+ super(message, "SIGN_MESSAGE_ERROR", cause);
291
+ this.name = "SignMessageError";
292
+ Object.setPrototypeOf(this, _SignMessageError.prototype);
293
+ }
294
+ };
295
+ var WalletNotInstalledError = class _WalletNotInstalledError extends WalletError {
296
+ constructor(walletType) {
297
+ super(`Wallet ${walletType} is not installed`, "WALLET_NOT_INSTALLED");
298
+ this.name = "WalletNotInstalledError";
299
+ Object.setPrototypeOf(this, _WalletNotInstalledError.prototype);
300
+ }
301
+ };
302
+ var NetworkError = class _NetworkError extends WalletError {
303
+ constructor(message, cause) {
304
+ super(message, "NETWORK_ERROR", cause);
305
+ this.name = "NetworkError";
306
+ Object.setPrototypeOf(this, _NetworkError.prototype);
307
+ }
308
+ };
309
+
310
+ // lib/storage.ts
311
+ function setStorageItem(key, value, preferredType = "localStorage") {
312
+ const types = preferredType === "localStorage" ? ["localStorage", "sessionStorage", "cookie"] : preferredType === "sessionStorage" ? ["sessionStorage", "localStorage", "cookie"] : ["cookie", "localStorage", "sessionStorage"];
313
+ for (const type of types) {
314
+ try {
315
+ switch (type) {
316
+ case "localStorage":
317
+ if (typeof window !== "undefined" && window.localStorage) {
318
+ window.localStorage.setItem(key, value);
319
+ return true;
320
+ }
321
+ break;
322
+ case "sessionStorage":
323
+ if (typeof window !== "undefined" && window.sessionStorage) {
324
+ window.sessionStorage.setItem(key, value);
325
+ return true;
326
+ }
327
+ break;
328
+ case "cookie":
329
+ if (typeof document !== "undefined") {
330
+ document.cookie = `${key}=${encodeURIComponent(value)}; path=/; max-age=${60 * 60 * 24 * 30}; SameSite=Lax`;
331
+ return true;
332
+ }
333
+ break;
334
+ }
335
+ } catch (error) {
336
+ logger.warn(`Failed to set ${key} in ${type}`, { error });
337
+ }
338
+ }
339
+ return false;
340
+ }
341
+ function getStorageItem(key) {
342
+ try {
343
+ if (typeof window !== "undefined" && window.localStorage) {
344
+ const value = window.localStorage.getItem(key);
345
+ if (value !== null) return value;
346
+ }
347
+ } catch (error) {
348
+ logger.warn(`Failed to read ${key} from localStorage`, { error });
349
+ }
350
+ try {
351
+ if (typeof window !== "undefined" && window.sessionStorage) {
352
+ const value = window.sessionStorage.getItem(key);
353
+ if (value !== null) return value;
354
+ }
355
+ } catch (error) {
356
+ logger.warn(`Failed to read ${key} from sessionStorage`, { error });
357
+ }
358
+ try {
359
+ if (typeof document !== "undefined") {
360
+ const match = document.cookie.split("; ").find((r) => r.startsWith(key + "="));
361
+ if (match) {
362
+ return decodeURIComponent(match.split("=").slice(1).join("="));
363
+ }
364
+ }
365
+ } catch (error) {
366
+ logger.warn(`Failed to read ${key} from cookie`, { error });
367
+ }
368
+ return null;
369
+ }
370
+ function removeStorageItem(key) {
371
+ try {
372
+ if (typeof window !== "undefined" && window.localStorage) {
373
+ window.localStorage.removeItem(key);
374
+ }
375
+ } catch (error) {
376
+ }
377
+ try {
378
+ if (typeof window !== "undefined" && window.sessionStorage) {
379
+ window.sessionStorage.removeItem(key);
380
+ }
381
+ } catch (error) {
382
+ }
383
+ try {
384
+ if (typeof document !== "undefined") {
385
+ document.cookie = `${key}=; path=/; expires=Thu, 01 Jan 1970 00:00:00 GMT`;
386
+ }
387
+ } catch (error) {
388
+ }
389
+ }
390
+
391
+ // lib/constants.ts
392
+ var STORAGE_KEYS = {
393
+ SELECTED_WALLET: "multiwallet.selectedWallet",
394
+ RECENT_WALLET: "recent_wallet_type",
395
+ USER_PROFILE_CACHE: "user_profile_cache",
396
+ USER_PROFILE_CACHE_TIMESTAMP: "user_profile_cache_timestamp",
397
+ IS_SIGNING_WALLET: "isSigningWallet",
398
+ STARKEY_ACCOUNTS: "starkey.accounts.0"
399
+ };
400
+ var CACHE_TTL = {
401
+ PROFILE: 600 * 1e3,
402
+ // 10 minutes
403
+ BALANCE: 30 * 1e3
404
+ // 30 seconds
405
+ };
406
+ var TIMEOUTS = {
407
+ WALLET_DETECTION_POLL: 3e3,
408
+ // 3 seconds (reduced from 5s)
409
+ WALLET_CHECK_INTERVAL: 2e3,
410
+ // 2 seconds
411
+ WALLET_CHECK_MAX_DURATION: 3e4,
412
+ // 30 seconds
413
+ CONNECTION_TIMEOUT: 3e4,
414
+ // 30 seconds
415
+ BALANCE_POLL_INTERVAL: 3e4,
416
+ // 30 seconds
417
+ MODAL_CLOSE_DELAY: 2500,
418
+ // 2.5 seconds
419
+ CLICK_OUTSIDE_DELAY: 2e3
420
+ // 2 seconds
421
+ };
422
+ var WALLET_DOWNLOAD_URLS = {
423
+ starkey: "https://chromewebstore.google.com/detail/starkey-wallet-the-offici/hcjhpkgbmechpabifbggldplacolbkoh",
424
+ ribbit: "https://ribbitwallet.com"
425
+ };
426
+ var DEFAULT_CHAIN_IDS = {
427
+ TESTNET: "6",
428
+ MAINNET: "8"
429
+ };
430
+ var ERROR_MESSAGES = {
431
+ WALLET_NOT_INSTALLED: "Wallet extension not installed",
432
+ CONNECTION_FAILED: "Failed to connect wallet",
433
+ CONNECTION_REJECTED: "Connection rejected by user",
434
+ NO_ACCOUNT_FOUND: "No account found",
435
+ SIGNING_FAILED: "Message signing failed",
436
+ SIGNING_REJECTED: "Message signing rejected",
437
+ TRANSACTION_FAILED: "Transaction failed",
438
+ TRANSACTION_REJECTED: "Transaction rejected",
439
+ NETWORK_ERROR: "Network error occurred",
440
+ UNSUPPORTED_WALLET: "Unsupported wallet type",
441
+ INVALID_ADDRESS: "Invalid wallet address"
442
+ };
443
+ var CONNECTION_MESSAGES = {
444
+ CONNECTING: "Connecting to wallet...",
445
+ SIGNING: "Please sign the message to verify your account",
446
+ SUCCESS: "Successfully connected",
447
+ ERROR: "Connection failed",
448
+ CONNECTED_NOT_SIGNED: "Connected but signature rejected"
449
+ };
450
+
451
+ // lib/crypto.ts
452
+ function generateNonce() {
453
+ if (typeof window !== "undefined" && window.crypto && window.crypto.getRandomValues) {
454
+ const array = new Uint32Array(1);
455
+ window.crypto.getRandomValues(array);
456
+ return array[0].toString(36) + Date.now().toString(36);
457
+ }
458
+ return Math.random().toString(36).substring(2) + Date.now().toString(36);
459
+ }
460
+
461
+ // lib/config.ts
462
+ var defaultConfig = {
463
+ rpcUrl: {
464
+ testnet: "https://rpc-testnet.supra.com",
465
+ mainnet: "https://rpc-mainnet.supra.com"
466
+ },
467
+ chainId: process.env.NEXT_PUBLIC_SUPRA_CHAIN_ID || DEFAULT_CHAIN_IDS.TESTNET,
468
+ enableLogging: process.env.NODE_ENV === "development",
469
+ balancePollInterval: 3e4,
470
+ walletDetectionTimeout: 3e3
471
+ };
472
+ var config = __spreadValues({}, defaultConfig);
473
+ function initConfig(userConfig) {
474
+ var _a, _b, _c;
475
+ config = {
476
+ rpcUrl: {
477
+ testnet: ((_a = userConfig == null ? void 0 : userConfig.rpcUrl) == null ? void 0 : _a.testnet) || defaultConfig.rpcUrl.testnet,
478
+ mainnet: ((_b = userConfig == null ? void 0 : userConfig.rpcUrl) == null ? void 0 : _b.mainnet) || defaultConfig.rpcUrl.mainnet
479
+ },
480
+ chainId: (userConfig == null ? void 0 : userConfig.chainId) || defaultConfig.chainId,
481
+ enableLogging: (_c = userConfig == null ? void 0 : userConfig.enableLogging) != null ? _c : defaultConfig.enableLogging,
482
+ balancePollInterval: (userConfig == null ? void 0 : userConfig.balancePollInterval) || defaultConfig.balancePollInterval,
483
+ walletDetectionTimeout: (userConfig == null ? void 0 : userConfig.walletDetectionTimeout) || defaultConfig.walletDetectionTimeout
484
+ };
485
+ }
486
+ function getRpcUrl(chainId) {
487
+ const targetChainId = chainId || config.chainId;
488
+ const isMainnet = targetChainId === DEFAULT_CHAIN_IDS.MAINNET;
489
+ return isMainnet ? config.rpcUrl.mainnet : config.rpcUrl.testnet;
490
+ }
491
+ function getChainId() {
492
+ return config.chainId;
493
+ }
494
+ initConfig();
495
+
496
+ // hooks/useSupraMultiWallet.ts
497
+ var WALLET_CONFIGS = {
498
+ starkey: {
499
+ capabilities: {
500
+ signMessage: true,
501
+ accountSwitching: true,
502
+ networkSwitching: true,
503
+ rawTransactions: true,
504
+ eventListeners: true,
505
+ tokenRevalidation: true
506
+ },
507
+ provider: () => {
508
+ var _a;
509
+ return typeof window !== "undefined" && ((_a = window == null ? void 0 : window.starkey) == null ? void 0 : _a.supra);
510
+ }
511
+ },
512
+ ribbit: {
513
+ capabilities: {
514
+ signMessage: true,
515
+ accountSwitching: false,
516
+ // Ribbit doesn't support account switching
517
+ networkSwitching: false,
518
+ // Ribbit network switching happens in-app
519
+ rawTransactions: true,
520
+ eventListeners: false,
521
+ tokenRevalidation: false
522
+ // Ribbit doesn't support token revalidation
523
+ },
524
+ provider: () => initSdk()
525
+ }
526
+ };
527
+ var WALLET_EVENTS = {
528
+ CONNECTED: "wallet-connected",
529
+ PRESIGNED_STATE: "presigned-state",
530
+ POSTSIGNED_STATE: "postsigned-state",
531
+ ERROR: "wallet-error"
532
+ };
533
+ var setStoredWalletType = (walletType) => {
534
+ setStorageItem(STORAGE_KEYS.SELECTED_WALLET, walletType);
535
+ };
536
+ var getStoredWalletType = () => {
537
+ const stored = getStorageItem(STORAGE_KEYS.SELECTED_WALLET);
538
+ if (stored && ["starkey", "ribbit"].includes(stored)) {
539
+ return stored;
540
+ }
541
+ return "starkey";
542
+ };
543
+ var clearStoredWalletType = () => {
544
+ removeStorageItem(STORAGE_KEYS.SELECTED_WALLET);
545
+ };
546
+ var useSupraMultiWallet = () => {
547
+ const router = useRouter();
548
+ const [selectedWallet, setSelectedWallet] = useState("starkey");
549
+ const [walletCapabilities, setWalletCapabilities] = useState(
550
+ WALLET_CONFIGS["starkey"].capabilities
551
+ );
552
+ useEffect(() => {
553
+ const stored = getStoredWalletType();
554
+ if (stored !== "starkey") {
555
+ setSelectedWallet(stored);
556
+ setWalletCapabilities(WALLET_CONFIGS[stored].capabilities);
557
+ }
558
+ }, []);
559
+ const [supraProvider, setSupraProvider] = useState(
560
+ WALLET_CONFIGS.starkey.provider()
561
+ );
562
+ const [ribbitProvider, setRibbitProvider] = useState(
563
+ WALLET_CONFIGS.ribbit.provider()
564
+ );
565
+ const [isExtensionInstalled, setIsExtensionInstalled] = useState(false);
566
+ const [accounts, setAccounts] = useState([]);
567
+ const [networkData, setNetworkData] = useState();
568
+ const [balance, setBalance] = useState("");
569
+ const [loading, setLoading] = useState(false);
570
+ const [justRequestedRelative, setJustRequestedRelative] = useState(false);
571
+ const [transactions, setTransactions] = useState([]);
572
+ const [selectedChainId, setSelectedChainId] = useState("");
573
+ const addTransactions = (hash) => {
574
+ setTransactions((prev) => [{ hash }, ...prev]);
575
+ };
576
+ const getCurrentProvider = () => {
577
+ switch (selectedWallet) {
578
+ case "starkey": {
579
+ return supraProvider;
580
+ }
581
+ case "ribbit": {
582
+ return ribbitProvider;
583
+ }
584
+ default: {
585
+ return supraProvider;
586
+ }
587
+ }
588
+ };
589
+ const checkExtensionInstalled = useCallback(async () => {
590
+ switch (selectedWallet) {
591
+ case "starkey": {
592
+ const provider = WALLET_CONFIGS.starkey.provider();
593
+ setSupraProvider(provider);
594
+ setIsExtensionInstalled(!!provider);
595
+ return !!provider;
596
+ }
597
+ case "ribbit": {
598
+ const provider = WALLET_CONFIGS.ribbit.provider();
599
+ if (!provider) {
600
+ setRibbitProvider(null);
601
+ setIsExtensionInstalled(false);
602
+ return false;
603
+ }
604
+ try {
605
+ setRibbitProvider(provider);
606
+ setIsExtensionInstalled(true);
607
+ return true;
608
+ } catch (error) {
609
+ logger.error("Error checking Ribbit wallet readiness", error);
610
+ setRibbitProvider(null);
611
+ setIsExtensionInstalled(false);
612
+ return false;
613
+ }
614
+ }
615
+ default: {
616
+ return false;
617
+ }
618
+ }
619
+ }, [selectedWallet]);
620
+ const updateAccounts = useCallback(async () => {
621
+ const provider = getCurrentProvider();
622
+ if (!provider) return;
623
+ try {
624
+ switch (selectedWallet) {
625
+ case "starkey": {
626
+ const responseAcc = await provider.account();
627
+ const newAccounts = responseAcc.length > 0 ? responseAcc : [];
628
+ setAccounts(newAccounts);
629
+ if (responseAcc.length > 0) {
630
+ setStorageItem(STORAGE_KEYS.STARKEY_ACCOUNTS, responseAcc[0]);
631
+ }
632
+ if (newAccounts.length > 0) {
633
+ const balance2 = await provider.balance();
634
+ if (balance2) {
635
+ setBalance(`${balance2.formattedBalance} ${balance2.displayUnit}`);
636
+ }
637
+ const networkData2 = await provider.getChainId();
638
+ setNetworkData(networkData2 || {});
639
+ }
640
+ break;
641
+ }
642
+ case "ribbit": {
643
+ const wallet = provider.getWalletInfo();
644
+ if (wallet == null ? void 0 : wallet.connected) {
645
+ setAccounts([wallet.walletAddress]);
646
+ const walletBalanceRequest = {
647
+ chainId: parseInt(getChainId()),
648
+ resourceType: "0x1::supra_coin::SupraCoin",
649
+ decimals: 8
650
+ };
651
+ const balanceStr = await provider.getWalletBalance(walletBalanceRequest);
652
+ logger.debug("Ribbit balance response", { balance: balanceStr });
653
+ setBalance(`${(balanceStr == null ? void 0 : balanceStr.balance) || 0} SUPRA`);
654
+ } else {
655
+ setAccounts([]);
656
+ }
657
+ break;
658
+ }
659
+ default: {
660
+ setAccounts([]);
661
+ break;
662
+ }
663
+ }
664
+ } catch (error) {
665
+ logger.error("Failed to update accounts", error, { walletType: selectedWallet });
666
+ setAccounts([]);
667
+ switch (selectedWallet) {
668
+ case "starkey": {
669
+ removeStorageItem(STORAGE_KEYS.STARKEY_ACCOUNTS);
670
+ break;
671
+ }
672
+ case "ribbit": {
673
+ break;
674
+ }
675
+ }
676
+ }
677
+ }, [selectedWallet]);
678
+ useEffect(() => {
679
+ let mounted = true;
680
+ const initProvider = async () => {
681
+ const isInstalled = await checkExtensionInstalled();
682
+ if (mounted && isInstalled) {
683
+ updateAccounts();
684
+ }
685
+ };
686
+ initProvider();
687
+ return () => {
688
+ mounted = false;
689
+ };
690
+ }, [selectedWallet, checkExtensionInstalled, updateAccounts]);
691
+ useEffect(() => {
692
+ const checkExtension = async () => {
693
+ return await checkExtensionInstalled();
694
+ };
695
+ checkExtension().then((isInstalled) => {
696
+ if (isInstalled && selectedWallet === "ribbit") {
697
+ updateAccounts();
698
+ }
699
+ });
700
+ const intv = setInterval(async () => {
701
+ const isInstalled = await checkExtension();
702
+ if (isInstalled) {
703
+ clearInterval(intv);
704
+ if (selectedWallet === "ribbit") {
705
+ updateAccounts();
706
+ }
707
+ }
708
+ }, 1e3);
709
+ setTimeout(() => {
710
+ clearInterval(intv);
711
+ }, TIMEOUTS.WALLET_DETECTION_POLL);
712
+ return () => clearInterval(intv);
713
+ }, [selectedWallet, updateAccounts, checkExtensionInstalled]);
714
+ const checkIsExtensionInstalled = useCallback(() => {
715
+ const intervalId = setInterval(async () => {
716
+ const isInstalled = await checkExtensionInstalled();
717
+ if (isInstalled) {
718
+ clearInterval(intervalId);
719
+ updateAccounts();
720
+ }
721
+ }, 500);
722
+ setTimeout(() => clearInterval(intervalId), TIMEOUTS.WALLET_DETECTION_POLL);
723
+ }, [updateAccounts, checkExtensionInstalled]);
724
+ const updateBalance = useCallback(async () => {
725
+ const provider = getCurrentProvider();
726
+ if (!provider || !accounts.length) {
727
+ setBalance("");
728
+ return;
729
+ }
730
+ try {
731
+ switch (selectedWallet) {
732
+ case "starkey": {
733
+ const balance2 = await provider.balance();
734
+ if (balance2) {
735
+ setBalance(`${balance2.formattedBalance} ${balance2.displayUnit}`);
736
+ }
737
+ break;
738
+ }
739
+ case "ribbit": {
740
+ const walletBalanceRequest = {
741
+ chainId: parseInt(getChainId()),
742
+ resourceType: "0x1::supra_coin::SupraCoin",
743
+ decimals: 8
744
+ };
745
+ const balanceStr = await provider.getWalletBalance(
746
+ walletBalanceRequest
747
+ );
748
+ logger.debug("Ribbit balance response", { balance: balanceStr });
749
+ setBalance(`${(balanceStr == null ? void 0 : balanceStr.balance) || 0} SUPRA`);
750
+ break;
751
+ }
752
+ default: {
753
+ setBalance("");
754
+ break;
755
+ }
756
+ }
757
+ } catch (error) {
758
+ logger.error("Failed to update balance", error, { walletType: selectedWallet });
759
+ setBalance("");
760
+ }
761
+ }, [selectedWallet, accounts]);
762
+ const getNetworkData = useCallback(async () => {
763
+ const provider = getCurrentProvider();
764
+ if (!provider) return {};
765
+ try {
766
+ switch (selectedWallet) {
767
+ case "starkey": {
768
+ const data = await provider.getChainId();
769
+ setNetworkData(data || {});
770
+ return data || {};
771
+ }
772
+ case "ribbit": {
773
+ const chainId = parseInt(getChainId());
774
+ const mockNetworkData = { chainId: chainId.toString() };
775
+ setNetworkData(mockNetworkData);
776
+ return mockNetworkData;
777
+ }
778
+ default: {
779
+ setNetworkData({});
780
+ return {};
781
+ }
782
+ }
783
+ } catch (error) {
784
+ logger.error("Failed to get network data", error, { walletType: selectedWallet });
785
+ setNetworkData({});
786
+ return {};
787
+ }
788
+ }, [selectedWallet]);
789
+ const connectWallet = async (walletType) => {
790
+ if (walletType) {
791
+ updateSelectedWallet(walletType);
792
+ }
793
+ const provider = walletType ? WALLET_CONFIGS[walletType].provider() : getCurrentProvider();
794
+ if (!provider) {
795
+ const error = new WalletNotInstalledError(walletType || selectedWallet);
796
+ logger.warn("Wallet not installed", { walletType: walletType || selectedWallet });
797
+ toast.error(ERROR_MESSAGES.WALLET_NOT_INSTALLED, {
798
+ description: `Please install the ${walletType || selectedWallet} extension`
799
+ });
800
+ return false;
801
+ }
802
+ setLoading(true);
803
+ try {
804
+ switch (walletType || selectedWallet) {
805
+ case "starkey": {
806
+ await provider.connect();
807
+ logger.info("Starkey wallet connection approved");
808
+ await updateAccounts();
809
+ const responseAcc = await provider.account();
810
+ if (responseAcc.length === 0) {
811
+ throw new WalletConnectionError(ERROR_MESSAGES.NO_ACCOUNT_FOUND);
812
+ }
813
+ if (responseAcc.length) {
814
+ setAccounts(responseAcc);
815
+ setStorageItem(STORAGE_KEYS.IS_SIGNING_WALLET, "false");
816
+ setStorageItem(STORAGE_KEYS.STARKEY_ACCOUNTS, responseAcc[0]);
817
+ window.dispatchEvent(
818
+ new CustomEvent(WALLET_EVENTS.PRESIGNED_STATE, {
819
+ detail: {
820
+ timestamp: Date.now(),
821
+ account: responseAcc[0]
822
+ }
823
+ })
824
+ );
825
+ window.dispatchEvent(
826
+ new CustomEvent(WALLET_EVENTS.CONNECTED, {
827
+ detail: {
828
+ timestamp: Date.now(),
829
+ account: responseAcc[0],
830
+ wallet: "starkey"
831
+ }
832
+ })
833
+ );
834
+ try {
835
+ const message = "To verify your account, please sign this message.";
836
+ const nonce = generateNonce();
837
+ const hexMessage = "0x" + Buffer.from(message, "utf8").toString("hex");
838
+ logger.debug("Signature request initiated", { account: responseAcc[0] });
839
+ const signatureResponse = await provider.signMessage({
840
+ message: hexMessage,
841
+ nonce
842
+ });
843
+ if (signatureResponse) {
844
+ logger.info("Signature approved", { account: responseAcc[0] });
845
+ window.dispatchEvent(
846
+ new CustomEvent(WALLET_EVENTS.POSTSIGNED_STATE, {
847
+ detail: {
848
+ timestamp: Date.now(),
849
+ account: responseAcc[0]
850
+ }
851
+ })
852
+ );
853
+ }
854
+ } catch (signError) {
855
+ const error = new SignMessageError(ERROR_MESSAGES.SIGNING_FAILED, signError);
856
+ logger.error("Signing failed", error, { account: responseAcc[0] });
857
+ window.dispatchEvent(
858
+ new CustomEvent(WALLET_EVENTS.ERROR, {
859
+ detail: {
860
+ timestamp: Date.now(),
861
+ error
862
+ }
863
+ })
864
+ );
865
+ throw error;
866
+ }
867
+ }
868
+ break;
869
+ }
870
+ case "ribbit": {
871
+ const dappMetadata = {
872
+ name: "multiwallet",
873
+ description: "NFT Marketplace and Lootbox Platform",
874
+ logo: window.location.origin + "/favicon.ico",
875
+ url: window.location.origin
876
+ };
877
+ const response = await provider.connectToWallet(
878
+ dappMetadata
879
+ );
880
+ if (response == null ? void 0 : response.connected) {
881
+ logger.info("Ribbit wallet connection approved");
882
+ }
883
+ if (response.walletAddress == null) {
884
+ throw new WalletConnectionError(ERROR_MESSAGES.NO_ACCOUNT_FOUND);
885
+ }
886
+ if (response == null ? void 0 : response.connected) {
887
+ await updateAccounts();
888
+ if (response.walletAddress) {
889
+ setAccounts([response.walletAddress]);
890
+ setStorageItem(STORAGE_KEYS.IS_SIGNING_WALLET, "false");
891
+ window.dispatchEvent(
892
+ new CustomEvent(WALLET_EVENTS.PRESIGNED_STATE, {
893
+ detail: {
894
+ timestamp: Date.now(),
895
+ account: response.walletAddress
896
+ }
897
+ })
898
+ );
899
+ window.dispatchEvent(
900
+ new CustomEvent(WALLET_EVENTS.CONNECTED, {
901
+ detail: {
902
+ timestamp: Date.now(),
903
+ account: response.walletAddress,
904
+ wallet: "ribbit"
905
+ }
906
+ })
907
+ );
908
+ try {
909
+ const message = "To verify your account, please sign this message.";
910
+ const nonce = generateNonce();
911
+ const hexMessage = "0x" + Buffer.from(message, "utf8").toString("hex");
912
+ logger.debug("Signature request initiated", { account: response.walletAddress });
913
+ const signatureResponse = await provider.signMessage({
914
+ message: hexMessage,
915
+ nonce: parseInt(nonce),
916
+ chainId: parseInt(getChainId())
917
+ });
918
+ if (signatureResponse && signatureResponse.approved) {
919
+ logger.info("Signature approved", { account: response.walletAddress });
920
+ window.dispatchEvent(
921
+ new CustomEvent(WALLET_EVENTS.POSTSIGNED_STATE, {
922
+ detail: {
923
+ timestamp: Date.now(),
924
+ account: response.walletAddress
925
+ }
926
+ })
927
+ );
928
+ } else {
929
+ throw new SignMessageError(signatureResponse.error || ERROR_MESSAGES.SIGNING_REJECTED);
930
+ }
931
+ } catch (signError) {
932
+ const error = new SignMessageError(ERROR_MESSAGES.SIGNING_FAILED, signError);
933
+ logger.error("Signing failed", error, { account: response.walletAddress });
934
+ window.dispatchEvent(
935
+ new CustomEvent(WALLET_EVENTS.ERROR, {
936
+ detail: {
937
+ timestamp: Date.now(),
938
+ error
939
+ }
940
+ })
941
+ );
942
+ throw error;
943
+ }
944
+ }
945
+ } else {
946
+ throw new WalletConnectionError(ERROR_MESSAGES.CONNECTION_REJECTED);
947
+ }
948
+ break;
949
+ }
950
+ default: {
951
+ throw new WalletConnectionError(
952
+ `${ERROR_MESSAGES.UNSUPPORTED_WALLET}: ${walletType || selectedWallet}`
953
+ );
954
+ }
955
+ }
956
+ return true;
957
+ } catch (error) {
958
+ const walletError = error instanceof WalletConnectionError ? error : new WalletConnectionError(ERROR_MESSAGES.CONNECTION_FAILED, error);
959
+ logger.error("Wallet connection failed", walletError, {
960
+ walletType: walletType || selectedWallet
961
+ });
962
+ window.dispatchEvent(
963
+ new CustomEvent(WALLET_EVENTS.ERROR, {
964
+ detail: {
965
+ timestamp: Date.now(),
966
+ error: walletError
967
+ }
968
+ })
969
+ );
970
+ return false;
971
+ } finally {
972
+ setLoading(false);
973
+ }
974
+ };
975
+ const disconnectWallet = async () => {
976
+ const provider = getCurrentProvider();
977
+ if (!provider) return;
978
+ try {
979
+ switch (selectedWallet) {
980
+ case "starkey": {
981
+ await provider.disconnect();
982
+ break;
983
+ }
984
+ case "ribbit": {
985
+ await provider.disconnect();
986
+ break;
987
+ }
988
+ }
989
+ resetWalletData();
990
+ clearStoredWalletType();
991
+ router.push("/");
992
+ } catch (error) {
993
+ logger.error("Wallet disconnect failed", error, { walletType: selectedWallet });
994
+ resetWalletData();
995
+ clearStoredWalletType();
996
+ }
997
+ };
998
+ const resetWalletData = () => {
999
+ setAccounts([]);
1000
+ setBalance("");
1001
+ setNetworkData({});
1002
+ switch (selectedWallet) {
1003
+ case "starkey": {
1004
+ setStorageItem(STORAGE_KEYS.IS_SIGNING_WALLET, "false");
1005
+ removeStorageItem(STORAGE_KEYS.STARKEY_ACCOUNTS);
1006
+ break;
1007
+ }
1008
+ case "ribbit": {
1009
+ break;
1010
+ }
1011
+ }
1012
+ };
1013
+ const getSequenceNumber = async (address) => {
1014
+ const rpcUrl = getRpcUrl();
1015
+ const data = await fetch(`${rpcUrl}/rpc/v1/accounts/${address}`);
1016
+ if (!data.ok) {
1017
+ throw new NetworkError(`Failed to fetch sequence number for ${address}`);
1018
+ }
1019
+ const accountData = await data.json();
1020
+ return accountData.sequence_number;
1021
+ };
1022
+ const sendRawTransaction = async (moduleAddress, moduleName, functionName, params, runTimeParams = [], txExpiryTime = Math.ceil(Date.now() / 1e3) + 3e3) => {
1023
+ const provider = getCurrentProvider();
1024
+ if (!provider || !accounts.length || !moduleAddress || !moduleName || !functionName)
1025
+ return;
1026
+ try {
1027
+ switch (selectedWallet) {
1028
+ case "starkey": {
1029
+ if (!walletCapabilities.rawTransactions) {
1030
+ throw new TransactionError("Raw transactions not supported by current wallet");
1031
+ }
1032
+ let networkData2 = await getNetworkData();
1033
+ const currentChainId = getChainId();
1034
+ if (networkData2.chainId !== currentChainId) {
1035
+ setSelectedChainId(currentChainId);
1036
+ await provider.changeNetwork({
1037
+ chainId: currentChainId
1038
+ });
1039
+ }
1040
+ const rawTxPayload = [
1041
+ accounts[0],
1042
+ 0,
1043
+ // sequence number
1044
+ moduleAddress,
1045
+ moduleName,
1046
+ functionName,
1047
+ runTimeParams,
1048
+ params,
1049
+ {}
1050
+ ];
1051
+ const data = await provider.createRawTransactionData(rawTxPayload);
1052
+ const txHash = await provider.sendTransaction({
1053
+ data,
1054
+ from: accounts[0],
1055
+ to: moduleAddress,
1056
+ chainId: currentChainId,
1057
+ value: ""
1058
+ });
1059
+ addTransactions(txHash || "failed");
1060
+ logger.info("Transaction sent successfully", { txHash, walletType: "starkey" });
1061
+ return txHash;
1062
+ }
1063
+ case "ribbit": {
1064
+ if (!walletCapabilities.rawTransactions) {
1065
+ throw new TransactionError("Raw transactions not supported by current wallet");
1066
+ }
1067
+ const currentChainId = getChainId();
1068
+ let chainId = SupraChainId.TESTNET;
1069
+ if (currentChainId === DEFAULT_CHAIN_IDS.TESTNET) {
1070
+ chainId = SupraChainId.TESTNET;
1071
+ } else if (currentChainId === DEFAULT_CHAIN_IDS.MAINNET) {
1072
+ chainId = SupraChainId.MAINNET;
1073
+ }
1074
+ const rawTxnRequest = {
1075
+ sender: accounts[0],
1076
+ // Use actual sender address
1077
+ moduleAddress,
1078
+ // Use provided module address
1079
+ moduleName,
1080
+ // Use provided module name
1081
+ functionName,
1082
+ // Use provided function name
1083
+ typeArgs: runTimeParams,
1084
+ // Use converted runtime parameters
1085
+ args: params || [],
1086
+ // Use provided parameters
1087
+ chainId
1088
+ };
1089
+ const rawTxnBase64 = await provider.createRawTransactionBuffer(rawTxnRequest);
1090
+ const response = await provider.signAndSendRawTransaction({
1091
+ rawTxn: rawTxnBase64,
1092
+ chainId,
1093
+ meta: {
1094
+ description: `Call ${moduleName}::${functionName}`
1095
+ // Dynamic description
1096
+ }
1097
+ });
1098
+ if (response.approved) {
1099
+ const txHash = response.txHash || response.result || "success";
1100
+ addTransactions(txHash);
1101
+ logger.info("Transaction sent successfully", { txHash, walletType: "ribbit" });
1102
+ return txHash;
1103
+ } else {
1104
+ throw new TransactionError(response.error || ERROR_MESSAGES.TRANSACTION_REJECTED);
1105
+ }
1106
+ }
1107
+ default: {
1108
+ throw new TransactionError(
1109
+ `Raw transactions not supported for wallet: ${selectedWallet}`
1110
+ );
1111
+ }
1112
+ }
1113
+ } catch (error) {
1114
+ const txError = error instanceof TransactionError ? error : new TransactionError(ERROR_MESSAGES.TRANSACTION_FAILED, void 0, error);
1115
+ logger.error("Transaction failed", txError, {
1116
+ walletType: selectedWallet,
1117
+ moduleAddress,
1118
+ moduleName,
1119
+ functionName
1120
+ });
1121
+ throw txError;
1122
+ }
1123
+ };
1124
+ const signMessage = async (message, nonce, account, forceSign = false) => {
1125
+ const provider = getCurrentProvider();
1126
+ if (!provider) return;
1127
+ const secureNonce = nonce || generateNonce();
1128
+ switch (selectedWallet) {
1129
+ case "starkey": {
1130
+ if (!walletCapabilities.signMessage) {
1131
+ throw new SignMessageError("Message signing not supported by current wallet");
1132
+ }
1133
+ if (!accounts.length && !account) return;
1134
+ if (!accounts.length && account) {
1135
+ accounts[0] = account;
1136
+ }
1137
+ if (getStorageItem(STORAGE_KEYS.IS_SIGNING_WALLET) === "true" && !forceSign) {
1138
+ return;
1139
+ }
1140
+ setStorageItem(STORAGE_KEYS.IS_SIGNING_WALLET, "true");
1141
+ try {
1142
+ const hexMessage = "0x" + Buffer.from(message, "utf8").toString("hex");
1143
+ const response = await provider.signMessage({
1144
+ message: hexMessage,
1145
+ nonce: secureNonce
1146
+ });
1147
+ const { publicKey, signature } = response;
1148
+ const verified = nacl.sign.detached.verify(
1149
+ new TextEncoder().encode(message),
1150
+ Uint8Array.from(Buffer.from(signature.slice(2), "hex")),
1151
+ Uint8Array.from(Buffer.from(publicKey.slice(2), "hex"))
1152
+ );
1153
+ setStorageItem(STORAGE_KEYS.IS_SIGNING_WALLET, "false");
1154
+ logger.info("Message signed successfully", { walletType: "starkey" });
1155
+ return __spreadProps(__spreadValues({}, response), { verified });
1156
+ } catch (error) {
1157
+ setStorageItem(STORAGE_KEYS.IS_SIGNING_WALLET, "false");
1158
+ throw new SignMessageError(ERROR_MESSAGES.SIGNING_FAILED, error);
1159
+ }
1160
+ }
1161
+ case "ribbit": {
1162
+ if (!walletCapabilities.signMessage) {
1163
+ throw new SignMessageError("Message signing not supported by current wallet");
1164
+ }
1165
+ if (!accounts.length && !account) return;
1166
+ if (!accounts.length && account) {
1167
+ accounts[0] = account;
1168
+ }
1169
+ if (getStorageItem(STORAGE_KEYS.IS_SIGNING_WALLET) === "true" && !forceSign) {
1170
+ return;
1171
+ }
1172
+ setStorageItem(STORAGE_KEYS.IS_SIGNING_WALLET, "true");
1173
+ try {
1174
+ const hexMessage = "0x" + Buffer.from(message, "utf8").toString("hex");
1175
+ const response = await provider.signMessage({
1176
+ message: hexMessage,
1177
+ nonce: parseInt(secureNonce),
1178
+ chainId: parseInt(getChainId())
1179
+ });
1180
+ if (response.approved && response.publicKey && response.signature) {
1181
+ const { publicKey, signature } = response;
1182
+ const verified = nacl.sign.detached.verify(
1183
+ new TextEncoder().encode(message),
1184
+ Uint8Array.from(Buffer.from(signature.slice(2), "hex")),
1185
+ Uint8Array.from(Buffer.from(publicKey.slice(2), "hex"))
1186
+ );
1187
+ setStorageItem(STORAGE_KEYS.IS_SIGNING_WALLET, "false");
1188
+ logger.info("Message signed successfully", { walletType: "ribbit" });
1189
+ return __spreadProps(__spreadValues({}, response), { verified });
1190
+ } else {
1191
+ setStorageItem(STORAGE_KEYS.IS_SIGNING_WALLET, "false");
1192
+ throw new SignMessageError(response.error || ERROR_MESSAGES.SIGNING_REJECTED);
1193
+ }
1194
+ } catch (error) {
1195
+ setStorageItem(STORAGE_KEYS.IS_SIGNING_WALLET, "false");
1196
+ throw new SignMessageError(ERROR_MESSAGES.SIGNING_FAILED, error);
1197
+ }
1198
+ }
1199
+ default: {
1200
+ throw new SignMessageError(
1201
+ `Message signing not supported for wallet: ${selectedWallet}`
1202
+ );
1203
+ }
1204
+ }
1205
+ };
1206
+ useEffect(() => {
1207
+ if (selectedWallet === "starkey" && walletCapabilities.eventListeners) {
1208
+ const handleExtensionEvents = (event) => {
1209
+ var _a, _b, _c;
1210
+ if ((_b = (_a = event == null ? void 0 : event.data) == null ? void 0 : _a.name) == null ? void 0 : _b.startsWith("starkey-")) {
1211
+ switch ((_c = event == null ? void 0 : event.data) == null ? void 0 : _c.name) {
1212
+ case "starkey-extension-installed": {
1213
+ checkIsExtensionInstalled();
1214
+ break;
1215
+ }
1216
+ case "starkey-wallet-updated": {
1217
+ (async () => {
1218
+ const responseAcc = await supraProvider.account();
1219
+ if (responseAcc.length) {
1220
+ setAccounts(responseAcc);
1221
+ window.dispatchEvent(
1222
+ new CustomEvent(WALLET_EVENTS.CONNECTED, {
1223
+ detail: {
1224
+ timestamp: Date.now(),
1225
+ account: responseAcc[0]
1226
+ }
1227
+ })
1228
+ );
1229
+ await updateBalance();
1230
+ await getNetworkData();
1231
+ } else {
1232
+ logger.debug("Starkey wallet updated: No accounts found - Resetting");
1233
+ resetWalletData();
1234
+ }
1235
+ setLoading(false);
1236
+ })();
1237
+ break;
1238
+ }
1239
+ case "starkey-wallet-disconnected": {
1240
+ resetWalletData();
1241
+ router.push("/");
1242
+ setLoading(false);
1243
+ break;
1244
+ }
1245
+ case "starkey-window-removed": {
1246
+ setLoading(false);
1247
+ break;
1248
+ }
1249
+ }
1250
+ }
1251
+ };
1252
+ checkIsExtensionInstalled();
1253
+ window.addEventListener("message", handleExtensionEvents);
1254
+ return () => window.removeEventListener("message", handleExtensionEvents);
1255
+ }
1256
+ }, [selectedWallet, walletCapabilities, supraProvider]);
1257
+ const getAvailableWallets = useCallback(() => {
1258
+ const availableWallets = [];
1259
+ Object.entries(WALLET_CONFIGS).forEach(([walletType, config2]) => {
1260
+ const provider = config2.provider();
1261
+ const isInstalled = !!provider;
1262
+ switch (walletType) {
1263
+ case "starkey": {
1264
+ availableWallets.push({
1265
+ type: "starkey",
1266
+ name: "Starkey Wallet",
1267
+ isInstalled,
1268
+ capabilities: config2.capabilities
1269
+ });
1270
+ break;
1271
+ }
1272
+ case "ribbit": {
1273
+ availableWallets.push({
1274
+ type: "ribbit",
1275
+ name: "Ribbit Wallet",
1276
+ isInstalled,
1277
+ capabilities: config2.capabilities
1278
+ });
1279
+ break;
1280
+ }
1281
+ }
1282
+ });
1283
+ return availableWallets;
1284
+ }, []);
1285
+ const updateSelectedWallet = (walletType) => {
1286
+ setSelectedWallet(walletType);
1287
+ setWalletCapabilities(WALLET_CONFIGS[walletType].capabilities);
1288
+ setStoredWalletType(walletType);
1289
+ };
1290
+ return {
1291
+ // New wallet selection functionality
1292
+ selectedWallet,
1293
+ walletCapabilities,
1294
+ getAvailableWallets,
1295
+ // Add this new function
1296
+ // Existing interface (unchanged)
1297
+ getCurrentProvider,
1298
+ isExtensionInstalled,
1299
+ accounts,
1300
+ networkData,
1301
+ balance,
1302
+ transactions,
1303
+ selectedChainId,
1304
+ connectWallet,
1305
+ // Now accepts optional walletType parameter
1306
+ disconnectWallet,
1307
+ sendRawTransaction,
1308
+ signMessage,
1309
+ setSelectedChainId,
1310
+ // switchToChain,
1311
+ loading
1312
+ // authFetch,
1313
+ // checkAndRevalidateToken,
1314
+ // signIn,
1315
+ };
1316
+ };
1317
+ var useSupraMultiWallet_default = useSupraMultiWallet;
1318
+
1319
+ // src/assets/walletIcons/Starkey.png
1320
+ var Starkey_default = "data:image/png;base64,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";
1321
+
1322
+ // src/assets/walletIcons/Ribbit.jpg
1323
+ var Ribbit_default = "data:image/jpeg;base64,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XgUI/Cojt9XIq+0ORb6HugAg2KoXeUjjgUFiuBhegVf2soPalH3iGy1MdeAQjvEhlQZGa6UlbArMZbhRt2mXIkRhKkSO197XztIncgu5vVOXIhEu/mqFIAoYZbcdfW2JpWja8llrSm2ZdpJES5KC1gmj7uTSkkSEy3eybKcy/OazhtEuSwAvoMGuF1TCmwpeXRMauXQSipW+MY879q9qv84xrBnofuj33gCjGoDhVhnekocsnAVLWN7bxnba4FTExP2dDDUQGLRa5QXVMKTDrxdExpQ4GES7YKMl9X+rMZSzkdx3a7RZ5tXKArQJ97TRWZuCx/Z7RpyMGS56eKWa2R3g+vllRZoNUr6o2chJmvennaSq2MxFz+y2pH9xX0u7Fbg8BPqlduK2pWQgLMufW2MEUgyAg8vSke6dZ9fKwdxXc9VPICdQiHwddsNBlZkXHva9pnDzH00YX1Duopc3Uin9bW9eds6iSOejVnicQ8Mas8bgPjU0KW5GhR+2NPxx5/LMz/ANfNTxpZro1x8YPhVljcA8alxS3TQ22WR05bvdCBcrvut53JyLWhwsBShj7iwff8XvyluMwNM6AAQFx8p43FYjTVC4D3a/x+nm5qBiRAYUGcKDXdbIjMmL+DrsvYehTpaLz0iufDd7oCJGSA91A2bbuflok7QCA+cRFQORoaM7cE4UeHGu90JLHIAoU6NHmb3tRtfgEBs/DAHrf13QEZHxloirGNdflaLZbgAibeZTK5CWCMPikYuE+JVBW/Dm2JsefyqcMSwF1IiISzc7hw7QvzGjLBGwRzLpoKjmVIlaEsqzfmFqBH13MbieSzfwYSrwTuafBlGDUJGGMMR130/OD7Cll3RzEtVu/wB99lavaLsTpd13UqFkLT62u945LD8NLLLu8IvsvuPmVckWWTeLuWBt+1p9LZRtXebXM1eIU6S7v32USVrpBunHf65VFzWssbPVw4FY75qMtaEEG/7BQsZyR6Grg4xp0JSTzR88KNHzwiVLQkYLQ6AMIHY+6dsHifdBNr8lM2boPtTsaUfOKjQTk9BOuTZo2S9MqXndfrTozn/0dqw0lD/TpSJavSV/8OXOp+HUal/sB//aAAwDAQACAAMAAAAQ888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888880V0ms888jqr9788888888888pzDl+e9A8k/hDxo8888888888d8+o/9999959q848888888888bmL999999950m+m888888888D+PNN994109989f/APPPPPPPPPE//ffffb3fffffffv/ADzzzzzzzzz3333333333333jzzzzzzzzzyXT333333333337PzzzzzzzzzzzQrPjTLvfnfaZDzzzzzzzzzzzzzzyyzzzyw1zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz/8QAJhEBAAIBAgQHAQEAAAAAAAAAAQARITFBIDBRYRBwcZGhscFAgf/aAAgBAwEBPxDzOPELehE5o9o1C9yI0V32g3wALYY0L7ymP4mUuP8ALh9j0deZUo1dIcG26jEG/wAjstSVNr6j1fid99p3fiNsPtGM7wDFr9htu4LneWHLtHYvg07jBgmLt9cQNfSNO4xV4ezHl+k8NJiaTzFss734lA7Q18ppPMZJiXbvXKWsx2hDOYNCKW78QAZYJjzpHGoeKGcwaEQtxDdt+VfF0eNHapgjJmIrdeIl6305TIbbc5RNjXmHEaTHXmURlJa78wBQsmUdTZ79JqC9oM0E0/8AEOzNuuaqEE0mkqIyq9JVmv4a4aPLn//EACkRAQACAAMGBgMBAAAAAAAAAAEAESExQTBRYXGBsRAgkaHR4XDB8ED/2gAIAQIBAT8Q/JztDuD97piRjoveX4x3IRYC2/SCJZ5AClEZpvi/EtRbwD4mOgOYP90mkomY4O0YAZuBBKM9XfDLqjkQ8dSIM4lXO0O76iX0Zxn0mBm9GLou6ZzDAZNd2GXZCxamTKl67OzdE+4eCy0VXKoUtWfKEKOHbzAcW5jWaMuUCWq75V4B0D6n1s6E3Y8rYfexlfTE1M4497ny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";
1324
+
1325
+ // src/components/ConnectWalletHandler.tsx
1326
+ import { Fragment, jsx as jsx3, jsxs as jsxs2 } from "react/jsx-runtime";
1327
+ var PROFILE_CACHE_KEY = STORAGE_KEYS.USER_PROFILE_CACHE;
1328
+ var PROFILE_CACHE_TIMESTAMP_KEY = STORAGE_KEYS.USER_PROFILE_CACHE_TIMESTAMP;
1329
+ var WALLET_INFO = {
1330
+ starkey: {
1331
+ name: "Starkey Wallet",
1332
+ icon: /* @__PURE__ */ jsx3(
1333
+ "img",
1334
+ {
1335
+ src: Starkey_default,
1336
+ alt: "Starkey Wallet",
1337
+ className: "w-10 h-10 rounded-full"
1338
+ }
1339
+ ),
1340
+ downloadUrl: WALLET_DOWNLOAD_URLS.starkey
1341
+ },
1342
+ ribbit: {
1343
+ name: "Ribbit Wallet",
1344
+ icon: /* @__PURE__ */ jsx3(
1345
+ "img",
1346
+ {
1347
+ src: Ribbit_default,
1348
+ alt: "Ribbit Wallet",
1349
+ className: "w-10 h-10 rounded-full"
1350
+ }
1351
+ ),
1352
+ downloadUrl: WALLET_DOWNLOAD_URLS.ribbit
1353
+ }
1354
+ };
1355
+ var ConnectWalletHandler = ({
1356
+ onConnect,
1357
+ onDisconnect,
1358
+ children
1359
+ }) => {
1360
+ const starKeyWalletHook = useSupraMultiWallet_default();
1361
+ const getAvailableWallets = starKeyWalletHook.getAvailableWallets;
1362
+ const [loading, setLoading] = useState2(false);
1363
+ const [showWalletModal, setShowWalletModal] = useState2(false);
1364
+ const [userProfile, setUserProfile] = useState2(null);
1365
+ const [walletBalance, setWalletBalance] = useState2("0.00");
1366
+ const [availableWallets, setAvailableWallets] = useState2([]);
1367
+ const [recentWallet, setRecentWallet] = useState2(null);
1368
+ const [selectedWallet, setSelectedWallet] = useState2(null);
1369
+ const [hoveredWallet, setHoveredWallet] = useState2(null);
1370
+ const [connectionStage, setConnectionStage] = useState2("idle");
1371
+ const [connectionStageStartTime, setConnectionStageStartTime] = useState2(null);
1372
+ const [canClickOutside, setCanClickOutside] = useState2(false);
1373
+ const getProfileFromCache = useCallback2(() => {
1374
+ try {
1375
+ if (typeof window === "undefined") return null;
1376
+ const cachedData = getStorageItem(PROFILE_CACHE_KEY);
1377
+ const timestamp = getStorageItem(PROFILE_CACHE_TIMESTAMP_KEY);
1378
+ if (!cachedData || !timestamp) return null;
1379
+ const now = Date.now();
1380
+ const cacheTime = parseInt(timestamp);
1381
+ if (now - cacheTime > CACHE_TTL.PROFILE) {
1382
+ return null;
1383
+ }
1384
+ return JSON.parse(cachedData);
1385
+ } catch (error) {
1386
+ logger.error("Failed to read profile from cache", error);
1387
+ return null;
1388
+ }
1389
+ }, []);
1390
+ const updateWalletBalance = useCallback2(async () => {
1391
+ const provider = starKeyWalletHook.getCurrentProvider();
1392
+ if (!provider) return;
1393
+ try {
1394
+ await new Promise((resolve) => setTimeout(resolve, 1));
1395
+ switch (starKeyWalletHook.selectedWallet) {
1396
+ case "starkey": {
1397
+ const balance = await provider.balance();
1398
+ if (balance && balance.formattedBalance) {
1399
+ setWalletBalance(balance.formattedBalance);
1400
+ }
1401
+ break;
1402
+ }
1403
+ case "ribbit": {
1404
+ const walletBalanceRequest = {
1405
+ chainId: parseInt(process.env.NEXT_PUBLIC_SUPRA_CHAIN_ID || "6"),
1406
+ resourceType: "0x1::supra_coin::SupraCoin",
1407
+ decimals: 8
1408
+ };
1409
+ try {
1410
+ const balance = await provider.getWalletBalance(walletBalanceRequest);
1411
+ const balanceStr = balance.balance;
1412
+ logger.debug("Ribbit balance fetched", { balance: balanceStr });
1413
+ if (balanceStr) {
1414
+ setWalletBalance(balanceStr);
1415
+ }
1416
+ } catch (error) {
1417
+ logger.error("Failed to fetch Ribbit balance", error);
1418
+ }
1419
+ break;
1420
+ }
1421
+ }
1422
+ } catch (error) {
1423
+ logger.error("Failed to update wallet balance", error);
1424
+ }
1425
+ }, [starKeyWalletHook.selectedWallet, starKeyWalletHook.getCurrentProvider]);
1426
+ const connectWallet = useCallback2(async (walletType) => {
1427
+ if (walletType) {
1428
+ setLoading(true);
1429
+ setSelectedWallet(walletType);
1430
+ setConnectionStage("connecting");
1431
+ try {
1432
+ const success = await starKeyWalletHook.connectWallet(walletType);
1433
+ if (success) {
1434
+ setStorageItem(STORAGE_KEYS.RECENT_WALLET, walletType);
1435
+ setRecentWallet(walletType);
1436
+ if (starKeyWalletHook.accounts.length > 0) {
1437
+ onConnect == null ? void 0 : onConnect(starKeyWalletHook.accounts[0]);
1438
+ }
1439
+ }
1440
+ } catch (error) {
1441
+ logger.error("Failed to connect wallet", error, { walletType });
1442
+ toast2.error(`Connection failed: ${error.message || "Unknown error"}`);
1443
+ setConnectionStage("idle");
1444
+ } finally {
1445
+ setLoading(false);
1446
+ }
1447
+ } else {
1448
+ handleConnectClick();
1449
+ }
1450
+ }, [starKeyWalletHook, onConnect]);
1451
+ const handleConnectClick = () => {
1452
+ const installedWallets = availableWallets.filter((w) => w.isInstalled);
1453
+ if (installedWallets.length === 0) {
1454
+ setShowWalletModal(true);
1455
+ } else if (installedWallets.length === 1) {
1456
+ setShowWalletModal(true);
1457
+ } else {
1458
+ setShowWalletModal(true);
1459
+ }
1460
+ };
1461
+ const handleDisconnectWallet = useCallback2(async () => {
1462
+ setLoading(true);
1463
+ try {
1464
+ await starKeyWalletHook.disconnectWallet();
1465
+ setUserProfile(null);
1466
+ setWalletBalance("0.00");
1467
+ onDisconnect == null ? void 0 : onDisconnect();
1468
+ } catch (error) {
1469
+ logger.error("Failed to disconnect wallet", error);
1470
+ } finally {
1471
+ setLoading(false);
1472
+ }
1473
+ }, [starKeyWalletHook, onDisconnect]);
1474
+ const getConnectionStageInfo = useCallback2(() => {
1475
+ const wallet = selectedWallet ? WALLET_INFO[selectedWallet] : null;
1476
+ switch (connectionStage) {
1477
+ case "connecting":
1478
+ return {
1479
+ title: `Waiting for ${(wallet == null ? void 0 : wallet.name) || "Wallet"}`,
1480
+ subtitle: CONNECTION_MESSAGES.CONNECTING,
1481
+ buttonText: "Connecting"
1482
+ };
1483
+ case "signing":
1484
+ return {
1485
+ title: "Sign to verify",
1486
+ subtitle: CONNECTION_MESSAGES.SIGNING,
1487
+ buttonText: "Signing"
1488
+ };
1489
+ case "success":
1490
+ return {
1491
+ title: `Connected to ${(wallet == null ? void 0 : wallet.name.replace(" Wallet", "")) || "Wallet"}`,
1492
+ subtitle: CONNECTION_MESSAGES.SUCCESS,
1493
+ buttonText: "Connected"
1494
+ };
1495
+ case "error":
1496
+ return {
1497
+ title: "Error",
1498
+ subtitle: CONNECTION_MESSAGES.ERROR,
1499
+ buttonText: "Close"
1500
+ };
1501
+ case "connected-not-signed":
1502
+ return {
1503
+ title: `Connected to ${(wallet == null ? void 0 : wallet.name.replace(" Wallet", "")) || "Wallet"}`,
1504
+ subtitle: CONNECTION_MESSAGES.CONNECTED_NOT_SIGNED,
1505
+ buttonText: "Connected"
1506
+ };
1507
+ default:
1508
+ return null;
1509
+ }
1510
+ }, [connectionStage, selectedWallet]);
1511
+ useEffect2(() => {
1512
+ const recent = getStorageItem(STORAGE_KEYS.RECENT_WALLET);
1513
+ if (recent && ["starkey", "ribbit"].includes(recent)) {
1514
+ setRecentWallet(recent);
1515
+ }
1516
+ }, []);
1517
+ useEffect2(() => {
1518
+ const checkWallets = () => {
1519
+ const wallets = getAvailableWallets();
1520
+ setAvailableWallets(wallets);
1521
+ };
1522
+ checkWallets();
1523
+ const interval = setInterval(checkWallets, TIMEOUTS.WALLET_CHECK_INTERVAL);
1524
+ const timeout = setTimeout(() => clearInterval(interval), TIMEOUTS.WALLET_CHECK_MAX_DURATION);
1525
+ return () => {
1526
+ clearInterval(interval);
1527
+ clearTimeout(timeout);
1528
+ };
1529
+ }, [getAvailableWallets]);
1530
+ useEffect2(() => {
1531
+ if (starKeyWalletHook.accounts.length > 0) {
1532
+ updateWalletBalance();
1533
+ }
1534
+ }, [starKeyWalletHook.accounts, starKeyWalletHook.selectedWallet]);
1535
+ useEffect2(() => {
1536
+ const handlePresignedState = () => {
1537
+ setConnectionStage(() => "signing");
1538
+ };
1539
+ const handlePostsignedState = () => {
1540
+ setConnectionStage("success");
1541
+ setTimeout(() => {
1542
+ setConnectionStage("idle");
1543
+ setShowWalletModal(false);
1544
+ updateWalletBalance();
1545
+ }, TIMEOUTS.MODAL_CLOSE_DELAY);
1546
+ };
1547
+ const handleWalletError = () => {
1548
+ if (connectionStage == "signing") {
1549
+ setConnectionStage(() => "connected-not-signed");
1550
+ } else {
1551
+ setConnectionStage(() => "error");
1552
+ }
1553
+ setTimeout(() => {
1554
+ setShowWalletModal(false);
1555
+ setSelectedWallet(null);
1556
+ setConnectionStage("idle");
1557
+ setLoading(false);
1558
+ }, TIMEOUTS.MODAL_CLOSE_DELAY);
1559
+ };
1560
+ const handleStarkeyEvents = (event) => {
1561
+ var _a, _b, _c;
1562
+ if ((_b = (_a = event == null ? void 0 : event.data) == null ? void 0 : _a.name) == null ? void 0 : _b.startsWith("starkey-")) {
1563
+ switch ((_c = event == null ? void 0 : event.data) == null ? void 0 : _c.name) {
1564
+ case "starkey-wallet-updated":
1565
+ case "starkey-wallet-connected":
1566
+ setTimeout(updateWalletBalance, 1);
1567
+ break;
1568
+ case "starkey-wallet-disconnected":
1569
+ setWalletBalance("0.00");
1570
+ break;
1571
+ }
1572
+ }
1573
+ };
1574
+ window.addEventListener("presigned-state", handlePresignedState);
1575
+ window.addEventListener("postsigned-state", handlePostsignedState);
1576
+ window.addEventListener("wallet-error", handleWalletError);
1577
+ window.addEventListener("message", handleStarkeyEvents);
1578
+ return () => {
1579
+ window.removeEventListener("presigned-state", handlePresignedState);
1580
+ window.removeEventListener("postsigned-state", handlePostsignedState);
1581
+ window.removeEventListener("wallet-error", handleWalletError);
1582
+ window.removeEventListener("message", handleStarkeyEvents);
1583
+ };
1584
+ }, [connectionStage]);
1585
+ useEffect2(() => {
1586
+ const handleProfileUpdated = (event) => {
1587
+ const { address, username, profileImage } = event.detail;
1588
+ if (starKeyWalletHook.accounts[0] === address) {
1589
+ setUserProfile({ address, username, profileImage });
1590
+ }
1591
+ };
1592
+ window.addEventListener("profile-updated", handleProfileUpdated);
1593
+ return () => {
1594
+ window.removeEventListener("profile-updated", handleProfileUpdated);
1595
+ };
1596
+ }, [starKeyWalletHook.accounts]);
1597
+ useEffect2(() => {
1598
+ if (starKeyWalletHook.accounts.length > 0) {
1599
+ const handleVisibilityChange = () => {
1600
+ if (!document.hidden) {
1601
+ updateWalletBalance();
1602
+ }
1603
+ };
1604
+ document.addEventListener("visibilitychange", handleVisibilityChange);
1605
+ const balanceInterval = setInterval(() => {
1606
+ if (!document.hidden) {
1607
+ updateWalletBalance();
1608
+ }
1609
+ }, TIMEOUTS.BALANCE_POLL_INTERVAL);
1610
+ return () => {
1611
+ clearInterval(balanceInterval);
1612
+ document.removeEventListener("visibilitychange", handleVisibilityChange);
1613
+ };
1614
+ }
1615
+ }, [starKeyWalletHook.accounts, updateWalletBalance]);
1616
+ useEffect2(() => {
1617
+ if (connectionStage === "connecting" || connectionStage === "signing") {
1618
+ setConnectionStageStartTime(Date.now());
1619
+ setCanClickOutside(false);
1620
+ const timer = setTimeout(() => {
1621
+ setCanClickOutside(true);
1622
+ }, TIMEOUTS.CLICK_OUTSIDE_DELAY);
1623
+ return () => clearTimeout(timer);
1624
+ } else {
1625
+ setConnectionStageStartTime(null);
1626
+ setCanClickOutside(false);
1627
+ }
1628
+ }, [connectionStage]);
1629
+ const handleModalClose = useCallback2((open) => {
1630
+ if (!open) {
1631
+ if (connectionStage === "idle" || connectionStage === "success" || connectionStage === "connected-not-signed" || connectionStage === "error" || canClickOutside && (connectionStage === "connecting" || connectionStage === "signing")) {
1632
+ setShowWalletModal(false);
1633
+ setSelectedWallet(null);
1634
+ setLoading(false);
1635
+ setCanClickOutside(false);
1636
+ setConnectionStageStartTime(null);
1637
+ setTimeout(() => {
1638
+ setConnectionStage("idle");
1639
+ }, 100);
1640
+ }
1641
+ }
1642
+ }, [connectionStage, canClickOutside]);
1643
+ return /* @__PURE__ */ jsxs2(Fragment, { children: [
1644
+ children({
1645
+ isConnected: starKeyWalletHook.accounts.length > 0,
1646
+ accounts: starKeyWalletHook.accounts,
1647
+ loading: loading || starKeyWalletHook.loading,
1648
+ balance: walletBalance,
1649
+ userProfile,
1650
+ handleConnect: handleConnectClick,
1651
+ handleDisconnect: handleDisconnectWallet
1652
+ }),
1653
+ /* @__PURE__ */ jsxs2(
1654
+ Dialog,
1655
+ {
1656
+ open: showWalletModal,
1657
+ onOpenChange: handleModalClose,
1658
+ children: [
1659
+ /* @__PURE__ */ jsx3(VisuallyHidden, { asChild: true, children: /* @__PURE__ */ jsx3(DialogTitle, { children: "Select a wallet" }) }),
1660
+ /* @__PURE__ */ jsx3(VisuallyHidden, { asChild: true, children: /* @__PURE__ */ jsx3(DialogDescription, { children: "Select a wallet to connect to MyDApp" }) }),
1661
+ /* @__PURE__ */ jsxs2(
1662
+ DialogContent,
1663
+ {
1664
+ className: "z-[100] px-4 py-6 w-[90%] mx-auto max-w-sm bg-gradient-to-br from-brand-dark via-gray-900 to-brand-dark border border-brand-dark sm:rounded-3xl rounded-3xl",
1665
+ children: [
1666
+ canClickOutside && (connectionStage === "connecting" || connectionStage === "signing") && /* @__PURE__ */ jsx3("div", { className: "absolute top-4 right-4", children: /* @__PURE__ */ jsx3(X2, { className: "h-5 w-5" }) }),
1667
+ /* @__PURE__ */ jsx3("div", { className: "", children: connectionStage === "idle" ? /* @__PURE__ */ jsxs2(Fragment, { children: [
1668
+ /* @__PURE__ */ jsx3("p", { className: "text-center text-sm text-brand-light/75 mb-6 text-white", children: "Select Wallet" }),
1669
+ /* @__PURE__ */ jsx3("div", { className: "space-y-3", children: availableWallets.map((wallet) => {
1670
+ return /* @__PURE__ */ jsx3("div", { className: "w-full relative", children: /* @__PURE__ */ jsxs2(
1671
+ motion.button,
1672
+ {
1673
+ initial: { opacity: 0, y: 20 },
1674
+ animate: { opacity: 1, y: 0 },
1675
+ transition: { duration: 0.05, ease: "easeInOut" },
1676
+ onClick: () => {
1677
+ wallet.isInstalled ? connectWallet(wallet.type) : window.open(WALLET_INFO[wallet.type].downloadUrl, "_blank");
1678
+ },
1679
+ type: "button",
1680
+ disabled: loading && wallet.isInstalled,
1681
+ onMouseEnter: () => setHoveredWallet(wallet.type),
1682
+ onMouseLeave: () => setHoveredWallet(null),
1683
+ className: "w-full px-4 py-2 rounded-2xl border border-gray-950/60 hover:border-gray-800/80 bg-gray-950/20 hover:bg-gray-900/40 transition-all duration-300 flex items-center gap-4 group",
1684
+ children: [
1685
+ /* @__PURE__ */ jsx3("div", { className: "flex-shrink-0", children: WALLET_INFO[wallet.type].icon }),
1686
+ /* @__PURE__ */ jsxs2("div", { className: "flex-1 text-left", children: [
1687
+ /* @__PURE__ */ jsx3("h3", { className: "font-medium text-white", children: WALLET_INFO[wallet.type].name }),
1688
+ !wallet.isInstalled && /* @__PURE__ */ jsx3("p", { className: "text-sm text-gray-400", children: "Not installed - Click to download" })
1689
+ ] }),
1690
+ /* @__PURE__ */ jsx3("div", { className: "flex-shrink-0", children: recentWallet === wallet.type && wallet.isInstalled ? /* @__PURE__ */ jsx3("span", { className: "bg-gray-800/60 text-gray-300 text-xs px-3 py-1 rounded-full border border-gray-700/40", children: "Recent" }) : wallet.isInstalled ? loading && wallet.type === selectedWallet ? /* @__PURE__ */ jsx3(Loader2, { className: "h-4 w-4 animate-spin text-gray-400" }) : hoveredWallet === wallet.type && /* @__PURE__ */ jsx3("span", { className: "text-gray-400 text-sm font-medium", children: "Connect" }) : /* @__PURE__ */ jsx3(ExternalLink, { className: "h-4 w-4 text-gray-500" }) })
1691
+ ]
1692
+ }
1693
+ ) }, wallet.type);
1694
+ }) })
1695
+ ] }) : /* @__PURE__ */ jsx3("div", { className: "w-full text-center py-8", children: (() => {
1696
+ const stageInfo = getConnectionStageInfo();
1697
+ const wallet = selectedWallet ? WALLET_INFO[selectedWallet] : null;
1698
+ return /* @__PURE__ */ jsxs2(Fragment, { children: [
1699
+ /* @__PURE__ */ jsx3("div", { className: "relative flex justify-center mb-6", children: connectionStage === "success" || connectionStage === "connected-not-signed" ? /* @__PURE__ */ jsx3("div", { className: "w-20 h-20 rounded-full border-4 border-green-500 flex items-center justify-center", children: wallet && /* @__PURE__ */ jsx3("div", { className: "w-12 h-12 flex items-center justify-center", children: wallet.icon }) }) : connectionStage === "error" ? /* @__PURE__ */ jsx3("div", { className: "w-20 h-20 rounded-full border-4 border-red-500 flex items-center justify-center", children: wallet && /* @__PURE__ */ jsx3("div", { className: "w-12 h-12 flex items-center justify-center", children: wallet.icon }) }) : /* @__PURE__ */ jsxs2("div", { className: "relative", children: [
1700
+ /* @__PURE__ */ jsx3("div", { className: "w-20 h-20 rounded-full border-4 border-gray-600 border-t-gray-400 animate-spin" }),
1701
+ /* @__PURE__ */ jsx3("div", { className: "absolute inset-0 flex items-center justify-center", children: wallet && /* @__PURE__ */ jsx3("div", { className: "w-12 h-12 flex items-center justify-center", children: wallet.icon }) })
1702
+ ] }) }),
1703
+ /* @__PURE__ */ jsx3("h3", { className: "text-lg font-semibold text-white mb-2", children: stageInfo == null ? void 0 : stageInfo.title }),
1704
+ /* @__PURE__ */ jsx3("p", { className: "text-sm text-gray-400 mb-6", children: stageInfo == null ? void 0 : stageInfo.subtitle }),
1705
+ /* @__PURE__ */ jsx3(
1706
+ Button,
1707
+ {
1708
+ disabled: true,
1709
+ className: "w-full bg-gray-700 text-gray-400 cursor-not-allowed rounded-2xl py-3",
1710
+ children: stageInfo == null ? void 0 : stageInfo.buttonText
1711
+ }
1712
+ )
1713
+ ] });
1714
+ })() }) })
1715
+ ]
1716
+ }
1717
+ )
1718
+ ]
1719
+ }
1720
+ )
1721
+ ] });
1722
+ };
1723
+
1724
+ // src/hooks/useSupraMultiWallet.ts
1725
+ import { useState as useState3, useEffect as useEffect3, useCallback as useCallback3 } from "react";
1726
+ import nacl2 from "tweetnacl";
1727
+ import { useRouter as useRouter2 } from "next/navigation";
1728
+ import { toast as toast3 } from "sonner";
1729
+ import {
1730
+ SupraChainId as SupraChainId2,
1731
+ initSdk as initSdk2
1732
+ } from "ribbit-wallet-connect";
1733
+ var WALLET_CONFIGS2 = {
1734
+ starkey: {
1735
+ capabilities: {
1736
+ signMessage: true,
1737
+ accountSwitching: true,
1738
+ networkSwitching: true,
1739
+ rawTransactions: true,
1740
+ eventListeners: true,
1741
+ tokenRevalidation: true
1742
+ },
1743
+ provider: () => {
1744
+ var _a;
1745
+ return typeof window !== "undefined" && ((_a = window == null ? void 0 : window.starkey) == null ? void 0 : _a.supra);
1746
+ }
1747
+ },
1748
+ ribbit: {
1749
+ capabilities: {
1750
+ signMessage: true,
1751
+ accountSwitching: false,
1752
+ // Ribbit doesn't support account switching
1753
+ networkSwitching: false,
1754
+ // Ribbit network switching happens in-app
1755
+ rawTransactions: true,
1756
+ eventListeners: false,
1757
+ tokenRevalidation: false
1758
+ // Ribbit doesn't support token revalidation
1759
+ },
1760
+ provider: () => initSdk2()
1761
+ }
1762
+ };
1763
+ var WALLET_EVENTS2 = {
1764
+ CONNECTED: "wallet-connected",
1765
+ PRESIGNED_STATE: "presigned-state",
1766
+ POSTSIGNED_STATE: "postsigned-state",
1767
+ ERROR: "wallet-error"
1768
+ };
1769
+ var setStoredWalletType2 = (walletType) => {
1770
+ setStorageItem(STORAGE_KEYS.SELECTED_WALLET, walletType);
1771
+ };
1772
+ var getStoredWalletType2 = () => {
1773
+ const stored = getStorageItem(STORAGE_KEYS.SELECTED_WALLET);
1774
+ if (stored && ["starkey", "ribbit"].includes(stored)) {
1775
+ return stored;
1776
+ }
1777
+ return "starkey";
1778
+ };
1779
+ var clearStoredWalletType2 = () => {
1780
+ removeStorageItem(STORAGE_KEYS.SELECTED_WALLET);
1781
+ };
1782
+ var useSupraMultiWallet2 = () => {
1783
+ const router = useRouter2();
1784
+ const [selectedWallet, setSelectedWallet] = useState3("starkey");
1785
+ const [walletCapabilities, setWalletCapabilities] = useState3(
1786
+ WALLET_CONFIGS2["starkey"].capabilities
1787
+ );
1788
+ useEffect3(() => {
1789
+ const stored = getStoredWalletType2();
1790
+ if (stored !== "starkey") {
1791
+ setSelectedWallet(stored);
1792
+ setWalletCapabilities(WALLET_CONFIGS2[stored].capabilities);
1793
+ }
1794
+ }, []);
1795
+ const [supraProvider, setSupraProvider] = useState3(
1796
+ WALLET_CONFIGS2.starkey.provider()
1797
+ );
1798
+ const [ribbitProvider, setRibbitProvider] = useState3(
1799
+ WALLET_CONFIGS2.ribbit.provider()
1800
+ );
1801
+ const [isExtensionInstalled, setIsExtensionInstalled] = useState3(false);
1802
+ const [accounts, setAccounts] = useState3([]);
1803
+ const [networkData, setNetworkData] = useState3();
1804
+ const [balance, setBalance] = useState3("");
1805
+ const [loading, setLoading] = useState3(false);
1806
+ const [justRequestedRelative, setJustRequestedRelative] = useState3(false);
1807
+ const [transactions, setTransactions] = useState3([]);
1808
+ const [selectedChainId, setSelectedChainId] = useState3("");
1809
+ const addTransactions = (hash) => {
1810
+ setTransactions((prev) => [{ hash }, ...prev]);
1811
+ };
1812
+ const getCurrentProvider = () => {
1813
+ switch (selectedWallet) {
1814
+ case "starkey": {
1815
+ return supraProvider;
1816
+ }
1817
+ case "ribbit": {
1818
+ return ribbitProvider;
1819
+ }
1820
+ default: {
1821
+ return supraProvider;
1822
+ }
1823
+ }
1824
+ };
1825
+ const checkExtensionInstalled = useCallback3(async () => {
1826
+ switch (selectedWallet) {
1827
+ case "starkey": {
1828
+ const provider = WALLET_CONFIGS2.starkey.provider();
1829
+ setSupraProvider(provider);
1830
+ setIsExtensionInstalled(!!provider);
1831
+ return !!provider;
1832
+ }
1833
+ case "ribbit": {
1834
+ const provider = WALLET_CONFIGS2.ribbit.provider();
1835
+ if (!provider) {
1836
+ setRibbitProvider(null);
1837
+ setIsExtensionInstalled(false);
1838
+ return false;
1839
+ }
1840
+ try {
1841
+ setRibbitProvider(provider);
1842
+ setIsExtensionInstalled(true);
1843
+ return true;
1844
+ } catch (error) {
1845
+ logger.error("Error checking Ribbit wallet readiness", error);
1846
+ setRibbitProvider(null);
1847
+ setIsExtensionInstalled(false);
1848
+ return false;
1849
+ }
1850
+ }
1851
+ default: {
1852
+ return false;
1853
+ }
1854
+ }
1855
+ }, [selectedWallet]);
1856
+ const updateAccounts = useCallback3(async () => {
1857
+ const provider = getCurrentProvider();
1858
+ if (!provider) return;
1859
+ try {
1860
+ switch (selectedWallet) {
1861
+ case "starkey": {
1862
+ const responseAcc = await provider.account();
1863
+ const newAccounts = responseAcc.length > 0 ? responseAcc : [];
1864
+ setAccounts(newAccounts);
1865
+ if (responseAcc.length > 0) {
1866
+ setStorageItem(STORAGE_KEYS.STARKEY_ACCOUNTS, responseAcc[0]);
1867
+ }
1868
+ if (newAccounts.length > 0) {
1869
+ const balance2 = await provider.balance();
1870
+ if (balance2) {
1871
+ setBalance(`${balance2.formattedBalance} ${balance2.displayUnit}`);
1872
+ }
1873
+ const networkData2 = await provider.getChainId();
1874
+ setNetworkData(networkData2 || {});
1875
+ }
1876
+ break;
1877
+ }
1878
+ case "ribbit": {
1879
+ const wallet = provider.getWalletInfo();
1880
+ if (wallet == null ? void 0 : wallet.connected) {
1881
+ setAccounts([wallet.walletAddress]);
1882
+ const walletBalanceRequest = {
1883
+ chainId: parseInt(getChainId()),
1884
+ resourceType: "0x1::supra_coin::SupraCoin",
1885
+ decimals: 8
1886
+ };
1887
+ const balanceStr = await provider.getWalletBalance(walletBalanceRequest);
1888
+ logger.debug("Ribbit balance response", { balance: balanceStr });
1889
+ setBalance(`${(balanceStr == null ? void 0 : balanceStr.balance) || 0} SUPRA`);
1890
+ } else {
1891
+ setAccounts([]);
1892
+ }
1893
+ break;
1894
+ }
1895
+ default: {
1896
+ setAccounts([]);
1897
+ break;
1898
+ }
1899
+ }
1900
+ } catch (error) {
1901
+ logger.error("Failed to update accounts", error, { walletType: selectedWallet });
1902
+ setAccounts([]);
1903
+ switch (selectedWallet) {
1904
+ case "starkey": {
1905
+ removeStorageItem(STORAGE_KEYS.STARKEY_ACCOUNTS);
1906
+ break;
1907
+ }
1908
+ case "ribbit": {
1909
+ break;
1910
+ }
1911
+ }
1912
+ }
1913
+ }, [selectedWallet]);
1914
+ useEffect3(() => {
1915
+ let mounted = true;
1916
+ const initProvider = async () => {
1917
+ const isInstalled = await checkExtensionInstalled();
1918
+ if (mounted && isInstalled) {
1919
+ updateAccounts();
1920
+ }
1921
+ };
1922
+ initProvider();
1923
+ return () => {
1924
+ mounted = false;
1925
+ };
1926
+ }, [selectedWallet, checkExtensionInstalled, updateAccounts]);
1927
+ useEffect3(() => {
1928
+ const checkExtension = async () => {
1929
+ return await checkExtensionInstalled();
1930
+ };
1931
+ checkExtension().then((isInstalled) => {
1932
+ if (isInstalled && selectedWallet === "ribbit") {
1933
+ updateAccounts();
1934
+ }
1935
+ });
1936
+ const intv = setInterval(async () => {
1937
+ const isInstalled = await checkExtension();
1938
+ if (isInstalled) {
1939
+ clearInterval(intv);
1940
+ if (selectedWallet === "ribbit") {
1941
+ updateAccounts();
1942
+ }
1943
+ }
1944
+ }, 1e3);
1945
+ setTimeout(() => {
1946
+ clearInterval(intv);
1947
+ }, TIMEOUTS.WALLET_DETECTION_POLL);
1948
+ return () => clearInterval(intv);
1949
+ }, [selectedWallet, updateAccounts, checkExtensionInstalled]);
1950
+ const checkIsExtensionInstalled = useCallback3(() => {
1951
+ const intervalId = setInterval(async () => {
1952
+ const isInstalled = await checkExtensionInstalled();
1953
+ if (isInstalled) {
1954
+ clearInterval(intervalId);
1955
+ updateAccounts();
1956
+ }
1957
+ }, 500);
1958
+ setTimeout(() => clearInterval(intervalId), TIMEOUTS.WALLET_DETECTION_POLL);
1959
+ }, [updateAccounts, checkExtensionInstalled]);
1960
+ const updateBalance = useCallback3(async () => {
1961
+ const provider = getCurrentProvider();
1962
+ if (!provider || !accounts.length) {
1963
+ setBalance("");
1964
+ return;
1965
+ }
1966
+ try {
1967
+ switch (selectedWallet) {
1968
+ case "starkey": {
1969
+ const balance2 = await provider.balance();
1970
+ if (balance2) {
1971
+ setBalance(`${balance2.formattedBalance} ${balance2.displayUnit}`);
1972
+ }
1973
+ break;
1974
+ }
1975
+ case "ribbit": {
1976
+ const walletBalanceRequest = {
1977
+ chainId: parseInt(getChainId()),
1978
+ resourceType: "0x1::supra_coin::SupraCoin",
1979
+ decimals: 8
1980
+ };
1981
+ const balanceStr = await provider.getWalletBalance(
1982
+ walletBalanceRequest
1983
+ );
1984
+ logger.debug("Ribbit balance response", { balance: balanceStr });
1985
+ setBalance(`${(balanceStr == null ? void 0 : balanceStr.balance) || 0} SUPRA`);
1986
+ break;
1987
+ }
1988
+ default: {
1989
+ setBalance("");
1990
+ break;
1991
+ }
1992
+ }
1993
+ } catch (error) {
1994
+ logger.error("Failed to update balance", error, { walletType: selectedWallet });
1995
+ setBalance("");
1996
+ }
1997
+ }, [selectedWallet, accounts]);
1998
+ const getNetworkData = useCallback3(async () => {
1999
+ const provider = getCurrentProvider();
2000
+ if (!provider) return {};
2001
+ try {
2002
+ switch (selectedWallet) {
2003
+ case "starkey": {
2004
+ const data = await provider.getChainId();
2005
+ setNetworkData(data || {});
2006
+ return data || {};
2007
+ }
2008
+ case "ribbit": {
2009
+ const chainId = parseInt(getChainId());
2010
+ const mockNetworkData = { chainId: chainId.toString() };
2011
+ setNetworkData(mockNetworkData);
2012
+ return mockNetworkData;
2013
+ }
2014
+ default: {
2015
+ setNetworkData({});
2016
+ return {};
2017
+ }
2018
+ }
2019
+ } catch (error) {
2020
+ logger.error("Failed to get network data", error, { walletType: selectedWallet });
2021
+ setNetworkData({});
2022
+ return {};
2023
+ }
2024
+ }, [selectedWallet]);
2025
+ const connectWallet = async (walletType) => {
2026
+ if (walletType) {
2027
+ updateSelectedWallet(walletType);
2028
+ }
2029
+ const provider = walletType ? WALLET_CONFIGS2[walletType].provider() : getCurrentProvider();
2030
+ if (!provider) {
2031
+ const error = new WalletNotInstalledError(walletType || selectedWallet);
2032
+ logger.warn("Wallet not installed", { walletType: walletType || selectedWallet });
2033
+ toast3.error(ERROR_MESSAGES.WALLET_NOT_INSTALLED, {
2034
+ description: `Please install the ${walletType || selectedWallet} extension`
2035
+ });
2036
+ return false;
2037
+ }
2038
+ setLoading(true);
2039
+ try {
2040
+ switch (walletType || selectedWallet) {
2041
+ case "starkey": {
2042
+ await provider.connect();
2043
+ logger.info("Starkey wallet connection approved");
2044
+ await updateAccounts();
2045
+ const responseAcc = await provider.account();
2046
+ if (responseAcc.length === 0) {
2047
+ throw new WalletConnectionError(ERROR_MESSAGES.NO_ACCOUNT_FOUND);
2048
+ }
2049
+ if (responseAcc.length) {
2050
+ setAccounts(responseAcc);
2051
+ setStorageItem(STORAGE_KEYS.IS_SIGNING_WALLET, "false");
2052
+ setStorageItem(STORAGE_KEYS.STARKEY_ACCOUNTS, responseAcc[0]);
2053
+ window.dispatchEvent(
2054
+ new CustomEvent(WALLET_EVENTS2.PRESIGNED_STATE, {
2055
+ detail: {
2056
+ timestamp: Date.now(),
2057
+ account: responseAcc[0]
2058
+ }
2059
+ })
2060
+ );
2061
+ window.dispatchEvent(
2062
+ new CustomEvent(WALLET_EVENTS2.CONNECTED, {
2063
+ detail: {
2064
+ timestamp: Date.now(),
2065
+ account: responseAcc[0],
2066
+ wallet: "starkey"
2067
+ }
2068
+ })
2069
+ );
2070
+ try {
2071
+ const message = "To verify your account, please sign this message.";
2072
+ const nonce = generateNonce();
2073
+ const hexMessage = "0x" + Buffer.from(message, "utf8").toString("hex");
2074
+ logger.debug("Signature request initiated", { account: responseAcc[0] });
2075
+ const signatureResponse = await provider.signMessage({
2076
+ message: hexMessage,
2077
+ nonce
2078
+ });
2079
+ if (signatureResponse) {
2080
+ logger.info("Signature approved", { account: responseAcc[0] });
2081
+ window.dispatchEvent(
2082
+ new CustomEvent(WALLET_EVENTS2.POSTSIGNED_STATE, {
2083
+ detail: {
2084
+ timestamp: Date.now(),
2085
+ account: responseAcc[0]
2086
+ }
2087
+ })
2088
+ );
2089
+ }
2090
+ } catch (signError) {
2091
+ const error = new SignMessageError(ERROR_MESSAGES.SIGNING_FAILED, signError);
2092
+ logger.error("Signing failed", error, { account: responseAcc[0] });
2093
+ window.dispatchEvent(
2094
+ new CustomEvent(WALLET_EVENTS2.ERROR, {
2095
+ detail: {
2096
+ timestamp: Date.now(),
2097
+ error
2098
+ }
2099
+ })
2100
+ );
2101
+ throw error;
2102
+ }
2103
+ }
2104
+ break;
2105
+ }
2106
+ case "ribbit": {
2107
+ const dappMetadata = {
2108
+ name: "multiwallet",
2109
+ description: "NFT Marketplace and Lootbox Platform",
2110
+ logo: window.location.origin + "/favicon.ico",
2111
+ url: window.location.origin
2112
+ };
2113
+ const response = await provider.connectToWallet(
2114
+ dappMetadata
2115
+ );
2116
+ if (response == null ? void 0 : response.connected) {
2117
+ logger.info("Ribbit wallet connection approved");
2118
+ }
2119
+ if (response.walletAddress == null) {
2120
+ throw new WalletConnectionError(ERROR_MESSAGES.NO_ACCOUNT_FOUND);
2121
+ }
2122
+ if (response == null ? void 0 : response.connected) {
2123
+ await updateAccounts();
2124
+ if (response.walletAddress) {
2125
+ setAccounts([response.walletAddress]);
2126
+ setStorageItem(STORAGE_KEYS.IS_SIGNING_WALLET, "false");
2127
+ window.dispatchEvent(
2128
+ new CustomEvent(WALLET_EVENTS2.PRESIGNED_STATE, {
2129
+ detail: {
2130
+ timestamp: Date.now(),
2131
+ account: response.walletAddress
2132
+ }
2133
+ })
2134
+ );
2135
+ window.dispatchEvent(
2136
+ new CustomEvent(WALLET_EVENTS2.CONNECTED, {
2137
+ detail: {
2138
+ timestamp: Date.now(),
2139
+ account: response.walletAddress,
2140
+ wallet: "ribbit"
2141
+ }
2142
+ })
2143
+ );
2144
+ try {
2145
+ const message = "To verify your account, please sign this message.";
2146
+ const nonce = generateNonce();
2147
+ const hexMessage = "0x" + Buffer.from(message, "utf8").toString("hex");
2148
+ logger.debug("Signature request initiated", { account: response.walletAddress });
2149
+ const signatureResponse = await provider.signMessage({
2150
+ message: hexMessage,
2151
+ nonce: parseInt(nonce),
2152
+ chainId: parseInt(getChainId())
2153
+ });
2154
+ if (signatureResponse && signatureResponse.approved) {
2155
+ logger.info("Signature approved", { account: response.walletAddress });
2156
+ window.dispatchEvent(
2157
+ new CustomEvent(WALLET_EVENTS2.POSTSIGNED_STATE, {
2158
+ detail: {
2159
+ timestamp: Date.now(),
2160
+ account: response.walletAddress
2161
+ }
2162
+ })
2163
+ );
2164
+ } else {
2165
+ throw new SignMessageError(signatureResponse.error || ERROR_MESSAGES.SIGNING_REJECTED);
2166
+ }
2167
+ } catch (signError) {
2168
+ const error = new SignMessageError(ERROR_MESSAGES.SIGNING_FAILED, signError);
2169
+ logger.error("Signing failed", error, { account: response.walletAddress });
2170
+ window.dispatchEvent(
2171
+ new CustomEvent(WALLET_EVENTS2.ERROR, {
2172
+ detail: {
2173
+ timestamp: Date.now(),
2174
+ error
2175
+ }
2176
+ })
2177
+ );
2178
+ throw error;
2179
+ }
2180
+ }
2181
+ } else {
2182
+ throw new WalletConnectionError(ERROR_MESSAGES.CONNECTION_REJECTED);
2183
+ }
2184
+ break;
2185
+ }
2186
+ default: {
2187
+ throw new WalletConnectionError(
2188
+ `${ERROR_MESSAGES.UNSUPPORTED_WALLET}: ${walletType || selectedWallet}`
2189
+ );
2190
+ }
2191
+ }
2192
+ return true;
2193
+ } catch (error) {
2194
+ const walletError = error instanceof WalletConnectionError ? error : new WalletConnectionError(ERROR_MESSAGES.CONNECTION_FAILED, error);
2195
+ logger.error("Wallet connection failed", walletError, {
2196
+ walletType: walletType || selectedWallet
2197
+ });
2198
+ window.dispatchEvent(
2199
+ new CustomEvent(WALLET_EVENTS2.ERROR, {
2200
+ detail: {
2201
+ timestamp: Date.now(),
2202
+ error: walletError
2203
+ }
2204
+ })
2205
+ );
2206
+ return false;
2207
+ } finally {
2208
+ setLoading(false);
2209
+ }
2210
+ };
2211
+ const disconnectWallet = async () => {
2212
+ const provider = getCurrentProvider();
2213
+ if (!provider) return;
2214
+ try {
2215
+ switch (selectedWallet) {
2216
+ case "starkey": {
2217
+ await provider.disconnect();
2218
+ break;
2219
+ }
2220
+ case "ribbit": {
2221
+ await provider.disconnect();
2222
+ break;
2223
+ }
2224
+ }
2225
+ resetWalletData();
2226
+ clearStoredWalletType2();
2227
+ router.push("/");
2228
+ } catch (error) {
2229
+ logger.error("Wallet disconnect failed", error, { walletType: selectedWallet });
2230
+ resetWalletData();
2231
+ clearStoredWalletType2();
2232
+ }
2233
+ };
2234
+ const resetWalletData = () => {
2235
+ setAccounts([]);
2236
+ setBalance("");
2237
+ setNetworkData({});
2238
+ switch (selectedWallet) {
2239
+ case "starkey": {
2240
+ setStorageItem(STORAGE_KEYS.IS_SIGNING_WALLET, "false");
2241
+ removeStorageItem(STORAGE_KEYS.STARKEY_ACCOUNTS);
2242
+ break;
2243
+ }
2244
+ case "ribbit": {
2245
+ break;
2246
+ }
2247
+ }
2248
+ };
2249
+ const getSequenceNumber = async (address) => {
2250
+ const rpcUrl = getRpcUrl();
2251
+ const data = await fetch(`${rpcUrl}/rpc/v1/accounts/${address}`);
2252
+ if (!data.ok) {
2253
+ throw new NetworkError(`Failed to fetch sequence number for ${address}`);
2254
+ }
2255
+ const accountData = await data.json();
2256
+ return accountData.sequence_number;
2257
+ };
2258
+ const sendRawTransaction = async (moduleAddress, moduleName, functionName, params, runTimeParams = [], txExpiryTime = Math.ceil(Date.now() / 1e3) + 3e3) => {
2259
+ const provider = getCurrentProvider();
2260
+ if (!provider || !accounts.length || !moduleAddress || !moduleName || !functionName)
2261
+ return;
2262
+ try {
2263
+ switch (selectedWallet) {
2264
+ case "starkey": {
2265
+ if (!walletCapabilities.rawTransactions) {
2266
+ throw new TransactionError("Raw transactions not supported by current wallet");
2267
+ }
2268
+ let networkData2 = await getNetworkData();
2269
+ const currentChainId = getChainId();
2270
+ if (networkData2.chainId !== currentChainId) {
2271
+ setSelectedChainId(currentChainId);
2272
+ await provider.changeNetwork({
2273
+ chainId: currentChainId
2274
+ });
2275
+ }
2276
+ const rawTxPayload = [
2277
+ accounts[0],
2278
+ 0,
2279
+ // sequence number
2280
+ moduleAddress,
2281
+ moduleName,
2282
+ functionName,
2283
+ runTimeParams,
2284
+ params,
2285
+ {}
2286
+ ];
2287
+ const data = await provider.createRawTransactionData(rawTxPayload);
2288
+ const txHash = await provider.sendTransaction({
2289
+ data,
2290
+ from: accounts[0],
2291
+ to: moduleAddress,
2292
+ chainId: currentChainId,
2293
+ value: ""
2294
+ });
2295
+ addTransactions(txHash || "failed");
2296
+ logger.info("Transaction sent successfully", { txHash, walletType: "starkey" });
2297
+ return txHash;
2298
+ }
2299
+ case "ribbit": {
2300
+ if (!walletCapabilities.rawTransactions) {
2301
+ throw new TransactionError("Raw transactions not supported by current wallet");
2302
+ }
2303
+ const currentChainId = getChainId();
2304
+ let chainId = SupraChainId2.TESTNET;
2305
+ if (currentChainId === DEFAULT_CHAIN_IDS.TESTNET) {
2306
+ chainId = SupraChainId2.TESTNET;
2307
+ } else if (currentChainId === DEFAULT_CHAIN_IDS.MAINNET) {
2308
+ chainId = SupraChainId2.MAINNET;
2309
+ }
2310
+ const rawTxnRequest = {
2311
+ sender: accounts[0],
2312
+ // Use actual sender address
2313
+ moduleAddress,
2314
+ // Use provided module address
2315
+ moduleName,
2316
+ // Use provided module name
2317
+ functionName,
2318
+ // Use provided function name
2319
+ typeArgs: runTimeParams,
2320
+ // Use converted runtime parameters
2321
+ args: params || [],
2322
+ // Use provided parameters
2323
+ chainId
2324
+ };
2325
+ const rawTxnBase64 = await provider.createRawTransactionBuffer(rawTxnRequest);
2326
+ const response = await provider.signAndSendRawTransaction({
2327
+ rawTxn: rawTxnBase64,
2328
+ chainId,
2329
+ meta: {
2330
+ description: `Call ${moduleName}::${functionName}`
2331
+ // Dynamic description
2332
+ }
2333
+ });
2334
+ if (response.approved) {
2335
+ const txHash = response.txHash || response.result || "success";
2336
+ addTransactions(txHash);
2337
+ logger.info("Transaction sent successfully", { txHash, walletType: "ribbit" });
2338
+ return txHash;
2339
+ } else {
2340
+ throw new TransactionError(response.error || ERROR_MESSAGES.TRANSACTION_REJECTED);
2341
+ }
2342
+ }
2343
+ default: {
2344
+ throw new TransactionError(
2345
+ `Raw transactions not supported for wallet: ${selectedWallet}`
2346
+ );
2347
+ }
2348
+ }
2349
+ } catch (error) {
2350
+ const txError = error instanceof TransactionError ? error : new TransactionError(ERROR_MESSAGES.TRANSACTION_FAILED, void 0, error);
2351
+ logger.error("Transaction failed", txError, {
2352
+ walletType: selectedWallet,
2353
+ moduleAddress,
2354
+ moduleName,
2355
+ functionName
2356
+ });
2357
+ throw txError;
2358
+ }
2359
+ };
2360
+ const signMessage = async (message, nonce, account, forceSign = false) => {
2361
+ const provider = getCurrentProvider();
2362
+ if (!provider) return;
2363
+ const secureNonce = nonce || generateNonce();
2364
+ switch (selectedWallet) {
2365
+ case "starkey": {
2366
+ if (!walletCapabilities.signMessage) {
2367
+ throw new SignMessageError("Message signing not supported by current wallet");
2368
+ }
2369
+ if (!accounts.length && !account) return;
2370
+ if (!accounts.length && account) {
2371
+ accounts[0] = account;
2372
+ }
2373
+ if (getStorageItem(STORAGE_KEYS.IS_SIGNING_WALLET) === "true" && !forceSign) {
2374
+ return;
2375
+ }
2376
+ setStorageItem(STORAGE_KEYS.IS_SIGNING_WALLET, "true");
2377
+ try {
2378
+ const hexMessage = "0x" + Buffer.from(message, "utf8").toString("hex");
2379
+ const response = await provider.signMessage({
2380
+ message: hexMessage,
2381
+ nonce: secureNonce
2382
+ });
2383
+ const { publicKey, signature } = response;
2384
+ const verified = nacl2.sign.detached.verify(
2385
+ new TextEncoder().encode(message),
2386
+ Uint8Array.from(Buffer.from(signature.slice(2), "hex")),
2387
+ Uint8Array.from(Buffer.from(publicKey.slice(2), "hex"))
2388
+ );
2389
+ setStorageItem(STORAGE_KEYS.IS_SIGNING_WALLET, "false");
2390
+ logger.info("Message signed successfully", { walletType: "starkey" });
2391
+ return __spreadProps(__spreadValues({}, response), { verified });
2392
+ } catch (error) {
2393
+ setStorageItem(STORAGE_KEYS.IS_SIGNING_WALLET, "false");
2394
+ throw new SignMessageError(ERROR_MESSAGES.SIGNING_FAILED, error);
2395
+ }
2396
+ }
2397
+ case "ribbit": {
2398
+ if (!walletCapabilities.signMessage) {
2399
+ throw new SignMessageError("Message signing not supported by current wallet");
2400
+ }
2401
+ if (!accounts.length && !account) return;
2402
+ if (!accounts.length && account) {
2403
+ accounts[0] = account;
2404
+ }
2405
+ if (getStorageItem(STORAGE_KEYS.IS_SIGNING_WALLET) === "true" && !forceSign) {
2406
+ return;
2407
+ }
2408
+ setStorageItem(STORAGE_KEYS.IS_SIGNING_WALLET, "true");
2409
+ try {
2410
+ const hexMessage = "0x" + Buffer.from(message, "utf8").toString("hex");
2411
+ const response = await provider.signMessage({
2412
+ message: hexMessage,
2413
+ nonce: parseInt(secureNonce),
2414
+ chainId: parseInt(getChainId())
2415
+ });
2416
+ if (response.approved && response.publicKey && response.signature) {
2417
+ const { publicKey, signature } = response;
2418
+ const verified = nacl2.sign.detached.verify(
2419
+ new TextEncoder().encode(message),
2420
+ Uint8Array.from(Buffer.from(signature.slice(2), "hex")),
2421
+ Uint8Array.from(Buffer.from(publicKey.slice(2), "hex"))
2422
+ );
2423
+ setStorageItem(STORAGE_KEYS.IS_SIGNING_WALLET, "false");
2424
+ logger.info("Message signed successfully", { walletType: "ribbit" });
2425
+ return __spreadProps(__spreadValues({}, response), { verified });
2426
+ } else {
2427
+ setStorageItem(STORAGE_KEYS.IS_SIGNING_WALLET, "false");
2428
+ throw new SignMessageError(response.error || ERROR_MESSAGES.SIGNING_REJECTED);
2429
+ }
2430
+ } catch (error) {
2431
+ setStorageItem(STORAGE_KEYS.IS_SIGNING_WALLET, "false");
2432
+ throw new SignMessageError(ERROR_MESSAGES.SIGNING_FAILED, error);
2433
+ }
2434
+ }
2435
+ default: {
2436
+ throw new SignMessageError(
2437
+ `Message signing not supported for wallet: ${selectedWallet}`
2438
+ );
2439
+ }
2440
+ }
2441
+ };
2442
+ useEffect3(() => {
2443
+ if (selectedWallet === "starkey" && walletCapabilities.eventListeners) {
2444
+ const handleExtensionEvents = (event) => {
2445
+ var _a, _b, _c;
2446
+ if ((_b = (_a = event == null ? void 0 : event.data) == null ? void 0 : _a.name) == null ? void 0 : _b.startsWith("starkey-")) {
2447
+ switch ((_c = event == null ? void 0 : event.data) == null ? void 0 : _c.name) {
2448
+ case "starkey-extension-installed": {
2449
+ checkIsExtensionInstalled();
2450
+ break;
2451
+ }
2452
+ case "starkey-wallet-updated": {
2453
+ (async () => {
2454
+ const responseAcc = await supraProvider.account();
2455
+ if (responseAcc.length) {
2456
+ setAccounts(responseAcc);
2457
+ window.dispatchEvent(
2458
+ new CustomEvent(WALLET_EVENTS2.CONNECTED, {
2459
+ detail: {
2460
+ timestamp: Date.now(),
2461
+ account: responseAcc[0]
2462
+ }
2463
+ })
2464
+ );
2465
+ await updateBalance();
2466
+ await getNetworkData();
2467
+ } else {
2468
+ logger.debug("Starkey wallet updated: No accounts found - Resetting");
2469
+ resetWalletData();
2470
+ }
2471
+ setLoading(false);
2472
+ })();
2473
+ break;
2474
+ }
2475
+ case "starkey-wallet-disconnected": {
2476
+ resetWalletData();
2477
+ router.push("/");
2478
+ setLoading(false);
2479
+ break;
2480
+ }
2481
+ case "starkey-window-removed": {
2482
+ setLoading(false);
2483
+ break;
2484
+ }
2485
+ }
2486
+ }
2487
+ };
2488
+ checkIsExtensionInstalled();
2489
+ window.addEventListener("message", handleExtensionEvents);
2490
+ return () => window.removeEventListener("message", handleExtensionEvents);
2491
+ }
2492
+ }, [selectedWallet, walletCapabilities, supraProvider]);
2493
+ const getAvailableWallets = useCallback3(() => {
2494
+ const availableWallets = [];
2495
+ Object.entries(WALLET_CONFIGS2).forEach(([walletType, config2]) => {
2496
+ const provider = config2.provider();
2497
+ const isInstalled = !!provider;
2498
+ switch (walletType) {
2499
+ case "starkey": {
2500
+ availableWallets.push({
2501
+ type: "starkey",
2502
+ name: "Starkey Wallet",
2503
+ isInstalled,
2504
+ capabilities: config2.capabilities
2505
+ });
2506
+ break;
2507
+ }
2508
+ case "ribbit": {
2509
+ availableWallets.push({
2510
+ type: "ribbit",
2511
+ name: "Ribbit Wallet",
2512
+ isInstalled,
2513
+ capabilities: config2.capabilities
2514
+ });
2515
+ break;
2516
+ }
2517
+ }
2518
+ });
2519
+ return availableWallets;
2520
+ }, []);
2521
+ const updateSelectedWallet = (walletType) => {
2522
+ setSelectedWallet(walletType);
2523
+ setWalletCapabilities(WALLET_CONFIGS2[walletType].capabilities);
2524
+ setStoredWalletType2(walletType);
2525
+ };
2526
+ return {
2527
+ // New wallet selection functionality
2528
+ selectedWallet,
2529
+ walletCapabilities,
2530
+ getAvailableWallets,
2531
+ // Add this new function
2532
+ // Existing interface (unchanged)
2533
+ getCurrentProvider,
2534
+ isExtensionInstalled,
2535
+ accounts,
2536
+ networkData,
2537
+ balance,
2538
+ transactions,
2539
+ selectedChainId,
2540
+ connectWallet,
2541
+ // Now accepts optional walletType parameter
2542
+ disconnectWallet,
2543
+ sendRawTransaction,
2544
+ signMessage,
2545
+ setSelectedChainId,
2546
+ // switchToChain,
2547
+ loading
2548
+ // authFetch,
2549
+ // checkAndRevalidateToken,
2550
+ // signIn,
2551
+ };
2552
+ };
2553
+ var useSupraMultiWallet_default2 = useSupraMultiWallet2;
2554
+
2555
+ // src/hooks/useConversionUtils.ts
2556
+ import { useCallback as useCallback4 } from "react";
2557
+ import { BCS as BCS3, TxnBuilderTypes } from "supra-l1-sdk-core";
2558
+
2559
+ // src/lib/abis/supra_account.ts
2560
+ var supraAccountABI = {
2561
+ address: "0x1",
2562
+ name: "supra_account",
2563
+ friends: [
2564
+ "0x1::genesis",
2565
+ "0x1::resource_account",
2566
+ "0x1::transaction_fee",
2567
+ "0x1::transaction_validation"
2568
+ ],
2569
+ exposed_functions: [
2570
+ {
2571
+ name: "assert_account_exists",
2572
+ visibility: "public",
2573
+ is_entry: false,
2574
+ is_view: false,
2575
+ generic_type_params: [],
2576
+ params: ["address"],
2577
+ return: []
2578
+ },
2579
+ {
2580
+ name: "assert_account_is_registered_for_apt",
2581
+ visibility: "public",
2582
+ is_entry: false,
2583
+ is_view: false,
2584
+ generic_type_params: [],
2585
+ params: ["address"],
2586
+ return: []
2587
+ },
2588
+ {
2589
+ name: "assert_account_is_registered_for_supra",
2590
+ visibility: "public",
2591
+ is_entry: false,
2592
+ is_view: false,
2593
+ generic_type_params: [],
2594
+ params: ["address"],
2595
+ return: []
2596
+ },
2597
+ {
2598
+ name: "batch_transfer",
2599
+ visibility: "public",
2600
+ is_entry: true,
2601
+ is_view: false,
2602
+ generic_type_params: [],
2603
+ params: ["&signer", "vector<address>", "vector<u64>"],
2604
+ return: []
2605
+ },
2606
+ {
2607
+ name: "batch_transfer_coins",
2608
+ visibility: "public",
2609
+ is_entry: true,
2610
+ is_view: false,
2611
+ generic_type_params: [{ constraints: [] }],
2612
+ params: ["&signer", "vector<address>", "vector<u64>"],
2613
+ return: []
2614
+ },
2615
+ {
2616
+ name: "burn_from_fungible_store",
2617
+ visibility: "friend",
2618
+ is_entry: false,
2619
+ is_view: false,
2620
+ generic_type_params: [],
2621
+ params: ["&0x1::fungible_asset::BurnRef", "address", "u64"],
2622
+ return: []
2623
+ },
2624
+ {
2625
+ name: "can_receive_direct_coin_transfers",
2626
+ visibility: "public",
2627
+ is_entry: false,
2628
+ is_view: true,
2629
+ generic_type_params: [],
2630
+ params: ["address"],
2631
+ return: ["bool"]
2632
+ },
2633
+ {
2634
+ name: "create_account",
2635
+ visibility: "public",
2636
+ is_entry: true,
2637
+ is_view: false,
2638
+ generic_type_params: [],
2639
+ params: ["address"],
2640
+ return: []
2641
+ },
2642
+ {
2643
+ name: "deposit_coins",
2644
+ visibility: "public",
2645
+ is_entry: false,
2646
+ is_view: false,
2647
+ generic_type_params: [{ constraints: [] }],
2648
+ params: ["address", "0x1::coin::Coin<T0>"],
2649
+ return: []
2650
+ },
2651
+ {
2652
+ name: "is_fungible_balance_at_least",
2653
+ visibility: "friend",
2654
+ is_entry: false,
2655
+ is_view: false,
2656
+ generic_type_params: [],
2657
+ params: ["address", "u64"],
2658
+ return: ["bool"]
2659
+ },
2660
+ {
2661
+ name: "register_supra",
2662
+ visibility: "friend",
2663
+ is_entry: false,
2664
+ is_view: false,
2665
+ generic_type_params: [],
2666
+ params: ["&signer"],
2667
+ return: []
2668
+ },
2669
+ {
2670
+ name: "set_allow_direct_coin_transfers",
2671
+ visibility: "public",
2672
+ is_entry: true,
2673
+ is_view: false,
2674
+ generic_type_params: [],
2675
+ params: ["&signer", "bool"],
2676
+ return: []
2677
+ },
2678
+ {
2679
+ name: "transfer",
2680
+ visibility: "public",
2681
+ is_entry: true,
2682
+ is_view: false,
2683
+ generic_type_params: [],
2684
+ params: ["&signer", "address", "u64"],
2685
+ return: []
2686
+ },
2687
+ {
2688
+ name: "transfer_coins",
2689
+ visibility: "public",
2690
+ is_entry: true,
2691
+ is_view: false,
2692
+ generic_type_params: [{ constraints: [] }],
2693
+ params: ["&signer", "address", "u64"],
2694
+ return: []
2695
+ }
2696
+ ],
2697
+ structs: [
2698
+ {
2699
+ name: "DirectCoinTransferConfigUpdated",
2700
+ is_native: false,
2701
+ abilities: ["drop", "store"],
2702
+ generic_type_params: [],
2703
+ fields: [
2704
+ { name: "account", type: "address" },
2705
+ { name: "new_allow_direct_transfers", type: "bool" }
2706
+ ]
2707
+ },
2708
+ {
2709
+ name: "DirectCoinTransferConfigUpdatedEvent",
2710
+ is_native: false,
2711
+ abilities: ["drop", "store"],
2712
+ generic_type_params: [],
2713
+ fields: [{ name: "new_allow_direct_transfers", type: "bool" }]
2714
+ },
2715
+ {
2716
+ name: "DirectTransferConfig",
2717
+ is_native: false,
2718
+ abilities: ["key"],
2719
+ generic_type_params: [],
2720
+ fields: [
2721
+ { name: "allow_arbitrary_coin_transfers", type: "bool" },
2722
+ {
2723
+ name: "update_coin_transfer_events",
2724
+ type: "0x1::event::EventHandle<0x1::supra_account::DirectCoinTransferConfigUpdatedEvent>"
2725
+ }
2726
+ ]
2727
+ }
2728
+ ]
2729
+ };
2730
+
2731
+ // src/lib/utils.ts
2732
+ import { clsx as clsx2 } from "clsx";
2733
+ import { twMerge as twMerge2 } from "tailwind-merge";
2734
+ function cn2(...inputs) {
2735
+ return twMerge2(clsx2(inputs));
2736
+ }
2737
+ function standardizeAddress(address) {
2738
+ let cleanAddress = address.replace(/^0x/, "");
2739
+ if (cleanAddress.length < 64) {
2740
+ cleanAddress = cleanAddress.padStart(64, "0");
2741
+ }
2742
+ if (cleanAddress.length > 64) {
2743
+ throw new Error(`Address ${address} is not a valid address`);
2744
+ }
2745
+ return `0x${cleanAddress}`;
2746
+ }
2747
+
2748
+ // src/lib/abiStorage.ts
2749
+ var abiStorage = {
2750
+ [standardizeAddress("0x1")]: {
2751
+ supra_account: supraAccountABI
2752
+ }
2753
+ };
2754
+ function getStoredABI(moduleAddress, moduleName) {
2755
+ var _a;
2756
+ const standardizedAddress = standardizeAddress(moduleAddress);
2757
+ const normalizedName = moduleName;
2758
+ if ((_a = abiStorage[standardizedAddress]) == null ? void 0 : _a[normalizedName]) {
2759
+ return abiStorage[standardizedAddress][normalizedName];
2760
+ }
2761
+ return null;
2762
+ }
2763
+
2764
+ // src/hooks/useConversionUtils.ts
2765
+ var useConversionUtils = () => {
2766
+ const stringToUint8Array = useCallback4((humanReadableStr) => {
2767
+ return BCS3.bcsToBytes(new TxnBuilderTypes.Identifier(humanReadableStr));
2768
+ }, []);
2769
+ const serializeString = useCallback4((humanReadableStr) => {
2770
+ return BCS3.bcsSerializeStr(humanReadableStr);
2771
+ }, []);
2772
+ const addressToUint8Array = useCallback4((cryptoAddress) => {
2773
+ return BCS3.bcsToBytes(TxnBuilderTypes.AccountAddress.fromHex(cryptoAddress));
2774
+ }, []);
2775
+ const deserializeString = (uint8Array) => {
2776
+ return BCS3.bcsSerializeStr(uint8Array);
2777
+ };
2778
+ const deserializeVector = (uint8Array) => {
2779
+ const deserializer = new BCS3.Deserializer(uint8Array);
2780
+ return BCS3.deserializeVector(deserializer, BCS3.bcsSerializeU8);
2781
+ };
2782
+ const serializeUint8 = useCallback4((value) => {
2783
+ const num = typeof value === "string" ? parseInt(value, 10) : value;
2784
+ if (num < 0 || num > 255) {
2785
+ throw new Error(`u8 value out of range: ${num}`);
2786
+ }
2787
+ return BCS3.bcsSerializeU8(num);
2788
+ }, []);
2789
+ const serializeUint16 = useCallback4((value) => {
2790
+ let num;
2791
+ if (typeof value === "string") {
2792
+ num = parseInt(value, 10);
2793
+ } else if (typeof value === "bigint") {
2794
+ num = Number(value);
2795
+ } else {
2796
+ num = value;
2797
+ }
2798
+ if (num < 0 || num > 65535) {
2799
+ throw new Error(`u16 value out of range: ${num}`);
2800
+ }
2801
+ return BCS3.bcsSerializeU16(num);
2802
+ }, []);
2803
+ const serializeUint32 = useCallback4((value) => {
2804
+ let num;
2805
+ if (typeof value === "string") {
2806
+ num = parseInt(value, 10);
2807
+ } else if (typeof value === "bigint") {
2808
+ num = Number(value);
2809
+ } else {
2810
+ num = value;
2811
+ }
2812
+ if (num < 0 || num > 4294967295) {
2813
+ throw new Error(`u32 value out of range: ${num}`);
2814
+ }
2815
+ return BCS3.bcsSerializeU32(num);
2816
+ }, []);
2817
+ const serializeUint64 = useCallback4((value) => {
2818
+ let num;
2819
+ if (typeof value === "string") {
2820
+ num = BigInt(value);
2821
+ } else if (typeof value === "number") {
2822
+ num = BigInt(value);
2823
+ } else {
2824
+ num = value;
2825
+ }
2826
+ if (num < 0) {
2827
+ throw new Error(`u64 value cannot be negative: ${num}`);
2828
+ }
2829
+ return BCS3.bcsSerializeUint64(num);
2830
+ }, []);
2831
+ const serializeUint128 = useCallback4((value) => {
2832
+ let num;
2833
+ if (typeof value === "string") {
2834
+ num = BigInt(value);
2835
+ } else if (typeof value === "number") {
2836
+ num = BigInt(value);
2837
+ } else {
2838
+ num = value;
2839
+ }
2840
+ if (num < 0) {
2841
+ throw new Error(`u128 value cannot be negative: ${num}`);
2842
+ }
2843
+ return BCS3.bcsSerializeU128(num);
2844
+ }, []);
2845
+ const serializeU256 = useCallback4((value) => {
2846
+ return BCS3.bcsSerializeU256(value);
2847
+ }, []);
2848
+ const serializeBool = useCallback4((value) => {
2849
+ return BCS3.bcsSerializeBool(value);
2850
+ }, []);
2851
+ const serializeVector = useCallback4((values, type) => {
2852
+ const serializer = new BCS3.Serializer();
2853
+ serializer.serializeU32AsUleb128(values.length);
2854
+ values.forEach((value) => {
2855
+ if (type === "u64") {
2856
+ serializer.serializeU64(value);
2857
+ } else if (type === "bool") {
2858
+ serializer.serializeBool(value);
2859
+ } else if (type === "string") {
2860
+ serializer.serializeStr(value);
2861
+ } else if (type === "address") {
2862
+ const accountAddress = TxnBuilderTypes.AccountAddress.fromHex(value);
2863
+ serializer.serializeFixedBytes(accountAddress.address);
2864
+ } else {
2865
+ serializer.serializeStr(value);
2866
+ }
2867
+ });
2868
+ return serializer.getBytes();
2869
+ }, []);
2870
+ const hexToString = (hex, type) => {
2871
+ if (!hex) {
2872
+ return "";
2873
+ }
2874
+ if (type !== "String") {
2875
+ try {
2876
+ return BigInt(hex).toString();
2877
+ } catch (error) {
2878
+ console.error("Error converting hex to string:", error);
2879
+ return hex;
2880
+ }
2881
+ }
2882
+ try {
2883
+ const cleanHex = hex.slice(2);
2884
+ return Buffer.from(cleanHex, "hex").toString().slice(1);
2885
+ } catch (error) {
2886
+ console.error("Error converting hex to string:", error);
2887
+ return hex;
2888
+ }
2889
+ };
2890
+ const stringToHex = (str) => {
2891
+ const encoder = new TextEncoder();
2892
+ const bytes = encoder.encode(str);
2893
+ let hexString = "";
2894
+ for (let i = 0; i < bytes.length; i++) {
2895
+ const hex = bytes[i].toString(16).padStart(2, "0");
2896
+ hexString += hex;
2897
+ }
2898
+ return hexString;
2899
+ };
2900
+ const serializeValueByType = useCallback4(
2901
+ (value, type, serializer) => {
2902
+ var _a;
2903
+ const ser = serializer || new BCS3.Serializer();
2904
+ const shouldReturnBytes = !serializer;
2905
+ if (type.startsWith("0x1::option::Option<")) {
2906
+ if (value === null || value === void 0) {
2907
+ ser.serializeU8(0);
2908
+ } else {
2909
+ ser.serializeU8(1);
2910
+ const innerType = type.slice(21, -1);
2911
+ serializeValueByType(value, innerType, ser);
2912
+ }
2913
+ return shouldReturnBytes ? ser.getBytes() : new Uint8Array(0);
2914
+ }
2915
+ if (type.startsWith("vector<")) {
2916
+ const vectorMatch = type.match(/vector<(.+)>$/);
2917
+ if (!vectorMatch) {
2918
+ throw new Error(`Invalid vector type format: ${type}`);
2919
+ }
2920
+ const innerType = vectorMatch[1];
2921
+ if (innerType === "u8") {
2922
+ let bytes;
2923
+ if (typeof value === "string") {
2924
+ const cleanHex = value.startsWith("0x") ? value.slice(2) : value;
2925
+ bytes = new Uint8Array(
2926
+ ((_a = cleanHex.match(/.{1,2}/g)) == null ? void 0 : _a.map((byte) => parseInt(byte, 16))) || []
2927
+ );
2928
+ } else if (value instanceof Uint8Array) {
2929
+ bytes = value;
2930
+ } else if (Array.isArray(value)) {
2931
+ bytes = new Uint8Array(
2932
+ value.map((item) => {
2933
+ const u8 = typeof item === "string" ? parseInt(item, 10) : item;
2934
+ if (u8 < 0 || u8 > 255) {
2935
+ throw new Error(`u8 value out of range in vector: ${u8}`);
2936
+ }
2937
+ return u8;
2938
+ })
2939
+ );
2940
+ } else {
2941
+ throw new Error(
2942
+ `Expected string, Uint8Array, or number[] for vector<u8>, got ${typeof value}`
2943
+ );
2944
+ }
2945
+ ser.serializeU32AsUleb128(bytes.length);
2946
+ for (let i = 0; i < bytes.length; i++) {
2947
+ ser.serializeU8(bytes[i]);
2948
+ }
2949
+ } else {
2950
+ if (!Array.isArray(value)) {
2951
+ throw new Error(
2952
+ `Expected array for vector<${innerType}>, got ${typeof value}`
2953
+ );
2954
+ }
2955
+ ser.serializeU32AsUleb128(value.length);
2956
+ for (const item of value) {
2957
+ serializeValueByType(item, innerType, ser);
2958
+ }
2959
+ }
2960
+ return shouldReturnBytes ? ser.getBytes() : new Uint8Array(0);
2961
+ }
2962
+ if (type.startsWith("0x1::object::Object")) {
2963
+ if (typeof value !== "string") {
2964
+ throw new Error(`Expected string for Object, got ${typeof value}`);
2965
+ }
2966
+ const objectAddress = TxnBuilderTypes.AccountAddress.fromHex(value);
2967
+ ser.serializeFixedBytes(objectAddress.address);
2968
+ return shouldReturnBytes ? ser.getBytes() : new Uint8Array(0);
2969
+ }
2970
+ switch (type) {
2971
+ case "address":
2972
+ if (typeof value !== "string") {
2973
+ throw new Error(`Expected string for address, got ${typeof value}`);
2974
+ }
2975
+ const accountAddress = TxnBuilderTypes.AccountAddress.fromHex(value);
2976
+ ser.serializeFixedBytes(accountAddress.address);
2977
+ break;
2978
+ case "u8":
2979
+ const u8 = typeof value === "string" ? parseInt(value, 10) : value;
2980
+ if (u8 < 0 || u8 > 255) {
2981
+ throw new Error(`u8 value out of range: ${u8}`);
2982
+ }
2983
+ ser.serializeU8(u8);
2984
+ break;
2985
+ case "u16":
2986
+ const u16 = typeof value === "string" ? parseInt(value, 10) : typeof value === "bigint" ? Number(value) : value;
2987
+ if (u16 < 0 || u16 > 65535) {
2988
+ throw new Error(`u16 value out of range: ${u16}`);
2989
+ }
2990
+ ser.serializeU16(u16);
2991
+ break;
2992
+ case "u32":
2993
+ const u32 = typeof value === "string" ? parseInt(value, 10) : typeof value === "bigint" ? Number(value) : value;
2994
+ if (u32 < 0 || u32 > 4294967295) {
2995
+ throw new Error(`u32 value out of range: ${u32}`);
2996
+ }
2997
+ ser.serializeU32(u32);
2998
+ break;
2999
+ case "u64":
3000
+ const u64 = typeof value === "string" ? BigInt(value) : typeof value === "number" ? BigInt(value) : value;
3001
+ if (u64 < 0) {
3002
+ throw new Error(`u64 value cannot be negative: ${u64}`);
3003
+ }
3004
+ ser.serializeU64(u64);
3005
+ break;
3006
+ case "u128":
3007
+ const u128 = typeof value === "string" ? BigInt(value) : typeof value === "number" ? BigInt(value) : value;
3008
+ if (u128 < 0) {
3009
+ throw new Error(`u128 value cannot be negative: ${u128}`);
3010
+ }
3011
+ ser.serializeU128(u128);
3012
+ break;
3013
+ case "u256":
3014
+ if (typeof value !== "bigint") {
3015
+ throw new Error(`Expected bigint for u256, got ${typeof value}`);
3016
+ }
3017
+ ser.serializeU256(value);
3018
+ break;
3019
+ case "bool":
3020
+ if (typeof value !== "boolean") {
3021
+ throw new Error(`Expected boolean, got ${typeof value}`);
3022
+ }
3023
+ ser.serializeBool(value);
3024
+ break;
3025
+ case "0x1::string::String":
3026
+ if (typeof value !== "string") {
3027
+ throw new Error(`Expected string, got ${typeof value}`);
3028
+ }
3029
+ ser.serializeStr(value);
3030
+ break;
3031
+ default:
3032
+ throw new Error(`Unsupported type: ${type}`);
3033
+ }
3034
+ return shouldReturnBytes ? ser.getBytes() : new Uint8Array(0);
3035
+ },
3036
+ []
3037
+ );
3038
+ const serializeArgsFromTypes = useCallback4(
3039
+ (args, paramTypes) => {
3040
+ if (args.length !== paramTypes.length) {
3041
+ throw new Error(
3042
+ `Argument count mismatch: expected ${paramTypes.length}, got ${args.length}`
3043
+ );
3044
+ }
3045
+ return args.map((arg, index) => {
3046
+ try {
3047
+ const paramType = paramTypes[index].replace("&signer", "").trim();
3048
+ return serializeValueByType(arg, paramType);
3049
+ } catch (error) {
3050
+ const errorMessage = error instanceof Error ? error.message : String(error);
3051
+ throw new Error(
3052
+ `Failed to serialize argument ${index} (${paramTypes[index]}): ${errorMessage}`
3053
+ );
3054
+ }
3055
+ });
3056
+ },
3057
+ [serializeValueByType]
3058
+ );
3059
+ const fetchModuleABI = useCallback4(
3060
+ async (moduleAddress, moduleName, rpcUrl) => {
3061
+ const storedABI = getStoredABI(moduleAddress, moduleName);
3062
+ if (storedABI) {
3063
+ return storedABI;
3064
+ }
3065
+ const baseUrl = rpcUrl || (process.env.NEXT_PUBLIC_SUPRA_CHAIN_ID === "8" ? "https://rpc-mainnet.supra.com" : "https://rpc-testnet.supra.com");
3066
+ const url = `${baseUrl}/rpc/v3/accounts/${moduleAddress}/modules/${moduleName}`;
3067
+ try {
3068
+ const response = await fetch(url);
3069
+ if (!response.ok) {
3070
+ throw new Error(`Failed to fetch ABI: ${response.statusText}`);
3071
+ }
3072
+ const data = await response.json();
3073
+ return data.abi;
3074
+ } catch (error) {
3075
+ console.error("Error fetching module ABI:", error);
3076
+ throw new Error(
3077
+ `Failed to fetch module ABI: ${error instanceof Error ? error.message : String(error)}`
3078
+ );
3079
+ }
3080
+ },
3081
+ []
3082
+ );
3083
+ const getFunctionParamTypes = useCallback4(
3084
+ async (moduleAddress, moduleName, functionName, rpcUrl) => {
3085
+ const moduleABI = await fetchModuleABI(moduleAddress, moduleName, rpcUrl);
3086
+ if (!moduleABI.exposed_functions) {
3087
+ throw new Error("Invalid module ABI response");
3088
+ }
3089
+ const functionDef = moduleABI.exposed_functions.find(
3090
+ (func) => func.name === functionName
3091
+ );
3092
+ if (!functionDef) {
3093
+ throw new Error(`Function ${functionName} not found in module ${moduleName}`);
3094
+ }
3095
+ return functionDef.params.filter((param) => {
3096
+ const trimmed = param.trim();
3097
+ return trimmed !== "signer" && trimmed !== "&signer";
3098
+ });
3099
+ },
3100
+ [fetchModuleABI]
3101
+ );
3102
+ const serializeTransactionArgs = useCallback4(
3103
+ async (args, moduleAddress, moduleName, functionName, rpcUrl) => {
3104
+ const paramTypes = await getFunctionParamTypes(
3105
+ moduleAddress,
3106
+ moduleName,
3107
+ functionName,
3108
+ rpcUrl
3109
+ );
3110
+ return serializeArgsFromTypes(args, paramTypes);
3111
+ },
3112
+ [getFunctionParamTypes, serializeArgsFromTypes]
3113
+ );
3114
+ return {
3115
+ stringToUint8Array,
3116
+ addressToUint8Array,
3117
+ serializeString,
3118
+ serializeUint8,
3119
+ serializeUint16,
3120
+ serializeUint32,
3121
+ serializeUint64,
3122
+ serializeUint128,
3123
+ serializeU256,
3124
+ serializeBool,
3125
+ serializeVector,
3126
+ deserializeString,
3127
+ deserializeVector,
3128
+ hexToString,
3129
+ stringToHex,
3130
+ // ABI-based serialization
3131
+ serializeValueByType,
3132
+ serializeArgsFromTypes,
3133
+ fetchModuleABI,
3134
+ getFunctionParamTypes,
3135
+ serializeTransactionArgs
3136
+ // Main function to use
3137
+ };
3138
+ };
3139
+ var useConversionUtils_default = useConversionUtils;
3140
+
3141
+ // src/components/ui/button.tsx
3142
+ import * as React3 from "react";
3143
+ import { Slot as Slot2 } from "@radix-ui/react-slot";
3144
+ import { cva as cva2 } from "class-variance-authority";
3145
+ import { jsx as jsx4 } from "react/jsx-runtime";
3146
+ var buttonVariants2 = cva2(
3147
+ "inline-flex items-center justify-center whitespace-nowrap rounded-md text-sm font-medium ring-offset-background transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50",
3148
+ {
3149
+ variants: {
3150
+ variant: {
3151
+ default: "bg-primary text-primary-foreground hover:bg-primary/90",
3152
+ destructive: "bg-destructive text-destructive-foreground hover:bg-destructive/90",
3153
+ outline: "border border-input bg-background hover:bg-accent hover:text-accent-foreground",
3154
+ secondary: "bg-secondary text-secondary-foreground hover:bg-secondary/80",
3155
+ ghost: "hover:bg-accent hover:text-accent-foreground",
3156
+ link: "text-primary underline-offset-4 hover:underline"
3157
+ },
3158
+ size: {
3159
+ default: "h-10 px-4 py-2",
3160
+ sm: "h-9 rounded-md px-3",
3161
+ lg: "h-11 rounded-md px-8",
3162
+ icon: "h-10 w-10"
3163
+ }
3164
+ },
3165
+ defaultVariants: {
3166
+ variant: "default",
3167
+ size: "default"
3168
+ }
3169
+ }
3170
+ );
3171
+ var Button2 = React3.forwardRef(
3172
+ (_a, ref) => {
3173
+ var _b = _a, { className, variant, size, asChild = false } = _b, props = __objRest(_b, ["className", "variant", "size", "asChild"]);
3174
+ const Comp = asChild ? Slot2 : "button";
3175
+ return /* @__PURE__ */ jsx4(
3176
+ Comp,
3177
+ __spreadValues({
3178
+ className: cn2(buttonVariants2({ variant, size, className })),
3179
+ ref
3180
+ }, props)
3181
+ );
3182
+ }
3183
+ );
3184
+ Button2.displayName = "Button";
3185
+
3186
+ // src/components/ui/dialog.tsx
3187
+ import * as React4 from "react";
3188
+ import * as DialogPrimitive2 from "@radix-ui/react-dialog";
3189
+ import { X as X3 } from "lucide-react";
3190
+ import { jsx as jsx5, jsxs as jsxs3 } from "react/jsx-runtime";
3191
+ var Dialog2 = DialogPrimitive2.Root;
3192
+ var DialogTrigger = DialogPrimitive2.Trigger;
3193
+ var DialogPortal2 = DialogPrimitive2.Portal;
3194
+ var DialogClose = DialogPrimitive2.Close;
3195
+ var DialogOverlay2 = React4.forwardRef((_a, ref) => {
3196
+ var _b = _a, { className } = _b, props = __objRest(_b, ["className"]);
3197
+ return /* @__PURE__ */ jsx5(DialogPortal2, { children: /* @__PURE__ */ jsx5(
3198
+ DialogPrimitive2.Overlay,
3199
+ __spreadValues({
3200
+ ref,
3201
+ className: cn2(
3202
+ "fixed inset-0 z-50 bg-black/80 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0",
3203
+ className
3204
+ )
3205
+ }, props)
3206
+ ) });
3207
+ });
3208
+ DialogOverlay2.displayName = DialogPrimitive2.Overlay.displayName;
3209
+ var DialogContent2 = React4.forwardRef((_a, ref) => {
3210
+ var _b = _a, { className, children } = _b, props = __objRest(_b, ["className", "children"]);
3211
+ return /* @__PURE__ */ jsxs3(DialogPortal2, { children: [
3212
+ /* @__PURE__ */ jsx5(DialogOverlay2, {}),
3213
+ /* @__PURE__ */ jsxs3(
3214
+ DialogPrimitive2.Content,
3215
+ __spreadProps(__spreadValues({
3216
+ ref,
3217
+ className: cn2(
3218
+ "fixed left-[50%] top-[50%] z-50 grid w-full max-w-lg translate-x-[-50%] translate-y-[-50%] gap-4 border bg-background p-6 shadow-lg duration-200 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[state=closed]:slide-out-to-left-1/2 data-[state=closed]:slide-out-to-top-[48%] data-[state=open]:slide-in-from-left-1/2 data-[state=open]:slide-in-from-top-[48%] sm:rounded-lg",
3219
+ className
3220
+ )
3221
+ }, props), {
3222
+ children: [
3223
+ children,
3224
+ /* @__PURE__ */ jsxs3(DialogPrimitive2.Close, { className: "absolute right-4 top-4 rounded-sm opacity-70 ring-offset-background transition-opacity hover:opacity-100 focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 disabled:pointer-events-none data-[state=open]:bg-accent data-[state=open]:text-muted-foreground", children: [
3225
+ /* @__PURE__ */ jsx5(X3, { className: "h-4 w-4" }),
3226
+ /* @__PURE__ */ jsx5("span", { className: "sr-only", children: "Close" })
3227
+ ] })
3228
+ ]
3229
+ })
3230
+ )
3231
+ ] });
3232
+ });
3233
+ DialogContent2.displayName = DialogPrimitive2.Content.displayName;
3234
+ var DialogHeader2 = (_a) => {
3235
+ var _b = _a, {
3236
+ className
3237
+ } = _b, props = __objRest(_b, [
3238
+ "className"
3239
+ ]);
3240
+ return /* @__PURE__ */ jsx5(
3241
+ "div",
3242
+ __spreadValues({
3243
+ className: cn2(
3244
+ "flex flex-col space-y-1.5 text-center sm:text-left",
3245
+ className
3246
+ )
3247
+ }, props)
3248
+ );
3249
+ };
3250
+ DialogHeader2.displayName = "DialogHeader";
3251
+ var DialogFooter2 = (_a) => {
3252
+ var _b = _a, {
3253
+ className
3254
+ } = _b, props = __objRest(_b, [
3255
+ "className"
3256
+ ]);
3257
+ return /* @__PURE__ */ jsx5(
3258
+ "div",
3259
+ __spreadValues({
3260
+ className: cn2(
3261
+ "flex flex-col-reverse sm:flex-row sm:justify-end sm:space-x-2",
3262
+ className
3263
+ )
3264
+ }, props)
3265
+ );
3266
+ };
3267
+ DialogFooter2.displayName = "DialogFooter";
3268
+ var DialogTitle2 = React4.forwardRef((_a, ref) => {
3269
+ var _b = _a, { className } = _b, props = __objRest(_b, ["className"]);
3270
+ return /* @__PURE__ */ jsx5(
3271
+ DialogPrimitive2.Title,
3272
+ __spreadValues({
3273
+ ref,
3274
+ className: cn2(
3275
+ "text-lg font-semibold leading-none tracking-tight",
3276
+ className
3277
+ )
3278
+ }, props)
3279
+ );
3280
+ });
3281
+ DialogTitle2.displayName = DialogPrimitive2.Title.displayName;
3282
+ var DialogDescription2 = React4.forwardRef((_a, ref) => {
3283
+ var _b = _a, { className } = _b, props = __objRest(_b, ["className"]);
3284
+ return /* @__PURE__ */ jsx5(
3285
+ DialogPrimitive2.Description,
3286
+ __spreadValues({
3287
+ ref,
3288
+ className: cn2("text-sm text-muted-foreground", className)
3289
+ }, props)
3290
+ );
3291
+ });
3292
+ DialogDescription2.displayName = DialogPrimitive2.Description.displayName;
3293
+
3294
+ // src/components/ui/sonner.tsx
3295
+ import { Toaster as Sonner } from "sonner";
3296
+ import { jsx as jsx6 } from "react/jsx-runtime";
3297
+ var Toaster = (_a) => {
3298
+ var _b = _a, { theme = "system" } = _b, props = __objRest(_b, ["theme"]);
3299
+ return /* @__PURE__ */ jsx6(
3300
+ Sonner,
3301
+ __spreadValues({
3302
+ theme,
3303
+ className: "toaster group",
3304
+ toastOptions: {
3305
+ classNames: {
3306
+ toast: "group toast group-[.toaster]:bg-background group-[.toaster]:text-foreground group-[.toaster]:border-border group-[.toaster]:shadow-lg",
3307
+ description: "group-[.toast]:text-muted-foreground",
3308
+ actionButton: "group-[.toast]:bg-primary group-[.toast]:text-primary-foreground",
3309
+ cancelButton: "group-[.toast]:bg-muted group-[.toast]:text-muted-foreground"
3310
+ }
3311
+ }
3312
+ }, props)
3313
+ );
3314
+ };
3315
+
3316
+ // src/assets/walletIcons/index.ts
3317
+ var WALLET_ICONS = {
3318
+ starkey: Starkey_default,
3319
+ ribbit: Ribbit_default
3320
+ };
3321
+ export {
3322
+ Button2 as Button,
3323
+ ConnectWalletHandler,
3324
+ Dialog2 as Dialog,
3325
+ DialogClose,
3326
+ DialogContent2 as DialogContent,
3327
+ DialogDescription2 as DialogDescription,
3328
+ DialogFooter2 as DialogFooter,
3329
+ DialogHeader2 as DialogHeader,
3330
+ DialogOverlay2 as DialogOverlay,
3331
+ DialogPortal2 as DialogPortal,
3332
+ DialogTitle2 as DialogTitle,
3333
+ DialogTrigger,
3334
+ Toaster,
3335
+ WALLET_EVENTS2 as WALLET_EVENTS,
3336
+ WALLET_ICONS,
3337
+ buttonVariants2 as buttonVariants,
3338
+ cn2 as cn,
3339
+ getStoredABI,
3340
+ Ribbit_default as ribbitIcon,
3341
+ standardizeAddress,
3342
+ Starkey_default as starkeyIcon,
3343
+ useConversionUtils_default as useConversionUtils,
3344
+ useSupraMultiWallet_default2 as useSupraMultiWallet
3345
+ };
3346
+ //# sourceMappingURL=index.mjs.map