Skip to content
This repository has been archived by the owner on Apr 23, 2024. It is now read-only.

Commit

Permalink
Merge pull request #59 from libotony/dev
Browse files Browse the repository at this point in the history
use browser's WebSocket when running in the browser
  • Loading branch information
libotony authored Sep 19, 2018
2 parents c28f81c + b6eb82e commit 8094e76
Show file tree
Hide file tree
Showing 12 changed files with 4,527 additions and 1,132 deletions.
5,458 changes: 4,358 additions & 1,100 deletions package-lock.json

Large diffs are not rendered by default.

14 changes: 10 additions & 4 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,16 +1,17 @@
{
"name": "thorify",
"version": "1.0.0",
"version": "1.0.1",
"description": "A web3 adaptor for VeChain Thor RESTful HTTP API.",
"main": "dist/index.js",
"typings": "dist/index.d.ts",
"scripts": {
"build": "tsc -p .",
"lint": "tslint --fix -p .",
"prepare": "rm -rf dist/; npm run build",
"test": "NODE_ENV=test mocha --require ts-node/register --timeout 20000 --recursive './**/*.test.ts'",
"test": "NODE_ENV=test mocha --require ts-node/register --timeout 20000 --recursive --exclude './test/browser/*.ts' './**/*.test.ts'",
"cover": "NODE_ENV=test nyc npm t",
"coverall": "NODE_ENV=test nyc npm t && nyc report --reporter=text-lcov | coveralls"
"coverall": "NODE_ENV=test nyc npm t && nyc report --reporter=text-lcov | coveralls",
"test:browser": "TS_NODE_PROJECT=\"test/browser/tsconfig.webpack.json\" webpack --config test/browser/webpack.test.config.ts && open test/browser/index.html"
},
"nyc": {
"include": [
Expand Down Expand Up @@ -40,23 +41,28 @@
"@types/chai": "^4.1.3",
"@types/mocha": "^5.2.0",
"@types/node": "^10.0.3",
"@types/webpack": "^4.4.11",
"@types/ws": "^6.0.0",
"chai": "^4.1.2",
"coveralls": "^3.0.1",
"mocha": "^5.1.1",
"nyc": "^11.8.0",
"repl-x": "^0.1.4",
"rewiremock": "^3.7.2",
"ts-loader": "^5.1.1",
"ts-node": "^5.0.1",
"tslint": "^5.9.1",
"typescript": "^2.8.1",
"web3": "^1.0.0-beta.36"
"web3": "^1.0.0-beta.36",
"webpack": "^4.19.1",
"webpack-cli": "^3.1.0"
},
"dependencies": {
"debug": "^3.1.0",
"elliptic": "^6.4.0",
"eth-lib": "^0.2.8",
"eventemitter3": "^3.1.0",
"isomorphic-ws": "^4.0.1",
"thor-devkit": "^0.2.3",
"web3-core-subscriptions": "^1.0.0-beta.36",
"web3-utils": "^1.0.0-beta.36",
Expand Down
50 changes: 29 additions & 21 deletions src/provider/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@
import { parse } from 'url'
import { Callback } from '../types'
const debug = require('debug')('thor:http-provider')
import {EventEmitter} from 'eventemitter3'
import { EventEmitter } from 'eventemitter3'
import WebSocket = require('isomorphic-ws')
import * as QS from 'querystring'
import * as WebSocket from 'ws'
import { JSONRPC } from './json-rpc'
import { RPCExecutor, RPCMethodMap } from './rpc-methods'

Expand Down Expand Up @@ -104,32 +104,32 @@ class ThorProvider extends EventEmitter {

const ws = new WebSocket(this.WSHost + URI)

ws.on('error', (error) => {
debug('error from ws: %O', error)
this.emit('data', rpc.makeSubError(error))
})
ws.onerror = (event) => {
debug('error from ws: %O', event)
this.emit('data', rpc.makeSubError(event.error ? event.error : 'Error from upstream'))
}

ws.on('message', (message) => {
debug('[ws]message from ws: %O', message)
ws.onmessage = (event) => {
debug('[ws]message from ws: %O', event.data)
try {
// wrong type define of message, typeof message turns to be string
const obj = JSON.parse(message as string)
const obj = JSON.parse(event.data as string)

obj.removed = obj.obsolete
delete obj.obsolete
this.emit('data', rpc.makeSubResult(obj))
} catch (e) {
debug('Parse message failed %O', e)
}
})
}

ws.on('open', () => {
ws.onopen = () => {
debug('[ws]opened')
ws.on('close', (code, reason) => {
debug('[ws]close', code, reason)
this.emit('data', rpc.makeSubError(new Error(`Connection closed${reason ? (':' + reason) : ''}`)))
})
})
ws.onclose = (event) => {
debug('[ws]close', event.code, event.reason)
this.emit('data', rpc.makeSubError(new Error(`Connection closed${event.reason ? (':' + event.reason) : ''}`)))
}
}

this.sockets[rpc.id] = {rpc, ws}

Expand All @@ -140,11 +140,19 @@ class ThorProvider extends EventEmitter {
const ws = this.sockets[rpc.params[0]].ws
if (ws && ws.readyState === ws.OPEN) {
ws.close()
ws.removeAllListeners()
ws.on('close', () => {
delete this.sockets[rpc.params[0]]
callback(null, rpc.makeResult(true))
})

// clean up
if (ws.removeAllListeners) {
ws.removeAllListeners()
} else {
ws.onopen = null!
ws.onerror = null!
ws.onmessage = null!
ws.onclose = null!
}

delete this.sockets[rpc.params[0]]
callback(null, rpc.makeResult(true))
} else {
delete this.sockets[rpc.params[0]]
callback(null, rpc.makeResult(true))
Expand Down
15 changes: 15 additions & 0 deletions test/browser/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
<html>

<head>
<meta charset="utf-8">
<title>Mocha Tests</title>
<link href="https://unpkg.com/[email protected]/mocha.css" rel="stylesheet" />
<script src="https://unpkg.com/[email protected]/mocha.js"></script>
</head>

<body>
<div id="mocha"></div>
<script src="./dist/mocha.test.bundle.js"></script>
</body>

</html>
9 changes: 9 additions & 0 deletions test/browser/mocha.runner.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
'use strict'

mocha.setup('bdd')

import '../web3/initialization.test'
import './required-module.test'

mocha.checkLeaks()
mocha.run()
40 changes: 40 additions & 0 deletions test/browser/required-module.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
'use strict'

import { expect } from 'chai'
import { thorify } from '../../src'
const Web3 = require('web3')
const web3 = thorify(new Web3(), 'http://localhost:8669', 0)

describe('XHR2: localhost:8669 should not be listened', () => {
it('call eth methods should throw error', (done) => {
web3.eth.getChainTag().then(() => {
done(new Error('no error thrown'))
}).catch((e: Error) => {
try {
expect(() => { throw e || 'no error' }).to.throw('[thor-provider] Invalid response, check the host')
done()
} catch (err) {
done(err)
}
})
})
})

describe('WebSocket: localhost:8669 should not be listened', () => {

it('call subscribe throw error', (done) => {
web3.eth.subscribe('newBlockHeaders', function(error: Error, result: any) {
if (!error) {
done(new Error('no error thrown'))
}
try {
expect(() => { throw error || 'no error' }).to.throw('Error from upstream')
done()
} catch (err) {
done(err)
}

})
})

})
8 changes: 8 additions & 0 deletions test/browser/tsconfig.webpack.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"compilerOptions": {
"module": "commonjs",
"target": "es5",
"noImplicitAny": false,
"esModuleInterop": true,
},
}
32 changes: 32 additions & 0 deletions test/browser/webpack.test.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@

'use strict'
import path from 'path'
import webpack from 'webpack'

const config: webpack.Configuration = {
mode: 'none',
devtool: 'inline-source-map',
entry: path.resolve(__dirname, './mocha.runner.ts'),
module: {
rules: [
{
test: /\.ts?$/,
loader: 'ts-loader',
exclude: /node_modules/,
},
],
},
resolve: {
extensions: ['.ts', '.js'],
},
output: {
path: path.resolve(__dirname, 'dist'),
filename: 'mocha.test.bundle.js',
},
node: {
fs: 'empty',
},
target: 'web',
}

export default config
1 change: 0 additions & 1 deletion test/provider/index.test.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
'use strict'
import { expect } from 'chai'
import { ThorProvider } from '../../src/provider'
import { JSONRPC } from '../../src/provider/json-rpc'

describe('thor-provider initialization', () => {

Expand Down
28 changes: 24 additions & 4 deletions test/test-utils/fake-ws.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,26 @@ class FakeWebSocket extends EventEmitter {
}, 10)
}

set onopen(value) {
this.removeListener('open')
this.addListener('open', value)
}

set onclose(value) {
this.removeListener('close')
this.addListener('close', value)
}

set onmessage(value) {
this.removeListener('')
this.addListener('message', value)
}

set onerror(value) {
this.removeListener('error')
this.addListener('error', value)
}

public resetMockData() {
data = null
error = null
Expand Down Expand Up @@ -47,21 +67,21 @@ class FakeWebSocket extends EventEmitter {
isClose = true
}

public close() {
public close() {
this.stopMockLoop()
setTimeout(() => {
this.emit('close', 1001, 'closed')
this.emit('close', { code: 1001, reaseon: 'closed' })
}, 100)
}

private startMockLoop() {
this.interval = setInterval(() => {
if (data) {
this.emit('message', JSON.stringify(data))
this.emit('message', { data: JSON.stringify(data) })
data = null
}
if (error) {
this.emit('error', error)
this.emit('error', {error})
error = null
}
if (isClose) {
Expand Down
2 changes: 1 addition & 1 deletion test/test-utils/init.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ const wsUtility = new FakeWebSocket(null)
wsUtility.close()

rewiremock('xhr2').with(require('./fake-xhr2'))
rewiremock('ws').with(require('./fake-ws'))
rewiremock('isomorphic-ws').with(require('./fake-ws'))

rewiremock.enable()

Expand Down
2 changes: 1 addition & 1 deletion test/utils/utils.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ describe('utils:validNumberOrDefault', () => {

})

describe('utils:valid*OrError', () => {
describe('utils:validOrError', () => {
it('validAddressOrError with valid input', () => {
expect(utils.validAddressOrError('7567d83b7b8d80addcb281a71d54fc7b3364ffed')).to.be.equal('0x7567d83b7b8d80addcb281a71d54fc7b3364ffed')
})
Expand Down

0 comments on commit 8094e76

Please sign in to comment.