Updated documentation in docs folder

Updated documentation in docs folder

Updated documentation in docs folder

Updated documentation in docs folder

Updated documentation in docs folder

Updated documentation in docs folder

Updated documentation in docs folder

Updated documentation in docs folder

Updated documentation in docs folder

Updated documentation in docs folder

Updated documentation in docs folder

Added documentation for floCrypto.js
This commit is contained in:
tripathyr 2023-10-03 12:41:09 +05:30
parent 945eaffe8c
commit 0d6c9f5fbe
15 changed files with 4730 additions and 6 deletions

View File

@ -72,7 +72,6 @@ Do not lose the private key. Copy and save it securely. Once a private key is lo
- [Product Overview](docs/product-overview.md)
- [Features](docs/features.md)
- [Usage](docs/usage.md)
- [Technical Documentation](docs/technical-documentation.md)
- [Functions](docs/functions.md)
- [Technical Architecture](docs/technical-architecture.md)
- [Additional Resources](docs/additional-resources.md)

View File

@ -0,0 +1,6 @@
## Additional Resources
### Please refer the following for explanation of non messenger files
- RanchiMall Standard Operations
- RanchiMall Standard UI
- RanchiMall Single User BTC Wallet

2
docs/changelog.md Normal file
View File

@ -0,0 +1,2 @@
### Important Changes
- Added Bitcoin Transaction fee increase update capability for multisig if the transaction is not getting confirmed.

400
docs/compactIDB.md Normal file
View File

@ -0,0 +1,400 @@
## upgradeDB Function
The `upgradeDB` function is used to upgrade an IndexedDB database to a new version. It allows creating and deleting object stores and indexes during the upgrade process.
### Function Parameters
- **dbName**: The name of the IndexedDB database to be upgraded.
- **createList**: An object specifying the object stores to create and their options. Each key represents the object store name, and the corresponding value is an object with optional `options` for the object store and `indexes` for creating indexes.
- **deleteList**: An array containing the names of object stores to be deleted during the upgrade.
### Function Logic
1. **Getting Current Version:** Retrieves the current version of the IndexedDB database using the `getDBversion` function.
2. **Opening a New Database:** Opens a new version of the IndexedDB database (version + 1).
3. **Upgrade Logic:** Handles the upgrade process inside the `onupgradeneeded` event. It creates new object stores and indexes based on the provided `createList` and deletes specified object stores from `deleteList`.
4. **Success and Error Handling:** Resolves with a success message when the upgrade is completed successfully. Rejects with an error message if there's an error in opening the IndexedDB.
### Return Value
- Returns a Promise that resolves with a success message when the database upgrade is completed successfully.
### Example Usage
- In this example, the upgradeDB function is used to upgrade the 'exampleDB' IndexedDB. It creates new object stores ('users' and 'posts') with specified options and indexes, and it deletes the 'oldStore' object store.
```javascript
const dbName = 'exampleDB';
const createList = {
'users': {
options: { keyPath: 'id', autoIncrement: true },
indexes: { 'username': 'username' }
},
'posts': {
options: { keyPath: 'postId', autoIncrement: true },
indexes: { 'author': 'authorId' }
}
};
const deleteList = ['oldStore'];
upgradeDB(dbName, createList, deleteList)
.then(result => console.log(result))
.catch(error => console.error(error));
// Output: Database upgraded
```
## compactIDB.initDB Function
The `compactIDB.initDB` function is used to initialize an IndexedDB database with specified object stores. It checks the existing object stores in the database and creates new ones and deletes unwanted ones based on the provided `objectStores` parameter.
### Function Parameters
- **dbName**: The name of the IndexedDB database to be initialized.
- **objectStores**: An object specifying the object stores to be created. Each key represents the object store name, and the corresponding value is an object with optional `options` for the object store.
### Function Logic
1. **Opening Existing Database:** Opens the existing IndexedDB database specified by `dbName`.
2. **Object Store Handling:** Compares the existing object stores with the specified `objectStores`. It creates new object stores that are not present in the database and deletes object stores that are not specified in `objectStores`.
3. **Upgrade Process:** Uses the `upgradeDB` function to handle the upgrade process, creating new object stores and deleting unwanted object stores.
4. **Success and Error Handling:** Resolves with a success message when the database initialization is completed successfully. Rejects with an error message if there's an error in opening the IndexedDB.
### Return Value
- Returns a Promise that resolves with a success message when the database initialization is completed successfully.
### Example Usage
- In this example, the compactIDB.initDB function is used to initialize the 'exampleDB' IndexedDB. It creates new object stores ('users' and 'posts') with specified options and indexes.
```javascript
const dbName = 'exampleDB';
const objectStores = {
'users': {
options: { keyPath: 'id', autoIncrement: true },
indexes: { 'username': 'username' }
},
'posts': {
options: { keyPath: 'postId', autoIncrement: true },
indexes: { 'author': 'authorId' }
}
};
compactIDB.initDB(dbName, objectStores)
.then(result => console.log(result))
.catch(error => console.error(error));
// Output: Initiated IndexedDB
```
## compactIDB.openDB Function
The `compactIDB.openDB` function is used to open an IndexedDB database for performing database operations.
### Function Parameters
- **dbName** (Optional): The name of the IndexedDB database to open. If not provided, the default database specified during initialization is used.
### Function Logic
1. **Opening Database:** Attempts to open the specified IndexedDB database (`dbName`).
2. **Error Handling:** If there's an error in opening the database, the function rejects the promise with an error message indicating the failure.
3. **Upgradeneeded Event:** If an "upgradeneeded" event is triggered during the database opening process, the function closes the existing database, deletes the database using `deleteDB` function, and rejects the promise with a message indicating that the database was not found.
4. **Success Event:** If the database is successfully opened, the function resolves with the opened database object for performing further database operations.
### Return Value
- Returns a Promise that resolves with the opened IndexedDB database object or rejects with an error message if there's an issue opening the database.
### Example Usage
```javascript
const dbName = 'myDatabase';
compactIDB.openDB(dbName)
.then(database => {
// Perform database operations using the 'database' object.
console.log(`Successfully opened database: ${dbName}`);
})
.catch(error => {
console.error(`Error opening database: ${error}`);
});
// Output: Successfully opened database: myDatabase
// Opens the 'myDatabase' IndexedDB database and performs operations inside the 'then' block.
```
## compactIDB.deleteDB Function
The `compactIDB.deleteDB` function is used to delete an existing IndexedDB database.
### Function Parameters
- **dbName** (Optional): The name of the IndexedDB database to be deleted. If not provided, the default database specified during initialization is used.
### Function Logic
1. **Deleting Database:** Initiates a request to delete the specified IndexedDB database (`dbName`).
2. **Error Handling:** If there's an error during the deletion process, the function rejects the promise with an error message indicating the failure.
3. **Success Event:** If the database is successfully deleted, the function resolves with a success message indicating that the database was deleted successfully.
### Return Value
- Returns a Promise that resolves with a success message if the database is deleted successfully or rejects with an error message if there's an issue deleting the database.
### Example Usage
```javascript
const dbName = 'myDatabase';
compactIDB.deleteDB(dbName)
.then(message => {
console.log(message); // Output: Database deleted successfully
})
.catch(error => {
console.error(`Error deleting database: ${error}`);
});
// Output: Database deleted successfully
// Deletes the 'myDatabase' IndexedDB database and logs a success message if the deletion is successful.
```
## compactIDB.writeData Function
The `compactIDB.writeData` function is used to write data to a specified object store in the IndexedDB. It allows adding or updating data records in the specified object store.
### Function Parameters
- **obsName**: The name of the object store where the data will be written.
- **data**: The data to be written to the object store.
- **key** (Optional): The key to identify the data record. If provided, the function updates the existing record with the specified key. If not provided, a new record is added to the object store.
- **dbName** (Optional): The name of the IndexedDB database where the object store is located. If not provided, the default database specified during initialization is used.
### Function Logic
1. **Opening Database:** Opens the specified IndexedDB database (`dbName`).
2. **Transaction and Object Store:** Starts a read-write transaction on the specified object store (`obsName`).
3. **Writing Data:** Writes the provided `data` to the object store. If a `key` is provided, it updates the existing record; otherwise, it adds a new record.
4. **Success and Error Handling:** Resolves with a success message when the data writing is successful. Rejects with an error message if there's an error during the write operation.
### Return Value
- Returns a Promise that resolves with a success message when the data writing is completed successfully.
### Example Usage
```javascript
const obsName = 'users';
const data = { id: 1, name: 'John Doe', email: 'john@example.com' };
compactIDB.writeData(obsName, data, 1)
.then(result => console.log(result))
.catch(error => console.error(error));
// Output: Write data Successful
// Updating an existing record with key 1 in the 'users' object store.
```
## compactIDB.addData Function
The `compactIDB.addData` function is used to add new data records to a specified object store in the IndexedDB. It allows adding data records with unique keys, ensuring no duplicate records with the same key are added.
### Function Parameters
- **obsName**: The name of the object store where the data will be added.
- **data**: The data to be added to the object store.
- **key** (Optional): The key to identify the new data record. If provided and a record with the same key already exists, the function fails, ensuring the uniqueness of the key. If not provided, the function generates a unique key for the new record.
- **dbName** (Optional): The name of the IndexedDB database where the object store is located. If not provided, the default database specified during initialization is used.
### Function Logic
1. **Opening Database:** Opens the specified IndexedDB database (`dbName`).
2. **Transaction and Object Store:** Starts a read-write transaction on the specified object store (`obsName`).
3. **Adding Data:** Adds the provided `data` to the object store. If a `key` is provided and a record with the same key already exists, the add operation fails. If no `key` is provided, the function generates a unique key for the new record.
4. **Success and Error Handling:** Resolves with a success message when the data addition is successful. Rejects with an error message if there's an error during the add operation, such as attempting to add a duplicate record with an existing key.
### Return Value
- Returns a Promise that resolves with a success message when the data addition is completed successfully.
### Example Usage
```javascript
const obsName = 'users';
const data = { id: 2, name: 'Alice Smith', email: 'alice@example.com' };
compactIDB.addData(obsName, data, 2)
.then(result => console.log(result))
.catch(error => console.error(error));
// Output: Add data successful
// Adding a new record with key 2 to the 'users' object store.
```
## compactIDB.removeData Function
The `compactIDB.removeData` function is used to remove a data record from a specified object store in the IndexedDB based on its key.
### Function Parameters
- **obsName**: The name of the object store from which the data record will be removed.
- **key**: The key of the data record that needs to be removed from the object store.
- **dbName** (Optional): The name of the IndexedDB database where the object store is located. If not provided, the default database specified during initialization is used.
### Function Logic
1. **Opening Database:** Opens the specified IndexedDB database (`dbName`).
2. **Transaction and Object Store:** Starts a read-write transaction on the specified object store (`obsName`).
3. **Removing Data:** Removes the data record with the provided `key` from the object store.
4. **Success and Error Handling:** Resolves with a success message, including the removed key, when the removal is successful. Rejects with an error message if there's an error during the delete operation, such as attempting to remove a non-existent record.
### Return Value
- Returns a Promise that resolves with a success message, including the removed key, when the removal is completed successfully.
### Example Usage
- In this example, the compactIDB.removeData function is used to remove the data record with key 2 from the 'users' object store in the IndexedDB.
```javascript
const obsName = 'users';
const key = 2;
compactIDB.removeData(obsName, key)
.then(result => console.log(result))
.catch(error => console.error(error));
// Output: Removed Data 2
// Removes the data record with key 2 from the 'users' object store.
```
## compactIDB.clearData Function
The `compactIDB.clearData` function is used to clear all data records from a specified object store in the IndexedDB.
### Function Parameters
- **obsName**: The name of the object store from which all data records will be cleared.
- **dbName** (Optional): The name of the IndexedDB database where the object store is located. If not provided, the default database specified during initialization is used.
### Function Logic
1. **Opening Database:** Opens the specified IndexedDB database (`dbName`).
2. **Transaction and Object Store:** Starts a read-write transaction on the specified object store (`obsName`).
3. **Clearing Data:** Removes all data records from the object store, effectively clearing it.
4. **Success and Error Handling:** Resolves with a success message when the clear operation is successful. Rejects with an error message if there's an error during the clear operation.
### Return Value
- Returns a Promise that resolves with a success message when the clear operation is completed successfully.
### Example Usage
```javascript
const obsName = 'users';
compactIDB.clearData(obsName)
.then(result => console.log(result))
.catch(error => console.error(error));
// Output: Clear data Successful
// Clears all data records from the 'users' object store.
```
## compactIDB.readData Function
The `compactIDB.readData` function is used to read a specific data record from an object store in the IndexedDB.
### Function Parameters
- **obsName**: The name of the object store from which the data record will be read.
- **key**: The key of the specific data record to be retrieved from the object store.
- **dbName** (Optional): The name of the IndexedDB database where the object store is located. If not provided, the default database specified during initialization is used.
### Function Logic
1. **Opening Database:** Opens the specified IndexedDB database (`dbName`).
2. **Transaction and Object Store:** Starts a read-only transaction on the specified object store (`obsName`).
3. **Reading Data:** Retrieves the data record corresponding to the provided key from the object store.
4. **Success and Error Handling:** Resolves with the retrieved data record when the read operation is successful. Rejects with an error message if there's an error during the read operation.
### Return Value
- Returns a Promise that resolves with the retrieved data record when the read operation is completed successfully.
### Example Usage
```javascript
const obsName = 'users';
const userID = 123;
compactIDB.readData(obsName, userID)
.then(data => console.log(data))
.catch(error => console.error(error));
// Output: { id: 123, name: 'John Doe', ... }
// Retrieves the data record with the key 123 from the 'users' object store.
```
## compactIDB.readAllData Function
The `compactIDB.readAllData` function is used to retrieve all data records from an object store in the IndexedDB.
### Function Parameters
- **obsName**: The name of the object store from which all data records will be retrieved.
- **dbName** (Optional): The name of the IndexedDB database where the object store is located. If not provided, the default database specified during initialization is used.
### Function Logic
1. **Opening Database:** Opens the specified IndexedDB database (`dbName`).
2. **Transaction and Object Store:** Starts a read-only transaction on the specified object store (`obsName`).
3. **Reading All Data:** Iterates over the object store using a cursor and collects all data records into a temporary result object.
4. **Success and Error Handling:** Resolves with the temporary result object containing all data records when the read operation is successful. Rejects with an error message if there's an error during the read operation.
### Return Value
- Returns a Promise that resolves with an object containing all retrieved data records when the read operation is completed successfully.
### Example Usage
```javascript
const obsName = 'users';
compactIDB.readAllData(obsName)
.then(data => console.log(data))
.catch(error => console.error(error));
// Output: { 123: { id: 123, name: 'John Doe', ... }, 124: { id: 124, name: 'Jane Smith', ... }, ... }
// Retrieves all data records from the 'users' object store and logs the result.
```

7
docs/features.md Normal file
View File

@ -0,0 +1,7 @@
## Features
- Ability to send messages to Bitcoin addresses
- Ability to co-ordinate Bitcoin Multisig Creation
- Ability to create messaging group of Bitcoin IDs
- Ability to add and remove Bitcoin ID as contact
- Ability to send direct messages, and mails
- Attachments are not supported yet

1204
docs/floBlockchainAPI.md Normal file

File diff suppressed because it is too large Load Diff

968
docs/floCloud.md Normal file
View File

