diff --git a/docs/nitrolite/build/examples.mdx b/docs/nitrolite/build/examples.mdx
new file mode 100644
index 0000000..a2e7e44
--- /dev/null
+++ b/docs/nitrolite/build/examples.mdx
@@ -0,0 +1,168 @@
+---
+title: Examples
+description: Deployed Nitrolite example applications, their source repositories, stacks, and SDK usage.
+sidebar_position: 4
+---
+
+# Examples
+
+These deployed examples show different ways to build on Nitrolite. Use the live apps to understand the product flow, then inspect the source repositories for integration details.
+
+:::note
+Stack and SDK details reflect the linked repositories when this page was added. The repositories are the source of truth if an example changes after deployment.
+:::
+
+
+
+
+
+
+
+
+
+
Co-Sign Checkout
+
+
+
+ A shared checkout demo where two participants create a cart, co-sign checkout actions,
+ move funds into an app-session cart, propose purchases, close the cart, and withdraw
+ remaining shared-wallet funds.
+
+
+
+
Functionality
+
+ - Two-party shared cart and approval flow.
+ - Shared Wallet plus Checkout Cart app session.
+ - Purchase proposals, cart close, and wallet withdrawal.
+ - YUSD and YELLOW on Ethereum Sepolia.
+
+
+
+
Stack
+
+ - Next.js, React, TypeScript, Tailwind CSS.
+ - Supabase rooms, proposals, and events.
+ - Vercel deployment with scheduled proposal expiration.
+ - MetaMask SDK and viem.
+
+
+
+
SDKs
+
+ @yellow-org/sdk
+ @yellow-org/sdk-compat
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Nitrolite Store
+
+
+
+ A content-store reference app with a Go backend and browser frontend. The shopper connects
+ MetaMask, opens a store app session, adds funds, buys catalog content, reads purchased
+ content, and withdraws the remaining balance.
+
+
+
+
Functionality
+
+ - MetaMask shopper identity with backend app signing.
+ - Frontend-constructed app-session updates.
+ - Catalog purchase and content gating.
+ - YUSD and YELLOW pricing on Ethereum Sepolia.
+
+
+
+
Stack
+
+ - Go service serving API and built web UI.
+ - React, Vite, TypeScript frontend.
+ - SQLite persistence, Docker, Railway.
+ - MetaMask and viem in the browser.
+
+
+
+
SDKs
+
+ github.com/layer-3/nitrolite/sdk/go
+ @yellow-org/sdk
+ @yellow-org/sdk-compat
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Nexus P2P Transfer
+
+
+
+ A workshop-style content app that demonstrates wallet connection, Nitrolite session setup,
+ balance polling, and instant peer-to-peer support payments to post authors.
+
+
+
+
Functionality
+
+ - MetaMask connection and Sepolia network selection.
+ - Nitrolite client session with balance polling.
+ - Small support transfers to author wallets.
+ - YUSD and YELLOW asset selection.
+
+
+
+
Stack
+
+ - Preact with Hooks, TypeScript, and Vite.
+ - CSS Modules for app styling.
+ - viem for wallet access and amount conversion.
+ - Vercel-hosted static frontend.
+
+
+
+
SDKs
+
+ @yellow-org/sdk
+ @yellow-org/sdk-compat
+
+
+
+
+
+
+
+
+
diff --git a/docs/nitrolite/build/sdk/typescript-compat/errors.mdx b/docs/nitrolite/build/sdk/typescript-compat/errors.mdx
new file mode 100644
index 0000000..277409e
--- /dev/null
+++ b/docs/nitrolite/build/sdk/typescript-compat/errors.mdx
@@ -0,0 +1,174 @@
+---
+title: "Errors and recovery (compat)"
+description: Typed compat errors and recovery recipes for migrated apps
+sidebar_position: 6
+---
+
+# Errors and Recovery
+
+At app boundaries, classify raw wallet or SDK failures and show only UI-safe copy:
+
+```typescript
+import { NitroliteClient, getUserFacingMessage } from '@yellow-org/sdk-compat';
+
+try {
+ await client.deposit(tokenAddress, 11_000_000n);
+} catch (err) {
+ const typed = NitroliteClient.classifyError(err);
+ showToast(getUserFacingMessage(typed));
+ throw typed;
+}
+```
+
+## Error Catalogue
+
+| Error class | Code | Trigger | Recovery |
+|---|---|---|---|
+| `CompatError` | varies | Base compat failure | Log `error.code`; show `getUserFacingMessage(error)` |
+| `AllowanceError` | `ALLOWANCE_INSUFFICIENT` | ChannelHub needs ERC-20 allowance | Approve, then retry |
+| `UserRejectedError` | `USER_REJECTED` | Wallet rejected a signature or transaction | Show retry UI; do not auto-loop prompts |
+| `InsufficientFundsError` | `INSUFFICIENT_FUNDS` | Not enough gas or token balance | Show funding guidance |
+| `NotInitializedError` | `NOT_INITIALIZED` | Wallet/client is disconnected | Reconnect and recreate the client |
+| `OngoingStateTransitionError` | `ONGOING_STATE_TRANSITION` | Previous transition still finalizing | Poll status, then retry |
+
+## Allowance
+
+Compat token helpers use token addresses and raw token units:
+
+```typescript
+import { AllowanceError, NitroliteClient, getUserFacingMessage } from '@yellow-org/sdk-compat';
+
+try {
+ await client.deposit(tokenAddress, 11_000_000n);
+} catch (err) {
+ const typed = NitroliteClient.classifyError(err);
+ showToast(getUserFacingMessage(typed));
+
+ if (typed instanceof AllowanceError) {
+ await client.approveTokens(tokenAddress, 11_000_000n);
+ await client.deposit(tokenAddress, 11_000_000n);
+ }
+}
+```
+
+When you fall through to native v1, use `client.innerClient.approveToken(chainId, asset, amount)` with `Decimal`:
+
+```typescript
+import Decimal from 'decimal.js';
+
+try {
+ await client.innerClient.checkpoint('usdc');
+} catch (err) {
+ showToast(getUserFacingMessage(err));
+ await client.innerClient.approveToken(11155111n, 'usdc', new Decimal(11));
+ await client.innerClient.checkpoint('usdc');
+}
+```
+
+## Prompt and Reconnect
+
+For `UserRejectedError`, show `getUserFacingMessage(error)` and expose an explicit retry button. Do not auto-loop wallet prompts. For `NotInitializedError`, reconnect the wallet and recreate `NitroliteClient` before retrying.
+
+## Ongoing Transition
+
+Use `EventPoller` to wait for channel status to settle before enabling another write:
+
+```typescript
+import {
+ EventPoller,
+ OngoingStateTransitionError,
+ NitroliteClient,
+ getUserFacingMessage,
+} from '@yellow-org/sdk-compat';
+
+try {
+ await client.deposit(tokenAddress, 11_000_000n);
+} catch (err) {
+ const typed = NitroliteClient.classifyError(err);
+ showToast(getUserFacingMessage(typed));
+
+ if (typed instanceof OngoingStateTransitionError) {
+ const poller = new EventPoller(client, {
+ onChannelUpdate: (channels) => {
+ if (!channels.some((channel) => channel.status === 'resizing')) {
+ poller.stop();
+ enableRetry();
+ }
+ },
+ onError: (pollError) => showToast(getUserFacingMessage(pollError)),
+ }, 3000);
+ poller.start();
+ }
+}
+```
+
+## Insufficient Funds
+
+```typescript
+import { InsufficientFundsError, NitroliteClient, getUserFacingMessage } from '@yellow-org/sdk-compat';
+
+try {
+ await client.deposit(tokenAddress, 11_000_000n);
+} catch (err) {
+ const typed = NitroliteClient.classifyError(err);
+ showToast(getUserFacingMessage(typed));
+
+ if (typed instanceof InsufficientFundsError) {
+ const tokenBalance = await client.getTokenBalance(tokenAddress);
+ renderFundingHelp({ tokenBalance, chainId: 11155111 });
+ }
+}
+```
+
+## Missing RPC URL
+
+On-chain helpers throw `No RPC URL configured for chain ...` when `blockchainRPCs` is missing. Fix the client config with `blockchainRPCs: { 80002: process.env.POLYGON_AMOY_RPC_URL! }`.
+
+```typescript
+try {
+ await client.getOpenChannels();
+} catch (err) {
+ showToast(getUserFacingMessage(err));
+ if (err instanceof Error && err.message.includes('No RPC URL configured')) promptForRpcUrl();
+}
+```
+
+## Unsupported Asset or Wrong Amount Unit
+
+```typescript
+try {
+ await client.transfer(destination, [{ asset: 'usdc', amount: '5000000' }]);
+} catch (err) {
+ showToast(getUserFacingMessage(err));
+
+ if (err instanceof Error && err.message.includes('Unknown asset')) {
+ renderSupportedAssets(await client.getAssetsList());
+ }
+}
+```
+
+If a transfer uses `5.0`, fix it before retrying. Compat transfer uses raw asset-unit strings. Keep the [amount-units table](./overview#amount-units) next to migrated payment code reviews.
+
+## Failed Checkpoint
+
+Retry with capped backoff only after approval and state preconditions are satisfied. Keep the visible message behind `getUserFacingMessage(err)`:
+
+```typescript
+let lastError: unknown;
+
+for (const waitMs of [1000, 3000, 5000]) {
+ try {
+ await client.innerClient.checkpoint('usdc');
+ lastError = undefined;
+ break;
+ } catch (err) {
+ lastError = err;
+ showToast(getUserFacingMessage(err));
+ await new Promise((resolve) => setTimeout(resolve, waitMs));
+ }
+}
+
+if (lastError) {
+ throw lastError;
+}
+```
diff --git a/docs/nitrolite/build/sdk/typescript-compat/event-poller.mdx b/docs/nitrolite/build/sdk/typescript-compat/event-poller.mdx
new file mode 100644
index 0000000..54d2bd4
--- /dev/null
+++ b/docs/nitrolite/build/sdk/typescript-compat/event-poller.mdx
@@ -0,0 +1,98 @@
+---
+title: "EventPoller: bridging the dropped server-push model"
+description: Polling bridge for migrated v0.5.3 event handlers
+sidebar_position: 5
+---
+
+# EventPoller
+
+`EventPoller` is the compat bridge for apps that used 0.5.3-style pushed channel, balance, or asset updates. The v1 runtime does not preserve that server-push event model, so compat polls the query methods and calls your existing UI update hooks.
+
+Use it when the rest of your app still expects callbacks. If you are already rewriting the state layer, call `client.getChannels()`, `client.getBalances()`, and `client.getAssetsList()` directly.
+
+## Public Surface
+
+```typescript
+import { EventPoller } from '@yellow-org/sdk-compat';
+
+const poller = new EventPoller(client, callbacks, intervalMs);
+
+poller.start();
+poller.stop();
+poller.setInterval(10000);
+```
+
+The constructor takes the compat `NitroliteClient`, optional `EventPollerCallbacks`, and an optional interval in milliseconds. The default interval is `5000`.
+
+```typescript
+interface EventPollerCallbacks {
+ onChannelUpdate?: (channels: LedgerChannel[]) => void;
+ onBalanceUpdate?: (balances: LedgerBalance[]) => void;
+ onAssetsUpdate?: (assets: ClearNodeAsset[]) => void;
+ onError?: (error: Error) => void;
+}
+```
+
+`onAssetsUpdate` keeps the legacy asset shape for backwards compatibility. New native v1 code should read the asset surface directly from `@yellow-org/sdk`.
+
+## Full Example
+
+```typescript
+import {
+ EventPoller,
+ NitroliteClient,
+ getUserFacingMessage,
+} from '@yellow-org/sdk-compat';
+
+const client = await NitroliteClient.create({
+ wsURL: '',
+ walletClient,
+ chainId: 11155111,
+ blockchainRPCs,
+});
+
+const poller = new EventPoller(client, {
+ onChannelUpdate: (channels) => {
+ channelStore.replace(channels);
+ },
+ onBalanceUpdate: (balances) => {
+ balanceStore.replace(balances);
+ },
+ onAssetsUpdate: (assets) => {
+ assetStore.replace(assets);
+ },
+ onError: (err) => {
+ showToast(getUserFacingMessage(err));
+ },
+}, 5000);
+
+poller.start();
+
+window.addEventListener('beforeunload', () => {
+ poller.stop();
+});
+```
+
+## Intervals
+
+Use `2000` to `5000` ms during active deposits, withdrawals, or app-session transitions. Use `5000` to `10000` ms for normal dashboards, and `15000` to `30000` ms for background views. Switch intervals as the user moves between active and passive flows:
+
+```typescript
+poller.setInterval(isTransitionPending ? 3000 : 10000);
+```
+
+## Failure Behavior
+
+Each poll cycle calls:
+
+- `client.getChannels()`
+- `client.getBalances()`
+- `client.getAssetsList()`
+
+Those requests run independently. If one fails, `EventPoller` calls `onError` for that failure and still delivers fulfilled results from the other requests.
+
+`EventPoller` does not renew auth tokens, persist state, or replace your app cache. It gives migrated apps a single start/stop lifecycle and normalizes channel, balance, and asset polling failures into one `onError` path while they move away from pushed WebSocket events.
+
+## Moving to Native v1
+
+When you remove compat, remove `EventPoller` too. Native v1 apps should own their own refresh policy and call SDK query methods such as `client.getChannels(wallet)`, `client.getBalances(wallet)`, and `client.getAssets()` from the screen that needs the data.
diff --git a/docs/nitrolite/build/sdk/typescript-compat/migration-offchain.mdx b/docs/nitrolite/build/sdk/typescript-compat/migration-offchain.mdx
index a5efde4..08aec5f 100644
--- a/docs/nitrolite/build/sdk/typescript-compat/migration-offchain.mdx
+++ b/docs/nitrolite/build/sdk/typescript-compat/migration-offchain.mdx
@@ -6,103 +6,173 @@ sidebar_position: 4
# Off-Chain Migration Guide
-Covers authentication, app sessions, transfers, ledger queries, and event polling when migrating from v0.5.3.
+This page covers authentication, app sessions, transfers, ledger queries, and event polling when moving 0.5.3 app code to `@yellow-org/sdk-compat`.
## Authentication
-v1.0.0 handles authentication internally when using `NitroliteClient`. For legacy WebSocket-auth code paths, the compat layer keeps `createAuthRequestMessage`, `createAuthVerifyMessage`, `createAuthVerifyMessageWithJWT`, and `createEIP712AuthMessageSigner` available.
+Native `NitroliteClient` usage handles connection authentication inside the client. Legacy auth helper imports are split into three buckets.
-## App Sessions
+### Available and Functional
-### List
+These helpers are exported and implemented for migration code that still owns a WebSocket auth flow:
-**Before:** `createGetAppSessionsMessage` + `sendRequest` + `parseGetAppSessionsResponse`
+```typescript
+import {
+ createAuthRequestMessage,
+ createAuthVerifyMessage,
+ createAuthVerifyMessageWithJWT,
+ createEIP712AuthMessageSigner,
+} from '@yellow-org/sdk-compat';
+```
-**After:**
+The v1 auth request fields are `application`, `expires_at`, `session_key`, `scope`, and `allowances`. The codemod flags older `app_name`, `expire`, `participant`, and `challenge` usage for review.
+
+### Exported but Fail Fast
+
+Workflow helpers that cannot map honestly to a single live v1 RPC remain exported so old imports compile, but throw with migration guidance:
```typescript
-const sessions = await client.getAppSessionsList();
+createTransferMessage;
+createCreateChannelMessage;
+createCloseChannelMessage;
+createResizeChannelMessage;
```
-### Create
+Use `NitroliteClient` methods instead.
+
+### Parse v1 Payloads Into 0.5.x Shapes
-**Before:**
+The `parse*Response` helpers normalize known v1 response payloads into the older app-facing response shape:
```typescript
-const msg = await createAppSessionMessage(signer.sign, { definition, allocations });
-const raw = await sendRequest(msg);
-parseCreateAppSessionResponse(raw);
+parseGetChannelsResponse;
+parseGetLedgerBalancesResponse;
+parseGetLedgerEntriesResponse;
+parseGetAppSessionsResponse;
+parseCreateAppSessionResponse;
+parseCloseAppSessionResponse;
+parseSubmitAppStateResponse;
+parseGetAppDefinitionResponse;
+parseAnyRPCResponse;
```
+These are migration aids, not a reason to keep an app-owned RPC transport indefinitely.
+
+## App Sessions
+
+### List
+
+**Before:** `createGetAppSessionsMessage` + `sendRequest` + `parseGetAppSessionsResponse`.
+
**After:**
```typescript
-await client.createAppSession(definition, allocations);
+const sessions = await client.getAppSessionsList();
```
-### Close
-
-**Before:** `createCloseAppSessionMessage` + send + parse
+### Create
-**After:**
+App-session allocation strings remain human-readable decimal strings:
```typescript
-await client.closeAppSession(appSessionId, allocations);
+const appAmount = '5.0'; // human-readable app-session decimal string
+
+await client.createAppSession(definition, [
+ { participant: userAddress, asset: 'usdc', amount: appAmount },
+], quorumSigs);
```
### Submit State
-**Before:** `createSubmitAppStateMessage` + send
+```typescript
+import { RPCAppStateIntent } from '@yellow-org/sdk-compat';
+
+await client.submitAppState({
+ app_session_id: appSessionId,
+ intent: RPCAppStateIntent.Operate,
+ version,
+ allocations,
+ quorum_sigs: quorumSigs,
+});
+```
-**After:**
+### Close
```typescript
-await client.submitAppState(params);
+await client.closeAppSession(appSessionId, allocations, quorumSigs);
```
## Transfers
-**Before:**
+Transfer allocations are raw asset-unit strings, not human-readable decimal strings.
+
+**Before:** helper workflow.
```typescript
const msg = await createTransferMessage(signer.sign, { destination, allocations });
await sendRequest(msg);
```
-**After:**
+**After:** compat method.
```typescript
-await client.transfer(destination, allocations);
+await client.transfer(destination, [
+ { asset: 'usdc', amount: '5000000' },
+]);
```
+That example means 5 USDC when the asset has 6 decimals. See the [amount-units table](./overview#amount-units).
+
## Ledger Queries
-**Before:** `createGetLedgerBalancesMessage` / `createGetLedgerEntriesMessage` + send + parse
+**Before:** create, send, parse.
-**After:**
+```typescript
+const msg = await createGetLedgerBalancesMessage(signer.sign, accountId);
+const raw = await sendRequest(msg);
+const balances = parseGetLedgerBalancesResponse(raw).params.ledgerBalances;
+```
+
+**After:** direct client calls.
```typescript
const balances = await client.getBalances();
const entries = await client.getLedgerEntries();
+const channels = await client.getChannels();
```
## Event Polling
-v0.5.3 used WebSocket push events (`ChannelUpdate`, `BalanceUpdate`). v1.0.0 uses polling. The `EventPoller` bridges this gap:
+0.5.3 apps often listened for pushed channel and balance updates. Compat replaces that with `EventPoller`, which polls the same query methods your app can call directly.
```typescript
import { EventPoller } from '@yellow-org/sdk-compat';
const poller = new EventPoller(client, {
- onChannelUpdate: (channels) => updateUI(channels),
+ onChannelUpdate: (channels) => updateChannels(channels),
onBalanceUpdate: (balances) => updateBalances(balances),
- onAssetsUpdate: (assets) => updateAssets(assets),
- onError: (err) => console.error(err),
+ onAssetsUpdate: (assets) => updateAssets(assets),
+ onError: (err) => reportError(err),
}, 5000);
poller.start();
```
-## RPC Compatibility Helpers
+See the [EventPoller cookbook](./event-poller) for lifecycle, interval, and cleanup guidance.
+
+## Error Handling
+
+Wrap migrated calls with typed error handling instead of string-matching raw wallet or RPC errors:
+
+```typescript
+import { getUserFacingMessage, NitroliteClient } from '@yellow-org/sdk-compat';
+
+try {
+ await client.transfer(destination, [{ asset: 'usdc', amount: '5000000' }]);
+} catch (err) {
+ const typed = NitroliteClient.classifyError(err);
+ showToast(getUserFacingMessage(typed));
+}
+```
-The `create*Message` and `parse*Response` functions still exist so existing imports compile. Most are transitional placeholders. Prefer `NitroliteClient` methods directly for new code.
+See [Errors and recovery](./errors) for recovery recipes.
diff --git a/docs/nitrolite/build/sdk/typescript-compat/migration-onchain.mdx b/docs/nitrolite/build/sdk/typescript-compat/migration-onchain.mdx
index 73a0ee4..f87d801 100644
--- a/docs/nitrolite/build/sdk/typescript-compat/migration-onchain.mdx
+++ b/docs/nitrolite/build/sdk/typescript-compat/migration-onchain.mdx
@@ -6,11 +6,13 @@ sidebar_position: 3
# On-Chain Migration Guide
-Covers deposits, withdrawals, channel operations, amount handling, and contract addresses when migrating from v0.5.3.
+This page covers deposits, withdrawals, channel operations, amount handling, and contract-address migration for apps moving from `@erc7824/nitrolite@0.5.3` to `@yellow-org/sdk-compat`.
## Deposits
-**Before (v0.5.3):** Manual approve → deposit → createChannel
+In v1, home-channel creation is implicit on first deposit. Apps should stop sending a separate `createChannel` workflow.
+
+**Before:** manual approve, deposit, and channel creation.
```typescript
await approveToken(custody, tokenAddress, amount);
@@ -18,63 +20,104 @@ await sendRequest(createDepositMessage(signer.sign, { token: tokenAddress, amoun
await sendRequest(createCreateChannelMessage(signer.sign, { token: tokenAddress, amount }));
```
-**After (compat):** Single call — approval and channel creation are implicit
+**After:** one compat call with raw token units.
```typescript
+const amount = 11_000_000n; // 11 USDC when the token has 6 decimals
await client.deposit(tokenAddress, amount);
```
+`deposit()` resolves the token to a v1 asset, sets the home blockchain, calls the native deposit path, and checkpoints. If token allowance is missing, the compat client retries after approval through the v1 SDK.
+
## Withdrawals
-**Before (v0.5.3):** Manual close → checkpoint → withdraw
+**Before:** close or resize workflow plus a manual withdrawal request.
```typescript
-const closeMsg = await createCloseChannelMessage(signer.sign, { channel_id });
-const raw = await sendRequest(closeMsg);
+const closeMsg = await createCloseChannelMessage(signer.sign, channelId, destination);
+await sendRequest(closeMsg);
await sendRequest(createWithdrawMessage(signer.sign, { token, amount }));
```
-**After (compat):** Single call
+**After:** one compat call with raw token units.
```typescript
+const amount = 5_000_000n; // 5 USDC
await client.withdrawal(tokenAddress, amount);
```
## Channel Operations
-| Operation | v0.5.3 | Compat |
-|-----------|--------|--------|
-| Create | Explicit `createChannel()` | Implicit on first `deposit()` |
-| Close | `createCloseChannelMessage` + send + parse | `client.closeChannel()` |
-| Resize | `createResizeChannelMessage` + send + parse | `client.resizeChannel({ allocate_amount, token })` |
+| Operation | v0.5.3 habit | Compat behavior |
+|---|---|---|
+| Create | `createChannel()` | Unsupported as a standalone flow; first `deposit()` creates the home channel when needed |
+| Close | `createCloseChannelMessage` + send + parse | `client.closeChannel()` or `client.closeChannel({ tokenAddress })` |
+| Resize | `createResizeChannelMessage` + send + parse | `client.resizeChannel({ allocate_amount, token })`, implemented through deposit |
+| Checkpoint | `checkpointChannel(...)` | Fail-fast stub; use `client.innerClient.checkpoint(asset)` |
+| Challenge | `challengeChannel({ state })` | Delegates to the v1 challenge path |
## Amount Handling
-**Before (v0.5.3):** Raw `BigInt` everywhere; app must handle decimals
+Compat does not accept one universal amount shape. Use the canonical [amount-units table](./overview#amount-units) before changing production amounts.
```typescript
-const amount = 11_000_000n; // 11 USDC (6 decimals)
+// Raw token-unit bigint for deposit and withdrawal.
+await client.deposit(usdcTokenAddress, 11_000_000n);
+await client.withdrawal(usdcTokenAddress, 5_000_000n);
+
+// Helpers for display conversion.
+const formatted = client.formatAmount(usdcTokenAddress, 11_000_000n); // "11"
+const parsed = client.parseAmount(usdcTokenAddress, '11.0'); // 11_000_000n
```
-**After (compat):** Accepts both; conversion handled internally
+Transfers are different. A transfer allocation uses a raw asset-unit string:
```typescript
-// Raw BigInt still works
-await client.deposit(tokenAddress, 11_000_000n);
-
-// Or use helpers
-const formatted = client.formatAmount(tokenAddress, 11_000_000n); // "11.0"
-const parsed = client.parseAmount(tokenAddress, "11.0"); // 11_000_000n
+await client.transfer(recipientAddress, [
+ { asset: 'usdc', amount: '5000000' },
+]);
```
-For transfers and allocations, compat accepts human-readable strings: `{ asset: 'usdc', amount: '5.0' }`.
+App-session allocations are different again: they use human-readable decimal strings. Keep these three cases separate during review.
## Contract Addresses
-**Before (v0.5.3):** Manual config
+**Before:** apps often carried manual contract maps.
```typescript
const addresses = { custody: '0x...', adjudicator: '0x...' };
```
-**After (compat):** Fetched from clearnode `get_config` — no manual setup. The `addresses` field in config is deprecated and ignored.
+**After:** contract and asset metadata comes from Nitronode config and asset discovery. The `addresses` config field is deprecated and ignored.
+
+```typescript
+const config = await client.getConfig();
+const assets = await client.getAssetsList();
+```
+
+If an on-chain helper needs an RPC URL for a chain, pass `blockchainRPCs` when creating `NitroliteClient` or use `blockchainRPCsFromEnv()`.
+
+```typescript
+const client = await NitroliteClient.create({
+ wsURL: '',
+ walletClient,
+ chainId: 11155111,
+ blockchainRPCs: {
+ 11155111: process.env.SEPOLIA_RPC_URL!,
+ },
+});
+```
+
+## Approval Helpers
+
+Compat exposes allowance helpers for migration code that still thinks in raw token units:
+
+```typescript
+const allowance = await client.getTokenAllowance(tokenAddress);
+
+if (allowance < 11_000_000n) {
+ await client.approveTokens(tokenAddress, 11_000_000n);
+}
+```
+
+For native v1-only flows, use `client.innerClient.approveToken(chainId, asset, amount)` with `Decimal`.
diff --git a/docs/nitrolite/build/sdk/typescript-compat/migration-overview.mdx b/docs/nitrolite/build/sdk/typescript-compat/migration-overview.mdx
index 8a71402..e3d55fc 100644
--- a/docs/nitrolite/build/sdk/typescript-compat/migration-overview.mdx
+++ b/docs/nitrolite/build/sdk/typescript-compat/migration-overview.mdx
@@ -4,70 +4,144 @@ description: Migrating from v0.5.3 to the compat layer
sidebar_position: 2
---
-# Migrating from v0.5.3 to Compat Layer
+# Migrating from v0.5.3 to Compat
-This guide explains how to migrate your Nitrolite dApp from the v0.5.3 SDK to the compat layer, which bridges the old API to the v1.0.0 runtime with minimal code changes.
+Use this guide when an existing app depends on `@erc7824/nitrolite@0.5.3` and needs a staged path onto the v1 runtime. Compat preserves the supported app-facing surface, but it does not promise full 0.5.3 package parity.
-## Why Use the Compat Layer
+## Start With the Codemod
-A direct migration from v0.5.3 to v1.0.0 touches **20+ files** per app with deep, scattered rewrites. The compat layer reduces this to **~5 file changes** per app.
+Run the codemod before hand-editing. It rewrites imports, migrates client constructors, renames auth fields, updates dependencies, and leaves `TODO [codemod]` comments where a human needs to collapse a workflow.
-:::tip Automate with Codemod
-Before migrating manually, try the [yellow-sdk-codemod](https://github.com/layer-3/yellow-sdk-codemod). It rewrites `@erc7824/nitrolite` imports, renames auth fields, migrates client constructors, updates `package.json`, and flags RPC patterns with `// TODO [codemod]` comments for the remaining manual steps.
-:::
+```bash
+git clone https://github.com/layer-3/yellow-sdk-codemod.git
+cd yellow-sdk-codemod
+npm install
+npm run build
+
+node dist/cli.js scan --path /path/to/your-app/src
+node dist/cli.js run --path /path/to/your-app --update-deps
+```
-## Installation
+Then search for the manual markers:
```bash
-npm install @yellow-org/sdk-compat
-# Peer dependencies
-npm install @yellow-org/sdk viem
+rg "TODO \\[codemod\\]" /path/to/your-app
```
-## Import Swap
+See the [overview](./overview) for the command sequence and `node dist/cli.js list` for available transforms.
+
+## MCP-Assisted Migration
+
+:::info Coming soon
+The Yellow SDK MCP server is proposed for npm publication as `@yellow-org/sdk-mcp`. Until that package is published, treat this as a preview of the assisted workflow, not a command that should work today.
+:::
+
+After publication, connect the MCP server to your MCP-compatible client and use it as a second review pass after the codemod:
+
+1. Run `server_info` to confirm the MCP content version matches the SDK version you are migrating to.
+2. Use the `migrate-from-v053` prompt to walk through changed files and unresolved `TODO [codemod]` markers.
+3. Use `validate_import` when you are unsure whether a symbol belongs to `@yellow-org/sdk-compat` or native `@yellow-org/sdk`.
+4. Use `get_rpc_method` to map old `create*Message` + `sendRequest` + `parse*Response` flows onto the v1 wire method.
+5. Use `lookup_method`, `lookup_type`, or `search_api` to verify direct v1 SDK replacements before reaching for `client.innerClient`.
+
+MCP assistance does not replace the manual checklist below. Tool-specific setup belongs with the package publish so the documented commands are runnable on the day they appear here.
-| Before (v0.5.3) | After (compat) |
-|-----------------|----------------|
-| `import { createGetChannelsMessage, parseGetChannelsResponse } from '@layer-3/nitrolite'` | `import { NitroliteClient } from '@yellow-org/sdk-compat'` |
-| Types: `AppSession`, `LedgerChannel`, `RPCAppDefinition` | Same types — re-exported from `@yellow-org/sdk-compat` |
+## Install Compat
-For **types**, just change the package name. For **functions**, switch to client methods instead of `create*Message` / `parse*Response`.
+```bash
+npm install @yellow-org/sdk-compat
+npm install @yellow-org/sdk viem
+```
-## The Key Pattern Change
+## Client Construction
-**Before (v0.5.3):** create-sign-send-parse
+**Before:** app-owned WebSocket plus helper calls.
```typescript
-const msg = await createGetChannelsMessage(signer.sign, addr);
+const msg = await createGetChannelsMessage(signer.sign, address);
const raw = await sendRequest(msg);
const parsed = parseGetChannelsResponse(raw);
-const channels = parsed.params.channels;
```
-**After (compat):** direct client method
+**After:** one compat client backed by the v1 SDK.
```typescript
-const client = await NitroliteClient.create(config);
+import { NitroliteClient, blockchainRPCsFromEnv } from '@yellow-org/sdk-compat';
+
+const client = await NitroliteClient.create({
+ wsURL: '',
+ walletClient,
+ chainId: 11155111,
+ blockchainRPCs: blockchainRPCsFromEnv(),
+});
+
const channels = await client.getChannels();
```
-## What Stays the Same
+:::info Sandbox URL - coming soon
+Use the same Nitronode URL placeholder pattern as the native v1 quickstart. Replace `` only when the canonical sandbox host is pinned.
+:::
+
+## Migration Matrix
+
+| Legacy use | Compat status | Direct v1 replacement |
+|---|---|---|
+| Auth helpers | Available: `createAuthRequestMessage`, `createAuthVerifyMessage`, `createAuthVerifyMessageWithJWT`, `createEIP712AuthMessageSigner` | SDK client auth flow |
+| Channel create or resize helpers | Unsupported or fail-fast where no honest v1 mapping exists | `Client.deposit`, `Client.checkpoint`, lifecycle methods |
+| Transfer | Available with raw-amount caveat | `Client.transfer(recipient, asset, Decimal)` |
+| App sessions | Available with v1 remapping | Native app-session methods on `Client` |
+
+## Amount Rules
+
+Do not flatten all amounts into one convention. Compat intentionally keeps separate units for separate method families.
+
+- `deposit`, `withdrawal`, and token allowance helpers use raw token-unit `bigint`.
+- `transfer` uses raw asset-unit strings, for example `{ asset: 'usdc', amount: '5000000' }` for 5 USDC with 6 decimals.
+- App-session allocations use human-readable decimal strings, for example `'5.0'`.
+- Direct native v1 calls use `Decimal`.
-- **Type shapes:** `AppSession`, `LedgerChannel`, `RPCAppDefinition`, `RPCBalance`, `RPCAsset`, etc.
-- **Response formats:** Balances, ledger entries, app sessions — same structure as v0.5.3.
-- **Auth helpers:** `createAuthRequestMessage`, `createAuthVerifyMessage`, `createAuthVerifyMessageWithJWT` remain available.
+See the canonical [amount-units table](./overview#amount-units).
## What Changes
-| Concern | v0.5.3 | Compat |
-|---------|--------|--------|
-| WebSocket | App creates and manages `WebSocket` | Managed internally by the client |
-| Signing | App passes `signer.sign` into every message | Internal — client uses `WalletClient` |
-| Amounts | Raw `BigInt` everywhere | Compat accepts both; conversion handled internally |
-| Contract addresses | Manual config | Fetched from clearnode `get_config` |
-| Channel creation | Explicit `createChannel()` | Implicit on first `deposit()` |
+| Concern | v0.5.3 habit | Compat behavior |
+|---|---|---|
+| WebSocket ownership | App creates and manages `WebSocket` | `NitroliteClient` manages the connection |
+| Signing | App passes `signer.sign` into each helper | Client methods sign internally with `walletClient` |
+| Contract addresses | App hard-codes custody and adjudicator addresses | Compat reads current node config and asset metadata |
+| Channel creation | App calls `createChannel()` | First `deposit()` creates the home channel when needed |
+| Server-push events | App handles pushed channel and balance events | Use [EventPoller](./event-poller) |
+| Errors | App matches raw strings | Use typed errors and [Errors and recovery](./errors) |
+
+## Manual Review Checklist
+
+After the codemod runs, review each changed area before shipping:
+
+| Area | What to check |
+|---|---|
+| Imports | `@erc7824/nitrolite`, `@layer-3/nitrolite`, and vendored tarballs are gone from app source |
+| Client setup | `new NitroliteClient(...)` and `createNitroliteClient(...)` are replaced with `NitroliteClient.create({ wsURL, walletClient, chainId, blockchainRPCs })` |
+| Auth | `app_name`, `expire`, `participant`, and `challenge` are migrated to `application`, `expires_at`, `session_key`, `scope`, and `allowances` |
+| RPC chains | `create*Message` + `sendRequest` + `parse*Response` call chains are replaced with client methods or consciously kept as transitional helpers |
+| Channel operations | `createChannel`, `depositToChannel`, and old `approveToken` wrappers are replaced with `deposit`, `withdrawal`, `approveTokens`, or a direct `innerClient` call |
+| Events | WebSocket push handlers are replaced with [EventPoller](./event-poller) or app-owned polling |
+| Contract config | `custody`, `adjudicator`, `CUSTODIES`, and `ADJUDICATORS` constants are removed; config comes from Nitronode |
+| Amounts | Transfer amounts are raw asset-unit strings; app-session allocations are human-readable decimal strings |
+| Errors | Raw string matching is replaced with `NitroliteClient.classifyError()` and `getUserFacingMessage()` |
+| SSR | Do not import `Client` from `@yellow-org/sdk-compat`; import SDK classes directly from `@yellow-org/sdk` |
+
+## Unsupported Surfaces
+
+The following names can still appear in migrated code, but they are not full live replacements:
+
+- `checkpointChannel(...)` fails fast; use `client.innerClient.checkpoint(asset)`.
+- Workflow-only `create*Message` helpers such as `createTransferMessage`, `createCreateChannelMessage`, `createCloseChannelMessage`, and `createResizeChannelMessage` fail fast with migration guidance.
+- `parse*Response` helpers normalize known v1 payloads into 0.5.x-shaped responses, but they are not a replacement for an app-owned RPC transport.
+- `get_session_keys` directory-style APIs and `get_rpc_history` are not preserved.
## Next Steps
-- [On-Chain Changes](./migration-onchain) — Deposits, withdrawals, channel operations, amount handling
-- [Off-Chain Changes](./migration-offchain) — App sessions, transfers, ledger queries, event polling
+- [On-Chain Changes](./migration-onchain) - deposits, withdrawals, channel operations, and raw token units
+- [Off-Chain Changes](./migration-offchain) - auth helpers, app sessions, transfers, and ledger queries
+- [EventPoller](./event-poller) - replace server-push handlers with polling callbacks
+- [Errors and recovery](./errors) - classify wallet, allowance, funds, and transition errors
diff --git a/docs/nitrolite/build/sdk/typescript-compat/overview.mdx b/docs/nitrolite/build/sdk/typescript-compat/overview.mdx
index db1e283..c53ff72 100644
--- a/docs/nitrolite/build/sdk/typescript-compat/overview.mdx
+++ b/docs/nitrolite/build/sdk/typescript-compat/overview.mdx
@@ -1,39 +1,49 @@
---
title: Overview
-description: Compatibility layer bridging Nitrolite SDK v0.5.3 API to v1.0.0
+description: Compatibility layer bridging selected Nitrolite SDK v0.5.3 APIs to the v1 runtime
sidebar_position: 1
---
# TypeScript Compat SDK
-Compatibility layer that bridges the Nitrolite SDK **v0.5.3 API** to the **v1.0.0 runtime**, letting existing dApps upgrade to the new protocol with minimal code changes.
+`@yellow-org/sdk-compat` is a migration layer for apps already built on the published `@erc7824/nitrolite@0.5.3` API. It keeps selected app-facing calls available while routing them through the native v1 `@yellow-org/sdk` runtime.
+
+:::note Package naming
+The published npm package audited for this migration path is `@erc7824/nitrolite@0.5.3`. Some older internal docs refer to the same 0.5.3 codebase as `@layer-3/nitrolite`.
+:::
Already integrated with @erc7824/nitrolite?
-If your app is already built on `@erc7824/nitrolite` (v0.4 through v0.5.3), you can speed up the migration using the [yellow-sdk-codemod](https://github.com/layer-3/yellow-sdk-codemod) tool. It handles the repetitive parts of the upgrade automatically: rewriting imports, migrating client constructors, renaming auth fields, and updating your `package.json`. Where the change requires context (collapsing RPC call chains, removing manual WebSocket setup), the codemod leaves a `// TODO [codemod]` comment with the exact replacement so you know what to do.
+Speed up the migration with the `yellow-sdk-codemod` repository:
```bash
# Clone the codemod and install its dependencies
git clone https://github.com/layer-3/yellow-sdk-codemod.git
-cd yellow-sdk-codemod && npm install
+cd yellow-sdk-codemod
+npm install
+npm run build
-# Scan your project to see what needs changing (no files are modified)
-npx tsx src/cli.ts scan --path /path/to/your-app/src
+# Scan your codebase for migrate-able patterns (no files modified)
+node dist/cli.js scan --path /path/to/your-app/src
-# Apply all transforms and update dependencies
-npx tsx src/cli.ts run --path /path/to/your-app --update-deps
+# Apply transforms (and update package.json deps)
+node dist/cli.js run --path /path/to/your-app --update-deps
```
-After running, search for `TODO [codemod]` in your codebase and work through the remaining items. See the [codemod README](https://github.com/layer-3/yellow-sdk-codemod#readme) for the full list of transforms and CLI options.
+After running, search for `TODO [codemod]` in your codebase and resolve them manually. The codemod surfaces every place a chained `create*Message` + `sendRequest` + `parse*Response` pattern needs context. See `node dist/cli.js list` for the full transform list.
+
+:::info MCP-assisted migration - coming soon
+The Yellow SDK MCP server is planned for npm as `@yellow-org/sdk-mcp`, but it is not published yet. After it lands, use it as a second review pass for unresolved codemod markers, uncertain imports, old RPC helper chains, and direct v1 SDK replacements. See the [migration overview](./migration-overview#mcp-assisted-migration) for the planned workflow.
+:::
-## Why Use the Compat Layer
+## Why Use Compat
-The v1.0.0 protocol introduces breaking changes across 14 dimensions — wire format, authentication, WebSocket lifecycle, unit system, asset resolution, and more. A direct migration touches 20+ files per app with deep, scattered rewrites.
+Use compat when a live app needs to move off the 0.5.3 package without rewriting every transport, auth, event, and amount-handling call at once. New apps should start with the native [`@yellow-org/sdk`](../typescript/getting-started) instead.
-The compat layer centralises this complexity into **~1,000 lines** that absorb the protocol differences, reducing per-app integration effort by an estimated **56–70%**.
+Compat is a bridge, not full package parity. The underlying v1 client is available as `client.innerClient` for flows that the migration surface cannot model honestly.
## Installation
@@ -43,134 +53,86 @@ npm install @yellow-org/sdk-compat
npm install @yellow-org/sdk viem
```
+:::info Sandbox URL - coming soon
+Use your Nitronode WebSocket URL in the `wsURL` field below. The public sandbox URL is intentionally shown as `` until the canonical host is pinned.
+:::
+
## Quick Start
```typescript
import { NitroliteClient, blockchainRPCsFromEnv } from '@yellow-org/sdk-compat';
-// Create client (replaces new Client(ws, signer))
const client = await NitroliteClient.create({
- wsURL: 'wss://clearnode.example.com/ws',
+ wsURL: '',
walletClient, // viem WalletClient with account
chainId: 11155111, // Sepolia
blockchainRPCs: blockchainRPCsFromEnv(),
});
-// Deposit (creates channel if needed)
await client.deposit(tokenAddress, 11_000_000n);
-// Query
const channels = await client.getChannels();
const balances = await client.getBalances();
const sessions = await client.getAppSessionsList();
-// Transfer
-await client.transfer(recipientAddress, [{ asset: 'usdc', amount: '5.0' }]);
+// 5 USDC (6 decimals) as raw asset-unit string:
+await client.transfer(recipientAddress, [{ asset: 'usdc', amount: '5000000' }]);
-// Cleanup
-await client.closeChannel();
await client.close();
```
+`TransferAllocation.amount` is a raw asset-unit string using the asset's canonical decimals; the compat layer divides by decimals before delegating to the v1 SDK.
+
+## Amount Units
+
+| Method area | Amount format | Example |
+|---|---|---|
+| `deposit`, `withdrawal`, token allowance helpers | raw token-unit `bigint` | `11_000_000n` |
+| `transfer` allocations | raw asset-unit string | `'5000000'` |
+| App-session allocations | human-readable decimal string | `'5.0'` |
+| Direct `@yellow-org/sdk` channel and app amounts | `Decimal` | `new Decimal(5)` |
+
## Method Cheat Sheet
-### Channel Operations
-
-| Method | Description |
-|--------|-------------|
-| `deposit(token, amount)` | Deposit to channel (creates if needed) |
-| `depositAndCreateChannel(token, amount)` | Alias for `deposit()` |
-| `withdrawal(token, amount)` | Withdraw from channel |
-| `closeChannel(params?)` | Close open channels (optionally for a specific token) |
-| `resizeChannel({ allocate_amount, token })` | Resize an existing channel |
-| `challengeChannel({ state })` | Challenge a channel on-chain |
-| `createChannel()` | No-op in v1 (channel creation is implicit on `deposit()`) |
-
-### Queries
-
-| Method | Description |
-|--------|-------------|
-| `getChannels()` | List all ledger channels |
-| `getChannelData(channelId)` | Full channel + state for a specific channel |
-| `getBalances(wallet?)` | Get ledger balances |
-| `getLedgerEntries(wallet?)` | Get transaction history |
-| `getAppSessionsList(wallet?, status?)` | List app sessions |
-| `getLastAppSessionsListError()` | Last error from `getAppSessionsList()` (if any) |
-| `getAssetsList()` | List supported assets |
-| `getAccountInfo()` | Aggregate balance + channel count |
-| `getConfig()` | Node configuration |
-
-### Transfers
-
-| Method | Description |
-|--------|-------------|
-| `transfer(destination, allocations)` | Off-chain transfer to another participant |
-
-### App Sessions
-
-| Method | Description |
-|--------|-------------|
-| `createAppSession(definition, allocations, quorumSigs?)` | Create an app session |
-| `closeAppSession(appSessionId, allocations, quorumSigs?)` | Close an app session |
-| `submitAppState(params)` | Submit state update (operate/deposit/withdraw/close) |
-| `getAppDefinition(appSessionId)` | Get session definition |
-
-### App Session Signing Helpers
-
-| Helper | Description |
-|--------|-------------|
-| `packCreateAppSessionHash(params)` | Deterministic hash for `createAppSession` quorum signing |
-| `packSubmitAppStateHash(params)` | Deterministic hash for `submitAppState` quorum signing |
-| `toWalletQuorumSignature(signature)` | Prefix wallet signature for app-session quorum format |
-| `toSessionKeyQuorumSignature(signature)` | Prefix session key signature (`0xa2`) for quorum format |
-
-### Session Keys
-
-| Method | Description |
-|--------|-------------|
-| `signChannelSessionKeyState(state)` | Sign a channel session-key state |
-| `submitChannelSessionKeyState(state)` | Register channel session-key |
-| `getLastChannelKeyStates(userAddress, sessionKey?)` | Get active channel session-key states |
-| `signSessionKeyState(state)` | Sign an app-session key state |
-| `submitSessionKeyState(state)` | Register app-session key |
-| `getLastKeyStates(userAddress, sessionKey?)` | Get active app-session key states |
-
-### Asset Resolution
-
-| Method | Description |
-|--------|-------------|
-| `resolveToken(tokenAddress)` | Look up asset info by token address |
-| `resolveAsset(symbol)` | Look up asset info by symbol |
-| `resolveAssetDisplay(tokenAddress, chainId?)` | Get display-friendly symbol + decimals |
-| `getTokenDecimals(tokenAddress)` | Get decimals for a token |
-| `formatAmount(tokenAddress, rawAmount)` | Raw bigint → human-readable string |
-| `parseAmount(tokenAddress, humanAmount)` | Human-readable string → raw bigint |
-| `findOpenChannel(tokenAddress, chainId?)` | Find an open channel for a given token |
-
-### Lifecycle
-
-| Method | Description |
-|--------|-------------|
-| `ping()` | Health check |
-| `close()` | Close the WebSocket connection |
-| `refreshAssets()` | Re-fetch the asset map from the clearnode |
-
-## Properties
-
-| Property | Type | Description |
-|----------|------|-------------|
-| `innerClient` | `Client` (readonly) | The underlying v1.0.0 SDK Client |
-| `userAddress` | `Address` (readonly) | The connected wallet address |
+| Area | Covered surface |
+|---|---|
+| Channel operations | `deposit`, `depositAndCreateChannel`, `withdrawal`, `closeChannel`, `resizeChannel`, `challengeChannel`, `acknowledge` |
+| Query methods | `getChannels`, `getChannelData`, `getBalances`, `getLedgerEntries`, `getAppSessionsList`, `getAssetsList`, `getAccountInfo`, `getConfig`, `getBlockchains`, `getActionAllowances` |
+| Transfers | `transfer(destination, allocations)` with raw asset-unit strings |
+| App sessions | `createAppSession`, `closeAppSession`, `submitAppState`, `getAppDefinition`, `registerApp`, `getApps` |
+| App-session signing | `packCreateAppSessionHash`, `packSubmitAppStateHash`, `toWalletQuorumSignature`, `toSessionKeyQuorumSignature` |
+| Auth helpers | `createAuthRequestMessage`, `createAuthVerifyMessage`, `createAuthVerifyMessageWithJWT`, `createEIP712AuthMessageSigner` |
+| Event polling | `EventPoller` polls `getChannels()`, `getBalances()`, and `getAssetsList()` and emits legacy-shaped callbacks |
+
+`checkpointChannel(...)` is exported as a fail-fast migration shim; use `client.innerClient.checkpoint(asset)` instead.
+
+See [EventPoller](./event-poller) for the cookbook.
+
+Lifecycle helpers include `ping()`, `close()`, `waitForClose()`, and `refreshAssets()`.
+
+## What Compat Does Not Preserve
+
+:::warning Compat is curated, not a drop-in
+`@yellow-org/sdk-compat` preserves selected `@erc7824/nitrolite@0.5.3` app-facing APIs. It does not preserve:
+
+- the legacy server-push event model; use [EventPoller](./event-poller)
+- `checkpointChannel(...)`; it is a fail-fast stub, use `client.innerClient.checkpoint(asset)`
+- `get_session_keys` directory-style APIs
+- `get_rpc_history`
+- full root-export parity with `@erc7824/nitrolite@0.5.3`
+
+If your code touches these surfaces, run the codemod first, then use the migration guides below to finish the manual changes.
+:::
## Configuration
```typescript
interface NitroliteClientConfig {
- wsURL: string; // Clearnode WebSocket URL
+ wsURL: string; // Nitronode WebSocket URL
walletClient: WalletClient; // viem WalletClient with account
- chainId: number; // Chain ID (e.g. 11155111)
- blockchainRPCs?: Record; // Chain ID → RPC URL map
- channelSessionKeySigner?: { // Optional session key for quick approvals
+ chainId: number; // Chain ID, for example 11155111
+ blockchainRPCs?: Record; // Chain ID -> RPC URL map
+ channelSessionKeySigner?: {
sessionKeyPrivateKey: Hex;
walletAddress: Address;
metadataHash: Hex;
@@ -179,17 +141,15 @@ interface NitroliteClientConfig {
}
```
-### Environment Variables
-
`blockchainRPCsFromEnv()` reads from `NEXT_PUBLIC_BLOCKCHAIN_RPCS`:
```text
NEXT_PUBLIC_BLOCKCHAIN_RPCS=11155111:https://rpc.sepolia.io,1:https://mainnet.infura.io/v3/KEY
```
-## Accessing the v1.0.0 SDK
+## Accessing the v1 SDK
-The underlying v1.0.0 `Client` is exposed for advanced use cases not covered by the compat surface:
+`Client` is not re-exported from `@yellow-org/sdk-compat` for SSR safety. Import SDK classes directly from `@yellow-org/sdk`, or use the wrapped instance exposed on the compat client:
```typescript
const v1Client = client.innerClient;
@@ -200,57 +160,10 @@ await v1Client.approveToken(chainId, 'usdc', amount);
## Error Handling
-| Error Class | Code | Description |
-|-------------|------|-------------|
-| `AllowanceError` | `ALLOWANCE_INSUFFICIENT` | Token approval needed |
-| `UserRejectedError` | `USER_REJECTED` | User cancelled in wallet |
-| `InsufficientFundsError` | `INSUFFICIENT_FUNDS` | Not enough balance |
-| `NotInitializedError` | `NOT_INITIALIZED` | Client not connected |
-
-```typescript
-import { getUserFacingMessage, AllowanceError } from '@yellow-org/sdk-compat';
-
-try {
- await client.deposit(token, amount);
-} catch (err) {
- // Convert raw errors to typed compat errors
- const typed = NitroliteClient.classifyError(err);
- if (typed instanceof AllowanceError) {
- // prompt user to approve token spending
- }
- showToast(getUserFacingMessage(err));
-}
-```
-
-## Event Polling
-
-v0.5.3 used WebSocket push events. v1.0.0 uses polling. The `EventPoller` bridges this gap:
-
-```typescript
-import { EventPoller } from '@yellow-org/sdk-compat';
-
-const poller = new EventPoller(client, {
- onChannelUpdate: (channels) => updateUI(channels),
- onBalanceUpdate: (balances) => updateBalances(balances),
- onAssetsUpdate: (assets) => updateAssets(assets),
- onError: (err) => console.error(err),
-}, 5000);
-
-poller.start();
-```
-
-## Next.js Integration
-
-Add to `transpilePackages` in `next.config.ts`:
-
-```typescript
-const nextConfig = {
- transpilePackages: ['@yellow-org/sdk', '@yellow-org/sdk-compat'],
-};
-```
+The compat package exports typed errors plus `getUserFacingMessage(error)` for UI-safe messages. See [Errors and recovery](./errors) for the cookbook.
## Migration Guides
-- [Migration Overview](./migration-overview) — Pattern changes, import swaps
-- [On-Chain Changes](./migration-onchain) — Deposits, withdrawals, channels
-- [Off-Chain Changes](./migration-offchain) — Auth, app sessions, transfers
+- [Migration Overview](./migration-overview) - choose the compat path and run the codemod
+- [On-Chain Changes](./migration-onchain) - deposits, withdrawals, channel operations, and amount units
+- [Off-Chain Changes](./migration-offchain) - auth, app sessions, transfers, ledger queries, and polling
diff --git a/src/css/custom.css b/src/css/custom.css
index c8634c9..08105b8 100644
--- a/src/css/custom.css
+++ b/src/css/custom.css
@@ -218,6 +218,104 @@ a.table-of-contents__link.table-of-contents__link--active code {
color: #333333 !important;
}
+/* Nitrolite Build examples page */
+.nitrolite-example-list {
+ display: flex;
+ flex-direction: column;
+ gap: 24px;
+}
+
+.nitrolite-example-card {
+ border-radius: 8px;
+ overflow: hidden;
+}
+
+.nitrolite-example-card__layout {
+ display: grid;
+ grid-template-columns: minmax(340px, 48%) minmax(0, 1fr);
+ align-items: center;
+}
+
+.nitrolite-example-card__media {
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ align-self: center;
+ aspect-ratio: 16 / 10;
+ overflow: hidden;
+ background: var(--ifm-color-emphasis-100);
+ border-right: 1px solid var(--ifm-color-emphasis-200);
+}
+
+.nitrolite-example-card__image {
+ display: block;
+ width: 100%;
+ height: 100%;
+ object-fit: contain;
+ object-position: center;
+}
+
+.nitrolite-example-card__content {
+ align-self: stretch;
+ min-width: 0;
+}
+
+.nitrolite-example-card__content .card__header h2 {
+ margin: 0;
+ font-size: 1.55rem;
+ line-height: 1.2;
+}
+
+.nitrolite-example-card__summary {
+ margin-bottom: 1rem;
+}
+
+.nitrolite-example-card__details {
+ display: grid;
+ grid-template-columns: repeat(2, minmax(0, 1fr));
+ gap: 20px;
+}
+
+.nitrolite-example-card__details > div:last-child {
+ grid-column: 1 / -1;
+}
+
+.nitrolite-example-card__details code {
+ overflow-wrap: anywhere;
+}
+
+.nitrolite-example-card__details h3 {
+ margin-bottom: 0.5rem;
+ font-size: 1rem;
+}
+
+.nitrolite-example-card__details ul {
+ margin: 0;
+ padding-left: 1.1rem;
+}
+
+.nitrolite-example-card__details li {
+ margin-bottom: 0.35rem;
+}
+
+@media (max-width: 996px) {
+ .nitrolite-example-card__layout {
+ grid-template-columns: 1fr;
+ }
+
+ .nitrolite-example-card__media {
+ aspect-ratio: 16 / 10;
+ border-right: 0;
+ border-bottom: 1px solid var(--ifm-color-emphasis-200);
+ }
+}
+
+@media (max-width: 640px) {
+ .nitrolite-example-card__details {
+ grid-template-columns: 1fr;
+ }
+}
+
[data-theme='dark'] .table-of-contents__link:hover,
[data-theme='dark'] .table-of-contents__link:hover code {
color: #cccccc !important;
diff --git a/static/img/nitrolite/examples/cosign-demo.png b/static/img/nitrolite/examples/cosign-demo.png
new file mode 100644
index 0000000..87ba806
Binary files /dev/null and b/static/img/nitrolite/examples/cosign-demo.png differ
diff --git a/static/img/nitrolite/examples/nexus-p2p-transfer.png b/static/img/nitrolite/examples/nexus-p2p-transfer.png
new file mode 100644
index 0000000..cf1f921
Binary files /dev/null and b/static/img/nitrolite/examples/nexus-p2p-transfer.png differ
diff --git a/static/img/nitrolite/examples/nitrolite-store.png b/static/img/nitrolite/examples/nitrolite-store.png
new file mode 100644
index 0000000..af26978
Binary files /dev/null and b/static/img/nitrolite/examples/nitrolite-store.png differ