Migrate to ArrowSquid (EVM)
This is a EVM guide. Substrate guide is available here. ArrowSquid refers to the versions@subsquid/[email protected] and @subsquid/[email protected]. ArrowSquid is not compatible with the FireSquid archive endpoints. Instead, it uses SQD Network gateways (see the Supported EVM networks page).
The main feature introduced by the ArrowSquid update on EVM is the new ability of the processor to ingest unfinalized blocks directly from a network node, instead of waiting for the archive to ingest and serve it first. The processor can now handle forks and rewrite the contents of its database if it happens to have indexed orphaned blocks. This allows SQD-based APIs to become near real-time and respond to the on-chain activity with subsecond latency.
Another major feature introduced by ArrowSquid is the support for transaction execution receipts, traces and state diffs. It enables a significantly more fine-grained control over the smart contract states, especially in the situations when the EVM log data is insufficient. For example, one can:
- Reliably index transaction data, taking into account the transaction status
- Keep track of internal calls
- Observe smart contract state changes even if they are caused by internal transactions
- Track smart contract creation and destruction
EvmBatchProcessor configuration and data selection interfaces has been simplified and the way in which the data is fetched has been made more efficient.
End-to-end ArrowSquid examples can be found in the SDK repo and in the EVM examples section.
Here is a step-by-step guide for migrating a squid built with an older SDK version to the post-ArrowSquid tooling.
Step 1
Update all packages affected by the update to use Portal API:The
@portal-api version of @subsquid/evm-processor is required for Portal support.file-store, please update any related packages to the @next version, too.
Step 2
Replace the oldsetDataSource() processor configuration call with a combination of setPortal() and setRpcEndpoint(). Use a public Portal URL for your network. If your squid did not use an RPC endpoint before, find one for your network and set it with setRpcEndpoint(). Also configure the network-specific number of transaction confirmations sufficient for finality. For Ethereum mainnet your edit might look like this:
Step 3
Next, we have to account for the changes in signatures ofaddLog() and addTransaction() processor methods. Previously, each call of these methods supplied its own fine-grained field selectors. In the new interface, these calls can only enable or disable the retrieval of related data (with boolean flags transaction for addLog() and logs and a few others for addTransaction()). Field selection is now done by the new setFields() method on a per-item-type basis: once for all logs, once for all transactions etc. The setting is processor-wide: for example, all transactions returned by the processor will have the same set of available fields, regardless of whether they are taken from the batch context directly or are accessed from within a log item.
Begin migrating to the new interface by finding all calls to addLog() and combining all the evmLog field selectors into a single processor-wide field selector that requests all fields previously requested by individual selectors. Remove the id, logIndex (previously index) and transactionIndex fields: now they are always available and cannot be requested explicitly. When done, make a call to setFields() and supply the new field selector at the log field of its argument. For example, suppose the processor was initialized with the following three calls:
Step 4
Repeat step 3 for thetransaction field selector. Make sure to check any transaction field selections by addLog() calls in addition to these made by addTransaction(). Remove the default fields id and transactionIndex (previously index) and add the final field selector to the .setFields() call. For example, suppose the processor was initialized like this:
Step 5
Replace the old calls toaddLog() and addTransaction() with calls using the new signatures.
Old data requests will be erased during the process. Make sure to request the appropriate data with the boolean flags (transaction for addLog() and logs for addTransaction()) while doing that.
For example, a processor originally initialized like this:
Step 6
Finally, update the batch handler to use the new batch context. There are two ways to do that:-
If you’re in a hurry, use the
transformContext.tsmodule. Download it withthen transform the new context to the old format at the beginning of the batch handler:src/processor.ts - Alternatively, rewrite your batch handler using the new batch context interface. Consult the block data page for EVM-specific details on the new context format.
Step 7
Update your transactions/events decoding code. The big change here is that now decoders generated by@subsquid/evm-typegen return bigint where ethers.BigNumber was used before. Regenerate all TypeScript ABI wrappers as described in the EVM typegen section, then find all places where ethers.BigNumbers returned by old decoders were handled in your code and rewrite it to use bigints.
Step 8
Iteratively reconcile any type errors arising when building your squid (e.g. withnpm run build). In case you’re using tranformContext.ts you may find the types it exports helpful. If you need to specify the field selection generic argument explicitly, get it as a typeof of the setFields argument value:

