Treasury
Where the float actually sits, how it gets there, and when it is not worth moving. The treasury context is the difference between paying customers and paying miners.
Tiers
| Tier | What it holds | Why it exists |
|---|---|---|
| UNSWEPT | Confirmed deposits still sitting at the addresses they arrived at. | Money you have, in the most awkward possible arrangement — a thousand addresses with dust in each. |
| HOT | Consolidated, online, available for signing. | What payouts actually draw from. Kept deliberately small: it is the amount an attacker could take. |
| COLD | Offline, requires a two-actor procedure to move. | Where the rest lives. Slow on purpose. |
Reading positions
const positions = await payments.treasury.positions('BTC'); positions.totalMinor; // "9007199255240993" — a string, always positions.tiers; // [{ tier, amountMinor, updatedAt }] // Arithmetic in BigInt, never Number. const hot = positions.tiers.find(t => t.tier === 'HOT'); const canPay = BigInt(hot.amountMinor) >= BigInt(withdrawal.amountMinor);
updatedAt is worth reading, not just the amount. A position that has not moved in hours during a busy period is more interesting than the number itself.
Sweeps
A sweep consolidates unswept deposits into the hot wallet. Candidates are selected, assembled into a batch with pinned inputs, signed by custody through the same allowlisted path as any payout, and broadcast idempotently.
When a sweep is not worth doing
| Policy control | Effect |
|---|---|
| Minimum sweep amount | Dust below this is never swept alone. It waits for a batch. |
| Fee ceiling | A proportion of the swept amount. Breach it and the candidate is skipped, with a reason. |
| Low-fee window | Non-urgent sweeps are scheduled when the observed fee rate is favourable. |
| Batch size | Bounded, so one sweep cannot become a transaction too large to confirm. |
| Skip records | Every skip is a row with a reason. "Nothing happened" is never a silent state. |
Float thresholds
A threshold per asset defines the minimum hot balance. The worker checks continuously and emits treasury.hot_low when it is breached — before payouts start failing, not after.
{ "eventType": "treasury.hot_low",
"asset": "BTC",
"hotMinor": "412000",
"thresholdMinor": "500000",
"shortfallMinor": "88000" }Page on this. A hot wallet that empties during a busy Saturday turns into a queue of failed withdrawals and a support incident, and the warning arrived hours earlier.
Cold to hot
Moving from cold to hot above the configured amount requires two actors: one proposes, another approves, and both are recorded with the approval token that authorised it. Neither can complete the movement alone.