Compare commits

..

6 Commits

Author SHA1 Message Date
Richard Moore
f318fd9cf1 Added fastRetry to polling for JsonRpcSigner to improve polling for sent transactions (#402). 2019-02-15 13:42:12 -05:00
Richard Moore
c15a89832b Fix waitForTransaction delay (#424). 2019-02-15 13:32:08 -05:00
Richard Moore
94b0abc240 Updated dist files. 2019-02-12 00:56:38 -05:00
Richard Moore
72edcd054f Fixed waitForTransaction and removeListener (#410). 2019-02-12 00:54:32 -05:00
Richard Moore
e4a2f8ac6c Updated BIP39 list in readme. 2019-02-11 19:24:48 -05:00
Richard Moore
c6d7b31a84 Updated dist files. 2019-02-11 19:24:27 -05:00
17 changed files with 122 additions and 79 deletions

View File

@@ -9,7 +9,7 @@ Complete Ethereum wallet implementation and utilities in JavaScript (and TypeScr
- Keep your private keys in your client, **safe** and sound
- Import and export **JSON wallets** (Geth, Parity and crowdsale)
- Import and export BIP 39 **mnemonic phrases** (12 word backup phrases) and **HD Wallets** (English, Italian, Japanese, Korean, Simplified Chinese, Traditional Chinese; more coming soon)
- Import and export BIP 39 **mnemonic phrases** (12 word backup phrases) and **HD Wallets** (English, French, Italian, Japanese, Korean, Simplified Chinese, Spanish, Traditional Chinese)
- Meta-classes create JavaScript objects from any contract ABI, including **ABIv2** and **Human-Readable ABI**
- Connect to Ethereum nodes over [JSON-RPC](https://github.com/ethereum/wiki/wiki/JSON-RPC), [INFURA](https://infura.io), [Etherscan](https://etherscan.io), or [MetaMask](https://metamask.io)
- **ENS names** are first-class citizens; they can be used anywhere an Ethereum addresses can be used

2
_version.d.ts vendored
View File

@@ -1 +1 @@
export declare const version = "4.0.24";
export declare const version = "4.0.25";

View File

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

5
contract.d.ts vendored
View File

@@ -1,7 +1,7 @@
import { BigNumber } from './utils/bignumber';
import { Indexed, Interface } from './utils/interface';
import { UnsignedTransaction } from './utils/transaction';
import { Provider } from './providers/abstract-provider';
import { BlockTag, Provider } from './providers/abstract-provider';
import { Signer } from './abstract-signer';
import { Arrayish } from './utils/bytes';
import { ParamType } from './utils/abi-coder';
@@ -50,9 +50,10 @@ export declare class Contract {
readonly [name: string]: ContractFunction | any;
readonly addressPromise: Promise<string>;
readonly deployTransaction: TransactionResponse;
private _deployed;
private _deployedPromise;
constructor(addressOrName: string, contractInterface: Array<string | ParamType> | string | Interface, signerOrProvider: Signer | Provider);
deployed(): Promise<Contract>;
_deployed(blockTag?: BlockTag): Promise<Contract>;
fallback(overrides?: TransactionRequest): Promise<TransactionResponse>;
connect(signerOrProvider: Signer | Provider | string): Contract;
attach(addressOrName: string): Contract;

View File

@@ -135,8 +135,7 @@ function runMethod(contract, functionName, estimateOnly) {
errors.throwError('cannot override ' + key, errors.UNSUPPORTED_OPERATION, { operation: key });
}
});
// Send to the contract address (after checking the contract is deployed)
tx.to = contract.deployed().then(function () {
tx.to = contract._deployed(blockTag).then(function () {
return contract.addressPromise;
});
return resolveAddresses(contract.provider, params, method.inputs).then(function (params) {
@@ -332,11 +331,14 @@ var Contract = /** @class */ (function () {
}
// @TODO: Allow timeout?
Contract.prototype.deployed = function () {
return this._deployed();
};
Contract.prototype._deployed = function (blockTag) {
var _this = this;
if (!this._deployed) {
if (!this._deployedPromise) {
// If we were just deployed, we know the transaction we should occur in
if (this.deployTransaction) {
this._deployed = this.deployTransaction.wait().then(function () {
this._deployedPromise = this.deployTransaction.wait().then(function () {
return _this;
});
}
@@ -344,7 +346,7 @@ var Contract = /** @class */ (function () {
// @TODO: Once we allow a timeout to be passed in, we will wait
// up to that many blocks for getCode
// Otherwise, poll for our code to be deployed
this._deployed = this.provider.getCode(this.address).then(function (code) {
this._deployedPromise = this.provider.getCode(this.address, blockTag).then(function (code) {
if (code === '0x') {
errors.throwError('contract not deployed', errors.UNSUPPORTED_OPERATION, {
contractAddress: _this.address,
@@ -355,7 +357,7 @@ var Contract = /** @class */ (function () {
});
}
}
return this._deployed;
return this._deployedPromise;
};
// @TODO:
// estimateFallback(overrides?: TransactionRequest): Promise<BigNumber>

58
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.24";
exports.version = "4.0.25";
},{}],2:[function(require,module,exports){
"use strict";
@@ -183,8 +183,7 @@ function runMethod(contract, functionName, estimateOnly) {
errors.throwError('cannot override ' + key, errors.UNSUPPORTED_OPERATION, { operation: key });
}
});
// Send to the contract address (after checking the contract is deployed)
tx.to = contract.deployed().then(function () {
tx.to = contract._deployed(blockTag).then(function () {
return contract.addressPromise;
});
return resolveAddresses(contract.provider, params, method.inputs).then(function (params) {
@@ -380,11 +379,14 @@ var Contract = /** @class */ (function () {
}
// @TODO: Allow timeout?
Contract.prototype.deployed = function () {
return this._deployed();
};
Contract.prototype._deployed = function (blockTag) {
var _this = this;
if (!this._deployed) {
if (!this._deployedPromise) {
// If we were just deployed, we know the transaction we should occur in
if (this.deployTransaction) {
this._deployed = this.deployTransaction.wait().then(function () {
this._deployedPromise = this.deployTransaction.wait().then(function () {
return _this;
});
}
@@ -392,7 +394,7 @@ var Contract = /** @class */ (function () {
// @TODO: Once we allow a timeout to be passed in, we will wait
// up to that many blocks for getCode
// Otherwise, poll for our code to be deployed
this._deployed = this.provider.getCode(this.address).then(function (code) {
this._deployedPromise = this.provider.getCode(this.address, blockTag).then(function (code) {
if (code === '0x') {
errors.throwError('contract not deployed', errors.UNSUPPORTED_OPERATION, {
contractAddress: _this.address,
@@ -403,7 +405,7 @@ var Contract = /** @class */ (function () {
});
}
}
return this._deployed;
return this._deployedPromise;
};
// @TODO:
// estimateFallback(overrides?: TransactionRequest): Promise<BigNumber>
@@ -10710,17 +10712,19 @@ var BaseProvider = /** @class */ (function (_super) {
if (confirmations == null) {
confirmations = 1;
}
return web_1.poll(function () {
return _this.getTransactionReceipt(transactionHash).then(function (receipt) {
if (confirmations === 0) {
return receipt;
if (confirmations === 0) {
return this.getTransactionReceipt(transactionHash);
}
return new Promise(function (resolve) {
var handler = function (receipt) {
if (receipt.confirmations < confirmations) {
return;
}
if (receipt == null || receipt.confirmations < confirmations) {
return undefined;
}
return receipt;
});
}, { onceBlock: this });
_this.removeListener(transactionHash, handler);
resolve(receipt);
};
_this.on(transactionHash, handler);
});
};
BaseProvider.prototype.getBlockNumber = function () {
var _this = this;
@@ -11223,13 +11227,19 @@ var BaseProvider = /** @class */ (function (_super) {
});
};
BaseProvider.prototype.removeAllListeners = function (eventName) {
var eventTag = getEventTag(eventName);
this._events = this._events.filter(function (event) {
return (event.tag !== eventTag);
});
if (eventName === 'pending') {
if (eventName == null) {
this._events = [];
this._stopPending();
}
else {
var eventTag_1 = getEventTag(eventName);
this._events = this._events.filter(function (event) {
return (event.tag !== eventTag_1);
});
if (eventName === 'pending') {
this._stopPending();
}
}
if (this._events.length === 0) {
this.polling = false;
}
@@ -11239,13 +11249,13 @@ var BaseProvider = /** @class */ (function (_super) {
var found = false;
var eventTag = getEventTag(eventName);
this._events = this._events.filter(function (event) {
if (event.tag !== eventTag) {
if (event.tag !== eventTag || event.listener != listener) {
return true;
}
if (found) {
return true;
}
found = false;
found = true;
return false;
});
if (eventName === 'pending' && this.listenerCount('pending') === 0) {

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

View File

@@ -26,7 +26,7 @@ declare module 'ethers/contract' {
import { BigNumber } from 'ethers/utils/bignumber';
import { Indexed, Interface } from 'ethers/utils/interface';
import { UnsignedTransaction } from 'ethers/utils/transaction';
import { Provider } from 'ethers/providers/abstract-provider';
import { BlockTag, Provider } from 'ethers/providers/abstract-provider';
import { Signer } from 'ethers/abstract-signer';
import { Arrayish } from 'ethers/utils/bytes';
import { ParamType } from 'ethers/utils/abi-coder';
@@ -77,6 +77,7 @@ declare module 'ethers/contract' {
readonly deployTransaction: TransactionResponse;
constructor(addressOrName: string, contractInterface: Array<string | ParamType> | string | Interface, signerOrProvider: Signer | Provider);
deployed(): Promise<Contract>;
_deployed(blockTag?: BlockTag): Promise<Contract>;
fallback(overrides?: TransactionRequest): Promise<TransactionResponse>;
connect(signerOrProvider: Signer | Provider | string): Contract;
attach(addressOrName: string): Contract;
@@ -265,7 +266,7 @@ declare module 'ethers/utils/shims' {
}
declare module 'ethers/_version' {
export const version = "4.0.24";
export const version = "4.0.25";
}
declare module 'ethers/utils/bignumber' {
@@ -783,7 +784,7 @@ declare module 'ethers/providers/base-provider' {
emit(eventName: EventType, ...args: Array<any>): boolean;
listenerCount(eventName?: EventType): number;
listeners(eventName: EventType): Array<Listener>;
removeAllListeners(eventName: EventType): Provider;
removeAllListeners(eventName?: EventType): Provider;
removeListener(eventName: EventType, listener: Listener): Provider;
}
}

2
package-lock.json generated
View File

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

View File

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

View File

@@ -69,6 +69,6 @@ export declare class BaseProvider extends Provider {
emit(eventName: EventType, ...args: Array<any>): boolean;
listenerCount(eventName?: EventType): number;
listeners(eventName: EventType): Array<Listener>;
removeAllListeners(eventName: EventType): Provider;
removeAllListeners(eventName?: EventType): Provider;
removeListener(eventName: EventType, listener: Listener): Provider;
}

View File

@@ -656,17 +656,19 @@ var BaseProvider = /** @class */ (function (_super) {
if (confirmations == null) {
confirmations = 1;
}
return web_1.poll(function () {
return _this.getTransactionReceipt(transactionHash).then(function (receipt) {
if (confirmations === 0) {
return receipt;
if (confirmations === 0) {
return this.getTransactionReceipt(transactionHash);
}
return new Promise(function (resolve) {
var handler = function (receipt) {
if (receipt.confirmations < confirmations) {
return;
}
if (receipt == null || receipt.confirmations < confirmations) {
return undefined;
}
return receipt;
});
}, { onceBlock: this });
_this.removeListener(transactionHash, handler);
resolve(receipt);
};
_this.on(transactionHash, handler);
});
};
BaseProvider.prototype.getBlockNumber = function () {
var _this = this;
@@ -1169,13 +1171,19 @@ var BaseProvider = /** @class */ (function (_super) {
});
};
BaseProvider.prototype.removeAllListeners = function (eventName) {
var eventTag = getEventTag(eventName);
this._events = this._events.filter(function (event) {
return (event.tag !== eventTag);
});
if (eventName === 'pending') {
if (eventName == null) {
this._events = [];
this._stopPending();
}
else {
var eventTag_1 = getEventTag(eventName);
this._events = this._events.filter(function (event) {
return (event.tag !== eventTag_1);
});
if (eventName === 'pending') {
this._stopPending();
}
}
if (this._events.length === 0) {
this.polling = false;
}
@@ -1185,13 +1193,13 @@ var BaseProvider = /** @class */ (function (_super) {
var found = false;
var eventTag = getEventTag(eventName);
this._events = this._events.filter(function (event) {
if (event.tag !== eventTag) {
if (event.tag !== eventTag || event.listener != listener) {
return true;
}
if (found) {
return true;
}
found = false;
found = true;
return false;
});
if (eventName === 'pending' && this.listenerCount('pending') === 0) {

View File

@@ -1 +1 @@
export const version = "4.0.24";
export const version = "4.0.25";

View File

@@ -776,15 +776,21 @@ export class BaseProvider extends Provider {
waitForTransaction(transactionHash: string, confirmations?: number): Promise<TransactionReceipt> {
if (confirmations == null) { confirmations = 1; }
return poll(() => {
return this.getTransactionReceipt(transactionHash).then((receipt) => {
if (confirmations === 0) { return receipt; }
if (receipt == null || receipt.confirmations < confirmations) {
return undefined;
}
return this.getTransactionReceipt(transactionHash).then((receipt) => {
if (confirmations === 0 || (receipt && receipt.confirmations >= confirmations)) {
return receipt;
});
}, { onceBlock: this });
}
return <Promise<TransactionReceipt>>(new Promise((resolve) => {
let handler = (receipt: TransactionReceipt) => {
if (receipt.confirmations < confirmations) { return; }
this.removeListener(transactionHash, handler);
resolve(receipt);
}
this.on(transactionHash, handler);
}));
});
}
getBlockNumber(): Promise<number> {
@@ -1306,13 +1312,18 @@ export class BaseProvider extends Provider {
});
}
removeAllListeners(eventName: EventType): Provider {
let eventTag = getEventTag(eventName);
this._events = this._events.filter((event) => {
return (event.tag !== eventTag);
});
removeAllListeners(eventName?: EventType): Provider {
if (eventName == null) {
this._events = [ ];
this._stopPending();
} else {
let eventTag = getEventTag(eventName);
this._events = this._events.filter((event) => {
return (event.tag !== eventTag);
});
if (eventName === 'pending') { this._stopPending(); }
}
if (eventName === 'pending') { this._stopPending(); }
if (this._events.length === 0) { this.polling = false; }
return this;
@@ -1323,9 +1334,9 @@ export class BaseProvider extends Provider {
let eventTag = getEventTag(eventName);
this._events = this._events.filter((event) => {
if (event.tag !== eventTag) { return true; }
if (event.tag !== eventTag || event.listener != listener) { return true; }
if (found) { return true; }
found = false;
found = true;
return false;
});

View File

@@ -158,7 +158,7 @@ export class JsonRpcSigner extends Signer {
if (tx === null) { return undefined; }
return this.provider._wrapTransaction(tx, hash);
});
}, { onceBlock: this.provider }).catch((error: Error) => {
}, { fastRetry: 250, onceBlock: this.provider }).catch((error: Error) => {
(<any>error).transactionHash = hash;
throw error;
});

View File

@@ -28,7 +28,8 @@ export type PollOptions = {
floor?: number,
ceiling?: number,
interval?: number,
onceBlock?: OnceBlockable
onceBlock?: OnceBlockable,
fastRetry?: number
};
@@ -208,6 +209,8 @@ export function poll(func: () => Promise<any>, options?: PollOptions): Promise<a
}, options.timeout)
}
let fastTimeout = options.fastRetry || null;
let attempt = 0;
function check() {
return func().then(function(result) {
@@ -227,6 +230,13 @@ export function poll(func: () => Promise<any>, options?: PollOptions): Promise<a
if (timeout < options.floor) { timeout = options.floor; }
if (timeout > options.ceiling) { timeout = options.ceiling; }
// Fast Timeout, means we quickly try again the first time
if (fastTimeout) {
attempt--;
timeout = fastTimeout;
fastTimeout = null;
}
setTimeout(check, timeout);
}