ipfs storage for images and other nontext items. for use with etica - runs on etica network and currencys
https://collect.etica-stats.org
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
232 lines
7.4 KiB
232 lines
7.4 KiB
/** |
|
* All errors in ethers include properties to ensure they are both |
|
* human-readable (i.e. ``.message``) and machine-readable (i.e. ``.code``). |
|
* |
|
* The [[isError]] function can be used to check the error ``code`` and |
|
* provide a type guard for the properties present on that error interface. |
|
* |
|
* @_section: api/utils/errors:Errors [about-errors] |
|
*/ |
|
import { version } from "../_version.js"; |
|
import { defineProperties } from "./properties.js"; |
|
function stringify(value, seen) { |
|
if (value == null) { |
|
return "null"; |
|
} |
|
if (seen == null) { |
|
seen = new Set(); |
|
} |
|
if (typeof (value) === "object") { |
|
if (seen.has(value)) { |
|
return "[Circular]"; |
|
} |
|
seen.add(value); |
|
} |
|
if (Array.isArray(value)) { |
|
return "[ " + (value.map((v) => stringify(v, seen))).join(", ") + " ]"; |
|
} |
|
if (value instanceof Uint8Array) { |
|
const HEX = "0123456789abcdef"; |
|
let result = "0x"; |
|
for (let i = 0; i < value.length; i++) { |
|
result += HEX[value[i] >> 4]; |
|
result += HEX[value[i] & 0xf]; |
|
} |
|
return result; |
|
} |
|
if (typeof (value) === "object" && typeof (value.toJSON) === "function") { |
|
return stringify(value.toJSON(), seen); |
|
} |
|
switch (typeof (value)) { |
|
case "boolean": |
|
case "number": |
|
case "symbol": |
|
return value.toString(); |
|
case "bigint": |
|
return BigInt(value).toString(); |
|
case "string": |
|
return JSON.stringify(value); |
|
case "object": { |
|
const keys = Object.keys(value); |
|
keys.sort(); |
|
return "{ " + keys.map((k) => `${stringify(k, seen)}: ${stringify(value[k], seen)}`).join(", ") + " }"; |
|
} |
|
} |
|
return `[ COULD NOT SERIALIZE ]`; |
|
} |
|
/** |
|
* Returns true if the %%error%% matches an error thrown by ethers |
|
* that matches the error %%code%%. |
|
* |
|
* In TypeScript environments, this can be used to check that %%error%% |
|
* matches an EthersError type, which means the expected properties will |
|
* be set. |
|
* |
|
* @See [ErrorCodes](api:ErrorCode) |
|
* @example |
|
* try { |
|
* // code.... |
|
* } catch (e) { |
|
* if (isError(e, "CALL_EXCEPTION")) { |
|
* // The Type Guard has validated this object |
|
* console.log(e.data); |
|
* } |
|
* } |
|
*/ |
|
export function isError(error, code) { |
|
return (error && error.code === code); |
|
} |
|
/** |
|
* Returns true if %%error%% is a [[CallExceptionError]. |
|
*/ |
|
export function isCallException(error) { |
|
return isError(error, "CALL_EXCEPTION"); |
|
} |
|
/** |
|
* Returns a new Error configured to the format ethers emits errors, with |
|
* the %%message%%, [[api:ErrorCode]] %%code%% and additional properties |
|
* for the corresponding EthersError. |
|
* |
|
* Each error in ethers includes the version of ethers, a |
|
* machine-readable [[ErrorCode]], and depending on %%code%%, additional |
|
* required properties. The error message will also include the %%message%%, |
|
* ethers version, %%code%% and all additional properties, serialized. |
|
*/ |
|
export function makeError(message, code, info) { |
|
let shortMessage = message; |
|
{ |
|
const details = []; |
|
if (info) { |
|
if ("message" in info || "code" in info || "name" in info) { |
|
throw new Error(`value will overwrite populated values: ${stringify(info)}`); |
|
} |
|
for (const key in info) { |
|
if (key === "shortMessage") { |
|
continue; |
|
} |
|
const value = (info[key]); |
|
// try { |
|
details.push(key + "=" + stringify(value)); |
|
// } catch (error: any) { |
|
// console.log("MMM", error.message); |
|
// details.push(key + "=[could not serialize object]"); |
|
// } |
|
} |
|
} |
|
details.push(`code=${code}`); |
|
details.push(`version=${version}`); |
|
if (details.length) { |
|
message += " (" + details.join(", ") + ")"; |
|
} |
|
} |
|
let error; |
|
switch (code) { |
|
case "INVALID_ARGUMENT": |
|
error = new TypeError(message); |
|
break; |
|
case "NUMERIC_FAULT": |
|
case "BUFFER_OVERRUN": |
|
error = new RangeError(message); |
|
break; |
|
default: |
|
error = new Error(message); |
|
} |
|
defineProperties(error, { code }); |
|
if (info) { |
|
Object.assign(error, info); |
|
} |
|
if (error.shortMessage == null) { |
|
defineProperties(error, { shortMessage }); |
|
} |
|
return error; |
|
} |
|
/** |
|
* Throws an EthersError with %%message%%, %%code%% and additional error |
|
* %%info%% when %%check%% is falsish.. |
|
* |
|
* @see [[api:makeError]] |
|
*/ |
|
export function assert(check, message, code, info) { |
|
if (!check) { |
|
throw makeError(message, code, info); |
|
} |
|
} |
|
/** |
|
* A simple helper to simply ensuring provided arguments match expected |
|
* constraints, throwing if not. |
|
* |
|
* In TypeScript environments, the %%check%% has been asserted true, so |
|
* any further code does not need additional compile-time checks. |
|
*/ |
|
export function assertArgument(check, message, name, value) { |
|
assert(check, message, "INVALID_ARGUMENT", { argument: name, value: value }); |
|
} |
|
export function assertArgumentCount(count, expectedCount, message) { |
|
if (message == null) { |
|
message = ""; |
|
} |
|
if (message) { |
|
message = ": " + message; |
|
} |
|
assert(count >= expectedCount, "missing argument" + message, "MISSING_ARGUMENT", { |
|
count: count, |
|
expectedCount: expectedCount |
|
}); |
|
assert(count <= expectedCount, "too many arguments" + message, "UNEXPECTED_ARGUMENT", { |
|
count: count, |
|
expectedCount: expectedCount |
|
}); |
|
} |
|
const _normalizeForms = ["NFD", "NFC", "NFKD", "NFKC"].reduce((accum, form) => { |
|
try { |
|
// General test for normalize |
|
/* c8 ignore start */ |
|
if ("test".normalize(form) !== "test") { |
|
throw new Error("bad"); |
|
} |
|
; |
|
/* c8 ignore stop */ |
|
if (form === "NFD") { |
|
const check = String.fromCharCode(0xe9).normalize("NFD"); |
|
const expected = String.fromCharCode(0x65, 0x0301); |
|
/* c8 ignore start */ |
|
if (check !== expected) { |
|
throw new Error("broken"); |
|
} |
|
/* c8 ignore stop */ |
|
} |
|
accum.push(form); |
|
} |
|
catch (error) { } |
|
return accum; |
|
}, []); |
|
/** |
|
* Throws if the normalization %%form%% is not supported. |
|
*/ |
|
export function assertNormalize(form) { |
|
assert(_normalizeForms.indexOf(form) >= 0, "platform missing String.prototype.normalize", "UNSUPPORTED_OPERATION", { |
|
operation: "String.prototype.normalize", info: { form } |
|
}); |
|
} |
|
/** |
|
* Many classes use file-scoped values to guard the constructor, |
|
* making it effectively private. This facilitates that pattern |
|
* by ensuring the %%givenGaurd%% matches the file-scoped %%guard%%, |
|
* throwing if not, indicating the %%className%% if provided. |
|
*/ |
|
export function assertPrivate(givenGuard, guard, className) { |
|
if (className == null) { |
|
className = ""; |
|
} |
|
if (givenGuard !== guard) { |
|
let method = className, operation = "new"; |
|
if (className) { |
|
method += "."; |
|
operation += " " + className; |
|
} |
|
assert(false, `private constructor; use ${method}from* methods`, "UNSUPPORTED_OPERATION", { |
|
operation |
|
}); |
|
} |
|
} |
|
//# sourceMappingURL=errors.js.map
|