From 20c55ec700ea6b1cba11e23b6c51097f06c8ea02 Mon Sep 17 00:00:00 2001 From: godlin Date: Mon, 9 Sep 2024 18:07:56 +0200 Subject: [PATCH] Acurast Featured --- acurast/.gitignore | 53 ++++++++++++++++ acurast/README.md | 75 +++++++++++++++++++++++ acurast/docker-compose.yml | 66 ++++++++++++++++++++ acurast/docker/load-extensions.sh | 5 ++ acurast/docker/pg-Dockerfile | 12 ++++ acurast/package.json | 31 ++++++++++ acurast/project.yaml | 27 +++++++++ acurast/schema.graphql | 20 ++++++ acurast/scripts/publish-manifest.sh | 6 ++ acurast/src/index.ts | 3 + acurast/src/mappings/mappingHandlers.ts | 81 +++++++++++++++++++++++++ acurast/tsconfig.json | 19 ++++++ yarn.lock | 4 ++ 13 files changed, 402 insertions(+) create mode 100644 acurast/.gitignore create mode 100644 acurast/README.md create mode 100644 acurast/docker-compose.yml create mode 100644 acurast/docker/load-extensions.sh create mode 100644 acurast/docker/pg-Dockerfile create mode 100644 acurast/package.json create mode 100644 acurast/project.yaml create mode 100644 acurast/schema.graphql create mode 100644 acurast/scripts/publish-manifest.sh create mode 100644 acurast/src/index.ts create mode 100644 acurast/src/mappings/mappingHandlers.ts create mode 100644 acurast/tsconfig.json create mode 100644 yarn.lock diff --git a/acurast/.gitignore b/acurast/.gitignore new file mode 100644 index 0000000..5140c32 --- /dev/null +++ b/acurast/.gitignore @@ -0,0 +1,53 @@ +# These are some examples of commonly ignored file patterns. +# You should customize this list as applicable to your project. +# Learn more about .gitignore: +# https://www.atlassian.com/git/tutorials/saving-changes/gitignore + +# Node artifact files +node_modules/ +dist/ +yarn.lock + +# Compiled Java class files +*.class + +# Compiled Python bytecode +*.py[cod] + +# Log files +*.log + +# Package files +*.jar + +# Maven +target/ +dist/ +src/types + +# JetBrains IDE +.idea/ + +# Unit test reports +TEST*.xml + +# Generated by MacOS +.DS_Store + +# Generated by Windows +Thumbs.db + +# Applications +*.app +*.exe +*.war + +# Large media files +*.mp4 +*.tiff +*.avi +*.flv +*.mov +*.wmv + +.data \ No newline at end of file diff --git a/acurast/README.md b/acurast/README.md new file mode 100644 index 0000000..d0b6db2 --- /dev/null +++ b/acurast/README.md @@ -0,0 +1,75 @@ +# SubQuery - Dictionary + +This special SubQuery Project provides a dictionary of data that pre-indexes events on chain to dramatically improve indexing the performance of your own SubQuery Project, sometimes up to 10x faster. + +It scans over the network, and simply records the module and method for every event/extrinsic on each block - please see the standard entities in `schema.graphql`. + +**If you want to create your SubQuery Dictionary to speed up indexing of your own Substrate chain, fork this project and let us know** + +# Geting Started +### 1. Install dependencies +```shell +yarn +``` + +### 2. Generate types +```shell +yarn codegen +``` + +### 3. Build +```shell +yarn build +``` + +### 4. Run locally +```shell +yarn start:docker +``` + +### 4. Queries + +Event: + +``` +query { + events(first: 10, filter: {blockHeight : {equalTo:"2804408"}}) { + nodes { + id, + module, + event, + blockHeight + } + } +} +``` + +Extrinsic: + +``` +query { + extrinsics(first: 10, filter: {blockHeight : {equalTo:"2804408"}}) { + nodes { + id, + module, + call, + blockHeight, + success, + isSigned, + } + } +} +``` + +SpecVersion: + +``` +query { + specVersions(first: 10) { + nodes { + id, + blockHeight + } + } +} +``` \ No newline at end of file diff --git a/acurast/docker-compose.yml b/acurast/docker-compose.yml new file mode 100644 index 0000000..57a7287 --- /dev/null +++ b/acurast/docker-compose.yml @@ -0,0 +1,66 @@ +version: "3" + +services: + postgres: + build: + context: . + dockerfile: ./docker/pg-Dockerfile + ports: + - 5432:5432 + volumes: + - .data/postgres:/var/lib/postgresql/data + environment: + POSTGRES_PASSWORD: postgres + healthcheck: + test: ["CMD-SHELL", "pg_isready -U postgres"] + interval: 5s + timeout: 5s + retries: 5 + + subquery-node: + image: subquerynetwork/subql-node-substrate:latest + depends_on: + "postgres": + condition: service_healthy + restart: unless-stopped + environment: + DB_USER: postgres + DB_PASS: postgres + DB_DATABASE: postgres + DB_HOST: postgres + DB_PORT: 5432 + volumes: + - ./:/app + command: + - ${SUB_COMMAND:-} # set SUB_COMMAND env variable to "test" to run tests + - -f=/app + - --db-schema=app + - --workers=4 + - --batch-size=30 + - --unfinalized-blocks=true + healthcheck: + test: ["CMD", "curl", "-f", "http://subquery-node:3000/ready"] + interval: 3s + timeout: 5s + retries: 10 + + graphql-engine: + image: subquerynetwork/subql-query:latest + ports: + - 3000:3000 + depends_on: + "postgres": + condition: service_healthy + "subquery-node": + condition: service_healthy + restart: always + environment: + DB_USER: postgres + DB_PASS: postgres + DB_DATABASE: postgres + DB_HOST: postgres + DB_PORT: 5432 + command: + - --name=app + - --playground + - --indexer=http://subquery-node:3000 diff --git a/acurast/docker/load-extensions.sh b/acurast/docker/load-extensions.sh new file mode 100644 index 0000000..6d33f86 --- /dev/null +++ b/acurast/docker/load-extensions.sh @@ -0,0 +1,5 @@ +#!/bin/sh + +psql -v ON_ERROR_STOP=1 --username "$POSTGRES_USER" <- + A SubQuery Dictionary Project that provides increased indexing speed to all + projects +repository: 'https://github.com/subquery/subql-dictionary' +schema: + file: ./schema.graphql +network: + chainId: '0xce7681fb12aa8f7265d229a9074be0ea1d5e99b53eedcec2deade43857901808' + endpoint: 'wss://public-rpc.canary.acurast.com' +dataSources: + - kind: substrate/Runtime + startBlock: 1 + mapping: + file: ./dist/index.js + handlers: + - handler: handleBlock + kind: substrate/BlockHandler diff --git a/acurast/schema.graphql b/acurast/schema.graphql new file mode 100644 index 0000000..d93080a --- /dev/null +++ b/acurast/schema.graphql @@ -0,0 +1,20 @@ +type SpecVersion @entity { + id: ID! #specVersion + blockHeight: BigInt! +} + +type Event @entity { + id: ID! + module: String! @index + event: String! @index + blockHeight: BigInt! @index +} + +type Extrinsic @entity { + id: ID! + module: String! @index + call: String! @index + blockHeight: BigInt! @index + success: Boolean! + isSigned: Boolean! +} \ No newline at end of file diff --git a/acurast/scripts/publish-manifest.sh b/acurast/scripts/publish-manifest.sh new file mode 100644 index 0000000..26cd1e3 --- /dev/null +++ b/acurast/scripts/publish-manifest.sh @@ -0,0 +1,6 @@ +#!/bin/bash + +for file in ./project*.yaml; do + echo "Publishing $file..." + npx subql publish -f "$file" +done \ No newline at end of file diff --git a/acurast/src/index.ts b/acurast/src/index.ts new file mode 100644 index 0000000..5091615 --- /dev/null +++ b/acurast/src/index.ts @@ -0,0 +1,3 @@ +//Exports all handler functions +export * from "./mappings/mappingHandlers"; +import "@polkadot/api-augment"; diff --git a/acurast/src/mappings/mappingHandlers.ts b/acurast/src/mappings/mappingHandlers.ts new file mode 100644 index 0000000..5da045b --- /dev/null +++ b/acurast/src/mappings/mappingHandlers.ts @@ -0,0 +1,81 @@ +import { EventRecord } from "@polkadot/types/interfaces"; +import { SubstrateExtrinsic, SubstrateBlock } from "@subql/types"; +import { SpecVersion, Event, Extrinsic } from "../types"; + +export async function handleBlock(block: SubstrateBlock): Promise { + // Initialise Spec Version + let specVersion = await SpecVersion.get(block.specVersion.toString()); + + // Check for updates to Spec Version + if (!specVersion) { + specVersion = new SpecVersion(block.specVersion.toString(),block.block.header.number.toBigInt()); + await specVersion.save(); + } + + // Process all events in block + const events = block.events + .filter( + (evt) => + !( + evt.event.section === "system" && + evt.event.method === "ExtrinsicSuccess" + ) + ) + .map((evt, idx) => + handleEvent(block.block.header.number.toString(), idx, evt) + ); + + // Process all calls in block + const calls = wrapExtrinsics(block).map((ext, idx) => + handleCall(`${block.block.header.number.toString()}-${idx}`, ext) + ); + + // Save all data + // All save order should always follow this structure + for (const event of events) { + await event.save() + } + for (const call of calls) { + await call.save() + } +} + +function handleEvent( + blockNumber: string, + eventIdx: number, + event: EventRecord +): Event { + return Event.create({ + id: `${blockNumber}-${eventIdx}`, + blockHeight: BigInt(blockNumber), + module: event.event.section, + event: event.event.method, + }); +} + +function handleCall(idx: string, extrinsic: SubstrateExtrinsic): Extrinsic { + return Extrinsic.create({ + id: idx, + module: extrinsic.extrinsic.method.section, + call: extrinsic.extrinsic.method.method, + blockHeight: extrinsic.block.block.header.number.toBigInt(), + success: extrinsic.success, + isSigned: extrinsic.extrinsic.isSigned, + }); +} + +function wrapExtrinsics(wrappedBlock: SubstrateBlock): SubstrateExtrinsic[] { + return wrappedBlock.block.extrinsics.map((extrinsic, idx) => { + const events = wrappedBlock.events.filter( + ({ phase }) => phase.isApplyExtrinsic && phase.asApplyExtrinsic.eqn(idx) + ); + return { + idx, + extrinsic, + block: wrappedBlock, + events, + success: + events.findIndex((evt) => evt.event.method === "ExtrinsicSuccess") > -1, + }; + }); +} \ No newline at end of file diff --git a/acurast/tsconfig.json b/acurast/tsconfig.json new file mode 100644 index 0000000..4146dec --- /dev/null +++ b/acurast/tsconfig.json @@ -0,0 +1,19 @@ +{ + "compilerOptions": { + "emitDecoratorMetadata": true, + "experimentalDecorators": true, + "esModuleInterop": true, + "declaration": true, + "importHelpers": true, + "resolveJsonModule": true, + "module": "commonjs", + "outDir": "dist", + "rootDir": "src", + "target": "es2017", + "strict": true + }, + "include": [ + "src/**/*", + "node_modules/@subql/types/dist/global.d.ts" + ] +} \ No newline at end of file diff --git a/yarn.lock b/yarn.lock new file mode 100644 index 0000000..fb57ccd --- /dev/null +++ b/yarn.lock @@ -0,0 +1,4 @@ +# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. +# yarn lockfile v1 + +