@yellow-org/sdk 1.2.1 → 1.3.1

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 CHANGED
@@ -3,7 +3,9 @@
3
3
  [![npm version](https://img.shields.io/npm/v/@yellow-org/sdk.svg)](https://www.npmjs.com/package/@yellow-org/sdk)
4
4
  [![License](https://img.shields.io/npm/l/@yellow-org/sdk.svg)](https://github.com/layer-3/nitrolite/blob/main/LICENSE)
5
5
 
6
- TypeScript SDK for Clearnode payment channels providing both high-level and low-level operations in a unified client:
6
+ > The off-chain broker was renamed from "Clearnode" to "Nitronode" in v1.3.0. The default WebSocket sandbox URL is now `wss://nitronode-sandbox.yellow.org/v1/ws`. See [`MIGRATION-NITRONODE.md`](../../MIGRATION-NITRONODE.md).
7
+
8
+ TypeScript SDK for Nitronode payment channels providing both high-level and low-level operations in a unified client:
7
9
  - **State Operations**: `deposit()`, `withdraw()`, `transfer()`, `closeHomeChannel()`, `acknowledge()` - build and co-sign states off-chain
8
10
  - **Blockchain Settlement**: `checkpoint()` - the single entry point for all on-chain transactions
9
11
  - **Low-Level Operations**: Direct RPC access for custom flows and advanced use cases
@@ -76,16 +78,18 @@ client.rebalanceAppSessions(signedUpdates) // Atomic rebala
76
78
 
77
79
  ### App Session Keys
78
80
  ```typescript
79
- client.signSessionKeyState(state) // Sign app session key state
80
- client.submitSessionKeyState(state) // Register/update app session key
81
- client.getLastKeyStates(userAddress, sessionKey?) // Get active app session key states
81
+ client.signSessionKeyState(state) // Wallet user_sig over app session key state
82
+ client.signAppSessionKeyOwnership(state, sessionKeySigner) // Session-key holder's session_key_sig
83
+ client.submitSessionKeyState(state) // Register/update app session key (both sigs required)
84
+ client.getLastAppKeyStates(userAddress, sessionKey?, options?) // Get app session key states (active-only by default; pass { includeInactive: true } to include expired)
82
85
  ```
83
86
 
84
87
  ### Channel Session Keys
85
88
  ```typescript
86
- client.signChannelSessionKeyState(state) // Sign channel session key state
87
- client.submitChannelSessionKeyState(state) // Register/update channel session key
88
- client.getLastChannelKeyStates(userAddress, sessionKey?) // Get active channel session key states
89
+ client.signChannelSessionKeyState(state) // Wallet user_sig over channel session key state
90
+ client.signChannelSessionKeyOwnership(state, sessionKeySigner) // Session-key holder's session_key_sig
91
+ client.submitChannelSessionKeyState(state) // Register/update channel session key (both sigs required)
92
+ client.getLastChannelKeyStates(userAddress, sessionKey?, options?) // Get channel session key states (active-only by default; pass { includeInactive: true } to include expired)
89
93
  ```
90
94
 
91
95
  ### Shared Utilities
@@ -123,7 +127,7 @@ async function main() {
123
127
 
124
128
  // Create unified client
125
129
  const client = await Client.create(
126
- 'wss://clearnode.example.com/ws',
130
+ 'wss://nitronode.example.com/ws',
127
131
  stateSigner,
128
132
  txSigner,
129
133
  withBlockchainRPC(80002n, 'https://polygon-amoy.alchemy.com/v2/KEY')
@@ -490,58 +494,65 @@ const sessionKeySigner = new AppSessionKeySignerV1(sessionKeyMsgSigner);
490
494
 
491
495
  ### App Session Keys
492
496
 
497
+ Registration requires two signatures: the wallet's `user_sig` (authorizing the
498
+ delegation) and the session-key holder's `session_key_sig` (proving possession of the key
499
+ being registered). The node rejects submits that lack a valid `session_key_sig`.
500
+
493
501
  ```typescript
494
- // Sign and submit an app session key state
495
- const sig = await client.signSessionKeyState({
502
+ // sessionKeyHolder is an EthereumMsgSigner whose address equals state.session_key.
503
+ // Use a raw message signer (not a wrapped StateSigner) — the node expects a
504
+ // raw 65-byte EIP-191 signature for session_key_sig.
505
+ const sessionKeyHolder = new EthereumMsgSigner(sessionKeyPrivateKey);
506
+ const state = {
496
507
  user_address: '0x1234...',
497
508
  session_key: '0xabcd...',
498
509
  version: '1',
499
510
  application_ids: ['app1'],
500
511
  app_session_ids: [],
501
512
  expires_at: String(Math.floor(Date.now() / 1000) + 86400),
502
- user_sig: '0x',
503
- });
513
+ user_sig: '',
514
+ session_key_sig: '',
515
+ };
516
+ state.user_sig = await client.signSessionKeyState(state);
517
+ state.session_key_sig = await client.signAppSessionKeyOwnership(state, sessionKeyHolder);
504
518
 
505
- await client.submitSessionKeyState({
506
- user_address: '0x1234...',
507
- session_key: '0xabcd...',
508
- version: '1',
509
- application_ids: ['app1'],
510
- app_session_ids: [],
511
- expires_at: String(Math.floor(Date.now() / 1000) + 86400),
512
- user_sig: sig,
513
- });
519
+ await client.submitSessionKeyState(state);
514
520
 
515
- // Query active app session key states
516
- const states = await client.getLastKeyStates('0x1234...');
517
- const filtered = await client.getLastKeyStates('0x1234...', '0xSessionKey...');
521
+ // Query app session key states (active-only by default)
522
+ const states = await client.getLastAppKeyStates('0x1234...');
523
+ const filtered = await client.getLastAppKeyStates('0x1234...', '0xSessionKey...');
524
+
525
+ // Include expired/revoked latest states (e.g. for rotation flows that need the prior version)
526
+ const all = await client.getLastAppKeyStates('0x1234...', '0xSessionKey...', { includeInactive: true });
518
527
  ```
519
528
 
520
529
  ### Channel Session Keys
521
530
 
522
531
  ```typescript
523
- // Sign and submit a channel session key state
524
- const sig = await client.signChannelSessionKeyState({
532
+ // sessionKeyHolder is an EthereumMsgSigner whose address equals state.session_key.
533
+ // Use a raw message signer (not a wrapped StateSigner) — the node expects a
534
+ // raw 65-byte EIP-191 signature for session_key_sig.
535
+ const sessionKeyHolder = new EthereumMsgSigner(sessionKeyPrivateKey);
536
+ const state = {
525
537
  user_address: '0x1234...',
526
538
  session_key: '0xabcd...',
527
539
  version: '1',
528
540
  assets: ['usdc'],
529
541
  expires_at: String(Math.floor(Date.now() / 1000) + 86400),
530
- user_sig: '0x',
531
- });
542
+ user_sig: '',
543
+ session_key_sig: '',
544
+ };
545
+ state.user_sig = await client.signChannelSessionKeyState(state);
546
+ state.session_key_sig = await client.signChannelSessionKeyOwnership(state, sessionKeyHolder);
532
547
 
533
- await client.submitChannelSessionKeyState({
534
- user_address: '0x1234...',
535
- session_key: '0xabcd...',
536
- version: '1',
537
- assets: ['usdc'],
538
- expires_at: String(Math.floor(Date.now() / 1000) + 86400),
539
- user_sig: sig,
540
- });
548
+ await client.submitChannelSessionKeyState(state);
541
549
 
542
- // Query active channel session key states
550
+ // Query channel session key states (active-only by default)
543
551
  const states = await client.getLastChannelKeyStates('0x1234...');
544
552
  const filtered = await client.getLastChannelKeyStates('0x1234...', '0xSessionKey...');
553
+
554
+ // Include expired/revoked latest states (e.g. for rotation flows that need the prior version)
555
+ const all = await client.getLastChannelKeyStates('0x1234...', '0xSessionKey...', { includeInactive: true });
545
556
  ```
546
557
 
547
558
  ## Key Concepts
@@ -688,7 +699,7 @@ async function basicExample() {
688
699
  const { stateSigner, txSigner } = createSigners(process.env.PRIVATE_KEY!);
689
700
 
690
701
  const client = await Client.create(
691
- 'wss://clearnode.example.com/ws',
702
+ 'wss://nitronode.example.com/ws',
692
703
  stateSigner,
693
704
  txSigner,
694
705
  withBlockchainRPC(80002n, process.env.RPC_URL!)
@@ -737,7 +748,7 @@ async function multiChainExample() {
737
748
  const { stateSigner, txSigner } = createSigners(process.env.PRIVATE_KEY!);
738
749
 
739
750
  const client = await Client.create(
740
- 'wss://clearnode.example.com/ws',
751
+ 'wss://nitronode.example.com/ws',
741
752
  stateSigner,
742
753
  txSigner,
743
754
  withBlockchainRPC(80002n, process.env.POLYGON_RPC!), // Polygon Amoy
@@ -775,7 +786,7 @@ import { Client, createSigners } from '@yellow-org/sdk';
775
786
  async function queryTransactions() {
776
787
  const { stateSigner, txSigner } = createSigners(process.env.PRIVATE_KEY!);
777
788
  const client = await Client.create(
778
- 'wss://clearnode.example.com/ws',
789
+ 'wss://nitronode.example.com/ws',
779
790
  stateSigner,
780
791
  txSigner
781
792
  );
@@ -821,7 +832,7 @@ import Decimal from 'decimal.js';
821
832
  async function appSessionExample() {
822
833
  const { stateSigner, txSigner } = createSigners(process.env.PRIVATE_KEY!);
823
834
  const client = await Client.create(
824
- 'wss://clearnode.example.com/ws',
835
+ 'wss://nitronode.example.com/ws',
825
836
  stateSigner,
826
837
  txSigner,
827
838
  withBlockchainRPC(80002n, process.env.RPC_URL!)
@@ -902,7 +913,7 @@ async function monitorConnection() {
902
913
  const { stateSigner, txSigner } = createSigners(process.env.PRIVATE_KEY!);
903
914
 
904
915
  const client = await Client.create(
905
- 'wss://clearnode.example.com/ws',
916
+ 'wss://nitronode.example.com/ws',
906
917
  stateSigner,
907
918
  txSigner,
908
919
  withPingInterval(3000),
@@ -1073,7 +1084,7 @@ For understanding how operations work under the hood:
1073
1084
 
1074
1085
  - **Node.js**: 20.0.0 or later
1075
1086
  - **TypeScript**: 5.3.0 or later (for development)
1076
- - **Running Clearnode instance** or access to public node
1087
+ - **Running Nitronode instance** or access to public node
1077
1088
  - **Blockchain RPC endpoint** (for on-chain operations via `checkpoint()`)
1078
1089
 
1079
1090
  ## License
@@ -1,4 +1,4 @@
1
- import { encodeAbiParameters, keccak256, pad, toHex } from 'viem';
1
+ import { encodeAbiParameters, keccak256, toHex } from 'viem';
2
2
  export function packCreateAppSessionRequestV1(definition, sessionData) {
3
3
  const participantComponents = [
4
4
  { name: 'walletAddress', type: 'address' },
@@ -106,26 +106,9 @@ export function packAppV1(app) {
106
106
  ]);
107
107
  return keccak256(packed);
108
108
  }
109
- function hexToBytes32(s) {
110
- let hex = s.startsWith('0x') || s.startsWith('0X') ? s.slice(2) : s;
111
- if (hex.length % 2 === 1) {
112
- hex = '0' + hex;
113
- }
114
- if (!/^[0-9a-fA-F]*$/.test(hex)) {
115
- return pad('0x00', { size: 32 });
116
- }
117
- if (hex.length === 0) {
118
- return pad('0x00', { size: 32 });
119
- }
120
- if (hex.length > 64) {
121
- hex = hex.slice(hex.length - 64);
122
- }
123
- const padded = hex.padStart(64, '0');
124
- return `0x${padded}`;
125
- }
126
109
  export function packAppSessionKeyStateV1(state) {
127
- const applicationIDHashes = state.application_ids.map(hexToBytes32);
128
- const appSessionIDHashes = state.app_session_ids.map(hexToBytes32);
110
+ const applicationIDHashes = state.application_ids.map((id) => keccak256(toHex(id)));
111
+ const appSessionIDHashes = state.app_session_ids.map((id) => keccak256(toHex(id)));
129
112
  const packed = encodeAbiParameters([
130
113
  { type: 'address' },
131
114
  { type: 'address' },
@@ -81,6 +81,7 @@ export interface AppSessionKeyStateV1 {
81
81
  app_session_ids: string[];
82
82
  expires_at: string;
83
83
  user_sig: string;
84
+ session_key_sig: string;
84
85
  }
85
86
  export interface AssetAllowanceV1 {
86
87
  asset: string;
@@ -30,6 +30,16 @@ export declare const ChannelHubAbi: readonly [{
30
30
  readonly internalType: "uint32";
31
31
  }];
32
32
  readonly stateMutability: "view";
33
+ }, {
34
+ readonly type: "function";
35
+ readonly name: "MAX_CHALLENGE_DURATION";
36
+ readonly inputs: readonly [];
37
+ readonly outputs: readonly [{
38
+ readonly name: "";
39
+ readonly type: "uint32";
40
+ readonly internalType: "uint32";
41
+ }];
42
+ readonly stateMutability: "view";
33
43
  }, {
34
44
  readonly type: "function";
35
45
  readonly name: "MAX_DEPOSIT_ESCROW_STEPS";
@@ -335,7 +345,7 @@ export declare const ChannelHubAbi: readonly [{
335
345
  }];
336
346
  }];
337
347
  readonly outputs: readonly [];
338
- readonly stateMutability: "payable";
348
+ readonly stateMutability: "nonpayable";
339
349
  }, {
340
350
  readonly type: "function";
341
351
  readonly name: "claimFunds";
@@ -450,7 +460,7 @@ export declare const ChannelHubAbi: readonly [{
450
460
  }];
451
461
  }];
452
462
  readonly outputs: readonly [];
453
- readonly stateMutability: "payable";
463
+ readonly stateMutability: "nonpayable";
454
464
  }, {
455
465
  readonly type: "function";
456
466
  readonly name: "createChannel";
@@ -2009,7 +2019,7 @@ export declare const ChannelHubAbi: readonly [{
2009
2019
  }];
2010
2020
  }];
2011
2021
  readonly outputs: readonly [];
2012
- readonly stateMutability: "payable";
2022
+ readonly stateMutability: "nonpayable";
2013
2023
  }, {
2014
2024
  readonly type: "function";
2015
2025
  readonly name: "withdrawFromNode";
@@ -3234,6 +3244,11 @@ export declare const ChannelHubAbi: readonly [{
3234
3244
  readonly type: "event";
3235
3245
  readonly name: "EscrowDepositsPurged";
3236
3246
  readonly inputs: readonly [{
3247
+ readonly name: "escrowIds";
3248
+ readonly type: "bytes32[]";
3249
+ readonly indexed: false;
3250
+ readonly internalType: "bytes32[]";
3251
+ }, {
3237
3252
  readonly name: "purgedCount";
3238
3253
  readonly type: "uint256";
3239
3254
  readonly indexed: false;
@@ -4325,6 +4340,10 @@ export declare const ChannelHubAbi: readonly [{
4325
4340
  readonly type: "error";
4326
4341
  readonly name: "IncorrectChannelStatus";
4327
4342
  readonly inputs: readonly [];
4343
+ }, {
4344
+ readonly type: "error";
4345
+ readonly name: "IncorrectMsgSender";
4346
+ readonly inputs: readonly [];
4328
4347
  }, {
4329
4348
  readonly type: "error";
4330
4349
  readonly name: "IncorrectNode";
@@ -41,6 +41,19 @@ export const ChannelHubAbi = [
41
41
  ],
42
42
  stateMutability: 'view'
43
43
  },
44
+ {
45
+ type: 'function',
46
+ name: 'MAX_CHALLENGE_DURATION',
47
+ inputs: [],
48
+ outputs: [
49
+ {
50
+ name: '',
51
+ type: 'uint32',
52
+ internalType: 'uint32'
53
+ }
54
+ ],
55
+ stateMutability: 'view'
56
+ },
44
57
  {
45
58
  type: 'function',
46
59
  name: 'MAX_DEPOSIT_ESCROW_STEPS',
@@ -431,7 +444,7 @@ export const ChannelHubAbi = [
431
444
  }
432
445
  ],
433
446
  outputs: [],
434
- stateMutability: 'payable'
447
+ stateMutability: 'nonpayable'
435
448
  },
436
449
  {
437
450
  type: 'function',
@@ -578,7 +591,7 @@ export const ChannelHubAbi = [
578
591
  }
579
592
  ],
580
593
  outputs: [],
581
- stateMutability: 'payable'
594
+ stateMutability: 'nonpayable'
582
595
  },
583
596
  {
584
597
  type: 'function',
@@ -2578,7 +2591,7 @@ export const ChannelHubAbi = [
2578
2591
  }
2579
2592
  ],
2580
2593
  outputs: [],
2581
- stateMutability: 'payable'
2594
+ stateMutability: 'nonpayable'
2582
2595
  },
2583
2596
  {
2584
2597
  type: 'function',
@@ -4136,6 +4149,12 @@ export const ChannelHubAbi = [
4136
4149
  type: 'event',
4137
4150
  name: 'EscrowDepositsPurged',
4138
4151
  inputs: [
4152
+ {
4153
+ name: 'escrowIds',
4154
+ type: 'bytes32[]',
4155
+ indexed: false,
4156
+ internalType: 'bytes32[]'
4157
+ },
4139
4158
  {
4140
4159
  name: 'purgedCount',
4141
4160
  type: 'uint256',
@@ -5526,6 +5545,11 @@ export const ChannelHubAbi = [
5526
5545
  name: 'IncorrectChannelStatus',
5527
5546
  inputs: []
5528
5547
  },
5548
+ {
5549
+ type: 'error',
5550
+ name: 'IncorrectMsgSender',
5551
+ inputs: []
5552
+ },
5529
5553
  {
5530
5554
  type: 'error',
5531
5555
  name: 'IncorrectNode',
@@ -132,7 +132,7 @@ export class Client {
132
132
  abi: ChannelHubAbi,
133
133
  functionName: 'depositToNode',
134
134
  args: [token, amountBig],
135
- account: this.walletSigner.account.address,
135
+ account: this.walletSigner.account,
136
136
  ...(token === zeroAddress ? { value: amountBig } : {}),
137
137
  });
138
138
  console.log('✅ Simulation successful - executing deposit...');
@@ -179,7 +179,7 @@ export class Client {
179
179
  abi: ChannelHubAbi,
180
180
  functionName: 'withdrawFromNode',
181
181
  args: [to, token, amountBig],
182
- account: this.walletSigner.account.address,
182
+ account: this.walletSigner.account,
183
183
  });
184
184
  console.log('✅ Simulation successful - executing withdrawal...');
185
185
  const hash = await this.walletSigner.writeContract(request);
@@ -237,7 +237,7 @@ export class Client {
237
237
  abi: ChannelHubAbi,
238
238
  functionName: 'createChannel',
239
239
  args: [contractDef, contractState],
240
- account: this.walletSigner.account.address,
240
+ account: this.walletSigner.account,
241
241
  ...(nativeValue != null ? { value: nativeValue } : {}),
242
242
  }));
243
243
  console.log('✅ Simulation successful - executing transaction...');
@@ -26,19 +26,18 @@ export class ERC20 {
26
26
  throw new Error('Wallet signer is required for approve operation');
27
27
  }
28
28
  try {
29
- const { request } = (await this.client.simulateContract({
29
+ const hash = await this.walletSigner.writeContract({
30
30
  address: this.tokenAddress,
31
31
  abi: Erc20Abi,
32
32
  functionName: 'approve',
33
33
  args: [spender, amount],
34
- account: this.walletSigner.account.address,
35
- }));
36
- const hash = await this.walletSigner.writeContract(request);
37
- await this.client.waitForTransactionReceipt({ hash });
34
+ account: this.walletSigner.account,
35
+ });
36
+ await this.client.waitForTransactionReceipt({ hash, confirmations: 3 });
38
37
  return hash;
39
38
  }
40
39
  catch (error) {
41
- console.error('❌ Approve simulation/execution failed!');
40
+ console.error('❌ Approve execution failed!');
42
41
  if (error.message) {
43
42
  console.error(' Reason:', error.message);
44
43
  }
@@ -6,3 +6,4 @@ export * from './channel_hub_abi.js';
6
6
  export * from './client.js';
7
7
  export * from './app_registry_abi.js';
8
8
  export * from './locking_client.js';
9
+ export * from './validator_watcher.js';
@@ -6,3 +6,4 @@ export * from './channel_hub_abi.js';
6
6
  export * from './client.js';
7
7
  export * from './app_registry_abi.js';
8
8
  export * from './locking_client.js';
9
+ export * from './validator_watcher.js';
@@ -0,0 +1,4 @@
1
+ import { Address } from 'viem';
2
+ import { EVMClient } from './interface.js';
3
+ import { ValidatorRegisteredEvent } from '../../core/event.js';
4
+ export declare function watchValidatorRegistered(contractAddress: Address, client: EVMClient, blockchainId: bigint, fromBlock: bigint, signal?: AbortSignal): AsyncGenerator<ValidatorRegisteredEvent>;
@@ -0,0 +1,119 @@
1
+ import { getAddress } from 'viem';
2
+ import { ChannelHubAbi } from './channel_hub_abi.js';
3
+ const VALIDATOR_REGISTERED_ABI = [
4
+ {
5
+ type: 'event',
6
+ name: 'ValidatorRegistered',
7
+ inputs: [
8
+ { name: 'validatorId', type: 'uint8', indexed: true, internalType: 'uint8' },
9
+ { name: 'validator', type: 'address', indexed: true, internalType: 'contract ISignatureValidator' },
10
+ ],
11
+ anonymous: false,
12
+ },
13
+ ];
14
+ export async function* watchValidatorRegistered(contractAddress, client, blockchainId, fromBlock, signal) {
15
+ let headBlock = 0n;
16
+ try {
17
+ headBlock = await client.getBlockNumber();
18
+ }
19
+ catch (err) {
20
+ if (!signal?.aborted) {
21
+ console.warn('[nitrolite] watchValidatorRegistered: failed to fetch block number, historical replay and transition gap-fill skipped', err);
22
+ }
23
+ }
24
+ if (fromBlock > 0n && headBlock >= fromBlock) {
25
+ try {
26
+ const logs = await client.getLogs({
27
+ address: contractAddress,
28
+ event: VALIDATOR_REGISTERED_ABI[0],
29
+ fromBlock,
30
+ toBlock: headBlock,
31
+ strict: true,
32
+ });
33
+ for (const log of logs) {
34
+ if (log.removed)
35
+ continue;
36
+ if (signal?.aborted)
37
+ return;
38
+ yield {
39
+ blockchainId,
40
+ validatorId: log.args.validatorId,
41
+ validator: getAddress(log.args.validator),
42
+ blockNumber: log.blockNumber ?? headBlock,
43
+ };
44
+ }
45
+ }
46
+ catch (err) {
47
+ if (!signal?.aborted) {
48
+ console.warn('[nitrolite] watchValidatorRegistered: failed to fetch historical logs, gap fill incomplete', err);
49
+ }
50
+ }
51
+ }
52
+ if (signal?.aborted)
53
+ return;
54
+ const liveFromBlock = headBlock > 0n ? headBlock + 1n : undefined;
55
+ const queue = [];
56
+ let wakeUp = null;
57
+ let watchError = null;
58
+ let done = false;
59
+ const notify = () => {
60
+ const resolve = wakeUp;
61
+ wakeUp = null;
62
+ resolve?.();
63
+ };
64
+ const unwatch = client.watchContractEvent({
65
+ address: contractAddress,
66
+ abi: ChannelHubAbi,
67
+ eventName: 'ValidatorRegistered',
68
+ fromBlock: liveFromBlock,
69
+ onLogs(logs) {
70
+ for (const log of logs) {
71
+ if (log.removed)
72
+ continue;
73
+ if (log.blockNumber === null)
74
+ continue;
75
+ const { validatorId, validator } = log.args;
76
+ if (validatorId === undefined || !validator)
77
+ continue;
78
+ queue.push({
79
+ blockchainId,
80
+ validatorId,
81
+ validator: getAddress(validator),
82
+ blockNumber: log.blockNumber,
83
+ });
84
+ }
85
+ notify();
86
+ },
87
+ onError(err) {
88
+ watchError = err;
89
+ done = true;
90
+ notify();
91
+ },
92
+ });
93
+ const onAbort = () => {
94
+ done = true;
95
+ notify();
96
+ };
97
+ signal?.addEventListener('abort', onAbort);
98
+ try {
99
+ while (!done || queue.length > 0) {
100
+ while (queue.length > 0) {
101
+ if (signal?.aborted)
102
+ return;
103
+ yield queue.shift();
104
+ }
105
+ if (!done) {
106
+ await new Promise((resolve) => {
107
+ wakeUp = resolve;
108
+ });
109
+ }
110
+ }
111
+ if (watchError && !signal?.aborted) {
112
+ throw watchError;
113
+ }
114
+ }
115
+ finally {
116
+ signal?.removeEventListener('abort', onAbort);
117
+ unwatch();
118
+ }
119
+ }
package/dist/client.d.ts CHANGED
@@ -4,7 +4,7 @@ import * as core from './core/index.js';
4
4
  import * as app from './app/index.js';
5
5
  import { ChannelSessionKeyStateV1, AppInfoV1 } from './rpc/types.js';
6
6
  import { Option } from './config.js';
7
- import { StateSigner, TransactionSigner } from './signers.js';
7
+ import { EthereumMsgSigner, StateSigner, TransactionSigner } from './signers.js';
8
8
  export declare const DEFAULT_CHALLENGE_PERIOD = 86400;
9
9
  export type { StateSigner, TransactionSigner };
10
10
  export declare class Client {
@@ -70,9 +70,9 @@ export declare class Client {
70
70
  channels: core.Channel[];
71
71
  metadata: core.PaginationMetadata;
72
72
  }>;
73
- getHomeChannel(wallet: Address, asset: string): Promise<core.Channel>;
74
- getEscrowChannel(escrowChannelId: string): Promise<core.Channel>;
75
- getLatestState(wallet: Address, asset: string, onlySigned: boolean): Promise<core.State>;
73
+ getHomeChannel(wallet: Address, asset: string): Promise<core.Channel | null>;
74
+ getEscrowChannel(escrowChannelId: string): Promise<core.Channel | null>;
75
+ getLatestState(wallet: Address, asset: string, onlySigned: boolean): Promise<core.State | null>;
76
76
  getAppSessions(options?: {
77
77
  appSessionId?: string;
78
78
  wallet?: Address;
@@ -83,7 +83,7 @@ export declare class Client {
83
83
  sessions: app.AppSessionInfoV1[];
84
84
  metadata: core.PaginationMetadata;
85
85
  }>;
86
- getAppDefinition(appSessionId: string): Promise<app.AppDefinitionV1>;
86
+ getAppDefinition(appSessionId: string): Promise<app.AppDefinitionV1 | null>;
87
87
  createAppSession(definition: app.AppDefinitionV1, sessionData: string, quorumSigs: string[], opts?: {
88
88
  ownerSig?: string;
89
89
  }): Promise<{
@@ -105,11 +105,18 @@ export declare class Client {
105
105
  }>;
106
106
  registerApp(appID: string, metadata: string, creationApprovalNotRequired: boolean): Promise<void>;
107
107
  signChannelSessionKeyState(state: ChannelSessionKeyStateV1): Promise<Hex>;
108
+ signChannelSessionKeyOwnership(state: ChannelSessionKeyStateV1, sessionKeySigner: EthereumMsgSigner): Promise<Hex>;
108
109
  submitChannelSessionKeyState(state: ChannelSessionKeyStateV1): Promise<void>;
109
- getLastChannelKeyStates(userAddress: string, sessionKey?: string): Promise<ChannelSessionKeyStateV1[]>;
110
+ getLastChannelKeyStates(userAddress: string, sessionKey?: string, options?: {
111
+ includeInactive?: boolean;
112
+ }): Promise<ChannelSessionKeyStateV1[]>;
110
113
  signSessionKeyState(state: app.AppSessionKeyStateV1): Promise<Hex>;
114
+ signAppSessionKeyOwnership(state: app.AppSessionKeyStateV1, sessionKeySigner: EthereumMsgSigner): Promise<Hex>;
111
115
  submitSessionKeyState(state: app.AppSessionKeyStateV1): Promise<void>;
112
- getLastKeyStates(userAddress: string, sessionKey?: string): Promise<app.AppSessionKeyStateV1[]>;
116
+ getLastAppKeyStates(userAddress: string, sessionKey?: string, options?: {
117
+ includeInactive?: boolean;
118
+ }): Promise<app.AppSessionKeyStateV1[]>;
119
+ watchValidatorRegistered(chainId: bigint, fromBlock?: bigint, signal?: AbortSignal): AsyncGenerator<core.ValidatorRegisteredEvent>;
113
120
  private getBlockchainRPCInfo;
114
121
  private createEVMClients;
115
122
  private initializeBlockchainClient;