@moon-x/core 0.2.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.
Files changed (55) hide show
  1. package/README.md +39 -0
  2. package/dist/chain-C9dvKXUY.d.mts +48 -0
  3. package/dist/chain-C9dvKXUY.d.ts +48 -0
  4. package/dist/chunk-264CEGDS.mjs +46 -0
  5. package/dist/chunk-CDT4MC7S.mjs +1532 -0
  6. package/dist/chunk-CMYR6AOY.mjs +0 -0
  7. package/dist/chunk-GQKIA37O.mjs +20 -0
  8. package/dist/chunk-IMLBIIJ4.mjs +36 -0
  9. package/dist/chunk-MOREUKOG.mjs +18 -0
  10. package/dist/chunk-SOKLPX7V.mjs +270 -0
  11. package/dist/index.d.mts +4 -0
  12. package/dist/index.d.ts +4 -0
  13. package/dist/index.js +402 -0
  14. package/dist/index.mjs +33 -0
  15. package/dist/interfaces-9k0eKCc4.d.ts +120 -0
  16. package/dist/interfaces-fNhwnCeY.d.mts +120 -0
  17. package/dist/lib/index.d.mts +410 -0
  18. package/dist/lib/index.d.ts +410 -0
  19. package/dist/lib/index.js +1622 -0
  20. package/dist/lib/index.mjs +89 -0
  21. package/dist/passkey-cache-B9PT3AWX.d.mts +47 -0
  22. package/dist/passkey-cache-B9PT3AWX.d.ts +47 -0
  23. package/dist/passkey-metadata-QqFF2SWQ.d.mts +25 -0
  24. package/dist/passkey-metadata-QqFF2SWQ.d.ts +25 -0
  25. package/dist/post-message-C_99BCBh.d.mts +70 -0
  26. package/dist/post-message-C_99BCBh.d.ts +70 -0
  27. package/dist/react/ethereum.d.mts +26 -0
  28. package/dist/react/ethereum.d.ts +26 -0
  29. package/dist/react/ethereum.js +99 -0
  30. package/dist/react/ethereum.mjs +56 -0
  31. package/dist/react/index.d.mts +182 -0
  32. package/dist/react/index.d.ts +182 -0
  33. package/dist/react/index.js +586 -0
  34. package/dist/react/index.mjs +328 -0
  35. package/dist/react/solana.d.mts +17 -0
  36. package/dist/react/solana.d.ts +17 -0
  37. package/dist/react/solana.js +75 -0
  38. package/dist/react/solana.mjs +35 -0
  39. package/dist/sdk/index.d.mts +126 -0
  40. package/dist/sdk/index.d.ts +126 -0
  41. package/dist/sdk/index.js +864 -0
  42. package/dist/sdk/index.mjs +579 -0
  43. package/dist/types/index.d.mts +1190 -0
  44. package/dist/types/index.d.ts +1190 -0
  45. package/dist/types/index.js +64 -0
  46. package/dist/types/index.mjs +10 -0
  47. package/dist/utils/index.d.mts +11 -0
  48. package/dist/utils/index.d.ts +11 -0
  49. package/dist/utils/index.js +365 -0
  50. package/dist/utils/index.mjs +25 -0
  51. package/dist/web/index.d.mts +20 -0
  52. package/dist/web/index.d.ts +20 -0
  53. package/dist/web/index.js +470 -0
  54. package/dist/web/index.mjs +155 -0
  55. package/package.json +111 -0
