@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.mjs
CHANGED
|
@@ -1,20 +1,16 @@
|
|
|
1
1
|
import {
|
|
2
2
|
PostMessageMethod,
|
|
3
3
|
PostMessageType
|
|
4
|
-
} from "../chunk-
|
|
4
|
+
} from "../chunk-JU5MWLXH.mjs";
|
|
5
5
|
import {
|
|
6
6
|
arrayLikeToBytes,
|
|
7
7
|
authState,
|
|
8
8
|
broadcastEthereumRaw,
|
|
9
9
|
broadcastSolanaSigned,
|
|
10
10
|
bs58ToBytes,
|
|
11
|
-
clearParentAssertCache,
|
|
12
|
-
readParentAssertCache,
|
|
13
11
|
serializeEthereumTransaction,
|
|
14
|
-
toB64url
|
|
15
|
-
|
|
16
|
-
writeParentAssertCache
|
|
17
|
-
} from "../chunk-CDT4MC7S.mjs";
|
|
12
|
+
toB64url
|
|
13
|
+
} from "../chunk-I56GRKAG.mjs";
|
|
18
14
|
import "../chunk-GQKIA37O.mjs";
|
|
19
15
|
|
|
20
16
|
// src/sdk/parent-passkey-assert.ts
|
|
@@ -22,13 +18,8 @@ var assertPasskeyInParent = async ({
|
|
|
22
18
|
transport,
|
|
23
19
|
passkey,
|
|
24
20
|
publishableKey,
|
|
25
|
-
requireFreshAssertion = false,
|
|
26
21
|
validateCredentialInAllowList = false
|
|
27
22
|
}) => {
|
|
28
|
-
if (!requireFreshAssertion) {
|
|
29
|
-
const cached = readParentAssertCache();
|
|
30
|
-
if (cached) return cached;
|
|
31
|
-
}
|
|
32
23
|
const dekInfo = await transport.send(
|
|
33
24
|
PostMessageType.AUTH,
|
|
34
25
|
PostMessageMethod.GET_DEK_INFO,
|
|
@@ -52,12 +43,10 @@ var assertPasskeyInParent = async ({
|
|
|
52
43
|
if (validateCredentialInAllowList && !allowList.includes(credential.rawIdB64url)) {
|
|
53
44
|
throw new Error("unknown_passkey_for_this_account");
|
|
54
45
|
}
|
|
55
|
-
|
|
46
|
+
return {
|
|
56
47
|
userHandleB64url: credential.userHandleB64url,
|
|
57
48
|
credentialIdB64url: credential.rawIdB64url
|
|
58
49
|
};
|
|
59
|
-
writeParentAssertCache(result);
|
|
60
|
-
return result;
|
|
61
50
|
};
|
|
62
51
|
|
|
63
52
|
// src/sdk/get-presence-token.ts
|
|
@@ -89,19 +78,79 @@ var getPresenceToken = async ({
|
|
|
89
78
|
};
|
|
90
79
|
};
|
|
91
80
|
|
|
81
|
+
// src/sdk/get-internal-presence-tokens.ts
|
|
82
|
+
var getInternalPresenceTokens = async ({
|
|
83
|
+
transport,
|
|
84
|
+
passkey,
|
|
85
|
+
publishableKey,
|
|
86
|
+
relyingPartyOrigin,
|
|
87
|
+
scopes,
|
|
88
|
+
scopeCounts
|
|
89
|
+
}) => {
|
|
90
|
+
const { token, optionsJSON } = await transport.send(
|
|
91
|
+
PostMessageType.AUTH,
|
|
92
|
+
PostMessageMethod.PASSKEY_PRESENCE_BEGIN,
|
|
93
|
+
{ publishableKey, relyingPartyOrigin }
|
|
94
|
+
);
|
|
95
|
+
const { response, userHandleB64url, credentialIdB64url } = await passkey.assertForInternalPresence({ optionsJSON });
|
|
96
|
+
const verifyPayload = {
|
|
97
|
+
publishableKey,
|
|
98
|
+
relyingPartyOrigin,
|
|
99
|
+
token,
|
|
100
|
+
response,
|
|
101
|
+
purpose: "internal"
|
|
102
|
+
};
|
|
103
|
+
if (scopes && scopes.length > 0) verifyPayload.scopes = scopes;
|
|
104
|
+
if (scopeCounts && Object.keys(scopeCounts).length > 0) {
|
|
105
|
+
verifyPayload.scope_counts = scopeCounts;
|
|
106
|
+
}
|
|
107
|
+
const verify = await transport.send(
|
|
108
|
+
PostMessageType.AUTH,
|
|
109
|
+
PostMessageMethod.PASSKEY_PRESENCE_VERIFY,
|
|
110
|
+
verifyPayload
|
|
111
|
+
);
|
|
112
|
+
const out = {};
|
|
113
|
+
for (const [scope, t] of Object.entries(verify.tokens ?? {})) {
|
|
114
|
+
out[scope] = { token: t.token, expiresAt: t.expires_at };
|
|
115
|
+
}
|
|
116
|
+
const outBatches = {};
|
|
117
|
+
for (const [scope, batch] of Object.entries(verify.token_batches ?? {})) {
|
|
118
|
+
outBatches[scope] = batch.map((t) => ({
|
|
119
|
+
token: t.token,
|
|
120
|
+
expiresAt: t.expires_at
|
|
121
|
+
}));
|
|
122
|
+
}
|
|
123
|
+
return {
|
|
124
|
+
tokens: out,
|
|
125
|
+
tokenBatches: outBatches,
|
|
126
|
+
userHandleB64url,
|
|
127
|
+
credentialIdB64url
|
|
128
|
+
};
|
|
129
|
+
};
|
|
130
|
+
var flattenPresenceTokens = (result) => {
|
|
131
|
+
const out = {};
|
|
132
|
+
for (const [scope, t] of Object.entries(result.tokens)) {
|
|
133
|
+
out[scope] = t.token;
|
|
134
|
+
}
|
|
135
|
+
return out;
|
|
136
|
+
};
|
|
137
|
+
|
|
92
138
|
// src/sdk/headless-ethereum.ts
|
|
139
|
+
var SCOPES_SIGN = ["keyshare_read", "sign"];
|
|
93
140
|
var getHeadlessEthereumMethods = ({
|
|
94
141
|
transport,
|
|
95
142
|
passkey,
|
|
96
|
-
publishableKey
|
|
143
|
+
publishableKey,
|
|
144
|
+
relyingPartyOrigin
|
|
97
145
|
}) => ({
|
|
98
|
-
signEthereumMessageHeadless: async (params) =>
|
|
146
|
+
signEthereumMessageHeadless: async (params) => {
|
|
99
147
|
if (!transport.isReady()) throw new Error("SDK not ready");
|
|
100
|
-
const { userHandleB64url, credentialIdB64url } = await
|
|
148
|
+
const { userHandleB64url, credentialIdB64url, tokens } = await getInternalPresenceTokens({
|
|
101
149
|
transport,
|
|
102
150
|
passkey,
|
|
103
151
|
publishableKey,
|
|
104
|
-
|
|
152
|
+
relyingPartyOrigin,
|
|
153
|
+
scopes: SCOPES_SIGN
|
|
105
154
|
});
|
|
106
155
|
return transport.send(
|
|
107
156
|
PostMessageType.WALLET,
|
|
@@ -112,17 +161,23 @@ var getHeadlessEthereumMethods = ({
|
|
|
112
161
|
wallet: params.wallet,
|
|
113
162
|
uiOptions: params.options?.uiOptions,
|
|
114
163
|
userHandleB64url,
|
|
115
|
-
credentialIdB64url
|
|
164
|
+
credentialIdB64url,
|
|
165
|
+
presenceTokens: flattenPresenceTokens({
|
|
166
|
+
tokens,
|
|
167
|
+
userHandleB64url,
|
|
168
|
+
credentialIdB64url
|
|
169
|
+
})
|
|
116
170
|
}
|
|
117
171
|
);
|
|
118
|
-
}
|
|
119
|
-
signEthereumTransactionHeadless: async (params) =>
|
|
172
|
+
},
|
|
173
|
+
signEthereumTransactionHeadless: async (params) => {
|
|
120
174
|
if (!transport.isReady()) throw new Error("SDK not ready");
|
|
121
|
-
const { userHandleB64url, credentialIdB64url } = await
|
|
175
|
+
const { userHandleB64url, credentialIdB64url, tokens } = await getInternalPresenceTokens({
|
|
122
176
|
transport,
|
|
123
177
|
passkey,
|
|
124
178
|
publishableKey,
|
|
125
|
-
|
|
179
|
+
relyingPartyOrigin,
|
|
180
|
+
scopes: SCOPES_SIGN
|
|
126
181
|
});
|
|
127
182
|
return transport.send(
|
|
128
183
|
PostMessageType.WALLET,
|
|
@@ -134,17 +189,23 @@ var getHeadlessEthereumMethods = ({
|
|
|
134
189
|
wallet: params.wallet,
|
|
135
190
|
options: params.options,
|
|
136
191
|
userHandleB64url,
|
|
137
|
-
credentialIdB64url
|
|
192
|
+
credentialIdB64url,
|
|
193
|
+
presenceTokens: flattenPresenceTokens({
|
|
194
|
+
tokens,
|
|
195
|
+
userHandleB64url,
|
|
196
|
+
credentialIdB64url
|
|
197
|
+
})
|
|
138
198
|
}
|
|
139
199
|
);
|
|
140
|
-
}
|
|
141
|
-
signEthereumTypedDataHeadless: async (params) =>
|
|
200
|
+
},
|
|
201
|
+
signEthereumTypedDataHeadless: async (params) => {
|
|
142
202
|
if (!transport.isReady()) throw new Error("SDK not ready");
|
|
143
|
-
const { userHandleB64url, credentialIdB64url } = await
|
|
203
|
+
const { userHandleB64url, credentialIdB64url, tokens } = await getInternalPresenceTokens({
|
|
144
204
|
transport,
|
|
145
205
|
passkey,
|
|
146
206
|
publishableKey,
|
|
147
|
-
|
|
207
|
+
relyingPartyOrigin,
|
|
208
|
+
scopes: SCOPES_SIGN
|
|
148
209
|
});
|
|
149
210
|
return transport.send(
|
|
150
211
|
PostMessageType.WALLET,
|
|
@@ -158,17 +219,23 @@ var getHeadlessEthereumMethods = ({
|
|
|
158
219
|
wallet: params.wallet,
|
|
159
220
|
options: params.options,
|
|
160
221
|
userHandleB64url,
|
|
161
|
-
credentialIdB64url
|
|
222
|
+
credentialIdB64url,
|
|
223
|
+
presenceTokens: flattenPresenceTokens({
|
|
224
|
+
tokens,
|
|
225
|
+
userHandleB64url,
|
|
226
|
+
credentialIdB64url
|
|
227
|
+
})
|
|
162
228
|
}
|
|
163
229
|
);
|
|
164
|
-
}
|
|
165
|
-
signEthereumHashHeadless: async (params) =>
|
|
230
|
+
},
|
|
231
|
+
signEthereumHashHeadless: async (params) => {
|
|
166
232
|
if (!transport.isReady()) throw new Error("SDK not ready");
|
|
167
|
-
const { userHandleB64url, credentialIdB64url } = await
|
|
233
|
+
const { userHandleB64url, credentialIdB64url, tokens } = await getInternalPresenceTokens({
|
|
168
234
|
transport,
|
|
169
235
|
passkey,
|
|
170
236
|
publishableKey,
|
|
171
|
-
|
|
237
|
+
relyingPartyOrigin,
|
|
238
|
+
scopes: SCOPES_SIGN
|
|
172
239
|
});
|
|
173
240
|
return transport.send(
|
|
174
241
|
PostMessageType.WALLET,
|
|
@@ -179,17 +246,23 @@ var getHeadlessEthereumMethods = ({
|
|
|
179
246
|
wallet: params.wallet,
|
|
180
247
|
options: params.options,
|
|
181
248
|
userHandleB64url,
|
|
182
|
-
credentialIdB64url
|
|
249
|
+
credentialIdB64url,
|
|
250
|
+
presenceTokens: flattenPresenceTokens({
|
|
251
|
+
tokens,
|
|
252
|
+
userHandleB64url,
|
|
253
|
+
credentialIdB64url
|
|
254
|
+
})
|
|
183
255
|
}
|
|
184
256
|
);
|
|
185
|
-
}
|
|
186
|
-
signEthereum7702AuthorizationHeadless: async (params) =>
|
|
257
|
+
},
|
|
258
|
+
signEthereum7702AuthorizationHeadless: async (params) => {
|
|
187
259
|
if (!transport.isReady()) throw new Error("SDK not ready");
|
|
188
|
-
const { userHandleB64url, credentialIdB64url } = await
|
|
260
|
+
const { userHandleB64url, credentialIdB64url, tokens } = await getInternalPresenceTokens({
|
|
189
261
|
transport,
|
|
190
262
|
passkey,
|
|
191
263
|
publishableKey,
|
|
192
|
-
|
|
264
|
+
relyingPartyOrigin,
|
|
265
|
+
scopes: SCOPES_SIGN
|
|
193
266
|
});
|
|
194
267
|
return transport.send(
|
|
195
268
|
PostMessageType.WALLET,
|
|
@@ -203,17 +276,23 @@ var getHeadlessEthereumMethods = ({
|
|
|
203
276
|
wallet: params.wallet,
|
|
204
277
|
options: params.options,
|
|
205
278
|
userHandleB64url,
|
|
206
|
-
credentialIdB64url
|
|
279
|
+
credentialIdB64url,
|
|
280
|
+
presenceTokens: flattenPresenceTokens({
|
|
281
|
+
tokens,
|
|
282
|
+
userHandleB64url,
|
|
283
|
+
credentialIdB64url
|
|
284
|
+
})
|
|
207
285
|
}
|
|
208
286
|
);
|
|
209
|
-
}
|
|
210
|
-
sendEthereumTransactionHeadless: async (params) =>
|
|
287
|
+
},
|
|
288
|
+
sendEthereumTransactionHeadless: async (params) => {
|
|
211
289
|
if (!transport.isReady()) throw new Error("SDK not ready");
|
|
212
|
-
const { userHandleB64url, credentialIdB64url } = await
|
|
290
|
+
const { userHandleB64url, credentialIdB64url, tokens } = await getInternalPresenceTokens({
|
|
213
291
|
transport,
|
|
214
292
|
passkey,
|
|
215
293
|
publishableKey,
|
|
216
|
-
|
|
294
|
+
relyingPartyOrigin,
|
|
295
|
+
scopes: SCOPES_SIGN
|
|
217
296
|
});
|
|
218
297
|
const serializedTransaction = await serializeEthereumTransaction(
|
|
219
298
|
params.transaction
|
|
@@ -227,7 +306,12 @@ var getHeadlessEthereumMethods = ({
|
|
|
227
306
|
wallet: params.wallet,
|
|
228
307
|
options: params.options,
|
|
229
308
|
userHandleB64url,
|
|
230
|
-
credentialIdB64url
|
|
309
|
+
credentialIdB64url,
|
|
310
|
+
presenceTokens: flattenPresenceTokens({
|
|
311
|
+
tokens,
|
|
312
|
+
userHandleB64url,
|
|
313
|
+
credentialIdB64url
|
|
314
|
+
})
|
|
231
315
|
}
|
|
232
316
|
);
|
|
233
317
|
if (!signed.serializedSigned) {
|
|
@@ -240,7 +324,7 @@ var getHeadlessEthereumMethods = ({
|
|
|
240
324
|
signed.serializedSigned
|
|
241
325
|
);
|
|
242
326
|
return { hash };
|
|
243
|
-
}
|
|
327
|
+
},
|
|
244
328
|
getEthereumBalance: async (params) => {
|
|
245
329
|
if (!transport.isReady()) throw new Error("SDK not ready");
|
|
246
330
|
return transport.send(
|
|
@@ -276,18 +360,21 @@ var getHeadlessEthereumMethods = ({
|
|
|
276
360
|
});
|
|
277
361
|
|
|
278
362
|
// src/sdk/headless-solana.ts
|
|
363
|
+
var SCOPES_SIGN2 = ["keyshare_read", "sign"];
|
|
279
364
|
var getHeadlessSolanaMethods = ({
|
|
280
365
|
transport,
|
|
281
366
|
passkey,
|
|
282
|
-
publishableKey
|
|
367
|
+
publishableKey,
|
|
368
|
+
relyingPartyOrigin
|
|
283
369
|
}) => ({
|
|
284
|
-
signSolanaMessageHeadless: async (params) =>
|
|
370
|
+
signSolanaMessageHeadless: async (params) => {
|
|
285
371
|
if (!transport.isReady()) throw new Error("SDK not ready");
|
|
286
|
-
const { userHandleB64url, credentialIdB64url } = await
|
|
372
|
+
const { userHandleB64url, credentialIdB64url, tokens } = await getInternalPresenceTokens({
|
|
287
373
|
transport,
|
|
288
374
|
passkey,
|
|
289
375
|
publishableKey,
|
|
290
|
-
|
|
376
|
+
relyingPartyOrigin,
|
|
377
|
+
scopes: SCOPES_SIGN2
|
|
291
378
|
});
|
|
292
379
|
const { signature } = await transport.send(
|
|
293
380
|
PostMessageType.WALLET,
|
|
@@ -298,18 +385,24 @@ var getHeadlessSolanaMethods = ({
|
|
|
298
385
|
wallet: params.wallet,
|
|
299
386
|
uiOptions: params.options?.uiOptions,
|
|
300
387
|
userHandleB64url,
|
|
301
|
-
credentialIdB64url
|
|
388
|
+
credentialIdB64url,
|
|
389
|
+
presenceTokens: flattenPresenceTokens({
|
|
390
|
+
tokens,
|
|
391
|
+
userHandleB64url,
|
|
392
|
+
credentialIdB64url
|
|
393
|
+
})
|
|
302
394
|
}
|
|
303
395
|
);
|
|
304
396
|
return { signature: arrayLikeToBytes(signature) };
|
|
305
|
-
}
|
|
306
|
-
signSolanaTransactionHeadless: async (params) =>
|
|
397
|
+
},
|
|
398
|
+
signSolanaTransactionHeadless: async (params) => {
|
|
307
399
|
if (!transport.isReady()) throw new Error("SDK not ready");
|
|
308
|
-
const { userHandleB64url, credentialIdB64url } = await
|
|
400
|
+
const { userHandleB64url, credentialIdB64url, tokens } = await getInternalPresenceTokens({
|
|
309
401
|
transport,
|
|
310
402
|
passkey,
|
|
311
403
|
publishableKey,
|
|
312
|
-
|
|
404
|
+
relyingPartyOrigin,
|
|
405
|
+
scopes: SCOPES_SIGN2
|
|
313
406
|
});
|
|
314
407
|
const { signedTransaction } = await transport.send(
|
|
315
408
|
PostMessageType.WALLET,
|
|
@@ -320,18 +413,24 @@ var getHeadlessSolanaMethods = ({
|
|
|
320
413
|
wallet: params.wallet,
|
|
321
414
|
options: params.options,
|
|
322
415
|
userHandleB64url,
|
|
323
|
-
credentialIdB64url
|
|
416
|
+
credentialIdB64url,
|
|
417
|
+
presenceTokens: flattenPresenceTokens({
|
|
418
|
+
tokens,
|
|
419
|
+
userHandleB64url,
|
|
420
|
+
credentialIdB64url
|
|
421
|
+
})
|
|
324
422
|
}
|
|
325
423
|
);
|
|
326
424
|
return { signedTransaction: await bs58ToBytes(signedTransaction) };
|
|
327
|
-
}
|
|
328
|
-
sendSolanaTransactionHeadless: async (params) =>
|
|
425
|
+
},
|
|
426
|
+
sendSolanaTransactionHeadless: async (params) => {
|
|
329
427
|
if (!transport.isReady()) throw new Error("SDK not ready");
|
|
330
|
-
const { userHandleB64url, credentialIdB64url } = await
|
|
428
|
+
const { userHandleB64url, credentialIdB64url, tokens } = await getInternalPresenceTokens({
|
|
331
429
|
transport,
|
|
332
430
|
passkey,
|
|
333
431
|
publishableKey,
|
|
334
|
-
|
|
432
|
+
relyingPartyOrigin,
|
|
433
|
+
scopes: SCOPES_SIGN2
|
|
335
434
|
});
|
|
336
435
|
const { signedTransaction } = await transport.send(
|
|
337
436
|
PostMessageType.WALLET,
|
|
@@ -342,7 +441,12 @@ var getHeadlessSolanaMethods = ({
|
|
|
342
441
|
wallet: params.wallet,
|
|
343
442
|
options: params.options,
|
|
344
443
|
userHandleB64url,
|
|
345
|
-
credentialIdB64url
|
|
444
|
+
credentialIdB64url,
|
|
445
|
+
presenceTokens: flattenPresenceTokens({
|
|
446
|
+
tokens,
|
|
447
|
+
userHandleB64url,
|
|
448
|
+
credentialIdB64url
|
|
449
|
+
})
|
|
346
450
|
}
|
|
347
451
|
);
|
|
348
452
|
const broadcastSignature = await broadcastSolanaSigned(
|
|
@@ -350,7 +454,7 @@ var getHeadlessSolanaMethods = ({
|
|
|
350
454
|
signedTransaction
|
|
351
455
|
);
|
|
352
456
|
return { signature: await bs58ToBytes(broadcastSignature) };
|
|
353
|
-
}
|
|
457
|
+
},
|
|
354
458
|
getSolanaBalance: async (params) => {
|
|
355
459
|
if (!transport.isReady()) throw new Error("SDK not ready");
|
|
356
460
|
return transport.send(
|
|
@@ -462,11 +566,17 @@ var getHeadlessAuthenticationMethods = ({
|
|
|
462
566
|
});
|
|
463
567
|
|
|
464
568
|
// src/sdk/headless-general.ts
|
|
569
|
+
var SCOPES_CREATE_WALLET = ["dek_bootstrap", "keyshare_write"];
|
|
570
|
+
var SCOPES_IMPORT_KEY = ["dek_bootstrap", "keyshare_write"];
|
|
571
|
+
var SCOPES_REMOVE_PASSKEY = ["passkey_remove"];
|
|
572
|
+
var SCOPES_PROVISION_EPHEMERAL_SIGNER = ["keyshare_read"];
|
|
573
|
+
var SCOPES_REVOKE_EPHEMERAL_SIGNER = ["ephemeral_signer_revoke"];
|
|
465
574
|
var getHeadlessGeneralMethods = ({
|
|
466
575
|
transport,
|
|
467
576
|
passkey,
|
|
468
577
|
storage,
|
|
469
578
|
publishableKey,
|
|
579
|
+
relyingPartyOrigin,
|
|
470
580
|
setIsAuthenticated,
|
|
471
581
|
setUser
|
|
472
582
|
}) => ({
|
|
@@ -476,18 +586,38 @@ var getHeadlessGeneralMethods = ({
|
|
|
476
586
|
{ publishableKey }
|
|
477
587
|
),
|
|
478
588
|
removePasskey: async (credentialIdB64url) => {
|
|
589
|
+
const {
|
|
590
|
+
tokens,
|
|
591
|
+
userHandleB64url,
|
|
592
|
+
credentialIdB64url: assertedCredId
|
|
593
|
+
} = await getInternalPresenceTokens({
|
|
594
|
+
transport,
|
|
595
|
+
passkey,
|
|
596
|
+
publishableKey,
|
|
597
|
+
relyingPartyOrigin,
|
|
598
|
+
scopes: SCOPES_REMOVE_PASSKEY
|
|
599
|
+
});
|
|
479
600
|
await transport.send(
|
|
480
601
|
PostMessageType.AUTH,
|
|
481
602
|
PostMessageMethod.REMOVE_PASSKEY,
|
|
482
|
-
{
|
|
603
|
+
{
|
|
604
|
+
publishableKey,
|
|
605
|
+
credentialIdB64url,
|
|
606
|
+
presenceTokens: flattenPresenceTokens({
|
|
607
|
+
tokens,
|
|
608
|
+
userHandleB64url,
|
|
609
|
+
credentialIdB64url: assertedCredId
|
|
610
|
+
})
|
|
611
|
+
}
|
|
483
612
|
);
|
|
484
613
|
},
|
|
485
|
-
createWallet: (walletType, options) =>
|
|
486
|
-
const { userHandleB64url, credentialIdB64url } = await
|
|
614
|
+
createWallet: async (walletType, options) => {
|
|
615
|
+
const { userHandleB64url, credentialIdB64url, tokens } = await getInternalPresenceTokens({
|
|
487
616
|
transport,
|
|
488
617
|
passkey,
|
|
489
618
|
publishableKey,
|
|
490
|
-
|
|
619
|
+
relyingPartyOrigin,
|
|
620
|
+
scopes: SCOPES_CREATE_WALLET
|
|
491
621
|
});
|
|
492
622
|
const wallet = await transport.send(
|
|
493
623
|
PostMessageType.WALLET,
|
|
@@ -497,17 +627,23 @@ var getHeadlessGeneralMethods = ({
|
|
|
497
627
|
publishableKey,
|
|
498
628
|
options,
|
|
499
629
|
userHandleB64url,
|
|
500
|
-
credentialIdB64url
|
|
630
|
+
credentialIdB64url,
|
|
631
|
+
presenceTokens: flattenPresenceTokens({
|
|
632
|
+
tokens,
|
|
633
|
+
userHandleB64url,
|
|
634
|
+
credentialIdB64url
|
|
635
|
+
})
|
|
501
636
|
}
|
|
502
637
|
);
|
|
503
638
|
return { wallet };
|
|
504
|
-
}
|
|
505
|
-
importKey: (walletType, key
|
|
506
|
-
const { userHandleB64url, credentialIdB64url } = await
|
|
639
|
+
},
|
|
640
|
+
importKey: async (walletType, key) => {
|
|
641
|
+
const { userHandleB64url, credentialIdB64url, tokens } = await getInternalPresenceTokens({
|
|
507
642
|
transport,
|
|
508
643
|
passkey,
|
|
509
644
|
publishableKey,
|
|
510
|
-
|
|
645
|
+
relyingPartyOrigin,
|
|
646
|
+
scopes: SCOPES_IMPORT_KEY
|
|
511
647
|
});
|
|
512
648
|
const wallet = await transport.send(
|
|
513
649
|
PostMessageType.WALLET,
|
|
@@ -517,11 +653,93 @@ var getHeadlessGeneralMethods = ({
|
|
|
517
653
|
publishableKey,
|
|
518
654
|
key,
|
|
519
655
|
userHandleB64url,
|
|
520
|
-
credentialIdB64url
|
|
656
|
+
credentialIdB64url,
|
|
657
|
+
presenceTokens: flattenPresenceTokens({
|
|
658
|
+
tokens,
|
|
659
|
+
userHandleB64url,
|
|
660
|
+
credentialIdB64url
|
|
661
|
+
})
|
|
521
662
|
}
|
|
522
663
|
);
|
|
523
664
|
return { wallet };
|
|
524
|
-
}
|
|
665
|
+
},
|
|
666
|
+
provisionEphemeralSigner: async (params) => {
|
|
667
|
+
const walletCount = params.walletIds.length;
|
|
668
|
+
if (walletCount === 0) {
|
|
669
|
+
throw new Error(
|
|
670
|
+
"provisionEphemeralSigner: at least one walletId required"
|
|
671
|
+
);
|
|
672
|
+
}
|
|
673
|
+
const { userHandleB64url, credentialIdB64url, tokenBatches } = await getInternalPresenceTokens({
|
|
674
|
+
transport,
|
|
675
|
+
passkey,
|
|
676
|
+
publishableKey,
|
|
677
|
+
relyingPartyOrigin,
|
|
678
|
+
scopeCounts: { [SCOPES_PROVISION_EPHEMERAL_SIGNER[0]]: walletCount }
|
|
679
|
+
});
|
|
680
|
+
const keyshareReadBatch = (tokenBatches[SCOPES_PROVISION_EPHEMERAL_SIGNER[0]] ?? []).map((t) => t.token);
|
|
681
|
+
if (keyshareReadBatch.length !== walletCount) {
|
|
682
|
+
throw new Error(
|
|
683
|
+
`provisionEphemeralSigner: server returned ${keyshareReadBatch.length} tokens, expected ${walletCount}`
|
|
684
|
+
);
|
|
685
|
+
}
|
|
686
|
+
return transport.send(
|
|
687
|
+
PostMessageType.WALLET,
|
|
688
|
+
PostMessageMethod.PROVISION_EPHEMERAL_SIGNER,
|
|
689
|
+
{
|
|
690
|
+
publishableKey,
|
|
691
|
+
userHandleB64url,
|
|
692
|
+
credentialIdB64url,
|
|
693
|
+
// One keyshare_read token per wallet, parallel to params.walletIds
|
|
694
|
+
// (iframe consumes them positionally after wallet resolution).
|
|
695
|
+
presenceTokenBatches: {
|
|
696
|
+
[SCOPES_PROVISION_EPHEMERAL_SIGNER[0]]: keyshareReadBatch
|
|
697
|
+
},
|
|
698
|
+
walletIds: params.walletIds,
|
|
699
|
+
expiresAt: params.expiresAt?.toISOString(),
|
|
700
|
+
label: params.label
|
|
701
|
+
}
|
|
702
|
+
);
|
|
703
|
+
},
|
|
704
|
+
// Read-only: list the user's active (non-revoked) provisioned agents
|
|
705
|
+
// for the current app. No WebAuthn ceremony needed — the wallet
|
|
706
|
+
// session JWT is enough since this exposes only metadata (api_pub,
|
|
707
|
+
// key_ids, expiry) and not the private agent material.
|
|
708
|
+
listEphemeralSigners: async () => {
|
|
709
|
+
return transport.send(
|
|
710
|
+
PostMessageType.WALLET,
|
|
711
|
+
PostMessageMethod.LIST_EPHEMERAL_SIGNERS,
|
|
712
|
+
{ publishableKey }
|
|
713
|
+
);
|
|
714
|
+
},
|
|
715
|
+
// Soft-revoke a signer (and forward the revoke to SES). Requires a
|
|
716
|
+
// fresh WebAuthn-bound presence token: ephemeral_signer_revoke scope. Wallet JWT
|
|
717
|
+
// alone isn't enough because revoke is destructive (DoS-grade) — the
|
|
718
|
+
// presence proof confirms it's really the user driving it.
|
|
719
|
+
revokeEphemeralSigner: async (params) => {
|
|
720
|
+
const { userHandleB64url, credentialIdB64url, tokens } = await getInternalPresenceTokens({
|
|
721
|
+
transport,
|
|
722
|
+
passkey,
|
|
723
|
+
publishableKey,
|
|
724
|
+
relyingPartyOrigin,
|
|
725
|
+
scopes: SCOPES_REVOKE_EPHEMERAL_SIGNER
|
|
726
|
+
});
|
|
727
|
+
await transport.send(
|
|
728
|
+
PostMessageType.WALLET,
|
|
729
|
+
PostMessageMethod.REVOKE_EPHEMERAL_SIGNER,
|
|
730
|
+
{
|
|
731
|
+
publishableKey,
|
|
732
|
+
apiPubHex: params.apiPubHex,
|
|
733
|
+
userHandleB64url,
|
|
734
|
+
credentialIdB64url,
|
|
735
|
+
presenceTokens: flattenPresenceTokens({
|
|
736
|
+
tokens,
|
|
737
|
+
userHandleB64url,
|
|
738
|
+
credentialIdB64url
|
|
739
|
+
})
|
|
740
|
+
}
|
|
741
|
+
);
|
|
742
|
+
},
|
|
525
743
|
getWallets: async (walletType) => {
|
|
526
744
|
const { wallets } = await transport.send(
|
|
527
745
|
PostMessageType.WALLET,
|
|
@@ -538,11 +756,9 @@ var getHeadlessGeneralMethods = ({
|
|
|
538
756
|
// silently extend session lifetime.
|
|
539
757
|
getSessionTokens: async () => {
|
|
540
758
|
try {
|
|
541
|
-
const session = await transport.send(
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
{ publishableKey }
|
|
545
|
-
);
|
|
759
|
+
const session = await transport.send(PostMessageType.AUTH, PostMessageMethod.GET_CURRENT_SESSION, {
|
|
760
|
+
publishableKey
|
|
761
|
+
});
|
|
546
762
|
return session ? {
|
|
547
763
|
accessToken: session.accessToken,
|
|
548
764
|
identityToken: session.identityToken,
|
|
@@ -561,7 +777,6 @@ var getHeadlessGeneralMethods = ({
|
|
|
561
777
|
await transport.send(PostMessageType.AUTH, PostMessageMethod.LOGOUT, {
|
|
562
778
|
publishableKey
|
|
563
779
|
});
|
|
564
|
-
clearParentAssertCache();
|
|
565
780
|
await storage.remove("id_token");
|
|
566
781
|
if (setIsAuthenticated) setIsAuthenticated(false);
|
|
567
782
|
if (setUser) setUser(null);
|
|
@@ -607,11 +822,156 @@ var getHeadlessGeneralMethods = ({
|
|
|
607
822
|
}
|
|
608
823
|
}
|
|
609
824
|
});
|
|
825
|
+
|
|
826
|
+
// src/sdk/ephemeral-signer-sign.ts
|
|
827
|
+
import { ed25519 } from "@noble/curves/ed25519";
|
|
828
|
+
import { bytesToHex, hexToBytes } from "@noble/hashes/utils";
|
|
829
|
+
function normalizeBase(url) {
|
|
830
|
+
return url.replace(/\/+$/, "");
|
|
831
|
+
}
|
|
832
|
+
var EphemeralSignerSignError = class extends Error {
|
|
833
|
+
constructor(message, status, body) {
|
|
834
|
+
super(message);
|
|
835
|
+
this.status = status;
|
|
836
|
+
this.body = body;
|
|
837
|
+
this.name = "EphemeralSignerSignError";
|
|
838
|
+
}
|
|
839
|
+
};
|
|
840
|
+
var bindingsCache = /* @__PURE__ */ new Map();
|
|
841
|
+
async function resolveBinding(input) {
|
|
842
|
+
const cached = bindingsCache.get(input.apiPubHex);
|
|
843
|
+
if (cached) {
|
|
844
|
+
const hit2 = cached.find((b) => b.walletId === input.walletId);
|
|
845
|
+
if (hit2) return hit2;
|
|
846
|
+
}
|
|
847
|
+
const issuedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
848
|
+
const signedBodyBytes = new TextEncoder().encode(
|
|
849
|
+
JSON.stringify({ issued_at: issuedAt })
|
|
850
|
+
);
|
|
851
|
+
const apiPrivBytes = hexToBytes(input.apiPrivHex);
|
|
852
|
+
const agentSig = ed25519.sign(signedBodyBytes, apiPrivBytes);
|
|
853
|
+
const url = `${normalizeBase(input.baseUrl)}/v0/wallets/ephemeral-signers/me/wallets`;
|
|
854
|
+
const fetchFn = input.fetchImpl ?? fetch;
|
|
855
|
+
let response;
|
|
856
|
+
try {
|
|
857
|
+
response = await fetchFn(url, {
|
|
858
|
+
method: "POST",
|
|
859
|
+
headers: {
|
|
860
|
+
"Content-Type": "application/json",
|
|
861
|
+
Authorization: `PublicToken ${input.publishableKey}`
|
|
862
|
+
},
|
|
863
|
+
body: JSON.stringify({
|
|
864
|
+
api_pub: input.apiPubHex,
|
|
865
|
+
signed_body: bytesToHex(signedBodyBytes),
|
|
866
|
+
agent_signature: bytesToHex(agentSig)
|
|
867
|
+
})
|
|
868
|
+
});
|
|
869
|
+
} catch (e) {
|
|
870
|
+
throw new EphemeralSignerSignError(
|
|
871
|
+
`wallet binding fetch failed: ${e instanceof Error ? e.message : String(e)}`
|
|
872
|
+
);
|
|
873
|
+
}
|
|
874
|
+
if (!response.ok) {
|
|
875
|
+
const body = await response.text().catch(() => "");
|
|
876
|
+
throw new EphemeralSignerSignError(
|
|
877
|
+
`wallet binding fetch failed: ${response.status}`,
|
|
878
|
+
response.status,
|
|
879
|
+
body
|
|
880
|
+
);
|
|
881
|
+
}
|
|
882
|
+
const json = await response.json();
|
|
883
|
+
const bindings = json.wallets.map((w) => ({
|
|
884
|
+
walletId: w.wallet_id,
|
|
885
|
+
keyId: w.key_id,
|
|
886
|
+
derivationPath: w.derivation_path
|
|
887
|
+
}));
|
|
888
|
+
bindingsCache.set(input.apiPubHex, bindings);
|
|
889
|
+
const hit = bindings.find((b) => b.walletId === input.walletId);
|
|
890
|
+
if (!hit) {
|
|
891
|
+
throw new EphemeralSignerSignError(
|
|
892
|
+
`walletId ${input.walletId} is not authorized for this agent`
|
|
893
|
+
);
|
|
894
|
+
}
|
|
895
|
+
return hit;
|
|
896
|
+
}
|
|
897
|
+
async function signWithEphemeralSigner(input) {
|
|
898
|
+
if (!/^[0-9a-f]{64}$/i.test(input.apiPubHex)) {
|
|
899
|
+
throw new EphemeralSignerSignError(
|
|
900
|
+
"apiPubHex must be 64 lowercase hex chars (32-byte Ed25519 pubkey)"
|
|
901
|
+
);
|
|
902
|
+
}
|
|
903
|
+
if (!/^[0-9a-f]{64}$/i.test(input.apiPrivHex)) {
|
|
904
|
+
throw new EphemeralSignerSignError(
|
|
905
|
+
"apiPrivHex must be 64 lowercase hex chars (32-byte Ed25519 privkey)"
|
|
906
|
+
);
|
|
907
|
+
}
|
|
908
|
+
if (!input.walletId) {
|
|
909
|
+
throw new EphemeralSignerSignError("walletId is required");
|
|
910
|
+
}
|
|
911
|
+
if (!input.rawSigningPayloadHex || !/^[0-9a-f]+$/i.test(input.rawSigningPayloadHex)) {
|
|
912
|
+
throw new EphemeralSignerSignError(
|
|
913
|
+
"rawSigningPayloadHex must be a non-empty lowercase hex string"
|
|
914
|
+
);
|
|
915
|
+
}
|
|
916
|
+
if (!input.publishableKey) {
|
|
917
|
+
throw new EphemeralSignerSignError(
|
|
918
|
+
"publishableKey is required \u2014 wallets backend gates /ephemeral-signers/* with RequirePublicToken"
|
|
919
|
+
);
|
|
920
|
+
}
|
|
921
|
+
const binding = await resolveBinding(input);
|
|
922
|
+
const issuedAt = (input.issuedAt ?? /* @__PURE__ */ new Date()).toISOString();
|
|
923
|
+
const signedPayload = {
|
|
924
|
+
raw_signing_payload: input.rawSigningPayloadHex,
|
|
925
|
+
key_id: binding.keyId,
|
|
926
|
+
derivation_path: binding.derivationPath,
|
|
927
|
+
issued_at: issuedAt
|
|
928
|
+
};
|
|
929
|
+
const signedBodyBytes = new TextEncoder().encode(
|
|
930
|
+
JSON.stringify(signedPayload)
|
|
931
|
+
);
|
|
932
|
+
const apiPrivBytes = hexToBytes(input.apiPrivHex);
|
|
933
|
+
const agentSig = ed25519.sign(signedBodyBytes, apiPrivBytes);
|
|
934
|
+
const requestBody = {
|
|
935
|
+
api_pub: input.apiPubHex,
|
|
936
|
+
signed_body: bytesToHex(signedBodyBytes),
|
|
937
|
+
agent_signature: bytesToHex(agentSig)
|
|
938
|
+
};
|
|
939
|
+
const url = `${normalizeBase(input.baseUrl)}/v0/wallets/ephemeral-signers/sign`;
|
|
940
|
+
const fetchFn = input.fetchImpl ?? fetch;
|
|
941
|
+
let response;
|
|
942
|
+
try {
|
|
943
|
+
response = await fetchFn(url, {
|
|
944
|
+
method: "POST",
|
|
945
|
+
headers: {
|
|
946
|
+
"Content-Type": "application/json",
|
|
947
|
+
Authorization: `PublicToken ${input.publishableKey}`
|
|
948
|
+
},
|
|
949
|
+
body: JSON.stringify(requestBody)
|
|
950
|
+
});
|
|
951
|
+
} catch (e) {
|
|
952
|
+
throw new EphemeralSignerSignError(
|
|
953
|
+
`transport failure: ${e instanceof Error ? e.message : String(e)}`
|
|
954
|
+
);
|
|
955
|
+
}
|
|
956
|
+
if (!response.ok) {
|
|
957
|
+
const body = await response.text().catch(() => "");
|
|
958
|
+
throw new EphemeralSignerSignError(
|
|
959
|
+
`ephemeral signer sign failed: ${response.status}`,
|
|
960
|
+
response.status,
|
|
961
|
+
body
|
|
962
|
+
);
|
|
963
|
+
}
|
|
964
|
+
return await response.json();
|
|
965
|
+
}
|
|
610
966
|
export {
|
|
967
|
+
EphemeralSignerSignError,
|
|
611
968
|
assertPasskeyInParent,
|
|
969
|
+
flattenPresenceTokens,
|
|
612
970
|
getHeadlessAuthenticationMethods,
|
|
613
971
|
getHeadlessEthereumMethods,
|
|
614
972
|
getHeadlessGeneralMethods,
|
|
615
973
|
getHeadlessSolanaMethods,
|
|
616
|
-
|
|
974
|
+
getInternalPresenceTokens,
|
|
975
|
+
getPresenceToken,
|
|
976
|
+
signWithEphemeralSigner
|
|
617
977
|
};
|