# or
$ yarn global add @graphprotocol/graph-cli

安裝Graph CLI后,您可以使用Graph CLIinit命令初始化一個新的子圖。

兩種方法:

1 從示例子圖中

$ graph init --from-example <GITHUB_USERNAME>/<SUBGRAPH_NAME> [<DIRECTORY>]

2 來自現有的智能合約
如果您已經將智能合約部署到以太坊主網或測試網之一,則從該合約初始化新的子圖是啟動和運行的簡便方法。

$ graph init --from-contract <CONTRACT_ADDRESS> \
[--network <ETHEREUM_NETWORK>] \
[--abi <FILE>] \
<GITHUB_USER>/<SUBGRAPH_NAME> [<DIRECTORY>]


在我們的例子中,我們將使用Zora令牌合約,因此我們可以通過使用–from-contract標志傳遞合約地址來從該合約地址進行初始化:

$ graph init --from-contract 0xabEFBc9fD2F806065b4f3C237d4b59D9A97Bcac7 --network mainnet  \
--contract-name Token --index-events
? Subgraph name ? your-username/Zoranftsubgraph
? Directory to create the subgraph in ? Zoranftsubgraph
? Ethereum network ? Mainnet
? Contract address ? 0xabEFBc9fD2F806065b4f3C237d4b59D9A97Bcac7
? Contract Name · Token


此命令將根據作為參數傳入的合同地址生成一個基本子圖–from-contract。通過使用此合同地址,CLI將在項目中初始化一些內容以幫助您入門。
子圖的主要配置和定義位于subgraph.yaml文件中,子圖代碼庫由幾個文件組成:

我們將使用的subgraph.yaml中的條目是:

定義實體

使用The Graph,您可以在schema.graphql中定義實體類型,并且Graph Node將生成用于查詢該實體類型的單個實例和集合的頂級字段。每種應為實體的類型都必須使用@entity指令進行注釋。
我們將要建立索引的實體/數據是Token和User。這樣,我們可以索引用戶以及用戶自己創建的令牌。
為此,請使用以下代碼更新schema.graphql:

type Token @entity {
id: ID!
tokenID: BigInt!
contentURI: String!
metadataURI: String!
creator: User!
owner: User!
}
type User @entity {
id: ID!
tokens: [Token!]! @derivedFrom(field: "owner")
created: [Token!]! @derivedFrom(field: "creator")
}

通過@derivedFrom(來自文檔)通過“關系” 

可以通過@derivedFrom字段在實體上定義反向查找。這會在實體上創建一個虛擬字段,可以查詢該虛擬字段,但無法通過映射API手動設置。
相反,它是從另一個實體上定義的關系派生的。對于此類關系,存儲關系的兩邊幾乎沒有意義,并且僅存儲一側而派生另一側時,索引和查詢性能都將更好。
現在,我們已經為我們的應用程序創建了GraphQL模式,我們可以在本地生成實體,以開始在mappingsCLI所創建的實體中使用:

graph codegen

為了使工作中的智能合約,事件和實體變得容易且類型安全,Graph CLI從子圖的GraphQL模式和數據源中包含的合約ABI的組合中生成AssemblyScript類型。

使用實體和映射更新子圖

現在,我們可以配置subgraph.yaml以使用我們剛剛創建的實體并配置它們的映射。
為此,請先dataSources.mapping.entities使用User和Token實體更新字段:

entities:
- Token
- User


接下來,更新,dataSources.mapping.eventHandlers使其僅包括以下兩個事件處理程序:

eventHandlers:
- event: TokenURIUpdated(indexed uint256,address,string)
handler: handleTokenURIUpdated
- event: Transfer(indexed address,indexed address,indexed uint256)
handler: handleTransfer


最后,更新配置以添加startBlock:

source:
address: "0xabEFBc9fD2F806065b4f3C237d4b59D9A97Bcac7"
abi: Token
startBlock: 11565020

Assemblyscript映射

接下來,打開src / mappings.ts來編寫我們在子圖subgraph中定義的映射eventHandlers。
使用以下代碼更新文件:

