Skip to main content
Version: 1.x

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.

Why Use the Compat Layer

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 compat layer centralises this complexity into ~1,000 lines that absorb the protocol differences, reducing per-app integration effort by an estimated 56–70%.

Installation

npm install @yellow-org/sdk-compat
# peer dependencies
npm install @yellow-org/sdk viem

Quick Start

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',
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' }]);

// Cleanup
await client.closeChannel();
await client.close();

Method Cheat Sheet

Channel Operations

MethodDescription
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

MethodDescription
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

MethodDescription
transfer(destination, allocations)Off-chain transfer to another participant

App Sessions

MethodDescription
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

HelperDescription
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

MethodDescription
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

MethodDescription
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

MethodDescription
ping()Health check
close()Close the WebSocket connection
refreshAssets()Re-fetch the asset map from the clearnode

Properties

PropertyTypeDescription
innerClientClient (readonly)The underlying v1.0.0 SDK Client
userAddressAddress (readonly)The connected wallet address

Configuration

interface NitroliteClientConfig {
wsURL: string; // Clearnode WebSocket URL
walletClient: WalletClient; // viem WalletClient with account
chainId: number; // Chain ID (e.g. 11155111)
blockchainRPCs?: Record<number, string>; // Chain ID → RPC URL map
channelSessionKeySigner?: { // Optional session key for quick approvals
sessionKeyPrivateKey: Hex;
walletAddress: Address;
metadataHash: Hex;
authSig: Hex;
};
}

Environment Variables

blockchainRPCsFromEnv() reads from NEXT_PUBLIC_BLOCKCHAIN_RPCS:

NEXT_PUBLIC_BLOCKCHAIN_RPCS=11155111:https://rpc.sepolia.io,1:https://mainnet.infura.io/v3/KEY

Accessing the v1.0.0 SDK

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

const v1Client = client.innerClient;
await v1Client.getHomeChannel(wallet, 'usdc');
await v1Client.checkpoint('usdc');
await v1Client.approveToken(chainId, 'usdc', amount);

Error Handling

Error ClassCodeDescription
AllowanceErrorALLOWANCE_INSUFFICIENTToken approval needed
UserRejectedErrorUSER_REJECTEDUser cancelled in wallet
InsufficientFundsErrorINSUFFICIENT_FUNDSNot enough balance
NotInitializedErrorNOT_INITIALIZEDClient not connected
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:

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:

const nextConfig = {
transpilePackages: ['@yellow-org/sdk', '@yellow-org/sdk-compat'],
};

Migration Guides