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
0ef4730dbb
commit
7316eed248
2 changed files with 60 additions and 2 deletions
|
|
@ -107,6 +107,54 @@ pub struct DaoConfig {
|
||||||
/// Cardano network this DAO lives on.
|
/// Cardano network this DAO lives on.
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
pub network: DaoNetwork,
|
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 {
|
impl DaoConfig {
|
||||||
|
|
@ -315,7 +363,7 @@ mod tests {
|
||||||
name: name.to_string(),
|
name: name.to_string(),
|
||||||
description: Some("test".into()),
|
description: Some("test".into()),
|
||||||
governor_addr: "addr1w8v73wfrru7smn738k6c5xafqvl2tgsvct7dtztc4jwlf4c35jnmy".into(),
|
governor_addr: "addr1w8v73wfrru7smn738k6c5xafqvl2tgsvct7dtztc4jwlf4c35jnmy".into(),
|
||||||
stakes_addr: "addr1w9gexmeunzsykesf42d4eqet5yvzeap6trjnflxqtkcf66g5740fw".into(),
|
stakes_addr: "addr1w8msu7psehjlcu5glzjgjtq53m4mk75c9d2p8hfjwyknmfqskkah8".into(),
|
||||||
treasury_addr: "addr1wx2xrpft9f97ggz4u5yrkev4u340fzfsrqama95kp8l2v6qll696y".into(),
|
treasury_addr: "addr1wx2xrpft9f97ggz4u5yrkev4u340fzfsrqama95kp8l2v6qll696y".into(),
|
||||||
gov_token_policy: "9c4bd4a90cdb73d9ff681215ecf7dea9fb183d916d30487d17098e05".into(),
|
gov_token_policy: "9c4bd4a90cdb73d9ff681215ecf7dea9fb183d916d30487d17098e05".into(),
|
||||||
gov_token_name_hex: "546572726170696e".into(),
|
gov_token_name_hex: "546572726170696e".into(),
|
||||||
|
|
@ -326,6 +374,10 @@ mod tests {
|
||||||
treasury_ref_config:
|
treasury_ref_config:
|
||||||
"d9a1cdac8d196ad9303e0faedba992ff31f5bc2186740c362686cfad".into(),
|
"d9a1cdac8d196ad9303e0faedba992ff31f5bc2186740c362686cfad".into(),
|
||||||
network: DaoNetwork::Mainnet,
|
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_chain::{ChainBackend, KoiosClient};
|
||||||
use aldabra_dao::agora::stake::Credential as DaoCredential;
|
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_dao::reader::{DaoReader, KoiosDaoReader};
|
||||||
use aldabra_core::plutus_cost_models::PLUTUS_V3_COST_MODEL_PREPROD;
|
use aldabra_core::plutus_cost_models::PLUTUS_V3_COST_MODEL_PREPROD;
|
||||||
use aldabra_core::{
|
use aldabra_core::{
|
||||||
|
|
@ -1340,6 +1340,12 @@ impl WalletService {
|
||||||
Some("preview") => DaoNetwork::Preview,
|
Some("preview") => DaoNetwork::Preview,
|
||||||
_ => DaoNetwork::Mainnet,
|
_ => 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
|
self.inner
|
||||||
.dao_store
|
.dao_store
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue