BitcoinWalletAggregate class
Bitcoin wallet aggregate root implementing event sourcing
This aggregate manages all wallet state changes through events, ensuring consistency and providing full audit trail for all operations. Follows the Eventador AggregateRoot pattern with functional state management.
One aggregate (persistence id BitcoinWallet_<walletId>) holds the whole
wallet, so a command's checks (a spend checks the UTXO, its reservation
and deferred holds) see one consistent state. The aggregate itself is the
actor plumbing: command and event dispatch, replies, persistence
callbacks and queries. The wallet's rules live in collaborators under
wallet/ (bead libspiffy-dp4), which work on the state they are given
and know nothing of actors or the journal:
WalletLifecycle: creation, configuration, deletion.AddressBook: addresses, derivation records, watch addresses.WalletKeys: key material, root and address derivation, private keys.UtxoLedger: receiving, confirming and spending UTXOs, availability, selection, the Benford split initiation.UtxoReservations: reserve, release, renew, expire.DeferredPayments: deferred payments and the holds on their inputs.OutgoingTransactions: imported and outgoing transaction records, the wallet outputs they create, confirmations.WalletTransactionSigner: signing P2PKH, P2PK and multisig inputs.ChannelFunding: payment channel funding transactions.WalletBalances(models): the balance rule.
Constructors
- BitcoinWalletAggregate({required String aggregateId, required String aggregateType, required EventStore eventStore, required CryptoService cryptoService, required SecureStorage secureStorage})
Properties
- aggregateId → String
-
The aggregate ID for this aggregate root
no setterinherited
- aggregateType → String
-
The aggregate type for this aggregate root
no setterinherited
-
commandHandlers
→ CommandHandlerRegistry<
WalletState> -
Command handler registry for this aggregate
no setterinherited
- cryptoService → CryptoService
-
final
- currentState → WalletState
-
Current state of the aggregate (non-nullable)
Throws if the aggregate hasn't been initialized
no setterinherited
-
eventHandlers
→ EventHandlerRegistry<
WalletState> -
Event handler registry for this aggregate
no setterinherited
- eventStore → EventStore
-
Current event store instance
no setterinherited
- hashCode → int
-
The hash code for this object.
no setterinherited
- isInitialized → bool
-
Whether the aggregate has been initialized with state
no setterinherited
- isOutOfService → bool
-
True once an infrastructure failure has taken this incarnation out of
service.
no setterinherited
- isRecovered → bool
-
Whether this actor has completed recovery
no setterinherited
- isRecovering → bool
-
Whether this actor is currently recovering from events
no setterinherited
- persistenceId → String
-
Unique identifier for this persistent actor
Used to store and retrieve events from the event store
no setterinherited
-
recoveryComplete
→ Future<
void> -
Future that completes when recovery finishes.
no setterinherited
- runtimeType → Type
-
A representation of the runtime type of the object.
no setterinherited
- secureStorage → SecureStorage
-
final
- sequenceNumber → int
-
Current sequence number for this actor
Incremented with each persisted event
no setterinherited
- state → WalletState?
-
Current state of the aggregate
Returns null if the aggregate hasn't been initialized yet
no setterinherited
Methods
-
applyEvent(
WalletState current, Event event) → WalletState -
Applies
eventtocurrentand returns the next state (Eventador pattern; bead libspiffy-mmb). -
canApplyEvent(
Event event) → bool -
Check if the aggregate can apply a specific event
Override in subclasses for custom event routing
inherited
-
canHandleCommand(
Command command) → bool -
Check if the aggregate can handle a specific command
Override in subclasses for custom command routing
inherited
-
canReserveUTXO(
WalletState state, String utxoKey) → bool - Check if UTXO can be reserved (business rules)
-
canSpendUTXO(
WalletState state, String utxoKey) → bool - Check if UTXO can be spent (business rules)
-
checkConcurrency(
int expectedVersion) → Future< void> -
Check optimistic concurrency control with expected version
Public method for explicit concurrency checking
inherited
-
commandHandler(
Command command) → Future< void> -
Process a command through the full pipeline
This is the main entry point for command processing.
inherited
-
createInitialState(
) → WalletState - Create initial empty wallet state
-
createSnapshot(
) → Future< void> -
Create a snapshot of current state
Override to provide custom snapshot logic
inherited
-
ensureStateInitialized(
) → void -
Initialize the aggregate state
This is a protected method that subclasses can use when overriding eventHandler
to ensure state is initialized before processing events (replicating base class behavior)
inherited
-
eventHandler(
Event event) → void -
Apply an event to update the aggregate state
This is called during both command processing and recovery
inherited
-
getAggregateInfo(
) → AggregateInfo -
Get aggregate information for debugging and monitoring
inherited
-
getAvailableUTXOs(
WalletState state) → List< BitcoinUtxo> - Get available UTXOs for spending (excludes plugin-managed UTXOs like tokens, and watch-only UTXOs at watch addresses, bead libspiffy-87a2)
-
getBusinessRuleViolations(
WalletState state) → List< String> -
Get business rule violations for the current state
Override in subclasses to provide specific violation messages
inherited
-
getReservedUTXOs(
WalletState state, String reservationId) → List< BitcoinUtxo> - Get UTXOs with specific reservation
-
getSnapshotState(
) → Future -
Get the current state for snapshot creation
inherited
-
handleCommand(
WalletState currentState, Command command) → Future< List< Event> > - Handle commands asynchronously and return events
-
hasSufficientBalance(
WalletState state, BigInt requiredAmount) → bool -
Whether selectUTXOsForAmount can cover
requiredAmount: WalletState.availableBalance, the total of the UTXOs it may select, is at leastrequiredAmount. Fees are the caller's to add. -
isInfrastructureFailure(
Object? error) → bool -
Whether
error, raised while processing the current command, is an infrastructure failure (see the mixin documentation) rather than a rejection of the command.inherited -
noSuchMethod(
Invocation invocation) → dynamic -
Invoked when a nonexistent method or property is accessed.
inherited
-
onCommandFailure(
Command command, dynamic error) → Future< void> - Send error responses when command processing fails Only active when aggregate is used as an actor in the actor system
-
onCommandProcessed(
Command command, List< Event> events) → Future<void> - Send response messages after successful command processing Only active when aggregate is used as an actor in the actor system
-
onError(
Object error, StackTrace stackTrace) → void -
Called when an error occurs.
inherited
-
onEventApplicationFailure(
Event event, dynamic error) → void - Logged instead of eventador's print; the error is rethrown.
-
onEventApplied(
Event event, WalletState newState) → void -
Called after an event has been applied to the state
Override to perform post-event application actions
inherited
-
onMessage(
dynamic message) → Future< void> - Handle incoming messages with command/event routing
-
onMessageDropped(
dynamic message) → Future< void> -
Called when a message is dropped because recovery timed out or failed.
Override to send error responses, log, or enqueue for retry.
inherited
-
onPersist(
Event event) → Future< void> -
Called after successful event persistence
Override to perform post-persistence actions
inherited
-
onPersistBatch(
List< Event> events) → Future<void> -
Called after successful batch event persistence
Override to perform post-persistence actions for batches
inherited
-
onPersistBatchFailure(
List< Event> events, dynamic error) → Future<void> -
Called when batch event persistence fails
Override to handle batch persistence failures
inherited
-
onPersistFailure(
Event event, dynamic error) → Future< void> -
Called when event persistence fails
Override to handle persistence failures
inherited
-
onRecover(
) → Future< void> -
Called at the start of recovery process
Override to perform custom recovery initialization
inherited
-
onRecoveryComplete(
) → Future< void> - Called when recovery is complete Override to perform post-recovery initialization
-
onRecoveryFailure(
dynamic error) → Future< void> -
Called when recovery fails
Override to handle recovery failures
inherited
-
onReplay(
Event event) → Future< void> -
Called for each event during replay
Override to perform custom replay logic
inherited
-
onSnapshot(
dynamic snapshotState, int sequenceNumber) → Future< void> -
Restore state from snapshot during recovery
inherited
-
onSnapshotCreated(
dynamic state, int sequenceNumber) → Future< void> -
Called when a snapshot is created
Override to perform post-snapshot actions
inherited
-
onSnapshotRestorationFailure(
dynamic snapshotData, int sequenceNumber, dynamic error) → Future< void> - A snapshot that cannot be restored must fail recovery. Eventador's default falls back to the empty state and then replays only the events after the snapshot, silently dropping the wallet's history.
-
onSnapshotRestored(
WalletState state, int sequenceNumber) → Future< void> -
Called after state has been restored from a snapshot
Override to perform post-snapshot restoration actions
inherited
-
persistEvent(
Event event) → Future< void> -
Persist an event to the event store
Events are immutable and stored permanently
inherited
-
persistEvents(
List< Event> events) → Future<void> -
Persist multiple events atomically
All events succeed or all fail together
inherited
-
postStop(
) → void -
Called when the actor is stopped.
inherited
-
preStart(
) → Future< void> - Registers with the snapshot manager and recovers state.
-
queryHandler(
dynamic message) → Future< void> - Non-command messages. WalletOwnershipQuery is answered from this aggregate's state (bead libspiffy-29t): the mailbox is FIFO, so the answer reflects every command handled before it, including an address generation already acknowledged to its caller.
-
registerHandlers(
) → void - Register command and event handlers
-
replay(
List< Event> events) → void -
Replay events to rebuild aggregate state
Used during recovery and testing
inherited
-
restoreFromSnapshot(
dynamic snapshotData, int sequenceNumber) → Future< WalletState> -
Restore state from snapshot data
Override in subclasses to provide custom restoration logic
inherited
-
restoreStateFromMap(
Map< String, dynamic> map, int sequenceNumber) → Future<WalletState> -
Rebuilds the wallet state from a snapshot written by
getSnapshotState(after the event store's CBOR round trip). -
selectUTXOsForAmount(
WalletState state, BigInt amount) → List< BitcoinUtxo> - Select UTXOs for a specific amount (simple first-fit algorithm)
-
toString(
) → String -
A string representation of this object.
inherited
-
validateBusinessRules(
WalletState state) → bool -
Validate business rules for the current state
Override in subclasses to implement domain-specific validation
inherited
Operators
-
operator ==(
Object other) → bool -
The equality operator.
inherited
Constants
- changePurpose → const String
- Chain discriminator on AddressGeneratedEvent.purpose / GenerateAddressCommand.purpose.
- deferredHoldPriority → const int
-
reservationPriorityof a held input. Informational: a hold is refused to every reservation by rule, not by priority. - deferredHoldReason → const String
-
reservationReasonof a held input.