2018-06-13 22:39:39 +03:00
|
|
|
'use strict';
|
|
|
|
|
2018-10-04 05:50:22 +03:00
|
|
|
import { version } from './_version';
|
|
|
|
|
2018-06-13 22:39:39 +03:00
|
|
|
// Unknown Error
|
|
|
|
export const UNKNOWN_ERROR = 'UNKNOWN_ERROR';
|
|
|
|
|
|
|
|
// Not implemented
|
|
|
|
export const NOT_IMPLEMENTED = 'NOT_IMPLEMENTED';
|
|
|
|
|
|
|
|
// Missing new operator to an object
|
|
|
|
// - name: The name of the class
|
|
|
|
export const MISSING_NEW = 'MISSING_NEW';
|
|
|
|
|
|
|
|
// Call exception
|
2018-06-25 01:41:28 +03:00
|
|
|
// - 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)")
|
2018-06-13 22:39:39 +03:00
|
|
|
export const CALL_EXCEPTION = 'CALL_EXCEPTION';
|
|
|
|
|
2018-06-25 01:41:28 +03:00
|
|
|
// Invalid argument (e.g. value is incompatible with type) to a function:
|
2018-12-13 00:31:23 +03:00
|
|
|
// - argument: The argument name that was invalid
|
2018-06-13 22:39:39 +03:00
|
|
|
// - value: The value of the argument
|
|
|
|
export const INVALID_ARGUMENT = 'INVALID_ARGUMENT';
|
|
|
|
|
|
|
|
// Missing argument to a function:
|
|
|
|
// - count: The number of arguments received
|
|
|
|
// - expectedCount: The number of arguments expected
|
|
|
|
export const MISSING_ARGUMENT = 'MISSING_ARGUMENT';
|
|
|
|
|
|
|
|
// Too many arguments
|
|
|
|
// - count: The number of arguments received
|
|
|
|
// - expectedCount: The number of arguments expected
|
|
|
|
export const UNEXPECTED_ARGUMENT = 'UNEXPECTED_ARGUMENT';
|
|
|
|
|
|
|
|
// Numeric Fault
|
|
|
|
// - operation: the operation being executed
|
|
|
|
// - fault: the reason this faulted
|
|
|
|
export const NUMERIC_FAULT = 'NUMERIC_FAULT';
|
|
|
|
|
2018-08-02 00:02:27 +03:00
|
|
|
// Insufficien funds (< value + gasLimit * gasPrice)
|
|
|
|
// - transaction: the transaction attempted
|
|
|
|
export const INSUFFICIENT_FUNDS = 'INSUFFICIENT_FUNDS';
|
|
|
|
|
|
|
|
// Nonce has already been used
|
|
|
|
// - transaction: the transaction attempted
|
|
|
|
export const NONCE_EXPIRED = 'NONCE_EXPIRED';
|
|
|
|
|
|
|
|
// The replacement fee for the transaction is too low
|
|
|
|
// - transaction: the transaction attempted
|
|
|
|
export const REPLACEMENT_UNDERPRICED = 'REPLACEMENT_UNDERPRICED';
|
2018-06-13 22:39:39 +03:00
|
|
|
|
|
|
|
// Unsupported operation
|
|
|
|
// - operation
|
|
|
|
export const UNSUPPORTED_OPERATION = 'UNSUPPORTED_OPERATION';
|
|
|
|
|
2018-06-25 01:41:28 +03:00
|
|
|
let _permanentCensorErrors = false;
|
|
|
|
let _censorErrors = false;
|
|
|
|
|
|
|
|
|
2018-06-13 22:39:39 +03:00
|
|
|
// @TODO: Enum
|
|
|
|
export function throwError(message: string, code: string, params: any): never {
|
2018-06-25 01:41:28 +03:00
|
|
|
if (_censorErrors) {
|
|
|
|
throw new Error('unknown error');
|
|
|
|
}
|
|
|
|
|
2018-06-13 22:39:39 +03:00
|
|
|
if (!code) { code = UNKNOWN_ERROR; }
|
|
|
|
if (!params) { params = {}; }
|
|
|
|
|
2018-10-04 05:50:22 +03:00
|
|
|
let messageDetails: Array<string> = [];
|
|
|
|
Object.keys(params).forEach((key) => {
|
2018-06-13 22:39:39 +03:00
|
|
|
try {
|
|
|
|
messageDetails.push(key + '=' + JSON.stringify(params[key]));
|
|
|
|
} catch (error) {
|
|
|
|
messageDetails.push(key + '=' + JSON.stringify(params[key].toString()));
|
|
|
|
}
|
|
|
|
});
|
2018-10-04 05:50:22 +03:00
|
|
|
messageDetails.push("version=" + version);
|
|
|
|
|
|
|
|
let reason = message;
|
2018-06-13 22:39:39 +03:00
|
|
|
if (messageDetails.length) {
|
|
|
|
message += ' (' + messageDetails.join(', ') + ')';
|
|
|
|
}
|
|
|
|
|
2018-06-25 01:41:28 +03:00
|
|
|
// @TODO: Any??
|
2018-10-04 05:50:22 +03:00
|
|
|
let error: any = new Error(message);
|
2018-06-13 22:39:39 +03:00
|
|
|
error.reason = reason;
|
|
|
|
error.code = code
|
|
|
|
|
|
|
|
Object.keys(params).forEach(function(key) {
|
|
|
|
error[key] = params[key];
|
|
|
|
});
|
|
|
|
|
|
|
|
throw error;
|
|
|
|
}
|
|
|
|
|
|
|
|
export function checkNew(self: any, kind: any): void {
|
|
|
|
if (!(self instanceof kind)) {
|
|
|
|
throwError('missing new', MISSING_NEW, { name: kind.name });
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-06-25 01:41:28 +03:00
|
|
|
export function checkArgumentCount(count: number, expectedCount: number, suffix?: string): void {
|
|
|
|
if (!suffix) { suffix = ''; }
|
|
|
|
if (count < expectedCount) {
|
|
|
|
throwError('missing argument' + suffix, MISSING_ARGUMENT, { count: count, expectedCount: expectedCount });
|
|
|
|
}
|
|
|
|
if (count > expectedCount) {
|
|
|
|
throwError('too many arguments' + suffix, UNEXPECTED_ARGUMENT, { count: count, expectedCount: expectedCount });
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
export function setCensorship(censorship: boolean, permanent?: boolean): void {
|
|
|
|
if (_permanentCensorErrors) {
|
2018-12-13 00:31:23 +03:00
|
|
|
throwError('error censorship permanent', UNSUPPORTED_OPERATION, { operation: 'setCensorship' });
|
2018-06-25 01:41:28 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
_censorErrors = !!censorship;
|
|
|
|
_permanentCensorErrors = !!permanent;
|
|
|
|
}
|
2018-11-09 22:34:14 +03:00
|
|
|
|
|
|
|
export function checkNormalize(): void {
|
|
|
|
try {
|
2018-11-27 23:59:14 +03:00
|
|
|
// Make sure all forms of normalization are supported
|
|
|
|
["NFD", "NFC", "NFKD", "NFKC"].forEach((form) => {
|
|
|
|
try {
|
|
|
|
"test".normalize(form);
|
|
|
|
} catch(error) {
|
|
|
|
throw new Error('missing ' + form);
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
2018-11-09 22:34:14 +03:00
|
|
|
if (String.fromCharCode(0xe9).normalize('NFD') !== String.fromCharCode(0x65, 0x0301)) {
|
2018-11-27 23:59:14 +03:00
|
|
|
throw new Error('broken implementation')
|
2018-11-09 22:34:14 +03:00
|
|
|
}
|
|
|
|
} catch (error) {
|
2018-11-27 23:59:14 +03:00
|
|
|
throwError('platform missing String.prototype.normalize', UNSUPPORTED_OPERATION, { operation: 'String.prototype.normalize', form: error.message });
|
2018-11-09 22:34:14 +03:00
|
|
|
}
|
|
|
|
}
|
2018-12-27 23:48:38 +03:00
|
|
|
|
|
|
|
const LogLevels: { [ name: string ]: number } = { debug: 1, "default": 2, info: 2, warn: 3, error: 4, off: 5 };
|
|
|
|
let LogLevel = LogLevels["default"];
|
|
|
|
|
|
|
|
export function setLogLevel(logLevel: string): void {
|
|
|
|
let level = LogLevels[logLevel];
|
|
|
|
if (level == null) {
|
|
|
|
warn("invliad log level - " + logLevel);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
LogLevel = level;
|
|
|
|
}
|
|
|
|
|
|
|
|
function log(logLevel: string, args: Array<any>): void {
|
|
|
|
if (LogLevel > LogLevels[logLevel]) { return; }
|
|
|
|
console.log.apply(console, args);
|
|
|
|
}
|
|
|
|
|
|
|
|
export function warn(...args: Array<any>): void {
|
|
|
|
log("warn", args);
|
|
|
|
}
|
|
|
|
|
|
|
|
export function info(...args: Array<any>): void {
|
|
|
|
log("info", args);
|
|
|
|
}
|