OpenSEAから作成したセットのNFTリストをインポート

31421 ワード

大規模プロジェクトのNFTは、ERC 721を独自に作成し、使用します.しかし、すべてのアーティストが開発能力を備えていないため、Openさんやファンデーションで自分の作品をアップロードします.すべてのNFTがイーサネットに記録されているため、web 3で表示できます.でもOPENはちょっと違う
  • CloneX: https://etherscan.io/token/0x49cf6f5d44e70224e2e23fdcdd2c053f30ada28b
  • OpenSea: https://etherscan.io/token/0x495f947276749ce646f68ac8c248420045cb7b5e
  • Open氏自身はOpenSea Shared Storefontという集合を作成し、Open氏内部で作成されたすべてのNFTを管理した.したがって、open氏以外の他の取引所(例えば、LooksRare)では、open氏が作成したコレクションを正しく表示できないという問題が発生します.
    大きなプロジェクトの場合、私が欲しいコレクションのNFTをインポートしたい場合は、web 3でリストを読み込むことができます.しかし、Openさんの場合、集合はサービスが自分で管理するので、普通のWeb方式を使うことができます.ブロックチェーン関連の文字で入るのを楽しみにしていたら申し訳ありません.スクロールに関する内容だけです.
    まず、openさんは正式なAPIを提供します.
    https://docs.opensea.io/reference/api-overview
    この文章はスクロール方式だけを紹介した.申請プロセスが複雑で、審査時間が長いため、APIドキュメントで申請できます.
    まず仕事はDeno v 119.1で行います.(npmをインストールする必要はありません.クライアントを作成するのに最適な環境だと思います.)
    開発者ツールを開き、openで使用されているAPIを表示します.このページにアクセスすると、必要なAPIが表示されます.GraphQLを使っていますね.

    次のようにcopy as fetchを選択します.ソースコードを貼り付けます.
    const response = await const response = await fetch("https://api.opensea.io/graphql/", {
      "headers": {
        "accept": "*/*",
        "accept-language": "ko,en;q=0.9,en-US;q=0.8",
        "authorization":
          "JWT eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VyX2lkIjoiVlhObGNsUjVjR1U2TWpVd09URTBNakk9IiwidXNlcm5hbWUiOiIweDJmYWNlZCIsImFkZHJlc3MiOiIweDJmYWNlZGEyODM1MDU0OWM3YjRiYWMyYTg0MDRhNmQ4YTdkZWJlMmIiLCJpc3MiOiJPcGVuU2VhIiwiZXhwIjoxNjQ3ODcwOTA2LCJvcmlnSWF0IjoxNjQ3Nzg0NTA2fQ.04hE-83DZAOBMlO_Uz9GuOfCbJfG0KXOOXmfCodLg9k",
        "content-type": "application/json",
        "sec-ch-ua":
          '" Not A;Brand";v="99", "Chromium";v="99", "Google Chrome";v="99"',
        "sec-ch-ua-mobile": "?0",
        "sec-ch-ua-platform": '"macOS"',
        "sec-fetch-dest": "empty",
        "sec-fetch-mode": "cors",
        "sec-fetch-site": "same-site",
        "x-api-key": "...",
        "x-build-id": "...",
        "x-signed-query":
          "8305260a50fc51a99603924f36a860bef838705ee8db238c5de9feea263aa5a8",
      },
      "referrer": "https://opensea.io/",
      "referrerPolicy": "strict-origin",
      "body": ""/* 길어서 생략 */, 
      "method": "POST",
      "mode": "cors",
      "credentials": "include",
    });
    
    const body = await response.json()
    console.log(body)
    まず一周して結果が正常かどうか見てみましょう.これらのタスクを実行する際には、最小限の必要性のみを保持および削除することが重要です.GraphQLの場合、方法はPOSTであり、content-typeはjsonである.この2つのオプションを保持して削除すると、ヘッダーx-signed-queryが消えたときに403応答が表示されます.
    fetch("https://api.opensea.io/graphql/", {
      "method": "POST",
      "headers": {
        "content-type": "application/json",
        "x-signed-query":
          "8305260a50fc51a99603924f36a860bef838705ee8db238c5de9feea263aa5a8",
      },
      "body": ""/* 길어서 생략 */, 
    });
    名前で推測できるかもしれませんが、クエリーが操作されているかどうか(私が今スクロールしているように)、検証された署名が含まれている可能性があります.Webアプリケーションでは、JavaScriptコードの完全な検索に時間がかかる場合があります.
    コツは...そのタイトルキーを押してソースコード全体を検索します.

    検索結果は2つあります.最初のceea8bb...5e0.jsファイルは、実際の実行時のソースコードのように見えます.私は毒化された.通常、ソースマッピングのため、タイプスクリプトのソースコードが検索されます.圧縮コードを推測するときに、タイプスクリプトコードを参照できます.

    クロムのprettyprint機能によりコードの可読性を向上させる最初のファイル(ceea8bb...5e0.js)を開きます.

    必要な部分のコードをコピーしました.次のソースコードでは、より追跡するためにコメントを参照してください.プロセスに基づいて、前に数字を表示しました.
    , T = n("CrYB") // (7) T는 CrYB라는 매개변수로 불러오는데, 보통 이렇게 생긴것은 require("module") 일 가능성이 높습니다.
    , O = function(e) { // (5) O라는 함수는 여기에 있습니다.
      var t = T[e]; //(6) T에서 불러옵니다.
      if (!t)
        throw new Error("Signature missing from generated file ".concat(e));
      return t
    }
    , P = function(e) { // (3) P라는 함수는 여기에 있습니다.
      var t, n = e.split("BATCH_REQUEST:");
      if (n.length > 1) {
        var r = n[1].split(":");
        t = JSON.stringify(r.map(O))
      } else
        t = O(e); // (4) t라는 값은 O라는 함수를 통해 생성됩니다. if 분기의 경우 Chrome Debugger의 breakpoint를 통해서 확인할 수 있습니다.
      return t
    }
    
    /* 중간생략 */
    switch (t.prev = t.next) {
      case 0:
        return r = n.getID(),
          i = P(r), // (2) i변수는 P라는 함수를 통해 생성됩니다.
          n.fetchOpts.headers["x-signed-query"] = i, // (1) i 변수에 우리가 원하는 값이 들어갑니다.
          t.abrupt("return", e(n));
      case 4:
      case "end":
        return t.stop()
    }
    
    /* 중간생략 */   
    CrYB: function(e) { // (8) CrYB를 검색하면 다음과 같은 내용을 확인할 수 있습니다.
      e.exports = JSON.parse('{"AccountCollectionsQuery": ...생략.. }')
    },
    私たちは(8)で私たちが探している秘密鍵を見つけた.GraphQLクエリの秘密鍵は、IDによって予め定数として保存される.スクロールに必要なすべてのコードが見つかりました.上の上にちゃんと整理しておけばいい
    私が整理したコードはGithubで見ることができます.
    https://github.com/0x2faced/opensea-unofficial
    簡単なサンプルコードを作成します.-)iTermを使用する場合は、imgcatライブラリを介して端末上で画像をプレビューすることができる.
    import { printImage } from "https://deno.land/x/[email protected]/mod.ts";
    import { query } from "https://raw.githubusercontent.com/0x2faced/opensea-unofficial/v0.0.1/opensea.ts";
    
    let hasNext = true;
    let cursor = null as string | null;
    while (hasNext) {
      const { query: { search } } = await query("AssetSearchQuery", {
        cursor,
        collection: "ujin",
        collectionQuery: null,
        collectionSortBy: "SEVEN_DAY_VOLUME",
        collections: [
          "ujin",
        ],
        count: 32,
        resultModel: "ASSETS",
        showContextMenu: true,
        shouldShowQuantity: false,
        sortAscending: false,
        sortBy: "CREATED_DATE",
      });
    
      const assets = search.edges.map(({ node }) => {
        return {
          id: node.asset.id,
          name: node.asset.name,
          imageUrl: node.asset.imageUrl,
          tokenId: node.asset.tokenId,
          assetContract: {
            address: node.asset.assetContract.address,
            chain: node.asset.assetContract.chain,
          },
        };
      });
    
      for (const asset of assets) {
        const assetPageQueryResult = await query("AssetPageQuery", {
          tokenId: asset.tokenId,
          chain: asset.assetContract.chain,
          contractAddress: asset.assetContract.address,
        });
    
        const result = {
          imageUrl: assetPageQueryResult.nft.imageUrl,
          name: assetPageQueryResult.nft.name,
          description: assetPageQueryResult.nft.description,
          traits: assetPageQueryResult.nft.traits.edges.map(({ node }) => {
            return {
              type: node.traitType,
              value: node.value,
            };
          }),
          owner: assetPageQueryResult.nft.assetOwners.edges.map(({ node }) => {
            return {
              name: node.owner.displayName,
              publicName: node.owner.user.publicUsername,
              address: node.owner.address,
            };
          }),
        };
    
        const imageBuffer = await fetch(assetPageQueryResult.nft.imageUrl).then((
          res,
        ) => res.arrayBuffer());
        await printImage(new Uint8Array(imageBuffer));
        console.log(JSON.stringify(result, null, 2));
        await new Promise((resolve) => setTimeout(resolve, 3000));
      }
    
      hasNext = search.pageInfo.hasNextPage;
      cursor = search.pageInfo.endCursor;
    }
    ちょっと回して

    収集に成功しました:-)
    NFTに関する情報を収集する過程で、Open氏の独特な政策が類似の問題に直面している人に役立つことを望んでいます.