什么是Subgraph
Subgraph 是由 The Graph 所提供的一种技术。The Graph 是一种去中心化的索引协议,用于查询类似以太坊和 IPFS 的区块链网络数据,目前支持了 Ethereum 主网和几个测试网,以及 BSC、Matic、Fantom 等。任何人都可以基于其创建和部署开放 API,即 subgraph,使得区块链数据更容易访问。
即是说,subgraph 是由开发者创建并部署到 The Graph 的开放索引服务。
基于 The Graph 和 subgraph,数据流大致如下:
- 一个 DApp 通过合约执行一个 transaction,合约 emit 了一个或多个 event;
- The Graph 的节点持续扫描区块数据,而你定义的 subgraph 设置了所需要监听的事件;
- Graph 节点监听到你的 subgraph 所关心的事件,会根据你的 subgraph 所定义的处理方法创建或更新实体对象的数据,这些数据会保存在 Graph 节点中;
- 前端框架连接到 Graph 节点,通过编写 GraphQL 查询相应的实体对象数据并展示到页面上。
简单地说,通过 subgraph 可以对链上数据进行再封装,形成更便于查询的数据。因为有些数据,是难以在链上直接查询得到的。
官方文档中举了一个例子,比如:谁是 2018 年 1 月至 2 月出生的 CryptoKitties 的所有者? 要回答这个问题,必须处理所有 Birth
事件 ,然后 为每个出生的 CryptoKitty 调用 ownerOf
方法。即使对于这个相对简单的问题,运行在浏览器中的 Dapp 也需要数小时甚至数天才能得到答案。索引区块链数据很困难。区块链属性,如最终性、链重整或未处理的块,使这个过程进一步复杂化,不仅耗时,而且在概念上很难从区块链数据中检索正确的查询结果。The Graph 通过一个为区块链数据编制索引的托管服务解决了这个问题。然后可以使用标准 GraphQL API 查询这些索引(subgraph)。
Graph Node
Graph Node 是 Subgraph 的运行环境,而目前其实存在三种方式的运行环境:
- Hosted Service:The Graph官方团队提供的中心化的托管服务,也是目前使用最广泛便利的一种方式。
- Private Node:私有节点,由 Dapp 团队根据开源的 graph-node 项目自主搭建。
- The Graph Network:去中心化网络,主网已上线,但目前还不稳定,开发团队目前也无法直接将 Subgraph 部署上去,需 The Graph 技术团队协同才能迁移到主网。
使用 Hosted Service 是最方便的,也是目前最推荐的一种方式。基于 Hosted Service 的 subgraph 部署流程如下:
1. 在官网注册账号
第一步,需要在 The Graph 官网(thegraph.com/explorer/)用 Github 账号进行注册,如果没有 Github 账号的话,还需要先去注册一个 Github 账号。
2. 在官网添加 Subgraph
创建账户并登录之后,进入 Dashboard 就可以开始通过界面创建 subgraph。进入你的 Dashboard,并点击 Add Subgraph。另外,每个账户都有一个 Access token,在将 subgraph 部署到 Graph 节点时需要用到。
需要填写以下信息:
其中,除了 Subgraph Name 和 Account 无法修改,其他字段都是后续可以修改的。另外,Subgraph Name 是区分大小写的,后续创建本地项目时需指定 Subgraph Name,切记这点。
3. 本地安装 Graph CLI
在本地环境安装 Graph CLI,即 Graph 的客户端工具,可以用 npm 或 yarn:
$ npm install -g @graphprotocol/graph-cli $ yarn global add @graphprotocol/graph-cli
在这个安装的过程中,可能会因为国内的网络问题导致失败,可以使用翻墙工具并通过设置代理的方式解决,而且可能还需要设置为 socks5 代理。我安装的过程中,曾经只设置为 http 代理,但有一个依赖的库总是报 ESOCKETTIMEOUT。
另外,npm 和 yarn 只支持设置 http 代理,并不支持设置 socks5 代理,因此,还需要一个工具将 http 代理转为 socks5 代理。这个工具为 http-proxy-to-socks。
# 假设本地socks5代理端口为1086 # 首先安装转换工具 npm install -g http-proxy-to-socks # 然后使用这个工具监听8002端口,支持http代理,然后所有8002的http代理数据都将转换成socks的代理数据发送到1086上 hpts -s 127.0.0.1:1086 -p 8002 # 最后设置npm代理 npm config set proxy http://127.0.0.1:8002 npm config set https-proxy http://127.0.0.1:8002
使用 yarn 同理。对应的几个 npm 命令可改为:
# 安装转换工具 yarn global add http-proxy-to-socks # 设置代理为 yarn config set proxy http://127.0.0.1:8002 yarn config set https-proxy http://127.0.0.1:8002
另外,使用期间,hpts -s 127.0.0.1:1086 -p 8002 需要一直开着。
当然,这是我遇到的情况,有些人可能遇到的问题不一样,我也不确定我的这种方案是否能解决你的问题,但至少可以尝试一下。
最后再补充一点,如果因为 git 原因发生网络问题,那可以将 git 也设置为使用代理。
4. 创建本地 subgraph 项目
在本地环境初始化一个 subgraph 项目主要使用 graph init 命令,后续参数可以指定 --from-contract 或 --from-example。--from-contract 是从一个合约地址新建项目,--from-example 则是用一个官方提供的案例进行初始化。
--from-contract 是比较实用的一种方式,使用的命令格式为:
graph init \ --from-contract <CONTRACT_ADDRESS> \ [--network <ETHEREUM_NETWORK>] \ [--abi <FILE>] \ <GITHUB_USER>/<SUBGRAPH_NAME> [<DIRECTORY>]
- --from-contract:配置合约地址
- --network:指定所使用的网络,目前支持了多种网络,包括 mainnet、kovan、rinkeby、ropsten、goerli、poa-core、xdai、poa-sokol、matic、mumbai、fantom、bsc、clover
- --abi:指定所使用的 abi 文件,如不指定,则会用 etherscan 获取,但因为网络原因,基本获取不到,所以最好指定本地文件
- <GITHUB_USER>/<SUBGRAPH_NAME>:就是前面在官网所创建的 subgraph,比如我之前创建的为 keeganlee/First
- [DIRECTORY]:指定创建的 subgraph 项目存放的目录,不指定的情况下和 SUBGRAPH_NAME 同名
比如,我创建的示例项目所使用的具体参数如下:
graph init \ --from-contract 0x3d9819210A31b4961b30EF54bE2aeD79B9c9Cd3B \ --network mainnet \ --abi Comptroller.json \ keeganlee/First
创建的过程中,还会下载一些依赖的库,可能也会因为国内网络原因而失败,因此,可以用上面所提到的方法设置代理。
创建成功后,项目的目录结构如下:
subgraph.yaml #manifest文件,也是subgraph的入口点,很多信息都是在该文件中配置 schema.graphql #schema主要定义了保存到Graph节点中的各种实体数据的数据结构 package.json yarn.lock abis #合约的abi文件都放在这里 - Contract.json src #主要编写对合约事件监听后的处理,处理逻辑一般就是创建或更新实体数据 - mapping.ts generated #这是自动生成的,修改以上的文件后可用graph codegen命令重新生成 - schema.ts - Contract - Contract.ts
5. 编码
根据实际的业务需要对subgraph项目进行编码工作,主要需要修改和编写的文件为:
- subgraph.yaml
- schema.graphql
- mapping.ts
这里面涉及到较多的知识点,后面再说。
6. 部署
当编码工作完成,也没什么问题之后,就可以将其部署到 The Graph 的 Hosted Service 中去。
部署之前,第一步是先进行授权,执行以下命令:
graph auth https://api.thegraph.com/deploy/ <access-token>
其中,access-token 就是你的 Dashboard 中所显示的那个 Access token,也是前面提到的。
接着,就可以在你的 subgraph 项目的根目录下调用以下命令进行部署:
yarn deploy
部署完成之后,就可以在 The Graph 官网中进入你的 subgraph 查看,比如我的 subgraph 部署完之后如下:
里面,有一个进度条,显示 Syncing(4.6%),这是在同步区块数据。
Playground 中右边展示了项目中所定义的 schema,左边则可以用 GraphQL 编写查询语句,点击 Play 按钮,则会将查询结果的数据展示在中间那片空白区域中。
私有节点
若要自己搭建私有节点,可按照 Github 上的 graph-node 项目的说明进行部署。其 Github 地址为:
部署 graph-node 也有两种方式,一是 README 上所描述的步骤,二是用 Docker 进行部署。两种方式我都尝试过,但第一种方式以失败告终,多次尝试解决问题依然无果,第二种方式很快就成功了,所以我强烈推荐用 Docker 方式进行部署。
首先,在需要部署的服务器安装好 docker 和 docker-compose。
其次,打开 graph-node/docker/docker-compose.yml 文件,修改其中一行:
ethereum: 'mainnet:http://host.docker.internal:8545'
该行指定了使用的网络和节点,比如,我部署接入 kovan 网络,节点使用 infura 的,那设置的值为:
ethereum: 'kovan:https://kovan.infura.io/v3/<PROJECT_ID>'
其中,<PROJECT_ID> 是在 infura 注册项目时所分配的项目ID。
最后,在 graph-node/docker 目录下,执行以下命令:
docker-compose up -d
将会自动下载 IPFS、Postgres 和 Graph Node 三个 Docker 镜像,并以后台的方式运行容器。
至此,私有的 Graph 节点就启动了,就可以访问以下这些:
- Graph Node:
- GraphiQL:
http://localhost:8000/
- HTTP:
http://localhost:8000/subgraphs/name/<subgraph-name>
- WebSockets:
ws://localhost:8001/subgraphs/name/<subgraph-name>
- Admin:
http://localhost:8020/
- IPFS:
127.0.0.1:5001
or/ip4/127.0.0.1/tcp/5001
- Postgres:
postgresql://graph-node:let-me-in@localhost:5432/graph-node
再配置下对外的端口和权限,外部也可以访问节点了。
而本地的 subgraph 项目想要部署到此私有节点的话,需要先在本地执行以下命令:
graph create <SUBGRAPH_NAME> --node http://<NODE_IP>:8020
其中,<SUBGRAPH_NAME> 替换成你自己的 subgraph 名称,<NODE_IP> 则替换成你的节点地址。
接着,需要修改下 subgraph 项目中的 package.json 的脚本配置。比如,使用 The Graph 官方的 Hosted Service 时,我的 package.json 中的 scripts 配置是这样的:
"scripts": { "codegen": "graph codegen --output-dir src/types/", "build": "graph build --ipfs https://api.staging.thegraph.com/ipfs/", "create-local": "graph create keeganlee/First --node http://127.0.0.1:8020", "deploy-local": "graph deploy keeganlee/First --debug --ipfs http://localhost:5001 --node http://127.0.0.1:8020/", "deploy": "graph deploy keeganlee/First --debug --ipfs https://api.thegraph.com/ipfs/ --node https://api.thegraph.com/deploy/", "deploy-staging": "graph deploy --debug --ipfs https://api.staging.thegraph.com/ipfs/ --node https://api.staging.thegraph.com/deploy/ keeganlee/First", "prettier": "./node_modules/.bin/prettier —-write '**/*.ts'" },
其中,build、deploy、deploy-staging 这三个命令的 --ipfs 和 --node 参数后面的 URL 都需要更改为自己搭建的私有节点地址,以 deploy 的为例:
"deploy": "graph deploy keeganlee/First --debug --ipfs http://<NODE_IP>:5001 --node http://<NODE_IP>:8020",
之后就可以执行 yarn deploy 命令进行部署了。
The Graph Network
关于去中心化的 The Graph Network,虽然主网已经上线,但目前还没有文档说明如何将 subgraph 部署到 Network,目前那些迁移到了 Network 的 subgraph 都是官方技术团队协同迁移过去的。官方团队人员还表示,最近会等主网表现稳定后,再把其他 subgraph 也迁移到主网。
目前对 Network 最详细的介绍,就是官方文档了:
至于详细内容,我自己还没有深入去研究,所以就不展开了,等以后深入研究后再另外发文讲解这一块。