github.com/gagliardetto/solana-go@v1.11.0/programs/system/instructions.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  // Create new accounts, allocate account data, assign accounts to owning programs,
    16  // transfer lamports from System Program owned accounts and pay transacation fees.
    17  
    18  package system
    19  
    20  import (
    21  	"bytes"
    22  	"encoding/binary"
    23  	"fmt"
    24  
    25  	ag_spew "github.com/davecgh/go-spew/spew"
    26  	ag_binary "github.com/gagliardetto/binary"
    27  	ag_solanago "github.com/gagliardetto/solana-go"
    28  	ag_text "github.com/gagliardetto/solana-go/text"
    29  	ag_treeout "github.com/gagliardetto/treeout"
    30  )
    31  
    32  var ProgramID ag_solanago.PublicKey = ag_solanago.SystemProgramID
    33  
    34  func SetProgramID(pubkey ag_solanago.PublicKey) {
    35  	ProgramID = pubkey
    36  	ag_solanago.RegisterInstructionDecoder(ProgramID, registryDecodeInstruction)
    37  }
    38  
    39  const ProgramName = "System"
    40  
    41  func init() {
    42  	ag_solanago.RegisterInstructionDecoder(ProgramID, registryDecodeInstruction)
    43  }
    44  
    45  const (
    46  	// Create a new account
    47  	Instruction_CreateAccount uint32 = iota
    48  
    49  	// Assign account to a program
    50  	Instruction_Assign
    51  
    52  	// Transfer lamports
    53  	Instruction_Transfer
    54  
    55  	// Create a new account at an address derived from a base pubkey and a seed
    56  	Instruction_CreateAccountWithSeed
    57  
    58  	// Consumes a stored nonce, replacing it with a successor
    59  	Instruction_AdvanceNonceAccount
    60  
    61  	// Withdraw funds from a nonce account
    62  	Instruction_WithdrawNonceAccount
    63  
    64  	// Drive state of Uninitalized nonce account to Initialized, setting the nonce value
    65  	Instruction_InitializeNonceAccount
    66  
    67  	// Change the entity authorized to execute nonce instructions on the account
    68  	Instruction_AuthorizeNonceAccount
    69  
    70  	// Allocate space in a (possibly new) account without funding
    71  	Instruction_Allocate
    72  
    73  	// Allocate space for and assign an account at an address derived from a base public key and a seed
    74  	Instruction_AllocateWithSeed
    75  
    76  	// Assign account to a program based on a seed
    77  	Instruction_AssignWithSeed
    78  
    79  	// Transfer lamports from a derived address
    80  	Instruction_TransferWithSeed
    81  )
    82  
    83  // InstructionIDToName returns the name of the instruction given its ID.
    84  func InstructionIDToName(id uint32) string {
    85  	switch id {
    86  	case Instruction_CreateAccount:
    87  		return "CreateAccount"
    88  	case Instruction_Assign:
    89  		return "Assign"
    90  	case Instruction_Transfer:
    91  		return "Transfer"
    92  	case Instruction_CreateAccountWithSeed:
    93  		return "CreateAccountWithSeed"
    94  	case Instruction_AdvanceNonceAccount:
    95  		return "AdvanceNonceAccount"
    96  	case Instruction_WithdrawNonceAccount:
    97  		return "WithdrawNonceAccount"
    98  	case Instruction_InitializeNonceAccount:
    99  		return "InitializeNonceAccount"
   100  	case Instruction_AuthorizeNonceAccount:
   101  		return "AuthorizeNonceAccount"
   102  	case Instruction_Allocate:
   103  		return "Allocate"
   104  	case Instruction_AllocateWithSeed:
   105  		return "AllocateWithSeed"
   106  	case Instruction_AssignWithSeed:
   107  		return "AssignWithSeed"
   108  	case Instruction_TransferWithSeed:
   109  		return "TransferWithSeed"
   110  	default:
   111  		return ""
   112  	}
   113  }
   114  
   115  type Instruction struct {
   116  	ag_binary.BaseVariant
   117  }
   118  
   119  func (inst *Instruction) EncodeToTree(parent ag_treeout.Branches) {
   120  	if enToTree, ok := inst.Impl.(ag_text.EncodableToTree); ok {
   121  		enToTree.EncodeToTree(parent)
   122  	} else {
   123  		parent.Child(ag_spew.Sdump(inst))
   124  	}
   125  }
   126  
   127  var InstructionImplDef = ag_binary.NewVariantDefinition(
   128  	ag_binary.Uint32TypeIDEncoding,
   129  	[]ag_binary.VariantType{
   130  		{
   131  			"CreateAccount", (*CreateAccount)(nil),
   132  		},
   133  		{
   134  			"Assign", (*Assign)(nil),
   135  		},
   136  		{
   137  			"Transfer", (*Transfer)(nil),
   138  		},
   139  		{
   140  			"CreateAccountWithSeed", (*CreateAccountWithSeed)(nil),
   141  		},
   142  		{
   143  			"AdvanceNonceAccount", (*AdvanceNonceAccount)(nil),
   144  		},
   145  		{
   146  			"WithdrawNonceAccount", (*WithdrawNonceAccount)(nil),
   147  		},
   148  		{
   149  			"InitializeNonceAccount", (*InitializeNonceAccount)(nil),
   150  		},
   151  		{
   152  			"AuthorizeNonceAccount", (*AuthorizeNonceAccount)(nil),
   153  		},
   154  		{
   155  			"Allocate", (*Allocate)(nil),
   156  		},
   157  		{
   158  			"AllocateWithSeed", (*AllocateWithSeed)(nil),
   159  		},
   160  		{
   161  			"AssignWithSeed", (*AssignWithSeed)(nil),
   162  		},
   163  		{
   164  			"TransferWithSeed", (*TransferWithSeed)(nil),
   165  		},
   166  	},
   167  )
   168  
   169  func (inst *Instruction) ProgramID() ag_solanago.PublicKey {
   170  	return ProgramID
   171  }
   172  
   173  func (inst *Instruction) Accounts() (out []*ag_solanago.AccountMeta) {
   174  	return inst.Impl.(ag_solanago.AccountsGettable).GetAccounts()
   175  }
   176  
   177  func (inst *Instruction) Data() ([]byte, error) {
   178  	buf := new(bytes.Buffer)
   179  	if err := ag_binary.NewBinEncoder(buf).Encode(inst); err != nil {
   180  		return nil, fmt.Errorf("unable to encode instruction: %w", err)
   181  	}
   182  	return buf.Bytes(), nil
   183  }
   184  
   185  func (inst *Instruction) TextEncode(encoder *ag_text.Encoder, option *ag_text.Option) error {
   186  	return encoder.Encode(inst.Impl, option)
   187  }
   188  
   189  func (inst *Instruction) UnmarshalWithDecoder(decoder *ag_binary.Decoder) error {
   190  	return inst.BaseVariant.UnmarshalBinaryVariant(decoder, InstructionImplDef)
   191  }
   192  
   193  func (inst Instruction) MarshalWithEncoder(encoder *ag_binary.Encoder) error {
   194  	err := encoder.WriteUint32(inst.TypeID.Uint32(), binary.LittleEndian)
   195  	if err != nil {
   196  		return fmt.Errorf("unable to write variant type: %w", err)
   197  	}
   198  	return encoder.Encode(inst.Impl)
   199  }
   200  
   201  func registryDecodeInstruction(accounts []*ag_solanago.AccountMeta, data []byte) (interface{}, error) {
   202  	inst, err := DecodeInstruction(accounts, data)
   203  	if err != nil {
   204  		return nil, err
   205  	}
   206  	return inst, nil
   207  }
   208  
   209  func DecodeInstruction(accounts []*ag_solanago.AccountMeta, data []byte) (*Instruction, error) {
   210  	inst := new(Instruction)
   211  	if err := ag_binary.NewBinDecoder(data).Decode(inst); err != nil {
   212  		return nil, fmt.Errorf("unable to decode instruction: %w", err)
   213  	}
   214  	if v, ok := inst.Impl.(ag_solanago.AccountsSettable); ok {
   215  		err := v.SetAccounts(accounts)
   216  		if err != nil {
   217  			return nil, fmt.Errorf("unable to set accounts for instruction: %w", err)
   218  		}
   219  	}
   220  	return inst, nil
   221  }