Docs
Buscar⌘ K
  • Início
  • Sobre o The Graph
  • Redes Apoiadas
  • Contratos de Protocolo
  • Subgraphs
    • Substreams
      • Token API
        • AI Suite
          • Indexação
            • Recursos
              Subgraphs > Programação > Criação

              17 minutos

              Funções Avançadas de Subgraph

              Visão geral

              Add and implement advanced Subgraph features to enhanced your Subgraph’s built.

              Starting from specVersion 0.0.4, Subgraph features must be explicitly declared in the features section at the top level of the manifest file, using their camelCase name, as listed in the table below:

              FunçãoNome
              Erros não fataisnonFatalErrors
              Busca em full-textfullTextSearch
              Enxertosgrafting

              For instance, if a Subgraph uses the Full-Text Search and the Non-fatal Errors features, the features field in the manifest should be:

              1specVersion: 1.3.02description: Gravatar for Ethereum3features:4  - fullTextSearch5  - nonFatalErrors6dataSources: ...

              Note that using a feature without declaring it will incur a validation error during Subgraph deployment, but no errors will occur if a feature is declared but not used.

              Séries de Tempo e Agregações

              Pré-requisitos:

              • O specVersion do subgraph deve ser maior que 1.1.0.

              Timeseries and aggregations enable your Subgraph to track statistics like daily average price, hourly total transfers, and more.

              This feature introduces two new types of Subgraph entity. Timeseries entities record data points with timestamps. Aggregation entities perform pre-declared calculations on the timeseries data points on an hourly or daily basis, then store the results for easy access via GraphQL.

              Exemplo de Schema

              1type Data @entity(timeseries: true) {2  id: Int8!3  timestamp: Timestamp!4  price: BigDecimal!5}67type Stats @aggregation(intervals: ["hour", "day"], source: "Data") {8  id: Int8!9  timestamp: Timestamp!10  sum: BigDecimal! @aggregate(fn: "sum", arg: "price")11}

              Como Definir Séries Temporais e Agregações

              Entidades de séries temporais são definidas com @entity(timeseries: true) no schema da GraphQL. Toda entidade deste tipo deve:

              • ter uma ID exclusiva do tipo int8
              • ter um registro de data e hora do tipo Timestamp
              • incluir dados a serem usados para cálculo pelas entidades de agregação.

              Estas entidades de Série Temporal podem ser guardadas em handlers regulares de gatilho, e atuam como “dados brutos” para as entidades de agregação.

              As entidades de agregação são definidas com @aggregation no schema da GraphQL. Toda entidade deste tipo define a fonte de onde retirará dados (que deve ser uma entidade de Série Temporal), determina os intervalos (por ex., hora, dia) e especifica a função de agregação que usará (por ex., soma, contagem, min, max, primeiro, último).

              As entidades de agregação são calculadas automaticamente com base na fonte especificada no final do intervalo necessário.

              Intervalos de Agregação Disponíveis

              • hour: configura o período de série de tempo para cada hora, em ponto.
              • day: configura o período de série de tempo para cada dia, a começar e terminar à meia-noite.

              Funções de Agregação Disponíveis

              • sum: Total de todos os valores.
              • count: Número de valores.
              • min: Valor mínimo.
              • max: Valor máximo.
              • first: Primeiro valor no período.
              • last: Último valor no período.

              Exemplo de Query de Agregações

              1{2  stats(interval: "hour", where: { timestamp_gt: 1704085200 }) {3    id4    timestamp5    sum6  }7}

              Leia mais⁠ sobre Séries Temporais e Agregações.

              Erros não-fatais

              Indexing errors on already synced Subgraphs will, by default, cause the Subgraph to fail and stop syncing. Subgraphs can alternatively be configured to continue syncing in the presence of errors, by ignoring the changes made by the handler which provoked the error. This gives Subgraph authors time to correct their Subgraphs while queries continue to be served against the latest block, though the results might be inconsistent due to the bug that caused the error. Note that some errors are still always fatal. To be non-fatal, the error must be known to be deterministic.

              Note: The Graph Network does not yet support non-fatal errors, and developers should not deploy Subgraphs using that functionality to the network via the Studio.

              Enabling non-fatal errors requires setting the following feature flag on the Subgraph manifest:

              1specVersion: 1.3.02description: Gravatar for Ethereum3features:4    - nonFatalErrors5    ...

              The query must also opt-in to querying data with potential inconsistencies through the subgraphError argument. It is also recommended to query _meta to check if the Subgraph has skipped over errors, as in the example:

              1foos(first: 100, subgraphError: allow) {2  id3}45_meta {6  hasIndexingErrors7}

              If the Subgraph encounters an error, that query will return both the data and a graphql error with the message "indexing_error", as in this example response:

              1"data": {2    "foos": [3        {4          "id": "0xdead"5        }6    ],7    "_meta": {8        "hasIndexingErrors": true9    }10},11"errors": [12    {13        "message": "indexing_error"14    }15]

              Fontes de Dados de Arquivos em IPFS/Arweave

              File data sources are a new Subgraph functionality for accessing off-chain data during indexing in a robust, extendable way. File data sources support fetching files from IPFS and from Arweave.

              Isto também abre as portas para indexar dados off-chain de forma determinística, além de potencialmente introduzir dados arbitrários com fonte em HTTP.

              Visão geral

              Em vez de buscar arquivos “em fila” durante a execução do handler, isto introduz modelos que podem ser colocados como novas fontes de dados para um identificador de arquivos. Estas novas fontes de dados pegam os arquivos e tentam novamente caso não obtenham êxito; quando o arquivo é encontrado, executam um handler dedicado.

              Isso é semelhante aos modelos existentes de fonte de dados, usados para criar dinamicamente novas fontes de dados baseados em chain.

              Isto substitui a API ipfs.cat existente

              Guia de atualização

              Atualização de graph-ts e graph-cli

              O recurso de fontes de dados de arquivos exige o graph-ts na versão acima de 0.29.0 e o graph-cli acima de 0.33.1

              Adicionar um novo tipo de entidade que será atualizado quando os arquivos forem encontrados

              Fontes de dados de arquivos não podem acessar ou atualizar entidades baseadas em chain, mas devem atualizar entidades específicas a arquivos.

              Isto pode implicar separar campos de entidades existentes em entidades separadas, ligadas juntas.

              Entidade combinada original:

              1type Token @entity {2  id: ID!3  tokenID: BigInt!4  tokenURI: String!5  externalURL: String!6  ipfsURI: String!7  image: String!8  name: String!9  description: String!10  type: String!11  updatedAtTimestamp: BigInt12  owner: User!13}

              Entidade nova, separada:

              1type Token @entity {2  id: ID!3  tokenID: BigInt!4  tokenURI: String!5  ipfsURI: TokenMetadata6  updatedAtTimestamp: BigInt7  owner: String!8}910type TokenMetadata @entity {11  id: ID!12  image: String!13  externalURL: String!14  name: String!15  description: String!16}

              Se o relacionamento for perfeitamente proporcional entre a entidade parente e a entidade de fontes de dados de arquivos resultante, é mais simples ligar a entidade parente a uma entidade de arquivos resultante, com a CID IPFS como o assunto de busca. Se tiver dificuldades em modelar suas novas entidades baseadas em arquivos, pergunte no Discord!

              É possível usar filtros aninhados para filtrar entidades parentes, com base nestas entidades aninhadas.

              Adicione um novo modelo de fonte de dados com kind: file/ipfs ou kind: file/arweave

              Esta é a fonte de dados que será gerada quando um arquivo de interesse for identificado.

              1templates:2  - name: TokenMetadata3    kind: file/ipfs4    mapping:5      apiVersion: 0.0.96      language: wasm/assemblyscript7      file: ./src/mapping.ts8      handler: handleMetadata9      entities:10        - TokenMetadata11      abis:12        - name: Token13          file: ./abis/Token.json

              Atualmente é obrigatório usar abis, mas não é possível chamar contratos de dentro de fontes de dados de arquivos

              A fonte de dados de arquivos deve mencionar, especificamente, todos os tipos de entidades com os quais ela interagirá sob entities. Veja as limitações para mais detalhes.

              Criar um novo handler para processar arquivos

              Este handler deve aceitar um parâmetro Bytes, que consistirá dos conteúdos do arquivo; quando encontrado, este poderá ser acessado. Isto costuma ser um arquivo JSON, que pode ser processado com helpers graph-ts (documentação).

              A CID do arquivo como um string legível pode ser acessada através do dataSource a seguir:

              1const cid = dataSource.stringParam()

              Exemplo de handler:

              1import { json, Bytes, dataSource } from '@graphprotocol/graph-ts'2import { TokenMetadata } from '../generated/schema'34export function handleMetadata(content: Bytes): void {5  let tokenMetadata = new TokenMetadata(dataSource.stringParam())6  const value = json.fromBytes(content).toObject()7  if (value) {8    const image = value.get('image')9    const name = value.get('name')10    const description = value.get('description')11    const externalURL = value.get('external_url')1213    if (name && image && description && externalURL) {14      tokenMetadata.name = name.toString()15      tokenMetadata.image = image.toString()16      tokenMetadata.externalURL = externalURL.toString()17      tokenMetadata.description = description.toString()18    }1920    tokenMetadata.save()21  }22}

              Gerar fontes de dados de arquivos quando for obrigatório

              Agora pode criar fontes de dados de arquivos durante a execução de handlers baseados em chain:

              • Importe o modelo do templates gerado automaticamente
              • chame o TemplateName.create(cid: string) de dentro de um mapeamento, onde o cid é um identificador de conteúdo válido para IPFS ou Arweave

              Para o IPFS, o Graph Node apoia identificadores de conteúdo v0 e v1⁠ e identificadores com diretórios (por ex. bafyreighykzv2we26wfrbzkcdw37sbrby4upq7ae3aqobbq7i4er3tnxci/metadata.json).

              Para o Arweave, a partir da versão 0.33.0, o Graph Node pode buscar arquivos armazenados no Arweave com base no seu ID de transação⁠ de um gateway Arweave (exemplo de arquivo⁠). O Arweave apoia transações enviadas via Irys (antigo Bundlr), e o Graph Node também pode solicitar arquivos com base em manifests do Irys⁠.

              Exemplo:

              1import { TokenMetadata as TokenMetadataTemplate } from '../generated/templates'23const ipfshash = 'QmaXzZhcYnsisuue5WRdQDH6FDvqkLQX1NckLqBYeYYEfm'4//This example code is for a Crypto coven Subgraph. The above ipfs hash is a directory with token metadata for all crypto coven NFTs.56export function handleTransfer(event: TransferEvent): void {7  let token = Token.load(event.params.tokenId.toString())8  if (!token) {9    token = new Token(event.params.tokenId.toString())10    token.tokenID = event.params.tokenId1112    token.tokenURI = '/' + event.params.tokenId.toString() + '.json'13    const tokenIpfsHash = ipfshash + token.tokenURI14    //This creates a path to the metadata for a single Crypto coven NFT. It concats the directory with "/" + filename + ".json"1516    token.ipfsURI = tokenIpfsHash1718    TokenMetadataTemplate.create(tokenIpfsHash)19  }2021  token.updatedAtTimestamp = event.block.timestamp22  token.owner = event.params.to.toHexString()23  token.save()24}

              Isto criará uma fonte de dados de arquivos, que avaliará o endpoint de IPFS ou Arweave configurado do Graph Node, e tentará novamente caso não achá-lo. Com o arquivo localizado, o handler da fonte de dados de arquivos será executado.

              Este exemplo usa a CID como a consulta entre a entidade parente Token e a entidade TokenMetadata resultante.

              Previously, this is the point at which a Subgraph developer would have called ipfs.cat(CID) to fetch the file

              Parabéns, você está a usar fontes de dados de arquivos!

              Deploying your Subgraphs

              You can now build and deploy your Subgraph to any Graph Node >=v0.30.0-rc.0.

              Limitações

              File data source handlers and entities are isolated from other Subgraph entities, ensuring that they are deterministic when executed, and ensuring no contamination of chain-based data sources. To be specific:

              • Entidades criadas por Fontes de Dados de Arquivos são imutáveis, e não podem ser atualizadas
              • Handlers de Fontes de Dados de Arquivos não podem acessar entidades de outras fontes de dados de arquivos
              • Entidades associadas com Fontes de Dados de Arquivos não podem ser acessadas por handlers baseados em chain

              While this constraint should not be problematic for most use-cases, it may introduce complexity for some. Please get in touch via Discord if you are having issues modelling your file-based data in a Subgraph!

              Além disto, não é possível criar fontes de dados de uma fonte de dado de arquivos, seja uma on-chain ou outra fonte de dados de arquivos. Esta restrição poderá ser retirada no futuro.

              Boas práticas

              Caso ligue metadados de NFTs a tokens correspondentes, use o hash IPFS destes para referenciar uma entidade de Metadados da entidade do Token. Salve a entidade de Metadados a usar o hash IPFS como ID.

              Você pode usar o contexto de DataSource ao criar Fontes de Dados de Arquivo (FDS), para passar informações extras que estarão disponíveis para o handler de FDS.

              Caso tenha entidades a ser atualizadas várias vezes, crie entidades únicas baseadas em arquivos utilizando o hash IPFS e o ID da entidade, e as referencie com um campo derivado na entidade baseada na chain.

              Estamos a melhorar a recomendação acima, para que os queries retornem apenas a versão “mais recente”

              Problemas conhecidos

              Fontes de dados de arquivo atualmente requerem ABIs, mesmo que estas não sejam usadas (problema⁠). Por enquanto, vale a pena adicionar qualquer ABI como alternativa.

              Handlers para Fontes de Dados de Arquivos não podem estar em arquivos que importam ligações de contrato eth_call, o que causa falhas com “unknown import: ethereum::ethereum.call has not been defined” (problema no GitHub⁠). A solução atual é criar handlers de fontes de dados de arquivos num arquivo dedicado.

              Exemplos

              Migração de Subgraph do Crypto Coven⁠

              Referências

              Fontes de Dados de Arquivos GIP⁠

              Filtros de Argumentos Indexados / Filtros de Tópicos

              Obrigatório: SpecVersion >= 1.2.0

              Topic filters, also known as indexed argument filters, are a powerful feature in Subgraphs that allow users to precisely filter blockchain events based on the values of their indexed arguments.

              • These filters help isolate specific events of interest from the vast stream of events on the blockchain, allowing Subgraphs to operate more efficiently by focusing only on relevant data.

              • This is useful for creating personal Subgraphs that track specific addresses and their interactions with various smart contracts on the blockchain.

              Como Filtros de Tópicos Funcionam

              When a smart contract emits an event, any arguments that are marked as indexed can be used as filters in a Subgraph’s manifest. This allows the Subgraph to listen selectively for events that match these indexed arguments.

              • O primeiro argumento indexado do evento corresponde ao topic1, o segundo ao topic2, e por aí vai até o topic3, já que a Máquina Virtual de Ethereum (EVM) só permite até três argumentos indexados por evento.
              1// SPDX-License-Identifier: MIT2pragma solidity ^0.8.0;34contract Token {5    // Declaração de evento com parâmetros indexados para endereços6    event Transfer(address indexed from, address indexed to, uint256 value);78    // Função para simular a transferência de tokens9    function transfer(address to, uint256 value) public {10        // Emitting the Transfer event with from, to, and value11        emit Transfer(msg.sender, to, value);12    }13}

              Neste exemplo:

              • O evento Transfer é usado para gravar transações de tokens entre endereços.
              • Os parâmetros from e to são indexados, o que permite que ouvidores de eventos filtrem e monitorizem transferências que envolvem endereços específicos.
              • A função transfer é uma representação simples de uma ação de transferência de token, e emite o evento Transfer sempre que é chamada.

              Configuração em Subgraphs

              Topic filters are defined directly within the event handler configuration in the Subgraph manifest. Here is how they are configured:

              1eventHandlers:2  - event: SomeEvent(indexed uint256, indexed address, indexed uint256)3    handler: handleSomeEvent4    topic1: ['0xValue1', '0xValue2']5    topic2: ['0xAddress1', '0xAddress2']6    topic3: ['0xValue3']

              Neste cenário:

              • topic1 corresponde ao primeiro argumento indexado do evento, topic2 ao segundo, e topic3 ao terceiro.
              • Cada tópico pode ter um ou mais valores, e um evento só é processado se corresponder a um dos valores em cada tópico especificado.

              Lógica de Filtro

              • Dentro de um Tópico Único: A lógica funciona como uma condição OR. O evento será processado se corresponder a qualquer dos valores listados num tópico.
              • Entre Tópicos Diferentes: A lógica funciona como uma condição AND. Um evento deve atender a todas as condições especificadas em vários tópicos para acionar o handler associado.

              Exemplo 1: Como Rastrear Transferências Diretas do Endereço A ao Endereço B

              1eventHandlers:2  - event: Transfer(indexed address,indexed address,uint256)3    handler: handleDirectedTransfer4    topic1: ['0xAddressA'] # Sender Address5    topic2: ['0xAddressB'] # Receiver Address

              Nesta configuração:

              • topic1 é configurado para filtrar eventos Transfer onde 0xAddressA é o remetente.
              • topic2 é configurado para filtrar eventos Transfer onde 0xAddressB é o destinatário.
              • The Subgraph will only index transactions that occur directly from 0xAddressA to 0xAddressB.

              Exemplo 2: Como Rastrear Transações em Qualquer Direção Entre Dois ou Mais Endereços

              1eventHandlers:2  - event: Transfer(indexed address,indexed address,uint256)3    handler: handleTransferToOrFrom4    topic1: ['0xAddressA', '0xAddressB', '0xAddressC'] # Endereço do Remetente5    topic2: ['0xAddressB', '0xAddressC'] # Endereço do Destinatário

              Nesta configuração:

              • O topic1 é configurado para filtrar eventos Transfer onde 0xAddressA, 0xAddressB, 0xAddressC é o remetente.
              • topic2 é configurado para filtrar eventos Transfer onde 0xAddressB e 0xAddressC é o destinatário.
              • The Subgraph will index transactions that occur in either direction between multiple addresses allowing for comprehensive monitoring of interactions involving all addresses.

              eth_call declarada

              Nota: Esta é uma função experimental que atualmente não está disponível numa versão estável do Graph Node, e só pode ser usada no Subgraph Studio ou no seu node auto-hospedado.

              Declarative eth_calls are a valuable Subgraph feature that allows eth_calls to be executed ahead of time, enabling graph-node to execute them in parallel.

              Esta ferramenta faz o seguinte:

              • Significantly improves the performance of fetching data from the Ethereum blockchain by reducing the total time for multiple calls and optimizing the Subgraph’s overall efficiency.
              • Permite retiros de dados mais rápidos, o que resulta em respostas de query aceleradas e uma experiência de utilizador melhorada.
              • Reduz tempos de espera para aplicativos que precisam agregar dados de várias chamadas no Ethereum, o que aumenta a eficácia do processo de retiro de dados.

              Conceitos Importantes

              • eth_calls declarativas: Chamadas no Ethereum definidas para serem executadas em paralelo, e não em sequência.
              • Execução Paralela: Ao invés de esperar o término de uma chamada para começar a próxima, várias chamadas podem ser iniciadas simultaneamente.
              • Eficácia de Tempo: O total de tempo levado para todas as chamadas muda da soma dos tempos de chamadas individuais (sequencial) para o tempo levado para a chamada mais longa (paralelo).

              Cenário sem eth_calls Declarativas

              Imagine you have a Subgraph that needs to make three Ethereum calls to fetch data about a user’s transactions, balance, and token holdings.

              Tradicionalmente, estas chamadas podem ser realizadas em sequência:

              1. Chamada 1 (Transações): Leva 3 segundos
              2. Chamada 2 (Saldo): Leva 2 segundos
              3. Chamada 3 (Posses de Token): Leva 4 segundos

              Total de tempo: 3 + 2 + 4 = 9 segundos

              Cenário com eth_calls Declarativas

              Com esta ferramenta, é possível declarar que estas chamadas sejam executadas em paralelo:

              1. Chamada 1 (Transações): Leva 3 segundos
              2. Chamada 2 (Saldo): Leva 2 segundos
              3. Chamada 3 (Posses de Token): Leva 4 segundos

              Como estas chamadas são executadas em paralelo, o total de tempo é igual ao tempo gasto pela chamada mais longa.

              Total de tempo = max (3, 2, 4) = 4 segundos

              Como Funciona

              1. Declarative Definition: In the Subgraph manifest, you declare the Ethereum calls in a way that indicates they can be executed in parallel.
              2. Motor de Execução Paralela: O motor de execução do Graph Node reconhece estas declarações e executa as chamadas simultaneamente.
              3. Result Aggregation: Once all calls are complete, the results are aggregated and used by the Subgraph for further processing.

              Exemplo de Configuração no Manifest do Subgraph

              eth_calls declaradas podem acessar o event.address do evento subjacente, assim como todos os event.params.

              subgraph.yaml using event.address:

              1eventHandlers:2event: Swap(indexed address,indexed address,int256,int256,uint160,uint128,int24)3handler: handleSwap4calls:5  global0X128: Pool[event.address].feeGrowthGlobal0X128()6  global1X128: Pool[event.address].feeGrowthGlobal1X128()

              Detalhes para o exemplo acima:

              • global0X128 é a eth_call declarada.
              • O texto antes dos dois pontos (global0X128) é o rótulo para esta eth_call que é usado ao registar erros.
              • O texto (Pool[event.address].feeGrowthGlobal0X128()) é a eth_call a ser executada, que está na forma do Contract[address].function(arguments)
              • O address e o arguments podem ser substituídos por variáveis a serem disponibilizadas quando o handler for executado.

              subgraph.yaml using event.params

              1calls:2  - ERC20DecimalsToken0: ERC20[event.params.token0].decimals()

              Como Enxertar em Subgraphs Existentes

              Observação: não é recomendado usar enxertos quando começar a atualização para a The Graph Network. Aprenda mais aqui.

              When a Subgraph is first deployed, it starts indexing events at the genesis block of the corresponding chain (or at the startBlock defined with each data source) In some circumstances; it is beneficial to reuse the data from an existing Subgraph and start indexing at a much later block. This mode of indexing is called Grafting. Grafting is, for example, useful during development to get past simple errors in the mappings quickly or to temporarily get an existing Subgraph working again after it has failed.

              A Subgraph is grafted onto a base Subgraph when the Subgraph manifest in subgraph.yaml contains a graft block at the top-level:

              1description: ...2graft:3  base: Qm... # Subgraph ID of base Subgraph4  block: 7345624 # Block number

              When a Subgraph whose manifest contains a graft block is deployed, Graph Node will copy the data of the base Subgraph up to and including the given block and then continue indexing the new Subgraph from that block on. The base Subgraph must exist on the target Graph Node instance and must have indexed up to at least the given block. Because of this restriction, grafting should only be used during development or during an emergency to speed up producing an equivalent non-grafted Subgraph.

              Because grafting copies rather than indexes base data, it is much quicker to get the Subgraph to the desired block than indexing from scratch, though the initial data copy can still take several hours for very large Subgraphs. While the grafted Subgraph is being initialized, the Graph Node will log information about the entity types that have already been copied.

              The grafted Subgraph can use a GraphQL schema that is not identical to the one of the base Subgraph, but merely compatible with it. It has to be a valid Subgraph schema in its own right, but may deviate from the base Subgraph’s schema in the following ways:

              • Ele adiciona ou remove tipos de entidade
              • Ele retira atributos de tipos de entidade
              • Ele adiciona atributos anuláveis a tipos de entidade
              • Ele transforma atributos não anuláveis em atributos anuláveis
              • Ele adiciona valores a enums
              • Ele adiciona ou remove interfaces
              • Ele muda os tipos de entidades para qual implementar uma interface

              Feature Management: grafting must be declared under features in the Subgraph manifest.

              ⁠Editar no GitHub⁠

              Escrita de Mapeamentos de AssemblyScriptIntrodução
              Nesta página
              • Visão geral
              • Séries de Tempo e Agregações
              • Exemplo de Schema
              • Como Definir Séries Temporais e Agregações
              • Erros não-fatais
              • Fontes de Dados de Arquivos em IPFS/Arweave
              • Visão geral
              • Guia de atualização
              • Filtros de Argumentos Indexados / Filtros de Tópicos
              • Como Filtros de Tópicos Funcionam
              • eth_call declarada
              • Conceitos Importantes
              • Como Enxertar em Subgraphs Existentes
              The GraphStatusRede de TestesAtivos de MarcaFórumSegurançaPolítica de PrivacidadeAcordo de Serviço