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

# Storage and concurrency

> Implement the durable storage and exclusive execution that the Server Wallet SDK requires, and understand the attestation it performs on every response.

The SDK holds no state of its own. You supply durable storage and exclusive execution, and both contracts are requirements rather than tuning options. Getting either wrong corrupts wallet state instead of degrading performance.

## Implement the state store

```typescript theme={null}
export interface StateStore {
  read(key: string): Promise<string | null>
  write(key: string, value: string): Promise<void>
}
```

`read` returns `null` for a key that was never written. `write` must complete durable persistence before its promise resolves. A store that resolves on a buffered write, or on a replica that has not yet committed, can lose a credential or a nonce that OMS has already seen.

## Encrypt credentials

Wrap your store so credentials are encrypted at rest:

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

const store = new EncryptedStore(persistence, encryptionKey, namespace)
```

`encryptionKey` is 32 random bytes, base64 encoded. Any other length raises `CONFIGURATION`.

<Warning>
  Keep the encryption key with your database backups. Replacing it makes existing encrypted state unreadable, and there is no automatic key rotation: replacing a key requires a data migration.
</Warning>

## Choose the namespace

The namespace is the encryption context. It must be stable for the lifetime of the wallet, unique to one identity, and identical across every instance serving that identity:

```typescript theme={null}
const environment = environmentFromKey(publishableKey)
const namespace = JSON.stringify([
  environment.origin,
  environment.projectId,
  issuer,
  audience,
  subject,
])
```

Never share a namespace between identities. Two identities writing one namespace overwrite each other's credentials.

Reading a record written under a different key or namespace raises `STORAGE_INTEGRITY`. When you see it, check that the key and namespace match the ones used to write, and that the database and its records are intact. Do not clear the record to clear the error.

## Provide exclusive execution

```typescript theme={null}
export interface ExclusiveExecutor {
  run<T>(task: () => Promise<T>): Promise<T>
}
```

`run` must hold exclusive ownership of the identity's state for the **entire** async task, including its remote calls. The SDK advances each RPC nonce durably before dispatching the request, so two concurrent tasks will consume the same nonce and one request will fail verification.

Every instance that touches one identity's state must share that ownership.

| Deployment                    | Executor                                                       |
| ----------------------------- | -------------------------------------------------------------- |
| One Node process              | `SerialExecutor`                                               |
| One Durable Object per wallet | `SerialExecutor` inside the object                             |
| Clustered Node processes      | A coordinator you provide                                      |
| Worker global scope           | Not sufficient; scope ownership to a per-wallet Durable Object |

A clustered backend needs a coordinator that provides exclusive ownership across processes, including recovery when a process crashes mid-task. Allocating nonces centrally is not sufficient on its own: the lock must span the whole operation, because the SDK's remote calls happen inside it.

## Attestation

Every OMS response passes Nitro root, certificate, COSE, PCR0, freshness, nonce, and body-binding verification before the SDK returns it. There is no bypass and no option to weaken it. A response that fails any check raises `ATTESTATION_FAILED`.

The transport bounds response sizes, times requests out after 20 seconds, and refuses redirects.

An unsigned gateway error can surface as an attestation failure, so check your publishable key and allowed origin before assuming an enclave problem.

<Warning>
  A development environment can be configured with the all-zero debug PCR0. Production publishable keys reject it. Use it only with disposable keys.
</Warning>

Continue with [transfers](/wallets/sdk/server/transfers) to move funds, or [balances](/wallets/sdk/server/balances) for reads that need none of this state.
