├── .gitignore ├── evm-transactions-example ├── src │ ├── model │ │ ├── index.ts │ │ └── generated │ │ │ ├── index.ts │ │ │ ├── transaction.model.ts │ │ │ └── marshal.ts │ ├── processor.ts │ └── main.ts ├── .gitignore ├── .env ├── .DS_Store ├── schema.graphql ├── docker-compose.yml ├── squid.yaml ├── tsconfig.json ├── db │ └── migrations │ │ └── 1681397371690-Data.js ├── renovate.json ├── package.json ├── README.md ├── .gitpod.yml ├── commands.json └── abi │ └── erc20.json └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | -------------------------------------------------------------------------------- /evm-transactions-example/src/model/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./generated" 2 | -------------------------------------------------------------------------------- /evm-transactions-example/src/model/generated/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./transaction.model" 2 | -------------------------------------------------------------------------------- /evm-transactions-example/.gitignore: -------------------------------------------------------------------------------- 1 | /node_modules 2 | /lib 3 | 4 | # IDE files 5 | /.idea 6 | pnpm-lock.yaml 7 | **/*.log -------------------------------------------------------------------------------- /evm-transactions-example/.env: -------------------------------------------------------------------------------- 1 | DB_NAME=squid 2 | DB_PASS=squid 3 | DB_PORT=23798 4 | PROCESSOR_PROMETHEUS_PORT=3000 5 | GQL_PORT=4350 6 | -------------------------------------------------------------------------------- /evm-transactions-example/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/subsquid-quests/ens-subgraph-migration/HEAD/evm-transactions-example/.DS_Store -------------------------------------------------------------------------------- /evm-transactions-example/schema.graphql: -------------------------------------------------------------------------------- 1 | type Transaction @entity { 2 | id: ID! 3 | block: Int! 4 | timestamp: DateTime! 5 | hash: String! 6 | from: String! 7 | to: String! 8 | input: String! 9 | } -------------------------------------------------------------------------------- /evm-transactions-example/docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: "3" 2 | 3 | services: 4 | db: 5 | image: postgres:15 6 | environment: 7 | POSTGRES_DB: squid 8 | POSTGRES_PASSWORD: squid 9 | ports: 10 | - "${DB_PORT}:5432" 11 | # command: ["postgres", "-c", "log_statement=all"] 12 | -------------------------------------------------------------------------------- /evm-transactions-example/squid.yaml: -------------------------------------------------------------------------------- 1 | manifestVersion: subsquid.io/v0.1 2 | name: transactions-example 3 | version: 1 4 | description: |- 5 | Basic example of processing transactions 6 | build: 7 | 8 | deploy: 9 | addons: 10 | postgres: 11 | processor: 12 | cmd: [ "node", "lib/main" ] 13 | api: 14 | cmd: [ "npx", "squid-graphql-server", "--dumb-cache", "in-memory", "--dumb-cache-ttl", "1000", "--dumb-cache-size", "100", "--dumb-cache-max-age", "1000" ] -------------------------------------------------------------------------------- /evm-transactions-example/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "module": "commonjs", 4 | "target": "es2020", 5 | "outDir": "lib", 6 | "rootDir": "src", 7 | "strict": true, 8 | "resolveJsonModule": true, 9 | "declaration": false, 10 | "sourceMap": true, 11 | "esModuleInterop": true, 12 | "experimentalDecorators": true, 13 | "emitDecoratorMetadata": true, 14 | "skipLibCheck": true 15 | }, 16 | "include": ["src"], 17 | "exclude": [ 18 | "node_modules" 19 | ] 20 | } 21 | -------------------------------------------------------------------------------- /evm-transactions-example/db/migrations/1681397371690-Data.js: -------------------------------------------------------------------------------- 1 | module.exports = class Data1681397371690 { 2 | name = 'Data1681397371690' 3 | 4 | async up(db) { 5 | await db.query(`CREATE TABLE "transaction" ("id" character varying NOT NULL, "block" integer NOT NULL, "timestamp" TIMESTAMP WITH TIME ZONE NOT NULL, "hash" text NOT NULL, "from" text NOT NULL, "to" text NOT NULL, "input" text NOT NULL, CONSTRAINT "PK_89eadb93a89810556e1cbcd6ab9" PRIMARY KEY ("id"))`) 6 | } 7 | 8 | async down(db) { 9 | await db.query(`DROP TABLE "transaction"`) 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /evm-transactions-example/renovate.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://docs.renovatebot.com/renovate-schema.json", 3 | "extends": [ 4 | "config:base" 5 | ], 6 | "packageRules": [ 7 | { 8 | "groupName": "@subsquid", 9 | "matchPackagePatterns": [ 10 | "^@subsquid/" 11 | ], 12 | "matchUpdateTypes": [ 13 | "minor", 14 | "patch", 15 | "pin", 16 | "digest" 17 | ] 18 | }, 19 | { 20 | "matchPackagePatterns": ["*"], 21 | "excludePackagePatterns": ["^@subsquid/"], 22 | "enabled": false 23 | } 24 | ], 25 | "automerge": true, 26 | "automergeType": "pr", 27 | "automergeStrategy": "squash", 28 | "ignoreTests": true 29 | } -------------------------------------------------------------------------------- /evm-transactions-example/src/model/generated/transaction.model.ts: -------------------------------------------------------------------------------- 1 | import {Entity as Entity_, Column as Column_, PrimaryColumn as PrimaryColumn_} from "typeorm" 2 | 3 | @Entity_() 4 | export class Transaction { 5 | constructor(props?: Partial) { 6 | Object.assign(this, props) 7 | } 8 | 9 | @PrimaryColumn_() 10 | id!: string 11 | 12 | @Column_("int4", {nullable: false}) 13 | block!: number 14 | 15 | @Column_("timestamp with time zone", {nullable: false}) 16 | timestamp!: Date 17 | 18 | @Column_("text", {nullable: false}) 19 | hash!: string 20 | 21 | @Column_("text", {nullable: false}) 22 | from!: string 23 | 24 | @Column_("text", {nullable: false}) 25 | to!: string 26 | 27 | @Column_("text", {nullable: false}) 28 | input!: string 29 | } 30 | -------------------------------------------------------------------------------- /evm-transactions-example/src/processor.ts: -------------------------------------------------------------------------------- 1 | import {EvmBatchProcessor} from '@subsquid/evm-processor' 2 | import {lookupArchive} from '@subsquid/archive-registry' 3 | 4 | const ACCOUNT_ADDRESS = '0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045' 5 | 6 | export const processor = new EvmBatchProcessor() 7 | .setDataSource({ 8 | archive: lookupArchive('eth-mainnet'), 9 | chain: 'https://rpc.ankr.com/eth', 10 | }) 11 | .setFinalityConfirmation(10) 12 | .setFields({ 13 | transaction: { 14 | from: true, 15 | value: true, 16 | hash: true, 17 | input: true, 18 | }, 19 | }) 20 | // Txs sent to vitalik.eth 21 | .addTransaction({ 22 | to: [ACCOUNT_ADDRESS], 23 | }) 24 | // Txs sent from vitalik.eth 25 | .addTransaction({ 26 | from: [ACCOUNT_ADDRESS], 27 | }) 28 | -------------------------------------------------------------------------------- /evm-transactions-example/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "squid", 3 | "version": "0.0.0", 4 | "private": true, 5 | "scripts": { 6 | "build": "rm -rf lib && tsc", 7 | "update": "npx npm-check-updates --filter /subsquid/ --upgrade && npm i -f" 8 | }, 9 | "dependencies": { 10 | "@subsquid/archive-registry": "^3.0.0", 11 | "@subsquid/evm-processor": "^1.4.0", 12 | "@subsquid/evm-typegen": "^3.2.0", 13 | "@subsquid/graphql-server": "^4.2.0", 14 | "@subsquid/typeorm-migration": "^1.2.0", 15 | "@subsquid/typeorm-store": "^1.2.0", 16 | "dotenv": "^16.0.3", 17 | "ethers": "^6.3.0", 18 | "pg": "^8.8.0", 19 | "typeorm": "^0.3.11" 20 | }, 21 | "devDependencies": { 22 | "@subsquid/evm-typegen": "^3.2.0", 23 | "@subsquid/typeorm-codegen": "^1.2.0", 24 | "@types/node": "^18.11.18", 25 | "typescript": "^4.9.4" 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /evm-transactions-example/src/main.ts: -------------------------------------------------------------------------------- 1 | import {TypeormDatabase} from '@subsquid/typeorm-store' 2 | import {processor} from './processor' 3 | import {Transaction} from './model' 4 | 5 | processor.run(new TypeormDatabase({supportHotBlocks: true}), async (ctx) => { 6 | let transactions: Transaction[] = [] 7 | 8 | for (let block of ctx.blocks) { 9 | for (let transaction of block.transactions) { 10 | transactions.push( 11 | new Transaction({ 12 | id: transaction.id, 13 | block: block.header.height, 14 | timestamp: new Date(block.header.timestamp), 15 | from: transaction.from || '0x', 16 | to: transaction.to || '0x', 17 | hash: transaction.hash, 18 | input: transaction.input, 19 | }) 20 | ) 21 | } 22 | } 23 | 24 | await ctx.store.insert(transactions) 25 | }) 26 | -------------------------------------------------------------------------------- /evm-transactions-example/README.md: -------------------------------------------------------------------------------- 1 | [![Open in Gitpod](https://gitpod.io/button/open-in-gitpod.svg)](https://gitpod.io/#https://github.com/subsquid-labs/transactions-example) 2 | 3 | 4 | # Tracking transactions 5 | 6 | This sample squid tracks transactions to and from `vitalik.eth` address on Ethereum Mainnet. 7 | One can use this example as a template for scaffolding a new squid project with [`sqd init`](https://docs.subsquid.io/squid-cli/): 8 | 9 | ```bash 10 | sqd init my-new-squid --template https://github.com/subsquid-labs/transactions-example 11 | ``` 12 | 13 | For a full reference, check the [docs](https://docs.subsquid.io). 14 | 15 | ## Prerequisites 16 | 17 | - Node v16.x 18 | - Docker 19 | - [Squid CLI](https://docs.subsquid.io/squid-cli/) 20 | 21 | ## Running 22 | 23 | Clone the repo and navigate to the root folder. 24 | 25 | ```bash 26 | npm ci 27 | sqd build 28 | # start the database 29 | sqd up 30 | # starts a long-running ETL and blocks the terminal 31 | sqd process 32 | 33 | # starts the GraphQL API server at localhost:4350/graphql 34 | sqd serve 35 | ``` 36 | -------------------------------------------------------------------------------- /evm-transactions-example/.gitpod.yml: -------------------------------------------------------------------------------- 1 | # This configuration file was automatically generated by Gitpod. 2 | # Please adjust to your needs (see https://www.gitpod.io/docs/introduction/learn-gitpod/gitpod-yaml) 3 | # and commit this file to your remote git repository to share the goodness with others. 4 | 5 | # Learn more from ready-to-use templates: https://www.gitpod.io/docs/introduction/getting-started/quickstart 6 | github: 7 | prebuilds: 8 | # enable for the master/default branch (defaults to true) 9 | master: true 10 | # enable for all branches in this repo (defaults to false) 11 | branches: false 12 | # enable for pull requests coming from this repo (defaults to true) 13 | pullRequests: true 14 | # add a check to pull requests (defaults to true) 15 | addCheck: true 16 | # add a "Review in Gitpod" button as a comment to pull requests (defaults to false) 17 | addComment: false 18 | 19 | tasks: 20 | - init: | 21 | npm i 22 | npm i -g @subsquid/cli 23 | docker compose pull 24 | gp sync-done setup 25 | - name: DB 26 | command: | 27 | make up 28 | - name: GraphQL API 29 | command: | 30 | gp sync-await setup 31 | sqd serve 32 | - command: | 33 | gp sync-await setup 34 | gp ports await 4350 35 | gp preview $(gp url 4350)/graphql 36 | - name: Squid procesor 37 | command: | 38 | gp open src/processor.ts 39 | gp sync-await setup 40 | npm run build 41 | gp ports await 23798 42 | npx sqd process 43 | -------------------------------------------------------------------------------- /evm-transactions-example/commands.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://cdn.subsquid.io/schemas/commands.json", 3 | "commands": { 4 | "clean": { 5 | "description": "delete all build artifacts", 6 | "cmd": ["npx", "--yes", "rimraf", "lib"] 7 | }, 8 | "build": { 9 | "description": "Build the squid project", 10 | "deps": ["clean"], 11 | "cmd": ["tsc"] 12 | }, 13 | "up": { 14 | "description": "Start a PG database", 15 | "cmd": ["docker", "compose", "up", "-d"] 16 | }, 17 | "down": { 18 | "description": "Drop a PG database", 19 | "cmd": ["docker", "compose", "down"] 20 | }, 21 | "migration:apply": { 22 | "description": "Apply the DB migrations", 23 | "cmd": ["squid-typeorm-migration", "apply"] 24 | }, 25 | "migration:generate": { 26 | "description": "Generate a DB migration matching the TypeORM entities", 27 | "deps": ["migration:clean"], 28 | "cmd": ["squid-typeorm-migration", "generate"], 29 | }, 30 | "migration:clean": { 31 | "description": "Clean the migrations folder", 32 | "cmd": ["npx", "--yes", "rimraf", "./db/migrations/*.js"], 33 | }, 34 | "migration": { 35 | "cmd": ["squid-typeorm-migration", "generate"], 36 | "hidden": true 37 | }, 38 | "codegen": { 39 | "description": "Generate TypeORM entities from the schema file", 40 | "cmd": ["squid-typeorm-codegen"] 41 | }, 42 | "typegen": { 43 | "description": "Generate data access classes for an ABI file(s) in the ./abi folder", 44 | "cmd": ["squid-evm-typegen", "./src/abi", {"glob": "./abi/*.json"}, "--multicall"] 45 | }, 46 | "process": { 47 | "description": "Load .env and start the squid processor", 48 | "deps": ["migration:apply"], 49 | "cmd": ["node", "--require=dotenv/config", "lib/main.js"] 50 | }, 51 | "process:prod": { 52 | "description": "Start the squid processor", 53 | "cmd": ["node", "lib/main.js"], 54 | "hidden": true 55 | }, 56 | "serve": { 57 | "description": "Start the GraphQL API server", 58 | "cmd": ["squid-graphql-server"] 59 | }, 60 | "serve:prod": { 61 | "description": "Start the GraphQL API server with caching and limits", 62 | "cmd": ["squid-graphql-server", 63 | "--dumb-cache", "in-memory", 64 | "--dumb-cache-ttl", "1000", 65 | "--dumb-cache-size", "100", 66 | "--dumb-cache-max-age", "1000" ] 67 | }, 68 | "check-updates": { 69 | "cmd": ["npx", "--yes", "npm-check-updates", "--filter=/subsquid/", "--upgrade"], 70 | "hidden": true 71 | }, 72 | "bump": { 73 | "description": "Bump @subsquid packages to the latest versions", 74 | "deps": ["check-updates"], 75 | "cmd": ["npm", "i", "-f"] 76 | }, 77 | "open": { 78 | "description": "Open a local browser window", 79 | "cmd": ["npx", "--yes", "opener"] 80 | } 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |

