@turnkey/core 1.0.0-beta.2 → 1.0.0-beta.4
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 +75 -2
- package/dist/__clients__/core.d.ts.map +1 -1
- package/dist/__clients__/core.js +637 -503
- package/dist/__clients__/core.js.map +1 -1
- package/dist/__clients__/core.mjs +640 -506
- package/dist/__clients__/core.mjs.map +1 -1
- package/dist/__generated__/sdk-client-base.d.ts +1 -1
- package/dist/__generated__/sdk-client-base.d.ts.map +1 -1
- package/dist/__generated__/sdk-client-base.js +156 -250
- package/dist/__generated__/sdk-client-base.js.map +1 -1
- package/dist/__generated__/sdk-client-base.mjs +156 -250
- 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/__types__/base.d.ts +1 -1
- package/dist/__wallet__/base.d.ts +11 -0
- package/dist/__wallet__/base.d.ts.map +1 -1
- package/dist/__wallet__/base.js +12 -1
- package/dist/__wallet__/base.js.map +1 -1
- package/dist/__wallet__/base.mjs +12 -1
- package/dist/__wallet__/base.mjs.map +1 -1
- package/dist/__wallet__/connector.d.ts +31 -4
- package/dist/__wallet__/connector.d.ts.map +1 -1
- package/dist/__wallet__/connector.js +35 -5
- package/dist/__wallet__/connector.js.map +1 -1
- package/dist/__wallet__/connector.mjs +35 -5
- package/dist/__wallet__/connector.mjs.map +1 -1
- package/dist/__wallet__/mobile/manager.d.ts +21 -5
- package/dist/__wallet__/mobile/manager.d.ts.map +1 -1
- package/dist/__wallet__/mobile/manager.js +28 -11
- package/dist/__wallet__/mobile/manager.js.map +1 -1
- package/dist/__wallet__/mobile/manager.mjs +28 -11
- package/dist/__wallet__/mobile/manager.mjs.map +1 -1
- package/dist/__wallet__/stamper.d.ts +73 -2
- package/dist/__wallet__/stamper.d.ts.map +1 -1
- package/dist/__wallet__/stamper.js +79 -13
- package/dist/__wallet__/stamper.js.map +1 -1
- package/dist/__wallet__/stamper.mjs +79 -13
- package/dist/__wallet__/stamper.mjs.map +1 -1
- package/dist/__wallet__/wallet-connect/base.d.ts +99 -19
- package/dist/__wallet__/wallet-connect/base.d.ts.map +1 -1
- package/dist/__wallet__/wallet-connect/base.js +172 -75
- package/dist/__wallet__/wallet-connect/base.js.map +1 -1
- package/dist/__wallet__/wallet-connect/base.mjs +172 -75
- package/dist/__wallet__/wallet-connect/base.mjs.map +1 -1
- package/dist/__wallet__/wallet-connect/client.d.ts +22 -14
- package/dist/__wallet__/wallet-connect/client.d.ts.map +1 -1
- package/dist/__wallet__/wallet-connect/client.js +22 -14
- package/dist/__wallet__/wallet-connect/client.js.map +1 -1
- package/dist/__wallet__/wallet-connect/client.mjs +22 -14
- package/dist/__wallet__/wallet-connect/client.mjs.map +1 -1
- package/dist/__wallet__/web/manager.d.ts +20 -12
- package/dist/__wallet__/web/manager.d.ts.map +1 -1
- package/dist/__wallet__/web/manager.js +29 -21
- package/dist/__wallet__/web/manager.js.map +1 -1
- package/dist/__wallet__/web/manager.mjs +29 -21
- package/dist/__wallet__/web/manager.mjs.map +1 -1
- package/dist/__wallet__/web/native/ethereum.d.ts +45 -11
- package/dist/__wallet__/web/native/ethereum.d.ts.map +1 -1
- package/dist/__wallet__/web/native/ethereum.js +58 -17
- package/dist/__wallet__/web/native/ethereum.js.map +1 -1
- package/dist/__wallet__/web/native/ethereum.mjs +58 -17
- package/dist/__wallet__/web/native/ethereum.mjs.map +1 -1
- package/dist/__wallet__/web/native/solana.d.ts +56 -3
- package/dist/__wallet__/web/native/solana.d.ts.map +1 -1
- package/dist/__wallet__/web/native/solana.js +95 -36
- package/dist/__wallet__/web/native/solana.js.map +1 -1
- package/dist/__wallet__/web/native/solana.mjs +95 -36
- package/dist/__wallet__/web/native/solana.mjs.map +1 -1
- package/dist/utils.d.ts +24 -1
- package/dist/utils.d.ts.map +1 -1
- package/dist/utils.js +54 -0
- package/dist/utils.js.map +1 -1
- package/dist/utils.mjs +54 -1
- package/dist/utils.mjs.map +1 -1
- package/package.json +7 -7
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { TurnkeySDKClientBase } from '../__generated__/sdk-client-base.mjs';
|
|
2
|
-
import {
|
|
3
|
-
import { SessionKey, DEFAULT_SESSION_EXPIRATION_IN_SECONDS, StamperType, Chain, FilterType, OtpTypeToFilterTypeMap,
|
|
4
|
-
import { isWeb, isReactNative, buildSignUpBody, isEthereumWallet, getPublicKeyFromStampHeader, toExternalTimestamp, isSolanaWallet, getWalletAccountMethods, getHashFunction, getEncodingType, getEncodedMessage, splitSignature, broadcastTransaction, googleISS, isWalletAccountArray, generateWalletAccountsFromAddressFormat } from '../utils.mjs';
|
|
2
|
+
import { TurnkeyErrorCodes, TurnkeyError, TurnkeyNetworkError } from '@turnkey/sdk-types';
|
|
3
|
+
import { SessionKey, DEFAULT_SESSION_EXPIRATION_IN_SECONDS, StamperType, Chain, FilterType, OtpTypeToFilterTypeMap, OtpType, WalletSource, Curve } from '../__types__/base.mjs';
|
|
4
|
+
import { withTurnkeyErrorHandling, isWeb, isReactNative, buildSignUpBody, isEthereumWallet, getPublicKeyFromStampHeader, toExternalTimestamp, isSolanaWallet, getWalletAccountMethods, 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';
|
|
@@ -30,7 +30,7 @@ class TurnkeyClient {
|
|
|
30
30
|
* @throws {TurnkeyError} If there is an error during passkey creation, or if the platform is unsupported.
|
|
31
31
|
*/
|
|
32
32
|
this.createPasskey = async (params) => {
|
|
33
|
-
|
|
33
|
+
return withTurnkeyErrorHandling(async () => {
|
|
34
34
|
const name = params?.name || "A Passkey";
|
|
35
35
|
const displayName = params?.displayName || "A Passkey";
|
|
36
36
|
let passkey;
|
|
@@ -68,16 +68,16 @@ class TurnkeyClient {
|
|
|
68
68
|
throw new TurnkeyError("Unsupported platform for passkey creation", TurnkeyErrorCodes.INVALID_REQUEST);
|
|
69
69
|
}
|
|
70
70
|
return passkey;
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
}
|
|
71
|
+
}, {
|
|
72
|
+
errorMessage: "Failed to create passkey",
|
|
73
|
+
errorCode: TurnkeyErrorCodes.CREATE_PASSKEY_ERROR,
|
|
74
|
+
customMessageByMessages: {
|
|
75
|
+
"timed out or was not allowed": {
|
|
76
|
+
message: "Passkey creation was cancelled by the user.",
|
|
77
|
+
code: TurnkeyErrorCodes.SELECT_PASSKEY_CANCELLED,
|
|
78
|
+
},
|
|
79
|
+
},
|
|
80
|
+
});
|
|
81
81
|
};
|
|
82
82
|
/**
|
|
83
83
|
* Logs out the current client session.
|
|
@@ -91,7 +91,7 @@ class TurnkeyClient {
|
|
|
91
91
|
* @throws {TurnkeyError} If there is no active session or if there is an error during the logout process.
|
|
92
92
|
*/
|
|
93
93
|
this.logout = async (params) => {
|
|
94
|
-
|
|
94
|
+
withTurnkeyErrorHandling(async () => {
|
|
95
95
|
if (params?.sessionKey) {
|
|
96
96
|
const session = await this.storageManager.getSession(params.sessionKey);
|
|
97
97
|
this.storageManager.clearSession(params.sessionKey);
|
|
@@ -108,12 +108,10 @@ class TurnkeyClient {
|
|
|
108
108
|
throw new TurnkeyError("No active session found to log out from.", TurnkeyErrorCodes.NO_SESSION_FOUND);
|
|
109
109
|
}
|
|
110
110
|
}
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
throw new TurnkeyError(`Failed to log out`, TurnkeyErrorCodes.LOGOUT_ERROR, error);
|
|
116
|
-
}
|
|
111
|
+
}, {
|
|
112
|
+
errorMessage: "Failed to log out",
|
|
113
|
+
errorCode: TurnkeyErrorCodes.LOGOUT_ERROR,
|
|
114
|
+
});
|
|
117
115
|
};
|
|
118
116
|
/**
|
|
119
117
|
* Logs in a user using a passkey, optionally specifying the public key, session key, and session expiration.
|
|
@@ -131,16 +129,17 @@ class TurnkeyClient {
|
|
|
131
129
|
* @throws {TurnkeyError} If there is an error during the passkey login process or if the user cancels the passkey prompt.
|
|
132
130
|
*/
|
|
133
131
|
this.loginWithPasskey = async (params) => {
|
|
134
|
-
let generatedKeyPair =
|
|
135
|
-
|
|
136
|
-
|
|
132
|
+
let generatedKeyPair = undefined;
|
|
133
|
+
return await withTurnkeyErrorHandling(async () => {
|
|
134
|
+
generatedKeyPair =
|
|
135
|
+
params?.publicKey || (await this.apiKeyStamper?.createKeyPair());
|
|
137
136
|
const sessionKey = params?.sessionKey || SessionKey.DefaultSessionkey;
|
|
138
137
|
const expirationSeconds = params?.expirationSeconds || DEFAULT_SESSION_EXPIRATION_IN_SECONDS;
|
|
139
|
-
if (!
|
|
138
|
+
if (!generatedKeyPair) {
|
|
140
139
|
throw new TurnkeyError("A publickey could not be found or generated.", TurnkeyErrorCodes.INTERNAL_ERROR);
|
|
141
140
|
}
|
|
142
141
|
const sessionResponse = await this.httpClient.stampLogin({
|
|
143
|
-
publicKey,
|
|
142
|
+
publicKey: generatedKeyPair,
|
|
144
143
|
organizationId: this.config.organizationId,
|
|
145
144
|
expirationSeconds,
|
|
146
145
|
}, StamperType.Passkey);
|
|
@@ -148,28 +147,29 @@ class TurnkeyClient {
|
|
|
148
147
|
sessionToken: sessionResponse.session,
|
|
149
148
|
sessionKey,
|
|
150
149
|
});
|
|
151
|
-
// Key pair was successfully used, set to null to prevent cleanup
|
|
152
|
-
generatedKeyPair = null;
|
|
150
|
+
generatedKeyPair = undefined; // Key pair was successfully used, set to null to prevent cleanup
|
|
153
151
|
return sessionResponse.session;
|
|
154
|
-
}
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
152
|
+
}, {
|
|
153
|
+
errorMessage: "Unable to log in with the provided passkey",
|
|
154
|
+
errorCode: TurnkeyErrorCodes.PASSKEY_LOGIN_AUTH_ERROR,
|
|
155
|
+
customMessageByMessages: {
|
|
156
|
+
"timed out or was not allowed": {
|
|
157
|
+
message: "Passkey login was cancelled by the user.",
|
|
158
|
+
code: TurnkeyErrorCodes.SELECT_PASSKEY_CANCELLED,
|
|
159
|
+
},
|
|
160
|
+
},
|
|
161
|
+
}, {
|
|
162
|
+
finallyFn: async () => {
|
|
163
|
+
if (generatedKeyPair) {
|
|
164
|
+
try {
|
|
165
|
+
await this.apiKeyStamper?.deleteKeyPair(generatedKeyPair);
|
|
166
|
+
}
|
|
167
|
+
catch (cleanupError) {
|
|
168
|
+
throw new TurnkeyError(`Failed to clean up generated key pair`, TurnkeyErrorCodes.KEY_PAIR_CLEANUP_ERROR, cleanupError);
|
|
169
|
+
}
|
|
170
170
|
}
|
|
171
|
-
}
|
|
172
|
-
}
|
|
171
|
+
},
|
|
172
|
+
});
|
|
173
173
|
};
|
|
174
174
|
/**
|
|
175
175
|
* Signs up a user using a passkey, creating a new sub-organization and session.
|
|
@@ -189,8 +189,8 @@ class TurnkeyClient {
|
|
|
189
189
|
*/
|
|
190
190
|
this.signUpWithPasskey = async (params) => {
|
|
191
191
|
const { createSubOrgParams, passkeyDisplayName, sessionKey = SessionKey.DefaultSessionkey, expirationSeconds = DEFAULT_SESSION_EXPIRATION_IN_SECONDS, } = params || {};
|
|
192
|
-
let generatedKeyPair =
|
|
193
|
-
|
|
192
|
+
let generatedKeyPair = undefined;
|
|
193
|
+
return withTurnkeyErrorHandling(async () => {
|
|
194
194
|
generatedKeyPair = await this.apiKeyStamper?.createKeyPair();
|
|
195
195
|
const passkeyName = passkeyDisplayName || `passkey-${Date.now()}`;
|
|
196
196
|
// A passkey will be created automatically when you call this function. The name is passed in
|
|
@@ -239,26 +239,24 @@ class TurnkeyClient {
|
|
|
239
239
|
sessionToken: sessionResponse.session,
|
|
240
240
|
sessionKey,
|
|
241
241
|
});
|
|
242
|
-
generatedKeyPair =
|
|
242
|
+
generatedKeyPair = undefined; // Key pair was successfully used, set to null to prevent cleanup
|
|
243
243
|
return sessionResponse.session;
|
|
244
|
-
}
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
catch (cleanupError) {
|
|
258
|
-
throw new TurnkeyError(`Failed to clean up generated key pair`, TurnkeyErrorCodes.KEY_PAIR_CLEANUP_ERROR, cleanupError);
|
|
244
|
+
}, {
|
|
245
|
+
errorCode: TurnkeyErrorCodes.PASSKEY_SIGNUP_AUTH_ERROR,
|
|
246
|
+
errorMessage: "Failed to sign up with passkey",
|
|
247
|
+
}, {
|
|
248
|
+
finallyFn: async () => {
|
|
249
|
+
this.apiKeyStamper?.clearPublicKeyOverride();
|
|
250
|
+
if (generatedKeyPair) {
|
|
251
|
+
try {
|
|
252
|
+
await this.apiKeyStamper?.deleteKeyPair(generatedKeyPair);
|
|
253
|
+
}
|
|
254
|
+
catch (cleanupError) {
|
|
255
|
+
throw new TurnkeyError(`Failed to clean up generated key pair`, TurnkeyErrorCodes.KEY_PAIR_CLEANUP_ERROR, cleanupError);
|
|
256
|
+
}
|
|
259
257
|
}
|
|
260
|
-
}
|
|
261
|
-
}
|
|
258
|
+
},
|
|
259
|
+
});
|
|
262
260
|
};
|
|
263
261
|
/**
|
|
264
262
|
* Retrieves wallet providers from the initialized wallet manager.
|
|
@@ -271,15 +269,15 @@ class TurnkeyClient {
|
|
|
271
269
|
* @throws {TurnkeyError} If the wallet manager is uninitialized or provider retrieval fails.
|
|
272
270
|
*/
|
|
273
271
|
this.getWalletProviders = async (chain) => {
|
|
274
|
-
|
|
272
|
+
return withTurnkeyErrorHandling(async () => {
|
|
275
273
|
if (!this.walletManager) {
|
|
276
274
|
throw new TurnkeyError("Wallet manager is not initialized", TurnkeyErrorCodes.WALLET_MANAGER_COMPONENT_NOT_INITIALIZED);
|
|
277
275
|
}
|
|
278
276
|
return await this.walletManager.getProviders(chain);
|
|
279
|
-
}
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
}
|
|
277
|
+
}, {
|
|
278
|
+
errorMessage: "Unable to get wallet providers",
|
|
279
|
+
errorCode: TurnkeyErrorCodes.FETCH_WALLETS_ERROR,
|
|
280
|
+
});
|
|
283
281
|
};
|
|
284
282
|
/**
|
|
285
283
|
* Connects the specified wallet account.
|
|
@@ -291,15 +289,15 @@ class TurnkeyClient {
|
|
|
291
289
|
* @throws {TurnkeyError} If the wallet manager is uninitialized or the connection fails.
|
|
292
290
|
*/
|
|
293
291
|
this.connectWalletAccount = async (walletProvider) => {
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
292
|
+
return withTurnkeyErrorHandling(async () => {
|
|
293
|
+
if (!this.walletManager?.connector) {
|
|
294
|
+
throw new TurnkeyError("Wallet connector is not initialized", TurnkeyErrorCodes.WALLET_MANAGER_COMPONENT_NOT_INITIALIZED);
|
|
295
|
+
}
|
|
298
296
|
await this.walletManager.connector.connectWalletAccount(walletProvider);
|
|
299
|
-
}
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
}
|
|
297
|
+
}, {
|
|
298
|
+
errorMessage: "Unable to connect wallet account",
|
|
299
|
+
errorCode: TurnkeyErrorCodes.CONNECT_WALLET_ACCOUNT_ERROR,
|
|
300
|
+
});
|
|
303
301
|
};
|
|
304
302
|
/**
|
|
305
303
|
* Disconnects the specified wallet account.
|
|
@@ -311,15 +309,15 @@ class TurnkeyClient {
|
|
|
311
309
|
* @throws {TurnkeyError} If the wallet manager is uninitialized or the disconnection fails.
|
|
312
310
|
*/
|
|
313
311
|
this.disconnectWalletAccount = async (walletProvider) => {
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
312
|
+
return withTurnkeyErrorHandling(async () => {
|
|
313
|
+
if (!this.walletManager?.connector) {
|
|
314
|
+
throw new TurnkeyError("Wallet connector is not initialized", TurnkeyErrorCodes.WALLET_MANAGER_COMPONENT_NOT_INITIALIZED);
|
|
315
|
+
}
|
|
318
316
|
await this.walletManager.connector.disconnectWalletAccount(walletProvider);
|
|
319
|
-
}
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
}
|
|
317
|
+
}, {
|
|
318
|
+
errorMessage: "Unable to disconnect wallet account",
|
|
319
|
+
errorCode: TurnkeyErrorCodes.DISCONNECT_WALLET_ACCOUNT_ERROR,
|
|
320
|
+
});
|
|
323
321
|
};
|
|
324
322
|
/**
|
|
325
323
|
* Switches the specified wallet provider to a different blockchain chain.
|
|
@@ -334,22 +332,22 @@ class TurnkeyClient {
|
|
|
334
332
|
* @throws {TurnkeyError} If the wallet manager is uninitialized, the provider is not connected, or the switch fails.
|
|
335
333
|
*/
|
|
336
334
|
this.switchWalletProviderChain = async (walletProvider, chainOrId) => {
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
335
|
+
return withTurnkeyErrorHandling(async () => {
|
|
336
|
+
if (!this.walletManager?.connector) {
|
|
337
|
+
throw new TurnkeyError("Wallet connector is not initialized", TurnkeyErrorCodes.WALLET_MANAGER_COMPONENT_NOT_INITIALIZED);
|
|
338
|
+
}
|
|
339
|
+
if (walletProvider.connectedAddresses.length === 0) {
|
|
340
|
+
throw new TurnkeyError("You can not switch chains for a provider that is not connected", TurnkeyErrorCodes.INVALID_REQUEST);
|
|
341
|
+
}
|
|
342
|
+
// if the wallet provider is already on the desired chain, do nothing
|
|
343
|
+
if (walletProvider.chainInfo.namespace === chainOrId) {
|
|
344
|
+
return;
|
|
345
|
+
}
|
|
348
346
|
await this.walletManager.connector.switchChain(walletProvider, chainOrId);
|
|
349
|
-
}
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
}
|
|
347
|
+
}, {
|
|
348
|
+
errorMessage: "Unable to switch wallet account chain",
|
|
349
|
+
errorCode: TurnkeyErrorCodes.SWITCH_WALLET_CHAIN_ERROR,
|
|
350
|
+
});
|
|
353
351
|
};
|
|
354
352
|
/**
|
|
355
353
|
* Logs in a user using the specified wallet provider.
|
|
@@ -368,11 +366,11 @@ class TurnkeyClient {
|
|
|
368
366
|
* @throws {TurnkeyError} If the wallet stamper is uninitialized, a public key cannot be found or generated, or login fails.
|
|
369
367
|
*/
|
|
370
368
|
this.loginWithWallet = async (params) => {
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
369
|
+
let publicKey = params.publicKey || (await this.apiKeyStamper?.createKeyPair());
|
|
370
|
+
return withTurnkeyErrorHandling(async () => {
|
|
371
|
+
if (!this.walletManager?.stamper) {
|
|
372
|
+
throw new TurnkeyError("Wallet stamper is not initialized", TurnkeyErrorCodes.WALLET_MANAGER_COMPONENT_NOT_INITIALIZED);
|
|
373
|
+
}
|
|
376
374
|
const sessionKey = params.sessionKey || SessionKey.DefaultSessionkey;
|
|
377
375
|
const walletProvider = params.walletProvider;
|
|
378
376
|
const expirationSeconds = params?.expirationSeconds || DEFAULT_SESSION_EXPIRATION_IN_SECONDS;
|
|
@@ -390,12 +388,23 @@ class TurnkeyClient {
|
|
|
390
388
|
sessionKey,
|
|
391
389
|
});
|
|
392
390
|
return sessionResponse.session;
|
|
393
|
-
}
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
391
|
+
}, {
|
|
392
|
+
errorMessage: "Unable to log in with the provided wallet",
|
|
393
|
+
errorCode: TurnkeyErrorCodes.WALLET_LOGIN_AUTH_ERROR,
|
|
394
|
+
}, {
|
|
395
|
+
finallyFn: async () => {
|
|
396
|
+
// Clean up the generated key pair if it wasn't successfully used
|
|
397
|
+
this.apiKeyStamper?.clearPublicKeyOverride();
|
|
398
|
+
if (publicKey) {
|
|
399
|
+
try {
|
|
400
|
+
await this.apiKeyStamper?.deleteKeyPair(publicKey);
|
|
401
|
+
}
|
|
402
|
+
catch (cleanupError) {
|
|
403
|
+
throw new TurnkeyError("Failed to clean up generated key pair", TurnkeyErrorCodes.KEY_PAIR_CLEANUP_ERROR, cleanupError);
|
|
404
|
+
}
|
|
405
|
+
}
|
|
406
|
+
},
|
|
407
|
+
});
|
|
399
408
|
};
|
|
400
409
|
/**
|
|
401
410
|
* Signs up a user using a wallet, creating a new sub-organization and session.
|
|
@@ -415,11 +424,11 @@ class TurnkeyClient {
|
|
|
415
424
|
*/
|
|
416
425
|
this.signUpWithWallet = async (params) => {
|
|
417
426
|
const { walletProvider, createSubOrgParams, sessionKey = SessionKey.DefaultSessionkey, expirationSeconds = DEFAULT_SESSION_EXPIRATION_IN_SECONDS, } = params;
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
427
|
+
let generatedKeyPair = undefined;
|
|
428
|
+
return withTurnkeyErrorHandling(async () => {
|
|
429
|
+
if (!this.walletManager?.stamper) {
|
|
430
|
+
throw new TurnkeyError("Wallet stamper is not initialized", TurnkeyErrorCodes.WALLET_MANAGER_COMPONENT_NOT_INITIALIZED);
|
|
431
|
+
}
|
|
423
432
|
generatedKeyPair = await this.apiKeyStamper?.createKeyPair();
|
|
424
433
|
this.walletManager.stamper.setProvider(walletProvider.interfaceType, walletProvider);
|
|
425
434
|
const publicKey = await this.walletManager.stamper.getPublicKey(walletProvider.interfaceType, walletProvider);
|
|
@@ -462,24 +471,25 @@ class TurnkeyClient {
|
|
|
462
471
|
sessionToken: sessionResponse.session,
|
|
463
472
|
sessionKey,
|
|
464
473
|
});
|
|
465
|
-
generatedKeyPair =
|
|
474
|
+
generatedKeyPair = undefined; // Key pair was successfully used, set to null to prevent cleanup
|
|
466
475
|
return sessionResponse.session;
|
|
467
|
-
}
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
}
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
476
|
+
}, {
|
|
477
|
+
errorMessage: "Failed to sign up with wallet",
|
|
478
|
+
errorCode: TurnkeyErrorCodes.WALLET_SIGNUP_AUTH_ERROR,
|
|
479
|
+
}, {
|
|
480
|
+
finallyFn: async () => {
|
|
481
|
+
// Clean up the generated key pair if it wasn't successfully used
|
|
482
|
+
this.apiKeyStamper?.clearPublicKeyOverride();
|
|
483
|
+
if (generatedKeyPair) {
|
|
484
|
+
try {
|
|
485
|
+
await this.apiKeyStamper?.deleteKeyPair(generatedKeyPair);
|
|
486
|
+
}
|
|
487
|
+
catch (cleanupError) {
|
|
488
|
+
throw new TurnkeyError("Failed to clean up generated key pair", TurnkeyErrorCodes.KEY_PAIR_CLEANUP_ERROR, cleanupError);
|
|
489
|
+
}
|
|
480
490
|
}
|
|
481
|
-
}
|
|
482
|
-
}
|
|
491
|
+
},
|
|
492
|
+
});
|
|
483
493
|
};
|
|
484
494
|
/**
|
|
485
495
|
* Logs in an existing user or signs up a new user using a wallet, creating a new sub-organization if needed.
|
|
@@ -499,25 +509,36 @@ class TurnkeyClient {
|
|
|
499
509
|
* @throws {TurnkeyError} If there is an error during wallet authentication, sub-organization creation, or session storage.
|
|
500
510
|
*/
|
|
501
511
|
this.loginOrSignupWithWallet = async (params) => {
|
|
502
|
-
if (!this.walletManager?.stamper) {
|
|
503
|
-
throw new TurnkeyError("Wallet stamper is not initialized", TurnkeyErrorCodes.WALLET_MANAGER_COMPONENT_NOT_INITIALIZED);
|
|
504
|
-
}
|
|
505
512
|
const createSubOrgParams = params.createSubOrgParams;
|
|
506
513
|
const sessionKey = params.sessionKey || SessionKey.DefaultSessionkey;
|
|
507
514
|
const walletProvider = params.walletProvider;
|
|
508
515
|
const expirationSeconds = params.expirationSeconds || DEFAULT_SESSION_EXPIRATION_IN_SECONDS;
|
|
509
|
-
let generatedKeyPair =
|
|
510
|
-
|
|
516
|
+
let generatedKeyPair = undefined;
|
|
517
|
+
return withTurnkeyErrorHandling(async () => {
|
|
518
|
+
if (!this.walletManager?.stamper) {
|
|
519
|
+
throw new TurnkeyError("Wallet stamper is not initialized", TurnkeyErrorCodes.WALLET_MANAGER_COMPONENT_NOT_INITIALIZED);
|
|
520
|
+
}
|
|
511
521
|
generatedKeyPair = await this.apiKeyStamper?.createKeyPair();
|
|
512
522
|
this.walletManager.stamper.setProvider(walletProvider.interfaceType, walletProvider);
|
|
513
523
|
// here we sign the request with the wallet, but we don't send it to the Turnkey yet
|
|
514
524
|
// this is because we need to check if the subOrg exists first, and create one if it doesn't
|
|
515
525
|
// once we have the subOrg for the publicKey, we then can send the request to the Turnkey
|
|
516
|
-
const signedRequest = await
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
526
|
+
const signedRequest = await withTurnkeyErrorHandling(async () => {
|
|
527
|
+
return this.httpClient.stampStampLogin({
|
|
528
|
+
publicKey: generatedKeyPair,
|
|
529
|
+
organizationId: this.config.organizationId,
|
|
530
|
+
expirationSeconds,
|
|
531
|
+
}, StamperType.Wallet);
|
|
532
|
+
}, {
|
|
533
|
+
errorMessage: "Failed to create stamped request for wallet login",
|
|
534
|
+
errorCode: TurnkeyErrorCodes.WALLET_LOGIN_OR_SIGNUP_ERROR,
|
|
535
|
+
customMessageByMessages: {
|
|
536
|
+
"Failed to sign the message": {
|
|
537
|
+
message: "Wallet auth was cancelled by the user.",
|
|
538
|
+
code: TurnkeyErrorCodes.CONNECT_WALLET_CANCELLED,
|
|
539
|
+
},
|
|
540
|
+
},
|
|
541
|
+
});
|
|
521
542
|
if (!signedRequest) {
|
|
522
543
|
throw new TurnkeyError("Failed to create stamped request for wallet login", TurnkeyErrorCodes.BAD_RESPONSE);
|
|
523
544
|
}
|
|
@@ -595,10 +616,20 @@ class TurnkeyClient {
|
|
|
595
616
|
sessionKey,
|
|
596
617
|
});
|
|
597
618
|
return sessionToken;
|
|
598
|
-
}
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
619
|
+
}, {
|
|
620
|
+
errorCode: TurnkeyErrorCodes.WALLET_LOGIN_OR_SIGNUP_ERROR,
|
|
621
|
+
errorMessage: "Failed to log in or sign up with wallet",
|
|
622
|
+
catchFn: async () => {
|
|
623
|
+
if (generatedKeyPair) {
|
|
624
|
+
try {
|
|
625
|
+
await this.apiKeyStamper?.deleteKeyPair(generatedKeyPair);
|
|
626
|
+
}
|
|
627
|
+
catch (cleanupError) {
|
|
628
|
+
throw new TurnkeyError(`Failed to clean up generated key pair`, TurnkeyErrorCodes.KEY_PAIR_CLEANUP_ERROR, cleanupError);
|
|
629
|
+
}
|
|
630
|
+
}
|
|
631
|
+
},
|
|
632
|
+
});
|
|
602
633
|
};
|
|
603
634
|
/**
|
|
604
635
|
* Initializes the OTP process by sending an OTP code to the provided contact.
|
|
@@ -613,23 +644,22 @@ class TurnkeyClient {
|
|
|
613
644
|
* @throws {TurnkeyError} If there is an error during the OTP initialization process or if the maximum number of OTPs has been reached.
|
|
614
645
|
*/
|
|
615
646
|
this.initOtp = async (params) => {
|
|
616
|
-
|
|
647
|
+
return withTurnkeyErrorHandling(async () => {
|
|
617
648
|
const initOtpRes = await this.httpClient.proxyInitOtp(params);
|
|
618
649
|
if (!initOtpRes || !initOtpRes.otpId) {
|
|
619
650
|
throw new TurnkeyError("Failed to initialize OTP: otpId is missing", TurnkeyErrorCodes.INIT_OTP_ERROR);
|
|
620
651
|
}
|
|
621
652
|
return initOtpRes.otpId;
|
|
622
|
-
}
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
}
|
|
653
|
+
}, {
|
|
654
|
+
errorMessage: "Failed to initialize OTP",
|
|
655
|
+
errorCode: TurnkeyErrorCodes.INIT_OTP_ERROR,
|
|
656
|
+
customMessageByMessages: {
|
|
657
|
+
"Max number of OTPs have been initiated": {
|
|
658
|
+
message: "Maximum number of OTPs has been reached for this contact.",
|
|
659
|
+
code: TurnkeyErrorCodes.MAX_OTP_INITIATED_ERROR,
|
|
660
|
+
},
|
|
661
|
+
},
|
|
662
|
+
});
|
|
633
663
|
};
|
|
634
664
|
/**
|
|
635
665
|
* Verifies the OTP code sent to the user.
|
|
@@ -650,7 +680,7 @@ class TurnkeyClient {
|
|
|
650
680
|
*/
|
|
651
681
|
this.verifyOtp = async (params) => {
|
|
652
682
|
const { otpId, otpCode, contact, otpType } = params;
|
|
653
|
-
|
|
683
|
+
return withTurnkeyErrorHandling(async () => {
|
|
654
684
|
const verifyOtpRes = await this.httpClient.proxyVerifyOtp({
|
|
655
685
|
otpId: otpId,
|
|
656
686
|
otpCode: otpCode,
|
|
@@ -670,16 +700,16 @@ class TurnkeyClient {
|
|
|
670
700
|
subOrganizationId: subOrganizationId,
|
|
671
701
|
verificationToken: verifyOtpRes.verificationToken,
|
|
672
702
|
};
|
|
673
|
-
}
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
}
|
|
703
|
+
}, {
|
|
704
|
+
errorMessage: "Failed to verify OTP",
|
|
705
|
+
errorCode: TurnkeyErrorCodes.VERIFY_OTP_ERROR,
|
|
706
|
+
customMessageByMessages: {
|
|
707
|
+
"Invalid OTP code": {
|
|
708
|
+
message: "The provided OTP code is invalid.",
|
|
709
|
+
code: TurnkeyErrorCodes.INVALID_OTP_CODE,
|
|
710
|
+
},
|
|
711
|
+
},
|
|
712
|
+
});
|
|
683
713
|
};
|
|
684
714
|
/**
|
|
685
715
|
* Logs in a user using an OTP verification token.
|
|
@@ -699,7 +729,7 @@ class TurnkeyClient {
|
|
|
699
729
|
*/
|
|
700
730
|
this.loginWithOtp = async (params) => {
|
|
701
731
|
const { verificationToken, invalidateExisting = false, publicKey = await this.apiKeyStamper?.createKeyPair(), sessionKey = SessionKey.DefaultSessionkey, } = params;
|
|
702
|
-
|
|
732
|
+
return withTurnkeyErrorHandling(async () => {
|
|
703
733
|
const res = await this.httpClient.proxyOtpLogin({
|
|
704
734
|
verificationToken,
|
|
705
735
|
publicKey: publicKey,
|
|
@@ -717,21 +747,21 @@ class TurnkeyClient {
|
|
|
717
747
|
sessionKey,
|
|
718
748
|
});
|
|
719
749
|
return loginRes.session;
|
|
720
|
-
}
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
750
|
+
}, {
|
|
751
|
+
errorMessage: "Failed to log in with OTP",
|
|
752
|
+
errorCode: TurnkeyErrorCodes.OTP_LOGIN_ERROR,
|
|
753
|
+
catchFn: async () => {
|
|
754
|
+
// Clean up the generated key pair if it wasn't successfully used
|
|
755
|
+
if (publicKey) {
|
|
756
|
+
try {
|
|
757
|
+
await this.apiKeyStamper?.deleteKeyPair(publicKey);
|
|
758
|
+
}
|
|
759
|
+
catch (cleanupError) {
|
|
760
|
+
throw new TurnkeyError(`Failed to clean up generated key pair`, TurnkeyErrorCodes.KEY_PAIR_CLEANUP_ERROR, cleanupError);
|
|
761
|
+
}
|
|
731
762
|
}
|
|
732
|
-
}
|
|
733
|
-
|
|
734
|
-
}
|
|
763
|
+
},
|
|
764
|
+
});
|
|
735
765
|
};
|
|
736
766
|
/**
|
|
737
767
|
* Signs up a user using an OTP verification token.
|
|
@@ -762,8 +792,8 @@ class TurnkeyClient {
|
|
|
762
792
|
verificationToken,
|
|
763
793
|
},
|
|
764
794
|
});
|
|
765
|
-
|
|
766
|
-
|
|
795
|
+
return withTurnkeyErrorHandling(async () => {
|
|
796
|
+
const generatedKeyPair = await this.apiKeyStamper?.createKeyPair();
|
|
767
797
|
const res = await this.httpClient.proxySignup(signUpBody);
|
|
768
798
|
if (!res) {
|
|
769
799
|
throw new TurnkeyError(`Auth proxy OTP sign up failed`, TurnkeyErrorCodes.OTP_SIGNUP_ERROR);
|
|
@@ -774,12 +804,10 @@ class TurnkeyClient {
|
|
|
774
804
|
...(invalidateExisting && { invalidateExisting }),
|
|
775
805
|
...(sessionKey && { sessionKey }),
|
|
776
806
|
});
|
|
777
|
-
}
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
throw new TurnkeyError(`Failed to sign up with OTP`, TurnkeyErrorCodes.OTP_SIGNUP_ERROR, error);
|
|
782
|
-
}
|
|
807
|
+
}, {
|
|
808
|
+
errorCode: TurnkeyErrorCodes.OTP_SIGNUP_ERROR,
|
|
809
|
+
errorMessage: "Failed to sign up with OTP",
|
|
810
|
+
});
|
|
783
811
|
};
|
|
784
812
|
/**
|
|
785
813
|
* Completes the OTP authentication flow by verifying the OTP code and then either signing up or logging in the user.
|
|
@@ -803,7 +831,7 @@ class TurnkeyClient {
|
|
|
803
831
|
*/
|
|
804
832
|
this.completeOtp = async (params) => {
|
|
805
833
|
const { otpId, otpCode, contact, otpType, publicKey, invalidateExisting = false, sessionKey, createSubOrgParams, } = params;
|
|
806
|
-
|
|
834
|
+
return withTurnkeyErrorHandling(async () => {
|
|
807
835
|
const { subOrganizationId, verificationToken } = await this.verifyOtp({
|
|
808
836
|
otpId: otpId,
|
|
809
837
|
otpCode: otpCode,
|
|
@@ -833,12 +861,10 @@ class TurnkeyClient {
|
|
|
833
861
|
...(sessionKey && { sessionKey }),
|
|
834
862
|
});
|
|
835
863
|
}
|
|
836
|
-
}
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
throw new TurnkeyError(`Failed to complete OTP process`, TurnkeyErrorCodes.OTP_COMPLETION_ERROR, error);
|
|
841
|
-
}
|
|
864
|
+
}, {
|
|
865
|
+
errorMessage: "Failed to complete OTP process",
|
|
866
|
+
errorCode: TurnkeyErrorCodes.OTP_COMPLETION_ERROR,
|
|
867
|
+
});
|
|
842
868
|
};
|
|
843
869
|
/**
|
|
844
870
|
* Completes the OAuth authentication flow by either signing up or logging in the user, depending on whether a sub-organization already exists for the provided OIDC token.
|
|
@@ -860,7 +886,7 @@ class TurnkeyClient {
|
|
|
860
886
|
*/
|
|
861
887
|
this.completeOauth = async (params) => {
|
|
862
888
|
const { oidcToken, publicKey, createSubOrgParams, providerName = "OpenID Connect Provider" + Date.now(), sessionKey = SessionKey.DefaultSessionkey, invalidateExisting = false, } = params;
|
|
863
|
-
|
|
889
|
+
return withTurnkeyErrorHandling(async () => {
|
|
864
890
|
const accountRes = await this.httpClient.proxyGetAccount({
|
|
865
891
|
filterType: "OIDC_TOKEN",
|
|
866
892
|
filterValue: oidcToken,
|
|
@@ -887,12 +913,10 @@ class TurnkeyClient {
|
|
|
887
913
|
}),
|
|
888
914
|
});
|
|
889
915
|
}
|
|
890
|
-
}
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
throw new TurnkeyError(`Failed to handle Google OAuth login`, TurnkeyErrorCodes.OAUTH_LOGIN_ERROR, error);
|
|
895
|
-
}
|
|
916
|
+
}, {
|
|
917
|
+
errorMessage: "Failed to complete OAuth process",
|
|
918
|
+
errorCode: TurnkeyErrorCodes.OAUTH_LOGIN_ERROR,
|
|
919
|
+
});
|
|
896
920
|
};
|
|
897
921
|
/**
|
|
898
922
|
* Logs in a user using OAuth authentication.
|
|
@@ -911,10 +935,10 @@ class TurnkeyClient {
|
|
|
911
935
|
*/
|
|
912
936
|
this.loginWithOauth = async (params) => {
|
|
913
937
|
const { oidcToken, invalidateExisting = false, publicKey, sessionKey = SessionKey.DefaultSessionkey, } = params;
|
|
914
|
-
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
|
|
938
|
+
return withTurnkeyErrorHandling(async () => {
|
|
939
|
+
if (!publicKey) {
|
|
940
|
+
throw new TurnkeyError("Public key must be provided to log in with OAuth. Please create a key pair first.", TurnkeyErrorCodes.MISSING_PARAMS);
|
|
941
|
+
}
|
|
918
942
|
const loginRes = await this.httpClient.proxyOAuthLogin({
|
|
919
943
|
oidcToken,
|
|
920
944
|
publicKey,
|
|
@@ -931,21 +955,27 @@ class TurnkeyClient {
|
|
|
931
955
|
sessionKey,
|
|
932
956
|
});
|
|
933
957
|
return loginRes.session;
|
|
934
|
-
}
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
|
|
940
|
-
|
|
941
|
-
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
|
|
958
|
+
}, {
|
|
959
|
+
errorMessage: "Failed to complete OAuth login",
|
|
960
|
+
errorCode: TurnkeyErrorCodes.OAUTH_LOGIN_ERROR,
|
|
961
|
+
customMessageByMessages: {
|
|
962
|
+
"OAUTH disallowed": {
|
|
963
|
+
message: "OAuth is disabled on the dashboard for this organization.",
|
|
964
|
+
code: TurnkeyErrorCodes.AUTH_METHOD_NOT_ENABLED,
|
|
965
|
+
},
|
|
966
|
+
},
|
|
967
|
+
catchFn: async () => {
|
|
968
|
+
// Clean up the generated key pair if it wasn't successfully used
|
|
969
|
+
if (publicKey) {
|
|
970
|
+
try {
|
|
971
|
+
await this.apiKeyStamper?.deleteKeyPair(publicKey);
|
|
972
|
+
}
|
|
973
|
+
catch (cleanupError) {
|
|
974
|
+
throw new TurnkeyError(`Failed to clean up generated key pair`, TurnkeyErrorCodes.KEY_PAIR_CLEANUP_ERROR, cleanupError);
|
|
975
|
+
}
|
|
945
976
|
}
|
|
946
|
-
}
|
|
947
|
-
|
|
948
|
-
}
|
|
977
|
+
},
|
|
978
|
+
});
|
|
949
979
|
};
|
|
950
980
|
/**
|
|
951
981
|
* Signs up a user using OAuth authentication.
|
|
@@ -965,7 +995,7 @@ class TurnkeyClient {
|
|
|
965
995
|
*/
|
|
966
996
|
this.signUpWithOauth = async (params) => {
|
|
967
997
|
const { oidcToken, publicKey, providerName, createSubOrgParams } = params;
|
|
968
|
-
|
|
998
|
+
return withTurnkeyErrorHandling(async () => {
|
|
969
999
|
const signUpBody = buildSignUpBody({
|
|
970
1000
|
createSubOrgParams: {
|
|
971
1001
|
...createSubOrgParams,
|
|
@@ -985,12 +1015,10 @@ class TurnkeyClient {
|
|
|
985
1015
|
oidcToken,
|
|
986
1016
|
publicKey: publicKey,
|
|
987
1017
|
});
|
|
988
|
-
}
|
|
989
|
-
|
|
990
|
-
|
|
991
|
-
|
|
992
|
-
throw new TurnkeyError(`Failed to sign up with OAuth`, TurnkeyErrorCodes.OAUTH_SIGNUP_ERROR, error);
|
|
993
|
-
}
|
|
1018
|
+
}, {
|
|
1019
|
+
errorMessage: "Failed to sign up with OAuth",
|
|
1020
|
+
errorCode: TurnkeyErrorCodes.OAUTH_SIGNUP_ERROR,
|
|
1021
|
+
});
|
|
994
1022
|
};
|
|
995
1023
|
/**
|
|
996
1024
|
* Fetches all wallets for the current user, including both embedded and connected wallets.
|
|
@@ -1011,7 +1039,7 @@ class TurnkeyClient {
|
|
|
1011
1039
|
if (!session) {
|
|
1012
1040
|
throw new TurnkeyError("No active session found. Please log in first.", TurnkeyErrorCodes.NO_SESSION_FOUND);
|
|
1013
1041
|
}
|
|
1014
|
-
|
|
1042
|
+
return withTurnkeyErrorHandling(async () => {
|
|
1015
1043
|
const res = await this.httpClient.getWallets({ organizationId: session.organizationId }, stampWith);
|
|
1016
1044
|
if (!res || !res.wallets) {
|
|
1017
1045
|
throw new TurnkeyError("No wallets found in the response", TurnkeyErrorCodes.BAD_RESPONSE);
|
|
@@ -1035,7 +1063,8 @@ class TurnkeyClient {
|
|
|
1035
1063
|
const providers = await this.getWalletProviders();
|
|
1036
1064
|
const groupedProviders = new Map();
|
|
1037
1065
|
for (const provider of providers) {
|
|
1038
|
-
const walletId = provider.info?.name?.toLowerCase().replace(/\s+/g, "-") ||
|
|
1066
|
+
const walletId = provider.info?.name?.toLowerCase().replace(/\s+/g, "-") ||
|
|
1067
|
+
"unknown";
|
|
1039
1068
|
const group = groupedProviders.get(walletId) || [];
|
|
1040
1069
|
group.push(provider);
|
|
1041
1070
|
groupedProviders.set(walletId, group);
|
|
@@ -1061,12 +1090,10 @@ class TurnkeyClient {
|
|
|
1061
1090
|
return wallet;
|
|
1062
1091
|
}))).filter((wallet) => wallet.accounts.length > 0);
|
|
1063
1092
|
return [...embedded, ...connected];
|
|
1064
|
-
}
|
|
1065
|
-
|
|
1066
|
-
|
|
1067
|
-
|
|
1068
|
-
throw new TurnkeyError("Failed to fetch wallets", TurnkeyErrorCodes.FETCH_WALLETS_ERROR, error);
|
|
1069
|
-
}
|
|
1093
|
+
}, {
|
|
1094
|
+
errorMessage: "Failed to fetch wallets",
|
|
1095
|
+
errorCode: TurnkeyErrorCodes.FETCH_WALLETS_ERROR,
|
|
1096
|
+
});
|
|
1070
1097
|
};
|
|
1071
1098
|
/**
|
|
1072
1099
|
* Fetches all accounts for a specific wallet, including both embedded and connected wallet accounts.
|
|
@@ -1090,58 +1117,65 @@ class TurnkeyClient {
|
|
|
1090
1117
|
if (!session) {
|
|
1091
1118
|
throw new TurnkeyError("No active session found. Please log in first.", TurnkeyErrorCodes.NO_SESSION_FOUND);
|
|
1092
1119
|
}
|
|
1093
|
-
|
|
1094
|
-
|
|
1095
|
-
|
|
1096
|
-
|
|
1097
|
-
|
|
1098
|
-
organizationId: session.organizationId,
|
|
1099
|
-
paginationOptions: paginationOptions || { limit: "100" },
|
|
1100
|
-
}, stampWith);
|
|
1101
|
-
if (!res || !res.accounts) {
|
|
1102
|
-
throw new TurnkeyError("No wallet accounts found in the response", TurnkeyErrorCodes.BAD_RESPONSE);
|
|
1103
|
-
}
|
|
1104
|
-
for (const account of res.accounts) {
|
|
1105
|
-
embedded.push({
|
|
1106
|
-
...account,
|
|
1107
|
-
source: WalletSource.Embedded,
|
|
1108
|
-
});
|
|
1109
|
-
}
|
|
1110
|
-
return embedded;
|
|
1111
|
-
}
|
|
1112
|
-
// this is an external wallet so we fetch accounts from the connected wallet provider
|
|
1113
|
-
// if wallet connecting is disabled we return only embedded wallets
|
|
1114
|
-
// we should never reach this point if wallet connecting is disabled
|
|
1115
|
-
if (!this.walletManager?.connector)
|
|
1116
|
-
return [];
|
|
1117
|
-
const connected = [];
|
|
1118
|
-
const providers = walletProviders ?? (await this.getWalletProviders());
|
|
1119
|
-
const matching = providers.filter((p) => p.info?.name?.toLowerCase().replace(/\s+/g, "-") === wallet.walletId &&
|
|
1120
|
-
p.connectedAddresses.length > 0);
|
|
1121
|
-
for (const provider of matching) {
|
|
1122
|
-
const timestamp = toExternalTimestamp();
|
|
1123
|
-
for (const address of provider.connectedAddresses) {
|
|
1124
|
-
const account = {
|
|
1125
|
-
walletAccountId: `${wallet.walletId}-${provider.interfaceType}-${address}`,
|
|
1126
|
-
organizationId: session.organizationId,
|
|
1120
|
+
return withTurnkeyErrorHandling(async () => {
|
|
1121
|
+
// this is an embedded wallet so we fetch accounts from Turnkey
|
|
1122
|
+
if (wallet.source === WalletSource.Embedded) {
|
|
1123
|
+
const embedded = [];
|
|
1124
|
+
const res = await this.httpClient.getWalletAccounts({
|
|
1127
1125
|
walletId: wallet.walletId,
|
|
1128
|
-
|
|
1129
|
-
|
|
1130
|
-
|
|
1131
|
-
|
|
1132
|
-
|
|
1133
|
-
|
|
1134
|
-
|
|
1135
|
-
|
|
1136
|
-
|
|
1137
|
-
|
|
1138
|
-
|
|
1139
|
-
|
|
1140
|
-
|
|
1141
|
-
connected.push(account);
|
|
1126
|
+
organizationId: session.organizationId,
|
|
1127
|
+
paginationOptions: paginationOptions || { limit: "100" },
|
|
1128
|
+
}, stampWith);
|
|
1129
|
+
if (!res || !res.accounts) {
|
|
1130
|
+
throw new TurnkeyError("No wallet accounts found in the response", TurnkeyErrorCodes.BAD_RESPONSE);
|
|
1131
|
+
}
|
|
1132
|
+
for (const account of res.accounts) {
|
|
1133
|
+
embedded.push({
|
|
1134
|
+
...account,
|
|
1135
|
+
source: WalletSource.Embedded,
|
|
1136
|
+
});
|
|
1137
|
+
}
|
|
1138
|
+
return embedded;
|
|
1142
1139
|
}
|
|
1143
|
-
|
|
1144
|
-
|
|
1140
|
+
// this is an external wallet so we fetch accounts from the connected wallet provider
|
|
1141
|
+
// if wallet connecting is disabled we return only embedded wallets
|
|
1142
|
+
// we should never reach this point if wallet connecting is disabled
|
|
1143
|
+
if (!this.walletManager?.connector)
|
|
1144
|
+
return [];
|
|
1145
|
+
const connected = [];
|
|
1146
|
+
const providers = walletProviders ?? (await this.getWalletProviders());
|
|
1147
|
+
const matching = providers.filter((p) => p.info?.name?.toLowerCase().replace(/\s+/g, "-") ===
|
|
1148
|
+
wallet.walletId && p.connectedAddresses.length > 0);
|
|
1149
|
+
for (const provider of matching) {
|
|
1150
|
+
const timestamp = toExternalTimestamp();
|
|
1151
|
+
for (const address of provider.connectedAddresses) {
|
|
1152
|
+
const account = {
|
|
1153
|
+
walletAccountId: `${wallet.walletId}-${provider.interfaceType}-${address}`,
|
|
1154
|
+
organizationId: session.organizationId,
|
|
1155
|
+
walletId: wallet.walletId,
|
|
1156
|
+
curve: isEthereumWallet(provider)
|
|
1157
|
+
? Curve.SECP256K1
|
|
1158
|
+
: Curve.ED25519,
|
|
1159
|
+
pathFormat: "PATH_FORMAT_BIP32",
|
|
1160
|
+
path: WalletSource.Connected,
|
|
1161
|
+
source: WalletSource.Connected,
|
|
1162
|
+
addressFormat: isEthereumWallet(provider)
|
|
1163
|
+
? "ADDRESS_FORMAT_ETHEREUM"
|
|
1164
|
+
: "ADDRESS_FORMAT_SOLANA",
|
|
1165
|
+
address,
|
|
1166
|
+
createdAt: timestamp,
|
|
1167
|
+
updatedAt: timestamp,
|
|
1168
|
+
...getWalletAccountMethods(this.walletManager.connector.sign.bind(this.walletManager.connector), provider),
|
|
1169
|
+
...(isSolanaWallet(provider) && { publicKey: address }),
|
|
1170
|
+
};
|
|
1171
|
+
connected.push(account);
|
|
1172
|
+
}
|
|
1173
|
+
}
|
|
1174
|
+
return connected;
|
|
1175
|
+
}, {
|
|
1176
|
+
errorMessage: "Failed to fetch wallet accounts",
|
|
1177
|
+
errorCode: TurnkeyErrorCodes.FETCH_WALLET_ACCOUNTS_ERROR,
|
|
1178
|
+
});
|
|
1145
1179
|
};
|
|
1146
1180
|
/**
|
|
1147
1181
|
* Signs a message using the specified wallet account.
|
|
@@ -1175,7 +1209,7 @@ class TurnkeyClient {
|
|
|
1175
1209
|
const { message, walletAccount, stampWith, addEthereumPrefix } = params;
|
|
1176
1210
|
const hashFunction = params.hashFunction || getHashFunction(walletAccount.addressFormat);
|
|
1177
1211
|
const payloadEncoding = params.encoding || getEncodingType(walletAccount.addressFormat);
|
|
1178
|
-
|
|
1212
|
+
return withTurnkeyErrorHandling(async () => {
|
|
1179
1213
|
const isEthereum = walletAccount.addressFormat === "ADDRESS_FORMAT_ETHEREUM";
|
|
1180
1214
|
if (walletAccount.source === WalletSource.Connected) {
|
|
1181
1215
|
// this is a connected wallet
|
|
@@ -1207,12 +1241,10 @@ class TurnkeyClient {
|
|
|
1207
1241
|
}
|
|
1208
1242
|
return response.activity.result
|
|
1209
1243
|
.signRawPayloadResult;
|
|
1210
|
-
}
|
|
1211
|
-
|
|
1212
|
-
|
|
1213
|
-
|
|
1214
|
-
throw new TurnkeyError(`Failed to sign message - ${error?.message ? error.message : "Unknown error"}`, TurnkeyErrorCodes.SIGN_MESSAGE_ERROR);
|
|
1215
|
-
}
|
|
1244
|
+
}, {
|
|
1245
|
+
errorMessage: "Failed to sign message",
|
|
1246
|
+
errorCode: TurnkeyErrorCodes.SIGN_MESSAGE_ERROR,
|
|
1247
|
+
});
|
|
1216
1248
|
};
|
|
1217
1249
|
/**
|
|
1218
1250
|
* Signs a transaction using the specified wallet account.
|
|
@@ -1232,7 +1264,7 @@ class TurnkeyClient {
|
|
|
1232
1264
|
*/
|
|
1233
1265
|
this.signTransaction = async (params) => {
|
|
1234
1266
|
const { walletAccount, unsignedTransaction, transactionType, stampWith } = params;
|
|
1235
|
-
|
|
1267
|
+
return withTurnkeyErrorHandling(async () => {
|
|
1236
1268
|
if (walletAccount.source === WalletSource.Connected) {
|
|
1237
1269
|
// this is a connected wallet account
|
|
1238
1270
|
if (!walletAccount.signTransaction) {
|
|
@@ -1251,12 +1283,10 @@ class TurnkeyClient {
|
|
|
1251
1283
|
type: transactionType,
|
|
1252
1284
|
}, stampWith);
|
|
1253
1285
|
return signTransaction.signedTransaction;
|
|
1254
|
-
}
|
|
1255
|
-
|
|
1256
|
-
|
|
1257
|
-
|
|
1258
|
-
throw new TurnkeyError(`Failed to sign transaction`, TurnkeyErrorCodes.SIGN_TRANSACTION_ERROR, error);
|
|
1259
|
-
}
|
|
1286
|
+
}, {
|
|
1287
|
+
errorMessage: "Failed to sign transaction",
|
|
1288
|
+
errorCode: TurnkeyErrorCodes.SIGN_TRANSACTION_ERROR,
|
|
1289
|
+
});
|
|
1260
1290
|
};
|
|
1261
1291
|
/**
|
|
1262
1292
|
* Signs and broadcasts a transaction using the specified wallet account.
|
|
@@ -1280,7 +1310,7 @@ class TurnkeyClient {
|
|
|
1280
1310
|
*/
|
|
1281
1311
|
this.signAndSendTransaction = async (params) => {
|
|
1282
1312
|
const { walletAccount, unsignedTransaction, transactionType, rpcUrl, stampWith, } = params;
|
|
1283
|
-
|
|
1313
|
+
return withTurnkeyErrorHandling(async () => {
|
|
1284
1314
|
if (walletAccount.source === WalletSource.Connected) {
|
|
1285
1315
|
// this is a connected wallet account
|
|
1286
1316
|
switch (transactionType) {
|
|
@@ -1324,12 +1354,10 @@ class TurnkeyClient {
|
|
|
1324
1354
|
transactionType,
|
|
1325
1355
|
});
|
|
1326
1356
|
return txHash;
|
|
1327
|
-
}
|
|
1328
|
-
|
|
1329
|
-
|
|
1330
|
-
|
|
1331
|
-
throw new TurnkeyError(`Failed to sign and send transaction`, TurnkeyErrorCodes.SIGN_AND_SEND_TRANSACTION_ERROR, error);
|
|
1332
|
-
}
|
|
1357
|
+
}, {
|
|
1358
|
+
errorMessage: "Failed to sign and send transaction",
|
|
1359
|
+
errorCode: TurnkeyErrorCodes.SIGN_AND_SEND_TRANSACTION_ERROR,
|
|
1360
|
+
});
|
|
1333
1361
|
};
|
|
1334
1362
|
/**
|
|
1335
1363
|
* Fetches the user details for the current session or a specified user.
|
|
@@ -1357,18 +1385,16 @@ class TurnkeyClient {
|
|
|
1357
1385
|
throw new TurnkeyError("User ID must be provided to fetch user", TurnkeyErrorCodes.INVALID_REQUEST);
|
|
1358
1386
|
}
|
|
1359
1387
|
const organizationId = params?.organizationId || session.organizationId;
|
|
1360
|
-
|
|
1388
|
+
return withTurnkeyErrorHandling(async () => {
|
|
1361
1389
|
const userResponse = await this.httpClient.getUser({ organizationId, userId }, stampWith);
|
|
1362
1390
|
if (!userResponse || !userResponse.user) {
|
|
1363
1391
|
throw new TurnkeyError("No user found in the response", TurnkeyErrorCodes.BAD_RESPONSE);
|
|
1364
1392
|
}
|
|
1365
1393
|
return userResponse.user;
|
|
1366
|
-
}
|
|
1367
|
-
|
|
1368
|
-
|
|
1369
|
-
|
|
1370
|
-
throw new TurnkeyError(`Failed to fetch user`, TurnkeyErrorCodes.FETCH_USER_ERROR, error);
|
|
1371
|
-
}
|
|
1394
|
+
}, {
|
|
1395
|
+
errorMessage: "Failed to fetch user",
|
|
1396
|
+
errorCode: TurnkeyErrorCodes.FETCH_USER_ERROR,
|
|
1397
|
+
});
|
|
1372
1398
|
};
|
|
1373
1399
|
/**
|
|
1374
1400
|
* Updates the user's email address.
|
|
@@ -1393,7 +1419,7 @@ class TurnkeyClient {
|
|
|
1393
1419
|
throw new TurnkeyError("No active session found. Please log in first.", TurnkeyErrorCodes.NO_SESSION_FOUND);
|
|
1394
1420
|
}
|
|
1395
1421
|
const userId = params?.userId || session.userId;
|
|
1396
|
-
|
|
1422
|
+
return withTurnkeyErrorHandling(async () => {
|
|
1397
1423
|
const existingUser = await this.httpClient.proxyGetAccount({
|
|
1398
1424
|
filterType: FilterType.Email,
|
|
1399
1425
|
filterValue: email,
|
|
@@ -1410,12 +1436,10 @@ class TurnkeyClient {
|
|
|
1410
1436
|
throw new TurnkeyError("No user ID found in the update user email response", TurnkeyErrorCodes.BAD_RESPONSE);
|
|
1411
1437
|
}
|
|
1412
1438
|
return res.userId;
|
|
1413
|
-
}
|
|
1414
|
-
|
|
1415
|
-
|
|
1416
|
-
|
|
1417
|
-
throw new TurnkeyError(`Failed to update user email`, TurnkeyErrorCodes.UPDATE_USER_EMAIL_ERROR, error);
|
|
1418
|
-
}
|
|
1439
|
+
}, {
|
|
1440
|
+
errorMessage: "Failed to update user email",
|
|
1441
|
+
errorCode: TurnkeyErrorCodes.UPDATE_USER_EMAIL_ERROR,
|
|
1442
|
+
});
|
|
1419
1443
|
};
|
|
1420
1444
|
/**
|
|
1421
1445
|
* Removes the user's email address.
|
|
@@ -1436,15 +1460,20 @@ class TurnkeyClient {
|
|
|
1436
1460
|
if (!session) {
|
|
1437
1461
|
throw new TurnkeyError("No active session found. Please log in first.", TurnkeyErrorCodes.NO_SESSION_FOUND);
|
|
1438
1462
|
}
|
|
1439
|
-
|
|
1440
|
-
|
|
1441
|
-
|
|
1442
|
-
|
|
1443
|
-
|
|
1444
|
-
|
|
1445
|
-
|
|
1446
|
-
|
|
1447
|
-
|
|
1463
|
+
return withTurnkeyErrorHandling(async () => {
|
|
1464
|
+
const userId = params?.userId || session.userId;
|
|
1465
|
+
const res = await this.httpClient.updateUserEmail({
|
|
1466
|
+
userId: userId,
|
|
1467
|
+
userEmail: "",
|
|
1468
|
+
}, stampWith);
|
|
1469
|
+
if (!res || !res.userId) {
|
|
1470
|
+
throw new TurnkeyError("No user ID found in the remove user email response", TurnkeyErrorCodes.BAD_RESPONSE);
|
|
1471
|
+
}
|
|
1472
|
+
return res.userId;
|
|
1473
|
+
}, {
|
|
1474
|
+
errorMessage: "Failed to remove user email",
|
|
1475
|
+
errorCode: TurnkeyErrorCodes.UPDATE_USER_EMAIL_ERROR,
|
|
1476
|
+
});
|
|
1448
1477
|
};
|
|
1449
1478
|
/**
|
|
1450
1479
|
* Updates the user's phone number.
|
|
@@ -1469,7 +1498,7 @@ class TurnkeyClient {
|
|
|
1469
1498
|
throw new TurnkeyError("No active session found. Please log in first.", TurnkeyErrorCodes.NO_SESSION_FOUND);
|
|
1470
1499
|
}
|
|
1471
1500
|
const userId = params?.userId || session.userId;
|
|
1472
|
-
|
|
1501
|
+
return withTurnkeyErrorHandling(async () => {
|
|
1473
1502
|
const res = await this.httpClient.updateUserPhoneNumber({
|
|
1474
1503
|
userId,
|
|
1475
1504
|
userPhoneNumber: phoneNumber,
|
|
@@ -1479,12 +1508,10 @@ class TurnkeyClient {
|
|
|
1479
1508
|
throw new TurnkeyError("Failed to update user phone number", TurnkeyErrorCodes.UPDATE_USER_PHONE_NUMBER_ERROR);
|
|
1480
1509
|
}
|
|
1481
1510
|
return res.userId;
|
|
1482
|
-
}
|
|
1483
|
-
|
|
1484
|
-
|
|
1485
|
-
|
|
1486
|
-
throw new TurnkeyError(`Failed to update user phone number`, TurnkeyErrorCodes.UPDATE_USER_PHONE_NUMBER_ERROR, error);
|
|
1487
|
-
}
|
|
1511
|
+
}, {
|
|
1512
|
+
errorMessage: "Failed to update user phone number",
|
|
1513
|
+
errorCode: TurnkeyErrorCodes.UPDATE_USER_PHONE_NUMBER_ERROR,
|
|
1514
|
+
});
|
|
1488
1515
|
};
|
|
1489
1516
|
/**
|
|
1490
1517
|
* Removes the user's phone number.
|
|
@@ -1506,14 +1533,19 @@ class TurnkeyClient {
|
|
|
1506
1533
|
throw new TurnkeyError("No active session found. Please log in first.", TurnkeyErrorCodes.NO_SESSION_FOUND);
|
|
1507
1534
|
}
|
|
1508
1535
|
const userId = params?.userId || session.userId;
|
|
1509
|
-
|
|
1510
|
-
|
|
1511
|
-
|
|
1512
|
-
|
|
1513
|
-
|
|
1514
|
-
|
|
1515
|
-
|
|
1516
|
-
|
|
1536
|
+
return withTurnkeyErrorHandling(async () => {
|
|
1537
|
+
const res = await this.httpClient.updateUserPhoneNumber({
|
|
1538
|
+
userId,
|
|
1539
|
+
userPhoneNumber: "",
|
|
1540
|
+
}, stampWith);
|
|
1541
|
+
if (!res || !res.userId) {
|
|
1542
|
+
throw new TurnkeyError("Failed to remove user phone number", TurnkeyErrorCodes.UPDATE_USER_PHONE_NUMBER_ERROR);
|
|
1543
|
+
}
|
|
1544
|
+
return res.userId;
|
|
1545
|
+
}, {
|
|
1546
|
+
errorMessage: "Failed to remove user phone number",
|
|
1547
|
+
errorCode: TurnkeyErrorCodes.UPDATE_USER_PHONE_NUMBER_ERROR,
|
|
1548
|
+
});
|
|
1517
1549
|
};
|
|
1518
1550
|
/**
|
|
1519
1551
|
* Updates the user's name.
|
|
@@ -1537,7 +1569,7 @@ class TurnkeyClient {
|
|
|
1537
1569
|
throw new TurnkeyError("No active session found. Please log in first.", TurnkeyErrorCodes.NO_SESSION_FOUND);
|
|
1538
1570
|
}
|
|
1539
1571
|
const userId = params?.userId || session.userId;
|
|
1540
|
-
|
|
1572
|
+
return withTurnkeyErrorHandling(async () => {
|
|
1541
1573
|
const res = await this.httpClient.updateUserName({
|
|
1542
1574
|
userId,
|
|
1543
1575
|
userName,
|
|
@@ -1546,12 +1578,10 @@ class TurnkeyClient {
|
|
|
1546
1578
|
throw new TurnkeyError("No user ID found in the update user name response", TurnkeyErrorCodes.BAD_RESPONSE);
|
|
1547
1579
|
}
|
|
1548
1580
|
return res.userId;
|
|
1549
|
-
}
|
|
1550
|
-
|
|
1551
|
-
|
|
1552
|
-
|
|
1553
|
-
throw new TurnkeyError(`Failed to update user name`, TurnkeyErrorCodes.UPDATE_USER_NAME_ERROR, error);
|
|
1554
|
-
}
|
|
1581
|
+
}, {
|
|
1582
|
+
errorMessage: "Failed to update user name",
|
|
1583
|
+
errorCode: TurnkeyErrorCodes.UPDATE_USER_NAME_ERROR,
|
|
1584
|
+
});
|
|
1555
1585
|
};
|
|
1556
1586
|
/**
|
|
1557
1587
|
* Adds an OAuth provider to the user.
|
|
@@ -1576,7 +1606,7 @@ class TurnkeyClient {
|
|
|
1576
1606
|
if (!session) {
|
|
1577
1607
|
throw new TurnkeyError("No active session found. Please log in first.", TurnkeyErrorCodes.NO_SESSION_FOUND);
|
|
1578
1608
|
}
|
|
1579
|
-
|
|
1609
|
+
return withTurnkeyErrorHandling(async () => {
|
|
1580
1610
|
const accountRes = await this.httpClient.proxyGetAccount({
|
|
1581
1611
|
filterType: "OIDC_TOKEN",
|
|
1582
1612
|
filterValue: oidcToken,
|
|
@@ -1620,12 +1650,10 @@ class TurnkeyClient {
|
|
|
1620
1650
|
throw new TurnkeyError("Failed to create OAuth provider", TurnkeyErrorCodes.ADD_OAUTH_PROVIDER_ERROR);
|
|
1621
1651
|
}
|
|
1622
1652
|
return createProviderRes?.providerIds || [];
|
|
1623
|
-
}
|
|
1624
|
-
|
|
1625
|
-
|
|
1626
|
-
|
|
1627
|
-
throw new TurnkeyError(`Failed to fetch account for OAuth provider`, TurnkeyErrorCodes.ACCOUNT_FETCH_ERROR, error);
|
|
1628
|
-
}
|
|
1653
|
+
}, {
|
|
1654
|
+
errorMessage: "Failed to add OAuth provider",
|
|
1655
|
+
errorCode: TurnkeyErrorCodes.ADD_OAUTH_PROVIDER_ERROR,
|
|
1656
|
+
});
|
|
1629
1657
|
};
|
|
1630
1658
|
/**
|
|
1631
1659
|
* Removes a list of OAuth providers from the user.
|
|
@@ -1649,14 +1677,19 @@ class TurnkeyClient {
|
|
|
1649
1677
|
throw new TurnkeyError("No active session found. Please log in first.", TurnkeyErrorCodes.NO_SESSION_FOUND);
|
|
1650
1678
|
}
|
|
1651
1679
|
const userId = params?.userId || session.userId;
|
|
1652
|
-
|
|
1653
|
-
|
|
1654
|
-
|
|
1655
|
-
|
|
1656
|
-
|
|
1657
|
-
|
|
1658
|
-
|
|
1659
|
-
|
|
1680
|
+
return withTurnkeyErrorHandling(async () => {
|
|
1681
|
+
const res = await this.httpClient.deleteOauthProviders({
|
|
1682
|
+
userId,
|
|
1683
|
+
providerIds,
|
|
1684
|
+
}, stampWith);
|
|
1685
|
+
if (!res) {
|
|
1686
|
+
throw new TurnkeyError("Failed to remove OAuth provider", TurnkeyErrorCodes.REMOVE_OAUTH_PROVIDER_ERROR);
|
|
1687
|
+
}
|
|
1688
|
+
return res.providerIds;
|
|
1689
|
+
}, {
|
|
1690
|
+
errorMessage: "Failed to remove OAuth provider",
|
|
1691
|
+
errorCode: TurnkeyErrorCodes.REMOVE_OAUTH_PROVIDER_ERROR,
|
|
1692
|
+
});
|
|
1660
1693
|
};
|
|
1661
1694
|
/**
|
|
1662
1695
|
* Adds a new passkey authenticator for the user.
|
|
@@ -1678,7 +1711,7 @@ class TurnkeyClient {
|
|
|
1678
1711
|
const { stampWith } = params || {};
|
|
1679
1712
|
const name = params?.name || `Turnkey Passkey-${Date.now()}`;
|
|
1680
1713
|
const displayName = params?.displayName || name;
|
|
1681
|
-
|
|
1714
|
+
return withTurnkeyErrorHandling(async () => {
|
|
1682
1715
|
const session = await this.storageManager.getActiveSession();
|
|
1683
1716
|
if (!session) {
|
|
1684
1717
|
throw new TurnkeyError("No active session found. Please log in first.", TurnkeyErrorCodes.NO_SESSION_FOUND);
|
|
@@ -1703,12 +1736,10 @@ class TurnkeyClient {
|
|
|
1703
1736
|
],
|
|
1704
1737
|
}, stampWith);
|
|
1705
1738
|
return res?.authenticatorIds || [];
|
|
1706
|
-
}
|
|
1707
|
-
|
|
1708
|
-
|
|
1709
|
-
|
|
1710
|
-
throw new TurnkeyError(`Failed to add passkey`, TurnkeyErrorCodes.ADD_PASSKEY_ERROR, error);
|
|
1711
|
-
}
|
|
1739
|
+
}, {
|
|
1740
|
+
errorMessage: "Failed to add passkey",
|
|
1741
|
+
errorCode: TurnkeyErrorCodes.ADD_PASSKEY_ERROR,
|
|
1742
|
+
});
|
|
1712
1743
|
};
|
|
1713
1744
|
/**
|
|
1714
1745
|
* Removes passkeys (authenticator) from the user.
|
|
@@ -1732,14 +1763,19 @@ class TurnkeyClient {
|
|
|
1732
1763
|
throw new TurnkeyError("No active session found. Please log in first.", TurnkeyErrorCodes.NO_SESSION_FOUND);
|
|
1733
1764
|
}
|
|
1734
1765
|
const userId = params?.userId || session.userId;
|
|
1735
|
-
|
|
1736
|
-
|
|
1737
|
-
|
|
1738
|
-
|
|
1739
|
-
|
|
1740
|
-
|
|
1741
|
-
|
|
1742
|
-
|
|
1766
|
+
return withTurnkeyErrorHandling(async () => {
|
|
1767
|
+
const res = await this.httpClient.deleteAuthenticators({
|
|
1768
|
+
userId,
|
|
1769
|
+
authenticatorIds,
|
|
1770
|
+
}, stampWith);
|
|
1771
|
+
if (!res) {
|
|
1772
|
+
throw new TurnkeyError("No response found in the remove passkey response", TurnkeyErrorCodes.REMOVE_PASSKEY_ERROR);
|
|
1773
|
+
}
|
|
1774
|
+
return res.authenticatorIds;
|
|
1775
|
+
}, {
|
|
1776
|
+
errorMessage: "Failed to remove passkey",
|
|
1777
|
+
errorCode: TurnkeyErrorCodes.REMOVE_PASSKEY_ERROR,
|
|
1778
|
+
});
|
|
1743
1779
|
};
|
|
1744
1780
|
/**
|
|
1745
1781
|
* Creates a new wallet for sub-organization.
|
|
@@ -1778,7 +1814,7 @@ class TurnkeyClient {
|
|
|
1778
1814
|
...DEFAULT_SOLANA_ACCOUNTS,
|
|
1779
1815
|
];
|
|
1780
1816
|
}
|
|
1781
|
-
|
|
1817
|
+
return withTurnkeyErrorHandling(async () => {
|
|
1782
1818
|
const res = await this.httpClient.createWallet({
|
|
1783
1819
|
organizationId: organizationId || session.organizationId,
|
|
1784
1820
|
walletName,
|
|
@@ -1789,12 +1825,10 @@ class TurnkeyClient {
|
|
|
1789
1825
|
throw new TurnkeyError("No wallet found in the create wallet response", TurnkeyErrorCodes.BAD_RESPONSE);
|
|
1790
1826
|
}
|
|
1791
1827
|
return res.walletId;
|
|
1792
|
-
}
|
|
1793
|
-
|
|
1794
|
-
|
|
1795
|
-
|
|
1796
|
-
throw new TurnkeyError(`Failed to create wallet`, TurnkeyErrorCodes.CREATE_WALLET_ERROR, error);
|
|
1797
|
-
}
|
|
1828
|
+
}, {
|
|
1829
|
+
errorMessage: "Failed to create wallet",
|
|
1830
|
+
errorCode: TurnkeyErrorCodes.CREATE_WALLET_ERROR,
|
|
1831
|
+
});
|
|
1798
1832
|
};
|
|
1799
1833
|
/**
|
|
1800
1834
|
* Creates new accounts in the specified wallet.
|
|
@@ -1819,7 +1853,7 @@ class TurnkeyClient {
|
|
|
1819
1853
|
if (!session) {
|
|
1820
1854
|
throw new TurnkeyError("No active session found. Please log in first.", TurnkeyErrorCodes.NO_SESSION_FOUND);
|
|
1821
1855
|
}
|
|
1822
|
-
|
|
1856
|
+
return withTurnkeyErrorHandling(async () => {
|
|
1823
1857
|
let walletAccounts = [];
|
|
1824
1858
|
if (accounts && !isWalletAccountArray(accounts)) {
|
|
1825
1859
|
// Query existing wallet accounts to avoid duplicates
|
|
@@ -1845,12 +1879,10 @@ class TurnkeyClient {
|
|
|
1845
1879
|
throw new TurnkeyError("No account found in the create wallet account response", TurnkeyErrorCodes.BAD_RESPONSE);
|
|
1846
1880
|
}
|
|
1847
1881
|
return res.addresses;
|
|
1848
|
-
}
|
|
1849
|
-
|
|
1850
|
-
|
|
1851
|
-
|
|
1852
|
-
throw new TurnkeyError(`Failed to create wallet account`, TurnkeyErrorCodes.CREATE_WALLET_ACCOUNT_ERROR, error);
|
|
1853
|
-
}
|
|
1882
|
+
}, {
|
|
1883
|
+
errorMessage: "Failed to create wallet account",
|
|
1884
|
+
errorCode: TurnkeyErrorCodes.CREATE_WALLET_ACCOUNT_ERROR,
|
|
1885
|
+
});
|
|
1854
1886
|
};
|
|
1855
1887
|
/**
|
|
1856
1888
|
* Exports a wallet as an encrypted bundle.
|
|
@@ -1875,7 +1907,7 @@ class TurnkeyClient {
|
|
|
1875
1907
|
if (!session) {
|
|
1876
1908
|
throw new TurnkeyError("No active session found. Please log in first.", TurnkeyErrorCodes.NO_SESSION_FOUND);
|
|
1877
1909
|
}
|
|
1878
|
-
|
|
1910
|
+
return withTurnkeyErrorHandling(async () => {
|
|
1879
1911
|
const res = await this.httpClient.exportWallet({
|
|
1880
1912
|
walletId,
|
|
1881
1913
|
targetPublicKey,
|
|
@@ -1885,12 +1917,85 @@ class TurnkeyClient {
|
|
|
1885
1917
|
throw new TurnkeyError("No export bundle found in the response", TurnkeyErrorCodes.BAD_RESPONSE);
|
|
1886
1918
|
}
|
|
1887
1919
|
return res.exportBundle;
|
|
1920
|
+
}, {
|
|
1921
|
+
errorMessage: "Failed to export wallet",
|
|
1922
|
+
errorCode: TurnkeyErrorCodes.EXPORT_WALLET_ERROR,
|
|
1923
|
+
});
|
|
1924
|
+
};
|
|
1925
|
+
/**
|
|
1926
|
+
* Exports a private key as an encrypted bundle.
|
|
1927
|
+
*
|
|
1928
|
+
* - This function exports the specified private key as an encrypted bundle, suitable for backup or transfer.
|
|
1929
|
+
* - The exported bundle contains the private key's key material, encrypted to the provided target public key.
|
|
1930
|
+
* - If a targetPublicKey is provided, the bundle will be encrypted to that public key; otherwise, an error will be thrown.
|
|
1931
|
+
* - If an organizationId is provided, the private key will be exported under that sub-organization; otherwise, the current session's organizationId is used.
|
|
1932
|
+
* - Optionally allows stamping the request with a specific stamper (StamperType.Passkey, StamperType.ApiKey, or StamperType.Wallet).
|
|
1933
|
+
*
|
|
1934
|
+
* @param params.privateKeyId - ID of the private key to export.
|
|
1935
|
+
* @param params.targetPublicKey - public key to encrypt the bundle to (required).
|
|
1936
|
+
* @param params.organizationId - organization ID to export the private key under a specific sub
|
|
1937
|
+
* @param params.stampWith - parameter to stamp the request with a specific stamper (StamperType.Passkey, StamperType.ApiKey, or StamperType.Wallet).
|
|
1938
|
+
* @returns A promise that resolves to an `ExportBundle` object containing the encrypted private key and metadata.
|
|
1939
|
+
* @throws {TurnkeyError} If there is no active session, if the targetPublicKey is missing, or if there is an error exporting the private key.
|
|
1940
|
+
*/
|
|
1941
|
+
this.exportPrivateKey = async (params) => {
|
|
1942
|
+
const { privateKeyId, targetPublicKey, stampWith, organizationId } = params;
|
|
1943
|
+
const session = await this.storageManager.getActiveSession();
|
|
1944
|
+
if (!session) {
|
|
1945
|
+
throw new TurnkeyError("No active session found. Please log in first.", TurnkeyErrorCodes.NO_SESSION_FOUND);
|
|
1888
1946
|
}
|
|
1889
|
-
|
|
1890
|
-
|
|
1891
|
-
|
|
1892
|
-
|
|
1947
|
+
return withTurnkeyErrorHandling(async () => {
|
|
1948
|
+
const res = await this.httpClient.exportPrivateKey({
|
|
1949
|
+
privateKeyId,
|
|
1950
|
+
targetPublicKey,
|
|
1951
|
+
organizationId: organizationId || session.organizationId,
|
|
1952
|
+
}, stampWith);
|
|
1953
|
+
if (!res.exportBundle) {
|
|
1954
|
+
throw new TurnkeyError("No export bundle found in the response", TurnkeyErrorCodes.BAD_RESPONSE);
|
|
1955
|
+
}
|
|
1956
|
+
return res.exportBundle;
|
|
1957
|
+
}, {
|
|
1958
|
+
errorMessage: "Failed to export private key",
|
|
1959
|
+
errorCode: TurnkeyErrorCodes.EXPORT_PRIVATE_KEY_ERROR,
|
|
1960
|
+
});
|
|
1961
|
+
};
|
|
1962
|
+
/**
|
|
1963
|
+
* Exports a wallet account as an encrypted bundle.
|
|
1964
|
+
*
|
|
1965
|
+
* - This function exports the specified wallet account as an encrypted bundle, suitable for backup or transfer.
|
|
1966
|
+
* - The exported bundle contains the wallet account's key material, encrypted to the provided target public key.
|
|
1967
|
+
* - If a targetPublicKey is provided, the bundle will be encrypted to that public key; otherwise, an error will be thrown.
|
|
1968
|
+
* - If an organizationId is provided, the wallet account will be exported under that sub-organization; otherwise, the current session's organizationId is used.
|
|
1969
|
+
* - Optionally allows stamping the request with a specific stamper (StamperType.Passkey, StamperType.ApiKey, or StamperType.Wallet).
|
|
1970
|
+
*
|
|
1971
|
+
* @param params.address - address of the wallet account to export.
|
|
1972
|
+
* @param params.targetPublicKey - public key to encrypt the bundle to.
|
|
1973
|
+
* @param params.organizationId - organization ID to export the wallet account under a specific sub-organization.
|
|
1974
|
+
* @param params.stampWith - parameter to stamp the request with a specific stamper (StamperType.Passkey, StamperType.ApiKey, or StamperType.Wallet).
|
|
1975
|
+
* @returns A promise that resolves to an `ExportBundle` object containing the encrypted wallet account and metadata.
|
|
1976
|
+
* @throws {TurnkeyError} If there is no active session, if the targetPublicKey is missing, or if there is an error exporting the wallet account.
|
|
1977
|
+
*
|
|
1978
|
+
*/
|
|
1979
|
+
this.exportWalletAccount = async (params) => {
|
|
1980
|
+
const { address, targetPublicKey, stampWith, organizationId } = params;
|
|
1981
|
+
const session = await this.storageManager.getActiveSession();
|
|
1982
|
+
if (!session) {
|
|
1983
|
+
throw new TurnkeyError("No active session found. Please log in first.", TurnkeyErrorCodes.NO_SESSION_FOUND);
|
|
1893
1984
|
}
|
|
1985
|
+
return withTurnkeyErrorHandling(async () => {
|
|
1986
|
+
const res = await this.httpClient.exportWalletAccount({
|
|
1987
|
+
address,
|
|
1988
|
+
targetPublicKey,
|
|
1989
|
+
organizationId: organizationId || session.organizationId,
|
|
1990
|
+
}, stampWith);
|
|
1991
|
+
if (!res.exportBundle) {
|
|
1992
|
+
throw new TurnkeyError("No export bundle found in the response", TurnkeyErrorCodes.BAD_RESPONSE);
|
|
1993
|
+
}
|
|
1994
|
+
return res.exportBundle;
|
|
1995
|
+
}, {
|
|
1996
|
+
errorMessage: "Failed to export wallet account",
|
|
1997
|
+
errorCode: TurnkeyErrorCodes.EXPORT_WALLET_ACCOUNT_ERROR,
|
|
1998
|
+
});
|
|
1894
1999
|
};
|
|
1895
2000
|
/**
|
|
1896
2001
|
* Imports a wallet from an encrypted bundle.
|
|
@@ -1898,7 +2003,7 @@ class TurnkeyClient {
|
|
|
1898
2003
|
* - This function imports a wallet using the provided encrypted bundle and creates accounts based on the provided parameters.
|
|
1899
2004
|
* - If a userId is provided, the wallet will be imported for that specific user; otherwise, it uses the current session's userId.
|
|
1900
2005
|
* - If an accounts array is provided, those accounts will be created in the imported wallet; otherwise, default Ethereum and Solana accounts will be created.
|
|
1901
|
-
* - The encrypted
|
|
2006
|
+
* - The encrypted bundle MUST be encrypted to
|
|
1902
2007
|
* - Automatically ensures an active session exists before making the request.
|
|
1903
2008
|
* - Optionally allows stamping the request with a specific stamper (StamperType.Passkey, StamperType.ApiKey, or StamperType.Wallet).
|
|
1904
2009
|
*
|
|
@@ -1916,7 +2021,7 @@ class TurnkeyClient {
|
|
|
1916
2021
|
if (!session) {
|
|
1917
2022
|
throw new TurnkeyError("No active session found. Please log in first.", TurnkeyErrorCodes.NO_SESSION_FOUND);
|
|
1918
2023
|
}
|
|
1919
|
-
|
|
2024
|
+
return withTurnkeyErrorHandling(async () => {
|
|
1920
2025
|
const res = await this.httpClient.importWallet({
|
|
1921
2026
|
organizationId: session.organizationId,
|
|
1922
2027
|
userId: userId || session.userId,
|
|
@@ -1931,12 +2036,66 @@ class TurnkeyClient {
|
|
|
1931
2036
|
throw new TurnkeyError("No wallet ID found in the import response", TurnkeyErrorCodes.BAD_RESPONSE);
|
|
1932
2037
|
}
|
|
1933
2038
|
return res.walletId;
|
|
2039
|
+
}, {
|
|
2040
|
+
errorMessage: "Failed to import wallet",
|
|
2041
|
+
errorCode: TurnkeyErrorCodes.IMPORT_WALLET_ERROR,
|
|
2042
|
+
customMessageByMessages: {
|
|
2043
|
+
"invalid mnemonic": {
|
|
2044
|
+
message: "Invalid mnemonic input",
|
|
2045
|
+
code: TurnkeyErrorCodes.BAD_REQUEST,
|
|
2046
|
+
},
|
|
2047
|
+
},
|
|
2048
|
+
});
|
|
2049
|
+
};
|
|
2050
|
+
/**
|
|
2051
|
+
* Imports a private key from an encrypted bundle.
|
|
2052
|
+
*
|
|
2053
|
+
* - This function imports a private key using the provided encrypted bundle.
|
|
2054
|
+
* - If a userId is provided, the private key will be imported for that specific user; otherwise, it uses the current session's userId.
|
|
2055
|
+
* - Requires address formats to
|
|
2056
|
+
* - Automatically infers the cryptographic curve used to generate the private key based on the address format (can be optionally overriden if needed).
|
|
2057
|
+
* - The encrypted bundle MUST be encrypted to ensure security.
|
|
2058
|
+
* - Automatically ensures an active session exists before making the request.
|
|
2059
|
+
* - Optionally allows stamping the request with a specific stamper (StamperType.Passkey, StamperType.ApiKey, or StamperType.Wallet).
|
|
2060
|
+
*
|
|
2061
|
+
* @param params.encryptedBundle - encrypted bundle containing the private key key material and metadata.
|
|
2062
|
+
* @param params.privateKeyName - name of the private key to create upon import.
|
|
2063
|
+
* @param params.curve - the cryptographic curve used to generate a given private key
|
|
2064
|
+
* @param params.addressFormat - address format of the private key to import.
|
|
2065
|
+
* @param params.userId - user ID to import the wallet for a specific user (defaults to the current session's userId).
|
|
2066
|
+
* @param params.stampWith - parameter to stamp the request with a specific stamper (StamperType.Passkey, StamperType.ApiKey, or StamperType.Wallet).
|
|
2067
|
+
* @returns A promise that resolves to the ID of the imported wallet.
|
|
2068
|
+
* @throws {TurnkeyError} If there is no active session, if the encrypted bundle is invalid, or if there is an error importing the wallet.
|
|
2069
|
+
*/
|
|
2070
|
+
this.importPrivateKey = async (params) => {
|
|
2071
|
+
const { encryptedBundle, privateKeyName, addressFormats, curve, userId, stampWith, } = params;
|
|
2072
|
+
const session = await this.storageManager.getActiveSession();
|
|
2073
|
+
if (!session) {
|
|
2074
|
+
throw new TurnkeyError("No active session found. Please log in first.", TurnkeyErrorCodes.NO_SESSION_FOUND);
|
|
1934
2075
|
}
|
|
1935
|
-
|
|
1936
|
-
|
|
1937
|
-
|
|
1938
|
-
|
|
1939
|
-
|
|
2076
|
+
return withTurnkeyErrorHandling(async () => {
|
|
2077
|
+
const res = await this.httpClient.importPrivateKey({
|
|
2078
|
+
organizationId: session.organizationId,
|
|
2079
|
+
userId: userId || session.userId,
|
|
2080
|
+
encryptedBundle,
|
|
2081
|
+
privateKeyName,
|
|
2082
|
+
curve,
|
|
2083
|
+
addressFormats,
|
|
2084
|
+
}, stampWith);
|
|
2085
|
+
if (!res || !res.privateKeyId) {
|
|
2086
|
+
throw new TurnkeyError("No wallet ID found in the import response", TurnkeyErrorCodes.BAD_RESPONSE);
|
|
2087
|
+
}
|
|
2088
|
+
return res.privateKeyId;
|
|
2089
|
+
}, {
|
|
2090
|
+
errorMessage: "Failed to import wallet",
|
|
2091
|
+
errorCode: TurnkeyErrorCodes.IMPORT_WALLET_ERROR,
|
|
2092
|
+
customMessageByMessages: {
|
|
2093
|
+
"invalid mnemonic": {
|
|
2094
|
+
message: "Invalid mnemonic input",
|
|
2095
|
+
code: TurnkeyErrorCodes.BAD_REQUEST,
|
|
2096
|
+
},
|
|
2097
|
+
},
|
|
2098
|
+
});
|
|
1940
2099
|
};
|
|
1941
2100
|
/**
|
|
1942
2101
|
* Deletes the current sub-organization (sub-org) for the active session.
|
|
@@ -1958,14 +2117,12 @@ class TurnkeyClient {
|
|
|
1958
2117
|
if (!session) {
|
|
1959
2118
|
throw new TurnkeyError("No active session found. Please log in first.", TurnkeyErrorCodes.NO_SESSION_FOUND);
|
|
1960
2119
|
}
|
|
1961
|
-
|
|
2120
|
+
return withTurnkeyErrorHandling(async () => {
|
|
1962
2121
|
return await this.httpClient.deleteSubOrganization({ deleteWithoutExport }, stampWith);
|
|
1963
|
-
}
|
|
1964
|
-
|
|
1965
|
-
|
|
1966
|
-
|
|
1967
|
-
throw new TurnkeyError(`Failed to delete sub-organization`, TurnkeyErrorCodes.DELETE_SUB_ORGANIZATION_ERROR, error);
|
|
1968
|
-
}
|
|
2122
|
+
}, {
|
|
2123
|
+
errorMessage: "Failed to delete sub-organization",
|
|
2124
|
+
errorCode: TurnkeyErrorCodes.DELETE_SUB_ORGANIZATION_ERROR,
|
|
2125
|
+
});
|
|
1969
2126
|
};
|
|
1970
2127
|
/**
|
|
1971
2128
|
* Stores a session token and updates the session associated with the specified session key, or by default the active session.
|
|
@@ -1985,21 +2142,18 @@ class TurnkeyClient {
|
|
|
1985
2142
|
const { sessionToken, sessionKey = SessionKey.DefaultSessionkey } = params;
|
|
1986
2143
|
if (!sessionToken)
|
|
1987
2144
|
return;
|
|
1988
|
-
|
|
2145
|
+
withTurnkeyErrorHandling(async () => {
|
|
1989
2146
|
const sessionToReplace = await this.storageManager.getSession(sessionKey);
|
|
1990
2147
|
await this.storageManager.storeSession(sessionToken, sessionKey);
|
|
1991
2148
|
if (sessionToReplace) {
|
|
1992
2149
|
await this.apiKeyStamper?.deleteKeyPair(sessionToReplace.publicKey);
|
|
1993
2150
|
}
|
|
1994
|
-
}
|
|
1995
|
-
|
|
1996
|
-
|
|
1997
|
-
|
|
1998
|
-
|
|
1999
|
-
}
|
|
2000
|
-
finally {
|
|
2001
|
-
await this.clearUnusedKeyPairs();
|
|
2002
|
-
}
|
|
2151
|
+
}, {
|
|
2152
|
+
errorMessage: "Failed to store session",
|
|
2153
|
+
errorCode: TurnkeyErrorCodes.STORE_SESSION_ERROR,
|
|
2154
|
+
}, {
|
|
2155
|
+
finallyFn: async () => await this.clearUnusedKeyPairs(),
|
|
2156
|
+
});
|
|
2003
2157
|
};
|
|
2004
2158
|
/**
|
|
2005
2159
|
* Clears the session associated with the specified session key, or the active session by default.
|
|
@@ -2015,7 +2169,7 @@ class TurnkeyClient {
|
|
|
2015
2169
|
*/
|
|
2016
2170
|
this.clearSession = async (params) => {
|
|
2017
2171
|
const { sessionKey = SessionKey.DefaultSessionkey } = params || {};
|
|
2018
|
-
|
|
2172
|
+
withTurnkeyErrorHandling(async () => {
|
|
2019
2173
|
const session = await this.storageManager.getSession(sessionKey);
|
|
2020
2174
|
if (session) {
|
|
2021
2175
|
await this.apiKeyStamper?.deleteKeyPair(session.publicKey);
|
|
@@ -2024,12 +2178,10 @@ class TurnkeyClient {
|
|
|
2024
2178
|
else {
|
|
2025
2179
|
throw new TurnkeyError(`No session found with key: ${sessionKey}`, TurnkeyErrorCodes.NOT_FOUND);
|
|
2026
2180
|
}
|
|
2027
|
-
}
|
|
2028
|
-
|
|
2029
|
-
|
|
2030
|
-
|
|
2031
|
-
throw new TurnkeyError(`Failed to delete session`, TurnkeyErrorCodes.CLEAR_SESSION_ERROR, error);
|
|
2032
|
-
}
|
|
2181
|
+
}, {
|
|
2182
|
+
errorMessage: "Failed to delete session",
|
|
2183
|
+
errorCode: TurnkeyErrorCodes.CLEAR_SESSION_ERROR,
|
|
2184
|
+
});
|
|
2033
2185
|
};
|
|
2034
2186
|
/**
|
|
2035
2187
|
* Clears all sessions and resets the active session state.
|
|
@@ -2043,7 +2195,7 @@ class TurnkeyClient {
|
|
|
2043
2195
|
* @throws {TurnkeyError} If no sessions exist or if there is an error clearing all sessions.
|
|
2044
2196
|
*/
|
|
2045
2197
|
this.clearAllSessions = async () => {
|
|
2046
|
-
|
|
2198
|
+
withTurnkeyErrorHandling(async () => {
|
|
2047
2199
|
const sessionKeys = await this.storageManager.listSessionKeys();
|
|
2048
2200
|
if (sessionKeys.length === 0) {
|
|
2049
2201
|
throw new TurnkeyError("No sessions found to clear.", TurnkeyErrorCodes.NO_SESSION_FOUND);
|
|
@@ -2051,12 +2203,10 @@ class TurnkeyClient {
|
|
|
2051
2203
|
for (const sessionKey of sessionKeys) {
|
|
2052
2204
|
this.clearSession({ sessionKey });
|
|
2053
2205
|
}
|
|
2054
|
-
}
|
|
2055
|
-
|
|
2056
|
-
|
|
2057
|
-
|
|
2058
|
-
throw new TurnkeyError(`Failed to clear all sessions`, TurnkeyErrorCodes.CLEAR_ALL_SESSIONS_ERROR, error);
|
|
2059
|
-
}
|
|
2206
|
+
}, {
|
|
2207
|
+
errorMessage: "Failed to clear all sessions",
|
|
2208
|
+
errorCode: TurnkeyErrorCodes.CLEAR_ALL_SESSIONS_ERROR,
|
|
2209
|
+
});
|
|
2060
2210
|
};
|
|
2061
2211
|
/**
|
|
2062
2212
|
* Refreshes the session associated with the specified session key, or the active session by default.
|
|
@@ -2091,7 +2241,7 @@ class TurnkeyClient {
|
|
|
2091
2241
|
throw new TurnkeyError("HTTP client is not initialized. Please initialize the client before refreshing the session.", TurnkeyErrorCodes.CLIENT_NOT_INITIALIZED);
|
|
2092
2242
|
}
|
|
2093
2243
|
let keyPair;
|
|
2094
|
-
|
|
2244
|
+
return withTurnkeyErrorHandling(async () => {
|
|
2095
2245
|
keyPair = publicKey ?? (await this.apiKeyStamper?.createKeyPair());
|
|
2096
2246
|
if (!keyPair) {
|
|
2097
2247
|
throw new TurnkeyError("Failed to create new key pair.", TurnkeyErrorCodes.INTERNAL_ERROR);
|
|
@@ -2109,12 +2259,10 @@ class TurnkeyClient {
|
|
|
2109
2259
|
...(sessionKey && { sessionKey }),
|
|
2110
2260
|
});
|
|
2111
2261
|
return res;
|
|
2112
|
-
}
|
|
2113
|
-
|
|
2114
|
-
|
|
2115
|
-
|
|
2116
|
-
throw new TurnkeyError(`Failed to refresh session`, TurnkeyErrorCodes.REFRESH_SESSION_ERROR, error);
|
|
2117
|
-
}
|
|
2262
|
+
}, {
|
|
2263
|
+
errorMessage: "Failed to refresh session",
|
|
2264
|
+
errorCode: TurnkeyErrorCodes.REFRESH_SESSION_ERROR,
|
|
2265
|
+
});
|
|
2118
2266
|
};
|
|
2119
2267
|
/**
|
|
2120
2268
|
* Retrieves the session associated with the specified session key, or the active session by default.
|
|
@@ -2128,15 +2276,13 @@ class TurnkeyClient {
|
|
|
2128
2276
|
* @throws {TurnkeyError} If there is an error retrieving the session from storage.
|
|
2129
2277
|
*/
|
|
2130
2278
|
this.getSession = async (params) => {
|
|
2131
|
-
|
|
2279
|
+
return withTurnkeyErrorHandling(async () => {
|
|
2132
2280
|
const { sessionKey = await this.storageManager.getActiveSessionKey() } = params || {};
|
|
2133
2281
|
return this.storageManager.getSession(sessionKey);
|
|
2134
|
-
}
|
|
2135
|
-
|
|
2136
|
-
|
|
2137
|
-
|
|
2138
|
-
throw new TurnkeyError(`Failed to get session with key`, TurnkeyErrorCodes.GET_SESSION_ERROR, error);
|
|
2139
|
-
}
|
|
2282
|
+
}, {
|
|
2283
|
+
errorMessage: "Failed to get session with key " + params?.sessionKey,
|
|
2284
|
+
errorCode: TurnkeyErrorCodes.GET_SESSION_ERROR,
|
|
2285
|
+
});
|
|
2140
2286
|
};
|
|
2141
2287
|
/**
|
|
2142
2288
|
* Retrieves all sessions stored in persistent storage.
|
|
@@ -2150,7 +2296,7 @@ class TurnkeyClient {
|
|
|
2150
2296
|
* @throws {TurnkeyError} If there is an error retrieving sessions from storage.
|
|
2151
2297
|
*/
|
|
2152
2298
|
this.getAllSessions = async () => {
|
|
2153
|
-
|
|
2299
|
+
return withTurnkeyErrorHandling(async () => {
|
|
2154
2300
|
const sessionKeys = await this.storageManager.listSessionKeys();
|
|
2155
2301
|
if (!sessionKeys || sessionKeys.length === 0) {
|
|
2156
2302
|
return undefined;
|
|
@@ -2162,13 +2308,11 @@ class TurnkeyClient {
|
|
|
2162
2308
|
sessions[sessionKey] = session;
|
|
2163
2309
|
}
|
|
2164
2310
|
}
|
|
2165
|
-
return sessions;
|
|
2166
|
-
}
|
|
2167
|
-
|
|
2168
|
-
|
|
2169
|
-
|
|
2170
|
-
throw new TurnkeyError(`Failed to get all sessions`, TurnkeyErrorCodes.GET_ALL_SESSIONS_ERROR, error);
|
|
2171
|
-
}
|
|
2311
|
+
return sessions || undefined;
|
|
2312
|
+
}, {
|
|
2313
|
+
errorMessage: "Failed to get all sessions",
|
|
2314
|
+
errorCode: TurnkeyErrorCodes.GET_ALL_SESSIONS_ERROR,
|
|
2315
|
+
});
|
|
2172
2316
|
};
|
|
2173
2317
|
/**
|
|
2174
2318
|
* Sets the active session to the specified session key.
|
|
@@ -2184,14 +2328,12 @@ class TurnkeyClient {
|
|
|
2184
2328
|
*/
|
|
2185
2329
|
this.setActiveSession = async (params) => {
|
|
2186
2330
|
const { sessionKey } = params;
|
|
2187
|
-
|
|
2331
|
+
return withTurnkeyErrorHandling(async () => {
|
|
2188
2332
|
await this.storageManager.setActiveSessionKey(sessionKey);
|
|
2189
|
-
}
|
|
2190
|
-
|
|
2191
|
-
|
|
2192
|
-
|
|
2193
|
-
throw new TurnkeyError(`Failed to set active session`, TurnkeyErrorCodes.SET_ACTIVE_SESSION_ERROR, error);
|
|
2194
|
-
}
|
|
2333
|
+
}, {
|
|
2334
|
+
errorMessage: "Failed to set active session",
|
|
2335
|
+
errorCode: TurnkeyErrorCodes.SET_ACTIVE_SESSION_ERROR,
|
|
2336
|
+
});
|
|
2195
2337
|
};
|
|
2196
2338
|
/**
|
|
2197
2339
|
* Retrieves the active session key currently set in persistent storage.
|
|
@@ -2205,14 +2347,12 @@ class TurnkeyClient {
|
|
|
2205
2347
|
* @throws {TurnkeyError} If there is an error retrieving the active session key from storage.
|
|
2206
2348
|
*/
|
|
2207
2349
|
this.getActiveSessionKey = async () => {
|
|
2208
|
-
|
|
2350
|
+
return withTurnkeyErrorHandling(async () => {
|
|
2209
2351
|
return await this.storageManager.getActiveSessionKey();
|
|
2210
|
-
}
|
|
2211
|
-
|
|
2212
|
-
|
|
2213
|
-
|
|
2214
|
-
throw new TurnkeyError(`Failed to get active session key`, TurnkeyErrorCodes.GET_ACTIVE_SESSION_KEY_ERROR, error);
|
|
2215
|
-
}
|
|
2352
|
+
}, {
|
|
2353
|
+
errorMessage: "Failed to get active session key",
|
|
2354
|
+
errorCode: TurnkeyErrorCodes.GET_ACTIVE_SESSION_KEY_ERROR,
|
|
2355
|
+
});
|
|
2216
2356
|
};
|
|
2217
2357
|
/**
|
|
2218
2358
|
* Clears any unused API key pairs from persistent storage.
|
|
@@ -2226,7 +2366,7 @@ class TurnkeyClient {
|
|
|
2226
2366
|
* @throws {TurnkeyError} If there is an error listing, checking, or deleting unused key pairs.
|
|
2227
2367
|
*/
|
|
2228
2368
|
this.clearUnusedKeyPairs = async () => {
|
|
2229
|
-
|
|
2369
|
+
withTurnkeyErrorHandling(async () => {
|
|
2230
2370
|
const publicKeys = await this.apiKeyStamper?.listKeyPairs();
|
|
2231
2371
|
if (!publicKeys || publicKeys.length === 0) {
|
|
2232
2372
|
return;
|
|
@@ -2249,12 +2389,10 @@ class TurnkeyClient {
|
|
|
2249
2389
|
}
|
|
2250
2390
|
}
|
|
2251
2391
|
}
|
|
2252
|
-
}
|
|
2253
|
-
|
|
2254
|
-
|
|
2255
|
-
|
|
2256
|
-
throw new TurnkeyError(`Failed to clear unused key pairs`, TurnkeyErrorCodes.CLEAR_UNUSED_KEY_PAIRS_ERROR, error);
|
|
2257
|
-
}
|
|
2392
|
+
}, {
|
|
2393
|
+
errorMessage: "Failed to clear unused key pairs",
|
|
2394
|
+
errorCode: TurnkeyErrorCodes.CLEAR_UNUSED_KEY_PAIRS_ERROR,
|
|
2395
|
+
});
|
|
2258
2396
|
};
|
|
2259
2397
|
/**
|
|
2260
2398
|
* Creates a new API key pair and returns the public key.
|
|
@@ -2271,23 +2409,21 @@ class TurnkeyClient {
|
|
|
2271
2409
|
* @throws {TurnkeyError} If the API key stamper is not initialized or if there is an error during key pair creation or storage.
|
|
2272
2410
|
*/
|
|
2273
2411
|
this.createApiKeyPair = async (params) => {
|
|
2274
|
-
|
|
2275
|
-
|
|
2276
|
-
|
|
2277
|
-
|
|
2278
|
-
|
|
2279
|
-
|
|
2412
|
+
return withTurnkeyErrorHandling(async () => {
|
|
2413
|
+
const externalKeyPair = params?.externalKeyPair;
|
|
2414
|
+
const storeOverride = params?.storeOverride ?? false;
|
|
2415
|
+
if (!this.apiKeyStamper) {
|
|
2416
|
+
throw new TurnkeyError("API Key Stamper is not initialized.", TurnkeyErrorCodes.INTERNAL_ERROR);
|
|
2417
|
+
}
|
|
2280
2418
|
const publicKey = await this.apiKeyStamper.createKeyPair(externalKeyPair ? externalKeyPair : undefined);
|
|
2281
2419
|
if (storeOverride && publicKey) {
|
|
2282
2420
|
await this.apiKeyStamper.setPublicKeyOverride(publicKey);
|
|
2283
2421
|
}
|
|
2284
2422
|
return publicKey;
|
|
2285
|
-
}
|
|
2286
|
-
|
|
2287
|
-
|
|
2288
|
-
|
|
2289
|
-
throw new TurnkeyError(`Failed to create API key pair`, TurnkeyErrorCodes.CREATE_API_KEY_PAIR_ERROR, error);
|
|
2290
|
-
}
|
|
2423
|
+
}, {
|
|
2424
|
+
errorMessage: "Failed to create API key pair",
|
|
2425
|
+
errorCode: TurnkeyErrorCodes.CREATE_API_KEY_PAIR_ERROR,
|
|
2426
|
+
});
|
|
2291
2427
|
};
|
|
2292
2428
|
/**
|
|
2293
2429
|
* Fetches the WalletKit proxy authentication configuration from the auth proxy.
|
|
@@ -2301,18 +2437,16 @@ class TurnkeyClient {
|
|
|
2301
2437
|
* @throws {TurnkeyError} If there is an error retrieving the proxy authentication configuration from the auth proxy.
|
|
2302
2438
|
*/
|
|
2303
2439
|
this.getProxyAuthConfig = async () => {
|
|
2304
|
-
|
|
2440
|
+
return withTurnkeyErrorHandling(async () => {
|
|
2305
2441
|
const res = await this.httpClient.proxyGetWalletKitConfig({});
|
|
2306
2442
|
if (!res) {
|
|
2307
2443
|
throw new TurnkeyError(`Failed to fetch auth proxy config`, TurnkeyErrorCodes.GET_PROXY_AUTH_CONFIG_ERROR);
|
|
2308
2444
|
}
|
|
2309
2445
|
return res;
|
|
2310
|
-
}
|
|
2311
|
-
|
|
2312
|
-
|
|
2313
|
-
|
|
2314
|
-
throw new TurnkeyError(`Failed to get auth proxy config`, TurnkeyErrorCodes.GET_PROXY_AUTH_CONFIG_ERROR, error);
|
|
2315
|
-
}
|
|
2446
|
+
}, {
|
|
2447
|
+
errorMessage: "Failed to get auth proxy config",
|
|
2448
|
+
errorCode: TurnkeyErrorCodes.GET_PROXY_AUTH_CONFIG_ERROR,
|
|
2449
|
+
});
|
|
2316
2450
|
};
|
|
2317
2451
|
this.config = config;
|
|
2318
2452
|
// Just store any explicitly provided stampers
|