UTXO Context¶
A UtxoContext tracks UTXOs
for a fixed set of addresses. It's bound to a
UtxoProcessor (see UTXO Processor) and fed by it: as the processor
receives notifications from the node, it routes changes to whichever
contexts have registered the relevant addresses. The context exposes
the resulting UTXO set, balance, and mature/pending splits.
The managed Wallet (see Wallet) creates one UtxoContext
per activated account internally.
UtxoContext can be used when you want UTXO tracking outside of Wallet.
Build one¶
from kaspa import NetworkId, Resolver, RpcClient, UtxoContext, UtxoProcessor
client = RpcClient(resolver=Resolver(), network_id="testnet-10")
await client.connect()
processor = UtxoProcessor(client, NetworkId("testnet-10"))
await processor.start()
context = UtxoContext(processor)
await context.track_addresses(["kaspatest:qr0lr4ml..."])
UtxoContext(processor, id=...) accepts an optional 32-byte hex id;
omitted ids are generated. Set an explicit id when you need the
context to be addressable across reconnects.
What it exposes¶
print(context.is_active) # bool — see "Lifecycle" below
print(context.balance) # Balance | None
print(context.balance_strings) # BalanceStrings | None (formatted)
print(context.mature_length) # int — number of spendable UTXOs
mature = context.mature_range(from_=0, to=10) # list[UtxoEntryReference]
pending = context.pending() # list[UtxoEntryReference]
balance is None until the first notification arrives; after that
it's a Balance(mature, pending, outgoing) in sompi
(balance_strings returns the formatted form);
mature_range and pending return UtxoEntryReferences.
Lifecycle¶
A UtxoContext has no separate active/inactive state of its own —
context.is_active mirrors the bound processor. Implications:
- The context's address set and in-memory UTXOs persist as long as the Python object lives, even if the processor is stopped or the socket dropped. On reconnect the processor re-registers them automatically.
track_addresses(addresses, current_daa_score=None)adds addresses, subscribes the processor toUtxosChangedfor them, and seeds the mature set via a singleget_utxos_by_addressesRPC. Passcurrent_daa_scoreonly if you need the maturity classification of the seeded UTXOs to use a DAA score other than the processor's current one — for example, when reconstructing balances at a specific historical point.unregister_addresses([...])removes those addresses and stops the matchingUtxosChangedsubscription. UTXOs they contributed remain in the in-memory set until evicted by a notification or byclear().clear()unregisters every tracked address (unsubscribing from the node) and drops every cached UTXO. The context is reusable —track_addressesagain to rehydrate it.
await context.track_addresses(["kaspatest:..."])
await context.unregister_addresses(["kaspatest:..."])
await context.clear()
track_addresses accepts Address instances or their string forms.
Use as Generator input¶
The Generator (see Transaction Generator) accepts a UtxoContext
as its entries argument:
from kaspa import Generator, PaymentOutput
gen = Generator(
entries=context, # mature UTXOs come from here
change_address=my_addr,
outputs=[PaymentOutput(recipient, 100_000_000)],
)
This avoids snapshotting the UTXO list yourself — the generator pulls the current mature set when it iterates.
Where to next¶
- Transaction Generator — sending using a
UtxoContextas input. - UTXO Processor — the engine the context is bound to.
- Wallet → Architecture — how the managed
Wallet uses
UtxoContexts internally.