diff --git a/README.md b/README.md index 3d3a08f..3c4abe6 100644 --- a/README.md +++ b/README.md @@ -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) diff --git a/docs/additional-resources.md b/docs/additional-resources.md new file mode 100644 index 0000000..838e004 --- /dev/null +++ b/docs/additional-resources.md @@ -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 \ No newline at end of file diff --git a/docs/changelog.md b/docs/changelog.md new file mode 100644 index 0000000..73fda88 --- /dev/null +++ b/docs/changelog.md @@ -0,0 +1,2 @@ +### Important Changes +- Added Bitcoin Transaction fee increase update capability for multisig if the transaction is not getting confirmed. \ No newline at end of file diff --git a/docs/compactIDB.md b/docs/compactIDB.md new file mode 100644 index 0000000..2cb38d7 --- /dev/null +++ b/docs/compactIDB.md @@ -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. +``` + diff --git a/docs/features.md b/docs/features.md new file mode 100644 index 0000000..6706c0a --- /dev/null +++ b/docs/features.md @@ -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 diff --git a/docs/floBlockchainAPI.md b/docs/floBlockchainAPI.md new file mode 100644 index 0000000..2c19577 --- /dev/null +++ b/docs/floBlockchainAPI.md @@ -0,0 +1,1204 @@ +## `fetch_retry(apicall, rm_node)` + +This function makes a fetch API call to the specified endpoint (`apicall`) and retries the request if it fails. It removes a specific server node (`rm_node`) from the list of servers before making the request. It returns a promise that resolves with the response data if the request is successful and rejects with an error if the request fails. + +### Parameters: + +- **`apicall`** (string): The API endpoint to which the fetch request is made. +- **`rm_node`** (string): The server node to be removed from the list before making the request. + +### Return Value: + +A Promise that resolves with the response data if the request is successful, and rejects with an error if the request fails. + +### Example Usage: + +```javascript +const apiEndpoint = "example/api/endpoint"; +const nodeToRemove = "exampleServerNode"; + +fetch_retry(apiEndpoint, nodeToRemove) + .then(responseData => { + console.log("API Response Data:", responseData); + // Handle the response data here + }) + .catch(error => { + console.error("API Request Error:", error); + // Handle API request errors here and implement retry logic if needed + }); +``` + +## `fetch_api(apicall, ic = true)` + +This function makes a fetch API call to the specified endpoint (`apicall`) using the available server nodes. If the request fails, it automatically retries the request using a different server node from the list. It returns a promise that resolves with the response data if the request is successful and rejects with an error if the request fails. + +### Parameters: + +- **`apicall`** (string): The API endpoint to which the fetch request is made. +- **`ic`** (boolean, optional, default: `true`): If `true`, the function initializes the server list from the full server list before making the request. If set to `false`, the server list is not initialized, and the function uses the existing server list. + +### Return Value: + +A Promise that resolves with the response data if the request is successful, and rejects with an error if the request fails. + +### Example Usage: + +```javascript +const apiEndpoint = "example/api/endpoint"; + +fetch_api(apiEndpoint) + .then(responseData => { + console.log("API Response Data:", responseData); + // Handle the response data here + }) + .catch(error => { + console.error("API Request Error:", error); + // Handle API request errors here and implement retry logic if needed + }); +``` + +## `promisedAPI(apicall, query_params = undefined)` + +This function serves as a wrapper around the `fetch_api` function, providing a convenient way to make API calls to the FLO blockchain. It returns a promise that resolves with the response data if the request is successful and rejects with an error if the request fails. + +### Parameters: + +- **`apicall`** (string): The API endpoint to which the fetch request is made. +- **`query_params`** (object, optional, default: `undefined`): An object containing query parameters to be appended to the API endpoint. If provided, these parameters are included in the API request. + +### Return Value: + +A Promise that resolves with the response data if the request is successful, and rejects with an error if the request fails. + +### Example Usage: + +```javascript +const apiEndpoint = "example/api/endpoint"; +const queryParams = { + param1: "value1", + param2: "value2" +}; + +promisedAPI(apiEndpoint, queryParams) + .then(responseData => { + console.log("API Response Data:", responseData); + // Handle the response data here + }) + .catch(error => { + console.error("API Request Error:", error); + // Handle API request errors here and implement retry logic if needed + }); +``` + +## `getBalance(addr)` + +This function retrieves the balance of a specified FLO blockchain address. + +### Parameters: + +- **`addr`** (string): The FLO blockchain address for which the balance needs to be retrieved. + +### Return Value: + +A Promise that resolves with the balance of the specified address if the request is successful, and rejects with an error if the request fails. + +### Example Usage: + +```javascript +const floAddress = "FLO1234567890abcdef"; // Replace with the target FLO blockchain address + +getBalance(floAddress) + .then(balance => { + console.log("Address Balance:", balance); + // Handle the balance data here + }) + .catch(error => { + console.error("Balance Retrieval Error:", error); + // Handle errors in retrieving address balance here + }); +``` + +## `getScriptPubKey(address)` + +This function generates the ScriptPubKey for a specified FLO blockchain address. + +### Parameters: + +- **`address`** (string): The FLO blockchain address for which the ScriptPubKey needs to be generated. + +### Return Value: + +A hexadecimal representation of the ScriptPubKey associated with the specified address. + +### Example Usage: + +```javascript +const floAddress = "FLO1234567890abcdef"; // Replace with the target FLO blockchain address + +const scriptPubKey = getScriptPubKey(floAddress); +console.log("ScriptPubKey:", scriptPubKey); +// Use the generated ScriptPubKey in your application +``` + +## `getUTXOs(address)` + +This function retrieves the Unspent Transaction Outputs (UTXOs) associated with a specified FLO blockchain address. + +### Parameters: + +- **`address`** (string): The FLO blockchain address for which UTXOs need to be retrieved. + +### Return Value: + +A Promise that resolves to an array of UTXO objects. Each UTXO object contains the following properties: +- **`txid`** (string): Transaction ID of the UTXO. +- **`vout`** (number): Output index of the UTXO transaction. +- **`amount`** (number): Amount of FLO tokens in the UTXO. +- **`confirmations`** (number): Number of confirmations for the UTXO transaction. +- **`scriptPubKey`** (string): Hexadecimal representation of the ScriptPubKey associated with the address. + +### Example Usage: + +- In this example, the getUTXOs function is used to retrieve the UTXOs associated with the specified FLO blockchain address. The function returns an array of UTXO objects, each containing relevant details about the unspent transaction output. These UTXOs can be used in transactions or for other purposes within your application. + + +```javascript +const floAddress = "FLO1234567890abcdef"; // Replace with the target FLO blockchain address + +getUTXOs(floAddress) + .then(utxos => { + console.log("UTXOs:", utxos); + // Process the retrieved UTXOs in your application + }) + .catch(error => { + console.error("Error:", error); + // Handle errors if any + }); +``` + +## `createTx(senderAddr, receiverAddr, sendAmt, floData = '', strict_utxo = true)` + +This function constructs a raw transaction for sending FLO tokens from one address to another on the FLO blockchain. + +### Parameters: + +- **`senderAddr`** (string): The sender's FLO blockchain address. +- **`receiverAddr`** (string): The recipient's FLO blockchain address. +- **`sendAmt`** (number): The amount of FLO tokens to be sent in the transaction. +- **`floData`** (string, optional): Additional data to be embedded in the transaction. Must contain printable ASCII characters only. +- **`strict_utxo`** (boolean, optional): If set to `true`, only confirmed UTXOs will be used in the transaction. Defaults to `true`. + +### Return Value: + +A Promise that resolves to the raw transaction object, or rejects with an error message if there are issues with the input parameters or insufficient balance. + +### Example Usage: + +- In this example, the createTx function is used to construct a raw transaction for sending a specified amount of FLO tokens from the sender's address to the recipient's address. Additional data (if provided) is embedded in the transaction. The function performs validations and constructs the transaction using appropriate UTXOs. + +```javascript +const senderAddress = "FLOSenderAddress"; // Replace with the sender's FLO address +const receiverAddress = "FLOReceiverAddress"; // Replace with the recipient's FLO address +const amountToSend = 10; // Amount of FLO tokens to send +const additionalData = "Hello, FLO!"; // Optional additional data to be included in the transaction + +createTx(senderAddress, receiverAddress, amountToSend, additionalData) + .then(rawTransaction => { + console.log("Raw Transaction:", rawTransaction); + // Broadcast the raw transaction to the FLO network using appropriate methods + }) + .catch(error => { + console.error("Error:", error); + // Handle errors if any + }); +``` + + +## `floBlockchainAPI.sendTx(senderAddr, receiverAddr, sendAmt, privKey, floData = '', strict_utxo = true)` + +This function constructs, signs, and broadcasts a FLO blockchain transaction from the sender's address to the recipient's address with a specified amount of FLO tokens. It also allows embedding optional additional data in the transaction. + +### Parameters: + +- **`senderAddr`** (string): The sender's FLO blockchain address. +- **`receiverAddr`** (string): The recipient's FLO blockchain address. +- **`sendAmt`** (number): The amount of FLO tokens to be sent in the transaction. +- **`privKey`** (string): The sender's private key for signing the transaction. +- **`floData`** (string, optional): Additional data to be embedded in the transaction. Must contain printable ASCII characters only. +- **`strict_utxo`** (boolean, optional): If set to `true`, only confirmed UTXOs will be used in the transaction. Defaults to `true`. + +### Return Value: + +A Promise that resolves to the transaction ID (txid) once the transaction is successfully broadcasted, or rejects with an error message if there are issues with the input parameters or the transaction broadcast fails. + +### Example Usage: + +- In this example, the floBlockchainAPI.sendTx function is used to create, sign, and broadcast a FLO transaction from the specified sender address to the recipient address. Additional data (if provided) is embedded in the transaction. The function performs validations, constructs the transaction, signs it with the provided private key, and then broadcasts it to the FLO network. + +```javascript +const senderAddress = "FLOSenderAddress"; // Replace with the sender's FLO address +const receiverAddress = "FLOReceiverAddress"; // Replace with the recipient's FLO address +const amountToSend = 10; // Amount of FLO tokens to send +const privatekey = "SenderPrivateKey"; // Sender's private key for signing the transaction +const additionalData = "Hello, FLO!"; // Optional additional data to be included in the transaction + +floBlockchainAPI.sendTx(senderAddress, receiverAddress, amountToSend, privatekey, additionalData) + .then(txid => { + console.log("Transaction ID:", txid); + // Handle the successful transaction broadcast, if needed + }) + .catch(error => { + console.error("Error:", error); + // Handle errors if any + }); +``` + +## `floBlockchainAPI.writeData(senderAddr, data, privKey, receiverAddr = DEFAULT.receiverID, options = {})` + +This function writes data into the FLO blockchain by creating a transaction with the specified data and embedding it into the blockchain. It allows customization of transaction parameters and additional options. + +### Parameters: + +- **`senderAddr`** (string): The sender's FLO blockchain address. +- **`data`** (string or object): The data to be written into the blockchain. It can be a string or an object, which will be automatically converted to a JSON string. +- **`privKey`** (string): The sender's private key for signing the transaction. +- **`receiverAddr`** (string, optional): The recipient's FLO blockchain address. Defaults to `DEFAULT.receiverID`. +- **`options`** (object, optional): Additional options for the transaction. + - **`strict_utxo`** (boolean, optional): If set to `false`, unconfirmed UTXOs will be considered for the transaction. Defaults to `true`. + - **`sendAmt`** (number, optional): The amount of FLO tokens to be sent in the transaction. Defaults to `DEFAULT.sendAmt`. + +### Return Value: + +A Promise that resolves to the transaction ID (txid) once the transaction is successfully broadcasted, or rejects with an error message if there are issues with the input parameters or the transaction broadcast fails. + +### Example Usage: + +- In this example, the floBlockchainAPI.writeData function is used to create a transaction containing the specified data and writes it into the FLO blockchain. The sender's address, data, and private key are provided as parameters. Additional options such as recipient address, UTXO strictness, and send amount can be customized if needed. + +```javascript +const senderAddress = "FLOSenderAddress"; // Replace with the sender's FLO address +const dataToSend = "Hello, FLO Blockchain!"; // Data to be written into the blockchain +const privatekey = "SenderPrivateKey"; // Sender's private key for signing the transaction + +floBlockchainAPI.writeData(senderAddress, dataToSend, privatekey) + .then(txid => { + console.log("Transaction ID:", txid); + // Handle the successful transaction broadcast, if needed + }) + .catch(error => { + console.error("Error:", error); + // Handle errors if any + }); +``` + +## `floBlockchainAPI.mergeUTXOs(floID, privKey, floData = '')` + +This function merges all UTXOs of a given FLO address into a single UTXO and creates a transaction with the specified data, if provided, embedding it into the blockchain. It consolidates multiple UTXOs into one for efficient transaction management. + +### Parameters: + +- **`floID`** (string): The FLO blockchain address whose UTXOs need to be merged. +- **`privKey`** (string): The private key corresponding to the `floID` address for signing the transaction. +- **`floData`** (string, optional): The data to be embedded into the blockchain. Only printable ASCII characters are allowed. Defaults to an empty string. + +### Return Value: + +A Promise that resolves to the transaction ID (txid) once the merge transaction is successfully broadcasted, or rejects with an error message if there are issues with the input parameters or the transaction broadcast fails. + +### Example Usage: + +- In this example, the floBlockchainAPI.mergeUTXOs function is used to merge all UTXOs of the specified FLO address into a single UTXO. The FLO address, corresponding private key, and optional data to be embedded into the blockchain are provided as parameters. The function consolidates the UTXOs and creates a transaction, embedding the data if provided, and broadcasts it into the FLO blockchain. + +```javascript +const floID = "FLOAddressToMergeUTXOs"; // Replace with the FLO address to merge UTXOs +const privatekey = "PrivateKey"; // Private key corresponding to the FLO address + +floBlockchainAPI.mergeUTXOs(floID, privatekey, "Merged UTXOs data") + .then(txid => { + console.log("Merge Transaction ID:", txid); + // Handle the successful merge transaction, if needed + }) + .catch(error => { + console.error("Error:", error); + // Handle errors if any + }); +``` + +## `floBlockchainAPI.splitUTXOs(floID, privKey, count, floData = '')` + +This function splits sufficient UTXOs of a given FLO address into multiple UTXOs for parallel sending. It creates transactions to split the UTXOs and embeds the specified data into the blockchain if provided. + +### Parameters: + +- **`floID`** (string): The FLO blockchain address whose UTXOs need to be split. +- **`privKey`** (string): The private key corresponding to the `floID` address for signing the split transactions. +- **`count`** (number): The number of UTXOs to split into. +- **`floData`** (string, optional): The data to be embedded into the blockchain. Only printable ASCII characters are allowed. Defaults to an empty string. + +### Return Value: + +A Promise that resolves to the transaction ID (txid) once the split transactions are successfully broadcasted, or rejects with an error message if there are issues with the input parameters or the transaction broadcast fails. + +### Example Usage: + +- In this example, the floBlockchainAPI.splitUTXOs function is used to split the UTXOs of the specified FLO address into the specified number of UTXOs. The FLO address, corresponding private key, the number of UTXOs to split into, and optional data to be embedded into the blockchain are provided as parameters. The function splits the UTXOs, creates transactions, embeds the data if provided, and broadcasts them into the FLO blockchain. + +```javascript +const floID = "FLOAddressToSplitUTXOs"; // Replace with the FLO address to split UTXOs +const privatekey = "PrivateKey"; // Private key corresponding to the FLO address +const splitCount = 5; // Number of UTXOs to split into + +floBlockchainAPI.splitUTXOs(floID, privatekey, splitCount, "Split UTXOs data") + .then(txid => { + console.log("Split Transaction ID:", txid); + // Handle the successful split transactions, if needed + }) + .catch(error => { + console.error("Error:", error); + // Handle errors if any + }); +``` + +## `floBlockchainAPI.writeDataMultiple(senderPrivKeys, data, receivers = [DEFAULT.receiverID], options = {})` + +This function allows multiple senders to split and send FLO data to multiple receivers. It takes an array of sender private keys, a single piece of data (string or JSON object), an array of receiver addresses, and additional options if needed. + +### Parameters: + +- **`senderPrivKeys`** (array of strings): An array of private keys corresponding to the sender addresses. +- **`data`** (string or object): The data to be sent and embedded into the blockchain. It can be a string or a JSON object. +- **`receivers`** (array of strings, optional): An array of FLO addresses representing the receivers. Defaults to `[DEFAULT.receiverID]`. +- **`options`** (object, optional): Additional options for the transaction. It can include: + - **`sendAmt`** (number): The amount of FLO to be sent from each sender to each receiver. Defaults to `DEFAULT.sendAmt`. + - **`preserveRatio`** (boolean): If `true`, the specified `sendAmt` will be divided equally among receivers. If `false`, each sender will send the specified `sendAmt` to each receiver. Defaults to `true`. + +### Return Value: + +A Promise that resolves to the transaction ID (txid) once the transactions are successfully broadcasted, or rejects with an error message if there are issues with the input parameters or the transaction broadcast fails. + +### Example Usage: + +- In this example, the floBlockchainAPI.writeDataMultiple function is used to send the specified data from multiple senders to multiple receivers. It allows customization of the send amount and division of the amount among receivers based on the preserveRatio option. The function broadcasts the transactions into the FLO blockchain. + +```javascript +const senderPrivKeys = ["PrivateKey1", "PrivateKey2", "PrivateKey3"]; // Array of sender private keys +const receivers = ["ReceiverAddress1", "ReceiverAddress2"]; // Array of receiver addresses +const data = { message: "Hello, World!" }; // Data to be sent (can be a string or object) +const options = { + sendAmt: 0.1, // Amount of FLO to be sent from each sender to each receiver + preserveRatio: false // Divide the specified sendAmt equally among receivers +}; + +floBlockchainAPI.writeDataMultiple(senderPrivKeys, data, receivers, options) + .then(txid => { + console.log("Transaction ID:", txid); + // Handle the successful broadcast of transactions, if needed + }) + .catch(error => { + console.error("Error:", error); + // Handle errors if any + }); +``` + +## `floBlockchainAPI.sendTxMultiple(senderPrivKeys, receivers, floData = '')` + +This function allows multiple senders to send FLO tokens to multiple receivers. It takes an array of sender private keys (or an object with private keys and corresponding send amounts), an object containing receiver addresses and corresponding receive amounts, and an optional FLO data string to embed in the transactions. + +### Parameters: + +- **`senderPrivKeys`** (array or object): An array of sender private keys or an object where keys are sender addresses and values are send amounts. +- **`receivers`** (object): An object where keys are receiver addresses and values are receive amounts. +- **`floData`** (string, optional): The FLO data to be embedded in the transactions. Only printable ASCII characters are allowed. + +### Return Value: + +A Promise that resolves to the transaction ID (txid) once the transactions are successfully broadcasted, or rejects with an error message if there are issues with the input parameters or the transaction broadcast fails. + +### Example Usage: + +#### Example 1: Using an Array of Sender Private Keys + +```javascript +const senderPrivKeys = ["PrivateKey1", "PrivateKey2", "PrivateKey3"]; // Array of sender private keys +const receivers = { + "ReceiverAddress1": 0.1, + "ReceiverAddress2": 0.2 +}; // Object with receiver addresses and corresponding receive amounts +const floData = "Hello, FLO!"; // Optional FLO data + +floBlockchainAPI.sendTxMultiple(senderPrivKeys, receivers, floData) + .then(txid => { + console.log("Transaction ID:", txid); + // Handle the successful broadcast of transactions, if needed + }) + .catch(error => { + console.error("Error:", error); + // Handle errors if any + }); +``` + +#### Example 2: Using an Object of Sender Private Keys and Send Amounts + +```javascript +const senderPrivKeys = { + "PrivateKey1": 0.1, + "PrivateKey2": 0.2, + "PrivateKey3": 0.3 +}; // Object with sender addresses as keys and corresponding send amounts as values +const receivers = { + "ReceiverAddress1": 0.1, + "ReceiverAddress2": 0.2 +}; // Object with receiver addresses and corresponding receive amounts +const floData = "Hello, FLO!"; // Optional FLO data + +floBlockchainAPI.sendTxMultiple(senderPrivKeys, receivers, floData) + .then(txid => { + console.log("Transaction ID:", txid); + // Handle the successful broadcast of transactions, if needed + }) + .catch(error => { + console.error("Error:", error); + // Handle errors if any + }); +``` + +## `createMultisigTx(redeemScript, receivers, amounts, floData = '', strict_utxo = true)` + +This function creates a multisig transaction, allowing multiple receivers to receive specified amounts of FLO tokens. It takes a redeem script, an array of receiver addresses, an array of corresponding receive amounts, optional FLO data, and a strict UTXO flag as input. + +### Parameters: + +- **`redeemScript`** (string): The redeem script associated with the multisig address. +- **`receivers`** (array): An array of receiver addresses where FLO tokens will be sent. +- **`amounts`** (array): An array of corresponding receive amounts for each receiver address. +- **`floData`** (string, optional): The FLO data to be embedded in the transactions. Only printable ASCII characters are allowed. +- **`strict_utxo`** (boolean, optional): A flag indicating whether to use only confirmed UTXOs for the transaction (default is `true`). + +### Return Value: + +A Promise that resolves to the constructed transaction object once the transaction data is successfully created, or rejects with an error message if there are issues with the input parameters or the UTXO validation fails. + +### Example Usage: + +- In this example, the createMultisigTx function is used to construct a multisig transaction with specified receiver addresses, corresponding amounts, optional FLO data, and a redeem script. The resulting transaction object can be further processed or signed before broadcasting. + +```javascript +const redeemScript = "redeemScriptHere"; // Replace with the actual redeem script +const receivers = ["ReceiverAddress1", "ReceiverAddress2"]; +const amounts = [0.1, 0.2]; // Amounts corresponding to the receivers +const floData = "Hello, FLO!"; // Optional FLO data + +createMultisigTx(redeemScript, receivers, amounts, floData) + .then(transaction => { + console.log("Constructed Transaction Object:", transaction); + // Handle the constructed transaction object, if needed + }) + .catch(error => { + console.error("Error:", error); + // Handle errors if any + }); +``` + +## `sendMultisigTx(redeemScript, privateKeys, receivers, amounts, floData = '', strict_utxo = true)` + +This function is part of the `floBlockchainAPI` and facilitates the creation and sending of multisig transactions on the FLO blockchain. It takes a redeem script, an array of private keys corresponding to the multisig address, an array of receiver addresses, an array of corresponding receive amounts, optional FLO data, and a strict UTXO flag as input. + +### Parameters: + +- **`redeemScript`** (string): The redeem script associated with the multisig address. +- **`privateKeys`** (array): An array of private keys corresponding to the multisig address. The number of private keys must meet the requirements specified in the redeem script. +- **`receivers`** (array): An array of receiver addresses where FLO tokens will be sent. +- **`amounts`** (array): An array of corresponding receive amounts for each receiver address. +- **`floData`** (string, optional): The FLO data to be embedded in the transactions. Only printable ASCII characters are allowed. +- **`strict_utxo`** (boolean, optional): A flag indicating whether to use only confirmed UTXOs for the transaction (default is `true`). + +### Return Value: + +A Promise that resolves to the transaction ID (txid) once the multisig transaction is successfully broadcasted, or rejects with an error message if there are issues with the input parameters, private keys, or the UTXO validation fails. + +### Example Usage: + +- In this example, the sendMultisigTx function is used to create and send a multisig transaction with specified private keys, receiver addresses, corresponding amounts, optional FLO data, and a redeem script. The resulting transaction ID (txid) can be used for further reference or verification. + +```javascript +const redeemScript = "redeemScriptHere"; // Replace with the actual redeem script +const privateKeys = ["PrivateKey1", "PrivateKey2", "PrivateKey3"]; // Private keys corresponding to the multisig address +const receivers = ["ReceiverAddress1", "ReceiverAddress2"]; +const amounts = [0.1, 0.2]; // Amounts corresponding to the receivers +const floData = "Hello, FLO!"; // Optional FLO data + +floBlockchainAPI.sendMultisigTx(redeemScript, privateKeys, receivers, amounts, floData) + .then(txid => { + console.log("Multisig Transaction Sent! TXID:", txid); + // Handle the transaction ID (txid), if needed + }) + .catch(error => { + console.error("Error:", error); + // Handle errors if any + }); +``` + +## `writeMultisigData(redeemScript, data, privatekeys, receiverAddr = DEFAULT.receiverID, options = {})` + +This function is part of the `floBlockchainAPI` and allows you to write data to the FLO blockchain using a multisig transaction. It takes a redeem script, data to be written, an array of private keys corresponding to the multisig address, an optional receiver address (defaulting to `DEFAULT.receiverID`), and additional options such as strict UTXO and send amount. + +### Parameters: + +- **`redeemScript`** (string): The redeem script associated with the multisig address. +- **`data`** (string): The data to be written to the blockchain. +- **`privatekeys`** (array): An array of private keys corresponding to the multisig address. +- **`receiverAddr`** (string, optional): The receiver address where FLO tokens will be sent. Defaults to `DEFAULT.receiverID`. +- **`options`** (object, optional): Additional options for the transaction, such as `strict_utxo` (boolean) and `sendAmt` (number). + +### Return Value: + +A Promise that resolves to the transaction ID (txid) once the multisig transaction with the specified data is successfully broadcasted, or rejects with an error message if there are issues with the input parameters or the transaction cannot be created or broadcasted. + +### Example Usage: + +- In this example, the sendMultisigTx function is used to create and send a multisig transaction with specified private keys, receiver addresses, corresponding amounts, optional FLO data, and a redeem script. The resulting transaction ID (txid) can be used for further reference or verification. + +```javascript +const redeemScript = "redeemScriptHere"; // Replace with the actual redeem script +const data = "Your data to be written to the blockchain"; +const privatekeys = ["PrivateKey1", "PrivateKey2", "PrivateKey3"]; // Private keys corresponding to the multisig address +const receiverAddr = "ReceiverAddress"; // Optional receiver address (default is DEFAULT.receiverID) +const options = { + strict_utxo: true, // Optional: Use only confirmed UTXOs (default is true) + sendAmt: 0.1 // Optional: Amount of FLO tokens to be sent (default is DEFAULT.sendAmt) +}; + +floBlockchainAPI.writeMultisigData(redeemScript, data, privatekeys, receiverAddr, options) + .then(txid => { + console.log("Multisig Data Written to Blockchain! TXID:", txid); + // Handle the transaction ID (txid), if needed + }) + .catch(error => { + console.error("Error:", error); + // Handle errors if any + }); +``` + +## `deserializeTx(tx)` + +This function allows you to deserialize a transaction from its hexadecimal representation or from a transaction object. It validates the input and returns a transaction object that can be further processed. + +### Parameters: + +- **`tx`** (string | array | object): The input transaction data. It can be either a hexadecimal string representing the transaction, an array containing the transaction data, or a transaction object. + +### Return Value: + +Returns a deserialized transaction object. + +### Throws: + +- Throws an error with the message "Invalid transaction hex" if the input transaction data is a string (hexadecimal representation) and cannot be deserialized. +- Throws an error with the message "Invalid transaction object" if the input transaction data is not a valid hexadecimal string, array, or transaction object. + +### Example Usage: + +```javascript +const serializedTxHex = "0100000001..."; // Replace with the actual transaction hex +const serializedTxArray = [0, 1, 2, ...]; // Replace with the actual transaction array +const transactionObject = { /* Replace with the actual transaction object */ }; + +try { + const deserializedTxFromHex = deserializeTx(serializedTxHex); + console.log("Deserialized Transaction from Hex:", deserializedTxFromHex); + + const deserializedTxFromArray = deserializeTx(serializedTxArray); + console.log("Deserialized Transaction from Array:", deserializedTxFromArray); + + const deserializedTxFromObject = deserializeTx(transactionObject); + console.log("Deserialized Transaction from Object:", deserializedTxFromObject); +} catch (error) { + console.error("Error:", error); + // Handle errors if any +} +``` + +## `floBlockchainAPI.signTx(tx, privateKey, sighashtype = 1)` + +This function allows you to sign a transaction with the provided private key and signature hash type. It takes a transaction object (or its hexadecimal representation), a private key, and an optional signature hash type. It returns the signed transaction in its hexadecimal form. + +### Parameters: + +- **`tx`** (string | array | object): The transaction to be signed. It can be either a hexadecimal string representing the transaction, an array containing the transaction data, or a transaction object. +- **`privateKey`** (string): The private key used for signing the transaction. +- **`sighashtype`** (number, optional, default: 1): The signature hash type. It specifies the way the transaction data is hashed. The default value is 1, indicating SIGHASH_ALL. + +### Return Value: + +Returns the signed transaction in its hexadecimal form. + +### Throws: + +- Throws an error with the message "Invalid Private key" if the provided private key is not valid. + +### Example Usage: + +- In this example, the signTx function is used to sign an unsigned transaction represented as a hexadecimal string. You can modify the unsignedTxHex and privateKey variables with actual transaction data and private key to test the function. + +```javascript +const unsignedTxHex = "0100000001..."; // Replace with the actual unsigned transaction hex +const privateKey = "privateKey"; // Replace with the actual private key + +try { + const signedTxHex = floBlockchainAPI.signTx(unsignedTxHex, privateKey); + console.log("Signed Transaction Hex:", signedTxHex); +} catch (error) { + console.error("Error:", error); + // Handle errors if any +} +``` + +## `floBlockchainAPI.checkSigned(tx, bool = true)` + +This function allows you to check if a transaction is signed correctly. It takes a transaction object (or its hexadecimal representation) and an optional boolean parameter. If the boolean parameter is set to `true` (default), it returns a boolean indicating whether the transaction is fully signed. If set to `false`, it returns an array containing information about the signing status for each input. + +### Parameters: + +- **`tx`** (string | array | object): The transaction to be checked. It can be either a hexadecimal string representing the transaction, an array containing the transaction data, or a transaction object. +- **`bool`** (boolean, optional, default: `true`): A boolean parameter indicating whether to return a boolean result (`true` for fully signed, `false` otherwise) or an array containing signing status information for each input. + +### Return Value: + +- If `bool` is `true` (default), returns `true` if the transaction is fully signed, and `false` otherwise. +- If `bool` is `false`, returns an array containing signing status information for each input. For inputs that require multisig, it includes an object with the properties `{ s: , r: , t: }`. For regular inputs, it includes `true` if signed and `false` otherwise. + +### Throws: + +- Throws an error with the message "signaturesRequired is more than publicKeys" if the number of required signatures is greater than the total number of public keys in a multisig input. + +### Example Usage: + +- In this example, the checkSigned function is used to check if a signed transaction represented as a hexadecimal string is fully signed. The isFullySigned variable contains a boolean indicating whether the transaction is fully signed, and the signingStatus variable contains an array with signing status information for each input. You can modify the signedTxHex variable with an actual signed transaction hex to test the function. + +```javascript +const signedTxHex = "0100000001..."; // Replace with the actual signed transaction hex + +try { + const isFullySigned = floBlockchainAPI.checkSigned(signedTxHex); + console.log("Is Fully Signed:", isFullySigned); + + const signingStatus = floBlockchainAPI.checkSigned(signedTxHex, false); + console.log("Signing Status for Each Input:", signingStatus); +} catch (error) { + console.error("Error:", error); + // Handle errors if any +} +``` + +## `floBlockchainAPI.checkIfSameTx(tx1, tx2)` + +This function allows you to compare two transactions to check if they are the same. It takes two transaction objects (or their hexadecimal representations) and returns a boolean indicating whether the transactions are identical in terms of inputs, outputs, and floData. + +### Parameters: + +- **`tx1`** (string | array | object): The first transaction to be compared. It can be either a hexadecimal string representing the transaction, an array containing the transaction data, or a transaction object. +- **`tx2`** (string | array | object): The second transaction to be compared. It can be either a hexadecimal string representing the transaction, an array containing the transaction data, or a transaction object. + +### Return Value: + +- Returns `true` if the two transactions are identical in terms of inputs, outputs, and floData. Returns `false` otherwise. + +### Example Usage: + +- In this example, the checkIfSameTx function is used to compare two transactions represented as hexadecimal strings. The areSameTransactions variable contains a boolean indicating whether the two transactions are identical in terms of inputs, outputs, and floData. + + + +```javascript +const tx1Hex = "0100000001..."; // Replace with the actual hexadecimal representation of the first transaction +const tx2Hex = "0100000001..."; // Replace with the actual hexadecimal representation of the second transaction + +const areSameTransactions = floBlockchainAPI.checkIfSameTx(tx1Hex, tx2Hex); +console.log("Are the Transactions the Same?", areSameTransactions); +``` + +## `floBlockchainAPI.transactionID(tx)` + +This function calculates the transaction ID (TxID) for a given transaction. It takes a transaction object (or its hexadecimal representation) and returns the corresponding transaction ID. + +### Parameters: + +- **`tx`** (string | array | object): The transaction for which the TxID needs to be calculated. It can be either a hexadecimal string representing the transaction, an array containing the transaction data, or a transaction object. + +### Return Value: + +- Returns the transaction ID (TxID) as a hexadecimal string. + +### Example Usage: + +- In this example, the transactionID function is used to calculate the transaction ID (TxID) for a given transaction represented as a hexadecimal string. The txid variable contains the resulting transaction ID as a hexadecimal string. + +```javascript +const txHex = "0100000001..."; // Replace with the actual hexadecimal representation of the transaction + +const txid = floBlockchainAPI.transactionID(txHex); +console.log("Transaction ID:", txid); +``` + + +## `getTxOutput(txid, index)` + +This function retrieves a specific transaction output (vout) from a given transaction by its transaction ID (TxID) and index. + +### Parameters: + +- **`txid`** (string): The transaction ID (TxID) of the transaction from which to retrieve the output. +- **`index`** (number): The index of the output in the transaction's vout array. + +### Return Value: + +- Returns a Promise that resolves with the specific transaction output (vout) object. + +### Example Usage: + +- In this example, the getTxOutput function is used to retrieve the transaction output at index 0 from the transaction with the specified txid. The function returns a Promise, and the resolved output object contains details about the specific transaction output. + +```javascript +const txid = "1234567890abcdef"; // Replace with the actual transaction ID +const outputIndex = 0; // Replace with the desired output index + +getTxOutput(txid, outputIndex) + .then(output => { + console.log("Transaction Output:", output); + }) + .catch(error => { + console.error("Error:", error); + }); +``` + +# `getOutputAddress(outscript)` + +The `getOutputAddress` function generates a FLO (or Bitcoin) address from a given output script. + +## Parameters: + +- **`outscript`** (Array): An array representing the output script. + +## Return Value: + +- Returns a FLO (or Bitcoin) address as a string. + +## Example Usage: + +- In this function, the input outscript is expected to be an array representing the output script of a transaction output. Depending on the script type (legacy or multisig), it processes the script bytes and version to create the address. The function then returns the generated FLO (or Bitcoin) address as a string. + +```javascript +const outscript = [118, 169, 20, ...]; // Replace with the actual output script + +const address = getOutputAddress(outscript); +console.log("Generated Address:", address); +``` + +# `floBlockchainAPI.parseTransaction(tx)` + +The `parseTransaction` function parses a FLO transaction, extracting inputs, outputs, total amounts, fees, and FLO data. + +## Parameters: + +- **`tx`** (String or Array): The serialized transaction in hexadecimal format or as an array of transaction bytes. + +## Return Value: + +- Returns a Promise that resolves to an object containing parsed transaction details: + - **`inputs`** (Array): An array of objects representing transaction inputs with properties `address` (input address) and `value` (input value). + - **`outputs`** (Array): An array of objects representing transaction outputs with properties `address` (output address) and `value` (output value). + - **`total_input`** (Number): Total value of inputs in FLO. + - **`total_output`** (Number): Total value of outputs in FLO. + - **`fee`** (Number): Transaction fee in FLO. + - **`floData`** (String): FLO data included in the transaction. + +## Example Usage: + +- In this function, you provide the tx parameter, which can be either a hexadecimal string or an array of transaction bytes. The function then resolves with an object containing detailed information about the parsed transaction, including inputs, outputs, total amounts, fees, and FLO data. + +```javascript +const txHex = '0123456789abcdef...'; // Replace with the actual transaction hex string + +floBlockchainAPI.parseTransaction(txHex) + .then(parsedTx => { + console.log("Parsed Transaction Details:"); + console.log("Inputs:", parsedTx.inputs); + console.log("Outputs:", parsedTx.outputs); + console.log("Total Input:", parsedTx.total_input, "FLO"); + console.log("Total Output:", parsedTx.total_output, "FLO"); + console.log("Transaction Fee:", parsedTx.fee, "FLO"); + console.log("FLO Data:", parsedTx.floData); + }) + .catch(error => { + console.error("Error:", error); + }); +``` + +# `floBlockchainAPI.broadcastTx(signedTxHash)` + +The `broadcastTx` function broadcasts a signed FLO transaction to the blockchain using the API. + +## Parameters: + +- **`signedTxHash`** (String): The signed FLO transaction hash in hexadecimal format. + +## Return Value: + +- Returns a Promise that resolves to the broadcasted transaction ID if successful. + +## Example Usage: + +- In this function, you provide the signedTxHash parameter, which is the hexadecimal representation of the signed FLO transaction. The function then broadcasts the transaction to the FLO blockchain using the API endpoint. If successful, it resolves with the transaction ID. + +```javascript +const signedTxHash = '0123456789abcdef...'; // Replace with the actual signed transaction hash + +floBlockchainAPI.broadcastTx(signedTxHash) + .then(txid => { + console.log("Transaction successfully broadcasted! Transaction ID:", txid); + }) + .catch(error => { + console.error("Error:", error); + }); +``` + +# `floBlockchainAPI.getTx(txid)` + +The `getTx` function retrieves information about a specific FLO transaction using its transaction ID (txid). + +## Parameters: + +- **`txid`** (String): The transaction ID (txid) of the FLO transaction to retrieve information about. + +## Return Value: + +- Returns a Promise that resolves to the transaction information if the transaction with the provided txid exists. + +## Example Usage: + +```javascript +const txid = '0123456789abcdef...'; // Replace with the actual transaction ID + +floBlockchainAPI.getTx(txid) + .then(transactionInfo => { + console.log("Transaction Information:", transactionInfo); + }) + .catch(error => { + console.error("Error:", error); + }); +``` + +# `floBlockchainAPI.waitForConfirmation(txid, max_retry = -1, retry_timeout = 20)` + +The `waitForConfirmation` function waits for a FLO transaction to be confirmed on the blockchain. It checks the confirmation status of the transaction at regular intervals until it gets confirmed or until the maximum retry limit is reached. + +## Parameters: + +- **`txid`** (String): The transaction ID (txid) of the FLO transaction to wait for confirmation. +- **`max_retry`** (Optional, Number): The maximum number of times to retry checking for confirmation. Set to `-1` for infinite retries (default: `-1`). +- **`retry_timeout`** (Optional, Number): The time interval (in seconds) between each confirmation check attempt (default: `20` seconds). + +## Return Value: + +- Returns a Promise that resolves to the confirmed transaction object when the transaction is confirmed. +- Rejects the Promise with an error message if the transaction is not found or if the maximum retry limit is reached. + +## Example Usage: + +- This function is useful for scenarios where developers need to wait for a transaction to be confirmed before proceeding with subsequent actions. It provides a way to handle waiting for transactions asynchronously, allowing for more efficient and responsive application behavior. + +```javascript +const txid = '0123456789abcdef...'; // Replace with the actual transaction ID + +floBlockchainAPI.waitForConfirmation(txid, 10, 30) + .then(confirmedTx => { + console.log("Transaction Confirmed:", confirmedTx); + }) + .catch(error => { + console.error("Error:", error); + }); +``` + +# `floBlockchainAPI.readTxs(addr, options = {})` + +The `readTxs` function retrieves a list of FLO transactions associated with a specific address. + +## Parameters: + +- **`addr`** (String): The FLO address for which transactions are to be retrieved. +- **`options`** (Object, Optional): Additional options for customizing the transaction retrieval. + - **`page`** (Number, Optional): The page number for paginated results (default: `1`). + - **`pageSize`** (Number, Optional): The number of transactions per page (default: `10`). + - **`confirmed`** (Boolean, Optional): If set to `true`, retrieves only confirmed transactions (default: `false`). + +## Return Value: + +- Returns a Promise that resolves to an object containing transaction details associated with the given address. + - **`txs`** (Array): An array of transaction objects containing details such as transaction ID, inputs, outputs, etc. + - **`totalItems`** (Number): Total number of transactions associated with the address. + - **`totalPages`** (Number): Total number of pages based on the given `pageSize`. + +## Example Usage: + +```javascript +const address = 'FLO_ADDRESS'; // Replace with the actual FLO address + +floBlockchainAPI.readTxs(address, { page: 1, pageSize: 10, confirmed: true }) + .then(transactionDetails => { + console.log("Transactions for Address:", transactionDetails.txs); + console.log("Total Transactions:", transactionDetails.totalItems); + console.log("Total Pages:", transactionDetails.totalPages); + }) + .catch(error => { + console.error("Error:", error); + }); +``` + +# `readAllTxs_oldSupport(addr, options, ignoreOld = 0, cacheTotal = 0)` + +The `readAllTxs_oldSupport` function retrieves all FLO transactions associated with a specific address with backward compatibility for `floBlockchainAPI` versions prior to `v2.5.6`. + +## Parameters: + +- **`addr`** (String): The FLO address for which transactions are to be retrieved. +- **`options`** (Object): Additional options for customizing the transaction retrieval. + - **`page`** (Number, Optional): The page number for paginated results (default: `1`). + - **`pageSize`** (Number, Optional): The number of transactions per page (default: `10`). + - **`confirmed`** (Boolean, Optional): If set to `true`, retrieves only confirmed transactions (default: `false`). +- **`ignoreOld`** (Number, Optional): Number of old transactions to ignore from the beginning of the result set (default: `0`). +- **`cacheTotal`** (Number, Optional): Total number of transactions already cached from previous calls (default: `0`). + +## Return Value: + +- Returns a Promise that resolves to an array of transaction objects containing details such as transaction ID, inputs, outputs, etc. + +## Example Usage: + +-This function provides backward compatibility for versions of floBlockchainAPI prior to v2.5.6. It retrieves all FLO transactions associated with a specific address while allowing developers to ignore a specified number of old transactions from the beginning of the result set. + +```javascript +const address = 'FLO_ADDRESS'; // Replace with the actual FLO address + +const options = { + page: 1, + pageSize: 10, + confirmed: true +}; + +const ignoreOld = 5; // Ignore 5 old transactions from the beginning of the result set + +readAllTxs_oldSupport(address, options, ignoreOld) + .then(transactions => { + console.log("All Transactions (Ignoring 5 Old Transactions):", transactions); + }) + .catch(error => { + console.error("Error:", error); + }); +``` + +# `readAllTxs_new(addr, options, lastItem)` + +The `readAllTxs_new` function retrieves FLO transactions associated with a specific address starting from the most recent transactions up to a specified `lastItem`. + +## Parameters: + +- **`addr`** (String): The FLO address for which transactions are to be retrieved. +- **`options`** (Object): Additional options for customizing the transaction retrieval. + - **`page`** (Number, Optional): The page number for paginated results (default: `1`). + - **`pageSize`** (Number, Optional): The number of transactions per page (default: `10`). + - **`confirmed`** (Boolean, Optional): If set to `true`, retrieves only confirmed transactions (default: `false`). +- **`lastItem`** (String, Optional): The transaction ID of the last known transaction. The retrieval will start from this transaction onward. + +## Return Value: + +- Returns a Promise that resolves to an array of transaction objects containing details such as transaction ID, inputs, outputs, etc. + +## Example Usage: + +- This function retrieves FLO transactions associated with a specific address starting from the most recent transactions up to a specified lastItem. Developers can provide the ID of the last known transaction, and the function will fetch transactions from that point onward. + +```javascript +const address = 'FLO_ADDRESS'; // Replace with the actual FLO address + +const options = { + page: 1, + pageSize: 10, + confirmed: true +}; + +const lastItemTxID = 'LAST_TXID'; // Replace with the actual transaction ID of the last known transaction + +readAllTxs_new(address, options, lastItemTxID) + .then(transactions => { + console.log("Transactions Starting from Last Known Item:", transactions); + }) + .catch(error => { + console.error("Error:", error); + }); +``` + +# `floBlockchainAPI.readAllTxs(addr, options)` + +The `readAllTxs` function retrieves all FLO transactions associated with a specific address, with the newest transactions appearing first. + +## Parameters: + +- **`addr`** (String): The FLO address for which transactions are to be retrieved. +- **`options`** (Object, Optional): Additional options for customizing the transaction retrieval. + - **`ignoreOld`** (Number, Optional): Number of old transactions to ignore from the beginning of the transaction history (backward compatibility with floBlockchainAPI versions prior to v2.5.6). + - **`after`** (String, Optional): The transaction ID of the last known transaction. The retrieval will start from this transaction onward. + - **`page`** (Number, Optional): The page number for paginated results (default: `1`). + - **`pageSize`** (Number, Optional): The number of transactions per page (default: `10`). + - **`confirmed`** (Boolean, Optional): If set to `true`, retrieves only confirmed transactions (default: `false`). + +## Return Value: + +- Returns a Promise that resolves to an object containing: + - **`lastItem`** (String): The transaction ID of the last known transaction. + - **`items`** (Array): An array of transaction objects containing details such as transaction ID, inputs, outputs, etc. + +## Example Usage: + +-This function retrieves all FLO transactions associated with a specific address, allowing developers to specify various options such as ignoring old transactions, starting from a specific transaction ID, and pagination. + +```javascript +const address = 'FLO_ADDRESS'; // Replace with the actual FLO address + +const options = { + page: 1, + pageSize: 10, + confirmed: true +}; + +// For backward compatibility (floBlockchainAPI < v2.5.6) +// const options = { +// ignoreOld: 5 +// }; + +// For starting from a specific transaction ID +// const options = { +// after: 'LAST_TXID' +// }; + +floBlockchainAPI.readAllTxs(address, options) + .then(result => { + console.log("Last Known Transaction ID:", result.lastItem); + console.log("Transactions:", result.items); + }) + .catch(error => { + console.error("Error:", error); + }); +``` + + +# `floBlockchainAPI.readData(addr, options)` + +The `readData` function retrieves FLO transactions associated with a specific address, with optional filtering options. + +## Parameters: + +- **`addr`** (String): The FLO address for which transactions are to be retrieved. +- **`options`** (Object, Optional): Additional options for customizing the transaction retrieval. + - **`confirmed`** (Boolean, Optional): If set to `true`, retrieves only confirmed transactions (default: `true`). + - **`after`** (String, Optional): The transaction ID of the last known transaction. The retrieval will start from this transaction onward. + - **`ignoreOld`** (Number, Optional): Number of old transactions to ignore from the beginning of the transaction history. + - **`sentOnly`** (Boolean, Optional): If set to `true`, retrieves only transactions sent from the specified address. + - **`receivedOnly`** (Boolean, Optional): If set to `true`, retrieves only transactions received by the specified address. + - **`senders`** (Array or String, Optional): Array of sender addresses to filter transactions. + - **`receivers`** (Array or String, Optional): Array of receiver addresses to filter transactions. + - **`pattern`** (String, Optional): JSON key pattern to filter transactions containing specific keys. + - **`filter`** (Function, Optional): Custom function to further filter transactions based on the FLO data. + - **`tx`** (Boolean, Optional): If set to `true`, returns detailed transaction objects (default: `false`). + +## Return Value: + +- Returns a Promise that resolves to an object containing: + - **`lastItem`** (String): The transaction ID of the last known transaction. + - **`items`** (Array, Optional): An array of transaction objects or FLO data strings based on the `tx` option. + +## Example Usage: + +```javascript +const address = 'FLO_ADDRESS'; // Replace with the actual FLO address + +const options = { + confirmed: true, + after: 'LAST_TXID', + sentOnly: true, + senders: ['SENDER_ADDRESS'], + receivers: ['RECEIVER_ADDRESS'], + pattern: 'KEY_PATTERN', + filter: (floData) => { + // Custom filter logic, return true to include the transaction + return floData.includes('FILTER_TEXT'); + }, + tx: true +}; + +floBlockchainAPI.readData(address, options) + .then(result => { + console.log("Last Known Transaction ID:", result.lastItem); + console.log("Transactions:", result.items); + }) + .catch(error => { + console.error("Error:", error); + }); +``` + +# `floBlockchainAPI.getLatestData(addr, caseFn, options)` + +The `getLatestData` function retrieves the latest confirmed FLO transaction data associated with a specific address based on a provided validation function (`caseFn`). + +## Parameters: + +- **`addr`** (String): The FLO address for which transactions are to be retrieved. +- **`caseFn`** (Function): A validation function that takes FLO data as input and returns a boolean value (`true` for valid, `false` for invalid). +- **`options`** (Object, Optional): Additional options for customizing the transaction retrieval. + - **`confirmed`** (Boolean, Optional): If set to `true`, retrieves only confirmed transactions (default: `true`). + - **`page`** (Number, Optional): The page number of transactions to retrieve (default: `1`). + - **`after`** (String, Optional): The transaction ID of the last known transaction. The retrieval will start from this transaction onward. + - **`sentOnly`** (Boolean, Optional): If set to `true`, retrieves only transactions sent from the specified address. + - **`receivedOnly`** (Boolean, Optional): If set to `true`, retrieves only transactions received by the specified address. + - **`senders`** (Array or String, Optional): Array of sender addresses to filter transactions. + - **`receivers`** (Array or String, Optional): Array of receiver addresses to filter transactions. + - **`tx`** (Boolean, Optional): If set to `true`, returns detailed transaction object (default: `false`). + +## Return Value: + +- Returns a Promise that resolves to an object containing: + - **`lastItem`** (String): The transaction ID of the last known transaction that matches the validation function. + - **`item`** (Object, Optional): Detailed transaction object if `tx` option is set to `true`. + - **`data`** (String, Optional): FLO data that matches the validation function. + +## Example Usage: + +```javascript +const address = 'FLO_ADDRESS'; // Replace with the actual FLO address + +const validationFunction = (floData) => { + // Custom validation logic, return true for valid data, false otherwise + return floData.includes('VALIDATION_TEXT'); +}; + +const options = { + confirmed: true, + page: 1, + after: 'LAST_TXID', + sentOnly: true, + senders: ['SENDER_ADDRESS'], + receivers: ['RECEIVER_ADDRESS'], + tx: true +}; + +floBlockchainAPI.getLatestData(address, validationFunction, options) + .then(result => { + console.log("Last Valid Transaction ID:", result.lastItem); + console.log("Transaction Data:", result.data); + // If tx option is set to true + // console.log("Transaction Object:", result.item); + }) + .catch(error => { + console.error("Error:", error); + }); +``` + diff --git a/docs/floCloud.md b/docs/floCloud.md new file mode 100644 index 0000000..9839a7d --- /dev/null +++ b/docs/floCloud.md @@ -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¶m2=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¶m2=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); + }); +``` + + + diff --git a/docs/floCrypto.md b/docs/floCrypto.md new file mode 100644 index 0000000..9617d94 --- /dev/null +++ b/docs/floCrypto.md @@ -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); +``` diff --git a/docs/floDapps.md b/docs/floDapps.md new file mode 100644 index 0000000..b1445de --- /dev/null +++ b/docs/floDapps.md @@ -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 +``` + diff --git a/docs/floTokenAPI.md b/docs/floTokenAPI.md new file mode 100644 index 0000000..379ace8 --- /dev/null +++ b/docs/floTokenAPI.md @@ -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); +``` + + diff --git a/docs/functions.md b/docs/functions.md index 1246a76..918a70f 100644 --- a/docs/functions.md +++ b/docs/functions.md @@ -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. \ No newline at end of file diff --git a/docs/product-overview.md b/docs/product-overview.md new file mode 100644 index 0000000..45321f7 --- /dev/null +++ b/docs/product-overview.md @@ -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 \ No newline at end of file diff --git a/docs/render.html b/docs/render.html new file mode 100644 index 0000000..3c41414 --- /dev/null +++ b/docs/render.html @@ -0,0 +1,41 @@ + + + + + + + + Dynamic List with uhtml + + + +
+ + + + + + diff --git a/docs/technical-architecture.md b/docs/technical-architecture.md new file mode 100644 index 0000000..c320ffa --- /dev/null +++ b/docs/technical-architecture.md @@ -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 + +``` + + + + + + + Dynamic List with uhtml + + + +
+ + + + + + +``` + +### 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` + + ` + } + +//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); + } +``` diff --git a/docs/usage.md b/docs/usage.md new file mode 100644 index 0000000..889b222 --- /dev/null +++ b/docs/usage.md @@ -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