你搬进了一个新小区,名叫“Web3 社区”。小区里有超市、健身房、影音室,每个房间门口都装着一扇带门禁的锁,锁上刻着唯一的门牌号。物业发给你一只“智能钥匙串”——钥匙的锯齿极其精密,只有你能看到;门牌号人人可见,但没人能从门牌号倒推出你的钥匙。这套钥匙串,就是钱包;钥匙是私钥,门牌号是地址。当你在超市结账、在健身房办卡时,只需把门牌号出示给前台(连接 DApp),真正开门的那一刻才掏出钥匙拧一下(签名授权)。整个过程中,钥匙从不离手,锁匠也永远猜不到你的钥匙长什么样。本文就用这条“钥匙串”故事线,带你理解 MetaMask、Phantom 这类钱包如何管理私钥、与 DApp 交互、完成身份认证与交易发起,以及集成时那些绕不开的安全与体验细节。

岗位关联

掌握钱包集成,你就能为用户搭起通往 Web3 的第一座桥:理解私钥、签名、链 ID 等底层机制,设计出既安全又顺滑的 DApp 接入体验,这份能力正是未来数据要素市场中“数字身份与授权”方向的核心竞争力。

目录
  1. 可视化演示
  2. 钱包身份组成
  3. 主流钱包工具
  4. 连接交互流程
  5. 账户动态管理
  6. 网络环境适配
  7. 签名安全机制
  8. 体验优化方案
  9. AI 应用场景
  10. Python 演示
  11. 常见误区
  12. 面试题

可视化演示

展示DApp通过MetaMask连接区块链的完整流程、EIP-1193事件监听机制与ERC-4337账户抽象,切换模式查看不同集成环节。

本节配有交互动效(进入视口后自动加载,约 3KB)。

钱包连接流程 DApp调用eth_requestAccounts请求连接 MetaMask弹窗用户签名授权 DApp→EIP-1193→MetaMask→签名→上链 连接后通过Provider接口与区块链交互

钱包身份组成

物业发钥匙串那天,管理员反复叮嘱:“钥匙的锯齿是你在小区里唯一的身份凭证,门牌号可以贴在大门口给所有人看,但钥匙绝不能离开你的口袋。”这套逻辑正是钱包身份体系的缩影:私钥就是钥匙,地址就是门牌号,而你每次开门时那个“咔哒”一声的拧钥匙动作,就是数字世界里的签名。没有钥匙的人永远进不了门,而拿着钥匙的人也从不需要向任何人证明“我有钥匙”——拧一下锁,就够了。

映射到技术世界:钱包的核心是一个或多个私钥(private key),它们通常由一组助记词(seed phrase)确定性派生而来,就像一把主钥匙能复制出所有分钥匙。从私钥可以算出公钥(public key),再从公钥哈希出地址(address)。地址是你对外展示的身份 ID,可以在区块浏览器上被所有人看到;私钥则是绝对不能离开本地设备的存在。所谓“身份认证”,本质就是向对方证明“我持有这把钥匙”,而证明的方式不是交出钥匙,而是用钥匙对一条随机消息做签名。

地址的生成过程在以太坊系钱包里遵循一条固定流水线。私钥经过椭圆曲线算法得到一个点坐标,序列化后就是公钥;公钥再做一次 Keccak-256 哈希,取后 20 个字节便得到 40 位的十六进制地址。这个过程是单向的:从私钥到地址易如反掌,从地址反推私钥却难如登天,就像从门牌号永远猜不出钥匙的锯齿结构。

理解了这套身份体系,你就明白为什么说“钱包即身份”。在接下来的每一节里,不管是连接 DApp、切换账户还是签名交易,本质上都是这一把钥匙在不同门禁前的反复使用——钥匙本身从未离开过你口袋。

