@turnkey/react-wallet-kit 2.3.2 → 2.4.1

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.
@@ -95,6 +95,9 @@ const ClientProvider = ({
95
95
  const expiryTimeoutsRef = react.useRef({});
96
96
  const proxyAuthConfigRef = react.useRef(null);
97
97
  const clientParamsRef = react.useRef(null);
98
+ // Stores the developer's custom MFA handler set via setMfaHandler.
99
+ // When unset, the default httpClient MFA behavior is used (no onMfaRequired callback).
100
+ const mfaHandlerRef = react.useRef(undefined);
98
101
  const [allSessions, setAllSessions] = react.useState(undefined);
99
102
  const {
100
103
  isMobile,
@@ -883,6 +886,12 @@ const ClientProvider = ({
883
886
  }
884
887
  return client.overridePasskeyStamper(params);
885
888
  }, [client]);
889
+ const overrideAttestedStamper = react.useCallback(params => {
890
+ if (!client) {
891
+ throw new sdkTypes.TurnkeyError("Client is not initialized.", sdkTypes.TurnkeyErrorCodes.CLIENT_NOT_INITIALIZED);
892
+ }
893
+ return client.overrideAttestedStamper(params);
894
+ }, [client]);
886
895
  const getActiveSessionKey = react.useCallback(async () => {
887
896
  if (!client) throw new sdkTypes.TurnkeyError("Client is not initialized.", sdkTypes.TurnkeyErrorCodes.CLIENT_NOT_INITIALIZED);
888
897
  return utils.withTurnkeyErrorHandling(() => client.getActiveSessionKey(), undefined, callbacks, "Failed to get active session key");
@@ -1367,13 +1376,23 @@ const ClientProvider = ({
1367
1376
  if (!client) {
1368
1377
  throw new sdkTypes.TurnkeyError("Client is not initialized.", sdkTypes.TurnkeyErrorCodes.CLIENT_NOT_INITIALIZED);
1369
1378
  }
1370
- return utils.withTurnkeyErrorHandling(() => client.verifyOtp(params), undefined, callbacks, "Failed to verify OTP");
1379
+ const res = await utils.withTurnkeyErrorHandling(() => client.verifyOtp(params), undefined, callbacks, "Failed to verify OTP");
1380
+ // Automatically override the attested stamper with the verification token
1381
+ await client.overrideAttestedStamper({
1382
+ verificationToken: res.verificationToken,
1383
+ publicKey: res.publicKey
1384
+ });
1385
+ return res;
1371
1386
  }, [client, callbacks]);
1372
1387
  const loginWithOtp = react.useCallback(async params => {
1373
1388
  if (!client) {
1374
1389
  throw new sdkTypes.TurnkeyError("Client is not initialized.", sdkTypes.TurnkeyErrorCodes.CLIENT_NOT_INITIALIZED);
1375
1390
  }
1376
- const res = await utils.withTurnkeyErrorHandling(() => client.loginWithOtp(params), undefined, callbacks, "Failed to login with OTP");
1391
+ const expirationSeconds = params?.expirationSeconds ?? masterConfig?.auth?.sessionExpirationSeconds ?? core.DEFAULT_SESSION_EXPIRATION_IN_SECONDS;
1392
+ const res = await utils.withTurnkeyErrorHandling(() => client.loginWithOtp({
1393
+ ...params,
1394
+ expirationSeconds
1395
+ }), undefined, callbacks, "Failed to login with OTP");
1377
1396
  if (res) {
1378
1397
  await handlePostAuth({
1379
1398
  method: base.AuthMethod.Otp,
@@ -1383,7 +1402,7 @@ const ClientProvider = ({
1383
1402
  });
1384
1403
  }
1385
1404
  return res;
1386
- }, [client, callbacks, handlePostAuth]);
1405
+ }, [client, callbacks, masterConfig, handlePostAuth]);
1387
1406
  const signUpWithOtp = react.useCallback(async params => {
1388
1407
  if (!client) {
1389
1408
  throw new sdkTypes.TurnkeyError("Client is not initialized.", sdkTypes.TurnkeyErrorCodes.CLIENT_NOT_INITIALIZED);
@@ -1454,7 +1473,11 @@ const ClientProvider = ({
1454
1473
  if (!client) {
1455
1474
  throw new sdkTypes.TurnkeyError("Client is not initialized.", sdkTypes.TurnkeyErrorCodes.CLIENT_NOT_INITIALIZED);
1456
1475
  }
1457
- const res = await utils.withTurnkeyErrorHandling(() => client.loginWithOauth(params), undefined, callbacks, "Failed to login with OAuth");
1476
+ const expirationSeconds = params?.expirationSeconds ?? masterConfig?.auth?.sessionExpirationSeconds ?? core.DEFAULT_SESSION_EXPIRATION_IN_SECONDS;
1477
+ const res = await utils.withTurnkeyErrorHandling(() => client.loginWithOauth({
1478
+ ...params,
1479
+ expirationSeconds
1480
+ }), undefined, callbacks, "Failed to login with OAuth");
1458
1481
  if (res) {
1459
1482
  await handlePostAuth({
1460
1483
  method: base.AuthMethod.Oauth,
@@ -1464,7 +1487,7 @@ const ClientProvider = ({
1464
1487
  });
1465
1488
  }
1466
1489
  return res;
1467
- }, [client, callbacks, handlePostAuth]);
1490
+ }, [client, callbacks, masterConfig, handlePostAuth]);
1468
1491
  const signUpWithOauth = react.useCallback(async params => {
1469
1492
  if (!client) {
1470
1493
  throw new sdkTypes.TurnkeyError("Client is not initialized.", sdkTypes.TurnkeyErrorCodes.CLIENT_NOT_INITIALIZED);
@@ -1840,10 +1863,9 @@ const ClientProvider = ({
1840
1863
  }, [client, callbacks, logout, clearSessionTimeouts, masterConfig?.passkeyConfig]);
1841
1864
  const setActiveSession = react.useCallback(async params => {
1842
1865
  if (!client) throw new sdkTypes.TurnkeyError("Client is not initialized.", sdkTypes.TurnkeyErrorCodes.CLIENT_NOT_INITIALIZED);
1843
- const session = await utils.withTurnkeyErrorHandling(() => client.getSession({
1866
+ const s = await getSession({
1844
1867
  sessionKey: params.sessionKey
1845
- }), () => logout(), callbacks, "Failed to get session");
1846
- const s = await getSession();
1868
+ });
1847
1869
  if (!s) {
1848
1870
  throw new sdkTypes.TurnkeyError("Session not found.", sdkTypes.TurnkeyErrorCodes.NOT_FOUND);
1849
1871
  }
@@ -1884,6 +1906,17 @@ const ClientProvider = ({
1884
1906
  if (!client) throw new sdkTypes.TurnkeyError("Client is not initialized.", sdkTypes.TurnkeyErrorCodes.CLIENT_NOT_INITIALIZED);
1885
1907
  return utils.withTurnkeyErrorHandling(() => client.verifyAppProofs(params), () => logout(), callbacks, "Failed to verify app proofs");
1886
1908
  }, [client, callbacks, logout]);
1909
+ const setMfaHandler = react.useCallback(handler => {
1910
+ mfaHandlerRef.current = handler;
1911
+ // Apply immediately if the client is ready.
1912
+ // When a custom handler is set, route the httpClient's MFA callback to it.
1913
+ // When cleared, restore the default httpClient behavior (no onMfaRequired callback).
1914
+ if (client) {
1915
+ client.httpClient.config.onMfaRequired = handler ? async ctx => {
1916
+ await handler(ctx);
1917
+ } : undefined;
1918
+ }
1919
+ }, [client]);
1887
1920
  const handleDiscordOauth = react.useCallback(async params => {
1888
1921
  const {
1889
1922
  primaryClientId = masterConfig?.auth?.oauthConfig?.discord?.primaryClientId,
@@ -1945,7 +1978,7 @@ const ClientProvider = ({
1945
1978
  }
1946
1979
  authWindow.location.href = authUrl;
1947
1980
  return new Promise((resolve, reject) => {
1948
- const interval = setInterval(() => {
1981
+ const interval = setInterval(async () => {
1949
1982
  try {
1950
1983
  if (authWindow.closed) {
1951
1984
  clearInterval(interval);
@@ -1987,7 +2020,15 @@ const ClientProvider = ({
1987
2020
  clientId,
1988
2021
  nonce
1989
2022
  });
1990
- return resp?.oidcToken ?? "";
2023
+ const oidcToken = resp?.oidcToken ?? "";
2024
+ // Set the attested stamper with the oidcToken
2025
+ if (oidcToken) {
2026
+ await client?.overrideAttestedStamper({
2027
+ oidcToken,
2028
+ publicKey
2029
+ });
2030
+ }
2031
+ return oidcToken;
1991
2032
  }
1992
2033
  }).then(() => resolve()).catch(reject);
1993
2034
  }
@@ -2062,7 +2103,7 @@ const ClientProvider = ({
2062
2103
  }
2063
2104
  authWindow.location.href = authUrl;
2064
2105
  return new Promise((resolve, reject) => {
2065
- const interval = setInterval(() => {
2106
+ const interval = setInterval(async () => {
2066
2107
  try {
2067
2108
  if (authWindow.closed) {
2068
2109
  clearInterval(interval);
@@ -2104,7 +2145,15 @@ const ClientProvider = ({
2104
2145
  clientId,
2105
2146
  nonce
2106
2147
  });
2107
- return resp?.oidcToken ?? "";
2148
+ const oidcToken = resp?.oidcToken ?? "";
2149
+ // Set the attested stamper with the oidcToken
2150
+ if (oidcToken) {
2151
+ await client?.overrideAttestedStamper({
2152
+ oidcToken,
2153
+ publicKey
2154
+ });
2155
+ }
2156
+ return oidcToken;
2108
2157
  }
2109
2158
  }).then(() => resolve()).catch(reject);
2110
2159
  }
@@ -2173,7 +2222,7 @@ const ClientProvider = ({
2173
2222
  }
2174
2223
  authWindow.location.href = authUrl;
2175
2224
  return new Promise((resolve, reject) => {
2176
- const interval = setInterval(() => {
2225
+ const interval = setInterval(async () => {
2177
2226
  try {
2178
2227
  if (authWindow.closed) {
2179
2228
  clearInterval(interval);
@@ -2186,6 +2235,13 @@ const ClientProvider = ({
2186
2235
  if (result) {
2187
2236
  authWindow.close();
2188
2237
  clearInterval(interval);
2238
+ // Set the attested stamper with the oidcToken
2239
+ if (result.idToken) {
2240
+ await client?.overrideAttestedStamper({
2241
+ oidcToken: result.idToken,
2242
+ publicKey
2243
+ });
2244
+ }
2189
2245
  completion.completeOAuthPopup({
2190
2246
  provider,
2191
2247
  publicKey,
@@ -2273,7 +2329,7 @@ const ClientProvider = ({
2273
2329
  }
2274
2330
  authWindow.location.href = authUrl;
2275
2331
  return new Promise((resolve, reject) => {
2276
- const interval = setInterval(() => {
2332
+ const interval = setInterval(async () => {
2277
2333
  try {
2278
2334
  if (authWindow.closed) {
2279
2335
  clearInterval(interval);
@@ -2286,6 +2342,13 @@ const ClientProvider = ({
2286
2342
  if (result) {
2287
2343
  authWindow.close();
2288
2344
  clearInterval(interval);
2345
+ // Set the attested stamper with the oidcToken
2346
+ if (result.idToken) {
2347
+ await client?.overrideAttestedStamper({
2348
+ oidcToken: result.idToken,
2349
+ publicKey
2350
+ });
2351
+ }
2289
2352
  completion.completeOAuthPopup({
2290
2353
  provider,
2291
2354
  publicKey,
@@ -2379,7 +2442,7 @@ const ClientProvider = ({
2379
2442
  }
2380
2443
  authWindow.location.href = authUrl;
2381
2444
  return new Promise((resolve, reject) => {
2382
- const interval = setInterval(() => {
2445
+ const interval = setInterval(async () => {
2383
2446
  try {
2384
2447
  if (authWindow.closed) {
2385
2448
  clearInterval(interval);
@@ -2414,7 +2477,15 @@ const ClientProvider = ({
2414
2477
  onOauthSuccess: params?.onOauthSuccess,
2415
2478
  exchangeCodeForToken: async codeVerifier => {
2416
2479
  const tokenData = await pkce.exchangeFacebookCodeForToken(clientId, redirectUri, result.authCode, codeVerifier);
2417
- return tokenData.id_token;
2480
+ const oidcToken = tokenData.id_token;
2481
+ // Set the attested stamper with the oidcToken
2482
+ if (oidcToken) {
2483
+ await client?.overrideAttestedStamper({
2484
+ oidcToken,
2485
+ publicKey
2486
+ });
2487
+ }
2488
+ return oidcToken;
2418
2489
  }
2419
2490
  }).then(() => resolve()).catch(reject);
2420
2491
  }
@@ -4059,8 +4130,8 @@ const ClientProvider = ({
4059
4130
  }
4060
4131
  }, [session]);
4061
4132
  react.useEffect(() => {
4062
- // This will handle any redirect based oAuth. It then initializes the session. This is the last step before client is considered "ready"
4063
4133
  if (!client || !masterConfig) return;
4134
+ // This will handle any redirect based oAuth. It then initializes the session. This is the last step before client is considered "ready"
4064
4135
  completeRedirectOauth().finally(() => {
4065
4136
  clearSessionTimeouts();
4066
4137
  // if auth or wallet connecting features are enabled, we want to fetch
@@ -4073,6 +4144,13 @@ const ClientProvider = ({
4073
4144
  setClientState(base.ClientState.Ready);
4074
4145
  });
4075
4146
  });
4147
+ // Only set the onMfaRequired handler if we have a mfaHandler set.
4148
+ const mfaHandler = mfaHandlerRef.current;
4149
+ if (mfaHandler) {
4150
+ client.httpClient.config.onMfaRequired = async ctx => {
4151
+ await mfaHandler(ctx);
4152
+ };
4153
+ }
4076
4154
  return () => {
4077
4155
  clearSessionTimeouts();
4078
4156
  };
@@ -4091,6 +4169,7 @@ const ClientProvider = ({
4091
4169
  createHttpClient,
4092
4170
  overrideApiKeyStamper,
4093
4171
  overridePasskeyStamper,
4172
+ overrideAttestedStamper,
4094
4173
  createPasskey,
4095
4174
  logout,
4096
4175
  loginWithPasskey,
@@ -4186,6 +4265,7 @@ const ClientProvider = ({
4186
4265
  handleOnRamp,
4187
4266
  handleSendTransaction,
4188
4267
  handleSendErc20Transfer,
4268
+ setMfaHandler,
4189
4269
  getTurnstileToken,
4190
4270
  setTurnstileToken
4191
4271
  },