@ckb-ccc/core 1.5.3 → 1.7.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 (161) hide show
  1. package/CHANGELOG.md +61 -7
  2. package/dist/ckb/script.d.ts +2 -1
  3. package/dist/ckb/script.d.ts.map +1 -1
  4. package/dist/ckb/transaction.d.ts +125 -7
  5. package/dist/ckb/transaction.d.ts.map +1 -1
  6. package/dist/ckb/transaction.js +263 -73
  7. package/dist/client/cache/cache.d.ts +67 -11
  8. package/dist/client/cache/cache.d.ts.map +1 -1
  9. package/dist/client/cache/cache.js +94 -9
  10. package/dist/client/cache/memory.advanced.d.ts +2 -2
  11. package/dist/client/cache/memory.advanced.d.ts.map +1 -1
  12. package/dist/client/cache/memory.advanced.js +19 -7
  13. package/dist/client/cache/memory.d.ts +24 -7
  14. package/dist/client/cache/memory.d.ts.map +1 -1
  15. package/dist/client/cache/memory.js +76 -18
  16. package/dist/client/client.d.ts +30 -7
  17. package/dist/client/client.d.ts.map +1 -1
  18. package/dist/client/client.js +114 -22
  19. package/dist/client/clientPublicMainnet.advanced.d.ts +2 -1
  20. package/dist/client/clientPublicMainnet.advanced.d.ts.map +1 -1
  21. package/dist/client/clientPublicMainnet.advanced.js +1 -1
  22. package/dist/client/clientPublicMainnet.d.ts +2 -1
  23. package/dist/client/clientPublicMainnet.d.ts.map +1 -1
  24. package/dist/client/clientPublicMainnet.js +1 -6
  25. package/dist/client/clientPublicTestnet.advanced.d.ts +2 -1
  26. package/dist/client/clientPublicTestnet.advanced.d.ts.map +1 -1
  27. package/dist/client/clientPublicTestnet.advanced.js +1 -1
  28. package/dist/client/clientPublicTestnet.d.ts +2 -1
  29. package/dist/client/clientPublicTestnet.d.ts.map +1 -1
  30. package/dist/client/clientTypes.advanced.d.ts +3 -0
  31. package/dist/client/clientTypes.advanced.d.ts.map +1 -1
  32. package/dist/client/clientTypes.advanced.js +3 -0
  33. package/dist/client/clientTypes.d.ts +110 -38
  34. package/dist/client/clientTypes.d.ts.map +1 -1
  35. package/dist/client/clientTypes.js +118 -31
  36. package/dist/client/index.d.ts +1 -0
  37. package/dist/client/index.d.ts.map +1 -1
  38. package/dist/client/index.js +1 -0
  39. package/dist/client/jsonRpc/client.d.ts +4 -4
  40. package/dist/client/jsonRpc/client.d.ts.map +1 -1
  41. package/dist/client/jsonRpc/client.js +4 -4
  42. package/dist/client/jsonRpc/transformers.js +3 -3
  43. package/dist/client/knownScript.d.ts +26 -0
  44. package/dist/client/knownScript.d.ts.map +1 -0
  45. package/dist/client/knownScript.js +27 -0
  46. package/dist/jsonRpc/transports/webSocket.d.ts.map +1 -1
  47. package/dist/jsonRpc/transports/webSocket.js +7 -3
  48. package/dist/molecule/predefined.d.ts +10 -10
  49. package/dist/molecule/predefined.d.ts.map +1 -1
  50. package/dist/num/index.d.ts.map +1 -1
  51. package/dist/num/index.js +17 -1
  52. package/dist/signer/ckb/signerCkbPublicKey.d.ts.map +1 -1
  53. package/dist/signer/ckb/signerCkbPublicKey.js +1 -5
  54. package/dist/signer/nostr/index.d.ts +1 -0
  55. package/dist/signer/nostr/index.d.ts.map +1 -1
  56. package/dist/signer/nostr/index.js +1 -0
  57. package/dist/signer/nostr/signerNostr.d.ts +1 -1
  58. package/dist/signer/nostr/signerNostr.d.ts.map +1 -1
  59. package/dist/signer/nostr/signerNostr.js +8 -0
  60. package/dist/signer/nostr/signerNostrPrivateKey.d.ts +5 -7
  61. package/dist/signer/nostr/signerNostrPrivateKey.d.ts.map +1 -1
  62. package/dist/signer/nostr/signerNostrPrivateKey.js +6 -12
  63. package/dist/signer/nostr/signerNostrPublicKeyReadonly.d.ts +11 -0
  64. package/dist/signer/nostr/signerNostrPublicKeyReadonly.d.ts.map +1 -0
  65. package/dist/signer/nostr/signerNostrPublicKeyReadonly.js +22 -0
  66. package/dist/utils/index.d.ts +4 -0
  67. package/dist/utils/index.d.ts.map +1 -1
  68. package/dist/utils/index.js +13 -1
  69. package/dist.commonjs/advanced.js +17 -7
  70. package/dist.commonjs/ckb/script.d.ts +2 -1
  71. package/dist.commonjs/ckb/script.d.ts.map +1 -1
  72. package/dist.commonjs/ckb/transaction.d.ts +125 -7
  73. package/dist.commonjs/ckb/transaction.d.ts.map +1 -1
  74. package/dist.commonjs/ckb/transaction.js +352 -160
  75. package/dist.commonjs/client/cache/cache.d.ts +67 -11
  76. package/dist.commonjs/client/cache/cache.d.ts.map +1 -1
  77. package/dist.commonjs/client/cache/cache.js +94 -9
  78. package/dist.commonjs/client/cache/memory.advanced.d.ts +2 -2
  79. package/dist.commonjs/client/cache/memory.advanced.d.ts.map +1 -1
  80. package/dist.commonjs/client/cache/memory.advanced.js +19 -7
  81. package/dist.commonjs/client/cache/memory.d.ts +24 -7
  82. package/dist.commonjs/client/cache/memory.d.ts.map +1 -1
  83. package/dist.commonjs/client/cache/memory.js +75 -17
  84. package/dist.commonjs/client/client.d.ts +30 -7
  85. package/dist.commonjs/client/client.d.ts.map +1 -1
  86. package/dist.commonjs/client/client.js +112 -20
  87. package/dist.commonjs/client/clientPublicMainnet.advanced.d.ts +2 -1
  88. package/dist.commonjs/client/clientPublicMainnet.advanced.d.ts.map +1 -1
  89. package/dist.commonjs/client/clientPublicMainnet.advanced.js +21 -21
  90. package/dist.commonjs/client/clientPublicMainnet.d.ts +2 -1
  91. package/dist.commonjs/client/clientPublicMainnet.d.ts.map +1 -1
  92. package/dist.commonjs/client/clientPublicMainnet.js +1 -6
  93. package/dist.commonjs/client/clientPublicTestnet.advanced.d.ts +2 -1
  94. package/dist.commonjs/client/clientPublicTestnet.advanced.d.ts.map +1 -1
  95. package/dist.commonjs/client/clientPublicTestnet.advanced.js +21 -21
  96. package/dist.commonjs/client/clientPublicTestnet.d.ts +2 -1
  97. package/dist.commonjs/client/clientPublicTestnet.d.ts.map +1 -1
  98. package/dist.commonjs/client/clientTypes.advanced.d.ts +3 -0
  99. package/dist.commonjs/client/clientTypes.advanced.d.ts.map +1 -1
  100. package/dist.commonjs/client/clientTypes.advanced.js +4 -0
  101. package/dist.commonjs/client/clientTypes.d.ts +110 -38
  102. package/dist.commonjs/client/clientTypes.d.ts.map +1 -1
  103. package/dist.commonjs/client/clientTypes.js +123 -31
  104. package/dist.commonjs/client/index.d.ts +1 -0
  105. package/dist.commonjs/client/index.d.ts.map +1 -1
  106. package/dist.commonjs/client/index.js +1 -0
  107. package/dist.commonjs/client/jsonRpc/client.d.ts +4 -4
  108. package/dist.commonjs/client/jsonRpc/client.d.ts.map +1 -1
  109. package/dist.commonjs/client/jsonRpc/client.js +4 -4
  110. package/dist.commonjs/client/jsonRpc/transformers.js +2 -2
  111. package/dist.commonjs/client/knownScript.d.ts +26 -0
  112. package/dist.commonjs/client/knownScript.d.ts.map +1 -0
  113. package/dist.commonjs/client/knownScript.js +30 -0
  114. package/dist.commonjs/index.js +17 -7
  115. package/dist.commonjs/jsonRpc/transports/webSocket.d.ts.map +1 -1
  116. package/dist.commonjs/jsonRpc/transports/webSocket.js +7 -3
  117. package/dist.commonjs/molecule/index.js +17 -7
  118. package/dist.commonjs/num/index.d.ts.map +1 -1
  119. package/dist.commonjs/num/index.js +17 -1
  120. package/dist.commonjs/signer/ckb/signerCkbPublicKey.d.ts.map +1 -1
  121. package/dist.commonjs/signer/ckb/signerCkbPublicKey.js +1 -5
  122. package/dist.commonjs/signer/nostr/index.d.ts +1 -0
  123. package/dist.commonjs/signer/nostr/index.d.ts.map +1 -1
  124. package/dist.commonjs/signer/nostr/index.js +1 -0
  125. package/dist.commonjs/signer/nostr/signerNostr.d.ts +1 -1
  126. package/dist.commonjs/signer/nostr/signerNostr.d.ts.map +1 -1
  127. package/dist.commonjs/signer/nostr/signerNostr.js +8 -0
  128. package/dist.commonjs/signer/nostr/signerNostrPrivateKey.d.ts +5 -7
  129. package/dist.commonjs/signer/nostr/signerNostrPrivateKey.d.ts.map +1 -1
  130. package/dist.commonjs/signer/nostr/signerNostrPrivateKey.js +6 -12
  131. package/dist.commonjs/signer/nostr/signerNostrPublicKeyReadonly.d.ts +11 -0
  132. package/dist.commonjs/signer/nostr/signerNostrPublicKeyReadonly.d.ts.map +1 -0
  133. package/dist.commonjs/signer/nostr/signerNostrPublicKeyReadonly.js +26 -0
  134. package/dist.commonjs/utils/index.d.ts +4 -0
  135. package/dist.commonjs/utils/index.d.ts.map +1 -1
  136. package/dist.commonjs/utils/index.js +13 -0
  137. package/package.json +1 -1
  138. package/src/ckb/script.ts +2 -1
  139. package/src/ckb/transaction.ts +376 -97
  140. package/src/client/cache/cache.ts +126 -13
  141. package/src/client/cache/memory.advanced.ts +24 -7
  142. package/src/client/cache/memory.ts +130 -30
  143. package/src/client/client.ts +172 -28
  144. package/src/client/clientPublicMainnet.advanced.ts +2 -1
  145. package/src/client/clientPublicMainnet.ts +3 -7
  146. package/src/client/clientPublicTestnet.advanced.ts +2 -1
  147. package/src/client/clientPublicTestnet.ts +2 -1
  148. package/src/client/clientTypes.advanced.ts +4 -0
  149. package/src/client/clientTypes.ts +224 -61
  150. package/src/client/index.ts +1 -0
  151. package/src/client/jsonRpc/client.ts +11 -9
  152. package/src/client/jsonRpc/transformers.ts +2 -2
  153. package/src/client/knownScript.ts +27 -0
  154. package/src/jsonRpc/transports/webSocket.ts +17 -13
  155. package/src/num/index.ts +21 -1
  156. package/src/signer/ckb/signerCkbPublicKey.ts +3 -5
  157. package/src/signer/nostr/index.ts +1 -0
  158. package/src/signer/nostr/signerNostr.ts +3 -1
  159. package/src/signer/nostr/signerNostrPrivateKey.ts +7 -14
  160. package/src/signer/nostr/signerNostrPublicKeyReadonly.ts +29 -0
  161. package/src/utils/index.ts +14 -1
