From 59afa6cc24196b276defd524250ed8a1316b02c6 Mon Sep 17 00:00:00 2001 From: Yonghui Lin Date: Thu, 25 May 2023 17:03:14 +0800 Subject: [PATCH] fix(ckb-indexer): wrong case handling when collect tx (#520) --- packages/ckb-indexer/src/indexer.ts | 38 +-- packages/ckb-indexer/src/services.ts | 63 +++- .../ckb-indexer/src/transaction_collector.ts | 82 ++--- packages/ckb-indexer/tests/test_cases.js | 22 +- .../tests/transaction_collector.unit.test.ts | 305 ++++++++++++++---- packages/testkit/src/mock-ckb-jsonrpc.ts | 7 +- 6 files changed, 348 insertions(+), 169 deletions(-) diff --git a/packages/ckb-indexer/src/indexer.ts b/packages/ckb-indexer/src/indexer.ts index e554d9d12..35663c6ec 100644 --- a/packages/ckb-indexer/src/indexer.ts +++ b/packages/ckb-indexer/src/indexer.ts @@ -8,11 +8,10 @@ import { utils, Block, } from "@ckb-lumos/base"; -import { requestBatch } from "./services"; +import { requestBatchTransactionWithStatus } from "./services"; import { CKBCellCollector } from "./collector"; import { EventEmitter } from "events"; import { - GetTransactionRPCResult, CKBIndexerQueryOptions, GetCellsResults, GetLiveCellsResult, @@ -271,31 +270,24 @@ export class CkbIndexer implements CellProvider, TerminableCellFetcher { const blockNumber = block.header.number; // publish changed events if subscribed script exists in previous output cells , skip the cellbase. if (txIndex > 0) { - const requestData = tx.inputs.map((input, index) => { - return { - id: index, - jsonrpc: "2.0", - method: "get_transaction", - params: [input.previousOutput.txHash], - }; - }); + const inputTxHashes = tx.inputs.map( + (input) => input.previousOutput.txHash + ); // batch request by block - const transactionResponse: OutputToVerify[] = await requestBatch( - this.uri, - requestData - ).then((response: GetTransactionRPCResult[]) => { - return response.map( - (item: GetTransactionRPCResult, index: number) => { - const cellIndex = tx.inputs[index].previousOutput.index; - const outputCell = - item.result.transaction.outputs[parseInt(cellIndex)]; - const outputData = - item.result.transaction.outputsData[parseInt(cellIndex)]; - return { output: outputCell, outputData } as OutputToVerify; + const transactionResponse: OutputToVerify[] = + await requestBatchTransactionWithStatus(this.uri, inputTxHashes).then( + (response) => { + return response.map((txWithStatus, index) => { + const cellIndex = tx.inputs[index].previousOutput.index; + const outputCell = + txWithStatus.transaction.outputs[parseInt(cellIndex)]; + const outputData = + txWithStatus.transaction.outputsData[parseInt(cellIndex)]; + return { output: outputCell, outputData }; + }); } ); - }); transactionResponse.forEach(({ output, outputData }) => { this.filterEvents(output, blockNumber, outputData); }); diff --git a/packages/ckb-indexer/src/services.ts b/packages/ckb-indexer/src/services.ts index f049c9edb..6448e236a 100644 --- a/packages/ckb-indexer/src/services.ts +++ b/packages/ckb-indexer/src/services.ts @@ -1,4 +1,4 @@ -import { utils, HexString, Script } from "@ckb-lumos/base"; +import { utils, HexString } from "@ckb-lumos/base"; import { CKBIndexerQueryOptions, SearchKey } from "./type"; import fetch from "cross-fetch"; import { BI } from "@ckb-lumos/bi"; @@ -6,6 +6,9 @@ import { toScript } from "./paramsFormatter"; import type * as RPCType from "./rpcType"; import { toSearchKey } from "./resultFormatter"; import { unwrapScriptWrapper } from "./ckbIndexerFilter"; +import { ResultFormatter } from "@ckb-lumos/rpc"; +import { RPC as RpcTypes } from "@ckb-lumos/rpc/lib/types/rpc"; +import { CKBComponents } from "@ckb-lumos/rpc/lib/types/api"; const generateSearchKey = (queries: CKBIndexerQueryOptions): SearchKey => { let script: RPCType.Script | undefined = undefined; @@ -67,17 +70,26 @@ const getHexStringBytes = (hexString: HexString): number => { return Math.ceil(hexString.substr(2).length / 2); }; +let id = 0; +// will be tested in e2e +/* c8 ignore next 25 */ // eslint-disable-next-line @typescript-eslint/no-explicit-any -const requestBatch = async (rpcUrl: string, data: unknown): Promise => { - const res: Response = await fetch(rpcUrl, { +async function requestBatch( + rpcUrl: string, + // eslint-disable-next-line + data: Record[] +): Promise<{ result: T; jsonrpc: string; id: number | string }[]> { + if (!data.length) { + return []; + } + + const res = await fetch(rpcUrl, { method: "POST", - body: JSON.stringify(data), - headers: { - "Content-Type": "application/json", - }, + headers: { "Content-Type": "application/json" }, + body: JSON.stringify(data.map((item) => ({ id: id++, ...item }))), }); if (res.status !== 200) { - throw new Error(`indexer request failed with HTTP code ${res.status}`); + throw new Error(`Indexer request failed with HTTP code ${res.status}`); } const result = await res.json(); if (result.error !== undefined) { @@ -86,6 +98,37 @@ const requestBatch = async (rpcUrl: string, data: unknown): Promise => { ); } return result; -}; +} + +/* c8 ignore next 23 */ +async function requestBatchTransactionWithStatus( + rpcUrl: string, + txHashes: string[] +): Promise { + if (txHashes.length === 0) { + return []; + } + const requestBody = txHashes.map((txHash, index) => { + return { + id: index, + jsonrpc: "2.0", + method: "get_transaction", + params: [txHash], + }; + }); -export { generateSearchKey, getHexStringBytes, requestBatch }; + const res = await requestBatch( + rpcUrl, + requestBody + ); + return res.map((item) => + ResultFormatter.toTransactionWithStatus(item.result) + ); +} + +export { + generateSearchKey, + getHexStringBytes, + requestBatch, + requestBatchTransactionWithStatus, +}; diff --git a/packages/ckb-indexer/src/transaction_collector.ts b/packages/ckb-indexer/src/transaction_collector.ts index 19ffbe65d..e8cb9935e 100644 --- a/packages/ckb-indexer/src/transaction_collector.ts +++ b/packages/ckb-indexer/src/transaction_collector.ts @@ -15,8 +15,6 @@ import { IndexerTransactionList, IOType, Order, - GetTransactionRPCResult, - JsonRprRequestBody, } from "./type"; import { CkbIndexer } from "./indexer"; import { instanceOfScriptWrapper } from "./ckbIndexerFilter"; @@ -43,6 +41,10 @@ export class CKBIndexerTransactionCollector extends BaseIndexerModule.Transactio this.filterOptions = { ...defaultOptions, ...this.options }; } + /** + * @deprecated + * @param CKBRpcUrl + */ public static asBaseTransactionCollector( CKBRpcUrl: string ): typeof BaseTransactionCollector { @@ -110,9 +112,8 @@ export class CKBIndexerTransactionCollector extends BaseIndexerModule.Transactio public getResolvedTransactionRequestPayload( unresolvedTransactionList: TransactionWithStatus[], indexerTransactionList: IndexerTransactionList - ): JsonRprRequestBody[] { - const requestPayload: JsonRprRequestBody[] = []; - let resolvedTransactionRequestId = 0; + ): string[] { + const requestPayload: string[] = []; unresolvedTransactionList.forEach( (unresolvedTransaction: TransactionWithStatus, index: number) => { const indexerTransaction = indexerTransactionList.objects[index]; @@ -121,35 +122,16 @@ export class CKBIndexerTransactionCollector extends BaseIndexerModule.Transactio unresolvedTransaction.transaction.inputs[ Number(indexerTransaction.ioIndex) ].previousOutput; - requestPayload.push({ - id: resolvedTransactionRequestId++, - jsonrpc: "2.0", - method: "get_transaction", - params: [unresolvedOutPoint.txHash], - }); + requestPayload.push(unresolvedOutPoint.txHash); } } ); return requestPayload; } - public async fetchResolvedTransaction( - txIoTypeInputOutPointList: JsonRprRequestBody[] - ): Promise { - let resolvedTransaction: GetTransactionRPCResult[] = []; - if (txIoTypeInputOutPointList.length <= 0) { - return resolvedTransaction; - } - resolvedTransaction = await services.requestBatch( - this.CKBRpcUrl, - txIoTypeInputOutPointList - ); - return resolvedTransaction; - } - public getResolvedCell( unresolvedTransaction: TransactionWithStatus, - resolvedTransactionList: GetTransactionRPCResult[], + resolvedTransactionList: TransactionWithStatus[], indexerTransaction: IndexerTransaction ): Output { if (indexerTransaction.ioType !== "input") { @@ -162,13 +144,13 @@ export class CKBIndexerTransactionCollector extends BaseIndexerModule.Transactio Number(indexerTransaction.ioIndex) ].previousOutput; const resolvedTransaction = resolvedTransactionList.find((tx) => { - return tx.result.transaction.hash === unresolvedOutPoint.txHash; + return tx.transaction.hash === unresolvedOutPoint.txHash; }); if (!resolvedTransaction) { throw new Error(`Impossible: can NOT find resolved transaction!`); } const resolvedCell = - resolvedTransaction.result.transaction.outputs[ + resolvedTransaction.transaction.outputs[ Number(unresolvedOutPoint.index) ]; return resolvedCell; @@ -176,9 +158,9 @@ export class CKBIndexerTransactionCollector extends BaseIndexerModule.Transactio } //filter by ScriptWrapper.argsLen - public filterTransaction( + private filterTransaction( unresolvedTransactionList: TransactionWithStatus[], - resolvedTransactionList: GetTransactionRPCResult[], + resolvedTransactionList: TransactionWithStatus[], indexerTransactionList: IndexerTransactionList ): TransactionWithStatus[] { const filteredTransactionList = unresolvedTransactionList.filter( @@ -228,9 +210,11 @@ export class CKBIndexerTransactionCollector extends BaseIndexerModule.Transactio unresolvedTransactionList, indexerTransactionList ); - const resolvedTransactionList = await this.fetchResolvedTransaction( - requestPayload - ); + const resolvedTransactionList = + await services.requestBatchTransactionWithStatus( + this.CKBRpcUrl, + requestPayload + ); const objects = this.filterTransaction( unresolvedTransactionList, resolvedTransactionList, @@ -294,30 +278,22 @@ export class CKBIndexerTransactionCollector extends BaseIndexerModule.Transactio indexerTransactionList: IndexerTransactionList ) => { const getDetailRequestData = indexerTransactionList.objects.map( - (hashItem: IndexerTransaction, index: number) => { - return { - id: index, - jsonrpc: "2.0", - method: "get_transaction", - params: [hashItem.txHash], - }; + (hashItem: IndexerTransaction) => { + return hashItem.txHash; } ); + const transactionList: TransactionWithStatus[] = await services - .requestBatch(this.CKBRpcUrl, getDetailRequestData) - .then((response: GetTransactionRPCResult[]) => { - return response.map( - (item: GetTransactionRPCResult): TransactionWithStatus => { - if (!this.filterOptions.skipMissing && !item.result) { - throw new Error( - `Transaction ${ - indexerTransactionList.objects[item.id].txHash - } is missing!` - ); - } - return { ...item.result }; + .requestBatchTransactionWithStatus(this.CKBRpcUrl, getDetailRequestData) + .then((response) => { + return response.map((item, index) => { + if (!this.filterOptions.skipMissing && !item.transaction) { + throw new Error( + `Transaction ${indexerTransactionList.objects[index].txHash} is missing!` + ); } - ); + return item; + }); }); return transactionList; }; diff --git a/packages/ckb-indexer/tests/test_cases.js b/packages/ckb-indexer/tests/test_cases.js index d46a18a75..893447798 100644 --- a/packages/ckb-indexer/tests/test_cases.js +++ b/packages/ckb-indexer/tests/test_cases.js @@ -7079,7 +7079,7 @@ const transactionByLock = [ }, txStatus: { blockHash: '0x92b197aa1fba0f63633922c61c92375c9c074a93e85963554f5499fe1450d0e5', - status: 'padding', + status: 'pending', } }, { @@ -7115,7 +7115,7 @@ const transactionByLock = [ }, txStatus: { blockHash: '0x7bb56e1288a1de98bab23d3e0ec7728634b6626ab03cc119ec23005a82ff12ff', - status: 'padding', + status: 'pending', } }, { @@ -7151,7 +7151,7 @@ const transactionByLock = [ }, txStatus: { blockHash: '0x21d6e5b949392186a6510c57da615f086f779b713a7f3d54c82a07d443e85c5d', - status: 'padding', + status: 'pending', } }, { @@ -7187,7 +7187,7 @@ const transactionByLock = [ }, txStatus: { blockHash: '0x3ea3a5122344ceb335ff776dbfa5f3e5a06b6edd965414f287f0d57f92304c89', - status: 'padding', + status: 'pending', } }, { @@ -7223,7 +7223,7 @@ const transactionByLock = [ }, txStatus: { blockHash: '0x1255b3b013addc93fb0301ad2a4150d15e6c1a1c4badbc653fc821b127a37929', - status: 'padding', + status: 'pending', } }, { @@ -7259,7 +7259,7 @@ const transactionByLock = [ }, txStatus: { blockHash: '0x2c96b715a2e2fe5602d518d75bc4912e6be16f34d9f1f2f420ff6e6de40c9379', - status: 'padding', + status: 'pending', } }, { @@ -7295,7 +7295,7 @@ const transactionByLock = [ }, txStatus: { blockHash: '0x02bfadbf60172d77af71ad141536d14f5ba191b40b5cffb2b2e7905459e8d500', - status: 'padding', + status: 'pending', } }, ] @@ -7378,10 +7378,10 @@ const transactionsByType = [ "witnesses": [ "0x55000000100000005500000055000000410000008b182319299acf5ba26e0d1f38854c69243a2fc8614ebbe813e87b24b2b9aafc35a11be33d65fcd2a3850d37cdb12c61a1693e8ea96e1a9a4a8aeebed297784a00" ] - }, + }, txStatus: { blockHash: '0x4cc7b42c12e0ed1c87c3ced726e419ba19f755be1739097d6758b6bf60c654ad', - status: 'padding', + status: 'pending', } }, { @@ -7445,7 +7445,7 @@ const transactionsByType = [ }, txStatus: { blockHash: '0xd4b10e5af3dac133888f47baeda057f7760fb4f81b2f4dc03a29c228c7dba7a0', - status: 'padding', + status: 'pending', } } ]; @@ -7512,7 +7512,7 @@ const transactionsByLockAndType = [ }, txStatus: { blockHash: '0xd4b10e5af3dac133888f47baeda057f7760fb4f81b2f4dc03a29c228c7dba7a0', - status: 'padding', + status: 'pending', } } ]; diff --git a/packages/ckb-indexer/tests/transaction_collector.unit.test.ts b/packages/ckb-indexer/tests/transaction_collector.unit.test.ts index 1de45a3e5..347234a31 100644 --- a/packages/ckb-indexer/tests/transaction_collector.unit.test.ts +++ b/packages/ckb-indexer/tests/transaction_collector.unit.test.ts @@ -1,28 +1,38 @@ +import { randomBytes } from "crypto"; import test from "ava"; import { Indexer, TransactionCollector } from "../src"; -import { JsonRprRequestBody } from "../src/type"; -import { stub, SinonStub } from "sinon"; -import * as services from "../src/services"; - import { indexerTransactionListThatHaveOneIoTypeInput, indexerTransactionListThatHaveTwoIoTypeInput, indexerTransactionListThatHaveZeroIoTypeInput, unresolvedTransactionList, queryOption, - batchRequestTransaction, } from "./transaction_collector_unit_test_case"; +import { SinonStub, stub } from "sinon"; +import * as services from "../src/services"; +import { CKBComponents } from "@ckb-lumos/rpc/lib/types/api"; +import { CkbIndexer } from "../src/indexer"; +import { bytes } from "@ckb-lumos/codec"; const nodeUri = "http://127.0.0.1:8118/rpc"; -const indexUri = "http://127.0.0.1:8120"; -const indexer = new Indexer(indexUri, nodeUri); -let requestBatchStub: SinonStub; +const indexer = new Indexer(nodeUri); + +let requestBatchTransactionWithStatusStub: SinonStub< + Parameters, + ReturnType +>; + test.before(() => { - requestBatchStub = stub(services, "requestBatch"); + requestBatchTransactionWithStatusStub = stub( + services, + "requestBatchTransactionWithStatus" + ); }); test.afterEach(() => { - requestBatchStub.resetHistory(); + requestBatchTransactionWithStatusStub.resetHistory(); + requestBatchTransactionWithStatusStub.reset(); }); + test.serial( "getResolvedTransactionRequestPayload# should return empty list if no indexerTransaction ioType is input", (t) => { @@ -36,8 +46,8 @@ test.serial( unresolvedTransactionList, indexerTransactionListThatHaveZeroIoTypeInput ); - const expectedResult: JsonRprRequestBody[] = []; - t.deepEqual(resolvedTransactionList, expectedResult); + + t.deepEqual(resolvedTransactionList, []); } ); @@ -54,15 +64,8 @@ test.serial( unresolvedTransactionList, indexerTransactionListThatHaveOneIoTypeInput ); - const expectedResult: JsonRprRequestBody[] = [ - { - id: 0, - jsonrpc: "2.0", - method: "get_transaction", - params: [ - "0x992208eab19d0f8ce5a2fc10579d8d614d265aa12851ea140ec717f2f41b925f", - ], - }, + const expectedResult: string[] = [ + "0x992208eab19d0f8ce5a2fc10579d8d614d265aa12851ea140ec717f2f41b925f", ]; t.deepEqual(resolvedTransactionList, expectedResult); } @@ -76,70 +79,234 @@ test.serial( queryOption, nodeUri ); + const resolvedTransactionList = transactionCollector.getResolvedTransactionRequestPayload( unresolvedTransactionList, indexerTransactionListThatHaveTwoIoTypeInput ); - const expectedResult: JsonRprRequestBody[] = [ - { - id: 0, - jsonrpc: "2.0", - method: "get_transaction", - params: [ - "0x992208eab19d0f8ce5a2fc10579d8d614d265aa12851ea140ec717f2f41b925f", - ], - }, - { - id: 1, - jsonrpc: "2.0", - method: "get_transaction", - params: [ - "0x805168dafc0c10ae31de2580541db0f5ee8ff53afb55e39a5e2eeb60f878553f", - ], - }, + const expectedResult: string[] = [ + "0x992208eab19d0f8ce5a2fc10579d8d614d265aa12851ea140ec717f2f41b925f", + "0x805168dafc0c10ae31de2580541db0f5ee8ff53afb55e39a5e2eeb60f878553f", ]; t.deepEqual(resolvedTransactionList, expectedResult); } ); -test.serial("fetchResolvedTransaction#", async (t) => { - const transactionCollector = new TransactionCollector( +test.serial( + "collect# should collect with a lock both in transaction inputs and outputs", + async (t) => { + const cellInInputTxHash = bytes.hexify(randomBytes(32)); + const cellInOutputTxHash = bytes.hexify(randomBytes(32)); + const targetCell = { lock: queryOption.lock, capacity: "0x0" }; + + const txs: Record = { + [cellInInputTxHash]: mockTxWithStatus({ + hash: cellInInputTxHash, + inputs: [ + { + previousOutput: { index: "0x0", txHash: cellInOutputTxHash }, + since: "0x0", + }, + ], + outputs: [targetCell], + }), + + [cellInOutputTxHash]: mockTxWithStatus({ + hash: cellInOutputTxHash, + inputs: [ + { previousOutput: { index: "0x0", txHash: "0x" }, since: "0x0" }, + ], + outputs: [{ lock: queryOption.lock, capacity: "0x0" }], + }), + }; + + // only affect the test case + const scopedIndexer = new CkbIndexer(""); + + stub(scopedIndexer, "getTransactions").callsFake( + async ( + _, + options + ): Promise> => { + // return empty result if lastCursor is 0xlast + if (options?.lastCursor === "0xlast") { + return { objects: [], lastCursor: "" }; + } + + return { + objects: [ + { + blockNumber: "0x", + txHash: cellInInputTxHash, + ioType: "input", + txIndex: "0x0", + ioIndex: "0x0", + }, + { + blockNumber: "0x", + txHash: cellInOutputTxHash, + ioType: "output", + txIndex: "0x0", + ioIndex: "0x0", + }, + ], + lastCursor: "0xlast", + }; + } + ); + + requestBatchTransactionWithStatusStub.callsFake(async (_, txHashes) => { + if (!txHashes.length) return []; + + return txHashes.map((hash) => { + if (!txs[hash]) { + throw new Error("Transaction not found" + hash); + } + return txs[hash]; + }); + }); + + const transactionCollector = new TransactionCollector( + scopedIndexer, + queryOption, + nodeUri + ); + const results = []; + for await (const tx of transactionCollector.collect()) { + results.push(tx); + } + t.is(results.length, 2); + + const expectedCount = await transactionCollector.count(); + t.is(expectedCount, 2); + + const txHashes = await transactionCollector.getTransactionHashes(); + t.deepEqual(txHashes, [cellInInputTxHash, cellInOutputTxHash]); + } +); + +test.serial("collect# should collect works with ScriptWrapper", async (t) => { + const indexer = new Indexer(""); + + const targetLock: CKBComponents.Script = { + codeHash: bytes.hexify(randomBytes(32)), + hashType: "type", + args: bytes.hexify(randomBytes(20)), + }; + const targetType: CKBComponents.Script = { + codeHash: bytes.hexify(randomBytes(32)), + hashType: "type", + args: bytes.hexify(randomBytes(20)), + }; + + const txHash = bytes.hexify(randomBytes(32)); + + const txs: Record = { + [txHash]: mockTxWithStatus({ + hash: txHash, + inputs: [], + outputs: [ + { + lock: { ...targetLock, args: targetLock.args }, + type: targetType, + capacity: "0x0", + }, + ], + }), + }; + + stub(indexer, "getTransactions").callsFake(async (_, options) => { + if (options?.lastCursor === "0xlast") { + return { objects: [], lastCursor: "" }; + } + + return { + objects: [ + { + blockNumber: "0x0", + txHash, + ioType: "output", + ioIndex: "0x0", + txIndex: "0x0", + }, + ], + lastCursor: "0xlast", + }; + }); + + requestBatchTransactionWithStatusStub.callsFake(async (_, txHashes) => { + if (!txHashes.length) return []; + return txHashes.map((hash) => txs[hash]); + }); + + const collector = new TransactionCollector( indexer, - queryOption, + { + lock: { + script: targetLock, + ioType: "output", + }, + type: { + script: targetType, + }, + }, nodeUri ); - const emptyPayload: JsonRprRequestBody[] = []; - const emptyResolvedTransaction = - await transactionCollector.fetchResolvedTransaction(emptyPayload); - t.is( - requestBatchStub.called, - false, - "empty request payload should not call batchRequest" - ); - t.deepEqual( - emptyResolvedTransaction, - [], - "should return empty result if request payload is empty" - ); - const payloadWithData: JsonRprRequestBody[] = [ + const result1 = []; + for await (const tx of collector.collect()) { + result1.push(tx); + } + t.is(result1.length, 1); + + const collectorWith21BytesArgs = new TransactionCollector( + indexer, { - id: 0, - jsonrpc: "2.0", - method: "get_transaction", - params: [ - "0x992208eab19d0f8ce5a2fc10579d8d614d265aa12851ea140ec717f2f41b925f", - ], + lock: { + script: targetLock, + ioType: "output", + argsLen: 21, + }, + type: { + script: targetType, + }, }, - ]; - requestBatchStub.resolves(batchRequestTransaction); - const resolvedTransactionList = - await transactionCollector.fetchResolvedTransaction(payloadWithData); + nodeUri + ); + + const result2 = []; + for await (const tx of collectorWith21BytesArgs.collect()) { + result2.push(tx); + } + t.is( - requestBatchStub.called, - true, - "should call batchRequest if request payload not empty" + result2.length, + 0, + 'Should not collect the tx since no "argsLen" with 21 bytes matches' ); - t.is(resolvedTransactionList.length, 1, "should return correct length data"); }); + +function mockTxWithStatus({ + hash, + inputs, + outputs, +}: { + hash: string; + inputs: CKBComponents.CellInput[]; + outputs: CKBComponents.CellOutput[]; +}): CKBComponents.TransactionWithStatus { + return { + transaction: { + hash: hash, + inputs: inputs, + outputs: outputs, + version: "0x1", + headerDeps: [], + outputsData: [], + witnesses: [], + cellDeps: [], + }, + txStatus: { status: "committed" }, + }; +} diff --git a/packages/testkit/src/mock-ckb-jsonrpc.ts b/packages/testkit/src/mock-ckb-jsonrpc.ts index c8b81980f..810bfc470 100644 --- a/packages/testkit/src/mock-ckb-jsonrpc.ts +++ b/packages/testkit/src/mock-ckb-jsonrpc.ts @@ -4,6 +4,7 @@ import bodyParser from "body-parser"; import { LocalNode, Block, utils, blockchain } from "@ckb-lumos/base"; import { bytes } from "@ckb-lumos/codec"; interface Options { + // FIXME it actually is RPCBlock blocks: Block[]; localNode: LocalNode; // defaults to /rpc @@ -90,7 +91,7 @@ export function createCKBMockRPC(options: Options): Express { } return { transaction: result, - txStatus: { status: "padding", blockHash: blockHash }, + tx_status: { status: "pending", block_hash: blockHash }, }; }); @@ -100,8 +101,8 @@ export function createCKBMockRPC(options: Options): Express { chain: "ckb_testnet", difficulty: "0x1b6f506b", epoch: "0x708069a000cc5", - isInitialBlockDownload: false, - medianTime: "0x17d3723d27d", + is_initial_block_download: false, + median_time: "0x17d3723d27d", }; });