forked from tornado-packages/ethers.js
Compare commits
7 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
493273d698 | ||
|
|
84344ac4c2 | ||
|
|
9b118af304 | ||
|
|
e39e2ed718 | ||
|
|
71f781d542 | ||
|
|
b2db10e216 | ||
|
|
3736a15714 |
2
_version.d.ts
vendored
2
_version.d.ts
vendored
@@ -1 +1 @@
|
||||
export declare const version = "4.0.2";
|
||||
export declare const version = "4.0.4";
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.version = "4.0.2";
|
||||
exports.version = "4.0.4";
|
||||
|
||||
6
contract.d.ts
vendored
6
contract.d.ts
vendored
@@ -21,6 +21,12 @@ export interface Event extends Log {
|
||||
getTransaction: () => Promise<TransactionResponse>;
|
||||
getTransactionReceipt: () => Promise<TransactionReceipt>;
|
||||
}
|
||||
export interface ContractReceipt extends TransactionReceipt {
|
||||
events?: Array<Event>;
|
||||
}
|
||||
export interface ContractTransaction extends TransactionResponse {
|
||||
wait(confirmations?: number): Promise<ContractReceipt>;
|
||||
}
|
||||
export declare class VoidSigner extends Signer {
|
||||
readonly address: string;
|
||||
constructor(address: string, provider: Provider);
|
||||
|
||||
32
contract.js
32
contract.js
@@ -106,6 +106,7 @@ function resolveAddresses(provider, value, paramType) {
|
||||
function runMethod(contract, functionName, estimateOnly) {
|
||||
var method = contract.interface.functions[functionName];
|
||||
return function () {
|
||||
var _this = this;
|
||||
var params = [];
|
||||
for (var _i = 0; _i < arguments.length; _i++) {
|
||||
params[_i] = arguments[_i];
|
||||
@@ -206,7 +207,36 @@ function runMethod(contract, functionName, estimateOnly) {
|
||||
if (tx.from != null) {
|
||||
errors.throwError('cannot override from in a transaction', errors.UNSUPPORTED_OPERATION, { operation: 'sendTransaction' });
|
||||
}
|
||||
return contract.signer.sendTransaction(tx);
|
||||
return contract.signer.sendTransaction(tx).then(function (tx) {
|
||||
var wait = tx.wait.bind(tx);
|
||||
tx.wait = function (confirmations) {
|
||||
return wait(confirmations).then(function (receipt) {
|
||||
receipt.events = receipt.logs.map(function (log) {
|
||||
var event = properties_1.deepCopy(log);
|
||||
var parsed = _this.interface.parseLog(log);
|
||||
if (parsed) {
|
||||
event.args = parsed.values;
|
||||
event.decode = parsed.decode;
|
||||
event.event = parsed.name;
|
||||
event.eventSignature = parsed.signature;
|
||||
}
|
||||
event.removeListener = function () { return _this.provider; };
|
||||
event.getBlock = function () {
|
||||
return _this.provider.getBlock(receipt.blockHash);
|
||||
};
|
||||
event.getTransaction = function () {
|
||||
return _this.provider.getTransaction(receipt.transactionHash);
|
||||
};
|
||||
event.getTransactionReceipt = function () {
|
||||
return Promise.resolve(receipt);
|
||||
};
|
||||
return event;
|
||||
});
|
||||
return receipt;
|
||||
});
|
||||
};
|
||||
return tx;
|
||||
});
|
||||
}
|
||||
throw new Error('invalid type - ' + method.type);
|
||||
return null;
|
||||
|
||||
209
dist/ethers.js
vendored
209
dist/ethers.js
vendored
@@ -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.2";
|
||||
exports.version = "4.0.4";
|
||||
|
||||
},{}],2:[function(require,module,exports){
|
||||
"use strict";
|
||||
@@ -154,6 +154,7 @@ function resolveAddresses(provider, value, paramType) {
|
||||
function runMethod(contract, functionName, estimateOnly) {
|
||||
var method = contract.interface.functions[functionName];
|
||||
return function () {
|
||||
var _this = this;
|
||||
var params = [];
|
||||
for (var _i = 0; _i < arguments.length; _i++) {
|
||||
params[_i] = arguments[_i];
|
||||
@@ -254,7 +255,36 @@ function runMethod(contract, functionName, estimateOnly) {
|
||||
if (tx.from != null) {
|
||||
errors.throwError('cannot override from in a transaction', errors.UNSUPPORTED_OPERATION, { operation: 'sendTransaction' });
|
||||
}
|
||||
return contract.signer.sendTransaction(tx);
|
||||
return contract.signer.sendTransaction(tx).then(function (tx) {
|
||||
var wait = tx.wait.bind(tx);
|
||||
tx.wait = function (confirmations) {
|
||||
return wait(confirmations).then(function (receipt) {
|
||||
receipt.events = receipt.logs.map(function (log) {
|
||||
var event = properties_1.deepCopy(log);
|
||||
var parsed = _this.interface.parseLog(log);
|
||||
if (parsed) {
|
||||
event.args = parsed.values;
|
||||
event.decode = parsed.decode;
|
||||
event.event = parsed.name;
|
||||
event.eventSignature = parsed.signature;
|
||||
}
|
||||
event.removeListener = function () { return _this.provider; };
|
||||
event.getBlock = function () {
|
||||
return _this.provider.getBlock(receipt.blockHash);
|
||||
};
|
||||
event.getTransaction = function () {
|
||||
return _this.provider.getTransaction(receipt.transactionHash);
|
||||
};
|
||||
event.getTransactionReceipt = function () {
|
||||
return Promise.resolve(receipt);
|
||||
};
|
||||
return event;
|
||||
});
|
||||
return receipt;
|
||||
});
|
||||
};
|
||||
return tx;
|
||||
});
|
||||
}
|
||||
throw new Error('invalid type - ' + method.type);
|
||||
return null;
|
||||
@@ -9958,6 +9988,7 @@ var formatTransaction = {
|
||||
blockHash: allowNull(checkHash, null),
|
||||
blockNumber: allowNull(checkNumber, null),
|
||||
transactionIndex: allowNull(checkNumber, null),
|
||||
confirmations: allowNull(checkNumber, null),
|
||||
from: address_1.getAddress,
|
||||
gasPrice: bignumber_1.bigNumberify,
|
||||
gasLimit: bignumber_1.bigNumberify,
|
||||
@@ -10086,6 +10117,7 @@ var formatTransactionReceipt = {
|
||||
transactionHash: checkHash,
|
||||
logs: arrayOf(checkTransactionReceiptLog),
|
||||
blockNumber: checkNumber,
|
||||
confirmations: allowNull(checkNumber, null),
|
||||
cumulativeGasUsed: bignumber_1.bigNumberify,
|
||||
status: allowNull(checkNumber)
|
||||
};
|
||||
@@ -10196,6 +10228,11 @@ function getEventTag(eventName) {
|
||||
}
|
||||
throw new Error('invalid event - ' + eventName);
|
||||
}
|
||||
//////////////////////////////
|
||||
// Helper Object
|
||||
function getTime() {
|
||||
return (new Date()).getTime();
|
||||
}
|
||||
var BaseProvider = /** @class */ (function (_super) {
|
||||
__extends(BaseProvider, _super);
|
||||
function BaseProvider(network) {
|
||||
@@ -10228,11 +10265,13 @@ var BaseProvider = /** @class */ (function (_super) {
|
||||
// until we get a response. This provides devs with a consistent view. Similarly for
|
||||
// transaction hashes.
|
||||
_this._emitted = { block: _this._lastBlockNumber };
|
||||
_this._fastQueryDate = 0;
|
||||
return _this;
|
||||
}
|
||||
BaseProvider.prototype._doPoll = function () {
|
||||
var _this = this;
|
||||
this.getBlockNumber().then(function (blockNumber) {
|
||||
_this._setFastBlockNumber(blockNumber);
|
||||
// If the block hasn't changed, meh.
|
||||
if (blockNumber === _this._lastBlockNumber) {
|
||||
return;
|
||||
@@ -10382,13 +10421,44 @@ var BaseProvider = /** @class */ (function (_super) {
|
||||
enumerable: true,
|
||||
configurable: true
|
||||
});
|
||||
BaseProvider.prototype._getFastBlockNumber = function () {
|
||||
var _this = this;
|
||||
var now = getTime();
|
||||
// Stale block number, request a newer value
|
||||
if ((now - this._fastQueryDate) > 2 * this._pollingInterval) {
|
||||
this._fastQueryDate = now;
|
||||
this._fastBlockNumberPromise = this.getBlockNumber().then(function (blockNumber) {
|
||||
if (_this._fastBlockNumber == null || blockNumber > _this._fastBlockNumber) {
|
||||
_this._fastBlockNumber = blockNumber;
|
||||
}
|
||||
return _this._fastBlockNumber;
|
||||
});
|
||||
}
|
||||
return this._fastBlockNumberPromise;
|
||||
};
|
||||
BaseProvider.prototype._setFastBlockNumber = function (blockNumber) {
|
||||
// Older block, maybe a stale request
|
||||
if (this._fastBlockNumber != null && blockNumber < this._fastBlockNumber) {
|
||||
return;
|
||||
}
|
||||
// Update the time we updated the blocknumber
|
||||
this._fastQueryDate = getTime();
|
||||
// Newer block number, use it
|
||||
if (this._fastBlockNumber == null || blockNumber > this._fastBlockNumber) {
|
||||
this._fastBlockNumber = blockNumber;
|
||||
this._fastBlockNumberPromise = Promise.resolve(blockNumber);
|
||||
}
|
||||
};
|
||||
// @TODO: Add .poller which must be an event emitter with a 'start', 'stop' and 'block' event;
|
||||
// this will be used once we move to the WebSocket or other alternatives to polling
|
||||
BaseProvider.prototype.waitForTransaction = function (transactionHash, timeout) {
|
||||
BaseProvider.prototype.waitForTransaction = function (transactionHash, confirmations) {
|
||||
var _this = this;
|
||||
if (!confirmations) {
|
||||
confirmations = 1;
|
||||
}
|
||||
return web_1.poll(function () {
|
||||
return _this.getTransactionReceipt(transactionHash).then(function (receipt) {
|
||||
if (receipt == null) {
|
||||
if (receipt == null || receipt.confirmations < confirmations) {
|
||||
return undefined;
|
||||
}
|
||||
return receipt;
|
||||
@@ -10403,6 +10473,7 @@ var BaseProvider = /** @class */ (function (_super) {
|
||||
if (value != result) {
|
||||
throw new Error('invalid response - getBlockNumber');
|
||||
}
|
||||
_this._setFastBlockNumber(value);
|
||||
return value;
|
||||
});
|
||||
});
|
||||
@@ -10496,7 +10567,7 @@ var BaseProvider = /** @class */ (function (_super) {
|
||||
// This should be called by any subclass wrapping a TransactionResponse
|
||||
BaseProvider.prototype._wrapTransaction = function (tx, hash) {
|
||||
var _this = this;
|
||||
if (bytes_1.hexDataLength(hash) !== 32) {
|
||||
if (hash != null && bytes_1.hexDataLength(hash) !== 32) {
|
||||
throw new Error('invalid response - sendTransaction');
|
||||
}
|
||||
var result = tx;
|
||||
@@ -10506,11 +10577,11 @@ var BaseProvider = /** @class */ (function (_super) {
|
||||
}
|
||||
this._emitted['t:' + tx.hash] = 'pending';
|
||||
// @TODO: (confirmations? number, timeout? number)
|
||||
result.wait = function () {
|
||||
return _this.waitForTransaction(hash).then(function (receipt) {
|
||||
result.wait = function (confirmations) {
|
||||
return _this.waitForTransaction(tx.hash, confirmations).then(function (receipt) {
|
||||
if (receipt.status === 0) {
|
||||
errors.throwError('transaction failed', errors.CALL_EXCEPTION, {
|
||||
transactionHash: hash,
|
||||
transactionHash: tx.hash,
|
||||
transaction: tx
|
||||
});
|
||||
}
|
||||
@@ -10612,7 +10683,22 @@ var BaseProvider = /** @class */ (function (_super) {
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
return BaseProvider.checkTransactionResponse(result);
|
||||
var tx = BaseProvider.checkTransactionResponse(result);
|
||||
if (tx.blockNumber == null) {
|
||||
tx.confirmations = 0;
|
||||
}
|
||||
else if (tx.confirmations == null) {
|
||||
return _this._getFastBlockNumber().then(function (blockNumber) {
|
||||
// Add the confirmations using the fast block number (pessimistic)
|
||||
var confirmations = (blockNumber - tx.blockNumber) + 1;
|
||||
if (confirmations <= 0) {
|
||||
confirmations = 1;
|
||||
}
|
||||
tx.confirmations = confirmations;
|
||||
return _this._wrapTransaction(tx);
|
||||
});
|
||||
}
|
||||
return _this._wrapTransaction(tx);
|
||||
});
|
||||
}, { onceBlock: _this });
|
||||
});
|
||||
@@ -10632,7 +10718,26 @@ var BaseProvider = /** @class */ (function (_super) {
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
return checkTransactionReceipt(result);
|
||||
// "geth-etc" returns receipts before they are ready
|
||||
if (result.blockHash == null) {
|
||||
return undefined;
|
||||
}
|
||||
var receipt = checkTransactionReceipt(result);
|
||||
if (receipt.blockNumber == null) {
|
||||
receipt.confirmations = 0;
|
||||
}
|
||||
else if (receipt.confirmations == null) {
|
||||
return _this._getFastBlockNumber().then(function (blockNumber) {
|
||||
// Add the confirmations using the fast block number (pessimistic)
|
||||
var confirmations = (blockNumber - receipt.blockNumber) + 1;
|
||||
if (confirmations <= 0) {
|
||||
confirmations = 1;
|
||||
}
|
||||
receipt.confirmations = confirmations;
|
||||
return receipt;
|
||||
});
|
||||
}
|
||||
return receipt;
|
||||
});
|
||||
}, { onceBlock: _this });
|
||||
});
|
||||
@@ -11035,17 +11140,19 @@ var EtherscanProvider = /** @class */ (function (_super) {
|
||||
url += '/api?module=proxy&action=eth_sendRawTransaction&hex=' + params.signedTransaction;
|
||||
url += apiKey;
|
||||
return web_1.fetchJson(url, null, getJsonResult).catch(function (error) {
|
||||
// "Insufficient funds. The account you tried to send transaction from does not have enough funds. Required 21464000000000 and got: 0"
|
||||
if (error.responseText.toLowerCase().indexOf('insufficient funds') >= 0) {
|
||||
errors.throwError('insufficient funds', errors.INSUFFICIENT_FUNDS, {});
|
||||
}
|
||||
// "Transaction with the same hash was already imported."
|
||||
if (error.responseText.indexOf('same hash was already imported') >= 0) {
|
||||
errors.throwError('nonce has already been used', errors.NONCE_EXPIRED, {});
|
||||
}
|
||||
// "Transaction gas price is too low. There is another transaction with same nonce in the queue. Try increasing the gas price or incrementing the nonce."
|
||||
if (error.responseText.indexOf('another transaction with same nonce') >= 0) {
|
||||
errors.throwError('replacement fee too low', errors.REPLACEMENT_UNDERPRICED, {});
|
||||
if (error.responseText) {
|
||||
// "Insufficient funds. The account you tried to send transaction from does not have enough funds. Required 21464000000000 and got: 0"
|
||||
if (error.responseText.toLowerCase().indexOf('insufficient funds') >= 0) {
|
||||
errors.throwError('insufficient funds', errors.INSUFFICIENT_FUNDS, {});
|
||||
}
|
||||
// "Transaction with the same hash was already imported."
|
||||
if (error.responseText.indexOf('same hash was already imported') >= 0) {
|
||||
errors.throwError('nonce has already been used', errors.NONCE_EXPIRED, {});
|
||||
}
|
||||
// "Transaction gas price is too low. There is another transaction with same nonce in the queue. Try increasing the gas price or incrementing the nonce."
|
||||
if (error.responseText.indexOf('another transaction with same nonce') >= 0) {
|
||||
errors.throwError('replacement fee too low', errors.REPLACEMENT_UNDERPRICED, {});
|
||||
}
|
||||
}
|
||||
throw error;
|
||||
});
|
||||
@@ -11532,21 +11639,23 @@ var JsonRpcSigner = /** @class */ (function (_super) {
|
||||
throw error;
|
||||
});
|
||||
}, function (error) {
|
||||
// See: JsonRpcProvider.sendTransaction (@TODO: Expose a ._throwError??)
|
||||
if (error.responseText.indexOf('insufficient funds') >= 0) {
|
||||
errors.throwError('insufficient funds', errors.INSUFFICIENT_FUNDS, {
|
||||
transaction: tx
|
||||
});
|
||||
}
|
||||
if (error.responseText.indexOf('nonce too low') >= 0) {
|
||||
errors.throwError('nonce has already been used', errors.NONCE_EXPIRED, {
|
||||
transaction: tx
|
||||
});
|
||||
}
|
||||
if (error.responseText.indexOf('replacement transaction underpriced') >= 0) {
|
||||
errors.throwError('replacement fee too low', errors.REPLACEMENT_UNDERPRICED, {
|
||||
transaction: tx
|
||||
});
|
||||
if (error.responseText) {
|
||||
// See: JsonRpcProvider.sendTransaction (@TODO: Expose a ._throwError??)
|
||||
if (error.responseText.indexOf('insufficient funds') >= 0) {
|
||||
errors.throwError('insufficient funds', errors.INSUFFICIENT_FUNDS, {
|
||||
transaction: tx
|
||||
});
|
||||
}
|
||||
if (error.responseText.indexOf('nonce too low') >= 0) {
|
||||
errors.throwError('nonce has already been used', errors.NONCE_EXPIRED, {
|
||||
transaction: tx
|
||||
});
|
||||
}
|
||||
if (error.responseText.indexOf('replacement transaction underpriced') >= 0) {
|
||||
errors.throwError('replacement fee too low', errors.REPLACEMENT_UNDERPRICED, {
|
||||
transaction: tx
|
||||
});
|
||||
}
|
||||
}
|
||||
throw error;
|
||||
});
|
||||
@@ -11645,17 +11754,19 @@ var JsonRpcProvider = /** @class */ (function (_super) {
|
||||
return this.send('eth_getStorageAt', [getLowerCase(params.address), params.position, params.blockTag]);
|
||||
case 'sendTransaction':
|
||||
return this.send('eth_sendRawTransaction', [params.signedTransaction]).catch(function (error) {
|
||||
// "insufficient funds for gas * price + value"
|
||||
if (error.responseText.indexOf('insufficient funds') > 0) {
|
||||
errors.throwError('insufficient funds', errors.INSUFFICIENT_FUNDS, {});
|
||||
}
|
||||
// "nonce too low"
|
||||
if (error.responseText.indexOf('nonce too low') > 0) {
|
||||
errors.throwError('nonce has already been used', errors.NONCE_EXPIRED, {});
|
||||
}
|
||||
// "replacement transaction underpriced"
|
||||
if (error.responseText.indexOf('replacement transaction underpriced') > 0) {
|
||||
errors.throwError('replacement fee too low', errors.REPLACEMENT_UNDERPRICED, {});
|
||||
if (error.responseText) {
|
||||
// "insufficient funds for gas * price + value"
|
||||
if (error.responseText.indexOf('insufficient funds') > 0) {
|
||||
errors.throwError('insufficient funds', errors.INSUFFICIENT_FUNDS, {});
|
||||
}
|
||||
// "nonce too low"
|
||||
if (error.responseText.indexOf('nonce too low') > 0) {
|
||||
errors.throwError('nonce has already been used', errors.NONCE_EXPIRED, {});
|
||||
}
|
||||
// "replacement transaction underpriced"
|
||||
if (error.responseText.indexOf('replacement transaction underpriced') > 0) {
|
||||
errors.throwError('replacement fee too low', errors.REPLACEMENT_UNDERPRICED, {});
|
||||
}
|
||||
}
|
||||
throw error;
|
||||
});
|
||||
@@ -13504,6 +13615,7 @@ var HDNode = /** @class */ (function () {
|
||||
properties_1.defineReadOnly(this, 'keyPair', new secp256k1_1.KeyPair(privateKey));
|
||||
properties_1.defineReadOnly(this, 'privateKey', this.keyPair.privateKey);
|
||||
properties_1.defineReadOnly(this, 'publicKey', this.keyPair.compressedPublicKey);
|
||||
properties_1.defineReadOnly(this, 'address', secp256k1_1.computeAddress(this.publicKey));
|
||||
properties_1.defineReadOnly(this, 'chainCode', bytes_1.hexlify(chainCode));
|
||||
properties_1.defineReadOnly(this, 'index', index);
|
||||
properties_1.defineReadOnly(this, 'depth', depth);
|
||||
@@ -15964,6 +16076,9 @@ function fetchJson(connection, json, processFunc) {
|
||||
// @TODO: not any!
|
||||
var error = new Error('invalid response - ' + request.status);
|
||||
error.statusCode = request.status;
|
||||
if (request.responseText) {
|
||||
error.responseText = request.responseText;
|
||||
}
|
||||
reject(error);
|
||||
return;
|
||||
}
|
||||
|
||||
2
dist/ethers.min.js
vendored
2
dist/ethers.min.js
vendored
File diff suppressed because one or more lines are too long
2
dist/ethers.min.js.map
vendored
2
dist/ethers.min.js.map
vendored
File diff suppressed because one or more lines are too long
23
dist/ethers.types.txt
vendored
23
dist/ethers.types.txt
vendored
@@ -17,9 +17,9 @@ declare module 'ethers/ethers' {
|
||||
import * as wordlists from 'ethers/wordlists';
|
||||
import { platform } from 'ethers/utils/shims';
|
||||
import { version } from 'ethers/_version';
|
||||
import { ContractFunction, Event, EventFilter } from 'ethers/contract';
|
||||
import { ContractFunction, ContractTransaction, Event, EventFilter } from 'ethers/contract';
|
||||
function getDefaultProvider(network?: utils.Network | string): providers.BaseProvider;
|
||||
export { Signer, Wallet, VoidSigner, getDefaultProvider, providers, Contract, ContractFactory, constants, errors, utils, wordlists, platform, version, ContractFunction, Event, EventFilter };
|
||||
export { Signer, Wallet, VoidSigner, getDefaultProvider, providers, Contract, ContractFactory, constants, errors, utils, wordlists, platform, version, ContractFunction, ContractTransaction, Event, EventFilter };
|
||||
}
|
||||
|
||||
declare module 'ethers/contract' {
|
||||
@@ -46,6 +46,12 @@ declare module 'ethers/contract' {
|
||||
getTransaction: () => Promise<TransactionResponse>;
|
||||
getTransactionReceipt: () => Promise<TransactionReceipt>;
|
||||
}
|
||||
export interface ContractReceipt extends TransactionReceipt {
|
||||
events?: Array<Event>;
|
||||
}
|
||||
export interface ContractTransaction extends TransactionResponse {
|
||||
wait(confirmations?: number): Promise<ContractReceipt>;
|
||||
}
|
||||
export class VoidSigner extends Signer {
|
||||
readonly address: string;
|
||||
constructor(address: string, provider: Provider);
|
||||
@@ -146,7 +152,7 @@ declare module 'ethers/wallet' {
|
||||
* Static methods to create Wallet instances.
|
||||
*/
|
||||
static createRandom(options?: any): Wallet;
|
||||
static fromEncryptedJson(json: string, password: Arrayish, progressCallback: ProgressCallback): Promise<Wallet>;
|
||||
static fromEncryptedJson(json: string, password: Arrayish, progressCallback?: ProgressCallback): Promise<Wallet>;
|
||||
static fromMnemonic(mnemonic: string, path?: string, wordlist?: Wordlist): Wallet;
|
||||
}
|
||||
}
|
||||
@@ -254,7 +260,7 @@ declare module 'ethers/utils/shims' {
|
||||
}
|
||||
|
||||
declare module 'ethers/_version' {
|
||||
export const version = "4.0.2";
|
||||
export const version = "4.0.4";
|
||||
}
|
||||
|
||||
declare module 'ethers/utils/bignumber' {
|
||||
@@ -482,6 +488,7 @@ declare module 'ethers/providers/abstract-provider' {
|
||||
transactionHash?: string;
|
||||
logs?: Array<Log>;
|
||||
blockNumber?: number;
|
||||
confirmations?: number;
|
||||
cumulativeGasUsed?: BigNumber;
|
||||
byzantium: boolean;
|
||||
status?: number;
|
||||
@@ -500,9 +507,10 @@ declare module 'ethers/providers/abstract-provider' {
|
||||
blockNumber?: number;
|
||||
blockHash?: string;
|
||||
timestamp?: number;
|
||||
confirmations: number;
|
||||
from: string;
|
||||
raw?: string;
|
||||
wait: (timeout?: number) => Promise<TransactionReceipt>;
|
||||
wait: (confirmations?: number) => Promise<TransactionReceipt>;
|
||||
}
|
||||
export type EventType = string | Array<string> | Filter;
|
||||
export type Listener = (...args: Array<any>) => void;
|
||||
@@ -614,6 +622,7 @@ declare module 'ethers/utils/hdnode' {
|
||||
export class HDNode {
|
||||
readonly privateKey: string;
|
||||
readonly publicKey: string;
|
||||
readonly address: string;
|
||||
readonly mnemonic: string;
|
||||
readonly path: string;
|
||||
readonly chainCode: string;
|
||||
@@ -721,7 +730,9 @@ declare module 'ethers/providers/base-provider' {
|
||||
readonly blockNumber: number;
|
||||
polling: boolean;
|
||||
pollingInterval: number;
|
||||
waitForTransaction(transactionHash: string, timeout?: number): Promise<TransactionReceipt>;
|
||||
_getFastBlockNumber(): Promise<number>;
|
||||
_setFastBlockNumber(blockNumber: number): void;
|
||||
waitForTransaction(transactionHash: string, confirmations?: number): Promise<TransactionReceipt>;
|
||||
getBlockNumber(): Promise<number>;
|
||||
getGasPrice(): Promise<BigNumber>;
|
||||
getBalance(addressOrName: string | Promise<string>, blockTag?: BlockTag | Promise<BlockTag>): Promise<BigNumber>;
|
||||
|
||||
4
ethers.d.ts
vendored
4
ethers.d.ts
vendored
@@ -8,6 +8,6 @@ import * as utils from './utils';
|
||||
import * as wordlists from './wordlists';
|
||||
import { platform } from './utils/shims';
|
||||
import { version } from './_version';
|
||||
import { ContractFunction, Event, EventFilter } from './contract';
|
||||
import { ContractFunction, ContractTransaction, Event, EventFilter } from './contract';
|
||||
declare function getDefaultProvider(network?: utils.Network | string): providers.BaseProvider;
|
||||
export { Signer, Wallet, VoidSigner, getDefaultProvider, providers, Contract, ContractFactory, constants, errors, utils, wordlists, platform, version, ContractFunction, Event, EventFilter };
|
||||
export { Signer, Wallet, VoidSigner, getDefaultProvider, providers, Contract, ContractFactory, constants, errors, utils, wordlists, platform, version, ContractFunction, ContractTransaction, Event, EventFilter };
|
||||
|
||||
2
package-lock.json
generated
2
package-lock.json
generated
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "ethers",
|
||||
"version": "4.0.1",
|
||||
"version": "4.0.4",
|
||||
"lockfileVersion": 1,
|
||||
"requires": true,
|
||||
"dependencies": {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "ethers",
|
||||
"version": "4.0.2",
|
||||
"version": "4.0.4",
|
||||
"description": "Ethereum wallet library.",
|
||||
"main": "./index.js",
|
||||
"types": "./index.d.ts",
|
||||
|
||||
4
providers/abstract-provider.d.ts
vendored
4
providers/abstract-provider.d.ts
vendored
@@ -46,6 +46,7 @@ export interface TransactionReceipt {
|
||||
transactionHash?: string;
|
||||
logs?: Array<Log>;
|
||||
blockNumber?: number;
|
||||
confirmations?: number;
|
||||
cumulativeGasUsed?: BigNumber;
|
||||
byzantium: boolean;
|
||||
status?: number;
|
||||
@@ -64,9 +65,10 @@ export interface TransactionResponse extends Transaction {
|
||||
blockNumber?: number;
|
||||
blockHash?: string;
|
||||
timestamp?: number;
|
||||
confirmations: number;
|
||||
from: string;
|
||||
raw?: string;
|
||||
wait: (timeout?: number) => Promise<TransactionReceipt>;
|
||||
wait: (confirmations?: number) => Promise<TransactionReceipt>;
|
||||
}
|
||||
export declare type EventType = string | Array<string> | Filter;
|
||||
export declare type Listener = (...args: Array<any>) => void;
|
||||
|
||||
7
providers/base-provider.d.ts
vendored
7
providers/base-provider.d.ts
vendored
@@ -12,6 +12,9 @@ export declare class BaseProvider extends Provider {
|
||||
private _poller;
|
||||
private _lastBlockNumber;
|
||||
private _balances;
|
||||
private _fastBlockNumber;
|
||||
private _fastBlockNumberPromise;
|
||||
private _fastQueryDate;
|
||||
/**
|
||||
* ready
|
||||
*
|
||||
@@ -30,7 +33,9 @@ export declare class BaseProvider extends Provider {
|
||||
readonly blockNumber: number;
|
||||
polling: boolean;
|
||||
pollingInterval: number;
|
||||
waitForTransaction(transactionHash: string, timeout?: number): Promise<TransactionReceipt>;
|
||||
_getFastBlockNumber(): Promise<number>;
|
||||
_setFastBlockNumber(blockNumber: number): void;
|
||||
waitForTransaction(transactionHash: string, confirmations?: number): Promise<TransactionReceipt>;
|
||||
getBlockNumber(): Promise<number>;
|
||||
getGasPrice(): Promise<BigNumber>;
|
||||
getBalance(addressOrName: string | Promise<string>, blockTag?: BlockTag | Promise<BlockTag>): Promise<BigNumber>;
|
||||
|
||||
@@ -150,6 +150,7 @@ var formatTransaction = {
|
||||
blockHash: allowNull(checkHash, null),
|
||||
blockNumber: allowNull(checkNumber, null),
|
||||
transactionIndex: allowNull(checkNumber, null),
|
||||
confirmations: allowNull(checkNumber, null),
|
||||
from: address_1.getAddress,
|
||||
gasPrice: bignumber_1.bigNumberify,
|
||||
gasLimit: bignumber_1.bigNumberify,
|
||||
@@ -278,6 +279,7 @@ var formatTransactionReceipt = {
|
||||
transactionHash: checkHash,
|
||||
logs: arrayOf(checkTransactionReceiptLog),
|
||||
blockNumber: checkNumber,
|
||||
confirmations: allowNull(checkNumber, null),
|
||||
cumulativeGasUsed: bignumber_1.bigNumberify,
|
||||
status: allowNull(checkNumber)
|
||||
};
|
||||
@@ -388,6 +390,11 @@ function getEventTag(eventName) {
|
||||
}
|
||||
throw new Error('invalid event - ' + eventName);
|
||||
}
|
||||
//////////////////////////////
|
||||
// Helper Object
|
||||
function getTime() {
|
||||
return (new Date()).getTime();
|
||||
}
|
||||
var BaseProvider = /** @class */ (function (_super) {
|
||||
__extends(BaseProvider, _super);
|
||||
function BaseProvider(network) {
|
||||
@@ -420,11 +427,13 @@ var BaseProvider = /** @class */ (function (_super) {
|
||||
// until we get a response. This provides devs with a consistent view. Similarly for
|
||||
// transaction hashes.
|
||||
_this._emitted = { block: _this._lastBlockNumber };
|
||||
_this._fastQueryDate = 0;
|
||||
return _this;
|
||||
}
|
||||
BaseProvider.prototype._doPoll = function () {
|
||||
var _this = this;
|
||||
this.getBlockNumber().then(function (blockNumber) {
|
||||
_this._setFastBlockNumber(blockNumber);
|
||||
// If the block hasn't changed, meh.
|
||||
if (blockNumber === _this._lastBlockNumber) {
|
||||
return;
|
||||
@@ -574,13 +583,44 @@ var BaseProvider = /** @class */ (function (_super) {
|
||||
enumerable: true,
|
||||
configurable: true
|
||||
});
|
||||
BaseProvider.prototype._getFastBlockNumber = function () {
|
||||
var _this = this;
|
||||
var now = getTime();
|
||||
// Stale block number, request a newer value
|
||||
if ((now - this._fastQueryDate) > 2 * this._pollingInterval) {
|
||||
this._fastQueryDate = now;
|
||||
this._fastBlockNumberPromise = this.getBlockNumber().then(function (blockNumber) {
|
||||
if (_this._fastBlockNumber == null || blockNumber > _this._fastBlockNumber) {
|
||||
_this._fastBlockNumber = blockNumber;
|
||||
}
|
||||
return _this._fastBlockNumber;
|
||||
});
|
||||
}
|
||||
return this._fastBlockNumberPromise;
|
||||
};
|
||||
BaseProvider.prototype._setFastBlockNumber = function (blockNumber) {
|
||||
// Older block, maybe a stale request
|
||||
if (this._fastBlockNumber != null && blockNumber < this._fastBlockNumber) {
|
||||
return;
|
||||
}
|
||||
// Update the time we updated the blocknumber
|
||||
this._fastQueryDate = getTime();
|
||||
// Newer block number, use it
|
||||
if (this._fastBlockNumber == null || blockNumber > this._fastBlockNumber) {
|
||||
this._fastBlockNumber = blockNumber;
|
||||
this._fastBlockNumberPromise = Promise.resolve(blockNumber);
|
||||
}
|
||||
};
|
||||
// @TODO: Add .poller which must be an event emitter with a 'start', 'stop' and 'block' event;
|
||||
// this will be used once we move to the WebSocket or other alternatives to polling
|
||||
BaseProvider.prototype.waitForTransaction = function (transactionHash, timeout) {
|
||||
BaseProvider.prototype.waitForTransaction = function (transactionHash, confirmations) {
|
||||
var _this = this;
|
||||
if (!confirmations) {
|
||||
confirmations = 1;
|
||||
}
|
||||
return web_1.poll(function () {
|
||||
return _this.getTransactionReceipt(transactionHash).then(function (receipt) {
|
||||
if (receipt == null) {
|
||||
if (receipt == null || receipt.confirmations < confirmations) {
|
||||
return undefined;
|
||||
}
|
||||
return receipt;
|
||||
@@ -595,6 +635,7 @@ var BaseProvider = /** @class */ (function (_super) {
|
||||
if (value != result) {
|
||||
throw new Error('invalid response - getBlockNumber');
|
||||
}
|
||||
_this._setFastBlockNumber(value);
|
||||
return value;
|
||||
});
|
||||
});
|
||||
@@ -688,7 +729,7 @@ var BaseProvider = /** @class */ (function (_super) {
|
||||
// This should be called by any subclass wrapping a TransactionResponse
|
||||
BaseProvider.prototype._wrapTransaction = function (tx, hash) {
|
||||
var _this = this;
|
||||
if (bytes_1.hexDataLength(hash) !== 32) {
|
||||
if (hash != null && bytes_1.hexDataLength(hash) !== 32) {
|
||||
throw new Error('invalid response - sendTransaction');
|
||||
}
|
||||
var result = tx;
|
||||
@@ -698,11 +739,11 @@ var BaseProvider = /** @class */ (function (_super) {
|
||||
}
|
||||
this._emitted['t:' + tx.hash] = 'pending';
|
||||
// @TODO: (confirmations? number, timeout? number)
|
||||
result.wait = function () {
|
||||
return _this.waitForTransaction(hash).then(function (receipt) {
|
||||
result.wait = function (confirmations) {
|
||||
return _this.waitForTransaction(tx.hash, confirmations).then(function (receipt) {
|
||||
if (receipt.status === 0) {
|
||||
errors.throwError('transaction failed', errors.CALL_EXCEPTION, {
|
||||
transactionHash: hash,
|
||||
transactionHash: tx.hash,
|
||||
transaction: tx
|
||||
});
|
||||
}
|
||||
@@ -804,7 +845,22 @@ var BaseProvider = /** @class */ (function (_super) {
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
return BaseProvider.checkTransactionResponse(result);
|
||||
var tx = BaseProvider.checkTransactionResponse(result);
|
||||
if (tx.blockNumber == null) {
|
||||
tx.confirmations = 0;
|
||||
}
|
||||
else if (tx.confirmations == null) {
|
||||
return _this._getFastBlockNumber().then(function (blockNumber) {
|
||||
// Add the confirmations using the fast block number (pessimistic)
|
||||
var confirmations = (blockNumber - tx.blockNumber) + 1;
|
||||
if (confirmations <= 0) {
|
||||
confirmations = 1;
|
||||
}
|
||||
tx.confirmations = confirmations;
|
||||
return _this._wrapTransaction(tx);
|
||||
});
|
||||
}
|
||||
return _this._wrapTransaction(tx);
|
||||
});
|
||||
}, { onceBlock: _this });
|
||||
});
|
||||
@@ -824,7 +880,26 @@ var BaseProvider = /** @class */ (function (_super) {
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
return checkTransactionReceipt(result);
|
||||
// "geth-etc" returns receipts before they are ready
|
||||
if (result.blockHash == null) {
|
||||
return undefined;
|
||||
}
|
||||
var receipt = checkTransactionReceipt(result);
|
||||
if (receipt.blockNumber == null) {
|
||||
receipt.confirmations = 0;
|
||||
}
|
||||
else if (receipt.confirmations == null) {
|
||||
return _this._getFastBlockNumber().then(function (blockNumber) {
|
||||
// Add the confirmations using the fast block number (pessimistic)
|
||||
var confirmations = (blockNumber - receipt.blockNumber) + 1;
|
||||
if (confirmations <= 0) {
|
||||
confirmations = 1;
|
||||
}
|
||||
receipt.confirmations = confirmations;
|
||||
return receipt;
|
||||
});
|
||||
}
|
||||
return receipt;
|
||||
});
|
||||
}, { onceBlock: _this });
|
||||
});
|
||||
|
||||
@@ -147,17 +147,19 @@ var EtherscanProvider = /** @class */ (function (_super) {
|
||||
url += '/api?module=proxy&action=eth_sendRawTransaction&hex=' + params.signedTransaction;
|
||||
url += apiKey;
|
||||
return web_1.fetchJson(url, null, getJsonResult).catch(function (error) {
|
||||
// "Insufficient funds. The account you tried to send transaction from does not have enough funds. Required 21464000000000 and got: 0"
|
||||
if (error.responseText.toLowerCase().indexOf('insufficient funds') >= 0) {
|
||||
errors.throwError('insufficient funds', errors.INSUFFICIENT_FUNDS, {});
|
||||
}
|
||||
// "Transaction with the same hash was already imported."
|
||||
if (error.responseText.indexOf('same hash was already imported') >= 0) {
|
||||
errors.throwError('nonce has already been used', errors.NONCE_EXPIRED, {});
|
||||
}
|
||||
// "Transaction gas price is too low. There is another transaction with same nonce in the queue. Try increasing the gas price or incrementing the nonce."
|
||||
if (error.responseText.indexOf('another transaction with same nonce') >= 0) {
|
||||
errors.throwError('replacement fee too low', errors.REPLACEMENT_UNDERPRICED, {});
|
||||
if (error.responseText) {
|
||||
// "Insufficient funds. The account you tried to send transaction from does not have enough funds. Required 21464000000000 and got: 0"
|
||||
if (error.responseText.toLowerCase().indexOf('insufficient funds') >= 0) {
|
||||
errors.throwError('insufficient funds', errors.INSUFFICIENT_FUNDS, {});
|
||||
}
|
||||
// "Transaction with the same hash was already imported."
|
||||
if (error.responseText.indexOf('same hash was already imported') >= 0) {
|
||||
errors.throwError('nonce has already been used', errors.NONCE_EXPIRED, {});
|
||||
}
|
||||
// "Transaction gas price is too low. There is another transaction with same nonce in the queue. Try increasing the gas price or incrementing the nonce."
|
||||
if (error.responseText.indexOf('another transaction with same nonce') >= 0) {
|
||||
errors.throwError('replacement fee too low', errors.REPLACEMENT_UNDERPRICED, {});
|
||||
}
|
||||
}
|
||||
throw error;
|
||||
});
|
||||
|
||||
@@ -132,21 +132,23 @@ var JsonRpcSigner = /** @class */ (function (_super) {
|
||||
throw error;
|
||||
});
|
||||
}, function (error) {
|
||||
// See: JsonRpcProvider.sendTransaction (@TODO: Expose a ._throwError??)
|
||||
if (error.responseText.indexOf('insufficient funds') >= 0) {
|
||||
errors.throwError('insufficient funds', errors.INSUFFICIENT_FUNDS, {
|
||||
transaction: tx
|
||||
});
|
||||
}
|
||||
if (error.responseText.indexOf('nonce too low') >= 0) {
|
||||
errors.throwError('nonce has already been used', errors.NONCE_EXPIRED, {
|
||||
transaction: tx
|
||||
});
|
||||
}
|
||||
if (error.responseText.indexOf('replacement transaction underpriced') >= 0) {
|
||||
errors.throwError('replacement fee too low', errors.REPLACEMENT_UNDERPRICED, {
|
||||
transaction: tx
|
||||
});
|
||||
if (error.responseText) {
|
||||
// See: JsonRpcProvider.sendTransaction (@TODO: Expose a ._throwError??)
|
||||
if (error.responseText.indexOf('insufficient funds') >= 0) {
|
||||
errors.throwError('insufficient funds', errors.INSUFFICIENT_FUNDS, {
|
||||
transaction: tx
|
||||
});
|
||||
}
|
||||
if (error.responseText.indexOf('nonce too low') >= 0) {
|
||||
errors.throwError('nonce has already been used', errors.NONCE_EXPIRED, {
|
||||
transaction: tx
|
||||
});
|
||||
}
|
||||
if (error.responseText.indexOf('replacement transaction underpriced') >= 0) {
|
||||
errors.throwError('replacement fee too low', errors.REPLACEMENT_UNDERPRICED, {
|
||||
transaction: tx
|
||||
});
|
||||
}
|
||||
}
|
||||
throw error;
|
||||
});
|
||||
@@ -245,17 +247,19 @@ var JsonRpcProvider = /** @class */ (function (_super) {
|
||||
return this.send('eth_getStorageAt', [getLowerCase(params.address), params.position, params.blockTag]);
|
||||
case 'sendTransaction':
|
||||
return this.send('eth_sendRawTransaction', [params.signedTransaction]).catch(function (error) {
|
||||
// "insufficient funds for gas * price + value"
|
||||
if (error.responseText.indexOf('insufficient funds') > 0) {
|
||||
errors.throwError('insufficient funds', errors.INSUFFICIENT_FUNDS, {});
|
||||
}
|
||||
// "nonce too low"
|
||||
if (error.responseText.indexOf('nonce too low') > 0) {
|
||||
errors.throwError('nonce has already been used', errors.NONCE_EXPIRED, {});
|
||||
}
|
||||
// "replacement transaction underpriced"
|
||||
if (error.responseText.indexOf('replacement transaction underpriced') > 0) {
|
||||
errors.throwError('replacement fee too low', errors.REPLACEMENT_UNDERPRICED, {});
|
||||
if (error.responseText) {
|
||||
// "insufficient funds for gas * price + value"
|
||||
if (error.responseText.indexOf('insufficient funds') > 0) {
|
||||
errors.throwError('insufficient funds', errors.INSUFFICIENT_FUNDS, {});
|
||||
}
|
||||
// "nonce too low"
|
||||
if (error.responseText.indexOf('nonce too low') > 0) {
|
||||
errors.throwError('nonce has already been used', errors.NONCE_EXPIRED, {});
|
||||
}
|
||||
// "replacement transaction underpriced"
|
||||
if (error.responseText.indexOf('replacement transaction underpriced') > 0) {
|
||||
errors.throwError('replacement fee too low', errors.REPLACEMENT_UNDERPRICED, {});
|
||||
}
|
||||
}
|
||||
throw error;
|
||||
});
|
||||
|
||||
@@ -1 +1 @@
|
||||
export const version = "4.0.2";
|
||||
export const version = "4.0.4";
|
||||
|
||||
@@ -16,7 +16,7 @@ import { UnsignedTransaction } from './utils/transaction';
|
||||
///////////////////////////////
|
||||
// Imported Abstracts
|
||||
|
||||
import { Provider } from './providers/abstract-provider';
|
||||
import { BlockTag, Provider } from './providers/abstract-provider';
|
||||
import { Signer } from './abstract-signer';
|
||||
|
||||
///////////////////////////////
|
||||
@@ -148,14 +148,21 @@ type RunFunction = (...params: Array<any>) => Promise<any>;
|
||||
function runMethod(contract: Contract, functionName: string, estimateOnly: boolean): RunFunction {
|
||||
let method = contract.interface.functions[functionName];
|
||||
return function(...params): Promise<any> {
|
||||
var tx: any = {}
|
||||
let tx: any = {}
|
||||
|
||||
let blockTag: BlockTag = null;
|
||||
|
||||
// If 1 extra parameter was passed in, it contains overrides
|
||||
if (params.length === method.inputs.length + 1 && typeof(params[params.length - 1]) === 'object') {
|
||||
tx = shallowCopy(params.pop());
|
||||
|
||||
if (tx.blockTag != null) {
|
||||
blockTag = tx.blockTag;
|
||||
delete tx.blockTag;
|
||||
}
|
||||
|
||||
// Check for unexpected keys (e.g. using "gas" instead of "gasLimit")
|
||||
for (var key in tx) {
|
||||
for (let key in tx) {
|
||||
if (!allowedTransactionKeys[key]) {
|
||||
throw new Error('unknown transaction override ' + key);
|
||||
}
|
||||
@@ -202,7 +209,7 @@ function runMethod(contract: Contract, functionName: string, estimateOnly: boole
|
||||
tx.from = contract.signer.getAddress()
|
||||
}
|
||||
|
||||
return contract.provider.call(tx).then((value) => {
|
||||
return contract.provider.call(tx, blockTag).then((value) => {
|
||||
|
||||
if ((hexDataLength(value) % 32) === 4 && hexDataSlice(value, 0, 4) === '0x08c379a0') {
|
||||
let reason = defaultAbiCoder.decode([ 'string' ], hexDataSlice(value, 4));
|
||||
|
||||
@@ -125,7 +125,7 @@ export abstract class Provider implements OnceBlockable {
|
||||
abstract getStorageAt(addressOrName: string | Promise<string>, position: BigNumberish | Promise<BigNumberish>, blockTag?: BlockTag | Promise<BlockTag>): Promise<string>;
|
||||
|
||||
abstract sendTransaction(signedTransaction: string | Promise<string>): Promise<TransactionResponse>;
|
||||
abstract call(transaction: TransactionRequest): Promise<string>;
|
||||
abstract call(transaction: TransactionRequest, blockTag?: BlockTag | Promise<BlockTag>): Promise<string>;
|
||||
abstract estimateGas(transaction: TransactionRequest): Promise<BigNumber>;
|
||||
|
||||
abstract getBlock(blockHashOrBlockTag: BlockTag | string | Promise<BlockTag | string>, includeTransactions?: boolean): Promise<Block>;
|
||||
|
||||
@@ -850,12 +850,12 @@ export class BaseProvider extends Provider {
|
||||
}
|
||||
|
||||
|
||||
call(transaction: TransactionRequest): Promise<string> {
|
||||
call(transaction: TransactionRequest, blockTag?: BlockTag | Promise<BlockTag>): Promise<string> {
|
||||
let tx: TransactionRequest = shallowCopy(transaction);
|
||||
return this.ready.then(() => {
|
||||
return resolveProperties(tx).then((tx) => {
|
||||
return resolveProperties({ blockTag: blockTag, tx: tx }).then(({ blockTag, tx }) => {
|
||||
return this._resolveNames(tx, [ 'to', 'from' ]).then((tx) => {
|
||||
var params = { transaction: checkTransactionRequest(tx) };
|
||||
let params = { blockTag: checkBlockTag(blockTag), transaction: checkTransactionRequest(tx) };
|
||||
return this.perform('call', params).then((result) => {
|
||||
return hexlify(result);
|
||||
});
|
||||
|
||||
@@ -108,9 +108,7 @@ export class EtherscanProvider extends BaseProvider{
|
||||
|
||||
|
||||
perform(method: string, params: any) {
|
||||
//if (!params) { params = {}; }
|
||||
|
||||
var url = this.baseUrl;
|
||||
let url = this.baseUrl;
|
||||
|
||||
let apiKey = '';
|
||||
if (this.apiKey) { apiKey += '&apikey=' + this.apiKey; }
|
||||
@@ -118,7 +116,7 @@ export class EtherscanProvider extends BaseProvider{
|
||||
switch (method) {
|
||||
case 'getBlockNumber':
|
||||
url += '/api?module=proxy&action=eth_blockNumber' + apiKey;
|
||||
return fetchJson(url, null, getJsonResult);
|
||||
return fetchJson(url, null, getJsonResult);
|
||||
|
||||
case 'getGasPrice':
|
||||
url += '/api?module=proxy&action=eth_gasPrice' + apiKey;
|
||||
@@ -193,19 +191,25 @@ export class EtherscanProvider extends BaseProvider{
|
||||
return fetchJson(url, null, getJsonResult);
|
||||
|
||||
|
||||
case 'call':
|
||||
var transaction = getTransactionString(params.transaction);
|
||||
case 'call': {
|
||||
let transaction = getTransactionString(params.transaction);
|
||||
if (transaction) { transaction = '&' + transaction; }
|
||||
url += '/api?module=proxy&action=eth_call' + transaction;
|
||||
//url += '&tag=' + params.blockTag + apiKey;
|
||||
if (params.blockTag !== 'latest') {
|
||||
throw new Error('EtherscanProvider does not support blockTag for call');
|
||||
}
|
||||
url += apiKey;
|
||||
return fetchJson(url, null, getJsonResult);
|
||||
}
|
||||
|
||||
case 'estimateGas':
|
||||
var transaction = getTransactionString(params.transaction);
|
||||
case 'estimateGas': {
|
||||
let transaction = getTransactionString(params.transaction);
|
||||
if (transaction) { transaction = '&' + transaction; }
|
||||
url += '/api?module=proxy&action=eth_estimateGas&' + transaction;
|
||||
url += apiKey;
|
||||
return fetchJson(url, null, getJsonResult);
|
||||
}
|
||||
|
||||
case 'getLogs':
|
||||
url += '/api?module=logs&action=getLogs';
|
||||
@@ -227,7 +231,7 @@ export class EtherscanProvider extends BaseProvider{
|
||||
if (params.filter.topics.length > 1) {
|
||||
throw new Error('unsupported topic format');
|
||||
}
|
||||
var topic0 = params.filter.topics[0];
|
||||
let topic0 = params.filter.topics[0];
|
||||
if (typeof(topic0) !== 'string' || topic0.length !== 66) {
|
||||
throw new Error('unsupported topic0 format');
|
||||
}
|
||||
|
||||
@@ -176,6 +176,10 @@ export class JsonRpcSigner extends Signer {
|
||||
}
|
||||
}
|
||||
|
||||
const allowedTransactionKeys: { [ key: string ]: boolean } = {
|
||||
chainId: true, data: true, gasLimit: true, gasPrice:true, nonce: true, to: true, value: true
|
||||
}
|
||||
|
||||
export class JsonRpcProvider extends BaseProvider {
|
||||
readonly connection: ConnectionInfo;
|
||||
|
||||
@@ -300,10 +304,10 @@ export class JsonRpcProvider extends BaseProvider {
|
||||
return this.send('eth_getTransactionReceipt', [ params.transactionHash ]);
|
||||
|
||||
case 'call':
|
||||
return this.send('eth_call', [ JsonRpcProvider.hexlifyTransaction(params.transaction), 'latest' ]);
|
||||
return this.send('eth_call', [ JsonRpcProvider.hexlifyTransaction(params.transaction, { from: true }), params.blockTag ]);
|
||||
|
||||
case 'estimateGas':
|
||||
return this.send('eth_estimateGas', [ JsonRpcProvider.hexlifyTransaction(params.transaction) ]);
|
||||
return this.send('eth_estimateGas', [ JsonRpcProvider.hexlifyTransaction(params.transaction, { from: true }) ]);
|
||||
|
||||
case 'getLogs':
|
||||
if (params.filter && params.filter.address != null) {
|
||||
@@ -369,9 +373,22 @@ export class JsonRpcProvider extends BaseProvider {
|
||||
// - gasLimit => gas
|
||||
// - All values hexlified
|
||||
// - All numeric values zero-striped
|
||||
// @TODO: Not any, a dictionary of string to strings
|
||||
static hexlifyTransaction(transaction: TransactionRequest): any {
|
||||
var result: any = {};
|
||||
// NOTE: This allows a TransactionRequest, but all values should be resolved
|
||||
// before this is called
|
||||
static hexlifyTransaction(transaction: TransactionRequest, allowExtra?: { [key: string]: boolean }): { [key: string]: string } {
|
||||
if (!allowExtra) { allowExtra = {}; }
|
||||
|
||||
for (let key in transaction) {
|
||||
if (!allowedTransactionKeys[key] && !allowExtra[key]) {
|
||||
errors.throwError('invalid key - ' + key, errors.INVALID_ARGUMENT, {
|
||||
argument: 'transaction',
|
||||
value: transaction,
|
||||
key: key
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
let result: { [key: string]: string } = {};
|
||||
|
||||
// Some nodes (INFURA ropsten; INFURA mainnet is fine) don't like extra zeros.
|
||||
['gasLimit', 'gasPrice', 'nonce', 'value'].forEach(function(key) {
|
||||
@@ -384,7 +401,7 @@ export class JsonRpcProvider extends BaseProvider {
|
||||
['from', 'to', 'data'].forEach(function(key) {
|
||||
if ((<any>transaction)[key] == null) { return; }
|
||||
result[key] = hexlify((<any>transaction)[key]);
|
||||
});
|
||||
});
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -19,7 +19,7 @@ import { toUtf8Bytes, UnicodeNormalizationForm } from './utf8';
|
||||
import { pbkdf2 } from './pbkdf2';
|
||||
import { computeHmac, SupportedAlgorithms } from './hmac';
|
||||
import { defineReadOnly, isType, setType } from './properties';
|
||||
import { KeyPair } from './secp256k1';
|
||||
import { computeAddress, KeyPair } from './secp256k1';
|
||||
import { sha256 } from './sha2';
|
||||
|
||||
const N = bigNumberify("0xfffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141");
|
||||
@@ -54,6 +54,8 @@ export class HDNode {
|
||||
readonly privateKey: string;
|
||||
readonly publicKey: string;
|
||||
|
||||
readonly address: string;
|
||||
|
||||
readonly mnemonic: string;
|
||||
readonly path: string;
|
||||
|
||||
@@ -81,6 +83,8 @@ export class HDNode {
|
||||
defineReadOnly(this, 'privateKey', this.keyPair.privateKey);
|
||||
defineReadOnly(this, 'publicKey', this.keyPair.compressedPublicKey);
|
||||
|
||||
defineReadOnly(this, 'address', computeAddress(this.publicKey));
|
||||
|
||||
defineReadOnly(this, 'chainCode', hexlify(chainCode));
|
||||
|
||||
defineReadOnly(this, 'index', index);
|
||||
|
||||
@@ -24,6 +24,9 @@ import { BlockTag, TransactionRequest, TransactionResponse } from './providers/a
|
||||
|
||||
import * as errors from './errors';
|
||||
|
||||
const allowedTransactionKeys: { [ key: string ]: boolean } = {
|
||||
chainId: true, data: true, gasLimit: true, gasPrice:true, nonce: true, to: true, value: true
|
||||
}
|
||||
|
||||
export class Wallet extends AbstractSigner {
|
||||
|
||||
@@ -69,6 +72,15 @@ export class Wallet extends AbstractSigner {
|
||||
}
|
||||
|
||||
sign(transaction: TransactionRequest): Promise<string> {
|
||||
for (let key in transaction) {
|
||||
if (!allowedTransactionKeys[key]) {
|
||||
errors.throwError('unsupported transaction property - ' + key, errors.INVALID_ARGUMENT, {
|
||||
argument: 'transaction',
|
||||
value: transaction,
|
||||
key: key
|
||||
});
|
||||
}
|
||||
}
|
||||
return resolveProperties(transaction).then((tx) => {
|
||||
let rawTx = serializeTransaction(tx);
|
||||
let signature = this.signingKey.signDigest(keccak256(rawTx));
|
||||
@@ -98,17 +110,12 @@ export class Wallet extends AbstractSigner {
|
||||
throw new Error('invalid transaction object');
|
||||
}
|
||||
|
||||
var tx = shallowCopy(transaction);
|
||||
let tx = shallowCopy(transaction);
|
||||
|
||||
if (tx.to != null) {
|
||||
tx.to = this.provider.resolveName(tx.to);
|
||||
}
|
||||
|
||||
if (tx.gasLimit == null) {
|
||||
tx.from = this.getAddress();
|
||||
tx.gasLimit = this.provider.estimateGas(tx);
|
||||
}
|
||||
|
||||
if (tx.gasPrice == null) {
|
||||
tx.gasPrice = this.provider.getGasPrice();
|
||||
}
|
||||
@@ -117,6 +124,12 @@ export class Wallet extends AbstractSigner {
|
||||
tx.nonce = this.getTransactionCount();
|
||||
}
|
||||
|
||||
if (tx.gasLimit == null) {
|
||||
let estimate = shallowCopy(tx);
|
||||
estimate.from = this.getAddress();
|
||||
tx.gasLimit = this.provider.estimateGas(estimate);
|
||||
}
|
||||
|
||||
if (tx.chainId == null) {
|
||||
tx.chainId = this.provider.getNetwork().then((network) => network.chainId);
|
||||
}
|
||||
@@ -165,7 +178,7 @@ export class Wallet extends AbstractSigner {
|
||||
return Wallet.fromMnemonic(mnemonic, options.path, options.locale);
|
||||
}
|
||||
|
||||
static fromEncryptedJson(json: string, password: Arrayish, progressCallback: ProgressCallback): Promise<Wallet> {
|
||||
static fromEncryptedJson(json: string, password: Arrayish, progressCallback?: ProgressCallback): Promise<Wallet> {
|
||||
if (isCrowdsaleWallet(json)) {
|
||||
try {
|
||||
if (progressCallback) { progressCallback(0); }
|
||||
|
||||
@@ -22,6 +22,8 @@ describe('Test HD Node Derivation', function(test) {
|
||||
var wallet = new ethers.Wallet(node.privateKey);
|
||||
assert.equal(wallet.address.toLowerCase(), nodeTest.address,
|
||||
'Generates address - ' + nodeTest.privateKey);
|
||||
|
||||
assert.equal(node.address, (new ethers.Wallet(node)).address, 'HDNode address matches - ' + nodeTest.privateKey);
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -64,6 +66,8 @@ function testEasySeed(lang, locale) {
|
||||
}
|
||||
|
||||
testEasySeed(ethers.wordlists.en, 'en');
|
||||
testEasySeed(ethers.wordlists.es, 'es');
|
||||
testEasySeed(ethers.wordlists.fr, 'fr');
|
||||
testEasySeed(ethers.wordlists.ja, 'ja');
|
||||
testEasySeed(ethers.wordlists.zh_cn, 'zh_cn');
|
||||
testEasySeed(ethers.wordlists.zh_tw, 'zh_tw');
|
||||
|
||||
1
utils/hdnode.d.ts
vendored
1
utils/hdnode.d.ts
vendored
@@ -5,6 +5,7 @@ export declare class HDNode {
|
||||
private readonly keyPair;
|
||||
readonly privateKey: string;
|
||||
readonly publicKey: string;
|
||||
readonly address: string;
|
||||
readonly mnemonic: string;
|
||||
readonly path: string;
|
||||
readonly chainCode: string;
|
||||
|
||||
@@ -54,6 +54,7 @@ var HDNode = /** @class */ (function () {
|
||||
properties_1.defineReadOnly(this, 'keyPair', new secp256k1_1.KeyPair(privateKey));
|
||||
properties_1.defineReadOnly(this, 'privateKey', this.keyPair.privateKey);
|
||||
properties_1.defineReadOnly(this, 'publicKey', this.keyPair.compressedPublicKey);
|
||||
properties_1.defineReadOnly(this, 'address', secp256k1_1.computeAddress(this.publicKey));
|
||||
properties_1.defineReadOnly(this, 'chainCode', bytes_1.hexlify(chainCode));
|
||||
properties_1.defineReadOnly(this, 'index', index);
|
||||
properties_1.defineReadOnly(this, 'depth', depth);
|
||||
|
||||
@@ -82,6 +82,9 @@ function fetchJson(connection, json, processFunc) {
|
||||
// @TODO: not any!
|
||||
var error = new Error('invalid response - ' + request.status);
|
||||
error.statusCode = request.status;
|
||||
if (request.responseText) {
|
||||
error.responseText = request.responseText;
|
||||
}
|
||||
reject(error);
|
||||
return;
|
||||
}
|
||||
|
||||
2
wallet.d.ts
vendored
2
wallet.d.ts
vendored
@@ -30,6 +30,6 @@ export declare class Wallet extends AbstractSigner {
|
||||
* Static methods to create Wallet instances.
|
||||
*/
|
||||
static createRandom(options?: any): Wallet;
|
||||
static fromEncryptedJson(json: string, password: Arrayish, progressCallback: ProgressCallback): Promise<Wallet>;
|
||||
static fromEncryptedJson(json: string, password: Arrayish, progressCallback?: ProgressCallback): Promise<Wallet>;
|
||||
static fromMnemonic(mnemonic: string, path?: string, wordlist?: Wordlist): Wallet;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user