@injectivelabs/wallet-turnkey 1.16.5 → 1.16.6-alpha.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +32 -34
- package/dist/cjs/strategy/strategy.d.ts +8 -9
- package/dist/cjs/strategy/strategy.js +23 -37
- package/dist/cjs/strategy/turnkey/oauth.d.ts +3 -3
- package/dist/cjs/strategy/turnkey/oauth.js +5 -4
- package/dist/cjs/strategy/turnkey/otp.d.ts +4 -3
- package/dist/cjs/strategy/turnkey/otp.js +10 -10
- package/dist/cjs/strategy/turnkey/turnkey.d.ts +8 -12
- package/dist/cjs/strategy/turnkey/turnkey.js +73 -119
- package/dist/cjs/strategy/types.d.ts +1 -1
- package/dist/esm/strategy/strategy.d.ts +8 -9
- package/dist/esm/strategy/strategy.js +20 -34
- package/dist/esm/strategy/turnkey/oauth.d.ts +3 -3
- package/dist/esm/strategy/turnkey/oauth.js +5 -4
- package/dist/esm/strategy/turnkey/otp.d.ts +4 -3
- package/dist/esm/strategy/turnkey/otp.js +10 -10
- package/dist/esm/strategy/turnkey/turnkey.d.ts +8 -12
- package/dist/esm/strategy/turnkey/turnkey.js +75 -121
- package/dist/esm/strategy/types.d.ts +1 -1
- package/package.json +11 -11
|
@@ -15,76 +15,66 @@ const utils_js_1 = require("../../utils.js");
|
|
|
15
15
|
class TurnkeyWallet {
|
|
16
16
|
otpId;
|
|
17
17
|
turnkey;
|
|
18
|
-
|
|
18
|
+
userOrganizationId;
|
|
19
19
|
client;
|
|
20
20
|
metadata;
|
|
21
|
-
|
|
21
|
+
indexedDbClient;
|
|
22
22
|
accountMap = {};
|
|
23
23
|
setMetadata(metadata) {
|
|
24
24
|
this.metadata = { ...this.metadata, ...metadata };
|
|
25
25
|
}
|
|
26
26
|
constructor(metadata) {
|
|
27
27
|
this.metadata = metadata;
|
|
28
|
-
this.organizationId = metadata.organizationId;
|
|
29
28
|
this.client = new utils_1.HttpRestClient(metadata.apiServerEndpoint);
|
|
30
29
|
}
|
|
31
30
|
static async getTurnkeyInstance(metadata) {
|
|
32
|
-
const { turnkey,
|
|
31
|
+
const { turnkey, indexedDbClient } = await createTurnkeyClient(metadata);
|
|
33
32
|
return {
|
|
34
33
|
turnkey,
|
|
35
|
-
|
|
34
|
+
indexedDbClient,
|
|
36
35
|
};
|
|
37
36
|
}
|
|
38
37
|
async getTurnkey() {
|
|
39
|
-
if (!this.
|
|
40
|
-
await this.
|
|
38
|
+
if (!this.indexedDbClient) {
|
|
39
|
+
await this.initClient();
|
|
41
40
|
}
|
|
42
41
|
if (!this.turnkey) {
|
|
43
42
|
this.turnkey = new sdk_browser_1.Turnkey(this.metadata);
|
|
44
43
|
}
|
|
45
44
|
return this.turnkey;
|
|
46
45
|
}
|
|
47
|
-
async
|
|
48
|
-
if (!this.
|
|
49
|
-
await this.
|
|
46
|
+
async getIndexedDbClient() {
|
|
47
|
+
if (!this.indexedDbClient) {
|
|
48
|
+
await this.initClient();
|
|
50
49
|
}
|
|
51
|
-
if (!this.
|
|
52
|
-
throw new exceptions_1.WalletException(new Error('
|
|
50
|
+
if (!this.indexedDbClient) {
|
|
51
|
+
throw new exceptions_1.WalletException(new Error('Indexed DB client not initialized'));
|
|
53
52
|
}
|
|
54
|
-
return this.
|
|
53
|
+
return this.indexedDbClient;
|
|
55
54
|
}
|
|
56
55
|
async getSession(existingCredentialBundle) {
|
|
57
|
-
const { metadata } = this;
|
|
58
|
-
const iframeClient = await this.getIframeClient();
|
|
59
|
-
const turnkey = await this.getTurnkey();
|
|
60
|
-
const currentSession = await turnkey.getSession();
|
|
61
|
-
const organizationId = currentSession?.organizationId || metadata.defaultOrganizationId;
|
|
62
|
-
const credentialBundle = existingCredentialBundle || currentSession?.token;
|
|
63
|
-
if (!credentialBundle) {
|
|
64
|
-
return {
|
|
65
|
-
session: undefined,
|
|
66
|
-
organizationId,
|
|
67
|
-
};
|
|
68
|
-
}
|
|
69
56
|
try {
|
|
70
|
-
const
|
|
71
|
-
|
|
72
|
-
await
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
57
|
+
const { metadata } = this;
|
|
58
|
+
const indexedDbClient = await this.getIndexedDbClient();
|
|
59
|
+
const turnkey = await this.getTurnkey();
|
|
60
|
+
const session = await turnkey.getSession();
|
|
61
|
+
const organizationId = session?.organizationId || metadata.defaultOrganizationId;
|
|
62
|
+
const credentialBundle = existingCredentialBundle || session?.token;
|
|
63
|
+
if (!credentialBundle) {
|
|
64
|
+
return {
|
|
65
|
+
session: undefined,
|
|
66
|
+
organizationId,
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
const user = await indexedDbClient.getWhoami();
|
|
81
70
|
const actualOrganizationId = user?.organizationId || session?.organizationId || organizationId;
|
|
82
|
-
if (!
|
|
71
|
+
if (!user) {
|
|
83
72
|
return {
|
|
84
73
|
session: undefined,
|
|
85
74
|
organizationId: actualOrganizationId,
|
|
86
75
|
};
|
|
87
76
|
}
|
|
77
|
+
this.userOrganizationId = actualOrganizationId;
|
|
88
78
|
return {
|
|
89
79
|
session,
|
|
90
80
|
organizationId: actualOrganizationId,
|
|
@@ -95,17 +85,17 @@ class TurnkeyWallet {
|
|
|
95
85
|
}
|
|
96
86
|
}
|
|
97
87
|
async getAccounts() {
|
|
98
|
-
const
|
|
99
|
-
if (!this.
|
|
88
|
+
const indexedDbClient = await this.getIndexedDbClient();
|
|
89
|
+
if (!this.userOrganizationId) {
|
|
100
90
|
return [];
|
|
101
91
|
}
|
|
102
92
|
try {
|
|
103
|
-
const response = await
|
|
104
|
-
organizationId: this.
|
|
93
|
+
const response = await indexedDbClient.getWallets({
|
|
94
|
+
organizationId: this.userOrganizationId,
|
|
105
95
|
});
|
|
106
|
-
const accounts = await Promise.allSettled(response.wallets.map((wallet) =>
|
|
96
|
+
const accounts = await Promise.allSettled(response.wallets.map((wallet) => indexedDbClient.getWalletAccounts({
|
|
107
97
|
walletId: wallet.walletId,
|
|
108
|
-
organizationId: this.
|
|
98
|
+
organizationId: this.userOrganizationId,
|
|
109
99
|
})));
|
|
110
100
|
const filteredAccounts = accounts
|
|
111
101
|
.filter((account) => account.status === 'fulfilled')
|
|
@@ -131,61 +121,33 @@ class TurnkeyWallet {
|
|
|
131
121
|
});
|
|
132
122
|
}
|
|
133
123
|
}
|
|
134
|
-
async getOrCreateAndGetAccount(address
|
|
124
|
+
async getOrCreateAndGetAccount(address) {
|
|
135
125
|
const { accountMap } = this;
|
|
136
|
-
const
|
|
126
|
+
const indexedDbClient = await this.getIndexedDbClient();
|
|
127
|
+
const organizationId = this.userOrganizationId;
|
|
137
128
|
if (accountMap[address] || accountMap[address.toLowerCase()]) {
|
|
138
129
|
return accountMap[address] || accountMap[address.toLowerCase()];
|
|
139
130
|
}
|
|
140
131
|
if (!organizationId) {
|
|
141
132
|
throw new exceptions_1.WalletException(new Error('Organization ID is required'));
|
|
142
133
|
}
|
|
143
|
-
|
|
134
|
+
indexedDbClient.config.organizationId = organizationId;
|
|
144
135
|
if (!address) {
|
|
145
136
|
throw new exceptions_1.WalletException(new Error('Account address not found'));
|
|
146
137
|
}
|
|
147
138
|
const turnkeyAccount = await (0, viem_1.createAccount)({
|
|
148
139
|
organizationId,
|
|
149
140
|
signWith: address,
|
|
150
|
-
client:
|
|
141
|
+
client: indexedDbClient,
|
|
151
142
|
});
|
|
152
143
|
this.accountMap[address] = turnkeyAccount;
|
|
153
144
|
return turnkeyAccount;
|
|
154
145
|
}
|
|
155
|
-
async injectAndRefresh(credentialBundle, options) {
|
|
156
|
-
const expirationSeconds = options.expirationSeconds || consts_js_1.DEFAULT_TURNKEY_REFRESH_SECONDS;
|
|
157
|
-
const iframeClient = await this.getIframeClient();
|
|
158
|
-
await iframeClient.injectCredentialBundle(credentialBundle);
|
|
159
|
-
await iframeClient.loginWithBundle({
|
|
160
|
-
bundle: credentialBundle,
|
|
161
|
-
expirationSeconds,
|
|
162
|
-
});
|
|
163
|
-
await iframeClient.refreshSession({
|
|
164
|
-
sessionType: sdk_browser_1.SessionType.READ_WRITE,
|
|
165
|
-
targetPublicKey: iframeClient.iframePublicKey,
|
|
166
|
-
expirationSeconds,
|
|
167
|
-
});
|
|
168
|
-
const session = await this.turnkey?.getSession();
|
|
169
|
-
if (!session) {
|
|
170
|
-
throw new exceptions_1.TurnkeyWalletSessionException(new Error('Session expired. Please login again.'));
|
|
171
|
-
}
|
|
172
|
-
this.organizationId = session.organizationId;
|
|
173
|
-
this.metadata.organizationId = session.organizationId;
|
|
174
|
-
// Refresh the session 2 minutes before it expires
|
|
175
|
-
setTimeout(() => {
|
|
176
|
-
iframeClient.refreshSession({
|
|
177
|
-
expirationSeconds: session?.expiry,
|
|
178
|
-
sessionType: sdk_browser_1.SessionType.READ_WRITE,
|
|
179
|
-
targetPublicKey: iframeClient.iframePublicKey,
|
|
180
|
-
});
|
|
181
|
-
}, (parseInt(expirationSeconds) - 120) * 1000);
|
|
182
|
-
return;
|
|
183
|
-
}
|
|
184
146
|
async initOTP(email) {
|
|
185
|
-
const
|
|
147
|
+
const indexedDbClient = await this.getIndexedDbClient();
|
|
186
148
|
const result = await otp_js_1.TurnkeyOtpWallet.initEmailOTP({
|
|
187
149
|
client: this.client,
|
|
188
|
-
|
|
150
|
+
indexedDbClient,
|
|
189
151
|
email,
|
|
190
152
|
otpInitPath: this.metadata.otpInitPath || consts_js_1.TURNKEY_OTP_INIT_PATH,
|
|
191
153
|
});
|
|
@@ -193,7 +155,7 @@ class TurnkeyWallet {
|
|
|
193
155
|
throw new exceptions_1.WalletException(new Error('Failed to initialize OTP'));
|
|
194
156
|
}
|
|
195
157
|
if (result?.organizationId) {
|
|
196
|
-
this.
|
|
158
|
+
this.userOrganizationId = result.organizationId;
|
|
197
159
|
}
|
|
198
160
|
if (result?.otpId) {
|
|
199
161
|
this.otpId = result.otpId;
|
|
@@ -201,30 +163,35 @@ class TurnkeyWallet {
|
|
|
201
163
|
return result;
|
|
202
164
|
}
|
|
203
165
|
async confirmOTP(otpCode) {
|
|
204
|
-
const
|
|
166
|
+
const indexedDbClient = await this.getIndexedDbClient();
|
|
167
|
+
const targetPublicKey = await indexedDbClient.getPublicKey();
|
|
205
168
|
if (!this.otpId) {
|
|
206
169
|
throw new exceptions_1.WalletException(new Error('OTP ID is required'));
|
|
207
170
|
}
|
|
171
|
+
if (!targetPublicKey) {
|
|
172
|
+
throw new exceptions_1.WalletException(new Error('Target public key not found'));
|
|
173
|
+
}
|
|
174
|
+
if (!this.userOrganizationId) {
|
|
175
|
+
throw new exceptions_1.WalletException(new Error('Organization ID is required'));
|
|
176
|
+
}
|
|
208
177
|
const result = await otp_js_1.TurnkeyOtpWallet.confirmEmailOTP({
|
|
209
178
|
otpCode,
|
|
210
|
-
iframeClient,
|
|
211
179
|
client: this.client,
|
|
212
180
|
emailOTPId: this.otpId,
|
|
213
|
-
organizationId: this.
|
|
181
|
+
organizationId: this.userOrganizationId,
|
|
182
|
+
targetPublicKey,
|
|
214
183
|
otpVerifyPath: this.metadata.otpVerifyPath || consts_js_1.TURNKEY_OTP_VERIFY_PATH,
|
|
215
184
|
});
|
|
216
|
-
if (!result || !result.
|
|
185
|
+
if (!result || !result.session) {
|
|
217
186
|
throw new exceptions_1.WalletException(new Error('Failed to confirm OTP'));
|
|
218
187
|
}
|
|
219
|
-
await
|
|
220
|
-
|
|
221
|
-
expirationSeconds: this.metadata.expirationSeconds,
|
|
222
|
-
});
|
|
188
|
+
await indexedDbClient.loginWithSession(result.session);
|
|
189
|
+
this.userOrganizationId = result.organizationId;
|
|
223
190
|
return result;
|
|
224
191
|
}
|
|
225
192
|
async initOAuth(provider) {
|
|
226
|
-
const
|
|
227
|
-
const nonce = await oauth_js_1.TurnkeyOauthWallet.generateOAuthNonce(
|
|
193
|
+
const indexedDbClient = await this.getIndexedDbClient();
|
|
194
|
+
const nonce = await oauth_js_1.TurnkeyOauthWallet.generateOAuthNonce(indexedDbClient);
|
|
228
195
|
if (provider === wallet_base_1.TurnkeyProvider.Apple) {
|
|
229
196
|
// TODO: implement the ability to generate Apple OAuth URL
|
|
230
197
|
return nonce;
|
|
@@ -239,10 +206,10 @@ class TurnkeyWallet {
|
|
|
239
206
|
});
|
|
240
207
|
}
|
|
241
208
|
async confirmOAuth(provider, oidcToken) {
|
|
242
|
-
const
|
|
209
|
+
const indexedDbClient = await this.getIndexedDbClient();
|
|
243
210
|
const oauthResult = await oauth_js_1.TurnkeyOauthWallet.oauthLogin({
|
|
244
211
|
oidcToken,
|
|
245
|
-
|
|
212
|
+
indexedDbClient,
|
|
246
213
|
client: this.client,
|
|
247
214
|
providerName: provider.toString(),
|
|
248
215
|
oauthLoginPath: this.metadata.oauthLoginPath || consts_js_1.TURNKEY_OAUTH_PATH,
|
|
@@ -250,54 +217,41 @@ class TurnkeyWallet {
|
|
|
250
217
|
if (!oauthResult || !oauthResult.credentialBundle) {
|
|
251
218
|
throw new exceptions_1.WalletException(new Error('Unexpected OAuth result'));
|
|
252
219
|
}
|
|
253
|
-
await
|
|
254
|
-
|
|
255
|
-
expirationSeconds: this.metadata.expirationSeconds,
|
|
256
|
-
});
|
|
220
|
+
await indexedDbClient.loginWithSession(oauthResult.credentialBundle);
|
|
221
|
+
this.userOrganizationId = oauthResult.organizationId;
|
|
257
222
|
return oauthResult.credentialBundle;
|
|
258
223
|
}
|
|
259
224
|
async refreshSession() {
|
|
260
225
|
const session = await this.getSession();
|
|
226
|
+
const indexedDbClient = await this.getIndexedDbClient();
|
|
261
227
|
if (session.session?.token) {
|
|
262
|
-
await
|
|
263
|
-
|
|
228
|
+
await indexedDbClient.refreshSession({
|
|
229
|
+
sessionType: sdk_browser_1.SessionType.READ_WRITE,
|
|
230
|
+
expirationSeconds: this.metadata.expirationSeconds,
|
|
264
231
|
});
|
|
232
|
+
this.userOrganizationId = session.organizationId;
|
|
265
233
|
return session.session.token;
|
|
266
234
|
}
|
|
267
235
|
throw new exceptions_1.TurnkeyWalletSessionException(new Error('Session expired. Please login again.'));
|
|
268
236
|
}
|
|
269
|
-
async
|
|
237
|
+
async initClient() {
|
|
270
238
|
const { metadata } = this;
|
|
271
|
-
const { turnkey,
|
|
239
|
+
const { turnkey, indexedDbClient } = await createTurnkeyClient(metadata);
|
|
272
240
|
this.turnkey = turnkey;
|
|
273
|
-
this.
|
|
241
|
+
this.indexedDbClient = indexedDbClient;
|
|
242
|
+
return { turnkey, indexedDbClient };
|
|
274
243
|
}
|
|
275
244
|
}
|
|
276
245
|
exports.TurnkeyWallet = TurnkeyWallet;
|
|
277
|
-
async function
|
|
246
|
+
async function createTurnkeyClient(metadata) {
|
|
278
247
|
const turnkey = new sdk_browser_1.Turnkey(metadata);
|
|
279
|
-
const
|
|
280
|
-
|
|
281
|
-
throw new exceptions_1.GeneralException(new Error('iframeContainerId is required'));
|
|
282
|
-
}
|
|
248
|
+
const indexedDbClient = await turnkey.indexedDbClient();
|
|
249
|
+
await indexedDbClient.init();
|
|
283
250
|
if (!turnkey) {
|
|
284
251
|
throw new exceptions_1.GeneralException(new Error('Turnkey is not initialized'));
|
|
285
252
|
}
|
|
286
|
-
const iframe = document.getElementById(metadata.iframeContainerId);
|
|
287
|
-
if (!iframe) {
|
|
288
|
-
throw new exceptions_1.GeneralException(new Error('iframe is null'));
|
|
289
|
-
}
|
|
290
|
-
const existingIframeClient = document.getElementById(turnkeyAuthIframeElementId);
|
|
291
|
-
if (existingIframeClient) {
|
|
292
|
-
existingIframeClient.remove();
|
|
293
|
-
}
|
|
294
|
-
const iframeClient = await turnkey.iframeClient({
|
|
295
|
-
iframeContainer: iframe,
|
|
296
|
-
iframeElementId: turnkeyAuthIframeElementId,
|
|
297
|
-
iframeUrl: metadata?.iframeUrl || 'https://auth.turnkey.com',
|
|
298
|
-
});
|
|
299
253
|
return {
|
|
300
254
|
turnkey,
|
|
301
|
-
|
|
255
|
+
indexedDbClient,
|
|
302
256
|
};
|
|
303
257
|
}
|
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
import { TxRaw, AminoSignResponse, DirectSignResponse } from '@injectivelabs/sdk-ts';
|
|
2
|
+
import { StdSignDoc, WalletDeviceType, type WalletMetadata, BaseConcreteStrategy, ConcreteWalletStrategy, SendTransactionOptions, WalletStrategyEvmOptions, ConcreteEvmWalletStrategyArgs } from '@injectivelabs/wallet-base';
|
|
2
3
|
import { HttpRestClient } from '@injectivelabs/utils';
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import { StdSignDoc, WalletDeviceType, type WalletMetadata, BaseConcreteStrategy, ConcreteWalletStrategy, SendTransactionOptions, WalletStrategyEthereumOptions, ConcreteEthereumWalletStrategyArgs } from '@injectivelabs/wallet-base';
|
|
4
|
+
import { TurnkeyIndexedDbClient } from '@turnkey/sdk-browser';
|
|
5
|
+
import { AccountAddress, EvmChainId } from '@injectivelabs/ts-types';
|
|
6
6
|
import { TurnkeyWallet } from './turnkey/turnkey.js';
|
|
7
7
|
export declare class TurnkeyWalletStrategy extends BaseConcreteStrategy implements ConcreteWalletStrategy {
|
|
8
8
|
turnkeyWallet?: TurnkeyWallet;
|
|
9
|
-
|
|
9
|
+
evmOptions: WalletStrategyEvmOptions;
|
|
10
10
|
client: HttpRestClient;
|
|
11
|
-
constructor(args:
|
|
11
|
+
constructor(args: ConcreteEvmWalletStrategyArgs & {
|
|
12
12
|
apiServerEndpoint?: string;
|
|
13
13
|
});
|
|
14
14
|
getWalletDeviceType(): Promise<WalletDeviceType>;
|
|
@@ -22,7 +22,7 @@ export declare class TurnkeyWalletStrategy extends BaseConcreteStrategy implemen
|
|
|
22
22
|
getWalletClient<TurnkeyWallet>(): Promise<TurnkeyWallet>;
|
|
23
23
|
sendEvmTransaction(transaction: unknown, args: {
|
|
24
24
|
address: AccountAddress;
|
|
25
|
-
|
|
25
|
+
evmChainId: EvmChainId;
|
|
26
26
|
}): Promise<string>;
|
|
27
27
|
sendTransaction(transaction: TxRaw, options: SendTransactionOptions): Promise<any>;
|
|
28
28
|
signEip712TypedData(eip712json: string, address: AccountAddress): Promise<string>;
|
|
@@ -38,9 +38,8 @@ export declare class TurnkeyWalletStrategy extends BaseConcreteStrategy implemen
|
|
|
38
38
|
}): Promise<AminoSignResponse>;
|
|
39
39
|
signArbitrary(_signer: AccountAddress, _data: string | Uint8Array): Promise<string>;
|
|
40
40
|
getEthereumChainId(): Promise<string>;
|
|
41
|
-
getEvmTransactionReceipt(txHash: string,
|
|
41
|
+
getEvmTransactionReceipt(txHash: string, evmChainId?: EvmChainId): Promise<Record<string, any>>;
|
|
42
42
|
getPubKey(): Promise<string>;
|
|
43
|
-
|
|
43
|
+
getIndexedDbClient(): Promise<TurnkeyIndexedDbClient>;
|
|
44
44
|
private getTurnkeyWallet;
|
|
45
|
-
private getOrganizationId;
|
|
46
45
|
}
|
|
@@ -1,16 +1,15 @@
|
|
|
1
1
|
/* eslint-disable class-methods-use-this */
|
|
2
2
|
import { TxGrpcApi, } from '@injectivelabs/sdk-ts';
|
|
3
3
|
import { ErrorType, WalletException, UnspecifiedErrorCode, TransactionException, CosmosWalletException, } from '@injectivelabs/exceptions';
|
|
4
|
-
import { getAddress } from 'viem';
|
|
5
|
-
import { sleep, HttpRestClient } from '@injectivelabs/utils';
|
|
6
|
-
import { http, createPublicClient, createWalletClient, } from 'viem';
|
|
4
|
+
import { http, getAddress, createPublicClient, createWalletClient, } from 'viem';
|
|
7
5
|
import { WalletAction, WalletDeviceType, BaseConcreteStrategy, } from '@injectivelabs/wallet-base';
|
|
6
|
+
import { sleep, HttpRestClient } from '@injectivelabs/utils';
|
|
8
7
|
import { TurnkeyErrorCodes } from './types.js';
|
|
9
8
|
import { TurnkeyWallet } from './turnkey/turnkey.js';
|
|
10
9
|
import { DEFAULT_EVM_CHAIN_CONFIG } from './consts.js';
|
|
11
10
|
export class TurnkeyWalletStrategy extends BaseConcreteStrategy {
|
|
12
11
|
turnkeyWallet;
|
|
13
|
-
|
|
12
|
+
evmOptions;
|
|
14
13
|
client;
|
|
15
14
|
constructor(args) {
|
|
16
15
|
super(args);
|
|
@@ -19,7 +18,7 @@ export class TurnkeyWalletStrategy extends BaseConcreteStrategy {
|
|
|
19
18
|
throw new WalletException(new Error('apiServerEndpoint is required'));
|
|
20
19
|
}
|
|
21
20
|
this.client = new HttpRestClient(endpoint);
|
|
22
|
-
this.
|
|
21
|
+
this.evmOptions = args.evmOptions;
|
|
23
22
|
}
|
|
24
23
|
async getWalletDeviceType() {
|
|
25
24
|
return Promise.resolve(WalletDeviceType.Browser);
|
|
@@ -47,7 +46,7 @@ export class TurnkeyWalletStrategy extends BaseConcreteStrategy {
|
|
|
47
46
|
}
|
|
48
47
|
return true;
|
|
49
48
|
}
|
|
50
|
-
return !!(await turnkeyWallet.
|
|
49
|
+
return !!(await turnkeyWallet.getIndexedDbClient());
|
|
51
50
|
}
|
|
52
51
|
catch (e) {
|
|
53
52
|
return false;
|
|
@@ -56,15 +55,15 @@ export class TurnkeyWalletStrategy extends BaseConcreteStrategy {
|
|
|
56
55
|
async disconnect() {
|
|
57
56
|
const turnkeyWallet = await this.getTurnkeyWallet();
|
|
58
57
|
const turnkey = await turnkeyWallet.getTurnkey();
|
|
58
|
+
const indexedDbClient = await turnkeyWallet.getIndexedDbClient();
|
|
59
59
|
const isUserLoggedIn = await turnkey.getSession();
|
|
60
60
|
if (!isUserLoggedIn) {
|
|
61
61
|
return;
|
|
62
62
|
}
|
|
63
|
-
await turnkey.logout();
|
|
63
|
+
await Promise.allSettled([turnkey.logout(), indexedDbClient.clear()]);
|
|
64
64
|
}
|
|
65
65
|
async getAddresses() {
|
|
66
66
|
const turnkeyWallet = await this.getTurnkeyWallet();
|
|
67
|
-
await turnkeyWallet.getSession();
|
|
68
67
|
try {
|
|
69
68
|
return await turnkeyWallet.getAccounts();
|
|
70
69
|
}
|
|
@@ -89,18 +88,17 @@ export class TurnkeyWalletStrategy extends BaseConcreteStrategy {
|
|
|
89
88
|
}
|
|
90
89
|
async sendEvmTransaction(transaction, args) {
|
|
91
90
|
try {
|
|
92
|
-
const options = this.
|
|
91
|
+
const options = this.evmOptions;
|
|
93
92
|
const turnkeyWallet = await this.getTurnkeyWallet();
|
|
94
|
-
const
|
|
95
|
-
const
|
|
96
|
-
const url = options.rpcUrl || options.rpcUrls?.[args.ethereumChainId];
|
|
93
|
+
const chainId = args.evmChainId || options.evmChainId;
|
|
94
|
+
const url = options.rpcUrl || options.rpcUrls?.[args.evmChainId];
|
|
97
95
|
if (!url) {
|
|
98
|
-
throw new WalletException(new Error('Please pass rpcUrl within the
|
|
96
|
+
throw new WalletException(new Error('Please pass rpcUrl within the evmOptions'), {
|
|
99
97
|
code: UnspecifiedErrorCode,
|
|
100
98
|
context: WalletAction.SendEvmTransaction,
|
|
101
99
|
});
|
|
102
100
|
}
|
|
103
|
-
const account = await turnkeyWallet.getOrCreateAndGetAccount(getAddress(args.address)
|
|
101
|
+
const account = await turnkeyWallet.getOrCreateAndGetAccount(getAddress(args.address));
|
|
104
102
|
const accountClient = createWalletClient({
|
|
105
103
|
account: account,
|
|
106
104
|
chain: {
|
|
@@ -147,10 +145,9 @@ export class TurnkeyWalletStrategy extends BaseConcreteStrategy {
|
|
|
147
145
|
}
|
|
148
146
|
async signEip712TypedData(eip712json, address) {
|
|
149
147
|
const turnkeyWallet = await this.getTurnkeyWallet();
|
|
150
|
-
const organizationId = await this.getOrganizationId();
|
|
151
148
|
//? Turnkey expects the case sensitive address and the current impl of getChecksumAddress from sdk-ts doesn't play nice with browser envs
|
|
152
149
|
const checksumAddress = getAddress(address);
|
|
153
|
-
const account = await turnkeyWallet.getOrCreateAndGetAccount(checksumAddress
|
|
150
|
+
const account = await turnkeyWallet.getOrCreateAndGetAccount(checksumAddress);
|
|
154
151
|
if (!account) {
|
|
155
152
|
throw new WalletException(new Error('Turnkey account not found'));
|
|
156
153
|
}
|
|
@@ -196,14 +193,14 @@ export class TurnkeyWalletStrategy extends BaseConcreteStrategy {
|
|
|
196
193
|
context: WalletAction.GetChainId,
|
|
197
194
|
});
|
|
198
195
|
}
|
|
199
|
-
async getEvmTransactionReceipt(txHash,
|
|
200
|
-
const options = this.
|
|
196
|
+
async getEvmTransactionReceipt(txHash, evmChainId) {
|
|
197
|
+
const options = this.evmOptions;
|
|
201
198
|
const maxAttempts = 10;
|
|
202
199
|
const interval = 3000;
|
|
203
|
-
const chainId =
|
|
200
|
+
const chainId = evmChainId || options.evmChainId;
|
|
204
201
|
const url = options.rpcUrl || options.rpcUrls?.[chainId];
|
|
205
202
|
if (!url) {
|
|
206
|
-
throw new WalletException(new Error('Please pass rpcUrl within the
|
|
203
|
+
throw new WalletException(new Error('Please pass rpcUrl within the evmOptions'), {
|
|
207
204
|
code: UnspecifiedErrorCode,
|
|
208
205
|
context: WalletAction.GetEvmTransactionReceipt,
|
|
209
206
|
});
|
|
@@ -240,9 +237,10 @@ export class TurnkeyWalletStrategy extends BaseConcreteStrategy {
|
|
|
240
237
|
async getPubKey() {
|
|
241
238
|
throw new WalletException(new Error('You can only fetch PubKey from Cosmos native wallets'));
|
|
242
239
|
}
|
|
243
|
-
async
|
|
240
|
+
async getIndexedDbClient() {
|
|
244
241
|
const turnkeyWallet = await this.getTurnkeyWallet();
|
|
245
|
-
|
|
242
|
+
const indexedDbClient = await turnkeyWallet.getIndexedDbClient();
|
|
243
|
+
return indexedDbClient;
|
|
246
244
|
}
|
|
247
245
|
async getTurnkeyWallet() {
|
|
248
246
|
const { metadata } = this;
|
|
@@ -256,20 +254,8 @@ export class TurnkeyWalletStrategy extends BaseConcreteStrategy {
|
|
|
256
254
|
if (!metadata.turnkey.apiServerEndpoint) {
|
|
257
255
|
throw new WalletException(new Error('Turnkey apiServerEndpoint is required'));
|
|
258
256
|
}
|
|
259
|
-
if (!metadata.turnkey.defaultOrganizationId) {
|
|
260
|
-
throw new WalletException(new Error('Turnkey defaultOrganizationId is required'));
|
|
261
|
-
}
|
|
262
257
|
this.turnkeyWallet = new TurnkeyWallet(metadata.turnkey);
|
|
263
258
|
}
|
|
264
259
|
return this.turnkeyWallet;
|
|
265
260
|
}
|
|
266
|
-
async getOrganizationId() {
|
|
267
|
-
const { metadata } = this;
|
|
268
|
-
const organizationId = metadata?.turnkey?.organizationId ||
|
|
269
|
-
metadata?.turnkey?.defaultOrganizationId;
|
|
270
|
-
if (!organizationId) {
|
|
271
|
-
throw new WalletException(new Error('Organization ID is required'));
|
|
272
|
-
}
|
|
273
|
-
return organizationId;
|
|
274
|
-
}
|
|
275
261
|
}
|
|
@@ -1,13 +1,13 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { TurnkeyIndexedDbClient } from '@turnkey/sdk-browser';
|
|
2
2
|
import { type HttpRestClient } from '@injectivelabs/utils';
|
|
3
3
|
export declare class TurnkeyOauthWallet {
|
|
4
|
-
static generateOAuthNonce(
|
|
4
|
+
static generateOAuthNonce(indexedDbClient: TurnkeyIndexedDbClient): Promise<string>;
|
|
5
5
|
static oauthLogin(args: {
|
|
6
6
|
oidcToken: string;
|
|
7
7
|
client: HttpRestClient;
|
|
8
8
|
oauthLoginPath?: string;
|
|
9
9
|
providerName: 'google' | 'apple';
|
|
10
|
-
|
|
10
|
+
indexedDbClient: TurnkeyIndexedDbClient;
|
|
11
11
|
expirationSeconds?: number;
|
|
12
12
|
}): Promise<{
|
|
13
13
|
organizationId: string;
|
|
@@ -2,9 +2,10 @@ import { ErrorType, WalletException, UnspecifiedErrorCode, } from '@injectivelab
|
|
|
2
2
|
import { sha256 } from '@injectivelabs/sdk-ts';
|
|
3
3
|
import { DEFAULT_TURNKEY_REFRESH_SECONDS, TURNKEY_OAUTH_PATH, } from '../consts.js';
|
|
4
4
|
export class TurnkeyOauthWallet {
|
|
5
|
-
static async generateOAuthNonce(
|
|
5
|
+
static async generateOAuthNonce(indexedDbClient) {
|
|
6
6
|
try {
|
|
7
|
-
|
|
7
|
+
await indexedDbClient.resetKeyPair();
|
|
8
|
+
const targetPublicKey = await indexedDbClient.getPublicKey();
|
|
8
9
|
if (!targetPublicKey) {
|
|
9
10
|
throw new WalletException(new Error('Target public key not found'));
|
|
10
11
|
}
|
|
@@ -21,10 +22,10 @@ export class TurnkeyOauthWallet {
|
|
|
21
22
|
}
|
|
22
23
|
}
|
|
23
24
|
static async oauthLogin(args) {
|
|
24
|
-
const { client,
|
|
25
|
+
const { client, indexedDbClient, expirationSeconds } = args;
|
|
25
26
|
const path = args.oauthLoginPath || TURNKEY_OAUTH_PATH;
|
|
26
27
|
try {
|
|
27
|
-
const targetPublicKey =
|
|
28
|
+
const targetPublicKey = await indexedDbClient.getPublicKey();
|
|
28
29
|
if (!targetPublicKey) {
|
|
29
30
|
throw new WalletException(new Error('Target public key not found'));
|
|
30
31
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { TurnkeyIndexedDbClient } from '@turnkey/sdk-browser';
|
|
2
2
|
import { type TurnkeyConfirmEmailOTPResponse, type TurnkeyOTPCredentialsResponse } from './../types.js';
|
|
3
3
|
import { type HttpRestClient } from '@injectivelabs/utils';
|
|
4
4
|
export declare class TurnkeyOtpWallet {
|
|
@@ -7,15 +7,16 @@ export declare class TurnkeyOtpWallet {
|
|
|
7
7
|
subOrgId?: string;
|
|
8
8
|
otpInitPath?: string;
|
|
9
9
|
client: HttpRestClient;
|
|
10
|
-
|
|
10
|
+
indexedDbClient: TurnkeyIndexedDbClient;
|
|
11
11
|
invalidateExistingSessions?: boolean;
|
|
12
|
+
expirationSeconds?: number;
|
|
12
13
|
}): Promise<TurnkeyOTPCredentialsResponse | undefined>;
|
|
13
14
|
static confirmEmailOTP(args: {
|
|
14
15
|
otpCode: string;
|
|
15
16
|
emailOTPId: string;
|
|
16
17
|
client: HttpRestClient;
|
|
18
|
+
targetPublicKey: string;
|
|
17
19
|
organizationId: string;
|
|
18
|
-
iframeClient: TurnkeyIframeClient;
|
|
19
20
|
otpVerifyPath?: string;
|
|
20
21
|
expirationSeconds?: number;
|
|
21
22
|
}): Promise<TurnkeyConfirmEmailOTPResponse | undefined>;
|
|
@@ -2,18 +2,21 @@ import { ErrorType, WalletException, UnspecifiedErrorCode, } from '@injectivelab
|
|
|
2
2
|
import { DEFAULT_TURNKEY_REFRESH_SECONDS, TURNKEY_OTP_INIT_PATH, TURNKEY_OTP_VERIFY_PATH, } from '../consts.js';
|
|
3
3
|
export class TurnkeyOtpWallet {
|
|
4
4
|
static async initEmailOTP(args) {
|
|
5
|
-
const { client,
|
|
5
|
+
const { client, indexedDbClient, expirationSeconds } = args;
|
|
6
6
|
try {
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
7
|
+
await indexedDbClient.resetKeyPair();
|
|
8
|
+
let publicKey = await indexedDbClient.getPublicKey();
|
|
9
|
+
if (!publicKey) {
|
|
10
|
+
throw new WalletException(new Error('Public key not found'));
|
|
10
11
|
}
|
|
11
12
|
// client.$post is undefined, resorting to this for now
|
|
12
13
|
const response = await client.post(args.otpInitPath || TURNKEY_OTP_INIT_PATH, {
|
|
13
|
-
targetPublicKey,
|
|
14
|
+
targetPublicKey: publicKey,
|
|
14
15
|
email: args.email,
|
|
15
16
|
suborgId: args.subOrgId,
|
|
16
17
|
invalidateExistingSessions: args.invalidateExistingSessions,
|
|
18
|
+
isUsingIndexedDB: true,
|
|
19
|
+
expirationSeconds: expirationSeconds || DEFAULT_TURNKEY_REFRESH_SECONDS,
|
|
17
20
|
});
|
|
18
21
|
return response?.data;
|
|
19
22
|
}
|
|
@@ -26,15 +29,11 @@ export class TurnkeyOtpWallet {
|
|
|
26
29
|
}
|
|
27
30
|
}
|
|
28
31
|
static async confirmEmailOTP(args) {
|
|
29
|
-
const { client,
|
|
32
|
+
const { client, expirationSeconds, targetPublicKey } = args;
|
|
30
33
|
try {
|
|
31
34
|
const organizationId = args.organizationId;
|
|
32
35
|
const emailOTPId = args.emailOTPId;
|
|
33
|
-
const targetPublicKey = iframeClient.iframePublicKey;
|
|
34
36
|
const otpVerifyPath = args.otpVerifyPath || TURNKEY_OTP_VERIFY_PATH;
|
|
35
|
-
if (!targetPublicKey) {
|
|
36
|
-
throw new WalletException(new Error('Target public key not found'));
|
|
37
|
-
}
|
|
38
37
|
if (!emailOTPId) {
|
|
39
38
|
throw new WalletException(new Error('Email OTP ID is required'));
|
|
40
39
|
}
|
|
@@ -42,6 +41,7 @@ export class TurnkeyOtpWallet {
|
|
|
42
41
|
throw new WalletException(new Error('Organization ID is required'));
|
|
43
42
|
}
|
|
44
43
|
const response = await client.post(otpVerifyPath, {
|
|
44
|
+
isUsingIndexedDB: true,
|
|
45
45
|
targetPublicKey,
|
|
46
46
|
otpId: emailOTPId,
|
|
47
47
|
otpCode: args.otpCode,
|