@@ -6,6 +6,8 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
6
6
  };
7
7
  var OutPoint_1, CellOutput_1, Since_1, CellInput_1, CellDep_1, WitnessArgs_1, Transaction_1;
8
8
  import { bytesFrom } from "../bytes/index.js";
9
+ import { ClientBlockHeader, } from "../client/index.js";
10
+ import { KnownScript } from "../client/knownScript.js";
9
11
  import { Zero, fixedPointFrom, fixedPointToString, } from "../fixedPoint/index.js";
10
12
  import { HasherCkb, hashCkb } from "../hasher/index.js";
11
13
  import { hexFrom } from "../hex/index.js";
@@ -198,7 +200,83 @@ export class Cell {
198
200
  if (cell instanceof Cell) {
199
201
  return cell;
200
202
  }
201
- return new Cell(OutPoint.from(cell.outPoint), CellOutput.from(cell.cellOutput), hexFrom(cell.outputData));
203
+ return new Cell(OutPoint.from("outPoint" in cell ? cell.outPoint : cell.previousOutput), CellOutput.from(cell.cellOutput), hexFrom(cell.outputData));
204
+ }
205
+ get capacityFree() {
206
+ const occupiedSize = fixedPointFrom(this.cellOutput.occupiedSize + bytesFrom(this.outputData).length);
207
+ return this.cellOutput.capacity - occupiedSize;
208
+ }
209
+ /**
210
+ * Occupied bytes of a cell on chain
211
+ * It's CellOutput.occupiedSize + bytesFrom(outputData).byteLength
212
+ */
213
+ get occupiedSize() {
214
+ return this.cellOutput.occupiedSize + bytesFrom(this.outputData).byteLength;
215
+ }
216
+ /**
217
+ * Gets confirmed Nervos DAO profit of a Cell
218
+ * It returns non-zero value only when the cell is in withdrawal phase 2
219
+ * See https://github.com/nervosnetwork/rfcs/blob/master/rfcs/0023-dao-deposit-withdraw/0023-dao-deposit-withdraw.md
220
+ *
221
+ * @param client - A client for searching DAO related headers
222
+ * @returns Profit
223
+ *
224
+ * @example
225
+ * ```typescript
226
+ * const profit = await cell.getDaoProfit(client);
227
+ * ```
228
+ */
229
+ async getDaoProfit(client) {
230
+ if (!(await this.isNervosDao(client, "withdrew"))) {
231
+ return Zero;
232
+ }
233
+ const { depositHeader, withdrawHeader } = await this.getNervosDaoInfo(client);
234
+ if (!withdrawHeader || !depositHeader) {
235
+ throw new Error(`Unable to get headers of a Nervos DAO cell ${this.outPoint.txHash}:${this.outPoint.index.toString()}`);
236
+ }
237
+ return calcDaoProfit(this.capacityFree, depositHeader, withdrawHeader);
238
+ }
239
+ async isNervosDao(client, phase) {
240
+ const { type } = this.cellOutput;
241
+ const daoType = await client.getKnownScript(KnownScript.NervosDao);
242
+ if (!type ||
243
+ type.codeHash !== daoType.codeHash ||
244
+ type.hashType !== daoType.hashType) {
245
+ // Non Nervos DAO cell
246
+ return false;
247
+ }
248
+ const hasWithdrew = numFrom(this.outputData) !== Zero;
249
+ return (!phase ||
250
+ (phase === "deposited" && !hasWithdrew) ||
251
+ (phase === "withdrew" && hasWithdrew));
252
+ }
253
+ async getNervosDaoInfo(client) {
254
+ if (!(await this.isNervosDao(client))) {
255
+ // Non Nervos DAO cell
256
+ return {};
257
+ }
258
+ if (numFrom(this.outputData) === Zero) {
259
+ // Deposited Nervos DAO cell
260
+ const depositRes = await client.getCellWithHeader(this.outPoint);
261
+ if (!depositRes?.header) {
262
+ throw new Error(`Unable to get header of a Nervos DAO deposited cell ${this.outPoint.txHash}:${this.outPoint.index.toString()}`);
263
+ }
264
+ return {
265
+ depositHeader: depositRes.header,
266
+ };
267
+ }
268
+ // Withdrew Nervos DAO cell
269
+ const [depositHeader, withdrawRes] = await Promise.all([
270
+ client.getHeaderByNumber(numFromBytes(this.outputData)),
271
+ client.getCellWithHeader(this.outPoint),
272
+ ]);
273
+ if (!withdrawRes?.header || !depositHeader) {
274
+ throw new Error(`Unable to get headers of a Nervos DAO withdrew cell ${this.outPoint.txHash}:${this.outPoint.index.toString()}`);
275
+ }
276
+ return {
277
+ depositHeader,
278
+ withdrawHeader: withdrawRes.header,
279
+ };
202
280
  }
