@ckb-ccc/core 1.22.1 → 1.23.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 (49) hide show
  1. package/CHANGELOG.md +61 -0
  2. package/dist/advanced.d.mts +1 -1
  3. package/dist/advanced.mjs +1 -1
  4. package/dist/{advancedBarrel-Daj_LJkz.d.mts → advancedBarrel-BBbQZ2OW.d.mts} +480 -379
  5. package/dist/advancedBarrel-BBbQZ2OW.d.mts.map +1 -0
  6. package/dist/advancedBarrel.d.mts +1 -1
  7. package/dist/advancedBarrel.mjs +1 -1
  8. package/dist/barrel-Dz1WLXRX.mjs +7 -0
  9. package/dist/barrel-Dz1WLXRX.mjs.map +1 -0
  10. package/dist/barrel.d.mts +2 -2
  11. package/dist/barrel.mjs +1 -1
  12. package/dist/index.d.mts +2 -2
  13. package/dist/index.mjs +1 -1
  14. package/dist/transformers-BHt442Nd.mjs +2 -0
  15. package/dist/transformers-BHt442Nd.mjs.map +1 -0
  16. package/dist.commonjs/advanced.d.ts +1 -1
  17. package/dist.commonjs/advanced.js +1 -1
  18. package/dist.commonjs/{advancedBarrel-CJL3rfuW.d.ts → advancedBarrel-BS4zFcFI.d.ts} +480 -379
  19. package/dist.commonjs/advancedBarrel-BS4zFcFI.d.ts.map +1 -0
  20. package/dist.commonjs/advancedBarrel.d.ts +1 -1
  21. package/dist.commonjs/advancedBarrel.js +1 -1
  22. package/dist.commonjs/{barrel--PaV2IZx.js → barrel-CZYID7jh.js} +10 -10
  23. package/dist.commonjs/barrel-CZYID7jh.js.map +1 -0
  24. package/dist.commonjs/barrel.d.ts +2 -2
  25. package/dist.commonjs/barrel.js +1 -1
  26. package/dist.commonjs/index.d.ts +2 -2
  27. package/dist.commonjs/index.js +1 -1
  28. package/dist.commonjs/transformers-CYUULrnt.js +2 -0
  29. package/dist.commonjs/transformers-CYUULrnt.js.map +1 -0
  30. package/package.json +1 -1
  31. package/src/address/index.ts +32 -4
  32. package/src/ckb/transaction.ts +59 -27
  33. package/src/client/cache/memory.advanced.ts +18 -3
  34. package/src/client/client.ts +41 -2
  35. package/src/client/clientPublicMainnet.ts +9 -2
  36. package/src/client/clientPublicTestnet.ts +9 -2
  37. package/src/client/jsonRpc/client.ts +7 -7
  38. package/src/codec/codec.ts +51 -27
  39. package/src/codec/entity.ts +26 -16
  40. package/src/molecule/codec.ts +437 -202
  41. package/dist/advancedBarrel-Daj_LJkz.d.mts.map +0 -1
  42. package/dist/barrel-pRBtHOAW.mjs +0 -7
  43. package/dist/barrel-pRBtHOAW.mjs.map +0 -1
  44. package/dist/transformers-lavDTtAW.mjs +0 -2
  45. package/dist/transformers-lavDTtAW.mjs.map +0 -1
  46. package/dist.commonjs/advancedBarrel-CJL3rfuW.d.ts.map +0 -1
  47. package/dist.commonjs/barrel--PaV2IZx.js.map +0 -1
  48. package/dist.commonjs/transformers-VBXQGQKe.js +0 -2
  49. package/dist.commonjs/transformers-VBXQGQKe.js.map +0 -1
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ckb-ccc/core",
3
- "version": "1.22.1",
3
+ "version": "1.23.0",
4
4
  "description": "Core of CCC - CKBer's Codebase",
5
5
  "author": "Hanssen0 <hanssen0@hanssen0.com>",
6
6
  "license": "MIT",
