LOADING STUFF...

Graph开发和部署

Graph开发部署

电报联系方式

Friend.tech是一个去中心化社交网络,它在Coinbase的Layer 2(L2)网络上构建,旨在将社交影响力转化为货币价值。本篇文章将以开发friend.tech项目的子图为例,演示如何进行子图的开发和部署过程。

friend.tech智能合约

首先来看一下合约信息

Graph开发和部署

合约代码

……
contract FriendtechSharesV1 is Ownable {
        ……
        event Trade(address trader, address subject, bool isBuy, uint256 shareAmount, uint256 ethAmount, uint256 protocolEthAmount, uint256 subjectEthAmount, uint256 supply);
        ……
function buyShares(address sharesSubject, uint256 amount) public payable {
            uint256 supply = sharesSupply[sharesSubject];
            require(supply > 0 || sharesSubject == msg.sender, “Only the shares’ subject can buy the first share”);
            uint256 price = getPrice(supply, amount);
            uint256 protocolFee = price * protocolFeePercent / 1 ether;
            uint256 subjectFee = price * subjectFeePercent / 1 ether;
            require(msg.value >= price + protocolFee + subjectFee, “Insufficient payment”);
            sharesBalance[sharesSubject][msg.sender] = sharesBalance[sharesSubject][msg.sender] + amount;
            sharesSupply[sharesSubject] = supply + amount;
            emit Trade(msg.sender, sharesSubject, true, amount, price, protocolFee, subjectFee, supply + amount);
            (bool success1, ) = protocolFeeDestination.call{value: protocolFee}(“”);
            (bool success2, ) = sharesSubject.call{value: subjectFee}(“”);
            require(success1 && success2, “Unable to send funds”);
       }
       function sellShares(address sharesSubject, uint256 amount) public payable {
            uint256 supply = sharesSupply[sharesSubject];
            require(supply > amount, “Cannot sell the last share”);
            uint256 price = getPrice(supply – amount, amount);
            uint256 protocolFee = price * protocolFeePercent / 1 ether;
            uint256 subjectFee = price * subjectFeePercent / 1 ether;
            require(sharesBalance[sharesSubject][msg.sender] >= amount, “Insufficient shares”);
            sharesBalance[sharesSubject][msg.sender] = sharesBalance[sharesSubject][msg.sender] – amount;
            sharesSupply[sharesSubject] = supply – amount;
            emit Trade(msg.sender, sharesSubject, false, amount, price, protocolFee, subjectFee, supply – amount);
            (bool success1, ) = msg.sender.call{value: price – protocolFee – subjectFee}(“”);
            (bool success2, ) = protocolFeeDestination.call{value: protocolFee}(“”);
            (bool success3, ) = sharesSubject.call{value: subjectFee}(“”);
            require(success1 && success2 && success3, “Unable to send funds”);
       }

}

Friend.tech项目的智能合约主要包含两个关键函数:buySharessellShares。用户的交易行为将触发Trade事件,而Trade事件的函数签名记录了与交易相关的信息,即需要进行索引的数据。

创建合约的区块

Graph开发和部署

安装依赖

yarn global add @graphprotocol/graph-cli
yarn global add @graphprotocol/graph-ts

初始化 subgraph 项目

Graph开发和部署

✔ Protocol · ethereum
✔ Product for which to initialize · subgraph-studio
✔ Subgraph slug · FriendtechGraph
✔ Directory to create the subgraph in · FriendtechGraph
✔ Ethereum network · base
✔ Contract address · 0xCF205808Ed36593aa40a44F10c7f7C2F67d4A4d4
✔ Fetching ABI from Etherscan
✖ Failed to fetch Start Block: Failed to fetch contract creation transaction
✔ Do you want to retry? (Y/n) · false
✔ Start Block · 2430439
✔ Contract Name · FriendtechSharesV1
✔ Index contract events as entities (Y/n) · true
Generate subgraph
Write subgraph to directory
✔ Create subgraph scaffold
✔ Initialize networks config
✔ Initialize subgraph repository
✔ Install dependencies with yarn
✔ Generate ABI and schema types with yarn codegen
Add another contract? (y/n):
Subgraph FriendtechGraph created in FriendtechGraph

第7步如果因为网络原因不能获取合约ABI文件,也可以使用本地文件。

项目结构

cd FriendtechGraph
tree -L 1

