Update stdop

This commit is contained in:
sairajzero 2022-05-25 02:31:31 +05:30
parent 44541513ef
commit 56e571606c
4 changed files with 216 additions and 120 deletions

View File

@ -1,9 +1,54 @@
(function(EXPORTS) { //floBlockchainAPI v2.3.0 (function(EXPORTS) { //floBlockchainAPI v2.3.3
/* FLO Blockchain Operator to send/receive data from blockchain using API calls*/ /* FLO Blockchain Operator to send/receive data from blockchain using API calls*/
'use strict'; 'use strict';
const floBlockchainAPI = EXPORTS; const floBlockchainAPI = EXPORTS;
const serverList = floGlobals.apiURL[floGlobals.blockchain].slice(0); const DEFAULT = {
blockchain: floGlobals.blockchain,
apiURL: {
FLO: ['https://livenet.flocha.in/', 'https://flosight.duckdns.org/'],
FLO_TEST: ['https://testnet-flosight.duckdns.org', 'https://testnet.flocha.in/']
},
sendAmt: 0.001,
fee: 0.0005,
receiverID: floGlobals.adminID
};
Object.defineProperties(floBlockchainAPI, {
sendAmt: {
get: () => DEFAULT.sendAmt,
set: amt => !isNaN(amt) ? DEFAULT.sendAmt = amt : null
},
fee: {
get: () => DEFAULT.fee,
set: fee => !isNaN(fee) ? DEFAULT.fee = fee : null
},
defaultReceiver: {
get: () => DEFAULT.receiverID,
set: floID => DEFAULT.receiverID = floID
},
blockchain: {
get: () => DEFAULT.blockchain
}
});
if (floGlobals.sendAmt) floBlockchainAPI.sendAmt = floGlobals.sendAmt;
if (floGlobals.fee) floBlockchainAPI.fee = floGlobals.fee;
Object.defineProperties(floGlobals, {
sendAmt: {
get: () => DEFAULT.sendAmt,
set: amt => !isNaN(amt) ? DEFAULT.sendAmt = amt : null
},
fee: {
get: () => DEFAULT.fee,
set: fee => !isNaN(fee) ? DEFAULT.fee = fee : null
}
});
const allServerList = new Set(floGlobals.apiURL && floGlobals.apiURL[DEFAULT.blockchain] ? floGlobals.apiURL[DEFAULT.blockchain] : DEFAULT.apiURL[DEFAULT.blockchain]);
var serverList = Array.from(allServerList);
var curPos = floCrypto.randInt(0, serverList - 1); var curPos = floCrypto.randInt(0, serverList - 1);
function fetch_retry(apicall, rm_flosight) { function fetch_retry(apicall, rm_flosight) {
@ -11,17 +56,24 @@
let i = serverList.indexOf(rm_flosight) let i = serverList.indexOf(rm_flosight)
if (i != -1) serverList.splice(i, 1); if (i != -1) serverList.splice(i, 1);
curPos = floCrypto.randInt(0, serverList.length - 1); curPos = floCrypto.randInt(0, serverList.length - 1);
fetch_api(apicall) fetch_api(apicall, false)
.then(result => resolve(result)) .then(result => resolve(result))
.catch(error => reject(error)); .catch(error => reject(error));
}) })
} }
function fetch_api(apicall) { function fetch_api(apicall, ic = true) {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
if (serverList.length === 0) if (serverList.length === 0) {
reject("No floSight server working"); if (ic) {
else { serverList = Array.from(allServerList);
curPos = floCrypto.randInt(0, serverList.length - 1);
fetch_api(apicall, false)
.then(result => resolve(result))
.catch(error => reject(error));
} else
reject("No floSight server working");
} else {
let flosight = serverList[curPos]; let flosight = serverList[curPos];
fetch(flosight + apicall).then(response => { fetch(flosight + apicall).then(response => {
if (response.ok) if (response.ok)
@ -40,12 +92,17 @@
}) })
} }
Object.defineProperty(floBlockchainAPI, 'current_server', { Object.defineProperties(floBlockchainAPI, {
get: () => serverList[curPos] serverList: {
get: () => Array.from(serverList)
},
current_server: {
get: () => serverList[curPos]
}
}); });
//Promised function to get data from API //Promised function to get data from API
const promisedAPI = floBlockchainAPI.promisedAPI = function(apicall) { const promisedAPI = floBlockchainAPI.promisedAPI = floBlockchainAPI.fetch = function(apicall) {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
//console.log(apicall); //console.log(apicall);
fetch_api(apicall) fetch_api(apicall)
@ -77,48 +134,52 @@
else if (typeof sendAmt !== 'number' || sendAmt <= 0) else if (typeof sendAmt !== 'number' || sendAmt <= 0)
return reject(`Invalid sendAmt : ${sendAmt}`); return reject(`Invalid sendAmt : ${sendAmt}`);
//get unconfirmed tx list getBalance(senderAddr).then(balance => {
promisedAPI(`api/addr/${senderAddr}`).then(result => { var fee = DEFAULT.fee;
readTxs(senderAddr, 0, result.unconfirmedTxApperances).then(result => { if (balance < sendAmt + fee)
let unconfirmedSpent = {}; return reject("Insufficient FLO balance!");
for (let tx of result.items) //get unconfirmed tx list
if (tx.confirmations == 0) promisedAPI(`api/addr/${senderAddr}`).then(result => {
for (let vin of tx.vin) readTxs(senderAddr, 0, result.unconfirmedTxApperances).then(result => {
if (vin.addr === senderAddr) { let unconfirmedSpent = {};
if (Array.isArray(unconfirmedSpent[vin.txid])) for (let tx of result.items)
unconfirmedSpent[vin.txid].push(vin.vout); if (tx.confirmations == 0)
else for (let vin of tx.vin)
unconfirmedSpent[vin.txid] = [vin.vout]; if (vin.addr === senderAddr) {
} if (Array.isArray(unconfirmedSpent[vin.txid]))
//get utxos list unconfirmedSpent[vin.txid].push(vin.vout);
promisedAPI(`api/addr/${senderAddr}/utxo`).then(utxos => { else
//form/construct the transaction data unconfirmedSpent[vin.txid] = [vin.vout];
var trx = bitjs.transaction(); }
var utxoAmt = 0.0; //get utxos list
var fee = floGlobals.fee; promisedAPI(`api/addr/${senderAddr}/utxo`).then(utxos => {
for (var i = utxos.length - 1; //form/construct the transaction data
(i >= 0) && (utxoAmt < sendAmt + fee); i--) { var trx = bitjs.transaction();
//use only utxos with confirmations (strict_utxo mode) var utxoAmt = 0.0;
if (utxos[i].confirmations || !strict_utxo) { for (var i = utxos.length - 1;
if (utxos[i].txid in unconfirmedSpent && unconfirmedSpent[utxos[i].txid].includes(utxos[i].vout)) (i >= 0) && (utxoAmt < sendAmt + fee); i--) {
continue; //A transaction has already used the utxo, but is unconfirmed. //use only utxos with confirmations (strict_utxo mode)
trx.addinput(utxos[i].txid, utxos[i].vout, utxos[i].scriptPubKey); if (utxos[i].confirmations || !strict_utxo) {
utxoAmt += utxos[i].amount; if (utxos[i].txid in unconfirmedSpent && unconfirmedSpent[utxos[i].txid].includes(utxos[i].vout))
}; continue; //A transaction has already used the utxo, but is unconfirmed.
} trx.addinput(utxos[i].txid, utxos[i].vout, utxos[i].scriptPubKey);
if (utxoAmt < sendAmt + fee) utxoAmt += utxos[i].amount;
reject("Insufficient FLO balance!"); };
else { }
trx.addoutput(receiverAddr, sendAmt); if (utxoAmt < sendAmt + fee)
var change = utxoAmt - sendAmt - fee; reject("Insufficient FLO: Some UTXOs are unconfirmed");
if (change > 0) else {
trx.addoutput(senderAddr, change); trx.addoutput(receiverAddr, sendAmt);
trx.addflodata(floData.replace(/\n/g, ' ')); var change = utxoAmt - sendAmt - fee;
var signedTxHash = trx.sign(privKey, 1); if (change > 0)
broadcastTx(signedTxHash) trx.addoutput(senderAddr, change);
.then(txid => resolve(txid)) trx.addflodata(floData.replace(/\n/g, ' '));
.catch(error => reject(error)) var signedTxHash = trx.sign(privKey, 1);
} broadcastTx(signedTxHash)
.then(txid => resolve(txid))
.catch(error => reject(error))
}
}).catch(error => reject(error))
}).catch(error => reject(error)) }).catch(error => reject(error))
}).catch(error => reject(error)) }).catch(error => reject(error))
}).catch(error => reject(error)) }).catch(error => reject(error))
@ -126,11 +187,13 @@
} }
//Write Data into blockchain //Write Data into blockchain
floBlockchainAPI.writeData = function(senderAddr, data, privKey, receiverAddr = floGlobals.adminID, strict_utxo = true) { floBlockchainAPI.writeData = function(senderAddr, data, privKey, receiverAddr = DEFAULT.receiverID, options = {}) {
let strict_utxo = options.strict_utxo === false ? false : true,
sendAmt = isNaN(options.sendAmt) ? DEFAULT.sendAmt : options.sendAmt;
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
if (typeof data != "string") if (typeof data != "string")
data = JSON.stringify(data); data = JSON.stringify(data);
sendTx(senderAddr, receiverAddr, floGlobals.sendAmt, privKey, data, strict_utxo) sendTx(senderAddr, receiverAddr, sendAmt, privKey, data, strict_utxo)
.then(txid => resolve(txid)) .then(txid => resolve(txid))
.catch(error => reject(error)); .catch(error => reject(error));
}); });
@ -147,7 +210,7 @@
return reject("Invalid FLO_Data: only printable ASCII characters are allowed"); return reject("Invalid FLO_Data: only printable ASCII characters are allowed");
var trx = bitjs.transaction(); var trx = bitjs.transaction();
var utxoAmt = 0.0; var utxoAmt = 0.0;
var fee = floGlobals.fee; var fee = DEFAULT.fee;
promisedAPI(`api/addr/${floID}/utxo`).then(utxos => { promisedAPI(`api/addr/${floID}/utxo`).then(utxos => {
for (var i = utxos.length - 1; i >= 0; i--) for (var i = utxos.length - 1; i >= 0; i--)
if (utxos[i].confirmations) { if (utxos[i].confirmations) {
@ -171,13 +234,13 @@
* @param {boolean} preserveRatio (optional) preserve ratio or equal contribution * @param {boolean} preserveRatio (optional) preserve ratio or equal contribution
* @return {Promise} * @return {Promise}
*/ */
floBlockchainAPI.writeDataMultiple = function(senderPrivKeys, data, receivers = [floGlobals.adminID], preserveRatio = true) { floBlockchainAPI.writeDataMultiple = function(senderPrivKeys, data, receivers = [DEFAULT.receiverID], preserveRatio = true) {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
if (!Array.isArray(senderPrivKeys)) if (!Array.isArray(senderPrivKeys))
return reject("Invalid senderPrivKeys: SenderPrivKeys must be Array"); return reject("Invalid senderPrivKeys: SenderPrivKeys must be Array");
if (!preserveRatio) { if (!preserveRatio) {
let tmp = {}; let tmp = {};
let amount = (floGlobals.sendAmt * receivers.length) / senderPrivKeys.length; let amount = (DEFAULT.sendAmt * receivers.length) / senderPrivKeys.length;
senderPrivKeys.forEach(key => tmp[key] = amount); senderPrivKeys.forEach(key => tmp[key] = amount);
senderPrivKeys = tmp; senderPrivKeys = tmp;
} }
@ -185,7 +248,7 @@
return reject("Invalid receivers: Receivers must be Array"); return reject("Invalid receivers: Receivers must be Array");
else { else {
let tmp = {}; let tmp = {};
let amount = floGlobals.sendAmt; let amount = DEFAULT.sendAmt;
receivers.forEach(floID => tmp[floID] = amount); receivers.forEach(floID => tmp[floID] = amount);
receivers = tmp receivers = tmp
} }
@ -288,7 +351,7 @@
promises.push(getBalance(floID)); promises.push(getBalance(floID));
Promise.all(promises).then(results => { Promise.all(promises).then(results => {
let totalBalance = 0, let totalBalance = 0,
totalFee = floGlobals.fee, totalFee = DEFAULT.fee,
balance = {}; balance = {};
//Divide fee among sender if not for preserveRatio //Divide fee among sender if not for preserveRatio
if (!preserveRatio) if (!preserveRatio)

View File

@ -2,17 +2,8 @@ const floGlobals = {
//Required for all //Required for all
blockchain: "FLO", blockchain: "FLO",
//Required for blockchain API operators
apiURL: {
FLO: ['https://livenet.flocha.in/', 'https://flosight.duckdns.org/'],
FLO_TEST: ['https://testnet-flosight.duckdns.org', 'https://testnet.flocha.in/']
},
application: "exchange", application: "exchange",
adminID: "FMxYC7gYZhouzqtHZukGnPiQ8nvG4CMzXM", adminID: "FMxYC7gYZhouzqtHZukGnPiQ8nvG4CMzXM",
sendAmt: 0.001,
fee: 0.0005,
tokenURL: "https://ranchimallflo.duckdns.org/",
currency: "rupee" currency: "rupee"
}; };

View File

@ -1,53 +1,95 @@
'use strict'; (function(EXPORTS) { //floTokenAPI v1.0.3a
/* Token Operator to send/receive tokens via blockchain using API calls*/
'use strict';
const tokenAPI = EXPORTS;
/* Token Operator to send/receive tokens from blockchain using API calls*/ const DEFAULT = {
(function(GLOBAL) { apiURL: floGlobals.tokenURL || "https://ranchimallflo.duckdns.org/",
const floTokenAPI = GLOBAL.floTokenAPI = { currency: "rupee"
fetch_api: function(apicall) {
return new Promise((resolve, reject) => {
console.log(floGlobals.tokenURL + apicall);
fetch(floGlobals.tokenURL + apicall).then(response => {
if (response.ok)
response.json().then(data => resolve(data));
else
reject(response)
}).catch(error => reject(error))
})
},
getBalance: function(floID, token = floGlobals.currency) {
return new Promise((resolve, reject) => {
this.fetch_api(`api/v1.0/getFloAddressBalance?token=${token}&floAddress=${floID}`)
.then(result => resolve(result.balance || 0))
.catch(error => reject(error))
})
},
getTx: function(txID) {
return new Promise((resolve, reject) => {
this.fetch_api(`api/v1.0/getTransactionDetails/${txID}`).then(res => {
if (res.result === "error")
reject(res.description);
else if (!res.parsedFloData)
reject("Data piece (parsedFloData) missing");
else if (!res.transactionDetails)
reject("Data piece (transactionDetails) missing");
else
resolve(res);
}).catch(error => reject(error))
})
},
sendToken: function(privKey, amount, receiverID, message = "", token = floGlobals.currency) {
return new Promise((resolve, reject) => {
let senderID = floCrypto.getFloID(privKey);
if (typeof amount !== "number" || amount <= 0)
return reject("Invalid amount");
this.getBalance(senderID, token).then(bal => {
if (amount > bal)
return reject(`Insufficient ${token}# balance`);
floBlockchainAPI.writeData(senderID, `send ${amount} ${token}# ${message}`, privKey, receiverID)
.then(txid => resolve(txid))
.catch(error => reject(error))
}).catch(error => reject(error))
});
}
} }
})(typeof global !== "undefined" ? global : window);
Object.defineProperties(tokenAPI, {
URL: {
get: () => DEFAULT.apiURL
},
currency: {
get: () => DEFAULT.currency,
set: currency => DEFAULT.currency = currency
}
});
if (floGlobals.currency) tokenAPI.currency = floGlobals.currency;
const fetch_api = tokenAPI.fetch = function(apicall) {
return new Promise((resolve, reject) => {
console.log(DEFAULT.apiURL + apicall);
fetch(DEFAULT.apiURL + apicall).then(response => {
if (response.ok)
response.json().then(data => resolve(data));
else
reject(response)
}).catch(error => reject(error))
})
}
const 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))
})
}
tokenAPI.getTx = function(txID) {
return new Promise((resolve, reject) => {
fetch_api(`api/v1.0/getTransactionDetails/${txID}`).then(res => {
if (res.result === "error")
reject(res.description);
else if (!res.parsedFloData)
reject("Data piece (parsedFloData) missing");
else if (!res.transactionDetails)
reject("Data piece (transactionDetails) missing");
else
resolve(res);
}).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 (typeof amount !== "number" || 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.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))
})
}
const util = tokenAPI.util = {};
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)
if (vout.scriptPubKey.addresses[0] !== parsedData.sender)
parsedData.receiver = vout.scriptPubKey.addresses[0];
parsedData.time = txData.transactionDetails.time;
return parsedData;
}
})('object' === typeof module ? module.exports : window.floTokenAPI = {});

View File

@ -4,7 +4,7 @@ require('./set_globals');
require('../docs/scripts/lib'); require('../docs/scripts/lib');
global.floCrypto = require('../docs/scripts/floCrypto'); global.floCrypto = require('../docs/scripts/floCrypto');
global.floBlockchainAPI = require('../docs/scripts/floBlockchainAPI'); global.floBlockchainAPI = require('../docs/scripts/floBlockchainAPI');
require('../docs/scripts/floTokenAPI'); global.floTokenAPI = require('../docs/scripts/floTokenAPI');
const Database = require("./database"); const Database = require("./database");
const App = require('./app'); const App = require('./app');