Compare commits

..

12 Commits

Author SHA1 Message Date
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
28 changed files with 269 additions and 105 deletions

2
_version.d.ts vendored
View File

@@ -1 +1 @@
export declare const version = "4.0.1";
export declare const version = "4.0.2";

View File

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

11
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.1";
exports.version = "4.0.2";
},{}],2:[function(require,module,exports){
"use strict";
@@ -718,6 +718,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
@@ -784,6 +785,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(', ') + ')';
@@ -825,7 +827,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;
@@ -9192,10 +9194,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)
@@ -13043,6 +13047,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)));
}

2
dist/ethers.min.js vendored

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -238,13 +238,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 +254,7 @@ declare module 'ethers/utils/shims' {
}
declare module 'ethers/_version' {
export const version = "4.0.1";
export const version = "4.0.2";
}
declare module 'ethers/utils/bignumber' {

2
dist/wordlist-es.js vendored

File diff suppressed because one or more lines are too long

2
dist/wordlist-fr.js vendored

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(', ') + ')';

6
package-lock.json generated
View File

@@ -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.1",
"version": "4.0.2",
"description": "Ethereum wallet library.",
"main": "./index.js",
"types": "./index.d.ts",

View File

@@ -1 +1 @@
export const version = "4.0.1";
export const version = "4.0.2";

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

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

@@ -9,19 +9,14 @@ let lookup: { [word: string]: number } = {};
let wordlist: Array<string> = null;
function dropDiacritic(word: string): string {
let output: Array<number> = [];
toUtf8Bytes(word.normalize('NFD').toLowerCase()).forEach((c) => {
if ((c >= 65 && c <= 90) || (c >= 97 && c <= 123)) {
output.push(c);
}
});
return toUtf8String(output);
return toUtf8String(Array.prototype.filter.call(toUtf8Bytes(word.normalize('NFD').toLowerCase()), (c: number) => {
return ((c >= 65 && c <= 90) || (c >= 97 && c <= 123));
}));
}
function expand(word: string): string {
let output: Array<number> = [];
toUtf8Bytes(word).forEach((c) => {
Array.prototype.forEach.call(toUtf8Bytes(word), (c: number) => {
// Acute accent
if (c === 47) {
output.push(204);

View File

@@ -9,19 +9,15 @@ let wordlist: Array<string> = null;
let lookup: { [word: string]: number } = { }
function dropDiacritic(word: string): string {
let output: Array<number> = [];
toUtf8Bytes(word.normalize('NFD').toLowerCase()).forEach((c) => {
if ((c >= 65 && c <= 90) || (c >= 97 && c <= 123)) {
output.push(c);
}
});
return toUtf8String(output);
return toUtf8String(Array.prototype.filter.call(toUtf8Bytes(word.normalize('NFD').toLowerCase()), (c: number) => {
return ((c >= 65 && c <= 90) || (c >= 97 && c <= 123));
}));
}
function expand(word: string): string {
let output: Array<number> = [];
toUtf8Bytes(word).forEach((c) => {
Array.prototype.forEach.call(toUtf8Bytes(word), (c: number) => {
// Acute accent
if (c === 47) {
output.push(204);

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

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

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

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

@@ -16,17 +16,13 @@ var words = "A/bacoAbdomenAbejaAbiertoAbogadoAbonoAbortoAbrazoAbrirAbueloAbusoAc
var lookup = {};
var wordlist = null;
function dropDiacritic(word) {
var output = [];
utf8_1.toUtf8Bytes(word.normalize('NFD').toLowerCase()).forEach(function (c) {
if ((c >= 65 && c <= 90) || (c >= 97 && c <= 123)) {
output.push(c);
}
});
return utf8_1.toUtf8String(output);
return utf8_1.toUtf8String(Array.prototype.filter.call(utf8_1.toUtf8Bytes(word.normalize('NFD').toLowerCase()), function (c) {
return ((c >= 65 && c <= 90) || (c >= 97 && c <= 123));
}));
}
function expand(word) {
var output = [];
utf8_1.toUtf8Bytes(word).forEach(function (c) {
Array.prototype.forEach.call(utf8_1.toUtf8Bytes(word), function (c) {
// Acute accent
if (c === 47) {
output.push(204);

View File

@@ -16,17 +16,13 @@ var words = "AbaisserAbandonAbdiquerAbeilleAbolirAborderAboutirAboyerAbrasifAbre
var wordlist = null;
var lookup = {};
function dropDiacritic(word) {
var output = [];
utf8_1.toUtf8Bytes(word.normalize('NFD').toLowerCase()).forEach(function (c) {
if ((c >= 65 && c <= 90) || (c >= 97 && c <= 123)) {
output.push(c);
}
});
return utf8_1.toUtf8String(output);
return utf8_1.toUtf8String(Array.prototype.filter.call(utf8_1.toUtf8Bytes(word.normalize('NFD').toLowerCase()), function (c) {
return ((c >= 65 && c <= 90) || (c >= 97 && c <= 123));
}));
}
function expand(word) {
var output = [];
utf8_1.toUtf8Bytes(word).forEach(function (c) {
Array.prototype.forEach.call(utf8_1.toUtf8Bytes(word), function (c) {
// Acute accent
if (c === 47) {
output.push(204);