Converted throwArgumentError to assertArgument.

This commit is contained in:
Richard Moore 2022-10-25 04:06:00 -04:00
parent 17ac965b12
commit e5c068c395
53 changed files with 297 additions and 528 deletions

@ -1,6 +1,6 @@
// See: https://github.com/ethereum/wiki/wiki/Ethereum-Contract-ABI
import { assertArgumentCount, throwArgumentError } from "../utils/index.js";
import { assertArgumentCount, assertArgument } from "../utils/index.js";
import { Coder, Reader, Result, Writer } from "./coders/abstract-coder.js";
import { AddressCoder } from "./coders/address.js";
@ -54,9 +54,8 @@ export class AbiCoder {
let match = param.type.match(paramTypeNumber);
if (match) {
let size = parseInt(match[2] || "256");
if (size === 0 || size > 256 || (size % 8) !== 0) {
throwArgumentError("invalid " + match[1] + " bit length", "param", param);
}
assertArgument(size !== 0 && size <= 256 && (size % 8) === 0,
"invalid " + match[1] + " bit length", "param", param);
return new NumberCoder(size / 8, (match[1] === "int"), param.name);
}
@ -64,13 +63,11 @@ export class AbiCoder {
match = param.type.match(paramTypeBytes);
if (match) {
let size = parseInt(match[1]);
if (size === 0 || size > 32) {
throwArgumentError("invalid bytes length", "param", param);
}
assertArgument(size !== 0 && size <= 32, "invalid bytes length", "param", param);
return new FixedBytesCoder(size, param.name);
}
return throwArgumentError("invalid type", "type", param.type);
assertArgument(false, "invalid type", "type", param.type);
}
getDefaultValue(types: ReadonlyArray<string | ParamType>): Result {

@ -2,7 +2,7 @@
import {
defineProperties, concat, getBytesCopy, getNumber, hexlify,
toArray, toBigInt, toNumber,
assertPrivate, throwArgumentError, throwError
assertPrivate, assertArgument, throwError
} from "../../utils/index.js";
import type { BigNumberish, BytesLike } from "../../utils/index.js";
@ -194,7 +194,7 @@ export abstract class Coder {
}
_throwError(message: string, value: any): never {
return throwArgumentError(message, this.localName, value);
assertArgument(false, message, this.localName, value);
}
abstract encode(writer: Writer, value: any): number;

@ -1,5 +1,5 @@
import {
defineProperties, isError, assertArgumentCount, throwArgumentError, throwError
defineProperties, isError, assertArgument, assertArgumentCount, throwError
} from "../../utils/index.js";
import { Typed } from "../typed.js";
@ -43,12 +43,10 @@ export function pack(writer: Writer, coders: ReadonlyArray<Coder>, values: Array
});
} else {
throwArgumentError("invalid tuple value", "tuple", values);
assertArgument(false, "invalid tuple value", "tuple", values);
}
if (coders.length !== arrayValues.length) {
throwArgumentError("types/value length mismatch", "tuple", values);
}
assertArgument(coders.length === arrayValues.length, "types/value length mismatch", "tuple", values);
let staticWriter = new Writer();
let dynamicWriter = new Writer();

@ -1,6 +1,6 @@
import {
defineProperties, getBigInt, getNumber,
assertPrivate, throwArgumentError, throwError
assertPrivate, assertArgument, throwError
} from "../utils/index.js";
import { id } from "../hash/index.js";
@ -401,25 +401,19 @@ const regexArrayType = new RegExp(/^(.*)\[([0-9]*)\]$/);
function verifyBasicType(type: string): string {
const match = type.match(regexType);
if (!match) {
return throwArgumentError("invalid type", "type", type);
}
assertArgument(match, "invalid type", "type", type);
if (type === "uint") { return "uint256"; }
if (type === "int") { return "int256"; }
if (match[2]) {
// bytesXX
const length = parseInt(match[2]);
if (length === 0 || length > 32) {
throwArgumentError("invalid bytes length", "type", type);
}
assertArgument(length !== 0 && length <= 32, "invalid bytes length", "type", type);
} else if (match[3]) {
// intXX or uintXX
const size = parseInt(match[3] as string);
if (size === 0 || size > 256 || size % 8) {
throwArgumentError("invalid numeric width", "type", type);
}
assertArgument(size !== 0 && size <= 256 && (size % 8) === 0, "invalid numeric width", "type", type);
}
return type;
@ -694,15 +688,12 @@ export class ParamType {
}
const name = obj.name;
if (name && (typeof(name) !== "string" || !name.match(regexIdentifier))) {
throwArgumentError("invalid name", "obj.name", name);
}
assertArgument(!name || (typeof(name) === "string" && name.match(regexIdentifier)),
"invalid name", "obj.name", name);
let indexed = obj.indexed;
if (indexed != null) {
if (!allowIndexed) {
throwArgumentError("parameter cannot be indexed", "obj.indexed", obj.indexed);
}
assertArgument(allowIndexed, "parameter cannot be indexed", "obj.indexed", obj.indexed);
indexed = !!indexed;
}
@ -813,9 +804,8 @@ export abstract class NamedFragment extends Fragment {
constructor(guard: any, type: FragmentType, name: string, inputs: ReadonlyArray<ParamType>) {
super(guard, type, inputs);
if (typeof(name) !== "string" || !name.match(regexIdentifier)) {
throwArgumentError("invalid identifier", "name", name);
}
assertArgument(typeof(name) === "string" && name.match(regexIdentifier),
"invalid identifier", "name", name);
inputs = Object.freeze(inputs.slice());
defineProperties<NamedFragment>(this, { name });
}

@ -2,7 +2,7 @@ import { keccak256 } from "../crypto/index.js"
import { id } from "../hash/index.js"
import {
concat, dataSlice, getBigInt, getBytes, getBytesCopy,
hexlify, zeroPadValue, isHexString, defineProperties, throwArgumentError, toHex,
hexlify, zeroPadValue, isHexString, defineProperties, assertArgument, toHex,
throwError
} from "../utils/index.js";
@ -279,7 +279,7 @@ export class Interface {
for (const fragment of this.#functions.values()) {
if (selector === fragment.selector) { return fragment; }
}
throwArgumentError("no matching function", "selector", key);
assertArgument(false, "no matching function", "selector", key);
}
// It is a bare name, look up the function (will return null if ambiguous)
@ -340,12 +340,11 @@ export class Interface {
}
}
if (matching.length === 0) {
throwArgumentError("no matching function", "name", key);
assertArgument(matching.length !== 0, "no matching function", "name", key);
} else if (matching.length > 1 && forceUnique) {
if (matching.length > 1 && forceUnique) {
const matchStr = matching.map((m) => JSON.stringify(m.format())).join(", ");
throwArgumentError(`multiple matching functions (i.e. ${ matchStr })`, "name", key);
assertArgument(false, `multiple matching functions (i.e. ${ matchStr })`, "name", key);
}
return matching[0];
@ -355,7 +354,7 @@ export class Interface {
const result = this.#functions.get(FunctionFragment.from(key).format());
if (result) { return result; }
return throwArgumentError("no matching function", "signature", key);
assertArgument(false, "no matching function", "signature", key);
}
/**
@ -390,7 +389,7 @@ export class Interface {
for (const fragment of this.#events.values()) {
if (eventTopic === fragment.topicHash) { return fragment; }
}
throwArgumentError("no matching event", "eventTopic", key);
assertArgument(false, "no matching event", "eventTopic", key);
}
// It is a bare name, look up the function (will return null if ambiguous)
@ -424,11 +423,10 @@ export class Interface {
}
}
if (matching.length === 0) {
throwArgumentError("no matching event", "name", key);
} else if (matching.length > 1 && forceUnique) {
assertArgument(matching.length > 0, "no matching event", "name", key);
if (matching.length > 1 && forceUnique) {
// @TODO: refine by Typed
throwArgumentError("multiple matching events", "name", key);
assertArgument(false, "multiple matching events", "name", key);
}
return matching[0];
@ -438,7 +436,7 @@ export class Interface {
const result = this.#events.get(EventFragment.from(key).format());
if (result) { return result; }
return throwArgumentError("no matching event", "signature", key);
assertArgument(false, "no matching event", "signature", key);
}
/**
@ -484,7 +482,7 @@ export class Interface {
for (const fragment of this.#errors.values()) {
if (selector === fragment.selector) { return fragment; }
}
throwArgumentError("no matching error", "selector", key);
assertArgument(false, "no matching error", "selector", key);
}
// It is a bare name, look up the function (will return null if ambiguous)
@ -497,10 +495,10 @@ export class Interface {
if (matching.length === 0) {
if (key === "Error") { return ErrorFragment.from("error Error(string)"); }
if (key === "Panic") { return ErrorFragment.from("error Panic(uint256)"); }
throwArgumentError("no matching error", "name", key);
assertArgument(false, "no matching error", "name", key);
} else if (matching.length > 1) {
// @TODO: refine by Typed
throwArgumentError("multiple matching errors", "name", key);
assertArgument(false, "multiple matching errors", "name", key);
}
return matching[0];
@ -514,7 +512,7 @@ export class Interface {
const result = this.#errors.get(key);
if (result) { return result; }
return throwArgumentError("no matching error", "signature", key);
assertArgument(false, "no matching error", "signature", key);
}
// Get the 4-byte selector used by Solidity to identify a function
@ -576,9 +574,8 @@ export class Interface {
decodeErrorResult(fragment: ErrorFragment | string, data: BytesLike): Result {
if (typeof(fragment) === "string") { fragment = this.getError(fragment); }
if (dataSlice(data, 0, 4) !== fragment.selector) {
throwArgumentError(`data signature does not match error ${ fragment.name }.`, "data", data);
}
assertArgument(dataSlice(data, 0, 4) === fragment.selector,
`data signature does not match error ${ fragment.name }.`, "data", data);
return this._decodeParams(fragment.inputs, dataSlice(data, 4));
}
@ -611,9 +608,8 @@ export class Interface {
decodeFunctionData(key: FunctionFragment | string, data: BytesLike): Result {
const fragment = (typeof(key) === "string") ? this.getFunction(key): key;
if (dataSlice(data, 0, 4) !== fragment.selector) {
throwArgumentError(`data signature does not match function ${ fragment.name }.`, "data", data);
}
assertArgument(dataSlice(data, 0, 4) === fragment.selector,
`data signature does not match function ${ fragment.name }.`, "data", data);
return this._decodeParams(fragment.inputs, dataSlice(data, 4));
}
@ -788,16 +784,15 @@ export class Interface {
const param = (<EventFragment>eventFragment).inputs[index];
if (!param.indexed) {
if (value != null) {
throwArgumentError("cannot filter non-indexed parameters; must be null", ("contract." + param.name), value);
}
assertArgument(value == null,
"cannot filter non-indexed parameters; must be null", ("contract." + param.name), value);
return;
}
if (value == null) {
topics.push(null);
} else if (param.baseType === "array" || param.baseType === "tuple") {
throwArgumentError("filtering with tuples or arrays not supported", ("contract." + param.name), value);
assertArgument(false, "filtering with tuples or arrays not supported", ("contract." + param.name), value);
} else if (Array.isArray(value)) {
topics.push(value.map((value) => encodeTopic(param, value)));
} else {
@ -827,9 +822,8 @@ export class Interface {
topics.push(eventFragment.topicHash);
}
if (values.length !== eventFragment.inputs.length) {
throwArgumentError("event arguments/values mismatch", "values", values);
}
assertArgument(values.length !== eventFragment.inputs.length,
"event arguments/values mismatch", "values", values);
eventFragment.inputs.forEach((param, index) => {
const value = values[index];
@ -864,9 +858,8 @@ export class Interface {
if (topics != null && !eventFragment.anonymous) {
const eventTopic = eventFragment.topicHash;
if (!isHexString(topics[0], 32) || topics[0].toLowerCase() !== eventTopic) {
throwArgumentError("fragment/topic mismatch", "topics[0]", topics[0]);
}
assertArgument(isHexString(topics[0], 32) && topics[0].toLowerCase() === eventTopic,
"fragment/topic mismatch", "topics[0]", topics[0]);
topics = topics.slice(1);
}

@ -1,5 +1,5 @@
import { keccak256 } from "../crypto/index.js";
import { getBytes, throwArgumentError } from "../utils/index.js";
import { getBytes, assertArgument } from "../utils/index.js";
const BN_0 = BigInt(0);
@ -83,9 +83,7 @@ function fromBase36(value: string): bigint {
export function getAddress(address: string): string {
if (typeof(address) !== "string") {
throwArgumentError("invalid address", "address", address);
}
assertArgument(typeof(address) === "string", "invalid address", "address", address);
if (address.match(/^(0x)?[0-9a-fA-F]{40}$/)) {
@ -95,9 +93,8 @@ export function getAddress(address: string): string {
const result = getChecksumAddress(address);
// It is a checksummed address with a bad checksum
if (address.match(/([A-F].*[a-f])|([a-f].*[A-F])/) && result !== address) {
throwArgumentError("bad address checksum", "address", address);
}
assertArgument(!address.match(/([A-F].*[a-f])|([a-f].*[A-F])/) || result === address,
"bad address checksum", "address", address);
return result;
}
@ -105,16 +102,14 @@ export function getAddress(address: string): string {
// Maybe ICAP? (we only support direct mode)
if (address.match(/^XE[0-9]{2}[0-9A-Za-z]{30,31}$/)) {
// It is an ICAP address with a bad checksum
if (address.substring(2, 4) !== ibanChecksum(address)) {
throwArgumentError("bad icap checksum", "address", address);
}
assertArgument(address.substring(2, 4) === ibanChecksum(address), "bad icap checksum", "address", address);
let result = fromBase36(address.substring(4)).toString(16);
while (result.length < 40) { result = "0" + result; }
return getChecksumAddress("0x" + result);
}
return throwArgumentError("invalid address", "address", address);
assertArgument(false, "invalid address", "address", address);
}
export function getIcapAddress(address: string): string {

@ -1,4 +1,4 @@
import { throwArgumentError, throwError } from "../utils/index.js";
import { assertArgument, throwError } from "../utils/index.js";
import { getAddress } from "./address.js";
@ -23,7 +23,7 @@ async function checkAddress(target: any, promise: Promise<null | string>): Promi
if (typeof(target) === "string") {
return throwError("unconfigured name", "UNCONFIGURED_NAME", { value: target });
}
return throwArgumentError("invalid AddressLike value; did not resolve to a value address", "target", target);
assertArgument(false, "invalid AddressLike value; did not resolve to a value address", "target", target);
}
return getAddress(result);
}
@ -50,5 +50,5 @@ export function resolveAddress(target: AddressLike, resolver?: null | NameResolv
return checkAddress(target, target);
}
return throwArgumentError("unsupported addressable value", "target", target);
assertArgument(false, "unsupported addressable value", "target", target);
}

@ -1,6 +1,6 @@
import { keccak256 } from "../crypto/index.js";
import {
concat, dataSlice, getBigInt, getBytes, encodeRlp, throwArgumentError
concat, dataSlice, getBigInt, getBytes, encodeRlp, assertArgument
} from "../utils/index.js";
import { getAddress } from "./address.js";
@ -30,13 +30,9 @@ export function getCreate2Address(_from: string, _salt: BytesLike, _initCodeHash
const salt = getBytes(_salt, "salt");
const initCodeHash = getBytes(_initCodeHash, "initCodeHash");
if (salt.length !== 32) {
throwArgumentError("salt must be 32 bytes", "salt", _salt);
}
assertArgument(salt.length === 32, "salt must be 32 bytes", "salt", _salt);
if (initCodeHash.length !== 32) {
throwArgumentError("initCodeHash must be 32 bytes", "initCodeHash", _initCodeHash);
}
assertArgument(initCodeHash.length === 32, "initCodeHash must be 32 bytes", "initCodeHash", _initCodeHash);
return getAddress(dataSlice(keccak256(concat([ "0xff", from, salt, initCodeHash ])), 12))
}

@ -3,7 +3,7 @@ import { resolveAddress } from "../address/index.js";
import { copyRequest, Log, TransactionResponse } from "../providers/index.js";
import {
defineProperties, isCallException, isHexString, resolveProperties,
makeError, throwArgumentError, throwError
makeError, assertArgument, throwError
} from "../utils/index.js";
import {
@ -133,9 +133,9 @@ export async function copyOverrides(arg: any): Promise<Omit<ContractTransaction,
// Some sanity checking; these are what these methods adds
//if ((<any>overrides).to) {
if (overrides.to) {
throwArgumentError("cannot override to", "overrides.to", overrides.to);
assertArgument(false, "cannot override to", "overrides.to", overrides.to);
} else if (overrides.data) {
throwArgumentError("cannot override data", "overrides.data", overrides.data);
assertArgument(false, "cannot override data", "overrides.data", overrides.data);
}
// Resolve any from

@ -3,7 +3,7 @@ import { Interface } from "../abi/index.js";
import { getCreateAddress } from "../address/index.js";
import {
concat, defineProperties, getBytes, hexlify,
throwArgumentError, throwError
assertArgument, throwError
} from "../utils/index.js";
import { BaseContract, copyOverrides, resolveArgs } from "./contract.js";
@ -80,9 +80,7 @@ export class ContractFactory<A extends Array<any> = Array<any>, I = BaseContract
}
static fromSolidity<A extends Array<any> = Array<any>, I = ContractInterface>(output: any, runner?: ContractRunner): ContractFactory<A, I> {
if (output == null) {
throwArgumentError("bad compiler output", "output", output);
}
assertArgument(output != null, "bad compiler output", "output", output);
if (typeof(output) === "string") { output = JSON.parse(output); }

@ -5,7 +5,7 @@ import { pbkdf2 } from "@noble/hashes/pbkdf2";
import { sha256 } from "@noble/hashes/sha256";
import { sha512 } from "@noble/hashes/sha512";
import { throwArgumentError, throwError } from "../utils/index.js";
import { assertArgument, throwError } from "../utils/index.js";
declare global {
@ -37,22 +37,18 @@ export function createHash(algo: string): CryptoHasher {
case "sha256": return sha256.create();
case "sha512": return sha512.create();
}
return throwArgumentError("invalid hashing algorithm name", "algorithm", algo);
assertArgument(false, "invalid hashing algorithm name", "algorithm", algo);
}
export function createHmac(_algo: string, key: Uint8Array): CryptoHasher {
const algo = ({ sha256, sha512 }[_algo]);
if (algo == null) {
return throwArgumentError("invalid hmac algorithm", "algorithm", _algo);
}
assertArgument(algo != null, "invalid hmac algorithm", "algorithm", _algo);
return hmac.create(algo, key);
}
export function pbkdf2Sync(password: Uint8Array, salt: Uint8Array, iterations: number, keylen: number, _algo: "sha256" | "sha512"): Uint8Array {
const algo = ({ sha256, sha512 }[_algo]);
if (algo == null) {
return throwArgumentError("invalid pbkdf2 algorithm", "algorithm", _algo);
}
assertArgument(algo != null, "invalid pbkdf2 algorithm", "algorithm", _algo);
return pbkdf2(algo, password, salt, { c: iterations, dkLen: keylen });
}
@ -63,9 +59,7 @@ export function randomBytes(length: number): Uint8Array {
});
}
if (!Number.isInteger(length) || length <= 0 || length > 1024) {
throwArgumentError("invalid length", "length", length);
}
assertArgument(Number.isInteger(length) && length > 0 && length <= 1024, "invalid length", "length", length);
const result = new Uint8Array(length);
crypto.getRandomValues(result);

@ -1,4 +1,4 @@
import { createHmac } from "./crypto-browser.js";
import { createHmac } from "./crypto.js";
import { getBytes, hexlify } from "../utils/index.js";
import type { BytesLike } from "../utils/index.js";

@ -2,7 +2,7 @@ import { ZeroHash } from "../constants/index.js";
import {
concat, dataLength, getBigInt, getBytes, getNumber, getStore, hexlify,
isHexString, setStore,
assertPrivate, throwArgumentError
assertArgument, assertPrivate
} from "../utils/index.js";
import type {
@ -48,26 +48,21 @@ export class Signature implements Freezable<Signature> {
get r(): string { return getStore(this.#props, "r"); }
set r(value: BytesLike) {
if (dataLength(value) !== 32) {
throwArgumentError("invalid r", "value", value);
}
assertArgument(dataLength(value) === 32, "invalid r", "value", value);
setStore(this.#props, "r", hexlify(value));
}
get s(): string { return getStore(this.#props, "s"); }
set s(value: BytesLike) {
if (dataLength(value) !== 32) {
throwArgumentError("invalid r", "value", value);
} else if (getBytes(value)[0] & 0x80) {
throwArgumentError("non-canonical s", "value", value);
}
assertArgument(dataLength(value) === 32, "invalid r", "value", value);
assertArgument((getBytes(value)[0] & 0x80) === 0, "non-canonical s", "value", value);
setStore(this.#props, "s", hexlify(value));
}
get v(): 27 | 28 { return getStore(this.#props, "v"); }
set v(value: BigNumberish) {
const v = getNumber(value, "value");
if (v !== 27 && v !== 28) { throw new Error("@TODO"); }
assertArgument(v === 27 || v === 28, "invalid v", "v", value);
setStore(this.#props, "v", v);
}
@ -130,10 +125,6 @@ export class Signature implements Freezable<Signature> {
};
}
//static create(): Signature {
// return new Signature(_guard, ZeroHash, ZeroHash, 27);
//}
// Get the chain ID from an EIP-155 v
static getChainId(v: BigNumberish): bigint {
const bv = getBigInt(v, "v");
@ -142,7 +133,7 @@ export class Signature implements Freezable<Signature> {
if ((bv == BN_27) || (bv == BN_28)) { return BN_0; }
// Bad value for an EIP-155 v
if (bv < BN_35) { throwArgumentError("invalid EIP-155 v", "v", v); }
assertArgument(bv >= BN_35, "invalid EIP-155 v", "v", v);
return (bv - BN_35) / BN_2;
}
@ -164,14 +155,14 @@ export class Signature implements Freezable<Signature> {
}
static from(sig?: SignatureLike): Signature {
function assertError(check: unknown, message: string): asserts check {
assertArgument(check, message, "signature", sig);
};
if (sig == null) {
return new Signature(_guard, ZeroHash, ZeroHash, 27);
}
const throwError = (message: string) => {
return throwArgumentError(message, "signature", sig);
};
if (typeof(sig) === "string") {
const bytes = getBytes(sig, "signature");
if (bytes.length === 64) {
@ -185,38 +176,38 @@ export class Signature implements Freezable<Signature> {
if (bytes.length === 65) {
const r = hexlify(bytes.slice(0, 32));
const s = bytes.slice(32, 64);
if (s[0] & 0x80) { throwError("non-canonical s"); }
assertError((s[0] & 0x80) === 0, "non-canonical s");
const v = Signature.getNormalizedV(bytes[64]);
return new Signature(_guard, r, hexlify(s), v);
}
return throwError("invlaid raw signature length");
assertError(false, "invlaid raw signature length");
}
if (sig instanceof Signature) { return sig.clone(); }
// Get r
const r = sig.r;
if (r == null) { throwError("missing r"); }
if (!isHexString(r, 32)) { throwError("invalid r"); }
assertError(r != null, "missing r");
assertError(isHexString(r, 32), "invalid r");
// Get s; by any means necessary (we check consistency below)
const s = (function(s?: string, yParityAndS?: string) {
if (s != null) {
if (!isHexString(s, 32)) { throwError("invalid s"); }
assertError(isHexString(s, 32), "invalid s");
return s;
}
if (yParityAndS != null) {
if (!isHexString(yParityAndS, 32)) { throwError("invalid yParityAndS"); }
assertError(isHexString(yParityAndS, 32), "invalid yParityAndS");
const bytes = getBytes(yParityAndS);
bytes[0] &= 0x7f;
return hexlify(bytes);
}
return throwError("missing s");
assertError(false, "missing s");
})(sig.s, sig.yParityAndS);
if (getBytes(s)[0] & 0x80) { throwError("non-canonical s"); }
assertError((getBytes(s)[0] & 0x80) == 0, "non-canonical s");
// Get v; by any means necessary (we check consistency below)
const { networkV, v } = (function(_v?: BigNumberish, yParityAndS?: string, yParity?: number): { networkV?: bigint, v: 27 | 28 } {
@ -229,7 +220,7 @@ export class Signature implements Freezable<Signature> {
}
if (yParityAndS != null) {
if (!isHexString(yParityAndS, 32)) { throwError("invalid yParityAndS"); }
assertError(isHexString(yParityAndS, 32), "invalid yParityAndS");
return { v: ((getBytes(yParityAndS)[0] & 0x80) ? 28: 27) };
}
@ -238,21 +229,18 @@ export class Signature implements Freezable<Signature> {
case 0: return { v: 27 };
case 1: return { v: 28 };
}
return throwError("invalid yParity");
assertError(false, "invalid yParity");
}
return throwError("missing v");
assertError(false, "missing v");
})(sig.v, sig.yParityAndS, sig.yParity);
const result = new Signature(_guard, r, s, v);
if (networkV) { setStore(result.#props, "networkV", networkV); }
// If multiple of v, yParity, yParityAndS we given, check they match
if ("yParity" in sig && sig.yParity !== result.yParity) {
throwError("yParity mismatch");
} else if ("yParityAndS" in sig && sig.yParityAndS !== result.yParityAndS) {
throwError("yParityAndS mismatch");
}
assertError(!("yParity" in sig && sig.yParity !== result.yParity), "yParity mismatch");
assertError(!("yParityAndS" in sig && sig.yParityAndS !== result.yParityAndS), "yParityAndS mismatch");
return result;
}

@ -3,7 +3,7 @@ import * as secp256k1 from "@noble/secp256k1";
import {
concat, dataLength, getBytes, getBytesCopy, hexlify, toHex,
assertArgument, throwArgumentError
assertArgument
} from "../utils/index.js";
import { computeHmac } from "./hmac.js";
@ -87,7 +87,7 @@ export class SigningKey {
const pubKey = secp256k1.recoverPublicKey(getBytesCopy(digest), der, sig.yParity);
if (pubKey != null) { return hexlify(pubKey); }
return throwArgumentError("invalid signautre for digest", "signature", signature);
assertArgument(false, "invalid signautre for digest", "signature", signature);
}
static _addPoints(p0: BytesLike, p1: BytesLike, compressed?: boolean): string {

@ -81,14 +81,14 @@ export {
concat, dataLength, dataSlice, getBytes, getBytesCopy, hexlify,
isHexString, isBytesLike, stripZerosLeft, zeroPadBytes, zeroPadValue,
assertArgument, assertArgumentCount, assertNormalize, assertPrivate,
makeError, throwArgumentError, throwError,
makeError, throwError,
isCallException, isError,
getIpfsGatewayFunc, FetchRequest, FetchResponse, FetchCancelSignal,
FixedFormat, FixedNumber, formatFixed, parseFixed,
getBigInt, getNumber, toArray, toBigInt, toHex, toNumber, toQuantity,
fromTwos, toTwos, mask,
formatEther, parseEther, formatUnits, parseUnits,
_toEscapedUtf8String, toUtf8Bytes, toUtf8CodePoints, toUtf8String,
toUtf8Bytes, toUtf8CodePoints, toUtf8String,
Utf8ErrorFuncs,
decodeRlp, encodeRlp
} from "./utils/index.js";

@ -1,7 +1,7 @@
import { keccak256 } from "../crypto/index.js";
import {
concat, hexlify, throwArgumentError, toUtf8Bytes, toUtf8String
concat, hexlify, assertArgument, toUtf8Bytes, toUtf8String
} from "../utils/index.js";
@ -56,9 +56,7 @@ export function isValidName(name: string): boolean {
export function namehash(name: string): string {
/* istanbul ignore if */
if (typeof(name) !== "string") {
throwArgumentError("invalid ENS name; not a string", "name", name);
}
assertArgument(typeof(name) === "string", "invalid ENS name; not a string", "name", name);
let result: string | Uint8Array = Zeros;

@ -3,7 +3,7 @@ import {
} from "../crypto/index.js";
import {
concat, dataLength, getBytes, hexlify, toArray, toTwos, toUtf8Bytes, zeroPadBytes, zeroPadValue,
throwArgumentError
assertArgument
} from "../utils/index.js";
@ -31,9 +31,7 @@ function _pack(type: string, value: any, isArray?: boolean): Uint8Array {
if (match) {
let size = parseInt(match[2] || "256")
if ((match[2] && String(size) !== match[2]) || (size % 8 !== 0) || size === 0 || size > 256) {
return throwArgumentError("invalid number type", "type", type)
}
assertArgument((!match[2] || match[2] === String(size)) && (size % 8 === 0) && size !== 0 && size <= 256, "invalid number type", "type", type);
if (isArray) { size = 256; }
@ -46,12 +44,9 @@ function _pack(type: string, value: any, isArray?: boolean): Uint8Array {
if (match) {
const size = parseInt(match[1]);
if (String(size) !== match[1] || size === 0 || size > 32) {
return throwArgumentError("invalid bytes type", "type", type)
}
if (dataLength(value) !== size) {
return throwArgumentError(`invalid value for ${ type }`, "value", value)
}
assertArgument(String(size) === match[1] && size !== 0 && size <= 32, "invalid bytes type", "type", type);
assertArgument(dataLength(value) === size, `invalid value for ${ type }`, "value", value);
if (isArray) { return getBytes(zeroPadBytes(value, 32)); }
return value;
}
@ -60,9 +55,8 @@ function _pack(type: string, value: any, isArray?: boolean): Uint8Array {
if (match && Array.isArray(value)) {
const baseType = match[1];
const count = parseInt(match[2] || String(value.length));
if (count != value.length) {
throwArgumentError(`invalid array length for ${ type }`, "value", value)
}
assertArgument(count === value.length, `invalid array length for ${ type }`, "value", value);
const result: Array<Uint8Array> = [];
value.forEach(function(value) {
result.push(_pack(baseType, value, true));
@ -70,15 +64,14 @@ function _pack(type: string, value: any, isArray?: boolean): Uint8Array {
return getBytes(concat(result));
}
return throwArgumentError("invalid type", "type", type)
assertArgument(false, "invalid type", "type", type)
}
// @TODO: Array Enum
export function solidityPacked(types: ReadonlyArray<string>, values: ReadonlyArray<any>): string {
if (types.length != values.length) {
throwArgumentError("wrong number of values; expected ${ types.length }", "values", values)
}
assertArgument(types.length === values.length, "wrong number of values; expected ${ types.length }", "values", values);
const tight: Array<Uint8Array> = [];
types.forEach(function(type, index) {
tight.push(_pack(type, values[index]));

@ -3,7 +3,7 @@ import { getAddress } from "../address/index.js";
import { keccak256 } from "../crypto/index.js";
import {
concat, defineProperties, getBigInt, getBytes, hexlify, isHexString, mask, toHex, toTwos, zeroPadValue,
throwArgumentError
assertArgument
} from "../utils/index.js";
import { id } from "./id.js";
@ -58,9 +58,7 @@ const domainFieldNames: Array<string> = [
function checkString(key: string): (value: any) => string {
return function (value: any){
if (typeof(value) !== "string") {
throwArgumentError(`invalid domain value for ${ JSON.stringify(key) }`, `domain.${ key }`, value);
}
assertArgument(typeof(value) === "string", `invalid domain value for ${ JSON.stringify(key) }`, `domain.${ key }`, value);
return value;
}
}
@ -75,13 +73,11 @@ const domainChecks: Record<string, (value: any) => any> = {
try {
return getAddress(value).toLowerCase();
} catch (error) { }
return throwArgumentError(`invalid domain value "verifyingContract"`, "domain.verifyingContract", value);
assertArgument(false, `invalid domain value "verifyingContract"`, "domain.verifyingContract", value);
},
salt: function(value: any) {
const bytes = getBytes(value, "domain.salt");
if (bytes.length !== 32) {
throwArgumentError(`invalid domain value "salt"`, "domain.salt", value);
}
assertArgument(bytes.length === 32, `invalid domain value "salt"`, "domain.salt", value);
return hexlify(bytes);
}
}
@ -94,9 +90,7 @@ function getBaseEncoder(type: string): null | ((value: any) => string) {
const signed = (match[1] === "");
const width = parseInt(match[2] || "256");
if (width % 8 !== 0 || width > 256 || (match[2] && match[2] !== String(width))) {
throwArgumentError("invalid numeric width", "type", type);
}
assertArgument(width % 8 === 0 && width !== 0 && width <= 256 && (match[2] == null || match[2] === String(width)), "invalid numeric width", "type", type);
const boundsUpper = mask(BN_MAX_UINT256, signed ? (width - 1): width);
const boundsLower = signed ? ((boundsUpper + BN_1) * BN__1): BN_0;
@ -104,9 +98,7 @@ function getBaseEncoder(type: string): null | ((value: any) => string) {
return function(_value: BigNumberish) {
const value = getBigInt(_value, "value");
if (value < boundsLower || value > boundsUpper) {
throwArgumentError(`value out-of-bounds for ${ type }`, "value", value);
}
assertArgument(value >= boundsLower && value <= boundsUpper, `value out-of-bounds for ${ type }`, "value", value);
return toHex(toTwos(value, 256), 32);
};
@ -118,15 +110,11 @@ function getBaseEncoder(type: string): null | ((value: any) => string) {
const match = type.match(/^bytes(\d+)$/);
if (match) {
const width = parseInt(match[1]);
if (width === 0 || width > 32 || match[1] !== String(width)) {
throwArgumentError("invalid bytes width", "type", type);
}
assertArgument(width !== 0 && width <= 32 && match[1] === String(width), "invalid bytes width", "type", type);
return function(value: BytesLike) {
const bytes = getBytes(value);
if (bytes.length !== width) {
throwArgumentError(`invalid length for ${ type }`, "value", value);
}
assertArgument(bytes.length === width, `invalid length for ${ type }`, "value", value);
return hexPadRight(value);
};
}
@ -192,24 +180,18 @@ export class TypedDataEncoder {
for (const field of types[name]) {
// Check each field has a unique name
if (uniqueNames.has(field.name)) {
throwArgumentError(`duplicate variable name ${ JSON.stringify(field.name) } in ${ JSON.stringify(name) }`, "types", types);
}
assertArgument(!uniqueNames.has(field.name), `duplicate variable name ${ JSON.stringify(field.name) } in ${ JSON.stringify(name) }`, "types", types);
uniqueNames.add(field.name);
// Get the base type (drop any array specifiers)
const baseType = (<any>(field.type.match(/^([^\x5b]*)(\x5b|$)/)))[1] || null;
if (baseType === name) {
throwArgumentError(`circular type reference to ${ JSON.stringify(baseType) }`, "types", types);
}
assertArgument(baseType !== name, `circular type reference to ${ JSON.stringify(baseType) }`, "types", types);
// Is this a base encoding type?
const encoder = getBaseEncoder(baseType);
if (encoder) { continue; }
if (!parents.has(baseType)) {
throwArgumentError(`unknown type ${ JSON.stringify(baseType) }`, "types", types);
}
assertArgument(parents.has(baseType), `unknown type ${ JSON.stringify(baseType) }`, "types", types);
// Add linkage
(parents.get(baseType) as Array<string>).push(name);
@ -219,20 +201,14 @@ export class TypedDataEncoder {
// Deduce the primary type
const primaryTypes = Array.from(parents.keys()).filter((n) => ((parents.get(n) as Array<string>).length === 0));
if (primaryTypes.length === 0) {
throwArgumentError("missing primary type", "types", types);
} else if (primaryTypes.length > 1) {
throwArgumentError(`ambiguous primary types or unused types: ${ primaryTypes.map((t) => (JSON.stringify(t))).join(", ") }`, "types", types);
}
assertArgument(primaryTypes.length !== 0, "missing primary type", "types", types);
assertArgument(primaryTypes.length === 1, `ambiguous primary types or unused types: ${ primaryTypes.map((t) => (JSON.stringify(t))).join(", ") }`, "types", types);
defineProperties<TypedDataEncoder>(this, { primaryType: primaryTypes[0] });
// Check for circular type references
function checkCircular(type: string, found: Set<string>) {
if (found.has(type)) {
throwArgumentError(`circular type reference to ${ JSON.stringify(type) }`, "types", types);
}
assertArgument(!found.has(type), `circular type reference to ${ JSON.stringify(type) }`, "types", types);
found.add(type);
@ -282,11 +258,8 @@ export class TypedDataEncoder {
if (match) {
const subtype = match[1];
const subEncoder = this.getEncoder(subtype);
const length = parseInt(match[3]);
return (value: Array<any>) => {
if (length >= 0 && value.length !== length) {
throwArgumentError("array length mismatch; expected length ${ arrayLength }", "value", value);
}
assertArgument(!match[3] || parseInt(match[3]) === value.length, `array length mismatch; expected length ${ parseInt(match[3]) }`, "value", value);
let result = value.map(subEncoder);
if (this.#fullTypes.has(subtype)) {
@ -312,14 +285,12 @@ export class TypedDataEncoder {
}
}
return throwArgumentError(`unknown type: ${ type }`, "type", type);
assertArgument(false, `unknown type: ${ type }`, "type", type);
}
encodeType(name: string): string {
const result = this.#fullTypes.get(name);
if (!result) {
return throwArgumentError(`unknown type: ${ JSON.stringify(name) }`, "name", name);
}
assertArgument(result, `unknown type: ${ JSON.stringify(name) }`, "name", name);
return result;
}
@ -349,12 +320,8 @@ export class TypedDataEncoder {
// Array
const match = type.match(/^(.*)(\x5b(\d*)\x5d)$/);
if (match) {
const subtype = match[1];
const length = parseInt(match[3]);
if (length >= 0 && value.length !== length) {
throwArgumentError("array length mismatch; expected length ${ arrayLength }", "value", value);
}
return value.map((v: any) => this._visit(subtype, v, callback));
assertArgument(!match[3] || parseInt(match[3]) === value.length, `array length mismatch; expected length ${ parseInt(match[3]) }`, "value", value);
return value.map((v: any) => this._visit(match[1], v, callback));
}
// Struct
@ -366,7 +333,7 @@ export class TypedDataEncoder {
}, <Record<string, any>>{});
}
return throwArgumentError(`unknown type: ${ type }`, "type", type);
assertArgument(false, `unknown type: ${ type }`, "type", type);
}
visit(value: Record<string, any>, callback: (type: string, data: any) => any): any {
@ -389,9 +356,7 @@ export class TypedDataEncoder {
const domainFields: Array<TypedDataField> = [ ];
for (const name in domain) {
const type = domainFieldTypes[name];
if (!type) {
throwArgumentError(`invalid typed-data domain key: ${ JSON.stringify(name) }`, "domain", domain);
}
assertArgument(type, `invalid typed-data domain key: ${ JSON.stringify(name) }`, "domain", domain);
domainFields.push({ name, type });
}
@ -475,11 +440,9 @@ export class TypedDataEncoder {
const encoder = TypedDataEncoder.from(types);
const typesWithDomain = Object.assign({ }, types);
if (typesWithDomain.EIP712Domain) {
throwArgumentError("types must not contain EIP712Domain type", "types.EIP712Domain", types);
} else {
assertArgument(typesWithDomain.EIP712Domain == null, "types must not contain EIP712Domain type", "types.EIP712Domain", types);
typesWithDomain.EIP712Domain = domainTypes;
}
// Validate the data structures and types
encoder.encode(value);
@ -506,13 +469,11 @@ export class TypedDataEncoder {
case "bool":
return !!value;
case "string":
if (typeof(value) !== "string") {
throwArgumentError(`invalid string`, "value", value);
}
assertArgument(typeof(value) === "string", "invalid string", "value", value);
return value;
}
return throwArgumentError("unsupported type", "type", type);
assertArgument(false, "unsupported type", "type", type);
})
};
}

@ -11,7 +11,7 @@ import { Transaction } from "../transaction/index.js";
import {
concat, dataLength, dataSlice, hexlify, isHexString,
getBigInt, getBytes, getNumber,
isCallException, makeError, throwError, throwArgumentError,
isCallException, makeError, throwError, assertArgument,
FetchRequest,
toArray, toQuantity,
defineProperties, EventPayload, resolveProperties,
@ -198,7 +198,7 @@ async function getSubscription(_event: ProviderEvent, provider: AbstractProvider
return { filter, tag: getTag("event", filter), type: "event" };
}
return throwArgumentError("unknown ProviderEvent", "event", _event);
assertArgument(false, "unknown ProviderEvent", "event", _event);
}
function getTime(): number { return (new Date()).getTime(); }
@ -500,7 +500,7 @@ export class AbstractProvider implements Provider {
return this.getBlockNumber().then((b) => toQuantity(b + blockTag));
}
return throwArgumentError("invalid blockTag", "blockTag", blockTag);
assertArgument(false, "invalid blockTag", "blockTag", blockTag);
}
_getFilter(filter: Filter | FilterByBlockHash): PerformActionFilter | Promise<PerformActionFilter> {

@ -1,7 +1,7 @@
import { Transaction } from "../transaction/index.js";
import {
defineProperties, getBigInt, resolveProperties,
throwArgumentError, throwError
assertArgument, throwError
} from "../utils/index.js";
import type { TypedDataDomain, TypedDataField } from "../hash/index.js";
@ -40,9 +40,7 @@ export abstract class AbstractSigner<P extends null | Provider = null | Provider
if (pop.to != null) {
pop.to = provider.resolveName(pop.to).then((to) => {
if (to == null) {
return throwArgumentError("transaction to ENS name not configured", "tx.to", pop.to);
}
assertArgument(to != null, "transaction to ENS name not configured", "tx.to", pop.to);
return to;
});
}
@ -53,9 +51,8 @@ export abstract class AbstractSigner<P extends null | Provider = null | Provider
this.getAddress(),
this.resolveName(from)
]).then(([ address, from ]) => {
if (!from || address.toLowerCase() !== from.toLowerCase()) {
return throwArgumentError("transaction from mismatch", "tx.from", from);
}
assertArgument(from && address.toLowerCase() === from.toLowerCase(),
"transaction from mismatch", "tx.from", from);
return address;
});
}
@ -84,9 +81,7 @@ export abstract class AbstractSigner<P extends null | Provider = null | Provider
const network = await (<Provider>(this.provider)).getNetwork();
if (pop.chainId != null) {
const chainId = getBigInt(pop.chainId);
if (chainId !== network.chainId) {
throwArgumentError("transaction chainId mismatch", "tx.chainId", tx.chainId);
}
assertArgument(chainId === network.chainId, "transaction chainId mismatch", "tx.chainId", tx.chainId);
} else {
pop.chainId = network.chainId;
}
@ -94,9 +89,9 @@ export abstract class AbstractSigner<P extends null | Provider = null | Provider
// Do not allow mixing pre-eip-1559 and eip-1559 properties
const hasEip1559 = (pop.maxFeePerGas != null || pop.maxPriorityFeePerGas != null);
if (pop.gasPrice != null && (pop.type === 2 || hasEip1559)) {
throwArgumentError("eip-1559 transaction do not support gasPrice", "tx", tx);
assertArgument(false, "eip-1559 transaction do not support gasPrice", "tx", tx);
} else if ((pop.type === 0 || pop.type === 1) && hasEip1559) {
throwArgumentError("pre-eip-1559 transaction do not support maxFeePerGas/maxPriorityFeePerGas", "tx", tx);
assertArgument(false, "pre-eip-1559 transaction do not support maxFeePerGas/maxPriorityFeePerGas", "tx", tx);
}
if ((pop.type === 2 || pop.type == null) && (pop.maxFeePerGas != null && pop.maxPriorityFeePerGas != null)) {

@ -5,7 +5,7 @@ import {
concat, dataSlice, getBytes, hexlify, zeroPadValue,
defineProperties, encodeBase58, getBigInt, toArray,
toNumber, toUtf8Bytes, toUtf8String,
throwArgumentError, throwError,
assertArgument, throwError,
FetchRequest
} from "../utils/index.js";
@ -81,9 +81,8 @@ function encodeBytes(datas: Array<BytesLike>) {
}
function callAddress(value: string): string {
if (value.length !== 66 || dataSlice(value, 0, 12) !== "0x000000000000000000000000") {
throwArgumentError("invalid call address", "value", value);
}
assertArgument(value.length === 66 && dataSlice(value, 0, 12) === "0x000000000000000000000000",
"invalid call address", "value", value);
return getAddress("0x" + value.substring(26));
}
@ -95,7 +94,7 @@ function getIpfsLink(link: string): string {
} else if (link.match(/^ipfs:\/\//i)) {
link = link.substring(7);
} else {
throwArgumentError("unsupported IPFS format", "link", link);
assertArgument(false, "unsupported IPFS format", "link", link);
}
return `https:/\/gateway.ipfs.io/ipfs/${ link }`;

@ -4,7 +4,7 @@ import { Signature } from "../crypto/index.js"
import { accessListify } from "../transaction/index.js";
import {
getBigInt, getNumber, hexlify, isHexString, zeroPadValue,
throwArgumentError, throwError
assertArgument, throwError
} from "../utils/index.js";
@ -63,20 +63,16 @@ export function formatBoolean(value: any): boolean {
case false: case "false":
return false;
}
return throwArgumentError(`invalid boolean; ${ JSON.stringify(value) }`, "value", value);
assertArgument(false, `invalid boolean; ${ JSON.stringify(value) }`, "value", value);
}
export function formatData(value: string): string {
if (!isHexString(value, true)) {
throwArgumentError("", "value", value);
}
assertArgument(isHexString(value, true), "invalid data", "value", value);
return value;
}
export function formatHash(value: any): string {
if (!isHexString(value, 32)) {
throwArgumentError("", "value", value);
}
assertArgument(isHexString(value, 32), "invalid hash", "value", value);
return value;
}

@ -1,6 +1,6 @@
import { accessListify } from "../transaction/index.js";
import {
getStore, getBigInt, setStore, throwArgumentError
getStore, getBigInt, setStore, assertArgument
} from "../utils/index.js";
import { EnsPlugin, GasCostPlugin } from "./plugins-network.js";
@ -192,7 +192,7 @@ export class Network {
return new Network("unknown", network);
}
throwArgumentError("unknown network", "network", network);
assertArgument(false, "unknown network", "network", network);
}
// Clonable with network-like abilities
@ -205,9 +205,8 @@ export class Network {
// Networkish
if (typeof(network) === "object") {
if (typeof(network.name) !== "string" || typeof(network.chainId) !== "number") {
throwArgumentError("invalid network object name or chainId", "network", network);
}
assertArgument(typeof(network.name) === "string" && typeof(network.chainId) === "number",
"invalid network object name or chainId", "network", network);
const custom = new Network(<string>(network.name), <number>(network.chainId));
@ -222,7 +221,7 @@ export class Network {
return custom;
}
return throwArgumentError("invalid network", "network", network);
assertArgument(false, "invalid network", "network", network);
}
/**
@ -233,7 +232,7 @@ export class Network {
if (typeof(nameOrChainId) === "number") { nameOrChainId = BigInt(nameOrChainId); }
const existing = Networks.get(nameOrChainId);
if (existing) {
throwArgumentError(`conflicting network for ${ JSON.stringify(existing.name) }`, "nameOrChainId", nameOrChainId);
assertArgument(false, `conflicting network for ${ JSON.stringify(existing.name) }`, "nameOrChainId", nameOrChainId);
}
Networks.set(nameOrChainId, networkFunc);
}

@ -1,6 +1,6 @@
import { defineProperties } from "../utils/properties.js";
import { throwArgumentError } from "../utils/index.js";
import { assertArgument } from "../utils/index.js";
import type { FeeData, Provider } from "./provider.js";
@ -52,9 +52,7 @@ export class GasCostPlugin extends NetworkPlugin implements GasCostParameters {
function set(name: keyof GasCostParameters, nullish: number): void {
let value = (costs || { })[name];
if (value == null) { value = nullish; }
if (typeof(value) !== "number") {
throwArgumentError(`invalud value for ${ name }`, "costs", costs);
}
assertArgument(typeof(value) === "number", `invalud value for ${ name }`, "costs", costs);
props[name] = value;
}

@ -1,6 +1,6 @@
import {
defineProperties, resolveProperties, throwArgumentError, throwError,
defineProperties, resolveProperties, assertArgument, throwError,
FetchRequest
} from "../utils/index.js";
@ -36,7 +36,7 @@ function getHost(name: string): string {
return "opt-goerli.g.alchemy.com";
}
return throwArgumentError("unsupported network", "network", name);
assertArgument(false, "unsupported network", "network", name);
}
export class AlchemyProvider extends JsonRpcProvider implements CommunityResourcable {

@ -1,5 +1,5 @@
import {
defineProperties, FetchRequest, throwArgumentError
defineProperties, FetchRequest, assertArgument
} from "../utils/index.js";
import { AbstractProvider } from "./abstract-provider.js";
@ -28,7 +28,8 @@ function getHost(name: string): string {
case "arbitrum":
return "rpc.ankr.com/arbitrum";
}
return throwArgumentError("unsupported network", "network", name);
assertArgument(false, "unsupported network", "network", name);
}

@ -1,4 +1,4 @@
import { throwArgumentError } from "../utils/index.js";
import { assertArgument } from "../utils/index.js";
import { Network } from "./network.js";
import { JsonRpcProvider } from "./provider-jsonrpc.js";
@ -9,9 +9,7 @@ import type { Networkish } from "./network.js";
export class CloudflareProvider extends JsonRpcProvider {
constructor(_network: Networkish = "mainnet") {
const network = Network.from(_network);
if (network.name !== "mainnet") {
return throwArgumentError("unsupported network", "network", _network);
}
assertArgument(network.name === "mainnet", "unsupported network", "network", _network);
super("https:/\/cloudflare-eth.com/", network, { staticNetwork: network });
}
}

@ -4,7 +4,7 @@ import {
defineProperties,
hexlify, toQuantity,
FetchRequest,
throwArgumentError, throwError,
assertArgument, throwError,
toUtf8String
} from "../utils/index.js";
@ -103,7 +103,7 @@ export class BaseEtherscanProvider extends AbstractProvider {
default:
}
return throwArgumentError("unsupported network", "network", this.network);
assertArgument(false, "unsupported network", "network", this.network);
}
getUrl(module: string, params: Record<string, string>): string {

@ -1,6 +1,6 @@
import {
getBigInt, getNumber, hexlify, throwError, throwArgumentError
getBigInt, getNumber, hexlify, throwError, assertArgument
} from "../utils/index.js";
import { AbstractProvider } from "./abstract-provider.js";
@ -284,9 +284,8 @@ export class FallbackProvider extends AbstractProvider {
this.eventQuorum = 1;
this.eventWorkers = 1;
if (this.quorum > this.#configs.reduce((a, c) => (a + c.weight), 0)) {
throwArgumentError("quorum exceed provider wieght", "quorum", this.quorum);
}
assertArgument(this.quorum <= this.#configs.reduce((a, c) => (a + c.weight), 0),
"quorum exceed provider wieght", "quorum", this.quorum);
}
// @TOOD: Copy these and only return public values

@ -1,5 +1,5 @@
import {
defineProperties, FetchRequest, throwArgumentError, throwError
defineProperties, FetchRequest, assertArgument, throwError
} from "../utils/index.js";
import { showThrottleMessage } from "./community.js";
@ -37,7 +37,7 @@ function getHost(name: string): string {
return "optimism-goerli.infura.io";
}
return throwArgumentError("unsupported network", "network", name);
assertArgument(false, "unsupported network", "network", name);
}
export class InfuraWebSocketProvider extends WebSocketProvider implements CommunityResourcable {

@ -9,7 +9,7 @@ import { TypedDataEncoder } from "../hash/index.js";
import { accessListify } from "../transaction/index.js";
import {
defineProperties, getBigInt, hexlify, isHexString, toQuantity, toUtf8Bytes,
makeError, throwArgumentError, throwError,
makeError, assertArgument, throwError,
FetchRequest, resolveProperties
} from "../utils/index.js";
@ -220,9 +220,8 @@ export class JsonRpcSigner extends AbstractSigner<JsonRpcApiProvider> {
const _from = tx.from;
promises.push((async () => {
const from = await resolveAddress(_from, this.provider);
if (from == null || from.toLowerCase() !== this.address.toLowerCase()) {
throwArgumentError("from address mismatch", "transaction", _tx);
}
assertArgument(from != null && from.toLowerCase() === this.address.toLowerCase(),
"from address mismatch", "transaction", _tx);
tx.from = from;
})());
} else {
@ -287,9 +286,8 @@ export class JsonRpcSigner extends AbstractSigner<JsonRpcApiProvider> {
// Make sure the from matches the sender
if (tx.from) {
const from = await resolveAddress(tx.from, this.provider);
if (from == null || from.toLowerCase() !== this.address.toLowerCase()) {
return throwArgumentError("from address mismatch", "transaction", _tx);
}
assertArgument(from != null && from.toLowerCase() === this.address.toLowerCase(),
"from address mismatch", "transaction", _tx);
tx.from = from;
} else {
tx.from = this.address;
@ -312,9 +310,7 @@ export class JsonRpcSigner extends AbstractSigner<JsonRpcApiProvider> {
// Populate any ENS names (in-place)
const populated = await TypedDataEncoder.resolveNames(domain, types, value, async (value: string) => {
const address = await resolveAddress(value);
if (address == null) {
return throwArgumentError("TypedData does not support null address", "value", value);
}
assertArgument(address != null, "TypedData does not support null address", "value", value);
return address;
});
@ -462,9 +458,8 @@ export class JsonRpcApiProvider extends AbstractProvider {
// This could be relaxed in the future to just check equivalent networks
const staticNetwork = this._getOption("staticNetwork");
if (staticNetwork) {
if (staticNetwork !== network) {
throwArgumentError("staticNetwork MUST match network object", "options", options);
}
assertArgument(staticNetwork === network,
"staticNetwork MUST match network object", "options", options);
this.#network = staticNetwork;
}
}

@ -3,7 +3,7 @@ import { getAddress } from "../address/index.js";
import { keccak256, Signature } from "../crypto/index.js";
import {
concat, decodeRlp, encodeRlp, getBytes, getStore, getBigInt, getNumber, hexlify,
setStore, throwArgumentError, toArray, zeroPadValue
setStore, assertArgument, toArray, zeroPadValue
} from "../utils/index.js";
import { accessListify } from "./accesslist.js";
@ -56,7 +56,7 @@ function handleData(value: string, param: string): string {
try {
return hexlify(value);
} catch (error) {
return throwArgumentError("invalid data", param, value);
assertArgument(false, "invalid data", param, value);
}
}
@ -64,7 +64,7 @@ function handleAccessList(value: any, param: string): AccessList {
try {
return accessListify(value);
} catch (error) {
return throwArgumentError("invalid accessList", param, value);
assertArgument(false, "invalid accessList", param, value);
}
}
@ -76,16 +76,14 @@ function handleNumber(_value: string, param: string): number {
function handleUint(_value: string, param: string): bigint {
if (_value === "0x") { return BN_0; }
const value = getBigInt(_value, param);
if (value > BN_MAX_UINT) { throwArgumentError("value exceeds uint size", param, value); }
assertArgument(value <= BN_MAX_UINT, "value exceeds uint size", param, value);
return value;
}
function formatNumber(_value: BigNumberish, name: string): Uint8Array {
const value = getBigInt(_value, "value");
const result = toArray(value);
if (result.length > 32) {
throwArgumentError(`value too large`, `tx.${ name }`, value);
}
assertArgument(result.length <= 32, `value too large`, `tx.${ name }`, value);
return result;
}
@ -96,9 +94,8 @@ function formatAccessList(value: AccessListish): Array<[ string, Array<string> ]
function _parseLegacy(data: Uint8Array): TransactionLike {
const fields: any = decodeRlp(data);
if (!Array.isArray(fields) || (fields.length !== 9 && fields.length !== 6)) {
return throwArgumentError("invalid field count for legacy transaction", "data", data);
}
assertArgument(Array.isArray(fields) && (fields.length === 9 || fields.length === 6),
"invalid field count for legacy transaction", "data", data);
const tx: TransactionLike = {
type: 0,
@ -130,9 +127,7 @@ function _parseLegacy(data: Uint8Array): TransactionLike {
tx.chainId = chainId
// Signed Legacy Transaction
if (chainId === BN_0 && (v < BN_27 || v > BN_28)) {
throwArgumentError("non-canonical legacy v", "v", fields[6]);
}
assertArgument(chainId !== BN_0 || (v === BN_27 || v === BN_28), "non-canonical legacy v", "v", fields[6]);
tx.signature = Signature.from({
r: zeroPadValue(fields[7], 32),
@ -163,9 +158,8 @@ function _serializeLegacy(tx: Transaction, sig?: Signature): string {
// We have a chainId in the tx and an EIP-155 v in the signature,
// make sure they agree with each other
if (sig && sig.networkV != null && sig.legacyChainId !== chainId) {
throwArgumentError("tx.chainId/sig.v mismatch", "sig", sig);
}
assertArgument(!sig || sig.networkV == null || sig.legacyChainId === chainId,
"tx.chainId/sig.v mismatch", "sig", sig);
} else if (sig) {
// No chainId provided, but the signature is signing with EIP-155; derive chainId
@ -190,7 +184,7 @@ function _serializeLegacy(tx: Transaction, sig?: Signature): string {
if (chainId !== BN_0) {
v = Signature.getChainIdV(chainId, sig.v);
} else if (BigInt(sig.v) !== v) {
throwArgumentError("tx.chainId/sig.v mismatch", "sig", sig);
assertArgument(false, "tx.chainId/sig.v mismatch", "sig", sig);
}
fields.push(toArray(v));
@ -206,7 +200,7 @@ function _parseEipSignature(tx: TransactionLike, fields: Array<string>, serializ
yParity = handleNumber(fields[0], "yParity");
if (yParity !== 0 && yParity !== 1) { throw new Error("bad yParity"); }
} catch (error) {
return throwArgumentError("invalid yParity", "yParity", fields[0]);
assertArgument(false, "invalid yParity", "yParity", fields[0]);
}
const r = zeroPadValue(fields[1], 32);
@ -219,9 +213,8 @@ function _parseEipSignature(tx: TransactionLike, fields: Array<string>, serializ
function _parseEip1559(data: Uint8Array): TransactionLike {
const fields: any = decodeRlp(getBytes(data).slice(1));
if (!Array.isArray(fields) || (fields.length !== 9 && fields.length !== 12)) {
throwArgumentError("invalid field count for transaction type: 2", "data", hexlify(data));
}
assertArgument(Array.isArray(fields) && (fields.length === 9 || fields.length === 12),
"invalid field count for transaction type: 2", "data", hexlify(data));
const maxPriorityFeePerGas = handleUint(fields[2], "maxPriorityFeePerGas");
const maxFeePerGas = handleUint(fields[3], "maxFeePerGas");
@ -274,9 +267,8 @@ function _serializeEip1559(tx: TransactionLike, sig?: Signature): string {
function _parseEip2930(data: Uint8Array): TransactionLike {
const fields: any = decodeRlp(getBytes(data).slice(1));
if (!Array.isArray(fields) || (fields.length !== 8 && fields.length !== 11)) {
throwArgumentError("invalid field count for transaction type: 1", "data", hexlify(data));
}
assertArgument(Array.isArray(fields) && (fields.length === 8 || fields.length === 11),
"invalid field count for transaction type: 1", "data", hexlify(data));
const tx: TransactionLike = {
type: 1,

@ -1,6 +1,6 @@
import { getBytes } from "./data.js";
import { throwArgumentError } from "./errors.js";
import { assertArgument } from "./errors.js";
import { toBigInt, toHex } from "./maths.js";
import type { BytesLike } from "./index.js";
@ -17,9 +17,7 @@ function getAlpha(letter: string): bigint {
}
}
const result = Lookup[letter];
if (result == null) {
throwArgumentError(`invalid base58 value`, "letter", letter);
}
assertArgument(result != null, `invalid base58 value`, "letter", letter);
return result;
}

@ -1,4 +1,4 @@
import { throwArgumentError, throwError } from "./errors.js";
import { assertArgument, throwError } from "./errors.js";
export type BytesLike = string | Uint8Array;
@ -19,7 +19,7 @@ function _getBytes(value: BytesLike, name?: string, copy?: boolean): Uint8Array
return result;
}
return throwArgumentError("invalid BytesLike value", name || "value", value);
assertArgument(false, "invalid BytesLike value", name || "value", value);
}
/**

@ -327,16 +327,6 @@ export function throwError<K extends ErrorCode, T extends CodedEthersError<K>>(m
throw makeError(message, code, info);
}
/**
* Throws an [[api:ArgumentError]] with %%message%% for the parameter with
* %%name%% and the %%value%%.
*/
export function throwArgumentError(message: string, name: string, value: any): never {
return throwError(message, "INVALID_ARGUMENT", {
argument: name,
value: value
});
}
/**
* A simple helper to simply ensuring provided arguments match expected
@ -346,7 +336,9 @@ export function throwArgumentError(message: string, name: string, value: any): n
* any further code does not need additional compile-time checks.
*/
export function assertArgument(check: unknown, message: string, name: string, value: unknown): asserts check {
if (!check) { throwArgumentError(message, name, value); }
if (!check) {
throwError(message, "INVALID_ARGUMENT", { argument: name, value: value });
}
}
export function assertArgumentCount(count: number, expectedCount: number, message: string = ""): void {

@ -1,6 +1,6 @@
import { decodeBase64, encodeBase64 } from "./base64.js";
import { hexlify } from "./data.js";
import { assertArgument, throwArgumentError, throwError } from "./errors.js";
import { assertArgument, throwError } from "./errors.js";
import { defineProperties } from "./properties.js";
import { toUtf8Bytes, toUtf8String } from "./utf8.js"
@ -310,9 +310,7 @@ export class FetchRequest implements Iterable<[ key: string, value: string ]> {
* Sets an ``Authorization`` for %%username%% with %%password%%.
*/
setCredentials(username: string, password: string): void {
if (username.match(/:/)) {
throwArgumentError("invalid basic authentication username", "username", "[REDACTED]");
}
assertArgument(!username.match(/:/), "invalid basic authentication username", "username", "[REDACTED]");
this.#creds = `${ username }:${ password }`;
}
@ -762,8 +760,8 @@ export class FetchResponse implements Iterable<[ key: string, value: string ]> {
throwThrottleError(message?: string, stall?: number): never {
if (stall == null) {
stall = -1;
} else if (typeof(stall) !== "number" || !Number.isInteger(stall) || stall < 0) {
return throwArgumentError("invalid stall timeout", "stall", stall);
} else {
assertArgument(Number.isInteger(stall) && stall >= 0, "invalid stall timeout", "stall", stall);
}
const error = new Error(message || "throttling requests");

@ -1,5 +1,5 @@
import { getBytes } from "./data.js";
import { throwArgumentError, throwError } from "./errors.js";
import { assertArgument, throwError } from "./errors.js";
import { getBigInt, getNumber, fromTwos, toBigInt, toHex, toTwos } from "./maths.js";
import type { BigNumberish, BytesLike, Numeric } from "./index.js";
@ -22,9 +22,8 @@ while (zeros.length < 256) { zeros += zeros; }
// Returns a string "1" followed by decimal "0"s
function getMultiplier(decimals: number): bigint {
if (typeof(decimals) !== "number" || decimals < 0 || decimals > 256 || decimals % 1 ) {
throwArgumentError("invalid decimal length", "decimals", decimals);
}
assertArgument(Number.isInteger(decimals) && decimals >= 0 && decimals <= 256,
"invalid decimal length", "decimals", decimals);
return BigInt("1" + zeros.substring(0, decimals));
}
@ -65,23 +64,18 @@ export function parseFixed(value: string, _decimals: Numeric): bigint {
const multiplier = getMultiplier(decimals);
if (typeof(value) !== "string" || !value.match(/^-?[0-9.]+$/)) {
throwArgumentError("invalid decimal value", "value", value);
}
assertArgument(typeof(value) === "string" && value.match(/^-?[0-9.]+$/),
"invalid decimal value", "value", value);
// Is it negative?
const negative = (value.substring(0, 1) === "-");
if (negative) { value = value.substring(1); }
if (value === ".") {
throwArgumentError("missing value", "value", value);
}
assertArgument(value !== ".", "missing value", "value", value);
// Split it into a whole and fractional part
const comps = value.split(".");
if (comps.length > 2) {
throwArgumentError("too many decimal points", "value", value);
}
assertArgument(comps.length <= 2, "too many decimal points", "value", value);
let whole = (comps[0] || "0"), fraction = (comps[1] || "0");
@ -155,9 +149,7 @@ export class FixedFormat {
signed = false;
} else {
const match = value.match(/^(u?)fixed([0-9]+)x([0-9]+)$/);
if (!match) {
return throwArgumentError("invalid fixed format", "format", value);
}
assertArgument(match, "invalid fixed format", "format", value);
signed = (match[1] !== "u");
width = parseInt(match[2]);
decimals = parseInt(match[3]);
@ -165,9 +157,8 @@ export class FixedFormat {
} else if (value) {
const check = (key: string, type: string, defaultValue: any): any => {
if (value[key] == null) { return defaultValue; }
if (typeof(value[key]) !== type) {
throwArgumentError("invalid fixed format (" + key + " not " + type +")", "format." + key, value[key]);
}
assertArgument(typeof(value[key]) === type,
"invalid fixed format (" + key + " not " + type +")", "format." + key, value[key]);
return value[key];
}
signed = check("signed", "boolean", signed);
@ -175,13 +166,8 @@ export class FixedFormat {
decimals = check("decimals", "number", decimals);
}
if (width % 8) {
throwArgumentError("invalid fixed format width (not byte aligned)", "format.width", width);
}
if (decimals > 80) {
throwArgumentError("invalid fixed format (decimals too large)", "format.decimals", decimals);
}
assertArgument((width % 8) === 0, "invalid fixed format width (not byte aligned)", "format.width", width);
assertArgument(decimals <= 80, "invalid fixed format (decimals too large)", "format.decimals", decimals);
return new FixedFormat(_constructorGuard, signed, width, decimals);
}
@ -215,9 +201,8 @@ export class FixedNumber {
}
#checkFormat(other: FixedNumber): void {
if (this.format.name !== other.format.name) {
throwArgumentError("incompatible format; use fixedNumber.toFormat", "other", other);
}
assertArgument(this.format.name === other.format.name,
"incompatible format; use fixedNumber.toFormat", "other", other);
}
/**
@ -288,9 +273,8 @@ export class FixedNumber {
const comps = this.toString().split(".");
if (comps.length === 1) { comps.push("0"); }
if (decimals < 0 || decimals > 80 || (decimals % 1)) {
throwArgumentError("invalid decimal count", "decimals", decimals);
}
assertArgument(Number.isInteger(decimals) && decimals >= 0 && decimals <= 80,
"invalid decimal count", "decimals", decimals);
if (comps[1].length <= decimals) { return this; }
@ -391,7 +375,7 @@ export class FixedNumber {
}
}
return throwArgumentError("invalid FixedNumber value", "value", value);
assertArgument(false, "invalid FixedNumber value", "value", value);
}
static isFixedNumber(value: any): value is FixedNumber {

@ -25,7 +25,7 @@ export {
export {
isCallException, isError,
makeError, throwError, throwArgumentError,
makeError, throwError,
assertArgument, assertArgumentCount, assertPrivate, assertNormalize
} from "./errors.js"
@ -53,7 +53,6 @@ export { getStore, setStore} from "./storage.js";
export { formatEther, parseEther, formatUnits, parseUnits } from "./units.js";
export {
_toEscapedUtf8String,
toUtf8Bytes,
toUtf8CodePoints,
toUtf8String,

@ -1,5 +1,5 @@
import { hexlify, isBytesLike } from "./data.js";
import { throwArgumentError } from "./errors.js";
import { assertArgument } from "./errors.js";
import type { BytesLike } from "./data.js";
@ -68,11 +68,8 @@ export function getBigInt(value: BigNumberish, name?: string): bigint {
switch (typeof(value)) {
case "bigint": return value;
case "number":
if (!Number.isInteger(value)) {
throwArgumentError("underflow", name || "value", value);
} else if (value < -maxValue || value > maxValue) {
throwArgumentError("overflow", name || "value", value);
}
assertArgument(Number.isInteger(value), "underflow", name || "value", value);
assertArgument(value >= -maxValue && value <= maxValue, "overflow", name || "value", value);
return BigInt(value);
case "string":
try {
@ -81,10 +78,10 @@ export function getBigInt(value: BigNumberish, name?: string): bigint {
}
return BigInt(value);
} catch(e: any) {
throwArgumentError(`invalid BigNumberish string: ${ e.message }`, name || "value", value);
assertArgument(false, `invalid BigNumberish string: ${ e.message }`, name || "value", value);
}
}
return throwArgumentError("invalid BigNumberish value", name || "value", value);
assertArgument(false, "invalid BigNumberish value", name || "value", value);
}
@ -114,25 +111,20 @@ export function toBigInt(value: BigNumberish | Uint8Array): bigint {
export function getNumber(value: BigNumberish, name?: string): number {
switch (typeof(value)) {
case "bigint":
if (value < -maxValue || value > maxValue) {
throwArgumentError("overflow", name || "value", value);
}
assertArgument(value >= -maxValue && value <= maxValue, "overflow", name || "value", value);
return Number(value);
case "number":
if (!Number.isInteger(value)) {
throwArgumentError("underflow", name || "value", value);
} else if (value < -maxValue || value > maxValue) {
throwArgumentError("overflow", name || "value", value);
}
assertArgument(Number.isInteger(value), "underflow", name || "value", value);
assertArgument(value >= -maxValue && value <= maxValue, "overflow", name || "value", value);
return value;
case "string":
try {
return getNumber(BigInt(value), name);
} catch(e: any) {
throwArgumentError(`invalid numeric string: ${ e.message }`, name || "value", value);
assertArgument(false, `invalid numeric string: ${ e.message }`, name || "value", value);
}
}
return throwArgumentError("invalid numeric value", name || "value", value);
assertArgument(false, "invalid numeric value", name || "value", value);
}

@ -1,7 +1,7 @@
//See: https://github.com/ethereum/wiki/wiki/RLP
import { hexlify } from "./data.js";
import { throwArgumentError, throwError } from "./errors.js";
import { assertArgument, throwError } from "./errors.js";
import { getBytes } from "./data.js";
import type { BytesLike, RlpStructuredData } from "./index.js";
@ -104,9 +104,7 @@ function _decode(data: Uint8Array, offset: number): { consumed: number, result:
export function decodeRlp(_data: BytesLike): RlpStructuredData {
const data = getBytes(_data, "data");
const decoded = _decode(data, 0);
if (decoded.consumed !== data.length) {
throwArgumentError("unexpected junk after rlp payload", "data", _data);
}
assertArgument(decoded.consumed === data.length, "unexpected junk after rlp payload", "data", _data);
return decoded.result;
}

@ -1,5 +1,5 @@
import { formatFixed, parseFixed } from "./fixednumber.js";
import { throwArgumentError } from "./errors.js";
import { assertArgument } from "./errors.js";
import type { BigNumberish, Numeric } from "../utils/index.js";
@ -23,7 +23,7 @@ const names = [
export function formatUnits(value: BigNumberish, unit?: string | Numeric): string {
if (typeof(unit) === "string") {
const index = names.indexOf(unit);
if (index === -1) { throwArgumentError("invalid unit", "unit", unit); }
assertArgument(index >= 0, "invalid unit", "unit", unit);
unit = 3 * index;
}
return formatFixed(value, (unit != null) ? unit: 18);
@ -35,15 +35,14 @@ export function formatUnits(value: BigNumberish, unit?: string | Numeric): strin
* or the name of a unit (e.g. ``"gwei"`` for 9 decimal places).
*/
export function parseUnits(value: string, unit?: string | Numeric): bigint {
if (typeof(value) !== "string") {
throwArgumentError("value must be a string", "value", value);
}
assertArgument(typeof(value) === "string", "value must be a string", "value", value);
if (typeof(unit) === "string") {
const index = names.indexOf(unit);
if (index === -1) { throwArgumentError("invalid unit", "unit", unit); }
assertArgument(index >= 0, "invalid unit", "unit", unit);
unit = 3 * index;
}
return parseFixed(value, (unit != null) ? unit: 18);
}

@ -1,5 +1,5 @@
import { getBytes } from "./data.js";
import { assertNormalize, throwArgumentError } from "./errors.js";
import { assertArgument, assertNormalize } from "./errors.js";
import type { BytesLike } from "./index.js";
@ -44,10 +44,8 @@ export type Utf8ErrorReason =
export type Utf8ErrorFunc = (reason: Utf8ErrorReason, offset: number, bytes: ArrayLike<number>, output: Array<number>, badCodepoint?: number) => number;
function errorFunc(reason: Utf8ErrorReason, offset: number, bytes: ArrayLike<number>, output: Array<number>, badCodepoint?: number): number {
return throwArgumentError(`invalid codepoint at offset ${ offset }; ${ reason }`, "bytes", bytes);
assertArgument(false, `invalid codepoint at offset ${ offset }; ${ reason }`, "bytes", bytes);
}
function ignoreFunc(reason: Utf8ErrorReason, offset: number, bytes: ArrayLike<number>, output: Array<number>, badCodepoint?: number): number {
@ -215,9 +213,8 @@ export function toUtf8Bytes(str: string, form?: UnicodeNormalizationForm): Uint8
i++;
const c2 = str.charCodeAt(i);
if (i >= str.length || (c2 & 0xfc00) !== 0xdc00) {
throw new Error("invalid utf-8 string");
}
assertArgument(i < str.length && ((c2 & 0xfc00) === 0xdc00),
"invalid surrogate pair", "str", str);
// Surrogate Pair
const pair = 0x10000 + ((c & 0x03ff) << 10) + (c2 & 0x03ff);
@ -236,37 +233,6 @@ export function toUtf8Bytes(str: string, form?: UnicodeNormalizationForm): Uint8
return new Uint8Array(result);
};
function escapeChar(value: number): string {
const hex = ("0000" + value.toString(16));
return "\\u" + hex.substring(hex.length - 4);
}
export function _toEscapedUtf8String(bytes: BytesLike, onError?: Utf8ErrorFunc): string {
return '"' + getUtf8CodePoints(bytes, onError).map((codePoint) => {
if (codePoint < 256) {
switch (codePoint) {
case 8: return "\\b";
case 9: return "\\t";
case 10: return "\\n"
case 13: return "\\r";
case 34: return "\\\"";
case 92: return "\\\\";
}
if (codePoint >= 32 && codePoint < 127) {
return String.fromCharCode(codePoint);
}
}
if (codePoint <= 0xffff) {
return escapeChar(codePoint);
}
codePoint -= 0x10000;
return escapeChar(((codePoint >> 10) & 0x3ff) + 0xd800) + escapeChar((codePoint & 0x3ff) + 0xdc00);
}).join("") + '"';
}
export function _toUtf8String(codePoints: Array<number>): string {
return codePoints.map((codePoint) => {
if (codePoint <= 0xffff) {

@ -3,7 +3,7 @@ import { hashMessage, TypedDataEncoder } from "../hash/index.js";
import { AbstractSigner } from "../providers/index.js";
import { computeAddress, Transaction } from "../transaction/index.js";
import {
defineProperties, resolveProperties, throwArgumentError, throwError
defineProperties, resolveProperties, assertArgument, throwError
} from "../utils/index.js";
import type { SigningKey } from "../crypto/index.js";
@ -46,9 +46,8 @@ export class BaseWallet extends AbstractSigner {
if (from != null) { tx.from = from; }
if (tx.from != null) {
if (getAddress(<string>(tx.from)) !== this.address) {
throwArgumentError("transaction from address mismatch", "tx.from", tx.from);
}
assertArgument(getAddress(<string>(tx.from)) === this.address,
"transaction from address mismatch", "tx.from", tx.from);
delete tx.from;
}

@ -5,7 +5,7 @@ import {
concat, dataSlice, decodeBase58, defineProperties, encodeBase58,
getBytes, hexlify,
getNumber, toBigInt, toHex,
assertPrivate, throwArgumentError, throwError
assertPrivate, assertArgument, throwError
} from "../utils/index.js";
import { langEn } from "../wordlists/lang-en.js";
@ -216,9 +216,8 @@ export class HDNodeWallet extends BaseWallet {
static fromExtendedKey(extendedKey: string): HDNodeWallet | HDNodeVoidWallet {
const bytes = getBytes(decodeBase58(extendedKey)); // @TODO: redact
if (bytes.length !== 82 || encodeBase58Check(bytes.slice(0, 78)) !== extendedKey) {
throwArgumentError("invalid extended key", "extendedKey", "[ REDACTED ]");
}
assertArgument(bytes.length === 82 || encodeBase58Check(bytes.slice(0, 78)) === extendedKey,
"invalid extended key", "extendedKey", "[ REDACTED ]");
const depth = bytes[4];
const parentFingerprint = hexlify(bytes.slice(5, 9));
@ -242,7 +241,7 @@ export class HDNodeWallet extends BaseWallet {
}
return throwArgumentError("invalid extended key prefix", "extendedKey", "[ REDACTED ]");
assertArgument(false, "invalid extended key prefix", "extendedKey", "[ REDACTED ]");
}
static createRandom(password: string = "", path: null | string = defaultPath, wordlist: Wordlist = langEn): HDNodeWallet {
@ -342,9 +341,7 @@ export class HDNodeWalletManager {
export function getAccountPath(_index: Numeric): string {
const index = getNumber(_index, "index");
if (index < 0 || index >= HardenedBit) {
throwArgumentError("invalid account index", "index", index);
}
assertArgument(index >= 0 && index < HardenedBit, "invalid account index", "index", index);
return `m/44'/60'/${ index }'/0/0`;
}

@ -3,7 +3,7 @@ import { CBC, pkcs7Strip } from "aes-js";
import { getAddress } from "../address/index.js";
import { pbkdf2 } from "../crypto/index.js";
import { id } from "../hash/index.js";
import { getBytes, throwArgumentError } from "../utils/index.js";
import { getBytes, assertArgument } from "../utils/index.js";
import { getPassword, looseArrayify, spelunk } from "./utils.js";
@ -31,9 +31,7 @@ export function decryptCrowdsaleJson(json: string, _password: string | Uint8Arra
// Encrypted Seed
const encseed = looseArrayify(spelunk(data, "encseed:string!"));
if (!encseed || (encseed.length % 16) !== 0) {
throwArgumentError("invalid encseed", "json", json);
}
assertArgument(encseed && (encseed.length % 16) === 0, "invalid encseed", "json", json);
const key = getBytes(pbkdf2(password, password, 2000, 32, "sha256")).slice(0, 16);

@ -4,7 +4,7 @@ import { getAddress } from "../address/index.js";
import { keccak256, pbkdf2, randomBytes, scrypt, scryptSync } from "../crypto/index.js";
import { computeAddress } from "../transaction/index.js";
import {
concat, getBytes, hexlify, throwArgumentError, throwError
concat, getBytes, hexlify, assertArgument, throwError
} from "../utils/index.js";
import { getPassword, spelunk, uuidV4, zpad } from "./utils.js";
@ -77,9 +77,8 @@ function getAccount(data: any, _key: string): KeystoreAccount {
const ciphertext = spelunk<Uint8Array>(data, "crypto.ciphertext:data!");
const computedMAC = hexlify(keccak256(concat([ key.slice(16, 32), ciphertext ]))).substring(2);
if (computedMAC !== spelunk(data, "crypto.mac:string!").toLowerCase()) {
return throwArgumentError("incorrect password", "password", "[ REDACTED ]");
}
assertArgument(computedMAC === spelunk(data, "crypto.mac:string!").toLowerCase(),
"incorrect password", "password", "[ REDACTED ]");
const privateKey = decrypt(data, key.slice(0, 16), ciphertext);
@ -88,9 +87,7 @@ function getAccount(data: any, _key: string): KeystoreAccount {
let check = data.address.toLowerCase();
if (check.substring(0, 2) !== "0x") { check = "0x" + check; }
if (getAddress(check) !== address) {
throwArgumentError("keystore address/privateKey mismatch", "address", data.address);
}
assertArgument(getAddress(check) === address, "keystore address/privateKey mismatch", "address", data.address);
}
const account: KeystoreAccount = { address, privateKey };
@ -134,7 +131,7 @@ function getKdfParams<T>(data: any): KdfParams {
const kdf = spelunk(data, "crypto.kdf:string");
if (kdf && typeof(kdf) === "string") {
const throwError = function(name: string, value: any): never {
return throwArgumentError("invalid key-derivation function parameters", name, value);
assertArgument(false, "invalid key-derivation function parameters", name, value);
}
if (kdf.toLowerCase() === "scrypt") {
@ -173,7 +170,7 @@ function getKdfParams<T>(data: any): KdfParams {
}
}
return throwArgumentError("unsupported key-derivation function", "kdf", kdf);
assertArgument(false, "unsupported key-derivation function", "kdf", kdf);
}
@ -275,15 +272,11 @@ export async function encryptKeystoreJson(account: KeystoreAccount, password: st
// Override initialization vector
const iv = (options.iv != null) ? getBytes(options.iv, "options.iv"): randomBytes(16);
if (iv.length !== 16) {
throwArgumentError("invalid options.iv", "options.iv", options.iv);
}
assertArgument(iv.length === 16, "invalid options.iv", "options.iv", options.iv);
// Override the uuid
const uuidRandom = (options.uuid != null) ? getBytes(options.uuid, "options.uuid"): randomBytes(16);
if (uuidRandom.length !== 16) {
throwArgumentError("invalid options.uuid", "options.uuid", options.iv);
}
assertArgument(uuidRandom.length === 16, "invalid options.uuid", "options.uuid", options.iv);
if (uuidRandom.length !== 16) { throw new Error("invalid uuid"); }
// Override the scrypt password-based key derivation function parameters

@ -1,6 +1,6 @@
import { pbkdf2, sha256 } from "../crypto/index.js";
import {
defineProperties, getBytes, hexlify, assertNormalize, assertPrivate, throwArgumentError, toUtf8Bytes
defineProperties, getBytes, hexlify, assertNormalize, assertPrivate, assertArgument, toUtf8Bytes
} from "../utils/index.js";
import { langEn } from "../wordlists/lang-en.js";
@ -25,18 +25,15 @@ function mnemonicToEntropy(mnemonic: string, wordlist: null | Wordlist = langEn)
if (wordlist == null) { wordlist = langEn; }
const words = wordlist.split(mnemonic);
if ((words.length % 3) !== 0 || words.length < 12 || words.length > 24) {
throwArgumentError("invalid mnemonic length", "mnemonic", "[ REDACTED ]");
}
assertArgument((words.length % 3) === 0 && words.length >= 12 && words.length <= 24,
"invalid mnemonic length", "mnemonic", "[ REDACTED ]");
const entropy = new Uint8Array(Math.ceil(11 * words.length / 8));
let offset = 0;
for (let i = 0; i < words.length; i++) {
let index = wordlist.getWordIndex(words[i].normalize("NFKD"));
if (index === -1) {
throwArgumentError(`invalid mnemonic word at index ${ i }`, "mnemonic", "[ REDACTED ]");
}
assertArgument(index >= 0, `invalid mnemonic word at index ${ i }`, "mnemonic", "[ REDACTED ]");
for (let bit = 0; bit < 11; bit++) {
if (index & (1 << (10 - bit))) {
@ -54,17 +51,15 @@ function mnemonicToEntropy(mnemonic: string, wordlist: null | Wordlist = langEn)
const checksum = getBytes(sha256(entropy.slice(0, entropyBits / 8)))[0] & checksumMask;
if (checksum !== (entropy[entropy.length - 1] & checksumMask)) {
throwArgumentError("invalid mnemonic checksum", "mnemonic", "[ REDACTED ]");
}
assertArgument(checksum === (entropy[entropy.length - 1] & checksumMask),
"invalid mnemonic checksum", "mnemonic", "[ REDACTED ]");
return hexlify(entropy.slice(0, entropyBits / 8));
}
function entropyToMnemonic(entropy: Uint8Array, wordlist: null | Wordlist = langEn): string {
if ((entropy.length % 4) || entropy.length < 16 || entropy.length > 32) {
throwArgumentError("invalid entropy size", "entropy", "[ REDACTED ]");
}
assertArgument((entropy.length % 4) === 0 && entropy.length >= 16 && entropy.length <= 32,
"invalid entropy size", "entropy", "[ REDACTED ]");
if (wordlist == null) { wordlist = langEn; }

@ -1,5 +1,5 @@
import {
getBytes, getBytesCopy, hexlify, throwArgumentError, toUtf8Bytes
getBytes, getBytesCopy, hexlify, assertArgument, toUtf8Bytes
} from "../utils/index.js";
import type { BytesLike } from "../utils/index.js";
@ -28,9 +28,8 @@ export function getPassword(password: string | Uint8Array): Uint8Array {
export function spelunk<T = string>(object: any, _path: string): T {
const match = _path.match(/^([a-z0-9$_.-]*)(:([a-z]+))?(!)?$/i);
if (match == null) {
return throwArgumentError("invalid path", "path", _path);
}
assertArgument(match != null, "invalid path", "path", _path);
const path = match[1];
const type = match[3];
const reqd = (match[4] === "!");
@ -60,9 +59,7 @@ export function spelunk<T = string>(object: any, _path: string): T {
if (cur == null) { break; }
}
if (reqd && cur == null) {
throwArgumentError("missing required value", "path", path);
}
assertArgument(!reqd || cur != null, "missing required value", "path", path);
if (type && cur != null) {
if (type === "int") {
@ -86,7 +83,7 @@ export function spelunk<T = string>(object: any, _path: string): T {
if (type === "array" && Array.isArray(cur)) { return <T><unknown>cur; }
if (type === typeof(cur)) { return cur; }
throwArgumentError(`wrong type found for ${ type } `, "path", path);
assertArgument(false, `wrong type found for ${ type } `, "path", path);
}
return cur;

@ -1,6 +1,6 @@
import { randomBytes, SigningKey } from "../crypto/index.js";
import { computeAddress } from "../transaction/index.js";
import { isHexString, throwArgumentError } from "../utils/index.js";
import { isHexString, assertArgument } from "../utils/index.js";
import { BaseWallet } from "./base-wallet.js";
import { HDNodeWallet } from "./hdwallet.js";
@ -89,9 +89,7 @@ export class Wallet extends BaseWallet {
// A signing key
if (signingKey == null) { signingKey = trySigningKey(key); }
if (signingKey == null) {
throwArgumentError("invalid key", "key", "[ REDACTED ]");
}
assertArgument(signingKey != null, "invalid key", "key", "[ REDACTED ]");
super(signingKey as SigningKey, provider);
this.#mnemonic = mnemonic;
@ -123,13 +121,12 @@ export class Wallet extends BaseWallet {
if (progress) { progress(1); await stall(0); }
} else {
return throwArgumentError("invalid JSON wallet", "json", "[ REDACTED ]");
assertArgument(false, "invalid JSON wallet", "json", "[ REDACTED ]");
}
const wallet = new Wallet(account.privateKey);
if (wallet.address !== account.address) {
throwArgumentError("address/privateKey mismatch", "json", "[ REDACTED ]");
}
assertArgument(wallet.address === account.address,
"address/privateKey mismatch", "json", "[ REDACTED ]");
// @TODO: mnemonic
return wallet;
}
@ -141,13 +138,12 @@ export class Wallet extends BaseWallet {
} else if (isCrowdsaleJson(json)) {
account = decryptCrowdsaleJson(json, password);
} else {
return throwArgumentError("invalid JSON wallet", "json", "[ REDACTED ]");
assertArgument(false, "invalid JSON wallet", "json", "[ REDACTED ]");
}
const wallet = new Wallet(account.privateKey);
if (wallet.address !== account.address) {
throwArgumentError("address/privateKey mismatch", "json", "[ REDACTED ]");
}
assertArgument(wallet.address === account.address,
"address/privateKey mismatch", "json", "[ REDACTED ]");
// @TODO: mnemonic
return wallet;
}

@ -1,6 +1,6 @@
import { id } from "../hash/index.js";
import {
hexlify, throwArgumentError, toUtf8Bytes, toUtf8String
hexlify, assertArgument, toUtf8Bytes, toUtf8String
} from "../utils/index.js";
import { Wordlist } from "./wordlist.js";
@ -136,9 +136,8 @@ class LangJa extends Wordlist {
getWord(index: number): string {
const words = loadWords();
if (index < 0 || index >= words.length) {
throwArgumentError(`invalid word index: ${ index }`, "index", index);
}
assertArgument(index >= 0 && index < words.length,
`invalid word index: ${ index }`, "index", index);
return words[index];
}

@ -1,5 +1,5 @@
import { id } from "../hash/index.js";
import { throwArgumentError, toUtf8String } from "../utils/index.js";
import { assertArgument, toUtf8String } from "../utils/index.js";
import { Wordlist } from "./wordlist.js";
@ -69,9 +69,8 @@ class LangKo extends Wordlist {
getWord(index: number): string {
const words = loadWords();
if (index < 0 || index >= words.length) {
throwArgumentError(`invalid word index: ${ index }`, "index", index);
}
assertArgument(index >= 0 && index < words.length,
`invalid word index: ${ index }`, "index", index);
return words[index];
}

@ -1,5 +1,5 @@
import { id } from "../hash/index.js";
import { throwArgumentError, toUtf8String } from "../utils/index.js";
import { assertArgument, toUtf8String } from "../utils/index.js";
import { Wordlist } from "./wordlist.js";
@ -63,9 +63,8 @@ class LangZh extends Wordlist {
getWord(index: number): string {
const words = loadWords(this.locale);
if (index < 0 || index >= words.length) {
throwArgumentError(`invalid word index: ${ index }`, "index", index);
}
assertArgument(index >= 0 && index < words.length,
`invalid word index: ${ index }`, "index", index);
return words[index];
}

@ -3,7 +3,7 @@
// data files to be consumed by this class
import { id } from "../hash/index.js";
import { throwArgumentError } from "../utils/index.js";
import { assertArgument } from "../utils/index.js";
import { decodeOwl } from "./decode-owl.js";
import { Wordlist } from "./wordlist.js";
@ -45,9 +45,7 @@ export class WordlistOwl extends Wordlist {
getWord(index: number): string {
const words = this.#loadWords();
if (index < 0 || index >= words.length) {
throwArgumentError(`invalid word index: ${ index }`, "index", index);
}
assertArgument(index >= 0 && index < words.length, `invalid word index: ${ index }`, "index", index);
return words[index];
}