Address=Keccak-256(PublicKey)[12: ]\displaystyle \text{Address} = \text{Keccak-256}(\text{PublicKey})_{[12:\,]}
通俗地说:先把公钥丢进一个“搅碎机”(哈希函数)得到 32 字节的乱码,然后只取最后 20 字节当作门牌号。任何人拿到门牌号都无法还原搅碎前的样子。
  1. PublicKey(公钥)由私钥经椭圆曲线点乘得到的坐标对,相当于门锁的“锁芯结构图”,可以公开但无法反推钥匙。
    PublicKey=privateKey×G\displaystyle \text{PublicKey} = \text{privateKey} \times G
  2. Keccak-256(哈希搅碎)以太坊专用的哈希函数,把任意长度输入打成固定 32 字节,相当于把锁芯图放进搅碎机,出来的碎纸片无法拼回原图。
    hash=Keccak-256(PublicKey)\displaystyle \text{hash} = \text{Keccak-256}(\text{PublicKey})
  3. [12](截取后段):从 32 字节哈希的第 13 个字节开始取到最后,共 20 字节(160 位),这就是我们熟悉的 0x 开头的地址。
    Address=hash[12:]\displaystyle \text{Address} = \text{hash}[12:]

主流钱包工具

小区里并不是只有一种门禁设备。核心区装了 MetaMask 牌的智能钥匙串,它几乎能开所有 EVM 兼容的门;而 Solana 游乐园区用的是 Phantom 手环,更轻便、专为那片区域优化。你住在哪片区域、常去哪些设施,决定了你该随身带哪个钥匙串。

MetaMask 是当前以太坊生态最主流的钱包:浏览器扩展、移动端 App 都有,支持以太坊主网以及 BSC、Polygon、Arbitrum 等所有 EVM 兼容链。它会在浏览器里注入一个 window.ethereum 全局对象,DApp 通过这个对象与钱包通信。Phantom 则是 Solana 生态的头部钱包,同样提供浏览器扩展和移动端,也注入 provider 对象,但 API 细节与以太坊系略有差异——比如签名方法名不同、链 ID 体系也不同。

选型原则其实很简单:先看你的 DApp 部署在哪条链,再选支持该链的钱包。如果做以太坊生态应用,MetaMask 是必测项;如果做 Solana 应用,Phantom 是标配。但随着多链应用增多,你往往需要同时兼容多个钱包——这就需要引入 EIP-1193 这样的通用 provider 抽象,把“钥匙串的牌子”差异屏蔽在底层。就像高级小区的门禁系统统一了接口:不管住户用的是哪个牌子的钥匙串,只要能拧开门就是好钥匙。

连接交互流程

第一次走进 Web3 小区的超市,你不会直接把钥匙插进收银机,而是先到前台扫码:超市的 App 弹出一个窗口,“这个应用请求读取你的门牌号”,你点“连接”。前台记下你的门牌号,之后你来逛超市,店员就知道你是老顾客了。这整个“扫码登记”的动作,在钱包集成里就叫连接(Connect)。

技术上的连接流程分三步。第一步是注入检测:DApp 在页面加载时检查 window.ethereum 是否存在,不存在则提示用户安装钱包——就像先摸摸口袋确认有没有带钥匙串。第二步是握手协商:调用 eth_requestAccounts 向钱包发起请求,钱包弹出授权框,让用户确认“是否允许这个 DApp 查看你的地址”。第三步是连接确认:用户点同意后,钱包返回当前账户地址列表,DApp 把第一个地址当作登录用户。

这里有一个新手容易搞混的点:连接成功不等于拿到了任何资金操作权限。超市前台登记门牌号,只是知道“你来了”,你并没有授权超市从你口袋里掏钱。同样,eth_requestAccounts 只返回地址,不返回私钥,也无法代你转账。真正的资金操作发生在后面的“签名”环节。连接是一次性完成的握手,签名则是每次操作都要重新做的授权。

账户动态管理

