Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,13 @@ title: kaspaSignTransaction
* Firmware version required
* Touch: 4.3.0
* Classic/Mini: 3.0.0
* `useTweak: false` requires newer firmware on some models
* Pro: 4.14.0+
* Classic 1S: 3.12.0+

## Kaspa: Sign transaction

Asks device to sign given transaction using the private key derived by given BIP32 path. User is asked to confirm all transaction details on OneKey.
Signs a Kaspa transaction with the private key derived from the given BIP32 path. The SDK can negotiate between the legacy blind-sign flow and the newer streaming flow based on the payload you send and the firmware the device exposes.

```typescript
const result = await HardwareSDK.kaspaSignTransaction(connectId, deviceId, params);
Expand All @@ -23,63 +26,91 @@ const result = await HardwareSDK.kaspaSignTransaction(connectId, deviceId, param
[**Optional common params**](/en/hardware-sdk/core-api-guide#common-params)

* `version` - _required_ `number` transaction version.
* `inputs` - _required_ `Array` of [KaspaSignInputParams](https://github.com/OneKeyHQ/hardware-js-sdk/blob/269ee367141ae2186a9a63d1d89e9f4c70428623/packages/core/src/types/api/kaspaSignTransaction.ts#L9C1-L19C3).
* `outputs` - _required_ `Array` of [KaspaSignOutputParams](https://github.com/OneKeyHQ/hardware-js-sdk/blob/269ee367141ae2186a9a63d1d89e9f4c70428623/packages/core/src/types/api/kaspaSignTransaction.ts#L21C1-L26C1).
* `lockTime` - _required_ `number` 
* `sigHashType` - _required_ `number` 
* `inputs` - _required_ `Array`
* `path`, `prevTxId`, `outputIndex`, and `sequenceNumber` are required on every input.
* `output.satoshis` is required.
* `output.script` is optional, but it is still needed by the legacy host-prehash flow.
* `sigOpCount` defaults to `1` per input.
* `outputs` - _required_ `Array`
* `satoshis` is required.
* Use `address` for a recipient output, or `addressN` for a change output, when you want the streaming protocol.
* `script` and `scriptVersion` stay available for legacy compatibility.
* `lockTime` - _required_ `number | string`
* `sigHashType` - _optional_ `number`
* ```
SIGHASH_ALL = 0x01,
SIGHASH_NONE = 0x02,
SIGHASH_SINGLE = 0x03,
SIGHASH_FORKID = 0x40,
SIGHASH_ANYONECANPAY = 0x80,
```
* `sigOpCount` - _optional_ `number` 
* `subNetworkID` - _optional_ `string` 
* `prefix` - _optional_ `string` Address prefix. Default is set to `kaspa`
* `scheme` - _optional_ `string` Encryption algorithm mode. Default is set to `schnorr`


* Default: `SIGHASH_ALL | SIGHASH_FORKID`
* `sigOpCount` - _optional_ `number` transaction-level default for inputs that do not override it
* `subNetworkID` - _optional_ `string` Default is the all-zero subnetwork id
* `payload` - _optional_ `string` Hex-encoded transaction payload
* `gas` - _optional_ `number | string` Default is `0`
* `refTxs` - _optional_ `Array` of previous transactions that the device may request for on-device input amount verification
* `prefix` - _optional_ `string` Address prefix. Default is `kaspa`
* `scheme` - _optional_ `string` Signature scheme. Default is `schnorr`
* `useTweak` - _optional_ `boolean` Default is `true`

### Flow selection and constraints

* Streaming verification is available when every output includes `address` or `addressN`, the transaction uses the default sighash, and the involved scripts are plain P2PK scripts or omitted.
* If the transaction is still legacy-signable and `refTxs` is missing, the SDK prefers blind signing for wider firmware compatibility.
* KRC20-style P2SH commit or reveal scripts are not streamable and must use blind signing.
* When the device asks for a previous transaction, the SDK matches it by `prevTxId` inside `refTxs`. Keep those ids exact.

### Examples

```typescript
const inputScript = `20${'ab'.repeat(32)}ac`;
const recipientAddress =
'kaspa:qr0lr4ml9fn3chekrqmjdkergxl93l4wrk3dankcgvjq776s9wn9jkdskewva';

