Skip to Content
硬件接入
本页目录
HARDWARE SDK / ETHEREUM & EVM

evmSignTransaction

请求用户在 OneKey 上确认一笔 Legacy 或 EIP-1559(Type 2)交易。设备使用指定 BIP32 路径派生的密钥签名,返回签名结果;应用负责序列化与广播。设备显示的交易详情取决于固件与 calldata。

const result = await HardwareSDK.evmSignTransaction(connectId, deviceId, params);
01 构造交易02 设备确认03 序列化与广播

调用前

参数

connectIdstring必需

设备发现返回的连接标识。

deviceIdstring必需

getDeviceState 返回的钱包身份标识。

params.pathstring | number[]必需

BIP32 派生路径。SDK 要求至少三个路径分量。

params.transactionobject必需

Legacy 或 EIP-1559 交易。数值字段使用十六进制字符串,chainId 使用数字。

可选通用参数

交易字段

字段类型说明
chainIdnumber目标网络的 Chain ID,位于 transaction 内。
tostring目标地址;ERC-20 调用时为代币合约。
valuestring以 wei 为单位的十六进制金额;ERC-20 调用时使用 0x0。
noncestring发送账户的交易计数,以十六进制表示。
gasLimitstringGas 上限,以十六进制表示。
datastring · optional完整的十六进制 calldata,空数据为 0x。
maxFeePerGasstring · EIP-1559每单位 Gas 的总费用上限,以十六进制 wei 表示。
maxPriorityFeePerGasstring · EIP-1559每单位 Gas 的优先费上限,以十六进制 wei 表示。
gasPricestring · LegacyLegacy 交易的 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。

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 格式序列化。

最后更新于