139 lines
5.3 KiB
Go
139 lines
5.3 KiB
Go
package service
|
|
|
|
import (
|
|
"context"
|
|
"crypto/sha256"
|
|
"encoding/hex"
|
|
"strings"
|
|
|
|
"github.com/coinbase/rosetta-sdk-go/types"
|
|
|
|
"github.com/cosmos/cosmos-sdk/server/rosetta/lib/errors"
|
|
)
|
|
|
|
// ConstructionCombine Combine creates a network-specific transaction from an unsigned transaction
|
|
// and an array of provided signatures. The signed transaction returned from this method will be
|
|
// sent to the /construction/submit endpoint by the caller.
|
|
func (on OnlineNetwork) ConstructionCombine(ctx context.Context, request *types.ConstructionCombineRequest) (*types.ConstructionCombineResponse, *types.Error) {
|
|
txBytes, err := hex.DecodeString(request.UnsignedTransaction)
|
|
if err != nil {
|
|
return nil, errors.ToRosetta(err)
|
|
}
|
|
|
|
signedTx, err := on.client.SignedTx(ctx, txBytes, request.Signatures)
|
|
if err != nil {
|
|
return nil, errors.ToRosetta(err)
|
|
}
|
|
|
|
return &types.ConstructionCombineResponse{
|
|
SignedTransaction: hex.EncodeToString(signedTx),
|
|
}, nil
|
|
}
|
|
|
|
// ConstructionDerive Derive returns the AccountIdentifier associated with a public key.
|
|
func (on OnlineNetwork) ConstructionDerive(_ context.Context, request *types.ConstructionDeriveRequest) (*types.ConstructionDeriveResponse, *types.Error) {
|
|
account, err := on.client.AccountIdentifierFromPublicKey(request.PublicKey)
|
|
if err != nil {
|
|
return nil, errors.ToRosetta(err)
|
|
}
|
|
return &types.ConstructionDeriveResponse{
|
|
AccountIdentifier: account,
|
|
Metadata: nil,
|
|
}, nil
|
|
}
|
|
|
|
// ConstructionHash TransactionHash returns the network-specific transaction hash for a signed
|
|
// transaction.
|
|
func (on OnlineNetwork) ConstructionHash(ctx context.Context, request *types.ConstructionHashRequest) (*types.TransactionIdentifierResponse, *types.Error) {
|
|
bz, err := hex.DecodeString(request.SignedTransaction)
|
|
if err != nil {
|
|
return nil, errors.ToRosetta(errors.WrapError(errors.ErrInvalidTransaction, "error decoding tx"))
|
|
}
|
|
|
|
hash := sha256.Sum256(bz)
|
|
bzHash := hash[:]
|
|
hashString := hex.EncodeToString(bzHash)
|
|
|
|
return &types.TransactionIdentifierResponse{
|
|
TransactionIdentifier: &types.TransactionIdentifier{
|
|
Hash: strings.ToUpper(hashString),
|
|
},
|
|
}, nil
|
|
}
|
|
|
|
// ConstructionMetadata Get any information required to construct a transaction for a specific
|
|
// network (i.e. ChainID, Gas, Memo, ...).
|
|
func (on OnlineNetwork) ConstructionMetadata(ctx context.Context, request *types.ConstructionMetadataRequest) (*types.ConstructionMetadataResponse, *types.Error) {
|
|
metadata, err := on.client.ConstructionMetadataFromOptions(ctx, request.Options)
|
|
if err != nil {
|
|
return nil, errors.ToRosetta(err)
|
|
}
|
|
|
|
return &types.ConstructionMetadataResponse{
|
|
Metadata: metadata,
|
|
}, nil
|
|
}
|
|
|
|
// ConstructionParse Parse is called on both unsigned and signed transactions to understand the
|
|
// intent of the formulated transaction. This is run as a sanity check before signing (after
|
|
// /construction/payloads) and before broadcast (after /construction/combine).
|
|
func (on OnlineNetwork) ConstructionParse(ctx context.Context, request *types.ConstructionParseRequest) (*types.ConstructionParseResponse, *types.Error) {
|
|
txBytes, err := hex.DecodeString(request.Transaction)
|
|
if err != nil {
|
|
err := errors.WrapError(errors.ErrInvalidTransaction, err.Error())
|
|
return nil, errors.ToRosetta(err)
|
|
}
|
|
ops, signers, err := on.client.TxOperationsAndSignersAccountIdentifiers(request.Signed, txBytes)
|
|
if err != nil {
|
|
return nil, errors.ToRosetta(err)
|
|
}
|
|
return &types.ConstructionParseResponse{
|
|
Operations: ops,
|
|
AccountIdentifierSigners: signers,
|
|
Metadata: nil,
|
|
}, nil
|
|
|
|
}
|
|
|
|
// ConstructionPayloads Payloads is called with an array of operations and the response from
|
|
// /construction/metadata. It returns an unsigned transaction blob and a collection of payloads that
|
|
// must be signed by particular AccountIdentifiers using a certain SignatureType.
|
|
func (on OnlineNetwork) ConstructionPayloads(ctx context.Context, request *types.ConstructionPayloadsRequest) (*types.ConstructionPayloadsResponse, *types.Error) {
|
|
payload, err := on.client.ConstructionPayload(ctx, request)
|
|
if err != nil {
|
|
return nil, errors.ToRosetta(err)
|
|
}
|
|
return payload, nil
|
|
}
|
|
|
|
// ConstructionPreprocess Preprocess is called prior to /construction/payloads to construct a
|
|
// request for any metadata that is needed for transaction construction given (i.e. account nonce).
|
|
func (on OnlineNetwork) ConstructionPreprocess(ctx context.Context, request *types.ConstructionPreprocessRequest) (*types.ConstructionPreprocessResponse, *types.Error) {
|
|
options, err := on.client.PreprocessOperationsToOptions(ctx, request)
|
|
if err != nil {
|
|
return nil, errors.ToRosetta(err)
|
|
}
|
|
|
|
return options, nil
|
|
}
|
|
|
|
// ConstructionSubmit Submit a pre-signed transaction to the node. This call does not block on the
|
|
// transaction being included in a block. Rather, it returns immediately with an indication of
|
|
// whether or not the transaction was included in the mempool.
|
|
func (on OnlineNetwork) ConstructionSubmit(ctx context.Context, request *types.ConstructionSubmitRequest) (*types.TransactionIdentifierResponse, *types.Error) {
|
|
txBytes, err := hex.DecodeString(request.SignedTransaction)
|
|
if err != nil {
|
|
return nil, errors.ToRosetta(err)
|
|
}
|
|
|
|
res, meta, err := on.client.PostTx(txBytes)
|
|
if err != nil {
|
|
return nil, errors.ToRosetta(err)
|
|
}
|
|
|
|
return &types.TransactionIdentifierResponse{
|
|
TransactionIdentifier: res,
|
|
Metadata: meta,
|
|
}, nil
|
|
}
|