> ## 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.

# React Native sessions and access

> Restore wallet sessions, create or import wallets, issue wallet ID tokens, and manage direct or remote access.

A completed wallet session combines a selected wallet, credential expiry, and authentication metadata. Protected wallet operations require this active session.

## Restore the completed session

The native SDK persists completed sessions. Reuse the single `OMSWallet` instance with the same publishable key when the app starts, then read its state:

```typescript theme={null}
const session = await omsWallet.wallet.getSession()

if (session.walletAddress !== undefined) {
  console.log('Restored wallet:', session.walletAddress)
  console.log('Credential expires:', session.expiresAt)
}
```

`OMSWalletSessionState` contains:

| Field           | Type                   | Meaning     |                                             |
| --------------- | ---------------------- | ----------- | ------------------------------------------- |
| `walletAddress` | \`string               | undefined\` | The selected wallet in a completed session. |
| `expiresAt`     | \`string               | undefined\` | The active credential expiry timestamp.     |
| `auth`          | \`OMSWalletSessionAuth | undefined\` | Email or OIDC authentication metadata.      |

Email metadata contains `type: 'email'` and `email`. OIDC metadata contains `type: 'oidc'`, `flow: 'id-token' | 'redirect'`, `issuer`, and optional provider, label, and email values.

Use `getWalletAddress()` when you only need the selected address:

```typescript theme={null}
const walletAddress = await omsWallet.wallet.getWalletAddress()
```

## Observe expiration

Subscribe where your application owns wallet-session state and remove the subscription during cleanup:

```typescript theme={null}
const subscription = omsWallet.wallet.onSessionExpired((event) => {
  console.log('Expired at:', event.expiredAt)
  console.log('Previous wallet:', event.session.walletAddress)
})

// During cleanup
subscription.remove()
```

The SDK replays the latest expiration event to a listener that subscribes after native expiration. Starting or completing a new authentication flow clears that replay.

## List and activate wallets

An access credential can have multiple wallets. `useWallet` changes the selected wallet for the active session:

```typescript theme={null}
const wallets = await omsWallet.wallet.listWallets()
const selected = wallets[0]

if (selected !== undefined) {
  const active = await omsWallet.wallet.useWallet(selected.id)
  console.log(active.walletAddress, active.wallet.keyOrigin)
}
```

Create and activate another wallet with an optional application reference:

```typescript theme={null}
const active = await omsWallet.wallet.createWallet({
  reference: 'savings',
})

console.log(active.wallet.id, active.walletAddress)
```

Wallet listing, switching, and creation require an active credential. They do not repeat authentication.

Create a Solana wallet with `walletType: 'solana'`:

```typescript theme={null}
const solana = await omsWallet.wallet.createWallet({
  walletType: 'solana',
  reference: 'solana-primary',
})
```

## Import and activate a wallet

```typescript theme={null}
const imported = await omsWallet.wallet.importWallet({
  type: 'ethereum',
  privateKey: '0x...', // Supply the private key from your secure migration flow.
  reference: 'imported-wallet',
})

console.log(imported.wallet.keyOrigin)
```

Ethereum imports accept 32 raw bytes or 64 hexadecimal digits with an optional `0x` prefix. Solana imports accept a 32-byte seed or 64-byte keypair as raw bytes, or the base58 encoding of either. The native SDK encrypts the key locally for the attested import transport and does not persist the plaintext key. Returned wallets identify `keyOrigin` as `'enclave'` or `'imported'`.

Attestation failures reject with SDK error code `OMS_ATTESTATION_VERIFICATION_FAILED`.

<Warning>
  Development uses Nitro debug-mode attestation. Use only disposable test keys in Development. Staging and Production verify against SDK-pinned enclave measurements.
</Warning>

## Issue a wallet ID token

A wallet ID token is short-lived proof for the currently active wallet. It is not the provider ID token used to authenticate and it is not the access credential that authorizes wallet API calls.

```typescript theme={null}
const walletIdToken = await omsWallet.wallet.getIdToken({
  ttlSeconds: 300,
  customClaims: {
    purpose: 'backend-session',
  },
})
```

Send the token to your backend over HTTPS and verify it there. See [backend wallet verification](/wallets/sdk/guides/backend-wallet-verification).

## Inspect access grants

Access grants authorize wallet operations and have their own credential IDs and expiry timestamps. A grant has `type: 'direct'` or `type: 'remote'`; remote grants also include a session ID, display metadata, and bounded smart-session grants. `isCaller` identifies the credential currently authorizing the list request.

For a short list:

```typescript theme={null}
const grants = await omsWallet.wallet.listAccess({
  pageSize: 20,
})

