高级
构建钱包
创建 WebExtension 或 iFrame 钱包
概述
本指南展示如何构建两种类型的钱包:
- WebExtension 钱包 - 浏览器扩展形式,如 Superhero Wallet
- iFrame 钱包 - 嵌入网页的 iframe 形式
WebExtension 钱包
完整实现示例:wallet-web-extension
更高级的实现可参考 Superhero Wallet 源码。
步骤 1创建扩展与页面的通信桥
Content Script 负责在扩展和页面之间建立通信:
// content-script.js
import {
BrowserRuntimeConnection,
BrowserWindowMessageConnection,
connectionProxy
} from '@aeternity/aepp-sdk';
// 连接到扩展后台
const runtimeConnection = new BrowserRuntimeConnection({ port: chrome.runtime.connect() });
// 连接到网页
const windowConnection = new BrowserWindowMessageConnection();
// 创建代理,双向转发消息
connectionProxy(runtimeConnection, windowConnection);
步骤 2初始化 AeSdkWallet 类
在扩展后台脚本中初始化钱包并监听连接:
// background.js
import {
AeSdkWallet,
Node,
AccountMemory,
BrowserRuntimeConnection,
WALLET_TYPE,
RpcConnectionDenyError
} from '@aeternity/aepp-sdk';
// 初始化 SDK
const node = new Node('https://testnet.aeternity.io');
const account = new AccountMemory(SECRET_KEY);
const aeSdkWallet = new AeSdkWallet({
id: 'my-wallet',
type: WALLET_TYPE.extension,
name: 'My Wallet',
nodes: [{ name: 'testnet', instance: node }],
accounts: [account],
// 处理连接请求
onConnection: (aeppInfo, origin) => {
// 可以在这里显示确认弹窗
if (confirm(`Allow ${aeppInfo.name} from ${origin} to connect?`)) {
return; // 允许连接
}
throw new RpcConnectionDenyError();
},
// 处理订阅请求
onSubscription: (aeppInfo, origin) => {
// 返回账户列表
return aeSdkWallet.accounts;
},
// 处理签名请求
onSign: async (aeppInfo, parameters, origin) => {
// 可以在这里显示签名确认弹窗
if (confirm(`Sign transaction for ${aeppInfo.name}?`)) {
return; // 允许签名
}
throw new RpcRejectedByUserError();
}
});
// 监听来自 content script 的连接
chrome.runtime.onConnect.addListener((port) => {
const connection = new BrowserRuntimeConnection({ port });
aeSdkWallet.addRpcClient(connection);
});
iFrame 钱包
iFrame 方式与 WebExtension 类似,只是不需要中间的 connectionProxy。
完整实现示例:wallet-iframe
// wallet-iframe.js
import {
AeSdkWallet,
Node,
AccountMemory,
BrowserWindowMessageConnection,
WALLET_TYPE
} from '@aeternity/aepp-sdk';
// 初始化钱包 SDK
const aeSdkWallet = new AeSdkWallet({
id: 'iframe-wallet',
type: WALLET_TYPE.window,
name: 'iFrame Wallet',
nodes: [{ name: 'testnet', instance: new Node('https://testnet.aeternity.io') }],
accounts: [new AccountMemory(SECRET_KEY)],
onConnection: (aeppInfo, origin) => { /* 处理连接 */ },
onSubscription: (aeppInfo, origin) => aeSdkWallet.accounts,
onSign: async (aeppInfo, params, origin) => { /* 处理签名 */ }
});
// 使用 BrowserWindowMessageConnection
const connection = new BrowserWindowMessageConnection({ target: window.parent });
aeSdkWallet.addRpcClient(connection);
关键回调函数
| 回调 | 触发时机 | 用途 |
|---|---|---|
onConnection |
Aepp 请求连接 | 显示连接确认弹窗 |
onSubscription |
Aepp 订阅账户 | 返回可用账户列表 |
onSign |
Aepp 请求签名 | 显示交易详情并确认签名 |
onDisconnect |
Aepp 断开连接 | 清理资源 |
本页目录