github.com/Finschia/finschia-sdk@v0.48.1/server/rosetta/lib/errors/errors.go (about) 1 package errors 2 3 // errors.go contains all the errors returned by the adapter implementation 4 // plus some extra utilities to parse those errors 5 6 import ( 7 "fmt" 8 9 grpccodes "google.golang.org/grpc/codes" 10 grpcstatus "google.golang.org/grpc/status" 11 12 "github.com/coinbase/rosetta-sdk-go/types" 13 ) 14 15 // ListErrors lists all the registered errors 16 func ListErrors() []*types.Error { 17 return registry.list() 18 } 19 20 // SealAndListErrors seals the registry and lists its errors 21 func SealAndListErrors() []*types.Error { 22 registry.seal() 23 return registry.list() 24 } 25 26 // Error defines an error that can be converted to a Rosetta API error. 27 type Error struct { 28 rosErr *types.Error 29 } 30 31 func (e *Error) Error() string { 32 if e.rosErr == nil { 33 return ErrUnknown.Error() 34 } 35 return fmt.Sprintf("rosetta: (%d) %s", e.rosErr.Code, e.rosErr.Message) 36 } 37 38 // Is implements errors.Is for *Error, two errors are considered equal 39 // if their error codes are identical 40 func (e *Error) Is(err error) bool { 41 // assert it can be casted 42 rosErr, ok := err.(*Error) 43 if rosErr == nil || !ok { 44 return false 45 } 46 // check that both *Error's are correctly initialized to avoid dereference panics 47 if rosErr.rosErr == nil || e.rosErr == nil { 48 return false 49 } 50 // messages are equal if their error codes match 51 return rosErr.rosErr.Code == e.rosErr.Code 52 } 53 54 // WrapError wraps the rosetta error with additional context 55 func WrapError(err *Error, msg string) *Error { 56 return &Error{rosErr: &types.Error{ 57 Code: err.rosErr.Code, 58 Message: err.rosErr.Message, 59 Description: err.rosErr.Description, 60 Retriable: err.rosErr.Retriable, 61 Details: map[string]interface{}{ 62 "info": msg, 63 }, 64 }} 65 } 66 67 // ToRosetta attempts to converting an error into a rosetta 68 // error, if the error cannot be converted it will be parsed as unknown 69 func ToRosetta(err error) *types.Error { 70 // if it's null or not known 71 rosErr, ok := err.(*Error) 72 if rosErr == nil || !ok { 73 return ToRosetta(WrapError(ErrUnknown, ErrUnknown.Error())) 74 } 75 return rosErr.rosErr 76 } 77 78 // FromGRPCToRosettaError converts a gRPC error to rosetta error 79 func FromGRPCToRosettaError(err error) *Error { 80 status, ok := grpcstatus.FromError(err) 81 if !ok { 82 return WrapError(ErrUnknown, err.Error()) 83 } 84 switch status.Code() { 85 case grpccodes.NotFound: 86 return WrapError(ErrNotFound, status.Message()) 87 case grpccodes.FailedPrecondition: 88 return WrapError(ErrBadArgument, status.Message()) 89 case grpccodes.InvalidArgument: 90 return WrapError(ErrBadArgument, status.Message()) 91 case grpccodes.Internal: 92 return WrapError(ErrInternal, status.Message()) 93 default: 94 return WrapError(ErrUnknown, status.Message()) 95 } 96 } 97 98 func RegisterError(code int32, message string, retryable bool, description string) *Error { 99 e := &Error{rosErr: &types.Error{ 100 Code: code, 101 Message: message, 102 Description: &description, 103 Retriable: retryable, 104 Details: nil, 105 }} 106 registry.add(e) 107 return e 108 } 109 110 // Default error list 111 var ( 112 // ErrUnknown defines an unknown error, if this is returned it means 113 // the library is ignoring an error 114 ErrUnknown = RegisterError(0, "unknown", false, "unknown error") 115 // ErrOffline is returned when there is an attempt to query an endpoint in offline mode 116 ErrOffline = RegisterError(1, "cannot query endpoint in offline mode", false, "returned when querying an online endpoint in offline mode") 117 // ErrNetworkNotSupported is returned when there is an attempt to query a network which is not supported 118 ErrNetworkNotSupported = RegisterError(2, "network is not supported", false, "returned when querying a non supported network") 119 // ErrCodec is returned when there's an error while marshalling or unmarshalling data 120 ErrCodec = RegisterError(3, "encode/decode error", true, "returned when there are errors encoding or decoding information to and from the node") 121 // ErrInvalidOperation is returned when the operation supplied to rosetta is not a valid one 122 ErrInvalidOperation = RegisterError(4, "invalid operation", false, "returned when the operation is not valid") 123 // ErrInvalidTransaction is returned when the provided hex bytes of a TX are not valid 124 ErrInvalidTransaction = RegisterError(5, "invalid transaction", false, "returned when the transaction is invalid") 125 // ErrInvalidAddress is returned when the byte of the address are bad 126 ErrInvalidAddress = RegisterError(7, "invalid address", false, "returned when the address is malformed") 127 // ErrInvalidPubkey is returned when the public key is invalid 128 ErrInvalidPubkey = RegisterError(8, "invalid pubkey", false, "returned when the public key is invalid") 129 // ErrInterpreting is returned when there are errors interpreting the data from the node, most likely related to breaking changes, version incompatibilities 130 ErrInterpreting = RegisterError(9, "error interpreting data from node", false, "returned when there are issues interpreting requests or response from node") 131 ErrInvalidMemo = RegisterError(11, "invalid memo", false, "returned when the memo is invalid") 132 // ErrBadArgument is returned when the request is malformed 133 ErrBadArgument = RegisterError(400, "bad argument", false, "request is malformed") 134 // ErrNotFound is returned when the required object was not found 135 // retry is set to true because something that is not found now 136 // might be found later, example: a TX 137 ErrNotFound = RegisterError(404, "not found", true, "returned when the node does not find what the client is asking for") 138 // ErrInternal is returned when the node is experiencing internal errors 139 ErrInternal = RegisterError(500, "internal error", false, "returned when the node experiences internal errors") 140 // ErrBadGateway is returned when there are problems interacting with the nodes 141 ErrBadGateway = RegisterError(502, "bad gateway", true, "return when the node is unreachable") 142 // ErrNotImplemented is returned when a method is not implemented yet 143 ErrNotImplemented = RegisterError(14, "not implemented", false, "returned when querying an endpoint which is not implemented") 144 // ErrUnsupportedCurve is returned when the curve specified is not supported 145 ErrUnsupportedCurve = RegisterError(15, "unsupported curve, expected secp256k1", false, "returned when using an unsupported crypto curve") 146 )