├── abis
├── generated
├── networks.json
├── node_modules
├── package.json
├── schema.graphql
├── src
├── subgraph.yaml
├── tests
├── tsconfig.json
└── yarn.lock

  1. schema.graphql: 这个文件用于定义Graph实体,类似于在Web2中定义模型。在这里,我们规定了数据的结构和类型,为后续的子图索引和查询提供基础。
  2. subgraph.yaml: 子图清单文件,其中定义了子图索引所需的智能合约,需要关注的事件以及如何将这些事件数据映射到Graph节点存储中,使其可以被查询。这是一个指导文件,告诉系统如何处理区块链上的数据并将其整合到友好的数据模型中。
  3. generated目录: 这个目录包含由系统生成的AssemblyScript类型,类似于模型的CRUD(创建、读取、更新、删除)函数。这些函数用于操作和管理数据,提供了对数据模型的基本操作。
  4. src目录: 在这个目录下,我们可以找到业务逻辑代码。这是实际处理用户交互、智能合约事件触发等的地方。在这里,我们定义了如何处理各种情况,以及如何调用生成的函数来实现相应的功能。

schema.graphql

定义需要索引的数据实体,以及实体之间的关系

type OwnershipTransferred @entity(immutable: true) {
id: Bytes!
previousOwner: Bytes! # address
newOwner: Bytes! # address
blockNumber: BigInt!
blockTimestamp: BigInt!
transactionHash: Bytes!
}

type Trade @entity(immutable: true) {
id: Bytes!
trader: Bytes! # address
subject: Bytes! # address
isBuy: Boolean! # bool
shareAmount: BigInt! # uint256
ethAmount: BigInt! # uint256
protocolEthAmount: BigInt! # uint256
subjectEthAmount: BigInt! # uint256
supply: BigInt! # uint256
blockNumber: BigInt!
blockTimestamp: BigInt!
transactionHash: Bytes!
}

src/subgraph.yaml

从区块链事件中索引数据的具体逻辑, handleTrade 函数会在每次 Trade 事件触发时被调用,然后获取到链上数据存储到子图中。

import {
OwnershipTransferred as OwnershipTransferredEvent,
Trade as TradeEvent
} from “../generated/FriendtechSharesV1/FriendtechSharesV1”
import { OwnershipTransferred, Trade } from “../generated/schema”

export function handleOwnershipTransferred(
event: OwnershipTransferredEvent
): void {
let entity = new OwnershipTransferred(
event.transaction.hash.concatI32(event.logIndex.toI32())
)
entity.previousOwner = event.params.previousOwner
entity.newOwner = event.params.newOwner

entity.blockNumber = event.block.number
entity.blockTimestamp = event.block.timestamp
entity.transactionHash = event.transaction.hash

entity.save()
}

export function handleTrade(event: TradeEvent): void {
let entity = new Trade(
event.transaction.hash.concatI32(event.logIndex.toI32())
)
entity.trader = event.params.trader
entity.subject = event.params.subject
entity.isBuy = event.params.isBuy
entity.shareAmount = event.params.shareAmount
entity.ethAmount = event.params.ethAmount
entity.protocolEthAmount = event.params.protocolEthAmount
entity.subjectEthAmount = event.params.subjectEthAmount
entity.supply = event.params.supply

entity.blockNumber = event.block.number
entity.blockTimestamp = event.block.timestamp
entity.transactionHash = event.transaction.hash

entity.save()
}

代码生成

在friend.tech项目中,对subgraph.yamlschema.graphql文件进行修改后,需要运行yarn codegen以生成相应的AssemblyScript文件,并将其保存在generated目录中。这确保了在更新子图索引和GraphQL模型后,系统能够生成相应的代码以维持代码的一致性。

xxx@Inspiron:~/tmp/FriendtechGraph$ yarn codegen
yarn run v1.22.5
$ graph codegen
Skip migration: Bump mapping apiVersion from 0.0.1 to 0.0.2
Skip migration: Bump mapping apiVersion from 0.0.2 to 0.0.3
Skip migration: Bump mapping apiVersion from 0.0.3 to 0.0.4
Skip migration: Bump mapping apiVersion from 0.0.4 to 0.0.5
Skip migration: Bump mapping apiVersion from 0.0.5 to 0.0.6
Skip migration: Bump manifest specVersion from 0.0.1 to 0.0.2
Skip migration: Bump manifest specVersion from 0.0.2 to 0.0.4
✔ Apply migrations
✔ Load subgraph from subgraph.yaml
Load contract ABI from abis/FriendtechSharesV1.json
✔ Load contract ABIs
Generate types for contract ABI: FriendtechSharesV1 (abis/FriendtechSharesV1.json)
Write types to generated/FriendtechSharesV1/FriendtechSharesV1.ts
✔ Generate types for contract ABIs
✔ Generate types for data source templates
✔ Load data source template ABIs
✔ Generate types for data source template ABIs
✔ Load GraphQL schema from schema.graphql
Write types to generated/schema.ts
✔ Generate types for GraphQL schema

