diff --git a/supernode/index.html b/supernode/index.html index 2f4ebc1..debdbbe 100644 --- a/supernode/index.html +++ b/supernode/index.html @@ -22102,6 +22102,16 @@ ] = true; const RM_RPC = new localbitcoinplusplus.rpc(); + + // Ask backup Supernodes to delete deletable data from backup db instance + RM_RPC.send_rpc + .call(this, "delete_deletables_from_supernode_db_instance", { + trader_flo_address: su_db_data.trader_flo_address, + delete_deletables: true + }) + .then(server_response => doSend(server_response)); + + // Inform users RM_RPC.send_rpc .call(this, "supernode_message", { trader_flo_address: @@ -22139,7 +22149,6 @@ ) { (async function() { let _addDB = addDB; - let _removeAllinDB = removeAllinDB; let _updateinDB = updateinDB; let backup_db; @@ -22231,6 +22240,60 @@ } break; + case "delete_deletables_from_supernode_db_instance": + if(localbitcoinplusplus.master_configurations.supernodesPubKeys + .includes(localbitcoinplusplus.wallets.my_local_flo_public_key) + && + localbitcoinplusplus.master_configurations.supernodesPubKeys + .includes(res_obj.nodePubKey)) { + + if(res_obj.params[0].delete_deletables===true + && typeof localbitcoinplusplus.newBackupDatabase + .db[res_obj.params[0].trader_flo_address]==="object") { + + const backup_db_inst = localbitcoinplusplus.newBackupDatabase + .db[res_obj.params[0].trader_flo_address]; + + const _readAllDB = backup_db_inst.backup_readAllDB.bind(backup_db_inst); + const _removeinDB = backup_db_inst.backup_removeinDB.bind(backup_db_inst); + + const tableArray = [ + "deposit", + "cash_deposits", + "withdraw_cash", + "withdraw_btc", + "cash_balances", + "crypto_balances", + "buyOrders", + "sellOrders", + "system_btc_reserves_private_keys" + ]; + + let del_promise = []; + + (async function() { + try { + for (let tbl of tableArray) { + const allDataPromises = await _readAllDB(tbl, false); + + for(t of allDataPromises) { + if(t.is_deletable===true) { + console.log(tbl, t); + del_promise.push(_removeinDB(tbl, t.id, true)); + } + } + } + + console.log(del_promise); + await Promise.all(del_promise); + } catch (error) { + throw new Error(error); + } + })(); + } + } + break; + case "reconnect_with_another_supernode": if ( typeof res_obj.params == "object" && @@ -25745,7 +25808,6 @@ ) { (async function() { let _addDB = addDB; - let _removeAllinDB = removeAllinDB; let _updateinDB = updateinDB; let backup_db; @@ -26418,6 +26480,60 @@ } break; + + case "delete_deletables_from_supernode_db_instance": + if(localbitcoinplusplus.master_configurations.supernodesPubKeys + .includes(localbitcoinplusplus.wallets.my_local_flo_public_key) + && + localbitcoinplusplus.master_configurations.supernodesPubKeys + .includes(res_obj.nodePubKey)) { + + if(res_obj.params[0].delete_deletables===true + && typeof localbitcoinplusplus.newBackupDatabase + .db[res_obj.params[0].trader_flo_address]==="object") { + + const backup_db_inst = localbitcoinplusplus.newBackupDatabase + .db[res_obj.params[0].trader_flo_address]; + + const _readAllDB = backup_db_inst.backup_readAllDB.bind(backup_db_inst); + const _removeinDB = backup_db_inst.backup_removeinDB.bind(backup_db_inst); + + const tableArray = [ + "deposit", + "cash_deposits", + "withdraw_cash", + "withdraw_btc", + "cash_balances", + "crypto_balances", + "buyOrders", + "sellOrders", + "system_btc_reserves_private_keys" + ]; + + let del_promise = []; + + (async function() { + try { + for (let tbl of tableArray) { + const allDataPromises = await _readAllDB(tbl, false); + + for(t of allDataPromises) { + if(t.is_deletable===true) { + console.log(tbl, t); + del_promise.push(_removeinDB(tbl, t.id, true)); + } + } + } + + console.log(del_promise); + await Promise.all(del_promise); + } catch (error) { + throw new Error(error); + } + })(); + } + } + break; default: break; @@ -27060,7 +27176,7 @@ var request = objectStore.get(id); request.onerror = function(event) { - reject("Unable to retrieve data from database!"); + reject(event); }; request.onsuccess = function(event) { @@ -27091,11 +27207,12 @@ var transaction = db.transaction([tablename]); var objectStore = transaction.objectStore(tablename); let response = []; - objectStore.openCursor().onerror = function(event) { + var myIndex = objectStore.index(index); + myIndex.openCursor().onerror = function(event) { console.error("Error fetching data"); reject(event); }; - objectStore.openCursor().onsuccess = function(event) { + myIndex.openCursor().onsuccess = function(event) { let cursor = event.target.result; if (cursor) { if (cursor.value[index] == indexValue) { @@ -27119,109 +27236,158 @@ return new Promise((resolve, reject) => { let response = []; var objectStore = db.transaction(tablename).objectStore(tablename); - objectStore.openCursor().onsuccess = function(event) { - let cursor = event.target.result; - if (cursor) { - if (filter_deletables == true) { - if (typeof cursor.value.is_deletable == "undefined") { - response.push(cursor.value); + + if ('getAll' in objectStore) { + // IDBObjectStore.getAll() will return the full set of items in our store. + objectStore.getAll().onsuccess = function(event) { + resolve(event.target.result); + }; + } else { + objectStore.openCursor().onsuccess = function(event) { + let cursor = event.target.result; + if (cursor) { + if (filter_deletables == true) { + if (typeof cursor.value.is_deletable == "undefined") { + response.push(cursor.value); + } + } else { + response.push(cursor.value); } - } else { - response.push(cursor.value); - } - cursor.continue(); - } else { - resolve(response); - } - }; + cursor.continue(); + } else { + resolve(response); + } + }; + } + }); } - async function addDB(tablename, dbObject) { - try { - if (typeof dbObject.vectorClock == "undefined") - dbObject.vectorClock = 0; - if (typeof dbObject.timestamp == "undefined") - dbObject.timestamp = +new Date(); - let request = db.transaction([tablename], "readwrite"); - let store = request.objectStore(tablename); - await store.add(dbObject); - await request.complete; - console.info("Data added in " + tablename); - return dbObject; - } catch (error) { - return new Error(error); - } + function addDB(tablename, dbObject) { + return new Promise((resolve, reject) => { + try { + if (typeof dbObject.vectorClock == "undefined") + dbObject.vectorClock = 0; + if (typeof dbObject.timestamp == "undefined") + dbObject.timestamp = +new Date(); + let request = db.transaction([tablename], "readwrite") + .objectStore(tablename) + .add(dbObject); + + request.onsuccess = function (event) { + console.trace("Data added in " + tablename); + resolve(dbObject); + }; + + request.onerror = function (event) { + reject(event); + } + + } catch (error) { + reject(error); + return new Error(error); + } + }); + + } - async function updateinDB( + function updateinDB( tablename, Obj, key, updateByVectorClock = false, increaseVectorClock = true ) { - // updateByVectorClock==true will not return Obj back. - // Return value will be undefined - try { - if (typeof Obj.vectorClock == "undefined") { - Obj.vectorClock = 0; - } else if (increaseVectorClock === false) { - // leave the vector clock field unchanged - } else { - Obj.vectorClock += 1; - } - if (typeof Obj.timestamp !== "number") { - Obj.timestamp = +new Date(); - } - var request = db.transaction([tablename], "readwrite"); - let store = request.objectStore(tablename); - if (updateByVectorClock === true) { - if (typeof key == "undefined") { - key = Obj[store.keyPath]; + return new Promise((resolve, reject) => { + try { + if (typeof Obj.vectorClock == "undefined") { + Obj.vectorClock = 0; + } else if (increaseVectorClock === false) { + // leave the vector clock field unchanged + } else { + Obj.vectorClock += 1; + } + if (typeof Obj.timestamp !== "number") { + Obj.timestamp = +new Date(); + } + var request = db.transaction([tablename], "readwrite") + .objectStore(tablename); + if (updateByVectorClock === true) { + if (typeof key == "undefined") { + key = Obj[request.keyPath]; + } + let objectStoreRequest = request.get(key); + objectStoreRequest.onsuccess = function (event) { + var myRecord = objectStoreRequest.result; + if (typeof myRecord !== "object") { + Obj.vectorClock = + typeof Obj.vectorClock == "number" ? Obj.vectorClock : 0; + request = db.transaction([tablename], "readwrite") + .objectStore(tablename).put(Obj); + } else if (myRecord.vectorClock < Obj.vectorClock) { + request = db.transaction([tablename], "readwrite") + .objectStore(tablename).put(Obj); + } else { + resolve(Obj); + } + + request.onsuccess = function() { + resolve(Obj); + } + + request.onerror = function(e) { + reject(e); + } + }; + } else { + request = db.transaction([tablename], "readwrite") + .objectStore(tablename).put(Obj); + } + + request.onsuccess = function() { + resolve(Obj); + } + + request.onerror = function(e) { + reject(e); + } + } catch (error) { + reject(error); + return new Error(error); } - let objectStoreRequest = store.get(key); - objectStoreRequest.onsuccess = async function(event) { - var myRecord = objectStoreRequest.result; - if (typeof myRecord !== "object") { - Obj.vectorClock = - typeof Obj.vectorClock == "number" ? Obj.vectorClock : 0; - await store.put(Obj); - await request.complete; - } else if (myRecord.vectorClock < Obj.vectorClock) { - await store.put(Obj); - await request.complete; - } - }; - } else { - await store.put(Obj); - await request.complete; - } - return Obj; - } catch (error) { - return new Error(error); - } + }); } - async function removeinDB(tablename, id) { - try { - var request = db.transaction([tablename], "readwrite"); - let store = request.objectStore(tablename); - await store.delete(id); - await request.complete; - return id; - } catch (error) { - return new Error(error); - } + function removeinDB(tablename, id) { + return new Promise((resolve, reject) => { + try { + var request = db.transaction([tablename], "readwrite") + .objectStore(tablename) + .delete(id); + + request.onsuccess = function(event) { + resolve(id); + } + + request.onerror = function(event) { + reject(event); + } + + } catch (error) { + reject(error); + return new Error(error); + } + }); } function removeByIndex(tablename, indexName, indexValue) { return new Promise((resolve, reject) => { - var request = db + var db_request = db .transaction([tablename], "readwrite") .objectStore(tablename); - var index = request.index(indexName); + var index = db_request.index(indexName); var request = index.openCursor(IDBKeyRange.only(indexValue)); request.onsuccess = function() { var cursor = request.result; @@ -27238,20 +27404,27 @@ }); } - async function removeAllinDB(tablename) { - try { - var request = db.transaction([tablename], "readwrite"); - var objectStore = request.objectStore(tablename); - var objectStoreRequest = await objectStore.clear(); - await request.complete; - console.info( - "All the data entry has been removed from your database " + - tablename - ); - return tablename; - } catch (error) { - return new Error(error); - } + function removeAllinDB(tablename) { + return new Promise((resolve, reject) => { + try { + var request = db.transaction([tablename], "readwrite"); + var objectStore = request.objectStore(tablename); + var objectStoreRequest = objectStore.clear(); + objectStoreRequest.onsuccess = function(event) { + console.info( + "All the data entry has been removed from your database " + + tablename + ); + resolve(tablename); + }; + objectStoreRequest.onerror = function(event) { + reject(event); + } + } catch (error) { + reject(event); + return new Error(error); + } + }); } @@ -27587,7 +27760,7 @@ let parent_request = this.request; this.request.onerror = function(event) { - reject("Unable to retrieve data from database!"); + reject(event); }; this.request.onsuccess = function(event) { @@ -27620,11 +27793,12 @@ this.transaction = this.db.transaction([tablename]); var objectStore = this.transaction.objectStore(tablename); let response = []; - objectStore.openCursor().onerror = function(event) { + var myIndex = objectStore.index(index); + myIndex.openCursor().onerror = function(event) { console.error("Error fetching data"); reject(event); }; - objectStore.openCursor().onsuccess = function(event) { + myIndex.openCursor().onsuccess = function(event) { let cursor = event.target.result; if (cursor) { if (cursor.value[index] == indexValue) { @@ -27650,6 +27824,7 @@ var objectStore = this.db .transaction(tablename) .objectStore(tablename); + objectStore.openCursor().onsuccess = function(event) { let cursor = event.target.result; if (cursor) { @@ -27665,123 +27840,165 @@ } else { resolve(response); } - }; + }; }); }, - async backup_addDB(tablename, dbObject) { - try { - if (typeof dbObject.vectorClock == "undefined") - dbObject.vectorClock = 0; - if (typeof dbObject.timestamp == "undefined") - dbObject.timestamp = +new Date(); - this.request = this.db.transaction([tablename], "readwrite"); - let store = this.request.objectStore(tablename); - await store.add(dbObject); - await this.request.complete; - console.info("Data added in " + tablename); - return dbObject; - } catch (error) { - return new Error(error); - } + backup_addDB(tablename, dbObject) { + return new Promise((resolve, reject) => { + try { + + if (typeof dbObject.vectorClock == "undefined") + dbObject.vectorClock = 0; + + if (typeof dbObject.timestamp == "undefined") + dbObject.timestamp = +new Date(); + + this.request = this.db.transaction([tablename], "readwrite") + .objectStore(tablename) + .add(dbObject); + + this.request.onsuccess = function (event) { + console.trace("Data added in " + tablename); + resolve(dbObject); + }; + + this.request.onerror = function (event) { + reject(event); + } + } catch (error) { + reject(error); + return new Error(error); + } + }); }, - async backup_updateinDB( + backup_updateinDB( tablename, Obj, key, updateByVectorClock = false, increaseVectorClock = true ) { - try { - if (typeof Obj.vectorClock == "undefined") { - Obj.vectorClock = 0; - } else if (increaseVectorClock === false) { - // leave the vector clock field unchanged - } else { - Obj.vectorClock += 1; - } - if (typeof Obj.timestamp !== "number") { - Obj.timestamp = +new Date(); - } - let that = this; - this.request = this.db.transaction([tablename], "readwrite"); - let store = this.request.objectStore(tablename); + return new Promise((resolve, reject) => { + try { + if (typeof Obj.vectorClock == "undefined") { + Obj.vectorClock = 0; + } else if (increaseVectorClock === false) { + // leave the vector clock field unchanged + } else { + Obj.vectorClock += 1; + } + if (typeof Obj.timestamp !== "number") { + Obj.timestamp = +new Date(); + } + this.request = this.db.transaction([tablename], "readwrite") + .objectStore(tablename); - if (updateByVectorClock === true) { - if (typeof key == "undefined") { - key = Obj[store.keyPath]; - } - let objectStoreRequest = store.get(key); - objectStoreRequest.onsuccess = function(event) { - return new Promise(async (resolve, reject) => { - var myRecord = objectStoreRequest.result; - var myRecord = objectStoreRequest.result; - if (typeof myRecord !== "object") { - Obj.vectorClock = - typeof Obj.vectorClock == "number" ? Obj.vectorClock : 0; - await store.put(Obj); - await that.request.complete; - } else if (myRecord.vectorClock < Obj.vectorClock) { - await store.put(Obj); - await that.request.complete; - } - }); - resolve(Obj); - return; - }; - } else { - await store.put(Obj); - await that.request.complete; - return Obj; + if (updateByVectorClock === true) { + if (typeof key == "undefined") { + key = Obj[this.request.keyPath]; + } + let objectStoreRequest = this.request.get(key); + objectStoreRequest.onsuccess = function(event) { + var myRecord = objectStoreRequest.result; + if (typeof myRecord !== "object") { + Obj.vectorClock = + typeof Obj.vectorClock == "number" ? Obj.vectorClock : 0; + this.request = this.db.transaction([tablename], "readwrite") + .objectStore(tablename).put(Obj); + } else if (myRecord.vectorClock < Obj.vectorClock) { + this.request = this.db.transaction([tablename], "readwrite") + .objectStore(tablename).put(Obj); + } else { + resolve(Obj); + } + this.request.onsuccess = function() { + resolve(Obj); + } + + this.request.onerror = function(e) { + reject(e); + } + }.bind(this); + } else { + this.request = this.db.transaction([tablename], "readwrite") + .objectStore(tablename).put(Obj); + } + + this.request.onsuccess = function() { + resolve(Obj); + } + + this.request.onerror = function(e) { + reject(e); + } + } catch (error) { + reject(error); + return new Error(error); } - } catch (error) { - return new Error(error); - } + }); }, - async backup_removeinDB(tablename, id) { - try { - this.request = this.db.transaction([tablename], "readwrite"); + backup_removeinDB(tablename, id, remove_deletables=false) { + return new Promise((resolve, reject) => { + try { + this.request = this.db.transaction([tablename], "readwrite"); - let store = this.request.objectStore(tablename); - let objectStoreRequest = store.get(id); - let that = this; - objectStoreRequest.onsuccess = function(event) { - return new Promise(async (resolve, reject) => { - var myRecord = objectStoreRequest.result; + if (remove_deletables===true) { + this.objectStore = this.request.objectStore(tablename); - if (typeof myRecord == "object") { - myRecord.vectorClock += 1; + this.objectStoreRequest = this.objectStore.delete(id); - // https://stackoverflow.com/a/39333479/5348972 - const modifiedRecord = (({ id, timestamp, vectorClock }) => ({ - id, - timestamp, - vectorClock - }))(myRecord); + this.objectStoreRequest.onsuccess = function(event) { + resolve(id); + } + + this.objectStoreRequest.onerror = function(event) { + reject(event); + } + } else { + let objectStoreRequest = this.request.objectStore(tablename).get(id); + objectStoreRequest.onsuccess = function(event) { + var myRecord = objectStoreRequest.result; - modifiedRecord.is_deletable = true; + if (typeof myRecord == "object") { + myRecord.vectorClock += 1; - await store.put(modifiedRecord); - await that.request.complete; - return id; + // https://stackoverflow.com/a/39333479/5348972 + const modifiedRecord = (({ id, timestamp, vectorClock }) => ({ + id, + timestamp, + vectorClock + }))(myRecord); + + modifiedRecord.is_deletable = true; + + this.request.objectStore(tablename).put(modifiedRecord); + return resolve(id); + } + reject(false); + }.bind(this); + + objectStoreRequest.onerror = function(event) { + reject(event); + } } - }); - reject(false); - }; - } catch (error) { - return new Error(error); - } + + } catch (error) { + reject(error); + return new Error(error); + } + }); }, backup_removeByIndex(tablename, indexName, indexValue) { return new Promise((resolve, reject) => { - this.request = this.db + this.db_request = this.db .transaction([tablename], "readwrite") .objectStore(tablename); - var index = this.request.index(indexName); - let parent_request = this.request; + var index = this.db_request.index(indexName); + let parent_request = this.db_request; this.request = index.openCursor(IDBKeyRange.only(indexValue)); this.request.onsuccess = async function(event) { var cursor = event.target.result; @@ -27798,19 +28015,42 @@ modifiedRecord.is_deletable = true; - await parent_request.put(modifiedRecord); - await parent_request.complete; + parent_request.put(modifiedRecord); cursor.continue(); } else { resolve(true); } }; - request.onerror = function(e) { + this.request.onerror = function(e) { reject(e); }; }); } }; + + function backup_removeAllinDB(tablename="") { + return new Promise((resolve, reject) => { + try { + this.request = this.db.transaction([tablename], "readwrite"); + var objectStore = this.request.objectStore(tablename); + + var objectStoreRequest = objectStore.clear(); + objectStoreRequest.onsuccess = function(event) { + console.info( + "All the data entry has been removed from backup database " + + tablename + ); + resolve(tablename); + }; + objectStoreRequest.onerror = function(event) { + reject(event); + } + } catch (error) { + reject(event); + return new Error(error); + } + }); + }