@avalabs/avacloud-waas-react 1.0.0

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,4178 @@
1
+ // src/AvaCloudWalletProvider.tsx
2
+ import { createContext as createContext4, useContext as useContext4, useEffect as useEffect5, useState as useState7, useCallback as useCallback5, useRef as useRef2 } from "react";
3
+ import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
4
+ import { envs } from "@cubist-labs/cubesigner-sdk";
5
+
6
+ // src/types/vm.ts
7
+ var VM = /* @__PURE__ */ ((VM2) => {
8
+ VM2["EVM"] = "EVM";
9
+ VM2["AVM"] = "AVM";
10
+ VM2["PVM"] = "PVM";
11
+ return VM2;
12
+ })(VM || {});
13
+
14
+ // src/utils/derivationPath.ts
15
+ var getCoinIndexForVm = (vm) => {
16
+ switch (vm) {
17
+ case "EVM" /* EVM */:
18
+ return 60;
19
+ case "AVM" /* AVM */:
20
+ case "PVM" /* PVM */:
21
+ return 9e3;
22
+ default:
23
+ throw new Error(`Unknown coin index for vm: ${vm}`);
24
+ }
25
+ };
26
+ function getDerivationPath(vm, accountIndex) {
27
+ if (accountIndex < 0 || Math.round(accountIndex) !== accountIndex) {
28
+ throw new Error("Account index must be a non-negative integer");
29
+ }
30
+ const coinIndex = getCoinIndexForVm(vm);
31
+ return `m/44'/${coinIndex}'/0'/0/${accountIndex}`;
32
+ }
33
+
34
+ // src/hooks/usePostMessage.ts
35
+ import { useCallback, useEffect, useRef } from "react";
36
+ import { AUTH_TOKENS_KEY, OIDC_TOKEN_KEY, AUTH0_STORAGE_KEYS, CUBIST_USER_ID_KEY } from "@avacloud/waas-common";
37
+ function usePostMessage({
38
+ authServiceUrl,
39
+ orgId,
40
+ environment,
41
+ iframe,
42
+ isIframeReady,
43
+ onAuthSuccess,
44
+ onAuthError,
45
+ onOidcReceived,
46
+ onOrgConfigUpdate,
47
+ setIsAuthenticated,
48
+ setUser,
49
+ setIsLoading,
50
+ setIsIframeReady,
51
+ cubistClient
52
+ }) {
53
+ const lastAuthStateRef = useRef({
54
+ isAuthenticated: false,
55
+ userId: null,
56
+ lastUpdateTime: 0
57
+ });
58
+ const hasRequestedOidcRef = useRef(false);
59
+ const isHandlingMessageRef = useRef(false);
60
+ const sendMessage = useCallback((message) => {
61
+ if (iframe == null ? void 0 : iframe.contentWindow) {
62
+ try {
63
+ console.log("Sending message to auth iframe:", message);
64
+ iframe.contentWindow.postMessage(message, authServiceUrl);
65
+ } catch (error) {
66
+ console.error("Error sending message to iframe:", error);
67
+ }
68
+ } else {
69
+ console.error("No iframe available to send message");
70
+ }
71
+ }, [iframe, authServiceUrl]);
72
+ useEffect(() => {
73
+ const handleMessage = async (event) => {
74
+ var _a, _b, _c, _d, _e, _f, _g;
75
+ if (isHandlingMessageRef.current) {
76
+ console.log("Already handling a message, skipping");
77
+ return;
78
+ }
79
+ if (event.origin !== new URL(authServiceUrl).origin) {
80
+ return;
81
+ }
82
+ if (typeof ((_a = event.data) == null ? void 0 : _a.type) !== "string") {
83
+ return;
84
+ }
85
+ try {
86
+ isHandlingMessageRef.current = true;
87
+ console.log("Received message from iframe:", event.data);
88
+ switch (event.data.type) {
89
+ case "IFRAME_READY":
90
+ console.log("Iframe ready message received, setting isIframeReady to true");
91
+ console.log("\u2705 Connection established: Parent received IFRAME_READY from auth service.");
92
+ setIsIframeReady(true);
93
+ break;
94
+ case "RECEIVE_OIDC":
95
+ console.log("Received OIDC token payload:", event.data.payload);
96
+ if (typeof ((_b = event.data.payload) == null ? void 0 : _b.idToken) === "string") {
97
+ const oidcToken = event.data.payload.idToken;
98
+ console.log("Triggering onOidcReceived callback with token...");
99
+ hasRequestedOidcRef.current = false;
100
+ onOidcReceived == null ? void 0 : onOidcReceived(oidcToken);
101
+ } else {
102
+ console.warn("RECEIVE_OIDC message missing idToken in payload.");
103
+ hasRequestedOidcRef.current = false;
104
+ }
105
+ break;
106
+ case "AUTH_STATUS": {
107
+ const newIsAuthenticated = !!event.data.isAuthenticated;
108
+ const newUserId = (_d = (_c = event.data.user) == null ? void 0 : _c.sub) != null ? _d : null;
109
+ const now = Date.now();
110
+ if (now - lastAuthStateRef.current.lastUpdateTime < 500) {
111
+ return;
112
+ }
113
+ const authStateChanged = lastAuthStateRef.current.isAuthenticated !== newIsAuthenticated || lastAuthStateRef.current.userId !== newUserId;
114
+ if (authStateChanged) {
115
+ console.log("Auth status changed:", { newIsAuthenticated, newUserId });
116
+ setIsAuthenticated(newIsAuthenticated);
117
+ if (event.data.user) {
118
+ const userInfo = {
119
+ email: event.data.user.email,
120
+ sub: event.data.user.sub,
121
+ configured_mfa: [],
122
+ displayName: event.data.user.nickname || event.data.user.name || ((_e = event.data.user.email) == null ? void 0 : _e.split("@")[0]) || "User",
123
+ rawUserData: event.data.user
124
+ };
125
+ console.log("Setting user info:", userInfo);
126
+ setUser(userInfo);
127
+ if (newIsAuthenticated && !cubistClient && !hasRequestedOidcRef.current) {
128
+ hasRequestedOidcRef.current = true;
129
+ console.log("User newly authenticated, sending GET_OIDC message");
130
+ sendMessage({ type: "GET_OIDC" });
131
+ return;
132
+ }
133
+ } else {
134
+ setUser(null);
135
+ localStorage.removeItem(AUTH_TOKENS_KEY);
136
+ localStorage.removeItem(AUTH0_STORAGE_KEYS.IS_AUTHENTICATED);
137
+ sessionStorage.removeItem(OIDC_TOKEN_KEY);
138
+ }
139
+ lastAuthStateRef.current = {
140
+ isAuthenticated: newIsAuthenticated,
141
+ userId: newUserId,
142
+ lastUpdateTime: now
143
+ };
144
+ if (newIsAuthenticated && event.data.user) {
145
+ if (!hasRequestedOidcRef.current) {
146
+ if (event.data.tokens) {
147
+ localStorage.setItem(AUTH_TOKENS_KEY, JSON.stringify(event.data.tokens));
148
+ }
149
+ onAuthSuccess == null ? void 0 : onAuthSuccess();
150
+ }
151
+ }
152
+ }
153
+ if (event.data.orgConfig && onOrgConfigUpdate) {
154
+ console.log("Received organization config:", event.data.orgConfig);
155
+ onOrgConfigUpdate(event.data.orgConfig);
156
+ }
157
+ if (!hasRequestedOidcRef.current) {
158
+ setIsLoading(false);
159
+ }
160
+ break;
161
+ }
162
+ case "REGISTER_SUCCESS": {
163
+ console.log("Registration successful:", event.data.payload);
164
+ const userId = (_f = event.data.payload) == null ? void 0 : _f.userId;
165
+ if (userId) {
166
+ localStorage.setItem(CUBIST_USER_ID_KEY, userId);
167
+ if (!hasRequestedOidcRef.current) {
168
+ console.log("Registration complete, sending GET_OIDC message");
169
+ hasRequestedOidcRef.current = true;
170
+ sendMessage({ type: "GET_OIDC" });
171
+ }
172
+ }
173
+ break;
174
+ }
175
+ case "ERROR":
176
+ console.error("Error from auth service:", event.data.error);
177
+ onAuthError == null ? void 0 : onAuthError(new Error((_g = event.data.error) != null ? _g : "Unknown error"));
178
+ setIsLoading(false);
179
+ break;
180
+ }
181
+ } finally {
182
+ isHandlingMessageRef.current = false;
183
+ }
184
+ };
185
+ window.addEventListener("message", handleMessage);
186
+ return () => window.removeEventListener("message", handleMessage);
187
+ }, [
188
+ authServiceUrl,
189
+ onAuthError,
190
+ onAuthSuccess,
191
+ onOidcReceived,
192
+ onOrgConfigUpdate,
193
+ setIsAuthenticated,
194
+ setIsIframeReady,
195
+ setIsLoading,
196
+ setUser,
197
+ sendMessage,
198
+ cubistClient
199
+ ]);
200
+ useEffect(() => {
201
+ if (isIframeReady && (iframe == null ? void 0 : iframe.contentWindow)) {
202
+ console.log("\u23F3 Connection attempt: Parent sending CHECK_AUTH_STATUS to auth service.");
203
+ sendMessage({
204
+ type: "CHECK_AUTH_STATUS",
205
+ payload: {
206
+ orgId,
207
+ environment
208
+ }
209
+ });
210
+ }
211
+ }, [isIframeReady, iframe, sendMessage, orgId, environment]);
212
+ return {
213
+ sendMessage
214
+ };
215
+ }
216
+
217
+ // src/AuthModalContext.tsx
218
+ import { createContext, useContext, useState as useState3, useCallback as useCallback2 } from "react";
219
+ import { Dialog as Dialog2, DialogContent as DialogContent2, DialogTitle } from "@avalabs/core-k2-components";
220
+
221
+ // src/components/Modal.tsx
222
+ import { useState as useState2, useEffect as useEffect2 } from "react";
223
+ import { Dialog, DialogContent, IconButton as IconButton2, Stack as Stack3, XIcon } from "@avalabs/core-k2-components";
224
+
225
+ // src/components/SignInContent.tsx
226
+ import { useState } from "react";
227
+ import { Button, TextField, Typography as Typography2, Stack as Stack2, IconButton, Divider, GoogleColorIcon, AppleIcon, XTwitterIcon, useTheme } from "@avalabs/core-k2-components";
228
+
229
+ // src/components/PoweredByAvaCloud.tsx
230
+ import { Stack, Typography, AvaCloudConnectIcon } from "@avalabs/core-k2-components";
231
+ import { jsx, jsxs } from "react/jsx-runtime";
232
+ function PoweredByAvaCloud() {
233
+ return /* @__PURE__ */ jsxs(Stack, { direction: "row", alignItems: "center", justifyContent: "center", spacing: 1, children: [
234
+ /* @__PURE__ */ jsx(Typography, { variant: "body2", children: "Powered by" }),
235
+ /* @__PURE__ */ jsxs(Stack, { direction: "row", alignItems: "center", spacing: 0.5, children: [
236
+ /* @__PURE__ */ jsx(AvaCloudConnectIcon, {}),
237
+ /* @__PURE__ */ jsx(Typography, { variant: "body2", children: "AvaCloud" })
238
+ ] })
239
+ ] });
240
+ }
241
+
242
+ // src/components/SignInContent.tsx
243
+ import { jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
244
+ function SignInContent({ onEmailLogin, onProviderLogin, error, isSubmitting }) {
245
+ const [email, setEmail] = useState("");
246
+ const [password, setPassword] = useState("");
247
+ const [isPasswordStep, setIsPasswordStep] = useState(false);
248
+ const theme = useTheme();
249
+ const handleEmailSubmit = (e) => {
250
+ e.preventDefault();
251
+ if (!email) return;
252
+ setIsPasswordStep(true);
253
+ };
254
+ const handlePasswordSubmit = (e) => {
255
+ e.preventDefault();
256
+ if (!password) return;
257
+ onEmailLogin(email, password);
258
+ };
259
+ const handleForgotPassword = () => {
260
+ console.log("Forgot password clicked");
261
+ };
262
+ const titleTypography = {
263
+ alignSelf: "stretch",
264
+ color: (theme2) => theme2.palette.mode === "dark" ? "#FFFFFF" : "rgba(0, 0, 0, 0.80)",
265
+ fontFamily: "Inter",
266
+ fontSize: "16px",
267
+ fontStyle: "normal",
268
+ fontWeight: 700,
269
+ lineHeight: "150%"
270
+ };
271
+ if (isPasswordStep) {
272
+ return /* @__PURE__ */ jsxs2(Stack2, { gap: 3, children: [
273
+ /* @__PURE__ */ jsx2(Typography2, { variant: "h6", sx: titleTypography, children: "Sign in with" }),
274
+ /* @__PURE__ */ jsx2("form", { onSubmit: handlePasswordSubmit, children: /* @__PURE__ */ jsxs2(Stack2, { gap: 2, children: [
275
+ /* @__PURE__ */ jsx2(
276
+ TextField,
277
+ {
278
+ placeholder: "Enter password",
279
+ type: "password",
280
+ value: password,
281
+ onChange: (e) => setPassword(e.target.value),
282
+ fullWidth: true,
283
+ required: true,
284
+ disabled: isSubmitting,
285
+ error: !!error,
286
+ helperText: error,
287
+ sx: {
288
+ "& .MuiOutlinedInput-root": {
289
+ backgroundColor: (theme2) => theme2.palette.mode === "dark" ? "rgba(255, 255, 255, 0.05)" : "grey.50"
290
+ }
291
+ }
292
+ }
293
+ ),
294
+ /* @__PURE__ */ jsx2(
295
+ Button,
296
+ {
297
+ type: "submit",
298
+ variant: "contained",
299
+ fullWidth: true,
300
+ disabled: isSubmitting || !password,
301
+ sx: {
302
+ height: 48,
303
+ backgroundColor: "#3A65FF",
304
+ borderRadius: 24,
305
+ textTransform: "none",
306
+ "&:hover": {
307
+ backgroundColor: "#2952E6"
308
+ }
309
+ },
310
+ children: "Continue"
311
+ }
312
+ ),
313
+ /* @__PURE__ */ jsx2(
314
+ Typography2,
315
+ {
316
+ variant: "body2",
317
+ sx: {
318
+ textAlign: "center",
319
+ "& a": {
320
+ color: "#3A65FF",
321
+ textDecoration: "none",
322
+ cursor: "pointer",
323
+ "&:hover": {
324
+ textDecoration: "underline"
325
+ }
326
+ }
327
+ },
328
+ children: /* @__PURE__ */ jsx2(
329
+ Button,
330
+ {
331
+ variant: "text",
332
+ onClick: handleForgotPassword,
333
+ sx: {
334
+ color: "#3A65FF",
335
+ textTransform: "none",
336
+ "&:hover": {
337
+ textDecoration: "underline",
338
+ backgroundColor: "transparent"
339
+ }
340
+ },
341
+ children: "Forget password?"
342
+ }
343
+ )
344
+ }
345
+ )
346
+ ] }) }),
347
+ /* @__PURE__ */ jsx2(PoweredByAvaCloud, {}),
348
+ /* @__PURE__ */ jsxs2(
349
+ Typography2,
350
+ {
351
+ variant: "body2",
352
+ sx: {
353
+ textAlign: "center",
354
+ color: "text.secondary",
355
+ fontSize: "0.75rem",
356
+ "& a": {
357
+ color: "inherit",
358
+ textDecoration: "none",
359
+ "&:hover": {
360
+ textDecoration: "underline"
361
+ }
362
+ }
363
+ },
364
+ children: [
365
+ "By connecting, you agree to the",
366
+ " ",
367
+ /* @__PURE__ */ jsx2(
368
+ Button,
369
+ {
370
+ variant: "text",
371
+ component: "a",
372
+ href: "https://avacloud.io/terms",
373
+ target: "_blank",
374
+ rel: "noopener noreferrer",
375
+ sx: {
376
+ color: "inherit",
377
+ p: 0,
378
+ minWidth: "auto",
379
+ textTransform: "none",
380
+ fontSize: "inherit",
381
+ fontWeight: "inherit",
382
+ "&:hover": {
383
+ textDecoration: "underline",
384
+ backgroundColor: "transparent"
385
+ }
386
+ },
387
+ children: "Terms of Service"
388
+ }
389
+ ),
390
+ " ",
391
+ "and",
392
+ " ",
393
+ /* @__PURE__ */ jsx2(
394
+ Button,
395
+ {
396
+ variant: "text",
397
+ component: "a",
398
+ href: "https://avacloud.io/privacy",
399
+ target: "_blank",
400
+ rel: "noopener noreferrer",
401
+ sx: {
402
+ color: "inherit",
403
+ p: 0,
404
+ minWidth: "auto",
405
+ textTransform: "none",
406
+ fontSize: "inherit",
407
+ fontWeight: "inherit",
408
+ "&:hover": {
409
+ textDecoration: "underline",
410
+ backgroundColor: "transparent"
411
+ }
412
+ },
413
+ children: "Privacy Policy"
414
+ }
415
+ )
416
+ ]
417
+ }
418
+ )
419
+ ] });
420
+ }
421
+ return /* @__PURE__ */ jsxs2(Stack2, { gap: 3, children: [
422
+ /* @__PURE__ */ jsx2(Typography2, { variant: "h6", sx: titleTypography, children: "Sign in with" }),
423
+ /* @__PURE__ */ jsxs2(Stack2, { direction: "row", spacing: 3, sx: { justifyContent: "center" }, children: [
424
+ /* @__PURE__ */ jsx2(
425
+ IconButton,
426
+ {
427
+ color: "default",
428
+ variant: "contained",
429
+ onClick: () => onProviderLogin("google-oauth2"),
430
+ disabled: isSubmitting,
431
+ sx: {
432
+ display: "flex",
433
+ padding: "16px",
434
+ alignItems: "center",
435
+ gap: "8px",
436
+ borderRadius: "8px",
437
+ background: "rgba(0, 0, 0, 0.02)",
438
+ boxShadow: "2px 1px 4px 0px rgba(0, 0, 0, 0.20)",
439
+ width: 72,
440
+ height: 72,
441
+ "&:hover": {
442
+ background: "rgba(0, 0, 0, 0.04)"
443
+ }
444
+ },
445
+ children: /* @__PURE__ */ jsx2(GoogleColorIcon, { sx: { width: 24, height: 24 } })
446
+ }
447
+ ),
448
+ /* @__PURE__ */ jsx2(
449
+ IconButton,
450
+ {
451
+ color: "default",
452
+ variant: "contained",
453
+ onClick: () => onProviderLogin("twitter"),
454
+ disabled: isSubmitting,
455
+ sx: {
456
+ display: "flex",
457
+ padding: "16px",
458
+ alignItems: "center",
459
+ gap: "8px",
460
+ borderRadius: "8px",
461
+ background: "rgba(0, 0, 0, 0.02)",
462
+ boxShadow: "2px 1px 4px 0px rgba(0, 0, 0, 0.20)",
463
+ width: 72,
464
+ height: 72,
465
+ "&:hover": {
466
+ background: "rgba(0, 0, 0, 0.04)"
467
+ }
468
+ },
469
+ children: /* @__PURE__ */ jsx2(XTwitterIcon, { sx: { width: 24, height: 24 } })
470
+ }
471
+ ),
472
+ /* @__PURE__ */ jsx2(
473
+ IconButton,
474
+ {
475
+ color: "default",
476
+ variant: "contained",
477
+ onClick: () => onProviderLogin("apple"),
478
+ disabled: isSubmitting,
479
+ sx: {
480
+ display: "flex",
481
+ padding: "16px",
482
+ alignItems: "center",
483
+ gap: "8px",
484
+ borderRadius: "8px",
485
+ background: "rgba(0, 0, 0, 0.02)",
486
+ boxShadow: "2px 1px 4px 0px rgba(0, 0, 0, 0.20)",
487
+ width: 72,
488
+ height: 72,
489
+ "&:hover": {
490
+ background: "rgba(0, 0, 0, 0.04)"
491
+ }
492
+ },
493
+ children: /* @__PURE__ */ jsx2(AppleIcon, { sx: { width: 24, height: 24 } })
494
+ }
495
+ )
496
+ ] }),
497
+ /* @__PURE__ */ jsx2(Divider, { children: /* @__PURE__ */ jsx2(Typography2, { variant: "body2", color: "text.secondary", children: "or" }) }),
498
+ /* @__PURE__ */ jsx2("form", { onSubmit: handleEmailSubmit, children: /* @__PURE__ */ jsxs2(Stack2, { gap: 2, children: [
499
+ /* @__PURE__ */ jsx2(
500
+ TextField,
501
+ {
502
+ placeholder: "Enter email",
503
+ type: "email",
504
+ value: email,
505
+ onChange: (e) => setEmail(e.target.value),
506
+ fullWidth: true,
507
+ required: true,
508
+ disabled: isSubmitting,
509
+ error: !!error,
510
+ helperText: error,
511
+ sx: {
512
+ "& .MuiOutlinedInput-root": {
513
+ backgroundColor: (theme2) => theme2.palette.mode === "dark" ? "rgba(255, 255, 255, 0.05)" : "grey.50"
514
+ }
515
+ }
516
+ }
517
+ ),
518
+ /* @__PURE__ */ jsx2(
519
+ Button,
520
+ {
521
+ type: "submit",
522
+ variant: "contained",
523
+ fullWidth: true,
524
+ disabled: isSubmitting || !email,
525
+ sx: {
526
+ height: 48,
527
+ backgroundColor: "#3A65FF",
528
+ borderRadius: 24,
529
+ textTransform: "none",
530
+ "&:hover": {
531
+ backgroundColor: "#2952E6"
532
+ }
533
+ },
534
+ children: "Continue"
535
+ }
536
+ )
537
+ ] }) }),
538
+ /* @__PURE__ */ jsx2(PoweredByAvaCloud, {}),
539
+ /* @__PURE__ */ jsxs2(
540
+ Typography2,
541
+ {
542
+ variant: "body2",
543
+ sx: {
544
+ textAlign: "center",
545
+ color: "text.secondary",
546
+ fontSize: "0.75rem",
547
+ "& a": {
548
+ color: "inherit",
549
+ textDecoration: "none",
550
+ "&:hover": {
551
+ textDecoration: "underline"
552
+ }
553
+ }
554
+ },
555
+ children: [
556
+ "By connecting, you agree to the",
557
+ " ",
558
+ /* @__PURE__ */ jsx2(
559
+ Button,
560
+ {
561
+ variant: "text",
562
+ component: "a",
563
+ href: "https://avacloud.io/terms",
564
+ target: "_blank",
565
+ rel: "noopener noreferrer",
566
+ sx: {
567
+ color: "inherit",
568
+ p: 0,
569
+ minWidth: "auto",
570
+ textTransform: "none",
571
+ fontSize: "inherit",
572
+ fontWeight: "inherit",
573
+ "&:hover": {
574
+ textDecoration: "underline",
575
+ backgroundColor: "transparent"
576
+ }
577
+ },
578
+ children: "Terms of Service"
579
+ }
580
+ ),
581
+ " ",
582
+ "and",
583
+ " ",
584
+ /* @__PURE__ */ jsx2(
585
+ Button,
586
+ {
587
+ variant: "text",
588
+ component: "a",
589
+ href: "https://avacloud.io/privacy",
590
+ target: "_blank",
591
+ rel: "noopener noreferrer",
592
+ sx: {
593
+ color: "inherit",
594
+ p: 0,
595
+ minWidth: "auto",
596
+ textTransform: "none",
597
+ fontSize: "inherit",
598
+ fontWeight: "inherit",
599
+ "&:hover": {
600
+ textDecoration: "underline",
601
+ backgroundColor: "transparent"
602
+ }
603
+ },
604
+ children: "Privacy Policy"
605
+ }
606
+ )
607
+ ]
608
+ }
609
+ )
610
+ ] });
611
+ }
612
+
613
+ // src/components/Modal.tsx
614
+ import { jsx as jsx3, jsxs as jsxs3 } from "react/jsx-runtime";
615
+ function LoginModal({ open, onClose }) {
616
+ const { iframe } = useAvaCloudWallet();
617
+ const [isSubmitting, setIsSubmitting] = useState2(false);
618
+ const [error, setError] = useState2("");
619
+ useEffect2(() => {
620
+ const handleMessage = (event) => {
621
+ if (event.data.type === "ERROR") {
622
+ setError(event.data.payload);
623
+ setIsSubmitting(false);
624
+ } else if (event.data.type === "AUTH_STATUS" && event.data.isAuthenticated) {
625
+ setIsSubmitting(false);
626
+ onClose();
627
+ }
628
+ };
629
+ window.addEventListener("message", handleMessage);
630
+ return () => window.removeEventListener("message", handleMessage);
631
+ }, [onClose]);
632
+ const handleProviderLogin = (provider) => {
633
+ var _a;
634
+ setError("");
635
+ if (iframe) {
636
+ console.log(`Sending LOGIN_REQUEST to auth service iframe with ${provider} connection`);
637
+ (_a = iframe.contentWindow) == null ? void 0 : _a.postMessage({
638
+ type: "LOGIN_REQUEST",
639
+ connection: provider
640
+ }, "*");
641
+ onClose();
642
+ } else {
643
+ console.error("Auth service iframe not found");
644
+ setError("Authentication service not available");
645
+ }
646
+ };
647
+ const handleEmailLogin = (email, password) => {
648
+ var _a;
649
+ setError("");
650
+ setIsSubmitting(true);
651
+ if (iframe) {
652
+ console.log("Sending email/password LOGIN_REQUEST to auth service iframe");
653
+ (_a = iframe.contentWindow) == null ? void 0 : _a.postMessage({
654
+ type: "LOGIN_REQUEST",
655
+ email,
656
+ password
657
+ }, "*");
658
+ } else {
659
+ console.error("Auth service iframe not found");
660
+ setError("Authentication service not available");
661
+ setIsSubmitting(false);
662
+ }
663
+ };
664
+ return /* @__PURE__ */ jsxs3(
665
+ Dialog,
666
+ {
667
+ open,
668
+ maxWidth: "xs",
669
+ PaperProps: {
670
+ sx: {
671
+ borderRadius: "8px",
672
+ width: "100%",
673
+ maxWidth: 400,
674
+ maxHeight: "calc(100% - 64px)",
675
+ m: 2,
676
+ overflow: "visible",
677
+ bgcolor: (theme) => theme.palette.mode === "dark" ? "#1A1A1A" : "#ffffff",
678
+ backgroundImage: "none",
679
+ display: "flex",
680
+ flexDirection: "column",
681
+ position: "relative",
682
+ boxShadow: (theme) => theme.palette.mode === "dark" ? "0px 4px 6px 0px rgba(0, 0, 0, 0.3), 0px 15px 15px 0px rgba(0, 0, 0, 0.25)" : "0px 4px 6px 0px rgba(0, 0, 0, 0.16), 0px 15px 15px 0px rgba(0, 0, 0, 0.15)",
683
+ transition: "all 0.2s ease-in-out"
684
+ }
685
+ },
686
+ children: [
687
+ /* @__PURE__ */ jsxs3(
688
+ Stack3,
689
+ {
690
+ direction: "row",
691
+ sx: {
692
+ display: "flex",
693
+ justifyContent: "space-between",
694
+ alignItems: "flex-start",
695
+ alignSelf: "stretch",
696
+ p: 3,
697
+ pb: 0
698
+ },
699
+ children: [
700
+ /* @__PURE__ */ jsx3(
701
+ "img",
702
+ {
703
+ src: "/avacloud.png",
704
+ alt: "AvaCloud",
705
+ style: {
706
+ height: 24,
707
+ objectFit: "contain"
708
+ }
709
+ }
710
+ ),
711
+ /* @__PURE__ */ jsx3(
712
+ IconButton2,
713
+ {
714
+ onClick: onClose,
715
+ size: "small",
716
+ sx: {
717
+ color: (theme) => theme.palette.mode === "dark" ? "rgba(255, 255, 255, 0.54)" : "rgba(0, 0, 0, 0.54)",
718
+ padding: "4px",
719
+ marginTop: "-4px",
720
+ marginRight: "-4px",
721
+ "&:hover": {
722
+ backgroundColor: (theme) => theme.palette.mode === "dark" ? "rgba(255, 255, 255, 0.04)" : "rgba(0, 0, 0, 0.04)"
723
+ }
724
+ },
725
+ children: /* @__PURE__ */ jsx3(XIcon, { sx: { fontSize: 20 } })
726
+ }
727
+ )
728
+ ]
729
+ }
730
+ ),
731
+ /* @__PURE__ */ jsx3(DialogContent, { sx: { p: 3 }, children: /* @__PURE__ */ jsx3(
732
+ SignInContent,
733
+ {
734
+ onEmailLogin: handleEmailLogin,
735
+ onProviderLogin: handleProviderLogin,
736
+ error,
737
+ isSubmitting
738
+ }
739
+ ) })
740
+ ]
741
+ }
742
+ );
743
+ }
744
+
745
+ // src/AuthModalContext.tsx
746
+ import { jsx as jsx4, jsxs as jsxs4 } from "react/jsx-runtime";
747
+ var AuthModalContext = createContext(void 0);
748
+ function AuthModalProvider({ children }) {
749
+ const [isModalOpen, setIsModalOpen] = useState3(false);
750
+ const openLoginModal = useCallback2(() => setIsModalOpen(true), []);
751
+ const closeLoginModal = useCallback2(() => setIsModalOpen(false), []);
752
+ return /* @__PURE__ */ jsxs4(AuthModalContext.Provider, { value: { openLoginModal, closeLoginModal, isModalOpen }, children: [
753
+ children,
754
+ /* @__PURE__ */ jsxs4(
755
+ Dialog2,
756
+ {
757
+ open: isModalOpen,
758
+ onClose: closeLoginModal,
759
+ maxWidth: "xs",
760
+ children: [
761
+ /* @__PURE__ */ jsx4(DialogTitle, { children: /* @__PURE__ */ jsx4("img", { src: "", alt: "AvaCloud Connect", style: { height: "32px" } }) }),
762
+ /* @__PURE__ */ jsx4(DialogContent2, { sx: { padding: 4 }, children: /* @__PURE__ */ jsx4(
763
+ LoginModal,
764
+ {
765
+ open: isModalOpen,
766
+ onClose: closeLoginModal
767
+ }
768
+ ) })
769
+ ]
770
+ }
771
+ )
772
+ ] });
773
+ }
774
+ function useAuthModal() {
775
+ const context = useContext(AuthModalContext);
776
+ if (context === void 0) {
777
+ throw new Error("useAuthModal must be used within an AuthModalProvider");
778
+ }
779
+ return context;
780
+ }
781
+
782
+ // src/AvaCloudWalletProvider.tsx
783
+ import { CubeSignerClient } from "@cubist-labs/cubesigner-sdk";
784
+
785
+ // src/providers/ViemContext.tsx
786
+ import { createContext as createContext2, useContext as useContext2, useState as useState4, useEffect as useEffect3 } from "react";
787
+ import { createPublicClient, createWalletClient, http } from "viem";
788
+
789
+ // src/hooks/useAuth.ts
790
+ import { useCallback as useCallback3 } from "react";
791
+ function useAuth() {
792
+ const {
793
+ isAuthenticated,
794
+ isLoading,
795
+ user,
796
+ wallet,
797
+ logout,
798
+ loginWithCubist,
799
+ cubistClient,
800
+ cubistError
801
+ } = useAvaCloudWallet();
802
+ const { openLoginModal } = useAuthModal();
803
+ const login = useCallback3(() => {
804
+ openLoginModal();
805
+ }, [openLoginModal]);
806
+ return {
807
+ isAuthenticated,
808
+ isLoading,
809
+ user,
810
+ wallet,
811
+ login,
812
+ logout,
813
+ loginWithCubist,
814
+ cubistClient,
815
+ cubistError
816
+ };
817
+ }
818
+
819
+ // src/providers/ViemContext.tsx
820
+ import { jsx as jsx5 } from "react/jsx-runtime";
821
+ var ViemContext = createContext2(null);
822
+ function ViemProvider({ children, rpcUrl, chainId, explorerUrl }) {
823
+ var _a, _b;
824
+ const [publicClient, setPublicClient] = useState4(null);
825
+ const [walletClient, setWalletClient] = useState4(null);
826
+ const [isConnected, setIsConnected] = useState4(false);
827
+ const [error, setError] = useState4(null);
828
+ const { cubistClient, wallet: authWallet } = useAuth();
829
+ useEffect3(() => {
830
+ const initClient = async () => {
831
+ var _a2;
832
+ try {
833
+ const transport = http(rpcUrl);
834
+ const customChain = {
835
+ id: chainId,
836
+ name: `Chain ${chainId}`,
837
+ nativeCurrency: {
838
+ name: "AVAX",
839
+ symbol: "AVAX",
840
+ decimals: 18
841
+ },
842
+ rpcUrls: {
843
+ default: { http: [rpcUrl] },
844
+ public: { http: [rpcUrl] }
845
+ },
846
+ blockExplorers: explorerUrl ? {
847
+ default: {
848
+ name: "Explorer",
849
+ url: explorerUrl
850
+ }
851
+ } : void 0
852
+ };
853
+ const client = createPublicClient({
854
+ transport,
855
+ chain: customChain
856
+ });
857
+ if ((_a2 = authWallet == null ? void 0 : authWallet.cubistWallet) == null ? void 0 : _a2.address) {
858
+ const walletInstance = createWalletClient({
859
+ transport,
860
+ chain: customChain,
861
+ account: authWallet.cubistWallet.address
862
+ });
863
+ setWalletClient(walletInstance);
864
+ }
865
+ await client.getBlockNumber();
866
+ setPublicClient(client);
867
+ setIsConnected(true);
868
+ setError(null);
869
+ } catch (err) {
870
+ setError(err instanceof Error ? err : new Error("Failed to connect"));
871
+ setIsConnected(false);
872
+ }
873
+ };
874
+ initClient();
875
+ }, [rpcUrl, chainId, explorerUrl, (_a = authWallet == null ? void 0 : authWallet.cubistWallet) == null ? void 0 : _a.address]);
876
+ useEffect3(() => {
877
+ var _a2;
878
+ if (((_a2 = authWallet == null ? void 0 : authWallet.cubistWallet) == null ? void 0 : _a2.address) && publicClient && walletClient) {
879
+ setIsConnected(true);
880
+ } else {
881
+ setIsConnected(false);
882
+ }
883
+ }, [(_b = authWallet == null ? void 0 : authWallet.cubistWallet) == null ? void 0 : _b.address, publicClient, walletClient]);
884
+ const clearError = () => setError(null);
885
+ return /* @__PURE__ */ jsx5(
886
+ ViemContext.Provider,
887
+ {
888
+ value: {
889
+ publicClient,
890
+ walletClient,
891
+ setPublicClient,
892
+ setWalletClient,
893
+ chainId,
894
+ explorerUrl,
895
+ isConnected,
896
+ error,
897
+ clearError
898
+ },
899
+ children
900
+ }
901
+ );
902
+ }
903
+ function useViem() {
904
+ const context = useContext2(ViemContext);
905
+ if (!context) {
906
+ throw new Error("useViem must be used within a ViemProvider");
907
+ }
908
+ return context;
909
+ }
910
+
911
+ // src/hooks/useGlacier.ts
912
+ import { useQuery } from "@tanstack/react-query";
913
+
914
+ // src/services/glacier/client.ts
915
+ var GLACIER_API_BASE_URL = "https://glacier-api.avax.network";
916
+ var GlacierApiClient = class {
917
+ constructor() {
918
+ this.baseUrl = GLACIER_API_BASE_URL;
919
+ }
920
+ async getBlockchains() {
921
+ const response = await fetch(`${this.baseUrl}/v1/chains`);
922
+ if (!response.ok) {
923
+ throw new Error("Failed to fetch blockchains");
924
+ }
925
+ return response.json();
926
+ }
927
+ async getValidators(subnetId) {
928
+ const response = await fetch(`${this.baseUrl}/v1/subnets/${subnetId}/validators`);
929
+ if (!response.ok) {
930
+ throw new Error("Failed to fetch validators");
931
+ }
932
+ return response.json();
933
+ }
934
+ async getSubnets() {
935
+ const response = await fetch(`${this.baseUrl}/v1/subnets`);
936
+ if (!response.ok) {
937
+ throw new Error("Failed to fetch subnets");
938
+ }
939
+ return response.json();
940
+ }
941
+ async getBlockchain(chainId) {
942
+ const response = await fetch(`${this.baseUrl}/v1/chains/${chainId}`);
943
+ if (!response.ok) {
944
+ throw new Error("Failed to fetch blockchain");
945
+ }
946
+ return response.json();
947
+ }
948
+ async getBalance(address, chainId) {
949
+ const chain = await this.getBlockchain(chainId);
950
+ const response = await fetch(chain.rpcUrl, {
951
+ method: "POST",
952
+ headers: {
953
+ "Content-Type": "application/json"
954
+ },
955
+ body: JSON.stringify({
956
+ jsonrpc: "2.0",
957
+ id: 1,
958
+ method: "eth_getBalance",
959
+ params: [address, "latest"]
960
+ })
961
+ });
962
+ if (!response.ok) {
963
+ throw new Error("Failed to fetch balance");
964
+ }
965
+ const data = await response.json();
966
+ return data.result;
967
+ }
968
+ async getERC20Balances(address, chainId) {
969
+ const response = await fetch(`${this.baseUrl}/v1/chains/${chainId}/addresses/${address}/balances:listErc20`);
970
+ if (!response.ok) {
971
+ throw new Error("Failed to fetch ERC20 balances");
972
+ }
973
+ return response.json();
974
+ }
975
+ async getERC721Balances(address, chainId) {
976
+ const response = await fetch(`${this.baseUrl}/v1/chains/${chainId}/addresses/${address}/balances:listErc721`);
977
+ if (!response.ok) {
978
+ throw new Error("Failed to fetch ERC721 balances");
979
+ }
980
+ return response.json();
981
+ }
982
+ async getERC1155Balances(address, chainId) {
983
+ const response = await fetch(`${this.baseUrl}/v1/chains/${chainId}/addresses/${address}/balances:listErc1155`);
984
+ if (!response.ok) {
985
+ throw new Error("Failed to fetch ERC1155 balances");
986
+ }
987
+ return response.json();
988
+ }
989
+ };
990
+ var glacierApi = new GlacierApiClient();
991
+
992
+ // src/hooks/useChainId.ts
993
+ import { useState as useState5 } from "react";
994
+ var CHAIN_ID_STORAGE_KEY = "avalanche-chain-id";
995
+ var DEFAULT_CHAIN_ID = 43113;
996
+ function useChainId() {
997
+ const [chainId, setChainIdState] = useState5(() => {
998
+ const storedChainId = localStorage.getItem(CHAIN_ID_STORAGE_KEY);
999
+ return storedChainId ? Number.parseInt(storedChainId, 10) : DEFAULT_CHAIN_ID;
1000
+ });
1001
+ const setChainId = (newChainId) => {
1002
+ localStorage.setItem(CHAIN_ID_STORAGE_KEY, newChainId.toString());
1003
+ setChainIdState(newChainId);
1004
+ };
1005
+ return { chainId, setChainId };
1006
+ }
1007
+
1008
+ // src/hooks/useGlacier.ts
1009
+ var glacierKeys = {
1010
+ all: ["glacier"],
1011
+ blockchains: () => [...glacierKeys.all, "blockchains"],
1012
+ blockchain: (chainId) => [...glacierKeys.blockchains(), chainId],
1013
+ validators: (subnetId) => [...glacierKeys.all, "validators", subnetId],
1014
+ subnets: () => [...glacierKeys.all, "subnets"],
1015
+ balance: (address, chainId) => [...glacierKeys.all, "balance", address, chainId],
1016
+ erc20Balances: (address, chainId) => [...glacierKeys.all, "erc20Balances", address, chainId],
1017
+ erc721Balances: (address, chainId) => [...glacierKeys.all, "erc721Balances", address, chainId],
1018
+ erc1155Balances: (address, chainId) => [...glacierKeys.all, "erc1155Balances", address, chainId]
1019
+ };
1020
+ function useGlacier() {
1021
+ var _a;
1022
+ const { wallet } = useAvaCloudWallet();
1023
+ const { chainId } = useChainId();
1024
+ const { data: blockchain } = useBlockchain(chainId.toString());
1025
+ const { data: balance, isLoading: isLoadingBalance } = useQuery({
1026
+ queryKey: glacierKeys.balance(wallet.address || "", chainId.toString()),
1027
+ queryFn: () => glacierApi.getBalance(wallet.address || "", chainId.toString()),
1028
+ enabled: !!wallet.address,
1029
+ refetchInterval: 3e3
1030
+ // Refetch every 3 seconds
1031
+ });
1032
+ return {
1033
+ balance: balance ? (Number.parseInt(balance, 16) / 1e18).toString() : "0",
1034
+ isLoadingBalance,
1035
+ currencySymbol: ((_a = blockchain == null ? void 0 : blockchain.networkToken) == null ? void 0 : _a.symbol) || "AVAX",
1036
+ blockchain
1037
+ };
1038
+ }
1039
+ function useBlockchain(chainId) {
1040
+ return useQuery({
1041
+ queryKey: glacierKeys.blockchain(chainId),
1042
+ queryFn: () => glacierApi.getBlockchain(chainId),
1043
+ enabled: !!chainId,
1044
+ staleTime: Number.POSITIVE_INFINITY
1045
+ });
1046
+ }
1047
+ function useERC20Balances(address, chainId) {
1048
+ return useQuery({
1049
+ queryKey: glacierKeys.erc20Balances(address || "", chainId || ""),
1050
+ queryFn: () => glacierApi.getERC20Balances(address || "", chainId || ""),
1051
+ enabled: !!address && !!chainId,
1052
+ refetchInterval: 3e3
1053
+ // Refetch every 3 seconds
1054
+ });
1055
+ }
1056
+ function useERC721Balances(address, chainId) {
1057
+ return useQuery({
1058
+ queryKey: glacierKeys.erc721Balances(address || "", chainId || ""),
1059
+ queryFn: () => glacierApi.getERC721Balances(address || "", chainId || ""),
1060
+ enabled: !!address && !!chainId,
1061
+ refetchInterval: 3e3
1062
+ // Refetch every 3 seconds
1063
+ });
1064
+ }
1065
+ function useERC1155Balances(address, chainId) {
1066
+ return useQuery({
1067
+ queryKey: glacierKeys.erc1155Balances(address || "", chainId || ""),
1068
+ queryFn: () => glacierApi.getERC1155Balances(address || "", chainId || ""),
1069
+ enabled: !!address && !!chainId,
1070
+ refetchInterval: 3e3
1071
+ // Refetch every 3 seconds
1072
+ });
1073
+ }
1074
+
1075
+ // src/providers/ThemeProvider.tsx
1076
+ import { ThemeProvider as K2ThemeProvider, createTheme } from "@avalabs/core-k2-components";
1077
+ import { createContext as createContext3, useContext as useContext3, useState as useState6, useCallback as useCallback4, useEffect as useEffect4 } from "react";
1078
+ import { jsx as jsx6 } from "react/jsx-runtime";
1079
+ var ThemeContext = createContext3({
1080
+ isDarkMode: false,
1081
+ toggleTheme: () => {
1082
+ }
1083
+ });
1084
+ var useThemeMode = () => useContext3(ThemeContext);
1085
+ var lightTheme = createTheme({
1086
+ typography: {
1087
+ fontFamily: "Inter, sans-serif"
1088
+ }
1089
+ });
1090
+ var darkTheme = createTheme({
1091
+ typography: {
1092
+ fontFamily: "Inter, sans-serif"
1093
+ },
1094
+ palette: {
1095
+ mode: "dark",
1096
+ background: {
1097
+ default: "#1A1A1A",
1098
+ paper: "#1A1A1A"
1099
+ },
1100
+ text: {
1101
+ primary: "#FFFFFF",
1102
+ secondary: "rgba(255, 255, 255, 0.7)"
1103
+ },
1104
+ primary: {
1105
+ main: "#4B9FFF",
1106
+ light: "#73B5FF",
1107
+ dark: "#3B7FCC",
1108
+ contrastText: "#FFFFFF"
1109
+ },
1110
+ divider: "rgba(255, 255, 255, 0.12)"
1111
+ },
1112
+ components: {
1113
+ MuiDialog: {
1114
+ styleOverrides: {
1115
+ paper: {
1116
+ backgroundColor: "#1A1A1A"
1117
+ }
1118
+ }
1119
+ }
1120
+ }
1121
+ });
1122
+ function ThemeProvider({ children, darkMode, onDarkModeChange }) {
1123
+ const [isDarkMode, setIsDarkMode] = useState6(darkMode != null ? darkMode : false);
1124
+ useEffect4(() => {
1125
+ if (darkMode !== void 0 && darkMode !== isDarkMode) {
1126
+ setIsDarkMode(darkMode);
1127
+ }
1128
+ }, [darkMode]);
1129
+ const toggleTheme = useCallback4(() => {
1130
+ const newDarkMode = !isDarkMode;
1131
+ setIsDarkMode(newDarkMode);
1132
+ onDarkModeChange == null ? void 0 : onDarkModeChange(newDarkMode);
1133
+ }, [isDarkMode, onDarkModeChange]);
1134
+ return /* @__PURE__ */ jsx6(ThemeContext.Provider, { value: { isDarkMode, toggleTheme }, children: /* @__PURE__ */ jsx6(K2ThemeProvider, { theme: isDarkMode ? darkTheme : lightTheme, children }) });
1135
+ }
1136
+
1137
+ // src/AvaCloudWalletProvider.tsx
1138
+ import { AUTH_TOKENS_KEY as AUTH_TOKENS_KEY2, OIDC_TOKEN_KEY as OIDC_TOKEN_KEY2, AUTH0_STORAGE_KEYS as AUTH0_STORAGE_KEYS2, CUBIST_USER_ID_KEY as CUBIST_USER_ID_KEY2 } from "@avacloud/waas-common";
1139
+ import { Fragment, jsx as jsx7 } from "react/jsx-runtime";
1140
+ var AvaCloudWalletContext = createContext4(void 0);
1141
+ var queryClient = new QueryClient({
1142
+ defaultOptions: {
1143
+ queries: {
1144
+ staleTime: 1e3 * 60 * 5,
1145
+ // 5 minutes
1146
+ retry: 2
1147
+ }
1148
+ }
1149
+ });
1150
+ var CUBIST_ENV = envs.gamma;
1151
+ function ViemProviderWrapper({ children, chainId }) {
1152
+ const { data: blockchain } = useBlockchain(chainId.toString());
1153
+ if (!(blockchain == null ? void 0 : blockchain.rpcUrl)) {
1154
+ return /* @__PURE__ */ jsx7(Fragment, { children });
1155
+ }
1156
+ return /* @__PURE__ */ jsx7(
1157
+ ViemProvider,
1158
+ {
1159
+ chainId,
1160
+ rpcUrl: blockchain.rpcUrl,
1161
+ explorerUrl: blockchain.explorerUrl,
1162
+ children
1163
+ }
1164
+ );
1165
+ }
1166
+ function AvaCloudWalletProvider({
1167
+ children,
1168
+ authServiceUrl = "https://ac-auth-service.vercel.app/",
1169
+ orgId,
1170
+ chainId = 43113,
1171
+ darkMode = false,
1172
+ environment = "development",
1173
+ onAuthSuccess,
1174
+ onAuthError,
1175
+ onWalletUpdate
1176
+ }) {
1177
+ const [isAuthenticated, setIsAuthenticated] = useState7(false);
1178
+ const [isCubistLoading, setIsCubistLoading] = useState7(true);
1179
+ const [isLoading, setIsLoading] = useState7(true);
1180
+ const [user, setUser] = useState7(null);
1181
+ const [wallet, setWallet] = useState7({ address: null });
1182
+ const [orgConfig, setOrgConfig] = useState7(null);
1183
+ const [iframe, setIframe] = useState7(null);
1184
+ const [isIframeReady, setIsIframeReady] = useState7(false);
1185
+ const [cubistClient, setCubistClient] = useState7(null);
1186
+ const [cubistError, setCubistError] = useState7(null);
1187
+ const [pendingOidcToken, setPendingOidcToken] = useState7(null);
1188
+ const iframeRef = useRef2(null);
1189
+ useEffect5(() => {
1190
+ setIsLoading(isCubistLoading || isAuthenticated && !wallet.address);
1191
+ }, [isCubistLoading, isAuthenticated, wallet.address]);
1192
+ const getWalletInfo = useCallback5(async (client, sessionId) => {
1193
+ try {
1194
+ const sessionKeys = await client.sessionKeys();
1195
+ if (!sessionKeys.length) {
1196
+ console.log("[getWalletInfo] No session keys found");
1197
+ return null;
1198
+ }
1199
+ const key = sessionKeys[0];
1200
+ const address = key.materialId;
1201
+ if (!(orgConfig == null ? void 0 : orgConfig.walletProviderOrgID)) {
1202
+ console.error("[getWalletInfo] Missing walletProviderOrgID in organization config");
1203
+ throw new Error("Missing required walletProviderOrgID in organization configuration");
1204
+ }
1205
+ console.log("[getWalletInfo] Returning wallet info with address:", address);
1206
+ return {
1207
+ address,
1208
+ sessionId,
1209
+ orgId: orgConfig.walletProviderOrgID
1210
+ };
1211
+ } catch (err) {
1212
+ console.error("[getWalletInfo] Error:", err);
1213
+ setCubistError(err instanceof Error ? err : new Error("Failed to get wallet info"));
1214
+ return null;
1215
+ }
1216
+ }, [orgConfig]);
1217
+ const loginWithCubist = useCallback5(async (oidcToken) => {
1218
+ console.log("[loginWithCubist] Starting...");
1219
+ console.log("[loginWithCubist] Current orgConfig:", orgConfig);
1220
+ if (!orgConfig || !orgConfig.walletProviderOrgID) {
1221
+ console.error("[loginWithCubist] PREVENTED: Missing walletProviderOrgID in organization config");
1222
+ const error = new Error("Missing required walletProviderOrgID in organization configuration");
1223
+ setCubistError(error);
1224
+ onAuthError == null ? void 0 : onAuthError(error);
1225
+ setIsCubistLoading(false);
1226
+ return;
1227
+ }
1228
+ try {
1229
+ setIsCubistLoading(true);
1230
+ setCubistError(null);
1231
+ if (!(orgConfig == null ? void 0 : orgConfig.walletProviderOrgID)) {
1232
+ console.error("[loginWithCubist] Missing walletProviderOrgID in organization config");
1233
+ throw new Error("Missing required walletProviderOrgID in organization configuration");
1234
+ }
1235
+ let accessToken;
1236
+ if (oidcToken) {
1237
+ console.log("[loginWithCubist] Using provided OIDC token.");
1238
+ accessToken = oidcToken;
1239
+ } else {
1240
+ console.log("[loginWithCubist] Attempting to get OIDC token from localStorage.");
1241
+ const tokens = localStorage.getItem(AUTH_TOKENS_KEY2);
1242
+ if (!tokens) {
1243
+ throw new Error("No authentication tokens found in localStorage");
1244
+ }
1245
+ const parsed = JSON.parse(tokens);
1246
+ accessToken = parsed.access_token;
1247
+ }
1248
+ try {
1249
+ console.log(`[loginWithCubist] Attempting CubeSignerClient.createOidcSession for Org: ${orgConfig.walletProviderOrgID}`);
1250
+ const resp = await CubeSignerClient.createOidcSession(
1251
+ CUBIST_ENV,
1252
+ orgConfig.walletProviderOrgID,
1253
+ accessToken,
1254
+ ["sign:*", "manage:*", "export:*"],
1255
+ {
1256
+ auth_lifetime: 5 * 60,
1257
+ // 5 minutes
1258
+ refresh_lifetime: 30 * 24 * 60 * 60,
1259
+ // 30 days
1260
+ session_lifetime: 90 * 24 * 60 * 60
1261
+ // 90 days
1262
+ }
1263
+ );
1264
+ console.log("[loginWithCubist] createOidcSession response received.");
1265
+ if (resp.requiresMfa()) {
1266
+ console.warn("[loginWithCubist] MFA required, aborting.");
1267
+ throw new Error("MFA required for Cubist login");
1268
+ }
1269
+ const sessionData = resp.data();
1270
+ console.log("[loginWithCubist] Session data obtained, attempting CubeSignerClient.create");
1271
+ const newClient = await CubeSignerClient.create(sessionData);
1272
+ const sessionId = sessionData.session_info.session_id;
1273
+ console.log(`[loginWithCubist] CubeSignerClient created successfully. Session ID: ${sessionId}`);
1274
+ console.log("[loginWithCubist] Attempting getWalletInfo");
1275
+ const cubistWallet = await getWalletInfo(newClient, sessionId);
1276
+ console.log("[loginWithCubist] getWalletInfo result:", cubistWallet);
1277
+ console.log("[loginWithCubist] Setting cubistClient state.");
1278
+ setCubistClient(newClient);
1279
+ if (cubistWallet) {
1280
+ console.log("[loginWithCubist] Setting wallet state with cubistWallet.");
1281
+ setWallet((prev) => ({
1282
+ ...prev,
1283
+ address: cubistWallet.address,
1284
+ cubistWallet
1285
+ }));
1286
+ console.log("[loginWithCubist] Calling onWalletUpdate callback.");
1287
+ onWalletUpdate == null ? void 0 : onWalletUpdate({
1288
+ ...wallet,
1289
+ // Use current wallet state potentially
1290
+ cubistWallet
1291
+ });
1292
+ } else {
1293
+ console.warn("[loginWithCubist] cubistWallet is null, not updating wallet state further.");
1294
+ }
1295
+ } catch (error) {
1296
+ console.error("[loginWithCubist] Error during Cubist session creation/wallet info:", error);
1297
+ localStorage.removeItem(AUTH_TOKENS_KEY2);
1298
+ localStorage.removeItem(AUTH0_STORAGE_KEYS2.IS_AUTHENTICATED);
1299
+ setIsAuthenticated(false);
1300
+ setUser(null);
1301
+ setCubistClient(null);
1302
+ throw error;
1303
+ }
1304
+ } catch (error) {
1305
+ const err = error instanceof Error ? error : new Error("Failed to create Cubist session");
1306
+ console.error("[loginWithCubist] Final catch block error:", err);
1307
+ setCubistError(err);
1308
+ onAuthError == null ? void 0 : onAuthError(err);
1309
+ } finally {
1310
+ console.log("[loginWithCubist] Setting isCubistLoading to false.");
1311
+ setIsCubistLoading(false);
1312
+ }
1313
+ }, [wallet, onWalletUpdate, onAuthError, getWalletInfo, orgConfig]);
1314
+ const { sendMessage } = usePostMessage({
1315
+ authServiceUrl,
1316
+ orgId,
1317
+ environment,
1318
+ iframe,
1319
+ isIframeReady,
1320
+ onAuthSuccess: () => {
1321
+ console.log("[onAuthSuccess] Called");
1322
+ if (user) {
1323
+ if (wallet.address) {
1324
+ console.log("[onAuthSuccess] Calling onAuthSuccess callback with user");
1325
+ onAuthSuccess == null ? void 0 : onAuthSuccess(user);
1326
+ } else {
1327
+ console.log("[onAuthSuccess] Not calling callback yet, waiting for wallet");
1328
+ }
1329
+ } else {
1330
+ console.log("[onAuthSuccess] No user available");
1331
+ }
1332
+ },
1333
+ onAuthError: (error) => {
1334
+ console.log("[onAuthError] Called with error:", error);
1335
+ setIsCubistLoading(false);
1336
+ onAuthError == null ? void 0 : onAuthError(error);
1337
+ },
1338
+ onWalletUpdate: (newWallet) => {
1339
+ console.log("[onWalletUpdate] Called with wallet:", newWallet);
1340
+ setWallet(newWallet);
1341
+ if (user && isAuthenticated) {
1342
+ console.log("[onWalletUpdate] Calling onAuthSuccess callback");
1343
+ onAuthSuccess == null ? void 0 : onAuthSuccess(user);
1344
+ }
1345
+ queryClient.invalidateQueries({ queryKey: ["wallet"] });
1346
+ onWalletUpdate == null ? void 0 : onWalletUpdate(newWallet);
1347
+ },
1348
+ onOidcReceived: (token) => {
1349
+ console.log("[onOidcReceived] Received OIDC token - storing in state only");
1350
+ setIsCubistLoading(true);
1351
+ setPendingOidcToken(token);
1352
+ console.log("[onOidcReceived] Current orgConfig:", orgConfig);
1353
+ const originalLoginWithCubist = loginWithCubist;
1354
+ window.___tempSafeguard_loginWithCubist = (oidcToken) => {
1355
+ if (!(orgConfig == null ? void 0 : orgConfig.walletProviderOrgID)) {
1356
+ console.error("[SAFEGUARD] Prevented direct call to loginWithCubist without orgConfig");
1357
+ return Promise.reject(new Error("Missing required walletProviderOrgID in organization configuration"));
1358
+ }
1359
+ return originalLoginWithCubist(oidcToken);
1360
+ };
1361
+ },
1362
+ onOrgConfigUpdate: (config) => {
1363
+ console.log("[onOrgConfigUpdate] Received org config with walletProviderOrgID:", config == null ? void 0 : config.walletProviderOrgID);
1364
+ console.log("[onOrgConfigUpdate] Current pendingOidcToken:", !!pendingOidcToken);
1365
+ setOrgConfig(config);
1366
+ },
1367
+ setIsAuthenticated,
1368
+ setUser,
1369
+ setIsLoading: (isLoading2) => {
1370
+ console.log("[setIsLoading] Setting isLoading to:", isLoading2);
1371
+ setIsLoading(isLoading2);
1372
+ },
1373
+ setIsIframeReady,
1374
+ wallet,
1375
+ cubistClient
1376
+ });
1377
+ const login = useCallback5(() => {
1378
+ console.log("[login] Called");
1379
+ if (iframe == null ? void 0 : iframe.contentWindow) {
1380
+ setIsCubistLoading(true);
1381
+ sendMessage({ type: "LOGIN_REQUEST" });
1382
+ } else {
1383
+ console.error("[login] No iframe available for login");
1384
+ }
1385
+ }, [iframe, sendMessage]);
1386
+ const logout = useCallback5(() => {
1387
+ console.log("[logout] Called");
1388
+ sendMessage({ type: "LOGOUT_REQUEST" });
1389
+ setUser(null);
1390
+ setWallet({ address: null });
1391
+ setIsAuthenticated(false);
1392
+ localStorage.removeItem(AUTH_TOKENS_KEY2);
1393
+ localStorage.removeItem(AUTH0_STORAGE_KEYS2.IS_AUTHENTICATED);
1394
+ localStorage.removeItem(AUTH0_STORAGE_KEYS2.ACCESS_TOKEN);
1395
+ localStorage.removeItem(AUTH0_STORAGE_KEYS2.ID_TOKEN);
1396
+ localStorage.removeItem(AUTH0_STORAGE_KEYS2.EXPIRES_AT);
1397
+ localStorage.removeItem(CUBIST_USER_ID_KEY2);
1398
+ sessionStorage.removeItem(OIDC_TOKEN_KEY2);
1399
+ setCubistClient(null);
1400
+ setCubistError(null);
1401
+ setPendingOidcToken(null);
1402
+ }, [sendMessage]);
1403
+ const addAccount = useCallback5(async (accountIndex) => {
1404
+ console.log("[addAccount] Called with accountIndex:", accountIndex);
1405
+ if (!isAuthenticated || !user || !wallet.mnemonicId) {
1406
+ throw new Error("User must be authenticated and have a wallet to add an account");
1407
+ }
1408
+ const path = getDerivationPath("EVM" /* EVM */, accountIndex);
1409
+ sendMessage({
1410
+ type: "ADD_ACCOUNT",
1411
+ payload: {
1412
+ accountIndex,
1413
+ mnemonicId: wallet.mnemonicId,
1414
+ derivationPath: path,
1415
+ identityProof: {
1416
+ email: user.email,
1417
+ displayName: user.displayName,
1418
+ sub: user.sub,
1419
+ configured_mfa: user.configured_mfa
1420
+ }
1421
+ }
1422
+ });
1423
+ }, [sendMessage, isAuthenticated, user, wallet.mnemonicId]);
1424
+ useEffect5(() => {
1425
+ console.log("[useEffect Auth] Running effect with dependencies...");
1426
+ console.log("[useEffect Auth] pendingOidcToken:", !!pendingOidcToken);
1427
+ console.log("[useEffect Auth] orgConfig?.walletProviderOrgID:", orgConfig == null ? void 0 : orgConfig.walletProviderOrgID);
1428
+ const hasOrgConfig = !!(orgConfig == null ? void 0 : orgConfig.walletProviderOrgID);
1429
+ const hasOidcToken = !!pendingOidcToken;
1430
+ console.log(`[useEffect Auth] Checking conditions - hasOrgConfig: ${hasOrgConfig}, hasOidcToken: ${hasOidcToken}`);
1431
+ if (hasOrgConfig && hasOidcToken && pendingOidcToken) {
1432
+ console.log("[useEffect Auth] Both orgConfig and oidcToken are available, calling loginWithCubist");
1433
+ const doLogin = async () => {
1434
+ try {
1435
+ await loginWithCubist(pendingOidcToken);
1436
+ } catch (error) {
1437
+ console.error("[useEffect Auth] Error in loginWithCubist:", error);
1438
+ onAuthError == null ? void 0 : onAuthError(error instanceof Error ? error : new Error("Failed to create Cubist session"));
1439
+ } finally {
1440
+ setIsCubistLoading(false);
1441
+ setPendingOidcToken(null);
1442
+ }
1443
+ };
1444
+ doLogin();
1445
+ }
1446
+ }, [orgConfig, pendingOidcToken, loginWithCubist, onAuthError]);
1447
+ useEffect5(() => {
1448
+ console.log("[useEffect Iframe] Setting up iframe...");
1449
+ if (typeof window === "undefined" || typeof document === "undefined") {
1450
+ return;
1451
+ }
1452
+ const frame = document.createElement("iframe");
1453
+ frame.style.position = "fixed";
1454
+ frame.style.bottom = "0";
1455
+ frame.style.right = "0";
1456
+ frame.style.width = "0";
1457
+ frame.style.height = "0";
1458
+ frame.style.border = "none";
1459
+ frame.style.visibility = "hidden";
1460
+ frame.setAttribute("sandbox", "allow-scripts allow-same-origin allow-forms allow-popups");
1461
+ frame.src = authServiceUrl;
1462
+ document.body.appendChild(frame);
1463
+ iframeRef.current = frame;
1464
+ setIframe(frame);
1465
+ console.log("[useEffect Iframe] Iframe created and added to DOM");
1466
+ const timeoutId = setTimeout(() => {
1467
+ console.log("[useEffect Iframe] Timeout reached, setting isCubistLoading to false");
1468
+ setIsCubistLoading(false);
1469
+ }, 5e3);
1470
+ return () => {
1471
+ clearTimeout(timeoutId);
1472
+ if (iframeRef.current) {
1473
+ iframeRef.current.remove();
1474
+ iframeRef.current = null;
1475
+ console.log("[useEffect Iframe] Iframe removed in cleanup");
1476
+ }
1477
+ };
1478
+ }, [authServiceUrl]);
1479
+ const contextValue = {
1480
+ isAuthenticated,
1481
+ isLoading,
1482
+ user,
1483
+ wallet,
1484
+ orgConfig,
1485
+ logout,
1486
+ loginWithCubist,
1487
+ cubistClient,
1488
+ cubistError,
1489
+ login,
1490
+ addAccount,
1491
+ queryClient,
1492
+ iframe,
1493
+ authServiceUrl,
1494
+ chainId,
1495
+ environment
1496
+ };
1497
+ return /* @__PURE__ */ jsx7(AvaCloudWalletContext.Provider, { value: contextValue, children: /* @__PURE__ */ jsx7(QueryClientProvider, { client: queryClient, children: /* @__PURE__ */ jsx7(ThemeProvider, { darkMode, children: /* @__PURE__ */ jsx7(AuthModalProvider, { children: /* @__PURE__ */ jsx7(ViemProviderWrapper, { chainId, children }) }) }) }) });
1498
+ }
1499
+ function useAvaCloudWallet() {
1500
+ const context = useContext4(AvaCloudWalletContext);
1501
+ if (context === void 0) {
1502
+ throw new Error("useAvaCloudWallet must be used within an AvaCloudWalletProvider");
1503
+ }
1504
+ return context;
1505
+ }
1506
+
1507
+ // src/components/LoginButton.tsx
1508
+ import { useState as useState8 } from "react";
1509
+ import { Button as Button2, Dialog as Dialog3, DialogContent as DialogContent3, DialogTitle as DialogTitle2 } from "@avalabs/core-k2-components";
1510
+ import { Fragment as Fragment2, jsx as jsx8, jsxs as jsxs5 } from "react/jsx-runtime";
1511
+ function LoginButton({
1512
+ label = "Sign in",
1513
+ className = "",
1514
+ ...props
1515
+ }) {
1516
+ const { isLoading } = useAvaCloudWallet();
1517
+ const [isModalOpen, setIsModalOpen] = useState8(false);
1518
+ const handleOpen = () => setIsModalOpen(true);
1519
+ const handleClose = () => setIsModalOpen(false);
1520
+ return /* @__PURE__ */ jsxs5(Fragment2, { children: [
1521
+ /* @__PURE__ */ jsx8(
1522
+ Button2,
1523
+ {
1524
+ onClick: handleOpen,
1525
+ disabled: isLoading,
1526
+ variant: "contained",
1527
+ color: "primary",
1528
+ className,
1529
+ ...props,
1530
+ children: isLoading ? "Loading..." : label
1531
+ }
1532
+ ),
1533
+ /* @__PURE__ */ jsxs5(
1534
+ Dialog3,
1535
+ {
1536
+ open: isModalOpen,
1537
+ onClose: handleClose,
1538
+ maxWidth: "xs",
1539
+ children: [
1540
+ /* @__PURE__ */ jsx8(DialogTitle2, { children: /* @__PURE__ */ jsx8("img", { src: "", alt: "AvaCloud Connect", style: { height: "32px" } }) }),
1541
+ /* @__PURE__ */ jsx8(DialogContent3, { sx: { padding: 4 }, children: /* @__PURE__ */ jsx8(
1542
+ LoginModal,
1543
+ {
1544
+ open: isModalOpen,
1545
+ onClose: handleClose
1546
+ }
1547
+ ) })
1548
+ ]
1549
+ }
1550
+ )
1551
+ ] });
1552
+ }
1553
+
1554
+ // src/components/WalletButton.tsx
1555
+ import { useState as useState16 } from "react";
1556
+ import {
1557
+ Button as Button8,
1558
+ Box as Box11,
1559
+ Typography as Typography11,
1560
+ IconButton as IconButton9,
1561
+ CopyIcon as CopyIcon5,
1562
+ AvaCloudIcon as AvaCloudIcon2,
1563
+ useTheme as useTheme4
1564
+ } from "@avalabs/core-k2-components";
1565
+
1566
+ // src/components/WalletCard.tsx
1567
+ import { useState as useState15 } from "react";
1568
+ import {
1569
+ Typography as Typography10,
1570
+ Box as Box10,
1571
+ IconButton as IconButton8,
1572
+ CopyIcon as CopyIcon4,
1573
+ useTheme as useTheme3,
1574
+ CircularProgress as CircularProgress2,
1575
+ AvaCloudIcon,
1576
+ Dialog as Dialog4,
1577
+ DialogContent as DialogContent4,
1578
+ Button as Button7
1579
+ } from "@avalabs/core-k2-components";
1580
+
1581
+ // src/components/SendView.tsx
1582
+ import { useState as useState11, useEffect as useEffect6 } from "react";
1583
+ import {
1584
+ Box as Box3,
1585
+ Typography as Typography4,
1586
+ TextField as TextField2,
1587
+ Button as Button3,
1588
+ Alert,
1589
+ Paper,
1590
+ IconButton as IconButton3,
1591
+ CircularProgress,
1592
+ Select,
1593
+ MenuItem
1594
+ } from "@avalabs/core-k2-components";
1595
+ import { Icon } from "@iconify/react";
1596
+
1597
+ // src/hooks/useTransferTokens.ts
1598
+ import { useCallback as useCallback6, useState as useState9 } from "react";
1599
+ import { Secp256k1 } from "@cubist-labs/cubesigner-sdk";
1600
+ import { useQueryClient } from "@tanstack/react-query";
1601
+ import {
1602
+ isAddress,
1603
+ parseEther,
1604
+ parseUnits,
1605
+ formatTransactionRequest,
1606
+ formatEther,
1607
+ encodeFunctionData,
1608
+ erc20Abi
1609
+ } from "viem";
1610
+ function useTransferTokens() {
1611
+ const [state, setState] = useState9({
1612
+ isLoading: false,
1613
+ error: null,
1614
+ txHash: null,
1615
+ viewState: "idle",
1616
+ actualBaseFee: null,
1617
+ actualPriorityFee: null,
1618
+ actualTotalFee: null
1619
+ });
1620
+ const { wallet, cubistClient } = useAvaCloudWallet();
1621
+ const { publicClient } = useViem();
1622
+ const queryClient2 = useQueryClient();
1623
+ const reset = useCallback6(() => {
1624
+ setState({
1625
+ isLoading: false,
1626
+ error: null,
1627
+ txHash: null,
1628
+ viewState: "idle",
1629
+ actualBaseFee: null,
1630
+ actualPriorityFee: null,
1631
+ actualTotalFee: null
1632
+ });
1633
+ }, []);
1634
+ const transfer = useCallback6(async (toAddress, amount) => {
1635
+ var _a;
1636
+ if (!publicClient || !cubistClient || !(wallet == null ? void 0 : wallet.address)) {
1637
+ setState((prev) => ({
1638
+ ...prev,
1639
+ error: "Client not initialized",
1640
+ viewState: "failure"
1641
+ }));
1642
+ return;
1643
+ }
1644
+ if (!publicClient.chain) {
1645
+ setState((prev) => ({
1646
+ ...prev,
1647
+ error: "Chain not configured",
1648
+ viewState: "failure"
1649
+ }));
1650
+ return;
1651
+ }
1652
+ if (!isAddress(toAddress)) {
1653
+ setState((prev) => ({
1654
+ ...prev,
1655
+ error: "Invalid recipient address",
1656
+ viewState: "failure"
1657
+ }));
1658
+ return;
1659
+ }
1660
+ setState((prev) => ({
1661
+ ...prev,
1662
+ isLoading: true,
1663
+ error: null,
1664
+ viewState: "loading"
1665
+ }));
1666
+ try {
1667
+ const key = await cubistClient.org().getKeyByMaterialId(Secp256k1.Evm, wallet.address);
1668
+ const tx = await publicClient.prepareTransactionRequest({
1669
+ account: wallet.address,
1670
+ to: toAddress,
1671
+ value: parseEther(amount),
1672
+ chain: publicClient.chain
1673
+ });
1674
+ const txReq = formatTransactionRequest(tx);
1675
+ const sig = await key.signEvm({
1676
+ chain_id: publicClient.chain.id,
1677
+ tx: txReq
1678
+ });
1679
+ const serializedTransaction = sig.data().rlp_signed_tx;
1680
+ const hash = await publicClient.sendRawTransaction({ serializedTransaction });
1681
+ setState((prev) => ({
1682
+ ...prev,
1683
+ txHash: hash
1684
+ }));
1685
+ const receipt = await publicClient.waitForTransactionReceipt({
1686
+ hash,
1687
+ confirmations: 1
1688
+ });
1689
+ const block = await publicClient.getBlock({
1690
+ blockHash: receipt.blockHash
1691
+ });
1692
+ const baseFeePerGas = block.baseFeePerGas || BigInt(0);
1693
+ const effectivePriorityFee = receipt.effectiveGasPrice - baseFeePerGas;
1694
+ const actualBaseFee = formatEther(baseFeePerGas * receipt.gasUsed);
1695
+ const actualPriorityFee = formatEther(effectivePriorityFee * receipt.gasUsed);
1696
+ const actualTotalFee = formatEther(receipt.effectiveGasPrice * receipt.gasUsed);
1697
+ console.log("Transaction confirmed:", receipt);
1698
+ if ((wallet == null ? void 0 : wallet.address) && ((_a = publicClient.chain) == null ? void 0 : _a.id)) {
1699
+ const chainId = publicClient.chain.id.toString();
1700
+ queryClient2.invalidateQueries({
1701
+ queryKey: glacierKeys.balance(wallet.address, chainId)
1702
+ });
1703
+ }
1704
+ setState((prev) => ({
1705
+ ...prev,
1706
+ viewState: "success",
1707
+ actualBaseFee: Number(actualBaseFee).toFixed(6),
1708
+ actualPriorityFee: Number(actualPriorityFee).toFixed(6),
1709
+ actualTotalFee: Number(actualTotalFee).toFixed(6)
1710
+ }));
1711
+ } catch (err) {
1712
+ console.error("Failed to send transaction:", err);
1713
+ setState((prev) => ({
1714
+ ...prev,
1715
+ error: err instanceof Error ? err.message : "Failed to send transaction",
1716
+ viewState: "failure"
1717
+ }));
1718
+ } finally {
1719
+ setState((prev) => ({ ...prev, isLoading: false }));
1720
+ }
1721
+ }, [publicClient, cubistClient, wallet == null ? void 0 : wallet.address, queryClient2]);
1722
+ const transferERC20 = useCallback6(async (tokenAddress, toAddress, amount, decimals) => {
1723
+ var _a;
1724
+ if (!publicClient || !cubistClient || !(wallet == null ? void 0 : wallet.address)) {
1725
+ setState((prev) => ({
1726
+ ...prev,
1727
+ error: "Client not initialized",
1728
+ viewState: "failure"
1729
+ }));
1730
+ return;
1731
+ }
1732
+ if (!publicClient.chain) {
1733
+ setState((prev) => ({
1734
+ ...prev,
1735
+ error: "Chain not configured",
1736
+ viewState: "failure"
1737
+ }));
1738
+ return;
1739
+ }
1740
+ if (!isAddress(toAddress)) {
1741
+ setState((prev) => ({
1742
+ ...prev,
1743
+ error: "Invalid recipient address",
1744
+ viewState: "failure"
1745
+ }));
1746
+ return;
1747
+ }
1748
+ setState((prev) => ({
1749
+ ...prev,
1750
+ isLoading: true,
1751
+ error: null,
1752
+ viewState: "loading"
1753
+ }));
1754
+ try {
1755
+ const key = await cubistClient.org().getKeyByMaterialId(Secp256k1.Evm, wallet.address);
1756
+ const data = encodeFunctionData({
1757
+ abi: erc20Abi,
1758
+ functionName: "transfer",
1759
+ args: [toAddress, parseUnits(amount, decimals)]
1760
+ });
1761
+ const tx = await publicClient.prepareTransactionRequest({
1762
+ account: wallet.address,
1763
+ to: tokenAddress,
1764
+ data,
1765
+ chain: publicClient.chain
1766
+ });
1767
+ const txReq = formatTransactionRequest(tx);
1768
+ const sig = await key.signEvm({
1769
+ chain_id: publicClient.chain.id,
1770
+ tx: txReq
1771
+ });
1772
+ const serializedTransaction = sig.data().rlp_signed_tx;
1773
+ const hash = await publicClient.sendRawTransaction({ serializedTransaction });
1774
+ setState((prev) => ({
1775
+ ...prev,
1776
+ txHash: hash
1777
+ }));
1778
+ const receipt = await publicClient.waitForTransactionReceipt({
1779
+ hash,
1780
+ confirmations: 1
1781
+ });
1782
+ const block = await publicClient.getBlock({
1783
+ blockHash: receipt.blockHash
1784
+ });
1785
+ const baseFeePerGas = block.baseFeePerGas || BigInt(0);
1786
+ const effectivePriorityFee = receipt.effectiveGasPrice - baseFeePerGas;
1787
+ const actualBaseFee = formatEther(baseFeePerGas * receipt.gasUsed);
1788
+ const actualPriorityFee = formatEther(effectivePriorityFee * receipt.gasUsed);
1789
+ const actualTotalFee = formatEther(receipt.effectiveGasPrice * receipt.gasUsed);
1790
+ console.log("Transaction confirmed:", receipt);
1791
+ if ((wallet == null ? void 0 : wallet.address) && ((_a = publicClient.chain) == null ? void 0 : _a.id)) {
1792
+ const chainId = publicClient.chain.id.toString();
1793
+ queryClient2.invalidateQueries({
1794
+ queryKey: glacierKeys.erc20Balances(wallet.address, chainId)
1795
+ });
1796
+ queryClient2.invalidateQueries({
1797
+ queryKey: glacierKeys.balance(wallet.address, chainId)
1798
+ });
1799
+ }
1800
+ setState((prev) => ({
1801
+ ...prev,
1802
+ viewState: "success",
1803
+ actualBaseFee: Number(actualBaseFee).toFixed(6),
1804
+ actualPriorityFee: Number(actualPriorityFee).toFixed(6),
1805
+ actualTotalFee: Number(actualTotalFee).toFixed(6)
1806
+ }));
1807
+ } catch (err) {
1808
+ console.error("Failed to send transaction:", err);
1809
+ setState((prev) => ({
1810
+ ...prev,
1811
+ error: err instanceof Error ? err.message : "Failed to send transaction",
1812
+ viewState: "failure"
1813
+ }));
1814
+ } finally {
1815
+ setState((prev) => ({ ...prev, isLoading: false }));
1816
+ }
1817
+ }, [publicClient, cubistClient, wallet == null ? void 0 : wallet.address, queryClient2]);
1818
+ return {
1819
+ ...state,
1820
+ transfer,
1821
+ transferERC20,
1822
+ reset
1823
+ };
1824
+ }
1825
+
1826
+ // src/hooks/useGasEstimation.ts
1827
+ import { useCallback as useCallback7, useState as useState10 } from "react";
1828
+ import { formatEther as formatEther2, parseEther as parseEther2 } from "viem";
1829
+ function useGasEstimation() {
1830
+ const [state, setState] = useState10({
1831
+ isLoading: false,
1832
+ error: null,
1833
+ baseFee: null,
1834
+ priorityFee: null,
1835
+ totalFee: null,
1836
+ totalWithAmount: null
1837
+ });
1838
+ const { publicClient } = useViem();
1839
+ const reset = useCallback7(() => {
1840
+ setState({
1841
+ isLoading: false,
1842
+ error: null,
1843
+ baseFee: null,
1844
+ priorityFee: null,
1845
+ totalFee: null,
1846
+ totalWithAmount: null
1847
+ });
1848
+ }, []);
1849
+ const updateTotal = useCallback7((amount) => {
1850
+ if (!state.totalFee) return;
1851
+ const amountValue = Number.parseFloat(amount);
1852
+ if (Number.isNaN(amountValue)) return;
1853
+ const newTotal = (Number(state.totalFee) + amountValue).toFixed(6);
1854
+ setState((prev) => ({
1855
+ ...prev,
1856
+ totalWithAmount: newTotal
1857
+ }));
1858
+ }, [state.totalFee]);
1859
+ const estimateGas = useCallback7(async (toAddress, amount) => {
1860
+ if (!publicClient) {
1861
+ setState((prev) => ({
1862
+ ...prev,
1863
+ error: "Client not initialized",
1864
+ isLoading: false
1865
+ }));
1866
+ return;
1867
+ }
1868
+ setState((prev) => ({
1869
+ ...prev,
1870
+ isLoading: true,
1871
+ error: null
1872
+ }));
1873
+ try {
1874
+ const block = await publicClient.getBlock();
1875
+ const gasEstimate = await publicClient.estimateGas({
1876
+ to: toAddress,
1877
+ value: parseEther2(amount)
1878
+ });
1879
+ const feeHistory = await publicClient.getFeeHistory({
1880
+ blockCount: 10,
1881
+ rewardPercentiles: [50]
1882
+ });
1883
+ const baseFeePerGas = block.baseFeePerGas || BigInt(0);
1884
+ const priorityFeePerGas = feeHistory.reward && feeHistory.reward.length > 0 ? feeHistory.reward.reduce((acc, reward) => acc + reward[0], BigInt(0)) / BigInt(feeHistory.reward.length) : BigInt(0);
1885
+ const totalFeeWei = (baseFeePerGas + priorityFeePerGas) * gasEstimate;
1886
+ const baseFeeEth = Number(formatEther2(baseFeePerGas * gasEstimate)).toFixed(6);
1887
+ const priorityFeeEth = Number(formatEther2(priorityFeePerGas * gasEstimate)).toFixed(6);
1888
+ const totalFeeEth = Number(formatEther2(totalFeeWei)).toFixed(6);
1889
+ const totalWithAmount = (Number(totalFeeEth) + Number.parseFloat(amount)).toFixed(6);
1890
+ setState((prev) => ({
1891
+ ...prev,
1892
+ baseFee: baseFeeEth,
1893
+ priorityFee: priorityFeeEth,
1894
+ totalFee: totalFeeEth,
1895
+ totalWithAmount
1896
+ }));
1897
+ } catch (err) {
1898
+ console.error("Failed to estimate gas:", err);
1899
+ setState((prev) => ({
1900
+ ...prev,
1901
+ error: err instanceof Error ? err.message : "Failed to estimate gas",
1902
+ baseFee: null,
1903
+ priorityFee: null,
1904
+ totalFee: null,
1905
+ totalWithAmount: null
1906
+ }));
1907
+ } finally {
1908
+ setState((prev) => ({ ...prev, isLoading: false }));
1909
+ }
1910
+ }, [publicClient]);
1911
+ return {
1912
+ ...state,
1913
+ estimateGas,
1914
+ updateTotal,
1915
+ reset
1916
+ };
1917
+ }
1918
+
1919
+ // src/components/LoadingAnimation.tsx
1920
+ import { useLottie } from "lottie-react";
1921
+ import { Box, Typography as Typography3 } from "@avalabs/core-k2-components";
1922
+ import { jsx as jsx9, jsxs as jsxs6 } from "react/jsx-runtime";
1923
+ var loadingAnimation = {
1924
+ "v": "5.5.9",
1925
+ "fr": 32.498,
1926
+ "ip": 0,
1927
+ "op": 40,
1928
+ "w": 500,
1929
+ "h": 500,
1930
+ "nm": " ",
1931
+ "assets": [],
1932
+ "layers": [
1933
+ {
1934
+ "ind": 1,
1935
+ "ty": 4,
1936
+ "nm": "kanan stop",
1937
+ "sr": 0.63,
1938
+ "ks": {
1939
+ "o": { "a": 0, "k": 100, "ix": 11 },
1940
+ "r": { "a": 0, "k": 0, "ix": 10 },
1941
+ "p": {
1942
+ "a": 1,
1943
+ "k": [
1944
+ { "i": { "x": 0.667, "y": 1 }, "o": { "x": 0.333, "y": 0 }, "t": 0, "s": [380, 350, 0], "to": [0, -16.667, 0], "ti": [0, 33.333, 0] },
1945
+ { "i": { "x": 0.667, "y": 1 }, "o": { "x": 0.333, "y": 0 }, "t": 10, "s": [380, 250, 0], "to": [0, -33.333, 0], "ti": [0, 16.667, 0] },
1946
+ { "t": 20, "s": [380, 150, 0] }
1947
+ ],
1948
+ "ix": 2,
1949
+ "x": "var $bm_rt;\n$bm_rt = loopOut('pingpong');"
1950
+ },
1951
+ "a": { "a": 0, "k": [-29.557, -1.557, 0], "ix": 1 },
1952
+ "s": { "a": 0, "k": [200, 200, 100], "ix": 6 }
1953
+ },
1954
+ "ao": 0,
1955
+ "shapes": [
1956
+ {
1957
+ "ty": "gr",
1958
+ "it": [
1959
+ { "d": 1, "ty": "el", "s": { "a": 0, "k": [48.887, 48.887], "ix": 2 }, "p": { "a": 0, "k": [0, 0], "ix": 3 }, "nm": "Ellipse Path 1" },
1960
+ { "ty": "fl", "c": { "a": 0, "k": [0.851, 0.878, 0.902, 1], "ix": 4 }, "o": { "a": 0, "k": 100, "ix": 5 }, "r": 1, "nm": "Fill 1" },
1961
+ { "ty": "tr", "p": { "a": 0, "k": [-29.557, -1.557], "ix": 2 }, "a": { "a": 0, "k": [0, 0], "ix": 1 }, "s": { "a": 0, "k": [100, 100], "ix": 3 }, "r": { "a": 0, "k": 0, "ix": 6 }, "o": { "a": 0, "k": 100, "ix": 7 }, "sk": { "a": 0, "k": 0, "ix": 4 }, "sa": { "a": 0, "k": 0, "ix": 5 }, "nm": "Transform" }
1962
+ ],
1963
+ "nm": "Ellipse 1",
1964
+ "cix": 2,
1965
+ "ix": 1
1966
+ }
1967
+ ],
1968
+ "ip": 0,
1969
+ "op": 40,
1970
+ "st": 0
1971
+ },
1972
+ {
1973
+ "ind": 2,
1974
+ "ty": 4,
1975
+ "nm": "tengah stop",
1976
+ "sr": 0.63,
1977
+ "ks": {
1978
+ "o": { "a": 0, "k": 100, "ix": 11 },
1979
+ "r": { "a": 0, "k": 0, "ix": 10 },
1980
+ "p": { "a": 0, "k": [250, 250, 0], "ix": 2 },
1981
+ "a": { "a": 0, "k": [-29.557, -1.557, 0], "ix": 1 },
1982
+ "s": { "a": 0, "k": [200, 200, 100], "ix": 6 }
1983
+ },
1984
+ "ao": 0,
1985
+ "shapes": [
1986
+ {
1987
+ "ty": "gr",
1988
+ "it": [
1989
+ { "d": 1, "ty": "el", "s": { "a": 0, "k": [48.887, 48.887], "ix": 2 }, "p": { "a": 0, "k": [0, 0], "ix": 3 }, "nm": "Ellipse Path 1" },
1990
+ { "ty": "fl", "c": { "a": 0, "k": [0.851, 0.878, 0.902, 1], "ix": 4 }, "o": { "a": 0, "k": 100, "ix": 5 }, "r": 1, "nm": "Fill 1" },
1991
+ { "ty": "tr", "p": { "a": 0, "k": [-29.557, -1.557], "ix": 2 }, "a": { "a": 0, "k": [0, 0], "ix": 1 }, "s": { "a": 0, "k": [100, 100], "ix": 3 }, "r": { "a": 0, "k": 0, "ix": 6 }, "o": { "a": 0, "k": 100, "ix": 7 }, "sk": { "a": 0, "k": 0, "ix": 4 }, "sa": { "a": 0, "k": 0, "ix": 5 }, "nm": "Transform" }
1992
+ ],
1993
+ "nm": "Ellipse 1",
1994
+ "cix": 2,
1995
+ "ix": 1
1996
+ }
1997
+ ],
1998
+ "ip": 0,
1999
+ "op": 40,
2000
+ "st": 0
2001
+ },
2002
+ {
2003
+ "ind": 3,
2004
+ "ty": 4,
2005
+ "nm": "kiri stop",
2006
+ "sr": 0.63,
2007
+ "ks": {
2008
+ "o": { "a": 0, "k": 100, "ix": 11 },
2009
+ "r": { "a": 0, "k": 0, "ix": 10 },
2010
+ "p": {
2011
+ "a": 1,
2012
+ "k": [
2013
+ { "i": { "x": 0.667, "y": 1 }, "o": { "x": 0.333, "y": 0 }, "t": 0, "s": [120, 150, 0], "to": [0, 16.667, 0], "ti": [0, -33.333, 0] },
2014
+ { "i": { "x": 0.667, "y": 1 }, "o": { "x": 0.333, "y": 0 }, "t": 10, "s": [120, 250, 0], "to": [0, 33.333, 0], "ti": [0, -16.667, 0] },
2015
+ { "t": 20, "s": [120, 350, 0] }
2016
+ ],
2017
+ "ix": 2,
2018
+ "x": "var $bm_rt;\n$bm_rt = loopOut('pingpong');"
2019
+ },
2020
+ "a": { "a": 0, "k": [-29.557, -1.557, 0], "ix": 1 },
2021
+ "s": { "a": 0, "k": [200, 200, 100], "ix": 6 }
2022
+ },
2023
+ "ao": 0,
2024
+ "shapes": [
2025
+ {
2026
+ "ty": "gr",
2027
+ "it": [
2028
+ { "d": 1, "ty": "el", "s": { "a": 0, "k": [48.887, 48.887], "ix": 2 }, "p": { "a": 0, "k": [0, 0], "ix": 3 }, "nm": "Ellipse Path 1" },
2029
+ { "ty": "fl", "c": { "a": 0, "k": [0.851, 0.878, 0.902, 1], "ix": 4 }, "o": { "a": 0, "k": 100, "ix": 5 }, "r": 1, "nm": "Fill 1" },
2030
+ { "ty": "tr", "p": { "a": 0, "k": [-29.557, -1.557], "ix": 2 }, "a": { "a": 0, "k": [0, 0], "ix": 1 }, "s": { "a": 0, "k": [100, 100], "ix": 3 }, "r": { "a": 0, "k": 0, "ix": 6 }, "o": { "a": 0, "k": 100, "ix": 7 }, "sk": { "a": 0, "k": 0, "ix": 4 }, "sa": { "a": 0, "k": 0, "ix": 5 }, "nm": "Transform" }
2031
+ ],
2032
+ "nm": "Ellipse 1",
2033
+ "cix": 2,
2034
+ "ix": 1
2035
+ }
2036
+ ],
2037
+ "ip": 0,
2038
+ "op": 40,
2039
+ "st": 0
2040
+ }
2041
+ ],
2042
+ "markers": []
2043
+ };
2044
+ var LoadingAnimation = ({ size = 120, message }) => {
2045
+ const { View } = useLottie({
2046
+ animationData: loadingAnimation,
2047
+ loop: true
2048
+ });
2049
+ return /* @__PURE__ */ jsxs6(Box, { sx: {
2050
+ display: "flex",
2051
+ flexDirection: "column",
2052
+ alignItems: "center",
2053
+ justifyContent: "center",
2054
+ gap: 2
2055
+ }, children: [
2056
+ /* @__PURE__ */ jsx9(Box, { sx: { width: size, height: size }, children: View }),
2057
+ message && /* @__PURE__ */ jsx9(Typography3, { variant: "body2", color: "text.secondary", children: message })
2058
+ ] });
2059
+ };
2060
+
2061
+ // src/components/SendView.tsx
2062
+ import {
2063
+ isAddress as isAddress2
2064
+ } from "viem";
2065
+
2066
+ // src/components/TokenImage.tsx
2067
+ import { Box as Box2 } from "@avalabs/core-k2-components";
2068
+ import { jsx as jsx10 } from "react/jsx-runtime";
2069
+ function TokenImage({ symbol, logoUri, size = 32 }) {
2070
+ if (logoUri) {
2071
+ return /* @__PURE__ */ jsx10(
2072
+ "img",
2073
+ {
2074
+ src: logoUri,
2075
+ alt: symbol,
2076
+ style: {
2077
+ width: size,
2078
+ height: size,
2079
+ borderRadius: "50%",
2080
+ objectFit: "cover"
2081
+ }
2082
+ }
2083
+ );
2084
+ }
2085
+ return /* @__PURE__ */ jsx10(Box2, { sx: {
2086
+ width: size,
2087
+ height: size,
2088
+ borderRadius: "50%",
2089
+ bgcolor: "primary.light",
2090
+ display: "flex",
2091
+ alignItems: "center",
2092
+ justifyContent: "center",
2093
+ color: "white",
2094
+ fontSize: `${size * 0.4375}px`,
2095
+ fontWeight: 500
2096
+ }, children: symbol == null ? void 0 : symbol.slice(0, 2) });
2097
+ }
2098
+
2099
+ // src/components/SendView.tsx
2100
+ import { Fragment as Fragment3, jsx as jsx11, jsxs as jsxs7 } from "react/jsx-runtime";
2101
+ var isValidAmount = (amount) => {
2102
+ if (!amount || amount === "." || amount === "0.") return false;
2103
+ const value = Number.parseFloat(amount);
2104
+ if (Number.isNaN(value) || value <= 0) return false;
2105
+ return true;
2106
+ };
2107
+ function LoadingView() {
2108
+ return /* @__PURE__ */ jsx11(Box3, { sx: {
2109
+ display: "flex",
2110
+ alignItems: "center",
2111
+ justifyContent: "center",
2112
+ height: "100%",
2113
+ minHeight: "400px"
2114
+ }, children: /* @__PURE__ */ jsx11(LoadingAnimation, { message: "Processing transaction..." }) });
2115
+ }
2116
+ function SendFormView({
2117
+ recipient,
2118
+ amount,
2119
+ error,
2120
+ isLoading,
2121
+ selectedToken,
2122
+ chainId,
2123
+ onRecipientChange,
2124
+ onAmountChange,
2125
+ onTokenSelect,
2126
+ onSend
2127
+ }) {
2128
+ var _a, _b, _c, _d;
2129
+ const { wallet } = useAvaCloudWallet();
2130
+ const { data: blockchainInfo } = useBlockchain((chainId == null ? void 0 : chainId.toString()) || "");
2131
+ const { data: tokenBalancesResponse } = useERC20Balances((wallet == null ? void 0 : wallet.address) || void 0, chainId == null ? void 0 : chainId.toString());
2132
+ const tokenBalances = tokenBalancesResponse;
2133
+ const { baseFee, priorityFee, totalFee, totalWithAmount, estimateGas, updateTotal } = useGasEstimation();
2134
+ const [addressError, setAddressError] = useState11(null);
2135
+ const handleRecipientChange = (value) => {
2136
+ if (value && !isAddress2(value)) {
2137
+ setAddressError("Invalid address format");
2138
+ } else {
2139
+ setAddressError(null);
2140
+ }
2141
+ onRecipientChange(value);
2142
+ };
2143
+ const handleAmountChange = (e) => {
2144
+ const value = e.target.value;
2145
+ if (/^\d*\.?\d{0,18}$/.test(value) || value === "") {
2146
+ onAmountChange(value);
2147
+ if (isValidAmount(value)) {
2148
+ updateTotal(value);
2149
+ }
2150
+ }
2151
+ };
2152
+ useEffect6(() => {
2153
+ if (!recipient || !isAddress2(recipient)) {
2154
+ return;
2155
+ }
2156
+ if (!isValidAmount(amount)) {
2157
+ return;
2158
+ }
2159
+ estimateGas(recipient, amount).catch(console.error);
2160
+ }, [recipient, amount, estimateGas]);
2161
+ const isInsufficientBalance = () => {
2162
+ if (!selectedToken || !amount || !isValidAmount(amount)) return false;
2163
+ const amountValue = Number(amount);
2164
+ const tokenBalance = Number(selectedToken.balance) / 10 ** selectedToken.decimals;
2165
+ if ("address" in selectedToken) {
2166
+ return amountValue > tokenBalance;
2167
+ }
2168
+ return amountValue + Number(totalFee || "0") > tokenBalance;
2169
+ };
2170
+ return /* @__PURE__ */ jsxs7(Box3, { sx: {
2171
+ display: "flex",
2172
+ flexDirection: "column",
2173
+ height: "100%",
2174
+ gap: 3,
2175
+ p: 2,
2176
+ width: "100%",
2177
+ maxWidth: "600px",
2178
+ margin: "0 auto"
2179
+ }, children: [
2180
+ /* @__PURE__ */ jsx11(
2181
+ Typography4,
2182
+ {
2183
+ variant: "h6",
2184
+ sx: {
2185
+ textAlign: "center",
2186
+ fontSize: "1.5rem",
2187
+ fontWeight: 500
2188
+ },
2189
+ children: "Send"
2190
+ }
2191
+ ),
2192
+ /* @__PURE__ */ jsxs7(Box3, { children: [
2193
+ /* @__PURE__ */ jsx11(Typography4, { variant: "body2", sx: { mb: 0.5, fontWeight: 500 }, children: "From" }),
2194
+ /* @__PURE__ */ jsxs7(
2195
+ Paper,
2196
+ {
2197
+ elevation: 0,
2198
+ sx: {
2199
+ display: "flex",
2200
+ flexDirection: "column",
2201
+ p: 1.5,
2202
+ gap: 1.5,
2203
+ border: "1px solid",
2204
+ borderColor: "divider",
2205
+ borderRadius: 1
2206
+ },
2207
+ children: [
2208
+ /* @__PURE__ */ jsxs7(Box3, { sx: { display: "flex", alignItems: "center", gap: 1.5 }, children: [
2209
+ /* @__PURE__ */ jsx11(
2210
+ Box3,
2211
+ {
2212
+ sx: {
2213
+ width: 40,
2214
+ height: 40,
2215
+ borderRadius: "50%",
2216
+ bgcolor: "#E84142",
2217
+ display: "flex",
2218
+ alignItems: "center",
2219
+ justifyContent: "center",
2220
+ overflow: "hidden"
2221
+ },
2222
+ children: (blockchainInfo == null ? void 0 : blockchainInfo.chainLogoUri) ? /* @__PURE__ */ jsx11(
2223
+ "img",
2224
+ {
2225
+ src: blockchainInfo.chainLogoUri,
2226
+ alt: blockchainInfo.chainName || "Network",
2227
+ style: { width: "100%", height: "100%", objectFit: "cover" }
2228
+ }
2229
+ ) : /* @__PURE__ */ jsx11(Icon, { icon: "cryptocurrency:avax", width: 24, height: 24, color: "white" })
2230
+ }
2231
+ ),
2232
+ /* @__PURE__ */ jsx11(Box3, { sx: { flex: 1, minWidth: 0 }, children: /* @__PURE__ */ jsx11(Typography4, { variant: "body1", sx: { fontWeight: 500 }, children: (blockchainInfo == null ? void 0 : blockchainInfo.chainName) || `Chain ${chainId}` }) })
2233
+ ] }),
2234
+ /* @__PURE__ */ jsxs7(
2235
+ Select,
2236
+ {
2237
+ size: "small",
2238
+ value: selectedToken ? JSON.stringify({
2239
+ symbol: selectedToken.symbol,
2240
+ balance: selectedToken.balance,
2241
+ decimals: selectedToken.decimals,
2242
+ address: "address" in selectedToken ? selectedToken.address : void 0
2243
+ }) : "",
2244
+ onChange: (e) => {
2245
+ const value = e.target.value;
2246
+ if (!value) return;
2247
+ const tokenData = JSON.parse(value);
2248
+ const token = tokenData.address ? tokenBalances.erc20TokenBalances.find((t) => t.address === tokenData.address) : tokenBalances.nativeTokenBalance;
2249
+ if (token) {
2250
+ onTokenSelect(token);
2251
+ }
2252
+ },
2253
+ sx: {
2254
+ ".MuiSelect-select": {
2255
+ display: "flex",
2256
+ alignItems: "center",
2257
+ gap: 1
2258
+ }
2259
+ },
2260
+ children: [
2261
+ (tokenBalances == null ? void 0 : tokenBalances.nativeTokenBalance) && /* @__PURE__ */ jsx11(MenuItem, { value: JSON.stringify({
2262
+ symbol: tokenBalances.nativeTokenBalance.symbol,
2263
+ balance: tokenBalances.nativeTokenBalance.balance,
2264
+ decimals: tokenBalances.nativeTokenBalance.decimals
2265
+ }), children: /* @__PURE__ */ jsxs7(Box3, { sx: { display: "flex", alignItems: "center", gap: 1, width: "100%" }, children: [
2266
+ /* @__PURE__ */ jsx11(
2267
+ TokenImage,
2268
+ {
2269
+ symbol: tokenBalances.nativeTokenBalance.symbol,
2270
+ logoUri: tokenBalances.nativeTokenBalance.logoUri,
2271
+ size: 24
2272
+ }
2273
+ ),
2274
+ /* @__PURE__ */ jsxs7(Box3, { sx: { flex: 1 }, children: [
2275
+ /* @__PURE__ */ jsx11(Typography4, { children: tokenBalances.nativeTokenBalance.symbol }),
2276
+ /* @__PURE__ */ jsxs7(Typography4, { variant: "body2", color: "text.secondary", children: [
2277
+ "Balance: ",
2278
+ Number(tokenBalances.nativeTokenBalance.balance || 0) / 10 ** tokenBalances.nativeTokenBalance.decimals
2279
+ ] })
2280
+ ] })
2281
+ ] }) }),
2282
+ (_a = tokenBalances == null ? void 0 : tokenBalances.erc20TokenBalances) == null ? void 0 : _a.map((token) => /* @__PURE__ */ jsx11(
2283
+ MenuItem,
2284
+ {
2285
+ value: JSON.stringify({
2286
+ symbol: token.symbol,
2287
+ balance: token.balance,
2288
+ decimals: token.decimals,
2289
+ address: token.address
2290
+ }),
2291
+ children: /* @__PURE__ */ jsxs7(Box3, { sx: { display: "flex", alignItems: "center", gap: 1, width: "100%" }, children: [
2292
+ /* @__PURE__ */ jsx11(
2293
+ TokenImage,
2294
+ {
2295
+ symbol: token.symbol,
2296
+ logoUri: token.logoUri,
2297
+ size: 24
2298
+ }
2299
+ ),
2300
+ /* @__PURE__ */ jsxs7(Box3, { sx: { flex: 1 }, children: [
2301
+ /* @__PURE__ */ jsx11(Typography4, { children: token.symbol }),
2302
+ /* @__PURE__ */ jsxs7(Typography4, { variant: "body2", color: "text.secondary", children: [
2303
+ "Balance: ",
2304
+ Number(token.balance) / 10 ** token.decimals
2305
+ ] })
2306
+ ] })
2307
+ ] })
2308
+ },
2309
+ token.address
2310
+ ))
2311
+ ]
2312
+ }
2313
+ )
2314
+ ]
2315
+ }
2316
+ )
2317
+ ] }),
2318
+ /* @__PURE__ */ jsxs7(Box3, { children: [
2319
+ /* @__PURE__ */ jsx11(Typography4, { variant: "body2", sx: { mb: 0.5, fontWeight: 500 }, children: "Send to" }),
2320
+ /* @__PURE__ */ jsx11(
2321
+ TextField2,
2322
+ {
2323
+ size: "small",
2324
+ fullWidth: true,
2325
+ placeholder: "Enter address",
2326
+ value: recipient,
2327
+ onChange: (e) => handleRecipientChange(e.target.value),
2328
+ error: !!error || !!addressError,
2329
+ helperText: addressError
2330
+ }
2331
+ )
2332
+ ] }),
2333
+ /* @__PURE__ */ jsxs7(Box3, { children: [
2334
+ /* @__PURE__ */ jsx11(Typography4, { variant: "body2", sx: { mb: 0.5, fontWeight: 500 }, children: "Amount" }),
2335
+ /* @__PURE__ */ jsx11(
2336
+ TextField2,
2337
+ {
2338
+ size: "small",
2339
+ fullWidth: true,
2340
+ type: "text",
2341
+ inputProps: {
2342
+ inputMode: "decimal",
2343
+ pattern: "^[0-9]*[.]?[0-9]*$"
2344
+ },
2345
+ placeholder: "0.00",
2346
+ value: amount,
2347
+ onChange: handleAmountChange,
2348
+ error: !!error
2349
+ }
2350
+ )
2351
+ ] }),
2352
+ /* @__PURE__ */ jsxs7(Box3, { children: [
2353
+ /* @__PURE__ */ jsxs7(Box3, { sx: { display: "flex", justifyContent: "space-between", mb: 1 }, children: [
2354
+ /* @__PURE__ */ jsx11(Typography4, { variant: "body2", color: "text.secondary", children: "Base fee" }),
2355
+ isValidAmount(amount) && recipient && isAddress2(recipient) && !isInsufficientBalance() ? /* @__PURE__ */ jsx11(Box3, { sx: { minWidth: 60, textAlign: "right" }, children: baseFee ? /* @__PURE__ */ jsxs7(Typography4, { variant: "body2", children: [
2356
+ baseFee,
2357
+ " ",
2358
+ ((_b = tokenBalances == null ? void 0 : tokenBalances.nativeTokenBalance) == null ? void 0 : _b.symbol) || "AVAX"
2359
+ ] }) : /* @__PURE__ */ jsx11(CircularProgress, { size: 16 }) }) : /* @__PURE__ */ jsx11(Typography4, { variant: "body2", children: "--" })
2360
+ ] }),
2361
+ /* @__PURE__ */ jsxs7(Box3, { sx: { display: "flex", justifyContent: "space-between", mb: 1 }, children: [
2362
+ /* @__PURE__ */ jsx11(Typography4, { variant: "body2", color: "text.secondary", children: "Priority fee" }),
2363
+ isValidAmount(amount) && recipient && isAddress2(recipient) && !isInsufficientBalance() ? /* @__PURE__ */ jsx11(Box3, { sx: { minWidth: 60, textAlign: "right" }, children: priorityFee ? /* @__PURE__ */ jsxs7(Typography4, { variant: "body2", children: [
2364
+ priorityFee,
2365
+ " ",
2366
+ ((_c = tokenBalances == null ? void 0 : tokenBalances.nativeTokenBalance) == null ? void 0 : _c.symbol) || "AVAX"
2367
+ ] }) : /* @__PURE__ */ jsx11(CircularProgress, { size: 16 }) }) : /* @__PURE__ */ jsx11(Typography4, { variant: "body2", children: "--" })
2368
+ ] }),
2369
+ /* @__PURE__ */ jsxs7(Box3, { sx: {
2370
+ display: "flex",
2371
+ justifyContent: "space-between",
2372
+ borderTop: "1px solid",
2373
+ borderColor: "divider",
2374
+ pt: 1,
2375
+ mt: 1
2376
+ }, children: [
2377
+ /* @__PURE__ */ jsx11(Typography4, { variant: "body2", sx: { fontWeight: 500 }, children: "Total" }),
2378
+ isValidAmount(amount) && recipient && isAddress2(recipient) && !isInsufficientBalance() ? /* @__PURE__ */ jsx11(Box3, { sx: { minWidth: 60, textAlign: "right" }, children: totalWithAmount ? /* @__PURE__ */ jsx11(Typography4, { variant: "body2", sx: { fontWeight: 500 }, children: selectedToken && "address" in selectedToken ? /* @__PURE__ */ jsxs7(Fragment3, { children: [
2379
+ amount,
2380
+ " ",
2381
+ selectedToken.symbol,
2382
+ " + ",
2383
+ totalFee,
2384
+ " ",
2385
+ ((_d = tokenBalances == null ? void 0 : tokenBalances.nativeTokenBalance) == null ? void 0 : _d.symbol) || "AVAX"
2386
+ ] }) : /* @__PURE__ */ jsxs7(Fragment3, { children: [
2387
+ totalWithAmount,
2388
+ " ",
2389
+ (selectedToken == null ? void 0 : selectedToken.symbol) || "AVAX"
2390
+ ] }) }) : /* @__PURE__ */ jsx11(CircularProgress, { size: 16 }) }) : /* @__PURE__ */ jsx11(Typography4, { variant: "body2", sx: { fontWeight: 500 }, children: "--" })
2391
+ ] })
2392
+ ] }),
2393
+ error && /* @__PURE__ */ jsx11(Alert, { severity: "error", children: error }),
2394
+ isValidAmount(amount) && selectedToken && isInsufficientBalance() && /* @__PURE__ */ jsx11(Alert, { severity: "error", children: selectedToken && "address" in selectedToken ? /* @__PURE__ */ jsxs7(Fragment3, { children: [
2395
+ "Insufficient token balance. Amount (",
2396
+ amount,
2397
+ " ",
2398
+ selectedToken.symbol,
2399
+ ") exceeds your balance (",
2400
+ (Number(selectedToken.balance) / 10 ** selectedToken.decimals).toFixed(4),
2401
+ " ",
2402
+ selectedToken.symbol,
2403
+ ")"
2404
+ ] }) : /* @__PURE__ */ jsxs7(Fragment3, { children: [
2405
+ "Insufficient balance. Total amount needed (",
2406
+ Number(amount) + Number(totalFee || "0"),
2407
+ " ",
2408
+ selectedToken.symbol,
2409
+ ") exceeds your balance (",
2410
+ (Number(selectedToken.balance) / 10 ** selectedToken.decimals).toFixed(4),
2411
+ " ",
2412
+ selectedToken.symbol,
2413
+ ")"
2414
+ ] }) }),
2415
+ /* @__PURE__ */ jsx11(Box3, { sx: { mt: "auto", display: "flex", justifyContent: "center" }, children: /* @__PURE__ */ jsx11(
2416
+ Button3,
2417
+ {
2418
+ variant: "contained",
2419
+ size: "large",
2420
+ onClick: onSend,
2421
+ disabled: isLoading || !recipient || !!addressError || !isValidAmount(amount) || !selectedToken || isInsufficientBalance(),
2422
+ fullWidth: true,
2423
+ sx: {
2424
+ borderRadius: "9999px",
2425
+ height: "48px"
2426
+ },
2427
+ children: isLoading ? "Sending..." : "Send"
2428
+ }
2429
+ ) }),
2430
+ /* @__PURE__ */ jsx11(PoweredByAvaCloud, {})
2431
+ ] });
2432
+ }
2433
+ function SuccessView({
2434
+ onDone,
2435
+ txHash,
2436
+ recipient,
2437
+ amount,
2438
+ currencySymbol,
2439
+ actualBaseFee,
2440
+ actualPriorityFee,
2441
+ actualTotalFee,
2442
+ nativeTokenSymbol
2443
+ }) {
2444
+ var _a, _b;
2445
+ const { blockchain } = useGlacier();
2446
+ const { wallet } = useAvaCloudWallet();
2447
+ const explorerUrl = (blockchain == null ? void 0 : blockchain.explorerUrl) ? `${blockchain.explorerUrl.replace(/\/$/, "")}/tx/${txHash}` : `https://subnets.avax.network/c-chain/tx/${txHash}`;
2448
+ const isERC20 = currencySymbol !== nativeTokenSymbol;
2449
+ return /* @__PURE__ */ jsxs7(Box3, { sx: {
2450
+ display: "flex",
2451
+ flexDirection: "column",
2452
+ height: "100%",
2453
+ p: 3,
2454
+ gap: 3,
2455
+ width: "100%",
2456
+ maxWidth: "600px",
2457
+ margin: "0 auto"
2458
+ }, children: [
2459
+ /* @__PURE__ */ jsxs7(Box3, { sx: { display: "flex", alignItems: "center", gap: 2 }, children: [
2460
+ /* @__PURE__ */ jsx11(Icon, { icon: "mdi:check-circle", color: "#4CAF50", width: 24, height: 24 }),
2461
+ /* @__PURE__ */ jsx11(Typography4, { variant: "h6", children: "Successfully sent" })
2462
+ ] }),
2463
+ /* @__PURE__ */ jsxs7(Box3, { children: [
2464
+ /* @__PURE__ */ jsx11(Typography4, { variant: "body2", sx: { mb: 1, fontWeight: 500 }, children: "From" }),
2465
+ /* @__PURE__ */ jsxs7(Box3, { sx: {
2466
+ display: "flex",
2467
+ alignItems: "center",
2468
+ gap: 1.5
2469
+ }, children: [
2470
+ /* @__PURE__ */ jsx11(
2471
+ Box3,
2472
+ {
2473
+ sx: {
2474
+ width: 40,
2475
+ height: 40,
2476
+ borderRadius: "50%",
2477
+ bgcolor: "#E84142",
2478
+ display: "flex",
2479
+ alignItems: "center",
2480
+ justifyContent: "center",
2481
+ overflow: "hidden"
2482
+ },
2483
+ children: (blockchain == null ? void 0 : blockchain.chainLogoUri) ? /* @__PURE__ */ jsx11(
2484
+ "img",
2485
+ {
2486
+ src: blockchain.chainLogoUri,
2487
+ alt: blockchain.chainName || "Network",
2488
+ style: { width: "100%", height: "100%", objectFit: "cover" }
2489
+ }
2490
+ ) : /* @__PURE__ */ jsx11(Icon, { icon: "cryptocurrency:avax", width: 24, height: 24, color: "white" })
2491
+ }
2492
+ ),
2493
+ /* @__PURE__ */ jsxs7(Box3, { sx: { flex: 1 }, children: [
2494
+ /* @__PURE__ */ jsx11(Typography4, { variant: "body1", sx: { fontWeight: 500 }, children: (blockchain == null ? void 0 : blockchain.chainName) || "Avalanche C-Chain" }),
2495
+ /* @__PURE__ */ jsxs7(Box3, { sx: { display: "flex", alignItems: "center", gap: 1 }, children: [
2496
+ /* @__PURE__ */ jsxs7(Typography4, { variant: "body2", sx: { color: "text.secondary" }, children: [
2497
+ (_a = wallet.address) == null ? void 0 : _a.slice(0, 6),
2498
+ "...",
2499
+ (_b = wallet.address) == null ? void 0 : _b.slice(-4)
2500
+ ] }),
2501
+ /* @__PURE__ */ jsx11(
2502
+ IconButton3,
2503
+ {
2504
+ size: "small",
2505
+ onClick: () => navigator.clipboard.writeText(wallet.address || ""),
2506
+ sx: { p: 0 },
2507
+ children: /* @__PURE__ */ jsx11(Icon, { icon: "mdi:content-copy", width: 16, height: 16 })
2508
+ }
2509
+ )
2510
+ ] })
2511
+ ] })
2512
+ ] })
2513
+ ] }),
2514
+ /* @__PURE__ */ jsxs7(Box3, { children: [
2515
+ /* @__PURE__ */ jsx11(Typography4, { variant: "body2", sx: { mb: 1, fontWeight: 500 }, children: "To" }),
2516
+ /* @__PURE__ */ jsxs7(Box3, { sx: { display: "flex", alignItems: "center", gap: 1 }, children: [
2517
+ /* @__PURE__ */ jsxs7(Typography4, { sx: { wordBreak: "break-all" }, children: [
2518
+ recipient.slice(0, 6),
2519
+ "...",
2520
+ recipient.slice(-4)
2521
+ ] }),
2522
+ /* @__PURE__ */ jsx11(
2523
+ IconButton3,
2524
+ {
2525
+ size: "small",
2526
+ onClick: () => navigator.clipboard.writeText(recipient),
2527
+ sx: { p: 0 },
2528
+ children: /* @__PURE__ */ jsx11(Icon, { icon: "mdi:content-copy", width: 16, height: 16 })
2529
+ }
2530
+ )
2531
+ ] })
2532
+ ] }),
2533
+ /* @__PURE__ */ jsxs7(Box3, { children: [
2534
+ /* @__PURE__ */ jsx11(Typography4, { variant: "body2", sx: { mb: 1, fontWeight: 500 }, children: "Amount" }),
2535
+ /* @__PURE__ */ jsxs7(Typography4, { children: [
2536
+ amount,
2537
+ " ",
2538
+ currencySymbol
2539
+ ] })
2540
+ ] }),
2541
+ actualTotalFee && /* @__PURE__ */ jsxs7(Box3, { children: [
2542
+ /* @__PURE__ */ jsx11(Typography4, { variant: "body2", sx: { mb: 1, fontWeight: 500 }, children: "Transaction Fees" }),
2543
+ actualBaseFee && /* @__PURE__ */ jsxs7(Box3, { sx: { display: "flex", justifyContent: "space-between", mb: 0.5 }, children: [
2544
+ /* @__PURE__ */ jsx11(Typography4, { variant: "body2", color: "text.secondary", children: "Base fee" }),
2545
+ /* @__PURE__ */ jsxs7(Typography4, { variant: "body2", children: [
2546
+ actualBaseFee,
2547
+ " ",
2548
+ nativeTokenSymbol
2549
+ ] })
2550
+ ] }),
2551
+ actualPriorityFee && /* @__PURE__ */ jsxs7(Box3, { sx: { display: "flex", justifyContent: "space-between", mb: 0.5 }, children: [
2552
+ /* @__PURE__ */ jsx11(Typography4, { variant: "body2", color: "text.secondary", children: "Priority fee" }),
2553
+ /* @__PURE__ */ jsxs7(Typography4, { variant: "body2", children: [
2554
+ actualPriorityFee,
2555
+ " ",
2556
+ nativeTokenSymbol
2557
+ ] })
2558
+ ] }),
2559
+ /* @__PURE__ */ jsxs7(Box3, { sx: {
2560
+ display: "flex",
2561
+ justifyContent: "space-between",
2562
+ borderTop: "1px solid",
2563
+ borderColor: "divider",
2564
+ pt: 1,
2565
+ mt: 1
2566
+ }, children: [
2567
+ /* @__PURE__ */ jsx11(Typography4, { variant: "body2", sx: { fontWeight: 500 }, children: "Total" }),
2568
+ /* @__PURE__ */ jsx11(Typography4, { variant: "body2", sx: { fontWeight: 500 }, children: isERC20 ? /* @__PURE__ */ jsxs7(Fragment3, { children: [
2569
+ amount,
2570
+ " ",
2571
+ currencySymbol,
2572
+ " + ",
2573
+ actualTotalFee,
2574
+ " ",
2575
+ nativeTokenSymbol
2576
+ ] }) : /* @__PURE__ */ jsxs7(Fragment3, { children: [
2577
+ (Number(amount) + Number(actualTotalFee)).toFixed(6),
2578
+ " ",
2579
+ currencySymbol
2580
+ ] }) })
2581
+ ] })
2582
+ ] }),
2583
+ /* @__PURE__ */ jsxs7(Box3, { children: [
2584
+ /* @__PURE__ */ jsx11(Typography4, { variant: "body2", sx: { mb: 1, fontWeight: 500 }, children: "Transaction hash" }),
2585
+ /* @__PURE__ */ jsx11(Box3, { sx: { display: "flex", alignItems: "center", gap: 1 }, children: /* @__PURE__ */ jsxs7(
2586
+ Box3,
2587
+ {
2588
+ component: "a",
2589
+ href: explorerUrl,
2590
+ target: "_blank",
2591
+ rel: "noopener noreferrer",
2592
+ sx: {
2593
+ textDecoration: "none",
2594
+ color: "text.primary",
2595
+ wordBreak: "break-all",
2596
+ display: "flex",
2597
+ alignItems: "center",
2598
+ gap: 0.5,
2599
+ "&:hover": {
2600
+ textDecoration: "underline",
2601
+ color: "primary.main"
2602
+ }
2603
+ },
2604
+ children: [
2605
+ /* @__PURE__ */ jsxs7(Typography4, { children: [
2606
+ txHash.slice(0, 6),
2607
+ "...",
2608
+ txHash.slice(-4)
2609
+ ] }),
2610
+ /* @__PURE__ */ jsx11(Icon, { icon: "mdi:open-in-new", width: 16, height: 16 })
2611
+ ]
2612
+ }
2613
+ ) })
2614
+ ] }),
2615
+ /* @__PURE__ */ jsx11(
2616
+ Button3,
2617
+ {
2618
+ fullWidth: true,
2619
+ variant: "contained",
2620
+ onClick: onDone,
2621
+ sx: {
2622
+ borderRadius: "9999px",
2623
+ height: "48px",
2624
+ mt: "auto"
2625
+ },
2626
+ children: "Done"
2627
+ }
2628
+ )
2629
+ ] });
2630
+ }
2631
+ function FailureView({ recipient, amount, currencySymbol, error, onDone }) {
2632
+ return /* @__PURE__ */ jsxs7(Box3, { sx: { p: 2 }, children: [
2633
+ /* @__PURE__ */ jsx11(Typography4, { variant: "h6", sx: { mb: 3 }, children: "Transaction Failed" }),
2634
+ /* @__PURE__ */ jsxs7(Box3, { sx: { mb: 3 }, children: [
2635
+ /* @__PURE__ */ jsx11(Typography4, { variant: "body2", color: "text.secondary", children: "Amount" }),
2636
+ /* @__PURE__ */ jsxs7(Typography4, { children: [
2637
+ amount,
2638
+ " ",
2639
+ currencySymbol
2640
+ ] }),
2641
+ /* @__PURE__ */ jsx11(Typography4, { variant: "body2", color: "text.secondary", sx: { mt: 2 }, children: "Recipient" }),
2642
+ /* @__PURE__ */ jsx11(Typography4, { sx: { wordBreak: "break-all" }, children: recipient })
2643
+ ] }),
2644
+ error && /* @__PURE__ */ jsx11(Alert, { severity: "error", sx: { mb: 3 }, children: error }),
2645
+ /* @__PURE__ */ jsx11(
2646
+ Button3,
2647
+ {
2648
+ fullWidth: true,
2649
+ variant: "contained",
2650
+ onClick: onDone,
2651
+ color: "error",
2652
+ children: "Try Again"
2653
+ }
2654
+ )
2655
+ ] });
2656
+ }
2657
+ function SendView({ onBack, onViewStateChange, selectedToken: initialToken }) {
2658
+ var _a;
2659
+ const { chainId } = useChainId();
2660
+ const [recipient, setRecipient] = useState11("");
2661
+ const [amount, setAmount] = useState11("");
2662
+ const [selectedToken, setSelectedToken] = useState11(initialToken);
2663
+ const { transfer, transferERC20, error, isLoading, txHash, viewState, reset, actualBaseFee, actualPriorityFee, actualTotalFee } = useTransferTokens();
2664
+ const { data: blockchainInfo } = useBlockchain((chainId == null ? void 0 : chainId.toString()) || "");
2665
+ useEffect6(() => {
2666
+ onViewStateChange == null ? void 0 : onViewStateChange(viewState);
2667
+ }, [viewState, onViewStateChange]);
2668
+ const handleSend = async () => {
2669
+ try {
2670
+ if (!recipient || !amount || !selectedToken) {
2671
+ throw new Error("Please fill in all fields");
2672
+ }
2673
+ if (!isAddress2(recipient)) {
2674
+ throw new Error("Invalid recipient address");
2675
+ }
2676
+ if (!/^\d*\.?\d{0,18}$/.test(amount)) {
2677
+ throw new Error("Invalid amount format");
2678
+ }
2679
+ const amountValue = Number.parseFloat(amount);
2680
+ if (Number.isNaN(amountValue) || amountValue <= 0) {
2681
+ throw new Error("Please enter a valid amount");
2682
+ }
2683
+ const formattedAmount = amountValue.toLocaleString("fullwide", { useGrouping: false });
2684
+ if ("address" in selectedToken) {
2685
+ await transferERC20(selectedToken.address, recipient, formattedAmount, selectedToken.decimals);
2686
+ } else {
2687
+ await transfer(recipient, formattedAmount);
2688
+ }
2689
+ } catch (err) {
2690
+ console.error("Send failed:", err);
2691
+ }
2692
+ };
2693
+ const handleDone = () => {
2694
+ setRecipient("");
2695
+ setAmount("");
2696
+ setSelectedToken(void 0);
2697
+ reset();
2698
+ onBack();
2699
+ };
2700
+ if (viewState === "loading") {
2701
+ return /* @__PURE__ */ jsx11(LoadingView, {});
2702
+ }
2703
+ if (viewState === "success" && txHash) {
2704
+ return /* @__PURE__ */ jsx11(
2705
+ SuccessView,
2706
+ {
2707
+ onDone: handleDone,
2708
+ txHash,
2709
+ recipient,
2710
+ amount,
2711
+ currencySymbol: (selectedToken == null ? void 0 : selectedToken.symbol) || "AVAX",
2712
+ actualBaseFee,
2713
+ actualPriorityFee,
2714
+ actualTotalFee,
2715
+ nativeTokenSymbol: ((_a = blockchainInfo == null ? void 0 : blockchainInfo.networkToken) == null ? void 0 : _a.symbol) || "AVAX"
2716
+ }
2717
+ );
2718
+ }
2719
+ if (viewState === "failure") {
2720
+ return /* @__PURE__ */ jsx11(
2721
+ FailureView,
2722
+ {
2723
+ recipient,
2724
+ amount,
2725
+ currencySymbol: (selectedToken == null ? void 0 : selectedToken.symbol) || "AVAX",
2726
+ error,
2727
+ onDone: handleDone
2728
+ }
2729
+ );
2730
+ }
2731
+ return /* @__PURE__ */ jsx11(
2732
+ SendFormView,
2733
+ {
2734
+ recipient,
2735
+ amount,
2736
+ error,
2737
+ isLoading,
2738
+ selectedToken,
2739
+ chainId,
2740
+ onRecipientChange: setRecipient,
2741
+ onAmountChange: setAmount,
2742
+ onTokenSelect: setSelectedToken,
2743
+ onSend: handleSend,
2744
+ onBack
2745
+ }
2746
+ );
2747
+ }
2748
+
2749
+ // src/components/ReceiveView.tsx
2750
+ import { useState as useState12 } from "react";
2751
+ import { QRCodeSVG } from "qrcode.react";
2752
+ import {
2753
+ Box as Box4,
2754
+ Typography as Typography5,
2755
+ IconButton as IconButton4,
2756
+ CopyIcon
2757
+ } from "@avalabs/core-k2-components";
2758
+ import { jsx as jsx12, jsxs as jsxs8 } from "react/jsx-runtime";
2759
+ function ReceiveView(_props) {
2760
+ const { wallet } = useAvaCloudWallet();
2761
+ const { chainId } = useChainId();
2762
+ const [_copied, setCopied] = useState12(false);
2763
+ if (!wallet.address) {
2764
+ return /* @__PURE__ */ jsx12(Box4, { sx: { p: 2 }, children: /* @__PURE__ */ jsx12(Typography5, { color: "text.secondary", children: "No wallet address available" }) });
2765
+ }
2766
+ const handleCopy = () => {
2767
+ if (wallet.address) {
2768
+ navigator.clipboard.writeText(wallet.address);
2769
+ setCopied(true);
2770
+ setTimeout(() => setCopied(false), 2e3);
2771
+ }
2772
+ };
2773
+ return /* @__PURE__ */ jsxs8(Box4, { sx: {
2774
+ display: "flex",
2775
+ flexDirection: "column",
2776
+ gap: 2,
2777
+ width: "100%",
2778
+ p: 2
2779
+ }, children: [
2780
+ /* @__PURE__ */ jsx12(
2781
+ Typography5,
2782
+ {
2783
+ sx: {
2784
+ color: "#000",
2785
+ fontSize: "14px",
2786
+ fontWeight: 500,
2787
+ lineHeight: "20px"
2788
+ },
2789
+ children: "Address"
2790
+ }
2791
+ ),
2792
+ /* @__PURE__ */ jsxs8(Box4, { sx: {
2793
+ display: "flex",
2794
+ alignItems: "center",
2795
+ gap: 1,
2796
+ width: "100%"
2797
+ }, children: [
2798
+ /* @__PURE__ */ jsx12(
2799
+ Typography5,
2800
+ {
2801
+ sx: {
2802
+ flex: 1,
2803
+ fontFamily: "monospace",
2804
+ fontSize: "14px",
2805
+ color: "#000",
2806
+ overflow: "hidden",
2807
+ textOverflow: "ellipsis"
2808
+ },
2809
+ children: wallet.address
2810
+ }
2811
+ ),
2812
+ /* @__PURE__ */ jsx12(IconButton4, { onClick: handleCopy, size: "small", children: /* @__PURE__ */ jsx12(CopyIcon, {}) })
2813
+ ] }),
2814
+ /* @__PURE__ */ jsx12(Box4, { sx: {
2815
+ display: "flex",
2816
+ justifyContent: "center",
2817
+ alignItems: "center",
2818
+ width: "100%",
2819
+ aspectRatio: "1",
2820
+ p: 2,
2821
+ background: "#FFF",
2822
+ borderRadius: "8px",
2823
+ border: "1px solid rgba(0, 0, 0, 0.12)"
2824
+ }, children: /* @__PURE__ */ jsx12(
2825
+ QRCodeSVG,
2826
+ {
2827
+ value: wallet.address ? `ethereum:${wallet.address}@${chainId}` : "",
2828
+ level: "H",
2829
+ includeMargin: false,
2830
+ size: 200
2831
+ }
2832
+ ) }),
2833
+ /* @__PURE__ */ jsx12(Box4, { sx: { mt: "auto" }, children: /* @__PURE__ */ jsx12(PoweredByAvaCloud, {}) })
2834
+ ] });
2835
+ }
2836
+
2837
+ // src/components/ExportView.tsx
2838
+ import { useState as useState13 } from "react";
2839
+ import {
2840
+ Box as Box5,
2841
+ Typography as Typography6,
2842
+ Button as Button4,
2843
+ IconButton as IconButton5,
2844
+ CopyIcon as CopyIcon2,
2845
+ Alert as Alert2,
2846
+ AlertTitle
2847
+ } from "@avalabs/core-k2-components";
2848
+ import { jsx as jsx13, jsxs as jsxs9 } from "react/jsx-runtime";
2849
+ function ExportView({ onBack }) {
2850
+ const { wallet, iframe } = useAvaCloudWallet();
2851
+ const [showKey, setShowKey] = useState13(false);
2852
+ const [copied, setCopied] = useState13(false);
2853
+ const [privateKey, setPrivateKey] = useState13(null);
2854
+ const [error, setError] = useState13(null);
2855
+ const handleExport = async () => {
2856
+ if (!(iframe == null ? void 0 : iframe.contentWindow)) return;
2857
+ try {
2858
+ iframe.contentWindow.postMessage({
2859
+ type: "EXPORT_PRIVATE_KEY",
2860
+ payload: {
2861
+ address: wallet.address
2862
+ }
2863
+ }, "*");
2864
+ const handleResponse = (event) => {
2865
+ if (event.data.type === "EXPORT_PRIVATE_KEY_RESPONSE") {
2866
+ setPrivateKey(event.data.payload.privateKey);
2867
+ setShowKey(true);
2868
+ window.removeEventListener("message", handleResponse);
2869
+ }
2870
+ };
2871
+ window.addEventListener("message", handleResponse);
2872
+ } catch (err) {
2873
+ console.error("Export failed:", err);
2874
+ setError("Failed to export private key. Please try again.");
2875
+ }
2876
+ };
2877
+ const handleCopy = () => {
2878
+ if (privateKey) {
2879
+ navigator.clipboard.writeText(privateKey);
2880
+ setCopied(true);
2881
+ setTimeout(() => setCopied(false), 2e3);
2882
+ }
2883
+ };
2884
+ return /* @__PURE__ */ jsxs9(Box5, { sx: { p: 2 }, children: [
2885
+ /* @__PURE__ */ jsx13(Typography6, { variant: "h6", sx: { mb: 3 }, children: "Export Private Key" }),
2886
+ /* @__PURE__ */ jsxs9(Alert2, { severity: "warning", sx: { mb: 3 }, children: [
2887
+ /* @__PURE__ */ jsx13(AlertTitle, { children: "Warning" }),
2888
+ "Never share your private key with anyone. Anyone with your private key can access your funds."
2889
+ ] }),
2890
+ !showKey ? /* @__PURE__ */ jsx13(
2891
+ Button4,
2892
+ {
2893
+ fullWidth: true,
2894
+ variant: "contained",
2895
+ color: "warning",
2896
+ onClick: handleExport,
2897
+ sx: { mb: 2 },
2898
+ children: "Show Private Key"
2899
+ }
2900
+ ) : /* @__PURE__ */ jsx13(Box5, { sx: { mb: 3 }, children: /* @__PURE__ */ jsxs9(Box5, { sx: {
2901
+ display: "flex",
2902
+ alignItems: "center",
2903
+ gap: 1,
2904
+ p: 2,
2905
+ bgcolor: "background.paper",
2906
+ borderRadius: 1,
2907
+ boxShadow: 1,
2908
+ mb: 2
2909
+ }, children: [
2910
+ /* @__PURE__ */ jsx13(
2911
+ Typography6,
2912
+ {
2913
+ variant: "body2",
2914
+ sx: {
2915
+ fontFamily: "monospace",
2916
+ overflow: "hidden",
2917
+ textOverflow: "ellipsis",
2918
+ whiteSpace: "nowrap",
2919
+ flex: 1
2920
+ },
2921
+ children: privateKey
2922
+ }
2923
+ ),
2924
+ /* @__PURE__ */ jsx13(
2925
+ IconButton5,
2926
+ {
2927
+ onClick: handleCopy,
2928
+ size: "small",
2929
+ color: copied ? "success" : "default",
2930
+ children: /* @__PURE__ */ jsx13(CopyIcon2, {})
2931
+ }
2932
+ )
2933
+ ] }) }),
2934
+ error && /* @__PURE__ */ jsx13(Typography6, { color: "error", sx: { mb: 2 }, children: error }),
2935
+ /* @__PURE__ */ jsx13(
2936
+ Button4,
2937
+ {
2938
+ fullWidth: true,
2939
+ variant: "outlined",
2940
+ onClick: onBack,
2941
+ children: "Back"
2942
+ }
2943
+ )
2944
+ ] });
2945
+ }
2946
+
2947
+ // src/components/TokensView.tsx
2948
+ import { useState as useState14 } from "react";
2949
+ import {
2950
+ Box as Box8,
2951
+ Tabs,
2952
+ Tab,
2953
+ useTheme as useTheme2
2954
+ } from "@avalabs/core-k2-components";
2955
+
2956
+ // src/components/FungibleList.tsx
2957
+ import {
2958
+ Box as Box6,
2959
+ Typography as Typography7,
2960
+ IconButton as IconButton6,
2961
+ CopyIcon as CopyIcon3
2962
+ } from "@avalabs/core-k2-components";
2963
+ import { jsx as jsx14, jsxs as jsxs10 } from "react/jsx-runtime";
2964
+ function FungibleList({ onSend, onCopyAddress }) {
2965
+ var _a, _b, _c, _d;
2966
+ const { wallet } = useAvaCloudWallet();
2967
+ const { chainId } = useChainId();
2968
+ const { data: tokenBalances, isLoading: isLoadingERC20 } = useERC20Balances(
2969
+ (wallet == null ? void 0 : wallet.address) || void 0,
2970
+ chainId == null ? void 0 : chainId.toString()
2971
+ );
2972
+ if (isLoadingERC20) {
2973
+ return /* @__PURE__ */ jsx14(Box6, { sx: {
2974
+ display: "flex",
2975
+ justifyContent: "center",
2976
+ alignItems: "center",
2977
+ height: "100%",
2978
+ minHeight: "200px"
2979
+ }, children: /* @__PURE__ */ jsx14(LoadingAnimation, { size: 80, message: "Loading tokens..." }) });
2980
+ }
2981
+ if (!(tokenBalances == null ? void 0 : tokenBalances.nativeTokenBalance) && !((_a = tokenBalances == null ? void 0 : tokenBalances.erc20TokenBalances) == null ? void 0 : _a.length)) {
2982
+ return /* @__PURE__ */ jsx14(Box6, { sx: {
2983
+ p: 3,
2984
+ textAlign: "center",
2985
+ color: "text.secondary",
2986
+ bgcolor: "background.paper",
2987
+ borderRadius: "8px",
2988
+ border: "1px dashed rgba(0, 0, 0, 0.12)"
2989
+ }, children: /* @__PURE__ */ jsx14(Typography7, { children: "No tokens found" }) });
2990
+ }
2991
+ return /* @__PURE__ */ jsxs10(Box6, { sx: {
2992
+ display: "flex",
2993
+ flexDirection: "column",
2994
+ height: "100%",
2995
+ overflow: "auto",
2996
+ py: 1,
2997
+ px: 1
2998
+ }, children: [
2999
+ (tokenBalances == null ? void 0 : tokenBalances.nativeTokenBalance) && /* @__PURE__ */ jsxs10(
3000
+ Box6,
3001
+ {
3002
+ onClick: () => onSend == null ? void 0 : onSend(tokenBalances.nativeTokenBalance),
3003
+ sx: {
3004
+ display: "flex",
3005
+ alignItems: "center",
3006
+ py: 1.5,
3007
+ px: 1,
3008
+ cursor: onSend ? "pointer" : "default",
3009
+ "&:hover": onSend ? {
3010
+ bgcolor: "action.hover",
3011
+ borderRadius: 1
3012
+ } : {},
3013
+ borderRadius: 1,
3014
+ mb: 1
3015
+ },
3016
+ children: [
3017
+ /* @__PURE__ */ jsx14(Box6, { sx: { mr: 2 }, children: /* @__PURE__ */ jsx14(
3018
+ TokenImage,
3019
+ {
3020
+ symbol: tokenBalances.nativeTokenBalance.symbol,
3021
+ logoUri: tokenBalances.nativeTokenBalance.logoUri,
3022
+ size: 32
3023
+ }
3024
+ ) }),
3025
+ /* @__PURE__ */ jsxs10(Box6, { sx: { flex: 1 }, children: [
3026
+ /* @__PURE__ */ jsx14(Typography7, { sx: { fontWeight: 500, fontSize: "14px" }, children: tokenBalances.nativeTokenBalance.symbol }),
3027
+ /* @__PURE__ */ jsxs10(Box6, { sx: { display: "flex", alignItems: "center", gap: 1 }, children: [
3028
+ /* @__PURE__ */ jsxs10(
3029
+ Typography7,
3030
+ {
3031
+ variant: "body2",
3032
+ sx: {
3033
+ color: "text.secondary",
3034
+ fontSize: "12px"
3035
+ },
3036
+ children: [
3037
+ (_b = wallet.address) == null ? void 0 : _b.slice(0, 6),
3038
+ "...",
3039
+ (_c = wallet.address) == null ? void 0 : _c.slice(-4)
3040
+ ]
3041
+ }
3042
+ ),
3043
+ /* @__PURE__ */ jsx14(
3044
+ IconButton6,
3045
+ {
3046
+ size: "small",
3047
+ onClick: (e) => {
3048
+ e.stopPropagation();
3049
+ onCopyAddress(wallet.address || "");
3050
+ },
3051
+ sx: {
3052
+ padding: 0,
3053
+ color: "text.secondary",
3054
+ "&:hover": {
3055
+ color: "primary.main"
3056
+ }
3057
+ },
3058
+ children: /* @__PURE__ */ jsx14(CopyIcon3, { fontSize: "small" })
3059
+ }
3060
+ )
3061
+ ] })
3062
+ ] }),
3063
+ /* @__PURE__ */ jsx14(Box6, { sx: { textAlign: "right" }, children: /* @__PURE__ */ jsx14(Typography7, { sx: { fontWeight: 500 }, children: Number(Number(tokenBalances.nativeTokenBalance.balance) / 10 ** tokenBalances.nativeTokenBalance.decimals).toLocaleString(void 0, {
3064
+ minimumFractionDigits: 0,
3065
+ maximumFractionDigits: 6
3066
+ }) }) })
3067
+ ]
3068
+ }
3069
+ ),
3070
+ (_d = tokenBalances == null ? void 0 : tokenBalances.erc20TokenBalances) == null ? void 0 : _d.map((token) => /* @__PURE__ */ jsxs10(
3071
+ Box6,
3072
+ {
3073
+ onClick: () => onSend == null ? void 0 : onSend(token),
3074
+ sx: {
3075
+ display: "flex",
3076
+ alignItems: "center",
3077
+ py: 1.5,
3078
+ px: 1,
3079
+ cursor: onSend ? "pointer" : "default",
3080
+ "&:hover": onSend ? {
3081
+ bgcolor: "action.hover",
3082
+ borderRadius: 1
3083
+ } : {},
3084
+ borderRadius: 1
3085
+ },
3086
+ children: [
3087
+ /* @__PURE__ */ jsx14(Box6, { sx: { mr: 2 }, children: /* @__PURE__ */ jsx14(
3088
+ TokenImage,
3089
+ {
3090
+ symbol: token.symbol,
3091
+ logoUri: token.logoUri,
3092
+ size: 32
3093
+ }
3094
+ ) }),
3095
+ /* @__PURE__ */ jsxs10(Box6, { sx: { flex: 1 }, children: [
3096
+ /* @__PURE__ */ jsxs10(Box6, { sx: { display: "flex", alignItems: "center", gap: 1 }, children: [
3097
+ /* @__PURE__ */ jsx14(Typography7, { sx: { fontWeight: 500 }, children: token.symbol }),
3098
+ /* @__PURE__ */ jsx14(
3099
+ Typography7,
3100
+ {
3101
+ variant: "body2",
3102
+ sx: {
3103
+ color: "text.secondary",
3104
+ fontSize: "12px"
3105
+ },
3106
+ children: token.name
3107
+ }
3108
+ )
3109
+ ] }),
3110
+ /* @__PURE__ */ jsxs10(Box6, { sx: { display: "flex", alignItems: "center", gap: 1 }, children: [
3111
+ /* @__PURE__ */ jsxs10(
3112
+ Typography7,
3113
+ {
3114
+ variant: "body2",
3115
+ sx: {
3116
+ color: "text.secondary",
3117
+ fontSize: "12px"
3118
+ },
3119
+ children: [
3120
+ token.address.slice(0, 6),
3121
+ "...",
3122
+ token.address.slice(-4)
3123
+ ]
3124
+ }
3125
+ ),
3126
+ /* @__PURE__ */ jsx14(
3127
+ IconButton6,
3128
+ {
3129
+ size: "small",
3130
+ onClick: (e) => {
3131
+ e.stopPropagation();
3132
+ onCopyAddress(token.address);
3133
+ },
3134
+ sx: {
3135
+ padding: 0,
3136
+ color: "text.secondary",
3137
+ "&:hover": {
3138
+ color: "primary.main"
3139
+ }
3140
+ },
3141
+ children: /* @__PURE__ */ jsx14(CopyIcon3, { fontSize: "small" })
3142
+ }
3143
+ )
3144
+ ] })
3145
+ ] }),
3146
+ /* @__PURE__ */ jsx14(Box6, { sx: { textAlign: "right" }, children: /* @__PURE__ */ jsx14(Typography7, { sx: { fontWeight: 500 }, children: Number(Number(token.balance) / 10 ** token.decimals).toLocaleString(void 0, {
3147
+ minimumFractionDigits: 0,
3148
+ maximumFractionDigits: 6
3149
+ }) }) })
3150
+ ]
3151
+ },
3152
+ token.address
3153
+ ))
3154
+ ] });
3155
+ }
3156
+
3157
+ // src/components/NonFungibleList.tsx
3158
+ import {
3159
+ Box as Box7,
3160
+ Typography as Typography8
3161
+ } from "@avalabs/core-k2-components";
3162
+ import { jsx as jsx15, jsxs as jsxs11 } from "react/jsx-runtime";
3163
+ function convertIpfsUrl(url) {
3164
+ if (!url) return "/placeholder-nft.png";
3165
+ if (url.startsWith("ipfs://")) {
3166
+ const ipfsHash = url.replace("ipfs://", "");
3167
+ return `https://ipfs.io/ipfs/${ipfsHash}`;
3168
+ }
3169
+ return url;
3170
+ }
3171
+ function NonFungibleList() {
3172
+ const { wallet } = useAvaCloudWallet();
3173
+ const { chainId } = useChainId();
3174
+ const { data: blockchain } = useBlockchain(chainId == null ? void 0 : chainId.toString());
3175
+ const { data: erc721Response, isLoading: isLoadingERC721 } = useERC721Balances(
3176
+ (wallet == null ? void 0 : wallet.address) || void 0,
3177
+ chainId == null ? void 0 : chainId.toString()
3178
+ );
3179
+ const { data: erc1155Response, isLoading: isLoadingERC1155 } = useERC1155Balances(
3180
+ (wallet == null ? void 0 : wallet.address) || void 0,
3181
+ chainId == null ? void 0 : chainId.toString()
3182
+ );
3183
+ const isLoading = isLoadingERC721 || isLoadingERC1155;
3184
+ const getExplorerUrl = (contractAddress) => {
3185
+ if (!(blockchain == null ? void 0 : blockchain.explorerUrl)) return `https://subnets.avax.network/c-chain/address/${contractAddress}`;
3186
+ return `${blockchain.explorerUrl.replace(/\/$/, "")}/address/${contractAddress}`;
3187
+ };
3188
+ if (isLoading) {
3189
+ return /* @__PURE__ */ jsx15(Box7, { sx: {
3190
+ display: "flex",
3191
+ justifyContent: "center",
3192
+ alignItems: "center",
3193
+ height: "100%",
3194
+ minHeight: "200px"
3195
+ }, children: /* @__PURE__ */ jsx15(LoadingAnimation, { size: 80, message: "Loading NFTs..." }) });
3196
+ }
3197
+ const erc721Tokens = (erc721Response == null ? void 0 : erc721Response.erc721TokenBalances) || [];
3198
+ const erc1155Tokens = (erc1155Response == null ? void 0 : erc1155Response.erc1155TokenBalances) || [];
3199
+ if (!erc721Tokens.length && !erc1155Tokens.length) {
3200
+ return /* @__PURE__ */ jsx15(Box7, { sx: {
3201
+ p: 3,
3202
+ textAlign: "center",
3203
+ color: "text.secondary",
3204
+ bgcolor: "background.paper",
3205
+ borderRadius: "8px",
3206
+ border: "1px dashed rgba(0, 0, 0, 0.12)"
3207
+ }, children: /* @__PURE__ */ jsx15(Typography8, { children: "No NFTs found" }) });
3208
+ }
3209
+ return /* @__PURE__ */ jsx15(Box7, { sx: {
3210
+ display: "flex",
3211
+ flexDirection: "column",
3212
+ height: "100%",
3213
+ overflow: "auto"
3214
+ }, children: /* @__PURE__ */ jsxs11(Box7, { sx: {
3215
+ display: "grid",
3216
+ gridTemplateColumns: "repeat(auto-fill, minmax(150px, 1fr))",
3217
+ gap: 2,
3218
+ p: 2
3219
+ }, children: [
3220
+ erc721Tokens.map((nft) => {
3221
+ var _a, _b, _c;
3222
+ return /* @__PURE__ */ jsxs11(
3223
+ Box7,
3224
+ {
3225
+ component: "a",
3226
+ href: getExplorerUrl(nft.address),
3227
+ target: "_blank",
3228
+ rel: "noopener noreferrer",
3229
+ sx: {
3230
+ bgcolor: "background.paper",
3231
+ borderRadius: 1,
3232
+ overflow: "hidden",
3233
+ boxShadow: 1,
3234
+ textDecoration: "none",
3235
+ color: "inherit",
3236
+ display: "block",
3237
+ transition: "transform 0.2s ease-in-out, box-shadow 0.2s ease-in-out",
3238
+ "&:hover": {
3239
+ transform: "translateY(-2px)",
3240
+ boxShadow: 2
3241
+ }
3242
+ },
3243
+ children: [
3244
+ /* @__PURE__ */ jsx15(Box7, { sx: {
3245
+ position: "relative",
3246
+ paddingTop: "100%",
3247
+ bgcolor: "action.hover"
3248
+ }, children: /* @__PURE__ */ jsx15(
3249
+ Box7,
3250
+ {
3251
+ component: "img",
3252
+ src: convertIpfsUrl((_a = nft.metadata) == null ? void 0 : _a.imageUri),
3253
+ alt: ((_b = nft.metadata) == null ? void 0 : _b.name) || nft.name,
3254
+ sx: {
3255
+ position: "absolute",
3256
+ top: 0,
3257
+ left: 0,
3258
+ width: "100%",
3259
+ height: "100%",
3260
+ objectFit: "cover"
3261
+ },
3262
+ onError: (e) => {
3263
+ const target = e.currentTarget;
3264
+ target.src = "/placeholder-nft.png";
3265
+ }
3266
+ }
3267
+ ) }),
3268
+ /* @__PURE__ */ jsxs11(Box7, { sx: { p: 1 }, children: [
3269
+ /* @__PURE__ */ jsx15(Typography8, { sx: { fontWeight: 500, fontSize: "14px" }, children: ((_c = nft.metadata) == null ? void 0 : _c.name) || nft.name }),
3270
+ /* @__PURE__ */ jsxs11(Typography8, { sx: { color: "text.secondary", fontSize: "12px" }, children: [
3271
+ "#",
3272
+ nft.tokenId
3273
+ ] })
3274
+ ] })
3275
+ ]
3276
+ },
3277
+ `${nft.address}-${nft.tokenId}`
3278
+ );
3279
+ }),
3280
+ erc1155Tokens.map((nft) => {
3281
+ var _a, _b, _c;
3282
+ return /* @__PURE__ */ jsxs11(
3283
+ Box7,
3284
+ {
3285
+ component: "a",
3286
+ href: getExplorerUrl(nft.address),
3287
+ target: "_blank",
3288
+ rel: "noopener noreferrer",
3289
+ sx: {
3290
+ bgcolor: "background.paper",
3291
+ borderRadius: 1,
3292
+ overflow: "hidden",
3293
+ boxShadow: 1,
3294
+ textDecoration: "none",
3295
+ color: "inherit",
3296
+ display: "block",
3297
+ transition: "transform 0.2s ease-in-out, box-shadow 0.2s ease-in-out",
3298
+ "&:hover": {
3299
+ transform: "translateY(-2px)",
3300
+ boxShadow: 2
3301
+ }
3302
+ },
3303
+ children: [
3304
+ /* @__PURE__ */ jsx15(Box7, { sx: {
3305
+ position: "relative",
3306
+ paddingTop: "100%",
3307
+ bgcolor: "action.hover"
3308
+ }, children: /* @__PURE__ */ jsx15(
3309
+ Box7,
3310
+ {
3311
+ component: "img",
3312
+ src: convertIpfsUrl((_a = nft.metadata) == null ? void 0 : _a.imageUri),
3313
+ alt: ((_b = nft.metadata) == null ? void 0 : _b.name) || nft.name,
3314
+ sx: {
3315
+ position: "absolute",
3316
+ top: 0,
3317
+ left: 0,
3318
+ width: "100%",
3319
+ height: "100%",
3320
+ objectFit: "cover"
3321
+ },
3322
+ onError: (e) => {
3323
+ const target = e.currentTarget;
3324
+ target.src = "/placeholder-nft.png";
3325
+ }
3326
+ }
3327
+ ) }),
3328
+ /* @__PURE__ */ jsxs11(Box7, { sx: { p: 1 }, children: [
3329
+ /* @__PURE__ */ jsx15(Typography8, { sx: { fontWeight: 500, fontSize: "14px" }, children: ((_c = nft.metadata) == null ? void 0 : _c.name) || nft.name }),
3330
+ /* @__PURE__ */ jsxs11(Typography8, { sx: { color: "text.secondary", fontSize: "12px" }, children: [
3331
+ "#",
3332
+ nft.tokenId,
3333
+ " ",
3334
+ nft.balance ? `\xD7 ${nft.balance}` : ""
3335
+ ] })
3336
+ ] })
3337
+ ]
3338
+ },
3339
+ `${nft.address}-${nft.tokenId}`
3340
+ );
3341
+ })
3342
+ ] }) });
3343
+ }
3344
+
3345
+ // src/components/TokensView.tsx
3346
+ import { jsx as jsx16, jsxs as jsxs12 } from "react/jsx-runtime";
3347
+ function TokensView({ onSend }) {
3348
+ const [activeTab, setActiveTab] = useState14("tokens");
3349
+ const theme = useTheme2();
3350
+ const handleCopyAddress = (address) => {
3351
+ navigator.clipboard.writeText(address);
3352
+ };
3353
+ const handleTabChange = (_, value) => {
3354
+ setActiveTab(value);
3355
+ };
3356
+ return /* @__PURE__ */ jsxs12(Box8, { sx: {
3357
+ display: "flex",
3358
+ flexDirection: "column",
3359
+ width: "100%",
3360
+ height: "100%",
3361
+ overflow: "hidden"
3362
+ }, children: [
3363
+ /* @__PURE__ */ jsx16(Box8, { sx: { mb: 2, display: "flex", justifyContent: "center" }, children: /* @__PURE__ */ jsxs12(
3364
+ Tabs,
3365
+ {
3366
+ value: activeTab,
3367
+ onChange: handleTabChange,
3368
+ isContained: true,
3369
+ centered: true,
3370
+ sx: {
3371
+ minHeight: 40,
3372
+ background: theme.palette.mode === "dark" ? "rgba(255, 255, 255, 0.05)" : "#F5F5F5",
3373
+ borderRadius: 999,
3374
+ padding: "4px",
3375
+ "& .MuiTabs-indicator": {
3376
+ backgroundColor: theme.palette.mode === "dark" ? "#000000" : "#000000",
3377
+ borderRadius: 999,
3378
+ height: "100%",
3379
+ zIndex: 1
3380
+ },
3381
+ "& .MuiTab-root": {
3382
+ minHeight: 32,
3383
+ borderRadius: 999,
3384
+ color: theme.palette.mode === "dark" ? "rgba(255, 255, 255, 0.5)" : "#666666",
3385
+ zIndex: 2,
3386
+ "&.Mui-selected": {
3387
+ color: "#FFFFFF"
3388
+ }
3389
+ }
3390
+ },
3391
+ children: [
3392
+ /* @__PURE__ */ jsx16(
3393
+ Tab,
3394
+ {
3395
+ value: "tokens",
3396
+ label: "Tokens"
3397
+ }
3398
+ ),
3399
+ /* @__PURE__ */ jsx16(
3400
+ Tab,
3401
+ {
3402
+ value: "nfts",
3403
+ label: "NFTs"
3404
+ }
3405
+ )
3406
+ ]
3407
+ }
3408
+ ) }),
3409
+ /* @__PURE__ */ jsx16(Box8, { sx: {
3410
+ flex: 1,
3411
+ minHeight: 0,
3412
+ position: "relative",
3413
+ maxHeight: "500px",
3414
+ overflow: "auto",
3415
+ "&::-webkit-scrollbar": {
3416
+ width: "8px"
3417
+ },
3418
+ "&::-webkit-scrollbar-track": {
3419
+ background: "transparent"
3420
+ }
3421
+ }, children: activeTab === "tokens" ? /* @__PURE__ */ jsx16(
3422
+ FungibleList,
3423
+ {
3424
+ onSend,
3425
+ onCopyAddress: handleCopyAddress
3426
+ }
3427
+ ) : /* @__PURE__ */ jsx16(NonFungibleList, {}) })
3428
+ ] });
3429
+ }
3430
+
3431
+ // src/components/WalletHeader.tsx
3432
+ import {
3433
+ Box as Box9,
3434
+ Typography as Typography9,
3435
+ IconButton as IconButton7,
3436
+ LogOutIcon
3437
+ } from "@avalabs/core-k2-components";
3438
+ import { Icon as Icon2 } from "@iconify/react";
3439
+ import { jsx as jsx17, jsxs as jsxs13 } from "react/jsx-runtime";
3440
+ function WalletHeader({ onClose }) {
3441
+ const { user, logout } = useAvaCloudWallet();
3442
+ if (!user) return null;
3443
+ return /* @__PURE__ */ jsxs13(Box9, { sx: {
3444
+ display: "grid",
3445
+ gridTemplateColumns: "repeat(3, 1fr)",
3446
+ alignItems: "center",
3447
+ width: "100%",
3448
+ mb: 1
3449
+ }, children: [
3450
+ /* @__PURE__ */ jsx17(Box9, { sx: {
3451
+ justifySelf: "start",
3452
+ display: "flex",
3453
+ alignItems: "center",
3454
+ gap: 1
3455
+ }, children: /* @__PURE__ */ jsx17(
3456
+ IconButton7,
3457
+ {
3458
+ onClick: logout,
3459
+ size: "small",
3460
+ sx: {
3461
+ color: "text.secondary",
3462
+ "&:hover": {
3463
+ color: "text.primary"
3464
+ }
3465
+ },
3466
+ children: /* @__PURE__ */ jsx17(LogOutIcon, {})
3467
+ }
3468
+ ) }),
3469
+ /* @__PURE__ */ jsx17(Box9, { sx: { justifySelf: "center" }, children: /* @__PURE__ */ jsx17(
3470
+ Typography9,
3471
+ {
3472
+ variant: "body2",
3473
+ sx: {
3474
+ color: "text.secondary",
3475
+ overflow: "hidden",
3476
+ textOverflow: "ellipsis",
3477
+ whiteSpace: "nowrap"
3478
+ },
3479
+ children: user.displayName
3480
+ }
3481
+ ) }),
3482
+ /* @__PURE__ */ jsx17(Box9, { sx: { justifySelf: "end" }, children: onClose && /* @__PURE__ */ jsx17(
3483
+ IconButton7,
3484
+ {
3485
+ onClick: onClose,
3486
+ sx: { color: "text.secondary" },
3487
+ children: /* @__PURE__ */ jsx17(Icon2, { icon: "ph:x-bold", width: 20, height: 20 })
3488
+ }
3489
+ ) })
3490
+ ] });
3491
+ }
3492
+
3493
+ // src/components/Buttons/SendButton.tsx
3494
+ import { memo } from "react";
3495
+ import {
3496
+ Button as Button5,
3497
+ ArrowUpIcon
3498
+ } from "@avalabs/core-k2-components";
3499
+ import { jsx as jsx18, jsxs as jsxs14 } from "react/jsx-runtime";
3500
+ function SendButtonComponent({
3501
+ label = "Send",
3502
+ variant = "text",
3503
+ color = "primary",
3504
+ ...props
3505
+ }) {
3506
+ return /* @__PURE__ */ jsxs14(
3507
+ Button5,
3508
+ {
3509
+ variant,
3510
+ color,
3511
+ ...props,
3512
+ sx: {
3513
+ display: "flex",
3514
+ width: "128px",
3515
+ height: "96px",
3516
+ flexDirection: "column",
3517
+ justifyContent: "center",
3518
+ alignItems: "center",
3519
+ gap: "8px",
3520
+ flexShrink: 0,
3521
+ borderRadius: "16px",
3522
+ background: "rgba(0, 0, 0, 0.02)",
3523
+ boxShadow: "2px 1px 4px 0px rgba(0, 0, 0, 0.25)",
3524
+ "& .MuiButton-startIcon": {
3525
+ margin: 0
3526
+ },
3527
+ ...props.sx
3528
+ },
3529
+ children: [
3530
+ /* @__PURE__ */ jsx18(ArrowUpIcon, {}),
3531
+ label
3532
+ ]
3533
+ }
3534
+ );
3535
+ }
3536
+ var SendButton = memo(SendButtonComponent);
3537
+
3538
+ // src/components/Buttons/ReceiveButton.tsx
3539
+ import { memo as memo2 } from "react";
3540
+ import {
3541
+ Button as Button6,
3542
+ ArrowDownIcon
3543
+ } from "@avalabs/core-k2-components";
3544
+ import { jsx as jsx19, jsxs as jsxs15 } from "react/jsx-runtime";
3545
+ function ReceiveButtonComponent({
3546
+ label = "Receive",
3547
+ variant = "text",
3548
+ color = "primary",
3549
+ ...props
3550
+ }) {
3551
+ return /* @__PURE__ */ jsxs15(
3552
+ Button6,
3553
+ {
3554
+ variant,
3555
+ color,
3556
+ ...props,
3557
+ sx: {
3558
+ display: "flex",
3559
+ width: "128px",
3560
+ height: "96px",
3561
+ flexDirection: "column",
3562
+ justifyContent: "center",
3563
+ alignItems: "center",
3564
+ gap: "8px",
3565
+ flexShrink: 0,
3566
+ borderRadius: "16px",
3567
+ background: "rgba(0, 0, 0, 0.02)",
3568
+ boxShadow: "2px 1px 4px 0px rgba(0, 0, 0, 0.25)",
3569
+ "& .MuiButton-startIcon": {
3570
+ margin: 0
3571
+ },
3572
+ ...props.sx
3573
+ },
3574
+ children: [
3575
+ /* @__PURE__ */ jsx19(ArrowDownIcon, {}),
3576
+ label
3577
+ ]
3578
+ }
3579
+ );
3580
+ }
3581
+ var ReceiveButton = memo2(ReceiveButtonComponent);
3582
+
3583
+ // src/components/WalletCard.tsx
3584
+ import { Fragment as Fragment4, jsx as jsx20, jsxs as jsxs16 } from "react/jsx-runtime";
3585
+ function WalletCard({ onClose }) {
3586
+ const { user, wallet, isAuthenticated } = useAvaCloudWallet();
3587
+ const { balance, isLoadingBalance, currencySymbol, blockchain } = useGlacier();
3588
+ const [currentView, setCurrentView] = useState15("main");
3589
+ const [selectedToken, setSelectedToken] = useState15();
3590
+ const theme = useTheme3();
3591
+ if (!isAuthenticated || !user) return null;
3592
+ const handleCopy = (e) => {
3593
+ e.stopPropagation();
3594
+ if (wallet.address) {
3595
+ navigator.clipboard.writeText(wallet.address);
3596
+ }
3597
+ };
3598
+ const handleTokenSend = (token) => {
3599
+ setSelectedToken(token);
3600
+ setCurrentView("send");
3601
+ };
3602
+ const renderMainView = () => {
3603
+ var _a;
3604
+ return /* @__PURE__ */ jsxs16(Fragment4, { children: [
3605
+ /* @__PURE__ */ jsx20(Box10, { sx: { textAlign: "center", mb: 3 }, children: /* @__PURE__ */ jsx20(AvaCloudIcon, { width: 64, height: 64, foregroundFill: theme.palette.primary.main }) }),
3606
+ /* @__PURE__ */ jsxs16(Box10, { sx: { textAlign: "center", mb: 4, width: "100%" }, children: [
3607
+ /* @__PURE__ */ jsx20(
3608
+ Typography10,
3609
+ {
3610
+ variant: "h4",
3611
+ sx: {
3612
+ mb: 2,
3613
+ fontWeight: 700,
3614
+ fontSize: "34px",
3615
+ lineHeight: "44px"
3616
+ },
3617
+ children: isLoadingBalance ? /* @__PURE__ */ jsx20(CircularProgress2, { size: 24, sx: { mx: 1 } }) : /* @__PURE__ */ jsxs16(Fragment4, { children: [
3618
+ Number(balance || 0).toLocaleString(void 0, {
3619
+ minimumFractionDigits: 0,
3620
+ maximumFractionDigits: 4
3621
+ }),
3622
+ /* @__PURE__ */ jsx20(
3623
+ Box10,
3624
+ {
3625
+ component: "span",
3626
+ sx: {
3627
+ display: "inline-flex",
3628
+ alignItems: "center",
3629
+ ml: 1,
3630
+ verticalAlign: "middle",
3631
+ "& img": {
3632
+ boxShadow: "0px 2px 4px rgba(0, 0, 0, 0.1)",
3633
+ border: "1px solid rgba(0, 0, 0, 0.05)",
3634
+ transition: "transform 0.2s ease-in-out",
3635
+ "&:hover": {
3636
+ transform: "scale(1.05)"
3637
+ }
3638
+ }
3639
+ },
3640
+ children: /* @__PURE__ */ jsx20(
3641
+ TokenImage,
3642
+ {
3643
+ symbol: currencySymbol,
3644
+ logoUri: (_a = blockchain == null ? void 0 : blockchain.networkToken) == null ? void 0 : _a.logoUri,
3645
+ size: 28
3646
+ }
3647
+ )
3648
+ }
3649
+ )
3650
+ ] })
3651
+ }
3652
+ ),
3653
+ /* @__PURE__ */ jsxs16(Box10, { sx: {
3654
+ display: "flex",
3655
+ alignItems: "center",
3656
+ justifyContent: "center",
3657
+ gap: 1
3658
+ }, children: [
3659
+ /* @__PURE__ */ jsx20(
3660
+ Typography10,
3661
+ {
3662
+ variant: "body2",
3663
+ sx: {
3664
+ overflow: "hidden",
3665
+ textOverflow: "ellipsis",
3666
+ whiteSpace: "nowrap"
3667
+ },
3668
+ children: wallet.address ? `${wallet.address.slice(0, 6)}...${wallet.address.slice(-4)}` : ""
3669
+ }
3670
+ ),
3671
+ /* @__PURE__ */ jsx20(
3672
+ IconButton8,
3673
+ {
3674
+ size: "small",
3675
+ onClick: handleCopy,
3676
+ sx: { color: "text.secondary" },
3677
+ children: /* @__PURE__ */ jsx20(CopyIcon4, {})
3678
+ }
3679
+ )
3680
+ ] })
3681
+ ] }),
3682
+ /* @__PURE__ */ jsxs16(Box10, { sx: { display: "flex", gap: 2, width: "100%", mb: 3, justifyContent: "center" }, children: [
3683
+ /* @__PURE__ */ jsx20(SendButton, { onClick: () => setCurrentView("send") }),
3684
+ /* @__PURE__ */ jsx20(ReceiveButton, { onClick: () => setCurrentView("receive") })
3685
+ ] }),
3686
+ /* @__PURE__ */ jsx20(
3687
+ Button7,
3688
+ {
3689
+ variant: "text",
3690
+ onClick: () => setCurrentView("tokens"),
3691
+ sx: {
3692
+ width: "100%",
3693
+ mb: 3,
3694
+ color: "text.secondary",
3695
+ "&:hover": {
3696
+ color: "primary.main",
3697
+ background: "transparent"
3698
+ }
3699
+ },
3700
+ children: "View All Assets \u2192"
3701
+ }
3702
+ ),
3703
+ /* @__PURE__ */ jsx20(Box10, { sx: { width: "100%" }, children: /* @__PURE__ */ jsx20(PoweredByAvaCloud, {}) })
3704
+ ] });
3705
+ };
3706
+ return /* @__PURE__ */ jsx20(
3707
+ Dialog4,
3708
+ {
3709
+ open: true,
3710
+ PaperProps: {
3711
+ sx: {
3712
+ width: "439px",
3713
+ maxWidth: "90vw",
3714
+ minHeight: "500px",
3715
+ maxHeight: "85vh",
3716
+ borderRadius: "16px",
3717
+ background: theme.palette.mode === "dark" ? theme.palette.background.paper : "#FCFCFC",
3718
+ boxShadow: theme.palette.mode === "dark" ? "0px 4px 6px 0px rgba(0, 0, 0, 0.3), 0px 4px 15px 0px rgba(0, 0, 0, 0.25)" : "0px 4px 6px 0px rgba(0, 0, 0, 0.16), 0px 4px 15px 0px rgba(0, 0, 0, 0.15)",
3719
+ backdropFilter: "blur(50px)",
3720
+ fontFamily: "Inter",
3721
+ display: "flex",
3722
+ flexDirection: "column"
3723
+ }
3724
+ },
3725
+ children: /* @__PURE__ */ jsxs16(
3726
+ DialogContent4,
3727
+ {
3728
+ sx: {
3729
+ display: "flex",
3730
+ flexDirection: "column",
3731
+ alignItems: "center",
3732
+ gap: "24px",
3733
+ padding: "24px 32px 12px 32px",
3734
+ overflow: "hidden",
3735
+ "&.MuiDialogContent-root": {
3736
+ padding: "24px 32px 12px 32px",
3737
+ fontFamily: "Inter"
3738
+ }
3739
+ },
3740
+ children: [
3741
+ /* @__PURE__ */ jsx20(WalletHeader, { onClose }),
3742
+ /* @__PURE__ */ jsx20(
3743
+ Box10,
3744
+ {
3745
+ sx: {
3746
+ flex: 1,
3747
+ width: "100%",
3748
+ minHeight: 0,
3749
+ overflowY: currentView === "tokens" ? "hidden" : "auto"
3750
+ },
3751
+ children: currentView === "main" ? renderMainView() : currentView === "receive" ? /* @__PURE__ */ jsx20(ReceiveView, { onBack: () => setCurrentView("main") }) : currentView === "send" ? /* @__PURE__ */ jsx20(
3752
+ SendView,
3753
+ {
3754
+ onBack: () => setCurrentView("main"),
3755
+ selectedToken
3756
+ }
3757
+ ) : currentView === "tokens" ? /* @__PURE__ */ jsx20(
3758
+ TokensView,
3759
+ {
3760
+ onBack: () => setCurrentView("main"),
3761
+ onSend: handleTokenSend
3762
+ }
3763
+ ) : /* @__PURE__ */ jsx20(ExportView, { onBack: () => setCurrentView("main") })
3764
+ }
3765
+ )
3766
+ ]
3767
+ }
3768
+ )
3769
+ }
3770
+ );
3771
+ }
3772
+
3773
+ // src/components/WalletButton.tsx
3774
+ import { Fragment as Fragment5, jsx as jsx21, jsxs as jsxs17 } from "react/jsx-runtime";
3775
+ function WalletButton({
3776
+ label = "Connect Wallet",
3777
+ className = "",
3778
+ ...props
3779
+ }) {
3780
+ const { isLoading, isAuthenticated, wallet } = useAvaCloudWallet();
3781
+ const [isModalOpen, setIsModalOpen] = useState16(false);
3782
+ const theme = useTheme4();
3783
+ const { isDarkMode } = useThemeMode();
3784
+ const handleOpen = () => setIsModalOpen(true);
3785
+ const handleClose = () => setIsModalOpen(false);
3786
+ const handleCopy = (e) => {
3787
+ e.stopPropagation();
3788
+ if (wallet.address) {
3789
+ navigator.clipboard.writeText(wallet.address);
3790
+ }
3791
+ };
3792
+ if (!isAuthenticated) {
3793
+ return /* @__PURE__ */ jsxs17(Fragment5, { children: [
3794
+ /* @__PURE__ */ jsx21(
3795
+ Button8,
3796
+ {
3797
+ onClick: handleOpen,
3798
+ disabled: isLoading,
3799
+ variant: "contained",
3800
+ color: "primary",
3801
+ className,
3802
+ sx: {
3803
+ fontFamily: "Inter"
3804
+ },
3805
+ ...props,
3806
+ children: isLoading ? "Loading..." : label
3807
+ }
3808
+ ),
3809
+ /* @__PURE__ */ jsx21(
3810
+ LoginModal,
3811
+ {
3812
+ open: isModalOpen,
3813
+ onClose: handleClose
3814
+ }
3815
+ )
3816
+ ] });
3817
+ }
3818
+ const displayAddress = wallet.address ? `${wallet.address.slice(0, 6)}...${wallet.address.slice(-4)}` : "";
3819
+ return /* @__PURE__ */ jsxs17(Fragment5, { children: [
3820
+ /* @__PURE__ */ jsxs17(
3821
+ Button8,
3822
+ {
3823
+ onClick: handleOpen,
3824
+ variant: "outlined",
3825
+ sx: {
3826
+ display: "inline-flex",
3827
+ padding: "12px 16px",
3828
+ alignItems: "center",
3829
+ gap: "16px",
3830
+ borderRadius: "16px",
3831
+ background: isDarkMode ? theme.palette.background.paper : "#FCFCFC",
3832
+ boxShadow: isDarkMode ? "0px 4px 6px 0px rgba(0, 0, 0, 0.3), 0px 4px 15px 0px rgba(0, 0, 0, 0.25)" : "0px 4px 6px 0px rgba(0, 0, 0, 0.16), 0px 4px 15px 0px rgba(0, 0, 0, 0.15)",
3833
+ backdropFilter: "blur(50px)",
3834
+ fontFamily: "Inter",
3835
+ border: `1px solid ${isDarkMode ? "rgba(255, 255, 255, 0.12)" : "rgba(0, 0, 0, 0.12)"}`,
3836
+ transition: "all 0.2s ease-in-out",
3837
+ "&:hover": {
3838
+ background: isDarkMode ? theme.palette.background.paper : "#FCFCFC",
3839
+ borderColor: theme.palette.primary.main,
3840
+ transform: "translateY(-1px)",
3841
+ boxShadow: isDarkMode ? "0px 6px 8px 0px rgba(0, 0, 0, 0.35), 0px 6px 20px 0px rgba(0, 0, 0, 0.3)" : "0px 6px 8px 0px rgba(0, 0, 0, 0.18), 0px 6px 20px 0px rgba(0, 0, 0, 0.17)"
3842
+ },
3843
+ "&:active": {
3844
+ transform: "translateY(0px)",
3845
+ background: isDarkMode ? theme.palette.background.paper : "#FCFCFC",
3846
+ boxShadow: isDarkMode ? "0px 2px 4px 0px rgba(0, 0, 0, 0.3), 0px 2px 10px 0px rgba(0, 0, 0, 0.25)" : "0px 2px 4px 0px rgba(0, 0, 0, 0.14), 0px 2px 10px 0px rgba(0, 0, 0, 0.13)"
3847
+ }
3848
+ },
3849
+ className,
3850
+ ...props,
3851
+ children: [
3852
+ /* @__PURE__ */ jsx21(AvaCloudIcon2, { width: 24, height: 24, foregroundFill: theme.palette.primary.main }),
3853
+ /* @__PURE__ */ jsxs17(Box11, { sx: { display: "flex", alignItems: "center", gap: 1 }, children: [
3854
+ /* @__PURE__ */ jsx21(
3855
+ Typography11,
3856
+ {
3857
+ variant: "body2",
3858
+ sx: {
3859
+ fontFamily: "Inter",
3860
+ fontWeight: 500,
3861
+ color: theme.palette.text.primary
3862
+ },
3863
+ children: displayAddress
3864
+ }
3865
+ ),
3866
+ /* @__PURE__ */ jsx21(
3867
+ IconButton9,
3868
+ {
3869
+ size: "small",
3870
+ onClick: handleCopy,
3871
+ sx: { color: "text.secondary" },
3872
+ children: /* @__PURE__ */ jsx21(CopyIcon5, {})
3873
+ }
3874
+ )
3875
+ ] })
3876
+ ]
3877
+ }
3878
+ ),
3879
+ isModalOpen && /* @__PURE__ */ jsx21(WalletCard, { onClose: handleClose })
3880
+ ] });
3881
+ }
3882
+
3883
+ // src/components/WalletDisplay.tsx
3884
+ import { useState as useState17 } from "react";
3885
+ import { jsx as jsx22, jsxs as jsxs18 } from "react/jsx-runtime";
3886
+ function WalletDisplay({
3887
+ className = "",
3888
+ truncateAddress = true,
3889
+ showAddAccount = true
3890
+ }) {
3891
+ const { wallet, addAccount, isAuthenticated } = useAvaCloudWallet();
3892
+ const [isAdding, setIsAdding] = useState17(false);
3893
+ const [accountIndex, setAccountIndex] = useState17(0);
3894
+ if (!isAuthenticated || !wallet.address) {
3895
+ return null;
3896
+ }
3897
+ const displayAddress = truncateAddress ? `${wallet.address.slice(0, 6)}...${wallet.address.slice(-4)}` : wallet.address;
3898
+ const handleAddAccount = async () => {
3899
+ try {
3900
+ setIsAdding(true);
3901
+ await addAccount(accountIndex);
3902
+ setAccountIndex((prev) => prev + 1);
3903
+ } catch (error) {
3904
+ console.error("Failed to add account:", error);
3905
+ } finally {
3906
+ setIsAdding(false);
3907
+ }
3908
+ };
3909
+ return /* @__PURE__ */ jsxs18("div", { className: `space-y-4 ${className}`, children: [
3910
+ /* @__PURE__ */ jsxs18("div", { className: "bg-gray-50 rounded-lg p-4", children: [
3911
+ /* @__PURE__ */ jsx22("div", { className: "text-sm text-gray-500", children: "Wallet Address" }),
3912
+ /* @__PURE__ */ jsx22("div", { className: "mt-1 font-mono text-sm break-all", children: displayAddress })
3913
+ ] }),
3914
+ showAddAccount && /* @__PURE__ */ jsx22(
3915
+ "button",
3916
+ {
3917
+ type: "button",
3918
+ onClick: handleAddAccount,
3919
+ disabled: isAdding,
3920
+ className: "w-full inline-flex items-center justify-center px-4 py-2 border border-transparent text-sm font-medium rounded-md text-white bg-indigo-600 hover:bg-indigo-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500 disabled:opacity-50 disabled:cursor-not-allowed",
3921
+ children: isAdding ? "Adding Account..." : "Add Account"
3922
+ }
3923
+ )
3924
+ ] });
3925
+ }
3926
+
3927
+ // src/components/UserProfile.tsx
3928
+ import { jsx as jsx23, jsxs as jsxs19 } from "react/jsx-runtime";
3929
+ function UserProfile({
3930
+ className = "",
3931
+ showLogout = true
3932
+ }) {
3933
+ const { user, logout, isAuthenticated } = useAvaCloudWallet();
3934
+ if (!isAuthenticated || !user) {
3935
+ return null;
3936
+ }
3937
+ return /* @__PURE__ */ jsx23("div", { className: `space-y-4 ${className}`, children: /* @__PURE__ */ jsxs19("div", { className: "bg-white shadow rounded-lg p-6", children: [
3938
+ /* @__PURE__ */ jsx23("div", { className: "px-4 py-5 sm:px-6", children: /* @__PURE__ */ jsx23("h3", { className: "text-lg font-medium leading-6 text-gray-900", children: "User Profile" }) }),
3939
+ /* @__PURE__ */ jsx23("div", { className: "border-t border-gray-200", children: /* @__PURE__ */ jsxs19("dl", { children: [
3940
+ /* @__PURE__ */ jsxs19("div", { className: "bg-gray-50 px-4 py-5 sm:grid sm:grid-cols-3 sm:gap-4 sm:px-6", children: [
3941
+ /* @__PURE__ */ jsx23("dt", { className: "text-sm font-medium text-gray-500", children: "Display Name" }),
3942
+ /* @__PURE__ */ jsx23("dd", { className: "mt-1 text-sm text-gray-900 sm:col-span-2", children: user.displayName })
3943
+ ] }),
3944
+ user.email && /* @__PURE__ */ jsxs19("div", { className: "bg-white px-4 py-5 sm:grid sm:grid-cols-3 sm:gap-4 sm:px-6", children: [
3945
+ /* @__PURE__ */ jsx23("dt", { className: "text-sm font-medium text-gray-500", children: "Email address" }),
3946
+ /* @__PURE__ */ jsx23("dd", { className: "mt-1 text-sm text-gray-900 sm:col-span-2", children: user.email })
3947
+ ] }),
3948
+ user.configured_mfa && user.configured_mfa.length > 0 && /* @__PURE__ */ jsxs19("div", { children: [
3949
+ /* @__PURE__ */ jsx23("div", { className: "text-sm font-medium text-gray-500", children: "MFA Methods" }),
3950
+ /* @__PURE__ */ jsx23("div", { className: "mt-1 space-y-1", children: user.configured_mfa.map((method) => {
3951
+ const mfaMethod = typeof method === "string" ? { type: method } : method;
3952
+ return /* @__PURE__ */ jsx23(
3953
+ "div",
3954
+ {
3955
+ className: "text-sm text-gray-900",
3956
+ children: mfaMethod.type === "totp" ? "Authenticator App" : mfaMethod.name
3957
+ },
3958
+ mfaMethod.type === "fido" ? mfaMethod.id : `totp-${mfaMethod.type}`
3959
+ );
3960
+ }) })
3961
+ ] })
3962
+ ] }) }),
3963
+ showLogout && /* @__PURE__ */ jsx23("div", { className: "mt-6", children: /* @__PURE__ */ jsx23(
3964
+ "button",
3965
+ {
3966
+ type: "button",
3967
+ onClick: logout,
3968
+ className: "w-full inline-flex items-center justify-center px-4 py-2 border border-transparent text-sm font-medium rounded-md text-white bg-red-600 hover:bg-red-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-red-500",
3969
+ children: "Sign Out"
3970
+ }
3971
+ ) })
3972
+ ] }) });
3973
+ }
3974
+
3975
+ // src/hooks/useSignMessage.ts
3976
+ import { useCallback as useCallback8, useState as useState18 } from "react";
3977
+ import { Secp256k1 as Secp256k12 } from "@cubist-labs/cubesigner-sdk";
3978
+ function useSignMessage() {
3979
+ const [state, setState] = useState18({
3980
+ isLoading: false,
3981
+ error: null,
3982
+ signature: null
3983
+ });
3984
+ const { wallet, cubistClient } = useAvaCloudWallet();
3985
+ const reset = useCallback8(() => {
3986
+ setState({
3987
+ isLoading: false,
3988
+ error: null,
3989
+ signature: null
3990
+ });
3991
+ }, []);
3992
+ const signMessage = useCallback8(async (message) => {
3993
+ if (!cubistClient || !wallet.address) {
3994
+ setState((prev) => ({
3995
+ ...prev,
3996
+ error: "Client not initialized"
3997
+ }));
3998
+ return;
3999
+ }
4000
+ setState((prev) => ({
4001
+ ...prev,
4002
+ isLoading: true,
4003
+ error: null
4004
+ }));
4005
+ try {
4006
+ const key = await cubistClient.org().getKeyByMaterialId(Secp256k12.Evm, wallet.address);
4007
+ const sig = await key.signBlob({
4008
+ message_base64: btoa(message)
4009
+ });
4010
+ const signature = `0x${sig.data().signature}`;
4011
+ setState((prev) => ({ ...prev, signature }));
4012
+ } catch (err) {
4013
+ setState((prev) => ({
4014
+ ...prev,
4015
+ error: err instanceof Error ? err.message : "Failed to sign message"
4016
+ }));
4017
+ } finally {
4018
+ setState((prev) => ({ ...prev, isLoading: false }));
4019
+ }
4020
+ }, [cubistClient, wallet.address]);
4021
+ return {
4022
+ ...state,
4023
+ signMessage,
4024
+ reset
4025
+ };
4026
+ }
4027
+
4028
+ // src/hooks/useSignTransaction.ts
4029
+ import { useCallback as useCallback9, useState as useState19 } from "react";
4030
+ import { Secp256k1 as Secp256k13 } from "@cubist-labs/cubesigner-sdk";
4031
+ function useSignTransaction() {
4032
+ const [state, setState] = useState19({
4033
+ isLoading: false,
4034
+ error: null,
4035
+ signature: null,
4036
+ signedTransaction: null
4037
+ });
4038
+ const { wallet, cubistClient } = useAvaCloudWallet();
4039
+ const { publicClient } = useViem();
4040
+ const reset = useCallback9(() => {
4041
+ setState({
4042
+ isLoading: false,
4043
+ error: null,
4044
+ signature: null,
4045
+ signedTransaction: null
4046
+ });
4047
+ }, []);
4048
+ const signTransaction = useCallback9(async (transaction) => {
4049
+ var _a, _b, _c, _d;
4050
+ console.log("Signing transaction with:", {
4051
+ wallet: wallet == null ? void 0 : wallet.address,
4052
+ hasClient: !!cubistClient,
4053
+ hasPublicClient: !!publicClient,
4054
+ chain: publicClient == null ? void 0 : publicClient.chain
4055
+ });
4056
+ if (!(wallet == null ? void 0 : wallet.address)) {
4057
+ setState((prev) => ({
4058
+ ...prev,
4059
+ error: "Wallet not connected"
4060
+ }));
4061
+ return;
4062
+ }
4063
+ if (!cubistClient) {
4064
+ setState((prev) => ({
4065
+ ...prev,
4066
+ error: "Cubist client not initialized"
4067
+ }));
4068
+ return;
4069
+ }
4070
+ if (!(publicClient == null ? void 0 : publicClient.chain)) {
4071
+ setState((prev) => ({
4072
+ ...prev,
4073
+ error: "Public client or chain not initialized"
4074
+ }));
4075
+ return;
4076
+ }
4077
+ setState((prev) => ({
4078
+ ...prev,
4079
+ isLoading: true,
4080
+ error: null
4081
+ }));
4082
+ try {
4083
+ const key = await cubistClient.org().getKeyByMaterialId(Secp256k13.Evm, wallet.address);
4084
+ if (!key) {
4085
+ throw new Error("No signing key available");
4086
+ }
4087
+ const signReq = {
4088
+ chain_id: publicClient.chain.id,
4089
+ tx: {
4090
+ to: transaction.to || void 0,
4091
+ value: (_a = transaction.value) == null ? void 0 : _a.toString(),
4092
+ data: transaction.data || "0x",
4093
+ nonce: (_b = transaction.nonce) == null ? void 0 : _b.toString(),
4094
+ type: "0x2",
4095
+ // EIP-1559
4096
+ maxFeePerGas: (_c = transaction.maxFeePerGas) == null ? void 0 : _c.toString(),
4097
+ maxPriorityFeePerGas: (_d = transaction.maxPriorityFeePerGas) == null ? void 0 : _d.toString()
4098
+ }
4099
+ };
4100
+ console.log("Signing request:", signReq);
4101
+ const sig = await key.signEvm(signReq);
4102
+ const signedTx = sig.data().rlp_signed_tx;
4103
+ setState((prev) => ({
4104
+ ...prev,
4105
+ signedTransaction: signedTx
4106
+ }));
4107
+ } catch (err) {
4108
+ console.error("Error signing transaction:", err);
4109
+ setState((prev) => ({
4110
+ ...prev,
4111
+ error: err instanceof Error ? err.message : "Failed to sign transaction"
4112
+ }));
4113
+ } finally {
4114
+ setState((prev) => ({ ...prev, isLoading: false }));
4115
+ }
4116
+ }, [wallet == null ? void 0 : wallet.address, publicClient, cubistClient]);
4117
+ return {
4118
+ ...state,
4119
+ signTransaction,
4120
+ reset
4121
+ };
4122
+ }
4123
+
4124
+ // src/hooks/useUserWallets.ts
4125
+ import { useCallback as useCallback10, useState as useState20 } from "react";
4126
+ function useUserWallets() {
4127
+ const [error, setError] = useState20(null);
4128
+ const [isLoading, setIsLoading] = useState20(false);
4129
+ const getWallets = useCallback10(async (client) => {
4130
+ setIsLoading(true);
4131
+ setError(null);
4132
+ try {
4133
+ const mnemonics = await client.org().keys();
4134
+ if (mnemonics.length === 0) {
4135
+ return [];
4136
+ }
4137
+ const wallets = mnemonics.map((key) => ({
4138
+ address: key.materialId,
4139
+ mnemonicId: key.id
4140
+ }));
4141
+ return wallets;
4142
+ } catch (err) {
4143
+ const error2 = err instanceof Error ? err : new Error("Failed to get user wallets");
4144
+ setError(error2);
4145
+ throw error2;
4146
+ } finally {
4147
+ setIsLoading(false);
4148
+ }
4149
+ }, []);
4150
+ return {
4151
+ getWallets,
4152
+ error,
4153
+ isLoading
4154
+ };
4155
+ }
4156
+ export {
4157
+ AvaCloudWalletProvider,
4158
+ ExportView,
4159
+ LoginButton,
4160
+ ReceiveView,
4161
+ SendView,
4162
+ ThemeProvider,
4163
+ TokensView,
4164
+ UserProfile,
4165
+ VM,
4166
+ WalletButton,
4167
+ WalletCard,
4168
+ WalletDisplay,
4169
+ useAuth,
4170
+ useAvaCloudWallet,
4171
+ useChainId,
4172
+ usePostMessage,
4173
+ useSignMessage,
4174
+ useSignTransaction,
4175
+ useThemeMode,
4176
+ useTransferTokens,
4177
+ useUserWallets
4178
+ };