|
15 | 15 | package vote |
16 | 16 |
|
17 | 17 | import ( |
| 18 | + "encoding/binary" |
| 19 | + "errors" |
| 20 | + "fmt" |
| 21 | + |
| 22 | + bin "github.com/gagliardetto/binary" |
18 | 23 | "github.com/gagliardetto/solana-go" |
| 24 | + "github.com/gagliardetto/solana-go/text/format" |
| 25 | + "github.com/gagliardetto/treeout" |
19 | 26 | ) |
20 | 27 |
|
| 28 | +// Authorize is the Authorize instruction. |
| 29 | +// Data: (Pubkey, VoteAuthorize) |
21 | 30 | type Authorize struct { |
22 | | - // TODO |
| 31 | + NewAuthority *solana.PublicKey |
| 32 | + VoteAuthorize *VoteAuthorizeKind |
23 | 33 |
|
24 | 34 | // [0] = [WRITE] VoteAccount |
25 | | - // ··········· Unitialized vote account |
26 | 35 | // |
27 | 36 | // [1] = [] SysVarClock |
28 | | - // ··········· Clock sysvar |
29 | 37 | // |
30 | 38 | // [2] = [SIGNER] Authority |
31 | | - // ··········· Vote or withdraw authority |
| 39 | + // ··········· Current vote or withdraw authority. |
32 | 40 | solana.AccountMetaSlice `bin:"-" borsh_skip:"true"` |
33 | 41 | } |
| 42 | + |
| 43 | +func NewAuthorizeInstructionBuilder() *Authorize { |
| 44 | + return &Authorize{ |
| 45 | + AccountMetaSlice: make(solana.AccountMetaSlice, 3), |
| 46 | + } |
| 47 | +} |
| 48 | + |
| 49 | +func NewAuthorizeInstruction( |
| 50 | + newAuthority solana.PublicKey, |
| 51 | + kind VoteAuthorizeKind, |
| 52 | + voteAccount solana.PublicKey, |
| 53 | + currentAuthority solana.PublicKey, |
| 54 | +) *Authorize { |
| 55 | + return NewAuthorizeInstructionBuilder(). |
| 56 | + SetNewAuthority(newAuthority). |
| 57 | + SetVoteAuthorize(kind). |
| 58 | + SetVoteAccount(voteAccount). |
| 59 | + SetClockSysvar(solana.SysVarClockPubkey). |
| 60 | + SetAuthority(currentAuthority) |
| 61 | +} |
| 62 | + |
| 63 | +func (inst *Authorize) SetNewAuthority(pk solana.PublicKey) *Authorize { |
| 64 | + inst.NewAuthority = &pk |
| 65 | + return inst |
| 66 | +} |
| 67 | + |
| 68 | +func (inst *Authorize) SetVoteAuthorize(kind VoteAuthorizeKind) *Authorize { |
| 69 | + inst.VoteAuthorize = &kind |
| 70 | + return inst |
| 71 | +} |
| 72 | + |
| 73 | +func (inst *Authorize) SetVoteAccount(pk solana.PublicKey) *Authorize { |
| 74 | + inst.AccountMetaSlice[0] = solana.Meta(pk).WRITE() |
| 75 | + return inst |
| 76 | +} |
| 77 | + |
| 78 | +func (inst *Authorize) SetClockSysvar(pk solana.PublicKey) *Authorize { |
| 79 | + inst.AccountMetaSlice[1] = solana.Meta(pk) |
| 80 | + return inst |
| 81 | +} |
| 82 | + |
| 83 | +func (inst *Authorize) SetAuthority(pk solana.PublicKey) *Authorize { |
| 84 | + inst.AccountMetaSlice[2] = solana.Meta(pk).SIGNER() |
| 85 | + return inst |
| 86 | +} |
| 87 | + |
| 88 | +func (inst *Authorize) GetVoteAccount() *solana.AccountMeta { return inst.AccountMetaSlice[0] } |
| 89 | +func (inst *Authorize) GetClockSysvar() *solana.AccountMeta { return inst.AccountMetaSlice[1] } |
| 90 | +func (inst *Authorize) GetAuthority() *solana.AccountMeta { return inst.AccountMetaSlice[2] } |
| 91 | + |
| 92 | +func (inst Authorize) Build() *Instruction { |
| 93 | + return &Instruction{BaseVariant: bin.BaseVariant{ |
| 94 | + Impl: inst, |
| 95 | + TypeID: bin.TypeIDFromUint32(Instruction_Authorize, bin.LE), |
| 96 | + }} |
| 97 | +} |
| 98 | + |
| 99 | +func (inst Authorize) ValidateAndBuild() (*Instruction, error) { |
| 100 | + if err := inst.Validate(); err != nil { |
| 101 | + return nil, err |
| 102 | + } |
| 103 | + return inst.Build(), nil |
| 104 | +} |
| 105 | + |
| 106 | +func (inst *Authorize) Validate() error { |
| 107 | + if inst.NewAuthority == nil { |
| 108 | + return errors.New("NewAuthority parameter is not set") |
| 109 | + } |
| 110 | + if inst.VoteAuthorize == nil { |
| 111 | + return errors.New("VoteAuthorize parameter is not set") |
| 112 | + } |
| 113 | + for i, acc := range inst.AccountMetaSlice { |
| 114 | + if acc == nil { |
| 115 | + return fmt.Errorf("accounts[%d] is not set", i) |
| 116 | + } |
| 117 | + } |
| 118 | + return nil |
| 119 | +} |
| 120 | + |
| 121 | +func (inst *Authorize) UnmarshalWithDecoder(dec *bin.Decoder) error { |
| 122 | + b, err := dec.ReadNBytes(32) |
| 123 | + if err != nil { |
| 124 | + return err |
| 125 | + } |
| 126 | + pk := solana.PublicKeyFromBytes(b) |
| 127 | + inst.NewAuthority = &pk |
| 128 | + raw, err := dec.ReadUint32(binary.LittleEndian) |
| 129 | + if err != nil { |
| 130 | + return err |
| 131 | + } |
| 132 | + kind := VoteAuthorizeKind(raw) |
| 133 | + inst.VoteAuthorize = &kind |
| 134 | + return nil |
| 135 | +} |
| 136 | + |
| 137 | +func (inst Authorize) MarshalWithEncoder(enc *bin.Encoder) error { |
| 138 | + if inst.NewAuthority == nil { |
| 139 | + return errors.New("Authorize.NewAuthority is nil") |
| 140 | + } |
| 141 | + if inst.VoteAuthorize == nil { |
| 142 | + return errors.New("Authorize.VoteAuthorize is nil") |
| 143 | + } |
| 144 | + if err := enc.WriteBytes(inst.NewAuthority[:], false); err != nil { |
| 145 | + return err |
| 146 | + } |
| 147 | + return enc.WriteUint32(uint32(*inst.VoteAuthorize), binary.LittleEndian) |
| 148 | +} |
| 149 | + |
| 150 | +func (inst *Authorize) EncodeToTree(parent treeout.Branches) { |
| 151 | + parent.Child(format.Program(ProgramName, ProgramID)). |
| 152 | + ParentFunc(func(programBranch treeout.Branches) { |
| 153 | + programBranch.Child(format.Instruction("Authorize")). |
| 154 | + ParentFunc(func(instructionBranch treeout.Branches) { |
| 155 | + instructionBranch.Child("Params").ParentFunc(func(paramsBranch treeout.Branches) { |
| 156 | + paramsBranch.Child(format.Param(" NewAuthority", inst.NewAuthority)) |
| 157 | + paramsBranch.Child(format.Param("VoteAuthorize", inst.VoteAuthorize)) |
| 158 | + }) |
| 159 | + instructionBranch.Child("Accounts").ParentFunc(func(accountsBranch treeout.Branches) { |
| 160 | + accountsBranch.Child(format.Meta("VoteAccount", inst.AccountMetaSlice[0])) |
| 161 | + accountsBranch.Child(format.Meta("ClockSysvar", inst.AccountMetaSlice[1])) |
| 162 | + accountsBranch.Child(format.Meta(" Authority", inst.AccountMetaSlice[2])) |
| 163 | + }) |
| 164 | + }) |
| 165 | + }) |
| 166 | +} |
0 commit comments