![見出し画像](https://assets.st-note.com/production/uploads/images/70229373/rectangle_large_type_2_906932a35753581446f1f71c0e480009.jpeg?width=1200)
【保存版】The Graphでサブグラフを作ってみよう。
こんにちは、CryptoGamesの高橋です。
クリスペの会社です。
今回、サブグラフ作成のYouTubeがありましたので、それに沿って記事を作りました。
また、自分の以前の記事でもサブグラフの作り方をみておりますので、よかったらそちらもご参照ください。
では、やっていきます。
1 The Graph上でサブグラフを作ってみよう
まずは、下のようにサブグラフを作ってみます。
こんな感じでサブグラフが作成できました。
2 graph-cliのインストール
次のようにインストールを行います。
npm install -g @graphprotocol/graph-cli
エラーは特に発生していなさそうです。
念の為、「graph」と打ってみて、「welcome to ~ 」と表示されれば大丈夫です。
3 新しいサブグラフの作成
「graph init」で新しいサブグラフを作成していきます。
ytakahashi@yuki subgraph % graph init --contract-name Token --index-events --product subgraph-studio \
> --from -contract 0xabEFBc9fD2F806065b4f3C237d4b59D9A97Bcac7
オプション・引数として次を設定します。
① コントラクト名
② 何をindexするか(events)
③ プロダクト(subgraph-studio)
④ 使用するコントラクト
(今回は、zoraのコントラクトを使用しています。)
その後、いくつか質問が出るので答えていきます。
左のようなディレクトリができたら完成です。
4 schema.graphqlの作成
次に、schema.graphqlでイベントから何を取得するのかを書いていきます。
最初にあったものは消して、次のように作成しました。
今回は
①Token
②User
という2つのタイプで値を取得していきます。
ちなみに、この2つは関連しています。
例えば、7行目の「creator」は「User」タイプであり、13行目のtokensは「Token」タイプです。(1対多の関係)
type Token @entity {
id: ID!
tokenId: BigInt!
contentURI: String!
metadataURI: String!
createdAtTimestamp: BigInt!
creator: User!
owner: User!
}
type User @entity {
id: ID!
tokens: [Token!]! @derivedFrom(field: "owner")
created: [Token!]! @derivedFrom(field: "creator")
}
5 subgraph.yaml
では次に、構成が書かれる「subgraph.yaml」を修正していきます。
まずは下のように「startBlock」を追加します。
これにより、どのブロック以降の情報をとってくれば良いのかを指定できるので、無駄な処理がなくなります。
次は「entities」と「eventHandlers」です。
「entities」は上の章の「schema.graphql」で設定した際のタイプを選択し、「eventHandlers」では、不要なイベントを削除します。
6 graph codegenでtsファイルを作成
第4・5章で構成を設定できたので、これをtsファイルにします。
「subgraph.yaml」がある階層に移動し、
graph codegen
を入力すると、下のように2つのtsファイルができます。
7 mapping.tsを作成
おそらく一番の肝である、mapping.tsをやっていきます。
ここでは、イベントを元にして、どのように必要なデータを取得していくのかを書いていきます。
こちらはコード量が多かったので、コードは記事の末尾に載せております。
7−1 import
まずはimportからです。
このように、上の章で作成した2つのtsファイルからインポートを行います。
7ー2 functionの作成(token)
では、まずはTransferイベントによって発火する関数を書いていきましょう。
やっている処理しては、10行目の「token」に「Token」から呼び込んだオブジェクトを格納しています。
event.params.~で取得しているのはこのイベント自体(Transfer)がとってくるパラメータです。
下のToken.tsを見ると、
このイベントによって
① from
② to
③ tokenId
を取ってくるのがわかり、このパラメータを利用しています。
一方、Tokenの内容は「schema.ts」にあり、これは第4章の「schema.graphql」で設定した内容です。
Tokenには「id」を除いて
① tokenId
② contentURI
③ metadataURI
④ createdAtTimestamp
⑤ creator
⑥ owner
があり、mapping.tsの11行目以降で、tokenが取得できなかった時に、これらの値を入れています。
7ー3 functionの作成(user)
同様の処理ではありますが、userの方も見てみましょう。
schema.tsのUserを見てみましょう。
あれ?3つ設定したような。。と思ったので、「schema.ts」の元となった「schema.graphql」を見てみましょう。
これを見ると、確かに「ID」を含めて、3つ設定されておりますが、「Token」に紐づいているようです。
「handleTokenURIUpdated」関数については、ここでは省略します。(下にコードはあります。)
8 デプロイをしよう
mapping.tsもできたので、デプロイをしていきます。
デプロイの仕方はサブグラフに書いてあります。
こちらに書いてありますので、このまま実行すれば作成ができます。
下のように実行してみました。
少し待つと、このように同期も完了しました。
9 実際にデータを取ってみよう
「playground」の紫のボタンを押してみましょう。
このようにデータが取ってこれましたね。
また、取ってきたいデータや順番の入れ替えなどをしたい場合には、下のようにクエリを変更します。
これも大丈夫そうです。
以上でサブグラフの作成について終了します。
最後までお読みいただき、ありがとうございました。
以下は、参考に「mapping.ts」のコードです。
import {
TokenURIUpdated as TokenURIUpdatedEvent,
Transfer as TransferEvent,
Token as TokenContract,
} from "../generated/Token/Token";
import { Token, User } from "../generated/schema";
export function handleTransfer(event: TransferEvent): void {
let token = Token.load(event.params.tokenId.toString());
if (!token) {
token = new Token(event.params.to.toString());
token.creator = event.params.to.toHexString();
token.tokenId = event.params.tokenId;
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();
}
}
export function handleTokenURIUpdated(event: TokenURIUpdatedEvent): void {
let token = Token.load(event.params._tokenId.toString());
if (!token) {
token = new Token(event.params._tokenId.toString());
token.save();
}
token.contentURI = event.params._uri;
token.save();
}
いいなと思ったら応援しよう!
![ユウキ](https://assets.st-note.com/production/uploads/images/52347520/profile_e7d36b385c74618d7fec56da47f68a35.jpeg?width=600&crop=1:1,smart)