@ -0,0 +1,968 @@
## ws_connect Function
The `ws_connect` function is used to establish a WebSocket connection to a specified supernode (`snID`). It performs checks to ensure that the supernode is in the list of available supernodes and is active before attempting to establish a connection.
### Parameters
- `snID` (string): The ID of the supernode to which the WebSocket connection will be established.
### Return Value
- Returns a Promise that resolves with the WebSocket connection object if the connection is successfully established, and rejects with an error message if the specified supernode is not in the list of available supernodes or is inactive.
### Example Usage
- In this example, the ws_connect function establishes a WebSocket connection to the specified supernode (snID). It checks if the supernode is available and active before attempting to establish the connection. Once the connection is established, the function resolves with the WebSocket connection object, allowing communication with the server in real-time.
```javascript
const snID = "exampleSnID";
ws_connect(snID)
.then(wsConnection => {
console.log("WebSocket connection established:", wsConnection);
// You can now use wsConnection to send and receive messages.
})
.catch(error => {
console.error("Error occurred during WebSocket connection:", error);
});
```
## ws_activeConnect Function
The `ws_activeConnect` function is used to establish an active WebSocket connection to a supernode, handling failover by selecting the next or previous active supernode from the routing table (`kBucket`).
### Parameters
- `snID` (string): The ID of the supernode to which the WebSocket connection will be established. If the provided supernode is inactive, the function selects the next or previous active supernode based on the `reverse` parameter.
- `reverse` (boolean, optional): A flag indicating whether to select the previous active supernode (`true`) or the next active supernode (`false`). Default is `false`.
### Return Value
- Returns a Promise that resolves with the active WebSocket connection object if the connection is successfully established, and rejects with an error message if all supernodes are inactive or if all attempts to establish an active connection fail.
### Example Usage
- In this example, the ws_activeConnect function establishes an active WebSocket connection to the specified supernode (snID). If the specified supernode is inactive, it selects the next or previous active supernode based on the reverse parameter. The function handles failover by attempting to connect to the active supernodes in the routing table until a successful connection is established, allowing real-time communication with the server.
```javascript
const snID = "exampleSnID";
ws_activeConnect(snID)
.then(wsConnection => {
console.log("Active WebSocket connection established:", wsConnection);
// You can now use wsConnection to send and receive messages in real-time.
})
.catch(error => {
console.error("Error occurred during active WebSocket connection:", error);
});
ws_activeConnect(snID, true) // To establish a connection to the previous active supernode
.then(wsConnection => {
console.log("Active WebSocket connection established:", wsConnection);
// You can now use wsConnection to send and receive messages in real-time.
})
.catch(error => {
console.error("Error occurred during active WebSocket connection:", error);
});
```
## fetch_API Function
The `fetch_API` function is used to send an HTTP request to the specified supernode (`snID`). It allows making GET and POST requests and handles response validation.
### Parameters
- `snID` (string): The ID of the supernode to which the request will be sent.
- `data` (string or object): The data to be sent with the request. If it is a string, it is appended to the URL as query parameters for GET requests. If it is an object with `method` property set to `"POST"`, it is sent as the body for a POST request.
### Return Value
- Returns a Promise that resolves with the response object if the request is successful (HTTP status code 200 or 400 or 500), and rejects with an error message if the request fails.
### Example Usage
- In this example, the fetch_API function sends an HTTP request to the specified supernode (snID). It handles both GET and POST requests and provides flexibility in sending data with the request. The function validates the response and resolves or rejects the Promise based on the response status code.
```javascript
const snID = "exampleSnID";
const queryParams = "param1=value1&param2=value2";
fetch_API(snID, queryParams)
.then(response => {
console.log("GET request successful. Response:", response);
})
.catch(error => {
console.error("Error occurred during the GET request:", error);
});
const postData = {
method: "POST",
body: JSON.stringify({ key: "value" })
};
fetch_API(snID, postData)
.then(response => {
console.log("POST request successful. Response:", response);
})
.catch(error => {
console.error("Error occurred during the POST request:", error);
});
```
## fetch_ActiveAPI Function
The `fetch_ActiveAPI` function is used to send an HTTP request to an active supernode, handling failover by selecting the next or previous active supernode from the routing table (`kBucket`).
### Parameters
- `snID` (string): The ID of the supernode to which the request will be sent. If the provided supernode is inactive, the function selects the next or previous active supernode based on the `reverse` parameter.
- `data` (string or object): The data to be sent with the request.
- `reverse` (boolean, optional): A flag indicating whether to select the previous active supernode (`true`) or the next active supernode (`false`). Default is `false`.
### Return Value
- Returns a Promise that resolves with the response object if the request is successful, and rejects with an error message if all supernodes are inactive or if all attempts to fetch from active supernodes fail.
### Example Usage
- In this example, the fetch_ActiveAPI function sends an HTTP request to an active supernode (snID). If the specified supernode is inactive, it selects the next or previous active supernode based on the reverse parameter. The function handles failover by attempting to fetch from the active supernodes in the routing table until a successful response is received.
```javascript
const snID = "exampleSnID";
const queryParams = "param1=value1&param2=value2";
fetch_ActiveAPI(snID, queryParams)
.then(response => {
console.log("Request successful. Response:", response);
})
.catch(error => {
console.error("Error occurred during the request:", error);
});
const postData = {
method: "POST",
body: JSON.stringify({ key: "value" })
};
fetch_ActiveAPI(snID, postData, true)
.then(response => {
console.log("Request successful. Response:", response);
})
.catch(error => {
console.error("Error occurred during the request:", error);
});
```
## singleRequest Function
The `singleRequest` function is used to send a single HTTP request to the specified flo server (`floID`). It allows customization of the request method and data payload.
### Parameters
- `floID` (string): The ID of the flo server to which the request will be sent.
- `data_obj` (object): The data object to be sent with the request. It will be serialized to JSON for POST requests and URL parameters for other request methods.
- `method` (string, optional): The HTTP request method. Default is `"POST"`. Can be `"POST"` or any other valid HTTP method like `"GET"`, `"PUT"`, `"DELETE"`, etc.
### Return Value
- Returns a Promise that resolves with the JSON response body if the request is successful (HTTP status code 200), and rejects with an error message if the request fails.
### Example Usage
- In this example, the singleRequest function sends a single HTTP request to the cloud server. The request method and data payload are customizable
```javascript
const floID = "exampleFloID";
const dataObj = {
key: "value",
anotherKey: "anotherValue"
};
singleRequest(floID, dataObj, "POST")
.then(response => {
console.log("POST request successful. Response:", response);
})
.catch(error => {
console.error("Error occurred during the request:", error);
});
```
## liveRequest Function
The `liveRequest` function is used to make a live request to FLO cloud node using WebSockets. It takes the following parameters:
### Parameters
- `floID` (string): The ID of the flo server.
- `request` (object): An object containing filter criteria for the live request. It can have the following properties:
- `status` (boolean, optional): If true, includes all data in the response. If false, filters the response based on other criteria.
- `trackList` (array of strings, optional): An array of keys to include in the response when `status` is false.
- `atVectorClock` (string, optional): Filters data with vector clock equal to the specified value.
- `lowerVectorClock` (string, optional): Filters data with vector clock greater than or equal to the specified value.
- `upperVectorClock` (string, optional): Filters data with vector clock less than or equal to the specified value.
- `afterTime` (number, optional): Filters data with log_time greater than the specified value.
- `application` (string, optional): Filters data with the specified application.
- `receiverID` (string, optional): Filters data with the specified receiver ID or proxy ID.
- `comment` (string, optional): Filters data with the specified comment.
- `type` (string, optional): Filters data with the specified type.
- `senderID` (array of strings, optional): Filters data with sender IDs included in the specified array.
- `callback` (function): A callback function to handle the response data and errors.
### Return Value
- Returns a Promise that resolves with a unique `randID` (string) representing the live request.
### Example Usage
- In this example, the liveRequest function connects to the specified flo server (floID), sends a live request with the provided filter criteria (request), and handles the response using the callback function.
```javascript
const floID = "exampleFloID";
const request = {
status: true,
application: "exampleApp",
callback: function(data, error) {
if (error) {
console.error("Error occurred:", error);
} else {
console.log("Filtered data received:", data);
}
}
};
liveRequest(floID, request, callback)
.then(randID => {
console.log("Live request sent with ID:", randID);
})
.catch(error => {
console.error("Error sending live request:", error);
});
```
## proxyID Function
The `proxyID` function is used to convert a given address into a proxy ID. It supports various address formats including legacy encoding, bech32 encoding, and public key hex format.
### Parameters
- `address` (string): The input address to be converted into a proxy ID.
### Return Value
- Returns a string representing the proxy ID derived from the input address.
### Address Formats Supported
- **Legacy Encoding (Base58)**
- Addresses with lengths 33 or 34 characters are supported.
- **Bech32 Encoding**
- Addresses with lengths 42 or 62 characters are supported.
- **Public Key Hex**
- Addresses with length 66 characters are supported.
### Example Usage
- In this example, the proxyID function converts a legacy Bitcoin address into a proxy ID. The function automatically detects the input address format and converts it into the corresponding proxy ID format.
```javascript
const address = "1BvBMSEYstWetqTFn5Au4m4GFg7xJaNVN2";
const proxyID = util.proxyID(address);
console.log("Proxy ID:", proxyID);
```
## updateObject Function
The `updateObject` function is used to update an object in the `appObjects` data store based on the incoming dataset. It performs actions like resetting or updating the object based on the dataset's content.
### Parameters
- `objectName` (string): The name of the object to be updated.
- `dataSet` (object): The dataset containing the updates for the specified object.
### Functionality
- The function processes the dataset for the specified object and performs the following actions:
- If the comment in the dataset is "RESET," the function resets the object with the data provided in the `message.reset` property.
- If the comment in the dataset is "UPDATE," the function updates the object by merging the changes provided in the `message.diff` property using the `diff.merge` function.
### Example Usage
In this example, the updateObject function processes the dataSet and updates the specified object (exampleObject) based on the provided reset and diff actions. The function maintains the last version control (lastVC) and stores the updated object in the appObjects data store.
```javascript
const objectName = "exampleObject";
const dataSet = {
"123": { type: "exampleObject", comment: "RESET", message: { reset: { key: "value" } } },
"456": { type: "exampleObject", comment: "UPDATE", message: { diff: { updatedKey: "updatedValue" } } }
};
updateObject(objectName, dataSet);
```
### Note
- The diff.merge function and other related functions used in the implementation are assumed to be available in the scope where this function is used.
## storeGeneral Function
The `storeGeneral` function is used to store general data entries in the `generalData` data store. It updates the data store with the provided dataset for a specific foreign key (`fk`).
### Parameters
- `fk` (string): The foreign key indicating the category or type of the general data.
- `dataSet` (object): The dataset containing the general data entries to be stored.
### Functionality
- The function updates the `generalData` data store for the specified foreign key with the entries from the provided dataset.
- It checks the `log_time` property of each entry in the dataset and updates the `lastVC` (last version control) property for the specified foreign key with the maximum log time value among the entries.
### Example Usage
- In this example, the storeGeneral function updates the generalData data store for the specified foreign key (exampleForeignKey) with the provided dataset. It also updates the lastVC property with the maximum log time value from the entries in the dataset.
```javascript
const fk = "exampleForeignKey";
const dataSet = {
"123": { log_time: 1633363200000, data: "Entry 1" },
"124": { log_time: 1633363800000, data: "Entry 2" },
// ... more data entries
};
storeGeneral(fk, dataSet);
```
### Note
Ensure that the necessary data structures and storage mechanisms, such as generalData and lastVC, are defined and available in the scope where this function is used.
## objectifier Function
The `objectifier` function is used to transform data from an array format into an object format. It takes an array of data objects as input and returns an object where the keys are taken from the `vectorClock` property of the input objects and the values are the input objects themselves with an additional property `message` that is decoded using the `decodeMessage` function.
### Parameters
- `data` (array or object): The input data to be transformed. If `data` is not an array, it will be converted into a single-element array before processing.
### Return Value
- Returns an object where keys are taken from the `vectorClock` property of the input objects, and the values are objects with the following properties:
- `vectorClock` (string): The key used in the input data.
- `message` (string): The decoded message obtained by applying the `decodeMessage` function to the `message` property of the input data.
### Example Usage
```javascript
const inputData = [
{ vectorClock: "12345", message: "Encoded Message 1" },
{ vectorClock: "67890", message: "Encoded Message 2" }
];
const transformedData = objectifier(inputData);
console.log(transformedData);
/*
Output
{
"12345": { vectorClock: "12345", message: "Decoded Message 1" },
"67890": { vectorClock: "67890", message: "Decoded Message 2" }
}
*/
```
## setStatus Function
The `setStatus` function is used to set the online status for a user specified by their `user_id` on the floCloud platform. It takes an options object as input, allowing customization of the request parameters.
### Parameters
- `options` (object, optional): An object containing the following properties:
- `callback` (function, optional): A callback function to handle the response data and errors. If not provided, the default callback function is used.
- `application` (string, optional): The application name associated with the status update. If not provided, the default application name is used.
- `refID` (string, optional): The reference ID used for the live request. If not provided, the default admin ID is used.
### Return Value
- Returns a Promise that resolves with the result of the live request upon success.
### Example Usage
- In this example, the setStatus function sets the online status for the user specified by user.id on the floCloud platform. The function allows customization of the request parameters through the options object and provides a callback function to handle the response data and errors.
```javascript
const options = {
callback: function(data, error) {
if (error) {
console.error("Error occurred:", error);
} else {
console.log("Status update successful:", data);
}
},
application: "MyApp",
refID: "admin123"
};
floCloudAPI.setStatus(options)
.then(result => {
console.log("Status set successfully:", result);
})
.catch(error => {
console.error("Error setting status:", error);
});
```
## requestStatus Function
The `requestStatus` function is used to request the status of one or more `floID`s specified in the `trackList`. It sends a live request to obtain the status of the specified `floID`s and returns the response.
### Parameters
- `trackList` (string or array of strings): The `floID`(s) for which the status will be requested. Can be a single `floID` or an array of multiple `floID`s.
- `options` (object, optional): An object containing the following properties:
- `callback` (function, optional): A callback function to handle the response data and errors. If not provided, the default callback function is used.
- `application` (string, optional): The application name associated with the status request. If not provided, the default application name is used.
- `refID` (string, optional): The reference ID used for the live request. If not provided, the default admin ID is used.
### Return Value
- Returns a Promise that resolves with the response data containing the status of the specified `floID`(s) upon success.
### Example Usage
- In this example, the requestStatus function sends a live request to obtain the status of the floID(s) specified in the trackList. The function allows customization of the request parameters through the options object and provides a callback function to handle the response data and errors.
```javascript
const trackList = ["floID1", "floID2", "floID3"];
const options = {
callback: function(data, error) {
if (error) {
console.error("Error occurred:", error);
} else {
console.log("Status data received:", data);
}
},
application: "MyApp",
refID: "admin123"
};
floCloudAPI.requestStatus(trackList, options)
.then(statusData => {
console.log("Status request successful:", statusData);
})
.catch(error => {
console.error("Error sending status request:", error);
});
```
## sendApplicationData Function
The `sendApplicationData` function is used to send application-specific data messages to a receiver identified by their `receiverID`. It allows customization of the message content, type, receiver ID, application name, and additional comments.
### Parameters
- `message` (string): The application-specific message to be sent.
- `type` (string): The type of the application data.
- `options` (object, optional): An object containing the following properties:
- `receiverID` (string, optional): The ID of the receiver for the application data message. If not provided, the default admin ID is used.
- `application` (string, optional): The application name associated with the data message. If not provided, the default application name is used.
- `comment` (string, optional): Additional comments or notes associated with the data message.
### Return Value
- Returns a Promise that resolves with the response data upon successful delivery of the application data message.
### Example Usage
- In this example, the sendApplicationData function sends an application-specific data message with the specified content, type, receiver ID, application name, and additional comments. The function allows customization of the message parameters through the options object and resolves with the response data upon successful delivery of the message.
```javascript
const message = "Hello, this is an application data message.";
const type = "text";
const options = {
receiverID: "receiverUserID",
application: "MyApp",
comment: "Optional comment for the message."
};
floCloudAPI.sendApplicationData(message, type, options)
.then(response => {
console.log("Application data message sent successfully:", response);
})
.catch(error => {
console.error("Error occurred while sending application data message:", error);
});
```
## requestApplicationData Function
The `requestApplicationData` function is a versatile method used to request data from the supernode cloud. It allows customization of the request parameters including the type of data, receiver and sender IDs, application name, vector clocks, timestamp, and request method.
### Parameters
- `type` (string): The type of data to be requested.
- `options` (object, optional): An object containing the following properties:
- `receiverID` (string, optional): The ID of the receiver for the data request. If not provided, the default admin ID is used.
- `senderID` (string, optional): The ID of the sender for the data request. If not provided, it's set to `undefined`.
- `application` (string, optional): The application name associated with the data request. If not provided, the default application name is used.
- `comment` (string, optional): Additional comments or notes for the data request. If not provided, it's set to `undefined`.
- `lowerVectorClock` (string, optional): The lower boundary for vector clock filtering. If not provided, it's set to `undefined`.
- `upperVectorClock` (string, optional): The upper boundary for vector clock filtering. If not provided, it's set to `undefined`.
- `atVectorClock` (string, optional): The specific vector clock at which the data is requested. If not provided, it's set to `undefined`.
- `afterTime` (number, optional): Request data after the specified timestamp. If not provided, it's set to `undefined`.
- `mostRecent` (boolean, optional): If set to `true`, requests the most recent data. If not provided, it's set to `undefined`.
- `method` (string, optional): The HTTP request method. Default is `"GET"`. Can be `"GET"` or `"POST"`.
### Return Value
- Returns a Promise that resolves with the response data upon successful retrieval of the requested data.
### Example Usage
- In this example, the requestApplicationData function sends a customizable data request to the supernode cloud. It allows flexibility in specifying request parameters, including vector clocks, timestamps, and request method. The function resolves with the response data upon successful retrieval of the requested data.
```javascript
const type = "exampleData";
const options = {
receiverID: "receiverUserID",
senderID: "senderUserID",
application: "MyApp",
comment: "Optional comment for the request.",
lowerVectorClock: "123",
upperVectorClock: "456",
atVectorClock: "789",
afterTime: 1633363200000,
mostRecent: true,
method: "POST",
callback: function(data, error) {
if (error) {
console.error("Error occurred:", error);
} else {
console.log("Data received:", data);
}
}
};
floCloudAPI.requestApplicationData(type, options)
.then(response => {
console.log("Data request successful:", response);
})
.catch(error => {
console.error("Error sending data request:", error);
});
```
## editApplicationData Function
The `editApplicationData` function is used by the sender to edit the comment of specific data in the supernode cloud identified by its `vectorClock`. It retrieves the data, verifies the sender's identity, edits the comment, and updates the data in the supernode cloud.
### Parameters
- `vectorClock` (string): The vector clock of the data to be edited.
- `comment_edit` (string): The edited comment to be applied to the data.
- `options` (object, optional): An object containing the following properties:
- `receiverID` (string, optional): The ID of the receiver for the edited data. If not provided, the default admin ID is used.
### Return Value
- Returns a Promise that resolves with the response data upon successful editing of the data comment.
### Example Usage
- In this example, the editApplicationData function allows the sender to edit the comment of specific data identified by its vectorClock. The function verifies the sender's identity and ensures that only the sender can edit the comment. Upon successful editing, the function resolves with the response data.
```javascript
const vectorClock = "exampleVectorClock123";
const editedComment = "This is the edited comment for the data.";
const options = {
receiverID: "receiverUserID"
};
floCloudAPI.editApplicationData(vectorClock, editedComment, options)
.then(response => {
console.log("Data comment edited successfully:", response);
})
.catch(error => {
console.error("Error editing data comment:", error);
});
```
## tagApplicationData Function
The `tagApplicationData` function is used by subAdmins to tag specific data in the supernode cloud identified by its `vectorClock`. It allows subAdmins to add tags to the data for organizational purposes.
### Parameters
- `vectorClock` (string): The vector clock of the data to be tagged.
- `tag` (string): The tag to be applied to the data.
- `options` (object, optional): An object containing the following properties:
- `receiverID` (string, optional): The ID of the receiver for the tagged data. If not provided, the default admin ID is used.
### Return Value
- Returns a Promise that resolves with the response data upon successful tagging of the data.
### Example Usage
- In this example, the tagApplicationData function allows subAdmins to tag specific data identified by its vectorClock. SubAdmins can add tags to the data for organizational purposes. The function ensures that only subAdmins have access to tagging data, and upon successful tagging, it resolves with the response data.
```javascript
const vectorClock = "exampleVectorClock123";
const tag = "important";
floCloudAPI.tagApplicationData(vectorClock, tag)
.then(response => {
console.log("Data tagged successfully:", response);
})
.catch(error => {
console.error("Error tagging data:", error);
});
```
## noteApplicationData Function
The `noteApplicationData` function allows users (receivers) and subAdmins (if the receiver is the `adminID`) to add notes to specific data in the supernode cloud identified by its `vectorClock`.
### Parameters
- `vectorClock` (string): The vector clock of the data to be noted.
- `note` (string): The note to be added to the data.
- `options` (object, optional): An object containing the following properties:
- `receiverID` (string, optional): The ID of the receiver for the noted data. If not provided, the default admin ID is used.
### Return Value
- Returns a Promise that resolves with the response data upon successful noting of the data.
### Example Usage
- In this example, the noteApplicationData function allows users and subAdmins to add notes to specific data identified by its vectorClock in the supernode cloud. The function ensures that only the receiver and subAdmins (if the receiver is the adminID) can add notes to the data. Upon successful noting, it resolves with the response data.
```javascript
const vectorClock = "exampleVectorClock123";
const note = "This is a note for the data.";
floCloudAPI.noteApplicationData(vectorClock, note)
.then(response => {
console.log("Data noted successfully:", response);
})
.catch(error => {
console.error("Error adding note to data:", error);
});
```
## sendGeneralData Function
The `sendGeneralData` function is used to send general data messages to the supernode cloud. It allows customization of the data content, type, encryption, and other options before sending.
### Parameters
- `message` (object or string): The general data to be sent. It can be an object or a string.
- `type` (string): The type of the general data.
- `options` (object, optional): An object containing the following properties:
- `encrypt` (boolean or string, optional): If `true`, the `message` will be encrypted using the default encryption key. If a string is provided, it will be used as the encryption key. If not provided or `false`, no encryption will be applied.
### Return Value
- Returns a Promise that resolves with the response data upon successful sending of the general data message.
### Example Usage
- In this example, the sendGeneralData function sends a general data message with the specified content and type to the supernode cloud. The function allows customization of the encryption option through the options object. Upon successful sending, it resolves with the response data.
```javascript
const message = {
key: "value"
};
const type = "exampleType";
const options = {
encrypt: true // Encrypt the message using the default encryption key
};
floCloudAPI.sendGeneralData(message, type, options)
.then(response => {
console.log("General data sent successfully:", response);
})
.catch(error => {
console.error("Error sending general data:", error);
});
```
## requestGeneralData Function
The `requestGeneralData` function is used to request general data of a specific type from the supernode cloud. It allows customization of the request parameters including the data type, filtering options, and callback function for data storage and handling.
### Parameters
- `type` (string): The type of general data to be requested.
- `options` (object, optional): An object containing the following properties:
- `receiverID` (string, optional): The ID of the receiver for the data request. If not provided, the default admin ID is used.
- `senderID` (string, optional): The ID of the sender for the data request. If not provided, it's set to `undefined`.
- `application` (string, optional): The application name associated with the data request. If not provided, the default application name is used.
- `comment` (string, optional): Additional comments or notes for the data request. If not provided, it's set to `undefined`.
- `lowerVectorClock` (string, optional): The lower boundary for vector clock filtering. If not provided, it's set to `undefined`.
- `upperVectorClock` (string, optional): The upper boundary for vector clock filtering. If not provided, it's set to `undefined`.
- `atVectorClock` (string, optional): The specific vector clock at which the data is requested. If not provided, it's set to `undefined`.
- `afterTime` (number, optional): Request data after the specified timestamp. If not provided, it's set to the last stored vector clock for the specified data type.
- `mostRecent` (boolean, optional): If set to `true`, requests the most recent data. If not provided, it's set to `undefined`.
- `callback` (function, optional): A callback function to handle the response data and errors. If provided, the function stores the data and then calls the callback. If not provided, the data is directly resolved.
### Return Value
- Returns a Promise that resolves with the response data upon successful retrieval of the requested general data.
### Example Usage
- In this example, the requestGeneralData function sends a customizable data request to the supernode cloud. It allows flexibility in specifying request parameters, including vector clocks, timestamps, and callback function for data storage and handling. The function resolves with the response data upon successful retrieval of the requested general data.
```javascript
const type = "exampleType";
const options = {
receiverID: "receiverUserID",
senderID: "senderUserID",
application: "MyApp",
comment: "Optional comment for the request.",
lowerVectorClock: "123",
upperVectorClock: "456",
atVectorClock: "789",
afterTime: 1633363200000,
mostRecent: true,
callback: function(data, error) {
if (error) {
console.error("Error occurred:", error);
} else {
console.log("Data received:", data);
}
}
};
floCloudAPI.requestGeneralData(type, options)
.then(response => {
console.log("General data request successful:", response);
})
.catch(error => {
console.error("Error sending general data request:", error);
});
```
## requestObjectData Function
The `requestObjectData` function is used to request data of a specific object type from the supernode cloud. It allows customization of the request parameters including the object name, filtering options, and callback function for data storage and handling.
### Parameters
- `objectName` (string): The name of the object data to be requested.
- `options` (object, optional): An object containing the following properties:
- `lowerVectorClock` (string, optional): The lower boundary for vector clock filtering. If not provided, it's set to the last stored vector clock for the specified object data type plus 1.
- `senderID` (string or array, optional): The sender ID(s) for filtering the data. If not provided, it's set to `null`. If provided, only data from the specified sender(s) will be requested.
- `mostRecent` (boolean, optional): If set to `true`, requests the most recent data. If not provided, it's set to `true`.
- `comment` (string, optional): The comment to be applied to the request. If provided, it's set to `'RESET'`.
- `callback` (function, optional): A callback function to handle the response data and errors. If provided, the function stores the data and then calls the callback. If not provided, the data is directly resolved.
### Return Value
- Returns a Promise that resolves with the response data upon successful retrieval of the requested object data.
### Example Usage
- In this example, the requestObjectData function sends a customizable data request for a specific object type to the supernode cloud. It allows flexibility in specifying request parameters, including vector clocks, sender IDs, and callback function for data storage and handling. The function resolves with the response data upon successful retrieval of the requested object data.
```javascript
const objectName = "exampleObject";
const options = {
lowerVectorClock: "123",
senderID: "senderUserID",
mostRecent: true,
callback: function(data, error) {
if (error) {
console.error("Error occurred:", error);
} else {
console.log("Data received:", data);
}
}
};
floCloudAPI.requestObjectData(objectName, options)
.then(response => {
console.log("Object data request successful:", response);
})
.catch(error => {
console.error("Error sending object data request:", error);
});
```
## closeRequest Function
The `closeRequest` function is used to close an active request connection to the supernode cloud identified by its `requestID`.
### Parameters
- `requestID` (string): The unique identifier of the request connection to be closed.
### Return Value
- Returns a Promise that resolves with a success message upon successful closure of the request connection.
### Example Usage
- In this example, the closeRequest function closes an active request connection to the supernode cloud based on the provided requestID. Upon successful closure, it resolves with a success message. If the request connection is not found, it rejects with an error message.
```javascript
const requestID = "exampleRequestID";
floCloudAPI.closeRequest(requestID)
.then(response => {
console.log("Request connection closed successfully:", response);
})
.catch(error => {
console.error("Error closing request connection:", error);
});
```
## resetObjectData Function
The `resetObjectData` function is used to reset or initialize an object and send it to the supernode cloud. It sends a reset message containing the initial state of the specified object to the cloud for synchronization.
### Parameters
- `objectName` (string): The name of the object to be reset and sent to the cloud.
- `options` (object, optional): An object containing the following properties:
- `comment` (string, optional): The comment to be applied to the reset operation. If provided, it's set to `'RESET'`.
### Return Value
- Returns a Promise that resolves with the response data upon successful reset and synchronization of the object data.
### Example Usage
- In this example, the resetObjectData function resets the specified object to its initial state and sends the reset message to the supernode cloud for synchronization. The function allows customization through the options object, including adding a comment to the reset operation. Upon successful reset and synchronization, it resolves with the response data.
```javascript
const objectName = "exampleObject";
const options = {
comment: "Resetting object to initial state."
};
floCloudAPI.resetObjectData(objectName, options)
.then(response => {
console.log("Object data reset and synchronized successfully:", response);
})
.catch(error => {
console.error("Error resetting object data:", error);
});
```
## updateObjectData Function
The `updateObjectData` function is used to update the differential changes of an object and send them to the supernode cloud. It computes the difference between the last committed state and the current state of the specified object and sends the update message to the cloud for synchronization.
### Parameters
- `objectName` (string): The name of the object whose differential changes need to be sent to the cloud.
- `options` (object, optional): An object containing the following properties:
- `comment` (string, optional): The comment to be applied to the update operation. If provided, it's set to `'UPDATE'`.
### Return Value
- Returns a Promise that resolves with the response data upon successful update and synchronization of the object's differential changes.
### Example Usage
- In this example, the updateObjectData function computes the differential changes of the specified object and sends the update message to the supernode cloud for synchronization. The function allows customization through the options object, including adding a comment to the update operation. Upon successful update and synchronization, it resolves with the response data.
```javascript
const objectName = "exampleObject";
const options = {
comment: "Updating object with differential changes."
};
floCloudAPI.updateObjectData(objectName, options)
.then(response => {
console.log("Object data updated and synchronized successfully:", response);
})
.catch(error => {
console.error("Error updating object data:", error);
});
```
## uploadFile Function
The `uploadFile` function is used to upload a file to the supernode cloud. It accepts a file blob or instance of File/Blob, processes the file content, and sends it to the cloud for storage.
### Parameters
- `fileBlob` (File/Blob): The File or Blob instance representing the file to be uploaded.
- `type` (string): The type of data to be associated with the uploaded file.
- `options` (object, optional): An object containing the following properties:
- `encrypt` (boolean or string, optional): If `true`, encrypts the file data using the default encryption key. If a string is provided, it uses the specified encryption key. If not provided, the file data is not encrypted.
### Return Value
- Returns a Promise that resolves with an object containing vectorClock, receiverID, type, and application upon successful upload of the file.
### Example Usage
- In this example, the uploadFile function uploads a file to the supernode cloud. It accepts a file blob or instance of File/Blob, processes the file content, and sends it to the cloud for storage. The function allows customization through the options object, including encryption of the file data. Upon successful upload, it resolves with an object containing vectorClock, receiverID, type, and application.
```javascript
const fileBlob = new Blob(["File content"], { type: "text/plain" });
const type = "fileData";
const options = {
encrypt: true
};
floCloudAPI.uploadFile(fileBlob, type, options)
.then(response => {
console.log("File uploaded successfully:", response);
})
.catch(error => {
console.error("Error uploading file:", error);
});
```
## downloadFile Function
The `downloadFile` function is used to download a file from the supernode cloud based on its vectorClock. It retrieves the file data, decrypts it if necessary, and reconstructs the file for download.
### Parameters
- `vectorClock` (string): The vectorClock of the file to be downloaded.
- `options` (object, optional): An object containing the following properties:
- `type` (string, optional): The type of the data to be downloaded. If not provided, it uses the default type.
- `decrypt` (boolean or string, optional): If `true`, decrypts the file data using the default decryption key. If a string is provided, it uses the specified decryption key. If not provided, and the file data is encrypted, it rejects the download request.
### Return Value
- Returns a Promise that resolves with an object containing the downloaded File instance upon successful download.
### Example Usage
- In this example, the downloadFile function downloads a file from the supernode cloud based on its vectorClock. It allows customization through the options object, including specifying the data type and providing a decryption key if the file data is encrypted. Upon successful download, it resolves with an object containing the downloaded File instance.
```javascript
const vectorClock = "exampleVectorClock";
const options = {
type: "fileData",
decrypt: true
};
floCloudAPI.downloadFile(vectorClock, options)
.then(response => {
console.log("File downloaded successfully:", response);
// Use response.file to access the downloaded file instance
})
.catch(error => {
console.error("Error downloading file:", error);
});
```

