Polkadot
UKey Wallet Polkadot Provider 用于在 Web 应用中连接 Polkadot/Substrate 账户、签名交易和消息,并配合 Polkadot.js API 发送交易。页面中可通过 window.$ukey.polkadot 或标准 Polkadot.js 扩展 API 访问。
ℹ️
UKey Wallet 实现 Polkadot.js 扩展接口,可被兼容 Substrate 扩展的钱包工具和 DApp 识别。
快捷链接
找 Provider
// UKey Wallet 会注册成 Polkadot.js 扩展
const provider = window.$ukey?.polkadot;
// 或者使用标准 web3Enable API
import { web3Enable, web3Accounts } from "@polkadot/extension-dapp";
快上手
启用扩展
// 直接调用 UKey Wallet provider
const enabled = await provider.web3Enable("UKey Wallet Demo");
if (enabled) {
const accounts = await provider.web3Accounts();
console.log("当前账户信息:", accounts);
}
使用 Polkadot.js 扩展 API(优先采用)
import { web3Enable, web3Accounts } from "@polkadot/extension-dapp";
// 打开全部扩展(含 UKey Wallet)
const extensions = await web3Enable("UKey Wallet Demo");
if (extensions.length === 0) {
throw new Error("未找到扩展");
}
// 读取所有账户
const allAccounts = await web3Accounts();
console.log("当前账户信息:", allAccounts);
账户管理
读取账户
const accounts = await provider.web3Accounts();
accounts.forEach((account) => {
console.log({
address: account.address, // Substrate 账户地址
name: account.name, // 账户显示名
type: account.type, // one of 'sr25519' | 'ed25519' | 'ecdsa'
genesisHash: account.genesisHash, // 可选的创世块哈希
});
});
订阅账户变化
const unsubscribe = provider.web3AccountsSubscribe((accounts) => {
console.log("当前账户已切换为:", accounts);
});
// 后续记得取消订阅: unsubscribe()
签署
签名交易 Payload
交易 payload 通常由 Polkadot.js API 生成,钱包负责展示并签名:
import { web3FromAddress } from '@polkadot/extension-dapp'
// 读取特定账户的 injector
const injector = await web3FromAddress(accountAddress)
// 对 payload 做签名
const payload = {
address: accountAddress,
blockHash: '0x...',
blockNumber: '0x...',
era: '0x...',
genesisHash: '0x...',
method: '0x...',
nonce: '0x...',
specVersion: '0x...',
tip: '0x...',
transactionVersion: '0x...',
signedExtensions: [...],
version: 4,
}
const callResult = await provider.web3SignPayload(payload)
console.log({
id: callResult.id,
signature: callResult.signature, // hex 形式的签名
})
签名原始消息
const payload = {
address: accountAddress,
data: "0x48656c6c6f", // hex 编码后的消息内容
type: "bytes",
};
const callResult = await provider.web3SignRaw(payload);
console.log({
id: callResult.id,
signature: callResult.signature,
});
配合 Polkadot.js API 使用
设置
npm install @polkadot/api @polkadot/extension-dapp
连接并签交易
import { ApiPromise, WsProvider } from "@polkadot/api";
import {
web3Enable,
web3FromAddress,
web3Accounts,
} from "@polkadot/extension-dapp";
// 先启用扩展
await web3Enable("UKey Wallet Demo");
// 读取账户
const accounts = await web3Accounts();
const account = accounts[0];
// 建立连接到链
const wsProvider = new WsProvider("wss:/rpc.polkadot.io");
const api = await ApiPromise.create({ provider: wsProvider });
// 读取 injector
const injector = await web3FromAddress(account.address);
// 构建并签名交易
const tx = api.tx.balances.transfer(
recipientAddress,
1000000000000, // equals 1 DOT in planck units
);
// 签名后发出交易
const hash = await tx.signAndSend(account.address, { signer: injector.signer });
console.log("交易哈希值:", hash.toHex());
监听交易事件
await tx.signAndSend(
account.address,
{ signer: injector.signer },
({ status, events }) => {
if (status.isInBlock) {
console.log("已写入区块:", status.asInBlock.toHex());
}
if (status.isFinalized) {
console.log("最终确认区块:", status.asFinalized.toHex());
events.forEach(({ event }) => {
if (api.events.system.ExtrinsicSuccess.is(event)) {
console.log("交易执行成功");
}
if (api.events.system.ExtrinsicFailed.is(event)) {
console.log("交易执行失败");
}
});
}
},
);
RPC 方法
发送 RPC 请求
const requestResult = await provider.web3RpcSend({
method: "chain_getHeader",
requestParams: [],
});
console.log("最新区块头数据:", requestResult.result);
订阅 RPC 事件
const subscriptionId = await provider.web3RpcSubscribe(
{
method: "chain_subscribeNewHeads",
requestParams: [],
},
(response) => {
console.log("捕获到的新区块:", response.result);
},
);
// 后续记得取消订阅
await provider.web3RpcUnSubscribe();
列出可用 Provider
const providers = await provider.web3RpcListProviders();
console.log("发现的 providers:", providers);
API说明
方法集
| 方法 | 说明 |
|---|---|
web3Enable(dappName) | 为 dApp 启用扩展 |
web3Accounts(anyType?) | 获取所有账户 |
web3AccountsSubscribe(callback) | 订阅账户变化 |
web3SignPayload(payload) | 签名交易 payload |
web3SignRaw(payload) | 签名原始消息 |
web3RpcSend(request) | 发送 RPC 请求 |
web3RpcSubscribe(request, callback) | 订阅 RPC 事件 |
web3RpcUnSubscribe() | 取消所有订阅 |
web3RpcListProviders() | 列出 RPC providers |
web3RpcStartProvider(key) | 启动特定 provider |
类型集
interface InjectedAccount {
address: string; // Substrate 账户地址
name?: string; // 账户显示名
type?: "sr25519" | "ed25519" | "ecdsa";
genesisHash?: string; // 可选的创世块限制
}
interface SignerPayloadJSON {
address: string;
blockHash: string;
blockNumber: string;
era: string;
genesisHash: string;
method: string;
nonce: string;
specVersion: string;
tip: string;
transactionVersion: string;
signedExtensions: string[];
version: number;
}
interface SignerPayloadRaw {
address: string;
data: string; // 用十六进制表示的数据内容
type: "bytes" | "payload";
}
interface SignerResult {
id: number;
signature: string; // hex 形式的签名
}
链列表
| 链 | 说明 |
|---|---|
| Polkadot | 默认中继网络 |
| Kusama | 试验先行网络 |
| Acala | 偏向 DeFi 的网络 |
| Moonbeam | 兼容 EVM 的网络 |
| Astar | 侧重合约能力的网络 |
| 任意 Substrate | 用户自定义链 |
处理异常
try {
const callResult = await provider.web3SignPayload(payload);
} catch (error) {
if (error.message === "Cancelled") {
console.log("用户取消了这次签名");
} else {
console.error("签名生成失败:", error);
}
}
配合 React 使用
import { useState, useEffect } from "react";
import { web3Enable, web3Accounts } from "@polkadot/extension-dapp";
function usePolkadotAccounts() {
const [accounts, setAccounts] = useState([]);
const [isConnected, setIsConnected] = useState(false);
const connect = async () => {
const extensions = await web3Enable("UKey Wallet Demo");
if (extensions.length > 0) {
const allAccounts = await web3Accounts();
setAccounts(allAccounts);
setIsConnected(true);
}
};
return { accounts, isConnected, connect };
}