-
Notifications
You must be signed in to change notification settings - Fork 28
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #479 from NomicFoundation/centralized-errors
Centralize error descriptions
- Loading branch information
Showing
43 changed files
with
827 additions
and
310 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,322 @@ | ||
export const ERROR_PREFIX = "IGN"; | ||
|
||
/** | ||
* ErrorDescriptor is a type that describes an error. | ||
* It's used to generate error codes and messages. | ||
* | ||
* @beta | ||
*/ | ||
export interface ErrorDescriptor { | ||
number: number; | ||
// Message can use templates. See applyErrorMessageTemplate | ||
message: string; | ||
} | ||
|
||
export function getErrorCode(error: ErrorDescriptor): string { | ||
return `${ERROR_PREFIX}${error.number}`; | ||
} | ||
|
||
export const ERROR_RANGES: { | ||
[category in keyof typeof ERRORS]: { | ||
min: number; | ||
max: number; | ||
title: string; | ||
}; | ||
} = { | ||
GENERAL: { | ||
min: 1, | ||
max: 99, | ||
title: "General errors", | ||
}, | ||
INTERNAL: { | ||
min: 100, | ||
max: 199, | ||
title: "Internal Ignition errors", | ||
}, | ||
MODULE: { | ||
min: 200, | ||
max: 299, | ||
title: "Module related errors", | ||
}, | ||
SERIALIZATION: { | ||
min: 300, | ||
max: 399, | ||
title: "Serialization errors", | ||
}, | ||
EXECUTION: { | ||
min: 400, | ||
max: 499, | ||
title: "Execution errors", | ||
}, | ||
RECONCILIATION: { | ||
min: 500, | ||
max: 599, | ||
title: "Reconciliation errors", | ||
}, | ||
WIPE: { | ||
min: 600, | ||
max: 699, | ||
title: "Wipe errors", | ||
}, | ||
VALIDATION: { | ||
min: 700, | ||
max: 799, | ||
title: "Validation errors", | ||
}, | ||
}; | ||
|
||
export const ERRORS = { | ||
GENERAL: { | ||
ASSERTION_ERROR: { | ||
number: 1, | ||
message: "Internal Ignition invariant was violated: %description%", | ||
}, | ||
UNSUPPORTED_DECODE: { | ||
number: 2, | ||
message: "Ignition can't decode ethers.js value of type %type%: %value%", | ||
}, | ||
}, | ||
INTERNAL: { | ||
TEMPLATE_INVALID_VARIABLE_NAME: { | ||
number: 100, | ||
message: | ||
"Variable names can only include ascii letters and numbers, and start with a letter, but got %variable%", | ||
}, | ||
TEMPLATE_VARIABLE_NOT_FOUND: { | ||
number: 101, | ||
message: "Variable %variable%'s tag not present in the template", | ||
}, | ||
TEMPLATE_VALUE_CONTAINS_VARIABLE_TAG: { | ||
number: 102, | ||
message: | ||
"Template values can't include variable tags, but %variable%'s value includes one", | ||
}, | ||
}, | ||
MODULE: { | ||
INVALID_MODULE_ID: { | ||
number: 200, | ||
message: "Module id must be a string", | ||
}, | ||
INVALID_MODULE_ID_CHARACTERS: { | ||
number: 201, | ||
message: | ||
'The moduleId "%moduleId%" contains banned characters, ids can only contain alphanumerics or underscores', | ||
}, | ||
INVALID_MODULE_DEFINITION_FUNCTION: { | ||
number: 202, | ||
message: "Module definition function must be a function", | ||
}, | ||
ASYNC_MODULE_DEFINITION_FUNCTION: { | ||
number: 203, | ||
message: | ||
"The callback passed to 'buildModule' for %moduleDefinitionId% returns a Promise; async callbacks are not allowed in 'buildModule'.", | ||
}, | ||
}, | ||
SERIALIZATION: { | ||
INVALID_FUTURE_ID: { | ||
number: 300, | ||
message: "Unable to lookup future during deserialization: %futureId%", | ||
}, | ||
INVALID_FUTURE_TYPE: { | ||
number: 301, | ||
message: "Invalid FutureType %type% as serialized argument", | ||
}, | ||
LOOKAHEAD_NOT_FOUND: { | ||
number: 302, | ||
message: "Lookahead value %key% missing", | ||
}, | ||
}, | ||
EXECUTION: { | ||
FUTURE_NOT_FOUND: { | ||
number: 400, | ||
message: "Could not locate future id from batching", | ||
}, | ||
DROPPED_TRANSACTION: { | ||
number: 401, | ||
message: | ||
"Error while executing %futureId%: all the transactions of its network interaction %networkInteractionId% were dropped. Please try rerunning Ignition.", | ||
}, | ||
INVALID_JSON_RPC_RESPONSE: { | ||
number: 402, | ||
message: "Invalid JSON-RPC response for %method%: %response%", | ||
}, | ||
WAITING_FOR_CONFIRMATIONS: { | ||
number: 403, | ||
message: | ||
"You have sent transactions from %sender%. Please wait until they get %requiredConfirmations% confirmations before running Ignition again.", | ||
}, | ||
WAITING_FOR_NONCE: { | ||
number: 404, | ||
message: | ||
"You have sent transactions from %sender% with nonce %nonce%. Please wait until they get %requiredConfirmations% confirmations before running Ignition again.", | ||
}, | ||
INVALID_NONCE: { | ||
number: 405, | ||
message: | ||
"The next nonce for %sender% should be %expectedNonce%, but is %pendingCount%. Please make sure not to send transactions from %sender% while running this deployment and try again.", | ||
}, | ||
}, | ||
RECONCILIATION: { | ||
INVALID_EXECUTION_STATUS: { | ||
number: 500, | ||
message: "Unsupported execution status: %status%", | ||
}, | ||
}, | ||
WIPE: { | ||
UNINITIALIZED_DEPLOYMENT: { | ||
number: 600, | ||
message: | ||
"Cannot wipe %futureId% as the deployment hasn't been intialialized yet", | ||
}, | ||
NO_STATE_FOR_FUTURE: { | ||
number: 601, | ||
message: "Cannot wipe %futureId% as no state recorded against it", | ||
}, | ||
DEPENDENT_FUTURES: { | ||
number: 602, | ||
message: `Cannot wipe %futureId% as there are dependent futures that have already started: %dependents%`, | ||
}, | ||
}, | ||
VALIDATION: { | ||
INVALID_DEFAULT_SENDER: { | ||
number: 700, | ||
message: | ||
"Default sender %defaultSender% is not part of the provided accounts", | ||
}, | ||
MISSING_EMITTER: { | ||
number: 701, | ||
message: | ||
"`options.emitter` must be provided when reading an event from a SendDataFuture", | ||
}, | ||
INVALID_MODULE: { | ||
number: 702, | ||
message: "Module validation failed with reason: %message%", | ||
}, | ||
INVALID_CONSTRUCTOR_ARGS_LENGTH: { | ||
number: 703, | ||
message: | ||
"The constructor of the contract '%contractName%' expects %expectedArgsLength% arguments but %argsLength% were given", | ||
}, | ||
INVALID_FUNCTION_ARGS_LENGTH: { | ||
number: 704, | ||
message: | ||
"Function %functionName% in contract %contractName% expects %expectedLength% arguments but %argsLength% were given", | ||
}, | ||
INVALID_STATIC_CALL: { | ||
number: 705, | ||
message: | ||
"Function %functionName% in contract %contractName% is not 'pure' or 'view' and cannot be statically called", | ||
}, | ||
INDEXED_EVENT_ARG: { | ||
number: 706, | ||
message: | ||
"Indexed argument %argument% of event %eventName% of contract %contractName% is not stored in the receipt, but its hash is, so you can't read it.", | ||
}, | ||
INVALID_OVERLOAD_NAME: { | ||
number: 707, | ||
message: "Invalid %eventOrFunction% name '%name%'", | ||
}, | ||
OVERLOAD_NOT_FOUND: { | ||
number: 708, | ||
message: | ||
"%eventOrFunction% '%name%' not found in contract %contractName%", | ||
}, | ||
REQUIRE_BARE_NAME: { | ||
number: 709, | ||
message: | ||
"%eventOrFunction% name '%name%' used for contract %contractName%, but it's not overloaded. Use '%bareName%' instead.", | ||
}, | ||
OVERLOAD_NAME_REQUIRED: { | ||
number: 710, | ||
message: `%eventOrFunction% '%name%' is overloaded in contract %contractName%. Please use one of these names instead: | ||
%normalizedNameList%`, | ||
}, | ||
INVALID_OVERLOAD_GIVEN: { | ||
number: 711, | ||
message: `%eventOrFunction% '%name%' is not a valid overload of '%bareName%' in contract %contractName%. Please use one of these names instead: | ||
%normalizedNameList%`, | ||
}, | ||
EVENT_ARG_NOT_FOUND: { | ||
number: 712, | ||
message: | ||
"Event %eventName% of contract %contractName% has no argument named %argument%", | ||
}, | ||
INVALID_EVENT_ARG_INDEX: { | ||
number: 713, | ||
message: | ||
"Event %eventName% of contract %contractName% has only %expectedLength% arguments, but argument %argument% was requested", | ||
}, | ||
FUNCTION_ARG_NOT_FOUND: { | ||
number: 714, | ||
message: | ||
"Function %functionName% of contract %contractName% has no return value named %argument%", | ||
}, | ||
INVALID_FUNCTION_ARG_INDEX: { | ||
number: 715, | ||
message: | ||
"Function %functionName% of contract %contractName% has only %expectedLength% return values, but value %argument% was requested", | ||
}, | ||
MISSING_LIBRARIES: { | ||
number: 716, | ||
message: | ||
"Invalid libraries for contract %contractName%: The following libraries are missing: %fullyQualifiedNames%", | ||
}, | ||
CONFLICTING_LIBRARY_NAMES: { | ||
number: 717, | ||
message: | ||
"Invalid libraries for contract %contractName%: The names '%inputName%' and '%libName%' clash with each other, please use qualified names for both.", | ||
}, | ||
INVALID_LIBRARY_NAME: { | ||
number: 718, | ||
message: "Invalid library name %libraryName% for contract %contractName%", | ||
}, | ||
LIBRARY_NOT_NEEDED: { | ||
number: 719, | ||
message: | ||
"Invalid library %libraryName% for contract %contractName%: this library is not needed by this contract.", | ||
}, | ||
AMBIGUOUS_LIBRARY_NAME: { | ||
number: 720, | ||
message: `Invalid libraries for contract %contractName%: The name "%libraryName%" is ambiguous, please use one of the following fully qualified names: %fullyQualifiedNames%`, | ||
}, | ||
INVALID_LIBRARY_ADDRESS: { | ||
number: 721, | ||
message: `Invalid address %address% for library %libraryName% of contract %contractName%`, | ||
}, | ||
NEGATIVE_ACCOUNT_INDEX: { | ||
number: 722, | ||
message: "Account index cannot be a negative number", | ||
}, | ||
ACCOUNT_INDEX_TOO_HIGH: { | ||
number: 723, | ||
message: | ||
"Requested account index '%accountIndex%' is greater than the total number of available accounts '%accountsLength%'", | ||
}, | ||
INVALID_ARTIFACT: { | ||
number: 724, | ||
message: "Artifact for contract '%contractName%' is invalid", | ||
}, | ||
MISSING_MODULE_PARAMETER: { | ||
number: 725, | ||
message: "Module parameter '%name%' requires a value but was given none", | ||
}, | ||
INVALID_MODULE_PARAMETER_TYPE: { | ||
number: 726, | ||
message: `Module parameter '%name%' must be of type '%expectedType%' but is '%actualType%'`, | ||
}, | ||
}, | ||
}; | ||
|
||
/** | ||
* Setting the type of ERRORS to a map let us access undefined ones. Letting it | ||
* be a literal doesn't enforce that its values are of type ErrorDescriptor. | ||
* | ||
* We let it be a literal, and use this variable to enforce the types | ||
*/ | ||
const _PHONY_VARIABLE_TO_FORCE_ERRORS_TO_BE_OF_TYPE_ERROR_DESCRIPTOR: { | ||
[category: string]: { | ||
[name: string]: ErrorDescriptor; | ||
}; | ||
} = ERRORS; |
Oops, something went wrong.