你的钥匙串上不止一把钥匙:家门钥匙、办公室钥匙、储物间钥匙,长得差不多但开的是不同的门。在 Web3 小区,一个钱包里也可以管理多个账户,每个账户都有自己的地址和余额。当你走到超市前台登记时,前台会问:“今天用哪把钥匙对应的门牌号?”——这就是当前账户的概念。

在代码层面,DApp 通过 eth_accounts 获取当前账户,但用户随时可能在钱包里切换账户。这就需要监听 accountsChanged 事件:一旦用户换了账户,钱包会主动通知 DApp“前台注意,门牌号变了”。收到事件后,DApp 应该重新拉取账户、刷新页面上的余额和身份信息,必要的时候还要重置本地状态,否则就会出现“页面上还挂着旧地址,但用户实际已经切走”的错乱。

对比一下没做监听的后果:用户用账户 A 登录了你的借贷应用,然后切到账户 B 去看自己的借款额度,界面却还显示 A 的数据——这就像前台登记簿上写着老门牌号,却把新来的人领去了旧楼层。多账户切换监听是钱包集成中最容易被忽略、却又直接影响用户体验的细节。别忘了:连接状态和当前账户是两个独立维度,eth_accounts 返回空数组表示未连接,返回多个地址时永远取第一个作为默认账户。

网络环境适配

Web3 小区分了几个区:核心区叫“Ethereum 主网”,新开发的东区叫“Polygon“,还有几间专门给装修队用的”样板间“(测试网)。门禁卡通用,但每个区的物价、店铺、规则都不同。你在东区逛超市,收银机却按核心区的价签结算,账单必然对不上。链(Chain)就是这个”区”,而链 ID 就是区的编号。

钱包集成时,DApp 必须知道自己运行在哪条链上。通过 eth_chainId 可以查询当前链 ID:以太坊主网是 1,Polygon 是 137,Sepolia 测试网是 11155111。DApp 的合约部署在 Polygon 上,用户钱包却连着以太坊主网,你展示的余额、价格就全是错的。因此在连接后和每次收到 chainChanged 事件时,都要校验链 ID;不匹配时调用 wallet_switchEthereumChain 引导用户切换,如果钱包里没有目标链,则用 wallet_addEthereumChain 把网络配置添加进去。

网络切换和账户切换一样,属于“用户主动操作,DApp 被动感知”的场景。监听 chainChanged 事件后,正确的做法是:清空旧链的缓存数据 → 重新查询链 ID → 拉取新链上的账户余额与状态 → 刷新界面。不做这一步,用户切了链之后页面还显示旧链的数据,轻则数据错乱,重则用户在错误链上发起交易导致资产损失。记住一句话:链不对,一切数字都是幻觉。

签名安全机制

超市的收银台设计得很巧妙:你买东西时,收银员不会伸手到你口袋里摸钥匙,而是把账单递到你面前,你在自己这边拧一下钥匙,锁开了,收银台只收到一个“已开锁”的凭证。这个凭证就是签名,而拧钥匙的动作,永远发生在你的钥匙串(钱包)内部。签名分为两类:消息签名和交易签名,它们的“账单”内容完全不同。

消息签名用于身份认证和授权登录,比如“证明我拥有这个地址”或“授权这个应用读取我的数据”。常用 API 是 personal_sign,签名前会在原文前加上一段固定前缀,向用户展示可读的原文,避免用户盲目签下看不懂的乱码。交易签名则是真正的“花钱”操作,调用 eth_sendTransaction 时,钱包会弹出交易详情:转给谁、转多少、手续费多少,用户确认后才签名并广播上链。两者的核心区别是:签消息不产生链上状态变化,签交易则真实动了链上的钱。

签名请求同样可能被用户拒绝——就像你不想买这件东西,把账单推回去。钱包会返回错误码 4001(用户拒绝请求),DApp 必须捕获这个错误并优雅回退:关闭加载状态、提示用户操作已取消、必要时给出重试入口。反过来,如果用户点了确认,钱包返回的就是签名后的结果(r, s, v 三件套),DApp 可以把它拿去验签或广播。整个签名流程可以浓缩成一个公式:

