parent
8dac30d2a1
commit
88d004d3cb
@ -0,0 +1,88 @@ |
|||||||
|
import { isWs } from '@harmony/utils'; |
||||||
|
import mitt from 'mitt'; |
||||||
|
import { BaseProvider } from './baseProvider'; |
||||||
|
|
||||||
|
export const enum SocketConnection { |
||||||
|
READY = 'ready', |
||||||
|
CONNECT = 'connect', |
||||||
|
ERROR = 'error', |
||||||
|
CLOSE = 'close', |
||||||
|
} |
||||||
|
|
||||||
|
export const enum SocketState { |
||||||
|
SOCKET_MESSAGE = 'socket_message', |
||||||
|
SOCKET_READY = 'socket_ready', |
||||||
|
SOCKET_CLOSE = 'socket_close', |
||||||
|
SOCKET_ERROR = 'socket_error', |
||||||
|
SOCKET_CONNECT = 'socket_connect', |
||||||
|
SOCKET_NETWORK_CHANGED = 'socket_networkChanged', |
||||||
|
SOCKET_ACCOUNTS_CHANGED = 'socket_accountsChanged', |
||||||
|
} |
||||||
|
|
||||||
|
class BaseSocket extends BaseProvider { |
||||||
|
url: string; |
||||||
|
emitter: mitt.Emitter; |
||||||
|
subscriptions: any = {}; |
||||||
|
handlers: any = {}; |
||||||
|
constructor(url: string) { |
||||||
|
super(url); |
||||||
|
if (!isWs(url)) { |
||||||
|
throw new Error(`${url} is not websocket`); |
||||||
|
} |
||||||
|
this.url = url; |
||||||
|
this.emitter = new mitt(this.handlers); |
||||||
|
} |
||||||
|
resetHandlers() { |
||||||
|
// tslint:disable-next-line: forin
|
||||||
|
for (const i in this.handlers) { |
||||||
|
delete this.handlers[i]; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
once(type: string, handler: mitt.Handler) { |
||||||
|
this.emitter.on(type, handler); |
||||||
|
this.removeListener(type); |
||||||
|
} |
||||||
|
|
||||||
|
removeListener(type?: string, handler?: mitt.Handler) { |
||||||
|
if (!type) { |
||||||
|
this.handlers = {}; |
||||||
|
return; |
||||||
|
} |
||||||
|
if (!handler) { |
||||||
|
delete this.handlers[type]; |
||||||
|
} else { |
||||||
|
return this.emitter.off(type, handler); |
||||||
|
} |
||||||
|
} |
||||||
|
reset() { |
||||||
|
this.removeListener('*'); |
||||||
|
// this.registerEventListeners();
|
||||||
|
} |
||||||
|
removeAllSocketListeners() { |
||||||
|
this.removeListener(SocketState.SOCKET_MESSAGE); |
||||||
|
this.removeListener(SocketState.SOCKET_READY); |
||||||
|
this.removeListener(SocketState.SOCKET_CLOSE); |
||||||
|
this.removeListener(SocketState.SOCKET_ERROR); |
||||||
|
this.removeListener(SocketState.SOCKET_CONNECT); |
||||||
|
} |
||||||
|
|
||||||
|
onReady(event: any) { |
||||||
|
this.emitter.on(SocketConnection.READY, () => event); |
||||||
|
this.emitter.on(SocketState.SOCKET_READY, () => event); |
||||||
|
} |
||||||
|
onError(error: any) { |
||||||
|
this.emitter.on(SocketConnection.ERROR, () => error); |
||||||
|
this.emitter.on(SocketState.SOCKET_ERROR, () => error); |
||||||
|
this.removeAllSocketListeners(); |
||||||
|
this.removeListener('*'); |
||||||
|
} |
||||||
|
onClose(error = null) { |
||||||
|
this.emitter.on(SocketConnection.CLOSE, () => error); |
||||||
|
this.emitter.on(SocketState.SOCKET_CLOSE, () => error); |
||||||
|
this.removeAllSocketListeners(); |
||||||
|
this.removeListener('*'); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
export { BaseSocket }; |
@ -0,0 +1,86 @@ |
|||||||
|
// TODO: implement Websocket Provider
|
||||||
|
import { w3cwebsocket as W3CWebsocket } from 'websocket'; |
||||||
|
import { BaseSocket } from './baseSocket'; |
||||||
|
import { isWs } from '@harmony/utils'; |
||||||
|
import { JsonRpc } from '../rpcMethod/rpcbuilder'; |
||||||
|
import { composeMiddleware } from '../rpcMethod/net'; |
||||||
|
import { RPCRequestPayload } from '../types'; |
||||||
|
|
||||||
|
class WSProvider extends BaseSocket { |
||||||
|
url: string; |
||||||
|
subscriptions: any = {}; |
||||||
|
options: any = {}; |
||||||
|
connection: W3CWebsocket | WebSocket; |
||||||
|
jsonRpc: JsonRpc; |
||||||
|
// ws: w3cwebsocket;
|
||||||
|
constructor(url: string, options: any = {}) { |
||||||
|
super(url); |
||||||
|
if (!isWs(url)) { |
||||||
|
throw new Error(`${url} is not websocket`); |
||||||
|
} |
||||||
|
this.url = url; |
||||||
|
this.options = options; |
||||||
|
this.connection = this.createWebsocketProvider(this.url, this.options); |
||||||
|
this.jsonRpc = new JsonRpc(); |
||||||
|
} |
||||||
|
|
||||||
|
createWebsocketProvider(url: string, options: any = {}) { |
||||||
|
// tslint:disable-next-line: no-string-literal
|
||||||
|
if (typeof window !== 'undefined' && (<any>window).WebSocket) { |
||||||
|
// tslint:disable-next-line: no-string-literal
|
||||||
|
return new WebSocket(url, options.protocol); |
||||||
|
} else { |
||||||
|
const headers = options.headers || {}; |
||||||
|
const urlObject = new URL(url); |
||||||
|
|
||||||
|
if (!headers.authorization && urlObject.username && urlObject.password) { |
||||||
|
const authToken = Buffer.from( |
||||||
|
`${urlObject.username}:${urlObject.password}`, |
||||||
|
).toString('base64'); |
||||||
|
headers.authorization = `Basic ${authToken}`; |
||||||
|
} |
||||||
|
|
||||||
|
return new W3CWebsocket( |
||||||
|
url, |
||||||
|
options.protocol, |
||||||
|
undefined, |
||||||
|
headers, |
||||||
|
undefined, |
||||||
|
options.clientConfig, |
||||||
|
); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
get connected() { |
||||||
|
return this.connection.readyState === this.connection.OPEN; |
||||||
|
} |
||||||
|
|
||||||
|
isConnecting() { |
||||||
|
return this.connection.readyState === this.connection.CONNECTING; |
||||||
|
} |
||||||
|
|
||||||
|
send(payload: RPCRequestPayload<object>): Promise<any> { |
||||||
|
const [tReq, tRes] = this.getMiddleware(payload.method); |
||||||
|
const reqMiddleware = composeMiddleware(...tReq); |
||||||
|
const resMiddleware = composeMiddleware(...tRes); |
||||||
|
|
||||||
|
return new Promise((resolve, reject) => { |
||||||
|
this.connection.send(reqMiddleware(JSON.stringify(payload))); |
||||||
|
this.connection.onmessage = (msg: MessageEvent) => { |
||||||
|
if (msg && msg.data) { |
||||||
|
let result; |
||||||
|
try { |
||||||
|
result = JSON.parse(msg.data); |
||||||
|
resolve(resMiddleware(result)); |
||||||
|
} catch (error) { |
||||||
|
reject(error); |
||||||
|
} |
||||||
|
} else { |
||||||
|
reject('provider error'); |
||||||
|
} |
||||||
|
}; |
||||||
|
}); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
export { WSProvider }; |
@ -0,0 +1,4 @@ |
|||||||
|
export interface Window { |
||||||
|
WebSocket: any; |
||||||
|
MozWebSocket: any; |
||||||
|
} |
Loading…
Reference in new issue