github.com/gagliardetto/solana-go@v1.11.0/programs/token/ApproveChecked.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 package token 16 17 import ( 18 "errors" 19 "fmt" 20 21 ag_binary "github.com/gagliardetto/binary" 22 ag_solanago "github.com/gagliardetto/solana-go" 23 ag_format "github.com/gagliardetto/solana-go/text/format" 24 ag_treeout "github.com/gagliardetto/treeout" 25 ) 26 27 // Approves a delegate. A delegate is given the authority over tokens on 28 // behalf of the source account's owner. 29 // 30 // This instruction differs from Approve in that the token mint and 31 // decimals value is checked by the caller. This may be useful when 32 // creating transactions offline or within a hardware wallet. 33 type ApproveChecked struct { 34 // The amount of tokens the delegate is approved for. 35 Amount *uint64 36 37 // Expected number of base 10 digits to the right of the decimal place. 38 Decimals *uint8 39 40 // [0] = [WRITE] source 41 // ··········· The source account. 42 // 43 // [1] = [] mint 44 // ··········· The token mint. 45 // 46 // [2] = [] delegate 47 // ··········· The delegate. 48 // 49 // [3] = [] owner 50 // ··········· The source account owner. 51 // 52 // [4...] = [SIGNER] signers 53 // ··········· M signer accounts. 54 Accounts ag_solanago.AccountMetaSlice `bin:"-" borsh_skip:"true"` 55 Signers ag_solanago.AccountMetaSlice `bin:"-" borsh_skip:"true"` 56 } 57 58 func (obj *ApproveChecked) SetAccounts(accounts []*ag_solanago.AccountMeta) error { 59 obj.Accounts, obj.Signers = ag_solanago.AccountMetaSlice(accounts).SplitFrom(4) 60 return nil 61 } 62 63 func (slice ApproveChecked) GetAccounts() (accounts []*ag_solanago.AccountMeta) { 64 accounts = append(accounts, slice.Accounts...) 65 accounts = append(accounts, slice.Signers...) 66 return 67 } 68 69 // NewApproveCheckedInstructionBuilder creates a new `ApproveChecked` instruction builder. 70 func NewApproveCheckedInstructionBuilder() *ApproveChecked { 71 nd := &ApproveChecked{ 72 Accounts: make(ag_solanago.AccountMetaSlice, 4), 73 Signers: make(ag_solanago.AccountMetaSlice, 0), 74 } 75 return nd 76 } 77 78 // SetAmount sets the "amount" parameter. 79 // The amount of tokens the delegate is approved for. 80 func (inst *ApproveChecked) SetAmount(amount uint64) *ApproveChecked { 81 inst.Amount = &amount 82 return inst 83 } 84 85 // SetDecimals sets the "decimals" parameter. 86 // Expected number of base 10 digits to the right of the decimal place. 87 func (inst *ApproveChecked) SetDecimals(decimals uint8) *ApproveChecked { 88 inst.Decimals = &decimals 89 return inst 90 } 91 92 // SetSourceAccount sets the "source" account. 93 // The source account. 94 func (inst *ApproveChecked) SetSourceAccount(source ag_solanago.PublicKey) *ApproveChecked { 95 inst.Accounts[0] = ag_solanago.Meta(source).WRITE() 96 return inst 97 } 98 99 // GetSourceAccount gets the "source" account. 100 // The source account. 101 func (inst *ApproveChecked) GetSourceAccount() *ag_solanago.AccountMeta { 102 return inst.Accounts[0] 103 } 104 105 // SetMintAccount sets the "mint" account. 106 // The token mint. 107 func (inst *ApproveChecked) SetMintAccount(mint ag_solanago.PublicKey) *ApproveChecked { 108 inst.Accounts[1] = ag_solanago.Meta(mint) 109 return inst 110 } 111 112 // GetMintAccount gets the "mint" account. 113 // The token mint. 114 func (inst *ApproveChecked) GetMintAccount() *ag_solanago.AccountMeta { 115 return inst.Accounts[1] 116 } 117 118 // SetDelegateAccount sets the "delegate" account. 119 // The delegate. 120 func (inst *ApproveChecked) SetDelegateAccount(delegate ag_solanago.PublicKey) *ApproveChecked { 121 inst.Accounts[2] = ag_solanago.Meta(delegate) 122 return inst 123 } 124 125 // GetDelegateAccount gets the "delegate" account. 126 // The delegate. 127 func (inst *ApproveChecked) GetDelegateAccount() *ag_solanago.AccountMeta { 128 return inst.Accounts[2] 129 } 130 131 // SetOwnerAccount sets the "owner" account. 132 // The source account owner. 133 func (inst *ApproveChecked) SetOwnerAccount(owner ag_solanago.PublicKey, multisigSigners ...ag_solanago.PublicKey) *ApproveChecked { 134 inst.Accounts[3] = ag_solanago.Meta(owner) 135 if len(multisigSigners) == 0 { 136 inst.Accounts[3].SIGNER() 137 } 138 for _, signer := range multisigSigners { 139 inst.Signers = append(inst.Signers, ag_solanago.Meta(signer).SIGNER()) 140 } 141 return inst 142 } 143 144 // GetOwnerAccount gets the "owner" account. 145 // The source account owner. 146 func (inst *ApproveChecked) GetOwnerAccount() *ag_solanago.AccountMeta { 147 return inst.Accounts[3] 148 } 149 150 func (inst ApproveChecked) Build() *Instruction { 151 return &Instruction{BaseVariant: ag_binary.BaseVariant{ 152 Impl: inst, 153 TypeID: ag_binary.TypeIDFromUint8(Instruction_ApproveChecked), 154 }} 155 } 156 157 // ValidateAndBuild validates the instruction parameters and accounts; 158 // if there is a validation error, it returns the error. 159 // Otherwise, it builds and returns the instruction. 160 func (inst ApproveChecked) ValidateAndBuild() (*Instruction, error) { 161 if err := inst.Validate(); err != nil { 162 return nil, err 163 } 164 return inst.Build(), nil 165 } 166 167 func (inst *ApproveChecked) Validate() error { 168 // Check whether all (required) parameters are set: 169 { 170 if inst.Amount == nil { 171 return errors.New("Amount parameter is not set") 172 } 173 if inst.Decimals == nil { 174 return errors.New("Decimals parameter is not set") 175 } 176 } 177 178 // Check whether all (required) accounts are set: 179 { 180 if inst.Accounts[0] == nil { 181 return errors.New("accounts.Source is not set") 182 } 183 if inst.Accounts[1] == nil { 184 return errors.New("accounts.Mint is not set") 185 } 186 if inst.Accounts[2] == nil { 187 return errors.New("accounts.Delegate is not set") 188 } 189 if inst.Accounts[3] == nil { 190 return errors.New("accounts.Owner is not set") 191 } 192 if !inst.Accounts[3].IsSigner && len(inst.Signers) == 0 { 193 return fmt.Errorf("accounts.Signers is not set") 194 } 195 if len(inst.Signers) > MAX_SIGNERS { 196 return fmt.Errorf("too many signers; got %v, but max is 11", len(inst.Signers)) 197 } 198 } 199 return nil 200 } 201 202 func (inst *ApproveChecked) EncodeToTree(parent ag_treeout.Branches) { 203 parent.Child(ag_format.Program(ProgramName, ProgramID)). 204 // 205 ParentFunc(func(programBranch ag_treeout.Branches) { 206 programBranch.Child(ag_format.Instruction("ApproveChecked")). 207 // 208 ParentFunc(func(instructionBranch ag_treeout.Branches) { 209 210 // Parameters of the instruction: 211 instructionBranch.Child("Params").ParentFunc(func(paramsBranch ag_treeout.Branches) { 212 paramsBranch.Child(ag_format.Param(" Amount", *inst.Amount)) 213 paramsBranch.Child(ag_format.Param("Decimals", *inst.Decimals)) 214 }) 215 216 // Accounts of the instruction: 217 instructionBranch.Child("Accounts").ParentFunc(func(accountsBranch ag_treeout.Branches) { 218 accountsBranch.Child(ag_format.Meta(" source", inst.Accounts[0])) 219 accountsBranch.Child(ag_format.Meta(" mint", inst.Accounts[1])) 220 accountsBranch.Child(ag_format.Meta("delegate", inst.Accounts[2])) 221 accountsBranch.Child(ag_format.Meta(" owner", inst.Accounts[3])) 222 223 signersBranch := accountsBranch.Child(fmt.Sprintf("signers[len=%v]", len(inst.Signers))) 224 for i, v := range inst.Signers { 225 if len(inst.Signers) > 9 && i < 10 { 226 signersBranch.Child(ag_format.Meta(fmt.Sprintf(" [%v]", i), v)) 227 } else { 228 signersBranch.Child(ag_format.Meta(fmt.Sprintf("[%v]", i), v)) 229 } 230 } 231 }) 232 }) 233 }) 234 } 235 236 func (obj ApproveChecked) MarshalWithEncoder(encoder *ag_binary.Encoder) (err error) { 237 // Serialize `Amount` param: 238 err = encoder.Encode(obj.Amount) 239 if err != nil { 240 return err 241 } 242 // Serialize `Decimals` param: 243 err = encoder.Encode(obj.Decimals) 244 if err != nil { 245 return err 246 } 247 return nil 248 } 249 func (obj *ApproveChecked) UnmarshalWithDecoder(decoder *ag_binary.Decoder) (err error) { 250 // Deserialize `Amount`: 251 err = decoder.Decode(&obj.Amount) 252 if err != nil { 253 return err 254 } 255 // Deserialize `Decimals`: 256 err = decoder.Decode(&obj.Decimals) 257 if err != nil { 258 return err 259 } 260 return nil 261 } 262 263 // NewApproveCheckedInstruction declares a new ApproveChecked instruction with the provided parameters and accounts. 264 func NewApproveCheckedInstruction( 265 // Parameters: 266 amount uint64, 267 decimals uint8, 268 // Accounts: 269 source ag_solanago.PublicKey, 270 mint ag_solanago.PublicKey, 271 delegate ag_solanago.PublicKey, 272 owner ag_solanago.PublicKey, 273 multisigSigners []ag_solanago.PublicKey, 274 ) *ApproveChecked { 275 return NewApproveCheckedInstructionBuilder(). 276 SetAmount(amount). 277 SetDecimals(decimals). 278 SetSourceAccount(source). 279 SetMintAccount(mint). 280 SetDelegateAccount(delegate). 281 SetOwnerAccount(owner, multisigSigners...) 282 }