github.com/gagliardetto/solana-go@v1.11.0/programs/system/instructions.go (about) 1 // Copyright 2021 github.com/gagliardetto 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 // Create new accounts, allocate account data, assign accounts to owning programs, 16 // transfer lamports from System Program owned accounts and pay transacation fees. 17 18 package system 19 20 import ( 21 "bytes" 22 "encoding/binary" 23 "fmt" 24 25 ag_spew "github.com/davecgh/go-spew/spew" 26 ag_binary "github.com/gagliardetto/binary" 27 ag_solanago "github.com/gagliardetto/solana-go" 28 ag_text "github.com/gagliardetto/solana-go/text" 29 ag_treeout "github.com/gagliardetto/treeout" 30 ) 31 32 var ProgramID ag_solanago.PublicKey = ag_solanago.SystemProgramID 33 34 func SetProgramID(pubkey ag_solanago.PublicKey) { 35 ProgramID = pubkey 36 ag_solanago.RegisterInstructionDecoder(ProgramID, registryDecodeInstruction) 37 } 38 39 const ProgramName = "System" 40 41 func init() { 42 ag_solanago.RegisterInstructionDecoder(ProgramID, registryDecodeInstruction) 43 } 44 45 const ( 46 // Create a new account 47 Instruction_CreateAccount uint32 = iota 48 49 // Assign account to a program 50 Instruction_Assign 51 52 // Transfer lamports 53 Instruction_Transfer 54 55 // Create a new account at an address derived from a base pubkey and a seed 56 Instruction_CreateAccountWithSeed 57 58 // Consumes a stored nonce, replacing it with a successor 59 Instruction_AdvanceNonceAccount 60 61 // Withdraw funds from a nonce account 62 Instruction_WithdrawNonceAccount 63 64 // Drive state of Uninitalized nonce account to Initialized, setting the nonce value 65 Instruction_InitializeNonceAccount 66 67 // Change the entity authorized to execute nonce instructions on the account 68 Instruction_AuthorizeNonceAccount 69 70 // Allocate space in a (possibly new) account without funding 71 Instruction_Allocate 72 73 // Allocate space for and assign an account at an address derived from a base public key and a seed 74 Instruction_AllocateWithSeed 75 76 // Assign account to a program based on a seed 77 Instruction_AssignWithSeed 78 79 // Transfer lamports from a derived address 80 Instruction_TransferWithSeed 81 ) 82 83 // InstructionIDToName returns the name of the instruction given its ID. 84 func InstructionIDToName(id uint32) string { 85 switch id { 86 case Instruction_CreateAccount: 87 return "CreateAccount" 88 case Instruction_Assign: 89 return "Assign" 90 case Instruction_Transfer: 91 return "Transfer" 92 case Instruction_CreateAccountWithSeed: 93 return "CreateAccountWithSeed" 94 case Instruction_AdvanceNonceAccount: 95 return "AdvanceNonceAccount" 96 case Instruction_WithdrawNonceAccount: 97 return "WithdrawNonceAccount" 98 case Instruction_InitializeNonceAccount: 99 return "InitializeNonceAccount" 100 case Instruction_AuthorizeNonceAccount: 101 return "AuthorizeNonceAccount" 102 case Instruction_Allocate: 103 return "Allocate" 104 case Instruction_AllocateWithSeed: 105 return "AllocateWithSeed" 106 case Instruction_AssignWithSeed: 107 return "AssignWithSeed" 108 case Instruction_TransferWithSeed: 109 return "TransferWithSeed" 110 default: 111 return "" 112 } 113 } 114 115 type Instruction struct { 116 ag_binary.BaseVariant 117 } 118 119 func (inst *Instruction) EncodeToTree(parent ag_treeout.Branches) { 120 if enToTree, ok := inst.Impl.(ag_text.EncodableToTree); ok { 121 enToTree.EncodeToTree(parent) 122 } else { 123 parent.Child(ag_spew.Sdump(inst)) 124 } 125 } 126 127 var InstructionImplDef = ag_binary.NewVariantDefinition( 128 ag_binary.Uint32TypeIDEncoding, 129 []ag_binary.VariantType{ 130 { 131 "CreateAccount", (*CreateAccount)(nil), 132 }, 133 { 134 "Assign", (*Assign)(nil), 135 }, 136 { 137 "Transfer", (*Transfer)(nil), 138 }, 139 { 140 "CreateAccountWithSeed", (*CreateAccountWithSeed)(nil), 141 }, 142 { 143 "AdvanceNonceAccount", (*AdvanceNonceAccount)(nil), 144 }, 145 { 146 "WithdrawNonceAccount", (*WithdrawNonceAccount)(nil), 147 }, 148 { 149 "InitializeNonceAccount", (*InitializeNonceAccount)(nil), 150 }, 151 { 152 "AuthorizeNonceAccount", (*AuthorizeNonceAccount)(nil), 153 }, 154 { 155 "Allocate", (*Allocate)(nil), 156 }, 157 { 158 "AllocateWithSeed", (*AllocateWithSeed)(nil), 159 }, 160 { 161 "AssignWithSeed", (*AssignWithSeed)(nil), 162 }, 163 { 164 "TransferWithSeed", (*TransferWithSeed)(nil), 165 }, 166 }, 167 ) 168 169 func (inst *Instruction) ProgramID() ag_solanago.PublicKey { 170 return ProgramID 171 } 172 173 func (inst *Instruction) Accounts() (out []*ag_solanago.AccountMeta) { 174 return inst.Impl.(ag_solanago.AccountsGettable).GetAccounts() 175 } 176 177 func (inst *Instruction) Data() ([]byte, error) { 178 buf := new(bytes.Buffer) 179 if err := ag_binary.NewBinEncoder(buf).Encode(inst); err != nil { 180 return nil, fmt.Errorf("unable to encode instruction: %w", err) 181 } 182 return buf.Bytes(), nil 183 } 184 185 func (inst *Instruction) TextEncode(encoder *ag_text.Encoder, option *ag_text.Option) error { 186 return encoder.Encode(inst.Impl, option) 187 } 188 189 func (inst *Instruction) UnmarshalWithDecoder(decoder *ag_binary.Decoder) error { 190 return inst.BaseVariant.UnmarshalBinaryVariant(decoder, InstructionImplDef) 191 } 192 193 func (inst Instruction) MarshalWithEncoder(encoder *ag_binary.Encoder) error { 194 err := encoder.WriteUint32(inst.TypeID.Uint32(), binary.LittleEndian) 195 if err != nil { 196 return fmt.Errorf("unable to write variant type: %w", err) 197 } 198 return encoder.Encode(inst.Impl) 199 } 200 201 func registryDecodeInstruction(accounts []*ag_solanago.AccountMeta, data []byte) (interface{}, error) { 202 inst, err := DecodeInstruction(accounts, data) 203 if err != nil { 204 return nil, err 205 } 206 return inst, nil 207 } 208 209 func DecodeInstruction(accounts []*ag_solanago.AccountMeta, data []byte) (*Instruction, error) { 210 inst := new(Instruction) 211 if err := ag_binary.NewBinDecoder(data).Decode(inst); err != nil { 212 return nil, fmt.Errorf("unable to decode instruction: %w", err) 213 } 214 if v, ok := inst.Impl.(ag_solanago.AccountsSettable); ok { 215 err := v.SetAccounts(accounts) 216 if err != nil { 217 return nil, fmt.Errorf("unable to set accounts for instruction: %w", err) 218 } 219 } 220 return inst, nil 221 }