@moon-x/core 0.3.0 → 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/dist/{chunk-CDT4MC7S.mjs → chunk-I56GRKAG.mjs} +19 -39
- package/dist/{chunk-VVL65GIB.mjs → chunk-JU5MWLXH.mjs} +14 -0
- package/dist/index.d.mts +2 -3
- package/dist/index.d.ts +2 -3
- package/dist/index.js +14 -0
- package/dist/index.mjs +1 -1
- package/dist/{interfaces-Bm7fGOAI.d.ts → interfaces-1vfik3Ef.d.ts} +24 -1
- package/dist/{interfaces-CYtJHALV.d.mts → interfaces-BdIeMGGD.d.mts} +24 -1
- package/dist/lib/index.d.mts +33 -3
- package/dist/lib/index.d.ts +33 -3
- package/dist/lib/index.js +23 -47
- package/dist/lib/index.mjs +7 -15
- package/dist/passkey-cache-WnDFQ-v4.d.mts +26 -0
- package/dist/passkey-cache-WnDFQ-v4.d.ts +26 -0
- package/dist/{post-message-CmgAfkOS.d.mts → post-message-Z6cLf0mS.d.mts} +3 -0
- package/dist/{post-message-CmgAfkOS.d.ts → post-message-Z6cLf0mS.d.ts} +3 -0
- package/dist/react/ethereum.d.mts +0 -1
- package/dist/react/ethereum.d.ts +0 -1
- package/dist/react/index.d.mts +41 -3
- package/dist/react/index.d.ts +41 -3
- package/dist/react/index.js +138 -12
- package/dist/react/index.mjs +137 -12
- package/dist/react/solana.d.mts +0 -1
- package/dist/react/solana.d.ts +0 -1
- package/dist/sdk/index.d.mts +87 -16
- package/dist/sdk/index.d.ts +87 -16
- package/dist/sdk/index.js +456 -102
- package/dist/sdk/index.mjs +440 -80
- package/dist/types/index.d.mts +135 -12
- package/dist/types/index.d.ts +135 -12
- package/dist/utils/index.d.mts +1 -1
- package/dist/utils/index.d.ts +1 -1
- package/dist/utils/index.js +14 -0
- package/dist/utils/index.mjs +1 -1
- package/dist/web/index.d.mts +2 -2
- package/dist/web/index.d.ts +2 -2
- package/dist/web/index.js +29 -0
- package/dist/web/index.mjs +30 -1
- package/package.json +3 -1
- package/dist/chain-C9dvKXUY.d.mts +0 -48
- package/dist/chain-C9dvKXUY.d.ts +0 -48
- package/dist/passkey-cache-B9PT3AWX.d.mts +0 -47
- package/dist/passkey-cache-B9PT3AWX.d.ts +0 -47
package/dist/sdk/index.js
CHANGED
|
@@ -30,12 +30,16 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
30
30
|
// src/sdk/index.ts
|
|
31
31
|
var sdk_exports = {};
|
|
32
32
|
__export(sdk_exports, {
|
|
33
|
+
EphemeralSignerSignError: () => EphemeralSignerSignError,
|
|
33
34
|
assertPasskeyInParent: () => assertPasskeyInParent,
|
|
35
|
+
flattenPresenceTokens: () => flattenPresenceTokens,
|
|
34
36
|
getHeadlessAuthenticationMethods: () => getHeadlessAuthenticationMethods,
|
|
35
37
|
getHeadlessEthereumMethods: () => getHeadlessEthereumMethods,
|
|
36
38
|
getHeadlessGeneralMethods: () => getHeadlessGeneralMethods,
|
|
37
39
|
getHeadlessSolanaMethods: () => getHeadlessSolanaMethods,
|
|
38
|
-
|
|
40
|
+
getInternalPresenceTokens: () => getInternalPresenceTokens,
|
|
41
|
+
getPresenceToken: () => getPresenceToken,
|
|
42
|
+
signWithEphemeralSigner: () => signWithEphemeralSigner
|
|
39
43
|
});
|
|
40
44
|
module.exports = __toCommonJS(sdk_exports);
|
|
41
45
|
|
|
@@ -66,34 +70,6 @@ var toB64url = (bytes) => {
|
|
|
66
70
|
return btoa(str).replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/, "");
|
|
67
71
|
};
|
|
68
72
|
|
|
69
|
-
// src/lib/passkey/passkey-cache.ts
|
|
70
|
-
var cacheTtlMs = 0;
|
|
71
|
-
var cache = null;
|
|
72
|
-
var clearParentAssertCache = () => {
|
|
73
|
-
cache = null;
|
|
74
|
-
};
|
|
75
|
-
var readParentAssertCache = () => {
|
|
76
|
-
if (cacheTtlMs <= 0) return null;
|
|
77
|
-
if (!cache) return null;
|
|
78
|
-
if (Date.now() - cache.ts >= cacheTtlMs) return null;
|
|
79
|
-
return {
|
|
80
|
-
userHandleB64url: cache.userHandleB64url,
|
|
81
|
-
credentialIdB64url: cache.credentialIdB64url
|
|
82
|
-
};
|
|
83
|
-
};
|
|
84
|
-
var writeParentAssertCache = (entry) => {
|
|
85
|
-
if (cacheTtlMs <= 0) return;
|
|
86
|
-
cache = { ...entry, ts: Date.now() };
|
|
87
|
-
};
|
|
88
|
-
var withClearOnFailure = async (fn) => {
|
|
89
|
-
try {
|
|
90
|
-
return await fn();
|
|
91
|
-
} catch (error) {
|
|
92
|
-
clearParentAssertCache();
|
|
93
|
-
throw error;
|
|
94
|
-
}
|
|
95
|
-
};
|
|
96
|
-
|
|
97
73
|
// src/lib/ethereum/chains.ts
|
|
98
74
|
var import_viem = require("viem");
|
|
99
75
|
|
|
@@ -270,6 +246,20 @@ var PostMessageMethod = {
|
|
|
270
246
|
// dispatcher boring.
|
|
271
247
|
SIGN_HASH: "SIGN_HASH",
|
|
272
248
|
SIGN_7702_AUTHORIZATION: "SIGN_7702_AUTHORIZATION",
|
|
249
|
+
// Provision a SES (Secure Ephemeral Signer) over one or more of the
|
|
250
|
+
// user's MPC wallets. Iframe verifies the Nitro attestation, decrypts
|
|
251
|
+
// the selected keyshares, HPKE-seals them to the verified enclave
|
|
252
|
+
// pubkey, and returns a freshly-generated Ed25519 signer keypair.
|
|
253
|
+
// MoonX never persists the private key — the parent must hand it to
|
|
254
|
+
// the user immediately.
|
|
255
|
+
PROVISION_EPHEMERAL_SIGNER: "PROVISION_EPHEMERAL_SIGNER",
|
|
256
|
+
// List the user's active provisioned ephemeral signers from the
|
|
257
|
+
// wallets backend. Read-only; doesn't touch SES or the enclave.
|
|
258
|
+
LIST_EPHEMERAL_SIGNERS: "LIST_EPHEMERAL_SIGNERS",
|
|
259
|
+
// Soft-revoke a previously-provisioned ephemeral signer. The wallets
|
|
260
|
+
// backend updates revoked_at locally and forwards the revoke to SES
|
|
261
|
+
// so the enclave drops the policy.
|
|
262
|
+
REVOKE_EPHEMERAL_SIGNER: "REVOKE_EPHEMERAL_SIGNER",
|
|
273
263
|
VERIFY_EMAIL_OTP: "VERIFY_EMAIL_OTP",
|
|
274
264
|
VERIFY_OAUTH: "VERIFY_OAUTH",
|
|
275
265
|
START_OAUTH: "START_OAUTH",
|
|
@@ -317,13 +307,8 @@ var assertPasskeyInParent = async ({
|
|
|
317
307
|
transport,
|
|
318
308
|
passkey,
|
|
319
309
|
publishableKey,
|
|
320
|
-
requireFreshAssertion = false,
|
|
321
310
|
validateCredentialInAllowList = false
|
|
322
311
|
}) => {
|
|
323
|
-
if (!requireFreshAssertion) {
|
|
324
|
-
const cached = readParentAssertCache();
|
|
325
|
-
if (cached) return cached;
|
|
326
|
-
}
|
|
327
312
|
const dekInfo = await transport.send(
|
|
328
313
|
PostMessageType.AUTH,
|
|
329
314
|
PostMessageMethod.GET_DEK_INFO,
|
|
@@ -347,12 +332,10 @@ var assertPasskeyInParent = async ({
|
|
|
347
332
|
if (validateCredentialInAllowList && !allowList.includes(credential.rawIdB64url)) {
|
|
348
333
|
throw new Error("unknown_passkey_for_this_account");
|
|
349
334
|
}
|
|
350
|
-
|
|
335
|
+
return {
|
|
351
336
|
userHandleB64url: credential.userHandleB64url,
|
|
352
337
|
credentialIdB64url: credential.rawIdB64url
|
|
353
338
|
};
|
|
354
|
-
writeParentAssertCache(result);
|
|
355
|
-
return result;
|
|
356
339
|
};
|
|
357
340
|
|
|
358
341
|
// src/sdk/get-presence-token.ts
|
|
@@ -384,19 +367,79 @@ var getPresenceToken = async ({
|
|
|
384
367
|
};
|
|
385
368
|
};
|
|
386
369
|
|
|
370
|
+
// src/sdk/get-internal-presence-tokens.ts
|
|
371
|
+
var getInternalPresenceTokens = async ({
|
|
372
|
+
transport,
|
|
373
|
+
passkey,
|
|
374
|
+
publishableKey,
|
|
375
|
+
relyingPartyOrigin,
|
|
376
|
+
scopes,
|
|
377
|
+
scopeCounts
|
|
378
|
+
}) => {
|
|
379
|
+
const { token, optionsJSON } = await transport.send(
|
|
380
|
+
PostMessageType.AUTH,
|
|
381
|
+
PostMessageMethod.PASSKEY_PRESENCE_BEGIN,
|
|
382
|
+
{ publishableKey, relyingPartyOrigin }
|
|
383
|
+
);
|
|
384
|
+
const { response, userHandleB64url, credentialIdB64url } = await passkey.assertForInternalPresence({ optionsJSON });
|
|
385
|
+
const verifyPayload = {
|
|
386
|
+
publishableKey,
|
|
387
|
+
relyingPartyOrigin,
|
|
388
|
+
token,
|
|
389
|
+
response,
|
|
390
|
+
purpose: "internal"
|
|
391
|
+
};
|
|
392
|
+
if (scopes && scopes.length > 0) verifyPayload.scopes = scopes;
|
|
393
|
+
if (scopeCounts && Object.keys(scopeCounts).length > 0) {
|
|
394
|
+
verifyPayload.scope_counts = scopeCounts;
|
|
395
|
+
}
|
|
396
|
+
const verify = await transport.send(
|
|
397
|
+
PostMessageType.AUTH,
|
|
398
|
+
PostMessageMethod.PASSKEY_PRESENCE_VERIFY,
|
|
399
|
+
verifyPayload
|
|
400
|
+
);
|
|
401
|
+
const out = {};
|
|
402
|
+
for (const [scope, t] of Object.entries(verify.tokens ?? {})) {
|
|
403
|
+
out[scope] = { token: t.token, expiresAt: t.expires_at };
|
|
404
|
+
}
|
|
405
|
+
const outBatches = {};
|
|
406
|
+
for (const [scope, batch] of Object.entries(verify.token_batches ?? {})) {
|
|
407
|
+
outBatches[scope] = batch.map((t) => ({
|
|
408
|
+
token: t.token,
|
|
409
|
+
expiresAt: t.expires_at
|
|
410
|
+
}));
|
|
411
|
+
}
|
|
412
|
+
return {
|
|
413
|
+
tokens: out,
|
|
414
|
+
tokenBatches: outBatches,
|
|
415
|
+
userHandleB64url,
|
|
416
|
+
credentialIdB64url
|
|
417
|
+
};
|
|
418
|
+
};
|
|
419
|
+
var flattenPresenceTokens = (result) => {
|
|
420
|
+
const out = {};
|
|
421
|
+
for (const [scope, t] of Object.entries(result.tokens)) {
|
|
422
|
+
out[scope] = t.token;
|
|
423
|
+
}
|
|
424
|
+
return out;
|
|
425
|
+
};
|
|
426
|
+
|
|
387
427
|
// src/sdk/headless-ethereum.ts
|
|
428
|
+
var SCOPES_SIGN = ["keyshare_read", "sign"];
|
|
388
429
|
var getHeadlessEthereumMethods = ({
|
|
389
430
|
transport,
|
|
390
431
|
passkey,
|
|
391
|
-
publishableKey
|
|
432
|
+
publishableKey,
|
|
433
|
+
relyingPartyOrigin
|
|
392
434
|
}) => ({
|
|
393
|
-
signEthereumMessageHeadless: async (params) =>
|
|
435
|
+
signEthereumMessageHeadless: async (params) => {
|
|
394
436
|
if (!transport.isReady()) throw new Error("SDK not ready");
|
|
395
|
-
const { userHandleB64url, credentialIdB64url } = await
|
|
437
|
+
const { userHandleB64url, credentialIdB64url, tokens } = await getInternalPresenceTokens({
|
|
396
438
|
transport,
|
|
397
439
|
passkey,
|
|
398
440
|
publishableKey,
|
|
399
|
-
|
|
441
|
+
relyingPartyOrigin,
|
|
442
|
+
scopes: SCOPES_SIGN
|
|
400
443
|
});
|
|
401
444
|
return transport.send(
|
|
402
445
|
PostMessageType.WALLET,
|
|
@@ -407,17 +450,23 @@ var getHeadlessEthereumMethods = ({
|
|
|
407
450
|
wallet: params.wallet,
|
|
408
451
|
uiOptions: params.options?.uiOptions,
|
|
409
452
|
userHandleB64url,
|
|
410
|
-
credentialIdB64url
|
|
453
|
+
credentialIdB64url,
|
|
454
|
+
presenceTokens: flattenPresenceTokens({
|
|
455
|
+
tokens,
|
|
456
|
+
userHandleB64url,
|
|
457
|
+
credentialIdB64url
|
|
458
|
+
})
|
|
411
459
|
}
|
|
412
460
|
);
|
|
413
|
-
}
|
|
414
|
-
signEthereumTransactionHeadless: async (params) =>
|
|
461
|
+
},
|
|
462
|
+
signEthereumTransactionHeadless: async (params) => {
|
|
415
463
|
if (!transport.isReady()) throw new Error("SDK not ready");
|
|
416
|
-
const { userHandleB64url, credentialIdB64url } = await
|
|
464
|
+
const { userHandleB64url, credentialIdB64url, tokens } = await getInternalPresenceTokens({
|
|
417
465
|
transport,
|
|
418
466
|
passkey,
|
|
419
467
|
publishableKey,
|
|
420
|
-
|
|
468
|
+
relyingPartyOrigin,
|
|
469
|
+
scopes: SCOPES_SIGN
|
|
421
470
|
});
|
|
422
471
|
return transport.send(
|
|
423
472
|
PostMessageType.WALLET,
|
|
@@ -429,17 +478,23 @@ var getHeadlessEthereumMethods = ({
|
|
|
429
478
|
wallet: params.wallet,
|
|
430
479
|
options: params.options,
|
|
431
480
|
userHandleB64url,
|
|
432
|
-
credentialIdB64url
|
|
481
|
+
credentialIdB64url,
|
|
482
|
+
presenceTokens: flattenPresenceTokens({
|
|
483
|
+
tokens,
|
|
484
|
+
userHandleB64url,
|
|
485
|
+
credentialIdB64url
|
|
486
|
+
})
|
|
433
487
|
}
|
|
434
488
|
);
|
|
435
|
-
}
|
|
436
|
-
signEthereumTypedDataHeadless: async (params) =>
|
|
489
|
+
},
|
|
490
|
+
signEthereumTypedDataHeadless: async (params) => {
|
|
437
491
|
if (!transport.isReady()) throw new Error("SDK not ready");
|
|
438
|
-
const { userHandleB64url, credentialIdB64url } = await
|
|
492
|
+
const { userHandleB64url, credentialIdB64url, tokens } = await getInternalPresenceTokens({
|
|
439
493
|
transport,
|
|
440
494
|
passkey,
|
|
441
495
|
publishableKey,
|
|
442
|
-
|
|
496
|
+
relyingPartyOrigin,
|
|
497
|
+
scopes: SCOPES_SIGN
|
|
443
498
|
});
|
|
444
499
|
return transport.send(
|
|
445
500
|
PostMessageType.WALLET,
|
|
@@ -453,17 +508,23 @@ var getHeadlessEthereumMethods = ({
|
|
|
453
508
|
wallet: params.wallet,
|
|
454
509
|
options: params.options,
|
|
455
510
|
userHandleB64url,
|
|
456
|
-
credentialIdB64url
|
|
511
|
+
credentialIdB64url,
|
|
512
|
+
presenceTokens: flattenPresenceTokens({
|
|
513
|
+
tokens,
|
|
514
|
+
userHandleB64url,
|
|
515
|
+
credentialIdB64url
|
|
516
|
+
})
|
|
457
517
|
}
|
|
458
518
|
);
|
|
459
|
-
}
|
|
460
|
-
signEthereumHashHeadless: async (params) =>
|
|
519
|
+
},
|
|
520
|
+
signEthereumHashHeadless: async (params) => {
|
|
461
521
|
if (!transport.isReady()) throw new Error("SDK not ready");
|
|
462
|
-
const { userHandleB64url, credentialIdB64url } = await
|
|
522
|
+
const { userHandleB64url, credentialIdB64url, tokens } = await getInternalPresenceTokens({
|
|
463
523
|
transport,
|
|
464
524
|
passkey,
|
|
465
525
|
publishableKey,
|
|
466
|
-
|
|
526
|
+
relyingPartyOrigin,
|
|
527
|
+
scopes: SCOPES_SIGN
|
|
467
528
|
});
|
|
468
529
|
return transport.send(
|
|
469
530
|
PostMessageType.WALLET,
|
|
@@ -474,17 +535,23 @@ var getHeadlessEthereumMethods = ({
|
|
|
474
535
|
wallet: params.wallet,
|
|
475
536
|
options: params.options,
|
|
476
537
|
userHandleB64url,
|
|
477
|
-
credentialIdB64url
|
|
538
|
+
credentialIdB64url,
|
|
539
|
+
presenceTokens: flattenPresenceTokens({
|
|
540
|
+
tokens,
|
|
541
|
+
userHandleB64url,
|
|
542
|
+
credentialIdB64url
|
|
543
|
+
})
|
|
478
544
|
}
|
|
479
545
|
);
|
|
480
|
-
}
|
|
481
|
-
signEthereum7702AuthorizationHeadless: async (params) =>
|
|
546
|
+
},
|
|
547
|
+
signEthereum7702AuthorizationHeadless: async (params) => {
|
|
482
548
|
if (!transport.isReady()) throw new Error("SDK not ready");
|
|
483
|
-
const { userHandleB64url, credentialIdB64url } = await
|
|
549
|
+
const { userHandleB64url, credentialIdB64url, tokens } = await getInternalPresenceTokens({
|
|
484
550
|
transport,
|
|
485
551
|
passkey,
|
|
486
552
|
publishableKey,
|
|
487
|
-
|
|
553
|
+
relyingPartyOrigin,
|
|
554
|
+
scopes: SCOPES_SIGN
|
|
488
555
|
});
|
|
489
556
|
return transport.send(
|
|
490
557
|
PostMessageType.WALLET,
|
|
@@ -498,17 +565,23 @@ var getHeadlessEthereumMethods = ({
|
|
|
498
565
|
wallet: params.wallet,
|
|
499
566
|
options: params.options,
|
|
500
567
|
userHandleB64url,
|
|
501
|
-
credentialIdB64url
|
|
568
|
+
credentialIdB64url,
|
|
569
|
+
presenceTokens: flattenPresenceTokens({
|
|
570
|
+
tokens,
|
|
571
|
+
userHandleB64url,
|
|
572
|
+
credentialIdB64url
|
|
573
|
+
})
|
|
502
574
|
}
|
|
503
575
|
);
|
|
504
|
-
}
|
|
505
|
-
sendEthereumTransactionHeadless: async (params) =>
|
|
576
|
+
},
|
|
577
|
+
sendEthereumTransactionHeadless: async (params) => {
|
|
506
578
|
if (!transport.isReady()) throw new Error("SDK not ready");
|
|
507
|
-
const { userHandleB64url, credentialIdB64url } = await
|
|
579
|
+
const { userHandleB64url, credentialIdB64url, tokens } = await getInternalPresenceTokens({
|
|
508
580
|
transport,
|
|
509
581
|
passkey,
|
|
510
582
|
publishableKey,
|
|
511
|
-
|
|
583
|
+
relyingPartyOrigin,
|
|
584
|
+
scopes: SCOPES_SIGN
|
|
512
585
|
});
|
|
513
586
|
const serializedTransaction = await serializeEthereumTransaction(
|
|
514
587
|
params.transaction
|
|
@@ -522,7 +595,12 @@ var getHeadlessEthereumMethods = ({
|
|
|
522
595
|
wallet: params.wallet,
|
|
523
596
|
options: params.options,
|
|
524
597
|
userHandleB64url,
|
|
525
|
-
credentialIdB64url
|
|
598
|
+
credentialIdB64url,
|
|
599
|
+
presenceTokens: flattenPresenceTokens({
|
|
600
|
+
tokens,
|
|
601
|
+
userHandleB64url,
|
|
602
|
+
credentialIdB64url
|
|
603
|
+
})
|
|
526
604
|
}
|
|
527
605
|
);
|
|
528
606
|
if (!signed.serializedSigned) {
|
|
@@ -535,7 +613,7 @@ var getHeadlessEthereumMethods = ({
|
|
|
535
613
|
signed.serializedSigned
|
|
536
614
|
);
|
|
537
615
|
return { hash };
|
|
538
|
-
}
|
|
616
|
+
},
|
|
539
617
|
getEthereumBalance: async (params) => {
|
|
540
618
|
if (!transport.isReady()) throw new Error("SDK not ready");
|
|
541
619
|
return transport.send(
|
|
@@ -571,18 +649,21 @@ var getHeadlessEthereumMethods = ({
|
|
|
571
649
|
});
|
|
572
650
|
|
|
573
651
|
// src/sdk/headless-solana.ts
|
|
652
|
+
var SCOPES_SIGN2 = ["keyshare_read", "sign"];
|
|
574
653
|
var getHeadlessSolanaMethods = ({
|
|
575
654
|
transport,
|
|
576
655
|
passkey,
|
|
577
|
-
publishableKey
|
|
656
|
+
publishableKey,
|
|
657
|
+
relyingPartyOrigin
|
|
578
658
|
}) => ({
|
|
579
|
-
signSolanaMessageHeadless: async (params) =>
|
|
659
|
+
signSolanaMessageHeadless: async (params) => {
|
|
580
660
|
if (!transport.isReady()) throw new Error("SDK not ready");
|
|
581
|
-
const { userHandleB64url, credentialIdB64url } = await
|
|
661
|
+
const { userHandleB64url, credentialIdB64url, tokens } = await getInternalPresenceTokens({
|
|
582
662
|
transport,
|
|
583
663
|
passkey,
|
|
584
664
|
publishableKey,
|
|
585
|
-
|
|
665
|
+
relyingPartyOrigin,
|
|
666
|
+
scopes: SCOPES_SIGN2
|
|
586
667
|
});
|
|
587
668
|
const { signature } = await transport.send(
|
|
588
669
|
PostMessageType.WALLET,
|
|
@@ -593,18 +674,24 @@ var getHeadlessSolanaMethods = ({
|
|
|
593
674
|
wallet: params.wallet,
|
|
594
675
|
uiOptions: params.options?.uiOptions,
|
|
595
676
|
userHandleB64url,
|
|
596
|
-
credentialIdB64url
|
|
677
|
+
credentialIdB64url,
|
|
678
|
+
presenceTokens: flattenPresenceTokens({
|
|
679
|
+
tokens,
|
|
680
|
+
userHandleB64url,
|
|
681
|
+
credentialIdB64url
|
|
682
|
+
})
|
|
597
683
|
}
|
|
598
684
|
);
|
|
599
685
|
return { signature: arrayLikeToBytes(signature) };
|
|
600
|
-
}
|
|
601
|
-
signSolanaTransactionHeadless: async (params) =>
|
|
686
|
+
},
|
|
687
|
+
signSolanaTransactionHeadless: async (params) => {
|
|
602
688
|
if (!transport.isReady()) throw new Error("SDK not ready");
|
|
603
|
-
const { userHandleB64url, credentialIdB64url } = await
|
|
689
|
+
const { userHandleB64url, credentialIdB64url, tokens } = await getInternalPresenceTokens({
|
|
604
690
|
transport,
|
|
605
691
|
passkey,
|
|
606
692
|
publishableKey,
|
|
607
|
-
|
|
693
|
+
relyingPartyOrigin,
|
|
694
|
+
scopes: SCOPES_SIGN2
|
|
608
695
|
});
|
|
609
696
|
const { signedTransaction } = await transport.send(
|
|
610
697
|
PostMessageType.WALLET,
|
|
@@ -615,18 +702,24 @@ var getHeadlessSolanaMethods = ({
|
|
|
615
702
|
wallet: params.wallet,
|
|
616
703
|
options: params.options,
|
|
617
704
|
userHandleB64url,
|
|
618
|
-
credentialIdB64url
|
|
705
|
+
credentialIdB64url,
|
|
706
|
+
presenceTokens: flattenPresenceTokens({
|
|
707
|
+
tokens,
|
|
708
|
+
userHandleB64url,
|
|
709
|
+
credentialIdB64url
|
|
710
|
+
})
|
|
619
711
|
}
|
|
620
712
|
);
|
|
621
713
|
return { signedTransaction: await bs58ToBytes(signedTransaction) };
|
|
622
|
-
}
|
|
623
|
-
sendSolanaTransactionHeadless: async (params) =>
|
|
714
|
+
},
|
|
715
|
+
sendSolanaTransactionHeadless: async (params) => {
|
|
624
716
|
if (!transport.isReady()) throw new Error("SDK not ready");
|
|
625
|
-
const { userHandleB64url, credentialIdB64url } = await
|
|
717
|
+
const { userHandleB64url, credentialIdB64url, tokens } = await getInternalPresenceTokens({
|
|
626
718
|
transport,
|
|
627
719
|
passkey,
|
|
628
720
|
publishableKey,
|
|
629
|
-
|
|
721
|
+
relyingPartyOrigin,
|
|
722
|
+
scopes: SCOPES_SIGN2
|
|
630
723
|
});
|
|
631
724
|
const { signedTransaction } = await transport.send(
|
|
632
725
|
PostMessageType.WALLET,
|
|
@@ -637,7 +730,12 @@ var getHeadlessSolanaMethods = ({
|
|
|
637
730
|
wallet: params.wallet,
|
|
638
731
|
options: params.options,
|
|
639
732
|
userHandleB64url,
|
|
640
|
-
credentialIdB64url
|
|
733
|
+
credentialIdB64url,
|
|
734
|
+
presenceTokens: flattenPresenceTokens({
|
|
735
|
+
tokens,
|
|
736
|
+
userHandleB64url,
|
|
737
|
+
credentialIdB64url
|
|
738
|
+
})
|
|
641
739
|
}
|
|
642
740
|
);
|
|
643
741
|
const broadcastSignature = await broadcastSolanaSigned(
|
|
@@ -645,7 +743,7 @@ var getHeadlessSolanaMethods = ({
|
|
|
645
743
|
signedTransaction
|
|
646
744
|
);
|
|
647
745
|
return { signature: await bs58ToBytes(broadcastSignature) };
|
|
648
|
-
}
|
|
746
|
+
},
|
|
649
747
|
getSolanaBalance: async (params) => {
|
|
650
748
|
if (!transport.isReady()) throw new Error("SDK not ready");
|
|
651
749
|
return transport.send(
|
|
@@ -757,11 +855,17 @@ var getHeadlessAuthenticationMethods = ({
|
|
|
757
855
|
});
|
|
758
856
|
|
|
759
857
|
// src/sdk/headless-general.ts
|
|
858
|
+
var SCOPES_CREATE_WALLET = ["dek_bootstrap", "keyshare_write"];
|
|
859
|
+
var SCOPES_IMPORT_KEY = ["dek_bootstrap", "keyshare_write"];
|
|
860
|
+
var SCOPES_REMOVE_PASSKEY = ["passkey_remove"];
|
|
861
|
+
var SCOPES_PROVISION_EPHEMERAL_SIGNER = ["keyshare_read"];
|
|
862
|
+
var SCOPES_REVOKE_EPHEMERAL_SIGNER = ["ephemeral_signer_revoke"];
|
|
760
863
|
var getHeadlessGeneralMethods = ({
|
|
761
864
|
transport,
|
|
762
865
|
passkey,
|
|
763
866
|
storage,
|
|
764
867
|
publishableKey,
|
|
868
|
+
relyingPartyOrigin,
|
|
765
869
|
setIsAuthenticated,
|
|
766
870
|
setUser
|
|
767
871
|
}) => ({
|
|
@@ -771,18 +875,38 @@ var getHeadlessGeneralMethods = ({
|
|
|
771
875
|
{ publishableKey }
|
|
772
876
|
),
|
|
773
877
|
removePasskey: async (credentialIdB64url) => {
|
|
878
|
+
const {
|
|
879
|
+
tokens,
|
|
880
|
+
userHandleB64url,
|
|
881
|
+
credentialIdB64url: assertedCredId
|
|
882
|
+
} = await getInternalPresenceTokens({
|
|
883
|
+
transport,
|
|
884
|
+
passkey,
|
|
885
|
+
publishableKey,
|
|
886
|
+
relyingPartyOrigin,
|
|
887
|
+
scopes: SCOPES_REMOVE_PASSKEY
|
|
888
|
+
});
|
|
774
889
|
await transport.send(
|
|
775
890
|
PostMessageType.AUTH,
|
|
776
891
|
PostMessageMethod.REMOVE_PASSKEY,
|
|
777
|
-
{
|
|
892
|
+
{
|
|
893
|
+
publishableKey,
|
|
894
|
+
credentialIdB64url,
|
|
895
|
+
presenceTokens: flattenPresenceTokens({
|
|
896
|
+
tokens,
|
|
897
|
+
userHandleB64url,
|
|
898
|
+
credentialIdB64url: assertedCredId
|
|
899
|
+
})
|
|
900
|
+
}
|
|
778
901
|
);
|
|
779
902
|
},
|
|
780
|
-
createWallet: (walletType, options) =>
|
|
781
|
-
const { userHandleB64url, credentialIdB64url } = await
|
|
903
|
+
createWallet: async (walletType, options) => {
|
|
904
|
+
const { userHandleB64url, credentialIdB64url, tokens } = await getInternalPresenceTokens({
|
|
782
905
|
transport,
|
|
783
906
|
passkey,
|
|
784
907
|
publishableKey,
|
|
785
|
-
|
|
908
|
+
relyingPartyOrigin,
|
|
909
|
+
scopes: SCOPES_CREATE_WALLET
|
|
786
910
|
});
|
|
787
911
|
const wallet = await transport.send(
|
|
788
912
|
PostMessageType.WALLET,
|
|
@@ -792,17 +916,23 @@ var getHeadlessGeneralMethods = ({
|
|
|
792
916
|
publishableKey,
|
|
793
917
|
options,
|
|
794
918
|
userHandleB64url,
|
|
795
|
-
credentialIdB64url
|
|
919
|
+
credentialIdB64url,
|
|
920
|
+
presenceTokens: flattenPresenceTokens({
|
|
921
|
+
tokens,
|
|
922
|
+
userHandleB64url,
|
|
923
|
+
credentialIdB64url
|
|
924
|
+
})
|
|
796
925
|
}
|
|
797
926
|
);
|
|
798
927
|
return { wallet };
|
|
799
|
-
}
|
|
800
|
-
importKey: (walletType, key
|
|
801
|
-
const { userHandleB64url, credentialIdB64url } = await
|
|
928
|
+
},
|
|
929
|
+
importKey: async (walletType, key) => {
|
|
930
|
+
const { userHandleB64url, credentialIdB64url, tokens } = await getInternalPresenceTokens({
|
|
802
931
|
transport,
|
|
803
932
|
passkey,
|
|
804
933
|
publishableKey,
|
|
805
|
-
|
|
934
|
+
relyingPartyOrigin,
|
|
935
|
+
scopes: SCOPES_IMPORT_KEY
|
|
806
936
|
});
|
|
807
937
|
const wallet = await transport.send(
|
|
808
938
|
PostMessageType.WALLET,
|
|
@@ -812,11 +942,93 @@ var getHeadlessGeneralMethods = ({
|
|
|
812
942
|
publishableKey,
|
|
813
943
|
key,
|
|
814
944
|
userHandleB64url,
|
|
815
|
-
credentialIdB64url
|
|
945
|
+
credentialIdB64url,
|
|
946
|
+
presenceTokens: flattenPresenceTokens({
|
|
947
|
+
tokens,
|
|
948
|
+
userHandleB64url,
|
|
949
|
+
credentialIdB64url
|
|
950
|
+
})
|
|
816
951
|
}
|
|
817
952
|
);
|
|
818
953
|
return { wallet };
|
|
819
|
-
}
|
|
954
|
+
},
|
|
955
|
+
provisionEphemeralSigner: async (params) => {
|
|
956
|
+
const walletCount = params.walletIds.length;
|
|
957
|
+
if (walletCount === 0) {
|
|
958
|
+
throw new Error(
|
|
959
|
+
"provisionEphemeralSigner: at least one walletId required"
|
|
960
|
+
);
|
|
961
|
+
}
|
|
962
|
+
const { userHandleB64url, credentialIdB64url, tokenBatches } = await getInternalPresenceTokens({
|
|
963
|
+
transport,
|
|
964
|
+
passkey,
|
|
965
|
+
publishableKey,
|
|
966
|
+
relyingPartyOrigin,
|
|
967
|
+
scopeCounts: { [SCOPES_PROVISION_EPHEMERAL_SIGNER[0]]: walletCount }
|
|
968
|
+
});
|
|
969
|
+
const keyshareReadBatch = (tokenBatches[SCOPES_PROVISION_EPHEMERAL_SIGNER[0]] ?? []).map((t) => t.token);
|
|
970
|
+
if (keyshareReadBatch.length !== walletCount) {
|
|
971
|
+
throw new Error(
|
|
972
|
+
`provisionEphemeralSigner: server returned ${keyshareReadBatch.length} tokens, expected ${walletCount}`
|
|
973
|
+
);
|
|
974
|
+
}
|
|
975
|
+
return transport.send(
|
|
976
|
+
PostMessageType.WALLET,
|
|
977
|
+
PostMessageMethod.PROVISION_EPHEMERAL_SIGNER,
|
|
978
|
+
{
|
|
979
|
+
publishableKey,
|
|
980
|
+
userHandleB64url,
|
|
981
|
+
credentialIdB64url,
|
|
982
|
+
// One keyshare_read token per wallet, parallel to params.walletIds
|
|
983
|
+
// (iframe consumes them positionally after wallet resolution).
|
|
984
|
+
presenceTokenBatches: {
|
|
985
|
+
[SCOPES_PROVISION_EPHEMERAL_SIGNER[0]]: keyshareReadBatch
|
|
986
|
+
},
|
|
987
|
+
walletIds: params.walletIds,
|
|
988
|
+
expiresAt: params.expiresAt?.toISOString(),
|
|
989
|
+
label: params.label
|
|
990
|
+
}
|
|
991
|
+
);
|
|
992
|
+
},
|
|
993
|
+
// Read-only: list the user's active (non-revoked) provisioned agents
|
|
994
|
+
// for the current app. No WebAuthn ceremony needed — the wallet
|
|
995
|
+
// session JWT is enough since this exposes only metadata (api_pub,
|
|
996
|
+
// key_ids, expiry) and not the private agent material.
|
|
997
|
+
listEphemeralSigners: async () => {
|
|
998
|
+
return transport.send(
|
|
999
|
+
PostMessageType.WALLET,
|
|
1000
|
+
PostMessageMethod.LIST_EPHEMERAL_SIGNERS,
|
|
1001
|
+
{ publishableKey }
|
|
1002
|
+
);
|
|
1003
|
+
},
|
|
1004
|
+
// Soft-revoke a signer (and forward the revoke to SES). Requires a
|
|
1005
|
+
// fresh WebAuthn-bound presence token: ephemeral_signer_revoke scope. Wallet JWT
|
|
1006
|
+
// alone isn't enough because revoke is destructive (DoS-grade) — the
|
|
1007
|
+
// presence proof confirms it's really the user driving it.
|
|
1008
|
+
revokeEphemeralSigner: async (params) => {
|
|
1009
|
+
const { userHandleB64url, credentialIdB64url, tokens } = await getInternalPresenceTokens({
|
|
1010
|
+
transport,
|
|
1011
|
+
passkey,
|
|
1012
|
+
publishableKey,
|
|
1013
|
+
relyingPartyOrigin,
|
|
1014
|
+
scopes: SCOPES_REVOKE_EPHEMERAL_SIGNER
|
|
1015
|
+
});
|
|
1016
|
+
await transport.send(
|
|
1017
|
+
PostMessageType.WALLET,
|
|
1018
|
+
PostMessageMethod.REVOKE_EPHEMERAL_SIGNER,
|
|
1019
|
+
{
|
|
1020
|
+
publishableKey,
|
|
1021
|
+
apiPubHex: params.apiPubHex,
|
|
1022
|
+
userHandleB64url,
|
|
1023
|
+
credentialIdB64url,
|
|
1024
|
+
presenceTokens: flattenPresenceTokens({
|
|
1025
|
+
tokens,
|
|
1026
|
+
userHandleB64url,
|
|
1027
|
+
credentialIdB64url
|
|
1028
|
+
})
|
|
1029
|
+
}
|
|
1030
|
+
);
|
|
1031
|
+
},
|
|
820
1032
|
getWallets: async (walletType) => {
|
|
821
1033
|
const { wallets } = await transport.send(
|
|
822
1034
|
PostMessageType.WALLET,
|
|
@@ -833,11 +1045,9 @@ var getHeadlessGeneralMethods = ({
|
|
|
833
1045
|
// silently extend session lifetime.
|
|
834
1046
|
getSessionTokens: async () => {
|
|
835
1047
|
try {
|
|
836
|
-
const session = await transport.send(
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
{ publishableKey }
|
|
840
|
-
);
|
|
1048
|
+
const session = await transport.send(PostMessageType.AUTH, PostMessageMethod.GET_CURRENT_SESSION, {
|
|
1049
|
+
publishableKey
|
|
1050
|
+
});
|
|
841
1051
|
return session ? {
|
|
842
1052
|
accessToken: session.accessToken,
|
|
843
1053
|
identityToken: session.identityToken,
|
|
@@ -856,7 +1066,6 @@ var getHeadlessGeneralMethods = ({
|
|
|
856
1066
|
await transport.send(PostMessageType.AUTH, PostMessageMethod.LOGOUT, {
|
|
857
1067
|
publishableKey
|
|
858
1068
|
});
|
|
859
|
-
clearParentAssertCache();
|
|
860
1069
|
await storage.remove("id_token");
|
|
861
1070
|
if (setIsAuthenticated) setIsAuthenticated(false);
|
|
862
1071
|
if (setUser) setUser(null);
|
|
@@ -902,12 +1111,157 @@ var getHeadlessGeneralMethods = ({
|
|
|
902
1111
|
}
|
|
903
1112
|
}
|
|
904
1113
|
});
|
|
1114
|
+
|
|
1115
|
+
// src/sdk/ephemeral-signer-sign.ts
|
|
1116
|
+
var import_ed25519 = require("@noble/curves/ed25519");
|
|
1117
|
+
var import_utils = require("@noble/hashes/utils");
|
|
1118
|
+
function normalizeBase(url) {
|
|
1119
|
+
return url.replace(/\/+$/, "");
|
|
1120
|
+
}
|
|
1121
|
+
var EphemeralSignerSignError = class extends Error {
|
|
1122
|
+
constructor(message, status, body) {
|
|
1123
|
+
super(message);
|
|
1124
|
+
this.status = status;
|
|
1125
|
+
this.body = body;
|
|
1126
|
+
this.name = "EphemeralSignerSignError";
|
|
1127
|
+
}
|
|
1128
|
+
};
|
|
1129
|
+
var bindingsCache = /* @__PURE__ */ new Map();
|
|
1130
|
+
async function resolveBinding(input) {
|
|
1131
|
+
const cached = bindingsCache.get(input.apiPubHex);
|
|
1132
|
+
if (cached) {
|
|
1133
|
+
const hit2 = cached.find((b) => b.walletId === input.walletId);
|
|
1134
|
+
if (hit2) return hit2;
|
|
1135
|
+
}
|
|
1136
|
+
const issuedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
1137
|
+
const signedBodyBytes = new TextEncoder().encode(
|
|
1138
|
+
JSON.stringify({ issued_at: issuedAt })
|
|
1139
|
+
);
|
|
1140
|
+
const apiPrivBytes = (0, import_utils.hexToBytes)(input.apiPrivHex);
|
|
1141
|
+
const agentSig = import_ed25519.ed25519.sign(signedBodyBytes, apiPrivBytes);
|
|
1142
|
+
const url = `${normalizeBase(input.baseUrl)}/v0/wallets/ephemeral-signers/me/wallets`;
|
|
1143
|
+
const fetchFn = input.fetchImpl ?? fetch;
|
|
1144
|
+
let response;
|
|
1145
|
+
try {
|
|
1146
|
+
response = await fetchFn(url, {
|
|
1147
|
+
method: "POST",
|
|
1148
|
+
headers: {
|
|
1149
|
+
"Content-Type": "application/json",
|
|
1150
|
+
Authorization: `PublicToken ${input.publishableKey}`
|
|
1151
|
+
},
|
|
1152
|
+
body: JSON.stringify({
|
|
1153
|
+
api_pub: input.apiPubHex,
|
|
1154
|
+
signed_body: (0, import_utils.bytesToHex)(signedBodyBytes),
|
|
1155
|
+
agent_signature: (0, import_utils.bytesToHex)(agentSig)
|
|
1156
|
+
})
|
|
1157
|
+
});
|
|
1158
|
+
} catch (e) {
|
|
1159
|
+
throw new EphemeralSignerSignError(
|
|
1160
|
+
`wallet binding fetch failed: ${e instanceof Error ? e.message : String(e)}`
|
|
1161
|
+
);
|
|
1162
|
+
}
|
|
1163
|
+
if (!response.ok) {
|
|
1164
|
+
const body = await response.text().catch(() => "");
|
|
1165
|
+
throw new EphemeralSignerSignError(
|
|
1166
|
+
`wallet binding fetch failed: ${response.status}`,
|
|
1167
|
+
response.status,
|
|
1168
|
+
body
|
|
1169
|
+
);
|
|
1170
|
+
}
|
|
1171
|
+
const json = await response.json();
|
|
1172
|
+
const bindings = json.wallets.map((w) => ({
|
|
1173
|
+
walletId: w.wallet_id,
|
|
1174
|
+
keyId: w.key_id,
|
|
1175
|
+
derivationPath: w.derivation_path
|
|
1176
|
+
}));
|
|
1177
|
+
bindingsCache.set(input.apiPubHex, bindings);
|
|
1178
|
+
const hit = bindings.find((b) => b.walletId === input.walletId);
|
|
1179
|
+
if (!hit) {
|
|
1180
|
+
throw new EphemeralSignerSignError(
|
|
1181
|
+
`walletId ${input.walletId} is not authorized for this agent`
|
|
1182
|
+
);
|
|
1183
|
+
}
|
|
1184
|
+
return hit;
|
|
1185
|
+
}
|
|
1186
|
+
async function signWithEphemeralSigner(input) {
|
|
1187
|
+
if (!/^[0-9a-f]{64}$/i.test(input.apiPubHex)) {
|
|
1188
|
+
throw new EphemeralSignerSignError(
|
|
1189
|
+
"apiPubHex must be 64 lowercase hex chars (32-byte Ed25519 pubkey)"
|
|
1190
|
+
);
|
|
1191
|
+
}
|
|
1192
|
+
if (!/^[0-9a-f]{64}$/i.test(input.apiPrivHex)) {
|
|
1193
|
+
throw new EphemeralSignerSignError(
|
|
1194
|
+
"apiPrivHex must be 64 lowercase hex chars (32-byte Ed25519 privkey)"
|
|
1195
|
+
);
|
|
1196
|
+
}
|
|
1197
|
+
if (!input.walletId) {
|
|
1198
|
+
throw new EphemeralSignerSignError("walletId is required");
|
|
1199
|
+
}
|
|
1200
|
+
if (!input.rawSigningPayloadHex || !/^[0-9a-f]+$/i.test(input.rawSigningPayloadHex)) {
|
|
1201
|
+
throw new EphemeralSignerSignError(
|
|
1202
|
+
"rawSigningPayloadHex must be a non-empty lowercase hex string"
|
|
1203
|
+
);
|
|
1204
|
+
}
|
|
1205
|
+
if (!input.publishableKey) {
|
|
1206
|
+
throw new EphemeralSignerSignError(
|
|
1207
|
+
"publishableKey is required \u2014 wallets backend gates /ephemeral-signers/* with RequirePublicToken"
|
|
1208
|
+
);
|
|
1209
|
+
}
|
|
1210
|
+
const binding = await resolveBinding(input);
|
|
1211
|
+
const issuedAt = (input.issuedAt ?? /* @__PURE__ */ new Date()).toISOString();
|
|
1212
|
+
const signedPayload = {
|
|
1213
|
+
raw_signing_payload: input.rawSigningPayloadHex,
|
|
1214
|
+
key_id: binding.keyId,
|
|
1215
|
+
derivation_path: binding.derivationPath,
|
|
1216
|
+
issued_at: issuedAt
|
|
1217
|
+
};
|
|
1218
|
+
const signedBodyBytes = new TextEncoder().encode(
|
|
1219
|
+
JSON.stringify(signedPayload)
|
|
1220
|
+
);
|
|
1221
|
+
const apiPrivBytes = (0, import_utils.hexToBytes)(input.apiPrivHex);
|
|
1222
|
+
const agentSig = import_ed25519.ed25519.sign(signedBodyBytes, apiPrivBytes);
|
|
1223
|
+
const requestBody = {
|
|
1224
|
+
api_pub: input.apiPubHex,
|
|
1225
|
+
signed_body: (0, import_utils.bytesToHex)(signedBodyBytes),
|
|
1226
|
+
agent_signature: (0, import_utils.bytesToHex)(agentSig)
|
|
1227
|
+
};
|
|
1228
|
+
const url = `${normalizeBase(input.baseUrl)}/v0/wallets/ephemeral-signers/sign`;
|
|
1229
|
+
const fetchFn = input.fetchImpl ?? fetch;
|
|
1230
|
+
let response;
|
|
1231
|
+
try {
|
|
1232
|
+
response = await fetchFn(url, {
|
|
1233
|
+
method: "POST",
|
|
1234
|
+
headers: {
|
|
1235
|
+
"Content-Type": "application/json",
|
|
1236
|
+
Authorization: `PublicToken ${input.publishableKey}`
|
|
1237
|
+
},
|
|
1238
|
+
body: JSON.stringify(requestBody)
|
|
1239
|
+
});
|
|
1240
|
+
} catch (e) {
|
|
1241
|
+
throw new EphemeralSignerSignError(
|
|
1242
|
+
`transport failure: ${e instanceof Error ? e.message : String(e)}`
|
|
1243
|
+
);
|
|
1244
|
+
}
|
|
1245
|
+
if (!response.ok) {
|
|
1246
|
+
const body = await response.text().catch(() => "");
|
|
1247
|
+
throw new EphemeralSignerSignError(
|
|
1248
|
+
`ephemeral signer sign failed: ${response.status}`,
|
|
1249
|
+
response.status,
|
|
1250
|
+
body
|
|
1251
|
+
);
|
|
1252
|
+
}
|
|
1253
|
+
return await response.json();
|
|
1254
|
+
}
|
|
905
1255
|
// Annotate the CommonJS export names for ESM import in node:
|
|
906
1256
|
0 && (module.exports = {
|
|
1257
|
+
EphemeralSignerSignError,
|
|
907
1258
|
assertPasskeyInParent,
|
|
1259
|
+
flattenPresenceTokens,
|
|
908
1260
|
getHeadlessAuthenticationMethods,
|
|
909
1261
|
getHeadlessEthereumMethods,
|
|
910
1262
|
getHeadlessGeneralMethods,
|
|
911
1263
|
getHeadlessSolanaMethods,
|
|
912
|
-
|
|
1264
|
+
getInternalPresenceTokens,
|
|
1265
|
+
getPresenceToken,
|
|
1266
|
+
signWithEphemeralSigner
|
|
913
1267
|
});
|