Skip to content

Commit

Permalink
Process & map TokensTransferEvent (#207)
Browse files Browse the repository at this point in the history
* Generate types for `Tokens.Transfer`

* Create handler for TokensTransferEvent init

* Handle token balances using tokensTransfer handler

* Connect handlers to processor
  • Loading branch information
saboonikhil committed Oct 21, 2022
1 parent 6222401 commit e5b5d16
Show file tree
Hide file tree
Showing 5 changed files with 198 additions and 4 deletions.
103 changes: 102 additions & 1 deletion src/mappings/tokens/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { EventHandlerContext, SubstrateEvent } from '@subsquid/substrate-process
import { Store } from '@subsquid/typeorm-store'
import { Account, AccountBalance, Asset, HistoricalAccountBalance } from '../../model'
import { initBalance } from '../helper'
import { getTokensEndowedEvent } from './types'
import { getTokensEndowedEvent, getTokensTransferEvent } from './types'


export async function tokensEndowed(ctx: EventHandlerContext<Store, {event: {args: true}}>) {
Expand Down Expand Up @@ -51,4 +51,105 @@ export async function tokensEndowed(ctx: EventHandlerContext<Store, {event: {arg
hab.timestamp = new Date(block.timestamp)
console.log(`[${event.name}] Saving historical account balance: ${JSON.stringify(hab, null, 2)}`)
await store.save<HistoricalAccountBalance>(hab)
}

export async function tokensTransfer(ctx: EventHandlerContext<Store, {event: {args: true}}>) {
const { store, block, event } = ctx
const { assetId, fromId, toId, amount } = getTokensTransferEvent(ctx)

let fromAcc = await store.get(Account, { where: { accountId: fromId } })
if (!fromAcc) {
fromAcc = new Account()
fromAcc.id = event.id + '-' + fromId.substring(fromId.length - 5)
fromAcc.accountId = fromId
fromAcc.pvalue = 0
console.log(`[${event.name}] Saving account: ${JSON.stringify(fromAcc, null, 2)}`)
await store.save<Account>(fromAcc)
await initBalance(fromAcc, store, block, event as SubstrateEvent)
}

const asset = await store.get(Asset, { where: { assetId: assetId } })

let fromAb = await store.findOneBy(AccountBalance, { account: { accountId: fromId }, assetId: assetId })
let oldValue = 0
if (fromAb) {
fromAb.balance = fromAb.balance - amount
oldValue = fromAb.value!
} else {
fromAb = new AccountBalance()
fromAb.id = event.id + '-' + fromId.substring(fromId.length - 5)
fromAb.account = fromAcc
fromAb.assetId = assetId
fromAb.balance = - amount
}
fromAb.value = asset ? asset.price ? Number(fromAb.balance) * asset.price : 0 : null
console.log(`[${event.name}] Saving account balance: ${JSON.stringify(fromAb, null, 2)}`)
await store.save<AccountBalance>(fromAb)

fromAcc.pvalue = fromAb.value ? fromAcc.pvalue - oldValue + fromAb.value! : fromAcc.pvalue
console.log(`[${event.name}] Saving account: ${JSON.stringify(fromAcc, null, 2)}`)
await store.save<Account>(fromAcc)

let fromHab = new HistoricalAccountBalance()
fromHab.id = event.id + '-' + fromId.substring(fromId.length - 5)
fromHab.accountId = fromAcc.accountId
fromHab.event = event.name.split('.')[1]
fromHab.assetId = fromAb.assetId
fromHab.dBalance = - amount
fromHab.balance = fromAb.balance
fromHab.dValue = fromAb.value ? fromAb.value - oldValue : 0
fromHab.value = fromAb.value
fromHab.pvalue = fromAcc.pvalue
fromHab.blockNumber = block.height
fromHab.timestamp = new Date(block.timestamp)
console.log(`[${event.name}] Saving historical account balance: ${JSON.stringify(fromHab, null, 2)}`)
await store.save<HistoricalAccountBalance>(fromHab)

let toAcc = await store.get(Account, { where: { accountId: toId } })
if (!toAcc) {
toAcc = new Account()
toAcc.id = event.id + '-' + toId.substring(toId.length - 5)
toAcc.accountId = toId
toAcc.pvalue = 0
console.log(`[${event.name}] Saving account: ${JSON.stringify(toAcc, null, 2)}`)
await store.save<Account>(toAcc)
await initBalance(toAcc, store, block, event as SubstrateEvent)
}

let toAb = await store.findOneBy(AccountBalance, { account: { accountId: toId }, assetId: assetId })
if (!toAb) { return }

let hab = await store.get(HistoricalAccountBalance, { where:
{ accountId: toAcc.accountId, assetId: assetId, event: 'Endowed', blockNumber: block.height } })
if (!hab) {
toAb.balance = toAb.balance + amount
oldValue = toAb.value!
toAb.value = asset ? asset.price ? Number(toAb.balance) * asset.price : 0 : null
console.log(`[${event.name}] Saving account balance: ${JSON.stringify(toAb, null, 2)}`)
await store.save<AccountBalance>(toAb)
} else {
hab.event = hab.event.concat(event.name.split('.')[1])
console.log(`[${event.name}] Saving historical account balance: ${JSON.stringify(hab, null, 2)}`)
await store.save<HistoricalAccountBalance>(hab)
return
}

toAcc.pvalue = toAb.value ? toAcc.pvalue - oldValue + toAb.value! : toAcc.pvalue
console.log(`[${event.name}] Saving account: ${JSON.stringify(toAcc, null, 2)}`)
await store.save<Account>(toAcc)

let toHab = new HistoricalAccountBalance()
toHab.id = event.id + '-' + toId.substring(toId.length - 5)
toHab.accountId = toAcc.accountId
toHab.event = event.name.split('.')[1]
toHab.assetId = toAb.assetId
toHab.dBalance = amount
toHab.balance = toAb.balance
toHab.dValue = toAb.value ? toAb.value - oldValue : 0
toHab.value = toAb.value
toHab.pvalue = toAcc.pvalue
toHab.blockNumber = block.height
toHab.timestamp = new Date(block.timestamp)
console.log(`[${event.name}] Saving historical account balance: ${JSON.stringify(toHab, null, 2)}`)
await store.save<HistoricalAccountBalance>(toHab)
}
34 changes: 33 additions & 1 deletion src/mappings/tokens/types.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { encodeAddress } from '@polkadot/keyring'
import * as ss58 from '@subsquid/ss58'
import { EventContext } from '../../types/support'
import { TokensEndowedEvent } from '../../types/events'
import { TokensEndowedEvent, TokensTransferEvent } from '../../types/events'
import { getAssetId } from '../helper'


Expand All @@ -26,8 +26,40 @@ export function getTokensEndowedEvent(ctx: EventContext): EndowedEvent {
return {assetId, walletId, amount}
}

export function getTokensTransferEvent(ctx: EventContext): TransferEvent {
const transferEvent = new TokensTransferEvent(ctx)
let currencyId, from, fromId, to, toId, amount
if (transferEvent.isV23) {
[currencyId, from, to, amount] = transferEvent.asV23
fromId = ss58.codec('zeitgeist').encode(from)
toId = ss58.codec('zeitgeist').encode(to)
} else if (transferEvent.isV32) {
[currencyId, from, to, amount] = transferEvent.asV32
fromId = ss58.codec('zeitgeist').encode(from)
toId = ss58.codec('zeitgeist').encode(to)
} else if (transferEvent.isV34) {
currencyId = transferEvent.asV34.currencyId
fromId = ss58.codec('zeitgeist').encode(transferEvent.asV34.from)
toId = ss58.codec('zeitgeist').encode(transferEvent.asV34.to)
amount = transferEvent.asV34.amount
} else {
[currencyId, from, to, amount] = ctx.event.args
fromId = encodeAddress(from, 73)
toId = encodeAddress(to, 73)
}
const assetId = getAssetId(currencyId)
return {assetId, fromId, toId, amount}
}

interface EndowedEvent {
assetId: any
walletId: string
amount: bigint
}

interface TransferEvent {
assetId: any
fromId: string
toId: string
amount: bigint
}
3 changes: 2 additions & 1 deletion src/processor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import { boughtCompleteSet, marketApproved, marketClosed, marketCreated, marketD
import { poolActive, poolClosed, poolCreate, poolExit, poolJoin, swapExactAmountIn,
swapExactAmountOut } from './mappings/swaps';
import { systemExtrinsicFailed, systemExtrinsicSuccess, systemNewAccount } from './mappings/system';
import { tokensEndowed } from './mappings/tokens';
import { tokensEndowed, tokensTransfer } from './mappings/tokens';

(BigInt.prototype as any).toJSON = function () {
return this.toString();
Expand Down Expand Up @@ -67,6 +67,7 @@ processor.addEventHandler('Swaps.SwapExactAmountOut', ctx => swapExactAmountOut(
processor.addEventHandler('System.NewAccount', ctx => systemNewAccount(ctx))

processor.addEventHandler('Tokens.Endowed', ctx => tokensEndowed(ctx))
processor.addEventHandler('Tokens.Transfer', ctx => tokensTransfer(ctx))

if (!process.env.WS_NODE_URL?.includes(`bs`)) {
processor.addEventHandler('Balances.Transfer', ctx => balancesTransfer(ctx))
Expand Down
59 changes: 59 additions & 0 deletions src/types/events.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1829,3 +1829,62 @@ export class TokensEndowedEvent {
return this._chain.decodeEvent(this.event)
}
}

export class TokensTransferEvent {
private readonly _chain: Chain
private readonly event: Event

constructor(ctx: EventContext)
constructor(ctx: ChainContext, event: Event)
constructor(ctx: EventContext, event?: Event) {
event = event || ctx.event
assert(event.name === 'Tokens.Transfer')
this._chain = ctx._chain
this.event = event
}

/**
* Transfer succeeded. \[currency_id, from, to, value\]
*/
get isV23(): boolean {
return this._chain.getEventHash('Tokens.Transfer') === 'd4ffed7d43664acfa5fe9f6825f538d93e8447c873d770deb40246b11895e2ab'
}

/**
* Transfer succeeded. \[currency_id, from, to, value\]
*/
get asV23(): [v23.CurrencyId, Uint8Array, Uint8Array, bigint] {
assert(this.isV23)
return this._chain.decodeEvent(this.event)
}

/**
* Transfer succeeded. \[currency_id, from, to, value\]
*/
get isV32(): boolean {
return this._chain.getEventHash('Tokens.Transfer') === '3eb8c7c7a28e521728d456307ad372e814aeb4fb200f4be58a00098f9f61c8de'
}

/**
* Transfer succeeded. \[currency_id, from, to, value\]
*/
get asV32(): [v32.Asset, Uint8Array, Uint8Array, bigint] {
assert(this.isV32)
return this._chain.decodeEvent(this.event)
}

/**
* Transfer succeeded.
*/
get isV34(): boolean {
return this._chain.getEventHash('Tokens.Transfer') === 'ad3d65a0944e3402fd00687198797c37e7b3335997a6f2143cf8893f4d007b35'
}

/**
* Transfer succeeded.
*/
get asV34(): {currencyId: v34.Asset, from: Uint8Array, to: Uint8Array, amount: bigint} {
assert(this.isV34)
return this._chain.decodeEvent(this.event)
}
}
3 changes: 2 additions & 1 deletion typegen.json
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,8 @@
"System.NewAccount",
"System.ExtrinsicSuccess",
"System.ExtrinsicFailed",
"Tokens.Endowed"
"Tokens.Endowed",
"Tokens.Transfer"
],
"calls": []
}

0 comments on commit e5b5d16

Please sign in to comment.