diff --git a/.prettierignore b/.prettierignore new file mode 100644 index 000000000..040d78a37 --- /dev/null +++ b/.prettierignore @@ -0,0 +1 @@ +**/test_cases.js \ No newline at end of file diff --git a/packages/ckb-indexer/src/collector.ts b/packages/ckb-indexer/src/collector.ts index 4700d7c6f..85c7865e2 100644 --- a/packages/ckb-indexer/src/collector.ts +++ b/packages/ckb-indexer/src/collector.ts @@ -104,6 +104,10 @@ export class CKBCellCollector implements BaseCellCollector { queries.outputDataLenRange[1] ); } + if (queries.scriptLenRange) { + utils.assertHexadecimal("scriptLenRange[0]", queries.scriptLenRange[0]); + utils.assertHexadecimal("scriptLenRange[1]", queries.scriptLenRange[1]); + } if (queries.outputDataLenRange && queries.data && queries.data !== "any") { const dataLen = getHexStringBytes(queries.data); @@ -154,6 +158,10 @@ export class CKBCellCollector implements BaseCellCollector { ]; } } + + if (!this.queries.scriptLenRange && this.queries.type === "empty") { + this.queries.scriptLenRange = ["0x0", "0x1"]; + } } private async getLiveCell(lastCursor?: string): Promise { diff --git a/packages/ckb-indexer/src/indexer.ts b/packages/ckb-indexer/src/indexer.ts index 7d7098783..f467052dc 100644 --- a/packages/ckb-indexer/src/indexer.ts +++ b/packages/ckb-indexer/src/indexer.ts @@ -41,7 +41,7 @@ function defaultLogger(level: string, message: string) { /** CkbIndexer.collector will not get cell with blockHash by default, please use OtherQueryOptions.withBlockHash and OtherQueryOptions.CKBRpcUrl to get blockHash if you need. */ export class CkbIndexer implements Indexer { - static version = "0.3.2"; + static version = "0.4.1"; uri: string; ckbIndexerUri: string; medianTimeEmitters: EventEmitter[] = []; diff --git a/packages/ckb-indexer/src/paramsFormatter.ts b/packages/ckb-indexer/src/paramsFormatter.ts index 7a85a2513..b65565dd6 100644 --- a/packages/ckb-indexer/src/paramsFormatter.ts +++ b/packages/ckb-indexer/src/paramsFormatter.ts @@ -1,6 +1,11 @@ import { Script } from "@ckb-lumos/base"; import type * as RPCType from "./rpcType"; -import { SearchKey, SearchFilter } from "./type"; +import { + SearchKey, + SearchFilter, + GetCellsSearchKey, + GetTransactionsSearchKey, +} from "./type"; const toScript = (data: Script): RPCType.Script => ({ code_hash: data.codeHash, @@ -14,6 +19,7 @@ const toSearchFilter = (data: SearchFilter): RPCType.SearchFilter => { output_data_len_range: data.outputDataLenRange, output_capacity_range: data.outputCapacityRange, block_range: data.blockRange, + script_len_range: data.scriptLenRange, }; }; @@ -23,4 +29,24 @@ const toSearchKey = (data: SearchKey): RPCType.SearchKey => ({ filter: data.filter ? toSearchFilter(data.filter) : data.filter, }); -export { toScript, toSearchKey, toSearchFilter }; +const toGetCellsSearchKey = ( + data: GetCellsSearchKey +): RPCType.GetCellsSearchKey => ({ + ...toSearchKey(data), + with_data: data.withData, +}); + +const toGetTransactionsSearchKey = ( + data: GetTransactionsSearchKey +): RPCType.GetTransactionsSearchKey => ({ + ...toSearchKey(data), + group_by_transaction: data.groupByTransaction, +}); + +export { + toScript, + toSearchKey, + toGetCellsSearchKey, + toGetTransactionsSearchKey, + toSearchFilter, +}; diff --git a/packages/ckb-indexer/src/resultFormatter.ts b/packages/ckb-indexer/src/resultFormatter.ts index 0828836bc..66ac46cf9 100644 --- a/packages/ckb-indexer/src/resultFormatter.ts +++ b/packages/ckb-indexer/src/resultFormatter.ts @@ -27,6 +27,7 @@ const toSearchFilter = (data: RPCType.SearchFilter): SearchFilter => { script: data.script ? toScript(data.script) : data.script, outputDataLenRange: data.output_data_len_range, outputCapacityRange: data.output_capacity_range, + scriptLenRange: data.script_len_range, blockRange: data.block_range, }; }; diff --git a/packages/ckb-indexer/src/rpc.ts b/packages/ckb-indexer/src/rpc.ts index 17142633c..a32413e80 100644 --- a/packages/ckb-indexer/src/rpc.ts +++ b/packages/ckb-indexer/src/rpc.ts @@ -3,10 +3,14 @@ import { GetLiveCellsResult, IndexerTransactionList, Order, - SearchKey, + GetCellsSearchKey, + GetTransactionsSearchKey, } from "./type"; import fetch from "cross-fetch"; -import { toSearchKey } from "./paramsFormatter"; +import { + toGetCellsSearchKey, + toGetTransactionsSearchKey, +} from "./paramsFormatter"; export class RPC { private uri: string; @@ -22,22 +26,28 @@ export class RPC { async getTip(): Promise { return utils.deepCamel(await request(this.uri, "get_tip")); } - async getCells( - searchKey: SearchKey, + async getCells( + searchKey: GetCellsSearchKey, order: Order, limit: HexString, cursor?: string - ): Promise { - const params = [toSearchKey(searchKey), order, limit, cursor]; + ): Promise> { + const params = [toGetCellsSearchKey(searchKey), order, limit, cursor]; return utils.deepCamel(await request(this.uri, "get_cells", params)); } - async getTransactions( - searchKey: SearchKey, + + async getTransactions( + searchKey: GetTransactionsSearchKey, order: Order, limit: HexString, cursor?: string - ): Promise { - const params = [toSearchKey(searchKey), order, limit, cursor]; + ): Promise> { + const params = [ + toGetTransactionsSearchKey(searchKey), + order, + limit, + cursor, + ]; return utils.deepCamel(await request(this.uri, "get_transactions", params)); } async getIndexerInfo(): Promise { diff --git a/packages/ckb-indexer/src/rpcType.ts b/packages/ckb-indexer/src/rpcType.ts index a553eaa70..3a6660561 100644 --- a/packages/ckb-indexer/src/rpcType.ts +++ b/packages/ckb-indexer/src/rpcType.ts @@ -27,9 +27,17 @@ export interface SearchFilter { output_data_len_range?: HexadecimalRange; //empty output_capacity_range?: HexadecimalRange; //empty block_range?: HexadecimalRange; //fromBlock-toBlock + script_len_range?: HexadecimalRange; } export interface SearchKey { script: Script; script_type: ScriptType; filter?: SearchFilter; } +export interface GetCellsSearchKey extends SearchKey { + with_data?: boolean; +} + +export interface GetTransactionsSearchKey extends SearchKey { + group_by_transaction?: boolean; +} diff --git a/packages/ckb-indexer/src/services.ts b/packages/ckb-indexer/src/services.ts index 6e2ce87fc..be5ccdc69 100644 --- a/packages/ckb-indexer/src/services.ts +++ b/packages/ckb-indexer/src/services.ts @@ -49,6 +49,9 @@ const generateSearchKey = (queries: CKBIndexerQueryOptions): SearchKey => { if (queries.outputCapacityRange) { filter.output_capacity_range = queries.outputCapacityRange; } + if (queries.scriptLenRange) { + filter.script_len_range = queries.scriptLenRange; + } if (!script) { throw new Error("Either lock or type script must be provided!"); } diff --git a/packages/ckb-indexer/src/type.ts b/packages/ckb-indexer/src/type.ts index 52fb6c6af..430fdefc3 100644 --- a/packages/ckb-indexer/src/type.ts +++ b/packages/ckb-indexer/src/type.ts @@ -18,12 +18,16 @@ export type Order = "asc" | "desc"; export interface CKBIndexerQueryOptions extends QueryOptions { outputDataLenRange?: HexadecimalRange; outputCapacityRange?: HexadecimalRange; + scriptLenRange?: HexadecimalRange; bufferSize?: number; + withData?: boolean; + groupByTransaction?: boolean; } export type HexadecimalRange = [Hexadecimal, Hexadecimal]; export interface SearchFilter { script?: Script; + scriptLenRange?: HexadecimalRange; outputDataLenRange?: HexadecimalRange; //empty outputCapacityRange?: HexadecimalRange; //empty blockRange?: HexadecimalRange; //fromBlock-toBlock @@ -33,9 +37,19 @@ export interface SearchKey { scriptType: ScriptType; filter?: SearchFilter; } -export interface GetLiveCellsResult { +export interface GetLiveCellsResult { lastCursor: string; - objects: IndexerCell[]; + objects: WithData extends true ? IndexerCell[] : IndexerCellWithoutData[]; +} + +export interface GetCellsSearchKey + extends SearchKey { + withData?: WithData; +} + +export interface GetTransactionsSearchKey + extends SearchKey { + groupByTransaction?: Group; } export interface rpcResponse { @@ -59,6 +73,12 @@ export interface IndexerCell { outputData: HexString; txIndex: Hexadecimal; } + +export interface IndexerCellWithoutData + extends Omit { + outputData: null; +} + export interface TerminatorResult { stop: boolean; push: boolean; @@ -72,16 +92,31 @@ export declare type Terminator = ( export type HexNum = string; export type IOType = "input" | "output" | "both"; export type Bytes32 = string; -export type IndexerTransaction = { +export type IndexerTransaction = + Goruped extends true + ? GroupedIndexerTransaction + : UngroupedIndexerTransaction; + +export type UngroupedIndexerTransaction = { blockNumber: HexNum; ioIndex: HexNum; ioType: IOType; txHash: Bytes32; txIndex: HexNum; }; -export interface IndexerTransactionList { + +export type GroupedIndexerTransaction = { + txHash: Bytes32; + blockNumber: HexNum; + txIndex: HexNum; + cells: Array<[IOType, HexNum]>; +}; + +export interface IndexerTransactionList { lastCursor: string | undefined; - objects: IndexerTransaction[]; + objects: Grouped extends true + ? GroupedIndexerTransaction[] + : UngroupedIndexerTransaction[]; } export interface GetCellsResults { diff --git a/packages/ckb-indexer/tests/cell_collector.unit.test.ts b/packages/ckb-indexer/tests/cell_collector.unit.test.ts index aa4dabe40..5bb445e76 100644 --- a/packages/ckb-indexer/tests/cell_collector.unit.test.ts +++ b/packages/ckb-indexer/tests/cell_collector.unit.test.ts @@ -1,7 +1,7 @@ import test from "ava"; import { Indexer, CellCollector } from "../src"; import { HexadecimalRange, Script, utils } from "@ckb-lumos/base"; -import sinon, { SinonSpy } from "sinon"; +import { spy, SinonSpy } from "sinon"; import { validators } from "@ckb-lumos/toolkit"; const nodeUri = "http://127.0.0.1:8118/rpc"; @@ -11,8 +11,8 @@ const indexer = new Indexer(indexUri, nodeUri); let validateScriptSpy: SinonSpy; let utilsSpy: SinonSpy; test.before(() => { - validateScriptSpy = sinon.spy(validators, "ValidateScript"); - utilsSpy = sinon.spy(utils, "assertHexadecimal"); + validateScriptSpy = spy(validators, "ValidateScript"); + utilsSpy = spy(utils, "assertHexadecimal"); }); test.afterEach(() => { validateScriptSpy.resetHistory(); @@ -65,6 +65,27 @@ test("convertParams# should match outputDataRange if data and outputData both de t.is(error.message, "data length not match outputDataLenRange"); }); +test("convertParams# should match scriptLenRange if type is 'empty' and scriptLenRange not provide", (t) => { + const cellCollect = new CellCollector(indexer, { + lock: lockScript, + type: "empty", + order: "asc", + }); + cellCollect.convertQueryOptionToSearchKey(); + + t.deepEqual(cellCollect.queries.scriptLenRange, ["0x0", "0x1"]); + + const cellCollect2 = new CellCollector(indexer, { + lock: lockScript, + scriptLenRange: ["0x0", "0xff"], + type: "empty", + order: "asc", + }); + cellCollect2.convertQueryOptionToSearchKey(); + + t.deepEqual(cellCollect2.queries.scriptLenRange, ["0x0", "0xff"]); +}); + test("validateQueryOption#should throw error if lock and type not provided", (t) => { t.throws( () => { @@ -156,3 +177,34 @@ test("validateQueryOption#validate outputDataLenRange", (t) => { t.is(utilsSpy.calledWith("outputDataLenRange[0]", "0x100"), true); t.is(utilsSpy.calledWith("outputDataLenRange[1]", "0x200"), true); }); + +test("validateQueryOption#validate scriptLenRange", (t) => { + const scriptLenRange: HexadecimalRange = ["0x0", "0x1"]; + const query = { + lock: lockScript, + scriptLenRange, + }; + new CellCollector(indexer, query); + t.is(utilsSpy.calledWith("scriptLenRange[0]", "0x0"), true); + t.is(utilsSpy.calledWith("scriptLenRange[1]", "0x1"), true); + + const wrongQuery = { + lock: lockScript, + data: "0x664455", + scriptLenRange: ["something", "0x1"] as HexadecimalRange, + }; + const error = t.throws(() => { + new CellCollector(indexer, wrongQuery); + }); + t.is(error.message, "scriptLenRange[0] must be a hexadecimal!"); + + const wrongQuery2 = { + lock: lockScript, + data: "0x664455", + scriptLenRange: ["0x0", "something"] as HexadecimalRange, + }; + const error2 = t.throws(() => { + new CellCollector(indexer, wrongQuery2); + }); + t.is(error2.message, "scriptLenRange[1] must be a hexadecimal!"); +}); diff --git a/packages/ckb-indexer/tests/indexer.e2e.test.ts b/packages/ckb-indexer/tests/indexer.e2e.test.ts index 71db97f5d..09baff128 100644 --- a/packages/ckb-indexer/tests/indexer.e2e.test.ts +++ b/packages/ckb-indexer/tests/indexer.e2e.test.ts @@ -1,4 +1,4 @@ -import sinon from "sinon"; +import { stub, spy } from "sinon"; import test from "ava"; import fs from "fs"; import path from "path"; @@ -30,7 +30,7 @@ async function asyncRetry( test("subscribe cells", async (t) => { let blockIndex = 0; - const stub = sinon.stub(indexer, "tip").callsFake(() => { + const _stub = stub(indexer, "tip").callsFake(() => { const blocks = JSON.parse( fs.readFileSync(path.join(__dirname, "./blocks_data.json")).toString() ); @@ -45,20 +45,20 @@ test("subscribe cells", async (t) => { }); for (const queryCase of indexerSubscribeTestCases) { - let spy = sinon.spy(); + let _spy = spy(); const eventEmitter = indexer.subscribe(queryCase.queryOption); eventEmitter.on("changed", spy); asyncRetry( () => { - return spy.callCount >= queryCase.expectedResult; + return _spy.callCount >= queryCase.expectedResult; }, 1000, 10000 ).then(() => { - t.is(spy.callCount, queryCase.expectedResult, queryCase.desc); - stub.resetHistory(); + t.is(_spy.callCount, queryCase.expectedResult, queryCase.desc); + _stub.resetHistory(); blockIndex = 0; - spy.resetHistory(); + _spy.resetHistory(); }); } }); diff --git a/packages/ckb-indexer/tests/indexer.unit.test.ts b/packages/ckb-indexer/tests/indexer.unit.test.ts index 696a37fe1..0634aa0f5 100644 --- a/packages/ckb-indexer/tests/indexer.unit.test.ts +++ b/packages/ckb-indexer/tests/indexer.unit.test.ts @@ -1,6 +1,6 @@ import { HashType } from "@ckb-lumos/base"; import test from "ava"; -import sinon from "sinon"; +import { stub } from "sinon"; import { Indexer } from "../src"; import { CKBIndexerQueryOptions, IndexerEmitter } from "../src/type"; const nodeUri = "http://127.0.0.1:8118/rpc"; @@ -9,7 +9,7 @@ const indexer = new Indexer(indexUri, nodeUri); test.before(() => { // @ts-ignore - sinon.stub(indexer, "scheduleLoop").callsFake(() => {}); + stub(indexer, "scheduleLoop").callsFake(() => {}); }); test("test subscrib by script", (t) => { diff --git a/packages/ckb-indexer/tests/paramsFormatter.unit.test.ts b/packages/ckb-indexer/tests/paramsFormatter.unit.test.ts index 37907d810..2ea549842 100644 --- a/packages/ckb-indexer/tests/paramsFormatter.unit.test.ts +++ b/packages/ckb-indexer/tests/paramsFormatter.unit.test.ts @@ -28,6 +28,7 @@ test("should toSearchKey works fine", async (t) => { script: undefined, block_range: undefined, output_capacity_range: undefined, + script_len_range: undefined, output_data_len_range: ["0x1", "0x2"], }, }; diff --git a/packages/ckb-indexer/tests/resultFormatter.unit.test.ts b/packages/ckb-indexer/tests/resultFormatter.unit.test.ts index d956984cb..8b81e7cb3 100644 --- a/packages/ckb-indexer/tests/resultFormatter.unit.test.ts +++ b/packages/ckb-indexer/tests/resultFormatter.unit.test.ts @@ -27,6 +27,7 @@ test("should toSearchKey works fine", async (t) => { filter: { script: undefined, outputCapacityRange: undefined, + scriptLenRange: undefined, blockRange: undefined, outputDataLenRange: ["0x1", "0x2"], }, diff --git a/packages/ckb-indexer/tests/rpc.e2e.test.ts b/packages/ckb-indexer/tests/rpc.e2e.test.ts index 027b671a6..4fecc7552 100644 --- a/packages/ckb-indexer/tests/rpc.e2e.test.ts +++ b/packages/ckb-indexer/tests/rpc.e2e.test.ts @@ -1,9 +1,12 @@ -import { Tip } from "@ckb-lumos/base"; +import { Tip, Script } from "@ckb-lumos/base"; import test from "ava"; -import { Indexer } from "../src"; -const indexerUri = "http://127.0.0.1:8120"; -const rpcUri = "http://127.0.0.1:8118"; -const ckbIndexer = new Indexer(indexerUri, rpcUri); +import { Indexer, RPC } from "../src"; + +const indexerRpcUri = "http://127.0.0.1:8120"; +const ckbRpcUri = "http://127.0.0.1:8118"; +const ckbIndexer = new Indexer(indexerRpcUri, ckbRpcUri); +const indexerRpc = new RPC(indexerRpcUri); + test.before(() => { // @ts-ignore: Unreachable code error BigInt = () => { @@ -20,3 +23,126 @@ test("get tip", async (t) => { const tip = await ckbIndexer.tip(); t.deepEqual(tip, expectTip); }); + +test("indexer rpc get tips", async (t) => { + const expectTip: Tip = { + blockHash: + "0x4d0913d3d9330b1f2acf70d1b38baffa1d0588a92b006be3c5a0ca031e9841c7", + blockNumber: "0x63", + }; + const tip = await indexerRpc.getTip(); + t.deepEqual(tip, expectTip); +}); + +test("indexer rpc get cells without data", async (t) => { + const lock: Script = { + codeHash: + "0x9bd7e06f3ecf4be0f2fcd2188b23f1b9fcc88e5d4b65a8637b17723bbda3cce8", + hashType: "type", + args: "0x19c5d58c535273452ac60f9d37831601adcf12b8", + }; + + const notsetWithDataCells = await indexerRpc.getCells( + { + script: lock, + scriptType: "lock", + }, + "asc", + "0x64" + ); + t.deepEqual( + notsetWithDataCells.objects[0].outputData, + "0x5468616e6b20796f75205361746f7368692e" + ); + + const withDataCells = await indexerRpc.getCells( + { + script: lock, + scriptType: "lock", + withData: true, + }, + "asc", + "0x64" + ); + t.deepEqual( + withDataCells.objects[0].outputData, + "0x5468616e6b20796f75205361746f7368692e" + ); + + const withoutDataCells = await indexerRpc.getCells( + { + script: lock, + scriptType: "lock", + withData: false, + }, + "asc", + "0x64" + ); + t.deepEqual(withoutDataCells.objects[0].outputData, null); +}); + +test("indexer rpc get cells with script_len_range param", async (t) => { + const lock: Script = { + codeHash: + "0x9bd7e06f3ecf4be0f2fcd2188b23f1b9fcc88e5d4b65a8637b17723bbda3cce8", + hashType: "type", + args: "0xb5a27e6b01d309135b06089ce192a267ceada8ea", + }; + + const allCells = await indexerRpc.getCells( + { + script: lock, + scriptType: "lock", + }, + "asc", + "0x64" + ); + t.deepEqual(allCells.objects.length, 1); + t.notDeepEqual(allCells.objects[0].outputData, null); + + const filteredCells = await indexerRpc.getCells( + { + script: lock, + scriptType: "lock", + filter: { + scriptLenRange: ["0x0", "0x1"], + }, + }, + "asc", + "0x64" + ); + t.deepEqual(filteredCells.objects.length, 0); +}); + +test("indexer rpc get group by hash transactions", async (t) => { + const lock: Script = { + codeHash: + "0x9bd7e06f3ecf4be0f2fcd2188b23f1b9fcc88e5d4b65a8637b17723bbda3cce8", + hashType: "type", + args: "0x19c5d58c535273452ac60f9d37831601adcf12b8", + }; + + const ungroupedTransactions = await indexerRpc.getTransactions( + { + script: lock, + scriptType: "lock", + }, + "asc", + "0x64" + ); + t.deepEqual(ungroupedTransactions.objects[0].ioIndex, "0x0"); + t.deepEqual(ungroupedTransactions.objects[0].ioType, "output"); + + const groupedTransactions = await indexerRpc.getTransactions( + { + script: lock, + scriptType: "lock", + groupByTransaction: true, + }, + "asc", + "0x64" + ); + t.deepEqual(groupedTransactions.objects[0].cells.length, 1); + t.deepEqual(groupedTransactions.objects[0].cells[0][0], "output"); + t.deepEqual(groupedTransactions.objects[0].cells[0][1], "0x0"); +}); diff --git a/packages/ckb-indexer/tests/service.unit.test.ts b/packages/ckb-indexer/tests/service.unit.test.ts index f48ab527a..3fc1dbf79 100644 --- a/packages/ckb-indexer/tests/service.unit.test.ts +++ b/packages/ckb-indexer/tests/service.unit.test.ts @@ -15,6 +15,7 @@ test("should generateSearchKey works fine", async (t) => { script: undefined, outputCapacityRange: undefined, blockRange: undefined, + scriptLenRange: undefined, outputDataLenRange: ["0x1", "0x2"], }, }; diff --git a/packages/ckb-indexer/tests/test_cases.js b/packages/ckb-indexer/tests/test_cases.js index a6e3d147f..d46a18a75 100644 --- a/packages/ckb-indexer/tests/test_cases.js +++ b/packages/ckb-indexer/tests/test_cases.js @@ -8152,6 +8152,14 @@ const cellCollectorTestCases = [ }, expectedResult: [], }, + { + desc: "Test query cells by lock and script length range and return empty result", + queryOption: { + lock: lockInNervosDAO, + scriptLenRange: ["0x0", "0x1"], + }, + expectedResult: [], + }, { desc: "Test query cells by bufferSize 3 and can get all", diff --git a/packages/ckb-indexer/tests/transaction_collector.unit.test.ts b/packages/ckb-indexer/tests/transaction_collector.unit.test.ts index 2ce162ecc..1de45a3e5 100644 --- a/packages/ckb-indexer/tests/transaction_collector.unit.test.ts +++ b/packages/ckb-indexer/tests/transaction_collector.unit.test.ts @@ -1,7 +1,7 @@ import test from "ava"; import { Indexer, TransactionCollector } from "../src"; import { JsonRprRequestBody } from "../src/type"; -import sinon, { SinonStub } from "sinon"; +import { stub, SinonStub } from "sinon"; import * as services from "../src/services"; import { @@ -18,7 +18,7 @@ const indexUri = "http://127.0.0.1:8120"; const indexer = new Indexer(indexUri, nodeUri); let requestBatchStub: SinonStub; test.before(() => { - requestBatchStub = sinon.stub(services, "requestBatch"); + requestBatchStub = stub(services, "requestBatch"); }); test.afterEach(() => { requestBatchStub.resetHistory(); diff --git a/packages/testkit/src/ckb-indexer-helper.ts b/packages/testkit/src/ckb-indexer-helper.ts index 3c94556d3..7de4bd61c 100644 --- a/packages/testkit/src/ckb-indexer-helper.ts +++ b/packages/testkit/src/ckb-indexer-helper.ts @@ -8,40 +8,59 @@ function log(info: string): void { console.log(info); } +let CKB_Indexer_Version = "0.2.2"; + function getDownloadOsType() { + const isOldVersion = parseInt(CKB_Indexer_Version.split(".")[1]) < 4; // before v4.0 // it returns 'Linux' on Linux, 'Darwin' on macOS, and 'Windows_NT' on Windows. const osType = os.type(); if (osType === "Linux") return "linux"; - if (osType === "Darwin") return "macos"; + if (osType === "Darwin" && isOldVersion) return "macos"; + if (osType === "Darwin") return "mac"; + // TODO support windows // if (osType === "Windows_NT") return "windows"; throw new Error(`Unknown OS Type: ${osType}`); } -let CKB_Indexer_Version = "0.2.2"; const download = async () => { + const isOldVersion = parseInt(CKB_Indexer_Version.split(".")[1]) < 4; // before v4.0 const osType = getDownloadOsType(); log("ckb-indexer not exist, downloading"); log(`cwd is ${process.cwd()}`); - const downloadUrl = `https://github.com/nervosnetwork/ckb-indexer/releases/download/v${CKB_Indexer_Version}/ckb-indexer-${CKB_Indexer_Version}-${osType}.zip`; + + const fileName = `ckb-indexer-${CKB_Indexer_Version}-${osType}${ + isOldVersion ? "" : "-x86_64" + }.${osType === "linux" ? "tar.gz" : "zip"}`; + + const downloadUrl = `https://github.com/nervosnetwork/ckb-indexer/releases/download/v${CKB_Indexer_Version}/${fileName}`; + + log( + `fileName is ${fileName}, osType is ${osType}, downloadUrl is ${downloadUrl}` + ); // TODO use option to extract await downloadAndExtract(downloadUrl, process.cwd()); // const downloadCmd = `curl -O -L "${downloadUrl}"`; // shell.exec(downloadCmd); - shell.exec(`unzip -o ./ckb-indexer-${CKB_Indexer_Version}-${osType}.zip`); if (osType === "macos") { - shell.exec(`unzip -o ./ckb-indexer-mac-x86_64.zip`); + log(`exec unzip -o ./${fileName} -x README.md`); + shell.exec(`unzip -o ./${fileName} -x README.md`); + shell.chmod("+x", "./ckb-indexer"); + shell.rm("-rf", fileName); + } else if (osType === "mac") { + log(`exec unzip -o ./${fileName} -x README.md`); + shell.exec(`unzip -o ./${fileName} -x README.md`); shell.chmod("+x", "./ckb-indexer"); - shell.rm("-rf", "ckb-indexer-linux-x86_64.zip"); + shell.rm("-rf", fileName); } else if (osType === "linux") { - shell.exec(`tar xvzf ./ckb-indexer-linux-x86_64.tar.gz ckb-indexer`); + shell.exec(`tar xvzf ./${fileName} ckb-indexer`); shell.chmod("+x", "./ckb-indexer"); - shell.rm("-rf", "ckb-indexer-linux-x86_64.tar.gz"); + shell.rm("-rf", fileName); } - shell.rm(`ckb-indexer-${CKB_Indexer_Version}-${osType}.zip`); + shell.rm(fileName); log("artifacts removed"); };