Las plantillas de fuentes de datos de Graph 4

Un patrón común para los contratos inteligentes de Ethereum es usar un contrato de registro o de fábrica, donde un contrato crea, administra o hace referencia a cualquier número de otros contratos, cada uno con su propio estado y eventos. Las direcciones de estos contratos subordinados pueden o no conocerse de antemano, y muchos de estos contratos pueden crearse o agregarse con el tiempo. Por eso, en este caso, no es posible definir una sola fuente de datos o un número fijo de fuentes de datos, y se requiere un enfoque más dinámico: plantillas de fuentes de datos.

contrato inteligente

El contrato de GravatarRegistry anterior se implementó manualmente, ahora lo modificamos ligeramente para crear dinámicamente el contrato de GravatarRegistry a través del contrato de fábrica.

Primero el contrato de fábrica:

// SPDX-License-Identifier: MIT
pragma solidity >0.5.16;

import './GravatarRegistry.sol';
import './IGravatarRegistry.sol';


contract GravatarRegistryFactory {

    mapping(string => address) public getRegistry;
    string[] public allRegistries;

    event RegistryCreated(string gravatarGroup, address indexed registry,uint);


    function allRegistriesLength() external view returns (uint) {
        return allRegistries.length;
    }

    function createGravatarRegistry(string calldata _gravatarGroup) external returns (address registry) {
        require(getRegistry[_gravatarGroup] == address(0), 'GravatarRegistry: ALREADY_EXISTS');
        bytes memory bytecode = type(GravatarRegistry).creationCode;
        bytes32 salt = keccak256(abi.encodePacked(_gravatarGroup));
        assembly {
            registry := create2(0, add(bytecode, 32), mload(bytecode), salt)
        }
        IGravatarRegistry(registry).initialize(_gravatarGroup);
        getRegistry[_gravatarGroup] = registry;
        allRegistries.push(_gravatarGroup);
        emit RegistryCreated(_gravatarGroup, registry, allRegistries.length);
    }
}

Agregar interfaz:

// SPDX-License-Identifier: MIT
pragma solidity >=0.5.0;

interface IGravatarRegistry {
    event NewGravatar(uint id, address owner, string displayName, string imageUrl);
    event UpdatedGravatar(uint id, address owner, string displayName, string imageUrl);

    function createGravatar(string calldata _displayName, string calldata _imageUrl) external;

    function getGravatar(address owner) external view returns (string memory, string memory);
    function updateGravatarName(string calldata _displayName) external;

    function updateGravatarImage(string calldata _imageUrl) external;

    function setMythicalGravatar() external ;

    function initialize(string calldata _groupName) external ;
}

El contrato GravatarRegistry agrega una variable groupName al original:

// SPDX-License-Identifier: MIT
pragma solidity >0.4.0;

contract GravatarRegistry {
  event NewGravatar(uint id, address owner, string displayName, string imageUrl);
  event UpdatedGravatar(uint id, address owner, string displayName, string imageUrl);

  struct Gravatar {
    address owner;
    string displayName;
    string imageUrl;
  }

  address public factory;
  string public groupName;


  Gravatar[] public gravatars;

  mapping (uint => address) public gravatarToOwner;
  mapping (address => uint) public ownerToGravatar;

  
  constructor() public {
      factory = msg.sender;
  }

  function createGravatar(string calldata _displayName, string calldata _imageUrl) public {
    require(ownerToGravatar[msg.sender] == 0);
    gravatars.push(Gravatar(msg.sender, _displayName, _imageUrl));
    uint id = gravatars.length - 1;

    gravatarToOwner[id] = msg.sender;
    ownerToGravatar[msg.sender] = id;

    emit NewGravatar(id, msg.sender, _displayName, _imageUrl);
  }

  function getGravatar(address owner) public view returns (string memory, string memory) {
    uint id = ownerToGravatar[owner];
    return (gravatars[id].displayName, gravatars[id].imageUrl);
  }

  function updateGravatarName(string calldata _displayName) public {
    require(ownerToGravatar[msg.sender] != 0);
    require(msg.sender == gravatars[ownerToGravatar[msg.sender]].owner);

    uint id = ownerToGravatar[msg.sender];

    gravatars[id].displayName = _displayName;
    emit UpdatedGravatar(id, msg.sender, _displayName, gravatars[id].imageUrl);
  }

  function updateGravatarImage(string calldata _imageUrl) public {
    require(ownerToGravatar[msg.sender] != 0);
    require(msg.sender == gravatars[ownerToGravatar[msg.sender]].owner);

    uint id = ownerToGravatar[msg.sender];

    gravatars[id].imageUrl =  _imageUrl;
    emit UpdatedGravatar(id, msg.sender, gravatars[id].displayName, _imageUrl);
  }

  // the gravatar at position 0 of gravatars[]
  // is fake
  // it's a mythical gravatar
  // that doesn't really exist
  // dani will invoke this function once when this contract is deployed
  // but then no more
  function setMythicalGravatar() public {
    require(msg.sender == 0xBA8B604410ca76AF86BDA9B00Eb53B65AC4c41AC);
    gravatars.push(Gravatar(address(0x0), " ", " "));
  }

  // called once by the factory at time of deployment
  function initialize(string calldata _groupName) external {
      require(msg.sender == factory, 'UniswapV2: FORBIDDEN'); // sufficient check
      groupName = _groupName;
  }
}

Implemente el contrato de fábrica y deje GravatarRegistry para la implementación dinámica más adelante.

subgraph.yaml

Agregue la configuración de plantillas, sus elementos de configuración son básicamente similares a las fuentes de datos, la dirección y el bloque de inicio no son compatibles con la fuente

