Skip to content

Commit

Permalink
Looking for voter_weight_record & max_voter_weight_record according t…
Browse files Browse the repository at this point in the history
…o realm configuration #30
  • Loading branch information
Semen Medvedev committed Apr 29, 2022
1 parent c1c6f14 commit 04e6a87
Show file tree
Hide file tree
Showing 6 changed files with 242 additions and 50 deletions.
2 changes: 2 additions & 0 deletions governance-lib/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,12 @@ edition = "2021"
[dependencies]
solana-sdk = "1.9"
solana-client = "1.9"
solana-account-decoder = "1.9"
borsh = "0.9.1"
goblin = "0.4.2"
log = "0.4.11"
thiserror = "1.0"
bs58 = "0.4.0"
spl-token = { version = "3.3", path = "../solana-program-library/token/program", features = [ "no-entrypoint" ] }
spl-associated-token-account = "1"
spl-governance = { version = "2.2", path = "../solana-program-library/governance/program" }
Expand Down
4 changes: 2 additions & 2 deletions governance-lib/src/governance.rs
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ impl<'a> Governance<'a> {
&token_owner.token_owner_record_address,
&self.realm.client.payer.pubkey(),
&creator, // realm_authority OR token_owner authority
token_owner.voter_weight_record_address,
token_owner.get_voter_weight_record_address(),
gov_config,
)
}
Expand All @@ -90,7 +90,7 @@ impl<'a> Governance<'a> {
&token_owner.token_owner_record_address,
&self.realm.client.payer.pubkey(),
&create_authority.pubkey(), // realm_authority OR token_owner authority
token_owner.voter_weight_record_address,
token_owner.get_voter_weight_record_address(),
gov_config,
transfer_mint_authorities,
),
Expand Down
23 changes: 19 additions & 4 deletions governance-lib/src/proposal.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ use {
instruction::{
cast_vote,
sign_off_proposal,
finalize_vote,
insert_transaction,
remove_transaction,
execute_transaction,
Expand Down Expand Up @@ -65,7 +66,7 @@ impl<'a> Proposal<'a> {
&token_owner.token_owner_record_address,
&create_authority,
&self.governance.realm.client.payer.pubkey(),
token_owner.voter_weight_record_address,
token_owner.get_voter_weight_record_address(),

&self.governance.realm.realm_address,
proposal_name.to_string(),
Expand Down Expand Up @@ -106,8 +107,6 @@ impl<'a> Proposal<'a> {
&self.get_proposal_transaction_address(option_index, index))
}

// pub fn finalize_vote(&self, sign_authority: &Keypair, token_owner: &TokenOwner) -> ClientResult<Signature>;

pub fn insert_transaction_instruction(&self, authority: &Pubkey, token_owner: &TokenOwner, option_index: u8, index: u16, hold_up_time: u32, instructions: Vec<InstructionData>) -> Instruction {
insert_transaction(
&self.governance.realm.program_id,
Expand Down Expand Up @@ -208,6 +207,22 @@ impl<'a> Proposal<'a> {
)
}

pub fn finalize_vote(&self, sign_authority: &Keypair, token_owner: &TokenOwner) -> ClientResult<Signature> {
self.governance.realm.client.send_and_confirm_transaction_with_payer_only(
&[
finalize_vote(
&self.governance.realm.program_id,
&self.governance.realm.realm_address,
&self.governance.governance_address,
&self.proposal_address,
&token_owner.token_owner_record_address,
&self.governance.realm.community_mint,
self.governance.realm.settings().max_voter_weight_record_address,
),
],
)
}

pub fn sign_off_proposal(&self, sign_authority: &Keypair, token_owner: &TokenOwner) -> ClientResult<Signature> {
self.governance.realm.client.send_and_confirm_transaction(
&[
Expand Down Expand Up @@ -251,7 +266,7 @@ impl<'a> Proposal<'a> {
&voter_authority.pubkey(),
&self.governance.realm.community_mint,
&payer.pubkey(),
voter.voter_weight_record_address,
voter.get_voter_weight_record_address(),
self.governance.realm.settings().max_voter_weight_record_address,
vote,
),
Expand Down
72 changes: 60 additions & 12 deletions governance-lib/src/realm.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
use {
crate::{
errors::GovernanceLibError,
client::{Client, ClientResult},
token_owner::TokenOwner,
governance::Governance,
},
borsh::{BorshSchema,BorshSerialize},
solana_sdk::{
pubkey::Pubkey,
instruction::Instruction,
Expand All @@ -15,7 +17,6 @@ use {
enums::MintMaxVoteWeightSource,
realm::{RealmV2, SetRealmAuthorityAction, get_realm_address},
realm_config::{RealmConfigAccount, get_realm_config_address},
token_owner_record::get_token_owner_record_address,
governance::get_governance_address,
},
instruction::{
Expand All @@ -24,12 +25,23 @@ use {
create_realm,
},
},
spl_governance_addin_api::max_voter_weight::MaxVoterWeightRecord,
solana_client::{
client_error::ClientError,
},
std::cell::{RefCell, Ref, RefMut},
};

use solana_account_decoder::{UiDataSliceConfig, UiAccountEncoding};
use solana_client::{
rpc_client::RpcClient,
rpc_config::{RpcAccountInfoConfig, RpcProgramAccountsConfig},
rpc_filter::{MemcmpEncodedBytes, RpcFilterType, Memcmp},
};
use solana_sdk::{
commitment_config::CommitmentConfig,
};

const MIN_COMMUNITY_WEIGHT_TO_CREATE_GOVERNANCE: u64 = 1;

pub struct RealmConfig {
Expand Down Expand Up @@ -79,6 +91,52 @@ impl<'a> Realm<'a> {
pub fn settings(&self) -> Ref<RealmSettings> {self._settings.borrow()}
pub fn settings_mut(&self) -> RefMut<RealmSettings> {self._settings.borrow_mut()}

pub fn update_max_voter_weight_record_address(&self) -> Result<Option<Pubkey>,GovernanceLibError> {
#[derive(BorshSchema,BorshSerialize)]
struct MaxVoterWeightFilterData {
pub account_discriminator: [u8; 8],
pub realm: Pubkey,
pub governing_token_mint: Pubkey,
}

let max_voter_weight_record_address = match self.get_realm_config()? {
Some(RealmConfigAccount {max_community_voter_weight_addin: Some(max_voter_weight_addin),..}) => {
let filter = MaxVoterWeightFilterData {
account_discriminator: MaxVoterWeightRecord::ACCOUNT_DISCRIMINATOR,
realm: self.realm_address,
governing_token_mint: self.community_mint,
};

let config = RpcProgramAccountsConfig {
filters: Some(vec![
RpcFilterType::Memcmp(Memcmp {
offset: 0,
bytes: MemcmpEncodedBytes::Base58(bs58::encode(filter.try_to_vec()?).into_string()),
encoding: None,
}),
]),
account_config: RpcAccountInfoConfig {
encoding: Some(UiAccountEncoding::Base64),
data_slice: None,
commitment: Some(CommitmentConfig::confirmed()),
},
with_context: Some(false),
};
let accounts = self.client.solana_client.get_program_accounts_with_config(
&max_voter_weight_addin,
config,
)?;
if accounts.is_empty() {
return Err(GovernanceLibError::StateError(max_voter_weight_addin, "Missed max_voter_weight_record".to_string()));
}
Some(accounts[0].0)
},
_ => {None},
};
self.settings_mut().max_voter_weight_record_address = max_voter_weight_record_address;
return Ok(max_voter_weight_record_address)
}

pub fn get_data(&self) -> ClientResult<Option<RealmV2>> {
self.client.get_account_data_borsh::<RealmV2>(&self.program_id, &self.realm_address)
}
Expand Down Expand Up @@ -111,17 +169,7 @@ impl<'a> Realm<'a> {
}

pub fn token_owner_record<'b:'a>(&'b self, token_owner: &Pubkey) -> TokenOwner<'a> {
let token_owner_record_address: Pubkey = get_token_owner_record_address(
&self.program_id,
&self.realm_address,
&self.community_mint, token_owner
);
TokenOwner {
realm: self,
token_owner_address: *token_owner,
token_owner_record_address,
voter_weight_record_address: None,
}
TokenOwner::new(self, token_owner)
}

pub fn governance<'b:'a>(&'b self, governed_account: &Pubkey) -> Governance<'a> {
Expand Down
114 changes: 109 additions & 5 deletions governance-lib/src/token_owner.rs
Original file line number Diff line number Diff line change
@@ -1,30 +1,63 @@
use {
crate::{
errors::GovernanceLibError,
realm::Realm,
client::ClientResult,
},
borsh::{BorshSchema,BorshSerialize},
solana_sdk::{
signer::{Signer, keypair::Keypair},
pubkey::Pubkey,
instruction::Instruction,
signature::Signature,
},
spl_governance::{
state::token_owner_record::TokenOwnerRecordV2,
state::{
realm_config::RealmConfigAccount,
token_owner_record::{
TokenOwnerRecordV2,
get_token_owner_record_address,
},
},
instruction::{
create_token_owner_record,
set_governance_delegate,
},
},
spl_governance_addin_api::voter_weight::VoterWeightRecord,
std::fmt,
std::cell::{RefCell, Ref, RefMut},
};
use solana_account_decoder::{UiDataSliceConfig, UiAccountEncoding};
use solana_client::{
rpc_client::RpcClient,
rpc_config::{RpcAccountInfoConfig, RpcProgramAccountsConfig},
rpc_filter::{MemcmpEncodedBytes, RpcFilterType, Memcmp},
};
use solana_sdk::{
commitment_config::CommitmentConfig,
};

#[derive(Debug)]
pub struct TokenOwnerSettings {
pub voter_weight_record_address: Option<Pubkey>,
}

impl TokenOwnerSettings {
pub fn default() -> Self {
Self {
voter_weight_record_address: None,
}
}
}

#[derive(Debug)]
pub struct TokenOwner<'a> {
pub realm: &'a Realm<'a>,
pub token_owner_address: Pubkey,
pub token_owner_record_address: Pubkey,
pub voter_weight_record_address: Option<Pubkey>,
_settings: RefCell<TokenOwnerSettings>,
//pub voter_weight_record_address: Option<Pubkey>,
}

impl<'a> fmt::Display for TokenOwner<'a> {
Expand All @@ -34,24 +67,95 @@ impl<'a> fmt::Display for TokenOwner<'a> {
.field("realm", &self.realm.realm_address)
.field("token_owner", &self.token_owner_address)
.field("token_owner_record", &self.token_owner_record_address)
.field("voter_weight_record", &self.voter_weight_record_address)
.field("settings", &self._settings.borrow())
.finish()
}
}

impl<'a> TokenOwner<'a> {

pub fn set_voter_weight_record_address(&mut self, voter_weight_record_address: Option<Pubkey>) {
self.voter_weight_record_address = voter_weight_record_address;
pub fn new(realm: &'a Realm, token_owner: &Pubkey) -> Self {
let token_owner_record_address: Pubkey = get_token_owner_record_address(
&realm.program_id,
&realm.realm_address,
&realm.community_mint,
token_owner,
);
Self {
realm,
token_owner_address: *token_owner,
token_owner_record_address,
_settings: RefCell::new(TokenOwnerSettings::default()),
}
}

pub fn settings(&self) -> Ref<TokenOwnerSettings> {self._settings.borrow()}
pub fn settings_mut(&self) -> RefMut<TokenOwnerSettings> {self._settings.borrow_mut()}

pub fn get_data(&self) -> ClientResult<Option<TokenOwnerRecordV2>> {
self.realm.client.get_account_data_borsh::<TokenOwnerRecordV2>(
&self.realm.program_id,
&self.token_owner_record_address
)
}

pub fn set_voter_weight_record_address(&mut self, voter_weight_record_address: Option<Pubkey>) {
self.settings_mut().voter_weight_record_address = voter_weight_record_address;
}

pub fn get_voter_weight_record_address(&self) -> Option<Pubkey> {
self.settings().voter_weight_record_address
}

pub fn update_voter_weight_record_address(&self) -> Result<Option<Pubkey>,GovernanceLibError> {
#[derive(BorshSchema,BorshSerialize)]
struct VoterWeightFilterData {
pub account_discriminator: [u8; 8],
pub realm: Pubkey,
pub governing_token_mint: Pubkey,
pub governing_token_owner: Pubkey,
}

let voter_weight_record_address = match self.realm.get_realm_config()? {
Some(RealmConfigAccount {community_voter_weight_addin: Some(voter_weight_addin),..}) => {
let filter = VoterWeightFilterData {
account_discriminator: VoterWeightRecord::ACCOUNT_DISCRIMINATOR,
realm: self.realm.realm_address,
governing_token_mint: self.realm.community_mint,
governing_token_owner: self.token_owner_address,
};

let config = RpcProgramAccountsConfig {
filters: Some(vec![
RpcFilterType::Memcmp(Memcmp {
offset: 0,
bytes: MemcmpEncodedBytes::Base58(bs58::encode(filter.try_to_vec()?).into_string()),
encoding: None,
}),
]),
account_config: RpcAccountInfoConfig {
encoding: Some(UiAccountEncoding::Base64),
data_slice: None,
commitment: Some(CommitmentConfig::confirmed()),
},
with_context: Some(false),
};
let accounts = self.realm.client.solana_client.get_program_accounts_with_config(
&voter_weight_addin,
config,
)?;
if accounts.is_empty() {
return Err(GovernanceLibError::StateError(voter_weight_addin,
format!("Missed voter_weight_record for {}", self.token_owner_address)));
}
Some(accounts[0].0)
},
_ => {None},
};
self.settings_mut().voter_weight_record_address = voter_weight_record_address;
return Ok(voter_weight_record_address)
}

pub fn create_token_owner_record_instruction(&self) -> Instruction {
create_token_owner_record(
&self.realm.program_id,
Expand Down
Loading

0 comments on commit 04e6a87

Please sign in to comment.