This repository has been archived by the owner on Apr 22, 2024. It is now read-only.
-
-
Notifications
You must be signed in to change notification settings - Fork 327
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
9b937c0
commit 822db54
Showing
9 changed files
with
9,522 additions
and
7,506 deletions.
There are no files selected for viewing
Large diffs are not rendered by default.
Oops, something went wrong.
Large diffs are not rendered by default.
Oops, something went wrong.
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 |
---|---|---|
@@ -1,13 +1,27 @@ | ||
const ProviderEngine = require('./index.js') | ||
const ZeroClientProvider = require('./zero.js') | ||
const FetchProvider = require('./subproviders/fetch') | ||
|
||
const fetchEngine = ZeroClientProvider({ | ||
getAccounts: function(){}, | ||
dataSubprovider: new FetchProvider({ | ||
rpcUrl: 'https://mainnet.infura.io', | ||
}) | ||
}) | ||
|
||
// create engine | ||
const engine = ZeroClientProvider({ | ||
const websocketEngine = ZeroClientProvider({ | ||
getAccounts: function(){}, | ||
rpcUrl: 'https://mainnet.infura.io/', | ||
rpcUrl: 'wss://mainnet.infura.io/_ws', | ||
//debug: true, | ||
}) | ||
|
||
// log new blocks | ||
engine.on('block', function(block){ | ||
console.log('BLOCK CHANGED:', '#'+block.number.toString('hex'), '0x'+block.hash.toString('hex')) | ||
}) | ||
websocketEngine.on('block', function(block) { | ||
console.log('WS:', '#'+block.number.toString('hex'), '0x'+block.hash.toString('hex')) | ||
}) | ||
|
||
// log new blocks | ||
fetchEngine.on('block', function(block) { | ||
console.log('Fetch:', '#'+block.number.toString('hex'), '0x'+block.hash.toString('hex')) | ||
}) |
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,130 @@ | ||
const Backoff = require('backoff') | ||
const createPayload = require('../util/create-payload') | ||
const inherits = require('util').inherits | ||
const Subprovider = require('./subprovider') | ||
const WebSocket = require('ws') | ||
|
||
class WebsocketProvider extends Subprovider { | ||
constructor({ rpcUrl, debug }) { | ||
super() | ||
|
||
Object.defineProperties(this, { | ||
_backoff: { | ||
value: Backoff.exponential({ | ||
randomisationFactor: 0.2, | ||
maxDelay: 5000 | ||
}) | ||
}, | ||
_connectTime: { | ||
value: null, | ||
writable: true | ||
}, | ||
_log: { | ||
value: debug | ||
? (...args) => console.info.apply(console, ['[WSProvider]', ...args]) | ||
: () => { } | ||
}, | ||
_pendingRequests: { | ||
value: new Map() | ||
}, | ||
_socket: { | ||
value: null, | ||
writable: true | ||
}, | ||
_unhandledRequests: { | ||
value: [] | ||
}, | ||
_url: { | ||
value: rpcUrl | ||
} | ||
}) | ||
|
||
this._handleSocketClose = this._handleSocketClose.bind(this) | ||
this._handleSocketMessage = this._handleSocketMessage.bind(this) | ||
this._handleSocketOpen = this._handleSocketOpen.bind(this) | ||
|
||
// Called when a backoff timeout has finished. Time to try reconnecting. | ||
this._backoff.on('ready', () => { | ||
this._openSocket() | ||
}) | ||
|
||
this._openSocket() | ||
} | ||
|
||
handleRequest(payload, next, end) { | ||
if (!this._socket || this._socket.readyState !== 1) { | ||
this._unhandledRequests.push(Array.from(arguments)) | ||
this._log('Socket not open. Request queued.') | ||
return; | ||
} | ||
|
||
this._pendingRequests.set(payload.id, Array.from(arguments)) | ||
|
||
const newPayload = createPayload(payload) | ||
delete newPayload.origin | ||
|
||
this._socket.send(JSON.stringify(newPayload)) | ||
this._log('Request sent:', newPayload.method) | ||
} | ||
|
||
_handleSocketClose({ reason, code }) { | ||
this._log(`Socket closed, code ${code} (${reason || 'no reason'})`); | ||
// If the socket has been open for longer than 5 seconds, reset the backoff | ||
if (this._connectTime && Date.now() - this._connectTime > 5000) { | ||
this._backoff.reset() | ||
} | ||
|
||
this._socket.removeEventListener('close', this._handleSocketClose) | ||
this._socket.removeEventListener('message', this._handleSocketMessage) | ||
this._socket.removeEventListener('open', this._handleSocketOpen) | ||
|
||
this._socket = null | ||
this._backoff.backoff() | ||
} | ||
|
||
_handleSocketMessage(message) { | ||
let data; | ||
|
||
try { | ||
data = JSON.parse(message.data) | ||
} catch (e) { | ||
this._log('Received a message that is not valid JSON:', message) | ||
return; | ||
} | ||
|
||
this._log('Received message ID:', data.id) | ||
|
||
if (!this._pendingRequests.has(data.id)) { | ||
return | ||
} | ||
|
||
const [payload, next, end] = this._pendingRequests.get(data.id) | ||
this._pendingRequests.delete(data.id) | ||
end(data.error && data.error.message, data.result) | ||
} | ||
|
||
_handleSocketOpen() { | ||
this._log('Socket open.') | ||
this._connectTime = Date.now(); | ||
|
||
// Any pending requests need to be resent because our session was lost | ||
// and will not get responses for them in our new session. | ||
this._pendingRequests.forEach(value => this._unhandledRequests.push(value)) | ||
this._pendingRequests.clear() | ||
|
||
const unhandledRequests = this._unhandledRequests.splice(0, this._unhandledRequests.length) | ||
unhandledRequests.forEach(request => { | ||
this.handleRequest.apply(this, request) | ||
}) | ||
} | ||
|
||
_openSocket() { | ||
this._log('Opening socket...') | ||
this._socket = new WebSocket(this._url) | ||
this._socket.addEventListener('close', this._handleSocketClose) | ||
this._socket.addEventListener('message', this._handleSocketMessage) | ||
this._socket.addEventListener('open', this._handleSocketOpen) | ||
} | ||
} | ||
|
||
module.exports = WebsocketProvider |
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 @@ | ||
module.exports = WebSocket; |
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