selectAndLockUtxos

suspend fun selectAndLockUtxos(address: String, tokenType: String, requiredAmount: BigInteger): UtxoSelector.SelectionResult

Select and lock UTXOs for transaction (atomic operation).

Critical: Prevents Double-Spend Race Condition

This method performs selection and locking in a SINGLE database transaction:

  1. SELECT available UTXOs (sorted by value, smallest first)

  2. Perform coin selection (smallest-first algorithm)

  3. UPDATE selected UTXOs to PENDING state

Atomicity: Room's @Transaction ensures this is a single SQLite transaction. No other thread can select the same UTXOs between steps 1-3.

Why Atomic?

// ❌ WITHOUT @Transaction (RACE CONDITION):
Thread A: SELECT utxos WHERE state = AVAILABLE → [utxo1, utxo2]
Thread B: SELECT utxos WHERE state = AVAILABLE → [utxo1, utxo2] // SAME UTXOs!
Thread A: UPDATE utxos SET state = PENDING
Thread B: UPDATE utxos SET state = PENDING
Result: DOUBLE-SPEND! Both threads use same UTXOs

// ✅ WITH @Transaction (SAFE):
Thread A: [SELECT + UPDATE in one transaction] → LOCKS [utxo1, utxo2]
Thread B: [waits for Thread A's transaction to complete]
Thread B: SELECT utxos WHERE state = AVAILABLE → [utxo3, utxo4] // Different UTXOs!
Result: SAFE! Each thread gets different UTXOs

Uses the smallest-first coin selection and state management strategy standard to the Midnight wallet model.

Usage in Transaction Builder:

// Lock UTXOs for transaction
val result = utxoManager.selectAndLockUtxos(
address = senderAddress,
tokenType = "NIGHT",
requiredAmount = BigInteger("100000000")
)

when (result) {
is SelectionResult.Success -> {
// Build transaction with result.selectedUtxos
// Create change output with result.change (if 0)
}
is SelectionResult.InsufficientFunds -> {
// Show error to user
}
}

// If transaction fails, unlock UTXOs:
utxoManager.unlockUtxos(result.selectedUtxos.map { it.id })

Return

SelectionResult (Success with locked UTXOs, or InsufficientFunds)

Parameters

address

Owner address

tokenType

Token type to select

requiredAmount

Amount needed (in smallest units)