Signature=Sign(sk, Keccak-256(prefix+message))\displaystyle \text{Signature} = \text{Sign}\left(\text{sk},\ \text{Keccak-256}(\text{prefix} + \text{message})\right)
通俗地说:钱包把“固定前缀 + 原始消息”一起搅碎成摘要,再用私钥对这个摘要做数学签名。加了前缀之后,同样的消息在 ETH 生态里就不会被当成其他链的合法签名,相当于在账单上盖了“本小区专用”的章。
  1. prefix(前缀)personal_sign 会在消息前加一段标准字符串,如 \x19Ethereum Signed Message:\n32,作用是防止签名被跨链、跨用途重放。
    \displaystyle \text{prefix} = \text{"\x19Ethereum Signed Message:\n32"}
  2. message(原始消息)用户要签的原文,可能是登录用的随机码,也可能是交易详情。钱包会把它展示给用户看,确保“所见即所签”。
    message=humanReadableContent\displaystyle \text{message} = \text{humanReadableContent}
  3. Keccak-256(消息摘要)对前缀 + 消息做哈希,得到 32 字节摘要。签名算法只对摘要签名,而不是对整段长文本签名,效率更高。
    h=Keccak-256(prefix+message)\displaystyle h = \text{Keccak-256}(\text{prefix} + \text{message})
  4. Sign(sk, h)(私钥签名)钱包在本地内存中用私钥对摘要做椭圆曲线签名,输出 (r, s) 两个整数。私钥全程不出本地,外面的人拿到 (r, s) 也无法反推私钥。
    (r,s)=ECDSAsign(sk,h)\displaystyle (r, s) = \text{ECDSA}_{\text{sign}}(\text{sk}, h)

体验优化方案

现在你已经是小区里的老住户了。回想第一次用钱包时的忐忑:点了“连接”之后页面毫无反馈,不知道钱包弹窗是不是被浏览器拦截了;签名后又要等十几秒,心里直打鼓。一个成熟的前台登记流程,应该让用户对每个环节都心里有数:扫码中、已登记、登记失败、可以重试。钱包集成的体验优化,本质就是把这种“门禁仪式感”打磨得顺畅自然。

在工程实现上,连接与签名都是异步操作,UI 必须覆盖四种状态:等待中(钱包弹窗未返回,按钮置灰并转圈)、成功(拿到地址或签名,进入下一步)、失败(网络错误、链不匹配等异常,展示原因)、拒绝(用户主动点了取消,友好提示而不报错)。常见做法是用一个状态机管理连接生命周期,避免用户重复点击导致多个弹窗叠加。

再往上一层,是多钱包桥接。新一代连接库如 Web3Modal、RainbowKit、wagmi 把 MetaMask、Phantom、Coinbase Wallet 等几十种钱包统一封装:你只需要写一份连接逻辑,库帮你完成钱包检测、注入适配、事件监听和错误归一化。对于面向广大用户的产品,这几乎是必选项——毕竟你不能要求所有住户都带同一个牌子的钥匙串。最后别忘了“断线重连”:用户可能在钱包里断开 DApp 连接,通过监听 accountsChanged 收到空数组或 disconnect 事件后,应自动回到未连接态并引导重新连接。好的钥匙串体验,是让用户忘了钥匙的存在,只记得门好开。

AI 应用场景

数据要素交易市场中的数字身份鉴权

阶段:数据确权与授权访问

解决的问题:传统数据交易依赖账号密码体系,用户身份与数据权属绑定在中心化服务器上,不仅存在撞库、泄露风险,而且数据被转卖后难以追责。用钱包签名做鉴权后,数据提供方用私钥对数据包哈希签名完成“确权”,购买方用相同机制完成“授权访问”,全程无需交出私钥,链上留痕可审计。

