Compare commits

..

9 Commits

Author SHA1 Message Date
Richard Moore
6ca1d77298 Fixed function name in parsed transactions (#370). 2018-12-08 18:46:29 -05:00
Richard Moore
4f6748ec4c Include request body in web errors. 2018-12-05 04:19:34 -05:00
Richard Moore
f56fc572f1 Squashed unhandled promise exception for Providers that are never used (#362). 2018-12-05 04:18:47 -05:00
Richard Moore
16fdf6b621 Added gas estimation back into JsonRpcSigner (#365). 2018-12-05 03:32:24 -05:00
Richard Moore
a863037ca3 Updated dist files. 2018-12-04 17:16:42 -05:00
Richard Moore
2d854bd94c Do not fill in implicit values for JSON-RPC based signers (#335). 2018-12-04 17:13:55 -05:00
Richard Moore
9565c28a91 More relaxed transaction parsing (#357). 2018-12-04 16:31:18 -05:00
Richard Moore
bc457bb3bd Allow any whitespace characters in human-readable ABI (#360). 2018-12-04 16:14:57 -05:00
Richard Moore
db383a3121 Updated dist files. 2018-11-27 17:32:47 -05:00
19 changed files with 129 additions and 53 deletions

2
_version.d.ts vendored
View File

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

View File

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

View File

@@ -106,7 +106,6 @@ 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];
@@ -218,19 +217,19 @@ function runMethod(contract, functionName, estimateOnly) {
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);
var parsed = contract.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.removeListener = function () { return contract.provider; };
event.getBlock = function () {
return _this.provider.getBlock(receipt.blockHash);
return contract.provider.getBlock(receipt.blockHash);
};
event.getTransaction = function () {
return _this.provider.getTransaction(receipt.transactionHash);
return contract.provider.getTransaction(receipt.transactionHash);
};
event.getTransactionReceipt = function () {
return Promise.resolve(receipt);

46
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.14";
exports.version = "4.0.17";
},{}],2:[function(require,module,exports){
"use strict";
@@ -154,7 +154,6 @@ 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];
@@ -266,19 +265,19 @@ function runMethod(contract, functionName, estimateOnly) {
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);
var parsed = contract.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.removeListener = function () { return contract.provider; };
event.getBlock = function () {
return _this.provider.getBlock(receipt.blockHash);
return contract.provider.getBlock(receipt.blockHash);
};
event.getTransaction = function () {
return _this.provider.getTransaction(receipt.transactionHash);
return contract.provider.getTransaction(receipt.transactionHash);
};
event.getTransactionReceipt = function () {
return Promise.resolve(receipt);
@@ -11628,7 +11627,6 @@ var address_1 = require("../utils/address");
var bytes_1 = require("../utils/bytes");
var networks_1 = require("../utils/networks");
var properties_1 = require("../utils/properties");
var transaction_1 = require("../utils/transaction");
var utf8_1 = require("../utils/utf8");
var web_1 = require("../utils/web");
function timer(timeout) {
@@ -11702,17 +11700,28 @@ var JsonRpcSigner = /** @class */ (function (_super) {
};
JsonRpcSigner.prototype.sendTransaction = function (transaction) {
var _this = this;
// Once populateTransaction resolves, the from address will be populated from getAddress
var from = null;
var getAddress = this.getAddress().then(function (address) {
transaction = properties_1.shallowCopy(transaction);
var fromAddress = this.getAddress().then(function (address) {
if (address) {
from = address.toLowerCase();
address = address.toLowerCase();
}
return from;
return address;
});
return transaction_1.populateTransaction(transaction, this.provider, getAddress).then(function (tx) {
// The JSON-RPC for eth_sendTransaction uses 90000 gas; if the user
// wishes to use this, it is easy to specify explicitly, otherwise
// we look it up for them.
if (transaction.gasLimit == null) {
var estimate = properties_1.shallowCopy(transaction);
estimate.from = fromAddress;
transaction.gasLimit = this.provider.estimateGas(estimate);
}
return Promise.all([
properties_1.resolveProperties(transaction),
fromAddress
]).then(function (results) {
var tx = results[0];
var hexTx = JsonRpcProvider.hexlifyTransaction(tx);
hexTx.from = from;
hexTx.from = results[1];
return _this.provider.send('eth_sendTransaction', [hexTx]).then(function (hash) {
return web_1.poll(function () {
return _this.provider.getTransaction(hash).then(function (tx) {
@@ -11980,7 +11989,7 @@ var JsonRpcProvider = /** @class */ (function (_super) {
}(base_provider_1.BaseProvider));
exports.JsonRpcProvider = JsonRpcProvider;
},{"../abstract-signer":2,"../errors":5,"../utils/address":59,"../utils/bytes":62,"../utils/networks":70,"../utils/properties":72,"../utils/transaction":81,"../utils/utf8":83,"../utils/web":84,"./base-provider":50}],57:[function(require,module,exports){
},{"../abstract-signer":2,"../errors":5,"../utils/address":59,"../utils/bytes":62,"../utils/networks":70,"../utils/properties":72,"../utils/utf8":83,"../utils/web":84,"./base-provider":50}],57:[function(require,module,exports){
'use strict';
var __extends = (this && this.__extends) || (function () {
var extendStatics = Object.setPrototypeOf ||
@@ -12121,9 +12130,11 @@ function verifyType(type) {
return type;
}
function parseParam(param, allowIndexed) {
var originalParam = param;
function throwError(i) {
throw new Error('unexpected character "' + param[i] + '" at position ' + i + ' in "' + param + '"');
throw new Error('unexpected character "' + originalParam[i] + '" at position ' + i + ' in "' + originalParam + '"');
}
param = param.replace(/\s/g, ' ');
var parent = { type: '', name: '', state: { allowType: true } };
var node = parent;
for (var i = 0; i < param.length; i++) {
@@ -12368,6 +12379,7 @@ exports.formatSignature = formatSignature;
function parseSignature(fragment) {
if (typeof (fragment) === 'string') {
// Make sure the "returns" is surrounded by a space and all whitespace is exactly one space
fragment = fragment.replace(/\s/g, ' ');
fragment = fragment.replace(/\(/g, ' (').replace(/\)/g, ') ').replace(/\s+/g, ' ');
fragment = fragment.trim();
if (fragment.substring(0, 6) === 'event ') {
@@ -14390,7 +14402,7 @@ var Interface = /** @class */ (function () {
name: name,
signature: func.signature,
sighash: func.sighash,
value: bignumber_1.bigNumberify(tx.value || null),
value: bignumber_1.bigNumberify(tx.value || '0'),
});
}
}

2
dist/ethers.min.js vendored

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -262,7 +262,7 @@ declare module 'ethers/utils/shims' {
}
declare module 'ethers/_version' {
export const version = "4.0.14";
export const version = "4.0.17";
}
declare module 'ethers/utils/bignumber' {

2
package-lock.json generated
View File

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

View File

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

View File

@@ -25,7 +25,6 @@ var address_1 = require("../utils/address");
var bytes_1 = require("../utils/bytes");
var networks_1 = require("../utils/networks");
var properties_1 = require("../utils/properties");
var transaction_1 = require("../utils/transaction");
var utf8_1 = require("../utils/utf8");
var web_1 = require("../utils/web");
function timer(timeout) {
@@ -99,17 +98,28 @@ var JsonRpcSigner = /** @class */ (function (_super) {
};
JsonRpcSigner.prototype.sendTransaction = function (transaction) {
var _this = this;
// Once populateTransaction resolves, the from address will be populated from getAddress
var from = null;
var getAddress = this.getAddress().then(function (address) {
transaction = properties_1.shallowCopy(transaction);
var fromAddress = this.getAddress().then(function (address) {
if (address) {
from = address.toLowerCase();
address = address.toLowerCase();
}
return from;
return address;
});
return transaction_1.populateTransaction(transaction, this.provider, getAddress).then(function (tx) {
// The JSON-RPC for eth_sendTransaction uses 90000 gas; if the user
// wishes to use this, it is easy to specify explicitly, otherwise
// we look it up for them.
if (transaction.gasLimit == null) {
var estimate = properties_1.shallowCopy(transaction);
estimate.from = fromAddress;
transaction.gasLimit = this.provider.estimateGas(estimate);
}
return Promise.all([
properties_1.resolveProperties(transaction),
fromAddress
]).then(function (results) {
var tx = results[0];
var hexTx = JsonRpcProvider.hexlifyTransaction(tx);
hexTx.from = from;
hexTx.from = results[1];
return _this.provider.send('eth_sendTransaction', [hexTx]).then(function (hash) {
return web_1.poll(function () {
return _this.provider.getTransaction(hash).then(function (tx) {

View File

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

View File

@@ -530,6 +530,9 @@ export class BaseProvider extends Provider {
return network;
}));
// Squash any "unhandled promise" errors; the don't need to be handled
this.ready.catch((error) => { });
} else {
let knownNetwork = getNetwork((network == null) ? 'homestead': network);
if (knownNetwork) {

View File

@@ -12,8 +12,7 @@ import { getAddress } from '../utils/address';
import { BigNumber } from '../utils/bignumber';
import { hexlify, hexStripZeros } from '../utils/bytes';
import { getNetwork } from '../utils/networks';
import { checkProperties, defineReadOnly, shallowCopy } from '../utils/properties';
import { populateTransaction } from '../utils/transaction';
import { checkProperties, defineReadOnly, resolveProperties, shallowCopy } from '../utils/properties';
import { toUtf8Bytes } from '../utils/utf8';
import { fetchJson, poll } from '../utils/web';
@@ -103,17 +102,29 @@ export class JsonRpcSigner extends Signer {
}
sendTransaction(transaction: TransactionRequest): Promise<TransactionResponse> {
transaction = shallowCopy(transaction);
// Once populateTransaction resolves, the from address will be populated from getAddress
let from: string = null;
let getAddress = this.getAddress().then((address) => {
if (address) { from = address.toLowerCase(); }
return from;
let fromAddress = this.getAddress().then((address) => {
if (address) { address = address.toLowerCase(); }
return address;
});
return populateTransaction(transaction, this.provider, getAddress).then((tx) => {
// The JSON-RPC for eth_sendTransaction uses 90000 gas; if the user
// wishes to use this, it is easy to specify explicitly, otherwise
// we look it up for them.
if (transaction.gasLimit == null) {
let estimate = shallowCopy(transaction);
estimate.from = fromAddress;
transaction.gasLimit = this.provider.estimateGas(estimate);
}
return Promise.all([
resolveProperties(transaction),
fromAddress
]).then((results) => {
let tx = results[0];
let hexTx = JsonRpcProvider.hexlifyTransaction(tx);
hexTx.from = from;
hexTx.from = results[1];
return this.provider.send('eth_sendTransaction', [ hexTx ]).then((hash) => {
return poll(() => {
return this.provider.getTransaction(hash).then((tx: TransactionResponse) => {

View File

@@ -107,9 +107,12 @@ type ParseNode = {
function parseParam(param: string, allowIndexed?: boolean): ParamType {
let originalParam = param;
function throwError(i: number) {
throw new Error('unexpected character "' + param[i] + '" at position ' + i + ' in "' + param + '"');
throw new Error('unexpected character "' + originalParam[i] + '" at position ' + i + ' in "' + originalParam + '"');
}
param = param.replace(/\s/g, ' ');
var parent: ParseNode = { type: '', name: '', state: { allowType: true } };
var node = parent;
@@ -380,6 +383,7 @@ export function formatSignature(fragment: EventFragment | FunctionFragment): str
export function parseSignature(fragment: string): EventFragment | FunctionFragment {
if(typeof(fragment) === 'string') {
// Make sure the "returns" is surrounded by a space and all whitespace is exactly one space
fragment = fragment.replace(/\s/g, ' ');
fragment = fragment.replace(/\(/g, ' (').replace(/\)/g, ') ').replace(/\s+/g, ' ');
fragment = fragment.trim();

View File

@@ -320,6 +320,7 @@ function addMethod(method: any): void {
payable: (method.payable == null || !!method.payable),
type: ((method.constant) ? 'call': 'transaction'),
name: method.name,
signature: signature,
sighash: sighash,
});
@@ -433,10 +434,10 @@ export class Interface {
return new _TransactionDescription({
args: result,
decode: func.decode,
name: name,
name: func.name,
signature: func.signature,
sighash: func.sighash,
value: bigNumberify(tx.value || null),
value: bigNumberify(tx.value || '0'),
});
}
}

View File

@@ -135,6 +135,9 @@ export function fetchJson(connection: string | ConnectionInfo, json: string, pro
let jsonError: any = new Error('invalid json response');
jsonError.orginialError = error;
jsonError.responseText = request.responseText;
if (json != null) {
jsonError.requestBody = json;
}
jsonError.url = url;
reject(jsonError);
return;
@@ -163,7 +166,7 @@ export function fetchJson(connection: string | ConnectionInfo, json: string, pro
}
try {
if (json) {
if (json != null) {
request.send(json);
} else {
request.send();

View File

@@ -231,6 +231,36 @@ describe('Test Interface Signatures', function() {
'derived the correct signature hash');
})
});
it('derives correct description for human-readable ABI', function() {
var iface = new Interface([ "function transfer(address from, uint amount)" ]);
[
"transfer",
"transfer(address,uint256)"
].forEach(function(key) {
var descr = iface.functions[key];
assert.equal(descr.name, "transfer", "incorrect name key - " + key);
assert.equal(descr.signature, "transfer(address,uint256)", "incorrect signature key - " + key);
assert.equal(descr.sighash, "0xa9059cbb", "incorrect sighash key - " + key);
});
});
// See: https://github.com/ethers-io/ethers.js/issues/370
it ('parses transaction function', function() {
var iface = new Interface([ "function transfer(address from, uint amount)" ]);
// Transaction: 0x820cc57bc77be44d8f4f024a18e18f64a8b6e62a82a3d7897db5970dbe181ba1
var rawTx = "0xf8aa028502540be4008316e36094334eec1482109bd802d9e72a447848de3bcc106380b844a9059cbb000000000000000000000000851b9167b7cbf772d38efaf89705b35022880a070000000000000000000000000000000000000000000000000de0b6b3a764000026a03200bf26e5f10f7eda59c0aad9adc2334dda79e785b9b004342524d97a66fca9a0450b07a4dc450bb472e08f8370350fa365fcef6db1a95309ae4c06c9d0748092";
var tx = ethers.utils.parseTransaction(rawTx);
var descr = iface.parseTransaction(tx);
assert.equal(descr.args[0], '0x851b9167B7cbf772D38eFaf89705b35022880A07', 'parsed tx - args[0]');
assert.equal(descr.args[1].toString(), '1000000000000000000', 'parsed tx - args[1]');
assert.equal(descr.name, 'transfer', 'parsed tx - name');
assert.equal(descr.signature, 'transfer(address,uint256)', 'parsed tx - signature');
assert.equal(descr.sighash, '0xa9059cbb', 'parsed tx - sighash');
assert.equal(descr.value.toString(), '0', 'parsed tx - value');
});
});
describe('Test Number Coder', function() {

View File

@@ -51,9 +51,11 @@ function verifyType(type) {
return type;
}
function parseParam(param, allowIndexed) {
var originalParam = param;
function throwError(i) {
throw new Error('unexpected character "' + param[i] + '" at position ' + i + ' in "' + param + '"');
throw new Error('unexpected character "' + originalParam[i] + '" at position ' + i + ' in "' + originalParam + '"');
}
param = param.replace(/\s/g, ' ');
var parent = { type: '', name: '', state: { allowType: true } };
var node = parent;
for (var i = 0; i < param.length; i++) {
@@ -298,6 +300,7 @@ exports.formatSignature = formatSignature;
function parseSignature(fragment) {
if (typeof (fragment) === 'string') {
// Make sure the "returns" is surrounded by a space and all whitespace is exactly one space
fragment = fragment.replace(/\s/g, ' ');
fragment = fragment.replace(/\(/g, ' (').replace(/\)/g, ') ').replace(/\s+/g, ' ');
fragment = fragment.trim();
if (fragment.substring(0, 6) === 'event ') {

View File

@@ -342,7 +342,7 @@ var Interface = /** @class */ (function () {
name: name,
signature: func.signature,
sighash: func.sighash,
value: bignumber_1.bigNumberify(tx.value || null),
value: bignumber_1.bigNumberify(tx.value || '0'),
});
}
}