move required stdop files to docs/scripts/

This commit is contained in:
sairajzero 2023-05-19 01:05:47 +05:30
parent 85de9d4b96
commit fd6e09b157
10 changed files with 0 additions and 2235 deletions

21
LICENCE
View File

@ -1,21 +0,0 @@
MIT License
Copyright (c) 2023 Sai Raj
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View File

@ -1,257 +0,0 @@
(function (EXPORTS) { //compactIDB v2.1.2
/* Compact IndexedDB operations */
'use strict';
const compactIDB = EXPORTS;
var defaultDB;
const indexedDB = window.indexedDB || window.mozIndexedDB || window.webkitIndexedDB || window.msIndexedDB;
const IDBTransaction = window.IDBTransaction || window.webkitIDBTransaction || window.msIDBTransaction;
const IDBKeyRange = window.IDBKeyRange || window.webkitIDBKeyRange || window.msIDBKeyRange;
if (!indexedDB) {
console.error("Your browser doesn't support a stable version of IndexedDB.");
return;
}
compactIDB.setDefaultDB = dbName => defaultDB = dbName;
Object.defineProperty(compactIDB, 'default', {
get: () => defaultDB,
set: dbName => defaultDB = dbName
});
function getDBversion(dbName = defaultDB) {
return new Promise((resolve, reject) => {
openDB(dbName).then(db => {
resolve(db.version)
db.close()
}).catch(error => reject(error))
})
}
function upgradeDB(dbName, createList = null, deleteList = null) {
return new Promise((resolve, reject) => {
getDBversion(dbName).then(version => {
var idb = indexedDB.open(dbName, version + 1);
idb.onerror = (event) => reject("Error in opening IndexedDB");
idb.onupgradeneeded = (event) => {
let db = event.target.result;
if (createList instanceof Object) {
if (Array.isArray(createList)) {
let tmp = {}
createList.forEach(o => tmp[o] = {})
createList = tmp
}
for (let o in createList) {
let obs = db.createObjectStore(o, createList[o].options || {});
if (createList[o].indexes instanceof Object)
for (let i in createList[o].indexes)
obs.createIndex(i, i, createList[o].indexes || {});
}
}
if (Array.isArray(deleteList))
deleteList.forEach(o => db.deleteObjectStore(o));
resolve('Database upgraded')
}
idb.onsuccess = (event) => event.target.result.close();
}).catch(error => reject(error))
})
}
compactIDB.initDB = function (dbName, objectStores = {}) {
return new Promise((resolve, reject) => {
if (!(objectStores instanceof Object))
return reject('ObjectStores must be an object or array')
defaultDB = defaultDB || dbName;
var idb = indexedDB.open(dbName);
idb.onerror = (event) => reject("Error in opening IndexedDB");
idb.onsuccess = (event) => {
var db = event.target.result;
let cList = Object.values(db.objectStoreNames);
var obs = {},
a_obs = {},
d_obs = [];
if (!Array.isArray(objectStores))
var obs = objectStores
else
objectStores.forEach(o => obs[o] = {})
let nList = Object.keys(obs)
for (let o of nList)
if (!cList.includes(o))
a_obs[o] = obs[o]
for (let o of cList)
if (!nList.includes(o))
d_obs.push(o)
if (!Object.keys(a_obs).length && !d_obs.length)
resolve("Initiated IndexedDB");
else
upgradeDB(dbName, a_obs, d_obs)
.then(result => resolve(result))
.catch(error => reject(error))
db.close();
}
});
}
const openDB = compactIDB.openDB = function (dbName = defaultDB) {
return new Promise((resolve, reject) => {
var idb = indexedDB.open(dbName);
idb.onerror = (event) => reject("Error in opening IndexedDB");
idb.onupgradeneeded = (event) => {
event.target.result.close();
deleteDB(dbName).then(_ => null).catch(_ => null).finally(_ => reject("Datebase not found"))
}
idb.onsuccess = (event) => resolve(event.target.result);
});
}
const deleteDB = compactIDB.deleteDB = function (dbName = defaultDB) {
return new Promise((resolve, reject) => {
var deleteReq = indexedDB.deleteDatabase(dbName);;
deleteReq.onerror = (event) => reject("Error deleting database!");
deleteReq.onsuccess = (event) => resolve("Database deleted successfully");
});
}
compactIDB.writeData = function (obsName, data, key = false, dbName = defaultDB) {
return new Promise((resolve, reject) => {
openDB(dbName).then(db => {
var obs = db.transaction(obsName, "readwrite").objectStore(obsName);
let writeReq = (key ? obs.put(data, key) : obs.put(data));
writeReq.onsuccess = (evt) => resolve(`Write data Successful`);
writeReq.onerror = (evt) => reject(
`Write data unsuccessful [${evt.target.error.name}] ${evt.target.error.message}`
);
db.close();
}).catch(error => reject(error));
});
}
compactIDB.addData = function (obsName, data, key = false, dbName = defaultDB) {
return new Promise((resolve, reject) => {
openDB(dbName).then(db => {
var obs = db.transaction(obsName, "readwrite").objectStore(obsName);
let addReq = (key ? obs.add(data, key) : obs.add(data));
addReq.onsuccess = (evt) => resolve(`Add data successful`);
addReq.onerror = (evt) => reject(
`Add data unsuccessful [${evt.target.error.name}] ${evt.target.error.message}`
);
db.close();
}).catch(error => reject(error));
});
}
compactIDB.removeData = function (obsName, key, dbName = defaultDB) {
return new Promise((resolve, reject) => {
openDB(dbName).then(db => {
var obs = db.transaction(obsName, "readwrite").objectStore(obsName);
let delReq = obs.delete(key);
delReq.onsuccess = (evt) => resolve(`Removed Data ${key}`);
delReq.onerror = (evt) => reject(
`Remove data unsuccessful [${evt.target.error.name}] ${evt.target.error.message}`
);
db.close();
}).catch(error => reject(error));
});
}
compactIDB.clearData = function (obsName, dbName = defaultDB) {
return new Promise((resolve, reject) => {
openDB(dbName).then(db => {
var obs = db.transaction(obsName, "readwrite").objectStore(obsName);
let clearReq = obs.clear();
clearReq.onsuccess = (evt) => resolve(`Clear data Successful`);
clearReq.onerror = (evt) => reject(`Clear data Unsuccessful`);
db.close();
}).catch(error => reject(error));
});
}
compactIDB.readData = function (obsName, key, dbName = defaultDB) {
return new Promise((resolve, reject) => {
openDB(dbName).then(db => {
var obs = db.transaction(obsName, "readonly").objectStore(obsName);
let getReq = obs.get(key);
getReq.onsuccess = (evt) => resolve(evt.target.result);
getReq.onerror = (evt) => reject(
`Read data unsuccessful [${evt.target.error.name}] ${evt.target.error.message}`
);
db.close();
}).catch(error => reject(error));
});
}
compactIDB.readAllData = function (obsName, dbName = defaultDB) {
return new Promise((resolve, reject) => {
openDB(dbName).then(db => {
var obs = db.transaction(obsName, "readonly").objectStore(obsName);
var tmpResult = {}
let curReq = obs.openCursor();
curReq.onsuccess = (evt) => {
var cursor = evt.target.result;
if (cursor) {
tmpResult[cursor.primaryKey] = cursor.value;
cursor.continue();
} else
resolve(tmpResult);
}
curReq.onerror = (evt) => reject(
`Read-All data unsuccessful [${evt.target.error.name}] ${evt.target.error.message}`
);
db.close();
}).catch(error => reject(error));
});
}
/* compactIDB.searchData = function (obsName, options = {}, dbName = defaultDB) {
return new Promise((resolve, reject) => {
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))
})
}*/
compactIDB.searchData = function (obsName, options = {}, dbName = defaultDB) {
options.lowerKey = options.atKey || options.lowerKey || 0
options.upperKey = options.atKey || options.upperKey || false
options.patternEval = options.patternEval || ((k, v) => true);
options.limit = options.limit || false;
options.reverse = options.reverse || false;
options.lastOnly = options.lastOnly || false
return new Promise((resolve, reject) => {
openDB(dbName).then(db => {
var obs = db.transaction(obsName, "readonly").objectStore(obsName);
var filteredResult = {}
let curReq = obs.openCursor(
options.upperKey ? IDBKeyRange.bound(options.lowerKey, options.upperKey) : IDBKeyRange.lowerBound(options.lowerKey),
options.lastOnly || options.reverse ? "prev" : "next");
curReq.onsuccess = (evt) => {
var cursor = evt.target.result;
if (!cursor || (options.limit && options.limit <= Object.keys(filteredResult).length))
return resolve(filteredResult); //reached end of key list or limit reached
else if (options.patternEval(cursor.primaryKey, cursor.value)) {
filteredResult[cursor.primaryKey] = cursor.value;
options.lastOnly ? resolve(filteredResult) : cursor.continue();
} else
cursor.continue();
}
curReq.onerror = (evt) => reject(`Search unsuccessful [${evt.target.error.name}] ${evt.target.error.message}`);
db.close();
}).catch(error => reject(error));
});
}
})(window.compactIDB = {});

