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