diff --git a/crates/aldabra-dao/src/config.rs b/crates/aldabra-dao/src/config.rs index 82b7a5c..cd3c078 100644 --- a/crates/aldabra-dao/src/config.rs +++ b/crates/aldabra-dao/src/config.rs @@ -107,6 +107,54 @@ pub struct DaoConfig { /// Cardano network this DAO lives on. #[serde(default)] pub network: DaoNetwork, + + // ─── Phase 4 prerequisites — populated by `dao_discover_scripts` ───────── + // + // All optional: existing configs registered before Phase 4 still load. + // The dao_discover_scripts MCP tool fills these in by inspecting on-chain + // state at the governor / stakes / treasury addresses. + + /// Proposal validator address (bech32). Where new proposal UTxOs land. + /// Different from stakes_addr / governor_addr — separate parameterized + /// validator. Discoverable from any tx that created a proposal. + #[serde(default, skip_serializing_if = "Option::is_none")] + pub proposal_addr: Option, + + /// StakeST minting policy id (56 hex chars). Mints exactly one + /// "stake state thread" token per stake; the asset_name on the token + /// equals the stake validator's script hash. + #[serde(default, skip_serializing_if = "Option::is_none")] + pub stake_st_policy: Option, + + /// ProposalST minting policy id (56 hex chars). Mints one token per + /// proposal with empty asset name. + #[serde(default, skip_serializing_if = "Option::is_none")] + pub proposal_st_policy: Option, + + /// Reference UTxOs for each Agora script (so we don't re-discover on + /// every tx). Stored as `txhash#index` strings. Optional — falls back + /// to a lookup at use time when absent. + #[serde(default)] + pub script_refs: ScriptRefs, +} + +/// Cached UTxO references for the parameterized Agora scripts. Populated by +/// [`dao_discover_scripts`], consumed by Phase 4 builders so each tx can +/// cite reference inputs without a fresh chain query. +#[derive(Debug, Clone, Default, Serialize, Deserialize)] +pub struct ScriptRefs { + #[serde(default, skip_serializing_if = "Option::is_none")] + pub governor_validator: Option, + #[serde(default, skip_serializing_if = "Option::is_none")] + pub stake_validator: Option, + #[serde(default, skip_serializing_if = "Option::is_none")] + pub proposal_validator: Option, + #[serde(default, skip_serializing_if = "Option::is_none")] + pub treasury_validator: Option, + #[serde(default, skip_serializing_if = "Option::is_none")] + pub stake_st_policy: Option, + #[serde(default, skip_serializing_if = "Option::is_none")] + pub proposal_st_policy: Option, } impl DaoConfig { @@ -315,7 +363,7 @@ mod tests { name: name.to_string(), description: Some("test".into()), governor_addr: "addr1w8v73wfrru7smn738k6c5xafqvl2tgsvct7dtztc4jwlf4c35jnmy".into(), - stakes_addr: "addr1w9gexmeunzsykesf42d4eqet5yvzeap6trjnflxqtkcf66g5740fw".into(), + stakes_addr: "addr1w8msu7psehjlcu5glzjgjtq53m4mk75c9d2p8hfjwyknmfqskkah8".into(), treasury_addr: "addr1wx2xrpft9f97ggz4u5yrkev4u340fzfsrqama95kp8l2v6qll696y".into(), gov_token_policy: "9c4bd4a90cdb73d9ff681215ecf7dea9fb183d916d30487d17098e05".into(), gov_token_name_hex: "546572726170696e".into(), @@ -326,6 +374,10 @@ mod tests { treasury_ref_config: "d9a1cdac8d196ad9303e0faedba992ff31f5bc2186740c362686cfad".into(), network: DaoNetwork::Mainnet, + proposal_addr: None, + stake_st_policy: None, + proposal_st_policy: None, + script_refs: ScriptRefs::default(), } } diff --git a/crates/aldabra-mcp/src/tools.rs b/crates/aldabra-mcp/src/tools.rs index f878d82..d798824 100644 --- a/crates/aldabra-mcp/src/tools.rs +++ b/crates/aldabra-mcp/src/tools.rs @@ -30,7 +30,7 @@ use std::sync::Arc; use aldabra_chain::{ChainBackend, KoiosClient}; use aldabra_dao::agora::stake::Credential as DaoCredential; -use aldabra_dao::config::{DaoConfig, DaoNetwork, DaoStore}; +use aldabra_dao::config::{DaoConfig, DaoNetwork, DaoStore, ScriptRefs}; use aldabra_dao::reader::{DaoReader, KoiosDaoReader}; use aldabra_core::plutus_cost_models::PLUTUS_V3_COST_MODEL_PREPROD; use aldabra_core::{ @@ -1340,6 +1340,12 @@ impl WalletService { Some("preview") => DaoNetwork::Preview, _ => DaoNetwork::Mainnet, }, + // Optional discovery fields — populated by `dao_discover_scripts` + // after registration. + proposal_addr: None, + stake_st_policy: None, + proposal_st_policy: None, + script_refs: ScriptRefs::default(), }; self.inner .dao_store