@ckb-ccc/core 1.8.1 → 1.9.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (67) hide show
  1. package/CHANGELOG.md +34 -0
  2. package/dist/bytes/index.d.ts +4 -0
  3. package/dist/bytes/index.d.ts.map +1 -1
  4. package/dist/bytes/index.js +4 -0
  5. package/dist/ckb/transaction.d.ts +11 -0
  6. package/dist/ckb/transaction.d.ts.map +1 -1
  7. package/dist/ckb/transaction.js +35 -11
  8. package/dist/client/clientPublicMainnet.advanced.d.ts.map +1 -1
  9. package/dist/client/clientPublicMainnet.advanced.js +15 -0
  10. package/dist/client/clientPublicTestnet.advanced.d.ts.map +1 -1
  11. package/dist/client/clientPublicTestnet.advanced.js +16 -1
  12. package/dist/client/clientTypes.js +1 -1
  13. package/dist/client/knownScript.d.ts +1 -0
  14. package/dist/client/knownScript.d.ts.map +1 -1
  15. package/dist/client/knownScript.js +1 -0
  16. package/dist/molecule/codec.d.ts +9 -3
  17. package/dist/molecule/codec.d.ts.map +1 -1
  18. package/dist/molecule/codec.js +37 -22
  19. package/dist/molecule/entity.d.ts +1 -8
  20. package/dist/molecule/entity.d.ts.map +1 -1
  21. package/dist/molecule/entity.js +11 -14
  22. package/dist/signer/nostr/signerNostrPrivateKey.d.ts +4 -0
  23. package/dist/signer/nostr/signerNostrPrivateKey.d.ts.map +1 -1
  24. package/dist/signer/nostr/signerNostrPrivateKey.js +13 -1
  25. package/dist/signer/nostr/signerNostrPublicKeyReadonly.d.ts +4 -0
  26. package/dist/signer/nostr/signerNostrPublicKeyReadonly.d.ts.map +1 -1
  27. package/dist/signer/nostr/signerNostrPublicKeyReadonly.js +4 -0
  28. package/dist.commonjs/bytes/index.d.ts +4 -0
  29. package/dist.commonjs/bytes/index.d.ts.map +1 -1
  30. package/dist.commonjs/bytes/index.js +5 -0
  31. package/dist.commonjs/ckb/transaction.d.ts +11 -0
  32. package/dist.commonjs/ckb/transaction.d.ts.map +1 -1
  33. package/dist.commonjs/ckb/transaction.js +35 -11
  34. package/dist.commonjs/client/clientPublicMainnet.advanced.d.ts.map +1 -1
  35. package/dist.commonjs/client/clientPublicMainnet.advanced.js +15 -0
  36. package/dist.commonjs/client/clientPublicTestnet.advanced.d.ts.map +1 -1
  37. package/dist.commonjs/client/clientPublicTestnet.advanced.js +16 -1
  38. package/dist.commonjs/client/clientTypes.js +1 -1
  39. package/dist.commonjs/client/knownScript.d.ts +1 -0
  40. package/dist.commonjs/client/knownScript.d.ts.map +1 -1
  41. package/dist.commonjs/client/knownScript.js +1 -0
  42. package/dist.commonjs/molecule/codec.d.ts +9 -3
  43. package/dist.commonjs/molecule/codec.d.ts.map +1 -1
  44. package/dist.commonjs/molecule/codec.js +37 -22
  45. package/dist.commonjs/molecule/entity.d.ts +1 -8
  46. package/dist.commonjs/molecule/entity.d.ts.map +1 -1
  47. package/dist.commonjs/molecule/entity.js +11 -14
  48. package/dist.commonjs/signer/nostr/signerNostrPrivateKey.d.ts +4 -0
  49. package/dist.commonjs/signer/nostr/signerNostrPrivateKey.d.ts.map +1 -1
  50. package/dist.commonjs/signer/nostr/signerNostrPrivateKey.js +13 -1
  51. package/dist.commonjs/signer/nostr/signerNostrPublicKeyReadonly.d.ts +4 -0
  52. package/dist.commonjs/signer/nostr/signerNostrPublicKeyReadonly.d.ts.map +1 -1
  53. package/dist.commonjs/signer/nostr/signerNostrPublicKeyReadonly.js +4 -0
  54. package/package.json +9 -10
  55. package/prettier.config.mjs +13 -0
  56. package/src/bytes/index.ts +4 -0
  57. package/src/ckb/transaction.ts +44 -11
  58. package/src/client/clientPublicMainnet.advanced.ts +17 -0
  59. package/src/client/clientPublicTestnet.advanced.ts +18 -1
  60. package/src/client/clientTypes.ts +1 -1
  61. package/src/client/knownScript.ts +1 -0
  62. package/src/molecule/codec.ts +56 -24
  63. package/src/molecule/entity.ts +11 -12
  64. package/src/signer/nostr/signerNostrPrivateKey.ts +17 -1
  65. package/src/signer/nostr/signerNostrPublicKeyReadonly.ts +4 -0
  66. package/vitest.config.ts +10 -0
  67. package/jest.config.js +0 -5