685
docs/floCrypto.md Normal file
View File

@ -0,0 +1,685 @@
# encryptData Function Documentation
The `encryptData` function takes two parameters: `data` (string) and `receiverPublicKeyHex` (string). It encrypts the given data using AES encryption algorithm with a shared key derived from the sender's private key and receiver's public key. The function returns an object with two properties: `secret` (the encrypted data) and `senderPublicKeyString` (the sender's public key string).
## Parameters
- **data** (String): The data to be encrypted.
- **receiverPublicKeyHex** (String): The hexadecimal representation of the receiver's public key.
## Return Value
An object containing the following properties:
- **secret** (String): The encrypted data.
- **senderPublicKeyString** (String): The sender's public key string.
## Example Usage
```javascript
const data = "Hello, World!";
const receiverPublicKeyHex = "receiver_public_key_hex_here";
const encryptedData = floCrypto.encryptData(data, receiverPublicKeyHex);
console.log("Encrypted Data:", encryptedData.secret);
console.log("Sender's Public Key:", encryptedData.senderPublicKeyString);
```
## Dependencies
`getSenderPublicKeyString`: A function to retrieve the sender's public key string.
`deriveSharedKeySender`: A function to derive a shared key using sender's private key and receiver's public key.
`Crypto.AES.encrypt`: AES encryption function used to encrypt the data.
## Notes
- Ensure that the necessary dependencies (getSenderPublicKeyString, deriveSharedKeySender, Crypto.AES.encrypt) are available and properly implemented before using this function.
- Note: Replace receiver_public_key_hex_here with the actual hexadecimal representation of the receiver's public key when using the function.
# decryptData Function Documentation
The `decryptData` function is used to decrypt encrypted data using the receiver's private key.
## Parameters
- **data** (Object): An object containing the encrypted data and sender's public key string.
- **secret** (String): The encrypted data.
- **senderPublicKeyString** (String): The sender's public key string.
- **privateKeyHex** (String): The hexadecimal representation of the receiver's private key.
## Return Value
The decrypted message as a string.
## Throws
- **Error**: If `privateKeyHex` is not a valid string or if the private key cannot be determined from the provided hexadecimal representation.
## Example Usage
```javascript
const encryptedData = {
secret: "encrypted_data_here",
senderPublicKeyString: "sender_public_key_string_here"
};
const privateKeyHex = "receiver_private_key_hex_here";
const decryptedMessage = floCrypto.decryptData(encryptedData, privateKeyHex);
console.log("Decrypted Message:", decryptedMessage);
```
## Dependencies
- **wifToDecimal**: A function to convert the receiver's private key from WIF format to decimal format.
- **deriveSharedKeyReceiver**: A function to derive a shared key using sender's public key string and receiver's private key.
- **Crypto.AES.decrypt**: AES decryption function used to decrypt the data.
## Notes
- Ensure that the necessary dependencies (`wifToDecimal`, `deriveSharedKeyReceiver`, `Crypto.AES.decrypt`) are available and properly implemented before using this function.
- **Note**: Replace `"encrypted_data_here"` with the actual encrypted data, `"sender_public_key_string_here"` with the sender's public key string, and `"receiver_private_key_hex_here"` with the receiver's private key in hexadecimal format when using the function.
# signData Function Documentation
The `signData` function is used to sign data using the sender's private key.
## Parameters
- **data** (String): The data to be signed.
- **privateKeyHex** (String): The hexadecimal representation of the sender's private key.
## Return Value
A hexadecimal string representing the signature of the input data.
## Dependencies
- **Bitcoin.ECKey**: A class for handling elliptic curve cryptography operations.
- **Crypto.SHA256**: SHA-256 hash function used to create the message hash.
- **Bitcoin.ECDSA.sign**: Function for generating the ECDSA signature.
- **Crypto.util.bytesToHex**: Utility function to convert bytes to hexadecimal string.
## Example Usage
```javascript
const data = "Hello, World!";
const privateKeyHex = "sender_private_key_hex_here";
const signature = floCrypto.signData(data, privateKeyHex);
console.log("Signature:", signature);
```
## Notes
- Ensure that the necessary dependencies (`Bitcoin.ECKey`, `Crypto.SHA256`, `Bitcoin.ECDSA.sign`, `Crypto.util.bytesToHex`) are available and properly implemented before using this function.
- **Note**: Replace `"sender_private_key_hex_here"` with the actual sender's private key in hexadecimal format when using the function.
# verifySign Function Documentation
The `verifySign` function is used to verify the signature of data using the sender's public key.
## Parameters
- **data** (String): The original data that was signed.
- **signatureHex** (String): The hexadecimal representation of the signature to be verified.
- **publicKeyHex** (String): The hexadecimal representation of the sender's public key.
## Return Value
A boolean value indicating whether the signature is valid (`true`) or not (`false`).
## Dependencies
- **Crypto.SHA256**: SHA-256 hash function used to create the message hash.
- **Crypto.util.hexToBytes**: Utility function to convert hexadecimal string to bytes.
- **ecparams.getCurve().decodePointHex**: Function to decode the sender's public key from hexadecimal format.
- **Bitcoin.ECDSA.verify**: Function for verifying the ECDSA signature.
## Example Usage
```javascript
const data = "Hello, World!";
const signatureHex = "signature_hex_here";
const publicKeyHex = "sender_public_key_hex_here";
const isSignatureValid = floCrypto.verifySign(data, signatureHex, publicKeyHex);
console.log("Is Signature Valid?", isSignatureValid);
```
## Notes
- Ensure that the necessary dependencies (`Crypto.SHA256`, `Crypto.util.hexToBytes`, `ecparams.getCurve().decodePointHex`, `Bitcoin.ECDSA.verify`) are available and properly implemented before using this function.
- **Note**: Replace `"signature_hex_here"` with the actual signature in hexadecimal format, and `"sender_public_key_hex_here"` with the sender's public key in hexadecimal format when using the function
# generateNewID Function Documentation
The `generateNewID` function is used to generate a new flo ID, along with its corresponding private key and public key.
## Return Value
An object containing the following properties:
- **floID** (String): The newly generated flo ID.
- **pubKey** (String): The hexadecimal representation of the corresponding public key.
- **privKey** (String): The Wallet Import Format (WIF) representation of the corresponding private key.
## Dependencies
- **Bitcoin.ECKey**: A class for generating elliptic curve key pairs.
## Example Usage
```javascript
const newIDInfo = floCrypto.generateNewID();
console.log("Flo ID:", newIDInfo.floID);
console.log("Public Key:", newIDInfo.pubKey);
console.log("Private Key (WIF):", newIDInfo.privKey);
```
## Notes
- Ensure that the necessary dependency (`Bitcoin.ECKey`) is available and properly implemented before using this function.
# getPubKeyHex Function Documentation
The `getPubKeyHex` function is used to obtain the public key from a given private key.
## Parameters
- **privateKeyHex** (String): The hexadecimal representation of the private key.
## Return Value
- (String): The hexadecimal representation of the corresponding public key.
## Dependencies
- **Bitcoin.ECKey**: A class for handling elliptic curve cryptography operations.
## Example Usage
```javascript
const privateKeyHex = "private_key_hex_here";
const publicKeyHex = floCrypto.getPubKeyHex(privateKeyHex);
console.log("Public Key:", publicKeyHex);
```
## Notes
- Ensure that the necessary dependency (`Bitcoin.ECKey`) is available and properly implemented before using this function.
- If `privateKeyHex` is not provided or invalid, the function will return `null`.
# getFloID Function Documentation
The `getFloID` function is used to obtain the flo-ID from a given public key or private key.
## Parameters
- **keyHex** (String): The hexadecimal representation of the public key or private key.
## Return Value
- (String): The corresponding flo-ID.
## Dependencies
- **Bitcoin.ECKey**: A class for handling elliptic curve cryptography operations.
## Example Usage
```javascript
const keyHex = "public_key_or_private_key_hex_here";
const floID = floCrypto.getFloID(keyHex);
console.log("Flo-ID:", floID);
```
## Notes
- Ensure that the necessary dependency (`Bitcoin.ECKey`) is available and properly implemented before using this function.
- If `keyHex` is not provided or invalid, the function will return `null`.
# getAddress Function Documentation
The `getAddress` function is used to obtain the cryptocurrency address (BTC or FLO) corresponding to a given private key.
## Parameters
- **privateKeyHex** (String): The hexadecimal representation of the private key.
- **strict** (Boolean, optional): A flag to enforce strict address generation. Default is `false`.
## Return Value
- (String): The cryptocurrency address corresponding to the provided private key.
## Dependencies
- **Bitcoin.ECKey**: A class for handling elliptic curve cryptography operations.
- **bitjs.Base58.decode**: Function to decode Base58 encoded strings.
- **coinjs.bech32Address**: Function to generate BTC bech32 address.
- **bitjs.pubkey2address**: Function to generate FLO address from public key.
## Example Usage
```javascript
const privateKeyHex = "private_key_hex_here";
const address = floCrypto.getAddress(privateKeyHex, true);
console.log("Cryptocurrency Address:", address);
```
## Notes
- Ensure that the necessary dependencies (`Bitcoin.ECKey`, `bitjs.Base58.decode`, `coinjs.bech32Address`, `bitjs.pubkey2address`) are available and properly implemented before using this function.
- If `privateKeyHex` is not provided or invalid, the function will return `null`.
- The `strict` flag, if set to `true`, enforces strict address generation based on the provided private key version. If set to `false`, the function will default to generating a FLO address.
# verifyPrivKey Function Documentation
The `verifyPrivKey` function is used to verify whether a given private key corresponds to a provided public key or flo-ID.
## Parameters
- **privateKeyHex** (String): The hexadecimal representation of the private key.
- **pubKey_floID** (String): The public key or flo-ID to be verified.
- **isfloID** (Boolean, optional): A flag indicating whether the provided key is a flo-ID. Default is `true`.
## Return Value
- (Boolean): `true` if the private key corresponds to the provided public key or flo-ID, `false` otherwise. Returns `null` if an error occurs during verification.
## Dependencies
- **Bitcoin.ECKey**: A class for handling elliptic curve cryptography operations.
## Example Usage
```javascript
const privateKeyHex = "private_key_hex_here";
const pubKey_floID = "public_key_or_floID_here";
const isfloID = true;
const isPrivateKeyValid = floCrypto.verifyPrivKey(privateKeyHex, pubKey_floID, isfloID);
console.log("Is Private Key Valid?", isPrivateKeyValid);
```
## Notes
- Ensure that the necessary dependency (`Bitcoin.ECKey`) is available and properly implemented before using this function.
- If `privateKeyHex` or `pubKey_floID` is not provided or invalid, the function will return `false`.
- If `isfloID` is set to `true`, the function will verify against a flo-ID. If set to `false`, it will verify against a public key.
# getMultisigAddress Function Documentation
The `getMultisigAddress` function is used to generate a multisignature address based on a list of public keys and the number of required signatures.
## Parameters
- **publicKeyList** (Array of Strings): An array containing hexadecimal representations of public keys.
- **requiredSignatures** (Integer): The number of required signatures for the multisignature address.
## Return Value
- (String): The generated multisignature address, or `null` if an error occurs during the generation.
## Dependencies
- **bitjs.pubkeys2multisig**: Function to generate a multisignature address from an array of public keys.
## Example Usage
```javascript
const publicKeyList = ["pubKey1_hex", "pubKey2_hex", "pubKey3_hex"];
const requiredSignatures = 2;
const multisigAddress = floCrypto.getMultisigAddress(publicKeyList, requiredSignatures);
console.log("Multisig Address:", multisigAddress);
```
## Notes
- Ensure that the necessary dependency (`bitjs.pubkeys2multisig`) is available and properly implemented before using this function.
- `publicKeyList` should be an array of hexadecimal strings representing the public keys.
- `requiredSignatures` should be an integer indicating the number of required signatures for the multisignature address.
- If `publicKeyList` is empty, not an array, or contains invalid keys, or if `requiredSignatures` is not a valid integer, the function will return `null`.
# decodeRedeemScript Function Documentation
The `decodeRedeemScript` function is used to decode a multisignature redeem script.
## Parameters
- **redeemScript** (String): The hexadecimal representation of the redeem script.
## Return Value
- (Object): An object containing the decoded information of the multisignature redeem script, or `null` if an error occurs during decoding.
## Dependencies
- **bitjs.transaction().decodeRedeemScript**: Function to decode a multisignature redeem script.
## Example Usage
```javascript
const redeemScript = "redeem_script_hex_here";
const decodedRedeemScript = floCrypto.decodeRedeemScript(redeemScript);
console.log("Decoded Redeem Script:", decodedRedeemScript);
```
## Notes
- Ensure that the necessary dependency (`bitjs.transaction().decodeRedeemScript`) is available and properly implemented before using this function.
- If the `redeemScript` is not a valid hexadecimal string or if an error occurs during decoding, the function will return `null`.
# validateFloID Function Documentation
The `validateFloID` function is used to check whether a given flo-ID is valid or not.
## Parameters
- **floID** (String): The flo-ID to be validated.
- **regularOnly** (Boolean, optional): A flag indicating whether to allow only regular flo-IDs. Default is `false`.
## Return Value
- (Boolean): `true` if the flo-ID is valid, `false` otherwise.
## Dependencies
- **Bitcoin.Address**: A class for handling Bitcoin addresses.
## Example Usage
```javascript
const floID = "flo_ID_here";
const isValidFloID = floCrypto.validateFloID(floID, true);
console.log("Is Flo-ID Valid?", isValidFloID);
```
## Notes
- Ensure that the necessary dependency (`Bitcoin.Address`) is available and properly implemented before using this function.
- If `floID` is not a valid flo-ID (not a valid Bitcoin address), the function will return `false`.
- If `regularOnly` is set to `true`, the function will only consider standard flo-IDs as valid; otherwise, it will consider all valid flo-IDs as valid.
# validateAddr Function Documentation
The `validateAddr` function is used to check whether a given address (from any blockchain) is valid or not.
## Parameters
- **address** (String): The address to be validated.
- **std** (Boolean or Integer or Array, optional): A flag or array indicating whether to allow specific address versions (standard addresses). Default is `true`.
- **bech** (Boolean or Integer or Array, optional): A flag or array indicating whether to allow specific bech32 address versions. Default is `true`.
## Return Value
- (Boolean): `true` if the address is valid, `false` otherwise.
## Dependencies
- **decodeAddress**: A function to decode the provided address.
## Example Usage
```javascript
const address = "address_here";
const isValidAddress = floCrypto.validateAddr(address, true, true);
console.log("Is Address Valid?", isValidAddress);
```
## Notes
- Ensure that the necessary dependency (`decodeAddress`) is available and properly implemented before using this function.
- If `address` is not a valid address, the function will return `false`.
- The `std` parameter allows specifying the allowed standard address versions. If set to `true`, all standard versions are allowed. If set to an integer or an array of integers, only the specified version(s) are allowed.
- The `bech` parameter allows specifying the allowed bech32 address versions. If set to `true`, all bech32 versions are allowed. If set to an integer or an array of integers, only the specified version(s) are allowed.
# verifyPubKey Function Documentation
The `verifyPubKey` function is used to verify whether a given public key or redeem script corresponds to the provided address (from any blockchain).
## Parameters
- **pubKeyHex** (String): The hexadecimal representation of the public key or redeem script.
- **address** (String): The address to be verified.
## Return Value
- (Boolean): `true` if the public key or redeem script corresponds to the provided address, `false` otherwise.
## Dependencies
- **decodeAddress**: A function to decode the provided address.
- **Crypto.util.bytesToHex**: Utility function to convert bytes to hexadecimal string.
- **Crypto.SHA256**: SHA-256 hash function.
- **ripemd160**: RIPEMD-160 hash function.
## Example Usage
```javascript
const pubKeyHex = "public_key_or_redeem_script_hex_here";
const address = "address_here";
const isPubKeyValid = floCrypto.verifyPubKey(pubKeyHex, address);
console.log("Is Public Key Valid?", isPubKeyValid);
```
## Notes
- Ensure that the necessary dependencies (`decodeAddress`, `Crypto.util.bytesToHex`, `Crypto.SHA256`, `Crypto.util.hexToBytes`, `ripemd160`) are available and properly implemented before using this function.
- If the public key or redeem script does not correspond to the provided address, the function will return `false`.
# toFloID Function Documentation
The `toFloID` function is used to convert a given address (from any blockchain) to its equivalent floID.
## Parameters
- **address** (String): The address to be converted.
- **options** (Object, optional): An object containing options for version checks. Default is `null`.
- **std** (Array of Integers, optional): An array of allowed standard address versions.
- **bech** (Array of Integers, optional): An array of allowed bech32 address versions.
## Return Value
- (String): The equivalent floID corresponding to the provided address. Returns `undefined` if the address is not valid or does not match the specified options.
## Dependencies
- **decodeAddress**: A function to decode the provided address.
- **Crypto.SHA256**: SHA-256 hash function.
- **bitjs.pub**: The version byte for FLO addresses.
- **bitjs.Base58.encode**: Base58 encoding function.
## Example Usage
```javascript
const address = "address_here";
const options = {
std: [version1, version2],
bech: [version3, version4]
};
const floID = floCrypto.toFloID(address, options);
console.log("Equivalent FloID:", floID);
```
## Notes
- Ensure that the necessary dependencies (`decodeAddress`, `Crypto.SHA256`, `bitjs.pub`, `bitjs.Base58.encode`) are available and properly implemented before using this function.
- If the `address` is not valid or does not match the specified options, the function will return `undefined`.
# toMultisigFloID Function Documentation
The `toMultisigFloID` function is used to convert a given multisig address (from any blockchain) to its equivalent multisig floID.
## Parameters
- **address** (String): The multisig address to be converted.
- **options** (Object, optional): An object containing options for version checks. Default is `null`.
- **std** (Array of Integers, optional): An array of allowed standard address versions.
- **bech** (Array of Integers, optional): An array of allowed bech32 address versions.
## Return Value
- (String): The equivalent multisig floID corresponding to the provided multisig address. Returns `undefined` if the address is not valid or does not match the specified options.
## Dependencies
- **decodeAddress**: A function to decode the provided multisig address.
- **Crypto.SHA256**: SHA-256 hash function.
- **ripemd160**: A cryptographic hash function.
- **bitjs.multisig**: The version byte for multisig FLO addresses.
- **bitjs.Base58.encode**: Base58 encoding function.
## Example Usage
```javascript
const multisigAddress = "multisig_address_here";
const options = {
std: [version1, version2],
bech: [version3, version4]
};
const multisigFloID = floCrypto.toMultisigFloID(multisigAddress, options);
console.log("Equivalent Multisig FloID:", multisigFloID);
```
## Notes
- Ensure that the necessary dependencies (`decodeAddress`, `Crypto.SHA256`, `ripemd160`, `bitjs.multisig`, `bitjs.Base58.encode`) are available and properly implemented before using this function.
- If the `address` is not valid or does not match the specified options, the function will return `undefined`.
# isSameAddr Function Documentation
The `isSameAddr` function is used to check whether two given addresses (from any blockchain) correspond to the same keys.
## Parameters
- **addr1** (String): The first address to be compared.
- **addr2** (String): The second address to be compared.
## Return Value
- (Boolean): `true` if the addresses correspond to the same keys, `false` otherwise. Returns `undefined` if either `addr1` or `addr2` is not provided or invalid.
## Dependencies
- **decodeAddress**: A function to decode the provided addresses.
- **Crypto.util.bytesToHex**: Utility function to convert bytes to hexadecimal string.
- **ripemd160**: A cryptographic hash function.
## Example Usage
```javascript
const addr1 = "address1_here";
const addr2 = "address2_here";
const sameKeys = floCrypto.isSameAddr(addr1, addr2);
console.log("Do Addresses Correspond to Same Keys?", sameKeys);
```
## Notes
- Ensure that the necessary dependencies (`decodeAddress`, `Crypto.util.bytesToHex`, `ripemd160`) are available and properly implemented before using this function.
- If either `addr1` or `addr2` is not provided or invalid, the function will return `undefined`.
# decodeAddr Function Documentation
The `decodeAddr` function is used to decode the provided address and determine its version, hexadecimal representation, and raw bytes.
## Parameters
- **address** (String): The address to be decoded.
## Return Value
- (Object or null): An object containing decoded information, including version, hexadecimal representation, and raw bytes. Returns `null` if the provided address is not valid.
## Dependencies
- **bitjs.Base58.decode**: Base58 decoding function for legacy addresses.
- **Crypto.SHA256**: SHA-256 hash function.
- **Crypto.util.bytesToHex**: Utility function to convert bytes to hexadecimal string.
- **coinjs.bech32_decode**: Bech32 decoding function for bech32 addresses.
- **coinjs.bech32_convert**: Bech32 conversion function.
## Example Usage
```javascript
const address = "address_here";
const decodedInfo = floCrypto.decodeAddr(address);
console.log("Decoded Address Information:", decodedInfo);
```
## Notes
- Ensure that the necessary dependencies (`bitjs.Base58.decode`, `Crypto.SHA256`, `Crypto.util.bytesToHex`, `coinjs.bech32_decode`, `coinjs.bech32_convert`) are available and properly implemented before using this function.
- The function will return `null` if the provided address is not valid.
# createShamirsSecretShares Function Documentation
The `createShamirsSecretShares` function uses Shamir's Secret Sharing algorithm to split a given string into shares based on the specified total shares and threshold limit.
## Parameters
- **str** (String): The input string to be split.
- **total_shares** (Integer): The total number of shares to be generated.
- **threshold_limit** (Integer): The minimum number of shares required to reconstruct the original string.
## Return Value
- (Array or Boolean): An array containing the shares generated using Shamir's Secret Sharing algorithm. Returns `false` if the input string is empty or if there is an error during the splitting process.
## Dependencies
- **shamirSecretShare.str2hex**: Function to convert a string to hexadecimal representation.
- **shamirSecretShare.share**: Function to generate shares using Shamir's Secret Sharing algorithm.
## Example Usage
```javascript
const inputString = "input_string_here";
const totalShares = 5;
const thresholdLimit = 3;
const shares = floCrypto.createShamirsSecretShares(inputString, totalShares, thresholdLimit);
console.log("Generated Shares:", shares);
```
## Notes
- Ensure that the necessary dependencies (`shamirSecretShare.str2hex`, `shamirSecretShare.share`) are available and properly implemented before using this function.
- The function will return `false` if the input string is empty or if there is an error during the splitting process.
# retrieveShamirSecret Function Documentation
The `retrieveShamirSecret` function is used to retrieve the original secret by combining the provided Shamir's Secret Sharing shares.
## Parameters
- **sharesArray** (Array): An array containing Shamir's Secret Sharing shares to be combined.
## Return Value
- (String or Boolean): The retrieved original secret. Returns `false` if the input shares array is empty or if there is an error during the retrieval process.
## Dependencies
- **shamirSecretShare.combine**: Function to combine shares using Shamir's Secret Sharing algorithm.
- **shamirSecretShare.hex2str**: Function to convert hexadecimal representation to a string.
## Example Usage
```javascript
const sharesArray = ["share1", "share2", "share3"];
const retrievedSecret = floCrypto.retrieveShamirSecret(sharesArray);
console.log("Retrieved Secret:", retrievedSecret);
```
## Notes
- Ensure that the necessary dependencies (`shamirSecretShare.combine`, `shamirSecretShare.hex2str`) are available and properly implemented before using this function.
- The function will return `false` if the input shares array is empty or if there is an error during the retrieval process.
# verifyShamirsSecret Function Documentation
The `verifyShamirsSecret` function is used to verify the provided Shamir's Secret Sharing shares against a given string.
## Parameters
- **sharesArray** (Array): An array containing Shamir's Secret Sharing shares to be verified.
- **str** (String): The original string to be verified against the retrieved secret.
## Return Value
- (Boolean or null): `true` if the shares verify the provided string, `false` otherwise. Returns `null` if the input string is not provided.
## Dependencies
- **retrieveShamirSecret**: Function to retrieve the original secret by combining shares using Shamir's Secret Sharing algorithm.
## Example Usage
```javascript
const sharesArray = ["share1", "share2", "share3"];
const originalString = "original_string_here";
const verificationResult = floCrypto.verifyShamirsSecret(sharesArray, originalString);
console.log("Shares Verification Result:", verificationResult);
```
## Notes
- Ensure that the necessary dependency (`retrieveShamirSecret`) is available and properly implemented before using this function.
- The function will return `null` if the input string is not provided.
# validateASCII Function Documentation
The `validateASCII` function is used to validate a string to ensure it contains only ASCII characters within the printable range (32 to 127) by default.
## Parameters
- **string** (String): The input string to be validated.
- **bool** (Boolean, optional): If `true`, the function returns `true` if the entire string contains only printable ASCII characters; if `false`, it returns an object containing information about invalid characters and their positions. Default is `true`.
## Return Value
- (Boolean or Object or null): Returns `true` if the input string contains only printable ASCII characters. Returns an object containing information about invalid characters and their positions if `bool` is set to `false`. Returns `null` if the input is not a string.
## Example Usage
```javascript
const inputString = "ASCII_string_here";
// Validate ASCII characters
const isValid = floCrypto.validateASCII(inputString);
console.log("Is Valid ASCII?", isValid);
// Validate ASCII characters and get invalid characters with their positions
const invalidChars = floCrypto.validateASCII(inputString, false);
console.log("Invalid Characters:", invalidChars);
```
## Notes
- If `bool` is set to `true`, the function will return `true` if the input string contains only printable ASCII characters; otherwise, it will return `false`.
- If `bool` is set to `false`, the function will return an object containing information about invalid characters and their positions. If there are no invalid characters, it will return an empty object.
- The function will return `null` if the input is not a string.
# convertToASCII Function Documentation
The `convertToASCII` function is used to convert a string to ASCII characters using specified conversion modes.
## Parameters
- **string** (String): The input string to be converted.
- **mode** (String, optional): The conversion mode. Available options are 'hard-unicode', 'soft-unicode', 'hard-remove', and 'soft-remove'. Default is 'soft-remove'.
## Return Value
- (String or null): The converted string. Returns `null` if the input is not a string.
## Example Usage
```javascript
const inputString = "input_string_here";
// Convert to ASCII characters using soft-remove mode
const convertedString = floCrypto.convertToASCII(inputString);
console.log("Converted String:", convertedString);
```
## Notes
- Available conversion modes:
- 'hard-unicode': Converts characters to Unicode escape sequences (e.g., `\uXXXX`).
- 'soft-unicode': Converts characters to Unicode escape sequences if available in `ascii_alternatives` list; otherwise, uses regular Unicode escape sequences.
- 'hard-remove': Removes non-ASCII characters from the string.
- 'soft-remove': Replaces non-ASCII characters with their alternatives from `ascii_alternatives` list if available; otherwise, removes them.
- Ensure that the necessary dependencies (`validateASCII`) and the `ascii_alternatives` list are available and properly implemented before using this function.
- The function will return `null` if the input is not a string.
# revertUnicode Function Documentation
The `revertUnicode` function is used to revert Unicode escape sequences (e.g., `\uXXXX`) back to their corresponding characters in a given string.
## Parameters
- **string** (String): The input string containing Unicode escape sequences to be reverted.
## Return Value
- (String): The string with reverted Unicode escape sequences.
## Example Usage
```javascript
const unicodeString = "\\u0048\\u0065\\u006c\\u006c\\u006f";
const revertedString = floCrypto.revertUnicode(unicodeString);
console.log("Reverted String:", revertedString);
```

344
docs/floDapps.md Normal file
View File

@ -0,0 +1,344 @@
## readSupernodeListFromAPI Function
The `readSupernodeListFromAPI` function is a startup function used to fetch and update the list of supernodes from the Flo blockchain API. It reads supernode data from the blockchain, processes the data, and updates the list of supernodes stored in the local database.
### Function Logic
1. Checks if cloud functionality is enabled for the application. If not, it resolves with "No cloud for this app".
2. Reads the last transaction count or transaction ID from the local database for the cloud storage.
3. Fetches supernode data from the Flo blockchain using the specified query options.
4. Compares the fetched data with the local list of supernodes, updating or removing nodes as necessary.
5. Writes the updated supernode list and the last transaction information to the local database.
6. Initializes the `floCloudAPI` with the updated supernode list.
### Return Value
- Returns a Promise that resolves with a success message upon successful loading and initialization of the supernode list.
### Example Usage
- This function is typically called during the startup process of the application to ensure that the local list of supernodes is up-to-date.
- In this example, the readSupernodeListFromAPI function updates the local list of supernodes based on the data fetched from the Flo blockchain. It resolves with a success message after successfully loading and initializing the supernode list.
```javascript
startUpFunctions.push(function readSupernodeListFromAPI() {
// Function logic as described above
// ...
return new Promise((resolve, reject) => {
// Resolving or rejecting based on success or error
// ...
});
});
```
## readAppConfigFromAPI Function
The `readAppConfigFromAPI` function is a startup function used to fetch and update the application configuration from the Flo blockchain API. It reads application configuration data from the blockchain, processes the data, and updates the local database with sub-admins, trusted IDs, and settings.
### Function Logic
1. Checks if application configuration functionality is enabled for the application. If not, it resolves with "No configs for this app".
2. Reads the last transaction count or transaction ID for the specified application and admin ID from the local database.
3. Fetches application configuration data from the Flo blockchain using the specified query options.
4. Processes the fetched data, updating sub-admins, trusted IDs, and settings in the local database.
5. Resolves with a success message after successfully reading the app configuration from the blockchain.
### Return Value
- Returns a Promise that resolves with a success message upon successful reading and updating of the application configuration.
### Example Usage
- This function is typically called during the startup process of the application to ensure that the local application configuration is synchronized with the data on the blockchain.
- In this example, the readAppConfigFromAPI function updates the local application configuration based on the data fetched from the Flo blockchain. It resolves with a success message after successfully reading and updating the application configuration.
```javascript
startUpFunctions.push(function readAppConfigFromAPI() {
// Function logic as described above
// ...
return new Promise((resolve, reject) => {
// Resolving or rejecting based on success or error
// ...
});
});
```
## loadDataFromAppIDB Function
The `loadDataFromAppIDB` function is a startup function used to load data from the IndexedDB (IDB) storage of the application. It reads specific data sets (`appObjects`, `generalData`, and `lastVC`) from the local IndexedDB and stores them in the respective global variables of the `floGlobals` object.
### Function Logic
1. Checks if cloud functionality is enabled for the application. If not, it resolves with "No cloud for this app".
2. Defines an array `loadData` containing the names of the data sets to be loaded from IndexedDB (`appObjects`, `generalData`, `lastVC`).
3. Iterates through the `loadData` array and creates an array of promises to read all data from each data set in IndexedDB.
4. Uses `Promise.all` to wait for all data reading operations to complete.
5. Assigns the retrieved data to the respective properties of the `floGlobals` object.
6. Resolves with a success message after successfully loading data from IndexedDB.
### Return Value
- Returns a Promise that resolves with a success message upon successful loading of data from IndexedDB.
### Example Usage
- This function is typically called during the startup process of the application to load essential data sets from the local IndexedDB storage.
- In this example, the loadDataFromAppIDB function loads specific data sets from the IndexedDB storage and assigns them to global variables within the floGlobals object. It resolves with a success message after successfully loading the data.
```javascript
startUpFunctions.push(function loadDataFromAppIDB() {
// Function logic as described above
// ...
return new Promise((resolve, reject) => {
// Resolving or rejecting based on success or error
// ...
});
});
```
## callStartUpFunction Function
The `callStartUpFunction` function is a utility function used for executing startup functions sequentially. It takes an index `i` as an argument, which represents the index of the startup function to be executed. This function returns a Promise that resolves when the specified startup function is successfully executed or rejects if there is an error during execution.
### Function Parameters
- **i**: Index of the startup function to be executed.
### Function Logic
1. Takes an index `i` as an argument representing the index of the startup function to be executed.
2. Executes the startup function at the specified index.
3. If the startup function execution is successful, it increments the `callStartUpFunction.completed` counter and logs the result as a successful startup function execution.
4. If the startup function encounters an error, it increments the `callStartUpFunction.failed` counter and logs the error message as a failed startup function execution.
5. Returns a Promise that resolves with `true` when the startup function is successfully executed and rejects with `false` if there is an error during execution.
### Return Value
- Returns a Promise that resolves with `true` if the startup function is executed successfully and rejects with `false` if there is an error during execution.
### Example Usage
- The `callStartUpFunction` function is typically used in a loop to sequentially execute multiple startup functions.
- In this example, the callStartUpFunction function is used to execute startup functions sequentially and handle success and error cases for each function execution.
```javascript
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)
})
});
```
## midStartUp Function
The `midStartUp` function is a utility function used for executing a middle-stage startup function. It checks if the `_midFunction` variable contains a function reference. If `_midFunction` is a function, it executes `_midFunction()`, and the function resolves with a success message. If `_midFunction` is not a function, the function resolves with a message indicating that there is no middle-stage startup function.
### Function Logic
1. Checks if `_midFunction` is a function.
2. If `_midFunction` is a function, it executes `_midFunction()` and resolves with a success message.
3. If `_midFunction` is not a function, it resolves with a message indicating that there is no middle-stage startup function.
### Return Value
- Returns a Promise that resolves with a success message if the middle-stage startup function is executed successfully.
- Returns a Promise that resolves with a message indicating that there is no middle-stage startup function if `_midFunction` is not a function.
### Example Usage
- The `midStartUp` function is typically used to execute a specific function during the middle stage of the application startup process.
```javascript
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")
});
```
## floDapps.launchStartUp Function
The `floDapps.launchStartUp` function is a central startup function responsible for initializing and launching various components of the application. It ensures the setup of the IndexedDB, executes a series of startup functions, and handles the initialization of user-related databases and credentials.
### Function Logic
1. **IndexedDB Initialization:** The function initializes the IndexedDB for the application.
2. **Startup Functions Execution:** Executes a list of startup functions (`startUpFunctions`) using the `callStartUpFunction` function. It logs the progress of the startup functions, indicating completion or failure.
3. **Middle-Stage Startup:** Executes the `midStartUp` function, if available. This function typically handles middle-stage startup tasks.
4. **User Database and Credentials:** Calls `getCredentials` to retrieve user credentials, initializes the user database using `initUserDB`, and loads user data using `loadUserDB`.
5. **Promise Handling:** The function uses promises to manage the asynchronous tasks and resolves with a success message if all tasks are completed successfully. If any task fails, it rejects with an error message.
### Return Value
- Returns a Promise that resolves with a success message when the entire startup process is finished successfully.
- Returns a Promise that rejects with an error message if any part of the startup process fails.
### Example Usage
```javascript
floDapps.launchStartUp()
.then(result => {
console.log(result); // Output: 'App Startup finished successful'
// Further application logic after successful startup
})
.catch(error => {
console.error(error); // Output: 'App Startup failed'
// Handle error and provide user feedback
});
```
## floDapps.manageAppConfig Function
The `floDapps.manageAppConfig` function allows the administrator to manage the application configuration. It enables adding or removing sub-administrators and updating application-specific settings.
### Function Parameters
- **adminPrivKey**: Private key of the administrator for authentication.
- **addList**: An array of FloIDs to be added as sub-administrators. (Optional)
- **rmList**: An array of FloIDs to be removed from sub-administrators. (Optional)
- **settings**: An object containing application-specific settings. (Optional)
### Function Logic
1. **Parameter Validation:** Validates the input parameters. If no changes are provided (addList, rmList, or settings), the function rejects with a message indicating no configuration change.
2. **FloData Preparation:** Prepares the `floData` object containing the application configuration changes, including added sub-administrators, removed sub-administrators, and updated settings.
3. **Admin Privilege Check:** Checks if the provided `adminPrivKey` matches the default admin ID (`DEFAULT.adminID`). If not, it rejects with an "Access Denied" error.
4. **Blockchain Data Writing:** Uses `floBlockchainAPI.writeData` to write the updated `floData` to the Flo blockchain. Resolves with a success message and the transaction result if successful. Rejects with an error message if the write operation fails.
### Return Value
- Returns a Promise that resolves with an array containing the success message ("Updated App Configuration") and the transaction result from the blockchain write operation.
- Returns a Promise that rejects with an error message if any of the following conditions are met:
- No configuration change is provided.
- The provided `adminPrivKey` does not match the default admin ID (`DEFAULT.adminID`).
### Example Usage
```javascript
const adminPrivKey = 'your_admin_private_key';
const addList = ['sub_admin_floID_1', 'sub_admin_floID_2'];
const rmList = ['sub_admin_floID_3'];
const settings = {
key: 'value',
// additional application-specific settings
};
floDapps.manageAppConfig(adminPrivKey, addList, rmList, settings)
.then(result => {
console.log(result[0]); // Output: 'Updated App Configuration'
console.log(result[1]); // Output: Transaction result from blockchain write operation
// Further application logic after successful configuration update
})
.catch(error => {
console.error(error); // Output: Error message if configuration update fails
// Handle error and provide user feedback
});
```
## floDapps.manageAppTrustedIDs Function
The `floDapps.manageAppTrustedIDs` function allows the administrator to manage trusted IDs for the application. It enables adding or removing trusted IDs.
### Function Parameters
- **adminPrivKey**: Private key of the administrator for authentication.
- **addList**: An array of FloIDs to be added as trusted IDs. (Optional)
- **rmList**: An array of FloIDs to be removed from trusted IDs. (Optional)
### Function Logic
1. **Parameter Validation:** Validates the input parameters. If no changes are provided (addList or rmList), the function rejects with a message indicating no change in the list.
2. **FloData Preparation:** Prepares the `floData` object containing the trusted ID changes, including added trusted IDs and removed trusted IDs.
3. **Admin Privilege Check:** Checks if the provided `adminPrivKey` matches the default admin ID (`DEFAULT.adminID`). If not, it rejects with an "Access Denied" error.
4. **Blockchain Data Writing:** Uses `floBlockchainAPI.writeData` to write the updated `floData` to the Flo blockchain. Resolves with a success message and the transaction result if successful. Rejects with an error message if the write operation fails.
### Return Value
- Returns a Promise that resolves with an array containing the success message ("Updated App Configuration") and the transaction result from the blockchain write operation.
- Returns a Promise that rejects with an error message if no change is provided in the list or if the provided `adminPrivKey` does not match the default admin ID (`DEFAULT.adminID`).
### Example Usage
```javascript
const adminPrivKey = 'your_admin_private_key';
const addList = ['trusted_floID_1', 'trusted_floID_2'];
const rmList = ['trusted_floID_3'];
floDapps.manageAppTrustedIDs(adminPrivKey, addList, rmList)
.then(result => {
console.log(result[0]); // Output: 'Updated App Configuration'
console.log(result[1]); // Output: Transaction result from blockchain write operation
// Further application logic after successful trusted IDs update
})
.catch(error => {
console.error(error); // Output: Error message if trusted IDs update fails
// Handle error and provide user feedback
});
```
## floDapps.getNextGeneralData Function
The `floDapps.getNextGeneralData` function allows retrieving the next set of general data based on the specified type and vector clock. It filters the data based on the provided type, vector clock, and optional comment.
### Function Parameters
- **type**: The type of general data to retrieve.
- **vectorClock**: The vector clock to start filtering the data from. If not provided, it defaults to the stored vector clock or '0'.
- **options**: An optional object containing additional filtering options.
- **comment**: Optional. If provided, filters the data based on the specified comment.
- **decrypt**: Optional. Decryption key for decrypting encrypted data. If `true`, it uses the user's private key for decryption.
### Function Logic
1. **Filtering by Type and Vector Clock:** Retrieves general data of the specified type and greater vector clocks than the provided vector clock.
2. **Filtering by Comment (Optional):** If the `comment` option is provided, further filters the data based on the specified comment.
3. **Data Decryption (Optional):** If the `decrypt` option is provided, decrypts the data using the specified decryption key. If `true`, it uses the user's private key for decryption.
4. **Updating Stored Vector Clock:** Updates the stored vector clock for the specified type with the latest vector clock from the retrieved data.
5. **Return Filtered Data:** Returns the filtered general data as an object.
### Return Value
- Returns an object containing the filtered general data based on the specified type, vector clock, comment, and decryption key.
### Example Usage
- In this example, floDapps.getNextGeneralData is used to retrieve and filter the next set of general data for the specified type, vector clock, comment, and decryption key.
```javascript
const type = 'exampleType';
const vectorClock = '12345';
const options = {
comment: 'exampleComment',
decrypt: true
};
const filteredData = floDapps.getNextGeneralData(type, vectorClock, options);
console.log(filteredData);
// Output: Filtered general data based on the specified type, vector clock, comment, and decryption key
```

307
docs/floTokenAPI.md Normal file
View File

@ -0,0 +1,307 @@
## `fetch_api(apicall)`
This utility function performs a fetch request to the specified API endpoint using the provided `apicall`. It returns a promise that resolves with the parsed JSON response if the request is successful, and rejects with the response object or an error if the request fails.
### Parameters:
- **`apicall`** (string): The API endpoint to be called.
### Return Value:
A Promise that resolves with the parsed JSON response if the request is successful, and rejects with the response object or an error if the request fails.
### Example Usage:
```javascript
const apiEndpoint = "exampleEndpoint";
fetch_api(apiEndpoint)
.then(data => {
console.log("API Response:", data);
// Handle the API response data here
})
.catch(error => {
console.error("API Error:", error);
// Handle API errors here
});
```
## `getBalance(floID, token = DEFAULT.currency)`
This function retrieves the balance of the specified FLO address (`floID`) for the given `token`. It returns a promise that resolves with the balance value if the request is successful, and rejects with an error if the request fails.
### Parameters:
- **`floID`** (string): The FLO address for which the balance needs to be retrieved.
- **`token`** (string, optional): The token for which the balance is retrieved. Defaults to `DEFAULT.currency`.
### Return Value:
A Promise that resolves with the balance value if the request is successful, and rejects with an error if the request fails.
### Example Usage:
```javascript
const floID = "exampleFLOAddress";
const token = "exampleToken";
getBalance(floID, token)
.then(balance => {
console.log("Balance:", balance);
// Handle the balance data here
})
.catch(error => {
console.error("Balance Retrieval Error:", error);
// Handle balance retrieval errors here
});
```
## `getTx(txID)`
This function retrieves transaction details for the specified transaction ID (`txID`). It returns a promise that resolves with the transaction details if the request is successful and rejects with an error if the request fails.
### Parameters:
- **`txID`** (string): The unique identifier of the transaction for which details are retrieved.
### Return Value:
A Promise that resolves with the transaction details if the request is successful, and rejects with an error if the request fails.
### Example Usage:
```javascript
const txID = "exampleTxID";
getTx(txID)
.then(transactionDetails => {
console.log("Transaction Details:", transactionDetails);
// Handle the transaction details here
})
.catch(error => {
console.error("Transaction Retrieval Error:", error);
// Handle transaction retrieval errors here
});
```
## `tokenAPI.sendToken(privKey, amount, receiverID, message = "", token = DEFAULT.currency, options = {})`
This function allows sending a specified amount of tokens from the sender to a receiver. It takes the following parameters:
- **`privKey`** (string): Private key of the sender.
- **`amount`** (number): Amount of tokens to be sent.
- **`receiverID`** (string): FLO ID of the receiver.
- **`message`** (string, optional): Additional message to attach to the transaction (default is an empty string).
- **`token`** (string, optional): Token type to be sent (default is `DEFAULT.currency`).
- **`options`** (object, optional): Additional options for the transaction (default is an empty object).
### Parameters:
- **`privKey`** (string): Private key of the sender.
- **`amount`** (number): Amount of tokens to be sent.
- **`receiverID`** (string): FLO ID of the receiver.
- **`message`** (string, optional): Additional message to attach to the transaction (default is an empty string).
- **`token`** (string, optional): Token type to be sent (default is `DEFAULT.currency`).
- **`options`** (object, optional): Additional options for the transaction (default is an empty object).
### Return Value:
A Promise that resolves to the transaction ID (txid) if the transaction is successful. If there are any errors, the Promise is rejected with an error message.
### Example Usage:
```javascript
const privKey = "senderPrivateKey";
const amount = 100;
const receiverID = "receiverFLOID";
const message = "Payment for services";
const token = "exampleToken";
const options = { fee: 0.1, someOption: "value" };
tokenAPI.sendToken(privKey, amount, receiverID, message, token, options)
.then(txid => {
console.log("Transaction ID:", txid);
})
.catch(error => {
console.error("Error:", error);
});
```
## `sendTokens_raw(privKey, receiverID, token, amount, utxo, vout, scriptPubKey)`
This function is a low-level utility used to send tokens from a specific Unspent Transaction Output (UTXO) to a receiver. It takes the following parameters:
- **`privKey`** (string): Private key of the sender.
- **`receiverID`** (string): FLO ID of the receiver.
- **`token`** (string): Token type to be sent.
- **`amount`** (number): Amount of tokens to be sent.
- **`utxo`** (string): UTXO (Unspent Transaction Output) hash.
- **`vout`** (number): Vout (index) of the UTXO in the transaction.
- **`scriptPubKey`** (string): Script Public Key associated with the UTXO.
### Parameters:
- **`privKey`** (string): Private key of the sender.
- **`receiverID`** (string): FLO ID of the receiver.
- **`token`** (string): Token type to be sent.
- **`amount`** (number): Amount of tokens to be sent.
- **`utxo`** (string): UTXO (Unspent Transaction Output) hash.
- **`vout`** (number): Vout (index) of the UTXO in the transaction.
- **`scriptPubKey`** (string): Script Public Key associated with the UTXO.
### Return Value:
A Promise that resolves to an array containing the receiver's FLO ID and the transaction ID (txid) if the transaction is successful. If there are any errors, the Promise is rejected with an array containing the receiver's FLO ID and the error message.
### Example Usage:
```javascript
const privKey = "senderPrivateKey";
const receiverID = "receiverFLOID";
const token = "exampleToken";
const amount = 100;
const utxo = "utxoHash";
const vout = 0;
const scriptPubKey = "scriptPublicKey";
sendTokens_raw(privKey, receiverID, token, amount, utxo, vout, scriptPubKey)
.then(([receiver, txid]) => {
console.log(`Tokens sent to ${receiver}. Transaction ID: ${txid}`);
})
.catch(([receiver, error]) => {
console.error(`Failed to send tokens to ${receiver}. Error: ${error}`);
});
```
## `tokenAPI.bulkTransferTokens(sender, privKey, token, receivers)`
This function facilitates bulk token transfers from a sender to multiple receivers. It takes the following parameters:
- **`sender`** (string): FLO ID of the sender.
- **`privKey`** (string): Private key corresponding to the sender's FLO ID.
- **`token`** (string): Token type to be transferred.
- **`receivers`** (object): An object containing receiver addresses as keys and the corresponding token amounts as values.
### Parameters:
- **`sender`** (string): FLO ID of the sender.
- **`privKey`** (string): Private key corresponding to the sender's FLO ID.
- **`token`** (string): Token type to be transferred.
- **`receivers`** (object): An object representing receivers and their corresponding token amounts. The format of the object should be `{ receiver1: amount1, receiver2: amount2, ... }`.
### Return Value:
A Promise that resolves to an object containing successful transactions and any failed transactions. The resolved object has the following format:
```javascript
{
success: {
receiver1: txid1,
receiver2: txid2,
// ... other successful transactions
},
failed: {
receiverX: "error message",
// ... other failed transactions
}
}
// If the function encounters any invalid inputs or errors during the process, it rejects the Promise with an error message.
```
### Example Usage
```javascript
const sender = "senderFLOID";
const privKey = "senderPrivateKey";
const token = "exampleToken";
const receivers = {
"receiver1FLOID": 100,
"receiver2FLOID": 200,
// ... other receivers and amounts
};
tokenAPI.bulkTransferTokens(sender, privKey, token, receivers)
.then(result => {
console.log("Successful Transactions:", result.success);
console.log("Failed Transactions:", result.failed);
})
.catch(error => {
console.error("Error:", error);
});
```
## `tokenAPI.getAllTxs(floID, token = DEFAULT.currency)`
This function retrieves all transactions associated with a specific FLO ID and token. It takes the following parameters:
- **`floID`** (string): FLO ID for which transactions need to be retrieved.
- **`token`** (string, optional): Token type for which transactions need to be retrieved. Defaults to the DEFAULT currency.
### Parameters:
- **`floID`** (string): FLO ID for which transactions need to be retrieved.
- **`token`** (string, optional): Token type for which transactions need to be retrieved. Defaults to the DEFAULT currency.
### Return Value:
A Promise that resolves to the result of the API call, containing the transactions associated with the specified FLO ID and token.
### Example Usage:
```javascript
const floID = "exampleFLOID";
const token = "exampleToken";
tokenAPI.getAllTxs(floID, token)
.then(transactions => {
console.log("All transactions for FLO ID:", floID);
console.log(transactions);
})
.catch(error => {
console.error("Error fetching transactions:", error);
});
```
## `util.parseTxData(txData)`
This utility function parses transaction data and extracts relevant information such as sender, receiver, parsed FLO data, and timestamp.
### Parameters:
- **`txData`** (object): Transaction data object to be parsed.
### Return Value:
An object containing the parsed transaction data with the following properties:
- **`sender`** (string): Address of the sender.
- **`receiver`** (string): Address of the receiver.
- **`parsedFloData`** (object): Parsed FLO data extracted from the transaction.
- **`time`** (number): Timestamp of the transaction in Unix epoch format.
### Example Usage:
- In this example, the util.parseTxData function is used to parse the provided txData object. It extracts sender, receiver, parsed FLO data, and the transaction timestamp. The function returns an object containing the parsed data for further processing or display.
```javascript
const txData = {
parsedFloData: {
key1: "value1",
key2: "value2"
// ...other parsed FLO data fields
},
transactionDetails: {
vin: [{ addr: "senderAddress" }],
vout: [{ scriptPubKey: { addresses: ["receiverAddress"] } }],
time: 1633442400 // Unix timestamp
// ...other transaction details
}
};
const parsedData = util.parseTxData(txData);
console.log(parsedData);
```

View File

@ -1,4 +1,6 @@
## Function: CheckDB
### This is a desciption of what we think are the functions that need some explaining in messenger.js and index.html It does not include explanations for Standard Operations functions for which you need to refer documentation of Standard Operations. It also does not include functions in messenger.js and index.html whose code is self evident.
## `CheckDB()`
### Description:
This function initializes a database connection based on the configuration provided in `config.json`. It then retrieves data structure information from `data_structure.json` and calculates CRC checksums for each column specified in the data structure. The function then queries each database table specified in `Database.DB.listTable()` and calculates the total number of records and CRC checksums for each table. The results are logged using `console.table`. Any errors during the process are logged using `console.error`.
@ -19,10 +21,10 @@ CheckDB()
});
```
## Function: sendRaw
## `sendRaw(message, recipient, type, encrypt)`
### Description:
This function sends raw application data messages to a recipient using Supernode Cloud. It allows for optional encryption of the message using the recipient's public key, if available.
This function is at the heart of messenger application. This function sends raw application data messages to a recipient using Supernode Cloud. It allows for optional encryption of the message using the recipient's public key, if available.
### Parameters:
- **message (string)**: The raw message data to be sent.
@ -41,7 +43,7 @@ sendRaw("Hello, recipient!", "recipient_address", "message_type", true, "Optiona
.catch(error => console.error("Error sending message:", error));
```
## Function: initUserDB
## `initUserDB()`
### Description:
This function initializes the user database for a messenger application. It creates an initial object structure with empty data fields for messages, mails, marked items, chats, groups, encryption keys, blocked contacts, pipeline, friend requests sent and received, responses sent and received, additional data (`flodata`), appendix, user settings, and multisig labels. The function requires specific data, including `floGlobals.application`, `floCrypto`, and `user.id`, to construct the `user_db` variable, which is used as the unique identifier for the user's database. It then initializes the IndexedDB database using the `compactIDB.initDB()` method and sets the default database. Upon successful initialization, it resolves with a success message.
@ -120,7 +122,7 @@ listRequests(myObjects, { type: "sampleType", completed: true })
## `processData.direct()`
Processes incoming data from various sources and updates the local database accordingly.
Processes incoming data for individual user mails and messages and updates the local database accordingly.
### Description
This function processes incoming data, decrypts messages if necessary, and updates the local database (`compactIDB`). It handles different types of incoming messages and actions, including regular messages, requests, responses, mails, group creation, key revocation, and pipeline creation.
@ -1139,3 +1141,121 @@ The function determines the type of conversation (chat or group) based on the pr
- If the conversation is a group and the last message has a timestamp of 0, it means the group was just created. In this case, the group creation time is used as the last message time.
- The function formats the last message for display purposes, adding sender information (or 'You' for sent messages) and handling blocked conversations appropriately.
- The formatted last message object is returned in the resolved Promise.
## `delegate` Function Explanation
The `delegate` function is a utility function in JavaScript used to implement event delegation. Event delegation is a technique where a single event listener is attached to a common ancestor element of multiple child elements. Instead of attaching event listeners to each child element individually, event delegation allows you to handle events for all child elements in a more efficient manner. When an event occurs, it bubbles up from the target element to the ancestor element, where the event listener is placed. The `delegate` function facilitates this pattern.
### Function Parameters:
- `el`: The common ancestor element to which the event listener is attached.
- `event`: The type of event (e.g., "click", "mouseover", etc.) to listen for.
- `selector`: A CSS selector string specifying the child elements for which the event should be delegated.
- `fn`: The callback function to be executed when the event occurs on a matching child element.
### Function Logic:
1. The `delegate` function takes in the ancestor element `el`, the event type `event`, the CSS selector `selector` for child elements, and the callback function `fn`.
2. It attaches an event listener to the ancestor element (`el`) for the specified event type (`event`).
3. When the event occurs on any descendant element of `el`, the event object (`e`) is passed to the event listener function.
4. Inside the event listener function, `e.target` represents the element on which the event actually occurred. The `closest` method is used to find the closest ancestor of the target element that matches the specified `selector`.
5. If a matching ancestor element is found (`potentialTarget`), the `delegateTarget` property is added to the event object (`e`). This property refers to the ancestor element that matches the specified selector.
6. The callback function `fn` is then executed in the context of the ancestor element (`this`). The event object (`e`) is passed to the callback function, allowing you to handle the event on the matching child element.
## `getFloIdType` Function
The `getFloIdType` function is used to determine the type of a given FLO ID in the context of the messenger application. It checks whether the provided FLO ID belongs to a group, a pipeline, or if it is a plain individual FLO ID.
### Function Parameters:
- `floID`: The FLO ID for which the type needs to be determined.
### Return Value:
- `'group'`: If the provided FLO ID belongs to a group.
- `'pipeline'`: If the provided FLO ID belongs to a pipeline.
- `'plain'`: If the provided FLO ID is an individual, not associated with a group or pipeline.
### Function Logic:
1. The `getFloIdType` function takes in a `floID` as a parameter.
2. It checks if the `floID` exists in the `messenger.groups` object. If it does, the function determines that the `floID` belongs to a group and returns `'group'`.
3. If the `floID` is not found in `messenger.groups`, the function checks if it exists in the `messenger.pipeline` object. If found, it indicates that the `floID` belongs to a pipeline and returns `'pipeline'`.
4. If the `floID` is not found in either `messenger.groups` or `messenger.pipeline`, the function concludes that it is a plain individual FLO ID and returns `'plain'`.
## `renderDirectUI(data)`
The JavaScript function `renderDirectUI(data)` is designed to handle the rendering of direct messages and mails in a user interface. This function plays a crucial role in updating the UI and providing notifications to the user based on new messages and mails, ensuring a responsive and interactive user experience.
### Parameters
- `data`: An object containing messages and mails data to be rendered in the UI.
### Function Logic
1. **New Message Notifications:**
- If there are new messages in the `data.messages` object and the last visited page is not 'chat_page', it updates the document title to indicate the presence of new messages and adds a notification badge to the 'chat_page_button'.
2. **New Mail Notifications:**
- If there are new mails in the `data.mails` object and the last visited page is not 'mail_page', it updates the document title to indicate the presence of new mails and adds a notification badge to the 'mail_page_button'.
3. **Notification Panel Updates:**
- It queries the server for uncompleted requests (`messenger.list_request_received({ completed: false })`) and updates the notification badge on the 'notification_panel_button' based on the number of pending requests.
4. **Message UI and Mail List Rendering:**
- It calls the `updateMessageUI(data.messages)` function to update the UI with new messages.
- It calls the `renderMailList(data.mails, true)` function to render the mail list, passing `true` as a parameter to indicate that these are new mails.
### Usage Example:
```javascript
// Example usage of the renderDirectUI function
const data = {
messages: { /* ... */ }, // New messages data
mails: { /* ... */ } // New mails data
};
renderDirectUI(data);
```
## `renderMailList(mails, markUnread = true)`
The JavaScript function `renderMailList(mails, markUnread = true)` is responsible for rendering mail items into the user interface. This function dynamically updates the mail interface, ensuring that mails are displayed in the inbox and sent mail categories.
### Parameters
- `mails`: An object containing mail data to be rendered in the UI.
- `markUnread` (optional, default: `true`): A boolean indicating whether unread mails should be marked.
### Function Logic
1. **Initialization:**
- It initializes two DocumentFragments, `inboxMails` and `sentMails`, to store the rendered mail items for inbox and sent mail categories respectively.
- Variables `inboxCount` and `sentCount` are initialized to keep track of the number of unread mails in each category.
2. **Mail Iteration and Rendering:**
- It iterates through the provided `mails` object and extracts mail details such as sender (`from`), receiver (`to`), subject, time, and content.
- Depending on whether the mail is sent by the user or received by the user, it renders the mail card using the `render.mailCard()` function. If `markUnread` is `true`, it increments the corresponding unread mail count.
- If there are replies (`prev` property), it removes the previous mail card from the rendering to avoid duplicates.
3. **Notification Badges:**
- It updates notification badges on the mail type selector based on the number of unread mails. If the current mail type selector is 'inbox', it adds the unread count to the 'sent' category badge, and vice versa.
4. **Rendering into UI:**
- It prepends the rendered inbox mails into the `inbox_mail_container` and sent mails into the `sent_mail_container` in the UI.
## `getChatCard(floID)`
This function retrieves the chat card element based on the given FloID (or Bitcoin address) from the chats list.
#### Parameters
- `floID` (string): The FloID or Bitcoin address for which the chat card needs to be retrieved.
#### Returns
- Returns the chat card element associated with the provided FloID or Bitcoin address. If no matching chat card is found, it returns `null`.
#### Function logic
- The floID parameter is first converted to a FloID using floCrypto.toFloID(floID).
- The Bitcoin address corresponding to the FloID is obtained using btcOperator.convert.legacy2bech(floID).
- The function queries the chats list using the getRef('chats_list') function.
- It searches for an element with the attribute data-flo-address set to the provided FloID or Bitcoin address.
- If a matching element is found, it is returned. Otherwise, null is returned indicating no matching chat card was found.

