upsertUTXO method
Upsert (insert or update) a UTXO in the read model.
Used by projections to persist UTXO state changes.
Parameters:
walletId: Unique identifier for the walletutxo: UTXO to store
Implementation
@override
Future<void> upsertUTXO(String walletId, BitcoinUtxo utxo) async {
_ensureInitialized();
await _pool!.execute(
Sql.named('''
INSERT INTO bitcoin_utxos (
wallet_id, txid, vout, utxo_key, satoshis, script_pub_key, address,
block_height, confirmations, status, created_at, spent_at,
spent_in_tx_id, script_type, is_spendable, category
) VALUES (
@walletId, @txid, @vout, @utxoKey, @satoshis, @scriptPubKey, @address,
@blockHeight, @confirmations, @status, @createdAt, @spentAt,
@spentInTxId, @scriptType, @isSpendable, @category
)
ON CONFLICT (utxo_key) DO UPDATE SET
satoshis = @satoshis,
script_pub_key = @scriptPubKey,
address = @address,
block_height = @blockHeight,
confirmations = @confirmations,
status = @status,
spent_at = @spentAt,
spent_in_tx_id = @spentInTxId,
is_spendable = @isSpendable
'''),
parameters: {
'walletId': walletId,
'txid': utxo.txid,
'vout': utxo.vout,
'utxoKey': '${utxo.txid}:${utxo.vout}',
'satoshis': utxo.satoshis.toInt(),
'scriptPubKey': utxo.scriptPubKey,
'address': utxo.address,
'blockHeight': utxo.blockHeight,
'confirmations': utxo.confirmations ?? 0,
'status': utxo.status.name,
'createdAt': utxo.createdAt,
'spentAt': null, // Set separately when spent
'spentInTxId': null,
'scriptType': 'p2pkh',
'isSpendable': true,
'category': 'funding',
},
);
}