github.com/gagliardetto/solana-go@v1.11.0/programs/token/Approve.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  type Approve struct {
    30  	// The amount of tokens the delegate is approved for.
    31  	Amount *uint64
    32  
    33  	// [0] = [WRITE] source
    34  	// ··········· The source account.
    35  	//
    36  	// [1] = [] delegate
    37  	// ··········· The delegate.
    38  	//
    39  	// [2] = [] owner
    40  	// ··········· The source account owner.
    41  	//
    42  	// [3...] = [SIGNER] signers
    43  	// ··········· M signer accounts.
    44  	Accounts ag_solanago.AccountMetaSlice `bin:"-" borsh_skip:"true"`
    45  	Signers  ag_solanago.AccountMetaSlice `bin:"-" borsh_skip:"true"`
    46  }
    47  
    48  func (obj *Approve) SetAccounts(accounts []*ag_solanago.AccountMeta) error {
    49  	obj.Accounts, obj.Signers = ag_solanago.AccountMetaSlice(accounts).SplitFrom(3)
    50  	return nil
    51  }
    52  
    53  func (slice Approve) GetAccounts() (accounts []*ag_solanago.AccountMeta) {
    54  	accounts = append(accounts, slice.Accounts...)
    55  	accounts = append(accounts, slice.Signers...)
    56  	return
    57  }
    58  
    59  // NewApproveInstructionBuilder creates a new `Approve` instruction builder.
    60  func NewApproveInstructionBuilder() *Approve {
    61  	nd := &Approve{
    62  		Accounts: make(ag_solanago.AccountMetaSlice, 3),
    63  		Signers:  make(ag_solanago.AccountMetaSlice, 0),
    64  	}
    65  	return nd
    66  }
    67  
    68  // SetAmount sets the "amount" parameter.
    69  // The amount of tokens the delegate is approved for.
    70  func (inst *Approve) SetAmount(amount uint64) *Approve {
    71  	inst.Amount = &amount
    72  	return inst
    73  }
    74  
    75  // SetSourceAccount sets the "source" account.
    76  // The source account.
    77  func (inst *Approve) SetSourceAccount(source ag_solanago.PublicKey) *Approve {
    78  	inst.Accounts[0] = ag_solanago.Meta(source).WRITE()
    79  	return inst
    80  }
    81  
    82  // GetSourceAccount gets the "source" account.
    83  // The source account.
    84  func (inst *Approve) GetSourceAccount() *ag_solanago.AccountMeta {
    85  	return inst.Accounts[0]
    86  }
    87  
    88  // SetDelegateAccount sets the "delegate" account.
    89  // The delegate.
    90  func (inst *Approve) SetDelegateAccount(delegate ag_solanago.PublicKey) *Approve {
    91  	inst.Accounts[1] = ag_solanago.Meta(delegate)
    92  	return inst
    93  }
    94  
    95  // GetDelegateAccount gets the "delegate" account.
    96  // The delegate.
    97  func (inst *Approve) GetDelegateAccount() *ag_solanago.AccountMeta {
    98  	return inst.Accounts[1]
    99  }
   100  
   101  // SetOwnerAccount sets the "owner" account.
   102  // The source account owner.
   103  func (inst *Approve) SetOwnerAccount(owner ag_solanago.PublicKey, multisigSigners ...ag_solanago.PublicKey) *Approve {
   104  	inst.Accounts[2] = ag_solanago.Meta(owner)
   105  	if len(multisigSigners) == 0 {
   106  		inst.Accounts[2].SIGNER()
   107  	}
   108  	for _, signer := range multisigSigners {
   109  		inst.Signers = append(inst.Signers, ag_solanago.Meta(signer).SIGNER())
   110  	}
   111  	return inst
   112  }
   113  
   114  // GetOwnerAccount gets the "owner" account.
   115  // The source account owner.
   116  func (inst *Approve) GetOwnerAccount() *ag_solanago.AccountMeta {
   117  	return inst.Accounts[2]
   118  }
   119  
   120  func (inst Approve) Build() *Instruction {
   121  	return &Instruction{BaseVariant: ag_binary.BaseVariant{
   122  		Impl:   inst,
   123  		TypeID: ag_binary.TypeIDFromUint8(Instruction_Approve),
   124  	}}
   125  }
   126  
   127  // ValidateAndBuild validates the instruction parameters and accounts;
   128  // if there is a validation error, it returns the error.
   129  // Otherwise, it builds and returns the instruction.
   130  func (inst Approve) ValidateAndBuild() (*Instruction, error) {
   131  	if err := inst.Validate(); err != nil {
   132  		return nil, err
   133  	}
   134  	return inst.Build(), nil
   135  }
   136  
   137  func (inst *Approve) Validate() error {
   138  	// Check whether all (required) parameters are set:
   139  	{
   140  		if inst.Amount == nil {
   141  			return errors.New("Amount parameter is not set")
   142  		}
   143  	}
   144  
   145  	// Check whether all (required) accounts are set:
   146  	{
   147  		if inst.Accounts[0] == nil {
   148  			return errors.New("accounts.Source is not set")
   149  		}
   150  		if inst.Accounts[1] == nil {
   151  			return errors.New("accounts.Delegate is not set")
   152  		}
   153  		if inst.Accounts[2] == nil {
   154  			return errors.New("accounts.Owner is not set")
   155  		}
   156  		if !inst.Accounts[2].IsSigner && len(inst.Signers) == 0 {
   157  			return fmt.Errorf("accounts.Signers is not set")
   158  		}
   159  		if len(inst.Signers) > MAX_SIGNERS {
   160  			return fmt.Errorf("too many signers; got %v, but max is 11", len(inst.Signers))
   161  		}
   162  	}
   163  	return nil
   164  }
   165  
   166  func (inst *Approve) EncodeToTree(parent ag_treeout.Branches) {
   167  	parent.Child(ag_format.Program(ProgramName, ProgramID)).
   168  		//
   169  		ParentFunc(func(programBranch ag_treeout.Branches) {
   170  			programBranch.Child(ag_format.Instruction("Approve")).
   171  				//
   172  				ParentFunc(func(instructionBranch ag_treeout.Branches) {
   173  
   174  					// Parameters of the instruction:
   175  					instructionBranch.Child("Params").ParentFunc(func(paramsBranch ag_treeout.Branches) {
   176  						paramsBranch.Child(ag_format.Param("Amount", *inst.Amount))
   177  					})
   178  
   179  					// Accounts of the instruction:
   180  					instructionBranch.Child("Accounts").ParentFunc(func(accountsBranch ag_treeout.Branches) {
   181  						accountsBranch.Child(ag_format.Meta("  source", inst.Accounts[0]))
   182  						accountsBranch.Child(ag_format.Meta("delegate", inst.Accounts[1]))
   183  						accountsBranch.Child(ag_format.Meta("   owner", inst.Accounts[2]))
   184  
   185  						signersBranch := accountsBranch.Child(fmt.Sprintf("signers[len=%v]", len(inst.Signers)))
   186  						for i, v := range inst.Signers {
   187  							if len(inst.Signers) > 9 && i < 10 {
   188  								signersBranch.Child(ag_format.Meta(fmt.Sprintf(" [%v]", i), v))
   189  							} else {
   190  								signersBranch.Child(ag_format.Meta(fmt.Sprintf("[%v]", i), v))
   191  							}
   192  						}
   193  					})
   194  				})
   195  		})
   196  }
   197  
   198  func (obj Approve) MarshalWithEncoder(encoder *ag_binary.Encoder) (err error) {
   199  	// Serialize `Amount` param:
   200  	err = encoder.Encode(obj.Amount)
   201  	if err != nil {
   202  		return err
   203  	}
   204  	return nil
   205  }
   206  func (obj *Approve) UnmarshalWithDecoder(decoder *ag_binary.Decoder) (err error) {
   207  	// Deserialize `Amount`:
   208  	err = decoder.Decode(&obj.Amount)
   209  	if err != nil {
   210  		return err
   211  	}
   212  	return nil
   213  }
   214  
   215  // NewApproveInstruction declares a new Approve instruction with the provided parameters and accounts.
   216  func NewApproveInstruction(
   217  	// Parameters:
   218  	amount uint64,
   219  	// Accounts:
   220  	source ag_solanago.PublicKey,
   221  	delegate ag_solanago.PublicKey,
   222  	owner ag_solanago.PublicKey,
   223  	multisigSigners []ag_solanago.PublicKey,
   224  ) *Approve {
   225  	return NewApproveInstructionBuilder().
   226  		SetAmount(amount).
   227  		SetSourceAccount(source).
   228  		SetDelegateAccount(delegate).
   229  		SetOwnerAccount(owner, multisigSigners...)
   230  }