const response = await HardwareSDK.kaspaSignTransaction(
connectId,
deviceId,
{
version: 0,
lockTime: '0',
sigHashType: 0x1,
sigOpCount: 1,
subNetworkID: "00000000000000000000000000000000",
prefix: "prefix",
scheme: "schnorr",
inputs: [
{
outputIndex: 1,
path: "m/44'/111111'/0'/0/0",
prevTxId: '1f226507807ff7dc5a7f8f2dec353fffc9dacc2645d8aecd02e5046907e3e2b2',
prevTxId: 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa',
outputIndex: 1,
sequenceNumber: '0',
sigOpCount: 1,
output: {
satoshis: '990096458',
script: '207afdae557e69c0040fd4135adffc60f9486fb21f4cbae233fd6db3e84ba47c55ac',
script: inputScript,
},
},
],
outputs: [
{
satoshis: '100000000',
script: '205ca3a7530284e5c5e472544edd6002c3afeb8c8f84d3a728fad255a4872753fbac',
scriptVersion: 0,
address: recipientAddress,
script: inputScript,
},
{
satoshis: '890094182',
script: '207afdae557e69c0040fd4135adffc60f9486fb21f4cbae233fd6db3e84ba47c55ac',
scriptVersion: 0,
addressN: "m/44'/111111'/0'/0/1",
script: inputScript,
},
],
refTxs: [
{
txId: 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa',
version: 0,
inputs: [],
outputs: [
{
satoshis: '990096458',
script: inputScript,
},
],
},
]
],
}
);
```
Expand All @@ -89,21 +120,31 @@ Result
```typescript
{
success: true,
payload: {
index: 0,
signature: "signed data"
}
payload: [
{
index: 0,
signature: 'signed data',
},
],
}
```

The SDK returns one signature per input and normalizes the final array by `index`, even if the device streams signatures back out of order.

Error

```typescript
{
success: false,
payload: {
error: string, // error message
code: number // error code
}
success: false,
payload: {
error: string, // error message
code: number, // error code
},
}
```

### Troubleshooting

* `HardwareErrorCode.KaspaPrevTxIdMismatch` (`829`): the device rejected one of the referenced previous transactions. Rebuild `refTxs` from the same source as the current transaction inputs instead of silently retrying without them.
* `HardwareErrorCode.CallMethodNeedUpgradeFirmware` (`407`): the transaction is streaming-only, but the connected firmware cannot decode the streaming packet.
* `HardwareErrorCode.CallMethodInvalidParameter` (`405`): the payload does not describe a valid output set for either protocol, or the device requested a previous transaction that is missing from `refTxs`.
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,13 @@ title: kaspaSignTransaction
* 固件版本要求
* Touch: 4.3.0
* Classic/Mini: 3.0.0
* 某些机型在 `useTweak: false` 时需要更高固件版本
* Pro: 4.14.0+
* Classic 1S: 3.12.0+

## Kaspa:签名交易

使用指定 BIP32 路径派生的私钥对交易进行签名。用户需要在 OneKey 上确认所有交易详情
使用指定 BIP32 路径派生的私钥对 Kaspa 交易进行签名。SDK 会根据你传入的参数结构和设备固件能力,在传统盲签流程与新的流式签名流程之间自动协商

```typescript
const result = await HardwareSDK.kaspaSignTransaction(connectId, deviceId, params);
Expand All @@ -23,63 +26,91 @@ const result = await HardwareSDK.kaspaSignTransaction(connectId, deviceId, param
[**可选通用参数**](/zh/hardware-sdk/core-api-guide#common-params)

* `version` - _必需_ `number` 交易版本。
* `inputs` - _必需_ [KaspaSignInputParams](https://github.com/OneKeyHQ/hardware-js-sdk/blob/269ee367141ae2186a9a63d1d89e9f4c70428623/packages/core/src/types/api/kaspaSignTransaction.ts#L9C1-L19C3) 的 `Array`。
* `outputs` - _必需_ [KaspaSignOutputParams](https://github.com/OneKeyHQ/hardware-js-sdk/blob/269ee367141ae2186a9a63d1d89e9f4c70428623/packages/core/src/types/api/kaspaSignTransaction.ts#L21C1-L26C1) 的 `Array`。
* `lockTime` - _必需_ `number`
* `sigHashType` - _必需_ `number`
* `inputs` - _必需_ `Array`
* 每个 input 都必须提供 `path`、`prevTxId`、`outputIndex` 和 `sequenceNumber`。
* `output.satoshis` 为必填项。
* `output.script` 是可选项,但传统 host-prehash 盲签流程仍然需要它。
* 单个 input 的 `sigOpCount` 默认值为 `1`。
* `outputs` - _必需_ `Array`
* `satoshis` 为必填项。
* 如果你希望走流式签名,请为外部收款输出传 `address`,为找零输出传 `addressN`。
* `script` 和 `scriptVersion` 仍然保留,用于兼容传统流程。
* `lockTime` - _必需_ `number | string`
* `sigHashType` - _可选_ `number`
* ```
SIGHASH_ALL = 0x01,
SIGHASH_NONE = 0x02,
SIGHASH_SINGLE = 0x03,
SIGHASH_FORKID = 0x40,
SIGHASH_ANYONECANPAY = 0x80,
```
* `sigOpCount` - _可选_ `number`
* `subNetworkID` - _可选_ `string`
* `prefix` - _可选_ `string` 地址前缀。默认设置为 `kaspa`
* `scheme` - _可选_ `string` 加密算法模式。默认设置为 `schnorr`


* 默认值:`SIGHASH_ALL | SIGHASH_FORKID`
* `sigOpCount` - _可选_ `number` 作为没有单独覆盖值时的交易级默认值
* `subNetworkID` - _可选_ `string` 默认值为全 0 的 subnetwork id
* `payload` - _可选_ `string` 十六进制编码的交易 payload
* `gas` - _可选_ `number | string` 默认值为 `0`
* `refTxs` - _可选_ `Array` 设备在机内校验 input 金额时可能会请求的前序交易
* `prefix` - _可选_ `string` 地址前缀。默认值为 `kaspa`
* `scheme` - _可选_ `string` 签名方案。默认值为 `schnorr`
* `useTweak` - _可选_ `boolean` 默认值为 `true`

### 流程选择与约束

* 当每个 output 都带有 `address` 或 `addressN`、交易使用默认 sighash、且相关脚本是普通 P2PK 脚本或省略时,可以启用流式校验。
* 如果交易同时兼容传统签名流程,而你又没有提供 `refTxs`,SDK 会优先选择盲签,以兼容更广的固件范围。
* KRC20 风格的 P2SH commit/reveal 脚本不能走流式签名,必须使用盲签。
* 当设备请求前序交易时,SDK 会按 `prevTxId` 在 `refTxs` 中做精确匹配。

### 示例

```typescript
const inputScript = `20${'ab'.repeat(32)}ac`;
const recipientAddress =
'kaspa:qr0lr4ml9fn3chekrqmjdkergxl93l4wrk3dankcgvjq776s9wn9jkdskewva';

const response = await HardwareSDK.kaspaSignTransaction(
connectId,
deviceId,
{
version: 0,
lockTime: '0',
sigHashType: 0x1,
sigOpCount: 1,
subNetworkID: "00000000000000000000000000000000",
prefix: "prefix",
scheme: "schnorr",
inputs: [
{
outputIndex: 1,
path: "m/44'/111111'/0'/0/0",
prevTxId: '1f226507807ff7dc5a7f8f2dec353fffc9dacc2645d8aecd02e5046907e3e2b2',
prevTxId: 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa',
outputIndex: 1,
sequenceNumber: '0',
sigOpCount: 1,
output: {
satoshis: '990096458',
script: '207afdae557e69c0040fd4135adffc60f9486fb21f4cbae233fd6db3e84ba47c55ac',
script: inputScript,
},
},
],
outputs: [
{
satoshis: '100000000',
script: '205ca3a7530284e5c5e472544edd6002c3afeb8c8f84d3a728fad255a4872753fbac',
scriptVersion: 0,
address: recipientAddress,
script: inputScript,
},
{
satoshis: '890094182',
script: '207afdae557e69c0040fd4135adffc60f9486fb21f4cbae233fd6db3e84ba47c55ac',
scriptVersion: 0,
addressN: "m/44'/111111'/0'/0/1",
script: inputScript,
},
],
refTxs: [
{
txId: 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa',
version: 0,
inputs: [],
outputs: [
{
satoshis: '990096458',
script: inputScript,
},
],
},
]
],
}
);
```
Expand All @@ -89,21 +120,31 @@ const response = await HardwareSDK.kaspaSignTransaction(
```typescript
{
success: true,
payload: {
index: 0,
signature: "signed data"
}
payload: [
{
index: 0,
signature: 'signed data',
},
],
}
```

每个 input 都会返回一条签名结果。即使设备按乱序返回签名,SDK 也会按 `index` 整理最终数组。

错误

```typescript
{
success: false,
payload: {
error: string, // 错误信息
code: number // 错误码
}
success: false,
payload: {
error: string, // 错误信息
code: number, // 错误码
},
}
```

### 排障

* `HardwareErrorCode.KaspaPrevTxIdMismatch` (`829`):设备拒绝了 `refTxs` 中的某笔前序交易。请使用和当前 inputs 相同的数据源重新构建 `refTxs`,不要静默降级为不带 `refTxs` 的重试。
* `HardwareErrorCode.CallMethodNeedUpgradeFirmware` (`407`):当前交易只能走流式签名,但连接的固件还不能解码对应的数据包。
* `HardwareErrorCode.CallMethodInvalidParameter` (`405`):当前参数既不满足流式输出描述,也不满足传统流程要求,或者设备请求的前序交易不在 `refTxs` 里。
Loading