9
docs/product-overview.md Normal file
View File

@ -0,0 +1,9 @@
# FLO Messenger
• Messenger is a blockchain-based decentralized messaging app that uses Bitcoin or FLO blockchain addresses as user identities. Instead of a centralized server, messages are encrypted and stored in the users' browsers.
• Bitcoin or FLO blockchain addresses can communicate with each other using a messaging interface
• Messenger comes with "Multisig" where users can create multi-sig addresses and using a messaging interface make transactions on the multi-sig.
• Switching browsers or devices won't bring back old messages. Remember to back up and import to access your messages in the new browser/device. That's the security of Messenger.
#### Note:
Do not lose the private key. Copy and save it securely. Once a private key is lost, it cannot be recovered

41
docs/render.html Normal file
View File

@ -0,0 +1,41 @@
<!-- A simple example illustrating render logic we have extensively used in this application -->
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Dynamic List with uhtml</title>
</head>
<body>
<div id="app"></div>
<script src="https://unpkg.com/uhtml@3.0.1/es.js"></script>
<script>
const { html, render } = uhtml;
// Data to be displayed
const items = ['Apple', 'Banana', 'Cherry', 'Date', 'Elderberry'];
// Function to render items using uhtml
function renderItems(items) {
return html`
<ul>
${items.map(item => html`<li>${item}</li>`)}
</ul>
`;
}
// Render items into the 'app' element
const appElement = document.getElementById('app');
// render is defined and exported from uhtml. html is also define and exported from uhtml
// Create html first, and then render it
// Creates actual HTML when render is applied to something that creates html
render(appElement, renderItems(items));
</script>
</body>
</html>

