From b9080200e78d8f85ccf17d48463846df6719fdb7 Mon Sep 17 00:00:00 2001 From: homura Date: Thu, 20 Jun 2024 17:42:37 +0900 Subject: [PATCH] feat: support indexer side data filter --- .eslintrc.next.js | 1 + packages/ckb-indexer/src/collector.ts | 8 +++++++- packages/ckb-indexer/src/resultFormatter.ts | 2 ++ packages/ckb-indexer/src/rpcType.ts | 3 +++ packages/ckb-indexer/src/services.ts | 11 ++++++++++- packages/ckb-indexer/src/type.ts | 3 +++ .../rpc/__tests__/formatters/params.fixtures.json | 4 ++++ packages/rpc/src/paramsFormatter.ts | 2 ++ packages/rpc/src/types/api.ts | 5 +++++ packages/rpc/src/types/rpc.ts | 3 +++ 10 files changed, 40 insertions(+), 2 deletions(-) diff --git a/.eslintrc.next.js b/.eslintrc.next.js index 240fa6c24..7905fb589 100644 --- a/.eslintrc.next.js +++ b/.eslintrc.next.js @@ -23,6 +23,7 @@ module.exports = { -1, // index -1 is not found 0, // first element of an array 1, // common for i + 1 in a loop + 2, // slice(2) for string that starts with "0x" is common to work with 3rd-party libs 16, // toString(16) 1000, // second to millisecond ], diff --git a/packages/ckb-indexer/src/collector.ts b/packages/ckb-indexer/src/collector.ts index 1b093dcc5..2f3721cf0 100644 --- a/packages/ckb-indexer/src/collector.ts +++ b/packages/ckb-indexer/src/collector.ts @@ -158,8 +158,14 @@ export class CKBCellCollector implements BaseCellCollector { } } + // set data range to narrow the search result if the data is set + // the default data search filter mode is exact search that is the same as ckb-indexer if (!query.outputDataLenRange) { - if (query.data && query.data !== "any") { + if ( + query.data && + query.data !== "any" && + typeof query.data === "string" + ) { const dataLenRange = getHexStringBytes(unwrapDataWrapper(query.data)); query.outputDataLenRange = [ "0x" + dataLenRange.toString(16), diff --git a/packages/ckb-indexer/src/resultFormatter.ts b/packages/ckb-indexer/src/resultFormatter.ts index 663177f92..07c15c284 100644 --- a/packages/ckb-indexer/src/resultFormatter.ts +++ b/packages/ckb-indexer/src/resultFormatter.ts @@ -29,6 +29,8 @@ const toSearchFilter = (data: RPCType.SearchFilter): SearchFilter => { outputCapacityRange: data.output_capacity_range, scriptLenRange: data.script_len_range, blockRange: data.block_range, + outputData: data.output_data, + outputDataFilterMode: data.output_data_filter_mode, }; }; diff --git a/packages/ckb-indexer/src/rpcType.ts b/packages/ckb-indexer/src/rpcType.ts index 90e2d19d0..76f3dc3c9 100644 --- a/packages/ckb-indexer/src/rpcType.ts +++ b/packages/ckb-indexer/src/rpcType.ts @@ -28,9 +28,12 @@ export type CellOutput = { export type HexadecimalRange = [Hexadecimal, Hexadecimal]; export type ScriptType = "type" | "lock"; export type ScriptSearchMode = "prefix" | "exact" | "partial"; +export type OutputDataFilterMode = "prefix" | "exact" | "partial"; export interface SearchFilter { script?: Script; + output_data?: HexString; + output_data_filter_mode?: OutputDataFilterMode; output_data_len_range?: HexadecimalRange; //empty output_capacity_range?: HexadecimalRange; //empty block_range?: HexadecimalRange; //fromBlock-toBlock diff --git a/packages/ckb-indexer/src/services.ts b/packages/ckb-indexer/src/services.ts index 6448e236a..55b0ae800 100644 --- a/packages/ckb-indexer/src/services.ts +++ b/packages/ckb-indexer/src/services.ts @@ -51,6 +51,14 @@ const generateSearchKey = (queries: CKBIndexerQueryOptions): SearchKey => { if (queries.scriptSearchMode) { script_search_mode = queries.scriptSearchMode; } + if (queries.data) { + if (typeof queries.data === "object") { + filter.output_data_filter_mode = queries.data.searchMode; + filter.output_data = queries.data.data; + } else if (typeof queries.data === "string") { + filter.output_data = queries.data; + } + } if (!script) { throw new Error("Either lock or type script must be provided!"); } @@ -88,7 +96,8 @@ async function requestBatch( headers: { "Content-Type": "application/json" }, body: JSON.stringify(data.map((item) => ({ id: id++, ...item }))), }); - if (res.status !== 200) { + const HTTP_SUCCESS_STATUS = 200; + if (res.status !== HTTP_SUCCESS_STATUS) { throw new Error(`Indexer request failed with HTTP code ${res.status}`); } const result = await res.json(); diff --git a/packages/ckb-indexer/src/type.ts b/packages/ckb-indexer/src/type.ts index 2772fbf4a..b5c2035a0 100644 --- a/packages/ckb-indexer/src/type.ts +++ b/packages/ckb-indexer/src/type.ts @@ -16,6 +16,7 @@ import { BIish } from "@ckb-lumos/bi"; export type ScriptType = "type" | "lock"; export type Order = "asc" | "desc"; export type ScriptSearchMode = "prefix" | "exact" | "partial"; +export type OutputDataFilterMode = "prefix" | "exact" | "partial"; export interface CKBIndexerQueryOptions extends QueryOptions { outputDataLenRange?: HexadecimalRange; @@ -31,6 +32,8 @@ export type HexadecimalRange = [Hexadecimal, Hexadecimal]; export interface SearchFilter { script?: Script; scriptLenRange?: HexadecimalRange; + outputData?: HexString; + outputDataFilterMode?: OutputDataFilterMode; outputDataLenRange?: HexadecimalRange; //empty outputCapacityRange?: HexadecimalRange; //empty blockRange?: HexadecimalRange; //fromBlock-toBlock diff --git a/packages/rpc/__tests__/formatters/params.fixtures.json b/packages/rpc/__tests__/formatters/params.fixtures.json index 09e14a554..0243a0c36 100644 --- a/packages/rpc/__tests__/formatters/params.fixtures.json +++ b/packages/rpc/__tests__/formatters/params.fixtures.json @@ -400,12 +400,16 @@ "outputDataLenRange": ["0x1", "0x2"], "outputCapacityRange": ["0x1", "0x2"], "blockRange": ["0x1", "0x2"], + "outputData": "0x01", + "outputDataFilterMode": "partial", "scriptLenRange": [0, 1] }, "expected": { "output_data_len_range": ["0x1", "0x2"], "output_capacity_range": ["0x1", "0x2"], "block_range": ["0x1", "0x2"], + "output_data": "0x01", + "output_data_filter_mode": "partial", "script_len_range": [0, 1] } } diff --git a/packages/rpc/src/paramsFormatter.ts b/packages/rpc/src/paramsFormatter.ts index 7fb71111a..4aa7b0440 100644 --- a/packages/rpc/src/paramsFormatter.ts +++ b/packages/rpc/src/paramsFormatter.ts @@ -181,6 +181,8 @@ export const formatter = { script: data.script ? formatter.toScript(data.script) : data.script, output_data_len_range: data.outputDataLenRange, output_capacity_range: data.outputCapacityRange, + output_data: data.outputData, + output_data_filter_mode: data.outputDataFilterMode, block_range: data.blockRange, script_len_range: data.scriptLenRange, }; diff --git a/packages/rpc/src/types/api.ts b/packages/rpc/src/types/api.ts index 06c7af6d8..647207315 100644 --- a/packages/rpc/src/types/api.ts +++ b/packages/rpc/src/types/api.ts @@ -1,10 +1,13 @@ import type * as api from "@ckb-lumos/base"; +import { HexString } from "@ckb-lumos/base"; +import { RPC } from "./rpc"; /** * @see https://github.com/nervosnetwork/ckb/blob/develop/protocol/src/protocol.fbs for more infGomation */ /* eslint-disable @typescript-eslint/no-namespace, @typescript-eslint/no-explicit-any, @typescript-eslint/ban-types */ export namespace CKBComponents { + import OutputDataFilterMode = RPC.OutputDataFilterMode; export type DAO = string; export type Hash = string; export type Number = string; @@ -252,6 +255,8 @@ export namespace CKBComponents { export interface SearchFilter { script?: Script; scriptLenRange?: HexadecimalRange; + outputData?: HexString; + outputDataFilterMode?: OutputDataFilterMode; outputDataLenRange?: HexadecimalRange; //empty outputCapacityRange?: HexadecimalRange; //empty blockRange?: HexadecimalRange; //fromBlock-toBlock diff --git a/packages/rpc/src/types/rpc.ts b/packages/rpc/src/types/rpc.ts index a4b98e336..691144fb6 100644 --- a/packages/rpc/src/types/rpc.ts +++ b/packages/rpc/src/types/rpc.ts @@ -451,11 +451,14 @@ export namespace RPC { export type HexadecimalRange = [string, string]; export type ScriptType = "type" | "lock"; export type ScriptSearchMode = "prefix" | "exact" | "partial"; + export type OutputDataFilterMode = "prefix" | "exact" | "partial"; export interface SearchFilter { script?: Script; output_data_len_range?: HexadecimalRange; //empty output_capacity_range?: HexadecimalRange; //empty + output_data?: HexString; + output_data_filter_mode?: OutputDataFilterMode; block_range?: HexadecimalRange; //fromBlock-toBlock script_len_range?: HexadecimalRange; }