Generating utility modules
- squid-evm-typegen
- squid-substrate-typegen
- squid-ink-typegen
The squid-evm-typegen(1)
tool generates TypeScript facades for EVM transactions, logs and eth_call
queries.
The generated facades are assumed to be used by squids indexing EVM data.
The tool takes a JSON ABIs as an input. Those can be specified in three ways:
-
as a plain JSON file(s):
npx squid-evm-typegen src/abi abi/erc20.json
To include all files in
./abi
and add an interface for the Multicall contract, runnpx squid-evm-typegen ./src/abi ./abi/*.json --multicall
-
as a contract address (to fetch the ABI from Etherscan API). Once can pass multiple addresses at once.
npx squid-evm-typegen src/abi 0xBB9bc244D798123fDe783fCc1C72d3Bb8C189413
Please check if your contract is a proxy when using this method. If it is, consult this page for guidance.
-
as an arbitrary URL:
npx squid-evm-typegen src/abi https://example.com/erc721.json
In all cases typegen will use basename
of the ABI as the root name for the generated files. You can change the basename of generated files using the fragment (#)
suffix.
squid-evm-typegen src/abi 0xBB9bc244D798123fDe783fCc1C72d3Bb8C189413#my-contract-name
Arguments:
output-dir | output directory for generated definitions |
abi | A contract address, an URL or a local path to the ABI file. Accepts multiple contracts. |
Options:
--multicall | generate a facade for the MakerDAO multicall contract. May significantly improve the performance of contract state calls by batching RPC requests |
--etherscan-api <url> | etherscan API to fetch contract ABI by a known address. By default, https://api.etherscan.io/ |
--clean | delete output directory before the run |
-h, --help | display help for command |
The generated modules depend on @subsquid/evm-abi
. Please add it to your package.json
as a peer dependency if it's not there already:
npm i @subsquid/evm-abi
Usage
The generated utility modules have three intended uses:
-
Constants: EVM log topic0 values and sighashes for transactions. Example:
// generated by evm-typegen
import * as weth from './abi/weth'
const CONTRACT_ADDRESS = '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2'.toLowerCase()
const processor = new EvmBatchProcessor()
.setGateway('https://v2.archive.subsquid.io/network/ethereum-mainnet')
.addLog({
address: [CONTRACT_ADDRESS],
topic0: [
weth.events.Deposit.topic,
weth.events.Withdrawal.topic
]
}) -
Direct chain state queries, including queries to multicall.
The substrate typegen tool is a part of Squid SDK. It generates TypeScript wrappers for interfacing Substrate events and calls.
Usage:
npx squid-substrate-typegen typegen.json
If necessary, multiple config files can be supplied:
npx squid-substrate-typegen typegen0.json typegen1.json ...
The structure of the typegen.json
config file is best illustrated with an example:
{
"outDir": "src/types",
"specVersions": "https://v2.archive.subsquid.io/metadata/kusama",
"pallets": {
// add one such section for each pallet
"Balances": {
"events": [
// list of events to generate wrappers for
"Transfer"
],
"calls": [
// list of calls to generate wrappers for
"transfer_allow_death"
],
"storage": [
"Account"
],
"constants": [
"ExistentialDeposit"
]
}
}
}
The specVersions
field is either
- a metadata service endpoint URL, like
or
https://v2.archive.subsquid.io/metadata/{network}
- a path to a
jsonl
file generated bysubstrate-metadata-explorer(1)
.
To generate all items defined by a given pallet, set any of the events
, calls
, storage
or constants
fields to true
, e.g.
{
"outDir": "src/types",
"specVersions": "kusamaVersions.jsonl",
"pallets": {
"Balances": {
// generate wrappers for all Balances pallet constants
"constants": true
}
}
}
In the rare cases when the typegen needs a types bundle, supply it alongside metadata:
{
"outDir": "src/types",
"specVersions": "westendVersions.jsonl",
"typesBundle": "westendTypes.json",
...
}
TypeScript wrappers
Wrappers generated by the typegen command can be found in the specified outDir
(src/types
by convention). Assuming that this folder is imported as types
(e.g. with import * as types from './types'
), you'll be able to find the wrappers at:
- for events:
types.events.${palletName}.${eventName}
- for calls:
types.calls.${palletName}.${callName}
- for storage items:
types.storage.${palletName}.${storageItemName}
- for constants:
types.constants.${palletName}.${constantName}
All identifiers (pallet name, call name etc) are lowerCamelCased. E.g. the constant Balances.ExistentialDeposit
becomes types.events.balances.existentialDeposit
and the call Balances.set_balance
becomes types.calls.setBalance
.
Usage
-
Item name constants (e.g.
events.balances.transfer.name
). -
Runtime versioning-aware decoding.
-
Runtime constants:
import {constants} from './types'
// ...
processor.run(new TypeormDatabase(), async ctx => {
for (let block of ctx.blocks) {
if (constants.balances.existentialDeposit.v1020.is(block.header)) {
let c = new constants.balances.existentialDeposit.v1020.get(block.header)
ctx.log.info(`Balances.ExistentialDeposit (runtime version V1020): ${c}`)
}
}
})
Use squid-ink-typegen
to generate facade classes for decoding ink! smart contract data from JSON ABI metadata.
Usage:
npx squid-ink-typegen --abi abi/erc20.json --output src/abi/erc20.ts
The generated source code exposes the decoding methods, some useful types and a class for performing wrapped RPC queries, using @subsquid/ink-abi
under the hood