for (const grant of grants) {
  console.log(
    grant.credentialId,
    grant.expiresAt,
    grant.isCaller
  )
  if (grant.type === 'remote') {
    console.log(grant.sessionId, grant.metadata, grant.grants)
  }
}
```

Iterate every page when you need the complete list:

```typescript theme={null}
for await (const page of omsWallet.wallet.listAccessPages({ pageSize: 20 })) {
  for (const grant of page.grants) {
    console.log(grant.credentialId)
  }
}
```

Use `listAccessPage` when your UI owns cursor pagination. Omit `cursor` for the first page, then pass the returned cursor when it is defined:

```typescript theme={null}
const firstPage = await omsWallet.wallet.listAccessPage({ pageSize: 20 })
const cursor = firstPage.page?.cursor

const nextPage =
  cursor === undefined
    ? undefined
    : await omsWallet.wallet.listAccessPage({ pageSize: 20, cursor })
```

## Revoke access safely

Check `isCaller` before revocation. Revoking the caller removes the credential being used for the request and can end the current app's ability to perform protected operations.

```typescript theme={null}
const grants = await omsWallet.wallet.listAccess({ pageSize: 100 })
const target = grants.find((grant) => !grant.isCaller)

if (target === undefined) {
  throw new Error('Credential not found')
}

await omsWallet.wallet.revokeAccess({
  credentialId: target.credentialId,
  sessionId: target.type === 'remote' ? target.sessionId : undefined,
})
```

For a remote grant, `sessionId` is required and revokes exactly that session.

## Authorize remote access

Remote access grants are bounded EVM smart sessions. Inspect the remote credential and show its returned metadata to the wallet owner before requesting approval:

This example uses Polygon Amoy. Grant limits are raw EVM base-unit amounts. A native-transfer limit is cumulative, so `1000000000000000` wei authorizes up to `0.001 POL` across the session.

```typescript theme={null}
import { Networks } from '@polygonlabs/oms-wallet-react-native'

const credentialId = 'REMOTE_CREDENTIAL_ID'
const metadata = await omsWallet.wallet.inspectRemoteCredential({ credentialId })

// Render the returned metadata in your consent UI and continue only after approval.
console.log(metadata.appName, metadata.appUrl)

const session = await omsWallet.wallet.authorizeRemoteAccess({
  credentialId,
  network: Networks.amoy,
  expiresAt: new Date(Date.now() + 60 * 60 * 1000).toISOString(),
  grants: [
    {
      kind: 'nativeTransfer',
      to: '0x1111111111111111111111111111111111111111',
      // Cumulative 0.001 POL limit in wei.
      limit: '1000000000000000',
    },
  ],
})

const details = await omsWallet.wallet.getRemoteAccessSession({
  sessionId: session.sessionId,
})
const usage = await omsWallet.wallet.getRemoteAccessSessionUsage({
  sessionId: session.sessionId,
  network: Networks.amoy,
})
```

WaaS caps the requested session expiry at the remote credential's expiry. Backend credential registration and remote execution are outside the React Native SDK; implement them with the TypeScript SDK's [backend smart sessions guide](/wallets/sdk/guides/backend-smart-sessions).

## Sign out

```typescript theme={null}
await omsWallet.wallet.signOut()
```

Sign-out clears the active local wallet session. It does not revoke other credentials. Use `revokeAccess` to remove access from another credential.
