Construyendo Subgrafos en Arweave
Reading time: 7 min
Arweave support in Graph Node and on Subgraph Studio is in beta: please reach us on with any questions about building Arweave subgraphs!
En esta guía, aprenderás a construir y deployar subgrafos para indexar la blockchain de Arweave.
El protocolo Arweave permite a los developers almacenar datos de forma permanente y esa es la principal diferencia entre Arweave e IPFS, donde IPFS carece de la característica; permanencia, y los archivos almacenados en Arweave no pueden ser modificados o eliminados.
Arweave ya ha construido numerosas bibliotecas para integrar el protocolo en varios lenguajes de programación. Para más información puede consultar:
The Graph te permite crear API abiertas personalizadas llamadas "subgrafos". Los Subgrafos se utilizan para indicar a los Indexadores (operadores de servidores) qué datos indexar en una blockchain y guardar en sus servidores para que puedas consultarlos en cualquier momento usando .
ahora puede indexar datos en el protocolo Arweave. La integración actual solo indexa Arweave como una blockchain (bloques y transacciones), aún no indexa los archivos almacenados.
Para poder construir y deployar subgrafos Arweave, necesita dos paquetes:
@graphprotocol/graph-cli
versión anterior 0.30.2: esta es una herramienta de línea de comandos para crear e implementar subgrafos. para descargar usandonpm
.@graphprotocol/graph-ts
versión anterior 0.27.0: esta es una biblioteca de tipos específicos de subgrafos. para descargar usandonpm
.
Hay tres componentes de un subgrafo:
Define las fuentes de datos de interés y cómo deben ser procesadas. Arweave es un nuevo tipo de fuente de datos.
Aquí defines qué datos quieres poder consultar después de indexar tu Subgrafo usando GraphQL. Esto es en realidad similar a un modelo para una API, donde el modelo define la estructura de un cuerpo de solicitud.
Los requisitos para los subgrafos de Arweave están cubiertos por la .
Esta es la lógica que determina cómo los datos deben ser recuperados y almacenados cuando alguien interactúa con las fuentes de datos que estás escuchando. Los datos se traducen y se almacenan basándose en el esquema que has listado.
Durante el desarrollo del subgrafo hay dos comandos clave:
$ graph codegen # genera tipos a partir del archivo de esquema identificado en el manifiesto$ graph build # genera Web Assembly a partir de los archivos de AssemblyScript y prepara todos los archivos de subgrafo en una carpeta /build
El manifiesto del subgrafo subgraph.yaml
identifica las fuentes de datos para el subgrafo, los disparadores de interés y las funciones que deben ejecutarse en respuesta a esos disparadores. A continuación se muestra un ejemplo de manifiesto de subgrafos para un subgrafo de Arweave:
specVersion: 0.0.5descripción: Indexación de bloques Arweaveesquema:file: ./schema.graphql # link to the schema filedataSources:- kind: arweavename: arweave-blocksnetwork: arweave-mainnet # The Graph only supports Arweave Mainnetsource:owner: 'ID-OF-AN-OWNER' # The public key of an Arweave walletstartBlock: 0 # set this to 0 to start indexing from chain genesismapping:apiVersion: 0.0.5language: wasm/assemblyscriptfile: ./src/blocks.ts # link to the file with the Assemblyscript mappingsentities:- Block- TransactionblockHandlers:- handler: handleBlock # the function name in the mapping filetransactionHandlers:- handler: handleTx # the function name in the mapping file
- Los subgrafos de Arweave introducen un nuevo tipo de fuente de datos (
arweave
) - The network should correspond to a network on the hosting Graph Node. In Subgraph Studio, Arweave's mainnet is
arweave-mainnet
- Las fuentes de datos de Arweave introducen un campo opcional "source.owner", que es la clave pública de una billetera Arweave
Las fuentes de datos de Arweave admiten dos tipos de handlers:
blockHandlers
- Ejecutar en cada nuevo bloque de Arweave. No se requiere source.owner.transactionHandlers
: se ejecuta en cada transacción en la que elsource.owner
de la fuente de datos es el propietario. Actualmente se requiere un propietario paratransactionHandlers
, si los usuarios desean procesar todas las transacciones deben proporcionar "" comosource.owner
El source.owner puede ser la dirección del propietario o su clave pública.
Las transacciones son los bloques de construcción de la permaweb de Arweave y son objetos creados por los usuarios finales.
La definición de esquema describe la estructura de la base de datos de subgrafos resultante y las relaciones entre las entidades. Esto es independiente de la fuente de datos original. Hay más detalles sobre la definición del esquema de subgrafo .
Los handlers para procesar eventos están escritos en .
Arweave indexing introduces Arweave-specific data types to the .
class Block {timestamp: u64lastRetarget: u64height: u64indepHash: Bytesnonce: BytespreviousBlock: Bytesdiff: Byteshash: BytestxRoot: Bytestxs: Bytes[]walletList: BytesrewardAddr: Bytestags: Tag[]rewardPool: BytesweaveSize: BytesblockSize: BytescumulativeDiff: ByteshashListMerkle: Bytespoa: ProofOfAccess}class Transaction {format: u32id: ByteslastTx: Bytesowner: Bytestags: Tag[]target: Bytesquantity: Bytesdata: BytesdataSize: BytesdataRoot: Bytessignature: Bytesreward: Bytes}
Los handlers de bloques reciben un Block
, mientras que las transacciones reciben una Transaction
.
Escribir los mappings de un subgrafo de Arweave es muy similar a escribir los mappings de un subgrafo de Ethereum. Para obtener más información, haz clic .
Once your subgraph has been created on your Subgraph Studio dashboard, you can deploy by using the graph deploy
CLI command.
graph deploy --access-token <your-access-token>
El endpoint de GraphQL para los subgrafos de Arweave está determinado por la definición del esquema, con la interfaz API existente. Visita la para obtener más información.
A continuación se muestra un ejemplo de subgrafo como referencia:
No, un subgrafo sólo puede admitir fuentes de datos de una cadena/red.
Actualmente, The Graph sólo indexa Arweave como blockchain (sus bloques y transacciones).
Actualmente no se admite.
El source.owner puede ser la clave pública del usuario o la dirección de la cuenta.
Los datos generalmente se pasan a los mappings como Bytes, que si se almacenan directamente se devuelven en el subgrafo en un formato hex
(por ejemplo, hash de bloque y transacción). Puedes querer convertir tus asignaciones a un formato seguro base64
o base64 URL
para que coincida con lo que se muestra en los exploradores de bloques como [Explorador de Arweave](https: //viewblock.io/arweave/).
Se puede usar la siguiente función auxiliar bytesToBase64(bytes: Uint8Array, urlSafe: boolean): string
y se agregará a graph-ts
:
const base64Alphabet = ["A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M","N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z","a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m","n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z","0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "+", "/"];const base64UrlAlphabet = ["A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M","N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z","a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m","n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z","0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "-", "_"];function bytesToBase64(bytes: Uint8Array, urlSafe: boolean): string {let alphabet = urlSafe? base64UrlAlphabet : base64Alphabet;let result = '', i: i32, l = bytes.length;for (i = 2; i < l; i += 3) {result += alphabet[bytes[i - 2] >> 2];result += alphabet[((bytes[i - 2] & 0x03) << 4) | (bytes[i - 1] >> 4)];result += alphabet[((bytes[i - 1] & 0x0F) << 2) | (bytes[i] >> 6)];result += alphabet[bytes[i] & 0x3F];}if (i === l + 1) { // 1 octet yet to writeresult += alphabet[bytes[i - 2] >> 2];result += alphabet[(bytes[i - 2] & 0x03) << 4];if (!urlSafe) {result += "==";}}if (!urlSafe && i === l) { // 2 octets yet to writeresult += alphabet[bytes[i - 2] >> 2];result += alphabet[((bytes[i - 2] & 0x03) << 4) | (bytes[i - 1] >> 4)];result += alphabet[(bytes[i - 1] & 0x0F) << 2];if (!urlSafe) {result += "=";}}return result;}