feat(dao-config): Phase 4 prerequisite fields + ScriptRefs
DaoConfig gains optional fields for Phase 4 (proposal_create) work:
- proposal_addr — proposal validator address (bech32)
- stake_st_policy — StakeST minting policy id (56 hex)
- proposal_st_policy — ProposalST minting policy id (56 hex)
- script_refs — cached reference UTxO refs for each Agora script
(governor / stake / proposal / treasury validators
+ stake_st / proposal_st minting policies)
All fields optional with serde defaults so existing configs keep loading.
Will be populated by upcoming `dao_discover_scripts` MCP tool that audits
on-chain state under a known governor_addr.
Test fixture also corrected: stakes_addr now uses Sulkta's real per-DAO
parameterized stake-validator address (`addr1w8msu7p...`) instead of the
shared MLabs deployer (`addr1w9gexmeunzsy...`) — matches audit findings.
aldabra-mcp dao_register tool initializes new optionals to None so
DaoConfig construction stays explicit.
This commit is contained in:
parent
4501700328
commit
3a7f536409
2 changed files with 60 additions and 2 deletions
|
|
@ -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<String>,
|
||||
|
||||
/// 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<String>,
|
||||
|
||||
/// 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<String>,
|
||||
|
||||
/// 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<String>,
|
||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||
pub stake_validator: Option<String>,
|
||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||
pub proposal_validator: Option<String>,
|
||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||
pub treasury_validator: Option<String>,
|
||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||
pub stake_st_policy: Option<String>,
|
||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||
pub proposal_st_policy: Option<String>,
|
||||
}
|
||||
|
||||
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(),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue