@ckb-ccc/core 0.0.13-alpha.6 → 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 (71) hide show
  1. package/CHANGELOG.md +22 -0
  2. package/dist/ckb/transaction.d.ts +91 -1
  3. package/dist/ckb/transaction.d.ts.map +1 -1
  4. package/dist/ckb/transaction.js +118 -24
  5. package/dist/client/cache/cache.d.ts +29 -9
  6. package/dist/client/cache/cache.d.ts.map +1 -1
  7. package/dist/client/cache/cache.js +43 -1
  8. package/dist/client/cache/memory.d.ts +10 -6
  9. package/dist/client/cache/memory.d.ts.map +1 -1
  10. package/dist/client/cache/memory.js +49 -39
  11. package/dist/client/client.d.ts +10 -4
  12. package/dist/client/client.d.ts.map +1 -1
  13. package/dist/client/client.js +6 -5
  14. package/dist/client/clientPublicMainnet.advanced.d.ts.map +1 -1
  15. package/dist/client/clientPublicMainnet.advanced.js +15 -0
  16. package/dist/client/clientPublicTestnet.advanced.d.ts.map +1 -1
  17. package/dist/client/clientPublicTestnet.advanced.js +15 -0
  18. package/dist/client/clientTypes.d.ts +47 -4
  19. package/dist/client/clientTypes.d.ts.map +1 -1
  20. package/dist/client/clientTypes.js +26 -1
  21. package/dist/client/jsonRpc/index.d.ts +39 -1
  22. package/dist/client/jsonRpc/index.d.ts.map +1 -1
  23. package/dist/client/jsonRpc/index.js +63 -2
  24. package/dist/client/jsonRpc/transformers.d.ts.map +1 -1
  25. package/dist/client/jsonRpc/transformers.js +11 -4
  26. package/dist/fixedPoint/index.d.ts +3 -3
  27. package/dist/fixedPoint/index.js +3 -3
  28. package/dist/signer/signer/index.d.ts +3 -1
  29. package/dist/signer/signer/index.d.ts.map +1 -1
  30. package/dist/signer/signer/index.js +14 -0
  31. package/dist.commonjs/ckb/transaction.d.ts +91 -1
  32. package/dist.commonjs/ckb/transaction.d.ts.map +1 -1
  33. package/dist.commonjs/ckb/transaction.js +121 -23
  34. package/dist.commonjs/client/cache/cache.d.ts +29 -9
  35. package/dist.commonjs/client/cache/cache.d.ts.map +1 -1
  36. package/dist.commonjs/client/cache/cache.js +45 -0
  37. package/dist.commonjs/client/cache/memory.d.ts +10 -6
  38. package/dist.commonjs/client/cache/memory.d.ts.map +1 -1
  39. package/dist.commonjs/client/cache/memory.js +49 -39
  40. package/dist.commonjs/client/client.d.ts +10 -4
  41. package/dist.commonjs/client/client.d.ts.map +1 -1
  42. package/dist.commonjs/client/client.js +6 -5
  43. package/dist.commonjs/client/clientPublicMainnet.advanced.d.ts.map +1 -1
  44. package/dist.commonjs/client/clientPublicMainnet.advanced.js +15 -0
  45. package/dist.commonjs/client/clientPublicTestnet.advanced.d.ts.map +1 -1
  46. package/dist.commonjs/client/clientPublicTestnet.advanced.js +15 -0
  47. package/dist.commonjs/client/clientTypes.d.ts +47 -4
  48. package/dist.commonjs/client/clientTypes.d.ts.map +1 -1
  49. package/dist.commonjs/client/clientTypes.js +33 -5
  50. package/dist.commonjs/client/jsonRpc/index.d.ts +39 -1
  51. package/dist.commonjs/client/jsonRpc/index.d.ts.map +1 -1
  52. package/dist.commonjs/client/jsonRpc/index.js +74 -13
  53. package/dist.commonjs/client/jsonRpc/transformers.d.ts.map +1 -1
  54. package/dist.commonjs/client/jsonRpc/transformers.js +55 -48
  55. package/dist.commonjs/fixedPoint/index.d.ts +3 -3
  56. package/dist.commonjs/fixedPoint/index.js +3 -3
  57. package/dist.commonjs/signer/signer/index.d.ts +3 -1
  58. package/dist.commonjs/signer/signer/index.d.ts.map +1 -1
  59. package/dist.commonjs/signer/signer/index.js +14 -0
  60. package/package.json +1 -1
  61. package/src/ckb/transaction.ts +170 -30
  62. package/src/client/cache/cache.ts +58 -13
  63. package/src/client/cache/memory.ts +60 -52
  64. package/src/client/client.ts +22 -5
  65. package/src/client/clientPublicMainnet.advanced.ts +17 -0
  66. package/src/client/clientPublicTestnet.advanced.ts +17 -0
  67. package/src/client/clientTypes.ts +76 -5
  68. package/src/client/jsonRpc/index.ts +105 -3
  69. package/src/client/jsonRpc/transformers.ts +11 -3
  70. package/src/fixedPoint/index.ts +3 -3
  71. package/src/signer/signer/index.ts +20 -1
