-
Notifications
You must be signed in to change notification settings - Fork 5
/
Copy pathtypes.go
212 lines (188 loc) · 6.7 KB
/
types.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
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
package tss
import (
"bytes"
"encoding/base64"
"fmt"
"strconv"
xdr3 "github.com/stellar/go-xdr/xdr3"
"github.com/stellar/go/xdr"
"github.com/stellar/wallet-backend/internal/entities"
)
type RPCGetIngestTxResponse struct {
// A status that indicated whether this transaction failed or successly made it to the ledger
Status entities.RPCStatus
// The error code that is derived by deserialzing the ResultXdr string in the sendTransaction response
// list of possible errror codes: https://developers.stellar.org/docs/data/horizon/api-reference/errors/result-codes/transactions
Code RPCTXCode
// The raw TransactionEnvelope XDR for this transaction
EnvelopeXDR string
// The raw TransactionResult XDR of the envelopeXdr
ResultXDR string
// The unix timestamp of when the transaction was included in the ledger
CreatedAt int64
}
func ParseToRPCGetIngestTxResponse(result entities.RPCGetTransactionResult, err error) (RPCGetIngestTxResponse, error) {
if err != nil {
return RPCGetIngestTxResponse{Status: entities.ErrorStatus}, err
}
getIngestTxResponse := RPCGetIngestTxResponse{
Status: result.Status,
EnvelopeXDR: result.EnvelopeXDR,
ResultXDR: result.ResultXDR,
}
if getIngestTxResponse.Status != entities.NotFoundStatus {
getIngestTxResponse.CreatedAt, err = strconv.ParseInt(result.CreatedAt, 10, 64)
if err != nil {
return RPCGetIngestTxResponse{Status: entities.ErrorStatus}, fmt.Errorf("unable to parse createdAt: %w", err)
}
}
getIngestTxResponse.Code, err = TransactionResultXDRToCode(result.ResultXDR)
if err != nil {
return getIngestTxResponse, fmt.Errorf("parse error result xdr string: %w", err)
}
return getIngestTxResponse, nil
}
type OtherStatus string
type OtherCodes int32
type TransactionResultCode int32
const (
NewStatus OtherStatus = "NEW"
NoStatus OtherStatus = ""
SentStatus OtherStatus = "SENT"
NotSentStatus OtherStatus = "NOT_SENT"
)
type RPCTXStatus struct {
RPCStatus entities.RPCStatus
OtherStatus OtherStatus
}
func (s RPCTXStatus) Status() string {
if s.OtherStatus != NoStatus {
return string(s.OtherStatus)
}
return string(s.RPCStatus)
}
const (
// Do not use NoCode
NoCode OtherCodes = 0
// These values need to not overlap the values in xdr.TransactionResultCode
NewCode OtherCodes = 100
RPCFailCode OtherCodes = 101
UnmarshalBinaryCode OtherCodes = 102
EmptyCode OtherCodes = 103
)
type RPCTXCode struct {
TxResultCode xdr.TransactionResultCode
OtherCodes OtherCodes
}
func (c RPCTXCode) Code() int {
if c.OtherCodes != NoCode {
return int(c.OtherCodes)
}
return int(c.TxResultCode)
}
var FinalCodes = []xdr.TransactionResultCode{
xdr.TransactionResultCodeTxSuccess,
xdr.TransactionResultCodeTxFailed,
xdr.TransactionResultCodeTxMissingOperation,
xdr.TransactionResultCodeTxInsufficientBalance,
xdr.TransactionResultCodeTxBadAuth,
xdr.TransactionResultCodeTxBadAuthExtra,
xdr.TransactionResultCodeTxMalformed,
xdr.TransactionResultCodeTxNotSupported,
xdr.TransactionResultCodeTxFeeBumpInnerFailed,
xdr.TransactionResultCodeTxFeeBumpInnerSuccess,
xdr.TransactionResultCodeTxNoAccount,
xdr.TransactionResultCodeTxBadSponsorship,
xdr.TransactionResultCodeTxSorobanInvalid,
xdr.TransactionResultCodeTxBadMinSeqAgeOrGap,
}
var NonJitterErrorCodes = []xdr.TransactionResultCode{
xdr.TransactionResultCodeTxTooEarly,
xdr.TransactionResultCodeTxTooLate,
xdr.TransactionResultCodeTxBadSeq,
}
var JitterErrorCodes = []xdr.TransactionResultCode{
xdr.TransactionResultCodeTxInsufficientFee,
xdr.TransactionResultCodeTxInternalError,
}
type RPCSendTxResponse struct {
// The hash of the transaction submitted to RPC
TransactionHash string
TransactionXDR string
// The status of an RPC sendTransaction call. Can be one of [PENDING, DUPLICATE, TRY_AGAIN_LATER, ERROR]
Status RPCTXStatus
// The (optional) error code that is derived by deserialzing the errorResultXdr string in the sendTransaction response
// list of possible errror codes: https://developers.stellar.org/docs/data/horizon/api-reference/errors/result-codes/transactions
Code RPCTXCode
ErrorResultXDR string
}
func ParseToRPCSendTxResponse(transactionXDR string, result entities.RPCSendTransactionResult, err error) (RPCSendTxResponse, error) {
sendTxResponse := RPCSendTxResponse{}
sendTxResponse.TransactionXDR = transactionXDR
if err != nil {
sendTxResponse.Status.RPCStatus = entities.ErrorStatus
sendTxResponse.Code.OtherCodes = RPCFailCode
return sendTxResponse, fmt.Errorf("RPC fail: %w", err)
}
sendTxResponse.Status.RPCStatus = result.Status
sendTxResponse.TransactionHash = result.Hash
sendTxResponse.ErrorResultXDR = result.ErrorResultXDR
sendTxResponse.Code, err = TransactionResultXDRToCode(result.ErrorResultXDR)
if err != nil {
return sendTxResponse, fmt.Errorf("parse error result xdr string: %w", err)
}
return sendTxResponse, nil
}
func UnmarshallTransactionResultXDR(resultXDR string) (xdr.TransactionResult, error) {
unmarshalErr := "unable to unmarshal errorResultXDR: %s"
decodedBytes, err := base64.StdEncoding.DecodeString(resultXDR)
if err != nil {
return xdr.TransactionResult{}, fmt.Errorf(unmarshalErr, resultXDR)
}
var txResultXDR xdr.TransactionResult
_, err = xdr3.Unmarshal(bytes.NewReader(decodedBytes), &txResultXDR)
if err != nil {
return xdr.TransactionResult{}, fmt.Errorf(unmarshalErr, resultXDR)
}
return txResultXDR, nil
}
func TransactionResultXDRToCode(errorResultXDR string) (RPCTXCode, error) {
if errorResultXDR == "" {
return RPCTXCode{
OtherCodes: EmptyCode,
}, nil
}
errorResult, err := UnmarshallTransactionResultXDR(errorResultXDR)
if err != nil {
return RPCTXCode{OtherCodes: UnmarshalBinaryCode}, fmt.Errorf("unable to parse: %w", err)
}
return RPCTXCode{
TxResultCode: errorResult.Result.Code,
}, nil
}
type TSSResponse struct {
TransactionHash string `json:"tx_hash"`
TransactionResultCode string `json:"tx_result_code"`
Status string `json:"status"`
CreatedAt int64 `json:"created_at"`
EnvelopeXDR string `json:"envelopeXdr"`
ResultXDR string `json:"resultXdr"`
}
type Payload struct {
WebhookURL string
// The hash of the transaction xdr submitted by the client - the id of the transaction submitted by a client
TransactionHash string
// The xdr of the transaction
TransactionXDR string
// Relevant fields in an RPC sendTransaction response
RpcSubmitTxResponse RPCSendTxResponse
// Relevant fields in the transaction list inside the RPC getTransactions response
RpcGetIngestTxResponse RPCGetIngestTxResponse
// indicates if the transaction to be built from this payload should be wrapped in a fee bump transaction
FeeBump bool
}
type Channel interface {
Send(payload Payload)
Receive(payload Payload)
Stop()
}