Skip to main content
This guide walks you through a wallet integration in Swift, from initializing the SDK and authenticating a user to retrieving their wallet address and sending tokens on Base Sepolia.

Before you begin

Install the Rain SDK and configure a Base Sepolia RPC endpoint. All wallet operations in this quickstart run directly in your iOS application. You do not need a Rain API key.
1

Create the provider

RainProvider is the Rain wallet: it owns login, wallet creation, and sessions. The wallet backend’s identity is embedded in the SDK, so the default configuration is the product. Create one provider per app and keep it for the app’s lifetime.
To react to a session that dies and can’t be refreshed, or to enable passkeys, pass a RainWalletConfig:
2

Log in: restore a session or start a login

On launch, wait for the SDK to restore a persisted session. A returning user skips the code entirely.
wallet.authState publishes .loading, .authenticated, or .unauthenticated on every change, and wallet.currentAuthState() is its snapshot, so a login screen can bind to it instead of polling.
3

Send a one-time code

Send a login code to the user’s email address or phone number. The contact is the account’s identity: a first login with it signs the user up, and later logins with the same contact find the same account.
Calling sendLoginCode again for the same contact issues a new code and replaces the pending one, which is how you implement Resend code. A blank email or a phone number that isn’t a valid international number throws RainError.invalidConfig before anything leaves the device.
4

Confirm the code and create the wallet

Pass the code the user typed. On a first login the SDK signs the user up and creates one wallet holding an Ethereum account and a Solana account, from a single seed, in the same request. On a returning login it finds the existing account.
A wrong code keeps the pending challenge, so the user can retype it without requesting a new one. Codes expire after 5 minutes and lock after 3 wrong attempts.
The user is logged in and their wallet exists. A successful login also ends the user’s sessions on other devices; the signed-out device’s onSessionExpired fires on its next call.
5

Build the SDK and resolve the wallet

Register the provider with the chains you want to use and build the SDK. Then resolve the wallet-bound RainClient. Resolution suspends once, while the SDK materializes the wallet, and is cached afterwards.
Resolving before a session is live throws RainError.tokenExpired (RAIN_201). Send the EVM address (and the Solana address, if you use Solana) to your backend: creating the user’s Rain application requires it. See Wallet creation.
6

Send a transaction

Fund the wallet with testnet USDC first (the Circle faucet supports Base Sepolia), then send some of it to another address you control. Amounts are Decimal in human units; the SDK resolves the token’s decimals and converts exactly.
Gas is sponsored by default, so the wallet doesn’t need ETH to send. Native sends use client.sendNative(chainId:to:amount:).
You’ve logged in, created a wallet, and sent a token. Everything else on RainClient follows the same shape: balances and history, receiving funds, and card funding.

Log in with a passkey instead

Users can log in with an existing passkey or add a passkey to their account for future authentication. Configure passkeyDomain during SDK setup. The anchor parameter specifies the window used to display the system passkey prompt.
Use signUpWithPasskey(anchor:) only when creating a new account. Returning users should use loginWithPasskey(anchor:) to access their existing wallet. See Authentication options for additional configuration and recovery guidance.

Log out and clean up

Use logout() to end the user’s session and close() to release SDK resources.
Calling rain.close() permanently closes the SDK instance. Create a new RainSdk instance before the next login. Use rain.reset() instead if you only need to clear resolved clients while keeping the provider active.

Using an existing wallet provider

If your application already uses Portal, Privy, or your own Turnkey organization, register the corresponding provider adapter instead of RainProvider. Authentication and session management remain with your existing provider. Subsequent wallet operations use the same RainClient interface.
For setup instructions and supported capabilities, see Third party wallet providers.

What’s next

Features

What each platform and chain supports.

Testing

Testnets, test tokens, and the pre-go-live checklist.

Error reference

Every RAIN_* code and how to handle it.