dappbundle/flowallet/scripts/floTokenAPI.min.js

1 line
5.3 KiB
JavaScript

!function(EXPORTS){"use strict";const tokenAPI="object"===typeof module?module.exports:window.floTokenAPI={},DEFAULT={apiURL:[floGlobals.tokenURL||"https://ranchimallflo.ranchimall.net/"],currency:floGlobals.currency||"rupee"},checkIfTor=tokenAPI.checkIfTor=()=>fetch("https://check.torproject.org/api/ip",{mode:"no-cors"}).then((response=>response.json())).then((result=>result.IsTor)).catch((error=>!1));let isTor=!1;checkIfTor().then((result=>{isTor=result,isTor&&(DEFAULT.apiURL=["http://omwkzk6bd6zuragdqsrhdyzgxzre7yx4vzrou4vzftintzc2dmagp6qd.onion:5017/"])})),Object.defineProperties(tokenAPI,{URL:{get:()=>DEFAULT.apiURL[0]},currency:{get:()=>DEFAULT.currency,set:currency=>DEFAULT.currency=currency}}),floGlobals.currency&&(tokenAPI.currency=floGlobals.currency),Object.defineProperties(floGlobals,{currency:{get:()=>DEFAULT.currency,set:currency=>DEFAULT.currency=currency}});const fetch_api=tokenAPI.fetch=function(apicall,apiURLs=DEFAULT.apiURL){return new Promise(((resolve,reject)=>{if(0===apiURLs.length)return void reject("No API URLs available");const currentURL=apiURLs[0];console.debug(currentURL+apicall),fetch(currentURL+apicall).then((response=>{response.ok?response.json().then((data=>resolve(data))):reject(response)})).catch((error=>{console.error(`Failed to fetch from ${currentURL}: ${error}`),fetch_api(apicall,apiURLs.slice(1)).then(resolve).catch(reject)}))}))},getBalance=tokenAPI.getBalance=function(floID,token=DEFAULT.currency){return new Promise(((resolve,reject)=>{fetch_api(`api/v1.0/getFloAddressBalance?token=${token}&floAddress=${floID}`).then((result=>resolve(result.balance||0))).catch((error=>reject(error)))}))};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])))}))}tokenAPI.getTx=function(txID){return new Promise(((resolve,reject)=>{fetch_api(`api/v1.0/getTransactionDetails/${txID}`).then((res=>{"error"===res.result?reject(res.description):res.parsedFloData?res.transactionDetails?resolve(res):reject("Data piece (transactionDetails) missing"):reject("Data piece (parsedFloData) missing")})).catch((error=>reject(error)))}))},tokenAPI.sendToken=function(privKey,amount,receiverID,message="",token=DEFAULT.currency,options={}){return new Promise(((resolve,reject)=>{let senderID=floCrypto.getFloID(privKey);if("number"!=typeof amount||isNaN(amount)||amount<=0)return reject("Invalid amount");getBalance(senderID,token).then((bal=>{if(amount>bal)return reject(`Insufficient ${token}# balance`);floBlockchainAPI.writeData(senderID,`send ${amount} ${token}# ${message}`,privKey,receiverID,options).then((txid=>resolve(txid))).catch((error=>reject(error)))})).catch((error=>reject(error)))}))},tokenAPI.bulkTransferTokens=function(sender,privKey,token,receivers){return new Promise(((resolve,reject)=>{if("object"!=typeof receivers)return reject("receivers must be object in format {receiver1: amount1, receiver2:amount2...}");let receiver_list=Object.keys(receivers),amount_list=Object.values(receivers),invalidReceivers=receiver_list.filter((id=>!floCrypto.validateFloID(id))),invalidAmount=amount_list.filter((val=>"number"!=typeof val||val<=0));if(invalidReceivers.length)return reject(`Invalid receivers: ${invalidReceivers}`);if(invalidAmount.length)return reject(`Invalid amounts: ${invalidAmount}`);if(0==receiver_list.length)return reject("Receivers cannot be empty");if(1==receiver_list.length){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 floTokenAPI.getBalance(sender,token).then((token_balance=>{if(amount_list.reduce(((a,e)=>a+e),0)>token_balance)return reject(`Insufficient ${token}# balance`);floBlockchainAPI.splitUTXOs(sender,privKey,receiver_list.length).then((split_txid=>{floBlockchainAPI.waitForConfirmation(split_txid).then((split_tx=>{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=>"fulfilled"==r.status)).map((r=>r.value))),failed=Object.fromEntries(results.filter((r=>"rejected"==r.status)).map((r=>r.reason)));resolve({success:success,failed: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}`).then((result=>resolve(result))).catch((error=>reject(error)))}))};(tokenAPI.util={}).parseTxData=function(txData){let parsedData={};for(let p in txData.parsedFloData)parsedData[p]=txData.parsedFloData[p];parsedData.sender=txData.transactionDetails.vin[0].addr;for(let vout of txData.transactionDetails.vout)vout.scriptPubKey.addresses[0]!==parsedData.sender&&(parsedData.receiver=vout.scriptPubKey.addresses[0]);return parsedData.time=txData.transactionDetails.time,parsedData}}();