├── .dockerignore ├── .editorconfig ├── .eslintignore ├── .eslintrc.js ├── .github ├── ISSUE_TEMPLATE.md ├── PULL_REQUEST_TEMPLATE.md ├── actions │ ├── create-prerelease │ │ ├── action.yml │ │ └── remove-stable-version.js │ └── create-release │ │ ├── action.yml │ │ └── gh-release-script.js └── workflows │ ├── benchmark.yml │ ├── discord.yml │ ├── gh-release.yml │ ├── node-docker.yml │ ├── pr.yml │ ├── prerelease.yml │ ├── query-docker.yml │ ├── release.yml │ └── scripts │ ├── benchmark │ ├── Dockerfile │ ├── benchmarking.sh │ ├── cleanHistory.sh │ └── queryMeta.sh │ ├── nodeVersion.sh │ └── queryVersion.sh ├── .gitignore ├── .gitpod.dockerfile ├── .gitpod.yml ├── .husky ├── .gitignore └── pre-commit ├── .prettierignore ├── .prettierrc ├── .yarn ├── plugins │ └── @yarnpkg │ │ ├── plugin-interactive-tools.cjs │ │ ├── plugin-typescript.cjs │ │ ├── plugin-version.cjs │ │ └── plugin-workspace-tools.cjs ├── releases │ └── yarn-3.2.4.cjs └── versions │ ├── 043f60d9.yml │ ├── 06878261.yml │ ├── 12f2ee2a.yml │ ├── 1447e381.yml │ ├── 1c09bcf3.yml │ ├── 29bf85e7.yml │ ├── 2d61ee26.yml │ ├── 2eebe132.yml │ ├── 33e756ee.yml │ ├── 351b62d7.yml │ ├── 3fbcf2a0.yml │ ├── 4078a944.yml │ ├── 46b26b5d.yml │ ├── 48ba8de1.yml │ ├── 4c39a3cb.yml │ ├── 4d1a19ef.yml │ ├── 4de1b78e.yml │ ├── 4ef73239.yml │ ├── 5284b2e3.yml │ ├── 532ac853.yml │ ├── 53f030f6.yml │ ├── 5c14c916.yml │ ├── 6b90a9bc.yml │ ├── 6cdd41ea.yml │ ├── 6ffda578.yml │ ├── 74e58e5b.yml │ ├── 7c0eab27.yml │ ├── 857e5ecd.yml │ ├── 86ccde0d.yml │ ├── 91e494d1.yml │ ├── 92e577ad.yml │ ├── a2c2414d.yml │ ├── abc53221.yml │ ├── ad1e1894.yml │ ├── b03d4318.yml │ ├── b426a40b.yml │ ├── bd58ec77.yml │ ├── ca56439e.yml │ ├── d2d9e21c.yml │ ├── d408027a.yml │ ├── d8be227b.yml │ ├── d9e0b292.yml │ ├── da057245.yml │ ├── db4f7e5e.yml │ ├── dbefade5.yml │ ├── e67c5647.yml │ ├── e6985a5f.yml │ ├── e7d60c2f.yml │ ├── f2404812.yml │ ├── f5fd9c46.yml │ ├── fd2e440b.yml │ └── ff271075.yml ├── .yarnrc.yml ├── CODE_OF_CONDUCT.md ├── LICENSE ├── README.md ├── SECURITY.md ├── babel.config.js ├── contributing.md ├── crowdin.yaml ├── deploy ├── k8s │ ├── README.md │ └── deploy.yaml └── logging_debug.png ├── jest.config.js ├── package.json ├── packages ├── cli │ ├── CHANGELOG.md │ ├── LICENSE │ ├── README.md │ ├── bin │ │ ├── run │ │ └── run.cmd │ ├── package.json │ ├── src │ │ ├── commands │ │ │ ├── build │ │ │ │ └── index.ts │ │ │ ├── codegen │ │ │ │ ├── generate.ts │ │ │ │ └── index.ts │ │ │ ├── deployment │ │ │ │ ├── delete.ts │ │ │ │ ├── deploy.ts │ │ │ │ ├── index.ts │ │ │ │ └── promote.ts │ │ │ ├── init.ts │ │ │ ├── migrate.test.ts │ │ │ ├── migrate.ts │ │ │ ├── multi-chain │ │ │ │ ├── add.ts │ │ │ │ └── deploy.ts │ │ │ ├── project │ │ │ │ ├── create-project.ts │ │ │ │ ├── delete-project.ts │ │ │ │ └── index.ts │ │ │ ├── publish.test.ts │ │ │ └── publish.ts │ │ ├── constants.ts │ │ ├── controller │ │ │ ├── add-chain-controller.spec.ts │ │ │ ├── add-chain-controller.ts │ │ │ ├── build-controller.ts │ │ │ ├── codegen-controller.spec.ts │ │ │ ├── codegen-controller.test.ts │ │ │ ├── codegen-controller.ts │ │ │ ├── codegen-cosmos.test.ts │ │ │ ├── deploy-controller.spec.ts │ │ │ ├── deploy-controller.test.ts │ │ │ ├── deploy-controller.ts │ │ │ ├── generate-controller.spec.ts │ │ │ ├── generate-controller.test.ts │ │ │ ├── generate-controller.ts │ │ │ ├── init-controller.spec.ts │ │ │ ├── init-controller.test.ts │ │ │ ├── init-controller.ts │ │ │ ├── migrate │ │ │ │ ├── abis │ │ │ │ │ └── migrate-abis.controller.ts │ │ │ │ ├── constants.ts │ │ │ │ ├── index.ts │ │ │ │ ├── manifest │ │ │ │ │ ├── ethereum.spec.ts │ │ │ │ │ ├── ethereum.ts │ │ │ │ │ ├── migrate-manifest.controller.spec.ts │ │ │ │ │ └── migrate-manifest.controller.ts │ │ │ │ ├── mapping │ │ │ │ │ └── migrate-mapping.controller.ts │ │ │ │ ├── migrate-controller.spec.ts │ │ │ │ ├── migrate-controller.ts │ │ │ │ ├── migrate.fixtures.ts │ │ │ │ ├── schema │ │ │ │ │ └── migrate-schema.controller.ts │ │ │ │ └── types.ts │ │ │ ├── project-controller.spec.ts │ │ │ ├── project-controller.ts │ │ │ ├── publish-controller.spec.ts │ │ │ ├── publish-controller.ts │ │ │ └── validate.spec.ts │ │ ├── createProject.fixtures.ts │ │ ├── index.ts │ │ ├── jsonrpc │ │ │ ├── client │ │ │ │ ├── http.ts │ │ │ │ ├── index.ts │ │ │ │ ├── types.ts │ │ │ │ └── ws.ts │ │ │ ├── index.ts │ │ │ └── jsonrpc.test.ts │ │ ├── template │ │ │ ├── datasource-templates.ts.ejs │ │ │ ├── enum.ts.ejs │ │ │ ├── interface.ts.ejs │ │ │ ├── model.ts.ejs │ │ │ ├── models-index.ts.ejs │ │ │ ├── project.ts.ejs │ │ │ ├── scaffold-handlers.ts.ejs │ │ │ └── types-index.ts.ejs │ │ ├── types.ts │ │ └── utils │ │ │ ├── build.spec.ts │ │ │ ├── build.ts │ │ │ ├── index.ts │ │ │ ├── networkFamily.spec.ts │ │ │ ├── networkFamily.ts │ │ │ └── utils.ts │ ├── test │ │ ├── abiTest1 │ │ │ ├── abis │ │ │ │ ├── abis.json │ │ │ │ ├── artifact.json │ │ │ │ └── artifact.sol │ │ │ │ │ └── artifact.json │ │ │ └── project.yaml │ │ ├── abiTest2 │ │ │ ├── abis │ │ │ │ └── artifact.json │ │ │ └── project.yaml │ │ ├── migrate │ │ │ └── testProject │ │ │ │ ├── package.json │ │ │ │ └── subgraph.yaml │ │ ├── protoTest1 │ │ │ ├── project.yaml │ │ │ └── proto │ │ │ │ ├── cosmos │ │ │ │ └── base │ │ │ │ │ └── v1beta1 │ │ │ │ │ └── coin.proto │ │ │ │ └── osmosis │ │ │ │ ├── gamm │ │ │ │ └── v1beta1 │ │ │ │ │ └── tx.proto │ │ │ │ └── poolmanager │ │ │ │ └── v1beta1 │ │ │ │ └── swap_route.proto │ │ ├── schemaTest │ │ │ ├── abis │ │ │ │ └── erc721.json │ │ │ ├── badEntity.graphql │ │ │ ├── badschema.graphql │ │ │ ├── generate-project-2.yaml │ │ │ ├── generate-project.yaml │ │ │ ├── non-evm-project.yaml │ │ │ ├── package.json │ │ │ ├── project-bad-entity.yaml │ │ │ ├── project-bad-schema.yaml │ │ │ ├── project-cosmos.yaml │ │ │ ├── project-no-abi.yaml │ │ │ ├── project-no-assets.yaml │ │ │ ├── project-templates-abi.yaml │ │ │ ├── project.ts │ │ │ ├── project.yaml │ │ │ ├── schema.graphql │ │ │ └── typechain-test.yaml │ │ ├── ts-manifest │ │ │ ├── erc20.json │ │ │ └── project.ts │ │ └── tsManifestTest │ │ │ ├── project1.ts │ │ │ ├── project2.ts │ │ │ ├── project3.yaml │ │ │ ├── subquery-multichain.ts │ │ │ ├── subquery-multichain2.ts │ │ │ ├── subquery-multichain3.ts │ │ │ └── subquery-multichain4.yaml │ └── tsconfig.json ├── common-substrate │ ├── CHANGELOG.md │ ├── LICENSE │ ├── package.json │ ├── src │ │ ├── index.ts │ │ └── project │ │ │ ├── index.ts │ │ │ ├── load.spec.ts │ │ │ ├── load.ts │ │ │ ├── models.ts │ │ │ ├── project.spec.ts │ │ │ ├── types.ts │ │ │ ├── utils.ts │ │ │ └── versioned │ │ │ ├── ProjectManifestVersioned.ts │ │ │ ├── index.ts │ │ │ └── v1_0_0 │ │ │ ├── index.ts │ │ │ └── model.ts │ ├── test │ │ ├── project_1.0.0.yaml │ │ ├── project_1.0.0_bad_processor.yaml │ │ ├── project_1.0.0_bad_runner.yaml │ │ ├── project_1.0.0_bad_runner_version.yaml │ │ ├── project_1.0.0_chainId.yaml │ │ ├── project_1.0.0_custom_ds.yaml │ │ ├── project_1.0.0_falsy.yaml │ │ ├── project_1.0.0_falsy_array.yaml │ │ ├── project_1.0.0_node_options.yaml │ │ ├── project_1.0.0_runner_ds_mismatch.yaml │ │ ├── project_bypass.yaml │ │ ├── project_bypass_range.yaml │ │ └── project_invalid_version.yaml │ └── tsconfig.json ├── common │ ├── CHANGELOG.md │ ├── LICENSE │ ├── fixtures │ │ ├── package.json │ │ └── project.yaml │ ├── package.json │ ├── src │ │ ├── constants.ts │ │ ├── index.ts │ │ ├── multichain │ │ │ ├── index.ts │ │ │ └── models.ts │ │ └── project │ │ │ ├── database │ │ │ ├── databaseUtil.ts │ │ │ └── index.ts │ │ │ ├── index.ts │ │ │ ├── load.ts │ │ │ ├── readers │ │ │ ├── github-reader.spec.ts │ │ │ ├── github-reader.ts │ │ │ ├── index.ts │ │ │ ├── ipfs-reader.spec.ts │ │ │ ├── ipfs-reader.ts │ │ │ ├── local-reader.spec.ts │ │ │ ├── local-reader.ts │ │ │ ├── reader.spec.ts │ │ │ └── reader.ts │ │ │ ├── utils.ts │ │ │ └── versioned │ │ │ ├── base.ts │ │ │ ├── index.ts │ │ │ └── v1_0_0 │ │ │ ├── index.ts │ │ │ └── models.ts │ ├── test │ │ ├── mockedSubqueryProject.tgz │ │ ├── project.yaml │ │ ├── project_0.2.0.yaml │ │ ├── project_0.2.0_custom_ds.yaml │ │ ├── project_0.2.0_invalid_custom_ds.yaml │ │ ├── project_falsy.yaml │ │ ├── project_falsy_array.yaml │ │ └── project_invalid_version.yaml │ └── tsconfig.json ├── node-core │ ├── CHANGELOG.md │ ├── LICENSE │ ├── logger.js │ ├── package.json │ ├── src │ │ ├── api.connection.error.ts │ │ ├── api.service.spec.ts │ │ ├── api.service.ts │ │ ├── configure │ │ │ ├── NodeConfig.spec.ts │ │ │ ├── NodeConfig.ts │ │ │ ├── ProjectUpgrade.service.spec.ts │ │ │ ├── ProjectUpgrade.service.ts │ │ │ ├── configure.module.spec.ts │ │ │ ├── configure.module.ts │ │ │ └── index.ts │ │ ├── db │ │ │ ├── db.module.test.ts │ │ │ ├── db.module.ts │ │ │ ├── index.ts │ │ │ ├── migration-service │ │ │ │ ├── SchemaMigration.service.spec.ts │ │ │ │ ├── SchemaMigration.service.test.ts │ │ │ │ ├── SchemaMigration.service.ts │ │ │ │ ├── index.ts │ │ │ │ ├── migration-helpers.ts │ │ │ │ └── migration.ts │ │ │ ├── sequelizeUtil.ts │ │ │ ├── sync-helper.spec.ts │ │ │ └── sync-helper.ts │ │ ├── events.ts │ │ ├── index.ts │ │ ├── indexer │ │ │ ├── StoreOperations.spec.ts │ │ │ ├── StoreOperations.ts │ │ │ ├── benchmark.service.ts │ │ │ ├── blockDispatcher │ │ │ │ ├── base-block-dispatcher.ts │ │ │ │ ├── block-dispatcher.ts │ │ │ │ ├── index.ts │ │ │ │ ├── worker-block-dispatcher.spec.ts │ │ │ │ └── worker-block-dispatcher.ts │ │ │ ├── connectionPool.service.spec.ts │ │ │ ├── connectionPool.service.ts │ │ │ ├── connectionPoolState.manager.spec.ts │ │ │ ├── connectionPoolState.manager.ts │ │ │ ├── dictionary │ │ │ │ ├── coreDictionary.ts │ │ │ │ ├── dictionary.fixtures.ts │ │ │ │ ├── dictionary.service.spec.ts │ │ │ │ ├── dictionary.service.ts │ │ │ │ ├── index.ts │ │ │ │ ├── types.ts │ │ │ │ ├── utils.spec.ts │ │ │ │ ├── utils.ts │ │ │ │ ├── v1 │ │ │ │ │ ├── dictionaryV1.spec.ts │ │ │ │ │ ├── dictionaryV1.ts │ │ │ │ │ ├── index.ts │ │ │ │ │ └── utils.ts │ │ │ │ └── v2 │ │ │ │ │ ├── dictionaryV2.spec.ts │ │ │ │ │ ├── dictionaryV2.ts │ │ │ │ │ ├── index.ts │ │ │ │ │ └── types.ts │ │ │ ├── ds-processor.service.ts │ │ │ ├── dynamic-ds.service.spec.ts │ │ │ ├── dynamic-ds.service.ts │ │ │ ├── entities │ │ │ │ ├── Metadata.entity.ts │ │ │ │ ├── Poi.entity.ts │ │ │ │ └── index.ts │ │ │ ├── fetch.service.spec.ts │ │ │ ├── fetch.service.ts │ │ │ ├── inMemoryCache.service.spec.ts │ │ │ ├── inMemoryCache.service.ts │ │ │ ├── index.ts │ │ │ ├── indexer.manager.ts │ │ │ ├── poi │ │ │ │ ├── PoiBlock.spec.ts │ │ │ │ ├── PoiBlock.ts │ │ │ │ ├── index.ts │ │ │ │ ├── poi.service.spec.ts │ │ │ │ ├── poi.service.ts │ │ │ │ ├── poiModel.ts │ │ │ │ ├── poiSync.service.spec.ts │ │ │ │ └── poiSync.service.ts │ │ │ ├── project.service.spec.ts │ │ │ ├── project.service.ts │ │ │ ├── sandbox.service.ts │ │ │ ├── sandbox.spec.ts │ │ │ ├── sandbox.ts │ │ │ ├── smartBatch.service.ts │ │ │ ├── store.service.spec.ts │ │ │ ├── store.service.ts │ │ │ ├── store │ │ │ │ ├── entity.ts │ │ │ │ ├── index.ts │ │ │ │ └── store.ts │ │ │ ├── storeCache │ │ │ │ ├── baseCache.service.ts │ │ │ │ ├── cacheMetadata.spec.ts │ │ │ │ ├── cacheMetadata.test.ts │ │ │ │ ├── cacheMetadata.ts │ │ │ │ ├── cacheModel.spec.ts │ │ │ │ ├── cacheModel.test.ts │ │ │ │ ├── cacheModel.ts │ │ │ │ ├── cachePoi.spec.ts │ │ │ │ ├── cachePoi.ts │ │ │ │ ├── cacheable.ts │ │ │ │ ├── csvStore.service.spec.ts │ │ │ │ ├── csvStore.service.ts │ │ │ │ ├── index.ts │ │ │ │ ├── setValueModel.spec.ts │ │ │ │ ├── setValueModel.ts │ │ │ │ ├── storeCache.service.spec.ts │ │ │ │ ├── storeCache.service.ts │ │ │ │ └── types.ts │ │ │ ├── test.runner.spec.ts │ │ │ ├── test.runner.ts │ │ │ ├── testing.service.ts │ │ │ ├── types.ts │ │ │ ├── unfinalizedBlocks.service.spec.ts │ │ │ ├── unfinalizedBlocks.service.ts │ │ │ └── worker │ │ │ │ ├── index.ts │ │ │ │ ├── test.store.worker.ts │ │ │ │ ├── utils.ts │ │ │ │ ├── worker.builder.ts │ │ │ │ ├── worker.cache.service.ts │ │ │ │ ├── worker.connectionPoolState.manager.ts │ │ │ │ ├── worker.dynamic-ds.service.ts │ │ │ │ ├── worker.service.ts │ │ │ │ ├── worker.store.service.test.ts │ │ │ │ ├── worker.store.service.ts │ │ │ │ ├── worker.ts │ │ │ │ └── worker.unfinalizedBlocks.service.ts │ │ ├── logger.ts │ │ ├── meta │ │ │ ├── event.listener.ts │ │ │ ├── health.controller.ts │ │ │ ├── health.service.ts │ │ │ ├── index.ts │ │ │ ├── meta.service.ts │ │ │ ├── meta.ts │ │ │ ├── ready.controller.ts │ │ │ └── ready.service.ts │ │ ├── profiler.ts │ │ ├── subcommands │ │ │ ├── forceClean.module.ts │ │ │ ├── forceClean.service.ts │ │ │ ├── foreceClean.init.ts │ │ │ ├── index.ts │ │ │ ├── reindex.init.ts │ │ │ └── reindex.service.ts │ │ ├── utils │ │ │ ├── autoQueue.spec.ts │ │ │ ├── autoQueue.ts │ │ │ ├── batch-size.ts │ │ │ ├── bigint.ts │ │ │ ├── blockHeightMap.spec.ts │ │ │ ├── blockHeightMap.ts │ │ │ ├── blockSizeBuffer.ts │ │ │ ├── blocks.spec.ts │ │ │ ├── blocks.ts │ │ │ ├── configure.spec.ts │ │ │ ├── configure.ts │ │ │ ├── decorators.ts │ │ │ ├── fetchHelper.spec.ts │ │ │ ├── fetchHelpers.ts │ │ │ ├── graphql.ts │ │ │ ├── index.ts │ │ │ ├── object.spec.ts │ │ │ ├── object.ts │ │ │ ├── project.ts │ │ │ ├── promise.spec.ts │ │ │ ├── promise.ts │ │ │ └── reindex.ts │ │ └── yargs.ts │ ├── test │ │ ├── config.json │ │ ├── config.toml │ │ ├── config.yml │ │ ├── migration-schemas │ │ │ ├── test_10_1.graphql │ │ │ ├── test_10_1000.graphql │ │ │ ├── test_11_1.graphql │ │ │ ├── test_11_2000.graphql │ │ │ ├── test_12_1.graphql │ │ │ ├── test_12_2000.graphql │ │ │ ├── test_13_1.graphql │ │ │ ├── test_13_2000.graphql │ │ │ ├── test_14_1.graphql │ │ │ ├── test_14_1000.graphql │ │ │ ├── test_15_1.graphql │ │ │ ├── test_15_2000.graphql │ │ │ ├── test_15_4000.graphql │ │ │ ├── test_16_1.graphql │ │ │ ├── test_16_2000.graphql │ │ │ ├── test_17_1.graphql │ │ │ ├── test_17_2000.graphql │ │ │ ├── test_1_1.graphql │ │ │ ├── test_1_1000.graphql │ │ │ ├── test_2_1.graphql │ │ │ ├── test_2_1000.graphql │ │ │ ├── test_5_1.graphql │ │ │ ├── test_5_1000.graphql │ │ │ ├── test_6_1.graphql │ │ │ └── test_6_2000.graphql │ │ ├── sandbox │ │ │ ├── atob-test.js │ │ │ ├── atob-test.ts │ │ │ ├── buffer-test.js │ │ │ ├── buffer-test.ts │ │ │ ├── main.js │ │ │ ├── main.ts │ │ │ ├── package.json │ │ │ ├── schema.graphql │ │ │ └── tsconfig.json │ │ ├── schemas │ │ │ ├── badSchema.graphql │ │ │ ├── badschema-2.graphql │ │ │ ├── newSchema.graphql │ │ │ ├── oldSchema.graphql │ │ │ └── schemaDiff.json │ │ └── v1.0.0 │ │ │ ├── distMock │ │ │ ├── chaintypes.js │ │ │ └── index.js │ │ │ ├── erc20.abi.json │ │ │ ├── package.json │ │ │ ├── project.yaml │ │ │ ├── projectOptions.yaml │ │ │ ├── schema.graphql │ │ │ └── types.yaml │ ├── tsconfig.json │ └── yargs.js ├── node │ ├── .gitignore │ ├── .prettierrc │ ├── .trigger │ ├── CHANGELOG.md │ ├── Dockerfile │ ├── LICENSE │ ├── README.md │ ├── bin │ │ ├── run │ │ └── run.cmd │ ├── docker │ │ ├── cockroach-db │ │ │ └── docker-compose.yml │ │ ├── docker-compose.yml │ │ ├── load-extensions.sh │ │ └── pg-Dockerfile │ ├── nest-cli.json │ ├── nodemon.json │ ├── package.json │ ├── src │ │ ├── app.module.ts │ │ ├── configure │ │ │ ├── NodeConfig.ts │ │ │ ├── SchemaMigration.service.test.ts │ │ │ ├── SubqueryProject.spec.ts │ │ │ ├── SubqueryProject.ts │ │ │ └── configure.module.ts │ │ ├── indexer │ │ │ ├── api.service.spec.ts │ │ │ ├── api.service.test.ts │ │ │ ├── api.service.ts │ │ │ ├── apiPromise.connection.ts │ │ │ ├── blockDispatcher │ │ │ │ ├── block-dispatcher.service.ts │ │ │ │ ├── index.ts │ │ │ │ ├── substrate-block-dispatcher.ts │ │ │ │ └── worker-block-dispatcher.service.ts │ │ │ ├── dictionary │ │ │ │ ├── index.ts │ │ │ │ ├── substrateDictionary.service.spec.ts │ │ │ │ ├── substrateDictionary.service.ts │ │ │ │ ├── types.ts │ │ │ │ ├── v1 │ │ │ │ │ ├── index.ts │ │ │ │ │ ├── substrateDictionaryV1.spec.ts │ │ │ │ │ └── substrateDictionaryV1.ts │ │ │ │ └── v2 │ │ │ │ │ ├── index.ts │ │ │ │ │ ├── substrateDictionaryV2.ts │ │ │ │ │ └── types.ts │ │ │ ├── ds-processor.service.spec.ts │ │ │ ├── ds-processor.service.ts │ │ │ ├── dynamic-ds.service.ts │ │ │ ├── fetch.module.ts │ │ │ ├── fetch.service.spec.ts │ │ │ ├── fetch.service.test.ts │ │ │ ├── fetch.service.ts │ │ │ ├── indexer.manager.spec.ts │ │ │ ├── indexer.manager.ts │ │ │ ├── project.service.ts │ │ │ ├── runtime │ │ │ │ ├── base-runtime.service.ts │ │ │ │ ├── runtime.service.spec.ts │ │ │ │ ├── runtimeService.ts │ │ │ │ └── workerRuntimeService.ts │ │ │ ├── store.service.test.ts │ │ │ ├── types.ts │ │ │ ├── unfinalizedBlocks.service.ts │ │ │ ├── worker │ │ │ │ ├── worker-fetch.module.ts │ │ │ │ ├── worker.module.ts │ │ │ │ ├── worker.service.ts │ │ │ │ └── worker.ts │ │ │ └── x-provider │ │ │ │ ├── cachedProvider.ts │ │ │ │ ├── http.ts │ │ │ │ └── x-provider.spec.ts │ │ ├── init.ts │ │ ├── main.ts │ │ ├── meta │ │ │ ├── meta.controller.ts │ │ │ ├── meta.module.ts │ │ │ └── meta.service.ts │ │ ├── subcommands │ │ │ ├── forceClean.init.ts │ │ │ ├── forceClean.module.ts │ │ │ ├── reindex.init.ts │ │ │ ├── reindex.module.ts │ │ │ ├── testing.init.ts │ │ │ ├── testing.module.ts │ │ │ └── testing.service.ts │ │ ├── utils │ │ │ ├── project.ts │ │ │ ├── substrate.test.ts │ │ │ ├── substrate.ts │ │ │ └── test.utils.ts │ │ └── yargs.ts │ ├── test │ │ ├── jest-e2e.json │ │ ├── jsonfy.js │ │ └── projectFixture │ │ │ ├── bad.json │ │ │ ├── template-v1.0.0 │ │ │ ├── distMock │ │ │ │ ├── chaintypes.js │ │ │ │ └── index.js │ │ │ ├── erc20.abi.json │ │ │ ├── js │ │ │ │ ├── test1 │ │ │ │ │ ├── project.yaml │ │ │ │ │ └── types.js │ │ │ │ ├── test2 │ │ │ │ │ ├── project.yaml │ │ │ │ │ └── types.js │ │ │ │ ├── test3 │ │ │ │ │ ├── project.yaml │ │ │ │ │ └── types.js │ │ │ │ └── test4 │ │ │ │ │ ├── project.yaml │ │ │ │ │ └── types.js │ │ │ ├── package.json │ │ │ ├── project.yaml │ │ │ ├── schema.graphql │ │ │ └── types.yaml │ │ │ └── v1.0.0 │ │ │ ├── distMock │ │ │ ├── chaintypes.js │ │ │ └── index.js │ │ │ ├── erc20.abi.json │ │ │ ├── js │ │ │ ├── test1 │ │ │ │ ├── project.yaml │ │ │ │ └── types.js │ │ │ ├── test2 │ │ │ │ ├── project.yaml │ │ │ │ └── types.js │ │ │ ├── test3 │ │ │ │ ├── project.yaml │ │ │ │ └── types.js │ │ │ └── test4 │ │ │ │ ├── project.yaml │ │ │ │ └── types.js │ │ │ ├── package.json │ │ │ ├── project.yaml │ │ │ ├── schema.graphql │ │ │ └── types.yaml │ ├── tsconfig.build.json │ └── tsconfig.json ├── query │ ├── .env.example │ ├── .gitignore │ ├── CHANGELOG.md │ ├── Dockerfile │ ├── LICENSE │ ├── README.md │ ├── bin │ │ ├── run │ │ └── run.cmd │ ├── nest-cli.json │ ├── nodemon.json │ ├── package.json │ ├── src │ │ ├── app.module.ts │ │ ├── configure │ │ │ ├── config.ts │ │ │ ├── configure.module.ts │ │ │ ├── index.ts │ │ │ └── x-postgraphile │ │ │ │ └── debugClient.ts │ │ ├── graphql │ │ │ ├── __snapshots__ │ │ │ │ └── graphql.historical.test.ts.snap │ │ │ ├── graphql.historical.test.ts │ │ │ ├── graphql.module.ts │ │ │ ├── graphql.test.ts │ │ │ ├── limit.test.ts │ │ │ ├── plugins │ │ │ │ ├── GetMetadataPlugin.ts │ │ │ │ ├── PgAggregationPlugin.ts │ │ │ │ ├── PgBackwardRelationPlugin.ts │ │ │ │ ├── PgConnectionArgFirstLastBeforeAfter.ts │ │ │ │ ├── PgDistinctPlugin.ts │ │ │ │ ├── PgOrderByAggregatesPlugin.ts │ │ │ │ ├── PgOrderByUnique.ts │ │ │ │ ├── PgRowByVirtualIdPlugin.ts │ │ │ │ ├── PgSearchPlugin.ts │ │ │ │ ├── PgSubscriptionPlugin.ts │ │ │ │ ├── QueryAliasLimitPlugin.ts │ │ │ │ ├── QueryComplexityPlugin.ts │ │ │ │ ├── QueryDepthLimitPlugin.spec.ts │ │ │ │ ├── QueryDepthLimitPlugin.ts │ │ │ │ ├── historical │ │ │ │ │ ├── PgBlockHeightPlugin.ts │ │ │ │ │ ├── PgConnectionArgFilterBackwardRelationsPlugin.ts │ │ │ │ │ ├── PgConnectionArgFilterForwardRelationsPlugin.ts │ │ │ │ │ ├── index.ts │ │ │ │ │ └── utils.ts │ │ │ │ ├── index.ts │ │ │ │ └── smartTagsPlugin.ts │ │ │ └── project.service.ts │ │ ├── main.ts │ │ ├── utils │ │ │ ├── asyncInterval.ts │ │ │ └── logger.ts │ │ └── yargs.ts │ ├── tsconfig.build.json │ └── tsconfig.json ├── testing │ ├── CHANGELOG.md │ ├── LICENSE │ ├── package.json │ ├── src │ │ ├── index.ts │ │ └── interfaces.ts │ └── tsconfig.json ├── types-core │ ├── CHANGELOG.md │ ├── LICENSE │ ├── package.json │ ├── src │ │ ├── global.ts │ │ ├── index.ts │ │ ├── interfaces.ts │ │ ├── multichain │ │ │ ├── index.ts │ │ │ └── types.ts │ │ ├── project │ │ │ ├── datasourceProcessors.ts │ │ │ ├── index.ts │ │ │ ├── readers │ │ │ │ ├── index.ts │ │ │ │ └── reader.ts │ │ │ ├── types.ts │ │ │ └── versioned │ │ │ │ ├── base.ts │ │ │ │ ├── index.ts │ │ │ │ └── v1_0_0 │ │ │ │ ├── index.ts │ │ │ │ └── types.ts │ │ └── store.ts │ └── tsconfig.json ├── types │ ├── CHANGELOG.md │ ├── LICENSE │ ├── package.json │ ├── src │ │ ├── global.ts │ │ ├── index.ts │ │ ├── interfaces.ts │ │ └── project.ts │ └── tsconfig.json └── utils │ ├── CHANGELOG.md │ ├── LICENSE │ ├── README.md │ ├── package.json │ ├── src │ ├── array │ │ ├── array.spec.ts │ │ ├── array.ts │ │ └── index.ts │ ├── buffer │ │ ├── buffer.spec.ts │ │ ├── buffer.ts │ │ └── index.ts │ ├── graphql │ │ ├── builder.spec.ts │ │ ├── builder.ts │ │ ├── constant.ts │ │ ├── entities.ts │ │ ├── graphql.spec.ts │ │ ├── index.ts │ │ ├── schema.ts │ │ ├── schema │ │ │ ├── directives.ts │ │ │ └── scalas.ts │ │ └── types.ts │ ├── index.ts │ ├── logger │ │ ├── colors.spec.ts │ │ ├── colors.ts │ │ ├── constants.ts │ │ ├── index.ts │ │ ├── logger.ts │ │ └── util.ts │ ├── query │ │ ├── index.ts │ │ ├── metadata.ts │ │ └── types.ts │ └── types │ │ ├── TypeClass.ts │ │ ├── generalTypes.spec.ts │ │ ├── generalTypes.ts │ │ ├── index.ts │ │ ├── supported │ │ ├── BigInt.ts │ │ ├── Boolean.ts │ │ ├── Bytes.ts │ │ ├── Date.ts │ │ ├── Float.ts │ │ ├── ID.ts │ │ ├── Int.ts │ │ ├── Json.ts │ │ ├── String.ts │ │ └── index.ts │ │ └── u8aUtils.ts │ └── tsconfig.json ├── report-main.json ├── scripts ├── build.sh └── update_versions.sh ├── test ├── Dockerfile ├── docker-compose.yaml ├── jest-setup.ts ├── load-extensions.sh └── pg-Dockerfile ├── tsconfig.json ├── tsconfig.test.json └── yarn.lock /.dockerignore: -------------------------------------------------------------------------------- 1 | .github 2 | node_modules 3 | coverage 4 | deploy 5 | docs 6 | test/docker-compose.yaml 7 | test/Dockerfile 8 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | indent_style = space 5 | indent_size = 2 6 | end_of_line = lf 7 | charset = utf-8 8 | trim_trailing_whitespace = true 9 | insert_final_newline = true 10 | 11 | [*.md] 12 | trim_trailing_whitespace = false 13 | -------------------------------------------------------------------------------- /.eslintignore: -------------------------------------------------------------------------------- 1 | /build/** 2 | /api_docs/** 3 | **/node_modules/** 4 | **/test/**/* 5 | /scripts/* 6 | packages/**/dist/** 7 | packages/**/lib/** 8 | .eslintrc.js 9 | *.proto 10 | *.ts.snap 11 | -------------------------------------------------------------------------------- /.github/PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | # Description 2 | Please include a summary of the change and which issue is fixed. Please also include relevant motivation and context. List any dependencies that are required for this change. 3 | 4 | Fixes # (issue) 5 | 6 | ## Type of change 7 | 8 | Please delete options that are not relevant. 9 | 10 | - [ ] Bug fix (non-breaking change which fixes an issue) 11 | - [ ] New feature (non-breaking change which adds functionality) 12 | - [ ] Breaking change (fix or feature that would cause existing functionality to not work as expected) 13 | - [ ] This change requires a documentation update 14 | 15 | ## Checklist 16 | 17 | - [ ] I have tested locally 18 | - [ ] I have performed a self review of my changes 19 | - [ ] Updated any relevant documentation 20 | - [ ] Linked to any relevant issues 21 | - [ ] I have added tests relevant to my changes 22 | - [ ] Any dependent changes have been merged and published in downstream modules 23 | - [ ] My code is up to date with the base branch 24 | - [ ] I have updated relevant changelogs. [We suggest using chan](https://github.com/geut/chan/tree/main/packages/chan) 25 | -------------------------------------------------------------------------------- /.github/actions/create-prerelease/action.yml: -------------------------------------------------------------------------------- 1 | # Composite action needed to access github context 2 | 3 | # This is to compensate for yarn 3 issue https://github.com/yarnpkg/berry/issues/3868 4 | name: 'Remove Stable Versions' 5 | description: 'This will remove stableVersion from packages for prerelease' 6 | inputs: 7 | package-path: 8 | description: 'package path to run action e.g. package/common' 9 | required: true 10 | npm-token: 11 | description: 'token to push to npm registry' 12 | required: true 13 | 14 | runs: 15 | using: "composite" 16 | steps: 17 | - working-directory: ${{ github.workspace }} 18 | run: node ${{ github.action_path }}/remove-stable-version.js ${{ github.workspace }}/${{ inputs.package-path }} 19 | shell: bash 20 | 21 | - working-directory: ${{ inputs.package-path }} 22 | run: echo "Changes exist in ${{ inputs.package-path }}" && yarn version prerelease && yarn npm publish --access public --tag dev 23 | env: 24 | NPM_TOKEN: ${{ inputs.npm-token }} 25 | shell: bash 26 | -------------------------------------------------------------------------------- /.github/actions/create-prerelease/remove-stable-version.js: -------------------------------------------------------------------------------- 1 | const fs = require('fs'); 2 | const myArgs = process.argv.slice(2); 3 | const pJson = require(`${myArgs[0]}/package.json`) 4 | 5 | if (pJson.stableVersion){ 6 | delete pJson.stableVersion 7 | fs.writeFileSync(`${myArgs[0]}/package.json`, JSON.stringify(pJson, null, 2)) 8 | } 9 | -------------------------------------------------------------------------------- /.github/actions/create-release/action.yml: -------------------------------------------------------------------------------- 1 | # Composite action needed to access github context 2 | 3 | name: 'Create Release' 4 | description: 'This will publish to NPM registry and create Github release' 5 | inputs: 6 | package-path: # id of input 7 | description: 'package path to run action e.g. package/common' 8 | required: true 9 | repo-token: 10 | description: 'token to create github release' 11 | required: true 12 | npm-token: 13 | description: 'token to push to npm registry' 14 | required: true 15 | 16 | runs: 17 | using: "composite" 18 | steps: 19 | - working-directory: ${{ inputs.package-path }} 20 | run: echo "Changes exist in ${{ inputs.package-path }}" && yarn npm publish --access public 21 | env: 22 | NPM_TOKEN: ${{ inputs.npm-token }} 23 | shell: bash 24 | 25 | - working-directory: ${{ github.workspace }} 26 | run: node ${{ github.action_path }}/gh-release-script.js ${{ github.workspace }}/${{ inputs.package-path }} ${{ github.sha }} 27 | env: 28 | REPO_TOKEN: ${{ inputs.repo-token }} 29 | shell: bash 30 | -------------------------------------------------------------------------------- /.github/workflows/discord.yml: -------------------------------------------------------------------------------- 1 | name: discord notification 2 | on: 3 | release: 4 | types: 5 | - published 6 | 7 | jobs: 8 | notify: 9 | name: Discord Notification 10 | runs-on: ubuntu-latest 11 | 12 | steps: 13 | - name: Send release details to Discord 14 | uses: rjstone/discord-webhook-notify@v1 15 | with: 16 | webhookUrl: ${{ secrets.DISCORD_RELEASE_NOTES_WEBHOOK }} 17 | color: '#6499ff' 18 | avatarUrl: https://github.githubassets.com/images/modules/logos_page/Octocat.png 19 | details: ${{ github.event.release.body }} 20 | description: "[Release] ${{ github.event.release.name }}" 21 | footer: ${{ github.event.release.html_url }} 22 | -------------------------------------------------------------------------------- /.github/workflows/scripts/benchmark/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM node:18 2 | 3 | # Define build-time arguments 4 | 5 | ARG input_indexer_version 6 | ENV INDEXER_VERSION=${input_indexer_version} 7 | 8 | ENV DB_USER=postgres 9 | ENV DB_PASS=postgres 10 | ENV DB_DATABASE=postgres 11 | ENV DB_HOST=postgres 12 | ENV DB_PORT=5432 13 | 14 | # Set the working directory in the container 15 | WORKDIR /app 16 | 17 | # Install app dependencies 18 | RUN npm i @subql/node@$INDEXER_VERSION -g 19 | 20 | # Copy the rest of the app's code to the container 21 | COPY . . 22 | 23 | # Custom script to run the Node.js app and handle other tasks 24 | COPY benchmarking.sh /app/benchmarking.sh 25 | RUN chmod +x /app/benchmarking.sh 26 | 27 | # Set the entrypoint to the script 28 | ENTRYPOINT ["/bin/bash", "/app/benchmarking.sh"] 29 | -------------------------------------------------------------------------------- /.github/workflows/scripts/benchmark/benchmarking.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Get input parameters passed from the GitHub Action workflow 4 | # Testing time 5 | input_duration=$1 6 | input_deployment=$2 7 | input_endpoint=$3 8 | input_batch_size=$4 9 | input_workers=$5 10 | input_disableHistorical=$6 11 | input_others=$7 12 | 13 | # Start the Node.js app in the background and save its PID 14 | subql-node -f ipfs://$input_deployment --network-endpoint=$input_endpoint --batch-size=$input_batch_size --workers=$input_workers --disable-historical=$input_disableHistorical $input_others --ipfs='https://unauthipfs.subquery.network/ipfs/api/v0' --db-schema=app > output/benchmark/indexing.log 2>&1 & 15 | 16 | APP_PID=$! 17 | 18 | echo "Benchmarking, please wait $input_duration." 19 | # Wait for timeout 20 | sleep $input_duration 21 | 22 | # Terminate the Node.js app 23 | pkill -P $APP_PID || true 24 | -------------------------------------------------------------------------------- /.github/workflows/scripts/benchmark/cleanHistory.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | output_dir=$1 4 | 5 | if [ -d "$output_dir" ]; then 6 | echo "Removing existing directory: $output_dir" 7 | rm -rf "$output_dir" 8 | fi 9 | # Create the new directory 10 | echo "Creating new directory: ${PWD}/$output_dir" 11 | mkdir -p "$output_dir" 12 | -------------------------------------------------------------------------------- /.github/workflows/scripts/nodeVersion.sh: -------------------------------------------------------------------------------- 1 | PACKAGE_VERSION=$(cat ./packages/node/package.json \ 2 | | grep version \ 3 | | head -1 \ 4 | | awk -F: '{ print $2 }' \ 5 | | sed 's/[",]//g' \ 6 | | tr -d '[[:space:]]') 7 | 8 | 9 | echo "::set-output name=NODE_VERSION::$PACKAGE_VERSION" 10 | -------------------------------------------------------------------------------- /.github/workflows/scripts/queryVersion.sh: -------------------------------------------------------------------------------- 1 | PACKAGE_VERSION=$(cat ./packages/query/package.json \ 2 | | grep version \ 3 | | head -1 \ 4 | | awk -F: '{ print $2 }' \ 5 | | sed 's/[",]//g' \ 6 | | tr -d '[[:space:]]') 7 | 8 | 9 | echo "::set-output name=QUERY_VERSION::$PACKAGE_VERSION" 10 | -------------------------------------------------------------------------------- /.gitpod.dockerfile: -------------------------------------------------------------------------------- 1 | FROM gitpod/workspace-postgresql -------------------------------------------------------------------------------- /.gitpod.yml: -------------------------------------------------------------------------------- 1 | # This configuration file was automatically generated by Gitpod. 2 | # Please adjust to your needs (see https://www.gitpod.io/docs/config-gitpod-file) 3 | # and commit this file to your remote git repository to share the goodness with others. 4 | image: 5 | file: .gitpod.dockerfile 6 | 7 | tasks: 8 | - init: yarn install && yarn run build 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /.husky/.gitignore: -------------------------------------------------------------------------------- 1 | _ 2 | -------------------------------------------------------------------------------- /.husky/pre-commit: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | . "$(dirname "$0")/_/husky.sh" 3 | 4 | npx lint-staged 5 | -------------------------------------------------------------------------------- /.prettierignore: -------------------------------------------------------------------------------- 1 | **/CHANGELOG.md 2 | **/node_modules/** 3 | **/.*/** 4 | **/coverage/** 5 | **/dist/** 6 | *.d.ts 7 | **/.DS_Store 8 | *.ejs 9 | *.tgz 10 | *.cmd 11 | *.sh 12 | generate-project*.yaml 13 | *.proto 14 | *.ts.snap 15 | -------------------------------------------------------------------------------- /.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "printWidth": 120, 3 | "trailingComma": "es5", 4 | "tabWidth": 2, 5 | "singleQuote": true, 6 | "bracketSpacing": false 7 | } 8 | -------------------------------------------------------------------------------- /.yarn/versions/043f60d9.yml: -------------------------------------------------------------------------------- 1 | undecided: 2 | - "@subql/utils" 3 | -------------------------------------------------------------------------------- /.yarn/versions/06878261.yml: -------------------------------------------------------------------------------- 1 | undecided: 2 | - "@subql/node-core" 3 | -------------------------------------------------------------------------------- /.yarn/versions/12f2ee2a.yml: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Zikc2023/subql/d164f848bfaa82aaa5f842a9a5a9a1b946fb97d3/.yarn/versions/12f2ee2a.yml -------------------------------------------------------------------------------- /.yarn/versions/1447e381.yml: -------------------------------------------------------------------------------- 1 | undecided: 2 | - "@subql/node-core" 3 | -------------------------------------------------------------------------------- /.yarn/versions/1c09bcf3.yml: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Zikc2023/subql/d164f848bfaa82aaa5f842a9a5a9a1b946fb97d3/.yarn/versions/1c09bcf3.yml -------------------------------------------------------------------------------- /.yarn/versions/29bf85e7.yml: -------------------------------------------------------------------------------- 1 | undecided: 2 | - "@subql/node-core" 3 | -------------------------------------------------------------------------------- /.yarn/versions/2d61ee26.yml: -------------------------------------------------------------------------------- 1 | undecided: 2 | - "@subql/cli" 3 | - "@subql/common" 4 | - "@subql/node" 5 | - "@subql/node-core" 6 | - "@subql/query" 7 | - "@subql/testing" 8 | - "@subql/types" 9 | - "@subql/types-core" 10 | -------------------------------------------------------------------------------- /.yarn/versions/2eebe132.yml: -------------------------------------------------------------------------------- 1 | undecided: 2 | - "@subql/node-core" 3 | -------------------------------------------------------------------------------- /.yarn/versions/33e756ee.yml: -------------------------------------------------------------------------------- 1 | undecided: 2 | - "@subql/node-core" 3 | -------------------------------------------------------------------------------- /.yarn/versions/351b62d7.yml: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Zikc2023/subql/d164f848bfaa82aaa5f842a9a5a9a1b946fb97d3/.yarn/versions/351b62d7.yml -------------------------------------------------------------------------------- /.yarn/versions/3fbcf2a0.yml: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Zikc2023/subql/d164f848bfaa82aaa5f842a9a5a9a1b946fb97d3/.yarn/versions/3fbcf2a0.yml -------------------------------------------------------------------------------- /.yarn/versions/4078a944.yml: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Zikc2023/subql/d164f848bfaa82aaa5f842a9a5a9a1b946fb97d3/.yarn/versions/4078a944.yml -------------------------------------------------------------------------------- /.yarn/versions/46b26b5d.yml: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Zikc2023/subql/d164f848bfaa82aaa5f842a9a5a9a1b946fb97d3/.yarn/versions/46b26b5d.yml -------------------------------------------------------------------------------- /.yarn/versions/48ba8de1.yml: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Zikc2023/subql/d164f848bfaa82aaa5f842a9a5a9a1b946fb97d3/.yarn/versions/48ba8de1.yml -------------------------------------------------------------------------------- /.yarn/versions/4c39a3cb.yml: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Zikc2023/subql/d164f848bfaa82aaa5f842a9a5a9a1b946fb97d3/.yarn/versions/4c39a3cb.yml -------------------------------------------------------------------------------- /.yarn/versions/4d1a19ef.yml: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Zikc2023/subql/d164f848bfaa82aaa5f842a9a5a9a1b946fb97d3/.yarn/versions/4d1a19ef.yml -------------------------------------------------------------------------------- /.yarn/versions/4de1b78e.yml: -------------------------------------------------------------------------------- 1 | undecided: 2 | - "@subql/node-core" 3 | -------------------------------------------------------------------------------- /.yarn/versions/4ef73239.yml: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Zikc2023/subql/d164f848bfaa82aaa5f842a9a5a9a1b946fb97d3/.yarn/versions/4ef73239.yml -------------------------------------------------------------------------------- /.yarn/versions/5284b2e3.yml: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Zikc2023/subql/d164f848bfaa82aaa5f842a9a5a9a1b946fb97d3/.yarn/versions/5284b2e3.yml -------------------------------------------------------------------------------- /.yarn/versions/532ac853.yml: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Zikc2023/subql/d164f848bfaa82aaa5f842a9a5a9a1b946fb97d3/.yarn/versions/532ac853.yml -------------------------------------------------------------------------------- /.yarn/versions/53f030f6.yml: -------------------------------------------------------------------------------- 1 | undecided: 2 | - "@subql/utils" 3 | -------------------------------------------------------------------------------- /.yarn/versions/5c14c916.yml: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Zikc2023/subql/d164f848bfaa82aaa5f842a9a5a9a1b946fb97d3/.yarn/versions/5c14c916.yml -------------------------------------------------------------------------------- /.yarn/versions/6b90a9bc.yml: -------------------------------------------------------------------------------- 1 | undecided: 2 | - "@subql/cli" 3 | - "@subql/node-core" 4 | -------------------------------------------------------------------------------- /.yarn/versions/6cdd41ea.yml: -------------------------------------------------------------------------------- 1 | undecided: 2 | - "@subql/common" 3 | - "@subql/node" 4 | - "@subql/node-core" 5 | - "@subql/query" 6 | - "@subql/types" 7 | - "@subql/utils" 8 | -------------------------------------------------------------------------------- /.yarn/versions/6ffda578.yml: -------------------------------------------------------------------------------- 1 | undecided: 2 | - "@subql/node-core" 3 | -------------------------------------------------------------------------------- /.yarn/versions/74e58e5b.yml: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Zikc2023/subql/d164f848bfaa82aaa5f842a9a5a9a1b946fb97d3/.yarn/versions/74e58e5b.yml -------------------------------------------------------------------------------- /.yarn/versions/7c0eab27.yml: -------------------------------------------------------------------------------- 1 | undecided: 2 | - "@subql/node-core" 3 | -------------------------------------------------------------------------------- /.yarn/versions/857e5ecd.yml: -------------------------------------------------------------------------------- 1 | undecided: 2 | - "@subql/node-core" 3 | - "@subql/types-core" 4 | -------------------------------------------------------------------------------- /.yarn/versions/86ccde0d.yml: -------------------------------------------------------------------------------- 1 | undecided: 2 | - "@subql/node-core" 3 | -------------------------------------------------------------------------------- /.yarn/versions/91e494d1.yml: -------------------------------------------------------------------------------- 1 | undecided: 2 | - "@subql/common" 3 | -------------------------------------------------------------------------------- /.yarn/versions/92e577ad.yml: -------------------------------------------------------------------------------- 1 | undecided: 2 | - "@subql/node-core" 3 | -------------------------------------------------------------------------------- /.yarn/versions/a2c2414d.yml: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Zikc2023/subql/d164f848bfaa82aaa5f842a9a5a9a1b946fb97d3/.yarn/versions/a2c2414d.yml -------------------------------------------------------------------------------- /.yarn/versions/abc53221.yml: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Zikc2023/subql/d164f848bfaa82aaa5f842a9a5a9a1b946fb97d3/.yarn/versions/abc53221.yml -------------------------------------------------------------------------------- /.yarn/versions/ad1e1894.yml: -------------------------------------------------------------------------------- 1 | undecided: 2 | - "@subql/node-core" 3 | -------------------------------------------------------------------------------- /.yarn/versions/b03d4318.yml: -------------------------------------------------------------------------------- 1 | undecided: 2 | - "@subql/node" 3 | - "@subql/node-core" 4 | - "@subql/types" 5 | - "@subql/types-core" 6 | -------------------------------------------------------------------------------- /.yarn/versions/b426a40b.yml: -------------------------------------------------------------------------------- 1 | undecided: 2 | - "@subql/common" 3 | - "@subql/node-core" 4 | - "@subql/types" 5 | - "@subql/types-core" 6 | -------------------------------------------------------------------------------- /.yarn/versions/bd58ec77.yml: -------------------------------------------------------------------------------- 1 | undecided: 2 | - "@subql/node-core" 3 | -------------------------------------------------------------------------------- /.yarn/versions/ca56439e.yml: -------------------------------------------------------------------------------- 1 | undecided: 2 | - "@subql/node-core" 3 | -------------------------------------------------------------------------------- /.yarn/versions/d2d9e21c.yml: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Zikc2023/subql/d164f848bfaa82aaa5f842a9a5a9a1b946fb97d3/.yarn/versions/d2d9e21c.yml -------------------------------------------------------------------------------- /.yarn/versions/d408027a.yml: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Zikc2023/subql/d164f848bfaa82aaa5f842a9a5a9a1b946fb97d3/.yarn/versions/d408027a.yml -------------------------------------------------------------------------------- /.yarn/versions/d8be227b.yml: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Zikc2023/subql/d164f848bfaa82aaa5f842a9a5a9a1b946fb97d3/.yarn/versions/d8be227b.yml -------------------------------------------------------------------------------- /.yarn/versions/d9e0b292.yml: -------------------------------------------------------------------------------- 1 | undecided: 2 | - "@subql/node-core" 3 | -------------------------------------------------------------------------------- /.yarn/versions/da057245.yml: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Zikc2023/subql/d164f848bfaa82aaa5f842a9a5a9a1b946fb97d3/.yarn/versions/da057245.yml -------------------------------------------------------------------------------- /.yarn/versions/db4f7e5e.yml: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Zikc2023/subql/d164f848bfaa82aaa5f842a9a5a9a1b946fb97d3/.yarn/versions/db4f7e5e.yml -------------------------------------------------------------------------------- /.yarn/versions/dbefade5.yml: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Zikc2023/subql/d164f848bfaa82aaa5f842a9a5a9a1b946fb97d3/.yarn/versions/dbefade5.yml -------------------------------------------------------------------------------- /.yarn/versions/e67c5647.yml: -------------------------------------------------------------------------------- 1 | undecided: 2 | - "@subql/node-core" 3 | -------------------------------------------------------------------------------- /.yarn/versions/e6985a5f.yml: -------------------------------------------------------------------------------- 1 | undecided: 2 | - "@subql/utils" 3 | -------------------------------------------------------------------------------- /.yarn/versions/e7d60c2f.yml: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Zikc2023/subql/d164f848bfaa82aaa5f842a9a5a9a1b946fb97d3/.yarn/versions/e7d60c2f.yml -------------------------------------------------------------------------------- /.yarn/versions/f2404812.yml: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Zikc2023/subql/d164f848bfaa82aaa5f842a9a5a9a1b946fb97d3/.yarn/versions/f2404812.yml -------------------------------------------------------------------------------- /.yarn/versions/f5fd9c46.yml: -------------------------------------------------------------------------------- 1 | undecided: 2 | - "@subql/utils" 3 | -------------------------------------------------------------------------------- /.yarn/versions/fd2e440b.yml: -------------------------------------------------------------------------------- 1 | undecided: 2 | - "@subql/node" 3 | -------------------------------------------------------------------------------- /.yarn/versions/ff271075.yml: -------------------------------------------------------------------------------- 1 | undecided: 2 | - "@subql/common" 3 | - "@subql/node-core" 4 | -------------------------------------------------------------------------------- /.yarnrc.yml: -------------------------------------------------------------------------------- 1 | changesetBaseRefs: 2 | - main 3 | - origin/main 4 | 5 | enableImmutableInstalls: false 6 | 7 | enableProgressBars: false 8 | 9 | nodeLinker: node-modules 10 | 11 | npmAuthToken: "${NPM_TOKEN:-}" 12 | 13 | npmPublishRegistry: "https://registry.npmjs.org" 14 | 15 | plugins: 16 | - path: .yarn/plugins/@yarnpkg/plugin-interactive-tools.cjs 17 | spec: "@yarnpkg/plugin-interactive-tools" 18 | - path: .yarn/plugins/@yarnpkg/plugin-workspace-tools.cjs 19 | spec: "@yarnpkg/plugin-workspace-tools" 20 | - path: .yarn/plugins/@yarnpkg/plugin-typescript.cjs 21 | spec: "@yarnpkg/plugin-typescript" 22 | - path: .yarn/plugins/@yarnpkg/plugin-version.cjs 23 | spec: "@yarnpkg/plugin-version" 24 | 25 | yarnPath: .yarn/releases/yarn-3.2.4.cjs 26 | -------------------------------------------------------------------------------- /SECURITY.md: -------------------------------------------------------------------------------- 1 | # Security Policy 2 | 3 | [Please see our policy here](https://academy.subquery.network/miscellaneous/vulnerability-reporting.html) 4 | -------------------------------------------------------------------------------- /babel.config.js: -------------------------------------------------------------------------------- 1 | module.exports = {presets: ['@babel/preset-env']} 2 | -------------------------------------------------------------------------------- /crowdin.yaml: -------------------------------------------------------------------------------- 1 | files: 2 | - source: /docs/*.md 3 | translation: /docs/%two_letters_code%/%original_file_name% 4 | - source: /docs/create/*.md 5 | translation: /docs/%two_letters_code%/create/%original_file_name% 6 | - source: /docs/faqs/*.md 7 | translation: /docs/%two_letters_code%/faqs/%original_file_name% 8 | - source: /docs/install/*.md 9 | translation: /docs/%two_letters_code%/install/%original_file_name% 10 | - source: /docs/miscellaneous/*.md 11 | translation: /docs/%two_letters_code%/miscellaneous/%original_file_name% 12 | - source: /docs/publish/*.md 13 | translation: /docs/%two_letters_code%/publish/%original_file_name% 14 | - source: /docs/query/*.md 15 | translation: /docs/%two_letters_code%/query/%original_file_name% 16 | - source: /docs/quickstart/*.md 17 | translation: /docs/%two_letters_code%/quickstart/%original_file_name% 18 | - source: /docs/run/*.md 19 | translation: /docs/%two_letters_code%/run/%original_file_name% 20 | - source: /docs/tutorials_examples/*.md 21 | translation: /docs/%two_letters_code%/tutorials_examples/%original_file_name% -------------------------------------------------------------------------------- /deploy/logging_debug.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Zikc2023/subql/d164f848bfaa82aaa5f842a9a5a9a1b946fb97d3/deploy/logging_debug.png -------------------------------------------------------------------------------- /packages/cli/bin/run: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | 3 | const pjson = require('../package.json'); 4 | const updateNotifier = require('update-notifier'); 5 | const chalk = require('chalk'); 6 | const boxen = require('boxen'); 7 | const semver = require('semver'); 8 | 9 | const notifier = updateNotifier({pkg: pjson, updateCheckInterval: 0}); 10 | if (notifier.update) { 11 | const {current, latest, name} = notifier.update; 12 | 13 | if (semver.lt(current, latest)) { 14 | const message = 15 | `Update available ${chalk.dim(`${current}`)} → ${chalk.green(`${latest}`)}` + 16 | `\nRun ${chalk.cyan(`npm i -g ${name}`)} to update`; 17 | const boxenOptions = { 18 | padding: 1, 19 | margin: 1, 20 | align: 'center', 21 | borderColor: 'yellow', 22 | borderStyle: 'round', 23 | }; 24 | console.log(boxen(message, boxenOptions)); 25 | } 26 | } 27 | const oclif = require('@oclif/core') 28 | oclif.run().then(oclif.flush).catch(oclif.Errors.handle) 29 | -------------------------------------------------------------------------------- /packages/cli/bin/run.cmd: -------------------------------------------------------------------------------- 1 | @echo off 2 | 3 | node "%~dp0\run" %* 4 | -------------------------------------------------------------------------------- /packages/cli/src/commands/multi-chain/add.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2020-2024 SubQuery Pte Ltd authors & contributors 2 | // SPDX-License-Identifier: GPL-3.0 3 | 4 | import {Command, Flags} from '@oclif/core'; 5 | import {cli} from 'cli-ux'; 6 | import {addChain} from '../../controller/add-chain-controller'; 7 | import {resolveToAbsolutePath} from '../../utils'; 8 | 9 | export default class MultiChainAdd extends Command { 10 | static description = 'Add new chain manifest to multi-chain configuration'; 11 | 12 | static flags = { 13 | multichain: Flags.string({char: 'f', description: 'specify multichain manifest file path', default: process.cwd()}), 14 | chainManifestPath: Flags.string({char: 'c', description: 'path to the new chain manifest'}), 15 | }; 16 | 17 | async run(): Promise { 18 | const {flags} = await this.parse(MultiChainAdd); 19 | 20 | const {multichain} = flags; 21 | let {chainManifestPath} = flags; 22 | 23 | if (!chainManifestPath) { 24 | chainManifestPath = await cli.prompt('Enter the path to the new chain manifest'); 25 | } 26 | 27 | await addChain(multichain, resolveToAbsolutePath(chainManifestPath)); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /packages/cli/src/controller/deploy-controller.test.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2020-2024 SubQuery Pte Ltd authors & contributors 2 | // SPDX-License-Identifier: GPL-3.0 3 | 4 | import {splitMultichainDataFields} from "./deploy-controller"; 5 | 6 | 7 | jest.setTimeout(30000); 8 | 9 | describe("splitMultichainDataFields test", () => { 10 | test("Single chain, single endpoint", () => { 11 | const result=splitMultichainDataFields("chainIdididid:http://1.1.1.1"); 12 | expect(result).toEqual({ chainIdididid: 'http://1.1.1.1' } 13 | ); 14 | }); 15 | 16 | test("multi chain, multi endpoint", () => { 17 | const result=splitMultichainDataFields("chainIdididid:http://1.1.1.1,chainIdididid222:http://2.2.2.2,chainIdididid333:http://3.3.33.3"); 18 | expect(result).toEqual({"chainIdididid": "http://1.1.1.1", "chainIdididid222": "http://2.2.2.2", "chainIdididid333": "http://3.3.33.3"} 19 | ); 20 | }); 21 | 22 | test("Incorrect values (endpoint without chainId)", () => { 23 | const result=splitMultichainDataFields("http://2.2.2.2,http://2.2.2.3"); 24 | expect(result).toEqual({}); 25 | }); 26 | 27 | 28 | }); 29 | -------------------------------------------------------------------------------- /packages/cli/src/controller/migrate/index.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2020-2024 SubQuery Pte Ltd authors & contributors 2 | // SPDX-License-Identifier: GPL-3.0 3 | 4 | export * from './migrate-controller'; 5 | export * from './manifest/migrate-manifest.controller'; 6 | export * from './abis/migrate-abis.controller'; 7 | export * from './schema/migrate-schema.controller'; 8 | export * from './constants'; 9 | -------------------------------------------------------------------------------- /packages/cli/src/controller/migrate/mapping/migrate-mapping.controller.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2020-2024 SubQuery Pte Ltd authors & contributors 2 | // SPDX-License-Identifier: GPL-3.0 3 | 4 | import fs from 'fs'; 5 | import path from 'path'; 6 | import {copyFolderSync} from '../../../utils'; 7 | 8 | export async function migrateMapping(subgraphDir: string, subqlDir: string): Promise { 9 | const subqlSrcPath = path.join(subqlDir, '/src'); 10 | await fs.promises.rm(subqlSrcPath, {force: true, recursive: true}); 11 | // copy over src 12 | copyFolderSync(path.join(subgraphDir, '/src'), subqlSrcPath); 13 | console.log( 14 | `* Mapping handlers have been copied over, they will need to be updated to work with SubQuery. See our documentation for more details https://academy.subquery.network/build/graph-migration.html#codegen` 15 | ); 16 | } 17 | -------------------------------------------------------------------------------- /packages/cli/src/controller/migrate/schema/migrate-schema.controller.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2020-2024 SubQuery Pte Ltd authors & contributors 2 | // SPDX-License-Identifier: GPL-3.0 3 | 4 | import fs from 'fs'; 5 | 6 | export async function migrateSchema(subgraphSchemaPath: string, subqlSchemaPath: string) { 7 | await fs.promises.rm(subqlSchemaPath, {force: true}); 8 | // copy over schema 9 | fs.copyFileSync(subgraphSchemaPath, subqlSchemaPath); 10 | console.log( 11 | `* schema.graphql have been copied over, they will need to be updated to work with SubQuery. See our documentation for more details https://academy.subquery.network/build/graphql.html` 12 | ); 13 | } 14 | -------------------------------------------------------------------------------- /packages/cli/src/controller/validate.spec.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2020-2024 SubQuery Pte Ltd authors & contributors 2 | // SPDX-License-Identifier: GPL-3.0 3 | 4 | import {NETWORK_FAMILY} from '@subql/common'; 5 | import {isValidEnum} from '../utils'; 6 | 7 | describe('Tests for validate, CLI', () => { 8 | it('ensure EnumValidator', () => { 9 | expect(isValidEnum(NETWORK_FAMILY, 'Cosmos')).toBe(true); 10 | expect(isValidEnum(NETWORK_FAMILY, 'bad')).toBe(false); 11 | }); 12 | }); 13 | -------------------------------------------------------------------------------- /packages/cli/src/index.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2020-2024 SubQuery Pte Ltd authors & contributors 2 | // SPDX-License-Identifier: GPL-3.0 3 | 4 | export {run} from '@oclif/core'; 5 | -------------------------------------------------------------------------------- /packages/cli/src/jsonrpc/client/http.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2020-2024 SubQuery Pte Ltd authors & contributors 2 | // SPDX-License-Identifier: GPL-3.0 3 | 4 | import axios, {AxiosInstance} from 'axios'; 5 | import {Response, ResponseError, ResponseSuccess, ResponseSuccessType} from './types'; 6 | 7 | const TIMEOUT = 5000; 8 | 9 | let id = 0; 10 | export class HttpJsonRpcClient { 11 | protected axios: AxiosInstance; 12 | constructor(url: string) { 13 | this.axios = axios.create({ 14 | baseURL: url, 15 | timeout: TIMEOUT, 16 | }); 17 | } 18 | 19 | async send(method: string, params?: any[]): Promise { 20 | const res = await this.axios.post>('', { 21 | jsonrpc: '2.0', 22 | id: id++, 23 | method, 24 | params, 25 | }); 26 | if ((res.data as ResponseError).error) { 27 | throw (res.data as ResponseError).error; 28 | } 29 | return (res.data as ResponseSuccess).result; 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /packages/cli/src/jsonrpc/client/index.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2020-2024 SubQuery Pte Ltd authors & contributors 2 | // SPDX-License-Identifier: GPL-3.0 3 | 4 | export * from './http'; 5 | export * from './ws'; 6 | -------------------------------------------------------------------------------- /packages/cli/src/jsonrpc/client/types.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2020-2024 SubQuery Pte Ltd authors & contributors 2 | // SPDX-License-Identifier: GPL-3.0 3 | 4 | export interface Message { 5 | jsonrpc: '2.0'; 6 | method: string; 7 | params?: T; 8 | } 9 | 10 | export interface Request extends Message { 11 | id: string | number; 12 | } 13 | 14 | export type Notification = Message; 15 | 16 | export interface ResponseSuccess { 17 | id: string | number | null; 18 | result: T; 19 | } 20 | 21 | export type ResponseSuccessType = string | number | boolean | object | null; 22 | 23 | export interface ResponseError { 24 | id: string | number | null; 25 | error: { 26 | code: number; 27 | message: string; 28 | data?: any; 29 | }; 30 | } 31 | 32 | export type Response = ResponseSuccess | ResponseError; 33 | -------------------------------------------------------------------------------- /packages/cli/src/jsonrpc/index.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2020-2024 SubQuery Pte Ltd authors & contributors 2 | // SPDX-License-Identifier: GPL-3.0 3 | 4 | import {HttpJsonRpcClient, WsJsonRpcClient} from './client'; 5 | 6 | export async function getGenesisHash(endpoint: string): Promise { 7 | const client = endpoint.startsWith('ws') ? new WsJsonRpcClient(endpoint) : new HttpJsonRpcClient(endpoint); 8 | const genesisBlock = await client.send('chain_getBlockHash', [0]); 9 | (client as WsJsonRpcClient).destroy?.(); 10 | return genesisBlock; 11 | } 12 | -------------------------------------------------------------------------------- /packages/cli/src/jsonrpc/jsonrpc.test.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2020-2024 SubQuery Pte Ltd authors & contributors 2 | // SPDX-License-Identifier: GPL-3.0 3 | 4 | import {getGenesisHash} from './index'; 5 | 6 | const WS_ENDPOINT = 'wss://polkadot.api.onfinality.io/public-ws'; 7 | const HTTP_ENDPOINT = 'https://polkadot.api.onfinality.io/public'; 8 | 9 | const GENESIS_HASH = '0x91b171bb158e2d3848fa23a9f1c25182fb8e20313b2c1eb49219da7a70ce90c3'; 10 | 11 | describe('test jsonrpc client', () => { 12 | it("Query polkadot's genesisHash via ws endpoint", async () => { 13 | const genesisHash = await getGenesisHash(WS_ENDPOINT); 14 | expect(genesisHash).toEqual(GENESIS_HASH); 15 | }, 10000); 16 | 17 | it("Query polkadot's genesisHash via http endpoint", async () => { 18 | const genesisHash = await getGenesisHash(HTTP_ENDPOINT); 19 | expect(genesisHash).toEqual(GENESIS_HASH); 20 | }); 21 | }); 22 | -------------------------------------------------------------------------------- /packages/cli/src/template/datasource-templates.ts.ejs: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | 3 | // Auto-generated , DO NOT EDIT 4 | <% props.forEach(function(e){ %> 5 | export function create<%= e.name %>Datasource(<% if (e.args) { %>args: <%- e.args %><% } %>): Promise { 6 | return createDynamicDatasource('<%= e.name %>'<% if (e.args) { %>, args<% } %>); 7 | } 8 | <% }); %> 9 | -------------------------------------------------------------------------------- /packages/cli/src/template/enum.ts.ejs: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | 3 | // Auto-generated , DO NOT EDIT 4 | <% props.enums.forEach(function(e){ %> 5 | export enum <%= e.name %> { 6 | <% e.values.forEach(function(value){ %> 7 | <%= value %> = "<%= value %>", 8 | <% }); %> 9 | } 10 | 11 | <% }); %> 12 | -------------------------------------------------------------------------------- /packages/cli/src/template/interface.ts.ejs: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | 3 | // Auto-generated , DO NOT EDIT 4 | <% props.jsonInterfaces.forEach(function(interface){ %> 5 | export interface <%= helper.upperFirst(interface.interfaceName) %> { 6 | <% interface.fields.forEach(function(field){ %> 7 | <%= field.name %><%= field.required ? "" : "?" %>: <%= field.type %><%= field.isArray ? "[]" : "" %>; 8 | <% }); %> 9 | } 10 | 11 | <% }); %> 12 | -------------------------------------------------------------------------------- /packages/cli/src/template/models-index.ts.ejs: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | 3 | // Auto-generated , DO NOT EDIT 4 | <% props.classNames.forEach(function(className){ %> 5 | export {<%= helper.upperFirst(className) %>} from "./<%= className %>" 6 | <% }); %> 7 | -------------------------------------------------------------------------------- /packages/cli/src/template/scaffold-handlers.ts.ejs: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | 3 | // Auto-generated 4 | <% props.abis.forEach(function (abi) { %> 5 | import {<% abi.handlers.forEach(function (handler) { %><%= handler.argType %>,<% })%>} from "../types/abi-interfaces/<%= abi.name %>"; 6 | <% })%> 7 | <% props.abis.forEach(function (abi) { %><% abi.handlers.forEach(function (handler) { %> 8 | export async function <%=handler.name %>(<%=handler.argName%>: <%=handler.argType %> ): Promise { 9 | // Place your code logic here 10 | } 11 | <% })%><% })%> -------------------------------------------------------------------------------- /packages/cli/src/template/types-index.ts.ejs: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | 3 | // Auto-generated , DO NOT EDIT 4 | <%if (props.exportTypes.models){%>export * from "./models"; <% } %> 5 | <%if (props.exportTypes.interfaces){%>export * from "./interfaces";<% } %> 6 | <%if (props.exportTypes.enums){%>export * from "./enums";<% } %> 7 | <%if (props.exportTypes.datasources){%>export * from "./datasources";<% } %> 8 | -------------------------------------------------------------------------------- /packages/cli/src/utils/index.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2020-2024 SubQuery Pte Ltd authors & contributors 2 | // SPDX-License-Identifier: GPL-3.0 3 | 4 | export * from './build'; 5 | export * from './utils'; 6 | export * from './networkFamily'; 7 | -------------------------------------------------------------------------------- /packages/cli/src/utils/networkFamily.spec.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2020-2024 SubQuery Pte Ltd authors & contributors 2 | // SPDX-License-Identifier: GPL-3.0 3 | 4 | import {NETWORK_FAMILY} from '@subql/common'; 5 | import {getNetworkFamily} from './networkFamily'; 6 | 7 | describe('Get network family', () => { 8 | it('convert input to right network family', () => { 9 | expect(getNetworkFamily('ethereum')).toBe(NETWORK_FAMILY.ethereum); 10 | expect(getNetworkFamily('Ethereum')).toBe(NETWORK_FAMILY.ethereum); 11 | expect(() => getNetworkFamily('fakeNetwork')).toThrow(`Network not found or unsupported network fakeNetwork`); 12 | }); 13 | }); 14 | -------------------------------------------------------------------------------- /packages/cli/src/utils/networkFamily.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2020-2024 SubQuery Pte Ltd authors & contributors 2 | // SPDX-License-Identifier: GPL-3.0 3 | 4 | import {NETWORK_FAMILY, runnerMapping} from '@subql/common'; 5 | 6 | const lowerCaseFirst = (str: string) => str.charAt(0).toLowerCase() + str.slice(1); 7 | 8 | function isNetwork(network: string): network is NETWORK_FAMILY { 9 | return network && lowerCaseFirst(network) in NETWORK_FAMILY; 10 | } 11 | 12 | // can be either lowerCased or UpperCased 13 | export function getNetworkFamily(network: string): NETWORK_FAMILY { 14 | if (!isNetwork(network)) { 15 | throw new Error(`Network not found or unsupported network ${network}`); 16 | } 17 | return NETWORK_FAMILY[lowerCaseFirst(network) as unknown as keyof typeof NETWORK_FAMILY]; 18 | } 19 | 20 | export function findRunnerByNetworkFamily(networkFamily: NETWORK_FAMILY): string | undefined { 21 | for (const [key, value] of Object.entries(runnerMapping)) { 22 | if (value === networkFamily) { 23 | return key; 24 | } 25 | } 26 | return undefined; 27 | } 28 | -------------------------------------------------------------------------------- /packages/cli/test/abiTest1/project.yaml: -------------------------------------------------------------------------------- 1 | specVersion: '1.0.0' 2 | name: 'example' 3 | 4 | version: '0.0.1' 5 | runner: 6 | node: 7 | name: '@subql/node-ethereum' 8 | version: '*' 9 | query: 10 | name: '@subql/query' 11 | version: '*' 12 | description: '' 13 | repository: '' 14 | schema: 15 | file: './schema.graphql' 16 | network: 17 | chainId: '1' 18 | endpoint: 'aaa' 19 | dictionary: '' 20 | 21 | customDs: 22 | assets: 23 | abis: 24 | file: ./abis.json 25 | artifact: 26 | file: ./abis/artifact.sol/artifact.json 27 | dataSources: 28 | - kind: ethereum/Runtime 29 | startBlock: 1 30 | mapping: 31 | file: '' 32 | handlers: 33 | - handler: handleTransaction 34 | kind: ethereum/BlockHandler 35 | -------------------------------------------------------------------------------- /packages/cli/test/abiTest2/project.yaml: -------------------------------------------------------------------------------- 1 | specVersion: '1.0.0' 2 | name: 'example' 3 | 4 | schema: 5 | file: './schema.graphql' 6 | 7 | customDs: 8 | assets: 9 | artifact: 10 | file: ./artifact.json 11 | dataSources: 12 | - kind: ethereum/Runtime 13 | startBlock: 1 14 | mapping: 15 | handlers: 16 | - handler: handleTransaction 17 | kind: ethereum/BlockHandler 18 | -------------------------------------------------------------------------------- /packages/cli/test/migrate/testProject/subgraph.yaml: -------------------------------------------------------------------------------- 1 | specVersion: 0.0.4 2 | description: POAPaaaa 3 | repository: https://github.com/poap-xyz/poap-mainnet-subgraph 4 | schema: 5 | file: ./schema.graphql 6 | dataSources: 7 | - kind: ethereum/contract 8 | name: Poap 9 | network: mainnet 10 | source: 11 | address: '0x22C1f6050E56d2876009903609a2cC3fEf83B415' 12 | abi: Poap 13 | startBlock: 7844214 14 | mapping: 15 | kind: ethereum/events 16 | apiVersion: 0.0.6 17 | language: wasm/assemblyscript 18 | entities: 19 | - EventToken 20 | - Transfer 21 | abis: 22 | - name: Poap 23 | file: ./abis/Poap.json 24 | eventHandlers: 25 | - event: EventToken(uint256,uint256) 26 | handler: handleEventToken 27 | - event: Transfer(indexed address,indexed address,indexed uint256) 28 | handler: handleTransfer 29 | file: ./src/mapping.ts 30 | -------------------------------------------------------------------------------- /packages/cli/test/schemaTest/badEntity.graphql: -------------------------------------------------------------------------------- 1 | type exampleEntity @entity { 2 | id: ID! 3 | filter: exampleEntityFilter 4 | filters: exampleEntityFilters 5 | } 6 | 7 | type exampleEntityFilter @entity { 8 | id: ID! 9 | minSore: Int 10 | } 11 | 12 | type exampleEntityFilters @entity { 13 | id: ID! 14 | maxSore: Int 15 | } 16 | -------------------------------------------------------------------------------- /packages/cli/test/schemaTest/badschema.graphql: -------------------------------------------------------------------------------- 1 | type badEntity @entity { 2 | id: BigDecimal 3 | } 4 | -------------------------------------------------------------------------------- /packages/cli/test/schemaTest/generate-project-2.yaml: -------------------------------------------------------------------------------- 1 | specVersion: 1.0.0 2 | name: generate-test 3 | version: 0.0.1 4 | runner: 5 | node: 6 | name: "@subql/node-ethereum" 7 | version: "*" 8 | query: 9 | name: "@subql/query" 10 | version: "*" 11 | schema: 12 | file: ./schema.graphql 13 | network: 14 | chainId: "1" 15 | endpoint: 16 | - https://eth.api.onfinality.io/public 17 | dictionary: https://gx.api.subquery.network/sq/subquery/eth-dictionary 18 | dataSources: 19 | #datasource comment 20 | - kind: ethereum/Runtime 21 | startBlock: 4719568 22 | options: 23 | abi: erc721 24 | address: "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2" 25 | assets: 26 | erc721: 27 | file: ./erc721.json 28 | mapping: 29 | file: ./dist/index.js 30 | handlers: 31 | - handler: handleTransaction 32 | kind: ethereum/TransactionHandler 33 | filter: 34 | function: approve(address,uint256) 35 | - handler: handleLog 36 | kind: ethereum/LogHandler 37 | filter: 38 | topics: 39 | - Transfer(address,address,uint256) 40 | #handler comment 41 | -------------------------------------------------------------------------------- /packages/cli/test/schemaTest/generate-project.yaml: -------------------------------------------------------------------------------- 1 | specVersion: 1.0.0 2 | name: generate-test 3 | version: 0.0.1 4 | runner: 5 | node: 6 | name: "@subql/node-ethereum" 7 | version: "*" 8 | query: 9 | name: "@subql/query" 10 | version: "*" 11 | schema: 12 | file: ./schema.graphql 13 | network: 14 | chainId: "1" 15 | endpoint: 16 | - https://eth.api.onfinality.io/public 17 | dictionary: https://gx.api.subquery.network/sq/subquery/eth-dictionary 18 | dataSources: 19 | - kind: ethereum/Runtime 20 | startBlock: 4719568 21 | options: 22 | abi: erc721 23 | address: "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2" 24 | assets: 25 | erc721: 26 | file: ./erc721.json 27 | mapping: 28 | file: ./dist/index.js 29 | handlers: 30 | - handler: handleTransaction 31 | kind: ethereum/TransactionHandler 32 | filter: 33 | function: approve(address spender, uint256 rawAmount) 34 | - handler: handleLog 35 | kind: ethereum/LogHandler 36 | filter: 37 | topics: 38 | - Transfer(address indexed from, address indexed to, uint256 39 | amount) 40 | -------------------------------------------------------------------------------- /packages/cli/test/schemaTest/non-evm-project.yaml: -------------------------------------------------------------------------------- 1 | specVersion: '1.0.0' 2 | name: 'example' 3 | 4 | schema: 5 | file: './schema.graphql' 6 | 7 | customDs: 8 | kind: substrate/Wasm 9 | assets: 10 | erc721: 11 | file: ./abis/erc721.json 12 | -------------------------------------------------------------------------------- /packages/cli/test/schemaTest/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "test-1", 3 | "version": "0.0.1", 4 | "description": "tester project", 5 | "main": "dist/index.js", 6 | "scripts": { 7 | "build": "subql build", 8 | "codegen": "subql codegen", 9 | "start:docker": "docker-compose pull && docker-compose up --remove-orphans", 10 | "dev": "subql codegen && subql build && docker-compose pull && docker-compose up --remove-orphans", 11 | "prepack": "rm -rf dist && npm run build", 12 | "test": "subql build && subql-node-ethereum test" 13 | }, 14 | "homepage": "https://github.com/subquery/ethereum-subql-starter", 15 | "repository": "github:subquery/ethereum-subql-starter", 16 | "files": [ 17 | "dist", 18 | "schema.graphql", 19 | "project.yaml" 20 | ], 21 | "author": "bz888", 22 | "license": "MIT", 23 | "dependencies": { 24 | "@subql/common": "latest", 25 | "@subql/types-ethereum": "latest", 26 | "assert": "^2.0.0" 27 | }, 28 | "devDependencies": { 29 | "@subql/cli": "latest", 30 | "@subql/types": "latest", 31 | "@subql/testing": "latest", 32 | "@subql/node-ethereum": "latest", 33 | "ethers": "^5.7.2", 34 | "typescript": "4.5.5" 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /packages/cli/test/schemaTest/project-bad-entity.yaml: -------------------------------------------------------------------------------- 1 | specVersion: '0.0.1' 2 | description: '' 3 | repository: 'https://github.com/subquery/subql-starter' 4 | schema: './badEntity.graphql' 5 | 6 | network: 7 | endpoint: 'wss://polkadot.api.onfinality.io/public-ws' 8 | 9 | dataSources: 10 | - name: main 11 | kind: substrate/Runtime 12 | startBlock: 1 13 | mapping: 14 | handlers: 15 | - handler: handleBlock 16 | kind: substrate/BlockHandler 17 | -------------------------------------------------------------------------------- /packages/cli/test/schemaTest/project-bad-schema.yaml: -------------------------------------------------------------------------------- 1 | specVersion: '0.0.1' 2 | description: '' 3 | repository: 'https://github.com/subquery/subql-starter' 4 | schema: './badschema.graphql' 5 | 6 | network: 7 | endpoint: 'wss://polkadot.api.onfinality.io/public-ws' 8 | 9 | dataSources: 10 | - name: main 11 | kind: substrate/Runtime 12 | startBlock: 1 13 | mapping: 14 | handlers: 15 | - handler: handleBlock 16 | kind: substrate/BlockHandler 17 | -------------------------------------------------------------------------------- /packages/cli/test/schemaTest/project-cosmos.yaml: -------------------------------------------------------------------------------- 1 | specVersion: 1.0.0 2 | name: axelar-subql-starter 3 | version: 0.0.1 4 | runner: 5 | node: 6 | name: '@subql/node-cosmos' 7 | version: '*' 8 | query: 9 | name: '@subql/query' 10 | version: '*' 11 | description: >- 12 | This project can be use as a starting point for developing your Cosmos (Axelar) based SubQuery project 13 | repository: 'https://github.com/subquery/cosmos-subql-starter' 14 | schema: 15 | file: ./schema.graphql 16 | network: 17 | chainId: axelar-dojo-1 18 | endpoint: ['https://axelar-archrpc.chainode.tech/'] 19 | chaintypes: {} 20 | dataSources: 21 | - kind: cosmos/Runtime 22 | startBlock: 5262 # The first deposit event occurs on this block 23 | mapping: 24 | file: ./dist/index.js 25 | handlers: 26 | - handler: handleEvent 27 | kind: cosmos/EventHandler 28 | filter: 29 | type: 'depositConfirmation' 30 | -------------------------------------------------------------------------------- /packages/cli/test/schemaTest/project-no-abi.yaml: -------------------------------------------------------------------------------- 1 | specVersion: '1.0.0' 2 | name: 'example' 3 | 4 | schema: 5 | file: './schema.graphql' 6 | 7 | dataSources: 8 | - kind: ethereum/Runtime 9 | startBlock: 1 10 | mapping: 11 | handlers: 12 | - handler: handleTransaction 13 | kind: ethereum/BlockHandler 14 | -------------------------------------------------------------------------------- /packages/cli/test/schemaTest/project-no-assets.yaml: -------------------------------------------------------------------------------- 1 | specVersion: '1.0.0' 2 | name: 'example' 3 | 4 | schema: 5 | file: './schema.graphql' 6 | 7 | goodDs: 8 | 9 | dataSources: 10 | - kind: ethereum/Runtime 11 | startBlock: 1 12 | mapping: 13 | handlers: 14 | - handler: handleTransaction 15 | kind: ethereum/BlockHandler 16 | templates: 17 | - name: ERC721 18 | kind: ethereum/Runtime 19 | mapping: 20 | handlers: 21 | - handler: handleERC721 22 | kind: ethereum/LogHandler 23 | filter: 24 | topics: 25 | - Transfer(address, address, uint256) 26 | -------------------------------------------------------------------------------- /packages/cli/test/schemaTest/project-templates-abi.yaml: -------------------------------------------------------------------------------- 1 | specVersion: '1.0.0' 2 | name: 'example' 3 | 4 | schema: 5 | file: './schema.graphql' 6 | 7 | dataSources: 8 | - kind: ethereum/Runtime 9 | startBlock: 1 10 | mapping: 11 | handlers: 12 | - handler: handleTransaction 13 | kind: ethereum/BlockHandler 14 | templates: 15 | - name: ERC721 16 | kind: ethereum/Runtime 17 | options: 18 | abi: erc721 19 | assets: 20 | erc721: 21 | file: './abis/erc721.json' 22 | mapping: 23 | handlers: 24 | - handler: handleERC721 25 | kind: ethereum/LogHandler 26 | filter: 27 | topics: 28 | - Transfer(address, address, uint256) 29 | -------------------------------------------------------------------------------- /packages/cli/test/schemaTest/project.yaml: -------------------------------------------------------------------------------- 1 | specVersion: '1.0.0' 2 | name: 'example' 3 | 4 | schema: 5 | file: './schema.graphql' 6 | 7 | customDs: 8 | kind: substrate/FrontierEvm 9 | assets: 10 | erc721: 11 | file: ./abis/erc721.json 12 | dataSources: 13 | - kind: ethereum/Runtime 14 | startBlock: 1 15 | mapping: 16 | handlers: 17 | - handler: handleTransaction 18 | kind: ethereum/BlockHandler 19 | -------------------------------------------------------------------------------- /packages/cli/test/schemaTest/schema.graphql: -------------------------------------------------------------------------------- 1 | enum Test { 2 | FOO 3 | BAR 4 | } 5 | type goodEntity @entity { 6 | id: ID! #id is a required field 7 | field1: Int! 8 | 9 | field2: String #filed2 is an optional field 10 | field3: BigInt 11 | 12 | field4: Date 13 | 14 | field5: Test 15 | 16 | field6: Float 17 | } 18 | -------------------------------------------------------------------------------- /packages/cli/test/schemaTest/typechain-test.yaml: -------------------------------------------------------------------------------- 1 | specVersion: '1.0.0' 2 | name: 'example' 3 | 4 | schema: 5 | file: './schema.graphql' 6 | 7 | dataSources: 8 | - kind: ethereum/Runtime 9 | startBlock: 1 10 | assets: 11 | erc721: 12 | file: ./abis/erc721.json 13 | mapping: 14 | handlers: 15 | - handler: handleTransaction 16 | kind: ethereum/BlockHandler 17 | - kind: ethereum/Runtime 18 | startBlock: 2 19 | assets: 20 | artifact: 21 | file: ../abiTest1/abis/artifact.sol/artifact.json 22 | mapping: 23 | handlers: 24 | - handler: handleTransaction 25 | kind: ethereum/BlockHandler 26 | -------------------------------------------------------------------------------- /packages/cli/test/tsManifestTest/subquery-multichain.ts: -------------------------------------------------------------------------------- 1 | import {MultichainProjectManifest} from '@subql/types-core'; 2 | 3 | const project: MultichainProjectManifest = { 4 | specVersion: '1.0.0', 5 | query: { 6 | name: '@subql/query', 7 | version: '*', 8 | }, 9 | projects: ['project1.ts', 'project2.ts'], 10 | }; 11 | 12 | export default project; 13 | -------------------------------------------------------------------------------- /packages/cli/test/tsManifestTest/subquery-multichain2.ts: -------------------------------------------------------------------------------- 1 | import {MultichainProjectManifest} from '@subql/types-core'; 2 | 3 | const project: MultichainProjectManifest = { 4 | specVersion: '1.0.0', 5 | query: { 6 | name: '@subql/query', 7 | version: '*', 8 | }, 9 | projects: ['project1.ts', 'project3.ts'], 10 | }; 11 | 12 | export default project; 13 | -------------------------------------------------------------------------------- /packages/cli/test/tsManifestTest/subquery-multichain3.ts: -------------------------------------------------------------------------------- 1 | import {MultichainProjectManifest} from '@subql/types-core'; 2 | 3 | const project: MultichainProjectManifest = { 4 | specVersion: '1.0.0', 5 | query: { 6 | name: '@subql/query', 7 | version: '*', 8 | }, 9 | projects: ['project1.ts', 'project3.yaml'], 10 | }; 11 | 12 | export default project; 13 | -------------------------------------------------------------------------------- /packages/cli/test/tsManifestTest/subquery-multichain4.yaml: -------------------------------------------------------------------------------- 1 | specVersion: 1.0.0 2 | query: 3 | name: '@subql/query' 4 | version: '*' 5 | projects: 6 | - project1.ts 7 | - project2.ts 8 | -------------------------------------------------------------------------------- /packages/cli/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.json", 3 | "compilerOptions": { 4 | "emitDecoratorMetadata": true, 5 | "experimentalDecorators": true, 6 | "esModuleInterop": true, 7 | "importHelpers": true, 8 | "rootDir": "src", 9 | "tsBuildInfoFile": "lib/.tsbuildinfo", 10 | "outDir": "lib", 11 | "noImplicitAny": true 12 | }, 13 | "references": [{"path": "../common"}, {"path": "../common-substrate"}, {"path": "../utils"}], 14 | "include": ["src/**/*"], 15 | "exclude": ["test/schemaTest/project.ts"] 16 | } 17 | -------------------------------------------------------------------------------- /packages/common-substrate/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@subql/common-substrate", 3 | "version": "3.7.0", 4 | "description": "", 5 | "scripts": { 6 | "build": "rm -rf dist && tsc -b", 7 | "test": "echo \"Error: no test specified\" && exit 1", 8 | "format": "prettier --write \"src/**/*.ts\"", 9 | "changelog:release": "echo \"Updating changelog $npm_package_version\" && npx chan release $npm_package_version --git-url \"https://github.com/subquery/subql\" --release-prefix=\"common-substrate/\"" 10 | }, 11 | "homepage": "https://github.com/subquery/subql", 12 | "repository": "github:subquery/subql", 13 | "author": "Ian He", 14 | "main": "dist/index.js", 15 | "license": "GPL-3.0", 16 | "dependencies": { 17 | "@subql/common": "workspace:*", 18 | "@subql/types": "workspace:*", 19 | "js-yaml": "^4.1.0", 20 | "reflect-metadata": "^0.1.13" 21 | }, 22 | "peerDependencies": { 23 | "class-transformer": "*", 24 | "class-validator": "*" 25 | }, 26 | "devDependencies": { 27 | "@types/bn.js": "4.11.6", 28 | "@types/js-yaml": "^4.0.4", 29 | "@types/pino": "^6.3.12" 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /packages/common-substrate/src/index.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2020-2024 SubQuery Pte Ltd authors & contributors 2 | // SPDX-License-Identifier: GPL-3.0 3 | 4 | export * from './project'; 5 | -------------------------------------------------------------------------------- /packages/common-substrate/src/project/index.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2020-2024 SubQuery Pte Ltd authors & contributors 2 | // SPDX-License-Identifier: GPL-3.0 3 | 4 | export * from './load'; 5 | export * from './models'; 6 | export * from './types'; 7 | export * from './utils'; 8 | export * from './versioned'; 9 | -------------------------------------------------------------------------------- /packages/common-substrate/src/project/types.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2020-2024 SubQuery Pte Ltd authors & contributors 2 | // SPDX-License-Identifier: GPL-3.0 3 | 4 | import {SubstrateDatasource} from '@subql/types'; 5 | import {IProjectManifest} from '@subql/types-core'; 6 | 7 | // All of these used to be redefined in this file, re-exporting for simplicity 8 | export { 9 | SubstrateRuntimeHandler, 10 | SubstrateCustomHandler, 11 | SubstrateHandler, 12 | SubstrateHandlerKind, 13 | SubstrateDatasource as SubstrateDataSource, 14 | SubstrateCustomDatasource as SubstrateCustomDataSource, 15 | SubstrateBlockFilter, 16 | SubstrateCallFilter, 17 | SubstrateEventFilter, 18 | SubstrateDatasourceProcessor, 19 | SubstrateRuntimeHandlerFilter, 20 | SubstrateDatasourceKind, 21 | RuntimeHandlerInputMap as SubstrateRuntimeHandlerInputMap, 22 | } from '@subql/types'; 23 | 24 | //make exception for runtime datasource 0.0.1 25 | export type ISubstrateProjectManifest = IProjectManifest; 26 | -------------------------------------------------------------------------------- /packages/common-substrate/src/project/versioned/index.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2020-2024 SubQuery Pte Ltd authors & contributors 2 | // SPDX-License-Identifier: GPL-3.0 3 | 4 | export * from './ProjectManifestVersioned'; 5 | export * from './v1_0_0'; 6 | -------------------------------------------------------------------------------- /packages/common-substrate/src/project/versioned/v1_0_0/index.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2020-2024 SubQuery Pte Ltd authors & contributors 2 | // SPDX-License-Identifier: GPL-3.0 3 | 4 | export * from './model'; 5 | -------------------------------------------------------------------------------- /packages/common-substrate/test/project_1.0.0_custom_ds.yaml: -------------------------------------------------------------------------------- 1 | specVersion: 1.0.0 2 | name: subquery-query-registry-project 3 | version: 1.0.0 4 | description: '' 5 | repository: '' 6 | runner: 7 | node: 8 | name: '@subql/node' 9 | version: '0.28.0' 10 | query: 11 | name: '@subql/query' 12 | version: '^0.12.0' 13 | schema: 14 | file: ./schema.graphql 15 | network: 16 | # genesisHash: '0x956876d5b80e47e523a6629b3c3ac3e42f2850ad12e236d87a0aaac87c9f6bc9' # Moonriver 17 | genesisHash: '0x91bc6e169807aaa54802737e1c504b2577d4fafedd5a02c10293b1cd60e39527' # Moonbase Alpha 18 | endpoint: wss://moonbeam-alpha.api.onfinality.io/public-ws 19 | dictionary: https://api.subquery.network/sq/subquery/moonbase-alpha-dictionary 20 | 21 | chaintypes: 22 | file: './types.yaml' 23 | dataSources: 24 | - kind: substrate/FrontierEvm 25 | startBlock: 171658 26 | processor: 27 | file: './node_modules/@subql/frontier-evm-processor/dist/index.js' 28 | mapping: 29 | file: './dist/index.js' 30 | handlers: 31 | - handler: handleTransaction 32 | kind: substrate/FrontierEvmCall 33 | filter: 34 | function: '0x60806040' 35 | -------------------------------------------------------------------------------- /packages/common-substrate/test/project_1.0.0_falsy.yaml: -------------------------------------------------------------------------------- 1 | specVersion: 1.0.0 2 | name: subquery-query-registry-project 3 | version: 1.0.0 4 | description: '' 5 | repository: '' 6 | runner: 7 | node: 8 | name: '@subql/node' 9 | version: '0.28.0' 10 | query: 11 | name: '@subql/query' 12 | version: '^0.12.0' 13 | schema: 14 | file: ./schema.graphql 15 | network: 16 | # genesisHash: '0x956876d5b80e47e523a6629b3c3ac3e42f2850ad12e236d87a0aaac87c9f6bc9' # Moonriver 17 | genesisHash: '0x91bc6e169807aaa54802737e1c504b2577d4fafedd5a02c10293b1cd60e39527' # Moonbase Alpha 18 | endpoint: wss://moonbeam-alpha.api.onfinality.io/public-ws 19 | dictionary: https://api.subquery.network/sq/subquery/moonbase-alpha-dictionary 20 | 21 | chaintypes: 22 | file: './types.yaml' 23 | dataSources: 24 | - name: main 25 | kind: substrate/SmartContract 26 | mapping: 27 | handlers: 28 | - handler: handleBlock 29 | kind: substrate/XXXHandler 30 | filter: 31 | module: xxx 32 | - name: handleEvent 33 | kind: substrate/CallHandler 34 | -------------------------------------------------------------------------------- /packages/common-substrate/test/project_1.0.0_falsy_array.yaml: -------------------------------------------------------------------------------- 1 | specVersion: 1.0.0 2 | name: subquery-query-registry-project 3 | version: 1.0.0 4 | description: '' 5 | repository: '' 6 | runner: 7 | node: 8 | name: '@subql/node' 9 | version: '0.28.0' 10 | query: 11 | name: '@subql/query' 12 | version: '^0.12.0' 13 | schema: 14 | file: ./schema.graphql 15 | network: 16 | # genesisHash: '0x956876d5b80e47e523a6629b3c3ac3e42f2850ad12e236d87a0aaac87c9f6bc9' # Moonriver 17 | genesisHash: '0x91bc6e169807aaa54802737e1c504b2577d4fafedd5a02c10293b1cd60e39527' # Moonbase Alpha 18 | endpoint: wss://moonbeam-alpha.api.onfinality.io/public-ws 19 | dictionary: https://api.subquery.network/sq/subquery/moonbase-alpha-dictionary 20 | 21 | chaintypes: 22 | file: './types.yaml' 23 | dataSources: 24 | - name: main 25 | kind: substrate/Runtime 26 | startBlock: 1 27 | mapping: 28 | handlers: 29 | - handler: handleBlock 30 | kind: substrate/BlockHandler 31 | filter: 32 | specVersion: [23, 24] 33 | -------------------------------------------------------------------------------- /packages/common-substrate/test/project_1.0.0_runner_ds_mismatch.yaml: -------------------------------------------------------------------------------- 1 | specVersion: 1.0.0 2 | name: subquery-query-registry-project 3 | version: 1.0.0 4 | description: '' 5 | repository: '' 6 | runner: 7 | node: 8 | name: '@subql/node' 9 | version: ^0.30.0 10 | query: 11 | name: '@subql/query' 12 | version: ^0.12.0 13 | schema: 14 | file: ./schema.graphql 15 | network: 16 | # genesisHash: '0x956876d5b80e47e523a6629b3c3ac3e42f2850ad12e236d87a0aaac87c9f6bc9' # Moonriver 17 | genesisHash: '0x91bc6e169807aaa54802737e1c504b2577d4fafedd5a02c10293b1cd60e39527' # Moonbase Alpha 18 | endpoint: wss://moonbeam-alpha.api.onfinality.io/public-ws 19 | dictionary: https://api.subquery.network/sq/subquery/moonbase-alpha-dictionary 20 | 21 | chaintypes: 22 | file: './types.yaml' 23 | dataSources: 24 | - kind: terra/Runtime 25 | startBlock: 6694554 26 | mapping: 27 | file: './dist/index.js' 28 | handlers: 29 | - handler: handleBlock 30 | kind: terra/BlockHandler 31 | - handler: handleEvent 32 | kind: terra/EventHandler 33 | filter: 34 | type: transfer 35 | -------------------------------------------------------------------------------- /packages/common-substrate/test/project_bypass.yaml: -------------------------------------------------------------------------------- 1 | specVersion: 1.0.0 2 | name: polkadot-starter 3 | version: 0.0.1 4 | runner: 5 | node: 6 | name: '@subql/node' 7 | version: '*' 8 | query: 9 | name: '@subql/query' 10 | version: '*' 11 | description: >- 12 | This project can be used as a starting point for developing your SubQuery 13 | project 14 | repository: 'https://github.com/subquery/subql-starter' 15 | schema: 16 | file: ./schema.graphql 17 | network: 18 | chainId: '0x91b171bb158e2d3848fa23a9f1c25182fb8e20313b2c1eb49219da7a70ce90c3' 19 | endpoint: 'wss://polkadot.api.onfinality.io/public-ws' 20 | dictionary: 'https://api.subquery.network/sq/subquery/polkadot-dictionary' 21 | bypassBlocks: [1, 2, 4, 5] 22 | dataSources: 23 | - kind: substrate/Runtime 24 | startBlock: 1 25 | mapping: 26 | file: ./dist/index.js 27 | handlers: 28 | - handler: handleBlock 29 | kind: substrate/BlockHandler 30 | - handler: handleEvent 31 | kind: substrate/EventHandler 32 | filter: 33 | module: balances 34 | method: Deposit 35 | - handler: handleCall 36 | kind: substrate/CallHandler 37 | -------------------------------------------------------------------------------- /packages/common-substrate/test/project_bypass_range.yaml: -------------------------------------------------------------------------------- 1 | specVersion: 1.0.0 2 | name: polkadot-starter 3 | version: 0.0.1 4 | runner: 5 | node: 6 | name: '@subql/node' 7 | version: '*' 8 | query: 9 | name: '@subql/query' 10 | version: '*' 11 | description: >- 12 | This project can be used as a starting point for developing your SubQuery 13 | project 14 | repository: 'https://github.com/subquery/subql-starter' 15 | schema: 16 | file: ./schema.graphql 17 | network: 18 | chainId: '0x91b171bb158e2d3848fa23a9f1c25182fb8e20313b2c1eb49219da7a70ce90c3' 19 | endpoint: 'wss://polkadot.api.onfinality.io/public-ws' 20 | dictionary: 'https://api.subquery.network/sq/subquery/polkadot-dictionary' 21 | bypassBlocks: [1, 2, 4, 5, '10 - 40'] 22 | dataSources: 23 | - kind: substrate/Runtime 24 | startBlock: 1 25 | mapping: 26 | file: ./dist/index.js 27 | handlers: 28 | - handler: handleBlock 29 | kind: substrate/BlockHandler 30 | - handler: handleEvent 31 | kind: substrate/EventHandler 32 | filter: 33 | module: balances 34 | method: Deposit 35 | - handler: handleCall 36 | kind: substrate/CallHandler 37 | -------------------------------------------------------------------------------- /packages/common-substrate/test/project_invalid_version.yaml: -------------------------------------------------------------------------------- 1 | # project.yaml 2 | specVersion: '0.0.0' 3 | description: '' 4 | repository: 'https://github.com/subquery/subql-starter' 5 | 6 | schema: 7 | file: ./schema.graphql 8 | 9 | network: 10 | genesisHash: '0x' 11 | chaintypes: 12 | file: ./types.json 13 | 14 | dataSources: 15 | - name: main 16 | kind: substrate/Runtime 17 | startBlock: 1 18 | mapping: 19 | file: dist/index.js 20 | handlers: 21 | - handler: handleBlock 22 | kind: substrate/BlockHandler 23 | - handler: handleEvent 24 | kind: substrate/EventHandler 25 | filter: #Filter is optional 26 | module: balances 27 | method: Deposit 28 | - handler: handleCall 29 | kind: substrate/CallHandler 30 | -------------------------------------------------------------------------------- /packages/common-substrate/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.json", 3 | "compilerOptions": { 4 | "rootDir": "src", 5 | "tsBuildInfoFile": "dist/.tsbuildinfo", 6 | "outDir": "dist", 7 | "noImplicitAny": true 8 | }, 9 | "references": [{"path": "../types"}, {"path": "../common"}], 10 | "include": ["src/**/*"] 11 | } 12 | -------------------------------------------------------------------------------- /packages/common/fixtures/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "subquery-starter", 3 | "version": "0.0.3", 4 | "description": "This project can be use as a starting point for developing your SubQuery project", 5 | "main": "dist/index.js", 6 | "scripts": { 7 | "build": "tsc -b", 8 | "prepack": "rm -rf dist && npm build", 9 | "test": "jest", 10 | "codegen": "./node_modules/.bin/subql codegen" 11 | }, 12 | "homepage": "https://github.com/subquery/subql-starter", 13 | "repository": "github:subquery/subql-starter", 14 | "files": [ 15 | "dist", 16 | "schema.graphql", 17 | "project.yaml" 18 | ], 19 | "author": "Ian He & Jay Ji", 20 | "license": "Apache-2.0", 21 | "devDependencies": { 22 | "@polkadot/api": "11.0.2", 23 | "@subql/types": "latest", 24 | "typescript": "^4.9.5", 25 | "@subql/cli": "latest" 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /packages/common/fixtures/project.yaml: -------------------------------------------------------------------------------- 1 | specVersion: "0.0.1" 2 | description: "" 3 | repository: "https://github.com/subquery/subql-starter" 4 | 5 | schema: "./schema.graphql" 6 | 7 | network: 8 | endpoint: "wss://polkadot.api.onfinality.io/public-ws" 9 | 10 | dataSources: 11 | - name: main 12 | kind: substrate/Runtime 13 | startBlock: 1 14 | mapping: 15 | handlers: 16 | - handler: handleBlock 17 | kind: substrate/BlockHandler 18 | - handler: handleEvent 19 | kind: substrate/EventHandler 20 | filter: #Filter is optional 21 | module: balances 22 | method: Deposit 23 | - handler: handleCall 24 | kind: substrate/CallHandler 25 | -------------------------------------------------------------------------------- /packages/common/src/index.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2020-2024 SubQuery Pte Ltd authors & contributors 2 | // SPDX-License-Identifier: GPL-3.0 3 | 4 | import 'reflect-metadata'; 5 | 6 | export * from './project'; 7 | export * from './constants'; 8 | export * from './multichain'; 9 | -------------------------------------------------------------------------------- /packages/common/src/multichain/index.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2020-2024 SubQuery Pte Ltd authors & contributors 2 | // SPDX-License-Identifier: GPL-3.0 3 | 4 | export * from './models'; 5 | -------------------------------------------------------------------------------- /packages/common/src/multichain/models.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2020-2024 SubQuery Pte Ltd authors & contributors 2 | // SPDX-License-Identifier: GPL-3.0 3 | 4 | import {MultichainProjectManifest, QuerySpec} from '@subql/types-core'; 5 | import {Type} from 'class-transformer'; 6 | import {Equals, IsObject, IsString} from 'class-validator'; 7 | import {RunnerQueryBaseModel} from '../project'; 8 | 9 | export class MultichainProjectManifestModel implements MultichainProjectManifest { 10 | @Equals('1.0.0') 11 | specVersion: string; 12 | @IsString({each: true}) 13 | projects: string[]; 14 | @IsObject() 15 | @Type(() => RunnerQueryBaseModel) 16 | query: QuerySpec; 17 | } 18 | -------------------------------------------------------------------------------- /packages/common/src/project/database/databaseUtil.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2020-2024 SubQuery Pte Ltd authors & contributors 2 | // SPDX-License-Identifier: GPL-3.0 3 | 4 | import {Sequelize} from '@subql/x-sequelize'; 5 | import {Pool} from 'pg'; 6 | import {SUPPORT_DB} from '../../constants'; 7 | 8 | export async function getDbType(queryFrom: Sequelize | Pool): Promise { 9 | const result = await (queryFrom as any).query('select version()'); 10 | // sequelize return an array, Promise<[unknown[], unknown] 11 | // pgPool return a single string object with rows 12 | const cleanResult = result instanceof Array ? result[0][0] : result.rows[0]; 13 | const matchDB = Object.values(SUPPORT_DB).find((db) => (cleanResult as {version: string}).version.includes(db)); 14 | if (!matchDB) { 15 | throw new Error(`Database type not supported, got ${result}`); 16 | } 17 | return matchDB; 18 | } 19 | -------------------------------------------------------------------------------- /packages/common/src/project/database/index.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2020-2024 SubQuery Pte Ltd authors & contributors 2 | // SPDX-License-Identifier: GPL-3.0 3 | 4 | export * from './databaseUtil'; 5 | -------------------------------------------------------------------------------- /packages/common/src/project/index.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2020-2024 SubQuery Pte Ltd authors & contributors 2 | // SPDX-License-Identifier: GPL-3.0 3 | 4 | export * from './load'; 5 | export * from './versioned'; 6 | export * from './readers'; 7 | export * from './database'; 8 | export * from './utils'; 9 | -------------------------------------------------------------------------------- /packages/common/src/project/readers/github-reader.spec.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2020-2024 SubQuery Pte Ltd authors & contributors 2 | // SPDX-License-Identifier: GPL-3.0 3 | 4 | import {Reader} from '@subql/types-core'; 5 | import {GithubReader} from './github-reader'; 6 | 7 | describe('GithubReader', () => { 8 | let reader: Reader; 9 | 10 | beforeAll(() => { 11 | const key = 'subquery/tutorials-block-timestamp'; 12 | reader = new GithubReader(key); 13 | }); 14 | 15 | it('should return the package json object', async () => { 16 | const data = await reader.getPkg(); 17 | expect(data.name).toBe('block-timestamp'); 18 | }); 19 | 20 | it('should return the project schema object', async () => { 21 | const data: any = await reader.getProjectSchema(); 22 | expect(data.repository).toBe('https://github.com/subquery/subql-examples'); 23 | }); 24 | }); 25 | -------------------------------------------------------------------------------- /packages/common/src/project/readers/index.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2020-2024 SubQuery Pte Ltd authors & contributors 2 | // SPDX-License-Identifier: GPL-3.0 3 | 4 | export * from './reader'; 5 | export * from './github-reader'; 6 | export * from './ipfs-reader'; 7 | export * from './local-reader'; 8 | -------------------------------------------------------------------------------- /packages/common/src/project/readers/ipfs-reader.spec.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2020-2024 SubQuery Pte Ltd authors & contributors 2 | // SPDX-License-Identifier: GPL-3.0 3 | 4 | import {Reader} from '@subql/types-core'; 5 | import {IPFSReader} from './ipfs-reader'; 6 | 7 | const IPFSGateway = 'https://unauthipfs.subquery.network/ipfs/api/v0'; 8 | 9 | describe('IPFSReader', () => { 10 | let reader: Reader; 11 | 12 | it('should return a project deployment', async () => { 13 | reader = new IPFSReader('QmNbkA1fJpV2gCAWCBjgUQ8xBTwkLZHuzx4EkUoKx7VYaD', IPFSGateway); 14 | 15 | const data: any = await reader.getProjectSchema(); 16 | 17 | expect(data.network.chainId).toBe('43114'); 18 | }); 19 | 20 | it('ipfs should only fetch once when cache found', async () => { 21 | reader = new IPFSReader('QmNbkA1fJpV2gCAWCBjgUQ8xBTwkLZHuzx4EkUoKx7VYaD', IPFSGateway); 22 | const spyIpfsCat = jest.spyOn((reader as any).ipfs, 'cat'); 23 | await Promise.all([reader.getProjectSchema(), reader.getProjectSchema(), reader.getProjectSchema()]); 24 | expect(spyIpfsCat).toHaveBeenCalledTimes(1); 25 | }); 26 | }); 27 | -------------------------------------------------------------------------------- /packages/common/src/project/readers/local-reader.spec.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2020-2024 SubQuery Pte Ltd authors & contributors 2 | // SPDX-License-Identifier: GPL-3.0 3 | 4 | import * as path from 'path'; 5 | import {Reader} from '@subql/types-core'; 6 | import {LocalReader} from './local-reader'; 7 | 8 | describe('LocalReader', () => { 9 | let reader: Reader; 10 | 11 | beforeAll(() => { 12 | const loc = path.join(__dirname, '../../../fixtures'); 13 | reader = new LocalReader(loc, path.resolve(loc, './project.yaml')); 14 | }); 15 | 16 | it('should return the package json object', async () => { 17 | const data = await reader.getPkg(); 18 | expect(data.name).toBe('subquery-starter'); 19 | }); 20 | 21 | it('should return the project schema object', async () => { 22 | const data: any = await reader.getProjectSchema(); 23 | expect(data.repository).toBe('https://github.com/subquery/subql-starter'); 24 | }); 25 | }); 26 | -------------------------------------------------------------------------------- /packages/common/src/project/versioned/index.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2020-2024 SubQuery Pte Ltd authors & contributors 2 | // SPDX-License-Identifier: GPL-3.0 3 | 4 | export * from './base'; 5 | export * from './v1_0_0'; 6 | -------------------------------------------------------------------------------- /packages/common/src/project/versioned/v1_0_0/index.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2020-2024 SubQuery Pte Ltd authors & contributors 2 | // SPDX-License-Identifier: GPL-3.0 3 | 4 | export * from './models'; 5 | -------------------------------------------------------------------------------- /packages/common/test/mockedSubqueryProject.tgz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Zikc2023/subql/d164f848bfaa82aaa5f842a9a5a9a1b946fb97d3/packages/common/test/mockedSubqueryProject.tgz -------------------------------------------------------------------------------- /packages/common/test/project_0.2.0.yaml: -------------------------------------------------------------------------------- 1 | # project.yaml 2 | specVersion: '0.2.0' 3 | description: '' 4 | repository: 'https://github.com/subquery/subql-starter' 5 | name: Test 6 | version: '0.0.0' 7 | 8 | schema: 9 | file: ./schema.graphql 10 | 11 | network: 12 | genesisHash: '0x' 13 | dictionary: 'https://api.subquery.network/sq/subquery/dictionary-polkadot' 14 | chaintypes: 15 | file: ./types.json 16 | 17 | dataSources: 18 | - kind: substrate/Runtime 19 | startBlock: 1 20 | mapping: 21 | file: dist/index.js 22 | handlers: 23 | - handler: handleBlock 24 | kind: substrate/BlockHandler 25 | - handler: handleEvent 26 | kind: substrate/EventHandler 27 | filter: #Filter is optional 28 | module: balances 29 | method: Deposit 30 | - handler: handleCall 31 | kind: substrate/CallHandler 32 | -------------------------------------------------------------------------------- /packages/common/test/project_0.2.0_custom_ds.yaml: -------------------------------------------------------------------------------- 1 | # project.yaml 2 | specVersion: '0.2.0' 3 | description: '' 4 | repository: 'https://github.com/subquery/subql-starter' 5 | name: Test 6 | version: '0.0.0' 7 | 8 | schema: 9 | file: ./schema.graphql 10 | 11 | network: 12 | genesisHash: '0x' 13 | chaintypes: 14 | file: ./types.json 15 | 16 | dataSources: 17 | - kind: substrate/Jsonfy 18 | startBlock: 1 19 | processor: 20 | file: '@subql/contract-processors/jsonfy.js' 21 | assets: 22 | test: 23 | file: './abi.json' 24 | mapping: 25 | file: dist/index.js 26 | handlers: 27 | - handler: handleEvent 28 | kind: substrate/JsonfyEvent 29 | -------------------------------------------------------------------------------- /packages/common/test/project_0.2.0_invalid_custom_ds.yaml: -------------------------------------------------------------------------------- 1 | # project.yaml 2 | specVersion: '0.2.0' 3 | description: '' 4 | repository: 'https://github.com/subquery/subql-starter' 5 | name: Test 6 | version: '0.0.0' 7 | 8 | schema: 9 | file: ./schema.graphql 10 | 11 | network: 12 | genesisHash: '0x' 13 | chaintypes: 14 | file: ./types.json 15 | 16 | dataSources: 17 | - kind: substrate/Jsonfy 18 | startBlock: 1 19 | # processor: 20 | # file: '@subql/contract-processors/jsonfy.js' 21 | mapping: 22 | file: dist/index.js 23 | handlers: 24 | - handler: handleEvent 25 | kind: substrate/JsonfyEvent 26 | -------------------------------------------------------------------------------- /packages/common/test/project_falsy.yaml: -------------------------------------------------------------------------------- 1 | specVersion: '0.0.1' 2 | description: '' 3 | repository: 'https://github.com/OnFinality-io/subql-examples' 4 | 5 | schema: './schema.graphql' 6 | 7 | #network: 8 | # endpoint: 'wss://polkadot.api.onfinality.io/public-ws' 9 | 10 | dataSources: 11 | - name: main 12 | kind: substrate/SmartContract 13 | mapping: 14 | handlers: 15 | - handler: handleBlock 16 | kind: substrate/XXXHandler 17 | filter: 18 | module: xxx 19 | - name: handleEvent 20 | kind: substrate/CallHandler 21 | -------------------------------------------------------------------------------- /packages/common/test/project_falsy_array.yaml: -------------------------------------------------------------------------------- 1 | - specVersion: '0.0.1' 2 | description: '' 3 | repository: 'https://github.com/OnFinality-io/subql-examples' 4 | 5 | schema: './schema.graphql' 6 | 7 | #network: 8 | # endpoint: 'wss://polkadot.api.onfinality.io/public-ws' 9 | dataSources: 10 | - name: main 11 | kind: substrate/Runtime 12 | startBlock: 1 13 | mapping: 14 | handlers: 15 | - handler: handleBlock 16 | kind: substrate/BlockHandler 17 | filter: 18 | specVersion: [23, 24] 19 | 20 | 21 | - specVersion: '0.0.2' 22 | description: '' 23 | repository: 'https://github.com/OnFinality-io/subql-examples' 24 | 25 | schema: './schema.graphql' 26 | 27 | #network: 28 | # endpoint: 'wss://polkadot.api.onfinality.io/public-ws' 29 | dataSources: 30 | - name: main 31 | kind: substrate/Runtime 32 | startBlock: 1 33 | mapping: 34 | handlers: 35 | - handler: handleBlock 36 | kind: substrate/BlockHandler 37 | filter: 38 | specVersion: [23, 24] 39 | -------------------------------------------------------------------------------- /packages/common/test/project_invalid_version.yaml: -------------------------------------------------------------------------------- 1 | # project.yaml 2 | specVersion: "0.0.0" 3 | description: "" 4 | repository: "https://github.com/subquery/subql-starter" 5 | 6 | schema: 7 | file: ./schema.graphql 8 | 9 | network: 10 | genesisHash: '0x' 11 | chaintypes: 12 | file: ./types.json 13 | 14 | dataSources: 15 | - name: main 16 | kind: substrate/Runtime 17 | startBlock: 1 18 | mapping: 19 | file: dist/index.js 20 | handlers: 21 | - handler: handleBlock 22 | kind: substrate/BlockHandler 23 | - handler: handleEvent 24 | kind: substrate/EventHandler 25 | filter: #Filter is optional 26 | module: balances 27 | method: Deposit 28 | - handler: handleCall 29 | kind: substrate/CallHandler 30 | 31 | 32 | -------------------------------------------------------------------------------- /packages/common/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.json", 3 | "compilerOptions": { 4 | "rootDir": "src", 5 | "tsBuildInfoFile": "dist/.tsbuildinfo", 6 | "outDir": "dist", 7 | "noImplicitAny": true 8 | }, 9 | "references": [{"path": "../types"}], 10 | "include": ["src/**/*"] 11 | } 12 | -------------------------------------------------------------------------------- /packages/node-core/logger.js: -------------------------------------------------------------------------------- 1 | // Copyright 2020-2024 SubQuery Pte Ltd authors & contributors 2 | // SPDX-License-Identifier: GPL-3.0 3 | 4 | // A standalone entrypoint for logger so we can import `@subql/node-core/logger` 5 | const logger = require('./dist/logger'); 6 | 7 | module.exports = logger; 8 | -------------------------------------------------------------------------------- /packages/node-core/src/configure/configure.module.spec.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2020-2024 SubQuery Pte Ltd authors & contributors 2 | // SPDX-License-Identifier: GPL-3.0 3 | 4 | import {validDbSchemaName} from './configure.module'; 5 | 6 | describe('Configure', () => { 7 | it('validDbSchemaName - works', () => { 8 | expect(validDbSchemaName('subquery_1')).toBeTruthy(); 9 | }); 10 | it('validDbSchemaName - works not alphanumeric', () => { 11 | expect(validDbSchemaName('subquery_-/1')).toBeTruthy(); 12 | }); 13 | it('validDbSchemaName - long', () => { 14 | expect(validDbSchemaName('a'.repeat(64))).toBeFalsy(); 15 | }); 16 | it('validDbSchemaName - invalid prefix', () => { 17 | expect(validDbSchemaName('pg_whatever')).toBeFalsy(); 18 | }); 19 | it('validDbSchemaName - invalid tokens', () => { 20 | expect(validDbSchemaName('he$$*')).toBeFalsy(); 21 | }); 22 | it('validDbSchemaName - empty', () => { 23 | expect(validDbSchemaName('')).toBeFalsy(); 24 | }); 25 | }); 26 | -------------------------------------------------------------------------------- /packages/node-core/src/configure/index.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2020-2024 SubQuery Pte Ltd authors & contributors 2 | // SPDX-License-Identifier: GPL-3.0 3 | 4 | export * from './configure.module'; 5 | export * from './NodeConfig'; 6 | export * from './ProjectUpgrade.service'; 7 | -------------------------------------------------------------------------------- /packages/node-core/src/db/index.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2020-2024 SubQuery Pte Ltd authors & contributors 2 | // SPDX-License-Identifier: GPL-3.0 3 | 4 | export * from './db.module'; 5 | export * from './migration-service'; 6 | export * from './sync-helper'; 7 | -------------------------------------------------------------------------------- /packages/node-core/src/db/migration-service/index.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2020-2024 SubQuery Pte Ltd authors & contributors 2 | // SPDX-License-Identifier: GPL-3.0 3 | 4 | export * from './migration'; 5 | export * from './SchemaMigration.service'; 6 | -------------------------------------------------------------------------------- /packages/node-core/src/index.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2020-2024 SubQuery Pte Ltd authors & contributors 2 | // SPDX-License-Identifier: GPL-3.0 3 | 4 | import './utils/bigint'; 5 | 6 | export * from './api.service'; 7 | export * from './api.connection.error'; 8 | export * from './logger'; 9 | export * from './profiler'; 10 | export * from './events'; 11 | export * from './configure'; 12 | export * from './db'; 13 | export * from './meta'; 14 | export * from './utils'; 15 | export * from './indexer'; 16 | export * from './subcommands'; 17 | export * from './yargs'; 18 | -------------------------------------------------------------------------------- /packages/node-core/src/indexer/blockDispatcher/index.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2020-2024 SubQuery Pte Ltd authors & contributors 2 | // SPDX-License-Identifier: GPL-3.0 3 | 4 | export * from './base-block-dispatcher'; 5 | export * from './block-dispatcher'; 6 | export * from './worker-block-dispatcher'; 7 | -------------------------------------------------------------------------------- /packages/node-core/src/indexer/dictionary/index.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2020-2024 SubQuery Pte Ltd authors & contributors 2 | // SPDX-License-Identifier: GPL-3.0 3 | 4 | export * from './v1'; 5 | export * from './v2'; 6 | export * from './types'; 7 | export * from './dictionary.service'; 8 | export * from './utils'; 9 | -------------------------------------------------------------------------------- /packages/node-core/src/indexer/dictionary/v1/index.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2020-2024 SubQuery Pte Ltd authors & contributors 2 | // SPDX-License-Identifier: GPL-3.0 3 | 4 | export * from './dictionaryV1'; 5 | export * from './utils'; 6 | -------------------------------------------------------------------------------- /packages/node-core/src/indexer/dictionary/v2/index.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2020-2024 SubQuery Pte Ltd authors & contributors 2 | // SPDX-License-Identifier: GPL-3.0 3 | 4 | export * from './types'; 5 | export * from './dictionaryV2'; 6 | -------------------------------------------------------------------------------- /packages/node-core/src/indexer/dictionary/v2/types.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2020-2024 SubQuery Pte Ltd authors & contributors 2 | // SPDX-License-Identifier: GPL-3.0 3 | 4 | export interface V2MetadataFilters { 5 | [key: string]: string[]; 6 | } 7 | 8 | export interface FieldSelector { 9 | [key: string]: boolean | FieldSelector; 10 | } 11 | 12 | export interface RawDictionaryResponseData { 13 | blocks: RFB[]; //raw fat blocks 14 | blockRange: [string, string]; // Hex encoded numbers 15 | genesisHash: string; 16 | } 17 | 18 | export interface DictionaryV2Metadata { 19 | start: number; 20 | end: number; 21 | genesisHash: string; 22 | chainId: string; 23 | filters: V2MetadataFilters; 24 | supported: string[]; 25 | } 26 | 27 | export type DictionaryV2QueryEntry = Record; 28 | -------------------------------------------------------------------------------- /packages/node-core/src/indexer/entities/index.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2020-2024 SubQuery Pte Ltd authors & contributors 2 | // SPDX-License-Identifier: GPL-3.0 3 | 4 | export * from './Poi.entity'; 5 | export * from './Metadata.entity'; 6 | -------------------------------------------------------------------------------- /packages/node-core/src/indexer/inMemoryCache.service.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2020-2024 SubQuery Pte Ltd authors & contributors 2 | // SPDX-License-Identifier: GPL-3.0 3 | 4 | import {Injectable} from '@nestjs/common'; 5 | import {Cache} from '@subql/types-core'; 6 | 7 | /** 8 | * The `InMemoryCacheService` class provides an in-memory caching solution. 9 | * It's designed to temporarily store data that doesn't need to be persisted in a database. 10 | * The service is injectable and designed to be used within the sandbox 11 | */ 12 | @Injectable() 13 | export class InMemoryCacheService = Record> { 14 | private cache: T = {} as T; 15 | 16 | getCache(): Cache { 17 | return { 18 | //eslint-disable-next-line @typescript-eslint/require-await 19 | get: async (key: keyof T): Promise => { 20 | return this.cache[key]; 21 | }, 22 | 23 | //eslint-disable-next-line @typescript-eslint/require-await 24 | set: async (key: keyof T, value: T[keyof T]): Promise => { 25 | this.cache[key] = value; 26 | }, 27 | }; 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /packages/node-core/src/indexer/index.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2020-2024 SubQuery Pte Ltd authors & contributors 2 | // SPDX-License-Identifier: GPL-3.0 3 | 4 | export * from './benchmark.service'; 5 | export * from './connectionPool.service'; 6 | export * from './connectionPoolState.manager'; 7 | export * from './entities'; 8 | export * from './poi'; 9 | export * from './types'; 10 | export * from './StoreOperations'; 11 | export * from './store.service'; 12 | export * from './inMemoryCache.service'; 13 | export * from './storeCache'; 14 | export * from './worker'; 15 | export * from './dictionary'; 16 | export * from './sandbox'; 17 | export * from './sandbox.service'; 18 | export * from './blockDispatcher'; 19 | export * from './dynamic-ds.service'; 20 | export * from './testing.service'; 21 | export * from './test.runner'; 22 | export * from './project.service'; 23 | export * from './fetch.service'; 24 | export * from './indexer.manager'; 25 | export * from './ds-processor.service'; 26 | export * from './unfinalizedBlocks.service'; 27 | -------------------------------------------------------------------------------- /packages/node-core/src/indexer/poi/index.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2020-2024 SubQuery Pte Ltd authors & contributors 2 | // SPDX-License-Identifier: GPL-3.0 3 | 4 | export * from './poiModel'; 5 | export * from './poi.service'; 6 | export * from './poiSync.service'; 7 | export * from './PoiBlock'; 8 | -------------------------------------------------------------------------------- /packages/node-core/src/indexer/store/entity.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2020-2024 SubQuery Pte Ltd authors & contributors 2 | // SPDX-License-Identifier: GPL-3.0 3 | 4 | import {Store, Entity} from '@subql/types-core'; 5 | 6 | export class EntityClass implements Entity { 7 | id: string; 8 | // Name needs to be private so that it can be converted to a generated entity 9 | #name: string; 10 | 11 | constructor(name: string, properties: {id: string} & any, private store: Store) { 12 | this.#name = name; 13 | this.id = properties.id; 14 | Object.assign(this, properties); 15 | } 16 | 17 | static create(name: string, properties: ({id: string} & any) | null, store: Store): T | undefined { 18 | if (!properties) return undefined; 19 | 20 | return new EntityClass(name, properties, store) as unknown as T; 21 | } 22 | 23 | async save(): Promise { 24 | return this.store.set(this.#name, this.id, this); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /packages/node-core/src/indexer/store/index.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2020-2024 SubQuery Pte Ltd authors & contributors 2 | // SPDX-License-Identifier: GPL-3.0 3 | 4 | export * from './store'; 5 | -------------------------------------------------------------------------------- /packages/node-core/src/indexer/storeCache/cacheable.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2020-2024 SubQuery Pte Ltd authors & contributors 2 | // SPDX-License-Identifier: GPL-3.0 3 | 4 | import {Transaction} from '@subql/x-sequelize'; 5 | import {Mutex} from 'async-mutex'; 6 | 7 | export abstract class Cacheable { 8 | protected mutex = new Mutex(); 9 | 10 | abstract clear(blockHeight?: number): void; 11 | protected abstract runFlush(tx: Transaction, blockHeight: number): Promise; 12 | 13 | async flush(tx: Transaction, blockHeight: number): Promise { 14 | const release = await this.mutex.acquire(); 15 | 16 | try { 17 | tx.afterCommit(() => { 18 | this.clear(blockHeight); 19 | release(); 20 | }); 21 | 22 | const pendingFlush = this.runFlush(tx, blockHeight); 23 | await pendingFlush; 24 | } catch (e) { 25 | release(); 26 | throw e; 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /packages/node-core/src/indexer/storeCache/index.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2020-2024 SubQuery Pte Ltd authors & contributors 2 | // SPDX-License-Identifier: GPL-3.0 3 | 4 | export * from './storeCache.service'; 5 | export * from './types'; 6 | export * from './cacheModel'; 7 | export * from './cacheMetadata'; 8 | -------------------------------------------------------------------------------- /packages/node-core/src/indexer/worker/index.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2020-2024 SubQuery Pte Ltd authors & contributors 2 | // SPDX-License-Identifier: GPL-3.0 3 | 4 | export * from './worker.builder'; 5 | export * from './worker.store.service'; 6 | export * from './worker.cache.service'; 7 | export * from './worker.dynamic-ds.service'; 8 | export * from './worker.connectionPoolState.manager'; 9 | export * from './worker.unfinalizedBlocks.service'; 10 | export * from './worker.service'; 11 | export * from './worker'; 12 | export * from './utils'; 13 | -------------------------------------------------------------------------------- /packages/node-core/src/indexer/worker/test.store.worker.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2020-2024 SubQuery Pte Ltd authors & contributors 2 | // SPDX-License-Identifier: GPL-3.0 3 | 4 | import {Store} from '@subql/types-core'; 5 | import {WorkerHost} from './worker.builder'; 6 | import {hostStoreKeys, hostStoreToStore} from './worker.store.service'; 7 | 8 | let store: Store | null = null; 9 | 10 | async function callStoreFunction(name: string, args: any[]) { 11 | if (store === null) { 12 | throw new Error('Store is null'); 13 | } 14 | const res = await (store as any)[name as any](...args); 15 | } 16 | 17 | const host = WorkerHost.create( 18 | hostStoreKeys, 19 | { 20 | callStoreFunction, 21 | }, 22 | null as any 23 | ); 24 | 25 | store = hostStoreToStore(host as any); 26 | -------------------------------------------------------------------------------- /packages/node-core/src/meta/health.controller.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2020-2024 SubQuery Pte Ltd authors & contributors 2 | // SPDX-License-Identifier: GPL-3.0 3 | 4 | import {Controller, Get, HttpException, HttpStatus} from '@nestjs/common'; 5 | import {getLogger} from '../logger'; 6 | import {HealthService} from './health.service'; 7 | 8 | const logger = getLogger('health'); 9 | 10 | @Controller('health') 11 | export class HealthController { 12 | constructor(private healthService: HealthService) {} 13 | 14 | @Get() 15 | getHealth(): void { 16 | try { 17 | this.healthService.getHealth(); 18 | } catch (e: any) { 19 | logger.error(e); 20 | throw new HttpException( 21 | { 22 | status: HttpStatus.INTERNAL_SERVER_ERROR, 23 | error: e.message, 24 | }, 25 | HttpStatus.INTERNAL_SERVER_ERROR 26 | ); 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /packages/node-core/src/meta/index.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2020-2024 SubQuery Pte Ltd authors & contributors 2 | // SPDX-License-Identifier: GPL-3.0 3 | 4 | import {MetricEventListener} from './event.listener'; 5 | import {HealthController} from './health.controller'; 6 | import {HealthService} from './health.service'; 7 | import {gaugeProviders} from './meta'; 8 | import {ReadyController} from './ready.controller'; 9 | import {ReadyService} from './ready.service'; 10 | 11 | export * from './meta.service'; 12 | 13 | export const metaControllers = [HealthController, ReadyController]; 14 | 15 | export const metaServices = [MetricEventListener, HealthService, ReadyService, ...gaugeProviders]; 16 | -------------------------------------------------------------------------------- /packages/node-core/src/meta/ready.controller.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2020-2024 SubQuery Pte Ltd authors & contributors 2 | // SPDX-License-Identifier: GPL-3.0 3 | 4 | import {Controller, Get, HttpException, HttpStatus} from '@nestjs/common'; 5 | import {ReadyService} from './ready.service'; 6 | 7 | @Controller('ready') 8 | export class ReadyController { 9 | constructor(private readyService: ReadyService) {} 10 | 11 | @Get() 12 | getReady() { 13 | if (!this.readyService.ready) { 14 | throw new HttpException( 15 | { 16 | status: HttpStatus.SERVICE_UNAVAILABLE, 17 | error: 'Database schema is not created or ready', 18 | }, 19 | HttpStatus.SERVICE_UNAVAILABLE 20 | ); 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /packages/node-core/src/meta/ready.service.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2020-2024 SubQuery Pte Ltd authors & contributors 2 | // SPDX-License-Identifier: GPL-3.0 3 | 4 | import {Injectable} from '@nestjs/common'; 5 | import {OnEvent} from '@nestjs/event-emitter'; 6 | import {EventPayload, IndexerEvent} from '../events'; 7 | 8 | @Injectable() 9 | export class ReadyService { 10 | private _ready: boolean; 11 | 12 | constructor() { 13 | this._ready = false; 14 | } 15 | 16 | @OnEvent(IndexerEvent.Ready) 17 | handleReady({value}: EventPayload): void { 18 | this._ready = value; 19 | } 20 | 21 | get ready(): boolean { 22 | return this._ready; 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /packages/node-core/src/subcommands/forceClean.module.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2020-2024 SubQuery Pte Ltd authors & contributors 2 | // SPDX-License-Identifier: GPL-3.0 3 | 4 | import {Module} from '@nestjs/common'; 5 | import {SchedulerRegistry} from '@nestjs/schedule'; 6 | import {ForceCleanService} from './forceClean.service'; 7 | 8 | @Module({ 9 | providers: [ForceCleanService, SchedulerRegistry], 10 | controllers: [], 11 | }) 12 | export class ForceCleanFeatureModule {} 13 | -------------------------------------------------------------------------------- /packages/node-core/src/subcommands/foreceClean.init.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2020-2024 SubQuery Pte Ltd authors & contributors 2 | // SPDX-License-Identifier: GPL-3.0 3 | 4 | import {NestFactory} from '@nestjs/core'; 5 | import {getLogger} from '../logger'; 6 | import {ForceCleanService} from './forceClean.service'; 7 | 8 | const logger = getLogger('CLI'); 9 | export async function forceClean(forceCleanModule: any): Promise { 10 | try { 11 | const app = await NestFactory.create(forceCleanModule); 12 | await app.init(); 13 | const forceCleanService = app.get(ForceCleanService); 14 | await forceCleanService.forceClean(); 15 | } catch (e: any) { 16 | logger.error(e, 'Force-clean failed to execute'); 17 | process.exit(1); 18 | } 19 | 20 | process.exit(0); 21 | } 22 | -------------------------------------------------------------------------------- /packages/node-core/src/subcommands/index.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2020-2024 SubQuery Pte Ltd authors & contributors 2 | // SPDX-License-Identifier: GPL-3.0 3 | 4 | export * from './forceClean.service'; 5 | export * from './forceClean.module'; 6 | export * from './foreceClean.init'; 7 | export * from './reindex.init'; 8 | export * from './reindex.service'; 9 | -------------------------------------------------------------------------------- /packages/node-core/src/subcommands/reindex.init.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2020-2024 SubQuery Pte Ltd authors & contributors 2 | // SPDX-License-Identifier: GPL-3.0 3 | 4 | import {NestFactory} from '@nestjs/core'; 5 | import {getLogger} from '../logger'; 6 | import {ReindexService} from './reindex.service'; 7 | 8 | const logger = getLogger('CLI-Reindex'); 9 | export async function reindexInit(reindexModule: any, targetHeight: number): Promise { 10 | try { 11 | const app = await NestFactory.create(reindexModule); 12 | 13 | await app.init(); 14 | const reindexService = app.get(ReindexService); 15 | 16 | await reindexService.init(); 17 | const actualReindexHeight = await reindexService.getTargetHeightWithUnfinalizedBlocks(targetHeight); 18 | if (actualReindexHeight !== targetHeight) { 19 | logger.info( 20 | `Found index target height ${targetHeight} beyond indexed unfinalized block ${actualReindexHeight}, will index to ${actualReindexHeight}` 21 | ); 22 | } 23 | await reindexService.reindex(actualReindexHeight); 24 | } catch (e: any) { 25 | logger.error(e, 'Reindex failed to execute'); 26 | process.exit(1); 27 | } 28 | process.exit(0); 29 | } 30 | -------------------------------------------------------------------------------- /packages/node-core/src/utils/bigint.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2020-2024 SubQuery Pte Ltd authors & contributors 2 | // SPDX-License-Identifier: GPL-3.0 3 | 4 | interface BigInt { 5 | toJSON(): string; 6 | } 7 | 8 | // Make BigInt json serializable, note this doesn't go from string -> BigInt when parsing 9 | BigInt.prototype.toJSON = function () { 10 | return `${this.toString()}n`; 11 | }; 12 | -------------------------------------------------------------------------------- /packages/node-core/src/utils/blockHeightMap.spec.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2020-2024 SubQuery Pte Ltd authors & contributors 2 | // SPDX-License-Identifier: GPL-3.0 3 | 4 | import {BlockHeightMap} from './blockHeightMap'; 5 | 6 | describe('Ensure correct logic on blockHeightMap', () => { 7 | it('getWithinRange should return projects within specified height range', () => { 8 | const blockHeightMap = new Map([ 9 | [1, {projectName: 'Project A'}], 10 | [500, {projectName: 'Project B'}], 11 | [1000, {projectName: 'Project C'}], 12 | ]); 13 | 14 | const blockHeight = new BlockHeightMap(blockHeightMap as any); 15 | 16 | const projectsWithinRange = blockHeight.getWithinRange(499, 700); 17 | 18 | console.log(projectsWithinRange); 19 | expect(projectsWithinRange).toStrictEqual( 20 | new Map([ 21 | [1, {projectName: 'Project A'}], 22 | [500, {projectName: 'Project B'}], 23 | ]) 24 | ); 25 | }); 26 | }); 27 | -------------------------------------------------------------------------------- /packages/node-core/src/utils/blockSizeBuffer.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2020-2024 SubQuery Pte Ltd authors & contributors 2 | // SPDX-License-Identifier: GPL-3.0 3 | 4 | import {Queue} from './autoQueue'; 5 | 6 | export class BlockSizeBuffer extends Queue { 7 | constructor(capacity: number) { 8 | super(capacity); 9 | } 10 | 11 | average(): number { 12 | if (this.size === 0) { 13 | throw new Error('No block sizes to average'); 14 | } 15 | 16 | let sum = 0; 17 | for (let i = 0; i < this.size; i++) { 18 | sum += this.items[i]; 19 | } 20 | 21 | if (!this.capacity) { 22 | throw new Error('Capacity is expected to be defined for block size buffer'); 23 | } 24 | return Math.floor(sum / this.capacity); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /packages/node-core/src/utils/configure.spec.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2020-2024 SubQuery Pte Ltd authors & contributors 2 | // SPDX-License-Identifier: GPL-3.0 3 | 4 | import path from 'path'; 5 | import {ReaderFactory} from '@subql/common'; 6 | import {rebaseArgsWithManifest} from '../utils/configure'; 7 | 8 | jest.setTimeout(30000); 9 | 10 | describe('configure utils', () => { 11 | it('could rebase node args with manifest file', async () => { 12 | const mockArgv = { 13 | ipfs: '', 14 | unsafe: false, 15 | batchSize: 500, 16 | } as any; 17 | 18 | const manifestPath = path.join(__dirname, '../../test/v1.0.0/projectOptions.yaml'); 19 | const reader = await ReaderFactory.create(manifestPath); 20 | const rawManifest = await reader.getProjectSchema(); 21 | 22 | rebaseArgsWithManifest(mockArgv, rawManifest); 23 | 24 | // Fill the missing args, in manifest runner historical is enabled 25 | expect(mockArgv.disableHistorical).toBeFalsy(); 26 | // Keep the original value from argv 27 | expect(mockArgv.batchSize).toBe(500); 28 | // Args could override manifest options 29 | expect(mockArgv.unsafe).toBeFalsy(); 30 | }); 31 | }); 32 | -------------------------------------------------------------------------------- /packages/node-core/src/utils/decorators.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2020-2024 SubQuery Pte Ltd authors & contributors 2 | // SPDX-License-Identifier: GPL-3.0 3 | 4 | import {isMainThread} from 'worker_threads'; 5 | import {getLogger} from '../logger'; 6 | 7 | const logger = getLogger('main'); 8 | export function mainThreadOnly(): MethodDecorator { 9 | return (target, name: string | symbol, descriptor: PropertyDescriptor): void => { 10 | if (!!descriptor && typeof descriptor.value === 'function') { 11 | const orig = descriptor.value; 12 | // tslint:disable no-function-expression no-invalid-this 13 | descriptor.value = function (...args: any[]): any { 14 | if (!isMainThread) { 15 | logger.warn(`${name?.toString()} should only run in main thread`); 16 | } 17 | return orig.bind(this)(...args); 18 | }; 19 | } 20 | }; 21 | } 22 | -------------------------------------------------------------------------------- /packages/node-core/src/utils/fetchHelper.spec.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2020-2024 SubQuery Pte Ltd authors & contributors 2 | // SPDX-License-Identifier: GPL-3.0 3 | 4 | import {retryOnFailAxios} from './fetchHelpers'; 5 | 6 | jest.setTimeout(30000); 7 | 8 | describe('fetchHelpers', () => { 9 | it('retryOnFail', async () => { 10 | const axiosError = new Error(); 11 | (axiosError as any).response = {status: 429}; 12 | 13 | const mockAxiosRequest = jest.fn().mockImplementation(() => { 14 | throw axiosError; 15 | }); 16 | 17 | const mockNotAxiosRequest = jest.fn().mockImplementation(() => { 18 | throw new Error('Oh no it failed'); 19 | }); 20 | // If not Axios error, should only be called once 21 | await expect(retryOnFailAxios(mockNotAxiosRequest, [429])).rejects.toThrow(); 22 | expect(mockNotAxiosRequest).toHaveBeenCalledTimes(1); 23 | 24 | //If Axios error, should retry 5 times before throwing 25 | await expect(retryOnFailAxios(mockAxiosRequest, [429])).rejects.toThrow(); 26 | expect(mockAxiosRequest).toHaveBeenCalledTimes(5); 27 | }); 28 | }); 29 | -------------------------------------------------------------------------------- /packages/node-core/src/utils/fetchHelpers.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2020-2024 SubQuery Pte Ltd authors & contributors 2 | // SPDX-License-Identifier: GPL-3.0 3 | 4 | import {getLogger} from '../logger'; 5 | import {delay} from './promise'; 6 | 7 | const logger = getLogger('fetch'); 8 | 9 | const RETRY_COUNT = 5; 10 | const RETRY_DELAY = 2; 11 | 12 | export async function retryOnFail( 13 | request: () => Promise, 14 | shouldRetry: (error: any) => boolean, 15 | retries = RETRY_COUNT 16 | ): Promise { 17 | try { 18 | return await request(); 19 | } catch (e) { 20 | if (!shouldRetry(e)) throw e; 21 | if (retries > 1) { 22 | await delay(RETRY_DELAY); 23 | return retryOnFail(request, shouldRetry, --retries); 24 | } else { 25 | logger.error(e as Error, `Retries failed after ${RETRY_COUNT}`); 26 | throw e; 27 | } 28 | } 29 | } 30 | 31 | // When dealing with Axios errors use shouldRetry 32 | export async function retryOnFailAxios(request: () => Promise, statusCodes: number[]): Promise { 33 | return retryOnFail(request, (e) => !!statusCodes.find((t) => t === e?.response?.status)); 34 | } 35 | -------------------------------------------------------------------------------- /packages/node-core/src/utils/index.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2020-2024 SubQuery Pte Ltd authors & contributors 2 | // SPDX-License-Identifier: GPL-3.0 3 | 4 | export * from './object'; 5 | export * from './promise'; 6 | export * from './graphql'; 7 | export * from './batch-size'; 8 | export * from './autoQueue'; 9 | export * from './project'; 10 | export * from './fetchHelpers'; 11 | export * from './blockSizeBuffer'; 12 | export * from './configure'; 13 | export * from './reindex'; 14 | export * from './decorators'; 15 | export * from './blocks'; 16 | export * from './blockHeightMap'; 17 | -------------------------------------------------------------------------------- /packages/node-core/src/utils/object.spec.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2020-2024 SubQuery Pte Ltd authors & contributors 2 | // SPDX-License-Identifier: GPL-3.0 3 | 4 | import {camelCaseObjectKey} from './object'; 5 | 6 | it('Convert objects key to camelCase', () => { 7 | const object = { 8 | entity: 'someEntity', 9 | active_for_auction: 'someAuction', 10 | }; 11 | 12 | const result = camelCaseObjectKey(object); 13 | 14 | expect(result).toEqual({ 15 | entity: 'someEntity', 16 | activeForAuction: 'someAuction', 17 | }); 18 | }); 19 | -------------------------------------------------------------------------------- /packages/node-core/test/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "subquery": "../../../../subql-example/extrinsics", 3 | "subqueryName": "extrinsics" 4 | } 5 | -------------------------------------------------------------------------------- /packages/node-core/test/config.toml: -------------------------------------------------------------------------------- 1 | { 2 | "subquery": "../../../../subql-example/extrinsics", 3 | "subqueryName": "extrinsics" 4 | } 5 | -------------------------------------------------------------------------------- /packages/node-core/test/config.yml: -------------------------------------------------------------------------------- 1 | subquery: ../../../../subql-example/extrinsics 2 | subqueryName: extrinsics 3 | -------------------------------------------------------------------------------- /packages/node-core/test/migration-schemas/test_14_1.graphql: -------------------------------------------------------------------------------- 1 | type Transfer @entity { 2 | id: ID! 3 | amount: BigInt! 4 | blockNumber: Int! 5 | date: Date! 6 | from: Account! 7 | to: Account! 8 | } 9 | 10 | type Account @entity { 11 | id: ID! 12 | publicKey: String! 13 | firstTransferBlock: Int 14 | lastTransferBlock: Int 15 | sentTransfers: [Transfer] @derivedFrom(field: "from") # These are virtual properties to help us navigate to the correct foreign key of Transfer 16 | recievedTransfers: [Transfer] @derivedFrom(field: "to") # These are virtual properties to help us navigate to the correct foreign key of Transfer 17 | } 18 | -------------------------------------------------------------------------------- /packages/node-core/test/migration-schemas/test_14_1000.graphql: -------------------------------------------------------------------------------- 1 | type Transfer @entity { 2 | id: ID! 3 | amount: BigInt! 4 | blockNumber: Int! 5 | date: Date! 6 | # from: Account! 7 | # to: Account! 8 | } 9 | -------------------------------------------------------------------------------- /packages/node-core/test/sandbox/atob-test.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | // SPDX-License-Identifier: GPL-3.0 3 | Object.defineProperty(exports, '__esModule', {value: true}); 4 | exports.testSandbox = void 0; 5 | async function testSandbox() { 6 | try { 7 | const base64String = 'SGVsbG8sIFdvcmxkIQ=='; 8 | console.log(atob(base64String)); //expect to be `Hello, World!` 9 | } catch (e) { 10 | throw new Error(`atob in sandbox failed, ${e}`); 11 | } 12 | } 13 | exports.testSandbox = testSandbox; 14 | //# sourceMappingURL=atob-test.js.map 15 | -------------------------------------------------------------------------------- /packages/node-core/test/sandbox/atob-test.ts: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0 2 | 3 | export async function testSandbox(): Promise { 4 | try { 5 | const base64String = 'SGVsbG8sIFdvcmxkIQ=='; 6 | console.log(atob(base64String)); //expect to be `Hello, World!` 7 | } catch (e) { 8 | throw new Error(`atob in sandbox failed, ${e}`); 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /packages/node-core/test/sandbox/buffer-test.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2020-2024 SubQuery Pte Ltd authors & contributors 2 | // SPDX-License-Identifier: GPL-3.0 3 | 4 | export async function testSandbox(): Promise { 5 | const str = 'Hello, Buffer!'; 6 | const strBuffer = Buffer.from(str); 7 | const uin8Array = new Uint8Array(2); 8 | uin8Array[0] = 72; //'H' 9 | uin8Array[1] = 101; //'e' 10 | try { 11 | const output = Buffer.concat([strBuffer, uin8Array]); 12 | console.log(output.toString()); //expect to be `Hello, Buffer!He` 13 | } catch (e) { 14 | throw new Error(`Buffer concat failed, ${e}`); 15 | } 16 | } 17 | 18 | export async function testUin8Array(): Promise { 19 | const uin8Array = new Uint8Array(2); 20 | const uin8Array2 = new Uint8Array(2); 21 | uin8Array[0] = 72; //'H' 22 | uin8Array[1] = 101; //'e' 23 | uin8Array2[0] = 72; 24 | uin8Array2[1] = 101; 25 | try { 26 | const output = Buffer.concat([uin8Array, uin8Array2]); 27 | console.log(output.toString()); //expect to be `HeHe` 28 | } catch (e) { 29 | throw new Error(`Uin8Array concat failed, ${e}`); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /packages/node-core/test/sandbox/main.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | // Copyright 2020-2024 SubQuery Pte Ltd authors & contributors 3 | // SPDX-License-Identifier: GPL-3.0 4 | Object.defineProperty(exports, '__esModule', {value: true}); 5 | exports.testSandbox = void 0; 6 | async function testSandbox() { 7 | await new Promise((resolve) => setTimeout(resolve, 3000)); 8 | console.log('OK'); 9 | } 10 | exports.testSandbox = testSandbox; 11 | -------------------------------------------------------------------------------- /packages/node-core/test/sandbox/main.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2020-2024 SubQuery Pte Ltd authors & contributors 2 | // SPDX-License-Identifier: GPL-3.0 3 | 4 | export async function testSandbox(): Promise { 5 | await new Promise((resolve) => setTimeout(resolve, 3000)); 6 | console.log('OK'); 7 | } 8 | -------------------------------------------------------------------------------- /packages/node-core/test/sandbox/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "sandbox", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "main.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "author": "", 10 | "license": "ISC" 11 | } 12 | -------------------------------------------------------------------------------- /packages/node-core/test/sandbox/schema.graphql: -------------------------------------------------------------------------------- 1 | type StarterEntity @entity { 2 | id: ID! #id is a required field 3 | field1: Int! 4 | 5 | field2: String #filed2 is an optional field 6 | field3: BigInt 7 | 8 | field4: Date 9 | 10 | field5: Boolean 11 | } 12 | -------------------------------------------------------------------------------- /packages/node-core/test/sandbox/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "module": "commonjs", 4 | "target": "es2017", 5 | "noImplicitAny": false, 6 | "moduleResolution": "node", 7 | "baseUrl": ".", 8 | "types": ["node", "jest"], 9 | "experimentalDecorators": true, 10 | "esModuleInterop": true, 11 | "allowSyntheticDefaultImports": true, 12 | "lib": ["ES2017"], 13 | "emitDecoratorMetadata": true, 14 | "sourceMap": false, 15 | "rootDir": ".", 16 | "outDir": "." 17 | }, 18 | "exclude": [], 19 | "include": ["./main.ts", "./project.ts"] 20 | } 21 | -------------------------------------------------------------------------------- /packages/node-core/test/schemas/badschema-2.graphql: -------------------------------------------------------------------------------- 1 | type EntityOne @entity { 2 | id: ID! #id is a required field 3 | field1: Int! 4 | field2: Int! # no nullability changes, but dataType change 5 | } 6 | 7 | type EntityTwo @entity { 8 | id: ID! 9 | field1: Int! 10 | field2: String 11 | field3: BigInt 12 | field5: FieldTypeOld! 13 | } 14 | 15 | enum FieldTypeOld { 16 | VALUE1 17 | VALUE2 18 | } 19 | 20 | enum FieldTypeMod { 21 | VALUE1 22 | VALUE2 23 | } 24 | -------------------------------------------------------------------------------- /packages/node-core/test/schemas/newSchema.graphql: -------------------------------------------------------------------------------- 1 | type EntityOne @entity { 2 | id: ID! 3 | field1: Int! @index(unique: true) # added @index unique 4 | field2: String! 5 | field3: EntityTwo! # Updated from BigInt to EntityTwo ID 6 | } 7 | 8 | type EntityTwo @entity @compositeIndexes(fields: [["field2", "field3"]]) { 9 | id: ID! 10 | # field1: Int! # Dropped field1 11 | field2: FieldTypeMod # Updated from nullable to non-nullable 12 | field3: Int # Updated from BigInt to Int 13 | field4: EntityFour! # Added new field 14 | } 15 | 16 | # Dropped Entity Three 17 | # Drop index on ID 18 | #type EntityThree @entity { 19 | # id: ID! 20 | # field1: Int! 21 | # field2: String 22 | # field3: BigInt 23 | #} 24 | type NewJsonOne @jsonField { 25 | one: String! 26 | two: Int! 27 | } 28 | 29 | type NewJsonTwo @jsonField { 30 | one: String! 31 | two: NewJsonOne # Nested Json 32 | } 33 | 34 | enum FieldTypeNew { 35 | VALUE1 36 | VALUE2 37 | } 38 | 39 | enum FieldTypeMod { 40 | VALUE1 41 | VALUE2 42 | VALUE3 43 | } 44 | 45 | type EntityFour @entity { 46 | id: ID! 47 | field1: FieldTypeNew! 48 | field2: [NewJsonTwo] 49 | field3: [EntityTwo] @derivedFrom(field: "field4") 50 | } 51 | -------------------------------------------------------------------------------- /packages/node-core/test/schemas/oldSchema.graphql: -------------------------------------------------------------------------------- 1 | type EntityOne @entity { 2 | id: ID! #id is a required field 3 | field1: Int! 4 | field2: String! 5 | field3: EntityThree! 6 | } 7 | 8 | type EntityTwo @entity { 9 | id: ID! #id is a required field 10 | field1: Int! 11 | field2: String #filed2 is an optional field 12 | field3: BigInt 13 | field5: FieldTypeOld! 14 | } 15 | 16 | type ExampleJsonOne @jsonField { 17 | one: String! 18 | two: Int! 19 | } 20 | 21 | type ExampleJsonTwo @jsonField { 22 | one: String! 23 | two: ExampleJsonOne! # Nested Json 24 | } 25 | 26 | type EntityThree @entity { 27 | id: ID! #id is a required field 28 | field1: [ExampleJsonTwo] 29 | } 30 | 31 | enum FieldTypeOld { 32 | VALUE1 33 | VALUE2 34 | } 35 | 36 | enum FieldTypeMod { 37 | VALUE1 38 | VALUE2 39 | } 40 | -------------------------------------------------------------------------------- /packages/node-core/test/v1.0.0/distMock/chaintypes.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | exports.default = {typesBundle: {}}; 4 | -------------------------------------------------------------------------------- /packages/node-core/test/v1.0.0/distMock/index.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | Object.defineProperty(exports, '__esModule', {value: true}); 3 | const tslib_1 = require('tslib'); 4 | //Exports all handler functions 5 | require('@polkadot/api-augment'); 6 | (0, tslib_1.__exportStar)(require('./mappings/mappingHandlers'), exports); 7 | -------------------------------------------------------------------------------- /packages/node-core/test/v1.0.0/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "subquery-starter", 3 | "version": "0.0.4", 4 | "description": "This project can be use as a starting point for developing your SubQuery project", 5 | "main": "dist/index.js", 6 | "scripts": { 7 | "build": "tsc -b", 8 | "prepack": "rm -rf dist && npm build", 9 | "test": "jest", 10 | "codegen": "./node_modules/.bin/subql codegen" 11 | }, 12 | "homepage": "https://github.com/subquery/subql-starter", 13 | "repository": "github:subquery/subql-starter", 14 | "files": [ 15 | "dist", 16 | "schema.graphql", 17 | "project.yaml" 18 | ], 19 | "author": "Ian He & Jay Ji", 20 | "license": "Apache-2.0", 21 | "devDependencies": { 22 | "@polkadot/api": "11.0.2", 23 | "@subql/types": "latest", 24 | "typescript": "^4.9.5", 25 | "@subql/cli": "latest" 26 | }, 27 | "resolutions": { 28 | "ipfs-unixfs": "6.0.6" 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /packages/node-core/test/v1.0.0/schema.graphql: -------------------------------------------------------------------------------- 1 | type StarterEntity @entity { 2 | id: ID! #id is a required field 3 | field1: Int! 4 | 5 | field2: String #filed2 is an optional field 6 | field3: BigInt 7 | 8 | field4: Date 9 | 10 | field5: Boolean 11 | } 12 | -------------------------------------------------------------------------------- /packages/node-core/test/v1.0.0/types.yaml: -------------------------------------------------------------------------------- 1 | types: 2 | TestType: u32 3 | typesAlias: 4 | Alias: 5 | TestType2: test 6 | typesBundle: 7 | spec: 8 | '2312': 9 | types: 10 | - minmax: 11 | - 232 12 | - 122 13 | types: 14 | TestType3: test3 15 | chain: 16 | mockchain: 17 | types: 18 | - minmax: 19 | - 232 20 | - 122 21 | types: 22 | TestType4: test4 23 | typesChain: 24 | chain2: 25 | TestType5: test 26 | typesSpec: 27 | spec3: 28 | TestType6: test 29 | -------------------------------------------------------------------------------- /packages/node-core/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.json", 3 | "compilerOptions": { 4 | "tsBuildInfoFile": "dist/.tsbuildinfo", 5 | "rootDir": "src", 6 | "outDir": "dist", 7 | "noImplicitAny": true, 8 | "esModuleInterop": true, 9 | "importHelpers": true, 10 | "strict": true 11 | }, 12 | "references": [{"path": "../common"}, {"path": "../utils"}, {"path": "../testing"}], 13 | "include": ["src/**/*"] 14 | } 15 | -------------------------------------------------------------------------------- /packages/node-core/yargs.js: -------------------------------------------------------------------------------- 1 | // Copyright 2020-2024 SubQuery Pte Ltd authors & contributors 2 | // SPDX-License-Identifier: GPL-3.0 3 | 4 | // A standalone entrypoint for logger so we can import `@subql/node-core/logger` 5 | const yargs = require('./dist/yargs'); 6 | 7 | module.exports = yargs; 8 | -------------------------------------------------------------------------------- /packages/node/.gitignore: -------------------------------------------------------------------------------- 1 | # compiled output 2 | /dist 3 | /node_modules 4 | 5 | # Logs 6 | logs 7 | *.log 8 | npm-debug.log* 9 | yarn-debug.log* 10 | yarn-error.log* 11 | lerna-debug.log* 12 | 13 | # OS 14 | .DS_Store 15 | 16 | # Tests 17 | /coverage 18 | /.nyc_output 19 | 20 | # IDEs and editors 21 | /.idea 22 | .project 23 | .classpath 24 | .c9/ 25 | *.launch 26 | .settings/ 27 | *.sublime-workspace 28 | 29 | # IDE - VSCode 30 | .vscode/* 31 | !.vscode/settings.json 32 | !.vscode/tasks.json 33 | !.vscode/launch.json 34 | !.vscode/extensions.json -------------------------------------------------------------------------------- /packages/node/.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "singleQuote": true, 3 | "trailingComma": "all" 4 | } 5 | -------------------------------------------------------------------------------- /packages/node/.trigger: -------------------------------------------------------------------------------- 1 | 0.8.1 2 | -------------------------------------------------------------------------------- /packages/node/Dockerfile: -------------------------------------------------------------------------------- 1 | # Build stage 2 | FROM node:18-alpine as builder 3 | 4 | # Set working directory 5 | WORKDIR /app 6 | 7 | # Copy all packages 8 | COPY ./packages ./packages 9 | 10 | # Copy tsconfig.json 11 | COPY ./tsconfig.json ./tsconfig.json 12 | 13 | # Copy build script 14 | COPY ./scripts/build.sh ./scripts/build.sh 15 | 16 | # Install dependencies and build 17 | RUN ./scripts/build.sh packages/node 18 | 19 | # Production stage 20 | FROM node:18-alpine 21 | 22 | # Copy .tgz file from builder 23 | COPY --from=builder /app/packages/node/app.tgz /app.tgz 24 | 25 | # Install production dependencies 26 | RUN apk add --no-cache tini curl git && \ 27 | tar -xzvf /app.tgz --strip 1 && \ 28 | rm /app.tgz && \ 29 | yarn install --production && \ 30 | yarn cache clean && \ 31 | rm -rf /root/.npm /root/.cache 32 | 33 | # Make the user not ROOT 34 | USER 1000 35 | 36 | # Set Entry point and command 37 | ENTRYPOINT ["/sbin/tini", "--", "/bin/run"] 38 | CMD ["-f","/app"] 39 | -------------------------------------------------------------------------------- /packages/node/bin/run: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | 3 | require('../dist/main.js') 4 | 5 | -------------------------------------------------------------------------------- /packages/node/bin/run.cmd: -------------------------------------------------------------------------------- 1 | @echo off 2 | 3 | node "%~dp0\run" %* 4 | -------------------------------------------------------------------------------- /packages/node/docker/cockroach-db/docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: '3.5' 2 | 3 | services: 4 | crdb: 5 | image: cockroachdb/cockroach:latest-v22.1 6 | ports: 7 | - '26257:26257' 8 | - '8080:8080' 9 | command: start-single-node --insecure 10 | volumes: 11 | - '${PWD}/cockroach-data/crdb:/cockroach/cockroach-data' 12 | -------------------------------------------------------------------------------- /packages/node/docker/docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: '3' 2 | 3 | services: 4 | postgres: 5 | build: 6 | context: . 7 | dockerfile: pg-Dockerfile 8 | ports: 9 | - 5432:5432 10 | volumes: 11 | - .data/postgres:/var/lib/postgresql/data 12 | environment: 13 | POSTGRES_PASSWORD: postgres 14 | -------------------------------------------------------------------------------- /packages/node/docker/load-extensions.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | psql -v ON_ERROR_STOP=1 --username "$POSTGRES_USER" < { 11 | /** 12 | * This is a wrapper around the core NodeConfig to get additional properties that are provided through args or node runner options 13 | * NOTE: This isn't injected anywhere so you need to wrap the injected node config 14 | * 15 | * @example 16 | * constructor( 17 | * nodeConfig: NodeConfig, 18 | * ) { 19 | * this.nodeConfig = new SubstrateNodeConfig(nodeConfig); 20 | * } 21 | * */ 22 | constructor(config: NodeConfig) { 23 | // Rebuild with internal config 24 | super((config as any)._config, (config as any)._isTest); 25 | } 26 | 27 | get skipTransactions(): boolean { 28 | return !!this._config.skipTransactions; 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /packages/node/src/indexer/blockDispatcher/index.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2020-2024 SubQuery Pte Ltd authors & contributors 2 | // SPDX-License-Identifier: GPL-3.0 3 | 4 | import { BlockDispatcherService } from './block-dispatcher.service'; 5 | import { WorkerBlockDispatcherService } from './worker-block-dispatcher.service'; 6 | 7 | export { BlockDispatcherService, WorkerBlockDispatcherService }; 8 | -------------------------------------------------------------------------------- /packages/node/src/indexer/blockDispatcher/substrate-block-dispatcher.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2020-2024 SubQuery Pte Ltd authors & contributors 2 | // SPDX-License-Identifier: GPL-3.0 3 | 4 | import { IBlockDispatcher } from '@subql/node-core'; 5 | import { SubstrateBlock } from '@subql/types'; 6 | import { RuntimeService } from '../runtime/runtimeService'; 7 | 8 | export interface ISubstrateBlockDispatcher 9 | extends IBlockDispatcher { 10 | init( 11 | onDynamicDsCreated: (height: number) => Promise, 12 | runtimeService?: RuntimeService, 13 | ): Promise; 14 | } 15 | -------------------------------------------------------------------------------- /packages/node/src/indexer/dictionary/index.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2020-2024 SubQuery Pte Ltd authors & contributors 2 | // SPDX-License-Identifier: GPL-3.0 3 | 4 | export * from './types'; 5 | export * from './substrateDictionary.service'; 6 | -------------------------------------------------------------------------------- /packages/node/src/indexer/dictionary/types.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2020-2024 SubQuery Pte Ltd authors & contributors 2 | // SPDX-License-Identifier: GPL-3.0 3 | 4 | import { MetaData } from '@subql/utils'; 5 | 6 | export type SpecVersion = { 7 | id: string; 8 | start: number; //start with this block 9 | end: number; 10 | }; 11 | 12 | export type SpecVersionDictionary = { 13 | _metadata: MetaData; 14 | specVersions: SpecVersion[]; 15 | }; 16 | -------------------------------------------------------------------------------- /packages/node/src/indexer/dictionary/v1/index.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2020-2024 SubQuery Pte Ltd authors & contributors 2 | // SPDX-License-Identifier: GPL-3.0 3 | 4 | export * from './substrateDictionaryV1'; 5 | -------------------------------------------------------------------------------- /packages/node/src/indexer/dictionary/v2/index.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2020-2024 SubQuery Pte Ltd authors & contributors 2 | // SPDX-License-Identifier: GPL-3.0 3 | 4 | export * from './substrateDictionaryV2'; 5 | export * from './types'; 6 | -------------------------------------------------------------------------------- /packages/node/src/indexer/dictionary/v2/types.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2020-2024 SubQuery Pte Ltd authors & contributors 2 | // SPDX-License-Identifier: GPL-3.0 3 | 4 | import { DictionaryV2QueryEntry } from '@subql/node-core'; 5 | 6 | /** 7 | * Substrate Fat dictionary RPC request filter conditions 8 | */ 9 | export type SubstrateDictionaryV2QueryEntry = DictionaryV2QueryEntry; 10 | -------------------------------------------------------------------------------- /packages/node/src/indexer/ds-processor.service.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2020-2024 SubQuery Pte Ltd authors & contributors 2 | // SPDX-License-Identifier: GPL-3.0 3 | 4 | import { Injectable } from '@nestjs/common'; 5 | import { isCustomDs } from '@subql/common-substrate'; 6 | import { BaseDsProcessorService } from '@subql/node-core'; 7 | import { 8 | SubstrateCustomDatasource, 9 | SubstrateCustomHandler, 10 | SubstrateDatasource, 11 | SubstrateDatasourceProcessor, 12 | SubstrateMapping, 13 | } from '@subql/types'; 14 | 15 | @Injectable() 16 | export class DsProcessorService extends BaseDsProcessorService< 17 | SubstrateDatasource, 18 | SubstrateCustomDatasource>, 19 | SubstrateDatasourceProcessor> 20 | > { 21 | protected isCustomDs = isCustomDs; 22 | } 23 | -------------------------------------------------------------------------------- /packages/node/src/indexer/types.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2020-2024 SubQuery Pte Ltd authors & contributors 2 | // SPDX-License-Identifier: GPL-3.0 3 | 4 | import { ApiPromise } from '@polkadot/api'; 5 | import { ApiDecoration } from '@polkadot/api/types'; 6 | import type { HexString } from '@polkadot/util/types'; 7 | import { 8 | BlockHeader, 9 | LightSubstrateEvent, 10 | SubstrateBlock, 11 | SubstrateEvent, 12 | SubstrateExtrinsic, 13 | } from '@subql/types'; 14 | 15 | export interface BlockContent { 16 | block: SubstrateBlock; 17 | extrinsics: SubstrateExtrinsic[]; 18 | events: SubstrateEvent[]; 19 | } 20 | 21 | export interface LightBlockContent { 22 | block: BlockHeader; // A subset of SubstrateBlock 23 | events: LightSubstrateEvent[]; 24 | } 25 | 26 | export type BestBlocks = Record; 27 | 28 | export type ApiAt = ApiDecoration<'promise'> & { rpc: ApiPromise['rpc'] }; 29 | 30 | export function isFullBlock( 31 | block: BlockContent | LightBlockContent, 32 | ): block is BlockContent { 33 | return (block as BlockContent).extrinsics !== undefined; 34 | } 35 | -------------------------------------------------------------------------------- /packages/node/src/indexer/worker/worker.module.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2020-2024 SubQuery Pte Ltd authors & contributors 2 | // SPDX-License-Identifier: GPL-3.0 3 | 4 | import { Module } from '@nestjs/common'; 5 | import { EventEmitterModule } from '@nestjs/event-emitter'; 6 | import { ScheduleModule } from '@nestjs/schedule'; 7 | import { ConfigureModule } from '../../configure/configure.module'; 8 | import { WorkerFetchModule } from './worker-fetch.module'; 9 | 10 | @Module({ 11 | imports: [ 12 | EventEmitterModule.forRoot(), 13 | ConfigureModule.register(), 14 | ScheduleModule.forRoot(), 15 | WorkerFetchModule, 16 | ], 17 | controllers: [], 18 | }) 19 | export class WorkerModule {} 20 | -------------------------------------------------------------------------------- /packages/node/src/main.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2020-2024 SubQuery Pte Ltd authors & contributors 2 | // SPDX-License-Identifier: GPL-3.0 3 | 4 | import { initLogger } from '@subql/node-core/logger'; 5 | import { yargsOptions } from './yargs'; 6 | 7 | const { argv } = yargsOptions; 8 | 9 | // initLogger is imported from true path, to make sure getLogger (or other logger values that relies on logger) isn't initialised 10 | initLogger( 11 | argv.debug, 12 | argv.outputFmt as 'json' | 'colored', 13 | argv.logLevel as string | undefined, 14 | ); 15 | 16 | const { setProfiler } = require('@subql/node-core'); 17 | setProfiler(argv.profiler); 18 | 19 | // Check for no subcommand 20 | if (!argv._[0]) { 21 | // Lazy import, to allow logger to be initialised before bootstrap() 22 | // As bootstrap runs services that requires logger 23 | const { bootstrap } = require('./init'); 24 | void bootstrap(); 25 | } 26 | -------------------------------------------------------------------------------- /packages/node/src/meta/meta.controller.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2020-2024 SubQuery Pte Ltd authors & contributors 2 | // SPDX-License-Identifier: GPL-3.0 3 | 4 | import { Controller, Get } from '@nestjs/common'; 5 | import { MetaService } from './meta.service'; 6 | 7 | @Controller('meta') 8 | export class MetaController { 9 | constructor(private metaService: MetaService) {} 10 | 11 | @Get() 12 | getMeta() { 13 | return this.metaService.getMeta(); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /packages/node/src/meta/meta.module.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2020-2024 SubQuery Pte Ltd authors & contributors 2 | // SPDX-License-Identifier: GPL-3.0 3 | 4 | import { Module } from '@nestjs/common'; 5 | import { metaServices, metaControllers } from '@subql/node-core'; 6 | import { PrometheusModule } from '@willsoto/nestjs-prometheus'; 7 | import { FetchModule } from '../indexer/fetch.module'; 8 | import { MetaController } from './meta.controller'; 9 | import { MetaService } from './meta.service'; 10 | 11 | @Module({ 12 | imports: [PrometheusModule.register(), FetchModule], 13 | controllers: [...metaControllers, MetaController], 14 | providers: [...metaServices, MetaService], 15 | }) 16 | export class MetaModule {} 17 | -------------------------------------------------------------------------------- /packages/node/src/meta/meta.service.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2020-2024 SubQuery Pte Ltd authors & contributors 2 | // SPDX-License-Identifier: GPL-3.0 3 | 4 | import { Injectable } from '@nestjs/common'; 5 | import { 6 | BaseMetaService, 7 | NodeConfig, 8 | StoreCacheService, 9 | } from '@subql/node-core'; 10 | 11 | // eslint-disable-next-line @typescript-eslint/no-var-requires 12 | const { version: polkadotSdkVersion } = require('@polkadot/api/package.json'); 13 | // eslint-disable-next-line @typescript-eslint/no-var-requires 14 | const { version: packageVersion } = require('../../package.json'); 15 | 16 | @Injectable() 17 | export class MetaService extends BaseMetaService { 18 | protected packageVersion = packageVersion; 19 | protected sdkVersion(): { name: string; version: string } { 20 | return { name: 'polkadotSdkVersion', version: polkadotSdkVersion }; 21 | } 22 | constructor(storeCacheService: StoreCacheService, config: NodeConfig) { 23 | super(storeCacheService, config); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /packages/node/src/subcommands/forceClean.init.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2020-2024 SubQuery Pte Ltd authors & contributors 2 | // SPDX-License-Identifier: GPL-3.0 3 | 4 | import { forceClean } from '@subql/node-core'; 5 | import { ForceCleanModule } from './forceClean.module'; 6 | 7 | export const forceCleanInit = (): Promise => forceClean(ForceCleanModule); 8 | -------------------------------------------------------------------------------- /packages/node/src/subcommands/forceClean.module.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2020-2024 SubQuery Pte Ltd authors & contributors 2 | // SPDX-License-Identifier: GPL-3.0 3 | 4 | import { Module } from '@nestjs/common'; 5 | import { DbModule, ForceCleanFeatureModule } from '@subql/node-core'; 6 | import { ConfigureModule } from '../configure/configure.module'; 7 | 8 | @Module({ 9 | imports: [ 10 | DbModule.forRoot(), 11 | ConfigureModule.register(), 12 | ForceCleanFeatureModule, 13 | ], 14 | controllers: [], 15 | }) 16 | export class ForceCleanModule {} 17 | -------------------------------------------------------------------------------- /packages/node/src/subcommands/reindex.init.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2020-2024 SubQuery Pte Ltd authors & contributors 2 | // SPDX-License-Identifier: GPL-3.0 3 | 4 | import { reindexInit as baseReindexInit } from '@subql/node-core'; 5 | import { ReindexModule } from './reindex.module'; 6 | 7 | export const reindexInit = (targetHeight: number) => 8 | baseReindexInit(ReindexModule, targetHeight); 9 | -------------------------------------------------------------------------------- /packages/node/src/subcommands/testing.init.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2020-2024 SubQuery Pte Ltd authors & contributors 2 | // SPDX-License-Identifier: GPL-3.0 3 | 4 | import { getLogger } from '@subql/node-core'; 5 | import { ConfigureModule } from '../configure/configure.module'; 6 | import { TestingService } from './testing.service'; 7 | 8 | const logger = getLogger('Testing'); 9 | export async function testingInit(): Promise { 10 | try { 11 | const { nodeConfig, project } = await ConfigureModule.getInstance(); 12 | 13 | const testingService = new TestingService(nodeConfig, project); 14 | await testingService.run(); 15 | } catch (e) { 16 | logger.error(e, 'Testing failed'); 17 | process.exit(1); 18 | } 19 | process.exit(0); 20 | } 21 | -------------------------------------------------------------------------------- /packages/node/src/yargs.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2020-2024 SubQuery Pte Ltd authors & contributors 2 | // SPDX-License-Identifier: GPL-3.0 3 | 4 | import { yargsBuilder } from '@subql/node-core/yargs'; 5 | 6 | export const yargsOptions = yargsBuilder({ 7 | initTesting: () => { 8 | // lazy import to make sure logger is instantiated before all other services 9 | // eslint-disable-next-line @typescript-eslint/no-var-requires 10 | const { testingInit } = require('./subcommands/testing.init'); 11 | return testingInit(); 12 | }, 13 | initForceClean: () => { 14 | // lazy import to make sure logger is instantiated before all other services 15 | // eslint-disable-next-line @typescript-eslint/no-var-requires 16 | const { forceCleanInit } = require('./subcommands/forceClean.init'); 17 | return forceCleanInit(); 18 | }, 19 | initReindex: (targetHeight: number) => { 20 | // lazy import to make sure logger is instantiated before all other services 21 | // eslint-disable-next-line @typescript-eslint/no-var-requires 22 | const { reindexInit } = require('./subcommands/reindex.init'); 23 | return reindexInit(targetHeight); 24 | }, 25 | }); 26 | -------------------------------------------------------------------------------- /packages/node/test/jest-e2e.json: -------------------------------------------------------------------------------- 1 | { 2 | "moduleFileExtensions": ["js", "json", "ts"], 3 | "rootDir": ".", 4 | "testEnvironment": "node", 5 | "testRegex": ".e2e-spec.ts$", 6 | "transform": { 7 | "^.+\\.(t|j)s$": "ts-jest" 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /packages/node/test/projectFixture/bad.json: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Zikc2023/subql/d164f848bfaa82aaa5f842a9a5a9a1b946fb97d3/packages/node/test/projectFixture/bad.json -------------------------------------------------------------------------------- /packages/node/test/projectFixture/template-v1.0.0/distMock/chaintypes.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | exports.default = { typesBundle: {} }; 4 | -------------------------------------------------------------------------------- /packages/node/test/projectFixture/template-v1.0.0/distMock/index.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | Object.defineProperty(exports, '__esModule', { value: true }); 3 | const tslib_1 = require('tslib'); 4 | //Exports all handler functions 5 | require('@polkadot/api-augment'); 6 | (0, tslib_1.__exportStar)(require('./mappings/mappingHandlers'), exports); 7 | -------------------------------------------------------------------------------- /packages/node/test/projectFixture/template-v1.0.0/js/test1/project.yaml: -------------------------------------------------------------------------------- 1 | # project.yaml 2 | specVersion: '0.2.0' 3 | 4 | name: '' 5 | version: '0.0.0' 6 | description: '' 7 | repository: 'https://github.com/subquery/subql-starter' 8 | 9 | schema: 10 | file: ./schema.graphql 11 | 12 | network: 13 | genesisHash: '0x' 14 | endpoint: 'wss://polkadot.api.onfinality.io/public-ws' 15 | chaintypes: 16 | file: ./types.js 17 | 18 | dataSources: 19 | - kind: substrate/Runtime 20 | startBlock: 1 21 | mapping: 22 | file: dist/index.js 23 | handlers: 24 | - handler: handleBlock 25 | kind: substrate/BlockHandler 26 | - handler: handleEvent 27 | kind: substrate/EventHandler 28 | filter: #Filter is optional 29 | module: balances 30 | method: Deposit 31 | - handler: handleCall 32 | kind: substrate/CallHandler 33 | -------------------------------------------------------------------------------- /packages/node/test/projectFixture/template-v1.0.0/js/test1/types.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const types = { 4 | types: { 5 | TestType: 'u32', 6 | }, 7 | typesAlias: { 8 | Alias: { 9 | TestType2: 'test', 10 | }, 11 | }, 12 | typesBundle: { 13 | spec: { 14 | 2312: { 15 | types: [ 16 | { 17 | minmax: [232, 122], 18 | types: { 19 | TestType3: 'test3', 20 | }, 21 | }, 22 | ], 23 | }, 24 | }, 25 | chain: { 26 | mockchain: { 27 | types: [ 28 | { 29 | minmax: [232, 122], 30 | types: { 31 | TestType4: 'test4', 32 | }, 33 | }, 34 | ], 35 | }, 36 | }, 37 | }, 38 | typesChain: { 39 | chain2: { 40 | TestType5: 'test', 41 | }, 42 | }, 43 | typesSpec: { 44 | spec3: { 45 | TestType6: 'test', 46 | }, 47 | }, 48 | }; 49 | 50 | Object.defineProperty(exports, '__esModule', { 51 | value: true, 52 | }); 53 | 54 | exports.default = types; 55 | -------------------------------------------------------------------------------- /packages/node/test/projectFixture/template-v1.0.0/js/test2/project.yaml: -------------------------------------------------------------------------------- 1 | # project.yaml 2 | specVersion: '0.2.0' 3 | 4 | name: '' 5 | version: '0.0.0' 6 | description: '' 7 | repository: 'https://github.com/subquery/subql-starter' 8 | 9 | schema: 10 | file: ./schema.graphql 11 | 12 | network: 13 | genesisHash: '0x' 14 | endpoint: 'wss://polkadot.api.onfinality.io/public-ws' 15 | chaintypes: 16 | file: ./types.js 17 | 18 | dataSources: 19 | - kind: substrate/Runtime 20 | startBlock: 1 21 | mapping: 22 | file: dist/index.js 23 | handlers: 24 | - handler: handleBlock 25 | kind: substrate/BlockHandler 26 | - handler: handleEvent 27 | kind: substrate/EventHandler 28 | filter: #Filter is optional 29 | module: balances 30 | method: Deposit 31 | - handler: handleCall 32 | kind: substrate/CallHandler 33 | -------------------------------------------------------------------------------- /packages/node/test/projectFixture/template-v1.0.0/js/test2/types.js: -------------------------------------------------------------------------------- 1 | const os = require('os'); 2 | 3 | console.log(os.platform); 4 | 5 | const types = { 6 | types: { 7 | TestType: 'u32', 8 | }, 9 | typesAlias: { 10 | Alias: { 11 | TestType2: 'test', 12 | }, 13 | }, 14 | typesBundle: { 15 | spec: { 16 | 2312: { 17 | types: [ 18 | { 19 | minmax: [232, 122], 20 | types: { 21 | TestType3: 'test3', 22 | }, 23 | }, 24 | ], 25 | }, 26 | }, 27 | chain: { 28 | mockchain: { 29 | types: [ 30 | { 31 | minmax: [232, 122], 32 | types: { 33 | TestType4: 'test4', 34 | }, 35 | }, 36 | ], 37 | }, 38 | }, 39 | }, 40 | typesChain: { 41 | chain2: { 42 | TestType5: 'test', 43 | }, 44 | }, 45 | typesSpec: { 46 | spec3: { 47 | TestType6: 'test', 48 | }, 49 | }, 50 | }; 51 | 52 | module.exports = types; 53 | -------------------------------------------------------------------------------- /packages/node/test/projectFixture/template-v1.0.0/js/test3/project.yaml: -------------------------------------------------------------------------------- 1 | # project.yaml 2 | specVersion: '0.2.0' 3 | 4 | name: '' 5 | version: '0.0.0' 6 | description: '' 7 | repository: 'https://github.com/subquery/subql-starter' 8 | 9 | schema: 10 | file: ./schema.graphql 11 | 12 | network: 13 | genesisHash: '0x' 14 | endpoint: 'wss://polkadot.api.onfinality.io/public-ws' 15 | chaintypes: 16 | file: ./types.js 17 | 18 | dataSources: 19 | - kind: substrate/Runtime 20 | startBlock: 1 21 | mapping: 22 | file: dist/index.js 23 | handlers: 24 | - handler: handleBlock 25 | kind: substrate/BlockHandler 26 | - handler: handleEvent 27 | kind: substrate/EventHandler 28 | filter: #Filter is optional 29 | module: balances 30 | method: Deposit 31 | - handler: handleCall 32 | kind: substrate/CallHandler 33 | -------------------------------------------------------------------------------- /packages/node/test/projectFixture/template-v1.0.0/js/test3/types.js: -------------------------------------------------------------------------------- 1 | const types = { 2 | types: { 3 | TestType: 'u32', 4 | }, 5 | typesAlias: { 6 | Alias: { 7 | TestType2: 'test', 8 | }, 9 | }, 10 | typesBundle: { 11 | spec: { 12 | 2312: { 13 | types: [ 14 | { 15 | minmax: [232, 122], 16 | types: { 17 | TestType3: 'test3', 18 | }, 19 | }, 20 | ], 21 | }, 22 | }, 23 | chain: { 24 | mockchain: { 25 | types: [ 26 | { 27 | minmax: [232, 122], 28 | types: { 29 | TestType4: 'test4', 30 | }, 31 | }, 32 | ], 33 | }, 34 | }, 35 | }, 36 | typesChain: { 37 | chain2: { 38 | TestType5: 'test', 39 | }, 40 | }, 41 | typesSpec: { 42 | spec3: { 43 | TestType6: 'test', 44 | }, 45 | }, 46 | }; 47 | 48 | module.exports.test = types; 49 | -------------------------------------------------------------------------------- /packages/node/test/projectFixture/template-v1.0.0/js/test4/project.yaml: -------------------------------------------------------------------------------- 1 | # project.yaml 2 | specVersion: '0.2.0' 3 | 4 | name: '' 5 | version: '0.0.0' 6 | description: '' 7 | repository: 'https://github.com/subquery/subql-starter' 8 | 9 | schema: 10 | file: ./schema.graphql 11 | 12 | network: 13 | genesisHash: '0x' 14 | endpoint: 'wss://polkadot.api.onfinality.io/public-ws' 15 | chaintypes: 16 | file: ./types.js 17 | 18 | dataSources: 19 | - kind: substrate/Runtime 20 | startBlock: 1 21 | mapping: 22 | file: dist/index.js 23 | handlers: 24 | - handler: handleBlock 25 | kind: substrate/BlockHandler 26 | - handler: handleEvent 27 | kind: substrate/EventHandler 28 | filter: #Filter is optional 29 | module: balances 30 | method: Deposit 31 | - handler: handleCall 32 | kind: substrate/CallHandler 33 | -------------------------------------------------------------------------------- /packages/node/test/projectFixture/template-v1.0.0/js/test4/types.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const types = { 4 | types: { 5 | TestType: 'u32', 6 | }, 7 | typesAlias: { 8 | Alias: { 9 | TestType2: 'test', 10 | }, 11 | }, 12 | typesBundle: { 13 | spec: { 14 | 2312: { 15 | types: [ 16 | { 17 | minmax: [232, 122], 18 | types: { 19 | TestType3: 'test3', 20 | }, 21 | }, 22 | ], 23 | }, 24 | }, 25 | chain: { 26 | mockchain: { 27 | types: [ 28 | { 29 | minmax: [232, 122], 30 | types: { 31 | TestType4: 'test4', 32 | }, 33 | }, 34 | ], 35 | }, 36 | }, 37 | }, 38 | typesChain: { 39 | chain2: { 40 | TestType5: 'test', 41 | }, 42 | }, 43 | typesSpec: { 44 | spec3: { 45 | TestType6: 'test', 46 | }, 47 | }, 48 | shouldIgnorefield: { 49 | chain2: { 50 | TestType5: 'test', 51 | }, 52 | }, 53 | }; 54 | 55 | Object.defineProperty(exports, '__esModule', { 56 | value: true, 57 | }); 58 | 59 | exports.default = types; 60 | -------------------------------------------------------------------------------- /packages/node/test/projectFixture/template-v1.0.0/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "subquery-starter", 3 | "version": "0.0.4", 4 | "description": "This project can be use as a starting point for developing your SubQuery project", 5 | "main": "dist/index.js", 6 | "scripts": { 7 | "build": "tsc -b", 8 | "prepack": "rm -rf dist && npm build", 9 | "test": "jest", 10 | "codegen": "./node_modules/.bin/subql codegen" 11 | }, 12 | "homepage": "https://github.com/subquery/subql-starter", 13 | "repository": "github:subquery/subql-starter", 14 | "files": [ 15 | "dist", 16 | "schema.graphql", 17 | "project.yaml" 18 | ], 19 | "author": "Ian He & Jay Ji", 20 | "license": "Apache-2.0", 21 | "devDependencies": { 22 | "@polkadot/api": "11.0.2", 23 | "@subql/types": "dev", 24 | "typescript": "^4.1.3", 25 | "@subql/cli": "dev" 26 | }, 27 | "resolutions": { 28 | "ipfs-unixfs": "6.0.6" 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /packages/node/test/projectFixture/template-v1.0.0/schema.graphql: -------------------------------------------------------------------------------- 1 | type StarterEntity @entity { 2 | id: ID! #id is a required field 3 | field1: Int! 4 | 5 | field2: String #filed2 is an optional field 6 | field3: BigInt 7 | 8 | field4: Date 9 | 10 | field5: Boolean 11 | } 12 | -------------------------------------------------------------------------------- /packages/node/test/projectFixture/template-v1.0.0/types.yaml: -------------------------------------------------------------------------------- 1 | types: 2 | TestType: u32 3 | typesAlias: 4 | Alias: 5 | TestType2: test 6 | typesBundle: 7 | spec: 8 | '2312': 9 | types: 10 | - minmax: 11 | - 232 12 | - 122 13 | types: 14 | TestType3: test3 15 | chain: 16 | mockchain: 17 | types: 18 | - minmax: 19 | - 232 20 | - 122 21 | types: 22 | TestType4: test4 23 | typesChain: 24 | chain2: 25 | TestType5: test 26 | typesSpec: 27 | spec3: 28 | TestType6: test 29 | -------------------------------------------------------------------------------- /packages/node/test/projectFixture/v1.0.0/distMock/chaintypes.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | exports.default = { typesBundle: {} }; 4 | -------------------------------------------------------------------------------- /packages/node/test/projectFixture/v1.0.0/distMock/index.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | Object.defineProperty(exports, '__esModule', { value: true }); 3 | const tslib_1 = require('tslib'); 4 | //Exports all handler functions 5 | require('@polkadot/api-augment'); 6 | (0, tslib_1.__exportStar)(require('./mappings/mappingHandlers'), exports); 7 | -------------------------------------------------------------------------------- /packages/node/test/projectFixture/v1.0.0/js/test1/project.yaml: -------------------------------------------------------------------------------- 1 | # project.yaml 2 | specVersion: '0.2.0' 3 | 4 | name: '' 5 | version: '0.0.0' 6 | description: '' 7 | repository: 'https://github.com/subquery/subql-starter' 8 | 9 | schema: 10 | file: ./schema.graphql 11 | 12 | network: 13 | genesisHash: '0x' 14 | endpoint: 'wss://polkadot.api.onfinality.io/public-ws' 15 | chaintypes: 16 | file: ./types.js 17 | 18 | dataSources: 19 | - kind: substrate/Runtime 20 | startBlock: 1 21 | mapping: 22 | file: dist/index.js 23 | handlers: 24 | - handler: handleBlock 25 | kind: substrate/BlockHandler 26 | - handler: handleEvent 27 | kind: substrate/EventHandler 28 | filter: #Filter is optional 29 | module: balances 30 | method: Deposit 31 | - handler: handleCall 32 | kind: substrate/CallHandler 33 | -------------------------------------------------------------------------------- /packages/node/test/projectFixture/v1.0.0/js/test1/types.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const types = { 4 | types: { 5 | TestType: 'u32', 6 | }, 7 | typesAlias: { 8 | Alias: { 9 | TestType2: 'test', 10 | }, 11 | }, 12 | typesBundle: { 13 | spec: { 14 | 2312: { 15 | types: [ 16 | { 17 | minmax: [232, 122], 18 | types: { 19 | TestType3: 'test3', 20 | }, 21 | }, 22 | ], 23 | }, 24 | }, 25 | chain: { 26 | mockchain: { 27 | types: [ 28 | { 29 | minmax: [232, 122], 30 | types: { 31 | TestType4: 'test4', 32 | }, 33 | }, 34 | ], 35 | }, 36 | }, 37 | }, 38 | typesChain: { 39 | chain2: { 40 | TestType5: 'test', 41 | }, 42 | }, 43 | typesSpec: { 44 | spec3: { 45 | TestType6: 'test', 46 | }, 47 | }, 48 | }; 49 | 50 | Object.defineProperty(exports, '__esModule', { 51 | value: true, 52 | }); 53 | 54 | exports.default = types; 55 | -------------------------------------------------------------------------------- /packages/node/test/projectFixture/v1.0.0/js/test2/project.yaml: -------------------------------------------------------------------------------- 1 | # project.yaml 2 | specVersion: '0.2.0' 3 | 4 | name: '' 5 | version: '0.0.0' 6 | description: '' 7 | repository: 'https://github.com/subquery/subql-starter' 8 | 9 | schema: 10 | file: ./schema.graphql 11 | 12 | network: 13 | genesisHash: '0x' 14 | endpoint: 'wss://polkadot.api.onfinality.io/public-ws' 15 | chaintypes: 16 | file: ./types.js 17 | 18 | dataSources: 19 | - kind: substrate/Runtime 20 | startBlock: 1 21 | mapping: 22 | file: dist/index.js 23 | handlers: 24 | - handler: handleBlock 25 | kind: substrate/BlockHandler 26 | - handler: handleEvent 27 | kind: substrate/EventHandler 28 | filter: #Filter is optional 29 | module: balances 30 | method: Deposit 31 | - handler: handleCall 32 | kind: substrate/CallHandler 33 | -------------------------------------------------------------------------------- /packages/node/test/projectFixture/v1.0.0/js/test2/types.js: -------------------------------------------------------------------------------- 1 | const os = require('os'); 2 | 3 | console.log(os.platform); 4 | 5 | const types = { 6 | types: { 7 | TestType: 'u32', 8 | }, 9 | typesAlias: { 10 | Alias: { 11 | TestType2: 'test', 12 | }, 13 | }, 14 | typesBundle: { 15 | spec: { 16 | 2312: { 17 | types: [ 18 | { 19 | minmax: [232, 122], 20 | types: { 21 | TestType3: 'test3', 22 | }, 23 | }, 24 | ], 25 | }, 26 | }, 27 | chain: { 28 | mockchain: { 29 | types: [ 30 | { 31 | minmax: [232, 122], 32 | types: { 33 | TestType4: 'test4', 34 | }, 35 | }, 36 | ], 37 | }, 38 | }, 39 | }, 40 | typesChain: { 41 | chain2: { 42 | TestType5: 'test', 43 | }, 44 | }, 45 | typesSpec: { 46 | spec3: { 47 | TestType6: 'test', 48 | }, 49 | }, 50 | }; 51 | 52 | module.exports = types; 53 | -------------------------------------------------------------------------------- /packages/node/test/projectFixture/v1.0.0/js/test3/project.yaml: -------------------------------------------------------------------------------- 1 | # project.yaml 2 | specVersion: '0.2.0' 3 | 4 | name: '' 5 | version: '0.0.0' 6 | description: '' 7 | repository: 'https://github.com/subquery/subql-starter' 8 | 9 | schema: 10 | file: ./schema.graphql 11 | 12 | network: 13 | genesisHash: '0x' 14 | endpoint: 'wss://polkadot.api.onfinality.io/public-ws' 15 | chaintypes: 16 | file: ./types.js 17 | 18 | dataSources: 19 | - kind: substrate/Runtime 20 | startBlock: 1 21 | mapping: 22 | file: dist/index.js 23 | handlers: 24 | - handler: handleBlock 25 | kind: substrate/BlockHandler 26 | - handler: handleEvent 27 | kind: substrate/EventHandler 28 | filter: #Filter is optional 29 | module: balances 30 | method: Deposit 31 | - handler: handleCall 32 | kind: substrate/CallHandler 33 | -------------------------------------------------------------------------------- /packages/node/test/projectFixture/v1.0.0/js/test3/types.js: -------------------------------------------------------------------------------- 1 | const types = { 2 | types: { 3 | TestType: 'u32', 4 | }, 5 | typesAlias: { 6 | Alias: { 7 | TestType2: 'test', 8 | }, 9 | }, 10 | typesBundle: { 11 | spec: { 12 | 2312: { 13 | types: [ 14 | { 15 | minmax: [232, 122], 16 | types: { 17 | TestType3: 'test3', 18 | }, 19 | }, 20 | ], 21 | }, 22 | }, 23 | chain: { 24 | mockchain: { 25 | types: [ 26 | { 27 | minmax: [232, 122], 28 | types: { 29 | TestType4: 'test4', 30 | }, 31 | }, 32 | ], 33 | }, 34 | }, 35 | }, 36 | typesChain: { 37 | chain2: { 38 | TestType5: 'test', 39 | }, 40 | }, 41 | typesSpec: { 42 | spec3: { 43 | TestType6: 'test', 44 | }, 45 | }, 46 | }; 47 | 48 | module.exports.test = types; 49 | -------------------------------------------------------------------------------- /packages/node/test/projectFixture/v1.0.0/js/test4/project.yaml: -------------------------------------------------------------------------------- 1 | # project.yaml 2 | specVersion: '0.2.0' 3 | 4 | name: '' 5 | version: '0.0.0' 6 | description: '' 7 | repository: 'https://github.com/subquery/subql-starter' 8 | 9 | schema: 10 | file: ./schema.graphql 11 | 12 | network: 13 | genesisHash: '0x' 14 | endpoint: 'wss://polkadot.api.onfinality.io/public-ws' 15 | chaintypes: 16 | file: ./types.js 17 | 18 | dataSources: 19 | - kind: substrate/Runtime 20 | startBlock: 1 21 | mapping: 22 | file: dist/index.js 23 | handlers: 24 | - handler: handleBlock 25 | kind: substrate/BlockHandler 26 | - handler: handleEvent 27 | kind: substrate/EventHandler 28 | filter: #Filter is optional 29 | module: balances 30 | method: Deposit 31 | - handler: handleCall 32 | kind: substrate/CallHandler 33 | -------------------------------------------------------------------------------- /packages/node/test/projectFixture/v1.0.0/js/test4/types.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const types = { 4 | types: { 5 | TestType: 'u32', 6 | }, 7 | typesAlias: { 8 | Alias: { 9 | TestType2: 'test', 10 | }, 11 | }, 12 | typesBundle: { 13 | spec: { 14 | 2312: { 15 | types: [ 16 | { 17 | minmax: [232, 122], 18 | types: { 19 | TestType3: 'test3', 20 | }, 21 | }, 22 | ], 23 | }, 24 | }, 25 | chain: { 26 | mockchain: { 27 | types: [ 28 | { 29 | minmax: [232, 122], 30 | types: { 31 | TestType4: 'test4', 32 | }, 33 | }, 34 | ], 35 | }, 36 | }, 37 | }, 38 | typesChain: { 39 | chain2: { 40 | TestType5: 'test', 41 | }, 42 | }, 43 | typesSpec: { 44 | spec3: { 45 | TestType6: 'test', 46 | }, 47 | }, 48 | shouldIgnorefield: { 49 | chain2: { 50 | TestType5: 'test', 51 | }, 52 | }, 53 | }; 54 | 55 | Object.defineProperty(exports, '__esModule', { 56 | value: true, 57 | }); 58 | 59 | exports.default = types; 60 | -------------------------------------------------------------------------------- /packages/node/test/projectFixture/v1.0.0/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "subquery-starter", 3 | "version": "0.0.4", 4 | "description": "This project can be use as a starting point for developing your SubQuery project", 5 | "main": "dist/index.js", 6 | "scripts": { 7 | "build": "tsc -b", 8 | "prepack": "rm -rf dist && npm build", 9 | "test": "jest", 10 | "codegen": "./node_modules/.bin/subql codegen" 11 | }, 12 | "homepage": "https://github.com/subquery/subql-starter", 13 | "repository": "github:subquery/subql-starter", 14 | "files": [ 15 | "dist", 16 | "schema.graphql", 17 | "project.yaml" 18 | ], 19 | "author": "Ian He & Jay Ji", 20 | "license": "Apache-2.0", 21 | "devDependencies": { 22 | "@polkadot/api": "11.0.2", 23 | "@subql/types": "dev", 24 | "typescript": "^4.9.5", 25 | "@subql/cli": "dev" 26 | }, 27 | "resolutions": { 28 | "ipfs-unixfs": "6.0.6" 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /packages/node/test/projectFixture/v1.0.0/schema.graphql: -------------------------------------------------------------------------------- 1 | type StarterEntity @entity { 2 | id: ID! #id is a required field 3 | field1: Int! 4 | 5 | field2: String #filed2 is an optional field 6 | field3: BigInt 7 | 8 | field4: Date 9 | 10 | field5: Boolean 11 | } 12 | -------------------------------------------------------------------------------- /packages/node/test/projectFixture/v1.0.0/types.yaml: -------------------------------------------------------------------------------- 1 | types: 2 | TestType: u32 3 | typesAlias: 4 | Alias: 5 | TestType2: test 6 | typesBundle: 7 | spec: 8 | '2312': 9 | types: 10 | - minmax: 11 | - 232 12 | - 122 13 | types: 14 | TestType3: test3 15 | chain: 16 | mockchain: 17 | types: 18 | - minmax: 19 | - 232 20 | - 122 21 | types: 22 | TestType4: test4 23 | typesChain: 24 | chain2: 25 | TestType5: test 26 | typesSpec: 27 | spec3: 28 | TestType6: test 29 | -------------------------------------------------------------------------------- /packages/node/tsconfig.build.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "exclude": ["node_modules", "test", "dist", "**/*spec.ts"] 4 | } 5 | -------------------------------------------------------------------------------- /packages/node/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.json", 3 | "compilerOptions": { 4 | "target": "es2017", 5 | "sourceMap": true, 6 | "tsBuildInfoFile": "dist/.tsbuildinfo", 7 | "rootDir": "src", 8 | "outDir": "./dist" 9 | }, 10 | "references": [ 11 | { "path": "../common" }, 12 | { "path": "../common-substrate" }, 13 | { "path": "../node-core" }, 14 | { "path": "../types-core" }, 15 | { "path": "../types" }, 16 | { "path": "../utils" }, 17 | { "path": "../testing" } 18 | ], 19 | "include": ["src/**/*"], 20 | "exclude": ["node_modules", "test", "dist"] 21 | } 22 | -------------------------------------------------------------------------------- /packages/query/.env.example: -------------------------------------------------------------------------------- 1 | DB_USER=postgres 2 | DB_PASS=postgres 3 | DB_DATABASE=postgres 4 | DB_HOST=localhost 5 | DB_PORT=5432 6 | PORT=3001 7 | -------------------------------------------------------------------------------- /packages/query/.gitignore: -------------------------------------------------------------------------------- 1 | # compiled output 2 | /dist 3 | /node_modules 4 | 5 | # Logs 6 | logs 7 | *.log 8 | npm-debug.log* 9 | yarn-debug.log* 10 | yarn-error.log* 11 | lerna-debug.log* 12 | 13 | # OS 14 | .DS_Store 15 | 16 | # Tests 17 | /coverage 18 | /.nyc_output 19 | 20 | # IDEs and editors 21 | /.idea 22 | .project 23 | .classpath 24 | .c9/ 25 | *.launch 26 | .settings/ 27 | *.sublime-workspace 28 | 29 | # IDE - VSCode 30 | .vscode/* 31 | !.vscode/settings.json 32 | !.vscode/tasks.json 33 | !.vscode/launch.json 34 | !.vscode/extensions.json 35 | 36 | .env 37 | -------------------------------------------------------------------------------- /packages/query/Dockerfile: -------------------------------------------------------------------------------- 1 | # Build stage 2 | FROM node:18-alpine as builder 3 | 4 | # Set working directory 5 | WORKDIR /app 6 | 7 | # Copy all packages 8 | COPY ./packages ./packages 9 | 10 | # Copy tsconfig.json 11 | COPY ./tsconfig.json ./tsconfig.json 12 | 13 | # Copy build script 14 | COPY ./scripts/build.sh ./scripts/build.sh 15 | 16 | # Install dependencies and build 17 | RUN ./scripts/build.sh packages/query 18 | 19 | # Production stage 20 | FROM node:18-alpine 21 | 22 | # Copy .tgz file from builder 23 | COPY --from=builder /app/packages/query/app.tgz /app.tgz 24 | 25 | # Install production dependencies 26 | RUN apk add --no-cache tini curl git && \ 27 | tar -xzvf /app.tgz --strip 1 && \ 28 | rm /app.tgz && \ 29 | yarn install --production && \ 30 | yarn cache clean && \ 31 | rm -rf /root/.npm /root/.cache 32 | 33 | # Make the user not ROOT 34 | USER 1000 35 | 36 | # Set Entry point and command 37 | ENTRYPOINT ["/sbin/tini", "--", "/bin/run"] 38 | CMD ["-f","/app"] 39 | -------------------------------------------------------------------------------- /packages/query/README.md: -------------------------------------------------------------------------------- 1 | # @subql/query 2 | 3 | ## Run this package 4 | 5 | To quickly setup the project, add a `.env` file in the `subql/packages/query` folder with the following content: 6 | 7 | ``` 8 | DB_HOST=localhost 9 | DB_PORT=5432 10 | DB_USER=postgres 11 | DB_PASS=postgres 12 | DB_DATABASE=postgres 13 | ``` 14 | 15 | then run the following command 16 | 17 | ``` 18 | $ NODE_OPTIONS="-r dotenv/config" yarn start -- --name --playground 19 | ``` 20 | -------------------------------------------------------------------------------- /packages/query/bin/run: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | 3 | require('../dist/main.js') 4 | 5 | -------------------------------------------------------------------------------- /packages/query/bin/run.cmd: -------------------------------------------------------------------------------- 1 | @echo off 2 | 3 | node "%~dp0\run" %* 4 | -------------------------------------------------------------------------------- /packages/query/nest-cli.json: -------------------------------------------------------------------------------- 1 | { 2 | "collection": "@nestjs/schematics", 3 | "sourceRoot": "src" 4 | } 5 | -------------------------------------------------------------------------------- /packages/query/nodemon.json: -------------------------------------------------------------------------------- 1 | { 2 | "watch": ["src"], 3 | "ext": "ts", 4 | "ignore": ["src/**/*.spec.ts"], 5 | "exec": "node -r dotenv/config -r tsconfig-paths/register -r ts-node/register src/main.ts" 6 | } 7 | -------------------------------------------------------------------------------- /packages/query/src/app.module.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2020-2024 SubQuery Pte Ltd authors & contributors 2 | // SPDX-License-Identifier: GPL-3.0 3 | 4 | import {Module} from '@nestjs/common'; 5 | import {ConfigureModule} from './configure/configure.module'; 6 | import {GraphqlModule} from './graphql/graphql.module'; 7 | 8 | @Module({ 9 | imports: [ConfigureModule.register(), GraphqlModule], 10 | controllers: [], 11 | }) 12 | export class AppModule {} 13 | -------------------------------------------------------------------------------- /packages/query/src/configure/config.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2020-2024 SubQuery Pte Ltd authors & contributors 2 | // SPDX-License-Identifier: GPL-3.0 3 | 4 | import {get} from 'lodash'; 5 | 6 | export class Config { 7 | constructor(private readonly store: Record) {} 8 | 9 | get(key: string, defaultValue?: T): T { 10 | return (process.env[key.toUpperCase()] as unknown as T) ?? get(this.store, key, defaultValue); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /packages/query/src/configure/index.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2020-2024 SubQuery Pte Ltd authors & contributors 2 | // SPDX-License-Identifier: GPL-3.0 3 | 4 | export * from './config'; 5 | -------------------------------------------------------------------------------- /packages/query/src/graphql/plugins/QueryAliasLimitPlugin.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2020-2024 SubQuery Pte Ltd authors & contributors 2 | // SPDX-License-Identifier: GPL-3.0 3 | 4 | import type {ApolloServerPlugin} from 'apollo-server-plugin-base'; 5 | import {GraphQLSchema, GraphQLError, DocumentNode, visit} from 'graphql'; 6 | 7 | function checkLimit(document: DocumentNode, limit: number): void { 8 | let aliasCount = 0; 9 | visit(document, { 10 | Field(node) { 11 | if (node.alias) { 12 | aliasCount += 1; 13 | if (aliasCount > limit) throw new GraphQLError('Alias limit exceeded'); 14 | } 15 | }, 16 | }); 17 | } 18 | 19 | export function queryAliasLimit(options: {schema: GraphQLSchema; limit?: number}): ApolloServerPlugin { 20 | return { 21 | requestDidStart: () => { 22 | return { 23 | didResolveOperation(context: {document: DocumentNode}) { 24 | if (options?.limit === undefined) { 25 | return; 26 | } 27 | checkLimit(context.document, options.limit); 28 | }, 29 | }; 30 | }, 31 | } as unknown as ApolloServerPlugin; 32 | } 33 | -------------------------------------------------------------------------------- /packages/query/src/graphql/plugins/historical/index.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2020-2024 SubQuery Pte Ltd authors & contributors 2 | // SPDX-License-Identifier: GPL-3.0 3 | 4 | import {PgBlockHeightPlugin} from './PgBlockHeightPlugin'; 5 | import PgConnectionArgFilterBackwardRelationsPlugin from './PgConnectionArgFilterBackwardRelationsPlugin'; 6 | import PgConnectionArgFilterForwardRelationsPlugin from './PgConnectionArgFilterForwardRelationsPlugin'; 7 | 8 | const historicalPlugins = [ 9 | PgBlockHeightPlugin, // This must be before the other plugins to ensure the context is set 10 | PgConnectionArgFilterBackwardRelationsPlugin, 11 | PgConnectionArgFilterForwardRelationsPlugin, 12 | ]; 13 | 14 | export default historicalPlugins; 15 | -------------------------------------------------------------------------------- /packages/query/src/graphql/plugins/historical/utils.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2020-2024 SubQuery Pte Ltd authors & contributors 2 | // SPDX-License-Identifier: GPL-3.0 3 | 4 | import {PgEntity, PgEntityKind, SQL} from '@subql/x-graphile-build-pg'; 5 | 6 | export function makeRangeQuery(tableName: SQL, blockHeight: SQL, sql: any): SQL { 7 | return sql.fragment`${tableName}._block_range @> ${blockHeight}`; 8 | } 9 | 10 | // Used to filter out _block_range attributes 11 | export function hasBlockRange(entity?: PgEntity): boolean { 12 | if (!entity) { 13 | return true; 14 | } 15 | 16 | switch (entity.kind) { 17 | case PgEntityKind.CLASS: { 18 | return entity.attributes.some(({name}) => name === '_block_range'); 19 | } 20 | case PgEntityKind.CONSTRAINT: { 21 | return hasBlockRange(entity.class); // DOESNT WORK && notBlockRange(pgFieldIntrospection.foreignClass) 22 | } 23 | default: 24 | return true; 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /packages/query/src/graphql/plugins/smartTagsPlugin.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2020-2024 SubQuery Pte Ltd authors & contributors 2 | // SPDX-License-Identifier: GPL-3.0 3 | 4 | import {MULTI_METADATA_REGEX, METADATA_REGEX} from '@subql/utils'; 5 | import {PgEntity, PgEntityKind} from '@subql/x-graphile-build-pg'; 6 | import {makePgSmartTagsPlugin} from 'graphile-utils'; 7 | 8 | export const smartTagsPlugin = makePgSmartTagsPlugin([ 9 | { 10 | //Rule 1, omit `_metadata` from node 11 | kind: PgEntityKind.CLASS, 12 | match: ({name}: PgEntity) => METADATA_REGEX.test(name) || MULTI_METADATA_REGEX.test(name), 13 | tags: { 14 | omit: true, 15 | }, 16 | }, 17 | // Omit _block_range column 18 | { 19 | kind: PgEntityKind.ATTRIBUTE, 20 | match: ({name}) => /^_block_range$/.test(name), 21 | tags: { 22 | omit: true, 23 | }, 24 | }, 25 | // Omit _id column 26 | { 27 | kind: PgEntityKind.ATTRIBUTE, 28 | match: ({name}) => /^_id$/.test(name), 29 | tags: { 30 | omit: true, 31 | }, 32 | }, 33 | ]); 34 | -------------------------------------------------------------------------------- /packages/query/tsconfig.build.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "exclude": ["node_modules", "test", "dist", "**/*spec.ts"] 4 | } 5 | -------------------------------------------------------------------------------- /packages/query/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.json", 3 | "compilerOptions": { 4 | "target": "es2017", 5 | "sourceMap": true, 6 | "tsBuildInfoFile": "dist/.tsbuildinfo", 7 | "rootDir": "src", 8 | "outDir": "./dist", 9 | "lib": ["dom"] 10 | }, 11 | "references": [{"path": "../common"}, {"path": "../types"}, {"path": "../utils"}], 12 | "include": ["src/**/*"] 13 | } 14 | -------------------------------------------------------------------------------- /packages/testing/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@subql/testing", 3 | "version": "2.1.1", 4 | "scripts": { 5 | "test": "echo \"Error: no test specified\" && exit 1", 6 | "build": "rm -rf dist && tsc -b", 7 | "changelog:release": "echo \"Updating changelog $npm_package_version\" && npx chan release $npm_package_version --git-url \"https://github.com/subquery/subql\" --release-prefix=\"testing/\"" 8 | }, 9 | "main": "dist/index.js", 10 | "license": "GPL-3.0", 11 | "files": [ 12 | "/dist" 13 | ], 14 | "packageManager": "yarn@3.1.1", 15 | "dependencies": { 16 | "@subql/types-core": "workspace:^" 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /packages/testing/src/index.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2020-2024 SubQuery Pte Ltd authors & contributors 2 | // SPDX-License-Identifier: GPL-3.0 3 | 4 | export * from './interfaces'; 5 | 6 | import {Entity} from '@subql/types-core'; 7 | 8 | // Register test functions to a global array 9 | export function subqlTest( 10 | name: string, 11 | blockHeight: number, 12 | dependentEntities: Entity[], 13 | expectedEntities: Entity[], 14 | handler: string 15 | ): void { 16 | (global as any).subqlTests = (global as any).subqlTests ?? []; 17 | 18 | (global as any).subqlTests.push({ 19 | name, 20 | blockHeight, 21 | dependentEntities, 22 | expectedEntities, 23 | handler, 24 | }); 25 | } 26 | -------------------------------------------------------------------------------- /packages/testing/src/interfaces.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2020-2024 SubQuery Pte Ltd authors & contributors 2 | // SPDX-License-Identifier: GPL-3.0 3 | 4 | import {Entity} from '@subql/types-core'; 5 | 6 | export type HandlerFunction = (input: T) => Promise; 7 | 8 | export type SubqlTest = { 9 | name: string; 10 | blockHeight: number; 11 | dependentEntities: Entity[]; 12 | expectedEntities: Entity[]; 13 | handler: string; 14 | }; 15 | -------------------------------------------------------------------------------- /packages/testing/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.json", 3 | "compilerOptions": { 4 | "tsBuildInfoFile": "dist/.tsbuildinfo", 5 | "rootDir": "src", 6 | "outDir": "dist", 7 | "noImplicitAny": true 8 | }, 9 | "include": ["src/**/*"], 10 | "references": [{"path": "../common"}, {"path": "../common-substrate"}] 11 | } 12 | -------------------------------------------------------------------------------- /packages/types-core/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@subql/types-core", 3 | "version": "0.7.0", 4 | "description": "", 5 | "homepage": "https://github.com/subquery/subql", 6 | "repository": "github:subquery/subql", 7 | "scripts": { 8 | "test": "echo \"Error: no test specified\" && exit 1", 9 | "build": "rm -rf dist && tsc -b", 10 | "changelog:release": "echo \"Updating changelog $npm_package_version\" && npx chan release $npm_package_version --git-url \"https://github.com/subquery/subql\" --release-prefix=\"types-core/\"" 11 | }, 12 | "author": "Ian He", 13 | "main": "dist/index.js", 14 | "license": "GPL-3.0", 15 | "files": [ 16 | "/dist" 17 | ], 18 | "dependencies": { 19 | "package-json-type": "^1.0.3" 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /packages/types-core/src/global.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2020-2024 SubQuery Pte Ltd authors & contributors 2 | // SPDX-License-Identifier: GPL-3.0 3 | 4 | import Pino from 'pino'; 5 | import {Cache, DynamicDatasourceCreator} from './interfaces'; 6 | import {Store} from './store'; 7 | 8 | // base global 9 | declare global { 10 | const logger: Pino.Logger; 11 | const store: Store; 12 | const cache: Cache; 13 | const chainId: string; 14 | const createDynamicDatasource: DynamicDatasourceCreator; 15 | } 16 | -------------------------------------------------------------------------------- /packages/types-core/src/index.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2020-2024 SubQuery Pte Ltd authors & contributors 2 | // SPDX-License-Identifier: GPL-3.0 3 | 4 | export * from './interfaces'; 5 | export * from './project'; 6 | export * from './store'; 7 | export * from './multichain'; 8 | -------------------------------------------------------------------------------- /packages/types-core/src/interfaces.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2020-2024 SubQuery Pte Ltd authors & contributors 2 | // SPDX-License-Identifier: GPL-3.0 3 | 4 | export type DynamicDatasourceCreator = (name: string, args: Record) => Promise; 5 | 6 | export interface Cache = Record> { 7 | set(key: keyof T, value: T[keyof T]): Promise; 8 | get(key: keyof T): Promise; 9 | } 10 | -------------------------------------------------------------------------------- /packages/types-core/src/multichain/index.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2020-2024 SubQuery Pte Ltd authors & contributors 2 | // SPDX-License-Identifier: GPL-3.0 3 | 4 | export * from './types'; 5 | -------------------------------------------------------------------------------- /packages/types-core/src/multichain/types.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2020-2024 SubQuery Pte Ltd authors & contributors 2 | // SPDX-License-Identifier: GPL-3.0 3 | 4 | import {QuerySpec} from '../project'; 5 | 6 | export interface MultichainProjectManifest { 7 | specVersion: string; 8 | projects: string[]; 9 | query: QuerySpec; 10 | } 11 | -------------------------------------------------------------------------------- /packages/types-core/src/project/index.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2020-2024 SubQuery Pte Ltd authors & contributors 2 | // SPDX-License-Identifier: GPL-3.0 3 | 4 | export * from './types'; 5 | export * from './versioned'; 6 | export * from './readers'; 7 | export * from './datasourceProcessors'; 8 | -------------------------------------------------------------------------------- /packages/types-core/src/project/readers/index.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2020-2024 SubQuery Pte Ltd authors & contributors 2 | // SPDX-License-Identifier: GPL-3.0 3 | 4 | export * from './reader'; 5 | -------------------------------------------------------------------------------- /packages/types-core/src/project/readers/reader.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2020-2024 SubQuery Pte Ltd authors & contributors 2 | // SPDX-License-Identifier: GPL-3.0 3 | 4 | import {IPackageJson} from 'package-json-type'; 5 | 6 | export type ReaderOptions = { 7 | ipfs?: string; 8 | }; 9 | 10 | export interface Reader { 11 | getProjectSchema(): Promise; 12 | getPkg(): Promise; 13 | getFile(file: string): Promise; 14 | root: string | undefined; 15 | } 16 | -------------------------------------------------------------------------------- /packages/types-core/src/project/versioned/index.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2020-2024 SubQuery Pte Ltd authors & contributors 2 | // SPDX-License-Identifier: GPL-3.0 3 | 4 | export * from './base'; 5 | export * from './v1_0_0'; 6 | -------------------------------------------------------------------------------- /packages/types-core/src/project/versioned/v1_0_0/index.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2020-2024 SubQuery Pte Ltd authors & contributors 2 | // SPDX-License-Identifier: GPL-3.0 3 | 4 | export * from './types'; 5 | -------------------------------------------------------------------------------- /packages/types-core/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.json", 3 | "compilerOptions": { 4 | "strictNullChecks": true, 5 | "noImplicitAny": true, 6 | "tsBuildInfoFile": "dist/.tsbuildinfo", 7 | "rootDir": "src", 8 | "outDir": "dist", 9 | "strict": true 10 | }, 11 | "include": ["src/**/*"] 12 | } 13 | -------------------------------------------------------------------------------- /packages/types/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@subql/types", 3 | "version": "3.6.0", 4 | "description": "", 5 | "homepage": "https://github.com/subquery/subql", 6 | "repository": "github:subquery/subql", 7 | "scripts": { 8 | "test": "echo \"Error: no test specified\" && exit 1", 9 | "build": "rm -rf dist && tsc -b", 10 | "changelog:release": "echo \"Updating changelog $npm_package_version\" && npx chan release $npm_package_version --git-url \"https://github.com/subquery/subql\" --release-prefix=\"types/\"" 11 | }, 12 | "author": "Ian He", 13 | "main": "dist/index.js", 14 | "license": "GPL-3.0", 15 | "files": [ 16 | "src/global.d.ts", 17 | "/dist" 18 | ], 19 | "dependencies": { 20 | "@subql/types-core": "workspace:*" 21 | }, 22 | "peerDependencies": { 23 | "@polkadot/api": "^11" 24 | }, 25 | "devDependencies": { 26 | "@polkadot/api": "11.0.2" 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /packages/types/src/global.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2020-2024 SubQuery Pte Ltd authors & contributors 2 | // SPDX-License-Identifier: GPL-3.0 3 | 4 | import {ApiPromise} from '@polkadot/api'; 5 | import {ApiDecoration} from '@polkadot/api/types'; 6 | 7 | import '@subql/types-core/dist/global'; 8 | 9 | type ApiAt = ApiDecoration<'promise'> & {rpc: ApiPromise['rpc']}; 10 | 11 | declare global { 12 | const api: ApiAt; 13 | const unsafeApi: ApiPromise | undefined; 14 | } 15 | -------------------------------------------------------------------------------- /packages/types/src/index.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2020-2024 SubQuery Pte Ltd authors & contributors 2 | // SPDX-License-Identifier: GPL-3.0 3 | 4 | export * from './interfaces'; 5 | export * from './project'; 6 | -------------------------------------------------------------------------------- /packages/types/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.json", 3 | "compilerOptions": { 4 | "strictNullChecks": true, 5 | "noImplicitAny": true, 6 | "tsBuildInfoFile": "dist/.tsbuildinfo", 7 | "rootDir": "src", 8 | "outDir": "dist", 9 | "strict": true 10 | }, 11 | "references": [{"path": "../types-core"}], 12 | "include": ["src/**/*"] 13 | } 14 | -------------------------------------------------------------------------------- /packages/utils/README.md: -------------------------------------------------------------------------------- 1 | # manifest-spec 2 | -------------------------------------------------------------------------------- /packages/utils/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@subql/utils", 3 | "version": "2.10.0", 4 | "description": "", 5 | "packageManager": "yarn@3.1.1", 6 | "scripts": { 7 | "build": "tsc -b", 8 | "changelog:release": "echo \"Updating changelog $npm_package_version\" && npx chan release $npm_package_version --git-url \"https://github.com/subquery/subql\" --release-prefix=\"utils/\"" 9 | }, 10 | "homepage": "https://github.com/subquery/subql", 11 | "repository": "github:subquery/subql", 12 | "author": "SubQuery Pty. Limited", 13 | "main": "dist/index.js", 14 | "license": "GPL-3.0", 15 | "dependencies": { 16 | "@polkadot/util": "^12.6.2", 17 | "@polkadot/util-crypto": "^12.6.2", 18 | "@subql/x-sequelize": "6.32.0-0.0.4", 19 | "ansi-styles": "^6.1.0", 20 | "chalk": "^4.1.2", 21 | "detect-port": "^1.3.0", 22 | "flatted": "^3.2.5", 23 | "graphql": "^15.8.0", 24 | "graphql-tag": "^2.12.6", 25 | "lodash": "^4.17.21", 26 | "pino": "^6.13.3", 27 | "rotating-file-stream": "^3.0.2", 28 | "semver": "^7.5.2", 29 | "tar": "^6.2.1" 30 | }, 31 | "devDependencies": { 32 | "@types/semver": "^7" 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /packages/utils/src/array/array.spec.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2020-2024 SubQuery Pte Ltd authors & contributors 2 | // SPDX-License-Identifier: GPL-3.0 3 | 4 | import {findDuplicateStringArray} from './array'; 5 | 6 | describe('Array util', () => { 7 | it('findDuplicateStringArray', () => { 8 | const arrays = [ 9 | ['1', '2', '3'], 10 | ['3', '1', '2'], 11 | ['apple', 'banana', 'orange'], 12 | ['orange', 'apple', 'banana'], 13 | ['grape', 'melon', 'kiwi'], //this is unique 14 | ]; 15 | expect(findDuplicateStringArray(arrays)).toStrictEqual([ 16 | ['1', '2', '3'], 17 | ['apple', 'banana', 'orange'], 18 | ]); 19 | }); 20 | }); 21 | -------------------------------------------------------------------------------- /packages/utils/src/array/array.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2020-2024 SubQuery Pte Ltd authors & contributors 2 | // SPDX-License-Identifier: GPL-3.0 3 | 4 | import {uniqWith, isEqual} from 'lodash'; 5 | 6 | // Find duplicate string array in arrays 7 | // Only sorted unique string array will be return 8 | export function findDuplicateStringArray(arrays: string[][]): string[][] { 9 | const sortedArrays = arrays.map((arr) => arr.sort().join('')); 10 | const duplicateArray = []; 11 | for (let i = 0; i < sortedArrays.length; i++) { 12 | if (sortedArrays.indexOf(sortedArrays[i]) !== sortedArrays.lastIndexOf(sortedArrays[i])) { 13 | duplicateArray.push(arrays[i]); 14 | } 15 | } 16 | return uniqWith(duplicateArray, isEqual); 17 | } 18 | -------------------------------------------------------------------------------- /packages/utils/src/array/index.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2020-2024 SubQuery Pte Ltd authors & contributors 2 | // SPDX-License-Identifier: GPL-3.0 3 | 4 | export * from './array'; 5 | -------------------------------------------------------------------------------- /packages/utils/src/buffer/buffer.spec.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2020-2024 SubQuery Pte Ltd authors & contributors 2 | // SPDX-License-Identifier: GPL-3.0 3 | 4 | import {hexStripZeros, numberToHex} from './buffer'; 5 | 6 | it('in getData, should hex number correctly', () => { 7 | const from = 10000; 8 | const to = 9999999; 9 | const to54897704 = 54897704; 10 | const zero = 0; 11 | 12 | // Use ethers.utils should have same output 13 | // expect(utils.hexValue(from)).toBe(numberToHex(from)) 14 | // expect(utils.hexValue(to54897704)).toBe(hexStripZeros(numberToHex(to54897704))) 15 | expect(hexStripZeros(numberToHex(zero))).toBe('0x0'); 16 | expect(hexStripZeros(numberToHex(from))).toBe('0x2710'); 17 | expect(hexStripZeros(numberToHex(to))).toBe('0x98967f'); 18 | expect(hexStripZeros(numberToHex(to54897704))).toBe('0x345ac28'); 19 | }); 20 | -------------------------------------------------------------------------------- /packages/utils/src/buffer/buffer.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2020-2024 SubQuery Pte Ltd authors & contributors 2 | // SPDX-License-Identifier: GPL-3.0 3 | 4 | import {isHex} from '@polkadot/util'; 5 | import {HexString} from '@polkadot/util/types'; 6 | 7 | export { 8 | u8aEq, 9 | hexToU8a, 10 | hexToNumber, 11 | bufferToU8a, 12 | numberToU8a, 13 | numberToHex, 14 | u8aToHex, 15 | u8aConcat, 16 | u8aToBuffer, 17 | isU8a, 18 | isHex, 19 | isString, 20 | isBuffer, 21 | isNull, 22 | } from '@polkadot/util'; 23 | 24 | export {blake2AsHex, blake2AsU8a, isBase58, isBase64, base58Decode, base64Decode} from '@polkadot/util-crypto'; 25 | 26 | // This is a clone from ethers.util hexStripZeros, in order to match polkadot util hex value with ethers 27 | export function hexStripZeros(value: HexString): string { 28 | if (!isHex(value)) { 29 | throw new Error(`invalid hex string ${value}`); 30 | } 31 | const str = value.toString().substring(2); 32 | let offset = 0; 33 | while (offset < str.length && str[offset] === '0') { 34 | offset++; 35 | } 36 | const trimmed = `0x${str.substring(offset)}`; 37 | if (trimmed === '0x') { 38 | return '0x0'; 39 | } 40 | return trimmed; 41 | } 42 | -------------------------------------------------------------------------------- /packages/utils/src/buffer/index.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2020-2024 SubQuery Pte Ltd authors & contributors 2 | // SPDX-License-Identifier: GPL-3.0 3 | 4 | export * from './buffer'; 5 | -------------------------------------------------------------------------------- /packages/utils/src/graphql/constant.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2020-2024 SubQuery Pte Ltd authors & contributors 2 | // SPDX-License-Identifier: GPL-3.0 3 | 4 | export enum DirectiveName { 5 | DerivedFrom = 'derivedFrom', 6 | Entity = 'entity', 7 | JsonField = 'jsonField', 8 | FullText = 'fullText', 9 | } 10 | -------------------------------------------------------------------------------- /packages/utils/src/graphql/index.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2020-2024 SubQuery Pte Ltd authors & contributors 2 | // SPDX-License-Identifier: GPL-3.0 3 | 4 | export * from './entities'; 5 | export * from './schema'; 6 | export * from './types'; 7 | export * from './builder'; 8 | -------------------------------------------------------------------------------- /packages/utils/src/graphql/schema.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2020-2024 SubQuery Pte Ltd authors & contributors 2 | // SPDX-License-Identifier: GPL-3.0 3 | 4 | import fs from 'fs'; 5 | import {buildASTSchema, DocumentNode, extendSchema, GraphQLSchema, parse, Source} from 'graphql'; 6 | import {directives} from './schema/directives'; 7 | import {scalas} from './schema/scalas'; 8 | 9 | function loadBaseSchema(): GraphQLSchema { 10 | const schema = buildASTSchema(scalas); 11 | return extendSchema(schema, directives); 12 | } 13 | 14 | export function buildSchemaFromFile(path: string): GraphQLSchema { 15 | return buildSchemaFromString(fs.readFileSync(path).toString()); 16 | } 17 | 18 | export function buildSchemaFromString(raw: string): GraphQLSchema { 19 | const src = new Source(raw); 20 | const doc = parse(src); 21 | return buildSchemaFromDocumentNode(doc); 22 | } 23 | 24 | export function buildSchemaFromDocumentNode(doc: DocumentNode): GraphQLSchema { 25 | return extendSchema(loadBaseSchema(), doc); 26 | } 27 | -------------------------------------------------------------------------------- /packages/utils/src/graphql/schema/directives.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2020-2024 SubQuery Pte Ltd authors & contributors 2 | // SPDX-License-Identifier: GPL-3.0 3 | 4 | import gql from 'graphql-tag'; 5 | 6 | export const directives = gql` 7 | directive @derivedFrom(field: String!) on FIELD_DEFINITION 8 | directive @entity on OBJECT 9 | directive @jsonField(indexed: Boolean) on OBJECT 10 | directive @index(unique: Boolean) on FIELD_DEFINITION 11 | directive @compositeIndexes(fields: [[String]]!) on OBJECT 12 | directive @fullText(fields: [String!], language: String) on OBJECT 13 | `; 14 | -------------------------------------------------------------------------------- /packages/utils/src/graphql/schema/scalas.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2020-2024 SubQuery Pte Ltd authors & contributors 2 | // SPDX-License-Identifier: GPL-3.0 3 | 4 | import gql from 'graphql-tag'; 5 | 6 | export const scalas = gql` 7 | scalar BigInt 8 | scalar BigDecimal 9 | scalar Date 10 | scalar Bytes 11 | scalar Float 12 | `; 13 | -------------------------------------------------------------------------------- /packages/utils/src/index.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2020-2024 SubQuery Pte Ltd authors & contributors 2 | // SPDX-License-Identifier: GPL-3.0 3 | 4 | export * from './graphql'; 5 | export {levelFilter, Logger, LoggerOption} from './logger'; 6 | export * from './query'; 7 | export * from './types'; 8 | export * from './buffer'; 9 | -------------------------------------------------------------------------------- /packages/utils/src/logger/colors.spec.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2020-2024 SubQuery Pte Ltd authors & contributors 2 | // SPDX-License-Identifier: GPL-3.0 3 | 4 | import {colorizeLevel} from './colors'; 5 | 6 | describe('LoggerColorLevel', () => { 7 | it('returns default for an unsupported level number', () => { 8 | const level = colorizeLevel(5); 9 | expect(level).toBe('\x1b[37mUSERLVL\x1b[39m'); 10 | }); 11 | 12 | it('returns the correct level for a level number', () => { 13 | const level = colorizeLevel(60); 14 | expect(level).toBe('\x1b[41mFATAL\x1b[49m'); 15 | }); 16 | }); 17 | -------------------------------------------------------------------------------- /packages/utils/src/logger/colors.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2020-2024 SubQuery Pte Ltd authors & contributors 2 | // SPDX-License-Identifier: GPL-3.0 3 | 4 | import chalk from 'chalk'; 5 | import {LEVELS} from './constants'; 6 | 7 | export const ctx = new chalk.Instance({level: 3}); 8 | const colored: Record = { 9 | default: ctx.white, 10 | 60: ctx.bgRed, 11 | 50: ctx.red, 12 | 40: ctx.yellow, 13 | 30: ctx.green, 14 | 20: ctx.blue, 15 | 10: ctx.grey, 16 | message: ctx.cyan, 17 | }; 18 | 19 | function isColouredValue(level: number | string): level is keyof typeof LEVELS { 20 | return Number.isInteger(+level) && level in colored; 21 | } 22 | 23 | export function colorizeLevel(level: number): string { 24 | if (isColouredValue(level) && Object.prototype.hasOwnProperty.call(LEVELS, level)) { 25 | return colored[level](LEVELS[level]); 26 | } 27 | return colored.default(LEVELS.default); 28 | } 29 | -------------------------------------------------------------------------------- /packages/utils/src/logger/constants.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2020-2024 SubQuery Pte Ltd authors & contributors 2 | // SPDX-License-Identifier: GPL-3.0 3 | 4 | export const LEVELS = { 5 | default: 'USERLVL', 6 | 60: 'FATAL', 7 | 50: 'ERROR', 8 | 40: 'WARN', 9 | 30: 'INFO', 10 | 20: 'DEBUG', 11 | 10: 'TRACE', 12 | }; 13 | 14 | export const LEVELS_MAP = { 15 | trace: 10, 16 | debug: 20, 17 | info: 30, 18 | warn: 40, 19 | error: 50, 20 | fatal: 60, 21 | silent: 999, 22 | }; 23 | -------------------------------------------------------------------------------- /packages/utils/src/logger/index.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2020-2024 SubQuery Pte Ltd authors & contributors 2 | // SPDX-License-Identifier: GPL-3.0 3 | 4 | export * from './logger'; 5 | export * from './util'; 6 | -------------------------------------------------------------------------------- /packages/utils/src/logger/util.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2020-2024 SubQuery Pte Ltd authors & contributors 2 | // SPDX-License-Identifier: GPL-3.0 3 | 4 | import {LevelWithSilent} from 'pino'; 5 | import {LEVELS_MAP} from './constants'; 6 | 7 | export function levelFilter(test: LevelWithSilent, target: LevelWithSilent): boolean { 8 | return LEVELS_MAP[test?.toLowerCase()] >= LEVELS_MAP[target.toLowerCase()]; 9 | } 10 | -------------------------------------------------------------------------------- /packages/utils/src/query/index.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2020-2024 SubQuery Pte Ltd authors & contributors 2 | // SPDX-License-Identifier: GPL-3.0 3 | 4 | export * from './types'; 5 | export * from './metadata'; 6 | -------------------------------------------------------------------------------- /packages/utils/src/query/metadata.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2020-2024 SubQuery Pte Ltd authors & contributors 2 | // SPDX-License-Identifier: GPL-3.0 3 | 4 | import {blake2AsHex} from '@polkadot/util-crypto'; 5 | 6 | export const METADATA_REGEX = /^_metadata$/; 7 | 8 | export const MULTI_METADATA_REGEX = /^_metadata_[a-zA-Z0-9-]+$/; 9 | 10 | export function getMetadataTableName(chainId: string): string { 11 | const hash = blake2AsHex(chainId, 64); 12 | return `_metadata_${hash}`.substring(0, 63); // 63 chars is the max postgres database table name length 13 | } 14 | 15 | // Hash names of SQL functions, triggers, channels to ensure it does not exceed the char limit 16 | export function hashName(schema: string, type: string, tableName: string): string { 17 | // Postgres identifier limit is 63 bytes (chars) 18 | return blake2AsHex(`${schema}_${tableName}_${type}`, 64).substring(0, 63); 19 | } 20 | -------------------------------------------------------------------------------- /packages/utils/src/query/types.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2020-2024 SubQuery Pte Ltd authors & contributors 2 | // SPDX-License-Identifier: GPL-3.0 3 | 4 | export type TableEstimate = { 5 | table: string; 6 | estimate: number; 7 | }; 8 | 9 | export type MetaData = { 10 | lastProcessedHeight: number; 11 | lastProcessedTimestamp: number; 12 | targetHeight: number; 13 | chain: string; 14 | specName: string; 15 | genesisHash: string; 16 | indexerHealthy: boolean; 17 | indexerNodeVersion: string; 18 | queryNodeVersion: string; 19 | startHeight?: number; 20 | rowCountEstimate: TableEstimate[]; 21 | deployments: Record; 22 | }; 23 | -------------------------------------------------------------------------------- /packages/utils/src/types/TypeClass.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2020-2024 SubQuery Pte Ltd authors & contributors 2 | // SPDX-License-Identifier: GPL-3.0 3 | 4 | import assert from 'assert'; 5 | import {DataTypes} from '@subql/x-sequelize'; 6 | type ValueOf = T[keyof T]; 7 | export type SequelizeTypes = string | ValueOf; 8 | 9 | export class TypeClass { 10 | constructor( 11 | public name: string, 12 | private _hashCode: (data: unknown) => Uint8Array, 13 | private _tsType?: string, 14 | private _fieldScalar?: string, 15 | private _sequelizeType?: SequelizeTypes 16 | ) {} 17 | get tsType(): string | undefined { 18 | return this._tsType; 19 | } 20 | get fieldScalar(): string | undefined { 21 | return this._fieldScalar; 22 | } 23 | get sequelizeType(): SequelizeTypes { 24 | assert(this._sequelizeType !== undefined, `Type ${this.name} associated sequelize type is not supported`); 25 | return this._sequelizeType; 26 | } 27 | hashCode(data: any): Uint8Array { 28 | if (this._hashCode === undefined) { 29 | return Buffer.from(JSON.stringify(data)); 30 | } 31 | return this._hashCode(data); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /packages/utils/src/types/generalTypes.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2020-2024 SubQuery Pte Ltd authors & contributors 2 | // SPDX-License-Identifier: GPL-3.0 3 | 4 | import * as supportedTypes from './supported'; 5 | import {TypeClass} from './TypeClass'; 6 | 7 | export function getTypeByScalarName(type: string): TypeClass | undefined { 8 | return Object.values(supportedTypes).find(({name}) => name === type); 9 | } 10 | -------------------------------------------------------------------------------- /packages/utils/src/types/index.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2020-2024 SubQuery Pte Ltd authors & contributors 2 | // SPDX-License-Identifier: GPL-3.0 3 | 4 | export * from './generalTypes'; 5 | 6 | export * from './TypeClass'; 7 | 8 | export * from './supported'; 9 | -------------------------------------------------------------------------------- /packages/utils/src/types/supported/BigInt.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2020-2024 SubQuery Pte Ltd authors & contributors 2 | // SPDX-License-Identifier: GPL-3.0 3 | 4 | import BN from 'bn.js'; 5 | import {TypeClass} from '../TypeClass'; 6 | 7 | export const BigInt = new TypeClass( 8 | 'BigInt', 9 | (data: bigint | string): Uint8Array => { 10 | return new BN(data.toString()).toBuffer(); 11 | }, 12 | 'bigint', 13 | 'BigInt', 14 | 'numeric' 15 | ); 16 | -------------------------------------------------------------------------------- /packages/utils/src/types/supported/Boolean.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2020-2024 SubQuery Pte Ltd authors & contributors 2 | // SPDX-License-Identifier: GPL-3.0 3 | 4 | import {numberToU8a} from '@polkadot/util'; 5 | import {TypeClass} from '../TypeClass'; 6 | 7 | export const Boolean = new TypeClass( 8 | 'Boolean', 9 | (data: boolean): Uint8Array => { 10 | return numberToU8a(data ? 1 : 0); 11 | }, 12 | 'boolean', 13 | 'Boolean', 14 | 'boolean' 15 | ); 16 | -------------------------------------------------------------------------------- /packages/utils/src/types/supported/Bytes.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2020-2024 SubQuery Pte Ltd authors & contributors 2 | // SPDX-License-Identifier: GPL-3.0 3 | 4 | import {isHex, hexToU8a} from '@polkadot/util'; 5 | import {DataTypes} from '@subql/x-sequelize'; 6 | import {TypeClass} from '../TypeClass'; 7 | 8 | export const Bytes = new TypeClass( 9 | 'Bytes', 10 | (data: string | Uint8Array): Uint8Array => { 11 | if (data instanceof Uint8Array) return data; 12 | if (isHex(data)) { 13 | return hexToU8a(data); 14 | } 15 | throw new Error(`can not hash ${data}`); 16 | }, 17 | 'string', 18 | 'Bytes', 19 | DataTypes.BLOB 20 | ); 21 | -------------------------------------------------------------------------------- /packages/utils/src/types/supported/Date.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2020-2024 SubQuery Pte Ltd authors & contributors 2 | // SPDX-License-Identifier: GPL-3.0 3 | 4 | import assert from 'assert'; 5 | import {numberToU8a} from '@polkadot/util'; 6 | import {TypeClass} from '../TypeClass'; 7 | 8 | export const DateObj = new TypeClass( 9 | 'Date', 10 | (data: Date): Uint8Array => { 11 | assert(data instanceof Date, `can not hash ${data}, expect instance of Date`); 12 | return numberToU8a(data.getTime()); 13 | }, 14 | 'Date', 15 | 'Date', 16 | 'timestamp' 17 | ); 18 | -------------------------------------------------------------------------------- /packages/utils/src/types/supported/Float.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2020-2024 SubQuery Pte Ltd authors & contributors 2 | // SPDX-License-Identifier: GPL-3.0 3 | 4 | import {DataTypes} from '@subql/x-sequelize'; 5 | import {TypeClass} from '../TypeClass'; 6 | 7 | export const Float = new TypeClass( 8 | 'Float', 9 | (data: number): Uint8Array => { 10 | //TODO, check if this is proper way to handle float 11 | return Buffer.from(data.toString()); 12 | }, 13 | 'number', 14 | 'Float', 15 | DataTypes.FLOAT 16 | ); 17 | -------------------------------------------------------------------------------- /packages/utils/src/types/supported/ID.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2020-2024 SubQuery Pte Ltd authors & contributors 2 | // SPDX-License-Identifier: GPL-3.0 3 | 4 | import {TypeClass} from '../TypeClass'; 5 | 6 | export const ID = new TypeClass( 7 | 'ID', 8 | (data: any): Uint8Array => { 9 | return Buffer.from(data); 10 | }, 11 | 'string', 12 | 'ID', 13 | 'text' 14 | ); 15 | -------------------------------------------------------------------------------- /packages/utils/src/types/supported/Int.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2020-2024 SubQuery Pte Ltd authors & contributors 2 | // SPDX-License-Identifier: GPL-3.0 3 | 4 | import {numberToU8a} from '@polkadot/util'; 5 | import {TypeClass} from '../TypeClass'; 6 | import {wrappedNumToU8a} from '../u8aUtils'; 7 | 8 | export const Int = new TypeClass( 9 | 'Int', 10 | (data: number): Uint8Array => { 11 | return wrappedNumToU8a(data); 12 | }, 13 | 'number', 14 | 'Int', 15 | 'integer' 16 | ); 17 | -------------------------------------------------------------------------------- /packages/utils/src/types/supported/Json.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2020-2024 SubQuery Pte Ltd authors & contributors 2 | // SPDX-License-Identifier: GPL-3.0 3 | 4 | import {DataTypes} from '@subql/x-sequelize'; 5 | import {TypeClass} from '../TypeClass'; 6 | 7 | export const Json = new TypeClass( 8 | 'Json', 9 | (data: unknown): Uint8Array => { 10 | return Buffer.from(JSON.stringify(data)); 11 | }, 12 | undefined, 13 | undefined, 14 | DataTypes.JSONB 15 | ); 16 | -------------------------------------------------------------------------------- /packages/utils/src/types/supported/String.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2020-2024 SubQuery Pte Ltd authors & contributors 2 | // SPDX-License-Identifier: GPL-3.0 3 | 4 | import {TypeClass} from '../TypeClass'; 5 | 6 | export const String = new TypeClass( 7 | 'String', 8 | (data: string): Uint8Array => { 9 | return Buffer.from(data); 10 | }, 11 | 'string', 12 | 'String', 13 | 'text' 14 | ); 15 | -------------------------------------------------------------------------------- /packages/utils/src/types/supported/index.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2020-2024 SubQuery Pte Ltd authors & contributors 2 | // SPDX-License-Identifier: GPL-3.0 3 | 4 | export * from './BigInt'; 5 | export * from './Boolean'; 6 | export * from './Bytes'; 7 | export * from './Date'; 8 | export * from './Float'; 9 | export * from './ID'; 10 | export * from './Int'; 11 | export * from './String'; 12 | export * from './Json'; 13 | -------------------------------------------------------------------------------- /packages/utils/src/types/u8aUtils.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2020-2024 SubQuery Pte Ltd authors & contributors 2 | // SPDX-License-Identifier: GPL-3.0 3 | 4 | import {numberToU8a, u8aConcat} from '@polkadot/util'; 5 | 6 | /** 7 | * Due to current polkadotjs `numberToU8a` not support negative number, 8 | * The helper method used to convert negative to a uint8Array 9 | * 10 | * @param byteArray 11 | */ 12 | 13 | export function wrappedNumToU8a(num: number) { 14 | if (num >= 0) { 15 | return numberToU8a(num); 16 | } 17 | return u8aConcat(new Uint8Array([0]), numberToU8a(Math.abs(num))); 18 | } 19 | -------------------------------------------------------------------------------- /packages/utils/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.json", 3 | "compilerOptions": { 4 | "target": "es2017", 5 | "sourceMap": true, 6 | "tsBuildInfoFile": "dist/.tsbuildinfo", 7 | "rootDir": "src", 8 | "outDir": "./dist", 9 | "noImplicitAny": true, 10 | "noImplicitThis": true 11 | }, 12 | "references": [{"path": "../types"}], 13 | "include": ["src/**/*"] 14 | } 15 | -------------------------------------------------------------------------------- /scripts/build.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | set -e 3 | 4 | apk add --no-cache jq 5 | npm install -g --force yarn@latest 6 | cd "$1" 7 | 8 | # Modifies the package.json to replace "workspace:*" versions with actual versions 9 | jq -r '.dependencies | to_entries[] | select(.value == "workspace:*") | .key' package.json | while read -r dep; do 10 | directory=$(jq --arg dep "$dep" -r '.compilerOptions.paths[$dep][0]' ../../tsconfig.json | cut -d'/' -f 2) 11 | version=$(jq --arg directory "$directory" -r '.version' ../"$directory"/package.json) 12 | if [ "$version" != null ]; then 13 | jq --arg dep "$dep" --arg version "$version" -r '.dependencies[$dep] = $version' package.json > package.tmp.json && mv package.tmp.json package.json 14 | fi 15 | done 16 | 17 | yarn pack --filename app.tgz 18 | rm -rf /root/.npm /root/.cache 19 | -------------------------------------------------------------------------------- /test/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM node:lts-bullseye 2 | WORKDIR /workdir 3 | 4 | COPY . . 5 | RUN yarn 6 | -------------------------------------------------------------------------------- /test/docker-compose.yaml: -------------------------------------------------------------------------------- 1 | version: '3' 2 | 3 | services: 4 | postgres: 5 | image: postgres:16-alpine 6 | build: 7 | context: . 8 | dockerfile: pg-Dockerfile 9 | ports: 10 | - 5432:5432 11 | environment: 12 | POSTGRES_PASSWORD: postgres 13 | 14 | test: 15 | build: 16 | context: .. 17 | dockerfile: test/Dockerfile 18 | volumes: 19 | - ../coverage:/workdir/coverage 20 | depends_on: 21 | - "postgres" 22 | environment: 23 | DB_USER: postgres 24 | DB_PASS: postgres 25 | DB_DATABASE: postgres 26 | DB_HOST: postgres 27 | DB_POST: 5432 28 | SUBQL_ACCESS_TOKEN: ${SUBQL_ACCESS_TOKEN} 29 | SUBQL_ACCESS_TOKEN_TEST: ${SUBQL_ACCESS_TOKEN_TEST} 30 | SUBQL_ORG_TEST: ${SUBQL_ORG_TEST} 31 | command: 32 | - yarn 33 | - test:all 34 | 35 | -------------------------------------------------------------------------------- /test/jest-setup.ts: -------------------------------------------------------------------------------- 1 | import 'reflect-metadata'; 2 | import 'regenerator-runtime/runtime'; 3 | 4 | // Causes the logger to be init 5 | (global as any).__TEST__ = true; 6 | -------------------------------------------------------------------------------- /test/load-extensions.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | psql -v ON_ERROR_STOP=1 --username "$POSTGRES_USER" <