You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
110 lines
4.1 KiB
110 lines
4.1 KiB
package services
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
|
|
"github.com/coinbase/rosetta-sdk-go/types"
|
|
hmyTypes "github.com/harmony-one/harmony/core/types"
|
|
"github.com/harmony-one/harmony/rosetta/common"
|
|
stakingTypes "github.com/harmony-one/harmony/staking/types"
|
|
"github.com/pkg/errors"
|
|
)
|
|
|
|
// ConstructionHash implements the /construction/hash endpoint.
|
|
func (s *ConstructAPI) ConstructionHash(
|
|
ctx context.Context, request *types.ConstructionHashRequest,
|
|
) (*types.TransactionIdentifierResponse, *types.Error) {
|
|
if err := assertValidNetworkIdentifier(request.NetworkIdentifier, s.hmy.ShardID); err != nil {
|
|
return nil, err
|
|
}
|
|
_, tx, rosettaError := unpackWrappedTransactionFromString(request.SignedTransaction, true)
|
|
if rosettaError != nil {
|
|
return nil, rosettaError
|
|
}
|
|
if tx == nil {
|
|
return nil, common.NewError(common.CatchAllError, map[string]interface{}{
|
|
"message": "nil transaction",
|
|
})
|
|
}
|
|
if tx.ShardID() != s.hmy.ShardID {
|
|
return nil, common.NewError(common.InvalidTransactionConstructionError, map[string]interface{}{
|
|
"message": fmt.Sprintf("transaction is for shard %v != shard %v", tx.ShardID(), s.hmy.ShardID),
|
|
})
|
|
}
|
|
return &types.TransactionIdentifierResponse{
|
|
TransactionIdentifier: &types.TransactionIdentifier{Hash: tx.Hash().String()},
|
|
}, nil
|
|
}
|
|
|
|
// ConstructionSubmit implements the /construction/submit endpoint.
|
|
func (s *ConstructAPI) ConstructionSubmit(
|
|
ctx context.Context, request *types.ConstructionSubmitRequest,
|
|
) (*types.TransactionIdentifierResponse, *types.Error) {
|
|
if err := assertValidNetworkIdentifier(request.NetworkIdentifier, s.hmy.ShardID); err != nil {
|
|
return nil, err
|
|
}
|
|
wrappedTransaction, tx, rosettaError := unpackWrappedTransactionFromString(request.SignedTransaction, true)
|
|
if rosettaError != nil {
|
|
return nil, rosettaError
|
|
}
|
|
if wrappedTransaction == nil || tx == nil {
|
|
return nil, common.NewError(common.CatchAllError, map[string]interface{}{
|
|
"message": "nil wrapped transaction or nil unwrapped transaction",
|
|
})
|
|
}
|
|
if tx.ShardID() != s.hmy.ShardID {
|
|
return nil, common.NewError(common.StakingTransactionSubmissionError, map[string]interface{}{
|
|
"message": fmt.Sprintf("transaction is for shard %v != shard %v", tx.ShardID(), s.hmy.ShardID),
|
|
})
|
|
}
|
|
|
|
wrappedSenderAddress, err := getAddress(wrappedTransaction.From)
|
|
if err != nil {
|
|
return nil, common.NewError(common.StakingTransactionSubmissionError, map[string]interface{}{
|
|
"message": errors.WithMessage(err, "unable to get address from wrapped transaction"),
|
|
})
|
|
}
|
|
|
|
var signedTx hmyTypes.PoolTransaction
|
|
if stakingTx, ok := tx.(*stakingTypes.StakingTransaction); ok && wrappedTransaction.IsStaking {
|
|
signedTx = stakingTx
|
|
} else if plainTx, ok := tx.(*hmyTypes.Transaction); ok && !wrappedTransaction.IsStaking {
|
|
signedTx = plainTx
|
|
} else {
|
|
return nil, common.NewError(common.CatchAllError, map[string]interface{}{
|
|
"message": "invalid/inconsistent type or unknown transaction type stored in wrapped transaction",
|
|
})
|
|
}
|
|
|
|
txSenderAddress, err := signedTx.SenderAddress()
|
|
if err != nil {
|
|
return nil, common.NewError(common.StakingTransactionSubmissionError, map[string]interface{}{
|
|
"message": errors.WithMessage(err, "unable to get sender address from transaction").Error(),
|
|
})
|
|
}
|
|
|
|
if wrappedSenderAddress != txSenderAddress {
|
|
return nil, common.NewError(common.StakingTransactionSubmissionError, map[string]interface{}{
|
|
"message": "transaction sender address does not match wrapped transaction sender address",
|
|
})
|
|
}
|
|
|
|
if wrappedTransaction.IsStaking {
|
|
if err := s.hmy.SendStakingTx(ctx, signedTx.(*stakingTypes.StakingTransaction)); err != nil {
|
|
return nil, common.NewError(common.StakingTransactionSubmissionError, map[string]interface{}{
|
|
"message": fmt.Sprintf("error is: %s, gas price is: %s, gas limit is: %d", err.Error(), signedTx.GasPrice().String(), signedTx.GasLimit()),
|
|
})
|
|
}
|
|
} else {
|
|
if err := s.hmy.SendTx(ctx, signedTx.(*hmyTypes.Transaction)); err != nil {
|
|
return nil, common.NewError(common.TransactionSubmissionError, map[string]interface{}{
|
|
"message": err.Error(),
|
|
})
|
|
}
|
|
}
|
|
|
|
return &types.TransactionIdentifierResponse{
|
|
TransactionIdentifier: &types.TransactionIdentifier{Hash: tx.Hash().String()},
|
|
}, nil
|
|
}
|
|
|