BTC Signer
Bitcoin UTXO signing guide. Covers address confirmation and P2PKH / P2SH-P2WPKH / P2WPKH / Taproot signing with strict path–script matching and complete refTxs. Behavior aligned with hardware-js-sdk (Promise responses + UI events).
Index
- How it works
- Installation
- Initialization
- Common scenarios
- Interaction & Status
- Examples
- Validation & Troubleshooting
How it works
OneKey BTC signer talks to the device app via HardwareSDK, wraps APDUs into UTXO review and signing tasks.
- Paths must match script purpose (44/49/84/86).
- Each input needs a full previous transaction (
refTxs), otherwise the device rejects. - The device shows inputs, outputs, change, and fee; after confirmation it returns signatures or a serialized tx.
Installation
npm i @onekeyfe/hd-core @onekeyfe/hd-common-connect-sdkInitialization
import HardwareSDK from '@onekeyfe/hd-common-connect-sdk';
await HardwareSDK.init({ env: 'webusb', fetchConfig: true, debug: false });
const [{ connectId }] = await HardwareSDK.searchDevices();
const deviceId = (await HardwareSDK.getFeatures(connectId)).payload?.device_id;Common scenarios
Scenario 1: Get Address
const res = await HardwareSDK.btcGetAddress(connectId, deviceId, {
path: "m/84'/0'/0'/0/0",
coin: 'btc',
showOnOneKey: true,
});
// res.payload.address, publicKey?, pathParameters
path/address_n: required; must match purpose.coin: required; e.g.,btc,test.showOnOneKey?: optional; display and confirm on device.
Returns
Promise<{ success, payload: { address, path, publicKey?, chainCode? } }>Scenario 2: Sign Transaction
const { success, payload } = await HardwareSDK.btcSignTransaction(connectId, deviceId, {
coin: 'btc',
inputs,
outputs,
refTxs,
locktime: 0,
});
// payload.serializedTx (ready to broadcast)Parameters
coin: required; selects network rules.inputs: required array with:address_n(path matched to script)prev_hash(txid hex)prev_index(vout)amount(string satoshi)script_type(SPENDADDRESS/SPENDP2SHWITNESS/SPENDWITNESS/SPENDTAPROOT)
outputs: required array with:- Recipient:
address+amount+script_type(e.g.,PAYTOADDRESS) - Change:
address_n+amount+script_typealigned to purpose
- Recipient:
refTxs: required; full previous transactions for every input.locktime?: optional.
Returns
Promise<{ success, payload: { serializedTx, signatures?: any } }>Interaction & Status
- APIs resolve on completion; user prompts arrive via
UI_REQUEST(unlock device, open BTC app, confirm inputs/outputs/change/fee). - Run calls serially per device; use
showOnOneKeyto confirm receive/change paths before signing.
Examples
P2SH-P2WPKH transaction
import HardwareSDK from '@onekeyfe/hd-common-connect-sdk';
await HardwareSDK.init({ env: 'webusb', debug: false });
const [{ connectId }] = await HardwareSDK.searchDevices();
const deviceId = (await HardwareSDK.getFeatures(connectId)).payload?.device_id;
const path49 = [(49 | 0x80000000) >>> 0, (0 | 0x80000000) >>> 0, (0 | 0x80000000) >>> 0, 0, 0];
await HardwareSDK.btcGetAddress(connectId, deviceId, { path: path49, coin: 'btc', showOnOneKey: true });
const inputs = [
{
address_n: path49,
prev_index: 0,
prev_hash: 'b035d89d4543ce5713c553d69431698116a822c57c03ddacf3f04b763d1999ac',
amount: '3382047',
script_type: 'SPENDP2SHWITNESS',
},
];
const outputs = [
{
address_n: [(49 | 0x80000000) >>> 0, (0 | 0x80000000) >>> 0, (0 | 0x80000000) >>> 0, 1, 1],
amount: '3181747',
script_type: 'PAYTOP2SHWITNESS', // change
},
{
address: '18WL2iZKmpDYWk1oFavJapdLALxwSjcSk2',
amount: '200000',
script_type: 'PAYTOADDRESS', // recipient
},
];
const refTxs = [
{
hash: 'b035d89d4543ce5713c553d69431698116a822c57c03ddacf3f04b763d1999ac',
version: 1,
lock_time: 0,
inputs: [/* previous tx inputs */],
bin_outputs: [/* previous tx outputs */],
},
];
const { success, payload } = await HardwareSDK.btcSignTransaction(connectId, deviceId, {
coin: 'btc',
inputs,
outputs,
refTxs,
locktime: 0,
});
if (success) {
console.info('signed tx:', payload.serializedTx); // ready to broadcast
}Validation & Troubleshooting
- Path ↔ script:
44'→P2PKH,49'→P2SH-P2WPKH,84'→P2WPKH,86'→P2TR. refTxsmust cover every input; missing data is rejected.- Change output should stay within the same account path.
- Verify on device: inputs, outputs, change, fee must match your UI.
- Host verify: rebuild with
bitcoinjs-lib/@scure/btc-signer, checkserializedTx/txid and signatures. - Common issues:
- Too many inputs: split transactions or simplify.
- Fee anomalies: recalc outputs/change; respect dust rules.
- User reject/timeout: offer retry/cancel; no auto-resubmission.
See method docs: btcSignTransaction · btcGetAddress.
Last updated on