From af49c340dc50bfa1232a0af89710257a1709372e Mon Sep 17 00:00:00 2001 From: Hippocampus Date: Fri, 20 Dec 2024 22:53:53 +0100 Subject: [PATCH] Fix Ledger integration (#1324) * Fix ledger integration * Changelog --- .changeset/weak-ducks-leave.md | 10 ++++++++++ packages/xchain-bitcoin/src/client.ts | 4 ++-- packages/xchain-bitcoin/src/clientLedger.ts | 4 ++-- packages/xchain-bitcoincash/src/client.ts | 4 ++-- packages/xchain-bitcoincash/src/clientLedger.ts | 7 ++++--- packages/xchain-bitcoincash/src/types/client-types.ts | 1 + packages/xchain-dash/src/client.ts | 4 ++-- packages/xchain-dash/src/clientLedger.ts | 7 ++++--- packages/xchain-dash/src/utils.ts | 4 ++-- packages/xchain-doge/src/client.ts | 10 +++++----- packages/xchain-doge/src/clientLedger.ts | 7 ++++--- packages/xchain-litecoin/src/ClientLedger.ts | 7 ++++--- packages/xchain-litecoin/src/client.ts | 10 +++++----- packages/xchain-utxo/src/types/types.ts | 1 + 14 files changed, 48 insertions(+), 32 deletions(-) create mode 100644 .changeset/weak-ducks-leave.md diff --git a/.changeset/weak-ducks-leave.md b/.changeset/weak-ducks-leave.md new file mode 100644 index 000000000..7537c0340 --- /dev/null +++ b/.changeset/weak-ducks-leave.md @@ -0,0 +1,10 @@ +--- +'@xchainjs/xchain-bitcoincash': patch +'@xchainjs/xchain-litecoin': patch +'@xchainjs/xchain-bitcoin': patch +'@xchainjs/xchain-dash': patch +'@xchainjs/xchain-doge': patch +'@xchainjs/xchain-utxo': patch +--- + +Fix Ledger integration diff --git a/packages/xchain-bitcoin/src/client.ts b/packages/xchain-bitcoin/src/client.ts index 8992f99a9..da7b7f26f 100644 --- a/packages/xchain-bitcoin/src/client.ts +++ b/packages/xchain-bitcoin/src/client.ts @@ -249,7 +249,7 @@ abstract class Client extends UTXOClient { spendPendingUTXO?: boolean }): Promise { // Build the transaction using the provided parameters. - const { psbt, utxos } = await this.buildTx({ + const { psbt, utxos, inputs } = await this.buildTx({ sender, recipient, amount, @@ -258,7 +258,7 @@ abstract class Client extends UTXOClient { spendPendingUTXO, }) // Return the raw unsigned transaction (PSBT) and associated UTXOs. - return { rawUnsignedTx: psbt.toBase64(), utxos } + return { rawUnsignedTx: psbt.toBase64(), utxos, inputs } } } diff --git a/packages/xchain-bitcoin/src/clientLedger.ts b/packages/xchain-bitcoin/src/clientLedger.ts index be2922153..47e41ea8e 100644 --- a/packages/xchain-bitcoin/src/clientLedger.ts +++ b/packages/xchain-bitcoin/src/clientLedger.ts @@ -59,10 +59,10 @@ class ClientLedger extends Client { // Get sender address const sender = await this.getAddressAsync(fromAddressIndex) // Prepare transaction - const { rawUnsignedTx, utxos } = await this.prepareTx({ ...params, sender, feeRate }) + const { rawUnsignedTx, inputs } = await this.prepareTx({ ...params, sender, feeRate }) const psbt = Bitcoin.Psbt.fromBase64(rawUnsignedTx) // Prepare Ledger inputs - const ledgerInputs: [Transaction, number, string | null, number | null][] = (utxos as UTXO[]).map( + const ledgerInputs: [Transaction, number, string | null, number | null][] = (inputs as UTXO[]).map( ({ txHex, hash, index }) => { if (!txHex) { throw Error(`Missing 'txHex' for UTXO (txHash ${hash})`) diff --git a/packages/xchain-bitcoincash/src/client.ts b/packages/xchain-bitcoincash/src/client.ts index 8fe708b36..555bfd06f 100644 --- a/packages/xchain-bitcoincash/src/client.ts +++ b/packages/xchain-bitcoincash/src/client.ts @@ -175,7 +175,7 @@ abstract class Client extends UTXOClient { feeRate: FeeRate }): Promise { // Build the transaction using provided options - const { builder, utxos } = await this.buildTx({ + const { builder, utxos, inputs } = await this.buildTx({ sender, recipient, amount, @@ -183,7 +183,7 @@ abstract class Client extends UTXOClient { feeRate, }) // Return the raw unsigned transaction and UTXOs - return { rawUnsignedTx: builder.buildIncomplete().toHex(), utxos } + return { rawUnsignedTx: builder.buildIncomplete().toHex(), utxos, inputs } } /** * Compile a memo. diff --git a/packages/xchain-bitcoincash/src/clientLedger.ts b/packages/xchain-bitcoincash/src/clientLedger.ts index 879f4f8d3..d405637e7 100644 --- a/packages/xchain-bitcoincash/src/clientLedger.ts +++ b/packages/xchain-bitcoincash/src/clientLedger.ts @@ -1,7 +1,7 @@ import AppBtc from '@ledgerhq/hw-app-btc' import { Transaction } from '@ledgerhq/hw-app-btc/lib/types' import * as bitcash from '@psf/bitcoincashjs-lib' -import { FeeOption, FeeRate, TxHash } from '@xchainjs/xchain-client' +import { FeeOption, FeeRate, TxHash, checkFeeBounds } from '@xchainjs/xchain-client' import { Address } from '@xchainjs/xchain-util' import { TxParams, UtxoClientParams } from '@xchainjs/xchain-utxo' @@ -53,12 +53,13 @@ class ClientLedger extends Client { const fromAddressIndex = params?.walletIndex || 0 // Get fee rate const feeRate = params.feeRate || (await this.getFeeRates())[FeeOption.Fast] + checkFeeBounds(this.feeBounds, feeRate) // Get sender address const sender = await this.getAddressAsync(fromAddressIndex) // Prepare transaction - const { rawUnsignedTx, utxos: txInputs } = await this.prepareTx({ ...params, sender, feeRate }) + const { rawUnsignedTx, inputs } = await this.prepareTx({ ...params, sender, feeRate }) - const ledgerInputs: Array<[Transaction, number, string | null, number | null]> = txInputs.map( + const ledgerInputs: Array<[Transaction, number, string | null, number | null]> = inputs.map( ({ txHex, hash, index }) => { if (!txHex) { throw Error(`Missing 'txHex' for UTXO (txHash ${hash})`) diff --git a/packages/xchain-bitcoincash/src/types/client-types.ts b/packages/xchain-bitcoincash/src/types/client-types.ts index feb5ae705..5f26c824e 100644 --- a/packages/xchain-bitcoincash/src/types/client-types.ts +++ b/packages/xchain-bitcoincash/src/types/client-types.ts @@ -35,4 +35,5 @@ export type GetChangeParams = { export type BchPreparedTx = { utxos: BaseUTXO[] + inputs: BaseUTXO[] } & PreparedTx diff --git a/packages/xchain-dash/src/client.ts b/packages/xchain-dash/src/client.ts index 8d207cc33..c043a3e31 100644 --- a/packages/xchain-dash/src/client.ts +++ b/packages/xchain-dash/src/client.ts @@ -212,7 +212,7 @@ abstract class Client extends UTXOClient { feeRate: FeeRate }): Promise { // Build the transaction using provided parameters - const { tx, utxos } = await Utils.buildTx({ + const { tx, utxos, inputs } = await Utils.buildTx({ sender, recipient, memo, @@ -221,7 +221,7 @@ abstract class Client extends UTXOClient { network: this.network, }) // Return the raw unsigned transaction and UTXOs - return { rawUnsignedTx: tx.toString(), utxos } + return { rawUnsignedTx: tx.toString(), utxos, inputs } } /** * Compiles a memo into a buffer. diff --git a/packages/xchain-dash/src/clientLedger.ts b/packages/xchain-dash/src/clientLedger.ts index d44c3c1ca..8a77d9199 100644 --- a/packages/xchain-dash/src/clientLedger.ts +++ b/packages/xchain-dash/src/clientLedger.ts @@ -1,7 +1,7 @@ import * as dashcore from '@dashevo/dashcore-lib' import AppBtc from '@ledgerhq/hw-app-btc' import { Transaction as LedgerTransaction } from '@ledgerhq/hw-app-btc/lib/types' -import { FeeOption, FeeRate, TxHash } from '@xchainjs/xchain-client' +import { FeeOption, FeeRate, TxHash, checkFeeBounds } from '@xchainjs/xchain-client' import { Address } from '@xchainjs/xchain-util' import { TxParams, UtxoClientParams } from '@xchainjs/xchain-utxo' @@ -56,10 +56,11 @@ class ClientLedger extends Client { const fromAddressIndex = params?.walletIndex || 0 // Get fee rate const feeRate = params.feeRate || (await this.getFeeRates())[FeeOption.Fast] + checkFeeBounds(this.feeBounds, feeRate) // Get sender address const sender = await this.getAddressAsync(fromAddressIndex) // Prepare transaction - const { rawUnsignedTx, utxos } = await this.prepareTx({ ...params, sender, feeRate }) + const { rawUnsignedTx, inputs } = await this.prepareTx({ ...params, sender, feeRate }) const tx = new dashcore.Transaction(rawUnsignedTx) // eslint-disable-next-line @typescript-eslint/no-explicit-any @@ -68,7 +69,7 @@ class ClientLedger extends Client { for (const input of tx.inputs) { // eslint-disable-next-line @typescript-eslint/no-explicit-any - const insightUtxo = utxos.find((utxo) => { + const insightUtxo = inputs.find((utxo) => { return utxo.hash === input.prevTxId.toString('hex') && utxo.index == input.outputIndex }) if (!insightUtxo) { diff --git a/packages/xchain-dash/src/utils.ts b/packages/xchain-dash/src/utils.ts index f95c352fb..f21bf01f1 100644 --- a/packages/xchain-dash/src/utils.ts +++ b/packages/xchain-dash/src/utils.ts @@ -89,7 +89,7 @@ export const buildTx = async ({ sender: Address network: Network withTxHex?: boolean -}): Promise<{ tx: Transaction; utxos: UTXO[] }> => { +}): Promise<{ tx: Transaction; utxos: UTXO[]; inputs: UTXO[] }> => { // Validate recipient address if (!validateAddress(recipient, network)) throw new Error('Invalid address') @@ -152,7 +152,7 @@ export const buildTx = async ({ tx.addData(memo) } - return { tx, utxos } // Return the built transaction and its UTXOs + return { tx, utxos, inputs } // Return the built transaction and its UTXOs } /** diff --git a/packages/xchain-doge/src/client.ts b/packages/xchain-doge/src/client.ts index 82d118f00..e7663ae0b 100644 --- a/packages/xchain-doge/src/client.ts +++ b/packages/xchain-doge/src/client.ts @@ -99,7 +99,7 @@ abstract class Client extends UTXOClient { }: TxParams & { feeRate: FeeRate sender: Address - }): Promise<{ psbt: Dogecoin.Psbt; utxos: UTXO[] }> => { + }): Promise<{ psbt: Dogecoin.Psbt; utxos: UTXO[]; inputs: UTXO[] }> => { // Validate the recipient address if (!this.validateAddress(recipient)) throw new Error('Invalid address') @@ -159,7 +159,7 @@ abstract class Client extends UTXOClient { } }) - return { psbt, utxos } + return { psbt, utxos, inputs } } /** @@ -198,9 +198,9 @@ abstract class Client extends UTXOClient { sender: Address feeRate: FeeRate spendPendingUTXO?: boolean - }): Promise { + }): Promise { // Build the transaction (PSBT) with the specified transfer options - const { psbt, utxos } = await this.buildTx({ + const { psbt, utxos, inputs } = await this.buildTx({ sender, recipient, amount, @@ -209,7 +209,7 @@ abstract class Client extends UTXOClient { }) // Return the raw unsigned transaction (PSBT) - return { rawUnsignedTx: psbt.toBase64(), utxos } + return { rawUnsignedTx: psbt.toBase64(), utxos, inputs } } /** diff --git a/packages/xchain-doge/src/clientLedger.ts b/packages/xchain-doge/src/clientLedger.ts index b57a328cf..f26b9890d 100644 --- a/packages/xchain-doge/src/clientLedger.ts +++ b/packages/xchain-doge/src/clientLedger.ts @@ -1,6 +1,6 @@ import AppBtc from '@ledgerhq/hw-app-btc' import { Transaction } from '@ledgerhq/hw-app-btc/lib/types' -import { FeeOption, FeeRate, TxHash } from '@xchainjs/xchain-client' +import { FeeOption, FeeRate, TxHash, checkFeeBounds } from '@xchainjs/xchain-client' import { Address } from '@xchainjs/xchain-util' import { TxParams, UtxoClientParams } from '@xchainjs/xchain-utxo' import * as Dogecoin from 'bitcoinjs-lib' @@ -52,13 +52,14 @@ class ClientLedger extends Client { const fromAddressIndex = params?.walletIndex || 0 // Get fee rate const feeRate = params.feeRate || (await this.getFeeRates())[FeeOption.Fast] + checkFeeBounds(this.feeBounds, feeRate) // Get sender address const sender = await this.getAddressAsync(fromAddressIndex) // Prepare transaction - const { rawUnsignedTx, utxos } = await this.prepareTx({ ...params, sender, feeRate }) + const { rawUnsignedTx, inputs } = await this.prepareTx({ ...params, sender, feeRate }) const psbt = Dogecoin.Psbt.fromBase64(rawUnsignedTx) // Prepare Ledger inputs - const ledgerInputs: Array<[Transaction, number, string | null, number | null]> = utxos.map( + const ledgerInputs: Array<[Transaction, number, string | null, number | null]> = inputs.map( ({ txHex, hash, index }) => { if (!txHex) { throw Error(`Missing 'txHex' for UTXO (txHash ${hash})`) diff --git a/packages/xchain-litecoin/src/ClientLedger.ts b/packages/xchain-litecoin/src/ClientLedger.ts index 681df3958..b521ef263 100644 --- a/packages/xchain-litecoin/src/ClientLedger.ts +++ b/packages/xchain-litecoin/src/ClientLedger.ts @@ -1,6 +1,6 @@ import AppBtc from '@ledgerhq/hw-app-btc' import { Transaction } from '@ledgerhq/hw-app-btc/lib/types' -import { FeeOption, FeeRate, TxHash } from '@xchainjs/xchain-client' +import { FeeOption, FeeRate, TxHash, checkFeeBounds } from '@xchainjs/xchain-client' import { Address } from '@xchainjs/xchain-util' import { TxParams, UtxoClientParams } from '@xchainjs/xchain-utxo' import * as Litecoin from 'bitcoinjs-lib' @@ -54,13 +54,14 @@ class ClientLedger extends Client { const fromAddressIndex = params?.walletIndex || 0 // Get fee rate const feeRate = params.feeRate || (await this.getFeeRates())[FeeOption.Fast] + checkFeeBounds(this.feeBounds, feeRate) // Get sender address const sender = await this.getAddressAsync(fromAddressIndex) // Prepare transaction - const { rawUnsignedTx, utxos } = await this.prepareTx({ ...params, sender, feeRate }) + const { rawUnsignedTx, inputs } = await this.prepareTx({ ...params, sender, feeRate }) const psbt = Litecoin.Psbt.fromBase64(rawUnsignedTx) // Prepare Ledger inputs - const ledgerInputs: [Transaction, number, string | null, number | null][] = utxos.map(({ txHex, hash, index }) => { + const ledgerInputs: [Transaction, number, string | null, number | null][] = inputs.map(({ txHex, hash, index }) => { if (!txHex) { throw Error(`Missing 'txHex' for UTXO (txHash ${hash})`) } diff --git a/packages/xchain-litecoin/src/client.ts b/packages/xchain-litecoin/src/client.ts index 8907d7d44..2a1693f59 100644 --- a/packages/xchain-litecoin/src/client.ts +++ b/packages/xchain-litecoin/src/client.ts @@ -111,7 +111,7 @@ abstract class Client extends UTXOClient { }: TxParams & { feeRate: FeeRate sender: Address - }): Promise<{ psbt: Litecoin.Psbt; utxos: UTXO[] }> { + }): Promise<{ psbt: Litecoin.Psbt; utxos: UTXO[]; inputs: UTXO[] }> { if (!this.validateAddress(recipient)) throw new Error('Invalid address') const utxos = await this.scanUTXOs(sender, false) @@ -163,7 +163,7 @@ abstract class Client extends UTXOClient { } }) - return { psbt, utxos } + return { psbt, utxos, inputs } } /** @@ -182,8 +182,8 @@ abstract class Client extends UTXOClient { sender: Address feeRate: FeeRate spendPendingUTXO?: boolean - }): Promise { - const { psbt, utxos } = await this.buildTx({ + }): Promise { + const { psbt, utxos, inputs } = await this.buildTx({ sender, recipient, amount, @@ -191,7 +191,7 @@ abstract class Client extends UTXOClient { memo, }) - return { rawUnsignedTx: psbt.toBase64(), utxos } + return { rawUnsignedTx: psbt.toBase64(), utxos, inputs } } /** * Compile memo. diff --git a/packages/xchain-utxo/src/types/types.ts b/packages/xchain-utxo/src/types/types.ts index 28a010638..711ae95c3 100644 --- a/packages/xchain-utxo/src/types/types.ts +++ b/packages/xchain-utxo/src/types/types.ts @@ -24,6 +24,7 @@ export type UtxoClientParams = XChainClientParams & { export type PreparedTx = BasePreparedTx & { utxos: UTXO[] + inputs: UTXO[] } export type TxParams = BaseTxParams & {