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  }