@yellow-org/sdk 1.0.0-alpha.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (72) hide show
  1. package/README.md +984 -0
  2. package/dist/abis/generated.d.ts +4300 -0
  3. package/dist/abis/generated.js +1 -0
  4. package/dist/app/index.d.ts +2 -0
  5. package/dist/app/index.js +2 -0
  6. package/dist/app/packing.d.ts +7 -0
  7. package/dist/app/packing.js +111 -0
  8. package/dist/app/types.d.ts +91 -0
  9. package/dist/app/types.js +42 -0
  10. package/dist/asset_store.d.ts +13 -0
  11. package/dist/asset_store.js +121 -0
  12. package/dist/blockchain/evm/channel_hub_abi.d.ts +4284 -0
  13. package/dist/blockchain/evm/channel_hub_abi.js +5475 -0
  14. package/dist/blockchain/evm/client.d.ts +46 -0
  15. package/dist/blockchain/evm/client.js +428 -0
  16. package/dist/blockchain/evm/erc20.d.ts +13 -0
  17. package/dist/blockchain/evm/erc20.js +54 -0
  18. package/dist/blockchain/evm/erc20_abi.d.ts +144 -0
  19. package/dist/blockchain/evm/erc20_abi.js +96 -0
  20. package/dist/blockchain/evm/index.d.ts +6 -0
  21. package/dist/blockchain/evm/index.js +6 -0
  22. package/dist/blockchain/evm/interface.d.ts +10 -0
  23. package/dist/blockchain/evm/interface.js +1 -0
  24. package/dist/blockchain/evm/types.d.ts +27 -0
  25. package/dist/blockchain/evm/types.js +1 -0
  26. package/dist/blockchain/evm/utils.d.ts +9 -0
  27. package/dist/blockchain/evm/utils.js +129 -0
  28. package/dist/blockchain/index.d.ts +1 -0
  29. package/dist/blockchain/index.js +1 -0
  30. package/dist/client.d.ts +99 -0
  31. package/dist/client.js +720 -0
  32. package/dist/config.d.ts +12 -0
  33. package/dist/config.js +28 -0
  34. package/dist/core/event.d.ts +29 -0
  35. package/dist/core/event.js +1 -0
  36. package/dist/core/index.d.ts +6 -0
  37. package/dist/core/index.js +6 -0
  38. package/dist/core/interface.d.ts +53 -0
  39. package/dist/core/interface.js +1 -0
  40. package/dist/core/state.d.ts +21 -0
  41. package/dist/core/state.js +267 -0
  42. package/dist/core/state_packer.d.ts +13 -0
  43. package/dist/core/state_packer.js +98 -0
  44. package/dist/core/types.d.ts +203 -0
  45. package/dist/core/types.js +220 -0
  46. package/dist/core/utils.d.ts +16 -0
  47. package/dist/core/utils.js +181 -0
  48. package/dist/index.d.ts +9 -0
  49. package/dist/index.js +9 -0
  50. package/dist/rpc/api.d.ts +181 -0
  51. package/dist/rpc/api.js +1 -0
  52. package/dist/rpc/client.d.ts +36 -0
  53. package/dist/rpc/client.js +102 -0
  54. package/dist/rpc/dialer.d.ts +30 -0
  55. package/dist/rpc/dialer.js +146 -0
  56. package/dist/rpc/error.d.ts +18 -0
  57. package/dist/rpc/error.js +27 -0
  58. package/dist/rpc/index.d.ts +7 -0
  59. package/dist/rpc/index.js +7 -0
  60. package/dist/rpc/message.d.ts +25 -0
  61. package/dist/rpc/message.js +102 -0
  62. package/dist/rpc/methods.d.ts +30 -0
  63. package/dist/rpc/methods.js +27 -0
  64. package/dist/rpc/types.d.ts +101 -0
  65. package/dist/rpc/types.js +1 -0
  66. package/dist/signers.d.ts +48 -0
  67. package/dist/signers.js +96 -0
  68. package/dist/utils/sign.d.ts +2 -0
  69. package/dist/utils/sign.js +8 -0
  70. package/dist/utils.d.ts +42 -0
  71. package/dist/utils.js +226 -0
  72. package/package.json +89 -0
