Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions sdk/ts-compat/CLAUDE.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# TypeScript SDK Compat (`@yellow-org/sdk-compat`)

Compatibility layer that bridges the old `@layer-3/nitrolite` v0.5.3 API to the `@yellow-org/sdk` v1.0.0+ runtime. Lets existing dApps upgrade with minimal code changes.
Curated migration layer that bridges the old `@layer-3/nitrolite` v0.5.3 API to the `@yellow-org/sdk` v1 runtime. Helps existing dApps migrate supported app-facing paths.

## Quick Reference

Expand All @@ -13,7 +13,7 @@ Compatibility layer that bridges the old `@layer-3/nitrolite` v0.5.3 API to the
## Package Details

- **Name:** `@yellow-org/sdk-compat`
- **Version:** 1.2.1
- **Version:** 1.2.0
- **Peer deps:** `@yellow-org/sdk >=1.2.0`, `viem ^2.0.0`
- **Dev dep:** `"@yellow-org/sdk": "file:../ts"` — **must build `sdk/ts` first**

Expand All @@ -25,7 +25,7 @@ The main SDK (`@yellow-org/sdk`) has side effects on module evaluation that brea

**SAFE:** `export type { StateSigner } from '@yellow-org/sdk'` (type-only exports are erased at compile time).

This is documented in `src/index.ts` lines 154-158.
This is documented in `src/index.ts`.

## Source Layout

Expand Down Expand Up @@ -57,4 +57,4 @@ This is documented in `src/index.ts` lines 154-158.
2. Export it from `src/index.ts`
3. If re-exporting from `@yellow-org/sdk`, use `export type` only (SSR safety)
4. Update `README.md` (Types Reference, RPC Stubs, or Auth Helpers section)
5. Add a test in `test/unit/exports.test.ts`
5. Add or update a focused unit test under `test/unit/` that matches the surface you changed
41 changes: 25 additions & 16 deletions sdk/ts-compat/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,25 @@