View File

@ -0,0 +1,594 @@
# Messenger Architecture
### Standard Operations Configuration
### `floGlobals Object`
- floGlobals is a standard object used in Standard Operations based App
- floGlobals.adminID is the blockchain based address whose commands all browser clients will follow. Currently it is `floGlobals.adminID: "FMRsefPydWznGWneLqi4ABeQAJeFvtS3aQ"`
- floGlobals.name is "messenger" indicating name of application
- floGlobals.idInterval is the time interval used to switch display between your Bitcoin Address used to log-in, and FLO address
- floGlobals.subadmins are used to do regular access control in the mesenger app. Currently there are none set
### `processData` object
- Understanding `processData` object is key to understand messenger product
- Overview of processDAta: `processData` is the processing part of messenger. There are kinds of `processData` activities:
1. `processData.direct` - This is used in processing individual mails and messages
2. `processData.group(groupID)` - This is used in processing group messages
3. `processData.pipeline[model](pipeID);` - This is used in processing any pipeline events foor
### Product Pipelines
1. The core feature of the product is pipelines. A pipeline is created by invloking inbuilt models
2. Right now we have models for Multisig creation for Bitcoin and FLO Multisigs.
3. What is pipeline ?
• It has an ID
• It has model like TYPE_BTC_MULTISIG
• It has members like different Bitcoin IDs or FLO IDs
• It has an encryption key unique to the pipeline, and known just to members of that pipeline
4. A pipeline sends custom messages defined as per a model to an attached group
5. Pipeline ID could be a recipient of a message. Then every Bitcoin or FLO Address will get the message with the action needed for that pipeline
# Let us specify all DATA DEFINITIONS used in Messenger Application first
## The master object encapsulates all the functionalities
```
var obj = {
messages: {},
mails: {},
marked: {},
chats: {},
groups: {},
gkeys: {},
blocked: {},
pipeline: {},
request_sent: {},
request_received: {},
response_sent: {},
response_received: {},
flodata: {},
appendix: {},
userSettings: {},
multisigLabels: {}
}
```
## Internal message `types` defined in application for usage in sendApplicationData
### The key to understand messenger application is to start with message types first
For sendraw function, `function sendRaw(message, recipient, type, encrypt = null, comment = undefined)` following types are defined
- "MESSAGE"
- "MAIL"
- "REQUEST"
- "RESPONSE"
- "UP_NAME"
- "UP_DESCRIPTION"
- "CREATE GROUP"
- "ADD_MEMBERS"
- "RM_MEMBERS"
- "REVOKE_KEY"
- "GROUP_MSG"
- "TRANSACTION"
- "BROADCAST"
- "CREATE_PIPELINE"
#### function `sendRaw(message, recipient, type, encrypt = null, comment = undefined)` packages the input parameters into `floCloudAPI.sendApplicationData(message, type, options)`
- options contain options.receiverID, and options.comment
```options = {
receiverID: recipient,
}
if (comment)
options.comment = comment
```
### Message Payload: When a message is sent it has a payload of vectorclock and data.
```
sendRaw(message, receiver, "MESSAGE").then(result => {
let vc = result.vectorClock;
let data = {
floID: receiver,
time: result.time,
category: 'sent',
message: encrypt(message)
}
```
### Description of Mail Object
```
let mail = {
subject: subject,
content: content,
ref: Date.now() + floCrypto.randString(8, true),
prev: prev
}
let promises = recipients.map(r => sendRaw(JSON.stringify(mail), r, "MAIL"))
```
### SendRequest types
- "PUBLIC_KEY"
- This is used in sendResponse as well
```
sendRequest(receiver, "PUBLIC_KEY", message, false);
```
### Understanding GroupInfo
- Contains groupInfo.eKey, groupInfo.admin, groupInfo.members, groupInfo.disabled, groupInfo.name
### Understanding DataList
- dataList = ["messages", "mails", "marked", "chats", "groups", "gkeys", "pipeline", "blocked", "appendix"]
- defaultList : dataList = ["mails", "marked", "groups", "pipeline", "chats", "blocked", "appendix"]
### Understanding Mapping between functionalities and sendRaw messages
This section illustrates how functionaility is getting translated into sendRaw feature
- messenger.changeGroupName = function (groupID, name)
- sendRaw(message, groupID, "UP_NAME", false)
- messenger.changeGroupDescription = function (groupID, description)
- sendRaw(message, groupID, "UP_DESCRIPTION", false)
- messenger.addGroupMembers = function (groupID, newMem, note = undefined)
- sendRaw(message, groupID, "ADD_MEMBERS", false, note)
- messenger.rmGroupMembers = function (groupID, rmMem, note = undefined)
- p1 = sendRaw(message, groupID, "RM_MEMBERS", false, note)
- messenger.revokeKey = function (groupID)
- groupInfo.members.map(m => sendRaw(JSON.stringify({
newKey,
groupID
}), m, "REVOKE_KEY", true))
- messenger.sendGroupMessage = function (message, groupID)
- sendRaw(message, groupID, "GROUP_MSG", false)
- message = encrypt(tx_hex, pipeline.eKey);
- sendRaw(message, pipeline.id, "TRANSACTION", false)
- btcOperator.broadcastTx(tx_hex_signed)
- sendRaw(encrypt(txid, pipeline.eKey), pipeline.id, "BROADCAST", false)
- messenger.createPipeline = function (model, members, ekeySize = 16, pubkeys = null)
- sendRaw(pipelineInfo, m, "CREATE_PIPELINE", true));
- messenger.sendPipelineMessage = function (message, pipeID)
- sendRaw(message, pipeID, "MESSAGE", false)
### Understanding appendix
It has two usages in the application
- appendix.lastReceived to compare against what vectorClock data we have
- appendix.AESKey to check what encryption keys to be used
### compactIDB.addData and compactIDB.writeData
- The addData function is used to add new records to an object store. It will throw an error if the key already exists
- The writeData function is used to update or insert data into an object store. It will update if the key already exists
### Why do we use uhtml
uhtml is a small, efficient, and ultra-fast JavaScript library for creating web components and managing the DOM (Document Object Model). It allows developers to write templates directly in JavaScript without needing a separate build step. uhtml focuses on minimalism and performance, aiming to provide a lightweight solution for rendering dynamic content in web applications.
## Here's a brief overview of what uhtml does:
- Template Rendering: uhtml provides a way to create HTML templates directly in JavaScript code. These templates can include dynamic content and data-binding expressions.
- Virtual DOM: uhtml utilizes a virtual DOM approach, where changes to the UI are first made in memory (virtual DOM), and then efficiently applied to the actual DOM, reducing unnecessary reflows and repaints.
- Efficiency: uhtml is designed to be incredibly fast and efficient. It achieves this by minimizing the overhead associated with creating and updating DOM elements.
- Reactivity: uhtml templates can be reactive, meaning they can automatically update when the underlying data changes. This reactivity is often used in modern web frameworks to create responsive and dynamic user interfaces.
## Explain the UI process
### `getRef(elementId)`
getRef is the cornerstone of UI in Messenger App. getRef(elementId), is a custom utility function designed to improve the efficiency of accessing DOM elements by their IDs. It provides a way to cache references to DOM elements and reuse them, reducing the number of times the actual DOM is queried. Instead of using `document.getElementById(elementId)` directly in the code, we use `getRef(elementId)` to access the DOM elements. The function takes care of efficient element retrieval and caching.
getRef(elementId) Function:
1. getRef(elementId) is a custom JavaScript function used to obtain references to DOM elements using their unique IDs. It optimizes the process of accessing DOM elements by caching the references, allowing for efficient reuse without the need to repeatedly query the DOM. When you call getRef('mail_contact_list'), it returns the DOM element with the ID 'mail_contact_list'.
2. We use getRef(elementId) instead of document.getElementById
### uhtml Library Usage:
1. uhtml is a JavaScript library for efficient and lightweight HTML templating and rendering. It allows you to create HTML templates directly in your JavaScript code.
2. The line const { html, render: renderElem } = uhtml; imports the html function and an alias for the render function from the uhtml library. The html function is used to create HTML template literals, and renderElem is used to render those templates into DOM elements efficiently.
- Rendering HTML with renderElem():
1. The code renderElem(getRef('mail_contact_list'), html${mailingContacts}) combines the previously mentioned concepts. Here's what's happening:
2. html${mailingContacts} creates an HTML template literal using the uhtml library. It represents the HTML structure defined by the mailingContacts variable.
3. getRef('mail_contact_list') retrieves the DOM element with the ID 'mail_contact_list' using the custom getRef() function.
4. renderElem(targetElement, htmlTemplate) is a call to the renderElem function from the uhtml library. It takes two parameters: the target DOM element where the rendered HTML will be appended (getRef('mail_contact_list') in this case) and the HTML template created with the html function.
### A direct simple example explaining the render logic
```
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Dynamic List with uhtml</title>
</head>
<body>
<div id="app"></div>
<script src="https://unpkg.com/uhtml@3.0.1/es.js"></script>
<script>
const { html, render } = uhtml;
// Data to be displayed
const items = ['Apple', 'Banana', 'Cherry', 'Date', 'Elderberry'];
// Function to render items using uhtml
function renderItems(items) {
return html`
<ul>
${items.map(item => html`<li>${item}</li>`)}
</ul>
`;
}
// Render items into the 'app' element
const appElement = document.getElementById('app');
render(appElement, renderItems(items));
</script>
</body>
</html>
```
### Functions created for Rendering
```
messenger.renderUI.chats = renderChatList;
messenger.renderUI.directChat = renderDirectUI;
messenger.renderUI.groupChat = renderGroupUI;
messenger.renderUI.pipeline = renderPipelineUI;
messenger.renderUI.mails = m => renderMailList(m, false);
messenger.renderUI.marked = renderMarked;
```
### There are two meanings of render in the UI of messenger application
1. In class lazyloader, this.render() is a method internal to lazyloader based objects
2. In uhtml invocations, render creates actual html when `html` parameter is fed to it
### Example of uhtml html creation
- METHOD 1: render.something () In the code below function takes floID as input parameter, and return uhtml compatible html. This can then be fed to `render.selectableContact(contact)` for actual HTML creation
```
//HTML creation stage
selectableContact(floID) {
const name = getContactName(floID)
const initial = name.charAt(0)
return html`
<label class="flex align-center selectable-contact interactive" data-flo-address=${floID} style=${`--contact-color: var(${contactColor(floID)})`}>
<div class="initial flex align-center"> ${initial} </div>
<div class="grid gap-0-3">
<h4 class="name">${name}</h4>
<p class="contact__flo-address wrap-around">${floID}</p>
</div>
<input type="checkbox" autocomplete="off" value=${floID}/>
</label>
`
}
//At render stage
render.selectableContact(contact);
```
- METHOD 2: renderElem(getRef,html) method. Another way we have used to to achieve html from render is the code snippet below using renderElem function
```
const { html, render: renderElem } = uhtml;
function renderContactList(contactList = floGlobals.contacts) {
const contacts = Object.keys(contactList)
.sort((a, b) => getContactName(a).localeCompare(getContactName(b)))
.map(floID => {
const isSelected = selectedMembers.has(floID)
return render.contactCard(floID, { type: 'contact', isSelected, ref: getRef('contacts_container') })
})
renderElem(getRef('contacts_container'), html`${contacts}`)
}
```
## How do you create new models
- Lets look at usage of createPipeline function which uses `TYPE_BTC_MULTISIG` model here.
```
createPipeline(TYPE_BTC_MULTISIG, co_owners, 32, decode.pubkeys).then(pipeline => {
let message = encrypt(tx_hex, pipeline.eKey);
sendRaw(message, pipeline.id, "TRANSACTION", false)
.then(result => resolve(pipeline.id))
.catch(error => reject(error)) //SENDRAW
}).catch(error => reject(error)) //CREATE PIPELINE
```
- To design a new model, you need to define the states the pipeline in the model will take, and also define the message types that will move the state forward.
- A model tells what are the types of messages in that system, and how should they be handled. There is no explicit definition of model. Rather we straight define the processing logic as part of processData.pipeLine function, and it initiates the model.
- You need to define what are the type of messages in your model. For instance the message types for `TYPE_BTC_MULTISIG` model are "TRANSACTION", "BROADCAST" and "MESSAGE".
- If the model message type is "TRANSACTION", then it needs to be signed by anyone of the person who sees this first, and then needs to sign the BTC Multisig transaction.
- If the model message type is "BROADCAST", then all signatures are received, and multisig messaeg has to be broadcasted to the blockchain.
- If the model message type is "MESSAGE", then simply show the message to all members in the pipeline
- Similarly as part of model design, you need to identify the types of messages for the models first.
- Then you need to create the processing logic for each type of message in processData.pipeline[MODEL_NAME]. It will have a common processing section and switch case for each of the message type
- A pipelines moves its state forward as the message type changes due to action of members.
- The model processing logic specified how the state of pipeline changes.
- In this example the state of pipeline changes as soon as one member performs an action which leads him client to proclaim the state of pipeline has moved to the next message
- States in TYPE_BTC_MULTISIG model are Create -> Transact -> Transact -> Broadcast -> close if it is 2 of 3 BTC Multisig
- After the processing, the message has to be given to inboxes of correct recipients like using `newInbox.messages[vc] = data;`
- You should also store a copy of that message locally like using `compactIDB.addData("messages", Object.assign({}, data),${pipeID}|${vc});`
- Every pipeline is identified by a system generated pipeID which is made available to creator and members when a new pipleline is created
```
//pipeline model for btc multisig
processData.pipeline[TYPE_BTC_MULTISIG] = function (pipeID) {
return (unparsed, newInbox) => {
if (!_loaded.pipeline[pipeID].members.includes(floCrypto.toFloID(unparsed.senderID)))
return;
let data = {
time: unparsed.time,
sender: unparsed.senderID,
pipeID: unparsed.receiverID
}
let vc = unparsed.vectorClock,
k = _loaded.pipeline[pipeID].eKey;
unparsed.message = decrypt(unparsed.message, k)
//store the pubKey if not stored already
floDapps.storePubKey(unparsed.senderID, unparsed.pubKey);
data.type = unparsed.type;
switch (unparsed.type) {
case "TRANSACTION": {
data.tx_hex = unparsed.message;
break;
}
case "BROADCAST": {
data.txid = unparsed.message;
//the following check is done on parallel (in background) instead of sync
btcOperator.getTx.hex(data.txid).then(tx_hex_final => {
getChat(pipeID).then(result => {
let tx_hex_inital = Object.keys(result).sort().map(i => result[i].tx_hex).filter(x => x).shift();
if (btcOperator.checkIfSameTx(tx_hex_inital, tx_hex_final))
disablePipeline(pipeID);
}).catch(error => console.error(error))
}).catch(error => console.error(error))
break;
}
case "MESSAGE": {
data.message = encrypt(unparsed.message);
break;
}
}
compactIDB.addData("messages", Object.assign({}, data), `${pipeID}|${vc}`);
if (data.message)
data.message = decrypt(data.message);
newInbox.messages[vc] = data;
}
}
```
## Ok. The model is created. How do I use it
- After a model has been created in processData.pipeline[YOUR_MODEL_NAME] with pipeID as the input parameter, the first action is creation of pipeline using that model.
- Pipeline creation is a standard function, and as new model creator, the system does it all for you. All you have to do is to use messenger.createPipeline with model parameter as YOUR_MODEL_NAME.
- Pipeline creation does not need a special message type. It will be created by the initiator, and sent as messages to everyone who is member of that pipeline.
- However once the message has been given to all users, a valid action from any of them can move the state of pipeline forward, and your model processing logic has to handle what do do next.
- Such sequence of actions has to be defined till the state reaches closure.
- You can also define role based messages in model processing logic, and assign those roles to specific Bitcoin or FLO IDs. Each of them will need their own message type. Switch case of message type has has handle the sequencing of hange of state.
- Role based implementation was not needed in Multisig cases. But it could be created if use case emerges by expanding the processing states.
- In theory role definition can be done at model stage. But role allocation will need the creator to act, and that would mean that createPipeline function will need an expansion.
```
const createPipeline = messenger.createPipeline = function (model, members, ekeySize = 16, pubkeys = null) {
return new Promise((resolve, reject) => {
//optional pubkey parameter
if (pubkeys !== null) {
if (!Array.isArray(pubkeys))
return reject('pubkeys must be an array (if passed)');
else if (pubkeys.length !== members.length)
return reject('pubkey length doesnot match members length');
}
//validate members
let imem1 = [],
imem2 = []
members.forEach((m, i) => {
if (!floCrypto.validateAddr(m))
imem1.push(m);
else if (!(m in floGlobals.pubKeys) && !floCrypto.isSameAddr(user.id, m)) {
if (pubkeys !== null && floCrypto.verifyPubKey(pubkeys[i], m))
floGlobals.pubKeys[m] = pubkeys[i];
else
imem2.push(m);
}
});
if (imem1.length)
return reject(`Invalid Members(floIDs): ${imem1}`);
else if (imem2.length)
return reject(`Invalid Members (pubKey not available): ${imem2}`);
//create pipeline info
const id = floCrypto.tmpID;
let pipeline = {
id,
model,
members
}
if (ekeySize)
pipeline.eKey = floCrypto.randString(ekeySize);
//send pipeline info to members
let pipelineInfo = JSON.stringify(pipeline);
let promises = members.filter(m => !floCrypto.isSameAddr(m, user.id)).map(m => sendRaw(pipelineInfo, m, "CREATE_PIPELINE", true));
Promise.allSettled(promises).then(results => {
console.debug(results.filter(r => r.status === "rejected").map(r => r.reason));
_loaded.pipeline[pipeline.id] = Object.assign({}, pipeline);
if (pipeline.eKey)
pipeline.eKey = encrypt(pipeline.eKey);
compactIDB.addData("pipeline", pipeline, pipeline.id).then(result => {
requestPipelineInbox(pipeline.id, pipeline.model);
resolve(_loaded.pipeline[pipeline.id])
}).catch(error => reject(error))
})
})
}
```
## Explain me the full cycle of pipeline creation process
- TYPE_BTC_MULTISIG pipeline is created in MultiSig.createTx_BTC function. And as part of creation process, the creator performs the first signature at `tx_hex = btcOperator.signTx(tx_hex, privateKey)`, and the proceeds to create the pipeline. So the pipleine starts at "TRANSACT" stage itself as seen in `sendRaw(message, pipeline.id, "TRANSACTION", false)` message.
```
MultiSig.createTx_BTC = function (address, redeemScript, receivers, amounts, fee = null, options = {}) {
return new Promise(async (resolve, reject) => {
let addr_type = btcOperator.validateAddress(address);
if (addr_type != "multisig" && addr_type != "multisigBech32")
return reject("Sender address is not a multisig");
let decode = (addr_type == "multisig" ?
coinjs.script().decodeRedeemScript : coinjs.script().decodeRedeemScriptBech32)(redeemScript);
if (!decode || decode.address !== address || decode.type !== "multisig__")
return reject("Invalid redeem-script");
else if (!decode.pubkeys.includes(user.public.toLowerCase()) && !decode.pubkeys.includes(user.public.toUpperCase()))
return reject("User is not a part of this multisig");
else if (decode.pubkeys.length < decode.signaturesRequired)
return reject("Invalid multisig (required is greater than users)");
let co_owners = decode.pubkeys.map(p => floCrypto.getFloID(p));
let privateKey = await floDapps.user.private;
btcOperator.createMultiSigTx(address, redeemScript, receivers, amounts, fee, options).then(({ tx_hex }) => {
tx_hex = btcOperator.signTx(tx_hex, privateKey);
createPipeline(TYPE_BTC_MULTISIG, co_owners, 32, decode.pubkeys).then(pipeline => {
let message = encrypt(tx_hex, pipeline.eKey);
sendRaw(message, pipeline.id, "TRANSACTION", false)
.then(result => resolve(pipeline.id))
.catch(error => reject(error))
}).catch(error => reject(error))
}).catch(error => reject(error))
})
}
```
- Similarly all role based definitions can be created at initial `MultiSig.createTx_BTC` equivalent function at pipeline creation stage. The initial start is needed here. Then the processing logic of model will dictate how will the state move forward.
- Right now all members are flat. But a system can be created where the message goes to a specific role.
### Callback functions used
- callbackFn are used to push data in localIDB and invoke new UI after main fetching of data has been done from Supernodes
- In requestDirectInbox()
```
let callbackFn = function (dataSet, error) {
if (error)
return console.error(error)
let newInbox = {
messages: {},
requests: {},
responses: {},
mails: {},
newgroups: [],
keyrevoke: [],
pipeline: {}
}
for (let vc in dataSet) {
try {
parseData(dataSet[vc], newInbox);
} catch (error) {
//if (error !== "blocked-user")
console.log(error);
} finally {
if (_loaded.appendix.lastReceived < vc)
_loaded.appendix.lastReceived = vc;
}
}
compactIDB.writeData("appendix", _loaded.appendix.lastReceived, "lastReceived");
console.debug(newInbox);
UI.direct(newInbox)
}
```
- In `requestGroupInbox(groupID, _async = true)`
```
let callbackFn = function (dataSet, error) {
if (error)
return console.error(error)
console.info(dataSet)
let newInbox = {
messages: {}
}
let infoChange = false;
for (let vc in dataSet) {
if (groupID !== dataSet[vc].receiverID)
continue;
try {
infoChange = parseData(dataSet[vc], newInbox) || infoChange;
if (!_loaded.appendix[`lastReceived_${groupID}`] ||
_loaded.appendix[`lastReceived_${groupID}`] < vc)
_loaded.appendix[`lastReceived_${groupID}`] = vc;
} catch (error) {
console.log(error)
}
}
compactIDB.writeData("appendix", _loaded.appendix[`lastReceived_${groupID}`], `lastReceived_${groupID}`);
if (infoChange) {
let newInfo = Object.assign({}, _loaded.groups[groupID]);
newInfo.eKey = encrypt(newInfo.eKey)
compactIDB.writeData("groups", newInfo, groupID)
}
console.debug(newInbox);
UI.group(newInbox);
}
```
- In `requestPipelineInbox(pipeID, model, _async = true)`
```
let callbackFn = function (dataSet, error) {
if (error)
return console.error(error);
console.info(dataSet)
let newInbox = {
messages: {}
}
for (let vc in dataSet) {
if (pipeID !== dataSet[vc].receiverID)
continue;
try {
parseData(dataSet[vc], newInbox);
if (!floCrypto.isSameAddr(dataSet[vc].senderID, user.id))
addMark(pipeID, "unread")
if (!_loaded.appendix[`lastReceived_${pipeID}`] ||
_loaded.appendix[`lastReceived_${pipeID}`] < vc)
_loaded.appendix[`lastReceived_${pipeID}`] = vc;
} catch (error) {
console.log(error)
}
}
compactIDB.writeData("appendix", _loaded.appendix[`lastReceived_${pipeID}`], `lastReceived_${pipeID}`);
console.debug(newInbox);
UI.pipeline(model, newInbox);
}
```

