Skip to content

jmwallet.wallet.models

jmwallet.wallet.models

Wallet data models.

Attributes

AddressStatus = Literal['deposit', 'cj-out', 'non-cj-change', 'new', 'reused', 'used-empty', 'bond', 'flagged'] module-attribute

Classes

AddressInfo

Information about a wallet address for display.

Source code in jmwallet/src/jmwallet/wallet/models.py
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
@dataclass
class AddressInfo:
    """Information about a wallet address for display."""

    address: str
    index: int
    balance: int  # satoshis
    status: AddressStatus
    path: str
    is_external: bool  # True for receive (external), False for change (internal)
    is_bond: bool = False
    locktime: int | None = None  # For fidelity bond addresses
    has_unconfirmed: bool = False  # True if any UTXOs at this address are unconfirmed

    @property
    def short_path(self) -> str:
        """Get shortened path for display (e.g., m/84'/0'/0'/0/5 -> 0/5)."""
        parts = self.path.split("/")
        if len(parts) >= 2:
            return f"{parts[-2]}/{parts[-1]}"
        return self.path
Attributes
address: str instance-attribute
balance: int instance-attribute
has_unconfirmed: bool = False class-attribute instance-attribute
index: int instance-attribute
is_bond: bool = False class-attribute instance-attribute
is_external: bool instance-attribute
locktime: int | None = None class-attribute instance-attribute
path: str instance-attribute
short_path: str property

Get shortened path for display (e.g., m/84'/0'/0'/0/5 -> 0/5).

status: AddressStatus instance-attribute

CoinSelection

Result of coin selection

Source code in jmwallet/src/jmwallet/wallet/models.py
111
112
113
114
115
116
117
118
@dataclass
class CoinSelection:
    """Result of coin selection"""

    utxos: list[UTXOInfo]
    total_value: int
    change_value: int
    fee: int
Attributes
change_value: int instance-attribute
fee: int instance-attribute
total_value: int instance-attribute
utxos: list[UTXOInfo] instance-attribute

UTXOInfo

Extended UTXO information with wallet context

Source code in jmwallet/src/jmwallet/wallet/models.py
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
@dataclass
class UTXOInfo:
    """Extended UTXO information with wallet context"""

    txid: str
    vout: int
    value: int
    address: str
    confirmations: int
    scriptpubkey: str
    path: str
    mixdepth: int
    height: int | None = None  # Block height where UTXO was confirmed (for Neutrino)
    locktime: int | None = None  # Locktime for fidelity bond UTXOs (None for regular UTXOs)
    label: str | None = None  # Human-readable label/note (e.g., "cj-out", "deposit", "change")
    frozen: bool = False  # Whether this UTXO is frozen (excluded from automatic coin selection)

    @property
    def outpoint(self) -> str:
        """Get the outpoint string (txid:vout) for this UTXO."""
        return f"{self.txid}:{self.vout}"

    @property
    def is_fidelity_bond(self) -> bool:
        """Check if this is a fidelity bond UTXO (has a locktime, regardless of expiry)."""
        return self.locktime is not None

    @property
    def is_timelocked(self) -> bool:
        """Check if this is a timelocked (fidelity bond) UTXO.

        Alias for is_fidelity_bond for backward compatibility.
        """
        return self.is_fidelity_bond

    @property
    def is_locked(self) -> bool:
        """Check if this fidelity bond UTXO is currently locked (timelock not yet expired).

        Returns False for non-fidelity-bond UTXOs.
        """
        if self.locktime is None:
            return False
        import time

        return self.locktime > int(time.time())

    @property
    def is_p2wsh(self) -> bool:
        """Check if this UTXO is P2WSH based on scriptpubkey."""
        # P2WSH scriptpubkey: OP_0 (0x00) + PUSH32 (0x20) + 32-byte hash = 34 bytes (68 hex chars)
        if len(self.scriptpubkey) != 68:
            return False
        return self.scriptpubkey.startswith("0020")

    @property
    def is_p2wpkh(self) -> bool:
        """Check if this UTXO is P2WPKH based on scriptpubkey."""
        # P2WPKH scriptpubkey: OP_0 (0x00) + PUSH20 (0x14) + 20-byte hash = 22 bytes (44 hex chars)
        if len(self.scriptpubkey) != 44:
            return False
        return self.scriptpubkey.startswith("0014")
Attributes
address: str instance-attribute
confirmations: int instance-attribute
frozen: bool = False class-attribute instance-attribute
height: int | None = None class-attribute instance-attribute
is_fidelity_bond: bool property

Check if this is a fidelity bond UTXO (has a locktime, regardless of expiry).

is_locked: bool property

Check if this fidelity bond UTXO is currently locked (timelock not yet expired).

Returns False for non-fidelity-bond UTXOs.

is_p2wpkh: bool property

Check if this UTXO is P2WPKH based on scriptpubkey.

is_p2wsh: bool property

Check if this UTXO is P2WSH based on scriptpubkey.

is_timelocked: bool property

Check if this is a timelocked (fidelity bond) UTXO.

Alias for is_fidelity_bond for backward compatibility.

label: str | None = None class-attribute instance-attribute
locktime: int | None = None class-attribute instance-attribute
mixdepth: int instance-attribute
outpoint: str property

Get the outpoint string (txid:vout) for this UTXO.

path: str instance-attribute
scriptpubkey: str instance-attribute
txid: str instance-attribute
value: int instance-attribute
vout: int instance-attribute