@ckb-ccc/core
Version:
Core of CCC - CKBer's Codebase
359 lines (355 loc) • 11 kB
text/typescript
import { bytesFrom } from "../../bytes/index.js";
import {
Cell,
CellDep,
CellDepLike,
CellInput,
CellInputLike,
CellOutput,
CellOutputLike,
DepType,
DepTypeLike,
HashType,
HashTypeLike,
OutPoint,
OutPointLike,
Script,
ScriptLike,
Transaction,
TransactionLike,
depTypeFrom,
epochFromHex,
hashTypeFrom,
} from "../../ckb/index.js";
import { Hex, HexLike, hexFrom } from "../../hex/index.js";
import { NumLike, numFrom, numLeFromBytes, numToHex } from "../../num/index.js";
import { apply } from "../../utils/index.js";
import {
ClientBlock,
ClientBlockHeader,
ClientBlockUncle,
ClientFindCellsResponse,
ClientFindTransactionsGroupedResponse,
ClientFindTransactionsResponse,
ClientIndexerSearchKey,
ClientIndexerSearchKeyFilter,
ClientIndexerSearchKeyLike,
ClientIndexerSearchKeyTransaction,
ClientIndexerSearchKeyTransactionLike,
ClientTransactionResponse,
TransactionStatus,
} from "../clientTypes.js";
import {
JsonRpcBlock,
JsonRpcBlockHeader,
JsonRpcBlockUncle,
JsonRpcCellDep,
JsonRpcCellInput,
JsonRpcCellOutput,
JsonRpcDepType,
JsonRpcHashType,
JsonRpcIndexerFindTransactionsGroupedResponse,
JsonRpcIndexerFindTransactionsResponse,
JsonRpcIndexerSearchKey,
JsonRpcIndexerSearchKeyFilter,
JsonRpcIndexerSearchKeyTransaction,
JsonRpcOutPoint,
JsonRpcScript,
JsonRpcTransaction,
} from "./types.js";
export class JsonRpcTransformers {
static hashTypeFrom(hashType: HashTypeLike): JsonRpcHashType {
return hashTypeFrom(hashType);
}
static hashTypeTo(hashType: JsonRpcHashType): HashType {
return hashType;
}
static depTypeFrom(depType: DepTypeLike): JsonRpcDepType {
switch (depTypeFrom(depType)) {
case "code":
return "code";
case "depGroup":
return "dep_group";
}
}
static depTypeTo(depType: JsonRpcDepType): DepType {
switch (depType) {
case "code":
return "code";
case "dep_group":
return "depGroup";
}
}
static scriptFrom(scriptLike: ScriptLike): JsonRpcScript {
const script = Script.from(scriptLike);
return {
code_hash: script.codeHash,
hash_type: JsonRpcTransformers.hashTypeFrom(script.hashType),
args: script.args,
};
}
static scriptTo(script: JsonRpcScript): Script {
return Script.from({
codeHash: script.code_hash,
hashType: JsonRpcTransformers.hashTypeTo(script.hash_type),
args: script.args,
});
}
static outPointFrom(outPointLike: OutPointLike): JsonRpcOutPoint {
const outPoint = OutPoint.from(outPointLike);
return {
index: numToHex(outPoint.index),
tx_hash: outPoint.txHash,
};
}
static outPointTo(outPoint: JsonRpcOutPoint): OutPoint {
return OutPoint.from({
index: outPoint.index,
txHash: outPoint.tx_hash,
});
}
static cellInputFrom(cellInputLike: CellInputLike): JsonRpcCellInput {
const cellInput = CellInput.from(cellInputLike);
return {
previous_output: JsonRpcTransformers.outPointFrom(
cellInput.previousOutput,
),
since: numToHex(cellInput.since),
};
}
static cellInputTo(cellInput: JsonRpcCellInput): CellInput {
return CellInput.from({
previousOutput: JsonRpcTransformers.outPointTo(cellInput.previous_output),
since: cellInput.since,
});
}
static cellOutputFrom(cellOutput: CellOutputLike): JsonRpcCellOutput {
return {
capacity: numToHex(cellOutput.capacity),
lock: JsonRpcTransformers.scriptFrom(cellOutput.lock),
type: apply(JsonRpcTransformers.scriptFrom, cellOutput.type),
};
}
static cellOutputTo(cellOutput: JsonRpcCellOutput): CellOutput {
return CellOutput.from({
capacity: cellOutput.capacity,
lock: JsonRpcTransformers.scriptTo(cellOutput.lock),
type: apply(JsonRpcTransformers.scriptTo, cellOutput.type),
});
}
static cellDepFrom(cellDep: CellDepLike): JsonRpcCellDep {
return {
out_point: JsonRpcTransformers.outPointFrom(cellDep.outPoint),
dep_type: JsonRpcTransformers.depTypeFrom(cellDep.depType),
};
}
static cellDepTo(cellDep: JsonRpcCellDep): CellDep {
return CellDep.from({
outPoint: JsonRpcTransformers.outPointTo(cellDep.out_point),
depType: JsonRpcTransformers.depTypeTo(cellDep.dep_type),
});
}
static transactionFrom(txLike: TransactionLike): JsonRpcTransaction {
const tx = Transaction.from(txLike);
return {
version: numToHex(tx.version),
cell_deps: tx.cellDeps.map((c) => JsonRpcTransformers.cellDepFrom(c)),
header_deps: tx.headerDeps,
inputs: tx.inputs.map((i) => JsonRpcTransformers.cellInputFrom(i)),
outputs: tx.outputs.map((o) => JsonRpcTransformers.cellOutputFrom(o)),
outputs_data: tx.outputsData,
witnesses: tx.witnesses,
};
}
static transactionTo(tx: JsonRpcTransaction): Transaction {
return Transaction.from({
version: tx.version,
cellDeps: tx.cell_deps.map((c) => JsonRpcTransformers.cellDepTo(c)),
headerDeps: tx.header_deps,
inputs: tx.inputs.map((i) => JsonRpcTransformers.cellInputTo(i)),
outputs: tx.outputs.map((o) => JsonRpcTransformers.cellOutputTo(o)),
outputsData: tx.outputs_data,
witnesses: tx.witnesses,
});
}
static transactionResponseTo({
cycles,
tx_status: { status, block_number, block_hash, tx_index, reason },
transaction,
}: {
cycles?: NumLike;
tx_status: {
status: TransactionStatus;
block_hash?: HexLike;
tx_index?: NumLike;
block_number?: NumLike;
reason?: string;
};
transaction: JsonRpcTransaction | null;
}): ClientTransactionResponse | undefined {
if (transaction == null) {
return;
}
return ClientTransactionResponse.from({
transaction: JsonRpcTransformers.transactionTo(transaction),
status,
cycles: apply(numFrom, cycles),
blockHash: apply(hexFrom, block_hash),
blockNumber: apply(numFrom, block_number),
txIndex: apply(numFrom, tx_index),
reason,
});
}
static blockHeaderTo(header: JsonRpcBlockHeader): ClientBlockHeader {
const dao = bytesFrom(header.dao);
return {
compactTarget: numFrom(header.compact_target),
dao: {
c: numLeFromBytes(dao.slice(0, 8)),
ar: numLeFromBytes(dao.slice(8, 16)),
s: numLeFromBytes(dao.slice(16, 24)),
u: numLeFromBytes(dao.slice(24, 32)),
},
epoch: epochFromHex(header.epoch),
extraHash: header.extra_hash,
hash: header.hash,
nonce: numFrom(header.nonce),
number: numFrom(header.number),
parentHash: header.parent_hash,
proposalsHash: header.proposals_hash,
timestamp: numFrom(header.timestamp),
transactionsRoot: header.transactions_root,
version: numFrom(header.version),
};
}
static blockUncleTo(block: JsonRpcBlockUncle): ClientBlockUncle {
return {
header: JsonRpcTransformers.blockHeaderTo(block.header),
proposals: block.proposals,
};
}
static blockTo(block: JsonRpcBlock): ClientBlock {
return {
header: JsonRpcTransformers.blockHeaderTo(block.header),
proposals: block.proposals,
transactions: block.transactions.map((t) =>
JsonRpcTransformers.transactionTo(t),
),
uncles: block.uncles.map((u) => JsonRpcTransformers.blockUncleTo(u)),
};
}
static rangeFrom([a, b]: [NumLike, NumLike]): [Hex, Hex] {
return [numToHex(a), numToHex(b)];
}
static indexerSearchKeyFilterFrom(
filter: ClientIndexerSearchKeyFilter,
): JsonRpcIndexerSearchKeyFilter {
return {
script: apply(JsonRpcTransformers.scriptFrom, filter.script),
script_len_range: apply(
JsonRpcTransformers.rangeFrom,
filter.scriptLenRange,
),
output_data: filter.outputData,
output_data_filter_mode: filter.outputDataSearchMode,
output_data_len_range: apply(
JsonRpcTransformers.rangeFrom,
filter.outputDataLenRange,
),
output_capacity_range: apply(
JsonRpcTransformers.rangeFrom,
filter.outputCapacityRange,
),
block_range: apply(JsonRpcTransformers.rangeFrom, filter.blockRange),
};
}
static indexerSearchKeyFrom(
keyLike: ClientIndexerSearchKeyLike,
): JsonRpcIndexerSearchKey {
const key = ClientIndexerSearchKey.from(keyLike);
return {
script: JsonRpcTransformers.scriptFrom(key.script),
script_type: key.scriptType,
script_search_mode: key.scriptSearchMode,
filter: apply(JsonRpcTransformers.indexerSearchKeyFilterFrom, key.filter),
with_data: key.withData,
};
}
static findCellsResponseTo({
last_cursor,
objects,
}: {
last_cursor: string;
objects: {
out_point: JsonRpcOutPoint;
output: JsonRpcCellOutput;
output_data?: Hex;
}[];
}): ClientFindCellsResponse {
return {
lastCursor: last_cursor,
cells: objects.map((cell) =>
Cell.from({
outPoint: JsonRpcTransformers.outPointTo(cell.out_point),
cellOutput: JsonRpcTransformers.cellOutputTo(cell.output),
outputData: cell.output_data ?? "0x",
}),
),
};
}
static indexerSearchKeyTransactionFrom(
keyLike: ClientIndexerSearchKeyTransactionLike,
): JsonRpcIndexerSearchKeyTransaction {
const key = ClientIndexerSearchKeyTransaction.from(keyLike);
return {
script: JsonRpcTransformers.scriptFrom(key.script),
script_type: key.scriptType,
script_search_mode: key.scriptSearchMode,
filter: apply(JsonRpcTransformers.indexerSearchKeyFilterFrom, key.filter),
group_by_transaction: key.groupByTransaction,
};
}
static findTransactionsResponseTo({
last_cursor,
objects,
}:
| JsonRpcIndexerFindTransactionsResponse
| JsonRpcIndexerFindTransactionsGroupedResponse):
| ClientFindTransactionsResponse
| ClientFindTransactionsGroupedResponse {
if (objects.length === 0) {
return {
lastCursor: last_cursor,
transactions: [],
};
}
if ("io_index" in objects[0]) {
return {
lastCursor: last_cursor,
transactions: (
objects as JsonRpcIndexerFindTransactionsResponse["objects"]
).map((tx) => ({
txHash: tx.tx_hash,
blockNumber: numFrom(tx.block_number),
txIndex: numFrom(tx.tx_index),
cellIndex: numFrom(tx.io_index),
isInput: tx.io_type === "input",
})),
};
}
return {
lastCursor: last_cursor,
transactions: (
objects as JsonRpcIndexerFindTransactionsGroupedResponse["objects"]
).map((tx) => ({
txHash: tx.tx_hash,
blockNumber: numFrom(tx.block_number),
txIndex: numFrom(tx.tx_index),
cells: tx.cells.map(([type, i]) => ({
isInput: type === "input",
cellIndex: numFrom(i),
})),
})),
};
}
}