-
Notifications
You must be signed in to change notification settings - Fork 12
/
get_transaction_status.go
108 lines (93 loc) · 4.19 KB
/
get_transaction_status.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
package publicapi
import (
"context"
"github.com/orbs-network/orbs-network-go/instrumentation/log"
"github.com/orbs-network/orbs-spec/types/go/primitives"
"github.com/orbs-network/orbs-spec/types/go/protocol"
"github.com/orbs-network/orbs-spec/types/go/protocol/client"
"github.com/orbs-network/orbs-spec/types/go/services"
"github.com/pkg/errors"
"time"
)
func (s *service) GetTransactionStatus(ctx context.Context, input *services.GetTransactionStatusInput) (*services.GetTransactionStatusOutput, error) {
if input.ClientRequest == nil {
err := errors.Errorf("error: missing input (client request is nil)")
s.logger.Info("get transaction status received missing input", log.Error(err))
return nil, err
}
s.logger.Info("get transaction status request received", log.String("flow", "checkpoint"), log.Transaction(input.ClientRequest.Txhash()))
txHash := input.ClientRequest.Txhash()
timestamp := input.ClientRequest.TransactionTimestamp()
return s.getTransactionStatus(ctx, txHash, timestamp)
}
func (s *service) getTransactionStatus(ctx context.Context, txHash primitives.Sha256, timestamp primitives.TimestampNano) (*services.GetTransactionStatusOutput, error) {
start := time.Now()
defer s.metrics.getTransactionStatusTime.RecordSince(start)
if txReceipt, err, ok := s.getFromTxPool(ctx, txHash, timestamp); ok {
return toGetTxOutput(txReceipt), err
}
blockReceipt, err := s.getFromBlockStorage(ctx, txHash, timestamp)
if err != nil {
return nil, err
}
return toGetTxOutput(blockReceipt), err
}
func (s *service) getFromTxPool(ctx context.Context, txHash primitives.Sha256, timestamp primitives.TimestampNano) (*txResponse, error, bool) {
txReceipt, err := s.transactionPool.GetCommittedTransactionReceipt(ctx, &services.GetCommittedTransactionReceiptInput{
Txhash: txHash,
TransactionTimestamp: timestamp,
})
if err != nil {
s.logger.Info("get transaction status failed in transactionPool", log.Error(err), log.String("flow", "checkpoint"), log.Transaction(txHash))
return txStatusToTxResponse(txReceipt), err, true
}
if txReceipt.TransactionStatus != protocol.TRANSACTION_STATUS_NO_RECORD_FOUND {
return txStatusToTxResponse(txReceipt), nil, true
}
return nil, nil, false
}
func txStatusToTxResponse(txStatus *services.GetCommittedTransactionReceiptOutput) *txResponse {
return &txResponse{
transactionStatus: txStatus.TransactionStatus,
transactionReceipt: txStatus.TransactionReceipt,
blockHeight: txStatus.BlockHeight,
blockTimestamp: txStatus.BlockTimestamp,
}
}
func (s *service) getFromBlockStorage(ctx context.Context, txHash primitives.Sha256, timestamp primitives.TimestampNano) (*txResponse, error) {
txReceipt, err := s.blockStorage.GetTransactionReceipt(ctx, &services.GetTransactionReceiptInput{
Txhash: txHash,
TransactionTimestamp: timestamp,
})
if err != nil {
s.logger.Info("get transaction status failed in blockStorage", log.Error(err), log.String("flow", "checkpoint"), log.Transaction(txHash))
return nil, err
}
return blockToTxResponse(txReceipt), nil
}
func blockToTxResponse(bReceipt *services.GetTransactionReceiptOutput) *txResponse {
status := protocol.TRANSACTION_STATUS_NO_RECORD_FOUND
if bReceipt.TransactionReceipt != nil {
status = protocol.TRANSACTION_STATUS_COMMITTED
}
return &txResponse{
transactionStatus: status,
transactionReceipt: bReceipt.TransactionReceipt,
blockHeight: bReceipt.BlockHeight,
blockTimestamp: bReceipt.BlockTimestamp,
}
}
func toGetTxOutput(transactionOutput *txResponse) *services.GetTransactionStatusOutput {
var receiptForClient *protocol.TransactionReceiptBuilder = nil
if transactionOutput.transactionReceipt != nil {
receiptForClient = protocol.TransactionReceiptBuilderFromRaw(transactionOutput.transactionReceipt.Raw())
}
response := &client.GetTransactionStatusResponseBuilder{
RequestStatus: translateTxStatusToResponseCode(transactionOutput.transactionStatus),
TransactionReceipt: receiptForClient,
TransactionStatus: transactionOutput.transactionStatus,
BlockHeight: transactionOutput.blockHeight,
BlockTimestamp: transactionOutput.blockTimestamp,
}
return &services.GetTransactionStatusOutput{ClientResponse: response.Build()}
}