Skip to content

Commit

Permalink
Implemented proposal for Token Genesis Event #30
Browse files Browse the repository at this point in the history
  • Loading branch information
Semen Medvedev committed Apr 29, 2022
1 parent c0c3732 commit f823b2d
Show file tree
Hide file tree
Showing 18 changed files with 1,335 additions and 20 deletions.
1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ members = [
"addin-vesting/cli",
"governance-test-scripts",
"governance-lib",
"launch-script",
]
exclude = [
"solana-program-library",
Expand Down
2 changes: 1 addition & 1 deletion addin-vesting/program/src/instruction.rs
Original file line number Diff line number Diff line change
Expand Up @@ -176,7 +176,7 @@ pub fn deposit_with_realm(
AccountMeta::new_readonly(*source_token_owner, true),
AccountMeta::new(*source_token_account, false),
AccountMeta::new_readonly(*vesting_owner, false),
AccountMeta::new_readonly(*payer, true),
AccountMeta::new(*payer, true),

AccountMeta::new_readonly(*governance_id, false),
AccountMeta::new_readonly(*realm, false),
Expand Down
1 change: 1 addition & 0 deletions artifacts/creator.keypair
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
[167,119,139,142,62,185,218,144,63,242,132,68,181,77,117,88,16,84,69,103,210,49,114,237,151,235,178,55,159,74,223,248,70,191,83,171,68,147,169,18,114,190,120,151,80,58,132,43,50,211,123,76,233,134,230,10,26,102,162,8,173,8,2,54]
1 change: 1 addition & 0 deletions governance-lib/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -16,3 +16,4 @@ spl-governance-addin-api= { version = "0.1.1", path = "../solana-program-library
spl-governance-addin-mock = { version = "0.1", path = "../solana-program-library/governance/addin-mock/program" }

spl-governance-addin-fixed-weights = { version = "0.1", path = "../addin-fixed-weights/program" }
spl-governance-addin-vesting = { path = "../addin-vesting/program" }
155 changes: 155 additions & 0 deletions governance-lib/src/addin_vesting.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,155 @@
use {
crate::{
client::SplGovernanceInteractor,
realm::Realm,
},
solana_sdk::{
pubkey::Pubkey,
signer::{Signer, keypair::Keypair},
instruction::Instruction,
transaction::Transaction,
program_error::ProgramError,
},
spl_governance_addin_vesting::{
state::VestingSchedule,
instruction::{deposit, deposit_with_realm},
voter_weight::get_voter_weight_record_address,
},
solana_client::{
client_error::ClientError,
},
};

#[derive(Debug)]
pub struct AddinVesting<'a> {
interactor: &'a SplGovernanceInteractor<'a>,
pub program_id: Pubkey,
}


impl<'a> AddinVesting<'a> {
pub fn new(interactor: &'a SplGovernanceInteractor, program_id: Pubkey) -> Self {
AddinVesting {
interactor,
program_id,
}
}

pub fn find_vesting_account(&self, vesting_token_account: &Pubkey) -> Pubkey {
let (vesting_account,_) = Pubkey::find_program_address(
&[&vesting_token_account.as_ref()],
&self.program_id,
);
vesting_account
}

pub fn get_voter_weight_record_address(&self, owner: &Pubkey, realm: &Realm) -> Pubkey {
get_voter_weight_record_address(
&self.program_id,
&realm.address,
&realm.community_mint,
owner)
}

pub fn deposit(&self, source_token_authority: &Pubkey, source_token_account: &Pubkey,
vesting_owner: &Pubkey, vesting_token_account: &Pubkey, schedules: Vec<VestingSchedule>) -> Result<Instruction, ProgramError>
{
deposit(
&self.program_id,
&spl_token::id(),
vesting_token_account,
&source_token_authority,
source_token_account,
vesting_owner,
&self.interactor.payer.pubkey(),
schedules,
)
}

pub fn deposit_with_realm_instruction(&self, source_token_authority: &Pubkey, source_token_account: &Pubkey,
vesting_owner: &Pubkey, vesting_token_account: &Pubkey, schedules: Vec<VestingSchedule>, realm: &Realm) -> Result<Instruction, ProgramError>
{
deposit_with_realm(
&self.program_id,
&spl_token::id(),
vesting_token_account,
&source_token_authority,
source_token_account,
vesting_owner,
&self.interactor.payer.pubkey(),
schedules,
&realm.interactor.spl_governance_program_address,
&realm.address,
&realm.community_mint,
)
}

/* pub fn setup_max_voter_weight_record(&self, realm: &Realm) -> Result<Pubkey, ()> {
use spl_governance_addin_fixed_weights::instruction;
let (max_voter_weight_record_pubkey,_): (Pubkey,u8) = instruction::get_max_voter_weight_address(
&self.program_id,
&realm.address,
&realm.community_mint,
);
if !self.interactor.account_exists(&max_voter_weight_record_pubkey) {
let setup_max_voter_weight_record_instruction: Instruction =
instruction::setup_max_voter_weight_record(
&self.program_id,
&realm.address,
&realm.community_mint,
&self.interactor.payer.pubkey(),
);
let transaction: Transaction =
Transaction::new_signed_with_payer(
&[
setup_max_voter_weight_record_instruction,
],
Some(&self.interactor.payer.pubkey()),
&[
self.interactor.payer,
],
self.interactor.solana_client.get_latest_blockhash().unwrap(),
);
self.interactor.solana_client.send_and_confirm_transaction(&transaction)
.map_err(|_|())?;
}
Ok(max_voter_weight_record_pubkey)
}
pub fn setup_voter_weight_record(&self, realm: &Realm, token_owner: &Pubkey) -> Result<Pubkey,()> {
let (voter_weight_record_pubkey,_): (Pubkey,u8) = spl_governance_addin_fixed_weights::instruction::get_voter_weight_address(
&self.program_id,
&realm.address,
&realm.community_mint,
token_owner);
if !self.interactor.account_exists(&voter_weight_record_pubkey) {
let setup_voter_weight_record_instruction: Instruction =
spl_governance_addin_fixed_weights::instruction::setup_voter_weight_record(
&self.program_id,
&realm.address,
&realm.data.community_mint,
token_owner,
&self.interactor.payer.pubkey(),
);
let transaction: Transaction =
Transaction::new_signed_with_payer(
&[
setup_voter_weight_record_instruction,
],
Some(&self.interactor.payer.pubkey()),
&[
self.interactor.payer,
],
self.interactor.solana_client.get_latest_blockhash().unwrap(),
);
self.interactor.solana_client.send_and_confirm_transaction(&transaction).unwrap();
}
Ok(voter_weight_record_pubkey)
}*/
}
86 changes: 83 additions & 3 deletions governance-lib/src/client.rs
Original file line number Diff line number Diff line change
@@ -1,14 +1,18 @@
use {
crate::realm::Realm,
crate::realm::{Realm, RealmSettings},
borsh::BorshDeserialize,
solana_sdk::{
borsh::try_from_slice_unchecked,
commitment_config::CommitmentConfig,
pubkey::Pubkey,
instruction::Instruction,
transaction::Transaction,
signer::{Signer, keypair::Keypair},
signers::Signers,
signature::Signature,
program_pack::{Pack, IsInitialized},
},
std::fmt,
std::{cell::RefCell, fmt},
spl_governance::{
state::{
enums::MintMaxVoteWeightSource,
Expand Down Expand Up @@ -53,6 +57,79 @@ impl<'a> SplGovernanceInteractor<'a> {
spl_governance_voter_weight_addin_address: addin_address,
}
}

pub fn send_and_confirm_transaction<T: Signers>(
&self,
instructions: &[Instruction],
signing_keypairs: &T,
) -> Result<Signature, ClientError> {
let mut transaction: Transaction =
Transaction::new_with_payer(
instructions,
Some(&self.payer.pubkey()),
);

let blockhash = self.solana_client.get_latest_blockhash().unwrap();
transaction.partial_sign(&[self.payer], blockhash);
transaction.sign(signing_keypairs, blockhash);

self.solana_client.send_and_confirm_transaction(&transaction)
}

pub fn get_account_data_pack<T: Pack + IsInitialized>(
&self,
owner_program_id: &Pubkey,
account_key: &Pubkey,
) -> Result<Option<T>, ClientError> {
let account_info = &self.solana_client.get_account_with_commitment(
&account_key, self.solana_client.commitment())?.value;

if let Some(account_info) = account_info {
if account_info.data.is_empty() {
panic!("Account {} is empty", account_key);
}
if account_info.owner != *owner_program_id {
panic!("Invalid account owner for {}: expected {}, actual {}",
account_key, owner_program_id, account_info.owner);
}

let account: T = T::unpack(&account_info.data).unwrap(); //try_from_slice_unchecked(&account_info.data).unwrap();
if !account.is_initialized() {
panic!("Unitialized account {}", account_key);
}
Ok(Some(account))
} else {
Ok(None)
}
}

pub fn get_account_data<T: BorshDeserialize + IsInitialized>(
&self,
owner_program_id: &Pubkey,
account_key: &Pubkey,
) -> Result<Option<T>, ClientError> {
let account_info = &self.solana_client.get_account_with_commitment(
&account_key, self.solana_client.commitment())?.value;

if let Some(account_info) = account_info {
if account_info.data.is_empty() {
panic!("Account {} is empty", account_key);
}
if account_info.owner != *owner_program_id {
panic!("Invalid account owner for {}: expected {}, actual {}",
account_key, owner_program_id, account_info.owner);
}

let account: T = try_from_slice_unchecked(&account_info.data).unwrap();
if !account.is_initialized() {
panic!("Unitialized account {}", account_key);
}
Ok(Some(account))
} else {
Ok(None)
}
}

pub fn account_exists(&self, address: &Pubkey) -> bool {
self.solana_client.get_account(address).is_ok()
}
Expand Down Expand Up @@ -124,7 +201,10 @@ impl<'a> SplGovernanceInteractor<'a> {
data: self.get_realm_v2(realm_name).unwrap(),
//max_voter_weight_addin_address: addin_opt,
// voter_weight_addin_address: addin_opt,
max_voter_weight_record_address: None,
//max_voter_weight_record_address: RefCell::new(None),
_settings: RefCell::new(RealmSettings {
max_voter_weight_record_address: addin_opt,
}),
}
)
}
Expand Down
19 changes: 15 additions & 4 deletions governance-lib/src/governance.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,10 @@ use {
},
spl_governance::{
state::{
governance::GovernanceV2,
governance::{GovernanceConfig, GovernanceV2},
proposal::{VoteType, ProposalV2, get_proposal_address},
},
instruction::create_proposal,
instruction::{create_proposal, set_governance_config},
},
solana_client::{
client_error::ClientError,
Expand All @@ -34,8 +34,11 @@ pub struct Governance<'a> {
impl<'a> Governance<'a> {
pub fn get_interactor(&self) -> &SplGovernanceInteractor<'a> {self.realm.interactor}

pub fn get_proposal_count(&self) -> u32 {
self.data.proposals_count
pub fn get_proposals_count(&self) -> u32 {
let data: GovernanceV2 = self.get_interactor().get_account_data(
&self.get_interactor().spl_governance_program_address,
&self.address).unwrap().unwrap();
data.proposals_count
}

pub fn get_proposal_address(&self, proposal_index: u32) -> Pubkey {
Expand All @@ -51,6 +54,14 @@ impl<'a> Governance<'a> {
ProposalV2::deserialize(&mut dt).unwrap()
}

// Note: Only governance PDA via a proposal can authorize change to its own config
pub fn set_governance_config_instruction(&self, config: GovernanceConfig) -> Instruction {
set_governance_config(
&self.get_interactor().spl_governance_program_address,
&self.address,
config)
}

pub fn create_proposal<'b:'a>(&'b self, create_authority: &Keypair, token_owner: &TokenOwner, proposal_name: &str, proposal_description: &str, proposal_index: u32) -> Result<Proposal<'a>,ClientError> {
let proposal_address: Pubkey = self.get_proposal_address(proposal_index);
let payer = &self.get_interactor().payer;
Expand Down
1 change: 1 addition & 0 deletions governance-lib/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ pub mod proposal;
pub mod token_owner;

pub mod addin_fixed_weights;
pub mod addin_vesting;

#[cfg(test)]
mod tests {
Expand Down
Loading

0 comments on commit f823b2d

Please sign in to comment.