Interacting with governance

Governance related transactions, such as submitting or voting on a proposal, can be constructed using the SDK similar to other types of transactions.

Constructing a proposal

For details on proposal structure, refer to the Governance section of these docs. The following code will prepare the proposal json; in the next step we'll construct a transaction to submit it on-chain.

This example assumes that Alice's account exists in the SDK wallet and that it contains enough funds to cover the proposal deposit.

Add the serde_json crate to your Cargo.toml.

serde_json = "1.0.128"

Next, prepare the proposal json:

use serde_json::json;
 
let source_address = alice_addr;
let start_epoch = 3 as u64;
let end_epoch = 6 as u64;
let activation_epoch = 9 as u64;
 
let proposal = json!({
  "proposal": {
    "content": {
      "title": "TheTitle",
      "authors": "[email protected]",
      "discussions-to": "forum.namada.net",
      "created": "2024-03-10T08:54:37Z",
      "license": "MIT",
      "abstract": "Ut convallis eleifend orci vel venenatis. Duis vulputate metus in lacus sollicitudin vestibulum. Suspendisse vel velit ac est consectetur feugiat nec ac urna. Ut faucibus ex nec dictum fermentum. Morbi aliquet purus at sollicitudin ultrices. Quisque viverra varius cursus. Praesent sed mauris gravida, pharetra turpis non, gravida eros. Nullam sed ex justo. Ut at placerat ipsum, sit amet rhoncus libero. Sed blandit non purus non suscipit. Phasellus sed quam nec augue bibendum bibendum ut vitae urna. Sed odio diam, ornare nec sapien eget, congue viverra enim.",
      "motivation": "Ut convallis eleifend orci vel venenatis. Duis vulputate metus in lacus sollicitudin vestibulum. Suspendisse vel velit ac est consectetur feugiat nec ac urna. Ut faucibus ex nec dictum fermentum. Morbi aliquet purus at sollicitudin ultrices.",
      "details": "Ut convallis eleifend orci vel venenatis. Duis vulputate metus in lacus sollicitudin vestibulum. Suspendisse vel velit ac est consectetur feugiat nec ac urna. Ut faucibus ex nec dictum fermentum. Morbi aliquet purus at sollicitudin ultrices. Quisque viverra varius cursus. Praesent sed mauris gravida, pharetra turpis non, gravida eros.",
      "requires": "2"
    },
    "author": source_address.to_string(),
    "voting_start_epoch": start_epoch,
    "voting_end_epoch": end_epoch,
    "activation_epoch": activation_epoch
  }
}).to_string();

Submitting the proposal

Once the json is constructed, the proposal can be submitted to the network using the following code:

use namada_sdk::signing::default_sign;
 
let proposal_data = proposal.as_bytes().to_vec();
 
let init_proposal_tx_builder = sdk
  .new_init_proposal(proposal_data)
  .signing_keys(vec![alice_acct.public_key.clone()]);
 
let (mut init_proposal_tx, signing_data) = init_proposal_tx_builder
  .build(&sdk)
  .await
  .expect("unable to build init_proposal tx");
 
sdk.sign(&mut init_proposal_tx, &init_proposal_tx_builder.tx, signing_data, default_sign, (),)
  .await
  .expect("unable to sign init_proposal tx");
 
match sdk.submit(init_proposal_tx, &init_proposal_tx_builder.tx).await {
  Ok(res) => println!("Tx result: {:?}", res),
  Err(e) => println!("Tx error: {:?}", e) 
}

Voting on a proposal

In order to vote on a proposal, we need a valid proposal id. If you know the proposal id, we can use it directly. However, we can retrieve the proposal id from the latest proposal submitted to the network using the following code:

let storage_key = namada_governance::storage::keys::get_counter_key();
// This returns the next proposal_id, so always subtract 1
let proposal_id = rpc::query_storage_value::<_, u64>(sdk.client(), &storage_key)
  .await
  .unwrap()
  - 1;

Once we have the proposal id, we can vote on the proposal using the following code:

let vote = String::from("Yay");
 
let vote_proposal_tx_builder = sdk
  .new_proposal_vote(proposal_id, vote.clone(), alice_addr.clone())
  .proposal_id(proposal_id)
  .signing_keys(vec![alice_acct.public_key.clone()]);
 
let (mut vote_proposal_tx, signing_data) = vote_proposal_tx_builder
  .build(&sdk)
  .await
  .expect("unable to build vote_proposal tx");
 
sdk.sign(&mut vote_proposal_tx, &vote_proposal_tx_builder.tx, signing_data, default_sign, ())
  .await
  .expect("unable to sign vote_proposal tx");
 
match sdk.submit(vote_proposal_tx, &vote_proposal_tx_builder.tx).await {
  Ok(res) => println!("Tx result: {:?}", res),
  Err(e) => println!("Tx error: {:?}", e) 
}