@ckb-ccc/core 0.0.13-alpha.7 → 0.0.13-alpha.8

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 (33) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/dist/client/cache/cache.d.ts +29 -9
  3. package/dist/client/cache/cache.d.ts.map +1 -1
  4. package/dist/client/cache/cache.js +43 -1
  5. package/dist/client/cache/memory.d.ts +10 -6
  6. package/dist/client/cache/memory.d.ts.map +1 -1
  7. package/dist/client/cache/memory.js +49 -39
  8. package/dist/client/clientTypes.d.ts +25 -2
  9. package/dist/client/clientTypes.d.ts.map +1 -1
  10. package/dist/client/clientTypes.js +26 -1
  11. package/dist/client/jsonRpc/index.d.ts.map +1 -1
  12. package/dist/client/jsonRpc/index.js +24 -1
  13. package/dist/fixedPoint/index.d.ts +3 -3
  14. package/dist/fixedPoint/index.js +3 -3
  15. package/dist.commonjs/client/cache/cache.d.ts +29 -9
  16. package/dist.commonjs/client/cache/cache.d.ts.map +1 -1
  17. package/dist.commonjs/client/cache/cache.js +45 -0
  18. package/dist.commonjs/client/cache/memory.d.ts +10 -6
  19. package/dist.commonjs/client/cache/memory.d.ts.map +1 -1
  20. package/dist.commonjs/client/cache/memory.js +49 -39
  21. package/dist.commonjs/client/clientTypes.d.ts +25 -2
  22. package/dist.commonjs/client/clientTypes.d.ts.map +1 -1
  23. package/dist.commonjs/client/clientTypes.js +33 -5
  24. package/dist.commonjs/client/jsonRpc/index.d.ts.map +1 -1
  25. package/dist.commonjs/client/jsonRpc/index.js +40 -17
  26. package/dist.commonjs/fixedPoint/index.d.ts +3 -3
  27. package/dist.commonjs/fixedPoint/index.js +3 -3
  28. package/package.json +1 -1
  29. package/src/client/cache/cache.ts +58 -13
  30. package/src/client/cache/memory.ts +60 -52
  31. package/src/client/clientTypes.ts +54 -3
  32. package/src/client/jsonRpc/index.ts +44 -2
  33. package/src/fixedPoint/index.ts +3 -3
@@ -11,24 +11,32 @@ import { ClientCollectableSearchKeyLike } from "../clientTypes.advanced.js";
11
11
  import { ClientCache } from "./cache.js";
12
12
  import { filterCell } from "./memory.advanced.js";
13
13
 
