├── .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-cosmos-docker.yml │ ├── pr.yml │ ├── prerelease.yml │ ├── release.yml │ ├── scripts │ ├── benchmark │ │ ├── Dockerfile │ │ ├── benchmarking.sh │ │ ├── cleanHistory.sh │ │ └── queryMeta.sh │ └── nodeVersion.sh │ └── sync-deps.yml ├── .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.1.1.cjs └── versions │ ├── 015eb803.yml │ ├── 04782ba3.yml │ ├── 0539ff9a.yml │ ├── 07e87407.yml │ ├── 0865e76b.yml │ ├── 095f496a.yml │ ├── 0a5ac396.yml │ ├── 0b0bc2a3.yml │ ├── 0ea17037.yml │ ├── 126538f3.yml │ ├── 127114e3.yml │ ├── 12c6b05e.yml │ ├── 168bce8e.yml │ ├── 17e47b29.yml │ ├── 1a63fd33.yml │ ├── 1cbeddd1.yml │ ├── 1ef5011d.yml │ ├── 2070419d.yml │ ├── 2c381cc7.yml │ ├── 2cd2922c.yml │ ├── 2ed81f15.yml │ ├── 305fc6e5.yml │ ├── 314c9df8.yml │ ├── 34b66995.yml │ ├── 358bef74.yml │ ├── 3775e704.yml │ ├── 380bbfa5.yml │ ├── 39055c5f.yml │ ├── 3c9a5976.yml │ ├── 3fe26997.yml │ ├── 43264fb5.yml │ ├── 45a7e688.yml │ ├── 49ba0b8a.yml │ ├── 4c8f6b9e.yml │ ├── 4d2b53f8.yml │ ├── 508f0d31.yml │ ├── 5428c933.yml │ ├── 54610e58.yml │ ├── 55192620.yml │ ├── 556bcbb5.yml │ ├── 57d7cbb2.yml │ ├── 5aa857c9.yml │ ├── 5dc26b93.yml │ ├── 689ddd69.yml │ ├── 6ab57fdd.yml │ ├── 6dc54c3b.yml │ ├── 71ee6ef5.yml │ ├── 724c556a.yml │ ├── 789dc02c.yml │ ├── 7ee34992.yml │ ├── 849df7f0.yml │ ├── 85c1d7a2.yml │ ├── 8685cba7.yml │ ├── 8e5687b3.yml │ ├── 92eab379.yml │ ├── 93d1bae2.yml │ ├── 95765d7c.yml │ ├── 95bd9aab.yml │ ├── 95f28132.yml │ ├── 97e9ad08.yml │ ├── 995a4638.yml │ ├── 9996cf4f.yml │ ├── 9ea41ba3.yml │ ├── a097e0b4.yml │ ├── a0dfddf3.yml │ ├── a1d4d641.yml │ ├── a4c7f709.yml │ ├── a5e2b500.yml │ ├── aca7ef93.yml │ ├── b4f1dd5b.yml │ ├── b678ab12.yml │ ├── b87a54e8.yml │ ├── b97fc139.yml │ ├── bb35b101.yml │ ├── bf08dae0.yml │ ├── bf1cb0a9.yml │ ├── c1ecb61b.yml │ ├── c38440c9.yml │ ├── c3d3784c.yml │ ├── c731748c.yml │ ├── c92c26a5.yml │ ├── cc432472.yml │ ├── d076915b.yml │ ├── d1167efd.yml │ ├── d5d3ed34.yml │ ├── d9a5c6c9.yml │ ├── dc0c537d.yml │ ├── de6e7b4b.yml │ ├── def48634.yml │ ├── e07e476d.yml │ ├── e099fb72.yml │ ├── e25fd62f.yml │ ├── e417fa20.yml │ ├── e4ebbcb3.yml │ ├── e594c6ad.yml │ ├── e7a88440.yml │ ├── e9855f18.yml │ ├── eaa6e623.yml │ ├── eb8d476b.yml │ ├── ed86c35b.yml │ ├── eec56ca6.yml │ ├── f13a382e.yml │ ├── f46ddc06.yml │ ├── f6577513.yml │ ├── f697f53e.yml │ └── f7152985.yml ├── .yarnrc.yml ├── CODE_OF_CONDUCT.md ├── LICENSE ├── README.md ├── babel.config.js ├── contributing.md ├── crowdin.yaml ├── deploy ├── k8s │ ├── README.md │ └── deploy.yaml └── logging_debug.png ├── jest.config.js ├── package.json ├── packages ├── common-cosmos │ ├── CHANGELOG.md │ ├── LICENSE │ ├── package.json │ ├── src │ │ ├── codegen │ │ │ ├── codegen-controller.spec.ts │ │ │ ├── codegen-controller.ts │ │ │ ├── constants.ts │ │ │ ├── index.ts │ │ │ └── util.ts │ │ ├── index.ts │ │ └── project │ │ │ ├── index.ts │ │ │ ├── load.ts │ │ │ ├── models.ts │ │ │ ├── project.spec.ts │ │ │ ├── types.ts │ │ │ ├── utils.ts │ │ │ └── versioned │ │ │ ├── ProjectManifestVersioned.ts │ │ │ ├── index.ts │ │ │ └── v1_0_0 │ │ │ ├── index.ts │ │ │ └── model.ts │ ├── templates │ │ ├── cosmwasm-interfaces.ts.ejs │ │ └── proto-interface.ts.ejs │ ├── test │ │ ├── project_1.0.0.yaml │ │ ├── project_1.0.0_bad_runner.yaml │ │ └── protoTest1 │ │ │ ├── bad-abi-cosmos-project.yaml │ │ │ ├── bad-chaintypes-project.yaml │ │ │ ├── cosmwasm-contract │ │ │ └── cw20 │ │ │ │ └── schema │ │ │ │ └── cw20.json │ │ │ ├── cosmwasm-project.yaml │ │ │ ├── project.yaml │ │ │ └── proto │ │ │ ├── cosmos │ │ │ └── base │ │ │ │ └── v1beta1 │ │ │ │ └── coin.proto │ │ │ └── osmosis │ │ │ ├── gamm │ │ │ └── v1beta1 │ │ │ │ └── tx.proto │ │ │ └── poolmanager │ │ │ └── v1beta1 │ │ │ └── swap_route.proto │ └── tsconfig.json ├── node │ ├── .gitignore │ ├── .prettierrc │ ├── 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 │ │ ├── blockchain.service.spec.ts │ │ ├── blockchain.service.ts │ │ ├── configure │ │ │ ├── NodeConfig.ts │ │ │ ├── SubqueryProject.ts │ │ │ └── configure.module.ts │ │ ├── indexer │ │ │ ├── api.service.test.ts │ │ │ ├── api.service.ts │ │ │ ├── cosmosClient.connection.ts │ │ │ ├── dictionary │ │ │ │ ├── dictionary.service.ts │ │ │ │ └── v1 │ │ │ │ │ ├── dictionaryV1.spec.ts │ │ │ │ │ ├── dictionaryV1.ts │ │ │ │ │ └── index.ts │ │ │ ├── fetch.module.ts │ │ │ ├── indexer.manager.ts │ │ │ ├── rpc-clients │ │ │ │ ├── HttpClient.ts │ │ │ │ ├── RpcClient.ts │ │ │ │ ├── WebsocketClient.ts │ │ │ │ └── index.ts │ │ │ ├── types.ts │ │ │ └── worker │ │ │ │ ├── worker-fetch.module.ts │ │ │ │ ├── worker.module.ts │ │ │ │ ├── worker.service.ts │ │ │ │ └── worker.ts │ │ ├── init.ts │ │ ├── main.ts │ │ ├── subcommands │ │ │ ├── forceClean.init.ts │ │ │ ├── forceClean.module.ts │ │ │ ├── reindex.init.ts │ │ │ ├── reindex.module.spec.ts │ │ │ ├── reindex.module.ts │ │ │ ├── testing.init.ts │ │ │ ├── testing.module.spec.ts │ │ │ ├── testing.module.ts │ │ │ └── testing.service.ts │ │ ├── utils │ │ │ ├── cosmos.spec.ts │ │ │ ├── cosmos.ts │ │ │ ├── kyve │ │ │ │ ├── kyve.spec.ts │ │ │ │ ├── kyve.ts │ │ │ │ └── kyveTypes.ts │ │ │ ├── project.spec.ts │ │ │ └── project.ts │ │ └── yargs.ts │ ├── test │ │ ├── jsonfy.js │ │ ├── kyve_block │ │ │ └── block_4326863.json │ │ └── projectFixture │ │ │ ├── template-v1.0.0 │ │ │ └── package.json │ │ │ └── v1.0.0 │ │ │ ├── dist │ │ │ └── index.js │ │ │ ├── package.json │ │ │ ├── project.yaml │ │ │ └── schema.graphql │ ├── tsconfig.build.json │ └── tsconfig.json └── types │ ├── CHANGELOG.md │ ├── LICENSE │ ├── package.json │ ├── src │ ├── global.ts │ ├── index.ts │ ├── interfaces.ts │ ├── modular.ts │ └── project.ts │ └── tsconfig.json ├── scripts ├── build.sh └── update_versions.sh ├── test ├── Dockerfile ├── docker-compose.yaml └── jest-setup.ts ├── 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 -------------------------------------------------------------------------------- /.eslintrc.js: -------------------------------------------------------------------------------- 1 | /* 2 | 👋 Hi! This file was autogenerated by tslint-to-eslint-config. 3 | https://github.com/typescript-eslint/tslint-to-eslint-config 4 | 5 | It represents the closest reasonable ESLint configuration to this 6 | project's original TSLint configuration. 7 | 8 | We recommend eventually switching this configuration to extend from 9 | the recommended rulesets in typescript-eslint. 10 | https://github.com/typescript-eslint/tslint-to-eslint-config/blob/master/docs/FAQs.md 11 | 12 | Happy linting! 💖 13 | */ 14 | module.exports = { 15 | env: { 16 | node: true, 17 | jest: true, 18 | }, 19 | parser: '@typescript-eslint/parser', 20 | parserOptions: { 21 | tsconfigRootDir: __dirname, 22 | sourceType: 'module', 23 | project: ['./tsconfig.json', './packages/*/tsconfig.json'], 24 | warnOnUnsupportedTypeScriptVersion: false, 25 | EXPERIMENTAL_useSourceOfProjectReferenceRedirect: true, 26 | }, 27 | plugins: ['@typescript-eslint', 'header', 'import', 'sort-destructure-keys'], 28 | extends: [ 29 | 'eslint:recommended', 30 | 'plugin:@typescript-eslint/recommended', 31 | 'plugin:@typescript-eslint/recommended-requiring-type-checking', 32 | 'plugin:jest/recommended', 33 | ], 34 | rules: { 35 | // rules turned off in upstream project (also required when recommended-requiring-type-checking is extended) 36 | '@typescript-eslint/explicit-function-return-type': 'off', 37 | '@typescript-eslint/no-unsafe-argument': 'off', 38 | '@typescript-eslint/no-unsafe-assignment': 'off', 39 | '@typescript-eslint/no-unsafe-call': 'off', 40 | '@typescript-eslint/no-unsafe-member-access': 'off', 41 | '@typescript-eslint/no-unsafe-return': 'off', 42 | '@typescript-eslint/no-unnecessary-type-assertion': 'off', 43 | '@typescript-eslint/restrict-plus-operands': 'off', 44 | '@typescript-eslint/restrict-template-expressions': 'off', 45 | // Support recommended-requiring-type-checking (specific to this project) set them as warning 46 | '@typescript-eslint/unbound-method': 'warn', 47 | '@typescript-eslint/no-floating-promises': 'warn', 48 | // Making affected recommended types as warning for now 49 | '@typescript-eslint/explicit-module-boundary-types': 'warn', 50 | '@typescript-eslint/no-explicit-any': 'warn', 51 | '@typescript-eslint/no-var-requires': 'warn', 52 | '@typescript-eslint/no-unused-vars': 'warn', 53 | '@typescript-eslint/ban-ts-comment': 'warn', 54 | '@typescript-eslint/ban-types': 'warn', 55 | '@typescript-eslint/no-inferrable-types': 'warn', 56 | '@typescript-eslint/await-thenable': 'error', 57 | '@typescript-eslint/dot-notation': 'error', 58 | '@typescript-eslint/explicit-member-accessibility': [ 59 | 'error', 60 | { 61 | accessibility: 'no-public', 62 | }, 63 | ], 64 | '@typescript-eslint/no-namespace': ['error', {allowDeclarations: true}], 65 | // "@typescript-eslint/member-ordering": "error", 66 | // "@typescript-eslint/naming-convention": "error", 67 | // "@typescript-eslint/no-param-reassign": "error", 68 | '@typescript-eslint/promise-function-async': ['error', {checkArrowFunctions: false}], 69 | // "arrow-body-style": "error", 70 | complexity: ['error', 20], 71 | curly: ['error', 'multi-line'], 72 | 'default-case': 'error', 73 | eqeqeq: ['error', 'always'], 74 | 'import/no-extraneous-dependencies': 'off', 75 | 'import/order': [ 76 | 'error', 77 | { 78 | alphabetize: { 79 | order: 'asc' /* sort in ascending order. Options: ['ignore', 'asc', 'desc'] */, 80 | caseInsensitive: true /* ignore case. Options: [true, false] */, 81 | }, 82 | }, 83 | ], 84 | 'header/header': [ 85 | 2, 86 | 'line', 87 | [ 88 | //// Copyright 2020-2025 SubQuery Pte Ltd authors & contributors 89 | {pattern: ' Copyright \\d{4}(-\\d{4})? SubQuery Pte Ltd authors & contributors'}, 90 | ' SPDX-License-Identifier: GPL-3.0', 91 | ], 92 | 2, 93 | ], 94 | 'sort-destructure-keys/sort-destructure-keys': [ 95 | 2, 96 | { 97 | caseSensitive: true, 98 | }, 99 | ], 100 | 'no-console': 'off', 101 | 'no-duplicate-imports': 'error', 102 | // "no-magic-numbers": "error", 103 | 'no-return-await': 'error', 104 | 'no-undef-init': 'error', 105 | 'prefer-template': 'error', 106 | 'use-isnan': 'error', 107 | }, 108 | settings: { 109 | 'import/extensions': ['.js', '.ts'], 110 | 'import/parsers': { 111 | '@typescript-eslint/parser': ['.ts', '.tsx'], 112 | }, 113 | }, 114 | }; 115 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | ### Prerequisites 2 | 3 | * [ ] Are you running the latest version(s)? 4 | * [ ] Have you searched the [documentation for your issue](https://academy.subquery.network/)? 5 | * [ ] Did you search for an existing issue or pull request? 6 | 7 | ### Description 8 | 9 | [Description of the bug or feature] 10 | 11 | ### Details 12 | 13 | These details can help to reproduce the environment the issue is occurring 14 | 15 | **Local Environment:** [You can get this information from executing `subql version`.] 16 | **Query Version:** [What is the version of the query service?] 17 | **Indexer Version:** [What is the version of the indexer service?] 18 | **Network Details:** 19 | * [Network] 20 | * [Block height, a block height where the issue is happening] 21 | * [Dictionary endpoint, if used] 22 | 23 | ### Steps to Reproduce 24 | 25 | 1. [First Step] 26 | 2. [Second Step] 27 | 3. [and so on...] 28 | 29 | **Example project:** [A link to a minimal example that can reproduce the issue] 30 | 31 | **Expected behavior:** [What you expected to happen] 32 | 33 | **Actual behavior:** [What actually happened] 34 | 35 | 36 | ### Any other information 37 | 38 | Is there any other information you would like to add? 39 | -------------------------------------------------------------------------------- /.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/actions/create-release/gh-release-script.js: -------------------------------------------------------------------------------- 1 | const fs = require('fs'); 2 | const { exit } = require('process'); 3 | const core = require('@actions/core'); 4 | const { request } = require('@octokit/request'); 5 | 6 | const myArgs = process.argv.slice(2); 7 | 8 | const pJson = require(`${myArgs[0]}/package.json`) 9 | 10 | const version = pJson.version; 11 | const repoName = pJson.name; 12 | 13 | const packageName = repoName.split('/'); 14 | 15 | function checkForBetaVersion(version) { 16 | if (version.includes('-')){ 17 | exit(0); //skip this package but continue trying to release others 18 | } 19 | } 20 | 21 | function gatherReleaseInfo(logPath) { 22 | const changeLogs = fs.readFileSync(logPath, 'utf8'); 23 | const regex = /## \[([0-9]+(\.[0-9]+)+)] - [0-9]{4}-[0-9]{2}-[0-9]{2}/i; 24 | 25 | let lines = changeLogs.split(/\n/); 26 | let foundChangelog = false; 27 | let releaseInfo = ''; 28 | let i = 0; 29 | 30 | for(let j = 0; j < lines.length; j++){ 31 | if(lines[j].includes(`[${version}]`)){ 32 | i = j; 33 | j = lines.length; 34 | foundChangelog = true; 35 | } 36 | } 37 | 38 | lines = lines.slice(i); 39 | 40 | if(foundChangelog){ 41 | for(let j = 0; j < lines.length; j++){ 42 | if(j == 0){ 43 | releaseInfo += `${lines[j]}`+ '\n'; 44 | continue; 45 | } 46 | 47 | if(!regex.test(lines[j])){ 48 | releaseInfo += `${lines[j]}`+ '\n'; 49 | } else { 50 | j = lines.length; 51 | } 52 | } 53 | } 54 | 55 | if(releaseInfo === ''){ 56 | core.setFailed("No release info found, either missing in changelog or changelog is formatted incorrectly") 57 | } 58 | 59 | console.log("Gathered release info...") 60 | return releaseInfo; 61 | } 62 | 63 | async function publishRelease(releaseInfo) { 64 | 65 | await request('POST /repos/{owner}/{repo}/releases', { 66 | headers: { 67 | authorization: `token ${process.env.REPO_TOKEN}`, 68 | }, 69 | owner: 'subquery', 70 | name: `[${version}] ${repoName}`, 71 | repo: 'subql-cosmos', 72 | tag_name: `${packageName[1]}/${version}`, 73 | target_commitish: `${myArgs[1]}`, 74 | body: releaseInfo 75 | }).catch( err => { 76 | core.setFailed(err) 77 | }) 78 | 79 | console.log("Release Created..."); 80 | } 81 | 82 | checkForBetaVersion(version); 83 | 84 | const releaseInfo = gatherReleaseInfo(`${myArgs[0]}/CHANGELOG.md`); 85 | 86 | publishRelease(releaseInfo); 87 | -------------------------------------------------------------------------------- /.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/gh-release.yml: -------------------------------------------------------------------------------- 1 | name: "Github Release" 2 | on: 3 | workflow_dispatch: 4 | 5 | jobs: 6 | github-release: 7 | name: github-release 8 | runs-on: ubuntu-latest 9 | steps: 10 | #Check out 11 | - uses: actions/checkout@v4 12 | with: 13 | fetch-depth: 100 14 | 15 | - name: Setup Node.js environment 16 | uses: actions/setup-node@v4 17 | with: 18 | node-version: lts/* 19 | 20 | - run: yarn install 21 | 22 | #Create github releases 23 | - uses: ./.github/actions/create-release 24 | with: 25 | package-path: packages/common-cosmos 26 | repo-token: ${{ secrets.REPO_TOKEN }} 27 | 28 | - uses: ./.github/actions/create-release 29 | with: 30 | package-path: packages/node 31 | repo-token: ${{ secrets.REPO_TOKEN }} 32 | 33 | - uses: ./.github/actions/create-release 34 | with: 35 | package-path: packages/types 36 | repo-token: ${{ secrets.REPO_TOKEN }} 37 | -------------------------------------------------------------------------------- /.github/workflows/node-cosmos-docker.yml: -------------------------------------------------------------------------------- 1 | name: "Node-to-docker" 2 | on: 3 | release: 4 | types: 5 | - published 6 | workflow_dispatch: 7 | inputs: 8 | isLatest: 9 | description: 'Add latest tag' 10 | default: 'true' 11 | required: true 12 | 13 | jobs: 14 | check: 15 | runs-on: ubuntu-latest 16 | outputs: 17 | changes_found: ${{ steps.check_changes.outputs.changes_found }} 18 | steps: 19 | - uses: actions/checkout@v4 20 | with: 21 | fetch-depth: 2 22 | 23 | - name: Check for package changes and commit message 24 | id: check_changes 25 | run: | 26 | if [[ "${{ github.event_name }}" == "release" ]] 27 | then 28 | TAG_NAME=${GITHUB_REF#refs/tags/} 29 | if [[ $TAG_NAME == "node-cosmos/"* ]] 30 | then 31 | echo "changes_found=true" >> "$GITHUB_OUTPUT" 32 | else 33 | echo "changes_found=false" >> "$GITHUB_OUTPUT" 34 | fi 35 | else 36 | echo "changes_found=true" >> "$GITHUB_OUTPUT" 37 | fi 38 | node-build-push-docker: 39 | needs: check 40 | if: needs.check.outputs.changes_found == 'true' 41 | runs-on: ubuntu-latest 42 | steps: 43 | - uses: actions/checkout@v4 44 | with: 45 | fetch-depth: 100 46 | token: ${{ secrets.REPO_TOKEN }} 47 | 48 | - name: Set up QEMU 49 | uses: docker/setup-qemu-action@v3 50 | 51 | - name: Set up Docker Buildx 52 | uses: docker/setup-buildx-action@v3 53 | 54 | - name: Login to DockerHub 55 | uses: docker/login-action@v3 56 | with: 57 | username: onfinality 58 | password: ${{ secrets.DOCKERHUB_TOKEN }} 59 | 60 | ## node 61 | - name: Get updated node version 62 | id: get-node-version 63 | run: | 64 | sh .github/workflows/scripts/nodeVersion.sh 65 | 66 | - run: yarn 67 | - name: build 68 | run: yarn build 69 | 70 | - name: Build and push 71 | if: github.event_name == 'workflow_dispatch' && github.event.inputs.isLatest == 'false' 72 | uses: docker/build-push-action@v2 73 | with: 74 | context: . 75 | push: true 76 | platforms: arm64,amd64 77 | file: ./packages/node/Dockerfile 78 | tags: onfinality/subql-node-cosmos:v${{ steps.get-node-version.outputs.NODE_VERSION }} 79 | build-args: RELEASE_VERSION=${{ steps.get-node-version.outputs.NODE_VERSION }} 80 | 81 | - name: Build and push 82 | if: github.event_name == 'release' || (github.event_name == 'workflow_dispatch' && github.event.inputs.isLatest == 'true') 83 | uses: docker/build-push-action@v2 84 | with: 85 | context: . 86 | push: true 87 | platforms: arm64,amd64 88 | file: ./packages/node/Dockerfile 89 | tags: onfinality/subql-node-cosmos:v${{ steps.get-node-version.outputs.NODE_VERSION }},onfinality/subql-node-cosmos:latest 90 | build-args: RELEASE_VERSION=${{ steps.get-node-version.outputs.NODE_VERSION }} 91 | 92 | - name: Image digest 93 | run: echo ${{ steps.docker_build.outputs.digest }} 94 | 95 | 96 | node-build-push-docker-subquery: 97 | needs: check 98 | if: needs.check.outputs.changes_found == 'true' 99 | runs-on: ubuntu-latest 100 | steps: 101 | - uses: actions/checkout@v4 102 | with: 103 | fetch-depth: 100 104 | token: ${{ secrets.REPO_TOKEN }} 105 | 106 | - name: Set up QEMU 107 | uses: docker/setup-qemu-action@v3 108 | 109 | - name: Set up Docker Buildx 110 | uses: docker/setup-buildx-action@v3 111 | 112 | - name: Login to DockerHub 113 | uses: docker/login-action@v3 114 | with: 115 | username: subquerynetwork 116 | password: ${{ secrets.SQ_DOCKERHUB_TOKEN }} 117 | 118 | ## node 119 | - name: Get updated node version 120 | id: get-node-version 121 | run: | 122 | sh .github/workflows/scripts/nodeVersion.sh 123 | 124 | - run: yarn 125 | - name: build 126 | run: yarn build 127 | 128 | - name: Build and push 129 | if: github.event_name == 'workflow_dispatch' && github.event.inputs.isLatest == 'false' 130 | uses: docker/build-push-action@v2 131 | with: 132 | context: . 133 | push: true 134 | platforms: arm64,amd64 135 | file: ./packages/node/Dockerfile 136 | tags: subquerynetwork/subql-node-cosmos:v${{ steps.get-node-version.outputs.NODE_VERSION }}, 137 | build-args: RELEASE_VERSION=${{ steps.get-node-version.outputs.NODE_VERSION }} 138 | 139 | - name: Build and push 140 | if: github.event_name == 'release' || (github.event_name == 'workflow_dispatch' && github.event.inputs.isLatest == 'true') 141 | uses: docker/build-push-action@v2 142 | with: 143 | context: . 144 | push: true 145 | platforms: arm64,amd64 146 | file: ./packages/node/Dockerfile 147 | tags: subquerynetwork/subql-node-cosmos:v${{ steps.get-node-version.outputs.NODE_VERSION }},subquerynetwork/subql-node-cosmos:latest 148 | build-args: RELEASE_VERSION=${{ steps.get-node-version.outputs.NODE_VERSION }} 149 | 150 | - name: Image digest 151 | run: echo ${{ steps.docker_build.outputs.digest }} 152 | 153 | 154 | 155 | -------------------------------------------------------------------------------- /.github/workflows/pr.yml: -------------------------------------------------------------------------------- 1 | name: PR 2 | on: 3 | pull_request: 4 | paths-ignore: 5 | - ".github/workflows/**" 6 | jobs: 7 | code-style: 8 | name: code-style 9 | runs-on: ubuntu-latest 10 | env: 11 | SUBQL_ACCESS_TOKEN: ${{ secrets.SUBQL_ACCESS_TOKEN }} 12 | SUBQL_ACCESS_TOKEN_TEST: ${{ secrets.SUBQL_ACCESS_TOKEN_TEST }} 13 | SUBQL_ORG_TEST: ${{ secrets.SUBQL_ORG_TEST }} 14 | steps: 15 | - uses: actions/checkout@v3 16 | - name: Setup Node.js environment 17 | uses: actions/setup-node@v4 18 | with: 19 | node-version: lts/* 20 | - run: yarn 21 | - name: build 22 | run: yarn build 23 | - name: code-style check 24 | run: yarn pretty-quick --check --pattern 'packages/*/src/**/*' --branch origin/main 25 | - name: lint 26 | run: yarn lint 27 | 28 | coverage: 29 | name: Coverage report 30 | runs-on: ubuntu-latest 31 | services: 32 | postgres: 33 | image: postgres:16-alpine 34 | ports: 35 | - 5432:5432 36 | env: 37 | POSTGRES_PASSWORD: postgres 38 | options: >- 39 | --health-cmd pg_isready 40 | --health-interval 10s 41 | --health-timeout 5s 42 | --health-retries 5 43 | env: 44 | DB_USER: postgres 45 | DB_PASS: postgres 46 | DB_DATABASE: postgres 47 | DB_HOST: localhost 48 | DB_PORT: 5432 49 | steps: 50 | - uses: actions/checkout@v3 51 | 52 | - name: Use Node.js environment 53 | uses: actions/setup-node@v4 54 | with: 55 | node-version: lts/* 56 | 57 | - name: Installing dependencies 58 | run: yarn install 59 | 60 | - uses: artiomtr/jest-coverage-report-action@v2 61 | with: 62 | github-token: ${{ secrets.GITHUB_TOKEN }} 63 | skip-step: install 64 | working-directory: ${{ matrix.path }} 65 | test-script: yarn test-jest 66 | annotations: none 67 | -------------------------------------------------------------------------------- /.github/workflows/prerelease.yml: -------------------------------------------------------------------------------- 1 | name: "Prerelease" 2 | on: 3 | push: 4 | branches: 5 | - main 6 | paths-ignore: 7 | - ".github/workflows/**" 8 | 9 | concurrency: 10 | group: publish 11 | cancel-in-progress: false 12 | 13 | jobs: 14 | Bump-Prerelease-Publish: 15 | name: Bump-Prerelease-Publish 16 | if: "!startsWith(github.event.head_commit.message, '[SKIP CI]') && !startsWith(github.event.head_commit.message, '[release]') && github.repository == 'subquery/subql-cosmos'" 17 | runs-on: ubuntu-latest 18 | steps: 19 | - uses: actions/checkout@v4 20 | with: 21 | fetch-depth: 100 22 | token: ${{ secrets.REPO_TOKEN }} 23 | 24 | - name: Setup Node.js environment 25 | uses: actions/setup-node@v4 26 | with: 27 | node-version: lts/* 28 | 29 | - uses: marceloprado/has-changed-path@v1 30 | id: changed-types 31 | with: 32 | paths: packages/types 33 | 34 | - uses: marceloprado/has-changed-path@v1 35 | id: changed-common-cosmos 36 | with: 37 | paths: packages/common-cosmos 38 | 39 | - uses: marceloprado/has-changed-path@v1 40 | id: changed-node 41 | with: 42 | paths: packages/node 43 | 44 | - run: yarn 45 | 46 | - name: build 47 | run: yarn build 48 | 49 | #Add remove-stable-version 50 | - name: Bump types & deploy 51 | if: steps.changed-types.outputs.changed == 'true' 52 | uses: ./.github/actions/create-prerelease 53 | with: 54 | package-path: packages/types 55 | npm-token: ${{ secrets.NPM_TOKEN }} 56 | 57 | - name: Bump common cosmos & deploy 58 | if: steps.changed-common-cosmos.outputs.changed == 'true' 59 | uses: ./.github/actions/create-prerelease 60 | with: 61 | package-path: packages/common-cosmos 62 | npm-token: ${{ secrets.NPM_TOKEN }} 63 | 64 | - name: Bump node & deploy 65 | if: steps.changed-node.outputs.changed == 'true' 66 | uses: ./.github/actions/create-prerelease 67 | with: 68 | package-path: packages/node 69 | npm-token: ${{ secrets.NPM_TOKEN }} 70 | 71 | - name: Commit changes 72 | uses: EndBug/add-and-commit@v5 73 | with: 74 | message: "[SKIP CI] Prerelease" 75 | env: 76 | GITHUB_TOKEN: ${{ secrets.REPO_TOKEN }} 77 | -------------------------------------------------------------------------------- /.github/workflows/release.yml: -------------------------------------------------------------------------------- 1 | name: "Release" 2 | on: 3 | push: 4 | branches: 5 | - main 6 | paths-ignore: 7 | - ".github/workflows/**" 8 | workflow_dispatch: 9 | 10 | concurrency: 11 | # Same group as prerelease 12 | group: publish 13 | cancel-in-progress: false 14 | 15 | jobs: 16 | # This gets the commit message because workflow dispatch doesnt set: github.event.head_commit.message 17 | pre-ci: 18 | runs-on: ubuntu-latest 19 | timeout-minutes: 1 20 | outputs: 21 | commit-message: ${{ steps.step1.outputs.commit-message }} 22 | steps: 23 | - uses: actions/checkout@v4 24 | with: 25 | fetch-depth: 100 26 | 27 | # Get the commit message, workflow_dispatch doesn't contain it so we need to get it through git cli 28 | - id: step1 29 | run: | 30 | if [ -n "${{ github.event.head_commit.message }}" ] 31 | then 32 | echo "commit-message=${{ github.event.head_commit.message }}" | head -n 1 >> "$GITHUB_OUTPUT" 33 | else 34 | echo "commit-message=\"$(git log -1 --pretty=%B | head -n 1)\"" >> "$GITHUB_OUTPUT" 35 | fi 36 | 37 | Build-Publish: 38 | name: Build-Publish 39 | needs: pre-ci 40 | if: "!startsWith(needs.pre-ci.outputs.commit-message, '[SKIP CI]') && startsWith(needs.pre-ci.outputs.commit-message, '[release]') && github.repository == 'subquery/subql-cosmos'" 41 | runs-on: ubuntu-latest 42 | steps: 43 | #Check out 44 | - uses: actions/checkout@v4 45 | with: 46 | fetch-depth: 100 47 | 48 | - name: Setup Node.js environment 49 | uses: actions/setup-node@v4 50 | with: 51 | node-version: lts/* 52 | 53 | #Identify changes 54 | - uses: marceloprado/has-changed-path@v1 55 | id: changed-types 56 | with: 57 | paths: packages/types 58 | 59 | - uses: marceloprado/has-changed-path@v1 60 | id: changed-common-cosmos 61 | with: 62 | paths: packages/common-cosmos 63 | 64 | - uses: marceloprado/has-changed-path@v1 65 | id: changed-node 66 | with: 67 | paths: packages/node 68 | 69 | - run: yarn 70 | 71 | - name: build 72 | run: yarn build 73 | 74 | #Publish to npm and github releases 75 | - name: Publish Types 76 | if: steps.changed-types.outputs.changed == 'true' 77 | uses: ./.github/actions/create-release 78 | with: 79 | package-path: packages/types 80 | repo-token: ${{ secrets.REPO_TOKEN }} 81 | npm-token: ${{ secrets.NPM_TOKEN }} 82 | 83 | - name: Publish Common cosmos 84 | if: steps.changed-common-cosmos.outputs.changed == 'true' 85 | uses: ./.github/actions/create-release 86 | with: 87 | package-path: packages/common-cosmos 88 | repo-token: ${{ secrets.REPO_TOKEN }} 89 | npm-token: ${{ secrets.NPM_TOKEN }} 90 | 91 | - name: Publish Node 92 | if: steps.changed-node.outputs.changed == 'true' 93 | uses: ./.github/actions/create-release 94 | with: 95 | package-path: packages/node 96 | repo-token: ${{ secrets.REPO_TOKEN }} 97 | npm-token: ${{ secrets.NPM_TOKEN }} 98 | -------------------------------------------------------------------------------- /.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-cosmos@$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-cosmos -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 | sed "s|${input_endpoint}|***|g" > 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/benchmark/queryMeta.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | input_duration=$1 4 | 5 | # Function to convert time string to seconds 6 | t2s() { 7 | sed 's/d/*24*3600 +/g; s/h/*3600 +/g; s/m/*60 +/g; s/s/\+/g; s/+[ ]*$//g' <<< "$1" | bc 8 | } 9 | 10 | # Query the database and store the result in variables 11 | runner_node=$(psql -h postgres -d postgres -U postgres -c "SELECT value FROM app._metadata WHERE key = 'runnerNode';" | awk 'NR == 3 {print $1}' | tr -d '"') 12 | indexer_version=$(psql -h postgres -d postgres -U postgres -c "SELECT value FROM app._metadata WHERE key = 'indexerNodeVersion';" | awk 'NR == 3 {print $1}' | tr -d '"') 13 | start_height=$(psql -h postgres -d postgres -U postgres -c "SELECT value::integer FROM app._metadata WHERE key = 'startHeight';" | awk 'NR == 3 {print $1}') 14 | last_processed_height=$(psql -h postgres -d postgres -U postgres -c "SELECT value::integer FROM app._metadata WHERE key = 'lastProcessedHeight';" | awk 'NR == 3 {print $1}') 15 | total_height=$((last_processed_height-start_height+1)) 16 | time_in_seconds=$(t2s "$input_duration") 17 | bps=$(awk "BEGIN {printf \"%.2f\", $total_height / $time_in_seconds}") 18 | # Set outputs for subsequent steps 19 | echo "::set-output name=runner_node::$runner_node" 20 | echo "::set-output name=indexer_version::$indexer_version" 21 | echo "::set-output name=start_height::$start_height" 22 | echo "::set-output name=last_processed_height::$last_processed_height" 23 | echo "::set-output name=total_height::$total_height" 24 | echo "::set-output name=bps::$bps" 25 | -------------------------------------------------------------------------------- /.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/sync-deps.yml: -------------------------------------------------------------------------------- 1 | name: Sync Deps 2 | on: 3 | workflow_dispatch: 4 | repository_dispatch: 5 | types: [trigger-workflow] 6 | jobs: 7 | code-style: 8 | name: update deps 9 | runs-on: ubuntu-latest 10 | permissions: 11 | contents: write 12 | pull-requests: write 13 | env: 14 | SUBQL_ACCESS_TOKEN: ${{ secrets.SUBQL_ACCESS_TOKEN }} 15 | SUBQL_ACCESS_TOKEN_TEST: ${{ secrets.SUBQL_ACCESS_TOKEN_TEST }} 16 | SUBQL_ORG_TEST: ${{ secrets.SUBQL_ORG_TEST }} 17 | steps: 18 | - uses: actions/checkout@v4 19 | - name: Setup Node.js environment 20 | uses: actions/setup-node@v4 21 | with: 22 | node-version: lts/* 23 | - run: yarn 24 | 25 | # Update deps 26 | - name: Update types 27 | run: yarn --cwd ./packages/types add @subql/types-core 28 | - name: Update common 29 | run: yarn --cwd ./packages/common-cosmos add @subql/common 30 | - name: Update node 31 | run: yarn --cwd ./packages/node add @subql/common @subql/node-core 32 | 33 | - name: Determine branch name 34 | id: branch-name 35 | run: echo "branch=sync-$(date +'%Y%m%d')" >> $GITHUB_OUTPUT 36 | 37 | - uses: peter-evans/create-pull-request@v7 38 | with: 39 | branch: ${{ steps.branch-name.outputs.branch }} 40 | commit-message: "Update @subql deps" 41 | title: "Sync @subql dependencies" 42 | body-path: ".github/PULL_REQUEST_TEMPLATE.md" 43 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Created by .ignore support plugin (hsz.mobi) 2 | ### JetBrains template 3 | # Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio, WebStorm and Rider 4 | # Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839 5 | .idea 6 | 7 | # CMake 8 | cmake-build-*/ 9 | 10 | # Mongo Explorer plugin 11 | .idea/**/mongoSettings.xml 12 | 13 | # File-based project format 14 | *.iws 15 | 16 | # IntelliJ 17 | out/ 18 | 19 | # mpeltonen/sbt-idea plugin 20 | .idea_modules/ 21 | 22 | # JIRA plugin 23 | atlassian-ide-plugin.xml 24 | 25 | # Cursive Clojure plugin 26 | .idea/replstate.xml 27 | 28 | # Crashlytics plugin (for Android Studio and IntelliJ) 29 | com_crashlytics_export_strings.xml 30 | crashlytics.properties 31 | crashlytics-build.properties 32 | fabric.properties 33 | 34 | # Editor-based Rest Client 35 | .idea/httpRequests 36 | 37 | # Android studio 3.1+ serialized cache file 38 | .idea/caches/build_file_checksums.ser 39 | 40 | ### Node template 41 | # Logs 42 | logs 43 | *.log 44 | npm-debug.log* 45 | yarn-debug.log* 46 | yarn-error.log* 47 | lerna-debug.log* 48 | 49 | # Diagnostic reports (https://nodejs.org/api/report.html) 50 | report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json 51 | 52 | # Runtime data 53 | pids 54 | *.pid 55 | *.seed 56 | *.pid.lock 57 | 58 | # Directory for instrumented libs generated by jscoverage/JSCover 59 | lib-cov 60 | 61 | # Coverage directory used by tools like istanbul 62 | coverage 63 | *.lcov 64 | 65 | # nyc test coverage 66 | .nyc_output 67 | 68 | # Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files) 69 | .grunt 70 | 71 | # Bower dependency directory (https://bower.io/) 72 | bower_components 73 | 74 | # node-waf configuration 75 | .lock-wscript 76 | 77 | # Compiled binary addons (https://nodejs.org/api/addons.html) 78 | build/Release 79 | 80 | # Dependency directories 81 | node_modules/ 82 | jspm_packages/ 83 | 84 | # Snowpack dependency directory (https://snowpack.dev/) 85 | web_modules/ 86 | 87 | # TypeScript cache 88 | *.tsbuildinfo 89 | 90 | # Optional npm cache directory 91 | .npm 92 | 93 | # Optional eslint cache 94 | .eslintcache 95 | 96 | # Microbundle cache 97 | .rpt2_cache/ 98 | .rts2_cache_cjs/ 99 | .rts2_cache_es/ 100 | .rts2_cache_umd/ 101 | 102 | # Optional REPL history 103 | .node_repl_history 104 | 105 | # Output of 'npm pack' 106 | *.tgz 107 | 108 | # Yarn Integrity file 109 | .yarn-integrity 110 | 111 | # dotenv environment variables file 112 | .env 113 | .env.test 114 | 115 | # parcel-bundler cache (https://parceljs.org/) 116 | .cache 117 | .parcel-cache 118 | 119 | # Next.js build output 120 | .next 121 | out 122 | 123 | # Nuxt.js build / generate output 124 | .nuxt 125 | dist 126 | 127 | # Gatsby files 128 | .cache/ 129 | # Comment in the public line in if your project uses Gatsby and not Next.js 130 | # https://nextjs.org/blog/next-9-1#public-directory-support 131 | # public 132 | 133 | # vuepress build output 134 | .vuepress/dist 135 | .vuepress/.temp 136 | .vuepress/.caches 137 | docs/.vuepress/dist 138 | docs/.vuepress/.temp 139 | docs/.vuepress/.caches 140 | 141 | # Serverless directories 142 | .serverless/ 143 | 144 | # FuseBox cache 145 | .fusebox/ 146 | 147 | # DynamoDB Local files 148 | .dynamodb/ 149 | 150 | # TernJS port file 151 | .tern-port 152 | 153 | # Stores VSCode versions used for testing VSCode extensions 154 | .vscode-test 155 | 156 | # yarn v2 157 | .pnp.* 158 | .yarn/* 159 | !.yarn/patches 160 | !.yarn/plugins 161 | !.yarn/releases 162 | !.yarn/sdks 163 | !.yarn/versions 164 | 165 | ### VisualStudioCode template 166 | .vscode/* 167 | !.vscode/settings.json 168 | !.vscode/tasks.json 169 | !.vscode/launch.json 170 | !.vscode/extensions.json 171 | *.code-workspace 172 | 173 | # Local History for Visual Studio Code 174 | .history/ 175 | 176 | #package-lock.json 177 | package-lock.json 178 | 179 | .data 180 | lib 181 | 182 | .DS_Store 183 | -------------------------------------------------------------------------------- /.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 | *.proto -------------------------------------------------------------------------------- /.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "printWidth": 120, 3 | "trailingComma": "es5", 4 | "tabWidth": 2, 5 | "singleQuote": true, 6 | "bracketSpacing": false 7 | } 8 | -------------------------------------------------------------------------------- /.yarn/versions/015eb803.yml: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/subquery/subql-cosmos/ccdfe23be59fcd59ab44bb6faf950ca655341ee9/.yarn/versions/015eb803.yml -------------------------------------------------------------------------------- /.yarn/versions/04782ba3.yml: -------------------------------------------------------------------------------- 1 | undecided: 2 | - "@subql/common-cosmos" 3 | - "@subql/types-cosmos" 4 | -------------------------------------------------------------------------------- /.yarn/versions/0539ff9a.yml: -------------------------------------------------------------------------------- 1 | undecided: 2 | - "@subql/common-cosmos" 3 | - "@subql/types-cosmos" 4 | -------------------------------------------------------------------------------- /.yarn/versions/07e87407.yml: -------------------------------------------------------------------------------- 1 | undecided: 2 | - "@subql/common-cosmos" 3 | - "@subql/node-cosmos" 4 | -------------------------------------------------------------------------------- /.yarn/versions/0865e76b.yml: -------------------------------------------------------------------------------- 1 | undecided: 2 | - "@subql/common-cosmos" 3 | -------------------------------------------------------------------------------- /.yarn/versions/095f496a.yml: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/subquery/subql-cosmos/ccdfe23be59fcd59ab44bb6faf950ca655341ee9/.yarn/versions/095f496a.yml -------------------------------------------------------------------------------- /.yarn/versions/0a5ac396.yml: -------------------------------------------------------------------------------- 1 | undecided: 2 | - "@subql/common-cosmos" 3 | - "@subql/types-cosmos" 4 | -------------------------------------------------------------------------------- /.yarn/versions/0b0bc2a3.yml: -------------------------------------------------------------------------------- 1 | undecided: 2 | - "@subql/types-cosmos" 3 | -------------------------------------------------------------------------------- /.yarn/versions/0ea17037.yml: -------------------------------------------------------------------------------- 1 | undecided: 2 | - "@subql/common-cosmos" 3 | -------------------------------------------------------------------------------- /.yarn/versions/126538f3.yml: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/subquery/subql-cosmos/ccdfe23be59fcd59ab44bb6faf950ca655341ee9/.yarn/versions/126538f3.yml -------------------------------------------------------------------------------- /.yarn/versions/127114e3.yml: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/subquery/subql-cosmos/ccdfe23be59fcd59ab44bb6faf950ca655341ee9/.yarn/versions/127114e3.yml -------------------------------------------------------------------------------- /.yarn/versions/12c6b05e.yml: -------------------------------------------------------------------------------- 1 | undecided: 2 | - "@subql/types-cosmos" 3 | -------------------------------------------------------------------------------- /.yarn/versions/168bce8e.yml: -------------------------------------------------------------------------------- 1 | undecided: 2 | - "@subql/node-cosmos" 3 | - "@subql/types-cosmos" 4 | -------------------------------------------------------------------------------- /.yarn/versions/17e47b29.yml: -------------------------------------------------------------------------------- 1 | undecided: 2 | - "@subql/common-cosmos" 3 | - "@subql/node-cosmos" 4 | -------------------------------------------------------------------------------- /.yarn/versions/1a63fd33.yml: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/subquery/subql-cosmos/ccdfe23be59fcd59ab44bb6faf950ca655341ee9/.yarn/versions/1a63fd33.yml -------------------------------------------------------------------------------- /.yarn/versions/1cbeddd1.yml: -------------------------------------------------------------------------------- 1 | undecided: 2 | - "@subql/node-cosmos" 3 | - "@subql/types-cosmos" 4 | -------------------------------------------------------------------------------- /.yarn/versions/1ef5011d.yml: -------------------------------------------------------------------------------- 1 | undecided: 2 | - "@subql/types-cosmos" 3 | -------------------------------------------------------------------------------- /.yarn/versions/2070419d.yml: -------------------------------------------------------------------------------- 1 | undecided: 2 | - "@subql/node-cosmos" 3 | - "@subql/types-cosmos" 4 | -------------------------------------------------------------------------------- /.yarn/versions/2c381cc7.yml: -------------------------------------------------------------------------------- 1 | undecided: 2 | - "@subql/common-cosmos" 3 | - "@subql/node-cosmos" 4 | -------------------------------------------------------------------------------- /.yarn/versions/2cd2922c.yml: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/subquery/subql-cosmos/ccdfe23be59fcd59ab44bb6faf950ca655341ee9/.yarn/versions/2cd2922c.yml -------------------------------------------------------------------------------- /.yarn/versions/2ed81f15.yml: -------------------------------------------------------------------------------- 1 | undecided: 2 | - "@subql/common-cosmos" 3 | -------------------------------------------------------------------------------- /.yarn/versions/305fc6e5.yml: -------------------------------------------------------------------------------- 1 | undecided: 2 | - "@subql/common-cosmos" 3 | - "@subql/types-cosmos" 4 | -------------------------------------------------------------------------------- /.yarn/versions/314c9df8.yml: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/subquery/subql-cosmos/ccdfe23be59fcd59ab44bb6faf950ca655341ee9/.yarn/versions/314c9df8.yml -------------------------------------------------------------------------------- /.yarn/versions/34b66995.yml: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/subquery/subql-cosmos/ccdfe23be59fcd59ab44bb6faf950ca655341ee9/.yarn/versions/34b66995.yml -------------------------------------------------------------------------------- /.yarn/versions/358bef74.yml: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/subquery/subql-cosmos/ccdfe23be59fcd59ab44bb6faf950ca655341ee9/.yarn/versions/358bef74.yml -------------------------------------------------------------------------------- /.yarn/versions/3775e704.yml: -------------------------------------------------------------------------------- 1 | undecided: 2 | - "@subql/node-cosmos" 3 | - "@subql/types-cosmos" 4 | -------------------------------------------------------------------------------- /.yarn/versions/380bbfa5.yml: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/subquery/subql-cosmos/ccdfe23be59fcd59ab44bb6faf950ca655341ee9/.yarn/versions/380bbfa5.yml -------------------------------------------------------------------------------- /.yarn/versions/39055c5f.yml: -------------------------------------------------------------------------------- 1 | undecided: 2 | - "@subql/common-cosmos" 3 | - "@subql/types-cosmos" 4 | -------------------------------------------------------------------------------- /.yarn/versions/3c9a5976.yml: -------------------------------------------------------------------------------- 1 | undecided: 2 | - "@subql/common-cosmos" 3 | - "@subql/types-cosmos" 4 | -------------------------------------------------------------------------------- /.yarn/versions/3fe26997.yml: -------------------------------------------------------------------------------- 1 | undecided: 2 | - "@subql/common-cosmos" 3 | -------------------------------------------------------------------------------- /.yarn/versions/43264fb5.yml: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/subquery/subql-cosmos/ccdfe23be59fcd59ab44bb6faf950ca655341ee9/.yarn/versions/43264fb5.yml -------------------------------------------------------------------------------- /.yarn/versions/45a7e688.yml: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/subquery/subql-cosmos/ccdfe23be59fcd59ab44bb6faf950ca655341ee9/.yarn/versions/45a7e688.yml -------------------------------------------------------------------------------- /.yarn/versions/49ba0b8a.yml: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/subquery/subql-cosmos/ccdfe23be59fcd59ab44bb6faf950ca655341ee9/.yarn/versions/49ba0b8a.yml -------------------------------------------------------------------------------- /.yarn/versions/4c8f6b9e.yml: -------------------------------------------------------------------------------- 1 | undecided: 2 | - "@subql/types-cosmos" 3 | -------------------------------------------------------------------------------- /.yarn/versions/4d2b53f8.yml: -------------------------------------------------------------------------------- 1 | undecided: 2 | - "@subql/node-cosmos" 3 | - "@subql/types-cosmos" 4 | -------------------------------------------------------------------------------- /.yarn/versions/508f0d31.yml: -------------------------------------------------------------------------------- 1 | undecided: 2 | - "@subql/node-cosmos" 3 | -------------------------------------------------------------------------------- /.yarn/versions/5428c933.yml: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/subquery/subql-cosmos/ccdfe23be59fcd59ab44bb6faf950ca655341ee9/.yarn/versions/5428c933.yml -------------------------------------------------------------------------------- /.yarn/versions/54610e58.yml: -------------------------------------------------------------------------------- 1 | undecided: 2 | - "@subql/common-ethereum" 3 | - "@subql/types-ethereum" 4 | -------------------------------------------------------------------------------- /.yarn/versions/55192620.yml: -------------------------------------------------------------------------------- 1 | undecided: 2 | - "@subql/common-cosmos" 3 | - "@subql/types-cosmos" 4 | -------------------------------------------------------------------------------- /.yarn/versions/556bcbb5.yml: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/subquery/subql-cosmos/ccdfe23be59fcd59ab44bb6faf950ca655341ee9/.yarn/versions/556bcbb5.yml -------------------------------------------------------------------------------- /.yarn/versions/57d7cbb2.yml: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/subquery/subql-cosmos/ccdfe23be59fcd59ab44bb6faf950ca655341ee9/.yarn/versions/57d7cbb2.yml -------------------------------------------------------------------------------- /.yarn/versions/5aa857c9.yml: -------------------------------------------------------------------------------- 1 | undecided: 2 | - "@subql/common-cosmos" 3 | - "@subql/node-cosmos" 4 | -------------------------------------------------------------------------------- /.yarn/versions/5dc26b93.yml: -------------------------------------------------------------------------------- 1 | undecided: 2 | - "@subql/node-cosmos" 3 | - "@subql/types-cosmos" 4 | -------------------------------------------------------------------------------- /.yarn/versions/689ddd69.yml: -------------------------------------------------------------------------------- 1 | undecided: 2 | - "@subql/common-cosmos" 3 | - "@subql/node-cosmos" 4 | -------------------------------------------------------------------------------- /.yarn/versions/6ab57fdd.yml: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/subquery/subql-cosmos/ccdfe23be59fcd59ab44bb6faf950ca655341ee9/.yarn/versions/6ab57fdd.yml -------------------------------------------------------------------------------- /.yarn/versions/6dc54c3b.yml: -------------------------------------------------------------------------------- 1 | undecided: 2 | - "@subql/common-cosmos" 3 | - "@subql/node-cosmos" 4 | -------------------------------------------------------------------------------- /.yarn/versions/71ee6ef5.yml: -------------------------------------------------------------------------------- 1 | undecided: 2 | - "@subql/common-cosmos" 3 | -------------------------------------------------------------------------------- /.yarn/versions/724c556a.yml: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/subquery/subql-cosmos/ccdfe23be59fcd59ab44bb6faf950ca655341ee9/.yarn/versions/724c556a.yml -------------------------------------------------------------------------------- /.yarn/versions/789dc02c.yml: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/subquery/subql-cosmos/ccdfe23be59fcd59ab44bb6faf950ca655341ee9/.yarn/versions/789dc02c.yml -------------------------------------------------------------------------------- /.yarn/versions/7ee34992.yml: -------------------------------------------------------------------------------- 1 | undecided: 2 | - "@subql/types-cosmos" 3 | -------------------------------------------------------------------------------- /.yarn/versions/849df7f0.yml: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/subquery/subql-cosmos/ccdfe23be59fcd59ab44bb6faf950ca655341ee9/.yarn/versions/849df7f0.yml -------------------------------------------------------------------------------- /.yarn/versions/85c1d7a2.yml: -------------------------------------------------------------------------------- 1 | undecided: 2 | - "@subql/common-cosmos" 3 | - "@subql/types-cosmos" 4 | -------------------------------------------------------------------------------- /.yarn/versions/8685cba7.yml: -------------------------------------------------------------------------------- 1 | undecided: 2 | - "@subql/types-cosmos" 3 | -------------------------------------------------------------------------------- /.yarn/versions/8e5687b3.yml: -------------------------------------------------------------------------------- 1 | undecided: 2 | - "@subql/common-cosmos" 3 | - "@subql/types-cosmos" 4 | -------------------------------------------------------------------------------- /.yarn/versions/92eab379.yml: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/subquery/subql-cosmos/ccdfe23be59fcd59ab44bb6faf950ca655341ee9/.yarn/versions/92eab379.yml -------------------------------------------------------------------------------- /.yarn/versions/93d1bae2.yml: -------------------------------------------------------------------------------- 1 | undecided: 2 | - "@subql/common-cosmos" 3 | -------------------------------------------------------------------------------- /.yarn/versions/95765d7c.yml: -------------------------------------------------------------------------------- 1 | undecided: 2 | - "@subql/common-cosmos" 3 | - "@subql/types-cosmos" 4 | -------------------------------------------------------------------------------- /.yarn/versions/95bd9aab.yml: -------------------------------------------------------------------------------- 1 | undecided: 2 | - "@subql/common-cosmos" 3 | - "@subql/types-cosmos" 4 | -------------------------------------------------------------------------------- /.yarn/versions/95f28132.yml: -------------------------------------------------------------------------------- 1 | undecided: 2 | - "@subql/common-cosmos" 3 | -------------------------------------------------------------------------------- /.yarn/versions/97e9ad08.yml: -------------------------------------------------------------------------------- 1 | undecided: 2 | - "@subql/common-cosmos" 3 | - "@subql/types-cosmos" 4 | -------------------------------------------------------------------------------- /.yarn/versions/995a4638.yml: -------------------------------------------------------------------------------- 1 | undecided: 2 | - "@subql/common-cosmos" 3 | -------------------------------------------------------------------------------- /.yarn/versions/9996cf4f.yml: -------------------------------------------------------------------------------- 1 | undecided: 2 | - "@subql/common-cosmos" 3 | - "@subql/types-cosmos" 4 | -------------------------------------------------------------------------------- /.yarn/versions/9ea41ba3.yml: -------------------------------------------------------------------------------- 1 | undecided: 2 | - "@subql/node-cosmos" 3 | -------------------------------------------------------------------------------- /.yarn/versions/a097e0b4.yml: -------------------------------------------------------------------------------- 1 | undecided: 2 | - "@subql/common-cosmos" 3 | - "@subql/types-cosmos" 4 | -------------------------------------------------------------------------------- /.yarn/versions/a0dfddf3.yml: -------------------------------------------------------------------------------- 1 | undecided: 2 | - "@subql/common-cosmos" 3 | - "@subql/types-cosmos" 4 | -------------------------------------------------------------------------------- /.yarn/versions/a1d4d641.yml: -------------------------------------------------------------------------------- 1 | undecided: 2 | - "@subql/common-cosmos" 3 | - "@subql/types-cosmos" 4 | -------------------------------------------------------------------------------- /.yarn/versions/a4c7f709.yml: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/subquery/subql-cosmos/ccdfe23be59fcd59ab44bb6faf950ca655341ee9/.yarn/versions/a4c7f709.yml -------------------------------------------------------------------------------- /.yarn/versions/a5e2b500.yml: -------------------------------------------------------------------------------- 1 | undecided: 2 | - "@subql/common-cosmos" 3 | - "@subql/node-cosmos" 4 | -------------------------------------------------------------------------------- /.yarn/versions/aca7ef93.yml: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/subquery/subql-cosmos/ccdfe23be59fcd59ab44bb6faf950ca655341ee9/.yarn/versions/aca7ef93.yml -------------------------------------------------------------------------------- /.yarn/versions/b4f1dd5b.yml: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/subquery/subql-cosmos/ccdfe23be59fcd59ab44bb6faf950ca655341ee9/.yarn/versions/b4f1dd5b.yml -------------------------------------------------------------------------------- /.yarn/versions/b678ab12.yml: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/subquery/subql-cosmos/ccdfe23be59fcd59ab44bb6faf950ca655341ee9/.yarn/versions/b678ab12.yml -------------------------------------------------------------------------------- /.yarn/versions/b87a54e8.yml: -------------------------------------------------------------------------------- 1 | undecided: 2 | - "@subql/types-cosmos" 3 | -------------------------------------------------------------------------------- /.yarn/versions/b97fc139.yml: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/subquery/subql-cosmos/ccdfe23be59fcd59ab44bb6faf950ca655341ee9/.yarn/versions/b97fc139.yml -------------------------------------------------------------------------------- /.yarn/versions/bb35b101.yml: -------------------------------------------------------------------------------- 1 | undecided: 2 | - "@subql/node-cosmos" 3 | - "@subql/types-cosmos" 4 | -------------------------------------------------------------------------------- /.yarn/versions/bf08dae0.yml: -------------------------------------------------------------------------------- 1 | undecided: 2 | - "@subql/common-cosmos" 3 | - "@subql/types-cosmos" 4 | -------------------------------------------------------------------------------- /.yarn/versions/bf1cb0a9.yml: -------------------------------------------------------------------------------- 1 | undecided: 2 | - "@subql/common-cosmos" 3 | - "@subql/types-cosmos" 4 | -------------------------------------------------------------------------------- /.yarn/versions/c1ecb61b.yml: -------------------------------------------------------------------------------- 1 | undecided: 2 | - "@subql/common-cosmos" 3 | - "@subql/node-cosmos" 4 | -------------------------------------------------------------------------------- /.yarn/versions/c38440c9.yml: -------------------------------------------------------------------------------- 1 | undecided: 2 | - "@subql/node-cosmos" 3 | - "@subql/types-cosmos" 4 | -------------------------------------------------------------------------------- /.yarn/versions/c3d3784c.yml: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/subquery/subql-cosmos/ccdfe23be59fcd59ab44bb6faf950ca655341ee9/.yarn/versions/c3d3784c.yml -------------------------------------------------------------------------------- /.yarn/versions/c731748c.yml: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/subquery/subql-cosmos/ccdfe23be59fcd59ab44bb6faf950ca655341ee9/.yarn/versions/c731748c.yml -------------------------------------------------------------------------------- /.yarn/versions/c92c26a5.yml: -------------------------------------------------------------------------------- 1 | undecided: 2 | - "@subql/node-solana" 3 | - "@subql/types-solana" 4 | -------------------------------------------------------------------------------- /.yarn/versions/cc432472.yml: -------------------------------------------------------------------------------- 1 | undecided: 2 | - "@subql/common-cosmos" 3 | - "@subql/node-cosmos" 4 | -------------------------------------------------------------------------------- /.yarn/versions/d076915b.yml: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/subquery/subql-cosmos/ccdfe23be59fcd59ab44bb6faf950ca655341ee9/.yarn/versions/d076915b.yml -------------------------------------------------------------------------------- /.yarn/versions/d1167efd.yml: -------------------------------------------------------------------------------- 1 | undecided: 2 | - "@subql/node-cosmos" 3 | - "@subql/types-cosmos" 4 | -------------------------------------------------------------------------------- /.yarn/versions/d5d3ed34.yml: -------------------------------------------------------------------------------- 1 | undecided: 2 | - "@subql/types-cosmos" 3 | -------------------------------------------------------------------------------- /.yarn/versions/d9a5c6c9.yml: -------------------------------------------------------------------------------- 1 | undecided: 2 | - "@subql/common-cosmos" 3 | - "@subql/types-cosmos" 4 | -------------------------------------------------------------------------------- /.yarn/versions/dc0c537d.yml: -------------------------------------------------------------------------------- 1 | undecided: 2 | - "@subql/common-cosmos" 3 | -------------------------------------------------------------------------------- /.yarn/versions/de6e7b4b.yml: -------------------------------------------------------------------------------- 1 | undecided: 2 | - "@subql/types-cosmos" 3 | -------------------------------------------------------------------------------- /.yarn/versions/def48634.yml: -------------------------------------------------------------------------------- 1 | undecided: 2 | - "@subql/common-cosmos" 3 | - "@subql/types-cosmos" 4 | -------------------------------------------------------------------------------- /.yarn/versions/e07e476d.yml: -------------------------------------------------------------------------------- 1 | undecided: 2 | - "@subql/types-cosmos" 3 | -------------------------------------------------------------------------------- /.yarn/versions/e099fb72.yml: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/subquery/subql-cosmos/ccdfe23be59fcd59ab44bb6faf950ca655341ee9/.yarn/versions/e099fb72.yml -------------------------------------------------------------------------------- /.yarn/versions/e25fd62f.yml: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/subquery/subql-cosmos/ccdfe23be59fcd59ab44bb6faf950ca655341ee9/.yarn/versions/e25fd62f.yml -------------------------------------------------------------------------------- /.yarn/versions/e417fa20.yml: -------------------------------------------------------------------------------- 1 | undecided: 2 | - "@subql/common-cosmos" 3 | -------------------------------------------------------------------------------- /.yarn/versions/e4ebbcb3.yml: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/subquery/subql-cosmos/ccdfe23be59fcd59ab44bb6faf950ca655341ee9/.yarn/versions/e4ebbcb3.yml -------------------------------------------------------------------------------- /.yarn/versions/e594c6ad.yml: -------------------------------------------------------------------------------- 1 | undecided: 2 | - "@subql/common-cosmos" 3 | -------------------------------------------------------------------------------- /.yarn/versions/e7a88440.yml: -------------------------------------------------------------------------------- 1 | undecided: 2 | - "@subql/node-cosmos" 3 | - "@subql/types-cosmos" 4 | -------------------------------------------------------------------------------- /.yarn/versions/e9855f18.yml: -------------------------------------------------------------------------------- 1 | undecided: 2 | - "@subql/common-cosmos" 3 | - "@subql/types-cosmos" 4 | -------------------------------------------------------------------------------- /.yarn/versions/eaa6e623.yml: -------------------------------------------------------------------------------- 1 | undecided: 2 | - "@subql/common-cosmos" 3 | - "@subql/types-cosmos" 4 | -------------------------------------------------------------------------------- /.yarn/versions/eb8d476b.yml: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/subquery/subql-cosmos/ccdfe23be59fcd59ab44bb6faf950ca655341ee9/.yarn/versions/eb8d476b.yml -------------------------------------------------------------------------------- /.yarn/versions/ed86c35b.yml: -------------------------------------------------------------------------------- 1 | undecided: 2 | - "@subql/common-cosmos" 3 | - "@subql/node-cosmos" 4 | -------------------------------------------------------------------------------- /.yarn/versions/eec56ca6.yml: -------------------------------------------------------------------------------- 1 | undecided: 2 | - "@subql/common-cosmos" 3 | - "@subql/types-cosmos" 4 | -------------------------------------------------------------------------------- /.yarn/versions/f13a382e.yml: -------------------------------------------------------------------------------- 1 | undecided: 2 | - "@subql/node-cosmos" 3 | - "@subql/types-cosmos" 4 | -------------------------------------------------------------------------------- /.yarn/versions/f46ddc06.yml: -------------------------------------------------------------------------------- 1 | undecided: 2 | - "@subql/common-cosmos" 3 | - "@subql/types-cosmos" 4 | -------------------------------------------------------------------------------- /.yarn/versions/f6577513.yml: -------------------------------------------------------------------------------- 1 | undecided: 2 | - "@subql/common-cosmos" 3 | - "@subql/types-cosmos" 4 | -------------------------------------------------------------------------------- /.yarn/versions/f697f53e.yml: -------------------------------------------------------------------------------- 1 | undecided: 2 | - "@subql/common-cosmos" 3 | - "@subql/types-cosmos" 4 | -------------------------------------------------------------------------------- /.yarn/versions/f7152985.yml: -------------------------------------------------------------------------------- 1 | undecided: 2 | - "@subql/node-cosmos" 3 | - "@subql/types-cosmos" 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.1.1.cjs 26 | 27 | changesetIgnorePatterns: 28 | - '.yarn/**/*' 29 | -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # SubQuery Code of Conduct 2 | 3 | SubQuery, as contributors, and maintainers pledge to make participation in our project and our 4 | community a harassment-free experience for everyone, regardless of age, body 5 | size, visible or invisible disability, ethnicity, sex characteristics, gender 6 | identity and expression, level of experience, education, socio-economic status, 7 | nationality, personal appearance, race, religion, or sexual identity 8 | and orientation. 9 | 10 | We pledge to act and interact in ways that contribute to an open, welcoming, 11 | diverse, inclusive, and healthy community. 12 | 13 | ## Our Standards 14 | 15 | Examples of behavior that contributes to a positive environment for our 16 | community include: 17 | 18 | * Supporting for new contributors by providing help and pointing them to the right examples and documentation 19 | * Demonstrating empathy and kindness toward other people 20 | * Using welcoming and inclusive language 21 | * Being respectful of differing opinions, viewpoints, and experiences 22 | * Giving and gracefully accepting constructive feedback 23 | * Focusing on what is best for the overall community 24 | 25 | Examples of unacceptable behavior include: 26 | 27 | * The use of sexualized language or imagery, and sexual attention or 28 | advances of any kind 29 | * Trolling, insulting or derogatory comments, and personal or political attacks 30 | * Public or private harassment 31 | * Publishing others' private information, such as a physical or email 32 | address, without their explicit permission 33 | * Other conduct which could reasonably be considered inappropriate in a 34 | professional setting 35 | 36 | ## Our Responsibilities 37 | 38 | Project maintainers are responsible for clarifying and enforcing our standards of 39 | acceptable behavior and will take appropriate and fair corrective action in 40 | response to any behavior that is deemed inappropriate, threatening, offensive, 41 | or harmful. 42 | 43 | Project maintainers have the right and responsibility to remove, edit, or reject 44 | comments, commits, code, wiki edits, issues, and other contributions that are 45 | not aligned to this Code of Conduct, or to ban temporarily or permanently any 46 | contributor for other behaviors that is deemed inappropriate, threatening, offensive, or harmful. 47 | 48 | ## Scope 49 | 50 | This Code of Conduct applies to all of SubQuery's content on GitHub, as well as at all official SubQuery 51 | events, whether offline or online. 52 | 53 | Examples of representing a project or community include using an official e-mail address, 54 | posting via an official social media account, or acting as an appointed 55 | representative at an online or offline event. 56 | 57 | ## Reporting Code of Conduct Issues 58 | 59 | SubQuery encourage all communities to resolve issues on their own whenever possible. 60 | This builds a broader and deeper understanding and ultimately a healthier interaction. 61 | In the event that an issue cannot be resolved locally, please feel free to report your concerns by 62 | contacting support@subquery.network. 63 | 64 | All complaints will be reviewed and investigated promptly and fairly. SubQuery will respect the privacy and security of the reporter of any incident. 65 | 66 | All reports will be reviewed by a multi-person team and will result in a response that 67 | is deemed necessary and appropriate to the circumstances. Where additional perspectives are needed, 68 | the team may seek insight from others with relevant expertise or experience. The confidentiality 69 | of the person reporting the incident will be kept at all times. Involved parties are never part of the review team. 70 | 71 | ## Attribution 72 | 73 | This Code of Conduct is adapted from version 2.0 of the [Contributor Covenant](https://www.contributor-covenant.org/version/2/0/code_of_conduct.html) 74 | 75 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Welcome to SubQuery! 2 | 3 | **Flexible, reliable, and decentralised APIs for your web3 project** 4 | 5 | SubQuery is an Open, Flexible, Fast and Universal data indexing framework for web3. Our mission is to help developers create the decentralised products of the future. 6 | 7 | SubQuery allows every Substrate/Polkadot team to process and query their data. The project is inspired by the growth of data protocols serving the application layer and its aim is to help Polkadot/Substrate projects build better dApps by allowing anyone to reliably find and consume data faster. Today, anyone can query and extract Polkadot network data in only minutes and at no cost. 8 | 9 | The future is multi-chain - SubQuery is no different. SubQuery is well on our way to support all leading blockchain networks with support for the following: 10 | 11 | - [Polkadot (and all Substrate networks)](https://academy.subquery.network/quickstart/quickstart_chains/polkadot.html) 12 | - [Ethereum] (https://academy.subquery.network/quickstart/quickstart_chains/ethereum-gravatar.html) 13 | - [Cosmos (and all CosmWasm and Ethermint networks)](https://academy.subquery.network/quickstart/quickstart_chains/cosmos.html) 14 | - [Avalanche (and all Avalanche Subnets)](https://academy.subquery.network/quickstart/quickstart_chains/avalanche.html) 15 | - [Algorand](https://academy.subquery.network/quickstart/quickstart_chains/algorand.html) 16 | - [Terra](https://academy.subquery.network/quickstart/quickstart_chains/terra.html) 17 | - [NEAR](https://academy.subquery.network/quickstart/quickstart_chains/near.html) 18 | - [Flare](https://academy.subquery.network/quickstart/quickstart_chains/flare.html) 19 | - [Polygon](https://academy.subquery.network/quickstart/quickstart_chains/polygon.html) 20 | - [BSC](https://academy.subquery.network/quickstart/quickstart_chains/bsc.html) 21 | 22 | ## Get Started 23 | 24 | #### Create a SubQuery project 25 | 26 | You can follow our [Quick Start Guide](https://academy.subquery.network/quickstart/quickstart.html) to learn how to create, initialize, build, and publish a new SubQuery Project using the `@subql/cli` tool. 27 | 28 | #### Learn and improve with our comprehensive documentation 29 | 30 | Dig into every term, usecases, and best-practices that help you build a dApp which your users love. Take a look at our [detailed technical documentation](https://academy.subquery.network/build/introduction.html). 31 | 32 | #### Publish your SubQuery Project to our Managed Service 33 | 34 | Don't want to worry about running your own indexing infrastructure? SubQuery provides a [managed Service](https://explorer.subquery.network) with industry leading hosting so you can sleep easy. Trused by hundreds of projects with millions of daily requests, follow our publishing guide to see how you can upload your project to [SubQuery Projects](https://academy.subquery.network/run_publish/publish.html). 35 | 36 | #### Run your own Indexer and Query Service 37 | 38 | [Follow our guide](https://academy.subquery.network/run_publish/run.html) to run your own SubQuery local node that you can use to debug, test, and run you own GraphQL server 39 | 40 | You're going to need to a Postgres database, a node to extract chain data, and a moderately powerful computer to run the indexer in the background. 41 | 42 | You'll also use our custom-built GraphQL query service [`@subql/query`](https://www.npmjs.com/package/@subql/query) to interact with your SubQuery project. 43 | 44 | #### Components 45 | 46 | * [`@subql/cli`](packages/cli) 47 | * [`@subql/node`](packages/node) 48 | * [`@subql/query`](packages/query) 49 | * [`@subql/common`](packages/common) 50 | * [`@subql/common-substrate`](packages/common-substrate) 51 | * [`@subql/types`](packages/types) 52 | * [`@subql/validator`](packages/validator) 53 | 54 | ## Contribute 55 | 56 | We love contributions and feedback from the community. To contribute the code, we suggest starting by creating an issue in our main repository so we can give you support. 57 | 58 | ## Copyright 59 | 60 | SubQuery is a project built with love from the team at [SubQuery](https://subquery.network) all the way from New Zealand 61 | 62 | Copyright © 2022 [SubQuery Pte Ltd](https://subquery.network) authors & contributors 63 | -------------------------------------------------------------------------------- /babel.config.js: -------------------------------------------------------------------------------- 1 | module.exports = {presets: ['@babel/preset-env']} 2 | -------------------------------------------------------------------------------- /contributing.md: -------------------------------------------------------------------------------- 1 | # Contributing to the SubQuery project 2 | 3 | Welcome and a big thank you for considering contributing to this SubQuery project! Together we can pave the way to a more decentralised future. 4 | 5 | What follows is a set of guidelines (not rules) for contributing to SubQuery. Following these guidelines will help us make the contribution process easy and effective for everyone involved. It also communicates that you agree to respect the time of the developers managing and developing this project. In return, we will reciprocate that respect by addressing your issue, considering changes, collaborating on improvements, and helping you finalise your pull requests. 6 | 7 | ## Code of Conduct 8 | 9 | We take our open source community projects and responsibility seriously and hold ourselves and other contributors to high standards of communication. By participating and contributing to this project, you agree to uphold our [Code of Conduct](https://github.com/subquery/subql/blob/contributors-guide/CODE_OF_CONDUCT.md). 10 | 11 | ## Getting started 12 | 13 | Contributions to our repositories are made through Issues and Pull Requests (PRs). A few general guidelines that cover both: 14 | 15 | * Search for existing Issues and PRs before creating your own. 16 | * We work hard to makes sure issues are handled in promptly but, depending on the impact, it could take a while to investigate the root cause. A friendly @ mention in the comment thread to the submitter or a contributor can help draw attention if your issue is blocking. 17 | 18 | ## How to Contribute 19 | 20 | ### Reporting Bugs 21 | 22 | Bugs are tracked as GitHub issues. When logging an issue, explain the problem and include additional details to help maintainers reproduce the problem: 23 | 24 | * Use a clear and descriptive title for the issue to identify the problem. 25 | * Describe the exact steps to reproduce the problem. 26 | * Describe the behavior you observed after following the steps. 27 | * Explain which behavior you expected to see instead and why. 28 | * Include screenshots if possible. 29 | 30 | ### Submitting Pull Requests 31 | 32 | In general, we follow the "fork-and-pull" Git workflow 33 | 34 | * Fork the repository to your own Github account 35 | * Clone the project to your machine 36 | * Create a branch locally with a succinct but descriptive name 37 | * Commit changes to the branch 38 | * Following any formatting and testing guidelines specific to this repo 39 | * Push changes to your fork 40 | * Open a PR in our repository 41 | 42 | ### Publishing to Github Releases 43 | 44 | In order to publish to github release, there are prerequisites: 45 | 46 | * Firstly in the merged commit the phrase `[release]` must be present 47 | * Next, you must add a description of the release in the respective package's `CHANGELOG.md` 48 | * There must be some difference in the package compared with main 49 | * Lastly, the version must be in a format of x.y.z without '-' 50 | 51 | When a pull request to main has been accepted the workflow will 52 | try to create releases for each package where possible. 53 | 54 | ## Coding Conventions 55 | 56 | ### Git Commit Messages 57 | 58 | * Use the present tense ("Add feature" not "Added feature") 59 | * Use the imperative mood ("Move cursor to..." not "Moves cursor to...") 60 | * Limit the first line to 72 characters or less 61 | 62 | ### JavaScript Styleguide 63 | 64 | * All JavaScript code is linted with Prettier and ESLint 65 | -------------------------------------------------------------------------------- /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/k8s/README.md: -------------------------------------------------------------------------------- 1 | # K8s Deploy 2 | This [deploy.yaml](deploy.yaml) demonstrate how to run subquery in k8s. 3 | 4 | You will need to run 5 | ### 1. a subql-node to index data 6 | ```yaml 7 | apiVersion: apps/v1 8 | kind: Deployment 9 | 10 | metadata: 11 | name: subql-node-1 12 | labels: 13 | app: subql-node 14 | release: subql-node-1 15 | 16 | spec: 17 | selector: 18 | matchLabels: 19 | release: subql-node-1 20 | replicas: 1 21 | template: 22 | metadata: 23 | labels: 24 | release: subql-node-1 25 | spec: 26 | volumes: 27 | - name: project-dir 28 | emptyDir: 29 | medium: Memory 30 | initContainers: 31 | - name: prepare 32 | imagePullPolicy: IfNotPresent 33 | image: node:14-alpine 34 | command: 35 | - sh 36 | - -c 37 | - apk add git && git clone https://github.com/OnFinality-io/subql-examples /subquery && cd /subquery/block-timestamp && npm i -g @subql/cli && yarn && subql codegen && yarn build 38 | volumeMounts: 39 | - name: project-dir 40 | mountPath: '/subquery' 41 | containers: 42 | - name: indexer 43 | imagePullPolicy: IfNotPresent 44 | image: onfinality/subql-node:v0.4.0 45 | args: 46 | - -f 47 | - /subquery/block-timestamp 48 | - --local 49 | env: 50 | - name: DB_HOST 51 | value: subquery-db-svc 52 | - name: DB_PORT 53 | value: "5432" 54 | - name: DB_USER 55 | value: postgres 56 | - name: DB_PASS 57 | value: postgres 58 | - name: DB_DATABASE 59 | value: postgres 60 | volumeMounts: 61 | - name: project-dir 62 | mountPath: '/subquery' 63 | securityContext: 64 | runAsUser: 1000 65 | 66 | securityContext: 67 | fsGroup: 1000 68 | imagePullSecrets: 69 | - name: regcred 70 | ``` 71 | Note: `--local` will create subquery tables in public schema, if you want to store multiple subquery in the same db, remove that flag. 72 | 73 | #### 2. a Postgres Database 74 | ```yaml 75 | apiVersion: apps/v1 76 | kind: StatefulSet 77 | 78 | metadata: 79 | name: subquery-db 80 | labels: 81 | app: postgres 82 | release: subquery-db 83 | 84 | spec: 85 | serviceName: subquery-db-svc 86 | 87 | selector: 88 | matchLabels: 89 | release: subquery-db 90 | 91 | volumeClaimTemplates: 92 | - metadata: 93 | name: subquery-db-pvc 94 | annotations: 95 | volume.beta.kubernetes.io/storage-class: standard 96 | spec: 97 | accessModes: 98 | - ReadWriteOnce 99 | resources: 100 | requests: 101 | storage: 20G 102 | template: 103 | metadata: 104 | labels: 105 | release: subquery-db 106 | spec: 107 | containers: 108 | - name: db 109 | imagePullPolicy: IfNotPresent 110 | image: postgres:12-alpine 111 | env: 112 | - name: POSTGRES_PASSWORD 113 | value: postgres 114 | ports: 115 | - containerPort: 5432 116 | volumeMounts: 117 | - mountPath: /var/lib/postgresql 118 | name: subquery-db-pvc 119 | 120 | securityContext: 121 | fsGroup: 1000 122 | imagePullSecrets: 123 | - name: regcred 124 | --- 125 | apiVersion: v1 126 | kind: Service 127 | 128 | metadata: 129 | name: subquery-db-svc 130 | 131 | spec: 132 | clusterIP: None 133 | ports: 134 | - port: 5432 135 | selector: 136 | release: subquery-db 137 | ``` 138 | 139 | Note that if used in production, a dedicated database should be used to get better performance. 140 | 141 | #### 3. Hasura for graphql querying 142 | ```yaml 143 | apiVersion: apps/v1 144 | kind: Deployment 145 | 146 | metadata: 147 | name: hasura-deploy 148 | labels: 149 | release: hasura 150 | 151 | spec: 152 | selector: 153 | matchLabels: 154 | release: hasura 155 | replicas: 1 156 | 157 | template: 158 | metadata: 159 | labels: 160 | release: hasura 161 | spec: 162 | containers: 163 | - name: hasura 164 | image: hasura/graphql-engine:v1.3.3 165 | imagePullPolicy: IfNotPresent 166 | ports: 167 | - containerPort: 8080 168 | env: 169 | # HASURA_GRAPHQL_DATABASE_URL: postgres://postgres:postgres@postgres:5432/postgres 170 | # ## enable the console served by server 171 | # HASURA_GRAPHQL_ENABLE_CONSOLE: "true" # set to "false" to disable console 172 | # ## enable debugging mode. It is recommended to disable this in production 173 | # HASURA_GRAPHQL_DEV_MODE: "true" 174 | # HASURA_GRAPHQL_ENABLED_LOG_TYPES: startup, http-log, webhook-log, websocket-log, query-log 175 | - name: HASURA_GRAPHQL_DATABASE_URL 176 | value: postgres://postgres:postgres@subquery-db-svc:5432/postgres 177 | - name: HASURA_GRAPHQL_ENABLE_CONSOLE 178 | value: 'true' 179 | terminationGracePeriodSeconds: 300 180 | ``` 181 | 182 | To gain further security, an archieve node should be used in the same k8s cluster, and a NetworkPolicy be added to limit all network communication within the internal network. 183 | ```yaml 184 | apiVersion: networking.k8s.io/v1 185 | kind: NetworkPolicy 186 | metadata: 187 | name: subquery-node-egress 188 | spec: 189 | podSelector: 190 | matchLabels: 191 | release: subql-node-1 192 | egress: 193 | - to: 194 | - ipBlock: 195 | cidr: 10.0.0.0/8 196 | policyTypes: 197 | - Egress 198 | ``` 199 | -------------------------------------------------------------------------------- /deploy/k8s/deploy.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: apps/v1 2 | kind: Deployment 3 | 4 | metadata: 5 | name: subql-node-1 6 | labels: 7 | app: subql-node 8 | release: subql-node-1 9 | 10 | spec: 11 | selector: 12 | matchLabels: 13 | release: subql-node-1 14 | replicas: 1 15 | template: 16 | metadata: 17 | labels: 18 | release: subql-node-1 19 | spec: 20 | volumes: 21 | - name: project-dir 22 | emptyDir: 23 | medium: Memory 24 | initContainers: 25 | - name: prepare 26 | imagePullPolicy: IfNotPresent 27 | image: node:14-alpine 28 | command: 29 | - sh 30 | - -c 31 | - apk add git && git clone https://github.com/OnFinality-io/subql-examples /subquery && cd /subquery/block-timestamp && npm i -g @subql/cli && yarn && subql codegen && yarn build 32 | volumeMounts: 33 | - name: project-dir 34 | mountPath: '/subquery' 35 | containers: 36 | - name: indexer 37 | imagePullPolicy: IfNotPresent 38 | image: onfinality/subql-node:v0.4.0 39 | args: 40 | - -f 41 | - /subquery/block-timestamp 42 | - --local 43 | env: 44 | - name: DB_HOST 45 | value: subquery-db-svc 46 | - name: DB_PORT 47 | value: "5432" 48 | - name: DB_USER 49 | value: postgres 50 | - name: DB_PASS 51 | value: postgres 52 | - name: DB_DATABASE 53 | value: postgres 54 | volumeMounts: 55 | - name: project-dir 56 | mountPath: '/subquery' 57 | securityContext: 58 | runAsUser: 1000 59 | 60 | securityContext: 61 | fsGroup: 1000 62 | imagePullSecrets: 63 | - name: regcred 64 | 65 | --- 66 | #apiVersion: networking.k8s.io/v1 67 | #kind: NetworkPolicy 68 | #metadata: 69 | # name: subquery-node-egress 70 | #spec: 71 | # podSelector: 72 | # matchLabels: 73 | # release: subql-node-1 74 | # egress: 75 | # - to: 76 | # - ipBlock: 77 | # cidr: 10.0.0.0/8 78 | # policyTypes: 79 | # - Egress 80 | --- 81 | apiVersion: apps/v1 82 | kind: StatefulSet 83 | 84 | metadata: 85 | name: subquery-db 86 | labels: 87 | app: postgres 88 | release: subquery-db 89 | 90 | spec: 91 | serviceName: subquery-db-svc 92 | 93 | selector: 94 | matchLabels: 95 | release: subquery-db 96 | 97 | volumeClaimTemplates: 98 | - metadata: 99 | name: subquery-db-pvc 100 | annotations: 101 | volume.beta.kubernetes.io/storage-class: standard 102 | spec: 103 | accessModes: 104 | - ReadWriteOnce 105 | resources: 106 | requests: 107 | storage: 20G 108 | template: 109 | metadata: 110 | labels: 111 | release: subquery-db 112 | spec: 113 | containers: 114 | - name: db 115 | imagePullPolicy: IfNotPresent 116 | image: postgres:12-alpine 117 | env: 118 | - name: POSTGRES_PASSWORD 119 | value: postgres 120 | ports: 121 | - containerPort: 5432 122 | volumeMounts: 123 | - mountPath: /var/lib/postgresql 124 | name: subquery-db-pvc 125 | 126 | securityContext: 127 | fsGroup: 1000 128 | imagePullSecrets: 129 | - name: regcred 130 | --- 131 | apiVersion: v1 132 | kind: Service 133 | 134 | metadata: 135 | name: subquery-db-svc 136 | 137 | spec: 138 | clusterIP: None 139 | ports: 140 | - port: 5432 141 | selector: 142 | release: subquery-db 143 | --- 144 | apiVersion: apps/v1 145 | kind: Deployment 146 | 147 | metadata: 148 | name: hasura-deploy 149 | labels: 150 | release: hasura 151 | 152 | spec: 153 | selector: 154 | matchLabels: 155 | release: hasura 156 | replicas: 1 157 | 158 | template: 159 | metadata: 160 | labels: 161 | release: hasura 162 | spec: 163 | containers: 164 | - name: hasura 165 | image: hasura/graphql-engine:v1.3.3 166 | imagePullPolicy: IfNotPresent 167 | ports: 168 | - containerPort: 8080 169 | env: 170 | # HASURA_GRAPHQL_DATABASE_URL: postgres://postgres:postgres@postgres:5432/postgres 171 | # ## enable the console served by server 172 | # HASURA_GRAPHQL_ENABLE_CONSOLE: "true" # set to "false" to disable console 173 | # ## enable debugging mode. It is recommended to disable this in production 174 | # HASURA_GRAPHQL_DEV_MODE: "true" 175 | # HASURA_GRAPHQL_ENABLED_LOG_TYPES: startup, http-log, webhook-log, websocket-log, query-log 176 | - name: HASURA_GRAPHQL_DATABASE_URL 177 | value: postgres://postgres:postgres@subquery-db-svc:5432/postgres 178 | - name: HASURA_GRAPHQL_ENABLE_CONSOLE 179 | value: 'true' 180 | terminationGracePeriodSeconds: 300 181 | -------------------------------------------------------------------------------- /deploy/logging_debug.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/subquery/subql-cosmos/ccdfe23be59fcd59ab44bb6faf950ca655341ee9/deploy/logging_debug.png -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "subql-mono", 3 | "private": true, 4 | "workspaces": [ 5 | "packages/*" 6 | ], 7 | "devDependencies": { 8 | "@actions/core": "^1.10.0", 9 | "@babel/preset-env": "^7.16.11", 10 | "@octokit/request": "^5.6.3", 11 | "@types/node": "^22.13.5", 12 | "@types/node-fetch": "2.6.2", 13 | "@typescript-eslint/eslint-plugin": "^5.10.2", 14 | "@typescript-eslint/parser": "^5.10.2", 15 | "babel-jest": "^29.7.0", 16 | "eslint": "^8.8.0", 17 | "eslint-config-prettier": "^8.3.0", 18 | "eslint-plugin-header": "^3.1.1", 19 | "eslint-plugin-import": "^2.25.4", 20 | "eslint-plugin-jest": "^27.2.3", 21 | "eslint-plugin-prettier": "^4.0.0", 22 | "eslint-plugin-sort-destructure-keys": "^1.4.0", 23 | "husky": "^7.0.4", 24 | "jest": "^29.7.0", 25 | "lint-staged": "^12.3.3", 26 | "node-fetch": "2.6.7", 27 | "prettier": "^2.5.1", 28 | "pretty-quick": "^3.1.3", 29 | "regenerator-runtime": "^0.13.9", 30 | "ts-jest": "^29.1.2", 31 | "ts-loader": "^9.2.6", 32 | "ts-node": "^10.4.0", 33 | "tsconfig-paths": "^3.12.0", 34 | "typescript": "^5.5.4" 35 | }, 36 | "resolutions": { 37 | "node-fetch": "2.6.7" 38 | }, 39 | "scripts": { 40 | "build": "yarn workspaces foreach -ptA run build", 41 | "lint": "eslint packages --ext .ts", 42 | "test": "jest --coverage", 43 | "test:all": "node --expose-gc ./node_modules/.bin/jest --logHeapUsage --testRegex='.*\\.(spec|test)\\.ts$' --forceExit --ci -w=2 --clearMocks", 44 | "test:docker": "docker-compose -f test/docker-compose.yaml up --remove-orphans --abort-on-container-exit --build test", 45 | "test-jest": "jest --testRegex='.*\\.(spec|test)\\.ts$' --forceExit", 46 | "postinstall": "husky install" 47 | }, 48 | "lint-staged": { 49 | "*.ts": [ 50 | "eslint --cache --fix", 51 | "prettier --write" 52 | ], 53 | "packages/**/*.!(*ejs|ts)": [ 54 | "prettier --write" 55 | ] 56 | }, 57 | "packageManager": "yarn@3.1.1", 58 | "dependencies": { 59 | "@geut/chan": "^3.2.9", 60 | "patch-package": "^8.0.0" 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /packages/common-cosmos/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@subql/common-cosmos", 3 | "version": "5.4.2", 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-cosmos\" --release-prefix=\"common-cosmos/\"" 10 | }, 11 | "homepage": "https://github.com/subquery/subql-cosmos", 12 | "repository": "github:subquery/subql-cosmos", 13 | "author": "SubQuery Pte Ltd", 14 | "main": "dist/index.js", 15 | "license": "GPL-3.0", 16 | "dependencies": { 17 | "@cosmwasm/ts-codegen": "^1.11.1", 18 | "@protobufs/cosmos": "^0.1.0", 19 | "@protobufs/cosmos_proto": "^0.0.10", 20 | "@protobufs/cosmwasm": "^0.1.1", 21 | "@protobufs/gogoproto": "^0.0.10", 22 | "@protobufs/google": "^0.0.10", 23 | "@protobufs/ibc": "^0.1.0", 24 | "@protobufs/tendermint": "^0.0.10", 25 | "@subql/common": "^5.6.0", 26 | "@subql/types-cosmos": "workspace:*", 27 | "@subql/x-cosmology-telescope": "^1.4.14", 28 | "fs-extra": "^11.1.1", 29 | "js-yaml": "^4.1.0", 30 | "reflect-metadata": "^0.1.13" 31 | }, 32 | "peerDependencies": { 33 | "class-transformer": "*", 34 | "class-validator": "*", 35 | "ejs": "*" 36 | }, 37 | "devDependencies": { 38 | "@types/bn.js": "4.11.6", 39 | "@types/ejs": "^3.1.2", 40 | "@types/fs-extra": "^11", 41 | "@types/js-yaml": "^4.0.4", 42 | "@types/lodash": "^4", 43 | "@types/pino": "^6.3.12", 44 | "@types/rimraf": "3.0.2", 45 | "ejs": "3.1.10", 46 | "lodash": "4.17.21", 47 | "rimraf": "^3.0.2" 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /packages/common-cosmos/src/codegen/constants.ts: -------------------------------------------------------------------------------- 1 | // // Copyright 2020-2025 SubQuery Pte Ltd authors & contributors 2 | // SPDX-License-Identifier: GPL-3.0 3 | 4 | import {TSBuilderInput, ContractFile} from '@cosmwasm/ts-codegen'; 5 | import {TelescopeOptions} from '@subql/x-cosmology-types'; 6 | 7 | export const TELESCOPE_OPTS: TelescopeOptions = { 8 | removeUnusedImports: true, 9 | interfaces: { 10 | enabled: false, 11 | useUnionTypes: false, 12 | }, 13 | prototypes: { 14 | enabled: false, 15 | addTypeUrlToDecoders: true, 16 | addTypeUrlToObjects: true, 17 | excluded: { 18 | packages: [ 19 | 'amino', 20 | 'gogoproto', 21 | // 'google.api', 22 | // 'ibc.core.port.v1', 23 | // 'ibc.core.types.v1', 24 | ], 25 | // query.proto can be removed, and it is unnecessary to generate types for them 26 | protos: ['**/query.proto'], 27 | }, 28 | methods: { 29 | fromJSON: false, 30 | toJSON: false, 31 | 32 | encode: false, 33 | decode: false, 34 | 35 | toSDK: false, 36 | fromSDK: false, 37 | 38 | toAmino: false, 39 | fromAmino: false, 40 | fromProto: false, 41 | toProto: false, 42 | }, 43 | parser: { 44 | keepCase: false, 45 | }, 46 | typingsFormat: { 47 | duration: 'duration', 48 | timestamp: 'date', 49 | useExact: false, 50 | useDeepPartial: false, 51 | }, 52 | }, 53 | aminoEncoding: { 54 | enabled: false, 55 | exceptions: {}, 56 | }, 57 | lcdClients: { 58 | enabled: false, 59 | }, 60 | rpcClients: { 61 | // unsure if needed 62 | enabled: false, 63 | camelCase: true, 64 | }, 65 | }; 66 | 67 | export const COSMWASM_OPTS = (outPath: string, contracts: (ContractFile | string)[]): TSBuilderInput => { 68 | return { 69 | contracts, 70 | outPath, 71 | options: { 72 | bundle: { 73 | enabled: false, 74 | }, 75 | types: { 76 | enabled: true, 77 | }, 78 | messageComposer: { 79 | enabled: true, 80 | }, 81 | }, 82 | }; 83 | }; 84 | -------------------------------------------------------------------------------- /packages/common-cosmos/src/codegen/index.ts: -------------------------------------------------------------------------------- 1 | // // Copyright 2020-2025 SubQuery Pte Ltd authors & contributors 2 | // SPDX-License-Identifier: GPL-3.0 3 | 4 | export * from './codegen-controller'; 5 | export * from './util'; 6 | -------------------------------------------------------------------------------- /packages/common-cosmos/src/codegen/util.ts: -------------------------------------------------------------------------------- 1 | // // Copyright 2020-2025 SubQuery Pte Ltd authors & contributors 2 | // SPDX-License-Identifier: GPL-3.0 3 | 4 | import path from 'path'; 5 | import {loadFromJsonOrYaml} from '@subql/common'; 6 | import {IDLObject} from 'wasm-ast-types'; 7 | import {parseCosmosProjectManifest, ProjectManifestImpls} from '../project'; 8 | 9 | export function validateCosmosManifest(manifest: unknown): manifest is ProjectManifestImpls { 10 | try { 11 | return !!parseCosmosProjectManifest(manifest); 12 | } catch (e) { 13 | return false; 14 | } 15 | } 16 | 17 | export function loadCosmwasmAbis(filePath: string): IDLObject { 18 | return loadFromJsonOrYaml(filePath) as IDLObject; 19 | } 20 | 21 | export function tmpProtoDir(tmpDir: string, protoPath: string): string { 22 | return path.join(tmpDir, path.basename(protoPath)); 23 | } 24 | -------------------------------------------------------------------------------- /packages/common-cosmos/src/index.ts: -------------------------------------------------------------------------------- 1 | // // Copyright 2020-2025 SubQuery Pte Ltd authors & contributors 2 | // SPDX-License-Identifier: GPL-3.0 3 | 4 | export * from './codegen'; 5 | export * from './project'; 6 | 7 | import {CosmosNetworkModule} from '@subql/types-cosmos'; 8 | import * as c from './codegen'; 9 | import * as p from './project'; 10 | 11 | // This provides a compiled time check to ensure that the correct exports are provided 12 | // eslint-disable-next-line @typescript-eslint/no-unused-vars 13 | const _ = { 14 | ...p, 15 | ...c, 16 | } satisfies CosmosNetworkModule; 17 | -------------------------------------------------------------------------------- /packages/common-cosmos/src/project/index.ts: -------------------------------------------------------------------------------- 1 | // // Copyright 2020-2025 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 | 10 | import {parseCosmosProjectManifest} from './load'; 11 | export {parseCosmosProjectManifest as parseProjectManifest}; 12 | import {isRuntimeCosmosDs, isCustomCosmosDs} from './utils'; 13 | export {isRuntimeCosmosDs as isRuntimeDs, isCustomCosmosDs as isCustomDs}; 14 | -------------------------------------------------------------------------------- /packages/common-cosmos/src/project/load.ts: -------------------------------------------------------------------------------- 1 | // // Copyright 2020-2025 SubQuery Pte Ltd authors & contributors 2 | // SPDX-License-Identifier: GPL-3.0 3 | 4 | import {CosmosProjectManifestVersioned, VersionedProjectManifest} from './versioned'; 5 | 6 | export function parseCosmosProjectManifest(raw: unknown): CosmosProjectManifestVersioned { 7 | const projectManifest = new CosmosProjectManifestVersioned(raw as VersionedProjectManifest); 8 | projectManifest.validate(); 9 | return projectManifest; 10 | } 11 | -------------------------------------------------------------------------------- /packages/common-cosmos/src/project/models.ts: -------------------------------------------------------------------------------- 1 | // // Copyright 2020-2025 SubQuery Pte Ltd authors & contributors 2 | // SPDX-License-Identifier: GPL-3.0 3 | 4 | import {BaseDataSource, ProcessorImpl} from '@subql/common'; 5 | import {FileReference, Processor} from '@subql/types-core'; 6 | import { 7 | CosmosEventFilter, 8 | CosmosHandlerKind, 9 | CosmosCustomHandler, 10 | CosmosMapping, 11 | CosmosHandler, 12 | CosmosRuntimeHandler, 13 | CosmosRuntimeDatasource, 14 | CosmosDatasourceKind, 15 | CosmosCustomDatasource, 16 | CustomDataSourceAsset, 17 | CosmosBlockFilter, 18 | CosmosBlockHandler, 19 | CosmosEventHandler, 20 | CosmosMessageFilter, 21 | CosmosTransactionHandler, 22 | CosmosMessageHandler, 23 | CustomModule, 24 | CosmosTxFilter, 25 | } from '@subql/types-cosmos'; 26 | import {plainToClass, Transform, Type} from 'class-transformer'; 27 | import { 28 | IsArray, 29 | IsEnum, 30 | IsInt, 31 | IsOptional, 32 | IsString, 33 | IsObject, 34 | ValidateNested, 35 | ValidateIf, 36 | IsBoolean, 37 | Validate, 38 | } from 'class-validator'; 39 | import {FileReferenceImp} from './utils'; 40 | 41 | export class BlockFilter implements CosmosBlockFilter { 42 | @IsOptional() 43 | @IsInt() 44 | modulo?: number; 45 | @IsOptional() 46 | @IsString() 47 | timestamp?: string; 48 | } 49 | 50 | export class TxFilter implements CosmosTxFilter { 51 | @IsOptional() 52 | @IsBoolean() 53 | includeFailedTx?: boolean; 54 | } 55 | 56 | export class MessageFilter extends TxFilter implements CosmosMessageFilter { 57 | @IsString() 58 | type!: string; 59 | @IsOptional() 60 | @IsObject() 61 | values?: {[key: string]: string}; 62 | @ValidateIf((o) => o.type === '/cosmwasm.wasm.v1.MsgExecuteContract') 63 | @IsOptional() 64 | @IsString() 65 | contractCall?: string; 66 | } 67 | 68 | export class EventFilter implements CosmosEventFilter { 69 | @IsString() 70 | type!: string; 71 | @IsOptional() 72 | @Type(() => MessageFilter) 73 | messageFilter?: CosmosMessageFilter; 74 | @IsOptional() 75 | @IsObject() 76 | attributes?: Record; 77 | } 78 | 79 | export class BlockHandler implements CosmosBlockHandler { 80 | @IsEnum(CosmosHandlerKind, {groups: [CosmosHandlerKind.Block]}) 81 | kind!: CosmosHandlerKind.Block; 82 | @IsString() 83 | handler!: string; 84 | @IsOptional() 85 | @Type(() => BlockFilter) 86 | filter?: CosmosBlockFilter; 87 | } 88 | 89 | export class TransactionHandler implements CosmosTransactionHandler { 90 | @IsEnum(CosmosHandlerKind, {groups: [CosmosHandlerKind.Transaction]}) 91 | kind!: CosmosHandlerKind.Transaction; 92 | @IsString() 93 | handler!: string; 94 | } 95 | 96 | export class MessageHandler implements CosmosMessageHandler { 97 | @IsEnum(CosmosHandlerKind, {groups: [CosmosHandlerKind.Message]}) 98 | kind!: CosmosHandlerKind.Message; 99 | @IsString() 100 | handler!: string; 101 | @IsOptional() 102 | @ValidateNested() 103 | @Type(() => MessageFilter) 104 | filter?: CosmosMessageFilter; 105 | } 106 | 107 | export class EventHandler implements CosmosEventHandler { 108 | @IsOptional() 109 | @ValidateNested() 110 | @Type(() => EventFilter) 111 | filter?: CosmosEventFilter; 112 | @IsEnum(CosmosHandlerKind, {groups: [CosmosHandlerKind.Event]}) 113 | kind!: CosmosHandlerKind.Event; 114 | @IsString() 115 | handler!: string; 116 | } 117 | 118 | export class CustomHandler implements CosmosCustomHandler { 119 | @IsString() 120 | kind!: string; 121 | @IsString() 122 | handler!: string; 123 | @IsObject() 124 | @IsOptional() 125 | filter?: Record; 126 | } 127 | 128 | export class RuntimeMapping implements CosmosMapping { 129 | @Transform((params) => { 130 | const handlers: CosmosHandler[] = params.value; 131 | return handlers.map((handler) => { 132 | switch (handler.kind) { 133 | case CosmosHandlerKind.Event: 134 | return plainToClass(EventHandler, handler); 135 | case CosmosHandlerKind.Message: 136 | return plainToClass(MessageHandler, handler); 137 | case CosmosHandlerKind.Transaction: 138 | return plainToClass(TransactionHandler, handler); 139 | case CosmosHandlerKind.Block: 140 | return plainToClass(BlockHandler, handler); 141 | default: 142 | throw new Error(`handler ${(handler as any).kind} not supported`); 143 | } 144 | }); 145 | }) 146 | @IsArray() 147 | @ValidateNested() 148 | handlers!: CosmosHandler[]; 149 | @IsString() 150 | file!: string; 151 | } 152 | 153 | export class CustomMapping implements CosmosMapping { 154 | @IsArray() 155 | @Type(() => CustomHandler) 156 | @ValidateNested() 157 | handlers!: CosmosCustomHandler[]; 158 | @IsString() 159 | file!: string; 160 | } 161 | 162 | export class CosmosProcessorOptions implements CosmosProcessorOptions { 163 | @IsOptional() 164 | @IsString() 165 | abi?: string; 166 | } 167 | 168 | export class CosmosRuntimeDataSourceBase> 169 | extends BaseDataSource 170 | implements CosmosRuntimeDatasource 171 | { 172 | @IsEnum(CosmosDatasourceKind, {groups: [CosmosDatasourceKind.Runtime]}) 173 | kind!: CosmosDatasourceKind.Runtime; 174 | @Type(() => RuntimeMapping) 175 | @ValidateNested() 176 | mapping!: M; 177 | @IsOptional() 178 | @Validate(FileReferenceImp) 179 | assets?: Map; 180 | @IsOptional() 181 | @Type(() => CosmosProcessorOptions) 182 | @ValidateNested() 183 | options?: CosmosProcessorOptions; 184 | } 185 | 186 | export class CosmosFileReferenceImpl implements FileReference { 187 | @IsString() 188 | file!: string; 189 | } 190 | 191 | export class CosmosCustomModuleImpl implements CustomModule { 192 | @IsString() 193 | file!: string; 194 | @IsArray() 195 | @Type(() => String) 196 | messages!: string[]; 197 | } 198 | 199 | export class CosmosCustomDataSourceBase< 200 | K extends string, 201 | M extends CosmosMapping = CosmosMapping, 202 | O = any 203 | > 204 | extends BaseDataSource 205 | implements CosmosCustomDatasource 206 | { 207 | @IsString() 208 | kind!: K; 209 | @Type(() => CustomMapping) 210 | @ValidateNested() 211 | mapping!: M; 212 | @Type(() => CosmosFileReferenceImpl) 213 | @ValidateNested({each: true}) 214 | assets!: Map; 215 | @Type(() => ProcessorImpl) 216 | @IsObject() 217 | processor!: Processor; 218 | } 219 | -------------------------------------------------------------------------------- /packages/common-cosmos/src/project/project.spec.ts: -------------------------------------------------------------------------------- 1 | // // Copyright 2020-2025 SubQuery Pte Ltd authors & contributors 2 | // SPDX-License-Identifier: GPL-3.0 3 | 4 | import path from 'path'; 5 | import {getManifestPath, loadFromJsonOrYaml} from '@subql/common'; 6 | import {validateCosmosManifest} from '../codegen/util'; 7 | import {parseCosmosProjectManifest} from './load'; 8 | import {CosmosProjectManifestVersioned, VersionedProjectManifest} from './versioned'; 9 | 10 | const projectsDir = path.join(__dirname, '../../test'); 11 | 12 | function loadCosmosProjectManifest(file: string): CosmosProjectManifestVersioned { 13 | const doc = loadFromJsonOrYaml(getManifestPath(file)); 14 | const projectManifest = new CosmosProjectManifestVersioned(doc as VersionedProjectManifest); 15 | projectManifest.validate(); 16 | return projectManifest; 17 | } 18 | 19 | describe('project.yaml', () => { 20 | it('can validate a v1.0.0 project.yaml', () => { 21 | expect(() => loadCosmosProjectManifest(path.join(projectsDir, 'project_1.0.0.yaml'))).not.toThrow(); 22 | }); 23 | 24 | it('can validate a v1.0.0 project.yaml with unsupported runner node', () => { 25 | expect(() => loadCosmosProjectManifest(path.join(projectsDir, 'project_1.0.0_bad_runner.yaml'))).toThrow(); 26 | }); 27 | it('assets should be validated', () => { 28 | expect(() => 29 | loadCosmosProjectManifest(path.join(projectsDir, 'protoTest1', 'cosmwasm-project.yaml')) 30 | ).not.toThrow(); 31 | }); 32 | it('Should throw on invalid FileReference on asset', () => { 33 | expect(() => 34 | loadCosmosProjectManifest(path.join(projectsDir, 'protoTest1', 'bad-abi-cosmos-project.yaml')) 35 | ).toThrow('- property dataSources[0].assets has failed the following constraints: isFileReference'); 36 | }); 37 | it('Ensure correctness on Cosmos Manifest validate', () => { 38 | const cosmosManifest = loadFromJsonOrYaml(path.join(projectsDir, './protoTest1', 'project.yaml')) as any; 39 | const ethManifest = loadFromJsonOrYaml(path.join(projectsDir, 'project_1.0.0_bad_runner.yaml')) as any; 40 | expect(validateCosmosManifest(cosmosManifest)).toBe(true); 41 | expect(validateCosmosManifest(ethManifest)).toBe(false); 42 | }); 43 | it('Validate incorrect chaintypes', () => { 44 | const cosmosManifest = loadFromJsonOrYaml( 45 | path.join(projectsDir, './protoTest1', 'bad-chaintypes-project.yaml') 46 | ) as any; 47 | expect(() => parseCosmosProjectManifest(cosmosManifest)).toThrow( 48 | 'Failed to parse project. Please see below for more information' 49 | ); 50 | }); 51 | it('Ensure chaintypes existence on manifest deployment', () => { 52 | const cosmosManifest = loadFromJsonOrYaml(path.join(projectsDir, './protoTest1', 'project.yaml')) as any; 53 | const manifest = parseCosmosProjectManifest(cosmosManifest); 54 | expect(manifest.asImpl.network.chaintypes?.size).toBeGreaterThan(0); 55 | }); 56 | }); 57 | -------------------------------------------------------------------------------- /packages/common-cosmos/src/project/types.ts: -------------------------------------------------------------------------------- 1 | // // Copyright 2020-2025 SubQuery Pte Ltd authors & contributors 2 | // SPDX-License-Identifier: GPL-3.0 3 | 4 | import {IProjectManifest, ProjectNetworkConfig} from '@subql/types-core'; 5 | import {CosmosDatasource, CustomModule} from '@subql/types-cosmos'; 6 | import {Root} from 'protobufjs'; 7 | 8 | // All of these used to be redefined in this file, re-exporting for simplicity 9 | export { 10 | CosmosRuntimeHandler, 11 | CosmosCustomHandler, 12 | CosmosHandler, 13 | CosmosHandlerKind, 14 | CosmosDatasource as CosmosDataSource, 15 | CosmosBlockFilter, 16 | CosmosMessageFilter, 17 | CosmosEventFilter, 18 | CosmosDatasourceProcessor, 19 | CosmosHandlerFilter, 20 | CosmosDatasourceKind, 21 | CosmosRuntimeHandlerInputMap as CosmosRuntimeHandlerInputMap, 22 | } from '@subql/types-cosmos'; 23 | 24 | export type ICosmosProjectManifest = IProjectManifest; 25 | 26 | export interface CosmosProjectNetworkConfig extends ProjectNetworkConfig { 27 | chainId?: string; 28 | } 29 | 30 | export type CosmosChainType = CustomModule & { 31 | proto: Root; 32 | packageName?: string; 33 | }; 34 | 35 | export type CosmosProjectNetConfig = CosmosProjectNetworkConfig & { 36 | chainId: string; 37 | chaintypes: Map & {protoRoot: protobuf.Root}; 38 | }; 39 | -------------------------------------------------------------------------------- /packages/common-cosmos/src/project/utils.ts: -------------------------------------------------------------------------------- 1 | // // Copyright 2020-2025 SubQuery Pte Ltd authors & contributors 2 | // SPDX-License-Identifier: GPL-3.0 3 | 4 | import {FileReference, BaseTemplateDataSource} from '@subql/types-core'; 5 | import { 6 | SecondLayerHandlerProcessor, 7 | CosmosCustomDatasource, 8 | CosmosDatasource, 9 | CosmosDatasourceKind, 10 | CosmosHandlerKind, 11 | CosmosRuntimeDatasource, 12 | CustomDatasourceTemplate, 13 | RuntimeDatasourceTemplate, 14 | SecondLayerHandlerProcessorArray, 15 | } from '@subql/types-cosmos'; 16 | import {ValidationArguments, ValidatorConstraint, ValidatorConstraintInterface} from 'class-validator'; 17 | import {gte} from 'semver'; 18 | 19 | export function isCustomCosmosDs( 20 | ds: CosmosDatasource | BaseTemplateDataSource 21 | ): ds is CosmosCustomDatasource { 22 | return ds.kind !== CosmosDatasourceKind.Runtime && !!(ds as CosmosCustomDatasource).processor; 23 | } 24 | 25 | export function isRuntimeCosmosDs( 26 | ds: CosmosDatasource | BaseTemplateDataSource 27 | ): ds is CosmosRuntimeDatasource { 28 | return ds.kind === CosmosDatasourceKind.Runtime; 29 | } 30 | 31 | type DefaultFilter = Record; 32 | 33 | export function isBlockHandlerProcessor( 34 | hp: SecondLayerHandlerProcessorArray 35 | ): hp is SecondLayerHandlerProcessor { 36 | return hp.baseHandlerKind === CosmosHandlerKind.Block; 37 | } 38 | 39 | export function isTransactionHandlerProcessor( 40 | hp: SecondLayerHandlerProcessorArray 41 | ): hp is SecondLayerHandlerProcessor { 42 | return hp.baseHandlerKind === CosmosHandlerKind.Transaction; 43 | } 44 | 45 | export function isMessageHandlerProcessor( 46 | hp: SecondLayerHandlerProcessorArray 47 | ): hp is SecondLayerHandlerProcessor { 48 | return hp.baseHandlerKind === CosmosHandlerKind.Message; 49 | } 50 | 51 | export function isEventHandlerProcessor( 52 | hp: SecondLayerHandlerProcessorArray 53 | ): hp is SecondLayerHandlerProcessor { 54 | return hp.baseHandlerKind === CosmosHandlerKind.Event; 55 | } 56 | 57 | export function isCosmosTemplates( 58 | templatesData: any, 59 | specVersion: string 60 | ): templatesData is (RuntimeDatasourceTemplate | CustomDatasourceTemplate)[] { 61 | return (isRuntimeCosmosDs(templatesData[0]) || isCustomCosmosDs(templatesData[0])) && gte(specVersion, '0.2.1'); 62 | } 63 | 64 | @ValidatorConstraint({name: 'isFileReference', async: false}) 65 | export class FileReferenceImp implements ValidatorConstraintInterface { 66 | validate(value: Map): boolean { 67 | if (!value) { 68 | return false; 69 | } 70 | return !!Object.values(value).find((fileReference: FileReference) => this.isValidFileReference(fileReference)); 71 | } 72 | defaultMessage(args: ValidationArguments): string { 73 | return `${JSON.stringify(args.value)} is not a valid assets format`; 74 | } 75 | 76 | private isValidFileReference(fileReference: FileReference): boolean { 77 | return typeof fileReference === 'object' && 'file' in fileReference && typeof fileReference.file === 'string'; 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /packages/common-cosmos/src/project/versioned/ProjectManifestVersioned.ts: -------------------------------------------------------------------------------- 1 | // // Copyright 2020-2025 SubQuery Pte Ltd authors & contributors 2 | // SPDX-License-Identifier: GPL-3.0 3 | 4 | import {CosmosDatasource} from '@subql/types-cosmos'; 5 | import {plainToInstance} from 'class-transformer'; 6 | import {ICosmosProjectManifest} from '../types'; 7 | import {ProjectManifestV1_0_0Impl} from './v1_0_0'; 8 | 9 | export type VersionedProjectManifest = {specVersion: string}; 10 | 11 | const SUPPORTED_VERSIONS = { 12 | '1.0.0': ProjectManifestV1_0_0Impl, 13 | }; 14 | 15 | type Versions = keyof typeof SUPPORTED_VERSIONS; 16 | 17 | export type ProjectManifestImpls = InstanceType<(typeof SUPPORTED_VERSIONS)[Versions]>; 18 | 19 | export function manifestIsV1_0_0(manifest: ICosmosProjectManifest): manifest is ProjectManifestV1_0_0Impl { 20 | return manifest.specVersion === '1.0.0'; 21 | } 22 | 23 | export class CosmosProjectManifestVersioned implements ICosmosProjectManifest { 24 | private _impl: ProjectManifestImpls; 25 | 26 | constructor(projectManifest: VersionedProjectManifest) { 27 | const klass = SUPPORTED_VERSIONS[projectManifest.specVersion as Versions]; 28 | if (!klass) { 29 | throw new Error('specVersion not supported for project manifest file'); 30 | } 31 | this._impl = plainToInstance(klass, projectManifest); 32 | } 33 | 34 | get asImpl(): ProjectManifestImpls { 35 | return this._impl; 36 | } 37 | 38 | get isV1_0_0(): boolean { 39 | return this.specVersion === '1.0.0'; 40 | } 41 | 42 | get asV1_0_0(): ProjectManifestV1_0_0Impl { 43 | return this._impl as ProjectManifestV1_0_0Impl; 44 | } 45 | 46 | toDeployment(): string { 47 | return this._impl.deployment.toYaml(); 48 | } 49 | 50 | validate(): void { 51 | return this._impl.validate(); 52 | } 53 | 54 | get dataSources(): CosmosDatasource[] { 55 | return this._impl.dataSources; 56 | } 57 | 58 | get schema(): string { 59 | return this._impl.schema.file; 60 | } 61 | 62 | get specVersion(): string { 63 | return this._impl.specVersion; 64 | } 65 | 66 | get description(): string | undefined { 67 | return this._impl.description; 68 | } 69 | 70 | get repository(): string | undefined { 71 | return this._impl.repository; 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /packages/common-cosmos/src/project/versioned/index.ts: -------------------------------------------------------------------------------- 1 | // // Copyright 2020-2025 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-cosmos/src/project/versioned/v1_0_0/index.ts: -------------------------------------------------------------------------------- 1 | // // Copyright 2020-2025 SubQuery Pte Ltd authors & contributors 2 | // SPDX-License-Identifier: GPL-3.0 3 | 4 | export * from './model'; 5 | -------------------------------------------------------------------------------- /packages/common-cosmos/src/project/versioned/v1_0_0/model.ts: -------------------------------------------------------------------------------- 1 | // // Copyright 2020-2025 SubQuery Pte Ltd authors & contributors 2 | // SPDX-License-Identifier: GPL-3.0 3 | 4 | import { 5 | BaseDeploymentV1_0_0, 6 | CommonProjectNetworkV1_0_0, 7 | FileType, 8 | ParentProjectModel, 9 | ProjectManifestBaseImpl, 10 | RunnerNodeImpl, 11 | RunnerQueryBaseModel, 12 | validateObject, 13 | } from '@subql/common'; 14 | import {NodeSpec, ParentProject, QuerySpec, RunnerSpecs} from '@subql/types-core'; 15 | import { 16 | CosmosCustomDatasource, 17 | CosmosCustomHandler, 18 | CosmosMapping, 19 | CosmosRuntimeDatasource, 20 | CosmosRuntimeHandler, 21 | RuntimeDatasourceTemplate, 22 | CustomDatasourceTemplate, 23 | CosmosProjectManifestV1_0_0, 24 | CosmosChaintypes, 25 | } from '@subql/types-cosmos'; 26 | import {Transform, TransformFnParams, Type} from 'class-transformer'; 27 | import {Equals, IsObject, IsString, ValidateNested, IsOptional, IsArray, IsNotEmpty} from 'class-validator'; 28 | import {CosmosCustomDataSourceBase, CosmosCustomModuleImpl, CosmosRuntimeDataSourceBase} from '../../models'; 29 | 30 | const COSMOS_NODE_NAME = `@subql/node-cosmos`; 31 | 32 | export class CosmosRunnerNodeImpl extends RunnerNodeImpl { 33 | @Equals(COSMOS_NODE_NAME, {message: `Runner Cosmos node name incorrect, suppose be '${COSMOS_NODE_NAME}'`}) 34 | name: string = COSMOS_NODE_NAME; 35 | } 36 | 37 | export class CosmosRuntimeDataSourceImpl 38 | extends CosmosRuntimeDataSourceBase> 39 | implements CosmosRuntimeDatasource 40 | { 41 | validate(): void { 42 | return validateObject(this, 'failed to validate runtime datasource.'); 43 | } 44 | } 45 | 46 | export class CosmosCustomDataSourceImpl< 47 | K extends string = string, 48 | M extends CosmosMapping = CosmosMapping 49 | > 50 | extends CosmosCustomDataSourceBase 51 | implements CosmosCustomDatasource 52 | { 53 | validate(): void { 54 | return validateObject(this, 'failed to validate custom datasource.'); 55 | } 56 | } 57 | 58 | export class CosmosProjectNetworkDeployment { 59 | @IsString() 60 | @IsNotEmpty() 61 | @Transform(({value}: TransformFnParams) => value.trim()) 62 | chainId!: string; 63 | @IsOptional() 64 | @IsArray() 65 | bypassBlocks?: (number | string)[]; 66 | @IsOptional() 67 | @Type(() => CosmosCustomModuleImpl) 68 | @ValidateNested({each: true}) 69 | chaintypes?: Map; 70 | } 71 | 72 | export class CosmosProjectNetwork extends CommonProjectNetworkV1_0_0 { 73 | @Type(() => CosmosCustomModuleImpl) 74 | @IsOptional() 75 | @ValidateNested({each: true}) 76 | declare chaintypes?: Map; 77 | } 78 | 79 | export class RuntimeDatasourceTemplateImpl extends CosmosRuntimeDataSourceImpl implements RuntimeDatasourceTemplate { 80 | @IsString() 81 | name!: string; 82 | } 83 | 84 | export class CustomDatasourceTemplateImpl extends CosmosCustomDataSourceImpl implements CustomDatasourceTemplate { 85 | @IsString() 86 | name!: string; 87 | } 88 | 89 | export class CosmosRunnerSpecsImpl implements RunnerSpecs { 90 | @IsObject() 91 | @ValidateNested() 92 | @Type(() => CosmosRunnerNodeImpl) 93 | node!: NodeSpec; 94 | @IsObject() 95 | @ValidateNested() 96 | @Type(() => RunnerQueryBaseModel) 97 | query!: QuerySpec; 98 | } 99 | 100 | export class DeploymentV1_0_0 extends BaseDeploymentV1_0_0 { 101 | @ValidateNested() 102 | @Type(() => CosmosProjectNetworkDeployment) 103 | network!: CosmosProjectNetworkDeployment; 104 | @IsObject() 105 | @ValidateNested() 106 | @Type(() => CosmosRunnerSpecsImpl) 107 | runner!: RunnerSpecs; 108 | @IsArray() 109 | @ValidateNested() 110 | @Type(() => CosmosCustomDataSourceImpl, { 111 | discriminator: { 112 | property: 'kind', 113 | subTypes: [{value: CosmosRuntimeDataSourceImpl, name: 'cosmos/Runtime'}], 114 | }, 115 | keepDiscriminatorProperty: true, 116 | }) 117 | dataSources!: (CosmosRuntimeDatasource | CosmosCustomDatasource)[]; 118 | @IsOptional() 119 | @IsArray() 120 | @ValidateNested() 121 | @Type(() => CustomDatasourceTemplateImpl, { 122 | discriminator: { 123 | property: 'kind', 124 | subTypes: [{value: RuntimeDatasourceTemplateImpl, name: 'cosmos/Runtime'}], 125 | }, 126 | keepDiscriminatorProperty: true, 127 | }) 128 | templates?: (RuntimeDatasourceTemplate | CustomDatasourceTemplate)[]; 129 | } 130 | 131 | export class ProjectManifestV1_0_0Impl 132 | extends ProjectManifestBaseImpl 133 | implements CosmosProjectManifestV1_0_0 134 | { 135 | constructor() { 136 | super(DeploymentV1_0_0); 137 | } 138 | 139 | @Equals('1.0.0') 140 | specVersion = '1.0.0'; 141 | @IsString() 142 | name!: string; 143 | @IsString() 144 | version!: string; 145 | @IsObject() 146 | @ValidateNested() 147 | @Type(() => CosmosProjectNetwork) 148 | network!: CosmosProjectNetwork; 149 | @ValidateNested() 150 | @Type(() => FileType) 151 | schema!: FileType; 152 | @IsArray() 153 | @ValidateNested() 154 | @Type(() => CosmosCustomDataSourceImpl, { 155 | discriminator: { 156 | property: 'kind', 157 | subTypes: [{value: CosmosRuntimeDataSourceImpl, name: 'cosmos/Runtime'}], 158 | }, 159 | keepDiscriminatorProperty: true, 160 | }) 161 | dataSources!: (CosmosRuntimeDatasource | CosmosCustomDatasource)[]; 162 | @IsOptional() 163 | @IsArray() 164 | @ValidateNested() 165 | @Type(() => CustomDatasourceTemplateImpl, { 166 | discriminator: { 167 | property: 'kind', 168 | subTypes: [{value: RuntimeDatasourceTemplateImpl, name: 'cosmos/Runtime'}], 169 | }, 170 | keepDiscriminatorProperty: true, 171 | }) 172 | templates?: (RuntimeDatasourceTemplate | CustomDatasourceTemplate)[]; 173 | @IsObject() 174 | @ValidateNested() 175 | @Type(() => CosmosRunnerSpecsImpl) 176 | runner!: RunnerSpecs; 177 | 178 | @IsOptional() 179 | @IsObject() 180 | @Type(() => ParentProjectModel) 181 | parent?: ParentProject; 182 | } 183 | -------------------------------------------------------------------------------- /packages/common-cosmos/templates/cosmwasm-interfaces.ts.ejs: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | 3 | // Auto-generated, DO NOT EDIT 4 | import { CosmosMessage, <%= Object.keys(props.abi.messages) %> } from "@subql/types-cosmos"; 5 | 6 | import { <%= Object.values(props.abi.messages).join(', ') %> } from "../cosmwasm-interfaces/<%=props.abi.contract %>.types"; 7 | 8 | <% Object.entries(props.abi.messages).forEach(([key, value]) => { %> 9 | export type <%= props.abi.contract%><%= value%> = CosmosMessage<<%= key %><<%= value%>>>; 10 | <% }); %> -------------------------------------------------------------------------------- /packages/common-cosmos/templates/proto-interface.ts.ejs: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | 3 | // Auto-generated , DO NOT EDIT 4 | import {CosmosMessage} from "@subql/types-cosmos"; 5 | <% props.proto.forEach(function(proto) { %> 6 | import * as <%= proto.name %> from "<%= proto.path %>"; 7 | <% }); %> 8 | <% props.proto.forEach(function(proto) { %> 9 | export namespace <%= proto.namespace %> { 10 | <% proto.messageNames.forEach(function(msg) { %> 11 | export type <%= helper.upperFirst(msg) %>Message = CosmosMessage<<%= proto.name %>.<%= helper.upperFirst(msg) %>>;<% }); %> 12 | } 13 | <% }); %> 14 | -------------------------------------------------------------------------------- /packages/common-cosmos/test/project_1.0.0.yaml: -------------------------------------------------------------------------------- 1 | specVersion: 1.0.0 2 | name: cosmos-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 based 13 | SubQuery project 14 | repository: https://github.com/subquery/terra-subql-starter 15 | schema: 16 | file: ./schema.graphql 17 | network: 18 | chainId: cosmoshub-4 19 | endpoint: https://rpc.cosmos.network:443 20 | 21 | dataSources: 22 | - kind: cosmos/Runtime 23 | startBlock: 10346000 24 | mapping: 25 | file: './dist/index.js' 26 | handlers: 27 | - handler: handleBlock 28 | kind: cosmos/BlockHandler 29 | - handler: handleTransaction 30 | kind: cosmos/TransactionHandler 31 | - handler: handleEvent 32 | kind: cosmos/EventHandler 33 | filter: 34 | type: transfer 35 | messageFilter: 36 | type: '/cosmos.bank.v1beta1.MsgSend' 37 | - handler: handleMessage 38 | kind: cosmos/MessageHandler 39 | filter: 40 | type: '/cosmos.bank.v1beta1.MsgSend' 41 | -------------------------------------------------------------------------------- /packages/common-cosmos/test/project_1.0.0_bad_runner.yaml: -------------------------------------------------------------------------------- 1 | specVersion: '1.0.0' 2 | 3 | name: 'cosmos-subql-starter' 4 | version: '0.0.0' 5 | description: '' 6 | repository: 'https://github.com/developerinprogress/subqlstarter-terra' 7 | runner: 8 | node: 9 | name: '@subql/node' 10 | version: 0.28.0 11 | query: 12 | name: '@subql/query' 13 | version: ^0.12.0 14 | 15 | schema: 16 | file: './schema.graphql' 17 | 18 | network: 19 | endpoint: 'https://terra.stakesystems.io' 20 | chainId: 'columbus-5' 21 | 22 | dataSources: 23 | - kind: terra/Runtime 24 | startBlock: 6694554 25 | mapping: 26 | file: './dist/index.js' 27 | handlers: 28 | - handler: handleBlock 29 | kind: terra/BlockHandler 30 | - handler: handleEvent 31 | kind: terra/EventHandler 32 | filter: 33 | type: transfer 34 | -------------------------------------------------------------------------------- /packages/common-cosmos/test/protoTest1/bad-abi-cosmos-project.yaml: -------------------------------------------------------------------------------- 1 | specVersion: 1.0.0 2 | name: test 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 | schema: 12 | file: ./schema.graphql 13 | dataSources: 14 | - kind: cosmos/Runtime 15 | startBlock: 6000000 16 | options: 17 | abi: cw20 18 | assets: 19 | baseMinter: 20 | filePath: './cosmwasm-contract/cw20/schema/cw20.json' 21 | mapping: 22 | file: ./dist/index.js 23 | handlers: 24 | - handler: handleMessage 25 | kind: cosmos/MessageHandler 26 | filter: 27 | type: /cosmwasm.wasm.v1.MsgExecuteContract 28 | -------------------------------------------------------------------------------- /packages/common-cosmos/test/protoTest1/bad-chaintypes-project.yaml: -------------------------------------------------------------------------------- 1 | specVersion: 1.0.0 2 | name: test 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 | repository: '' 13 | schema: 14 | file: ./schema.graphql 15 | network: 16 | chainId: osmosis-1 17 | endpoint: 18 | - https://osmosis.api.onfinality.io/public 19 | dictionary: 'https://api.subquery.network/sq/subquery/cosmos-osmosis-dictionary' 20 | chaintypes: 21 | osmosis.gamm.v1beta1: 22 | filePath: './proto/osmosis/gamm/v1beta1/tx.proto' 23 | message: 24 | - MsgSwapExactAmountIn 25 | osmosis.poolmanager.v1beta1: 26 | # needed by MsgSwapExactAmountIn 27 | file: './proto/osmosis/poolmanager/v1beta1/swap_route.proto' 28 | messages: 29 | - SwapAmountInRoute 30 | 31 | dataSources: 32 | - kind: cosmos/Runtime 33 | startBlock: 9798050 34 | mapping: 35 | file: ./dist/index.js 36 | handlers: 37 | - handler: handleMessage 38 | kind: cosmos/MessageHandler 39 | filter: 40 | type: /osmosis.gamm.v1beta1.MsgSwapExactAmountIn 41 | -------------------------------------------------------------------------------- /packages/common-cosmos/test/protoTest1/cosmwasm-project.yaml: -------------------------------------------------------------------------------- 1 | specVersion: 1.0.0 2 | name: test 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 | schema: 12 | file: ./schema.graphql 13 | dataSources: 14 | - kind: cosmos/Runtime 15 | startBlock: 6000000 16 | options: 17 | abi: cw20 18 | assets: 19 | baseMinter: 20 | file: './cosmwasm-contract/cw20/schema/cw20.json' 21 | mapping: 22 | file: ./dist/index.js 23 | handlers: 24 | - handler: handleMessage 25 | kind: cosmos/MessageHandler 26 | filter: 27 | type: /cosmwasm.wasm.v1.MsgExecuteContract 28 | -------------------------------------------------------------------------------- /packages/common-cosmos/test/protoTest1/project.yaml: -------------------------------------------------------------------------------- 1 | specVersion: 1.0.0 2 | name: test 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 | repository: '' 13 | schema: 14 | file: ./schema.graphql 15 | network: 16 | chainId: osmosis-1 17 | endpoint: 18 | - https://osmosis.api.onfinality.io/public 19 | dictionary: 'https://api.subquery.network/sq/subquery/cosmos-osmosis-dictionary' 20 | chaintypes: 21 | osmosis.gamm.v1beta1: 22 | file: './proto/osmosis/gamm/v1beta1/tx.proto' 23 | messages: 24 | - MsgSwapExactAmountIn 25 | osmosis.poolmanager.v1beta1: 26 | # needed by MsgSwapExactAmountIn 27 | file: './proto/osmosis/poolmanager/v1beta1/swap_route.proto' 28 | messages: 29 | - SwapAmountInRoute 30 | cosmos.base.v1beta1: 31 | # needed by MsgSwapExactAmountIn 32 | file: './proto/cosmos/base/v1beta1/coin.proto' 33 | messages: 34 | - 'Coin' 35 | 36 | dataSources: 37 | - kind: cosmos/Runtime 38 | startBlock: 9798050 39 | mapping: 40 | file: ./dist/index.js 41 | handlers: 42 | - handler: handleMessage 43 | kind: cosmos/MessageHandler 44 | filter: 45 | type: /osmosis.gamm.v1beta1.MsgSwapExactAmountIn 46 | -------------------------------------------------------------------------------- /packages/common-cosmos/test/protoTest1/proto/cosmos/base/v1beta1/coin.proto: -------------------------------------------------------------------------------- 1 | fake proto -------------------------------------------------------------------------------- /packages/common-cosmos/test/protoTest1/proto/osmosis/gamm/v1beta1/tx.proto: -------------------------------------------------------------------------------- 1 | fake proto -------------------------------------------------------------------------------- /packages/common-cosmos/test/protoTest1/proto/osmosis/poolmanager/v1beta1/swap_route.proto: -------------------------------------------------------------------------------- 1 | fake proto -------------------------------------------------------------------------------- /packages/common-cosmos/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/.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/Dockerfile: -------------------------------------------------------------------------------- 1 | # Build stage 2 | FROM node:lts-alpine as builder 3 | # Set working directory 4 | WORKDIR /app 5 | 6 | # Copy all packages 7 | COPY ./packages ./packages 8 | 9 | # Copy tsconfig.json 10 | COPY ./tsconfig.json ./tsconfig.json 11 | 12 | # Copy build script 13 | COPY ./scripts/build.sh ./scripts/build.sh 14 | 15 | # Install dependencies and build 16 | RUN ./scripts/build.sh packages/node 17 | 18 | # Production stage 19 | FROM node:lts-alpine 20 | 21 | # Copy .tgz file from builder 22 | COPY --from=builder /app/packages/node/app.tgz /app.tgz 23 | 24 | # Install production dependencies 25 | RUN apk add --no-cache tini curl git && \ 26 | apk add --no-cache python3 make g++ && \ 27 | npm install -g node-gyp 28 | 29 | # Install the app 30 | RUN npm i -g app.tgz 31 | 32 | # Clean up unused deps 33 | RUN rm /app.tgz && \ 34 | yarn cache clean && \ 35 | rm -rf /root/.npm /root/.cache 36 | 37 | # Create ./.monitor directory and set permissions 38 | RUN mkdir -p .monitor && \ 39 | chown 1000:1000 .monitor 40 | 41 | # Make the user not ROOT 42 | USER 1000 43 | ENV TZ=utc 44 | 45 | # Set Entry point and command 46 | ENTRYPOINT ["/sbin/tini", "--", "/usr/local/lib/node_modules/@subql/node-cosmos/bin/run"] 47 | CMD ["-f","/app"] 48 | -------------------------------------------------------------------------------- /packages/node/README.md: -------------------------------------------------------------------------------- 1 | # @subql-node 2 | 3 | ## Description 4 | 5 | Indexer service in our @subql toolkit, can load user's subquery then fetch, process and persist to db accordingly. 6 | 7 | ## Installation 8 | 9 | ```bash 10 | $ npm i -g @subql/node-terra 11 | ``` 12 | 13 | ## Running the app 14 | 15 | ``` 16 | $> subql-node-cosmos 17 | 18 | Commands: 19 | run force-clean Force cleans the database, dropping project schemas and 20 | tables (Once the command is executed, the application would 21 | exit upon completion) 22 | 23 | run reindex Reindex to specified block height (Once the command is 24 | executed, the application would exit upon completion). 25 | 26 | Options: 27 | --help Show help [boolean] 28 | --version Show version number [boolean] 29 | -f, --subquery Local path or IPFS cid of the subquery project 30 | [string] [required] [default: process.cwd()] 31 | --subquery-name Name of the subquery project [deprecated] [string] 32 | -c, --config Specify configuration file [string] 33 | --local Use local mode [deprecated] [boolean] 34 | --db-schema Db schema name of the project [string] 35 | --unsafe Allows usage of any built-in module within the 36 | sandbox [boolean] 37 | --subscription Enable subscription by create notification triggers 38 | [boolean] [default: false] 39 | --batch-size Batch size of blocks to fetch in one round [number] 40 | --scale-batch-size scale batch size based on memory usage 41 | [boolean] [default: false] 42 | --timeout Timeout for indexer sandbox to execute the mapping 43 | functions [number] 44 | --debug Show debug information to console output. will 45 | forcefully set log level to debug 46 | [boolean] [default: false] 47 | --profiler Show profiler information to console output 48 | [boolean] [default: false] 49 | --network-endpoint Blockchain network endpoint to connect [string] 50 | --output-fmt Print log as json or plain text 51 | [string] [choices: "json", "colored"] 52 | --log-level Specify log level to print. Ignored when --debug is 53 | used 54 | [string] [choices: "fatal", "error", "warn", "info", "debug", "trace", 55 | "silent"] 56 | --timestamp-field Enable/disable created_at and updated_at in schema 57 | [boolean] [default: false] 58 | -d, --network-dictionary Specify the dictionary api for this network [string] 59 | --dictionary-timeout Max timeout for dictionary query [number] 60 | --sponsored-dictionary Use subquery network sponsored dictionary [string] 61 | -m, --mmr-path Local path of the merkle mountain range (.mmr) file 62 | [string] 63 | --proof-of-index Enable/disable proof of index 64 | [boolean] [default: false] 65 | --ipfs IPFS gateway endpoint [string] 66 | -p, --port The port the service will bind to [number] 67 | --disable-historical Disable storing historical state entities 68 | [boolean] [default: true] 69 | -w, --workers Number of worker threads to use for fetching and 70 | processing blocks. Disabled by default. [number] 71 | --multi-chain Enables indexing multiple subquery projects into the 72 | same database schema [boolean] [default: false] 73 | ``` 74 | 75 | ## License 76 | 77 | Apache-2.0 78 | -------------------------------------------------------------------------------- /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" < { 14 | /** 15 | * This is a wrapper around the core NodeConfig to get additional properties that are provided through args or node runner options 16 | * NOTE: This isn't injected anywhere, so you need to wrap the injected node config 17 | * 18 | * @example 19 | * constructor( 20 | * nodeConfig: NodeConfig, 21 | * ) { 22 | * this.nodeConfig = new CosmosNodeConfig(nodeConfig); 23 | * } 24 | * */ 25 | constructor(config: NodeConfig) { 26 | // Rebuild with internal config 27 | super((config as any)._config, (config as any)._isTest); 28 | } 29 | 30 | get kyveEndpoint(): string { 31 | return this._config.kyveEndpoint; 32 | } 33 | 34 | get kyveChainId(): SupportedChains { 35 | return this._config.kyveChainId; 36 | } 37 | 38 | get kyveStorageUrl(): string { 39 | return this._config.kyveStorageUrl; 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /packages/node/src/configure/SubqueryProject.ts: -------------------------------------------------------------------------------- 1 | // // Copyright 2020-2025 SubQuery Pte Ltd authors & contributors 2 | // SPDX-License-Identifier: GPL-3.0 3 | 4 | import fs from 'fs'; 5 | import os from 'os'; 6 | import { sep } from 'path'; 7 | import { isMainThread } from 'worker_threads'; 8 | import { 9 | CosmosProjectNetworkConfig, 10 | parseCosmosProjectManifest, 11 | isRuntimeCosmosDs as isRuntimeDs, 12 | isCustomCosmosDs as isCustomDs, 13 | } from '@subql/common-cosmos'; 14 | import { CronFilter, WorkerHost, BaseSubqueryProject } from '@subql/node-core'; 15 | import { Reader } from '@subql/types-core'; 16 | import { 17 | CosmosDatasource, 18 | CustomDatasourceTemplate, 19 | RuntimeDatasourceTemplate, 20 | CosmosHandlerKind, 21 | CosmosBlockFilter, 22 | } from '@subql/types-cosmos'; 23 | import { processNetworkConfig } from '../utils/project'; 24 | 25 | const { version: packageVersion } = require('../../package.json'); 26 | 27 | export type CosmosProjectDsTemplate = 28 | | RuntimeDatasourceTemplate 29 | | CustomDatasourceTemplate; 30 | 31 | export type SubqlProjectBlockFilter = CosmosBlockFilter & CronFilter; 32 | 33 | // This is the runtime type after we have mapped genesisHash to chainId and endpoint/dict have been provided when dealing with deployments 34 | type NetworkConfig = CosmosProjectNetworkConfig & { chainId: string }; 35 | 36 | export type SubqueryProject = BaseSubqueryProject< 37 | CosmosDatasource, 38 | CosmosProjectDsTemplate, 39 | NetworkConfig 40 | > & { tempDir?: string }; 41 | 42 | export async function createSubQueryProject( 43 | path: string, 44 | rawManifest: unknown, 45 | reader: Reader, 46 | root: string, // If project local then directory otherwise temp directory 47 | networkOverrides?: Partial, 48 | ): Promise { 49 | const project = await BaseSubqueryProject.create({ 50 | parseManifest: (raw) => parseCosmosProjectManifest(raw).asV1_0_0, 51 | path, 52 | rawManifest, 53 | reader, 54 | root, 55 | nodeSemver: packageVersion, 56 | blockHandlerKind: CosmosHandlerKind.Block, 57 | networkOverrides, 58 | isRuntimeDs, 59 | isCustomDs, 60 | }); 61 | 62 | (project.network as any) = await processNetworkConfig( 63 | project.network, 64 | reader, 65 | ); 66 | project.tempDir = getTempDir(); 67 | 68 | return project; 69 | } 70 | 71 | /** 72 | * Gets a temp dir shared between main thread and workers 73 | * */ 74 | function getTempDir(): string { 75 | if (isMainThread) return fs.mkdtempSync(`${os.tmpdir()}${sep}`); 76 | const workerTempDir = ( 77 | (global as any).host as WorkerHost | undefined 78 | )?.getWorkerData()?.tempDir; 79 | 80 | if (!workerTempDir) { 81 | throw new Error( 82 | 'Worker expected tempDir to be provided through workerData', 83 | ); 84 | } 85 | return workerTempDir; 86 | } 87 | -------------------------------------------------------------------------------- /packages/node/src/configure/configure.module.ts: -------------------------------------------------------------------------------- 1 | // // Copyright 2020-2025 SubQuery Pte Ltd authors & contributors 2 | // SPDX-License-Identifier: GPL-3.0 3 | 4 | import { DynamicModule, Global, Module } from '@nestjs/common'; 5 | import { NodeConfig, registerApp } from '@subql/node-core'; 6 | import { yargsOptions } from '../yargs'; 7 | import { createSubQueryProject, SubqueryProject } from './SubqueryProject'; 8 | 9 | const pjson = require('../../package.json'); 10 | 11 | @Global() 12 | @Module({}) 13 | export class ConfigureModule { 14 | static async getInstance(): Promise<{ 15 | nodeConfig: NodeConfig; 16 | project: SubqueryProject; 17 | }> { 18 | const { argv } = yargsOptions; 19 | return registerApp( 20 | argv, 21 | createSubQueryProject, 22 | yargsOptions.showHelp.bind(yargsOptions), 23 | pjson, 24 | ); 25 | } 26 | static async register(): Promise { 27 | const { nodeConfig, project } = await ConfigureModule.getInstance(); 28 | return this.registerManual(nodeConfig, project); 29 | } 30 | static registerManual( 31 | nodeConfig: NodeConfig, 32 | project: SubqueryProject, 33 | ): DynamicModule { 34 | return { 35 | module: ConfigureModule, 36 | providers: [ 37 | { 38 | provide: NodeConfig, 39 | useValue: nodeConfig, 40 | }, 41 | { 42 | provide: 'ISubqueryProject', 43 | useValue: project, 44 | }, 45 | { 46 | provide: 'IProjectUpgradeService', 47 | useValue: project, 48 | }, 49 | { 50 | provide: 'Null', 51 | useValue: null, 52 | }, 53 | ], 54 | exports: [ 55 | NodeConfig, 56 | 'ISubqueryProject', 57 | 'IProjectUpgradeService', 58 | 'Null', 59 | ], 60 | }; 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /packages/node/src/indexer/api.service.test.ts: -------------------------------------------------------------------------------- 1 | // // Copyright 2020-2025 SubQuery Pte Ltd authors & contributors 2 | // SPDX-License-Identifier: GPL-3.0 3 | 4 | import path from 'path'; 5 | import { toHex } from '@cosmjs/encoding'; 6 | import { Uint53 } from '@cosmjs/math'; 7 | import { toRfc3339WithNanoseconds } from '@cosmjs/tendermint-rpc'; 8 | import { INestApplication } from '@nestjs/common'; 9 | import { EventEmitter2, EventEmitterModule } from '@nestjs/event-emitter'; 10 | import { Test } from '@nestjs/testing'; 11 | import { loadFromJsonOrYaml, makeTempDir } from '@subql/common'; 12 | import { 13 | ConnectionPoolService, 14 | ConnectionPoolStateManager, 15 | NodeConfig, 16 | } from '@subql/node-core'; 17 | import { GraphQLSchema } from 'graphql'; 18 | import { SubqueryProject } from '../configure/SubqueryProject'; 19 | import { ApiService } from './api.service'; 20 | 21 | const TEST_BLOCKNUMBER = 3266772; 22 | 23 | const projectsDir = path.join(__dirname, '../../test'); 24 | 25 | function testCosmosProject( 26 | endpoint: string, 27 | chainId: string, 28 | fileCacheDir?: string, 29 | ): SubqueryProject { 30 | return { 31 | network: { 32 | endpoint: [endpoint], 33 | chainId: chainId, 34 | }, 35 | dataSources: [], 36 | id: 'test', 37 | root: './', 38 | schema: new GraphQLSchema({}), 39 | templates: [], 40 | tempDir: fileCacheDir, 41 | } as unknown as SubqueryProject; 42 | } 43 | 44 | jest.setTimeout(200000); 45 | 46 | describe('ApiService', () => { 47 | let app: INestApplication; 48 | let apiService: ApiService; 49 | 50 | let tmpPath: string; 51 | 52 | const prepareApiService = async ( 53 | endpoint: string, 54 | chainId: string, 55 | fileCacheDir?: string, 56 | ) => { 57 | const module = await Test.createTestingModule({ 58 | providers: [ 59 | ConnectionPoolStateManager, 60 | ConnectionPoolService, 61 | { 62 | provide: 'ISubqueryProject', 63 | useFactory: () => testCosmosProject(endpoint, chainId, fileCacheDir), 64 | }, 65 | { 66 | provide: NodeConfig, 67 | useFactory: () => 68 | new NodeConfig( 69 | { 70 | kyveEndpoint: 'https://api-us-1.kyve.network', 71 | kyveStorageUrl: 'https://arweave.net', 72 | } as any, 73 | true, 74 | ), 75 | }, 76 | EventEmitter2, 77 | { 78 | provide: ApiService, 79 | useFactory: ApiService.create.bind(ApiService), 80 | inject: [ 81 | 'ISubqueryProject', 82 | ConnectionPoolService, 83 | EventEmitter2, 84 | NodeConfig, 85 | ], 86 | }, 87 | ], 88 | imports: [EventEmitterModule.forRoot()], 89 | }).compile(); 90 | app = module.createNestApplication(); 91 | await app.init(); 92 | apiService = app.get(ApiService); 93 | }; 94 | 95 | const ENDPOINT = 'https://rpc-juno.itastakers.com/'; 96 | const CHAINID = 'juno-1'; 97 | 98 | describe('RPC api service', () => { 99 | beforeAll(async () => { 100 | tmpPath = await makeTempDir(); 101 | }); 102 | 103 | it('Falls back on rpc if kyve fails', async () => { 104 | const endpoint = 'https://rpc.mainnet.archway.io:443'; 105 | const chainId = 'archway-1'; 106 | 107 | await prepareApiService(endpoint, chainId, tmpPath); 108 | 109 | jest 110 | .spyOn((apiService as any).kyveApi, 'retrieveBundleData') 111 | .mockRejectedValueOnce( 112 | 'Error: Client network socket disconnected before secure TLS connection was established', 113 | ); 114 | 115 | const rpcFetchSpy = jest.spyOn(apiService as any, 'retryFetch'); 116 | 117 | await apiService.fetchBlocks([4282099]); 118 | 119 | expect(rpcFetchSpy).toHaveBeenCalledTimes(1); 120 | }); 121 | 122 | it.skip('query block info', async () => { 123 | await prepareApiService(ENDPOINT, CHAINID, tmpPath); 124 | 125 | const api = apiService.api; 126 | const blockInfo = await api.blockInfo(TEST_BLOCKNUMBER); 127 | const doc: any = loadFromJsonOrYaml( 128 | path.join(projectsDir, 'block_3266772.json'), 129 | ); 130 | const realBlockInfo = { 131 | id: toHex(doc.block_id.hash).toUpperCase(), 132 | header: { 133 | version: { 134 | block: new Uint53(+doc.block.header.version.block).toString(), 135 | app: blockInfo.block.header.version.app, 136 | }, 137 | height: doc.block.header.height, 138 | chainId: doc.block.header.chainId, 139 | time: toRfc3339WithNanoseconds(doc.block.header.time), 140 | }, 141 | txs: doc.block.txs, 142 | }; 143 | expect(blockInfo).toMatchObject(realBlockInfo); 144 | }); 145 | 146 | it.skip('query tx info by height', async () => { 147 | await prepareApiService(ENDPOINT, CHAINID, tmpPath); 148 | 149 | const api = apiService.api; 150 | const txInfos = await api.txInfoByHeight(TEST_BLOCKNUMBER); 151 | expect(txInfos.length).toEqual(4); 152 | }); 153 | }); 154 | }); 155 | -------------------------------------------------------------------------------- /packages/node/src/indexer/dictionary/dictionary.service.ts: -------------------------------------------------------------------------------- 1 | // // Copyright 2020-2025 SubQuery Pte Ltd authors & contributors 2 | // SPDX-License-Identifier: GPL-3.0 3 | 4 | import { Inject, Injectable } from '@nestjs/common'; 5 | import { EventEmitter2 } from '@nestjs/event-emitter'; 6 | import { NETWORK_FAMILY } from '@subql/common'; 7 | import { 8 | NodeConfig, 9 | DictionaryService as BaseDictionaryService, 10 | getLogger, 11 | DsProcessorService, 12 | } from '@subql/node-core'; 13 | import { CosmosDatasource } from '@subql/types-cosmos'; 14 | import { SubqueryProject } from '../../configure/SubqueryProject'; 15 | import { BlockContent } from '../types'; 16 | import { DictionaryV1 } from './v1'; 17 | 18 | const logger = getLogger('DictionaryService'); 19 | 20 | @Injectable() 21 | export class DictionaryService extends BaseDictionaryService< 22 | CosmosDatasource, 23 | BlockContent 24 | > { 25 | constructor( 26 | @Inject('ISubqueryProject') protected project: SubqueryProject, 27 | nodeConfig: NodeConfig, 28 | protected dsProcessorService: DsProcessorService, 29 | eventEmitter: EventEmitter2, 30 | ) { 31 | super(project.network.chainId, nodeConfig, eventEmitter); 32 | } 33 | 34 | async initDictionaries(): Promise { 35 | const dictionariesV1: DictionaryV1[] = []; 36 | 37 | if (!this.project) { 38 | throw new Error(`Project in Dictionary service not initialized `); 39 | } 40 | 41 | const dictionaryEndpoints = await this.getDictionaryEndpoints( 42 | NETWORK_FAMILY.cosmos, 43 | this.project.network, 44 | ); 45 | 46 | for (const endpoint of dictionaryEndpoints) { 47 | try { 48 | const dictionary = await DictionaryV1.create( 49 | this.project, 50 | this.nodeConfig, 51 | this.dsProcessorService.getDsProcessor.bind(this.dsProcessorService), 52 | endpoint, 53 | ); 54 | dictionariesV1.push(dictionary); 55 | } catch (e) { 56 | logger.warn( 57 | `Dictionary endpoint "${endpoint}" is not a valid dictionary`, 58 | ); 59 | } 60 | } 61 | // v2 should be prioritised 62 | this.init(dictionariesV1); 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /packages/node/src/indexer/dictionary/v1/dictionaryV1.spec.ts: -------------------------------------------------------------------------------- 1 | // // Copyright 2020-2025 SubQuery Pte Ltd authors & contributors 2 | // SPDX-License-Identifier: GPL-3.0 3 | 4 | import { CosmosMessageFilter } from '@subql/common-cosmos'; 5 | import { NodeConfig } from '@subql/node-core'; 6 | import { DictionaryV1, messageFilterToQueryEntry } from './dictionaryV1'; 7 | 8 | // describe('dictionary service', () => { 9 | // let dictionaryService: DictionaryV1; 10 | 11 | // beforeEach(async () => { 12 | // dictionaryService = await DictionaryV1.create( 13 | // { 14 | // network: { 15 | // chainId: 'juno-1', 16 | // dictionary: 17 | // 'https://api.subquery.network/sq/subquery/cosmos-juno-dictionary', 18 | // }, 19 | // } as any, 20 | // { dictionaryTimeout: 10000 } as NodeConfig, 21 | // new EventEmitter2(), 22 | // ); 23 | // }); 24 | 25 | // it('successfully validates metatada', async () => { 26 | // /* Genesis hash is unused with cosmos, chainId is used from project instead */ 27 | // await expect( 28 | // dictionaryService.initValidation('juno-1'), 29 | // ).resolves.toBeTruthy(); 30 | // }); 31 | // }); 32 | 33 | type DictionaryQuery = DictionaryV1['dictionaryQuery']; 34 | type DictionaryServicePrivate = DictionaryV1 & { 35 | dictionaryQuery: DictionaryQuery; 36 | }; 37 | 38 | const nodeConfig = new NodeConfig({ 39 | subquery: 'asdf', 40 | subqueryName: 'asdf', 41 | networkEndpoint: { 'https://rpc-juno.itastakers.com/': {} }, 42 | dictionaryTimeout: 10, 43 | }); 44 | 45 | // eslint-disable-next-line @typescript-eslint/require-await 46 | async function mockDictionaryService( 47 | url: string, 48 | ): Promise { 49 | return DictionaryV1.create( 50 | { 51 | network: { 52 | dictionary: url, 53 | chianId: 'fetchhub-4', 54 | }, 55 | } as any, 56 | nodeConfig, 57 | () => { 58 | throw new Error(`Shouldn't be called`); 59 | }, 60 | url, 61 | ) as DictionaryServicePrivate; 62 | } 63 | 64 | describe('Dictionary Queries', () => { 65 | let dictionary: DictionaryServicePrivate; 66 | 67 | beforeAll(async () => { 68 | dictionary = await mockDictionaryService( 69 | 'https://datasource.subquery.dev/query/QmfKJuaL8iwwnSwaKt7RjTBk6Q5aUPqBzcZ1J2Q68ZvnLf', 70 | ); 71 | }); 72 | 73 | describe('Message Filter Queries', () => { 74 | it('Basic wasm filter works', () => { 75 | const filter: CosmosMessageFilter = { 76 | type: '/cosmwasm.wasm.v1.MsgExecuteContract', 77 | }; 78 | 79 | const condition = messageFilterToQueryEntry(filter); 80 | 81 | const query = (dictionary as any).dictionaryQuery( 82 | 3_093_822, 83 | 4_000_000, 84 | 5, 85 | [condition], 86 | ); 87 | 88 | expect(query).toEqual({ 89 | query: `query($messages_0_0:String!){_metadata {lastProcessedHeight chain } messages (filter:{or:[{type:{equalTo:$messages_0_0}}],blockHeight:{greaterThanOrEqualTo:"3093822",lessThan:"4000000"}},orderBy:BLOCK_HEIGHT_ASC,first:5,distinct:[BLOCK_HEIGHT]){nodes {blockHeight } } }`, 90 | variables: { messages_0_0: '/cosmwasm.wasm.v1.MsgExecuteContract' }, 91 | }); 92 | }); 93 | 94 | it('Wasm with contract filter builds a valid query', () => { 95 | const filter: CosmosMessageFilter = { 96 | type: '/cosmwasm.wasm.v1.MsgExecuteContract', 97 | contractCall: 'vote', 98 | values: { 99 | contract: 100 | 'juno1lgnstas4ruflg0eta394y8epq67s4rzhg5anssz3rc5zwvjmmvcql6qps2', 101 | }, 102 | }; 103 | 104 | const condition = messageFilterToQueryEntry(filter); 105 | 106 | const query = (dictionary as any).dictionaryQuery( 107 | 3_093_822, 108 | 4_000_000, 109 | 5, 110 | [condition], 111 | ); 112 | 113 | expect(query).toEqual({ 114 | query: `query($messages_0_0:String!,$messages_0_1:JSON){_metadata {lastProcessedHeight chain } messages (filter:{or:[{and:[{type:{equalTo:$messages_0_0}},{data:{contains:$messages_0_1}}]}],blockHeight:{greaterThanOrEqualTo:"3093822",lessThan:"4000000"}},orderBy:BLOCK_HEIGHT_ASC,first:5,distinct:[BLOCK_HEIGHT]){nodes {blockHeight } } }`, 115 | variables: { 116 | messages_0_0: '/cosmwasm.wasm.v1.MsgExecuteContract', 117 | messages_0_1: { 118 | contract: 119 | 'juno1lgnstas4ruflg0eta394y8epq67s4rzhg5anssz3rc5zwvjmmvcql6qps2', 120 | }, 121 | }, 122 | }); 123 | }); 124 | 125 | it('Wasm with nested filter works', () => { 126 | const filter: CosmosMessageFilter = { 127 | type: '/cosmwasm.wasm.v1.MsgExecuteContract', 128 | contractCall: 'swap', 129 | values: { 130 | 'msg.swap.input_token': 'Token2', 131 | }, 132 | }; 133 | 134 | const condition = messageFilterToQueryEntry(filter); 135 | 136 | expect(condition.conditions[1].value).toEqual({ 137 | msg: { swap: { input_token: 'Token2' } }, 138 | }); 139 | }); 140 | 141 | // it('Wasm with enum filter works', () => { 142 | // const filter: CosmosMessageFilter = { 143 | // type: '/cosmwasm.wasm.v1.MsgExecuteContract', 144 | // contractCall: 'swap', 145 | // values: { 146 | // 'msg.swap.input_token': 'Token2', 147 | // }, 148 | // }; 149 | 150 | // const condition = messageFilterToQueryEntry(filter); 151 | 152 | // console.log('CONDITION', condition, condition.conditions[1].value); 153 | 154 | // const query = (dictionary as any).dictionaryQuery( 155 | // 3_093_822, 4_000_000, 5, [condition] 156 | // ); 157 | 158 | // console.log('QUERY', query.query, query.variables); 159 | 160 | // }); 161 | }); 162 | 163 | // describe('Event Filter Queries', () => { 164 | 165 | // }); 166 | }); 167 | -------------------------------------------------------------------------------- /packages/node/src/indexer/dictionary/v1/index.ts: -------------------------------------------------------------------------------- 1 | // // Copyright 2020-2025 SubQuery Pte Ltd authors & contributors 2 | // SPDX-License-Identifier: GPL-3.0 3 | 4 | export * from './dictionaryV1'; 5 | -------------------------------------------------------------------------------- /packages/node/src/indexer/fetch.module.ts: -------------------------------------------------------------------------------- 1 | // // Copyright 2020-2025 SubQuery Pte Ltd authors & contributors 2 | // SPDX-License-Identifier: GPL-3.0 3 | 4 | import path from 'node:path'; 5 | import { Module } from '@nestjs/common'; 6 | import { EventEmitter2 } from '@nestjs/event-emitter'; 7 | import { 8 | CoreModule, 9 | StoreService, 10 | PoiSyncService, 11 | NodeConfig, 12 | ConnectionPoolStateManager, 13 | InMemoryCacheService, 14 | MonitorService, 15 | ConnectionPoolService, 16 | ProjectService, 17 | DynamicDsService, 18 | UnfinalizedBlocksService, 19 | FetchService, 20 | DsProcessorService, 21 | DictionaryService, 22 | MultiChainRewindService, 23 | blockDispatcherFactory, 24 | } from '@subql/node-core'; 25 | import { BlockchainService } from '../blockchain.service'; 26 | import { SubqueryProject } from '../configure/SubqueryProject'; 27 | import { ApiService } from './api.service'; 28 | import { DictionaryService as CosmosDictionaryService } from './dictionary/dictionary.service'; 29 | import { IndexerManager } from './indexer.manager'; 30 | 31 | @Module({ 32 | imports: [CoreModule], 33 | providers: [ 34 | { 35 | provide: 'APIService', 36 | useFactory: ApiService.create.bind(ApiService), 37 | inject: [ 38 | 'ISubqueryProject', 39 | ConnectionPoolService, 40 | EventEmitter2, 41 | NodeConfig, 42 | ], 43 | }, 44 | { 45 | provide: 'IBlockchainService', 46 | useClass: BlockchainService, 47 | }, 48 | IndexerManager, 49 | MultiChainRewindService, 50 | { 51 | provide: 'IBlockDispatcher', 52 | useFactory: ( 53 | ...args: Parameters> 54 | ) => { 55 | const project = args[8] as SubqueryProject; 56 | return blockDispatcherFactory( 57 | path.resolve(__dirname, '../../dist/indexer/worker/worker.js'), 58 | [], 59 | { 60 | // Needed for kyve 61 | tempDir: project.tempDir, 62 | }, 63 | )(...args); 64 | }, 65 | inject: [ 66 | NodeConfig, 67 | EventEmitter2, 68 | 'IProjectService', 69 | 'IProjectUpgradeService', 70 | InMemoryCacheService, 71 | StoreService, 72 | 'IStoreModelProvider', 73 | PoiSyncService, 74 | 'ISubqueryProject', 75 | DynamicDsService, 76 | 'IUnfinalizedBlocksService', 77 | ConnectionPoolStateManager, 78 | 'IBlockchainService', 79 | IndexerManager, 80 | MultiChainRewindService, 81 | MonitorService, 82 | ], 83 | }, 84 | FetchService, 85 | { 86 | provide: DictionaryService, 87 | useClass: CosmosDictionaryService, 88 | }, 89 | DsProcessorService, 90 | DynamicDsService, 91 | { 92 | useClass: ProjectService, 93 | provide: 'IProjectService', 94 | }, 95 | { 96 | provide: 'IUnfinalizedBlocksService', 97 | useClass: UnfinalizedBlocksService, 98 | }, 99 | ], 100 | }) 101 | export class FetchModule {} 102 | -------------------------------------------------------------------------------- /packages/node/src/indexer/rpc-clients/HttpClient.ts: -------------------------------------------------------------------------------- 1 | // // Copyright 2020-2025 SubQuery Pte Ltd authors & contributors 2 | // SPDX-License-Identifier: GPL-3.0 3 | 4 | import http from 'http'; 5 | import https from 'https'; 6 | import { 7 | isJsonRpcErrorResponse, 8 | JsonRpcRequest, 9 | JsonRpcSuccessResponse, 10 | parseJsonRpcResponse, 11 | } from '@cosmjs/json-rpc'; 12 | import { HttpEndpoint } from '@cosmjs/tendermint-rpc'; 13 | import axios, { AxiosInstance } from 'axios'; 14 | import { RpcClient } from './RpcClient'; 15 | 16 | export function hasProtocol(url: string): boolean { 17 | return url.search('://') !== -1; 18 | } 19 | 20 | export async function httpRequest( 21 | connection: AxiosInstance, 22 | request?: any, 23 | ): Promise { 24 | const { data } = await connection.post('/', request); 25 | 26 | return data; 27 | } 28 | 29 | export class HttpClient implements RpcClient { 30 | protected readonly url: string; 31 | protected readonly headers: Record; 32 | connection: AxiosInstance; 33 | 34 | constructor(endpoint: string | HttpEndpoint) { 35 | if (typeof endpoint === 'string') { 36 | // accept host.name:port and assume http protocol 37 | this.url = hasProtocol(endpoint) ? endpoint : `http://${endpoint}`; 38 | this.headers = {}; 39 | } else { 40 | this.url = endpoint.url; 41 | this.headers = endpoint.headers; 42 | } 43 | 44 | const { searchParams } = new URL(this.url); 45 | 46 | // Support OnFinality api keys 47 | const apiKey = searchParams.get('apikey'); 48 | if (apiKey) { 49 | this.headers.apikey = apiKey; 50 | this.url = this.url.slice(0, this.url.indexOf('?apikey')); 51 | } 52 | 53 | const httpAgent = new http.Agent({ keepAlive: true, maxSockets: 10 }); 54 | const httpsAgent = new https.Agent({ keepAlive: true, maxSockets: 10 }); 55 | 56 | this.connection = axios.create({ 57 | httpAgent, 58 | httpsAgent, 59 | baseURL: this.url, 60 | headers: this.headers, 61 | }); 62 | } 63 | 64 | disconnect(): void { 65 | // nothing to be done 66 | } 67 | 68 | async execute(request: JsonRpcRequest): Promise { 69 | const response = parseJsonRpcResponse( 70 | await httpRequest(this.connection, request), 71 | ); 72 | if (isJsonRpcErrorResponse(response)) { 73 | throw new Error(JSON.stringify(response.error)); 74 | } 75 | return response; 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /packages/node/src/indexer/rpc-clients/RpcClient.ts: -------------------------------------------------------------------------------- 1 | // // Copyright 2020-2025 SubQuery Pte Ltd authors & contributors 2 | // SPDX-License-Identifier: GPL-3.0 3 | 4 | import { JsonRpcRequest, JsonRpcSuccessResponse } from '@cosmjs/json-rpc'; 5 | 6 | export interface RpcClient { 7 | readonly execute: ( 8 | request: JsonRpcRequest, 9 | ) => Promise; 10 | readonly disconnect: () => void; 11 | } 12 | -------------------------------------------------------------------------------- /packages/node/src/indexer/rpc-clients/index.ts: -------------------------------------------------------------------------------- 1 | // // Copyright 2020-2025 SubQuery Pte Ltd authors & contributors 2 | // SPDX-License-Identifier: GPL-3.0 3 | 4 | export * from './HttpClient'; 5 | export * from './RpcClient'; 6 | export * from './WebsocketClient'; 7 | -------------------------------------------------------------------------------- /packages/node/src/indexer/types.ts: -------------------------------------------------------------------------------- 1 | // // Copyright 2020-2025 SubQuery Pte Ltd authors & contributors 2 | // SPDX-License-Identifier: GPL-3.0 3 | 4 | import type { 5 | tendermint34, 6 | tendermint37, 7 | comet38, 8 | } from '@cosmjs/tendermint-rpc'; 9 | import { 10 | CosmosBlock, 11 | CosmosEvent, 12 | CosmosTransaction, 13 | CosmosMessage, 14 | } from '@subql/types-cosmos'; 15 | 16 | export type BlockResponse = 17 | | tendermint34.BlockResponse 18 | | tendermint37.BlockResponse 19 | | comet38.BlockResponse; 20 | export type BlockResultsResponse = 21 | | tendermint34.BlockResultsResponse 22 | | tendermint37.BlockResultsResponse 23 | | comet38.BlockResultsResponse; 24 | 25 | export interface BlockContent { 26 | block: CosmosBlock; 27 | transactions: CosmosTransaction[]; 28 | messages: CosmosMessage[]; 29 | events: CosmosEvent[]; 30 | // Tendermint34,37 31 | beginBlockEvents?: CosmosEvent[]; 32 | endBlockEvents?: CosmosEvent[]; 33 | 34 | // Comet38 35 | finalizeBlockEvents?: CosmosEvent[]; 36 | } 37 | 38 | export type BestBlocks = Record; 39 | 40 | export function getBlockSize(block: BlockContent): number { 41 | return ( 42 | block.messages.length + 43 | block.transactions.length + 44 | block.events.length + 45 | (block.beginBlockEvents?.length ?? 0) + 46 | (block.endBlockEvents?.length ?? 0) + 47 | (block.finalizeBlockEvents?.length ?? 0) 48 | ); 49 | } 50 | -------------------------------------------------------------------------------- /packages/node/src/indexer/worker/worker-fetch.module.ts: -------------------------------------------------------------------------------- 1 | // // Copyright 2020-2025 SubQuery Pte Ltd authors & contributors 2 | // SPDX-License-Identifier: GPL-3.0 3 | 4 | import { Module } from '@nestjs/common'; 5 | import { EventEmitter2 } from '@nestjs/event-emitter'; 6 | import { 7 | WorkerCoreModule, 8 | ConnectionPoolService, 9 | NodeConfig, 10 | DsProcessorService, 11 | ProjectService, 12 | } from '@subql/node-core'; 13 | import { BlockchainService } from '../../blockchain.service'; 14 | import { ApiService } from '../api.service'; 15 | import { IndexerManager } from '../indexer.manager'; 16 | import { WorkerService } from './worker.service'; 17 | 18 | @Module({ 19 | imports: [WorkerCoreModule], 20 | providers: [ 21 | DsProcessorService, 22 | IndexerManager, 23 | { 24 | provide: 'APIService', 25 | useFactory: ApiService.create.bind(ApiService), 26 | inject: [ 27 | 'ISubqueryProject', 28 | ConnectionPoolService, 29 | EventEmitter2, 30 | NodeConfig, 31 | ], 32 | }, 33 | { 34 | provide: 'IProjectService', 35 | useClass: ProjectService, 36 | }, 37 | { 38 | provide: 'IBlockchainService', 39 | useClass: BlockchainService, 40 | }, 41 | WorkerService, 42 | ], 43 | }) 44 | export class WorkerFetchModule {} 45 | -------------------------------------------------------------------------------- /packages/node/src/indexer/worker/worker.module.ts: -------------------------------------------------------------------------------- 1 | // // Copyright 2020-2025 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 { DbModule, WorkerCoreModule } from '@subql/node-core'; 8 | import { ConfigureModule } from '../../configure/configure.module'; 9 | import { WorkerFetchModule } from './worker-fetch.module'; 10 | 11 | @Module({ 12 | imports: [ 13 | DbModule.forRoot(), 14 | EventEmitterModule.forRoot(), 15 | ConfigureModule.register(), 16 | ScheduleModule.forRoot(), 17 | WorkerCoreModule, 18 | WorkerFetchModule, 19 | ], 20 | controllers: [], 21 | }) 22 | export class WorkerModule {} 23 | -------------------------------------------------------------------------------- /packages/node/src/indexer/worker/worker.service.ts: -------------------------------------------------------------------------------- 1 | // // Copyright 2020-2025 SubQuery Pte Ltd authors & contributors 2 | // SPDX-License-Identifier: GPL-3.0 3 | 4 | import { threadId } from 'node:worker_threads'; 5 | import { Inject, Injectable } from '@nestjs/common'; 6 | import { 7 | NodeConfig, 8 | getLogger, 9 | IProjectService, 10 | ProcessBlockResponse, 11 | BaseWorkerService, 12 | IProjectUpgradeService, 13 | IBlock, 14 | Header, 15 | } from '@subql/node-core'; 16 | import { CosmosDatasource } from '@subql/types-cosmos'; 17 | import { cosmosBlockToHeader } from '../../utils/cosmos'; 18 | import { ApiService } from '../api.service'; 19 | import { IndexerManager } from '../indexer.manager'; 20 | import { BlockContent, getBlockSize } from '../types'; 21 | 22 | export type FetchBlockResponse = Header; 23 | 24 | export type WorkerStatusResponse = { 25 | threadId: number; 26 | isIndexing: boolean; 27 | fetchedBlocks: number; 28 | toFetchBlocks: number; 29 | }; 30 | 31 | const logger = getLogger(`Worker Service #${threadId}`); 32 | 33 | @Injectable() 34 | export class WorkerService extends BaseWorkerService< 35 | BlockContent, 36 | FetchBlockResponse, 37 | CosmosDatasource 38 | > { 39 | constructor( 40 | @Inject('APIService') private apiService: ApiService, 41 | private indexerManager: IndexerManager, 42 | @Inject('IProjectService') 43 | projectService: IProjectService, 44 | @Inject('IProjectUpgradeService') 45 | projectUpgradeService: IProjectUpgradeService, 46 | nodeConfig: NodeConfig, 47 | ) { 48 | super(projectService, projectUpgradeService, nodeConfig); 49 | } 50 | 51 | protected async fetchChainBlock( 52 | heights: number, 53 | extra: {}, 54 | ): Promise> { 55 | const [block] = await this.apiService.fetchBlocks([heights]); 56 | 57 | return block; 58 | } 59 | 60 | protected toBlockResponse(block: BlockContent): FetchBlockResponse { 61 | return cosmosBlockToHeader(block.block.header); 62 | } 63 | 64 | protected async processFetchedBlock( 65 | block: IBlock, 66 | dataSources: CosmosDatasource[], 67 | ): Promise { 68 | return this.indexerManager.indexBlock(block, dataSources); 69 | } 70 | 71 | getBlockSize(block: IBlock): number { 72 | return getBlockSize(block.block); 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /packages/node/src/indexer/worker/worker.ts: -------------------------------------------------------------------------------- 1 | // // Copyright 2020-2025 SubQuery Pte Ltd authors & contributors 2 | // SPDX-License-Identifier: GPL-3.0 3 | 4 | // initlogger and yargs must be imported before all other imports 5 | // making sure logger is defined before its called 6 | // eslint-disable-next-line import/order 7 | import { initLogger } from '@subql/node-core/logger'; 8 | // eslint-disable-next-line import/order 9 | import { yargsOptions } from '../../yargs'; 10 | 11 | const { argv } = yargsOptions; 12 | 13 | initLogger( 14 | argv.debug, 15 | argv.outputFmt as 'json' | 'colored', 16 | argv.logLevel as string | undefined, 17 | ); 18 | 19 | import { threadId } from 'node:worker_threads'; 20 | import { NestFactory } from '@nestjs/core'; 21 | import { 22 | getLogger, 23 | NestLogger, 24 | createWorkerHost, 25 | IBaseIndexerWorker, 26 | initWorkerServices, 27 | ProjectService, 28 | } from '@subql/node-core'; 29 | import { WorkerModule } from './worker.module'; 30 | import { WorkerService } from './worker.service'; 31 | 32 | const logger = getLogger(`worker #${threadId}`); 33 | 34 | async function initWorker(startHeight?: number): Promise { 35 | try { 36 | const app = await NestFactory.create(WorkerModule, { 37 | logger: new NestLogger(!!argv.debug), // TIP: If the worker is crashing comment out this line for better logging 38 | }); 39 | 40 | await app.init(); 41 | 42 | const projectService: ProjectService = app.get('IProjectService'); 43 | // Initialise async services, we do this here rather than in factories so we can capture one off events 44 | await projectService.init(startHeight); 45 | 46 | const workerService = app.get(WorkerService); 47 | 48 | initWorkerServices(app, workerService); 49 | } catch (e: any) { 50 | console.log('Failed to start worker', e); 51 | logger.error(e, 'Failed to start worker'); 52 | throw e; 53 | } 54 | } 55 | 56 | export type IIndexerWorker = IBaseIndexerWorker; 57 | 58 | (global as any).host = createWorkerHost([], { 59 | initWorker, 60 | }); 61 | -------------------------------------------------------------------------------- /packages/node/src/init.ts: -------------------------------------------------------------------------------- 1 | // // Copyright 2020-2025 SubQuery Pte Ltd authors & contributors 2 | // SPDX-License-Identifier: GPL-3.0 3 | 4 | import { NestFactory } from '@nestjs/core'; 5 | import { notifyUpdates } from '@subql/common'; 6 | import { 7 | exitWithError, 8 | FetchService, 9 | getLogger, 10 | getValidPort, 11 | NestLogger, 12 | ProjectService, 13 | } from '@subql/node-core'; 14 | import { AppModule } from './app.module'; 15 | import { yargsOptions } from './yargs'; 16 | const pjson = require('../package.json'); 17 | 18 | const { argv } = yargsOptions; 19 | 20 | const logger = getLogger('subql-node'); 21 | 22 | notifyUpdates(pjson, logger); 23 | 24 | export async function bootstrap(): Promise { 25 | logger.info(`Current ${pjson.name} version is ${pjson.version}`); 26 | 27 | const port = await getValidPort(argv.port); 28 | 29 | if (argv.unsafe) { 30 | logger.warn( 31 | 'UNSAFE MODE IS ENABLED. This is not recommended for most projects and will not be supported by our hosted service', 32 | ); 33 | } 34 | 35 | try { 36 | const app = await NestFactory.create(AppModule, { 37 | logger: new NestLogger(!!argv.debug), 38 | }); 39 | await app.init(); 40 | 41 | const projectService: ProjectService = app.get('IProjectService'); 42 | const fetchService = app.get(FetchService); 43 | 44 | // Initialise async services, we do this here rather than in factories, so we can capture one off events 45 | await projectService.init(); 46 | await fetchService.init(projectService.startHeight); 47 | 48 | app.enableShutdownHooks(); 49 | 50 | await app.listen(port); 51 | 52 | logger.info(`Node started on port: ${port}`); 53 | } catch (e) { 54 | exitWithError(new Error(`Node failed to start`, { cause: e }), logger); 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /packages/node/src/main.ts: -------------------------------------------------------------------------------- 1 | // // Copyright 2020-2025 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 | (BigInt.prototype as any).toJSON = function () { 10 | return this.toString(); 11 | }; 12 | 13 | // initLogger is imported from true path, to make sure getLogger (or other logger values that relies on logger) isn't initialised 14 | initLogger( 15 | argv.debug, 16 | argv.outputFmt as 'json' | 'colored', 17 | argv.logLevel as string | undefined, 18 | ); 19 | 20 | // Check for no subcommand 21 | if (!argv._[0]) { 22 | // Lazy import, to allow logger to be initialised before bootstrap() 23 | // As bootstrap runs services that requires logger 24 | const { bootstrap } = require('./init'); 25 | void bootstrap(); 26 | } 27 | -------------------------------------------------------------------------------- /packages/node/src/subcommands/forceClean.init.ts: -------------------------------------------------------------------------------- 1 | // // Copyright 2020-2025 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-2025 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-2025 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 { reindexInit as baseReindexInit, DbModule } from '@subql/node-core'; 7 | import { ConfigureModule } from '../configure/configure.module'; 8 | import { ReindexFeatureModule } from './reindex.module'; 9 | 10 | @Module({ 11 | imports: [ 12 | DbModule.forRoot(), 13 | ConfigureModule.register(), 14 | ReindexFeatureModule, 15 | EventEmitterModule.forRoot(), 16 | ], 17 | controllers: [], 18 | }) 19 | export class ReindexModule {} 20 | 21 | export const reindexInit = (targetHeight: number): Promise => 22 | baseReindexInit(ReindexModule, targetHeight); 23 | -------------------------------------------------------------------------------- /packages/node/src/subcommands/reindex.module.spec.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2020-2025 SubQuery Pte Ltd authors & contributors 2 | // SPDX-License-Identifier: GPL-3.0 3 | 4 | import path from 'node:path'; 5 | import { EventEmitterModule } from '@nestjs/event-emitter'; 6 | import { Test, TestingModule } from '@nestjs/testing'; 7 | import { LocalReader, ReaderFactory } from '@subql/common'; 8 | import { DbModule, NodeConfig } from '@subql/node-core'; 9 | import { ConfigureModule } from '../configure/configure.module'; 10 | import { createSubQueryProject } from '../configure/SubqueryProject'; 11 | import { ReindexFeatureModule } from './reindex.module'; 12 | 13 | describe('ReindexModule', () => { 14 | let module: TestingModule; 15 | const nodeConfig = new NodeConfig({ subquery: 'test' } as any); 16 | 17 | afterEach(async () => { 18 | await module?.close(); 19 | }); 20 | 21 | it('should compile without error', async () => { 22 | const projectDirV1_0_0 = path.resolve( 23 | __dirname, 24 | '../../test/projectFixture/v1.0.0', 25 | ); 26 | 27 | const reader = await ReaderFactory.create(projectDirV1_0_0); 28 | const rawManifest = await reader.getProjectSchema(); 29 | const project = await createSubQueryProject( 30 | projectDirV1_0_0, 31 | rawManifest, 32 | reader, 33 | (reader as LocalReader).root, 34 | ); 35 | module = await Test.createTestingModule({ 36 | imports: [ 37 | DbModule.forRoot(), 38 | ConfigureModule.registerManual(nodeConfig, project), 39 | EventEmitterModule.forRoot(), 40 | ReindexFeatureModule, 41 | ], 42 | }).compile(); 43 | 44 | expect(module).toBeDefined(); 45 | }, 20_000); 46 | }); 47 | -------------------------------------------------------------------------------- /packages/node/src/subcommands/reindex.module.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2020-2025 SubQuery Pte Ltd authors & contributors 2 | // SPDX-License-Identifier: GPL-3.0 3 | 4 | import { Module } from '@nestjs/common'; 5 | import { EventEmitter2 } from '@nestjs/event-emitter'; 6 | import { 7 | ForceCleanService, 8 | ReindexService, 9 | StoreService, 10 | PoiService, 11 | storeModelFactory, 12 | NodeConfig, 13 | ConnectionPoolStateManager, 14 | ConnectionPoolService, 15 | DsProcessorService, 16 | DynamicDsService, 17 | UnfinalizedBlocksService, 18 | MultiChainRewindService, 19 | } from '@subql/node-core'; 20 | import { Sequelize } from '@subql/x-sequelize'; 21 | import { BlockchainService } from '../blockchain.service'; 22 | import { ApiService } from '../indexer/api.service'; 23 | 24 | @Module({ 25 | providers: [ 26 | { 27 | provide: 'IStoreModelProvider', 28 | useFactory: storeModelFactory, 29 | inject: [NodeConfig, EventEmitter2, Sequelize], 30 | }, 31 | StoreService, 32 | ReindexService, 33 | PoiService, 34 | ForceCleanService, 35 | { 36 | provide: 'UnfinalizedBlocksService', 37 | useClass: UnfinalizedBlocksService, 38 | }, 39 | { 40 | provide: 'DynamicDsService', 41 | useClass: DynamicDsService, 42 | }, 43 | DsProcessorService, 44 | ConnectionPoolStateManager, 45 | ConnectionPoolService, 46 | { 47 | provide: 'APIService', 48 | useFactory: ApiService.create.bind(ApiService), 49 | inject: [ 50 | 'ISubqueryProject', 51 | ConnectionPoolService, 52 | EventEmitter2, 53 | NodeConfig, 54 | ], 55 | }, 56 | { 57 | provide: 'IBlockchainService', 58 | useClass: BlockchainService, 59 | }, 60 | MultiChainRewindService, 61 | ], 62 | controllers: [], 63 | }) 64 | export class ReindexFeatureModule {} 65 | -------------------------------------------------------------------------------- /packages/node/src/subcommands/testing.init.ts: -------------------------------------------------------------------------------- 1 | // // Copyright 2020-2025 SubQuery Pte Ltd authors & contributors 2 | // SPDX-License-Identifier: GPL-3.0 3 | 4 | import { exitWithError, 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 | exitWithError(new Error(`Testing failed`, { cause: e }), logger); 17 | } 18 | process.exit(0); 19 | } 20 | -------------------------------------------------------------------------------- /packages/node/src/subcommands/testing.module.spec.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2020-2025 SubQuery Pte Ltd authors & contributors 2 | // SPDX-License-Identifier: GPL-3.0 3 | 4 | import path from 'node:path'; 5 | import { EventEmitterModule } from '@nestjs/event-emitter'; 6 | import { ScheduleModule } from '@nestjs/schedule'; 7 | import { Test, TestingModule } from '@nestjs/testing'; 8 | import { LocalReader, ReaderFactory } from '@subql/common'; 9 | import { DbModule, NodeConfig } from '@subql/node-core'; 10 | import { ConfigureModule } from '../configure/configure.module'; 11 | import { createSubQueryProject } from '../configure/SubqueryProject'; 12 | import { TestingFeatureModule } from './testing.module'; 13 | 14 | describe('TestingModule', () => { 15 | let module: TestingModule; 16 | const nodeConfig = new NodeConfig({ subquery: 'test' } as any); 17 | 18 | afterEach(async () => { 19 | await module?.close(); 20 | }); 21 | 22 | it('should compile without error', async () => { 23 | const projectDirV1_0_0 = path.resolve( 24 | __dirname, 25 | '../../test/projectFixture/v1.0.0', 26 | ); 27 | 28 | const reader = await ReaderFactory.create(projectDirV1_0_0); 29 | const rawManifest = await reader.getProjectSchema(); 30 | const project = await createSubQueryProject( 31 | projectDirV1_0_0, 32 | rawManifest, 33 | reader, 34 | (reader as LocalReader).root, 35 | ); 36 | module = await Test.createTestingModule({ 37 | imports: [ 38 | DbModule.forRoot(), 39 | ConfigureModule.registerManual(nodeConfig, project), 40 | EventEmitterModule.forRoot(), 41 | ScheduleModule.forRoot(), 42 | TestingFeatureModule, 43 | ], 44 | }).compile(); 45 | 46 | expect(module).toBeDefined(); 47 | }, 20_000); 48 | }); 49 | -------------------------------------------------------------------------------- /packages/node/src/subcommands/testing.module.ts: -------------------------------------------------------------------------------- 1 | // // Copyright 2020-2025 SubQuery Pte Ltd authors & contributors 2 | // SPDX-License-Identifier: GPL-3.0 3 | 4 | import { Module } from '@nestjs/common'; 5 | import { EventEmitter2 } from '@nestjs/event-emitter'; 6 | import { 7 | ConnectionPoolService, 8 | NodeConfig, 9 | TestRunner, 10 | TestingCoreModule, 11 | ProjectService, 12 | UnfinalizedBlocksService, 13 | DsProcessorService, 14 | DynamicDsService, 15 | MultiChainRewindService, 16 | } from '@subql/node-core'; 17 | import { BlockchainService } from '../blockchain.service'; 18 | import { ApiService } from '../indexer/api.service'; 19 | import { IndexerManager } from '../indexer/indexer.manager'; 20 | 21 | @Module({ 22 | imports: [TestingCoreModule], 23 | providers: [ 24 | { 25 | provide: 'IProjectService', 26 | useClass: ProjectService, 27 | }, 28 | { 29 | provide: 'APIService', 30 | useFactory: ApiService.create.bind(ApiService), 31 | inject: [ 32 | 'ISubqueryProject', 33 | ConnectionPoolService, 34 | EventEmitter2, 35 | NodeConfig, 36 | ], 37 | }, 38 | { 39 | provide: 'IUnfinalizedBlocksService', 40 | useClass: UnfinalizedBlocksService, 41 | }, 42 | { 43 | provide: 'IBlockchainService', 44 | useClass: BlockchainService, 45 | }, 46 | TestRunner, 47 | { 48 | provide: 'IIndexerManager', 49 | useClass: IndexerManager, 50 | }, 51 | DsProcessorService, 52 | DynamicDsService, 53 | MultiChainRewindService, 54 | ], 55 | 56 | controllers: [], 57 | }) 58 | export class TestingFeatureModule {} 59 | -------------------------------------------------------------------------------- /packages/node/src/subcommands/testing.service.ts: -------------------------------------------------------------------------------- 1 | // // Copyright 2020-2025 SubQuery Pte Ltd authors & contributors 2 | // SPDX-License-Identifier: GPL-3.0 3 | 4 | import { Inject, Injectable, Module } from '@nestjs/common'; 5 | import { NestFactory } from '@nestjs/core'; 6 | import { EventEmitterModule } from '@nestjs/event-emitter'; 7 | import { ScheduleModule } from '@nestjs/schedule'; 8 | import { 9 | NestLogger, 10 | NodeConfig, 11 | TestingService as BaseTestingService, 12 | TestRunner, 13 | ProjectService, 14 | DbModule, 15 | } from '@subql/node-core'; 16 | import { CosmosDatasource } from '@subql/types-cosmos'; 17 | import { ConfigureModule } from '../configure/configure.module'; 18 | import { SubqueryProject } from '../configure/SubqueryProject'; 19 | import { CosmosClient, CosmosSafeClient } from '../indexer/api.service'; 20 | import { BlockContent } from '../indexer/types'; 21 | import { TestingFeatureModule } from './testing.module'; 22 | 23 | @Module({ 24 | imports: [ 25 | DbModule.forRoot(), 26 | ConfigureModule.register(), 27 | EventEmitterModule.forRoot(), 28 | ScheduleModule.forRoot(), 29 | TestingFeatureModule, 30 | ], 31 | controllers: [], 32 | }) 33 | export class TestingModule {} 34 | 35 | @Injectable() 36 | export class TestingService extends BaseTestingService< 37 | CosmosClient, 38 | CosmosSafeClient, 39 | BlockContent, 40 | CosmosDatasource 41 | > { 42 | constructor( 43 | nodeConfig: NodeConfig, 44 | @Inject('ISubqueryProject') project: SubqueryProject, 45 | ) { 46 | super(nodeConfig, project); 47 | } 48 | 49 | async getTestRunner(): Promise< 50 | [ 51 | close: () => Promise, 52 | runner: TestRunner< 53 | CosmosClient, 54 | CosmosSafeClient, 55 | BlockContent, 56 | CosmosDatasource 57 | >, 58 | ] 59 | > { 60 | const testContext = await NestFactory.createApplicationContext( 61 | TestingModule, 62 | { 63 | logger: new NestLogger(), 64 | }, 65 | ); 66 | 67 | await testContext.init(); 68 | 69 | const projectService: ProjectService = testContext.get('IProjectService'); 70 | await projectService.init(); 71 | 72 | return [testContext.close.bind(testContext), testContext.get(TestRunner)]; 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /packages/node/src/utils/kyve/kyveTypes.ts: -------------------------------------------------------------------------------- 1 | // // Copyright 2020-2025 SubQuery Pte Ltd authors & contributors 2 | // SPDX-License-Identifier: GPL-3.0 3 | 4 | // Note: this is due to incorrect typings provided by kyvejs 5 | // https://github.com/KYVENetwork/kyvejs/issues/131 6 | export interface BundleDetails { 7 | pool_id: string; 8 | id: string; 9 | storage_id: string; 10 | uploader: string; 11 | from_index: string; 12 | to_index: string; 13 | from_key: string; 14 | to_key: string; 15 | bundle_summary: string; 16 | data_hash: string; 17 | finalized_at: FinalizedAt; 18 | storage_provider_id: string; 19 | compression_id: string; 20 | stake_security: StakeSecurity; 21 | } 22 | 23 | interface FinalizedAt { 24 | height: string; 25 | timestamp: string; 26 | } 27 | 28 | interface StakeSecurity { 29 | valid_vote_power: string; 30 | total_vote_power: string; 31 | } 32 | -------------------------------------------------------------------------------- /packages/node/src/utils/project.spec.ts: -------------------------------------------------------------------------------- 1 | // // Copyright 2020-2025 SubQuery Pte Ltd authors & contributors 2 | // SPDX-License-Identifier: GPL-3.0 3 | 4 | import { makeTempDir } from '@subql/common'; 5 | import { isTmpDir } from './project'; 6 | 7 | describe('Project tests', () => { 8 | it('ensure isTmpDir', async () => { 9 | const tmpDir = await makeTempDir(); 10 | expect(isTmpDir(tmpDir)).toBe(true); 11 | }); 12 | it('Not isTmpDir', () => { 13 | const unixDir = '/Users/test/'; 14 | const winDir = 'C:\\Users\\test\\'; 15 | expect(isTmpDir(unixDir)).toBe(false); 16 | expect(isTmpDir(winDir)).toBe(false); 17 | }); 18 | }); 19 | -------------------------------------------------------------------------------- /packages/node/src/utils/project.ts: -------------------------------------------------------------------------------- 1 | // // Copyright 2020-2025 SubQuery Pte Ltd authors & contributors 2 | // SPDX-License-Identifier: GPL-3.0 3 | 4 | import os from 'os'; 5 | import { 6 | CosmosRuntimeHandler, 7 | CosmosCustomHandler, 8 | CosmosHandler, 9 | CosmosHandlerKind, 10 | CosmosProjectNetConfig, 11 | CosmosChainType, 12 | } from '@subql/common-cosmos'; 13 | import { Reader } from '@subql/types-core'; 14 | import * as protobuf from 'protobufjs'; 15 | 16 | export function isBaseHandler( 17 | handler: CosmosHandler, 18 | ): handler is CosmosRuntimeHandler { 19 | return Object.values(CosmosHandlerKind).includes(handler.kind); 20 | } 21 | 22 | export function isCustomHandler( 23 | handler: CosmosHandler, 24 | ): handler is CosmosCustomHandler { 25 | return !isBaseHandler(handler); 26 | } 27 | 28 | export async function processNetworkConfig( 29 | network: any, 30 | reader: Reader, 31 | ): Promise { 32 | const chaintypes = new Map() as Map< 33 | string, 34 | CosmosChainType 35 | > & { protoRoot: protobuf.Root }; 36 | if (!network.chaintypes) { 37 | network.chaintypes = chaintypes; 38 | return network; 39 | } 40 | 41 | const protoRoot = new protobuf.Root(); 42 | for (const [key, value] of network.chaintypes) { 43 | const [packageName, proto] = await loadNetworkChainType(reader, value.file); 44 | chaintypes.set(key, { ...value, packageName, proto }); 45 | 46 | protoRoot.add(proto); 47 | } 48 | chaintypes.protoRoot = protoRoot; 49 | network.chaintypes = chaintypes; 50 | return network; 51 | } 52 | 53 | export async function loadNetworkChainType( 54 | reader: Reader, 55 | file: string, 56 | ): Promise<[string | undefined, protobuf.Root]> { 57 | const proto = await reader.getFile(file); 58 | 59 | if (!proto) throw new Error(`Unable to load chain type from ${file}`); 60 | 61 | const { package: packageName, root } = protobuf.parse(proto); 62 | 63 | return [packageName, root]; 64 | } 65 | 66 | export function isTmpDir(path: string): boolean { 67 | const normalizedPath = path.replace(/\\/g, '/').toLowerCase(); 68 | return normalizedPath.startsWith( 69 | os.tmpdir().replace(/\\/g, '/').toLowerCase(), 70 | ); 71 | } 72 | -------------------------------------------------------------------------------- /packages/node/src/yargs.ts: -------------------------------------------------------------------------------- 1 | // // Copyright 2020-2025 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 | runOptions: { 26 | 'kyve-chain-id': { 27 | demandOption: false, 28 | describe: 'When indexing from Kyve, supported kyve chain-id', 29 | type: 'string', 30 | default: 'kyve-1', 31 | }, 32 | 'kyve-endpoint': { 33 | demandOption: false, 34 | describe: 35 | 'If indexing a network that Kyve supports adding a Kyve LCD endpoint will fetch blocks from Kyve. Use `false` to disable kyve.', 36 | type: 'string', 37 | default: 'https://api-us-1.kyve.network', 38 | }, 39 | 'kyve-storage-url': { 40 | demandOption: false, 41 | describe: 42 | 'When indexing from kyve, you can alternatively provide a different storageUrl to index data from, it is defaulted to arweave.', 43 | type: 'string', 44 | default: 'https://arweave.net', 45 | }, 46 | }, 47 | }); 48 | -------------------------------------------------------------------------------- /packages/node/test/jsonfy.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | // // Copyright 2020-2025 SubQuery Pte Ltd authors & contributors 3 | // SPDX-License-Identifier: GPL-3.0 4 | Object.defineProperty(exports, '__esModule', { value: true }); 5 | exports.JsonfyDatasourcePlugin = void 0; 6 | exports.JsonfyDatasourcePlugin = { 7 | kind: 'substrate/Jsonfy', 8 | validate(ds) { 9 | return; 10 | }, 11 | dsFilterProcessor(ds, api) { 12 | return true; 13 | }, 14 | handlerProcessors: { 15 | 'substrate/JsonfyEvent': { 16 | specVersion: '1.0.0', 17 | baseFilter: [], 18 | baseHandlerKind: 'substrate/EventHandler', 19 | // eslint-disable-next-line @typescript-eslint/require-await 20 | async transformer({ original, ds }) { 21 | return JSON.parse(JSON.stringify(original.toJSON())); 22 | }, 23 | filterProcessor({ filter, input, ds }) { 24 | return ( 25 | filter.module && 26 | input.event.section === filter.module && 27 | filter.method && 28 | input.event.method === filter.method 29 | ); 30 | }, 31 | filterValidator(filter) { 32 | return; 33 | }, 34 | }, 35 | }, 36 | }; 37 | exports.default = exports.JsonfyDatasourcePlugin; 38 | //# sourceMappingURL=jsonfy.js.map 39 | -------------------------------------------------------------------------------- /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": "^10", 23 | "@subql/types": "latest", 24 | "typescript": "^4.1.3", 25 | "@subql/cli": "latest" 26 | }, 27 | "resolutions": { 28 | "ipfs-unixfs": "6.0.6" 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /packages/node/test/projectFixture/v1.0.0/dist/index.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/subquery/subql-cosmos/ccdfe23be59fcd59ab44bb6faf950ca655341ee9/packages/node/test/projectFixture/v1.0.0/dist/index.js -------------------------------------------------------------------------------- /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": "^10", 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/test/projectFixture/v1.0.0/project.yaml: -------------------------------------------------------------------------------- 1 | specVersion: 1.0.0 2 | name: cosmos-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 based 13 | SubQuery project 14 | repository: https://github.com/subquery/terra-subql-starter 15 | schema: 16 | file: ./schema.graphql 17 | network: 18 | chainId: cosmoshub-4 19 | endpoint: https://cosmoshub.tendermintrpc.lava.build:443 20 | 21 | dataSources: 22 | - kind: cosmos/Runtime 23 | startBlock: 10346000 24 | mapping: 25 | file: './dist/index.js' 26 | handlers: 27 | - handler: handleBlock 28 | kind: cosmos/BlockHandler 29 | - handler: handleTransaction 30 | kind: cosmos/TransactionHandler 31 | - handler: handleEvent 32 | kind: cosmos/EventHandler 33 | filter: 34 | type: transfer 35 | messageFilter: 36 | type: '/cosmos.bank.v1beta1.MsgSend' 37 | - handler: handleMessage 38 | kind: cosmos/MessageHandler 39 | filter: 40 | type: '/cosmos.bank.v1beta1.MsgSend' 41 | -------------------------------------------------------------------------------- /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/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 | "sourceMap": true, 5 | "tsBuildInfoFile": "dist/.tsbuildinfo", 6 | "rootDir": "src", 7 | "outDir": "./dist" 8 | }, 9 | "references": [{ "path": "../common-cosmos" }, { "path": "../types" }], 10 | "include": ["src/**/*"] 11 | } 12 | -------------------------------------------------------------------------------- /packages/types/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@subql/types-cosmos", 3 | "version": "4.1.1", 4 | "description": "", 5 | "homepage": "https://github.com/subquery/subql-cosmos", 6 | "repository": "github:subquery/subql-cosmos", 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-cosmos\" --release-prefix=\"types-cosmos/\"" 11 | }, 12 | "author": "SubQuery Pte Ltd", 13 | "main": "dist/index.js", 14 | "license": "GPL-3.0", 15 | "files": [ 16 | "/dist" 17 | ], 18 | "dependencies": { 19 | "@cosmjs/cosmwasm-stargate": "^0.32.4", 20 | "@cosmjs/proto-signing": "^0.32.4", 21 | "@cosmjs/stargate": "npm:@subql/x-cosmjs-stargate@0.33.0", 22 | "@subql/types-core": "^2.0.2" 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /packages/types/src/global.ts: -------------------------------------------------------------------------------- 1 | // // Copyright 2020-2025 SubQuery Pte Ltd authors & contributors 2 | // SPDX-License-Identifier: GPL-3.0 3 | 4 | import type {CosmWasmClient} from '@cosmjs/cosmwasm-stargate'; 5 | import {Registry} from '@cosmjs/proto-signing'; 6 | import {CosmWasmSafeClient} from './interfaces'; 7 | import '@subql/types-core/dist/global'; 8 | 9 | declare global { 10 | const apiUnsafe: CosmWasmClient; //requires --unsafe flag to be defined 11 | const api: CosmWasmSafeClient; 12 | const registry: Registry; 13 | } 14 | -------------------------------------------------------------------------------- /packages/types/src/index.ts: -------------------------------------------------------------------------------- 1 | // // Copyright 2020-2025 SubQuery Pte Ltd authors & contributors 2 | // SPDX-License-Identifier: GPL-3.0 3 | 4 | export * from './interfaces'; 5 | export * from './project'; 6 | export * from './modular'; 7 | -------------------------------------------------------------------------------- /packages/types/src/interfaces.ts: -------------------------------------------------------------------------------- 1 | // // Copyright 2020-2025 SubQuery Pte Ltd authors & contributors 2 | // SPDX-License-Identifier: GPL-3.0 3 | 4 | import {CosmWasmClient} from '@cosmjs/cosmwasm-stargate'; 5 | import {DecodedTxRaw} from '@cosmjs/proto-signing'; 6 | import {Log} from '@cosmjs/stargate/build/logs'; 7 | import type {tendermint34, tendermint37, comet38} from '@cosmjs/tendermint-rpc'; 8 | import Long from 'long'; 9 | 10 | export type Block = tendermint34.Block | tendermint37.Block | comet38.Block; 11 | export type BlockId = tendermint34.BlockId | tendermint37.BlockId | comet38.BlockId; 12 | export type Validator = tendermint34.Validator | tendermint37.Validator | comet38.Validator; 13 | export type TxData = tendermint34.TxData | tendermint37.TxData | comet38.TxData; 14 | export type TxEvent = tendermint34.Event | tendermint37.Event | comet38.Event; 15 | export type Header = tendermint34.Header | tendermint37.Header | comet38.Header; 16 | 17 | export interface CosmWasmSafeClient extends CosmWasmClient { 18 | validators: () => Promise; 19 | } 20 | 21 | export interface CosmosBlock { 22 | blockId: BlockId; 23 | block: {id: string} & Block; 24 | header: Header; // Full header 25 | /* The raw transaction data */ 26 | txs: TxData[]; 27 | 28 | /** 29 | * Decoded transactions, this is the same data as passed to a transaction handler 30 | * */ 31 | transactions: CosmosTransaction[]; 32 | /** 33 | * Decoded messages, this is the same data as passed to a message handler 34 | * */ 35 | messages: CosmosMessage[]; 36 | /** 37 | * Decoded events, this is the same data as passed to a event handler. 38 | * This is all events including, beginBlockEvents, endBlockEvents and finalizedBlockEvents 39 | * */ 40 | events: CosmosEvent[]; 41 | } 42 | 43 | export interface CosmosTransaction { 44 | idx: number; 45 | block: CosmosBlock; 46 | hash: string; 47 | tx: TxData; 48 | decodedTx: DecodedTxRaw; 49 | } 50 | 51 | export interface CosmosMessage { 52 | /** 53 | * The index of the message within the transaction 54 | */ 55 | idx: number; 56 | block: CosmosBlock; 57 | tx: CosmosTransaction; 58 | msg: { 59 | typeUrl: string; 60 | decodedMsg: T; 61 | }; 62 | } 63 | 64 | export enum CosmosEventKind { 65 | BeginBlock = 'begin_block', 66 | EndBlock = 'end_block', 67 | FinalizeBlock = 'finalize_block', 68 | Message = 'message', 69 | Transaction = 'transaction', 70 | } 71 | 72 | export interface CosmosEvent { 73 | idx: number; 74 | block: CosmosBlock; 75 | tx: CosmosTransaction; 76 | msg?: CosmosMessage; 77 | log: Log; 78 | event: TxEvent; 79 | kind: CosmosEventKind; 80 | } 81 | 82 | export type DynamicDatasourceCreator = (name: string, args: Record) => Promise; 83 | 84 | export interface Coin { 85 | denom: string; 86 | amount: string; 87 | } 88 | 89 | export interface MsgExecuteContract { 90 | /** Sender is the that actor that signed the messages */ 91 | sender: string; 92 | /** Contract is the address of the smart contract */ 93 | contract: string; 94 | /** Msg json encoded message to be passed to the contract */ 95 | msg: T; 96 | /** Funds coins that are transferred to the contract on execution */ 97 | funds: Coin[]; 98 | } 99 | 100 | export interface MsgMigrateContract { 101 | /** Sender is the that actor that signed the messages */ 102 | sender: string; 103 | /** Contract is the address of the smart contract */ 104 | contract: string; 105 | /** CodeID references the new WASM code */ 106 | codeId: Long; 107 | /** Msg json encoded message to be passed to the contract on migration */ 108 | msg: T; 109 | } 110 | 111 | export interface MsgInstantiateContract { 112 | /** Sender is the that actor that signed the messages */ 113 | sender: string; 114 | /** Admin is an optional address that can execute migrations */ 115 | admin: string; 116 | /** CodeID is the reference to the stored WASM code */ 117 | codeId: Long; 118 | /** Label is optional metadata to be stored with a contract instance. */ 119 | label: string; 120 | /** Msg json encoded message to be passed to the contract on instantiation */ 121 | msg: T; 122 | /** Funds coins that are transferred to the contract on instantiation */ 123 | funds: Coin[]; 124 | } 125 | -------------------------------------------------------------------------------- /packages/types/src/modular.ts: -------------------------------------------------------------------------------- 1 | // // Copyright 2020-2025 SubQuery Pte Ltd authors & contributors 2 | // SPDX-License-Identifier: GPL-3.0 3 | 4 | import {INetworkCommonModule, ProjectManifestV1_0_0} from '@subql/types-core'; 5 | import {Data} from 'ejs'; 6 | import {CosmosCustomDatasource, CosmosDatasource, CosmosRuntimeDatasource} from './project'; 7 | 8 | export interface CosmosNetworkModule 9 | extends INetworkCommonModule { 10 | projectCodegen( 11 | manifest: ProjectManifestV1_0_0[], 12 | projectPath: string, 13 | prepareDirPath: (path: string, recreate: boolean) => Promise, 14 | renderTemplate: (templatePath: string, outputPath: string, templateData: Data) => Promise, 15 | upperFirst: (string?: string) => string, 16 | datasources: CosmosRuntimeDatasource[] 17 | ): Promise; 18 | } 19 | -------------------------------------------------------------------------------- /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 | }, 10 | "include": ["src/**/*"] 11 | } 12 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /scripts/update_versions.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | set -e 3 | 4 | LIGHT_BLUE='\033[1;34m' 5 | YELLOW='\033[1;33m' 6 | NC='\033[0m' 7 | 8 | # Function to echo unreleased changes from CHANGELOG.md 9 | echo_unreleased_changes() { 10 | local changelog_file="$1" 11 | 12 | # Check if the provided argument is a valid file 13 | if [ ! -f "$changelog_file" ]; then 14 | echo "Changelog doesn't exist" 15 | return 1 16 | fi 17 | 18 | # Use sed to extract the line number of the start and end of the unreleased changes 19 | local start_line=$(sed -n '/## \[Unreleased\]/=' "$changelog_file") 20 | local end_line=$(sed -n '/## \[/=' "$changelog_file" | sed -n 2p) 21 | 22 | # Use awk to extract the unreleased changes 23 | local changes=$(awk "NR > $start_line && NR < $end_line" "$changelog_file") 24 | 25 | # Check if there are any changes 26 | if [ -z "$changes" ]; then 27 | echo "No unreleased changes found. Please include some changes and try again" 28 | exit 1 29 | else 30 | echo "Unreleased Changes:\n${LIGHT_BLUE}$changes${NC}\n" 31 | fi 32 | } 33 | 34 | prepare_package_release() { 35 | local dir="$1" 36 | 37 | # Check if the provided argument is a valid file 38 | if [ ! -d "$dir" ]; then 39 | echo "Expected $dir to be a directory" 40 | exit 1 41 | fi 42 | 43 | # Movde into the directory in the path 44 | cd "$dir" 45 | 46 | # Get the version from package.json 47 | VERSION=$(jq -r '.version' package.json) 48 | NAME=$(jq -r '.name' package.json) 49 | 50 | # Check if the version is a prerelease (ends with a hyphen and one or more digits) 51 | if [[ $VERSION =~ -[0-9]+$ ]]; then 52 | # Prompt the user for the version bump 53 | echo "Please select the version bump for ${YELLOW}$NAME${NC}" 54 | echo_unreleased_changes "./CHANGELOG.md" 55 | read -p "Version bump (major, minor or patch): " BUMP 56 | 57 | # Update the package.json version 58 | yarn version $BUMP 59 | 60 | # Run the changelog:release command 61 | yarn changelog:release 62 | fi 63 | 64 | # Back to previous dir 65 | cd - 66 | } 67 | 68 | ## Warning this will not automatically update packages that just have dependency changes 69 | ## E.g. when @subql/common is updated, @subql/common-substrate should also be updated 70 | ## It also doesn't do things in order of dependencies 71 | for dir in packages/*; do 72 | # Check the path is a directory and is tracked by git 73 | if [ -d "$dir" ] && [[ $(git ls-files "$dir") ]]; then 74 | prepare_package_release "$dir" 75 | fi 76 | 77 | git add .yarn/versions 78 | done 79 | 80 | # prepare_package_release "$1" 81 | -------------------------------------------------------------------------------- /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:12-alpine 6 | ports: 7 | - 5432:5432 8 | environment: 9 | POSTGRES_PASSWORD: postgres 10 | 11 | test: 12 | build: 13 | context: .. 14 | dockerfile: test/Dockerfile 15 | volumes: 16 | - ../coverage:/workdir/coverage 17 | depends_on: 18 | - "postgres" 19 | environment: 20 | DB_USER: postgres 21 | DB_PASS: postgres 22 | DB_DATABASE: postgres 23 | DB_HOST: postgres 24 | DB_POST: 5432 25 | SUBQL_ACCESS_TOKEN: ${SUBQL_ACCESS_TOKEN} 26 | SUBQL_ACCESS_TOKEN_TEST: ${SUBQL_ACCESS_TOKEN_TEST} 27 | SUBQL_ORG_TEST: ${SUBQL_ORG_TEST} 28 | command: 29 | - yarn 30 | - test:all 31 | 32 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "module": "commonjs", 4 | "target": "ES2022", 5 | "noImplicitAny": false, 6 | "noImplicitThis": true, 7 | "moduleResolution": "node", 8 | "outDir": "dist", 9 | "baseUrl": ".", 10 | "types": ["node", "jest"], 11 | "experimentalDecorators": true, 12 | "esModuleInterop": true, 13 | "allowSyntheticDefaultImports": true, 14 | "lib": ["ES2022"], 15 | "emitDecoratorMetadata": true, 16 | "declaration": true, 17 | "sourceMap": true, 18 | "inlineSources": true, 19 | "composite": true, 20 | "paths": { 21 | "@subql/common-cosmos": ["packages/common-cosmos/src"], 22 | "@subql/common-cosmos/*": ["packages/common-cosmos/src/*"], 23 | "@subql/types-cosmos": ["packages/types/src"], 24 | "@subql/types-cosmos/*": ["packages/types/src/*"] 25 | }, 26 | "skipLibCheck": true, 27 | "strict": true 28 | }, 29 | "references": [ 30 | {"path": "packages/common-cosmos"}, 31 | {"path": "packages/node"}, 32 | {"path": "packages/node-core"}, 33 | {"path": "packages/types"} 34 | ], 35 | "include": ["packages/**/*"], 36 | "exclude": ["**/node_modules/**"], 37 | "typeRoots": ["./node_modules/@types"] 38 | } 39 | -------------------------------------------------------------------------------- /tsconfig.test.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "exclude": [ 4 | "**/node_modules/**", 5 | "**/*.spec.ts", 6 | "**/*.test.ts" 7 | ] 8 | } 9 | --------------------------------------------------------------------------------