@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,864 @@
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/sdk/index.ts
31
+ var sdk_exports = {};
32
+ __export(sdk_exports, {
33
+ assertPasskeyInParent: () => assertPasskeyInParent,
34
+ getHeadlessAuthenticationMethods: () => getHeadlessAuthenticationMethods,
35
+ getHeadlessEthereumMethods: () => getHeadlessEthereumMethods,
36
+ getHeadlessGeneralMethods: () => getHeadlessGeneralMethods,
37
+ getHeadlessSolanaMethods: () => getHeadlessSolanaMethods
38
+ });
39
+ module.exports = __toCommonJS(sdk_exports);
40
+
41
+ // src/lib/auth/authentication-state.ts
42
+ var AuthenticationState = class {
43
+ constructor() {
44
+ this.email = null;
45
+ }
46
+ setEmail(email) {
47
+ this.email = email;
48
+ }
49
+ getEmail() {
50
+ return this.email;
51
+ }
52
+ clearEmail() {
53
+ this.email = null;
54
+ }
55
+ clear() {
56
+ this.clearEmail();
57
+ }
58
+ };
59
+ var authState = new AuthenticationState();
60
+
61
+ // src/lib/passkey/passkey-codec.ts
62
+ var toB64url = (bytes) => {
63
+ let str = "";
64
+ for (let i = 0; i < bytes.length; i++) str += String.fromCharCode(bytes[i]);
65
+ return btoa(str).replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/, "");
66
+ };
67
+
68
+ // src/lib/passkey/passkey-cache.ts
69
+ var cacheTtlMs = 0;
70
+ var cache = null;
71
+ var clearParentAssertCache = () => {
72
+ cache = null;
73
+ };
74
+ var readParentAssertCache = () => {
75
+ if (cacheTtlMs <= 0) return null;
76
+ if (!cache) return null;
77
+ if (Date.now() - cache.ts >= cacheTtlMs) return null;
78
+ return {
79
+ userHandleB64url: cache.userHandleB64url,
80
+ credentialIdB64url: cache.credentialIdB64url
81
+ };
82
+ };
83
+ var writeParentAssertCache = (entry) => {
84
+ if (cacheTtlMs <= 0) return;
85
+ cache = { ...entry, ts: Date.now() };
86
+ };
87
+ var withClearOnFailure = async (fn) => {
88
+ try {
89
+ return await fn();
90
+ } catch (error) {
91
+ clearParentAssertCache();
92
+ throw error;
93
+ }
94
+ };
95
+
96
+ // src/lib/ethereum/chains.ts
97
+ var import_viem = require("viem");
98
+
99
+ // src/lib/ethereum/siwe.ts
100
+ var import_siwe = require("siwe");
101
+ var import_viem2 = require("viem");
102
+
103
+ // src/lib/ethereum/tx-prep.ts
104
+ var import_viem3 = require("viem");
105
+
106
+ // src/lib/solana/siws.ts
107
+ var nacl = __toESM(require("tweetnacl"));
108
+
109
+ // src/lib/solana/transaction-log-parser.ts
110
+ var import_web3 = require("@solana/web3.js");
111
+ var import_bn = __toESM(require("bn.js"));
112
+
113
+ // src/lib/rpc-broadcast.ts
114
+ var serializeEthereumTransaction = async (transaction) => {
115
+ if (typeof transaction === "string") {
116
+ return transaction;
117
+ }
118
+ if (!transaction || typeof transaction !== "object") {
119
+ throw new Error("ethereum_transaction_invalid");
120
+ }
121
+ const { serializeTransaction: serializeTransaction2, parseEther: parseEther3, parseGwei: parseGwei2 } = await import("viem");
122
+ const toWei = (val, humanUnit) => {
123
+ if (val == null || val === "") return BigInt(0);
124
+ if (typeof val === "bigint") return val;
125
+ if (typeof val === "number") return BigInt(val);
126
+ if (typeof val === "string") {
127
+ if (val.startsWith("0x")) return BigInt(val);
128
+ if (val.includes(".")) {
129
+ return humanUnit === "ether" ? parseEther3(val) : parseGwei2(val);
130
+ }
131
+ return BigInt(val);
132
+ }
133
+ return BigInt(val);
134
+ };
135
+ const formatted = {
136
+ to: transaction.to,
137
+ value: toWei(transaction.value, "ether"),
138
+ data: transaction.data || "0x",
139
+ chainId: transaction.chainId || 1,
140
+ type: "eip1559",
141
+ maxPriorityFeePerGas: transaction.maxPriorityFeePerGas ? toWei(transaction.maxPriorityFeePerGas, "gwei") : BigInt(2e9),
142
+ maxFeePerGas: transaction.maxFeePerGas ? toWei(transaction.maxFeePerGas, "gwei") : BigInt(22e9),
143
+ ...transaction.nonce && { nonce: Number(transaction.nonce) },
144
+ ...transaction.gas && { gas: BigInt(transaction.gas) }
145
+ };
146
+ return serializeTransaction2(formatted);
147
+ };
148
+ var broadcastEthereumRaw = async (rpcUrl, signedSerialized) => {
149
+ const controller = new AbortController();
150
+ const timeoutId = setTimeout(() => controller.abort(), 3e4);
151
+ try {
152
+ const response = await fetch(rpcUrl, {
153
+ method: "POST",
154
+ headers: { "Content-Type": "application/json" },
155
+ body: JSON.stringify({
156
+ jsonrpc: "2.0",
157
+ id: 1,
158
+ method: "eth_sendRawTransaction",
159
+ params: [signedSerialized]
160
+ }),
161
+ signal: controller.signal
162
+ });
163
+ const result = await response.json();
164
+ if (result.error) {
165
+ throw new Error(result.error.message || "eth_sendRawTransaction failed");
166
+ }
167
+ return result.result;
168
+ } catch (error) {
169
+ if (error instanceof Error && error.name === "AbortError") {
170
+ throw new Error("RPC request timed out after 30 seconds");
171
+ }
172
+ throw error;
173
+ } finally {
174
+ clearTimeout(timeoutId);
175
+ }
176
+ };
177
+ var broadcastSolanaSigned = async (rpcUrl, signedBase58) => {
178
+ const { default: bs58 } = await import("bs58");
179
+ const transactionBytes = bs58.decode(signedBase58);
180
+ const base64Transaction = Buffer.from(transactionBytes).toString("base64");
181
+ const response = await fetch(rpcUrl, {
182
+ method: "POST",
183
+ headers: { "Content-Type": "application/json" },
184
+ body: JSON.stringify({
185
+ jsonrpc: "2.0",
186
+ id: 1,
187
+ method: "sendTransaction",
188
+ params: [
189
+ base64Transaction,
190
+ {
191
+ encoding: "base64",
192
+ skipPreflight: false,
193
+ preflightCommitment: "confirmed",
194
+ maxRetries: 3
195
+ }
196
+ ]
197
+ })
198
+ });
199
+ const result = await response.json();
200
+ if (result.error) {
201
+ throw new Error(`Solana RPC error: ${result.error.message}`);
202
+ }
203
+ return result.result;
204
+ };
205
+
206
+ // src/lib/wire-codec.ts
207
+ var arrayLikeToBytes = (value) => {
208
+ if (value instanceof Uint8Array) return value;
209
+ if (Array.isArray(value)) return new Uint8Array(value);
210
+ if (value && typeof value === "object") {
211
+ const keys = Object.keys(value);
212
+ if (keys.length === 0) return new Uint8Array();
213
+ if (keys.every((k) => /^\d+$/.test(k))) {
214
+ const len = keys.length;
215
+ const out = new Uint8Array(len);
216
+ for (let i = 0; i < len; i++) {
217
+ out[i] = value[String(i)] ?? 0;
218
+ }
219
+ return out;
220
+ }
221
+ }
222
+ throw new Error(`arrayLikeToBytes: unsupported shape (${typeof value})`);
223
+ };
224
+ var bs58ToBytes = async (value) => {
225
+ if (value instanceof Uint8Array) return value;
226
+ if (Array.isArray(value)) return new Uint8Array(value);
227
+ if (typeof value === "string") {
228
+ const { default: bs58 } = await import("bs58");
229
+ return bs58.decode(value);
230
+ }
231
+ return arrayLikeToBytes(value);
232
+ };
233
+
234
+ // src/utils/post-message.ts
235
+ var PostMessageType = {
236
+ AUTH: "auth",
237
+ INIT: "init",
238
+ WALLET: "wallet",
239
+ EXTERNAL_WALLET: "external_wallet"
240
+ };
241
+ var PostMessageMethod = {
242
+ CLOSE: "CLOSE",
243
+ CREATE_WALLET: "CREATE_WALLET",
244
+ IMPORT_KEY: "IMPORT_KEY",
245
+ FUND_WALLET: "FUND_WALLET",
246
+ GET_APP_CONFIG: "GET_APP_CONFIG",
247
+ GET_BALANCE: "GET_BALANCE",
248
+ GET_CONFIRM_TRANSACTION: "GET_CONFIRM_TRANSACTION",
249
+ GET_CONFIRM_ETHEREUM_TRANSACTION: "GET_CONFIRM_ETHEREUM_TRANSACTION",
250
+ GET_CURRENT_SESSION: "GET_CURRENT_SESSION",
251
+ GET_TOKEN_ACCOUNTS_BY_OWNER: "GET_TOKEN_ACCOUNTS_BY_OWNER",
252
+ GET_USER: "GET_USER",
253
+ GET_WALLET: "GET_WALLET",
254
+ GET_WALLETS: "GET_WALLETS",
255
+ IS_AUTHENTICATED: "IS_AUTHENTICATED",
256
+ LOGIN_CREATE: "LOGIN_CREATE",
257
+ LOGOUT: "LOGOUT",
258
+ PREFETCH_CAPTCHA: "PREFETCH_CAPTCHA",
259
+ READY: "READY",
260
+ SEND_TRANSACTION: "SEND_TRANSACTION",
261
+ SIGN_MESSAGE: "SIGN_MESSAGE",
262
+ SIGN_TRANSACTION: "SIGN_TRANSACTION",
263
+ SIGN_TYPED_DATA: "SIGN_TYPED_DATA",
264
+ // Sign a pre-computed 32-byte digest as ECDSA. Caller-supplied hash
265
+ // — no EIP-191 prefix, no tx parsing, no domain separator. Useful
266
+ // for ZK circuits / custom auth flows / anywhere the digest is
267
+ // computed externally. Mirrors Privy's `secp256k1_sign` provider
268
+ // method but exposed as its own postMessage to keep the iframe
269
+ // dispatcher boring.
270
+ SIGN_HASH: "SIGN_HASH",
271
+ SIGN_7702_AUTHORIZATION: "SIGN_7702_AUTHORIZATION",
272
+ VERIFY_EMAIL_OTP: "VERIFY_EMAIL_OTP",
273
+ VERIFY_OAUTH: "VERIFY_OAUTH",
274
+ START_OAUTH: "START_OAUTH",
275
+ WALLET_REGISTRATION_NONCE: "WALLET_REGISTRATION_NONCE",
276
+ VERIFY_SIWE_WALLET_REGISTRATION: "VERIFY_SIWE_WALLET_REGISTRATION",
277
+ ATTACH_OAUTH: "ATTACH_OAUTH",
278
+ DETACH_OAUTH: "DETACH_OAUTH",
279
+ // Passkey as a post-identity enrollment / unlock ceremony. The two
280
+ // methods below split the ceremony so the parent owns the WebAuthn
281
+ // API call (where user activation lives) and the iframe owns the
282
+ // begin/verify HTTP calls (where the session JWT lives).
283
+ PASSKEY_REGISTER_BEGIN: "PASSKEY_REGISTER_BEGIN",
284
+ PASSKEY_REGISTER_VERIFY: "PASSKEY_REGISTER_VERIFY",
285
+ GET_PASSKEY_STATUS: "GET_PASSKEY_STATUS",
286
+ // Parent-side passkey assertion plumbing. Parent calls GET_DEK_INFO
287
+ // to learn which credential IDs to put in allowCredentials and to
288
+ // know whether bootstrap-vs-unwrap path applies, then runs
289
+ // navigator.credentials.get itself (where iframe-cross-origin
290
+ // activation rules don't bite). Wallet-op postMessages then carry
291
+ // the resulting user_handle_b64url + credential_id_b64url back into
292
+ // the iframe so encrypted-keyshare helpers can unwrap the DEK.
293
+ GET_DEK_INFO: "GET_DEK_INFO",
294
+ // Multi-passkey management on an existing user. ADD_PASSKEY_WRAP is
295
+ // the iframe half of the parent-driven add-passkey flow: parent runs
296
+ // both WebAuthn ceremonies (assert old credential, register new
297
+ // credential), then posts the two resulting (userHandle, credId)
298
+ // pairs here so the iframe can unlock the DEK with the old
299
+ // credential and seal a new wrap with the new credential.
300
+ ADD_PASSKEY_WRAP: "ADD_PASSKEY_WRAP",
301
+ REMOVE_PASSKEY: "REMOVE_PASSKEY"
302
+ };
303
+
304
+ // src/sdk/parent-passkey-assert.ts
305
+ var assertPasskeyInParent = async ({
306
+ transport,
307
+ passkey,
308
+ publishableKey,
309
+ requireFreshAssertion = false
310
+ }) => {
311
+ if (!requireFreshAssertion) {
312
+ const cached = readParentAssertCache();
313
+ if (cached) return cached;
314
+ }
315
+ const dekInfo = await transport.send(
316
+ PostMessageType.AUTH,
317
+ PostMessageMethod.GET_DEK_INFO,
318
+ { publishableKey }
319
+ );
320
+ const allowList = dekInfo.allow_credential_ids_b64url ?? [];
321
+ if (allowList.length === 0) {
322
+ throw new Error("passkey_required");
323
+ }
324
+ const rpId = dekInfo.rp_id;
325
+ if (!rpId) {
326
+ throw new Error("webauthn_rp_id_not_configured");
327
+ }
328
+ const challengeBytes = crypto.getRandomValues(new Uint8Array(32));
329
+ const challenge = toB64url(challengeBytes);
330
+ const credential = await passkey.assert({
331
+ rpId,
332
+ challenge,
333
+ allowCredentials: []
334
+ });
335
+ const result = {
336
+ userHandleB64url: credential.userHandleB64url,
337
+ credentialIdB64url: credential.rawIdB64url
338
+ };
339
+ writeParentAssertCache(result);
340
+ return result;
341
+ };
342
+
343
+ // src/sdk/headless-ethereum.ts
344
+ var getHeadlessEthereumMethods = ({
345
+ transport,
346
+ passkey,
347
+ publishableKey
348
+ }) => ({
349
+ signEthereumMessageHeadless: async (params) => withClearOnFailure(async () => {
350
+ if (!transport.isReady()) throw new Error("SDK not ready");
351
+ const { userHandleB64url, credentialIdB64url } = await assertPasskeyInParent({
352
+ transport,
353
+ passkey,
354
+ publishableKey,
355
+ requireFreshAssertion: params.requireFreshAssertion
356
+ });
357
+ return transport.send(
358
+ PostMessageType.WALLET,
359
+ PostMessageMethod.SIGN_MESSAGE,
360
+ {
361
+ message: params.message,
362
+ publishableKey,
363
+ wallet: params.wallet,
364
+ uiOptions: params.options?.uiOptions,
365
+ userHandleB64url,
366
+ credentialIdB64url
367
+ }
368
+ );
369
+ }),
370
+ signEthereumTransactionHeadless: async (params) => withClearOnFailure(async () => {
371
+ if (!transport.isReady()) throw new Error("SDK not ready");
372
+ const { userHandleB64url, credentialIdB64url } = await assertPasskeyInParent({
373
+ transport,
374
+ passkey,
375
+ publishableKey,
376
+ requireFreshAssertion: params.requireFreshAssertion
377
+ });
378
+ return transport.send(
379
+ PostMessageType.WALLET,
380
+ PostMessageMethod.SIGN_TRANSACTION,
381
+ {
382
+ // params.transaction is typed as a pre-serialized RLP string.
383
+ serializedTransaction: params.transaction,
384
+ publishableKey,
385
+ wallet: params.wallet,
386
+ options: params.options,
387
+ userHandleB64url,
388
+ credentialIdB64url
389
+ }
390
+ );
391
+ }),
392
+ signEthereumTypedDataHeadless: async (params) => withClearOnFailure(async () => {
393
+ if (!transport.isReady()) throw new Error("SDK not ready");
394
+ const { userHandleB64url, credentialIdB64url } = await assertPasskeyInParent({
395
+ transport,
396
+ passkey,
397
+ publishableKey,
398
+ requireFreshAssertion: params.requireFreshAssertion
399
+ });
400
+ return transport.send(
401
+ PostMessageType.WALLET,
402
+ PostMessageMethod.SIGN_TYPED_DATA,
403
+ {
404
+ domain: params.domain,
405
+ types: params.types,
406
+ primaryType: params.primaryType,
407
+ message: params.message,
408
+ publishableKey,
409
+ wallet: params.wallet,
410
+ options: params.options,
411
+ userHandleB64url,
412
+ credentialIdB64url
413
+ }
414
+ );
415
+ }),
416
+ signEthereumHashHeadless: async (params) => withClearOnFailure(async () => {
417
+ if (!transport.isReady()) throw new Error("SDK not ready");
418
+ const { userHandleB64url, credentialIdB64url } = await assertPasskeyInParent({
419
+ transport,
420
+ passkey,
421
+ publishableKey,
422
+ requireFreshAssertion: params.requireFreshAssertion
423
+ });
424
+ return transport.send(
425
+ PostMessageType.WALLET,
426
+ PostMessageMethod.SIGN_HASH,
427
+ {
428
+ hash: params.hash,
429
+ publishableKey,
430
+ wallet: params.wallet,
431
+ options: params.options,
432
+ userHandleB64url,
433
+ credentialIdB64url
434
+ }
435
+ );
436
+ }),
437
+ signEthereum7702AuthorizationHeadless: async (params) => withClearOnFailure(async () => {
438
+ if (!transport.isReady()) throw new Error("SDK not ready");
439
+ const { userHandleB64url, credentialIdB64url } = await assertPasskeyInParent({
440
+ transport,
441
+ passkey,
442
+ publishableKey,
443
+ requireFreshAssertion: params.requireFreshAssertion
444
+ });
445
+ return transport.send(
446
+ PostMessageType.WALLET,
447
+ PostMessageMethod.SIGN_7702_AUTHORIZATION,
448
+ {
449
+ contractAddress: params.contractAddress,
450
+ chainId: params.chainId,
451
+ nonce: params.nonce,
452
+ executor: params.executor,
453
+ publishableKey,
454
+ wallet: params.wallet,
455
+ options: params.options,
456
+ userHandleB64url,
457
+ credentialIdB64url
458
+ }
459
+ );
460
+ }),
461
+ sendEthereumTransactionHeadless: async (params) => withClearOnFailure(async () => {
462
+ if (!transport.isReady()) throw new Error("SDK not ready");
463
+ const { userHandleB64url, credentialIdB64url } = await assertPasskeyInParent({
464
+ transport,
465
+ passkey,
466
+ publishableKey,
467
+ requireFreshAssertion: params.requireFreshAssertion
468
+ });
469
+ const serializedTransaction = await serializeEthereumTransaction(
470
+ params.transaction
471
+ );
472
+ const signed = await transport.send(
473
+ PostMessageType.WALLET,
474
+ PostMessageMethod.SIGN_TRANSACTION,
475
+ {
476
+ serializedTransaction,
477
+ publishableKey,
478
+ wallet: params.wallet,
479
+ options: params.options,
480
+ userHandleB64url,
481
+ credentialIdB64url
482
+ }
483
+ );
484
+ if (!signed.serializedSigned) {
485
+ throw new Error(
486
+ "iframe returned no serializedSigned for SIGN_TRANSACTION"
487
+ );
488
+ }
489
+ const hash = await broadcastEthereumRaw(
490
+ params.rpcUrl,
491
+ signed.serializedSigned
492
+ );
493
+ return { hash };
494
+ }),
495
+ getEthereumBalance: async (params) => {
496
+ if (!transport.isReady()) throw new Error("SDK not ready");
497
+ return transport.send(
498
+ PostMessageType.WALLET,
499
+ PostMessageMethod.GET_BALANCE,
500
+ { publishableKey, ...params }
501
+ );
502
+ },
503
+ getEthereumTokenAccountsByOwner: async (params) => {
504
+ if (!transport.isReady()) throw new Error("SDK not ready");
505
+ return transport.send(
506
+ PostMessageType.WALLET,
507
+ PostMessageMethod.GET_TOKEN_ACCOUNTS_BY_OWNER,
508
+ { publishableKey, ...params }
509
+ );
510
+ },
511
+ getEthereumConfirmTransaction: async (params) => {
512
+ if (!transport.isReady()) throw new Error("SDK not ready");
513
+ const serializedTransaction = typeof params.transaction === "string" ? params.transaction : await serializeEthereumTransaction(
514
+ params.transaction
515
+ );
516
+ return transport.send(
517
+ PostMessageType.WALLET,
518
+ PostMessageMethod.GET_CONFIRM_ETHEREUM_TRANSACTION,
519
+ {
520
+ transaction: serializedTransaction,
521
+ walletAddress: params.walletAddress,
522
+ rpcUrl: params.rpcUrl,
523
+ network: params.network
524
+ }
525
+ );
526
+ }
527
+ });
528
+
529
+ // src/sdk/headless-solana.ts
530
+ var getHeadlessSolanaMethods = ({
531
+ transport,
532
+ passkey,
533
+ publishableKey
534
+ }) => ({
535
+ signSolanaMessageHeadless: async (params) => withClearOnFailure(async () => {
536
+ if (!transport.isReady()) throw new Error("SDK not ready");
537
+ const { userHandleB64url, credentialIdB64url } = await assertPasskeyInParent({
538
+ transport,
539
+ passkey,
540
+ publishableKey,
541
+ requireFreshAssertion: params.requireFreshAssertion
542
+ });
543
+ const { signature } = await transport.send(
544
+ PostMessageType.WALLET,
545
+ PostMessageMethod.SIGN_MESSAGE,
546
+ {
547
+ message: params.message,
548
+ publishableKey,
549
+ wallet: params.wallet,
550
+ uiOptions: params.options?.uiOptions,
551
+ userHandleB64url,
552
+ credentialIdB64url
553
+ }
554
+ );
555
+ return { signature: arrayLikeToBytes(signature) };
556
+ }),
557
+ signSolanaTransactionHeadless: async (params) => withClearOnFailure(async () => {
558
+ if (!transport.isReady()) throw new Error("SDK not ready");
559
+ const { userHandleB64url, credentialIdB64url } = await assertPasskeyInParent({
560
+ transport,
561
+ passkey,
562
+ publishableKey,
563
+ requireFreshAssertion: params.requireFreshAssertion
564
+ });
565
+ const { signedTransaction } = await transport.send(
566
+ PostMessageType.WALLET,
567
+ PostMessageMethod.SIGN_TRANSACTION,
568
+ {
569
+ serializedTransaction: params.transaction,
570
+ publishableKey,
571
+ wallet: params.wallet,
572
+ options: params.options,
573
+ userHandleB64url,
574
+ credentialIdB64url
575
+ }
576
+ );
577
+ return { signedTransaction: await bs58ToBytes(signedTransaction) };
578
+ }),
579
+ sendSolanaTransactionHeadless: async (params) => withClearOnFailure(async () => {
580
+ if (!transport.isReady()) throw new Error("SDK not ready");
581
+ const { userHandleB64url, credentialIdB64url } = await assertPasskeyInParent({
582
+ transport,
583
+ passkey,
584
+ publishableKey,
585
+ requireFreshAssertion: params.requireFreshAssertion
586
+ });
587
+ const { signedTransaction } = await transport.send(
588
+ PostMessageType.WALLET,
589
+ PostMessageMethod.SIGN_TRANSACTION,
590
+ {
591
+ serializedTransaction: params.transaction,
592
+ publishableKey,
593
+ wallet: params.wallet,
594
+ options: params.options,
595
+ userHandleB64url,
596
+ credentialIdB64url
597
+ }
598
+ );
599
+ const broadcastSignature = await broadcastSolanaSigned(
600
+ params.rpcUrl,
601
+ signedTransaction
602
+ );
603
+ return { signature: await bs58ToBytes(broadcastSignature) };
604
+ }),
605
+ getSolanaBalance: async (params) => {
606
+ if (!transport.isReady()) throw new Error("SDK not ready");
607
+ return transport.send(
608
+ PostMessageType.WALLET,
609
+ PostMessageMethod.GET_BALANCE,
610
+ { publishableKey, ...params }
611
+ );
612
+ },
613
+ getSolanaTokenAccountsByOwner: async (params) => {
614
+ if (!transport.isReady()) throw new Error("SDK not ready");
615
+ return transport.send(
616
+ PostMessageType.WALLET,
617
+ PostMessageMethod.GET_TOKEN_ACCOUNTS_BY_OWNER,
618
+ { publishableKey, ...params }
619
+ );
620
+ }
621
+ });
622
+
623
+ // src/sdk/headless-authentication.ts
624
+ var getHeadlessAuthenticationMethods = ({
625
+ transport,
626
+ publishableKey,
627
+ emailConfig,
628
+ setIsAuthenticated,
629
+ setUser
630
+ }) => ({
631
+ /** Send a one-time passcode to the user's email address. */
632
+ sendCode: async (params) => {
633
+ await transport.send(
634
+ PostMessageType.AUTH,
635
+ PostMessageMethod.LOGIN_CREATE,
636
+ {
637
+ email: params.email,
638
+ publishableKey,
639
+ disableSignup: params.disableSignup
640
+ }
641
+ );
642
+ authState.clearEmail();
643
+ authState.setEmail(params.email);
644
+ },
645
+ /**
646
+ * Verify the OTP and complete the login. The iframe-app handles
647
+ * session persistence; on success the SDK flips isAuthenticated and
648
+ * fetches the real user object to populate provider state.
649
+ */
650
+ loginWithCode: async (params) => {
651
+ const email = authState.getEmail();
652
+ if (!email) throw new Error("no_pending_email_otp");
653
+ const result = await transport.send(
654
+ PostMessageType.AUTH,
655
+ PostMessageMethod.VERIFY_EMAIL_OTP,
656
+ {
657
+ email,
658
+ code: params.code,
659
+ publishableKey,
660
+ expiresIn: emailConfig?.expiresIn
661
+ }
662
+ );
663
+ authState.clearEmail();
664
+ if (setIsAuthenticated) setIsAuthenticated(true);
665
+ if (setUser) {
666
+ try {
667
+ const user = await transport.send(
668
+ PostMessageType.AUTH,
669
+ PostMessageMethod.GET_USER,
670
+ { publishableKey }
671
+ );
672
+ setUser(user ?? null);
673
+ } catch {
674
+ }
675
+ }
676
+ return result;
677
+ },
678
+ /**
679
+ * Commit an OAuth code/token for a session. The deep-link / popup
680
+ * round-trip lives in the platform-specific OAuth hook; this method
681
+ * is the tail-end commit step the hook calls.
682
+ */
683
+ verifyOAuth: async (params) => {
684
+ const result = await transport.send(
685
+ PostMessageType.AUTH,
686
+ PostMessageMethod.VERIFY_OAUTH,
687
+ {
688
+ publishableKey,
689
+ provider: params.provider,
690
+ code: params.code,
691
+ token: params.token,
692
+ state: params.state
693
+ }
694
+ );
695
+ if (setIsAuthenticated) setIsAuthenticated(true);
696
+ if (setUser) {
697
+ try {
698
+ const user = await transport.send(
699
+ PostMessageType.AUTH,
700
+ PostMessageMethod.GET_USER,
701
+ { publishableKey }
702
+ );
703
+ setUser(user ?? null);
704
+ } catch {
705
+ }
706
+ }
707
+ return result;
708
+ }
709
+ });
710
+
711
+ // src/sdk/headless-general.ts
712
+ var getHeadlessGeneralMethods = ({
713
+ transport,
714
+ passkey,
715
+ storage,
716
+ publishableKey,
717
+ setIsAuthenticated,
718
+ setUser
719
+ }) => ({
720
+ getPasskeyStatus: async () => transport.send(
721
+ PostMessageType.AUTH,
722
+ PostMessageMethod.GET_PASSKEY_STATUS,
723
+ { publishableKey }
724
+ ),
725
+ removePasskey: async (credentialIdB64url) => {
726
+ await transport.send(
727
+ PostMessageType.AUTH,
728
+ PostMessageMethod.REMOVE_PASSKEY,
729
+ { publishableKey, credentialIdB64url }
730
+ );
731
+ },
732
+ createWallet: (walletType, options) => withClearOnFailure(async () => {
733
+ const { userHandleB64url, credentialIdB64url } = await assertPasskeyInParent({
734
+ transport,
735
+ passkey,
736
+ publishableKey,
737
+ requireFreshAssertion: options?.requireFreshAssertion
738
+ });
739
+ const wallet = await transport.send(
740
+ PostMessageType.WALLET,
741
+ PostMessageMethod.CREATE_WALLET,
742
+ {
743
+ walletType,
744
+ publishableKey,
745
+ options,
746
+ userHandleB64url,
747
+ credentialIdB64url
748
+ }
749
+ );
750
+ return { wallet };
751
+ }),
752
+ importKey: (walletType, key, options) => withClearOnFailure(async () => {
753
+ const { userHandleB64url, credentialIdB64url } = await assertPasskeyInParent({
754
+ transport,
755
+ passkey,
756
+ publishableKey,
757
+ requireFreshAssertion: options?.requireFreshAssertion
758
+ });
759
+ const wallet = await transport.send(
760
+ PostMessageType.WALLET,
761
+ PostMessageMethod.IMPORT_KEY,
762
+ {
763
+ walletType,
764
+ publishableKey,
765
+ key,
766
+ userHandleB64url,
767
+ credentialIdB64url
768
+ }
769
+ );
770
+ return { wallet };
771
+ }),
772
+ getWallets: async (walletType) => {
773
+ const { wallets } = await transport.send(
774
+ PostMessageType.WALLET,
775
+ PostMessageMethod.GET_WALLETS,
776
+ { walletType, publishableKey }
777
+ );
778
+ return { wallets, walletType };
779
+ },
780
+ // getSessionTokens returns only the tokens that may safely cross the
781
+ // iframe -> parent-page boundary: access + identity. The refresh token
782
+ // is the session's primary credential and stays inside the iframe's
783
+ // origin (held in IndexedDB, used internally for /auth/refresh). An
784
+ // XSS in the host page would otherwise be able to exfiltrate it and
785
+ // silently extend session lifetime.
786
+ getSessionTokens: async () => {
787
+ try {
788
+ const session = await transport.send(
789
+ PostMessageType.AUTH,
790
+ PostMessageMethod.GET_CURRENT_SESSION,
791
+ { publishableKey }
792
+ );
793
+ return session ? {
794
+ accessToken: session.accessToken,
795
+ identityToken: session.identityToken,
796
+ expiresAt: session.expiresAt
797
+ } : null;
798
+ } catch (error) {
799
+ console.error(
800
+ "Failed to get session tokens:",
801
+ error instanceof Error ? error.message : String(error)
802
+ );
803
+ return null;
804
+ }
805
+ },
806
+ logout: async () => {
807
+ try {
808
+ await transport.send(PostMessageType.AUTH, PostMessageMethod.LOGOUT, {
809
+ publishableKey
810
+ });
811
+ clearParentAssertCache();
812
+ await storage.remove("id_token");
813
+ if (setIsAuthenticated) setIsAuthenticated(false);
814
+ if (setUser) setUser(null);
815
+ return { success: true, message: "Successfully logged out" };
816
+ } catch (error) {
817
+ console.error(
818
+ "Logout failed:",
819
+ error instanceof Error ? error.message : String(error)
820
+ );
821
+ return { success: false, message: "Logout failed" };
822
+ }
823
+ },
824
+ getCurrentSession: async () => {
825
+ try {
826
+ return await transport.send(
827
+ PostMessageType.AUTH,
828
+ PostMessageMethod.GET_CURRENT_SESSION,
829
+ { publishableKey }
830
+ );
831
+ } catch (error) {
832
+ console.error(
833
+ "Get session failed:",
834
+ error instanceof Error ? error.message : String(error)
835
+ );
836
+ return null;
837
+ }
838
+ },
839
+ getUser: async () => {
840
+ try {
841
+ const user = await transport.send(
842
+ PostMessageType.AUTH,
843
+ PostMessageMethod.GET_USER,
844
+ { publishableKey }
845
+ );
846
+ if (setUser) setUser(user);
847
+ return user;
848
+ } catch (error) {
849
+ console.error(
850
+ "Get user failed:",
851
+ error instanceof Error ? error.message : String(error)
852
+ );
853
+ return null;
854
+ }
855
+ }
856
+ });
857
+ // Annotate the CommonJS export names for ESM import in node:
858
+ 0 && (module.exports = {
859
+ assertPasskeyInParent,
860
+ getHeadlessAuthenticationMethods,
861
+ getHeadlessEthereumMethods,
862
+ getHeadlessGeneralMethods,
863
+ getHeadlessSolanaMethods
864
+ });