github.com/gagliardetto/solana-go@v1.11.0/programs/token/CloseAccount.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 // Close an account by transferring all its SOL to the destination account. 28 // Non-native accounts may only be closed if its token amount is zero. 29 type CloseAccount struct { 30 31 // [0] = [WRITE] account 32 // ··········· The account to close. 33 // 34 // [1] = [WRITE] destination 35 // ··········· The destination account. 36 // 37 // [2] = [] owner 38 // ··········· The account's owner. 39 // 40 // [3...] = [SIGNER] signers 41 // ··········· M signer accounts. 42 Accounts ag_solanago.AccountMetaSlice `bin:"-" borsh_skip:"true"` 43 Signers ag_solanago.AccountMetaSlice `bin:"-" borsh_skip:"true"` 44 } 45 46 func (obj *CloseAccount) SetAccounts(accounts []*ag_solanago.AccountMeta) error { 47 obj.Accounts, obj.Signers = ag_solanago.AccountMetaSlice(accounts).SplitFrom(3) 48 return nil 49 } 50 51 func (slice CloseAccount) GetAccounts() (accounts []*ag_solanago.AccountMeta) { 52 accounts = append(accounts, slice.Accounts...) 53 accounts = append(accounts, slice.Signers...) 54 return 55 } 56 57 // NewCloseAccountInstructionBuilder creates a new `CloseAccount` instruction builder. 58 func NewCloseAccountInstructionBuilder() *CloseAccount { 59 nd := &CloseAccount{ 60 Accounts: make(ag_solanago.AccountMetaSlice, 3), 61 Signers: make(ag_solanago.AccountMetaSlice, 0), 62 } 63 return nd 64 } 65 66 // SetAccount sets the "account" account. 67 // The account to close. 68 func (inst *CloseAccount) SetAccount(account ag_solanago.PublicKey) *CloseAccount { 69 inst.Accounts[0] = ag_solanago.Meta(account).WRITE() 70 return inst 71 } 72 73 // GetAccount gets the "account" account. 74 // The account to close. 75 func (inst *CloseAccount) GetAccount() *ag_solanago.AccountMeta { 76 return inst.Accounts[0] 77 } 78 79 // SetDestinationAccount sets the "destination" account. 80 // The destination account. 81 func (inst *CloseAccount) SetDestinationAccount(destination ag_solanago.PublicKey) *CloseAccount { 82 inst.Accounts[1] = ag_solanago.Meta(destination).WRITE() 83 return inst 84 } 85 86 // GetDestinationAccount gets the "destination" account. 87 // The destination account. 88 func (inst *CloseAccount) GetDestinationAccount() *ag_solanago.AccountMeta { 89 return inst.Accounts[1] 90 } 91 92 // SetOwnerAccount sets the "owner" account. 93 // The account's owner. 94 func (inst *CloseAccount) SetOwnerAccount(owner ag_solanago.PublicKey, multisigSigners ...ag_solanago.PublicKey) *CloseAccount { 95 inst.Accounts[2] = ag_solanago.Meta(owner) 96 if len(multisigSigners) == 0 { 97 inst.Accounts[2].SIGNER() 98 } 99 for _, signer := range multisigSigners { 100 inst.Signers = append(inst.Signers, ag_solanago.Meta(signer).SIGNER()) 101 } 102 return inst 103 } 104 105 // GetOwnerAccount gets the "owner" account. 106 // The account's owner. 107 func (inst *CloseAccount) GetOwnerAccount() *ag_solanago.AccountMeta { 108 return inst.Accounts[2] 109 } 110 111 func (inst CloseAccount) Build() *Instruction { 112 return &Instruction{BaseVariant: ag_binary.BaseVariant{ 113 Impl: inst, 114 TypeID: ag_binary.TypeIDFromUint8(Instruction_CloseAccount), 115 }} 116 } 117 118 // ValidateAndBuild validates the instruction parameters and accounts; 119 // if there is a validation error, it returns the error. 120 // Otherwise, it builds and returns the instruction. 121 func (inst CloseAccount) ValidateAndBuild() (*Instruction, error) { 122 if err := inst.Validate(); err != nil { 123 return nil, err 124 } 125 return inst.Build(), nil 126 } 127 128 func (inst *CloseAccount) Validate() error { 129 // Check whether all (required) accounts are set: 130 { 131 if inst.Accounts[0] == nil { 132 return errors.New("accounts.Account is not set") 133 } 134 if inst.Accounts[1] == nil { 135 return errors.New("accounts.Destination is not set") 136 } 137 if inst.Accounts[2] == nil { 138 return errors.New("accounts.Owner is not set") 139 } 140 if !inst.Accounts[2].IsSigner && len(inst.Signers) == 0 { 141 return fmt.Errorf("accounts.Signers is not set") 142 } 143 if len(inst.Signers) > MAX_SIGNERS { 144 return fmt.Errorf("too many signers; got %v, but max is 11", len(inst.Signers)) 145 } 146 } 147 return nil 148 } 149 150 func (inst *CloseAccount) EncodeToTree(parent ag_treeout.Branches) { 151 parent.Child(ag_format.Program(ProgramName, ProgramID)). 152 // 153 ParentFunc(func(programBranch ag_treeout.Branches) { 154 programBranch.Child(ag_format.Instruction("CloseAccount")). 155 // 156 ParentFunc(func(instructionBranch ag_treeout.Branches) { 157 158 // Parameters of the instruction: 159 instructionBranch.Child("Params").ParentFunc(func(paramsBranch ag_treeout.Branches) {}) 160 161 // Accounts of the instruction: 162 instructionBranch.Child("Accounts").ParentFunc(func(accountsBranch ag_treeout.Branches) { 163 accountsBranch.Child(ag_format.Meta(" account", inst.Accounts[0])) 164 accountsBranch.Child(ag_format.Meta("destination", inst.Accounts[1])) 165 accountsBranch.Child(ag_format.Meta(" owner", inst.Accounts[2])) 166 167 signersBranch := accountsBranch.Child(fmt.Sprintf("signers[len=%v]", len(inst.Signers))) 168 for i, v := range inst.Signers { 169 if len(inst.Signers) > 9 && i < 10 { 170 signersBranch.Child(ag_format.Meta(fmt.Sprintf(" [%v]", i), v)) 171 } else { 172 signersBranch.Child(ag_format.Meta(fmt.Sprintf("[%v]", i), v)) 173 } 174 } 175 }) 176 }) 177 }) 178 } 179 180 func (obj CloseAccount) MarshalWithEncoder(encoder *ag_binary.Encoder) (err error) { 181 return nil 182 } 183 func (obj *CloseAccount) UnmarshalWithDecoder(decoder *ag_binary.Decoder) (err error) { 184 return nil 185 } 186 187 // NewCloseAccountInstruction declares a new CloseAccount instruction with the provided parameters and accounts. 188 func NewCloseAccountInstruction( 189 // Accounts: 190 account ag_solanago.PublicKey, 191 destination ag_solanago.PublicKey, 192 owner ag_solanago.PublicKey, 193 multisigSigners []ag_solanago.PublicKey, 194 ) *CloseAccount { 195 return NewCloseAccountInstructionBuilder(). 196 SetAccount(account). 197 SetDestinationAccount(destination). 198 SetOwnerAccount(owner, multisigSigners...) 199 }