LoginSignup
Iyarr
@Iyarr

Are you sure you want to delete the question?

If your question is resolved, you may close it.

Leaving a resolved question undeleted may help others!

We hope you find it useful!

Metamaskアカウントの紐づけができない

解決したいこと

Metamaskアカウントの紐づけを同意してもらうためのポップアップを表示させたい
以下のYoutubeの動画をもとにコードを作成(てか全く同じコード)し、サーバーを起動してみたところ、20:46でいったんmetamaskの
アカウントの紐づけを同意してもらうためのポップアップを表示させるとこれで以下のエラーコードが表示されます。
なぜこうなっているのかわかる方いますか?

ファイル構成
metamask-login
├ error.html
├ success.html
├ index.html
├ index.js
└ package.json

<!DOCTYPE html>
<html>
  <head>
    <title>Ethers.js Sign Message Example</title>
    <script
      src="https://cdn.ethers.io/lib/ethers-5.7.1.umd.min.js"
      type="application/javascript"
    ></script>
    <style>
      body {
        font-family: Arial, sans-serif;
        text-align: center;
      }

      h1 {
        margin-bottom: 20px;
      }

      p {
        text-align: center;
        font-size: 20px;
        margin-top: 50px;
      }

      button {
        padding: 10px 20px;
        border: none;
        border-radius: 5px;
        background-color: #3f51b5;
        color: #fff;
        font-size: 16px;
        cursor: pointer;
      }

      button:hover {
        background-color: #1c2b46;
      }
    </style>
  </head>
  <body>
    <h1>Ethers.js Sign Message Example</h1>
    <button onclick="signMessage()">Sign Message</button>
    <p id="p1"></p>
    <script>
      // Get the nonce value from the backend server
      async function getNonce() {
        const response = await fetch("/api/nonce");
        const data = await response.json();
        return data.nonce;
      }

      // Sign the message with the nonce and send it to the backend server for verification
      async function signMessage() {
        try {
          var element = document.getElementById("p1");
          const nonce = await getNonce();

          const provider = new ethers.providers.Web3Provider(window.ethereum);
          const signer = provider.getSigner();
          console.log(signer);
          const address = await signer.getAddress();
          const message = `this nonce is signed using metamask ${nonce}`;

          const signedMessage = await signer.signMessage(message);

          const data = { signedMessage, message, address };

          const response = await fetch("/login", {
            method: "POST",
            headers: {
              Accept: "application/json",
              "Content-Type": "application/json",
            },
            body: JSON.stringify(data),
          });

          let token = await response.json();
          element.innerHTML = token;
        } catch (error) {
          console.error(error);
        }
      }
    </script>
  </body>
</html>


const express = require("express");
const crypto = require("crypto");
const ethers = require("ethers");
const app = express();
const path = require("path");
const bodyParser = require("body-parser");
app.use(express.static(__dirname));
const jwt = require("jsonwebtoken");
app.use(express.json());
app.use(bodyParser.json());
app.get("/", (req, res) => {
  res.sendFile(path.join(__dirname + "/index.html"));
});

// GET route to retrieve a nonce value for use in signing
app.get("/api/nonce", (req, res) => {
  // Generate a random 32-byte value to use as the nonce
  const nonce = crypto.randomBytes(32).toString("hex");
  // Return the nonce value as a JSON object in the response body
  res.json({ nonce });
});

const secretKey = "mySecretKey";

app.post("/login", (req, res) => {
  const { signedMessage, message, address } = req.body;
  const recoveredAddress = ethers.utils.verifyMessage(message, signedMessage);
  console.log(recoveredAddress);
  if (recoveredAddress !== address) {
    return res.status(401).json({ error: "Invalid signature" });
  }

  // Generate the JWT token
  const token = jwt.sign({ address }, secretKey, { expiresIn: "1h" });
  // Send the JWT token to the frontend
  res.json(token);
});

// Endpoint for verifying the JWT token and logging in the user
app.post("/verify", (req, res) => {
  const authHeader = req.headers.authorization;

  if (!authHeader || !authHeader.startsWith("Bearer ")) {
    return res.status(401).json({ error: "Invalid token" });
  }

  const token = authHeader.split(" ")[1];

  try {
    // Verify the JWT token
    const decoded = jwt.verify(token, secretKey);
    console.log(decoded);
    const currentTime = Math.floor(Date.now() / 1000);
    console.log(currentTime);
    if (decoded.exp < currentTime) {
      res.json("tokenExpired");
    } else {
      res.json("ok");
    }
  } catch (err) {
    res.status(401).json({ error: "Invalid token" });
  }
});

// Serve the success page
app.get("/success", (req, res) => {
  res.sendFile(path.join(__dirname + "/success.html"));
});

// Start the server
app.listen(3000, () => {
  console.log("Server started on port 3000");
});

発生している問題・エラー

unknown account #0 (operation="getAddress", code=UNSUPPORTED_OPERATION, version=providers/5.7.1)

自分で試したこと

  • 紐づけたいmetamaskアカウントのネットワークの変更
  • 同時に起動してたブラウザの拡張機能の停止
  • アクセスしたウェブサイト上にある自分の全データの読み取りと変更の許可の設定の確認
    -> すべてのサイト
0

1Answer

机上ですみません。

const provider = new ethers.providers.Web3Provider(window.ethereum);
const signer = provider.getSigner();
console.log(signer); ヌル表示と仮定
const address = await signer.getAddress(); ヌルsignerなのでgetAddressがUNSUPPORTED_OPERATIONとなる仮説

Web3がサーバとして事前に実行されていない? BlockChainは自前のサーバも必要では?

または、window.ethereumの仕様が変わりethers-5.7.1.umd.min.jsがサンプルと合わない。umd.minの意味は?フルライブラリー(ethers-5.7.1.js)はないの?

0Like

Comments

  1. @Iyarr

    Questioner

    申し訳ありません
    今現在YouTubeの動画をもとに全く同じコードでコマンドを同じように叩いただけでそれぞれの処理で使われているものがそれぞれどのような役割を果たしているのかを調べている最中で、window.ethereumの使用が変更されたのも知りませんでした。
    ドキュメントは以下のサイトのものを参考にしてます
    https://docs.ethers.org/v5/

  2. window.ethereumの仕様が変わり

    推測、仮定です。事実ではありません。
    console.log(signer); をタイプ表示、他プロパティ表示の情報で、もう少し情報があれば、原因がわかるかも?

    const provider = new ethers.providers.Web3Provider(web3.currentProvider);
    

    サンプルを、v4のものを探し、比較すると、自環境の違いで、引数の選択、方式の選択があることがわかるかも?

  3. @Iyarr

    Questioner

    うーん、ではほかのやり方もいくつか探して試してみます
    それでできたものに対して他とどの違いがあるのかも調べます

  4. 力及ばずすみません。調査頑張って下さい。

    Web3サーバの実行の有無は確認してますか?

  5. @Iyarr

    Questioner

    metamaskのnonceの作成で事前にWeb3サーバにアクセスしないと次の処理に行けないので毎回確認しています

  6. console.log(signer);
    const address = await signer.getAddress();
    

    getAddressがUNSUPPORTED_OPERATIONとなる理由がWeb3の設定ミスと考えているからです。サンプルと異なる環境でsignerが生成されていると推測してます。

    先ずは調査頑張って下さい。

Your answer might help someone💌