diff --git a/db/migrations/1659350771447-Data.js b/db/migrations/1665740912657-Data.js similarity index 89% rename from db/migrations/1659350771447-Data.js rename to db/migrations/1665740912657-Data.js index 2dd0963b..c64fd876 100644 --- a/db/migrations/1659350771447-Data.js +++ b/db/migrations/1665740912657-Data.js @@ -1,8 +1,8 @@ -module.exports = class Data1659350771447 { - name = 'Data1659350771447' +module.exports = class Data1665740912657 { + name = 'Data1665740912657' async up(db) { - await db.query(`CREATE TABLE "transfer" ("id" character varying NOT NULL, "block_number" integer NOT NULL, "timestamp" TIMESTAMP WITH TIME ZONE NOT NULL, "extrinsic_hash" text, "amount" numeric NOT NULL, "fee" numeric, "from_id" character varying, "to_id" character varying, CONSTRAINT "PK_fd9ddbdd49a17afcbe014401295" PRIMARY KEY ("id"))`) + await db.query(`CREATE TABLE "transfer" ("id" character varying NOT NULL, "block_number" integer NOT NULL, "timestamp" TIMESTAMP WITH TIME ZONE NOT NULL, "extrinsic_hash" text, "amount" numeric NOT NULL, "fee" numeric NOT NULL, "from_id" character varying, "to_id" character varying, CONSTRAINT "PK_fd9ddbdd49a17afcbe014401295" PRIMARY KEY ("id"))`) await db.query(`CREATE INDEX "IDX_d6624eacc30144ea97915fe846" ON "transfer" ("block_number") `) await db.query(`CREATE INDEX "IDX_70ff8b624c3118ac3a4862d22c" ON "transfer" ("timestamp") `) await db.query(`CREATE INDEX "IDX_070c555a86b0b41a534a55a659" ON "transfer" ("extrinsic_hash") `) diff --git a/schema.graphql b/schema.graphql index ae82105f..c54a8575 100644 --- a/schema.graphql +++ b/schema.graphql @@ -1,17 +1,7 @@ -type Account @entity { - "Account address" - id: ID! - transfersTo: [Transfer!] @derivedFrom(field: "to") - transfersFrom: [Transfer!] @derivedFrom(field: "from") -} - type Transfer @entity { id: ID! - blockNumber: Int! @index - timestamp: DateTime! @index - extrinsicHash: String @index - from: Account! - to: Account! - amount: BigInt! @index - fee: BigInt! # fee is calculated at the best effort and may be zero for some old extrinsics + from: String! + to: String! + amount: BigInt! + assetId: String! } diff --git a/src/model/generated/account.model.ts b/src/model/generated/account.model.ts deleted file mode 100644 index 09d6c5b4..00000000 --- a/src/model/generated/account.model.ts +++ /dev/null @@ -1,21 +0,0 @@ -import {Entity as Entity_, Column as Column_, PrimaryColumn as PrimaryColumn_, OneToMany as OneToMany_} from "typeorm" -import {Transfer} from "./transfer.model" - -@Entity_() -export class Account { - constructor(props?: Partial) { - Object.assign(this, props) - } - - /** - * Account address - */ - @PrimaryColumn_() - id!: string - - @OneToMany_(() => Transfer, e => e.to) - transfersTo!: Transfer[] - - @OneToMany_(() => Transfer, e => e.from) - transfersFrom!: Transfer[] -} diff --git a/src/model/generated/index.ts b/src/model/generated/index.ts index 0264fef4..1403303c 100644 --- a/src/model/generated/index.ts +++ b/src/model/generated/index.ts @@ -1,2 +1 @@ -export * from "./account.model" export * from "./transfer.model" diff --git a/src/model/generated/transfer.model.ts b/src/model/generated/transfer.model.ts index edb91512..0ce37ad3 100644 --- a/src/model/generated/transfer.model.ts +++ b/src/model/generated/transfer.model.ts @@ -1,6 +1,5 @@ -import {Entity as Entity_, Column as Column_, PrimaryColumn as PrimaryColumn_, Index as Index_, ManyToOne as ManyToOne_} from "typeorm" +import {Entity as Entity_, Column as Column_, PrimaryColumn as PrimaryColumn_} from "typeorm" import * as marshal from "./marshal" -import {Account} from "./account.model" @Entity_() export class Transfer { @@ -11,30 +10,15 @@ export class Transfer { @PrimaryColumn_() id!: string - @Index_() - @Column_("int4", {nullable: false}) - blockNumber!: number + @Column_("text", {nullable: false}) + from!: string - @Index_() - @Column_("timestamp with time zone", {nullable: false}) - timestamp!: Date + @Column_("text", {nullable: false}) + to!: string - @Index_() - @Column_("text", {nullable: true}) - extrinsicHash!: string | undefined | null - - @Index_() - @ManyToOne_(() => Account, {nullable: true}) - from!: Account - - @Index_() - @ManyToOne_(() => Account, {nullable: true}) - to!: Account - - @Index_() @Column_("numeric", {transformer: marshal.bigintTransformer, nullable: false}) amount!: bigint - @Column_("numeric", {transformer: marshal.bigintTransformer, nullable: false}) - fee!: bigint + @Column_("text", {nullable: false}) + assetId!: string } diff --git a/src/processor.ts b/src/processor.ts index 4f125f5d..abe8dd10 100644 --- a/src/processor.ts +++ b/src/processor.ts @@ -1,27 +1,24 @@ -import {lookupArchive} from "@subsquid/archive-registry" -import * as ss58 from "@subsquid/ss58" import {BatchContext, BatchProcessorItem, SubstrateBatchProcessor} from "@subsquid/substrate-processor" import {Store, TypeormDatabase} from "@subsquid/typeorm-store" -import {In} from "typeorm" -import {Account, Transfer} from "./model" +import {Transfer} from "./model" import {BalancesTransferEvent} from "./types/events" const processor = new SubstrateBatchProcessor() .setBatchSize(500) .setDataSource({ - // Lookup archive by the network name in the Subsquid registry - archive: lookupArchive("kusama", {release: "FireSquid"}) - // Use archive created by archive/docker-compose.yml - // archive: 'http://localhost:8888/graphql' + archive: 'http://localhost:8888/graphql' }) .addEvent('Balances.Transfer', { data: { event: { args: true, extrinsic: { - hash: true, + id: true, + from: true, + to: true, + amount: true, fee: true } } @@ -36,60 +33,43 @@ type Ctx = BatchContext processor.run(new TypeormDatabase(), async ctx => { let transfersData = getTransfers(ctx) - let accountIds = new Set() - for (let t of transfersData) { - accountIds.add(t.from) - accountIds.add(t.to) - } - - let accounts = await ctx.store.findBy(Account, {id: In([...accountIds])}).then(accounts => { - return new Map(accounts.map(a => [a.id, a])) - }) - let transfers: Transfer[] = [] for (let t of transfersData) { - let {id, blockNumber, timestamp, extrinsicHash, amount, fee} = t + let { id, amount } = t - let from = getAccount(accounts, t.from) - let to = getAccount(accounts, t.to) + let from = t.from + let to = t.to transfers.push(new Transfer({ id, - blockNumber, - timestamp, - extrinsicHash, from, to, amount, - fee + assetId })) } - await ctx.store.save(Array.from(accounts.values())) + // await ctx.store.save(Array.from(accounts.values())) await ctx.store.insert(transfers) }) interface TransferEvent { id: string - blockNumber: number - timestamp: Date - extrinsicHash?: string from: string to: string - amount: bigint - fee?: bigint + amount: string + assetId: string } - function getTransfers(ctx: Ctx): TransferEvent[] { let transfers: TransferEvent[] = [] for (let block of ctx.blocks) { for (let item of block.items) { if (item.name == "Balances.Transfer") { let e = new BalancesTransferEvent(ctx, item.event) - let rec: {from: Uint8Array, to: Uint8Array, amount: bigint} + let rec: {from: string, to: string, amount: bigint} if (e.isV1020) { let [from, to, amount,] = e.asV1020 rec = {from, to, amount} @@ -101,27 +81,12 @@ function getTransfers(ctx: Ctx): TransferEvent[] { } transfers.push({ id: item.event.id, - blockNumber: block.header.height, - timestamp: new Date(block.header.timestamp), - extrinsicHash: item.event.extrinsic?.hash, - from: ss58.codec('kusama').encode(rec.from), - to: ss58.codec('kusama').encode(rec.to), - amount: rec.amount, - fee: item.event.extrinsic?.fee || 0n + from: rec.from, + to: rec.to, + amount: rec.amount }) } } } return transfers } - - -function getAccount(m: Map, id: string): Account { - let acc = m.get(id) - if (acc == null) { - acc = new Account() - acc.id = id - m.set(id, acc) - } - return acc -} diff --git a/src/types/events.ts b/src/types/events.ts index 3c8f3b7f..009e9f85 100644 --- a/src/types/events.ts +++ b/src/types/events.ts @@ -1,8 +1,5 @@ import assert from 'assert' import {Chain, ChainContext, EventContext, Event, Result} from './support' -import * as v1020 from './v1020' -import * as v1050 from './v1050' -import * as v9130 from './v9130' export class BalancesTransferEvent { private readonly _chain: Chain @@ -27,7 +24,7 @@ export class BalancesTransferEvent { /** * Transfer succeeded (from, to, value, fees). */ - get asV1020(): [v1020.AccountId, v1020.AccountId, v1020.Balance, v1020.Balance] { + get asV1020(): [Uint8Array, Uint8Array, bigint, bigint] { assert(this.isV1020) return this._chain.decodeEvent(this.event) } @@ -42,7 +39,7 @@ export class BalancesTransferEvent { /** * Transfer succeeded (from, to, value). */ - get asV1050(): [v1050.AccountId, v1050.AccountId, v1050.Balance] { + get asV1050(): [Uint8Array, Uint8Array, bigint] { assert(this.isV1050) return this._chain.decodeEvent(this.event) } @@ -57,7 +54,7 @@ export class BalancesTransferEvent { /** * Transfer succeeded. */ - get asV9130(): {from: v9130.AccountId32, to: v9130.AccountId32, amount: bigint} { + get asV9130(): {from: Uint8Array, to: Uint8Array, amount: bigint} { assert(this.isV9130) return this._chain.decodeEvent(this.event) } diff --git a/src/types/support.ts b/src/types/support.ts index a46af0a6..56ef5a9e 100644 --- a/src/types/support.ts +++ b/src/types/support.ts @@ -16,6 +16,8 @@ export interface Chain { getStorageItemTypeHash(prefix: string, name: string): string | undefined getStorage(blockHash: string, prefix: string, name: string, ...args: any[]): Promise queryStorage(blockHash: string, prefix: string, name: string, ...args: any[]): Promise + getConstantTypeHash(pallet: string, name: string): string | undefined + getConstant(pallet: string, name: string): any } diff --git a/src/types/v1020.ts b/src/types/v1020.ts deleted file mode 100644 index 668f015b..00000000 --- a/src/types/v1020.ts +++ /dev/null @@ -1,5 +0,0 @@ -import type {Result} from './support' - -export type AccountId = Uint8Array - -export type Balance = bigint diff --git a/src/types/v1050.ts b/src/types/v1050.ts deleted file mode 100644 index 668f015b..00000000 --- a/src/types/v1050.ts +++ /dev/null @@ -1,5 +0,0 @@ -import type {Result} from './support' - -export type AccountId = Uint8Array - -export type Balance = bigint diff --git a/src/types/v9130.ts b/src/types/v9130.ts deleted file mode 100644 index b4d85f3a..00000000 --- a/src/types/v9130.ts +++ /dev/null @@ -1,3 +0,0 @@ -import type {Result} from './support' - -export type AccountId32 = Uint8Array