具体案例:某城市数据交易所上线“数据资产凭证”功能:数据提供方用 MetaMask 对数据包的哈希签名,生成不可篡改的权属凭证;AI 训练机构作为购买方,连接钱包后对使用条款签名授权,智能合约自动完成付款与数据解密。整个过程像在小区门口刷卡登记——身份真实、动作留痕、钥匙(私钥)从不离手。

AI 模型服务的匿名订阅准入

阶段:模型服务鉴权与支付

解决的问题:传统 API 订阅用 API Key 鉴权,密钥一旦泄露即可被盗刷,且用户身份与行为可被平台追踪。通过钱包签名实现“钱包即身份”,用户每次调用 AI 模型都用交易签名支付微额费用,平台只需验签即可放行,无需存储任何用户敏感信息,兼顾安全与隐私。

具体案例:某去中心化 AI 推理平台接入 Phantom 钱包:用户选择模型 → 钱包弹出“支付 0.5 SOL 调用 100 次”的签名确认 → 平台验签通过后下发临时访问令牌。与传统 API Key 相比,省去了注册审核流程,全球用户打开钱包就能用。

Python 演示

python93 行
# -*- coding: utf-8 -*-"""简化版椭圆曲线签名演示教学用途:用极小曲线模拟钱包的私钥签名与公钥验签。生产环境请使用 eth_account / web3.py 等成熟库。"""from hashlib import sha256 P = 97   # 有限域素数A = 0B = 9    # 曲线 y^2 = x^3 + 9 (mod 97)G = (3, 6)  # 基点,验证: 6^2 = 36, 3^3+9 = 36  def inv(n):    """模 P 乘法逆元(Fermat 小定理)"""    if n % P == 0:        return 0    return pow(n, P - 2, P)  def add(p1, p2):    """椭圆曲线点加法,None 表示无穷远点"""    if p1 is None:        return p2    if p2 is None:        return p1    x1, y1 = p1    x2, y2 = p2    if x1 == x2 and (y1 + y2) % P == 0:        return None    if p1 == p2:        if y1 % P == 0:            return None        lam = (3 * x1 * x1 + A) * inv(2 * y1) % P    else:        lam = (y2 - y1) * inv(x2 - x1) % P    x3 = (lam * lam - x1 - x2) % P    y3 = (lam * (x1 - x3) - y1) % P    return (x3, y3)  def mul(k, p):    """标量乘法:重复点加(类比私钥乘基点得公钥)"""    r = None    while k:        if k & 1:            r = add(r, p)        p = add(p, p)        k >>= 1    return r  def hash_to_int(text):    """把消息哈希成曲线上的标量"""    digest = sha256(text.encode()).digest()    return int.from_bytes(digest, 'big') % P  def sign(message, private_key):    """私钥签名:返回 (r, s) 二元组"""    z = hash_to_int(message)    k = 23  # 教学用固定随机数,生产必须随机    R = mul(k, G)    r = R[0] % P    s = inv(k) * (z + r * private_key) % P    return (r, s)  def verify(message, public_key, sig):    """公钥验签:返回布尔值"""    r, s = sig    if not (1 <= r < P and 1 <= s < P):        return False    z = hash_to_int(message)    w = inv(s)    u1 = z * w % P    u2 = r * w % P    point = add(mul(u1, G), mul(u2, public_key))    if point is None:        return False    return point[0] % P == r  if __name__ == '__main__':    private_key = 17    public_key = mul(private_key, G)  # 由私钥推导公钥    msg = 'transfer 1 ETH to data-market'    sig = sign(msg, private_key)     print('公钥:', public_key)    print('签名:', sig)    print('验签原始消息:', verify(msg, public_key, sig))    print('验签篡改消息:', verify(msg + ' (fake)', public_key, sig))
目的:用极简椭圆曲线演示钱包签名的核心思想——私钥签名、公钥验签、原始消息通过而篡改消息失败,帮助理解 MetaMask 中 personal_sign 背后的数学原理。
  1. private_key = 17私钥就是一把“钥匙的锯齿”,一个普通整数,必须保密。
  2. public_key = mul(private_key, G)用私钥做标量乘法得到公钥,相当于从钥匙铸出门牌号,方向单向。
  3. hash_to_int(message)把消息哈希成整数,相当于把账单内容搅碎成摘要。
  4. sig = sign(msg, private_key)用私钥对摘要做签名,整个过程私钥不出函数、不出本机。
  5. verify(msg, public_key, sig)任何人拿到公钥、消息和签名都可以验签,但无法反推私钥。

