Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added transaction processed status #386

Merged
merged 13 commits into from
Jun 26, 2023
17 changes: 17 additions & 0 deletions api/groups/baseTransactionGroup.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ func NewTransactionGroup(facadeHandler data.FacadeHandler) (*transactionGroup, e
{Path: "/send-user-funds", Handler: tg.sendUserFunds, Method: http.MethodPost},
{Path: "/cost", Handler: tg.requestTransactionCost, Method: http.MethodPost},
{Path: "/:txhash/status", Handler: tg.getTransactionStatus, Method: http.MethodGet},
{Path: "/:txhash/process-status", Handler: tg.getProcessedTransactionStatus, Method: http.MethodGet},
{Path: "/:txhash", Handler: tg.getTransaction, Method: http.MethodGet},
{Path: "/pool", Handler: tg.getTransactionsPool, Method: http.MethodGet},
}
Expand Down Expand Up @@ -247,6 +248,22 @@ func (group *transactionGroup) getTransaction(c *gin.Context) {
shared.RespondWith(c, http.StatusOK, gin.H{"transaction": tx}, "", data.ReturnCodeSuccess)
}

func (group *transactionGroup) getProcessedTransactionStatus(c *gin.Context) {
txHash := c.Param("txhash")
if txHash == "" {
shared.RespondWith(c, http.StatusBadRequest, nil, errors.ErrTransactionHashMissing.Error(), data.ReturnCodeRequestError)
return
}

status, err := group.facade.GetProcessedTransactionStatus(txHash)
if err != nil {
shared.RespondWith(c, http.StatusInternalServerError, nil, err.Error(), data.ReturnCodeInternalError)
return
}

shared.RespondWith(c, http.StatusOK, gin.H{"transaction": status}, "", data.ReturnCodeSuccess)
}

