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 > API AssemblyScript

              21 minutos

              API AssemblyScript

              Note: If you created a Subgraph prior to graph-cli/graph-ts version 0.22.0, then you’re using an older version of AssemblyScript. It is recommended to review the Migration Guide.

              Learn what built-in APIs can be used when writing Subgraph mappings. There are two kinds of APIs available out of the box:

              • A biblioteca do Graph TypeScript⁠ (graph-ts)
              • Code generated from Subgraph files by graph codegen

              Você também pode adicionar outras bibliotecas como dependências, contanto que sejam compatíveis com AssemblyScript⁠.

              Já que os mapeamentos de linguagem são escritos em AssemblyScript, vale a pena consultar os recursos padrão de linguagem e biblioteca da wiki do AssemblyScript⁠.

              Referência da API

              A biblioteca @graphprotocol/graph-ts fornece as seguintes APIs:

              • Uma API ethereum para trabalhar com contratos inteligentes, eventos, blocos, transações, e valores no Ethereum.
              • Uma API store para carregar e guardar entidades dentro e fora do armazenamento do Graph Node.
              • Uma API log para gravar mensagens ao resultado do Graph Node e ao Graph Explorer.
              • Uma API ipfs para carregar arquivos do IPFS.
              • Uma API json para analisar dados em JSON.
              • Uma API crypto para usar funções criptográficas.
              • Primitivos de baixo nível para traduzir entre sistemas de tipos diferentes, como Ethereum, JSON, GraphQL e AssemblyScript.

              Versões

              The apiVersion in the Subgraph manifest specifies the mapping API version which is run by Graph Node for a given Subgraph.

              VersãoNotas de atualização
              0.0.9Adiciona novas funções de host eth_get_balance & hasCode
              0.0.8Adiciona validação para existência de campos no schema ao salvar uma entidade.
              0.0.7Classes TransactionReceipt e Log adicionadas aos tipos do EthereumCampo
              Campo receipt adicionado ao objeto Ethereum Event
              0.0.6Campo nonce adicionado ao objeto Ethereum TransactionCampo
              baseFeePerGas adicionado ao objeto Ethereum Block
              0.0.5AssemblyScript upgraded to version 0.19.10 (this includes breaking changes, please see the Migration Guide)
              ethereum.transaction.gasUsed renamed to ethereum.transaction.gasLimit
              0.0.4Campo functionSignature adicionado ao objeto Ethereum SmartContractCall
              0.0.3Campo from adicionado ao objeto de chamada no Ethereum
              Callethereum.call.address renomeado para ethereum.call.to
              0.0.2Campo input adicionado ao objeto Ethereum Transaction

              Tipos Embutidos

              A documentação sobre os tipos de base embutidos no AssemblyScript está na wiki do AssemblyScript⁠.

              Os seguintes tipos adicionais são fornecidos pelo @graphprotocol/graph-ts.

              ByteArray

              1import { ByteArray } from '@graphprotocol/graph-ts'

              ByteArray representa um arranjo de u8.

              Construção

              • fromI32(x: i32): ByteArray - Decompõe x em bytes.
              • fromHexString(hex: string): ByteArray — O comprimento da entrada deve ser par. É facultativo prefixar com 0x.

              Conversões de tipo

              • toHexString(): string — Converte numa cadeia de caracteres hex prefixada com 0x`.
              • toString(): string — Interpreta os bytes como uma cadeia de caracteres UTF-8.
              • toBase58(): string — Codifica os bytes como uma cadeia base58.
              • toU32(): u32 — Interpreta os bytes como um u32 little-endian. Não funciona em caso de overflow.
              • toI32(): i32 - Interpreta o arranjo de byte como um i32 little-endian. Não funciona em caso de overflow.

              Operadores

              • equals(y: ByteArray): bool — pode ser escrito como x == y`.
              • concat(other: ByteArray) : ByteArray — retorna um novo ByteArray que consiste de this diretamente seguido de other
              • concatI32(other: i32) : ByteArray — retorna um novo ByteArray que consiste de this diretamente seguido pela representação em byte de other

              BigDecimal

              1import { BigDecimal } from '@graphprotocol/graph-ts'

              O BigDecimal é usado para representar decimais de precisão arbitrária.

              Nota: Internalmente⁠, o BigDecimal é armazenado no formato de ponto flutuante IEEE-754 decimal128⁠, que apoia 34 dígitos decimais de significando. Portanto, o BigDecimal não serve para representar tipos de ponto fixo que possam exceder 34 dígitos, como um (ufixed256x18)[https://docs.soliditylang.org/en/latest/types.html#fixed-point-numbers⁠] em Solidity ou equivalente.

              Construção

              • constructor(bigInt: BigInt) – cria um BigDecimal a partir de um BigInt.
              • static fromString(s: string): BigDecimal — faz uma análise sintática a partir de uma cadeia decimal.

              Conversões de tipo

              • toString(): string — imprime para uma cadeia decimal.

              Matemática

              • plus(y: BigDecimal): BigDecimal — pode ser escrito como x + y.
              • minus(y: BigDecimal): BigDecimal — pode ser escrito como x - y.
              • times(y: BigDecimal): BigDecimal — pode ser x * y.
              • div(y: BigDecimal): BigDecimal — pode ser escrito como x / y.
              • equals(y: BigDecimal): bool — pode ser x == y.
              • notEqual(y: BigDecimal): bool — pode ser x != y.
              • lt(y: BigDecimal): bool — pode ser x < y.
              • le(y: BigDecimal): bool – pode ser x <= y.
              • gt(y: BigDecimal): bool – pode ser x > y.
              • ge(y: BigDecimal): bool – pode ser x >= y.
              • neg(): BigDecimal - pode ser -x.

              BigInt

              1import { BigInt } from '@graphprotocol/graph-ts'

              O BigInt é usado para representar números inteiros grandes, inclusive valores em Ethereum de uint32 até uint256, e int64 até int256. Tudo abaixo de uint32, como o int32, uint24 ou int8 é representado como i32.

              A classe BigInt tem a seguinte API:

              Construção

              • BigInt.fromI32(x: i32): BigInt – cria um BigInt de um i32.

              • BigInt.fromString(s: string): BigInt– Analisa um BigInt de uma cadeia.

              • BigInt.fromUnsignedBytes(x: Bytes): BigInt — Interpreta bytes como um inteiro little-endian, não assinado. Se a sua entrada for big-endian, chame pelo .reverse() primeiro.

              • BigInt.fromSignedBytes(x: Bytes): BigInt — Interpreta bytes como um inteiro little-endian, assinado. Se a sua entrada for big-endian, chame pelo .reverse() primeiro.

                Conversões de tipo

              • x.toHex(): string — transforma o BigInt numa cadeia de caracteres hexadecimais.

              • x.toString(): string — transforma o BigInt numa cadeia de números decimais.

              • x.toI32(): i32 — retorna o BigInt como um i32; falha se o valor não couber no i32. É bom verificar o x.isI32() primeiro.

              • x.toBigDecimal(): BigDecimal — converte num decimal sem fracionário.

              Matemática

              • x.plus(y: BigInt): BigInt – pode ser escrito como x + y.
              • x.minus(y: BigInt): BigInt – pode ser escrito como x - y.
              • x.times(y: BigInt): BigInt – pode ser escrito como x * y.
              • x.div(y: BigInt): BigInt – pode ser escrito como x / y.
              • x.mod(y: BigInt): BigInt – pode ser escrito como x % y.
              • x.equals(y: BigInt): bool – pode ser escrito como x == y.
              • x.notEqual(y: BigInt): bool – pode ser escrito como x != y.
              • x.lt(y: BigInt): bool – pode ser escrito como x < y.
              • x.le(y: BigInt): bool – pode ser escrito como x <= y.
              • x.gt(y: BigInt): bool – pode ser escrito como x > y.
              • x.ge(y: BigInt): bool – pode ser escrito como x >= y.
              • x.neg(): BigInt – pode ser escrito como -x.
              • x.divDecimal(y: BigDecimal): BigDecimal – divide por um decimal e dá um resultado decimal.
              • x.isZero(): bool — Conveniência para conferir se o número é zero.
              • x.isl32(): bool — Confere se o número cabe em um i32.
              • x.abs(): BigInt — Valor absoluto.
              • x.pow(exp: u8): BigInt — Exponenciação.
              • bitOr(x: BigInt, y: BigInt): BigInt — pode ser escrito como x | y.
              • bitAnd(x: BigInt, y: BigInt): BigInt — pode ser escrito como x & y.
              • leftShift(x: BigInt, bits: u8): BigInt – pode ser escrito como x << y.
              • rightShift(x: BigInt, bits: u8): BigInt – pode ser escrito como x >> y.

              TypedMap

              1import { TypedMap } from '@graphprotocol/graph-ts'

              O TypedMap pode servir para armazenar pares de chave e valor (key e value ). Confira este exemplo⁠.

              A classe TypedMap tem a seguinte API:

              • new TypedMap<K, V>() — cria um mapa vazio com chaves do tipo K e valores do tipo V
              • map.set(key: K, value: V): void — coloca o valor do key como value
              • map.getEntry(key: K): TypedMapEntry<K, V> | null — retorna o par de valor-chave para um key ou null se o key não existir no mapa
              • map.get(key: K): V | null — retorna o valor para um key ou null se o key não existir no mapa
              • map.isSet(key: K): bool — retorna true se o key existir no mapa e false se não existir

              Bytes

              1import { Bytes } from '@graphprotocol/graph-ts'

              O Bytes serve para representar arranjos de comprimento arbitrário de bytes. Isto inclui valores do Ethereum do tipo bytes, bytes32, etc.

              A classe Bytes estende o Uint8Array⁠ do AssemblyScript. Isto apoia toda a funcionalidade Uint8Array, além dos novos métodos a seguir:

              Construção

              • fromHexString(hex: string) : Bytes — Converte a cadeia hex, que deve consistir de um número par de dígitos hexadecimais para um ByteArray. Opcionalmente, a cadeia hex pode começar com 0x
              • fromI32(i: i32) : Bytes - Converte o i em um arranjo de bytes

              Conversões de tipo

              • b.toHex() — retorna uma cadeia hexadecimal que representa os bytes no arranjo
              • b.toString() — converte os bytes no arranjo para uma cadeia de caracteres em unicode
              • b.toBase58() — transforma um valor de Ethereum Bytes numa codificação base58 (usado para hashes IPFS)

              Operadores

              • b.concat(other: Bytes) : Bytes - - retorna um novo Bytes que consiste de this diretamente seguido por other
              • b.concatI32(other: i32) : ByteArray — retorna um novo Bytes que consiste de this diretamente seguido pela representação em byte de other

              Address

              1import { Address } from '@graphprotocol/graph-ts'

              Address estende o Bytes para representar valores de address do Ethereum.

              Ele adiciona o seguinte método em cima da API Bytes:

              • Address.fromString(s: string): Address — cria um Address a partir de uma cadeia hexadecimal
              • Address.fromBytes(b: Bytes): Address — cria um Address a partir do b, que deve ter o comprimento exato de 20 bytes. Preencher um valor com menos ou mais bytes causará um erro

              Armazenamento da API

              1import { store } from '@graphprotocol/graph-ts'

              A API store permite carregar, salvar e remover entidades do/para o armazenamento do Graph Node.

              Entities written to the store map one-to-one to the @entity types defined in the Subgraph’s GraphQL schema. To make working with these entities convenient, the graph codegen command provided by the Graph CLI⁠ generates entity classes, which are subclasses of the built-in Entity type, with property getters and setters for the fields in the schema as well as methods to load and save these entities.

              Como criar entidades

              Este é um padrão comum para a criação de entidades de eventos do Ethereum.

              1// Importar a classe de evento de transferência gerada da ABI ERC202import { Transfer as TransferEvent } from '../generated/ERC20/ERC20'34// Importar o tipo de entidade de transferência gerado do schema do GraphQL5import { Transfer } from '../generated/schema'67// Handler de evento de transferência8export function handleTransfer(event: TransferEvent): void {9  // Criar uma entidade de Transferência, usando o hash da transação como a ID da entidade10  let id = event.transaction.hash11  let transfer = new Transfer(id)1213  // Determinar propriedades na entidade, usando os parâmetros do evento14  transfer.from = event.params.from15  transfer.to = event.params.to16  transfer.amount = event.params.amount1718  // Salvar a entidade no armazenamento19  transfer.save()20}

              Quando um evento Transfer é encontrado durante o processamento da chain, ele é passado para o handler de evento handleTransfer com o tipo Transfer gerado (apelidado de TransferEvent aqui, para evitar confusões com o tipo de entidade). Este tipo permite o acesso a dados como a transação parente do evento e seus parâmetros.

              Cada entidade deve ter um identificador exclusivo para evitar colisões com outras entidades. É bastante comum que parâmetros de evento incluam um identificador exclusivo que pode ser usado.

              Nota: Usar o hash de transação como ID supõe que nenhum outro evento na mesma transação cria entidades com este hash como o ID.

              Como carregar entidades a partir do armazenamento

              Se uma entidade já existe, ela pode ser carregada do armazenamento com os seguintes comandos:

              1let id = event.transaction.hash // ou como a ID for construída2let transfer = Transfer.load(id)3if (transfer == null) {4  transfer = new Transfer(id)5}67// Use a entidade Transfer como antes

              Como a entidade pode ainda não existir no armazenamento, o método load retorna um valor de tipo Transfer | null. Portanto, é bom prestar atenção ao caso null antes de usar o valor.

              Nota: Só é necessário carregar entidades se as mudanças feitas no mapeamento dependem dos dados anteriores de uma entidade. Veja a próxima seção para ver as duas maneiras de atualizar entidades existentes.

              Como consultar entidades criadas dentro de um bloco

              Desde o graph-node v0.31.0, o @graphprotocol/graph-ts v0.30.0 e o @graphprotocol/graph-cli v0.49.0, o método loadInBlock está disponível em todos os tipos de entidade.

              A API do armazenamento facilita a recuperação de entidades que já foram criadas ou atualizadas no bloco atual. Uma situação típica para isso é que um manipulador cria uma transação a partir de algum evento em cadeia, e um handler posterior quer acessar esta transação — se ela existir.

              • In the case where the transaction does not exist, the Subgraph will have to go to the database simply to find out that the entity does not exist. If the Subgraph author already knows that the entity must have been created in the same block, using loadInBlock avoids this database roundtrip.
              • For some Subgraphs, these missed lookups can contribute significantly to the indexing time.
              1let id = event.transaction.hash // ou como a ID for construída2let transfer = Transfer.load(id)3if (transfer == null) {4  transfer = new Transfer(id)5}67// Use a entidade Transfer como antes

              Nota: se não houver nenhuma entidade criada no bloco dado, o loadInBlock retornará um null mesmo se houver uma entidade com o ID dado no armazenamento.

              Como buscar entidades derivadas

              A partir da versão 0.31.0 do graph-node, @graphprotocol/graph-ts v0.31.0 e a versão 0.51.0 do @graphprotocol/graph-cli, está disponível o método loadRelated.

              Isto permite o carregamento de campos de entidade derivada a partir de um event handler. Por exemplo, considerando o schema a seguir:

              1type Token @entity {2  id: ID!3  holder: Holder!4  color: String5}67type Holder @entity {8  id: ID!9  tokens: [Token!]! @derivedFrom(field: "holder")10}

              O código a seguir carregará a entidade Token de que foi derivada a entidade Holder:

              1let holder = Holder.load('test-id')2// Carrega as entidades de Token associadas com um titular dado3let tokens = holder.tokens.load()

              Como atualizar entidades existentes

              Há duas maneiras de atualizar uma entidade existente:

              1. Carregar a entidade com, por ex., Transfer.load(id), determinar as propriedades da entidade, e então usar o .save() para colocá-la no armazenamento.
              2. Simplesmente criar a entidade com, por ex., new Transfer(id), determinar as propriedades da entidade, e depois colocá-la no armazenamento com .save(). Se a entidade já existir, as mudanças serão integradas a ela.

              Geralmente é simples mudar propriedades, graças aos setters de propriedade gerados:

              1let transfer = new Transfer(id)2transfer.from = ...3transfer.to = ...4transfer.amount = ...

              Também é possível cancelar propriedades com uma das seguintes instruções:

              1transfer.from.unset()2transfer.from = null

              Isto só funciona com propriedades opcionais; por ex., propriedades declaradas sem um ! no GraphQL. Dois exemplos seriam owner: Bytes ou amount: BigInt.

              Atualizar propriedades de arranjos é um processo um pouco mais envolvido, pois pegar um arranjo de uma entidade cria uma cópia deste mesmo arranjo. Isto significa que as propriedades de arranjos devem ser impostas explicitamente após mudar um arranjo. O seguinte assume que o entity tem um campo numbers: [BigInt!]!.

              1// Isto não funcionará2entity.numbers.push(BigInt.fromI32(1))3entity.save()45// Isto funcionará6let numbers = entity.numbers7numbers.push(BigInt.fromI32(1))8entity.numbers = numbers9entity.save()

              Como remover entidades do armazenamento

              Atualmente, não há como remover uma entidade através dos tipos gerados. Em vez disto, o processo requer a passagem do ID da entidade e do nome do tipo da mesma ao store.remove:

              1import { store } from '@graphprotocol/graph-ts'2...3let id = event.transaction.hash4store.remove('Transfer', id)

              API do Ethereum

              A API do Ethereum fornece acesso a contratos inteligentes, variáveis de estado público, funções de contrato, eventos, transações, blocos e a codificação/decodificação de dados no Ethereum.

              Apoio para Tipos no Ethereum

              As with entities, graph codegen generates classes for all smart contracts and events used in a Subgraph. For this, the contract ABIs need to be part of the data source in the Subgraph manifest. Typically, the ABI files are stored in an abis/ folder.

              With the generated classes, conversions between Ethereum types and the built-in types take place behind the scenes so that Subgraph authors do not have to worry about them.

              The following example illustrates this. Given a Subgraph schema like

              1type Transfer @entity {2  id: Bytes!3  from: Bytes!4  to: Bytes!5  amount: BigInt!6}

              e uma assinatura de evento Transfer(address,address,uint256) na Ethereum, os valores from, to e amount do tipo address, address and uint256 são convertidos para Address and BigInt, o que permite que sejam passados para as propriedades Bytes! and BigInt! da entidade Transfer:

              1let id = event.transaction.hash2let transfer = new Transfer(id)3transfer.from = event.params.from4transfer.to = event.params.to5transfer.amount = event.params.amount6transfer.save()

              Eventos e Dados de Blocos/Transações

              Eventos de Ethereum passados para handlers de eventos, como o evento Transfer nos exemplos anteriores, não só permitem acessar os parâmetros de evento, mas também sua transação parente e o bloco de qual fazem parte. Os seguintes dados podem ser obtidos de instâncias event (estas classes são parte do módulo ethereum no graph-ts):

              1class Event {2  address: Address3  logIndex: BigInt4  transactionLogIndex: BigInt5  logType: string | null6  block: Block7  transaction: Transaction8  parameters: Array<EventParam>9  receipt: TransactionReceipt | null10}1112class Block {13  hash: Bytes14  parentHash: Bytes15  unclesHash: Bytes16  author: Address17  stateRoot: Bytes18  transactionsRoot: Bytes19  receiptsRoot: Bytes20  number: BigInt21  gasUsed: BigInt22  gasLimit: BigInt23  timestamp: BigInt24  difficulty: BigInt25  totalDifficulty: BigInt26  size: BigInt | null27  baseFeePerGas: BigInt | null28}2930class Transaction {31  hash: Bytes32  index: BigInt33  from: Address34  to: Address | null35  value: BigInt36  gasLimit: BigInt37  gasPrice: BigInt38  input: Bytes39  nonce: BigInt40}4142class TransactionReceipt {43  transactionHash: Bytes44  transactionIndex: BigInt45  blockHash: Bytes46  blockNumber: BigInt47  cumulativeGasUsed: BigInt48  gasUsed: BigInt49  contractAddress: Address50  logs: Array<Log>51  status: BigInt52  root: Bytes53  logsBloom: Bytes54}5556class Log {57  address: Address58  topics: Array<Bytes>59  data: Bytes60  blockHash: Bytes61  blockNumber: Bytes62  transactionHash: Bytes63  transactionIndex: BigInt64  logIndex: BigInt65  transactionLogIndex: BigInt66  logType: string67  removed: bool | null68}

              Acesso ao Estado do Contrato Inteligente

              The code generated by graph codegen also includes classes for the smart contracts used in the Subgraph. These can be used to access public state variables and call functions of the contract at the current block.

              É comum acessar o contrato de qual origina um evento. Isto é feito com o seguinte código:

              1// Importar a classe do contrato gerado e a classe do evento de transferência gerado2import { ERC20Contract, Transfer as TransferEvent } from '../generated/ERC20Contract/ERC20Contract'3// Import the generated entity class4import { Transfer } from '../generated/schema'56export function handleTransfer(event: TransferEvent) {7  // Ligar o contrato ao endereço que emitiu o evento8  let contract = ERC20Contract.bind(event.address)910  // Acessar variáveis e funções de estado fazendo chamadas11  let erc20Symbol = contract.symbol()12}

              O Transfer é apelidado de TransferEvent aqui para evitar confusões de nomenclatura com o tipo da entidade

              Enquanto o ERC20Contract no Ethereum tiver uma função pública de apenas-leitura chamada symbol, ele pode ser chamado com o .symbol(). Para variáveis de estado público, um método com o mesmo nome é criado automaticamente.

              Any other contract that is part of the Subgraph can be imported from the generated code and can be bound to a valid address.

              Como Lidar com Chamadas Revertidas

              Se houver reversão dos métodos somente-leitura do seu contrato, cuide disso chamando o método do contrato gerado prefixado com try_.

              • Por exemplo, o contrato da Gravity expõe o método gravatarToOwner. Este código poderia manusear uma reversão nesse método:
              1let gravity = Gravity.bind(event.address)2let callResult = gravity.try_gravatarToOwner(gravatar)3if (callResult.reverted) {4  log.info('getGravatar reverted', [])5} else {6  let owner = callResult.value7}

              Observe que um Graph Node conectado a um cliente Geth ou Infura pode não detetar todas as reversões; se depender disto, recomendamos usar um Graph Node conectado a um cliente Parity.

              ABI de Codificação/Decodificação

              Dados podem ser codificados e decodificados conforme o formato de codificação da ABI do Ethereum, através das funções encode e decode no módulo ethereum.

              1import { Address, BigInt, ethereum } from '@graphprotocol/graph-ts'23let tupleArray: Array<ethereum.Value> = [4  ethereum.Value.fromAddress(Address.fromString('0x0000000000000000000000000000000000000420')),5  ethereum.Value.fromUnsignedBigInt(BigInt.fromI32(62)),6]78let tuple = tupleArray as ethereum.Tuple910let encoded = ethereum.encode(ethereum.Value.fromTuple(tuple))!1112let decoded = ethereum.decode('(address,uint256)', encoded)

              Para mais informações:

              • ABI Spec⁠
              • Codificação e decodificação da biblioteca/CLI do Rust⁠
              • Um exemplo mais complexo⁠.

              Saldo de um Endereço

              O saldo de token nativo de um endereço pode ser resgatado com o módulo ethereum. Este recurso está disponível a partir do apiVersion: 0.0.9, definido no subgraph.yaml. O getBalance() resgata o saldo do endereço especificado como o do fim do bloco em que o evento é adicionado.

              1import { ethereum } from '@graphprotocol/graph-ts'23let address = Address.fromString('0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045')4let balance = ethereum.getBalance(address) // retorna o saldo em BigInt

              Como Conferir Se Um Endereço é Um Contrato Ou Um EOA

              Para conferir se um endereço é um de contrato inteligente ou um endereço titulado externamente (sigla em português para EOA), use a função hasCode() do módulo ethereum que retornará boolean. Este recurso está disponível a partir do apiVersion: 0.0.9, definido no subgraph.yaml.

              1import { ethereum } from '@graphprotocol/graph-ts'23let contractAddr = Address.fromString('0x2E645469f354BB4F5c8a05B3b30A929361cf77eC')4let isContract = ethereum.hasCode(contractAddr).inner // returns true56let eoa = Address.fromString('0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045')7let isContract = ethereum.hasCode(eoa).inner // retorna false

              API de Logging

              1import { log } from '@graphprotocol/graph-ts'

              The log API allows Subgraphs to log information to the Graph Node standard output as well as Graph Explorer. Messages can be logged using different log levels. A basic format string syntax is provided to compose log messages from argument.

              A API log inclui as seguintes funções:

              • log.debug(fmt: string, args: Array<string>): void — loga uma mensagem de debug.
              • log.info(fmt: string, args: Array<string>): void - loga uma mensagem de debug.
              • log.warning(fmt: string, args: Array<string>): void - loga um aviso.
              • log.error(fmt: string, args: Array<string>): void - loga uma mensagem de erro.
              • log.critical(fmt: string, args: Array<string>): void – logs a critical message and terminates the Subgraph.

              A API log toma um string de formato e um arranjo de valores de string. Ele então substitui os temporários com os valores de strings do arranjo. O primeiro {} temporário é substituído pelo primeiro valor no arranjo, o segundo {} temporário é substituído pelo segundo valor, e assim por diante.

              1log.info('Message to be displayed: {}, {}, {}', [value.toString(), anotherValue.toString(), 'already a string'])

              Como logar um ou mais valores

              Como logar um único valor

              No exemplo abaixo, o valor de string “A” é passado a um arranjo para tornar-se ['A'] antes de ser registado no log:

              1let myValue = 'A'23export function handleSomeEvent(event: SomeEvent): void {4  // Mostra : "My value is: A"5  log.info('My value is: {}', [myValue])6}
              Como logar uma única entrada de um arranjo existente

              No exemplo abaixo, só é logado o primeiro valor do arranjo do argumento, apesar de haver três valores no arranjo.

              1let myArray = ['A', 'B', 'C']23export function handleSomeEvent(event: SomeEvent): void {4  // Displays : "My value is: A"  (Apesar de três valores serem passados ao `log.info`)5  log.info('My value is: {}', myArray)6}

              Como logar várias entradas de um arranjo existente

              Cada entrada no arranjo dos argumentos exige o seu próprio {} no string de mensagens de log. O exemplo abaixo contém três {} temporários na mensagem de log. Por causa disto, são registados todos os três valores no myArray.

              1let myArray = ['A', 'B', 'C']23export function handleSomeEvent(event: SomeEvent): void {4  // Mostra : "My first value is: A, second value is: B, third value is: C"5  log.info('My first value is: {}, second value is: {}, third value is: {}', myArray)6}
              Como logar uma entrada específica de um arranjo existente

              Para mostrar um valor específico no arranjo, forneça o valor indexado.

              1export function handleSomeEvent(event: SomeEvent): void {2  // Mostra : "My third value is C"3  log.info('My third value is: {}', [myArray[2]])4}
              Como logar informações de eventos

              O exemplo abaixo loga o número do bloco, hash do bloco e o hash da transação de um evento:

              1import { log } from '@graphprotocol/graph-ts'23export function handleSomeEvent(event: SomeEvent): void {4  log.debug('Block number: {}, block hash: {}, transaction hash: {}', [5    event.block.number.toString(), // "47596000"6    event.block.hash.toHexString(), // "0x..."7    event.transaction.hash.toHexString(), // "0x..."8  ])9}

              API do IPFS

              1import { ipfs } from '@graphprotocol/graph-ts'

              Contratos inteligentes, ocasionalmente, ancoram arquivos IPFS on-chain. Assim, os mapeamentos obtém os hashes IPFS do contrato e lêem os arquivos correspondentes do IPFS. Os dados dos arquivos serão retornados como Bytes, o que costuma exigir mais processamento; por ex., com a API json documentada mais abaixo nesta página.

              Considerando um hash ou local IPFS, um arquivo do IPFS é lido da seguinte maneira:

              1// Coloque isto dentro de um handler de evento no mapeamento2let hash = 'QmTkzDwWqPbnAh5YiV5VwcTLnGdwSNsNTn2aDxdXBFca7D'3let data = ipfs.cat(hash)45// Locais como `QmTkzDwWqPbnAh5YiV5VwcTLnGdwSNsNTn2aDxdXBFca7D/Makefile`6// que incluem arquivos em diretorias também são apoiados7let path = 'QmTkzDwWqPbnAh5YiV5VwcTLnGdwSNsNTn2aDxdXBFca7D/Makefile'8let data = ipfs.cat(path)

              Nota: O ipfs.cat não é determinístico no momento. Se o arquivo não puder ser retirado sobre a rede IPFS antes do tempo do pedido acabar, ele retornará um null. Com isto, sempre vale a pena procurar o null no resultado.

              Também é possível processar arquivos maiores em streaming com o ipfs.map. A função espera o hash ou local de um arquivo IPFS, o nome de um callback, e flags para modificar o seu comportamento:

              1import { JSONValue, Value } from '@graphprotocol/graph-ts'23export function processItem(value: JSONValue, userData: Value): void {4  // Ver a documentação do JSONValue para detalhes sobre5  // como lidar com valores JSON6  let obj = value.toObject()7  let id = obj.get('id')8  let title = obj.get('title')910  if (!id || !title) {11    return12  }1314  // Callbacks também podem criar entidades15  let newItem = new Item(id)16  newItem.title = title.toString()17  newitem.parent = userData.toString() // Set parent to "parentId"18  newitem.save()19}2021// Coloque isto dentro de um handler de evento no mapeamento22ipfs.map('Qm...', 'processItem', Value.fromString('parentId'), ['json'])2324// Como alternativa, use `ipfs.mapJSON`25ipfs.mapJSON('Qm...', 'processItem', Value.fromString('parentId'))

              O único flag atualmente apoiado é o json, que deve ser passado ao ipfs.map. Com o flag json, o arquivo IPFS deve consistir de uma série de valores JSON, com um valor por linha. Chamar ipfs.map, irá ler cada linha no arquivo, desserializá-lo em um JSONValue, e chamar o callback para cada linha. O callback pode então armazenar dados do JSONValue com operações de entidade. As mudanças na entidade só serão armazenadas quando o handler que chamou o ipfs.map concluir com sucesso; enquanto isso, elas ficam na memória, e o tamanho do arquivo que o ipfs.map pode processar é então limitado.

              On success, ipfs.map returns void. If any invocation of the callback causes an error, the handler that invoked ipfs.map is aborted, and the Subgraph is marked as failed.

              API de Criptografia

              1import { crypto } from '@graphprotocol/graph-ts'

              A API crypto disponibiliza funções criptográficas para uso em mapeamentos. No momento, apenas um está disponível:

              • crypto.keccak256(input: ByteArray): ByteArray

              API JSON

              1import { json, JSONValueKind } from '@graphprotocol/graph-ts'

              Dados em JSON podem ser analisados com a API json:

              • json.fromBytes(data: Bytes): JSONValue — analisa dados JSON de um arranjo Bytes interpretado como uma sequência válida de UTF-8
              • json.try_fromBytes(data: Bytes): Result<JSONValue, boolean>— versão segura do json.fromBytes, retorna um erro se houver falha no parsing
              • json.fromString(data: string): JSONValue — faz parsing de dados JSON de um String em UTF-8 válido`
              • json.try_fromString(data: string): Result<JSONValue, boolean> – versão segura do json.fromString, retorna um erro se houver falha no parsing

              A classe JSONValue fornece uma maneira de retirar valores de um documento JSON arbitrário. Como valores JSON podem ser booleans, números, arranjos e mais, o JSONValue vem com uma propriedade kind para conferir o tipo de um valor:

              1let value = json.fromBytes(...)2if (value.kind == JSONValueKind.BOOL) {3  ...4}

              Além disso, há um método para conferir se o valor é null:

              • value.isNull(): boolean

              Quando o tipo de um valor é confirmado, ele pode ser convertido num tipo embutido usando um dos seguintes métodos:

              • value.toBool(): boolean
              • value.toI64(): i64
              • value.toF64(): f64
              • value.toBigInt(): BigInt
              • value.toString(): string
              • value.toArray(): Array<JSONValue> - (e depois converter o JSONValue com um dos 5 métodos acima)

              Referência de Conversões de Tipos

              Fonte(s)DestinoFunção de conversão
              AddressBytesnenhum
              AddressStrings.toHexString()
              BigDecimalStrings.toString()
              BigIntBigDecimals.toBigDecimal()
              BigIntString (hexadecimal)s.toHexString() ou s.toHex()
              BigIntString (unicode)s.toString()
              BigInti32s.toI32()
              BooleanBooleannenhum
              Bytes (assinado)BigIntBigInt.fromSignedBytes(s)
              Bytes (não assinado)BigIntBigInt.fromUnsignedBytes(s)
              BytesString (hexadecimal)s.toHexString() ou s.toHex()
              BytesString (unicode)s.toString()
              BytesString (base58)s.toBase58()
              Bytesi32s.toI32()
              Bytesu32s.toU32()
              BytesJSONjson.fromBytes(s)
              int8i32nenhum
              int32i32nenhum
              int32BigIntBigInt.fromI32(s)
              uint24i32nenhum
              int64 - int256BigIntnenhum
              uint32 - uint256BigIntnenhum
              JSONbooleans.toBool()
              JSONi64s.toI64()
              JSONu64s.toU64()
              JSONf64s.toF64()
              JSONBigInts.toBigInt()
              JSONstrings.toString()
              JSONArrays.toArray()
              JSONObjects.toObject()
              StringAddressAddress.fromString(s)
              BytesAddressAddress.fromBytes(s)
              StringBigIntBigInt.fromString(s)
              StringBigDecimalBigDecimal.fromString(s)
              String (hexadecimal)BytesByteArray.fromHexString(s)
              String (UTF-8)BytesByteArray.fromUTF8(s)

              Metadados de Fontes de Dados

              É possível inspecionar o endereço do contrato, a rede, e o contexto das fontes de dados que invocaram o handler através do namespace dataSource:

              • dataSource.address(): Address
              • dataSource.network(): string
              • dataSource.context(): DataSourceContext

              Entidade e DataSourceContext

              A classe base Entity e a subclasse DataSourceContext têm helpers para determinar e retornar campos de forma dinâmica:

              • setString(key: string, value: string): void
              • setI32(key: string, value: i32): void
              • setBigInt(key: string, value: BigInt): void
              • setBytes(key: string, value: Bytes): void
              • setBoolean(key: string, value: bool): void
              • setBigDecimal(key, value: BigDecimal): void
              • getString(key: string): string
              • getI32(key: string): i32
              • getBigInt(key: string): BigInt
              • getBytes(key: string): Bytes
              • getBoolean(key: string): boolean
              • getBigDecimal(key: string): BigDecimal

              DataSourceContext no Manifest

              The context section within dataSources allows you to define key-value pairs that are accessible within your Subgraph mappings. The available types are Bool, String, Int, Int8, BigDecimal, Bytes, List, and BigInt.

              Aqui está um exemplo de YAML que ilustra o uso de vários tipos na seção context:

              1dataSources:2  - kind: ethereum/contract3    name: ContractName4    network: mainnet5    context:6      bool_example:7        type: Bool8        data: true9      string_example:10        type: String11        data: 'hello'12      int_example:13        type: Int14        data: 4215      int8_example:16        type: Int817        data: 12718      big_decimal_example:19        type: BigDecimal20        data: '10.99'21      bytes_example:22        type: Bytes23        data: '0x68656c6c6f'24      list_example:25        type: List26        data:27          - type: Int28            data: 129          - type: Int30            data: 231          - type: Int32            data: 333      big_int_example:34        type: BigInt35        data: '1000000000000000000000000'
              • Bool: Especifica um valor Boolean (true ou false).
              • String: Especifica um valor String.
              • Int: Especifica um integral de 32 bits.
              • Int8: Especifica um integral de 8 bits.
              • BigDecimal: Especifica um número decimal. Deve ser citado.
              • Bytes: Especifica um string hexadecimal.
              • List: Especifica uma lista de itens. Cada item deve especificar o seu tipo e dados.
              • BigInt: Especifica um valor integral largo. É necessário citar este devido ao seu grande tamanho.

              This context is then accessible in your Subgraph mapping files, enabling more dynamic and configurable Subgraphs.

              ⁠Editar no GitHub⁠

              IntroduçãoCommon Issues
              Nesta página
              • Referência da API
              • Versões
              • Tipos Embutidos
              • Armazenamento da API
              • API do Ethereum
              • API de Logging
              • API do IPFS
              • API de Criptografia
              • API JSON
              • Referência de Conversões de Tipos
              • Metadados de Fontes de Dados
              • Entidade e DataSourceContext
              • DataSourceContext no Manifest
              The GraphStatusRede de TestesAtivos de MarcaFórumSegurançaPolítica de PrivacidadeAcordo de Serviço