38
docs/usage.md Normal file
View File

@ -0,0 +1,38 @@
## How to use Messenger
### General messaging
1. Go to the homepage of Messenger
2. Sign in using a Bitcoin or FLO blockchain private key
3. In case you don't have the private key, generate using
FLO Wallet (for FLO address and private key): https://ranchimall.github.io/flowallet/
BTC Wallet (for Bitcoin address and private key): https://ranchimall.github.io/btcwallet/
** Note: FLO address or FLO ID and private key can be created from Messenger's homepage as well
4. To start a new message or chat, click on the "New chat" button
5. Add a FLO ID or a Bitcoin address as a contact
6. Select the contact to start messaging
** Note: Until the receiver replies, the message is not encrypted.
### Mail
1. Mail is similar to Messaging except the user can send messages to multiple FLO IDs or Bitcoin addresses at the same time
2. Go to "Mail" and enter the recipient's FLO or Bitcoin address
3. Separate multiple addresses with a comma
4. Type a mail and send
### Multisig messaging
1. Go to "Multisig" on the homepage
2. To create a Bitcoin multisig, click on "BTC"
3. To create a FLO multisig, click on "FLO"
4. To add BTC or FLO addresses in the new multisig, select contacts that are to be added
5. Contacts have to be saved in advance before creating a multisig address
6. After selecting the contacts, click "Next" and give the multisig address a label name
7. Select the minimum number of signatures required for the multisig
8. Click "Create" and the multisig address will be created
### Sending a multisig transaction
1. The user must have some balance in the multisig address
2. Go to "Multisig" and click on "init transaction"
3. Enter the receiver's BTC address for a Bitcoin multisig or FLO address for a FLO multisig
4. Enter the amount to be transferred
5. Multiple addresses can be added as receivers with different amounts for each address
6. Click on "Initiate" to initiate the transaction from the multisig address
7. Associated multisig owners will be notified of this transaction
8. Once the required number of signatures is approved, the transaction will take place from the multisig address