func getTransactionByHashAndSenderAddress(c *gin.Context, ef TransactionFacadeHandler, txHash string, sndAddr string, withEvents bool) {
tx, statusCode, err := ef.GetTransactionByHashAndSenderAddress(txHash, sndAddr, withEvents)
if err != nil {
Expand Down
82 changes: 82 additions & 0 deletions api/groups/baseTransactionGroup_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,13 @@ type nonceGapsResp struct {
Data nonceGaps
}

type txProcessedStatusResp struct {
GeneralResponse
Data struct {
TransactionHash string `json:"transaction"`
} `json:"data"`
}

func TestNewTransactionGroup_WrongFacadeShouldErr(t *testing.T) {
wrongFacade := &mock.WrongFacade{}
group, err := groups.NewTransactionGroup(wrongFacade)
Expand Down Expand Up @@ -741,3 +748,78 @@ func TestGetTransactionsPoolPoolNonceGapsForSender_ReturnsSuccessfully(t *testin
assert.Equal(t, response.Error, "")
assert.Equal(t, providedNonceGaps, &response.Data.NonceGaps)
}

func TestTransactionGroup_getProcessedTransactionStatus(t *testing.T) {
t.Parallel()

expectedErr := errors.New("expected error")
hash := "hash"
t.Run("no tx hash provided, should error", func(t *testing.T) {
t.Parallel()

transactionsGroup, err := groups.NewTransactionGroup(&mock.FacadeStub{})
require.NoError(t, err)
ws := startProxyServer(transactionsGroup, transactionsPath)

req, _ := http.NewRequest("GET", "/transaction//process-status", nil)

resp := httptest.NewRecorder()
ws.ServeHTTP(resp, req)

response := GeneralResponse{}
loadResponse(resp.Body, &response)

assert.Equal(t, http.StatusBadRequest, resp.Code)
assert.Equal(t, apiErrors.ErrTransactionHashMissing.Error(), response.Error)
})
t.Run("GetProcessedTransactionStatus errors, should error", func(t *testing.T) {
t.Parallel()

facade := &mock.FacadeStub{
GetProcessedTransactionStatusHandler: func(txHash string) (string, error) {
assert.Equal(t, hash, txHash)
return "", expectedErr
},
}
transactionsGroup, err := groups.NewTransactionGroup(facade)
require.NoError(t, err)
ws := startProxyServer(transactionsGroup, transactionsPath)

req, _ := http.NewRequest("GET", "/transaction/"+hash+"/process-status", nil)

resp := httptest.NewRecorder()
ws.ServeHTTP(resp, req)

response := GeneralResponse{}
loadResponse(resp.Body, &response)

assert.Equal(t, http.StatusInternalServerError, resp.Code)
assert.Equal(t, expectedErr.Error(), response.Error)
})
t.Run("should work", func(t *testing.T) {
t.Parallel()

status := "status"
facade := &mock.FacadeStub{
GetProcessedTransactionStatusHandler: func(txHash string) (string, error) {
assert.Equal(t, hash, txHash)
return status, nil
},
}
transactionsGroup, err := groups.NewTransactionGroup(facade)
require.NoError(t, err)
ws := startProxyServer(transactionsGroup, transactionsPath)

req, _ := http.NewRequest("GET", "/transaction/"+hash+"/process-status", nil)

resp := httptest.NewRecorder()
ws.ServeHTTP(resp, req)

response := txProcessedStatusResp{}
loadResponse(resp.Body, &response)

assert.Equal(t, http.StatusOK, resp.Code)
assert.Empty(t, response.Error)
assert.Equal(t, status, response.Data.TransactionHash)
})
}
1 change: 1 addition & 0 deletions api/groups/interface.go
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,7 @@ type TransactionFacadeHandler interface {
SendUserFunds(receiver string, value *big.Int) error
TransactionCostRequest(tx *data.Transaction) (*data.TxCostResponseData, error)
GetTransactionStatus(txHash string, sender string) (string, error)
GetProcessedTransactionStatus(txHash string) (string, error)
GetTransaction(txHash string, withResults bool) (*transaction.ApiTransactionResult, error)
GetTransactionByHashAndSenderAddress(txHash string, sndAddr string, withEvents bool) (*transaction.ApiTransactionResult, int, error)
GetTransactionsPool(fields string) (*data.TransactionsPool, error)
Expand Down
6 changes: 6 additions & 0 deletions api/mock/facadeStub.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ type FacadeStub struct {
ValidatorStatisticsHandler func() (map[string]*data.ValidatorApiResponse, error)
TransactionCostRequestHandler func(tx *data.Transaction) (*data.TxCostResponseData, error)
GetTransactionStatusHandler func(txHash string, sender string) (string, error)
GetProcessedTransactionStatusHandler func(txHash string) (string, error)
GetConfigMetricsHandler func() (*data.GenericAPIResponse, error)
GetNetworkMetricsHandler func(shardID uint32) (*data.GenericAPIResponse, error)
GetAllIssuedESDTsHandler func(tokenType string) (*data.GenericAPIResponse, error)
Expand Down Expand Up @@ -400,6 +401,11 @@ func (f *FacadeStub) GetTransactionStatus(txHash string, sender string) (string,
return f.GetTransactionStatusHandler(txHash, sender)
}

// GetProcessedTransactionStatus -
func (f *FacadeStub) GetProcessedTransactionStatus(txHash string) (string, error) {
return f.GetProcessedTransactionStatusHandler(txHash)
}

// SendUserFunds -
func (f *FacadeStub) SendUserFunds(receiver string, value *big.Int) error {
return f.SendUserFundsCalled(receiver, value)
Expand Down
1 change: 1 addition & 0 deletions cmd/proxy/config/apiConfig/v1_0.toml
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,7 @@ Routes = [
{ Name = "/cost", Open = true, Secured = false, RateLimit = 0 },
{ Name = "/:txhash", Open = true, Secured = false, RateLimit = 0 },
{ Name = "/:txhash/status", Open = true, Secured = false, RateLimit = 0 },
{ Name = "/:txhash/process-status", Open = true, Secured = false, RateLimit = 0 },
{ Name = "/pool", Open = true, Secured = false, RateLimit = 0 }
]

Expand Down
1 change: 1 addition & 0 deletions cmd/proxy/config/apiConfig/v_next.toml
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,7 @@ Routes = [
{ Name = "/cost", Open = true, Secured = false, RateLimit = 0 },
{ Name = "/:txhash", Open = true, Secured = false, RateLimit = 0 },
{ Name = "/:txhash/status", Open = true, Secured = false, RateLimit = 0 },
{ Name = "/:txhash/process-status", Open = true, Secured = false, RateLimit = 0 },
{ Name = "/pool", Open = true, Secured = false, RateLimit = 0 }
]

Expand Down
6 changes: 6 additions & 0 deletions data/constants.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package data

import "github.com/multiversx/mx-chain-core-go/data/transaction"

// TxStatusUnknown defines the response that should be received from an observer when transaction status is unknown
const TxStatusUnknown transaction.TxStatus = "unknown"
5 changes: 5 additions & 0 deletions facade/baseFacade.go
Original file line number Diff line number Diff line change
Expand Up @@ -216,6 +216,11 @@ func (epf *ProxyFacade) GetTransactionStatus(txHash string, sender string) (stri
return epf.txProc.GetTransactionStatus(txHash, sender)
}

// GetProcessedTransactionStatus should return transaction status after internal processing of the transaction results
func (epf *ProxyFacade) GetProcessedTransactionStatus(txHash string) (string, error) {
return epf.txProc.GetProcessedTransactionStatus(txHash)
}

// GetTransaction should return a transaction by hash
func (epf *ProxyFacade) GetTransaction(txHash string, withResults bool) (*transaction.ApiTransactionResult, error) {
return epf.txProc.GetTransaction(txHash, withResults)
Expand Down
1 change: 1 addition & 0 deletions facade/interface.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ type TransactionProcessor interface {
TransactionCostRequest(tx *data.Transaction) (*data.TxCostResponseData, error)
GetTransactionStatus(txHash string, sender string) (string, error)
GetTransaction(txHash string, withEvents bool) (*transaction.ApiTransactionResult, error)
GetProcessedTransactionStatus(txHash string) (string, error)
GetTransactionByHashAndSenderAddress(txHash string, sndAddr string, withEvents bool) (*transaction.ApiTransactionResult, int, error)
ComputeTransactionHash(tx *data.Transaction) (string, error)
GetTransactionsPool(fields string) (*data.TransactionsPool, error)
Expand Down
81 changes: 65 additions & 16 deletions facade/mock/transactionProcessorStub.go
Original file line number Diff line number Diff line change
@@ -1,20 +1,24 @@
package mock

import (
"errors"
"math/big"

"github.com/multiversx/mx-chain-core-go/data/transaction"
"github.com/multiversx/mx-chain-proxy-go/data"
)

var errNotImplemented = errors.New("not implemented")

// TransactionProcessorStub -
type TransactionProcessorStub struct {
SendTransactionCalled func(tx *data.Transaction) (int, string, error)
SendMultipleTransactionsCalled func(txs []*data.Transaction) (data.MultipleTransactionsResponseData, error)
SimulateTransactionCalled func(tx *data.Transaction, checkSignature bool) (*data.GenericAPIResponse, error)
SendUserFundsCalled func(receiver string, value *big.Int) error
TransactionCostRequestHandler func(tx *data.Transaction) (*data.TxCostResponseData, error)
GetTransactionStatusHandler func(txHash string, sender string) (string, error)
TransactionCostRequestCalled func(tx *data.Transaction) (*data.TxCostResponseData, error)
GetTransactionStatusCalled func(txHash string, sender string) (string, error)
GetProcessedTransactionStatusCalled func(txHash string) (string, error)
GetTransactionCalled func(txHash string, withEvents bool) (*transaction.ApiTransactionResult, error)
GetTransactionByHashAndSenderAddressCalled func(txHash string, sndAddr string, withEvents bool) (*transaction.ApiTransactionResult, int, error)
ComputeTransactionHashCalled func(tx *data.Transaction) (string, error)
Expand All @@ -27,47 +31,92 @@ type TransactionProcessorStub struct {

// SimulateTransaction -
func (tps *TransactionProcessorStub) SimulateTransaction(tx *data.Transaction, checkSignature bool) (*data.GenericAPIResponse, error) {
return tps.SimulateTransactionCalled(tx, checkSignature)
if tps.SimulateTransactionCalled != nil {
return tps.SimulateTransactionCalled(tx, checkSignature)
}

return nil, errNotImplemented
}

// SendTransaction -
func (tps *TransactionProcessorStub) SendTransaction(tx *data.Transaction) (int, string, error) {
return tps.SendTransactionCalled(tx)
if tps.SendTransactionCalled != nil {
return tps.SendTransactionCalled(tx)
}

return 0, "", errNotImplemented
}

// SendMultipleTransactions -
func (tps *TransactionProcessorStub) SendMultipleTransactions(txs []*data.Transaction) (data.MultipleTransactionsResponseData, error) {
return tps.SendMultipleTransactionsCalled(txs)
if tps.SendMultipleTransactionsCalled != nil {
return tps.SendMultipleTransactionsCalled(txs)
}

return data.MultipleTransactionsResponseData{}, errNotImplemented
}

// ComputeTransactionHash -
func (tps *TransactionProcessorStub) ComputeTransactionHash(tx *data.Transaction) (string, error) {
return tps.ComputeTransactionHashCalled(tx)
if tps.ComputeTransactionHashCalled != nil {
return tps.ComputeTransactionHashCalled(tx)
}

return "", errNotImplemented
}

// SendUserFunds -
func (tps *TransactionProcessorStub) SendUserFunds(receiver string, value *big.Int) error {
return tps.SendUserFundsCalled(receiver, value)
if tps.SendUserFundsCalled != nil {
return tps.SendUserFundsCalled(receiver, value)
}

return errNotImplemented
}

// GetTransactionStatus -
func (tps *TransactionProcessorStub) GetTransactionStatus(txHash string, sender string) (string, error) {
return tps.GetTransactionStatusHandler(txHash, sender)
if tps.GetTransactionStatusCalled != nil {
return tps.GetTransactionStatusCalled(txHash, sender)
}

return "", errNotImplemented
}

// GetProcessedTransactionStatus -
func (tps *TransactionProcessorStub) GetProcessedTransactionStatus(txHash string) (string, error) {
if tps.GetProcessedTransactionStatusCalled != nil {
return tps.GetProcessedTransactionStatusCalled(txHash)
}

return "", errNotImplemented
}

// GetTransaction -
func (tps *TransactionProcessorStub) GetTransaction(txHash string, withEvents bool) (*transaction.ApiTransactionResult, error) {
return tps.GetTransactionCalled(txHash, withEvents)
if tps.GetTransactionCalled != nil {
return tps.GetTransactionCalled(txHash, withEvents)
}

return nil, errNotImplemented
}

// GetTransactionByHashAndSenderAddress -
func (tps *TransactionProcessorStub) GetTransactionByHashAndSenderAddress(txHash string, sndAddr string, withEvents bool) (*transaction.ApiTransactionResult, int, error) {
return tps.GetTransactionByHashAndSenderAddressCalled(txHash, sndAddr, withEvents)
if tps.GetTransactionByHashAndSenderAddressCalled != nil {
return tps.GetTransactionByHashAndSenderAddressCalled(txHash, sndAddr, withEvents)
}

return nil, 0, errNotImplemented
}

// TransactionCostRequest -
func (tps *TransactionProcessorStub) TransactionCostRequest(tx *data.Transaction) (*data.TxCostResponseData, error) {
return tps.TransactionCostRequestHandler(tx)
if tps.TransactionCostRequestCalled != nil {
return tps.TransactionCostRequestCalled(tx)
}

return nil, errNotImplemented
}

// GetTransactionsPool -
Expand All @@ -76,7 +125,7 @@ func (tps *TransactionProcessorStub) GetTransactionsPool(fields string) (*data.T
return tps.GetTransactionsPoolCalled(fields)
}

return nil, nil
return nil, errNotImplemented
}

// GetTransactionsPoolForShard -
Expand All @@ -85,7 +134,7 @@ func (tps *TransactionProcessorStub) GetTransactionsPoolForShard(shardID uint32,
return tps.GetTransactionsPoolForShardCalled(shardID, fields)
}

return nil, nil
return nil, errNotImplemented
}

// GetTransactionsPoolForSender -
Expand All @@ -94,7 +143,7 @@ func (tps *TransactionProcessorStub) GetTransactionsPoolForSender(sender, fields
return tps.GetTransactionsPoolForSenderCalled(sender, fields)
}

return nil, nil
return nil, errNotImplemented
}

// GetLastPoolNonceForSender -
Expand All @@ -103,7 +152,7 @@ func (tps *TransactionProcessorStub) GetLastPoolNonceForSender(sender string) (u
return tps.GetLastPoolNonceForSenderCalled(sender)
}

return 0, nil
return 0, errNotImplemented
}

// GetTransactionsPoolNonceGapsForSender -
Expand All @@ -112,5 +161,5 @@ func (tps *TransactionProcessorStub) GetTransactionsPoolNonceGapsForSender(sende
return tps.GetTransactionsPoolNonceGapsForSenderCalled(sender)
}

return nil, nil
return nil, errNotImplemented
}
6 changes: 6 additions & 0 deletions process/export_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package process
import (
"time"

"github.com/multiversx/mx-chain-core-go/data/transaction"
proxyData "github.com/multiversx/mx-chain-proxy-go/data"
)

Expand All @@ -25,3 +26,8 @@ func ComputeTokenStorageKey(tokenID string, nonce uint64) string {
func GetShortHashSize() int {
return shortHashSize
}

// ComputeTransactionStatus -
func (tp *TransactionProcessor) ComputeTransactionStatus(tx *transaction.ApiTransactionResult, withResults bool) transaction.TxStatus {
return tp.computeTransactionStatus(tx, withResults)
}
Loading