import {
TokenURIUpdated as TokenURIUpdatedEvent,
Transfer as TransferEvent,
Token as TokenContract
} from "../generated/Token/Token"
import {
Token, User
} from '../generated/schema'
export function handleTokenURIUpdated(event: TokenURIUpdatedEvent): void {
let token = Token.load(event.params._tokenId.toString());
token.contentURI = event.params._uri;
token.save();
}
export function handleTransfer(event: TransferEvent): void {
let token = Token.load(event.params.tokenId.toString());
if (!token) {
token = new Token(event.params.tokenId.toString());
token.creator = event.params.to.toHexString();
token.tokenID = event.params.tokenId;
let tokenContract = TokenContract.bind(event.address);
token.contentURI = tokenContract.tokenURI(event.params.tokenId);
token.metadataURI = tokenContract.tokenMetadataURI(event.params.tokenId);
}
token.owner = event.params.to.toHexString();
token.save();
let user = User.load(event.params.to.toHexString());
if (!user) {
user = new User(event.params.to.toHexString());
user.save();
}
}

運行構建

接下來,讓我們運行一個構建以確保正確配置了所有內容。為此,請運行以下build命令:

$ graph build

如果構建成功,則應該在根目錄中看到一個新的構建文件夾。

部署子圖

要進行部署,我們可以deploy使用Graph CLI運行該命令。要進行部署,您首先需要為在Graph Explorer中創建的子圖復制Access令牌:

接下來,運行以下命令:

$ graph auth https://api.thegraph.com/deploy/ <ACCESS_TOKEN>
$ yarn deploy


部署子圖后,您應該看到它顯示在您的儀表板中:

當您單擊子圖時,它應該打開Graph資源管理器:

查詢數據

現在我們位于儀表板中,我們應該能夠開始查詢數據了。運行以下查詢以獲取令牌及其元數據的列表:

{
tokens {
id
tokenID
contentURI
metadataURI
}
}


我們還可以配置訂單方向:

{
tokens(
orderBy:id,
orderDirection: desc
) {
id
tokenID
contentURI
metadataURI
}
}


或選擇跳過某些結果以實現一些基本分頁:

{
tokens(
skip: 100,
orderBy:id,
orderDirection: desc
) {
id
tokenID
contentURI
metadataURI
}
}


或查詢用戶及其相關內容:

{
users {
id
tokens {
id
contentURI
}
}
}

更新子圖

如果我們想要對子圖進行一些更改然后重新部署,我們應該怎么辦?假設我們要向子圖添加新功能,假設我們除了現有的查詢功能外,還想添加該功能以按創建NFT的時間戳進行排序。
為此,我們需要先向實體添加一個新createdAtTimestamp字段Token:

type Token @entity {
id: ID!
tokenID: BigInt!
contentURI: String!
metadataURI: String!
creator: User!
owner: User!
"Add new createdAtTimesamp field"
createdAtTimestamp: BigInt!
}


現在,我們可以重新運行代碼生成:

graph codegen

接下來,我們需要更新映射以保存此新字段:

// update the handleTransfer function to add the createdAtTimestamp to the token object
export function handleTransfer(event: TransferEvent): void {
let token = Token.load(event.params.tokenId.toString());
if (!token) {
token = new Token(event.params.tokenId.toString());
token.creator = event.params.to.toHexString();
token.tokenID = event.params.tokenId;
// Add the createdAtTimestamp to the token object
token.createdAtTimestamp = event.block.timestamp;
let tokenContract = TokenContract.bind(event.address);
token.contentURI = tokenContract.tokenURI(event.params.tokenId);
token.metadataURI = tokenContract.tokenMetadataURI(event.params.tokenId);
}
token.owner = event.params.to.toHexString();
token.save();
let user = User.load(event.params.to.toHexString());
if (!user) {
user = new User(event.params.to.toHexString());
user.save();
}
}


現在我們可以重新部署子圖:

$ yarn deploy

子圖重新部署后,我們現在可以按時間戳查詢以查看最近創建的NFTS:

{
tokens(
orderBy:createdAtTimestamp,
orderDirection: desc
) {
id
tokenID
contentURI
metadataURI
}
}}

文章轉自微信公眾號@區塊鏈研究實驗室

上一篇:

GraphQL 初體驗,Node.js 構建 GraphQL API 指南

下一篇:

怎樣設計安全的GraphQL API?
#你可能也喜歡這些API文章!

我們有何不同?

API服務商零注冊

多API并行試用

數據驅動選型,提升決策效率

查看全部API→
??

熱門場景實測,選對API

#AI文本生成大模型API

對比大模型API的內容創意新穎性、情感共鳴力、商業轉化潛力

25個渠道
一鍵對比試用API 限時免費

#AI深度推理大模型API

對比大模型API的邏輯推理準確性、分析深度、可視化建議合理性

10個渠道
一鍵對比試用API 限時免費