@turnkey/core 1.0.0-beta.5 → 1.0.0-beta.6
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/__clients__/core.d.ts +71 -28
- package/dist/__clients__/core.d.ts.map +1 -1
- package/dist/__clients__/core.js +189 -88
- package/dist/__clients__/core.js.map +1 -1
- package/dist/__clients__/core.mjs +191 -90
- package/dist/__clients__/core.mjs.map +1 -1
- package/dist/__generated__/sdk-client-base.d.ts +13 -0
- package/dist/__generated__/sdk-client-base.d.ts.map +1 -1
- package/dist/__generated__/sdk-client-base.js +198 -5
- package/dist/__generated__/sdk-client-base.js.map +1 -1
- package/dist/__generated__/sdk-client-base.mjs +198 -5
- package/dist/__generated__/sdk-client-base.mjs.map +1 -1
- package/dist/__generated__/version.d.ts +1 -1
- package/dist/__generated__/version.js +1 -1
- package/dist/__generated__/version.mjs +1 -1
- package/dist/__inputs__/public_api.types.d.ts +263 -1
- package/dist/__inputs__/public_api.types.d.ts.map +1 -1
- package/dist/__polyfills__/jest.setup.webcrypto.d.ts +2 -0
- package/dist/__polyfills__/jest.setup.webcrypto.d.ts.map +1 -0
- package/dist/__stampers__/api/base.d.ts +11 -5
- package/dist/__stampers__/api/base.d.ts.map +1 -1
- package/dist/__stampers__/api/base.js +32 -10
- package/dist/__stampers__/api/base.js.map +1 -1
- package/dist/__stampers__/api/base.mjs +32 -10
- package/dist/__stampers__/api/base.mjs.map +1 -1
- package/dist/__stampers__/api/web/stamper.d.ts.map +1 -1
- package/dist/__stampers__/api/web/stamper.js +2 -4
- package/dist/__stampers__/api/web/stamper.js.map +1 -1
- package/dist/__stampers__/api/web/stamper.mjs +2 -4
- package/dist/__stampers__/api/web/stamper.mjs.map +1 -1
- package/dist/__types__/base.d.ts +3 -1
- package/dist/__types__/base.d.ts.map +1 -1
- package/dist/__types__/base.js.map +1 -1
- package/dist/__types__/base.mjs.map +1 -1
- package/dist/__wallet__/stamper.d.ts.map +1 -1
- package/dist/__wallet__/stamper.js +7 -6
- package/dist/__wallet__/stamper.js.map +1 -1
- package/dist/__wallet__/stamper.mjs +8 -7
- package/dist/__wallet__/stamper.mjs.map +1 -1
- package/dist/utils.d.ts +27 -2
- package/dist/utils.d.ts.map +1 -1
- package/dist/utils.js +133 -2
- package/dist/utils.js.map +1 -1
- package/dist/utils.mjs +131 -6
- package/dist/utils.mjs.map +1 -1
- package/package.json +9 -8
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { TurnkeySDKClientBase } from '../__generated__/sdk-client-base.mjs';
|
|
2
|
-
import { TurnkeyErrorCodes, TurnkeyError, TurnkeyNetworkError } from '@turnkey/sdk-types';
|
|
2
|
+
import { TurnkeyErrorCodes, TurnkeyError, TurnkeyNetworkError, AuthAction } from '@turnkey/sdk-types';
|
|
3
3
|
import { SessionKey, DEFAULT_SESSION_EXPIRATION_IN_SECONDS, StamperType, WalletSource, Chain, FilterType, OtpTypeToFilterTypeMap, OtpType, Curve, SignIntent } from '../__types__/base.mjs';
|
|
4
|
-
import { withTurnkeyErrorHandling, isWeb, isReactNative, buildSignUpBody, findWalletProviderFromAddress,
|
|
4
|
+
import { withTurnkeyErrorHandling, isValidPasskeyName, isWeb, isReactNative, buildSignUpBody, findWalletProviderFromAddress, addressFromPublicKey, getCurveTypeFromProvider, getPublicKeyFromStampHeader, toExternalTimestamp, getAuthenticatorAddresses, isEthereumProvider, isSolanaProvider, getHashFunction, getEncodingType, getEncodedMessage, splitSignature, broadcastTransaction, googleISS, isWalletAccountArray, generateWalletAccountsFromAddressFormat } from '../utils.mjs';
|
|
5
5
|
import { createStorageManager } from '../__storage__/base.mjs';
|
|
6
6
|
import { CrossPlatformApiKeyStamper } from '../__stampers__/api/base.mjs';
|
|
7
7
|
import { CrossPlatformPasskeyStamper } from '../__stampers__/passkey/base.mjs';
|
|
@@ -21,9 +21,9 @@ class TurnkeyClient {
|
|
|
21
21
|
* - Handles both web and React Native environments, automatically selecting the appropriate passkey creation flow.
|
|
22
22
|
* - The resulting attestation and challenge can be used to register the passkey with Turnkey.
|
|
23
23
|
*
|
|
24
|
-
* @param params.name - name
|
|
25
|
-
* @param params.displayName - display name for the passkey. If not provided, defaults to "A Passkey".
|
|
24
|
+
* @param params.name - display name for the passkey (defaults to a generated name based on the current timestamp).
|
|
26
25
|
* @param params.stampWith - parameter to stamp the request with a specific stamper (StamperType.Passkey, StamperType.ApiKey, or StamperType.Wallet).
|
|
26
|
+
* @param params.challenge - challenge string to use for passkey registration. If not provided, a new challenge will be generated.
|
|
27
27
|
* @returns A promise that resolves to an object containing:
|
|
28
28
|
* - attestation: attestation object returned from the passkey creation process.
|
|
29
29
|
* - encodedChallenge: encoded challenge string used for passkey registration.
|
|
@@ -31,16 +31,16 @@ class TurnkeyClient {
|
|
|
31
31
|
*/
|
|
32
32
|
this.createPasskey = async (params) => {
|
|
33
33
|
return withTurnkeyErrorHandling(async () => {
|
|
34
|
-
const name = params?.name ||
|
|
35
|
-
const displayName = params?.displayName || "A Passkey";
|
|
34
|
+
const name = isValidPasskeyName(params?.name || `passkey-${Date.now()}`);
|
|
36
35
|
let passkey;
|
|
37
36
|
if (isWeb()) {
|
|
38
37
|
const res = await this.passkeyStamper?.createWebPasskey({
|
|
39
38
|
publicKey: {
|
|
40
39
|
user: {
|
|
41
40
|
name,
|
|
42
|
-
displayName,
|
|
41
|
+
displayName: name,
|
|
43
42
|
},
|
|
43
|
+
...(params?.challenge && { challenge: params.challenge }),
|
|
44
44
|
},
|
|
45
45
|
});
|
|
46
46
|
if (!res) {
|
|
@@ -54,7 +54,7 @@ class TurnkeyClient {
|
|
|
54
54
|
else if (isReactNative()) {
|
|
55
55
|
const res = await this.passkeyStamper?.createReactNativePasskey({
|
|
56
56
|
name,
|
|
57
|
-
displayName,
|
|
57
|
+
displayName: name,
|
|
58
58
|
});
|
|
59
59
|
if (!res) {
|
|
60
60
|
throw new TurnkeyError("Failed to create React Native passkey", TurnkeyErrorCodes.INTERNAL_ERROR);
|
|
@@ -125,21 +125,23 @@ class TurnkeyClient {
|
|
|
125
125
|
* @param params.publicKey - public key to use for authentication. If not provided, a new key pair will be generated.
|
|
126
126
|
* @param params.sessionKey - session key to use for session creation (defaults to the default session key).
|
|
127
127
|
* @param params.expirationSeconds - session expiration time in seconds (defaults to the configured default).
|
|
128
|
-
* @returns A promise that resolves to a
|
|
128
|
+
* @returns A promise that resolves to a {@link PasskeyAuthResult}, which includes:
|
|
129
|
+
* - `sessionToken`: the signed JWT session token.
|
|
130
|
+
* - `credentialId`: an empty string.
|
|
129
131
|
* @throws {TurnkeyError} If there is an error during the passkey login process or if the user cancels the passkey prompt.
|
|
130
132
|
*/
|
|
131
133
|
this.loginWithPasskey = async (params) => {
|
|
132
|
-
let
|
|
134
|
+
let generatedPublicKey = undefined;
|
|
133
135
|
return await withTurnkeyErrorHandling(async () => {
|
|
134
|
-
|
|
136
|
+
generatedPublicKey =
|
|
135
137
|
params?.publicKey || (await this.apiKeyStamper?.createKeyPair());
|
|
136
138
|
const sessionKey = params?.sessionKey || SessionKey.DefaultSessionkey;
|
|
137
139
|
const expirationSeconds = params?.expirationSeconds || DEFAULT_SESSION_EXPIRATION_IN_SECONDS;
|
|
138
|
-
if (!
|
|
140
|
+
if (!generatedPublicKey) {
|
|
139
141
|
throw new TurnkeyError("A publickey could not be found or generated.", TurnkeyErrorCodes.INTERNAL_ERROR);
|
|
140
142
|
}
|
|
141
143
|
const sessionResponse = await this.httpClient.stampLogin({
|
|
142
|
-
publicKey:
|
|
144
|
+
publicKey: generatedPublicKey,
|
|
143
145
|
organizationId: this.config.organizationId,
|
|
144
146
|
expirationSeconds,
|
|
145
147
|
}, StamperType.Passkey);
|
|
@@ -147,8 +149,14 @@ class TurnkeyClient {
|
|
|
147
149
|
sessionToken: sessionResponse.session,
|
|
148
150
|
sessionKey,
|
|
149
151
|
});
|
|
150
|
-
|
|
151
|
-
return
|
|
152
|
+
generatedPublicKey = undefined; // Key pair was successfully used, set to null to prevent cleanup
|
|
153
|
+
return {
|
|
154
|
+
sessionToken: sessionResponse.session,
|
|
155
|
+
// TODO: can we return the credentialId here?
|
|
156
|
+
// from a quick glance this is going to be difficult
|
|
157
|
+
// for now we return an empty string
|
|
158
|
+
credentialId: "",
|
|
159
|
+
};
|
|
152
160
|
}, {
|
|
153
161
|
errorMessage: "Unable to log in with the provided passkey",
|
|
154
162
|
errorCode: TurnkeyErrorCodes.PASSKEY_LOGIN_AUTH_ERROR,
|
|
@@ -160,9 +168,9 @@ class TurnkeyClient {
|
|
|
160
168
|
},
|
|
161
169
|
}, {
|
|
162
170
|
finallyFn: async () => {
|
|
163
|
-
if (
|
|
171
|
+
if (generatedPublicKey) {
|
|
164
172
|
try {
|
|
165
|
-
await this.apiKeyStamper?.deleteKeyPair(
|
|
173
|
+
await this.apiKeyStamper?.deleteKeyPair(generatedPublicKey);
|
|
166
174
|
}
|
|
167
175
|
catch (cleanupError) {
|
|
168
176
|
throw new TurnkeyError(`Failed to clean up generated key pair`, TurnkeyErrorCodes.KEY_PAIR_CLEANUP_ERROR, cleanupError);
|
|
@@ -180,23 +188,26 @@ class TurnkeyClient {
|
|
|
180
188
|
* - Automatically generates a new API key pair for authentication and session management.
|
|
181
189
|
* - Stores the resulting session token and manages cleanup of unused key pairs.
|
|
182
190
|
*
|
|
191
|
+
* @param params.passkeyDisplayName - display name for the passkey (defaults to a generated name based on the current timestamp).
|
|
183
192
|
* @param params.createSubOrgParams - parameters for creating a sub-organization (e.g., authenticators, user metadata).
|
|
184
193
|
* @param params.sessionKey - session key to use for storing the session (defaults to the default session key).
|
|
185
|
-
* @param params.passkeyDisplayName - display name for the passkey (defaults to a generated name based on the current timestamp).
|
|
186
194
|
* @param params.expirationSeconds - session expiration time in seconds (defaults to the configured default).
|
|
187
|
-
* @
|
|
195
|
+
* @param params.challenge - challenge string to use for passkey registration. If not provided, a new challenge will be generated.
|
|
196
|
+
* @returns A promise that resolves to a {@link PasskeyAuthResult}, which includes:
|
|
197
|
+
* - `sessionToken`: the signed JWT session token.
|
|
198
|
+
* - `credentialId`: the credential ID associated with the passkey created.
|
|
188
199
|
* @throws {TurnkeyError} If there is an error during passkey creation, sub-organization creation, or session storage.
|
|
189
200
|
*/
|
|
190
201
|
this.signUpWithPasskey = async (params) => {
|
|
191
202
|
const { createSubOrgParams, passkeyDisplayName, sessionKey = SessionKey.DefaultSessionkey, expirationSeconds = DEFAULT_SESSION_EXPIRATION_IN_SECONDS, } = params || {};
|
|
192
|
-
let
|
|
203
|
+
let generatedPublicKey = undefined;
|
|
193
204
|
return withTurnkeyErrorHandling(async () => {
|
|
194
|
-
|
|
205
|
+
generatedPublicKey = await this.apiKeyStamper?.createKeyPair();
|
|
195
206
|
const passkeyName = passkeyDisplayName || `passkey-${Date.now()}`;
|
|
196
207
|
// A passkey will be created automatically when you call this function. The name is passed in
|
|
197
208
|
const passkey = await this.createPasskey({
|
|
198
209
|
name: passkeyName,
|
|
199
|
-
|
|
210
|
+
...(params?.challenge && { challenge: params.challenge }),
|
|
200
211
|
});
|
|
201
212
|
if (!passkey) {
|
|
202
213
|
throw new TurnkeyError("Failed to create passkey: encoded challenge or attestation is missing", TurnkeyErrorCodes.INTERNAL_ERROR);
|
|
@@ -215,8 +226,8 @@ class TurnkeyClient {
|
|
|
215
226
|
],
|
|
216
227
|
apiKeys: [
|
|
217
228
|
{
|
|
218
|
-
apiKeyName: `passkey-auth-${
|
|
219
|
-
publicKey:
|
|
229
|
+
apiKeyName: `passkey-auth-${generatedPublicKey}`,
|
|
230
|
+
publicKey: generatedPublicKey,
|
|
220
231
|
curveType: "API_KEY_CURVE_P256",
|
|
221
232
|
expirationSeconds: "60",
|
|
222
233
|
},
|
|
@@ -228,28 +239,31 @@ class TurnkeyClient {
|
|
|
228
239
|
throw new TurnkeyError(`Sign up failed`, TurnkeyErrorCodes.PASSKEY_SIGNUP_AUTH_ERROR);
|
|
229
240
|
}
|
|
230
241
|
const newGeneratedKeyPair = await this.apiKeyStamper?.createKeyPair();
|
|
231
|
-
this.apiKeyStamper?.
|
|
242
|
+
this.apiKeyStamper?.setTemporaryPublicKey(generatedPublicKey);
|
|
232
243
|
const sessionResponse = await this.httpClient.stampLogin({
|
|
233
244
|
publicKey: newGeneratedKeyPair,
|
|
234
245
|
organizationId: this.config.organizationId,
|
|
235
246
|
expirationSeconds,
|
|
236
247
|
});
|
|
237
|
-
await this.apiKeyStamper?.deleteKeyPair(
|
|
248
|
+
await this.apiKeyStamper?.deleteKeyPair(generatedPublicKey);
|
|
238
249
|
await this.storeSession({
|
|
239
250
|
sessionToken: sessionResponse.session,
|
|
240
251
|
sessionKey,
|
|
241
252
|
});
|
|
242
|
-
|
|
243
|
-
return
|
|
253
|
+
generatedPublicKey = undefined; // Key pair was successfully used, set to null to prevent cleanup
|
|
254
|
+
return {
|
|
255
|
+
sessionToken: sessionResponse.session,
|
|
256
|
+
credentialId: passkey.attestation.credentialId,
|
|
257
|
+
};
|
|
244
258
|
}, {
|
|
245
259
|
errorCode: TurnkeyErrorCodes.PASSKEY_SIGNUP_AUTH_ERROR,
|
|
246
260
|
errorMessage: "Failed to sign up with passkey",
|
|
247
261
|
}, {
|
|
248
262
|
finallyFn: async () => {
|
|
249
|
-
this.apiKeyStamper?.
|
|
250
|
-
if (
|
|
263
|
+
this.apiKeyStamper?.clearTemporaryPublicKey();
|
|
264
|
+
if (generatedPublicKey) {
|
|
251
265
|
try {
|
|
252
|
-
await this.apiKeyStamper?.deleteKeyPair(
|
|
266
|
+
await this.apiKeyStamper?.deleteKeyPair(generatedPublicKey);
|
|
253
267
|
}
|
|
254
268
|
catch (cleanupError) {
|
|
255
269
|
throw new TurnkeyError(`Failed to clean up generated key pair`, TurnkeyErrorCodes.KEY_PAIR_CLEANUP_ERROR, cleanupError);
|
|
@@ -372,7 +386,9 @@ class TurnkeyClient {
|
|
|
372
386
|
* @param params.publicKey - optional public key to associate with the session (generated if not provided).
|
|
373
387
|
* @param params.sessionKey - optional key to store the session under (defaults to the default session key).
|
|
374
388
|
* @param params.expirationSeconds - optional session expiration time in seconds (defaults to the configured default).
|
|
375
|
-
* @returns A promise that resolves to
|
|
389
|
+
* @returns A promise that resolves to a {@link WalletAuthResult}, which includes:
|
|
390
|
+
* - `sessionToken`: the signed JWT session token.
|
|
391
|
+
* - `address`: the authenticated wallet address.
|
|
376
392
|
* @throws {TurnkeyError} If the wallet stamper is uninitialized, a public key cannot be found or generated, or login fails.
|
|
377
393
|
*/
|
|
378
394
|
this.loginWithWallet = async (params) => {
|
|
@@ -397,14 +413,19 @@ class TurnkeyClient {
|
|
|
397
413
|
sessionToken: sessionResponse.session,
|
|
398
414
|
sessionKey,
|
|
399
415
|
});
|
|
400
|
-
|
|
416
|
+
// TODO (Moe): What happens if a user connects to MetaMask on Ethereum,
|
|
417
|
+
// then switches to a Solana account within MetaMask? Will this flow break?
|
|
418
|
+
return {
|
|
419
|
+
sessionToken: sessionResponse.session,
|
|
420
|
+
address: addressFromPublicKey(walletProvider.chainInfo.namespace, publicKey),
|
|
421
|
+
};
|
|
401
422
|
}, {
|
|
402
423
|
errorMessage: "Unable to log in with the provided wallet",
|
|
403
424
|
errorCode: TurnkeyErrorCodes.WALLET_LOGIN_AUTH_ERROR,
|
|
404
425
|
}, {
|
|
405
426
|
finallyFn: async () => {
|
|
406
427
|
// Clean up the generated key pair if it wasn't successfully used
|
|
407
|
-
this.apiKeyStamper?.
|
|
428
|
+
this.apiKeyStamper?.clearTemporaryPublicKey();
|
|
408
429
|
if (publicKey) {
|
|
409
430
|
try {
|
|
410
431
|
await this.apiKeyStamper?.deleteKeyPair(publicKey);
|
|
@@ -429,17 +450,19 @@ class TurnkeyClient {
|
|
|
429
450
|
* @param params.createSubOrgParams - parameters for creating a sub-organization (e.g., authenticators, user metadata).
|
|
430
451
|
* @param params.sessionKey - session key to use for storing the session (defaults to the default session key).
|
|
431
452
|
* @param params.expirationSeconds - session expiration time in seconds (defaults to the configured default).
|
|
432
|
-
* @returns A promise that resolves to a
|
|
453
|
+
* @returns A promise that resolves to a {@link WalletAuthResult}, which includes:
|
|
454
|
+
* - `sessionToken`: the signed JWT session token.
|
|
455
|
+
* - `address`: the authenticated wallet address.
|
|
433
456
|
* @throws {TurnkeyError} If there is an error during wallet authentication, sub-organization creation, session storage, or cleanup.
|
|
434
457
|
*/
|
|
435
458
|
this.signUpWithWallet = async (params) => {
|
|
436
459
|
const { walletProvider, createSubOrgParams, sessionKey = SessionKey.DefaultSessionkey, expirationSeconds = DEFAULT_SESSION_EXPIRATION_IN_SECONDS, } = params;
|
|
437
|
-
let
|
|
460
|
+
let generatedPublicKey = undefined;
|
|
438
461
|
return withTurnkeyErrorHandling(async () => {
|
|
439
462
|
if (!this.walletManager?.stamper) {
|
|
440
463
|
throw new TurnkeyError("Wallet stamper is not initialized", TurnkeyErrorCodes.WALLET_MANAGER_COMPONENT_NOT_INITIALIZED);
|
|
441
464
|
}
|
|
442
|
-
|
|
465
|
+
generatedPublicKey = await this.apiKeyStamper?.createKeyPair();
|
|
443
466
|
this.walletManager.stamper.setProvider(walletProvider.interfaceType, walletProvider);
|
|
444
467
|
const publicKey = await this.walletManager.stamper.getPublicKey(walletProvider.interfaceType, walletProvider);
|
|
445
468
|
if (!publicKey) {
|
|
@@ -452,13 +475,11 @@ class TurnkeyClient {
|
|
|
452
475
|
{
|
|
453
476
|
apiKeyName: `wallet-auth:${publicKey}`,
|
|
454
477
|
publicKey: publicKey,
|
|
455
|
-
curveType:
|
|
456
|
-
? "API_KEY_CURVE_SECP256K1"
|
|
457
|
-
: "API_KEY_CURVE_ED25519",
|
|
478
|
+
curveType: getCurveTypeFromProvider(walletProvider),
|
|
458
479
|
},
|
|
459
480
|
{
|
|
460
|
-
apiKeyName: `wallet-auth-${
|
|
461
|
-
publicKey:
|
|
481
|
+
apiKeyName: `wallet-auth-${generatedPublicKey}`,
|
|
482
|
+
publicKey: generatedPublicKey,
|
|
462
483
|
curveType: "API_KEY_CURVE_P256",
|
|
463
484
|
expirationSeconds: "60",
|
|
464
485
|
},
|
|
@@ -470,29 +491,34 @@ class TurnkeyClient {
|
|
|
470
491
|
throw new TurnkeyError(`Sign up failed`, TurnkeyErrorCodes.WALLET_SIGNUP_AUTH_ERROR);
|
|
471
492
|
}
|
|
472
493
|
const newGeneratedKeyPair = await this.apiKeyStamper?.createKeyPair();
|
|
473
|
-
this.apiKeyStamper?.
|
|
494
|
+
this.apiKeyStamper?.setTemporaryPublicKey(generatedPublicKey);
|
|
474
495
|
const sessionResponse = await this.httpClient.stampLogin({
|
|
475
496
|
publicKey: newGeneratedKeyPair,
|
|
476
497
|
organizationId: this.config.organizationId,
|
|
477
498
|
expirationSeconds,
|
|
478
499
|
});
|
|
479
|
-
await this.apiKeyStamper?.deleteKeyPair(
|
|
500
|
+
await this.apiKeyStamper?.deleteKeyPair(generatedPublicKey);
|
|
480
501
|
await this.storeSession({
|
|
481
502
|
sessionToken: sessionResponse.session,
|
|
482
503
|
sessionKey,
|
|
483
504
|
});
|
|
484
|
-
|
|
485
|
-
|
|
505
|
+
generatedPublicKey = undefined; // Key pair was successfully used, set to null to prevent cleanup
|
|
506
|
+
// TODO (Moe): What happens if a user connects to MetaMask on Ethereum,
|
|
507
|
+
// then switches to a Solana account within MetaMask? Will this flow break?
|
|
508
|
+
return {
|
|
509
|
+
sessionToken: sessionResponse.session,
|
|
510
|
+
address: addressFromPublicKey(walletProvider.chainInfo.namespace, publicKey),
|
|
511
|
+
};
|
|
486
512
|
}, {
|
|
487
513
|
errorMessage: "Failed to sign up with wallet",
|
|
488
514
|
errorCode: TurnkeyErrorCodes.WALLET_SIGNUP_AUTH_ERROR,
|
|
489
515
|
}, {
|
|
490
516
|
finallyFn: async () => {
|
|
491
517
|
// Clean up the generated key pair if it wasn't successfully used
|
|
492
|
-
this.apiKeyStamper?.
|
|
493
|
-
if (
|
|
518
|
+
this.apiKeyStamper?.clearTemporaryPublicKey();
|
|
519
|
+
if (generatedPublicKey) {
|
|
494
520
|
try {
|
|
495
|
-
await this.apiKeyStamper?.deleteKeyPair(
|
|
521
|
+
await this.apiKeyStamper?.deleteKeyPair(generatedPublicKey);
|
|
496
522
|
}
|
|
497
523
|
catch (cleanupError) {
|
|
498
524
|
throw new TurnkeyError("Failed to clean up generated key pair", TurnkeyErrorCodes.KEY_PAIR_CLEANUP_ERROR, cleanupError);
|
|
@@ -515,7 +541,10 @@ class TurnkeyClient {
|
|
|
515
541
|
* @param params.createSubOrgParams - optional parameters for creating a sub-organization (e.g., authenticators, user metadata).
|
|
516
542
|
* @param params.sessionKey - session key to use for storing the session (defaults to the default session key).
|
|
517
543
|
* @param params.expirationSeconds - session expiration time in seconds (defaults to the configured default).
|
|
518
|
-
* @returns A promise that resolves to
|
|
544
|
+
* @returns A promise that resolves to an object containing:
|
|
545
|
+
* - `sessionToken`: the signed JWT session token.
|
|
546
|
+
* - `address`: the authenticated wallet address.
|
|
547
|
+
* - `action`: whether the flow resulted in a login or signup ({@link AuthAction}).
|
|
519
548
|
* @throws {TurnkeyError} If there is an error during wallet authentication, sub-organization creation, or session storage.
|
|
520
549
|
*/
|
|
521
550
|
this.loginOrSignupWithWallet = async (params) => {
|
|
@@ -523,19 +552,19 @@ class TurnkeyClient {
|
|
|
523
552
|
const sessionKey = params.sessionKey || SessionKey.DefaultSessionkey;
|
|
524
553
|
const walletProvider = params.walletProvider;
|
|
525
554
|
const expirationSeconds = params.expirationSeconds || DEFAULT_SESSION_EXPIRATION_IN_SECONDS;
|
|
526
|
-
let
|
|
555
|
+
let generatedPublicKey = undefined;
|
|
527
556
|
return withTurnkeyErrorHandling(async () => {
|
|
528
557
|
if (!this.walletManager?.stamper) {
|
|
529
558
|
throw new TurnkeyError("Wallet stamper is not initialized", TurnkeyErrorCodes.WALLET_MANAGER_COMPONENT_NOT_INITIALIZED);
|
|
530
559
|
}
|
|
531
|
-
|
|
560
|
+
generatedPublicKey = await this.apiKeyStamper?.createKeyPair();
|
|
532
561
|
this.walletManager.stamper.setProvider(walletProvider.interfaceType, walletProvider);
|
|
533
|
-
// here we sign the request with the wallet, but we don't send it to
|
|
562
|
+
// here we sign the request with the wallet, but we don't send it to Turnkey yet
|
|
534
563
|
// this is because we need to check if the subOrg exists first, and create one if it doesn't
|
|
535
|
-
// once we have the subOrg for the publicKey, we then can send the request to
|
|
564
|
+
// once we have the subOrg for the publicKey, we then can send the request to Turnkey
|
|
536
565
|
const signedRequest = await withTurnkeyErrorHandling(async () => {
|
|
537
566
|
return this.httpClient.stampStampLogin({
|
|
538
|
-
publicKey:
|
|
567
|
+
publicKey: generatedPublicKey,
|
|
539
568
|
organizationId: this.config.organizationId,
|
|
540
569
|
expirationSeconds,
|
|
541
570
|
}, StamperType.Wallet);
|
|
@@ -572,7 +601,7 @@ class TurnkeyClient {
|
|
|
572
601
|
throw new TurnkeyError(`Unsupported interface type: ${walletProvider.interfaceType}`, TurnkeyErrorCodes.INVALID_REQUEST);
|
|
573
602
|
}
|
|
574
603
|
// here we check if the subOrg exists and create one
|
|
575
|
-
// then we send off the stamped request to
|
|
604
|
+
// then we send off the stamped request to Turnkey
|
|
576
605
|
const accountRes = await this.httpClient.proxyGetAccount({
|
|
577
606
|
filterType: FilterType.PublicKey,
|
|
578
607
|
filterValue: publicKey,
|
|
@@ -590,9 +619,7 @@ class TurnkeyClient {
|
|
|
590
619
|
{
|
|
591
620
|
apiKeyName: `wallet-auth:${publicKey}`,
|
|
592
621
|
publicKey: publicKey,
|
|
593
|
-
curveType:
|
|
594
|
-
? "API_KEY_CURVE_SECP256K1"
|
|
595
|
-
: "API_KEY_CURVE_ED25519",
|
|
622
|
+
curveType: getCurveTypeFromProvider(walletProvider),
|
|
596
623
|
},
|
|
597
624
|
],
|
|
598
625
|
},
|
|
@@ -602,7 +629,7 @@ class TurnkeyClient {
|
|
|
602
629
|
throw new TurnkeyError(`Sign up failed`, TurnkeyErrorCodes.WALLET_SIGNUP_AUTH_ERROR);
|
|
603
630
|
}
|
|
604
631
|
}
|
|
605
|
-
// now we can send the stamped request to
|
|
632
|
+
// now we can send the stamped request to Turnkey
|
|
606
633
|
const headers = {
|
|
607
634
|
"Content-Type": "application/json",
|
|
608
635
|
[signedRequest.stamp.stampHeaderName]: signedRequest.stamp.stampHeaderValue,
|
|
@@ -625,14 +652,19 @@ class TurnkeyClient {
|
|
|
625
652
|
sessionToken: sessionToken,
|
|
626
653
|
sessionKey,
|
|
627
654
|
});
|
|
628
|
-
return
|
|
655
|
+
return {
|
|
656
|
+
sessionToken: sessionToken,
|
|
657
|
+
address: addressFromPublicKey(walletProvider.chainInfo.namespace, publicKey),
|
|
658
|
+
// if the subOrganizationId exists, it means the user is logging in
|
|
659
|
+
action: subOrganizationId ? AuthAction.LOGIN : AuthAction.SIGNUP,
|
|
660
|
+
};
|
|
629
661
|
}, {
|
|
630
662
|
errorCode: TurnkeyErrorCodes.WALLET_LOGIN_OR_SIGNUP_ERROR,
|
|
631
663
|
errorMessage: "Failed to log in or sign up with wallet",
|
|
632
664
|
catchFn: async () => {
|
|
633
|
-
if (
|
|
665
|
+
if (generatedPublicKey) {
|
|
634
666
|
try {
|
|
635
|
-
await this.apiKeyStamper?.deleteKeyPair(
|
|
667
|
+
await this.apiKeyStamper?.deleteKeyPair(generatedPublicKey);
|
|
636
668
|
}
|
|
637
669
|
catch (cleanupError) {
|
|
638
670
|
throw new TurnkeyError(`Failed to clean up generated key pair`, TurnkeyErrorCodes.KEY_PAIR_CLEANUP_ERROR, cleanupError);
|
|
@@ -734,7 +766,8 @@ class TurnkeyClient {
|
|
|
734
766
|
* @param params.publicKey - public key to use for authentication. If not provided, a new key pair will be generated.
|
|
735
767
|
* @param params.invalidateExisting - flag to invalidate existing session for the user.
|
|
736
768
|
* @param params.sessionKey - session key to use for session creation (defaults to the default session key).
|
|
737
|
-
* @returns A promise that resolves to a
|
|
769
|
+
* @returns A promise that resolves to a {@link BaseAuthResult}, which includes:
|
|
770
|
+
* - `sessionToken`: the signed JWT session token.
|
|
738
771
|
* @throws {TurnkeyError} If there is an error during the OTP login process or if key pair cleanup fails.
|
|
739
772
|
*/
|
|
740
773
|
this.loginWithOtp = async (params) => {
|
|
@@ -756,7 +789,9 @@ class TurnkeyClient {
|
|
|
756
789
|
sessionToken: loginRes.session,
|
|
757
790
|
sessionKey,
|
|
758
791
|
});
|
|
759
|
-
return
|
|
792
|
+
return {
|
|
793
|
+
sessionToken: loginRes.session,
|
|
794
|
+
};
|
|
760
795
|
}, {
|
|
761
796
|
errorMessage: "Failed to log in with OTP",
|
|
762
797
|
errorCode: TurnkeyErrorCodes.OTP_LOGIN_ERROR,
|
|
@@ -788,7 +823,8 @@ class TurnkeyClient {
|
|
|
788
823
|
* @param params.createSubOrgParams - parameters for creating a sub-organization (e.g., authenticators, user metadata).
|
|
789
824
|
* @param params.invalidateExisting - flag to invalidate existing session for the user.
|
|
790
825
|
* @param params.sessionKey - session key to use for session creation (defaults to the default session key).
|
|
791
|
-
* @returns A promise that resolves to a
|
|
826
|
+
* @returns A promise that resolves to a {@link BaseAuthResult}, which includes:
|
|
827
|
+
* - `sessionToken`: the signed JWT session token.
|
|
792
828
|
* @throws {TurnkeyError} If there is an error during the OTP sign-up process or session storage.
|
|
793
829
|
*/
|
|
794
830
|
this.signUpWithOtp = async (params) => {
|
|
@@ -803,14 +839,14 @@ class TurnkeyClient {
|
|
|
803
839
|
},
|
|
804
840
|
});
|
|
805
841
|
return withTurnkeyErrorHandling(async () => {
|
|
806
|
-
const
|
|
842
|
+
const generatedPublicKey = await this.apiKeyStamper?.createKeyPair();
|
|
807
843
|
const res = await this.httpClient.proxySignup(signUpBody);
|
|
808
844
|
if (!res) {
|
|
809
845
|
throw new TurnkeyError(`Auth proxy OTP sign up failed`, TurnkeyErrorCodes.OTP_SIGNUP_ERROR);
|
|
810
846
|
}
|
|
811
847
|
return await this.loginWithOtp({
|
|
812
848
|
verificationToken,
|
|
813
|
-
publicKey:
|
|
849
|
+
publicKey: generatedPublicKey,
|
|
814
850
|
...(invalidateExisting && { invalidateExisting }),
|
|
815
851
|
...(sessionKey && { sessionKey }),
|
|
816
852
|
});
|
|
@@ -836,7 +872,10 @@ class TurnkeyClient {
|
|
|
836
872
|
* @param params.invalidateExisting - flag to invalidate existing sessions for the user.
|
|
837
873
|
* @param params.sessionKey - session key to use for session creation (defaults to the default session key).
|
|
838
874
|
* @param params.createSubOrgParams - parameters for sub-organization creation (e.g., authenticators, user metadata).
|
|
839
|
-
* @returns A promise that resolves to
|
|
875
|
+
* @returns A promise that resolves to an object containing:
|
|
876
|
+
* - `sessionToken`: the signed JWT session token.
|
|
877
|
+
* - `verificationToken`: the OTP verification token.
|
|
878
|
+
* - `action`: whether the flow resulted in a login or signup ({@link AuthAction}).
|
|
840
879
|
* @throws {TurnkeyError} If there is an error during OTP verification, sign-up, or login.
|
|
841
880
|
*/
|
|
842
881
|
this.completeOtp = async (params) => {
|
|
@@ -852,24 +891,32 @@ class TurnkeyClient {
|
|
|
852
891
|
throw new TurnkeyError("No verification token returned from OTP verification", TurnkeyErrorCodes.VERIFY_OTP_ERROR);
|
|
853
892
|
}
|
|
854
893
|
if (!subOrganizationId) {
|
|
855
|
-
|
|
894
|
+
const signUpRes = await this.signUpWithOtp({
|
|
856
895
|
verificationToken,
|
|
857
|
-
contact
|
|
858
|
-
otpType
|
|
859
|
-
...(createSubOrgParams && {
|
|
860
|
-
createSubOrgParams,
|
|
861
|
-
}),
|
|
896
|
+
contact,
|
|
897
|
+
otpType,
|
|
898
|
+
...(createSubOrgParams && { createSubOrgParams }),
|
|
862
899
|
...(invalidateExisting && { invalidateExisting }),
|
|
863
900
|
...(sessionKey && { sessionKey }),
|
|
864
901
|
});
|
|
902
|
+
return {
|
|
903
|
+
...signUpRes,
|
|
904
|
+
verificationToken,
|
|
905
|
+
action: AuthAction.SIGNUP,
|
|
906
|
+
};
|
|
865
907
|
}
|
|
866
908
|
else {
|
|
867
|
-
|
|
909
|
+
const loginRes = await this.loginWithOtp({
|
|
868
910
|
verificationToken,
|
|
869
911
|
...(publicKey && { publicKey }),
|
|
870
912
|
...(invalidateExisting && { invalidateExisting }),
|
|
871
913
|
...(sessionKey && { sessionKey }),
|
|
872
914
|
});
|
|
915
|
+
return {
|
|
916
|
+
...loginRes,
|
|
917
|
+
verificationToken,
|
|
918
|
+
action: AuthAction.LOGIN,
|
|
919
|
+
};
|
|
873
920
|
}
|
|
874
921
|
}, {
|
|
875
922
|
errorMessage: "Failed to complete OTP process",
|
|
@@ -886,12 +933,14 @@ class TurnkeyClient {
|
|
|
886
933
|
* - Handles session storage and management, and supports invalidating existing sessions if specified.
|
|
887
934
|
*
|
|
888
935
|
* @param params.oidcToken - OIDC token received after successful authentication with the OAuth provider.
|
|
889
|
-
* @param params.publicKey - public key to use for authentication. Must be generated prior to calling this function
|
|
936
|
+
* @param params.publicKey - public key to use for authentication. Must be generated prior to calling this function, this is because the OIDC nonce has to be set to `sha256(publicKey)`.
|
|
890
937
|
* @param params.providerName - name of the OAuth provider (defaults to a generated name with a timestamp).
|
|
891
938
|
* @param params.sessionKey - session key to use for session creation (defaults to the default session key).
|
|
892
939
|
* @param params.invalidateExisting - flag to invalidate existing sessions for the user.
|
|
893
940
|
* @param params.createSubOrgParams - parameters for sub-organization creation (e.g., authenticators, user metadata).
|
|
894
|
-
* @returns A promise that resolves to
|
|
941
|
+
* @returns A promise that resolves to an object containing:
|
|
942
|
+
* - `sessionToken`: the signed JWT session token.
|
|
943
|
+
* - `action`: whether the flow resulted in a login or signup ({@link AuthAction}).
|
|
895
944
|
* @throws {TurnkeyError} If there is an error during the OAuth completion process, such as account lookup, sign-up, or login.
|
|
896
945
|
*/
|
|
897
946
|
this.completeOauth = async (params) => {
|
|
@@ -906,22 +955,31 @@ class TurnkeyClient {
|
|
|
906
955
|
}
|
|
907
956
|
const subOrganizationId = accountRes.organizationId;
|
|
908
957
|
if (subOrganizationId) {
|
|
909
|
-
|
|
958
|
+
const loginRes = await this.loginWithOauth({
|
|
910
959
|
oidcToken,
|
|
911
960
|
publicKey,
|
|
912
961
|
invalidateExisting,
|
|
913
962
|
sessionKey,
|
|
914
963
|
});
|
|
964
|
+
return {
|
|
965
|
+
...loginRes,
|
|
966
|
+
action: AuthAction.LOGIN,
|
|
967
|
+
};
|
|
915
968
|
}
|
|
916
969
|
else {
|
|
917
|
-
|
|
970
|
+
const signUpRes = await this.signUpWithOauth({
|
|
918
971
|
oidcToken,
|
|
919
972
|
publicKey,
|
|
920
973
|
providerName,
|
|
974
|
+
sessionKey,
|
|
921
975
|
...(createSubOrgParams && {
|
|
922
976
|
createSubOrgParams,
|
|
923
977
|
}),
|
|
924
978
|
});
|
|
979
|
+
return {
|
|
980
|
+
...signUpRes,
|
|
981
|
+
action: AuthAction.SIGNUP,
|
|
982
|
+
};
|
|
925
983
|
}
|
|
926
984
|
}, {
|
|
927
985
|
errorMessage: "Failed to complete OAuth process",
|
|
@@ -940,7 +998,8 @@ class TurnkeyClient {
|
|
|
940
998
|
* @param params.publicKey - public key to use for authentication. Must be generated prior to calling this function.
|
|
941
999
|
* @param params.invalidateExisting - flag to invalidate existing sessions for the user.
|
|
942
1000
|
* @param params.sessionKey - session key to use for session creation (defaults to the default session key).
|
|
943
|
-
* @returns A promise that resolves to a
|
|
1001
|
+
* @returns A promise that resolves to a {@link BaseAuthResult}, which includes:
|
|
1002
|
+
* - `sessionToken`: the signed JWT session token.
|
|
944
1003
|
* @throws {TurnkeyError} If there is an error during the OAuth login process or if key pair cleanup fails.
|
|
945
1004
|
*/
|
|
946
1005
|
this.loginWithOauth = async (params) => {
|
|
@@ -964,7 +1023,7 @@ class TurnkeyClient {
|
|
|
964
1023
|
sessionToken: loginRes.session,
|
|
965
1024
|
sessionKey,
|
|
966
1025
|
});
|
|
967
|
-
return loginRes.session;
|
|
1026
|
+
return { sessionToken: loginRes.session };
|
|
968
1027
|
}, {
|
|
969
1028
|
errorMessage: "Failed to complete OAuth login",
|
|
970
1029
|
errorCode: TurnkeyErrorCodes.OAUTH_LOGIN_ERROR,
|
|
@@ -1000,11 +1059,12 @@ class TurnkeyClient {
|
|
|
1000
1059
|
* @param params.providerName - name of the OAuth provider (e.g., "Google", "Apple").
|
|
1001
1060
|
* @param params.createSubOrgParams - parameters for sub-organization creation (e.g., authenticators, user metadata).
|
|
1002
1061
|
* @param params.sessionKey - session key to use for session creation (defaults to the default session key).
|
|
1003
|
-
* @returns A promise that resolves to a
|
|
1062
|
+
* @returns A promise that resolves to a {@link BaseAuthResult}, which includes:
|
|
1063
|
+
* - `sessionToken`: the signed JWT session token.
|
|
1004
1064
|
* @throws {TurnkeyError} If there is an error during the OAuth sign-up or login process.
|
|
1005
1065
|
*/
|
|
1006
1066
|
this.signUpWithOauth = async (params) => {
|
|
1007
|
-
const { oidcToken, publicKey, providerName, createSubOrgParams } = params;
|
|
1067
|
+
const { oidcToken, publicKey, providerName, createSubOrgParams, sessionKey, } = params;
|
|
1008
1068
|
return withTurnkeyErrorHandling(async () => {
|
|
1009
1069
|
const signUpBody = buildSignUpBody({
|
|
1010
1070
|
createSubOrgParams: {
|
|
@@ -1024,6 +1084,7 @@ class TurnkeyClient {
|
|
|
1024
1084
|
return await this.loginWithOauth({
|
|
1025
1085
|
oidcToken,
|
|
1026
1086
|
publicKey: publicKey,
|
|
1087
|
+
...(sessionKey && { sessionKey }),
|
|
1027
1088
|
});
|
|
1028
1089
|
}, {
|
|
1029
1090
|
errorMessage: "Failed to sign up with OAuth",
|
|
@@ -1040,6 +1101,7 @@ class TurnkeyClient {
|
|
|
1040
1101
|
* - Optionally allows stamping the request with a specific stamper (StamperType.Passkey, StamperType.ApiKey, or StamperType.Wallet).
|
|
1041
1102
|
*
|
|
1042
1103
|
* @param params.stampWith - parameter to stamp the request with a specific stamper (StamperType.Passkey, StamperType.ApiKey, or StamperType.Wallet).
|
|
1104
|
+
* @param params.walletProviders - array of wallet providers to use for fetching wallets.
|
|
1043
1105
|
* @returns A promise that resolves to an array of `Wallet` objects.
|
|
1044
1106
|
* @throws {TurnkeyError} If no active session is found or if there is an error fetching wallets.
|
|
1045
1107
|
*/
|
|
@@ -1073,6 +1135,8 @@ class TurnkeyClient {
|
|
|
1073
1135
|
const providers = walletProviders ?? (await this.getWalletProviders());
|
|
1074
1136
|
const groupedProviders = new Map();
|
|
1075
1137
|
for (const provider of providers) {
|
|
1138
|
+
// connected wallets don't all have some uuid we can use for the walletId
|
|
1139
|
+
// so what we do is we use a normalized version of the name for the wallet, like "metamask" or "phantom-wallet"
|
|
1076
1140
|
const walletId = provider.info?.name?.toLowerCase().replace(/\s+/g, "-") ||
|
|
1077
1141
|
"unknown";
|
|
1078
1142
|
const group = groupedProviders.get(walletId) || [];
|
|
@@ -1154,9 +1218,20 @@ class TurnkeyClient {
|
|
|
1154
1218
|
return [];
|
|
1155
1219
|
const connected = [];
|
|
1156
1220
|
const providers = walletProviders ?? (await this.getWalletProviders());
|
|
1221
|
+
// Context: connected wallets don't all have some uuid we can use for the walletId so what
|
|
1222
|
+
// we do is we use a normalized version of the name for the wallet, like "metamask"
|
|
1223
|
+
// or "phantom-wallet"
|
|
1224
|
+
//
|
|
1225
|
+
// when fetching accounts, we select all providers with this normalized walletId.
|
|
1226
|
+
// A single wallet can map to multiple providers if it supports multiple chains
|
|
1227
|
+
// (e.g. MetaMask for Ethereum and MetaMask for Solana)
|
|
1157
1228
|
const matching = providers.filter((p) => p.info?.name?.toLowerCase().replace(/\s+/g, "-") ===
|
|
1158
1229
|
wallet.walletId && p.connectedAddresses.length > 0);
|
|
1159
1230
|
const sign = this.walletManager.connector.sign.bind(this.walletManager.connector);
|
|
1231
|
+
const user = await this.fetchUser({
|
|
1232
|
+
stampWith,
|
|
1233
|
+
});
|
|
1234
|
+
const { ethereum: ethereumAddresses, solana: solanaAddresses } = getAuthenticatorAddresses(user);
|
|
1160
1235
|
for (const provider of matching) {
|
|
1161
1236
|
const timestamp = toExternalTimestamp();
|
|
1162
1237
|
for (const address of provider.connectedAddresses) {
|
|
@@ -1175,6 +1250,7 @@ class TurnkeyClient {
|
|
|
1175
1250
|
curve: Curve.SECP256K1,
|
|
1176
1251
|
addressFormat: "ADDRESS_FORMAT_ETHEREUM",
|
|
1177
1252
|
chainInfo: provider.chainInfo,
|
|
1253
|
+
isAuthenticator: ethereumAddresses.includes(address.toLowerCase()),
|
|
1178
1254
|
signMessage: (msg) => sign(msg, provider, SignIntent.SignMessage),
|
|
1179
1255
|
signAndSendTransaction: (tx) => sign(tx, provider, SignIntent.SignAndSendTransaction),
|
|
1180
1256
|
};
|
|
@@ -1197,6 +1273,7 @@ class TurnkeyClient {
|
|
|
1197
1273
|
curve: Curve.ED25519,
|
|
1198
1274
|
addressFormat: "ADDRESS_FORMAT_SOLANA",
|
|
1199
1275
|
chainInfo: provider.chainInfo,
|
|
1276
|
+
isAuthenticator: solanaAddresses.includes(address),
|
|
1200
1277
|
signMessage: (msg) => sign(msg, provider, SignIntent.SignMessage),
|
|
1201
1278
|
signTransaction: (tx) => sign(tx, provider, SignIntent.SignTransaction),
|
|
1202
1279
|
};
|
|
@@ -1212,6 +1289,33 @@ class TurnkeyClient {
|
|
|
1212
1289
|
errorCode: TurnkeyErrorCodes.FETCH_WALLET_ACCOUNTS_ERROR,
|
|
1213
1290
|
});
|
|
1214
1291
|
};
|
|
1292
|
+
/**
|
|
1293
|
+
* Fetches all private keys for the current user.
|
|
1294
|
+
*
|
|
1295
|
+
* - Retrieves private keys from the Turnkey API.
|
|
1296
|
+
* - Supports stamping the request with a specific stamper (StamperType.Passkey, StamperType.ApiKey, or StamperType.Wallet).
|
|
1297
|
+
*
|
|
1298
|
+
* @param params.stampWith - parameter to stamp the request with a specific stamper (StamperType.Passkey, StamperType.ApiKey, or StamperType.Wallet).
|
|
1299
|
+
* @returns A promise that resolves to an array of `v1PrivateKey` objects.
|
|
1300
|
+
* @throws {TurnkeyError} If no active session is found or if there is an error fetching private keys.
|
|
1301
|
+
*/
|
|
1302
|
+
this.fetchPrivateKeys = async (params) => {
|
|
1303
|
+
const { stampWith } = params || {};
|
|
1304
|
+
const session = await this.storageManager.getActiveSession();
|
|
1305
|
+
if (!session) {
|
|
1306
|
+
throw new TurnkeyError("No active session found. Please log in first.", TurnkeyErrorCodes.NO_SESSION_FOUND);
|
|
1307
|
+
}
|
|
1308
|
+
return withTurnkeyErrorHandling(async () => {
|
|
1309
|
+
const res = await this.httpClient.getPrivateKeys({ organizationId: session.organizationId }, stampWith);
|
|
1310
|
+
if (!res) {
|
|
1311
|
+
throw new TurnkeyError("Failed to fetch private keys", TurnkeyErrorCodes.BAD_RESPONSE);
|
|
1312
|
+
}
|
|
1313
|
+
return res.privateKeys;
|
|
1314
|
+
}, {
|
|
1315
|
+
errorMessage: "Failed to fetch private keys",
|
|
1316
|
+
errorCode: TurnkeyErrorCodes.FETCH_PRIVATE_KEYS_ERROR,
|
|
1317
|
+
});
|
|
1318
|
+
};
|
|
1215
1319
|
/**
|
|
1216
1320
|
* Signs a message using the specified wallet account.
|
|
1217
1321
|
*
|
|
@@ -1744,7 +1848,6 @@ class TurnkeyClient {
|
|
|
1744
1848
|
this.addPasskey = async (params) => {
|
|
1745
1849
|
const { stampWith } = params || {};
|
|
1746
1850
|
const name = params?.name || `Turnkey Passkey-${Date.now()}`;
|
|
1747
|
-
const displayName = params?.displayName || name;
|
|
1748
1851
|
return withTurnkeyErrorHandling(async () => {
|
|
1749
1852
|
const session = await this.storageManager.getActiveSession();
|
|
1750
1853
|
if (!session) {
|
|
@@ -1753,7 +1856,6 @@ class TurnkeyClient {
|
|
|
1753
1856
|
const userId = params?.userId || session.userId;
|
|
1754
1857
|
const { encodedChallenge, attestation } = await this.createPasskey({
|
|
1755
1858
|
name,
|
|
1756
|
-
displayName,
|
|
1757
1859
|
...(stampWith && { stampWith }),
|
|
1758
1860
|
});
|
|
1759
1861
|
if (!attestation || !encodedChallenge) {
|
|
@@ -2227,9 +2329,8 @@ class TurnkeyClient {
|
|
|
2227
2329
|
this.clearAllSessions = async () => {
|
|
2228
2330
|
withTurnkeyErrorHandling(async () => {
|
|
2229
2331
|
const sessionKeys = await this.storageManager.listSessionKeys();
|
|
2230
|
-
if (sessionKeys.length === 0)
|
|
2231
|
-
|
|
2232
|
-
}
|
|
2332
|
+
if (sessionKeys.length === 0)
|
|
2333
|
+
return;
|
|
2233
2334
|
for (const sessionKey of sessionKeys) {
|
|
2234
2335
|
this.clearSession({ sessionKey });
|
|
2235
2336
|
}
|
|
@@ -2447,7 +2548,7 @@ class TurnkeyClient {
|
|
|
2447
2548
|
}
|
|
2448
2549
|
const publicKey = await this.apiKeyStamper.createKeyPair(externalKeyPair ? externalKeyPair : undefined);
|
|
2449
2550
|
if (storeOverride && publicKey) {
|
|
2450
|
-
await this.apiKeyStamper.
|
|
2551
|
+
await this.apiKeyStamper.setTemporaryPublicKey(publicKey);
|
|
2451
2552
|
}
|
|
2452
2553
|
return publicKey;
|
|
2453
2554
|
}, {
|