@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,470 @@
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/web/index.ts
31
+ var web_exports = {};
32
+ __export(web_exports, {
33
+ createIframeTransport: () => createIframeTransport,
34
+ createLocalStorageKv: () => createLocalStorageKv,
35
+ createWebAuthnPasskey: () => createWebAuthnPasskey,
36
+ getCachedPostMessageClient: () => getCachedPostMessageClient
37
+ });
38
+ module.exports = __toCommonJS(web_exports);
39
+
40
+ // src/utils/post-message.ts
41
+ var FORWARDED_ERROR_FIELDS = [
42
+ "error_type",
43
+ "error_code",
44
+ "status_code"
45
+ ];
46
+ var generateUUID = () => {
47
+ if (typeof crypto !== "undefined" && crypto.randomUUID) {
48
+ return crypto.randomUUID();
49
+ }
50
+ return "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, (c) => {
51
+ const r = Math.random() * 16 | 0;
52
+ const v = c === "x" ? r : r & 3 | 8;
53
+ return v.toString(16);
54
+ });
55
+ };
56
+ var PostMessageClient = class {
57
+ constructor(target, origin = "*") {
58
+ this.target = target;
59
+ this.origin = origin;
60
+ }
61
+ async send(type, method, payload) {
62
+ const id = generateUUID();
63
+ return new Promise((resolve, reject) => {
64
+ const timeout = setTimeout(() => {
65
+ window.removeEventListener("message", handler);
66
+ reject(new Error("Timeout: No response from iframe"));
67
+ }, 3e4);
68
+ const handler = (event) => {
69
+ if (this.origin !== "*" && event.origin !== this.origin) {
70
+ return;
71
+ }
72
+ const response = event.data;
73
+ if (response.id === id) {
74
+ clearTimeout(timeout);
75
+ window.removeEventListener("message", handler);
76
+ if (response.success) {
77
+ resolve(response.data);
78
+ } else {
79
+ const err = new Error(response.error);
80
+ for (const key of FORWARDED_ERROR_FIELDS) {
81
+ const value = response[key];
82
+ if (value !== void 0) {
83
+ err[key] = value;
84
+ }
85
+ }
86
+ reject(err);
87
+ }
88
+ }
89
+ };
90
+ window.addEventListener("message", handler);
91
+ this.target.postMessage(
92
+ {
93
+ id,
94
+ type,
95
+ method,
96
+ payload
97
+ },
98
+ this.origin
99
+ );
100
+ });
101
+ }
102
+ async sendOneWay(type, method, payload) {
103
+ const id = generateUUID();
104
+ const envelope = {
105
+ id,
106
+ type,
107
+ method,
108
+ payload
109
+ };
110
+ if (typeof window !== "undefined" && typeof window.ReactNativeWebView !== "undefined") {
111
+ try {
112
+ window.ReactNativeWebView.postMessage(JSON.stringify(envelope));
113
+ } catch {
114
+ }
115
+ return;
116
+ }
117
+ this.target.postMessage(envelope, this.origin);
118
+ }
119
+ };
120
+ var isReactNativeWebView = () => typeof window !== "undefined" && typeof window.ReactNativeWebView !== "undefined";
121
+ var sendReactNativeReply = (response) => {
122
+ try {
123
+ window.ReactNativeWebView.postMessage(JSON.stringify(response));
124
+ } catch {
125
+ }
126
+ };
127
+ var PostMessageServer = class {
128
+ constructor(originValidator) {
129
+ this.trustedSources = /* @__PURE__ */ new Set();
130
+ this.handlers = /* @__PURE__ */ new Map();
131
+ this.originValidator = originValidator;
132
+ window.addEventListener("message", this.handleMessage.bind(this));
133
+ }
134
+ addTrustedSource(source) {
135
+ this.trustedSources.add(source);
136
+ }
137
+ removeTrustedSource(source) {
138
+ this.trustedSources.delete(source);
139
+ }
140
+ register(type, method, handler) {
141
+ const key = `${type}:${method}`;
142
+ this.handlers.set(key, handler);
143
+ }
144
+ cleanup() {
145
+ window.removeEventListener("message", this.handleMessage.bind(this));
146
+ this.handlers.clear();
147
+ }
148
+ static isLocalhostOrigin(origin) {
149
+ try {
150
+ const url = new URL(origin);
151
+ return url.hostname === "localhost" || url.hostname === "127.0.0.1" || url.hostname === "[::1]";
152
+ } catch {
153
+ return false;
154
+ }
155
+ }
156
+ isValidPostMessageRequest(data) {
157
+ return data && typeof data === "object" && typeof data.id === "string" && typeof data.type === "string" && typeof data.method === "string";
158
+ }
159
+ async handleMessage(event) {
160
+ if (!this.isValidPostMessageRequest(event.data)) {
161
+ return;
162
+ }
163
+ if (!event.origin || event.origin === "null") {
164
+ console.error("[PostMessageServer] Invalid or null origin received");
165
+ return;
166
+ }
167
+ const request = event.data;
168
+ const rnMode = isReactNativeWebView();
169
+ const reply = (response) => {
170
+ if (rnMode) {
171
+ sendReactNativeReply(response);
172
+ return;
173
+ }
174
+ if (event.source && event.origin) {
175
+ event.source.postMessage(response, { targetOrigin: event.origin });
176
+ }
177
+ };
178
+ if (this.originValidator && !rnMode) {
179
+ const publishableKey = request.payload?.publishableKey;
180
+ try {
181
+ const isAllowed = await this.originValidator(
182
+ event.origin,
183
+ publishableKey
184
+ );
185
+ if (!isAllowed) {
186
+ reply({
187
+ id: request.id,
188
+ type: request.type,
189
+ success: false,
190
+ error: `Origin ${event.origin} is not whitelisted. Please add it to your MoonKey dashboard.`
191
+ });
192
+ return;
193
+ }
194
+ } catch (error) {
195
+ reply({
196
+ id: request.id,
197
+ type: request.type,
198
+ success: false,
199
+ error: "Origin validation failed"
200
+ });
201
+ return;
202
+ }
203
+ }
204
+ const key = `${request.type}:${request.method}`;
205
+ const handler = this.handlers.get(key);
206
+ if (handler) {
207
+ try {
208
+ const data = await handler(request.payload);
209
+ reply({
210
+ id: request.id,
211
+ type: request.type,
212
+ success: true,
213
+ data
214
+ });
215
+ } catch (error) {
216
+ const extras = {};
217
+ if (error && typeof error === "object") {
218
+ for (const key2 of FORWARDED_ERROR_FIELDS) {
219
+ const value = error[key2];
220
+ if (value !== void 0) extras[key2] = value;
221
+ }
222
+ }
223
+ reply({
224
+ ...extras,
225
+ id: request.id,
226
+ type: request.type,
227
+ success: false,
228
+ error: error instanceof Error ? error.message : "Unknown error"
229
+ });
230
+ }
231
+ }
232
+ }
233
+ };
234
+
235
+ // src/utils/get-iframe-url.ts
236
+ var DEFAULT_IFRAME_PROJECT_NAME = "moonx-wallet-iframe";
237
+ var joinUrl = (baseUrl, path) => {
238
+ if (!path) return baseUrl;
239
+ const normalizedBase = baseUrl.replace(/\/$/, "");
240
+ const normalizedPath = path.startsWith("/") ? path : `/${path}`;
241
+ return `${normalizedBase}${normalizedPath}`;
242
+ };
243
+ var withBypass = (url) => {
244
+ const bypass = process.env.NEXT_PUBLIC_VERCEL_PROTECTION_BYPASS;
245
+ if (!bypass) return url;
246
+ const separator = url.includes("?") ? "&" : "?";
247
+ return `${url}${separator}x-vercel-protection-bypass=${bypass}&x-vercel-set-bypass-cookie=samesitenone`;
248
+ };
249
+ var getIframeUrl = (path = "") => {
250
+ if (process.env.NEXT_PUBLIC_VERCEL_ENV === "preview" && process.env.NEXT_PUBLIC_VERCEL_BRANCH_URL) {
251
+ const vercelUrl = process.env.NEXT_PUBLIC_VERCEL_BRANCH_URL.replace(
252
+ /^https?:\/\//,
253
+ ""
254
+ ).replace(/\/$/, "");
255
+ const iframeProjectName = process.env.NEXT_PUBLIC_MOONKEY_IFRAME_PROJECT_NAME || DEFAULT_IFRAME_PROJECT_NAME;
256
+ const iframeUrl = /-git-/.test(vercelUrl) ? vercelUrl.replace(/^[^.]+?-git-/, `${iframeProjectName}-git-`) : (
257
+ // Fallback: legacy `{prefix}-{hash}.vercel.app` style
258
+ vercelUrl.replace(/^[^-]+-/, `${iframeProjectName}-`)
259
+ );
260
+ return withBypass(joinUrl(`https://${iframeUrl}`, path));
261
+ }
262
+ if (process.env.NEXT_PUBLIC_MOONKEY_IFRAME_URL) {
263
+ return joinUrl(process.env.NEXT_PUBLIC_MOONKEY_IFRAME_URL, path);
264
+ }
265
+ return joinUrl("https://iframe.moonx-dev.com", path);
266
+ };
267
+ var getIframeOrigin = (url) => {
268
+ try {
269
+ const urlObj = new URL(url);
270
+ return urlObj.origin;
271
+ } catch (error) {
272
+ console.error("Invalid URL:", url);
273
+ return "";
274
+ }
275
+ };
276
+
277
+ // src/web/iframe-transport.ts
278
+ var clientCache = /* @__PURE__ */ new WeakMap();
279
+ var getCachedPostMessageClient = (contentWindow) => {
280
+ const iframeUrl = getIframeUrl();
281
+ const iframeOrigin = getIframeOrigin(iframeUrl);
282
+ let perTarget = clientCache.get(contentWindow);
283
+ if (!perTarget) {
284
+ perTarget = /* @__PURE__ */ new Map();
285
+ clientCache.set(contentWindow, perTarget);
286
+ }
287
+ let client = perTarget.get(iframeOrigin);
288
+ if (!client) {
289
+ client = new PostMessageClient(contentWindow, iframeOrigin);
290
+ perTarget.set(iframeOrigin, client);
291
+ }
292
+ return client;
293
+ };
294
+ var createIframeTransport = ({
295
+ getContentWindow,
296
+ isReady
297
+ }) => ({
298
+ send: async (type, method, payload) => {
299
+ const contentWindow = getContentWindow();
300
+ if (!contentWindow) throw new Error("iframe_not_ready");
301
+ const client = getCachedPostMessageClient(contentWindow);
302
+ return client.send(type, method, payload);
303
+ },
304
+ register: (type, method, handler) => {
305
+ const server = new PostMessageServer();
306
+ server.register(type, method, async (payload) => handler(payload));
307
+ return () => {
308
+ };
309
+ },
310
+ isReady
311
+ });
312
+
313
+ // src/lib/auth/authentication-state.ts
314
+ var AuthenticationState = class {
315
+ constructor() {
316
+ this.email = null;
317
+ }
318
+ setEmail(email) {
319
+ this.email = email;
320
+ }
321
+ getEmail() {
322
+ return this.email;
323
+ }
324
+ clearEmail() {
325
+ this.email = null;
326
+ }
327
+ clear() {
328
+ this.clearEmail();
329
+ }
330
+ };
331
+ var authState = new AuthenticationState();
332
+
333
+ // src/lib/passkey/passkey-codec.ts
334
+ var fromB64url = (b64url) => {
335
+ const base64 = b64url.replace(/-/g, "+").replace(/_/g, "/");
336
+ const padded = base64 + "=".repeat((4 - base64.length % 4) % 4);
337
+ const binary = atob(padded);
338
+ const bytes = new Uint8Array(binary.length);
339
+ for (let i = 0; i < binary.length; i++) bytes[i] = binary.charCodeAt(i);
340
+ return bytes;
341
+ };
342
+ var toB64url = (bytes) => {
343
+ let str = "";
344
+ for (let i = 0; i < bytes.length; i++) str += String.fromCharCode(bytes[i]);
345
+ return btoa(str).replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/, "");
346
+ };
347
+
348
+ // src/lib/ethereum/chains.ts
349
+ var import_viem = require("viem");
350
+
351
+ // src/lib/ethereum/siwe.ts
352
+ var import_siwe = require("siwe");
353
+ var import_viem2 = require("viem");
354
+
355
+ // src/lib/ethereum/tx-prep.ts
356
+ var import_viem3 = require("viem");
357
+
358
+ // src/lib/solana/siws.ts
359
+ var nacl = __toESM(require("tweetnacl"));
360
+
361
+ // src/lib/solana/transaction-log-parser.ts
362
+ var import_web3 = require("@solana/web3.js");
363
+ var import_bn = __toESM(require("bn.js"));
364
+
365
+ // src/web/webauthn-passkey.ts
366
+ var createWebAuthnPasskey = () => ({
367
+ assert: async ({ rpId, challenge }) => {
368
+ const challengeBytes = fromB64url(challenge);
369
+ const credential = await navigator.credentials.get({
370
+ publicKey: {
371
+ challenge: challengeBytes,
372
+ rpId,
373
+ userVerification: "preferred",
374
+ // Empty allowCredentials → discoverable login → userHandle is
375
+ // REQUIRED on the response. See `parent-passkey-assert.ts`
376
+ // for the full rationale.
377
+ allowCredentials: []
378
+ }
379
+ });
380
+ if (!credential) throw new Error("passkey_assertion_cancelled");
381
+ const assertion = credential.response;
382
+ if (!assertion.userHandle) {
383
+ throw new Error("user_handle_missing");
384
+ }
385
+ return {
386
+ rawIdB64url: toB64url(new Uint8Array(credential.rawId)),
387
+ userHandleB64url: toB64url(new Uint8Array(assertion.userHandle))
388
+ };
389
+ },
390
+ create: async ({
391
+ rpId,
392
+ rpName,
393
+ userId,
394
+ userName,
395
+ userDisplayName,
396
+ challenge,
397
+ excludeCredentials
398
+ }) => {
399
+ const challengeBytes = fromB64url(challenge);
400
+ const credential = await navigator.credentials.create({
401
+ publicKey: {
402
+ rp: { id: rpId, name: rpName },
403
+ user: {
404
+ id: userId,
405
+ name: userName,
406
+ displayName: userDisplayName
407
+ },
408
+ challenge: challengeBytes,
409
+ pubKeyCredParams: [
410
+ { type: "public-key", alg: -7 },
411
+ // ES256
412
+ { type: "public-key", alg: -257 }
413
+ // RS256
414
+ ],
415
+ authenticatorSelection: {
416
+ residentKey: "required",
417
+ userVerification: "preferred"
418
+ },
419
+ excludeCredentials: (excludeCredentials ?? []).map((id) => ({
420
+ id: fromB64url(id),
421
+ type: "public-key"
422
+ }))
423
+ }
424
+ });
425
+ if (!credential) throw new Error("passkey_registration_cancelled");
426
+ const attestation = credential.response;
427
+ return {
428
+ rawIdB64url: toB64url(new Uint8Array(credential.rawId)),
429
+ clientDataJSONB64url: toB64url(new Uint8Array(attestation.clientDataJSON)),
430
+ attestationObjectB64url: toB64url(
431
+ new Uint8Array(attestation.attestationObject)
432
+ )
433
+ };
434
+ }
435
+ });
436
+
437
+ // src/web/local-storage-kv.ts
438
+ var createLocalStorageKv = (prefix = "moonkey:") => ({
439
+ get: async (key) => {
440
+ if (typeof window === "undefined") return null;
441
+ try {
442
+ return localStorage.getItem(prefix + key);
443
+ } catch {
444
+ return null;
445
+ }
446
+ },
447
+ set: async (key, value) => {
448
+ if (typeof window === "undefined") return;
449
+ try {
450
+ localStorage.setItem(prefix + key, value);
451
+ } catch (error) {
452
+ console.error("LocalStorageKv.set failed:", error);
453
+ }
454
+ },
455
+ remove: async (key) => {
456
+ if (typeof window === "undefined") return;
457
+ try {
458
+ localStorage.removeItem(prefix + key);
459
+ } catch (error) {
460
+ console.error("LocalStorageKv.remove failed:", error);
461
+ }
462
+ }
463
+ });
464
+ // Annotate the CommonJS export names for ESM import in node:
465
+ 0 && (module.exports = {
466
+ createIframeTransport,
467
+ createLocalStorageKv,
468
+ createWebAuthnPasskey,
469
+ getCachedPostMessageClient
470
+ });
@@ -0,0 +1,155 @@
1
+ import {
2
+ getIframeOrigin,
3
+ getIframeUrl
4
+ } from "../chunk-264CEGDS.mjs";
5
+ import {
6
+ PostMessageClient,
7
+ PostMessageServer
8
+ } from "../chunk-SOKLPX7V.mjs";
9
+ import {
10
+ fromB64url,
11
+ toB64url
12
+ } from "../chunk-CDT4MC7S.mjs";
13
+ import "../chunk-GQKIA37O.mjs";
14
+
15
+ // src/web/iframe-transport.ts
16
+ var clientCache = /* @__PURE__ */ new WeakMap();
17
+ var getCachedPostMessageClient = (contentWindow) => {
18
+ const iframeUrl = getIframeUrl();
19
+ const iframeOrigin = getIframeOrigin(iframeUrl);
20
+ let perTarget = clientCache.get(contentWindow);
21
+ if (!perTarget) {
22
+ perTarget = /* @__PURE__ */ new Map();
23
+ clientCache.set(contentWindow, perTarget);
24
+ }
25
+ let client = perTarget.get(iframeOrigin);
26
+ if (!client) {
27
+ client = new PostMessageClient(contentWindow, iframeOrigin);
28
+ perTarget.set(iframeOrigin, client);
29
+ }
30
+ return client;
31
+ };
32
+ var createIframeTransport = ({
33
+ getContentWindow,
34
+ isReady
35
+ }) => ({
36
+ send: async (type, method, payload) => {
37
+ const contentWindow = getContentWindow();
38
+ if (!contentWindow) throw new Error("iframe_not_ready");
39
+ const client = getCachedPostMessageClient(contentWindow);
40
+ return client.send(type, method, payload);
41
+ },
42
+ register: (type, method, handler) => {
43
+ const server = new PostMessageServer();
44
+ server.register(type, method, async (payload) => handler(payload));
45
+ return () => {
46
+ };
47
+ },
48
+ isReady
49
+ });
50
+
51
+ // src/web/webauthn-passkey.ts
52
+ var createWebAuthnPasskey = () => ({
53
+ assert: async ({ rpId, challenge }) => {
54
+ const challengeBytes = fromB64url(challenge);
55
+ const credential = await navigator.credentials.get({
56
+ publicKey: {
57
+ challenge: challengeBytes,
58
+ rpId,
59
+ userVerification: "preferred",
60
+ // Empty allowCredentials → discoverable login → userHandle is
61
+ // REQUIRED on the response. See `parent-passkey-assert.ts`
62
+ // for the full rationale.
63
+ allowCredentials: []
64
+ }
65
+ });
66
+ if (!credential) throw new Error("passkey_assertion_cancelled");
67
+ const assertion = credential.response;
68
+ if (!assertion.userHandle) {
69
+ throw new Error("user_handle_missing");
70
+ }
71
+ return {
72
+ rawIdB64url: toB64url(new Uint8Array(credential.rawId)),
73
+ userHandleB64url: toB64url(new Uint8Array(assertion.userHandle))
74
+ };
75
+ },
76
+ create: async ({
77
+ rpId,
78
+ rpName,
79
+ userId,
80
+ userName,
81
+ userDisplayName,
82
+ challenge,
83
+ excludeCredentials
84
+ }) => {
85
+ const challengeBytes = fromB64url(challenge);
86
+ const credential = await navigator.credentials.create({
87
+ publicKey: {
88
+ rp: { id: rpId, name: rpName },
89
+ user: {
90
+ id: userId,
91
+ name: userName,
92
+ displayName: userDisplayName
93
+ },
94
+ challenge: challengeBytes,
95
+ pubKeyCredParams: [
96
+ { type: "public-key", alg: -7 },
97
+ // ES256
98
+ { type: "public-key", alg: -257 }
99
+ // RS256
100
+ ],
101
+ authenticatorSelection: {
102
+ residentKey: "required",
103
+ userVerification: "preferred"
104
+ },
105
+ excludeCredentials: (excludeCredentials ?? []).map((id) => ({
106
+ id: fromB64url(id),
107
+ type: "public-key"
108
+ }))
109
+ }
110
+ });
111
+ if (!credential) throw new Error("passkey_registration_cancelled");
112
+ const attestation = credential.response;
113
+ return {
114
+ rawIdB64url: toB64url(new Uint8Array(credential.rawId)),
115
+ clientDataJSONB64url: toB64url(new Uint8Array(attestation.clientDataJSON)),
116
+ attestationObjectB64url: toB64url(
117
+ new Uint8Array(attestation.attestationObject)
118
+ )
119
+ };
120
+ }
121
+ });
122
+
123
+ // src/web/local-storage-kv.ts
124
+ var createLocalStorageKv = (prefix = "moonkey:") => ({
125
+ get: async (key) => {
126
+ if (typeof window === "undefined") return null;
127
+ try {
128
+ return localStorage.getItem(prefix + key);
129
+ } catch {
130
+ return null;
131
+ }
132
+ },
133
+ set: async (key, value) => {
134
+ if (typeof window === "undefined") return;
135
+ try {
136
+ localStorage.setItem(prefix + key, value);
137
+ } catch (error) {
138
+ console.error("LocalStorageKv.set failed:", error);
139
+ }
140
+ },
141
+ remove: async (key) => {
142
+ if (typeof window === "undefined") return;
143
+ try {
144
+ localStorage.removeItem(prefix + key);
145
+ } catch (error) {
146
+ console.error("LocalStorageKv.remove failed:", error);
147
+ }
148
+ }
149
+ });
150
+ export {
151
+ createIframeTransport,
152
+ createLocalStorageKv,
153
+ createWebAuthnPasskey,
154
+ getCachedPostMessageClient
155
+ };