使用Next.js和web3auth来创建DApps

这篇文章的目标受众。

  • 想使用web3auth引入认证
  • 想在Next.js中引入web3技术

什么是web3auth?

一项聚合所有社交登录、网络和移动原生平台、钱包和其他密钥管理方法的服务。
它允许开发者为新用户提供一个更通用的登录流程,类似于谷歌和Twitter等平台的登录页面。 它还允许开发者继续向当前用户提供种子词认证。

什么是Dapps?

Dapps是去中心化应用的缩写。
它是 "智能合约 "的一种应用,是在区块链上运行软件的机制。

Dapps与PC和智能手机等常规应用的不同之处在于,它们是

  • 持久性:由于它们是基于智能合约的,它们可以通过去中心化的管理一直保持运行,同时在区块链上记录历史和数据。
  • 透明度:任何人都可以检查代码,操作日志永远存储在区块链上。
  • 抗审查:可以在没有集中管理员的情况下与Dapp进行交流。 一旦部署(在生产环境中),代码就不能被改变。

更新应用程序需要用户达成共识。

构建Next.js环境

1.创建项目

## 创建一个Next.js项目
$ npx create-next-app . -e with-tailwindcss

2.改为绝对路径

  "compilerOptions": {
    "target": "es5",
    "lib": ["dom", "dom.iterable", "esnext"],
    "allowJs": true,
    "skipLibCheck": true,
    "strict": true,
    "forceConsistentCasingInFileNames": true,
    "noEmit": true,
    "esModuleInterop": true,
    "module": "esnext",
    "moduleResolution": "node",
    "resolveJsonModule": true,
    "isolatedModules": true,
    "jsx": "preserve",
-    "incremental": true
+    "incremental": true,
+    "baseUrl": "."
  },

准备使用web3auth

要在web3auth中要求一个客户ID

获取仪表板中的客户ID

1.注册并使用您的账户登录

*即使你还没有报名。

在这篇文章中,你已经用你的谷歌账户登录了。

如果你有1000个月活跃用户,你可以免费使用它。

2.创建一个项目

要使用Web3auth,你需要在开发者仪表板上创建一个项目,并获得一个客户端ID

web3auth的介绍

参考以下官方网站进行介绍

1.在package.json中添加以下代码并安装

  "dependencies": {
+    "@web3auth/base": "^1.1.0",
+    "@web3auth/web3auth": "^1.1.0",
+    "@web3auth/ethereum-provider": "^1.0.0",
+    "web3": "^1.7.0",
    "next": "latest",
    "react": "18.1.0",
    "react-dom": "18.1.0"
  },
  "devDependencies": {
+    "@types/elliptic": "^6.4.14",
    "@types/node": "17.0.35",
    "@types/react": "18.0.9",
    "@types/react-dom": "18.0.5",
    "autoprefixer": "^10.4.7",
    "postcss": "^8.4.14",
    "tailwindcss": "^3.1.2",
    "typescript": "4.7.2"
  }
$ npm i

2.创建App.tsx并粘贴以下代码

$ touch pages/App.tsx
import { useEffect, useState } from "react";
import { Web3Auth } from "@web3auth/web3auth";
import { CHAIN_NAMESPACES, SafeEventEmitterProvider } from "@web3auth/base";
import RPC from "./evm";

const clientId = "#######################"; // get from https://dashboard.web3auth.io Torus walletクライアントID

