Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implements governance program #274

Open
wants to merge 7 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
59 changes: 59 additions & 0 deletions src/Solnet.Examples/GovernanceProgramExamples.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
using Solnet.Programs.Governance;
using Solnet.Rpc;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Solnet.Examples
{
public class GovernanceProgramExamples : IExample
{

private static readonly IRpcClient mRpcClient = ClientFactory.GetClient(Cluster.MainNet);
private GovernanceClient governanceClient;

public GovernanceProgramExamples()
{
governanceClient = new GovernanceClient(mRpcClient, GovernanceProgram.MainNetProgramIdKey);
}

public void Run()
{
var realms = governanceClient.GetRealms();

for(int i = 0; i < realms.ParsedResult.Count; i++)
{
Console.WriteLine($"--------------------------------------\n" +
$"Realm: {realms.ParsedResult[i].Name}\n" +
$"Community Mint: {realms.ParsedResult[i].CommunityMint}\n" +
$"Authority: {realms.ParsedResult[i]?.Authority}\n" +
$"Council Mint: {realms.ParsedResult[i].Config?.CouncilMint}\n" +
$"Vote Weight Source: {realms.ParsedResult[i].Config.CommunityMintMaxVoteWeightSource}\n");

var progGovernances = governanceClient.GetProgramGovernanceAccounts(realms.OriginalRequest.Result[i].PublicKey);
var mintGovernances = governanceClient.GetMintGovernanceAccounts(realms.OriginalRequest.Result[i].PublicKey);
var tokenGovernances = governanceClient.GetTokenGovernanceAccounts(realms.OriginalRequest.Result[i].PublicKey);
var genericGovernances = governanceClient.GetGenericGovernanceAccounts(realms.OriginalRequest.Result[i].PublicKey);
Console.WriteLine($"Program Governance Accounts: {progGovernances.ParsedResult?.Count}\n" +
$"Mint Governance Accounts: {mintGovernances.ParsedResult?.Count}\n" +
$"Token Governance Accounts: {tokenGovernances.ParsedResult?.Count}\n" +
$"Generic Governance Accounts: {genericGovernances.ParsedResult?.Count}\n");

for(int j = 0; j < progGovernances.ParsedResult?.Count; j++)
{
var proposals = governanceClient.GetProposalsV1(progGovernances.OriginalRequest.Result[j].PublicKey);
Console.WriteLine($"Program Governance: {progGovernances.OriginalRequest.Result[j].PublicKey}\n" +
$"Proposals: {proposals.OriginalRequest.Result.Count}");
for(int k = 0; k < proposals.ParsedResult?.Count; k++)
{
Console.WriteLine($"Proposal: {proposals.ParsedResult[k].Name}\n" +
$"Link: {proposals.ParsedResult[k].DescriptionLink}");
}
}
}

}
}
}
92 changes: 92 additions & 0 deletions src/Solnet.Programs/Governance/Enums/GovernanceAccountType.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Solnet.Programs.Governance.Enums
{
/// <summary>
/// Defines all Governance accounts types
/// </summary>
public enum GovernanceAccountType : byte
{
/// <summary>
/// Default uninitialized account state
/// </summary>
Uninitialized = 0,

/// <summary>
/// Top level aggregation for governances with Community Token (and optional Council Token)
/// </summary>
Realm = 1,

/// <summary>
/// Token Owner Record for given governing token owner within a Realm
/// </summary>
TokenOwnerRecord = 2,

/// <summary>
/// Generic Account Governance account
/// </summary>
AccountGovernance = 3,

/// <summary>
/// Program Governance account
/// </summary>
ProgramGovernance = 4,

/// <summary>
/// Proposal account for Governance account. A single Governance account can have multiple Proposal accounts
/// </summary>
ProposalV1 = 5,

/// <summary>
/// Proposal Signatory account
/// </summary>
SignatoryRecord = 6,

/// <summary>
/// Vote record account for a given Proposal. Proposal can have 0..n voting records
/// </summary>
VoteRecordV1 = 7,

/// <summary>
/// ProposalInstruction account which holds an instruction to execute for Proposal
/// </summary>
ProposalInstructionV1 = 8,

/// <summary>
/// Mint Governance account
/// </summary>
MintGovernance = 9,

/// <summary>
/// Token Governance account
/// </summary>
TokenGovernance = 10,

/// <summary>
/// Realm config account
/// </summary>
RealmConfig = 11,

/// <summary>
/// Vote record account for a given Proposal. Proposal can have 0..n voting records
/// V2 adds support for multi option votes
/// </summary>
VoteRecordV2 = 12,

/// <summary>
/// ProposalInstruction account which holds an instruction to execute for Proposal
/// V2 adds index for proposal option
/// </summary>
ProposalInstructionV2 = 13,

/// <summary>
/// Proposal account for Governance account. A single Governance account can have multiple Proposal accounts
/// V2 adds support for multiple vote options
/// </summary>
ProposalV2 = 14,
}
}
34 changes: 34 additions & 0 deletions src/Solnet.Programs/Governance/Enums/InstructionExecutionFlags.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Solnet.Programs.Governance.Enums
{
/// <summary>
/// Instruction execution flags defining how instructions are executed for a Proposal
/// </summary>
public enum InstructionExecutionFlags : byte
{
/// <summary>
/// No execution flags are specified
/// Instructions can be executed individually, in any order, as soon as they hold_up time expires
/// </summary>
None = 0,

/// <summary>
/// Instructions are executed in a specific order
/// Note: Ordered execution is not supported in the current version
/// The implementation requires another account type to track deleted instructions
/// </summary>
Ordered = 1,

/// <summary>
/// Multiple instructions can be executed as a single transaction
/// Note: Transactions are not supported in the current version
/// The implementation requires another account type to group instructions within a transaction
/// </summary>
UseTransaction = 2,
}
}
29 changes: 29 additions & 0 deletions src/Solnet.Programs/Governance/Enums/InstructionExecutionStatus.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Solnet.Programs.Governance.Enums
{
/// <summary>
/// The status of instruction execution
/// </summary>
public enum InstructionExecutionStatus : byte
{
/// <summary>
/// Instruction was not executed yet
/// </summary>
None = 0,

/// <summary>
/// Instruction was executed successfully
/// </summary>
Success = 1,

/// <summary>
/// Instruction execution failed
/// </summary>
Error = 2,
}
}
27 changes: 27 additions & 0 deletions src/Solnet.Programs/Governance/Enums/MintMaxVoteWeightSource.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Solnet.Programs.Governance.Enums
{
/// <summary>
/// The source of max vote weight used for voting
/// Values below 100% mint supply can be used when the governing token is fully minted but not distributed yet
/// </summary>
public enum MintMaxVoteWeightSource : byte
{
/// <summary>
/// Fraction (10^10 precision) of the governing mint supply is used as max vote weight
/// The default is 100% (10^10) to use all available mint supply for voting
/// </summary>
SupplyFraction = 0,

/// <summary>
/// Absolute value, irrelevant of the actual mint supply, is used as max vote weight
/// Note: this option is not implemented in the current version
/// </summary>
Absolute = 0,
}
}
29 changes: 29 additions & 0 deletions src/Solnet.Programs/Governance/Enums/OptionVoteResult.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Solnet.Programs.Governance.Enums
{
/// <summary>
/// Proposal option vote result
/// </summary>
public enum OptionVoteResult : byte
{
/// <summary>
/// Vote on the option is not resolved yet
/// </summary>
None = 0,

/// <summary>
/// Vote on the option is completed and the option passed
/// </summary>
Succeeded = 1,

/// <summary>
/// Vote on the option is completed and the option was defeated
/// </summary>
Defeated = 2
}
}
62 changes: 62 additions & 0 deletions src/Solnet.Programs/Governance/Enums/ProposalState.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Solnet.Programs.Governance.Enums
{
/// <summary>
/// What state a Proposal is in
/// </summary>
public enum ProposalState : byte
{
/// <summary>
/// Draft - Proposal enters Draft state when it's created
/// </summary>
Draft = 0,

/// <summary>
/// SigningOff - The Proposal is being signed off by Signatories
/// Proposal enters the state when first Signatory Sings and leaves it when last Signatory signs
/// </summary>
SigningOff = 1,

/// <summary>
/// Taking votes
/// </summary>
Voting = 2,

/// <summary>
/// Voting ended with success
/// </summary>
Succeeded = 3,

/// <summary>
/// Voting on Proposal succeeded and now instructions are being executed
/// Proposal enter this state when first instruction is executed and leaves when the last instruction is executed
/// </summary>
Executing = 4,

/// <summary>
/// Completed
/// </summary>
Completed = 5,

/// <summary>
/// Cancelled
/// </summary>
Cancelled = 6,

/// <summary>
/// Defeated
/// </summary>
Defeated = 7,

/// <summary>
/// Same as Executing but indicates some instructions failed to execute
/// Proposal can't be transitioned from ExecutingWithErrors to Completed state
/// </summary>
ExecutingWithErrors = 8,
}
}
24 changes: 24 additions & 0 deletions src/Solnet.Programs/Governance/Enums/Vote.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Solnet.Programs.Governance.Enums
{
/// <summary>
/// User's vote
/// </summary>
public enum Vote : byte
{
/// <summary>
/// Vote approving choices
/// </summary>
Approve = 0,

/// <summary>
/// Vote rejecting proposal
/// </summary>
Deny = 1
}
}
30 changes: 30 additions & 0 deletions src/Solnet.Programs/Governance/Enums/VoteThresholdPercentage.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Solnet.Programs.Governance.Enums
{
/// <summary>
/// The type of the vote threshold percentage used to resolve a vote on a Proposal
/// </summary>
public enum VoteThresholdPercentage : byte
{
/// <summary>
/// Voting threshold of Yes votes in % required to tip the vote
/// It's the percentage of tokens out of the entire pool of governance tokens eligible to vote
/// Note: If the threshold is below or equal to 50% then an even split of votes ex: 50:50 or 40:40 is always resolved as Defeated
/// In other words a '+1 vote' tie breaker is always required to have a successful vote
/// </summary>
YesVote = 0,

/// <summary>
/// The minimum number of votes in % out of the entire pool of governance tokens eligible to vote
/// which must be cast for the vote to be valid
/// Once the quorum is achieved a simple majority (50%+1) of Yes votes is required for the vote to succeed
/// Note: Quorum is not implemented in the current version
/// </summary>
Quorum = 1,
}
}
Loading