@ckb-ccc/core 0.0.13 → 0.0.14-alpha.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.
- package/CHANGELOG.md +21 -0
- package/README.md +16 -3
- package/dist/ckb/transaction.d.ts.map +1 -1
- package/dist/ckb/transaction.js +12 -8
- package/dist/client/client.d.ts +1 -1
- package/dist/client/client.d.ts.map +1 -1
- package/dist/client/client.js +2 -2
- package/dist/client/clientTypes.d.ts +9 -0
- package/dist/client/clientTypes.d.ts.map +1 -1
- package/dist/client/clientTypes.js +13 -0
- package/dist/client/jsonRpc/index.d.ts.map +1 -1
- package/dist/client/jsonRpc/index.js +29 -13
- package/dist/num/index.d.ts +13 -0
- package/dist/num/index.d.ts.map +1 -1
- package/dist/num/index.js +23 -1
- package/dist/signer/ckb/signerCkbPrivateKey.d.ts.map +1 -1
- package/dist/signer/ckb/signerCkbPrivateKey.js +9 -8
- package/dist/signer/ckb/signerCkbPublicKey.d.ts +8 -2
- package/dist/signer/ckb/signerCkbPublicKey.d.ts.map +1 -1
- package/dist/signer/ckb/signerCkbPublicKey.js +65 -7
- package/dist.commonjs/ckb/transaction.d.ts.map +1 -1
- package/dist.commonjs/ckb/transaction.js +11 -7
- package/dist.commonjs/client/client.d.ts +1 -1
- package/dist.commonjs/client/client.d.ts.map +1 -1
- package/dist.commonjs/client/client.js +2 -2
- package/dist.commonjs/client/clientTypes.d.ts +9 -0
- package/dist.commonjs/client/clientTypes.d.ts.map +1 -1
- package/dist.commonjs/client/clientTypes.js +16 -1
- package/dist.commonjs/client/jsonRpc/index.d.ts.map +1 -1
- package/dist.commonjs/client/jsonRpc/index.js +28 -12
- package/dist.commonjs/num/index.d.ts +13 -0
- package/dist.commonjs/num/index.d.ts.map +1 -1
- package/dist.commonjs/num/index.js +25 -2
- package/dist.commonjs/signer/ckb/signerCkbPrivateKey.d.ts.map +1 -1
- package/dist.commonjs/signer/ckb/signerCkbPrivateKey.js +9 -8
- package/dist.commonjs/signer/ckb/signerCkbPublicKey.d.ts +8 -2
- package/dist.commonjs/signer/ckb/signerCkbPublicKey.d.ts.map +1 -1
- package/dist.commonjs/signer/ckb/signerCkbPublicKey.js +64 -6
- package/package.json +1 -1
- package/src/ckb/transaction.ts +13 -11
- package/src/client/client.ts +2 -2
- package/src/client/clientTypes.ts +24 -0
- package/src/client/jsonRpc/index.ts +43 -28
- package/src/num/index.ts +24 -1
- package/src/signer/ckb/signerCkbPrivateKey.ts +13 -9
- package/src/signer/ckb/signerCkbPublicKey.ts +97 -12
|
@@ -15,6 +15,8 @@ import {
|
|
|
15
15
|
ClientTransactionResponse,
|
|
16
16
|
ErrorClientBase,
|
|
17
17
|
ErrorClientBaseLike,
|
|
18
|
+
ErrorClientDuplicatedTransaction,
|
|
19
|
+
ErrorClientRBFRejected,
|
|
18
20
|
ErrorClientResolveUnknown,
|
|
19
21
|
ErrorClientVerification,
|
|
20
22
|
OutputsValidator,
|
|
@@ -50,6 +52,41 @@ async function transform(
|
|
|
50
52
|
return value;
|
|
51
53
|
}
|
|
52
54
|
|
|
55
|
+
const ERROR_PARSERS: [
|
|
56
|
+
string,
|
|
57
|
+
(error: ErrorClientBaseLike, match: RegExpMatchArray) => ErrorClientBase,
|
|
58
|
+
][] = [
|
|
59
|
+
[
|
|
60
|
+
"Resolve\\(Unknown\\(OutPoint\\((0x.*)\\)\\)\\)",
|
|
61
|
+
(error, match) =>
|
|
62
|
+
new ErrorClientResolveUnknown(error, OutPoint.fromBytes(match[1])),
|
|
63
|
+
],
|
|
64
|
+
[
|
|
65
|
+
"Verification\\(Error { kind: Script, inner: TransactionScriptError { source: (Inputs|Outputs)\\[([0-9]*)\\].(Lock|Type), cause: ValidationFailure: see error code (-?[0-9])* on page https://nervosnetwork\\.github\\.io/ckb-script-error-codes/by-(type|data)-hash/(.*)\\.html",
|
|
66
|
+
(error, match) =>
|
|
67
|
+
new ErrorClientVerification(
|
|
68
|
+
error,
|
|
69
|
+
match[3] === "Lock"
|
|
70
|
+
? "lock"
|
|
71
|
+
: match[1] === "Inputs"
|
|
72
|
+
? "inputType"
|
|
73
|
+
: "outputType",
|
|
74
|
+
match[2],
|
|
75
|
+
Number(match[4]),
|
|
76
|
+
match[5] === "data" ? "data" : "type",
|
|
77
|
+
match[6],
|
|
78
|
+
),
|
|
79
|
+
],
|
|
80
|
+
[
|
|
81
|
+
"Duplicated\\(Byte32\\((0x.*)\\)\\)",
|
|
82
|
+
(error, match) => new ErrorClientDuplicatedTransaction(error, match[1]),
|
|
83
|
+
],
|
|
84
|
+
[
|
|
85
|
+
'RBFRejected\\("Tx\'s current fee is ([0-9]*), expect it to >= ([0-9]*) to replace old txs"\\)',
|
|
86
|
+
(error, match) => new ErrorClientRBFRejected(error, match[1], match[2]),
|
|
87
|
+
],
|
|
88
|
+
];
|
|
89
|
+
|
|
53
90
|
/**
|
|
54
91
|
* An abstract class implementing JSON-RPC client functionality for a specific URL and timeout.
|
|
55
92
|
* Provides methods for sending transactions and building JSON-RPC payloads.
|
|
@@ -353,33 +390,11 @@ export abstract class ClientJsonRpc extends Client {
|
|
|
353
390
|
}
|
|
354
391
|
const err = errAny as ErrorClientBaseLike;
|
|
355
392
|
|
|
356
|
-
const
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
err,
|
|
362
|
-
OutPoint.fromBytes(unknownOutPointMatch),
|
|
363
|
-
);
|
|
364
|
-
}
|
|
365
|
-
const verificationFailedMatch = err.data.match(
|
|
366
|
-
new RegExp(
|
|
367
|
-
"Verification\\(Error { kind: Script, inner: TransactionScriptError { source: (Inputs|Outputs)\\[([0-9]*)\\].(Lock|Type), cause: ValidationFailure: see error code (-?[0-9])* on page https://nervosnetwork\\.github\\.io/ckb-script-error-codes/by-(type|data)-hash/(.*)\\.html",
|
|
368
|
-
),
|
|
369
|
-
);
|
|
370
|
-
if (verificationFailedMatch) {
|
|
371
|
-
throw new ErrorClientVerification(
|
|
372
|
-
err,
|
|
373
|
-
verificationFailedMatch[3] === "Lock"
|
|
374
|
-
? "lock"
|
|
375
|
-
: verificationFailedMatch[1] === "Inputs"
|
|
376
|
-
? "inputType"
|
|
377
|
-
: "outputType",
|
|
378
|
-
verificationFailedMatch[2],
|
|
379
|
-
Number(verificationFailedMatch[4]),
|
|
380
|
-
verificationFailedMatch[5] === "data" ? "data" : "type",
|
|
381
|
-
verificationFailedMatch[6],
|
|
382
|
-
);
|
|
393
|
+
for (const [regexp, builder] of ERROR_PARSERS) {
|
|
394
|
+
const match = err.data.match(regexp);
|
|
395
|
+
if (match) {
|
|
396
|
+
throw builder(err, match);
|
|
397
|
+
}
|
|
383
398
|
}
|
|
384
399
|
|
|
385
400
|
throw new ErrorClientBase(err);
|
|
@@ -405,7 +420,7 @@ export abstract class ClientJsonRpc extends Client {
|
|
|
405
420
|
throw new Error(`Id mismatched, got ${res.id}, expected ${payload.id}`);
|
|
406
421
|
}
|
|
407
422
|
if (res.error) {
|
|
408
|
-
throw res.error;
|
|
423
|
+
throw new Error(`Client request error ${JSON.stringify(res.error)}`);
|
|
409
424
|
}
|
|
410
425
|
return res.result;
|
|
411
426
|
}
|
package/src/num/index.ts
CHANGED
|
@@ -14,6 +14,29 @@ export type Num = bigint;
|
|
|
14
14
|
*/
|
|
15
15
|
export type NumLike = string | number | bigint | HexLike;
|
|
16
16
|
|
|
17
|
+
/**
|
|
18
|
+
* Get the min among all numbers.
|
|
19
|
+
* @public
|
|
20
|
+
*
|
|
21
|
+
* @param numbers - numbers.
|
|
22
|
+
* @returns The min numbers among them.
|
|
23
|
+
*
|
|
24
|
+
* @example
|
|
25
|
+
* ```typescript
|
|
26
|
+
* numMin(1, 2, 3); // Outputs 1n
|
|
27
|
+
* ```
|
|
28
|
+
*/
|
|
29
|
+
export function numMin(a: NumLike, ...numbers: NumLike[]): Num {
|
|
30
|
+
let min = numFrom(a);
|
|
31
|
+
numbers.forEach((nLike) => {
|
|
32
|
+
const n = numFrom(nLike);
|
|
33
|
+
if (n < min) {
|
|
34
|
+
min = n;
|
|
35
|
+
}
|
|
36
|
+
});
|
|
37
|
+
return min;
|
|
38
|
+
}
|
|
39
|
+
|
|
17
40
|
/**
|
|
18
41
|
* Get the max among all numbers.
|
|
19
42
|
* @public
|
|
@@ -167,7 +190,7 @@ export function numFromBytes(val: BytesLike): Num {
|
|
|
167
190
|
* ```
|
|
168
191
|
*/
|
|
169
192
|
export function numLeFromBytes(val: BytesLike): Num {
|
|
170
|
-
return numBeFromBytes(bytesFrom(val).reverse());
|
|
193
|
+
return numBeFromBytes([...bytesFrom(val)].reverse());
|
|
171
194
|
}
|
|
172
195
|
|
|
173
196
|
/**
|
|
@@ -45,17 +45,21 @@ export class SignerCkbPrivateKey extends SignerCkbPublicKey {
|
|
|
45
45
|
|
|
46
46
|
async signOnlyTransaction(txLike: TransactionLike): Promise<Transaction> {
|
|
47
47
|
const tx = Transaction.from(txLike);
|
|
48
|
-
const { script } = await this.getRecommendedAddressObj();
|
|
49
|
-
const info = await tx.getSignHashInfo(script, this.client);
|
|
50
|
-
if (!info) {
|
|
51
|
-
return tx;
|
|
52
|
-
}
|
|
53
48
|
|
|
54
|
-
const
|
|
49
|
+
for (const { script } of await this.getRelatedScripts(tx)) {
|
|
50
|
+
const info = await tx.getSignHashInfo(script, this.client);
|
|
51
|
+
if (!info) {
|
|
52
|
+
return tx;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
const signature = await this._signMessage(info.message);
|
|
56
|
+
|
|
57
|
+
const witness =
|
|
58
|
+
tx.getWitnessArgsAt(info.position) ?? WitnessArgs.from({});
|
|
59
|
+
witness.lock = signature;
|
|
60
|
+
tx.setWitnessArgsAt(info.position, witness);
|
|
61
|
+
}
|
|
55
62
|
|
|
56
|
-
const witness = tx.getWitnessArgsAt(info.position) ?? WitnessArgs.from({});
|
|
57
|
-
witness.lock = signature;
|
|
58
|
-
tx.setWitnessArgsAt(info.position, witness);
|
|
59
63
|
return tx;
|
|
60
64
|
}
|
|
61
65
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { Address } from "../../address/index.js";
|
|
2
2
|
import { bytesFrom } from "../../bytes/index.js";
|
|
3
|
-
import { Transaction, TransactionLike } from "../../ckb/index.js";
|
|
4
|
-
import { Client, KnownScript } from "../../client/index.js";
|
|
3
|
+
import { Script, Transaction, TransactionLike } from "../../ckb/index.js";
|
|
4
|
+
import { CellDepInfo, Client, KnownScript } from "../../client/index.js";
|
|
5
5
|
import { hashCkb } from "../../hasher/index.js";
|
|
6
6
|
import { Hex, HexLike, hexFrom } from "../../hex/index.js";
|
|
7
7
|
import { Signer, SignerSignType, SignerType } from "../signer/index.js";
|
|
@@ -43,24 +43,109 @@ export class SignerCkbPublicKey extends Signer {
|
|
|
43
43
|
return this.publicKey;
|
|
44
44
|
}
|
|
45
45
|
|
|
46
|
+
async getAddressObjSecp256k1(): Promise<Address> {
|
|
47
|
+
return Address.fromKnownScript(
|
|
48
|
+
this.client,
|
|
49
|
+
KnownScript.Secp256k1Blake160,
|
|
50
|
+
bytesFrom(hashCkb(this.publicKey)).slice(0, 20),
|
|
51
|
+
);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
async getRecommendedAddressObj(_preference?: unknown): Promise<Address> {
|
|
55
|
+
return this.getAddressObjSecp256k1();
|
|
56
|
+
}
|
|
57
|
+
|
|
46
58
|
async getAddressObjs(): Promise<Address[]> {
|
|
47
|
-
|
|
48
|
-
|
|
59
|
+
const secp256k1 = await this.getAddressObjSecp256k1();
|
|
60
|
+
|
|
61
|
+
const addresses: Address[] = [];
|
|
62
|
+
let count = 0;
|
|
63
|
+
for await (const cell of this.client.findCells({
|
|
64
|
+
script: await Script.fromKnownScript(
|
|
49
65
|
this.client,
|
|
50
|
-
KnownScript.
|
|
51
|
-
|
|
66
|
+
KnownScript.AnyoneCanPay,
|
|
67
|
+
secp256k1.script.args,
|
|
52
68
|
),
|
|
53
|
-
|
|
69
|
+
scriptType: "lock",
|
|
70
|
+
scriptSearchMode: "prefix",
|
|
71
|
+
withData: false,
|
|
72
|
+
})) {
|
|
73
|
+
if (count >= 10) {
|
|
74
|
+
break;
|
|
75
|
+
}
|
|
76
|
+
count += 1;
|
|
77
|
+
|
|
78
|
+
if (addresses.some(({ script }) => script.eq(cell.cellOutput.lock))) {
|
|
79
|
+
continue;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
addresses.push(
|
|
83
|
+
Address.from({
|
|
84
|
+
prefix: this.client.addressPrefix,
|
|
85
|
+
script: cell.cellOutput.lock,
|
|
86
|
+
}),
|
|
87
|
+
);
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
return [secp256k1, ...addresses];
|
|
54
91
|
}
|
|
55
92
|
|
|
56
|
-
async
|
|
93
|
+
async getRelatedScripts(
|
|
94
|
+
txLike: TransactionLike,
|
|
95
|
+
): Promise<{ script: Script; cellDeps: CellDepInfo[] }[]> {
|
|
57
96
|
const tx = Transaction.from(txLike);
|
|
58
|
-
|
|
59
|
-
await
|
|
97
|
+
|
|
98
|
+
const secp256k1 = await this.getAddressObjSecp256k1();
|
|
99
|
+
const acp = await Script.fromKnownScript(
|
|
60
100
|
this.client,
|
|
61
|
-
KnownScript.
|
|
101
|
+
KnownScript.AnyoneCanPay,
|
|
102
|
+
secp256k1.script.args,
|
|
103
|
+
);
|
|
104
|
+
|
|
105
|
+
const scripts: { script: Script; cellDeps: CellDepInfo[] }[] = [];
|
|
106
|
+
for (const input of tx.inputs) {
|
|
107
|
+
await input.completeExtraInfos(this.client);
|
|
108
|
+
if (!input.cellOutput) {
|
|
109
|
+
throw new Error("Unable to complete input");
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
const { lock } = input.cellOutput;
|
|
113
|
+
if (scripts.some(({ script }) => script.eq(lock))) {
|
|
114
|
+
continue;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
if (lock.eq(secp256k1.script)) {
|
|
118
|
+
scripts.push({
|
|
119
|
+
script: lock,
|
|
120
|
+
cellDeps: (
|
|
121
|
+
await this.client.getKnownScript(KnownScript.Secp256k1Blake160)
|
|
122
|
+
).cellDeps,
|
|
123
|
+
});
|
|
124
|
+
} else if (
|
|
125
|
+
lock.codeHash === acp.codeHash &&
|
|
126
|
+
lock.hashType === acp.hashType &&
|
|
127
|
+
lock.args.startsWith(acp.args)
|
|
128
|
+
) {
|
|
129
|
+
scripts.push({
|
|
130
|
+
script: lock,
|
|
131
|
+
cellDeps: (await this.client.getKnownScript(KnownScript.AnyoneCanPay))
|
|
132
|
+
.cellDeps,
|
|
133
|
+
});
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
return scripts;
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
async prepareTransaction(txLike: TransactionLike): Promise<Transaction> {
|
|
141
|
+
const tx = Transaction.from(txLike);
|
|
142
|
+
|
|
143
|
+
await Promise.all(
|
|
144
|
+
(await this.getRelatedScripts(tx)).map(async ({ script, cellDeps }) => {
|
|
145
|
+
await tx.prepareSighashAllWitness(script, 65, this.client);
|
|
146
|
+
await tx.addCellDepInfos(this.client, cellDeps);
|
|
147
|
+
}),
|
|
62
148
|
);
|
|
63
|
-
await tx.prepareSighashAllWitness(script, 65, this.client);
|
|
64
149
|
return tx;
|
|
65
150
|
}
|
|
66
151
|
}
|