function App() {
  const [web3auth, setWeb3auth] = useState<Web3Auth | null>(null);
  const [provider, setProvider] = useState<SafeEventEmitterProvider | null>(null);

  useEffect(() => {
    const init = async () => {
      try {
      const web3auth = new Web3Auth({
        clientId,
        chainConfig: {
          chainNamespace: "eip155", // polygon-mumbai用
          chainId:  "0x13881", // polygon-mumbai用
          rpcTarget: "####################", // 私はinfura経由でpolygon-mumbaiにアップしておりますが、テスト環境はお任せします。
        },
      });

          setWeb3auth(web3auth);

      await web3auth.initModal();
      if (web3auth.provider) {
        setProvider(web3auth.provider);
      }
        } catch (error) {
          console.error(error);
        }
      };

      init();
  }, []);

  const login = async () => {
    if (!web3auth) {
      console.log("web3auth not initialized yet");
      return;
    }
    const web3authProvider = await web3auth.connect();
    setProvider(web3authProvider);
  };

  const getUserInfo = async () => {
    if (!web3auth) {
      console.log("web3auth not initialized yet");
      return;
    }
    const user = await web3auth.getUserInfo();
    console.log(user);
  };

  const logout = async () => {
    if (!web3auth) {
      console.log("web3auth not initialized yet");
      return;
    }
    await web3auth.logout();
    setProvider(null);
  };

  const getChainId = async () => {
    if (!provider) {
      console.log("provider not initialized yet");
      return;
    }
    const rpc = new RPC(provider);
    const chainId = await rpc.getChainId();
    console.log(chainId);
  };
  const getAccounts = async () => {
    if (!provider) {
      console.log("provider not initialized yet");
      return;
    }
    const rpc = new RPC(provider);
    const address = await rpc.getAccounts();
    console.log(address);
  };

  const getBalance = async () => {
    if (!provider) {
      console.log("provider not initialized yet");
      return;
    }
    const rpc = new RPC(provider);
    const balance = await rpc.getBalance();
    console.log(balance);
  };

  const signMessage = async () => {
    if (!provider) {
      console.log("provider not initialized yet");
      return;
    }
    const rpc = new RPC(provider);
    const signedMessage = await rpc.signMessage();
    console.log(signedMessage);
  };

  const getPrivateKey = async () => {
    if (!provider) {
      console.log("provider not initialized yet");
      return;
    }
    const rpc = new RPC(provider);
    const privateKey = await rpc.getPrivateKey();
    console.log(privateKey);
  };
  const loggedInView = (
    <>
      <button onClick={getUserInfo} className="card">
        Get User Info
      </button>
      <button onClick={getChainId} className="card">
        Get Chain ID
      </button>
      <button onClick={getAccounts} className="card">
        Get Accounts
      </button>
      <button onClick={getBalance} className="card">
        Get Balance
      </button>
      <button onClick={signMessage} className="card">
        Sign Message
      </button>
      <button onClick={getPrivateKey} className="card">
        Get Private Key
      </button>
      <button onClick={logout} className="card">
        Log Out
      </button>

      <div id="console" style={{ whiteSpace: "pre-line" }}>
        <p style={{ whiteSpace: "pre-line" }}></p>
      </div>
    </>
  );

  const unloggedInView = (
    <button onClick={login} className="card">
      Login
    </button>
  );

  return (
    <div className="container">
      <h1 className="title">
        <a target="_blank" href="http://web3auth.io/" rel="noreferrer">
          Web3Auth
        </a>
        & ReactJS Example
      </h1>

      <div className="grid">{provider ? loggedInView : unloggedInView}</div>

      <footer className="footer">
        <a href="https://github.com/Web3Auth/Web3Auth/tree/master/examples/react-app" target="_blank" rel="noopener noreferrer">
          Source code
        </a>
      </footer>
    </div>
  );
}

export default App;

*每个网络的ChainId和其他信息的摘要

3.在App.tsx的clientId中的YOUR_CLIENT_ID中输入你自己的客户ID。

4.访问以下网站

https://dashboard.web3auth.io

5.创建evm.ts并粘贴以下代码

$ touch pages/evm.ts
import type { SafeEventEmitterProvider } from "@web3auth/base";
import Web3 from "web3";

export default class EthereumRpc {
  private provider: SafeEventEmitterProvider;

  constructor(provider: SafeEventEmitterProvider) {
    this.provider = provider;
  }

  async getChainId(): Promise<string> {
    try {
      const web3 = new Web3(this.provider as any);

      // Get the connected Chain's ID
      const chainId = await web3.eth.getChainId();

      return chainId.toString();
    } catch (error) {
      return error as string;
    }
  }

