github.com/Finschia/finschia-sdk@v0.48.1/server/rosetta/lib/internal/service/construction.go (about)

     1  package service
     2  
     3  import (
     4  	"context"
     5  	"crypto/sha256"
     6  	"encoding/hex"
     7  	"strings"
     8  
     9  	"github.com/coinbase/rosetta-sdk-go/types"
    10  
    11  	"github.com/Finschia/finschia-sdk/server/rosetta/lib/errors"
    12  )
    13  
    14  // ConstructionCombine Combine creates a network-specific transaction from an unsigned transaction
    15  // and an array of provided signatures. The signed transaction returned from this method will be
    16  // sent to the /construction/submit endpoint by the caller.
    17  func (on OnlineNetwork) ConstructionCombine(ctx context.Context, request *types.ConstructionCombineRequest) (*types.ConstructionCombineResponse, *types.Error) {
    18  	txBytes, err := hex.DecodeString(request.UnsignedTransaction)
    19  	if err != nil {
    20  		return nil, errors.ToRosetta(err)
    21  	}
    22  
    23  	signedTx, err := on.client.SignedTx(ctx, txBytes, request.Signatures)
    24  	if err != nil {
    25  		return nil, errors.ToRosetta(err)
    26  	}
    27  
    28  	return &types.ConstructionCombineResponse{
    29  		SignedTransaction: hex.EncodeToString(signedTx),
    30  	}, nil
    31  }
    32  
    33  // ConstructionDerive Derive returns the AccountIdentifier associated with a public key.
    34  func (on OnlineNetwork) ConstructionDerive(_ context.Context, request *types.ConstructionDeriveRequest) (*types.ConstructionDeriveResponse, *types.Error) {
    35  	account, err := on.client.AccountIdentifierFromPublicKey(request.PublicKey)
    36  	if err != nil {
    37  		return nil, errors.ToRosetta(err)
    38  	}
    39  	return &types.ConstructionDeriveResponse{
    40  		AccountIdentifier: account,
    41  		Metadata:          nil,
    42  	}, nil
    43  }
    44  
    45  // ConstructionHash TransactionHash returns the network-specific transaction hash for a signed
    46  // transaction.
    47  func (on OnlineNetwork) ConstructionHash(ctx context.Context, request *types.ConstructionHashRequest) (*types.TransactionIdentifierResponse, *types.Error) {
    48  	bz, err := hex.DecodeString(request.SignedTransaction)
    49  	if err != nil {
    50  		return nil, errors.ToRosetta(errors.WrapError(errors.ErrInvalidTransaction, "error decoding tx"))
    51  	}
    52  
    53  	hash := sha256.Sum256(bz)
    54  	bzHash := hash[:]
    55  	hashString := hex.EncodeToString(bzHash)
    56  
    57  	return &types.TransactionIdentifierResponse{
    58  		TransactionIdentifier: &types.TransactionIdentifier{
    59  			Hash: strings.ToUpper(hashString),
    60  		},
    61  	}, nil
    62  }
    63  
    64  // ConstructionMetadata Get any information required to construct a transaction for a specific
    65  // network (i.e. ChainID, Gas, Memo, ...).
    66  func (on OnlineNetwork) ConstructionMetadata(ctx context.Context, request *types.ConstructionMetadataRequest) (*types.ConstructionMetadataResponse, *types.Error) {
    67  	metadata, err := on.client.ConstructionMetadataFromOptions(ctx, request.Options)
    68  	if err != nil {
    69  		return nil, errors.ToRosetta(err)
    70  	}
    71  
    72  	return &types.ConstructionMetadataResponse{
    73  		Metadata: metadata,
    74  	}, nil
    75  }
    76  
    77  // ConstructionParse Parse is called on both unsigned and signed transactions to understand the
    78  // intent of the formulated transaction. This is run as a sanity check before signing (after
    79  // /construction/payloads) and before broadcast (after /construction/combine).
    80  func (on OnlineNetwork) ConstructionParse(ctx context.Context, request *types.ConstructionParseRequest) (*types.ConstructionParseResponse, *types.Error) {
    81  	txBytes, err := hex.DecodeString(request.Transaction)
    82  	if err != nil {
    83  		err := errors.WrapError(errors.ErrInvalidTransaction, err.Error())
    84  		return nil, errors.ToRosetta(err)
    85  	}
    86  	ops, signers, err := on.client.TxOperationsAndSignersAccountIdentifiers(request.Signed, txBytes)
    87  	if err != nil {
    88  		return nil, errors.ToRosetta(err)
    89  	}
    90  	return &types.ConstructionParseResponse{
    91  		Operations:               ops,
    92  		AccountIdentifierSigners: signers,
    93  		Metadata:                 nil,
    94  	}, nil
    95  }
    96  
    97  // ConstructionPayloads Payloads is called with an array of operations and the response from
    98  // /construction/metadata. It returns an unsigned transaction blob and a collection of payloads that
    99  // must be signed by particular AccountIdentifiers using a certain SignatureType.
   100  func (on OnlineNetwork) ConstructionPayloads(ctx context.Context, request *types.ConstructionPayloadsRequest) (*types.ConstructionPayloadsResponse, *types.Error) {
   101  	payload, err := on.client.ConstructionPayload(ctx, request)
   102  	if err != nil {
   103  		return nil, errors.ToRosetta(err)
   104  	}
   105  	return payload, nil
   106  }
   107  
   108  // ConstructionPreprocess Preprocess is called prior to /construction/payloads to construct a
   109  // request for any metadata that is needed for transaction construction given (i.e. account nonce).
   110  func (on OnlineNetwork) ConstructionPreprocess(ctx context.Context, request *types.ConstructionPreprocessRequest) (*types.ConstructionPreprocessResponse, *types.Error) {
   111  	options, err := on.client.PreprocessOperationsToOptions(ctx, request)
   112  	if err != nil {
   113  		return nil, errors.ToRosetta(err)
   114  	}
   115  
   116  	return options, nil
   117  }
   118  
   119  // ConstructionSubmit Submit a pre-signed transaction to the node. This call does not block on the
   120  // transaction being included in a block. Rather, it returns immediately with an indication of
   121  // whether or not the transaction was included in the mempool.
   122  func (on OnlineNetwork) ConstructionSubmit(ctx context.Context, request *types.ConstructionSubmitRequest) (*types.TransactionIdentifierResponse, *types.Error) {
   123  	txBytes, err := hex.DecodeString(request.SignedTransaction)
   124  	if err != nil {
   125  		return nil, errors.ToRosetta(err)
   126  	}
   127  
   128  	res, meta, err := on.client.PostTx(txBytes)
   129  	if err != nil {
   130  		return nil, errors.ToRosetta(err)
   131  	}
   132  
   133  	return &types.TransactionIdentifierResponse{
   134  		TransactionIdentifier: res,
   135  		Metadata:              meta,
   136  	}, nil
   137  }