The biggest change: no more credential bundles
With@turnkey/sdk-react-native, authentication ended with a credential bundle: your app created an embedded key with createEmbeddedKey, your backend ran an auth activity such as OTP_AUTH with that key as the target, and the app decrypted the result with createSession({ bundle }).
@turnkey/react-native-wallet-kit has no bundles. The app generates its own key pair, which never leaves the device. Authentication is bound to that key, and login returns a session JWT for it. The kit stores the session and refreshes it for you.
This changes your authentication code on both the app and, if you have one, your backend. It is more than a package rename.
Sessions are stored differently, so existing sessions are not carried over. Users sign in again after you upgrade.
Install
with-react-native-wallet-kit example app.
New features and improvements
- Auth helpers for every method: email and SMS OTP, passkeys, OAuth (Google, Apple, Facebook, X, Discord), and WalletConnect wallets.
- Optional backend: use Turnkey’s Auth Proxy for signup and login without running your own backend, or keep your backend.
- Session lifecycle management: sessions are stored and refreshed automatically, with
beforeSessionExpiryandonSessionExpiredcallbacks. - Managed state:
user,wallets,session, andauthStateare kept up to date by the provider. - Signing helpers: sign messages and transactions, or sign and broadcast, with a wallet account.
Breaking changes
Provider and hooks
Old approach- Configuration goes in
configand lifecycle hooks incallbacks. onSessionCreated,onSessionSelected,onSessionCleared,onSessionEmpty, andonInitializedhave no direct equivalent. UseonAuthenticationSuccess, or readauthStateandclientStatefrom the hook.clientis replaced byhttpClient. See Other API calls.
Configuration
authProxyConfigId, OTP, OAuth client IDs, and session settings come from the Auth Proxy configuration in the Turnkey dashboard. See Getting started for every option.
Sessions
Authentication
Email and SMS OTP
Old approach The app created an embedded key, your backend initialized OTP and then ranOTP_AUTH with the embedded key as the target, and the app decrypted the returned credential bundle.
completeOtp signs the user up if they do not have a sub-organization yet.
@turnkey/sdk-server, the flow changes on both sides. The code is encrypted on the device, so your backend never sees it, and login is bound to the app’s key pair through a client signature.
- The app calls
createApiKeyPair(). - Your backend calls
initOtp(INIT_OTP_V3).appNameis required. It returnsotpIdandotpEncryptionTargetBundle. - The app encrypts the code with
encryptOtpCodeToBundlefrom@turnkey/crypto. - Your backend calls
verifyOtp(VERIFY_OTP_V2) with the encrypted bundle. It returns averificationToken. - Your backend looks up or creates the user’s sub-organization, as before.
- The app builds the login message with
getClientSignatureMessageForLoginand signs it withsignWithApiKey. - Your backend calls
otpLogin(OTP_LOGIN_V2) on the sub-organization. It returns the session JWT. - The app calls
storeSession.
getClientSignatureMessageForLogin is not re-exported by @turnkey/react-native-wallet-kit. Install @turnkey/core and import it from there.otp-auth/with-backend example implements this flow with @turnkey/react-wallet-kit. The backend is identical for React Native, and the app side differs only in the @turnkey/core import above.
Other changes to the OTP flow:
OTP_AUTHreturned an API key ID and a credential bundle. Neither exists in the new flow.- Email customization moves to the
emailCustomizationparameter ofINIT_OTP_V3. - See the OTP migration guide for the activity changes in detail.
Passkeys
Old approach@turnkey/sdk-react-native exported createPasskey and PasskeyStamper, and you wired signup and login to your backend yourself.
New approach
rpId and associated domains setup.
OAuth
Old approachhandleGoogleOAuth returned an OIDC token through onSuccess, and your backend used it to sign the user up or log them in.
auth.oauth.appScheme and the provider client IDs in your config. Pass onOauthSuccess if you want to receive the OIDC token and complete authentication yourself. See Social logins.
Wallet authentication
This is new. Users can sign in with an external wallet through WalletConnect, usingloginOrSignupWithWallet. It requires walletConfig with a WalletConnect project ID; see the example app for the configuration.
Passkey management
Adding and removing passkeys is new:Wallets
List wallets
Old approach Wallets were nested underuser.wallets.
user is now a v1User, with fields such as userId, userName, and userEmail.
Create wallets and accounts
createWallet now returns the wallet ID instead of an activity, and createWalletAccounts is new.
Export and import
There is no export iframe on React Native.exportWallet decrypts the export on the device and returns the mnemonic to your app, as before, so your app decides how to display it.
exportWalletAccount, exportPrivateKey, and importPrivateKey are also available. See Importing and exporting wallets.
Signing
Old approachwallets, not an address string.
signAndSendTransaction signs and broadcasts in one step. See Signing.
Other API calls
For any API call without a helper, usehttpClient instead of the old client. It stamps requests with the current session, and takes the activity parameters directly instead of the full request envelope.
Old approach
Errors
The kit throwsTurnkeyError with a code from TurnkeyErrorCodes, such as INVALID_OTP_CODE or MAX_OTP_INITIATED_ERROR, instead of raw API errors. Import both from @turnkey/sdk-types. You can also handle every error in one place with the onError callback on TurnkeyProvider.