@ckb-ccc/core 1.0.0 → 1.1.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 +14 -0
- package/dist/address/address.advanced.d.ts.map +1 -1
- package/dist/address/address.advanced.js +6 -2
- package/dist/bytes/index.d.ts +21 -0
- package/dist/bytes/index.d.ts.map +1 -1
- package/dist/bytes/index.js +31 -4
- package/dist/ckb/script.d.ts +1 -1
- package/dist/ckb/script.d.ts.map +1 -1
- package/dist/ckb/script.js +2 -4
- package/dist/ckb/transaction.d.ts +19 -12
- package/dist/ckb/transaction.d.ts.map +1 -1
- package/dist/ckb/transaction.js +23 -38
- package/dist/client/clientPublicMainnet.d.ts +4 -4
- package/dist/client/clientPublicMainnet.d.ts.map +1 -1
- package/dist/client/clientPublicTestnet.d.ts +4 -4
- package/dist/client/clientPublicTestnet.d.ts.map +1 -1
- package/dist/client/clientPublicTestnet.js +3 -0
- package/dist/client/jsonRpc/index.d.ts +4 -0
- package/dist/client/jsonRpc/index.d.ts.map +1 -1
- package/dist/client/jsonRpc/index.js +11 -0
- package/dist/molecule/codec.d.ts +2 -0
- package/dist/molecule/codec.d.ts.map +1 -1
- package/dist/molecule/codec.js +51 -41
- package/dist/molecule/entity.d.ts +25 -4
- package/dist/molecule/entity.d.ts.map +1 -1
- package/dist/molecule/entity.js +22 -1
- package/dist/num/index.d.ts.map +1 -1
- package/dist/num/index.js +2 -2
- package/dist/signer/btc/verify.js +1 -1
- package/dist/signer/doge/verify.d.ts.map +1 -1
- package/dist/signer/doge/verify.js +3 -1
- package/dist.commonjs/address/address.advanced.d.ts.map +1 -1
- package/dist.commonjs/address/address.advanced.js +6 -2
- package/dist.commonjs/bytes/index.d.ts +21 -0
- package/dist.commonjs/bytes/index.d.ts.map +1 -1
- package/dist.commonjs/bytes/index.js +32 -4
- package/dist.commonjs/ckb/script.d.ts +1 -1
- package/dist.commonjs/ckb/script.d.ts.map +1 -1
- package/dist.commonjs/ckb/script.js +2 -4
- package/dist.commonjs/ckb/transaction.d.ts +19 -12
- package/dist.commonjs/ckb/transaction.d.ts.map +1 -1
- package/dist.commonjs/ckb/transaction.js +23 -38
- package/dist.commonjs/client/clientPublicMainnet.d.ts +4 -4
- package/dist.commonjs/client/clientPublicMainnet.d.ts.map +1 -1
- package/dist.commonjs/client/clientPublicTestnet.d.ts +4 -4
- package/dist.commonjs/client/clientPublicTestnet.d.ts.map +1 -1
- package/dist.commonjs/client/clientPublicTestnet.js +3 -0
- package/dist.commonjs/client/jsonRpc/index.d.ts +4 -0
- package/dist.commonjs/client/jsonRpc/index.d.ts.map +1 -1
- package/dist.commonjs/client/jsonRpc/index.js +11 -0
- package/dist.commonjs/molecule/codec.d.ts +2 -0
- package/dist.commonjs/molecule/codec.d.ts.map +1 -1
- package/dist.commonjs/molecule/codec.js +50 -40
- package/dist.commonjs/molecule/entity.d.ts +25 -4
- package/dist.commonjs/molecule/entity.d.ts.map +1 -1
- package/dist.commonjs/molecule/entity.js +22 -1
- package/dist.commonjs/num/index.d.ts.map +1 -1
- package/dist.commonjs/num/index.js +2 -2
- package/dist.commonjs/signer/btc/verify.js +1 -1
- package/dist.commonjs/signer/doge/verify.d.ts.map +1 -1
- package/dist.commonjs/signer/doge/verify.js +3 -1
- package/package.json +1 -1
- package/src/address/address.advanced.ts +6 -2
- package/src/bytes/index.ts +36 -6
- package/src/ckb/script.ts +5 -7
- package/src/ckb/transaction.ts +43 -58
- package/src/client/clientPublicMainnet.ts +4 -3
- package/src/client/clientPublicTestnet.ts +9 -3
- package/src/client/jsonRpc/index.ts +24 -1
- package/src/molecule/codec.ts +73 -61
- package/src/molecule/entity.ts +25 -5
- package/src/num/index.ts +2 -5
- package/src/signer/btc/verify.ts +1 -1
- package/src/signer/doge/verify.ts +3 -1
package/src/bytes/index.ts
CHANGED
|
@@ -10,6 +10,41 @@ export type Bytes = Uint8Array;
|
|
|
10
10
|
*/
|
|
11
11
|
export type BytesLike = string | Uint8Array | ArrayBuffer | ArrayLike<number>;
|
|
12
12
|
|
|
13
|
+
/**
|
|
14
|
+
* Concatenates multiple byte-like arrays to the first number array.
|
|
15
|
+
* @public
|
|
16
|
+
*
|
|
17
|
+
* @param result - The number array as result
|
|
18
|
+
* @param args - The byte-like arrays to concatenate.
|
|
19
|
+
* @returns The first number array
|
|
20
|
+
*
|
|
21
|
+
* @example
|
|
22
|
+
* ```typescript
|
|
23
|
+
* const concatenatedBytes = [1, 2];
|
|
24
|
+
* bytesConcatTo(
|
|
25
|
+
* concatenatedBytes
|
|
26
|
+
* new Uint8Array([3, 4]),
|
|
27
|
+
* "hello",
|
|
28
|
+
* [5, 6, 7]
|
|
29
|
+
* );
|
|
30
|
+
* console.log(concatenatedBytes); // Outputs [1, 2, 3, 4, /* bytes of "hello" *\/, 5, 6, 7]
|
|
31
|
+
* ```
|
|
32
|
+
*/
|
|
33
|
+
|
|
34
|
+
export function bytesConcatTo(
|
|
35
|
+
result: number[],
|
|
36
|
+
...args: BytesLike[]
|
|
37
|
+
): number[] {
|
|
38
|
+
return args.reduce((acc: number[], v) => {
|
|
39
|
+
const bytes = bytesFrom(v);
|
|
40
|
+
// Spread operator will cause call stack size exceeded
|
|
41
|
+
for (const byte of bytes) {
|
|
42
|
+
result.push(byte);
|
|
43
|
+
}
|
|
44
|
+
return acc;
|
|
45
|
+
}, result);
|
|
46
|
+
}
|
|
47
|
+
|
|
13
48
|
/**
|
|
14
49
|
* Concatenates multiple byte-like arrays into a single byte array.
|
|
15
50
|
* @public
|
|
@@ -30,12 +65,7 @@ export type BytesLike = string | Uint8Array | ArrayBuffer | ArrayLike<number>;
|
|
|
30
65
|
*/
|
|
31
66
|
|
|
32
67
|
export function bytesConcat(...args: BytesLike[]): Bytes {
|
|
33
|
-
return new Uint8Array(
|
|
34
|
-
args.reduce((acc: number[], v) => {
|
|
35
|
-
acc.push(...bytesFrom(v));
|
|
36
|
-
return acc;
|
|
37
|
-
}, []),
|
|
38
|
-
);
|
|
68
|
+
return new Uint8Array(bytesConcatTo([], ...args));
|
|
39
69
|
}
|
|
40
70
|
|
|
41
71
|
/**
|
package/src/ckb/script.ts
CHANGED
|
@@ -108,13 +108,11 @@ export type ScriptLike = {
|
|
|
108
108
|
* @public
|
|
109
109
|
*/
|
|
110
110
|
@mol.codec(
|
|
111
|
-
mol
|
|
112
|
-
.
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
})
|
|
117
|
-
.map({ outMap: (decoded) => Script.from(decoded) }),
|
|
111
|
+
mol.table({
|
|
112
|
+
codeHash: mol.Byte32,
|
|
113
|
+
hashType: HashTypeCodec,
|
|
114
|
+
args: mol.Bytes,
|
|
115
|
+
}),
|
|
118
116
|
)
|
|
119
117
|
export class Script extends mol.Entity.Base<ScriptLike, Script>() {
|
|
120
118
|
/**
|
package/src/ckb/transaction.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { ClientCollectableSearchKeyFilterLike } from "../advancedBarrel.js";
|
|
2
1
|
import { Bytes, BytesLike, bytesFrom } from "../bytes/index.js";
|
|
3
|
-
import {
|
|
2
|
+
import type { ClientCollectableSearchKeyFilterLike } from "../client/clientTypes.advanced.js";
|
|
3
|
+
import type { CellDepInfoLike, Client, KnownScript } from "../client/index.js";
|
|
4
4
|
import {
|
|
5
5
|
Zero,
|
|
6
6
|
fixedPointFrom,
|
|
@@ -17,11 +17,11 @@ import {
|
|
|
17
17
|
numToBytes,
|
|
18
18
|
numToHex,
|
|
19
19
|
} from "../num/index.js";
|
|
20
|
-
import { Signer } from "../signer/index.js";
|
|
20
|
+
import type { Signer } from "../signer/index.js";
|
|
21
21
|
import { apply, reduceAsync } from "../utils/index.js";
|
|
22
22
|
import { Script, ScriptLike, ScriptOpt } from "./script.js";
|
|
23
23
|
import { DEP_TYPE_TO_NUM, NUM_TO_DEP_TYPE } from "./transaction.advanced.js";
|
|
24
|
-
import { LumosTransactionSkeletonType } from "./transactionLumos.js";
|
|
24
|
+
import type { LumosTransactionSkeletonType } from "./transactionLumos.js";
|
|
25
25
|
|
|
26
26
|
export const DepTypeCodec: mol.Codec<DepTypeLike, DepType> = mol.Codec.from({
|
|
27
27
|
byteLength: 1,
|
|
@@ -119,12 +119,10 @@ export type OutPointLike = {
|
|
|
119
119
|
* @public
|
|
120
120
|
*/
|
|
121
121
|
@mol.codec(
|
|
122
|
-
mol
|
|
123
|
-
.
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
})
|
|
127
|
-
.map({ outMap: (decoded) => OutPoint.from(decoded) }),
|
|
122
|
+
mol.struct({
|
|
123
|
+
txHash: mol.Byte32,
|
|
124
|
+
index: mol.Uint32,
|
|
125
|
+
}),
|
|
128
126
|
)
|
|
129
127
|
export class OutPoint extends mol.Entity.Base<OutPointLike, OutPoint>() {
|
|
130
128
|
/**
|
|
@@ -172,13 +170,11 @@ export type CellOutputLike = {
|
|
|
172
170
|
* @public
|
|
173
171
|
*/
|
|
174
172
|
@mol.codec(
|
|
175
|
-
mol
|
|
176
|
-
.
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
})
|
|
181
|
-
.map({ outMap: (decoded) => CellOutput.from(decoded) }),
|
|
173
|
+
mol.table({
|
|
174
|
+
capacity: mol.Uint64,
|
|
175
|
+
lock: Script,
|
|
176
|
+
type: ScriptOpt,
|
|
177
|
+
}),
|
|
182
178
|
)
|
|
183
179
|
export class CellOutput extends mol.Entity.Base<CellOutputLike, CellOutput>() {
|
|
184
180
|
/**
|
|
@@ -347,10 +343,7 @@ export type SinceLike =
|
|
|
347
343
|
* @public
|
|
348
344
|
*/
|
|
349
345
|
@mol.codec(
|
|
350
|
-
mol.Uint64.
|
|
351
|
-
inMap: (encodable) => Since.from(encodable).toNum(),
|
|
352
|
-
outMap: (decoded) => Since.from(decoded),
|
|
353
|
-
}),
|
|
346
|
+
mol.Uint64.mapIn((encodable: SinceLike) => Since.from(encodable).toNum()),
|
|
354
347
|
)
|
|
355
348
|
export class Since extends mol.Entity.Base<SinceLike, Since>() {
|
|
356
349
|
/**
|
|
@@ -472,10 +465,10 @@ export type CellInputLike = {
|
|
|
472
465
|
since: Since,
|
|
473
466
|
previousOutput: OutPoint,
|
|
474
467
|
})
|
|
475
|
-
.
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
}),
|
|
468
|
+
.mapIn((encodable: CellInputLike) => ({
|
|
469
|
+
...encodable,
|
|
470
|
+
since: encodable.since ?? 0,
|
|
471
|
+
})),
|
|
479
472
|
)
|
|
480
473
|
export class CellInput extends mol.Entity.Base<CellInputLike, CellInput>() {
|
|
481
474
|
/**
|
|
@@ -560,12 +553,10 @@ export type CellDepLike = {
|
|
|
560
553
|
* @public
|
|
561
554
|
*/
|
|
562
555
|
@mol.codec(
|
|
563
|
-
mol
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
})
|
|
568
|
-
.map({ outMap: (decoded) => CellDep.from(decoded) }),
|
|
556
|
+
mol.struct({
|
|
557
|
+
outPoint: OutPoint,
|
|
558
|
+
depType: DepTypeCodec,
|
|
559
|
+
}),
|
|
569
560
|
)
|
|
570
561
|
export class CellDep extends mol.Entity.Base<CellDepLike, CellDep>() {
|
|
571
562
|
/**
|
|
@@ -637,13 +628,11 @@ export type WitnessArgsLike = {
|
|
|
637
628
|
* @public
|
|
638
629
|
*/
|
|
639
630
|
@mol.codec(
|
|
640
|
-
mol
|
|
641
|
-
.
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
})
|
|
646
|
-
.map({ outMap: (decoded) => WitnessArgs.from(decoded) }),
|
|
631
|
+
mol.table({
|
|
632
|
+
lock: mol.BytesOpt,
|
|
633
|
+
inputType: mol.BytesOpt,
|
|
634
|
+
outputType: mol.BytesOpt,
|
|
635
|
+
}),
|
|
647
636
|
)
|
|
648
637
|
export class WitnessArgs extends mol.Entity.Base<
|
|
649
638
|
WitnessArgsLike,
|
|
@@ -706,16 +695,14 @@ export function udtBalanceFrom(dataLike: BytesLike): Num {
|
|
|
706
695
|
return numFromBytes(data);
|
|
707
696
|
}
|
|
708
697
|
|
|
709
|
-
export const RawTransaction = mol
|
|
710
|
-
.
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
})
|
|
718
|
-
.map({ outMap: (decoded) => Transaction.from(decoded) });
|
|
698
|
+
export const RawTransaction = mol.table({
|
|
699
|
+
version: mol.Uint32,
|
|
700
|
+
cellDeps: CellDepVec,
|
|
701
|
+
headerDeps: mol.Byte32Vec,
|
|
702
|
+
inputs: CellInputVec,
|
|
703
|
+
outputs: CellOutputVec,
|
|
704
|
+
outputsData: mol.BytesVec,
|
|
705
|
+
});
|
|
719
706
|
|
|
720
707
|
/**
|
|
721
708
|
* @public
|
|
@@ -741,16 +728,14 @@ export type TransactionLike = {
|
|
|
741
728
|
raw: RawTransaction,
|
|
742
729
|
witnesses: mol.BytesVec,
|
|
743
730
|
})
|
|
744
|
-
.
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
outMap: (tx) => Transaction.from({ ...tx.raw, witnesses: tx.witnesses }),
|
|
753
|
-
}),
|
|
731
|
+
.mapIn((txLike: TransactionLike) => {
|
|
732
|
+
const tx = Transaction.from(txLike);
|
|
733
|
+
return {
|
|
734
|
+
raw: tx,
|
|
735
|
+
witnesses: tx.witnesses,
|
|
736
|
+
};
|
|
737
|
+
})
|
|
738
|
+
.mapOut((tx) => Transaction.from({ ...tx.raw, witnesses: tx.witnesses })),
|
|
754
739
|
)
|
|
755
740
|
export class Transaction extends mol.Entity.Base<
|
|
756
741
|
TransactionLike,
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import WebSocket from "isomorphic-ws";
|
|
2
2
|
import { ClientCache } from "./cache/index.js";
|
|
3
3
|
import { MAINNET_SCRIPTS } from "./clientPublicMainnet.advanced.js";
|
|
4
|
-
import { KnownScript, ScriptInfo } from "./clientTypes.js";
|
|
4
|
+
import { KnownScript, ScriptInfo, ScriptInfoLike } from "./clientTypes.js";
|
|
5
5
|
import { ClientJsonRpc } from "./jsonRpc/index.js";
|
|
6
6
|
|
|
7
7
|
/**
|
|
@@ -12,7 +12,8 @@ export class ClientPublicMainnet extends ClientJsonRpc {
|
|
|
12
12
|
private readonly config?: {
|
|
13
13
|
url?: string;
|
|
14
14
|
timeout?: number;
|
|
15
|
-
|
|
15
|
+
maxConcurrent?: number;
|
|
16
|
+
scripts?: Record<KnownScript, ScriptInfoLike | undefined>;
|
|
16
17
|
cache?: ClientCache;
|
|
17
18
|
},
|
|
18
19
|
) {
|
|
@@ -25,7 +26,7 @@ export class ClientPublicMainnet extends ClientJsonRpc {
|
|
|
25
26
|
);
|
|
26
27
|
}
|
|
27
28
|
|
|
28
|
-
get scripts():
|
|
29
|
+
get scripts(): Record<KnownScript, ScriptInfoLike | undefined> {
|
|
29
30
|
return this.config?.scripts ?? MAINNET_SCRIPTS;
|
|
30
31
|
}
|
|
31
32
|
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import WebSocket from "isomorphic-ws";
|
|
2
2
|
import { ClientCache } from "./cache/index.js";
|
|
3
3
|
import { TESTNET_SCRIPTS } from "./clientPublicTestnet.advanced.js";
|
|
4
|
-
import { KnownScript, ScriptInfo } from "./clientTypes.js";
|
|
4
|
+
import { KnownScript, ScriptInfo, ScriptInfoLike } from "./clientTypes.js";
|
|
5
5
|
import { ClientJsonRpc } from "./jsonRpc/index.js";
|
|
6
6
|
|
|
7
7
|
/**
|
|
@@ -12,7 +12,8 @@ export class ClientPublicTestnet extends ClientJsonRpc {
|
|
|
12
12
|
private readonly config?: {
|
|
13
13
|
url?: string;
|
|
14
14
|
timeout?: number;
|
|
15
|
-
|
|
15
|
+
maxConcurrent?: number;
|
|
16
|
+
scripts?: Record<KnownScript, ScriptInfoLike | undefined>,
|
|
16
17
|
cache?: ClientCache;
|
|
17
18
|
},
|
|
18
19
|
) {
|
|
@@ -25,7 +26,7 @@ export class ClientPublicTestnet extends ClientJsonRpc {
|
|
|
25
26
|
);
|
|
26
27
|
}
|
|
27
28
|
|
|
28
|
-
get scripts():
|
|
29
|
+
get scripts(): Record<KnownScript, ScriptInfoLike | undefined> {
|
|
29
30
|
return this.config?.scripts ?? TESTNET_SCRIPTS;
|
|
30
31
|
}
|
|
31
32
|
|
|
@@ -35,6 +36,11 @@ export class ClientPublicTestnet extends ClientJsonRpc {
|
|
|
35
36
|
|
|
36
37
|
async getKnownScript(script: KnownScript): Promise<ScriptInfo> {
|
|
37
38
|
const found = this.scripts[script];
|
|
39
|
+
if (!found) {
|
|
40
|
+
throw new Error(
|
|
41
|
+
`No script information was found for ${script} on ${this.addressPrefix}`,
|
|
42
|
+
);
|
|
43
|
+
}
|
|
38
44
|
return ScriptInfo.from(found);
|
|
39
45
|
}
|
|
40
46
|
}
|
|
@@ -95,6 +95,10 @@ const ERROR_PARSERS: [
|
|
|
95
95
|
*/
|
|
96
96
|
|
|
97
97
|
export abstract class ClientJsonRpc extends Client {
|
|
98
|
+
private readonly maxConcurrent?: number;
|
|
99
|
+
private concurrent = 0;
|
|
100
|
+
private readonly pending: (() => void)[] = [];
|
|
101
|
+
|
|
98
102
|
private id = 0;
|
|
99
103
|
private readonly transport: Transport;
|
|
100
104
|
|
|
@@ -107,10 +111,15 @@ export abstract class ClientJsonRpc extends Client {
|
|
|
107
111
|
|
|
108
112
|
constructor(
|
|
109
113
|
private readonly url_: string,
|
|
110
|
-
config?: {
|
|
114
|
+
config?: {
|
|
115
|
+
timeout?: number;
|
|
116
|
+
cache?: ClientCache;
|
|
117
|
+
maxConcurrent?: number;
|
|
118
|
+
},
|
|
111
119
|
) {
|
|
112
120
|
super(config);
|
|
113
121
|
|
|
122
|
+
this.maxConcurrent = config?.maxConcurrent;
|
|
114
123
|
this.transport = transportFromUri(url_, config);
|
|
115
124
|
}
|
|
116
125
|
|
|
@@ -433,11 +442,25 @@ export abstract class ClientJsonRpc extends Client {
|
|
|
433
442
|
* @throws Will throw an error if the response ID does not match the request ID, or if the response contains an error.
|
|
434
443
|
*/
|
|
435
444
|
async send(payload: JsonRpcPayload): Promise<unknown> {
|
|
445
|
+
if (
|
|
446
|
+
this.maxConcurrent !== undefined &&
|
|
447
|
+
this.concurrent >= this.maxConcurrent
|
|
448
|
+
) {
|
|
449
|
+
const pending = new Promise<void>((resolve) =>
|
|
450
|
+
this.pending.push(resolve),
|
|
451
|
+
);
|
|
452
|
+
await pending;
|
|
453
|
+
}
|
|
454
|
+
|
|
455
|
+
this.concurrent += 1;
|
|
436
456
|
const res = (await this.transport.request(payload)) as {
|
|
437
457
|
id: number;
|
|
438
458
|
error: unknown;
|
|
439
459
|
result: unknown;
|
|
440
460
|
};
|
|
461
|
+
this.concurrent -= 1;
|
|
462
|
+
this.pending.pop()?.();
|
|
463
|
+
|
|
441
464
|
if (res.id !== payload.id) {
|
|
442
465
|
throw new Error(`Id mismatched, got ${res.id}, expected ${payload.id}`);
|
|
443
466
|
}
|
package/src/molecule/codec.ts
CHANGED
|
@@ -1,6 +1,12 @@
|
|
|
1
1
|
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
2
2
|
|
|
3
|
-
import {
|
|
3
|
+
import {
|
|
4
|
+
Bytes,
|
|
5
|
+
bytesConcat,
|
|
6
|
+
bytesConcatTo,
|
|
7
|
+
bytesFrom,
|
|
8
|
+
BytesLike,
|
|
9
|
+
} from "../bytes/index.js";
|
|
4
10
|
import {
|
|
5
11
|
Num,
|
|
6
12
|
numBeFromBytes,
|
|
@@ -47,6 +53,18 @@ export class Codec<Encodable, Decoded = Encodable> {
|
|
|
47
53
|
: this.decode(buffer)) as NewDecoded,
|
|
48
54
|
});
|
|
49
55
|
}
|
|
56
|
+
|
|
57
|
+
mapIn<NewEncodable>(
|
|
58
|
+
map: (encodable: NewEncodable) => Encodable,
|
|
59
|
+
): Codec<NewEncodable, Decoded> {
|
|
60
|
+
return this.map({ inMap: map });
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
mapOut<NewDecoded>(
|
|
64
|
+
map: (decoded: Decoded) => NewDecoded,
|
|
65
|
+
): Codec<Encodable, NewDecoded> {
|
|
66
|
+
return this.map({ outMap: map });
|
|
67
|
+
}
|
|
50
68
|
}
|
|
51
69
|
|
|
52
70
|
export type EncodableType<T extends CodecLike<any, any>> =
|
|
@@ -77,10 +95,12 @@ export function fixedItemVec<Encodable, Decoded>(
|
|
|
77
95
|
return Codec.from({
|
|
78
96
|
encode(userDefinedItems) {
|
|
79
97
|
try {
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
98
|
+
const concatted: number[] = [];
|
|
99
|
+
bytesConcatTo(concatted, uint32To(userDefinedItems.length));
|
|
100
|
+
for (const item of userDefinedItems) {
|
|
101
|
+
bytesConcatTo(concatted, itemCodec.encode(item));
|
|
102
|
+
}
|
|
103
|
+
return bytesFrom(concatted);
|
|
84
104
|
} catch (e: unknown) {
|
|
85
105
|
throw new Error(`fixedItemVec(${e?.toString()})`);
|
|
86
106
|
}
|
|
@@ -125,26 +145,19 @@ export function dynItemVec<Encodable, Decoded>(
|
|
|
125
145
|
return Codec.from({
|
|
126
146
|
encode(userDefinedItems) {
|
|
127
147
|
try {
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
offset: 4 + userDefinedItems.length * 4,
|
|
142
|
-
},
|
|
143
|
-
);
|
|
144
|
-
const packedTotalSize = uint32To(
|
|
145
|
-
encoded.header.byteLength + encoded.body.byteLength + 4,
|
|
146
|
-
);
|
|
147
|
-
return bytesConcat(packedTotalSize, encoded.header, encoded.body);
|
|
148
|
+
let offset = 4 + userDefinedItems.length * 4;
|
|
149
|
+
const header: number[] = [];
|
|
150
|
+
const body: number[] = [];
|
|
151
|
+
|
|
152
|
+
for (const item of userDefinedItems) {
|
|
153
|
+
const encoded = itemCodec.encode(item);
|
|
154
|
+
bytesConcatTo(header, uint32To(offset));
|
|
155
|
+
bytesConcatTo(body, encoded);
|
|
156
|
+
offset += encoded.byteLength;
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
const packedTotalSize = uint32To(header.length + body.length + 4);
|
|
160
|
+
return bytesConcat(packedTotalSize, header, body);
|
|
148
161
|
} catch (e) {
|
|
149
162
|
throw new Error(`dynItemVec(${e?.toString()})`);
|
|
150
163
|
}
|
|
@@ -317,29 +330,22 @@ export function table<
|
|
|
317
330
|
|
|
318
331
|
return Codec.from({
|
|
319
332
|
encode(object) {
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
const
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
{
|
|
337
|
-
header: bytesFrom([]),
|
|
338
|
-
body: bytesFrom([]),
|
|
339
|
-
offset: headerLength,
|
|
340
|
-
},
|
|
341
|
-
);
|
|
342
|
-
const packedTotalSize = uint32To(header.byteLength + body.byteLength + 4);
|
|
333
|
+
let offset = 4 + keys.length * 4;
|
|
334
|
+
const header: number[] = [];
|
|
335
|
+
const body: number[] = [];
|
|
336
|
+
|
|
337
|
+
for (const key of keys) {
|
|
338
|
+
try {
|
|
339
|
+
const encoded = codecLayout[key].encode((object as any)[key]);
|
|
340
|
+
bytesConcatTo(header, uint32To(offset));
|
|
341
|
+
bytesConcatTo(body, encoded);
|
|
342
|
+
offset += encoded.byteLength;
|
|
343
|
+
} catch (e: unknown) {
|
|
344
|
+
throw new Error(`table.${key}(${e?.toString()})`);
|
|
345
|
+
}
|
|
346
|
+
}
|
|
347
|
+
|
|
348
|
+
const packedTotalSize = uint32To(header.length + body.length + 4);
|
|
343
349
|
return bytesConcat(packedTotalSize, header, body);
|
|
344
350
|
},
|
|
345
351
|
decode(buffer) {
|
|
@@ -482,23 +488,27 @@ export function struct<
|
|
|
482
488
|
Decoded extends DecodedRecord<T>,
|
|
483
489
|
>(codecLayout: T): Codec<Encodable, Decoded> {
|
|
484
490
|
const codecArray = Object.values(codecLayout);
|
|
485
|
-
if (codecArray.some((codec) => codec.byteLength === undefined)) {
|
|
486
|
-
throw new Error("struct: all fields must be fixed-size");
|
|
487
|
-
}
|
|
488
|
-
|
|
489
491
|
const keys = Object.keys(codecLayout);
|
|
490
492
|
|
|
491
493
|
return Codec.from({
|
|
492
|
-
byteLength: codecArray.reduce((
|
|
494
|
+
byteLength: codecArray.reduce((acc, codec) => {
|
|
495
|
+
if (codec.byteLength === undefined) {
|
|
496
|
+
throw new Error("struct: all fields must be fixed-size");
|
|
497
|
+
}
|
|
498
|
+
return acc + codec.byteLength;
|
|
499
|
+
}, 0),
|
|
493
500
|
encode(object) {
|
|
494
|
-
|
|
501
|
+
const bytes: number[] = [];
|
|
502
|
+
for (const key of keys) {
|
|
495
503
|
try {
|
|
496
|
-
const
|
|
497
|
-
|
|
504
|
+
const encoded = codecLayout[key].encode((object as any)[key]);
|
|
505
|
+
bytesConcatTo(bytes, encoded);
|
|
498
506
|
} catch (e: unknown) {
|
|
499
507
|
throw new Error(`struct.${key}(${e?.toString()})`);
|
|
500
508
|
}
|
|
501
|
-
}
|
|
509
|
+
}
|
|
510
|
+
|
|
511
|
+
return bytesFrom(bytes);
|
|
502
512
|
},
|
|
503
513
|
decode(buffer) {
|
|
504
514
|
const value = bytesFrom(buffer);
|
|
@@ -538,10 +548,12 @@ export function array<Encodable, Decoded>(
|
|
|
538
548
|
byteLength,
|
|
539
549
|
encode(items) {
|
|
540
550
|
try {
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
551
|
+
const bytes: number[] = [];
|
|
552
|
+
for (const item of items) {
|
|
553
|
+
bytesConcatTo(bytes, itemCodec.encode(item));
|
|
554
|
+
}
|
|
555
|
+
|
|
556
|
+
return bytesFrom(bytes);
|
|
545
557
|
} catch (e: unknown) {
|
|
546
558
|
throw new Error(`array(${e?.toString()})`);
|
|
547
559
|
}
|
package/src/molecule/entity.ts
CHANGED
|
@@ -1,13 +1,19 @@
|
|
|
1
1
|
import { Bytes, bytesEq, BytesLike } from "../bytes/index.js";
|
|
2
2
|
import { hashCkb } from "../hasher/index.js";
|
|
3
3
|
import { Hex } from "../hex/index.js";
|
|
4
|
+
import { Constructor } from "../utils/index.js";
|
|
4
5
|
import { Codec } from "./codec.js";
|
|
5
6
|
|
|
6
7
|
/**
|
|
7
|
-
* The base class of CCC to create a serializable instance
|
|
8
|
+
* The base class of CCC to create a serializable instance. This should be used with the {@link codec} decorator.
|
|
8
9
|
* @public
|
|
9
10
|
*/
|
|
10
11
|
export abstract class Entity {
|
|
12
|
+
/**
|
|
13
|
+
* Generate a base class of CCC to create a serializable instance.
|
|
14
|
+
* This should be used with the {@link codec} decorator.
|
|
15
|
+
* @public
|
|
16
|
+
*/
|
|
11
17
|
static Base<SubTypeLike, SubType = SubTypeLike>() {
|
|
12
18
|
abstract class Impl {
|
|
13
19
|
/**
|
|
@@ -97,7 +103,7 @@ export abstract class Entity {
|
|
|
97
103
|
* @param other - The other entity to compare with
|
|
98
104
|
* @returns True if the entities are equal, false otherwise
|
|
99
105
|
*/
|
|
100
|
-
eq(other: SubTypeLike
|
|
106
|
+
eq(other: SubTypeLike): boolean {
|
|
101
107
|
if (this === (other as unknown as this)) {
|
|
102
108
|
return true;
|
|
103
109
|
}
|
|
@@ -130,14 +136,28 @@ export abstract class Entity {
|
|
|
130
136
|
abstract clone(): Entity;
|
|
131
137
|
}
|
|
132
138
|
|
|
139
|
+
/**
|
|
140
|
+
* A class decorator to add methods implementation on the {@link Entity.Base} class
|
|
141
|
+
* @example
|
|
142
|
+
* ```typescript
|
|
143
|
+
* @mol.codec(
|
|
144
|
+
* mol.table({
|
|
145
|
+
* codeHash: mol.Byte32,
|
|
146
|
+
* hashType: HashTypeCodec,
|
|
147
|
+
* args: mol.Bytes,
|
|
148
|
+
* }),
|
|
149
|
+
* )
|
|
150
|
+
* export class Script extends mol.Entity.Base<ScriptLike, Script>() {
|
|
151
|
+
* from(scriptLike: ScriptLike): Script {}
|
|
152
|
+
* }
|
|
153
|
+
* ```
|
|
154
|
+
*/
|
|
133
155
|
export function codec<
|
|
134
156
|
Encodable,
|
|
135
157
|
TypeLike extends Encodable,
|
|
136
158
|
Decoded extends TypeLike,
|
|
137
159
|
Type extends object & TypeLike,
|
|
138
|
-
ConstructorType extends {
|
|
139
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
140
|
-
new (...args: any[]): Type;
|
|
160
|
+
ConstructorType extends Constructor<Type> & {
|
|
141
161
|
from(decoded: TypeLike): Type;
|
|
142
162
|
byteLength?: number;
|
|
143
163
|
encode(encodable: TypeLike): Bytes;
|
package/src/num/index.ts
CHANGED
|
@@ -155,10 +155,7 @@ export function numBeToBytes(val: NumLike, bytes?: number): Bytes {
|
|
|
155
155
|
return rawBytes;
|
|
156
156
|
}
|
|
157
157
|
|
|
158
|
-
return bytesConcat(
|
|
159
|
-
Array.from(Array(bytes - rawBytes.length), () => 0),
|
|
160
|
-
rawBytes,
|
|
161
|
-
);
|
|
158
|
+
return bytesConcat("00".repeat(bytes - rawBytes.length), rawBytes);
|
|
162
159
|
}
|
|
163
160
|
|
|
164
161
|
/**
|
|
@@ -190,7 +187,7 @@ export function numFromBytes(val: BytesLike): Num {
|
|
|
190
187
|
* ```
|
|
191
188
|
*/
|
|
192
189
|
export function numLeFromBytes(val: BytesLike): Num {
|
|
193
|
-
return numBeFromBytes(
|
|
190
|
+
return numBeFromBytes(bytesFrom(val).reverse());
|
|
194
191
|
}
|
|
195
192
|
|
|
196
193
|
/**
|
package/src/signer/btc/verify.ts
CHANGED
|
@@ -43,7 +43,7 @@ export function verifyMessageBtcEcdsa(
|
|
|
43
43
|
const challenge =
|
|
44
44
|
typeof message === "string" ? message : hexFrom(message).slice(2);
|
|
45
45
|
|
|
46
|
-
const
|
|
46
|
+
const rawSign = bytesFrom(signature, "base64").slice(1);
|
|
47
47
|
|
|
48
48
|
return secp256k1.verify(bytesFrom(rawSign), magicHash(challenge), publicKey);
|
|
49
49
|
}
|
|
@@ -17,7 +17,9 @@ export function verifyMessageDogeEcdsa(
|
|
|
17
17
|
): boolean {
|
|
18
18
|
const challenge =
|
|
19
19
|
typeof message === "string" ? message : hexFrom(message).slice(2);
|
|
20
|
-
const
|
|
20
|
+
const signatureBytes = bytesFrom(signature, "base64");
|
|
21
|
+
const recoveryBit = signatureBytes[0];
|
|
22
|
+
const rawSign = signatureBytes.slice(1);
|
|
21
23
|
|
|
22
24
|
const sig = secp256k1.Signature.fromCompact(
|
|
23
25
|
hexFrom(rawSign).slice(2),
|