14
- export class ClientCacheMemory implements ClientCache {
15
- private readonly unusableOutPoints: OutPoint[] = [];
16
- private readonly usableCells: Cell[] = [];
17
- private readonly knownTransactions: Transaction[] = [];
18
- private readonly knownCells: Cell[] = [];
14
+ export class ClientCacheMemory extends ClientCache {
15
+ /**
16
+ * OutPoint => [isLive, Cell | OutPoint]
17
+ */
18
+ private readonly cells: Map<
19
+ string,
20
+ | [
21
+ false,
22
+ Pick<Cell, "outPoint"> &
23
+ Partial<Pick<Cell, "cellOutput" | "outputData">>,
24
+ ]
25
+ | [true, Cell]
26
+ | [undefined, Cell]
27
+ > = new Map();
28
+
29
+ /**
30
+ * TX Hash => Transaction
31
+ */
32
+ private readonly knownTransactions: Map<string, Transaction> = new Map();
19
33
 
20
34
  async markUsable(...cellLikes: (CellLike | CellLike[])[]): Promise<void> {
21
35
  cellLikes.flat().forEach((cellLike) => {
22
36
  const cell = Cell.from(cellLike).clone();
23
- this.usableCells.push(cell);
24
- this.knownCells.push(cell);
37
+ const outPointStr = hexFrom(cell.outPoint.toBytes());
25
38
 
26
- const index = this.unusableOutPoints.findIndex((o) =>
27
- cell.outPoint.eq(o),
28
- );
29
- if (index !== -1) {
30
- this.unusableOutPoints.splice(index, 1);
31
- }
39
+ this.cells.set(outPointStr, [true, cell]);
32
40
  });
33
41
  }
34
42
 
@@ -37,74 +45,74 @@ export class ClientCacheMemory implements ClientCache {
37
45
  ): Promise<void> {
38
46
  outPointLikes.flat().forEach((outPointLike) => {
39
47
  const outPoint = OutPoint.from(outPointLike);
40
- this.unusableOutPoints.push(outPoint.clone());
48
+ const outPointStr = hexFrom(outPoint.toBytes());
41
49
 
42
- const index = this.usableCells.findIndex((c) => c.outPoint.eq(outPoint));
43
- if (index !== -1) {
44
- this.usableCells.splice(index, 1);
50
+ const existed = this.cells.get(outPointStr);
51
+ if (existed) {
52
+ existed[0] = false;
53
+ return;
45
54
  }
55
+ this.cells.set(outPointStr, [false, { outPoint }]);
46
56
  });
47
57
  }
48
58
 
49
- async markTransactions(
50
- ...transactionLike: (TransactionLike | TransactionLike[])[]
51
- ): Promise<void> {
52
- await Promise.all(
53
- transactionLike.flat().map(async (transactionLike) => {
54
- const tx = Transaction.from(transactionLike);
55
- const txHash = tx.hash();
56
-
57
- await Promise.all(
58
- tx.inputs.map((i) => this.markUnusable(i.previousOutput)),
59
- );
60
- await Promise.all(
61
- tx.outputs.map((o, i) =>
62
- this.markUsable({
63
- cellOutput: o,
64
- outputData: tx.outputsData[i],
65
- outPoint: {
66
- txHash,
67
- index: i,
68
- },
69
- }),
70
- ),
71
- );
72
- }),
73
- );
59
+ async clear(): Promise<void> {
60
+ for (const val of this.cells.values()) {
61
+ val[0] = undefined;
62
+ }
74
63
  }
75
64
 
76
65
  async *findCells(
77
66
  keyLike: ClientCollectableSearchKeyLike,
78
67
  ): AsyncGenerator<Cell> {
79
- for (const cell of this.usableCells) {
68
+ for (const [isLive, cell] of this.cells.values()) {
69
+ if (!isLive) {
70
+ continue;
71
+ }
80
72
  if (!filterCell(keyLike, cell)) {
81
73
  continue;
82
74
  }
83
75
 
84
- yield cell;
76
+ yield cell.clone();
77
+ }
78
+ }
79
+ async getCell(outPointLike: OutPointLike): Promise<Cell | undefined> {
80
+ const outPoint = OutPoint.from(outPointLike);
81
+
82
+ const cell = this.cells.get(hexFrom(outPoint.toBytes()))?.[1];
83
+ if (cell && cell.cellOutput && cell.outputData) {
84
+ return Cell.from((cell as Cell).clone());
85
85
  }
86
86
  }
87
87
 
88
88
  async isUnusable(outPointLike: OutPointLike): Promise<boolean> {
89
89
  const outPoint = OutPoint.from(outPointLike);
90
- return this.unusableOutPoints.find((o) => o.eq(outPoint)) !== undefined;
90
+
91
+ return !(this.cells.get(hexFrom(outPoint.toBytes()))?.[0] ?? true);
91
92
  }
92
93
 
93
94
  async recordTransactions(
94
95
  ...transactions: (TransactionLike | TransactionLike[])[]
95
96
  ): Promise<void> {
96
- this.knownTransactions.push(...transactions.flat().map(Transaction.from));
97
+ transactions.flat().map((txLike) => {
98
+ const tx = Transaction.from(txLike);
99
+ this.knownTransactions.set(tx.hash(), tx);
100
+ });
97
101
  }
98
102
  async getTransaction(txHashLike: HexLike): Promise<Transaction | undefined> {
99
103
  const txHash = hexFrom(txHashLike);
100
- return this.knownTransactions.find((tx) => tx.hash() === txHash);
104
+ return this.knownTransactions.get(txHash)?.clone();
101
105
  }
102
106
 
103
107
  async recordCells(...cells: (CellLike | CellLike[])[]): Promise<void> {
104
- this.knownCells.push(...cells.flat().map(Cell.from));
105
- }
106
- async getCell(outPointLike: OutPointLike): Promise<Cell | undefined> {
107
- const outPoint = OutPoint.from(outPointLike);
108
- return this.knownCells.find((cell) => cell.outPoint.eq(outPoint));
108
+ cells.flat().map((cellLike) => {
109
+ const cell = Cell.from(cellLike);
110
+ const outPointStr = hexFrom(cell.outPoint.toBytes());
111
+
112
+ if (this.cells.get(outPointStr)) {
113
+ return;
114
+ }
115
+ this.cells.set(outPointStr, [undefined, cell]);
116
+ });
109
117
  }
110
118
  }
@@ -1,6 +1,13 @@
1
- import { Cell, Epoch, Script, Transaction } from "../ckb/index.js";
2
- import { Hex, hexFrom } from "../hex/index.js";
3
- import { Num, NumLike } from "../num/index.js";
1
+ import {
2
+ Cell,
3
+ Epoch,
4
+ OutPoint,
5
+ OutPointLike,
6
+ Script,
7
+ Transaction,
8
+ } from "../ckb/index.js";
9
+ import { Hex, HexLike, hexFrom } from "../hex/index.js";
10
+ import { Num, NumLike, numFrom } from "../num/index.js";
4
11
  import { apply } from "../utils/index.js";
5
12
  import {
6
13
  ClientCollectableSearchKeyFilterLike,
@@ -231,3 +238,47 @@ export type ClientBlock = {
231
238
  transactions: Transaction[];
232
239
  uncles: ClientBlockUncle[];
233
240
  };
241
+
242
+ export interface ErrorClientBaseLike {
243
+ message: string;
244
+ code: number;
245
+ data: string;
246
+ }
247
+ export class ErrorClientBase extends Error {
248
+ public readonly message: string;
249
+ public readonly code: number;
250
+ public readonly data: string;
251
+
252
+ constructor(origin: ErrorClientBaseLike) {
253
+ super(origin.message);
254
+ this.message = origin.message;
255
+ this.code = origin.code;
256
+ this.data = origin.data;
257
+ }
258
+ }
259
+
260
+ export class ErrorClientResolveUnknown extends ErrorClientBase {
261
+ public readonly outPoint: OutPoint;
262
+ constructor(origin: ErrorClientBaseLike, outPointLike: OutPointLike) {
263
+ super(origin);
264
+ this.outPoint = OutPoint.from(outPointLike);
265
+ }
266
+ }
267
+
268
+ export class ErrorClientVerification extends ErrorClientBase {
269
+ public readonly sourceIndex: Num;
270
+ public readonly scriptCodeHash: Hex;
271
+
272
+ constructor(
273
+ origin: ErrorClientBaseLike,
274
+ public readonly source: "lock" | "inputType" | "outputType",
275
+ sourceIndex: NumLike,
276
+ public readonly errorCode: number,
277
+ public readonly scriptHashType: "data" | "type",
278
+ scriptCodeHash: HexLike,
279
+ ) {
280
+ super(origin);
281
+ this.sourceIndex = numFrom(sourceIndex);
282
+ this.scriptCodeHash = hexFrom(scriptCodeHash);
283
+ }
284
+ }
@@ -1,4 +1,4 @@
1
- import { TransactionLike } from "../../ckb/index.js";
1
+ import { OutPoint, TransactionLike } from "../../ckb/index.js";
2
2
  import { Hex, HexLike, hexFrom } from "../../hex/index.js";
3
3
  import { Num, NumLike, numFrom, numToHex } from "../../num/index.js";
4
4
  import { apply } from "../../utils/index.js";
@@ -8,6 +8,10 @@ import {
8
8
  ClientFindCellsResponse,
9
9
  ClientIndexerSearchKeyLike,
10
10
  ClientTransactionResponse,
11
+ ErrorClientBase,
12
+ ErrorClientBaseLike,
13
+ ErrorClientResolveUnknown,
14
+ ErrorClientVerification,
11
15
  OutputsValidator,
12
16
  } from "../clientTypes.js";
13
17
  import {
@@ -289,7 +293,45 @@ export abstract class ClientJsonRpc extends Client {
289
293
  ),
290
294
  );
291
295
 
292
- return transform(await this.send(payload), outTransformer);
296
+ try {
297
+ return transform(await this.send(payload), outTransformer);
298
+ } catch (errAny: unknown) {
299
+ if (typeof errAny !== "object" || errAny === null) {
300
+ throw errAny;
301
+ }
302
+ const err = errAny as ErrorClientBaseLike;
303
+
304
+ const unknownOutPointMatch = err.data.match(
305
+ new RegExp("Resolve\\(Unknown\\(OutPoint\\((0x.*)\\)\\)\\)"),
306
+ )?.[1];
307
+ if (unknownOutPointMatch) {
308
+ throw new ErrorClientResolveUnknown(
309
+ err,
310
+ OutPoint.fromBytes(unknownOutPointMatch),
311
+ );
312
+ }
313
+ const verificationFailedMatch = err.data.match(
314
+ new RegExp(
315
+ "Verification\\(Error { kind: Script, inner: TransactionScriptError { source: (Inputs|Outputs)\\[([0-9]*)\\].(Lock|Type), cause: ValidationFailure: see error code (-?[0-9])* on page https://nervosnetwork\\.github\\.io/ckb-script-error-codes/by-(type|data)-hash/(.*)\\.html",
316
+ ),
317
+ );
318
+ if (verificationFailedMatch) {
319
+ throw new ErrorClientVerification(
320
+ err,
321
+ verificationFailedMatch[3] === "Lock"
322
+ ? "lock"
323
+ : verificationFailedMatch[1] === "Inputs"
324
+ ? "inputType"
325
+ : "outputType",
326
+ verificationFailedMatch[2],
327
+ Number(verificationFailedMatch[4]),
328
+ verificationFailedMatch[5] === "data" ? "data" : "type",
329
+ verificationFailedMatch[6],
330
+ );
331
+ }
332
+
333
+ throw new ErrorClientBase(err);
334
+ }
293
335
  };
294
336
  }
295
337
 
@@ -24,8 +24,8 @@ export type FixedPointLike = bigint | string | number;
24
24
  * @example
25
25
  * ```typescript
26
26
  * const str = fixedPointToString(123456789n, 8); // Outputs "1.23456789"
27
- * const strFromString = fixedPointToString("123456789", 8); // Outputs "1.23456789"
28
- * const strFromNumber = fixedPointToString(123456789, 8); // Outputs "1.23456789"
27
+ * const strFromString = fixedPointToString("1.23456789", 8); // Outputs "1.23456789"
28
+ * const strFromNumber = fixedPointToString(1.23456789, 8); // Outputs "1.23456789"
29
29
  * ```
30
30
  */
31
31
 
@@ -54,7 +54,7 @@ export function fixedPointToString(val: FixedPointLike, decimals = 8): string {
54
54
  *
55
55
  * @example
56
56
  * ```typescript
57
- * const fixedPoint = fixedPointFrom(1.23456789, 8); // Outputs 123456789n
57
+ * const fixedPoint = fixedPointFrom(123456789n, 8); // Outputs 123456789n
58
58
  * const fixedPointFromString = fixedPointFrom("1.23456789", 8); // Outputs 123456789n
59
59
  * const fixedPointFromNumber = fixedPointFrom(1.23456789, 8); // Outputs 123456789n
60
60
  * ```