@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/README.md +287 -0
- package/dist/index.d.mts +473 -0
- package/dist/index.d.ts +473 -0
- package/dist/index.js +4148 -0
- package/dist/index.mjs +4178 -0
- package/package.json +61 -0
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
|
+
};
|