@ckb-ccc/core 1.0.0 → 1.0.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 (55) hide show
  1. package/CHANGELOG.md +8 -0
  2. package/dist/address/address.advanced.d.ts.map +1 -1
  3. package/dist/address/address.advanced.js +6 -2
  4. package/dist/bytes/index.d.ts +21 -0
  5. package/dist/bytes/index.d.ts.map +1 -1
  6. package/dist/bytes/index.js +31 -4
  7. package/dist/ckb/script.d.ts +1 -1
  8. package/dist/ckb/script.d.ts.map +1 -1
  9. package/dist/ckb/script.js +2 -4
  10. package/dist/ckb/transaction.d.ts +19 -12
  11. package/dist/ckb/transaction.d.ts.map +1 -1
  12. package/dist/ckb/transaction.js +23 -38
  13. package/dist/molecule/codec.d.ts +2 -0
  14. package/dist/molecule/codec.d.ts.map +1 -1
  15. package/dist/molecule/codec.js +51 -41
  16. package/dist/molecule/entity.d.ts +25 -4
  17. package/dist/molecule/entity.d.ts.map +1 -1
  18. package/dist/molecule/entity.js +22 -1
  19. package/dist/num/index.d.ts.map +1 -1
  20. package/dist/num/index.js +2 -2
  21. package/dist/signer/btc/verify.js +1 -1
  22. package/dist/signer/doge/verify.d.ts.map +1 -1
  23. package/dist/signer/doge/verify.js +3 -1
  24. package/dist.commonjs/address/address.advanced.d.ts.map +1 -1
  25. package/dist.commonjs/address/address.advanced.js +6 -2
  26. package/dist.commonjs/bytes/index.d.ts +21 -0
  27. package/dist.commonjs/bytes/index.d.ts.map +1 -1
  28. package/dist.commonjs/bytes/index.js +32 -4
  29. package/dist.commonjs/ckb/script.d.ts +1 -1
  30. package/dist.commonjs/ckb/script.d.ts.map +1 -1
  31. package/dist.commonjs/ckb/script.js +2 -4
  32. package/dist.commonjs/ckb/transaction.d.ts +19 -12
  33. package/dist.commonjs/ckb/transaction.d.ts.map +1 -1
  34. package/dist.commonjs/ckb/transaction.js +23 -38
  35. package/dist.commonjs/molecule/codec.d.ts +2 -0
  36. package/dist.commonjs/molecule/codec.d.ts.map +1 -1
  37. package/dist.commonjs/molecule/codec.js +50 -40
  38. package/dist.commonjs/molecule/entity.d.ts +25 -4
  39. package/dist.commonjs/molecule/entity.d.ts.map +1 -1
  40. package/dist.commonjs/molecule/entity.js +22 -1
  41. package/dist.commonjs/num/index.d.ts.map +1 -1
  42. package/dist.commonjs/num/index.js +2 -2
  43. package/dist.commonjs/signer/btc/verify.js +1 -1
  44. package/dist.commonjs/signer/doge/verify.d.ts.map +1 -1
  45. package/dist.commonjs/signer/doge/verify.js +3 -1
  46. package/package.json +1 -1
  47. package/src/address/address.advanced.ts +6 -2
  48. package/src/bytes/index.ts +36 -6
  49. package/src/ckb/script.ts +5 -7
  50. package/src/ckb/transaction.ts +43 -58
  51. package/src/molecule/codec.ts +73 -61
  52. package/src/molecule/entity.ts +25 -5
  53. package/src/num/index.ts +2 -5
  54. package/src/signer/btc/verify.ts +1 -1
  55. package/src/signer/doge/verify.ts +3 -1
@@ -1,6 +1,12 @@
1
1
  /* eslint-disable @typescript-eslint/no-explicit-any */
2
2
 
3
- import { Bytes, bytesConcat, bytesFrom, BytesLike } from "../bytes/index.js";
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
- return userDefinedItems.reduce(
81
- (concatted, item) => bytesConcat(concatted, itemCodec.encode(item)),
82
- uint32To(userDefinedItems.length),
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
- const encoded = userDefinedItems.reduce(
129
- ({ offset, header, body }, item) => {
130
- const encodedItem = itemCodec.encode(item);
131
- const packedHeader = uint32To(offset);
132
- return {
133
- header: bytesConcat(header, packedHeader),
134
- body: bytesConcat(body, encodedItem),
135
- offset: offset + bytesFrom(encodedItem).byteLength,
136
- };
137
- },
138
- {
139
- header: bytesFrom([]),
140
- body: bytesFrom([]),
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
- const headerLength = 4 + keys.length * 4;
321
-
322
- const { header, body } = keys.reduce(
323
- (result, key) => {
324
- try {
325
- const encodedItem = codecLayout[key].encode((object as any)[key]);
326
- const packedOffset = uint32To(result.offset);
327
- return {
328
- header: bytesConcat(result.header, packedOffset),
329
- body: bytesConcat(result.body, encodedItem),
330
- offset: result.offset + bytesFrom(encodedItem).byteLength,
331
- };
332
- } catch (e: unknown) {
333
- throw new Error(`table.${key}(${e?.toString()})`);
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((sum, codec) => sum + codec.byteLength!, 0),
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
- return keys.reduce((result, key) => {
501
+ const bytes: number[] = [];
502
+ for (const key of keys) {
495
503
  try {
496
- const encodedItem = codecLayout[key].encode((object as any)[key]);
497
- return bytesConcat(result, encodedItem);
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
- }, bytesFrom([]));
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
- return items.reduce(
542
- (concatted, item) => bytesConcat(concatted, itemCodec.encode(item)),
543
- bytesFrom([]),
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
  }
@@ -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 | SubType): boolean {
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([...bytesFrom(val)].reverse());
190
+ return numBeFromBytes(bytesFrom(val).reverse());
194
191
  }
195
192
 
196
193
  /**
@@ -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 [_, ...rawSign] = bytesFrom(signature, "base64");
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 [recoveryBit, ...rawSign] = bytesFrom(signature, "base64");
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),