diff --git a/backends/Eclair.ts b/backends/Eclair.ts index 108956de6..b73d1b178 100644 --- a/backends/Eclair.ts +++ b/backends/Eclair.ts @@ -8,16 +8,18 @@ import Base64Utils from './../utils/Base64Utils'; import { Hash as sha256Hash } from 'fast-sha256'; // keep track of all active calls so we can cancel when appropriate -const calls: any = {}; +const calls = new Map>(); export default class Eclair { + clearCachedCalls = () => calls.clear(); + api = (method: string, params: any = {}) => { const { password, certVerification, enableTor } = stores.settingsStore; let { url } = stores.settingsStore; const id: string = method + JSON.stringify(params); - if (calls[id]) { - return calls[id]; + if (calls.has(id)) { + return calls.get(id); } url = url.slice(-1) === '/' ? url : url + '/'; @@ -28,48 +30,49 @@ export default class Eclair { const body = querystring.stringify(params); if (enableTor === true) { - calls[id] = doTorRequest( - url + method, - RequestMethod.POST, - body, - headers + calls.set( + id, + doTorRequest(url + method, RequestMethod.POST, body, headers) ); } else { - calls[id] = ReactNativeBlobUtil.config({ - trusty: !certVerification - }) - .fetch('POST', url + method, headers, body) - .then((response: any) => { - delete calls[id]; + calls.set( + id, + ReactNativeBlobUtil.config({ + trusty: !certVerification + }) + .fetch('POST', url + method, headers, body) + .then((response: any) => { + calls.delete(id); - const status = response.info().status; - if (status < 300) { - return response.json(); - } else { - let errorInfo; - try { - errorInfo = response.json(); - } catch (err) { - throw new Error( - 'response was (' + - status + - ')' + - response.text() - ); + const status = response.info().status; + if (status < 300) { + return response.json(); + } else { + let errorInfo; + try { + errorInfo = response.json(); + } catch (err) { + throw new Error( + 'response was (' + + status + + ')' + + response.text() + ); + } + throw new Error(errorInfo.error); } - throw new Error(errorInfo.error); - } - }); + }) + ); } setTimeout( (id: string) => { - delete calls[id]; + calls.delete(id); }, 9000, id ); - return calls[id]; + return calls.get(id); }; getTransactions = () => diff --git a/backends/LND.ts b/backends/LND.ts index 55cf74b33..851dc1e52 100644 --- a/backends/LND.ts +++ b/backends/LND.ts @@ -15,9 +15,13 @@ interface Headers { } // keep track of all active calls so we can cancel when appropriate -const calls: any = {}; +const calls = new Map>(); + export default class LND { torSocksPort?: number = undefined; + + clearCachedCalls = () => calls.clear(); + restReq = async ( headers: Headers | any, url: string, @@ -29,49 +33,60 @@ export default class LND { // use body data as an identifier too, we don't want to cancel when we // are making multiples calls to get all the node names, for example const id = data ? `${url}${JSON.stringify(data)}` : url; - if (calls[id]) { - return calls[id]; + if (calls.has(id)) { + return calls.get(id); } // API is a bit of a mess but // If tor enabled in setting, start up the daemon here if (useTor === true) { - calls[id] = doTorRequest( - url, - method as RequestMethod, - JSON.stringify(data), - headers - ).then((response: any) => { - delete calls[id]; - return response; - }); + calls.set( + id, + doTorRequest( + url, + method as RequestMethod, + JSON.stringify(data), + headers + ).then((response: any) => { + calls.delete(id); + return response; + }) + ); } else { - calls[id] = ReactNativeBlobUtil.config({ - trusty: !certVerification - }) - .fetch(method, url, headers, data ? JSON.stringify(data) : data) - .then((response: any) => { - delete calls[id]; - if (response.info().status < 300) { - // handle ws responses - if (response.data.includes('\n')) { - const split = response.data.split('\n'); - const length = split.length; - // last instance is empty - return JSON.parse(split[length - 2]); + calls.set( + id, + ReactNativeBlobUtil.config({ + trusty: !certVerification + }) + .fetch( + method, + url, + headers, + data ? JSON.stringify(data) : data + ) + .then((response: any) => { + calls.delete(id); + if (response.info().status < 300) { + // handle ws responses + if (response.data.includes('\n')) { + const split = response.data.split('\n'); + const length = split.length; + // last instance is empty + return JSON.parse(split[length - 2]); + } + return response.json(); + } else { + const errorInfo = response.json(); + throw new Error( + (errorInfo.error && errorInfo.error.message) || + errorInfo.message || + errorInfo.error + ); } - return response.json(); - } else { - const errorInfo = response.json(); - throw new Error( - (errorInfo.error && errorInfo.error.message) || - errorInfo.message || - errorInfo.error - ); - } - }); + }) + ); } - return await calls[id]; + return await calls.get(id); }; supports = (minVersion: string, eosVersion?: string) => { diff --git a/backends/Spark.ts b/backends/Spark.ts index f57d36840..d3a7f9d15 100644 --- a/backends/Spark.ts +++ b/backends/Spark.ts @@ -5,16 +5,18 @@ import TransactionRequest from './../models/TransactionRequest'; import OpenChannelRequest from './../models/OpenChannelRequest'; // keep track of all active calls so we can cancel when appropriate -const calls: any = {}; +const calls = new Map>(); export default class Spark { + clearCachedCalls = () => calls.clear(); + rpc = (rpcmethod: string, param = {}, range: any = null) => { const { accessKey, certVerification, enableTor } = stores.settingsStore; let { url } = stores.settingsStore; const id = rpcmethod + JSON.stringify(param) + JSON.stringify(range); - if (calls[id]) { - return calls[id]; + if (calls.has(id)) { + return calls.get(id); } url = url.slice(-4) === '/rpc' ? url : url + '/rpc'; @@ -26,35 +28,38 @@ export default class Spark { const body = JSON.stringify({ method: rpcmethod, params: param }); if (enableTor === true) { - calls[id] = doTorRequest(url, RequestMethod.POST, body, headers); + calls.set(id, doTorRequest(url, RequestMethod.POST, body, headers)); } else { - calls[id] = ReactNativeBlobUtil.config({ - trusty: !certVerification - }) - .fetch('POST', url, headers, body) - .then((response: any) => { - delete calls[id]; - const status = response.info().status; - if (status < 300) { - return response.json(); - } else { - let errorInfo; - try { - errorInfo = response.json(); - } catch (err) { - throw new Error( - 'response was (' + - status + - ')' + - response.text() - ); + calls.set( + id, + ReactNativeBlobUtil.config({ + trusty: !certVerification + }) + .fetch('POST', url, headers, body) + .then((response: any) => { + calls.delete(id); + const status = response.info().status; + if (status < 300) { + return response.json(); + } else { + let errorInfo; + try { + errorInfo = response.json(); + } catch (err) { + throw new Error( + 'response was (' + + status + + ')' + + response.text() + ); + } + throw new Error(errorInfo.message); } - throw new Error(errorInfo.message); - } - }); + }) + ); } - return calls[id]; + return calls.get(id); }; getTransactions = () => diff --git a/stores/NodeInfoStore.ts b/stores/NodeInfoStore.ts index c0cba8abd..a97697414 100644 --- a/stores/NodeInfoStore.ts +++ b/stores/NodeInfoStore.ts @@ -38,12 +38,18 @@ export default class NodeInfoStore { this.loading = true; }; + private currentRequest: any; + @action public getNodeInfo = () => { this.errorMsg = ''; this.loading = true; + const currentRequest = (this.currentRequest = {}); BackendUtils.getMyNodeInfo() .then((data: any) => { + if (this.currentRequest !== currentRequest) { + return; + } const nodeInfo = new NodeInfo(data); this.nodeInfo = nodeInfo; this.testnet = nodeInfo.isTestNet; @@ -52,6 +58,9 @@ export default class NodeInfoStore { this.error = false; }) .catch((error: any) => { + if (this.currentRequest !== currentRequest) { + return; + } // handle error this.errorMsg = ErrorUtils.errorToUserFriendly( error.toString() diff --git a/stores/SettingsStore.ts b/stores/SettingsStore.ts index adaca0280..736432a48 100644 --- a/stores/SettingsStore.ts +++ b/stores/SettingsStore.ts @@ -1027,6 +1027,7 @@ export default class SettingsStore { if (status) { this.error = false; this.errorMsg = ''; + BackendUtils.clearCachedCalls(); } this.connecting = status; return this.connecting; diff --git a/utils/BackendUtils.ts b/utils/BackendUtils.ts index 75c5093ab..64df6904f 100644 --- a/utils/BackendUtils.ts +++ b/utils/BackendUtils.ts @@ -135,6 +135,8 @@ class BackendUtils { checkPerms = () => this.call('checkPerms'); isConnected = (...args: any[]) => this.call('isConnected', args); disconnect = (...args: any[]) => this.call('disconnect', args); + + clearCachedCalls = (...args: any[]) => this.call('clearCachedCalls', args); } const backendUtils = new BackendUtils();