hw-wallet 0.1.2

Shared wallet orchestration utilities for CLI and FFI
Documentation
use serde::Deserialize;
use trezor_connect::thp::{BtcRefTx, BtcRefTxInput, BtcRefTxOutput};

use super::inputs::default_sequence;
use super::sats::parse_sats;
use crate::error::{WalletError, WalletResult};
use crate::hex::{decode, decode_hash32};

#[derive(Debug, Deserialize)]
pub struct TxInputRefTx {
    pub hash: String,
    pub version: u32,
    pub lock_time: u32,
    pub inputs: Vec<TxInputRefTxInput>,
    pub bin_outputs: Vec<TxInputRefTxOutput>,
    pub extra_data: Option<String>,
    pub timestamp: Option<u32>,
    pub version_group_id: Option<u32>,
    pub expiry: Option<u32>,
    pub branch_id: Option<u32>,
}

#[derive(Debug, Deserialize)]
pub struct TxInputRefTxInput {
    pub prev_hash: String,
    pub prev_index: u32,
    pub script_sig: String,
    #[serde(default = "default_sequence")]
    pub sequence: u32,
}

#[derive(Debug, Deserialize)]
pub struct TxInputRefTxOutput {
    pub amount: String,
    pub script_pubkey: String,
}

impl TryFrom<TxInputRefTx> for BtcRefTx {
    type Error = WalletError;

    fn try_from(tx: TxInputRefTx) -> WalletResult<Self> {
        Ok(Self {
            hash: decode_hash32("ref_txs.hash", &tx.hash)?,
            version: tx.version,
            lock_time: tx.lock_time,
            inputs: tx
                .inputs
                .into_iter()
                .map(BtcRefTxInput::try_from)
                .collect::<WalletResult<_>>()?,
            bin_outputs: tx
                .bin_outputs
                .into_iter()
                .map(BtcRefTxOutput::try_from)
                .collect::<WalletResult<_>>()?,
            extra_data: tx.extra_data.as_deref().map(decode).transpose()?,
            timestamp: tx.timestamp,
            version_group_id: tx.version_group_id,
            expiry: tx.expiry,
            branch_id: tx.branch_id,
        })
    }
}

impl TryFrom<TxInputRefTxInput> for BtcRefTxInput {
    type Error = WalletError;

    fn try_from(input: TxInputRefTxInput) -> WalletResult<Self> {
        Ok(Self {
            prev_hash: decode_hash32("ref_txs.inputs.prev_hash", &input.prev_hash)?,
            prev_index: input.prev_index,
            script_sig: decode(&input.script_sig)?,
            sequence: input.sequence,
        })
    }
}

impl TryFrom<TxInputRefTxOutput> for BtcRefTxOutput {
    type Error = WalletError;

    fn try_from(output: TxInputRefTxOutput) -> WalletResult<Self> {
        Ok(Self {
            amount: parse_sats(&output.amount)?,
            script_pubkey: decode(&output.script_pubkey)?,
        })
    }
}