Types generated successfully

编译

将 subgraph 编译为 WebAssembly 等待部署。

xxx@Inspiron:~/tmp/FriendtechGraph$ yarn build
yarn run v1.22.5
$ graph build
Skip migration: Bump mapping apiVersion from 0.0.1 to 0.0.2
Skip migration: Bump mapping apiVersion from 0.0.2 to 0.0.3
Skip migration: Bump mapping apiVersion from 0.0.3 to 0.0.4
Skip migration: Bump mapping apiVersion from 0.0.4 to 0.0.5
Skip migration: Bump mapping apiVersion from 0.0.5 to 0.0.6
Skip migration: Bump manifest specVersion from 0.0.1 to 0.0.2
Skip migration: Bump manifest specVersion from 0.0.2 to 0.0.4
✔ Apply migrations
✔ Load subgraph from subgraph.yaml
Compile data source: FriendtechSharesV1 => build/FriendtechSharesV1/FriendtechSharesV1.wasm
✔ Compile subgraph
Copy schema file build/schema.graphql
Write subgraph file build/FriendtechSharesV1/abis/FriendtechSharesV1.json
Write subgraph manifest build/subgraph.yaml
✔ Write compiled subgraph to build/

Build completed: build/subgraph.yaml

部署

可以把 subgraph 部署到本地,也可以使用托管服务,这里演示使用 graph 官网提供的托管服务——子图工作室 。

Graph开发和部署

连接钱包并签名后,就可以创建子图项目了。

Graph开发和部署

右边可以看到相关的操作命令:

Graph开发和部署

使用 AUTH & DEPLOY 栏的示例命令进行部署,因为已经编译过,下面跳过编译命令:

xxx@Inspiron:~/tmp/FriendtechGraph$ graph auth –studio fffff2e2e969c873d1daf88c27c2b238
Deploy key set for https://api.studio.thegraph.com/deploy/

xxx@Inspiron:~/tmp/FriendtechGraph$ graph deploy –studio friendtechgraph
Which version label to use? (e.g. “v0.0.1”): v0.0.1
Skip migration: Bump mapping apiVersion from 0.0.1 to 0.0.2
Skip migration: Bump mapping apiVersion from 0.0.2 to 0.0.3
Skip migration: Bump mapping apiVersion from 0.0.3 to 0.0.4
Skip migration: Bump mapping apiVersion from 0.0.4 to 0.0.5
Skip migration: Bump mapping apiVersion from 0.0.5 to 0.0.6
Skip migration: Bump manifest specVersion from 0.0.1 to 0.0.2
Skip migration: Bump manifest specVersion from 0.0.2 to 0.0.4
✔ Apply migrations
✔ Load subgraph from subgraph.yaml
Compile data source: FriendtechSharesV1 => build/FriendtechSharesV1/FriendtechSharesV1.wasm
✔ Compile subgraph
Copy schema file build/schema.graphql
Write subgraph file build/FriendtechSharesV1/abis/FriendtechSharesV1.json
Write subgraph manifest build/subgraph.yaml
✔ Write compiled subgraph to build/
Add file to IPFS build/schema.graphql
.. QmU2ns3ySUcCQ7ZRcY4qUDnaToSwx1nxGuagFHBJWg9UFZ
Add file to IPFS build/FriendtechSharesV1/abis/FriendtechSharesV1.json
.. QmfA1DYEazwF9cx6rJy1hTj5ToVTz1GySGeaETJ25S7hJR
Add file to IPFS build/FriendtechSharesV1/FriendtechSharesV1.wasm
.. QmU3PEhQaZ2PqZiEfreGvSSSXAMhgVpbygbJbL8uTy9FLy
✔ Upload subgraph to IPFS

Build completed: QmW1eEAf6aeS11kjGgZFfA9Y1E1t3gNFmHYuvX1sZvbcbk

Deployed to https://thegraph.com/studio/subgraph/friendtechgraph

Subgraph endpoints:
Queries (HTTP): https://api.studio.thegraph.com/query/61273/friendtechgraph/v0.0.1

可以在子图工作室看到已经完成了部署,且数据已经完成了同步。

Graph开发和部署

查询数据

可以使用提供的 QUERY URL 在 GraphiQL 中查询数据:

Graph开发和部署

部署完后可以进行测试,如果想在将子图发布到网络之前对其进行测试,也可以在 Subgraph Playground 中执行此操作或查看日志。

开发联系:DEXDAO

 

© 版权声明

相关文章

暂无评论

暂无评论...