web3-core-method
Advanced tools
Comparing version 1.2.1 to 1.2.2
{ | ||
"name": "web3-core-method", | ||
"version": "1.2.1", | ||
"version": "1.2.2", | ||
"description": "Creates the methods on the web3 modules. This is an internal package.", | ||
@@ -10,10 +10,18 @@ "repository": "https://github.com/ethereum/web3.js/tree/1.x/packages/web3-core-method", | ||
}, | ||
"types": "types/index.d.ts", | ||
"scripts": { | ||
"dtslint": "dtslint types --onlyTestTsNext" | ||
}, | ||
"main": "src/index.js", | ||
"dependencies": { | ||
"underscore": "1.9.1", | ||
"web3-core-helpers": "1.2.1", | ||
"web3-core-promievent": "1.2.1", | ||
"web3-core-subscriptions": "1.2.1", | ||
"web3-utils": "1.2.1" | ||
"web3-core-helpers": "1.2.2", | ||
"web3-core-promievent": "1.2.2", | ||
"web3-core-subscriptions": "1.2.2", | ||
"web3-utils": "1.2.2" | ||
}, | ||
"devDependencies": { | ||
"definitelytyped-header-parser": "^1.0.1", | ||
"dtslint": "0.4.2" | ||
} | ||
} |
@@ -27,3 +27,2 @@ # web3-core-method | ||
## Usage | ||
@@ -46,6 +45,7 @@ | ||
## Types | ||
All the typescript typings are placed in the types folder. | ||
[docs]: http://web3js.readthedocs.io/en/1.0/ | ||
[repo]: https://github.com/ethereum/web3.js | ||
391
src/index.js
@@ -24,3 +24,3 @@ /* | ||
"use strict"; | ||
'use strict'; | ||
@@ -34,9 +34,5 @@ var _ = require('underscore'); | ||
var TIMEOUTBLOCK = 50; | ||
var POLLINGTIMEOUT = 15 * TIMEOUTBLOCK; // ~average block time (seconds) * TIMEOUTBLOCK | ||
var CONFIRMATIONBLOCKS = 24; | ||
var Method = function Method(options) { | ||
if(!options.call || !options.name) { | ||
if (!options.call || !options.name) { | ||
throw new Error('When creating a method you need to provide at least the "name" and "call" property.'); | ||
@@ -60,5 +56,11 @@ } | ||
this.defaultAccount = options.defaultAccount || null; | ||
this.transactionBlockTimeout = options.transactionBlockTimeout || 50; | ||
this.transactionConfirmationBlocks = options.transactionConfirmationBlocks || 24; | ||
this.transactionPollingTimeout = options.transactionPollingTimeout || 750; | ||
this.defaultCommon = options.defaultCommon; | ||
this.defaultChain = options.defaultChain; | ||
this.defaultHardfork = options.defaultHardfork; | ||
}; | ||
Method.prototype.setRequestManager = function (requestManager, accounts) { | ||
Method.prototype.setRequestManager = function(requestManager, accounts) { | ||
this.requestManager = requestManager; | ||
@@ -73,3 +75,3 @@ | ||
Method.prototype.createFunction = function (requestManager, accounts) { | ||
Method.prototype.createFunction = function(requestManager, accounts) { | ||
var func = this.buildCall(); | ||
@@ -83,3 +85,3 @@ func.call = this.call; | ||
Method.prototype.attachToObject = function (obj) { | ||
Method.prototype.attachToObject = function(obj) { | ||
var func = this.buildCall(); | ||
@@ -103,3 +105,3 @@ func.call = this.call; | ||
*/ | ||
Method.prototype.getCall = function (args) { | ||
Method.prototype.getCall = function(args) { | ||
return _.isFunction(this.call) ? this.call(args) : this.call; | ||
@@ -115,3 +117,3 @@ }; | ||
*/ | ||
Method.prototype.extractCallback = function (args) { | ||
Method.prototype.extractCallback = function(args) { | ||
if (_.isFunction(args[args.length - 1])) { | ||
@@ -129,3 +131,3 @@ return args.pop(); // modify the args array! | ||
*/ | ||
Method.prototype.validateArgs = function (args) { | ||
Method.prototype.validateArgs = function(args) { | ||
if (args.length !== this.params) { | ||
@@ -143,3 +145,3 @@ throw errors.InvalidNumberOfParams(args.length, this.params, this.name); | ||
*/ | ||
Method.prototype.formatInput = function (args) { | ||
Method.prototype.formatInput = function(args) { | ||
var _this = this; | ||
@@ -151,3 +153,3 @@ | ||
return this.inputFormatter.map(function (formatter, index) { | ||
return this.inputFormatter.map(function(formatter, index) { | ||
// bind this for defaultBlock, and defaultAccount | ||
@@ -165,7 +167,7 @@ return formatter ? formatter.call(_this, args[index]) : args[index]; | ||
*/ | ||
Method.prototype.formatOutput = function (result) { | ||
Method.prototype.formatOutput = function(result) { | ||
var _this = this; | ||
if(_.isArray(result)) { | ||
return result.map(function(res){ | ||
if (_.isArray(result)) { | ||
return result.map(function(res) { | ||
return _this.outputFormatter && res ? _this.outputFormatter(res) : res; | ||
@@ -185,3 +187,3 @@ }); | ||
*/ | ||
Method.prototype.toPayload = function (args) { | ||
Method.prototype.toPayload = function(args) { | ||
var call = this.getCall(args); | ||
@@ -206,3 +208,3 @@ var callback = this.extractCallback(args); | ||
Method.prototype._confirmTransaction = function (defer, result, payload) { | ||
Method.prototype._confirmTransaction = function(defer, result, payload) { | ||
var method = this, | ||
@@ -214,2 +216,3 @@ promiseResolved = false, | ||
intervalId = null, | ||
lastBlock = null, | ||
receiptJSON = '', | ||
@@ -225,2 +228,11 @@ gasProvided = (_.isObject(payload.params[0]) && payload.params[0].gas) ? payload.params[0].gas : null, | ||
new Method({ | ||
name: 'getBlockByNumber', | ||
call: 'eth_getBlockByNumber', | ||
params: 2, | ||
inputFormatter: [formatters.inputBlockNumberFormatter, function(val) { | ||
return !!val; | ||
}], | ||
outputFormatter: formatters.outputBlockFormatter | ||
}), | ||
new Method({ | ||
name: 'getTransactionReceipt', | ||
@@ -252,3 +264,3 @@ call: 'eth_getTransactionReceipt', | ||
var _ethereumCall = {}; | ||
_.each(_ethereumCalls, function (mthd) { | ||
_.each(_ethereumCalls, function(mthd) { | ||
mthd.attachToObject(_ethereumCall); | ||
@@ -260,3 +272,3 @@ mthd.requestManager = method.requestManager; // assign rather than call setRequestManager() | ||
// fire "receipt" and confirmation events and resolve after | ||
var checkConfirmation = function (existingReceipt, isPolling, err, blockHeader, sub) { | ||
var checkConfirmation = function(existingReceipt, isPolling, err, blockHeader, sub) { | ||
if (!err) { | ||
@@ -266,3 +278,3 @@ // create fake unsubscribe | ||
sub = { | ||
unsubscribe: function () { | ||
unsubscribe: function() { | ||
clearInterval(intervalId); | ||
@@ -275,72 +287,135 @@ } | ||
// catch error from requesting receipt | ||
.catch(function (err) { | ||
sub.unsubscribe(); | ||
promiseResolved = true; | ||
utils._fireError({message: 'Failed to check for transaction receipt:', data: err}, defer.eventEmitter, defer.reject); | ||
}) | ||
// if CONFIRMATION listener exists check for confirmations, by setting canUnsubscribe = false | ||
.then(function(receipt) { | ||
if (!receipt || !receipt.blockHash) { | ||
throw new Error('Receipt missing or blockHash null'); | ||
} | ||
// apply extra formatters | ||
if (method.extraFormatters && method.extraFormatters.receiptFormatter) { | ||
receipt = method.extraFormatters.receiptFormatter(receipt); | ||
} | ||
// check if confirmation listener exists | ||
if (defer.eventEmitter.listeners('confirmation').length > 0) { | ||
// If there was an immediately retrieved receipt, it's already | ||
// been confirmed by the direct call to checkConfirmation needed | ||
// for parity instant-seal | ||
if (existingReceipt === undefined || confirmationCount !== 0){ | ||
defer.eventEmitter.emit('confirmation', confirmationCount, receipt); | ||
.catch(function(err) { | ||
sub.unsubscribe(); | ||
promiseResolved = true; | ||
utils._fireError( | ||
{ | ||
message: 'Failed to check for transaction receipt:', | ||
data: err | ||
}, | ||
defer.eventEmitter, | ||
defer.reject | ||
); | ||
}) | ||
// if CONFIRMATION listener exists check for confirmations, by setting canUnsubscribe = false | ||
.then(async function(receipt) { | ||
if (!receipt || !receipt.blockHash) { | ||
throw new Error('Receipt missing or blockHash null'); | ||
} | ||
canUnsubscribe = false; | ||
confirmationCount++; | ||
if (confirmationCount === CONFIRMATIONBLOCKS + 1) { // add 1 so we account for conf 0 | ||
sub.unsubscribe(); | ||
defer.eventEmitter.removeAllListeners(); | ||
// apply extra formatters | ||
if (method.extraFormatters && method.extraFormatters.receiptFormatter) { | ||
receipt = method.extraFormatters.receiptFormatter(receipt); | ||
} | ||
} | ||
return receipt; | ||
}) | ||
// CHECK for CONTRACT DEPLOYMENT | ||
.then(function(receipt) { | ||
// check if confirmation listener exists | ||
if (defer.eventEmitter.listeners('confirmation').length > 0) { | ||
var block; | ||
if (isContractDeployment && !promiseResolved) { | ||
// If there was an immediately retrieved receipt, it's already | ||
// been confirmed by the direct call to checkConfirmation needed | ||
// for parity instant-seal | ||
if (existingReceipt === undefined || confirmationCount !== 0) { | ||
if (isPolling) { // Check if actually a new block is existing on polling | ||
if (lastBlock) { | ||
block = await _ethereumCall.getBlockByNumber(lastBlock.number + 1); | ||
if (block) { | ||
lastBlock = block; | ||
defer.eventEmitter.emit('confirmation', confirmationCount, receipt); | ||
} | ||
} else { | ||
block = await _ethereumCall.getBlockByNumber(receipt.blockNumber); | ||
lastBlock = block; | ||
defer.eventEmitter.emit('confirmation', confirmationCount, receipt); | ||
} | ||
} else { | ||
defer.eventEmitter.emit('confirmation', confirmationCount, receipt); | ||
} | ||
} | ||
if (!receipt.contractAddress) { | ||
if ((isPolling && block) || !isPolling) { | ||
confirmationCount++; | ||
} | ||
canUnsubscribe = false; | ||
if (canUnsubscribe) { | ||
if (confirmationCount === method.transactionConfirmationBlocks + 1) { // add 1 so we account for conf 0 | ||
sub.unsubscribe(); | ||
promiseResolved = true; | ||
defer.eventEmitter.removeAllListeners(); | ||
} | ||
utils._fireError(new Error('The transaction receipt didn\'t contain a contract address.'), defer.eventEmitter, defer.reject); | ||
return; | ||
} | ||
_ethereumCall.getCode(receipt.contractAddress, function (e, code) { | ||
return receipt; | ||
}) | ||
// CHECK for CONTRACT DEPLOYMENT | ||
.then(function(receipt) { | ||
if (!code) { | ||
if (isContractDeployment && !promiseResolved) { | ||
if (!receipt.contractAddress) { | ||
if (canUnsubscribe) { | ||
sub.unsubscribe(); | ||
promiseResolved = true; | ||
} | ||
utils._fireError( | ||
new Error('The transaction receipt didn\'t contain a contract address.'), | ||
defer.eventEmitter, | ||
defer.reject, | ||
null, | ||
receipt | ||
); | ||
return; | ||
} | ||
_ethereumCall.getCode(receipt.contractAddress, function(e, code) { | ||
if (code.length > 2) { | ||
defer.eventEmitter.emit('receipt', receipt); | ||
if (!code) { | ||
return; | ||
} | ||
// if contract, return instance instead of receipt | ||
if (method.extraFormatters && method.extraFormatters.contractDeployFormatter) { | ||
defer.resolve(method.extraFormatters.contractDeployFormatter(receipt)); | ||
if (code.length > 2) { | ||
defer.eventEmitter.emit('receipt', receipt); | ||
// if contract, return instance instead of receipt | ||
if (method.extraFormatters && method.extraFormatters.contractDeployFormatter) { | ||
defer.resolve(method.extraFormatters.contractDeployFormatter(receipt)); | ||
} else { | ||
defer.resolve(receipt); | ||
} | ||
// need to remove listeners, as they aren't removed automatically when succesfull | ||
if (canUnsubscribe) { | ||
defer.eventEmitter.removeAllListeners(); | ||
} | ||
} else { | ||
defer.resolve(receipt); | ||
utils._fireError( | ||
new Error('The contract code couldn\'t be stored, please check your gas limit.'), | ||
defer.eventEmitter, | ||
defer.reject, | ||
null, | ||
receipt | ||
); | ||
} | ||
if (canUnsubscribe) { | ||
sub.unsubscribe(); | ||
} | ||
promiseResolved = true; | ||
}); | ||
} | ||
return receipt; | ||
}) | ||
// CHECK for normal tx check for receipt only | ||
.then(function(receipt) { | ||
if (!isContractDeployment && !promiseResolved) { | ||
if (!receipt.outOfGas && | ||
(!gasProvided || gasProvided !== utils.numberToHex(receipt.gasUsed)) && | ||
(receipt.status === true || receipt.status === '0x1' || typeof receipt.status === 'undefined')) { | ||
defer.eventEmitter.emit('receipt', receipt); | ||
defer.resolve(receipt); | ||
// need to remove listeners, as they aren't removed automatically when succesfull | ||
@@ -352,3 +427,21 @@ if (canUnsubscribe) { | ||
} else { | ||
utils._fireError(new Error('The contract code couldn\'t be stored, please check your gas limit.'), defer.eventEmitter, defer.reject); | ||
receiptJSON = JSON.stringify(receipt, null, 2); | ||
if (receipt.status === false || receipt.status === '0x0') { | ||
utils._fireError( | ||
new Error('Transaction has been reverted by the EVM:\n' + receiptJSON), | ||
defer.eventEmitter, | ||
defer.reject, | ||
null, | ||
receipt | ||
); | ||
} else { | ||
utils._fireError( | ||
new Error('Transaction ran out of gas. Please provide more gas:\n' + receiptJSON), | ||
defer.eventEmitter, | ||
defer.reject, | ||
null, | ||
receipt | ||
); | ||
} | ||
} | ||
@@ -360,68 +453,42 @@ | ||
promiseResolved = true; | ||
}); | ||
} | ||
} | ||
return receipt; | ||
}) | ||
// CHECK for normal tx check for receipt only | ||
.then(function(receipt) { | ||
}) | ||
// time out the transaction if not mined after 50 blocks | ||
.catch(function() { | ||
timeoutCount++; | ||
if (!isContractDeployment && !promiseResolved) { | ||
if(!receipt.outOfGas && | ||
(!gasProvided || gasProvided !== receipt.gasUsed) && | ||
(receipt.status === true || receipt.status === '0x1' || typeof receipt.status === 'undefined')) { | ||
defer.eventEmitter.emit('receipt', receipt); | ||
defer.resolve(receipt); | ||
// need to remove listeners, as they aren't removed automatically when succesfull | ||
if (canUnsubscribe) { | ||
defer.eventEmitter.removeAllListeners(); | ||
// check to see if we are http polling | ||
if (!!isPolling) { | ||
// polling timeout is different than transactionBlockTimeout blocks since we are triggering every second | ||
if (timeoutCount - 1 >= method.transactionPollingTimeout) { | ||
sub.unsubscribe(); | ||
promiseResolved = true; | ||
utils._fireError( | ||
new Error('Transaction was not mined within ' + method.transactionPollingTimeout + ' seconds, please make sure your transaction was properly sent. Be aware that it might still be mined!'), | ||
defer.eventEmitter, | ||
defer.reject | ||
); | ||
} | ||
} else { | ||
receiptJSON = JSON.stringify(receipt, null, 2); | ||
if (receipt.status === false || receipt.status === '0x0') { | ||
utils._fireError(new Error("Transaction has been reverted by the EVM:\n" + receiptJSON), | ||
defer.eventEmitter, defer.reject); | ||
} else { | ||
if (timeoutCount - 1 >= method.transactionBlockTimeout) { | ||
sub.unsubscribe(); | ||
promiseResolved = true; | ||
utils._fireError( | ||
new Error("Transaction ran out of gas. Please provide more gas:\n" + receiptJSON), | ||
defer.eventEmitter, defer.reject); | ||
new Error('Transaction was not mined within ' + method.transactionBlockTimeout + ' blocks, please make sure your transaction was properly sent. Be aware that it might still be mined!'), | ||
defer.eventEmitter, | ||
defer.reject | ||
); | ||
} | ||
} | ||
}); | ||
if (canUnsubscribe) { | ||
sub.unsubscribe(); | ||
} | ||
promiseResolved = true; | ||
} | ||
}) | ||
// time out the transaction if not mined after 50 blocks | ||
.catch(function () { | ||
timeoutCount++; | ||
// check to see if we are http polling | ||
if(!!isPolling) { | ||
// polling timeout is different than TIMEOUTBLOCK blocks since we are triggering every second | ||
if (timeoutCount - 1 >= POLLINGTIMEOUT) { | ||
sub.unsubscribe(); | ||
promiseResolved = true; | ||
utils._fireError(new Error('Transaction was not mined within' + POLLINGTIMEOUT + ' seconds, please make sure your transaction was properly sent. Be aware that it might still be mined!'), defer.eventEmitter, defer.reject); | ||
} | ||
} else { | ||
if (timeoutCount - 1 >= TIMEOUTBLOCK) { | ||
sub.unsubscribe(); | ||
promiseResolved = true; | ||
utils._fireError(new Error('Transaction was not mined within 50 blocks, please make sure your transaction was properly sent. Be aware that it might still be mined!'), defer.eventEmitter, defer.reject); | ||
} | ||
} | ||
}); | ||
} else { | ||
sub.unsubscribe(); | ||
promiseResolved = true; | ||
utils._fireError({message: 'Failed to subscribe to new newBlockHeaders to confirm the transaction receipts.', data: err}, defer.eventEmitter, defer.reject); | ||
utils._fireError({ | ||
message: 'Failed to subscribe to new newBlockHeaders to confirm the transaction receipts.', | ||
data: err | ||
}, defer.eventEmitter, defer.reject); | ||
} | ||
@@ -443,18 +510,18 @@ }; | ||
_ethereumCall.getTransactionReceipt(result) | ||
.then(function(receipt) { | ||
if (receipt && receipt.blockHash) { | ||
if (defer.eventEmitter.listeners('confirmation').length > 0) { | ||
// We must keep on watching for new Blocks, if a confirmation listener is present | ||
startWatching(receipt); | ||
.then(function(receipt) { | ||
if (receipt && receipt.blockHash) { | ||
if (defer.eventEmitter.listeners('confirmation').length > 0) { | ||
// We must keep on watching for new Blocks, if a confirmation listener is present | ||
startWatching(receipt); | ||
} | ||
checkConfirmation(receipt, false); | ||
} else if (!promiseResolved) { | ||
startWatching(); | ||
} | ||
checkConfirmation(receipt, false); | ||
}) | ||
.catch(function() { | ||
if (!promiseResolved) startWatching(); | ||
}); | ||
} else if (!promiseResolved) { | ||
startWatching(); | ||
} | ||
}) | ||
.catch(function(){ | ||
if (!promiseResolved) startWatching(); | ||
}); | ||
}; | ||
@@ -487,3 +554,3 @@ | ||
// actual send function | ||
var send = function () { | ||
var send = function() { | ||
var defer = promiEvent(!isSendTx), | ||
@@ -494,6 +561,6 @@ payload = method.toPayload(Array.prototype.slice.call(arguments)); | ||
// CALLBACK function | ||
var sendTxCallback = function (err, result) { | ||
var sendTxCallback = function(err, result) { | ||
try { | ||
result = method.formatOutput(result); | ||
} catch(e) { | ||
} catch (e) { | ||
err = e; | ||
@@ -511,3 +578,3 @@ } | ||
} else { | ||
if(err.error) { | ||
if (err.error) { | ||
err = err.error; | ||
@@ -537,3 +604,3 @@ } | ||
// SENDS the SIGNED SIGNATURE | ||
var sendSignedTx = function(sign){ | ||
var sendSignedTx = function(sign) { | ||
@@ -562,3 +629,27 @@ var signedPayload = _.extend({}, payload, { | ||
if (wallet && wallet.privateKey) { | ||
return method.accounts.signTransaction(_.omit(tx, 'from'), wallet.privateKey).then(sendSignedTx); | ||
var txOptions = _.omit(tx, 'from'); | ||
if (method.defaultChain && !txOptions.chain) { | ||
txOptions.chain = method.defaultChain; | ||
} | ||
if (method.defaultHardfork && !txOptions.hardfork) { | ||
txOptions.hardfork = method.defaultHardfork; | ||
} | ||
if (method.defaultCommon && !txOptions.common) { | ||
txOptions.common = method.defaultCommon; | ||
} | ||
return method.accounts.signTransaction(txOptions, wallet.privateKey) | ||
.then(sendSignedTx) | ||
.catch(function(err) { | ||
if (_.isFunction(defer.eventEmitter.listeners) && defer.eventEmitter.listeners('error').length) { | ||
defer.eventEmitter.emit('error', err); | ||
defer.eventEmitter.removeAllListeners(); | ||
defer.eventEmitter.catch(function() { | ||
}); | ||
} | ||
defer.reject(err); | ||
}); | ||
} | ||
@@ -591,3 +682,3 @@ | ||
// Send the actual transaction | ||
if(isSendTx && _.isObject(payload.params[0]) && typeof payload.params[0].gasPrice === 'undefined') { | ||
if (isSendTx && _.isObject(payload.params[0]) && typeof payload.params[0].gasPrice === 'undefined') { | ||
@@ -600,3 +691,3 @@ var getGasPrice = (new Method({ | ||
getGasPrice(function (err, gasPrice) { | ||
getGasPrice(function(err, gasPrice) { | ||
@@ -630,3 +721,3 @@ if (gasPrice) { | ||
*/ | ||
Method.prototype.request = function () { | ||
Method.prototype.request = function() { | ||
var payload = this.toPayload(Array.prototype.slice.call(arguments)); | ||
@@ -633,0 +724,0 @@ payload.format = this.formatOutput.bind(this); |
28963
6
639
2
+ Added@noble/hashes@1.4.0(transitive)
+ Addedethereum-bloom-filters@1.1.0(transitive)
+ Addedrandombytes@2.1.0(transitive)
+ Addedsafe-buffer@5.2.1(transitive)
+ Addedweb3-core-helpers@1.2.2(transitive)
+ Addedweb3-core-promievent@1.2.2(transitive)
+ Addedweb3-core-subscriptions@1.2.2(transitive)
+ Addedweb3-eth-iban@1.2.2(transitive)
+ Addedweb3-utils@1.2.2(transitive)
- Removedrandomhex@0.1.5(transitive)
- Removedweb3-core-helpers@1.2.1(transitive)
- Removedweb3-core-promievent@1.2.1(transitive)
- Removedweb3-core-subscriptions@1.2.1(transitive)
- Removedweb3-eth-iban@1.2.1(transitive)
- Removedweb3-utils@1.2.1(transitive)
Updatedweb3-core-helpers@1.2.2
Updatedweb3-core-promievent@1.2.2
Updatedweb3-utils@1.2.2