Merge branch 'sairajzero:master' into master
This commit is contained in:
commit
f7fcaf12c6
@ -33,7 +33,20 @@
|
|||||||
lastVC: {}
|
lastVC: {}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
<script id="onLoadStartUp">
|
||||||
|
function onLoadStartUp() {
|
||||||
|
|
||||||
|
//floDapps.addStartUpFunction('Sample', Promised Function)
|
||||||
|
//floDapps.setAppObjectStores({sampleObs1:{}, sampleObs2:{options{autoIncrement:true, keyPath:'SampleKey'}, Indexes:{sampleIndex:{}}}})
|
||||||
|
//floDapps.setCustomPrivKeyInput( () => { FUNCTION BODY *must resolve private key* } )
|
||||||
|
|
||||||
|
floDapps.launchStartUp().then(result => {
|
||||||
|
console.log(result)
|
||||||
|
alert(`Welcome FLO_ID: ${myFloID}`)
|
||||||
|
//App functions....
|
||||||
|
}).catch(error => console.error(error))
|
||||||
|
}
|
||||||
|
</script>
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body onload="onLoadStartUp()">
|
<body onload="onLoadStartUp()">
|
||||||
@ -6942,7 +6955,7 @@ Bitcoin.Util = {
|
|||||||
})();
|
})();
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<script id="floCrypto" version="2.0.0">
|
<script id="floCrypto" version="2.0.1">
|
||||||
/* FLO Crypto Operators*/
|
/* FLO Crypto Operators*/
|
||||||
const floCrypto = {
|
const floCrypto = {
|
||||||
|
|
||||||
@ -6951,6 +6964,8 @@ Bitcoin.Util = {
|
|||||||
|
|
||||||
ecparams: EllipticCurve.getSECCurveByName("secp256k1"),
|
ecparams: EllipticCurve.getSECCurveByName("secp256k1"),
|
||||||
|
|
||||||
|
asciiAlternatives: `‘ '\n’ '\n“ "\n” "\n– --\n— ---\n≥ >=\n≤ <=\n≠ !=\n× *\n÷ /\n← <-\n→ ->\n↔ <->\n⇒ =>\n⇐ <=\n⇔ <=>`,
|
||||||
|
|
||||||
exponent1: function() {
|
exponent1: function() {
|
||||||
return this.p.add(BigInteger.ONE).divide(BigInteger("4"))
|
return this.p.add(BigInteger.ONE).divide(BigInteger("4"))
|
||||||
},
|
},
|
||||||
@ -6976,9 +6991,8 @@ Bitcoin.Util = {
|
|||||||
// verify y value
|
// verify y value
|
||||||
let resultBigInt = y.mod(BigInteger("2"));
|
let resultBigInt = y.mod(BigInteger("2"));
|
||||||
let check = resultBigInt.toString() % 2;
|
let check = resultBigInt.toString() % 2;
|
||||||
if (prefix_modulus !== check) {
|
if (prefix_modulus !== check)
|
||||||
yDecimalValue = y.negate().mod(p).toString();
|
yDecimalValue = y.negate().mod(p).toString();
|
||||||
}
|
|
||||||
return {
|
return {
|
||||||
x: xDecimalValue,
|
x: xDecimalValue,
|
||||||
y: yDecimalValue
|
y: yDecimalValue
|
||||||
@ -6995,20 +7009,15 @@ Bitcoin.Util = {
|
|||||||
},
|
},
|
||||||
|
|
||||||
deriveSharedKeySender: function(receiverCompressedPublicKey, senderPrivateKey) {
|
deriveSharedKeySender: function(receiverCompressedPublicKey, senderPrivateKey) {
|
||||||
try {
|
|
||||||
let receiverPublicKeyString = this.getUncompressedPublicKey(receiverCompressedPublicKey);
|
let receiverPublicKeyString = this.getUncompressedPublicKey(receiverCompressedPublicKey);
|
||||||
var senderDerivedKey = ellipticCurveEncryption.senderSharedKeyDerivation(
|
var senderDerivedKey = ellipticCurveEncryption.senderSharedKeyDerivation(
|
||||||
receiverPublicKeyString.x, receiverPublicKeyString.y, senderPrivateKey);
|
receiverPublicKeyString.x, receiverPublicKeyString.y, senderPrivateKey);
|
||||||
return senderDerivedKey;
|
return senderDerivedKey;
|
||||||
} catch (error) {
|
|
||||||
return new Error(error);
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
|
|
||||||
deriveReceiverSharedKey: function(senderPublicKeyString, receiverPrivateKey) {
|
deriveReceiverSharedKey: function(senderPublicKeyString, receiverPrivateKey) {
|
||||||
return ellipticCurveEncryption.receiverSharedKeyDerivation(
|
return ellipticCurveEncryption.receiverSharedKeyDerivation(
|
||||||
senderPublicKeyString.XValuePublicString, senderPublicKeyString.YValuePublicString,
|
senderPublicKeyString.XValuePublicString, senderPublicKeyString.YValuePublicString, receiverPrivateKey);
|
||||||
receiverPrivateKey);
|
|
||||||
},
|
},
|
||||||
|
|
||||||
getReceiverPublicKeyString: function(privateKey) {
|
getReceiverPublicKeyString: function(privateKey) {
|
||||||
@ -7016,14 +7025,8 @@ Bitcoin.Util = {
|
|||||||
},
|
},
|
||||||
|
|
||||||
deriveSharedKeyReceiver: function(senderPublicKeyString, receiverPrivateKey) {
|
deriveSharedKeyReceiver: function(senderPublicKeyString, receiverPrivateKey) {
|
||||||
try {
|
return ellipticCurveEncryption.receiverSharedKeyDerivation(
|
||||||
return ellipticCurveEncryption.receiverSharedKeyDerivation(senderPublicKeyString
|
senderPublicKeyString.XValuePublicString, senderPublicKeyString.YValuePublicString, receiverPrivateKey);
|
||||||
.XValuePublicString,
|
|
||||||
senderPublicKeyString.YValuePublicString, receiverPrivateKey);
|
|
||||||
|
|
||||||
} catch (error) {
|
|
||||||
return new Error(error);
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
|
|
||||||
wifToDecimal: function(pk_wif, isPubKeyCompressed = false) {
|
wifToDecimal: function(pk_wif, isPubKeyCompressed = false) {
|
||||||
@ -7228,10 +7231,68 @@ Bitcoin.Util = {
|
|||||||
} catch {
|
} catch {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
validateASCII: function(string, bool = true) {
|
||||||
|
if (typeof string !== "string")
|
||||||
|
return null;
|
||||||
|
if (bool) {
|
||||||
|
let x;
|
||||||
|
for (let i = 0; i < string.length; i++) {
|
||||||
|
x = string.charCodeAt(i);
|
||||||
|
if (x < 32 || x > 127)
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
let x, invalids = {};
|
||||||
|
for (let i = 0; i < string.length; i++) {
|
||||||
|
x = string.charCodeAt(i);
|
||||||
|
if (x < 32 || x > 127)
|
||||||
|
if (x in invalids)
|
||||||
|
invalids[string[i]].push(i)
|
||||||
|
else
|
||||||
|
invalids[string[i]] = [i];
|
||||||
|
}
|
||||||
|
if (Object.keys(invalids).length)
|
||||||
|
return invalids;
|
||||||
|
else
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
convertToASCII: function(string, mode = 'soft-remove') {
|
||||||
|
let chars = this.validateASCII(string, false);
|
||||||
|
if (chars === true)
|
||||||
|
return string;
|
||||||
|
else if (chars === null)
|
||||||
|
return null;
|
||||||
|
let convertor, result = string,
|
||||||
|
refAlt = {};
|
||||||
|
this.util.asciiAlternatives.split('\n').forEach(a => refAlt[a[0]] = a.slice(2));
|
||||||
|
mode = mode.toLowerCase();
|
||||||
|
if (mode === "hard-unicode")
|
||||||
|
convertor = (c) => `\\u${('000'+c.charCodeAt().toString(16)).slice(-4)}`;
|
||||||
|
else if (mode === "soft-unicode")
|
||||||
|
convertor = (c) => refAlt[c] || `\\u${('000'+c.charCodeAt().toString(16)).slice(-4)}`;
|
||||||
|
else if (mode === "hard-remove")
|
||||||
|
convertor = c => "";
|
||||||
|
else if (mode === "soft-remove")
|
||||||
|
convertor = c => refAlt[c] || "";
|
||||||
|
else
|
||||||
|
return null;
|
||||||
|
for (let c in chars)
|
||||||
|
result = result.replaceAll(c, convertor(c));
|
||||||
|
return result;
|
||||||
|
},
|
||||||
|
|
||||||
|
revertUnicode: function(string) {
|
||||||
|
return string.replace(/\\u[\dA-F]{4}/gi,
|
||||||
|
m => String.fromCharCode(parseInt(m.replace(/\\u/g, ''), 16)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
<script id="floBlockchainAPI" version="2.0.1">
|
<script id="floBlockchainAPI" version="2.0.1c">
|
||||||
/* FLO Blockchain Operator to send/receive data from blockchain using API calls*/
|
/* FLO Blockchain Operator to send/receive data from blockchain using API calls*/
|
||||||
const floBlockchainAPI = {
|
const floBlockchainAPI = {
|
||||||
|
|
||||||
@ -7241,7 +7302,7 @@ Bitcoin.Util = {
|
|||||||
fetch_retry: function(apicall) {
|
fetch_retry: function(apicall) {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
this.serverList.splice(this.curPos, 1);
|
this.serverList.splice(this.curPos, 1);
|
||||||
this.curPos = floCrypto.randInt(0, this.serverList.length)
|
this.curPos = floCrypto.randInt(0, this.serverList.length - 1)
|
||||||
this.fetch_api(apicall)
|
this.fetch_api(apicall)
|
||||||
.then(result => resolve(result))
|
.then(result => resolve(result))
|
||||||
.catch(error => reject(error));
|
.catch(error => reject(error));
|
||||||
@ -7303,6 +7364,8 @@ Bitcoin.Util = {
|
|||||||
//Send Tx to blockchain
|
//Send Tx to blockchain
|
||||||
sendTx: function(senderAddr, receiverAddr, sendAmt, privKey, floData = '') {
|
sendTx: function(senderAddr, receiverAddr, sendAmt, privKey, floData = '') {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
|
if (!floCrypto.validateASCII(floData))
|
||||||
|
return reject("Invalid FLO_Data: only printable ASCII characters are allowed");
|
||||||
if (!floCrypto.validateAddr(senderAddr))
|
if (!floCrypto.validateAddr(senderAddr))
|
||||||
reject(`Invalid address : ${senderAddr}`);
|
reject(`Invalid address : ${senderAddr}`);
|
||||||
else if (!floCrypto.validateAddr(receiverAddr))
|
else if (!floCrypto.validateAddr(receiverAddr))
|
||||||
@ -7349,6 +7412,8 @@ Bitcoin.Util = {
|
|||||||
return reject(`Invalid floID`);
|
return reject(`Invalid floID`);
|
||||||
if (!floCrypto.verifyPrivKey(privKey, floID))
|
if (!floCrypto.verifyPrivKey(privKey, floID))
|
||||||
return reject("Invalid Private Key")
|
return reject("Invalid Private Key")
|
||||||
|
if (!floCrypto.validateASCII(floData))
|
||||||
|
return reject("Invalid FLO_Data: only printable ASCII characters are allowed");
|
||||||
|
|
||||||
var trx = bitjs.transaction();
|
var trx = bitjs.transaction();
|
||||||
var utxoAmt = 0.0;
|
var utxoAmt = 0.0;
|
||||||
@ -7412,7 +7477,8 @@ Bitcoin.Util = {
|
|||||||
*/
|
*/
|
||||||
sendTxMultiple: function(senderPrivKeys, receivers, floData = '') {
|
sendTxMultiple: function(senderPrivKeys, receivers, floData = '') {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
|
if (!floCrypto.validateASCII(floData))
|
||||||
|
return reject("Invalid FLO_Data: only printable ASCII characters are allowed");
|
||||||
let senders = {},
|
let senders = {},
|
||||||
preserveRatio;
|
preserveRatio;
|
||||||
//check for argument validations
|
//check for argument validations
|
||||||
@ -7625,13 +7691,18 @@ Bitcoin.Util = {
|
|||||||
limit : maximum number of filtered data (default = 1000, negative = no limit)
|
limit : maximum number of filtered data (default = 1000, negative = no limit)
|
||||||
ignoreOld : ignore old txs (default = 0)
|
ignoreOld : ignore old txs (default = 0)
|
||||||
sentOnly : filters only sent data
|
sentOnly : filters only sent data
|
||||||
pattern : filters data that starts with a pattern
|
receivedOnly: filters only received data
|
||||||
contains : filters data that contains a string
|
pattern : filters data that with JSON pattern
|
||||||
filter : custom filter funtion for floData (eg . filter: d => {return d[0] == '$'})
|
filter : custom filter funtion for floData (eg . filter: d => {return d[0] == '$'})
|
||||||
|
txid : (boolean) resolve txid or not
|
||||||
|
sender : flo-id(s) of sender
|
||||||
|
receiver : flo-id(s) of receiver
|
||||||
*/
|
*/
|
||||||
readData: function(addr, options = {}) {
|
readData: function(addr, options = {}) {
|
||||||
options.limit = options.limit | 0
|
options.limit = options.limit || 0
|
||||||
options.ignoreOld = options.ignoreOld | 0
|
options.ignoreOld = options.ignoreOld || 0
|
||||||
|
if (typeof options.sender === "string") options.sender = [options.sender];
|
||||||
|
if (typeof options.receiver === "string") options.receiver = [options.receiver];
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
this.promisedAPI(`api/addrs/${addr}/txs?from=0&to=1`).then(response => {
|
this.promisedAPI(`api/addrs/${addr}/txs?from=0&to=1`).then(response => {
|
||||||
var newItems = response.totalItems - options.ignoreOld;
|
var newItems = response.totalItems - options.ignoreOld;
|
||||||
@ -7642,24 +7713,54 @@ Bitcoin.Util = {
|
|||||||
var filteredData = [];
|
var filteredData = [];
|
||||||
for (i = 0; i < (response.totalItems - options.ignoreOld) &&
|
for (i = 0; i < (response.totalItems - options.ignoreOld) &&
|
||||||
filteredData.length < options.limit; i++) {
|
filteredData.length < options.limit; i++) {
|
||||||
if (options.sentOnly && response.items[i].vin[0].addr !==
|
|
||||||
addr)
|
|
||||||
continue;
|
|
||||||
if (options.pattern) {
|
if (options.pattern) {
|
||||||
try {
|
try {
|
||||||
let jsonContent = JSON.parse(response.items[i]
|
let jsonContent = JSON.parse(response.items[i].floData)
|
||||||
.floData)
|
if (!Object.keys(jsonContent).includes(options.pattern))
|
||||||
if (!Object.keys(jsonContent).includes(options
|
|
||||||
.pattern))
|
|
||||||
continue;
|
continue;
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (options.filter && !options.filter(response.items[i]
|
if (options.sentOnly) {
|
||||||
.floData))
|
let flag = false;
|
||||||
|
for (let vin of response.items[i].vin)
|
||||||
|
if (vin.addr === addr) {
|
||||||
|
flag = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (!flag) continue;
|
||||||
|
}
|
||||||
|
if (Array.isArray(options.sender)) {
|
||||||
|
let flag = false;
|
||||||
|
for (let vin of response.items[i].vin)
|
||||||
|
if (options.sender.includes(vin.addr)) {
|
||||||
|
flag = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (!flag) continue;
|
||||||
|
}
|
||||||
|
if (options.receivedOnly) {
|
||||||
|
let flag = false;
|
||||||
|
for (let vout of response.items[i].vout)
|
||||||
|
if (vout.scriptPubKey.addresses[0] === addr) {
|
||||||
|
flag = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (!flag) continue;
|
||||||
|
}
|
||||||
|
if (Array.isArray(options.receiver)) {
|
||||||
|
let flag = false;
|
||||||
|
for (let vout of response.items[i].vout)
|
||||||
|
if (options.receiver.includes(vout.scriptPubKey.addresses[0])) {
|
||||||
|
flag = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (!flag) continue;
|
||||||
|
}
|
||||||
|
if (options.filter && !options.filter(response.items[i].floData))
|
||||||
continue;
|
continue;
|
||||||
filteredData.push(response.items[i].floData);
|
filteredData.push(options.txid ? [response.items[i].txid, response.items[i].floData] : response.items[i].floData);
|
||||||
}
|
}
|
||||||
resolve({
|
resolve({
|
||||||
totalTxs: response.totalItems,
|
totalTxs: response.totalItems,
|
||||||
@ -7876,43 +7977,59 @@ Bitcoin.Util = {
|
|||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
|
/*searchData: function (obsName, options = {}, dbName = this.defaultDB) {
|
||||||
|
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
this.openDB(dbName).then(db => {
|
||||||
|
var obs = db.transaction(obsName, "readonly").objectStore(obsName);
|
||||||
|
var filteredResult = {}
|
||||||
|
let keyRange;
|
||||||
|
if(options.lowerKey!==null && options.upperKey!==null)
|
||||||
|
keyRange = IDBKeyRange.bound(options.lowerKey, options.upperKey);
|
||||||
|
else if(options.lowerKey!==null)
|
||||||
|
keyRange = IDBKeyRange.lowerBound(options.lowerKey);
|
||||||
|
else if (options.upperKey!==null)
|
||||||
|
keyRange = IDBKeyRange.upperBound(options.upperBound);
|
||||||
|
else if (options.atKey)
|
||||||
|
let curReq = obs.openCursor(keyRange, )
|
||||||
|
}).catch(error => reject(error))
|
||||||
|
})
|
||||||
|
},*/
|
||||||
|
|
||||||
searchData: function (obsName, options = {}, dbName = this.defaultDB) {
|
searchData: function (obsName, options = {}, dbName = this.defaultDB) {
|
||||||
options.lowerKey = options.atKey || options.lowerKey || 0
|
options.lowerKey = options.atKey || options.lowerKey || 0
|
||||||
options.upperKey = options.atKey || options.upperKey || false
|
options.upperKey = options.atKey || options.upperKey || false
|
||||||
options.patternEval = options.patternEval || ((k, v) => {
|
options.patternEval = options.patternEval || ((k, v) => {
|
||||||
return true
|
return true
|
||||||
})
|
})
|
||||||
|
options.limit = options.limit || false;
|
||||||
options.lastOnly = options.lastOnly || false
|
options.lastOnly = options.lastOnly || false
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
this.openDB(dbName).then(db => {
|
this.openDB(dbName).then(db => {
|
||||||
var obs = db.transaction(obsName, "readonly").objectStore(obsName);
|
var obs = db.transaction(obsName, "readonly").objectStore(obsName);
|
||||||
var filteredResult = {}
|
var filteredResult = {}
|
||||||
let curReq = obs.openCursor(
|
let curReq = obs.openCursor(
|
||||||
options.upperKey ? IDBKeyRange.bound(options.lowerKey, options
|
options.upperKey ? IDBKeyRange.bound(options.lowerKey, options.upperKey) : IDBKeyRange.lowerBound(options.lowerKey),
|
||||||
.upperKey) : IDBKeyRange.lowerBound(options.lowerKey),
|
|
||||||
options.lastOnly ? "prev" : "next");
|
options.lastOnly ? "prev" : "next");
|
||||||
curReq.onsuccess = (evt) => {
|
curReq.onsuccess = (evt) => {
|
||||||
var cursor = evt.target.result;
|
var cursor = evt.target.result;
|
||||||
if (cursor) {
|
if (cursor) {
|
||||||
if (options.patternEval(cursor.primaryKey, cursor.value)) {
|
if (options.patternEval(cursor.primaryKey, cursor.value)) {
|
||||||
filteredResult[cursor.primaryKey] = cursor.value;
|
filteredResult[cursor.primaryKey] = cursor.value;
|
||||||
options.lastOnly ? resolve(filteredResult) : cursor
|
options.lastOnly ? resolve(filteredResult) : cursor.continue();
|
||||||
.continue();
|
|
||||||
} else
|
} else
|
||||||
cursor.continue();
|
cursor.continue();
|
||||||
} else
|
} else
|
||||||
resolve(filteredResult);
|
resolve(filteredResult);
|
||||||
}
|
}
|
||||||
curReq.onerror = (evt) => reject(
|
curReq.onerror = (evt) => reject(`Search unsuccessful [${evt.target.error.name}] ${evt.target.error.message}`);
|
||||||
`Search unsuccessful [${evt.target.error.name}] ${evt.target.error.message}`
|
|
||||||
);
|
|
||||||
db.close();
|
db.close();
|
||||||
}).catch(error => reject(error));
|
}).catch(error => reject(error));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
<script id="floCloudAPI" version="2.0.2c">
|
<script id="floCloudAPI" version="2.0.2e">
|
||||||
/* FLO Cloud operations to send/request application data*/
|
/* FLO Cloud operations to send/request application data*/
|
||||||
const floCloudAPI = {
|
const floCloudAPI = {
|
||||||
|
|
||||||
@ -8056,13 +8173,13 @@ Bitcoin.Util = {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
inactive: [],
|
inactive: new Set(),
|
||||||
connect(snID) {
|
connect(snID) {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
if (!(snID in floGlobals.supernodes))
|
if (!(snID in floGlobals.supernodes))
|
||||||
return reject(`${snID} is not a supernode`)
|
return reject(`${snID} is not a supernode`)
|
||||||
let inactive = this.inactive
|
let inactive = this.inactive
|
||||||
if (inactive.includes(snID))
|
if (inactive.has(snID))
|
||||||
return reject(`${snID} is not active`)
|
return reject(`${snID} is not active`)
|
||||||
var wsConn = new WebSocket("wss://" + floGlobals.supernodes[snID].uri + "/ws");
|
var wsConn = new WebSocket("wss://" + floGlobals.supernodes[snID].uri + "/ws");
|
||||||
wsConn.onmessage = (evt) => {
|
wsConn.onmessage = (evt) => {
|
||||||
@ -8070,12 +8187,12 @@ Bitcoin.Util = {
|
|||||||
resolve(wsConn)
|
resolve(wsConn)
|
||||||
else if (evt.data == '$-') {
|
else if (evt.data == '$-') {
|
||||||
wsConn.close();
|
wsConn.close();
|
||||||
inactive.push(snID)
|
inactive.add(snID)
|
||||||
reject(`${snID} is not active`)
|
reject(`${snID} is not active`)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
wsConn.onerror = evt => {
|
wsConn.onerror = evt => {
|
||||||
inactive.push(snID)
|
inactive.add(snID)
|
||||||
reject(`${snID} is unavailable`)
|
reject(`${snID} is unavailable`)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
@ -8083,7 +8200,7 @@ Bitcoin.Util = {
|
|||||||
|
|
||||||
connectActive(snID, reverse = false) {
|
connectActive(snID, reverse = false) {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
if (this.inactive.length === this.kBucket.SNCO.length)
|
if (this.inactive.size === this.kBucket.SNCO.length)
|
||||||
return reject('Cloud offline')
|
return reject('Cloud offline')
|
||||||
if (!(snID in floGlobals.supernodes))
|
if (!(snID in floGlobals.supernodes))
|
||||||
snID = this.kBucket.closestNode(snID);
|
snID = this.kBucket.closestNode(snID);
|
||||||
@ -8455,7 +8572,7 @@ Bitcoin.Util = {
|
|||||||
}
|
}
|
||||||
delete options.callback;
|
delete options.callback;
|
||||||
}
|
}
|
||||||
this.requestApplicationData(objectName, options).then(data).then(dataSet => {
|
this.requestApplicationData(objectName, options).then(dataSet => {
|
||||||
this.util.updateObject(dataSet)
|
this.util.updateObject(dataSet)
|
||||||
delete options.comment;
|
delete options.comment;
|
||||||
options.lowerVectorClock = floGlobals.lastVC[objectName] + 1
|
options.lowerVectorClock = floGlobals.lastVC[objectName] + 1
|
||||||
@ -8477,6 +8594,19 @@ Bitcoin.Util = {
|
|||||||
})
|
})
|
||||||
},
|
},
|
||||||
|
|
||||||
|
closeRequest: function(requestID) {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
let conn = this.util.liveRequest[requestID]
|
||||||
|
if (!conn)
|
||||||
|
return reject('Request not found')
|
||||||
|
conn.onclose = evt => {
|
||||||
|
delete this.util.liveRequest[requestID]
|
||||||
|
resolve('Request connection closed')
|
||||||
|
}
|
||||||
|
conn.close()
|
||||||
|
})
|
||||||
|
},
|
||||||
|
|
||||||
//reset or initialize an object and send it to cloud
|
//reset or initialize an object and send it to cloud
|
||||||
resetObjectData: function(objectName, options = {}) {
|
resetObjectData: function(objectName, options = {}) {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
@ -8687,7 +8817,7 @@ Bitcoin.Util = {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
<script id="floDapps" version="2.0.1a">
|
<script id="floDapps" version="2.0.1c">
|
||||||
/* General functions for FLO Dapps*/
|
/* General functions for FLO Dapps*/
|
||||||
const floDapps = {
|
const floDapps = {
|
||||||
|
|
||||||
@ -8762,32 +8892,25 @@ Bitcoin.Util = {
|
|||||||
|
|
||||||
readSupernodeListFromAPI: function() {
|
readSupernodeListFromAPI: function() {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
compactIDB.readData("lastTx", floGlobals.SNStorageID, "floDapps").then(
|
compactIDB.readData("lastTx", floGlobals.SNStorageID, "floDapps").then(lastTx => {
|
||||||
lastTx => {
|
|
||||||
floBlockchainAPI.readData(floGlobals.SNStorageID, {
|
floBlockchainAPI.readData(floGlobals.SNStorageID, {
|
||||||
ignoreOld: lastTx,
|
ignoreOld: lastTx,
|
||||||
sentOnly: true,
|
sentOnly: true,
|
||||||
pattern: "SuperNodeStorage"
|
pattern: "SuperNodeStorage"
|
||||||
}).then(result => {
|
}).then(result => {
|
||||||
for (var i = result.data.length - 1; i >= 0; i--) {
|
for (var i = result.data.length - 1; i >= 0; i--) {
|
||||||
var content = JSON.parse(result.data[i])
|
var content = JSON.parse(result.data[i]).SuperNodeStorage;
|
||||||
.SuperNodeStorage;
|
|
||||||
for (sn in content.removeNodes)
|
for (sn in content.removeNodes)
|
||||||
compactIDB.removeData("supernodes", sn,
|
compactIDB.removeData("supernodes", sn, "floDapps");
|
||||||
"floDapps");
|
|
||||||
for (sn in content.newNodes)
|
for (sn in content.newNodes)
|
||||||
compactIDB.writeData("supernodes", content
|
compactIDB.writeData("supernodes", content.newNodes[sn], sn, "floDapps");
|
||||||
.newNodes[sn], sn, "floDapps");
|
|
||||||
}
|
}
|
||||||
compactIDB.writeData("lastTx", result.totalTxs,
|
compactIDB.writeData("lastTx", result.totalTxs, floGlobals.SNStorageID, "floDapps");
|
||||||
floGlobals.SNStorageID, "floDapps");
|
compactIDB.readAllData("supernodes", "floDapps").then(result => {
|
||||||
compactIDB.readAllData("supernodes", "floDapps").then(
|
|
||||||
result => {
|
|
||||||
floGlobals.supernodes = result;
|
floGlobals.supernodes = result;
|
||||||
floCloudAPI.util.kBucket.launch()
|
floCloudAPI.util.kBucket.launch()
|
||||||
.then(result => resolve(
|
.then(result => resolve("Loaded Supernode list\n" + result))
|
||||||
"Loaded Supernode list\n" +
|
.catch(error => reject(error))
|
||||||
result))
|
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
}).catch(error => reject(error))
|
}).catch(error => reject(error))
|
||||||
@ -8796,42 +8919,32 @@ Bitcoin.Util = {
|
|||||||
|
|
||||||
readAppConfigFromAPI: function() {
|
readAppConfigFromAPI: function() {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
compactIDB.readData("lastTx", floGlobals.adminID, "floDapps").then(lastTx => {
|
compactIDB.readData("lastTx", `${floGlobals.application}|${floGlobals.adminID}`, "floDapps").then(lastTx => {
|
||||||
floBlockchainAPI.readData(floGlobals.adminID, {
|
floBlockchainAPI.readData(floGlobals.adminID, {
|
||||||
ignoreOld: lastTx,
|
ignoreOld: lastTx,
|
||||||
sentOnly: true,
|
sentOnly: true,
|
||||||
pattern: floGlobals.application
|
pattern: floGlobals.application
|
||||||
}).then(result => {
|
}).then(result => {
|
||||||
for (var i = result.data.length - 1; i >= 0; i--) {
|
for (var i = result.data.length - 1; i >= 0; i--) {
|
||||||
var content = JSON.parse(result.data[i])[floGlobals
|
var content = JSON.parse(result.data[i])[floGlobals.application];
|
||||||
.application];
|
|
||||||
if (!content || typeof content !== "object")
|
if (!content || typeof content !== "object")
|
||||||
continue;
|
continue;
|
||||||
if (Array.isArray(content.removeSubAdmin))
|
if (Array.isArray(content.removeSubAdmin))
|
||||||
for (var j = 0; j < content.removeSubAdmin
|
for (var j = 0; j < content.removeSubAdmin.length; j++)
|
||||||
.length; j++)
|
compactIDB.removeData("subAdmins", content.removeSubAdmin[j]);
|
||||||
compactIDB.removeData("subAdmins", content
|
|
||||||
.removeSubAdmin[j]);
|
|
||||||
if (Array.isArray(content.addSubAdmin))
|
if (Array.isArray(content.addSubAdmin))
|
||||||
for (var k = 0; k < content.addSubAdmin
|
for (var k = 0; k < content.addSubAdmin.length; k++)
|
||||||
.length; k++)
|
compactIDB.writeData("subAdmins", true, content.addSubAdmin[k]);
|
||||||
compactIDB.writeData("subAdmins", true,
|
|
||||||
content.addSubAdmin[k]);
|
|
||||||
if (content.settings)
|
if (content.settings)
|
||||||
for (let l in content.settings)
|
for (let l in content.settings)
|
||||||
compactIDB.writeData("settings", content
|
compactIDB.writeData("settings", content.settings[l], l)
|
||||||
.settings[l], l)
|
|
||||||
}
|
}
|
||||||
compactIDB.writeData("lastTx", result.totalTxs,
|
compactIDB.writeData("lastTx", result.totalTxs, `${floGlobals.application}|${floGlobals.adminID}`, "floDapps");
|
||||||
floGlobals.adminID, "floDapps");
|
|
||||||
compactIDB.readAllData("subAdmins").then(result => {
|
compactIDB.readAllData("subAdmins").then(result => {
|
||||||
floGlobals.subAdmins = Object.keys(result);
|
floGlobals.subAdmins = Object.keys(result);
|
||||||
compactIDB.readAllData("settings").then(
|
compactIDB.readAllData("settings").then(result => {
|
||||||
result => {
|
|
||||||
floGlobals.settings = result;
|
floGlobals.settings = result;
|
||||||
resolve(
|
resolve("Read app configuration from blockchain");
|
||||||
"Read app configuration from blockchain"
|
|
||||||
);
|
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
@ -8884,7 +8997,7 @@ Bitcoin.Util = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const writeSharesToIDB = function(shares, i = 0, resultIndexes = []) {
|
const writeSharesToIDB = function(shares, i = 0, resultIndexes = []) {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise(resolve => {
|
||||||
if (i >= shares.length)
|
if (i >= shares.length)
|
||||||
return resolve(resultIndexes)
|
return resolve(resultIndexes)
|
||||||
var n = floCrypto.randInt(0, 100000)
|
var n = floCrypto.randInt(0, 100000)
|
||||||
@ -8922,25 +9035,18 @@ Bitcoin.Util = {
|
|||||||
if (!privKey)
|
if (!privKey)
|
||||||
return;
|
return;
|
||||||
var threshold = floCrypto.randInt(10, 20)
|
var threshold = floCrypto.randInt(10, 20)
|
||||||
writeSharesToIDB(floCrypto.createShamirsSecretShares(
|
var shares = floCrypto.createShamirsSecretShares(privKey, threshold, threshold)
|
||||||
privKey, threshold, threshold)).then(
|
writeSharesToIDB(shares).then(resultIndexes => {
|
||||||
resultIndexes => {
|
|
||||||
//store index keys in localStorage
|
//store index keys in localStorage
|
||||||
localStorage.setItem(
|
localStorage.setItem(`${floGlobals.application}#privKey`, JSON.stringify(resultIndexes))
|
||||||
`${floGlobals.application}#privKey`,
|
|
||||||
JSON.stringify(resultIndexes))
|
|
||||||
//also add a dummy privatekey to the IDB
|
//also add a dummy privatekey to the IDB
|
||||||
var randomPrivKey = floCrypto
|
var randomPrivKey = floCrypto.generateNewID().privKey
|
||||||
.generateNewID().privKey
|
var randomThreshold = floCrypto.randInt(10, 20)
|
||||||
var randomThreshold = floCrypto.randInt(10,
|
var randomShares = floCrypto.createShamirsSecretShares(randomPrivKey, randomThreshold, randomThreshold)
|
||||||
20)
|
writeSharesToIDB(randomShares)
|
||||||
writeSharesToIDB(floCrypto
|
|
||||||
.createShamirsSecretShares(
|
|
||||||
randomPrivKey, randomThreshold,
|
|
||||||
randomThreshold))
|
|
||||||
//resolve private Key
|
//resolve private Key
|
||||||
resolve(privKey)
|
resolve(privKey)
|
||||||
}).catch(error => reject(error))
|
})
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
@ -8958,8 +9064,7 @@ Bitcoin.Util = {
|
|||||||
} catch (error) {
|
} catch (error) {
|
||||||
reject("Access Denied: Incorrect PIN/Password")
|
reject("Access Denied: Incorrect PIN/Password")
|
||||||
}
|
}
|
||||||
}).catch(error => reject(
|
}).catch(error => reject("Access Denied: PIN/Password required"))
|
||||||
"Access Denied: PIN/Password required"))
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@ -8992,15 +9097,11 @@ Bitcoin.Util = {
|
|||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
this.startUpFunctions[fname]().then(result => {
|
this.startUpFunctions[fname]().then(result => {
|
||||||
this.callStartUpFunction.completed += 1
|
this.callStartUpFunction.completed += 1
|
||||||
this.startUpLog(true,
|
this.startUpLog(true, `${result}\nCompleted ${this.callStartUpFunction.completed}/${this.callStartUpFunction.total} Startup functions`)
|
||||||
`${result}\nCompleted ${this.callStartUpFunction.completed}/${this.callStartUpFunction.total} Startup functions`
|
|
||||||
)
|
|
||||||
resolve(true)
|
resolve(true)
|
||||||
}).catch(error => {
|
}).catch(error => {
|
||||||
this.callStartUpFunction.failed += 1
|
this.callStartUpFunction.failed += 1
|
||||||
this.startUpLog(false,
|
this.startUpLog(false, `${error}\nFailed ${this.callStartUpFunction.failed}/${this.callStartUpFunction.total} Startup functions`)
|
||||||
`${error}\nFailed ${this.callStartUpFunction.failed}/${this.callStartUpFunction.total} Startup functions`
|
|
||||||
)
|
|
||||||
reject(false)
|
reject(false)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
@ -9011,8 +9112,7 @@ Bitcoin.Util = {
|
|||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
this.util.initIndexedDB().then(log => {
|
this.util.initIndexedDB().then(log => {
|
||||||
console.log(log)
|
console.log(log)
|
||||||
this.util.callStartUpFunction.total = Object.keys(this.util
|
this.util.callStartUpFunction.total = Object.keys(this.util.startUpFunctions).length
|
||||||
.startUpFunctions).length
|
|
||||||
this.util.callStartUpFunction.completed = 0
|
this.util.callStartUpFunction.completed = 0
|
||||||
this.util.callStartUpFunction.failed = 0
|
this.util.callStartUpFunction.failed = 0
|
||||||
var p0 = []
|
var p0 = []
|
||||||
@ -9152,8 +9252,7 @@ Bitcoin.Util = {
|
|||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
if (!Array.isArray(addList) || !addList.length) addList = undefined;
|
if (!Array.isArray(addList) || !addList.length) addList = undefined;
|
||||||
if (!Array.isArray(rmList) || !rmList.length) rmList = undefined;
|
if (!Array.isArray(rmList) || !rmList.length) rmList = undefined;
|
||||||
if (!settings || typeof settings !== "object" || !Object.keys(settings).length)
|
if (!settings || typeof settings !== "object" || !Object.keys(settings).length) settings = undefined;
|
||||||
settings = undefined;
|
|
||||||
if (!addList && !rmList && !settings)
|
if (!addList && !rmList && !settings)
|
||||||
return reject("No configuration change")
|
return reject("No configuration change")
|
||||||
var floData = {
|
var floData = {
|
||||||
@ -9200,8 +9299,10 @@ Bitcoin.Util = {
|
|||||||
compactIDB.deleteDB(floGlobals.application).then(result => {
|
compactIDB.deleteDB(floGlobals.application).then(result => {
|
||||||
localStorage.removeItem(`${floGlobals.application}#privKey`)
|
localStorage.removeItem(`${floGlobals.application}#privKey`)
|
||||||
myPrivKey = myPubKey = myFloID = undefined;
|
myPrivKey = myPubKey = myFloID = undefined;
|
||||||
resolve("App database(local) deleted")
|
compactIDB.removeData('lastTx', `${floGlobals.application}|${floGlobals.adminID}`, 'floDapps')
|
||||||
})
|
.then(result => resolve("App database(local) deleted"))
|
||||||
|
.catch(error => reject(error))
|
||||||
|
}).catch(error => reject(error))
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -9225,6 +9326,49 @@ Bitcoin.Util = {
|
|||||||
})
|
})
|
||||||
},
|
},
|
||||||
|
|
||||||
|
verifyPin: function(pin = null) {
|
||||||
|
const readSharesFromIDB = function(indexArr) {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
var promises = []
|
||||||
|
for (var i = 0; i < indexArr.length; i++)
|
||||||
|
promises.push(compactIDB.readData('credentials', indexArr[i]))
|
||||||
|
Promise.all(promises).then(shares => {
|
||||||
|
var secret = floCrypto.retrieveShamirSecret(shares)
|
||||||
|
console.info(shares, secret)
|
||||||
|
if (secret)
|
||||||
|
resolve(secret)
|
||||||
|
else
|
||||||
|
reject("Shares are insufficient or incorrect")
|
||||||
|
}).catch(error => reject(error))
|
||||||
|
})
|
||||||
|
}
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
var indexArr = localStorage.getItem(`${floGlobals.application}#privKey`)
|
||||||
|
console.info(indexArr)
|
||||||
|
if (!indexArr)
|
||||||
|
reject('No login credentials found')
|
||||||
|
readSharesFromIDB(JSON.parse(indexArr)).then(key => {
|
||||||
|
if (key.length == 52) {
|
||||||
|
if (pin === null)
|
||||||
|
resolve("Private key not secured")
|
||||||
|
else
|
||||||
|
reject("Private key not secured")
|
||||||
|
} else {
|
||||||
|
if (pin === null)
|
||||||
|
return reject("PIN/Password required")
|
||||||
|
try {
|
||||||
|
let privKey = Crypto.AES.decrypt(key, pin);
|
||||||
|
resolve("PIN/Password verified")
|
||||||
|
} catch (error) {
|
||||||
|
reject("Incorrect PIN/Password")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}).catch(error => reject(error))
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
|
},
|
||||||
|
|
||||||
getNextGeneralData: function(type, vectorClock = null, options = {}) {
|
getNextGeneralData: function(type, vectorClock = null, options = {}) {
|
||||||
var fk = floCloudAPI.util.filterKey(type, options)
|
var fk = floCloudAPI.util.filterKey(type, options)
|
||||||
vectorClock = vectorClock || this.getNextGeneralData[fk] || '0';
|
vectorClock = vectorClock || this.getNextGeneralData[fk] || '0';
|
||||||
@ -9295,9 +9439,8 @@ Bitcoin.Util = {
|
|||||||
let vc = Object.keys(response).sort().pop()
|
let vc = Object.keys(response).sort().pop()
|
||||||
let sync = JSON.parse(Crypto.AES.decrypt(response[vc].message, myPrivKey))
|
let sync = JSON.parse(Crypto.AES.decrypt(response[vc].message, myPrivKey))
|
||||||
let promises = []
|
let promises = []
|
||||||
let store = (key, val, obs) =>
|
let store = (key, val, obs) => promises.push(compactIDB.writeData(obs, val, key, `floDapps#${floID}`));
|
||||||
promises.push(compactIDB.writeData(obs, val, key, `floDapps#${floID}`))[
|
["contacts", "pubKeys", "messages"].forEach(c => {
|
||||||
"contacts", "pubKeys", "messages"].forEach(c => {
|
|
||||||
for (let i in sync[c]) {
|
for (let i in sync[c]) {
|
||||||
store(i, sync[c][i], c)
|
store(i, sync[c][i], c)
|
||||||
floGlobals[c][i] = sync[c][i]
|
floGlobals[c][i] = sync[c][i]
|
||||||
@ -9312,19 +9455,5 @@ Bitcoin.Util = {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
<script id="onLoadStartUp">
|
|
||||||
function onLoadStartUp() {
|
|
||||||
|
|
||||||
//floDapps.addStartUpFunction('Sample', Promised Function)
|
|
||||||
//floDapps.setAppObjectStores({sampleObs1:{}, sampleObs2:{options{autoIncrement:true, keyPath:'SampleKey'}, Indexes:{sampleIndex:{}}}})
|
|
||||||
//floDapps.setCustomPrivKeyInput( () => { FUNCTION BODY *must return private key* } )
|
|
||||||
|
|
||||||
floDapps.launchStartUp().then(result => {
|
|
||||||
console.log(result)
|
|
||||||
alert(`Welcome FLO_ID: ${myFloID}`)
|
|
||||||
//App functions....
|
|
||||||
}).catch(error => console.error(error))
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user