2 | 3 | 4 | Subsquid Logo 5 | 6 |

7 | 8 | [![docs.rs](https://docs.rs/leptos/badge.svg)](https://docs.subsquid.io/) 9 | [![Discord](https://img.shields.io/discord/1031524867910148188?color=%237289DA&label=discord)](https://discord.gg/subsquid) 10 | 11 | [Website](https://subsquid.io) | [Docs](https://docs.subsquid.io/) | [Discord](https://discord.gg/subsquid) 12 | 13 | # ENS Subgraph migration 14 | 15 | **ATT: We updated and re-opened this quest to submissions on Oct 27th** 16 | 17 | This quest is to migrate the [ENS Subgraph](https://thegraph.com/hosted-service/subgraph/ensdomains/ens) to Squid SDK. The repo for the subgraph can be found [here](https://github.com/ensdomains/ens-subgraph). The resulting squid should match the GraphQL API of the subgraph as close as possible, by migrating `schema.graphql`. The judges reserve the right to request improvements afther the initial review of the submission. Reach out to the [Discord Channel]( https://discord.com/channels/857105545135390731/1155812879770058783) for any tech questions regarding this quest. 18 | 19 | # Quest Info 20 | 21 | | Category | Skill Level | Time required (hours) | Max Participants | Reward | Status | 22 | | ---------------- | ------------------------------------ | --------------------- | ---------------- | ---------------------------------- | ------ | 23 | | Squid Deployment | $\textcolor{orange}{\textsf{Medium}}$ | ~100 | 5 | $\textcolor{red}{\textsf{5000tSQD}}$ | ended | 24 | 25 | # Acceptance critera 26 | 27 | Ultimately, the solutions are accepted at the discretion of judges following a manual review. This sections is a rough guide that is in no way binding on our side. 28 | 29 | Some of the reasons why the solution will not be accepted include: 30 | - squid does not start 31 | - squid fails to sync fully due to internal errors 32 | - [batch handler filters](https://docs.subsquid.io/evm-indexing/configuration/caveats/) are not set up correctly (leads to a late sync failure in [RPC-ingesting](https://docs.subsquid.io/evm-indexing/evm-processor/#rpc-ingestion) squids) 33 | - data returned for any query is not consistent with subgraph data 34 | 35 | You may find [this tool](https://github.com/abernatskiy/compareGraphQL) to be useful for squid to subgraph API comparisons. 36 | 37 | It is desirable that your solution: 38 | - includes a suite of test GraphQL queries that touches every [schema entity](https://docs.subsquid.io/store/postgres/schema-file/entities/) and, if used, every [custom resolver](https://docs.subsquid.io/graphql-api/custom-resolvers/) at least once, with corresponding subgraph queries (listing in README is enough) 39 | - has high code quality (readability, simplicity, comments where necessary) 40 | - uses [batch processing](https://docs.subsquid.io/basics/batch-processing/) consistently 41 | - avoids any "sleeping bugs": logic errors that accidentally happen to not break the data 42 | - follows the standard squid startup procedure: 43 | ``` 44 | git clone 45 | cd 46 | npm ci 47 | sqd up 48 | sqd process & 49 | sqd serve 50 | ``` 51 | If it does not, describe your startup procedure in the README. 52 | 53 | Please test your solutions before submitting. We do allow some corrections, but judges' time is not limitless. 54 | 55 | To submit, invite the following github accounts to your private repo : [@dariaag](https://github.com/dariaag), [@belopash](https://github.com/belopash), [@abernatskiy](https://github.com/abernatskiy) and [@dzhelezov](https://github.com/dzhelezov). 56 | 57 | # Rewards 58 | 59 | tSQD rewards will be delivered via the [quests page](https://app.subsquid.io/quests) of Subsquid Cloud. Make sure you use the same GitHub handle to make a submission and when linking to that page. 60 | 61 | Winners will be listed at the quest repository README. If you do not wish to be listed please tell us that in an issue in your submission repo. 62 | 63 | # Useful links 64 | 65 | - [Quickstart](https://docs.subsquid.io/deploy-squid/quickstart/) 66 | - [TheGraph Migration guide](https://docs.subsquid.io/migrate/migrate-subgraph/) 67 | - [ENS Subgraph source code](https://docs.ens.domains/contract-api-reference/subgraphdata) 68 | -------------------------------------------------------------------------------- /evm-transactions-example/src/model/generated/marshal.ts: -------------------------------------------------------------------------------- 1 | import assert from 'assert' 2 | 3 | 4 | export interface Marshal { 5 | fromJSON(value: unknown): T 6 | toJSON(value: T): S 7 | } 8 | 9 | 10 | export const string: Marshal = { 11 | fromJSON(value: unknown): string { 12 | assert(typeof value === 'string', 'invalid String') 13 | return value 14 | }, 15 | toJSON(value) { 16 | return value 17 | } 18 | } 19 | 20 | 21 | export const id = string 22 | 23 | 24 | export const int: Marshal = { 25 | fromJSON(value: unknown): number { 26 | assert(Number.isInteger(value), 'invalid Int') 27 | return value as number 28 | }, 29 | toJSON(value) { 30 | return value 31 | } 32 | } 33 | 34 | 35 | export const float: Marshal = { 36 | fromJSON(value: unknown): number { 37 | assert(typeof value === 'number', 'invalid Float') 38 | return value as number 39 | }, 40 | toJSON(value) { 41 | return value 42 | } 43 | } 44 | 45 | 46 | export const boolean: Marshal = { 47 | fromJSON(value: unknown): boolean { 48 | assert(typeof value === 'boolean', 'invalid Boolean') 49 | return value 50 | }, 51 | toJSON(value: boolean): boolean { 52 | return value 53 | } 54 | } 55 | 56 | 57 | export const bigint: Marshal = { 58 | fromJSON(value: unknown): bigint { 59 | assert(typeof value === 'string', 'invalid BigInt') 60 | return BigInt(value) 61 | }, 62 | toJSON(value: bigint): string { 63 | return value.toString() 64 | } 65 | } 66 | 67 | 68 | export const bigdecimal: Marshal = { 69 | fromJSON(value: unknown): bigint { 70 | assert(typeof value === 'string', 'invalid BigDecimal') 71 | return decimal.BigDecimal(value) 72 | }, 73 | toJSON(value: any): string { 74 | return value.toString() 75 | } 76 | } 77 | 78 | 79 | // credit - https://github.com/Urigo/graphql-scalars/blob/91b4ea8df891be8af7904cf84751930cc0c6613d/src/scalars/iso-date/validator.ts#L122 80 | const RFC_3339_REGEX = 81 | /^(\d{4}-(0[1-9]|1[012])-(0[1-9]|[12][0-9]|3[01])T([01][0-9]|2[0-3]):([0-5][0-9]):([0-5][0-9]|60))(\.\d{1,})?([Z])$/ 82 | 83 | 84 | function isIsoDateTimeString(s: string): boolean { 85 | return RFC_3339_REGEX.test(s) 86 | } 87 | 88 | 89 | export const datetime: Marshal = { 90 | fromJSON(value: unknown): Date { 91 | assert(typeof value === 'string', 'invalid DateTime') 92 | assert(isIsoDateTimeString(value), 'invalid DateTime') 93 | return new Date(value) 94 | }, 95 | toJSON(value: Date): string { 96 | return value.toISOString() 97 | } 98 | } 99 | 100 | 101 | export const bytes: Marshal = { 102 | fromJSON(value: unknown): Buffer { 103 | assert(typeof value === 'string', 'invalid Bytes') 104 | assert(value.length % 2 === 0, 'invalid Bytes') 105 | assert(/^0x[0-9a-f]+$/i.test(value), 'invalid Bytes') 106 | return Buffer.from(value.slice(2), 'hex') 107 | }, 108 | toJSON(value: Uint8Array): string { 109 | if (Buffer.isBuffer(value)) { 110 | return '0x' + value.toString('hex') 111 | } else { 112 | return '0x' + Buffer.from(value.buffer, value.byteOffset, value.byteLength).toString('hex') 113 | } 114 | } 115 | } 116 | 117 | 118 | export function fromList(list: unknown, f: (val: unknown) => T): T[] { 119 | assert(Array.isArray(list)) 120 | return list.map((val) => f(val)) 121 | } 122 | 123 | 124 | export function nonNull(val: T | undefined | null): T { 125 | assert(val != null, 'non-nullable value is null') 126 | return val 127 | } 128 | 129 | 130 | export const bigintTransformer = { 131 | to(x?: bigint) { 132 | return x?.toString() 133 | }, 134 | from(s?: string): bigint | undefined { 135 | return s == null ? undefined : BigInt(s) 136 | } 137 | } 138 | 139 | 140 | export const floatTransformer = { 141 | to(x?: number) { 142 | return x?.toString() 143 | }, 144 | from(s?: string): number | undefined { 145 | return s == null ? undefined : Number(s) 146 | } 147 | } 148 | 149 | 150 | export const bigdecimalTransformer = { 151 | to(x?: any) { 152 | return x?.toString() 153 | }, 154 | from(s?: any): any | undefined { 155 | return s == null ? undefined : decimal.BigDecimal(s) 156 | } 157 | } 158 | 159 | 160 | export function enumFromJson(json: unknown, enumObject: E): E[keyof E] { 161 | assert(typeof json == 'string', 'invalid enum value') 162 | let val = (enumObject as any)[json] 163 | assert(typeof val == 'string', `invalid enum value`) 164 | return val as any 165 | } 166 | 167 | 168 | const decimal = { 169 | get BigDecimal(): any { 170 | throw new Error('Package `@subsquid/big-decimal` is not installed') 171 | } 172 | } 173 | 174 | 175 | try { 176 | Object.defineProperty(decimal, "BigDecimal", { 177 | value: require('@subsquid/big-decimal').BigDecimal 178 | }) 179 | } catch (e) {} 180 | -------------------------------------------------------------------------------- /evm-transactions-example/abi/erc20.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "constant": true, 4 | "inputs": [], 5 | "name": "name", 6 | "outputs": [ 7 | { 8 | "name": "", 9 | "type": "string" 10 | } 11 | ], 12 | "payable": false, 13 | "stateMutability": "view", 14 | "type": "function" 15 | }, 16 | { 17 | "constant": false, 18 | "inputs": [ 19 | { 20 | "name": "_spender", 21 | "type": "address" 22 | }, 23 | { 24 | "name": "_value", 25 | "type": "uint256" 26 | } 27 | ], 28 | "name": "approve", 29 | "outputs": [ 30 | { 31 | "name": "", 32 | "type": "bool" 33 | } 34 | ], 35 | "payable": false, 36 | "stateMutability": "nonpayable", 37 | "type": "function" 38 | }, 39 | { 40 | "constant": true, 41 | "inputs": [], 42 | "name": "totalSupply", 43 | "outputs": [ 44 | { 45 | "name": "", 46 | "type": "uint256" 47 | } 48 | ], 49 | "payable": false, 50 | "stateMutability": "view", 51 | "type": "function" 52 | }, 53 | { 54 | "constant": false, 55 | "inputs": [ 56 | { 57 | "name": "_from", 58 | "type": "address" 59 | }, 60 | { 61 | "name": "_to", 62 | "type": "address" 63 | }, 64 | { 65 | "name": "_value", 66 | "type": "uint256" 67 | } 68 | ], 69 | "name": "transferFrom", 70 | "outputs": [ 71 | { 72 | "name": "", 73 | "type": "bool" 74 | } 75 | ], 76 | "payable": false, 77 | "stateMutability": "nonpayable", 78 | "type": "function" 79 | }, 80 | { 81 | "constant": true, 82 | "inputs": [], 83 | "name": "decimals", 84 | "outputs": [ 85 | { 86 | "name": "", 87 | "type": "uint8" 88 | } 89 | ], 90 | "payable": false, 91 | "stateMutability": "view", 92 | "type": "function" 93 | }, 94 | { 95 | "constant": true, 96 | "inputs": [ 97 | { 98 | "name": "_owner", 99 | "type": "address" 100 | } 101 | ], 102 | "name": "balanceOf", 103 | "outputs": [ 104 | { 105 | "name": "balance", 106 | "type": "uint256" 107 | } 108 | ], 109 | "payable": false, 110 | "stateMutability": "view", 111 | "type": "function" 112 | }, 113 | { 114 | "constant": true, 115 | "inputs": [], 116 | "name": "symbol", 117 | "outputs": [ 118 | { 119 | "name": "", 120 | "type": "string" 121 | } 122 | ], 123 | "payable": false, 124 | "stateMutability": "view", 125 | "type": "function" 126 | }, 127 | { 128 | "constant": false, 129 | "inputs": [ 130 | { 131 | "name": "_to", 132 | "type": "address" 133 | }, 134 | { 135 | "name": "_value", 136 | "type": "uint256" 137 | } 138 | ], 139 | "name": "transfer", 140 | "outputs": [ 141 | { 142 | "name": "", 143 | "type": "bool" 144 | } 145 | ], 146 | "payable": false, 147 | "stateMutability": "nonpayable", 148 | "type": "function" 149 | }, 150 | { 151 | "constant": true, 152 | "inputs": [ 153 | { 154 | "name": "_owner", 155 | "type": "address" 156 | }, 157 | { 158 | "name": "_spender", 159 | "type": "address" 160 | } 161 | ], 162 | "name": "allowance", 163 | "outputs": [ 164 | { 165 | "name": "", 166 | "type": "uint256" 167 | } 168 | ], 169 | "payable": false, 170 | "stateMutability": "view", 171 | "type": "function" 172 | }, 173 | { 174 | "payable": true, 175 | "stateMutability": "payable", 176 | "type": "fallback" 177 | }, 178 | { 179 | "anonymous": false, 180 | "inputs": [ 181 | { 182 | "indexed": true, 183 | "name": "owner", 184 | "type": "address" 185 | }, 186 | { 187 | "indexed": true, 188 | "name": "spender", 189 | "type": "address" 190 | }, 191 | { 192 | "indexed": false, 193 | "name": "value", 194 | "type": "uint256" 195 | } 196 | ], 197 | "name": "Approval", 198 | "type": "event" 199 | }, 200 | { 201 | "anonymous": false, 202 | "inputs": [ 203 | { 204 | "indexed": true, 205 | "name": "from", 206 | "type": "address" 207 | }, 208 | { 209 | "indexed": true, 210 | "name": "to", 211 | "type": "address" 212 | }, 213 | { 214 | "indexed": false, 215 | "name": "value", 216 | "type": "uint256" 217 | } 218 | ], 219 | "name": "Transfer", 220 | "type": "event" 221 | } 222 | ] --------------------------------------------------------------------------------