└── account-transfers ├── .gitignore ├── README.md ├── docker-compose.yml ├── package.json ├── project.yaml ├── schema.graphql ├── src ├── index.ts └── mappings │ └── mappingHandlers.ts └── tsconfig.json /account-transfers/.gitignore: -------------------------------------------------------------------------------- 1 | # These are some examples of commonly ignored file patterns. 2 | # You should customize this list as applicable to your project. 3 | # Learn more about .gitignore: 4 | # https://www.atlassian.com/git/tutorials/saving-changes/gitignore 5 | 6 | # Node artifact files 7 | node_modules/ 8 | dist/ 9 | 10 | # lock files 11 | yarn.lock 12 | package-lock.json 13 | 14 | # Compiled Java class files 15 | *.class 16 | 17 | # Compiled Python bytecode 18 | *.py[cod] 19 | 20 | # Log files 21 | *.log 22 | 23 | # Package files 24 | *.jar 25 | 26 | # Maven 27 | target/ 28 | dist/ 29 | src/types 30 | 31 | # JetBrains IDE 32 | .idea/ 33 | 34 | # Unit test reports 35 | TEST*.xml 36 | 37 | # Generated by MacOS 38 | .DS_Store 39 | 40 | # Generated by Windows 41 | Thumbs.db 42 | 43 | # Applications 44 | *.app 45 | *.exe 46 | *.war 47 | 48 | # Large media files 49 | *.mp4 50 | *.tiff 51 | *.avi 52 | *.flv 53 | *.mov 54 | *.wmv 55 | 56 | -------------------------------------------------------------------------------- /account-transfers/README.md: -------------------------------------------------------------------------------- 1 | # What is SubQuery? 2 | 3 | SubQuery powers the next generation of Polkadot dApps by allowing developers to extract, transform and query blockchain data in real time using GraphQL. In addition to this, SubQuery provides production quality hosting infrastructure to run these projects in. 4 | 5 | # SubQuery Example - Account transfers 6 | 7 | This subquery example indexes the amount transferred of each account and it is an example of a 1-many entity relationshp. In other words, one account can have many receiving addresses. 8 | 9 | # Getting Started 10 | 11 | ### 1. Clone the entire subql-example repository 12 | 13 | ```shell 14 | git clone https://github.com/subquery/tutorials-account-transfers.git 15 | 16 | ``` 17 | 18 | ### 2. Install dependencies 19 | 20 | ```shell 21 | cd 22 | yarn 23 | ``` 24 | 25 | ### 3. Generate types 26 | 27 | ```shell 28 | yarn codegen 29 | ``` 30 | 31 | ### 4. Build the project 32 | 33 | ```shell 34 | yarn build 35 | ``` 36 | 37 | ### 5. Start Docker 38 | 39 | ```shell 40 | docker-compose pull & docker-compose up 41 | ``` 42 | 43 | ### 6. Run locally 44 | 45 | Open http://localhost:3000/ on your browser 46 | 47 | ### 7. Example query to run 48 | 49 | ```shell 50 | query{ 51 | transfers(first: 3){ 52 | nodes{ 53 | id 54 | amount 55 | blockNumber 56 | to{ 57 | id 58 | } 59 | } 60 | } 61 | } 62 | ``` 63 | 64 | -------------------------------------------------------------------------------- /account-transfers/docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: '3' 2 | 3 | services: 4 | postgres: 5 | image: postgres:12-alpine 6 | ports: 7 | - 5432:5432 8 | volumes: 9 | - .data/postgres:/var/lib/postgresql/data 10 | environment: 11 | POSTGRES_PASSWORD: postgres 12 | 13 | subquery-node: 14 | image: onfinality/subql-node:latest 15 | depends_on: 16 | - "postgres" 17 | restart: always 18 | environment: 19 | DB_USER: postgres 20 | DB_PASS: postgres 21 | DB_DATABASE: postgres 22 | DB_HOST: postgres 23 | DB_PORT: 5432 24 | volumes: 25 | - ./:/app 26 | command: 27 | - -f=/app 28 | - --local 29 | 30 | graphql-engine: 31 | image: onfinality/subql-query:latest 32 | ports: 33 | - 3000:3000 34 | depends_on: 35 | - "postgres" 36 | - "subquery-node" 37 | restart: always 38 | environment: 39 | DB_USER: postgres 40 | DB_PASS: postgres 41 | DB_DATABASE: postgres 42 | DB_HOST: postgres 43 | DB_PORT: 5432 44 | command: 45 | - --name=app 46 | - --playground 47 | - --indexer=http://subquery-node:3000 48 | -------------------------------------------------------------------------------- /account-transfers/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "account-transfers", 3 | "version": "1.0.0", 4 | "description": "", 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": "sa", 20 | "license": "Apache-2.0", 21 | "devDependencies": { 22 | "@polkadot/api": "^6", 23 | "@subql/types": "latest", 24 | "typescript": "^4.1.3", 25 | "@subql/cli": "latest" 26 | } 27 | } -------------------------------------------------------------------------------- /account-transfers/project.yaml: -------------------------------------------------------------------------------- 1 | specVersion: 0.0.1 2 | description: '' 3 | repository: '' 4 | schema: ./schema.graphql 5 | network: 6 | endpoint: 'wss://polkadot.api.onfinality.io/public-ws' 7 | dictionary: 'https://api.subquery.network/sq/subquery/dictionary-polkadot' 8 | dataSources: 9 | - name: main 10 | kind: substrate/Runtime 11 | startBlock: 1 12 | mapping: 13 | handlers: 14 | - handler: handleEvent 15 | kind: substrate/EventHandler 16 | filter: 17 | module: balances 18 | method: Transfer 19 | -------------------------------------------------------------------------------- /account-transfers/schema.graphql: -------------------------------------------------------------------------------- 1 | # This is an example of a one-many entity relation. One account can have many receiving addresses. 2 | # The Account entity has 1 column storing the toAddress. 3 | # The Transfer entity has 4 columns where "to" refers to the Account.id 4 | 5 | type Account @entity { 6 | id: ID! #this primary key is set as the toAddress 7 | } 8 | 9 | type Transfer @entity { 10 | id: ID! #this primary key is the block number + the event id 11 | amount: BigInt 12 | blockNumber: BigInt 13 | to: Account! #receiving address 14 | } 15 | 16 | 17 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /account-transfers/src/index.ts: -------------------------------------------------------------------------------- 1 | //Exports all handler functions 2 | export * from './mappings/mappingHandlers' 3 | -------------------------------------------------------------------------------- /account-transfers/src/mappings/mappingHandlers.ts: -------------------------------------------------------------------------------- 1 | import {SubstrateEvent} from "@subql/types"; 2 | import {Account, Transfer} from "../types"; 3 | import {Balance} from "@polkadot/types/interfaces"; 4 | 5 | export async function handleEvent(event: SubstrateEvent): Promise { 6 | // The balances.transfer event has the following payload \[from, to, value\] that we can access 7 | 8 | // const fromAddress = event.event.data[0]; 9 | const toAddress = event.event.data[1]; 10 | const amount = event.event.data[2]; 11 | 12 | // query for toAddress from DB 13 | const toAccount = await Account.get(toAddress.toString()); 14 | // if not in DB, instantiate a new Account object using the toAddress as a unique ID 15 | if (!toAccount) { 16 | await new Account(toAddress.toString()).save(); 17 | } 18 | 19 | // instantiate a new Transfer object using the block number and event.idx as a unique ID 20 | const transfer = new Transfer(`${event.block.block.header.number.toNumber()}-${event.idx}`, ); 21 | transfer.blockNumber = event.block.block.header.number.toBigInt(); 22 | transfer.toId = toAddress.toString(); 23 | transfer.amount = (amount as Balance).toBigInt(); 24 | await transfer.save(); 25 | } 26 | 27 | -------------------------------------------------------------------------------- /account-transfers/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "emitDecoratorMetadata": true, 4 | "experimentalDecorators": true, 5 | "esModuleInterop": true, 6 | "declaration": true, 7 | "importHelpers": true, 8 | "resolveJsonModule": true, 9 | "module": "commonjs", 10 | "outDir": "dist", 11 | "rootDir": "src", 12 | "target": "es2017" 13 | }, 14 | "include": [ 15 | "src/**/*", 16 | "node_modules/@subql/types/dist/global.d.ts" 17 | ] 18 | } 19 | --------------------------------------------------------------------------------