这篇文章的目标受众。
- 想使用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.访问以下网站
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。 faucet.polygon.technology/
Wallet Address应说明获取账户的响应结果。 1~2分钟后,ETHER被授予指定的Wallet。