wowok
Version:
Wowok Blockchain TypeScript API
1 lines • 3.43 kB
JavaScript
import{JsonRpcError}from'./errors.js';function getWebsocketUrl(a){const b=new URL(a);return b['protocol']=b['protocol']['replace']('http','ws'),b['toString']();}export const DEFAULT_CLIENT_OPTIONS={'WebSocketConstructor':typeof WebSocket!=='undefined'?WebSocket:undefined,'callTimeout':0x7530,'reconnectTimeout':0xbb8,'maxReconnects':0x5};export class WebsocketClient{['endpoint'];['options'];#requestId=0x0;#disconnects=0x0;#webSocket=null;#connectionPromise=null;#subscriptions=new Set();#pendingRequests=new Map();constructor(a,b={}){this['endpoint']=a,this['options']={...DEFAULT_CLIENT_OPTIONS,...b};if(!this['options']['WebSocketConstructor'])throw new Error('Missing\x20WebSocket\x20constructor');this['endpoint']['startsWith']('http')&&(this['endpoint']=getWebsocketUrl(this['endpoint']));}async['makeRequest'](a,b,c){const d=await this.#setupWebSocket();return new Promise((e,f)=>{this.#requestId+=0x1,this.#pendingRequests['set'](this.#requestId,{'resolve':e,'reject':f,'timeout':setTimeout(()=>{this.#pendingRequests['delete'](this.#requestId),f(new Error('Request\x20timeout:\x20'+a));},this['options']['callTimeout'])}),c?.['addEventListener']('abort',()=>{this.#pendingRequests['delete'](this.#requestId),f(c['reason']);}),d['send'](JSON['stringify']({'jsonrpc':'2.0','id':this.#requestId,'method':a,'params':b}));})['then'](({error:e,result:f})=>{if(e)throw new JsonRpcError(e['message'],e['code']);return f;});}#setupWebSocket(){if(this.#connectionPromise)return this.#connectionPromise;return this.#connectionPromise=new Promise(a=>{this.#webSocket?.['close'](),this.#webSocket=new this['options']['WebSocketConstructor'](this['endpoint']),this.#webSocket['addEventListener']('open',()=>{this.#disconnects=0x0,a(this.#webSocket);}),this.#webSocket['addEventListener']('close',()=>{this.#disconnects++,this.#disconnects<=this['options']['maxReconnects']&&setTimeout(()=>{this.#reconnect();},this['options']['reconnectTimeout']);}),this.#webSocket['addEventListener']('message',({data:b})=>{let c;try{c=JSON['parse'](b);}catch(d){const e=new Error('Failed\x20to\x20parse\x20RPC\x20message:\x20'+b);e['cause']=d,console['error'](e);return;}if('id'in c&&c['id']!=null&&this.#pendingRequests['has'](c['id'])){const {resolve:f,timeout:g}=this.#pendingRequests['get'](c['id']);clearTimeout(g),f(c);}else{if('params'in c){const {params:h}=c;this.#subscriptions['forEach'](i=>{if(i['subscriptionId']===h['subscription'])h['subscription']===i['subscriptionId']&&i['onMessage'](h['result']);});}}});}),this.#connectionPromise;}async #reconnect(){return this.#webSocket?.['close'](),this.#connectionPromise=null,Promise['allSettled']([...this.#subscriptions]['map'](a=>a['subscribe'](this)));}async['subscribe'](a){const b=new RpcSubscription(a);return this.#subscriptions['add'](b),await b['subscribe'](this),()=>b['unsubscribe'](this);}}class RpcSubscription{['subscriptionId']=null;['input'];['subscribed']=![];constructor(a){this['input']=a;}['onMessage'](a){this['subscribed']&&this['input']['onMessage'](a);}async['unsubscribe'](a){const {subscriptionId:b}=this;this['subscribed']=![];if(b==null)return![];return this['subscriptionId']=null,a['makeRequest'](this['input']['unsubscribe'],[b]);}async['subscribe'](a){this['subscriptionId']=null,this['subscribed']=!![];const b=await a['makeRequest'](this['input']['method'],this['input']['params'],this['input']['signal']);this['subscribed']&&(this['subscriptionId']=b);}}