Moved away from isNamedInstance which breaks after Browserify name mangling.
This commit is contained in:
parent
e6f6383346
commit
257d67c962
|
@ -2,7 +2,7 @@
|
|||
|
||||
import { BigNumber } from "@ethersproject/bignumber";
|
||||
import * as errors from "@ethersproject/errors";
|
||||
import { defineReadOnly, isNamedInstance } from "@ethersproject/properties";
|
||||
import { defineReadOnly } from "@ethersproject/properties";
|
||||
|
||||
|
||||
export interface JsonFragmentType {
|
||||
|
@ -238,6 +238,8 @@ export class ParamType {
|
|||
readonly arrayLength: number;
|
||||
readonly arrayChildren: ParamType;
|
||||
|
||||
readonly _isParamType: boolean;
|
||||
|
||||
constructor(constructorGuard: any, params: any) {
|
||||
if (constructorGuard !== _constructorGuard) { throw new Error("use fromString"); }
|
||||
populate(this, params);
|
||||
|
@ -259,6 +261,10 @@ export class ParamType {
|
|||
baseType: ((this.components != null) ? "tuple": this.type)
|
||||
});
|
||||
}
|
||||
|
||||
this._isParamType = true;
|
||||
|
||||
Object.freeze(this);
|
||||
}
|
||||
|
||||
// Format the parameter fragment
|
||||
|
@ -298,7 +304,7 @@ export class ParamType {
|
|||
}
|
||||
|
||||
static fromObject(value: JsonFragmentType | ParamType): ParamType {
|
||||
if (isNamedInstance<ParamType>(ParamType, value)) { return value; }
|
||||
if (ParamType.isParamType(value)) { return value; }
|
||||
|
||||
return new ParamType(_constructorGuard, {
|
||||
name: (value.name || null),
|
||||
|
@ -320,6 +326,10 @@ export class ParamType {
|
|||
|
||||
return ParamTypify(parseParamType(value, !!allowIndexed));
|
||||
}
|
||||
|
||||
static isParamType(value: any): value is ParamType {
|
||||
return !!(value != null && value._isParamType);
|
||||
}
|
||||
};
|
||||
|
||||
function parseParams(value: string, allowIndex: boolean): Array<ParamType> {
|
||||
|
@ -332,9 +342,15 @@ export abstract class Fragment {
|
|||
readonly name: string;
|
||||
readonly inputs: Array<ParamType>;
|
||||
|
||||
readonly _isFragment: boolean;
|
||||
|
||||
constructor(constructorGuard: any, params: any) {
|
||||
if (constructorGuard !== _constructorGuard) { throw new Error("use a static from method"); }
|
||||
populate(this, params);
|
||||
|
||||
this._isFragment = true;
|
||||
|
||||
Object.freeze(this);
|
||||
}
|
||||
|
||||
// @TOOD: move logic to sub-classes; make this abstract
|
||||
|
@ -370,14 +386,17 @@ export abstract class Fragment {
|
|||
}
|
||||
|
||||
static from(value: Fragment | JsonFragment | string): Fragment {
|
||||
if (Fragment.isFragment(value)) { return value; }
|
||||
|
||||
if (typeof(value) === "string") {
|
||||
return Fragment.fromString(value);
|
||||
}
|
||||
|
||||
return Fragment.fromObject(value);
|
||||
}
|
||||
|
||||
static fromObject(value: Fragment | JsonFragment): Fragment {
|
||||
if (isNamedInstance<Fragment>(Fragment, value)) { return value; }
|
||||
if (Fragment.isFragment(value)) { return value; }
|
||||
|
||||
if (value.type === "function") {
|
||||
return FunctionFragment.fromObject(value);
|
||||
|
@ -412,6 +431,10 @@ export abstract class Fragment {
|
|||
|
||||
throw new Error("unknown fragment");
|
||||
}
|
||||
|
||||
static isFragment(value: any): value is Fragment {
|
||||
return !!(value && value._isFragment);
|
||||
}
|
||||
}
|
||||
|
||||
export class EventFragment extends Fragment {
|
||||
|
@ -425,7 +448,7 @@ export class EventFragment extends Fragment {
|
|||
}
|
||||
|
||||
static fromObject(value: JsonFragment | EventFragment): EventFragment {
|
||||
if (isNamedInstance<EventFragment>(EventFragment, value)) { return value; }
|
||||
if (EventFragment.isEventFragment(value)) { return value; }
|
||||
|
||||
if (value.type !== "event") { throw new Error("invalid event object - " + value.type); }
|
||||
|
||||
|
@ -462,6 +485,10 @@ export class EventFragment extends Fragment {
|
|||
type: "event"
|
||||
});
|
||||
}
|
||||
|
||||
static isEventFragment(value: any): value is EventFragment {
|
||||
return (value && value._isFragment && value.type === "event");
|
||||
}
|
||||
}
|
||||
|
||||
function parseGas(value: string, params: any): string {
|
||||
|
@ -528,7 +555,7 @@ export class ConstructorFragment extends Fragment {
|
|||
}
|
||||
|
||||
static fromObject(value: ConstructorFragment | JsonFragment): ConstructorFragment {
|
||||
if (isNamedInstance<ConstructorFragment>(ConstructorFragment, value)) { return value; }
|
||||
if (ConstructorFragment.isConstructorFragment(value)) { return value; }
|
||||
|
||||
if (value.type !== "constructor") { throw new Error("invalid constructor object - " + value.type); }
|
||||
|
||||
|
@ -557,6 +584,9 @@ export class ConstructorFragment extends Fragment {
|
|||
return ConstructorFragment.fromObject(params);
|
||||
}
|
||||
|
||||
static isConstructorFragment(value: any): value is ConstructorFragment {
|
||||
return (value && value._isFragment && value.type === "constructor");
|
||||
}
|
||||
}
|
||||
|
||||
export class FunctionFragment extends ConstructorFragment {
|
||||
|
@ -571,7 +601,7 @@ export class FunctionFragment extends ConstructorFragment {
|
|||
}
|
||||
|
||||
static fromObject(value: FunctionFragment | JsonFragment): FunctionFragment {
|
||||
if (isNamedInstance<FunctionFragment>(FunctionFragment, value)) { return value; }
|
||||
if (FunctionFragment.isFunctionFragment(value)) { return value; }
|
||||
|
||||
if (value.type !== "function") { throw new Error("invalid function object - " + value.type); }
|
||||
|
||||
|
@ -619,6 +649,10 @@ export class FunctionFragment extends ConstructorFragment {
|
|||
|
||||
return FunctionFragment.fromObject(params);
|
||||
}
|
||||
|
||||
static isFunctionFragment(value: any): value is FunctionFragment {
|
||||
return (value && value._isFragment && value.type === "function");
|
||||
}
|
||||
}
|
||||
|
||||
//export class ErrorFragment extends Fragment {
|
||||
|
|
|
@ -6,7 +6,7 @@ import { arrayify, BytesLike, concat, hexDataSlice, hexlify, hexZeroPad, isHexSt
|
|||
import { id } from "@ethersproject/hash";
|
||||
import { keccak256 } from "@ethersproject/keccak256"
|
||||
import * as errors from "@ethersproject/errors";
|
||||
import { defineReadOnly, Description, isNamedInstance } from "@ethersproject/properties";
|
||||
import { defineReadOnly, Description } from "@ethersproject/properties";
|
||||
|
||||
import { AbiCoder, defaultAbiCoder } from "./abi-coder";
|
||||
import { ConstructorFragment, EventFragment, Fragment, FunctionFragment, JsonFragment, ParamType } from "./fragments";
|
||||
|
@ -31,6 +31,10 @@ export class TransactionDescription extends Description {
|
|||
|
||||
export class Indexed extends Description {
|
||||
readonly hash: string;
|
||||
|
||||
static isIndexed(value: any): value is Indexed {
|
||||
return !!(value && value._isIndexed);
|
||||
}
|
||||
}
|
||||
|
||||
export class Result {
|
||||
|
@ -51,6 +55,8 @@ export class Interface {
|
|||
|
||||
readonly _abiCoder: AbiCoder;
|
||||
|
||||
static _isInterface: boolean;
|
||||
|
||||
constructor(fragments: string | Array<Fragment | JsonFragment | string>) {
|
||||
errors.checkNew(new.target, Interface);
|
||||
|
||||
|
@ -62,9 +68,6 @@ export class Interface {
|
|||
}
|
||||
|
||||
defineReadOnly(this, "fragments", abi.map((fragment) => {
|
||||
if (isNamedInstance<Fragment>(Fragment, fragment)) {
|
||||
return fragment
|
||||
}
|
||||
return Fragment.from(fragment);
|
||||
}).filter((fragment) => (fragment != null)));
|
||||
|
||||
|
@ -122,6 +125,8 @@ export class Interface {
|
|||
if (!this.deploy) {
|
||||
defineReadOnly(this, "deploy", ConstructorFragment.from( { type: "constructor" } ));
|
||||
}
|
||||
|
||||
defineReadOnly(this, "_isInterface", true);
|
||||
}
|
||||
|
||||
static getAbiCoder(): AbiCoder {
|
||||
|
@ -325,10 +330,10 @@ export class Interface {
|
|||
eventFragment.inputs.forEach((param, index) => {
|
||||
if (param.indexed) {
|
||||
if (resultIndexed == null) {
|
||||
result[index] = new Indexed({ hash: null });
|
||||
result[index] = new Indexed({ _isIndexed: true, hash: null });
|
||||
|
||||
} else if (dynamic[index]) {
|
||||
result[index] = new Indexed({ hash: resultIndexed[indexedIndex++] });
|
||||
result[index] = new Indexed({ _isIndexed: true, hash: resultIndexed[indexedIndex++] });
|
||||
|
||||
} else {
|
||||
result[index] = resultIndexed[indexedIndex++];
|
||||
|
@ -387,6 +392,10 @@ export class Interface {
|
|||
return new Interface(value);
|
||||
}
|
||||
*/
|
||||
|
||||
static isInterface(value: any): value is Interface {
|
||||
return !!(value && value._isInterface);
|
||||
}
|
||||
}
|
||||
|
||||
function getFragment(hash: string, calcFunc: (f: Fragment) => string, items: { [ sig: string ]: Fragment } ) {
|
||||
|
|
|
@ -5,7 +5,7 @@ import { BytesLike, isHexString } from "@ethersproject/bytes";
|
|||
import * as errors from "@ethersproject/errors";
|
||||
import { checkAbstract } from "@ethersproject/errors";
|
||||
import { Network } from "@ethersproject/networks";
|
||||
import { defineReadOnly } from "@ethersproject/properties";
|
||||
import { Description, defineReadOnly } from "@ethersproject/properties";
|
||||
import { Transaction } from "@ethersproject/transactions";
|
||||
import { OnceBlockable } from "@ethersproject/web";
|
||||
|
||||
|
@ -128,11 +128,13 @@ export interface FilterByBlockHash extends EventFilter {
|
|||
// call(transaction: TransactionRequest): Promise<TransactionResponse>;
|
||||
//};
|
||||
|
||||
export class ForkEvent {
|
||||
export abstract class ForkEvent extends Description {
|
||||
readonly expiry: number;
|
||||
|
||||
constructor(expiry?: number) {
|
||||
defineReadOnly(this, "expiry", expiry || 0);
|
||||
readonly _isForkEvent: boolean;
|
||||
|
||||
static isForkEvent(value: any): value is ForkEvent {
|
||||
return !!(value && value._isForkEvent);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -143,8 +145,13 @@ export class BlockForkEvent extends ForkEvent {
|
|||
if (!isHexString(blockhash, 32)) {
|
||||
errors.throwArgumentError("invalid blockhash", "blockhash", blockhash);
|
||||
}
|
||||
super(expiry);
|
||||
defineReadOnly(this, "blockhash", blockhash);
|
||||
|
||||
super({
|
||||
_isForkEvent: true,
|
||||
_isBlockForkEvent: true,
|
||||
expiry: (expiry || 0),
|
||||
blockHash: blockhash
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -155,8 +162,13 @@ export class TransactionForkEvent extends ForkEvent {
|
|||
if (!isHexString(hash, 32)) {
|
||||
errors.throwArgumentError("invalid transaction hash", "hash", hash);
|
||||
}
|
||||
super(expiry);
|
||||
defineReadOnly(this, "hash", hash);
|
||||
|
||||
super({
|
||||
_isForkEvent: true,
|
||||
_isTransactionForkEvent: true,
|
||||
expiry: (expiry || 0),
|
||||
hash: hash
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -171,9 +183,14 @@ export class TransactionOrderForkEvent extends ForkEvent {
|
|||
if (!isHexString(afterHash, 32)) {
|
||||
errors.throwArgumentError("invalid transaction hash", "afterHash", afterHash);
|
||||
}
|
||||
super(expiry);
|
||||
defineReadOnly(this, "beforeHash", beforeHash);
|
||||
defineReadOnly(this, "afterHash", afterHash);
|
||||
|
||||
super({
|
||||
_isForkEvent: true,
|
||||
_isTransactionOrderForkEvent: true,
|
||||
expiry: (expiry || 0),
|
||||
beforeHash: beforeHash,
|
||||
afterHash: afterHash
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -239,8 +256,15 @@ export abstract class Provider implements OnceBlockable {
|
|||
// @TODO: This *could* be implemented here, but would pull in events...
|
||||
abstract waitForTransaction(transactionHash: string, timeout?: number): Promise<TransactionReceipt>;
|
||||
|
||||
readonly _isProvider: boolean;
|
||||
|
||||
constructor() {
|
||||
checkAbstract(new.target, Provider);
|
||||
defineReadOnly(this, "_isProvider", true);
|
||||
}
|
||||
|
||||
static isProvider(value: any): value is Provider {
|
||||
return !!(value && value._isProvider);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -51,11 +51,14 @@ export abstract class Signer {
|
|||
// This MAY throw if changing providers is not supported.
|
||||
abstract connect(provider: Provider): Signer;
|
||||
|
||||
readonly _isSigner: boolean;
|
||||
|
||||
|
||||
///////////////////
|
||||
// Sub-classes MUST call super
|
||||
constructor() {
|
||||
errors.checkAbstract(new.target, Signer);
|
||||
defineReadOnly(this, "_isSigner", true);
|
||||
}
|
||||
|
||||
|
||||
|
@ -179,6 +182,10 @@ export abstract class Signer {
|
|||
operation: (operation || "_checkProvider") });
|
||||
}
|
||||
}
|
||||
|
||||
static isSigner(value: any): value is Signer {
|
||||
return !!(value && value._isSigner);
|
||||
}
|
||||
}
|
||||
|
||||
export class VoidSigner extends Signer {
|
||||
|
|
|
@ -11,7 +11,6 @@
|
|||
import * as BN from "bn.js";
|
||||
|
||||
import { Bytes, Hexable, hexlify, isBytes, isHexString } from "@ethersproject/bytes";
|
||||
import { defineReadOnly, isNamedInstance } from "@ethersproject/properties";
|
||||
|
||||
import * as errors from "@ethersproject/errors";
|
||||
|
||||
|
@ -22,18 +21,20 @@ const MAX_SAFE = 0x1fffffffffffff;
|
|||
|
||||
export type BigNumberish = BigNumber | Bytes | string | number;
|
||||
|
||||
/*
|
||||
export function isBigNumberLike(value: any): value is BigNumberish {
|
||||
return (BigNumber.isBigNumber(value) ||
|
||||
(!!((<any>value).toHexString)) ||
|
||||
isBytes(value) ||
|
||||
value.match(/^-?([0-9]+|0x[0-9a-f]+)$/i) ||
|
||||
typeof(value) === "number");
|
||||
export function isBigNumberish(value: any): value is BigNumberish {
|
||||
return (value != null) && (
|
||||
BigNumber.isBigNumber(value) ||
|
||||
(typeof(value) === "number" && (value % 1) === 0) ||
|
||||
(typeof(value) === "string" && !!value.match(/^-?[0-9]+$/)) ||
|
||||
isHexString(value) ||
|
||||
(typeof(value) === "bigint") ||
|
||||
isBytes(value)
|
||||
);
|
||||
}
|
||||
*/
|
||||
|
||||
export class BigNumber implements Hexable {
|
||||
readonly _hex: string;
|
||||
readonly _isBigNumber: boolean;
|
||||
|
||||
constructor(constructorGuard: any, hex: string) {
|
||||
errors.checkNew(new.target, BigNumber);
|
||||
|
@ -44,7 +45,10 @@ export class BigNumber implements Hexable {
|
|||
});
|
||||
}
|
||||
|
||||
defineReadOnly(this, "_hex", hex);
|
||||
this._hex = hex;
|
||||
this._isBigNumber = true;
|
||||
|
||||
Object.freeze(this);
|
||||
}
|
||||
|
||||
fromTwos(value: number): BigNumber {
|
||||
|
@ -189,104 +193,10 @@ export class BigNumber implements Hexable {
|
|||
}
|
||||
|
||||
static isBigNumber(value: any): value is BigNumber {
|
||||
return isNamedInstance<BigNumber>(this, value);
|
||||
return !!(value && value._isBigNumber);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
export function bigNumberify(value: BigNumberish): BigNumber {
|
||||
if (BigNumber.isBigNumber(value)) { return value; }
|
||||
return new BigNumber(value);
|
||||
}
|
||||
*/
|
||||
|
||||
/*
|
||||
function zeros(length) {
|
||||
let result = "";
|
||||
while (result.length < length) { tens += "0"; }
|
||||
return result;
|
||||
}
|
||||
export class FixedNumber {
|
||||
readonly value: BigNumber;
|
||||
readonly decimalPlaces: number;
|
||||
|
||||
constructor(value: BigNumberish, decimalPlaces: number) {
|
||||
defineReadOnly(this, "value", bigNumberify(value));
|
||||
defineReadOnly(this, "decimalPlaces", decimalPlaces);
|
||||
}
|
||||
|
||||
toString(): string {
|
||||
return formatUnits(this.value, this.decimalPlaces);
|
||||
}
|
||||
|
||||
static fromString(value: string): FixedNumber {
|
||||
let comps = value.split(".");
|
||||
let decimalPlaces = 0;
|
||||
if (comps.length === 2) { decimalPlaces = comps[1].length; }
|
||||
return new FixedNumber(parseUnits(value, decimalPlaces), decimalPlaces);
|
||||
}
|
||||
*/
|
||||
/*
|
||||
|
||||
readonly negative: boolean;
|
||||
readonly whole: BigNumber;
|
||||
readonly fraction: BigNumber;
|
||||
constructor(whole: BigNumberish, fraction: BigNumberish, negative?: boolean) {
|
||||
if (whole.lt(constants.Zero)) {
|
||||
errors.throwError("whole component must be positive", errors.INVALID_ARGUMENT, {
|
||||
argument: whole,
|
||||
value: whole
|
||||
});
|
||||
}
|
||||
defineReadOnly(this, "whole", bigNumberify(whole));
|
||||
defineReadOnly(this, "fraction", bigNumberify(fraction));
|
||||
defineReadOnly(this, "negative", !!boolean);
|
||||
}
|
||||
*/
|
||||
/*
|
||||
toHexString(bitWidth?: number, decimalPlaces?: number, signed?: boolean): string {
|
||||
if (bitWidth == null) { bitWidth = 128; }
|
||||
if (decimalPlaces == null) { decimalPlaces = 18; }
|
||||
if (signed == null) { signed = true; }
|
||||
return null;
|
||||
}
|
||||
static fromValue(value: BigNumberish, decimalPlaces: number): FixedNumber {
|
||||
let negative = false;
|
||||
if (value.lt(constants.Zero)) {
|
||||
negative = true;
|
||||
value = value.abs();
|
||||
}
|
||||
let tens = bigNumberify("1" + zeros(decimalPlaces));
|
||||
return new FixedNumber(value.divide(tens), value.mod(tens), negative);
|
||||
}
|
||||
let negative = false;
|
||||
if (value.substring(0, 1) === "-") {
|
||||
negative = true;
|
||||
value = value.substring(1);
|
||||
}
|
||||
|
||||
if (value !== "." && value !== "") {
|
||||
let comps = value.split(".");
|
||||
if (comps.length === 1) {
|
||||
return new FixedNumber(comps[0], 0, negative);
|
||||
} else if (comps.length === 2) {
|
||||
if (comps[0] === "") { comps[0] = "0"; }
|
||||
if (comps[1] === "") { comps[1] = "0"; }
|
||||
return new FixedNumber(comps[0], comps[1], negative);
|
||||
}
|
||||
}
|
||||
|
||||
errors.throwError("invalid fixed-point value", errors.INVALID_ARGUMENT, {
|
||||
argument: "value",
|
||||
value: value
|
||||
});
|
||||
|
||||
return null;
|
||||
*/
|
||||
|
||||
//}
|
||||
|
||||
|
||||
// Normalize the hex string
|
||||
function toHex(value: string | BN.BN): string {
|
||||
|
||||
|
|
|
@ -2,9 +2,8 @@
|
|||
|
||||
import { arrayify, BytesLike, hexZeroPad, isBytes } from "@ethersproject/bytes";
|
||||
import * as errors from "@ethersproject/errors";
|
||||
import { defineReadOnly, isNamedInstance } from "@ethersproject/properties";
|
||||
|
||||
import { BigNumber, BigNumberish } from "./bignumber";
|
||||
import { BigNumber, BigNumberish, isBigNumberish } from "./bignumber";
|
||||
|
||||
const _constructorGuard = { };
|
||||
|
||||
|
@ -115,17 +114,18 @@ export class FixedFormat {
|
|||
readonly width: number;
|
||||
readonly decimals: number;
|
||||
readonly name: string;
|
||||
readonly _multiplier: BigNumber;
|
||||
readonly _multiplier: string;
|
||||
|
||||
constructor(constructorGuard: any, signed: boolean, width: number, decimals: number) {
|
||||
defineReadOnly(this, "signed", signed);
|
||||
defineReadOnly(this, "width", width);
|
||||
defineReadOnly(this, "decimals", decimals);
|
||||
this.signed = signed;
|
||||
this.width = width;
|
||||
this.decimals = decimals;
|
||||
|
||||
let name = (signed ? "": "u") + "fixed" + String(width) + "x" + String(decimals);
|
||||
defineReadOnly(this, "name", name);
|
||||
this.name = (signed ? "": "u") + "fixed" + String(width) + "x" + String(decimals);
|
||||
|
||||
defineReadOnly(this, "_multiplier", getMultiplier(decimals));
|
||||
this._multiplier = getMultiplier(decimals);
|
||||
|
||||
Object.freeze(this);
|
||||
}
|
||||
|
||||
static from(value: any): FixedFormat {
|
||||
|
@ -170,10 +170,6 @@ export class FixedFormat {
|
|||
|
||||
return new FixedFormat(_constructorGuard, signed, width, decimals);
|
||||
}
|
||||
|
||||
static isInstance(value: any): value is FixedFormat {
|
||||
return isNamedInstance(this, value);
|
||||
}
|
||||
}
|
||||
|
||||
export class FixedNumber {
|
||||
|
@ -181,13 +177,19 @@ export class FixedNumber {
|
|||
readonly _hex: string;
|
||||
readonly _value: string;
|
||||
|
||||
readonly _isFixedNumber: boolean;
|
||||
|
||||
constructor(constructorGuard: any, hex: string, value: string, format?: FixedFormat) {
|
||||
errors.checkNew(new.target, FixedNumber);
|
||||
defineReadOnly(this, 'format', format);
|
||||
defineReadOnly(this, '_hex', hex);
|
||||
defineReadOnly(this, '_value', value);
|
||||
}
|
||||
|
||||
this.format = format;
|
||||
this._hex = hex;
|
||||
this._value = value;
|
||||
|
||||
this._isFixedNumber = true;
|
||||
|
||||
Object.freeze(this);
|
||||
}
|
||||
|
||||
_checkFormat(other: FixedNumber): void {
|
||||
if (this.format.name !== other.format.name) {
|
||||
|
@ -261,7 +263,7 @@ export class FixedNumber {
|
|||
|
||||
static fromValue(value: BigNumber, decimals?: BigNumberish, format?: FixedFormat | string): FixedNumber {
|
||||
// If decimals looks more like a format, and there is no format, shift the parameters
|
||||
if (format == null && decimals != null && (FixedFormat.isInstance(decimals) || typeof(decimals) === "string")) {
|
||||
if (format == null && decimals != null && !isBigNumberish(decimals)) {
|
||||
format = decimals;
|
||||
decimals = null;
|
||||
}
|
||||
|
@ -269,15 +271,14 @@ export class FixedNumber {
|
|||
if (decimals == null) { decimals = 0; }
|
||||
if (format == null) { format = "fixed"; }
|
||||
|
||||
let fixedFormat = (FixedFormat.isInstance(format) ? format: FixedFormat.from(format));
|
||||
return FixedNumber.fromString(formatFixed(value, decimals), fixedFormat);
|
||||
return FixedNumber.fromString(formatFixed(value, decimals), FixedFormat.from(format));
|
||||
}
|
||||
|
||||
|
||||
static fromString(value: string, format?: FixedFormat | string): FixedNumber {
|
||||
if (format == null) { format = "fixed"; }
|
||||
|
||||
let fixedFormat = (FixedFormat.isInstance(format) ? format: FixedFormat.from(format));
|
||||
let fixedFormat = FixedFormat.from(format);
|
||||
|
||||
let numeric = parseFixed(value, fixedFormat.decimals);
|
||||
|
||||
|
@ -301,7 +302,7 @@ export class FixedNumber {
|
|||
static fromBytes(value: BytesLike, format?: FixedFormat | string): FixedNumber {
|
||||
if (format == null) { format = "fixed"; }
|
||||
|
||||
let fixedFormat = (FixedFormat.isInstance(format) ? format: FixedFormat.from(format));
|
||||
let fixedFormat = FixedFormat.from(format);
|
||||
|
||||
if (arrayify(value).length > fixedFormat.width / 8) {
|
||||
throw new Error("overflow");
|
||||
|
@ -338,6 +339,6 @@ export class FixedNumber {
|
|||
}
|
||||
|
||||
static isFixedNumber(value: any): value is FixedNumber {
|
||||
return isNamedInstance<FixedNumber>(this, value);
|
||||
return !!(value && value._isFixedNumber);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -8,7 +8,7 @@ import { BigNumber, BigNumberish } from "@ethersproject/bignumber";
|
|||
import { BytesLike, concat, hexlify, isBytes, isHexString } from "@ethersproject/bytes";
|
||||
import { Zero } from "@ethersproject/constants";
|
||||
import * as errors from "@ethersproject/errors";
|
||||
import { defineReadOnly, deepCopy, isNamedInstance, resolveProperties, shallowCopy } from "@ethersproject/properties";
|
||||
import { defineReadOnly, deepCopy, resolveProperties, shallowCopy } from "@ethersproject/properties";
|
||||
import { UnsignedTransaction } from "@ethersproject/transactions";
|
||||
|
||||
|
||||
|
@ -440,10 +440,10 @@ export class Contract {
|
|||
|
||||
defineReadOnly(this, "interface", new.target.getInterface(contractInterface));
|
||||
|
||||
if (isNamedInstance<Signer>(Signer, signerOrProvider)) {
|
||||
defineReadOnly(this, "provider", signerOrProvider.provider);
|
||||
if (Signer.isSigner(signerOrProvider)) {
|
||||
defineReadOnly(this, "provider", signerOrProvider.provider || null);
|
||||
defineReadOnly(this, "signer", signerOrProvider);
|
||||
} else if (isNamedInstance<Provider>(Provider, signerOrProvider)) {
|
||||
} else if (Provider.isProvider(signerOrProvider)) {
|
||||
defineReadOnly(this, "provider", signerOrProvider);
|
||||
defineReadOnly(this, "signer", null);
|
||||
} else {
|
||||
|
@ -518,7 +518,7 @@ export class Contract {
|
|||
}
|
||||
|
||||
static getInterface(contractInterface: ContractInterface): Interface {
|
||||
if (isNamedInstance<Interface>(Interface, contractInterface)) {
|
||||
if (Interface.isInterface(contractInterface)) {
|
||||
return contractInterface;
|
||||
}
|
||||
return new Interface(contractInterface);
|
||||
|
@ -601,7 +601,7 @@ export class Contract {
|
|||
}
|
||||
|
||||
static isIndexed(value: any): value is Indexed {
|
||||
return isNamedInstance<Indexed>(Indexed, value);
|
||||
return Indexed.isIndexed(value);
|
||||
}
|
||||
|
||||
private _normalizeRunningEvent(runningEvent: RunningEvent): RunningEvent {
|
||||
|
@ -845,7 +845,7 @@ export class ContractFactory {
|
|||
}
|
||||
|
||||
// If we have a signer, make sure it is valid
|
||||
if (signer && !isNamedInstance<Signer>(Signer, signer)) {
|
||||
if (signer && !Signer.isSigner(signer)) {
|
||||
errors.throwArgumentError("invalid signer", "signer", signer);
|
||||
}
|
||||
|
||||
|
|
|
@ -19,8 +19,10 @@ export class CrowdsaleAccount extends Description implements ExternallyOwnedAcco
|
|||
readonly mnemonic?: string;
|
||||
readonly path?: string;
|
||||
|
||||
isType(value: any): value is CrowdsaleAccount {
|
||||
return Description.isType(value);
|
||||
readonly _isCrowdsaleAccount: boolean;
|
||||
|
||||
isCrowdsaleAccount(value: any): value is CrowdsaleAccount {
|
||||
return !!(value && value._isCrowdsaleAccount);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -63,6 +65,7 @@ export function decrypt(json: string, password: Bytes | string): ExternallyOwned
|
|||
let privateKey = keccak256(seedHexBytes);
|
||||
|
||||
return new CrowdsaleAccount ({
|
||||
_isCrowdsaleAccount: true,
|
||||
address: ethaddr,
|
||||
privateKey: privateKey
|
||||
});
|
||||
|
|
|
@ -24,8 +24,10 @@ export class KeystoreAccount extends Description implements ExternallyOwnedAccou
|
|||
readonly mnemonic?: string;
|
||||
readonly path?: string;
|
||||
|
||||
isType(value: any): value is KeystoreAccount {
|
||||
return Description.isType(value);
|
||||
readonly _isKeystoreAccount: boolean;
|
||||
|
||||
isKeystoreAccount(value: any): value is KeystoreAccount {
|
||||
return !!(value && value._isKeystoreAccount);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -95,6 +97,7 @@ export function decrypt(json: string, password: Bytes | string, progressCallback
|
|||
} catch (e) { }
|
||||
|
||||
let account: any = {
|
||||
_isKeystoreAccount: true,
|
||||
address: address,
|
||||
privateKey: hexlify(privateKey)
|
||||
};
|
||||
|
|
|
@ -10,47 +10,6 @@ export function defineReadOnly(object: any, name: string, value: any): void {
|
|||
});
|
||||
}
|
||||
|
||||
// There are some issues with instanceof with npm link, so we use this
|
||||
// to ensure types are what we expect. We use this for a little extra
|
||||
// protection to make sure the correct types are being passed around.
|
||||
|
||||
function getType(object: any) {
|
||||
|
||||
let type = typeof(object);
|
||||
if (type !== "function") { return null; }
|
||||
|
||||
let types = [ ];
|
||||
let obj = object;
|
||||
while (true) {
|
||||
let type = obj.name;
|
||||
if (!type) { break; }
|
||||
types.push(type);
|
||||
obj = Object.getPrototypeOf(obj);
|
||||
}
|
||||
return types.join(" ");
|
||||
}
|
||||
|
||||
function hasSuffix(text: string, suffix: string) {
|
||||
return text.substring(text.length - suffix.length) === suffix;
|
||||
}
|
||||
|
||||
export function isNamedInstance<T>(type: Function | string, value: any): value is T {
|
||||
let name = getType(type);
|
||||
if (!name) { return false; }
|
||||
|
||||
// Not a string...
|
||||
if (typeof(value) !== "string") {
|
||||
|
||||
// Not an instance...
|
||||
if (typeof(value) !== "object") { return false; }
|
||||
|
||||
// Get the instance type
|
||||
value = getType(value.constructor);
|
||||
}
|
||||
|
||||
return (name === value || hasSuffix(value, " " + name));
|
||||
}
|
||||
|
||||
export function resolveProperties(object: any): Promise<any> {
|
||||
let result: any = {};
|
||||
|
||||
|
@ -115,10 +74,8 @@ export function deepCopy(object: any, frozen?: boolean): any {
|
|||
|
||||
if (typeof(object) === "object") {
|
||||
|
||||
// Some internal objects, which are already immutable
|
||||
if (isNamedInstance("BigNumber", object)) { return object; }
|
||||
if (isNamedInstance("Description", object)) { return object; }
|
||||
if (isNamedInstance("Indexed", object)) { return object; }
|
||||
// Immutable objects are safe to just use
|
||||
if (Object.isFrozen(object)) { return object; }
|
||||
|
||||
let result: { [ key: string ]: any } = {};
|
||||
for (let key in object) {
|
||||
|
@ -147,8 +104,4 @@ export class Description {
|
|||
}
|
||||
Object.freeze(this);
|
||||
}
|
||||
|
||||
static isType(value: any): boolean {
|
||||
return isNamedInstance(this, value);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -9,7 +9,7 @@ import { arrayify, hexDataLength, hexlify, hexValue, isHexString } from "@ethers
|
|||
import * as errors from "@ethersproject/errors";
|
||||
import { namehash } from "@ethersproject/hash";
|
||||
import { getNetwork, Network, Networkish } from "@ethersproject/networks";
|
||||
import { defineReadOnly, isNamedInstance, resolveProperties } from "@ethersproject/properties";
|
||||
import { defineReadOnly, resolveProperties } from "@ethersproject/properties";
|
||||
import { Transaction } from "@ethersproject/transactions";
|
||||
import { toUtf8String } from "@ethersproject/strings";
|
||||
import { poll } from "@ethersproject/web";
|
||||
|
@ -77,7 +77,7 @@ function getEventTag(eventName: EventType): string {
|
|||
} else if (Array.isArray(eventName)) {
|
||||
return "filter:*:" + serializeTopics(eventName);
|
||||
|
||||
} else if (isNamedInstance<ForkEvent>(ForkEvent, eventName)) {
|
||||
} else if (ForkEvent.isForkEvent(eventName)) {
|
||||
errors.warn("not implemented");
|
||||
throw new Error("not implemented");
|
||||
|
||||
|
|
|
@ -22,7 +22,9 @@ export class SigningKey {
|
|||
readonly publicKey: string;
|
||||
readonly compressedPublicKey: string;
|
||||
|
||||
readonly address: string;
|
||||
//readonly address: string;
|
||||
|
||||
readonly _isSigningKey: boolean;
|
||||
|
||||
constructor(privateKey: BytesLike) {
|
||||
defineReadOnly(this, "curve", "secp256k1");
|
||||
|
@ -33,6 +35,8 @@ export class SigningKey {
|
|||
|
||||
defineReadOnly(this, "publicKey", "0x" + keyPair.getPublic(false, "hex"));
|
||||
defineReadOnly(this, "compressedPublicKey", "0x" + keyPair.getPublic(true, "hex"));
|
||||
|
||||
defineReadOnly(this, "_isSigningKey", true);
|
||||
}
|
||||
|
||||
_addPoint(other: BytesLike): string {
|
||||
|
@ -56,6 +60,10 @@ export class SigningKey {
|
|||
let otherKeyPair = getCurve().keyFromPublic(arrayify(computePublicKey(otherKey)));
|
||||
return hexZeroPad("0x" + keyPair.derive(otherKeyPair.getPublic()).toString(16), 32);
|
||||
}
|
||||
|
||||
static isSigningKey(value: any): value is SigningKey {
|
||||
return !!(value && value._isSigningKey);
|
||||
}
|
||||
}
|
||||
|
||||
export function recoverPublicKey(digest: BytesLike, signature: SignatureLike): string {
|
||||
|
|
|
@ -8,7 +8,7 @@ import * as errors from "@ethersproject/errors";
|
|||
import { hashMessage } from "@ethersproject/hash";
|
||||
import { defaultPath, HDNode, entropyToMnemonic } from "@ethersproject/hdnode";
|
||||
import { keccak256 } from "@ethersproject/keccak256";
|
||||
import { defineReadOnly, isNamedInstance, resolveProperties } from "@ethersproject/properties";
|
||||
import { defineReadOnly, resolveProperties } from "@ethersproject/properties";
|
||||
import { randomBytes } from "@ethersproject/random";
|
||||
import { SigningKey } from "@ethersproject/signing-key";
|
||||
import { decryptJsonWallet, encryptKeystore, ProgressCallback } from "@ethersproject/json-wallets";
|
||||
|
@ -61,7 +61,10 @@ export class Wallet extends Signer implements ExternallyOwnedAccount {
|
|||
|
||||
|
||||
} else {
|
||||
if (isNamedInstance<SigningKey>(SigningKey, privateKey)) {
|
||||
if (SigningKey.isSigningKey(privateKey)) {
|
||||
if (privateKey.curve !== "secp256k1") {
|
||||
errors.throwArgumentError("unsupported curve; must be secp256k1", "privateKey", "[REDACTED]");
|
||||
}
|
||||
defineReadOnly(this, "_signingKey", () => privateKey);
|
||||
} else {
|
||||
let signingKey = new SigningKey(privateKey);
|
||||
|
@ -72,7 +75,7 @@ export class Wallet extends Signer implements ExternallyOwnedAccount {
|
|||
defineReadOnly(this, "address", computeAddress(this.publicKey));
|
||||
}
|
||||
|
||||
if (provider && !isNamedInstance<Provider>(Provider, provider)) {
|
||||
if (provider && !Provider.isProvider(provider)) {
|
||||
errors.throwError("invalid provider", errors.INVALID_ARGUMENT, {
|
||||
argument: "provider",
|
||||
value: provider
|
||||
|
|
Loading…
Reference in New Issue