From 7e618c98f23979dd1949d123f6dfb8e4b2310074 Mon Sep 17 00:00:00 2001 From: sairajzero Date: Tue, 2 May 2023 22:15:54 +0530 Subject: [PATCH] floTokenAPI v1.0.4: Added bunkTransferTokens - Added bunkTransferTokens: bulk transfer tokens to multiple receivers - usage: floWebWallet.bunkTransferTokens(sender, privKey, token, receivers) sender: floID of sender privKey: private key of sender token: token to send receivers: an object representing receiver floID and token amount ie, {receiverID1: amount1, receiverID2: amount2....} eg: {Fxyz: 123, Fpqr:321, Fabc: 987} --- floTokenAPI.js | 66 +++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 65 insertions(+), 1 deletion(-) diff --git a/floTokenAPI.js b/floTokenAPI.js index efbd2ae..346ab65 100644 --- a/floTokenAPI.js +++ b/floTokenAPI.js @@ -1,4 +1,4 @@ -(function (EXPORTS) { //floTokenAPI v1.0.3c +(function (EXPORTS) { //floTokenAPI v1.0.4 /* Token Operator to send/receive tokens via blockchain using API calls*/ 'use strict'; const tokenAPI = EXPORTS; @@ -77,6 +77,70 @@ }); } + function sendTokens_raw(privKey, receiverID, token, amount, utxo, vout, scriptPubKey) { + return new Promise((resolve, reject) => { + var trx = bitjs.transaction(); + trx.addinput(utxo, vout, scriptPubKey) + trx.addoutput(receiverID, floBlockchainAPI.sendAmt); + trx.addflodata(`send ${amount} ${token}#`); + var signedTxHash = trx.sign(privKey, 1); + floBlockchainAPI.broadcastTx(signedTxHash) + .then(txid => resolve([receiverID, txid])) + .catch(error => reject([receiverID, error])) + }) + } + + //bulk transfer tokens + tokenAPI.bunkTransferTokens = function (sender, privKey, token, receivers) { + return new Promise((resolve, reject) => { + if (typeof receivers !== 'object') + return reject("receivers must be object in format {receiver1: amount1, receiver2:amount2...}") + + let receiver_list = Object.keys(receivers), amount_list = Object.values(receivers); + let invalidReceivers = receiver_list.filter(id => !floCrypto.validateFloID(id)); + let invalidAmount = amount_list.filter(val => typeof val !== 'number' || val <= 0); + if (invalidReceivers.length) + return reject(`Invalid receivers: ${invalidReceivers}`); + else if (invalidAmount.length) + return reject(`Invalid amounts: ${invalidAmount}`); + + if (receiver_list.length == 0) + return reject("Receivers cannot be empty"); + + if (receiver_list.length == 1) { + let receiver = receiver_list[0], amount = amount_list[0]; + floTokenAPI.sendToken(privKey, amount, receiver, "", token) + .then(txid => resolve({ success: { [receiver]: txid } })) + .catch(error => reject(error)) + } else { + //check for token balance + floTokenAPI.getBalance(sender, token).then(token_balance => { + let total_token_amout = amount_list.reduce((a, e) => a + e, 0); + if (total_token_amout > token_balance) + return reject(`Insufficient ${token}# balance`); + + //split utxos + floBlockchainAPI.splitUTXOs(sender, privKey, receiver_list.length).then(split_txid => { + //wait for the split utxo to get confirmation + floBlockchainAPI.waitForConfirmation(split_txid).then(split_tx => { + //send tokens using the split-utxo + var scriptPubKey = split_tx.vout[0].scriptPubKey.hex; + let promises = []; + for (let i in receiver_list) + promises.push(sendTokens_raw(privKey, receiver_list[i], token, amount_list[i], split_txid, i, scriptPubKey)); + Promise.allSettled(promises).then(results => { + let success = Object.fromEntries(results.filter(r => r.status == 'fulfilled').map(r => r.value)); + let failed = Object.fromEntries(results.filter(r => r.status == 'rejected').map(r => r.reason)); + resolve({ success, failed }); + }) + }).catch(error => reject(error)) + }).catch(error => reject(error)) + }).catch(error => reject(error)) + } + + }) + } + tokenAPI.getAllTxs = function (floID, token = DEFAULT.currency) { return new Promise((resolve, reject) => { fetch_api(`api/v1.0/getFloAddressTransactions?token=${token}&floAddress=${floID}`)