From 0ad809ac01d54a9714406abfe6b97f2f1e1962fc Mon Sep 17 00:00:00 2001 From: codersbrother Date: Tue, 21 Oct 2014 06:34:03 +0200 Subject: [PATCH 1/8] Some refactors: Scopes delimitation of functions and vars. Remove unused vars. Comment uncommented methods --- client/gateway.js | 753 ++++++++++++++++++++++++---------------------- 1 file changed, 400 insertions(+), 353 deletions(-) diff --git a/client/gateway.js b/client/gateway.js index 0cc1958..a220882 100644 --- a/client/gateway.js +++ b/client/gateway.js @@ -1,389 +1,436 @@ /** * Client to connect to a darkwallet gateway. - * - * @param {String} connect_uri Gateway websocket URI - * @param {Function} handle_connect Callback to run when connected - * @param {Function} handle_disconnect Callback to run when disconnected - * @param {Function} handle_error Callback to run on errors (except connection errors go to handle_connect first parameter). - * - * handle_* callbacks take parameters as (error, data) + * TODO camelcase methods */ -function GatewayClient(connect_uri, handle_connect, handle_disconnect, handle_error) { - var self = this; - this.handler_map = {}; - this.connected = false; - this.websocket = new WebSocket(connect_uri); - var closingCb; - this.close = function(_cb) { - self.connected = false; - self.handler_map = {}; - closingCb = _cb; - self.websocket.close(); - }; - this.websocket.onopen = function(evt) { - self.connected = true; - handle_connect(); - }; - this.websocket.onclose = function(evt) { - self.connected = false; - self.on_close(evt); - if (handle_disconnect) { - handle_disconnect(null, evt) - } - if (closingCb) { - closingCb(); - closingCb = false; - } - }; - this.websocket.onerror = function(evt) { - // TODO: should probably disconnect - if (!self.connected) { - handle_connect(evt); - } else if (handle_error) { - handle_error(evt); - } - }; - this.websocket.onmessage = function(evt) { - self._on_message(evt); - }; -} - -/** - * Get last height - * - * @param {Function} handle_fetch Callback to handle the returned height - */ -GatewayClient.prototype.fetch_last_height = function(handle_fetch) { - GatewayClient._check_function(handle_fetch); - - this.make_request("fetch_last_height", [], function(response) { - handle_fetch(response["error"], response["result"][0]); - }); -}; - -/** - * Fetch transaction - * - * @param {String} tx_hash Transaction identifier hash - * @param {Function} handle_fetch Callback to handle the JSON object - * representing the transaction - */ -GatewayClient.prototype.fetch_transaction = function(tx_hash, handle_fetch) { - GatewayClient._check_function(handle_fetch); - - this.make_request("fetch_transaction", [tx_hash], function(response) { - handle_fetch(response["error"], response["result"][0]); - }); -}; +(function(){ + + /** + * Client to connect to a darkwallet gateway. + * + * @param {String} connect_uri Gateway websocket URI + * @param {Function} handle_connect Callback to run when connected + * @param {Function} handle_disconnect Callback to run when disconnected + * @param {Function} handle_error Callback to run on errors (except connection errors go to handle_connect first parameter). + * + * handle_* callbacks take parameters as (error, data) + */ + function GatewayClient(connect_uri, handle_connect, handle_disconnect, handle_error) { + var self = this; + this.handler_map = {}; + this.connected = false; + this.websocket = new WebSocket(connect_uri); + var closingCb; + this.close = function(_cb) { + self.connected = false; + self.handler_map = {}; + closingCb = _cb; + self.websocket.close(); + }; + this.websocket.onopen = function() { + self.connected = true; + handle_connect(); + }; + this.websocket.onclose = function(evt) { + self.connected = false; + //self.on_close(evt); + if (handle_disconnect) { + handle_disconnect(null, evt) + } + if (closingCb) { + closingCb(); + closingCb = false; + } + }; + this.websocket.onerror = function(evt) { + // TODO: should probably disconnect + if (!self.connected) { + handle_connect(evt); + } else if (handle_error) { + handle_error(evt); + } + }; + this.websocket.onmessage = onMessage.bind(this); + } -/** - * Fetch history - * - * @param {String} address - * @param {Function} handle_fetch Callback to handle the JSON object - * representing the history of the address - */ -GatewayClient.prototype.fetch_history = function(address, height, handle_fetch) { - height = height || 0; - GatewayClient._check_function(handle_fetch); - - this.make_request("fetch_history", [address, height], function(response) { - handle_fetch(response["error"], response["result"][0]); - }); -}; - -GatewayClient.prototype.fetch_stealth = function( - prefix, handle_fetch, from_height) -{ - GatewayClient._check_function(handle_fetch); - - this.make_request("fetch_stealth", [prefix, from_height], - function(response) { - handle_fetch(response["error"], response["result"][0]); + /** + * Make requests to the server + * + * @param {String} command + * @param {Array} params + * @param {Function} handler + */ + function makeRequest(command, params, handler) { + checkFunction(handler); + var id = randomInteger(); + var message = JSON.stringify({ + "id": id, + "command": command, + "params": params }); -}; - -/** - * Subscribe - * - * @param {String} address - * @param {Function} handle_fetch Callback to handle subscription result - * @param {Function} handle_update Callback to handle the JSON object - * representing for updates - */ -GatewayClient.prototype.subscribe = function( - address, handle_fetch, handle_update) -{ - var self = this; - this.make_request("subscribe_address", [address], function(response) { - handle_fetch(response["error"], response["result"][0]); - if (handle_update) { - self.handler_map["update." + address] = handle_update; - } - }); -} - -/** - * Unsubscribe - * - * @param {String} address - * @param {Function} handle_fetch Callback to handle subscription result - * representing for updates - */ - -GatewayClient.prototype.unsubscribe = function(address, handle_fetch) -{ - if (this.handler_map["update." + address]) { - delete this.handler_map["update." + address]; + this.websocket.send(message); + this.handler_map[id] = handler; } - this.make_request("unsubscribe_address", [address], function(response) { - handle_fetch(response["error"], response["result"][0]); - }); -} + /** + * (Pseudo-)Random integer generator + * + * @return {Number} Random integer + */ + function randomInteger() { + return Math.floor((Math.random() * 4294967296)); + } -GatewayClient.prototype.fetch_block_header = function(index, handle_fetch) { - GatewayClient._check_function(handle_fetch); - - this.make_request("fetch_block_header", [index], function(response) { - handle_fetch(response["error"], response["result"][0]); - }); -}; + /** + * Checks if param can be executed + * + * @param {Function} func to be checked + * + * @throws {String} Parameter is not a function + */ + function checkFunction(func) { + if(typeof func !== 'function') throw "Parameter is not a function"; + } -GatewayClient.prototype.fetch_block_transaction_hashes = function( - index, handle_fetch) -{ - GatewayClient._check_function(handle_fetch); + /** + * After triggering message event, calls to the handler of the petition + * + * @param {Object} evt event + */ + function onMessage(evt) { + //this.on_message(evt); + var response = JSON.parse(evt.data); + var id = response.id; + // Should be a separate map entirely. This is a hack. + if (response.type == "update") + id = "update." + response.address; + if (response.type == "chan_update") + id = "chan.update." + response.thread; + // Prefer flat code over nested. + var handler = this.handler_map[id]; + if (handler) { + handler(response); + }else{ + console.log("Handler not found", id); + } + } - this.make_request("fetch_block_transaction_hashes", [index], - function(response) { - handle_fetch(response["error"], response["result"][0]); + /** + * METHODS + */ + + /** + * Get last height + * + * @param {Function} handle_fetch Callback to handle the returned height + */ + GatewayClient.prototype.fetch_last_height = function(handle_fetch) { + checkFunction(handle_fetch); + makeRequest.call(this, "fetch_last_height", [], function(response) { + handle_fetch(response.error, response.result[0]); }); -}; + }; -GatewayClient.prototype.fetch_spend = function(outpoint, handle_fetch) { - GatewayClient._check_function(handle_fetch); + /** + * Fetch transaction + * + * @param {String} tx_hash Transaction identifier hash + * @param {Function} handle_fetch Callback to handle the JSON object representing the transaction + */ + GatewayClient.prototype.fetch_transaction = function(tx_hash, handle_fetch) { + checkFunction(handle_fetch); + makeRequest.call(this, 'fetch_transaction', [tx_hash], function(response) { + handle_fetch(response.error, response.result[0]); + }); + }; - this.make_request("fetch_spend", [outpoint], function(response) { - handle_fetch(response["error"], response["result"][0]); - }); -}; + /** + * Fetch history + * + * @param {String} address + * @param {Number} height + * @param {Function} handle_fetch Callback to handle the JSON object representing the history of the address + */ + GatewayClient.prototype.fetch_history = function(address, height, handle_fetch) { + height = height || 0; + checkFunction(handle_fetch); + makeRequest.call(this, 'fetch_history', [address, height], function(response) { + handle_fetch(response.error, response.result[0]); + }); + }; -GatewayClient.prototype.fetch_transaction_index = function( - tx_hash, handle_fetch) -{ - GatewayClient._check_function(handle_fetch); + /** + * Fetch stealth + * TODO: move params order + * + * @param {String} prefix + * @param {Function} handle_fetch + * @param {Number} from_height + */ + GatewayClient.prototype.fetch_stealth = function(prefix, handle_fetch, from_height){ + checkFunction(handle_fetch); + makeRequest.call(this, 'fetch_stealth', [prefix, from_height], function(response) { + handle_fetch(response.error, response.result[0]); + }); + }; - this.make_request("fetch_transaction_index", [tx_hash], - function(response) { - result = response["result"]; - handle_fetch(response["error"], result[0], result[1]); + /** + * Subscribe + * + * @param {String} address + * @param {Function} handle_fetch Callback to handle subscription result + * @param {Function} handle_update Callback to handle the JSON object representing for updates + */ + GatewayClient.prototype.subscribe = function(address, handle_fetch, handle_update){ + checkFunction(handle_fetch); + var handle_map = this.handler_map; + makeRequest.call(this, 'subscribe_address', [address], function(response) { + handle_fetch(response.error, response.result[0]); + if (handle_update ) { + checkFunction(handle_update); + handle_map['update.' + address] = handle_update; + } }); -}; + }; -GatewayClient.prototype.fetch_block_height = function(blk_hash, handle_fetch) -{ - GatewayClient._check_function(handle_fetch); + /** + * Unsubscribe + * + * @param {String} address + * @param {Function} handle_fetch Callback to handle subscription result representing for updates + */ + GatewayClient.prototype.unsubscribe = function(address, handle_fetch){ + checkFunction(handle_fetch); + if (this.handler_map['update.' + address]) { + delete this.handler_map['update.' + address]; + } + makeRequest.call(this, 'unsubscribe_address', [address], function(response) { + handle_fetch(response.error, response.result[0]); + }); + }; - this.make_request("fetch_block_height", [blk_hash], function(response) { - handle_fetch(response["error"], response["result"][0]); - }); -}; + /** + * Fetch block header + * + * @param {String} index + * @param {Function} handle_fetch + */ + GatewayClient.prototype.fetch_block_header = function(index, handle_fetch) { + checkFunction(handle_fetch); + makeRequest.call(this, 'fetch_block_header', [index], function(response) { + handle_fetch(response.error, response.result[0]); + }); + }; -GatewayClient.prototype.broadcast_transaction = function( - raw_tx, handle_fetch) -{ - GatewayClient._check_function(handle_fetch); + /** + * Fetch block transaction hashes + * + * @param {String} index + * @param {Function} handle_fetch + */ + GatewayClient.prototype.fetch_block_transaction_hashes = function(index, handle_fetch) { + checkFunction(handle_fetch); + makeRequest.call(this, "fetch_block_transaction_hashes", [index], function(response) { + handle_fetch(response.error, response.result[0]); + }); + }; - this.make_request("broadcast_transaction", [raw_tx], function(response) { - handle_fetch(response["error"], response["result"][0]); - }); -}; + /** + * Fetch spend + * + * @param {String} outpoint + * @param {Function} handle_fetch + */ + GatewayClient.prototype.fetch_spend = function(outpoint, handle_fetch) { + checkFunction(handle_fetch); + makeRequest.call(this, 'fetch_spend', [outpoint], function(response) { + handle_fetch(response.error, response.result[0]); + }); + }; -/** - * Renew - * - * @param {String} address - * @param {Function} handle_fetch Callback to handle subscription result - * @param {Function} handle_update Callback to handle the JSON object - * representing for updates - */ -GatewayClient.prototype.renew = function(address, handle_fetch, handle_update) -{ - var self = this; - this.make_request("renew_address", [address], function(response) { - handle_fetch(response["error"], response["result"][0]); - if (handle_update) { - self.handler_map["update."+address] = handle_update; - } - }); -} + /** + * Fetch transaction index + * + * @param {String} tx_hash + * @param {Function} handle_fetch + */ + GatewayClient.prototype.fetch_transaction_index = function(tx_hash, handle_fetch){ + checkFunction(handle_fetch); + makeRequest.call(this, 'fetch_transaction_index', [tx_hash], function(response) { + var result = response.result; + handle_fetch(response["error"], result[0], result[1]); + }); + }; -/** - * Chan functionality - */ -GatewayClient.prototype.chan_post = function(section_name, thread_id, data, handle_fetch) { - GatewayClient._check_function(handle_fetch); - - this.make_request("chan_post", [section_name, thread_id, data], function(response) { - if (handle_fetch) - handle_fetch(response["error"], response["result"]); - }); -}; - -GatewayClient.prototype.chan_list = function(section_name, handle_fetch) { - GatewayClient._check_function(handle_fetch); - - this.make_request("chan_list", [section_name], function(response) { - if (handle_fetch) - handle_fetch(response["error"], response["result"]); - }); -}; - - -GatewayClient.prototype.chan_get = function(section_name, thread_id, handle_fetch) { - GatewayClient._check_function(handle_fetch); - - this.make_request("chan_get", [section_name, thread_id], function(response) { - if (handle_fetch) - handle_fetch(response["error"], response["result"]); - }); -}; - -GatewayClient.prototype.chan_subscribe = function(section_name, thread_id, handle_fetch, handle_update) { - GatewayClient._check_function(handle_fetch); - var self = this; - this.make_request("chan_subscribe", [section_name, thread_id], function(response) { - if (handle_fetch) - handle_fetch(response["error"], response["result"]); - if (handle_update) { - self.handler_map["chan.update." + thread_id] = handle_update; - } + /** + * Fetch block height + * + * @param {String} blk_hash + * @param {Function} handle_fetch + */ + GatewayClient.prototype.fetch_block_height = function(blk_hash, handle_fetch){ + checkFunction(handle_fetch); + makeRequest.call(this, 'fetch_block_height', [blk_hash], function(response) { + handle_fetch(response.error, response.result[0]); + }); + }; - }); -}; -GatewayClient.prototype.chan_unsubscribe = function(section_name, thread_id, handle_fetch, handle_update) { - GatewayClient._check_function(handle_fetch); - var self = this; - this.make_request("chan_unsubscribe", [section_name, thread_id], function(response) { - if (handle_fetch) - handle_fetch(response["error"], response["result"]); - if (self.handler_map["chan.update." + thread_id]) { - delete self.handler_map["chan.update." + thread_id] - } - }); -}; + /** + * Broadcast transaction + * + * @param {String} raw_tx + * @param {Function} handle_fetch + */ + GatewayClient.prototype.broadcast_transaction = function(raw_tx, handle_fetch){ + checkFunction(handle_fetch); + makeRequest.call(this, 'broadcast_transaction', [raw_tx], function(response) { + handle_fetch(response.error, response.result[0]); + }); + }; + /** + * Renew + * + * @param {String} address + * @param {Function} handle_fetch Callback to handle subscription result + * @param {Function} handle_update Callback to handle the JSON object representing for updates + */ + GatewayClient.prototype.renew = function(address, handle_fetch, handle_update) { + var handler_map = this.handler_map; + makeRequest.call(this, 'renew_address', [address], function(response) { + handle_fetch(response.error, response.result[0]); + if (handle_update) { + checkFunction(handle_update); + handler_map['update.' + address] = handle_update; + } + }); + }; -/** - * Ticker functionality - * - * @param {String} currency, like USD, EUR... - * @param {Function} handle_fetch - */ + /** + * Chan post + * + * @param {String} section_name + * @param {String} thread_id + * @param {String} data + * @param {Function} handle_fetch + */ + GatewayClient.prototype.chan_post = function(section_name, thread_id, data, handle_fetch) { + checkFunction(handle_fetch); + makeRequest.call(this, 'chan_post', [section_name, thread_id, data], function(response) { + handle_fetch(response.error, response.result); + }); + }; -GatewayClient.prototype.fetch_ticker = function(currency, handle_fetch) -{ - GatewayClient._check_function(handle_fetch); + /** + * Chan list + * + * @param {String} section_name + * @param {Function} handle_fetch + */ + GatewayClient.prototype.chan_list = function(section_name, handle_fetch) { + checkFunction(handle_fetch); + makeRequest.call(this, 'chan_list', [section_name], function(response) { + handle_fetch(response.error, response.result); + }); + }; - this.make_request("fetch_ticker", [currency], function(response) { - handle_fetch(response["error"], response["result"][0]); - }); -}; + /** + * Chan get + * + * @param {String} section_name + * @param {String} thread_id + * @param {Function} handle_fetch + */ + GatewayClient.prototype.chan_get = function(section_name, thread_id, handle_fetch) { + checkFunction(handle_fetch); + makeRequest.call(this, 'chan_get', [section_name, thread_id], function(response) { + handle_fetch(response.error, response.result); + }); + }; -/** - * Make requests to the server - * - * @param {String} command - * @param {Array} params - * @param {Function} handler - */ -GatewayClient.prototype.make_request = function(command, params, handler) { - GatewayClient._check_function(handler); - - var id = GatewayClient._random_integer(); - var request = { - "id": id, - "command": command, - "params": params + /** + * Chan subscribe + * + * @param {String} section_name + * @param {String} thread_id + * @param {Function} handle_fetch + * @param {Function} handle_update + */ + GatewayClient.prototype.chan_subscribe = function(section_name, thread_id, handle_fetch, handle_update) { + checkFunction(handle_fetch); + var handler_map = self.handler_map; + makeRequest.call(this, 'chan_subscribe', [section_name, thread_id], function(response) { + handle_fetch(response.error, response.result); + if (handle_update) { + checkFunction(handle_update); + handler_map["chan.update." + thread_id] = handle_update; + } + }); }; - var message = JSON.stringify(request); - this.websocket.send(message); - this.handler_map[id] = handler; -}; -/** - * Close event handler - * - * @param {Object} evt event - */ -GatewayClient.prototype.on_close = function(evt) { -}; + /** + * Chan subscribe + * TODO ¿handle_update param? + * + * @param {String} section_name + * @param {String} thread_id + * @param {Function} handle_fetch + * @param {Function} handle_update + */ + GatewayClient.prototype.chan_unsubscribe = function(section_name, thread_id, handle_fetch, handle_update) { + checkFunction(handle_fetch); + var handler_map = this.handler_map; + makeRequest.call(this, 'chan_unsubscribe', [section_name, thread_id], function(response) { + handle_fetch(response.error, response.result); + if (handler_map['chan.update.' + thread_id]) { + delete handler_map['chan.update.' + thread_id]; + } + }); + }; -/** - * Error event handler - * - * @param {Object} evt event - * - * @throws {Object} - */ -GatewayClient.prototype.on_error = function(evt) { - throw evt; -}; + /** + * Ticker functionality + * + * @param {String} currency Like USD, EUR... + * @param {Function} handle_fetch + */ + GatewayClient.prototype.fetch_ticker = function(currency, handle_fetch){ + checkFunction(handle_fetch); + makeRequest.call(this, 'fetch_ticker', [currency], function(response) { + handle_fetch(response.error, response.result[0]); + }); + }; -/** - * After triggering message event, calls to the handler of the petition - * - * @param {Object} evt event - * @private - */ -GatewayClient.prototype._on_message = function(evt) { - this.on_message(evt) - response = JSON.parse(evt.data); - id = response.id; - // Should be a separate map entirely. This is a hack. - if (response.type == "update") - id = "update." + response.address; - if (response.type == "chan_update") - id = "chan.update." + response.thread; - // Prefer flat code over nested. - if (!this.handler_map[id]) { - console.log("Handler not found", id); - return; - } - handler = this.handler_map[id]; - handler(response); -}; + /** + * LIKE EVENTS + */ + + /** + * Close event handler + * + * @param {Object} evt event + */ + GatewayClient.prototype.on_close = function(evt) {}; + + /** + * Error event handler + * + * @param {Object} evt event + * + * @throws {Object} + */ + GatewayClient.prototype.on_error = function(evt) { + throw evt; + }; -/** - * Message event handler - * - * @param {Object} evt event - */ -GatewayClient.prototype.on_message = function(evt) { -} + /** + * Message event handler + * + * @param {Object} evt event + */ + GatewayClient.prototype.on_message = function(evt) {}; -/** - * (Pseudo-)Random integer generator - * - * @return {Number} Random integer - * @private - */ -GatewayClient._random_integer = function() { - return Math.floor((Math.random() * 4294967296)); -}; -/** - * Checks if param can be executed - * - * @param {Function} Function to be checked - * - * @throws {String} Parameter is not a function - * @protected - */ -GatewayClient._check_function = function(func) { - if (typeof func !== 'function') { - throw "Parameter is not a function"; - } -}; + // Expose GatewayClient + window.GatewayClient = GatewayClient; +})(); \ No newline at end of file From 65301d533506b6bd1f1f28cdb121584c80ebe524 Mon Sep 17 00:00:00 2001 From: codersbrother Date: Tue, 21 Oct 2014 06:37:24 +0200 Subject: [PATCH 2/8] Remove some not used and empty methods. --- client/gateway.js | 32 -------------------------------- 1 file changed, 32 deletions(-) diff --git a/client/gateway.js b/client/gateway.js index a220882..50e51fa 100644 --- a/client/gateway.js +++ b/client/gateway.js @@ -32,7 +32,6 @@ }; this.websocket.onclose = function(evt) { self.connected = false; - //self.on_close(evt); if (handle_disconnect) { handle_disconnect(null, evt) } @@ -97,7 +96,6 @@ * @param {Object} evt event */ function onMessage(evt) { - //this.on_message(evt); var response = JSON.parse(evt.data); var id = response.id; // Should be a separate map entirely. This is a hack. @@ -400,36 +398,6 @@ }); }; - /** - * LIKE EVENTS - */ - - /** - * Close event handler - * - * @param {Object} evt event - */ - GatewayClient.prototype.on_close = function(evt) {}; - - /** - * Error event handler - * - * @param {Object} evt event - * - * @throws {Object} - */ - GatewayClient.prototype.on_error = function(evt) { - throw evt; - }; - - /** - * Message event handler - * - * @param {Object} evt event - */ - GatewayClient.prototype.on_message = function(evt) {}; - - // Expose GatewayClient window.GatewayClient = GatewayClient; From 8e841cd01f8e479e1903b07e5a2325502bda4649 Mon Sep 17 00:00:00 2001 From: codersbrother Date: Tue, 21 Oct 2014 07:36:15 +0200 Subject: [PATCH 3/8] Unnused params, some TODO tasks. --- README.md | 5 +++++ client/gateway.js | 12 +++++------- 2 files changed, 10 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index 847b3bf..20695f6 100644 --- a/README.md +++ b/README.md @@ -49,3 +49,8 @@ address history $ curl http://localhost:8888/address/1dice3jkpTvevsohA4Np1yP4uKzG1SRLv { "history" : [{"spend_hash": "cdf6ea4f4590fbc847855cf68af181f1398b8997081cf0cfbd14e0f2cf2808ea", "output_height": 228180, "spend_index": 0, "value": 1000000, .... ``` + +TODO +-------------- +* Add to wiki method documentation, and some link to learn about concepts +* Create a image-schema of Darkwallet ecosystem parts and how are connected \ No newline at end of file diff --git a/client/gateway.js b/client/gateway.js index 50e51fa..2ed5198 100644 --- a/client/gateway.js +++ b/client/gateway.js @@ -62,9 +62,9 @@ checkFunction(handler); var id = randomInteger(); var message = JSON.stringify({ - "id": id, - "command": command, - "params": params + id: id, + command: command, + params: params }); this.websocket.send(message); this.handler_map[id] = handler; @@ -367,14 +367,12 @@ /** * Chan subscribe - * TODO ¿handle_update param? * * @param {String} section_name * @param {String} thread_id * @param {Function} handle_fetch - * @param {Function} handle_update */ - GatewayClient.prototype.chan_unsubscribe = function(section_name, thread_id, handle_fetch, handle_update) { + GatewayClient.prototype.chan_unsubscribe = function(section_name, thread_id, handle_fetch) { checkFunction(handle_fetch); var handler_map = this.handler_map; makeRequest.call(this, 'chan_unsubscribe', [section_name, thread_id], function(response) { @@ -398,7 +396,7 @@ }); }; - // Expose GatewayClient + // Expose only GatewayClient window.GatewayClient = GatewayClient; })(); \ No newline at end of file From bd4b5ca212ce849abc6566e238328030805e187e Mon Sep 17 00:00:00 2001 From: codersbrother Date: Tue, 21 Oct 2014 08:00:02 +0200 Subject: [PATCH 4/8] Suported as AMD module --- client/gateway.js | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/client/gateway.js b/client/gateway.js index 2ed5198..292ade2 100644 --- a/client/gateway.js +++ b/client/gateway.js @@ -3,6 +3,7 @@ * TODO camelcase methods */ (function(){ + "use strict"; /** * Client to connect to a darkwallet gateway. @@ -396,7 +397,14 @@ }); }; - // Expose only GatewayClient + // Expose at window window.GatewayClient = GatewayClient; + // Expose as AMD module + if (typeof window.define === "function" && window.define.amd) { + window.define("GatewayClient", [], function() { + return window.GatewayClient; + }); + } + })(); \ No newline at end of file From 4c345f98be920f68be6c4e6bcf38c9a99cceb0b1 Mon Sep 17 00:00:00 2001 From: codersbrother Date: Tue, 21 Oct 2014 12:11:14 +0200 Subject: [PATCH 5/8] Refactor for better view. Sync messages with responses and order for load functions. Some visual changes for see as blocks and understand what is the same part of a request. Changed url of websocket server --- client/test.html | 379 ++++++++++++++++++++++++++++------------------- 1 file changed, 223 insertions(+), 156 deletions(-) diff --git a/client/test.html b/client/test.html index 50e854a..4b1a35d 100644 --- a/client/test.html +++ b/client/test.html @@ -6,181 +6,248 @@ + +

WebSocket Test

- - + \ No newline at end of file From c3156bb8c1ea9e3122214d28c37e7e610d9cc81c Mon Sep 17 00:00:00 2001 From: codersbrother Date: Wed, 22 Oct 2014 04:38:43 +0200 Subject: [PATCH 6/8] Object to manage logs and resolve async order to log in Screen. Simple example without pyramid of doom. --- client/test.html | 238 ++++++++++++++++++++++++++--------------------- 1 file changed, 134 insertions(+), 104 deletions(-) diff --git a/client/test.html b/client/test.html index 4b1a35d..70c7057 100644 --- a/client/test.html +++ b/client/test.html @@ -11,217 +11,244 @@ function init() { output = document.getElementById("output"); - var handle_connect = function() { - write_to_screen("CONNECTED"); + + var client = new GatewayClient(WEBSOCKET_SERVER_URL, function(){ + output.innerHTML = 'CONNECTED'; test(client); - }; - var client = new GatewayClient(WEBSOCKET_SERVER_URL, handle_connect); + }); client.on_error = function(evt) { - write_to_screen('ERROR: ' + evt.data); + output.innerHTML = 'ERROR: ' + evt.data; }; - client.on_close = function(evt) { - write_to_screen("DISCONNECTED"); + client.on_close = function() { + output.innerHTML += "DISCONNECTED"; }; } - function write_to_screen(message) { - var pre = document.createElement("p"); - pre.innerHTML = message; - output.appendChild(pre); - } - - function logError(error){ - write_to_screen('ERROR: ' + error); - } - - function logJSON(label, json){ - var tx_str = JSON.stringify(json, null, 2); - return label + ":
" + tx_str + "
"; - } - - function blockLog(title, result){ - var html = '
' + - '

' + title + '

' + - result + - '
'; - write_to_screen(html); - } - window.addEventListener("load", init, false); + /** + * ON WEBSOCKET CONNECTED RUN ALL THIS AS EXAMPLE + */ function test(client) { var txHash = "2604ba7d2190111dbc16b53b0f56ad4351ceabe1b9e1b4f6f1bc75e271bb09b9"; var blkHash = "000000000019d6689c085ae165831e934ff763ae46a2a6c172b3f1b60a8ce26f"; - // Wellcome to piramyd of doom :D (Add promises) - fetchLastHeight(function(){ - fetchTransaction(function(){ - fetchHistory(function(){ - fetchBlockHeader(function(){ - fetchBlockHeaderByHash(function(){ - fetchBlockTransactionHashes(function(){ - fetchSpend(function(){ - fetchTransactionIndex(function(){ - fetchBlockHeight(function(){ - broadcastTransaction(function(){ - fetchStealth(function(){ - fetchTicker(); - }); - }); - }); - }); - }); - }); - }); - }); - }); - }); - }); - + fetchLastHeight(); + fetchTransaction(); + fetchHistory(); + fetchBlockHeader(); + fetchBlockHeaderByHash(); + fetchBlockTransactionHashes(); + fetchSpend(); + fetchTransactionIndex(); + fetchBlockHeight(); + broadcastTransaction(); + fetchStealth(); + fetchTicker(); - function fetchLastHeight(cb){ + function fetchLastHeight(){ + var writeToScreen = new WriteToScreen('Fetch last height', 'Loading...'); client.fetch_last_height(function(error, height) { + writeToScreen.clear(); if (error) { - logError(error); + writeToScreen.error(error); return; } - blockLog('Fetching last height', height); - cb(); + writeToScreen.text(height); + }); } - function fetchTransaction(cb){ + function fetchTransaction(){ + var writeToScreen = new WriteToScreen('Fetching transaction', 'Loading...'); client.fetch_transaction(txHash, function(error, tx){ + writeToScreen.clear(); if (error) { - logError(error); + writeToScreen.error(error); return; } - blockLog('Fetching transaction', logJSON('tx', tx)); - cb(); + writeToScreen.json(tx); }); } - function fetchHistory(cb){ - var address = "1PF8uJGxheHCJePsbbPh22dQ1Z1nz3J61F"; + function fetchHistory(){ + var address = "14KBBqizrowzeezaTtgXY5us1LxZMksi93"; + var writeToScreen = new WriteToScreen('Fetching address history ' + address, 'Loading...'); client.fetch_history(address, 0, function (error, history) { + writeToScreen.clear(); if (error) { - logError(error); + writeToScreen.error(error); return; } - blockLog('Fetching address history ' + address, logJSON('History', history)); - cb(); + writeToScreen.json(history); }); } - function fetchBlockHeader(cb){ + function fetchBlockHeader(){ var blk_height = 0; + var writeToScreen = new WriteToScreen('Fetch block header ' + blk_height, 'Loading...'); client.fetch_block_header(blk_height, function (error, header) { + writeToScreen.clear(); if (error) { - logError(error); + writeToScreen.error(error); return; } - blockLog('Fetch block header ' + blk_height, logJSON('Block header', header)); - cb(); + writeToScreen.json(header); }); } - function fetchBlockHeaderByHash(cb){ + function fetchBlockHeaderByHash(){ + var writeToScreen = new WriteToScreen('Fetching block header ' + blkHash, 'Loading...'); client.fetch_block_header(blkHash, function (error, header) { + writeToScreen.clear(); if (error) { - logError(error); + writeToScreen.error(error); return; } - blockLog('Fetch block header ' + blkHash, logJSON('Block header', header)); - cb(); + writeToScreen.json(header); }); } - function fetchBlockTransactionHashes(cb){ + function fetchBlockTransactionHashes(){ var blk_height = 100000; + var writeToScreen = new WriteToScreen('Fetching block tx hashes ' + blk_height, 'Loading...'); client.fetch_block_transaction_hashes(blk_height, function (error, tx_hashes) { + writeToScreen.clear(); if (error) { - logError(error); + writeToScreen.error(error); return; } - blockLog('Fetch block tx hashes ' + blk_height, logJSON('Block tx hashes', tx_hashes)); - cb(); + writeToScreen.json(tx_hashes); }); } - function fetchSpend(cb){ + function fetchSpend(){ var outpoint = ["3ca64964ecb449a70a845a437e83d6c4040b5529aaeeb5a89b50a5ab96a293f0", 0]; + var writeToScreen = new WriteToScreen('Fetching spend ' + outpoint, 'Loading...'); client.fetch_spend(outpoint, function (error, inpoint) { + writeToScreen.clear(); if (error) { - logError(error); + writeToScreen.error(error); return; } - blockLog('Fetch spend ' + outpoint, logJSON('Send input point', inpoint)); - cb(); + writeToScreen.json(inpoint); }); } - function fetchTransactionIndex(cb){ + function fetchTransactionIndex(){ + var writeToScreen = new WriteToScreen('Fetching transaction index ' + txHash, 'Loading...'); client.fetch_transaction_index(txHash, function (error, blk_height, tx_offset) { + writeToScreen.clear(); if (error) { - logError(error); + writeToScreen.error(error); return; } - blockLog('Fetch transaction index ' + txHash, "Tx index: " + blk_height + " " + tx_offset + ""); - cb(); + writeToScreen.text('Tx index: ' + blk_height + ' ' + tx_offset); }); } - function fetchBlockHeight(cb){ + function fetchBlockHeight(){ + var writeToScreen = new WriteToScreen('Fetching block height ' + blkHash, 'Loading...'); client.fetch_block_height(blkHash, function (error, blk_height, tx_offset) { + writeToScreen.clear(); if (error) { - logError(error); + writeToScreen.error(error); return; } - blockLog('Fetch block height ' + blkHash, "Tx index: " + blk_height + " " + tx_offset + ""); - cb(); + writeToScreen.text('Tx index: ' + blk_height + ' ' + tx_offset); }); } - function broadcastTransaction(cb){ + function broadcastTransaction(){ var raw_tx = "0100000002f5e32bb2cdeed63c2afcda68075fd5ab87222b17376ea0f45377faaf9f89818e000000008b483045022100a1a7a7f10cf1453a9daa51f09deb26c6cfee439a1bc123e8b482782baf45b41902206a1da8fc5c9d441fb58ce54b88c157535cc01c654d38c5494426c7fe37d1be72014104cf2e5b02d6f02340f5a9defbbf710c388b8451c82145b1419fe9696837b1cdefc569a2a79baa6da2f747c3b25a102a081dfd5e799abc41262103e0d17114770bfffffffffd9dcdb0da7840ca00001d83737faeabcb80c0a0a5bcc884bcd833d01863d2f5000000008a47304402200211a9ab26ce9c5a195492c5ee947f0cedd4be16de9e8f3fe98c2421ae325ba9022008094b2db5374d21d8e2447d1c5ad914adc9d845912998a04997bfdb5a440f1c014104cf2e5b02d6f02340f5a9defbbf710c388b8451c82145b1419fe9696837b1cdefc569a2a79baa6da2f747c3b25a102a081dfd5e799abc41262103e0d17114770bffffffff0240548900000000001976a914981da5bcf1120129a4de20be4d8bf9ea9665dfb788ac80dff400000000001976a914f6475d27495d28093c7089a3d2d2486e78dc894088ac00000000"; + var writeToScreen = new WriteToScreen('Broadcasting tx ' + raw_tx, 'Loading...'); client.broadcast_transaction(raw_tx, function (error, count) { + writeToScreen.clear(); if (error) { - logError(error); + writeToScreen.error(error); return; } - blockLog('Broadcasting tx ' + raw_tx, "Tx radar count:
" + count + "
"); - cb(); + writeToScreen.text('Tx radar count:
' + count + '
'); }); } - function fetchStealth(cb){ + function fetchStealth(){ var prefix = [2, 1763505291]; + var writeToScreen = new WriteToScreen('Fetching stealth ' + prefix, 'Loading...'); client.fetch_stealth(prefix, function (error, results) { + writeToScreen.clear(); if (error) { - logError(error); + writeToScreen.error(error); return; } - blockLog('Fetch stealth ' + prefix, logJSON('Stealth results', results)); - cb(); + writeToScreen.json(results); }, 0); } - function fetchTicker(cb){ + function fetchTicker(){ + var writeToScreen = new WriteToScreen('Fetching ticker', 'Loading...'); client.fetch_ticker("USD", function (error, result) { + writeToScreen.clear(); if (error) { - logError(error); + writeToScreen.error(error); return; } - blockLog('Fetch ticker', logJSON('Ticker results', result)); - cb(); + writeToScreen.json(result); }); } } + /** + * ONLY FOR MANAGE SCREEN LOGS + */ + (function(){ + + function writeInBlock(text){ + var content = this.block.getElementsByClassName('content')[0]; + content.innerHTML += text; + } + + function WriteToScreen(title, text){ + this.block = document.createElement("div"); + this.block.setAttribute('class', 'block'); + this.block.innerHTML = '

' + title + '

'; + this.block.innerHTML += '
' + text + '
'; + output.appendChild(this.block); + } + + WriteToScreen.prototype.clear = function(){ + var content = this.block.getElementsByClassName('content'); + while (content.firstChild) { + content.removeChild(content.firstChild); + } + return this; + }; + + WriteToScreen.prototype.text = function(text){ + writeInBlock.call(this, text); + }; + + WriteToScreen.prototype.error = function(text){ + var html = 'ERROR: ' + text; + writeInBlock.call(this, html); + return this; + }; + + WriteToScreen.prototype.json = function(json){ + var tx_str = JSON.stringify(json, null, 2); + var html = '
' + tx_str + '
'; + writeInBlock.call(this, html); + return this; + }; + + window.WriteToScreen = WriteToScreen; + + })(); + From 65de4a5bd6b398fb01c40a7799712af175c19ad8 Mon Sep 17 00:00:00 2001 From: codersbrother Date: Wed, 22 Oct 2014 04:40:23 +0200 Subject: [PATCH 7/8] Some bugfix in method documentation. Added methods on_error, on close (removed as error previously) --- client/gateway.js | 32 ++++++++++++++++++++++++++------ 1 file changed, 26 insertions(+), 6 deletions(-) diff --git a/client/gateway.js b/client/gateway.js index 292ade2..b4f2139 100644 --- a/client/gateway.js +++ b/client/gateway.js @@ -10,8 +10,8 @@ * * @param {String} connect_uri Gateway websocket URI * @param {Function} handle_connect Callback to run when connected - * @param {Function} handle_disconnect Callback to run when disconnected - * @param {Function} handle_error Callback to run on errors (except connection errors go to handle_connect first parameter). + * @param {Function} [handle_disconnect] Callback to run when disconnected + * @param {Function} [handle_error] Callback to run on errors (except connection errors go to handle_connect first parameter). * * handle_* callbacks take parameters as (error, data) */ @@ -33,6 +33,7 @@ }; this.websocket.onclose = function(evt) { self.connected = false; + self.on_close(evt); if (handle_disconnect) { handle_disconnect(null, evt) } @@ -42,6 +43,7 @@ } }; this.websocket.onerror = function(evt) { + self.on_error(evt); // TODO: should probably disconnect if (!self.connected) { handle_connect(evt); @@ -161,7 +163,7 @@ * Fetch stealth * TODO: move params order * - * @param {String} prefix + * @param {Array} prefix * @param {Function} handle_fetch * @param {Number} from_height */ @@ -210,7 +212,7 @@ /** * Fetch block header * - * @param {String} index + * @param {Number} index * @param {Function} handle_fetch */ GatewayClient.prototype.fetch_block_header = function(index, handle_fetch) { @@ -223,7 +225,7 @@ /** * Fetch block transaction hashes * - * @param {String} index + * @param {Number} index * @param {Function} handle_fetch */ GatewayClient.prototype.fetch_block_transaction_hashes = function(index, handle_fetch) { @@ -236,7 +238,7 @@ /** * Fetch spend * - * @param {String} outpoint + * @param {Array} outpoint * @param {Function} handle_fetch */ GatewayClient.prototype.fetch_spend = function(outpoint, handle_fetch) { @@ -397,6 +399,24 @@ }); }; + /** + * Error event handler + * + * @param {Object} evt event + * + * @throws {Object} + */ + GatewayClient.prototype.on_error = function(evt){ + throw evt; + }; + + /** + * Close event handler + * + * @param {Object} evt event + */ + GatewayClient.prototype.on_close = function(evt){}; + // Expose at window window.GatewayClient = GatewayClient; From 52b96c8c0e8bd3e43dab3c145bba42cb783a5b7a Mon Sep 17 00:00:00 2001 From: codersbrother Date: Mon, 3 Nov 2014 23:57:13 +0100 Subject: [PATCH 8/8] Bugfix self reference --- client/gateway.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/gateway.js b/client/gateway.js index b4f2139..3eb731a 100644 --- a/client/gateway.js +++ b/client/gateway.js @@ -358,7 +358,7 @@ */ GatewayClient.prototype.chan_subscribe = function(section_name, thread_id, handle_fetch, handle_update) { checkFunction(handle_fetch); - var handler_map = self.handler_map; + var handler_map = this.handler_map; makeRequest.call(this, 'chan_subscribe', [section_name, thread_id], function(response) { handle_fetch(response.error, response.result); if (handle_update) {