code.vegaprotocol.io/vega@v0.79.0/wallet/api/errors.go (about) 1 // Copyright (C) 2023 Gobalsky Labs Limited 2 // 3 // This program is free software: you can redistribute it and/or modify 4 // it under the terms of the GNU Affero General Public License as 5 // published by the Free Software Foundation, either version 3 of the 6 // License, or (at your option) any later version. 7 // 8 // This program is distributed in the hope that it will be useful, 9 // but WITHOUT ANY WARRANTY; without even the implied warranty of 10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 // GNU Affero General Public License for more details. 12 // 13 // You should have received a copy of the GNU Affero General Public License 14 // along with this program. If not, see <http://www.gnu.org/licenses/>. 15 16 package api 17 18 import ( 19 "context" 20 "errors" 21 "fmt" 22 23 "code.vegaprotocol.io/vega/libs/jsonrpc" 24 "code.vegaprotocol.io/vega/wallet/api/node/types" 25 ) 26 27 const ( 28 // Implementation-defined server-errors. 29 30 // ErrorCodeRequestHasBeenInterrupted refers to a request that has been 31 // interrupted by the server or the third-party application. It could 32 // originate from a timeout or an explicit cancellation. 33 ErrorCodeRequestHasBeenInterrupted jsonrpc.ErrorCode = -32001 34 35 // ErrorCodeHostnameResolutionFailure refers to the inability for the server 36 // to resolve the hostname from the request. 37 ErrorCodeHostnameResolutionFailure jsonrpc.ErrorCode = -32002 38 39 // ErrorCodeAuthenticationFailure refers to a request that have authentication 40 // problems. 41 ErrorCodeAuthenticationFailure jsonrpc.ErrorCode = -32003 42 43 // Network error codes are errors that comes from the network itself and its 44 // nodes. It ranges from 1000 to 1999, included. 45 // Apart from the communication failure, network errors are valued based on 46 // their ABCI code counter-part: 47 // Network_Error_Code == ABCI_Error_Code + 1000 48 49 // ErrorCodeNodeCommunicationFailed refers to the inability of the program to 50 // talk to the network nodes. 51 ErrorCodeNodeCommunicationFailed jsonrpc.ErrorCode = 1000 52 53 // ErrorCodeNetworkRejectedTransaction refers to a transaction rejected by 54 // the network nodes but for an unknown ABCI code. 55 ErrorCodeNetworkRejectedTransaction jsonrpc.ErrorCode = 1001 56 57 // ErrorCodeNetworkRejectedInvalidTransaction refers to a validation failure raised 58 // by the network nodes (error code 51). 59 ErrorCodeNetworkRejectedInvalidTransaction jsonrpc.ErrorCode = 1051 60 61 // ErrorCodeNetworkRejectedMalformedTransaction refers to the inability to 62 // decode a transaction from the network nodes (error code 60). 63 ErrorCodeNetworkRejectedMalformedTransaction jsonrpc.ErrorCode = 1060 64 65 // ErrorCodeNetworkCouldNotProcessTransaction refers to the inability to 66 // process a transaction from the network nodes (error code 70). 67 ErrorCodeNetworkCouldNotProcessTransaction jsonrpc.ErrorCode = 1070 68 69 // ErrorCodeNetworkRejectedUnsupportedTransaction is raised when the network 70 // nodes encounter an unsupported transaction (error code 80). 71 ErrorCodeNetworkRejectedUnsupportedTransaction jsonrpc.ErrorCode = 1080 72 73 // ErrorCodeNetworkSpamProtectionActivated is raised when the network 74 // nodes spin up the spam protection mechanism (error code 89). 75 ErrorCodeNetworkSpamProtectionActivated jsonrpc.ErrorCode = 1089 76 77 // Application error codes are programmatic errors that comes from the API 78 // itself and its "business" rules. It ranges from 2000 to 2999, included. 79 80 // ErrorCodeRequestNotPermitted refers a request made by a third-party application 81 // that is not permitted to do. This error is related to the permissions' 82 // system. 83 ErrorCodeRequestNotPermitted jsonrpc.ErrorCode = 2000 84 85 // ErrorCodeRequestHasBeenCancelledByApplication refers to an automated 86 // cancellation of a request by the application core. This happens when some 87 // requirements are missing to ensure correct handling of a request. 88 ErrorCodeRequestHasBeenCancelledByApplication jsonrpc.ErrorCode = 2001 89 90 // User error codes are errors that results from the user. It ranges 91 // from 3000 to 3999, included. 92 93 // ErrorCodeConnectionHasBeenClosed refers to an interruption of the service 94 // triggered by the user. 95 ErrorCodeConnectionHasBeenClosed jsonrpc.ErrorCode = 3000 96 97 // ErrorCodeRequestHasBeenRejected refers to an explicit rejection of a 98 // request by the user. When received, the third-party application should 99 // consider the user has withdrawn from the action, and thus, abort the 100 // action. 101 ErrorCodeRequestHasBeenRejected jsonrpc.ErrorCode = 3001 102 103 // ErrorCodeRequestHasBeenCancelledByUser refers to a cancellation of a 104 // request by the user. It's conceptually different from a rejection. 105 // Contrary to a rejection, when a cancellation is received, the third-party 106 // application should temporarily back off, maintain its state, and wait for 107 // the user to be ready to continue. 108 ErrorCodeRequestHasBeenCancelledByUser jsonrpc.ErrorCode = 3002 109 ) 110 111 var ( 112 ErrApplicationCancelledTheRequest = errors.New("the application cancelled the request") 113 ErrBlockHashIsRequired = errors.New("the block hash is required") 114 ErrBlockHeightIsRequired = errors.New("the block height is required") 115 ErrBlockHeightTooHistoric = errors.New("the block height is too historic") 116 ErrCannotRotateKeysOnIsolatedWallet = errors.New("cannot rotate keys on an isolated wallet") 117 ErrChainIDIsRequired = errors.New("the chain ID is required") 118 ErrConnectionClosed = errors.New("the connection has been closed") 119 ErrCouldNotCheckTransaction = errors.New("could not check transaction") 120 ErrCouldNotConnectToWallet = errors.New("could not connect to the wallet") 121 ErrCouldNotGetChainIDFromNode = errors.New("could not get the chain ID from the node") 122 ErrCouldNotGetLastBlockInformation = errors.New("could not get information about the last block on the network") 123 ErrCouldNotGetSpamStatistics = errors.New("could not get latest spam statistics for the public key on the network") 124 ErrCouldNotListKeys = errors.New("could not list the keys") 125 ErrCouldNotSendTransaction = errors.New("could not send transaction") 126 ErrCouldNotSignTransaction = errors.New("could not sign transaction") 127 ErrCurrentPublicKeyDoesNotExist = errors.New("the current public key does not exist") 128 ErrCurrentPublicKeyIsRequired = errors.New("the next public key is required") 129 ErrEnactmentBlockHeightIsRequired = errors.New("the enactment block height is required") 130 ErrEnactmentBlockHeightMustBeGreaterThanSubmissionOne = errors.New("the enactment block height must be greater than the submission one") 131 ErrEncodedMessageIsNotValidBase64String = errors.New("the encoded message is not a valid base-64 string") 132 ErrEncodedSignatureIsNotValidBase64String = errors.New("the encoded signature is not a valid base-64 string") 133 ErrEncodedTransactionIsNotValidBase64String = errors.New("the encoded transaction is not a valid base-64 string") 134 ErrEncodedTransactionIsRequired = errors.New("the encoded transaction is required") 135 ErrHostnameIsRequired = errors.New("the hostname is required") 136 ErrIsolatedWalletPassphraseIsRequired = errors.New("the isolated wallet passphrase is required") 137 ErrLastBlockDataOrNetworkIsRequired = errors.New("a network or the last block data is required") 138 ErrMessageIsRequired = errors.New("the message is required") 139 ErrNetworkAlreadyExists = errors.New("a network with the same name already exists") 140 ErrNetworkConfigurationDoesNotHaveGRPCNodes = errors.New("the network does not have gRPC hosts configured") 141 ErrNetworkDoesNotExist = errors.New("the network does not exist") 142 ErrNetworkIsRequired = errors.New("the network is required") 143 ErrNetworkNameIsRequired = errors.New("the network name is required") 144 ErrNetworkOrNodeAddressIsRequired = errors.New("a network or a node address is required") 145 ErrNetworkSourceIsRequired = errors.New("a network source is required") 146 ErrNewNameIsRequired = errors.New("the new name is required") 147 ErrNewPassphraseIsRequired = errors.New("the new passphrase is required") 148 ErrNextAndCurrentPublicKeysCannotBeTheSame = errors.New("the next and current public keys cannot be the same") 149 ErrNextPublicKeyDoesNotExist = errors.New("the next public key does not exist") 150 ErrNextPublicKeyIsRequired = errors.New("the next public key is required") 151 ErrNextPublicKeyIsTainted = errors.New("the next public key is tainted") 152 ErrNoHealthyNodeAvailable = errors.New("no healthy node available") 153 ErrNoWalletToConnectTo = errors.New("there is no wallet to connect to, you should, first, create or import a wallet") 154 ErrParamsDoNotMatch = errors.New("the params do not match expected ones") 155 ErrParamsRequired = errors.New("the params are required") 156 ErrPassphraseIsRequired = errors.New("the passphrase is required") 157 ErrProofOfWorkDifficultyRequired = errors.New("the proof-of-work difficulty is required") 158 ErrProofOfWorkHashFunctionRequired = errors.New("the proof-of-work hash function is required") 159 ErrPublicKeyDoesNotExist = errors.New("the public key does not exist") 160 ErrPublicKeyIsNotAllowedToBeUsed = errors.New("this public key is not allowed to be used") 161 ErrPublicKeyIsRequired = errors.New("the public key is required") 162 ErrRawTransactionIsNotValidVegaTransaction = errors.New("the raw transaction is not a valid Vega transaction") 163 ErrRecoveryPhraseIsRequired = errors.New("the recovery phrase is required") 164 ErrRequestCancelled = errors.New("the request has been cancelled") 165 ErrRequestInterrupted = errors.New("the request has been interrupted") 166 ErrSendingModeCannotBeTypeUnspecified = errors.New(`the sending mode can't be "TYPE_UNSPECIFIED"`) 167 ErrSendingModeIsRequired = errors.New("the sending mode is required") 168 ErrSignatureIsRequired = errors.New("the signature is required") 169 ErrSpecifyingNetworkAndLastBlockDataIsNotSupported = errors.New("specifying a network and the last block data is not supported") 170 ErrSpecifyingNetworkAndNodeAddressIsNotSupported = errors.New("specifying a network and a node address is not supported") 171 ErrSubmissionBlockHeightIsRequired = errors.New("the submission block height is required") 172 ErrTransactionIsNotValidJSON = errors.New("the transaction is not valid JSON") 173 ErrTransactionIsRequired = errors.New("the transaction is required") 174 ErrTransactionsPerBlockLimitReached = errors.New("the transaction per block limit has been reached") 175 ErrUserCancelledTheRequest = errors.New("the user cancelled the request") 176 ErrUserCloseTheConnection = errors.New("the user closed the connection") 177 ErrUserRejectedAccessToKeys = errors.New("the user rejected the access to the keys") 178 ErrUserRejectedCheckingOfTransaction = errors.New("the user rejected the checking of the transaction") 179 ErrUserRejectedSendingOfTransaction = errors.New("the user rejected the sending of the transaction") 180 ErrUserRejectedSigningOfTransaction = errors.New("the user rejected the signing of the transaction") 181 ErrUserRejectedWalletConnection = errors.New("the user rejected the wallet connection") 182 ErrWalletAlreadyExists = errors.New("a wallet with the same name already exists") 183 ErrWalletDoesNotExist = errors.New("the wallet does not exist") 184 ErrWalletIsLocked = errors.New("the wallet is locked") 185 ErrWalletIsRequired = errors.New("the wallet is required") 186 ErrWalletKeyDerivationVersionIsRequired = errors.New("the wallet key derivation version is required") 187 ) 188 189 func ApplicationError(code jsonrpc.ErrorCode, err error) *jsonrpc.ErrorDetails { 190 if code <= -32000 { 191 panic("application error code should be greater than -32000") 192 } 193 return jsonrpc.NewCustomError(code, "Application error", err) 194 } 195 196 func UserError(code jsonrpc.ErrorCode, err error) *jsonrpc.ErrorDetails { 197 if code <= -32000 { 198 panic("user error code should be greater than -32000") 199 } 200 return jsonrpc.NewCustomError(code, "User error", err) 201 } 202 203 func NetworkError(code jsonrpc.ErrorCode, err error) *jsonrpc.ErrorDetails { 204 return jsonrpc.NewCustomError(code, "Network error", err) 205 } 206 207 // NetworkErrorFromTransactionError returns an error with a generic message but 208 // a specialized code. This is intended to give a coarse-grained indication 209 // to the third-party application without taking any risk of leaking information 210 // from the error message. 211 func NetworkErrorFromTransactionError(err error) *jsonrpc.ErrorDetails { 212 txErr := types.TransactionError{} 213 isTxErr := errors.As(err, &txErr) 214 if !isTxErr { 215 return NetworkError(ErrorCodeNodeCommunicationFailed, fmt.Errorf("the transaction failed: %w", err)) 216 } 217 218 switch txErr.ABCICode { 219 case 51: 220 return NetworkError(ErrorCodeNetworkRejectedInvalidTransaction, fmt.Errorf("the network rejected the transaction because it's invalid: %w", err)) 221 case 60: 222 return NetworkError(ErrorCodeNetworkRejectedMalformedTransaction, fmt.Errorf("the network rejected the transaction because it's malformed: %w", err)) 223 case 70: 224 return NetworkError(ErrorCodeNetworkCouldNotProcessTransaction, fmt.Errorf("the network could not process the transaction: %w", err)) 225 case 80: 226 return NetworkError(ErrorCodeNetworkRejectedUnsupportedTransaction, fmt.Errorf("the network does not support this transaction: %w", err)) 227 case 89: 228 return NetworkError(ErrorCodeNetworkSpamProtectionActivated, fmt.Errorf("the network blocked the transaction through the spam protection: %w", err)) 229 default: 230 return NetworkError(ErrorCodeNetworkRejectedTransaction, fmt.Errorf("the transaction failed: %w", err)) 231 } 232 } 233 234 func NodeCommunicationError(err error) *jsonrpc.ErrorDetails { 235 return NetworkError(ErrorCodeNodeCommunicationFailed, err) 236 } 237 238 func InvalidParams(err error) *jsonrpc.ErrorDetails { 239 return jsonrpc.NewInvalidParams(err) 240 } 241 242 func RequestInterruptedError(err error) *jsonrpc.ErrorDetails { 243 return jsonrpc.NewServerError(ErrorCodeRequestHasBeenInterrupted, err) 244 } 245 246 func ConnectionClosedError(err error) *jsonrpc.ErrorDetails { 247 return UserError(ErrorCodeConnectionHasBeenClosed, err) 248 } 249 250 func UserCancellationError(err error) *jsonrpc.ErrorDetails { 251 return UserError(ErrorCodeRequestHasBeenCancelledByUser, err) 252 } 253 254 func UserRejectionError(err error) *jsonrpc.ErrorDetails { 255 return UserError(ErrorCodeRequestHasBeenRejected, err) 256 } 257 258 func RequestNotPermittedError(err error) *jsonrpc.ErrorDetails { 259 return ApplicationError(ErrorCodeRequestNotPermitted, err) 260 } 261 262 func ApplicationCancellationError(err error) *jsonrpc.ErrorDetails { 263 return ApplicationError(ErrorCodeRequestHasBeenCancelledByApplication, err) 264 } 265 266 func InternalError(err error) *jsonrpc.ErrorDetails { 267 return jsonrpc.NewInternalError(err) 268 } 269 270 // HandleRequestFlowError is a generic function that build the appropriate 271 // API error response based on the underlying error. 272 // If none of them matches, the error handling is delegating to the caller. 273 func HandleRequestFlowError(ctx context.Context, traceID string, interactor Interactor, err error) *jsonrpc.ErrorDetails { 274 if errors.Is(err, ErrUserCancelledTheRequest) { 275 // 1. Using a different error message to better fit the front-end needs. 276 // 2. Contrary to the response returned to the third-party application, 277 // we notify an ApplicationErrorType to the wallet front-end, so it knows 278 // it has to consider this error as a terminal one. 279 interactor.NotifyError(ctx, traceID, ApplicationErrorType, ErrRequestCancelled) 280 return UserCancellationError(err) 281 } 282 if errors.Is(err, ErrUserCloseTheConnection) { 283 // 1. Using a different error message to better fit the front-end needs. 284 // 2. Contrary to the response returned to the third-party application, 285 // we notify an ApplicationErrorType to the wallet front-end, so it knows 286 // it has to consider this error as a terminal one. 287 interactor.NotifyError(ctx, traceID, ApplicationErrorType, ErrConnectionClosed) 288 return ConnectionClosedError(err) 289 } 290 if errors.Is(err, ErrRequestInterrupted) { 291 interactor.NotifyError(ctx, traceID, ServerErrorType, err) 292 return RequestInterruptedError(err) 293 } 294 return nil 295 }