> ## Documentation Index
> Fetch the complete documentation index at: https://docs.polygon.technology/llms.txt
> Use this file to discover all available pages before exploring further.

# Migrate the React Native SDK from 0.3 to 0.4

> Update an application from the OMS Wallet React Native SDK 0.3 to 0.4.

Version 0.4.0 of the React Native SDK uses version 0.4.0 of the Swift and Kotlin SDKs. It replaces the wallet address and expiry APIs with the active wallet and session change APIs, and adds Tron wallets and claimable wallets. This page covers the changes most applications need. The [full migration guide](https://github.com/0xPolygon/oms-wallet-react-native-sdk/blob/master/MIGRATION.md) lists every change.

## Run `pod install` after upgrading

On iOS, the module now pulls the Swift SDK with Swift Package Manager instead of the `oms-wallet-swift-sdk` pod, which is no longer published to CocoaPods. Run `pod install` after upgrading, and keep the `react_native_post_install` call in your `Podfile`'s `post_install` hook, as in the React Native template; Expo adds it for you. Remove any `pod 'oms-wallet-swift-sdk'` line you added yourself.

## Users sign in once after upgrading

The native SDKs store sessions in a new format and do not restore sessions saved by 0.3, so each user signs in once after the upgrade.

## Read the active wallet

`getWalletAddress()` was removed. Read the active `WalletAccount` from the synchronous `activeWallet` property; it is `undefined` when signed out. Check its `type` before passing the address to chain-specific code.

```typescript theme={null}
// 0.3
const address = await omsWallet.wallet.getWalletAddress()

// 0.4
const activeWallet = omsWallet.wallet.activeWallet
if (activeWallet?.type === 'ethereum') {
  const address = activeWallet.address
}
```

`WalletActivationResult` and `CompleteAuthResult` no longer have `walletAddress`; use `result.wallet.address`.

## Read `session` instead of `getSession()`

`getSession()` was removed. Read the synchronous `session` property, an `OMSWalletSession` (renamed from `OMSWalletSessionState`) or `undefined` when signed out. In 0.3, `getSession()` resolved to an object whose fields were `undefined` when signed out. The session has no `walletAddress`; its `expiresAt` and `auth` are always set, and it is defined exactly when `activeWallet` is.

```typescript theme={null}
// 0.3
const email = (await omsWallet.wallet.getSession()).auth?.email

// 0.4
const email = omsWallet.wallet.session?.auth.email
```

`activeWallet` and `session` are current as soon as a sign-in or wallet change returns, and they return the same frozen objects until the state changes, so React components can read them with `useSyncExternalStore`.

## `new OMSWallet()` throws when the client cannot be created

The constructor now creates the native client synchronously. When that fails, for example for an invalid publishable key, `new OMSWallet()` throws `OMSWalletError` instead of the first call rejecting.

## Replace `onSessionExpired` with `onSessionChange`

`onSessionChange` reports every change of the active wallet or session with a `reason`: `signedIn`, `walletChanged`, `expiryUpdated`, `signedOut`, or `expired`. An `expired` change carries the ended session as `expiredSession`, which replaces `OMSWalletSessionExpiredEvent`.

```typescript theme={null}
// 0.3
omsWallet.wallet.onSessionExpired(({ session }) => showSignIn(session.auth))

// 0.4
const unsubscribe = omsWallet.wallet.onSessionChange((event) => {
  if (event.reason === 'expired') showSignIn(event.expiredSession.session.auth)
})
```

`onSessionChange` returns a function that removes the listener, instead of an `EventSubscription`: call `unsubscribe()` instead of `subscription.remove()`. As before, a listener added while signed out first receives the last `expired` change. See [sessions and access](https://docs.polygon.technology/wallets/sdk/react-native/sessions-and-access.md#keep-your-ui-in-sync).

## Renamed parameters and new cases

`importEncryptedWallet` takes `walletType` instead of `type`, matching `createWallet`:

```typescript theme={null}
// 0.3
await omsWallet.wallet.importEncryptedWallet({ type: 'solana', keyMaterial })

// 0.4
await omsWallet.wallet.importEncryptedWallet({ walletType: 'solana', keyMaterial })
```

`WalletType` and `ImportWalletParams` gained `tron`, and `OMSWalletErrorCode` gained `OMS_WALLET_ADDRESS_ALREADY_IMPORTED`, which importing an already imported address now throws instead of `OMS_REQUEST_FAILED`. Update exhaustive `switch` statements over them.

The `isValid…Signature` methods accept an optional `walletAddress` to verify any wallet, even while signed out. Existing calls are unchanged and still verify against the active wallet.

## Behavior changes

These need no code change to compile, but can change what your application sees:

* **Session expiry extends with use.** `session.expiresAt` is the current expiry, not a fixed end time. An idle session ends about 10 days after its last use, and never after the requested lifetime. Sign-in now requests 180 days instead of 7 when `sessionLifetimeSeconds` is omitted; pass a shorter value for a hard limit. Listen for `expiryUpdated` instead of treating `expiresAt` as final.
* **Rejected credentials end the session.** A wallet call whose credential the wallet API rejects as not found or expired fails with `OMS_SESSION_EXPIRED` instead of `OMS_REQUEST_FAILED`, and the session ends with an `expired` change. When the wallet API cannot be reached, the session is kept and calls fail with `OMS_REQUEST_FAILED`.
* **Signed requests time out after 30 seconds** with `OMS_REQUEST_FAILED`, counting the time spent waiting behind other signed requests, which are now sent one at a time. A transaction that times out after it was sent still fails with `OMS_TRANSACTION_EXECUTION_UNCONFIRMED`: check its status before sending it again.
* **Refused transactions fail as request errors.** A transaction the wallet API refuses before submitting it, for example because simulation shows it would revert, fails with `OMS_REQUEST_FAILED` (or `OMS_SESSION_EXPIRED` when the session has ended) instead of `OMS_TRANSACTION_EXECUTION_UNCONFIRMED`. It was never submitted.
* **`callContract` takes a bare method name.** Pass `'transfer'`, not `'transfer(address,uint256)'`. A full signature now fails with `OMS_VALIDATION_ERROR` before any request.
* **Invalid lifetimes fail early.** A `sessionLifetimeSeconds` that is not an integer from 1 to `MAX_SESSION_LIFETIME_SECONDS` fails with `OMS_VALIDATION_ERROR` on both platforms before any request.
* **Sign-in claims a claimable wallet.** With automatic selection, a user with no wallet of the requested type but a claimable one gets that wallet instead of a new one.
* **iOS keys stay on the device.** On an iOS device, the session signing key is generated in the Secure Enclave, and keychain items are readable only while the device is unlocked and are never restored to another device from a backup.