常见误区

误区很多初学者以为“我点了一下连接钱包,这个 DApp 就能动我的钱了”,于是对任何请求连接的钱包弹窗都产生恐惧,或者反过来觉得连接很危险。

正解连接(eth_requestAccounts)只暴露地址,就像在前台登记门牌号;转账必须每次单独签名(eth_sendTransaction),就像每笔消费都要当场拧一次钥匙。连接 ≠ 授权,二者权限边界完全不同。真正要警惕的是那些让你“一次性授权无限额度”的合约调用。

为何常见:传统互联网里“登录即授权”的习惯根深蒂固,用户天然把“允许访问我的账号”和“允许动用我的资产”混为一谈。

误区有些开发者觉得“签名的逻辑在后端做更安全”,于是让用户把私钥或助记词上传到服务器,由后端统一签名。

正解私钥是钥匙本身,一旦离开本地设备就等于把家门钥匙复制给了别人。正确的架构是:签名永远在钱包内部完成,后端只负责验签。前端把请求发给钱包,钱包签好名,再把签名结果发给后端验证——相当于你自己拧钥匙,把“已开锁”的凭证交给门卫。

为何常见:传统 Web 开发习惯中“服务端持有密钥”的模式非常普遍,开发者容易把中心化的安全思维直接套用到去中心化场景。

误区有人认为“用户会不会切链是他的自由,我只要按照当前链显示数据就行”,于是完全不监听 `chainChanged`,也不校验链 ID。

正解链不对会导致价格错误、交易失败甚至资产损失。DApp 必须主动查询 eth_chainId,监听 chainChanged,发现链不匹配时调用 wallet_switchEthereumChain 引导用户切换。引导切换是 DApp 的责任,不是用户的义务。

为何常见:多链概念对新手本就抽象,很多教程只讲了连接和签名,忽略了网络层,导致开发者把“链”当成了钱包内部的不透明配置。

误区初学者常以为 MetaMask = 以太坊专用,Phantom = Solana 专用,二者毫无交集,于是对“MetaMask 也能连 Polygon”感到吃惊。

正解MetaMask 支持所有 EVM 兼容链(BSC、Polygon、Arbitrum、Optimism 等),通过添加自定义 RPC 即可切换;Phantom 目前聚焦 Solana,但也在逐步扩展多链能力。选钱包要看目标链的 EVM 兼容性,而非品牌印象。

为何常见:钱包品牌与单条链的强绑定宣传深入人心,加上各生态教程各说各话,形成了“一钱包一链”的刻板印象。

面试题

Q1. 钱包管理资产时,以下哪一项是必须绝对保密的?

单选题 · easy

  • A.账户的公钥地址
  • B.自己生成交易哈希
  • C.钱包的私钥助记词← 正确答案
  • D.历史交易记录列表

答案:C。地址可公开,交易哈希和记录链上可查;唯独私钥/助记词是“钥匙锯齿”,泄露等于把家门的钥匙复制给了别人,因此只有 C 必须保密。

Q2. MetaMask 在浏览器中注入的全局对象是哪一个?

单选题 · easy

  • A.window.ethereum← 正确答案
  • B.window.etherjs
  • C.window.web3js
  • D.window.provider

