feat(tollgate): periodically sweep TollGate's router wallet into the local wallet

tollgate-wrt keeps its own separate Cashu wallet on the router
(/etc/tollgate/wallet.db) — customer payments land there, never in
this node's own wallet. Its Lightning auto-payout is configured
independently in /etc/tollgate/identities.json, which is easy to
leave misconfigured or pointed at a placeholder address (found live:
both "owner" and "developer" identities on this deployment pointed at
the same unconfigured tollgate@minibits.cash default).

Rather than depend on getting that Lightning payout config right,
tollgate_sweep::sweep_once() periodically (every 5 min, via SSH)
checks the router's `tollgate wallet balance`, and if nonzero, runs
`tollgate wallet drain cashu` and receives the resulting token(s)
straight into the local wallet via the same path the "Receive ecash"
UI uses (wallet::ecash::receive_token) — bypassing Lightning payout
entirely. A no-op (Ok(0)) if no router is configured or it doesn't
have TollGate installed.
This commit is contained in:
2026-07-02 23:55:15 +00:00
parent 9902ffd31d
commit 8f47d6608a
3 changed files with 104 additions and 0 deletions
+22
View File
@@ -534,6 +534,28 @@ impl Server {
});
}
// Periodic TollGate ecash sweep. tollgate-wrt keeps its own separate
// Cashu wallet on the router — customer payments never land in this
// node's wallet on their own, and its Lightning auto-payout config is
// independent and easy to leave misconfigured. This drains whatever
// TollGate has collected straight into the local wallet on a timer,
// sidestepping Lightning payout configuration entirely.
{
let data_dir = config.data_dir.clone();
tokio::spawn(async move {
tokio::time::sleep(Duration::from_secs(30)).await;
let mut interval = tokio::time::interval(Duration::from_secs(300));
loop {
interval.tick().await;
match crate::tollgate_sweep::sweep_once(&data_dir).await {
Ok(0) => {}
Ok(swept) => info!(sats = swept, "tollgate wallet sweep complete"),
Err(e) => debug!(error = %e, "tollgate wallet sweep (non-fatal)"),
}
}
});
}
// Initialize container scanner — discovers installed apps from Podman/Docker
{
let scanner = create_docker_scanner(&config).await?;