solana-go/rpc/getTransaction.go

129 lines
3.4 KiB
Go

package rpc
import (
"context"
"fmt"
bin "github.com/dfuse-io/binary"
"github.com/gagliardetto/solana-go"
)
type GetTransactionOpts struct {
Encoding solana.EncodingType `json:"encoding,omitempty"`
// Desired commitment. "processed" is not supported. If parameter not provided, the default is "finalized".
Commitment CommitmentType `json:"commitment,omitempty"`
}
// GetTransaction returns transaction details for a confirmed transaction.
//
// NEW: This method is only available in solana-core v1.7 or newer.
// Please use `getConfirmedTransaction` for solana-core v1.6
func (cl *Client) GetTransaction(
ctx context.Context,
txSig solana.Signature, // transaction signature
opts *GetTransactionOpts,
) (out *GetTransactionResult, err error) {
params := []interface{}{txSig}
if opts != nil {
obj := M{}
if opts.Encoding != "" {
if !solana.IsAnyOfEncodingType(
opts.Encoding,
// Valid encodings:
solana.EncodingJSON,
// solana.EncodingJSONParsed, // TODO
solana.EncodingBase58,
solana.EncodingBase64,
) {
return nil, fmt.Errorf("provided encoding is not supported: %s", opts.Encoding)
}
obj["encoding"] = opts.Encoding
}
if opts.Commitment != "" {
obj["commitment"] = opts.Commitment
}
if len(obj) > 0 {
params = append(params, obj)
}
}
err = cl.rpcClient.CallForInto(ctx, &out, "getTransaction", params)
if err != nil {
return nil, err
}
if out == nil {
return nil, ErrNotFound
}
return
}
type GetTransactionResult struct {
// The slot this transaction was processed in.
Slot bin.Uint64 `json:"slot"`
// Estimated production time, as Unix timestamp (seconds since the Unix epoch)
// of when the transaction was processed.
// Nil if not available.
BlockTime *UnixTimeSeconds `json:"blockTime"`
Transaction *TransactionResultEnvelope `json:"transaction"`
Meta *TransactionMeta `json:"meta,omitempty"`
}
// TransactionResultEnvelope will contain a *ParsedTransaction if the requested encoding is `solana.EncodingJSON`
// (which is also the default when the encoding is not specified),
// or a `solana.Data` in case of EncodingBase58, EncodingBase64.
type TransactionResultEnvelope struct {
asDecodedBinary solana.Data
asParsedTransaction *ParsedTransaction
}
func (wrap TransactionResultEnvelope) MarshalJSON() ([]byte, error) {
if wrap.asParsedTransaction != nil {
return json.Marshal(wrap.asParsedTransaction)
}
return json.Marshal(wrap.asDecodedBinary)
}
func (wrap *TransactionResultEnvelope) UnmarshalJSON(data []byte) error {
if len(data) == 0 || (len(data) == 4 && string(data) == "null") {
// TODO: is this an error?
return nil
}
firstChar := data[0]
switch firstChar {
// Check if first character is `[`, standing for a JSON array.
case '[':
// It's base64 (or similar)
{
err := wrap.asDecodedBinary.UnmarshalJSON(data)
if err != nil {
return err
}
}
case '{':
// It's JSON, most likely.
{
return json.Unmarshal(data, &wrap.asParsedTransaction)
}
default:
return fmt.Errorf("Unknown kind: %v", data)
}
return nil
}
// GetBinary returns the decoded bytes if the encoding is
// "base58", "base64".
func (dt *TransactionResultEnvelope) GetBinary() []byte {
return dt.asDecodedBinary.Content
}
// GetRawJSON returns a *ParsedTransaction when the data
// encoding is EncodingJSON.
func (dt *TransactionResultEnvelope) GetParsedTransaction() *ParsedTransaction {
return dt.asParsedTransaction
}