# Class BSV::Wallet::Daemon <a id="class-BSV-Wallet-Daemon"></a>

**Inherits:** `Object`

Persistent process host for background wallet tasks.

Boots logical models (Engine::Broadcast, Engine::TxProof) with OMQ sockets and
a Scheduler with discovery loops inside an Async reactor. This is the runtime
for walletd.

Usage:
    daemon = BSV::Wallet::Daemon.new(store: store, broadcaster: broadcaster)
    daemon.run!  # blocks until stopped

## Constants
### `DEFAULT_SHUTDOWN_TIMEOUT_S` <a id="constant-DEFAULT_SHUTDOWN_TIMEOUT_S"></a> <a id="DEFAULT_SHUTDOWN_TIMEOUT_S-constant"></a>
Default drain budget — see {Scheduler#shutdown}. Configurable per-instance via
the `shutdown_timeout` constructor kwarg.

### `SHUTDOWN_POLL_INTERVAL_S` <a id="constant-SHUTDOWN_POLL_INTERVAL_S"></a> <a id="SHUTDOWN_POLL_INTERVAL_S-constant"></a>
Not documented.

## Attributes
### `scheduler` [R] <a id="attribute-i-scheduler"></a> <a id="scheduler-instance_method"></a>
Returns the value of attribute scheduler.

### `watcher_thread` [R] <a id="attribute-i-watcher_thread"></a> <a id="watcher_thread-instance_method"></a>
Returns the value of attribute watcher_thread.

## Public Instance Methods
### `initialize(store:, broadcaster:, wallet: = nil, network: = nil, callback_token: = nil, shutdown_timeout: = DEFAULT_SHUTDOWN_TIMEOUT_S)` <a id="method-i-initialize"></a> <a id="initialize-instance_method"></a>
- **@param** `store` [BSV::Wallet::Store]
- **@param** `broadcaster` [BSV::Network::Broadcaster]
- **@param** `wallet` [String, nil] wallet name for telemetry
- **@param** `network` [Symbol, nil] :mainnet / :testnet for telemetry
- **@param** `callback_token` [String, nil] Arcade callbackToken
(typically derived via {BSV::Wallet::CallbackToken.derive}).
When set, the daemon both boots the SSE listener fiber to
consume the live status stream AND passes the token to
Engine::Broadcast so every submit's POST carries a matching
X-CallbackToken header -- the two halves of the same #251 push
loop. When nil, the listener is skipped, submits go out without
the header, and resolution falls back entirely to the poll loop.
- **@param** `shutdown_timeout` [Numeric]
- **@return** [Daemon] a new instance of Daemon

### `run!()` <a id="method-i-run-21"></a> <a id="run!-instance_method"></a>
Start the Async reactor. Blocks until stop! is called or interrupted.

### `stop!()` <a id="method-i-stop-21"></a> <a id="stop!-instance_method"></a>
Stop the reactor cooperatively: drain in-flight broadcasts and proof
acquisitions first, then halt the Async task. Drain timeout is
+@shutdown_timeout+; on timeout the reactor stops anyway and any
still-in-flight work is killed mid-fibre.

Idempotent — repeat calls after the first are no-ops, so the
<code>daemon.stopped</code> event fires exactly once even if the watcher
thread races a programmatic caller.

Safe to call from any thread or fiber EXCEPT a signal trap —Scheduler#shutdown
uses Mutex and sleep, which raise ThreadError in trap context. Signal traps
must set +@stop_requested+ instead; the watcher thread installed by {#run!}
picks it up and calls <code>stop!</code> off-trap.
