【SubGraph作成からフロント表示まで】TheGraphの始め方
The Graph について
スマートコントラクトのEventに合わせて情報を整形し、保存しAPIとして返してくれるサービスです。The Graphを用いることで、スマコンの情報を直接getter関数で読みにいったり、フロントで無駄に整形せずに済みます。
記事の内容について
The Graphの基本的な使い方が分かるハンズオンになっています。実際のコントラクトや内容に関しては、こちらの記事を引用させて頂いております。その上で動かない部分やわかりづらい部分に説明を加えて紹介する形にしております。
Step1 -The Graphの登録&プロジェクト作成-
まずはThe Graphの公式ページ右上「product」から「SubGraph Studio」を選択しMetamaskを接続していきます。
SubGraph Studio右上から「Create Project」を選択することで、SubGraphの元を作成することができます。そうするとAPI作成に必要なsubgraph slag
やdeploy key
などを取得することができます。
Step2 -contractをデプロイ&ABI取得-
- Remixを使ってcontractをデプロイ
- HardhatでcontractをコンパイルしABIを取得
RemixとHardhatの両方を使う理由は、Remixで出力したABIをTheGraphが読み込んでくれなかったことと、Hardhatでデプロイする場合INFURAなどの登録が必要な外部サービスが必要になるため、ハンズオンとして適切ではないと思い、両方使うことにしました。
Remixにコードを貼りつけてデプロイ
Remixはブラウザで簡単にSolidityを書けるツールです。今回はGoerliでデプロイしていきます。デプロイする際にコインの名前とシンボルを入力する必要があるので、名前を「TestCoin」、シンボルを「TC」にしてデプロイしました。(命名は自由です)
pragma solidity ^0.8.9;
import "@OpenZeppelin/contracts/token/ERC20/ERC20.sol";
contract AdventCalendarToken is ERC20 {
uint8 private _decimals = 18;
address account = msg.sender;
uint value = 10000000000000000000000;
constructor(string memory _name, string memory _symbol) ERC20( _name, _symbol) public {
_mint(account, value);
}
}
Remixでデプロイしたcontractアドレスとブロックナンバーを確認してメモ
コントラクトアドレスとデプロイしたブロックナンバーを後で使うのでメモしておきます。ブロックナンバーはRemixのコンソールログに書いてあります。
Hardhatの初期設定
とりあえずRemixは横に置きつつ、HardhatでABIを取得していきます。自分はVScodeを使っています。
#メインディレクトリの作成
mkdir the-graph-test
cd the-graph-test
#package.jsonの作成
npm init --yes
#hardhatのインストール
npm install --save-dev hardhat
#hardhatの初期化
#※Create an empty hardhat.config.jsを選択
npx hardhat
スマコンファイルの作成
#solファイルの作成
touch coin.sol
#@OpenZeppelin/contractsのインストール
npm install @openzeppelin/contracts
スマコンの記述
pragma solidity ^0.8.9;
import "@OpenZeppelin/contracts/token/ERC20/ERC20.sol";
contract AdventCalendarToken is ERC20 {
uint8 private _decimals = 18;
address account = msg.sender;
uint value = 10000000000000000000000;
constructor(string memory _name, string memory _symbol) ERC20( _name, _symbol) public {
_mint(account, value);
}
}
スマコンのコンパイル&デプロイ
#hardhatでスマコンをコンパイル
npx hardhat compile
ファイルからABIを確認
artifacts/[コントラクトファイル名]/
の中に[コントラクト名].json
が生成されていることを確認してください。これがTheGraphに読み込ませるABIファイルです。
Step3 -TheGraphの準備-
TheGraphの初期設定
#必要なライブラリをインストール
npm install -g @graphprotocol/graph-cli
#初期設定
graph init --studio coin
初期設定では利用するチェーンやコントラクトアドレス、ABIのパスなど色々聞かれます。特に自分が苦戦したのはABIで、上記の[コントラクト名].json
を選択して「Copy Path」で貼り付けると上手くいきます。
返ってきてほしいデータへの整形ロジック
type AccountTokenBalance @entity {
id: ID!
token: String!
balance: BigInt!
}
#schema.graphqlから自動で生成させる
graph codegen
import { BigInt } from "@graphprotocol/graph-ts";
import { Transfer } from "../generated/AdventCalendarToken/AdventCalendarToken";
import { AccountTokenBalance } from "../generated/schema";
// Transferのイベントが発火された時に実行されるfunction
export function handleTransfer(event: Transfer): void {
let tokenId = event.address.toHex();
let toAddress = event.params.to.toHex();
let toAccount = AccountTokenBalance.load(toAddress);
if (toAccount == null) {
toAccount = new AccountTokenBalance(toAddress);
toAccount.balance = BigInt.fromI32(0);
}
toAccount.balance = toAccount.balance.plus(event.params.value);
toAccount.token = tokenId;
toAccount.save();
let fromAddress = event.params.from.toHex();
if (fromAddress == "0x0000000000000000000000000000000000000000") {
return;
}
let fromAccount = AccountTokenBalance.load(fromAddress);
if (fromAccount == null) {
fromAccount = new AccountTokenBalance(fromAddress);
fromAccount.balance = BigInt.fromI32(0);
}
fromAccount.balance = fromAccount.balance.minus(event.params.value);
fromAccount.token = tokenId;
fromAccount.save();
}
注意:
- httpリクエスト系は送れません。(他のAPIは呼べない)
- typescriptみたいな感じですが微妙に違うためライブラリが使えないことがある。
- キャストの仕方が微妙に違う。
キャストや整形に関する参考記事
デプロイしてAPIを作成
#デプロイキーで認証
graph auth --studio 363563505......5f7cd1179b7
#coinファイルに移動
cd coin
#ビルド
graph codegen && graph build
#デプロイ
graph deploy --studio yomiswap
APIを確認してメモ
https://api.studio.thegraph.com/query/34004/[プロジェクト名]/[バージョン]
Step4 -フロントでAPIを呼び出す-
ReactかNextのプロジェクトを作成
#Reactの場合
npx create-react-app coin
#Nextの場合
npx create-next-app coin
_app.jsxにAPIを登録
#The Graphに必要なライブラリを追加
npm install @apollo/client
import { ApolloClient, ApolloProvider, InMemoryCache } from '@apollo/client'
const client = new ApolloClient({
cache: new InMemoryCache(),
uri: 'https://api.studio.thegraph.com/query/34004/[プロジェクト名]/[バージョン名]',
})
function App({pageProps}){
return(
<ApolloProvider client={client}>
<Component {...pageProps} >
</ApolloProvider>
)
}
graphqlファイルを準備
import { gql } from "apollo-boost";
const GET_TRANSFERS = gql`
{
accountTokenBalances(orderBy: balance) {
id
token
balance
}
}
export default GET_TRANSFERS;
表示したいコンポーネントに実装
import { useQuery } from '@apollo/client'
import GET_TRANSFERS from '../../../graphql/subgraph'
const Test = () => {
const { loading, error, data } = useQuery(GET_TRANSFERS)
const [eventList, setEventList] = useState<History[]>([])
useEffect(() => {
if (!loading && !error && data) {
setTokenHolders(data.accountTokenBalances);
console.log(data);
}
}, [loading, error, data]);
}
終わりに
よく友人のエンジニアから「TheGraphに興味があるけど始められない...」というお話をよく聞くので、そこの敷居が少しでも下がらないかと思い、書かせて頂きました。これで少しでもTheGraphを触れるエンジニアが増えることを祈ります。
Discussion