squid-substrate-typegen generates TypeScript wrappers for interfacing Substrate events, calls,
storage items, and constants, aware of runtime version changes. A companion tool,
squid-ink-typegen, does the same for ink! smart contracts.
Install both with --save-dev.
Generating wrappers
typegen.json are resolved relative to the config file. The structure is best
illustrated with an example:
specVersions field is either
- a metadata service endpoint URL, like
or
- a path to a
jsonlfile generated bysubstrate-metadata-explorer(1).
events, calls, storage or
constants fields to true. The events, calls, storage, and constants selectors can
also be set at the top level to select items across pallets, and a pallet entry can itself be
true to select the whole pallet.
In the rare cases when typegen needs pre-v14 type definitions, Built-in bundles include
typesBundle accepts either a
built-in chain name or a path to a JSON bundle (resolved relative to typegen.json):acala/karura, aleph-node, altair, astar, basilisk,
bifrost, calamari, clover, crust, darwinia, hydradx, khala, kilt, kintsugi,
kusama, manta, moonbeam/moonbase/moonriver, parallel/heiko, pioneer, polkadot,
reef, shell, shiden, shibuya, sora-substrate, statemint/statemine, subsocial,
unique/quartz, and zeitgeist. See also the
types bundle miniguide.TypeScript wrappers
Wrappers generated by the typegen command can be found in the specifiedoutDir (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}
Balances.ExistentialDeposit becomes types.constants.balances.existentialDeposit and the call
Balances.set_balance becomes types.calls.balances.setBalance.
Runtime constants are available directly from the wrappers:
Decoding events and calls
To decode events and calls, first determine the appropriate runtime version with.is(), then
decode them with .decode():
Storage queries
It is sometimes impossible to extract the required data with only event and call data without querying the runtime state. The context exposes a lightweight JSON-RPC client atctx._chain.rpc
with low-level methods for accessing the storage. However, the recommended way to query the
storage is with the type-safe wrappers exposed at src/types/storage.ts, following the
general naming pattern:
block argument.
Example of a generated storage wrapper
Example of a generated storage wrapper
src/types/balances/storage.ts
- the default storage value with
getDefault(block) - a single storage value with
get(block, key) - multiple values in a batch call with
getMany(block, keys[]) - all storage keys with
getKeys(block) - all keys with a given prefix with
getKeys(block, keyPrefix)(only if the storage keys are decodable) - paginated keys via
getKeysPaged(pageSize, block)andgetKeysPaged(pageSize, block, keyPrefix) - key-value pairs via
getPairs(block)andgetPairs(block, keyPrefix) - paginated key-value pairs via
getPairsPaged(pageSize, block)andgetPairsPaged(pageSize, block, keyPrefix)
src/main.ts
ink! contracts
Usesquid-ink-typegen
to generate facade classes for decoding ink! smart contract data from JSON ABI metadata:
@subsquid/ink-abi under the hood:
src/abi/erc20.ts
Contract class provides facades for all state calls that don’t mutate the
contract state (mutability is taken from the contract metadata):