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  }