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`
}
}
}
}
})