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

# TypeScript sessions and access

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

An active session binds the local credential to one selected wallet. Authentication can return several wallets, but `omsWallet.wallet` exposes one active `walletAddress` at a time.

## Read and restore session state

Create `OMSWallet` with the same publishable key and storage configuration on each application load. The constructor synchronously restores unexpired session metadata. Protected wallet operations also verify the corresponding signer credential.

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

const omsWallet = new OMSWallet({
  publishableKey: 'YOUR_PUBLISHABLE_KEY',
})

const { walletAddress, expiresAt, auth } = omsWallet.wallet.session

if (walletAddress) {
  console.log('Restored wallet:', walletAddress)
  console.log('Credential expires:', expiresAt)
  console.log('Authentication:', auth)
}
```

`wallet.session` is a read-only snapshot:

* `walletAddress` and `expiresAt` are defined only for an active session.
* Email auth metadata is `{ type: 'email', email }`.
* OIDC metadata is `{ type: 'oidc', flow, issuer, provider, providerLabel, email }`. Optional provider fields can be `undefined`.

The stored record is scoped to the publishable-key project and API environment. Restoration also requires the same local signer credential ID and signing algorithm.

## Understand storage defaults

Browser defaults use separate storage for completed sessions and pending redirects:

* Completed session metadata uses `localStorage`.
* The default non-extractable WebCrypto P-256 signer stores its credential in IndexedDB.
* Temporary OIDC verifier and state data use `sessionStorage`.

Outside a browser, completed session metadata defaults to in-memory storage, so it does not survive a process restart. Redirect storage has no non-browser default. Pass `redirectAuthStorage` before calling any redirect auth method, and make sure it remains available to the callback process.

For a non-browser runtime, provide application-owned implementations of the public `StorageManager` and `CredentialSigner` interfaces through the `storage`, `redirectAuthStorage`, and `credentialSigner` constructor options. See the [package API reference](/wallets/sdk/typescript/api-reference) for their exact contracts.

For the redirect convenience wrapper outside a browser, pass `currentUrl` and `assignUrl`. On completion, pass `callbackUrl`; either keep `cleanUrl: false` or provide `replaceUrl` when URL cleanup is required. An in-memory redirect store is suitable only when both stages run in the same process. See [authentication](/wallets/sdk/typescript/authentication#control-browser-routing-directly) for the lower-level browser flow.

## Respond to expiry

The SDK makes an expired session inactive before protected operations. Subscribe while your application needs to update its routing or UI.

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

// Call during application or component cleanup.
unsubscribe()
```

An expiry event includes the expired session snapshot even though `wallet.walletAddress` is now `undefined`. A newly constructed client can replay a stored expiry event to a listener. Starting authentication, completing a new session, or signing out clears that replay state.

## List and activate wallets

List every wallet available to the authenticated credential:

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

for (const wallet of wallets) {
  console.log(wallet.id, wallet.type, wallet.address, wallet.keyOrigin)
}
```

`listWallets` works with an active session and while manual auth selection is pending. After normal automatic auth, switch the active wallet with its server-side ID:

```typescript theme={null}
const wallet = wallets[0]

if (wallet) {
  const active = await omsWallet.wallet.useWallet({ walletId: wallet.id })
  console.log('Now active:', active.walletAddress)
}
```

`useWallet` requires an active session and preserves its credential expiry and auth metadata. If auth returned `PendingWalletSelection`, call `selection.selectWallet` instead.

## Create and activate another wallet

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

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

`createWallet` creates an Ethereum wallet by default and immediately makes it active. A pending manual selection must use `selection.createAndSelectWallet` instead.

Create a Solana wallet by setting its type explicitly:

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

const solana = await omsWallet.wallet.createWallet({
  type: WalletType.Solana,
  reference: 'solana-primary',
})
```

## Import and activate a wallet

`importWallet` validates and encrypts private-key material locally, sends only the encrypted material through the attested import transport, and activates the imported wallet:

```typescript theme={null}
import { WalletKeyOrigin, WalletType } from '@polygonlabs/oms-wallet'

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

console.log(imported.wallet.keyOrigin === WalletKeyOrigin.Imported)
```

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. Pass raw bytes when a valid base58 value is itself exactly 32 or 64 characters, because those string lengths are ambiguous and rejected. The SDK does not persist the plaintext key. `WalletAccount.keyOrigin` reports whether each returned wallet is enclave-created or imported.

Attestation failures throw an SDK error with 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 an ID token for your backend

`getIdToken` asks OMS Wallet to issue an ID token that proves the active wallet session to your backend.

```typescript theme={null}
const idToken = await omsWallet.wallet.getIdToken({
  ttlSeconds: 300,
  customClaims: { purpose: 'checkout' },
})
```

This token is OMS Wallet output. It is distinct from the provider-issued ID token passed into `signInWithOidcIdToken` during authentication. Treat client-supplied custom claims as untrusted context unless your backend independently controls or validates them. See [backend wallet verification](/wallets/sdk/guides/backend-wallet-verification).

## Review and revoke access

`listAccess` follows all service pages and returns direct or remote grants for the active wallet. Use `listAccessPages` when you want page-at-a-time rendering, and narrow on `type` before reading remote-session fields.

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

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)
  }
}

for await (const page of omsWallet.wallet.listAccessPages({ pageSize: 25 })) {
  console.log(page.grants)
}
```

Revoke only a credential that is not the caller for the current session:

```typescript theme={null}
const revocableGrant = grants.find((grant) => !grant.isCaller)

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

<Warning>
  Do not offer `revokeAccess` for a grant whose `isCaller` field is `true`. It represents the credential making the current request. Revocation is permanent for the target grant.
</Warning>

## 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 `1_000_000_000_000_000` wei authorizes up to `0.001 POL` across the session.

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

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: 1_000_000_000_000_000n,
    },
  ],
})

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

Pass the remote grant's `credentialId` and `sessionId` to `revokeAccess` to revoke that specific session. WaaS caps the requested session expiry at the remote credential's expiry.

## Operate a remote session from a backend

TypeScript also exports `RemoteAccessClient` for a remote application's backend. The backend owns and registers a persistent credential, reconciles the sessions approved for it, and prepares and executes transactions within each session's grants. This backend credential and the application workflow are separate from the wallet owner's active SDK session.

<Card title="Manage smart sessions from a backend" href="/wallets/sdk/guides/backend-smart-sessions">
  Set up the persistent signer, owner approval handoff, application storage, backend session reconciliation, remote execution, revocation, and credential rotation.
</Card>

See the [TypeScript API reference](/wallets/sdk/typescript/api-reference) for the exact `RemoteAccessClient` contracts.

## Sign out locally

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

`signOut` clears the local session record, pending auth state, active wallet, and local credential signer where supported. It does not call the OMS service and does not revoke server-side access grants. Use `revokeAccess` separately for other grants before signing out when your account-management flow requires revocation.
