Compare commits

..

21 Commits

Author SHA1 Message Date
Richard Moore
e39e2ed718 Added address to HDNode (#196). 2018-10-07 01:09:56 -04:00
Richard Moore
71f781d542 Added French and Spanish to test-hdnode. 2018-10-07 01:05:49 -04:00
Richard Moore
b2db10e216 Mark progressCallback as optional (#293). 2018-10-07 00:42:52 -04:00
Richard Moore
3736a15714 Updated dist files. 2018-10-04 20:25:07 -04:00
Richard Moore
248158130e Added automatic event parsing for contract transaction receipts from tx.wait. 2018-10-04 19:54:15 -04:00
Richard Moore
f5c7ccbb80 Added ability to wait for a specific number of confirmations (#229). 2018-10-04 17:27:42 -04:00
Richard Moore
24335d0dd7 Fix for geth-etc (official geth is fine), which returns Receipts before the blockHash is synced to the database. 2018-10-04 16:46:19 -04:00
Richard Moore
908c2c1096 Fixed confirmations tests and bootstrap fast blockNumber. 2018-10-04 16:44:29 -04:00
Richard Moore
9797b36186 Added confirmations to TransactionResponse (#156, #238). 2018-10-04 16:24:31 -04:00
Richard Moore
731f189010 Fixed nested errors for providers that were masking true error (#292). 2018-10-04 15:24:29 -04:00
Richard Moore
cc5b157231 Updated dist files. 2018-10-03 22:52:55 -04:00
Richard Moore
99fed75202 Added version to errors. 2018-10-03 22:50:22 -04:00
Richard Moore
cb5f9f576a Fixed French and Spanish for browsers without Uint8Array.forEach. 2018-10-03 22:47:44 -04:00
Richard Moore
aeac2cdb86 Added French and Spanish includes to phantomjs test page. 2018-10-03 20:22:59 -04:00
Richard Moore
0dafd83033 Increased timeout for querying npm registry. 2018-10-03 20:08:01 -04:00
Richard Moore
f6d946cf68 Updated dist files. 2018-10-03 20:03:32 -04:00
Richard Moore
b9c07b549c Added French and Spanish wordlist dist files. 2018-10-03 20:01:35 -04:00
Richard Moore
c34a1f73c6 Added French and Spanish BIP-39 wordlists (#191). 2018-10-03 19:58:45 -04:00
Richard Moore
281bd0613d Added support for JSON serialized BigNumbers in the constructor (#288). 2018-10-03 19:54:38 -04:00
Richard Moore
d936b4cd09 Fixed scrypt for long passwords (#223). 2018-10-03 19:50:15 -04:00
Richard Moore
5a0ebf84ef Updated dist files. 2018-10-01 17:34:44 -04:00
53 changed files with 5275 additions and 247 deletions

2
_version.d.ts vendored
View File

@@ -1 +1 @@
export declare const version = "4.0.0";
export declare const version = "4.0.3";

View File

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

14
contract.d.ts vendored
View File

@@ -12,15 +12,21 @@ export declare type EventFilter = {
topics?: Array<string>;
};
export interface Event extends Log {
args: Array<any>;
decode: (data: string, topics?: Array<string>) => any;
event: string;
eventSignature: string;
args?: Array<any>;
decode?: (data: string, topics?: Array<string>) => any;
event?: string;
eventSignature?: string;
removeListener: () => void;
getBlock: () => Promise<Block>;
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);

View File

@@ -59,7 +59,7 @@ var VoidSigner = /** @class */ (function (_super) {
}(abstract_signer_1.Signer));
exports.VoidSigner = VoidSigner;
var allowedTransactionKeys = {
data: true, from: true, gasLimit: true, gasPrice: true, nonce: true, to: true, value: true
chainId: true, data: true, from: true, gasLimit: true, gasPrice: true, nonce: true, to: true, value: true
};
// Recursively replaces ENS names with promises to resolve the name and
// stalls until all promises have returned
@@ -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;
@@ -214,7 +244,10 @@ function runMethod(contract, functionName, estimateOnly) {
};
}
function getEventTag(filter) {
return (filter.address || '') + (filter.topics ? filter.topics.join(':') : '');
if (filter.address && (filter.topics == null || filter.topics.length === 0)) {
return '*';
}
return (filter.address || '*') + '@' + (filter.topics ? filter.topics.join(':') : '');
}
var Contract = /** @class */ (function () {
// https://github.com/Microsoft/TypeScript/issues/5453
@@ -366,8 +399,15 @@ var Contract = /** @class */ (function () {
// Listen for any event
if (eventName === '*') {
return {
decode: function (log) {
return [_this.interface.parseLog(log)];
prepareEvent: function (e) {
var parsed = _this.interface.parseLog(e);
if (parsed) {
e.args = parsed.values;
e.decode = parsed.decode;
e.event = parsed.name;
e.eventSignature = parsed.signature;
}
return [e];
},
eventTag: '*',
filter: { address: this.address },
@@ -386,8 +426,12 @@ var Contract = /** @class */ (function () {
topics: [event_1.topic]
};
return {
decode: function (log) {
return event_1.decode(log.data, log.topics);
prepareEvent: function (e) {
var args = event_1.decode(e.data, e.topics);
e.args = args;
var result = Array.prototype.slice.call(args);
result.push(e);
return result;
},
event: event_1,
eventTag: getEventTag(filter_1),
@@ -402,11 +446,11 @@ var Contract = /** @class */ (function () {
var event = null;
if (eventName.topics && eventName.topics[0]) {
filter.topics = eventName.topics;
for (var name in this.interface.events) {
if (name.indexOf('(') === -1) {
for (var name_1 in this.interface.events) {
if (name_1.indexOf('(') === -1) {
continue;
}
var e = this.interface.events[name];
var e = this.interface.events[name_1];
if (e.topic === eventName.topics[0].toLowerCase()) {
event = e;
break;
@@ -414,11 +458,15 @@ var Contract = /** @class */ (function () {
}
}
return {
decode: function (log) {
if (event) {
return event.decode(log.data, log.topics);
prepareEvent: function (e) {
if (!event) {
return [e];
}
return [log];
var args = event.decode(e.data, e.topics);
e.args = args;
var result = Array.prototype.slice.call(args);
result.push(e);
return result;
},
event: event,
eventTag: getEventTag(filter),
@@ -431,18 +479,18 @@ var Contract = /** @class */ (function () {
errors.throwError('events require a provider or a signer with a provider', errors.UNSUPPORTED_OPERATION, { operation: 'once' });
}
var wrappedListener = function (log) {
var decoded = Array.prototype.slice.call(eventFilter.decode(log));
var event = properties_1.deepCopy(log);
event.args = decoded;
event.decode = eventFilter.event.decode;
event.event = eventFilter.event.name;
event.eventSignature = eventFilter.event.signature;
var args = eventFilter.prepareEvent(event);
if (eventFilter.event) {
event.decode = eventFilter.event.decode;
event.event = eventFilter.event.name;
event.eventSignature = eventFilter.event.signature;
}
event.removeListener = function () { _this.removeListener(eventFilter.filter, listener); };
event.getBlock = function () { return _this.provider.getBlock(log.blockHash); };
event.getTransaction = function () { return _this.provider.getTransactionReceipt(log.transactionHash); };
event.getTransaction = function () { return _this.provider.getTransaction(log.transactionHash); };
event.getTransactionReceipt = function () { return _this.provider.getTransactionReceipt(log.transactionHash); };
decoded.push(event);
_this.emit.apply(_this, [eventFilter.filter].concat(decoded));
_this.emit.apply(_this, [eventFilter.filter].concat(args));
};
this.provider.on(eventFilter.filter, wrappedListener);
this._events.push({ eventFilter: eventFilter, listener: listener, wrappedListener: wrappedListener, once: once });
@@ -470,13 +518,16 @@ var Contract = /** @class */ (function () {
var result = false;
var eventFilter = this._getEventFilter(eventName);
this._events = this._events.filter(function (event) {
// Not this event (keep it for later)
if (event.eventFilter.eventTag !== eventFilter.eventTag) {
return true;
}
// Call the callback in the next event loop
setTimeout(function () {
event.listener.apply(_this, args);
}, 0);
result = true;
// Reschedule it if it not "once"
return !(event.once);
});
return result;

305
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.0";
exports.version = "4.0.3";
},{}],2:[function(require,module,exports){
"use strict";
@@ -107,7 +107,7 @@ var VoidSigner = /** @class */ (function (_super) {
}(abstract_signer_1.Signer));
exports.VoidSigner = VoidSigner;
var allowedTransactionKeys = {
data: true, from: true, gasLimit: true, gasPrice: true, nonce: true, to: true, value: true
chainId: true, data: true, from: true, gasLimit: true, gasPrice: true, nonce: true, to: true, value: true
};
// Recursively replaces ENS names with promises to resolve the name and
// stalls until all promises have returned
@@ -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;
@@ -262,7 +292,10 @@ function runMethod(contract, functionName, estimateOnly) {
};
}
function getEventTag(filter) {
return (filter.address || '') + (filter.topics ? filter.topics.join(':') : '');
if (filter.address && (filter.topics == null || filter.topics.length === 0)) {
return '*';
}
return (filter.address || '*') + '@' + (filter.topics ? filter.topics.join(':') : '');
}
var Contract = /** @class */ (function () {
// https://github.com/Microsoft/TypeScript/issues/5453
@@ -414,8 +447,15 @@ var Contract = /** @class */ (function () {
// Listen for any event
if (eventName === '*') {
return {
decode: function (log) {
return [_this.interface.parseLog(log)];
prepareEvent: function (e) {
var parsed = _this.interface.parseLog(e);
if (parsed) {
e.args = parsed.values;
e.decode = parsed.decode;
e.event = parsed.name;
e.eventSignature = parsed.signature;
}
return [e];
},
eventTag: '*',
filter: { address: this.address },
@@ -434,8 +474,12 @@ var Contract = /** @class */ (function () {
topics: [event_1.topic]
};
return {
decode: function (log) {
return event_1.decode(log.data, log.topics);
prepareEvent: function (e) {
var args = event_1.decode(e.data, e.topics);
e.args = args;
var result = Array.prototype.slice.call(args);
result.push(e);
return result;
},
event: event_1,
eventTag: getEventTag(filter_1),
@@ -450,11 +494,11 @@ var Contract = /** @class */ (function () {
var event = null;
if (eventName.topics && eventName.topics[0]) {
filter.topics = eventName.topics;
for (var name in this.interface.events) {
if (name.indexOf('(') === -1) {
for (var name_1 in this.interface.events) {
if (name_1.indexOf('(') === -1) {
continue;
}
var e = this.interface.events[name];
var e = this.interface.events[name_1];
if (e.topic === eventName.topics[0].toLowerCase()) {
event = e;
break;
@@ -462,11 +506,15 @@ var Contract = /** @class */ (function () {
}
}
return {
decode: function (log) {
if (event) {
return event.decode(log.data, log.topics);
prepareEvent: function (e) {
if (!event) {
return [e];
}
return [log];
var args = event.decode(e.data, e.topics);
e.args = args;
var result = Array.prototype.slice.call(args);
result.push(e);
return result;
},
event: event,
eventTag: getEventTag(filter),
@@ -479,18 +527,18 @@ var Contract = /** @class */ (function () {
errors.throwError('events require a provider or a signer with a provider', errors.UNSUPPORTED_OPERATION, { operation: 'once' });
}
var wrappedListener = function (log) {
var decoded = Array.prototype.slice.call(eventFilter.decode(log));
var event = properties_1.deepCopy(log);
event.args = decoded;
event.decode = eventFilter.event.decode;
event.event = eventFilter.event.name;
event.eventSignature = eventFilter.event.signature;
var args = eventFilter.prepareEvent(event);
if (eventFilter.event) {
event.decode = eventFilter.event.decode;
event.event = eventFilter.event.name;
event.eventSignature = eventFilter.event.signature;
}
event.removeListener = function () { _this.removeListener(eventFilter.filter, listener); };
event.getBlock = function () { return _this.provider.getBlock(log.blockHash); };
event.getTransaction = function () { return _this.provider.getTransactionReceipt(log.transactionHash); };
event.getTransaction = function () { return _this.provider.getTransaction(log.transactionHash); };
event.getTransactionReceipt = function () { return _this.provider.getTransactionReceipt(log.transactionHash); };
decoded.push(event);
_this.emit.apply(_this, [eventFilter.filter].concat(decoded));
_this.emit.apply(_this, [eventFilter.filter].concat(args));
};
this.provider.on(eventFilter.filter, wrappedListener);
this._events.push({ eventFilter: eventFilter, listener: listener, wrappedListener: wrappedListener, once: once });
@@ -518,13 +566,16 @@ var Contract = /** @class */ (function () {
var result = false;
var eventFilter = this._getEventFilter(eventName);
this._events = this._events.filter(function (event) {
// Not this event (keep it for later)
if (event.eventFilter.eventTag !== eventFilter.eventTag) {
return true;
}
// Call the callback in the next event loop
setTimeout(function () {
event.listener.apply(_this, args);
}, 0);
result = true;
// Reschedule it if it not "once"
return !(event.once);
});
return result;
@@ -697,6 +748,7 @@ exports.ContractFactory = ContractFactory;
},{"./abstract-signer":2,"./constants":3,"./errors":5,"./providers/abstract-provider":49,"./utils/abi-coder":58,"./utils/address":59,"./utils/bignumber":61,"./utils/bytes":62,"./utils/interface":67,"./utils/properties":72}],5:[function(require,module,exports){
'use strict';
Object.defineProperty(exports, "__esModule", { value: true });
var _version_1 = require("./_version");
// Unknown Error
exports.UNKNOWN_ERROR = 'UNKNOWN_ERROR';
// Not implemented
@@ -763,6 +815,7 @@ function throwError(message, code, params) {
messageDetails.push(key + '=' + JSON.stringify(params[key].toString()));
}
});
messageDetails.push("version=" + _version_1.version);
var reason = message;
if (messageDetails.length) {
message += ' (' + messageDetails.join(', ') + ')';
@@ -804,7 +857,7 @@ function setCensorship(censorship, permanent) {
}
exports.setCensorship = setCensorship;
},{}],6:[function(require,module,exports){
},{"./_version":1}],6:[function(require,module,exports){
'use strict';
var __importStar = (this && this.__importStar) || function (mod) {
if (mod && mod.__esModule) return mod;
@@ -9171,10 +9224,12 @@ module.exports = { browser: true };
if (!checkBufferish(password)) {
throw new Error('password must be an array or buffer');
}
password = Array.prototype.slice.call(password);
if (!checkBufferish(salt)) {
throw new Error('salt must be an array or buffer');
}
salt = Array.prototype.slice.call(salt);
var b = PBKDF2_HMAC_SHA256_OneIter(password, salt, p * 128 * r);
var B = new Uint32Array(p * 32 * r)
@@ -9933,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,
@@ -10061,6 +10117,7 @@ var formatTransactionReceipt = {
transactionHash: checkHash,
logs: arrayOf(checkTransactionReceiptLog),
blockNumber: checkNumber,
confirmations: allowNull(checkNumber, null),
cumulativeGasUsed: bignumber_1.bigNumberify,
status: allowNull(checkNumber)
};
@@ -10127,6 +10184,9 @@ function serializeTopics(topics) {
});
return topic.join(',');
}
else if (topic === null) {
return '';
}
return errors.throwError('invalid topic value', errors.INVALID_ARGUMENT, { argument: 'topic', value: topic });
}).join('&');
}
@@ -10139,7 +10199,12 @@ function deserializeTopics(data) {
}
return topic;
}
return comps;
return comps.map(function (topic) {
if (topic === '') {
return null;
}
return topic;
});
});
}
function getEventTag(eventName) {
@@ -10163,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) {
@@ -10195,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;
@@ -10349,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;
@@ -10370,6 +10473,7 @@ var BaseProvider = /** @class */ (function (_super) {
if (value != result) {
throw new Error('invalid response - getBlockNumber');
}
_this._setFastBlockNumber(value);
return value;
});
});
@@ -10463,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;
@@ -10473,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
});
}
@@ -10579,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 });
});
@@ -10599,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 });
});
@@ -11002,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;
});
@@ -11499,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;
});
@@ -11612,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;
});
@@ -13014,6 +13158,9 @@ var BigNumber = /** @class */ (function () {
else if (value.toHexString) {
properties_1.defineReadOnly(this, '_hex', toHex(toBN(value.toHexString())));
}
else if (value._hex && bytes_1.isHexString(value._hex)) {
properties_1.defineReadOnly(this, '_hex', value._hex);
}
else if (bytes_1.isArrayish(value)) {
properties_1.defineReadOnly(this, '_hex', toHex(new bn_js_1.default.BN(bytes_1.hexlify(value).substring(2), 16)));
}
@@ -14429,18 +14576,17 @@ function shallowCopy(object) {
exports.shallowCopy = shallowCopy;
var opaque = { boolean: true, number: true, string: true };
function deepCopy(object, frozen) {
// Opaque objects are not mutable, so safe to copy by assignment
if (object === undefined || object === null || opaque[typeof (object)]) {
return object;
}
// Arrays are mutable, so we need to create a copy
if (Array.isArray(object)) {
var result_1 = [];
object.forEach(function (item) {
result_1.push(deepCopy(item, frozen));
});
var result = object.map(function (item) { return deepCopy(item, frozen); });
if (frozen) {
Object.freeze(result_1);
Object.freeze(result);
}
return result_1;
return result;
}
if (typeof (object) === 'object') {
// Some internal objects, which are already immutable
@@ -14466,6 +14612,10 @@ function deepCopy(object, frozen) {
}
return result;
}
// The function type is also immutable, so safe to copy by assignment
if (typeof (object) === 'function') {
return object;
}
throw new Error('Cannot deepCopy ' + typeof (object));
}
exports.deepCopy = deepCopy;
@@ -15925,6 +16075,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

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

34
dist/ethers.types.txt vendored
View File

@@ -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' {
@@ -37,15 +37,21 @@ declare module 'ethers/contract' {
topics?: Array<string>;
};
export interface Event extends Log {
args: Array<any>;
decode: (data: string, topics?: Array<string>) => any;
event: string;
eventSignature: string;
args?: Array<any>;
decode?: (data: string, topics?: Array<string>) => any;
event?: string;
eventSignature?: string;
removeListener: () => void;
getBlock: () => Promise<Block>;
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);
@@ -238,13 +244,15 @@ declare module 'ethers/utils' {
declare module 'ethers/wordlists' {
import { Wordlist } from 'ethers/utils/wordlist';
const en: Wordlist;
const ko: Wordlist;
const es: Wordlist;
const fr: Wordlist;
const it: Wordlist;
const ja: Wordlist;
const ko: Wordlist;
const zh: Wordlist;
const zh_cn: Wordlist;
const zh_tw: Wordlist;
export { en, it, ja, ko, zh, zh_cn, zh_tw };
export { en, es, fr, it, ja, ko, zh, zh_cn, zh_tw };
}
declare module 'ethers/utils/shims' {
@@ -252,7 +260,7 @@ declare module 'ethers/utils/shims' {
}
declare module 'ethers/_version' {
export const version = "4.0.0";
export const version = "4.0.3";
}
declare module 'ethers/utils/bignumber' {
@@ -480,6 +488,7 @@ declare module 'ethers/providers/abstract-provider' {
transactionHash?: string;
logs?: Array<Log>;
blockNumber?: number;
confirmations?: number;
cumulativeGasUsed?: BigNumber;
byzantium: boolean;
status?: number;
@@ -498,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;
@@ -719,7 +729,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>;

1
dist/wordlist-es.js vendored Normal file

File diff suppressed because one or more lines are too long

1
dist/wordlist-fr.js vendored Normal file

File diff suppressed because one or more lines are too long

View File

@@ -1,5 +1,6 @@
'use strict';
Object.defineProperty(exports, "__esModule", { value: true });
var _version_1 = require("./_version");
// Unknown Error
exports.UNKNOWN_ERROR = 'UNKNOWN_ERROR';
// Not implemented
@@ -66,6 +67,7 @@ function throwError(message, code, params) {
messageDetails.push(key + '=' + JSON.stringify(params[key].toString()));
}
});
messageDetails.push("version=" + _version_1.version);
var reason = message;
if (messageDetails.length) {
message += ' (' + messageDetails.join(', ') + ')';

4
ethers.d.ts vendored
View File

@@ -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 };

View File

@@ -270,6 +270,8 @@ function taskLang(locale) {
});
}
taskLang("es");
taskLang("fr");
taskLang("it");
taskLang("ja");
taskLang("ko");

8
package-lock.json generated
View File

@@ -1,6 +1,6 @@
{
"name": "ethers",
"version": "4.0.0",
"version": "4.0.3",
"lockfileVersion": 1,
"requires": true,
"dependencies": {
@@ -5838,9 +5838,9 @@
"dev": true
},
"scrypt-js": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/scrypt-js/-/scrypt-js-2.0.3.tgz",
"integrity": "sha1-uwBAvgMEPamgEqLOqfyfhSz8h9Q="
"version": "2.0.4",
"resolved": "https://registry.npmjs.org/scrypt-js/-/scrypt-js-2.0.4.tgz",
"integrity": "sha512-4KsaGcPnuhtCZQCxFxN3GVYIhKFPTdLd8PLC552XwbMndtD0cjRFAhDuuydXQ0h08ZfPgzqe6EKHozpuH74iDw=="
},
"secp256k1": {
"version": "3.5.0",

View File

@@ -1,6 +1,6 @@
{
"name": "ethers",
"version": "4.0.0",
"version": "4.0.3",
"description": "Ethereum wallet library.",
"main": "./index.js",
"types": "./index.d.ts",
@@ -9,7 +9,7 @@
"auto-build": "npm run build -- -w",
"dist": "npm run dist-version && npm run build && gulp default minified && npm run dist-types",
"dist-test": "gulp default-test minified-test",
"dist-bip39": "gulp bip39-it bip39-ja bip39-ko bip39-zh",
"dist-bip39": "gulp bip39-es bip39-fr bip39-it bip39-ja bip39-ko bip39-zh",
"dist-types": "dts-bundle --name ethers --main ./index.d.ts --out ./dist/ethers.types.txt",
"dist-version": "node -e \"let v = require('./package.json').version; require('fs').writeFileSync('./src.ts/_version.ts', 'export const version = \\\"' + v +'\\\";\\n')\"",
"eslint": "eslint index.js contracts/*.js providers/*.js utils/*.js wallet/*.js wordlists/*.js",
@@ -25,7 +25,7 @@
"elliptic": "6.3.3",
"hash.js": "1.1.3",
"js-sha3": "0.5.7",
"scrypt-js": "2.0.3",
"scrypt-js": "2.0.4",
"setimmediate": "1.0.4",
"uuid": "2.0.1",
"xmlhttprequest": "1.8.0"

View File

@@ -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;

View File

@@ -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>;

View File

@@ -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)
};
@@ -344,6 +346,9 @@ function serializeTopics(topics) {
});
return topic.join(',');
}
else if (topic === null) {
return '';
}
return errors.throwError('invalid topic value', errors.INVALID_ARGUMENT, { argument: 'topic', value: topic });
}).join('&');
}
@@ -356,7 +361,12 @@ function deserializeTopics(data) {
}
return topic;
}
return comps;
return comps.map(function (topic) {
if (topic === '') {
return null;
}
return topic;
});
});
}
function getEventTag(eventName) {
@@ -380,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) {
@@ -412,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;
@@ -566,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;
@@ -587,6 +635,7 @@ var BaseProvider = /** @class */ (function (_super) {
if (value != result) {
throw new Error('invalid response - getBlockNumber');
}
_this._setFastBlockNumber(value);
return value;
});
});
@@ -680,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;
@@ -690,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
});
}
@@ -796,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 });
});
@@ -816,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 });
});

View File

@@ -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;
});

View File

@@ -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;
});

View File

@@ -1 +1 @@
export const version = "4.0.0";
export const version = "4.0.3";

View File

@@ -53,6 +53,14 @@ export interface Event extends Log {
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 {
@@ -256,7 +264,42 @@ function runMethod(contract: Contract, functionName: string, estimateOnly: boole
errors.throwError('cannot override from in a transaction', errors.UNSUPPORTED_OPERATION, { operation: 'sendTransaction' })
}
return contract.signer.sendTransaction(tx);
return contract.signer.sendTransaction(tx).then((tx) => {
let wait = tx.wait.bind(tx);
tx.wait = (confirmations?: number) => {
return wait(confirmations).then((receipt: ContractReceipt) => {
receipt.events = receipt.logs.map((log) => {
let event: Event = (<Event>deepCopy(log));
let 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 = () => { return this.provider; }
event.getBlock = () => {
return this.provider.getBlock(receipt.blockHash);
}
event.getTransaction = () => {
return this.provider.getTransaction(receipt.transactionHash);
}
event.getTransactionReceipt = () => {
return Promise.resolve(receipt);
}
return event;
});
return receipt;
});
};
return tx;
});
}
throw new Error('invalid type - ' + method.type);

View File

@@ -1,5 +1,7 @@
'use strict';
import { version } from './_version';
// Unknown Error
export const UNKNOWN_ERROR = 'UNKNOWN_ERROR';
@@ -69,21 +71,23 @@ export function throwError(message: string, code: string, params: any): never {
if (!code) { code = UNKNOWN_ERROR; }
if (!params) { params = {}; }
var messageDetails: Array<string> = [];
Object.keys(params).forEach(function(key) {
let messageDetails: Array<string> = [];
Object.keys(params).forEach((key) => {
try {
messageDetails.push(key + '=' + JSON.stringify(params[key]));
} catch (error) {
messageDetails.push(key + '=' + JSON.stringify(params[key].toString()));
}
});
var reason = message;
messageDetails.push("version=" + version);
let reason = message;
if (messageDetails.length) {
message += ' (' + messageDetails.join(', ') + ')';
}
// @TODO: Any??
var error: any = new Error(message);
let error: any = new Error(message);
error.reason = reason;
error.code = code

View File

@@ -26,7 +26,7 @@ import { version } from './_version';
////////////////////////
// Types
import { ContractFunction, Event, EventFilter } from './contract';
import { ContractFunction, ContractTransaction, Event, EventFilter } from './contract';
////////////////////////
@@ -72,6 +72,7 @@ export {
// Types
ContractFunction,
ContractTransaction,
Event,
EventFilter
};

View File

@@ -69,6 +69,7 @@ export interface TransactionReceipt {
transactionHash?: string,
logs?: Array<Log>,
blockNumber?: number,
confirmations?: number,
cumulativeGasUsed?: BigNumber,
byzantium: boolean,
status?: number
@@ -93,6 +94,8 @@ export interface TransactionResponse extends Transaction {
blockHash?: string,
timestamp?: number,
confirmations: number,
// Not optional (as it is in Transaction)
from: string;
@@ -100,7 +103,7 @@ export interface TransactionResponse extends Transaction {
raw?: string,
// This function waits until the transaction has been mined
wait: (timeout?: number) => Promise<TransactionReceipt>
wait: (confirmations?: number) => Promise<TransactionReceipt>
};
export type EventType = string | Array<string> | Filter;

View File

@@ -156,6 +156,8 @@ const formatTransaction = {
blockNumber: allowNull(checkNumber, null),
transactionIndex: allowNull(checkNumber, null),
confirmations: allowNull(checkNumber, null),
from: getAddress,
gasPrice: bigNumberify,
@@ -236,7 +238,7 @@ function checkTransactionResponse(transaction: any): TransactionResponse {
if (typeof(networkId) !== 'number') { networkId = 0; }
result.networkId = networkId;
// 0x0000... should actually be null
if (result.blockHash && result.blockHash.replace(/0/g, '') === 'x') {
result.blockHash = null;
@@ -313,6 +315,7 @@ const formatTransactionReceipt = {
transactionHash: checkHash,
logs: arrayOf(checkTransactionReceiptLog),
blockNumber: checkNumber,
confirmations: allowNull(checkNumber, null),
cumulativeGasUsed: bigNumberify,
status: allowNull(checkNumber)
};
@@ -377,6 +380,7 @@ function checkLog(log: any): any {
return check(formatLog, log);
}
//////////////////////////////
// Event Serializeing
@@ -438,6 +442,13 @@ function getEventTag(eventName: EventType): string {
throw new Error('invalid event - ' + eventName);
}
//////////////////////////////
// Helper Object
function getTime() {
return (new Date()).getTime();
}
//////////////////////////////
// Provider Object
@@ -473,6 +484,10 @@ export class BaseProvider extends Provider {
// string => BigNumber
private _balances: any;
private _fastBlockNumber: number;
private _fastBlockNumberPromise: Promise<number>;
private _fastQueryDate: number;
/**
* ready
@@ -521,10 +536,13 @@ export class BaseProvider extends Provider {
// until we get a response. This provides devs with a consistent view. Similarly for
// transaction hashes.
this._emitted = { block: this._lastBlockNumber };
this._fastQueryDate = 0;
}
private _doPoll(): void {
this.getBlockNumber().then((blockNumber) => {
this._setFastBlockNumber(blockNumber);
// If the block hasn't changed, meh.
if (blockNumber === this._lastBlockNumber) { return; }
@@ -665,13 +683,45 @@ export class BaseProvider extends Provider {
}
}
_getFastBlockNumber(): Promise<number> {
let now = getTime();
// Stale block number, request a newer value
if ((now - this._fastQueryDate) > 2 * this._pollingInterval) {
this._fastQueryDate = now;
this._fastBlockNumberPromise = this.getBlockNumber().then((blockNumber) => {
if (this._fastBlockNumber == null || blockNumber > this._fastBlockNumber) {
this._fastBlockNumber = blockNumber;
}
return this._fastBlockNumber;
});
}
return this._fastBlockNumberPromise;
}
_setFastBlockNumber(blockNumber: number): void {
// 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
waitForTransaction(transactionHash: string, timeout?: number): Promise<TransactionReceipt> {
waitForTransaction(transactionHash: string, confirmations?: number): Promise<TransactionReceipt> {
if (!confirmations) { confirmations = 1; }
return poll(() => {
return this.getTransactionReceipt(transactionHash).then((receipt) => {
if (receipt == null) { return undefined; }
if (receipt == null || receipt.confirmations < confirmations) { return undefined; }
return receipt;
});
}, { onceBlock: this });
@@ -680,8 +730,9 @@ export class BaseProvider extends Provider {
getBlockNumber(): Promise<number> {
return this.ready.then(() => {
return this.perform('getBlockNumber', { }).then((result) => {
var value = parseInt(result);
let value = parseInt(result);
if (value != result) { throw new Error('invalid response - getBlockNumber'); }
this._setFastBlockNumber(value);
return value;
});
});
@@ -771,7 +822,7 @@ export class BaseProvider extends Provider {
// This should be called by any subclass wrapping a TransactionResponse
_wrapTransaction(tx: Transaction, hash?: string): TransactionResponse {
if (hexDataLength(hash) !== 32) { throw new Error('invalid response - sendTransaction'); }
if (hash != null && hexDataLength(hash) !== 32) { throw new Error('invalid response - sendTransaction'); }
let result: TransactionResponse = <TransactionResponse>tx;
@@ -781,12 +832,13 @@ export class BaseProvider extends Provider {
}
this._emitted['t:' + tx.hash] = 'pending';
// @TODO: (confirmations? number, timeout? number)
result.wait = () => {
return this.waitForTransaction(hash).then((receipt) => {
result.wait = (confirmations?: number) => {
return this.waitForTransaction(tx.hash, confirmations).then((receipt) => {
if (receipt.status === 0) {
errors.throwError('transaction failed', errors.CALL_EXCEPTION, {
transactionHash: hash,
transactionHash: tx.hash,
transaction: tx
});
}
@@ -883,7 +935,7 @@ export class BaseProvider extends Provider {
getTransaction(transactionHash: string): Promise<TransactionResponse> {
return this.ready.then(() => {
return resolveProperties({ transactionHash: transactionHash }).then(({ transactionHash }) => {
var params = { transactionHash: checkHash(transactionHash) };
let params = { transactionHash: checkHash(transactionHash) };
return poll(() => {
return this.perform('getTransaction', params).then((result) => {
if (result == null) {
@@ -892,7 +944,25 @@ export class BaseProvider extends Provider {
}
return undefined;
}
return BaseProvider.checkTransactionResponse(result);
let tx = BaseProvider.checkTransactionResponse(result);
if (tx.blockNumber == null) {
tx.confirmations = 0;
} else if (tx.confirmations == null) {
return this._getFastBlockNumber().then((blockNumber) => {
// Add the confirmations using the fast block number (pessimistic)
let confirmations = (blockNumber - tx.blockNumber) + 1;
if (confirmations <= 0) { confirmations = 1; }
tx.confirmations = confirmations;
return this._wrapTransaction(tx);
});
}
return this._wrapTransaction(tx);
});
}, { onceBlock: this });
});
@@ -902,7 +972,7 @@ export class BaseProvider extends Provider {
getTransactionReceipt(transactionHash: string): Promise<TransactionReceipt> {
return this.ready.then(() => {
return resolveProperties({ transactionHash: transactionHash }).then(({ transactionHash }) => {
var params = { transactionHash: checkHash(transactionHash) };
let params = { transactionHash: checkHash(transactionHash) };
return poll(() => {
return this.perform('getTransactionReceipt', params).then((result) => {
if (result == null) {
@@ -911,7 +981,28 @@ export class BaseProvider extends Provider {
}
return undefined;
}
return checkTransactionReceipt(result);
// "geth-etc" returns receipts before they are ready
if (result.blockHash == null) { return undefined; }
let receipt = checkTransactionReceipt(result);
if (receipt.blockNumber == null) {
receipt.confirmations = 0;
} else if (receipt.confirmations == null) {
return this._getFastBlockNumber().then((blockNumber) => {
// Add the confirmations using the fast block number (pessimistic)
let confirmations = (blockNumber - receipt.blockNumber) + 1;
if (confirmations <= 0) { confirmations = 1; }
receipt.confirmations = confirmations;
return receipt;
});
}
return receipt;
});
}, { onceBlock: this });
});

View File

@@ -152,17 +152,19 @@ export class EtherscanProvider extends BaseProvider{
url += '/api?module=proxy&action=eth_sendRawTransaction&hex=' + params.signedTransaction;
url += apiKey;
return fetchJson(url, null, getJsonResult).catch((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;
});

View File

@@ -135,21 +135,23 @@ export class JsonRpcSigner extends Signer {
throw error;
});
}, (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;
});
@@ -266,17 +268,19 @@ export class JsonRpcProvider extends BaseProvider {
case 'sendTransaction':
return this.send('eth_sendRawTransaction', [ params.signedTransaction ]).catch((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;
});

View File

@@ -89,6 +89,9 @@ export class BigNumber implements Hexable {
} else if ((<any>value).toHexString) {
defineReadOnly(this, '_hex', toHex(toBN((<any>value).toHexString())));
} else if ((<any>value)._hex && isHexString((<any>value)._hex)) {
defineReadOnly(this, '_hex', (<any>value)._hex);
} else if (isArrayish(value)) {
defineReadOnly(this, '_hex', toHex(new BN.BN(hexlify(value).substring(2), 16)));

View File

@@ -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);

View File

@@ -118,6 +118,9 @@ export function fetchJson(connection: string | ConnectionInfo, json: string, pro
// @TODO: not any!
let error: any = new Error('invalid response - ' + request.status);
error.statusCode = request.status;
if (request.responseText) {
error.responseText = request.responseText;
}
reject(error);
return;
}

View File

@@ -165,7 +165,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); }

View File

@@ -1,21 +1,29 @@
'use strict';
// Wordlists
// See: https://github.com/bitcoin/bips/blob/master/bip-0039/bip-0039-wordlists.md
import { Wordlist } from '../utils/wordlist';
import { langEn as _en } from './lang-en';
import { langEs as _es } from './lang-es';
import { langFr as _fr } from './lang-fr';
import { langJa as _ja } from './lang-ja';
import { langKo as _ko } from './lang-ko';
import { langIt as _it } from './lang-it';
import { langEn as _en } from './lang-en';
import { langZhCn as _zh_cn, langZhTw as _zh_tw } from './lang-zh';
const en: Wordlist = _en;
const ko: Wordlist = _ko;
const es: Wordlist = _es;
const fr: Wordlist = _fr;
const it: Wordlist = _it;
const ja: Wordlist = _ja;
const ko: Wordlist = _ko;
const zh: Wordlist = _zh_cn;
const zh_cn: Wordlist = _zh_cn;
const zh_tw: Wordlist = _zh_tw;
export {
en, it, ja, ko, zh, zh_cn, zh_tw
en, es, fr, it, ja, ko, zh, zh_cn, zh_tw
}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -9,6 +9,7 @@ var ethers = utils.getEthers(__filename);
describe("Package Version", function() {
var url = "http://registry.npmjs.org/ethers"
it("is not already published", function() {
this.timeout(20000);
return ethers.utils.fetchJson(url).then(function(data) {
assert.ok(Object.keys(data.versions).indexOf(ethers.version) === -1);
});

View File

@@ -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');

View File

@@ -302,6 +302,11 @@ function testProvider(providerName, networkName) {
function testTransactionReceipt(expected) {
var title = ('Receipt ' + expected.transactionHash.substring(0, 10) + ' - ');
return provider.getTransactionReceipt(expected.transactionHash).then(function(receipt) {
// This changes with every block
assert.equal(typeof(receipt.confirmations), 'number', 'confirmations is a number');
delete receipt.confirmations;
for (var key in receipt) {
equals((title + key), receipt[key], expected[key]);
}
@@ -326,6 +331,14 @@ function testProvider(providerName, networkName) {
function testTransaction(expected) {
var title = ('Transaction ' + expected.hash.substring(0, 10) + ' - ');
return provider.getTransaction(expected.hash).then(function(tx) {
// This changes with every block
assert.equal(typeof(tx.confirmations), 'number', 'confirmations is a number');
delete tx.confirmations;
assert.equal(typeof(tx.wait), 'function', 'wait is a function');
delete tx.wait
for (var key in tx) {
equals((title + key), tx[key], expected[key]);
}

View File

@@ -19,6 +19,8 @@ function checkWordlist(filename, wordlist) {
describe('Check Wordlists', function() {
checkWordlist('./wordlist-generation/lang-en.txt', ethers.wordlists.en);
checkWordlist('./wordlist-generation/lang-es.txt', ethers.wordlists.es);
checkWordlist('./wordlist-generation/lang-fr.txt', ethers.wordlists.fr);
checkWordlist('./wordlist-generation/lang-it.txt', ethers.wordlists.it);
checkWordlist('./wordlist-generation/lang-ja.txt', ethers.wordlists.ja);
checkWordlist('./wordlist-generation/lang-ko.txt', ethers.wordlists.ko);

View File

@@ -56,6 +56,8 @@
<!-- Load the browser dist ethers package -->
<script type="text/javascript" src="../dist/ethers.min.js"></script>
<script type="text/javascript" src="../dist/wordlist-es.js"></script>
<script type="text/javascript" src="../dist/wordlist-fr.js"></script>
<script type="text/javascript" src="../dist/wordlist-it.js"></script>
<script type="text/javascript" src="../dist/wordlist-ja.js"></script>
<script type="text/javascript" src="../dist/wordlist-ko.js"></script>

View File

@@ -0,0 +1,49 @@
var fs = require('fs');
var ethers = require('../../');
var words = fs.readFileSync('./lang-es.txt').toString();
console.log(ethers.utils.id(words));
words = words.split('\x0a');
var chars = {};
var charsByte = {};
var data = words.map((word) => {
if (!word) { return ''; }
word = word[0].toUpperCase() + word.substring(1);
/*
for (var i = 0; i < word.length; i++) {
chars[word[i]] = (chars[word[i]] || 0) + 1;
charsByte[word[i]] = [ word, ethers.utils.toUtf8Bytes(word) ];
}
*/
return word;
}).join('');
data = ethers.utils.toUtf8Bytes(data);
var output= []
for (var i = 0; i < data.length; i++) {
var c = data[i];
chars[data[i]] = (chars[data[i]] || 0) + 1;
if ((c >= 65 && c <= 90) || (c >= 97 && c <= 123)) {
output.push(c);
} else if (c === 129) {
output.push(0x30);
} else if (c === 131) {
output.push(0x31);
} else if (c === 204) {
output.push(0x32);
} else {
console.log(c);
}
}
//console.log(chars);
output = ethers.utils.toUtf8String(output);
output = output.replace(/n21/g, '~').replace(/20/g, '/')
console.log('Output:', output);

View File

@@ -0,0 +1,43 @@
var fs = require('fs');
var ethers = require('../../');
var words = fs.readFileSync('./lang-fr.txt').toString();
console.log(ethers.utils.id(words));
words = words.split('\x0a');
var chars = {};
var charsByte = {};
var data = words.map((word) => {
if (!word) { return ''; }
word = word[0].toUpperCase() + word.substring(1);
return word;
}).join('');
data = ethers.utils.toUtf8Bytes(data);
var output= []
for (var i = 0; i < data.length; i++) {
var c = data[i];
chars[data[i]] = (chars[data[i]] || 0) + 1;
if ((c >= 65 && c <= 90) || (c >= 97 && c <= 123)) {
output.push(c);
} else if (c === 128) {
output.push(0x31);
} else if (c === 129) {
output.push(0x30);
} else if (c === 204) {
output.push(0x32);
} else {
console.log(c);
}
}
//console.log(chars);
output = ethers.utils.toUtf8String(output);
output = output.replace(/21/g, '-').replace(/20/g, '/')
console.log('Output:', output);

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -89,6 +89,9 @@ var BigNumber = /** @class */ (function () {
else if (value.toHexString) {
properties_1.defineReadOnly(this, '_hex', toHex(toBN(value.toHexString())));
}
else if (value._hex && bytes_1.isHexString(value._hex)) {
properties_1.defineReadOnly(this, '_hex', value._hex);
}
else if (bytes_1.isArrayish(value)) {
properties_1.defineReadOnly(this, '_hex', toHex(new bn_js_1.default.BN(bytes_1.hexlify(value).substring(2), 16)));
}

View File

@@ -48,18 +48,17 @@ function shallowCopy(object) {
exports.shallowCopy = shallowCopy;
var opaque = { boolean: true, number: true, string: true };
function deepCopy(object, frozen) {
// Opaque objects are not mutable, so safe to copy by assignment
if (object === undefined || object === null || opaque[typeof (object)]) {
return object;
}
// Arrays are mutable, so we need to create a copy
if (Array.isArray(object)) {
var result_1 = [];
object.forEach(function (item) {
result_1.push(deepCopy(item, frozen));
});
var result = object.map(function (item) { return deepCopy(item, frozen); });
if (frozen) {
Object.freeze(result_1);
Object.freeze(result);
}
return result_1;
return result;
}
if (typeof (object) === 'object') {
// Some internal objects, which are already immutable
@@ -85,6 +84,10 @@ function deepCopy(object, frozen) {
}
return result;
}
// The function type is also immutable, so safe to copy by assignment
if (typeof (object) === 'function') {
return object;
}
throw new Error('Cannot deepCopy ' + typeof (object));
}
exports.deepCopy = deepCopy;

View File

@@ -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;
}

View File

@@ -1,9 +1,11 @@
import { Wordlist } from '../utils/wordlist';
declare const en: Wordlist;
declare const ko: Wordlist;
declare const es: Wordlist;
declare const fr: Wordlist;
declare const it: Wordlist;
declare const ja: Wordlist;
declare const ko: Wordlist;
declare const zh: Wordlist;
declare const zh_cn: Wordlist;
declare const zh_tw: Wordlist;
export { en, it, ja, ko, zh, zh_cn, zh_tw };
export { en, es, fr, it, ja, ko, zh, zh_cn, zh_tw };

View File

@@ -1,18 +1,24 @@
'use strict';
Object.defineProperty(exports, "__esModule", { value: true });
var lang_en_1 = require("./lang-en");
var lang_es_1 = require("./lang-es");
var lang_fr_1 = require("./lang-fr");
var lang_ja_1 = require("./lang-ja");
var lang_ko_1 = require("./lang-ko");
var lang_it_1 = require("./lang-it");
var lang_en_1 = require("./lang-en");
var lang_zh_1 = require("./lang-zh");
var en = lang_en_1.langEn;
exports.en = en;
var ko = lang_ko_1.langKo;
exports.ko = ko;
var es = lang_es_1.langEs;
exports.es = es;
var fr = lang_fr_1.langFr;
exports.fr = fr;
var it = lang_it_1.langIt;
exports.it = it;
var ja = lang_ja_1.langJa;
exports.ja = ja;
var ko = lang_ko_1.langKo;
exports.ko = ko;
var zh = lang_zh_1.langZhCn;
exports.zh = zh;
var zh_cn = lang_zh_1.langZhCn;

8
wordlists/lang-es.d.ts vendored Normal file
View File

@@ -0,0 +1,8 @@
import { Wordlist } from '../utils/wordlist';
declare class LangEs extends Wordlist {
constructor();
getWord(index: number): string;
getWordIndex(word: string): number;
}
declare const langEs: LangEs;
export { langEs };

77
wordlists/lang-es.js Normal file

File diff suppressed because one or more lines are too long

8
wordlists/lang-fr.d.ts vendored Normal file
View File

@@ -0,0 +1,8 @@
import { Wordlist } from '../utils/wordlist';
declare class LangFr extends Wordlist {
constructor();
getWord(index: number): string;
getWordIndex(word: string): number;
}
declare const langFr: LangFr;
export { langFr };

76
wordlists/lang-fr.js Normal file

File diff suppressed because one or more lines are too long