Overview
If your app previously used Privy’s Swift1.Y.Z SDK, follow the migration guide below to upgrade to 2.0.
Privy’s 2.Y.Z Swift SDK is Swift 6 compliant and adhere’s to the new strict concurrency standards.
We’ve taken this opportunity to also introduce some major API changes, which are outlined below in logical sections.
Initialization
1. App client ID required at initialization
Previously, apps were only required to pass in anappId when initializing the Privy SDK. Now, appClientId is required too. You can retrieve more information on how to retrieve your appClientId here.
Initializing the Privy SDK
2. PrivySdk.initialize can only be called once
It’s important to use a single instance of Privy across the lifetime of your application. Calling PrivySdk.initialize multiple times will result in a fatal error.3. Privy.awaitReady()
When the Privy SDK is first initialized, the user’s authentication state will be set tonotReady until Privy finishes initialization. We’ve added an async privy.awaitReady() function that allows you to await initialization completion. During this time, we suggest you show a loading state to your user.
Calling PrivySDK functions before calling
privy.awaitReady() might result in unexpected
functionality.Authentication
AuthState
TheAuthState represents the authentication state of your user.
Accessing AuthState
The current auth state can be accessed any time viaprivy.authState.
Subscribing to AuthState updates
Auth state updates are exposed viaprivy.authStateStream, which is an AsyncStream.
The PrivyUser
After authenticating a user via any login method, you will receive thePrivyUser object. The PrivyUser represents an authenticated user. All user specific actions, such as creating a wallet or retrieving the user’s access token, are accessed via the PrivyUser.
You may retrieve the PrivyUser anytime by calling privy.user. If this value is non-null, there is an authenticated user. If the value is null, there is no authenticated user.
The PrivyUser can also be retrieved via the associated type of the “authenticated” auth state:
PrivyUser object to:
- Get the user’s ID
- Get the user’s identity token
- Get the user’s access token
- Get the user’s linked accounts
- Get the user’s embedded Ethereum wallets
- Get the user’s embedded Solana wallets
- Create an embedded Ethereum wallet
- Create an embedded Solana wallet
- Refresh the user
- Log the user out
Miscellaneous
Errors
We’ve significantly enhanced our error handling. When an SDK function throws an error, it will be aPrivyError, which contains an errorCode and a localizedDescription.
AuthSession
TheAuthSession is no longer exposed. Values previously available in AuthSession are now available through different methods:
PrivyUser: can be accessed viaprivy.useras described above.accessToken: can be accessed viaprivy.user.getAccessToken(). This method will return the user’s access token, refreshing the session if needed.
Session Refresh
To refresh / update aPrivyUser, you’d previously call privy.refreshSession. Now, trigger the refresh via the PrivyUser, specifically, privyUser.refresh.
Logout
To logout an authenticated user, callawait privyUser.logout() instead of privy.logout(). Once calling logout, the PrivyUser instance is no longer valid.
Linked Accounts
LinkedAccountand its associated types are no longerCodable,Hashable,IdentifiableorEquatable.LinkedAccount.embeddedWalletis now split into chain specific values -LinkedAccount.embeddedEthereumWalletandLinkedAccount.embeddedSolanaWallet- The
chainIdproperty on the embedded wallet linked accounts is removed. firstVerifiedAtandlatestVerifiedAtfields are now optional values.
Other type changes
firstVerifiedAt,latestVerifiedAt, andcreatedAtfields now have typeDateinstead ofTimeIntervalorIntverifiedAtfields now replaced withfirstVerifiedAtandlatestVerifiedAtLoginMethodis no longerEquatable
Login with SMS
- The
OtpFlowStateenum is no longer exposed. You should manually handle state management based on function results. For example, ifLoginWithSms.loginWithCodethrows an error, you can catch the error and update your UI accordingly. LoginWithSms.sendCodenow throws an error if sending code is unsuccessful, instead of returning falseLoginWithSms.loginWithCodenow returnsPrivyUserLoginWithSms.loginWithCodenow requires phone number to be passed in as a parameter (previously was optional)
Login with email
- The
OtpFlowStateenum is no longer exposed. You should manually handle state management based on function results. For example, ifLoginWithEmail.loginWithCodethrows an error, you can catch the error and update your UI accordingly. LoginWithEmail.sendCodenow throws an error if sending code is unsuccessful, instead of returning falseLoginWithEmail.linkWithCodeno longer returns anything, and throws an error if linking failsLoginWithEmail.loginWithCodenow returnsPrivyUserLoginWithEmail.loginWithCodenow requires email to be passed in (no longer optional)
Login with custom auth
LoginWithCustomAccessToken.loginWithCustomAccessTokennow returnsPrivyUser- When initializing the PrivySDK, you should now pass the
TokenProviderthrough thePrivyLoginWithCustomAuthConfigfield in thePrivyConfigobject. This allows Privy to access your user’s access token at initialization while attempting to restore the Privy user’s session.
Login with SIWE
SiweFlowStateenum is no longer exposed. You should manually handle state management based on function results. For example, ifLoginWithSiwe.loginWithSiwethrows an error, you can catch the error and update your UI accordingly.LoginWithSiwe.loginWithSiwenow returnsPrivyUserLoginWithSiwe.loginWithSiwenow requires message and params to be passed in (no longer optional)LoginWithSiwe.linkWithSiweno long returns anything, and throws an error if linking failsLoginWithSiwe.linkWithSiwenow requires message and params to be passed in (no longer optional)
Login with OAuth
- LoginWithOAuth.login now returns
PrivyUser
Embedded wallets
Overview
Previously, all embedded wallet APIs were accessible directly from theprivy.embeddedWallet object, which is no longer available.
All embedded wallet APIs are now available via the PrivyUser instead. This is because all embedded wallet actions require an authenticated user, so adding the methods inside the authenticated PrivyUser was the most logical.
As an example, when creating an Ethereum wallet:
Connecting the wallet
In SDK 1.Y.Z, you had to ensure wallets were connected prior to accessing them by callingprivy.connectWallet(). This method is now removed as we handle connected state internally! You may access the user’s embedded wallets at anytime, without ensuring “wallet connected” state.
Because you no longer need to manage wallet state, EmbeddedWalletState has been removed.
Ethereum vs Solana
Now, all embedded wallet APIs are chain specific and available via thePrivyUser.
Creating a wallet
Ethereum:Retrieving a wallet
Ethereum:Using a wallet / rpc providers
Instead of grabbing the wallet’s provider viatry privy.embeddedWallet.getEthereumProvider(for: wallet.address), the provider is now available directly on the wallet instance. For example:
Ethereum:
Changing the EVM chain
When utilizing theEmbeddedEthereumWalletProvider, you may specify the EVM Chain by calling provider.switchChain. This was previously named provider.configure.
