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