PostgresWalletStorage class

PostgreSQL implementation of ReadModelStorage.

Provides read model storage for wallets, UTXOs, transactions, addresses, invoices, payment channels, and SPV data (block headers, merkle proofs).

Implemented types

Constructors

PostgresWalletStorage(PostgresConfig _config)
Creates a new PostgresWalletStorage with the given configuration.

Properties

hashCode → int
The hash code for this object.
no setterinherited
headerInsertChunkSize ↔ int
Headers per multi-row INSERT in storeBlockHeadersBulk. Eight bind parameters per header: 1000 stays far below the protocol's 65535.
getter/setter pair
onDeferredPaymentQuery ↔ void Function(String sql, Map<String, dynamic> parameters)?
Set by tests: receives the SQL and parameters of each listDeferredPayments query.
getter/setter pair
onHeaderInsertStatement ↔ void Function(int rows)?
Called with the row count of each INSERT storeBlockHeadersBulk sends.
getter/setter pair
onTransactionLookupQuery ↔ void Function(String sql, Map<String, dynamic> parameters)?
Set by tests: receives the SQL and parameters of each getTransactionsByTxids, getConfirmedTransactionsFromHeight and getTransactionsByStatusSince query.
getter/setter pair
runtimeType → Type
A representation of the runtime type of the object.
no setterinherited

Methods

