Compare commits

..

11 Commits

Author SHA1 Message Date
Richard Moore
f3ec27b95f Added customizable log levels to quiet warnings (#379). 2018-12-27 15:48:38 -05:00
Richard Moore
c88cb5ea90 Updated dist files. 2018-12-14 18:39:46 -05:00
Richard Moore
99a21660ab Allow unchecked transactions which will remain unwrapped for the JsonRpcSigner (#340). 2018-12-14 18:36:24 -05:00
Richard Moore
4bc62a1e8a Make it easier for sub-classes of Wallet to manage nonces. 2018-12-14 18:32:48 -05:00
Richard Moore
26eb6cc01a Updated dist files. 2018-12-12 16:59:25 -05:00
Richard Moore
bcba17a9e7 Allow nonce to be a BigNumber (#228). 2018-12-12 16:56:50 -05:00
Richard Moore
918b66bc2e Fixed typo in error strings (#376). 2018-12-12 16:31:23 -05:00
Richard Moore
152d672278 Add isHexString to exported utils (#367). 2018-12-12 16:23:39 -05:00
Richard Moore
51fb472809 Add abs method to BigNumber (#375). 2018-12-12 16:10:28 -05:00
Richard Moore
66440b8542 Better error messages for namehash (#364). 2018-12-10 17:02:02 -05:00
Richard Moore
fefdd51084 Updated dist files. 2018-12-08 18:48:53 -05:00
36 changed files with 267 additions and 100 deletions

2
_version.d.ts vendored
View File

@@ -1 +1 @@
export declare const version = "4.0.17";
export declare const version = "4.0.20";

View File

@@ -1,3 +1,3 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.version = "4.0.17";
exports.version = "4.0.20";

86
dist/ethers.js vendored
View File

@@ -1,7 +1,7 @@
(function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.ethers = f()}})(function(){var define,module,exports;return (function(){function r(e,n,t){function o(i,f){if(!n[i]){if(!e[i]){var c="function"==typeof require&&require;if(!f&&c)return c(i,!0);if(u)return u(i,!0);var a=new Error("Cannot find module '"+i+"'");throw a.code="MODULE_NOT_FOUND",a}var p=n[i]={exports:{}};e[i][0].call(p.exports,function(r){var n=e[i][1][r];return o(n||r)},p,p.exports,r,e,n,t)}return n[i].exports}for(var u="function"==typeof require&&require,i=0;i<t.length;i++)o(t[i]);return o}return r})()({1:[function(require,module,exports){
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.version = "4.0.17";
exports.version = "4.0.20";
},{}],2:[function(require,module,exports){
"use strict";
@@ -770,7 +770,7 @@ exports.MISSING_NEW = 'MISSING_NEW';
// - reason: The reason (only for EIP848 "Error(string)")
exports.CALL_EXCEPTION = 'CALL_EXCEPTION';
// Invalid argument (e.g. value is incompatible with type) to a function:
// - arg: The argument name that was invalid
// - argument: The argument name that was invalid
// - value: The value of the argument
exports.INVALID_ARGUMENT = 'INVALID_ARGUMENT';
// Missing argument to a function:
@@ -854,7 +854,7 @@ function checkArgumentCount(count, expectedCount, suffix) {
exports.checkArgumentCount = checkArgumentCount;
function setCensorship(censorship, permanent) {
if (_permanentCensorErrors) {
throwError('error censorship permanent', exports.UNSUPPORTED_OPERATION, { operation: 'setCersorship' });
throwError('error censorship permanent', exports.UNSUPPORTED_OPERATION, { operation: 'setCensorship' });
}
_censorErrors = !!censorship;
_permanentCensorErrors = !!permanent;
@@ -10284,6 +10284,8 @@ var BaseProvider = /** @class */ (function (_super) {
properties_1.defineReadOnly(_this, '_network', network);
return network;
}));
// Squash any "unhandled promise" errors; the don't need to be handled
_this.ready.catch(function (error) { });
}
else {
var knownNetwork = networks_1.getNetwork((network == null) ? 'homestead' : network);
@@ -11698,7 +11700,7 @@ var JsonRpcSigner = /** @class */ (function (_super) {
JsonRpcSigner.prototype.getTransactionCount = function (blockTag) {
return this.provider.getTransactionCount(this.getAddress(), blockTag);
};
JsonRpcSigner.prototype.sendTransaction = function (transaction) {
JsonRpcSigner.prototype.sendUncheckedTransaction = function (transaction) {
var _this = this;
transaction = properties_1.shallowCopy(transaction);
var fromAddress = this.getAddress().then(function (address) {
@@ -11723,17 +11725,7 @@ var JsonRpcSigner = /** @class */ (function (_super) {
var hexTx = JsonRpcProvider.hexlifyTransaction(tx);
hexTx.from = results[1];
return _this.provider.send('eth_sendTransaction', [hexTx]).then(function (hash) {
return web_1.poll(function () {
return _this.provider.getTransaction(hash).then(function (tx) {
if (tx === null) {
return undefined;
}
return _this.provider._wrapTransaction(tx, hash);
});
}, { onceBlock: _this.provider }).catch(function (error) {
error.transactionHash = hash;
throw error;
});
return hash;
}, function (error) {
if (error.responseText) {
// See: JsonRpcProvider.sendTransaction (@TODO: Expose a ._throwError??)
@@ -11757,6 +11749,22 @@ var JsonRpcSigner = /** @class */ (function (_super) {
});
});
};
JsonRpcSigner.prototype.sendTransaction = function (transaction) {
var _this = this;
return this.sendUncheckedTransaction(transaction).then(function (hash) {
return web_1.poll(function () {
return _this.provider.getTransaction(hash).then(function (tx) {
if (tx === null) {
return undefined;
}
return _this.provider._wrapTransaction(tx, hash);
});
}, { onceBlock: _this.provider }).catch(function (error) {
error.transactionHash = hash;
throw error;
});
});
};
JsonRpcSigner.prototype.signMessage = function (message) {
var _this = this;
var data = ((typeof (message) === 'string') ? utf8_1.toUtf8Bytes(message) : message);
@@ -13297,6 +13305,12 @@ var BigNumber = /** @class */ (function () {
BigNumber.prototype.toTwos = function (value) {
return toBigNumber(_bnify(this).toTwos(value));
};
BigNumber.prototype.abs = function () {
if (this._hex[0] === '-') {
return toBigNumber(_bnify(this).mul(BN_1));
}
return this;
};
BigNumber.prototype.add = function (other) {
return toBigNumber(_bnify(this).add(toBN(other)));
};
@@ -13640,7 +13654,15 @@ exports.joinSignature = joinSignature;
},{"../errors":5}],63:[function(require,module,exports){
'use strict';
var __importStar = (this && this.__importStar) || function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (Object.hasOwnProperty.call(mod, k)) result[k] = mod[k];
result["default"] = mod;
return result;
};
Object.defineProperty(exports, "__esModule", { value: true });
var errors = __importStar(require("../errors"));
var bytes_1 = require("./bytes");
var utf8_1 = require("./utf8");
var keccak256_1 = require("./keccak256");
@@ -13649,13 +13671,22 @@ var Zeros = new Uint8Array([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
var Partition = new RegExp("^((.*)\\.)?([^.]+)$");
var UseSTD3ASCIIRules = new RegExp("^[a-z0-9.-]*$");
function namehash(name) {
if (typeof (name) !== 'string') {
errors.throwError('invalid address - ' + String(name), errors.INVALID_ARGUMENT, {
argument: 'name',
value: name
});
}
name = name.toLowerCase();
// Supporting the full UTF-8 space requires additional (and large)
// libraries, so for now we simply do not support them.
// It should be fairly easy in the future to support systems with
// String.normalize, but that is future work.
if (!name.match(UseSTD3ASCIIRules)) {
throw new Error('contains invalid UseSTD3ASCIIRules characters');
errors.throwError('contains invalid UseSTD3ASCIIRules characters', errors.INVALID_ARGUMENT, {
argument: 'name',
value: name
});
}
var result = Zeros;
while (name.length) {
@@ -13672,16 +13703,15 @@ function id(text) {
}
exports.id = id;
function hashMessage(message) {
var payload = bytes_1.concat([
return keccak256_1.keccak256(bytes_1.concat([
utf8_1.toUtf8Bytes('\x19Ethereum Signed Message:\n'),
utf8_1.toUtf8Bytes(String(message.length)),
((typeof (message) === 'string') ? utf8_1.toUtf8Bytes(message) : message)
]);
return keccak256_1.keccak256(payload);
]));
}
exports.hashMessage = hashMessage;
},{"./bytes":62,"./keccak256":69,"./utf8":83}],64:[function(require,module,exports){
},{"../errors":5,"./bytes":62,"./keccak256":69,"./utf8":83}],64:[function(require,module,exports){
'use strict';
var __importStar = (this && this.__importStar) || function (mod) {
if (mod && mod.__esModule) return mod;
@@ -13988,6 +14018,7 @@ exports.hexDataLength = bytes_1.hexDataLength;
exports.hexlify = bytes_1.hexlify;
exports.hexStripZeros = bytes_1.hexStripZeros;
exports.hexZeroPad = bytes_1.hexZeroPad;
exports.isHexString = bytes_1.isHexString;
exports.joinSignature = bytes_1.joinSignature;
exports.padZeros = bytes_1.padZeros;
exports.splitSignature = bytes_1.splitSignature;
@@ -14309,6 +14340,7 @@ function addMethod(method) {
gas: method.gas,
payable: (method.payable == null || !!method.payable),
type: ((method.constant) ? 'call' : 'transaction'),
name: method.name,
signature: signature,
sighash: sighash,
});
@@ -14399,7 +14431,7 @@ var Interface = /** @class */ (function () {
return new _TransactionDescription({
args: result,
decode: func.decode,
name: name,
name: func.name,
signature: func.signature,
sighash: func.sighash,
value: bignumber_1.bigNumberify(tx.value || '0'),
@@ -16327,6 +16359,9 @@ function fetchJson(connection, json, processFunc) {
var jsonError = new Error('invalid json response');
jsonError.orginialError = error;
jsonError.responseText = request.responseText;
if (json != null) {
jsonError.requestBody = json;
}
jsonError.url = url;
reject(jsonError);
return;
@@ -16352,7 +16387,7 @@ function fetchJson(connection, json, processFunc) {
reject(error);
};
try {
if (json) {
if (json != null) {
request.send(json);
}
else {
@@ -16603,6 +16638,13 @@ var Wallet = /** @class */ (function (_super) {
};
Wallet.prototype.sendTransaction = function (transaction) {
var _this = this;
if (!this.provider) {
throw new Error('missing provider');
}
if (transaction.nonce == null) {
transaction = properties_1.shallowCopy(transaction);
transaction.nonce = this.getTransactionCount("pending");
}
return transaction_1.populateTransaction(transaction, this.provider, this.address).then(function (tx) {
return _this.sign(tx).then(function (signedTransaction) {
return _this.provider.sendTransaction(signedTransaction);

2
dist/ethers.min.js vendored

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

10
dist/ethers.types.txt vendored
View File

@@ -210,7 +210,7 @@ declare module 'ethers/utils' {
import { getAddress, getContractAddress, getIcapAddress } from 'ethers/utils/address';
import * as base64 from 'ethers/utils/base64';
import { BigNumber, bigNumberify } from 'ethers/utils/bignumber';
import { arrayify, concat, hexDataSlice, hexDataLength, hexlify, hexStripZeros, hexZeroPad, joinSignature, padZeros, splitSignature, stripZeros } from 'ethers/utils/bytes';
import { arrayify, concat, hexDataSlice, hexDataLength, hexlify, hexStripZeros, hexZeroPad, isHexString, joinSignature, padZeros, splitSignature, stripZeros } from 'ethers/utils/bytes';
import { hashMessage, id, namehash } from 'ethers/utils/hash';
import * as HDNode from 'ethers/utils/hdnode';
import { Interface } from 'ethers/utils/interface';
@@ -240,7 +240,7 @@ declare module 'ethers/utils' {
import { ConnectionInfo, OnceBlockable, PollOptions } from 'ethers/utils/web';
import { EncryptOptions, ProgressCallback } from 'ethers/utils/secret-storage';
import { Wordlist } from 'ethers/utils/wordlist';
export { AbiCoder, defaultAbiCoder, formatSignature, formatParamType, parseSignature, parseParamType, RLP, fetchJson, getNetwork, checkProperties, deepCopy, defineReadOnly, resolveProperties, shallowCopy, arrayify, concat, padZeros, stripZeros, HDNode, SigningKey, Interface, base64, BigNumber, bigNumberify, hexlify, hexStripZeros, hexZeroPad, hexDataLength, hexDataSlice, toUtf8Bytes, toUtf8String, formatBytes32String, parseBytes32String, hashMessage, namehash, id, getAddress, getIcapAddress, getContractAddress, formatEther, parseEther, formatUnits, parseUnits, commify, keccak256, sha256, randomBytes, solidityPack, solidityKeccak256, soliditySha256, splitSignature, joinSignature, parseTransaction, populateTransaction, serializeTransaction, getJsonWalletAddress, computeAddress, computePublicKey, recoverAddress, recoverPublicKey, verifyMessage, SupportedAlgorithms, UnicodeNormalizationForm, CoerceFunc, EventFragment, FunctionFragment, ParamType, BigNumberish, Arrayish, Hexable, Signature, Indexed, DeployDescription, EventDescription, FunctionDescription, LogDescription, TransactionDescription, Network, Networkish, Transaction, UnsignedTransaction, ConnectionInfo, OnceBlockable, PollOptions, EncryptOptions, ProgressCallback, Wordlist, };
export { AbiCoder, defaultAbiCoder, formatSignature, formatParamType, parseSignature, parseParamType, RLP, fetchJson, getNetwork, checkProperties, deepCopy, defineReadOnly, resolveProperties, shallowCopy, arrayify, concat, padZeros, stripZeros, HDNode, SigningKey, Interface, base64, BigNumber, bigNumberify, hexlify, isHexString, hexStripZeros, hexZeroPad, hexDataLength, hexDataSlice, toUtf8Bytes, toUtf8String, formatBytes32String, parseBytes32String, hashMessage, namehash, id, getAddress, getIcapAddress, getContractAddress, formatEther, parseEther, formatUnits, parseUnits, commify, keccak256, sha256, randomBytes, solidityPack, solidityKeccak256, soliditySha256, splitSignature, joinSignature, parseTransaction, populateTransaction, serializeTransaction, getJsonWalletAddress, computeAddress, computePublicKey, recoverAddress, recoverPublicKey, verifyMessage, SupportedAlgorithms, UnicodeNormalizationForm, CoerceFunc, EventFragment, FunctionFragment, ParamType, BigNumberish, Arrayish, Hexable, Signature, Indexed, DeployDescription, EventDescription, FunctionDescription, LogDescription, TransactionDescription, Network, Networkish, Transaction, UnsignedTransaction, ConnectionInfo, OnceBlockable, PollOptions, EncryptOptions, ProgressCallback, Wordlist, };
}
declare module 'ethers/wordlists' {
@@ -262,7 +262,7 @@ declare module 'ethers/utils/shims' {
}
declare module 'ethers/_version' {
export const version = "4.0.17";
export const version = "4.0.20";
}
declare module 'ethers/utils/bignumber' {
@@ -273,6 +273,7 @@ declare module 'ethers/utils/bignumber' {
constructor(value: BigNumberish);
fromTwos(value: number): BigNumber;
toTwos(value: number): BigNumber;
abs(): BigNumber;
add(other: BigNumberish): BigNumber;
sub(other: BigNumberish): BigNumber;
div(other: BigNumberish): BigNumber;
@@ -500,7 +501,7 @@ declare module 'ethers/providers/abstract-provider' {
export type TransactionRequest = {
to?: string | Promise<string>;
from?: string | Promise<string>;
nonce?: number | string | Promise<number | string>;
nonce?: BigNumberish | Promise<BigNumberish>;
gasLimit?: BigNumberish | Promise<BigNumberish>;
gasPrice?: BigNumberish | Promise<BigNumberish>;
data?: Arrayish | Promise<Arrayish>;
@@ -832,6 +833,7 @@ declare module 'ethers/providers/json-rpc-provider' {
getAddress(): Promise<string>;
getBalance(blockTag?: BlockTag): Promise<BigNumber>;
getTransactionCount(blockTag?: BlockTag): Promise<number>;
sendUncheckedTransaction(transaction: TransactionRequest): Promise<string>;
sendTransaction(transaction: TransactionRequest): Promise<TransactionResponse>;
signMessage(message: Arrayish | string): Promise<string>;
unlock(password: string): Promise<boolean>;

View File

@@ -18,7 +18,7 @@ exports.MISSING_NEW = 'MISSING_NEW';
// - reason: The reason (only for EIP848 "Error(string)")
exports.CALL_EXCEPTION = 'CALL_EXCEPTION';
// Invalid argument (e.g. value is incompatible with type) to a function:
// - arg: The argument name that was invalid
// - argument: The argument name that was invalid
// - value: The value of the argument
exports.INVALID_ARGUMENT = 'INVALID_ARGUMENT';
// Missing argument to a function:
@@ -102,7 +102,7 @@ function checkArgumentCount(count, expectedCount, suffix) {
exports.checkArgumentCount = checkArgumentCount;
function setCensorship(censorship, permanent) {
if (_permanentCensorErrors) {
throwError('error censorship permanent', exports.UNSUPPORTED_OPERATION, { operation: 'setCersorship' });
throwError('error censorship permanent', exports.UNSUPPORTED_OPERATION, { operation: 'setCensorship' });
}
_censorErrors = !!censorship;
_permanentCensorErrors = !!permanent;

2
package-lock.json generated
View File

@@ -1,6 +1,6 @@
{
"name": "ethers",
"version": "4.0.17",
"version": "4.0.20",
"lockfileVersion": 1,
"requires": true,
"dependencies": {

View File

@@ -1,6 +1,6 @@
{
"name": "ethers",
"version": "4.0.17",
"version": "4.0.20",
"description": "Ethereum wallet library.",
"main": "./index.js",
"types": "./index.d.ts",

View File

@@ -54,7 +54,7 @@ export interface TransactionReceipt {
export declare type TransactionRequest = {
to?: string | Promise<string>;
from?: string | Promise<string>;
nonce?: number | string | Promise<number | string>;
nonce?: BigNumberish | Promise<BigNumberish>;
gasLimit?: BigNumberish | Promise<BigNumberish>;
gasPrice?: BigNumberish | Promise<BigNumberish>;
data?: Arrayish | Promise<Arrayish>;

View File

@@ -415,6 +415,8 @@ var BaseProvider = /** @class */ (function (_super) {
properties_1.defineReadOnly(_this, '_network', network);
return network;
}));
// Squash any "unhandled promise" errors; the don't need to be handled
_this.ready.catch(function (error) { });
}
else {
var knownNetwork = networks_1.getNetwork((network == null) ? 'homestead' : network);

View File

@@ -13,6 +13,7 @@ export declare class JsonRpcSigner extends Signer {
getAddress(): Promise<string>;
getBalance(blockTag?: BlockTag): Promise<BigNumber>;
getTransactionCount(blockTag?: BlockTag): Promise<number>;
sendUncheckedTransaction(transaction: TransactionRequest): Promise<string>;
sendTransaction(transaction: TransactionRequest): Promise<TransactionResponse>;
signMessage(message: Arrayish | string): Promise<string>;
unlock(password: string): Promise<boolean>;

View File

@@ -96,7 +96,7 @@ var JsonRpcSigner = /** @class */ (function (_super) {
JsonRpcSigner.prototype.getTransactionCount = function (blockTag) {
return this.provider.getTransactionCount(this.getAddress(), blockTag);
};
JsonRpcSigner.prototype.sendTransaction = function (transaction) {
JsonRpcSigner.prototype.sendUncheckedTransaction = function (transaction) {
var _this = this;
transaction = properties_1.shallowCopy(transaction);
var fromAddress = this.getAddress().then(function (address) {
@@ -121,17 +121,7 @@ var JsonRpcSigner = /** @class */ (function (_super) {
var hexTx = JsonRpcProvider.hexlifyTransaction(tx);
hexTx.from = results[1];
return _this.provider.send('eth_sendTransaction', [hexTx]).then(function (hash) {
return web_1.poll(function () {
return _this.provider.getTransaction(hash).then(function (tx) {
if (tx === null) {
return undefined;
}
return _this.provider._wrapTransaction(tx, hash);
});
}, { onceBlock: _this.provider }).catch(function (error) {
error.transactionHash = hash;
throw error;
});
return hash;
}, function (error) {
if (error.responseText) {
// See: JsonRpcProvider.sendTransaction (@TODO: Expose a ._throwError??)
@@ -155,6 +145,22 @@ var JsonRpcSigner = /** @class */ (function (_super) {
});
});
};
JsonRpcSigner.prototype.sendTransaction = function (transaction) {
var _this = this;
return this.sendUncheckedTransaction(transaction).then(function (hash) {
return web_1.poll(function () {
return _this.provider.getTransaction(hash).then(function (tx) {
if (tx === null) {
return undefined;
}
return _this.provider._wrapTransaction(tx, hash);
});
}, { onceBlock: _this.provider }).catch(function (error) {
error.transactionHash = hash;
throw error;
});
});
};
JsonRpcSigner.prototype.signMessage = function (message) {
var _this = this;
var data = ((typeof (message) === 'string') ? utf8_1.toUtf8Bytes(message) : message);

View File

@@ -1 +1 @@
export const version = "4.0.17";
export const version = "4.0.20";

View File

@@ -411,7 +411,6 @@ export class Contract {
if (address == null) { throw new Error('name not found'); }
return address;
}).catch((error: Error) => {
console.log('ERROR: Cannot find Contract - ' + addressOrName);
throw error;
}));
} else {
@@ -429,7 +428,7 @@ export class Contract {
if ((<any>this)[name] == null) {
defineReadOnly(this, name, run);
} else {
console.log('WARNING: Multiple definitions for ' + name);
errors.warn('WARNING: Multiple definitions for ' + name);
}
if (this.functions[name] == null) {

View File

@@ -23,7 +23,7 @@ export const MISSING_NEW = 'MISSING_NEW';
export const CALL_EXCEPTION = 'CALL_EXCEPTION';
// Invalid argument (e.g. value is incompatible with type) to a function:
// - arg: The argument name that was invalid
// - argument: The argument name that was invalid
// - value: The value of the argument
export const INVALID_ARGUMENT = 'INVALID_ARGUMENT';
@@ -116,7 +116,7 @@ export function checkArgumentCount(count: number, expectedCount: number, suffix?
export function setCensorship(censorship: boolean, permanent?: boolean): void {
if (_permanentCensorErrors) {
throwError('error censorship permanent', UNSUPPORTED_OPERATION, { operation: 'setCersorship' });
throwError('error censorship permanent', UNSUPPORTED_OPERATION, { operation: 'setCensorship' });
}
_censorErrors = !!censorship;
@@ -141,3 +141,28 @@ export function checkNormalize(): void {
throwError('platform missing String.prototype.normalize', UNSUPPORTED_OPERATION, { operation: 'String.prototype.normalize', form: error.message });
}
}
const LogLevels: { [ name: string ]: number } = { debug: 1, "default": 2, info: 2, warn: 3, error: 4, off: 5 };
let LogLevel = LogLevels["default"];
export function setLogLevel(logLevel: string): void {
let level = LogLevels[logLevel];
if (level == null) {
warn("invliad log level - " + logLevel);
return;
}
LogLevel = level;
}
function log(logLevel: string, args: Array<any>): void {
if (LogLevel > LogLevels[logLevel]) { return; }
console.log.apply(console, args);
}
export function warn(...args: Array<any>): void {
log("warn", args);
}
export function info(...args: Array<any>): void {
log("info", args);
}

View File

@@ -78,7 +78,7 @@ export interface TransactionReceipt {
export type TransactionRequest = {
to?: string | Promise<string>,
from?: string | Promise<string>,
nonce?: number | string | Promise<number | string>,
nonce?: BigNumberish | Promise<BigNumberish>,
gasLimit?: BigNumberish | Promise<BigNumberish>,
gasPrice?: BigNumberish | Promise<BigNumberish>,

View File

@@ -1224,7 +1224,7 @@ export class BaseProvider extends Provider {
}
protected _startPending(): void {
console.log('WARNING: this provider does not support pending events');
errors.warn('WARNING: this provider does not support pending events');
}
protected _stopPending(): void {

View File

@@ -41,7 +41,7 @@ export class InfuraProvider extends JsonRpcProvider {
}
protected _startPending(): void {
console.log('WARNING: INFURA does not support pending filters');
errors.warn('WARNING: INFURA does not support pending filters');
}
getSigner(address?: string): JsonRpcSigner {

View File

@@ -34,7 +34,7 @@ function timer(timeout: number): Promise<any> {
function getResult(payload: { error?: { code?: number, data?: any, message?: string }, result?: any }): any {
if (payload.error) {
// @TODO: not any
var error: any = new Error(payload.error.message);
let error: any = new Error(payload.error.message);
error.code = payload.error.code;
error.data = payload.error.data;
throw error;
@@ -101,7 +101,7 @@ export class JsonRpcSigner extends Signer {
return this.provider.getTransactionCount(this.getAddress(), blockTag);
}
sendTransaction(transaction: TransactionRequest): Promise<TransactionResponse> {
sendUncheckedTransaction(transaction: TransactionRequest): Promise<string> {
transaction = shallowCopy(transaction);
let fromAddress = this.getAddress().then((address) => {
@@ -126,15 +126,7 @@ export class JsonRpcSigner extends Signer {
let hexTx = JsonRpcProvider.hexlifyTransaction(tx);
hexTx.from = results[1];
return this.provider.send('eth_sendTransaction', [ hexTx ]).then((hash) => {
return poll(() => {
return this.provider.getTransaction(hash).then((tx: TransactionResponse) => {
if (tx === null) { return undefined; }
return this.provider._wrapTransaction(tx, hash);
});
}, { onceBlock: this.provider }).catch((error: Error) => {
(<any>error).transactionHash = hash;
throw error;
});
return hash;
}, (error) => {
if (error.responseText) {
// See: JsonRpcProvider.sendTransaction (@TODO: Expose a ._throwError??)
@@ -159,8 +151,22 @@ export class JsonRpcSigner extends Signer {
});
}
sendTransaction(transaction: TransactionRequest): Promise<TransactionResponse> {
return this.sendUncheckedTransaction(transaction).then((hash) => {
return poll(() => {
return this.provider.getTransaction(hash).then((tx: TransactionResponse) => {
if (tx === null) { return undefined; }
return this.provider._wrapTransaction(tx, hash);
});
}, { onceBlock: this.provider }).catch((error: Error) => {
(<any>error).transactionHash = hash;
throw error;
});
});
}
signMessage(message: Arrayish | string): Promise<string> {
var data = ((typeof(message) === 'string') ? toUtf8Bytes(message): message);
let data = ((typeof(message) === 'string') ? toUtf8Bytes(message): message);
return this.getAddress().then((address) => {
// https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_sign
@@ -169,7 +175,7 @@ export class JsonRpcSigner extends Signer {
}
unlock(password: string): Promise<boolean> {
var provider = this.provider;
let provider = this.provider;
return this.getAddress().then(function(address) {
return provider.send('personal_unlockAccount', [ address.toLowerCase(), password, null ]);
@@ -334,9 +340,9 @@ export class JsonRpcProvider extends BaseProvider {
protected _startPending(): void {
if (this._pendingFilter != null) { return; }
var self = this;
let self = this;
var pendingFilter: Promise<number> = this.send('eth_newPendingTransactionFilter', []);
let pendingFilter: Promise<number> = this.send('eth_newPendingTransactionFilter', []);
this._pendingFilter = pendingFilter;
pendingFilter.then(function(filterId) {
@@ -344,7 +350,7 @@ export class JsonRpcProvider extends BaseProvider {
self.send('eth_getFilterChanges', [ filterId ]).then(function(hashes: Array<string>) {
if (self._pendingFilter != pendingFilter) { return null; }
var seq = Promise.resolve();
let seq = Promise.resolve();
hashes.forEach(function(hash) {
// @TODO: This should be garbage collected at some point... How? When?
self._emitted['t:' + hash.toLowerCase()] = 'pending';

View File

@@ -266,7 +266,7 @@ function parseSignatureEvent(fragment: string): EventFragment {
case '':
break;
default:
console.log('unknown modifier: ' + modifier);
errors.info('unknown modifier: ' + modifier);
}
});
@@ -336,7 +336,7 @@ function parseSignatureFunction(fragment: string): FunctionFragment {
case '':
break;
default:
console.log('unknown modifier: ' + modifier);
errors.info('unknown modifier: ' + modifier);
}
});

View File

@@ -47,7 +47,6 @@ function _bnify(value: BigNumber): BN.BN {
return new BN.BN(hex.substring(2), 16);
}
export type BigNumberish = BigNumber | string | number | Arrayish;
export class BigNumber implements Hexable {
@@ -108,6 +107,13 @@ export class BigNumber implements Hexable {
return toBigNumber(_bnify(this).toTwos(value));
}
abs(): BigNumber {
if (this._hex[0] === '-') {
return toBigNumber(_bnify(this).mul(BN_1));
}
return this;
}
add(other: BigNumberish): BigNumber {
return toBigNumber(_bnify(this).add(toBN(other)));
}

View File

@@ -1,5 +1,7 @@
'use strict';
import * as errors from '../errors';
import { concat, hexlify } from './bytes';
import { toUtf8Bytes } from './utf8';
import { keccak256 } from './keccak256';
@@ -11,11 +13,18 @@ import { Arrayish } from './bytes';
///////////////////////////////
var Zeros = new Uint8Array([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]);
var Partition = new RegExp("^((.*)\\.)?([^.]+)$");
var UseSTD3ASCIIRules = new RegExp("^[a-z0-9.-]*$");
const Zeros = new Uint8Array([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]);
const Partition = new RegExp("^((.*)\\.)?([^.]+)$");
const UseSTD3ASCIIRules = new RegExp("^[a-z0-9.-]*$");
export function namehash(name: string): string {
if (typeof(name) !== 'string') {
errors.throwError('invalid address - ' + String(name), errors.INVALID_ARGUMENT, {
argument: 'name',
value: name
});
}
name = name.toLowerCase();
// Supporting the full UTF-8 space requires additional (and large)
@@ -23,13 +32,16 @@ export function namehash(name: string): string {
// It should be fairly easy in the future to support systems with
// String.normalize, but that is future work.
if (!name.match(UseSTD3ASCIIRules)) {
throw new Error('contains invalid UseSTD3ASCIIRules characters');
errors.throwError('contains invalid UseSTD3ASCIIRules characters', errors.INVALID_ARGUMENT, {
argument: 'name',
value: name
});
}
var result: string | Uint8Array = Zeros;
let result: string | Uint8Array = Zeros;
while (name.length) {
var partition = name.match(Partition);
var label = toUtf8Bytes(partition[3]);
let partition = name.match(Partition);
let label = toUtf8Bytes(partition[3]);
result = keccak256(concat([result, keccak256(label)]));
name = partition[2] || '';
@@ -44,11 +56,10 @@ export function id(text: string): string {
}
export function hashMessage(message: Arrayish | string): string {
var payload = concat([
return keccak256(concat([
toUtf8Bytes('\x19Ethereum Signed Message:\n'),
toUtf8Bytes(String(message.length)),
((typeof(message) === 'string') ? toUtf8Bytes(message): message)
]);
return keccak256(payload);
]));
}

View File

@@ -4,7 +4,7 @@ import { AbiCoder, defaultAbiCoder, formatSignature, formatParamType, parseSigna
import { getAddress, getContractAddress, getIcapAddress } from './address';
import * as base64 from './base64';
import { BigNumber, bigNumberify } from './bignumber';
import { arrayify, concat, hexDataSlice, hexDataLength, hexlify, hexStripZeros, hexZeroPad, joinSignature, padZeros, splitSignature, stripZeros } from './bytes';
import { arrayify, concat, hexDataSlice, hexDataLength, hexlify, hexStripZeros, hexZeroPad, isHexString, joinSignature, padZeros, splitSignature, stripZeros } from './bytes';
import { hashMessage, id, namehash } from './hash';
import * as HDNode from './hdnode';
import { Interface } from './interface';
@@ -84,6 +84,7 @@ export {
bigNumberify,
hexlify,
isHexString,
hexStripZeros,
hexZeroPad,
hexDataLength,

View File

@@ -325,9 +325,13 @@ function addMethod(method: any): void {
sighash: sighash,
});
// Expose the first (and hopefully unique named function
if (method.name && this.functions[method.name] == null) {
defineReadOnly(this.functions, method.name, description);
// Expose the first (and hopefully unique named function)
if (method.name) {
if (this.functions[method.name] == null) {
defineReadOnly(this.functions, method.name, description);
} else {
errors.warn('WARNING: Multiple definitions for ' + method.name);
}
}
// Expose all methods by their signature, for overloaded functions
@@ -368,7 +372,7 @@ function addMethod(method: any): void {
break;
default:
console.log('WARNING: unsupported ABI type - ' + method.type);
errors.warn('WARNING: unsupported ABI type - ' + method.type);
break;
}
}

View File

@@ -162,7 +162,7 @@ export function parse(rawTransaction: Arrayish): Transaction {
tx.v = bigNumberify(transaction[6]).toNumber();
} catch (error) {
console.log(error);
errors.info(error);
return tx;
}
@@ -195,7 +195,7 @@ export function parse(rawTransaction: Arrayish): Transaction {
try {
tx.from = recoverAddress(digest, { r: hexlify(tx.r), s: hexlify(tx.s), recoveryParam: recoveryParam });
} catch (error) {
console.log(error);
errors.info(error);
}
tx.hash = keccak256(rawTransaction);

View File

@@ -62,7 +62,6 @@ export class Wallet extends AbstractSigner {
return new Wallet(this.signingKey, provider);
}
getAddress(): Promise<string> {
return Promise.resolve(this.address);
}
@@ -91,6 +90,13 @@ export class Wallet extends AbstractSigner {
}
sendTransaction(transaction: TransactionRequest): Promise<TransactionResponse> {
if (!this.provider) { throw new Error('missing provider'); }
if (transaction.nonce == null) {
transaction = shallowCopy(transaction);
transaction.nonce = this.getTransactionCount("pending");
}
return populateTransaction(transaction, this.provider, this.address).then((tx) => {
return this.sign(tx).then((signedTransaction) => {
return this.provider.sendTransaction(signedTransaction);

View File

@@ -327,3 +327,24 @@ describe('Test Bytes32String coder', function() {
assert.equal(str2, str, "parsed correctly");
});
});
describe('Test BigNumber', function() {
it("computes absoltue values", function() {
function testAbs(test) {
var value = ethers.utils.bigNumberify(test.value);
var expected = ethers.utils.bigNumberify(test.expected);
assert.ok(value.abs().eq(expected), 'BigNumber.abs - ' + test.value);
}
[
{ value: "0x0", expected: "0x0" },
{ value: "-0x0", expected: "0x0" },
{ value: "0x5", expected: "0x5" },
{ value: "-0x5", expected: "0x5" },
{ value: "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", expected: "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff" },
{ value: "-0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", expected: "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff" },
{ value: "0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", expected: "0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff" },
{ value: "-0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", expected: "0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff" },
].forEach(testAbs);
});
});

View File

@@ -6,6 +6,7 @@ export declare class BigNumber implements Hexable {
constructor(value: BigNumberish);
fromTwos(value: number): BigNumber;
toTwos(value: number): BigNumber;
abs(): BigNumber;
add(other: BigNumberish): BigNumber;
sub(other: BigNumberish): BigNumber;
div(other: BigNumberish): BigNumber;

View File

@@ -105,6 +105,12 @@ var BigNumber = /** @class */ (function () {
BigNumber.prototype.toTwos = function (value) {
return toBigNumber(_bnify(this).toTwos(value));
};
BigNumber.prototype.abs = function () {
if (this._hex[0] === '-') {
return toBigNumber(_bnify(this).mul(BN_1));
}
return this;
};
BigNumber.prototype.add = function (other) {
return toBigNumber(_bnify(this).add(toBN(other)));
};

View File

@@ -1,5 +1,13 @@
'use strict';
var __importStar = (this && this.__importStar) || function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (Object.hasOwnProperty.call(mod, k)) result[k] = mod[k];
result["default"] = mod;
return result;
};
Object.defineProperty(exports, "__esModule", { value: true });
var errors = __importStar(require("../errors"));
var bytes_1 = require("./bytes");
var utf8_1 = require("./utf8");
var keccak256_1 = require("./keccak256");
@@ -8,13 +16,22 @@ var Zeros = new Uint8Array([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
var Partition = new RegExp("^((.*)\\.)?([^.]+)$");
var UseSTD3ASCIIRules = new RegExp("^[a-z0-9.-]*$");
function namehash(name) {
if (typeof (name) !== 'string') {
errors.throwError('invalid address - ' + String(name), errors.INVALID_ARGUMENT, {
argument: 'name',
value: name
});
}
name = name.toLowerCase();
// Supporting the full UTF-8 space requires additional (and large)
// libraries, so for now we simply do not support them.
// It should be fairly easy in the future to support systems with
// String.normalize, but that is future work.
if (!name.match(UseSTD3ASCIIRules)) {
throw new Error('contains invalid UseSTD3ASCIIRules characters');
errors.throwError('contains invalid UseSTD3ASCIIRules characters', errors.INVALID_ARGUMENT, {
argument: 'name',
value: name
});
}
var result = Zeros;
while (name.length) {
@@ -31,11 +48,10 @@ function id(text) {
}
exports.id = id;
function hashMessage(message) {
var payload = bytes_1.concat([
return keccak256_1.keccak256(bytes_1.concat([
utf8_1.toUtf8Bytes('\x19Ethereum Signed Message:\n'),
utf8_1.toUtf8Bytes(String(message.length)),
((typeof (message) === 'string') ? utf8_1.toUtf8Bytes(message) : message)
]);
return keccak256_1.keccak256(payload);
]));
}
exports.hashMessage = hashMessage;

4
utils/index.d.ts vendored
View File

@@ -2,7 +2,7 @@ import { AbiCoder, defaultAbiCoder, formatSignature, formatParamType, parseSigna
import { getAddress, getContractAddress, getIcapAddress } from './address';
import * as base64 from './base64';
import { BigNumber, bigNumberify } from './bignumber';
import { arrayify, concat, hexDataSlice, hexDataLength, hexlify, hexStripZeros, hexZeroPad, joinSignature, padZeros, splitSignature, stripZeros } from './bytes';
import { arrayify, concat, hexDataSlice, hexDataLength, hexlify, hexStripZeros, hexZeroPad, isHexString, joinSignature, padZeros, splitSignature, stripZeros } from './bytes';
import { hashMessage, id, namehash } from './hash';
import * as HDNode from './hdnode';
import { Interface } from './interface';
@@ -32,4 +32,4 @@ import { Transaction, UnsignedTransaction } from './transaction';
import { ConnectionInfo, OnceBlockable, PollOptions } from './web';
import { EncryptOptions, ProgressCallback } from './secret-storage';
import { Wordlist } from './wordlist';
export { AbiCoder, defaultAbiCoder, formatSignature, formatParamType, parseSignature, parseParamType, RLP, fetchJson, getNetwork, checkProperties, deepCopy, defineReadOnly, resolveProperties, shallowCopy, arrayify, concat, padZeros, stripZeros, HDNode, SigningKey, Interface, base64, BigNumber, bigNumberify, hexlify, hexStripZeros, hexZeroPad, hexDataLength, hexDataSlice, toUtf8Bytes, toUtf8String, formatBytes32String, parseBytes32String, hashMessage, namehash, id, getAddress, getIcapAddress, getContractAddress, formatEther, parseEther, formatUnits, parseUnits, commify, keccak256, sha256, randomBytes, solidityPack, solidityKeccak256, soliditySha256, splitSignature, joinSignature, parseTransaction, populateTransaction, serializeTransaction, getJsonWalletAddress, computeAddress, computePublicKey, recoverAddress, recoverPublicKey, verifyMessage, SupportedAlgorithms, UnicodeNormalizationForm, CoerceFunc, EventFragment, FunctionFragment, ParamType, BigNumberish, Arrayish, Hexable, Signature, Indexed, DeployDescription, EventDescription, FunctionDescription, LogDescription, TransactionDescription, Network, Networkish, Transaction, UnsignedTransaction, ConnectionInfo, OnceBlockable, PollOptions, EncryptOptions, ProgressCallback, Wordlist, };
export { AbiCoder, defaultAbiCoder, formatSignature, formatParamType, parseSignature, parseParamType, RLP, fetchJson, getNetwork, checkProperties, deepCopy, defineReadOnly, resolveProperties, shallowCopy, arrayify, concat, padZeros, stripZeros, HDNode, SigningKey, Interface, base64, BigNumber, bigNumberify, hexlify, isHexString, hexStripZeros, hexZeroPad, hexDataLength, hexDataSlice, toUtf8Bytes, toUtf8String, formatBytes32String, parseBytes32String, hashMessage, namehash, id, getAddress, getIcapAddress, getContractAddress, formatEther, parseEther, formatUnits, parseUnits, commify, keccak256, sha256, randomBytes, solidityPack, solidityKeccak256, soliditySha256, splitSignature, joinSignature, parseTransaction, populateTransaction, serializeTransaction, getJsonWalletAddress, computeAddress, computePublicKey, recoverAddress, recoverPublicKey, verifyMessage, SupportedAlgorithms, UnicodeNormalizationForm, CoerceFunc, EventFragment, FunctionFragment, ParamType, BigNumberish, Arrayish, Hexable, Signature, Indexed, DeployDescription, EventDescription, FunctionDescription, LogDescription, TransactionDescription, Network, Networkish, Transaction, UnsignedTransaction, ConnectionInfo, OnceBlockable, PollOptions, EncryptOptions, ProgressCallback, Wordlist, };

View File

@@ -31,6 +31,7 @@ exports.hexDataLength = bytes_1.hexDataLength;
exports.hexlify = bytes_1.hexlify;
exports.hexStripZeros = bytes_1.hexStripZeros;
exports.hexZeroPad = bytes_1.hexZeroPad;
exports.isHexString = bytes_1.isHexString;
exports.joinSignature = bytes_1.joinSignature;
exports.padZeros = bytes_1.padZeros;
exports.splitSignature = bytes_1.splitSignature;

View File

@@ -249,6 +249,7 @@ function addMethod(method) {
gas: method.gas,
payable: (method.payable == null || !!method.payable),
type: ((method.constant) ? 'call' : 'transaction'),
name: method.name,
signature: signature,
sighash: sighash,
});
@@ -339,7 +340,7 @@ var Interface = /** @class */ (function () {
return new _TransactionDescription({
args: result,
decode: func.decode,
name: name,
name: func.name,
signature: func.signature,
sighash: func.sighash,
value: bignumber_1.bigNumberify(tx.value || '0'),

View File

@@ -99,6 +99,9 @@ function fetchJson(connection, json, processFunc) {
var jsonError = new Error('invalid json response');
jsonError.orginialError = error;
jsonError.responseText = request.responseText;
if (json != null) {
jsonError.requestBody = json;
}
jsonError.url = url;
reject(jsonError);
return;
@@ -124,7 +127,7 @@ function fetchJson(connection, json, processFunc) {
reject(error);
};
try {
if (json) {
if (json != null) {
request.send(json);
}
else {

View File

@@ -103,6 +103,13 @@ var Wallet = /** @class */ (function (_super) {
};
Wallet.prototype.sendTransaction = function (transaction) {
var _this = this;
if (!this.provider) {
throw new Error('missing provider');
}
if (transaction.nonce == null) {
transaction = properties_1.shallowCopy(transaction);
transaction.nonce = this.getTransactionCount("pending");
}
return transaction_1.populateTransaction(transaction, this.provider, this.address).then(function (tx) {
return _this.sign(tx).then(function (signedTransaction) {
return _this.provider.sendTransaction(signedTransaction);