203
281
  /**
204
282
  * Clone a Cell
@@ -369,16 +447,31 @@ let CellInput = CellInput_1 = class CellInput extends mol.Entity.Base() {
369
447
  if (cellInput instanceof CellInput_1) {
370
448
  return cellInput;
371
449
  }
372
- return new CellInput_1(OutPoint.from(cellInput.previousOutput), Since.from(cellInput.since ?? 0).toNum(), apply(CellOutput.from, cellInput.cellOutput), apply(hexFrom, cellInput.outputData));
450
+ return new CellInput_1(OutPoint.from("previousOutput" in cellInput
451
+ ? cellInput.previousOutput
452
+ : cellInput.outPoint), Since.from(cellInput.since ?? 0).toNum(), apply(CellOutput.from, cellInput.cellOutput), apply(hexFrom, cellInput.outputData));
453
+ }
454
+ async getCell(client) {
455
+ await this.completeExtraInfos(client);
456
+ if (!this.cellOutput || !this.outputData) {
457
+ throw new Error("Unable to complete input");
458
+ }
459
+ return Cell.from({
460
+ outPoint: this.previousOutput,
461
+ cellOutput: this.cellOutput,
462
+ outputData: this.outputData,
463
+ });
373
464
  }
374
465
  /**
375
- * Complete extra infos in the input. Like the output of the out point.
466
+ * Complete extra infos in the input. Including
467
+ * - Previous cell output
468
+ * - Previous cell data
376
469
  * The instance will be modified.
377
470
  *
378
471
  * @returns true if succeed.
379
472
  * @example
380
473
  * ```typescript
381
- * await cellInput.completeExtraInfos();
474
+ * await cellInput.completeExtraInfos(client);
382
475
  * ```
383
476
  */
