0xweb
Version:
Contract package manager and other web3 tools
89 lines (71 loc) • 2.66 kB
text/typescript
import memd from 'memd';
import { WebSocketProvider } from './WsTransportIsomorphic'
import { TTransport } from './ITransport';
import { MessageBasedTransport } from './MessageBasedTransport';
import { RpcSubscription } from '../RpcSubscription';
export class WsTransport implements TTransport.Transport {
private ws: WsTransportSingleton;
public id: string
constructor(private options: TTransport.Options.Ws) {
this.id = this.options.url;
this.ws = WsTransportSingleton.create(this.options.url, {});
}
async request (req: TTransport.Request)
async request (req: TTransport.Request[])
async request (req: TTransport.Request | TTransport.Request[]) {
return this.ws.request(req);
}
async subscribe <TResult = any> (req: TTransport.Request): Promise<RpcSubscription<TResult>> {
return this.ws.subscribe<TResult>(req);
}
async unsubscribe (req: TTransport.Request & { method: 'eth_unsubscribe', params: [number] }) {
return this.ws.unsubscribe(req);
}
}
class WsTransportSingleton extends MessageBasedTransport {
.deco.memoize()
public static create (url: string, options) {
return new WsTransportSingleton({
url,
...options
});
}
constructor(private options: TTransport.Options.Ws) {
super(options);
}
protected async send(message: string) {
let ws = await this.connect();
ws.send(message);
}
.deco.memoize({ perInstance: true })
private async connect() {
const { url, clientConfig } = this.options
const WebSocket = await WebSocketProvider.get();
const ws = new WebSocket(url, clientConfig ?? {});
const onMessage = ({ data }) => {
this.onMessage(data);
this.emit('message', data);
};
const onClose = () => {
//wsCache.delete(url);
memd.fn.clearMemoized(this.connect, this.options.url);
ws.removeEventListener('close', onClose)
ws.removeEventListener('open', onConnect)
ws.removeEventListener('message', onMessage)
this.emit('close');
};
const onConnect = () => {
this.emit('connect');
}
ws.addEventListener('close', onClose);
ws.addEventListener('message', onMessage);
ws.addEventListener('open', onConnect);
if (ws.readyState === WebSocket.CONNECTING) {
await new Promise((resolve, reject) => {
ws.onopen = resolve
ws.onerror = reject
})
}
return ws;
}
}