@moon-x/core 0.4.0 → 0.6.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/dist/{chunk-6LTEG7VN.mjs → chunk-I56GRKAG.mjs} +19 -0
- 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-pNTEOKaK.d.ts → interfaces-BWxOajnD.d.mts} +17 -2
- package/dist/{interfaces-cdKh3sLA.d.mts → interfaces-BZ5GMWS9.d.ts} +17 -2
- package/dist/lib/index.d.mts +32 -2
- package/dist/lib/index.d.ts +32 -2
- package/dist/lib/index.js +21 -0
- package/dist/lib/index.mjs +5 -1
- 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 +68 -14
- package/dist/sdk/index.d.ts +68 -14
- package/dist/sdk/index.js +280 -20
- package/dist/sdk/index.mjs +264 -21
- package/dist/types/index.d.mts +135 -3
- package/dist/types/index.d.ts +135 -3
- 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.mjs +1 -1
- package/package.json +3 -1
- package/dist/chain-C9dvKXUY.d.mts +0 -48
- package/dist/chain-C9dvKXUY.d.ts +0 -48
package/dist/sdk/index.d.ts
CHANGED
|
@@ -1,9 +1,8 @@
|
|
|
1
|
-
import { T as Transport, P as PasskeyAssertor, K as KvStorage } from '../interfaces-
|
|
2
|
-
export { O as OAuthOpener, a as PlatformImpls, W as WebAuthnAssertionResponse, b as WebAuthnRequestOptions } from '../interfaces-
|
|
1
|
+
import { T as Transport, P as PasskeyAssertor, R as RelyingPartyOriginInput, K as KvStorage } from '../interfaces-BZ5GMWS9.js';
|
|
2
|
+
export { O as OAuthOpener, a as PlatformImpls, W as WebAuthnAssertionResponse, b as WebAuthnRequestOptions, r as resolveRelyingPartyOrigin } from '../interfaces-BZ5GMWS9.js';
|
|
3
3
|
import { C as CachedAssertion } from '../passkey-cache-WnDFQ-v4.js';
|
|
4
|
-
import { EthereumSignMessageParams, EthereumSignMessageResult, EthereumSignTransactionParams, EthereumSignTransactionResult, EthereumSignTypedDataParams, EthereumSignTypedDataResult, EthereumSignHashParams, EthereumSignHashResult, EthereumSign7702AuthorizationParams, EthereumSign7702AuthorizationResult, EthereumSendTransactionParams, EthereumSendTransactionResult, EthereumGetBalanceParams, EthereumGetBalanceResult, EthereumGetTokenAccountsByOwnerParams, EthereumGetTokenAccountsByOwnerResult, SolanaSignMessageParams, SolanaSignMessageResult, SolanaSignTransactionParams, SolanaSignTransactionResult, SolanaSendTransactionParams, SolanaSendTransactionResult, SolanaGetBalanceParams, SolanaGetBalanceResult, SolanaGetTokenAccountsByOwnerParams, SolanaGetTokenAccountsByOwnerResult, SendEmailOtpResponse, PublicWallet } from '../types/index.js';
|
|
5
|
-
import '../post-message-
|
|
6
|
-
import '../chain-C9dvKXUY.js';
|
|
4
|
+
import { EthereumSignMessageParams, EthereumSignMessageResult, EthereumSignTransactionParams, EthereumSignTransactionResult, EthereumSignTypedDataParams, EthereumSignTypedDataResult, EthereumSignHashParams, EthereumSignHashResult, EthereumSign7702AuthorizationParams, EthereumSign7702AuthorizationResult, EthereumSendTransactionParams, EthereumSendTransactionResult, EthereumGetBalanceParams, EthereumGetBalanceResult, EthereumGetTokenAccountsByOwnerParams, EthereumGetTokenAccountsByOwnerResult, SolanaSignMessageParams, SolanaSignMessageResult, SolanaSignTransactionParams, SolanaSignTransactionResult, SolanaSendTransactionParams, SolanaSendTransactionResult, SolanaGetBalanceParams, SolanaGetBalanceResult, SolanaGetTokenAccountsByOwnerParams, SolanaGetTokenAccountsByOwnerResult, SendEmailOtpResponse, PublicWallet, ProvisionEphemeralSignerParams, ProvisionEphemeralSignerResult, ListEphemeralSignersResult, RevokeEphemeralSignerParams } from '../types/index.js';
|
|
5
|
+
import '../post-message-Z6cLf0mS.js';
|
|
7
6
|
|
|
8
7
|
type AssertPasskeyInParentResult = CachedAssertion;
|
|
9
8
|
declare const assertPasskeyInParent: ({ transport, passkey, publishableKey, validateCredentialInAllowList, }: {
|
|
@@ -21,7 +20,7 @@ declare const getPresenceToken: ({ transport, passkey, publishableKey, relyingPa
|
|
|
21
20
|
transport: Transport;
|
|
22
21
|
passkey: PasskeyAssertor;
|
|
23
22
|
publishableKey: string;
|
|
24
|
-
relyingPartyOrigin:
|
|
23
|
+
relyingPartyOrigin: RelyingPartyOriginInput;
|
|
25
24
|
}) => Promise<GetPresenceTokenResult>;
|
|
26
25
|
|
|
27
26
|
interface ScopedPresenceToken {
|
|
@@ -30,23 +29,25 @@ interface ScopedPresenceToken {
|
|
|
30
29
|
}
|
|
31
30
|
interface GetInternalPresenceTokensResult {
|
|
32
31
|
tokens: Record<string, ScopedPresenceToken>;
|
|
32
|
+
tokenBatches: Record<string, ScopedPresenceToken[]>;
|
|
33
33
|
userHandleB64url: string;
|
|
34
34
|
credentialIdB64url: string;
|
|
35
35
|
}
|
|
36
|
-
declare const getInternalPresenceTokens: ({ transport, passkey, publishableKey, relyingPartyOrigin, scopes, }: {
|
|
36
|
+
declare const getInternalPresenceTokens: ({ transport, passkey, publishableKey, relyingPartyOrigin, scopes, scopeCounts, }: {
|
|
37
37
|
transport: Transport;
|
|
38
38
|
passkey: PasskeyAssertor;
|
|
39
39
|
publishableKey: string;
|
|
40
|
-
relyingPartyOrigin:
|
|
41
|
-
scopes
|
|
40
|
+
relyingPartyOrigin: RelyingPartyOriginInput;
|
|
41
|
+
scopes?: string[];
|
|
42
|
+
scopeCounts?: Record<string, number>;
|
|
42
43
|
}) => Promise<GetInternalPresenceTokensResult>;
|
|
43
|
-
declare const flattenPresenceTokens: (result: GetInternalPresenceTokensResult) => Record<string, string>;
|
|
44
|
+
declare const flattenPresenceTokens: (result: Pick<GetInternalPresenceTokensResult, "tokens"> & Partial<GetInternalPresenceTokensResult>) => Record<string, string>;
|
|
44
45
|
|
|
45
46
|
declare const getHeadlessEthereumMethods: ({ transport, passkey, publishableKey, relyingPartyOrigin, }: {
|
|
46
47
|
transport: Transport;
|
|
47
48
|
passkey: PasskeyAssertor;
|
|
48
49
|
publishableKey: string;
|
|
49
|
-
relyingPartyOrigin:
|
|
50
|
+
relyingPartyOrigin: RelyingPartyOriginInput;
|
|
50
51
|
}) => {
|
|
51
52
|
signEthereumMessageHeadless: (params: EthereumSignMessageParams) => Promise<EthereumSignMessageResult>;
|
|
52
53
|
signEthereumTransactionHeadless: (params: EthereumSignTransactionParams) => Promise<EthereumSignTransactionResult>;
|
|
@@ -68,7 +69,7 @@ declare const getHeadlessSolanaMethods: ({ transport, passkey, publishableKey, r
|
|
|
68
69
|
transport: Transport;
|
|
69
70
|
passkey: PasskeyAssertor;
|
|
70
71
|
publishableKey: string;
|
|
71
|
-
relyingPartyOrigin:
|
|
72
|
+
relyingPartyOrigin: RelyingPartyOriginInput;
|
|
72
73
|
}) => {
|
|
73
74
|
signSolanaMessageHeadless: (params: SolanaSignMessageParams) => Promise<SolanaSignMessageResult>;
|
|
74
75
|
signSolanaTransactionHeadless: (params: SolanaSignTransactionParams) => Promise<SolanaSignTransactionResult>;
|
|
@@ -122,7 +123,7 @@ declare const getHeadlessGeneralMethods: ({ transport, passkey, storage, publish
|
|
|
122
123
|
passkey: PasskeyAssertor;
|
|
123
124
|
storage: KvStorage;
|
|
124
125
|
publishableKey: string;
|
|
125
|
-
relyingPartyOrigin:
|
|
126
|
+
relyingPartyOrigin: RelyingPartyOriginInput;
|
|
126
127
|
setIsAuthenticated?: (isAuth: boolean) => void;
|
|
127
128
|
setUser?: (user: unknown | null) => void;
|
|
128
129
|
}) => {
|
|
@@ -137,6 +138,9 @@ declare const getHeadlessGeneralMethods: ({ transport, passkey, storage, publish
|
|
|
137
138
|
importKey: (walletType: "solana" | "ethereum", key: string) => Promise<{
|
|
138
139
|
wallet: PublicWallet;
|
|
139
140
|
}>;
|
|
141
|
+
provisionEphemeralSigner: (params: ProvisionEphemeralSignerParams) => Promise<ProvisionEphemeralSignerResult>;
|
|
142
|
+
listEphemeralSigners: () => Promise<ListEphemeralSignersResult>;
|
|
143
|
+
revokeEphemeralSigner: (params: RevokeEphemeralSignerParams) => Promise<void>;
|
|
140
144
|
getWallets: (walletType: "solana" | "ethereum") => Promise<{
|
|
141
145
|
wallets: unknown[];
|
|
142
146
|
walletType: string;
|
|
@@ -154,4 +158,54 @@ declare const getHeadlessGeneralMethods: ({ transport, passkey, storage, publish
|
|
|
154
158
|
getUser: () => Promise<unknown>;
|
|
155
159
|
};
|
|
156
160
|
|
|
157
|
-
|
|
161
|
+
interface EphemeralSignerSignInput {
|
|
162
|
+
/** Lowercase-hex 32-byte Ed25519 agent public key (no 0x prefix). */
|
|
163
|
+
apiPubHex: string;
|
|
164
|
+
/** Lowercase-hex 32-byte Ed25519 agent private key (no 0x prefix). */
|
|
165
|
+
apiPrivHex: string;
|
|
166
|
+
/**
|
|
167
|
+
* Wallet UUID (from `user.wallets[i].id`) the agent should sign on
|
|
168
|
+
* behalf of. Must be one of the wallets the agent was provisioned
|
|
169
|
+
* for. The SDK resolves this internally to the wallet's MPC `key_id`
|
|
170
|
+
* + stored `derivation_path` — integrators never see those values.
|
|
171
|
+
*/
|
|
172
|
+
walletId: string;
|
|
173
|
+
/**
|
|
174
|
+
* Lowercase-hex digest to sign — keccak256 of the message/tx for
|
|
175
|
+
* ECDSA, raw bytes for Ed25519. No 0x prefix.
|
|
176
|
+
*/
|
|
177
|
+
rawSigningPayloadHex: string;
|
|
178
|
+
/** Defaults to now. SES rejects timestamps further than ±5 min from its clock. */
|
|
179
|
+
issuedAt?: Date;
|
|
180
|
+
/** Wallets backend base URL (no trailing slash). */
|
|
181
|
+
baseUrl: string;
|
|
182
|
+
/**
|
|
183
|
+
* MoonX publishable key (`moon_pk_…`). The wallets backend's
|
|
184
|
+
* /ephemeral-signers/* router group is gated by RequirePublicToken — every
|
|
185
|
+
* call needs an `Authorization: PublicToken <publishableKey>` header.
|
|
186
|
+
*/
|
|
187
|
+
publishableKey: string;
|
|
188
|
+
/** Optional fetch override — e.g. for Next.js route handlers or test stubs. */
|
|
189
|
+
fetchImpl?: typeof fetch;
|
|
190
|
+
}
|
|
191
|
+
interface EphemeralSignerSignResult {
|
|
192
|
+
scheme: "ecdsa_secp256k1" | "eddsa_ed25519";
|
|
193
|
+
signature: {
|
|
194
|
+
/** ECDSA only. Lowercase-hex 32-byte r. */
|
|
195
|
+
r?: string;
|
|
196
|
+
/** ECDSA only. Lowercase-hex 32-byte s. */
|
|
197
|
+
s?: string;
|
|
198
|
+
/** ECDSA only. 0..3. */
|
|
199
|
+
recovery_id?: number;
|
|
200
|
+
/** Ed25519 only. Lowercase-hex 64-byte signature. */
|
|
201
|
+
signature?: string;
|
|
202
|
+
};
|
|
203
|
+
}
|
|
204
|
+
declare class EphemeralSignerSignError extends Error {
|
|
205
|
+
readonly status?: number | undefined;
|
|
206
|
+
readonly body?: string | undefined;
|
|
207
|
+
constructor(message: string, status?: number | undefined, body?: string | undefined);
|
|
208
|
+
}
|
|
209
|
+
declare function signWithEphemeralSigner(input: EphemeralSignerSignInput): Promise<EphemeralSignerSignResult>;
|
|
210
|
+
|
|
211
|
+
export { type AssertPasskeyInParentResult, EphemeralSignerSignError, type EphemeralSignerSignInput, type EphemeralSignerSignResult, type GetInternalPresenceTokensResult, type GetPresenceTokenResult, KvStorage, type LoginWithCodeParams, PasskeyAssertor, RelyingPartyOriginInput, type ScopedPresenceToken, type SendCodeParams, Transport, type VerifyOAuthParams, assertPasskeyInParent, flattenPresenceTokens, getHeadlessAuthenticationMethods, getHeadlessEthereumMethods, getHeadlessGeneralMethods, getHeadlessSolanaMethods, getInternalPresenceTokens, getPresenceToken, signWithEphemeralSigner };
|
package/dist/sdk/index.js
CHANGED
|
@@ -30,6 +30,7 @@ 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,
|
|
34
35
|
flattenPresenceTokens: () => flattenPresenceTokens,
|
|
35
36
|
getHeadlessAuthenticationMethods: () => getHeadlessAuthenticationMethods,
|
|
@@ -37,10 +38,15 @@ __export(sdk_exports, {
|
|
|
37
38
|
getHeadlessGeneralMethods: () => getHeadlessGeneralMethods,
|
|
38
39
|
getHeadlessSolanaMethods: () => getHeadlessSolanaMethods,
|
|
39
40
|
getInternalPresenceTokens: () => getInternalPresenceTokens,
|
|
40
|
-
getPresenceToken: () => getPresenceToken
|
|
41
|
+
getPresenceToken: () => getPresenceToken,
|
|
42
|
+
resolveRelyingPartyOrigin: () => resolveRelyingPartyOrigin,
|
|
43
|
+
signWithEphemeralSigner: () => signWithEphemeralSigner
|
|
41
44
|
});
|
|
42
45
|
module.exports = __toCommonJS(sdk_exports);
|
|
43
46
|
|
|
47
|
+
// src/sdk/interfaces.ts
|
|
48
|
+
var resolveRelyingPartyOrigin = async (input) => typeof input === "function" ? input() : input;
|
|
49
|
+
|
|
44
50
|
// src/lib/auth/authentication-state.ts
|
|
45
51
|
var AuthenticationState = class {
|
|
46
52
|
constructor() {
|
|
@@ -244,6 +250,20 @@ var PostMessageMethod = {
|
|
|
244
250
|
// dispatcher boring.
|
|
245
251
|
SIGN_HASH: "SIGN_HASH",
|
|
246
252
|
SIGN_7702_AUTHORIZATION: "SIGN_7702_AUTHORIZATION",
|
|
253
|
+
// Provision a SES (Secure Ephemeral Signer) over one or more of the
|
|
254
|
+
// user's MPC wallets. Iframe verifies the Nitro attestation, decrypts
|
|
255
|
+
// the selected keyshares, HPKE-seals them to the verified enclave
|
|
256
|
+
// pubkey, and returns a freshly-generated Ed25519 signer keypair.
|
|
257
|
+
// MoonX never persists the private key — the parent must hand it to
|
|
258
|
+
// the user immediately.
|
|
259
|
+
PROVISION_EPHEMERAL_SIGNER: "PROVISION_EPHEMERAL_SIGNER",
|
|
260
|
+
// List the user's active provisioned ephemeral signers from the
|
|
261
|
+
// wallets backend. Read-only; doesn't touch SES or the enclave.
|
|
262
|
+
LIST_EPHEMERAL_SIGNERS: "LIST_EPHEMERAL_SIGNERS",
|
|
263
|
+
// Soft-revoke a previously-provisioned ephemeral signer. The wallets
|
|
264
|
+
// backend updates revoked_at locally and forwards the revoke to SES
|
|
265
|
+
// so the enclave drops the policy.
|
|
266
|
+
REVOKE_EPHEMERAL_SIGNER: "REVOKE_EPHEMERAL_SIGNER",
|
|
247
267
|
VERIFY_EMAIL_OTP: "VERIFY_EMAIL_OTP",
|
|
248
268
|
VERIFY_OAUTH: "VERIFY_OAUTH",
|
|
249
269
|
START_OAUTH: "START_OAUTH",
|
|
@@ -329,10 +349,11 @@ var getPresenceToken = async ({
|
|
|
329
349
|
publishableKey,
|
|
330
350
|
relyingPartyOrigin
|
|
331
351
|
}) => {
|
|
352
|
+
const rpOrigin = await resolveRelyingPartyOrigin(relyingPartyOrigin);
|
|
332
353
|
const { token, optionsJSON } = await transport.send(
|
|
333
354
|
PostMessageType.AUTH,
|
|
334
355
|
PostMessageMethod.PASSKEY_PRESENCE_BEGIN,
|
|
335
|
-
{ publishableKey, relyingPartyOrigin }
|
|
356
|
+
{ publishableKey, relyingPartyOrigin: rpOrigin }
|
|
336
357
|
);
|
|
337
358
|
const response = await passkey.assertForServer({ optionsJSON });
|
|
338
359
|
const verify = await transport.send(
|
|
@@ -340,7 +361,7 @@ var getPresenceToken = async ({
|
|
|
340
361
|
PostMessageMethod.PASSKEY_PRESENCE_VERIFY,
|
|
341
362
|
{
|
|
342
363
|
publishableKey,
|
|
343
|
-
relyingPartyOrigin,
|
|
364
|
+
relyingPartyOrigin: rpOrigin,
|
|
344
365
|
token,
|
|
345
366
|
response
|
|
346
367
|
}
|
|
@@ -357,32 +378,46 @@ var getInternalPresenceTokens = async ({
|
|
|
357
378
|
passkey,
|
|
358
379
|
publishableKey,
|
|
359
380
|
relyingPartyOrigin,
|
|
360
|
-
scopes
|
|
381
|
+
scopes,
|
|
382
|
+
scopeCounts
|
|
361
383
|
}) => {
|
|
384
|
+
const rpOrigin = await resolveRelyingPartyOrigin(relyingPartyOrigin);
|
|
362
385
|
const { token, optionsJSON } = await transport.send(
|
|
363
386
|
PostMessageType.AUTH,
|
|
364
387
|
PostMessageMethod.PASSKEY_PRESENCE_BEGIN,
|
|
365
|
-
{ publishableKey, relyingPartyOrigin }
|
|
388
|
+
{ publishableKey, relyingPartyOrigin: rpOrigin }
|
|
366
389
|
);
|
|
367
390
|
const { response, userHandleB64url, credentialIdB64url } = await passkey.assertForInternalPresence({ optionsJSON });
|
|
391
|
+
const verifyPayload = {
|
|
392
|
+
publishableKey,
|
|
393
|
+
relyingPartyOrigin: rpOrigin,
|
|
394
|
+
token,
|
|
395
|
+
response,
|
|
396
|
+
purpose: "internal"
|
|
397
|
+
};
|
|
398
|
+
if (scopes && scopes.length > 0) verifyPayload.scopes = scopes;
|
|
399
|
+
if (scopeCounts && Object.keys(scopeCounts).length > 0) {
|
|
400
|
+
verifyPayload.scope_counts = scopeCounts;
|
|
401
|
+
}
|
|
368
402
|
const verify = await transport.send(
|
|
369
403
|
PostMessageType.AUTH,
|
|
370
404
|
PostMessageMethod.PASSKEY_PRESENCE_VERIFY,
|
|
371
|
-
|
|
372
|
-
publishableKey,
|
|
373
|
-
relyingPartyOrigin,
|
|
374
|
-
token,
|
|
375
|
-
response,
|
|
376
|
-
purpose: "internal",
|
|
377
|
-
scopes
|
|
378
|
-
}
|
|
405
|
+
verifyPayload
|
|
379
406
|
);
|
|
380
407
|
const out = {};
|
|
381
408
|
for (const [scope, t] of Object.entries(verify.tokens ?? {})) {
|
|
382
409
|
out[scope] = { token: t.token, expiresAt: t.expires_at };
|
|
383
410
|
}
|
|
411
|
+
const outBatches = {};
|
|
412
|
+
for (const [scope, batch] of Object.entries(verify.token_batches ?? {})) {
|
|
413
|
+
outBatches[scope] = batch.map((t) => ({
|
|
414
|
+
token: t.token,
|
|
415
|
+
expiresAt: t.expires_at
|
|
416
|
+
}));
|
|
417
|
+
}
|
|
384
418
|
return {
|
|
385
419
|
tokens: out,
|
|
420
|
+
tokenBatches: outBatches,
|
|
386
421
|
userHandleB64url,
|
|
387
422
|
credentialIdB64url
|
|
388
423
|
};
|
|
@@ -829,6 +864,8 @@ var getHeadlessAuthenticationMethods = ({
|
|
|
829
864
|
var SCOPES_CREATE_WALLET = ["dek_bootstrap", "keyshare_write"];
|
|
830
865
|
var SCOPES_IMPORT_KEY = ["dek_bootstrap", "keyshare_write"];
|
|
831
866
|
var SCOPES_REMOVE_PASSKEY = ["passkey_remove"];
|
|
867
|
+
var SCOPES_PROVISION_EPHEMERAL_SIGNER = ["keyshare_read"];
|
|
868
|
+
var SCOPES_REVOKE_EPHEMERAL_SIGNER = ["ephemeral_signer_revoke"];
|
|
832
869
|
var getHeadlessGeneralMethods = ({
|
|
833
870
|
transport,
|
|
834
871
|
passkey,
|
|
@@ -844,7 +881,11 @@ var getHeadlessGeneralMethods = ({
|
|
|
844
881
|
{ publishableKey }
|
|
845
882
|
),
|
|
846
883
|
removePasskey: async (credentialIdB64url) => {
|
|
847
|
-
const {
|
|
884
|
+
const {
|
|
885
|
+
tokens,
|
|
886
|
+
userHandleB64url,
|
|
887
|
+
credentialIdB64url: assertedCredId
|
|
888
|
+
} = await getInternalPresenceTokens({
|
|
848
889
|
transport,
|
|
849
890
|
passkey,
|
|
850
891
|
publishableKey,
|
|
@@ -917,6 +958,83 @@ var getHeadlessGeneralMethods = ({
|
|
|
917
958
|
);
|
|
918
959
|
return { wallet };
|
|
919
960
|
},
|
|
961
|
+
provisionEphemeralSigner: async (params) => {
|
|
962
|
+
const walletCount = params.walletIds.length;
|
|
963
|
+
if (walletCount === 0) {
|
|
964
|
+
throw new Error(
|
|
965
|
+
"provisionEphemeralSigner: at least one walletId required"
|
|
966
|
+
);
|
|
967
|
+
}
|
|
968
|
+
const { userHandleB64url, credentialIdB64url, tokenBatches } = await getInternalPresenceTokens({
|
|
969
|
+
transport,
|
|
970
|
+
passkey,
|
|
971
|
+
publishableKey,
|
|
972
|
+
relyingPartyOrigin,
|
|
973
|
+
scopeCounts: { [SCOPES_PROVISION_EPHEMERAL_SIGNER[0]]: walletCount }
|
|
974
|
+
});
|
|
975
|
+
const keyshareReadBatch = (tokenBatches[SCOPES_PROVISION_EPHEMERAL_SIGNER[0]] ?? []).map((t) => t.token);
|
|
976
|
+
if (keyshareReadBatch.length !== walletCount) {
|
|
977
|
+
throw new Error(
|
|
978
|
+
`provisionEphemeralSigner: server returned ${keyshareReadBatch.length} tokens, expected ${walletCount}`
|
|
979
|
+
);
|
|
980
|
+
}
|
|
981
|
+
return transport.send(
|
|
982
|
+
PostMessageType.WALLET,
|
|
983
|
+
PostMessageMethod.PROVISION_EPHEMERAL_SIGNER,
|
|
984
|
+
{
|
|
985
|
+
publishableKey,
|
|
986
|
+
userHandleB64url,
|
|
987
|
+
credentialIdB64url,
|
|
988
|
+
// One keyshare_read token per wallet, parallel to params.walletIds
|
|
989
|
+
// (iframe consumes them positionally after wallet resolution).
|
|
990
|
+
presenceTokenBatches: {
|
|
991
|
+
[SCOPES_PROVISION_EPHEMERAL_SIGNER[0]]: keyshareReadBatch
|
|
992
|
+
},
|
|
993
|
+
walletIds: params.walletIds,
|
|
994
|
+
expiresAt: params.expiresAt?.toISOString(),
|
|
995
|
+
label: params.label
|
|
996
|
+
}
|
|
997
|
+
);
|
|
998
|
+
},
|
|
999
|
+
// Read-only: list the user's active (non-revoked) provisioned agents
|
|
1000
|
+
// for the current app. No WebAuthn ceremony needed — the wallet
|
|
1001
|
+
// session JWT is enough since this exposes only metadata (api_pub,
|
|
1002
|
+
// key_ids, expiry) and not the private agent material.
|
|
1003
|
+
listEphemeralSigners: async () => {
|
|
1004
|
+
return transport.send(
|
|
1005
|
+
PostMessageType.WALLET,
|
|
1006
|
+
PostMessageMethod.LIST_EPHEMERAL_SIGNERS,
|
|
1007
|
+
{ publishableKey }
|
|
1008
|
+
);
|
|
1009
|
+
},
|
|
1010
|
+
// Soft-revoke a signer (and forward the revoke to SES). Requires a
|
|
1011
|
+
// fresh WebAuthn-bound presence token: ephemeral_signer_revoke scope. Wallet JWT
|
|
1012
|
+
// alone isn't enough because revoke is destructive (DoS-grade) — the
|
|
1013
|
+
// presence proof confirms it's really the user driving it.
|
|
1014
|
+
revokeEphemeralSigner: async (params) => {
|
|
1015
|
+
const { userHandleB64url, credentialIdB64url, tokens } = await getInternalPresenceTokens({
|
|
1016
|
+
transport,
|
|
1017
|
+
passkey,
|
|
1018
|
+
publishableKey,
|
|
1019
|
+
relyingPartyOrigin,
|
|
1020
|
+
scopes: SCOPES_REVOKE_EPHEMERAL_SIGNER
|
|
1021
|
+
});
|
|
1022
|
+
await transport.send(
|
|
1023
|
+
PostMessageType.WALLET,
|
|
1024
|
+
PostMessageMethod.REVOKE_EPHEMERAL_SIGNER,
|
|
1025
|
+
{
|
|
1026
|
+
publishableKey,
|
|
1027
|
+
apiPubHex: params.apiPubHex,
|
|
1028
|
+
userHandleB64url,
|
|
1029
|
+
credentialIdB64url,
|
|
1030
|
+
presenceTokens: flattenPresenceTokens({
|
|
1031
|
+
tokens,
|
|
1032
|
+
userHandleB64url,
|
|
1033
|
+
credentialIdB64url
|
|
1034
|
+
})
|
|
1035
|
+
}
|
|
1036
|
+
);
|
|
1037
|
+
},
|
|
920
1038
|
getWallets: async (walletType) => {
|
|
921
1039
|
const { wallets } = await transport.send(
|
|
922
1040
|
PostMessageType.WALLET,
|
|
@@ -933,11 +1051,9 @@ var getHeadlessGeneralMethods = ({
|
|
|
933
1051
|
// silently extend session lifetime.
|
|
934
1052
|
getSessionTokens: async () => {
|
|
935
1053
|
try {
|
|
936
|
-
const session = await transport.send(
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
{ publishableKey }
|
|
940
|
-
);
|
|
1054
|
+
const session = await transport.send(PostMessageType.AUTH, PostMessageMethod.GET_CURRENT_SESSION, {
|
|
1055
|
+
publishableKey
|
|
1056
|
+
});
|
|
941
1057
|
return session ? {
|
|
942
1058
|
accessToken: session.accessToken,
|
|
943
1059
|
identityToken: session.identityToken,
|
|
@@ -1001,8 +1117,150 @@ var getHeadlessGeneralMethods = ({
|
|
|
1001
1117
|
}
|
|
1002
1118
|
}
|
|
1003
1119
|
});
|
|
1120
|
+
|
|
1121
|
+
// src/sdk/ephemeral-signer-sign.ts
|
|
1122
|
+
var import_ed25519 = require("@noble/curves/ed25519");
|
|
1123
|
+
var import_utils = require("@noble/hashes/utils");
|
|
1124
|
+
function normalizeBase(url) {
|
|
1125
|
+
return url.replace(/\/+$/, "");
|
|
1126
|
+
}
|
|
1127
|
+
var EphemeralSignerSignError = class extends Error {
|
|
1128
|
+
constructor(message, status, body) {
|
|
1129
|
+
super(message);
|
|
1130
|
+
this.status = status;
|
|
1131
|
+
this.body = body;
|
|
1132
|
+
this.name = "EphemeralSignerSignError";
|
|
1133
|
+
}
|
|
1134
|
+
};
|
|
1135
|
+
var bindingsCache = /* @__PURE__ */ new Map();
|
|
1136
|
+
async function resolveBinding(input) {
|
|
1137
|
+
const cached = bindingsCache.get(input.apiPubHex);
|
|
1138
|
+
if (cached) {
|
|
1139
|
+
const hit2 = cached.find((b) => b.walletId === input.walletId);
|
|
1140
|
+
if (hit2) return hit2;
|
|
1141
|
+
}
|
|
1142
|
+
const issuedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
1143
|
+
const signedBodyBytes = new TextEncoder().encode(
|
|
1144
|
+
JSON.stringify({ issued_at: issuedAt })
|
|
1145
|
+
);
|
|
1146
|
+
const apiPrivBytes = (0, import_utils.hexToBytes)(input.apiPrivHex);
|
|
1147
|
+
const agentSig = import_ed25519.ed25519.sign(signedBodyBytes, apiPrivBytes);
|
|
1148
|
+
const url = `${normalizeBase(input.baseUrl)}/v0/wallets/ephemeral-signers/me/wallets`;
|
|
1149
|
+
const fetchFn = input.fetchImpl ?? fetch;
|
|
1150
|
+
let response;
|
|
1151
|
+
try {
|
|
1152
|
+
response = await fetchFn(url, {
|
|
1153
|
+
method: "POST",
|
|
1154
|
+
headers: {
|
|
1155
|
+
"Content-Type": "application/json",
|
|
1156
|
+
Authorization: `PublicToken ${input.publishableKey}`
|
|
1157
|
+
},
|
|
1158
|
+
body: JSON.stringify({
|
|
1159
|
+
api_pub: input.apiPubHex,
|
|
1160
|
+
signed_body: (0, import_utils.bytesToHex)(signedBodyBytes),
|
|
1161
|
+
agent_signature: (0, import_utils.bytesToHex)(agentSig)
|
|
1162
|
+
})
|
|
1163
|
+
});
|
|
1164
|
+
} catch (e) {
|
|
1165
|
+
throw new EphemeralSignerSignError(
|
|
1166
|
+
`wallet binding fetch failed: ${e instanceof Error ? e.message : String(e)}`
|
|
1167
|
+
);
|
|
1168
|
+
}
|
|
1169
|
+
if (!response.ok) {
|
|
1170
|
+
const body = await response.text().catch(() => "");
|
|
1171
|
+
throw new EphemeralSignerSignError(
|
|
1172
|
+
`wallet binding fetch failed: ${response.status}`,
|
|
1173
|
+
response.status,
|
|
1174
|
+
body
|
|
1175
|
+
);
|
|
1176
|
+
}
|
|
1177
|
+
const json = await response.json();
|
|
1178
|
+
const bindings = json.wallets.map((w) => ({
|
|
1179
|
+
walletId: w.wallet_id,
|
|
1180
|
+
keyId: w.key_id,
|
|
1181
|
+
derivationPath: w.derivation_path
|
|
1182
|
+
}));
|
|
1183
|
+
bindingsCache.set(input.apiPubHex, bindings);
|
|
1184
|
+
const hit = bindings.find((b) => b.walletId === input.walletId);
|
|
1185
|
+
if (!hit) {
|
|
1186
|
+
throw new EphemeralSignerSignError(
|
|
1187
|
+
`walletId ${input.walletId} is not authorized for this agent`
|
|
1188
|
+
);
|
|
1189
|
+
}
|
|
1190
|
+
return hit;
|
|
1191
|
+
}
|
|
1192
|
+
async function signWithEphemeralSigner(input) {
|
|
1193
|
+
if (!/^[0-9a-f]{64}$/i.test(input.apiPubHex)) {
|
|
1194
|
+
throw new EphemeralSignerSignError(
|
|
1195
|
+
"apiPubHex must be 64 lowercase hex chars (32-byte Ed25519 pubkey)"
|
|
1196
|
+
);
|
|
1197
|
+
}
|
|
1198
|
+
if (!/^[0-9a-f]{64}$/i.test(input.apiPrivHex)) {
|
|
1199
|
+
throw new EphemeralSignerSignError(
|
|
1200
|
+
"apiPrivHex must be 64 lowercase hex chars (32-byte Ed25519 privkey)"
|
|
1201
|
+
);
|
|
1202
|
+
}
|
|
1203
|
+
if (!input.walletId) {
|
|
1204
|
+
throw new EphemeralSignerSignError("walletId is required");
|
|
1205
|
+
}
|
|
1206
|
+
if (!input.rawSigningPayloadHex || !/^[0-9a-f]+$/i.test(input.rawSigningPayloadHex)) {
|
|
1207
|
+
throw new EphemeralSignerSignError(
|
|
1208
|
+
"rawSigningPayloadHex must be a non-empty lowercase hex string"
|
|
1209
|
+
);
|
|
1210
|
+
}
|
|
1211
|
+
if (!input.publishableKey) {
|
|
1212
|
+
throw new EphemeralSignerSignError(
|
|
1213
|
+
"publishableKey is required \u2014 wallets backend gates /ephemeral-signers/* with RequirePublicToken"
|
|
1214
|
+
);
|
|
1215
|
+
}
|
|
1216
|
+
const binding = await resolveBinding(input);
|
|
1217
|
+
const issuedAt = (input.issuedAt ?? /* @__PURE__ */ new Date()).toISOString();
|
|
1218
|
+
const signedPayload = {
|
|
1219
|
+
raw_signing_payload: input.rawSigningPayloadHex,
|
|
1220
|
+
key_id: binding.keyId,
|
|
1221
|
+
derivation_path: binding.derivationPath,
|
|
1222
|
+
issued_at: issuedAt
|
|
1223
|
+
};
|
|
1224
|
+
const signedBodyBytes = new TextEncoder().encode(
|
|
1225
|
+
JSON.stringify(signedPayload)
|
|
1226
|
+
);
|
|
1227
|
+
const apiPrivBytes = (0, import_utils.hexToBytes)(input.apiPrivHex);
|
|
1228
|
+
const agentSig = import_ed25519.ed25519.sign(signedBodyBytes, apiPrivBytes);
|
|
1229
|
+
const requestBody = {
|
|
1230
|
+
api_pub: input.apiPubHex,
|
|
1231
|
+
signed_body: (0, import_utils.bytesToHex)(signedBodyBytes),
|
|
1232
|
+
agent_signature: (0, import_utils.bytesToHex)(agentSig)
|
|
1233
|
+
};
|
|
1234
|
+
const url = `${normalizeBase(input.baseUrl)}/v0/wallets/ephemeral-signers/sign`;
|
|
1235
|
+
const fetchFn = input.fetchImpl ?? fetch;
|
|
1236
|
+
let response;
|
|
1237
|
+
try {
|
|
1238
|
+
response = await fetchFn(url, {
|
|
1239
|
+
method: "POST",
|
|
1240
|
+
headers: {
|
|
1241
|
+
"Content-Type": "application/json",
|
|
1242
|
+
Authorization: `PublicToken ${input.publishableKey}`
|
|
1243
|
+
},
|
|
1244
|
+
body: JSON.stringify(requestBody)
|
|
1245
|
+
});
|
|
1246
|
+
} catch (e) {
|
|
1247
|
+
throw new EphemeralSignerSignError(
|
|
1248
|
+
`transport failure: ${e instanceof Error ? e.message : String(e)}`
|
|
1249
|
+
);
|
|
1250
|
+
}
|
|
1251
|
+
if (!response.ok) {
|
|
1252
|
+
const body = await response.text().catch(() => "");
|
|
1253
|
+
throw new EphemeralSignerSignError(
|
|
1254
|
+
`ephemeral signer sign failed: ${response.status}`,
|
|
1255
|
+
response.status,
|
|
1256
|
+
body
|
|
1257
|
+
);
|
|
1258
|
+
}
|
|
1259
|
+
return await response.json();
|
|
1260
|
+
}
|
|
1004
1261
|
// Annotate the CommonJS export names for ESM import in node:
|
|
1005
1262
|
0 && (module.exports = {
|
|
1263
|
+
EphemeralSignerSignError,
|
|
1006
1264
|
assertPasskeyInParent,
|
|
1007
1265
|
flattenPresenceTokens,
|
|
1008
1266
|
getHeadlessAuthenticationMethods,
|
|
@@ -1010,5 +1268,7 @@ var getHeadlessGeneralMethods = ({
|
|
|
1010
1268
|
getHeadlessGeneralMethods,
|
|
1011
1269
|
getHeadlessSolanaMethods,
|
|
1012
1270
|
getInternalPresenceTokens,
|
|
1013
|
-
getPresenceToken
|
|
1271
|
+
getPresenceToken,
|
|
1272
|
+
resolveRelyingPartyOrigin,
|
|
1273
|
+
signWithEphemeralSigner
|
|
1014
1274
|
});
|