package/README.md ADDED
@@ -0,0 +1,984 @@
1
+ # Clearnode TypeScript SDK
2
+
3
+ [![npm version](https://img.shields.io/npm/v/@yellow-org/sdk.svg)](https://www.npmjs.com/package/@yellow-org/sdk)
4
+ [![License](https://img.shields.io/npm/l/@yellow-org/sdk.svg)](https://github.com/erc7824/nitrolite/blob/main/LICENSE)
5
+
6
+ TypeScript SDK for Clearnode payment channels providing both high-level and low-level operations in a unified client:
7
+ - **State Operations**: `deposit()`, `withdraw()`, `transfer()`, `closeHomeChannel()`, `acknowledge()` - build and co-sign states off-chain
8
+ - **Blockchain Settlement**: `checkpoint()` - the single entry point for all on-chain transactions
9
+ - **Low-Level Operations**: Direct RPC access for custom flows and advanced use cases
10
+ - **Full Feature Parity**: 100% compatibility with Go SDK functionality
11
+
12
+ > If you're an old developer who is looking to upgrade from @erc7824/nitrolite@v0.5.3, please try out the [@yellow-org/sdk-compat](https://www.npmjs.com/package/@yellow-org/sdk-compat) which is a translation layer that uses this package underneath by mapping the 0.5.3 familiar api surfaces to this sdk
13
+
14
+ ## Method Cheat Sheet
15
+
16
+ ### State Operations (Off-Chain)
17
+ ```typescript
18
+ client.deposit(blockchainId, asset, amount) // Prepare deposit state
19
+ client.withdraw(blockchainId, asset, amount) // Prepare withdrawal state
20
+ client.transfer(recipientWallet, asset, amount) // Prepare transfer state
21
+ client.closeHomeChannel(asset) // Prepare finalize state
22
+ client.acknowledge(asset) // Acknowledge received state
23
+ ```
24
+
25
+ ### Blockchain Settlement
26
+ ```typescript
27
+ client.checkpoint(asset) // Settle latest state on-chain
28
+ client.challenge(state) // Submit on-chain challenge
29
+ client.approveToken(chainId, asset, amount) // Approve token spending
30
+ client.checkTokenAllowance(chainId, token, owner) // Check token allowance
31
+ ```
32
+
33
+ ### Node Information
34
+ ```typescript
35
+ client.ping() // Health check
36
+ client.getConfig() // Node configuration
37
+ client.getBlockchains() // Supported blockchains
38
+ client.getAssets(blockchainId?) // Supported assets
39
+ ```
40
+
41
+ ### User Queries
42
+ ```typescript
43
+ client.getBalances(wallet) // User balances
44
+ client.getTransactions(wallet, opts) // Transaction history
45
+ ```
46
+
47
+ ### Channel Queries
48
+ ```typescript
49
+ client.getChannels(wallet, options?) // List all channels
50
+ client.getHomeChannel(wallet, asset) // Home channel info
51
+ client.getEscrowChannel(escrowChannelId) // Escrow channel info
52
+ client.getLatestState(wallet, asset, onlySigned) // Latest state
53
+ ```
54
+
55
+ ### App Sessions
56
+ ```typescript
57
+ client.getAppSessions(opts) // List sessions
58
+ client.getAppDefinition(appSessionId) // Session definition
59
+ client.createAppSession(definition, sessionData, sigs) // Create session
60
+ client.submitAppSessionDeposit(update, sigs, asset, amount) // Deposit to session
61
+ client.submitAppState(update, sigs) // Update session
62
+ client.rebalanceAppSessions(signedUpdates) // Atomic rebalance
63
+ ```
64
+
65
+ ### App Session Keys
66
+ ```typescript
67
+ client.signSessionKeyState(state) // Sign app session key state
68
+ client.submitSessionKeyState(state) // Register/update app session key
69
+ client.getLastKeyStates(userAddress, sessionKey?) // Get active app session key states
70
+ ```
71
+
72
+ ### Channel Session Keys
73
+ ```typescript
74
+ client.signChannelSessionKeyState(state) // Sign channel session key state
75
+ client.submitChannelSessionKeyState(state) // Register/update channel session key
76
+ client.getLastChannelKeyStates(userAddress, sessionKey?) // Get active channel session key states
77
+ ```
78
+
79
+ ### Shared Utilities
80
+ ```typescript
81
+ client.close() // Close connection
82
+ client.waitForClose() // Connection monitor promise
83
+ client.signState(state) // Sign a state (advanced)
84
+ client.getUserAddress() // Get signer's address
85
+ client.setHomeBlockchain(asset, chainId) // Set default blockchain for asset
86
+ ```
87
+
88
+ ## Installation
89
+
90
+ ```bash
91
+ npm install @yellow-org/sdk
92
+ # or
93
+ yarn add @yellow-org/sdk
94
+ # or
95
+ pnpm add @yellow-org/sdk
96
+ ```
97
+
98
+ ## Quick Start
99
+
100
+ ### Unified Client (High-Level + Low-Level)
101
+
102
+ ```typescript
103
+ import { Client, createSigners, withBlockchainRPC } from '@yellow-org/sdk';
104
+ import Decimal from 'decimal.js';
105
+
106
+ async function main() {
107
+ // Create signers from private key
108
+ const { stateSigner, txSigner } = createSigners(
109
+ process.env.PRIVATE_KEY as `0x${string}`
110
+ );
111
+
112
+ // Create unified client
113
+ const client = await Client.create(
114
+ 'wss://clearnode.example.com/ws',
115
+ stateSigner,
116
+ txSigner,
117
+ withBlockchainRPC(80002n, 'https://polygon-amoy.alchemy.com/v2/KEY')
118
+ );
119
+
120
+ try {
121
+ // Step 1: Build and co-sign states off-chain
122
+ const state = await client.deposit(80002n, 'usdc', new Decimal(100));
123
+ console.log('Deposit state version:', state.version);
124
+
125
+ // Step 2: Settle on-chain via checkpoint
126
+ const txHash = await client.checkpoint('usdc');
127
+ console.log('On-chain tx:', txHash);
128
+
129
+ // Transfer (off-chain only, no checkpoint needed for existing channels)
130
+ const transferState = await client.transfer('0xRecipient...', 'usdc', new Decimal(50));
131
+
132
+ // Low-level operations - same client
133
+ const config = await client.getConfig();
134
+ const balances = await client.getBalances(client.getUserAddress());
135
+ } finally {
136
+ await client.close();
137
+ }
138
+ }
139
+
140
+ main().catch(console.error);
141
+ ```
142
+
143
+ ## Architecture
144
+
145
+ ```
146
+ sdk/ts/src/
147
+ ├── client.ts # Core client, constructors, high-level operations
148
+ ├── signers.ts # EthereumMsgSigner and EthereumRawSigner
149
+ ├── config.ts # Configuration options
150
+ ├── asset_store.ts # Asset metadata caching
151
+ ├── utils.ts # Type transformations
152
+ ├── core/ # State management, transitions, types
153
+ ├── rpc/ # WebSocket RPC client
154
+ ├── blockchain/ # EVM blockchain interactions
155
+ └── app/ # App session types and logic
156
+ ```
157
+
158
+ ## Client API
159
+
160
+ ### Creating a Client
161
+
162
+ ```typescript
163
+ import { Client, createSigners, withBlockchainRPC } from '@yellow-org/sdk';
164
+
165
+ // Step 1: Create signers from private key
166
+ const { stateSigner, txSigner } = createSigners('0x1234...');
167
+
168
+ // Step 2: Create unified client
169
+ const client = await Client.create(
170
+ wsURL,
171
+ stateSigner, // For signing channel states
172
+ txSigner, // For signing blockchain transactions
173
+ withBlockchainRPC(chainId, rpcURL), // Required for Checkpoint
174
+ withHandshakeTimeout(10000), // Optional: connection timeout
175
+ withPingInterval(5000) // Optional: keepalive interval
176
+ );
177
+
178
+ // Step 3: (Optional) Set home blockchain for assets
179
+ // Required for Transfer operations that may trigger channel creation
180
+ await client.setHomeBlockchain('usdc', 80002n);
181
+ ```
182
+
183
+ ### Signer Implementations
184
+
185
+ The SDK provides two signer types matching the Go SDK patterns:
186
+
187
+ #### EthereumMsgSigner (for channel states)
188
+
189
+ Signs channel state updates with EIP-191 "Ethereum Signed Message" prefix.
190
+
191
+ ```typescript
192
+ import { EthereumMsgSigner } from '@yellow-org/sdk';
193
+ import { privateKeyToAccount } from 'viem/accounts';
194
+
195
+ // From private key
196
+ const signer1 = new EthereumMsgSigner('0x...');
197
+
198
+ // From viem account
199
+ const account = privateKeyToAccount('0x...');
200
+ const signer2 = new EthereumMsgSigner(account);
201
+ ```
202
+
203
+ **When to use**: All off-chain operations (state signatures, transfers)
204
+
205
+ #### EthereumRawSigner (for blockchain transactions)
206
+
207
+ Signs raw hashes directly without prefix for on-chain operations.
208
+
209
+ ```typescript
210
+ import { EthereumRawSigner } from '@yellow-org/sdk';
211
+
212
+ const signer = new EthereumRawSigner('0x...');
213
+ ```
214
+
215
+ **When to use**: On-chain operations (deposits, withdrawals, channel creation)
216
+
217
+ #### Helper: createSigners()
218
+
219
+ ```typescript
220
+ import { createSigners } from '@yellow-org/sdk';
221
+
222
+ // Creates both signers at once
223
+ const { stateSigner, txSigner } = createSigners('0x...');
224
+ const client = await Client.create(wsURL, stateSigner, txSigner);
225
+ ```
226
+
227
+ ### Configuring Home Blockchain
228
+
229
+ #### `setHomeBlockchain(asset, blockchainId)`
230
+
231
+ Sets the default blockchain network for a specific asset. Required for `transfer()` operations that may trigger channel creation.
232
+
233
+ ```typescript
234
+ await client.setHomeBlockchain('usdc', 80002n);
235
+ ```
236
+
237
+ **Important Notes:**
238
+ - This mapping is immutable once set for the client instance
239
+ - The asset must be supported on the specified blockchain
240
+ - Required before calling `transfer()` on a new channel
241
+
242
+ ### State Operations
243
+
244
+ All state operations build and co-sign a state off-chain. They return `Promise<core.State>`. Use `checkpoint()` to settle the state on-chain.
245
+
246
+ #### `deposit(blockchainId, asset, amount): Promise<core.State>`
247
+
248
+ Prepares a deposit state. Creates a new channel if none exists, otherwise advances the existing state.
249
+
250
+ ```typescript
251
+ const state = await client.deposit(80002n, 'usdc', new Decimal(100));
252
+ const txHash = await client.checkpoint('usdc'); // settle on-chain
253
+ ```
254
+
255
+ **Requirements:**
256
+ - Sufficient token balance (checked on-chain during checkpoint)
257
+
258
+ **Scenarios:**
259
+ 1. **No channel exists**: Creates new channel with initial deposit
260
+ 2. **Channel exists**: Advances the existing state with a deposit transition
261
+
262
+ #### `withdraw(blockchainId, asset, amount): Promise<core.State>`
263
+
264
+ Prepares a withdrawal state to remove funds from the channel.
265
+
266
+ ```typescript
267
+ const state = await client.withdraw(80002n, 'usdc', new Decimal(25));
268
+ const txHash = await client.checkpoint('usdc'); // settle on-chain
269
+ ```
270
+
271
+ **Requirements:**
272
+ - Existing channel with sufficient balance
273
+
274
+ #### `transfer(recipientWallet, asset, amount): Promise<core.State>`
275
+
276
+ Prepares an off-chain transfer to another wallet. For existing channels, no checkpoint is needed.
277
+
278
+ ```typescript
279
+ const state = await client.transfer(
280
+ '0xRecipient...', // Recipient address
281
+ 'usdc', // Asset symbol
282
+ new Decimal(50) // Amount
283
+ );
284
+ ```
285
+
286
+ **Requirements:**
287
+ - Existing channel with sufficient balance OR
288
+ - Home blockchain configured via `setHomeBlockchain()` (for new channels)
289
+
290
+ #### `closeHomeChannel(asset): Promise<core.State>`
291
+
292
+ Prepares a finalize state to close the user's channel for a specific asset.
293
+
294
+ ```typescript
295
+ const state = await client.closeHomeChannel('usdc');
296
+ const txHash = await client.checkpoint('usdc'); // close on-chain
297
+ ```
298
+
299
+ **Requirements:**
300
+ - Existing channel (user must have deposited first)
301
+
302
+ #### `acknowledge(asset): Promise<core.State>`
303
+
304
+ Acknowledges a received state (e.g., after receiving a transfer).
305
+
306
+ ```typescript
307
+ const state = await client.acknowledge('usdc');
308
+ ```
309
+
310
+ **Requirements:**
311
+ - Home blockchain configured via `setHomeBlockchain()` when no channel exists
312
+
313
+ ### Blockchain Settlement
314
+
315
+ #### `checkpoint(asset): Promise<string>`
316
+
317
+ Settles the latest co-signed state on-chain. This is the single entry point for all blockchain transactions. Based on the transition type and on-chain channel status, it calls the appropriate blockchain method:
318
+
319
+ - **Channel not on-chain** (status Void): Creates the channel
320
+ - **Deposit/Withdrawal on existing channel**: Checkpoints the state
321
+ - **Finalize**: Closes the channel
322
+
323
+ ```typescript
324
+ const txHash = await client.checkpoint('usdc');
325
+ ```
326
+
327
+ **Requirements:**
328
+ - Blockchain RPC configured via `withBlockchainRPC()`
329
+ - A co-signed state must exist (call `deposit()`, `withdraw()`, etc. first)
330
+ - Sufficient gas for the blockchain transaction
331
+
332
+ #### `challenge(state): Promise<string>`
333
+
334
+ Submits an on-chain challenge for a channel using a co-signed state. Initiates a dispute period on-chain.
335
+
336
+ ```typescript
337
+ const state = await client.getLatestState(wallet, 'usdc', true);
338
+ const txHash = await client.challenge(state);
339
+ ```
340
+
341
+ **Requirements:**
342
+ - State must have both user and node signatures
343
+
344
+ #### `approveToken(chainId, asset, amount): Promise<string>`
345
+
346
+ Approves the ChannelHub contract to spend tokens on behalf of the user. Required before depositing ERC-20 tokens.
347
+
348
+ ```typescript
349
+ const txHash = await client.approveToken(80002n, 'usdc', new Decimal(1000));
350
+ ```
351
+
352
+ #### `checkTokenAllowance(chainId, tokenAddress, owner): Promise<bigint>`
353
+
354
+ Checks the current token allowance for the ChannelHub contract.
355
+
356
+ ```typescript
357
+ const allowance = await client.checkTokenAllowance(80002n, '0xToken...', '0xOwner...');
358
+ ```
359
+
360
+ ## Low-Level API
361
+
362
+ All low-level RPC methods are available on the same Client instance.
363
+
364
+ ### Node Information
365
+
366
+ ```typescript
367
+ await client.ping();
368
+ const config = await client.getConfig();
369
+ const blockchains = await client.getBlockchains();
370
+ const assets = await client.getAssets(); // or client.getAssets(blockchainId)
371
+ ```
372
+
373
+ ### User Data
374
+
375
+ ```typescript
376
+ const balances = await client.getBalances(wallet);
377
+ const { transactions, metadata } = await client.getTransactions(wallet, {
378
+ page: 1,
379
+ pageSize: 50,
380
+ });
381
+ ```
382
+
383
+ ### Channel Queries
384
+
385
+ ```typescript
386
+ const { channels, metadata } = await client.getChannels(wallet);
387
+ const channel = await client.getHomeChannel(wallet, asset);
388
+ const escrow = await client.getEscrowChannel(escrowChannelId);
389
+ const state = await client.getLatestState(wallet, asset, onlySigned);
390
+ ```
391
+
392
+ **Note:** State submission and channel creation are handled internally by state operations (`deposit()`, `withdraw()`, `transfer()`). On-chain settlement is handled by `checkpoint()`.
393
+
394
+ ### App Sessions (Low-Level)
395
+
396
+ ```typescript
397
+ // Query sessions
398
+ const { sessions, metadata } = await client.getAppSessions(opts);
399
+ const definition = await client.getAppDefinition(appSessionId);
400
+
401
+ // Create and manage sessions
402
+ const { appSessionId, version, status } = await client.createAppSession(
403
+ definition,
404
+ sessionData,
405
+ signatures
406
+ );
407
+
408
+ const nodeSig = await client.submitAppSessionDeposit(
409
+ appUpdate,
410
+ quorumSigs,
411
+ asset,
412
+ depositAmount
413
+ );
414
+
415
+ await client.submitAppState(appUpdate, quorumSigs);
416
+
417
+ const batchId = await client.rebalanceAppSessions(signedUpdates);
418
+ ```
419
+
420
+ ### App Session Keys
421
+
422
+ ```typescript
423
+ // Sign and submit an app session key state
424
+ const sig = await client.signSessionKeyState({
425
+ user_address: '0x1234...',
426
+ session_key: '0xabcd...',
427
+ version: '1',
428
+ application_ids: ['app1'],
429
+ app_session_ids: [],
430
+ expires_at: String(Math.floor(Date.now() / 1000) + 86400),
431
+ user_sig: '0x',
432
+ });
433
+
434
+ await client.submitSessionKeyState({
435
+ user_address: '0x1234...',
436
+ session_key: '0xabcd...',
437
+ version: '1',
438
+ application_ids: ['app1'],
439
+ app_session_ids: [],
440
+ expires_at: String(Math.floor(Date.now() / 1000) + 86400),
441
+ user_sig: sig,
442
+ });
443
+
444
+ // Query active app session key states
445
+ const states = await client.getLastKeyStates('0x1234...');
446
+ const filtered = await client.getLastKeyStates('0x1234...', '0xSessionKey...');
447
+ ```
448
+
449
+ ### Channel Session Keys
450
+
451
+ ```typescript
452
+ // Sign and submit a channel session key state
453
+ const sig = await client.signChannelSessionKeyState({
454
+ user_address: '0x1234...',
455
+ session_key: '0xabcd...',
456
+ version: '1',
457
+ assets: ['usdc'],
458
+ expires_at: String(Math.floor(Date.now() / 1000) + 86400),
459
+ user_sig: '0x',
460
+ });
461
+
462
+ await client.submitChannelSessionKeyState({
463
+ user_address: '0x1234...',
464
+ session_key: '0xabcd...',
465
+ version: '1',
466
+ assets: ['usdc'],
467
+ expires_at: String(Math.floor(Date.now() / 1000) + 86400),
468
+ user_sig: sig,
469
+ });
470
+
471
+ // Query active channel session key states
472
+ const states = await client.getLastChannelKeyStates('0x1234...');
473
+ const filtered = await client.getLastChannelKeyStates('0x1234...', '0xSessionKey...');
474
+ ```
475
+
476
+ ## Key Concepts
477
+
478
+ ### State Management
479
+
480
+ Payment channels use versioned states signed by both user and node. The SDK uses a two-step pattern:
481
+
482
+ ```typescript
483
+ // Step 1: Build and co-sign state off-chain
484
+ const state = await client.deposit(...); // Returns core.State
485
+ const state = await client.withdraw(...); // Returns core.State
486
+ const state = await client.transfer(...); // Returns core.State
487
+
488
+ // Step 2: Settle on-chain (when needed)
489
+ const txHash = await client.checkpoint('usdc');
490
+ ```
491
+
492
+ **State Flow (Internal):**
493
+ 1. Get latest state with `getLatestState()`
494
+ 2. Create next state with `nextState()`
495
+ 3. Apply transition (deposit, withdraw, transfer, etc.)
496
+ 4. Sign state with `signState()`
497
+ 5. Submit to node for co-signing
498
+ 6. Return co-signed state
499
+
500
+ On-chain settlement is handled separately by `checkpoint()`.
501
+
502
+ ### Signing
503
+
504
+ States are signed using ECDSA with EIP-191/EIP-155:
505
+
506
+ ```typescript
507
+ // Create signers from private key
508
+ const { stateSigner, txSigner } = createSigners('0x...');
509
+
510
+ // Get address
511
+ const address = stateSigner.getAddress();
512
+ ```
513
+
514
+ **Signing Process:**
515
+ 1. State -> ABI Encode (via `packState`)
516
+ 2. Packed State -> Keccak256 Hash
517
+ 3. Hash -> ECDSA Sign (via signer)
518
+ 4. Result: 65-byte signature (R || S || V)
519
+
520
+ **Two Signer Types:**
521
+ - `EthereumMsgSigner`: Signs channel state updates (off-chain signatures) with EIP-191 prefix
522
+ - `EthereumRawSigner`: Signs blockchain transactions (on-chain operations) without prefix
523
+
524
+ ### Channel Lifecycle
525
+
526
+ 1. **Void**: No channel exists
527
+ 2. **Create**: Deposit creates channel on-chain
528
+ 3. **Open**: Channel active, can deposit/withdraw/transfer
529
+ 4. **Challenged**: Dispute initiated (advanced)
530
+ 5. **Closed**: Channel finalized (advanced)
531
+
532
+ ## When to Use State Operations vs Low-Level Operations
533
+
534
+ ### Use State Operations When:
535
+ - Building user-facing applications
536
+ - Need simple deposit/withdraw/transfer
537
+ - Want automatic state management with two-step pattern
538
+ - Don't need custom flows
539
+
540
+ ### Use Low-Level Operations When:
541
+ - Building infrastructure/tooling
542
+ - Implementing custom state transitions
543
+ - Need fine-grained control
544
+ - Working with app sessions directly
545
+
546
+ ## Error Handling
547
+
548
+ All errors include context:
549
+
550
+ ```typescript
551
+ try {
552
+ const state = await client.deposit(80002n, 'usdc', amount);
553
+ const txHash = await client.checkpoint('usdc');
554
+ } catch (error) {
555
+ // State error: "channel not created, deposit first"
556
+ // Checkpoint error: "failed to create channel on blockchain: insufficient balance"
557
+ console.error('Operation failed:', error);
558
+ }
559
+ ```
560
+
561
+ ### Common Errors
562
+
563
+ | Error Message | Cause | Solution |
564
+ |--------------|-------|----------|
565
+ | `"channel not created, deposit first"` | Transfer before deposit | Deposit funds first |
566
+ | `"home blockchain not set for asset"` | Missing `setHomeBlockchain()` | Call `setHomeBlockchain()` before transfer |
567
+ | `"blockchain client not configured"` | Missing `withBlockchainRPC()` | Add `withBlockchainRPC()` configuration |
568
+ | `"insufficient balance"` | Not enough funds | Deposit more funds |
569
+ | `"failed to sign state"` | Invalid private key or state | Check signer configuration |
570
+ | `"no channel exists for asset"` | Checkpoint called without a co-signed state | Call `deposit()`, `withdraw()`, etc. first |
571
+ | `"transition type ... does not require a blockchain operation"` | Checkpoint called on unsupported transition | Only checkpoint after deposit, withdraw, close, or acknowledge |
572
+
573
+ ### Custom Error Handler
574
+
575
+ ```typescript
576
+ const client = await Client.create(
577
+ wsURL,
578
+ stateSigner,
579
+ txSigner,
580
+ withErrorHandler((error) => {
581
+ console.error('[Connection Error]', error);
582
+ // Custom error handling logic
583
+ })
584
+ );
585
+ ```
586
+
587
+ ## Configuration Options
588
+
589
+ ```typescript
590
+ import {
591
+ withBlockchainRPC,
592
+ withHandshakeTimeout,
593
+ withPingInterval,
594
+ withErrorHandler
595
+ } from '@yellow-org/sdk';
596
+
597
+ const client = await Client.create(
598
+ wsURL,
599
+ stateSigner,
600
+ txSigner,
601
+ withBlockchainRPC(chainId, rpcURL), // Configure blockchain RPC (required for Checkpoint)
602
+ withHandshakeTimeout(10000), // Connection timeout (ms, default: 5000)
603
+ withPingInterval(5000), // Keepalive interval (ms, default: 5000)
604
+ withErrorHandler(func) // Connection error handler
605
+ );
606
+ ```
607
+
608
+ ## Complete Examples
609
+
610
+ ### Example 1: Basic Deposit and Transfer
611
+
612
+ ```typescript
613
+ import { Client, createSigners, withBlockchainRPC } from '@yellow-org/sdk';
614
+ import Decimal from 'decimal.js';
615
+
616
+ async function basicExample() {
617
+ const { stateSigner, txSigner } = createSigners(process.env.PRIVATE_KEY!);
618
+
619
+ const client = await Client.create(
620
+ 'wss://clearnode.example.com/ws',
621
+ stateSigner,
622
+ txSigner,
623
+ withBlockchainRPC(80002n, process.env.RPC_URL!)
624
+ );
625
+
626
+ try {
627
+ console.log('User:', client.getUserAddress());
628
+
629
+ // Set home blockchain
630
+ await client.setHomeBlockchain('usdc', 80002n);
631
+
632
+ // Step 1: Build and co-sign deposit state
633
+ const depositState = await client.deposit(80002n, 'usdc', new Decimal(100));
634
+ console.log('Deposit state version:', depositState.version);
635
+
636
+ // Step 2: Settle on-chain
637
+ const txHash = await client.checkpoint('usdc');
638
+ console.log('On-chain tx:', txHash);
639
+
640
+ // Check balance
641
+ const balances = await client.getBalances(client.getUserAddress());
642
+ console.log('Balances:', balances);
643
+
644
+ // Transfer 50 USDC (off-chain, no checkpoint needed)
645
+ const transferState = await client.transfer(
646
+ '0xRecipient...',
647
+ 'usdc',
648
+ new Decimal(50)
649
+ );
650
+ console.log('Transfer state version:', transferState.version);
651
+ } finally {
652
+ await client.close();
653
+ }
654
+ }
655
+
656
+ basicExample().catch(console.error);
657
+ ```
658
+
659
+ ### Example 2: Multi-Chain Operations
660
+
661
+ ```typescript
662
+ import { Client, createSigners, withBlockchainRPC } from '@yellow-org/sdk';
663
+ import Decimal from 'decimal.js';
664
+
665
+ async function multiChainExample() {
666
+ const { stateSigner, txSigner } = createSigners(process.env.PRIVATE_KEY!);
667
+
668
+ const client = await Client.create(
669
+ 'wss://clearnode.example.com/ws',
670
+ stateSigner,
671
+ txSigner,
672
+ withBlockchainRPC(80002n, process.env.POLYGON_RPC!), // Polygon Amoy
673
+ withBlockchainRPC(11155111n, process.env.SEPOLIA_RPC!) // Sepolia
674
+ );
675
+
676
+ try {
677
+ // Set home blockchains
678
+ await client.setHomeBlockchain('usdc', 80002n);
679
+ await client.setHomeBlockchain('eth', 11155111n);
680
+
681
+ // Deposit on different chains (two-step pattern)
682
+ await client.deposit(80002n, 'usdc', new Decimal(100));
683
+ await client.checkpoint('usdc');
684
+
685
+ await client.deposit(11155111n, 'eth', new Decimal(0.1));
686
+ await client.checkpoint('eth');
687
+
688
+ // Check balances across all chains
689
+ const balances = await client.getBalances(client.getUserAddress());
690
+ balances.forEach(b => console.log(`${b.asset}: ${b.balance}`));
691
+ } finally {
692
+ await client.close();
693
+ }
694
+ }
695
+
696
+ multiChainExample().catch(console.error);
697
+ ```
698
+
699
+ ### Example 3: Transaction History with Pagination
700
+
701
+ ```typescript
702
+ import { Client, createSigners } from '@yellow-org/sdk';
703
+
704
+ async function queryTransactions() {
705
+ const { stateSigner, txSigner } = createSigners(process.env.PRIVATE_KEY!);
706
+ const client = await Client.create(
707
+ 'wss://clearnode.example.com/ws',
708
+ stateSigner,
709
+ txSigner
710
+ );
711
+
712
+ try {
713
+ const wallet = client.getUserAddress();
714
+
715
+ // Get paginated transactions
716
+ const result = await client.getTransactions(wallet, {
717
+ page: 1,
718
+ pageSize: 10,
719
+ });
720
+
721
+ console.log(`Total: ${result.metadata.totalCount}`);
722
+ console.log(`Page ${result.metadata.page} of ${result.metadata.pageCount}`);
723
+
724
+ result.transactions.forEach((tx, i) => {
725
+ console.log(`${i + 1}. ${tx.txType}: ${tx.amount} ${tx.asset}`);
726
+ });
727
+ } finally {
728
+ await client.close();
729
+ }
730
+ }
731
+
732
+ queryTransactions().catch(console.error);
733
+ ```
734
+
735
+ ### Example 4: App Session Workflow
736
+
737
+ ```typescript
738
+ import { Client, createSigners, withBlockchainRPC } from '@yellow-org/sdk';
739
+ import Decimal from 'decimal.js';
740
+
741
+ async function appSessionExample() {
742
+ const { stateSigner, txSigner } = createSigners(process.env.PRIVATE_KEY!);
743
+ const client = await Client.create(
744
+ 'wss://clearnode.example.com/ws',
745
+ stateSigner,
746
+ txSigner,
747
+ withBlockchainRPC(80002n, process.env.RPC_URL!)
748
+ );
749
+
750
+ try {
751
+ // Create app session
752
+ const definition = {
753
+ application: 'chess-v1',
754
+ participants: [
755
+ { walletAddress: client.getUserAddress(), signatureWeight: 1 },
756
+ { walletAddress: '0xOpponent...', signatureWeight: 1 },
757
+ ],
758
+ quorum: 2,
759
+ nonce: 1n,
760
+ };
761
+
762
+ const { appSessionId } = await client.createAppSession(
763
+ definition,
764
+ '{}',
765
+ ['sig1', 'sig2']
766
+ );
767
+ console.log('Session created:', appSessionId);
768
+
769
+ // Deposit to app session
770
+ const appUpdate = {
771
+ appSessionId,
772
+ intent: 1, // Deposit
773
+ version: 1n,
774
+ allocations: [{
775
+ participant: client.getUserAddress(),
776
+ asset: 'usdc',
777
+ amount: new Decimal(50),
778
+ }],
779
+ sessionData: '{}',
780
+ };
781
+
782
+ const nodeSig = await client.submitAppSessionDeposit(
783
+ appUpdate,
784
+ ['sig1'],
785
+ 'usdc',
786
+ new Decimal(50)
787
+ );
788
+ console.log('Deposit signature:', nodeSig);
789
+
790
+ // Query sessions
791
+ const { sessions } = await client.getAppSessions({
792
+ wallet: client.getUserAddress(),
793
+ });
794
+ console.log(`Found ${sessions.length} sessions`);
795
+ } finally {
796
+ await client.close();
797
+ }
798
+ }
799
+
800
+ appSessionExample().catch(console.error);
801
+ ```
802
+
803
+ ### Example 5: Connection Monitoring
804
+
805
+ ```typescript
806
+ import { Client, createSigners, withErrorHandler, withPingInterval } from '@yellow-org/sdk';
807
+
808
+ async function monitorConnection() {
809
+ const { stateSigner, txSigner } = createSigners(process.env.PRIVATE_KEY!);
810
+
811
+ const client = await Client.create(
812
+ 'wss://clearnode.example.com/ws',
813
+ stateSigner,
814
+ txSigner,
815
+ withPingInterval(3000),
816
+ withErrorHandler((error) => {
817
+ console.error('Connection error:', error);
818
+ })
819
+ );
820
+
821
+ // Monitor connection
822
+ client.waitForClose().then(() => {
823
+ console.log('Connection closed, reconnecting...');
824
+ // Reconnection logic here
825
+ });
826
+
827
+ // Perform operations
828
+ const config = await client.getConfig();
829
+ console.log('Connected to:', config.nodeAddress);
830
+
831
+ // Keep alive...
832
+ await new Promise(resolve => setTimeout(resolve, 30000));
833
+ await client.close();
834
+ }
835
+
836
+ monitorConnection().catch(console.error);
837
+ ```
838
+
839
+ ## TypeScript-Specific Notes
840
+
841
+ ### Type Imports
842
+
843
+ ```typescript
844
+ import type {
845
+ State,
846
+ Channel,
847
+ Transaction,
848
+ BalanceEntry,
849
+ Asset,
850
+ Blockchain,
851
+ AppSessionInfoV1,
852
+ AppDefinitionV1,
853
+ AppSessionKeyStateV1,
854
+ ChannelSessionKeyStateV1,
855
+ PaginationMetadata,
856
+ } from '@yellow-org/sdk';
857
+ ```
858
+
859
+ ### BigInt for Chain IDs
860
+
861
+ ```typescript
862
+ // Use 'n' suffix for bigint literals
863
+ const polygonAmoy = 80002n;
864
+ const ethereum = 1n;
865
+
866
+ await client.deposit(polygonAmoy, 'usdc', amount);
867
+ ```
868
+
869
+ ### Decimal.js for Amounts
870
+
871
+ ```typescript
872
+ import Decimal from 'decimal.js';
873
+
874
+ const amount1 = new Decimal(100);
875
+ const amount2 = new Decimal('123.456');
876
+ const amount3 = Decimal.div(1000, 3);
877
+
878
+ await client.deposit(chainId, 'usdc', amount1);
879
+ ```
880
+
881
+ ### Viem Integration
882
+
883
+ ```typescript
884
+ import { privateKeyToAccount } from 'viem/accounts';
885
+ import type { Address } from 'viem';
886
+
887
+ const account = privateKeyToAccount('0x...');
888
+ const stateSigner = new EthereumMsgSigner(account);
889
+
890
+ const wallet: Address = '0x1234...';
891
+ const balances = await client.getBalances(wallet);
892
+ ```
893
+
894
+ ### Async/Await
895
+
896
+ ```typescript
897
+ // All SDK methods are async
898
+ // State operations return core.State
899
+ const state = await client.deposit(chainId, asset, amount);
900
+ // Checkpoint returns a transaction hash
901
+ const txHash = await client.checkpoint(asset);
902
+
903
+ // Or with .then()
904
+ client.deposit(chainId, asset, amount)
905
+ .then(state => console.log('Deposit state version:', state.version))
906
+ .catch(error => console.error('Error:', error));
907
+ ```
908
+
909
+ ## Operation Internals
910
+
911
+ For understanding how operations work under the hood:
912
+
913
+ ### Deposit Flow (New Channel)
914
+ 1. Create channel definition
915
+ 2. Create void state
916
+ 3. Set home ledger (token, chain)
917
+ 4. Apply deposit transition
918
+ 5. Sign state
919
+ 6. Request channel creation from node (co-sign)
920
+ 7. Return co-signed state
921
+
922
+ ### Deposit Flow (Existing Channel)
923
+ 1. Get latest state
924
+ 2. Create next state
925
+ 3. Apply deposit transition
926
+ 4. Sign state
927
+ 5. Submit to node (co-sign)
928
+ 6. Return co-signed state
929
+
930
+ ### Withdraw Flow
931
+ 1. Get latest state
932
+ 2. Create next state
933
+ 3. Apply withdrawal transition
934
+ 4. Sign state
935
+ 5. Submit to node (co-sign)
936
+ 6. Return co-signed state
937
+
938
+ ### Transfer Flow
939
+ 1. Get latest state
940
+ 2. Create next state
941
+ 3. Apply transfer transition
942
+ 4. Sign state
943
+ 5. Submit to node (co-sign)
944
+ 6. Return co-signed state
945
+
946
+ ### CloseHomeChannel Flow
947
+ 1. Get latest state
948
+ 2. Verify channel exists
949
+ 3. Create next state
950
+ 4. Apply finalize transition
951
+ 5. Sign state
952
+ 6. Submit to node (co-sign)
953
+ 7. Return co-signed state
954
+
955
+ ### Checkpoint Flow
956
+ 1. Get latest signed state (both signatures)
957
+ 2. Determine blockchain ID from state's home ledger
958
+ 3. Get on-chain channel status
959
+ 4. Route based on transition type + status:
960
+ - Void channel -> `blockchainClient.create()`
961
+ - Existing channel -> `blockchainClient.checkpoint()`
962
+ - Finalize -> `blockchainClient.close()`
963
+ 5. Return transaction hash
964
+
965
+ ## Requirements
966
+
967
+ - **Node.js**: 20.0.0 or later
968
+ - **TypeScript**: 5.3.0 or later (for development)
969
+ - **Running Clearnode instance** or access to public node
970
+ - **Blockchain RPC endpoint** (for on-chain operations via `checkpoint()`)
971
+
972
+ ## License
973
+
974
+ Part of the Nitrolite project. See [LICENSE](../../LICENSE) for details.
975
+
976
+ ## Related Projects
977
+
978
+ - [Nitrolite TS Compat](https://www.npmjs.com/package/@yellow-org/sdk-compat) - Compatibility layer for older TypeScript versions
979
+ - [Nitrolite Go SDK](https://github.com/erc7824/nitrolite/tree/stable/sdk/go) - Go implementation with same API
980
+ - [Nitrolite Smart Contracts](https://github.com/erc7824/nitrolite/tree/stable/contracts) - On-chain contracts
981
+
982
+ ---
983
+
984
+ **Built with Nitrolite** - Powering the next generation of scalable blockchain applications.