@turnkey/react-wallet-kit 1.0.0-beta.5 → 1.0.0-beta.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/_virtual/_rollupPluginBabelHelpers.mjs +49 -1
- package/dist/_virtual/_rollupPluginBabelHelpers.mjs.map +1 -1
- package/dist/components/auth/OTP.d.ts +1 -0
- package/dist/components/auth/OTP.d.ts.map +1 -1
- package/dist/components/auth/OTP.js +5 -1
- package/dist/components/auth/OTP.js.map +1 -1
- package/dist/components/auth/OTP.mjs +6 -3
- package/dist/components/auth/OTP.mjs.map +1 -1
- package/dist/components/auth/Wallet.d.ts +4 -4
- package/dist/components/auth/Wallet.d.ts.map +1 -1
- package/dist/components/auth/Wallet.js +69 -48
- package/dist/components/auth/Wallet.js.map +1 -1
- package/dist/components/auth/Wallet.mjs +75 -55
- package/dist/components/auth/Wallet.mjs.map +1 -1
- package/dist/components/auth/index.d.ts +5 -1
- package/dist/components/auth/index.d.ts.map +1 -1
- package/dist/components/auth/index.js +98 -12
- package/dist/components/auth/index.js.map +1 -1
- package/dist/components/auth/index.mjs +185 -82
- package/dist/components/auth/index.mjs.map +1 -1
- package/dist/components/export/Export.d.ts +2 -1
- package/dist/components/export/Export.d.ts.map +1 -1
- package/dist/components/export/Export.js +7 -6
- package/dist/components/export/Export.js.map +1 -1
- package/dist/components/export/Export.mjs +7 -6
- package/dist/components/export/Export.mjs.map +1 -1
- package/dist/components/export/ExportWarning.d.ts +2 -1
- package/dist/components/export/ExportWarning.d.ts.map +1 -1
- package/dist/components/export/ExportWarning.js +3 -2
- package/dist/components/export/ExportWarning.js.map +1 -1
- package/dist/components/export/ExportWarning.mjs +3 -2
- package/dist/components/export/ExportWarning.mjs.map +1 -1
- package/dist/components/import/Import.d.ts +7 -3
- package/dist/components/import/Import.d.ts.map +1 -1
- package/dist/components/import/Import.js +74 -37
- package/dist/components/import/Import.js.map +1 -1
- package/dist/components/import/Import.mjs +116 -54
- package/dist/components/import/Import.mjs.map +1 -1
- package/dist/components/user/ConnectWallet.d.ts +8 -0
- package/dist/components/user/ConnectWallet.d.ts.map +1 -0
- package/dist/components/user/{LinkWallet.js → ConnectWallet.js} +18 -18
- package/dist/components/user/ConnectWallet.js.map +1 -0
- package/dist/components/user/{LinkWallet.mjs → ConnectWallet.mjs} +25 -25
- package/dist/components/user/ConnectWallet.mjs.map +1 -0
- package/dist/index.js +13 -0
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +2 -1
- package/dist/index.mjs.map +1 -1
- package/dist/providers/client/Provider.d.ts +3 -3
- package/dist/providers/client/Provider.d.ts.map +1 -1
- package/dist/providers/client/Provider.js +684 -105
- package/dist/providers/client/Provider.js.map +1 -1
- package/dist/providers/client/Provider.mjs +2368 -1597
- package/dist/providers/client/Provider.mjs.map +1 -1
- package/dist/providers/client/Types.d.ts +116 -11
- package/dist/providers/client/Types.d.ts.map +1 -1
- package/dist/providers/client/Types.js.map +1 -1
- package/dist/providers/client/Types.mjs.map +1 -1
- package/dist/providers/modal/Provider.js +1 -1
- package/dist/providers/modal/Provider.mjs +1 -1
- package/dist/styles.css +1 -1
- package/dist/types/base.d.ts +28 -2
- package/dist/types/base.d.ts.map +1 -1
- package/dist/types/base.js +23 -0
- package/dist/types/base.js.map +1 -1
- package/dist/types/base.mjs +19 -1
- package/dist/types/base.mjs.map +1 -1
- package/dist/utils/timers.d.ts +73 -0
- package/dist/utils/timers.d.ts.map +1 -0
- package/dist/utils/timers.js +133 -0
- package/dist/utils/timers.js.map +1 -0
- package/dist/utils/timers.mjs +142 -0
- package/dist/utils/timers.mjs.map +1 -0
- package/dist/{utils.d.ts → utils/utils.d.ts} +8 -3
- package/dist/utils/utils.d.ts.map +1 -0
- package/dist/{utils.js → utils/utils.js} +12 -3
- package/dist/utils/utils.js.map +1 -0
- package/dist/{utils.mjs → utils/utils.mjs} +12 -5
- package/dist/utils/utils.mjs.map +1 -0
- package/package.json +3 -3
- package/dist/components/user/LinkWallet.d.ts +0 -8
- package/dist/components/user/LinkWallet.d.ts.map +0 -1
- package/dist/components/user/LinkWallet.js.map +0 -1
- package/dist/components/user/LinkWallet.mjs.map +0 -1
- package/dist/utils.d.ts.map +0 -1
- package/dist/utils.js.map +0 -1
- package/dist/utils.mjs.map +0 -1
|
@@ -4,7 +4,8 @@
|
|
|
4
4
|
var jsxRuntime = require('react/jsx-runtime');
|
|
5
5
|
var sha2 = require('@noble/hashes/sha2');
|
|
6
6
|
var utils$1 = require('@noble/hashes/utils');
|
|
7
|
-
var utils = require('../../utils.js');
|
|
7
|
+
var utils = require('../../utils/utils.js');
|
|
8
|
+
var timers = require('../../utils/timers.js');
|
|
8
9
|
var core = require('@turnkey/core');
|
|
9
10
|
var react = require('react');
|
|
10
11
|
var sdkTypes = require('@turnkey/sdk-types');
|
|
@@ -23,7 +24,7 @@ var UpdatePhoneNumber = require('../../components/user/UpdatePhoneNumber.js');
|
|
|
23
24
|
var UpdateUserName = require('../../components/user/UpdateUserName.js');
|
|
24
25
|
var RemoveOAuthProvider = require('../../components/user/RemoveOAuthProvider.js');
|
|
25
26
|
var RemovePasskey = require('../../components/user/RemovePasskey.js');
|
|
26
|
-
var
|
|
27
|
+
var ConnectWallet = require('../../components/user/ConnectWallet.js');
|
|
27
28
|
var Types = require('./Types.js');
|
|
28
29
|
var OTP = require('../../components/auth/OTP.js');
|
|
29
30
|
var RemoveEmail = require('../../components/user/RemoveEmail.js');
|
|
@@ -32,7 +33,7 @@ var RemovePhoneNumber = require('../../components/user/RemovePhoneNumber.js');
|
|
|
32
33
|
/**
|
|
33
34
|
* Provides Turnkey client authentication, session management, wallet operations, and user profile management
|
|
34
35
|
* for the React Wallet Kit SDK. This context provider encapsulates all core authentication flows (Passkey, Wallet, OTP, OAuth),
|
|
35
|
-
* session lifecycle (creation, expiration, refresh), wallet
|
|
36
|
+
* session lifecycle (creation, expiration, refresh), wallet connecting/import/export, and user profile updates (email, phone, name).
|
|
36
37
|
*
|
|
37
38
|
* The provider automatically initializes the Turnkey client, fetches configuration (including proxy auth config if needed),
|
|
38
39
|
* and synchronizes session and authentication state. It exposes a comprehensive set of methods for authentication flows,
|
|
@@ -41,9 +42,9 @@ var RemovePhoneNumber = require('../../components/user/RemovePhoneNumber.js');
|
|
|
41
42
|
* Features:
|
|
42
43
|
* - Passkey, Wallet, OTP (Email/SMS), and OAuth (Google, Apple, Facebook) authentication and sign-up flows.
|
|
43
44
|
* - Session management: creation, expiration scheduling, refresh, and clearing.
|
|
44
|
-
* - Wallet management: fetch,
|
|
45
|
+
* - Wallet management: fetch, connect, import, export, account management.
|
|
45
46
|
* - User profile management: email, phone, name, OAuth provider, and passkey linking/removal.
|
|
46
|
-
* - Modal-driven UI flows for authentication, wallet
|
|
47
|
+
* - Modal-driven UI flows for authentication, wallet connecting, and profile updates.
|
|
47
48
|
* - Error handling and callback integration for custom error and event responses.
|
|
48
49
|
*
|
|
49
50
|
* Usage:
|
|
@@ -92,6 +93,7 @@ const ClientProvider = ({
|
|
|
92
93
|
const flow = stateParams.get("flow");
|
|
93
94
|
const publicKey = stateParams.get("publicKey");
|
|
94
95
|
const openModal = stateParams.get("openModal");
|
|
96
|
+
const sessionKey = stateParams.get("sessionKey");
|
|
95
97
|
if (provider === "facebook" && flow === "redirect" && publicKey) {
|
|
96
98
|
// We have all the required parameters for a Facebook PKCE flow
|
|
97
99
|
const clientId = masterConfig?.auth?.oauthConfig?.facebookClientId;
|
|
@@ -116,8 +118,13 @@ const ClientProvider = ({
|
|
|
116
118
|
await completeOauth({
|
|
117
119
|
oidcToken,
|
|
118
120
|
publicKey,
|
|
119
|
-
providerName: "facebook"
|
|
121
|
+
providerName: "facebook",
|
|
122
|
+
...(sessionKey && {
|
|
123
|
+
sessionKey
|
|
124
|
+
})
|
|
120
125
|
});
|
|
126
|
+
// Clean up the URL after processing
|
|
127
|
+
window.history.replaceState(null, document.title, window.location.pathname);
|
|
121
128
|
resolve();
|
|
122
129
|
} catch (err) {
|
|
123
130
|
reject(err);
|
|
@@ -140,6 +147,114 @@ const ClientProvider = ({
|
|
|
140
147
|
});
|
|
141
148
|
}
|
|
142
149
|
}
|
|
150
|
+
if (provider === "discord" && flow === "redirect" && publicKey) {
|
|
151
|
+
const clientId = masterConfig?.auth?.oauthConfig?.discordClientId;
|
|
152
|
+
const redirectURI = masterConfig?.auth?.oauthConfig?.oauthRedirectUri;
|
|
153
|
+
const verifier = sessionStorage.getItem("discord_verifier");
|
|
154
|
+
const nonce = stateParams.get("nonce");
|
|
155
|
+
const sessionKey = stateParams.get("sessionKey");
|
|
156
|
+
if (clientId && redirectURI && verifier && nonce) {
|
|
157
|
+
await new Promise((resolve, reject) => {
|
|
158
|
+
pushPage({
|
|
159
|
+
key: `Discord OAuth`,
|
|
160
|
+
content: jsxRuntime.jsx(Action.ActionPage, {
|
|
161
|
+
title: `Authenticating with Discord...`,
|
|
162
|
+
action: async () => {
|
|
163
|
+
try {
|
|
164
|
+
const resp = await client?.httpClient.proxyOAuth2Authenticate({
|
|
165
|
+
provider: "OAUTH2_PROVIDER_DISCORD",
|
|
166
|
+
authCode: code,
|
|
167
|
+
redirectUri: redirectURI,
|
|
168
|
+
codeVerifier: verifier,
|
|
169
|
+
nonce: nonce
|
|
170
|
+
});
|
|
171
|
+
sessionStorage.removeItem("discord_verifier");
|
|
172
|
+
const oidcToken = resp?.oidcToken;
|
|
173
|
+
if (!oidcToken) {
|
|
174
|
+
throw new sdkTypes.TurnkeyError("Missing OIDC token", sdkTypes.TurnkeyErrorCodes.OAUTH_LOGIN_ERROR);
|
|
175
|
+
}
|
|
176
|
+
await completeOauth({
|
|
177
|
+
oidcToken,
|
|
178
|
+
publicKey,
|
|
179
|
+
providerName: "discord",
|
|
180
|
+
...(sessionKey && {
|
|
181
|
+
sessionKey
|
|
182
|
+
})
|
|
183
|
+
});
|
|
184
|
+
// Clean up the URL after processing
|
|
185
|
+
window.history.replaceState(null, document.title, window.location.pathname);
|
|
186
|
+
resolve(null);
|
|
187
|
+
} catch (err) {
|
|
188
|
+
reject(err);
|
|
189
|
+
if (callbacks?.onError) {
|
|
190
|
+
callbacks.onError(err instanceof sdkTypes.TurnkeyError ? err : new sdkTypes.TurnkeyError("Discord authentication failed", sdkTypes.TurnkeyErrorCodes.OAUTH_SIGNUP_ERROR, err));
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
},
|
|
194
|
+
icon: jsxRuntime.jsx(reactFontawesome.FontAwesomeIcon, {
|
|
195
|
+
size: "3x",
|
|
196
|
+
icon: freeBrandsSvgIcons.faDiscord
|
|
197
|
+
})
|
|
198
|
+
}),
|
|
199
|
+
showTitle: false
|
|
200
|
+
});
|
|
201
|
+
});
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
if (provider === "twitter" && flow === "redirect" && publicKey) {
|
|
205
|
+
const clientId = masterConfig?.auth?.oauthConfig?.xClientId;
|
|
206
|
+
const redirectURI = masterConfig?.auth?.oauthConfig?.oauthRedirectUri;
|
|
207
|
+
const verifier = sessionStorage.getItem("twitter_verifier");
|
|
208
|
+
const nonce = stateParams.get("nonce");
|
|
209
|
+
const sessionKey = stateParams.get("sessionKey");
|
|
210
|
+
if (clientId && redirectURI && verifier && nonce) {
|
|
211
|
+
await new Promise((resolve, reject) => {
|
|
212
|
+
pushPage({
|
|
213
|
+
key: `Twitter OAuth`,
|
|
214
|
+
content: jsxRuntime.jsx(Action.ActionPage, {
|
|
215
|
+
title: `Authenticating with Twitter...`,
|
|
216
|
+
action: async () => {
|
|
217
|
+
try {
|
|
218
|
+
const resp = await client?.httpClient.proxyOAuth2Authenticate({
|
|
219
|
+
provider: "OAUTH2_PROVIDER_X",
|
|
220
|
+
authCode: code,
|
|
221
|
+
redirectUri: redirectURI,
|
|
222
|
+
codeVerifier: verifier,
|
|
223
|
+
nonce: nonce
|
|
224
|
+
});
|
|
225
|
+
sessionStorage.removeItem("twitter_verifier");
|
|
226
|
+
const oidcToken = resp?.oidcToken;
|
|
227
|
+
if (!oidcToken) {
|
|
228
|
+
throw new sdkTypes.TurnkeyError("Missing OIDC token", sdkTypes.TurnkeyErrorCodes.OAUTH_LOGIN_ERROR);
|
|
229
|
+
}
|
|
230
|
+
await completeOauth({
|
|
231
|
+
oidcToken,
|
|
232
|
+
publicKey,
|
|
233
|
+
providerName: "twitter",
|
|
234
|
+
...(sessionKey && {
|
|
235
|
+
sessionKey
|
|
236
|
+
})
|
|
237
|
+
});
|
|
238
|
+
// Clean up the URL after processing
|
|
239
|
+
window.history.replaceState(null, document.title, window.location.pathname);
|
|
240
|
+
resolve(null);
|
|
241
|
+
} catch (err) {
|
|
242
|
+
reject(err);
|
|
243
|
+
if (callbacks?.onError) {
|
|
244
|
+
callbacks.onError(err instanceof sdkTypes.TurnkeyError ? err : new sdkTypes.TurnkeyError("Twitter authentication failed", sdkTypes.TurnkeyErrorCodes.OAUTH_SIGNUP_ERROR, err));
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
},
|
|
248
|
+
icon: jsxRuntime.jsx(reactFontawesome.FontAwesomeIcon, {
|
|
249
|
+
size: "3x",
|
|
250
|
+
icon: freeBrandsSvgIcons.faXTwitter
|
|
251
|
+
})
|
|
252
|
+
}),
|
|
253
|
+
showTitle: false
|
|
254
|
+
});
|
|
255
|
+
});
|
|
256
|
+
}
|
|
257
|
+
}
|
|
143
258
|
}
|
|
144
259
|
}
|
|
145
260
|
// Handle Google/Apple redirects (uses hash with id_token)
|
|
@@ -151,7 +266,8 @@ const ClientProvider = ({
|
|
|
151
266
|
provider,
|
|
152
267
|
flow,
|
|
153
268
|
publicKey,
|
|
154
|
-
openModal
|
|
269
|
+
openModal,
|
|
270
|
+
sessionKey
|
|
155
271
|
} = utils.parseOAuthRedirect(hash);
|
|
156
272
|
if (idToken && flow === "redirect" && publicKey) {
|
|
157
273
|
if (openModal === "true") {
|
|
@@ -183,7 +299,10 @@ const ClientProvider = ({
|
|
|
183
299
|
publicKey,
|
|
184
300
|
...(provider ? {
|
|
185
301
|
providerName: provider
|
|
186
|
-
} : {})
|
|
302
|
+
} : {}),
|
|
303
|
+
...(sessionKey && {
|
|
304
|
+
sessionKey
|
|
305
|
+
})
|
|
187
306
|
});
|
|
188
307
|
resolve(null);
|
|
189
308
|
} catch (err) {
|
|
@@ -223,11 +342,13 @@ const ClientProvider = ({
|
|
|
223
342
|
passkeyAuthEnabled: config.auth?.methods?.passkeyAuthEnabled ?? proxyAuthConfig?.enabledProviders.includes("passkey"),
|
|
224
343
|
walletAuthEnabled: config.auth?.methods?.walletAuthEnabled ?? proxyAuthConfig?.enabledProviders.includes("wallet"),
|
|
225
344
|
googleOauthEnabled: config.auth?.methods?.googleOauthEnabled ?? proxyAuthConfig?.enabledProviders.includes("google"),
|
|
345
|
+
xOauthEnabled: config.auth?.methods?.xOauthEnabled ?? proxyAuthConfig?.enabledProviders.includes("x"),
|
|
346
|
+
discordOauthEnabled: config.auth?.methods?.discordOauthEnabled ?? proxyAuthConfig?.enabledProviders.includes("discord"),
|
|
226
347
|
appleOauthEnabled: config.auth?.methods?.appleOauthEnabled ?? proxyAuthConfig?.enabledProviders.includes("apple"),
|
|
227
348
|
facebookOauthEnabled: config.auth?.methods?.facebookOauthEnabled ?? proxyAuthConfig?.enabledProviders.includes("facebook")
|
|
228
349
|
};
|
|
229
350
|
// Set a default ordering for the oAuth methods
|
|
230
|
-
const oauthOrder = config.auth?.oauthOrder ?? ["google", "apple", "facebook"].filter(provider => resolvedMethods[`${provider}OauthEnabled`]);
|
|
351
|
+
const oauthOrder = config.auth?.oauthOrder ?? ["google", "apple", "x", "discord", "facebook"].filter(provider => resolvedMethods[`${provider}OauthEnabled`]);
|
|
231
352
|
// Set a default ordering for the overall auth methods
|
|
232
353
|
const methodOrder = config.auth?.methodOrder ?? [oauthOrder.length > 0 ? "socials" : null, resolvedMethods.emailOtpAuthEnabled ? "email" : null, resolvedMethods.smsOtpAuthEnabled ? "sms" : null, resolvedMethods.passkeyAuthEnabled ? "passkey" : null, resolvedMethods.walletAuthEnabled ? "wallet" : null].filter(Boolean);
|
|
233
354
|
return {
|
|
@@ -442,14 +563,13 @@ const ClientProvider = ({
|
|
|
442
563
|
}
|
|
443
564
|
/**
|
|
444
565
|
* @internal
|
|
445
|
-
* Schedules a session expiration and warning
|
|
566
|
+
* Schedules a session expiration and warning timer for the given session key.
|
|
446
567
|
*
|
|
447
|
-
* -
|
|
448
|
-
* -
|
|
449
|
-
* - The expiration timeout clears the session and triggers any necessary callbacks.
|
|
568
|
+
* - Sets up two timers: one for warning before expiry and one for actual expiry.
|
|
569
|
+
* - Uses capped timeouts under the hood so delays > 24.8 days are safe (see utils/timers.ts).
|
|
450
570
|
*
|
|
451
571
|
* @param params.sessionKey - The key of the session to schedule expiration for.
|
|
452
|
-
* @param params.expiry - The expiration time in seconds
|
|
572
|
+
* @param params.expiry - The expiration time in seconds since epoch.
|
|
453
573
|
* @throws {TurnkeyError} If an error occurs while scheduling the session expiration.
|
|
454
574
|
*/
|
|
455
575
|
async function scheduleSessionExpiration(params) {
|
|
@@ -458,21 +578,18 @@ const ClientProvider = ({
|
|
|
458
578
|
expiry
|
|
459
579
|
} = params;
|
|
460
580
|
try {
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
delete expiryTimeoutsRef.current[`${sessionKey}-warning`];
|
|
469
|
-
}
|
|
470
|
-
const timeUntilExpiry = expiry * 1000 - Date.now();
|
|
581
|
+
const warnKey = `${sessionKey}-warning`;
|
|
582
|
+
// Replace any prior timers for this session
|
|
583
|
+
timers.clearKey(expiryTimeoutsRef.current, sessionKey);
|
|
584
|
+
timers.clearKey(expiryTimeoutsRef.current, warnKey);
|
|
585
|
+
const now = Date.now();
|
|
586
|
+
const expiryMs = expiry * 1000;
|
|
587
|
+
const timeUntilExpiry = expiryMs - now;
|
|
471
588
|
const beforeExpiry = async () => {
|
|
472
589
|
const activeSession = await getSession();
|
|
473
|
-
if (!activeSession && expiryTimeoutsRef.current[
|
|
474
|
-
|
|
475
|
-
expiryTimeoutsRef.current
|
|
590
|
+
if (!activeSession && expiryTimeoutsRef.current[warnKey]) {
|
|
591
|
+
// Keep nudging until session materializes (short 10s timer is fine)
|
|
592
|
+
timers.setTimeoutInMap(expiryTimeoutsRef.current, warnKey, beforeExpiry, 10_000);
|
|
476
593
|
return;
|
|
477
594
|
}
|
|
478
595
|
const session = await getSession({
|
|
@@ -500,27 +617,36 @@ const ClientProvider = ({
|
|
|
500
617
|
if ((await getActiveSessionKey()) === sessionKey) {
|
|
501
618
|
setSession(undefined);
|
|
502
619
|
}
|
|
503
|
-
setAllSessions(
|
|
504
|
-
if (!
|
|
505
|
-
const
|
|
506
|
-
...
|
|
620
|
+
setAllSessions(prev => {
|
|
621
|
+
if (!prev) return prev;
|
|
622
|
+
const next = {
|
|
623
|
+
...prev
|
|
507
624
|
};
|
|
508
|
-
delete
|
|
509
|
-
return
|
|
625
|
+
delete next[sessionKey];
|
|
626
|
+
return next;
|
|
510
627
|
});
|
|
511
628
|
await clearSession({
|
|
512
629
|
sessionKey
|
|
513
630
|
});
|
|
514
|
-
|
|
515
|
-
|
|
631
|
+
// Remove timers for this session
|
|
632
|
+
timers.clearKey(expiryTimeoutsRef.current, sessionKey);
|
|
633
|
+
timers.clearKey(expiryTimeoutsRef.current, warnKey);
|
|
516
634
|
await logout();
|
|
517
635
|
};
|
|
518
|
-
|
|
519
|
-
|
|
636
|
+
// Already expired → expire immediately
|
|
637
|
+
if (timeUntilExpiry <= 0) {
|
|
638
|
+
await expireSession();
|
|
639
|
+
return;
|
|
640
|
+
}
|
|
641
|
+
// Warning timer (if threshold is in the future)
|
|
642
|
+
const warnAt = expiryMs - utils.SESSION_WARNING_THRESHOLD_MS;
|
|
643
|
+
if (warnAt <= now) {
|
|
644
|
+
void beforeExpiry(); // fire-and-forget is fine
|
|
520
645
|
} else {
|
|
521
|
-
expiryTimeoutsRef.current
|
|
646
|
+
timers.setCappedTimeoutInMap(expiryTimeoutsRef.current, warnKey, beforeExpiry, warnAt - now);
|
|
522
647
|
}
|
|
523
|
-
|
|
648
|
+
// Actual expiry timer (safe for long delays)
|
|
649
|
+
timers.setCappedTimeoutInMap(expiryTimeoutsRef.current, sessionKey, expireSession, timeUntilExpiry);
|
|
524
650
|
} catch (error) {
|
|
525
651
|
if (error instanceof sdkTypes.TurnkeyError || error instanceof sdkTypes.TurnkeyNetworkError) {
|
|
526
652
|
callbacks?.onError?.(error);
|
|
@@ -530,25 +656,25 @@ const ClientProvider = ({
|
|
|
530
656
|
}
|
|
531
657
|
}
|
|
532
658
|
/**
|
|
533
|
-
* Clears all scheduled session
|
|
659
|
+
* Clears all scheduled session timers (warning + expiry).
|
|
534
660
|
*
|
|
535
|
-
* -
|
|
536
|
-
* -
|
|
537
|
-
* - All timeouts stored in `expiryTimeoutsRef` are cleared and the reference is reset.
|
|
661
|
+
* - Removes all active timers managed by this client.
|
|
662
|
+
* - Useful on re-init or logout to avoid stale timers.
|
|
538
663
|
*
|
|
539
|
-
* @throws {TurnkeyError} If an error occurs while clearing the
|
|
664
|
+
* @throws {TurnkeyError} If an error occurs while clearing the timers.
|
|
540
665
|
*/
|
|
541
|
-
function clearSessionTimeouts() {
|
|
666
|
+
function clearSessionTimeouts(sessionKeys) {
|
|
542
667
|
try {
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
}
|
|
546
|
-
|
|
668
|
+
if (sessionKeys) {
|
|
669
|
+
timers.clearKeys(expiryTimeoutsRef.current, sessionKeys);
|
|
670
|
+
} else {
|
|
671
|
+
timers.clearAll(expiryTimeoutsRef.current); // clears & deletes everything
|
|
672
|
+
}
|
|
547
673
|
} catch (error) {
|
|
548
674
|
if (error instanceof sdkTypes.TurnkeyError || error instanceof sdkTypes.TurnkeyNetworkError) {
|
|
549
675
|
callbacks?.onError?.(error);
|
|
550
676
|
} else {
|
|
551
|
-
callbacks?.onError?.(new sdkTypes.TurnkeyError(
|
|
677
|
+
callbacks?.onError?.(new sdkTypes.TurnkeyError("Failed to clear session timeouts", sdkTypes.TurnkeyErrorCodes.CLEAR_SESSION_TIMEOUTS_ERROR, error));
|
|
552
678
|
}
|
|
553
679
|
}
|
|
554
680
|
}
|
|
@@ -564,7 +690,12 @@ const ClientProvider = ({
|
|
|
564
690
|
* @returns A void promise.
|
|
565
691
|
* @throws {TurnkeyError} If the client is not initialized or if there is an error during the process.
|
|
566
692
|
*/
|
|
567
|
-
const handlePostAuth = async
|
|
693
|
+
const handlePostAuth = async params => {
|
|
694
|
+
const {
|
|
695
|
+
method,
|
|
696
|
+
action,
|
|
697
|
+
identifier
|
|
698
|
+
} = params;
|
|
568
699
|
try {
|
|
569
700
|
const sessionKey = await getActiveSessionKey();
|
|
570
701
|
const session = await getSession({
|
|
@@ -581,6 +712,12 @@ const ClientProvider = ({
|
|
|
581
712
|
setAllSessions(allSessions);
|
|
582
713
|
await refreshWallets();
|
|
583
714
|
await refreshUser();
|
|
715
|
+
callbacks?.onAuthenticationSuccess?.({
|
|
716
|
+
session,
|
|
717
|
+
method,
|
|
718
|
+
action,
|
|
719
|
+
identifier
|
|
720
|
+
});
|
|
584
721
|
} catch (error) {
|
|
585
722
|
if (error instanceof sdkTypes.TurnkeyError || error instanceof sdkTypes.TurnkeyNetworkError) {
|
|
586
723
|
callbacks?.onError?.(error);
|
|
@@ -594,19 +731,29 @@ const ClientProvider = ({
|
|
|
594
731
|
* Handles the post-logout flow.
|
|
595
732
|
*
|
|
596
733
|
* - This function is called after a successful logout or session clear.
|
|
597
|
-
* - It clears all scheduled session expiration and warning timeouts to prevent memory leaks.
|
|
598
|
-
* - It resets the session state, removes
|
|
734
|
+
* - It clears all scheduled session expiration and warning timeouts associated to the session key to prevent memory leaks.
|
|
735
|
+
* - It resets the session state, removes user data from memory, the logged out session from all sessions state, and clears the wallets list.
|
|
599
736
|
* - This ensures that all sensitive information is removed from the provider state after logout.
|
|
600
737
|
* - Called internally after logout or when all sessions are cleared.
|
|
601
738
|
*
|
|
602
739
|
* @returns void
|
|
603
740
|
* @throws {TurnkeyError} If there is an error during the post-logout process.
|
|
604
741
|
*/
|
|
605
|
-
const handlePostLogout =
|
|
742
|
+
const handlePostLogout = sessionKey => {
|
|
606
743
|
try {
|
|
607
|
-
clearSessionTimeouts();
|
|
744
|
+
clearSessionTimeouts(sessionKey ? [sessionKey, `${sessionKey}-warning`] : undefined);
|
|
745
|
+
setAllSessions(prev => {
|
|
746
|
+
if (!prev) return prev;
|
|
747
|
+
if (sessionKey) {
|
|
748
|
+
const next = {
|
|
749
|
+
...prev
|
|
750
|
+
};
|
|
751
|
+
delete next[sessionKey];
|
|
752
|
+
return next;
|
|
753
|
+
}
|
|
754
|
+
return {};
|
|
755
|
+
});
|
|
608
756
|
setSession(undefined);
|
|
609
|
-
setAllSessions(undefined);
|
|
610
757
|
setUser(undefined);
|
|
611
758
|
setWallets([]);
|
|
612
759
|
} catch (error) {
|
|
@@ -625,8 +772,14 @@ const ClientProvider = ({
|
|
|
625
772
|
if (!client) {
|
|
626
773
|
throw new sdkTypes.TurnkeyError("Client is not initialized.", sdkTypes.TurnkeyErrorCodes.CLIENT_NOT_INITIALIZED);
|
|
627
774
|
}
|
|
628
|
-
await utils.withTurnkeyErrorHandling(() =>
|
|
629
|
-
|
|
775
|
+
await utils.withTurnkeyErrorHandling(async () => {
|
|
776
|
+
// If no sessionKey is provided, we try to get the active one.
|
|
777
|
+
let sessionKey = params?.sessionKey;
|
|
778
|
+
if (!sessionKey) sessionKey = await getActiveSessionKey();
|
|
779
|
+
await client.logout(params);
|
|
780
|
+
// We only handle post logout if the sessionKey is defined since that means we actually logged out of a session.
|
|
781
|
+
if (sessionKey) handlePostLogout(sessionKey);
|
|
782
|
+
}, callbacks, "Failed to logout");
|
|
630
783
|
return;
|
|
631
784
|
}, [client, callbacks]);
|
|
632
785
|
const loginWithPasskey = react.useCallback(async params => {
|
|
@@ -639,7 +792,11 @@ const ClientProvider = ({
|
|
|
639
792
|
expirationSeconds
|
|
640
793
|
}), callbacks, "Failed to login with passkey");
|
|
641
794
|
if (res) {
|
|
642
|
-
await handlePostAuth(
|
|
795
|
+
await handlePostAuth({
|
|
796
|
+
method: base.AuthMethod.Passkey,
|
|
797
|
+
action: sdkTypes.AuthAction.LOGIN,
|
|
798
|
+
identifier: res.credentialId
|
|
799
|
+
});
|
|
643
800
|
}
|
|
644
801
|
return res;
|
|
645
802
|
}, [client, callbacks]);
|
|
@@ -674,7 +831,11 @@ const ClientProvider = ({
|
|
|
674
831
|
expirationSeconds
|
|
675
832
|
}), callbacks, "Failed to sign up with passkey");
|
|
676
833
|
if (res) {
|
|
677
|
-
await handlePostAuth(
|
|
834
|
+
await handlePostAuth({
|
|
835
|
+
method: base.AuthMethod.Passkey,
|
|
836
|
+
action: sdkTypes.AuthAction.SIGNUP,
|
|
837
|
+
identifier: res.credentialId
|
|
838
|
+
});
|
|
678
839
|
}
|
|
679
840
|
return res;
|
|
680
841
|
}, [client, callbacks]);
|
|
@@ -705,7 +866,7 @@ const ClientProvider = ({
|
|
|
705
866
|
await client.disconnectWalletAccount(walletProvider);
|
|
706
867
|
// we only refresh the wallets if:
|
|
707
868
|
// 1. there is an active session. This is needed because for WalletConnect
|
|
708
|
-
// you can
|
|
869
|
+
// you can disconnect a wallet before actually being logged in
|
|
709
870
|
//
|
|
710
871
|
// 2. it was a WalletConnect provider that we just disconnected. Since
|
|
711
872
|
// native providers emit a disconnect event which will already refresh
|
|
@@ -734,7 +895,11 @@ const ClientProvider = ({
|
|
|
734
895
|
expirationSeconds
|
|
735
896
|
}), callbacks, "Failed to login with wallet");
|
|
736
897
|
if (res) {
|
|
737
|
-
await handlePostAuth(
|
|
898
|
+
await handlePostAuth({
|
|
899
|
+
method: base.AuthMethod.Wallet,
|
|
900
|
+
action: sdkTypes.AuthAction.LOGIN,
|
|
901
|
+
identifier: res.address
|
|
902
|
+
});
|
|
738
903
|
}
|
|
739
904
|
return res;
|
|
740
905
|
}, [client, callbacks]);
|
|
@@ -759,7 +924,11 @@ const ClientProvider = ({
|
|
|
759
924
|
expirationSeconds
|
|
760
925
|
}), callbacks, "Failed to sign up with wallet");
|
|
761
926
|
if (res) {
|
|
762
|
-
await handlePostAuth(
|
|
927
|
+
await handlePostAuth({
|
|
928
|
+
method: base.AuthMethod.Wallet,
|
|
929
|
+
action: sdkTypes.AuthAction.SIGNUP,
|
|
930
|
+
identifier: res.address
|
|
931
|
+
});
|
|
763
932
|
}
|
|
764
933
|
return res;
|
|
765
934
|
}, [client, callbacks, masterConfig]);
|
|
@@ -784,7 +953,11 @@ const ClientProvider = ({
|
|
|
784
953
|
expirationSeconds
|
|
785
954
|
}), callbacks, "Failed to login or sign up with wallet");
|
|
786
955
|
if (res) {
|
|
787
|
-
await handlePostAuth(
|
|
956
|
+
await handlePostAuth({
|
|
957
|
+
method: base.AuthMethod.Wallet,
|
|
958
|
+
action: res.action,
|
|
959
|
+
identifier: res.address
|
|
960
|
+
});
|
|
788
961
|
}
|
|
789
962
|
return res;
|
|
790
963
|
}, [client, callbacks, masterConfig]);
|
|
@@ -806,7 +979,11 @@ const ClientProvider = ({
|
|
|
806
979
|
}
|
|
807
980
|
const res = await utils.withTurnkeyErrorHandling(() => client.loginWithOtp(params), callbacks, "Failed to login with OTP");
|
|
808
981
|
if (res) {
|
|
809
|
-
await handlePostAuth(
|
|
982
|
+
await handlePostAuth({
|
|
983
|
+
method: base.AuthMethod.Otp,
|
|
984
|
+
action: sdkTypes.AuthAction.LOGIN,
|
|
985
|
+
identifier: params.verificationToken
|
|
986
|
+
});
|
|
810
987
|
}
|
|
811
988
|
return res;
|
|
812
989
|
}, [client, callbacks]);
|
|
@@ -834,7 +1011,11 @@ const ClientProvider = ({
|
|
|
834
1011
|
};
|
|
835
1012
|
const res = await utils.withTurnkeyErrorHandling(() => client.signUpWithOtp(params), callbacks, "Failed to sign up with OTP");
|
|
836
1013
|
if (res) {
|
|
837
|
-
await handlePostAuth(
|
|
1014
|
+
await handlePostAuth({
|
|
1015
|
+
method: base.AuthMethod.Otp,
|
|
1016
|
+
action: sdkTypes.AuthAction.SIGNUP,
|
|
1017
|
+
identifier: params.verificationToken
|
|
1018
|
+
});
|
|
838
1019
|
}
|
|
839
1020
|
return res;
|
|
840
1021
|
}, [client, callbacks, masterConfig]);
|
|
@@ -862,11 +1043,29 @@ const ClientProvider = ({
|
|
|
862
1043
|
};
|
|
863
1044
|
const res = await utils.withTurnkeyErrorHandling(() => client.completeOtp(params), callbacks, "Failed to complete OTP");
|
|
864
1045
|
if (res) {
|
|
865
|
-
await handlePostAuth(
|
|
1046
|
+
await handlePostAuth({
|
|
1047
|
+
method: base.AuthMethod.Otp,
|
|
1048
|
+
action: res.action,
|
|
1049
|
+
identifier: res.verificationToken
|
|
1050
|
+
});
|
|
866
1051
|
}
|
|
867
1052
|
return res;
|
|
868
1053
|
}, [client, callbacks, masterConfig]);
|
|
869
|
-
const
|
|
1054
|
+
const loginWithOauth = react.useCallback(async params => {
|
|
1055
|
+
if (!client) {
|
|
1056
|
+
throw new sdkTypes.TurnkeyError("Client is not initialized.", sdkTypes.TurnkeyErrorCodes.CLIENT_NOT_INITIALIZED);
|
|
1057
|
+
}
|
|
1058
|
+
const res = await utils.withTurnkeyErrorHandling(() => client.loginWithOauth(params), callbacks, "Failed to login with OAuth");
|
|
1059
|
+
if (res) {
|
|
1060
|
+
await handlePostAuth({
|
|
1061
|
+
method: base.AuthMethod.Oauth,
|
|
1062
|
+
action: sdkTypes.AuthAction.LOGIN,
|
|
1063
|
+
identifier: params.oidcToken
|
|
1064
|
+
});
|
|
1065
|
+
}
|
|
1066
|
+
return res;
|
|
1067
|
+
}, [client, callbacks]);
|
|
1068
|
+
const signUpWithOauth = react.useCallback(async params => {
|
|
870
1069
|
if (!client) {
|
|
871
1070
|
throw new sdkTypes.TurnkeyError("Client is not initialized.", sdkTypes.TurnkeyErrorCodes.CLIENT_NOT_INITIALIZED);
|
|
872
1071
|
}
|
|
@@ -874,30 +1073,24 @@ const ClientProvider = ({
|
|
|
874
1073
|
throw new sdkTypes.TurnkeyError("Config is not ready yet!", sdkTypes.TurnkeyErrorCodes.INVALID_CONFIGURATION);
|
|
875
1074
|
}
|
|
876
1075
|
// If createSubOrgParams is not provided, use the default from masterConfig
|
|
877
|
-
|
|
1076
|
+
let createSubOrgParams = params.createSubOrgParams ?? masterConfig.auth?.createSuborgParams?.oauth;
|
|
878
1077
|
params = createSubOrgParams !== undefined ? {
|
|
879
1078
|
...params,
|
|
880
1079
|
createSubOrgParams
|
|
881
1080
|
} : {
|
|
882
1081
|
...params
|
|
883
1082
|
};
|
|
884
|
-
const res = await utils.withTurnkeyErrorHandling(() => client.
|
|
1083
|
+
const res = await utils.withTurnkeyErrorHandling(() => client.signUpWithOauth(params), callbacks, "Failed to sign up with OAuth");
|
|
885
1084
|
if (res) {
|
|
886
|
-
await handlePostAuth(
|
|
1085
|
+
await handlePostAuth({
|
|
1086
|
+
method: base.AuthMethod.Oauth,
|
|
1087
|
+
action: sdkTypes.AuthAction.SIGNUP,
|
|
1088
|
+
identifier: params.oidcToken
|
|
1089
|
+
});
|
|
887
1090
|
}
|
|
888
1091
|
return res;
|
|
889
1092
|
}, [client, callbacks, masterConfig]);
|
|
890
|
-
const
|
|
891
|
-
if (!client) {
|
|
892
|
-
throw new sdkTypes.TurnkeyError("Client is not initialized.", sdkTypes.TurnkeyErrorCodes.CLIENT_NOT_INITIALIZED);
|
|
893
|
-
}
|
|
894
|
-
const res = await utils.withTurnkeyErrorHandling(() => client.loginWithOauth(params), callbacks, "Failed to login with OAuth");
|
|
895
|
-
if (res) {
|
|
896
|
-
await handlePostAuth();
|
|
897
|
-
}
|
|
898
|
-
return res;
|
|
899
|
-
}, [client, callbacks]);
|
|
900
|
-
const signUpWithOauth = react.useCallback(async params => {
|
|
1093
|
+
const completeOauth = react.useCallback(async params => {
|
|
901
1094
|
if (!client) {
|
|
902
1095
|
throw new sdkTypes.TurnkeyError("Client is not initialized.", sdkTypes.TurnkeyErrorCodes.CLIENT_NOT_INITIALIZED);
|
|
903
1096
|
}
|
|
@@ -905,16 +1098,20 @@ const ClientProvider = ({
|
|
|
905
1098
|
throw new sdkTypes.TurnkeyError("Config is not ready yet!", sdkTypes.TurnkeyErrorCodes.INVALID_CONFIGURATION);
|
|
906
1099
|
}
|
|
907
1100
|
// If createSubOrgParams is not provided, use the default from masterConfig
|
|
908
|
-
|
|
1101
|
+
const createSubOrgParams = params.createSubOrgParams ?? masterConfig.auth?.createSuborgParams?.oauth;
|
|
909
1102
|
params = createSubOrgParams !== undefined ? {
|
|
910
1103
|
...params,
|
|
911
1104
|
createSubOrgParams
|
|
912
1105
|
} : {
|
|
913
1106
|
...params
|
|
914
1107
|
};
|
|
915
|
-
const res = await utils.withTurnkeyErrorHandling(() => client.
|
|
1108
|
+
const res = await utils.withTurnkeyErrorHandling(() => client.completeOauth(params), callbacks, "Failed to complete OAuth");
|
|
916
1109
|
if (res) {
|
|
917
|
-
await handlePostAuth(
|
|
1110
|
+
await handlePostAuth({
|
|
1111
|
+
method: base.AuthMethod.Oauth,
|
|
1112
|
+
action: res.action,
|
|
1113
|
+
identifier: params.oidcToken
|
|
1114
|
+
});
|
|
918
1115
|
}
|
|
919
1116
|
return res;
|
|
920
1117
|
}, [client, callbacks, masterConfig]);
|
|
@@ -930,6 +1127,12 @@ const ClientProvider = ({
|
|
|
930
1127
|
}
|
|
931
1128
|
return utils.withTurnkeyErrorHandling(() => client.fetchWalletAccounts(params), callbacks, "Failed to fetch wallet accounts");
|
|
932
1129
|
}, [client, callbacks]);
|
|
1130
|
+
const fetchPrivateKeys = react.useCallback(async params => {
|
|
1131
|
+
if (!client) {
|
|
1132
|
+
throw new sdkTypes.TurnkeyError("Client is not initialized.", sdkTypes.TurnkeyErrorCodes.CLIENT_NOT_INITIALIZED);
|
|
1133
|
+
}
|
|
1134
|
+
return utils.withTurnkeyErrorHandling(() => client.fetchPrivateKeys(params), callbacks, "Failed to fetch private keys");
|
|
1135
|
+
}, [client, callbacks]);
|
|
933
1136
|
const signMessage = react.useCallback(async params => {
|
|
934
1137
|
if (!client) throw new sdkTypes.TurnkeyError("Client is not initialized.", sdkTypes.TurnkeyErrorCodes.CLIENT_NOT_INITIALIZED);
|
|
935
1138
|
return utils.withTurnkeyErrorHandling(() => client.signMessage(params), callbacks, "Failed to sign message");
|
|
@@ -941,7 +1144,7 @@ const ClientProvider = ({
|
|
|
941
1144
|
if (!client) throw new sdkTypes.TurnkeyError("Client is not initialized.", sdkTypes.TurnkeyErrorCodes.CLIENT_NOT_INITIALIZED);
|
|
942
1145
|
return new Promise((resolve, reject) => {
|
|
943
1146
|
pushPage({
|
|
944
|
-
key: "Sign
|
|
1147
|
+
key: "Sign message",
|
|
945
1148
|
content: jsxRuntime.jsx(Message.SignMessageModal, {
|
|
946
1149
|
message: params.message,
|
|
947
1150
|
subText: params?.subText,
|
|
@@ -1185,6 +1388,10 @@ const ClientProvider = ({
|
|
|
1185
1388
|
}
|
|
1186
1389
|
await utils.withTurnkeyErrorHandling(() => client.setActiveSession(params), callbacks, "Failed to set active session");
|
|
1187
1390
|
setSession(session);
|
|
1391
|
+
await utils.withTurnkeyErrorHandling(async () => {
|
|
1392
|
+
await refreshWallets();
|
|
1393
|
+
await refreshUser();
|
|
1394
|
+
}, callbacks, "Failed to refresh data after setting active session");
|
|
1188
1395
|
return;
|
|
1189
1396
|
}, [client, callbacks]);
|
|
1190
1397
|
const getActiveSessionKey = react.useCallback(async () => {
|
|
@@ -1229,6 +1436,282 @@ const ClientProvider = ({
|
|
|
1229
1436
|
setWallets(wallets);
|
|
1230
1437
|
}
|
|
1231
1438
|
}, [client, callbacks, getWalletProviders, fetchWallets]);
|
|
1439
|
+
const handleDiscordOauth = react.useCallback(async params => {
|
|
1440
|
+
const {
|
|
1441
|
+
clientId = masterConfig?.auth?.oauthConfig?.discordClientId,
|
|
1442
|
+
openInPage = masterConfig?.auth?.oauthConfig?.openOauthInPage ?? false,
|
|
1443
|
+
additionalState: additionalParameters
|
|
1444
|
+
} = params || {};
|
|
1445
|
+
try {
|
|
1446
|
+
if (!masterConfig) {
|
|
1447
|
+
throw new sdkTypes.TurnkeyError("Config is not ready yet!", sdkTypes.TurnkeyErrorCodes.INVALID_CONFIGURATION);
|
|
1448
|
+
}
|
|
1449
|
+
if (!clientId) {
|
|
1450
|
+
throw new sdkTypes.TurnkeyError("Discord Client ID is not configured.", sdkTypes.TurnkeyErrorCodes.INVALID_CONFIGURATION);
|
|
1451
|
+
}
|
|
1452
|
+
if (!masterConfig.auth?.oauthConfig?.oauthRedirectUri) {
|
|
1453
|
+
throw new sdkTypes.TurnkeyError("OAuth Redirect URI is not configured.", sdkTypes.TurnkeyErrorCodes.INVALID_CONFIGURATION);
|
|
1454
|
+
}
|
|
1455
|
+
const flow = openInPage ? "redirect" : "popup";
|
|
1456
|
+
const redirectURI = masterConfig.auth?.oauthConfig.oauthRedirectUri;
|
|
1457
|
+
// Create key pair and generate nonce
|
|
1458
|
+
const publicKey = await createApiKeyPair();
|
|
1459
|
+
if (!publicKey) {
|
|
1460
|
+
throw new Error("Failed to create public key for OAuth.");
|
|
1461
|
+
}
|
|
1462
|
+
const nonce = utils$1.bytesToHex(sha2.sha256(publicKey));
|
|
1463
|
+
// Generate PKCE challenge pair
|
|
1464
|
+
const {
|
|
1465
|
+
verifier,
|
|
1466
|
+
codeChallenge
|
|
1467
|
+
} = await utils.generateChallengePair();
|
|
1468
|
+
sessionStorage.setItem("discord_verifier", verifier);
|
|
1469
|
+
// Construct Discord Auth URL
|
|
1470
|
+
const discordAuthUrl = new URL(utils.DISCORD_AUTH_URL);
|
|
1471
|
+
discordAuthUrl.searchParams.set("client_id", clientId);
|
|
1472
|
+
discordAuthUrl.searchParams.set("redirect_uri", redirectURI);
|
|
1473
|
+
discordAuthUrl.searchParams.set("response_type", "code");
|
|
1474
|
+
discordAuthUrl.searchParams.set("code_challenge", codeChallenge);
|
|
1475
|
+
discordAuthUrl.searchParams.set("code_challenge_method", "S256");
|
|
1476
|
+
discordAuthUrl.searchParams.set("scope", "identify email");
|
|
1477
|
+
discordAuthUrl.searchParams.set("state", `provider=discord&flow=${flow}&publicKey=${encodeURIComponent(publicKey)}&nonce=${nonce}`);
|
|
1478
|
+
if (additionalParameters) {
|
|
1479
|
+
const extra = Object.entries(additionalParameters).map(([k, v]) => `${encodeURIComponent(k)}=${encodeURIComponent(v)}`).join("&");
|
|
1480
|
+
if (extra) {
|
|
1481
|
+
discordAuthUrl.searchParams.set("state", discordAuthUrl.searchParams.get("state") + `&${extra}`);
|
|
1482
|
+
}
|
|
1483
|
+
}
|
|
1484
|
+
if (openInPage) {
|
|
1485
|
+
window.location.href = discordAuthUrl.toString();
|
|
1486
|
+
return new Promise((_, reject) => {
|
|
1487
|
+
const timeout = setTimeout(() => {
|
|
1488
|
+
reject(new Error("Authentication timed out."));
|
|
1489
|
+
}, 300000);
|
|
1490
|
+
window.addEventListener("beforeunload", () => clearTimeout(timeout));
|
|
1491
|
+
});
|
|
1492
|
+
} else {
|
|
1493
|
+
const width = utils.popupWidth;
|
|
1494
|
+
const height = utils.popupHeight;
|
|
1495
|
+
const left = window.screenX + (window.innerWidth - width) / 2;
|
|
1496
|
+
const top = window.screenY + (window.innerHeight - height) / 2;
|
|
1497
|
+
const authWindow = window.open("about:blank", "_blank", `width=${width},height=${height},top=${top},left=${left},scrollbars=yes,resizable=yes`);
|
|
1498
|
+
if (!authWindow) {
|
|
1499
|
+
throw new Error("Failed to open Discord login window.");
|
|
1500
|
+
}
|
|
1501
|
+
authWindow.location.href = discordAuthUrl.toString();
|
|
1502
|
+
return new Promise((resolve, reject) => {
|
|
1503
|
+
const interval = setInterval(() => {
|
|
1504
|
+
try {
|
|
1505
|
+
if (authWindow.closed) {
|
|
1506
|
+
clearInterval(interval);
|
|
1507
|
+
reject(new Error("Authentication window was closed."));
|
|
1508
|
+
return;
|
|
1509
|
+
}
|
|
1510
|
+
const url = authWindow.location.href || "";
|
|
1511
|
+
if (url.startsWith(window.location.origin)) {
|
|
1512
|
+
const urlParams = new URLSearchParams(new URL(url).search);
|
|
1513
|
+
const authCode = urlParams.get("code");
|
|
1514
|
+
const stateParam = urlParams.get("state");
|
|
1515
|
+
const sessionKey = stateParam?.split("&").find(param => param.startsWith("sessionKey="))?.split("=")[1];
|
|
1516
|
+
if (authCode && stateParam && stateParam.includes("provider=discord")) {
|
|
1517
|
+
authWindow.close();
|
|
1518
|
+
clearInterval(interval);
|
|
1519
|
+
const verifier = sessionStorage.getItem("discord_verifier");
|
|
1520
|
+
if (!verifier) {
|
|
1521
|
+
reject(new Error("Missing PKCE verifier"));
|
|
1522
|
+
return;
|
|
1523
|
+
}
|
|
1524
|
+
client?.httpClient.proxyOAuth2Authenticate({
|
|
1525
|
+
provider: "OAUTH2_PROVIDER_DISCORD",
|
|
1526
|
+
authCode,
|
|
1527
|
+
redirectUri: redirectURI,
|
|
1528
|
+
codeVerifier: verifier,
|
|
1529
|
+
nonce: nonce
|
|
1530
|
+
}).then(resp => {
|
|
1531
|
+
sessionStorage.removeItem("discord_verifier");
|
|
1532
|
+
const oidcToken = resp.oidcToken;
|
|
1533
|
+
if (params?.onOauthSuccess) {
|
|
1534
|
+
params.onOauthSuccess({
|
|
1535
|
+
oidcToken,
|
|
1536
|
+
providerName: "discord",
|
|
1537
|
+
...(sessionKey && {
|
|
1538
|
+
sessionKey
|
|
1539
|
+
})
|
|
1540
|
+
});
|
|
1541
|
+
} else if (callbacks?.onOauthRedirect) {
|
|
1542
|
+
callbacks.onOauthRedirect({
|
|
1543
|
+
idToken: oidcToken,
|
|
1544
|
+
publicKey,
|
|
1545
|
+
...(sessionKey && {
|
|
1546
|
+
sessionKey
|
|
1547
|
+
})
|
|
1548
|
+
});
|
|
1549
|
+
} else {
|
|
1550
|
+
completeOauth({
|
|
1551
|
+
oidcToken,
|
|
1552
|
+
publicKey,
|
|
1553
|
+
providerName: "discord",
|
|
1554
|
+
...(sessionKey && {
|
|
1555
|
+
sessionKey
|
|
1556
|
+
})
|
|
1557
|
+
}).then(() => resolve()).catch(reject);
|
|
1558
|
+
return;
|
|
1559
|
+
}
|
|
1560
|
+
resolve();
|
|
1561
|
+
}).catch(reject);
|
|
1562
|
+
}
|
|
1563
|
+
}
|
|
1564
|
+
} catch {
|
|
1565
|
+
// ignore cross-origin
|
|
1566
|
+
}
|
|
1567
|
+
}, 500);
|
|
1568
|
+
if (authWindow.closed) {
|
|
1569
|
+
clearInterval(interval);
|
|
1570
|
+
}
|
|
1571
|
+
});
|
|
1572
|
+
}
|
|
1573
|
+
} catch (error) {
|
|
1574
|
+
throw error;
|
|
1575
|
+
}
|
|
1576
|
+
}, [client, callbacks]);
|
|
1577
|
+
const handleXOauth = react.useCallback(async params => {
|
|
1578
|
+
const {
|
|
1579
|
+
clientId = masterConfig?.auth?.oauthConfig?.xClientId,
|
|
1580
|
+
openInPage = masterConfig?.auth?.oauthConfig?.openOauthInPage ?? false,
|
|
1581
|
+
additionalState: additionalParameters
|
|
1582
|
+
} = params || {};
|
|
1583
|
+
try {
|
|
1584
|
+
if (!masterConfig) {
|
|
1585
|
+
throw new sdkTypes.TurnkeyError("Config is not ready yet!", sdkTypes.TurnkeyErrorCodes.INVALID_CONFIGURATION);
|
|
1586
|
+
}
|
|
1587
|
+
if (!clientId) {
|
|
1588
|
+
throw new sdkTypes.TurnkeyError("Twitter Client ID is not configured.", sdkTypes.TurnkeyErrorCodes.INVALID_CONFIGURATION);
|
|
1589
|
+
}
|
|
1590
|
+
if (!masterConfig.auth?.oauthConfig?.oauthRedirectUri) {
|
|
1591
|
+
throw new sdkTypes.TurnkeyError("OAuth Redirect URI is not configured.", sdkTypes.TurnkeyErrorCodes.INVALID_CONFIGURATION);
|
|
1592
|
+
}
|
|
1593
|
+
const flow = openInPage ? "redirect" : "popup";
|
|
1594
|
+
const redirectURI = masterConfig.auth?.oauthConfig.oauthRedirectUri;
|
|
1595
|
+
// Create key pair and generate nonce
|
|
1596
|
+
const publicKey = await createApiKeyPair();
|
|
1597
|
+
if (!publicKey) {
|
|
1598
|
+
throw new Error("Failed to create public key for OAuth.");
|
|
1599
|
+
}
|
|
1600
|
+
const nonce = utils$1.bytesToHex(sha2.sha256(publicKey));
|
|
1601
|
+
// Generate PKCE challenge pair
|
|
1602
|
+
const {
|
|
1603
|
+
verifier,
|
|
1604
|
+
codeChallenge
|
|
1605
|
+
} = await utils.generateChallengePair();
|
|
1606
|
+
sessionStorage.setItem("twitter_verifier", verifier);
|
|
1607
|
+
// Construct Twitter Auth URL
|
|
1608
|
+
const twitterAuthUrl = new URL(utils.X_AUTH_URL);
|
|
1609
|
+
twitterAuthUrl.searchParams.set("client_id", clientId);
|
|
1610
|
+
twitterAuthUrl.searchParams.set("redirect_uri", redirectURI);
|
|
1611
|
+
twitterAuthUrl.searchParams.set("response_type", "code");
|
|
1612
|
+
twitterAuthUrl.searchParams.set("code_challenge", codeChallenge);
|
|
1613
|
+
twitterAuthUrl.searchParams.set("code_challenge_method", "S256");
|
|
1614
|
+
twitterAuthUrl.searchParams.set("scope", "tweet.read users.read");
|
|
1615
|
+
twitterAuthUrl.searchParams.set("state", `provider=twitter&flow=${flow}&publicKey=${encodeURIComponent(publicKey)}&nonce=${nonce}`);
|
|
1616
|
+
if (additionalParameters) {
|
|
1617
|
+
const extra = Object.entries(additionalParameters).map(([k, v]) => `${encodeURIComponent(k)}=${encodeURIComponent(v)}`).join("&");
|
|
1618
|
+
if (extra) {
|
|
1619
|
+
twitterAuthUrl.searchParams.set("state", twitterAuthUrl.searchParams.get("state") + `&${extra}`);
|
|
1620
|
+
}
|
|
1621
|
+
}
|
|
1622
|
+
if (openInPage) {
|
|
1623
|
+
window.location.href = twitterAuthUrl.toString();
|
|
1624
|
+
return new Promise((_, reject) => {
|
|
1625
|
+
const timeout = setTimeout(() => {
|
|
1626
|
+
reject(new Error("Authentication timed out."));
|
|
1627
|
+
}, 300000);
|
|
1628
|
+
window.addEventListener("beforeunload", () => clearTimeout(timeout));
|
|
1629
|
+
});
|
|
1630
|
+
} else {
|
|
1631
|
+
const width = utils.popupWidth;
|
|
1632
|
+
const height = utils.popupHeight;
|
|
1633
|
+
const left = window.screenX + (window.innerWidth - width) / 2;
|
|
1634
|
+
const top = window.screenY + (window.innerHeight - height) / 2;
|
|
1635
|
+
const authWindow = window.open("about:blank", "_blank", `width=${width},height=${height},top=${top},left=${left},scrollbars=yes,resizable=yes`);
|
|
1636
|
+
if (!authWindow) {
|
|
1637
|
+
throw new Error("Failed to open Twitter login window.");
|
|
1638
|
+
}
|
|
1639
|
+
authWindow.location.href = twitterAuthUrl.toString();
|
|
1640
|
+
return new Promise((resolve, reject) => {
|
|
1641
|
+
const interval = setInterval(() => {
|
|
1642
|
+
try {
|
|
1643
|
+
if (authWindow.closed) {
|
|
1644
|
+
clearInterval(interval);
|
|
1645
|
+
reject(new Error("Authentication window was closed."));
|
|
1646
|
+
return;
|
|
1647
|
+
}
|
|
1648
|
+
const url = authWindow.location.href || "";
|
|
1649
|
+
if (url.startsWith(window.location.origin)) {
|
|
1650
|
+
const urlParams = new URLSearchParams(new URL(url).search);
|
|
1651
|
+
const authCode = urlParams.get("code");
|
|
1652
|
+
const stateParam = urlParams.get("state");
|
|
1653
|
+
const sessionKey = stateParam?.split("&").find(param => param.startsWith("sessionKey="))?.split("=")[1];
|
|
1654
|
+
if (authCode && stateParam && stateParam.includes("provider=twitter")) {
|
|
1655
|
+
authWindow.close();
|
|
1656
|
+
clearInterval(interval);
|
|
1657
|
+
const verifier = sessionStorage.getItem("twitter_verifier");
|
|
1658
|
+
if (!verifier) {
|
|
1659
|
+
reject(new Error("Missing PKCE verifier"));
|
|
1660
|
+
return;
|
|
1661
|
+
}
|
|
1662
|
+
client?.httpClient.proxyOAuth2Authenticate({
|
|
1663
|
+
provider: "OAUTH2_PROVIDER_X",
|
|
1664
|
+
authCode,
|
|
1665
|
+
redirectUri: redirectURI,
|
|
1666
|
+
codeVerifier: verifier,
|
|
1667
|
+
nonce
|
|
1668
|
+
}).then(resp => {
|
|
1669
|
+
sessionStorage.removeItem("twitter_verifier");
|
|
1670
|
+
const oidcToken = resp.oidcToken;
|
|
1671
|
+
if (params?.onOauthSuccess) {
|
|
1672
|
+
params.onOauthSuccess({
|
|
1673
|
+
oidcToken,
|
|
1674
|
+
providerName: "twitter",
|
|
1675
|
+
...(sessionKey && {
|
|
1676
|
+
sessionKey
|
|
1677
|
+
})
|
|
1678
|
+
});
|
|
1679
|
+
} else if (callbacks?.onOauthRedirect) {
|
|
1680
|
+
callbacks.onOauthRedirect({
|
|
1681
|
+
idToken: oidcToken,
|
|
1682
|
+
publicKey,
|
|
1683
|
+
...(sessionKey && {
|
|
1684
|
+
sessionKey
|
|
1685
|
+
})
|
|
1686
|
+
});
|
|
1687
|
+
} else {
|
|
1688
|
+
completeOauth({
|
|
1689
|
+
oidcToken,
|
|
1690
|
+
publicKey,
|
|
1691
|
+
providerName: "twitter",
|
|
1692
|
+
...(sessionKey && {
|
|
1693
|
+
sessionKey
|
|
1694
|
+
})
|
|
1695
|
+
}).then(() => resolve()).catch(reject);
|
|
1696
|
+
return;
|
|
1697
|
+
}
|
|
1698
|
+
resolve();
|
|
1699
|
+
}).catch(reject);
|
|
1700
|
+
}
|
|
1701
|
+
}
|
|
1702
|
+
} catch {
|
|
1703
|
+
// ignore cross-origin
|
|
1704
|
+
}
|
|
1705
|
+
}, 500);
|
|
1706
|
+
if (authWindow.closed) {
|
|
1707
|
+
clearInterval(interval);
|
|
1708
|
+
}
|
|
1709
|
+
});
|
|
1710
|
+
}
|
|
1711
|
+
} catch (error) {
|
|
1712
|
+
throw error;
|
|
1713
|
+
}
|
|
1714
|
+
}, [client, callbacks]);
|
|
1232
1715
|
const handleGoogleOauth = react.useCallback(async params => {
|
|
1233
1716
|
const {
|
|
1234
1717
|
clientId = masterConfig?.auth?.oauthConfig?.googleClientId,
|
|
@@ -1309,24 +1792,35 @@ const ClientProvider = ({
|
|
|
1309
1792
|
if (url.startsWith(window.location.origin)) {
|
|
1310
1793
|
const hashParams = new URLSearchParams(url.split("#")[1]);
|
|
1311
1794
|
const idToken = hashParams.get("id_token");
|
|
1795
|
+
const stateParams = hashParams.get("state");
|
|
1796
|
+
const sessionKey = stateParams?.split("&").find(param => param.startsWith("sessionKey="))?.split("=")[1];
|
|
1312
1797
|
if (idToken) {
|
|
1313
1798
|
authWindow.close();
|
|
1314
1799
|
clearInterval(interval);
|
|
1315
1800
|
if (params?.onOauthSuccess) {
|
|
1316
1801
|
params.onOauthSuccess({
|
|
1317
1802
|
oidcToken: idToken,
|
|
1318
|
-
providerName: "google"
|
|
1803
|
+
providerName: "google",
|
|
1804
|
+
...(sessionKey && {
|
|
1805
|
+
sessionKey
|
|
1806
|
+
})
|
|
1319
1807
|
});
|
|
1320
1808
|
} else if (callbacks?.onOauthRedirect) {
|
|
1321
1809
|
callbacks.onOauthRedirect({
|
|
1322
1810
|
idToken,
|
|
1323
|
-
publicKey
|
|
1811
|
+
publicKey,
|
|
1812
|
+
...(sessionKey && {
|
|
1813
|
+
sessionKey
|
|
1814
|
+
})
|
|
1324
1815
|
});
|
|
1325
1816
|
} else {
|
|
1326
1817
|
completeOauth({
|
|
1327
1818
|
oidcToken: idToken,
|
|
1328
1819
|
publicKey,
|
|
1329
|
-
providerName: "google"
|
|
1820
|
+
providerName: "google",
|
|
1821
|
+
...(sessionKey && {
|
|
1822
|
+
sessionKey
|
|
1823
|
+
})
|
|
1330
1824
|
}).then(() => resolve()).catch(reject);
|
|
1331
1825
|
return;
|
|
1332
1826
|
}
|
|
@@ -1422,24 +1916,35 @@ const ClientProvider = ({
|
|
|
1422
1916
|
if (url.startsWith(window.location.origin)) {
|
|
1423
1917
|
const hashParams = new URLSearchParams(url.split("#")[1]);
|
|
1424
1918
|
const idToken = hashParams.get("id_token");
|
|
1919
|
+
const stateParams = hashParams.get("state");
|
|
1920
|
+
const sessionKey = stateParams?.split("&").find(param => param.startsWith("sessionKey="))?.split("=")[1];
|
|
1425
1921
|
if (idToken) {
|
|
1426
1922
|
authWindow.close();
|
|
1427
1923
|
clearInterval(interval);
|
|
1428
1924
|
if (params?.onOauthSuccess) {
|
|
1429
1925
|
params.onOauthSuccess({
|
|
1430
1926
|
oidcToken: idToken,
|
|
1431
|
-
providerName: "apple"
|
|
1927
|
+
providerName: "apple",
|
|
1928
|
+
...(sessionKey && {
|
|
1929
|
+
sessionKey
|
|
1930
|
+
})
|
|
1432
1931
|
});
|
|
1433
1932
|
} else if (callbacks?.onOauthRedirect) {
|
|
1434
1933
|
callbacks.onOauthRedirect({
|
|
1435
1934
|
idToken,
|
|
1436
|
-
publicKey
|
|
1935
|
+
publicKey,
|
|
1936
|
+
...(sessionKey && {
|
|
1937
|
+
sessionKey
|
|
1938
|
+
})
|
|
1437
1939
|
});
|
|
1438
1940
|
} else {
|
|
1439
1941
|
completeOauth({
|
|
1440
1942
|
oidcToken: idToken,
|
|
1441
1943
|
publicKey,
|
|
1442
|
-
providerName: "apple"
|
|
1944
|
+
providerName: "apple",
|
|
1945
|
+
...(sessionKey && {
|
|
1946
|
+
sessionKey
|
|
1947
|
+
})
|
|
1443
1948
|
}).then(() => resolve()).catch(reject);
|
|
1444
1949
|
return;
|
|
1445
1950
|
}
|
|
@@ -1546,6 +2051,7 @@ const ClientProvider = ({
|
|
|
1546
2051
|
const authCode = urlParams.get("code");
|
|
1547
2052
|
const stateParam = urlParams.get("state");
|
|
1548
2053
|
if (authCode && stateParam && stateParam.includes("provider=facebook")) {
|
|
2054
|
+
const sessionKey = stateParam?.split("&").find(param => param.startsWith("sessionKey="))?.split("=")[1];
|
|
1549
2055
|
authWindow.close();
|
|
1550
2056
|
clearInterval(interval);
|
|
1551
2057
|
// Exchange code for token
|
|
@@ -1559,18 +2065,27 @@ const ClientProvider = ({
|
|
|
1559
2065
|
if (params?.onOauthSuccess) {
|
|
1560
2066
|
params.onOauthSuccess({
|
|
1561
2067
|
oidcToken: tokenData.id_token,
|
|
1562
|
-
providerName: "
|
|
2068
|
+
providerName: "facebook",
|
|
2069
|
+
...(sessionKey && {
|
|
2070
|
+
sessionKey
|
|
2071
|
+
})
|
|
1563
2072
|
});
|
|
1564
2073
|
} else if (callbacks?.onOauthRedirect) {
|
|
1565
2074
|
callbacks.onOauthRedirect({
|
|
1566
2075
|
idToken: tokenData.id_token,
|
|
1567
|
-
publicKey
|
|
2076
|
+
publicKey,
|
|
2077
|
+
...(sessionKey && {
|
|
2078
|
+
sessionKey
|
|
2079
|
+
})
|
|
1568
2080
|
});
|
|
1569
2081
|
} else {
|
|
1570
2082
|
completeOauth({
|
|
1571
2083
|
oidcToken: tokenData.id_token,
|
|
1572
2084
|
publicKey,
|
|
1573
|
-
providerName: "facebook"
|
|
2085
|
+
providerName: "facebook",
|
|
2086
|
+
...(sessionKey && {
|
|
2087
|
+
sessionKey
|
|
2088
|
+
})
|
|
1574
2089
|
}).then(() => resolve()).catch(reject);
|
|
1575
2090
|
return;
|
|
1576
2091
|
}
|
|
@@ -1591,10 +2106,12 @@ const ClientProvider = ({
|
|
|
1591
2106
|
throw error;
|
|
1592
2107
|
}
|
|
1593
2108
|
}, [client, callbacks]);
|
|
1594
|
-
const handleLogin = react.useCallback(async
|
|
2109
|
+
const handleLogin = react.useCallback(async params => {
|
|
1595
2110
|
pushPage({
|
|
1596
2111
|
key: "Log in or sign up",
|
|
1597
|
-
content: jsxRuntime.jsx(index.AuthComponent, {
|
|
2112
|
+
content: jsxRuntime.jsx(index.AuthComponent, {
|
|
2113
|
+
sessionKey: params?.sessionKey
|
|
2114
|
+
})
|
|
1598
2115
|
});
|
|
1599
2116
|
}, [pushPage]);
|
|
1600
2117
|
const handleExportWallet = react.useCallback(async params => {
|
|
@@ -1604,7 +2121,7 @@ const ClientProvider = ({
|
|
|
1604
2121
|
stampWith
|
|
1605
2122
|
} = params;
|
|
1606
2123
|
pushPage({
|
|
1607
|
-
key: "Export
|
|
2124
|
+
key: "Export wallet",
|
|
1608
2125
|
content: jsxRuntime.jsx(Export.ExportComponent, {
|
|
1609
2126
|
target: walletId,
|
|
1610
2127
|
exportType: base.ExportType.Wallet,
|
|
@@ -1621,13 +2138,17 @@ const ClientProvider = ({
|
|
|
1621
2138
|
const {
|
|
1622
2139
|
privateKeyId,
|
|
1623
2140
|
targetPublicKey,
|
|
2141
|
+
keyFormat,
|
|
1624
2142
|
stampWith
|
|
1625
2143
|
} = params;
|
|
1626
2144
|
pushPage({
|
|
1627
|
-
key: "Export
|
|
2145
|
+
key: "Export private key",
|
|
1628
2146
|
content: jsxRuntime.jsx(Export.ExportComponent, {
|
|
1629
2147
|
target: privateKeyId,
|
|
1630
2148
|
exportType: base.ExportType.PrivateKey,
|
|
2149
|
+
...(keyFormat !== undefined ? {
|
|
2150
|
+
keyFormat
|
|
2151
|
+
} : {}),
|
|
1631
2152
|
...(targetPublicKey !== undefined ? {
|
|
1632
2153
|
targetPublicKey
|
|
1633
2154
|
} : {}),
|
|
@@ -1641,13 +2162,17 @@ const ClientProvider = ({
|
|
|
1641
2162
|
const {
|
|
1642
2163
|
address,
|
|
1643
2164
|
targetPublicKey,
|
|
2165
|
+
keyFormat,
|
|
1644
2166
|
stampWith
|
|
1645
2167
|
} = params;
|
|
1646
2168
|
pushPage({
|
|
1647
|
-
key: "Export
|
|
2169
|
+
key: "Export wallet account",
|
|
1648
2170
|
content: jsxRuntime.jsx(Export.ExportComponent, {
|
|
1649
2171
|
target: address,
|
|
1650
2172
|
exportType: base.ExportType.WalletAccount,
|
|
2173
|
+
...(keyFormat !== undefined ? {
|
|
2174
|
+
keyFormat
|
|
2175
|
+
} : {}),
|
|
1651
2176
|
...(targetPublicKey !== undefined ? {
|
|
1652
2177
|
targetPublicKey
|
|
1653
2178
|
} : {}),
|
|
@@ -1665,8 +2190,9 @@ const ClientProvider = ({
|
|
|
1665
2190
|
} = params || {};
|
|
1666
2191
|
try {
|
|
1667
2192
|
return utils.withTurnkeyErrorHandling(() => new Promise((resolve, reject) => pushPage({
|
|
1668
|
-
key: "Import
|
|
2193
|
+
key: "Import wallet",
|
|
1669
2194
|
content: jsxRuntime.jsx(Import.ImportComponent, {
|
|
2195
|
+
importType: base.ImportType.Wallet,
|
|
1670
2196
|
onError: error => {
|
|
1671
2197
|
reject(error);
|
|
1672
2198
|
},
|
|
@@ -1689,6 +2215,39 @@ const ClientProvider = ({
|
|
|
1689
2215
|
throw new sdkTypes.TurnkeyError("Failed to import wallet.", sdkTypes.TurnkeyErrorCodes.IMPORT_WALLET_ERROR, error);
|
|
1690
2216
|
}
|
|
1691
2217
|
}, [pushPage]);
|
|
2218
|
+
const handleImportPrivateKey = react.useCallback(async params => {
|
|
2219
|
+
const {
|
|
2220
|
+
curve,
|
|
2221
|
+
addressFormats,
|
|
2222
|
+
successPageDuration = 2000,
|
|
2223
|
+
stampWith
|
|
2224
|
+
} = params || {};
|
|
2225
|
+
try {
|
|
2226
|
+
return utils.withTurnkeyErrorHandling(() => new Promise((resolve, reject) => pushPage({
|
|
2227
|
+
key: "Import private key",
|
|
2228
|
+
content: jsxRuntime.jsx(Import.ImportComponent, {
|
|
2229
|
+
importType: base.ImportType.PrivateKey,
|
|
2230
|
+
curve: curve,
|
|
2231
|
+
addressFormats: addressFormats,
|
|
2232
|
+
onError: error => {
|
|
2233
|
+
reject(error);
|
|
2234
|
+
},
|
|
2235
|
+
onSuccess: privateKeyId => resolve(privateKeyId),
|
|
2236
|
+
...(successPageDuration !== undefined && {
|
|
2237
|
+
successPageDuration
|
|
2238
|
+
}),
|
|
2239
|
+
...(stampWith !== undefined && {
|
|
2240
|
+
stampWith
|
|
2241
|
+
})
|
|
2242
|
+
})
|
|
2243
|
+
})));
|
|
2244
|
+
} catch (error) {
|
|
2245
|
+
if (error instanceof sdkTypes.TurnkeyError) {
|
|
2246
|
+
throw error;
|
|
2247
|
+
}
|
|
2248
|
+
throw new sdkTypes.TurnkeyError("Failed to import private key.", sdkTypes.TurnkeyErrorCodes.IMPORT_WALLET_ERROR, error);
|
|
2249
|
+
}
|
|
2250
|
+
}, [pushPage]);
|
|
1692
2251
|
const handleUpdateUserName = react.useCallback(async params => {
|
|
1693
2252
|
const {
|
|
1694
2253
|
successPageDuration = 2000,
|
|
@@ -2320,6 +2879,22 @@ const ClientProvider = ({
|
|
|
2320
2879
|
});
|
|
2321
2880
|
};
|
|
2322
2881
|
switch (providerName) {
|
|
2882
|
+
case sdkTypes.OAuthProviders.DISCORD:
|
|
2883
|
+
{
|
|
2884
|
+
await handleDiscordOauth({
|
|
2885
|
+
openInPage: false,
|
|
2886
|
+
onOauthSuccess
|
|
2887
|
+
});
|
|
2888
|
+
break;
|
|
2889
|
+
}
|
|
2890
|
+
case sdkTypes.OAuthProviders.X:
|
|
2891
|
+
{
|
|
2892
|
+
await handleXOauth({
|
|
2893
|
+
openInPage: false,
|
|
2894
|
+
onOauthSuccess
|
|
2895
|
+
});
|
|
2896
|
+
break;
|
|
2897
|
+
}
|
|
2323
2898
|
case sdkTypes.OAuthProviders.GOOGLE:
|
|
2324
2899
|
{
|
|
2325
2900
|
await handleGoogleOauth({
|
|
@@ -2350,7 +2925,7 @@ const ClientProvider = ({
|
|
|
2350
2925
|
}
|
|
2351
2926
|
}
|
|
2352
2927
|
}, [pushPage]);
|
|
2353
|
-
const
|
|
2928
|
+
const handleConnectExternalWallet = react.useCallback(async params => {
|
|
2354
2929
|
const {
|
|
2355
2930
|
successPageDuration = 2000
|
|
2356
2931
|
} = params || {};
|
|
@@ -2363,8 +2938,8 @@ const ClientProvider = ({
|
|
|
2363
2938
|
}
|
|
2364
2939
|
const providers = await getWalletProviders();
|
|
2365
2940
|
pushPage({
|
|
2366
|
-
key: "
|
|
2367
|
-
content: jsxRuntime.jsx(
|
|
2941
|
+
key: "Connect wallet",
|
|
2942
|
+
content: jsxRuntime.jsx(ConnectWallet.ConnectWalletModal, {
|
|
2368
2943
|
providers: providers,
|
|
2369
2944
|
successPageDuration: successPageDuration
|
|
2370
2945
|
})
|
|
@@ -2563,6 +3138,7 @@ const ClientProvider = ({
|
|
|
2563
3138
|
completeOauth,
|
|
2564
3139
|
fetchWallets,
|
|
2565
3140
|
fetchWalletAccounts,
|
|
3141
|
+
fetchPrivateKeys,
|
|
2566
3142
|
refreshWallets,
|
|
2567
3143
|
signMessage,
|
|
2568
3144
|
signTransaction,
|
|
@@ -2599,12 +3175,15 @@ const ClientProvider = ({
|
|
|
2599
3175
|
getProxyAuthConfig,
|
|
2600
3176
|
handleLogin,
|
|
2601
3177
|
handleGoogleOauth,
|
|
3178
|
+
handleXOauth,
|
|
3179
|
+
handleDiscordOauth,
|
|
2602
3180
|
handleAppleOauth,
|
|
2603
3181
|
handleFacebookOauth,
|
|
2604
3182
|
handleExportWallet,
|
|
2605
3183
|
handleExportPrivateKey,
|
|
2606
3184
|
handleExportWalletAccount,
|
|
2607
3185
|
handleImportWallet,
|
|
3186
|
+
handleImportPrivateKey,
|
|
2608
3187
|
handleUpdateUserEmail,
|
|
2609
3188
|
handleUpdateUserPhoneNumber,
|
|
2610
3189
|
handleUpdateUserName,
|
|
@@ -2615,7 +3194,7 @@ const ClientProvider = ({
|
|
|
2615
3194
|
handleAddEmail,
|
|
2616
3195
|
handleAddPhoneNumber,
|
|
2617
3196
|
handleSignMessage,
|
|
2618
|
-
|
|
3197
|
+
handleConnectExternalWallet,
|
|
2619
3198
|
handleRemoveUserEmail,
|
|
2620
3199
|
handleRemoveUserPhoneNumber
|
|
2621
3200
|
},
|