github.com/gagliardetto/solana-go@v1.11.0/rpc/simulateTransaction.go (about)

     1  // Copyright 2021 github.com/gagliardetto
     2  // This file has been modified by github.com/gagliardetto
     3  //
     4  // Copyright 2020 dfuse Platform Inc.
     5  //
     6  // Licensed under the Apache License, Version 2.0 (the "License");
     7  // you may not use this file except in compliance with the License.
     8  // You may obtain a copy of the License at
     9  //
    10  //	http://www.apache.org/licenses/LICENSE-2.0
    11  //
    12  // Unless required by applicable law or agreed to in writing, software
    13  // distributed under the License is distributed on an "AS IS" BASIS,
    14  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    15  // See the License for the specific language governing permissions and
    16  // limitations under the License.
    17  package rpc
    18  
    19  import (
    20  	"context"
    21  	"encoding/base64"
    22  	"fmt"
    23  
    24  	"github.com/gagliardetto/solana-go"
    25  )
    26  
    27  type SimulateTransactionResponse struct {
    28  	RPCContext
    29  	Value *SimulateTransactionResult `json:"value"`
    30  }
    31  
    32  type SimulateTransactionResult struct {
    33  	// Error if transaction failed, null if transaction succeeded.
    34  	Err interface{} `json:"err,omitempty"`
    35  
    36  	// Array of log messages the transaction instructions output during execution,
    37  	// null if simulation failed before the transaction was able to execute
    38  	// (for example due to an invalid blockhash or signature verification failure)
    39  	Logs []string `json:"logs,omitempty"`
    40  
    41  	// Array of accounts with the same length as the accounts.addresses array in the request.
    42  	Accounts []*Account `json:"accounts"`
    43  
    44  	// The number of compute budget units consumed during the processing of this transaction.
    45  	UnitsConsumed *uint64 `json:"unitsConsumed,omitempty"`
    46  }
    47  
    48  // SimulateTransaction simulates sending a transaction.
    49  func (cl *Client) SimulateTransaction(
    50  	ctx context.Context,
    51  	transaction *solana.Transaction,
    52  ) (out *SimulateTransactionResponse, err error) {
    53  	return cl.SimulateTransactionWithOpts(
    54  		ctx,
    55  		transaction,
    56  		nil,
    57  	)
    58  }
    59  
    60  type SimulateTransactionOpts struct {
    61  	// If true the transaction signatures will be verified
    62  	// (default: false, conflicts with ReplaceRecentBlockhash)
    63  	SigVerify bool
    64  
    65  	// Commitment level to simulate the transaction at.
    66  	// (default: "finalized").
    67  	Commitment CommitmentType
    68  
    69  	// If true the transaction recent blockhash will be replaced with the most recent blockhash.
    70  	// (default: false, conflicts with SigVerify)
    71  	ReplaceRecentBlockhash bool
    72  
    73  	Accounts *SimulateTransactionAccountsOpts
    74  }
    75  
    76  type SimulateTransactionAccountsOpts struct {
    77  	// (optional) Encoding for returned Account data,
    78  	// either "base64" (default), "base64+zstd" or "jsonParsed".
    79  	// - "jsonParsed" encoding attempts to use program-specific state parsers
    80  	//   to return more human-readable and explicit account state data.
    81  	//   If "jsonParsed" is requested but a parser cannot be found,
    82  	//   the field falls back to binary encoding, detectable when
    83  	//   the data field is type <string>.
    84  	Encoding solana.EncodingType
    85  
    86  	// An array of accounts to return.
    87  	Addresses []solana.PublicKey
    88  }
    89  
    90  // SimulateTransaction simulates sending a transaction.
    91  func (cl *Client) SimulateTransactionWithOpts(
    92  	ctx context.Context,
    93  	transaction *solana.Transaction,
    94  	opts *SimulateTransactionOpts,
    95  ) (out *SimulateTransactionResponse, err error) {
    96  	txData, err := transaction.MarshalBinary()
    97  	if err != nil {
    98  		return nil, fmt.Errorf("send transaction: encode transaction: %w", err)
    99  	}
   100  	return cl.SimulateRawTransactionWithOpts(ctx, txData, opts)
   101  }
   102  
   103  func (cl *Client) SimulateRawTransactionWithOpts(
   104  	ctx context.Context,
   105  	txData []byte,
   106  	opts *SimulateTransactionOpts,
   107  ) (out *SimulateTransactionResponse, err error) {
   108  	obj := M{
   109  		"encoding": "base64",
   110  	}
   111  	if opts != nil {
   112  		if opts.SigVerify {
   113  			obj["sigVerify"] = opts.SigVerify
   114  		}
   115  		if opts.Commitment != "" {
   116  			obj["commitment"] = opts.Commitment
   117  		}
   118  		if opts.ReplaceRecentBlockhash {
   119  			obj["replaceRecentBlockhash"] = opts.ReplaceRecentBlockhash
   120  		}
   121  		if opts.Accounts != nil {
   122  			obj["accounts"] = M{
   123  				"encoding":  opts.Accounts.Encoding,
   124  				"addresses": opts.Accounts.Addresses,
   125  			}
   126  		}
   127  	}
   128  
   129  	b64Data := base64.StdEncoding.EncodeToString(txData)
   130  	params := []interface{}{
   131  		b64Data,
   132  		obj,
   133  	}
   134  
   135  	err = cl.rpcClient.CallForInto(ctx, &out, "simulateTransaction", params)
   136  	return
   137  }