> ## 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 Kotlin SDK from 0.3 to 0.4

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

Version 0.4.0 of the Kotlin SDK changes how the active wallet and session are read, replaces the expiry listener with a session change listener, and renames several parameters and types. This page covers the changes most applications need. The [full migration guide](https://github.com/0xsequence/kotlin-sdk/blob/master/MIGRATION.md) lists every change.

## Users sign in once after upgrading

Version 0.4.0 discards sessions saved by 0.3 on load, so each user signs in once after the upgrade.

## Read the active wallet

`omsWallet.wallet.walletAddress` was removed. Read `omsWallet.wallet.activeWallet`, a `Wallet` or `null` when signed out, and branch on its `type` before passing the address to family-specific code.

```kotlin theme={null}
// 0.3
val address = omsWallet.wallet.walletAddress

// 0.4
val activeWallet = omsWallet.wallet.activeWallet
if (activeWallet?.type == WalletType.Ethereum) {
    val ethereumAddress = activeWallet.address
}
```

`WalletActivationResult` and `CompleteAuthResult.WalletSelected` no longer have `walletAddress`; use `result.wallet.address`. Code that creates or destructures them positionally must drop the removed first component.

## Check `session` for `null`

`omsWallet.wallet.session` is now `OMSWalletSession?` (renamed from `OMSWalletSessionState`). In 0.3 it was an object whose fields were `null` when signed out. `session` is non-null exactly when `activeWallet` is, and its `expiresAt` and `auth` are non-null.

```kotlin theme={null}
// 0.3
val email = omsWallet.wallet.session.auth?.email

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

## Replace `onSessionExpired` with `onSessionChange`

`onSessionChange` reports every change of the active wallet or session as an `OMSWalletSessionChangeEvent`: `SignedIn`, `WalletChanged`, `ExpiryUpdated`, `SignedOut`, or `Expired`. `Expired` carries the ended session as `expiredSession`.

```kotlin theme={null}
// 0.3
val unsubscribe = omsWallet.wallet.onSessionExpired { event -> showSignIn(event.session.auth) }

// 0.4
val unsubscribe =
    omsWallet.wallet.onSessionChange { change ->
        if (change is OMSWalletSessionChangeEvent.Expired) showSignIn(change.expiredSession.session.auth)
    }
```

Listeners run on the main thread, always posted after the change, never during the call that made it. See [Sessions and access](https://docs.polygon.technology/wallets/sdk/kotlin/sessions-and-access.md).

## Renamed parameters and types

| 0.3 | 0.4 |
| - | - |
| `WalletSelectionResult` | `WalletActivationResult` |
| `TokenBalancesResult` | `BalancesResult` |
| `OidcRedirectAuthMode` | `OidcAuthMode` |
| `callContract(contract = …)` | `callContract(contractAddress = …)` |
| `TransactionStatusPollingOptions(fastPollIntervalMillis, pollIntervalMillis, timeoutMillis)` | `fastIntervalMs`, `intervalMs`, `timeoutMs` |

Positional arguments moved in three places:

* `sendTransaction(network, to, value, …)` gained `mode` before `waitForStatus`. Name `waitForStatus` if you passed it fourth.
* `signInWithOidcIdToken` takes `walletType` before `walletSelection`.
* `startOidcRedirectAuth` with a custom provider takes `loginHint` before `authorizeParams`.

`WalletType` gained `Tron`, `WalletImportPrivateKey` gained `Tron` and `TronBytes`, and `OMSWalletOperation` and `OMSWalletErrorCode` gained cases. Exhaustive `when` expressions over them need the new branches.

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

Importing a key whose address is already imported now throws `OMSWalletErrorCode.WalletAddressAlreadyImported` instead of `RequestFailed`.

## 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. The default lifetime is now 180 days instead of 7; pass `sessionLifetimeSeconds` for a hard limit. Listen for `ExpiryUpdated` instead of caching the sign-in expiry.
* **The expiry is checked when it passes.** When `expiresAt` passes, a session past its requested lifetime ends at once. Otherwise the SDK asks the wallet API, once the app is in the foreground, and reports `Expired` only if the session ended.
* **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, throws `OMS_REQUEST_FAILED` (or `OMS_SESSION_EXPIRED` when the session has ended) instead of `OMS_TRANSACTION_EXECUTION_UNCONFIRMED`. It was never submitted, so there is nothing to check.
* **`callContract` takes a bare method name.** Pass `"transfer"`, not `"transfer(address,uint256)"`. A full signature now throws `OMSWalletValidationException` 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.
* **Instances of one project share one session.** Every `OMSWallet` for the same project and environment in the process shares the active wallet, sign-out, expiry, and listeners.