@@ -8,23 +8,68 @@ import {
8
8
  import { HexLike } from "../../hex/index.js";
9
9
  import { ClientCollectableSearchKeyLike } from "../clientTypes.advanced.js";
10
10
 
11
- export interface ClientCache {
12
- markUsable(...cellLikes: (CellLike | CellLike[])[]): Promise<void>;
13
- markUnusable(
11
+ export abstract class ClientCache {
12
+ abstract markUsable(...cellLikes: (CellLike | CellLike[])[]): Promise<void>;
13
+ abstract markUnusable(
14
14
  ...outPointLike: (OutPointLike | OutPointLike[])[]
15
15
  ): Promise<void>;
16
- markTransactions(
16
+ async markTransactions(
17
17
  ...transactionLike: (TransactionLike | TransactionLike[])[]
18
- ): Promise<void>;
18
+ ): Promise<void> {
19
+ await Promise.all([
20
+ this.recordTransactions(...transactionLike),
21
+ ...transactionLike.flat().map((transactionLike) => {
22
+ const tx = Transaction.from(transactionLike);
23
+ const txHash = tx.hash();
19
24
 
20
- isUnusable(outPointLike: OutPointLike): Promise<boolean>;
25
+ return Promise.all([
26
+ ...tx.inputs.map((i) => this.markUnusable(i.previousOutput)),
27
+ ...tx.outputs.map((o, i) =>
28
+ this.markUsable({
29
+ cellOutput: o,
30
+ outputData: tx.outputsData[i],
31
+ outPoint: {
32
+ txHash,
33
+ index: i,
34
+ },
35
+ }),
36
+ ),
37
+ ]);
38
+ }),
39
+ ]);
40
+ }
41
+ abstract clear(): Promise<void>;
42
+ abstract findCells(
43
+ filter: ClientCollectableSearchKeyLike,
44
+ ): AsyncGenerator<Cell>;
45
+ /**
46
+ * Get a known cell by out point
47
+ * @param _outPoint
48
+ */
49
+ abstract getCell(_outPoint: OutPointLike): Promise<Cell | undefined>;
50
+ abstract isUnusable(outPointLike: OutPointLike): Promise<boolean>;
21
51
 
22
- recordTransactions(
23
- ...transactions: (TransactionLike | TransactionLike[])[]
24
- ): Promise<void>;
25
- getTransaction(txHash: HexLike): Promise<Transaction | undefined>;
52
+ /**
53
+ * Record known transactions
54
+ * Implement this method to enable transactions query caching
55
+ * @param _transactions
56
+ */
57
+ async recordTransactions(
58
+ ..._transactions: (TransactionLike | TransactionLike[])[]
59
+ ): Promise<void> {}
60
+ /**
61
+ * Get a known transaction by hash
62
+ * Implement this method to enable transactions query caching
63
+ * @param _txHash
64
+ */
65
+ async getTransaction(_txHash: HexLike): Promise<Transaction | undefined> {
66
+ return;
67
+ }
26
68
 
27
- recordCells(...cells: (CellLike | CellLike[])[]): Promise<void>;
28
- getCell(outPoint: OutPointLike): Promise<Cell | undefined>;
29
- findCells(filter: ClientCollectableSearchKeyLike): AsyncGenerator<Cell>;
69
+ /**
70
+ * Record known cells
71
+ * Implement this method to enable cells query caching
72
+ * @param _cells
73
+ */
74
+ async recordCells(..._cells: (CellLike | CellLike[])[]): Promise<void> {}
30
75
  }
@@ -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
  }
@@ -18,6 +18,7 @@ import { ClientCacheMemory } from "./cache/memory.js";
18
18
  import { ClientCollectableSearchKeyLike } from "./clientTypes.advanced.js";
19
19
  import {
20
20
  ClientBlock,
21
+ ClientBlockHeader,
21
22
  ClientFindCellsResponse,
22
23
  ClientFindTransactionsGroupedResponse,
23
24
  ClientFindTransactionsResponse,
@@ -45,6 +46,7 @@ export enum KnownScript {
45
46
  UniqueType = "UniqueType",
46
47
  SingleUseLock = "SingleUseLock",
47
48
  OutputTypeProxyLock = "OutputTypeProxyLock",
49
+ NervosDao = "NervosDao",
48
50
  }
49
51
 
50
52
  /**
@@ -92,6 +94,7 @@ export abstract class Client {
92
94
  >;
93
95
 
94
96
  abstract getTip(): Promise<Num>;
97
+ abstract getTipHeader(verbosity?: number | null): Promise<ClientBlockHeader>;
95
98
  abstract getBlockByNumber(
96
99
  blockNumber: NumLike,
97
100
  verbosity?: number | null,
@@ -102,6 +105,20 @@ export abstract class Client {
102
105
  verbosity?: number | null,
103
106
  withCycles?: boolean | null,
104
107
  ): Promise<ClientBlock | undefined>;
108
+ abstract getHeaderByNumber(
109
+ blockNumber: NumLike,
110
+ verbosity?: number | null,
111
+ ): Promise<ClientBlockHeader | undefined>;
112
+ abstract getHeaderByHash(
113
+ blockHash: HexLike,
114
+ verbosity?: number | null,
115
+ ): Promise<ClientBlockHeader | undefined>;
116
+
117
+ abstract estimateCycles(transaction: TransactionLike): Promise<Num>;
118
+ abstract sendTransactionDry(
119
+ transaction: TransactionLike,
120
+ validator?: OutputsValidator,
121
+ ): Promise<Num>;
105
122
 
106
123
  abstract sendTransactionNoCache(
107
124
  transaction: TransactionLike,
@@ -155,7 +172,7 @@ export abstract class Client {
155
172
  return res;
156
173
  }
157
174
 
158
- async *findCells(
175
+ async *findCellsOnChin(
159
176
  key: ClientIndexerSearchKeyLike,
160
177
  order?: "asc" | "desc",
161
178
  limit = 10,
@@ -185,7 +202,7 @@ export abstract class Client {
185
202
  * @param keyLike - The search key.
186
203
  * @returns A async generator for yielding cells.
187
204
  */
188
- async *findCellsByCollectableSearchKey(
205
+ async *findCells(
189
206
  keyLike: ClientCollectableSearchKeyLike,
190
207
  order?: "asc" | "desc",
191
208
  limit = 10,
@@ -198,7 +215,7 @@ export abstract class Client {
198
215
  yield cell;
199
216
  }
200
217
 
201
- for await (const cell of this.findCells(key, order, limit)) {
218
+ for await (const cell of this.findCellsOnChin(key, order, limit)) {
202
219
  if (
203
220
  (await this.cache.isUnusable(cell.outPoint)) ||
204
221
  foundedOutPoints.some((founded) => founded.eq(cell.outPoint))
@@ -217,7 +234,7 @@ export abstract class Client {
217
234
  order?: "asc" | "desc",
218
235
  limit = 10,
219
236
  ): AsyncGenerator<Cell> {
220
- return this.findCellsByCollectableSearchKey(
237
+ return this.findCells(
221
238
  {
222
239
  script: lock,
223
240
  scriptType: "lock",
@@ -238,7 +255,7 @@ export abstract class Client {
238
255
  order?: "asc" | "desc",
239
256
  limit = 10,
240
257
  ): AsyncGenerator<Cell> {
241
- return this.findCellsByCollectableSearchKey(
258
+ return this.findCells(
242
259
  {
243
260
  script: type,
244
261
  scriptType: "type",
@@ -254,4 +254,21 @@ export const MAINNET_SCRIPTS: Record<
254
254
  },
255
255
  ],
256
256
  },
257
+ [KnownScript.NervosDao]: {
258
+ codeHash:
259
+ "0x82d76d1b75fe2fd9a27dfbaa65a039221a380d76c926f378d3f81cf3e7e13f2e",
260
+ hashType: "type",
261
+ cellDeps: [
262
+ {
263
+ cellDep: {
264
+ outPoint: {
265
+ txHash:
266
+ "0xe2fb199810d49a4d8beec56718ba2593b665db9d52299a0f9e6e75416d73ff5c",
267
+ index: 2,
268
+ },
269
+ depType: "code",
270
+ },
271
+ },
272
+ ],
273
+ },
257
274
  });
@@ -265,4 +265,21 @@ export const TESTNET_SCRIPTS: Record<
265
265
  },
266
266
  ],
267
267
  },
268
+ [KnownScript.NervosDao]: {
269
+ codeHash:
270
+ "0x82d76d1b75fe2fd9a27dfbaa65a039221a380d76c926f378d3f81cf3e7e13f2e",
271
+ hashType: "type",
272
+ cellDeps: [
273
+ {
274
+ cellDep: {
275
+ outPoint: {
276
+ txHash:
277
+ "0x8f8c79eb6671709633fe6a46de93c0fedc9c1b8a6527a18d3983879542635c9f",
278
+ index: 2,
279
+ },
280
+ depType: "code",
281
+ },
282
+ },
283
+ ],
284
+ },
268
285
  });
@@ -1,6 +1,13 @@
1
- import { Cell, 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,
@@ -181,8 +188,28 @@ export type ClientFindTransactionsGroupedResponse = {
181
188
  */
182
189
  export type ClientBlockHeader = {
183
190
  compactTarget: Num;
184
- dao: Hex;
185
- epoch: Num;
191
+ dao: {
192
+ /**
193
+ * C_i: the total issuance up to and including block i.
194
+ */
195
+ c: Num;
196
+ /**
197
+ * AR_i: the current accumulated rate at block i.
198
+ * AR_j / AR_i reflects the CKByte amount if one deposit 1 CKB to Nervos DAO at block i, and withdraw at block j.
199
+ */
200
+ ar: Num;
201
+ /**
202
+ * S_i: the total unissued secondary issuance up to and including block i,
203
+ * including unclaimed Nervos DAO compensation and treasury funds.
204
+ */
205
+ s: Num;
206
+ /**
207
+ * U_i: the total occupied capacities currently in the blockchain up to and including block i.
208
+ * Occupied capacity is the sum of capacities used to store all cells.
209
+ */
210
+ u: Num;
211
+ };
212
+ epoch: Epoch;
186
213
  extraHash: Hex;
187
214
  hash: Hex;
188
215
  nonce: Num;
@@ -211,3 +238,47 @@ export type ClientBlock = {
211
238
  transactions: Transaction[];
212
239
  uncles: ClientBlockUncle[];
213
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 {
@@ -88,7 +92,17 @@ export abstract class ClientJsonRpc extends Client {
88
92
  ) as () => Promise<Num>;
89
93
 
90
94
  /**
91
- * Get block by block hash
95
+ * Get tip block header
96
+ *
97
+ * @param verbosity - result format which allows 0 and 1. (Optional, the default is 1.)
98
+ * @returns BlockHeader
99
+ */
100
+ getTipHeader = this.buildSender("get_tip_header", [], (b) =>
101
+ apply(JsonRpcTransformers.blockHeaderTo, b),
102
+ ) as Client["getTipHeader"];
103
+
104
+ /**
105
+ * Get block by block number
92
106
  *
93
107
  * @param blockNumber - The block number.
94
108
  * @param verbosity - result format which allows 0 and 2. (Optional, the default is 2.)
@@ -113,6 +127,56 @@ export abstract class ClientJsonRpc extends Client {
113
127
  apply(JsonRpcTransformers.blockTo, b),
114
128
  ) as Client["getBlockByHash"];
115
129
 
130
+ /**
131
+ * Get header by block number
132
+ *
133
+ * @param blockNumber - The block number.
134
+ * @param verbosity - result format which allows 0 and 1. (Optional, the default is 1.)
135
+ * @returns BlockHeader
136
+ */
137
+ getHeaderByNumber = this.buildSender(
138
+ "get_header_by_number",
139
+ [(v: NumLike) => numToHex(numFrom(v))],
140
+ (b) => apply(JsonRpcTransformers.blockHeaderTo, b),
141
+ ) as Client["getHeaderByNumber"];
142
+
143
+ /**
144
+ * Get header by block hash
145
+ *
146
+ * @param blockHash - The block hash.
147
+ * @param verbosity - result format which allows 0 and 1. (Optional, the default is 1.)
148
+ * @returns BlockHeader
149
+ */
150
+ getHeaderByHash = this.buildSender("get_header", [hexFrom], (b) =>
151
+ apply(JsonRpcTransformers.blockHeaderTo, b),
152
+ ) as Client["getHeaderByHash"];
153
+
154
+ /**
155
+ * Estimate cycles of a transaction.
156
+ *
157
+ * @param transaction - The transaction to estimate.
158
+ * @returns Consumed cycles
159
+ */
160
+ estimateCycles = this.buildSender(
161
+ "estimate_cycles",
162
+ [JsonRpcTransformers.transactionFrom],
163
+ ({ cycles }: { cycles: NumLike }) => numFrom(cycles),
164
+ ) as Client["estimateCycles"];
165
+
166
+ /**
167
+ * Test a transaction.
168
+ *
169
+ * @param transaction - The transaction to test.
170
+ * @param validator - "passthrough": Disable validation. "well_known_scripts_only": Only accept well known scripts in the transaction.
171
+ * @returns Consumed cycles
172
+ */
173
+
174
+ sendTransactionDry = this.buildSender(
175
+ "test_tx_pool_accept",
176
+ [JsonRpcTransformers.transactionFrom],
177
+ ({ cycles }: { cycles: NumLike }) => numFrom(cycles),
178
+ ) as Client["sendTransactionDry"];
179
+
116
180
  /**
117
181
  * Send a transaction to node.
118
182
  *
@@ -229,7 +293,45 @@ export abstract class ClientJsonRpc extends Client {
229
293
  ),
230
294
  );
231
295
 
232
- 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
+ }
233
335
  };
234
336
  }
235
337
 
@@ -1,3 +1,4 @@
1
+ import { bytesFrom } from "../../bytes/index.js";
1
2
  import {
2
3
  Cell,
3
4
  CellDep,
@@ -17,10 +18,11 @@ import {
17
18
  Transaction,
18
19
  TransactionLike,
19
20
  depTypeFrom,
21
+ epochFromHex,
20
22
  hashTypeFrom,
21
23
  } from "../../ckb/index.js";
22
24
  import { Hex, HexLike, hexFrom } from "../../hex/index.js";
23
- import { NumLike, numFrom, numToHex } from "../../num/index.js";
25
+ import { NumLike, numFrom, numLeFromBytes, numToHex } from "../../num/index.js";
24
26
  import { apply } from "../../utils/index.js";
25
27
  import {
26
28
  ClientBlock,
@@ -201,10 +203,16 @@ export class JsonRpcTransformers {
201
203
  };
202
204
  }
203
205
  static blockHeaderTo(header: JsonRpcBlockHeader): ClientBlockHeader {
206
+ const dao = bytesFrom(header.dao);
204
207
  return {
205
208
  compactTarget: numFrom(header.compact_target),
206
- dao: header.dao,
207
- epoch: numFrom(header.epoch),
209
+ dao: {
210
+ c: numLeFromBytes(dao.slice(0, 8)),
211
+ ar: numLeFromBytes(dao.slice(8, 16)),
212
+ s: numLeFromBytes(dao.slice(16, 24)),
213
+ u: numLeFromBytes(dao.slice(24, 32)),
214
+ },
215
+ epoch: epochFromHex(header.epoch),
208
216
  extraHash: header.extra_hash,
209
217
  hash: header.hash,
210
218
  nonce: numFrom(header.nonce),
@@ -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
  * ```