@@ -1 +1 @@
1
- {"version":3,"file":"entity.d.ts","sourceRoot":"","sources":["../../src/molecule/entity.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAW,SAAS,EAAE,MAAM,mBAAmB,CAAC;AAE9D,OAAO,EAAE,GAAG,EAAE,MAAM,iBAAiB,CAAC;AACtC,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAChD,OAAO,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AAEnC;;;GAGG;AACH,8BAAsB,MAAM;IAC1B;;;;OAIG;IACH,MAAM,CAAC,IAAI,CAAC,WAAW,EAAE,OAAO,GAAG,WAAW;QA6D1C;;;;WAIG;mBACQ,KAAK;QAMhB;;;;WAIG;iBACM,OAAO;QAMhB;;;;;WAKG;kBACO,WAAW,GAAG,OAAO;QAe/B;;;;WAIG;gBACK,GAAG;;QA3GX;;;;WAIG;qBACiB,MAAM;QAC1B;;;;;;;WAOG;kBACc,WAAW,GAAG,KAAK;QAKpC;;;;;;;WAOG;kBACc,SAAS,GAAG,OAAO;QAMpC;;;;;;;WAOG;0BACsB,SAAS,GAAG,OAAO;QAM5C;;;;;;;WAOG;gBACY,WAAW,GAAG,OAAO;;IA4DxC,QAAQ,CAAC,OAAO,IAAI,KAAK;IACzB,QAAQ,CAAC,IAAI,IAAI,GAAG;IACpB,QAAQ,CAAC,KAAK,IAAI,MAAM;CACzB;AAED;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,KAAK,CACnB,SAAS,EACT,QAAQ,SAAS,SAAS,EAC1B,OAAO,SAAS,QAAQ,EACxB,IAAI,SAAS,MAAM,GAAG,QAAQ,EAC9B,eAAe,SAAS,WAAW,CAAC,IAAI,CAAC,GAAG;IAC1C,IAAI,CAAC,OAAO,EAAE,QAAQ,GAAG,IAAI,CAAC;IAC9B,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,MAAM,CAAC,SAAS,EAAE,QAAQ,GAAG,KAAK,CAAC;IACnC,MAAM,CAAC,SAAS,EAAE,SAAS,GAAG,QAAQ,CAAC;IACvC,SAAS,CAAC,KAAK,EAAE,SAAS,GAAG,IAAI,CAAC;CACnC,EACD,KAAK,EAAE,KAAK,CAAC,SAAS,EAAE,OAAO,CAAC,iBACF,eAAe;;;sBAGhB,QAAQ,GAAG,KAAK;sBAGhB,SAAS,GAAG,IAAI;qBAIjB,SAAS,GAAG,IAAI;kBAjB5B,QAAQ,GAAG,IAAI;oBAsBhC"}
1
+ {"version":3,"file":"entity.d.ts","sourceRoot":"","sources":["../../src/molecule/entity.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAW,SAAS,EAAE,MAAM,mBAAmB,CAAC;AAE9D,OAAO,EAAE,GAAG,EAAE,MAAM,iBAAiB,CAAC;AACtC,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAChD,OAAO,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AAEnC;;;GAGG;AACH,8BAAsB,MAAM;IAC1B;;;;OAIG;IACH,MAAM,CAAC,IAAI,CAAC,WAAW,EAAE,OAAO,GAAG,WAAW;QA6D1C;;;;WAIG;mBACQ,KAAK;QAMhB;;;;WAIG;iBACM,OAAO;QAMhB;;;;;WAKG;kBACO,WAAW,GAAG,OAAO;QAe/B;;;;WAIG;gBACK,GAAG;;QA3GX;;;;WAIG;qBACiB,MAAM;QAC1B;;;;;;;WAOG;kBACc,WAAW,GAAG,KAAK;QAKpC;;;;;;;WAOG;kBACc,SAAS,GAAG,OAAO;QAMpC;;;;;;;WAOG;0BACsB,SAAS,GAAG,OAAO;QAM5C;;;;;;;WAOG;gBACY,WAAW,GAAG,OAAO;;IA4DxC,QAAQ,CAAC,OAAO,IAAI,KAAK;IACzB,QAAQ,CAAC,IAAI,IAAI,GAAG;IACpB,QAAQ,CAAC,KAAK,IAAI,MAAM;CACzB;AAED;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,KAAK,CACnB,SAAS,EACT,QAAQ,SAAS,SAAS,EAC1B,OAAO,SAAS,QAAQ,EACxB,IAAI,SAAS,MAAM,GAAG,QAAQ,EAC9B,eAAe,SAAS,WAAW,CAAC,IAAI,CAAC,GAAG;IAC1C,IAAI,CAAC,OAAO,EAAE,QAAQ,GAAG,IAAI,CAAC;IAC9B,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,MAAM,CAAC,SAAS,EAAE,QAAQ,GAAG,KAAK,CAAC;IACnC,MAAM,CAAC,SAAS,EAAE,SAAS,GAAG,QAAQ,CAAC;IACvC,SAAS,CAAC,KAAK,EAAE,SAAS,GAAG,IAAI,CAAC;CACnC,EACD,KAAK,EAAE,KAAK,CAAC,SAAS,EAAE,OAAO,CAAC,iBACF,eAAe,qBAc9C"}
@@ -121,19 +121,16 @@ exports.Entity = Entity;
121
121
  */
122
122
  function codec(codec) {
123
123
  return function (Constructor) {
124
- var _a;
125
- return _a = class Extended extends Constructor {
126
- static encode(encodable) {
127
- return codec.encode(encodable);
128
- }
129
- static decode(bytesLike) {
130
- return Constructor.from(codec.decode(bytesLike));
131
- }
132
- static fromBytes(bytes) {
133
- return Constructor.from(codec.decode(bytes));
134
- }
135
- },
136
- _a.byteLength = codec.byteLength,
137
- _a;
124
+ Constructor.byteLength = codec.byteLength;
125
+ Constructor.encode = function (encodable) {
126
+ return codec.encode(encodable);
127
+ };
128
+ Constructor.decode = function (bytesLike) {
129
+ return Constructor.from(codec.decode(bytesLike));
130
+ };
131
+ Constructor.fromBytes = function (bytes) {
132
+ return Constructor.from(codec.decode(bytes));
133
+ };
134
+ return Constructor;
138
135
  };
139
136
  }
@@ -2,6 +2,10 @@ import { Client } from "../../client/index.js";
2
2
  import { HexLike } from "../../hex/index.js";
3
3
  import { NostrEvent } from "./signerNostr.js";
4
4
  import { SignerNostrPublicKeyReadonly } from "./signerNostrPublicKeyReadonly.js";
5
+ /**
6
+ * Signer from Nostr private key
7
+ * Support nsec and hex format
8
+ */
5
9
  export declare class SignerNostrPrivateKey extends SignerNostrPublicKeyReadonly {
6
10
  private readonly privateKey;
7
11
  constructor(client: Client, privateKeyLike: HexLike);
@@ -1 +1 @@
1
- {"version":3,"file":"signerNostrPrivateKey.d.ts","sourceRoot":"","sources":["../../../src/signer/nostr/signerNostrPrivateKey.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,MAAM,EAAE,MAAM,uBAAuB,CAAC;AAC/C,OAAO,EAAgB,OAAO,EAAE,MAAM,oBAAoB,CAAC;AAC3D,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAC9C,OAAO,EAAE,4BAA4B,EAAE,MAAM,mCAAmC,CAAC;AAGjF,qBAAa,qBAAsB,SAAQ,4BAA4B;IACrE,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAM;gBAErB,MAAM,EAAE,MAAM,EAAE,cAAc,EAAE,OAAO;IAO7C,cAAc,CAAC,KAAK,EAAE,UAAU,GAAG,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAC,CAAC;CAYvE"}
1
+ {"version":3,"file":"signerNostrPrivateKey.d.ts","sourceRoot":"","sources":["../../../src/signer/nostr/signerNostrPrivateKey.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,MAAM,EAAE,MAAM,uBAAuB,CAAC;AAC/C,OAAO,EAAgB,OAAO,EAAE,MAAM,oBAAoB,CAAC;AAC3D,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAC9C,OAAO,EAAE,4BAA4B,EAAE,MAAM,mCAAmC,CAAC;AAGjF;;;GAGG;AACH,qBAAa,qBAAsB,SAAQ,4BAA4B;IACrE,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAM;gBAErB,MAAM,EAAE,MAAM,EAAE,cAAc,EAAE,OAAO;IAkB7C,cAAc,CAAC,KAAK,EAAE,UAAU,GAAG,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAC,CAAC;CAYvE"}
@@ -2,12 +2,24 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.SignerNostrPrivateKey = void 0;
4
4
  const secp256k1_1 = require("@noble/curves/secp256k1");
5
+ const bech32_1 = require("bech32");
5
6
  const index_js_1 = require("../../hex/index.js");
6
7
  const signerNostrPublicKeyReadonly_js_1 = require("./signerNostrPublicKeyReadonly.js");
7
8
  const verify_js_1 = require("./verify.js");
9
+ /**
10
+ * Signer from Nostr private key
11
+ * Support nsec and hex format
12
+ */
8
13
  class SignerNostrPrivateKey extends signerNostrPublicKeyReadonly_js_1.SignerNostrPublicKeyReadonly {
9
14
  constructor(client, privateKeyLike) {
10
- const privateKey = (0, index_js_1.hexFrom)(privateKeyLike);
15
+ const privateKey = (() => {
16
+ if (typeof privateKeyLike === "string" &&
17
+ privateKeyLike.startsWith("nsec")) {
18
+ const { words } = bech32_1.bech32.decode(privateKeyLike);
19
+ return (0, index_js_1.hexFrom)(bech32_1.bech32.fromWords(words));
20
+ }
21
+ return (0, index_js_1.hexFrom)(privateKeyLike);
22
+ })();
11
23
  super(client, secp256k1_1.schnorr.getPublicKey(privateKey.slice(2)));
12
24
  this.privateKey = privateKey;
13
25
  }
@@ -1,6 +1,10 @@
1
1
  import { Client } from "../../client/index.js";
2
2
  import { Hex, HexLike } from "../../hex/index.js";
3
3
  import { SignerNostr } from "./signerNostr.js";
4
+ /**
5
+ * Signer from Nostr public key
6
+ * Support npub and hex format
7
+ */
4
8
  export declare class SignerNostrPublicKeyReadonly extends SignerNostr {
5
9
  readonly publicKey: Hex;
6
10
  constructor(client: Client, publicKey: HexLike);
@@ -1 +1 @@
1
- {"version":3,"file":"signerNostrPublicKeyReadonly.d.ts","sourceRoot":"","sources":["../../../src/signer/nostr/signerNostrPublicKeyReadonly.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,MAAM,EAAE,MAAM,uBAAuB,CAAC;AAC/C,OAAO,EAAE,GAAG,EAAW,OAAO,EAAE,MAAM,oBAAoB,CAAC;AAC3D,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAE/C,qBAAa,4BAA6B,SAAQ,WAAW;IAC3D,SAAgB,SAAS,EAAE,GAAG,CAAC;gBAEnB,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,OAAO;IAWxC,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;IAExB,WAAW,IAAI,OAAO,CAAC,OAAO,CAAC;IAI/B,iBAAiB,IAAI,OAAO,CAAC,GAAG,CAAC;CAGxC"}
1
+ {"version":3,"file":"signerNostrPublicKeyReadonly.d.ts","sourceRoot":"","sources":["../../../src/signer/nostr/signerNostrPublicKeyReadonly.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,MAAM,EAAE,MAAM,uBAAuB,CAAC;AAC/C,OAAO,EAAE,GAAG,EAAW,OAAO,EAAE,MAAM,oBAAoB,CAAC;AAC3D,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAE/C;;;GAGG;AACH,qBAAa,4BAA6B,SAAQ,WAAW;IAC3D,SAAgB,SAAS,EAAE,GAAG,CAAC;gBAEnB,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,OAAO;IAWxC,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;IAExB,WAAW,IAAI,OAAO,CAAC,OAAO,CAAC;IAI/B,iBAAiB,IAAI,OAAO,CAAC,GAAG,CAAC;CAGxC"}
@@ -4,6 +4,10 @@ exports.SignerNostrPublicKeyReadonly = void 0;
4
4
  const bech32_1 = require("bech32");
5
5
  const index_js_1 = require("../../hex/index.js");
6
6
  const signerNostr_js_1 = require("./signerNostr.js");
7
+ /**
8
+ * Signer from Nostr public key
9
+ * Support npub and hex format
10
+ */
7
11
  class SignerNostrPublicKeyReadonly extends signerNostr_js_1.SignerNostr {
8
12
  constructor(client, publicKey) {
9
13
  super(client);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ckb-ccc/core",
3
- "version": "1.8.1",
3
+ "version": "1.9.1",
4
4
  "description": "Core of CCC - CKBer's Codebase",
5
5
  "author": "Hanssen0 <hanssen0@hanssen0.com>",
6
6
  "license": "MIT",
@@ -38,20 +38,18 @@
38
38
  "devDependencies": {
39
39
  "@eslint/js": "^9.1.1",
40
40
  "@types/blake2b": "^2.1.3",
41
- "@types/jest": "^29.5.12",
42
41
  "@types/ws": "^8.5.12",
43
42
  "copyfiles": "^2.4.1",
44
43
  "eslint": "^9.1.0",
45
- "eslint-config-prettier": "^9.1.0",
46
- "eslint-plugin-prettier": "^5.1.3",
47
- "jest": "^29.7.0",
48
- "prettier": "^3.2.5",
49
- "prettier-plugin-organize-imports": "^3.2.4",
44
+ "eslint-config-prettier": "^10.1.5",
45
+ "eslint-plugin-prettier": "^5.4.1",
46
+ "prettier": "^3.5.3",
47
+ "prettier-plugin-organize-imports": "^4.1.0",
50
48
  "rimraf": "^5.0.5",
51
49
  "ts-essentials": "^9.4.2",
52
- "ts-jest": "^29.1.4",
53
50
  "typescript": "^5.4.5",
54
- "typescript-eslint": "^7.7.0"
51
+ "typescript-eslint": "^7.7.0",
52
+ "vitest": "^3.2.2"
55
53
  },
56
54
  "publishConfig": {
57
55
  "access": "public"
@@ -72,7 +70,8 @@
72
70
  "ws": "^8.18.0"
73
71
  },
74
72
  "scripts": {
75
- "test": "jest",
73
+ "test": "vitest",
74
+ "test:ci": "vitest run",
76
75
  "build": "rimraf ./dist && rimraf ./dist.commonjs && tsc && tsc --project tsconfig.commonjs.json && copyfiles -u 2 misc/basedirs/**/* .",
77
76
  "lint": "eslint ./src",
78
77
  "format": "prettier --write . && eslint --fix ./src"
@@ -0,0 +1,13 @@
1
+ // prettier.config.js, .prettierrc.js, prettier.config.mjs, or .prettierrc.mjs
2
+
3
+ /**
4
+ * @see https://prettier.io/docs/configuration
5
+ * @type {import("prettier").Config}
6
+ */
7
+ const config = {
8
+ singleQuote: false,
9
+ trailingComma: "all",
10
+ plugins: [import.meta.resolve("prettier-plugin-organize-imports")],
11
+ };
12
+
13
+ export default config;
@@ -5,6 +5,10 @@ import { BytesFromEncoding } from "./advanced.js";
5
5
  * @public
6
6
  */
7
7
  export type Bytes = Uint8Array;
8
+ /**
9
+ * @public
10
+ */
11
+ export const Bytes = Uint8Array;
8
12
  /**
9
13
  * @public
10
14
  */
@@ -1673,10 +1673,10 @@ export class Transaction extends mol.Entity.Base<
1673
1673
  capacityTweak?: NumLike,
1674
1674
  filter?: ClientCollectableSearchKeyFilterLike,
1675
1675
  ): Promise<number> {
1676
- const exceptedCapacity =
1676
+ const expectedCapacity =
1677
1677
  this.getOutputsCapacity() + numFrom(capacityTweak ?? 0);
1678
1678
  const inputsCapacity = await this.getInputsCapacity(from.client);
1679
- if (inputsCapacity >= exceptedCapacity) {
1679
+ if (inputsCapacity >= expectedCapacity) {
1680
1680
  return 0;
1681
1681
  }
1682
1682
 
@@ -1688,7 +1688,7 @@ export class Transaction extends mol.Entity.Base<
1688
1688
  },
1689
1689
  (acc, { cellOutput: { capacity } }) => {
1690
1690
  const sum = acc + capacity;
1691
- return sum >= exceptedCapacity ? undefined : sum;
1691
+ return sum >= expectedCapacity ? undefined : sum;
1692
1692
  },
1693
1693
  inputsCapacity,
1694
1694
  );
@@ -1698,7 +1698,7 @@ export class Transaction extends mol.Entity.Base<
1698
1698
  }
1699
1699
 
1700
1700
  throw new Error(
1701
- `Insufficient CKB, need ${fixedPointToString(exceptedCapacity - accumulated)} extra CKB`,
1701
+ `Insufficient CKB, need ${fixedPointToString(expectedCapacity - accumulated)} extra CKB`,
1702
1702
  );
1703
1703
  }
1704
1704
 
@@ -1719,15 +1719,45 @@ export class Transaction extends mol.Entity.Base<
1719
1719
  return addedCount;
1720
1720
  }
1721
1721
 
1722
+ /**
1723
+ * Complete inputs by UDT balance
1724
+ *
1725
+ * This method succeeds only if enough balance is collected.
1726
+ *
1727
+ * It will try to collect at least two inputs, even when the first input already contains enough balance, to avoid extra occupation fees introduced by the change cell. An edge case: If the first cell has the same amount as the output, a new cell is not needed.
1728
+ * @param from - The signer to complete the inputs.
1729
+ * @param type - The type script of the UDT.
1730
+ * @param balanceTweak - The tweak of the balance.
1731
+ * @returns A promise that resolves to the number of inputs added.
1732
+ */
1722
1733
  async completeInputsByUdt(
1723
1734
  from: Signer,
1724
1735
  type: ScriptLike,
1725
1736
  balanceTweak?: NumLike,
1726
1737
  ): Promise<number> {
1727
- const exceptedBalance =
1738
+ const expectedBalance =
1728
1739
  this.getOutputsUdtBalance(type) + numFrom(balanceTweak ?? 0);
1729
- const inputsBalance = await this.getInputsUdtBalance(from.client, type);
1730
- if (inputsBalance >= exceptedBalance) {
1740
+ if (expectedBalance === numFrom(0)) {
1741
+ return 0;
1742
+ }
1743
+
1744
+ const [inputsBalance, inputsCount] = await reduceAsync(
1745
+ this.inputs,
1746
+ async ([balanceAcc, countAcc], input) => {
1747
+ const { cellOutput, outputData } = await input.getCell(from.client);
1748
+ if (!cellOutput.type?.eq(type)) {
1749
+ return;
1750
+ }
1751
+
1752
+ return [balanceAcc + udtBalanceFrom(outputData), countAcc + 1];
1753
+ },
1754
+ [numFrom(0), 0],
1755
+ );
1756
+
1757
+ if (
1758
+ inputsBalance === expectedBalance ||
1759
+ (inputsBalance >= expectedBalance && inputsCount >= 2)
1760
+ ) {
1731
1761
  return 0;
1732
1762
  }
1733
1763
 
@@ -1737,20 +1767,23 @@ export class Transaction extends mol.Entity.Base<
1737
1767
  script: type,
1738
1768
  outputDataLenRange: [16, numFrom("0xffffffff")],
1739
1769
  },
1740
- (acc, { outputData }) => {
1770
+ (acc, { outputData }, _i, collected) => {
1741
1771
  const balance = udtBalanceFrom(outputData);
1742
1772
  const sum = acc + balance;
1743
- return sum >= exceptedBalance ? undefined : sum;
1773
+ return sum === expectedBalance ||
1774
+ (sum >= expectedBalance && inputsCount + collected.length >= 2)
1775
+ ? undefined
1776
+ : sum;
1744
1777
  },
1745
1778
  inputsBalance,
1746
1779
  );
1747
1780
 
1748
- if (accumulated === undefined) {
1781
+ if (accumulated === undefined || accumulated >= expectedBalance) {
1749
1782
  return addedCount;
1750
1783
  }
1751
1784
 
1752
1785
  throw new Error(
1753
- `Insufficient coin, need ${exceptedBalance - accumulated} extra coin`,
1786
+ `Insufficient coin, need ${expectedBalance - accumulated} extra coin`,
1754
1787
  );
1755
1788
  }
1756
1789
 
@@ -54,6 +54,23 @@ export const MAINNET_SCRIPTS: Record<KnownScript, ScriptInfoLike | undefined> =
54
54
  },
55
55
  ],
56
56
  },
57
+ [KnownScript.Secp256k1MultisigV2]: {
58
+ codeHash:
59
+ "0x36c971b8d41fbd94aabca77dc75e826729ac98447b46f91e00796155dddb0d29",
60
+ hashType: "data1",
61
+ cellDeps: [
62
+ {
63
+ cellDep: {
64
+ outPoint: {
65
+ txHash:
66
+ "0x6888aa39ab30c570c2c30d9d5684d3769bf77265a7973211a3c087fe8efbf738",
67
+ index: 0,
68
+ },
69
+ depType: "depGroup",
70
+ },
71
+ },
72
+ ],
73
+ },
57
74
  [KnownScript.AnyoneCanPay]: {
58
75
  codeHash:
59
76
  "0xd369597ff47f29fbc0d47d2e3775370d1250b85140c670e4718af712983a2354",
@@ -54,6 +54,23 @@ export const TESTNET_SCRIPTS: Record<KnownScript, ScriptInfoLike> =
54
54
  },
55
55
  ],
56
56
  },
57
+ [KnownScript.Secp256k1MultisigV2]: {
58
+ codeHash:
59
+ "0x36c971b8d41fbd94aabca77dc75e826729ac98447b46f91e00796155dddb0d29",
60
+ hashType: "data1",
61
+ cellDeps: [
62
+ {
63
+ cellDep: {
64
+ outPoint: {
65
+ txHash:
66
+ "0x2eefdeb21f3a3edf697c28a52601b4419806ed60bb427420455cc29a090b26d5",
67
+ index: 0,
68
+ },
69
+ depType: "depGroup",
70
+ },
71
+ },
72
+ ],
73
+ },
57
74
  [KnownScript.AnyoneCanPay]: {
58
75
  codeHash:
59
76
  "0x3419a1c09eb2567f6552ee7a8ecffd64155cffe0f1796e6e61ec088d740c1356",
@@ -109,7 +126,7 @@ export const TESTNET_SCRIPTS: Record<KnownScript, ScriptInfoLike> =
109
126
  cellDep: {
110
127
  outPoint: {
111
128
  txHash:
112
- "0x4dcf3f3b09efac8995d6cbee87c5345e812d310094651e0c3d9a730f32dc9263",
129
+ "0x759f281588c96979764cb21c196478cf8e13ea81fede7f4ba26d1ff29dbc6a81",
113
130
  index: 0,
114
131
  },
115
132
  depType: "depGroup",
@@ -555,7 +555,7 @@ export class ErrorClientMaxFeeRateExceeded extends ErrorClientBase {
555
555
  const limit = numFrom(limitLike).toString();
556
556
  const actual = numFrom(actualLike).toString();
557
557
  super({
558
- message: `Max fee rate exceeded limit ${limit}, actual ${actual}. Developer might forgot to complete transaction fee before sending. See https://docs.ckbccc.com/classes/_ckb_ccc_core.index.ccc.Transaction.html#completeFeeBy.`,
558
+ message: `Max fee rate exceeded limit ${limit}, actual ${actual}. Developer might forgot to complete transaction fee before sending. See https://api.ckbccc.com/classes/_ckb_ccc_core.index.ccc.Transaction.html#completeFeeBy.`,
559
559
  data: JSON.stringify({ limit, actual }),
560
560
  });
561
561
  }
@@ -5,6 +5,7 @@ export enum KnownScript {
5
5
  NervosDao = "NervosDao",
6
6
  Secp256k1Blake160 = "Secp256k1Blake160",
7
7
  Secp256k1Multisig = "Secp256k1Multisig",
8
+ Secp256k1MultisigV2 = "Secp256k1MultisigV2", // Enhanced since handling (https://github.com/nervosnetwork/ckb-system-scripts/pull/99)
8
9
  AnyoneCanPay = "AnyoneCanPay",
9
10
  TypeId = "TypeId",
10
11
  XUdt = "XUdt",
@@ -18,13 +18,19 @@ import {
18
18
 
19
19
  export type CodecLike<Encodable, Decoded = Encodable> = {
20
20
  readonly encode: (encodable: Encodable) => Bytes;
21
- readonly decode: (decodable: BytesLike) => Decoded;
21
+ readonly decode: (
22
+ decodable: BytesLike,
23
+ config?: { isExtraFieldIgnored?: boolean },
24
+ ) => Decoded;
22
25
  readonly byteLength?: number;
23
26
  };
24
27
  export class Codec<Encodable, Decoded = Encodable> {
25
28
  constructor(
26
29
  public readonly encode: (encodable: Encodable) => Bytes,
27
- public readonly decode: (decodable: BytesLike) => Decoded,
30
+ public readonly decode: (
31
+ decodable: BytesLike,
32
+ config?: { isExtraFieldIgnored?: boolean }, // This is equivalent to "compatible" in the Rust implementation of Molecule.
33
+ ) => Decoded,
28
34
  public readonly byteLength?: number, // if provided, treat codec as fixed length
29
35
  ) {}
30
36
 
@@ -43,7 +49,7 @@ export class Codec<Encodable, Decoded = Encodable> {
43
49
  }
44
50
  return encoded;
45
51
  },
46
- (decodable) => {
52
+ (decodable, config) => {
47
53
  const decodableBytes = bytesFrom(decodable);
48
54
  if (
49
55
  byteLength !== undefined &&
@@ -53,7 +59,7 @@ export class Codec<Encodable, Decoded = Encodable> {
53
59
  `Codec.decode: expected byte length ${byteLength}, got ${decodableBytes.byteLength}`,
54
60
  );
55
61
  }
56
- return decode(decodable);
62
+ return decode(decodable, config);
57
63
  },
58
64
  byteLength,
59
65
  );
@@ -69,10 +75,10 @@ export class Codec<Encodable, Decoded = Encodable> {
69
75
  return new Codec(
70
76
  (encodable) =>
71
77
  this.encode((inMap ? inMap(encodable) : encodable) as Encodable),
72
- (buffer) =>
78
+ (buffer, config) =>
73
79
  (outMap
74
- ? outMap(this.decode(buffer))
75
- : this.decode(buffer)) as NewDecoded,
80
+ ? outMap(this.decode(buffer, config))
81
+ : this.decode(buffer, config)) as NewDecoded,
76
82
  this.byteLength,
77
83
  );
78
84
  }
@@ -128,7 +134,7 @@ export function fixedItemVec<Encodable, Decoded>(
128
134
  throw new Error(`fixedItemVec(${e?.toString()})`);
129
135
  }
130
136
  },
131
- decode(buffer) {
137
+ decode(buffer, config) {
132
138
  const value = bytesFrom(buffer);
133
139
  if (value.byteLength < 4) {
134
140
  throw new Error(
@@ -147,7 +153,10 @@ export function fixedItemVec<Encodable, Decoded>(
147
153
  const decodedArray: Array<Decoded> = [];
148
154
  for (let offset = 4; offset < byteLength; offset += itemByteLength) {
149
155
  decodedArray.push(
150
- itemCodec.decode(value.slice(offset, offset + itemByteLength)),
156
+ itemCodec.decode(
157
+ value.slice(offset, offset + itemByteLength),
158
+ config,
159
+ ),
151
160
  );
152
161
  }
153
162
  return decodedArray;
@@ -185,7 +194,7 @@ export function dynItemVec<Encodable, Decoded>(
185
194
  throw new Error(`dynItemVec(${e?.toString()})`);
186
195
  }
187
196
  },
188
- decode(buffer) {
197
+ decode(buffer, config) {
189
198
  const value = bytesFrom(buffer);
190
199
  if (value.byteLength < 4) {
191
200
  throw new Error(
@@ -215,7 +224,7 @@ export function dynItemVec<Encodable, Decoded>(
215
224
  const start = offsets[index];
216
225
  const end = offsets[index + 1];
217
226
  const itemBuffer = value.slice(start, end);
218
- decodedArray.push(itemCodec.decode(itemBuffer));
227
+ decodedArray.push(itemCodec.decode(itemBuffer, config));
219
228
  }
220
229
  return decodedArray;
221
230
  } catch (e) {
@@ -259,13 +268,13 @@ export function option<Encodable, Decoded>(
259
268
  throw new Error(`option(${e?.toString()})`);
260
269
  }
261
270
  },
262
- decode(buffer) {
271
+ decode(buffer, config) {
263
272
  const value = bytesFrom(buffer);
264
273
  if (value.byteLength === 0) {
265
274
  return undefined;
266
275
  }
267
276
  try {
268
- return innerCodec.decode(buffer);
277
+ return innerCodec.decode(buffer, config);
269
278
  } catch (e) {
270
279
  throw new Error(`option(${e?.toString()})`);
271
280
  }
@@ -290,7 +299,7 @@ export function byteVec<Encodable, Decoded>(
290
299
  throw new Error(`byteVec(${e?.toString()})`);
291
300
  }
292
301
  },
293
- decode(buffer) {
302
+ decode(buffer, config) {
294
303
  const value = bytesFrom(buffer);
295
304
  if (value.byteLength < 4) {
296
305
  throw new Error(
@@ -304,7 +313,7 @@ export function byteVec<Encodable, Decoded>(
304
313
  );
305
314
  }
306
315
  try {
307
- return codec.decode(value.slice(4));
316
+ return codec.decode(value.slice(4), config);
308
317
  } catch (e: unknown) {
309
318
  throw new Error(`byteVec(${e?.toString()})`);
310
319
  }
@@ -371,7 +380,7 @@ export function table<
371
380
  const packedTotalSize = uint32To(header.length + body.length + 4);
372
381
  return bytesConcat(packedTotalSize, header, body);
373
382
  },
374
- decode(buffer) {
383
+ decode(buffer, config) {
375
384
  const value = bytesFrom(buffer);
376
385
  if (value.byteLength < 4) {
377
386
  throw new Error(
@@ -379,15 +388,38 @@ export function table<
379
388
  );
380
389
  }
381
390
  const byteLength = uint32From(value.slice(0, 4));
391
+ const headerLength = uint32From(value.slice(4, 8));
392
+ const actualFieldCount = (headerLength - 4) / 4;
393
+
382
394
  if (byteLength !== value.byteLength) {
383
395
  throw new Error(
384
396
  `table: invalid buffer size, expected ${byteLength}, but got ${value.byteLength}`,
385
397
  );
386
398
  }
399
+
400
+ if (actualFieldCount < keys.length) {
401
+ throw new Error(
402
+ `table: invalid field count, expected ${keys.length}, but got ${actualFieldCount}`,
403
+ );
404
+ }
405
+
406
+ if (actualFieldCount > keys.length && !config?.isExtraFieldIgnored) {
407
+ throw new Error(
408
+ `table: invalid field count, expected ${keys.length}, but got ${actualFieldCount}, and extra fields are not allowed in the current configuration. If you want to ignore extra fields, set isExtraFieldIgnored to true.`,
409
+ );
410
+ }
387
411
  const offsets = keys.map((_, index) =>
388
412
  uint32From(value.slice(4 + index * 4, 8 + index * 4)),
389
413
  );
390
- offsets.push(byteLength);
414
+ // If there are extra fields, add the last offset to the offsets array
415
+ if (actualFieldCount > keys.length) {
416
+ offsets.push(
417
+ uint32From(value.slice(4 + keys.length * 4, 8 + keys.length * 4)),
418
+ );
419
+ } else {
420
+ // If there are no extra fields, add the byte length to the offsets array
421
+ offsets.push(byteLength);
422
+ }
391
423
  const object = {};
392
424
  for (let i = 0; i < offsets.length - 1; i++) {
393
425
  const start = offsets[i];
@@ -397,7 +429,7 @@ export function table<
397
429
  const payload = value.slice(start, end);
398
430
  try {
399
431
  // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
400
- Object.assign(object, { [field]: codec.decode(payload) });
432
+ Object.assign(object, { [field]: codec.decode(payload, config) });
401
433
  } catch (e: unknown) {
402
434
  throw new Error(`table.${field}(${e?.toString()})`);
403
435
  }
@@ -466,7 +498,7 @@ export function union<T extends Record<string, CodecLike<any, any>>>(
466
498
  throw new Error(`union.(${typeStr})(${e?.toString()})`);
467
499
  }
468
500
  },
469
- decode(buffer) {
501
+ decode(buffer, config) {
470
502
  const value = bytesFrom(buffer);
471
503
  const fieldIndex = uint32From(value.slice(0, 4));
472
504
  const keys = Object.keys(codecLayout);
@@ -496,7 +528,7 @@ export function union<T extends Record<string, CodecLike<any, any>>>(
496
528
  return {
497
529
  type: field,
498
530
  // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
499
- value: codecLayout[field].decode(value.slice(4)),
531
+ value: codecLayout[field].decode(value.slice(4), config),
500
532
  } as UnionDecoded<T>;
501
533
  },
502
534
  });
@@ -535,7 +567,7 @@ export function struct<
535
567
 
536
568
  return bytesFrom(bytes);
537
569
  },
538
- decode(buffer) {
570
+ decode(buffer, config) {
539
571
  const value = bytesFrom(buffer);
540
572
  const object = {};
541
573
  let offset = 0;
@@ -543,7 +575,7 @@ export function struct<
543
575
  const payload = value.slice(offset, offset + codec.byteLength!);
544
576
  try {
545
577
  // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
546
- Object.assign(object, { [key]: codec.decode(payload) });
578
+ Object.assign(object, { [key]: codec.decode(payload, config) });
547
579
  } catch (e: unknown) {
548
580
  throw new Error(`struct.${key}(${(e as Error).toString()})`);
549
581
  }
@@ -583,7 +615,7 @@ export function array<Encodable, Decoded>(
583
615
  throw new Error(`array(${e?.toString()})`);
584
616
  }
585
617
  },
586
- decode(buffer) {
618
+ decode(buffer, config) {
587
619
  const value = bytesFrom(buffer);
588
620
  if (value.byteLength != byteLength) {
589
621
  throw new Error(
@@ -594,7 +626,7 @@ export function array<Encodable, Decoded>(
594
626
  const result: Array<Decoded> = [];
595
627
  for (let i = 0; i < value.byteLength; i += itemCodec.byteLength!) {
596
628
  result.push(
597
- itemCodec.decode(value.slice(i, i + itemCodec.byteLength!)),
629
+ itemCodec.decode(value.slice(i, i + itemCodec.byteLength!), config),
598
630
  );
599
631
  }
600
632
  return result;
@@ -166,18 +166,17 @@ export function codec<
166
166
  },
167
167
  >(codec: Codec<Encodable, Decoded>) {
168
168
  return function (Constructor: ConstructorType) {
169
- return class Extended extends Constructor {
170
- static byteLength = codec.byteLength;
171
- static encode(encodable: TypeLike): Bytes {
172
- return codec.encode(encodable);
173
- }
174
- static decode(bytesLike: BytesLike): Type {
175
- return Constructor.from(codec.decode(bytesLike));
176
- }
177
-
178
- static fromBytes(bytes: BytesLike): Type {
179
- return Constructor.from(codec.decode(bytes));
180
- }
169
+ Constructor.byteLength = codec.byteLength;
170
+ Constructor.encode = function (encodable: TypeLike) {
171
+ return codec.encode(encodable);
181
172
  };
173
+ Constructor.decode = function (bytesLike: BytesLike) {
174
+ return Constructor.from(codec.decode(bytesLike));
175
+ };
176
+ Constructor.fromBytes = function (bytes: BytesLike) {
177
+ return Constructor.from(codec.decode(bytes));
178
+ };
179
+
180
+ return Constructor;
182
181
  };
183
182
  }