checkAddresses(String walletId, List<String> addresses) → Future<Map<String, bool>>
Batch check if addresses belong to wallet (optimized for bulk operations)
override
close() → Future<void>
Closes the storage and releases resources.
countSpentUTXOs(String walletId) → Future<int>
How many of the wallet's UTXO rows are spent.
override
deletePaymentChannel(String channelId) → Future<void>
Delete a payment channel
override
deleteUTXO(String walletId, String txid, int vout) → Future<void>
Delete a UTXO from the read model.
override
deleteWallet(String walletId) → Future<void>
Delete all data for a specific wallet.
override
getAddressCount(String walletId) → Future<int>
Get the count of addresses for a wallet (for verification during import)
override
getAddressesByPurpose(String walletId, String purpose) → Future<List<AddressMetadata>>
The wallet's address rows whose purpose is purpose (for example watch), in no particular order. Filtered in the backend: only the matching rows are loaded (bead libspiffy-p4kv).
override
getAddressesWithMetadata(String walletId, {bool? includeUnused, AddressChain? chain, int? limit, int? offset}) → Future<List<AddressMetadata>>
Get all addresses for a wallet with pagination; only those on chain when it is given.
override
getAddressMetadata(String walletId, String address) → Future<AddressMetadata?>
Get address metadata if it belongs to wallet
override
getAddressRange(String walletId, {required int startIndex, required int count, AddressChain chain = AddressChain.receive}) → Future<List<AddressMetadata>>
Get the addresses on chain by derivation range (efficient for HD wallets)
override
getAddressTransactionCount(String walletId, String address) → Future<int>
Get transaction count for an address
override
getAncestorTransactionsBatch(List<String> txids) → Future<Map<String, String>>
The raw hex of every stored ancestor transaction among txids, as a map txid → rawHex (txids without a row are absent).
override
getAvailableUTXOs(String walletId) → Future<List<BitcoinUtxo>>
Get only available (unspent and unreserved) UTXOs for a wallet.
override
getBalance(String walletId) → Future<BigInt>
ReadModelStorage.getBalance: splitBalanceUtxos over getPaymentUTXOs (plugin-managed UTXOs left out in SQL), as on every backend.
override
getBestHeight() → Future<int>
Get current best block height
override
getBlockHeaderByHash(String hash) → Future<BlockHeader?>
Get block header by hash
override
getBlockHeaderByHeight(int height) → Future<BlockHeader?>
Get block header by height
override
getBlockHeaderRange(int fromHeight, int toHeight) → Future<List<BlockHeader>>
Get range of block headers
override
getChainTip() → Future<BlockHeader?>
Get current chain tip header
override
getConfirmedTransactionsFromHeight(int minHeight, {bool includeWithoutHeight = false}) → Future<List<BitcoinTransaction>>
Confirmed rows of every wallet whose blockHeight is at least minHeight; with includeWithoutHeight, also confirmed rows that have no block height (bead libspiffy-ctkm). Rows come newest first (createdAt descending).
override
getDeferredPayment(String walletId, String txid) → Future<DeferredPayment?>
The deferred payment txid of walletId, or null.
override
getHeightByBlockHash(String hash) → Future<int?>
Get height for a block hash
override
getInvoice(String invoiceId) → Future<InvoiceReadModel?>
Get a specific invoice by ID.
override
getInvoicesByStatus(InvoiceStatus status, {String? walletId}) → Future<List<InvoiceReadModel>>
Get all invoices with a specific status, newest first.
override
getInvoicesByWallet(String walletId) → Future<List<InvoiceReadModel>>
Get all invoices for a specific wallet, newest first.
override
getMerkleProof(String txid) → Future<MerkleProof?>
The current proof of txid: its one MerkleProof.isCurrent row (MerkleProofStatus.verified or MerkleProofStatus.pendingHeader), or null. Orphaned and rejected rows are never returned.
override
getMerkleProofCount({String? walletId}) → Future<int>
Get the count of stored merkle proofs.
override
getMerkleProofHistory(String txid) → Future<List<MerkleProof>>
Every proof row stored for txid, orphaned and rejected ones included, oldest first.
override
getMerkleProofsBatch(List<String> txids) → Future<Map<String, MerkleProof>>
Batch get the current proofs by txid list (see getMerkleProof).
override
getMerkleProofsByStatus(MerkleProofStatus status) → Future<List<MerkleProof>>
Every proof row with status (for example the MerkleProofStatus.pendingHeader proofs to check once headers arrive).
override
getMerkleProofsByStatusBetweenHeights(MerkleProofStatus status, int fromHeight, int toHeight) → Future<List<MerkleProof>>
idx_merkle_proofs_status_height (v016): the rows of status at those heights only (bead hg0).
override
getMerkleProofsByStatusChangedSince(MerkleProofStatus status, DateTime since) → Future<List<MerkleProof>>
idx_merkle_proofs_status_changed (v018): the rows of status changed at or after since only (bead hccp).
override
getMerkleProofsForBlock(String blockHash) → Future<List<MerkleProof>>
The current (MerkleProof.isCurrent) proofs that name blockHash.
override
getOutputsAwaitingAncestorProof(String walletId, {int maxDepth = 20}) → Future<List<OutputAwaitingProof>>
The wallet's unspent outputs that cannot be proven to a counterparty right now, each with the ancestors that stand in the way (bead libspiffy-0lx).
override
getPaymentChannel(String channelId) → Future<PaymentChannel?>
Get a payment channel by ID.
override
getPaymentChannelsForWallet(String walletId) → Future<List<PaymentChannel>>
Get all payment channels for a wallet.
override
getPaymentUTXOs(String walletId) → Future<List<BitcoinUtxo>>
Get available UTXOs suitable for BSV payments.
override
getPendingReceive(String walletId, String txid) → Future<PendingReceive?>
The parked receive of (walletId, txid), resolved or not.
override
getPendingReceivesUpToHeight(int height, {int limit = 64}) → Future<List<PendingReceive>>
Reads idx_pending_receives_waiting (v020): only the waiting rows at or below height, oldest first, capped at limit.
override
getRecentHeaders(int count) → Future<List<BlockHeader>>
Get recent block headers
override
getTransaction(String txid, {String? walletId}) → Future<BitcoinTransaction?>
Get a specific transaction by ID.
override
getTransactionAddresses(String walletId, String txid) → Future<TransactionAddresses>
Get all addresses involved in a transaction
override
getTransactionHistory(String walletId, {int? limit, int? offset}) → Future<List<BitcoinTransaction>>
Get transaction history for a wallet
override
getTransactionsBatch(List<String> txids) → Future<Map<String, BitcoinTransaction>>
Batch get transactions by txid list
override
getTransactionsByAddress(String walletId, String address, {String? direction, int? limit, int? offset}) → Future<List<String>>
Get all transactions involving a specific address
override
getTransactionsByStatus(TransactionStatus status, {String? walletId}) → Future<List<BitcoinTransaction>>
Get transactions by status
override
getTransactionsByStatusSince(TransactionStatus status, DateTime since, {int limit = 100}) → Future<List<BitcoinTransaction>>
The rows with status last updated at or after since, newest first (updatedAt descending), at most limit of them (bead libspiffy-5bju).
override
getTransactionsByTxids(List<String> txids) → Future<List<BitcoinTransaction>>
Every wallet's row for each of txids (bead libspiffy-ctkm).
override
getUTXO(String walletId, String txid, int vout) → Future<BitcoinUtxo?>
The wallet's UTXO row for one outpoint, or null when it holds none.
override
getUTXOs(String walletId, {bool includeSpent = false}) → Future<List<BitcoinUtxo>>
Get all UTXOs for a specific wallet.
override
getUTXOsByPlugin(String walletId, String pluginId, {Map<String, dynamic>? metadataFilter}) → Future<List<BitcoinUtxo>>
Get UTXOs managed by a specific plugin.
override
getUTXOsByTxid(String walletId, String txid, {bool includeSpent = false}) → Future<List<BitcoinUtxo>>
The wallet's UTXO rows created by txid, newest first.
override
getWallet(String walletId) → Future<Map<String, dynamic>?>
Get wallet metadata; null for an unknown or deleted wallet. The metadata entry is a map, empty when the wallet has none, never null.
override
getWalletAddresses(String walletId) → Future<List<String>>
Get all addresses for a wallet
override
getWalletIds() → Future<List<String>>
Get a list of all wallet IDs in storage.
override
getWatchOnlyBalance(String walletId) → Future<BigInt>
The watch-only part of the wallet's getPaymentUTXOs: available UTXOs the wallet holds no key for because a key they need is a watch address (bead libspiffy-vsap). Not part of getBalance; the coordinator's BalanceResponse.watchOnlyBalance.
override
initialize() → Future<void>
Initializes the storage by creating the connection pool.
isWalletAddress(String walletId, String address) → Future<bool>
Check if an address belongs to a wallet (O(1) hash lookup)
override
listDeferredPayments(String walletId, {DeferredPaymentQuery query = const DeferredPaymentQuery()}) → Future<DeferredPaymentPage>
A page of walletId's deferred payments matching query, in its order (createdAt, then txid; newest first unless DeferredPaymentQuery.oldestFirst). Backends answer the default outstanding-only query from an index on (wallet, state, createdAt), never by reading every row. Throws FormatException for a cursor this API did not produce.
override
listInvoices({String? walletId, InvoiceStatus? status}) → Future<List<InvoiceReadModel>>
List invoices, newest first.
override
listWallets() → Future<List<String>>
List the IDs of all existing wallets, newest first.
override
markHeaderAsOrphaned(String hash) → Future<void>
Mark a block header as orphaned due to reorganization
override
markMerkleProofOrphaned(String txid, {String? blockHash, List<String>? onlyIfMerkleProof, DateTime? at}) → Future<bool>
Mark the current proof of txid orphaned: its block left the active chain (audit 3b0, bead libspiffy-mny). The row is kept and stays readable through getMerkleProofHistory; getMerkleProof no longer returns it.
override
noSuchMethod(Invocation invocation) → dynamic
Invoked when a nonexistent method or property is accessed.
inherited
resolvePendingReceive(String walletId, String txid, String resolution, {DateTime? at}) → Future<bool>
Record that the receive of (walletId, txid) stopped waiting: resolution says why (it was recorded, or it failed for a reason more headers cannot change). The row is kept, and no longer replayed.
override
storeAncestorTransaction(String txid, String rawHex) → Future<void>
Store the raw transaction rawHex of txid as ancestor evidence.
override
storeBlockHeader(BlockHeader header, int height) → Future<void>
Store a block header as part of the active chain at height.
override
storeBlockHeadersBulk(List<(BlockHeader, int)> headers) → Future<void>
Bulk store block headers: a CDN import, or a run of headers a peer sent (BlockHeaderChain.acceptHeaders).
override
storeDeferredPayment(DeferredPayment payment) → Future<void>
Insert or replace the row of payment (key: walletId, txid).
override
storeInvoice(InvoiceReadModel invoice) → Future<void>
Store an invoice read model (insert, or replace an existing row with the same invoiceId).
override
storeMerkleProof(String txid, MerkleProof proof) → Future<void>
Rows are only added or updated (bead mny; v009 enforces one row per (txid, block hash) and v012 one current (verified or pendingHeader) row per txid). The rows of txid are read and written in one transaction holding a per-txid advisory lock; see ReadModelStorage.storeMerkleProof and planMerkleProofStore.
override
storePaymentChannel(PaymentChannel channel) → Future<void>
Store a payment channel (insert, or replace every mutable column of an existing row with the same channelId).
override
storePendingReceive(PendingReceive receive) → Future<void>
Park receive until headers reach its neededHeight, or update the row already parked for its (walletId, txid).
override
storeRevertedTransaction(String walletId, BitcoinTransaction transaction) → Future<void>
Stores transaction as the row of (walletId, txid) with the status, block height and confirmations it carries, even when that lowers a confirmed status: the one way a confirmation is taken back, used for a reorganization past the confirming block or a proof its block header contradicts (audit 3b0, bead libspiffy-7dj). A non-confirmed record clears the stored block height. Raw hex and the other rules of storeTransaction apply; nothing is deleted.
override
storeTransaction(String walletId, BitcoinTransaction transaction) → Future<void>
Store a raw transaction in the read model.
override
storeTransactionAddresses(String walletId, String txid, List<TransactionAddressLink> links) → Future<void>
Store transaction-address junction records.
override
storeWallet(String walletId, String name, {String? rootAddress, String? networkType, Map<String, dynamic>? metadata}) → Future<void>
Store or update wallet metadata.
override
toString() → String
A string representation of this object.
inherited
updateAddressUsage(String walletId, String address, {DateTime? usedAt, BigInt? balanceDelta}) → Future<void>
Update address usage statistics.
override
updateInvoiceStatus(String invoiceId, InvoiceStatus status, {String? txid, BigInt? amountReceived, DateTime? paidAt}) → Future<void>
Update the status of an invoice.
override
updatePaymentChannelBalance(String channelId, BigInt clientBalance, BigInt serverBalance) → Future<void>
Update payment channel balances
override
updatePaymentChannelState(String channelId, String state) → Future<void>
Update payment channel state.
override
upsertAddress(String walletId, AddressMetadata metadata) → Future<void>
Store or update address metadata
override
upsertUTXO(String walletId, BitcoinUtxo utxo) → Future<void>
Inserts or updates the (walletId, txid, vout) row.
override
walletExists(String walletId) → Future<bool>
Check if a wallet exists in storage.
override

Operators

operator ==(Object other) → bool
The equality operator.
inherited