导览 > 用嫁接替换合约并保持合约的历史

用嫁接替换合约并保持合约的历史

Reading time: 8 min

在本指南中,您将学习如何通过嫁接现有的子图来构建和部署新的子图。

什么是嫁接?

链到本节

嫁接重用现有子图中的数据,并开始在稍后的区块中对其进行索引。这在开发过程中非常有用,可以快速克服映射中的简单错误,或者在现有子图失败后暂时使其重新工作。此外,当向子图添加特性时可以使用它,因为从头开始索引需要很长时间。

嫁接子图可以使用一个 GraphQL 模式 schema,该模式与基子图之一不同,但仅与基子图兼容。它本身必须是一个有效的子图模式,但是可以通过以下方式偏离基子图的模式:

  • 它添加或删除实体类型
  • 它从实体类型中删除属性
  • 它将可为空的属性添加到实体类型
  • 它将不可为空的属性转换为可空的属性
  • 它将值添加到枚举类型中
  • 它添加或删除接口
  • 它改变了实现接口的实体类型

有关详情,请参阅:

在本教程中,我们将介绍一个基本用例。我们将用一个相同的合约(用一个新的地址,但相同的代码) 替换现有的合约。然后,将现有的子图移植到跟踪新合约的基本子图上。

Important Note on Grafting When Upgrading to the Network

链到本节

Caution: if you are upgrading your subgraph from Subgraph Studio or the hosted service to the decentralized network, it is strongly recommended to avoid using grafting during the upgrade process.

Why Is This Important?

链到本节

Grafting is a powerful feature that allows you to "graft" one subgraph onto another, effectively transferring historical data from the existing subgraph to a new version. While this is an effective way to preserve data and save time on indexing, grafting may introduce complexities and potential issues when migrating from a hosted environment to the decentralized network. It is not possible to graft a subgraph from The Graph Network back to the hosted service or Subgraph Studio.

Best Practices

链到本节

Initial Migration: when you first deploy your subgraph to the decentralized network, do so without grafting. Ensure that the subgraph is stable and functioning as expected.

Subsequent Updates: once your subgraph is live and stable on the decentralized network, you may use grafting for future versions to make the transition smoother and to preserve historical data.

By adhering to these guidelines, you minimize risks and ensure a smoother migration process.

构建现有子图

链到本节

构建子图是Graph的重要组成部分,我们在此文进行更深入的描述。为了能够构建和部署本教程中使用的现有子图,提供了以下存储库:

注意: 子图中使用的合约取自以下Hackathon Starterkit

子图清单定义

链到本节

子图诠释了subgraph.yaml标识子图的数据源、感兴趣的触发器以及应该响应这些触发器而运行的函数。下面是您将使用的子图清单示例:

specVersion: 0.0.4
schema:
file: ./schema.graphql
dataSources:
- kind: ethereum
name: Lock
network: goerli
source:
address: '0x4Ed995e775D3629b0566D2279f058729Ae6EA493'
abi: Lock
startBlock: 7674603
mapping:
kind: ethereum/events
apiVersion: 0.0.6
language: wasm/assemblyscript
entities:
- Withdrawal
abis:
- name: Lock
file: ./abis/Lock.json
eventHandlers:
- event: Withdrawal(uint256,uint256)
handler: handleWithdrawal
file: ./src/lock.ts
  • Lock数据源是我们在编译和部署合约时获得的abi和合约地址
  • 网络应该对应于一个被查询的索引网络。因为我们运行在Goerli testnet上,所以这个网络就是Goerli
  • mapping部分定义了感兴趣的触发器以及应该响应这些触发器而运行的函数。在这种情况下,我们正在监听Withdrawl事件,并在发出该事件时调用处理Withdrawal函数。

嫁接清单定义

链到本节

嫁接需要在原始子图清单中添加两个新项:

---
features:
- grafting # feature name
graft:
base: Qm... # subgraph ID of base subgraph
block: 1502122 # block number
  • features:是所有使用过的特性名称的列表。
  • graft:是base子图和要嫁接到的模块的映射。block是开始索引的区块号。Graph将把基本子图的数据复制到给定的区块并将其包括在内,然后从该区块开始继续索引新的子图。

通过部署两个子图可以找到baseblock值:一个用于基索引,一个用于嫁接

部署基子图

链到本节
  1. 转到Graph Studio UI并在Goerli 测试网上创建一个称为嫁接示例的子图
  2. 按照存储库中graft-example文件夹中子图页面的 AUTH& DEPLOY 部分中的说明操作
  3. 完成后,验证子图是否正确索引。如果在Graph Playground中运行下列指令。
{
withdrawals(first: 5) {
id
amount
when
}
}

它返回的结果是这样的:

{
"data": {
"withdrawals": [
{
"id": "0x13098b538a61837e9f29b32fb40527bbbe63c9120c250242b02b69bb42c287e5-5",
"amount": "0",
"when": "1664367528"
},
{
"id": "0x800c92fcc0edbd26f74e19ad058c62008a47c7789f2064023b987028343dd498-3",
"amount": "0",
"when": "1664367648"
}
]
}
}

一旦您验证了子图是正确的索引,您可以快速更新子图与嫁接。

部署嫁接子图

链到本节

嫁接替代Subgraph.yaml将获得一个新的合约地址。这可能发生在更新dapp、重新部署合约等时。

  1. Graph Studio UI并在Goerli testnet上创建一个称为graft-replacement的子图
  2. 创建一个新的清单。subgraph.yaml用于graph-replacement,它包含一个不同的合约地址和关于如何移植的新信息。这些是旧合约发出的最后一个事件block和旧子图的basebase 子图ID是原始graph-exampleDeployment ID。您可以在Graph Studio UI中找到它。
  3. 按照存储库中的graft-replacement文件夹中子图页面上的 AUTH& DEPLOY 部分的说明操作。
  4. 完成后,验证子图是否正确索引。如果在Graph Playground中运行下列指令。
{
withdrawals(first: 5) {
id
amount
when
}
}

它返回的结果是这样的:

{
"data": {
"withdrawals": [
{
"id": "0x13098b538a61837e9f29b32fb40527bbbe63c9120c250242b02b69bb42c287e5-5",
"amount": "0",
"when": "1664367528"
},
{
"id": "0x800c92fcc0edbd26f74e19ad058c62008a47c7789f2064023b987028343dd498-3",
"amount": "0",
"when": "1664367648"
},
{
"id": "0xb4010e4c76f86762beb997a13cf020231778eaf7c64fa3b7794971a5e6b343d3-22",
"amount": "0",
"when": "1664371512"
}
]
}
}

您可以看到,graft-replacement子图索引来自旧的graph-example数据和来自新合约地址的新数据。原始合约发出了两个Withdrawal事件,即事件1事件2。新合约在事件3之后发生一次Withdrawal。先前索引的两个交易(事件1和2)和新的交易(事件3)在graft-replacement子图中组合在一起。

恭喜! 你成功地将一个子图嫁接到另一个子图上。

其他资源

链到本节

如果你想要更多的嫁接经验,这里有一些流行合约的例子:

要成为更专业的Graph专家,请考虑学习处理底层数据源更改的其他方法。像数据源模板这样的替代方案可以实现类似的结果。

注意:这篇文章中的很多内容都来自之前发表的Arweave文章

编辑

上页
在 Arweave 上构建子图
下页
安全子图代码生成器
编辑