Skip to content

Commit 098d053

Browse files
committed
feat(core): add Encodable type for wider hex like types
1 parent d4a3188 commit 098d053

File tree

20 files changed

+163
-110
lines changed

20 files changed

+163
-110
lines changed

packages/core/src/address/index.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import { bech32m } from "bech32";
22
import { bytesConcat, bytesFrom } from "../bytes/index.js";
33
import { Script, ScriptLike, hashTypeToBytes } from "../ckb/index.js";
44
import { Client, KnownScript } from "../client/index.js";
5+
import { Encodable } from "../codec/index.js";
56
import { HexLike } from "../hex/index.js";
67
import {
78
ADDRESS_BECH32_LIMIT,
@@ -96,7 +97,7 @@ export class Address {
9697
static async fromKnownScript(
9798
client: Client,
9899
script: KnownScript,
99-
args: HexLike,
100+
args: Encodable,
100101
): Promise<Address> {
101102
return Address.from({
102103
script: await Script.fromKnownScript(client, script, args),

packages/core/src/ckb/hash.ts

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,5 @@ export function hashTypeId(
2121
cellInputLike: CellInputLike,
2222
outputIndex: NumLike,
2323
): Hex {
24-
return hashCkb(
25-
CellInput.from(cellInputLike).toBytes(),
26-
numLeToBytes(outputIndex, 8),
27-
);
24+
return hashCkb(CellInput.from(cellInputLike), numLeToBytes(outputIndex, 8));
2825
}

packages/core/src/ckb/script.ts

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { Bytes, BytesLike, bytesFrom } from "../bytes/index.js";
22
import type { Client } from "../client/index.js";
33
import { KnownScript } from "../client/knownScript.js";
4-
import { Codec, Entity, codec } from "../codec/index.js";
4+
import { Codec, Encodable, Entity, codec, encodableToHex } from "../codec/index.js";
55
import { Hex, HexLike, hexFrom } from "../hex/index.js";
66
import { mol } from "../molecule/index.js";
77
import {
@@ -102,9 +102,9 @@ export function hashTypeFromBytes(bytes: BytesLike): HashType {
102102
* @public
103103
*/
104104
export type ScriptLike = {
105-
codeHash: BytesLike;
105+
codeHash: Encodable;
106106
hashType: HashTypeLike;
107-
args: BytesLike;
107+
args: Encodable;
108108
};
109109
/**
110110
* @public
@@ -192,9 +192,9 @@ export class Script extends Entity.Base<ScriptLike, Script>() {
192192
}
193193

194194
return new Script(
195-
hexFrom(script.codeHash),
195+
encodableToHex(script.codeHash),
196196
hashTypeFrom(script.hashType),
197-
hexFrom(script.args),
197+
encodableToHex(script.args),
198198
);
199199
}
200200

@@ -219,10 +219,10 @@ export class Script extends Entity.Base<ScriptLike, Script>() {
219219
static async fromKnownScript(
220220
client: Client,
221221
knownScript: KnownScript,
222-
args: HexLike,
222+
args: Encodable,
223223
): Promise<Script> {
224224
const script = await client.getKnownScript(knownScript);
225-
return new Script(script.codeHash, script.hashType, hexFrom(args));
225+
return new Script(script.codeHash, script.hashType, encodableToHex(args));
226226
}
227227

228228
/**

packages/core/src/ckb/transaction.ts

Lines changed: 35 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,13 @@ import {
77
type ClientBlockHeaderLike,
88
} from "../client/index.js";
99
import { KnownScript } from "../client/knownScript.js";
10-
import { Codec, Entity, codec } from "../codec/index.js";
10+
import {
11+
Codec,
12+
Encodable,
13+
Entity,
14+
codec,
15+
encodableToHex,
16+
} from "../codec/index.js";
1117
import { Zero, fixedPointFrom } from "../fixedPoint/index.js";
1218
import { Hasher, HasherCkb, hashCkb } from "../hasher/index.js";
1319
import { Hex, HexLike, hexFrom } from "../hex/index.js";
@@ -121,7 +127,7 @@ export function depTypeFromBytes(bytes: BytesLike): DepType {
121127
* @public
122128
*/
123129
export type OutPointLike = {
124-
txHash: HexLike;
130+
txHash: Encodable;
125131
index: NumLike;
126132
};
127133
/**
@@ -163,7 +169,10 @@ export class OutPoint extends Entity.Base<OutPointLike, OutPoint>() {
163169
if (outPoint instanceof OutPoint) {
164170
return outPoint;
165171
}
166-
return new OutPoint(hexFrom(outPoint.txHash), numFrom(outPoint.index));
172+
return new OutPoint(
173+
encodableToHex(outPoint.txHash),
174+
numFrom(outPoint.index),
175+
);
167176
}
168177

169178
/**
@@ -263,7 +272,7 @@ export class CellOutput extends Entity.Base<CellOutputLike, CellOutput>() {
263272
*/
264273
static from(
265274
cellOutput: CellOutputLike,
266-
outputData?: HexLike | null,
275+
outputData?: Encodable | null,
267276
): CellOutput {
268277
const output = (() => {
269278
if (cellOutput instanceof CellOutput) {
@@ -279,7 +288,9 @@ export class CellOutput extends Entity.Base<CellOutputLike, CellOutput>() {
279288
if (outputData != null) {
280289
output.capacity = numMax(
281290
output.capacity,
282-
fixedPointFrom(output.occupiedSize + bytesFrom(outputData).length),
291+
fixedPointFrom(
292+
output.occupiedSize + encodableToBytes(outputData).length,
293+
),
283294
);
284295
}
285296

@@ -783,7 +794,7 @@ export type CellInputLike = (
783794
) & {
784795
since?: SinceLike | NumLike | null;
785796
cellOutput?: CellOutputLike | null;
786-
outputData?: HexLike | null;
797+
outputData?: Encodable | null;
787798
};
788799
/**
789800
* @public
@@ -840,10 +851,11 @@ export class CellInput extends Entity.Base<CellInputLike, CellInput>() {
840851
? cellInput.previousOutput
841852
: cellInput.outPoint,
842853
),
843-
Since.from(cellInput.since ?? 0).toNum(),
854+
numFrom(cellInput.since ?? 0),
844855
apply(CellOutput.from, cellInput.cellOutput),
845-
apply(hexFrom, cellInput.outputData),
856+
apply(encodableToHex, cellInput.outputData),
846857
);
858+
847859
}
848860

849861
async getCell(client: Client): Promise<Cell> {
@@ -992,9 +1004,9 @@ export const CellDepVec = mol.vector(CellDep);
9921004
* @public
9931005
*/
9941006
export type WitnessArgsLike = {
995-
lock?: HexLike | null;
996-
inputType?: HexLike | null;
997-
outputType?: HexLike | null;
1007+
lock?: Encodable | null;
1008+
inputType?: Encodable | null;
1009+
outputType?: Encodable | null;
9981010
};
9991011
/**
10001012
* @public
@@ -1045,9 +1057,9 @@ export class WitnessArgs extends Entity.Base<WitnessArgsLike, WitnessArgs>() {
10451057
}
10461058

10471059
return new WitnessArgs(
1048-
apply(hexFrom, witnessArgs.lock),
1049-
apply(hexFrom, witnessArgs.inputType),
1050-
apply(hexFrom, witnessArgs.outputType),
1060+
apply(encodableToHex, witnessArgs.lock),
1061+
apply(encodableToHex, witnessArgs.inputType),
1062+
apply(encodableToHex, witnessArgs.outputType),
10511063
);
10521064
}
10531065
}
@@ -1083,8 +1095,8 @@ export type TransactionLike = {
10831095
| (Omit<CellOutputLike, "capacity"> &
10841096
Partial<Pick<CellOutputLike, "capacity">>)[]
10851097
| null;
1086-
outputsData?: HexLike[] | null;
1087-
witnesses?: HexLike[] | null;
1098+
outputsData?: Encodable[] | null;
1099+
witnesses?: Encodable[] | null;
10881100
};
10891101
/**
10901102
* @public
@@ -1243,11 +1255,13 @@ export class Transaction extends Entity.Base<TransactionLike, Transaction>() {
12431255
CellOutput.from(output, tx.outputsData?.[i] ?? []),
12441256
) ?? [];
12451257
const outputsData = outputs.map((_, i) =>
1246-
hexFrom(tx.outputsData?.[i] ?? "0x"),
1258+
encodableToHex(tx.outputsData?.[i] ?? "0x"),
12471259
);
12481260
if (tx.outputsData != null && outputsData.length < tx.outputsData.length) {
12491261
outputsData.push(
1250-
...tx.outputsData.slice(outputsData.length).map((d) => hexFrom(d)),
1262+
...tx.outputsData
1263+
.slice(outputsData.length)
1264+
.map((d) => encodableToHex(d)),
12511265
);
12521266
}
12531267

@@ -1258,7 +1272,7 @@ export class Transaction extends Entity.Base<TransactionLike, Transaction>() {
12581272
tx.inputs?.map((input) => CellInput.from(input)) ?? [],
12591273
outputs,
12601274
outputsData,
1261-
tx.witnesses?.map(hexFrom) ?? [],
1275+
tx.witnesses?.map(encodableToHex) ?? [],
12621276
);
12631277
}
12641278

@@ -1808,8 +1822,8 @@ export class Transaction extends Entity.Base<TransactionLike, Transaction>() {
18081822
* await tx.setWitnessArgsAt(0, witnessArgs);
18091823
* ```
18101824
*/
1811-
setWitnessArgsAt(index: number, witness: WitnessArgs): void {
1812-
this.setWitnessAt(index, witness.toBytes());
1825+
setWitnessArgsAt(index: number, witness: WitnessArgsLike): void {
1826+
this.setWitnessAt(index, WitnessArgs.from(witness).toBytes());
18131827
}
18141828

18151829
/**

packages/core/src/client/cache/memory.ts

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ export class ClientCacheMemory extends ClientCache {
7777
): Promise<void> {
7878
cellLikes.flat().forEach((cellLike) => {
7979
const cell = Cell.from(cellLike).clone();
80-
const outPointStr = hexFrom(cell.outPoint.toBytes());
80+
const outPointStr = cell.outPoint.toHex();
8181

8282
this.cells.set(outPointStr, [true, cell]);
8383
});
@@ -88,7 +88,7 @@ export class ClientCacheMemory extends ClientCache {
8888
): Promise<void> {
8989
outPointLikes.flat().forEach((outPointLike) => {
9090
const outPoint = OutPoint.from(outPointLike);
91-
const outPointStr = hexFrom(outPoint.toBytes());
91+
const outPointStr = outPoint.toHex();
9292

9393
const existed = this.cells.get(outPointStr);
9494
if (existed) {
@@ -123,13 +123,13 @@ export class ClientCacheMemory extends ClientCache {
123123
async isUnusable(outPointLike: OutPointLike): Promise<boolean> {
124124
const outPoint = OutPoint.from(outPointLike);
125125

126-
return !(this.cells.get(hexFrom(outPoint.toBytes()))?.[0] ?? true);
126+
return !(this.cells.get(outPoint.toHex())?.[0] ?? true);
127127
}
128128

129129
async recordCells(...cells: (CellLike | CellLike[])[]): Promise<void> {
130130
cells.flat().map((cellLike) => {
131131
const cell = Cell.from(cellLike);
132-
const outPointStr = hexFrom(cell.outPoint.toBytes());
132+
const outPointStr = cell.outPoint.toHex();
133133

134134
if (this.cells.get(outPointStr)) {
135135
return;
@@ -140,7 +140,7 @@ export class ClientCacheMemory extends ClientCache {
140140
async getCell(outPointLike: OutPointLike): Promise<Cell | undefined> {
141141
const outPoint = OutPoint.from(outPointLike);
142142

143-
const cell = this.cells.get(hexFrom(outPoint.toBytes()))?.[1];
143+
const cell = this.cells.get(outPoint.toHex())?.[1];
144144
if (cell && cell.cellOutput && cell.outputData) {
145145
return Cell.from((cell as Cell).clone());
146146
}

packages/core/src/codec/entity.ts

Lines changed: 49 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { Bytes, bytesEq, bytesFrom, BytesLike } from "../bytes/index.js";
22
import { hashCkb } from "../hasher/index.js";
3-
import { Hex, hexFrom } from "../hex/index.js";
3+
import { Hex, hexFrom, HexLike } from "../hex/index.js";
44
import { Constructor } from "../utils/index.js";
55

66
/**
@@ -123,7 +123,7 @@ export abstract class Entity {
123123
* @returns The hash of the entity
124124
*/
125125
hash(): Hex {
126-
return hashCkb(this.toBytes());
126+
return hashCkb(this);
127127
}
128128

129129
/**
@@ -151,6 +151,53 @@ export abstract class Entity {
151151
abstract clone(): Entity;
152152
}
153153

154+
/**
155+
* Represents any type that can be encoded into bytes or hex.
156+
* @public
157+
*/
158+
export type Encodable =
159+
| BytesLike
160+
| { toBytes(): BytesLike }
161+
| { toHex(): HexLike };
162+
163+
/**
164+
* Converts an {@link Encodable} object to {@link Bytes}.
165+
*
166+
* @param entity - The encodable object.
167+
* @returns The bytes representation.
168+
* @public
169+
*/
170+
export function encodableToBytes(entity: Encodable): Bytes {
171+
if (entity instanceof Object) {
172+
if ("toBytes" in entity) {
173+
return bytesFrom(entity.toBytes());
174+
} else if ("toHex" in entity) {
175+
return bytesFrom(entity.toHex());
176+
}
177+
}
178+
179+
return bytesFrom(entity);
180+
}
181+
182+
/**
183+
* Converts an {@link Encodable} object to {@link Hex}.
184+
*
185+
* @param entity - The encodable object.
186+
* @returns The hex representation.
187+
* @public
188+
*/
189+
export function encodableToHex(entity: Encodable): Hex {
190+
if (entity instanceof Object) {
191+
if ("toBytes" in entity) {
192+
return hexFrom(entity.toBytes());
193+
} else if ("toHex" in entity) {
194+
return hexFrom(entity.toHex());
195+
}
196+
}
197+
198+
return hexFrom(entity);
199+
}
200+
154201
/**
155202
* A class decorator to add methods implementation on the {@link Entity.Base} class
156203
* @example

packages/core/src/hasher/hasherCkb.ts

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import { blake2b } from "@noble/hashes/blake2.js";
2-
import { BytesLike, bytesFrom } from "../bytes/index.js";
2+
import { BytesLike } from "../bytes/index.js";
3+
import { Encodable, encodableToBytes } from "../codec/index.js";
34
import { Hex, hexFrom } from "../hex/index.js";
45
import { CKB_BLAKE2B_PERSONAL } from "./advanced.js";
56
import { Hasher } from "./hasher.js";
@@ -41,8 +42,8 @@ export class HasherCkb implements Hasher {
4142
* ```
4243
*/
4344

44-
update(data: BytesLike): HasherCkb {
45-
this.hasher.update(bytesFrom(data));
45+
update(data: Encodable): HasherCkb {
46+
this.hasher.update(encodableToBytes(data));
4647
return this;
4748
}
4849

@@ -76,12 +77,12 @@ export class HasherCkb implements Hasher {
7677
* const hash = hashCkb("some data"); // Outputs something like "0x..."
7778
* ```
7879
*/
79-
export function hashCkb(...data: BytesLike[]): Hex {
80+
export function hashCkb(...data: Encodable[]): Hex {
8081
const hasher = new HasherCkb();
8182
data.forEach((d) => hasher.update(d));
8283
return hasher.digest();
8384
}
8485

85-
export function hashCkbShort(...data: BytesLike[]): Hex {
86+
export function hashCkbShort(...data: Encodable[]): Hex {
8687
return hashCkb(...data).slice(0, HASH_CKB_SHORT_LENGTH * 2 + 2) as Hex;
8788
}

packages/core/src/signer/btc/signerBtc.ts

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -124,19 +124,17 @@ export abstract class SignerBtc extends Signer {
124124
);
125125
signature[0] = 31 + ((signature[0] - 27) % 4);
126126

127-
const witness = WitnessArgs.fromBytes(tx.witnesses[info.position]);
128-
witness.lock = hexFrom(
129-
bytesConcat(
127+
tx.setWitnessArgsAt(info.position, {
128+
...(tx.getWitnessArgsAt(info.position) ?? {}),
129+
lock: bytesConcat(
130130
numToBytes(5 * 4 + signature.length, 4),
131131
numToBytes(4 * 4, 4),
132132
numToBytes(5 * 4 + signature.length, 4),
133133
numToBytes(5 * 4 + signature.length, 4),
134134
numToBytes(signature.length, 4),
135135
signature,
136136
),
137-
);
138-
139-
tx.setWitnessArgsAt(info.position, witness);
137+
});
140138
return tx;
141139
}
142140

0 commit comments

Comments
 (0)