specVersion: 0.0.5
schema:
  file: ./schema.graphql
features:
  - fullTextSearch
dataSources:
  - kind: ethereum/contract
    name: Factory
    network: goerli
    source:
      address: '0x580b57db55a0636B53Cb09BbA4aE8CbB765D72bA'
      abi: Factory
      startBlock: 8403815
    mapping:
      kind: ethereum/events
      apiVersion: 0.0.7
      language: wasm/assemblyscript
      file: ./src/factory.ts
      entities:
        - Registry
      abis:
        - name: Factory
          file: ./abis/Factory.json
      eventHandlers:
        - event: RegistryCreated(string,indexed address,uint256)
          handler: handleNewRegistry
templates:
  - kind: ethereum
    name: GravatarRegistry
    network: goerli
    source:
      abi: GravatarRegistry
    mapping:
      kind: ethereum/events
      apiVersion: 0.0.7
      language: wasm/assemblyscript
      entities:
        - Gravatar
        - Transaction
        - Block
      abis:
        - name: GravatarRegistry
          file: ./abis/GravatarRegistry.json
      eventHandlers:
        - event: NewGravatar(string,uint256,address,string,string)
          handler: handleNewGravatar
        - event: UpdatedGravatar(string,uint256,address,string,string)
          handler: handleUpdatedGravatar
      callHandlers:
        - function: createGravatar(string,string)
          handler: handleCreateGravatar
      blockHandlers:
        - handler: handleBlockWithCallToContract
          filter:
            kind: call
      file: ./src/gravatar-registry.ts

esquema.graphql

type _Schema_
  @fulltext(
    name: "gravatarSearch"
    language: en
    algorithm: rank
    include: [{ entity: "Gravatar", fields: [{ name: "displayName" }, { name: "description" }] }]
  )


type Gravatar @entity(immutable: false) {
  id: String!
  owner: Bytes! # address
  groupName: String! # string
  displayName: String! # string
  description: String! # string
  imageUrl: String! # string
  transaction: Transaction
}


type Transaction @entity(immutable: true) {
  id: Bytes!
  block: Block
  gasPrice: BigInt! # bigInt
}

type Block @entity(immutable: true) {
  id: Bytes!
  blockNumber: BigInt!
  blockTimestamp: BigInt!
  transactions: [Transaction!] @derivedFrom(field: "block")
}

type Registry @entity(immutable: false) {
  id: String!
  address: Bytes! # address
  groupName: String! # string
}

fábrica.ts

import {
  RegistryCreated as RegistryCreatedEvent,
} from "../generated/Factory/Factory"
import { Registry} from "../generated/schema"
import { GravatarRegistry } from "../generated/templates"
export function handleNewRegistry(event: RegistryCreatedEvent): void {
  let registry = new Registry(event.params.param2.toString());
  registry.address = event.params.registry;
  registry.groupName = event.params.gravatarGroup
  registry.save()
  GravatarRegistry.create(event.params.registry);
}

Esto se utiliza principalmente para monitorear el contrato de fábrica.La clave es la última línea de código, que crea dinámicamente la fuente de datos del contrato que se monitoreará.

gravatar-registry.ts

También hay que hacer algunas modificaciones aquí, principalmente para agregar el campo groupName.

import {
  CreateGravatarCall,
  NewGravatar as NewGravatarEvent,
  UpdatedGravatar as UpdatedGravatarEvent
} from "../generated/templates/GravatarRegistry/GravatarRegistry"
import { Gravatar,Transaction,Block} from "../generated/schema"
import { ethereum } from '@graphprotocol/graph-ts'

export function handleNewGravatar(event: NewGravatarEvent): void {
  let gravatar = new Gravatar(event.params.id.toString()+event.params.groupName);
  gravatar.owner = event.params.owner
  gravatar.groupName = event.params.groupName
  gravatar.displayName = event.params.displayName
  gravatar.imageUrl = event.params.imageUrl
  gravatar.description = event.params.imageUrl.replaceAll("/"," ");
  gravatar.transaction = event.transaction.hash
  gravatar.save()
}

export function handleUpdatedGravatar(event: UpdatedGravatarEvent): void {
  let id = event.params.id.toString();
  let gravatar = Gravatar.load(id+event.params.groupName)
  if (gravatar == null) {
    gravatar = new Gravatar(id+event.params.groupName)
  }
  gravatar.groupName = event.params.groupName
  gravatar.owner = event.params.owner
  gravatar.displayName = event.params.displayName
  gravatar.description = event.params.imageUrl.replaceAll("/"," ");
  gravatar.imageUrl = event.params.imageUrl
  gravatar.transaction = event.transaction.hash
  gravatar.save()
}

Vuelva a compilar la versión:

 graph codegen
 graph build
 yarn deploy

verificar

Finalmente llamamos al método createGravatarRegistry del contrato de fábrica. Aquí, test1, test2, test3 y test4 se pasan respectivamente y se crean cuatro contratos GravatarRegistry. Su nombre de grupo es test1, test2, test3, test4 respectivamente.

De hecho, este tipo de contrato inteligente creado dinámicamente por la fábrica también debería tener acceso a un contrato de enrutamiento a través del salto groupName Aquí, la complejidad del ejemplo se simplifica y la función del contrato GravatarRegistry se llama manualmente directamente a través de la dirección devuelta por el contrato de fábrica.

Llamado al método createGravatar de los cuatro contratos respectivamente, consulta de verificación:

El código de ejemplo es el siguiente:

https://github.com/ziyiyu/subgraph-example

Supongo que te gusta

Origin blog.csdn.net/gambool/article/details/128797639
Recomendado
Clasificación