2019-05-14 18:48:48 -04:00
"use strict" ;
//import { version } from "./_version";
2019-08-25 02:39:20 -04:00
const version = "@TODO" ;
2019-05-14 18:48:48 -04:00
///////////////////
// Generic Errors
// Unknown Error
2019-08-25 02:39:20 -04:00
export const UNKNOWN _ERROR = "UNKNOWN_ERROR" ;
2019-05-14 18:48:48 -04:00
// Not Implemented
2019-08-25 02:39:20 -04:00
export const NOT _IMPLEMENTED = "NOT_IMPLEMENTED" ;
2019-05-14 18:48:48 -04:00
// Unsupported Operation
// - operation
2019-08-25 02:39:20 -04:00
export const UNSUPPORTED _OPERATION = "UNSUPPORTED_OPERATION" ;
2019-06-12 01:01:04 -04:00
// Network Error (i.e. Ethereum Network, such as an invalid chain ID)
2019-08-25 02:39:20 -04:00
export const NETWORK _ERROR = "NETWORK_ERROR" ;
2019-06-12 01:01:04 -04:00
// Some sort of bad response from the server
2019-08-25 02:39:20 -04:00
export const SERVER _ERROR = "SERVER_ERROR" ;
2019-06-12 01:01:04 -04:00
// Timeout
2019-08-25 02:39:20 -04:00
export const TIMEOUT = "TIMEOUT" ;
2019-05-14 18:48:48 -04:00
///////////////////
// Operational Errors
// Buffer Overrun
2019-08-25 02:39:20 -04:00
export const BUFFER _OVERRUN = "BUFFER_OVERRUN" ;
2019-05-14 18:48:48 -04:00
// Numeric Fault
// - operation: the operation being executed
// - fault: the reason this faulted
2019-08-25 02:39:20 -04:00
export const NUMERIC _FAULT = "NUMERIC_FAULT" ;
2019-05-14 18:48:48 -04:00
///////////////////
// Argument Errors
// Missing new operator to an object
// - name: The name of the class
2019-08-25 02:39:20 -04:00
export const MISSING _NEW = "MISSING_NEW" ;
2019-05-14 18:48:48 -04:00
// Invalid argument (e.g. value is incompatible with type) to a function:
// - argument: The argument name that was invalid
// - value: The value of the argument
2019-08-25 02:39:20 -04:00
export const INVALID _ARGUMENT = "INVALID_ARGUMENT" ;
2019-05-14 18:48:48 -04:00
// Missing argument to a function:
// - count: The number of arguments received
// - expectedCount: The number of arguments expected
2019-08-25 02:39:20 -04:00
export const MISSING _ARGUMENT = "MISSING_ARGUMENT" ;
2019-05-14 18:48:48 -04:00
// Too many arguments
// - count: The number of arguments received
// - expectedCount: The number of arguments expected
2019-08-25 02:39:20 -04:00
export const UNEXPECTED _ARGUMENT = "UNEXPECTED_ARGUMENT" ;
2019-05-14 18:48:48 -04:00
///////////////////
// Blockchain Errors
// Call exception
// - transaction: the transaction
// - address?: the contract address
// - args?: The arguments passed into the function
// - method?: The Solidity method signature
// - errorSignature?: The EIP848 error signature
// - errorArgs?: The EIP848 error parameters
// - reason: The reason (only for EIP848 "Error(string)")
2019-08-25 02:39:20 -04:00
export const CALL _EXCEPTION = "CALL_EXCEPTION" ;
2019-05-14 18:48:48 -04:00
// Insufficien funds (< value + gasLimit * gasPrice)
// - transaction: the transaction attempted
2019-08-25 02:39:20 -04:00
export const INSUFFICIENT _FUNDS = "INSUFFICIENT_FUNDS" ;
2019-05-14 18:48:48 -04:00
// Nonce has already been used
// - transaction: the transaction attempted
2019-08-25 02:39:20 -04:00
export const NONCE _EXPIRED = "NONCE_EXPIRED" ;
2019-05-14 18:48:48 -04:00
// The replacement fee for the transaction is too low
// - transaction: the transaction attempted
2019-08-25 02:39:20 -04:00
export const REPLACEMENT _UNDERPRICED = "REPLACEMENT_UNDERPRICED" ;
2019-05-14 18:48:48 -04:00
// The gas limit could not be estimated
// - transaction: the transaction passed to estimateGas
2019-08-25 02:39:20 -04:00
export const UNPREDICTABLE _GAS _LIMIT = "UNPREDICTABLE_GAS_LIMIT" ;
2019-05-14 18:48:48 -04:00
//export const errors: { [ code: string ]: string } = {
//};
///////////////////
// Censorship
2019-08-25 02:39:20 -04:00
let _permanentCensorErrors = false ;
let _censorErrors = false ;
export function setCensorship ( censorship , permanent ) {
2019-05-14 18:48:48 -04:00
if ( _permanentCensorErrors ) {
2019-08-25 02:39:20 -04:00
throwError ( "error censorship permanent" , UNSUPPORTED _OPERATION , { operation : "setCensorship" } ) ;
2019-05-14 18:48:48 -04:00
}
_censorErrors = ! ! censorship ;
_permanentCensorErrors = ! ! permanent ;
}
///////////////////
// Errors
2019-08-25 02:39:20 -04:00
export function makeError ( message , code , params ) {
2019-05-14 18:48:48 -04:00
if ( _censorErrors ) {
return new Error ( "unknown error" ) ;
}
if ( ! code ) {
2019-08-25 02:39:20 -04:00
code = UNKNOWN _ERROR ;
2019-05-14 18:48:48 -04:00
}
if ( ! params ) {
params = { } ;
}
2019-08-25 02:39:20 -04:00
let messageDetails = [ ] ;
Object . keys ( params ) . forEach ( ( key ) => {
2019-05-14 18:48:48 -04:00
try {
messageDetails . push ( key + "=" + JSON . stringify ( params [ key ] ) ) ;
}
catch ( error ) {
messageDetails . push ( key + "=" + JSON . stringify ( params [ key ] . toString ( ) ) ) ;
}
} ) ;
messageDetails . push ( "version=" + version ) ;
2019-08-25 02:39:20 -04:00
let reason = message ;
2019-05-14 18:48:48 -04:00
if ( messageDetails . length ) {
message += " (" + messageDetails . join ( ", " ) + ")" ;
}
// @TODO: Any??
2019-08-25 02:39:20 -04:00
let error = new Error ( message ) ;
2019-05-14 18:48:48 -04:00
error . reason = reason ;
error . code = code ;
Object . keys ( params ) . forEach ( function ( key ) {
error [ key ] = params [ key ] ;
} ) ;
return error ;
}
// @TODO: Enum
2019-08-25 02:39:20 -04:00
export function throwError ( message , code , params ) {
2019-05-14 18:48:48 -04:00
throw makeError ( message , code , params ) ;
}
2019-08-25 02:39:20 -04:00
export function throwArgumentError ( message , name , value ) {
return throwError ( message , INVALID _ARGUMENT , {
2019-05-14 18:48:48 -04:00
argument : name ,
value : value
} ) ;
}
///////////////////
// Checking
2019-08-25 02:39:20 -04:00
export function checkArgumentCount ( count , expectedCount , suffix ) {
2019-05-14 18:48:48 -04:00
if ( suffix ) {
suffix = " " + suffix ;
}
else {
suffix = "" ;
}
if ( count < expectedCount ) {
2019-08-25 02:39:20 -04:00
throwError ( "missing argument" + suffix , MISSING _ARGUMENT , { count : count , expectedCount : expectedCount } ) ;
2019-05-14 18:48:48 -04:00
}
if ( count > expectedCount ) {
2019-08-25 02:39:20 -04:00
throwError ( "too many arguments" + suffix , UNEXPECTED _ARGUMENT , { count : count , expectedCount : expectedCount } ) ;
2019-05-14 18:48:48 -04:00
}
}
2019-08-25 02:39:20 -04:00
export function checkNew ( target , kind ) {
2019-05-14 18:48:48 -04:00
if ( target === Object || target == null ) {
2019-08-25 02:39:20 -04:00
throwError ( "missing new" , MISSING _NEW , { name : kind . name } ) ;
2019-05-14 18:48:48 -04:00
}
}
/ *
export function check ( target : any : void {
if ( target === Object || target == null ) {
throwError ( "missing new" , MISSING _NEW , { name : kind . name } ) ;
}
}
* /
2019-08-25 02:39:20 -04:00
export function checkAbstract ( target , kind ) {
2019-05-14 18:48:48 -04:00
if ( target === kind ) {
2019-08-25 02:39:20 -04:00
throwError ( "cannot instantiate abstract class " + JSON . stringify ( kind . name ) + " directly; use a sub-class" , UNSUPPORTED _OPERATION , { name : target . name , operation : "new" } ) ;
2019-05-14 18:48:48 -04:00
}
else if ( target === Object || target == null ) {
2019-08-25 02:39:20 -04:00
throwError ( "missing new" , MISSING _NEW , { name : kind . name } ) ;
2019-05-14 18:48:48 -04:00
}
}
/ *
export function checkTarget ( target : any , kind : any ) : void {
if ( target == null ) {
throwError ( "missing new" , MISSING _NEW , { name : kind . name } ) ;
}
}
* /
function _checkNormalize ( ) {
try {
2019-08-25 02:39:20 -04:00
let missing = [ ] ;
2019-05-14 18:48:48 -04:00
// Make sure all forms of normalization are supported
2019-08-25 02:39:20 -04:00
[ "NFD" , "NFC" , "NFKD" , "NFKC" ] . forEach ( ( form ) => {
2019-05-14 18:48:48 -04:00
try {
"test" . normalize ( form ) ;
}
catch ( error ) {
2019-08-25 02:39:20 -04:00
missing . push ( form ) ;
2019-05-14 18:48:48 -04:00
}
} ) ;
2019-08-25 02:39:20 -04:00
if ( missing . length ) {
throw new Error ( "missing " + missing . join ( ", " ) ) ;
2019-05-14 18:48:48 -04:00
}
if ( String . fromCharCode ( 0xe9 ) . normalize ( "NFD" ) !== String . fromCharCode ( 0x65 , 0x0301 ) ) {
throw new Error ( "broken implementation" ) ;
}
}
catch ( error ) {
return error . message ;
}
return null ;
}
2019-08-25 02:39:20 -04:00
let _normalizeError = _checkNormalize ( ) ;
export function checkNormalize ( ) {
2019-05-14 18:48:48 -04:00
if ( _normalizeError ) {
2019-08-25 02:39:20 -04:00
throwError ( "platform missing String.prototype.normalize" , UNSUPPORTED _OPERATION , {
2019-05-14 18:48:48 -04:00
operation : "String.prototype.normalize" , form : _normalizeError
} ) ;
}
}
2019-08-25 02:39:20 -04:00
export function checkSafeUint53 ( value , message ) {
2019-05-14 18:48:48 -04:00
if ( typeof ( value ) !== "number" ) {
return ;
}
if ( message == null ) {
message = "value not safe" ;
}
if ( value < 0 || value >= 0x1fffffffffffff ) {
2019-08-25 02:39:20 -04:00
throwError ( message , NUMERIC _FAULT , {
2019-05-14 18:48:48 -04:00
operation : "checkSafeInteger" ,
fault : "out-of-safe-range" ,
value : value
} ) ;
}
if ( value % 1 ) {
2019-08-25 02:39:20 -04:00
throwError ( message , NUMERIC _FAULT , {
2019-05-14 18:48:48 -04:00
operation : "checkSafeInteger" ,
fault : "non-integer" ,
value : value
} ) ;
}
}
///////////////////
// Logging
2019-08-25 02:39:20 -04:00
const LogLevels = { debug : 1 , "default" : 2 , info : 2 , warn : 3 , error : 4 , off : 5 } ;
let LogLevel = LogLevels [ "default" ] ;
export function setLogLevel ( logLevel ) {
let level = LogLevels [ logLevel ] ;
2019-05-14 18:48:48 -04:00
if ( level == null ) {
2020-04-23 23:35:39 -04:00
warn ( "invalid log level - " + logLevel ) ;
2019-05-14 18:48:48 -04:00
return ;
}
LogLevel = level ;
}
function log ( logLevel , args ) {
if ( LogLevel > LogLevels [ logLevel ] ) {
return ;
}
console . log . apply ( console , args ) ;
}
2019-08-25 02:39:20 -04:00
export function warn ( ... args ) {
2019-05-14 18:48:48 -04:00
log ( "warn" , args ) ;
}
2019-08-25 02:39:20 -04:00
export function info ( ... args ) {
2019-05-14 18:48:48 -04:00
log ( "info" , args ) ;
}