# Module BSV::Wallet::CallbackToken <a id="module-BSV-Wallet-CallbackToken"></a>

Deterministic Arcade callbackToken derivation.

Arcade scopes its SSE +/events?callbackToken=...+ stream by token and matches
it against the <code>X-CallbackToken</code> header carried on each broadcast
POST. The wallet needs a stable per-wallet identifier so the listener and the
submit-side use the same value -- otherwise the listener subscribes to one
stream and Arcade publishes status events on another.

We derive the token from the wallet's WIF via HMAC-SHA256 truncated to 16
bytes (32-char hex). Two properties matter:

*   <strong>Deterministic.</strong> Same WIF, same token. The listener and the
    broadcast POST converge on one stream without an extra persistence layer
    (no settings table row, no env var, no boot ordering).
*   <strong>Recoverable.</strong> Lose the wallet DB but keep the WIF -- you
    can still reconnect the SSE stream by deriving the same token. The
    wallet's recoverability story is "key + chain history reconstructs
    everything" (see WBIKD derivation memory); the callback token inherits the
    same property.

The token is a **routing identifier, not a secret**. Arcade does not treat it
as authentication -- knowing a token lets you receive that subscriber's status
frames, not act on the wallet. Truncating HMAC to 16 bytes is therefore fine;
collision-resistance dominates over cryptographic strength.

## Constants
### `DOMAIN` <a id="constant-DOMAIN"></a> <a id="DOMAIN-constant"></a>
Domain-separation tag so the same WIF used to derive other HMAC-based
identifiers in the future does not collide with this one. Plain ASCII; matches
the recommended construction in #266.

## Public Class Methods
### `derive(wif_secret)` <a id="method-c-derive"></a> <a id="derive-class_method"></a>
Derive the Arcade callbackToken for a wallet identified by its WIF secret.
- **@param** `wif_secret` [String] WIF string (or any non-empty string used
as the HMAC key)
- **@raise** [ArgumentError] when +wif_secret+ is nil or empty -- this
guard catches mis-wired callers (e.g. CLI.boot before the WIF is
resolved) rather than silently producing a token from an empty
key
- **@return** [String] 32-char lowercase hex (16 raw bytes truncated from
the HMAC-SHA256 output)
