Субграфы, работающие на основе субпотоков (Substreams)
Reading time: 5 min
is a new framework for processing blockchain data, developed by StreamingFast for The Graph Network. A substreams modules can output entity changes, which are compatible with Subgraph entities. A subgraph can use such a Substreams module as a data source, bringing the indexing speed and additional data of Substreams to subgraph developers.
This cookbook requires , , and the latest version of Graph CLI (>=0.52.0):
npm install -g @graphprotocol/graph-cli
graph init --from-example substreams-powered-subgraph
A Substreams package is composed of types (defined as ), modules (written in Rust), and a substreams.yaml
file which references the types, and specifies how modules are triggered. , and check out and the for more examples.
Рассматриваемый пакет Substreams обнаруживает развертывания контрактов в основной сети Ethereum, отслеживая блок создания и временную метку для всех вновь развернутых контрактов. Для этого в /proto/example.proto
есть специальный тип Contract
():
syntax = "proto3";package example;message Contracts {repeated Contract contracts = 1;}message Contract {string address = 1;uint64 blockNumber = 2;string timestamp = 3;uint64 ordinal = 4;}
Основной логикой пакета Substreams является модуль map_contract
в lib.rs
, который обрабатывает каждый блок, фильтруя вызовы Create, которые не были отменены, возвращая Contracts
:
#[substreams::handlers::map]fn map_contract(block: eth::v2::Block) -> Result<Contracts, substreams::errors::Error> {let contracts = block.transactions().flat_map(|tx| {tx.calls.iter().filter(|call| !call.state_reverted).filter(|call| call.call_type == eth::v2::CallType::Create as i32).map(|call| Contract {address: format!("0x{}", Hex(&call.address)),block_number: block.number,timestamp: block.timestamp_seconds().to_string(),ordinal: tx.begin_ordinal,})}).collect();Ok(Contracts { contracts })}
Пакет Substreams может использоваться субграфом, если у него есть модуль, который выдает совместимые изменения объектов. В примере пакета Substreams есть дополнительный модуль graph_out
в lib.rs
который возвращает выходные данные substreams_entity_change::pb::entity::EntityChanges
, которые могут быть обработаны Graph Node.
В крейте substreams_entity_change
также есть специальная функция Tables
для простой генерации изменений объектов (). Сгенерированные изменения объектов должны быть совместимы с объектами schema.graphql
, определенными в subgraph.graphql
соответствующего субграфа.
#[substreams::handlers::map]pub fn graph_out(contracts: Contracts) -> Result<EntityChanges, substreams::errors::Error> {// hash map of name to a tablelet mut tables = Tables::new();for contract in contracts.contracts.into_iter() {tables.create_row("Contract", contract.address).set("timestamp", contract.timestamp).set("blockNumber", contract.block_number);}Ok(tables.to_entity_changes())}
Эти типы и модули объединены в substreams.yaml
:
specVersion: v0.1.0package:name: 'substreams_test' # the name to be used in the .spkgversion: v1.0.1 # the version to use when creating the .spkgimports: # dependenciesentity: https://github.com/streamingfast/substreams-entity-change/releases/download/v0.2.1/substreams-entity-change-v0.2.1.spkgprotobuf: # specifies custom types for use by Substreams modulesfiles:- example.protoimportPaths:- ./protobinaries:default:type: wasm/rust-v1file: ./target/wasm32-unknown-unknown/release/substreams.wasmmodules: # specify modules with their inputs and outputs.- name: map_contractkind: mapinputs:- source: sf.ethereum.type.v2.Blockoutput:type: proto:test.Contracts- name: graph_outkind: mapinputs:- map: map_contractoutput:type: proto:substreams.entity.v1.EntityChanges # this type can be consumed by Graph Node
Вы можете проверить общий "поток" из Блока от map_contract
до graph_out
, запустив substreams graph
:
Чтобы подготовить этот пакет субпотоков к использованию субграфом, необходимо выполнить следующие команды:
yarn substreams:protogen # генерирует типы в /src/pbyarn substreams:build # создает субпотокиyarn substreams:package # упаковывает субпотоки в файл .spkg# в качестве альтернативы, yarn substreams:prepare вызывают все вышеперечисленные команды
Эти скрипты определены в файле package.json
, если вы хотите понять базовые команды субпотоков
При этом создается файл spkg
на основе имени и версии пакета из substreams.yaml
. Файл spkg
содержит всю информацию, которая необходима Graph Node для приема этого пакета субпотоков.
Если Вы обновите пакет субпотоков, в зависимости от внесенных Вами изменений, Вам может потребоваться выполнить некоторые или все вышеперечисленные команды, чтобы spkg
был обновлен.
Субграфы, работающие на основе на субпотоков, вводят в употребление новый "вид" источника данных - "субпотоки". Такие субграфы могут иметь только один источник данных.
В этом источнике данных должна быть указана индексированная сеть, пакет Substreams (spkg
) в качестве относительного местоположения файла и модуль в этом пакете Substreams, который производит совместимые с субграфами изменения объектов (в данном случае map_entity_changes
из пакета Substreams, указанного выше). Мэппинг указан, но просто идентифицирует вид мэппинга ("substreams/graph-entities") и apiVersion.
Currently, Subgraph Studio and The Graph Network support Substreams-powered subgraphs which index mainnet
(Mainnet Ethereum).
specVersion: 0.0.4description: Ethereum Contract Tracking Subgraph (powered by Substreams)repository: https://github.com/graphprotocol/graph-toolingschema:file: schema.graphqldataSources:- kind: substreamsname: substream_testnetwork: mainnetsource:package:moduleName: graph_outfile: substreams-test-v1.0.1.spkgmapping:kind: substreams/graph-entitiesapiVersion: 0.0.5
subgraph.yaml
также ссылается на файл схемы. Требования к этому файлу не изменились, но указанные объекты должны быть совместимы с изменениями объектов, произведенными модулем Substreams, на который ссылается subgraph.yaml
.
type Contract @entity {id: ID!"The timestamp when the contract was deployed"timestamp: String!"The block number of the contract deployment"blockNumber: BigInt!}
Учитывая вышеизложенное, разработчики субграфов могут использовать Graph CLI для развертывания этого субграфа, работающего на основе субпотоков.
Субграфы, работающие на основе субпотоков, индексирующие основную сеть Ethereum, могут быть развернуты в .
yarn install # install graph-cliyarn subgraph:build # build the subgraphyarn subgraph:deploy # deploy the subgraph
Вот и все! Вы создали и развернули субграф, работающий на основе субпотоков.
Для обслуживания субграфов, работающих на основе субпотоков, Graph Node должен быть сконфигурирован с соответствующей сетью провайдера субпотоков, а также с Firehose или RPC для отслеживания головного блока чейна. Эти провайдеры могут быть настроены с помощью файла config.toml
:
[chains.mainnet]shard = "main"protocol = "ethereum"provider = [{ label = "substreams-provider-mainnet",details = { type = "substreams",url = "https://mainnet-substreams-url.grpc.substreams.io/",token = "exampletokenhere" }},{ label = "firehose-provider-mainnet",details = { type = "firehose",url = "https://mainnet-firehose-url.grpc.firehose.io/",token = "exampletokenhere" }},]