feat(mcp,chain,dao): support Koios paid-tier bearer via ALDABRA_KOIOS_BEARER env
Adds optional Authorization: Bearer <token> on every Koios request, sourced from ALDABRA_KOIOS_BEARER env var only — never from the on-disk config.toml, never from CLI args, never hardcoded. Bearers are credentials and the on-disk config dir gets routinely backed up; keeping them env-only guarantees rotations don't leak into snapshots. Wired through three Koios clients: - aldabra-chain::KoiosClient — new with_timeout_and_bearer ctor; legacy new() / with_timeout() route through it with bearer=None. - aldabra-dao::KoiosDaoReader — new with_bearer ctor; ditto. - aldabra-dao::KoiosDiscoveryClient — new with_bearer ctor; ditto. Bearer is set as a default header on the reqwest client builder so every request inherits it without per-call boilerplate. HeaderValue::set_sensitive(true) prevents the value from showing in reqwest's debug-format output. Config wiring (aldabra-mcp::config::Config): - New koios_bearer: Option<String> field. Loaded ONLY from ALDABRA_KOIOS_BEARER env var; absent or empty-string means None. - Startup tracing logs koios_bearer_set: bool — never the value. WalletInner caches the bearer alongside the koios_base so the on-demand KoiosDiscoveryClient (constructed inside dao_discover_scripts) inherits paid-tier auth too. Motivation: 2026-05-08 preprod_test2 bringup tripped Koios free-tier daily quota (5240 req/day, 'Exceeded Tier Limit') mid-deploy. Sulkta provided a paid-tier JWT (Aldabra project, exp 2026-06-26). Wiring via env var lets the operator (systemd EnvironmentFile, docker run -e, or k8s Secret) inject it without touching code or config files.
This commit is contained in:
parent
9547bd95e4
commit
48679883ec
6 changed files with 106 additions and 17 deletions
|
|
@ -63,12 +63,27 @@ pub struct KoiosDiscoveryClient {
|
|||
|
||||
impl KoiosDiscoveryClient {
|
||||
pub fn new(base_url: impl Into<String>) -> Self {
|
||||
Self::with_bearer(base_url, None)
|
||||
}
|
||||
|
||||
/// Same as [`Self::new`] but with an optional `Authorization: Bearer
|
||||
/// <token>` default header for paid-tier Koios access. Bearer comes
|
||||
/// from `ALDABRA_KOIOS_BEARER` env var only — never from disk.
|
||||
pub fn with_bearer(base_url: impl Into<String>, bearer: Option<&str>) -> Self {
|
||||
let mut builder =
|
||||
reqwest::Client::builder().timeout(std::time::Duration::from_secs(30));
|
||||
if let Some(token) = bearer {
|
||||
let mut hdrs = reqwest::header::HeaderMap::new();
|
||||
let value = format!("Bearer {token}");
|
||||
let mut hv = reqwest::header::HeaderValue::from_str(&value)
|
||||
.expect("ALDABRA_KOIOS_BEARER contains invalid header bytes");
|
||||
hv.set_sensitive(true);
|
||||
hdrs.insert(reqwest::header::AUTHORIZATION, hv);
|
||||
builder = builder.default_headers(hdrs);
|
||||
}
|
||||
Self {
|
||||
base_url: base_url.into(),
|
||||
http: reqwest::Client::builder()
|
||||
.timeout(std::time::Duration::from_secs(30))
|
||||
.build()
|
||||
.expect("reqwest client"),
|
||||
http: builder.build().expect("reqwest client"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -93,12 +93,27 @@ impl KoiosDaoReader {
|
|||
/// Construct against a Koios base URL (e.g. `https://api.koios.rest/api/v1`
|
||||
/// or `https://preprod.koios.rest/api/v1`).
|
||||
pub fn new(base_url: impl Into<String>) -> Self {
|
||||
Self::with_bearer(base_url, None)
|
||||
}
|
||||
|
||||
/// Same as [`Self::new`] but with an optional `Authorization: Bearer
|
||||
/// <token>` default header for paid-tier Koios access. Bearer is
|
||||
/// supplied by the caller from `ALDABRA_KOIOS_BEARER` env var only.
|
||||
pub fn with_bearer(base_url: impl Into<String>, bearer: Option<&str>) -> Self {
|
||||
let mut builder =
|
||||
reqwest::Client::builder().timeout(std::time::Duration::from_secs(30));
|
||||
if let Some(token) = bearer {
|
||||
let mut hdrs = reqwest::header::HeaderMap::new();
|
||||
let value = format!("Bearer {token}");
|
||||
let mut hv = reqwest::header::HeaderValue::from_str(&value)
|
||||
.expect("ALDABRA_KOIOS_BEARER contains invalid header bytes");
|
||||
hv.set_sensitive(true);
|
||||
hdrs.insert(reqwest::header::AUTHORIZATION, hv);
|
||||
builder = builder.default_headers(hdrs);
|
||||
}
|
||||
Self {
|
||||
base_url: base_url.into(),
|
||||
http: reqwest::Client::builder()
|
||||
.timeout(std::time::Duration::from_secs(30))
|
||||
.build()
|
||||
.expect("reqwest client"),
|
||||
http: builder.build().expect("reqwest client"),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue