Converted throwArgumentError to assertArgument.
This commit is contained in:
parent
17ac965b12
commit
e5c068c395
@ -1,6 +1,6 @@
|
|||||||
// See: https://github.com/ethereum/wiki/wiki/Ethereum-Contract-ABI
|
// 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 { Coder, Reader, Result, Writer } from "./coders/abstract-coder.js";
|
||||||
import { AddressCoder } from "./coders/address.js";
|
import { AddressCoder } from "./coders/address.js";
|
||||||
@ -54,9 +54,8 @@ export class AbiCoder {
|
|||||||
let match = param.type.match(paramTypeNumber);
|
let match = param.type.match(paramTypeNumber);
|
||||||
if (match) {
|
if (match) {
|
||||||
let size = parseInt(match[2] || "256");
|
let size = parseInt(match[2] || "256");
|
||||||
if (size === 0 || size > 256 || (size % 8) !== 0) {
|
assertArgument(size !== 0 && size <= 256 && (size % 8) === 0,
|
||||||
throwArgumentError("invalid " + match[1] + " bit length", "param", param);
|
"invalid " + match[1] + " bit length", "param", param);
|
||||||
}
|
|
||||||
return new NumberCoder(size / 8, (match[1] === "int"), param.name);
|
return new NumberCoder(size / 8, (match[1] === "int"), param.name);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -64,13 +63,11 @@ export class AbiCoder {
|
|||||||
match = param.type.match(paramTypeBytes);
|
match = param.type.match(paramTypeBytes);
|
||||||
if (match) {
|
if (match) {
|
||||||
let size = parseInt(match[1]);
|
let size = parseInt(match[1]);
|
||||||
if (size === 0 || size > 32) {
|
assertArgument(size !== 0 && size <= 32, "invalid bytes length", "param", param);
|
||||||
throwArgumentError("invalid bytes length", "param", param);
|
|
||||||
}
|
|
||||||
return new FixedBytesCoder(size, param.name);
|
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 {
|
getDefaultValue(types: ReadonlyArray<string | ParamType>): Result {
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
import {
|
import {
|
||||||
defineProperties, concat, getBytesCopy, getNumber, hexlify,
|
defineProperties, concat, getBytesCopy, getNumber, hexlify,
|
||||||
toArray, toBigInt, toNumber,
|
toArray, toBigInt, toNumber,
|
||||||
assertPrivate, throwArgumentError, throwError
|
assertPrivate, assertArgument, throwError
|
||||||
} from "../../utils/index.js";
|
} from "../../utils/index.js";
|
||||||
|
|
||||||
import type { BigNumberish, BytesLike } 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 {
|
_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;
|
abstract encode(writer: Writer, value: any): number;
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import {
|
import {
|
||||||
defineProperties, isError, assertArgumentCount, throwArgumentError, throwError
|
defineProperties, isError, assertArgument, assertArgumentCount, throwError
|
||||||
} from "../../utils/index.js";
|
} from "../../utils/index.js";
|
||||||
|
|
||||||
import { Typed } from "../typed.js";
|
import { Typed } from "../typed.js";
|
||||||
@ -43,12 +43,10 @@ export function pack(writer: Writer, coders: ReadonlyArray<Coder>, values: Array
|
|||||||
});
|
});
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
throwArgumentError("invalid tuple value", "tuple", values);
|
assertArgument(false, "invalid tuple value", "tuple", values);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (coders.length !== arrayValues.length) {
|
assertArgument(coders.length === arrayValues.length, "types/value length mismatch", "tuple", values);
|
||||||
throwArgumentError("types/value length mismatch", "tuple", values);
|
|
||||||
}
|
|
||||||
|
|
||||||
let staticWriter = new Writer();
|
let staticWriter = new Writer();
|
||||||
let dynamicWriter = new Writer();
|
let dynamicWriter = new Writer();
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import {
|
import {
|
||||||
defineProperties, getBigInt, getNumber,
|
defineProperties, getBigInt, getNumber,
|
||||||
assertPrivate, throwArgumentError, throwError
|
assertPrivate, assertArgument, throwError
|
||||||
} from "../utils/index.js";
|
} from "../utils/index.js";
|
||||||
import { id } from "../hash/index.js";
|
import { id } from "../hash/index.js";
|
||||||
|
|
||||||
@ -401,25 +401,19 @@ const regexArrayType = new RegExp(/^(.*)\[([0-9]*)\]$/);
|
|||||||
|
|
||||||
function verifyBasicType(type: string): string {
|
function verifyBasicType(type: string): string {
|
||||||
const match = type.match(regexType);
|
const match = type.match(regexType);
|
||||||
if (!match) {
|
assertArgument(match, "invalid type", "type", type);
|
||||||
return throwArgumentError("invalid type", "type", type);
|
|
||||||
}
|
|
||||||
if (type === "uint") { return "uint256"; }
|
if (type === "uint") { return "uint256"; }
|
||||||
if (type === "int") { return "int256"; }
|
if (type === "int") { return "int256"; }
|
||||||
|
|
||||||
if (match[2]) {
|
if (match[2]) {
|
||||||
// bytesXX
|
// bytesXX
|
||||||
const length = parseInt(match[2]);
|
const length = parseInt(match[2]);
|
||||||
if (length === 0 || length > 32) {
|
assertArgument(length !== 0 && length <= 32, "invalid bytes length", "type", type);
|
||||||
throwArgumentError("invalid bytes length", "type", type);
|
|
||||||
}
|
|
||||||
|
|
||||||
} else if (match[3]) {
|
} else if (match[3]) {
|
||||||
// intXX or uintXX
|
// intXX or uintXX
|
||||||
const size = parseInt(match[3] as string);
|
const size = parseInt(match[3] as string);
|
||||||
if (size === 0 || size > 256 || size % 8) {
|
assertArgument(size !== 0 && size <= 256 && (size % 8) === 0, "invalid numeric width", "type", type);
|
||||||
throwArgumentError("invalid numeric width", "type", type);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return type;
|
return type;
|
||||||
@ -694,15 +688,12 @@ export class ParamType {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const name = obj.name;
|
const name = obj.name;
|
||||||
if (name && (typeof(name) !== "string" || !name.match(regexIdentifier))) {
|
assertArgument(!name || (typeof(name) === "string" && name.match(regexIdentifier)),
|
||||||
throwArgumentError("invalid name", "obj.name", name);
|
"invalid name", "obj.name", name);
|
||||||
}
|
|
||||||
|
|
||||||
let indexed = obj.indexed;
|
let indexed = obj.indexed;
|
||||||
if (indexed != null) {
|
if (indexed != null) {
|
||||||
if (!allowIndexed) {
|
assertArgument(allowIndexed, "parameter cannot be indexed", "obj.indexed", obj.indexed);
|
||||||
throwArgumentError("parameter cannot be indexed", "obj.indexed", obj.indexed);
|
|
||||||
}
|
|
||||||
indexed = !!indexed;
|
indexed = !!indexed;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -813,9 +804,8 @@ export abstract class NamedFragment extends Fragment {
|
|||||||
|
|
||||||
constructor(guard: any, type: FragmentType, name: string, inputs: ReadonlyArray<ParamType>) {
|
constructor(guard: any, type: FragmentType, name: string, inputs: ReadonlyArray<ParamType>) {
|
||||||
super(guard, type, inputs);
|
super(guard, type, inputs);
|
||||||
if (typeof(name) !== "string" || !name.match(regexIdentifier)) {
|
assertArgument(typeof(name) === "string" && name.match(regexIdentifier),
|
||||||
throwArgumentError("invalid identifier", "name", name);
|
"invalid identifier", "name", name);
|
||||||
}
|
|
||||||
inputs = Object.freeze(inputs.slice());
|
inputs = Object.freeze(inputs.slice());
|
||||||
defineProperties<NamedFragment>(this, { name });
|
defineProperties<NamedFragment>(this, { name });
|
||||||
}
|
}
|
||||||
|
@ -2,7 +2,7 @@ import { keccak256 } from "../crypto/index.js"
|
|||||||
import { id } from "../hash/index.js"
|
import { id } from "../hash/index.js"
|
||||||
import {
|
import {
|
||||||
concat, dataSlice, getBigInt, getBytes, getBytesCopy,
|
concat, dataSlice, getBigInt, getBytes, getBytesCopy,
|
||||||
hexlify, zeroPadValue, isHexString, defineProperties, throwArgumentError, toHex,
|
hexlify, zeroPadValue, isHexString, defineProperties, assertArgument, toHex,
|
||||||
throwError
|
throwError
|
||||||
} from "../utils/index.js";
|
} from "../utils/index.js";
|
||||||
|
|
||||||
@ -279,7 +279,7 @@ export class Interface {
|
|||||||
for (const fragment of this.#functions.values()) {
|
for (const fragment of this.#functions.values()) {
|
||||||
if (selector === fragment.selector) { return fragment; }
|
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)
|
// 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) {
|
assertArgument(matching.length !== 0, "no matching function", "name", key);
|
||||||
throwArgumentError("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(", ");
|
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];
|
return matching[0];
|
||||||
@ -355,7 +354,7 @@ export class Interface {
|
|||||||
const result = this.#functions.get(FunctionFragment.from(key).format());
|
const result = this.#functions.get(FunctionFragment.from(key).format());
|
||||||
if (result) { return result; }
|
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()) {
|
for (const fragment of this.#events.values()) {
|
||||||
if (eventTopic === fragment.topicHash) { return fragment; }
|
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)
|
// 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) {
|
assertArgument(matching.length > 0, "no matching event", "name", key);
|
||||||
throwArgumentError("no matching event", "name", key);
|
if (matching.length > 1 && forceUnique) {
|
||||||
} else if (matching.length > 1 && forceUnique) {
|
|
||||||
// @TODO: refine by Typed
|
// @TODO: refine by Typed
|
||||||
throwArgumentError("multiple matching events", "name", key);
|
assertArgument(false, "multiple matching events", "name", key);
|
||||||
}
|
}
|
||||||
|
|
||||||
return matching[0];
|
return matching[0];
|
||||||
@ -438,7 +436,7 @@ export class Interface {
|
|||||||
const result = this.#events.get(EventFragment.from(key).format());
|
const result = this.#events.get(EventFragment.from(key).format());
|
||||||
if (result) { return result; }
|
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()) {
|
for (const fragment of this.#errors.values()) {
|
||||||
if (selector === fragment.selector) { return fragment; }
|
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)
|
// 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 (matching.length === 0) {
|
||||||
if (key === "Error") { return ErrorFragment.from("error Error(string)"); }
|
if (key === "Error") { return ErrorFragment.from("error Error(string)"); }
|
||||||
if (key === "Panic") { return ErrorFragment.from("error Panic(uint256)"); }
|
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) {
|
} else if (matching.length > 1) {
|
||||||
// @TODO: refine by Typed
|
// @TODO: refine by Typed
|
||||||
throwArgumentError("multiple matching errors", "name", key);
|
assertArgument(false, "multiple matching errors", "name", key);
|
||||||
}
|
}
|
||||||
|
|
||||||
return matching[0];
|
return matching[0];
|
||||||
@ -514,7 +512,7 @@ export class Interface {
|
|||||||
const result = this.#errors.get(key);
|
const result = this.#errors.get(key);
|
||||||
if (result) { return result; }
|
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
|
// 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 {
|
decodeErrorResult(fragment: ErrorFragment | string, data: BytesLike): Result {
|
||||||
if (typeof(fragment) === "string") { fragment = this.getError(fragment); }
|
if (typeof(fragment) === "string") { fragment = this.getError(fragment); }
|
||||||
|
|
||||||
if (dataSlice(data, 0, 4) !== fragment.selector) {
|
assertArgument(dataSlice(data, 0, 4) === fragment.selector,
|
||||||
throwArgumentError(`data signature does not match error ${ fragment.name }.`, "data", data);
|
`data signature does not match error ${ fragment.name }.`, "data", data);
|
||||||
}
|
|
||||||
|
|
||||||
return this._decodeParams(fragment.inputs, dataSlice(data, 4));
|
return this._decodeParams(fragment.inputs, dataSlice(data, 4));
|
||||||
}
|
}
|
||||||
@ -611,9 +608,8 @@ export class Interface {
|
|||||||
decodeFunctionData(key: FunctionFragment | string, data: BytesLike): Result {
|
decodeFunctionData(key: FunctionFragment | string, data: BytesLike): Result {
|
||||||
const fragment = (typeof(key) === "string") ? this.getFunction(key): key;
|
const fragment = (typeof(key) === "string") ? this.getFunction(key): key;
|
||||||
|
|
||||||
if (dataSlice(data, 0, 4) !== fragment.selector) {
|
assertArgument(dataSlice(data, 0, 4) === fragment.selector,
|
||||||
throwArgumentError(`data signature does not match function ${ fragment.name }.`, "data", data);
|
`data signature does not match function ${ fragment.name }.`, "data", data);
|
||||||
}
|
|
||||||
|
|
||||||
return this._decodeParams(fragment.inputs, dataSlice(data, 4));
|
return this._decodeParams(fragment.inputs, dataSlice(data, 4));
|
||||||
}
|
}
|
||||||
@ -788,16 +784,15 @@ export class Interface {
|
|||||||
const param = (<EventFragment>eventFragment).inputs[index];
|
const param = (<EventFragment>eventFragment).inputs[index];
|
||||||
|
|
||||||
if (!param.indexed) {
|
if (!param.indexed) {
|
||||||
if (value != null) {
|
assertArgument(value == null,
|
||||||
throwArgumentError("cannot filter non-indexed parameters; must be null", ("contract." + param.name), value);
|
"cannot filter non-indexed parameters; must be null", ("contract." + param.name), value);
|
||||||
}
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (value == null) {
|
if (value == null) {
|
||||||
topics.push(null);
|
topics.push(null);
|
||||||
} else if (param.baseType === "array" || param.baseType === "tuple") {
|
} 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)) {
|
} else if (Array.isArray(value)) {
|
||||||
topics.push(value.map((value) => encodeTopic(param, value)));
|
topics.push(value.map((value) => encodeTopic(param, value)));
|
||||||
} else {
|
} else {
|
||||||
@ -827,9 +822,8 @@ export class Interface {
|
|||||||
topics.push(eventFragment.topicHash);
|
topics.push(eventFragment.topicHash);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (values.length !== eventFragment.inputs.length) {
|
assertArgument(values.length !== eventFragment.inputs.length,
|
||||||
throwArgumentError("event arguments/values mismatch", "values", values);
|
"event arguments/values mismatch", "values", values);
|
||||||
}
|
|
||||||
|
|
||||||
eventFragment.inputs.forEach((param, index) => {
|
eventFragment.inputs.forEach((param, index) => {
|
||||||
const value = values[index];
|
const value = values[index];
|
||||||
@ -864,9 +858,8 @@ export class Interface {
|
|||||||
|
|
||||||
if (topics != null && !eventFragment.anonymous) {
|
if (topics != null && !eventFragment.anonymous) {
|
||||||
const eventTopic = eventFragment.topicHash;
|
const eventTopic = eventFragment.topicHash;
|
||||||
if (!isHexString(topics[0], 32) || topics[0].toLowerCase() !== eventTopic) {
|
assertArgument(isHexString(topics[0], 32) && topics[0].toLowerCase() === eventTopic,
|
||||||
throwArgumentError("fragment/topic mismatch", "topics[0]", topics[0]);
|
"fragment/topic mismatch", "topics[0]", topics[0]);
|
||||||
}
|
|
||||||
topics = topics.slice(1);
|
topics = topics.slice(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import { keccak256 } from "../crypto/index.js";
|
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);
|
const BN_0 = BigInt(0);
|
||||||
@ -83,9 +83,7 @@ function fromBase36(value: string): bigint {
|
|||||||
|
|
||||||
export function getAddress(address: string): string {
|
export function getAddress(address: string): string {
|
||||||
|
|
||||||
if (typeof(address) !== "string") {
|
assertArgument(typeof(address) === "string", "invalid address", "address", address);
|
||||||
throwArgumentError("invalid address", "address", address);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (address.match(/^(0x)?[0-9a-fA-F]{40}$/)) {
|
if (address.match(/^(0x)?[0-9a-fA-F]{40}$/)) {
|
||||||
|
|
||||||
@ -95,9 +93,8 @@ export function getAddress(address: string): string {
|
|||||||
const result = getChecksumAddress(address);
|
const result = getChecksumAddress(address);
|
||||||
|
|
||||||
// It is a checksummed address with a bad checksum
|
// It is a checksummed address with a bad checksum
|
||||||
if (address.match(/([A-F].*[a-f])|([a-f].*[A-F])/) && result !== address) {
|
assertArgument(!address.match(/([A-F].*[a-f])|([a-f].*[A-F])/) || result === address,
|
||||||
throwArgumentError("bad address checksum", "address", address);
|
"bad address checksum", "address", address);
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
@ -105,16 +102,14 @@ export function getAddress(address: string): string {
|
|||||||
// Maybe ICAP? (we only support direct mode)
|
// Maybe ICAP? (we only support direct mode)
|
||||||
if (address.match(/^XE[0-9]{2}[0-9A-Za-z]{30,31}$/)) {
|
if (address.match(/^XE[0-9]{2}[0-9A-Za-z]{30,31}$/)) {
|
||||||
// It is an ICAP address with a bad checksum
|
// It is an ICAP address with a bad checksum
|
||||||
if (address.substring(2, 4) !== ibanChecksum(address)) {
|
assertArgument(address.substring(2, 4) === ibanChecksum(address), "bad icap checksum", "address", address);
|
||||||
throwArgumentError("bad icap checksum", "address", address);
|
|
||||||
}
|
|
||||||
|
|
||||||
let result = fromBase36(address.substring(4)).toString(16);
|
let result = fromBase36(address.substring(4)).toString(16);
|
||||||
while (result.length < 40) { result = "0" + result; }
|
while (result.length < 40) { result = "0" + result; }
|
||||||
return getChecksumAddress("0x" + result);
|
return getChecksumAddress("0x" + result);
|
||||||
}
|
}
|
||||||
|
|
||||||
return throwArgumentError("invalid address", "address", address);
|
assertArgument(false, "invalid address", "address", address);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getIcapAddress(address: string): string {
|
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";
|
import { getAddress } from "./address.js";
|
||||||
|
|
||||||
@ -23,7 +23,7 @@ async function checkAddress(target: any, promise: Promise<null | string>): Promi
|
|||||||
if (typeof(target) === "string") {
|
if (typeof(target) === "string") {
|
||||||
return throwError("unconfigured name", "UNCONFIGURED_NAME", { value: target });
|
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);
|
return getAddress(result);
|
||||||
}
|
}
|
||||||
@ -50,5 +50,5 @@ export function resolveAddress(target: AddressLike, resolver?: null | NameResolv
|
|||||||
return checkAddress(target, target);
|
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 { keccak256 } from "../crypto/index.js";
|
||||||
import {
|
import {
|
||||||
concat, dataSlice, getBigInt, getBytes, encodeRlp, throwArgumentError
|
concat, dataSlice, getBigInt, getBytes, encodeRlp, assertArgument
|
||||||
} from "../utils/index.js";
|
} from "../utils/index.js";
|
||||||
|
|
||||||
import { getAddress } from "./address.js";
|
import { getAddress } from "./address.js";
|
||||||
@ -30,13 +30,9 @@ export function getCreate2Address(_from: string, _salt: BytesLike, _initCodeHash
|
|||||||
const salt = getBytes(_salt, "salt");
|
const salt = getBytes(_salt, "salt");
|
||||||
const initCodeHash = getBytes(_initCodeHash, "initCodeHash");
|
const initCodeHash = getBytes(_initCodeHash, "initCodeHash");
|
||||||
|
|
||||||
if (salt.length !== 32) {
|
assertArgument(salt.length === 32, "salt must be 32 bytes", "salt", _salt);
|
||||||
throwArgumentError("salt must be 32 bytes", "salt", _salt);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (initCodeHash.length !== 32) {
|
assertArgument(initCodeHash.length === 32, "initCodeHash must be 32 bytes", "initCodeHash", _initCodeHash);
|
||||||
throwArgumentError("initCodeHash must be 32 bytes", "initCodeHash", _initCodeHash);
|
|
||||||
}
|
|
||||||
|
|
||||||
return getAddress(dataSlice(keccak256(concat([ "0xff", from, salt, initCodeHash ])), 12))
|
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 { copyRequest, Log, TransactionResponse } from "../providers/index.js";
|
||||||
import {
|
import {
|
||||||
defineProperties, isCallException, isHexString, resolveProperties,
|
defineProperties, isCallException, isHexString, resolveProperties,
|
||||||
makeError, throwArgumentError, throwError
|
makeError, assertArgument, throwError
|
||||||
} from "../utils/index.js";
|
} from "../utils/index.js";
|
||||||
|
|
||||||
import {
|
import {
|
||||||
@ -133,9 +133,9 @@ export async function copyOverrides(arg: any): Promise<Omit<ContractTransaction,
|
|||||||
// Some sanity checking; these are what these methods adds
|
// Some sanity checking; these are what these methods adds
|
||||||
//if ((<any>overrides).to) {
|
//if ((<any>overrides).to) {
|
||||||
if (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) {
|
} else if (overrides.data) {
|
||||||
throwArgumentError("cannot override data", "overrides.data", overrides.data);
|
assertArgument(false, "cannot override data", "overrides.data", overrides.data);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Resolve any from
|
// Resolve any from
|
||||||
|
@ -3,7 +3,7 @@ import { Interface } from "../abi/index.js";
|
|||||||
import { getCreateAddress } from "../address/index.js";
|
import { getCreateAddress } from "../address/index.js";
|
||||||
import {
|
import {
|
||||||
concat, defineProperties, getBytes, hexlify,
|
concat, defineProperties, getBytes, hexlify,
|
||||||
throwArgumentError, throwError
|
assertArgument, throwError
|
||||||
} from "../utils/index.js";
|
} from "../utils/index.js";
|
||||||
|
|
||||||
import { BaseContract, copyOverrides, resolveArgs } from "./contract.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> {
|
static fromSolidity<A extends Array<any> = Array<any>, I = ContractInterface>(output: any, runner?: ContractRunner): ContractFactory<A, I> {
|
||||||
if (output == null) {
|
assertArgument(output != null, "bad compiler output", "output", output);
|
||||||
throwArgumentError("bad compiler output", "output", output);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (typeof(output) === "string") { output = JSON.parse(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 { sha256 } from "@noble/hashes/sha256";
|
||||||
import { sha512 } from "@noble/hashes/sha512";
|
import { sha512 } from "@noble/hashes/sha512";
|
||||||
|
|
||||||
import { throwArgumentError, throwError } from "../utils/index.js";
|
import { assertArgument, throwError } from "../utils/index.js";
|
||||||
|
|
||||||
|
|
||||||
declare global {
|
declare global {
|
||||||
@ -37,22 +37,18 @@ export function createHash(algo: string): CryptoHasher {
|
|||||||
case "sha256": return sha256.create();
|
case "sha256": return sha256.create();
|
||||||
case "sha512": return sha512.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 {
|
export function createHmac(_algo: string, key: Uint8Array): CryptoHasher {
|
||||||
const algo = ({ sha256, sha512 }[_algo]);
|
const algo = ({ sha256, sha512 }[_algo]);
|
||||||
if (algo == null) {
|
assertArgument(algo != null, "invalid hmac algorithm", "algorithm", _algo);
|
||||||
return throwArgumentError("invalid hmac algorithm", "algorithm", _algo);
|
|
||||||
}
|
|
||||||
return hmac.create(algo, key);
|
return hmac.create(algo, key);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function pbkdf2Sync(password: Uint8Array, salt: Uint8Array, iterations: number, keylen: number, _algo: "sha256" | "sha512"): Uint8Array {
|
export function pbkdf2Sync(password: Uint8Array, salt: Uint8Array, iterations: number, keylen: number, _algo: "sha256" | "sha512"): Uint8Array {
|
||||||
const algo = ({ sha256, sha512 }[_algo]);
|
const algo = ({ sha256, sha512 }[_algo]);
|
||||||
if (algo == null) {
|
assertArgument(algo != null, "invalid pbkdf2 algorithm", "algorithm", _algo);
|
||||||
return throwArgumentError("invalid pbkdf2 algorithm", "algorithm", _algo);
|
|
||||||
}
|
|
||||||
return pbkdf2(algo, password, salt, { c: iterations, dkLen: keylen });
|
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) {
|
assertArgument(Number.isInteger(length) && length > 0 && length <= 1024, "invalid length", "length", length);
|
||||||
throwArgumentError("invalid length", "length", length);
|
|
||||||
}
|
|
||||||
|
|
||||||
const result = new Uint8Array(length);
|
const result = new Uint8Array(length);
|
||||||
crypto.getRandomValues(result);
|
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 { getBytes, hexlify } from "../utils/index.js";
|
||||||
|
|
||||||
import type { BytesLike } from "../utils/index.js";
|
import type { BytesLike } from "../utils/index.js";
|
||||||
|
@ -2,7 +2,7 @@ import { ZeroHash } from "../constants/index.js";
|
|||||||
import {
|
import {
|
||||||
concat, dataLength, getBigInt, getBytes, getNumber, getStore, hexlify,
|
concat, dataLength, getBigInt, getBytes, getNumber, getStore, hexlify,
|
||||||
isHexString, setStore,
|
isHexString, setStore,
|
||||||
assertPrivate, throwArgumentError
|
assertArgument, assertPrivate
|
||||||
} from "../utils/index.js";
|
} from "../utils/index.js";
|
||||||
|
|
||||||
import type {
|
import type {
|
||||||
@ -48,26 +48,21 @@ export class Signature implements Freezable<Signature> {
|
|||||||
|
|
||||||
get r(): string { return getStore(this.#props, "r"); }
|
get r(): string { return getStore(this.#props, "r"); }
|
||||||
set r(value: BytesLike) {
|
set r(value: BytesLike) {
|
||||||
if (dataLength(value) !== 32) {
|
assertArgument(dataLength(value) === 32, "invalid r", "value", value);
|
||||||
throwArgumentError("invalid r", "value", value);
|
|
||||||
}
|
|
||||||
setStore(this.#props, "r", hexlify(value));
|
setStore(this.#props, "r", hexlify(value));
|
||||||
}
|
}
|
||||||
|
|
||||||
get s(): string { return getStore(this.#props, "s"); }
|
get s(): string { return getStore(this.#props, "s"); }
|
||||||
set s(value: BytesLike) {
|
set s(value: BytesLike) {
|
||||||
if (dataLength(value) !== 32) {
|
assertArgument(dataLength(value) === 32, "invalid r", "value", value);
|
||||||
throwArgumentError("invalid r", "value", value);
|
assertArgument((getBytes(value)[0] & 0x80) === 0, "non-canonical s", "value", value);
|
||||||
} else if (getBytes(value)[0] & 0x80) {
|
|
||||||
throwArgumentError("non-canonical s", "value", value);
|
|
||||||
}
|
|
||||||
setStore(this.#props, "s", hexlify(value));
|
setStore(this.#props, "s", hexlify(value));
|
||||||
}
|
}
|
||||||
|
|
||||||
get v(): 27 | 28 { return getStore(this.#props, "v"); }
|
get v(): 27 | 28 { return getStore(this.#props, "v"); }
|
||||||
set v(value: BigNumberish) {
|
set v(value: BigNumberish) {
|
||||||
const v = getNumber(value, "value");
|
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);
|
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
|
// Get the chain ID from an EIP-155 v
|
||||||
static getChainId(v: BigNumberish): bigint {
|
static getChainId(v: BigNumberish): bigint {
|
||||||
const bv = getBigInt(v, "v");
|
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; }
|
if ((bv == BN_27) || (bv == BN_28)) { return BN_0; }
|
||||||
|
|
||||||
// Bad value for an EIP-155 v
|
// 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;
|
return (bv - BN_35) / BN_2;
|
||||||
}
|
}
|
||||||
@ -164,14 +155,14 @@ export class Signature implements Freezable<Signature> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static from(sig?: SignatureLike): Signature {
|
static from(sig?: SignatureLike): Signature {
|
||||||
|
function assertError(check: unknown, message: string): asserts check {
|
||||||
|
assertArgument(check, message, "signature", sig);
|
||||||
|
};
|
||||||
|
|
||||||
if (sig == null) {
|
if (sig == null) {
|
||||||
return new Signature(_guard, ZeroHash, ZeroHash, 27);
|
return new Signature(_guard, ZeroHash, ZeroHash, 27);
|
||||||
}
|
}
|
||||||
|
|
||||||
const throwError = (message: string) => {
|
|
||||||
return throwArgumentError(message, "signature", sig);
|
|
||||||
};
|
|
||||||
|
|
||||||
if (typeof(sig) === "string") {
|
if (typeof(sig) === "string") {
|
||||||
const bytes = getBytes(sig, "signature");
|
const bytes = getBytes(sig, "signature");
|
||||||
if (bytes.length === 64) {
|
if (bytes.length === 64) {
|
||||||
@ -185,38 +176,38 @@ export class Signature implements Freezable<Signature> {
|
|||||||
if (bytes.length === 65) {
|
if (bytes.length === 65) {
|
||||||
const r = hexlify(bytes.slice(0, 32));
|
const r = hexlify(bytes.slice(0, 32));
|
||||||
const s = bytes.slice(32, 64);
|
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]);
|
const v = Signature.getNormalizedV(bytes[64]);
|
||||||
return new Signature(_guard, r, hexlify(s), v);
|
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(); }
|
if (sig instanceof Signature) { return sig.clone(); }
|
||||||
|
|
||||||
// Get r
|
// Get r
|
||||||
const r = sig.r;
|
const r = sig.r;
|
||||||
if (r == null) { throwError("missing r"); }
|
assertError(r != null, "missing r");
|
||||||
if (!isHexString(r, 32)) { throwError("invalid r"); }
|
assertError(isHexString(r, 32), "invalid r");
|
||||||
|
|
||||||
// Get s; by any means necessary (we check consistency below)
|
// Get s; by any means necessary (we check consistency below)
|
||||||
const s = (function(s?: string, yParityAndS?: string) {
|
const s = (function(s?: string, yParityAndS?: string) {
|
||||||
if (s != null) {
|
if (s != null) {
|
||||||
if (!isHexString(s, 32)) { throwError("invalid s"); }
|
assertError(isHexString(s, 32), "invalid s");
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (yParityAndS != null) {
|
if (yParityAndS != null) {
|
||||||
if (!isHexString(yParityAndS, 32)) { throwError("invalid yParityAndS"); }
|
assertError(isHexString(yParityAndS, 32), "invalid yParityAndS");
|
||||||
const bytes = getBytes(yParityAndS);
|
const bytes = getBytes(yParityAndS);
|
||||||
bytes[0] &= 0x7f;
|
bytes[0] &= 0x7f;
|
||||||
return hexlify(bytes);
|
return hexlify(bytes);
|
||||||
}
|
}
|
||||||
|
|
||||||
return throwError("missing s");
|
assertError(false, "missing s");
|
||||||
})(sig.s, sig.yParityAndS);
|
})(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)
|
// 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 } {
|
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 (yParityAndS != null) {
|
||||||
if (!isHexString(yParityAndS, 32)) { throwError("invalid yParityAndS"); }
|
assertError(isHexString(yParityAndS, 32), "invalid yParityAndS");
|
||||||
return { v: ((getBytes(yParityAndS)[0] & 0x80) ? 28: 27) };
|
return { v: ((getBytes(yParityAndS)[0] & 0x80) ? 28: 27) };
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -238,21 +229,18 @@ export class Signature implements Freezable<Signature> {
|
|||||||
case 0: return { v: 27 };
|
case 0: return { v: 27 };
|
||||||
case 1: return { v: 28 };
|
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);
|
})(sig.v, sig.yParityAndS, sig.yParity);
|
||||||
|
|
||||||
const result = new Signature(_guard, r, s, v);
|
const result = new Signature(_guard, r, s, v);
|
||||||
if (networkV) { setStore(result.#props, "networkV", networkV); }
|
if (networkV) { setStore(result.#props, "networkV", networkV); }
|
||||||
|
|
||||||
// If multiple of v, yParity, yParityAndS we given, check they match
|
// If multiple of v, yParity, yParityAndS we given, check they match
|
||||||
if ("yParity" in sig && sig.yParity !== result.yParity) {
|
assertError(!("yParity" in sig && sig.yParity !== result.yParity), "yParity mismatch");
|
||||||
throwError("yParity mismatch");
|
assertError(!("yParityAndS" in sig && sig.yParityAndS !== result.yParityAndS), "yParityAndS mismatch");
|
||||||
} else if ("yParityAndS" in sig && sig.yParityAndS !== result.yParityAndS) {
|
|
||||||
throwError("yParityAndS mismatch");
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
@ -3,7 +3,7 @@ import * as secp256k1 from "@noble/secp256k1";
|
|||||||
|
|
||||||
import {
|
import {
|
||||||
concat, dataLength, getBytes, getBytesCopy, hexlify, toHex,
|
concat, dataLength, getBytes, getBytesCopy, hexlify, toHex,
|
||||||
assertArgument, throwArgumentError
|
assertArgument
|
||||||
} from "../utils/index.js";
|
} from "../utils/index.js";
|
||||||
|
|
||||||
import { computeHmac } from "./hmac.js";
|
import { computeHmac } from "./hmac.js";
|
||||||
@ -87,7 +87,7 @@ export class SigningKey {
|
|||||||
const pubKey = secp256k1.recoverPublicKey(getBytesCopy(digest), der, sig.yParity);
|
const pubKey = secp256k1.recoverPublicKey(getBytesCopy(digest), der, sig.yParity);
|
||||||
if (pubKey != null) { return hexlify(pubKey); }
|
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 {
|
static _addPoints(p0: BytesLike, p1: BytesLike, compressed?: boolean): string {
|
||||||
|
@ -81,14 +81,14 @@ export {
|
|||||||
concat, dataLength, dataSlice, getBytes, getBytesCopy, hexlify,
|
concat, dataLength, dataSlice, getBytes, getBytesCopy, hexlify,
|
||||||
isHexString, isBytesLike, stripZerosLeft, zeroPadBytes, zeroPadValue,
|
isHexString, isBytesLike, stripZerosLeft, zeroPadBytes, zeroPadValue,
|
||||||
assertArgument, assertArgumentCount, assertNormalize, assertPrivate,
|
assertArgument, assertArgumentCount, assertNormalize, assertPrivate,
|
||||||
makeError, throwArgumentError, throwError,
|
makeError, throwError,
|
||||||
isCallException, isError,
|
isCallException, isError,
|
||||||
getIpfsGatewayFunc, FetchRequest, FetchResponse, FetchCancelSignal,
|
getIpfsGatewayFunc, FetchRequest, FetchResponse, FetchCancelSignal,
|
||||||
FixedFormat, FixedNumber, formatFixed, parseFixed,
|
FixedFormat, FixedNumber, formatFixed, parseFixed,
|
||||||
getBigInt, getNumber, toArray, toBigInt, toHex, toNumber, toQuantity,
|
getBigInt, getNumber, toArray, toBigInt, toHex, toNumber, toQuantity,
|
||||||
fromTwos, toTwos, mask,
|
fromTwos, toTwos, mask,
|
||||||
formatEther, parseEther, formatUnits, parseUnits,
|
formatEther, parseEther, formatUnits, parseUnits,
|
||||||
_toEscapedUtf8String, toUtf8Bytes, toUtf8CodePoints, toUtf8String,
|
toUtf8Bytes, toUtf8CodePoints, toUtf8String,
|
||||||
Utf8ErrorFuncs,
|
Utf8ErrorFuncs,
|
||||||
decodeRlp, encodeRlp
|
decodeRlp, encodeRlp
|
||||||
} from "./utils/index.js";
|
} from "./utils/index.js";
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
|
|
||||||
import { keccak256 } from "../crypto/index.js";
|
import { keccak256 } from "../crypto/index.js";
|
||||||
import {
|
import {
|
||||||
concat, hexlify, throwArgumentError, toUtf8Bytes, toUtf8String
|
concat, hexlify, assertArgument, toUtf8Bytes, toUtf8String
|
||||||
} from "../utils/index.js";
|
} from "../utils/index.js";
|
||||||
|
|
||||||
|
|
||||||
@ -56,9 +56,7 @@ export function isValidName(name: string): boolean {
|
|||||||
|
|
||||||
export function namehash(name: string): string {
|
export function namehash(name: string): string {
|
||||||
/* istanbul ignore if */
|
/* istanbul ignore if */
|
||||||
if (typeof(name) !== "string") {
|
assertArgument(typeof(name) === "string", "invalid ENS name; not a string", "name", name);
|
||||||
throwArgumentError("invalid ENS name; not a string", "name", name);
|
|
||||||
}
|
|
||||||
|
|
||||||
let result: string | Uint8Array = Zeros;
|
let result: string | Uint8Array = Zeros;
|
||||||
|
|
||||||
|
@ -3,7 +3,7 @@ import {
|
|||||||
} from "../crypto/index.js";
|
} from "../crypto/index.js";
|
||||||
import {
|
import {
|
||||||
concat, dataLength, getBytes, hexlify, toArray, toTwos, toUtf8Bytes, zeroPadBytes, zeroPadValue,
|
concat, dataLength, getBytes, hexlify, toArray, toTwos, toUtf8Bytes, zeroPadBytes, zeroPadValue,
|
||||||
throwArgumentError
|
assertArgument
|
||||||
} from "../utils/index.js";
|
} from "../utils/index.js";
|
||||||
|
|
||||||
|
|
||||||
@ -31,9 +31,7 @@ function _pack(type: string, value: any, isArray?: boolean): Uint8Array {
|
|||||||
if (match) {
|
if (match) {
|
||||||
let size = parseInt(match[2] || "256")
|
let size = parseInt(match[2] || "256")
|
||||||
|
|
||||||
if ((match[2] && String(size) !== match[2]) || (size % 8 !== 0) || size === 0 || size > 256) {
|
assertArgument((!match[2] || match[2] === String(size)) && (size % 8 === 0) && size !== 0 && size <= 256, "invalid number type", "type", type);
|
||||||
return throwArgumentError("invalid number type", "type", type)
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isArray) { size = 256; }
|
if (isArray) { size = 256; }
|
||||||
|
|
||||||
@ -46,12 +44,9 @@ function _pack(type: string, value: any, isArray?: boolean): Uint8Array {
|
|||||||
if (match) {
|
if (match) {
|
||||||
const size = parseInt(match[1]);
|
const size = parseInt(match[1]);
|
||||||
|
|
||||||
if (String(size) !== match[1] || size === 0 || size > 32) {
|
assertArgument(String(size) === match[1] && size !== 0 && size <= 32, "invalid bytes type", "type", type);
|
||||||
return throwArgumentError("invalid bytes type", "type", type)
|
assertArgument(dataLength(value) === size, `invalid value for ${ type }`, "value", value);
|
||||||
}
|
|
||||||
if (dataLength(value) !== size) {
|
|
||||||
return throwArgumentError(`invalid value for ${ type }`, "value", value)
|
|
||||||
}
|
|
||||||
if (isArray) { return getBytes(zeroPadBytes(value, 32)); }
|
if (isArray) { return getBytes(zeroPadBytes(value, 32)); }
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
@ -60,9 +55,8 @@ function _pack(type: string, value: any, isArray?: boolean): Uint8Array {
|
|||||||
if (match && Array.isArray(value)) {
|
if (match && Array.isArray(value)) {
|
||||||
const baseType = match[1];
|
const baseType = match[1];
|
||||||
const count = parseInt(match[2] || String(value.length));
|
const count = parseInt(match[2] || String(value.length));
|
||||||
if (count != value.length) {
|
assertArgument(count === value.length, `invalid array length for ${ type }`, "value", value);
|
||||||
throwArgumentError(`invalid array length for ${ type }`, "value", value)
|
|
||||||
}
|
|
||||||
const result: Array<Uint8Array> = [];
|
const result: Array<Uint8Array> = [];
|
||||||
value.forEach(function(value) {
|
value.forEach(function(value) {
|
||||||
result.push(_pack(baseType, value, true));
|
result.push(_pack(baseType, value, true));
|
||||||
@ -70,15 +64,14 @@ function _pack(type: string, value: any, isArray?: boolean): Uint8Array {
|
|||||||
return getBytes(concat(result));
|
return getBytes(concat(result));
|
||||||
}
|
}
|
||||||
|
|
||||||
return throwArgumentError("invalid type", "type", type)
|
assertArgument(false, "invalid type", "type", type)
|
||||||
}
|
}
|
||||||
|
|
||||||
// @TODO: Array Enum
|
// @TODO: Array Enum
|
||||||
|
|
||||||
export function solidityPacked(types: ReadonlyArray<string>, values: ReadonlyArray<any>): string {
|
export function solidityPacked(types: ReadonlyArray<string>, values: ReadonlyArray<any>): string {
|
||||||
if (types.length != values.length) {
|
assertArgument(types.length === values.length, "wrong number of values; expected ${ types.length }", "values", values);
|
||||||
throwArgumentError("wrong number of values; expected ${ types.length }", "values", values)
|
|
||||||
}
|
|
||||||
const tight: Array<Uint8Array> = [];
|
const tight: Array<Uint8Array> = [];
|
||||||
types.forEach(function(type, index) {
|
types.forEach(function(type, index) {
|
||||||
tight.push(_pack(type, values[index]));
|
tight.push(_pack(type, values[index]));
|
||||||
|
@ -3,7 +3,7 @@ import { getAddress } from "../address/index.js";
|
|||||||
import { keccak256 } from "../crypto/index.js";
|
import { keccak256 } from "../crypto/index.js";
|
||||||
import {
|
import {
|
||||||
concat, defineProperties, getBigInt, getBytes, hexlify, isHexString, mask, toHex, toTwos, zeroPadValue,
|
concat, defineProperties, getBigInt, getBytes, hexlify, isHexString, mask, toHex, toTwos, zeroPadValue,
|
||||||
throwArgumentError
|
assertArgument
|
||||||
} from "../utils/index.js";
|
} from "../utils/index.js";
|
||||||
|
|
||||||
import { id } from "./id.js";
|
import { id } from "./id.js";
|
||||||
@ -58,9 +58,7 @@ const domainFieldNames: Array<string> = [
|
|||||||
|
|
||||||
function checkString(key: string): (value: any) => string {
|
function checkString(key: string): (value: any) => string {
|
||||||
return function (value: any){
|
return function (value: any){
|
||||||
if (typeof(value) !== "string") {
|
assertArgument(typeof(value) === "string", `invalid domain value for ${ JSON.stringify(key) }`, `domain.${ key }`, value);
|
||||||
throwArgumentError(`invalid domain value for ${ JSON.stringify(key) }`, `domain.${ key }`, value);
|
|
||||||
}
|
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -75,13 +73,11 @@ const domainChecks: Record<string, (value: any) => any> = {
|
|||||||
try {
|
try {
|
||||||
return getAddress(value).toLowerCase();
|
return getAddress(value).toLowerCase();
|
||||||
} catch (error) { }
|
} catch (error) { }
|
||||||
return throwArgumentError(`invalid domain value "verifyingContract"`, "domain.verifyingContract", value);
|
assertArgument(false, `invalid domain value "verifyingContract"`, "domain.verifyingContract", value);
|
||||||
},
|
},
|
||||||
salt: function(value: any) {
|
salt: function(value: any) {
|
||||||
const bytes = getBytes(value, "domain.salt");
|
const bytes = getBytes(value, "domain.salt");
|
||||||
if (bytes.length !== 32) {
|
assertArgument(bytes.length === 32, `invalid domain value "salt"`, "domain.salt", value);
|
||||||
throwArgumentError(`invalid domain value "salt"`, "domain.salt", value);
|
|
||||||
}
|
|
||||||
return hexlify(bytes);
|
return hexlify(bytes);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -94,9 +90,7 @@ function getBaseEncoder(type: string): null | ((value: any) => string) {
|
|||||||
const signed = (match[1] === "");
|
const signed = (match[1] === "");
|
||||||
|
|
||||||
const width = parseInt(match[2] || "256");
|
const width = parseInt(match[2] || "256");
|
||||||
if (width % 8 !== 0 || width > 256 || (match[2] && match[2] !== String(width))) {
|
assertArgument(width % 8 === 0 && width !== 0 && width <= 256 && (match[2] == null || match[2] === String(width)), "invalid numeric width", "type", type);
|
||||||
throwArgumentError("invalid numeric width", "type", type);
|
|
||||||
}
|
|
||||||
|
|
||||||
const boundsUpper = mask(BN_MAX_UINT256, signed ? (width - 1): width);
|
const boundsUpper = mask(BN_MAX_UINT256, signed ? (width - 1): width);
|
||||||
const boundsLower = signed ? ((boundsUpper + BN_1) * BN__1): BN_0;
|
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) {
|
return function(_value: BigNumberish) {
|
||||||
const value = getBigInt(_value, "value");
|
const value = getBigInt(_value, "value");
|
||||||
|
|
||||||
if (value < boundsLower || value > boundsUpper) {
|
assertArgument(value >= boundsLower && value <= boundsUpper, `value out-of-bounds for ${ type }`, "value", value);
|
||||||
throwArgumentError(`value out-of-bounds for ${ type }`, "value", value);
|
|
||||||
}
|
|
||||||
|
|
||||||
return toHex(toTwos(value, 256), 32);
|
return toHex(toTwos(value, 256), 32);
|
||||||
};
|
};
|
||||||
@ -118,15 +110,11 @@ function getBaseEncoder(type: string): null | ((value: any) => string) {
|
|||||||
const match = type.match(/^bytes(\d+)$/);
|
const match = type.match(/^bytes(\d+)$/);
|
||||||
if (match) {
|
if (match) {
|
||||||
const width = parseInt(match[1]);
|
const width = parseInt(match[1]);
|
||||||
if (width === 0 || width > 32 || match[1] !== String(width)) {
|
assertArgument(width !== 0 && width <= 32 && match[1] === String(width), "invalid bytes width", "type", type);
|
||||||
throwArgumentError("invalid bytes width", "type", type);
|
|
||||||
}
|
|
||||||
|
|
||||||
return function(value: BytesLike) {
|
return function(value: BytesLike) {
|
||||||
const bytes = getBytes(value);
|
const bytes = getBytes(value);
|
||||||
if (bytes.length !== width) {
|
assertArgument(bytes.length === width, `invalid length for ${ type }`, "value", value);
|
||||||
throwArgumentError(`invalid length for ${ type }`, "value", value);
|
|
||||||
}
|
|
||||||
return hexPadRight(value);
|
return hexPadRight(value);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@ -192,24 +180,18 @@ export class TypedDataEncoder {
|
|||||||
for (const field of types[name]) {
|
for (const field of types[name]) {
|
||||||
|
|
||||||
// Check each field has a unique name
|
// Check each field has a unique name
|
||||||
if (uniqueNames.has(field.name)) {
|
assertArgument(!uniqueNames.has(field.name), `duplicate variable name ${ JSON.stringify(field.name) } in ${ JSON.stringify(name) }`, "types", types);
|
||||||
throwArgumentError(`duplicate variable name ${ JSON.stringify(field.name) } in ${ JSON.stringify(name) }`, "types", types);
|
|
||||||
}
|
|
||||||
uniqueNames.add(field.name);
|
uniqueNames.add(field.name);
|
||||||
|
|
||||||
// Get the base type (drop any array specifiers)
|
// Get the base type (drop any array specifiers)
|
||||||
const baseType = (<any>(field.type.match(/^([^\x5b]*)(\x5b|$)/)))[1] || null;
|
const baseType = (<any>(field.type.match(/^([^\x5b]*)(\x5b|$)/)))[1] || null;
|
||||||
if (baseType === name) {
|
assertArgument(baseType !== name, `circular type reference to ${ JSON.stringify(baseType) }`, "types", types);
|
||||||
throwArgumentError(`circular type reference to ${ JSON.stringify(baseType) }`, "types", types);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Is this a base encoding type?
|
// Is this a base encoding type?
|
||||||
const encoder = getBaseEncoder(baseType);
|
const encoder = getBaseEncoder(baseType);
|
||||||
if (encoder) { continue; }
|
if (encoder) { continue; }
|
||||||
|
|
||||||
if (!parents.has(baseType)) {
|
assertArgument(parents.has(baseType), `unknown type ${ JSON.stringify(baseType) }`, "types", types);
|
||||||
throwArgumentError(`unknown type ${ JSON.stringify(baseType) }`, "types", types);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add linkage
|
// Add linkage
|
||||||
(parents.get(baseType) as Array<string>).push(name);
|
(parents.get(baseType) as Array<string>).push(name);
|
||||||
@ -219,20 +201,14 @@ export class TypedDataEncoder {
|
|||||||
|
|
||||||
// Deduce the primary type
|
// Deduce the primary type
|
||||||
const primaryTypes = Array.from(parents.keys()).filter((n) => ((parents.get(n) as Array<string>).length === 0));
|
const primaryTypes = Array.from(parents.keys()).filter((n) => ((parents.get(n) as Array<string>).length === 0));
|
||||||
|
assertArgument(primaryTypes.length !== 0, "missing primary type", "types", types);
|
||||||
if (primaryTypes.length === 0) {
|
assertArgument(primaryTypes.length === 1, `ambiguous primary types or unused types: ${ primaryTypes.map((t) => (JSON.stringify(t))).join(", ") }`, "types", types);
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
defineProperties<TypedDataEncoder>(this, { primaryType: primaryTypes[0] });
|
defineProperties<TypedDataEncoder>(this, { primaryType: primaryTypes[0] });
|
||||||
|
|
||||||
// Check for circular type references
|
// Check for circular type references
|
||||||
function checkCircular(type: string, found: Set<string>) {
|
function checkCircular(type: string, found: Set<string>) {
|
||||||
if (found.has(type)) {
|
assertArgument(!found.has(type), `circular type reference to ${ JSON.stringify(type) }`, "types", types);
|
||||||
throwArgumentError(`circular type reference to ${ JSON.stringify(type) }`, "types", types);
|
|
||||||
}
|
|
||||||
|
|
||||||
found.add(type);
|
found.add(type);
|
||||||
|
|
||||||
@ -282,11 +258,8 @@ export class TypedDataEncoder {
|
|||||||
if (match) {
|
if (match) {
|
||||||
const subtype = match[1];
|
const subtype = match[1];
|
||||||
const subEncoder = this.getEncoder(subtype);
|
const subEncoder = this.getEncoder(subtype);
|
||||||
const length = parseInt(match[3]);
|
|
||||||
return (value: Array<any>) => {
|
return (value: Array<any>) => {
|
||||||
if (length >= 0 && value.length !== length) {
|
assertArgument(!match[3] || parseInt(match[3]) === value.length, `array length mismatch; expected length ${ parseInt(match[3]) }`, "value", value);
|
||||||
throwArgumentError("array length mismatch; expected length ${ arrayLength }", "value", value);
|
|
||||||
}
|
|
||||||
|
|
||||||
let result = value.map(subEncoder);
|
let result = value.map(subEncoder);
|
||||||
if (this.#fullTypes.has(subtype)) {
|
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 {
|
encodeType(name: string): string {
|
||||||
const result = this.#fullTypes.get(name);
|
const result = this.#fullTypes.get(name);
|
||||||
if (!result) {
|
assertArgument(result, `unknown type: ${ JSON.stringify(name) }`, "name", name);
|
||||||
return throwArgumentError(`unknown type: ${ JSON.stringify(name) }`, "name", name);
|
|
||||||
}
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -349,12 +320,8 @@ export class TypedDataEncoder {
|
|||||||
// Array
|
// Array
|
||||||
const match = type.match(/^(.*)(\x5b(\d*)\x5d)$/);
|
const match = type.match(/^(.*)(\x5b(\d*)\x5d)$/);
|
||||||
if (match) {
|
if (match) {
|
||||||
const subtype = match[1];
|
assertArgument(!match[3] || parseInt(match[3]) === value.length, `array length mismatch; expected length ${ parseInt(match[3]) }`, "value", value);
|
||||||
const length = parseInt(match[3]);
|
return value.map((v: any) => this._visit(match[1], v, callback));
|
||||||
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));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Struct
|
// Struct
|
||||||
@ -366,7 +333,7 @@ export class TypedDataEncoder {
|
|||||||
}, <Record<string, any>>{});
|
}, <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 {
|
visit(value: Record<string, any>, callback: (type: string, data: any) => any): any {
|
||||||
@ -389,9 +356,7 @@ export class TypedDataEncoder {
|
|||||||
const domainFields: Array<TypedDataField> = [ ];
|
const domainFields: Array<TypedDataField> = [ ];
|
||||||
for (const name in domain) {
|
for (const name in domain) {
|
||||||
const type = domainFieldTypes[name];
|
const type = domainFieldTypes[name];
|
||||||
if (!type) {
|
assertArgument(type, `invalid typed-data domain key: ${ JSON.stringify(name) }`, "domain", domain);
|
||||||
throwArgumentError(`invalid typed-data domain key: ${ JSON.stringify(name) }`, "domain", domain);
|
|
||||||
}
|
|
||||||
domainFields.push({ name, type });
|
domainFields.push({ name, type });
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -475,11 +440,9 @@ export class TypedDataEncoder {
|
|||||||
const encoder = TypedDataEncoder.from(types);
|
const encoder = TypedDataEncoder.from(types);
|
||||||
|
|
||||||
const typesWithDomain = Object.assign({ }, types);
|
const typesWithDomain = Object.assign({ }, types);
|
||||||
if (typesWithDomain.EIP712Domain) {
|
assertArgument(typesWithDomain.EIP712Domain == null, "types must not contain EIP712Domain type", "types.EIP712Domain", types);
|
||||||
throwArgumentError("types must not contain EIP712Domain type", "types.EIP712Domain", types);
|
|
||||||
} else {
|
|
||||||
typesWithDomain.EIP712Domain = domainTypes;
|
typesWithDomain.EIP712Domain = domainTypes;
|
||||||
}
|
|
||||||
|
|
||||||
// Validate the data structures and types
|
// Validate the data structures and types
|
||||||
encoder.encode(value);
|
encoder.encode(value);
|
||||||
@ -506,13 +469,11 @@ export class TypedDataEncoder {
|
|||||||
case "bool":
|
case "bool":
|
||||||
return !!value;
|
return !!value;
|
||||||
case "string":
|
case "string":
|
||||||
if (typeof(value) !== "string") {
|
assertArgument(typeof(value) === "string", "invalid string", "value", value);
|
||||||
throwArgumentError(`invalid string`, "value", value);
|
|
||||||
}
|
|
||||||
return 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 {
|
import {
|
||||||
concat, dataLength, dataSlice, hexlify, isHexString,
|
concat, dataLength, dataSlice, hexlify, isHexString,
|
||||||
getBigInt, getBytes, getNumber,
|
getBigInt, getBytes, getNumber,
|
||||||
isCallException, makeError, throwError, throwArgumentError,
|
isCallException, makeError, throwError, assertArgument,
|
||||||
FetchRequest,
|
FetchRequest,
|
||||||
toArray, toQuantity,
|
toArray, toQuantity,
|
||||||
defineProperties, EventPayload, resolveProperties,
|
defineProperties, EventPayload, resolveProperties,
|
||||||
@ -198,7 +198,7 @@ async function getSubscription(_event: ProviderEvent, provider: AbstractProvider
|
|||||||
return { filter, tag: getTag("event", filter), type: "event" };
|
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(); }
|
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 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> {
|
_getFilter(filter: Filter | FilterByBlockHash): PerformActionFilter | Promise<PerformActionFilter> {
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import { Transaction } from "../transaction/index.js";
|
import { Transaction } from "../transaction/index.js";
|
||||||
import {
|
import {
|
||||||
defineProperties, getBigInt, resolveProperties,
|
defineProperties, getBigInt, resolveProperties,
|
||||||
throwArgumentError, throwError
|
assertArgument, throwError
|
||||||
} from "../utils/index.js";
|
} from "../utils/index.js";
|
||||||
|
|
||||||
import type { TypedDataDomain, TypedDataField } from "../hash/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) {
|
if (pop.to != null) {
|
||||||
pop.to = provider.resolveName(pop.to).then((to) => {
|
pop.to = provider.resolveName(pop.to).then((to) => {
|
||||||
if (to == null) {
|
assertArgument(to != null, "transaction to ENS name not configured", "tx.to", pop.to);
|
||||||
return throwArgumentError("transaction to ENS name not configured", "tx.to", pop.to);
|
|
||||||
}
|
|
||||||
return to;
|
return to;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -53,9 +51,8 @@ export abstract class AbstractSigner<P extends null | Provider = null | Provider
|
|||||||
this.getAddress(),
|
this.getAddress(),
|
||||||
this.resolveName(from)
|
this.resolveName(from)
|
||||||
]).then(([ address, from ]) => {
|
]).then(([ address, from ]) => {
|
||||||
if (!from || address.toLowerCase() !== from.toLowerCase()) {
|
assertArgument(from && address.toLowerCase() === from.toLowerCase(),
|
||||||
return throwArgumentError("transaction from mismatch", "tx.from", from);
|
"transaction from mismatch", "tx.from", from);
|
||||||
}
|
|
||||||
return address;
|
return address;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -84,9 +81,7 @@ export abstract class AbstractSigner<P extends null | Provider = null | Provider
|
|||||||
const network = await (<Provider>(this.provider)).getNetwork();
|
const network = await (<Provider>(this.provider)).getNetwork();
|
||||||
if (pop.chainId != null) {
|
if (pop.chainId != null) {
|
||||||
const chainId = getBigInt(pop.chainId);
|
const chainId = getBigInt(pop.chainId);
|
||||||
if (chainId !== network.chainId) {
|
assertArgument(chainId === network.chainId, "transaction chainId mismatch", "tx.chainId", tx.chainId);
|
||||||
throwArgumentError("transaction chainId mismatch", "tx.chainId", tx.chainId);
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
pop.chainId = network.chainId;
|
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
|
// Do not allow mixing pre-eip-1559 and eip-1559 properties
|
||||||
const hasEip1559 = (pop.maxFeePerGas != null || pop.maxPriorityFeePerGas != null);
|
const hasEip1559 = (pop.maxFeePerGas != null || pop.maxPriorityFeePerGas != null);
|
||||||
if (pop.gasPrice != null && (pop.type === 2 || hasEip1559)) {
|
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) {
|
} 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)) {
|
if ((pop.type === 2 || pop.type == null) && (pop.maxFeePerGas != null && pop.maxPriorityFeePerGas != null)) {
|
||||||
|
@ -5,7 +5,7 @@ import {
|
|||||||
concat, dataSlice, getBytes, hexlify, zeroPadValue,
|
concat, dataSlice, getBytes, hexlify, zeroPadValue,
|
||||||
defineProperties, encodeBase58, getBigInt, toArray,
|
defineProperties, encodeBase58, getBigInt, toArray,
|
||||||
toNumber, toUtf8Bytes, toUtf8String,
|
toNumber, toUtf8Bytes, toUtf8String,
|
||||||
throwArgumentError, throwError,
|
assertArgument, throwError,
|
||||||
FetchRequest
|
FetchRequest
|
||||||
} from "../utils/index.js";
|
} from "../utils/index.js";
|
||||||
|
|
||||||
@ -81,9 +81,8 @@ function encodeBytes(datas: Array<BytesLike>) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function callAddress(value: string): string {
|
function callAddress(value: string): string {
|
||||||
if (value.length !== 66 || dataSlice(value, 0, 12) !== "0x000000000000000000000000") {
|
assertArgument(value.length === 66 && dataSlice(value, 0, 12) === "0x000000000000000000000000",
|
||||||
throwArgumentError("invalid call address", "value", value);
|
"invalid call address", "value", value);
|
||||||
}
|
|
||||||
return getAddress("0x" + value.substring(26));
|
return getAddress("0x" + value.substring(26));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -95,7 +94,7 @@ function getIpfsLink(link: string): string {
|
|||||||
} else if (link.match(/^ipfs:\/\//i)) {
|
} else if (link.match(/^ipfs:\/\//i)) {
|
||||||
link = link.substring(7);
|
link = link.substring(7);
|
||||||
} else {
|
} else {
|
||||||
throwArgumentError("unsupported IPFS format", "link", link);
|
assertArgument(false, "unsupported IPFS format", "link", link);
|
||||||
}
|
}
|
||||||
|
|
||||||
return `https:/\/gateway.ipfs.io/ipfs/${ 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 { accessListify } from "../transaction/index.js";
|
||||||
import {
|
import {
|
||||||
getBigInt, getNumber, hexlify, isHexString, zeroPadValue,
|
getBigInt, getNumber, hexlify, isHexString, zeroPadValue,
|
||||||
throwArgumentError, throwError
|
assertArgument, throwError
|
||||||
} from "../utils/index.js";
|
} from "../utils/index.js";
|
||||||
|
|
||||||
|
|
||||||
@ -63,20 +63,16 @@ export function formatBoolean(value: any): boolean {
|
|||||||
case false: case "false":
|
case false: case "false":
|
||||||
return 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 {
|
export function formatData(value: string): string {
|
||||||
if (!isHexString(value, true)) {
|
assertArgument(isHexString(value, true), "invalid data", "value", value);
|
||||||
throwArgumentError("", "value", value);
|
|
||||||
}
|
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function formatHash(value: any): string {
|
export function formatHash(value: any): string {
|
||||||
if (!isHexString(value, 32)) {
|
assertArgument(isHexString(value, 32), "invalid hash", "value", value);
|
||||||
throwArgumentError("", "value", value);
|
|
||||||
}
|
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import { accessListify } from "../transaction/index.js";
|
import { accessListify } from "../transaction/index.js";
|
||||||
import {
|
import {
|
||||||
getStore, getBigInt, setStore, throwArgumentError
|
getStore, getBigInt, setStore, assertArgument
|
||||||
} from "../utils/index.js";
|
} from "../utils/index.js";
|
||||||
|
|
||||||
import { EnsPlugin, GasCostPlugin } from "./plugins-network.js";
|
import { EnsPlugin, GasCostPlugin } from "./plugins-network.js";
|
||||||
@ -192,7 +192,7 @@ export class Network {
|
|||||||
return new Network("unknown", network);
|
return new Network("unknown", network);
|
||||||
}
|
}
|
||||||
|
|
||||||
throwArgumentError("unknown network", "network", network);
|
assertArgument(false, "unknown network", "network", network);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Clonable with network-like abilities
|
// Clonable with network-like abilities
|
||||||
@ -205,9 +205,8 @@ export class Network {
|
|||||||
|
|
||||||
// Networkish
|
// Networkish
|
||||||
if (typeof(network) === "object") {
|
if (typeof(network) === "object") {
|
||||||
if (typeof(network.name) !== "string" || typeof(network.chainId) !== "number") {
|
assertArgument(typeof(network.name) === "string" && typeof(network.chainId) === "number",
|
||||||
throwArgumentError("invalid network object name or chainId", "network", network);
|
"invalid network object name or chainId", "network", network);
|
||||||
}
|
|
||||||
|
|
||||||
const custom = new Network(<string>(network.name), <number>(network.chainId));
|
const custom = new Network(<string>(network.name), <number>(network.chainId));
|
||||||
|
|
||||||
@ -222,7 +221,7 @@ export class Network {
|
|||||||
return custom;
|
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); }
|
if (typeof(nameOrChainId) === "number") { nameOrChainId = BigInt(nameOrChainId); }
|
||||||
const existing = Networks.get(nameOrChainId);
|
const existing = Networks.get(nameOrChainId);
|
||||||
if (existing) {
|
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);
|
Networks.set(nameOrChainId, networkFunc);
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import { defineProperties } from "../utils/properties.js";
|
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";
|
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 {
|
function set(name: keyof GasCostParameters, nullish: number): void {
|
||||||
let value = (costs || { })[name];
|
let value = (costs || { })[name];
|
||||||
if (value == null) { value = nullish; }
|
if (value == null) { value = nullish; }
|
||||||
if (typeof(value) !== "number") {
|
assertArgument(typeof(value) === "number", `invalud value for ${ name }`, "costs", costs);
|
||||||
throwArgumentError(`invalud value for ${ name }`, "costs", costs);
|
|
||||||
}
|
|
||||||
props[name] = value;
|
props[name] = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
|
|
||||||
import {
|
import {
|
||||||
defineProperties, resolveProperties, throwArgumentError, throwError,
|
defineProperties, resolveProperties, assertArgument, throwError,
|
||||||
FetchRequest
|
FetchRequest
|
||||||
} from "../utils/index.js";
|
} from "../utils/index.js";
|
||||||
|
|
||||||
@ -36,7 +36,7 @@ function getHost(name: string): string {
|
|||||||
return "opt-goerli.g.alchemy.com";
|
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 {
|
export class AlchemyProvider extends JsonRpcProvider implements CommunityResourcable {
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import {
|
import {
|
||||||
defineProperties, FetchRequest, throwArgumentError
|
defineProperties, FetchRequest, assertArgument
|
||||||
} from "../utils/index.js";
|
} from "../utils/index.js";
|
||||||
|
|
||||||
import { AbstractProvider } from "./abstract-provider.js";
|
import { AbstractProvider } from "./abstract-provider.js";
|
||||||
@ -28,7 +28,8 @@ function getHost(name: string): string {
|
|||||||
case "arbitrum":
|
case "arbitrum":
|
||||||
return "rpc.ankr.com/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 { Network } from "./network.js";
|
||||||
import { JsonRpcProvider } from "./provider-jsonrpc.js";
|
import { JsonRpcProvider } from "./provider-jsonrpc.js";
|
||||||
@ -9,9 +9,7 @@ import type { Networkish } from "./network.js";
|
|||||||
export class CloudflareProvider extends JsonRpcProvider {
|
export class CloudflareProvider extends JsonRpcProvider {
|
||||||
constructor(_network: Networkish = "mainnet") {
|
constructor(_network: Networkish = "mainnet") {
|
||||||
const network = Network.from(_network);
|
const network = Network.from(_network);
|
||||||
if (network.name !== "mainnet") {
|
assertArgument(network.name === "mainnet", "unsupported network", "network", _network);
|
||||||
return throwArgumentError("unsupported network", "network", _network);
|
|
||||||
}
|
|
||||||
super("https:/\/cloudflare-eth.com/", network, { staticNetwork: network });
|
super("https:/\/cloudflare-eth.com/", network, { staticNetwork: network });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -4,7 +4,7 @@ import {
|
|||||||
defineProperties,
|
defineProperties,
|
||||||
hexlify, toQuantity,
|
hexlify, toQuantity,
|
||||||
FetchRequest,
|
FetchRequest,
|
||||||
throwArgumentError, throwError,
|
assertArgument, throwError,
|
||||||
toUtf8String
|
toUtf8String
|
||||||
} from "../utils/index.js";
|
} from "../utils/index.js";
|
||||||
|
|
||||||
@ -103,7 +103,7 @@ export class BaseEtherscanProvider extends AbstractProvider {
|
|||||||
default:
|
default:
|
||||||
}
|
}
|
||||||
|
|
||||||
return throwArgumentError("unsupported network", "network", this.network);
|
assertArgument(false, "unsupported network", "network", this.network);
|
||||||
}
|
}
|
||||||
|
|
||||||
getUrl(module: string, params: Record<string, string>): string {
|
getUrl(module: string, params: Record<string, string>): string {
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
|
|
||||||
import {
|
import {
|
||||||
getBigInt, getNumber, hexlify, throwError, throwArgumentError
|
getBigInt, getNumber, hexlify, throwError, assertArgument
|
||||||
} from "../utils/index.js";
|
} from "../utils/index.js";
|
||||||
|
|
||||||
import { AbstractProvider } from "./abstract-provider.js";
|
import { AbstractProvider } from "./abstract-provider.js";
|
||||||
@ -284,9 +284,8 @@ export class FallbackProvider extends AbstractProvider {
|
|||||||
this.eventQuorum = 1;
|
this.eventQuorum = 1;
|
||||||
this.eventWorkers = 1;
|
this.eventWorkers = 1;
|
||||||
|
|
||||||
if (this.quorum > this.#configs.reduce((a, c) => (a + c.weight), 0)) {
|
assertArgument(this.quorum <= this.#configs.reduce((a, c) => (a + c.weight), 0),
|
||||||
throwArgumentError("quorum exceed provider wieght", "quorum", this.quorum);
|
"quorum exceed provider wieght", "quorum", this.quorum);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// @TOOD: Copy these and only return public values
|
// @TOOD: Copy these and only return public values
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import {
|
import {
|
||||||
defineProperties, FetchRequest, throwArgumentError, throwError
|
defineProperties, FetchRequest, assertArgument, throwError
|
||||||
} from "../utils/index.js";
|
} from "../utils/index.js";
|
||||||
|
|
||||||
import { showThrottleMessage } from "./community.js";
|
import { showThrottleMessage } from "./community.js";
|
||||||
@ -37,7 +37,7 @@ function getHost(name: string): string {
|
|||||||
return "optimism-goerli.infura.io";
|
return "optimism-goerli.infura.io";
|
||||||
}
|
}
|
||||||
|
|
||||||
return throwArgumentError("unsupported network", "network", name);
|
assertArgument(false, "unsupported network", "network", name);
|
||||||
}
|
}
|
||||||
|
|
||||||
export class InfuraWebSocketProvider extends WebSocketProvider implements CommunityResourcable {
|
export class InfuraWebSocketProvider extends WebSocketProvider implements CommunityResourcable {
|
||||||
|
@ -9,7 +9,7 @@ import { TypedDataEncoder } from "../hash/index.js";
|
|||||||
import { accessListify } from "../transaction/index.js";
|
import { accessListify } from "../transaction/index.js";
|
||||||
import {
|
import {
|
||||||
defineProperties, getBigInt, hexlify, isHexString, toQuantity, toUtf8Bytes,
|
defineProperties, getBigInt, hexlify, isHexString, toQuantity, toUtf8Bytes,
|
||||||
makeError, throwArgumentError, throwError,
|
makeError, assertArgument, throwError,
|
||||||
FetchRequest, resolveProperties
|
FetchRequest, resolveProperties
|
||||||
} from "../utils/index.js";
|
} from "../utils/index.js";
|
||||||
|
|
||||||
@ -220,9 +220,8 @@ export class JsonRpcSigner extends AbstractSigner<JsonRpcApiProvider> {
|
|||||||
const _from = tx.from;
|
const _from = tx.from;
|
||||||
promises.push((async () => {
|
promises.push((async () => {
|
||||||
const from = await resolveAddress(_from, this.provider);
|
const from = await resolveAddress(_from, this.provider);
|
||||||
if (from == null || from.toLowerCase() !== this.address.toLowerCase()) {
|
assertArgument(from != null && from.toLowerCase() === this.address.toLowerCase(),
|
||||||
throwArgumentError("from address mismatch", "transaction", _tx);
|
"from address mismatch", "transaction", _tx);
|
||||||
}
|
|
||||||
tx.from = from;
|
tx.from = from;
|
||||||
})());
|
})());
|
||||||
} else {
|
} else {
|
||||||
@ -287,9 +286,8 @@ export class JsonRpcSigner extends AbstractSigner<JsonRpcApiProvider> {
|
|||||||
// Make sure the from matches the sender
|
// Make sure the from matches the sender
|
||||||
if (tx.from) {
|
if (tx.from) {
|
||||||
const from = await resolveAddress(tx.from, this.provider);
|
const from = await resolveAddress(tx.from, this.provider);
|
||||||
if (from == null || from.toLowerCase() !== this.address.toLowerCase()) {
|
assertArgument(from != null && from.toLowerCase() === this.address.toLowerCase(),
|
||||||
return throwArgumentError("from address mismatch", "transaction", _tx);
|
"from address mismatch", "transaction", _tx);
|
||||||
}
|
|
||||||
tx.from = from;
|
tx.from = from;
|
||||||
} else {
|
} else {
|
||||||
tx.from = this.address;
|
tx.from = this.address;
|
||||||
@ -312,9 +310,7 @@ export class JsonRpcSigner extends AbstractSigner<JsonRpcApiProvider> {
|
|||||||
// Populate any ENS names (in-place)
|
// Populate any ENS names (in-place)
|
||||||
const populated = await TypedDataEncoder.resolveNames(domain, types, value, async (value: string) => {
|
const populated = await TypedDataEncoder.resolveNames(domain, types, value, async (value: string) => {
|
||||||
const address = await resolveAddress(value);
|
const address = await resolveAddress(value);
|
||||||
if (address == null) {
|
assertArgument(address != null, "TypedData does not support null address", "value", value);
|
||||||
return throwArgumentError("TypedData does not support null address", "value", value);
|
|
||||||
}
|
|
||||||
return address;
|
return address;
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -462,9 +458,8 @@ export class JsonRpcApiProvider extends AbstractProvider {
|
|||||||
// This could be relaxed in the future to just check equivalent networks
|
// This could be relaxed in the future to just check equivalent networks
|
||||||
const staticNetwork = this._getOption("staticNetwork");
|
const staticNetwork = this._getOption("staticNetwork");
|
||||||
if (staticNetwork) {
|
if (staticNetwork) {
|
||||||
if (staticNetwork !== network) {
|
assertArgument(staticNetwork === network,
|
||||||
throwArgumentError("staticNetwork MUST match network object", "options", options);
|
"staticNetwork MUST match network object", "options", options);
|
||||||
}
|
|
||||||
this.#network = staticNetwork;
|
this.#network = staticNetwork;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3,7 +3,7 @@ import { getAddress } from "../address/index.js";
|
|||||||
import { keccak256, Signature } from "../crypto/index.js";
|
import { keccak256, Signature } from "../crypto/index.js";
|
||||||
import {
|
import {
|
||||||
concat, decodeRlp, encodeRlp, getBytes, getStore, getBigInt, getNumber, hexlify,
|
concat, decodeRlp, encodeRlp, getBytes, getStore, getBigInt, getNumber, hexlify,
|
||||||
setStore, throwArgumentError, toArray, zeroPadValue
|
setStore, assertArgument, toArray, zeroPadValue
|
||||||
} from "../utils/index.js";
|
} from "../utils/index.js";
|
||||||
|
|
||||||
import { accessListify } from "./accesslist.js";
|
import { accessListify } from "./accesslist.js";
|
||||||
@ -56,7 +56,7 @@ function handleData(value: string, param: string): string {
|
|||||||
try {
|
try {
|
||||||
return hexlify(value);
|
return hexlify(value);
|
||||||
} catch (error) {
|
} 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 {
|
try {
|
||||||
return accessListify(value);
|
return accessListify(value);
|
||||||
} catch (error) {
|
} 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 {
|
function handleUint(_value: string, param: string): bigint {
|
||||||
if (_value === "0x") { return BN_0; }
|
if (_value === "0x") { return BN_0; }
|
||||||
const value = getBigInt(_value, param);
|
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;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
function formatNumber(_value: BigNumberish, name: string): Uint8Array {
|
function formatNumber(_value: BigNumberish, name: string): Uint8Array {
|
||||||
const value = getBigInt(_value, "value");
|
const value = getBigInt(_value, "value");
|
||||||
const result = toArray(value);
|
const result = toArray(value);
|
||||||
if (result.length > 32) {
|
assertArgument(result.length <= 32, `value too large`, `tx.${ name }`, value);
|
||||||
throwArgumentError(`value too large`, `tx.${ name }`, value);
|
|
||||||
}
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -96,9 +94,8 @@ function formatAccessList(value: AccessListish): Array<[ string, Array<string> ]
|
|||||||
function _parseLegacy(data: Uint8Array): TransactionLike {
|
function _parseLegacy(data: Uint8Array): TransactionLike {
|
||||||
const fields: any = decodeRlp(data);
|
const fields: any = decodeRlp(data);
|
||||||
|
|
||||||
if (!Array.isArray(fields) || (fields.length !== 9 && fields.length !== 6)) {
|
assertArgument(Array.isArray(fields) && (fields.length === 9 || fields.length === 6),
|
||||||
return throwArgumentError("invalid field count for legacy transaction", "data", data);
|
"invalid field count for legacy transaction", "data", data);
|
||||||
}
|
|
||||||
|
|
||||||
const tx: TransactionLike = {
|
const tx: TransactionLike = {
|
||||||
type: 0,
|
type: 0,
|
||||||
@ -130,9 +127,7 @@ function _parseLegacy(data: Uint8Array): TransactionLike {
|
|||||||
tx.chainId = chainId
|
tx.chainId = chainId
|
||||||
|
|
||||||
// Signed Legacy Transaction
|
// Signed Legacy Transaction
|
||||||
if (chainId === BN_0 && (v < BN_27 || v > BN_28)) {
|
assertArgument(chainId !== BN_0 || (v === BN_27 || v === BN_28), "non-canonical legacy v", "v", fields[6]);
|
||||||
throwArgumentError("non-canonical legacy v", "v", fields[6]);
|
|
||||||
}
|
|
||||||
|
|
||||||
tx.signature = Signature.from({
|
tx.signature = Signature.from({
|
||||||
r: zeroPadValue(fields[7], 32),
|
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,
|
// We have a chainId in the tx and an EIP-155 v in the signature,
|
||||||
// make sure they agree with each other
|
// make sure they agree with each other
|
||||||
if (sig && sig.networkV != null && sig.legacyChainId !== chainId) {
|
assertArgument(!sig || sig.networkV == null || sig.legacyChainId === chainId,
|
||||||
throwArgumentError("tx.chainId/sig.v mismatch", "sig", sig);
|
"tx.chainId/sig.v mismatch", "sig", sig);
|
||||||
}
|
|
||||||
|
|
||||||
} else if (sig) {
|
} else if (sig) {
|
||||||
// No chainId provided, but the signature is signing with EIP-155; derive chainId
|
// 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) {
|
if (chainId !== BN_0) {
|
||||||
v = Signature.getChainIdV(chainId, sig.v);
|
v = Signature.getChainIdV(chainId, sig.v);
|
||||||
} else if (BigInt(sig.v) !== 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));
|
fields.push(toArray(v));
|
||||||
@ -206,7 +200,7 @@ function _parseEipSignature(tx: TransactionLike, fields: Array<string>, serializ
|
|||||||
yParity = handleNumber(fields[0], "yParity");
|
yParity = handleNumber(fields[0], "yParity");
|
||||||
if (yParity !== 0 && yParity !== 1) { throw new Error("bad yParity"); }
|
if (yParity !== 0 && yParity !== 1) { throw new Error("bad yParity"); }
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
return throwArgumentError("invalid yParity", "yParity", fields[0]);
|
assertArgument(false, "invalid yParity", "yParity", fields[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
const r = zeroPadValue(fields[1], 32);
|
const r = zeroPadValue(fields[1], 32);
|
||||||
@ -219,9 +213,8 @@ function _parseEipSignature(tx: TransactionLike, fields: Array<string>, serializ
|
|||||||
function _parseEip1559(data: Uint8Array): TransactionLike {
|
function _parseEip1559(data: Uint8Array): TransactionLike {
|
||||||
const fields: any = decodeRlp(getBytes(data).slice(1));
|
const fields: any = decodeRlp(getBytes(data).slice(1));
|
||||||
|
|
||||||
if (!Array.isArray(fields) || (fields.length !== 9 && fields.length !== 12)) {
|
assertArgument(Array.isArray(fields) && (fields.length === 9 || fields.length === 12),
|
||||||
throwArgumentError("invalid field count for transaction type: 2", "data", hexlify(data));
|
"invalid field count for transaction type: 2", "data", hexlify(data));
|
||||||
}
|
|
||||||
|
|
||||||
const maxPriorityFeePerGas = handleUint(fields[2], "maxPriorityFeePerGas");
|
const maxPriorityFeePerGas = handleUint(fields[2], "maxPriorityFeePerGas");
|
||||||
const maxFeePerGas = handleUint(fields[3], "maxFeePerGas");
|
const maxFeePerGas = handleUint(fields[3], "maxFeePerGas");
|
||||||
@ -274,9 +267,8 @@ function _serializeEip1559(tx: TransactionLike, sig?: Signature): string {
|
|||||||
function _parseEip2930(data: Uint8Array): TransactionLike {
|
function _parseEip2930(data: Uint8Array): TransactionLike {
|
||||||
const fields: any = decodeRlp(getBytes(data).slice(1));
|
const fields: any = decodeRlp(getBytes(data).slice(1));
|
||||||
|
|
||||||
if (!Array.isArray(fields) || (fields.length !== 8 && fields.length !== 11)) {
|
assertArgument(Array.isArray(fields) && (fields.length === 8 || fields.length === 11),
|
||||||
throwArgumentError("invalid field count for transaction type: 1", "data", hexlify(data));
|
"invalid field count for transaction type: 1", "data", hexlify(data));
|
||||||
}
|
|
||||||
|
|
||||||
const tx: TransactionLike = {
|
const tx: TransactionLike = {
|
||||||
type: 1,
|
type: 1,
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
|
|
||||||
import { getBytes } from "./data.js";
|
import { getBytes } from "./data.js";
|
||||||
import { throwArgumentError } from "./errors.js";
|
import { assertArgument } from "./errors.js";
|
||||||
import { toBigInt, toHex } from "./maths.js";
|
import { toBigInt, toHex } from "./maths.js";
|
||||||
|
|
||||||
import type { BytesLike } from "./index.js";
|
import type { BytesLike } from "./index.js";
|
||||||
@ -17,9 +17,7 @@ function getAlpha(letter: string): bigint {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
const result = Lookup[letter];
|
const result = Lookup[letter];
|
||||||
if (result == null) {
|
assertArgument(result != null, `invalid base58 value`, "letter", letter);
|
||||||
throwArgumentError(`invalid base58 value`, "letter", letter);
|
|
||||||
}
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import { throwArgumentError, throwError } from "./errors.js";
|
import { assertArgument, throwError } from "./errors.js";
|
||||||
|
|
||||||
|
|
||||||
export type BytesLike = string | Uint8Array;
|
export type BytesLike = string | Uint8Array;
|
||||||
@ -19,7 +19,7 @@ function _getBytes(value: BytesLike, name?: string, copy?: boolean): Uint8Array
|
|||||||
return result;
|
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);
|
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
|
* 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.
|
* any further code does not need additional compile-time checks.
|
||||||
*/
|
*/
|
||||||
export function assertArgument(check: unknown, message: string, name: string, value: unknown): asserts check {
|
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 {
|
export function assertArgumentCount(count: number, expectedCount: number, message: string = ""): void {
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import { decodeBase64, encodeBase64 } from "./base64.js";
|
import { decodeBase64, encodeBase64 } from "./base64.js";
|
||||||
import { hexlify } from "./data.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 { defineProperties } from "./properties.js";
|
||||||
import { toUtf8Bytes, toUtf8String } from "./utf8.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%%.
|
* Sets an ``Authorization`` for %%username%% with %%password%%.
|
||||||
*/
|
*/
|
||||||
setCredentials(username: string, password: string): void {
|
setCredentials(username: string, password: string): void {
|
||||||
if (username.match(/:/)) {
|
assertArgument(!username.match(/:/), "invalid basic authentication username", "username", "[REDACTED]");
|
||||||
throwArgumentError("invalid basic authentication username", "username", "[REDACTED]");
|
|
||||||
}
|
|
||||||
this.#creds = `${ username }:${ password }`;
|
this.#creds = `${ username }:${ password }`;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -762,8 +760,8 @@ export class FetchResponse implements Iterable<[ key: string, value: string ]> {
|
|||||||
throwThrottleError(message?: string, stall?: number): never {
|
throwThrottleError(message?: string, stall?: number): never {
|
||||||
if (stall == null) {
|
if (stall == null) {
|
||||||
stall = -1;
|
stall = -1;
|
||||||
} else if (typeof(stall) !== "number" || !Number.isInteger(stall) || stall < 0) {
|
} else {
|
||||||
return throwArgumentError("invalid stall timeout", "stall", stall);
|
assertArgument(Number.isInteger(stall) && stall >= 0, "invalid stall timeout", "stall", stall);
|
||||||
}
|
}
|
||||||
|
|
||||||
const error = new Error(message || "throttling requests");
|
const error = new Error(message || "throttling requests");
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import { getBytes } from "./data.js";
|
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 { getBigInt, getNumber, fromTwos, toBigInt, toHex, toTwos } from "./maths.js";
|
||||||
|
|
||||||
import type { BigNumberish, BytesLike, Numeric } from "./index.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
|
// Returns a string "1" followed by decimal "0"s
|
||||||
function getMultiplier(decimals: number): bigint {
|
function getMultiplier(decimals: number): bigint {
|
||||||
|
|
||||||
if (typeof(decimals) !== "number" || decimals < 0 || decimals > 256 || decimals % 1 ) {
|
assertArgument(Number.isInteger(decimals) && decimals >= 0 && decimals <= 256,
|
||||||
throwArgumentError("invalid decimal length", "decimals", decimals);
|
"invalid decimal length", "decimals", decimals);
|
||||||
}
|
|
||||||
|
|
||||||
return BigInt("1" + zeros.substring(0, decimals));
|
return BigInt("1" + zeros.substring(0, decimals));
|
||||||
}
|
}
|
||||||
@ -65,23 +64,18 @@ export function parseFixed(value: string, _decimals: Numeric): bigint {
|
|||||||
|
|
||||||
const multiplier = getMultiplier(decimals);
|
const multiplier = getMultiplier(decimals);
|
||||||
|
|
||||||
if (typeof(value) !== "string" || !value.match(/^-?[0-9.]+$/)) {
|
assertArgument(typeof(value) === "string" && value.match(/^-?[0-9.]+$/),
|
||||||
throwArgumentError("invalid decimal value", "value", value);
|
"invalid decimal value", "value", value);
|
||||||
}
|
|
||||||
|
|
||||||
// Is it negative?
|
// Is it negative?
|
||||||
const negative = (value.substring(0, 1) === "-");
|
const negative = (value.substring(0, 1) === "-");
|
||||||
if (negative) { value = value.substring(1); }
|
if (negative) { value = value.substring(1); }
|
||||||
|
|
||||||
if (value === ".") {
|
assertArgument(value !== ".", "missing value", "value", value);
|
||||||
throwArgumentError("missing value", "value", value);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Split it into a whole and fractional part
|
// Split it into a whole and fractional part
|
||||||
const comps = value.split(".");
|
const comps = value.split(".");
|
||||||
if (comps.length > 2) {
|
assertArgument(comps.length <= 2, "too many decimal points", "value", value);
|
||||||
throwArgumentError("too many decimal points", "value", value);
|
|
||||||
}
|
|
||||||
|
|
||||||
let whole = (comps[0] || "0"), fraction = (comps[1] || "0");
|
let whole = (comps[0] || "0"), fraction = (comps[1] || "0");
|
||||||
|
|
||||||
@ -155,9 +149,7 @@ export class FixedFormat {
|
|||||||
signed = false;
|
signed = false;
|
||||||
} else {
|
} else {
|
||||||
const match = value.match(/^(u?)fixed([0-9]+)x([0-9]+)$/);
|
const match = value.match(/^(u?)fixed([0-9]+)x([0-9]+)$/);
|
||||||
if (!match) {
|
assertArgument(match, "invalid fixed format", "format", value);
|
||||||
return throwArgumentError("invalid fixed format", "format", value);
|
|
||||||
}
|
|
||||||
signed = (match[1] !== "u");
|
signed = (match[1] !== "u");
|
||||||
width = parseInt(match[2]);
|
width = parseInt(match[2]);
|
||||||
decimals = parseInt(match[3]);
|
decimals = parseInt(match[3]);
|
||||||
@ -165,9 +157,8 @@ export class FixedFormat {
|
|||||||
} else if (value) {
|
} else if (value) {
|
||||||
const check = (key: string, type: string, defaultValue: any): any => {
|
const check = (key: string, type: string, defaultValue: any): any => {
|
||||||
if (value[key] == null) { return defaultValue; }
|
if (value[key] == null) { return defaultValue; }
|
||||||
if (typeof(value[key]) !== type) {
|
assertArgument(typeof(value[key]) === type,
|
||||||
throwArgumentError("invalid fixed format (" + key + " not " + type +")", "format." + key, value[key]);
|
"invalid fixed format (" + key + " not " + type +")", "format." + key, value[key]);
|
||||||
}
|
|
||||||
return value[key];
|
return value[key];
|
||||||
}
|
}
|
||||||
signed = check("signed", "boolean", signed);
|
signed = check("signed", "boolean", signed);
|
||||||
@ -175,13 +166,8 @@ export class FixedFormat {
|
|||||||
decimals = check("decimals", "number", decimals);
|
decimals = check("decimals", "number", decimals);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (width % 8) {
|
assertArgument((width % 8) === 0, "invalid fixed format width (not byte aligned)", "format.width", width);
|
||||||
throwArgumentError("invalid fixed format width (not byte aligned)", "format.width", width);
|
assertArgument(decimals <= 80, "invalid fixed format (decimals too large)", "format.decimals", decimals);
|
||||||
}
|
|
||||||
|
|
||||||
if (decimals > 80) {
|
|
||||||
throwArgumentError("invalid fixed format (decimals too large)", "format.decimals", decimals);
|
|
||||||
}
|
|
||||||
|
|
||||||
return new FixedFormat(_constructorGuard, signed, width, decimals);
|
return new FixedFormat(_constructorGuard, signed, width, decimals);
|
||||||
}
|
}
|
||||||
@ -215,9 +201,8 @@ export class FixedNumber {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#checkFormat(other: FixedNumber): void {
|
#checkFormat(other: FixedNumber): void {
|
||||||
if (this.format.name !== other.format.name) {
|
assertArgument(this.format.name === other.format.name,
|
||||||
throwArgumentError("incompatible format; use fixedNumber.toFormat", "other", other);
|
"incompatible format; use fixedNumber.toFormat", "other", other);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -288,9 +273,8 @@ export class FixedNumber {
|
|||||||
const comps = this.toString().split(".");
|
const comps = this.toString().split(".");
|
||||||
if (comps.length === 1) { comps.push("0"); }
|
if (comps.length === 1) { comps.push("0"); }
|
||||||
|
|
||||||
if (decimals < 0 || decimals > 80 || (decimals % 1)) {
|
assertArgument(Number.isInteger(decimals) && decimals >= 0 && decimals <= 80,
|
||||||
throwArgumentError("invalid decimal count", "decimals", decimals);
|
"invalid decimal count", "decimals", decimals);
|
||||||
}
|
|
||||||
|
|
||||||
if (comps[1].length <= decimals) { return this; }
|
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 {
|
static isFixedNumber(value: any): value is FixedNumber {
|
||||||
|
@ -25,7 +25,7 @@ export {
|
|||||||
|
|
||||||
export {
|
export {
|
||||||
isCallException, isError,
|
isCallException, isError,
|
||||||
makeError, throwError, throwArgumentError,
|
makeError, throwError,
|
||||||
assertArgument, assertArgumentCount, assertPrivate, assertNormalize
|
assertArgument, assertArgumentCount, assertPrivate, assertNormalize
|
||||||
} from "./errors.js"
|
} from "./errors.js"
|
||||||
|
|
||||||
@ -53,7 +53,6 @@ export { getStore, setStore} from "./storage.js";
|
|||||||
export { formatEther, parseEther, formatUnits, parseUnits } from "./units.js";
|
export { formatEther, parseEther, formatUnits, parseUnits } from "./units.js";
|
||||||
|
|
||||||
export {
|
export {
|
||||||
_toEscapedUtf8String,
|
|
||||||
toUtf8Bytes,
|
toUtf8Bytes,
|
||||||
toUtf8CodePoints,
|
toUtf8CodePoints,
|
||||||
toUtf8String,
|
toUtf8String,
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import { hexlify, isBytesLike } from "./data.js";
|
import { hexlify, isBytesLike } from "./data.js";
|
||||||
import { throwArgumentError } from "./errors.js";
|
import { assertArgument } from "./errors.js";
|
||||||
|
|
||||||
import type { BytesLike } from "./data.js";
|
import type { BytesLike } from "./data.js";
|
||||||
|
|
||||||
@ -68,11 +68,8 @@ export function getBigInt(value: BigNumberish, name?: string): bigint {
|
|||||||
switch (typeof(value)) {
|
switch (typeof(value)) {
|
||||||
case "bigint": return value;
|
case "bigint": return value;
|
||||||
case "number":
|
case "number":
|
||||||
if (!Number.isInteger(value)) {
|
assertArgument(Number.isInteger(value), "underflow", name || "value", value);
|
||||||
throwArgumentError("underflow", name || "value", value);
|
assertArgument(value >= -maxValue && value <= maxValue, "overflow", name || "value", value);
|
||||||
} else if (value < -maxValue || value > maxValue) {
|
|
||||||
throwArgumentError("overflow", name || "value", value);
|
|
||||||
}
|
|
||||||
return BigInt(value);
|
return BigInt(value);
|
||||||
case "string":
|
case "string":
|
||||||
try {
|
try {
|
||||||
@ -81,10 +78,10 @@ export function getBigInt(value: BigNumberish, name?: string): bigint {
|
|||||||
}
|
}
|
||||||
return BigInt(value);
|
return BigInt(value);
|
||||||
} catch(e: any) {
|
} 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 {
|
export function getNumber(value: BigNumberish, name?: string): number {
|
||||||
switch (typeof(value)) {
|
switch (typeof(value)) {
|
||||||
case "bigint":
|
case "bigint":
|
||||||
if (value < -maxValue || value > maxValue) {
|
assertArgument(value >= -maxValue && value <= maxValue, "overflow", name || "value", value);
|
||||||
throwArgumentError("overflow", name || "value", value);
|
|
||||||
}
|
|
||||||
return Number(value);
|
return Number(value);
|
||||||
case "number":
|
case "number":
|
||||||
if (!Number.isInteger(value)) {
|
assertArgument(Number.isInteger(value), "underflow", name || "value", value);
|
||||||
throwArgumentError("underflow", name || "value", value);
|
assertArgument(value >= -maxValue && value <= maxValue, "overflow", name || "value", value);
|
||||||
} else if (value < -maxValue || value > maxValue) {
|
|
||||||
throwArgumentError("overflow", name || "value", value);
|
|
||||||
}
|
|
||||||
return value;
|
return value;
|
||||||
case "string":
|
case "string":
|
||||||
try {
|
try {
|
||||||
return getNumber(BigInt(value), name);
|
return getNumber(BigInt(value), name);
|
||||||
} catch(e: any) {
|
} 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
|
//See: https://github.com/ethereum/wiki/wiki/RLP
|
||||||
|
|
||||||
import { hexlify } from "./data.js";
|
import { hexlify } from "./data.js";
|
||||||
import { throwArgumentError, throwError } from "./errors.js";
|
import { assertArgument, throwError } from "./errors.js";
|
||||||
import { getBytes } from "./data.js";
|
import { getBytes } from "./data.js";
|
||||||
|
|
||||||
import type { BytesLike, RlpStructuredData } from "./index.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 {
|
export function decodeRlp(_data: BytesLike): RlpStructuredData {
|
||||||
const data = getBytes(_data, "data");
|
const data = getBytes(_data, "data");
|
||||||
const decoded = _decode(data, 0);
|
const decoded = _decode(data, 0);
|
||||||
if (decoded.consumed !== data.length) {
|
assertArgument(decoded.consumed === data.length, "unexpected junk after rlp payload", "data", _data);
|
||||||
throwArgumentError("unexpected junk after rlp payload", "data", _data);
|
|
||||||
}
|
|
||||||
return decoded.result;
|
return decoded.result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import { formatFixed, parseFixed } from "./fixednumber.js";
|
import { formatFixed, parseFixed } from "./fixednumber.js";
|
||||||
import { throwArgumentError } from "./errors.js";
|
import { assertArgument } from "./errors.js";
|
||||||
|
|
||||||
import type { BigNumberish, Numeric } from "../utils/index.js";
|
import type { BigNumberish, Numeric } from "../utils/index.js";
|
||||||
|
|
||||||
@ -23,7 +23,7 @@ const names = [
|
|||||||
export function formatUnits(value: BigNumberish, unit?: string | Numeric): string {
|
export function formatUnits(value: BigNumberish, unit?: string | Numeric): string {
|
||||||
if (typeof(unit) === "string") {
|
if (typeof(unit) === "string") {
|
||||||
const index = names.indexOf(unit);
|
const index = names.indexOf(unit);
|
||||||
if (index === -1) { throwArgumentError("invalid unit", "unit", unit); }
|
assertArgument(index >= 0, "invalid unit", "unit", unit);
|
||||||
unit = 3 * index;
|
unit = 3 * index;
|
||||||
}
|
}
|
||||||
return formatFixed(value, (unit != null) ? unit: 18);
|
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).
|
* or the name of a unit (e.g. ``"gwei"`` for 9 decimal places).
|
||||||
*/
|
*/
|
||||||
export function parseUnits(value: string, unit?: string | Numeric): bigint {
|
export function parseUnits(value: string, unit?: string | Numeric): bigint {
|
||||||
if (typeof(value) !== "string") {
|
assertArgument(typeof(value) === "string", "value must be a string", "value", value);
|
||||||
throwArgumentError("value must be a string", "value", value);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (typeof(unit) === "string") {
|
if (typeof(unit) === "string") {
|
||||||
const index = names.indexOf(unit);
|
const index = names.indexOf(unit);
|
||||||
if (index === -1) { throwArgumentError("invalid unit", "unit", unit); }
|
assertArgument(index >= 0, "invalid unit", "unit", unit);
|
||||||
unit = 3 * index;
|
unit = 3 * index;
|
||||||
}
|
}
|
||||||
|
|
||||||
return parseFixed(value, (unit != null) ? unit: 18);
|
return parseFixed(value, (unit != null) ? unit: 18);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import { getBytes } from "./data.js";
|
import { getBytes } from "./data.js";
|
||||||
import { assertNormalize, throwArgumentError } from "./errors.js";
|
import { assertArgument, assertNormalize } from "./errors.js";
|
||||||
|
|
||||||
import type { BytesLike } from "./index.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;
|
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 {
|
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 {
|
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++;
|
i++;
|
||||||
const c2 = str.charCodeAt(i);
|
const c2 = str.charCodeAt(i);
|
||||||
|
|
||||||
if (i >= str.length || (c2 & 0xfc00) !== 0xdc00) {
|
assertArgument(i < str.length && ((c2 & 0xfc00) === 0xdc00),
|
||||||
throw new Error("invalid utf-8 string");
|
"invalid surrogate pair", "str", str);
|
||||||
}
|
|
||||||
|
|
||||||
// Surrogate Pair
|
// Surrogate Pair
|
||||||
const pair = 0x10000 + ((c & 0x03ff) << 10) + (c2 & 0x03ff);
|
const pair = 0x10000 + ((c & 0x03ff) << 10) + (c2 & 0x03ff);
|
||||||
@ -236,37 +233,6 @@ export function toUtf8Bytes(str: string, form?: UnicodeNormalizationForm): Uint8
|
|||||||
return new Uint8Array(result);
|
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 {
|
export function _toUtf8String(codePoints: Array<number>): string {
|
||||||
return codePoints.map((codePoint) => {
|
return codePoints.map((codePoint) => {
|
||||||
if (codePoint <= 0xffff) {
|
if (codePoint <= 0xffff) {
|
||||||
|
@ -3,7 +3,7 @@ import { hashMessage, TypedDataEncoder } from "../hash/index.js";
|
|||||||
import { AbstractSigner } from "../providers/index.js";
|
import { AbstractSigner } from "../providers/index.js";
|
||||||
import { computeAddress, Transaction } from "../transaction/index.js";
|
import { computeAddress, Transaction } from "../transaction/index.js";
|
||||||
import {
|
import {
|
||||||
defineProperties, resolveProperties, throwArgumentError, throwError
|
defineProperties, resolveProperties, assertArgument, throwError
|
||||||
} from "../utils/index.js";
|
} from "../utils/index.js";
|
||||||
|
|
||||||
import type { SigningKey } from "../crypto/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 (from != null) { tx.from = from; }
|
||||||
|
|
||||||
if (tx.from != null) {
|
if (tx.from != null) {
|
||||||
if (getAddress(<string>(tx.from)) !== this.address) {
|
assertArgument(getAddress(<string>(tx.from)) === this.address,
|
||||||
throwArgumentError("transaction from address mismatch", "tx.from", tx.from);
|
"transaction from address mismatch", "tx.from", tx.from);
|
||||||
}
|
|
||||||
delete tx.from;
|
delete tx.from;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5,7 +5,7 @@ import {
|
|||||||
concat, dataSlice, decodeBase58, defineProperties, encodeBase58,
|
concat, dataSlice, decodeBase58, defineProperties, encodeBase58,
|
||||||
getBytes, hexlify,
|
getBytes, hexlify,
|
||||||
getNumber, toBigInt, toHex,
|
getNumber, toBigInt, toHex,
|
||||||
assertPrivate, throwArgumentError, throwError
|
assertPrivate, assertArgument, throwError
|
||||||
} from "../utils/index.js";
|
} from "../utils/index.js";
|
||||||
import { langEn } from "../wordlists/lang-en.js";
|
import { langEn } from "../wordlists/lang-en.js";
|
||||||
|
|
||||||
@ -216,9 +216,8 @@ export class HDNodeWallet extends BaseWallet {
|
|||||||
static fromExtendedKey(extendedKey: string): HDNodeWallet | HDNodeVoidWallet {
|
static fromExtendedKey(extendedKey: string): HDNodeWallet | HDNodeVoidWallet {
|
||||||
const bytes = getBytes(decodeBase58(extendedKey)); // @TODO: redact
|
const bytes = getBytes(decodeBase58(extendedKey)); // @TODO: redact
|
||||||
|
|
||||||
if (bytes.length !== 82 || encodeBase58Check(bytes.slice(0, 78)) !== extendedKey) {
|
assertArgument(bytes.length === 82 || encodeBase58Check(bytes.slice(0, 78)) === extendedKey,
|
||||||
throwArgumentError("invalid extended key", "extendedKey", "[ REDACTED ]");
|
"invalid extended key", "extendedKey", "[ REDACTED ]");
|
||||||
}
|
|
||||||
|
|
||||||
const depth = bytes[4];
|
const depth = bytes[4];
|
||||||
const parentFingerprint = hexlify(bytes.slice(5, 9));
|
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 {
|
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 {
|
export function getAccountPath(_index: Numeric): string {
|
||||||
const index = getNumber(_index, "index");
|
const index = getNumber(_index, "index");
|
||||||
if (index < 0 || index >= HardenedBit) {
|
assertArgument(index >= 0 && index < HardenedBit, "invalid account index", "index", index);
|
||||||
throwArgumentError("invalid account index", "index", index);
|
|
||||||
}
|
|
||||||
return `m/44'/60'/${ index }'/0/0`;
|
return `m/44'/60'/${ index }'/0/0`;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3,7 +3,7 @@ import { CBC, pkcs7Strip } from "aes-js";
|
|||||||
import { getAddress } from "../address/index.js";
|
import { getAddress } from "../address/index.js";
|
||||||
import { pbkdf2 } from "../crypto/index.js";
|
import { pbkdf2 } from "../crypto/index.js";
|
||||||
import { id } from "../hash/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";
|
import { getPassword, looseArrayify, spelunk } from "./utils.js";
|
||||||
|
|
||||||
@ -31,9 +31,7 @@ export function decryptCrowdsaleJson(json: string, _password: string | Uint8Arra
|
|||||||
|
|
||||||
// Encrypted Seed
|
// Encrypted Seed
|
||||||
const encseed = looseArrayify(spelunk(data, "encseed:string!"));
|
const encseed = looseArrayify(spelunk(data, "encseed:string!"));
|
||||||
if (!encseed || (encseed.length % 16) !== 0) {
|
assertArgument(encseed && (encseed.length % 16) === 0, "invalid encseed", "json", json);
|
||||||
throwArgumentError("invalid encseed", "json", json);
|
|
||||||
}
|
|
||||||
|
|
||||||
const key = getBytes(pbkdf2(password, password, 2000, 32, "sha256")).slice(0, 16);
|
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 { keccak256, pbkdf2, randomBytes, scrypt, scryptSync } from "../crypto/index.js";
|
||||||
import { computeAddress } from "../transaction/index.js";
|
import { computeAddress } from "../transaction/index.js";
|
||||||
import {
|
import {
|
||||||
concat, getBytes, hexlify, throwArgumentError, throwError
|
concat, getBytes, hexlify, assertArgument, throwError
|
||||||
} from "../utils/index.js";
|
} from "../utils/index.js";
|
||||||
|
|
||||||
import { getPassword, spelunk, uuidV4, zpad } from "./utils.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 ciphertext = spelunk<Uint8Array>(data, "crypto.ciphertext:data!");
|
||||||
|
|
||||||
const computedMAC = hexlify(keccak256(concat([ key.slice(16, 32), ciphertext ]))).substring(2);
|
const computedMAC = hexlify(keccak256(concat([ key.slice(16, 32), ciphertext ]))).substring(2);
|
||||||
if (computedMAC !== spelunk(data, "crypto.mac:string!").toLowerCase()) {
|
assertArgument(computedMAC === spelunk(data, "crypto.mac:string!").toLowerCase(),
|
||||||
return throwArgumentError("incorrect password", "password", "[ REDACTED ]");
|
"incorrect password", "password", "[ REDACTED ]");
|
||||||
}
|
|
||||||
|
|
||||||
const privateKey = decrypt(data, key.slice(0, 16), ciphertext);
|
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();
|
let check = data.address.toLowerCase();
|
||||||
if (check.substring(0, 2) !== "0x") { check = "0x" + check; }
|
if (check.substring(0, 2) !== "0x") { check = "0x" + check; }
|
||||||
|
|
||||||
if (getAddress(check) !== address) {
|
assertArgument(getAddress(check) === address, "keystore address/privateKey mismatch", "address", data.address);
|
||||||
throwArgumentError("keystore address/privateKey mismatch", "address", data.address);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const account: KeystoreAccount = { address, privateKey };
|
const account: KeystoreAccount = { address, privateKey };
|
||||||
@ -134,7 +131,7 @@ function getKdfParams<T>(data: any): KdfParams {
|
|||||||
const kdf = spelunk(data, "crypto.kdf:string");
|
const kdf = spelunk(data, "crypto.kdf:string");
|
||||||
if (kdf && typeof(kdf) === "string") {
|
if (kdf && typeof(kdf) === "string") {
|
||||||
const throwError = function(name: string, value: any): never {
|
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") {
|
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
|
// Override initialization vector
|
||||||
const iv = (options.iv != null) ? getBytes(options.iv, "options.iv"): randomBytes(16);
|
const iv = (options.iv != null) ? getBytes(options.iv, "options.iv"): randomBytes(16);
|
||||||
if (iv.length !== 16) {
|
assertArgument(iv.length === 16, "invalid options.iv", "options.iv", options.iv);
|
||||||
throwArgumentError("invalid options.iv", "options.iv", options.iv);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Override the uuid
|
// Override the uuid
|
||||||
const uuidRandom = (options.uuid != null) ? getBytes(options.uuid, "options.uuid"): randomBytes(16);
|
const uuidRandom = (options.uuid != null) ? getBytes(options.uuid, "options.uuid"): randomBytes(16);
|
||||||
if (uuidRandom.length !== 16) {
|
assertArgument(uuidRandom.length === 16, "invalid options.uuid", "options.uuid", options.iv);
|
||||||
throwArgumentError("invalid options.uuid", "options.uuid", options.iv);
|
|
||||||
}
|
|
||||||
if (uuidRandom.length !== 16) { throw new Error("invalid uuid"); }
|
if (uuidRandom.length !== 16) { throw new Error("invalid uuid"); }
|
||||||
|
|
||||||
// Override the scrypt password-based key derivation function parameters
|
// Override the scrypt password-based key derivation function parameters
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import { pbkdf2, sha256 } from "../crypto/index.js";
|
import { pbkdf2, sha256 } from "../crypto/index.js";
|
||||||
import {
|
import {
|
||||||
defineProperties, getBytes, hexlify, assertNormalize, assertPrivate, throwArgumentError, toUtf8Bytes
|
defineProperties, getBytes, hexlify, assertNormalize, assertPrivate, assertArgument, toUtf8Bytes
|
||||||
} from "../utils/index.js";
|
} from "../utils/index.js";
|
||||||
import { langEn } from "../wordlists/lang-en.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; }
|
if (wordlist == null) { wordlist = langEn; }
|
||||||
|
|
||||||
const words = wordlist.split(mnemonic);
|
const words = wordlist.split(mnemonic);
|
||||||
if ((words.length % 3) !== 0 || words.length < 12 || words.length > 24) {
|
assertArgument((words.length % 3) === 0 && words.length >= 12 && words.length <= 24,
|
||||||
throwArgumentError("invalid mnemonic length", "mnemonic", "[ REDACTED ]");
|
"invalid mnemonic length", "mnemonic", "[ REDACTED ]");
|
||||||
}
|
|
||||||
|
|
||||||
const entropy = new Uint8Array(Math.ceil(11 * words.length / 8));
|
const entropy = new Uint8Array(Math.ceil(11 * words.length / 8));
|
||||||
|
|
||||||
let offset = 0;
|
let offset = 0;
|
||||||
for (let i = 0; i < words.length; i++) {
|
for (let i = 0; i < words.length; i++) {
|
||||||
let index = wordlist.getWordIndex(words[i].normalize("NFKD"));
|
let index = wordlist.getWordIndex(words[i].normalize("NFKD"));
|
||||||
if (index === -1) {
|
assertArgument(index >= 0, `invalid mnemonic word at index ${ i }`, "mnemonic", "[ REDACTED ]");
|
||||||
throwArgumentError(`invalid mnemonic word at index ${ i }`, "mnemonic", "[ REDACTED ]");
|
|
||||||
}
|
|
||||||
|
|
||||||
for (let bit = 0; bit < 11; bit++) {
|
for (let bit = 0; bit < 11; bit++) {
|
||||||
if (index & (1 << (10 - 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;
|
const checksum = getBytes(sha256(entropy.slice(0, entropyBits / 8)))[0] & checksumMask;
|
||||||
|
|
||||||
if (checksum !== (entropy[entropy.length - 1] & checksumMask)) {
|
assertArgument(checksum === (entropy[entropy.length - 1] & checksumMask),
|
||||||
throwArgumentError("invalid mnemonic checksum", "mnemonic", "[ REDACTED ]");
|
"invalid mnemonic checksum", "mnemonic", "[ REDACTED ]");
|
||||||
}
|
|
||||||
|
|
||||||
return hexlify(entropy.slice(0, entropyBits / 8));
|
return hexlify(entropy.slice(0, entropyBits / 8));
|
||||||
}
|
}
|
||||||
|
|
||||||
function entropyToMnemonic(entropy: Uint8Array, wordlist: null | Wordlist = langEn): string {
|
function entropyToMnemonic(entropy: Uint8Array, wordlist: null | Wordlist = langEn): string {
|
||||||
if ((entropy.length % 4) || entropy.length < 16 || entropy.length > 32) {
|
assertArgument((entropy.length % 4) === 0 && entropy.length >= 16 && entropy.length <= 32,
|
||||||
throwArgumentError("invalid entropy size", "entropy", "[ REDACTED ]");
|
"invalid entropy size", "entropy", "[ REDACTED ]");
|
||||||
}
|
|
||||||
|
|
||||||
if (wordlist == null) { wordlist = langEn; }
|
if (wordlist == null) { wordlist = langEn; }
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import {
|
import {
|
||||||
getBytes, getBytesCopy, hexlify, throwArgumentError, toUtf8Bytes
|
getBytes, getBytesCopy, hexlify, assertArgument, toUtf8Bytes
|
||||||
} from "../utils/index.js";
|
} from "../utils/index.js";
|
||||||
|
|
||||||
import type { BytesLike } 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 {
|
export function spelunk<T = string>(object: any, _path: string): T {
|
||||||
|
|
||||||
const match = _path.match(/^([a-z0-9$_.-]*)(:([a-z]+))?(!)?$/i);
|
const match = _path.match(/^([a-z0-9$_.-]*)(:([a-z]+))?(!)?$/i);
|
||||||
if (match == null) {
|
assertArgument(match != null, "invalid path", "path", _path);
|
||||||
return throwArgumentError("invalid path", "path", _path);
|
|
||||||
}
|
|
||||||
const path = match[1];
|
const path = match[1];
|
||||||
const type = match[3];
|
const type = match[3];
|
||||||
const reqd = (match[4] === "!");
|
const reqd = (match[4] === "!");
|
||||||
@ -60,9 +59,7 @@ export function spelunk<T = string>(object: any, _path: string): T {
|
|||||||
if (cur == null) { break; }
|
if (cur == null) { break; }
|
||||||
}
|
}
|
||||||
|
|
||||||
if (reqd && cur == null) {
|
assertArgument(!reqd || cur != null, "missing required value", "path", path);
|
||||||
throwArgumentError("missing required value", "path", path);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (type && cur != null) {
|
if (type && cur != null) {
|
||||||
if (type === "int") {
|
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 === "array" && Array.isArray(cur)) { return <T><unknown>cur; }
|
||||||
if (type === typeof(cur)) { return 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;
|
return cur;
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import { randomBytes, SigningKey } from "../crypto/index.js";
|
import { randomBytes, SigningKey } from "../crypto/index.js";
|
||||||
import { computeAddress } from "../transaction/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 { BaseWallet } from "./base-wallet.js";
|
||||||
import { HDNodeWallet } from "./hdwallet.js";
|
import { HDNodeWallet } from "./hdwallet.js";
|
||||||
@ -89,9 +89,7 @@ export class Wallet extends BaseWallet {
|
|||||||
// A signing key
|
// A signing key
|
||||||
if (signingKey == null) { signingKey = trySigningKey(key); }
|
if (signingKey == null) { signingKey = trySigningKey(key); }
|
||||||
|
|
||||||
if (signingKey == null) {
|
assertArgument(signingKey != null, "invalid key", "key", "[ REDACTED ]");
|
||||||
throwArgumentError("invalid key", "key", "[ REDACTED ]");
|
|
||||||
}
|
|
||||||
|
|
||||||
super(signingKey as SigningKey, provider);
|
super(signingKey as SigningKey, provider);
|
||||||
this.#mnemonic = mnemonic;
|
this.#mnemonic = mnemonic;
|
||||||
@ -123,13 +121,12 @@ export class Wallet extends BaseWallet {
|
|||||||
if (progress) { progress(1); await stall(0); }
|
if (progress) { progress(1); await stall(0); }
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
return throwArgumentError("invalid JSON wallet", "json", "[ REDACTED ]");
|
assertArgument(false, "invalid JSON wallet", "json", "[ REDACTED ]");
|
||||||
}
|
}
|
||||||
|
|
||||||
const wallet = new Wallet(account.privateKey);
|
const wallet = new Wallet(account.privateKey);
|
||||||
if (wallet.address !== account.address) {
|
assertArgument(wallet.address === account.address,
|
||||||
throwArgumentError("address/privateKey mismatch", "json", "[ REDACTED ]");
|
"address/privateKey mismatch", "json", "[ REDACTED ]");
|
||||||
}
|
|
||||||
// @TODO: mnemonic
|
// @TODO: mnemonic
|
||||||
return wallet;
|
return wallet;
|
||||||
}
|
}
|
||||||
@ -141,13 +138,12 @@ export class Wallet extends BaseWallet {
|
|||||||
} else if (isCrowdsaleJson(json)) {
|
} else if (isCrowdsaleJson(json)) {
|
||||||
account = decryptCrowdsaleJson(json, password);
|
account = decryptCrowdsaleJson(json, password);
|
||||||
} else {
|
} else {
|
||||||
return throwArgumentError("invalid JSON wallet", "json", "[ REDACTED ]");
|
assertArgument(false, "invalid JSON wallet", "json", "[ REDACTED ]");
|
||||||
}
|
}
|
||||||
|
|
||||||
const wallet = new Wallet(account.privateKey);
|
const wallet = new Wallet(account.privateKey);
|
||||||
if (wallet.address !== account.address) {
|
assertArgument(wallet.address === account.address,
|
||||||
throwArgumentError("address/privateKey mismatch", "json", "[ REDACTED ]");
|
"address/privateKey mismatch", "json", "[ REDACTED ]");
|
||||||
}
|
|
||||||
// @TODO: mnemonic
|
// @TODO: mnemonic
|
||||||
return wallet;
|
return wallet;
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import { id } from "../hash/index.js";
|
import { id } from "../hash/index.js";
|
||||||
import {
|
import {
|
||||||
hexlify, throwArgumentError, toUtf8Bytes, toUtf8String
|
hexlify, assertArgument, toUtf8Bytes, toUtf8String
|
||||||
} from "../utils/index.js";
|
} from "../utils/index.js";
|
||||||
|
|
||||||
import { Wordlist } from "./wordlist.js";
|
import { Wordlist } from "./wordlist.js";
|
||||||
@ -136,9 +136,8 @@ class LangJa extends Wordlist {
|
|||||||
|
|
||||||
getWord(index: number): string {
|
getWord(index: number): string {
|
||||||
const words = loadWords();
|
const words = loadWords();
|
||||||
if (index < 0 || index >= words.length) {
|
assertArgument(index >= 0 && index < words.length,
|
||||||
throwArgumentError(`invalid word index: ${ index }`, "index", index);
|
`invalid word index: ${ index }`, "index", index);
|
||||||
}
|
|
||||||
return words[index];
|
return words[index];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import { id } from "../hash/index.js";
|
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";
|
import { Wordlist } from "./wordlist.js";
|
||||||
|
|
||||||
@ -69,9 +69,8 @@ class LangKo extends Wordlist {
|
|||||||
|
|
||||||
getWord(index: number): string {
|
getWord(index: number): string {
|
||||||
const words = loadWords();
|
const words = loadWords();
|
||||||
if (index < 0 || index >= words.length) {
|
assertArgument(index >= 0 && index < words.length,
|
||||||
throwArgumentError(`invalid word index: ${ index }`, "index", index);
|
`invalid word index: ${ index }`, "index", index);
|
||||||
}
|
|
||||||
return words[index];
|
return words[index];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import { id } from "../hash/index.js";
|
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";
|
import { Wordlist } from "./wordlist.js";
|
||||||
|
|
||||||
@ -63,9 +63,8 @@ class LangZh extends Wordlist {
|
|||||||
|
|
||||||
getWord(index: number): string {
|
getWord(index: number): string {
|
||||||
const words = loadWords(this.locale);
|
const words = loadWords(this.locale);
|
||||||
if (index < 0 || index >= words.length) {
|
assertArgument(index >= 0 && index < words.length,
|
||||||
throwArgumentError(`invalid word index: ${ index }`, "index", index);
|
`invalid word index: ${ index }`, "index", index);
|
||||||
}
|
|
||||||
return words[index];
|
return words[index];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
// data files to be consumed by this class
|
// data files to be consumed by this class
|
||||||
|
|
||||||
import { id } from "../hash/index.js";
|
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 { decodeOwl } from "./decode-owl.js";
|
||||||
import { Wordlist } from "./wordlist.js";
|
import { Wordlist } from "./wordlist.js";
|
||||||
@ -45,9 +45,7 @@ export class WordlistOwl extends Wordlist {
|
|||||||
|
|
||||||
getWord(index: number): string {
|
getWord(index: number): string {
|
||||||
const words = this.#loadWords();
|
const words = this.#loadWords();
|
||||||
if (index < 0 || index >= words.length) {
|
assertArgument(index >= 0 && index < words.length, `invalid word index: ${ index }`, "index", index);
|
||||||
throwArgumentError(`invalid word index: ${ index }`, "index", index);
|
|
||||||
}
|
|
||||||
return words[index];
|
return words[index];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user