This repository has been archived by the owner on Jun 14, 2018. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 8
Expand web3.js transport method wrapping to improve error reporting #6
Merged
Merged
Changes from all commits
Commits
Show all changes
3 commits
Select commit
Hold shift + click to select a range
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
var inherits = require("util").inherits; | ||
var TruffleError = require("truffle-error"); | ||
|
||
// HACK: string comparison seems to be only way to identify being unable to | ||
// connect to RPC node. | ||
var NOT_CONNECTED_MESSAGE = 'Invalid JSON RPC response: ""'; | ||
|
||
function ProviderError(message, error) { | ||
if (message == NOT_CONNECTED_MESSAGE) { | ||
message = "Could not connect to your Ethereum client. " + | ||
"Please check that your Ethereum client:\n" + | ||
" - is running\n" + | ||
" - is accepting RPC connections (i.e., \"--rpc\" option is used in geth)\n" + | ||
" - is accessible over the network\n" + | ||
" - is properly configured in your Truffle configuration file (truffle.js)\n"; | ||
} | ||
ProviderError.super_.call(this, message); | ||
this.message = message; | ||
} | ||
|
||
inherits(ProviderError, TruffleError); | ||
|
||
module.exports = ProviderError; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,138 @@ | ||
var ProviderError = require('./error'); | ||
|
||
module.exports = { | ||
/* | ||
* Web3.js Transport Wrapper | ||
* | ||
* Wraps an underlying web3 provider's RPC transport methods (send/sendAsync) | ||
* for Truffle-specific purposes, mainly for logging / request verbosity. | ||
*/ | ||
wrap: function(provider, options) { | ||
/* wrapping should be idempotent */ | ||
if (provider._alreadyWrapped) return provider; | ||
|
||
/* setup options defaults */ | ||
options = options || {}; | ||
// custom logger | ||
options.logger = options.logger || console; | ||
// to see what web3 is sending and receiving. | ||
options.verbose = options.verbose || options.verboseRpc || false; | ||
|
||
/* create wrapper functions for before/after send */ | ||
var preHook = this.preHook(options); | ||
var postHook = this.postHook(options); | ||
|
||
var originalSend = provider.send.bind(provider); | ||
var originalSendAsync = provider.sendAsync.bind(provider); | ||
|
||
/* overwrite methods */ | ||
provider.send = this.send(originalSend, preHook, postHook); | ||
provider.sendAsync = this.sendAsync(originalSendAsync, preHook, postHook); | ||
|
||
/* mark as wrapped */ | ||
provider._alreadyWrapped = true; | ||
|
||
return provider; | ||
}, | ||
|
||
/* | ||
* Transport Hook Generators | ||
* | ||
* Used to wrap underlying web3.js behavior before/after sending request | ||
* payloads to the RPC. | ||
* | ||
* Transport hooks may be used to perform additional operations before/after | ||
* sending, and/or to modify request/response data. | ||
* | ||
* Each generator accepts an `options` argument and uses it to construct | ||
* and return a function. | ||
* | ||
* Returned functions accept relevant arguments and return potentially new | ||
* versions of those arguments (for payload/result/error overrides) | ||
*/ | ||
|
||
// before send/sendAsync | ||
preHook: function(options) { | ||
return function(payload) { | ||
if (options.verbose) { | ||
// for request payload debugging | ||
options.logger.log(" > " + JSON.stringify(payload, null, 2).split("\n").join("\n > ")); | ||
} | ||
|
||
return payload; | ||
}; | ||
}, | ||
|
||
// after send/sendAsync | ||
postHook: function(options) { | ||
return function(payload, error, result) { | ||
if (error != null) { | ||
// wrap errors in internal error class | ||
error = new ProviderError(error.message, error); | ||
return [payload, error, result]; | ||
} | ||
|
||
if (options.verbose) { | ||
options.logger.log(" < " + JSON.stringify(result, null, 2).split("\n").join("\n < ")); | ||
} | ||
|
||
return [payload, error, result]; | ||
}; | ||
}, | ||
|
||
/* | ||
* Transport Method Generators | ||
* | ||
* Generate wrapped versions of `send`/`sendAsync`, given original method and | ||
* transport hooks. | ||
* | ||
* Pre-condition: originals are bound correctly (`send.bind(provider)`) | ||
* | ||
* Return the wrapped function matching the original function's signature. | ||
*/ | ||
|
||
// wrap a `provider.send` function with behavior hooks | ||
// returns a function(payload) to replace `provider.send` | ||
send: function(originalSend, preHook, postHook) { | ||
return function(payload) { | ||
var result = null; | ||
var error = null; | ||
|
||
payload = preHook(payload); | ||
|
||
try { | ||
result = originalSend(payload); | ||
} catch (e) { | ||
error = e; | ||
} | ||
|
||
var modified = postHook(payload, error, result); | ||
payload = modified[0]; | ||
error = modified[1]; | ||
result = modified[2]; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm taking this approach specifically to modify the error that gets thrown, but it doesn't work as nicely without being able to return multiple values. Wondering if there's a less awkward way to do this same thing (if only we could use fancy new destructuring :) |
||
|
||
if (error != null) { | ||
throw error; | ||
} | ||
|
||
return result; | ||
} | ||
}, | ||
|
||
// wrap a `provider.sendAsync` function with behavior hooks | ||
// returns a function(payload, callback) to replace `provider.sendAsync` | ||
sendAsync: function(originalSendAsync, preHook, postHook) { | ||
return function(payload, callback) { | ||
payload = preHook(payload); | ||
|
||
originalSendAsync(payload, function(error, result) { | ||
var modified = postHook(payload, error, result); | ||
payload = modified[0]; | ||
error = modified[1]; | ||
result = modified[2]; | ||
|
||
callback(error, result); | ||
}); | ||
}; | ||
} | ||
} |
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I found this pattern in
truffle-compile
but I don't know if any of that is extraneous here.