Skip to content

Commit 3c3d7f5

Browse files
authored
Merge pull request #274 from hoakbuilds/265-governance-program
Implements governance program
2 parents 4c29360 + 60c6f94 commit 3c3d7f5

28 files changed

+2945
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
using Solnet.Programs.Governance;
2+
using Solnet.Rpc;
3+
using System;
4+
using System.Collections.Generic;
5+
using System.Linq;
6+
using System.Text;
7+
using System.Threading.Tasks;
8+
9+
namespace Solnet.Examples
10+
{
11+
public class GovernanceProgramExamples : IExample
12+
{
13+
14+
private static readonly IRpcClient mRpcClient = ClientFactory.GetClient(Cluster.MainNet);
15+
private GovernanceClient governanceClient;
16+
17+
public GovernanceProgramExamples()
18+
{
19+
governanceClient = new GovernanceClient(mRpcClient, GovernanceProgram.MainNetProgramIdKey);
20+
}
21+
22+
public void Run()
23+
{
24+
var realms = governanceClient.GetRealms();
25+
26+
for(int i = 0; i < realms.ParsedResult.Count; i++)
27+
{
28+
Console.WriteLine($"--------------------------------------\n" +
29+
$"Realm: {realms.ParsedResult[i].Name}\n" +
30+
$"Community Mint: {realms.ParsedResult[i].CommunityMint}\n" +
31+
$"Authority: {realms.ParsedResult[i]?.Authority}\n" +
32+
$"Council Mint: {realms.ParsedResult[i].Config?.CouncilMint}\n" +
33+
$"Vote Weight Source: {realms.ParsedResult[i].Config.CommunityMintMaxVoteWeightSource}\n");
34+
35+
var progGovernances = governanceClient.GetProgramGovernanceAccounts(realms.OriginalRequest.Result[i].PublicKey);
36+
var mintGovernances = governanceClient.GetMintGovernanceAccounts(realms.OriginalRequest.Result[i].PublicKey);
37+
var tokenGovernances = governanceClient.GetTokenGovernanceAccounts(realms.OriginalRequest.Result[i].PublicKey);
38+
var genericGovernances = governanceClient.GetGenericGovernanceAccounts(realms.OriginalRequest.Result[i].PublicKey);
39+
Console.WriteLine($"Program Governance Accounts: {progGovernances.ParsedResult?.Count}\n" +
40+
$"Mint Governance Accounts: {mintGovernances.ParsedResult?.Count}\n" +
41+
$"Token Governance Accounts: {tokenGovernances.ParsedResult?.Count}\n" +
42+
$"Generic Governance Accounts: {genericGovernances.ParsedResult?.Count}\n");
43+
44+
for(int j = 0; j < progGovernances.ParsedResult?.Count; j++)
45+
{
46+
var proposals = governanceClient.GetProposalsV1(progGovernances.OriginalRequest.Result[j].PublicKey);
47+
Console.WriteLine($"Program Governance: {progGovernances.OriginalRequest.Result[j].PublicKey}\n" +
48+
$"Proposals: {proposals.OriginalRequest.Result.Count}");
49+
for(int k = 0; k < proposals.ParsedResult?.Count; k++)
50+
{
51+
Console.WriteLine($"Proposal: {proposals.ParsedResult[k].Name}\n" +
52+
$"Link: {proposals.ParsedResult[k].DescriptionLink}");
53+
}
54+
}
55+
}
56+
57+
}
58+
}
59+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Linq;
4+
using System.Text;
5+
using System.Threading.Tasks;
6+
7+
namespace Solnet.Programs.Governance.Enums
8+
{
9+
/// <summary>
10+
/// Defines all Governance accounts types
11+
/// </summary>
12+
public enum GovernanceAccountType : byte
13+
{
14+
/// <summary>
15+
/// Default uninitialized account state
16+
/// </summary>
17+
Uninitialized = 0,
18+
19+
/// <summary>
20+
/// Top level aggregation for governances with Community Token (and optional Council Token)
21+
/// </summary>
22+
Realm = 1,
23+
24+
/// <summary>
25+
/// Token Owner Record for given governing token owner within a Realm
26+
/// </summary>
27+
TokenOwnerRecord = 2,
28+
29+
/// <summary>
30+
/// Generic Account Governance account
31+
/// </summary>
32+
AccountGovernance = 3,
33+
34+
/// <summary>
35+
/// Program Governance account
36+
/// </summary>
37+
ProgramGovernance = 4,
38+
39+
/// <summary>
40+
/// Proposal account for Governance account. A single Governance account can have multiple Proposal accounts
41+
/// </summary>
42+
ProposalV1 = 5,
43+
44+
/// <summary>
45+
/// Proposal Signatory account
46+
/// </summary>
47+
SignatoryRecord = 6,
48+
49+
/// <summary>
50+
/// Vote record account for a given Proposal. Proposal can have 0..n voting records
51+
/// </summary>
52+
VoteRecordV1 = 7,
53+
54+
/// <summary>
55+
/// ProposalInstruction account which holds an instruction to execute for Proposal
56+
/// </summary>
57+
ProposalInstructionV1 = 8,
58+
59+
/// <summary>
60+
/// Mint Governance account
61+
/// </summary>
62+
MintGovernance = 9,
63+
64+
/// <summary>
65+
/// Token Governance account
66+
/// </summary>
67+
TokenGovernance = 10,
68+
69+
/// <summary>
70+
/// Realm config account
71+
/// </summary>
72+
RealmConfig = 11,
73+
74+
/// <summary>
75+
/// Vote record account for a given Proposal. Proposal can have 0..n voting records
76+
/// V2 adds support for multi option votes
77+
/// </summary>
78+
VoteRecordV2 = 12,
79+
80+
/// <summary>
81+
/// ProposalInstruction account which holds an instruction to execute for Proposal
82+
/// V2 adds index for proposal option
83+
/// </summary>
84+
ProposalInstructionV2 = 13,
85+
86+
/// <summary>
87+
/// Proposal account for Governance account. A single Governance account can have multiple Proposal accounts
88+
/// V2 adds support for multiple vote options
89+
/// </summary>
90+
ProposalV2 = 14,
91+
}
92+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Linq;
4+
using System.Text;
5+
using System.Threading.Tasks;
6+
7+
namespace Solnet.Programs.Governance.Enums
8+
{
9+
/// <summary>
10+
/// Instruction execution flags defining how instructions are executed for a Proposal
11+
/// </summary>
12+
public enum InstructionExecutionFlags : byte
13+
{
14+
/// <summary>
15+
/// No execution flags are specified
16+
/// Instructions can be executed individually, in any order, as soon as they hold_up time expires
17+
/// </summary>
18+
None = 0,
19+
20+
/// <summary>
21+
/// Instructions are executed in a specific order
22+
/// Note: Ordered execution is not supported in the current version
23+
/// The implementation requires another account type to track deleted instructions
24+
/// </summary>
25+
Ordered = 1,
26+
27+
/// <summary>
28+
/// Multiple instructions can be executed as a single transaction
29+
/// Note: Transactions are not supported in the current version
30+
/// The implementation requires another account type to group instructions within a transaction
31+
/// </summary>
32+
UseTransaction = 2,
33+
}
34+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Linq;
4+
using System.Text;
5+
using System.Threading.Tasks;
6+
7+
namespace Solnet.Programs.Governance.Enums
8+
{
9+
/// <summary>
10+
/// The status of instruction execution
11+
/// </summary>
12+
public enum InstructionExecutionStatus : byte
13+
{
14+
/// <summary>
15+
/// Instruction was not executed yet
16+
/// </summary>
17+
None = 0,
18+
19+
/// <summary>
20+
/// Instruction was executed successfully
21+
/// </summary>
22+
Success = 1,
23+
24+
/// <summary>
25+
/// Instruction execution failed
26+
/// </summary>
27+
Error = 2,
28+
}
29+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Linq;
4+
using System.Text;
5+
using System.Threading.Tasks;
6+
7+
namespace Solnet.Programs.Governance.Enums
8+
{
9+
/// <summary>
10+
/// The source of max vote weight used for voting
11+
/// Values below 100% mint supply can be used when the governing token is fully minted but not distributed yet
12+
/// </summary>
13+
public enum MintMaxVoteWeightSource : byte
14+
{
15+
/// <summary>
16+
/// Fraction (10^10 precision) of the governing mint supply is used as max vote weight
17+
/// The default is 100% (10^10) to use all available mint supply for voting
18+
/// </summary>
19+
SupplyFraction = 0,
20+
21+
/// <summary>
22+
/// Absolute value, irrelevant of the actual mint supply, is used as max vote weight
23+
/// Note: this option is not implemented in the current version
24+
/// </summary>
25+
Absolute = 0,
26+
}
27+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Linq;
4+
using System.Text;
5+
using System.Threading.Tasks;
6+
7+
namespace Solnet.Programs.Governance.Enums
8+
{
9+
/// <summary>
10+
/// Proposal option vote result
11+
/// </summary>
12+
public enum OptionVoteResult : byte
13+
{
14+
/// <summary>
15+
/// Vote on the option is not resolved yet
16+
/// </summary>
17+
None = 0,
18+
19+
/// <summary>
20+
/// Vote on the option is completed and the option passed
21+
/// </summary>
22+
Succeeded = 1,
23+
24+
/// <summary>
25+
/// Vote on the option is completed and the option was defeated
26+
/// </summary>
27+
Defeated = 2
28+
}
29+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Linq;
4+
using System.Text;
5+
using System.Threading.Tasks;
6+
7+
namespace Solnet.Programs.Governance.Enums
8+
{
9+
/// <summary>
10+
/// What state a Proposal is in
11+
/// </summary>
12+
public enum ProposalState : byte
13+
{
14+
/// <summary>
15+
/// Draft - Proposal enters Draft state when it's created
16+
/// </summary>
17+
Draft = 0,
18+
19+
/// <summary>
20+
/// SigningOff - The Proposal is being signed off by Signatories
21+
/// Proposal enters the state when first Signatory Sings and leaves it when last Signatory signs
22+
/// </summary>
23+
SigningOff = 1,
24+
25+
/// <summary>
26+
/// Taking votes
27+
/// </summary>
28+
Voting = 2,
29+
30+
/// <summary>
31+
/// Voting ended with success
32+
/// </summary>
33+
Succeeded = 3,
34+
35+
/// <summary>
36+
/// Voting on Proposal succeeded and now instructions are being executed
37+
/// Proposal enter this state when first instruction is executed and leaves when the last instruction is executed
38+
/// </summary>
39+
Executing = 4,
40+
41+
/// <summary>
42+
/// Completed
43+
/// </summary>
44+
Completed = 5,
45+
46+
/// <summary>
47+
/// Cancelled
48+
/// </summary>
49+
Cancelled = 6,
50+
51+
/// <summary>
52+
/// Defeated
53+
/// </summary>
54+
Defeated = 7,
55+
56+
/// <summary>
57+
/// Same as Executing but indicates some instructions failed to execute
58+
/// Proposal can't be transitioned from ExecutingWithErrors to Completed state
59+
/// </summary>
60+
ExecutingWithErrors = 8,
61+
}
62+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Linq;
4+
using System.Text;
5+
using System.Threading.Tasks;
6+
7+
namespace Solnet.Programs.Governance.Enums
8+
{
9+
/// <summary>
10+
/// User's vote
11+
/// </summary>
12+
public enum Vote : byte
13+
{
14+
/// <summary>
15+
/// Vote approving choices
16+
/// </summary>
17+
Approve = 0,
18+
19+
/// <summary>
20+
/// Vote rejecting proposal
21+
/// </summary>
22+
Deny = 1
23+
}
24+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Linq;
4+
using System.Text;
5+
using System.Threading.Tasks;
6+
7+
namespace Solnet.Programs.Governance.Enums
8+
{
9+
/// <summary>
10+
/// The type of the vote threshold percentage used to resolve a vote on a Proposal
11+
/// </summary>
12+
public enum VoteThresholdPercentage : byte
13+
{
14+
/// <summary>
15+
/// Voting threshold of Yes votes in % required to tip the vote
16+
/// It's the percentage of tokens out of the entire pool of governance tokens eligible to vote
17+
/// 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
18+
/// In other words a '+1 vote' tie breaker is always required to have a successful vote
19+
/// </summary>
20+
YesVote = 0,
21+
22+
/// <summary>
23+
/// The minimum number of votes in % out of the entire pool of governance tokens eligible to vote
24+
/// which must be cast for the vote to be valid
25+
/// Once the quorum is achieved a simple majority (50%+1) of Yes votes is required for the vote to succeed
26+
/// Note: Quorum is not implemented in the current version
27+
/// </summary>
28+
Quorum = 1,
29+
}
30+
}

0 commit comments

Comments
 (0)