File diff suppressed because it is too large Load Diff

View File

@ -1,845 +0,0 @@
(function (EXPORTS) { //floDapps v2.4.0
/* General functions for FLO Dapps*/
'use strict';
const floDapps = EXPORTS;
const DEFAULT = {
root: "floDapps",
application: floGlobals.application,
adminID: floGlobals.adminID
};
Object.defineProperties(floDapps, {
application: {
get: () => DEFAULT.application
},
adminID: {
get: () => DEFAULT.adminID
},
root: {
get: () => DEFAULT.root
}
});
var user_priv_raw, aes_key, user_priv_wrap; //private variable inside capsule
const raw_user = {
get private() {
if (!user_priv_raw)
throw "User not logged in";
return Crypto.AES.decrypt(user_priv_raw, aes_key);
}
}
var user_id, user_public, user_private;
const user = floDapps.user = {
get id() {
if (!user_id)
throw "User not logged in";
return user_id;
},
get public() {
if (!user_public)
throw "User not logged in";
return user_public;
},
get private() {
if (!user_private)
throw "User not logged in";
else if (user_private instanceof Function)
return user_private();
else
return Crypto.AES.decrypt(user_private, aes_key);
},
sign(message) {
return floCrypto.signData(message, raw_user.private);
},
decrypt(data) {
return floCrypto.decryptData(data, raw_user.private);
},
encipher(message) {
return Crypto.AES.encrypt(message, raw_user.private);
},
decipher(data) {
return Crypto.AES.decrypt(data, raw_user.private);
},
get db_name() {
return "floDapps#" + floCrypto.toFloID(user.id);
},
lock() {
user_private = user_priv_wrap;
},
async unlock() {
if (await user.private === raw_user.private)
user_private = user_priv_raw;
},
get_contact(id) {
if (!user.contacts)
throw "Contacts not available";
else if (user.contacts[id])
return user.contacts[id];
else {
let id_raw = floCrypto.decodeAddr(id).hex;
for (let i in user.contacts)
if (floCrypto.decodeAddr(i).hex == id_raw)
return user.contacts[i];
}
},
get_pubKey(id) {
if (!user.pubKeys)
throw "Contacts not available";
else if (user.pubKeys[id])
return user.pubKeys[id];
else {
let id_raw = floCrypto.decodeAddr(id).hex;
for (let i in user.pubKeys)
if (floCrypto.decodeAddr(i).hex == id_raw)
return user.pubKeys[i];
}
},
clear() {
user_id = user_public = user_private = undefined;
user_priv_raw = aes_key = undefined;
delete user.contacts;
delete user.pubKeys;
delete user.messages;
}
};
Object.defineProperties(window, {
myFloID: {
get: () => {
try {
return user.id;
} catch {
return;
}
}
},
myUserID: {
get: () => {
try {
return user.id;
} catch {
return;
}
}
},
myPubKey: {
get: () => {
try {
return user.public;
} catch {
return;
}
}
},
myPrivKey: {
get: () => {
try {
return user.private;
} catch {
return;
}
}
}
});
var subAdmins, trustedIDs, settings;
Object.defineProperties(floGlobals, {
subAdmins: {
get: () => subAdmins
},
trustedIDs: {
get: () => trustedIDs
},
settings: {
get: () => settings
},
contacts: {
get: () => user.contacts
},
pubKeys: {
get: () => user.pubKeys
},
messages: {
get: () => user.messages
}
})
function initIndexedDB() {
return new Promise((resolve, reject) => {
var obs_g = {
//general
lastTx: {},
//supernode (cloud list)
supernodes: {
indexes: {
uri: null,
pubKey: null
}
}
}
var obs_a = {
//login credentials
credentials: {},
//for Dapps
subAdmins: {},
trustedIDs: {},
settings: {},
appObjects: {},
generalData: {},
lastVC: {}
}
//add other given objectStores
initIndexedDB.appObs = initIndexedDB.appObs || {}
for (let o in initIndexedDB.appObs)
if (!(o in obs_a))
obs_a[o] = initIndexedDB.appObs[o]
Promise.all([
compactIDB.initDB(DEFAULT.application, obs_a),
compactIDB.initDB(DEFAULT.root, obs_g)
]).then(result => {
compactIDB.setDefaultDB(DEFAULT.application)
resolve("IndexedDB App Storage Initated Successfully")
}).catch(error => reject(error));
})
}
function initUserDB() {
return new Promise((resolve, reject) => {
var obs = {
contacts: {},
pubKeys: {},
messages: {}
}
compactIDB.initDB(user.db_name, obs).then(result => {
resolve("UserDB Initated Successfully")
}).catch(error => reject('Init userDB failed'));
})
}
function loadUserDB() {
return new Promise((resolve, reject) => {
var loadData = ["contacts", "pubKeys", "messages"]
var promises = []
for (var i = 0; i < loadData.length; i++)
promises[i] = compactIDB.readAllData(loadData[i], user.db_name)
Promise.all(promises).then(results => {
for (var i = 0; i < loadData.length; i++)
user[loadData[i]] = results[i]
resolve("Loaded Data from userDB")
}).catch(error => reject('Load userDB failed'))
})
}
const startUpOptions = {
cloud: true,
app_config: true,
}
floDapps.startUpOptions = {
set app_config(val) {
if (val === true || val === false)
startUpOptions.app_config = val;
},
get app_config() { return startUpOptions.app_config },
set cloud(val) {
if (val === true || val === false)
startUpOptions.cloud = val;
},
get cloud() { return startUpOptions.cloud },
}
const startUpFunctions = [];
startUpFunctions.push(function readSupernodeListFromAPI() {
return new Promise((resolve, reject) => {
if (!startUpOptions.cloud)
return resolve("No cloud for this app");
compactIDB.readData("lastTx", floCloudAPI.SNStorageID, DEFAULT.root).then(lastTx => {
var query_options = { sentOnly: true, pattern: floCloudAPI.SNStorageName };
if (typeof lastTx == 'number') //lastTx is tx count (*backward support)
query_options.ignoreOld = lastTx;
else if (typeof lastTx == 'string') //lastTx is txid of last tx
query_options.after = lastTx;
//fetch data from flosight
floBlockchainAPI.readData(floCloudAPI.SNStorageID, query_options).then(result => {
for (var i = result.data.length - 1; i >= 0; i--) {
var content = JSON.parse(result.data[i])[floCloudAPI.SNStorageName];
for (let sn in content.removeNodes)
compactIDB.removeData("supernodes", sn, DEFAULT.root);
for (let sn in content.newNodes)
compactIDB.writeData("supernodes", content.newNodes[sn], sn, DEFAULT.root);
for (let sn in content.updateNodes)
compactIDB.readData("supernodes", sn, DEFAULT.root).then(r => {
r = r || {}
r.uri = content.updateNodes[sn];
compactIDB.writeData("supernodes", r, sn, DEFAULT.root);
});
}
compactIDB.writeData("lastTx", result.lastItem, floCloudAPI.SNStorageID, DEFAULT.root);
compactIDB.readAllData("supernodes", DEFAULT.root).then(nodes => {
floCloudAPI.init(nodes)
.then(result => resolve("Loaded Supernode list\n" + result))
.catch(error => reject(error))
})
})
}).catch(error => reject(error))
})
});
startUpFunctions.push(function readAppConfigFromAPI() {
return new Promise((resolve, reject) => {
if (!startUpOptions.app_config)
return resolve("No configs for this app");
compactIDB.readData("lastTx", `${DEFAULT.application}|${DEFAULT.adminID}`, DEFAULT.root).then(lastTx => {
var query_options = { sentOnly: true, pattern: DEFAULT.application };
if (typeof lastTx == 'number') //lastTx is tx count (*backward support)
query_options.ignoreOld = lastTx;
else if (typeof lastTx == 'string') //lastTx is txid of last tx
query_options.after = lastTx;
//fetch data from flosight
floBlockchainAPI.readData(DEFAULT.adminID, query_options).then(result => {
for (var i = result.data.length - 1; i >= 0; i--) {
var content = JSON.parse(result.data[i])[DEFAULT.application];
if (!content || typeof content !== "object")
continue;
if (Array.isArray(content.removeSubAdmin))
for (var j = 0; j < content.removeSubAdmin.length; j++)
compactIDB.removeData("subAdmins", content.removeSubAdmin[j]);
if (Array.isArray(content.addSubAdmin))
for (var k = 0; k < content.addSubAdmin.length; k++)
compactIDB.writeData("subAdmins", true, content.addSubAdmin[k]);
if (Array.isArray(content.removeTrustedID))
for (var j = 0; j < content.removeTrustedID.length; j++)
compactIDB.removeData("trustedIDs", content.removeTrustedID[j]);
if (Array.isArray(content.addTrustedID))
for (var k = 0; k < content.addTrustedID.length; k++)
compactIDB.writeData("trustedIDs", true, content.addTrustedID[k]);
if (content.settings)
for (let l in content.settings)
compactIDB.writeData("settings", content.settings[l], l)
}
compactIDB.writeData("lastTx", result.lastItem, `${DEFAULT.application}|${DEFAULT.adminID}`, DEFAULT.root);
compactIDB.readAllData("subAdmins").then(result => {
subAdmins = Object.keys(result);
compactIDB.readAllData("trustedIDs").then(result => {
trustedIDs = Object.keys(result);
compactIDB.readAllData("settings").then(result => {
settings = result;
resolve("Read app configuration from blockchain");
})
})
})
})
}).catch(error => reject(error))
})
});
startUpFunctions.push(function loadDataFromAppIDB() {
return new Promise((resolve, reject) => {
if (!startUpOptions.cloud)
return resolve("No cloud for this app");
var loadData = ["appObjects", "generalData", "lastVC"]
var promises = []
for (var i = 0; i < loadData.length; i++)
promises[i] = compactIDB.readAllData(loadData[i])
Promise.all(promises).then(results => {
for (var i = 0; i < loadData.length; i++)
floGlobals[loadData[i]] = results[i]
resolve("Loaded Data from app IDB")
}).catch(error => reject(error))
})
});
var keyInput = type => new Promise((resolve, reject) => {
let inputVal = prompt(`Enter ${type}: `)
if (inputVal === null)
reject(null)
else
resolve(inputVal)
});
function getCredentials() {
const readSharesFromIDB = indexArr => 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)
if (secret)
resolve(secret)
else
reject("Shares are insufficient or incorrect")
}).catch(error => {
clearCredentials();
location.reload();
})
});
const writeSharesToIDB = (shares, i = 0, resultIndexes = []) => new Promise(resolve => {
if (i >= shares.length)
return resolve(resultIndexes)
var n = floCrypto.randInt(0, 100000)
compactIDB.addData("credentials", shares[i], n).then(res => {
resultIndexes.push(n)
writeSharesToIDB(shares, i + 1, resultIndexes)
.then(result => resolve(result))
}).catch(error => {
writeSharesToIDB(shares, i, resultIndexes)
.then(result => resolve(result))
})
});
const getPrivateKeyCredentials = () => new Promise((resolve, reject) => {
var indexArr = localStorage.getItem(`${DEFAULT.application}#privKey`)
if (indexArr) {
readSharesFromIDB(JSON.parse(indexArr))
.then(result => resolve(result))
.catch(error => reject(error))
} else {
var privKey;
keyInput("PRIVATE_KEY").then(result => {
if (!result)
return reject("Empty Private Key")
var floID = floCrypto.getFloID(result)
if (!floID || !floCrypto.validateFloID(floID))
return reject("Invalid Private Key")
privKey = result;
}).catch(error => {
console.log(error, "Generating Random Keys")
privKey = floCrypto.generateNewID().privKey
}).finally(_ => {
if (!privKey)
return;
var threshold = floCrypto.randInt(10, 20)
var shares = floCrypto.createShamirsSecretShares(privKey, threshold, threshold)
writeSharesToIDB(shares).then(resultIndexes => {
//store index keys in localStorage
localStorage.setItem(`${DEFAULT.application}#privKey`, JSON.stringify(resultIndexes))
//also add a dummy privatekey to the IDB
var randomPrivKey = floCrypto.generateNewID().privKey
var randomThreshold = floCrypto.randInt(10, 20)
var randomShares = floCrypto.createShamirsSecretShares(randomPrivKey, randomThreshold, randomThreshold)
writeSharesToIDB(randomShares)
//resolve private Key
resolve(privKey)
})
})
}
});
const checkIfPinRequired = key => new Promise((resolve, reject) => {
if (key.length == 52)
resolve(key)
else {
keyInput("PIN/Password").then(pwd => {
try {
let privKey = Crypto.AES.decrypt(key, pwd);
resolve(privKey)
} catch (error) {
reject("Access Denied: Incorrect PIN/Password")
}
}).catch(error => reject("Access Denied: PIN/Password required"))
}
});
return new Promise((resolve, reject) => {
getPrivateKeyCredentials().then(key => {
checkIfPinRequired(key).then(privKey => {
try {
user_public = floCrypto.getPubKeyHex(privKey);
user_id = floCrypto.getAddress(privKey);
if (startUpOptions.cloud)
floCloudAPI.user(user_id, privKey); //Set user for floCloudAPI
user_priv_wrap = () => checkIfPinRequired(key);
let n = floCrypto.randInt(12, 20);
aes_key = floCrypto.randString(n);
user_priv_raw = Crypto.AES.encrypt(privKey, aes_key);
user_private = user_priv_wrap;
resolve('Login Credentials loaded successful')
} catch (error) {
console.log(error)
reject("Corrupted Private Key")
}
}).catch(error => reject(error))
}).catch(error => reject(error))
})
}
var startUpLog = (status, log) => status ? console.log(log) : console.error(log);
const callStartUpFunction = i => new Promise((resolve, reject) => {
startUpFunctions[i]().then(result => {
callStartUpFunction.completed += 1;
startUpLog(true, `${result}\nCompleted ${callStartUpFunction.completed}/${callStartUpFunction.total} Startup functions`)
resolve(true)
}).catch(error => {
callStartUpFunction.failed += 1;
startUpLog(false, `${error}\nFailed ${callStartUpFunction.failed}/${callStartUpFunction.total} Startup functions`)
reject(false)
})
});
var _midFunction;
const midStartUp = () => new Promise((res, rej) => {
if (_midFunction instanceof Function) {
_midFunction()
.then(r => res("Mid startup function completed"))
.catch(e => rej("Mid startup function failed"))
} else
res("No mid startup function")
});
const callAndLog = p => new Promise((res, rej) => {
p.then(r => {
startUpLog(true, r)
res(r)
}).catch(e => {
startUpLog(false, e)
rej(e)
})
});
floDapps.launchStartUp = function () {
return new Promise((resolve, reject) => {
initIndexedDB().then(log => {
console.log(log)
callStartUpFunction.total = startUpFunctions.length;
callStartUpFunction.completed = 0;
callStartUpFunction.failed = 0;
let p1 = new Promise((res, rej) => {
Promise.all(startUpFunctions.map((f, i) => callStartUpFunction(i))).then(r => {
callAndLog(midStartUp())
.then(r => res(true))
.catch(e => rej(false))
})
});
let p2 = new Promise((res, rej) => {
callAndLog(getCredentials()).then(r => {
callAndLog(initUserDB()).then(r => {
callAndLog(loadUserDB())
.then(r => res(true))
.catch(e => rej(false))
}).catch(e => rej(false))
}).catch(e => rej(false))
})
Promise.all([p1, p2])
.then(r => resolve('App Startup finished successful'))
.catch(e => reject('App Startup failed'))
}).catch(error => {
startUpLog(false, error);
reject("App database initiation failed")
})
})
}
floDapps.addStartUpFunction = fn => fn instanceof Function && !startUpFunctions.includes(fn) ? startUpFunctions.push(fn) : false;
floDapps.setMidStartup = fn => fn instanceof Function ? _midFunction = fn : false;
floDapps.setCustomStartupLogger = fn => fn instanceof Function ? startUpLog = fn : false;
floDapps.setCustomPrivKeyInput = fn => fn instanceof Function ? keyInput = fn : false;
floDapps.setAppObjectStores = appObs => initIndexedDB.appObs = appObs;
floDapps.storeContact = function (floID, name) {
return new Promise((resolve, reject) => {
if (!floCrypto.validateAddr(floID))
return reject("Invalid floID!")
compactIDB.writeData("contacts", name, floID, user.db_name).then(result => {
user.contacts[floID] = name;
resolve("Contact stored")
}).catch(error => reject(error))
});
}
floDapps.storePubKey = function (floID, pubKey) {
return new Promise((resolve, reject) => {
if (floID in user.pubKeys)
return resolve("pubKey already stored")
if (!floCrypto.validateAddr(floID))
return reject("Invalid floID!")
if (!floCrypto.verifyPubKey(pubKey, floID))
return reject("Incorrect pubKey")
compactIDB.writeData("pubKeys", pubKey, floID, user.db_name).then(result => {
user.pubKeys[floID] = pubKey;
resolve("pubKey stored")
}).catch(error => reject(error))
});
}
floDapps.sendMessage = function (floID, message) {
return new Promise((resolve, reject) => {
let options = {
receiverID: floID,
application: DEFAULT.root,
comment: DEFAULT.application
}
if (floID in user.pubKeys)
message = floCrypto.encryptData(JSON.stringify(message), user.pubKeys[floID])
floCloudAPI.sendApplicationData(message, "Message", options)
.then(result => resolve(result))
.catch(error => reject(error))
})
}
floDapps.requestInbox = function (callback) {
return new Promise((resolve, reject) => {
let lastVC = Object.keys(user.messages).sort().pop()
let options = {
receiverID: user.id,
application: DEFAULT.root,
lowerVectorClock: lastVC + 1
}
let privKey = raw_user.private;
options.callback = (d, e) => {
for (let v in d) {
try {
if (d[v].message instanceof Object && "secret" in d[v].message)
d[v].message = floCrypto.decryptData(d[v].message, privKey)
} catch (error) { }
compactIDB.writeData("messages", d[v], v, user.db_name)
user.messages[v] = d[v]
}
if (callback instanceof Function)
callback(d, e)
}
floCloudAPI.requestApplicationData("Message", options)
.then(result => resolve(result))
.catch(error => reject(error))
})
}
floDapps.manageAppConfig = function (adminPrivKey, addList, rmList, settings) {
return new Promise((resolve, reject) => {
if (!startUpOptions.app_config)
return reject("No configs for this app");
if (!Array.isArray(addList) || !addList.length) addList = undefined;
if (!Array.isArray(rmList) || !rmList.length) rmList = undefined;
if (!settings || typeof settings !== "object" || !Object.keys(settings).length) settings = undefined;
if (!addList && !rmList && !settings)
return reject("No configuration change")
var floData = {
[DEFAULT.application]: {
addSubAdmin: addList,
removeSubAdmin: rmList,
settings: settings
}
}
var floID = floCrypto.getFloID(adminPrivKey)
if (floID != DEFAULT.adminID)
reject('Access Denied for Admin privilege')
else
floBlockchainAPI.writeData(floID, JSON.stringify(floData), adminPrivKey)
.then(result => resolve(['Updated App Configuration', result]))
.catch(error => reject(error))
})
}
floDapps.manageAppTrustedIDs = function (adminPrivKey, addList, rmList) {
return new Promise((resolve, reject) => {
if (!startUpOptions.app_config)
return reject("No configs for this app");
if (!Array.isArray(addList) || !addList.length) addList = undefined;
if (!Array.isArray(rmList) || !rmList.length) rmList = undefined;
if (!addList && !rmList)
return reject("No change in list")
var floData = {
[DEFAULT.application]: {
addTrustedID: addList,
removeTrustedID: rmList
}
}
var floID = floCrypto.getFloID(adminPrivKey)
if (floID != DEFAULT.adminID)
reject('Access Denied for Admin privilege')
else
floBlockchainAPI.writeData(floID, JSON.stringify(floData), adminPrivKey)
.then(result => resolve(['Updated App Configuration', result]))
.catch(error => reject(error))
})
}
const clearCredentials = floDapps.clearCredentials = function () {
return new Promise((resolve, reject) => {
compactIDB.clearData('credentials', DEFAULT.application).then(result => {
localStorage.removeItem(`${DEFAULT.application}#privKey`);
user.clear();
resolve("privKey credentials deleted!")
}).catch(error => reject(error))
})
}
floDapps.deleteUserData = function (credentials = false) {
return new Promise((resolve, reject) => {
let p = []
p.push(compactIDB.deleteDB(user.db_name))
if (credentials)
p.push(clearCredentials())
Promise.all(p)
.then(result => resolve('User database(local) deleted'))
.catch(error => reject(error))
})
}
floDapps.deleteAppData = function () {
return new Promise((resolve, reject) => {
compactIDB.deleteDB(DEFAULT.application).then(result => {
localStorage.removeItem(`${DEFAULT.application}#privKey`)
user.clear();
compactIDB.removeData('lastTx', `${DEFAULT.application}|${DEFAULT.adminID}`, DEFAULT.root)
.then(result => resolve("App database(local) deleted"))
.catch(error => reject(error))
}).catch(error => reject(error))
})
}
floDapps.securePrivKey = function (pwd) {
return new Promise(async (resolve, reject) => {
let indexArr = localStorage.getItem(`${DEFAULT.application}#privKey`)
if (!indexArr)
return reject("PrivKey not found");
indexArr = JSON.parse(indexArr)
let encryptedKey = Crypto.AES.encrypt(await user.private, pwd);
let threshold = indexArr.length;
let shares = floCrypto.createShamirsSecretShares(encryptedKey, threshold, threshold)
let promises = [];
let overwriteFn = (share, index) =>
compactIDB.writeData("credentials", share, index, DEFAULT.application);
for (var i = 0; i < threshold; i++)
promises.push(overwriteFn(shares[i], indexArr[i]));
Promise.all(promises)
.then(results => resolve("Private Key Secured"))
.catch(error => reject(error))
})
}
floDapps.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 => {
clearCredentials();
location.reload();
})
})
}
return new Promise((resolve, reject) => {
var indexArr = localStorage.getItem(`${DEFAULT.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))
})
}
const getNextGeneralData = floDapps.getNextGeneralData = function (type, vectorClock = null, options = {}) {
var fk = floCloudAPI.util.filterKey(type, options)
vectorClock = vectorClock || getNextGeneralData[fk] || '0';
var filteredResult = {}
if (floGlobals.generalData[fk]) {
for (let d in floGlobals.generalData[fk])
if (d > vectorClock)
filteredResult[d] = JSON.parse(JSON.stringify(floGlobals.generalData[fk][d]))
} else if (options.comment) {
let comment = options.comment;
delete options.comment;
let fk = floCloudAPI.util.filterKey(type, options);
for (let d in floGlobals.generalData[fk])
if (d > vectorClock && floGlobals.generalData[fk][d].comment == comment)
filteredResult[d] = JSON.parse(JSON.stringify(floGlobals.generalData[fk][d]))
}
if (options.decrypt) {
let decryptionKey = (options.decrypt === true) ? raw_user.private : options.decrypt;
if (!Array.isArray(decryptionKey))
decryptionKey = [decryptionKey];
for (let f in filteredResult) {
let data = filteredResult[f]
try {
if (data.message instanceof Object && "secret" in data.message) {
for (let key of decryptionKey) {
try {
let tmp = floCrypto.decryptData(data.message, key)
data.message = JSON.parse(tmp)
break;
} catch (error) { }
}
}
} catch (error) { }
}
}
getNextGeneralData[fk] = Object.keys(filteredResult).sort().pop();
return filteredResult;
}
const syncData = floDapps.syncData = {};
syncData.oldDevice = () => new Promise((resolve, reject) => {
let sync = {
contacts: user.contacts,
pubKeys: user.pubKeys,
messages: user.messages
}
let message = Crypto.AES.encrypt(JSON.stringify(sync), raw_user.private)
let options = {
receiverID: user.id,
application: DEFAULT.root
}
floCloudAPI.sendApplicationData(message, "syncData", options)
.then(result => resolve(result))
.catch(error => reject(error))
});
syncData.newDevice = () => new Promise((resolve, reject) => {
var options = {
receiverID: user.id,
senderID: user.id,
application: DEFAULT.root,
mostRecent: true,
}
floCloudAPI.requestApplicationData("syncData", options).then(response => {
let vc = Object.keys(response).sort().pop()
let sync = JSON.parse(Crypto.AES.decrypt(response[vc].message, raw_user.private))
let promises = []
let store = (key, val, obs) => promises.push(compactIDB.writeData(obs, val, key, user.db_name));
["contacts", "pubKeys", "messages"].forEach(c => {
for (let i in sync[c]) {
store(i, sync[c][i], c)
user[c][i] = sync[c][i]
}
})
Promise.all(promises)
.then(results => resolve("Sync data successful"))
.catch(error => reject(error))
}).catch(error => reject(error))
});
})('object' === typeof module ? module.exports : window.floDapps = {});

View File

@ -1,57 +0,0 @@
<!DOCTYPE html>
<html lang="en">
<head>
<title>FLO Standard Operators</title>
<script id="floGlobals">
/* Constants for FLO blockchain operations !!Make sure to add this at beginning!! */
const floGlobals = {
blockchain: "FLO",
adminID: "FKAEdnPfjXLHSYwrXQu377ugN4tXU7VGdf",
application: "TEST_MODE",
}
</script>
<script>
(function () {
const urlSearchParams = new URLSearchParams(window.location.search);
const params = Object.fromEntries(urlSearchParams.entries());
if ('testnet' in params) {
floGlobals.blockchain = "FLO_TEST";
floGlobals.adminID = "oKKHdK5uYAJ52U91sYsWhnEaEAAhZP779B";
floGlobals.application = "TEST_MODE_testnet";
}
if ('quick' in params)
window.quick = true;
})();
</script>
<script src="lib.js"></script>
<script src="floCrypto.js"></script>
<script src="btcOperator.js"></script>
<script src="floBlockchainAPI.js"></script>
<script src="floTokenAPI.js"></script>
<script src="compactIDB.js"></script>
<script src="floCloudAPI.js"></script>
<script src="floDapps.js"></script>
<script id="onLoadStartUp">
function onLoadStartUp() {
if (window.quick) return;
//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>
<body onload="onLoadStartUp()">
TEST_MODE
(use console)
</body>
</html>