9 分钟
用嫁接替换合约并保持合约的历史
在本指南中,您将学习如何通过嫁接现有的子图来构建和部署新的子图。
什么是嫁接?
嫁接重用现有子图中的数据,并开始在稍后的区块中对其进行索引。这在开发过程中非常有用,可以快速克服映射中的简单错误,或者在现有子图失败后暂时使其重新工作。此外,当向子图添加特性时可以使用它,因为从头开始索引需要很长时间。
嫁接子图可以使用一个与基础子图不同的GraphQL 模式,但仅与之兼容。它本身必须是一个有效的子图模式,但是可以通过以下方式偏离基础子图的模式:
- 添加或删除实体类型
- 从实体类型中删除属性
- 将可为空的属性添加到实体类型
- 将不可为空的属性转换为可空的属性
- 将值添加到枚举类型中
- 添加或删除接口
- 改变了实现接口的实体类型
有关详情,请参阅:
在本教程中,我们将介绍一个基本用例。我们将用一个相同的合约(用一个新的地址,但相同的代码) 替换现有的合约。然后,将现有的子图嫁接到跟踪新合约的 “基础 “子图上。
升级到网络时嫁接的重要注意事项
警告:建议不要对发布到The Graph网络的子图使用嫁接
为什么这很重要?
嫁接是一个强大的功能,允许您将一个子图“嫁接”到另一个子图上,有效地将历史数据从现有子图转移到新版本。无法将子图从The Graph网络嫁接回subgraph Studio。
最佳实践
初始迁移:当你第一次将子图部署到去中心化网络时,不要进行嫁接。确保子图稳定并按预期运行。
后续更新:一旦你的子图在去中心化网络上上线并稳定,你可以在未来的版本中使用嫁接,使过渡更平滑,并保留历史数据。
通过遵守这些准则,您可以将风险降至最低,并确保迁移过程更加顺利。
构建现有子图
构建子图是The Graph的重要组成部分,在此文进行更深入的描述。为了能够构建和部署本教程中使用的现有子图,提供了以下库:
注意: 子图中使用的合约取自以下Hackathon Starterkit。
子图清单定义
子图诠释了subgraph.yaml
标识子图的数据源、感兴趣的触发器以及应该响应这些触发器而运行的函数。下面是您将使用的子图清单示例:
1specVersion: 1.3.02schema:3 file: ./schema.graphql4dataSources:5 - kind: ethereum6 name: Lock7 network: sepolia8 source:9 address: '0xb3aabe721794b85fe4e72134795c2f93b4eb7e63'10 abi: Lock11 startBlock: 595569012 mapping:13 kind: ethereum/events14 apiVersion: 0.0.915 language: wasm/assemblyscript16 entities:17 - Withdrawal18 abis:19 - name: Lock20 file: ./abis/Lock.json21 eventHandlers:22 - event: Withdrawal(uint256,uint256)23 handler: handleWithdrawal24 file: ./src/lock.ts
Lock
数据源是我们在编译和部署合约时获得的abi和合约地址。- 网络应该对应于一个被查询的索引网络。因为我们运行在Sepolia 测试网上,所以这个网络就是Sepolia。
mapping
部分定义了感兴趣的触发器以及应该响应这些触发器而运行的函数。在这种情况下,我们正在监听Withdrawl
事件,并在发出该事件时调用处理Withdrawal
函数。
嫁接清单定义
嫁接需要在原始子图清单中添加两个新项:
1---2features:3 - grafting # feature name4graft:5 base: Qm... # Subgraph ID of base Subgraph6 block: 5956000 # block number
features:
是所有使用的功能名称的列表。graft
:是基础
子图和要嫁接到的模块的映射。block
是开始索引的区块号。The Graph将把基础子图的数据复制到给定的区块并将其包括在内,然后从该区块开始继续索引新的子图。
通过部署两个子图可以找到base
和block
值:一个用于基础索引,一个用于嫁接。
部署基子图
- 转到Subgraph Studio 子图并在Sepolia 测试网上创建一个称为
graft-example
的子图。 - 按照存储库中
graft-example
文件夹中子图页面的AUTH& DEPLOY
部分中的说明操作。 - 完成后,验证子图是否正确索引。如果在The Graph Playground中运行下列指令。
1{2 withdrawals(first: 5) {3 id4 amount5 when6 }7}
它返回的结果是这样的:
1{2 "data": {3 "withdrawals": [4 {5 "id": "0xe8323d21c4f104607b10b0fff9fc24b9612b9488795dea8196b2d5f980d3dc1d0a000000",6 "amount": "0",7 "when": "1716394824"8 },9 {10 "id": "0xea1cee35036f2cacb72f2a336be3e54ab911f5bebd58f23400ebb8ecc5cfc45203000000",11 "amount": "0",12 "when": "1716394848"13 }14 ]15 }16}
一旦您验证了子图是正确的索引,您可以快速更新子图与嫁接。
部署嫁接子图
嫁接替代Subgraph.yaml将获得一个新的合约地址。这可能发生在更新dapp、重新部署合约等时。
- 转到Subgraph Studio 子图并在Sepolia 测试网上创建一个称为
graft-replacement
的子图。 - 创建新清单。
graph-replacement
的subgraph.yaml
包含一个不同的合约地址和关于其应该如何嫁接的新信息。这些是旧合约发出的最后一个事件 的模块
,你关心的是旧合约,也是旧子图的基础
。基础
子图ID是原始graph-example
子图的部署ID
。你可以在Subgraph Studio中找到它。 - 按照存储库中的
graft-replacement
文件夹中子图页面上的AUTH& DEPLOY
部分的说明操作。 - 完成后,验证子图是否正确索引。如果在Graph Playground中运行下列指令。
1{2 withdrawals(first: 5) {3 id4 amount5 when6 }7}
它返回的结果是这样的:
1{2 "data": {3 "withdrawals": [4 {5 "id": "0xe8323d21c4f104607b10b0fff9fc24b9612b9488795dea8196b2d5f980d3dc1d0a000000",6 "amount": "0",7 "when": "1716394824"8 },9 {10 "id": "0xea1cee35036f2cacb72f2a336be3e54ab911f5bebd58f23400ebb8ecc5cfc45203000000",11 "amount": "0",12 "when": "1716394848"13 },14 {15 "id": "0x2410475f76a44754bae66d293d14eac34f98ec03a3689cbbb56a716d20b209af06000000",16 "amount": "0",17 "when": "1716429732"18 }19 ]20 }21}
您可以看到,嫁接替换
子图是从旧的graph-example
数据和新合约地址的新数据中索引的。原始合约发出了两个撤回
事件,事件1和事件2。新合约在事件3之后发出一次撤回
。两个先前索引的交易(事件1和2)和新交易(事件3)在graft-replacement
子图中合并在一起。
恭喜! 你成功地将一个子图嫁接到另一个子图上。
其他资源
如果你想要更多的嫁接经验,这里有一些流行合约的例子:
要成为更专业的Graph专家,请考虑学习处理底层数据源更改的其他方法。像Data Source Templates 这样的替代方案可以实现类似的结果。
注意:这篇文章中的很多内容都来自之前发表的Arweave文章。