Upgrade to Pro — share decks privately, control downloads, hide ads and more …

NFTのインデクシングとGraphQLのすゝめ / NFT indexing and GraphQL

NFTのインデクシングとGraphQLのすゝめ / NFT indexing and GraphQL

no plan inc. CTO @_serinuntius

2022.07.12, TOKYO BLOCKCHAIN TECH MEETUP 2022 登壇資料

serinuntius

July 12, 2022
Tweet

More Decks by serinuntius

Other Decks in Technology

Transcript

  1. NFTのインデクシングと
    GraphQLのすゝめ
    Presentation by @_serinuntius
    2022.07.12, TOKYO BLOCKCHAIN TECH MEETUP 2022

    View full-size slide

  2. 今日話すこと
    自己紹介
    NFTのインデクシングとは?
    なぜインデクシングが必要なのか?
    インデクシングの実装
    GraphQLのすゝめ
    まとめ

    View full-size slide

  3. 自己紹介
    芹川葵: @_serinuntius
    no plan inc. CTO
    JPYC 技術顧問
    趣味:
    キャンプ
    スノボ

    View full-size slide

  4. 興味ある技術とか、最近やってる技術とか(雑)

    View full-size slide

  5. NFTのインデクシングとは?
    NFTが持つ情報や付随する情報を、検索し易いよ
    うにDBに格納すること
    tokenId address metadata
    1 0xabc {"image": "ipfs://..."}
    2 0x123 {"image": "ipfs://..."}
    3 0x456 {"image": "ipfs://..."}
    4 0x789 {"image": "ipfs://..."}

    View full-size slide

  6. なぜインデクシングが必要なのか?
    一般的にNFTの情報にアクセスするには、コントラクトに生えてるview関数を叩く


















    function ownerOf(uint256 tokenId) public view virtual override returns (address) {
    address owner = _owners[tokenId];
    require(owner != address(0), "ERC721: invalid token ID");
    return owner;
    }
    function tokenURI(uint256 tokenId) public view virtual override returns (string memory) {
    _requireMinted(tokenId);
    string memory baseURI = _baseURI();
    return bytes(baseURI).length > 0 ? string(abi.encodePacked(baseURI, tokenId.toString())) : "";
    }

    View full-size slide

  7. なぜインデクシングが必要なのか?
    一般的にNFTの情報にアクセスするには、コントラクトに生えてるview関数を叩く
    function ownerOf(uint256 tokenId) public view virtual override returns (address) {

    address owner = _owners[tokenId];

    require(owner != address(0), "ERC721: invalid token ID");

    return owner;

    }









    function tokenURI(uint256 tokenId) public view virtual override returns (string memory) {
    _requireMinted(tokenId);
    string memory baseURI = _baseURI();
    return bytes(baseURI).length > 0 ? string(abi.encodePacked(baseURI, tokenId.toString())) : "";
    }

    View full-size slide

  8. なぜインデクシングが必要なのか?
    一般的にNFTの情報にアクセスするには、コントラクトに生えてるview関数を叩く










    function tokenURI(uint256 tokenId) public view virtual override returns (string memory) {

    _requireMinted(tokenId);

    string memory baseURI = _baseURI();

    return bytes(baseURI).length > 0 ? string(abi.encodePacked(baseURI, tokenId.toString())) : "";

    }
    function ownerOf(uint256 tokenId) public view virtual override returns (address) {
    address owner = _owners[tokenId];
    require(owner != address(0), "ERC721: invalid token ID");
    return owner;
    }

    View full-size slide

  9. なぜインデクシングが必要なのか?
    一般的にNFTの情報にアクセスするには、コントラクトに生えてるview関数を叩く
    function ownerOf(uint256 tokenId) public view virtual override returns (address) {

    address owner = _owners[tokenId];

    require(owner != address(0), "ERC721: invalid token ID");

    return owner;

    }

    function tokenURI(uint256 tokenId) public view virtual override returns (string memory) {

    _requireMinted(tokenId);

    string memory baseURI = _baseURI();

    return bytes(baseURI).length > 0 ? string(abi.encodePacked(baseURI, tokenId.toString())) : "";

    }

    View full-size slide

  10. なぜインデクシングが必要なのか?
    一般的にNFTの情報にアクセスするには、コントラクトに生えてるview関数を叩く
    情報が欲しくなった時にview関数を叩きまくるのは色々と現実的ではない
    ノードの負担増🆙, Infura, Alchemy等のノードプロバイダーのコスト増🆙
    時間もかかる
    function ownerOf(uint256 tokenId) public view virtual override returns (address) {

    address owner = _owners[tokenId];

    require(owner != address(0), "ERC721: invalid token ID");

    return owner;

    }

    function tokenURI(uint256 tokenId) public view virtual override returns (string memory) {

    _requireMinted(tokenId);

    string memory baseURI = _baseURI();

    return bytes(baseURI).length > 0 ? string(abi.encodePacked(baseURI, tokenId.toString())) : "";

    }

    View full-size slide

  11. なぜインデクシングが必要なのか?
    一般的にNFTの情報にアクセスするには、コントラクトに生えてるview関数を叩く
    情報が欲しくなった時にview関数を叩きまくるのは色々と現実的ではない
    ノードの負担増🆙, Infura, Alchemy等のノードプロバイダーのコスト増🆙
    時間もかかる
    ERC1155対応の闇😈
    function ownerOf(uint256 tokenId) public view virtual override returns (address) {

    address owner = _owners[tokenId];

    require(owner != address(0), "ERC721: invalid token ID");

    return owner;

    }

    function tokenURI(uint256 tokenId) public view virtual override returns (string memory) {

    _requireMinted(tokenId);

    string memory baseURI = _baseURI();

    return bytes(baseURI).length > 0 ? string(abi.encodePacked(baseURI, tokenId.toString())) : "";

    }

    View full-size slide

  12. ERC1155対応の闇😈

    View full-size slide

  13. ERC1155対応の闇😈
    ERC721みたいな
    ownerOf(tokenId)
    が生えてないので、
    tokenId
    の所有者情報をview関数だけでは
    調べることができない😇
    ` ` ` `

    View full-size slide

  14. ERC1155対応の闇😈
    ERC721みたいな
    ownerOf(tokenId)
    が生えてないので、
    tokenId
    の所有者情報をview関数だけでは
    調べることができない😇
    name()
    が生えてないのも地味にだるい
    ノードの情報だけでは何のコントラクトなのかわからない
    ERC721は規格としてマストにはなってないものの、OpenZeppelinの
    ERC721Metadata
    が普及して
    いるため、大体取れる気がする
    ` ` ` `
    ` `
    ` `

    View full-size slide

  15. どうやってインデクシングするのか?

    View full-size slide

  16. 闇の魔術😈に対する防衛術をお教えします👍

    View full-size slide

  17. インデクシングの実装

    View full-size slide

  18. インデクシングの実装
    EVMには 「event」 という概念がある

    View full-size slide

  19. インデクシングの実装
    EVMには 「event」 という概念がある
    ノードに対してイベントをリッスンしておくことで、コントラクトからイベントが発火した時に何かを実行
    できる

    View full-size slide

  20. インデクシングの実装
    EVMには 「event」 という概念がある
    ノードに対してイベントをリッスンしておくことで、コントラクトからイベントが発火した時に何かを実行
    できる
    ex) ERC721
    event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);

    View full-size slide

  21. インデクシングの実装
    EVMには 「event」 という概念がある
    ノードに対してイベントをリッスンしておくことで、コントラクトからイベントが発火した時に何かを実行
    できる
    ex) ERC721
    indexed
    というキーワードをつけると、その変数は検索できるようになる
    event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);
    ` `

    View full-size slide

  22. インデクシングの実装
    EVMには 「event」 という概念がある
    ノードに対してイベントをリッスンしておくことで、コントラクトからイベントが発火した時に何かを実行
    できる
    ex) ERC721
    indexed
    というキーワードをつけると、その変数は検索できるようになる
    eth_getLogs
    というAPIを呼び出すことによってイベントを取得できる
    event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);
    ` `
    ` `

    View full-size slide

  23. インデクシングの実装
    EVMには 「event」 という概念がある
    ノードに対してイベントをリッスンしておくことで、コントラクトからイベントが発火した時に何かを実行
    できる
    ex) ERC721
    indexed
    というキーワードをつけると、その変数は検索できるようになる
    eth_getLogs
    というAPIを呼び出すことによってイベントを取得できる
    どのブロック高でそのイベントが発生したかがわかる
    event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);
    ` `
    ` `

    View full-size slide

  24. インデクシングの実装 - ERC721

    View full-size slide

  25. インデクシングの実装 - ERC721
    1ブロック目から、

    View full-size slide

  26. インデクシングの実装 - ERC721
    1ブロック目から、
    event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);

    View full-size slide

  27. インデクシングの実装 - ERC721
    1ブロック目から、
    これを順に追って行けば良い
    event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);

    View full-size slide

  28. インデクシングの実装 - ERC721
    1ブロック目から、
    これを順に追って行けば良い
    最後に同期したブロック高をdbに入れて、次回以降は差分更新で良い
    event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);

    View full-size slide

  29. インデクシングの実装 - ERC1155

    View full-size slide

  30. インデクシングの実装 - ERC1155
    ERC1155の場合はイベントが2種類ある

    View full-size slide

  31. インデクシングの実装 - ERC1155
    ERC1155の場合はイベントが2種類ある














    event TransferSingle(address indexed operator, address indexed from, address indexed to, uint256 id, uint256 value);
    event TransferBatch(
    address indexed operator,
    address indexed from,
    address indexed to,
    uint256[] ids,
    uint256[] values
    );

    View full-size slide

  32. インデクシングの実装 - ERC1155
    ERC1155の場合はイベントが2種類ある
    event TransferSingle(address indexed operator, address indexed from, address indexed to, uint256 id, uint256 value);













    event TransferBatch(
    address indexed operator,
    address indexed from,
    address indexed to,
    uint256[] ids,
    uint256[] values
    );

    View full-size slide

  33. インデクシングの実装 - ERC1155
    ERC1155の場合はイベントが2種類ある


    event TransferBatch(

    address indexed operator,

    address indexed from,

    address indexed to,

    uint256[] ids,

    uint256[] values

    );
    event TransferSingle(address indexed operator, address indexed from, address indexed to, uint256 id, uint256 value);

    View full-size slide

  34. インデクシングの実装 - ERC1155
    ERC1155の場合はイベントが2種類ある
    event TransferSingle(address indexed operator, address indexed from, address indexed to, uint256 id, uint256 value);

    event TransferBatch(

    address indexed operator,

    address indexed from,

    address indexed to,

    uint256[] ids,

    uint256[] values

    );

    View full-size slide

  35. インデクシングの実装 - ERC1155
    ERC1155の場合はイベントが2種類ある
    これらを順に追って行けば良い
    event TransferSingle(address indexed operator, address indexed from, address indexed to, uint256 id, uint256 value);

    event TransferBatch(

    address indexed operator,

    address indexed from,

    address indexed to,

    uint256[] ids,

    uint256[] values

    );

    View full-size slide

  36. GraphQLのすゝめ (時間なかった)
    先程行ったインデクシングでDBに保管してGraphQLで返すように実装してみました
    型付のクライアントが自動生成できるのでオススメ🔥
    Nestjs / PlanetScale / Prisma / Cloud Run 辺りで実装しています

    View full-size slide

  37. この辺りを全部気をつけて

    実装するの面倒では?🤔🤔🤔

    View full-size slide

  38. その通り!

    View full-size slide

  39. 面倒ごとを全部うちが引き受けて

    インデクシングするSaaS始めます!

    View full-size slide

  40. NFT GraphQL API (仮)

    View full-size slide

  41. NFT GraphQL API (仮)
    ⛓ 任意のEVM互換のチェーンに対応できる(サポートして欲しいチェーンがあればお気軽に連絡くださ
    い)

    View full-size slide

  42. NFT GraphQL API (仮)
    ⛓ 任意のEVM互換のチェーンに対応できる(サポートして欲しいチェーンがあればお気軽に連絡くださ
    い)
    💰 実装コストやら、ノードのメンテコストやら考えると圧倒的コスパ

    View full-size slide

  43. NFT GraphQL API (仮)
    ⛓ 任意のEVM互換のチェーンに対応できる(サポートして欲しいチェーンがあればお気軽に連絡くださ
    い)
    💰 実装コストやら、ノードのメンテコストやら考えると圧倒的コスパ
    ¥ ボラの高い草コインじゃなくて、日本円で払えます(円も実質草コイ・・・🤫

    View full-size slide

  44. NFT GraphQL API (仮)
    ⛓ 任意のEVM互換のチェーンに対応できる(サポートして欲しいチェーンがあればお気軽に連絡くださ
    い)
    💰 実装コストやら、ノードのメンテコストやら考えると圧倒的コスパ
    ¥ ボラの高い草コインじゃなくて、日本円で払えます(円も実質草コイ・・・🤫
    🚀 もう少しでリリースするのでちぇけら

    View full-size slide

  45. 興味ある方はこちら

    View full-size slide

  46. 参考文献
    EIP721
    EIP1155
    OpenZeppelin - IERC721.sol
    OpenZeppelin - IERC1155.sol

    View full-size slide

  47. ご静聴ありがとうございました🙌

    View full-size slide