Data decoding
- squid-evm-typegen
- squid-substrate-typegen
- squid-ink-typegen
Decoding events:
import * as depositsAbi from './abi/deposits'
processor.run(new TypeormDatabase(), async (ctx) => {
for (let c of ctx.blocks) {
for (let log of c.logs) {
if (log.address === CONTRACT_ADDRESS &&
log.topics[0] == depositsAbi.events.Deposit.topic) {
// type-safe decoding of the Deposit event data
const amt = depositsAbi.events.Deposit.decode(log).wad
}
}
}
})
Similar to events, transaction access is provided by the functions object for each contract method defined in the ABI.
To decode events and calls, first determine the appropriate runtime version with .is(), then decode them with .decode():
import {events, calls} from './types'
processor.run(new TypeormDatabase(), async ctx => {
for (let block of ctx.blocks) {
for (let event of block.events) {
if (event.name == events.balances.transfer.name) {
let rec: {from: Bytes, to: Bytes, amount: bigint}
if (events.balances.transfer.v1020.is(event)) {
let [from, to, amount, fee] =
events.balances.transfer.v1020.decode(event)
rec = {from, to, amount}
}
// ... decode all runtime versions similarly
// with events.balances.transfer.${ver}.is/.decode
}
}
for (let call of block.calls) {
if (call.name == calls.balances.forceTransfer.name) {
let rec: {source: Bytes, dest: Bytes, value: bigint} | undefined
if (calls.balances.forceTransfer.v1020.is(call)) {
let res =
calls.balances.forceTransfer.v1020.decode(call)
assert(res.source.__kind === 'AccountId')
assert(res.dest.__kind === 'AccountId')
rec = {
source: res.source.value,
dest: res.dest.value,
value: res.value
}
}
// ... decode all runtime versions similarly
// with calls.balances.forceTransfer.${ver}.is/.decode
}
}
})
Here is an example of a utility module generated by the ink! typegen:
src/abi/erc20.ts
const _abi = new Abi(metadata)
export function decodeEvent(hex: string): Event {
return _abi.decodeEvent(hex)
}
export function decodeMessage(hex: string): Message {
return _abi.decodeMessage(hex)
}
export function decodeConstructor(hex: string): Constructor {
return _abi.decodeConstructor(hex)
}
The usage in a batch handler is straightforward:
processor.run(new TypeormDatabase(), async ctx => {
for (let block of ctx.blocks) {
for (let event of block.events) {
if (event.name==='Contracts.ContractEmitted' &&
event.args.contract===CONTRACT_ADDRESS) {
let event = erc20.decodeEvent(event.args.data)
if (event.__kind==='Transfer') {
// event is of type `Event_Transfer`
}
}
}
}
})