无需助记词、钱包插件,仅用 OAuth 账号即可安全进入 Web3 场景。本文手把手教你使用 SUI Move 合约、React 前端与 zkLogin 零知识登录,打造一款“链上笔记本”。
目录
- 项目目标
- 零信任基石:什么是 zkLogin
- 环境准备
- Move 合约设计与部署
- React 前端整合 zkLogin
- 测试与常见问题(FAQ)
- 后续优化方向
1. 项目目标
- 开发一个 React 前端,与 SUI Move 合约无缝交互
- 集成 zkLogin,用户通过 Google 邮箱即可登录 Web3 账号
- 继承链上资产权限,用户创建或删除笔记,余额、数据均存于链上
2. 零信任基石:什么是 zkLogin
zkLogin 是 SUI 官方推出的无钱包登录协议:
- 用户走 OAuth2/OpenID,拿到 JWT 令牌
- SUI 节点使用 zk-SNARK 电路验证令牌合法性,自动派生 SUI 地址
- 零知识保证:任何人看不到 JWT 原始内容,却可验证“令牌有效”
关键词:zkLogin、SUI、无钱包登录、JWT、OAuth
3. 环境准备
3.1 获取示例仓库
git clone https://github.com/dacadeorg/zk-login-boilerplate
cd zk-login-boilerplate
yarn install3.2 Google OAuth 创建
- 打开 Google Cloud 控制台
- 新建项目 → OAuth 2.0 凭据 → 记录 Client ID & Client Secret
- 回到项目根目录,新建
.env:
REACT_APP_CLIENT_ID=<YOUR_CLIENT_ID>.apps.googleusercontent.com
REACT_APP_PROVER_URL=https://prover-dev.mystenlabs.com/v1
REACT_APP_REDIRECT_URL=http://localhost:3000
REACT_APP_OPENID_PROVIDER_URL=https://accounts.google.com/.well-known/openid-configuration
REACT_APP_FULLNODE_URL=http://127.0.0.1:9000
REACT_APP_PACKAGE_ID=<稍后部署生成的PackageID>👉 跟着官方文档快速验证 OAuth 回调流程,避 99% 的坑。
3.3 本地链启动
RUST_LOG="off,sui_node=info" sui-test-validator
# 新开终端,切换网络
sui client new-env --alias localnet --rpc http://127.0.0.1:9000
sui client switch --env localnet领取测试 SUI:
export MY_ADDR=0x5c5882d73a6e5b6ea1743fb028eff5e0
curl -X POST http://127.0.0.1:9123/gas \
-H "Content-Type: application/json" \
-d "{\"FixedAmountRequest\":{\"recipient\":\"$MY_ADDR\"}}"4. Move 合约设计与部署
4.1 初始化工程
sui move new notes
cd notes4.2 核心合约
sources/notes.move
module notes::notes {
use std::string::String;
use sui::table::{Self, Table};
use sui::tx_context::{Self, TxContext};
use sui::object::{Self, UID};
use sui::transfer;
#[lint_allow(self_transfer)]
public struct Ledger has key {
id: UID,
notes: Table<address, vector<Note>>,
}
public struct Note has store, drop {
title: String,
body: String,
}
fun init(ctx: &mut TxContext) {
transfer::share_object(Ledger {
id: object::new(ctx),
notes: table::new(ctx),
});
}
public entry fun add_note(ledger: &mut Ledger, title: String, body: String, ctx: &mut TxContext) {
let sender = tx_context::sender(ctx);
let new_note = Note { title, body };
if (table::contains(&ledger.notes, sender)) {
let notes = table::borrow_mut(&mut ledger.notes, sender);
vector::push_back(notes, new_note);
} else {
table::add(&mut ledger.notes, sender, vector[new_note]);
}
}
public entry fun del_note(ledger: &mut Ledger, idx: u64, ctx: &mut TxContext) {
let sender = tx_context::sender(ctx);
assert!(table::contains(&ledger.notes, sender), 0);
let notes = table::borrow_mut(&mut ledger.notes, sender);
assert!(idx < vector::length(notes), 1);
vector::remove(notes, idx);
}
}4.3 合约部署
sui client publish --gas-budget 100000000
# 终端输出记录
PACKAGE_ID=0x3d133870aa4959c2804430d8d582d907537b521cff595fce865734更新 .env 的 REACT_APP_PACKAGE_ID
5. React 前端整合 zkLogin
5.1 Sui 客户端 service
src/utils/suiClient.tssrc/utils/authService.ts
核心逻辑回顾:
await AuthService.generateZkLoginSignature(userSig)
// 返回 SerializedSignature,可上链5.2 笔记 CRUD 封装
src/utils/notesService.ts
新增笔记示例:
const txb = new TransactionBlock();
txb.moveCall({
target: `${PACKAGE_ID}::notes::add_note`,
arguments: [
txb.object("<Ledger_Object_Id>"),
txb.pure.string(title),
txb.pure.string(body),
],
});5.3 UI 组件栈
- Cover(登录页)
- Wallet(显示 zkLogin 地址、余额,一键注销)
- Notes(列表/新增/删除)
👉 源码级剖析:如何把 Google 登录按钮嵌成链上地址,立即体验。
6. 测试流程
| 步骤 | 命令/操作 |
|---|---|
| 启动本地节点 | sui-test-validator |
| 启动前端 | yarn start |
| 登录 | 访问 http://localhost:3000 → Google OAuth |
| 查看地址 | 右上角钱包地址 |
| 领水 | 同上 curl 命令 |
| 创建/删除笔记 | 前端交互 |
7. 常见问题(FAQ)
Q1. zkLogin 在正式网是否已可用?
A:截至 2025-06 已上线主网,推荐使用官方最新 CLI:≥v1.26。
Q2. OAuth 回调出现错误码 redirect_uri_mismatch?
A:回到 Google Cloud 控制台,将 http://localhost:3000 作为授权回调 URI,保存即可。
Q3. 想更换其他 OAuth(GitHub、Apple)?
A:只需生成对应 OpenID .well-known 信息,环境变量替换即可,完整兼容 zkLogin。
Q4. 升级依赖时出现 @mysten/sui.js 版本冲突?
A:使用 pnpm up --latest 解决 Node-API 差异,或锁定至 v0.52.x。
Q5. 部署失败后合约 Gas 消耗过大?
A:减少 Table/Vector 初始化大小,或在 CLI 加 --gas-budget 200000000。
Q6. zkLogin 地址能否与普通钱包共存?
A:可以。将派生地址导入任何生态钱包,私钥即 OAuth 派生凭证,安全由 zk 守护。
8. 后续优化方向
- 二次保密:用同态加密存储笔记 body,仅持有对应 NFT 可读
- 批量签名:一次 JWT 换取 n 次交易,避免频繁跳转
- 移动适配:将 React 重打包成 React-Native,更丝滑原生体验
- 多网络支持:在代码层把
REACT_APP_FULLNODE_URL设为空,通过 Vercel Edge 自动切换
尾声
到这里,一个极简且安全的 基于 zkLogin 的 SUI Move 私密笔记 dApp 已经跑通。你会惊奇地发现,Web2 用户的零门槛之旅仅在几分钟内完成。借此思路,你可以轻松延伸出链上投票、博客、游戏资产等更多场景。祝开发愉快!