Merge pull request #9 from sairajzero/master
This commit is contained in:
commit
49d4377900
40
README.md
40
README.md
@ -282,16 +282,15 @@ Note: If passed as Array, then ratio of the balance of the senders are preserved
|
|||||||
`readData` reads FLO data from transactions of specified address
|
`readData` reads FLO data from transactions of specified address
|
||||||
1. addr - FLO address for which the transactions data has to be read.
|
1. addr - FLO address for which the transactions data has to be read.
|
||||||
2. options - Contains options for filter data from transactions.
|
2. options - Contains options for filter data from transactions.
|
||||||
- limit : maximum number of filtered data (default = 1000, negative = no limit)
|
- limit : maximum number of filtered data (default = no limit)
|
||||||
- ignoreOld : ignore old transactions (default = 0)
|
- ignoreOld : ignore old transactions (default = 0)
|
||||||
- sentOnly : filters only sent data
|
- sentOnly : filters only sent data
|
||||||
- pattern : filters data that starts with a pattern
|
- pattern : filters data that contains pattern as an object key in the JSON string
|
||||||
- contains : filters data that contains a string
|
|
||||||
- filter : custom filter funtion for floData (eg . filter: d => {return d[0] == '$'})
|
- filter : custom filter funtion for floData (eg . filter: d => {return d[0] == '$'})
|
||||||
* Resolves: Object {totalTxs, floData (Array)}
|
* Resolves: Object {totalTxs, floData (Array)}
|
||||||
|
|
||||||
## Compact IndexedDB operations
|
## Compact IndexedDB operations
|
||||||
`compactIDB` operations can be used to perform basic IndexedDB operations such as add, read/write, modify and remove.Contains following operations.
|
`compactIDB` operations can be used to perform basic IndexedDB operations such as add, read/write, modify and remove. These functions are asynchronous and return a promise. Contains the following operations.
|
||||||
|
|
||||||
#### Important: Compact IndexedDB operations have all been promisified. All output needs to be handled using .then These operations do not return function return values. Once again, they resolve: they do not return.
|
#### Important: Compact IndexedDB operations have all been promisified. All output needs to be handled using .then These operations do not return function return values. Once again, they resolve: they do not return.
|
||||||
|
|
||||||
@ -299,22 +298,26 @@ Note: If passed as Array, then ratio of the balance of the senders are preserved
|
|||||||
compactIDB.setDefaultDB(dbName)
|
compactIDB.setDefaultDB(dbName)
|
||||||
`setDefaultDB` sets the database on which further operations will be performed.
|
`setDefaultDB` sets the database on which further operations will be performed.
|
||||||
1. dbName - This is the name of default database to be used.
|
1. dbName - This is the name of default database to be used.
|
||||||
|
* Note: this operation is neither promisified nor returns a value. It just sets the default DB
|
||||||
|
|
||||||
#### initDB
|
#### initDB
|
||||||
compactIDB.initDB(dbName, objectStores = {})
|
compactIDB.initDB(dbName, objectStores = {})
|
||||||
`initDB` initializes new IndexedDB.
|
`initDB` initializes new IndexedDB.
|
||||||
1. dbName - Specifies database to be initialized.
|
1. dbName - Specifies database to be initialized.
|
||||||
2. objectStores - This is an object containing various objectStores to be initiazed when creating an IDB.
|
2. objectStores - This is an object containing various objectStores to be initiazed when creating an IDB.
|
||||||
|
* Resolves: Status (string) | Rejects: error
|
||||||
|
|
||||||
#### openDB
|
#### openDB
|
||||||
compactIDB.openDB(dbName = this.defaultDB)
|
compactIDB.openDB(dbName = this.defaultDB)
|
||||||
`openDB` returns a promise that resolves to a default database object.
|
`openDB` returns a promise that resolves to a default database object.
|
||||||
1. dbName - Name of the database (optional, uses defaultDB if not specified)
|
1. dbName - Name of the database (optional, uses defaultDB if not specified)
|
||||||
|
* Resolves: database (IDB) | Rejects: error
|
||||||
|
|
||||||
#### deleteDB
|
#### deleteDB
|
||||||
compactIDB.deleteDB(dbName = this.defaultDB)
|
compactIDB.deleteDB(dbName = this.defaultDB)
|
||||||
`deleteDB` deletes the specified database.
|
`deleteDB` deletes the specified database.
|
||||||
1. dbName - Name of the database (optional, uses defaultDB if not specified)
|
1. dbName - Name of the database (optional, uses defaultDB if not specified)
|
||||||
|
* Resolves: Status (string) | Rejects: error
|
||||||
|
|
||||||
#### writeData
|
#### writeData
|
||||||
compactIDB.writeData(obsName, data, key = false, dbName = this.defaultDB)
|
compactIDB.writeData(obsName, data, key = false, dbName = this.defaultDB)
|
||||||
@ -323,6 +326,7 @@ Note: If passed as Array, then ratio of the balance of the senders are preserved
|
|||||||
2. data - data that has to be written in specified object store.
|
2. data - data that has to be written in specified object store.
|
||||||
3. key - Primary key of the data (optional, false indicates key is autoincremented or passed in data)
|
3. key - Primary key of the data (optional, false indicates key is autoincremented or passed in data)
|
||||||
4. dbName - Name of the database (optional, uses defaultDB if not specified)
|
4. dbName - Name of the database (optional, uses defaultDB if not specified)
|
||||||
|
* Resolves: Status (string) | Rejects: error
|
||||||
|
|
||||||
#### addData
|
#### addData
|
||||||
compactIDB.addData(obsName, data, key = false, dbName = this.defaultDB)
|
compactIDB.addData(obsName, data, key = false, dbName = this.defaultDB)
|
||||||
@ -331,6 +335,7 @@ Note: If passed as Array, then ratio of the balance of the senders are preserved
|
|||||||
2. data - The data which has to be added to obeject store.
|
2. data - The data which has to be added to obeject store.
|
||||||
3. key - Primary key of the data (optional, false indicates key is autoincremented or passed in data)
|
3. key - Primary key of the data (optional, false indicates key is autoincremented or passed in data)
|
||||||
4. dbName - Name of the database (optional, uses defaultDB if not specified)
|
4. dbName - Name of the database (optional, uses defaultDB if not specified)
|
||||||
|
* Resolves: Status (string) | Rejects: error
|
||||||
|
|
||||||
#### removeData
|
#### removeData
|
||||||
compactDB.removeData(obsName, key, dbName = this.defaultDB)
|
compactDB.removeData(obsName, key, dbName = this.defaultDB)
|
||||||
@ -338,12 +343,14 @@ Note: If passed as Array, then ratio of the balance of the senders are preserved
|
|||||||
1. obsName - Name of object store from which the data has to be removed.
|
1. obsName - Name of object store from which the data has to be removed.
|
||||||
2. key - Primary key of the data.
|
2. key - Primary key of the data.
|
||||||
3. dbName - Name of the database (optional, uses defaultDB if not specified)
|
3. dbName - Name of the database (optional, uses defaultDB if not specified)
|
||||||
|
* Resolves: Status (string) | Rejects: error
|
||||||
|
|
||||||
#### clearData
|
#### clearData
|
||||||
compactDB.clearData(obsName, dbName = this.defaultDB)
|
compactDB.clearData(obsName, dbName = this.defaultDB)
|
||||||
`clearData` clears all data in the objectStore.
|
`clearData` clears all data in the objectStore.
|
||||||
1. obsName - Name of object store from which the data has to be removed.
|
1. obsName - Name of object store from which the data has to be removed.
|
||||||
2. dbName - Name of the database (optional, uses defaultDB if not specified)
|
2. dbName - Name of the database (optional, uses defaultDB if not specified)
|
||||||
|
* Resolves: Status (string) | Rejects: error
|
||||||
|
|
||||||
#### readData
|
#### readData
|
||||||
compactDB.readData(obsName, key, dbName = this.defaultDB)
|
compactDB.readData(obsName, key, dbName = this.defaultDB)
|
||||||
@ -351,20 +358,34 @@ Note: If passed as Array, then ratio of the balance of the senders are preserved
|
|||||||
1. obsName - Name of object store from which the data has to be retrieved.
|
1. obsName - Name of object store from which the data has to be retrieved.
|
||||||
2. key - Primary key of the data to read.
|
2. key - Primary key of the data to read.
|
||||||
3. dbName - Name of the database (optional, uses defaultDB if not specified)
|
3. dbName - Name of the database (optional, uses defaultDB if not specified)
|
||||||
|
* Resolves: data (Object) | Rejects: error
|
||||||
|
|
||||||
#### readAllData
|
#### readAllData
|
||||||
compactDB.readAllData(obsName, dbName = this.defaultDB)
|
compactDB.readAllData(obsName, dbName = this.defaultDB)
|
||||||
`readAllData` reads all the data from specified object store using IndexedDB openCursor method.
|
`readAllData` reads all the data from specified object store using IndexedDB openCursor method.
|
||||||
1. obsName - Name of object store from which the data has to be retrieved.
|
1. obsName - Name of object store from which the data has to be retrieved.
|
||||||
2. dbName - Name of the database (optional, uses defaultDB if not specified)
|
2. dbName - Name of the database (optional, uses defaultDB if not specified)
|
||||||
|
* Resolves: data (Object) | Rejects: error
|
||||||
|
|
||||||
## FLO Supernode module
|
## FLO Supernode module
|
||||||
This module contains functions that interact with the supernode to send and retrive data in the backend. Use floClouldAPI operations to send and receive data for application.
|
This module contains functions that interact with the supernode to send and retrive data in the backend. Use floClouldAPI operations to send and receive data for application.
|
||||||
|
|
||||||
## FLO Cloud API operations
|
## FLO Cloud API operations
|
||||||
`floCloudAPI` operations can interact with floSupernode cloud to send and retrieve data for applications. floCloudAPI uses floSupernode module for backend interactions.
|
`floCloudAPI` operations can interact with floSupernode cloud to send and retrieve data for applications. floCloudAPI uses floSupernode module for backend interactions. FLO Cloud API functions are promisified and resolves the data or status.
|
||||||
|
|
||||||
FLO Cloud API operations have all been promisified. All output needs to be handled using .then These operations do not return function return values. Once again, they resolve: they do not return.
|
#### sendApplicationData
|
||||||
|
floCloudAPI.sendApplicationData(message, type, options = {})
|
||||||
|
`sendApplicationData` sends application data to the cloud.
|
||||||
|
1. message - data to be sent
|
||||||
|
2. type - type of the data
|
||||||
|
3. options - (optional, options detailed at end of module)
|
||||||
|
* Resolves: Sent-Status (string) | Rejects: error
|
||||||
|
|
||||||
|
#### requestApplicationData
|
||||||
|
floCloudAPI.requestApplicationData(options = {})
|
||||||
|
`requestApplicationData` requests application data from the cloud.
|
||||||
|
1. options - (optional, options detailed at end of module)
|
||||||
|
* Resolves: data (Object) | Rejects: error
|
||||||
|
|
||||||
#### sendGeneralData
|
#### sendGeneralData
|
||||||
floCloudAPI.sendGeneralData(message, type, options = {})
|
floCloudAPI.sendGeneralData(message, type, options = {})
|
||||||
@ -372,6 +393,7 @@ FLO Cloud API operations have all been promisified. All output needs to be handl
|
|||||||
1. message - data to be sent
|
1. message - data to be sent
|
||||||
2. type - type of the data
|
2. type - type of the data
|
||||||
3. options - (optional, options detailed at end of module)
|
3. options - (optional, options detailed at end of module)
|
||||||
|
* Resolves: Sent-Status (string) | Rejects: error
|
||||||
|
|
||||||
###### Minimal Example:
|
###### Minimal Example:
|
||||||
floCloudAPI.sendGeneralData("Hello World", "type1")
|
floCloudAPI.sendGeneralData("Hello World", "type1")
|
||||||
@ -382,6 +404,7 @@ Sends "Hello World" message to the cloud as General Data with type1 as `type` wi
|
|||||||
`requestGeneralData` requests application data from the cloud.
|
`requestGeneralData` requests application data from the cloud.
|
||||||
1. type - type of the data
|
1. type - type of the data
|
||||||
2. options - (optional, options detailed at end of module)
|
2. options - (optional, options detailed at end of module)
|
||||||
|
* Resolves: Status (string) | Rejects: error
|
||||||
|
|
||||||
###### Minimal Example:
|
###### Minimal Example:
|
||||||
floCloudAPI.requestGeneralData("type1")
|
floCloudAPI.requestGeneralData("type1")
|
||||||
@ -392,9 +415,9 @@ Requests all messages of General Data nature from the cloud with type1 as `type`
|
|||||||
`resetObjectData` resets the objectData to cloud.
|
`resetObjectData` resets the objectData to cloud.
|
||||||
1. "objectName" - Name of the objectData to be reset. Quotes are must
|
1. "objectName" - Name of the objectData to be reset. Quotes are must
|
||||||
2. options - (optional, options detailed at end of module)
|
2. options - (optional, options detailed at end of module)
|
||||||
|
* Resolves: Sent-Status (string) | Rejects: error
|
||||||
|
|
||||||
Note: value of objectData is taken from floGlobals.appObjects["objectName"]
|
Note: value of objectData is taken from floGlobals.appObjects["objectName"]
|
||||||
|
|
||||||
The object data corresponding with Object Name must be defined in floGlobals.appObjects["objectName"] before a reset can be done
|
The object data corresponding with Object Name must be defined in floGlobals.appObjects["objectName"] before a reset can be done
|
||||||
|
|
||||||
###### Minimal Example:
|
###### Minimal Example:
|
||||||
@ -407,9 +430,9 @@ Initiates "myFirstObject" with {a:1,b:2}, and sends to cloud with `myFloID` as d
|
|||||||
`updateObjectData` updates the objectData to cloud.
|
`updateObjectData` updates the objectData to cloud.
|
||||||
1. "objectName" - Name of the objectData to be updated. Quotes are must.
|
1. "objectName" - Name of the objectData to be updated. Quotes are must.
|
||||||
2. options - (optional, options detailed at end of module)
|
2. options - (optional, options detailed at end of module)
|
||||||
|
* Resolves: Sent-Status (string) | Rejects: error
|
||||||
|
|
||||||
Note: value of objectData is taken from floGlobals.appObjects["objectName"]
|
Note: value of objectData is taken from floGlobals.appObjects["objectName"]
|
||||||
|
|
||||||
The object data corresponding with Object Name must be defined in floGlobals.appObjects["objectName"] before an update can be done
|
The object data corresponding with Object Name must be defined in floGlobals.appObjects["objectName"] before an update can be done
|
||||||
|
|
||||||
###### Minimal Example:
|
###### Minimal Example:
|
||||||
@ -422,6 +445,7 @@ Updates "myFirstObject" with {a:1,c:3,d:4}, and sends to cloud with `myFloID` as
|
|||||||
`requestObjectData` requests application data from the cloud.
|
`requestObjectData` requests application data from the cloud.
|
||||||
1. "objectName" - Name of the objectData to be requested. Quotes are must.
|
1. "objectName" - Name of the objectData to be requested. Quotes are must.
|
||||||
2. options - (optional, options detailed at end of module)
|
2. options - (optional, options detailed at end of module)
|
||||||
|
* Resolves: Status (string) | Rejects: error
|
||||||
|
|
||||||
Note: The output is available at floGlobals.appObjects["objectName"] after the promise is resolved
|
Note: The output is available at floGlobals.appObjects["objectName"] after the promise is resolved
|
||||||
|
|
||||||
|
|||||||
@ -7400,7 +7400,7 @@ Bitcoin.Util = {
|
|||||||
var change = utxoAmt - sendAmt - fee;
|
var change = utxoAmt - sendAmt - fee;
|
||||||
if (change > 0)
|
if (change > 0)
|
||||||
trx.addoutput(senderAddr, change);
|
trx.addoutput(senderAddr, change);
|
||||||
trx.addflodata(floData.replace(/\n/g,' '));
|
trx.addflodata(floData.replace(/\n/g, ' '));
|
||||||
var signedTxHash = trx.sign(privKey, 1);
|
var signedTxHash = trx.sign(privKey, 1);
|
||||||
this.broadcastTx(signedTxHash)
|
this.broadcastTx(signedTxHash)
|
||||||
.then(txid => resolve(txid))
|
.then(txid => resolve(txid))
|
||||||
@ -7431,7 +7431,7 @@ Bitcoin.Util = {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
trx.addoutput(floID, utxoAmt - fee);
|
trx.addoutput(floID, utxoAmt - fee);
|
||||||
trx.addflodata(floData.replace(/\n/g,' '));
|
trx.addflodata(floData.replace(/\n/g, ' '));
|
||||||
var signedTxHash = trx.sign(privKey, 1);
|
var signedTxHash = trx.sign(privKey, 1);
|
||||||
this.broadcastTx(signedTxHash)
|
this.broadcastTx(signedTxHash)
|
||||||
.then(txid => resolve(txid))
|
.then(txid => resolve(txid))
|
||||||
@ -7447,11 +7447,11 @@ Bitcoin.Util = {
|
|||||||
* @param {boolean} preserveRatio (optional) preserve ratio or equal contribution
|
* @param {boolean} preserveRatio (optional) preserve ratio or equal contribution
|
||||||
* @return {Promise}
|
* @return {Promise}
|
||||||
*/
|
*/
|
||||||
writeDataMultiple: function (senderPrivKeys, data, receivers = [floGlobals.adminID], preserveRatio = true){
|
writeDataMultiple: function (senderPrivKeys, data, receivers = [floGlobals.adminID], preserveRatio = true) {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
if (!Array.isArray(senderPrivKeys))
|
if (!Array.isArray(senderPrivKeys))
|
||||||
return reject("Invalid senderPrivKeys: SenderPrivKeys must be Array")
|
return reject("Invalid senderPrivKeys: SenderPrivKeys must be Array")
|
||||||
if(!preserveRatio){
|
if (!preserveRatio) {
|
||||||
let tmp = {};
|
let tmp = {};
|
||||||
let amount = (floGlobals.sendAmt * receivers.length) / senderPrivKeys.length;
|
let amount = (floGlobals.sendAmt * receivers.length) / senderPrivKeys.length;
|
||||||
senderPrivKeys.forEach(key => tmp[key] = amount);
|
senderPrivKeys.forEach(key => tmp[key] = amount);
|
||||||
@ -7481,54 +7481,59 @@ Bitcoin.Util = {
|
|||||||
*/
|
*/
|
||||||
sendTxMultiple: function (senderPrivKeys, receivers, floData = '') {
|
sendTxMultiple: function (senderPrivKeys, receivers, floData = '') {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
|
|
||||||
let senders = {}, preserveRatio;
|
let senders = {},
|
||||||
|
preserveRatio;
|
||||||
//check for argument validations
|
//check for argument validations
|
||||||
try{
|
try {
|
||||||
let invalids = {
|
let invalids = {
|
||||||
InvalidSenderPrivKeys: [],
|
InvalidSenderPrivKeys: [],
|
||||||
InvalidSenderAmountFor: [],
|
InvalidSenderAmountFor: [],
|
||||||
InvalidReceiverIDs: [],
|
InvalidReceiverIDs: [],
|
||||||
InvalidReceiveAmountFor: []
|
InvalidReceiveAmountFor: []
|
||||||
}
|
}
|
||||||
let inputVal = 0, outputVal = 0;
|
let inputVal = 0,
|
||||||
|
outputVal = 0;
|
||||||
//Validate sender privatekeys (and send amount if passed)
|
//Validate sender privatekeys (and send amount if passed)
|
||||||
//conversion when only privateKeys are passed (preserveRatio mode)
|
//conversion when only privateKeys are passed (preserveRatio mode)
|
||||||
if(Array.isArray(senderPrivKeys)){
|
if (Array.isArray(senderPrivKeys)) {
|
||||||
senderPrivKeys.forEach(key => {
|
senderPrivKeys.forEach(key => {
|
||||||
try{
|
try {
|
||||||
if(!key)
|
if (!key)
|
||||||
invalids.InvalidSenderPrivKeys.push(key);
|
invalids.InvalidSenderPrivKeys.push(key);
|
||||||
else{
|
else {
|
||||||
let floID = floCrypto.getFloIDfromPubkeyHex(floCrypto.getPubKeyHex(key));
|
let floID = floCrypto.getFloIDfromPubkeyHex(floCrypto
|
||||||
|
.getPubKeyHex(key));
|
||||||
senders[floID] = {
|
senders[floID] = {
|
||||||
wif: key
|
wif: key
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}catch(error){
|
} catch (error) {
|
||||||
invalids.InvalidSenderPrivKeys.push(key)
|
invalids.InvalidSenderPrivKeys.push(key)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
preserveRatio = true;
|
preserveRatio = true;
|
||||||
}
|
}
|
||||||
//conversion when privatekeys are passed with send amount
|
//conversion when privatekeys are passed with send amount
|
||||||
else{
|
else {
|
||||||
for(let key in senderPrivKeys){
|
for (let key in senderPrivKeys) {
|
||||||
try{
|
try {
|
||||||
if(!key)
|
if (!key)
|
||||||
invalids.InvalidSenderPrivKeys.push(key);
|
invalids.InvalidSenderPrivKeys.push(key);
|
||||||
else{
|
else {
|
||||||
if(typeof senderPrivKeys[key] !== 'number' || senderPrivKeys[key] <= 0)
|
if (typeof senderPrivKeys[key] !== 'number' || senderPrivKeys[
|
||||||
|
key] <= 0)
|
||||||
invalids.InvalidSenderAmountFor.push(key)
|
invalids.InvalidSenderAmountFor.push(key)
|
||||||
else
|
else
|
||||||
inputVal += senderPrivKeys[key];
|
inputVal += senderPrivKeys[key];
|
||||||
let floID = floCrypto.getFloIDfromPubkeyHex(floCrypto.getPubKeyHex(key));
|
let floID = floCrypto.getFloIDfromPubkeyHex(floCrypto.getPubKeyHex(
|
||||||
|
key));
|
||||||
senders[floID] = {
|
senders[floID] = {
|
||||||
wif: key,
|
wif: key,
|
||||||
coins: senderPrivKeys[key]
|
coins: senderPrivKeys[key]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}catch(error){
|
} catch (error) {
|
||||||
invalids.InvalidSenderPrivKeys.push(key)
|
invalids.InvalidSenderPrivKeys.push(key)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -7550,9 +7555,10 @@ Bitcoin.Util = {
|
|||||||
if (Object.keys(invalids).length)
|
if (Object.keys(invalids).length)
|
||||||
return reject(invalids);
|
return reject(invalids);
|
||||||
//Reject if given inputVal and outputVal are not equal
|
//Reject if given inputVal and outputVal are not equal
|
||||||
if(!preserveRatio && inputVal != outputVal)
|
if (!preserveRatio && inputVal != outputVal)
|
||||||
return reject(`Input Amount (${inputVal}) not equal to Output Amount (${outputVal})`)
|
return reject(
|
||||||
}catch(error){
|
`Input Amount (${inputVal}) not equal to Output Amount (${outputVal})`)
|
||||||
|
} catch (error) {
|
||||||
return reject(error)
|
return reject(error)
|
||||||
}
|
}
|
||||||
//Get balance of senders
|
//Get balance of senders
|
||||||
@ -7564,18 +7570,22 @@ Bitcoin.Util = {
|
|||||||
totalFee = floGlobals.fee,
|
totalFee = floGlobals.fee,
|
||||||
balance = {};
|
balance = {};
|
||||||
//Divide fee among sender if not for preserveRatio
|
//Divide fee among sender if not for preserveRatio
|
||||||
if(!preserveRatio)
|
if (!preserveRatio)
|
||||||
var dividedFee = totalFee / Object.keys(senders).length;
|
var dividedFee = totalFee / Object.keys(senders).length;
|
||||||
//Check if balance of each sender is sufficient enough
|
//Check if balance of each sender is sufficient enough
|
||||||
let insufficient = [];
|
let insufficient = [];
|
||||||
for (let floID in senders) {
|
for (let floID in senders) {
|
||||||
balance[floID] = parseFloat(results.shift());
|
balance[floID] = parseFloat(results.shift());
|
||||||
if (isNaN(balance[floID]) || (preserveRatio && balance[floID] <= totalFee) || (!preserveRatio && balance[floID] < senders[floID].coins + dividedFee))
|
if (isNaN(balance[floID]) || (preserveRatio && balance[floID] <=
|
||||||
|
totalFee) || (!preserveRatio && balance[floID] < senders[floID]
|
||||||
|
.coins + dividedFee))
|
||||||
insufficient.push(floID)
|
insufficient.push(floID)
|
||||||
totalBalance += balance[floID];
|
totalBalance += balance[floID];
|
||||||
}
|
}
|
||||||
if (insufficient.length)
|
if (insufficient.length)
|
||||||
return reject({InsufficientBalance: insufficient})
|
return reject({
|
||||||
|
InsufficientBalance: insufficient
|
||||||
|
})
|
||||||
//Calculate totalSentAmount and check if totalBalance is sufficient
|
//Calculate totalSentAmount and check if totalBalance is sufficient
|
||||||
let totalSendAmt = totalFee;
|
let totalSendAmt = totalFee;
|
||||||
for (floID in receivers)
|
for (floID in receivers)
|
||||||
@ -7592,10 +7602,10 @@ Bitcoin.Util = {
|
|||||||
for (floID in senders) {
|
for (floID in senders) {
|
||||||
let utxos = results.shift();
|
let utxos = results.shift();
|
||||||
let sendAmt;
|
let sendAmt;
|
||||||
if(preserveRatio){
|
if (preserveRatio) {
|
||||||
let ratio = (balance[floID] / totalBalance);
|
let ratio = (balance[floID] / totalBalance);
|
||||||
sendAmt = totalSendAmt * ratio;
|
sendAmt = totalSendAmt * ratio;
|
||||||
} else
|
} else
|
||||||
sendAmt = senders[floID].coins + dividedFee;
|
sendAmt = senders[floID].coins + dividedFee;
|
||||||
let wif = senders[floID].wif;
|
let wif = senders[floID].wif;
|
||||||
let utxoAmt = 0.0;
|
let utxoAmt = 0.0;
|
||||||
@ -7616,7 +7626,7 @@ Bitcoin.Util = {
|
|||||||
}
|
}
|
||||||
for (floID in receivers)
|
for (floID in receivers)
|
||||||
trx.addoutput(floID, receivers[floID]);
|
trx.addoutput(floID, receivers[floID]);
|
||||||
trx.addflodata(floData.replace(/\n/g,' '));
|
trx.addflodata(floData.replace(/\n/g, ' '));
|
||||||
for (let i = 0; i < wifSeq.length; i++)
|
for (let i = 0; i < wifSeq.length; i++)
|
||||||
trx.signinput(i, wifSeq[i], 1);
|
trx.signinput(i, wifSeq[i], 1);
|
||||||
var signedTxHash = trx.serialize();
|
var signedTxHash = trx.serialize();
|
||||||
@ -7683,7 +7693,7 @@ Bitcoin.Util = {
|
|||||||
filter : custom filter funtion for floData (eg . filter: d => {return d[0] == '$'})
|
filter : custom filter funtion for floData (eg . filter: d => {return d[0] == '$'})
|
||||||
*/
|
*/
|
||||||
readData: function (addr, options = {}) {
|
readData: function (addr, options = {}) {
|
||||||
options.limit = options.limit | 1000
|
options.limit = options.limit | 0
|
||||||
options.ignoreOld = options.ignoreOld | 0
|
options.ignoreOld = options.ignoreOld | 0
|
||||||
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 => {
|
||||||
@ -7698,13 +7708,17 @@ Bitcoin.Util = {
|
|||||||
if (options.sentOnly && response.items[i].vin[0].addr !==
|
if (options.sentOnly && response.items[i].vin[0].addr !==
|
||||||
addr)
|
addr)
|
||||||
continue;
|
continue;
|
||||||
if (options.pattern && !response.items[i].floData
|
if (options.pattern) {
|
||||||
.startsWith(options.pattern, 0) && !response.items[i]
|
try {
|
||||||
.floData.startsWith(options.pattern, 2))
|
let jsonContent = JSON.parse(response.items[i]
|
||||||
continue;
|
.floData)
|
||||||
if (options.contains && !response.items[i].floData.includes(
|
if (!Object.keys(jsonContent).includes(options
|
||||||
options.contains))
|
.pattern))
|
||||||
continue;
|
continue;
|
||||||
|
} catch (error) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
if (options.filter && !options.filter(response.items[i]
|
if (options.filter && !options.filter(response.items[i]
|
||||||
.floData))
|
.floData))
|
||||||
continue;
|
continue;
|
||||||
@ -8606,7 +8620,9 @@ Bitcoin.Util = {
|
|||||||
floGlobals.generalData[filterStr].push({
|
floGlobals.generalData[filterStr].push({
|
||||||
sender: dataSet[vc].senderID,
|
sender: dataSet[vc].senderID,
|
||||||
vectorClock: vc,
|
vectorClock: vc,
|
||||||
message: dataSet[vc].message
|
message: dataSet[vc].message,
|
||||||
|
sign: dataSet[vc].sign,
|
||||||
|
pubKey: dataSet[vc].pubKey
|
||||||
})
|
})
|
||||||
compactIDB.writeData("generalData", floGlobals.generalData[filterStr], filterStr)
|
compactIDB.writeData("generalData", floGlobals.generalData[filterStr], filterStr)
|
||||||
floGlobals.generalVC[filterStr] = vc
|
floGlobals.generalVC[filterStr] = vc
|
||||||
@ -8660,6 +8676,10 @@ Bitcoin.Util = {
|
|||||||
//send General Data
|
//send General Data
|
||||||
sendGeneralData: function (message, type, options = {}) {
|
sendGeneralData: function (message, type, options = {}) {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
|
if(options.encrypt){
|
||||||
|
let encryptionKey = (options.encrypt === true) ? floGlobals.settings.encryptionKey : options.encrypt
|
||||||
|
message = floCrypto.encryptData(JSON.stringify(message), encryptionKey)
|
||||||
|
}
|
||||||
this.sendApplicationData(message, type, options)
|
this.sendApplicationData(message, type, options)
|
||||||
.then(result => resolve(result))
|
.then(result => resolve(result))
|
||||||
.catch(error => reject(error))
|
.catch(error => reject(error))
|
||||||
@ -8772,6 +8792,7 @@ Bitcoin.Util = {
|
|||||||
credentials: {},
|
credentials: {},
|
||||||
//for Dapps
|
//for Dapps
|
||||||
subAdmins: {},
|
subAdmins: {},
|
||||||
|
settings: {},
|
||||||
appObjects: {},
|
appObjects: {},
|
||||||
vectorClock: {},
|
vectorClock: {},
|
||||||
generalData: {},
|
generalData: {},
|
||||||
@ -8823,7 +8844,7 @@ Bitcoin.Util = {
|
|||||||
})
|
})
|
||||||
},
|
},
|
||||||
|
|
||||||
readSubAdminListFromAPI: function () {
|
readAppConfigFromAPI: function () {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
compactIDB.readData("lastTx", floGlobals.adminID).then(lastTx => {
|
compactIDB.readData("lastTx", floGlobals.adminID).then(lastTx => {
|
||||||
floBlockchainAPI.readData(floGlobals.adminID, {
|
floBlockchainAPI.readData(floGlobals.adminID, {
|
||||||
@ -8834,6 +8855,8 @@ Bitcoin.Util = {
|
|||||||
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")
|
||||||
|
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++)
|
||||||
@ -8844,12 +8867,21 @@ Bitcoin.Util = {
|
|||||||
.length; k++)
|
.length; k++)
|
||||||
compactIDB.writeData("subAdmins", true,
|
compactIDB.writeData("subAdmins", true,
|
||||||
content.addSubAdmin[k]);
|
content.addSubAdmin[k]);
|
||||||
|
if (content.settings)
|
||||||
|
for (let l in content.settings)
|
||||||
|
compactIDB.writeData("settings", content
|
||||||
|
.settings[l], l)
|
||||||
}
|
}
|
||||||
compactIDB.writeData("lastTx", result.totalTxs,
|
compactIDB.writeData("lastTx", result.totalTxs,
|
||||||
floGlobals.adminID);
|
floGlobals.adminID);
|
||||||
compactIDB.readAllData("subAdmins").then(result => {
|
compactIDB.readAllData("subAdmins").then(result => {
|
||||||
floGlobals.subAdmins = Object.keys(result);
|
floGlobals.subAdmins = Object.keys(result);
|
||||||
resolve("Read subAdmins from blockchain");
|
compactIDB.readAllData("settings").then(
|
||||||
|
result => {
|
||||||
|
floGlobals.settings = result;
|
||||||
|
resolve(
|
||||||
|
"Read app configuration from blockchain");
|
||||||
|
})
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
}).catch(error => reject(error))
|
}).catch(error => reject(error))
|
||||||
@ -8949,7 +8981,7 @@ Bitcoin.Util = {
|
|||||||
JSON.stringify(resultIndexes))
|
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,
|
var randomThreshold = floCrypto.randInt(10,
|
||||||
20)
|
20)
|
||||||
writeSharesToIDB(floCrypto
|
writeSharesToIDB(floCrypto
|
||||||
@ -8964,32 +8996,33 @@ Bitcoin.Util = {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
const checkIfPinRequired = function(key){
|
const checkIfPinRequired = function (key) {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
if(key.length == 52)
|
if (key.length == 52)
|
||||||
resolve(key)
|
resolve(key)
|
||||||
else {
|
else {
|
||||||
inputFn("PIN/Password").then(pwd => {
|
inputFn("PIN/Password").then(pwd => {
|
||||||
try{
|
try {
|
||||||
let privKey = Crypto.AES.decrypt(key, pwd);
|
let privKey = Crypto.AES.decrypt(key, pwd);
|
||||||
resolve(privKey)
|
resolve(privKey)
|
||||||
}catch(error){
|
} catch (error) {
|
||||||
reject("Access Denied: Incorrect PIN/Password")
|
reject("Access Denied: Incorrect PIN/Password")
|
||||||
}
|
}
|
||||||
}).catch(error => reject("Access Denied: PIN/Password required"))
|
}).catch(error => reject(
|
||||||
}
|
"Access Denied: PIN/Password required"))
|
||||||
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
getPrivateKeyCredentials().then(key => {
|
getPrivateKeyCredentials().then(key => {
|
||||||
checkIfPinRequired(key).then(privKey => {
|
checkIfPinRequired(key).then(privKey => {
|
||||||
try{
|
try {
|
||||||
myPrivKey = privKey
|
myPrivKey = privKey
|
||||||
myPubKey = floCrypto.getPubKeyHex(myPrivKey)
|
myPubKey = floCrypto.getPubKeyHex(myPrivKey)
|
||||||
myFloID = floCrypto.getFloIDfromPubkeyHex(myPubKey)
|
myFloID = floCrypto.getFloIDfromPubkeyHex(myPubKey)
|
||||||
resolve('Login Credentials loaded successful')
|
resolve('Login Credentials loaded successful')
|
||||||
}catch(error){
|
} catch (error) {
|
||||||
reject("Corrupted Private Key")
|
reject("Corrupted Private Key")
|
||||||
}
|
}
|
||||||
}).catch(error => reject(error))
|
}).catch(error => reject(error))
|
||||||
@ -9004,13 +9037,13 @@ Bitcoin.Util = {
|
|||||||
this.callStartUpFunction.completed += 1
|
this.callStartUpFunction.completed += 1
|
||||||
reactor.dispatchEvent("startUpSuccessLog",
|
reactor.dispatchEvent("startUpSuccessLog",
|
||||||
`${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
|
||||||
reactor.dispatchEvent("startUpErrorLog",
|
reactor.dispatchEvent("startUpErrorLog",
|
||||||
`${error}\nFailed ${this.callStartUpFunction.failed}/${this.callStartUpFunction.total} Startup functions`
|
`${error}\nFailed ${this.callStartUpFunction.failed}/${this.callStartUpFunction.total} Startup functions`
|
||||||
)
|
)
|
||||||
reject(false)
|
reject(false)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
@ -9060,8 +9093,10 @@ Bitcoin.Util = {
|
|||||||
|
|
||||||
manageSubAdmins(adminPrivKey, addList, rmList) {
|
manageSubAdmins(adminPrivKey, addList, rmList) {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
if (!Array.isArray(addList)) addList = undefined;
|
if (!Array.isArray(addList) || !addList.length) addList = undefined;
|
||||||
if (!Array.isArray(rmList)) rmList = undefined;
|
if (!Array.isArray(rmList) || !rmList.length) rmList = undefined;
|
||||||
|
if (!addList && !rmList)
|
||||||
|
return reject("subAdmin manage list is empty")
|
||||||
var floData = {
|
var floData = {
|
||||||
[floGlobals.application]: {
|
[floGlobals.application]: {
|
||||||
addSubAdmin: addList,
|
addSubAdmin: addList,
|
||||||
@ -9078,6 +9113,25 @@ Bitcoin.Util = {
|
|||||||
})
|
})
|
||||||
},
|
},
|
||||||
|
|
||||||
|
setApplicationSettings(adminPrivKey, settings = {}) {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
if (!settings || typeof settings !== "object")
|
||||||
|
return reject("Settings must be object")
|
||||||
|
var floData = {
|
||||||
|
[floGlobals.application]: {
|
||||||
|
settings: settings
|
||||||
|
}
|
||||||
|
}
|
||||||
|
var floID = floCrypto.getFloIDfromPubkeyHex(floCrypto.getPubKeyHex(adminPrivKey))
|
||||||
|
if (floID != floGlobals.adminID)
|
||||||
|
reject('Access Denied for Admin privilege')
|
||||||
|
else
|
||||||
|
floBlockchainAPI.writeData(floID, JSON.stringify(floData), adminPrivKey)
|
||||||
|
.then(result => resolve(['Updated app settings', result]))
|
||||||
|
.catch(error => reject(error))
|
||||||
|
})
|
||||||
|
},
|
||||||
|
|
||||||
clearCredentials: function () {
|
clearCredentials: function () {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
compactIDB.clearData('credentials').then(result => {
|
compactIDB.clearData('credentials').then(result => {
|
||||||
@ -9088,18 +9142,19 @@ Bitcoin.Util = {
|
|||||||
})
|
})
|
||||||
},
|
},
|
||||||
|
|
||||||
securePrivKey: function(pwd){
|
securePrivKey: function (pwd) {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
let indexArr = localStorage.getItem(`${floGlobals.application}#privKey`)
|
let indexArr = localStorage.getItem(`${floGlobals.application}#privKey`)
|
||||||
if(!indexArr)
|
if (!indexArr)
|
||||||
return reject("PrivKey not found");
|
return reject("PrivKey not found");
|
||||||
indexArr = JSON.parse(indexArr)
|
indexArr = JSON.parse(indexArr)
|
||||||
let encryptedKey = Crypto.AES.encrypt(myPrivKey, pwd);
|
let encryptedKey = Crypto.AES.encrypt(myPrivKey, pwd);
|
||||||
let threshold = indexArr.length;
|
let threshold = indexArr.length;
|
||||||
let shares = floCrypto.createShamirsSecretShares(encryptedKey, threshold, threshold)
|
let shares = floCrypto.createShamirsSecretShares(encryptedKey, threshold, threshold)
|
||||||
let promises = [];
|
let promises = [];
|
||||||
for(var i=0; i<threshold;i++)
|
for (var i = 0; i < threshold; i++)
|
||||||
promises.push(compactIDB.writeData("credentials", shares[i], indexArr[i], floGlobals.application));
|
promises.push(compactIDB.writeData("credentials", shares[i], indexArr[i], floGlobals
|
||||||
|
.application));
|
||||||
Promise.all(promises)
|
Promise.all(promises)
|
||||||
.then(results => resolve("Private Key Secured"))
|
.then(results => resolve("Private Key Secured"))
|
||||||
.catch(error => reject(error))
|
.catch(error => reject(error))
|
||||||
@ -9122,7 +9177,25 @@ Bitcoin.Util = {
|
|||||||
var filteredResult = []
|
var filteredResult = []
|
||||||
for (var i = 0; i < floGlobals.generalData[filter].length; i++)
|
for (var i = 0; i < floGlobals.generalData[filter].length; i++)
|
||||||
if (floGlobals.generalData[filter][i].vectorClock > vectorClock)
|
if (floGlobals.generalData[filter][i].vectorClock > vectorClock)
|
||||||
filteredResult.push(floGlobals.generalData[filter][i])
|
filteredResult.push(JSON.parse(JSON.stringify(floGlobals.generalData[filter][i])))
|
||||||
|
if (options.decrypt) {
|
||||||
|
let decryptionKey = (options.decrypt === true) ? myPrivKey : options.decrypt;
|
||||||
|
if (!Array.isArray(decryptionKey))
|
||||||
|
decryptionKey = [decryptionKey];
|
||||||
|
filteredResult.forEach(data => {
|
||||||
|
try {
|
||||||
|
if ("secret" in data.message && "senderPublicKeyString" 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) {}
|
||||||
|
})
|
||||||
|
}
|
||||||
return filteredResult
|
return filteredResult
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user