@ckb-ccc/core 1.8.1 → 1.9.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.
- package/CHANGELOG.md +27 -0
- package/dist/bytes/index.d.ts +4 -0
- package/dist/bytes/index.d.ts.map +1 -1
- package/dist/bytes/index.js +4 -0
- package/dist/ckb/transaction.d.ts +11 -0
- package/dist/ckb/transaction.d.ts.map +1 -1
- package/dist/ckb/transaction.js +35 -11
- package/dist/client/clientPublicMainnet.advanced.d.ts.map +1 -1
- package/dist/client/clientPublicMainnet.advanced.js +15 -0
- package/dist/client/clientPublicTestnet.advanced.d.ts.map +1 -1
- package/dist/client/clientPublicTestnet.advanced.js +15 -0
- package/dist/client/clientTypes.js +1 -1
- package/dist/client/knownScript.d.ts +1 -0
- package/dist/client/knownScript.d.ts.map +1 -1
- package/dist/client/knownScript.js +1 -0
- package/dist/molecule/codec.d.ts +9 -3
- package/dist/molecule/codec.d.ts.map +1 -1
- package/dist/molecule/codec.js +37 -22
- package/dist/molecule/entity.d.ts +1 -8
- package/dist/molecule/entity.d.ts.map +1 -1
- package/dist/molecule/entity.js +11 -14
- package/dist/signer/nostr/signerNostrPrivateKey.d.ts +4 -0
- package/dist/signer/nostr/signerNostrPrivateKey.d.ts.map +1 -1
- package/dist/signer/nostr/signerNostrPrivateKey.js +13 -1
- package/dist/signer/nostr/signerNostrPublicKeyReadonly.d.ts +4 -0
- package/dist/signer/nostr/signerNostrPublicKeyReadonly.d.ts.map +1 -1
- package/dist/signer/nostr/signerNostrPublicKeyReadonly.js +4 -0
- package/dist.commonjs/bytes/index.d.ts +4 -0
- package/dist.commonjs/bytes/index.d.ts.map +1 -1
- package/dist.commonjs/bytes/index.js +5 -0
- package/dist.commonjs/ckb/transaction.d.ts +11 -0
- package/dist.commonjs/ckb/transaction.d.ts.map +1 -1
- package/dist.commonjs/ckb/transaction.js +35 -11
- package/dist.commonjs/client/clientPublicMainnet.advanced.d.ts.map +1 -1
- package/dist.commonjs/client/clientPublicMainnet.advanced.js +15 -0
- package/dist.commonjs/client/clientPublicTestnet.advanced.d.ts.map +1 -1
- package/dist.commonjs/client/clientPublicTestnet.advanced.js +15 -0
- package/dist.commonjs/client/clientTypes.js +1 -1
- package/dist.commonjs/client/knownScript.d.ts +1 -0
- package/dist.commonjs/client/knownScript.d.ts.map +1 -1
- package/dist.commonjs/client/knownScript.js +1 -0
- package/dist.commonjs/molecule/codec.d.ts +9 -3
- package/dist.commonjs/molecule/codec.d.ts.map +1 -1
- package/dist.commonjs/molecule/codec.js +37 -22
- package/dist.commonjs/molecule/entity.d.ts +1 -8
- package/dist.commonjs/molecule/entity.d.ts.map +1 -1
- package/dist.commonjs/molecule/entity.js +11 -14
- package/dist.commonjs/signer/nostr/signerNostrPrivateKey.d.ts +4 -0
- package/dist.commonjs/signer/nostr/signerNostrPrivateKey.d.ts.map +1 -1
- package/dist.commonjs/signer/nostr/signerNostrPrivateKey.js +13 -1
- package/dist.commonjs/signer/nostr/signerNostrPublicKeyReadonly.d.ts +4 -0
- package/dist.commonjs/signer/nostr/signerNostrPublicKeyReadonly.d.ts.map +1 -1
- package/dist.commonjs/signer/nostr/signerNostrPublicKeyReadonly.js +4 -0
- package/package.json +9 -10
- package/prettier.config.mjs +13 -0
- package/src/bytes/index.ts +4 -0
- package/src/ckb/transaction.ts +44 -11
- package/src/client/clientPublicMainnet.advanced.ts +17 -0
- package/src/client/clientPublicTestnet.advanced.ts +17 -0
- package/src/client/clientTypes.ts +1 -1
- package/src/client/knownScript.ts +1 -0
- package/src/molecule/codec.ts +56 -24
- package/src/molecule/entity.ts +11 -12
- package/src/signer/nostr/signerNostrPrivateKey.ts +17 -1
- package/src/signer/nostr/signerNostrPublicKeyReadonly.ts +4 -0
- package/vitest.config.ts +10 -0
- package/jest.config.js +0 -5
|
@@ -121,19 +121,16 @@ exports.Entity = Entity;
|
|
|
121
121
|
*/
|
|
122
122
|
function codec(codec) {
|
|
123
123
|
return function (Constructor) {
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
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":"
|
|
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 = (
|
|
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.
|
|
3
|
+
"version": "1.9.0",
|
|
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": "^
|
|
46
|
-
"eslint-plugin-prettier": "^5.1
|
|
47
|
-
"
|
|
48
|
-
"prettier": "^
|
|
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": "
|
|
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;
|
package/src/bytes/index.ts
CHANGED
package/src/ckb/transaction.ts
CHANGED
|
@@ -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
|
|
1676
|
+
const expectedCapacity =
|
|
1677
1677
|
this.getOutputsCapacity() + numFrom(capacityTweak ?? 0);
|
|
1678
1678
|
const inputsCapacity = await this.getInputsCapacity(from.client);
|
|
1679
|
-
if (inputsCapacity >=
|
|
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 >=
|
|
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(
|
|
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
|
|
1738
|
+
const expectedBalance =
|
|
1728
1739
|
this.getOutputsUdtBalance(type) + numFrom(balanceTweak ?? 0);
|
|
1729
|
-
|
|
1730
|
-
|
|
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
|
|
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 ${
|
|
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",
|
|
@@ -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://
|
|
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",
|
package/src/molecule/codec.ts
CHANGED
|
@@ -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: (
|
|
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: (
|
|
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(
|
|
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
|
|
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;
|
package/src/molecule/entity.ts
CHANGED
|
@@ -166,18 +166,17 @@ export function codec<
|
|
|
166
166
|
},
|
|
167
167
|
>(codec: Codec<Encodable, Decoded>) {
|
|
168
168
|
return function (Constructor: ConstructorType) {
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
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
|
}
|
|
@@ -1,15 +1,31 @@
|
|
|
1
1
|
import { schnorr } from "@noble/curves/secp256k1";
|
|
2
|
+
import { bech32 } from "bech32";
|
|
2
3
|
import { Client } from "../../client/index.js";
|
|
3
4
|
import { Hex, hexFrom, HexLike } from "../../hex/index.js";
|
|
4
5
|
import { NostrEvent } from "./signerNostr.js";
|
|
5
6
|
import { SignerNostrPublicKeyReadonly } from "./signerNostrPublicKeyReadonly.js";
|
|
6
7
|
import { nostrEventHash } from "./verify.js";
|
|
7
8
|
|
|
9
|
+
/**
|
|
10
|
+
* Signer from Nostr private key
|
|
11
|
+
* Support nsec and hex format
|
|
12
|
+
*/
|
|
8
13
|
export class SignerNostrPrivateKey extends SignerNostrPublicKeyReadonly {
|
|
9
14
|
private readonly privateKey: Hex;
|
|
10
15
|
|
|
11
16
|
constructor(client: Client, privateKeyLike: HexLike) {
|
|
12
|
-
const privateKey =
|
|
17
|
+
const privateKey = (() => {
|
|
18
|
+
if (
|
|
19
|
+
typeof privateKeyLike === "string" &&
|
|
20
|
+
privateKeyLike.startsWith("nsec")
|
|
21
|
+
) {
|
|
22
|
+
const { words } = bech32.decode(privateKeyLike);
|
|
23
|
+
return hexFrom(bech32.fromWords(words));
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
return hexFrom(privateKeyLike);
|
|
27
|
+
})();
|
|
28
|
+
|
|
13
29
|
super(client, schnorr.getPublicKey(privateKey.slice(2)));
|
|
14
30
|
|
|
15
31
|
this.privateKey = privateKey;
|
|
@@ -3,6 +3,10 @@ import { Client } from "../../client/index.js";
|
|
|
3
3
|
import { Hex, hexFrom, HexLike } from "../../hex/index.js";
|
|
4
4
|
import { SignerNostr } from "./signerNostr.js";
|
|
5
5
|
|
|
6
|
+
/**
|
|
7
|
+
* Signer from Nostr public key
|
|
8
|
+
* Support npub and hex format
|
|
9
|
+
*/
|
|
6
10
|
export class SignerNostrPublicKeyReadonly extends SignerNostr {
|
|
7
11
|
public readonly publicKey: Hex;
|
|
8
12
|
|