[![License](https://img.shields.io/npm/l/@yellow-org/sdk-compat.svg)](https://github.com/layer-3/nitrolite/blob/main/LICENSE)

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 that preserves selected Nitrolite SDK **v0.5.3 app-facing APIs** over the **v1 runtime**.

- Keep v0.5.3-style app-facing calls in your code.
- Keep supported v0.5.3-style app-facing calls in your code.
- Run them through `@yellow-org/sdk-compat`, backed by `@yellow-org/sdk`.
- Treat it as a migration aid, not a drop-in replacement for the full published v0.5.3 package.

## Compatibility Scope

`@yellow-org/sdk-compat` is intentionally narrower than the published v0.5.3 package surface.

- **Preserved app-facing APIs**: the `NitroliteClient` facade, selected auth helpers, app-session signing helpers, and many app-facing types remain available for supported migration paths.
- **Transitional helper surfaces**: many legacy `create*Message` / `parse*Response` exports remain so imports can keep compiling during migration, but several are transitional shims rather than one-to-one v1 RPC mappings.
- **Unsupported full-package parity**: low-level internals, broad root-export parity, and every legacy helper being runtime-faithful are not promised by this package.

## Why

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.
The v1 protocol changes wire format, authentication, WebSocket lifecycle, unit handling, asset resolution, and more. For apps built around the old surface, a direct migration can require scattered rewrites across transport, signing, and amount-handling paths.

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%**.
The compat layer centralizes the supported migration paths into one package so app code can move to client-level methods incrementally instead of rewriting every call site at once.

## Build Size

Expand All @@ -32,7 +41,7 @@ npm pack --dry-run --json

## Migration Guide

Step-by-step guides for migrating from v0.5.3:
Step-by-step guides for migrating supported app-facing paths from v0.5.3:

- [Overview & Quick Start](./docs/migration-overview.md) — pattern changes, import swaps
- [On-Chain Changes](./docs/migration-onchain.md) — deposits, withdrawals, channels
Expand Down Expand Up @@ -65,7 +74,7 @@ const client = await NitroliteClient.create({

### 2. Deposit & create a channel

In v1.0.0, channel creation is implicit on deposit — no separate `createChannel()` call needed:
In v1, channel creation is implicit on deposit — no separate `createChannel()` call needed:

```typescript
const tokenAddress = '0x6E2C4707DA119425DF2C722E2695300154652F56'; // USDC on Sepolia
Expand Down Expand Up @@ -211,9 +220,9 @@ await client.close();
| `waitForClose()` | Returns a promise that resolves when the connection is closed |
| `refreshAssets()` | Re-fetch the asset map from the clearnode |

### Accessing the v1.0.0 SDK Directly
### Accessing the v1 SDK Directly

The underlying v1.0.0 `Client` is exposed for advanced use cases not covered by the compat surface:
The underlying v1 `Client` is exposed for advanced use cases not covered by the compat surface:

```typescript
const v1Client = client.innerClient;
Expand Down Expand Up @@ -253,7 +262,7 @@ NEXT_PUBLIC_BLOCKCHAIN_RPCS=11155111:https://rpc.sepolia.io,1:https://mainnet.in

### `WalletStateSigner`

A v0.5.3-compatible signer class that wraps a `WalletClient`. Actual state signing in v1.0.0 is handled internally by `ChannelDefaultSigner`; this class exists so existing store types compile:
A v0.5.3-compatible signer class that wraps a `WalletClient`. Actual state signing in v1 is handled internally by `ChannelDefaultSigner`; this class exists so existing store types compile:

```typescript
import { WalletStateSigner } from '@yellow-org/sdk-compat';
Expand Down Expand Up @@ -317,7 +326,7 @@ try {

## Event Polling

v0.5.3 used server-push WebSocket events. v1.0.0 uses a polling model. The `EventPoller` bridges this gap:
v0.5.3 used server-push WebSocket events. v1 uses a polling model. The `EventPoller` bridges this gap:

```typescript
import { EventPoller } from '@yellow-org/sdk-compat';
Expand Down Expand Up @@ -377,12 +386,12 @@ The compat layer accepts raw amounts (smallest token unit) and converts to human

## RPC Stubs

The following functions exist so that any remaining v0.5.3 `create*Message` / `parse*Response` imports compile.
`create*` helpers are mostly placeholders; `parse*` helpers perform lightweight normalization of known response shapes.
Prefer calling `NitroliteClient` methods directly for new integrations:
The following functions remain exported primarily so legacy `create*Message` / `parse*Response` imports can keep compiling while an app migrates.
Many `create*` helpers are transitional shims rather than protocol-backed one-to-one v1 RPC mappings, and `parse*` helpers only do lightweight normalization of known response shapes.
Prefer `NitroliteClient` methods directly for new integrations:

```typescript
// These compile but do nothing meaningful:
// Transitional compat exports:
createGetChannelsMessage, parseGetChannelsResponse,
createGetLedgerBalancesMessage, parseGetLedgerBalancesResponse,
parseGetLedgerEntriesResponse, parseGetAppSessionsResponse,
Expand Down Expand Up @@ -462,7 +471,7 @@ All legacy compat types are re-exported from `@yellow-org/sdk-compat`:

### `buildClientOptions`

Converts a `CompatClientConfig` into v1.0.0 `Option[]` values passed to `Client.create()`. Useful if you need to customise the underlying SDK client beyond what `NitroliteClient.create()` exposes:
Converts a `CompatClientConfig` into v1 `Option[]` values passed to `Client.create()`. Useful if you need to customise the underlying SDK client beyond what `NitroliteClient.create()` exposes:

```typescript
import { buildClientOptions, type CompatClientConfig } from '@yellow-org/sdk-compat';
Expand Down Expand Up @@ -491,7 +500,7 @@ const nextConfig = {

| Package | Version |
|---|---|
| `@yellow-org/sdk` | `>=1.0.0` |
| `@yellow-org/sdk` | `>=1.2.0` |
| `viem` | `^2.0.0` |

## License
Expand Down
8 changes: 4 additions & 4 deletions sdk/ts-compat/docs/migration-offchain.md
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
# Off-Chain Migration Guide

This guide covers off-chain operations when migrating from v0.5.3 to the compat layer: authentication, app sessions, transfers, ledger queries, event polling, and RPC compatibility helpers.
This guide covers off-chain operations when migrating from v0.5.3 to the compat layer: authentication, app sessions, transfers, ledger queries, event polling, and transitional RPC helper imports.

## 1. 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.
v1 handles authentication internally when using `NitroliteClient`. For legacy WebSocket-auth code paths, the compat layer keeps `createAuthRequestMessage`, `createAuthVerifyMessage`, `createAuthVerifyMessageWithJWT`, and `createEIP712AuthMessageSigner` available.

## 2. App Sessions

Expand Down Expand Up @@ -54,7 +54,7 @@ await sendRequest(msg);

## 5. Event Polling

v0.5.3 used WebSocket push events (`ChannelUpdate`, `BalanceUpdate`). v1.0.0 uses polling. The compat layer provides `EventPoller`:
v0.5.3 used WebSocket push events (`ChannelUpdate`, `BalanceUpdate`). v1 uses polling. The compat layer provides `EventPoller`:

```typescript
import { EventPoller } from '@yellow-org/sdk-compat';
Expand All @@ -70,4 +70,4 @@ poller.start();

## 6. RPC Compatibility Helpers

The `create*Message` and `parse*Response` functions still exist so existing imports compile. Most `create*Message` helpers are transitional placeholders; prefer `NitroliteClient` methods directly for new code. Examples: `createGetChannelsMessage`, `parseGetChannelsResponse`, `createTransferMessage`, `createAppSessionMessage`, `createCloseAppSessionMessage`, etc.
The `create*Message` and `parse*Response` exports still exist primarily so legacy imports can keep compiling while you migrate call sites. Treat them as transitional compatibility shims, not as proof of full one-to-one v1 RPC coverage. For new code, prefer `NitroliteClient` methods directly. Examples: `createGetChannelsMessage`, `parseGetChannelsResponse`, `createTransferMessage`, `createAppSessionMessage`, `createCloseAppSessionMessage`, etc.
4 changes: 3 additions & 1 deletion sdk/ts-compat/docs/migration-onchain.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,8 @@ await client.withdrawal(tokenAddress, amount);

## 3. Channel Operations

Legacy channel helper imports may still exist to keep migration moving, but the supported path is the compat client methods below. Do not treat every legacy helper name as a protocol-backed one-to-one v1 RPC.

| Operation | v0.5.3 | Compat |
|-----------|--------|--------|
| Create | Explicit `createChannel()` | Implicit on first `deposit()` |
Expand Down Expand Up @@ -64,7 +66,7 @@ const amount = 11_000_000n; // 11 USDC (6 decimals)
// Manual conversion for display: formatUnits(amount, 6)
```

**After (compat):** Accepts both; conversion handled internally
**After (compat):** App-facing methods still accept raw token amounts, and the compat layer handles the conversion needed to call the v1 SDK correctly

```typescript
// Raw BigInt still works
Expand Down
16 changes: 7 additions & 9 deletions sdk/ts-compat/docs/migration-overview.md
Original file line number Diff line number Diff line change
@@ -1,12 +1,10 @@
# Migrating from v0.5.3 to Compat Layer

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.
This guide explains how to migrate your Nitrolite dApp from the v0.5.3 SDK to the **compat layer**, a curated migration layer that preserves selected app-facing APIs over the v1 runtime.

## 1. Why Use the Compat Layer

The v1.0.0 protocol introduces breaking changes across wire format, authentication, WebSocket lifecycle, unit system, asset resolution, and more. A direct migration touches **20+ files** per app with deep, scattered rewrites.

The compat layer centralises this complexity into **~5 file changes** per app. Instead of rewriting every RPC call, you swap imports and replace the `create-sign-send-parse` pattern with direct client method calls.
The v1 protocol changes wire format, authentication, WebSocket lifecycle, unit handling, and asset resolution. Instead of rewriting every RPC call at once, the compat layer lets supported app-facing paths move over incrementally by swapping imports and replacing the `create-sign-send-parse` pattern with direct client method calls.

## 2. Installation

Expand All @@ -21,9 +19,9 @@ npm install @yellow-org/sdk viem
| 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` |
| Types: `AppSession`, `LedgerChannel`, `RPCAppDefinition` | Many app-facing types remain re-exported from `@yellow-org/sdk-compat` |

For **types**, just change the package name. For **functions**, switch to client methods instead of `create*Message` / `parse*Response`.
For **types**, many app-facing imports only need a package-name swap. For **functions**, prefer client methods instead of `create*Message` / `parse*Response`. Some legacy helper imports remain exported only as transitional migration shims.

## 4. The Key Pattern Change

Expand All @@ -45,8 +43,8 @@ const channels = await client.getChannels();

## 5. What Stays the Same

- **Type shapes:** `AppSession`, `LedgerChannel`, `RPCAppDefinition`, `RPCBalance`, `RPCAsset`, etc.
- **Response formats:** Balances, ledger entries, app sessions — same structure as v0.5.3.
- **Many app-facing type shapes:** `AppSession`, `LedgerChannel`, `RPCAppDefinition`, `RPCBalance`, `RPCAsset`, etc.
- **Familiar response shapes:** balances, ledger entries, and app sessions remain close to v0.5.3 for the supported app-facing paths.
- **Auth helpers:** `createAuthRequestMessage`, `createAuthVerifyMessage`, `createAuthVerifyMessageWithJWT`, and `createEIP712AuthMessageSigner` remain available for legacy auth flows.

## 6. What Changes
Expand All @@ -55,7 +53,7 @@ const channels = await client.getChannels();
|---------|--------|--------|
| 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 |
| Amounts | Raw `BigInt` everywhere | Compat keeps raw-unit app-facing inputs and handles the v1 bridge internally |
| Contract addresses | Manual config | Fetched from clearnode `get_config` |
| Channel creation | Explicit `createChannel()` | Implicit on first `deposit()` |

Expand Down
26 changes: 26 additions & 0 deletions sdk/ts-compat/eslint.config.cjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
const tseslint = require('@typescript-eslint/eslint-plugin');
const tsParser = require('@typescript-eslint/parser');

module.exports = [
{
ignores: ['dist/**', 'node_modules/**'],
},
{
files: ['src/**/*.ts', 'test/**/*.ts'],
languageOptions: {
parser: tsParser,
parserOptions: {
ecmaVersion: 'latest',
sourceType: 'module',
},
},
plugins: {
'@typescript-eslint': tseslint,
},
rules: {
...tseslint.configs.recommended.rules,
'@typescript-eslint/no-explicit-any': 'off',
'@typescript-eslint/no-unused-vars': 'off',
},
},
];
24 changes: 24 additions & 0 deletions sdk/ts-compat/jest.config.cjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
/** @type {import('ts-jest').JestConfigWithTsJest} */
module.exports = {
preset: 'ts-jest/presets/default-esm',
testEnvironment: 'node',
roots: ['<rootDir>/test/unit'],
testMatch: ['**/*.test.ts'],
extensionsToTreatAsEsm: ['.ts'],
transform: {
'^.+\\.ts$': [
'ts-jest',
{
useESM: true,
tsconfig: {
module: 'Node16',
moduleResolution: 'Node16',
types: ['node', 'jest'],
},
},
],
},
moduleNameMapper: {
'^(\\.{1,2}/.*)\\.js$': '$1',
},
};
Loading
Loading