384
477
  async completeExtraInfos(client) {
@@ -392,6 +485,20 @@ let CellInput = CellInput_1 = class CellInput extends mol.Entity.Base() {
392
485
  this.cellOutput = cell.cellOutput;
393
486
  this.outputData = cell.outputData;
394
487
  }
488
+ /**
489
+ * The extra capacity created when consume this input.
490
+ * This is usually NervosDAO interest, see https://github.com/nervosnetwork/rfcs/blob/master/rfcs/0023-dao-deposit-withdraw/0023-dao-deposit-withdraw.md.
491
+ * And it can also be miners' income. (But this is not implemented yet)
492
+ */
493
+ async getExtraCapacity(client) {
494
+ return (await this.getCell(client)).getDaoProfit(client);
495
+ }
496
+ clone() {
497
+ const cloned = super.clone();
498
+ cloned.cellOutput = this.cellOutput;
499
+ cloned.outputData = this.outputData;
500
+ return cloned;
501
+ }
395
502
  };
396
503
  CellInput = CellInput_1 = __decorate([
397
504
  mol.codec(mol
@@ -399,10 +506,7 @@ CellInput = CellInput_1 = __decorate([
399
506
  since: Since,
400
507
  previousOutput: OutPoint,
401
508
  })
402
- .mapIn((encodable) => ({
403
- ...encodable,
404
- since: encodable.since ?? 0,
405
- })))
509
+ .mapIn((encodable) => CellInput.from(encodable)))
406
510
  ], CellInput);
407
511
  export { CellInput };
408
512
  export const CellInputVec = mol.vector(CellInput);
@@ -511,11 +615,13 @@ WitnessArgs = WitnessArgs_1 = __decorate([
511
615
  ], WitnessArgs);
512
616
  export { WitnessArgs };
513
617
  /**
618
+ * Convert a bytes to a num.
619
+ *
514
620
  * @public
515
621
  */
516
622
  export function udtBalanceFrom(dataLike) {
517
623
  const data = bytesFrom(dataLike).slice(0, 16);
518
- return numFromBytes(data);
624
+ return data.length === 0 ? Zero : numFromBytes(data);
519
625
  }
520
626
  export const RawTransaction = mol.table({
521
627
  version: mol.Uint32,
@@ -655,6 +761,11 @@ let Transaction = Transaction_1 = class Transaction extends mol.Entity.Base() {
655
761
  witnesses: skeleton.witnesses.toArray(),
656
762
  });
657
763
  }
