4 minutos
Escrita de Mapeamentos de AssemblyScript
Visão geral
Os mapeamentos tomam dados de uma fonte particular e os transformam em entidades que são definidas dentro do seu schema. São escritos em um subconjunto do TypeScript chamado AssemblyScript, que pode ser compilado ao (WebAssembly). O AssemblyScript é mais rígido que o TypeScript normal, mas rende uma sintaxe familiar.
Como Escrever Mapeamentos
Para cada handler de evento definido no subgraph.yaml
sob o mapping.eventHandlers
, crie uma função exportada de mesmo nome. Cada handler deve aceitar um único parâmetro chamado event
com um tipo a corresponder ao nome do evento a ser lidado.
In the example Subgraph, src/mapping.ts
contains handlers for the NewGravatar
and UpdatedGravatar
events:
1import { NewGravatar, UpdatedGravatar } from '../generated/Gravity/Gravity'2import { Gravatar } from '../generated/schema'34export function handleNewGravatar(event: NewGravatar): void {5 let gravatar = new Gravatar(event.params.id)6 gravatar.owner = event.params.owner7 gravatar.displayName = event.params.displayName8 gravatar.imageUrl = event.params.imageUrl9 gravatar.save()10}1112export function handleUpdatedGravatar(event: UpdatedGravatar): void {13 let id = event.params.id14 let gravatar = Gravatar.load(id)15 if (gravatar == null) {16 gravatar = new Gravatar(id)17 }18 gravatar.owner = event.params.owner19 gravatar.displayName = event.params.displayName20 gravatar.imageUrl = event.params.imageUrl21 gravatar.save()22}
O primeiro handler toma um evento NewGravatar
e cria uma nova entidade Gravatar
com o new Gravatar(event.params.id.toHex())
, e assim popula os campos da entidade com os parâmetros de evento correspondentes. Esta instância da entidade é representada pelo variável gravatar
, com um valor de id de event.params.id.toHex()
.
O segundo handler tenta carregar o Gravatar
existente do armazenamento do Graph Node. Se ele ainda não existe, ele é criado por demanda. A entidade é então atualizada para corresponder aos novos parâmetros de evento, antes de ser devolvida ao armazenamento com gravatar.save()
.
IDs Recomendadas para Criar Novas Entidades
Recomendamos muito utilizar Bytes
como o tipo para campos id
, e só usar o String
para atributos que realmente contenham texto legível para humanos, como o nome de um token. Abaixo estão alguns valores recomendados de id
para considerar ao criar novas entidades.
-
transfer.id = event.transaction.hash
-
let id = event.transaction.hash.concatI32(event.logIndex.toI32())
-
Para entidades que armazenam dados agregados como, por exemplo, volumes diários de trading, a
id
costuma conter o número do dia. Aqui, usarBytes
como aid
é beneficial. Determinar aid
pareceria com:
1let dayID = event.block.timestamp.toI32() / 864002let id = Bytes.fromI32(dayID)
- Converta endereços constantes em Bytes`.
const id = Bytes.fromHexString('0xdead...beef')
Há uma Biblioteca do Graph Typescript, com utilidades para interagir com o armazenamento do Graph Node e conveniências para lidar com entidades e dados de contratos inteligentes. Ela pode ser importada ao mapping.ts
do @graphprotocol/graph-ts
.
Gestão de entidades com IDs idênticas
Ao criar e salvar uma nova entidade, se já houver uma com a mesma ID, vale sempre usar as propriedades da nova entidade durante o processo de fusão. Isto significa que a entidade existente será atualizada com os valores da entidade nova.
Se um valor nulo for propositadamente determinado para um campo na nova entidade com a mesma ID, a entidade existente será atualizada com o valor nulo.
Se nenhum valor for inserido para um campo na nova entidade com a mesma ID, o campo também resultará em nulo.
Geração de Código
In order to make it easy and type-safe to work with smart contracts, events and entities, the Graph CLI can generate AssemblyScript types from the Subgraph’s GraphQL schema and the contract ABIs included in the data sources.
Isto é feito com
1graph codegen [--output-dir <OUTPUT_DIR>] [<MANIFEST>]
but in most cases, Subgraphs are already preconfigured via package.json
to allow you to simply run one of the following to achieve the same:
1# Yarn2yarn codegen34# NPM5npm run codegen
This will generate an AssemblyScript class for every smart contract in the ABI files mentioned in subgraph.yaml
, allowing you to bind these contracts to specific addresses in the mappings and call read-only contract methods against the block being processed. It will also generate a class for every contract event to provide easy access to event parameters, as well as the block and transaction the event originated from. All of these types are written to <OUTPUT_DIR>/<DATA_SOURCE_NAME>/<ABI_NAME>.ts
. In the example Subgraph, this would be generated/Gravity/Gravity.ts
, allowing mappings to import these types with.
1import {2 // Classe do contrato:3 Gravity,4 // Classes de eventos:5 NewGravatar,6 UpdatedGravatar,7} from '../generated/Gravity/Gravity'
In addition to this, one class is generated for each entity type in the Subgraph’s GraphQL schema. These classes provide type-safe entity loading, read and write access to entity fields as well as a save()
method to write entities to store. All entity classes are written to <OUTPUT_DIR>/schema.ts
, allowing mappings to import them with
1import { Gravatar } from '../generated/schema'
Note: The code generation must be performed again after every change to the GraphQL schema or the ABIs included in the manifest. It must also be performed at least once before building or deploying the Subgraph.
Code generation does not check your mapping code in src/mapping.ts
. If you want to check that before trying to deploy your Subgraph to Graph Explorer, you can run yarn build
and fix any syntax errors that the TypeScript compiler might find.