@@ -0,0 +1,1622 @@
1
+ "use strict";
2
+ var __create = Object.create;
3
+ var __defProp = Object.defineProperty;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
7
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __export = (target, all) => {
9
+ for (var name in all)
10
+ __defProp(target, name, { get: all[name], enumerable: true });
11
+ };
12
+ var __copyProps = (to, from, except, desc) => {
13
+ if (from && typeof from === "object" || typeof from === "function") {
14
+ for (let key of __getOwnPropNames(from))
15
+ if (!__hasOwnProp.call(to, key) && key !== except)
16
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
17
+ }
18
+ return to;
19
+ };
20
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
21
+ // If the importer is in node compatibility mode or this is not an ESM
22
+ // file that has been converted to a CommonJS file using a Babel-
23
+ // compatible transform (i.e. "__esModule" has not been set), then set
24
+ // "default" to the CommonJS "module.exports" for node compatibility.
25
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
26
+ mod
27
+ ));
28
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
29
+
30
+ // src/lib/index.ts
31
+ var lib_exports = {};
32
+ __export(lib_exports, {
33
+ DEFAULT_AUTH_URL: () => DEFAULT_AUTH_URL,
34
+ EthereumSiweMessage: () => EthereumSiweMessage,
35
+ SiwsMessage: () => SiwsMessage,
36
+ SolanaTransactionParser: () => SolanaTransactionParser,
37
+ arrayLikeToBytes: () => arrayLikeToBytes,
38
+ authState: () => authState,
39
+ broadcastEthereumRaw: () => broadcastEthereumRaw,
40
+ broadcastSolanaSigned: () => broadcastSolanaSigned,
41
+ bs58ToBytes: () => bs58ToBytes,
42
+ buildUrl: () => buildUrl,
43
+ clearParentAssertCache: () => clearParentAssertCache,
44
+ createManualSiweMessage: () => createManualSiweMessage,
45
+ estimateEvmGas: () => estimateEvmGas,
46
+ estimateEvmGasReserve: () => estimateEvmGasReserve,
47
+ formatPasskeyLabel: () => formatPasskeyLabel,
48
+ fromB64url: () => fromB64url,
49
+ generatePasskeyUserId: () => generatePasskeyUserId,
50
+ getAssertCacheTtlMs: () => getAssertCacheTtlMs,
51
+ getChainById: () => getChainById,
52
+ getDefaultChain: () => getDefaultChain,
53
+ getEvmGasPrice: () => getEvmGasPrice,
54
+ getEvmMaxPriorityFeePerGas: () => getEvmMaxPriorityFeePerGas,
55
+ getEvmNonce: () => getEvmNonce,
56
+ getInstructionsForHTML: () => getInstructionsForHTML,
57
+ getRpcUrl: () => getRpcUrl,
58
+ getSOLTransfersFromInstructions: () => getSOLTransfersFromInstructions,
59
+ getTransferInfoFromInstructions: () => getTransferInfoFromInstructions,
60
+ isChainSupported: () => isChainSupported,
61
+ prepareEvmSendTransaction: () => prepareEvmSendTransaction,
62
+ prepareEvmSignTransaction: () => prepareEvmSignTransaction,
63
+ readParentAssertCache: () => readParentAssertCache,
64
+ resolveEvmChain: () => resolveEvmChain,
65
+ resolvePasskeyMetadata: () => resolvePasskeyMetadata,
66
+ sanitizeUserData: () => sanitizeUserData,
67
+ serializeEthereumTransaction: () => serializeEthereumTransaction,
68
+ setAssertCacheTtlMs: () => setAssertCacheTtlMs,
69
+ setChainRpcUrl: () => setChainRpcUrl,
70
+ toB64url: () => toB64url,
71
+ validateChainConfig: () => validateChainConfig,
72
+ verifyIdToken: () => verifyIdToken,
73
+ withClearOnFailure: () => withClearOnFailure,
74
+ writeParentAssertCache: () => writeParentAssertCache
75
+ });
76
+ module.exports = __toCommonJS(lib_exports);
77
+
78
+ // src/lib/auth/authentication-state.ts
79
+ var AuthenticationState = class {
80
+ constructor() {
81
+ this.email = null;
82
+ }
83
+ setEmail(email) {
84
+ this.email = email;
85
+ }
86
+ getEmail() {
87
+ return this.email;
88
+ }
89
+ clearEmail() {
90
+ this.email = null;
91
+ }
92
+ clear() {
93
+ this.clearEmail();
94
+ }
95
+ };
96
+ var authState = new AuthenticationState();
97
+
98
+ // src/lib/auth/sanitize-user.ts
99
+ function sanitizeUserData(userData) {
100
+ if (!userData) return null;
101
+ const publicUser = {
102
+ user_id: userData.user_id,
103
+ first_name: userData.first_name,
104
+ last_name: userData.last_name,
105
+ status: userData.status,
106
+ active: userData.active,
107
+ is_guest: userData.is_guest,
108
+ emails: userData.emails,
109
+ phone_numbers: userData.phone_numbers,
110
+ idp_providers: userData.idp_providers,
111
+ wallets: userData.wallets,
112
+ totps: userData.totps,
113
+ webauthn_credentials: userData.webauthn_credentials,
114
+ created_at: userData.created_at,
115
+ updated_at: userData.updated_at
116
+ };
117
+ return Object.fromEntries(
118
+ Object.entries(publicUser).filter(([_, value]) => value !== void 0)
119
+ );
120
+ }
121
+
122
+ // src/utils/get-api-url.ts
123
+ var getMoonKeyApiUrl = () => {
124
+ if (process.env?.NEXT_PUBLIC_MOONKEY_API_URL) {
125
+ return process.env.NEXT_PUBLIC_MOONKEY_API_URL;
126
+ }
127
+ if (process.env?.NEXT_PUBLIC_MOONKEY_IFRAME_URL) {
128
+ const iframeUrl = process.env.NEXT_PUBLIC_MOONKEY_IFRAME_URL;
129
+ if (iframeUrl.includes("staging") || iframeUrl.includes("auth-staging")) {
130
+ return "https://api.moonx-dev.com";
131
+ }
132
+ }
133
+ if (process.env?.NEXT_PUBLIC_VERCEL_ENV === "preview") {
134
+ return "https://api.moonx-dev.com";
135
+ }
136
+ return "https://api.moonx-dev.com";
137
+ };
138
+
139
+ // src/lib/auth/verify-id-token.ts
140
+ var verifyIdToken = async (publishableKey, idToken) => {
141
+ try {
142
+ const apiUrl = getMoonKeyApiUrl();
143
+ const response = await fetch(
144
+ `${apiUrl}/v1/auth/users/public/id_token/verify`,
145
+ {
146
+ method: "GET",
147
+ headers: {
148
+ "Content-Type": "application/json",
149
+ Authorization: `PublicToken ${publishableKey}`,
150
+ "X-Streambird-id-token": idToken
151
+ }
152
+ }
153
+ );
154
+ if (!response.ok) {
155
+ const errorData = await response.json().catch(() => ({}));
156
+ return {
157
+ success: false,
158
+ error: errorData.message || `Failed to verify ID token: ${response.statusText}`,
159
+ statusCode: response.status
160
+ };
161
+ }
162
+ const responseData = await response.json();
163
+ const user = responseData.user || responseData;
164
+ return {
165
+ success: true,
166
+ user
167
+ };
168
+ } catch (error) {
169
+ console.error("Error verifying ID token:", error);
170
+ return {
171
+ success: false,
172
+ error: error instanceof Error ? error.message : "Unknown error occurred"
173
+ };
174
+ }
175
+ };
176
+
177
+ // src/lib/passkey/passkey-codec.ts
178
+ var fromB64url = (b64url) => {
179
+ const base64 = b64url.replace(/-/g, "+").replace(/_/g, "/");
180
+ const padded = base64 + "=".repeat((4 - base64.length % 4) % 4);
181
+ const binary = atob(padded);
182
+ const bytes = new Uint8Array(binary.length);
183
+ for (let i = 0; i < binary.length; i++) bytes[i] = binary.charCodeAt(i);
184
+ return bytes;
185
+ };
186
+ var toB64url = (bytes) => {
187
+ let str = "";
188
+ for (let i = 0; i < bytes.length; i++) str += String.fromCharCode(bytes[i]);
189
+ return btoa(str).replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/, "");
190
+ };
191
+
192
+ // src/lib/passkey/passkey-cache.ts
193
+ var cacheTtlMs = 0;
194
+ var cache = null;
195
+ var setAssertCacheTtlMs = (ms) => {
196
+ cacheTtlMs = Math.max(0, Math.floor(ms));
197
+ if (cacheTtlMs === 0) {
198
+ cache = null;
199
+ }
200
+ };
201
+ var getAssertCacheTtlMs = () => cacheTtlMs;
202
+ var clearParentAssertCache = () => {
203
+ cache = null;
204
+ };
205
+ var readParentAssertCache = () => {
206
+ if (cacheTtlMs <= 0) return null;
207
+ if (!cache) return null;
208
+ if (Date.now() - cache.ts >= cacheTtlMs) return null;
209
+ return {
210
+ userHandleB64url: cache.userHandleB64url,
211
+ credentialIdB64url: cache.credentialIdB64url
212
+ };
213
+ };
214
+ var writeParentAssertCache = (entry) => {
215
+ if (cacheTtlMs <= 0) return;
216
+ cache = { ...entry, ts: Date.now() };
217
+ };
218
+ var withClearOnFailure = async (fn) => {
219
+ try {
220
+ return await fn();
221
+ } catch (error) {
222
+ clearParentAssertCache();
223
+ throw error;
224
+ }
225
+ };
226
+ var generatePasskeyUserId = () => {
227
+ const bytes = crypto.getRandomValues(new Uint8Array(32));
228
+ return { userIdB64url: toB64url(bytes), userIdBytes: bytes };
229
+ };
230
+
231
+ // src/lib/passkey/passkey-aaguid-registry.json
232
+ var passkey_aaguid_registry_default = {
233
+ "a11a5faa-9f32-4b8c-8c5d-2f7d13e8c942": {
234
+ name: "AliasVault"
235
+ },
236
+ "ea9b8d66-4d01-1d21-3ce4-b6b48cb575d4": {
237
+ name: "Google Password Manager"
238
+ },
239
+ "adce0002-35bc-c60a-648b-0b25f1f05503": {
240
+ name: "Chrome on Mac"
241
+ },
242
+ "08987058-cadc-4b81-b6e1-30de50dcbe96": {
243
+ name: "Windows Hello"
244
+ },
245
+ "9ddd1817-af5a-4672-a2b9-3e3dd95000a9": {
246
+ name: "Windows Hello"
247
+ },
248
+ "6028b017-b1d4-4c02-b4b3-afcdafc96bb2": {
249
+ name: "Windows Hello"
250
+ },
251
+ "dd4ec289-e01d-41c9-bb89-70fa845d4bf2": {
252
+ name: "iCloud Keychain (Managed)"
253
+ },
254
+ "531126d6-e717-415c-9320-3d9aa6981239": {
255
+ name: "Dashlane"
256
+ },
257
+ "bada5566-a7aa-401f-bd96-45619a55120d": {
258
+ name: "1Password"
259
+ },
260
+ "b84e4048-15dc-4dd0-8640-f4f60813c8af": {
261
+ name: "NordPass"
262
+ },
263
+ "0ea242b4-43c4-4a1b-8b17-dd6d0b6baec6": {
264
+ name: "Keeper"
265
+ },
266
+ "891494da-2c90-4d31-a9cd-4eab0aed1309": {
267
+ name: "S\xE9same"
268
+ },
269
+ "f3809540-7f14-49c1-a8b3-8f813b225541": {
270
+ name: "Enpass"
271
+ },
272
+ "b5397666-4885-aa6b-cebf-e52262a439a2": {
273
+ name: "Chromium Browser"
274
+ },
275
+ "771b48fd-d3d4-4f74-9232-fc157ab0507a": {
276
+ name: "Edge on Mac"
277
+ },
278
+ "39a5647e-1853-446c-a1f6-a79bae9f5bc7": {
279
+ name: "IDmelon"
280
+ },
281
+ "d548826e-79b4-db40-a3d8-11116f7e8349": {
282
+ name: "Bitwarden"
283
+ },
284
+ "fbfc3007-154e-4ecc-8c0b-6e020557d7bd": {
285
+ name: "Apple Passwords"
286
+ },
287
+ "53414d53-554e-4700-0000-000000000000": {
288
+ name: "Samsung Pass"
289
+ },
290
+ "66a0ccb3-bd6a-191f-ee06-e375c50b9846": {
291
+ name: "Thales Bio iOS SDK"
292
+ },
293
+ "8836336a-f590-0921-301d-46427531eee6": {
294
+ name: "Thales Bio Android SDK"
295
+ },
296
+ "cd69adb5-3c7a-deb9-3177-6800ea6cb72a": {
297
+ name: "Thales PIN Android SDK"
298
+ },
299
+ "17290f1e-c212-34d0-1423-365d729f09d9": {
300
+ name: "Thales PIN iOS SDK"
301
+ },
302
+ "50726f74-6f6e-5061-7373-50726f746f6e": {
303
+ name: "Proton Pass"
304
+ },
305
+ "fdb141b2-5d84-443e-8a35-4698c205a502": {
306
+ name: "KeePassXC"
307
+ },
308
+ "eaecdef2-1c31-5634-8639-f1cbd9c00a08": {
309
+ name: "KeePassDX"
310
+ },
311
+ "cc45f64e-52a2-451b-831a-4edd8022a202": {
312
+ name: "ToothPic Passkey Provider"
313
+ },
314
+ "bfc748bb-3429-4faa-b9f9-7cfa9f3b76d0": {
315
+ name: "iPasswords"
316
+ },
317
+ "b35a26b2-8f6e-4697-ab1d-d44db4da28c6": {
318
+ name: "Zoho Vault"
319
+ },
320
+ "b78a0a55-6ef8-d246-a042-ba0f6d55050c": {
321
+ name: "LastPass"
322
+ },
323
+ "de503f9c-21a4-4f76-b4b7-558eb55c6f89": {
324
+ name: "Devolutions"
325
+ },
326
+ "22248c4c-7a12-46e2-9a41-44291b373a4d": {
327
+ name: "LogMeOnce"
328
+ },
329
+ "a10c6dd9-465e-4226-8198-c7c44b91c555": {
330
+ name: "Kaspersky Password Manager"
331
+ },
332
+ "d350af52-0351-4ba2-acd3-dfeeadc3f764": {
333
+ name: "pwSafe"
334
+ },
335
+ "d3452668-01fd-4c12-926c-83a4204853aa": {
336
+ name: "Microsoft Password Manager"
337
+ },
338
+ "6d212b28-a2c1-4638-b375-5932070f62e9": {
339
+ name: "initial"
340
+ },
341
+ "d49b2120-b865-4191-8cea-be84a52b0485": {
342
+ name: "Heimlane Vault"
343
+ },
344
+ "e8b7f4a2-c3d5-e6f7-890a-b1c2d3e4f567": {
345
+ name: "Sherlocked"
346
+ },
347
+ "d9be9d39-e6a6-4c28-a581-32b044d986e4": {
348
+ name: "Sticky Password Manager"
349
+ },
350
+ "70617373-7761-6c6c-6669-646f32303236": {
351
+ name: "Passwall"
352
+ },
353
+ "c9cadfc9-89a9-489e-a25a-c7e86a4d5f15": {
354
+ name: "Burp Suite Navigation Recorder"
355
+ }
356
+ };
357
+
358
+ // src/lib/passkey/passkey-metadata.ts
359
+ var aaguidRegistry = passkey_aaguid_registry_default;
360
+ var ZERO_AAGUID = "00000000-0000-0000-0000-000000000000";
361
+ function resolveProvider(aaguid, transports) {
362
+ if (!aaguid) return "Unknown authenticator";
363
+ const entry = aaguidRegistry[aaguid];
364
+ if (entry?.name) return entry.name;
365
+ if (aaguid === ZERO_AAGUID) {
366
+ if (transports.includes("internal")) return "iCloud Keychain";
367
+ return "Unknown authenticator";
368
+ }
369
+ return "Unknown authenticator";
370
+ }
371
+ function resolveFormFactor(transports) {
372
+ if (transports.includes("hybrid")) return "hybrid";
373
+ if (transports.includes("internal")) return "platform";
374
+ if (transports.includes("usb") || transports.includes("nfc") || transports.includes("ble")) {
375
+ return "roaming";
376
+ }
377
+ return "unknown";
378
+ }
379
+ function formatPasskeyLabel(input) {
380
+ if (input.nickname && input.nickname.trim()) return input.nickname.trim();
381
+ const transports = input.transports ?? [];
382
+ const providerName = resolveProvider(input.aaguid, transports);
383
+ if (providerName.includes(" on ")) return providerName;
384
+ if (input.registeredBrowser) {
385
+ return `${providerName} on ${input.registeredBrowser}`;
386
+ }
387
+ return providerName;
388
+ }
389
+ function resolvePasskeyMetadata(input) {
390
+ const transports = input.transports ?? [];
391
+ const providerName = resolveProvider(input.aaguid, transports);
392
+ return {
393
+ providerName,
394
+ formFactor: resolveFormFactor(transports),
395
+ isCloudSynced: !!input.backupState,
396
+ label: formatPasskeyLabel(input)
397
+ };
398
+ }
399
+
400
+ // src/lib/ethereum/chains.ts
401
+ var import_viem = require("viem");
402
+ function setChainRpcUrl(chain, rpcUrl) {
403
+ return {
404
+ ...chain,
405
+ rpcUrls: {
406
+ ...chain.rpcUrls,
407
+ default: {
408
+ http: [rpcUrl],
409
+ webSocket: chain.rpcUrls.default.webSocket
410
+ }
411
+ }
412
+ };
413
+ }
414
+ function getRpcUrl(chain) {
415
+ return chain.rpcUrls.default.http[0];
416
+ }
417
+ async function getEvmMaxPriorityFeePerGas(rpcUrl) {
418
+ const response = await fetch(rpcUrl, {
419
+ method: "POST",
420
+ headers: { "Content-Type": "application/json" },
421
+ body: JSON.stringify({
422
+ jsonrpc: "2.0",
423
+ id: 1,
424
+ method: "eth_maxPriorityFeePerGas",
425
+ params: []
426
+ })
427
+ });
428
+ const result = await response.json();
429
+ if (result.error) {
430
+ throw new Error(
431
+ result.error.message || "eth_maxPriorityFeePerGas failed"
432
+ );
433
+ }
434
+ return BigInt(result.result);
435
+ }
436
+ async function getEvmGasPrice(rpcUrl) {
437
+ const response = await fetch(rpcUrl, {
438
+ method: "POST",
439
+ headers: { "Content-Type": "application/json" },
440
+ body: JSON.stringify({
441
+ jsonrpc: "2.0",
442
+ id: 1,
443
+ method: "eth_gasPrice",
444
+ params: []
445
+ })
446
+ });
447
+ const result = await response.json();
448
+ if (result.error) {
449
+ throw new Error(result.error.message || "eth_gasPrice failed");
450
+ }
451
+ return BigInt(result.result);
452
+ }
453
+ async function estimateEvmGas(rpcUrl, tx) {
454
+ const valueHex = (() => {
455
+ const v = tx.value;
456
+ if (v == null) return "0x0";
457
+ if (typeof v === "bigint") return `0x${v.toString(16)}`;
458
+ if (typeof v === "number") return `0x${BigInt(v).toString(16)}`;
459
+ if (typeof v === "string") {
460
+ if (v === "") return "0x0";
461
+ if (v.startsWith("0x")) return v;
462
+ if (v.includes(".")) {
463
+ return `0x${(0, import_viem.parseEther)(v).toString(16)}`;
464
+ }
465
+ try {
466
+ return `0x${BigInt(v).toString(16)}`;
467
+ } catch {
468
+ return "0x0";
469
+ }
470
+ }
471
+ return "0x0";
472
+ })();
473
+ const params = {
474
+ from: tx.from,
475
+ value: valueHex,
476
+ data: tx.data || "0x"
477
+ };
478
+ if (tx.to) params.to = tx.to;
479
+ const response = await fetch(rpcUrl, {
480
+ method: "POST",
481
+ headers: { "Content-Type": "application/json" },
482
+ body: JSON.stringify({
483
+ jsonrpc: "2.0",
484
+ id: 1,
485
+ method: "eth_estimateGas",
486
+ params: [params]
487
+ })
488
+ });
489
+ const result = await response.json();
490
+ if (result.error) {
491
+ throw new Error(result.error.message || "eth_estimateGas failed");
492
+ }
493
+ return BigInt(result.result);
494
+ }
495
+ async function getEvmNonce(rpcUrl, address) {
496
+ const response = await fetch(rpcUrl, {
497
+ method: "POST",
498
+ headers: { "Content-Type": "application/json" },
499
+ body: JSON.stringify({
500
+ jsonrpc: "2.0",
501
+ id: 1,
502
+ method: "eth_getTransactionCount",
503
+ params: [address, "pending"]
504
+ })
505
+ });
506
+ const result = await response.json();
507
+ if (result.error) {
508
+ throw new Error(result.error.message || "eth_getTransactionCount failed");
509
+ }
510
+ return Number(BigInt(result.result));
511
+ }
512
+ function typicalSwapGasUnits(chainId) {
513
+ switch (chainId) {
514
+ case 1:
515
+ return 300000n;
516
+ // Ethereum mainnet
517
+ case 137:
518
+ return 300000n;
519
+ // Polygon
520
+ case 56:
521
+ return 250000n;
522
+ // BSC
523
+ case 42161:
524
+ return 1500000n;
525
+ // Arbitrum (incl L1 calldata)
526
+ case 8453:
527
+ case 10:
528
+ return 700000n;
529
+ // Base / Optimism (incl L1 calldata)
530
+ default:
531
+ return 300000n;
532
+ }
533
+ }
534
+ async function estimateEvmGasReserve(rpcUrl, chainId, opts = {}) {
535
+ const gasUnits = opts.gasUnits ?? typicalSwapGasUnits(chainId);
536
+ const rawBuffer = opts.bufferBps ?? 15e3;
537
+ const bufferBps = Math.max(
538
+ Number.isFinite(rawBuffer) ? Math.round(rawBuffer) : 15e3,
539
+ 1
540
+ );
541
+ const gasPrice = await getEvmGasPrice(rpcUrl);
542
+ const reserveWei = gasPrice * gasUnits * BigInt(bufferBps) / 10000n;
543
+ return Number((0, import_viem.formatEther)(reserveWei));
544
+ }
545
+ function getChainById(chains, chainId) {
546
+ return chains.find((chain) => chain.id === chainId);
547
+ }
548
+ function isChainSupported(chains, chainId) {
549
+ return chains.some((chain) => chain.id === chainId);
550
+ }
551
+ function validateChainConfig(config) {
552
+ const { defaultChain, supportedChains } = config;
553
+ if (supportedChains && supportedChains.length === 0) {
554
+ throw new Error("supportedChains cannot be an empty array");
555
+ }
556
+ if (defaultChain && supportedChains) {
557
+ const isDefaultInSupported = supportedChains.some(
558
+ (chain) => chain.id === defaultChain.id
559
+ );
560
+ if (!isDefaultInSupported) {
561
+ throw new Error(
562
+ `defaultChain (${defaultChain.name}, ID: ${defaultChain.id}) must be included in supportedChains`
563
+ );
564
+ }
565
+ }
566
+ }
567
+ function getDefaultChain(config) {
568
+ if (config.defaultChain) {
569
+ return config.defaultChain;
570
+ }
571
+ if (config.supportedChains && config.supportedChains.length > 0) {
572
+ return config.supportedChains[0];
573
+ }
574
+ return void 0;
575
+ }
576
+
577
+ // src/lib/ethereum/siwe.ts
578
+ var import_siwe = require("siwe");
579
+ var import_viem2 = require("viem");
580
+ var EthereumSiweMessage = class {
581
+ constructor({
582
+ nonce,
583
+ domain,
584
+ address,
585
+ uri,
586
+ version = "1",
587
+ chainId = 1,
588
+ statement,
589
+ issuedAt,
590
+ expirationTime,
591
+ notBefore,
592
+ requestId,
593
+ resources
594
+ }) {
595
+ this.siweMessage = new import_siwe.SiweMessage({
596
+ domain,
597
+ address,
598
+ uri,
599
+ version,
600
+ chainId,
601
+ nonce,
602
+ statement,
603
+ issuedAt,
604
+ expirationTime,
605
+ notBefore,
606
+ requestId,
607
+ resources
608
+ });
609
+ }
610
+ prepareMessage() {
611
+ return this.siweMessage.prepareMessage();
612
+ }
613
+ getMessage() {
614
+ return this.siweMessage;
615
+ }
616
+ };
617
+ function createManualSiweMessage({
618
+ nonce,
619
+ domain,
620
+ address,
621
+ uri = typeof window !== "undefined" ? window.location.origin : "",
622
+ version = "1",
623
+ chainId = 1,
624
+ statement,
625
+ issuedAt = (/* @__PURE__ */ new Date()).toISOString(),
626
+ walletName = "Ethereum"
627
+ }) {
628
+ let checksummedAddress;
629
+ try {
630
+ checksummedAddress = (0, import_viem2.getAddress)(address);
631
+ } catch (error) {
632
+ checksummedAddress = address;
633
+ }
634
+ let siweMessage = `${domain} wants you to sign in with your Ethereum account:
635
+ `;
636
+ siweMessage += `${checksummedAddress}`;
637
+ const defaultStatement = `Sign in with Ethereum to MoonKey using ${walletName}.`;
638
+ siweMessage += `
639
+
640
+ ${statement || defaultStatement}`;
641
+ const fields = [];
642
+ fields.push(`URI: ${uri}`);
643
+ fields.push(`Version: ${version}`);
644
+ fields.push(`Chain ID: ${chainId}`);
645
+ fields.push(`Nonce: ${nonce}`);
646
+ fields.push(`Issued At: ${issuedAt}`);
647
+ siweMessage += `
648
+
649
+ ${fields.join("\n")}`;
650
+ return siweMessage;
651
+ }
652
+
653
+ // src/lib/ethereum/tx-prep.ts
654
+ var import_viem3 = require("viem");
655
+ function resolveEvmChain({
656
+ requestedChainId,
657
+ walletChainId,
658
+ supportedChains,
659
+ defaultChain,
660
+ strict = false
661
+ }) {
662
+ let target;
663
+ if (requestedChainId && supportedChains) {
664
+ target = getChainById(supportedChains, Number(requestedChainId));
665
+ }
666
+ if (!target && walletChainId && supportedChains) {
667
+ target = getChainById(supportedChains, walletChainId);
668
+ }
669
+ if (!target) {
670
+ target = defaultChain;
671
+ }
672
+ if (!target) {
673
+ throw new Error(
674
+ "No chain configured. Please set ethereum.defaultChain in MoonKeyProvider config."
675
+ );
676
+ }
677
+ if (strict && requestedChainId && Number(requestedChainId) !== target.id) {
678
+ throw new Error(
679
+ `Requested chainId ${requestedChainId} is not in the configured supportedChains.`
680
+ );
681
+ }
682
+ return target;
683
+ }
684
+ async function prepareEvmSignTransaction({
685
+ transaction,
686
+ wallet,
687
+ supportedChains,
688
+ defaultChain
689
+ }) {
690
+ if (typeof transaction === "string") {
691
+ return { serializedTransaction: transaction, chain: void 0 };
692
+ }
693
+ const txObj = transaction;
694
+ const transactionType = txObj.type ?? 2;
695
+ const chain = resolveEvmChain({
696
+ requestedChainId: txObj.chainId,
697
+ walletChainId: wallet.chainId,
698
+ supportedChains,
699
+ defaultChain,
700
+ strict: false
701
+ });
702
+ const derivedChainId = txObj.chainId || chain.id;
703
+ const formattedTransaction = {
704
+ to: txObj.to,
705
+ value: txObj.value ? typeof txObj.value === "bigint" ? txObj.value : (0, import_viem3.parseEther)(txObj.value.toString()) : BigInt(0),
706
+ data: txObj.data || "0x",
707
+ chainId: derivedChainId
708
+ };
709
+ if (transactionType === 2 || transactionType === "eip1559") {
710
+ formattedTransaction.type = "eip1559";
711
+ formattedTransaction.maxPriorityFeePerGas = txObj.maxPriorityFeePerGas ? typeof txObj.maxPriorityFeePerGas === "bigint" ? txObj.maxPriorityFeePerGas : (0, import_viem3.parseGwei)(txObj.maxPriorityFeePerGas.toString()) : BigInt(2e9);
712
+ formattedTransaction.maxFeePerGas = txObj.maxFeePerGas ? typeof txObj.maxFeePerGas === "bigint" ? txObj.maxFeePerGas : (0, import_viem3.parseGwei)(txObj.maxFeePerGas.toString()) : BigInt(22e9);
713
+ } else {
714
+ formattedTransaction.type = "legacy";
715
+ formattedTransaction.gasPrice = txObj.gasPrice ? typeof txObj.gasPrice === "bigint" ? txObj.gasPrice : (0, import_viem3.parseGwei)(txObj.gasPrice.toString()) : BigInt(2e9);
716
+ }
717
+ if (txObj.nonce !== void 0) {
718
+ formattedTransaction.nonce = Number(txObj.nonce);
719
+ }
720
+ if (txObj.gas !== void 0) {
721
+ formattedTransaction.gas = typeof txObj.gas === "bigint" ? txObj.gas : BigInt(txObj.gas);
722
+ }
723
+ if (txObj.gasLimit !== void 0) {
724
+ formattedTransaction.gas = typeof txObj.gasLimit === "bigint" ? txObj.gasLimit : BigInt(txObj.gasLimit);
725
+ }
726
+ return {
727
+ serializedTransaction: (0, import_viem3.serializeTransaction)(formattedTransaction),
728
+ chain
729
+ };
730
+ }
731
+ async function prepareEvmSendTransaction({
732
+ transaction,
733
+ wallet,
734
+ supportedChains,
735
+ defaultChain
736
+ }) {
737
+ const chain = resolveEvmChain({
738
+ requestedChainId: transaction.chainId,
739
+ walletChainId: wallet.chainId,
740
+ supportedChains,
741
+ defaultChain,
742
+ strict: true
743
+ });
744
+ const rpcUrl = getRpcUrl(chain);
745
+ if (!rpcUrl) {
746
+ throw new Error(
747
+ `No RPC URL found for chain ${chain.name}. Chain may be missing rpcUrls configuration.`
748
+ );
749
+ }
750
+ const txWithChainId = {
751
+ ...transaction,
752
+ chainId: chain.id
753
+ };
754
+ if (txWithChainId.nonce == null) {
755
+ try {
756
+ txWithChainId.nonce = await getEvmNonce(rpcUrl, wallet.public_address);
757
+ } catch {
758
+ }
759
+ }
760
+ const callerGas = txWithChainId.gas ?? txWithChainId.gasLimit;
761
+ if (callerGas == null) {
762
+ try {
763
+ const estimate = await estimateEvmGas(rpcUrl, {
764
+ from: wallet.public_address,
765
+ to: txWithChainId.to,
766
+ data: txWithChainId.data,
767
+ value: txWithChainId.value
768
+ });
769
+ txWithChainId.gas = (estimate * 12n / 10n).toString();
770
+ } catch {
771
+ txWithChainId.gas = "800000";
772
+ }
773
+ } else if (callerGas != null && txWithChainId.gas == null) {
774
+ txWithChainId.gas = callerGas;
775
+ }
776
+ if (txWithChainId.maxFeePerGas == null && txWithChainId.gasPrice == null) {
777
+ try {
778
+ const [baseGasPrice, suggestedTipResult] = await Promise.all([
779
+ getEvmGasPrice(rpcUrl),
780
+ getEvmMaxPriorityFeePerGas(rpcUrl).catch(() => null)
781
+ ]);
782
+ let tip;
783
+ if (suggestedTipResult != null && suggestedTipResult > 0n) {
784
+ tip = suggestedTipResult * 12n / 10n;
785
+ } else {
786
+ const cap = 2000000000n;
787
+ tip = baseGasPrice / 10n < cap ? baseGasPrice / 10n : cap;
788
+ if (tip <= 0n) tip = 1n;
789
+ }
790
+ const baseMaxFee = baseGasPrice > 0n ? baseGasPrice * 15n / 10n : tip * 2n;
791
+ const maxFee = baseMaxFee > tip ? baseMaxFee : tip + 1n;
792
+ txWithChainId.maxFeePerGas = `0x${maxFee.toString(16)}`;
793
+ txWithChainId.maxPriorityFeePerGas = `0x${tip.toString(16)}`;
794
+ } catch {
795
+ }
796
+ }
797
+ return { transaction: txWithChainId, rpcUrl, chain };
798
+ }
799
+
800
+ // src/lib/solana/siws.ts
801
+ var nacl = __toESM(require("tweetnacl"));
802
+ var SiwsMessage = class {
803
+ constructor({
804
+ nonce,
805
+ domain,
806
+ address,
807
+ uri,
808
+ version,
809
+ chainId,
810
+ statement,
811
+ issuedAt,
812
+ expirationTime,
813
+ notBefore,
814
+ requestId,
815
+ resources,
816
+ message,
817
+ signature
818
+ }) {
819
+ this.nonce = nonce;
820
+ this.domain = domain;
821
+ this.address = address;
822
+ this.uri = uri;
823
+ this.version = version;
824
+ this.chainId = chainId;
825
+ this.statement = statement;
826
+ this.issuedAt = issuedAt;
827
+ this.expirationTime = expirationTime;
828
+ this.notBefore = notBefore;
829
+ this.requestId = requestId;
830
+ this.resources = resources;
831
+ this.message = message;
832
+ this.signature = signature;
833
+ }
834
+ prepareBasic() {
835
+ let message = `${this.domain} wants you to sign in with your Solana account:
836
+ `;
837
+ message += `${this.address}`;
838
+ if (this.statement) {
839
+ message += `
840
+
841
+ ${this.statement}`;
842
+ }
843
+ const fields = [];
844
+ if (this.nonce) {
845
+ fields.push(`Nonce: ${this.nonce}`);
846
+ }
847
+ if (this.issuedAt) {
848
+ fields.push(`Issued At: ${this.issuedAt}`);
849
+ }
850
+ if (fields.length) {
851
+ message += `
852
+
853
+ ${fields.join("\n")}`;
854
+ }
855
+ this.message = message;
856
+ return new TextEncoder().encode(message);
857
+ }
858
+ prepareAdvanced() {
859
+ const issuedAt = this.issuedAt || (/* @__PURE__ */ new Date()).toISOString();
860
+ let message = `${this.domain} wants you to sign in with your Solana account:
861
+ `;
862
+ message += `${this.address}`;
863
+ if (this.statement) {
864
+ message += `
865
+
866
+ ${this.statement}`;
867
+ }
868
+ const fields = [];
869
+ if (this.uri) {
870
+ fields.push(`URI: ${this.uri}`);
871
+ }
872
+ if (this.version) {
873
+ fields.push(`Version: ${this.version}`);
874
+ }
875
+ if (this.chainId) {
876
+ fields.push(`Chain ID: ${this.chainId}`);
877
+ }
878
+ if (this.nonce) {
879
+ fields.push(`Nonce: ${this.nonce}`);
880
+ }
881
+ if (this.issuedAt) {
882
+ fields.push(`Issued At: ${this.issuedAt}`);
883
+ }
884
+ if (this.expirationTime) {
885
+ fields.push(`Expiration Time: ${this.expirationTime}`);
886
+ }
887
+ if (this.notBefore) {
888
+ fields.push(`Not Before: ${this.notBefore}`);
889
+ }
890
+ if (this.requestId) {
891
+ fields.push(`Request ID: ${this.requestId}`);
892
+ }
893
+ if (this.resources && this.resources.length > 0) {
894
+ fields.push(`Resources:`);
895
+ for (const resource of this.resources) {
896
+ fields.push(`- ${resource}`);
897
+ }
898
+ }
899
+ if (fields.length) {
900
+ message += `
901
+
902
+ ${fields.join("\n")}`;
903
+ }
904
+ this.message = message;
905
+ return new TextEncoder().encode(message);
906
+ }
907
+ async token(signature) {
908
+ const bs58 = await import("bs58");
909
+ this.signature = bs58.default.encode(signature);
910
+ const tokenData = Buffer.from(JSON.stringify(this));
911
+ return tokenData.toString("base64");
912
+ }
913
+ decode(token) {
914
+ const tokenObject = Buffer.from(token, "base64");
915
+ const siwsMessage = JSON.parse(tokenObject.toString("utf8"));
916
+ this.nonce = siwsMessage.nonce;
917
+ this.domain = siwsMessage.domain;
918
+ this.address = siwsMessage.address;
919
+ this.uri = siwsMessage.uri;
920
+ this.version = siwsMessage.version;
921
+ this.chainId = siwsMessage.chainId;
922
+ this.statement = siwsMessage.statement;
923
+ this.issuedAt = siwsMessage.issuedAt;
924
+ this.expirationTime = siwsMessage.expirationTime;
925
+ this.notBefore = siwsMessage.notBefore;
926
+ this.requestId = siwsMessage.requestId;
927
+ this.resources = siwsMessage.resources;
928
+ this.signature = siwsMessage.signature;
929
+ this.message = siwsMessage.message;
930
+ return this;
931
+ }
932
+ async validate() {
933
+ if (!this.message || !this.signature) {
934
+ return false;
935
+ }
936
+ const bs58 = await import("bs58");
937
+ const messageBytes = new TextEncoder().encode(this.message);
938
+ const publicKeyBytes = bs58.default.decode(this.address);
939
+ const signatureBytes = bs58.default.decode(this.signature);
940
+ const result = nacl.sign.detached.verify(
941
+ messageBytes,
942
+ signatureBytes,
943
+ publicKeyBytes
944
+ );
945
+ return result;
946
+ }
947
+ };
948
+
949
+ // src/lib/solana/transaction-log-parser.ts
950
+ var import_web3 = require("@solana/web3.js");
951
+ var import_bn = __toESM(require("bn.js"));
952
+ var base64ToUint8Array = (base64) => {
953
+ const binaryString = atob(base64);
954
+ const bytes = new Uint8Array(binaryString.length);
955
+ for (let i = 0; i < binaryString.length; i++) {
956
+ bytes[i] = binaryString.charCodeAt(i);
957
+ }
958
+ return bytes;
959
+ };
960
+ var SolanaTransactionParser = class {
961
+ constructor(logs, base64Transaction, connection, userPublicKey) {
962
+ this.instructions = [];
963
+ this.logs = logs;
964
+ this.connection = connection;
965
+ this.userPublicKey = userPublicKey;
966
+ if (base64Transaction) {
967
+ try {
968
+ const txBuffer = base64ToUint8Array(base64Transaction);
969
+ try {
970
+ this.transaction = import_web3.VersionedTransaction.deserialize(txBuffer);
971
+ } catch {
972
+ this.transaction = import_web3.Transaction.from(txBuffer);
973
+ }
974
+ } catch (e) {
975
+ console.error("Failed to deserialize transaction:", e);
976
+ }
977
+ }
978
+ }
979
+ async parse() {
980
+ if (!this.transaction) {
981
+ throw new Error("No transaction provided. Pass base64 transaction string to constructor.");
982
+ }
983
+ this.instructions = [];
984
+ const message = this.transaction instanceof import_web3.VersionedTransaction ? this.transaction.message : this.transaction.compileMessage();
985
+ const accountKeys = "staticAccountKeys" in message ? message.staticAccountKeys : message.accountKeys;
986
+ const compiledInstructions = "compiledInstructions" in message ? message.compiledInstructions : message.instructions;
987
+ for (let i = 0; i < compiledInstructions.length; i++) {
988
+ const ix = compiledInstructions[i];
989
+ const programId = accountKeys[ix.programIdIndex];
990
+ const programIdStr = programId.toBase58();
991
+ const ixAccounts = ix.accountKeyIndexes.map((idx) => accountKeys[idx]);
992
+ const data = ix.data instanceof Uint8Array ? ix.data : new Uint8Array(ix.data);
993
+ await this.parseInstruction(programIdStr, data, ixAccounts, i);
994
+ }
995
+ return this.instructions;
996
+ }
997
+ async parseInstruction(programId, data, accounts, instructionIndex) {
998
+ switch (programId) {
999
+ case "ComputeBudget11111111111111111111111111111111":
1000
+ this.parseComputeBudget(data);
1001
+ break;
1002
+ case "ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL":
1003
+ this.parseAssociatedToken(accounts);
1004
+ break;
1005
+ case "11111111111111111111111111111111":
1006
+ this.parseSystemProgram(data, accounts);
1007
+ break;
1008
+ case "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA":
1009
+ this.parseTokenProgram(data, accounts);
1010
+ break;
1011
+ case "JUP6LkbZbjS1jKKwapdHNy74zcZ3tLUZoi5QNyVTaV4":
1012
+ break;
1013
+ default:
1014
+ this.parseGenericInstruction(programId, data, accounts, instructionIndex);
1015
+ break;
1016
+ }
1017
+ }
1018
+ parseGenericInstruction(programId, data, accounts, instructionIndex) {
1019
+ const instructionType = data.length > 0 ? data[0] : 0;
1020
+ this.instructions.push({
1021
+ type: "Unknown",
1022
+ details: {
1023
+ programId: this.truncate(programId, 8, 4),
1024
+ instructionType,
1025
+ dataLength: data.length,
1026
+ rawData: data.toString("hex"),
1027
+ accountCount: accounts.length,
1028
+ accounts: accounts.map((acc) => this.truncate(acc.toBase58(), 5, 4))
1029
+ }
1030
+ });
1031
+ }
1032
+ parseComputeBudget(data) {
1033
+ const instructionType = data[0];
1034
+ this.instructions.push({
1035
+ type: "ComputeBudget",
1036
+ details: {
1037
+ programId: this.truncate("ComputeBudget11111111111111111111111111111111", 8, 4),
1038
+ data: instructionType
1039
+ }
1040
+ });
1041
+ }
1042
+ parseAssociatedToken(accounts) {
1043
+ const owner = accounts[2];
1044
+ this.instructions.push({
1045
+ type: "CreateTokenAccount",
1046
+ details: {
1047
+ programId: this.truncate("ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL", 5, 4),
1048
+ owner: this.truncate(owner?.toBase58() || "Unknown", 5, 4)
1049
+ }
1050
+ });
1051
+ }
1052
+ parseSystemProgram(data, accounts) {
1053
+ const instructionType = data.readUInt32LE(0);
1054
+ if (instructionType === 2) {
1055
+ const lamports = new import_bn.default(data.slice(4, 12), "le");
1056
+ const destination = accounts[1];
1057
+ this.instructions.push({
1058
+ type: "Transfer",
1059
+ details: {
1060
+ amount: this.formatSOL(lamports.toString()),
1061
+ destination: this.truncate(destination?.toBase58() || "Unknown", 5, 4)
1062
+ }
1063
+ });
1064
+ }
1065
+ }
1066
+ parseTokenProgram(data, accounts) {
1067
+ const instructionType = data[0];
1068
+ if (instructionType === 17) {
1069
+ this.instructions.push({
1070
+ type: "SyncNative",
1071
+ details: {
1072
+ programId: this.truncate("TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA", 5, 4)
1073
+ }
1074
+ });
1075
+ } else if (instructionType === 9) {
1076
+ const source = accounts[0];
1077
+ const destination = accounts[1];
1078
+ const owner = accounts[2];
1079
+ this.instructions.push({
1080
+ type: "CloseAccount",
1081
+ details: {
1082
+ source: this.truncate(source?.toBase58() || "Unknown", 5, 4),
1083
+ destination: this.truncate(destination?.toBase58() || "Unknown", 5, 4),
1084
+ owner: this.truncate(owner?.toBase58() || "Unknown", 5, 4)
1085
+ }
1086
+ });
1087
+ }
1088
+ }
1089
+ parseJupiterBasic(data, accounts) {
1090
+ let inAmount = "Unknown";
1091
+ let outAmount = "Unknown";
1092
+ let tokenIn = "Unknown";
1093
+ let tokenOut = "Unknown";
1094
+ for (const log of this.logs) {
1095
+ if (log.includes("Transfer") && log.includes("lamports")) {
1096
+ const lamportsMatch = log.match(/(\d+)\s*lamports/);
1097
+ if (lamportsMatch && inAmount === "Unknown") {
1098
+ inAmount = this.formatSOL(lamportsMatch[1]);
1099
+ }
1100
+ }
1101
+ if (log.includes("amount:") || log.includes("Amount:")) {
1102
+ const amountMatch = log.match(/amount:\s*(\d+)/i);
1103
+ if (amountMatch) {
1104
+ if (inAmount === "Unknown") {
1105
+ inAmount = amountMatch[1];
1106
+ } else if (outAmount === "Unknown") {
1107
+ outAmount = amountMatch[1];
1108
+ }
1109
+ }
1110
+ }
1111
+ if (log.includes("mint:") || log.includes("Mint:") || log.includes("mint=")) {
1112
+ const mintMatch = log.match(/(?:mint:|Mint:|mint=)\s*([A-Za-z0-9]{32,44})/i);
1113
+ if (mintMatch) {
1114
+ const mintAddress = mintMatch[1];
1115
+ if (tokenIn === "Unknown") {
1116
+ tokenIn = this.truncate(mintAddress, 5, 4);
1117
+ } else if (tokenOut === "Unknown") {
1118
+ tokenOut = this.truncate(mintAddress, 5, 4);
1119
+ }
1120
+ }
1121
+ }
1122
+ if (log.includes("Program return: JUP6")) {
1123
+ const match = log.match(/Program return: \S+ (.+)/);
1124
+ if (match) {
1125
+ try {
1126
+ const decoded = base64ToUint8Array(match[1]);
1127
+ outAmount = new import_bn.default(decoded, "le").toString();
1128
+ } catch (e) {
1129
+ console.error("Failed to decode Jupiter return:", e);
1130
+ }
1131
+ }
1132
+ }
1133
+ }
1134
+ if (tokenIn === "Unknown" || tokenOut === "Unknown") {
1135
+ const wsolMint = "So11111111111111111111111111111111111111112";
1136
+ for (const account of accounts) {
1137
+ try {
1138
+ const accountStr = account.toBase58();
1139
+ if (!accountStr.includes("11111111111111111111111111111111") && !accountStr.includes("TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA") && !accountStr.includes("ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL") && !accountStr.includes("JUP6LkbZbjS1jKKwapdHNy74zcZ3tLUZoi5QNyVTaV4")) {
1140
+ if (tokenIn === "Unknown") {
1141
+ tokenIn = this.truncate(accountStr, 5, 4);
1142
+ } else if (tokenOut === "Unknown") {
1143
+ tokenOut = this.truncate(accountStr, 5, 4);
1144
+ break;
1145
+ }
1146
+ }
1147
+ } catch (e) {
1148
+ }
1149
+ }
1150
+ if (tokenIn === "Unknown") {
1151
+ tokenIn = this.truncate(wsolMint, 5, 4);
1152
+ }
1153
+ }
1154
+ this.instructions.push({
1155
+ type: "JupiterSwap",
1156
+ details: {
1157
+ inAmount,
1158
+ outAmount,
1159
+ tokenIn,
1160
+ tokenOut
1161
+ }
1162
+ });
1163
+ }
1164
+ parseTokenAccountData(data) {
1165
+ try {
1166
+ if (data.length < 146) {
1167
+ throw new Error(`Invalid token account data length: ${data.length}`);
1168
+ }
1169
+ const mint = new import_web3.PublicKey(data.slice(0, 32));
1170
+ const owner = new import_web3.PublicKey(data.slice(32, 64));
1171
+ const amount = new import_bn.default(data.slice(64, 72), "le");
1172
+ const delegate = data.slice(72, 104).every((b) => b === 0) ? null : new import_web3.PublicKey(data.slice(72, 104));
1173
+ const state = data[104];
1174
+ const isNative = data[105] === 1;
1175
+ const delegatedAmount = new import_bn.default(data.slice(106, 114), "le");
1176
+ const closeAuthority = data.slice(114, 146).every((b) => b === 0) ? null : new import_web3.PublicKey(data.slice(114, 146));
1177
+ return {
1178
+ mint,
1179
+ owner,
1180
+ amount,
1181
+ delegate,
1182
+ state,
1183
+ isNative,
1184
+ delegatedAmount,
1185
+ closeAuthority
1186
+ };
1187
+ } catch (error) {
1188
+ console.error("Error parsing token account data:", error);
1189
+ throw error;
1190
+ }
1191
+ }
1192
+ formatTokenAmount(amount, mint) {
1193
+ const wsolMint = "So11111111111111111111111111111111111111112";
1194
+ if (mint.toBase58() === wsolMint) {
1195
+ return this.formatSOL(amount.toString());
1196
+ }
1197
+ return amount.toString();
1198
+ }
1199
+ formatSOL(lamports) {
1200
+ try {
1201
+ const bn = new import_bn.default(lamports);
1202
+ const divisor = new import_bn.default(1e9);
1203
+ const sol = bn.div(divisor);
1204
+ const remainder = bn.mod(divisor);
1205
+ const decStr = remainder.toString().padStart(9, "0");
1206
+ const trimmed = decStr.replace(/0+$/, "");
1207
+ if (trimmed.length === 0) {
1208
+ return `${sol.toString()} SOL`;
1209
+ }
1210
+ return `${sol.toString()}.${trimmed} SOL`;
1211
+ } catch {
1212
+ return `${lamports} lamports`;
1213
+ }
1214
+ }
1215
+ truncate(address, start = 5, end = 4) {
1216
+ if (!address || address.length <= start + end) return address;
1217
+ return `${address.slice(0, start)}...${address.slice(-end)}`;
1218
+ }
1219
+ getInstructions() {
1220
+ return this.instructions;
1221
+ }
1222
+ getInstructionsByType(type) {
1223
+ return this.instructions.filter((i) => i.type === type);
1224
+ }
1225
+ };
1226
+ async function getInstructionsForHTML(base64Transaction, logs, connection, userPublicKey) {
1227
+ const parser = new SolanaTransactionParser(logs, base64Transaction, connection, userPublicKey);
1228
+ const instructions = await parser.parse();
1229
+ return instructions.map((instruction, index) => {
1230
+ const details = [];
1231
+ switch (instruction.type) {
1232
+ case "ComputeBudget":
1233
+ details.push(
1234
+ { label: "Program ID", value: instruction.details.programId },
1235
+ { label: "Data", value: instruction.details.data.toString() }
1236
+ );
1237
+ return {
1238
+ id: `${instruction.type}-${index}`,
1239
+ type: instruction.type,
1240
+ title: "",
1241
+ details
1242
+ };
1243
+ case "CreateTokenAccount":
1244
+ details.push(
1245
+ { label: "Program ID", value: instruction.details.programId },
1246
+ { label: "Owner", value: instruction.details.owner }
1247
+ );
1248
+ return {
1249
+ id: `${instruction.type}-${index}`,
1250
+ type: instruction.type,
1251
+ title: "Create token account",
1252
+ details
1253
+ };
1254
+ case "Transfer":
1255
+ details.push(
1256
+ { label: "Amount", value: instruction.details.amount },
1257
+ { label: "Destination", value: instruction.details.destination }
1258
+ );
1259
+ return {
1260
+ id: `${instruction.type}-${index}`,
1261
+ type: instruction.type,
1262
+ title: "Transfer",
1263
+ details
1264
+ };
1265
+ case "SyncNative":
1266
+ details.push(
1267
+ { label: "Program ID", value: instruction.details.programId }
1268
+ );
1269
+ return {
1270
+ id: `${instruction.type}-${index}`,
1271
+ type: instruction.type,
1272
+ title: "Sync native",
1273
+ details
1274
+ };
1275
+ case "JupiterSwap":
1276
+ details.push(
1277
+ { label: "in amount", value: instruction.details.inAmount },
1278
+ { label: "out amount", value: instruction.details.outAmount },
1279
+ { label: "Token in", value: instruction.details.tokenIn },
1280
+ { label: "Token out", value: instruction.details.tokenOut }
1281
+ );
1282
+ return {
1283
+ id: `${instruction.type}-${index}`,
1284
+ type: instruction.type,
1285
+ title: "Jupiter swap",
1286
+ details
1287
+ };
1288
+ case "CloseAccount":
1289
+ details.push(
1290
+ { label: "Source", value: instruction.details.source },
1291
+ { label: "Destination", value: instruction.details.destination },
1292
+ { label: "Owner", value: instruction.details.owner }
1293
+ );
1294
+ return {
1295
+ id: `${instruction.type}-${index}`,
1296
+ type: instruction.type,
1297
+ title: "Close token account",
1298
+ details
1299
+ };
1300
+ case "Unknown":
1301
+ details.push(
1302
+ { label: "Program ID", value: instruction.details.programId },
1303
+ { label: "Instruction Type", value: instruction.details.instructionType.toString() },
1304
+ { label: "Data Length", value: instruction.details.dataLength.toString() },
1305
+ { label: "Account Count", value: instruction.details.accountCount.toString() },
1306
+ { label: "Raw Data", value: instruction.details.rawData },
1307
+ { label: "Accounts", value: instruction.details.accounts.join(", ") }
1308
+ );
1309
+ return {
1310
+ id: `${instruction.type}-${index}`,
1311
+ type: instruction.type,
1312
+ title: "Unknown instruction",
1313
+ details
1314
+ };
1315
+ default:
1316
+ return {
1317
+ id: `${instruction.type}-${index}`,
1318
+ type: instruction.type,
1319
+ title: instruction.type,
1320
+ details: Object.entries(instruction.details).map(([key, value]) => ({
1321
+ label: key,
1322
+ value: String(value)
1323
+ }))
1324
+ };
1325
+ }
1326
+ });
1327
+ }
1328
+ async function getTransferInfoFromInstructions(base64Transaction, logs, solPriceUsd) {
1329
+ const transfers = [];
1330
+ try {
1331
+ const parser = new SolanaTransactionParser(logs, base64Transaction);
1332
+ const instructions = await parser.parse();
1333
+ for (const instruction of instructions) {
1334
+ if (instruction.type === "Transfer") {
1335
+ let usdValue;
1336
+ if (solPriceUsd && instruction.details.amount.includes("SOL")) {
1337
+ const solAmountMatch = instruction.details.amount.match(/(\d+(?:\.\d+)?)\s*SOL/);
1338
+ if (solAmountMatch) {
1339
+ const solAmount = parseFloat(solAmountMatch[1]);
1340
+ const usdPrice = parseFloat(solPriceUsd);
1341
+ const usdAmount = solAmount * usdPrice;
1342
+ usdValue = `$${usdAmount.toFixed(2)}`;
1343
+ }
1344
+ }
1345
+ transfers.push({
1346
+ amount: instruction.details.amount,
1347
+ destination: instruction.details.destination,
1348
+ type: "SOL",
1349
+ usdValue
1350
+ });
1351
+ } else if (instruction.type === "JupiterSwap") {
1352
+ if (instruction.details.inAmount && instruction.details.outAmount) {
1353
+ let usdValue;
1354
+ if (solPriceUsd && instruction.details.inAmount.includes("SOL")) {
1355
+ const solAmountMatch = instruction.details.inAmount.match(/(\d+(?:\.\d+)?)\s*SOL/);
1356
+ if (solAmountMatch) {
1357
+ const solAmount = parseFloat(solAmountMatch[1]);
1358
+ const usdPrice = parseFloat(solPriceUsd);
1359
+ const usdAmount = solAmount * usdPrice;
1360
+ usdValue = `$${usdAmount.toFixed(2)}`;
1361
+ }
1362
+ }
1363
+ transfers.push({
1364
+ amount: instruction.details.inAmount,
1365
+ destination: "Jupiter Swap",
1366
+ type: "SOL",
1367
+ usdValue
1368
+ });
1369
+ }
1370
+ }
1371
+ }
1372
+ } catch (error) {
1373
+ console.error("Error parsing instructions for transfers:", error);
1374
+ }
1375
+ return transfers;
1376
+ }
1377
+ async function getSOLTransfersFromInstructions(base64Transaction, logs, solPriceUsd) {
1378
+ const transfers = [];
1379
+ try {
1380
+ const parser = new SolanaTransactionParser(logs, base64Transaction);
1381
+ const instructions = await parser.parse();
1382
+ for (const instruction of instructions) {
1383
+ if (instruction.type === "Transfer") {
1384
+ const amountStr = instruction.details.amount;
1385
+ const lamportsMatch = amountStr.match(/(\d+(?:\.\d+)?)\s*SOL/);
1386
+ const lamports = lamportsMatch ? Math.floor(parseFloat(lamportsMatch[1]) * 1e9).toString() : "0";
1387
+ let usdValue;
1388
+ if (solPriceUsd && lamportsMatch) {
1389
+ const solAmount = parseFloat(lamportsMatch[1]);
1390
+ const usdPrice = parseFloat(solPriceUsd);
1391
+ const usdAmount = solAmount * usdPrice;
1392
+ usdValue = `$${usdAmount.toFixed(2)}`;
1393
+ }
1394
+ transfers.push({
1395
+ amount: instruction.details.amount,
1396
+ destination: instruction.details.destination,
1397
+ lamports,
1398
+ usdValue
1399
+ });
1400
+ }
1401
+ }
1402
+ } catch (error) {
1403
+ console.error("Error parsing instructions for SOL transfers:", error);
1404
+ }
1405
+ return transfers;
1406
+ }
1407
+
1408
+ // src/lib/build-url.ts
1409
+ var buildUrl = (baseUrl, sdkConfig, enableCaptcha, captchaSitekey) => {
1410
+ if (!sdkConfig.publishableKey) {
1411
+ throw new Error("MoonKey SDK Error: Publishable Key is required");
1412
+ }
1413
+ if (!baseUrl || typeof baseUrl !== "string" || baseUrl === "null" || baseUrl === "undefined") {
1414
+ console.error("Invalid baseUrl:", baseUrl);
1415
+ throw new Error(
1416
+ `MoonKey SDK Error: Invalid base URL provided: "${baseUrl}"`
1417
+ );
1418
+ }
1419
+ if (typeof window === "undefined") {
1420
+ const params = new URLSearchParams();
1421
+ params.append("publishableKey", sdkConfig.publishableKey);
1422
+ const hideClose = sdkConfig.config?.appearance?.hideClose;
1423
+ if (hideClose === true) {
1424
+ params.append("hideClose", "true");
1425
+ }
1426
+ if (enableCaptcha) {
1427
+ params.append("enableCaptcha", "true");
1428
+ }
1429
+ if (captchaSitekey) {
1430
+ params.append("captchaSitekey", captchaSitekey);
1431
+ }
1432
+ return `${baseUrl}?${params.toString()}`;
1433
+ }
1434
+ try {
1435
+ const url = new URL(baseUrl);
1436
+ url.searchParams.append("publishableKey", sdkConfig.publishableKey);
1437
+ const hideClose = sdkConfig.config?.appearance?.hideClose;
1438
+ if (hideClose === true) {
1439
+ url.searchParams.append("hideClose", "true");
1440
+ }
1441
+ if (enableCaptcha) {
1442
+ url.searchParams.append("enableCaptcha", "true");
1443
+ }
1444
+ if (captchaSitekey) {
1445
+ url.searchParams.append("captchaSitekey", captchaSitekey);
1446
+ }
1447
+ return url.toString();
1448
+ } catch (error) {
1449
+ throw new Error(
1450
+ `MoonKey SDK Error: Invalid base URL "${baseUrl}": ${error instanceof Error ? error.message : "Unknown error"}`
1451
+ );
1452
+ }
1453
+ };
1454
+
1455
+ // src/lib/constants.ts
1456
+ var DEFAULT_AUTH_URL = "https://iframe.moonx-dev.com";
1457
+
1458
+ // src/lib/rpc-broadcast.ts
1459
+ var serializeEthereumTransaction = async (transaction) => {
1460
+ if (typeof transaction === "string") {
1461
+ return transaction;
1462
+ }
1463
+ if (!transaction || typeof transaction !== "object") {
1464
+ throw new Error("ethereum_transaction_invalid");
1465
+ }
1466
+ const { serializeTransaction: serializeTransaction2, parseEther: parseEther3, parseGwei: parseGwei2 } = await import("viem");
1467
+ const toWei = (val, humanUnit) => {
1468
+ if (val == null || val === "") return BigInt(0);
1469
+ if (typeof val === "bigint") return val;
1470
+ if (typeof val === "number") return BigInt(val);
1471
+ if (typeof val === "string") {
1472
+ if (val.startsWith("0x")) return BigInt(val);
1473
+ if (val.includes(".")) {
1474
+ return humanUnit === "ether" ? parseEther3(val) : parseGwei2(val);
1475
+ }
1476
+ return BigInt(val);
1477
+ }
1478
+ return BigInt(val);
1479
+ };
1480
+ const formatted = {
1481
+ to: transaction.to,
1482
+ value: toWei(transaction.value, "ether"),
1483
+ data: transaction.data || "0x",
1484
+ chainId: transaction.chainId || 1,
1485
+ type: "eip1559",
1486
+ maxPriorityFeePerGas: transaction.maxPriorityFeePerGas ? toWei(transaction.maxPriorityFeePerGas, "gwei") : BigInt(2e9),
1487
+ maxFeePerGas: transaction.maxFeePerGas ? toWei(transaction.maxFeePerGas, "gwei") : BigInt(22e9),
1488
+ ...transaction.nonce && { nonce: Number(transaction.nonce) },
1489
+ ...transaction.gas && { gas: BigInt(transaction.gas) }
1490
+ };
1491
+ return serializeTransaction2(formatted);
1492
+ };
1493
+ var broadcastEthereumRaw = async (rpcUrl, signedSerialized) => {
1494
+ const controller = new AbortController();
1495
+ const timeoutId = setTimeout(() => controller.abort(), 3e4);
1496
+ try {
1497
+ const response = await fetch(rpcUrl, {
1498
+ method: "POST",
1499
+ headers: { "Content-Type": "application/json" },
1500
+ body: JSON.stringify({
1501
+ jsonrpc: "2.0",
1502
+ id: 1,
1503
+ method: "eth_sendRawTransaction",
1504
+ params: [signedSerialized]
1505
+ }),
1506
+ signal: controller.signal
1507
+ });
1508
+ const result = await response.json();
1509
+ if (result.error) {
1510
+ throw new Error(result.error.message || "eth_sendRawTransaction failed");
1511
+ }
1512
+ return result.result;
1513
+ } catch (error) {
1514
+ if (error instanceof Error && error.name === "AbortError") {
1515
+ throw new Error("RPC request timed out after 30 seconds");
1516
+ }
1517
+ throw error;
1518
+ } finally {
1519
+ clearTimeout(timeoutId);
1520
+ }
1521
+ };
1522
+ var broadcastSolanaSigned = async (rpcUrl, signedBase58) => {
1523
+ const { default: bs58 } = await import("bs58");
1524
+ const transactionBytes = bs58.decode(signedBase58);
1525
+ const base64Transaction = Buffer.from(transactionBytes).toString("base64");
1526
+ const response = await fetch(rpcUrl, {
1527
+ method: "POST",
1528
+ headers: { "Content-Type": "application/json" },
1529
+ body: JSON.stringify({
1530
+ jsonrpc: "2.0",
1531
+ id: 1,
1532
+ method: "sendTransaction",
1533
+ params: [
1534
+ base64Transaction,
1535
+ {
1536
+ encoding: "base64",
1537
+ skipPreflight: false,
1538
+ preflightCommitment: "confirmed",
1539
+ maxRetries: 3
1540
+ }
1541
+ ]
1542
+ })
1543
+ });
1544
+ const result = await response.json();
1545
+ if (result.error) {
1546
+ throw new Error(`Solana RPC error: ${result.error.message}`);
1547
+ }
1548
+ return result.result;
1549
+ };
1550
+
1551
+ // src/lib/wire-codec.ts
1552
+ var arrayLikeToBytes = (value) => {
1553
+ if (value instanceof Uint8Array) return value;
1554
+ if (Array.isArray(value)) return new Uint8Array(value);
1555
+ if (value && typeof value === "object") {
1556
+ const keys = Object.keys(value);
1557
+ if (keys.length === 0) return new Uint8Array();
1558
+ if (keys.every((k) => /^\d+$/.test(k))) {
1559
+ const len = keys.length;
1560
+ const out = new Uint8Array(len);
1561
+ for (let i = 0; i < len; i++) {
1562
+ out[i] = value[String(i)] ?? 0;
1563
+ }
1564
+ return out;
1565
+ }
1566
+ }
1567
+ throw new Error(`arrayLikeToBytes: unsupported shape (${typeof value})`);
1568
+ };
1569
+ var bs58ToBytes = async (value) => {
1570
+ if (value instanceof Uint8Array) return value;
1571
+ if (Array.isArray(value)) return new Uint8Array(value);
1572
+ if (typeof value === "string") {
1573
+ const { default: bs58 } = await import("bs58");
1574
+ return bs58.decode(value);
1575
+ }
1576
+ return arrayLikeToBytes(value);
1577
+ };
1578
+ // Annotate the CommonJS export names for ESM import in node:
1579
+ 0 && (module.exports = {
1580
+ DEFAULT_AUTH_URL,
1581
+ EthereumSiweMessage,
1582
+ SiwsMessage,
1583
+ SolanaTransactionParser,
1584
+ arrayLikeToBytes,
1585
+ authState,
1586
+ broadcastEthereumRaw,
1587
+ broadcastSolanaSigned,
1588
+ bs58ToBytes,
1589
+ buildUrl,
1590
+ clearParentAssertCache,
1591
+ createManualSiweMessage,
1592
+ estimateEvmGas,
1593
+ estimateEvmGasReserve,
1594
+ formatPasskeyLabel,
1595
+ fromB64url,
1596
+ generatePasskeyUserId,
1597
+ getAssertCacheTtlMs,
1598
+ getChainById,
1599
+ getDefaultChain,
1600
+ getEvmGasPrice,
1601
+ getEvmMaxPriorityFeePerGas,
1602
+ getEvmNonce,
1603
+ getInstructionsForHTML,
1604
+ getRpcUrl,
1605
+ getSOLTransfersFromInstructions,
1606
+ getTransferInfoFromInstructions,
1607
+ isChainSupported,
1608
+ prepareEvmSendTransaction,
1609
+ prepareEvmSignTransaction,
1610
+ readParentAssertCache,
1611
+ resolveEvmChain,
1612
+ resolvePasskeyMetadata,
1613
+ sanitizeUserData,
1614
+ serializeEthereumTransaction,
1615
+ setAssertCacheTtlMs,
1616
+ setChainRpcUrl,
1617
+ toB64url,
1618
+ validateChainConfig,
1619
+ verifyIdToken,
1620
+ withClearOnFailure,
1621
+ writeParentAssertCache
1622
+ });