本页目录
evmSignTransaction
请求用户在 OneKey 上确认一笔 Legacy 或 EIP-1559(Type 2)交易。设备使用指定 BIP32 路径派生的密钥签名,返回签名结果;应用负责序列化与广播。设备显示的交易详情取决于固件与 calldata。
const result = await HardwareSDK.evmSignTransaction(connectId, deviceId, params);调用前
- 初始化 SDK 并选择设备。
- 注册 UI 事件处理器,并明确选择标准钱包或目标隐藏钱包。
- 从目标网络获取当前 Nonce、Gas 和费率。
参数
connectIdstring必需设备发现返回的连接标识。
deviceIdstring必需getDeviceState 返回的钱包身份标识。
params.pathstring | number[]必需BIP32 派生路径。SDK 要求至少三个路径分量。
params.transactionobject必需Legacy 或 EIP-1559 交易。数值字段使用十六进制字符串,chainId 使用数字。
交易字段
| 字段 | 类型 | 说明 |
|---|---|---|
chainId | number | 目标网络的 Chain ID,位于 transaction 内。 |
to | string | 目标地址;ERC-20 调用时为代币合约。 |
value | string | 以 wei 为单位的十六进制金额;ERC-20 调用时使用 0x0。 |
nonce | string | 发送账户的交易计数,以十六进制表示。 |
gasLimit | string | Gas 上限,以十六进制表示。 |
data | string · optional | 完整的十六进制 calldata,空数据为 0x。 |
maxFeePerGas | string · EIP-1559 | 每单位 Gas 的总费用上限,以十六进制 wei 表示。 |
maxPriorityFeePerGas | string · EIP-1559 | 每单位 Gas 的优先费上限,以十六进制 wei 表示。 |
gasPrice | string · Legacy | Legacy 交易的 Gas 单价,以十六进制 wei 表示。 |
本页涵盖 EVMTransaction 和 EVMTransactionEIP1559。路径格式见 HD 路径。请确保目标 RPC 支持所用交易类型。
EIP-1559 必须同时提供两个费率字段,Legacy 使用 gasPrice。无需向 SDK 传入 type: 2,该类型在序列化已签名交易时指定。
Clear Signing
原生币转账、ERC-20 转账、授权/撤销和合约调用均使用此方法。ERC-20 调用的 to 是代币合约,value 为零,calldata 中包含收款人/spender 和代币金额。支持的固件自动解析已识别格式;没有 clearSigning、代币元数据或合约标签参数。
输入与展示对照、未知合约行为见 Clear Signing 指南。EIP-712 和 Safe owner 签名使用 evmSignTypedData。
示例
下列片段假设已初始化 SDK 并选定钱包。签名前请替换示例收款人,并从目标网络获取 Nonce、Gas 和费率。
EIP-1559 需要同时提供 maxFeePerGas 和 maxPriorityFeePerGas。Legacy 使用 gasPrice。
EIP-1559
const result = await HardwareSDK.evmSignTransaction(connectId, deviceId, {
path: "m/44'/60'/0'/0/0",
useEmptyPassphrase: true,
transaction: {
to: '0xd0d6d6c5fe4a677d343cc433536bb717bae167dd',
value: '0xf4240',
data: '0x',
chainId: 1,
nonce: '0x0',
maxFeePerGas: '0x77359400',
maxPriorityFeePerGas: '0x3b9aca00',
gasLimit: '0x5208',
},
});
if (result.success === false) throw new Error(result.payload.error);示例明确选择标准钱包。隐藏钱包请传入确认账户时使用的同一组钱包参数。
返回结果
使用 payload 前先检查 success。成功时返回 v、r、s 签名分量;SDK 不会自动广播交易。
成功
{
success: true,
payload: {
v: string, // 带有 "0x" 前缀的十六进制字符串
r: string, // 带有 "0x" 前缀的十六进制字符串
s: string, // 带有 "0x" 前缀的十六进制字符串
}
}交易签名和广播示例
此示例使用 @ethersproject/* v5 和已初始化的 SDK,签名并序列化 EIP-1559(Type 2)交易。广播前应恢复签名者并与选定账户核对。用户签名后,必须保持原始交易字段不变。
import type { EVMTransactionEIP1559 } from '@onekeyfe/hd-core';
import type { UnsignedTransaction } from '@ethersproject/transactions';
import { splitSignature } from '@ethersproject/bytes';
import { TransactionTypes, serialize } from '@ethersproject/transactions';
import { keccak256 } from '@ethersproject/keccak256';
function buildSignedTxFromSignatureEvm({
tx,
signature,
}: {
tx: UnsignedTransaction;
signature: {
v: string | number; // '0x11' , '17', 17
r: string; // 前缀 0x
s: string; // 前缀 0x
};
}) {
const { r, s, v } = signature;
/**
* SDK 的 Legacy 和 EIP-1559 均返回 {v,r,s}。
* splitSignature 自动将 v 转换为 recoveryParam
*/
const sig = splitSignature({
v: Number(v),
r,
s,
});
const rawTx = serialize(tx, sig);
const txid = keccak256(rawTx);
return {
rawTx,
txid,
};
}
// 1. 创建交易参数
const txParams: EVMTransactionEIP1559 = {
to: '0x7314e0f1c0e28474bdb6be3e2c3e0453255188f8',
value: '0x0', // 如果没有值则默认为 0
data: '0x', // 空数据
chainId: 1,
nonce: '0x0',
// 对于 EIP-1559 交易
maxFeePerGas: '0x77359400', // 2 gwei
maxPriorityFeePerGas: '0x3b9aca00', // 1 gwei
gasLimit: '0x5208', // 21000
};
// 2. 签名交易
const result = await HardwareSDK.evmSignTransaction(connectId, deviceId, {
path: "m/44'/60'/0'/0/0",
transaction: txParams,
// Add the same wallet common params used when confirming the account.
});
// 3. 构建已签名交易
if (result.success === false) throw new Error(result.payload.error);
const baseTx: UnsignedTransaction = {
to: txParams.to,
nonce: parseInt(txParams.nonce, 16),
gasLimit: txParams.gasLimit,
data: txParams.data,
value: txParams.value,
chainId: txParams.chainId,
type: TransactionTypes.eip1559,
maxFeePerGas: txParams.maxFeePerGas,
maxPriorityFeePerGas: txParams.maxPriorityFeePerGas,
};
// 4. 使用签名构建最终交易
const { rawTx, txid } = buildSignedTxFromSignatureEvm({
tx: baseTx,
signature: result.payload
});
// 5. 广播交易
// const provider = new ethers.providers.JsonRpcProvider();
// const broadcastedTx = await provider.sendTransaction(rawTx);
// 6. 等待确认
// const receipt = await broadcastedTx.wait();
// console.log('交易已确认:', receipt);Legacy 交易使用 gasPrice,不要传入 EIP-1559 的两个费率字段,并应按 Legacy 格式序列化。