  async getAccounts(): Promise<any> {
    try {
      const web3 = new Web3(this.provider as any);

      // Get user's Ethereum public address
      const address = (await web3.eth.getAccounts())[0];

      return address;
    } catch (error) {
      return error;
    }
  }

  async getBalance(): Promise<string> {
    try {
      const web3 = new Web3(this.provider as any);

      // Get user's Ethereum public address
      const address = (await web3.eth.getAccounts())[0];

      // Get user's balance in ether
      const balance = web3.utils.fromWei(
        await web3.eth.getBalance(address) // Balance is in wei
      );

      return balance;
    } catch (error) {
      return error as string;
    }
  }

  async signMessage() {
    try {
      const web3 = new Web3(this.provider as any);

      // Get user's Ethereum public address
      const fromAddress = (await web3.eth.getAccounts())[0];

      const originalMessage = "YOUR_MESSAGE";

      // Sign the message
      const signedMessage = await web3.eth.personal.sign(
        originalMessage,
        fromAddress,
        "test password!" // configure your own password here.
      );

      return signedMessage;
    } catch (error) {
      return error as string;
    }
  }

  async getPrivateKey(): Promise<any> {
    try {
      const privateKey = await this.provider.request({
        method: "eth_private_key",
      });

      return privateKey;
    } catch (error) {
      return error as string;
    }
  }
}

5.按照下面的代码修改index.tx

import type { NextPage } from 'next';
import dynamic from "next/dynamic";

const App = dynamic(
  () => {
    return import("./App");
  },
  { ssr: false }
);

const Home: NextPage = () => {
  return <App />;
}

export default Home

6.修改global.css如下

html,
body {
  padding: 0;
  margin: 0;
  font-family: -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Oxygen,
    Ubuntu, Cantarell, Fira Sans, Droid Sans, Helvetica Neue, sans-serif;
}

a {
  color: inherit;
  text-decoration: none;
}

* {
  box-sizing: border-box;
}

.container {
  width: 60%;
  margin: auto;
  padding: 0 2rem;
}

.main {
  min-height: 100vh;
  padding: 4rem 0;
  flex: 1;
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
}

.title {
  line-height: 1.15;
  font-size: 3rem;
  text-align: center;
  margin: 50px;
}

.title a {
  color: #0070f3;
  text-decoration: none;
}

.grid {
  display: flex;
  align-items: center;
  flex-direction: column;
}

.card {
  margin: 0.5rem;
  padding: 0.7rem;
  text-align: center;
  color: #0070f3;
  background-color: #fafafa;
  text-decoration: none;
  border: 1px solid #0070f3;
  border-radius: 10px;
  transition: color 0.15s ease, border-color 0.15s ease;
  width: 100%;
}

.card:hover,
.card:focus,
.card:active {
  cursor: pointer;
  background-color: #f1f1f1;
}

.footer {
  display: flex;
  flex: 1;
  padding: 2rem 0;
  border-top: 1px solid #eaeaea;
  justify-content: center;
  align-items: center;
  margin-top: 10rem;
}

.footer a {
  display: flex;
  justify-content: center;
  align-items: center;
  flex-grow: 1;
}

.logo {
  height: 1.5rem;
  margin-left: 0.5rem;
}

@media (max-width: 1200px) {
  .container {
    width: 100%;
  }
}

创建Wallet

1.修改index.tx,代码如下。

使用了多边形链。

      web3auth = new window.Web3auth.Web3Auth({
        clientId,
        chainConfig: {
          chainNamespace: "eip155",
-         chainId: "0x1",
-         rpcTarget: "https://rpc.ankr.com/eth"
+         chainId: "0x13881",
+         rpcTarget: "https://polygon-mumbai.infura.io/v3/81984a3dbd7d4446886a8add0f51aa79"
        },
      });

2.让ether进入测试网

你可以用polygon Faucet向测试网发送ether。
https://faucet.polygon.technology/

Wallet Address应说明获取账户的响应结果。
1~2分钟后,ETHER被授予指定的Wallet。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

前端仙人

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值