@@ -52,18 +52,46 @@ export class Address {
52
52
  /**
53
53
  * Creates an Address instance from an address string.
54
54
  *
55
- * @param address - The address string to parse.
56
- * @param clients - A Client instance or a record of Client instances keyed by prefix.
55
+ * @param address - The address string to parse. If it does not parse, a
56
+ * single Client's `addressResolver` may resolve it.
57
+ * @param client - The Client instance used to parse or resolve the address.
57
58
  * @returns A promise that resolves to an Address instance.
58
59
  *
59
- * @throws Will throw an error if the address prefix is unknown or mismatched.
60
+ * @throws Will throw an error if the address prefix is unknown or mismatched,
61
+ * or if the resolver handles the address but does not find it.
60
62
  */
61
63
 
64
+ static async fromString(address: string, client: Client): Promise<Address>;
65
+
66
+ /**
67
+ * @deprecated Pass a single Client instead. Callers supporting multiple
68
+ * prefixes should try each Client themselves.
69
+ */
70
+ static async fromString(
71
+ address: string,
72
+ clients: Record<string, Client>,
73
+ ): Promise<Address>;
74
+
62
75
  static async fromString(
63
76
  address: string,
64
77
  clients: Client | Record<string, Client>,
65
78
  ): Promise<Address> {
66
- const { prefix, format, payload } = addressPayloadFromString(address);
79
+ let parsed: ReturnType<typeof addressPayloadFromString>;
80
+ try {
81
+ parsed = addressPayloadFromString(address);
82
+ } catch (error) {
83
+ const client = clients as Client;
84
+ const resolver = client.addressResolver;
85
+ if (!resolver?.shouldResolve(address)) {
86
+ throw error;
87
+ }
88
+ const script = await resolver.resolve(address, client);
89
+ if (!script) {
90
+ throw new Error(`Address ${address} not found`, { cause: error });
91
+ }
92
+ return Address.fromScript(script, client);
93
+ }
94
+ const { prefix, format, payload } = parsed;
67
95
 
68
96
  const client = (clients as Record<string, Client>)[prefix] ?? clients;
69
97
  if (!client) {
@@ -265,12 +265,13 @@ export class CellOutput extends Entity.Base<CellOutputLike, CellOutput>() {
265
265
 
266
266
  /**
267
267
  * Creates a CellOutput instance from a CellOutputLike object.
268
- * This method supports automatic capacity calculation when outputData is provided and capacity is 0 or omitted.
268
+ *
269
+ * If `outputData` is provided, capacity is ensured to meet the occupied minimum.
270
+ * Valid instances are returned as-is, while invalid instances are reconstructed
271
+ * shallowly without mutating the original.
269
272
  *
270
273
  * @param cellOutput - A CellOutputLike object or an instance of CellOutput.
271
- * @param outputData - Optional output data used for automatic capacity calculation.
272
- * When provided and capacity is 0, the capacity will be calculated
273
- * as occupiedSize + outputData.length.
274
+ * @param outputData - Optional output data for capacity verification.
274
275
  * @returns A CellOutput instance.
275
276
  *
276
277
  * @example
@@ -285,23 +286,33 @@ export class CellOutput extends Entity.Base<CellOutputLike, CellOutput>() {
285
286
  * // Automatic capacity calculation
286
287
  * const cellOutput2 = CellOutput.from({
287
288
  * lock: { codeHash: "0x...", hashType: "type", args: "0x..." }
288
- * }, "0x1234"); // Capacity will be calculated automatically
289
+ * }, "0x1234");
289
290
  * ```
290
291
  */
291
292
  static from(
292
293
  cellOutput: CellOutputLike,
293
294
  outputData?: HexLike | null,
294
295
  ): CellOutput {
295
- const output = (() => {
296
- if (cellOutput instanceof CellOutput) {
296
+ if (cellOutput instanceof CellOutput) {
297
+ if (outputData == null) {
297
298
  return cellOutput;
298
299
  }
299
- return new CellOutput(
300
- numFrom(cellOutput.capacity ?? 0),
301
- Script.from(cellOutput.lock),
302
- apply(Script.from, cellOutput.type),
300
+
301
+ const minCapacity = fixedPointFrom(
302
+ cellOutput.occupiedSize + bytesFrom(outputData).length,
303
303
  );
304
- })();
304
+ if (cellOutput.capacity >= minCapacity) {
305
+ return cellOutput;
306
+ }
307
+
308
+ return new CellOutput(minCapacity, cellOutput.lock, cellOutput.type);
309
+ }
310
+
311
+ const output = new CellOutput(
312
+ numFrom(cellOutput.capacity ?? 0),
313
+ Script.from(cellOutput.lock),
314
+ apply(Script.from, cellOutput.type),
315
+ );
305
316
 
306
317
  if (outputData != null) {
307
318
  output.capacity = numMax(
@@ -374,11 +385,12 @@ export class CellAny {
374
385
 
375
386
  /**
376
387
  * Creates a `CellAny` instance from a `CellAnyLike` object.
377
- * This factory method provides a convenient way to create `CellAny` instances
378
- * from plain objects, automatically handling the optional `outPoint` or `previousOutput`.
388
+ *
389
+ * Returns valid instances as-is. Reconstructs a corrected instance shallowly
390
+ * without mutating the original if capacity is insufficient for the data.
379
391
  *
380
392
  * @param cell - A `CellAnyLike` object.
381
- * @returns A new `CellAny` instance.
393
+ * @returns A `CellAny` instance.
382
394
  *
383
395
  * @example
384
396
  * ```typescript
@@ -398,8 +410,11 @@ export class CellAny {
398
410
  */
399
411
  static from(cell: CellAnyLike): CellAny {
400
412
  if (cell instanceof CellAny) {
401
- cell.cellOutput = CellOutput.from(cell.cellOutput, cell.outputData);
402
- return cell;
413
+ const output = CellOutput.from(cell.cellOutput, cell.outputData);
414
+ if (output === cell.cellOutput) {
415
+ return cell;
416
+ }
417
+ return new CellAny(output, cell.outputData, cell.outPoint);
403
418
  }
404
419
 
405
420
  const outputData = hexFrom(cell.outputData ?? "0x");
@@ -524,13 +539,13 @@ export class Cell extends CellAny {
524
539
 
525
540
  /**
526
541
  * Creates a Cell instance from a CellLike object.
527
- * This method accepts either `outPoint` or `previousOutput` to specify the cell's location,
528
- * and supports automatic capacity calculation for the cell output.
542
+ *
543
+ * Returns valid instances as-is. Reconstructs a corrected instance shallowly
544
+ * without mutating the original if capacity is insufficient for the data.
529
545
  *
530
546
  * @param cell - A CellLike object or an instance of Cell. The object can use either:
531
547
  * - `outPoint`: For referencing a cell output
532
548
  * - `previousOutput`: For referencing a cell input (alternative name for outPoint)
533
- * The cellOutput can omit capacity for automatic calculation.
534
549
  * @returns A Cell instance.
535
550
  *
536
551
  * @example
@@ -550,7 +565,6 @@ export class Cell extends CellAny {
550
565
  * previousOutput: { txHash: "0x...", index: 0 },
551
566
  * cellOutput: {
552
567
  * lock: { codeHash: "0x...", hashType: "type", args: "0x..." }
553
- * // capacity will be calculated automatically
554
568
  * },
555
569
  * outputData: "0x1234"
556
570
  * });
@@ -559,8 +573,11 @@ export class Cell extends CellAny {
559
573
 
560
574
  static from(cell: CellLike): Cell {
561
575
  if (cell instanceof Cell) {
562
- cell.cellOutput = CellOutput.from(cell.cellOutput, cell.outputData);
563
- return cell;
576
+ const output = CellOutput.from(cell.cellOutput, cell.outputData);
577
+ if (output === cell.cellOutput) {
578
+ return cell;
579
+ }
580
+ return new Cell(cell.outPoint, output, cell.outputData);
564
581
  }
565
582
 
566
583
  return new Cell(
@@ -1261,6 +1278,9 @@ export class Transaction extends Entity.Base<TransactionLike, Transaction>() {
1261
1278
  /**
1262
1279
  * Creates a Transaction instance from a TransactionLike object.
1263
1280
  *
1281
+ * Returns valid instances as-is. Reconstructs a corrected transaction shallowly
1282
+ * without mutating the original if any output capacity is insufficient.
1283
+ *
1264
1284
  * @param tx - A TransactionLike object or an instance of Transaction.
1265
1285
  * @returns A Transaction instance.
1266
1286
  *
@@ -1280,10 +1300,22 @@ export class Transaction extends Entity.Base<TransactionLike, Transaction>() {
1280
1300
 
1281
1301
  static from(tx: TransactionLike): Transaction {
1282
1302
  if (tx instanceof Transaction) {
1283
- tx.outputs.forEach((output, i) => {
1284
- tx.outputs[i] = CellOutput.from(output, tx.outputsData[i] ?? "0x");
1285
- });
1286
- return tx;
1303
+ const outputs = tx.outputs.map((output, i) =>
1304
+ CellOutput.from(output, tx.outputsData[i] ?? "0x"),
1305
+ );
1306
+ if (outputs.every((output, i) => output === tx.outputs[i])) {
1307
+ return tx;
1308
+ }
1309
+
1310
+ return new Transaction(
1311
+ tx.version,
1312
+ Array.from(tx.cellDeps),
1313
+ Array.from(tx.headerDeps),
1314
+ Array.from(tx.inputs),
1315
+ outputs,
1316
+ Array.from(tx.outputsData),
1317
+ Array.from(tx.witnesses),
1318
+ );
1287
1319
  }
1288
1320
  const outputs =
1289
1321
  tx.outputs?.map((output, i) =>
@@ -1,6 +1,6 @@
1
1
  import { bytesFrom } from "../../bytes/index.js";
2
2
  import { Cell, CellLike, Script, ScriptLike } from "../../ckb/index.js";
3
- import { HexLike, hexFrom } from "../../hex/index.js";
3
+ import { Hex, HexLike, hexFrom } from "../../hex/index.js";
4
4
  import { NumLike, numFrom } from "../../num/index.js";
5
5
  import {
6
6
  ClientCollectableSearchKeyLike,
@@ -19,12 +19,27 @@ export type CellRecord =
19
19
  | [true, Cell]
20
20
  | [undefined, Cell];
21
21
 
22
+ function matchPartialHex(data: Hex, filter: Hex): boolean {
23
+ const needle = filter.slice(2);
24
+ if (needle.length === 0) {
25
+ return true;
26
+ }
27
+ let pos = data.indexOf(needle, 2);
28
+ while (pos !== -1) {
29
+ if (pos % 2 === 0) {
30
+ return true;
31
+ }
32
+ pos = data.indexOf(needle, pos + 1);
33
+ }
34
+ return false;
35
+ }
36
+
22
37
  export function filterData(
23
38
  dataLike: HexLike,
24
39
  filterLike: HexLike | undefined,
25
40
  filterMode: "exact" | "prefix" | "partial",
26
41
  ): boolean {
27
- if (!filterLike) {
42
+ if (filterLike == null) {
28
43
  return true;
29
44
  }
30
45
 
@@ -33,7 +48,7 @@ export function filterData(
33
48
  if (
34
49
  (filterMode === "exact" && data !== filter) ||
35
50
  (filterMode === "prefix" && !data.startsWith(filter)) ||
36
- (filterMode === "partial" && data.search(filter) === -1)
51
+ (filterMode === "partial" && !matchPartialHex(data, filter))
37
52
  ) {
38
53
  return false;
39
54
  }
@@ -38,9 +38,23 @@ import {
38
38
  } from "./clientTypes.js";
39
39
  import { KnownScript } from "./knownScript.js";
40
40
 
41
+ /**
42
+ * Resolves address representations that `Address.fromString` cannot parse,
43
+ * such as human-readable names, to scripts.
44
+ *
45
+ * @public
46
+ */
47
+ export interface AddressResolver {
48
+ /** Whether this resolver handles the representation. */
49
+ shouldResolve(address: string): boolean;
50
+ /** The script it points to, or `undefined` if it is not found. */
51
+ resolve(address: string, client: Client): Promise<ScriptLike | undefined>;
52
+ }
53
+
41
54
  export type ClientConfig = {
42
55
  cache?: ClientCache;
43
56
  scripts?: Partial<Record<KnownScript, ScriptInfoLike>>;
57
+ addressResolver?: AddressResolver;
44
58
  };
45
59
 
46
60
  /**
@@ -49,10 +63,12 @@ export type ClientConfig = {
49
63
  export abstract class Client {
50
64
  public cache: ClientCache;
51
65
  private readonly scripts: Partial<Record<KnownScript, ScriptInfoLike>>;
66
+ public readonly addressResolver?: AddressResolver;
52
67
 
53
68
  constructor(config?: ClientConfig) {
54
69
  this.cache = config?.cache ?? new ClientCacheMemory();
55
70
  this.scripts = config?.scripts ?? {};
71
+ this.addressResolver = config?.addressResolver;
56
72
  }
57
73
 
58
74
  /**
@@ -161,7 +177,7 @@ export abstract class Client {
161
177
  /**
162
178
  * Get the header of the latest block.
163
179
  *
164
- * @param verbosity - Verbosity level (0 for hex, 1 for object).
180
+ * @param verbosity - Deprecated; this parameter has no effect.
165
181
  * @returns The tip block header.
166
182
  *
167
183
  * @example
@@ -175,28 +191,45 @@ export abstract class Client {
175
191
  * console.log(`Block #${header.number}, hash: ${header.hash}`);
176
192
  * ```
177
193
  */
178
- abstract getTipHeader(verbosity?: number | null): Promise<ClientBlockHeader>;
194
+ abstract getTipHeader(
195
+ /** @deprecated This parameter has no effect and will be removed. */
196
+ verbosity?: number | null,
197
+ ): Promise<ClientBlockHeader>;
179
198
  abstract getBlockByNumberNoCache(
180
199
  blockNumber: NumLike,
200
+ /** @deprecated This parameter has no effect and will be removed. */
181
201
  verbosity?: number | null,
202
+ /**
203
+ * @deprecated This parameter has no effect and will be removed.
204
+ */
182
205
  withCycles?: boolean | null,
183
206
  ): Promise<ClientBlock | undefined>;
184
207
  abstract getBlockByHashNoCache(
185
208
  blockHash: HexLike,
209
+ /** @deprecated This parameter has no effect and will be removed. */
186
210
  verbosity?: number | null,
211
+ /**
212
+ * @deprecated This parameter has no effect and will be removed.
213
+ */
187
214
  withCycles?: boolean | null,
188
215
  ): Promise<ClientBlock | undefined>;
189
216
  abstract getHeaderByNumberNoCache(
190
217
  blockNumber: NumLike,
218
+ /** @deprecated This parameter has no effect and will be removed. */
191
219
  verbosity?: number | null,
192
220
  ): Promise<ClientBlockHeader | undefined>;
193
221
  abstract getHeaderByHashNoCache(
194
222
  blockHash: HexLike,
223
+ /** @deprecated This parameter has no effect and will be removed. */
195
224
  verbosity?: number | null,
196
225
  ): Promise<ClientBlockHeader | undefined>;
197
226
  async getBlockByNumber(
198
227
  blockNumber: NumLike,
228
+ /** @deprecated This parameter has no effect and will be removed. */
199
229
  verbosity?: number | null,
230
+ /**
231
+ * @deprecated This parameter has no effect and will be removed.
232
+ */
200
233
  withCycles?: boolean | null,
201
234
  ): Promise<ClientBlock | undefined> {
202
235
  const block = await this.cache.getBlockByNumber(blockNumber);
@@ -216,7 +249,11 @@ export abstract class Client {
216
249
  }
217
250
  async getBlockByHash(
218
251
  blockHash: HexLike,
252
+ /** @deprecated This parameter has no effect and will be removed. */
219
253
  verbosity?: number | null,
254
+ /**
255
+ * @deprecated This parameter has no effect and will be removed.
256
+ */
220
257
  withCycles?: boolean | null,
221
258
  ): Promise<ClientBlock | undefined> {
222
259
  const block = await this.cache.getBlockByHash(blockHash);
@@ -236,6 +273,7 @@ export abstract class Client {
236
273
  }
237
274
  async getHeaderByNumber(
238
275
  blockNumber: NumLike,
276
+ /** @deprecated This parameter has no effect and will be removed. */
239
277
  verbosity?: number | null,
240
278
  ): Promise<ClientBlockHeader | undefined> {
241
279
  const header = await this.cache.getHeaderByNumber(blockNumber);
@@ -251,6 +289,7 @@ export abstract class Client {
251
289
  }
252
290
  async getHeaderByHash(
253
291
  blockHash: HexLike,
292
+ /** @deprecated This parameter has no effect and will be removed. */
254
293
  verbosity?: number | null,
255
294
  ): Promise<ClientBlockHeader | undefined> {
256
295
  const header = await this.cache.getHeaderByHash(blockHash);
@@ -52,9 +52,14 @@ export class ClientPublicMainnet extends ClientJsonRpc {
52
52
  config: Omit<Parameters<typeof RequestorJsonRpc.new>[0], "onError"> &
53
53
  ClientConfig,
54
54
  ): ClientPublicMainnet {
55
- const { cache, scripts, ...requestorConfig } = config;
55
+ const { cache, scripts, addressResolver, ...requestorConfig } = config;
56
56
  const requestor = this.newRequestor(requestorConfig);
57
- return new ClientPublicMainnet({ cache, scripts, requestor });
57
+ return new ClientPublicMainnet({
58
+ cache,
59
+ scripts,
60
+ addressResolver,
61
+ requestor,
62
+ });
58
63
  }
59
64
 
60
65
  /** Opens a Client with explicit ownership of its default dependencies. */
@@ -70,6 +75,7 @@ export class ClientPublicMainnet extends ClientJsonRpc {
70
75
  const {
71
76
  cache,
72
77
  scripts,
78
+ addressResolver,
73
79
  urls = this.defaultUrls(),
74
80
  ...requestorConfig
75
81
  } = config ?? {};
@@ -81,6 +87,7 @@ export class ClientPublicMainnet extends ClientJsonRpc {
81
87
  new ClientPublicMainnet({
82
88
  cache,
83
89
  scripts,
90
+ addressResolver,
84
91
  requestor,
85
92
  url: urls[0],
86
93
  fallbacks: [...urls.slice(1)],
@@ -52,9 +52,14 @@ export class ClientPublicTestnet extends ClientJsonRpc {
52
52
  config: Omit<Parameters<typeof RequestorJsonRpc.new>[0], "onError"> &
53
53
  ClientConfig,
54
54
  ): ClientPublicTestnet {
55
- const { cache, scripts, ...requestorConfig } = config;
55
+ const { cache, scripts, addressResolver, ...requestorConfig } = config;
56
56
  const requestor = this.newRequestor(requestorConfig);
57
- return new ClientPublicTestnet({ cache, scripts, requestor });
57
+ return new ClientPublicTestnet({
58
+ cache,
59
+ scripts,
60
+ addressResolver,
61
+ requestor,
62
+ });
58
63
  }
59
64
 
60
65
  /** Opens a Client with explicit ownership of its default dependencies. */
@@ -70,6 +75,7 @@ export class ClientPublicTestnet extends ClientJsonRpc {
70
75
  const {
71
76
  cache,
72
77
  scripts,
78
+ addressResolver,
73
79
  urls = this.defaultUrls(),
74
80
  ...requestorConfig
75
81
  } = config ?? {};
@@ -81,6 +87,7 @@ export class ClientPublicTestnet extends ClientJsonRpc {
81
87
  new ClientPublicTestnet({
82
88
  cache,
83
89
  scripts,
90
+ addressResolver,
84
91
  requestor,
85
92
  url: urls[0],
86
93
  fallbacks: [...urls.slice(1)],
@@ -203,7 +203,7 @@ export abstract class ClientJsonRpc extends Client {
203
203
  /**
204
204
  * Get tip block header
205
205
  *
206
- * @param verbosity - result format which allows 0 and 1. (Optional, the default is 1.)
206
+ * @param verbosity - Deprecated; this parameter has no effect.
207
207
  * @returns BlockHeader
208
208
  */
209
209
  getTipHeader = this.buildSender(
@@ -216,8 +216,8 @@ export abstract class ClientJsonRpc extends Client {
216
216
  * Get block by block number
217
217
  *
218
218
  * @param blockNumber - The block number.
219
- * @param verbosity - result format which allows 0 and 2. (Optional, the default is 2.)
220
- * @param withCycles - whether the return cycles of block transactions. (Optional, default false.)
219
+ * @param verbosity - Deprecated; this parameter has no effect.
220
+ * @param withCycles - Deprecated; this parameter has no effect.
221
221
  * @returns Block
222
222
  */
223
223
  getBlockByNumberNoCache = this.buildSender(
@@ -230,8 +230,8 @@ export abstract class ClientJsonRpc extends Client {
230
230
  * Get block by block hash
231
231
  *
232
232
  * @param blockHash - The block hash.
233
- * @param verbosity - result format which allows 0 and 2. (Optional, the default is 2.)
234
- * @param withCycles - whether the return cycles of block transactions. (Optional, default false.)
233
+ * @param verbosity - Deprecated; this parameter has no effect.
234
+ * @param withCycles - Deprecated; this parameter has no effect.
235
235
  * @returns Block
236
236
  */
237
237
  getBlockByHashNoCache = this.buildSender(
@@ -244,7 +244,7 @@ export abstract class ClientJsonRpc extends Client {
244
244
  * Get header by block number
245
245
  *
246
246
  * @param blockNumber - The block number.
247
- * @param verbosity - result format which allows 0 and 1. (Optional, the default is 1.)
247
+ * @param verbosity - Deprecated; this parameter has no effect.
248
248
  * @returns BlockHeader
249
249
  */
250
250
  getHeaderByNumberNoCache = this.buildSender(
@@ -257,7 +257,7 @@ export abstract class ClientJsonRpc extends Client {
257
257
  * Get header by block hash
258
258
  *
259
259
  * @param blockHash - The block hash.
260
- * @param verbosity - result format which allows 0 and 1. (Optional, the default is 1.)
260
+ * @param verbosity - Deprecated; this parameter has no effect.
261
261
  * @returns BlockHeader
262
262
  */
263
263
  getHeaderByHashNoCache = this.buildSender(
@@ -2,20 +2,17 @@
2
2
 
3
3
  import { Bytes, bytesFrom, BytesLike } from "../bytes/index.js";
4
4
 
5
- export type CodecLike<Encodable, Decoded = Encodable> = {
5
+ export type CodecLike<Encodable, Decoded = Encodable, Context = any> = {
6
6
  readonly encode: (encodable: Encodable) => Bytes;
7
- readonly decode: (
8
- decodable: BytesLike,
9
- config?: { isExtraFieldIgnored?: boolean },
10
- ) => Decoded;
7
+ readonly decode: (decodable: BytesLike, context?: Context) => Decoded;
11
8
  readonly byteLength?: number;
12
9
  };
13
- export class Codec<Encodable, Decoded = Encodable> {
10
+ export class Codec<Encodable, Decoded = Encodable, Context = any> {
14
11
  constructor(
15
12
  public readonly encode: (encodable: Encodable) => Bytes,
16
13
  public readonly decode: (
17
14
  decodable: BytesLike,
18
- config?: { isExtraFieldIgnored?: boolean }, // This is equivalent to "compatible" in the Rust implementation of Molecule.
15
+ context?: Context,
19
16
  ) => Decoded,
20
17
  public readonly byteLength?: number, // if provided, treat codec as fixed length
21
18
  ) {}
@@ -28,23 +25,23 @@ export class Codec<Encodable, Decoded = Encodable> {
28
25
  }
29
26
  }
30
27
 
31
- decodeOr<T>(
32
- decodable: BytesLike,
33
- fallback: T,
34
- config?: { isExtraFieldIgnored?: boolean }, // This is equivalent to "compatible" in the Rust implementation of Molecule.
35
- ) {
28
+ decodeOr<T>(decodable: BytesLike, fallback: T, context?: Context) {
36
29
  try {
37
- return this.decode(decodable, config);
30
+ return this.decode(decodable, context);
38
31
  } catch (_) {
39
32
  return fallback;
40
33
  }
41
34
  }
42
35
 
43
- static from<Encodable, Decoded = Encodable>({
36
+ static from<Encodable, Decoded = Encodable, Context = any>({
44
37
  encode,
45
38
  decode,
46
39
  byteLength,
47
- }: CodecLike<Encodable, Decoded>): Codec<Encodable, Decoded> {
40
+ }: CodecLike<Encodable, Decoded, Context>): Codec<
41
+ Encodable,
42
+ Decoded,
43
+ Context
44
+ > {
48
45
  return new Codec(
49
46
  (encodable: Encodable) => {
50
47
  const encoded = encode(encodable);
@@ -55,7 +52,7 @@ export class Codec<Encodable, Decoded = Encodable> {
55
52
  }
56
53
  return encoded;
57
54
  },
58
- (decodable, config) => {
55
+ (decodable, context) => {
59
56
  const decodableBytes = bytesFrom(decodable);
60
57
  if (
61
58
  byteLength !== undefined &&
@@ -65,7 +62,7 @@ export class Codec<Encodable, Decoded = Encodable> {
65
62
  `Codec.decode: expected byte length ${byteLength}, got ${decodableBytes.byteLength}`,
66
63
  );
67
64
  }
68
- return decode(decodable, config);
65
+ return decode(decodable, context);
69
66
  },
70
67
  byteLength,
71
68
  );
@@ -77,32 +74,59 @@ export class Codec<Encodable, Decoded = Encodable> {
77
74
  }: {
78
75
  inMap?: (encodable: NewEncodable) => Encodable;
79
76
  outMap?: (decoded: Decoded) => NewDecoded;
80
- }): Codec<NewEncodable, NewDecoded> {
77
+ }): Codec<NewEncodable, NewDecoded, Context> {
81
78
  return new Codec(
82
79
  (encodable) =>
83
80
  this.encode((inMap ? inMap(encodable) : encodable) as Encodable),
84
- (buffer, config) =>
81
+ (buffer, context) =>
85
82
  (outMap
86
- ? outMap(this.decode(buffer, config))
87
- : this.decode(buffer, config)) as NewDecoded,
83
+ ? outMap(this.decode(buffer, context))
84
+ : this.decode(buffer, context)) as NewDecoded,
88
85
  this.byteLength,
89
86
  );
90
87
  }
91
88
 
92
89
  mapIn<NewEncodable>(
93
90
  map: (encodable: NewEncodable) => Encodable,
94
- ): Codec<NewEncodable, Decoded> {
91
+ ): Codec<NewEncodable, Decoded, Context> {
95
92
  return this.map({ inMap: map });
96
93
  }
97
94
 
98
95
  mapOut<NewDecoded>(
99
96
  map: (decoded: Decoded) => NewDecoded,
100
- ): Codec<Encodable, NewDecoded> {
97
+ ): Codec<Encodable, NewDecoded, Context> {
101
98
  return this.map({ outMap: map });
102
99
  }
103
100
  }
104
101
 
105
- export type EncodableType<T extends CodecLike<any, any>> =
106
- T extends CodecLike<infer Encodable, unknown> ? Encodable : never;
107
- export type DecodedType<T extends CodecLike<any, any>> =
108
- T extends CodecLike<any, infer Decoded> ? Decoded : never;
102
+ export type EncodableType<T extends CodecLike<any, any, any>> =
103
+ T extends CodecLike<infer Encodable, unknown, any> ? Encodable : never;
104
+ export type DecodedType<T extends CodecLike<any, any, any>> =
105
+ T extends CodecLike<any, infer Decoded, any> ? Decoded : never;
106
+
107
+ type IsAny<T> = 0 extends 1 & T ? true : false;
108
+
109
+ /**
110
+ * The context a codec specifically requires when composed with other codecs.
111
+ * Legacy `any` is normalized to `unknown`, while `Extract` preserves that the
112
+ * normalized type is assignable to the codec's original context.
113
+ */
114
+ export type ContextType<T extends CodecLike<any, any, any>> = T extends {
115
+ readonly decode: (decodable: BytesLike, context?: infer Context) => unknown;
116
+ }
117
+ ? Extract<IsAny<Context> extends true ? unknown : Context, Context>
118
+ : unknown;
119
+
120
+ /**
121
+ * The combined context required by every codec in a record.
122
+ *
123
+ * Map each child context to a function parameter before forming the union so a
124
+ * legacy `any` (normalized to `unknown` by {@link ContextType}) cannot absorb
125
+ * the other contexts. Inferring from the resulting contravariant parameter
126
+ * position converts the function union into an intersection of its contexts.
127
+ */
128
+ export type ChildContext<T extends Record<string, CodecLike<any, any, any>>> = {
129
+ [K in keyof T]: (context: ContextType<T[K]>) => void;
130
+ }[keyof T] extends (context: infer Context) => void
131
+ ? Context
132
+ : unknown;