764
+ /**
765
+ * @deprecated
766
+ * Use ccc.stringify instead.
767
+ * stringify the tx to JSON string.
768
+ */
658
769
  stringify() {
659
770
  return JSON.stringify(this, (_, value) => {
660
771
  if (typeof value === "bigint") {
@@ -744,11 +855,8 @@ let Transaction = Transaction_1 = class Transaction extends mol.Entity.Base() {
744
855
  for (let i = 0; i < this.witnesses.length; i += 1) {
745
856
  const input = this.inputs[i];
746
857
  if (input) {
747
- await input.completeExtraInfos(client);
748
- if (!input.cellOutput) {
749
- throw new Error("Unable to complete input");
750
- }
751
- if (!script.eq(input.cellOutput.lock)) {
858
+ const { cellOutput } = await input.getCell(client);
859
+ if (!script.eq(cellOutput.lock)) {
752
860
  continue;
753
861
  }
754
862
  if (position === -1) {
@@ -783,13 +891,9 @@ let Transaction = Transaction_1 = class Transaction extends mol.Entity.Base() {
783
891
  async findInputIndexByLockId(scriptIdLike, client) {
784
892
  const script = Script.from({ ...scriptIdLike, args: "0x" });
785
893
  for (let i = 0; i < this.inputs.length; i += 1) {
786
- const input = this.inputs[i];
787
- await input.completeExtraInfos(client);
788
- if (!input.cellOutput) {
789
- throw new Error("Unable to complete input");
790
- }
791
- if (script.codeHash === input.cellOutput.lock.codeHash &&
792
- script.hashType === input.cellOutput.lock.hashType) {
894
+ const { cellOutput } = await this.inputs[i].getCell(client);
895
+ if (script.codeHash === cellOutput.lock.codeHash &&
896
+ script.hashType === cellOutput.lock.hashType) {
793
897
  return i;
794
898
  }
795
899
  }
@@ -809,12 +913,8 @@ let Transaction = Transaction_1 = class Transaction extends mol.Entity.Base() {
809
913
  async findInputIndexByLock(scriptLike, client) {
810
914
  const script = Script.from(scriptLike);
811
915
  for (let i = 0; i < this.inputs.length; i += 1) {
812
- const input = this.inputs[i];
813
- await input.completeExtraInfos(client);
814
- if (!input.cellOutput) {
815
- throw new Error("Unable to complete input");
816
- }
817
- if (script.eq(input.cellOutput.lock)) {
916
+ const { cellOutput } = await this.inputs[i].getCell(client);
917
+ if (script.eq(cellOutput.lock)) {
818
918
  return i;
819
919
  }
820
920
  }
@@ -834,12 +934,8 @@ let Transaction = Transaction_1 = class Transaction extends mol.Entity.Base() {
834
934
  async findLastInputIndexByLock(scriptLike, client) {
835
935
  const script = Script.from(scriptLike);
836
936
  for (let i = this.inputs.length - 1; i >= 0; i -= 1) {
837
- const input = this.inputs[i];
838
- await input.completeExtraInfos(client);
839
- if (!input.cellOutput) {
840
- throw new Error("Unable to complete input");
841
- }
842
- if (script.eq(input.cellOutput.lock)) {
937
+ const { cellOutput } = await this.inputs[i].getCell(client);
938
+ if (script.eq(cellOutput.lock)) {
843
939
  return i;
844
940
  }
845
941
  }
@@ -929,6 +1025,55 @@ let Transaction = Transaction_1 = class Transaction extends mol.Entity.Base() {
929
1025
  }
930
1026
  this.outputsData[index] = hexFrom(witness);
931
1027
  }
1028
+ /**
1029
+ * get input
1030
+ *
1031
+ * @param index - The cell input index
1032
+ *
1033
+ * @example
1034
+ * ```typescript
1035
+ * await tx.getInput(0);
1036
+ * ```
1037
+ */
1038
+ getInput(index) {
1039
+ return this.inputs[Number(numFrom(index))];
1040
+ }
1041
+ /**
1042
+ * add input
1043
+ *
1044
+ * @param inputLike - The cell input.
1045
+ *
1046
+ * @example
1047
+ * ```typescript
1048
+ * await tx.addInput({ });
1049
+ * ```
1050
+ */
1051
+ addInput(inputLike) {
1052
+ if (this.witnesses.length > this.inputs.length) {
1053
+ this.witnesses.splice(this.inputs.length, 0, "0x");
1054
+ }
1055
+ return this.inputs.push(CellInput.from(inputLike));
1056
+ }
1057
+ /**
1058
+ * get output
1059
+ *
1060
+ * @param index - The cell output index
1061
+ *
1062
+ * @example
1063
+ * ```typescript
1064
+ * await tx.getOutput(0);
1065
+ * ```
1066
+ */
1067
+ getOutput(index) {
1068
+ const i = Number(numFrom(index));
1069
+ if (i >= this.outputs.length) {
1070
+ return;
1071
+ }
1072
+ return {
1073
+ cellOutput: this.outputs[i],
1074
+ outputData: this.outputsData[i] ?? "0x",
1075
+ };
1076
+ }
932
1077
  /**
933
1078
  * Add output
934
1079
  *
@@ -948,8 +1093,9 @@ let Transaction = Transaction_1 = class Transaction extends mol.Entity.Base() {
948
1093
  if (output.capacity === Zero) {
949
1094
  output.capacity = fixedPointFrom(output.occupiedSize + bytesFrom(outputData).length);
950
1095
  }
951
- const i = this.outputs.push(output) - 1;
952
- this.setOutputDataAt(i, outputData);
1096
+ const len = this.outputs.push(output);
1097
+ this.setOutputDataAt(len - 1, outputData);
1098
+ return len;
953
1099
  }
954
1100
  /**
955
1101
  * Get witness at index as WitnessArgs
@@ -980,10 +1126,24 @@ let Transaction = Transaction_1 = class Transaction extends mol.Entity.Base() {
980
1126
  * ```
981
1127
  */
982
1128
  setWitnessArgsAt(index, witness) {
1129
+ this.setWitnessAt(index, witness.toBytes());
1130
+ }
1131
+ /**
1132
+ * Set witness at index
1133
+ *
1134
+ * @param index - The index of the witness.
1135
+ * @param witness - The witness to set.
1136
+ *
1137
+ * @example
1138
+ * ```typescript
1139
+ * await tx.setWitnessAt(0, witness);
1140
+ * ```
1141
+ */
1142
+ setWitnessAt(index, witness) {
983
1143
  if (this.witnesses.length < index) {
984
1144
  this.witnesses.push(...Array.from(new Array(index - this.witnesses.length), () => "0x"));
985
1145
  }
986
- this.witnesses[index] = hexFrom(witness.toBytes());
1146
+ this.witnesses[index] = hexFrom(witness);
987
1147
  }
988
1148
  /**
989
1149
  * Prepare dummy witness for sighash all method
@@ -1007,28 +1167,26 @@ let Transaction = Transaction_1 = class Transaction extends mol.Entity.Base() {
1007
1167
  witness.lock = hexFrom(Array.from(new Array(lockLen), () => 0));
1008
1168
  this.setWitnessArgsAt(position, witness);
1009
1169
  }
1170
+ async getInputsCapacityExtra(client) {
1171
+ return reduceAsync(this.inputs, async (acc, input) => acc + (await input.getExtraCapacity(client)), numFrom(0));
1172
+ }
1173
+ // This also includes extra amount
1010
1174
  async getInputsCapacity(client) {
1011
- return reduceAsync(this.inputs, async (acc, input) => {
1012
- await input.completeExtraInfos(client);
1013
- if (!input.cellOutput) {
1014
- throw new Error("Unable to complete input");
1015
- }
1016
- return acc + input.cellOutput.capacity;
1017
- }, numFrom(0));
1175
+ return ((await reduceAsync(this.inputs, async (acc, input) => {
1176
+ const { cellOutput: { capacity }, } = await input.getCell(client);
1177
+ return acc + capacity;
1178
+ }, numFrom(0))) + (await this.getInputsCapacityExtra(client)));
1018
1179
  }
1019
1180
  getOutputsCapacity() {
1020
1181
  return this.outputs.reduce((acc, { capacity }) => acc + capacity, numFrom(0));
1021
1182
  }
1022
1183
  async getInputsUdtBalance(client, type) {
1023
1184
  return reduceAsync(this.inputs, async (acc, input) => {
1024
- await input.completeExtraInfos(client);
1025
- if (!input.cellOutput || !input.outputData) {
1026
- throw new Error("Unable to complete input");
1027
- }
1028
- if (!input.cellOutput.type?.eq(type)) {
1185
+ const { cellOutput, outputData } = await input.getCell(client);
1186
+ if (!cellOutput.type?.eq(type)) {
1029
1187
  return;
1030
1188
  }
1031
- return acc + udtBalanceFrom(input.outputData);
1189
+ return acc + udtBalanceFrom(outputData);
1032
1190
  }, numFrom(0));
1033
1191
  }
1034
1192
  getOutputsUdtBalance(type) {
@@ -1055,11 +1213,7 @@ let Transaction = Transaction_1 = class Transaction extends mol.Entity.Base() {
1055
1213
  }
1056
1214
  acc = next;
1057
1215
  }
1058
- this.inputs.push(...collectedCells.map(({ outPoint, outputData, cellOutput }) => CellInput.from({
1059
- previousOutput: outPoint,
1060
- outputData,
1061
- cellOutput,
1062
- })));
1216
+ collectedCells.forEach((cell) => this.addInput(cell));
1063
1217
  if (fulfilled) {
1064
1218
  return {
1065
1219
  addedCount: collectedCells.length,
@@ -1115,19 +1269,12 @@ let Transaction = Transaction_1 = class Transaction extends mol.Entity.Base() {
1115
1269
  throw new Error(`Insufficient coin, need ${exceptedBalance - accumulated} extra coin`);
1116
1270
  }
1117
1271
  async completeInputsAddOne(from, filter) {
1118
- for await (const cell of from.findCells(filter ?? {
1272
+ const { addedCount, accumulated } = await this.completeInputs(from, filter ?? {
1119
1273
  scriptLenRange: [0, 1],
1120
1274
  outputDataLenRange: [0, 1],
1121
- }, true, undefined, 1)) {
1122
- if (this.inputs.some(({ previousOutput }) => previousOutput.eq(cell.outPoint))) {
1123
- continue;
1124
- }
1125
- this.inputs.push(CellInput.from({
1126
- previousOutput: cell.outPoint,
1127
- outputData: cell.outputData,
1128
- cellOutput: cell.cellOutput,
1129
- }));
1130
- return 1;
1275
+ }, () => undefined, true);
1276
+ if (accumulated === undefined) {
1277
+ return addedCount;
1131
1278
  }
1132
1279
  throw new Error(`Insufficient CKB, need at least one new cell`);
1133
1280
  }
@@ -1137,12 +1284,21 @@ let Transaction = Transaction_1 = class Transaction extends mol.Entity.Base() {
1137
1284
  }
1138
1285
  return this.completeInputsAddOne(from, filter);
1139
1286
  }
1287
+ async getFee(client) {
1288
+ return (await this.getInputsCapacity(client)) - this.getOutputsCapacity();
1289
+ }
1290
+ async getFeeRate(client) {
1291
+ return (((await this.getFee(client)) * numFrom(1000)) /
1292
+ numFrom(this.toBytes().length + 4));
1293
+ }
1140
1294
  estimateFee(feeRate) {
1141
1295
  const txSize = this.toBytes().length + 4;
1142
- return (numFrom(txSize) * numFrom(feeRate) + numFrom(1000)) / numFrom(1000);
1296
+ // + 999 then / 1000 to ceil the calculated fee
1297
+ return (numFrom(txSize) * numFrom(feeRate) + numFrom(999)) / numFrom(1000);
1143
1298
  }
1144
- async completeFee(from, change, expectedFeeRate, filter) {
1145
- const feeRate = expectedFeeRate ?? (await from.client.getFeeRate());
1299
+ async completeFee(from, change, expectedFeeRate, filter, options) {
1300
+ const feeRate = expectedFeeRate ??
1301
+ (await from.client.getFeeRate(options?.feeRateBlockRange, options));
1146
1302
  // Complete all inputs extra infos for cache
1147
1303
  await this.getInputsCapacity(from.client);
1148
1304
  let leastFee = Zero;
@@ -1165,20 +1321,19 @@ let Transaction = Transaction_1 = class Transaction extends mol.Entity.Base() {
1165
1321
  // The initial fee is calculated based on prepared transaction
1166
1322
  leastFee = tx.estimateFee(feeRate);
1167
1323
  }
1168
- const extraCapacity = (await tx.getInputsCapacity(from.client)) - tx.getOutputsCapacity();
1324
+ const fee = await tx.getFee(from.client);
1169
1325
  // The extra capacity paid the fee without a change
1170
- if (extraCapacity === leastFee) {
1326
+ if (fee === leastFee) {
1171
1327
  this.copy(tx);
1172
1328
  return [collected, false];
1173
1329
  }
1174
- const needed = numFrom(await Promise.resolve(change(tx, extraCapacity - leastFee)));
1330
+ const needed = numFrom(await Promise.resolve(change(tx, fee - leastFee)));
1175
1331
  // No enough extra capacity to create new cells for change
1176
1332
  if (needed > Zero) {
1177
1333
  leastExtraCapacity = needed;
1178
1334
  continue;
1179
1335
  }
1180
- if ((await tx.getInputsCapacity(from.client)) - tx.getOutputsCapacity() !==
1181
- leastFee) {
1336
+ if ((await tx.getFee(from.client)) !== leastFee) {
1182
1337
  throw new Error("The change function doesn't use all available capacity");
1183
1338
  }
1184
1339
  // New change cells created, update the fee
@@ -1240,3 +1395,38 @@ Transaction = Transaction_1 = __decorate([
1240
1395
  .mapOut((tx) => Transaction.from({ ...tx.raw, witnesses: tx.witnesses })))
1241
1396
  ], Transaction);
1242
1397
  export { Transaction };
1398
+ /**
1399
+ * Calculate Nervos DAO profit between two blocks
1400
+ */
1401
+ export function calcDaoProfit(profitableCapacity, depositHeaderLike, withdrawHeaderLike) {
1402
+ const depositHeader = ClientBlockHeader.from(depositHeaderLike);
1403
+ const withdrawHeader = ClientBlockHeader.from(withdrawHeaderLike);
1404
+ const profitableSize = numFrom(profitableCapacity);
1405
+ return ((profitableSize * withdrawHeader.dao.ar) / depositHeader.dao.ar -
1406
+ profitableSize);
1407
+ }
1408
+ /**
1409
+ * Calculate claimable epoch for Nervos DAO withdrawal
1410
+ * See https://github.com/nervosnetwork/rfcs/blob/master/rfcs/0023-dao-deposit-withdraw/0023-dao-deposit-withdraw.md
1411
+ */
1412
+ export function calcDaoClaimEpoch(depositHeader, withdrawHeader) {
1413
+ const depositEpoch = ClientBlockHeader.from(depositHeader).epoch;
1414
+ const withdrawEpoch = ClientBlockHeader.from(withdrawHeader).epoch;
1415
+ const intDiff = withdrawEpoch[0] - depositEpoch[0];
1416
+ // deposit[1] withdraw[1]
1417
+ // ---------- <= -----------
1418
+ // deposit[2] withdraw[2]
1419
+ if (intDiff % numFrom(180) !== numFrom(0) ||
1420
+ depositEpoch[1] * withdrawEpoch[2] <= depositEpoch[2] * withdrawEpoch[1]) {
1421
+ return [
1422
+ depositEpoch[0] + (intDiff / numFrom(180) + numFrom(1)) * numFrom(180),
1423
+ depositEpoch[1],
1424
+ depositEpoch[2],
1425
+ ];
1426
+ }
1427
+ return [
1428
+ depositEpoch[0] + (intDiff / numFrom(180)) * numFrom(180),
1429
+ depositEpoch[1],
1430
+ depositEpoch[2],
1431
+ ];
1432
+ }
@@ -1,35 +1,91 @@
1
1
  import { Cell, CellLike, OutPointLike, Transaction, TransactionLike } from "../../ckb/index.js";
2
2
  import { HexLike } from "../../hex/index.js";
3
+ import { NumLike } from "../../num/index.js";
3
4
  import { ClientCollectableSearchKeyLike } from "../clientTypes.advanced.js";
5
+ import { ClientBlock, ClientBlockHeader, ClientBlockHeaderLike, ClientBlockLike, ClientTransactionResponse, ClientTransactionResponseLike } from "../clientTypes.js";
6
+ /**
7
+ * @public
8
+ * The ClientCache class is mainly designed for chained transactions.
9
+ * Consumed & Created cells are "marked" so they can be correctly handled when composing transactions.
10
+ * It also act as cache for rpc requests to reduce cost, but this is optional.
11
+ */
4
12
  export declare abstract class ClientCache {
5
- abstract markUsable(...cellLikes: (CellLike | CellLike[])[]): Promise<void>;
13
+ abstract markUsableNoCache(...cellLikes: (CellLike | CellLike[])[]): Promise<void>;
14
+ markUsable(...cellLikes: (CellLike | CellLike[])[]): Promise<void>;
6
15
  abstract markUnusable(...outPointLike: (OutPointLike | OutPointLike[])[]): Promise<void>;
7
16
  markTransactions(...transactionLike: (TransactionLike | TransactionLike[])[]): Promise<void>;
8
17
  abstract clear(): Promise<void>;
9
18
  abstract findCells(filter: ClientCollectableSearchKeyLike): AsyncGenerator<Cell>;
19
+ abstract isUnusable(outPointLike: OutPointLike): Promise<boolean>;
20
+ /**
21
+ * Record known cells
22
+ * Implement this method to enable cells query caching
23
+ * @param _cells
24
+ */
25
+ recordCells(..._cells: (CellLike | CellLike[])[]): Promise<void>;
10
26
  /**
11
27
  * Get a known cell by out point
28
+ * Implement this method to enable cells query caching
12
29
  * @param _outPoint
13
30
  */
14
- abstract getCell(_outPoint: OutPointLike): Promise<Cell | undefined>;
15
- abstract isUnusable(outPointLike: OutPointLike): Promise<boolean>;
31
+ getCell(_outPoint: OutPointLike): Promise<Cell | undefined>;
16
32
  /**
17
- * Record known transactions
33
+ * Record known transaction responses.
18
34
  * Implement this method to enable transactions query caching
19
35
  * @param _transactions
20
36
  */
21
- recordTransactions(..._transactions: (TransactionLike | TransactionLike[])[]): Promise<void>;
37
+ recordTransactionResponses(..._transactions: (ClientTransactionResponseLike | ClientTransactionResponseLike[])[]): Promise<void>;
22
38
  /**
23
- * Get a known transaction by hash
39
+ * Get a known transaction response by hash
24
40
  * Implement this method to enable transactions query caching
25
41
  * @param _txHash
26
42
  */
27
- getTransaction(_txHash: HexLike): Promise<Transaction | undefined>;
43
+ getTransactionResponse(_txHash: HexLike): Promise<ClientTransactionResponse | undefined>;
28
44
  /**
29
- * Record known cells
30
- * Implement this method to enable cells query caching
31
- * @param _cells
45
+ * Record known transactions.
46
+ * @param transactions
32
47
  */
33
- recordCells(..._cells: (CellLike | CellLike[])[]): Promise<void>;
48
+ recordTransactions(...transactions: (TransactionLike | TransactionLike[])[]): Promise<void>;
49
+ /**
50
+ * Get a known transaction by hash
51
+ * @param txHash
52
+ */
53
+ getTransaction(txHash: HexLike): Promise<Transaction | undefined>;
54
+ /**
55
+ * Record known block headers.
56
+ * Implement this method to enable block headers query caching
57
+ * @param _headers
58
+ */
59
+ recordHeaders(..._headers: (ClientBlockHeaderLike | ClientBlockHeaderLike[])[]): Promise<void>;
60
+ /**
61
+ * Get a known block header by hash
62
+ * Implement this method to enable block headers query caching
63
+ * @param _hash
64
+ */
65
+ getHeaderByHash(_hash: HexLike): Promise<ClientBlockHeader | undefined>;
66
+ /**
67
+ * Get a known block header by number
68
+ * Implement this method to enable block headers query caching
69
+ * @param _number
70
+ */
71
+ getHeaderByNumber(_number: NumLike): Promise<ClientBlockHeader | undefined>;
72
+ /**
73
+ * Record known blocks.
74
+ * Implement this method to enable blocks query caching
75
+ * @param _blocks
76
+ */
77
+ recordBlocks(..._blocks: (ClientBlockLike | ClientBlockLike[])[]): Promise<void>;
78
+ /**
79
+ * Get a known block header by hash
80
+ * Implement this method to enable block headers query caching
81
+ * @param _hash
82
+ */
83
+ getBlockByHash(_hash: HexLike): Promise<ClientBlock | undefined>;
84
+ /**
85
+ * Get a known block header by number
86
+ * Implement this method to enable block headers query caching
87
+ * @param _number
88
+ */
89
+ getBlockByNumber(_number: NumLike): Promise<ClientBlock | undefined>;
34
90
  }
35
91
  //# sourceMappingURL=cache.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"cache.d.ts","sourceRoot":"","sources":["../../../src/client/cache/cache.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,IAAI,EACJ,QAAQ,EACR,YAAY,EACZ,WAAW,EACX,eAAe,EAChB,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EAAE,OAAO,EAAE,MAAM,oBAAoB,CAAC;AAC7C,OAAO,EAAE,8BAA8B,EAAE,MAAM,4BAA4B,CAAC;AAE5E,8BAAsB,WAAW;IAC/B,QAAQ,CAAC,UAAU,CAAC,GAAG,SAAS,EAAE,CAAC,QAAQ,GAAG,QAAQ,EAAE,CAAC,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC;IAC3E,QAAQ,CAAC,YAAY,CACnB,GAAG,YAAY,EAAE,CAAC,YAAY,GAAG,YAAY,EAAE,CAAC,EAAE,GACjD,OAAO,CAAC,IAAI,CAAC;IACV,gBAAgB,CACpB,GAAG,eAAe,EAAE,CAAC,eAAe,GAAG,eAAe,EAAE,CAAC,EAAE,GAC1D,OAAO,CAAC,IAAI,CAAC;IAuBhB,QAAQ,CAAC,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAC/B,QAAQ,CAAC,SAAS,CAChB,MAAM,EAAE,8BAA8B,GACrC,cAAc,CAAC,IAAI,CAAC;IACvB;;;OAGG;IACH,QAAQ,CAAC,OAAO,CAAC,SAAS,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,GAAG,SAAS,CAAC;IACpE,QAAQ,CAAC,UAAU,CAAC,YAAY,EAAE,YAAY,GAAG,OAAO,CAAC,OAAO,CAAC;IAEjE;;;;OAIG;IACG,kBAAkB,CACtB,GAAG,aAAa,EAAE,CAAC,eAAe,GAAG,eAAe,EAAE,CAAC,EAAE,GACxD,OAAO,CAAC,IAAI,CAAC;IAChB;;;;OAIG;IACG,cAAc,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,WAAW,GAAG,SAAS,CAAC;IAIxE;;;;OAIG;IACG,WAAW,CAAC,GAAG,MAAM,EAAE,CAAC,QAAQ,GAAG,QAAQ,EAAE,CAAC,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC;CACvE"}
1
+ {"version":3,"file":"cache.d.ts","sourceRoot":"","sources":["../../../src/client/cache/cache.ts"],"names":[],"mappings":"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"}