/
errors.go
105 lines (96 loc) · 3.83 KB
/
errors.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
package api
import (
"fmt"
"strings"
"github.com/coinbase/rosetta-sdk-go/types"
"github.com/onflow/rosetta/log"
)
var (
errorCodes = map[int32]*types.Error{}
serverErrors = []*types.Error{}
)
var (
// base errors
errBroadcastFailed = newError(101, "broadcast failed", false)
errNotImplemented = newError(102, "method not implemented", false)
errOfflineMode = newError(103, "method not available in offline mode", false)
errTransactionNotInMempool = newError(104, "transaction not in mempool", false)
// on-chain errors
errInvalidNumberOfAccountKeys = newError(201, "invalid number of account keys", false)
errTransactionExpired = newError(202, "transaction expired", false)
errInvalidKeyID = newError(203, "invalid key id", false)
// internal errors
errInternal = newError(301, "unexpected internal error", false)
errMissingData = newError(302, "block state doesn't exist or has been pruned at the execution node", false)
errProtobuf = newError(303, "protobuf error", false)
// input validation errors
errInvalidAccountAddress = newError(401, "invalid account address", false)
errInvalidBlockHash = newError(402, "invalid block hash", false)
errInvalidBlockIdentifier = newError(403, "invalid block identifier", false)
errInvalidBlockIndex = newError(404, "invalid block index", false)
errInvalidConstructOptions = newError(405, "invalid construct options", false)
errInvalidCurrency = newError(406, "invalid currency", false)
errInvalidMetadataField = newError(407, "invalid metadata field", false)
errInvalidOpsIntent = newError(408, "invalid ops intent", false)
errInvalidSignature = newError(409, "invalid signature", false)
errInvalidTransactionHash = newError(410, "invalid transaction hash", false)
errInvalidTransactionPayload = newError(411, "invalid transaction payload", false)
errUnknownTransactionHash = newError(412, "unknown transaction hash", false)
// potentially retriable errors
errAccessNodeInaccessible = newError(501, "access node inaccessible", true)
errBlockNotIndexed = newError(502, "block data not in index", true)
errRateLimited = newError(503, "rate limited", true)
errInvalidIndexedState = newError(504, "invalid indexed state", true)
errFailedAccessAPICall = newError(505, "failed access api call", true)
)
func formatErr(xerr *types.Error) string {
if len(xerr.Details) > 0 {
detail := xerr.Details["error"].(string)
return fmt.Sprintf(
"%s [%d] (%s)", xerr.Message, xerr.Code, detail,
)
}
return fmt.Sprintf("%s [%d]", xerr.Message, xerr.Code)
}
func handleExecutionErr(err error, typ string) *types.Error {
// NOTE(tav): We use string matching to try and determine if the data
// doesn't exist, e.g. because the state has been pruned from the execution
// node or doesn't exist.
//
// This error string may change upstream in which case, we'd need to update
// this check.
if strings.Contains(err.Error(), "get register failed") {
return wrapErrorf(errMissingData, "failed to %s: %s", typ, err)
}
return wrapErrorf(errInternal, "failed to %s: %s", typ, err)
}
func newError(code int32, msg string, retriable bool) *types.Error {
prev, exists := errorCodes[code]
if exists {
log.Fatalf(
"Duplicate API error definition %d for %q and %q",
code, msg, prev.Message,
)
}
err := &types.Error{
Code: code,
Message: msg,
Retriable: retriable,
}
serverErrors = append(serverErrors, err)
return err
}
func wrapErr(xerr *types.Error, err error) *types.Error {
dup := *xerr
dup.Details = map[string]interface{}{
"error": err.Error(),
}
return &dup
}
func wrapErrorf(xerr *types.Error, format string, args ...interface{}) *types.Error {
dup := *xerr
dup.Details = map[string]interface{}{
"error": fmt.Sprintf(format, args...),
}
return &dup
}