diff --git a/packages/abi/package.json b/packages/abi/package.json index 7c8908e84..0910c9122 100644 --- a/packages/abi/package.json +++ b/packages/abi/package.json @@ -11,9 +11,9 @@ "@ethersproject/bignumber": ">5.0.0-beta.0", "@ethersproject/bytes": ">5.0.0-beta.0", "@ethersproject/constants": ">5.0.0-beta.0", - "@ethersproject/errors": ">5.0.0-beta.0", "@ethersproject/hash": ">5.0.0-beta.0", "@ethersproject/keccak256": ">5.0.0-beta.0", + "@ethersproject/logger": ">5.0.0-beta.0", "@ethersproject/properties": ">5.0.0-beta.0", "@ethersproject/strings": ">5.0.0-beta.0" }, diff --git a/packages/abi/src.ts/abi-coder.ts b/packages/abi/src.ts/abi-coder.ts index 24d9d99a9..c607b1302 100644 --- a/packages/abi/src.ts/abi-coder.ts +++ b/packages/abi/src.ts/abi-coder.ts @@ -3,9 +3,12 @@ // See: https://github.com/ethereum/wiki/wiki/Ethereum-Contract-ABI import { arrayify, BytesLike } from "@ethersproject/bytes"; -import * as errors from "@ethersproject/errors"; import { defineReadOnly } from "@ethersproject/properties"; +import { Logger } from "@ethersproject/logger"; +import { version } from "./_version"; +const logger = new Logger(version); + import { Coder, Reader, Writer } from "./coders/abstract-coder"; import { AddressCoder } from "./coders/address"; import { ArrayCoder } from "./coders/array"; @@ -30,7 +33,7 @@ export class AbiCoder { readonly coerceFunc: CoerceFunc; constructor(coerceFunc?: CoerceFunc) { - errors.checkNew(new.target, AbiCoder); + logger.checkNew(new.target, AbiCoder); defineReadOnly(this, "coerceFunc", coerceFunc || null); } @@ -60,10 +63,7 @@ export class AbiCoder { if (match) { let size = parseInt(match[2] || "256"); if (size === 0 || size > 256 || (size % 8) !== 0) { - errors.throwError("invalid " + match[1] + " bit length", errors.INVALID_ARGUMENT, { - arg: "param", - value: param - }); + logger.throwArgumentError("invalid " + match[1] + " bit length", "param", param); } return new NumberCoder(size / 8, (match[1] === "int"), param.name); } @@ -73,18 +73,12 @@ export class AbiCoder { if (match) { let size = parseInt(match[1]); if (size === 0 || size > 32) { - errors.throwError("invalid bytes length", errors.INVALID_ARGUMENT, { - arg: "param", - value: param - }); + logger.throwArgumentError("invalid bytes length", "param", param); } return new FixedBytesCoder(size, param.name); } - return errors.throwError("invalid type", errors.INVALID_ARGUMENT, { - arg: "type", - value: param.type - }); + return logger.throwError("invalid type", "type", param.type); } _getWordSize(): number { return 32; } @@ -99,7 +93,7 @@ export class AbiCoder { encode(types: Array, values: Array): string { if (types.length !== values.length) { - errors.throwError("types/values length mismatch", errors.INVALID_ARGUMENT, { + logger.throwError("types/values length mismatch", Logger.errors.INVALID_ARGUMENT, { count: { types: types.length, values: values.length }, value: { types: types, values: values } }); diff --git a/packages/abi/src.ts/coders/abstract-coder.ts b/packages/abi/src.ts/coders/abstract-coder.ts index 00e5a332c..0b5702bda 100644 --- a/packages/abi/src.ts/coders/abstract-coder.ts +++ b/packages/abi/src.ts/coders/abstract-coder.ts @@ -2,9 +2,12 @@ import { arrayify, BytesLike, concat, hexlify } from "@ethersproject/bytes"; import { BigNumber, BigNumberish } from "@ethersproject/bignumber"; -import * as errors from "@ethersproject/errors"; import { defineReadOnly } from "@ethersproject/properties"; +import { Logger } from "@ethersproject/logger"; +import { version } from "../_version"; +const logger = new Logger(version); + export type CoerceFunc = (type: string, value: any) => any; export abstract class Coder { @@ -34,11 +37,7 @@ export abstract class Coder { } _throwError(message: string, value: any): void { - errors.throwError(message, errors.INVALID_ARGUMENT, { - argument: this.localName, - coder: this, - value: value - }); + logger.throwArgumentError(message, this.localName, value); } abstract encode(writer: Writer, value: any): number; @@ -77,7 +76,7 @@ export class Writer { _getValue(value: BigNumberish): Uint8Array { let bytes = arrayify(BigNumber.from(value)); if (bytes.length > this.wordSize) { - errors.throwError("value out-of-bounds", errors.BUFFER_OVERRUN, { + logger.throwError("value out-of-bounds", Logger.errors.BUFFER_OVERRUN, { length: this.wordSize, offset: bytes.length }); @@ -136,7 +135,7 @@ export class Reader { _peekBytes(offset: number, length: number): Uint8Array { let alignedLength = Math.ceil(length / this.wordSize) * this.wordSize; if (this._offset + alignedLength > this._data.length) { - errors.throwError("data out-of-bounds", errors.BUFFER_OVERRUN, { + logger.throwError("data out-of-bounds", Logger.errors.BUFFER_OVERRUN, { length: this._data.length, offset: this._offset + alignedLength }); diff --git a/packages/abi/src.ts/coders/array.ts b/packages/abi/src.ts/coders/array.ts index 6b066a222..a06518338 100644 --- a/packages/abi/src.ts/coders/array.ts +++ b/packages/abi/src.ts/coders/array.ts @@ -1,6 +1,8 @@ "use strict"; -import * as errors from "@ethersproject/errors"; +import { Logger } from "@ethersproject/logger"; +import { version } from "../_version"; +const logger = new Logger(version); import { Coder, Reader, Writer } from "./abstract-coder"; import { AnonymousCoder } from "./anonymous"; @@ -18,17 +20,11 @@ export function pack(writer: Writer, coders: Array, values: Array): values = arrayValues; } else { - errors.throwError("invalid tuple value", errors.INVALID_ARGUMENT, { - coderType: "tuple", - value: values - }); + logger.throwArgumentError("invalid tuple value", "tuple", values); } if (coders.length !== values.length) { - errors.throwError("types/value length mismatch", errors.INVALID_ARGUMENT, { - coderType: "tuple", - value: values - }); + logger.throwArgumentError("types/value length mismatch", "tuple", values); } let staticWriter = new Writer(writer.wordSize); @@ -136,7 +132,7 @@ export class ArrayCoder extends Coder { writer.writeValue(value.length); } - errors.checkArgumentCount(count, value.length, " in coder array" + (this.localName? (" "+ this.localName): "")); + logger.checkArgumentCount(count, value.length, "coder array" + (this.localName? (" "+ this.localName): "")); let coders = []; for (let i = 0; i < value.length; i++) { coders.push(this.coder); } diff --git a/packages/abi/src.ts/fragments.ts b/packages/abi/src.ts/fragments.ts index 72c796ed8..1c4476d65 100644 --- a/packages/abi/src.ts/fragments.ts +++ b/packages/abi/src.ts/fragments.ts @@ -1,9 +1,11 @@ "use strict"; import { BigNumber } from "@ethersproject/bignumber"; -import * as errors from "@ethersproject/errors"; import { defineReadOnly } from "@ethersproject/properties"; +import { Logger } from "@ethersproject/logger"; +import { version } from "./_version"; +const logger = new Logger(version); export interface JsonFragmentType { name?: string; @@ -58,7 +60,7 @@ function checkModifier(type: string, name: string): boolean { if (name === "payable") { return true; } } if (ModifiersBytes[name] || name === "payable") { - errors.throwArgumentError("invalid modifier", "name", name); + logger.throwArgumentError("invalid modifier", "name", name); } return false; } @@ -299,7 +301,7 @@ export class ParamType { format(format?: string): string { if (!format) { format = FormatTypes.sighash; } if (!FormatTypes[format]) { - errors.throwArgumentError("invalid format type", "format", format); + logger.throwArgumentError("invalid format type", "format", format); } if (format === FormatTypes.json) { @@ -426,7 +428,7 @@ export abstract class Fragment { return null; } - return errors.throwArgumentError("invalid fragment object", "value", value); + return logger.throwArgumentError("invalid fragment object", "value", value); } static fromString(value: string): Fragment { @@ -457,7 +459,7 @@ export class EventFragment extends Fragment { format(format?: string): string { if (!format) { format = FormatTypes.sighash; } if (!FormatTypes[format]) { - errors.throwArgumentError("invalid format type", "format", format); + logger.throwArgumentError("invalid format type", "format", format); } if (format === FormatTypes.json) { @@ -522,7 +524,7 @@ export class EventFragment extends Fragment { case "": break; default: - errors.warn("unknown modifier: " + modifier); + logger.warn("unknown modifier: " + modifier); } }); @@ -638,7 +640,7 @@ export class ConstructorFragment extends Fragment { format(format?: string): string { if (!format) { format = FormatTypes.sighash; } if (!FormatTypes[format]) { - errors.throwArgumentError("invalid format type", "format", format); + logger.throwArgumentError("invalid format type", "format", format); } if (format === FormatTypes.json) { @@ -652,7 +654,7 @@ export class ConstructorFragment extends Fragment { } if (format === FormatTypes.sighash) { - errors.throwError("cannot format a constructor for sighash", errors.UNSUPPORTED_OPERATION, { + logger.throwError("cannot format a constructor for sighash", Logger.errors.UNSUPPORTED_OPERATION, { operation: "format(sighash)" }); } @@ -722,7 +724,7 @@ export class FunctionFragment extends ConstructorFragment { format(format?: string): string { if (!format) { format = FormatTypes.sighash; } if (!FormatTypes[format]) { - errors.throwArgumentError("invalid format type", "format", format); + logger.throwArgumentError("invalid format type", "format", format); } if (format === FormatTypes.json) { diff --git a/packages/abi/src.ts/interface.ts b/packages/abi/src.ts/interface.ts index 05f79c721..e232d5b89 100644 --- a/packages/abi/src.ts/interface.ts +++ b/packages/abi/src.ts/interface.ts @@ -5,12 +5,14 @@ import { BigNumber, BigNumberish } from "@ethersproject/bignumber"; import { arrayify, BytesLike, concat, hexDataSlice, hexlify, hexZeroPad, isHexString } from "@ethersproject/bytes"; import { id } from "@ethersproject/hash"; import { keccak256 } from "@ethersproject/keccak256" -import * as errors from "@ethersproject/errors"; import { defineReadOnly, Description, getStatic } from "@ethersproject/properties"; import { AbiCoder, defaultAbiCoder } from "./abi-coder"; import { ConstructorFragment, EventFragment, Fragment, FunctionFragment, JsonFragment, ParamType } from "./fragments"; +import { Logger } from "@ethersproject/logger"; +import { version } from "./_version"; +const logger = new Logger(version); export class LogDescription extends Description { readonly eventFragment: EventFragment; @@ -58,7 +60,7 @@ export class Interface { static _isInterface: boolean; constructor(fragments: string | Array) { - errors.checkNew(new.target, Interface); + logger.checkNew(new.target, Interface); let abi: Array = [ ]; if (typeof(fragments) === "string") { @@ -84,7 +86,7 @@ export class Interface { switch (fragment.type) { case "constructor": if (this.deploy) { - errors.warn("duplicate definition - constructor"); + logger.warn("duplicate definition - constructor"); return; } defineReadOnly(this, "deploy", fragment); @@ -101,7 +103,7 @@ export class Interface { let signature = fragment.format(); if (bucket[signature]) { - errors.warn("duplicate definition - " + signature); + logger.warn("duplicate definition - " + signature); return; } @@ -114,7 +116,7 @@ export class Interface { Object.keys(bucket).forEach((signature) => { let fragment = bucket[signature]; if (count[fragment.name] !== 1) { - errors.warn("duplicate definition - " + fragment.name); + logger.warn("duplicate definition - " + fragment.name); return; } bucket[fragment.name] = fragment; @@ -233,7 +235,7 @@ export class Interface { break; } - return errors.throwError("call revert exception", errors.CALL_EXCEPTION, { + return logger.throwError("call revert exception", Logger.errors.CALL_EXCEPTION, { method: functionFragment.format(), errorSignature: errorSignature, errorArgs: [ reason ], @@ -247,7 +249,7 @@ export class Interface { } if (values.length > eventFragment.inputs.length) { - errors.throwError("too many arguments for " + eventFragment.format(), errors.UNEXPECTED_ARGUMENT, { + logger.throwError("too many arguments for " + eventFragment.format(), Logger.errors.UNEXPECTED_ARGUMENT, { argument: "values", value: values }) @@ -262,7 +264,7 @@ export class Interface { if (!param.indexed) { if (value != null) { - errors.throwArgumentError("cannot filter non-indexed parameters; must be null", ("contract." + param.name), value); + logger.throwArgumentError("cannot filter non-indexed parameters; must be null", ("contract." + param.name), value); } return; } @@ -274,7 +276,7 @@ export class Interface { } else if (param.type === "bytes") { topics.push(keccak256(hexlify(value))); } else if (param.type.indexOf("[") !== -1 || param.type.substring(0, 5) === "tuple") { - errors.throwArgumentError("filtering with tuples or arrays not supported", ("contract." + param.name), value); + logger.throwArgumentError("filtering with tuples or arrays not supported", ("contract." + param.name), value); } else { // Check addresses are valid if (param.type === "address") { this._abiCoder.encode( [ "address" ], [ value ]); } @@ -298,7 +300,7 @@ export class Interface { if (topics != null && !eventFragment.anonymous) { let topicHash = this.getEventTopic(eventFragment); if (!isHexString(topics[0], 32) || topics[0].toLowerCase() !== topicHash) { - errors.throwError("fragment/topic mismatch", errors.INVALID_ARGUMENT, { argument: "topics[0]", expected: topicHash, value: topics[0] }); + logger.throwError("fragment/topic mismatch", Logger.errors.INVALID_ARGUMENT, { argument: "topics[0]", expected: topicHash, value: topics[0] }); } topics = topics.slice(1); } diff --git a/packages/abstract-provider/package.json b/packages/abstract-provider/package.json index 0d9a2cc98..1a6973dd3 100644 --- a/packages/abstract-provider/package.json +++ b/packages/abstract-provider/package.json @@ -13,7 +13,7 @@ "dependencies": { "@ethersproject/bignumber": ">5.0.0-beta.0", "@ethersproject/bytes": ">5.0.0-beta.0", - "@ethersproject/errors": ">5.0.0-beta.0", + "@ethersproject/logger": ">5.0.0-beta.0", "@ethersproject/networks": ">5.0.0-beta.0", "@ethersproject/properties": ">5.0.0-beta.0", "@ethersproject/transactions": ">5.0.0-beta.0", diff --git a/packages/abstract-provider/src.ts/index.ts b/packages/abstract-provider/src.ts/index.ts index 775a11f5d..108e7c339 100644 --- a/packages/abstract-provider/src.ts/index.ts +++ b/packages/abstract-provider/src.ts/index.ts @@ -2,13 +2,15 @@ import { BigNumber, BigNumberish } from "@ethersproject/bignumber"; import { BytesLike, isHexString } from "@ethersproject/bytes"; -import * as errors from "@ethersproject/errors"; import { checkAbstract } from "@ethersproject/errors"; import { Network } from "@ethersproject/networks"; import { Description, defineReadOnly } from "@ethersproject/properties"; import { Transaction } from "@ethersproject/transactions"; import { OnceBlockable } from "@ethersproject/web"; +import { Logger } from "@ethersproject/logger"; +import { version } from "./_version"; +const logger = new Logger(version); /////////////////////////////// // Exported Types @@ -143,7 +145,7 @@ export class BlockForkEvent extends ForkEvent { constructor(blockhash: string, expiry?: number) { if (!isHexString(blockhash, 32)) { - errors.throwArgumentError("invalid blockhash", "blockhash", blockhash); + logger.throwArgumentError("invalid blockhash", "blockhash", blockhash); } super({ @@ -160,7 +162,7 @@ export class TransactionForkEvent extends ForkEvent { constructor(hash: string, expiry?: number) { if (!isHexString(hash, 32)) { - errors.throwArgumentError("invalid transaction hash", "hash", hash); + logger.throwArgumentError("invalid transaction hash", "hash", hash); } super({ @@ -178,10 +180,10 @@ export class TransactionOrderForkEvent extends ForkEvent { constructor(beforeHash: string, afterHash: string, expiry?: number) { if (!isHexString(beforeHash, 32)) { - errors.throwArgumentError("invalid transaction hash", "beforeHash", beforeHash); + logger.throwArgumentError("invalid transaction hash", "beforeHash", beforeHash); } if (!isHexString(afterHash, 32)) { - errors.throwArgumentError("invalid transaction hash", "afterHash", afterHash); + logger.throwArgumentError("invalid transaction hash", "afterHash", afterHash); } super({ diff --git a/packages/abstract-signer/package.json b/packages/abstract-signer/package.json index ccb088984..660fa1e96 100644 --- a/packages/abstract-signer/package.json +++ b/packages/abstract-signer/package.json @@ -10,7 +10,7 @@ "@ethersproject/abstract-provider": ">5.0.0-beta.0", "@ethersproject/bignumber": ">5.0.0-beta.0", "@ethersproject/bytes": ">5.0.0-beta.0", - "@ethersproject/errors": ">5.0.0-beta.0", + "@ethersproject/logger": ">5.0.0-beta.0", "@ethersproject/properties": ">5.0.0-beta.0" }, "keywords": [ diff --git a/packages/abstract-signer/src.ts/index.ts b/packages/abstract-signer/src.ts/index.ts index 31dd4de54..d5322a8a9 100644 --- a/packages/abstract-signer/src.ts/index.ts +++ b/packages/abstract-signer/src.ts/index.ts @@ -3,9 +3,12 @@ import { BlockTag, Provider, TransactionRequest, TransactionResponse } from "@ethersproject/abstract-provider"; import { BigNumber } from "@ethersproject/bignumber"; import { Bytes } from "@ethersproject/bytes"; -import * as errors from "@ethersproject/errors"; import { defineReadOnly, resolveProperties, shallowCopy } from "@ethersproject/properties"; +import { Logger } from "@ethersproject/logger"; +import { version } from "./_version"; +const logger = new Logger(version); + const allowedTransactionKeys: Array = [ "chainId", "data", "from", "gasLimit", "gasPrice", "nonce", "to", "value" ]; @@ -57,7 +60,7 @@ export abstract class Signer { /////////////////// // Sub-classes MUST call super constructor() { - errors.checkAbstract(new.target, Signer); + logger.checkAbstract(new.target, Signer); defineReadOnly(this, "_isSigner", true); } @@ -131,7 +134,7 @@ export abstract class Signer { checkTransaction(transaction: TransactionRequest): TransactionRequest { for (let key in transaction) { if (allowedTransactionKeys.indexOf(key) === -1) { - errors.throwArgumentError("invalid transaction key: " + key, "transaction", transaction); + logger.throwArgumentError("invalid transaction key: " + key, "transaction", transaction); } } @@ -160,7 +163,7 @@ export abstract class Signer { this.provider.resolveName(tx.from) ]).then((results) => { if (results[0] !== results[1]) { - errors.throwArgumentError("from address mismatch", "transaction", transaction); + logger.throwArgumentError("from address mismatch", "transaction", transaction); } return results[0]; }); @@ -178,7 +181,7 @@ export abstract class Signer { // Sub-classes SHOULD leave these alone _checkProvider(operation?: string): void { - if (!this.provider) { errors.throwError("missing provider", errors.UNSUPPORTED_OPERATION, { + if (!this.provider) { logger.throwError("missing provider", Logger.errors.UNSUPPORTED_OPERATION, { operation: (operation || "_checkProvider") }); } } @@ -192,7 +195,7 @@ export class VoidSigner extends Signer { readonly address: string; constructor(address: string, provider?: Provider) { - errors.checkNew(new.target, VoidSigner); + logger.checkNew(new.target, VoidSigner); super(); defineReadOnly(this, "address", address); defineReadOnly(this, "provider", provider || null); @@ -204,7 +207,7 @@ export class VoidSigner extends Signer { _fail(message: string, operation: string): Promise { return Promise.resolve().then(() => { - errors.throwError(message, errors.UNSUPPORTED_OPERATION, { operation: operation }); + logger.throwError(message, Logger.errors.UNSUPPORTED_OPERATION, { operation: operation }); }); } diff --git a/packages/address/package.json b/packages/address/package.json index 3b88052ee..f24db0dce 100644 --- a/packages/address/package.json +++ b/packages/address/package.json @@ -9,8 +9,8 @@ "dependencies": { "@ethersproject/bignumber": ">5.0.0-beta.0", "@ethersproject/bytes": ">5.0.0-beta.0", - "@ethersproject/errors": ">5.0.0-beta.0", "@ethersproject/keccak256": ">5.0.0-beta.0", + "@ethersproject/logger": ">5.0.0-beta.0", "@ethersproject/rlp": ">5.0.0-beta.0", "bn.js": "^4.4.0" }, diff --git a/packages/address/src.ts/index.ts b/packages/address/src.ts/index.ts index 40acf766f..2fcdebe07 100644 --- a/packages/address/src.ts/index.ts +++ b/packages/address/src.ts/index.ts @@ -3,17 +3,18 @@ // We use this for base 36 maths import * as BN from "bn.js"; -import * as errors from "@ethersproject/errors"; - import { arrayify, hexDataSlice, isHexString, stripZeros } from "@ethersproject/bytes"; import { BigNumberish } from "@ethersproject/bignumber"; import { keccak256 } from "@ethersproject/keccak256"; import { encode } from "@ethersproject/rlp"; +import { Logger } from "@ethersproject/logger"; +import { version } from "./_version"; +const logger = new Logger(version); function getChecksumAddress(address: string): string { if (!isHexString(address, 20)) { - errors.throwError("invalid address", errors.INVALID_ARGUMENT, { arg: "address", value: address }); + logger.throwArgumentError("invalid address", "address", address); } address = address.toLowerCase(); @@ -82,7 +83,7 @@ export function getAddress(address: string): string { let result = null; if (typeof(address) !== "string") { - errors.throwArgumentError("invalid address", "address", address); + logger.throwArgumentError("invalid address", "address", address); } if (address.match(/^(0x)?[0-9a-fA-F]{40}$/)) { @@ -94,7 +95,7 @@ export function getAddress(address: string): string { // It is a checksummed address with a bad checksum if (address.match(/([A-F].*[a-f])|([a-f].*[A-F])/) && result !== address) { - errors.throwArgumentError("bad address checksum", "address", address); + logger.throwArgumentError("bad address checksum", "address", address); } // Maybe ICAP? (we only support direct mode) @@ -102,7 +103,7 @@ export function getAddress(address: string): string { // It is an ICAP address with a bad checksum if (address.substring(2, 4) !== ibanChecksum(address)) { - errors.throwArgumentError("bad icap checksum", "address", address); + logger.throwArgumentError("bad icap checksum", "address", address); } result = (new BN.BN(address.substring(4), 36)).toString(16); @@ -110,7 +111,7 @@ export function getAddress(address: string): string { result = getChecksumAddress("0x" + result); } else { - errors.throwArgumentError("invalid address", "address", address); + logger.throwArgumentError("invalid address", "address", address); } return result; @@ -136,7 +137,7 @@ export function getContractAddress(transaction: { from: string, nonce: BigNumber try { from = getAddress(transaction.from); } catch (error) { - errors.throwArgumentError("missing from address", "transaction", transaction); + logger.throwArgumentError("missing from address", "transaction", transaction); } let nonce = stripZeros(arrayify(transaction.nonce)); diff --git a/packages/bignumber/package.json b/packages/bignumber/package.json index 58509f847..60c071f5d 100644 --- a/packages/bignumber/package.json +++ b/packages/bignumber/package.json @@ -8,7 +8,7 @@ }, "dependencies": { "@ethersproject/bytes": ">5.0.0-beta.0", - "@ethersproject/errors": ">5.0.0-beta.0", + "@ethersproject/logger": ">5.0.0-beta.0", "@ethersproject/properties": ">5.0.0-beta.0", "bn.js": "^4.4.0" }, diff --git a/packages/bignumber/src.ts/bignumber.ts b/packages/bignumber/src.ts/bignumber.ts index 97e78411d..d8829edf4 100644 --- a/packages/bignumber/src.ts/bignumber.ts +++ b/packages/bignumber/src.ts/bignumber.ts @@ -12,7 +12,9 @@ import * as BN from "bn.js"; import { Bytes, Hexable, hexlify, isBytes, isHexString } from "@ethersproject/bytes"; -import * as errors from "@ethersproject/errors"; +import { Logger } from "@ethersproject/logger"; +import { version } from "./_version"; +const logger = new Logger(version); const _constructorGuard = { }; @@ -37,10 +39,10 @@ export class BigNumber implements Hexable { readonly _isBigNumber: boolean; constructor(constructorGuard: any, hex: string) { - errors.checkNew(new.target, BigNumber); + logger.checkNew(new.target, BigNumber); if (constructorGuard !== _constructorGuard) { - errors.throwError("cannot call consturtor directly; use BigNumber.from", errors.UNSUPPORTED_OPERATION, { + logger.throwError("cannot call consturtor directly; use BigNumber.from", Logger.errors.UNSUPPORTED_OPERATION, { operation: "new (BigNumber)" }); } @@ -134,7 +136,7 @@ export class BigNumber implements Hexable { toString(): string { // Lots of people expect this, which we do not support, so check if (arguments.length !== 0) { - errors.throwError("bigNumber.toString does not accept parameters", errors.UNEXPECTED_ARGUMENT, { }); + logger.throwError("bigNumber.toString does not accept parameters", Logger.errors.UNEXPECTED_ARGUMENT, { }); } return toBN(this).toString(10); } @@ -155,7 +157,7 @@ export class BigNumber implements Hexable { return new BigNumber(_constructorGuard, toHex(new BN.BN(value))); } - return errors.throwArgumentError("invalid BigNumber string", "value", value); + return logger.throwArgumentError("invalid BigNumber string", "value", value); } if (typeof(value) === "number") { @@ -189,7 +191,7 @@ export class BigNumber implements Hexable { } } - return errors.throwArgumentError("invalid BigNumber value", "value", value); + return logger.throwArgumentError("invalid BigNumber value", "value", value); } static isBigNumber(value: any): value is BigNumber { @@ -211,7 +213,7 @@ function toHex(value: string | BN.BN): string { value = value.substring(1); // Cannot have mulitple negative signs (e.g. "--0x04") - if (value[0] === "-") { errors.throwArgumentError("invalid hex", "value", value); } + if (value[0] === "-") { logger.throwArgumentError("invalid hex", "value", value); } // Call toHex on the positive component value = toHex(value); @@ -256,5 +258,5 @@ function throwFault(fault: string, operation: string, value?: any): never { let params: any = { fault: fault, operation: operation }; if (value != null) { params.value = value; } - return errors.throwError(fault, errors.NUMERIC_FAULT, params); + return logger.throwError(fault, Logger.errors.NUMERIC_FAULT, params); } diff --git a/packages/bignumber/src.ts/fixednumber.ts b/packages/bignumber/src.ts/fixednumber.ts index 2cbf9a182..b9f0e9b2e 100644 --- a/packages/bignumber/src.ts/fixednumber.ts +++ b/packages/bignumber/src.ts/fixednumber.ts @@ -1,7 +1,10 @@ "use strict"; import { arrayify, BytesLike, hexZeroPad, isBytes } from "@ethersproject/bytes"; -import * as errors from "@ethersproject/errors"; + +import { Logger } from "@ethersproject/logger"; +import { version } from "./_version"; +const logger = new Logger(version); import { BigNumber, BigNumberish, isBigNumberish } from "./bignumber"; @@ -13,7 +16,7 @@ const NegativeOne = BigNumber.from(-1); function throwFault(message: string, fault: string, operation: string, value?: any): never { let params: any = { fault: fault, operation: operation }; if (value !== undefined) { params.value = value; } - return errors.throwError(message, errors.NUMERIC_FAULT, params); + return logger.throwError(message, Logger.errors.NUMERIC_FAULT, params); } // Constant to pull zeros from for multipliers @@ -33,7 +36,7 @@ function getMultiplier(decimals: BigNumberish): string { return ("1" + zeros.substring(0, decimals)); } - return errors.throwArgumentError("invalid decimal size", "decimals", decimals); + return logger.throwArgumentError("invalid decimal size", "decimals", decimals); } export function formatFixed(value: BigNumberish, decimals?: string | BigNumberish): string { @@ -66,7 +69,7 @@ export function parseFixed(value: string, decimals?: BigNumberish): BigNumber { let multiplier = getMultiplier(decimals); if (typeof(value) !== "string" || !value.match(/^-?[0-9.,]+$/)) { - errors.throwArgumentError("invalid decimal value", "value", value); + logger.throwArgumentError("invalid decimal value", "value", value); } if (multiplier.length - 1 === 0) { @@ -78,13 +81,13 @@ export function parseFixed(value: string, decimals?: BigNumberish): BigNumber { if (negative) { value = value.substring(1); } if (value === ".") { - errors.throwArgumentError("missing value", "value", value); + logger.throwArgumentError("missing value", "value", value); } // Split it into a whole and fractional part let comps = value.split("."); if (comps.length > 2) { - errors.throwArgumentError("too many decimal points", "value", value); + logger.throwArgumentError("too many decimal points", "value", value); } let whole = comps[0], fraction = comps[1]; @@ -142,7 +145,7 @@ export class FixedFormat { signed = false; } else if (value != null) { let match = value.match(/^(u?)fixed([0-9]+)x([0-9]+)$/); - if (!match) { errors.throwArgumentError("invalid fixed format", "format", value); } + if (!match) { logger.throwArgumentError("invalid fixed format", "format", value); } signed = (match[1] !== "u"); width = parseInt(match[2]); decimals = parseInt(match[3]); @@ -151,7 +154,7 @@ export class FixedFormat { let check = (key: string, type: string, defaultValue: any): any => { if (value[key] == null) { return defaultValue; } if (typeof(value[key]) !== type) { - errors.throwArgumentError("invalid fixed format (" + key + " not " + type +")", "format." + key, value[key]); + logger.throwArgumentError("invalid fixed format (" + key + " not " + type +")", "format." + key, value[key]); } return value[key]; } @@ -161,11 +164,11 @@ export class FixedFormat { } if (width % 8) { - errors.throwArgumentError("invalid fixed format width (not byte aligned)", "format.width", width); + logger.throwArgumentError("invalid fixed format width (not byte aligned)", "format.width", width); } if (decimals > 80) { - errors.throwArgumentError("invalid fixed format (decimals too large)", "format.decimals", decimals); + logger.throwArgumentError("invalid fixed format (decimals too large)", "format.decimals", decimals); } return new FixedFormat(_constructorGuard, signed, width, decimals); @@ -180,7 +183,7 @@ export class FixedNumber { readonly _isFixedNumber: boolean; constructor(constructorGuard: any, hex: string, value: string, format?: FixedFormat) { - errors.checkNew(new.target, FixedNumber); + logger.checkNew(new.target, FixedNumber); this.format = format; this._hex = hex; @@ -193,7 +196,7 @@ export class FixedNumber { _checkFormat(other: FixedNumber): void { if (this.format.name !== other.format.name) { - errors.throwArgumentError("incompatible format; use fixedNumber.toFormat", "other", other); + logger.throwArgumentError("incompatible format; use fixedNumber.toFormat", "other", other); } } @@ -229,7 +232,7 @@ export class FixedNumber { round(decimals?: number): FixedNumber { if (decimals == null) { decimals = 0; } if (decimals < 0 || decimals > 80 || (decimals % 1)) { - errors.throwArgumentError("invalid decimal cound", "decimals", decimals); + logger.throwArgumentError("invalid decimal cound", "decimals", decimals); } // If we are already in range, we're done @@ -249,7 +252,7 @@ export class FixedNumber { toHexString(width?: number): string { if (width == null) { return this._hex; } - if (width % 8) { errors.throwArgumentError("invalid byte width", "width", width); } + if (width % 8) { logger.throwArgumentError("invalid byte width", "width", width); } let hex = BigNumber.from(this._hex).fromTwos(this.format.width).toTwos(width).toHexString(); return hexZeroPad(hex, width / 8); } @@ -330,12 +333,12 @@ export class FixedNumber { return FixedNumber.fromValue(value, 0, format); } catch (error) { // Allow NUMERIC_FAULT to bubble up - if (error.code !== errors.INVALID_ARGUMENT) { + if (error.code !== Logger.errors.INVALID_ARGUMENT) { throw error; } } - return errors.throwArgumentError("invalid FixedNumber value", "value", value); + return logger.throwArgumentError("invalid FixedNumber value", "value", value); } static isFixedNumber(value: any): value is FixedNumber { diff --git a/packages/bytes/package.json b/packages/bytes/package.json index f0b473aa7..79cc24ed7 100644 --- a/packages/bytes/package.json +++ b/packages/bytes/package.json @@ -9,7 +9,7 @@ "test": "echo \"Error: no test specified\" && exit 1" }, "dependencies": { - "@ethersproject/errors": ">5.0.0-beta.0" + "@ethersproject/logger": ">5.0.0-beta.0" }, "keywords": [ "Ethereum", diff --git a/packages/bytes/src.ts/index.ts b/packages/bytes/src.ts/index.ts index 8cf1e1d4f..7f2927d16 100644 --- a/packages/bytes/src.ts/index.ts +++ b/packages/bytes/src.ts/index.ts @@ -1,8 +1,8 @@ "use strict"; - -import * as errors from "@ethersproject/errors"; - +import { Logger } from "@ethersproject/logger"; +import { version } from "./_version"; +const logger = new Logger(version); /////////////////////////////// // Exported Types @@ -92,7 +92,7 @@ export function arrayify(value: BytesLike | Hexable | number, options?: DataOpti if (!options) { options = { }; } if (typeof(value) === "number") { - errors.checkSafeUint53(value, "invalid arrayify value"); + logger.checkSafeUint53(value, "invalid arrayify value"); let result = []; while (value) { @@ -113,7 +113,7 @@ export function arrayify(value: BytesLike | Hexable | number, options?: DataOpti if (isHexString(value)) { let hex = (value).substring(2); if (!options.allowOddLength && hex.length % 2) { - errors.throwArgumentError("hex data is odd-length", "value", value); + logger.throwArgumentError("hex data is odd-length", "value", value); } let result = []; @@ -128,7 +128,7 @@ export function arrayify(value: BytesLike | Hexable | number, options?: DataOpti return addSlice(new Uint8Array(value)); } - return errors.throwArgumentError("invalid arrayify value", "value", value); + return logger.throwArgumentError("invalid arrayify value", "value", value); } export function concat(items: Array): Uint8Array { @@ -166,7 +166,7 @@ export function zeroPad(value: BytesLike, length: number): Uint8Array { value = arrayify(value); if (value.length > length) { - errors.throwArgumentError("value out of range", "value", arguments[0]); + logger.throwArgumentError("value out of range", "value", arguments[0]); } let result = new Uint8Array(length); @@ -189,7 +189,7 @@ export function hexlify(value: BytesLike | Hexable | number, options?: DataOptio if (!options) { options = { }; } if (typeof(value) === "number") { - errors.checkSafeUint53(value, "invalid hexlify value"); + logger.checkSafeUint53(value, "invalid hexlify value"); let hex = ""; while (value) { @@ -213,7 +213,7 @@ export function hexlify(value: BytesLike | Hexable | number, options?: DataOptio if (isHexString(value)) { if (!options.allowOddLength && (value).length % 2) { - errors.throwArgumentError("hex data is odd-length", "value", value); + logger.throwArgumentError("hex data is odd-length", "value", value); } return (value).toLowerCase(); } @@ -227,7 +227,7 @@ export function hexlify(value: BytesLike | Hexable | number, options?: DataOptio return result; } - return errors.throwArgumentError("invalid hexlify value", "value", value); + return logger.throwArgumentError("invalid hexlify value", "value", value); } /* @@ -252,7 +252,7 @@ export function hexDataSlice(data: BytesLike, offset: number, endOffset?: number if (typeof(data) !== "string") { data = hexlify(data); } else if (!isHexString(data) || (data.length % 2)) { - errors.throwArgumentError("invalid hexData", "value", data ); + logger.throwArgumentError("invalid hexData", "value", data ); } offset = 2 + 2 * offset; @@ -282,7 +282,7 @@ export function hexStripZeros(value: BytesLike): string { if (typeof(value) !== "string") { value = hexlify(value); } if (!isHexString(value)) { - errors.throwArgumentError("invalid hex string", "value", value); + logger.throwArgumentError("invalid hex string", "value", value); } value = value.substring(2); let offset = 0; @@ -294,11 +294,11 @@ export function hexZeroPad(value: BytesLike, length: number): string { if (typeof(value) !== "string") { value = hexlify(value); } else if (!isHexString(value)) { - errors.throwArgumentError("invalid hex string", "value", value); + logger.throwArgumentError("invalid hex string", "value", value); } if (value.length > 2 * length + 2) { - errors.throwArgumentError("value out of range", "value", arguments[1]); + logger.throwArgumentError("value out of range", "value", arguments[1]); } while (value.length < 2 * length + 2) { @@ -320,7 +320,7 @@ export function splitSignature(signature: SignatureLike): Signature { if (isBytesLike(signature)) { let bytes: Uint8Array = arrayify(signature); if (bytes.length !== 65) { - errors.throwArgumentError("invalid signature string; must be 65 bytes", "signature", signature); + logger.throwArgumentError("invalid signature string; must be 65 bytes", "signature", signature); } // Get the r and s @@ -359,7 +359,7 @@ export function splitSignature(signature: SignatureLike): Signature { result.v = 27 + result.recoveryParam; } else if (result.recoveryParam != null && result.v != null) { if (result.v !== 27 + result.recoveryParam) { - errors.throwArgumentError("signature v mismatch recoveryParam", "signature", signature); + logger.throwArgumentError("signature v mismatch recoveryParam", "signature", signature); } } @@ -372,7 +372,7 @@ export function splitSignature(signature: SignatureLike): Signature { if (result._vs != null) { result._vs = hexZeroPad(result._vs, 32); if (result._vs.length > 66) { - errors.throwArgumentError("signature _vs overflow", "signature", signature); + logger.throwArgumentError("signature _vs overflow", "signature", signature); } let vs = arrayify(result._vs); @@ -389,41 +389,41 @@ export function splitSignature(signature: SignatureLike): Signature { if (result.s == null) { result.s = s; } else if (result.s !== s) { - errors.throwArgumentError("signature v mismatch _vs", "signature", signature); + logger.throwArgumentError("signature v mismatch _vs", "signature", signature); } if (result.v == null) { result.v = v; } else if (result.v !== v) { - errors.throwArgumentError("signature v mismatch _vs", "signature", signature); + logger.throwArgumentError("signature v mismatch _vs", "signature", signature); } if (recoveryParam == null) { result.recoveryParam = recoveryParam; } else if (result.recoveryParam !== recoveryParam) { - errors.throwArgumentError("signature recoveryParam mismatch _vs", "signature", signature); + logger.throwArgumentError("signature recoveryParam mismatch _vs", "signature", signature); } } // After all populating, both v and recoveryParam are still missing... if (result.v == null && result.recoveryParam == null) { - errors.throwArgumentError("signature requires at least one of recoveryParam, v or _vs", "signature", signature); + logger.throwArgumentError("signature requires at least one of recoveryParam, v or _vs", "signature", signature); } // Check for canonical v if (result.v !== 27 && result.v !== 28) { - errors.throwArgumentError("signature v not canonical", "signature", signature); + logger.throwArgumentError("signature v not canonical", "signature", signature); } // Check that r and s are in range if (result.r.length > 66 || result.s.length > 66) { - errors.throwArgumentError("signature overflow r or s", "signature", signature); + logger.throwArgumentError("signature overflow r or s", "signature", signature); } if (result._vs == null) { let vs = arrayify(result.s); if (vs[0] >= 128) { - errors.throwArgumentError("signature s out of range", "signature", signature); + logger.throwArgumentError("signature s out of range", "signature", signature); } if (result.recoveryParam) { vs[0] |= 0x80; } result._vs = hexlify(vs); diff --git a/packages/contracts/package.json b/packages/contracts/package.json index b14c0497f..444e06212 100644 --- a/packages/contracts/package.json +++ b/packages/contracts/package.json @@ -14,7 +14,7 @@ "@ethersproject/bignumber": ">5.0.0-beta.0", "@ethersproject/bytes": ">5.0.0-beta.0", "@ethersproject/constants": ">5.0.0-beta.0", - "@ethersproject/errors": ">5.0.0-beta.0", + "@ethersproject/logger": ">5.0.0-beta.0", "@ethersproject/properties": ">5.0.0-beta.0", "@ethersproject/transactions": ">5.0.0-beta.0" }, diff --git a/packages/contracts/src.ts/index.ts b/packages/contracts/src.ts/index.ts index 7a3ba848b..d0f150744 100644 --- a/packages/contracts/src.ts/index.ts +++ b/packages/contracts/src.ts/index.ts @@ -7,10 +7,12 @@ import { getContractAddress } from "@ethersproject/address"; import { BigNumber, BigNumberish } from "@ethersproject/bignumber"; import { BytesLike, concat, hexlify, isBytes, isHexString } from "@ethersproject/bytes"; import { Zero } from "@ethersproject/constants"; -import * as errors from "@ethersproject/errors"; import { defineReadOnly, deepCopy, getStatic, resolveProperties, shallowCopy } from "@ethersproject/properties"; import { UnsignedTransaction } from "@ethersproject/transactions"; +import { Logger } from "@ethersproject/logger"; +import { version } from "./_version"; +const logger = new Logger(version); export interface Overrides { gasLimit?: BigNumberish | Promise; @@ -131,17 +133,17 @@ function runMethod(contract: Contract, functionName: string, options: RunOptions // Check for unexpected keys (e.g. using "gas" instead of "gasLimit") for (let key in tx) { if (!allowedTransactionKeys[key]) { - errors.throwError(("unknown transaxction override - " + key), "overrides", tx); + logger.throwError(("unknown transaxction override - " + key), "overrides", tx); } } } - errors.checkArgumentCount(params.length, method.inputs.length, "passed to contract"); + logger.checkArgumentCount(params.length, method.inputs.length, "passed to contract"); // Check overrides make sense ["data", "to"].forEach(function(key) { if (tx[key] != null) { - errors.throwError("cannot override " + key, errors.UNSUPPORTED_OPERATION, { operation: key }); + logger.throwError("cannot override " + key, Logger.errors.UNSUPPORTED_OPERATION, { operation: key }); } }); @@ -164,7 +166,7 @@ function runMethod(contract: Contract, functionName: string, options: RunOptions } if (!contract.provider && !contract.signer) { - errors.throwError("call (constant functions) require a provider or signer", errors.UNSUPPORTED_OPERATION, { operation: "call" }) + logger.throwError("call (constant functions) require a provider or signer", Logger.errors.UNSUPPORTED_OPERATION, { operation: "call" }) } // Check overrides make sense @@ -186,7 +188,7 @@ function runMethod(contract: Contract, functionName: string, options: RunOptions return result; } catch (error) { - if (error.code === errors.CALL_EXCEPTION) { + if (error.code === Logger.errors.CALL_EXCEPTION) { error.address = contract.address; error.args = params; error.transaction = tx; @@ -200,7 +202,7 @@ function runMethod(contract: Contract, functionName: string, options: RunOptions // Only computing the transaction estimate if (options.estimate) { if (!contract.provider && !contract.signer) { - errors.throwError("estimate require a provider or signer", errors.UNSUPPORTED_OPERATION, { operation: "estimateGas" }) + logger.throwError("estimate require a provider or signer", Logger.errors.UNSUPPORTED_OPERATION, { operation: "estimateGas" }) } return (contract.signer || contract.provider).estimateGas(tx); @@ -211,17 +213,13 @@ function runMethod(contract: Contract, functionName: string, options: RunOptions } if (tx.value != null && !method.payable) { - errors.throwError("contract method is not payable", errors.INVALID_ARGUMENT, { - argument: "sendTransaction", - value: tx, - method: method.format() - }) + logger.throwArgumentError("contract method is not payable", "sendTransaction:" + method.format(), tx); } if (options.transaction) { return resolveProperties(tx); } if (!contract.signer) { - errors.throwError("sending a transaction require a signer", errors.UNSUPPORTED_OPERATION, { operation: "sendTransaction" }) + logger.throwError("sending a transaction require a signer", Logger.errors.UNSUPPORTED_OPERATION, { operation: "sendTransaction" }) } return contract.signer.sendTransaction(tx).then((tx) => { @@ -353,7 +351,7 @@ class FragmentRunningEvent extends RunningEvent { let topic = contractInterface.getEventTopic(fragment); if (topics) { - if (topic !== topics[0]) { errors.throwArgumentError("topic mismatch", "topics", topics); } + if (topic !== topics[0]) { logger.throwArgumentError("topic mismatch", "topics", topics); } filter.topics = topics.slice(); } else { filter.topics = [ topic ]; @@ -442,7 +440,7 @@ export class Contract { private _wrappedEmits: { [ eventTag: string ]: (...args: Array) => void }; constructor(addressOrName: string, contractInterface: ContractInterface, signerOrProvider: Signer | Provider) { - errors.checkNew(new.target, Contract); + logger.checkNew(new.target, Contract); // @TODO: Maybe still check the addressOrName looks like a valid address or name? //address = getAddress(address); @@ -455,7 +453,7 @@ export class Contract { defineReadOnly(this, "provider", signerOrProvider); defineReadOnly(this, "signer", null); } else { - errors.throwError("invalid signer or provider", errors.INVALID_ARGUMENT, { arg: "signerOrProvider", value: signerOrProvider }); + logger.throwArgumentError("invalid signer or provider", "signerOrProvider", signerOrProvider); } defineReadOnly(this, "callStatic", { }); @@ -492,7 +490,7 @@ export class Contract { defineReadOnly(this, "addressPromise", Promise.resolve(((this.interface.constructor)).getAddress(addressOrName))); } catch (error) { // Without a provider, we cannot use ENS names - errors.throwError("provider is required to use non-address contract address", errors.INVALID_ARGUMENT, { argument: "addressOrName", value: addressOrName }); + logger.throwArgumentError("provider is required to use non-address contract address", "addressOrName", addressOrName); } } @@ -553,7 +551,7 @@ export class Contract { // Otherwise, poll for our code to be deployed this._deployedPromise = this.provider.getCode(this.address, blockTag).then((code) => { if (code === "0x") { - errors.throwError("contract not deployed", errors.UNSUPPORTED_OPERATION, { + logger.throwError("contract not deployed", Logger.errors.UNSUPPORTED_OPERATION, { contractAddress: this.address, operation: "getDeployed" }); @@ -574,14 +572,14 @@ export class Contract { fallback(overrides?: TransactionRequest): Promise { if (!this.signer) { - errors.throwError("sending a transaction require a signer", errors.UNSUPPORTED_OPERATION, { operation: "sendTransaction(fallback)" }) + logger.throwError("sending a transaction require a signer", Logger.errors.UNSUPPORTED_OPERATION, { operation: "sendTransaction(fallback)" }) } let tx: TransactionRequest = shallowCopy(overrides || {}); ["from", "to"].forEach(function(key) { if ((tx)[key] == null) { return; } - errors.throwError("cannot override " + key, errors.UNSUPPORTED_OPERATION, { operation: key }) + logger.throwError("cannot override " + key, Logger.errors.UNSUPPORTED_OPERATION, { operation: key }) }); tx.to = this.addressPromise; @@ -637,7 +635,7 @@ export class Contract { let fragment = this.interface.getEvent(eventName) if (!fragment) { - errors.throwError("unknown event - " + eventName, errors.INVALID_ARGUMENT, { argumnet: "eventName", value: eventName }); + logger.throwArgumentError("unknown event - " + eventName, "eventName", eventName); } return this._normalizeRunningEvent(new FragmentRunningEvent(this.address, this.interface, fragment)); @@ -701,7 +699,7 @@ export class Contract { private _addEventListener(runningEvent: RunningEvent, listener: Listener, once: boolean): void { if (!this.provider) { - errors.throwError("events require a provider or a signer with a provider", errors.UNSUPPORTED_OPERATION, { operation: "once" }) + logger.throwError("events require a provider or a signer with a provider", Logger.errors.UNSUPPORTED_OPERATION, { operation: "once" }) } runningEvent.addListener(listener, once); @@ -732,7 +730,7 @@ export class Contract { if (typeof(fromBlockOrBlockhash) === "string" && isHexString(fromBlockOrBlockhash, 32)) { if (toBlock != null) { - errors.throwArgumentError("cannot specify toBlock with blockhash", "toBlock", toBlock); + logger.throwArgumentError("cannot specify toBlock with blockhash", "toBlock", toBlock); } filter.blockhash = fromBlockOrBlockhash; } else { @@ -849,12 +847,12 @@ export class ContractFactory { // Make sure the final result is valid bytecode if (!isHexString(bytecodeHex) || (bytecodeHex.length % 2)) { - errors.throwArgumentError("invalid bytecode", "bytecode", bytecode); + logger.throwArgumentError("invalid bytecode", "bytecode", bytecode); } // If we have a signer, make sure it is valid if (signer && !Signer.isSigner(signer)) { - errors.throwArgumentError("invalid signer", "signer", signer); + logger.throwArgumentError("invalid signer", "signer", signer); } defineReadOnly(this, "bytecode", bytecodeHex); @@ -879,11 +877,11 @@ export class ContractFactory { // Do not allow these to be overridden in a deployment transaction ["data", "from", "to"].forEach((key) => { if ((tx)[key] == null) { return; } - errors.throwError("cannot override " + key, errors.UNSUPPORTED_OPERATION, { operation: key }) + logger.throwError("cannot override " + key, Logger.errors.UNSUPPORTED_OPERATION, { operation: key }) }); // Make sure the call matches the constructor signature - errors.checkArgumentCount(args.length, this.interface.deploy.inputs.length, " in Contract constructor"); + logger.checkArgumentCount(args.length, this.interface.deploy.inputs.length, " in Contract constructor"); // Set the data to the bytecode + the encoded constructor arguments tx.data = hexlify(concat([ @@ -920,7 +918,7 @@ export class ContractFactory { static fromSolidity(compilerOutput: any, signer?: Signer): ContractFactory { if (compilerOutput == null) { - errors.throwError("missing compiler output", errors.MISSING_ARGUMENT, { argument: "compilerOutput" }); + logger.throwError("missing compiler output", Logger.errors.MISSING_ARGUMENT, { argument: "compilerOutput" }); } if (typeof(compilerOutput) === "string") { diff --git a/packages/errors/README.md b/packages/errors/README.md index 40b419026..9ebc5c444 100644 --- a/packages/errors/README.md +++ b/packages/errors/README.md @@ -1,17 +1,6 @@ Error Generalizations and Utilities =================================== -**EXPERIMENTAL** +**DEPRECATED** -Please see the [ethers](https://github.com/ethers-io/ethers.js) repository -for more informations. - -API ---- - -`@TODO` - -License -------- - -MIT License +Please use `@ethersproject/logger` instead. diff --git a/packages/hash/package.json b/packages/hash/package.json index 3c941119b..dc69ce09d 100644 --- a/packages/hash/package.json +++ b/packages/hash/package.json @@ -8,8 +8,8 @@ }, "dependencies": { "@ethersproject/bytes": ">5.0.0-beta.0", - "@ethersproject/errors": ">5.0.0-beta.0", "@ethersproject/keccak256": ">5.0.0-beta.0", + "@ethersproject/logger": ">5.0.0-beta.0", "@ethersproject/strings": ">5.0.0-beta.0" }, "keywords": [ diff --git a/packages/hash/src.ts/index.ts b/packages/hash/src.ts/index.ts index 077369ca5..35457d437 100644 --- a/packages/hash/src.ts/index.ts +++ b/packages/hash/src.ts/index.ts @@ -1,11 +1,13 @@ "use strict"; -import * as errors from "@ethersproject/errors"; - import { Bytes, concat, hexlify } from "@ethersproject/bytes"; import { nameprep, toUtf8Bytes } from "@ethersproject/strings"; import { keccak256 } from "@ethersproject/keccak256"; +import { Logger } from "@ethersproject/logger"; +import { version } from "./_version"; +const logger = new Logger(version); + /////////////////////////////// const Zeros = new Uint8Array([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]); @@ -26,10 +28,7 @@ export function isValidName(name: string): boolean { export function namehash(name: string): string { if (typeof(name) !== "string") { - errors.throwError("invalid address - " + String(name), errors.INVALID_ARGUMENT, { - argument: "name", - value: name - }); + logger.throwArgumentError("invalid address - " + String(name), "name", name); } let result: string | Uint8Array = Zeros; diff --git a/packages/hdnode/package.json b/packages/hdnode/package.json index bfb1d7d99..d9e4eeae7 100644 --- a/packages/hdnode/package.json +++ b/packages/hdnode/package.json @@ -11,7 +11,7 @@ "@ethersproject/basex": ">5.0.0-beta.0", "@ethersproject/bignumber": ">5.0.0-beta.0", "@ethersproject/bytes": ">5.0.0-beta.0", - "@ethersproject/errors": ">5.0.0-beta.0", + "@ethersproject/logger": ">5.0.0-beta.0", "@ethersproject/pbkdf2": ">5.0.0-beta.0", "@ethersproject/properties": ">5.0.0-beta.0", "@ethersproject/sha2": ">5.0.0-beta.0", diff --git a/packages/hdnode/src.ts/index.ts b/packages/hdnode/src.ts/index.ts index 4dadf220a..a4c4cce5a 100644 --- a/packages/hdnode/src.ts/index.ts +++ b/packages/hdnode/src.ts/index.ts @@ -6,7 +6,6 @@ import { ExternallyOwnedAccount } from "@ethersproject/abstract-signer"; import { Base58 } from "@ethersproject/basex"; -import * as errors from "@ethersproject/errors"; import { arrayify, BytesLike, concat, hexDataSlice, hexZeroPad, hexlify } from "@ethersproject/bytes"; import { BigNumber } from "@ethersproject/bignumber"; import { toUtf8Bytes, UnicodeNormalizationForm } from "@ethersproject/strings"; @@ -17,6 +16,10 @@ import { computeHmac, ripemd160, sha256, SupportedAlgorithms } from "@ethersproj import { computeAddress } from "@ethersproject/transactions"; import { Wordlist, wordlists } from "@ethersproject/wordlists"; +import { Logger } from "@ethersproject/logger"; +import { version } from "./_version"; +const logger = new Logger(version); + const N = BigNumber.from("0xfffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141"); @@ -73,7 +76,7 @@ export class HDNode implements ExternallyOwnedAccount { * - fromSeed */ constructor(constructorGuard: any, privateKey: string, publicKey: string, parentFingerprint: string, chainCode: string, index: number, depth: number, mnemonic: string, path: string) { - errors.checkNew(new.target, HDNode); + logger.checkNew(new.target, HDNode); if (constructorGuard !== _constructorGuard) { throw new Error("HDNode constructor cannot be called directly"); @@ -226,10 +229,7 @@ export class HDNode implements ExternallyOwnedAccount { let bytes = Base58.decode(extendedKey); if (bytes.length !== 82 || base58check(bytes.slice(0, 78)) !== extendedKey) { - errors.throwError("invalid extended key", errors.INVALID_ARGUMENT, { - argument: "extendedKey", - value: "[REDACTED]" - }); + logger.throwArgumentError("invalid extended key", "extendedKey", "[REDACTED]"); } let depth = bytes[4]; @@ -249,10 +249,7 @@ export class HDNode implements ExternallyOwnedAccount { return new HDNode(_constructorGuard, hexlify(key.slice(1)), null, parentFingerprint, chainCode, index, depth, null, null); } - return errors.throwError("invalid extended key", errors.INVALID_ARGUMENT, { - argument: "extendedKey", - value: "[REDACTED]" - }); + return logger.throwError("invalid extended key", "extendedKey", "[REDACTED]"); } } @@ -268,7 +265,7 @@ export function mnemonicToSeed(mnemonic: string, password?: string): string { export function mnemonicToEntropy(mnemonic: string, wordlist?: Wordlist): string { if (!wordlist) { wordlist = wordlists["en"]; } - errors.checkNormalize(); + logger.checkNormalize(); let words = wordlist.split(mnemonic); if ((words.length % 3) !== 0) { throw new Error("invalid mnemonic"); } diff --git a/packages/json-wallets/package.json b/packages/json-wallets/package.json index bd53ca80a..40426d8ef 100644 --- a/packages/json-wallets/package.json +++ b/packages/json-wallets/package.json @@ -10,9 +10,9 @@ "@ethersproject/abstract-signer": ">5.0.0-beta.0", "@ethersproject/address": ">5.0.0-beta.0", "@ethersproject/bytes": ">5.0.0-beta.0", - "@ethersproject/errors": ">5.0.0-beta.0", "@ethersproject/hdnode": ">5.0.0-beta.0", "@ethersproject/keccak256": ">5.0.0-beta.0", + "@ethersproject/logger": ">5.0.0-beta.0", "@ethersproject/pbkdf2": ">5.0.0-beta.0", "@ethersproject/properties": ">5.0.0-beta.0", "@ethersproject/random": ">5.0.0-beta.0", diff --git a/packages/json-wallets/src.ts/crowdsale.ts b/packages/json-wallets/src.ts/crowdsale.ts index 2fc12d2df..e0ffdeaed 100644 --- a/packages/json-wallets/src.ts/crowdsale.ts +++ b/packages/json-wallets/src.ts/crowdsale.ts @@ -5,12 +5,15 @@ import aes from "aes-js"; import { ExternallyOwnedAccount } from "@ethersproject/abstract-signer"; import { getAddress } from "@ethersproject/address"; import { arrayify, Bytes } from "@ethersproject/bytes"; -import * as errors from "@ethersproject/errors"; import { keccak256 } from "@ethersproject/keccak256"; import { pbkdf2 } from "@ethersproject/pbkdf2"; import { toUtf8Bytes } from "@ethersproject/strings"; import { Description } from "@ethersproject/properties"; +import { Logger } from "@ethersproject/logger"; +import { version } from "./_version"; +const logger = new Logger(version); + import { getPassword, looseArrayify, searchPath } from "./utils"; export class CrowdsaleAccount extends Description implements ExternallyOwnedAccount { @@ -38,10 +41,7 @@ export function decrypt(json: string, password: Bytes | string): ExternallyOwned // Encrypted Seed let encseed = looseArrayify(searchPath(data, "encseed")); if (!encseed || (encseed.length % 16) !== 0) { - errors.throwError("invalid encseed", errors.INVALID_ARGUMENT, { - argument: "json", - value: json - }); + logger.throwArgumentError("invalid encseed", "json", json); } let key = arrayify(pbkdf2(password, password, 2000, 32, "sha256")).slice(0, 16); diff --git a/packages/logger/.npmignore b/packages/logger/.npmignore new file mode 100644 index 000000000..a3bf689c5 --- /dev/null +++ b/packages/logger/.npmignore @@ -0,0 +1,4 @@ +# We do not need the TypeScipt source in deployments +tsconfig.json +src.ts/ + diff --git a/packages/logger/README.md b/packages/logger/README.md new file mode 100644 index 000000000..911a0f8ab --- /dev/null +++ b/packages/logger/README.md @@ -0,0 +1,9 @@ +Logger +====== + +@TODO: + +License +------- + +MIT License. diff --git a/packages/logger/package.json b/packages/logger/package.json new file mode 100644 index 000000000..0cdc0d34a --- /dev/null +++ b/packages/logger/package.json @@ -0,0 +1,19 @@ +{ + "name": "@ethersproject/logger", + "version": "5.0.0-beta.127", + "description": "Logger utility functions for ethers.", + "main": "index.js", + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "keywords": [ + "Ethereum", + "ethers" + ], + "author": "Richard Moore ", + "license": "MIT", + "publishConfig": { + "access": "public" + }, + "tarballHash": "0xd285051d17a97638f3840564e5121f34ac194907818e337e0a1339784d8daeff" +} diff --git a/packages/logger/src.ts/_version.ts b/packages/logger/src.ts/_version.ts new file mode 100644 index 000000000..4195fb7ad --- /dev/null +++ b/packages/logger/src.ts/_version.ts @@ -0,0 +1,2 @@ +export const version = "willbeaddedlater"; + diff --git a/packages/logger/src.ts/index.ts b/packages/logger/src.ts/index.ts new file mode 100644 index 000000000..5facdf695 --- /dev/null +++ b/packages/logger/src.ts/index.ts @@ -0,0 +1,313 @@ +"use strict"; + +let _permanentCensorErrors = false; +let _censorErrors = false; + +const LogLevels: { [ name: string ]: number } = { debug: 1, "default": 2, info: 2, warn: 3, error: 4, off: 5 }; +let LogLevel = LogLevels["default"]; + +import { version } from "./_version"; + +let _globalLogger: Logger = null; + +export type LogLevel = "DEBUG" | "INFO" | "WARNING" | "ERROR" | "OFF"; + +function _checkNormalize(): string { + try { + let missing: Array = [ ]; + + // Make sure all forms of normalization are supported + ["NFD", "NFC", "NFKD", "NFKC"].forEach((form) => { + try { + if ("test".normalize(form) !== "test") { + throw new Error("bad normalize"); + }; + } catch(error) { + missing.push(form); + } + }); + + if (missing.length) { + throw new Error("missing " + missing.join(", ")); + } + + if (String.fromCharCode(0xe9).normalize("NFD") !== String.fromCharCode(0x65, 0x0301)) { + throw new Error("broken implementation") + } + } catch (error) { + return error.message; + } + + return null; +} + +let _normalizeError = _checkNormalize(); + +export class Logger { + readonly version: string; + + static errors = { + + /////////////////// + // Generic Errors + + // Unknown Error + UNKNOWN_ERROR: "UNKNOWN_ERROR", + + // Not Implemented + NOT_IMPLEMENTED: "NOT_IMPLEMENTED", + + // Unsupported Operation + // - operation + UNSUPPORTED_OPERATION: "UNSUPPORTED_OPERATION", + + // Network Error (i.e. Ethereum Network, such as an invalid chain ID) + NETWORK_ERROR: "NETWORK_ERROR", + + // Some sort of bad response from the server + SERVER_ERROR: "SERVER_ERROR", + + // Timeout + TIMEOUT: "TIMEOUT", + + /////////////////// + // Operational Errors + + // Buffer Overrun + BUFFER_OVERRUN: "BUFFER_OVERRUN", + + // Numeric Fault + // - operation: the operation being executed + // - fault: the reason this faulted + NUMERIC_FAULT: "NUMERIC_FAULT", + + + /////////////////// + // Argument Errors + + // Missing new operator to an object + // - name: The name of the class + MISSING_NEW: "MISSING_NEW", + + // 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 + INVALID_ARGUMENT: "INVALID_ARGUMENT", + + // Missing argument to a function: + // - count: The number of arguments received + // - expectedCount: The number of arguments expected + MISSING_ARGUMENT: "MISSING_ARGUMENT", + + // Too many arguments + // - count: The number of arguments received + // - expectedCount: The number of arguments expected + UNEXPECTED_ARGUMENT: "UNEXPECTED_ARGUMENT", + + + /////////////////// + // 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)") + CALL_EXCEPTION: "CALL_EXCEPTION", + + // Insufficien funds (< value + gasLimit * gasPrice) + // - transaction: the transaction attempted + INSUFFICIENT_FUNDS: "INSUFFICIENT_FUNDS", + + // Nonce has already been used + // - transaction: the transaction attempted + NONCE_EXPIRED: "NONCE_EXPIRED", + + // The replacement fee for the transaction is too low + // - transaction: the transaction attempted + REPLACEMENT_UNDERPRICED: "REPLACEMENT_UNDERPRICED", + + // The gas limit could not be estimated + // - transaction: the transaction passed to estimateGas + UNPREDICTABLE_GAS_LIMIT: "UNPREDICTABLE_GAS_LIMIT", + }; + + static levels: { [ name: string ]: LogLevel } = { + DEBUG: "DEBUG", + INFO: "INFO", + WARNING: "WARNING", + ERROR: "ERROR", + OFF: "OFF" + }; + + constructor(version: string) { + Object.defineProperty(this, "version", { + enumerable: true, + value: version, + writable: false + }); + } + + setLogLevel(logLevel: LogLevel): void { + let level = LogLevels[logLevel]; + if (level == null) { + this.warn("invliad log level - " + logLevel); + return; + } + LogLevel = level; + } + + _log(logLevel: LogLevel, args: Array): void { + if (LogLevel > LogLevels[logLevel]) { return; } + console.log.apply(console, args); + } + + debug(...args: Array): void { + this._log(Logger.levels.DEBUG, args); + } + + info(...args: Array): void { + this._log(Logger.levels.INFO, args); + } + + warn(...args: Array): void { + this._log(Logger.levels.WARNING, args); + } + + makeError(message: string, code?: string, params?: any): Error { + if (_censorErrors) { + return new Error("unknown error"); + } + + if (!code) { code = Logger.errors.UNKNOWN_ERROR; } + if (!params) { params = {}; } + + let messageDetails: Array = []; + Object.keys(params).forEach((key) => { + try { + messageDetails.push(key + "=" + JSON.stringify(params[key])); + } catch (error) { + messageDetails.push(key + "=" + JSON.stringify(params[key].toString())); + } + }); + messageDetails.push("version=" + this.version); + + let reason = message; + if (messageDetails.length) { + message += " (" + messageDetails.join(", ") + ")"; + } + + // @TODO: Any?? + let error: any = new Error(message); + error.reason = reason; + error.code = code + + Object.keys(params).forEach(function(key) { + error[key] = params[key]; + }); + + return error; + } + + throwError(message: string, code?: string, params?: any): never { + throw this.makeError(message, code, params); + } + + throwArgumentError(message: string, name: string, value: any): never { + return this.throwError(message, Logger.errors.INVALID_ARGUMENT, { + argument: name, + value: value + }); + } + + checkNormalize(message?: string): void { + if (message == null) { message = "platform missing String.prototype.normalize"; } + if (_normalizeError) { + this.throwError("platform missing String.prototype.normalize", Logger.errors.UNSUPPORTED_OPERATION, { + operation: "String.prototype.normalize", form: _normalizeError + }); + } + } + + checkSafeUint53(value: number, message?: string): void { + if (typeof(value) !== "number") { return; } + + if (message == null) { message = "value not safe"; } + + if (value < 0 || value >= 0x1fffffffffffff) { + this.throwError(message, Logger.errors.NUMERIC_FAULT, { + operation: "checkSafeInteger", + fault: "out-of-safe-range", + value: value + }); + } + + if (value % 1) { + this.throwError(message, Logger.errors.NUMERIC_FAULT, { + operation: "checkSafeInteger", + fault: "non-integer", + value: value + }); + } + } + + checkArgumentCount(count: number, expectedCount: number, message?: string): void { + if (message) { + message = ": " + message; + } else { + message = ""; + } + + if (count < expectedCount) { + this.throwError("missing argument" + message, Logger.errors.MISSING_ARGUMENT, { + count: count, + expectedCount: expectedCount + }); + } + + if (count > expectedCount) { + this.throwError("too many arguments" + message, Logger.errors.UNEXPECTED_ARGUMENT, { + count: count, + expectedCount: expectedCount + }); + } + } + + checkNew(target: any, kind: any): void { + if (target === Object || target == null) { + this.throwError("missing new", Logger.errors.MISSING_NEW, { name: kind.name }); + } + } + + checkAbstract(target: any, kind: any): void { + if (target === kind) { + this.throwError( + "cannot instantiate abstract class " + JSON.stringify(kind.name) + " directly; use a sub-class", + Logger.errors.UNSUPPORTED_OPERATION, + { name: target.name, operation: "new" } + ); + } else if (target === Object || target == null) { + this.throwError("missing new", Logger.errors.MISSING_NEW, { name: kind.name }); + } + } + + static globalLogger(): Logger { + if (!_globalLogger) { _globalLogger = new Logger(version); } + return _globalLogger; + } + + static setCensorship(censorship: boolean, permanent?: boolean): void { + if (_permanentCensorErrors) { + if (!censorship) { return; } + this.globalLogger().throwError("error censorship permanent", Logger.errors.UNSUPPORTED_OPERATION, { + operation: "setCensorship" + }); + } + + _censorErrors = !!censorship; + _permanentCensorErrors = !!permanent; + } +} diff --git a/packages/logger/tsconfig.json b/packages/logger/tsconfig.json new file mode 100644 index 000000000..f8b22b29e --- /dev/null +++ b/packages/logger/tsconfig.json @@ -0,0 +1,12 @@ +{ + "extends": "../../tsconfig.package.json", + "compilerOptions": { + "rootDir": "./src.ts", + "outDir": "./" + }, + "include": [ + "./src.ts/*" + ], + "exclude": [ ] +} + diff --git a/packages/networks/package.json b/packages/networks/package.json index 737e01001..970e1f20e 100644 --- a/packages/networks/package.json +++ b/packages/networks/package.json @@ -7,7 +7,7 @@ "test": "echo \"Error: no test specified\" && exit 1" }, "dependencies": { - "@ethersproject/errors": ">5.0.0-beta.0" + "@ethersproject/logger": ">5.0.0-beta.0" }, "keywords": [ "Ethereum", diff --git a/packages/networks/src.ts/index.ts b/packages/networks/src.ts/index.ts index 92e079617..9c7ffe6f7 100644 --- a/packages/networks/src.ts/index.ts +++ b/packages/networks/src.ts/index.ts @@ -1,6 +1,8 @@ "use strict"; -import * as errors from "@ethersproject/errors"; +import { Logger } from "@ethersproject/logger"; +import { version } from "./_version"; +const logger = new Logger(version); import { Network, Networkish } from "./types"; @@ -167,14 +169,14 @@ export function getNetwork(network: Networkish): Network { // Not a standard network; check that it is a valid network in general if (!standard) { if (typeof(network.chainId) !== "number") { - errors.throwError("invalid network chainId", errors.INVALID_ARGUMENT, { arg: "network", value: network }); + logger.throwArgumentError("invalid network chainId", "network", network); } return network; } // Make sure the chainId matches the expected network chainId (or is 0; disable EIP-155) if (network.chainId !== 0 && network.chainId !== standard.chainId) { - errors.throwError("network chainId mismatch", errors.INVALID_ARGUMENT, { arg: "network", value: network }); + logger.throwArgumentError("network chainId mismatch", "network", network); } // Standard Network (allow overriding the ENS address) diff --git a/packages/properties/package.json b/packages/properties/package.json index 5dd4cf17d..3569cefb5 100644 --- a/packages/properties/package.json +++ b/packages/properties/package.json @@ -9,7 +9,7 @@ "test": "echo \"Error: no test specified\" && exit 1" }, "dependencies": { - "@ethersproject/errors": ">5.0.0-beta.0" + "@ethersproject/logger": ">5.0.0-beta.0" }, "keywords": [ "Ethereum", diff --git a/packages/properties/src.ts/index.ts b/packages/properties/src.ts/index.ts index dcdbc143f..90732cd5e 100644 --- a/packages/properties/src.ts/index.ts +++ b/packages/properties/src.ts/index.ts @@ -1,6 +1,8 @@ "use strict"; -import * as errors from "@ethersproject/errors"; +import { Logger } from "@ethersproject/logger"; +import { version } from "./_version"; +const logger = new Logger(version); export function defineReadOnly(object: any, name: string, value: any): void { Object.defineProperty(object, name, { @@ -46,19 +48,12 @@ export function resolveProperties(object: any): Promise { export function checkProperties(object: any, properties: { [ name: string ]: boolean }): void { if (!object || typeof(object) !== "object") { - errors.throwError("invalid object", errors.INVALID_ARGUMENT, { - argument: "object", - value: object - }); + logger.throwArgumentError("invalid object", "object", object); } Object.keys(object).forEach((key) => { if (!properties[key]) { - errors.throwError("invalid object key - " + key, errors.INVALID_ARGUMENT, { - argument: "transaction", - value: object, - key: key - }); + logger.throwArgumentError("invalid object key - " + key, "transaction:" + key, object); } }); } diff --git a/packages/providers/package.json b/packages/providers/package.json index 26a1f26b5..d2a0d32b7 100644 --- a/packages/providers/package.json +++ b/packages/providers/package.json @@ -1,7 +1,7 @@ { "name": "@ethersproject/providers", "version": "5.0.0-beta.136", - "description": "Error utility functions for ethers.", + "description": "Ethereum Providers for ethers.", "main": "index.js", "browser": { "net": "./browser-net.js", @@ -17,8 +17,8 @@ "@ethersproject/bignumber": ">5.0.0-beta.0", "@ethersproject/bytes": ">5.0.0-beta.0", "@ethersproject/constants": ">5.0.0-beta.0", - "@ethersproject/errors": ">5.0.0-beta.0", "@ethersproject/hash": ">5.0.0-beta.0", + "@ethersproject/logger": ">5.0.0-beta.0", "@ethersproject/networks": ">5.0.0-beta.0", "@ethersproject/properties": ">5.0.0-beta.0", "@ethersproject/random": ">5.0.0-beta.0", diff --git a/packages/providers/src.ts/alchemy-provider.ts b/packages/providers/src.ts/alchemy-provider.ts index d7fd4faca..49c12ca29 100644 --- a/packages/providers/src.ts/alchemy-provider.ts +++ b/packages/providers/src.ts/alchemy-provider.ts @@ -1,8 +1,11 @@ "use strict"; -import * as errors from "@ethersproject/errors"; import { Network } from "@ethersproject/networks"; +import { Logger } from "@ethersproject/logger"; +import { version } from "./_version"; +const logger = new Logger(version); + import { UrlJsonRpcProvider } from "./url-json-rpc-provider"; // This key was provided to ethers.js by Alchemy to be used by the @@ -36,7 +39,7 @@ export class AlchemyProvider extends UrlJsonRpcProvider { host = "eth-kovan.alchemyapi.io/jsonrpc/"; break; default: - errors.throwArgumentError("unsupported network", "network", arguments[0]); + logger.throwArgumentError("unsupported network", "network", arguments[0]); } return ("https:/" + "/" + host + apiKey); diff --git a/packages/providers/src.ts/base-provider.ts b/packages/providers/src.ts/base-provider.ts index 73f165f2f..68dec9373 100644 --- a/packages/providers/src.ts/base-provider.ts +++ b/packages/providers/src.ts/base-provider.ts @@ -6,7 +6,6 @@ import { } from "@ethersproject/abstract-provider"; import { BigNumber, BigNumberish } from "@ethersproject/bignumber"; import { arrayify, hexDataLength, hexlify, hexValue, isHexString } from "@ethersproject/bytes"; -import * as errors from "@ethersproject/errors"; import { namehash } from "@ethersproject/hash"; import { getNetwork, Network, Networkish } from "@ethersproject/networks"; import { defineReadOnly, getStatic, resolveProperties } from "@ethersproject/properties"; @@ -14,6 +13,10 @@ import { Transaction } from "@ethersproject/transactions"; import { toUtf8String } from "@ethersproject/strings"; import { poll } from "@ethersproject/web"; +import { Logger } from "@ethersproject/logger"; +import { version } from "./_version"; +const logger = new Logger(version); + import { Formatter } from "./formatter"; @@ -23,7 +26,7 @@ import { Formatter } from "./formatter"; function checkTopic(topic: string): string { if (topic == null) { return "null"; } if (hexDataLength(topic) !== 32) { - errors.throwArgumentError("invalid topic", "topic", topic); + logger.throwArgumentError("invalid topic", "topic", topic); } return topic.toLowerCase(); } @@ -78,7 +81,7 @@ function getEventTag(eventName: EventType): string { return "filter:*:" + serializeTopics(eventName); } else if (ForkEvent.isForkEvent(eventName)) { - errors.warn("not implemented"); + logger.warn("not implemented"); throw new Error("not implemented"); } else if (eventName && typeof(eventName) === "object") { @@ -171,7 +174,7 @@ export class BaseProvider extends Provider { ready: Promise; constructor(network: Networkish | Promise) { - errors.checkNew(new.target, Provider); + logger.checkNew(new.target, Provider); super(); @@ -193,7 +196,7 @@ export class BaseProvider extends Provider { defineReadOnly(this, "ready", Promise.resolve(this._network)); } else { - errors.throwError("invalid network", errors.INVALID_ARGUMENT, { arg: "network", value: network }); + logger.throwArgumentError("invalid network", "network", network); } } @@ -499,7 +502,7 @@ export class BaseProvider extends Provider { // Check the hash we expect is the same as the hash the server reported if (hash != null && tx.hash !== hash) { - errors.throwError("Transaction hash mismatch from Provider.sendTransaction.", errors.UNKNOWN_ERROR, { expectedHash: tx.hash, returnedHash: hash }); + logger.throwError("Transaction hash mismatch from Provider.sendTransaction.", Logger.errors.UNKNOWN_ERROR, { expectedHash: tx.hash, returnedHash: hash }); } // @TODO: (confirmations? number, timeout? number) @@ -519,7 +522,7 @@ export class BaseProvider extends Provider { this._emitted["t:" + tx.hash] = receipt.blockNumber; if (receipt.status === 0) { - errors.throwError("transaction failed", errors.CALL_EXCEPTION, { + logger.throwError("transaction failed", Logger.errors.CALL_EXCEPTION, { transactionHash: tx.hash, transaction: tx }); @@ -606,7 +609,7 @@ export class BaseProvider extends Provider { _getAddress(addressOrName: string | Promise): Promise { return this.resolveName(addressOrName).then((address) => { if (address == null) { - errors.throwError("ENS name not configured", errors.UNSUPPORTED_OPERATION, { + logger.throwError("ENS name not configured", Logger.errors.UNSUPPORTED_OPERATION, { operation: `resolveName(${ JSON.stringify(addressOrName) })` }); } @@ -637,7 +640,7 @@ export class BaseProvider extends Provider { blockNumber = parseInt(params.blockTag.substring(2), 16); } } catch (error) { - errors.throwError("invalid block hash or block tag", "blockHashOrBlockTag", blockHashOrBlockTag); + logger.throwArgumentError("invalid block hash or block tag", "blockHashOrBlockTag", blockHashOrBlockTag); } } @@ -782,7 +785,7 @@ export class BaseProvider extends Provider { if (typeof(blockTag) === "number" && blockTag < 0) { if (blockTag % 1) { - errors.throwArgumentError("invalid BlockTag", "blockTag", blockTag); + logger.throwArgumentError("invalid BlockTag", "blockTag", blockTag); } return this._getFastBlockNumber().then((bn) => { @@ -802,9 +805,9 @@ export class BaseProvider extends Provider { // No ENS... if (!network.ensAddress) { - errors.throwError( + logger.throwError( "network does support ENS", - errors.UNSUPPORTED_OPERATION, + Logger.errors.UNSUPPORTED_OPERATION, { operation: "ENS", network: network.name } ); } @@ -883,7 +886,7 @@ export class BaseProvider extends Provider { } perform(method: string, params: any): Promise { - return errors.throwError(method + " not implemented", errors.NOT_IMPLEMENTED, { operation: method }); + return logger.throwError(method + " not implemented", Logger.errors.NOT_IMPLEMENTED, { operation: method }); } _startPending(): void { diff --git a/packages/providers/src.ts/etherscan-provider.ts b/packages/providers/src.ts/etherscan-provider.ts index c5b840e07..002bf9683 100644 --- a/packages/providers/src.ts/etherscan-provider.ts +++ b/packages/providers/src.ts/etherscan-provider.ts @@ -2,11 +2,14 @@ import { BlockTag, TransactionRequest, TransactionResponse } from "@ethersproject/abstract-provider"; import { hexlify, hexValue } from "@ethersproject/bytes"; -import * as errors from "@ethersproject/errors"; import { Networkish } from "@ethersproject/networks"; import { deepCopy, defineReadOnly } from "@ethersproject/properties"; import { fetchJson } from "@ethersproject/web"; +import { Logger } from "@ethersproject/logger"; +import { version } from "./_version"; +const logger = new Logger(version); + import { BaseProvider } from "./base-provider"; @@ -72,7 +75,7 @@ export class EtherscanProvider extends BaseProvider{ readonly baseUrl: string; readonly apiKey: string; constructor(network?: Networkish, apiKey?: string) { - errors.checkNew(new.target, EtherscanProvider); + logger.checkNew(new.target, EtherscanProvider); super(network); @@ -169,15 +172,15 @@ export class EtherscanProvider extends BaseProvider{ if (error.responseText) { // "Insufficient funds. The account you tried to send transaction from does not have enough funds. Required 21464000000000 and got: 0" if (error.responseText.toLowerCase().indexOf("insufficient funds") >= 0) { - errors.throwError("insufficient funds", errors.INSUFFICIENT_FUNDS, { }); + logger.throwError("insufficient funds", Logger.errors.INSUFFICIENT_FUNDS, { }); } // "Transaction with the same hash was already imported." if (error.responseText.indexOf("same hash was already imported") >= 0) { - errors.throwError("nonce has already been used", errors.NONCE_EXPIRED, { }); + logger.throwError("nonce has already been used", Logger.errors.NONCE_EXPIRED, { }); } // "Transaction gas price is too low. There is another transaction with same nonce in the queue. Try increasing the gas price or incrementing the nonce." if (error.responseText.indexOf("another transaction with same nonce") >= 0) { - errors.throwError("replacement fee too low", errors.REPLACEMENT_UNDERPRICED, { }); + logger.throwError("replacement fee too low", Logger.errors.REPLACEMENT_UNDERPRICED, { }); } } throw error; diff --git a/packages/providers/src.ts/fallback-provider.ts b/packages/providers/src.ts/fallback-provider.ts index 7403086ad..3b60040a9 100644 --- a/packages/providers/src.ts/fallback-provider.ts +++ b/packages/providers/src.ts/fallback-provider.ts @@ -1,10 +1,13 @@ "use strict"; -import * as errors from "@ethersproject/errors"; import { Network } from "@ethersproject/networks"; import { shuffled } from "@ethersproject/random"; import { deepCopy, defineReadOnly } from "@ethersproject/properties"; +import { Logger } from "@ethersproject/logger"; +import { version } from "./_version"; +const logger = new Logger(version); + import { BaseProvider } from "./base-provider"; function now() { return (new Date()).getTime(); } @@ -37,11 +40,7 @@ function checkNetworks(networks: Array): boolean { ((check.ensAddress === network.ensAddress) || (check.ensAddress == null && network.ensAddress == null))) { return; } - errors.throwError( - "provider mismatch", - errors.INVALID_ARGUMENT, - { arg: "networks", value: networks } - ); + logger.throwArgumentError("provider mismatch", "networks", networks); }); return result; @@ -87,20 +86,20 @@ export class FallbackProvider extends BaseProvider { readonly quorum: number; constructor(providers: Array, quorum?: number, weights?: Array) { - errors.checkNew(new.target, FallbackProvider); + logger.checkNew(new.target, FallbackProvider); if (providers.length === 0) { - errors.throwArgumentError("missing providers", "providers", providers); + logger.throwArgumentError("missing providers", "providers", providers); } if (weights != null && weights.length !== providers.length) { - errors.throwArgumentError("too many weights", "weights", weights); + logger.throwArgumentError("too many weights", "weights", weights); } else if (!weights) { weights = providers.map((p) => 1); } else { weights.forEach((w) => { if (w % 1 || w > 512 || w < 1) { - errors.throwArgumentError("invalid weight; must be integer in [1, 512]", "weights", weights); + logger.throwArgumentError("invalid weight; must be integer in [1, 512]", "weights", weights); } }); } @@ -111,7 +110,7 @@ export class FallbackProvider extends BaseProvider { quorum = total / 2; } else { if (quorum > total) { - errors.throwArgumentError("quorum will always fail; larger than total weight", "quorum", quorum); + logger.throwArgumentError("quorum will always fail; larger than total weight", "quorum", quorum); } } @@ -125,7 +124,7 @@ export class FallbackProvider extends BaseProvider { // The network won't be known until all child providers know let ready = Promise.all(providers.map((p) => p.getNetwork())).then((networks) => { if (!checkNetworks(networks)) { - errors.throwError("getNetwork returned null", errors.UNKNOWN_ERROR, { }) + logger.throwError("getNetwork returned null", Logger.errors.UNKNOWN_ERROR) } return networks[0]; }); diff --git a/packages/providers/src.ts/formatter.ts b/packages/providers/src.ts/formatter.ts index 6e378b43c..e550311be 100644 --- a/packages/providers/src.ts/formatter.ts +++ b/packages/providers/src.ts/formatter.ts @@ -5,10 +5,13 @@ import { getAddress, getContractAddress } from "@ethersproject/address"; import { BigNumber } from "@ethersproject/bignumber"; import { hexDataLength, hexDataSlice, hexValue, hexZeroPad, isHexString } from "@ethersproject/bytes"; import { AddressZero } from "@ethersproject/constants"; -import * as errors from "@ethersproject/errors"; import { shallowCopy } from "@ethersproject/properties"; import { parse as parseTransaction } from "@ethersproject/transactions"; +import { Logger } from "@ethersproject/logger"; +import { version } from "./_version"; +const logger = new Logger(version); + export type FormatFunc = (value: any) => any; export type FormatFuncs = { [ key: string ]: FormatFunc }; @@ -28,7 +31,7 @@ export class Formatter { readonly formats: Formats; constructor() { - errors.checkNew(new.target, Formatter); + logger.checkNew(new.target, Formatter); this.formats = this.getDefaultFormats(); } @@ -188,10 +191,7 @@ export class Formatter { return value.toLowerCase(); } } - return errors.throwError("invalid hash", errors.INVALID_ARGUMENT, { - argument: "value", - value: value - }); + return logger.throwArgumentError("invalid hash", "value", value); } data(value: any, strict?: boolean): string { @@ -239,10 +239,7 @@ export class Formatter { hash(value: any, strict?: boolean): string { let result = this.hex(value, strict); if (hexDataLength(result) !== 32) { - return errors.throwError("invalid hash", errors.INVALID_ARGUMENT, { - argument: "value", - value: value - }); + return logger.throwArgumentError("invalid hash", "value", value); } return result; } diff --git a/packages/providers/src.ts/infura-provider.ts b/packages/providers/src.ts/infura-provider.ts index 9d00dfbf9..f86e9891d 100644 --- a/packages/providers/src.ts/infura-provider.ts +++ b/packages/providers/src.ts/infura-provider.ts @@ -1,8 +1,11 @@ "use strict"; -import * as errors from "@ethersproject/errors"; import { Network } from "@ethersproject/networks"; +import { Logger } from "@ethersproject/logger"; +import { version } from "./_version"; +const logger = new Logger(version); + import { UrlJsonRpcProvider } from "./url-json-rpc-provider"; @@ -35,7 +38,7 @@ export class InfuraProvider extends UrlJsonRpcProvider { host = "goerli.infura.io"; break; default: - errors.throwError("unsupported network", errors.INVALID_ARGUMENT, { + logger.throwError("unsupported network", Logger.errors.INVALID_ARGUMENT, { argument: "network", value: network }); diff --git a/packages/providers/src.ts/ipc-provider.ts b/packages/providers/src.ts/ipc-provider.ts index a0b44d38c..5bb279e3a 100644 --- a/packages/providers/src.ts/ipc-provider.ts +++ b/packages/providers/src.ts/ipc-provider.ts @@ -2,10 +2,13 @@ import net from "net"; -import * as errors from "@ethersproject/errors"; import { defineReadOnly } from "@ethersproject/properties"; import { Networkish } from "@ethersproject/networks"; +import { Logger } from "@ethersproject/logger"; +import { version } from "./_version"; +const logger = new Logger(version); + import { JsonRpcProvider } from "./json-rpc-provider"; @@ -13,10 +16,10 @@ export class IpcProvider extends JsonRpcProvider { readonly path: string; constructor(path: string, network?: Networkish) { - errors.checkNew(new.target, IpcProvider); + logger.checkNew(new.target, IpcProvider); if (path == null) { - errors.throwError("missing path", errors.MISSING_ARGUMENT, { arg: "path" }); + logger.throwError("missing path", Logger.errors.MISSING_ARGUMENT, { arg: "path" }); } super("ipc://" + path, network); diff --git a/packages/providers/src.ts/json-rpc-provider.ts b/packages/providers/src.ts/json-rpc-provider.ts index 38bf91817..6a33789f3 100644 --- a/packages/providers/src.ts/json-rpc-provider.ts +++ b/packages/providers/src.ts/json-rpc-provider.ts @@ -6,12 +6,15 @@ import { Provider, TransactionRequest, TransactionResponse } from "@ethersprojec import { Signer } from "@ethersproject/abstract-signer"; import { BigNumber } from "@ethersproject/bignumber"; import { Bytes, hexlify, hexValue } from "@ethersproject/bytes"; -import * as errors from "@ethersproject/errors"; import { getNetwork, Network, Networkish } from "@ethersproject/networks"; import { checkProperties, deepCopy, defineReadOnly, resolveProperties, shallowCopy } from "@ethersproject/properties"; import { toUtf8Bytes } from "@ethersproject/strings"; import { ConnectionInfo, fetchJson, poll } from "@ethersproject/web"; +import { Logger } from "@ethersproject/logger"; +import { version } from "./_version"; +const logger = new Logger(version); + import { BaseProvider } from "./base-provider"; @@ -48,7 +51,7 @@ export class JsonRpcSigner extends Signer { _address: string; constructor(constructorGuard: any, provider: JsonRpcProvider, addressOrIndex?: string | number) { - errors.checkNew(new.target, JsonRpcSigner); + logger.checkNew(new.target, JsonRpcSigner); super(); @@ -69,12 +72,12 @@ export class JsonRpcSigner extends Signer { defineReadOnly(this, "_address", null); } else { - errors.throwError("invalid address or index", errors.INVALID_ARGUMENT, { argument: "addressOrIndex", value: addressOrIndex }); + logger.throwArgumentError("invalid address or index", "addressOrIndex", addressOrIndex); } } connect(provider: Provider): JsonRpcSigner { - return errors.throwError("cannot alter JSON-RPC Signer connection", errors.UNSUPPORTED_OPERATION, { + return logger.throwError("cannot alter JSON-RPC Signer connection", Logger.errors.UNSUPPORTED_OPERATION, { operation: "connect" }); } @@ -90,7 +93,9 @@ export class JsonRpcSigner extends Signer { return this.provider.send("eth_accounts", []).then((accounts) => { if (accounts.length <= this._index) { - errors.throwError("unknown account #" + this._index, errors.UNSUPPORTED_OPERATION, { operation: "getAddress" }); + logger.throwError("unknown account #" + this._index, Logger.errors.UNSUPPORTED_OPERATION, { + operation: "getAddress" + }); } return this.provider.formatter.address(accounts[this._index]) }); @@ -126,17 +131,17 @@ export class JsonRpcSigner extends Signer { if (error.responseText) { // See: JsonRpcProvider.sendTransaction (@TODO: Expose a ._throwError??) if (error.responseText.indexOf("insufficient funds") >= 0) { - errors.throwError("insufficient funds", errors.INSUFFICIENT_FUNDS, { + logger.throwError("insufficient funds", Logger.errors.INSUFFICIENT_FUNDS, { transaction: tx }); } if (error.responseText.indexOf("nonce too low") >= 0) { - errors.throwError("nonce has already been used", errors.NONCE_EXPIRED, { + logger.throwError("nonce has already been used", Logger.errors.NONCE_EXPIRED, { transaction: tx }); } if (error.responseText.indexOf("replacement transaction underpriced") >= 0) { - errors.throwError("replacement fee too low", errors.REPLACEMENT_UNDERPRICED, { + logger.throwError("replacement fee too low", Logger.errors.REPLACEMENT_UNDERPRICED, { transaction: tx }); } @@ -147,7 +152,7 @@ export class JsonRpcSigner extends Signer { } signTransaction(transaction: TransactionRequest): Promise { - return errors.throwError("signing transactions is unsupported", errors.UNSUPPORTED_OPERATION, { + return logger.throwError("signing transactions is unsupported", Logger.errors.UNSUPPORTED_OPERATION, { operation: "signTransaction" }); } @@ -214,7 +219,7 @@ export class JsonRpcProvider extends BaseProvider { _nextId: number; constructor(url?: ConnectionInfo | string, network?: Networkish) { - errors.checkNew(new.target, JsonRpcProvider); + logger.checkNew(new.target, JsonRpcProvider); // One parameter, but it is a network name, so swap it with the URL if (typeof(url) === "string") { @@ -239,7 +244,7 @@ export class JsonRpcProvider extends BaseProvider { this.send("net_version", [ ]).then((result) => { resolve(getNetwork(BigNumber.from(result).toNumber())); }).catch((error) => { - reject(errors.makeError("could not detect network", errors.NETWORK_ERROR, { })); + reject(logger.makeError("could not detect network", Logger.errors.NETWORK_ERROR)); }); }); }); @@ -325,15 +330,15 @@ export class JsonRpcProvider extends BaseProvider { if (error.responseText) { // "insufficient funds for gas * price + value" if (error.responseText.indexOf("insufficient funds") > 0) { - errors.throwError("insufficient funds", errors.INSUFFICIENT_FUNDS, { }); + logger.throwError("insufficient funds", Logger.errors.INSUFFICIENT_FUNDS, { }); } // "nonce too low" if (error.responseText.indexOf("nonce too low") > 0) { - errors.throwError("nonce has already been used", errors.NONCE_EXPIRED, { }); + logger.throwError("nonce has already been used", Logger.errors.NONCE_EXPIRED, { }); } // "replacement transaction underpriced" if (error.responseText.indexOf("replacement transaction underpriced") > 0) { - errors.throwError("replacement fee too low", errors.REPLACEMENT_UNDERPRICED, { }); + logger.throwError("replacement fee too low", Logger.errors.REPLACEMENT_UNDERPRICED, { }); } } throw error; @@ -369,7 +374,7 @@ export class JsonRpcProvider extends BaseProvider { break; } - return errors.throwError(method + " not implemented", errors.NOT_IMPLEMENTED, { operation: method }); + return logger.throwError(method + " not implemented", Logger.errors.NOT_IMPLEMENTED, { operation: method }); } _startPending(): void { diff --git a/packages/providers/src.ts/nodesmith-provider.ts b/packages/providers/src.ts/nodesmith-provider.ts index 55c2fc132..274659f20 100644 --- a/packages/providers/src.ts/nodesmith-provider.ts +++ b/packages/providers/src.ts/nodesmith-provider.ts @@ -1,10 +1,11 @@ "use strict"; -import * as errors from "@ethersproject/errors"; - import { Network } from "@ethersproject/networks"; import { UrlJsonRpcProvider } from "./url-json-rpc-provider"; +import { Logger } from "@ethersproject/logger"; +import { version } from "./_version"; +const logger = new Logger(version); // Special API key provided by Nodesmith for ethers.js const defaultApiKey = "ETHERS_JS_SHARED"; @@ -34,7 +35,7 @@ export class NodesmithProvider extends UrlJsonRpcProvider { host = "https://ethereum.api.nodesmith.io/v1/kovan/jsonrpc"; break; default: - errors.throwArgumentError("unsupported network", "network", arguments[0]); + logger.throwArgumentError("unsupported network", "network", arguments[0]); } return (host + "?apiKey=" + apiKey); diff --git a/packages/providers/src.ts/url-json-rpc-provider.ts b/packages/providers/src.ts/url-json-rpc-provider.ts index 70f99278c..d5e0f63c7 100644 --- a/packages/providers/src.ts/url-json-rpc-provider.ts +++ b/packages/providers/src.ts/url-json-rpc-provider.ts @@ -1,16 +1,19 @@ "use strict"; -import * as errors from "@ethersproject/errors"; import { getNetwork, Network, Networkish } from "@ethersproject/networks"; import { defineReadOnly } from "@ethersproject/properties"; +import { Logger } from "@ethersproject/logger"; +import { version } from "./_version"; +const logger = new Logger(version); + import { JsonRpcProvider, JsonRpcSigner } from "./json-rpc-provider"; export class UrlJsonRpcProvider extends JsonRpcProvider { readonly apiKey: string; constructor(network?: Networkish, apiKey?: string) { - errors.checkAbstract(new.target, UrlJsonRpcProvider); + logger.checkAbstract(new.target, UrlJsonRpcProvider); // Normalize the Network and API Key network = new.target.getNetwork(network); @@ -24,13 +27,13 @@ export class UrlJsonRpcProvider extends JsonRpcProvider { } _startPending(): void { - errors.warn("WARNING: API provider does not support pending filters"); + logger.warn("WARNING: API provider does not support pending filters"); } getSigner(address?: string): JsonRpcSigner { - errors.throwError( + logger.throwError( "API provider does not support signing", - errors.UNSUPPORTED_OPERATION, + Logger.errors.UNSUPPORTED_OPERATION, { operation: "getSigner" } ); return null; @@ -51,7 +54,7 @@ export class UrlJsonRpcProvider extends JsonRpcProvider { // Returns the url for the given network and API key static getUrl(network: Network, apiKey: string): string { - return errors.throwError("not implemented; sub-classes must override getUrl", errors.NOT_IMPLEMENTED, { + return logger.throwError("not implemented; sub-classes must override getUrl", Logger.errors.NOT_IMPLEMENTED, { operation: "getUrl" }); } diff --git a/packages/providers/src.ts/web3-provider.ts b/packages/providers/src.ts/web3-provider.ts index 4082de958..039228e70 100644 --- a/packages/providers/src.ts/web3-provider.ts +++ b/packages/providers/src.ts/web3-provider.ts @@ -1,9 +1,12 @@ "use strict"; -import * as errors from "@ethersproject/errors"; import { Networkish } from "@ethersproject/networks"; import { defineReadOnly } from "@ethersproject/properties"; +import { Logger } from "@ethersproject/logger"; +import { version } from "./_version"; +const logger = new Logger(version); + import { JsonRpcProvider } from "./json-rpc-provider"; @@ -29,7 +32,7 @@ export class Web3Provider extends JsonRpcProvider { private _sendAsync: (request: any, callback: (error: any, response: any) => void) => void; constructor(web3Provider: AsyncSendable, network?: Networkish) { - errors.checkNew(new.target, Web3Provider); + logger.checkNew(new.target, Web3Provider); // HTTP has a host; IPC has a path. super(web3Provider.host || web3Provider.path || "", network); @@ -43,11 +46,7 @@ export class Web3Provider extends JsonRpcProvider { } if (!web3Provider || !this._sendAsync) { - errors.throwError( - "invalid web3Provider", - errors.INVALID_ARGUMENT, - { arg: "web3Provider", value: web3Provider } - ); + logger.throwArgumentError("invalid web3Provider", "web3Provider", web3Provider); } defineReadOnly(this, "_web3Provider", web3Provider); diff --git a/packages/random/package.json b/packages/random/package.json index b92f1fc65..051157ffd 100644 --- a/packages/random/package.json +++ b/packages/random/package.json @@ -9,7 +9,7 @@ }, "dependencies": { "@ethersproject/bytes": ">5.0.0-beta.0", - "@ethersproject/errors": ">5.0.0-beta.0" + "@ethersproject/logger": ">5.0.0-beta.0" }, "devDependencies": { "@types/node": "10.3.2" diff --git a/packages/random/src.ts/browser.ts b/packages/random/src.ts/browser.ts index 86eff57ef..363d44d3d 100644 --- a/packages/random/src.ts/browser.ts +++ b/packages/random/src.ts/browser.ts @@ -1,18 +1,21 @@ "use strict"; import { arrayify } from "@ethersproject/bytes"; -import * as errors from"@ethersproject/errors"; + +import { Logger } from "@ethersproject/logger"; +import { version } from "./_version"; +const logger = new Logger(version); export { shuffled } from "./shuffle"; let crypto: any = (global).crypto || (global).msCrypto; if (!crypto || !crypto.getRandomValues) { - errors.warn("WARNING: Missing strong random number source"); + logger.warn("WARNING: Missing strong random number source"); crypto = { getRandomValues: function(buffer: Uint8Array): Uint8Array { - return errors.throwError("no secure random source avaialble", errors.UNSUPPORTED_OPERATION, { + return logger.throwError("no secure random source avaialble", Logger.errors.UNSUPPORTED_OPERATION, { operation: "crypto.getRandomValues" }); } @@ -21,10 +24,7 @@ if (!crypto || !crypto.getRandomValues) { export function randomBytes(length: number): Uint8Array { if (length <= 0 || length > 1024 || parseInt(String(length)) != length) { - errors.throwError("invalid length", errors.INVALID_ARGUMENT, { - argument: "length", - value: length - }); + logger.throwArgumentError("invalid length", "length", length); } let result = new Uint8Array(length); diff --git a/packages/sha2/package.json b/packages/sha2/package.json index 99df15dff..f4e225251 100644 --- a/packages/sha2/package.json +++ b/packages/sha2/package.json @@ -9,7 +9,7 @@ }, "dependencies": { "@ethersproject/bytes": ">5.0.0-beta.0", - "@ethersproject/errors": ">5.0.0-beta.0", + "@ethersproject/logger": ">5.0.0-beta.0", "hash.js": "1.1.3" }, "keywords": [ diff --git a/packages/sha2/src.ts/browser.ts b/packages/sha2/src.ts/browser.ts index f26c3d77a..7dd0d19d6 100644 --- a/packages/sha2/src.ts/browser.ts +++ b/packages/sha2/src.ts/browser.ts @@ -3,8 +3,10 @@ import * as hash from "hash.js"; import { arrayify, BytesLike } from "@ethersproject/bytes"; -import * as errors from "@ethersproject/errors"; +import { Logger } from "@ethersproject/logger"; +import { version } from "./_version"; +const logger = new Logger(version); export enum SupportedAlgorithms { sha256 = "sha256", sha512 = "sha512" }; @@ -23,7 +25,7 @@ export function sha512(data: BytesLike): string { export function computeHmac(algorithm: SupportedAlgorithms, key: BytesLike, data: BytesLike): string { if (!SupportedAlgorithms[algorithm]) { - errors.throwError("unsupported algorithm " + algorithm, errors.UNSUPPORTED_OPERATION, { + logger.throwError("unsupported algorithm " + algorithm, Logger.errors.UNSUPPORTED_OPERATION, { operation: "hmac", algorithm: algorithm }); diff --git a/packages/signing-key/package.json b/packages/signing-key/package.json index 56e2b0c53..d4febf964 100644 --- a/packages/signing-key/package.json +++ b/packages/signing-key/package.json @@ -8,7 +8,7 @@ }, "dependencies": { "@ethersproject/bytes": ">5.0.0-beta.0", - "@ethersproject/errors": ">5.0.0-beta.0", + "@ethersproject/logger": ">5.0.0-beta.0", "@ethersproject/properties": ">5.0.0-beta.0", "elliptic": "6.3.3" }, diff --git a/packages/signing-key/src.ts/index.ts b/packages/signing-key/src.ts/index.ts index 9db377301..8031c12ee 100644 --- a/packages/signing-key/src.ts/index.ts +++ b/packages/signing-key/src.ts/index.ts @@ -3,9 +3,12 @@ import { ec as EC } from "elliptic"; import { arrayify, BytesLike, hexlify, hexZeroPad, Signature, SignatureLike, splitSignature } from "@ethersproject/bytes"; -import * as errors from "@ethersproject/errors"; import { defineReadOnly } from "@ethersproject/properties"; +import { Logger } from "@ethersproject/logger"; +import { version } from "./_version"; +const logger = new Logger(version); + let _curve: EC = null function getCurve() { if (!_curve) { @@ -91,6 +94,6 @@ export function computePublicKey(key: BytesLike, compressed?: boolean): string { return "0x" + getCurve().keyFromPublic(bytes).getPublic(true, "hex"); } - return errors.throwArgumentError("invalid public or private key", "key", "[REDACTED]"); + return logger.throwArgumentError("invalid public or private key", "key", "[REDACTED]"); } diff --git a/packages/transactions/package.json b/packages/transactions/package.json index 2ba5ab682..135adb8c8 100644 --- a/packages/transactions/package.json +++ b/packages/transactions/package.json @@ -11,8 +11,8 @@ "@ethersproject/bignumber": ">5.0.0-beta.0", "@ethersproject/bytes": ">5.0.0-beta.0", "@ethersproject/constants": ">5.0.0-beta.0", - "@ethersproject/errors": ">5.0.0-beta.0", "@ethersproject/keccak256": ">5.0.0-beta.0", + "@ethersproject/logger": ">5.0.0-beta.0", "@ethersproject/properties": ">5.0.0-beta.0", "@ethersproject/rlp": ">5.0.0-beta.0", "@ethersproject/signing-key": ">5.0.0-beta.0" diff --git a/packages/transactions/src.ts/index.ts b/packages/transactions/src.ts/index.ts index a856c202c..b4c90eafe 100644 --- a/packages/transactions/src.ts/index.ts +++ b/packages/transactions/src.ts/index.ts @@ -4,12 +4,15 @@ import { getAddress } from "@ethersproject/address"; import { BigNumber, BigNumberish } from "@ethersproject/bignumber"; import { arrayify, BytesLike, hexDataSlice, hexlify, hexZeroPad, SignatureLike, splitSignature, stripZeros, } from "@ethersproject/bytes"; import { Zero } from "@ethersproject/constants"; -import * as errors from "@ethersproject/errors"; import { keccak256 } from "@ethersproject/keccak256"; import { checkProperties } from "@ethersproject/properties"; import * as RLP from "@ethersproject/rlp"; import { computePublicKey, recoverPublicKey } from "@ethersproject/signing-key"; +import { Logger } from "@ethersproject/logger"; +import { version } from "./_version"; +const logger = new Logger(version); + /////////////////////////////// // Exported Types @@ -90,14 +93,14 @@ export function serialize(transaction: UnsignedTransaction, signature?: Signatur // Fixed-width field if (fieldInfo.length && value.length !== fieldInfo.length && value.length > 0) { - errors.throwError("invalid length for " + fieldInfo.name, errors.INVALID_ARGUMENT, { arg: ("transaction" + fieldInfo.name), value: value }); + logger.throwArgumentError("invalid length for " + fieldInfo.name, ("transaction:" + fieldInfo.name), value); } // Variable-width (with a maximum) if (fieldInfo.maxLength) { value = stripZeros(value); if (value.length > fieldInfo.maxLength) { - errors.throwError("invalid length for " + fieldInfo.name, errors.INVALID_ARGUMENT, { arg: ("transaction" + fieldInfo.name), value: value }); + logger.throwArgumentError("invalid length for " + fieldInfo.name, ("transaction:" + fieldInfo.name), value ); } } @@ -140,7 +143,7 @@ export function serialize(transaction: UnsignedTransaction, signature?: Signatur export function parse(rawTransaction: BytesLike): Transaction { let transaction = RLP.decode(rawTransaction); if (transaction.length !== 9 && transaction.length !== 6) { - errors.throwError("invalid raw transaction", errors.INVALID_ARGUMENT, { arg: "rawTransactin", value: rawTransaction }); + logger.throwArgumentError("invalid raw transaction", "rawTransactin", rawTransaction); } let tx: Transaction = { diff --git a/packages/units/package.json b/packages/units/package.json index a998ffd9a..70f9b9f9e 100644 --- a/packages/units/package.json +++ b/packages/units/package.json @@ -9,7 +9,7 @@ "dependencies": { "@ethersproject/bignumber": ">5.0.0-beta.0", "@ethersproject/constants": ">5.0.0-beta.0", - "@ethersproject/errors": ">5.0.0-beta.0" + "@ethersproject/logger": ">5.0.0-beta.0" }, "keywords": [ "Ethereum", diff --git a/packages/units/src.ts/index.ts b/packages/units/src.ts/index.ts index 0e9ca3a3c..3d7a09ea8 100644 --- a/packages/units/src.ts/index.ts +++ b/packages/units/src.ts/index.ts @@ -2,8 +2,10 @@ import { BigNumber, BigNumberish } from "@ethersproject/bignumber"; import { formatFixed, parseFixed } from "@ethersproject/bignumber/fixednumber"; -import * as errors from "@ethersproject/errors"; +import { Logger } from "@ethersproject/logger"; +import { version } from "./_version"; +const logger = new Logger(version); const names = [ "wei", @@ -22,7 +24,7 @@ export function commify(value: string | number): string { let comps = String(value).split("."); if (comps.length > 2 || !comps[0].match(/^-?[0-9]*$/) || (comps[1] && !comps[1].match(/^[0-9]*$/)) || value === "." || value === "-.") { - errors.throwError("invalid value", errors.INVALID_ARGUMENT, { argument: "value", value: value }); + logger.throwArgumentError("invalid value", "value", value); } // Make sure we have at least one whole digit (0 if none) diff --git a/packages/wallet/package.json b/packages/wallet/package.json index d2c7bc814..09b4646bb 100644 --- a/packages/wallet/package.json +++ b/packages/wallet/package.json @@ -12,11 +12,11 @@ "@ethersproject/address": ">5.0.0-beta.0", "@ethersproject/bignumber": ">5.0.0-beta.0", "@ethersproject/bytes": ">5.0.0-beta.0", - "@ethersproject/errors": ">5.0.0-beta.0", "@ethersproject/hash": ">5.0.0-beta.0", "@ethersproject/hdnode": ">5.0.0-beta.0", "@ethersproject/json-wallets": ">5.0.0-beta.0", "@ethersproject/keccak256": ">5.0.0-beta.0", + "@ethersproject/logger": ">5.0.0-beta.0", "@ethersproject/properties": ">5.0.0-beta.0", "@ethersproject/random": ">5.0.0-beta.0", "@ethersproject/signing-key": ">5.0.0-beta.0", diff --git a/packages/wallet/src.ts/index.ts b/packages/wallet/src.ts/index.ts index 6b118a9f1..81c7d0aed 100644 --- a/packages/wallet/src.ts/index.ts +++ b/packages/wallet/src.ts/index.ts @@ -4,7 +4,6 @@ import { getAddress } from "@ethersproject/address"; import { Provider, TransactionRequest } from "@ethersproject/abstract-provider"; import { ExternallyOwnedAccount, Signer } from "@ethersproject/abstract-signer"; import { arrayify, Bytes, BytesLike, concat, hexDataSlice, isHexString, joinSignature, SignatureLike } from "@ethersproject/bytes"; -import * as errors from "@ethersproject/errors"; import { hashMessage } from "@ethersproject/hash"; import { defaultPath, HDNode, entropyToMnemonic } from "@ethersproject/hdnode"; import { keccak256 } from "@ethersproject/keccak256"; @@ -15,6 +14,10 @@ import { decryptJsonWallet, encryptKeystore, ProgressCallback } from "@etherspro import { computeAddress, recoverAddress, serialize } from "@ethersproject/transactions"; import { Wordlist } from "@ethersproject/wordlists/wordlist"; +import { Logger } from "@ethersproject/logger"; +import { version } from "./_version"; +const logger = new Logger(version); + function isAccount(value: any): value is ExternallyOwnedAccount { return (value != null && isHexString(value.privateKey, 32) && value.address != null); } @@ -32,7 +35,7 @@ export class Wallet extends Signer implements ExternallyOwnedAccount { readonly _mnemonic: () => string; constructor(privateKey: BytesLike | ExternallyOwnedAccount | SigningKey, provider?: Provider) { - errors.checkNew(new.target, Wallet); + logger.checkNew(new.target, Wallet); super(); @@ -42,7 +45,7 @@ export class Wallet extends Signer implements ExternallyOwnedAccount { defineReadOnly(this, "address", computeAddress(this.publicKey)); if (this.address !== getAddress(privateKey.address)) { - errors.throwArgumentError("privateKey/address mismatch", "privateKey", "[REDCACTED]"); + logger.throwArgumentError("privateKey/address mismatch", "privateKey", "[REDCACTED]"); } if (privateKey.mnemonic != null) { @@ -52,7 +55,7 @@ export class Wallet extends Signer implements ExternallyOwnedAccount { defineReadOnly(this, "path", privateKey.path); let node = HDNode.fromMnemonic(mnemonic).derivePath(path); if (computeAddress(node.privateKey) !== this.address) { - errors.throwArgumentError("mnemonic/address mismatch", "privateKey", "[REDCACTED]"); + logger.throwArgumentError("mnemonic/address mismatch", "privateKey", "[REDCACTED]"); } } else { defineReadOnly(this, "_mnemonic", (): string => null); @@ -63,7 +66,7 @@ export class Wallet extends Signer implements ExternallyOwnedAccount { } else { if (SigningKey.isSigningKey(privateKey)) { if (privateKey.curve !== "secp256k1") { - errors.throwArgumentError("unsupported curve; must be secp256k1", "privateKey", "[REDACTED]"); + logger.throwArgumentError("unsupported curve; must be secp256k1", "privateKey", "[REDACTED]"); } defineReadOnly(this, "_signingKey", () => privateKey); } else { @@ -76,10 +79,7 @@ export class Wallet extends Signer implements ExternallyOwnedAccount { } if (provider && !Provider.isProvider(provider)) { - errors.throwError("invalid provider", errors.INVALID_ARGUMENT, { - argument: "provider", - value: provider - }); + logger.throwArgumentError("invalid provider", "provider", provider); } defineReadOnly(this, "provider", provider || null); diff --git a/packages/web/package.json b/packages/web/package.json index 0217a1761..a618d6b72 100644 --- a/packages/web/package.json +++ b/packages/web/package.json @@ -8,7 +8,7 @@ }, "dependencies": { "@ethersproject/base64": ">5.0.0-beta.0", - "@ethersproject/errors": ">5.0.0-beta.0", + "@ethersproject/logger": ">5.0.0-beta.0", "@ethersproject/properties": ">5.0.0-beta.0", "@ethersproject/strings": ">5.0.0-beta.0", "cross-fetch": "3.0.4" diff --git a/packages/web/src.ts/index.ts b/packages/web/src.ts/index.ts index 215d743cf..ca5e4c259 100644 --- a/packages/web/src.ts/index.ts +++ b/packages/web/src.ts/index.ts @@ -3,10 +3,12 @@ import fetch from "cross-fetch"; import { encode as base64Encode } from "@ethersproject/base64"; -import * as errors from "@ethersproject/errors"; import { shallowCopy } from "@ethersproject/properties"; import { toUtf8Bytes } from "@ethersproject/strings"; +import { Logger } from "@ethersproject/logger"; +import { version } from "./_version"; +const logger = new Logger(version); // Exported Types export type ConnectionInfo = { @@ -57,7 +59,7 @@ export function fetchJson(connection: string | ConnectionInfo, json?: string, pr } else if (typeof(connection) === "object") { if (connection == null || connection.url == null) { - errors.throwArgumentError("missing URL", "connection.url", connection); + logger.throwArgumentError("missing URL", "connection.url", connection); } url = connection.url; @@ -74,10 +76,10 @@ export function fetchJson(connection: string | ConnectionInfo, json?: string, pr if (connection.user != null && connection.password != null) { if (url.substring(0, 6) !== "https:" && connection.allowInsecureAuthentication !== true) { - errors.throwError( + logger.throwError( "basic authentication requires a secure https url", - errors.INVALID_ARGUMENT, - { arg: "url", url: url, user: connection.user, password: "[REDACTED]" } + Logger.errors.INVALID_ARGUMENT, + { argument: "url", url: url, user: connection.user, password: "[REDACTED]" } ); } @@ -97,10 +99,7 @@ export function fetchJson(connection: string | ConnectionInfo, json?: string, pr if (timer == null) { return; } timer = null; - reject(errors.makeError("timeout", errors.TIMEOUT, { })); - //setTimeout(() => { - // request.abort(); - //}, 0); + reject(logger.makeError("timeout", Logger.errors.TIMEOUT, { timeout: timeout })); }, timeout); } @@ -126,7 +125,7 @@ export function fetchJson(connection: string | ConnectionInfo, json?: string, pr return fetch(url, options).then((response) => { return response.text().then((body) => { if (!response.ok) { - errors.throwError("bad response", errors.SERVER_ERROR, { + logger.throwError("bad response", Logger.errors.SERVER_ERROR, { status: response.status, body: body, type: response.type, @@ -142,7 +141,7 @@ export function fetchJson(connection: string | ConnectionInfo, json?: string, pr try { json = JSON.parse(text); } catch (error) { - errors.throwError("invalid JSON", errors.SERVER_ERROR, { + logger.throwError("invalid JSON", Logger.errors.SERVER_ERROR, { body: text, error: error, url: url @@ -153,7 +152,7 @@ export function fetchJson(connection: string | ConnectionInfo, json?: string, pr try { json = processFunc(json); } catch (error) { - errors.throwError("processing response error", errors.SERVER_ERROR, { + logger.throwError("processing response error", Logger.errors.SERVER_ERROR, { body: json, error: error }); diff --git a/packages/wordlists/package.json b/packages/wordlists/package.json index 1fab3f164..06c781a30 100644 --- a/packages/wordlists/package.json +++ b/packages/wordlists/package.json @@ -9,8 +9,8 @@ }, "dependencies": { "@ethersproject/bytes": ">5.0.0-beta.0", - "@ethersproject/errors": ">5.0.0-beta.0", "@ethersproject/hash": ">5.0.0-beta.0", + "@ethersproject/logger": ">5.0.0-beta.0", "@ethersproject/properties": ">5.0.0-beta.0", "@ethersproject/strings": ">5.0.0-beta.0" }, diff --git a/packages/wordlists/src.ts/lang-es.ts b/packages/wordlists/src.ts/lang-es.ts index dd86a3b08..b4dbedbb5 100644 --- a/packages/wordlists/src.ts/lang-es.ts +++ b/packages/wordlists/src.ts/lang-es.ts @@ -1,8 +1,11 @@ "use strict"; -import { checkNormalize } from "@ethersproject/errors"; import { toUtf8Bytes, toUtf8String } from "@ethersproject/strings"; +import { Logger } from "@ethersproject/logger"; +import { version } from "./_version"; +const logger = new Logger(version); + import { check, register, Wordlist } from "./wordlist"; @@ -12,7 +15,7 @@ let lookup: { [word: string]: number } = {}; let wordlist: Array = null; function dropDiacritic(word: string): string { - checkNormalize(); + logger.checkNormalize(); return toUtf8String(Array.prototype.filter.call(toUtf8Bytes(word.normalize("NFD").toLowerCase()), (c: number) => { return ((c >= 65 && c <= 90) || (c >= 97 && c <= 123)); })); diff --git a/packages/wordlists/src.ts/lang-fr.ts b/packages/wordlists/src.ts/lang-fr.ts index 673e5b628..bbce6cb3a 100644 --- a/packages/wordlists/src.ts/lang-fr.ts +++ b/packages/wordlists/src.ts/lang-fr.ts @@ -1,8 +1,11 @@ "use strict"; -import { checkNormalize } from "@ethersproject/errors"; import { toUtf8Bytes, toUtf8String } from "@ethersproject/strings"; +import { Logger } from "@ethersproject/logger"; +import { version } from "./_version"; +const logger = new Logger(version); + import { check, register, Wordlist } from "./wordlist"; @@ -12,7 +15,7 @@ let wordlist: Array = null; let lookup: { [word: string]: number } = { } function dropDiacritic(word: string): string { - checkNormalize(); + logger.checkNormalize(); return toUtf8String(Array.prototype.filter.call(toUtf8Bytes(word.normalize("NFD").toLowerCase()), (c: number) => { return ((c >= 65 && c <= 90) || (c >= 97 && c <= 123)); })); diff --git a/packages/wordlists/src.ts/lang-ja.ts b/packages/wordlists/src.ts/lang-ja.ts index c042bb852..7c5448429 100644 --- a/packages/wordlists/src.ts/lang-ja.ts +++ b/packages/wordlists/src.ts/lang-ja.ts @@ -1,9 +1,12 @@ "use strict"; import { hexlify } from "@ethersproject/bytes"; -import * as errors from "@ethersproject/errors"; import { toUtf8Bytes, toUtf8String } from "@ethersproject/strings"; +import { Logger } from "@ethersproject/logger"; +import { version } from "./_version"; +const logger = new Logger(version); + import { check, register, Wordlist } from "./wordlist"; @@ -133,7 +136,7 @@ class LangJa extends Wordlist { } split(mnemonic: string): Array { - errors.checkNormalize(); + logger.checkNormalize(); return mnemonic.split(/(?:\u3000| )+/g); } diff --git a/packages/wordlists/src.ts/wordlist.ts b/packages/wordlists/src.ts/wordlist.ts index bc72612b7..532815103 100644 --- a/packages/wordlists/src.ts/wordlist.ts +++ b/packages/wordlists/src.ts/wordlist.ts @@ -3,10 +3,12 @@ // This gets overriddenby gulp during bip39-XX let exportWordlist = false; -import { checkAbstract } from "@ethersproject/errors"; import { id } from "@ethersproject/hash"; import { defineReadOnly } from "@ethersproject/properties"; +import { Logger } from "@ethersproject/logger"; +import { version } from "./_version"; +const logger = new Logger(version); export function check(wordlist: Wordlist) { let words = []; @@ -22,7 +24,7 @@ export abstract class Wordlist { readonly locale: string; constructor(locale: string) { - checkAbstract(new.target, Wordlist); + logger.checkAbstract(new.target, Wordlist); defineReadOnly(this, "locale", locale); } diff --git a/tsconfig.project.json b/tsconfig.project.json index fd653d22e..2fbec7ced 100644 --- a/tsconfig.project.json +++ b/tsconfig.project.json @@ -12,6 +12,9 @@ { "path": "./packages/errors" }, + { + "path": "./packages/logger" + }, { "path": "./packages/bytes" },