答案:A。MetaMask 按 EIP-1193 标准注入 window.ethereum。B 和 C 是混淆项(ethers 是库不是注入对象),D 是通用叫法而非具体全局对象名。

Q3. Phantom 钱包主要服务于哪条区块链生态?

单选题 · easy

  • A.比特币与闪电网络
  • B.以太坊与 Layer2
  • C.Solana 生态应用← 正确答案
  • D.波卡平行链生态

答案:C。Phantom 是 Solana 生态的头部钱包,类似于 MetaMask 之于 EVM 链。知道“哪个钥匙串开哪个区”是多链开发的基础常识。

Q4. accountsChanged 事件的作用是什么?

单选题 · mid

  • A.用户切换了钱包账户← 正确答案
  • B.用户切换了钱包网络
  • C.用户拒绝了签名请求
  • D.用户发起了新的交易

答案:A。当用户在钱包内切换当前账户时触发 accountsChanged,DApp 需要更新界面数据。切网络触发的是 chainChanged,拒绝签名是错误回调,发起交易是 eth_sendTransaction 的响应。

Q5. personal_sign 相比早期 eth_sign 最大的改进是什么?

单选题 · mid

  • A.签名速度更快更省 gas
  • B.展示原文防止盲目签名← 正确答案
  • C.所需私钥权限更高级
  • D.可绕过账户切换流程

答案:B。personal_sign 会附加 \x19Ethereum Signed Message 前缀,并在钱包中展示可读原文,避免用户对不可读数据盲目签名。它不会改变 gas、权限或账户逻辑,核心是“所见即所签”。

Q6. 用户点击“拒绝签名”后,钱包抛出的标准错误码是多少?

单选题 · mid

  • A.4001 用户拒绝请求← 正确答案
  • B.4100 账户不可用
  • C.4200 网络请求失败
  • D.4900 节点连接断开

答案:A。EIP-1193 规定 4001 表示用户拒绝请求。4100 是未授权,4200 是方法不支持,4900 是断连。捕获 4001 时应当优雅回退而不是报系统错误。

Q7. DApp 部署在 Polygon,而用户钱包连着以太坊主网,正确的处理是?

单选题 · mid

  • A.强制读取主网数据展示
  • B.引导用户切换到目标链← 正确答案
  • C.忽略差异继续发起交易
  • D.让用户手动刷新页面

答案:B。链不匹配时数据是错的,发起交易会失败。正确做法是检测 eth_chainId 后用 wallet_switchEthereumChain 引导切换,必要时用 wallet_addEthereumChain 添加网络。

Q8. 以下哪些属于钱包的核心职责?

多选题 · mid

  • A.保管私钥与助记词← 正确答案
  • B.对交易进行数字签名← 正确答案
  • C.验证交易合法性
  • D.连接 DApp 完成授权← 正确答案

答案:ABD。钱包负责私钥保管、交易签名和 DApp 连接授权;“验证交易合法性”是区块链节点的职责,不是钱包的。钱包是钥匙串,不是门禁核查员。

Q9. 关于 EIP-1193 标准中的 provider,以下说法正确的是?

多选题 · hard

  • A.以 request 方法发请求← 正确答案
  • B.以事件监听状态变化← 正确答案
  • C.同步返回签名结果
  • D.直接访问用户私钥

答案:AB。provider 用 request({method, params}) 发异步请求,用 on('accountsChanged') 等事件监听状态变化。异步请求不会同步返回,且 provider 永远无法访问私钥。

Q10. 从私钥到钱包地址,正确的派生顺序是什么?

单选题 · extreme

  • A.私钥哈希公钥取后段
  • B.私钥公钥哈希取后段← 正确答案
  • C.公钥私钥哈希取前段
  • D.哈希私钥公钥取前段

答案:B。正确顺序是:私钥 → 椭圆曲线点乘得公钥 → Keccak-256 哈希 → 取后 20 字节。整个过程单向不可逆,任何把私钥排在公钥之后的顺序都是错的。