Compare commits

..

No commits in common. "main" and "dev" have entirely different histories.
main ... dev

15 changed files with 360 additions and 829 deletions

View File

@ -1,32 +0,0 @@
name: Workflow push to Dappbundle
on: [push]
jobs:
build:
name: Build
runs-on: self-hosted
steps:
- name: Executing remote command
uses: appleboy/ssh-action@v1.0.0
with:
host: ${{ secrets.R_HOST }}
username: ${{ secrets.P_USERNAME }}
password: ${{ secrets.P_PASSWORD }}
port: ${{ secrets.SSH_PORT }}
script: |
if [ -d "${{ secrets.DEPLOYMENT_LOCATION}}/dappbundle" ]; then
echo "Folder exists. Skipping Git clone."
else
echo "Folder does not exist. Cloning repository..."
cd ${{ secrets.DEPLOYMENT_LOCATION}}/ && git clone https://github.com/ranchimall/dappbundle.git
fi
if [ -d "${{ secrets.DEPLOYMENT_LOCATION}}/dappbundle/${{ github.event.repository.name }}" ]; then
echo "Repository exists. Remove folder "
rm -r "${{ secrets.DEPLOYMENT_LOCATION}}/dappbundle/${{ github.event.repository.name }}"
fi
echo "Cloning repository..."
cd ${{ secrets.DEPLOYMENT_LOCATION}}/dappbundle && git clone https://github.com/ranchimall/${{ github.event.repository.name }}
cd "${{ secrets.DEPLOYMENT_LOCATION}}/dappbundle/${{ github.event.repository.name }}" && rm -rf .gitattributes .git .github .gitignore
cd ${{ secrets.DEPLOYMENT_LOCATION}}/dappbundle/ && git add . && git commit -m "Workflow updating files of ${{ github.event.repository.name }}" && git push "https://saketongit:${{ secrets.RM_ACCESS_TOKEN }}@github.com/ranchimall/dappbundle.git"

View File

@ -27,6 +27,7 @@ body {
scrollbar-gutter: stable;
color: rgba(var(--text-color), 1);
background-color: rgba(var(--background-color), 1);
transition: background-color 0.3s;
}
body[data-theme=dark] {
@ -452,6 +453,24 @@ ul {
align-content: flex-start;
}
.logo {
display: grid;
align-items: center;
grid-template-columns: auto 1fr;
gap: 0 0.3rem;
margin-right: auto;
}
.logo h4 {
text-transform: capitalize;
font-weight: 600;
}
.logo .main-logo {
height: 1.4rem;
width: 1.4rem;
fill: rgba(var(--text-color), 1);
stroke: none;
}
details:not(:last-of-type) {
border-bottom: thin solid rgba(var(--text-color), 0.3);
}
@ -664,22 +683,6 @@ sm-checkbox {
align-items: center;
}
.app-brand {
display: flex;
gap: 0.3rem;
align-items: center;
}
.app-brand .icon {
height: 1.7rem;
width: 1.7rem;
}
.app-name__company {
font-size: 0.8rem;
font-weight: 500;
color: rgba(var(--text-color), 0.8);
}
#user_popup_button {
background-color: rgba(var(--text-color), 0.06);
border-radius: 2rem;
@ -736,6 +739,7 @@ sm-checkbox {
padding: 1rem 0;
border-radius: 0.5rem;
font-weight: 400;
transition: background-color 0.3s;
-webkit-user-select: none;
-moz-user-select: none;
user-select: none;
@ -869,6 +873,7 @@ sm-checkbox {
top: 0;
background-color: rgba(var(--background-color), 1);
z-index: 2;
transition: background-color 0.3s;
}
.list__item {
@ -1574,6 +1579,7 @@ sm-checkbox {
flex: 0;
flex-direction: row;
border-radius: 0.5rem;
transition: background-color 0.3s;
}
.main_navbar__item .icon {
margin-bottom: 0;

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load Diff

View File

@ -21,7 +21,7 @@
<script src="scripts/floBlockchainAPI.js"></script>
<script src="scripts/floTokenAPI.js"></script>
<script src="scripts/floExchangeAPI.js"></script>
<script src="https://unpkg.com/lightweight-charts@3.8.0/dist/lightweight-charts.standalone.production.js"></script>
<script src="https://unpkg.com/lightweight-charts/dist/lightweight-charts.standalone.production.js"></script>
<script>
const DEFAULT_TRADE_PRICE_DEVIATION_BUY = 15 / 100;
const DEFAULT_TRADE_PRICE_DEVIATION_SELL = 10 / 100;
@ -71,17 +71,14 @@
</div>
<article id="home" class="page hidden">
<header id="main_header">
<div class="app-brand margin-right-auto">
<svg id="main_logo" class="icon" viewBox="0 0 27.25 32">
<div class="logo">
<svg class="main-logo" viewBox="0 0 27.25 32">
<title>RanchiMall</title>
<path
d="M27.14,30.86c-.74-2.48-3-4.36-8.25-6.94a20,20,0,0,1-4.2-2.49,6,6,0,0,1-1.25-1.67,4,4,0,0,1,0-2.26c.37-1.08.79-1.57,3.89-4.55a11.66,11.66,0,0,0,3.34-4.67,6.54,6.54,0,0,0,.05-2.82C20,3.6,18.58,2,16.16.49c-.89-.56-1.29-.64-1.3-.24a3,3,0,0,1-.3.72l-.3.55L13.42.94C13,.62,12.4.26,12.19.15c-.4-.2-.73-.18-.72.05a9.39,9.39,0,0,1-.61,1.33s-.14,0-.27-.13C8.76.09,8-.27,8,.23A11.73,11.73,0,0,1,6.76,2.6C4.81,5.87,2.83,7.49.77,7.49c-.89,0-.88,0-.61,1,.22.85.33.92,1.09.69A5.29,5.29,0,0,0,3,8.33c.23-.17.45-.29.49-.26a2,2,0,0,1,.22.63A1.31,1.31,0,0,0,4,9.34a5.62,5.62,0,0,0,2.27-.87L7,8l.13.55c.19.74.32.82,1,.65a7.06,7.06,0,0,0,3.46-2.47l.6-.71-.06.64c-.17,1.63-1.3,3.42-3.39,5.42L6.73,14c-3.21,3.06-3,5.59.6,8a46.77,46.77,0,0,0,4.6,2.41c.28.13,1,.52,1.59.87,3.31,2,4.95,3.92,4.95,5.93a2.49,2.49,0,0,0,.07.77h0c.09.09,0,.1.9-.14a2.61,2.61,0,0,0,.83-.32,3.69,3.69,0,0,0-.55-1.83A11.14,11.14,0,0,0,17,26.81a35.7,35.7,0,0,0-5.1-2.91C9.37,22.64,8.38,22,7.52,21.17a3.53,3.53,0,0,1-1.18-2.48c0-1.38.71-2.58,2.5-4.23,2.84-2.6,3.92-3.91,4.67-5.65a3.64,3.64,0,0,0,.42-2A3.37,3.37,0,0,0,13.61,5l-.32-.74.29-.48c.17-.27.37-.63.46-.8l.15-.3.44.64a5.92,5.92,0,0,1,1,2.81,5.86,5.86,0,0,1-.42,1.94c0,.12-.12.3-.15.4a9.49,9.49,0,0,1-.67,1.1,28,28,0,0,1-4,4.29C8.62,15.49,8.05,16.44,8,17.78a3.28,3.28,0,0,0,1.11,2.76c.95,1,2.07,1.74,5.25,3.32,3.64,1.82,5.22,2.9,6.41,4.38A4.78,4.78,0,0,1,21.94,31a3.21,3.21,0,0,0,.14.92,1.06,1.06,0,0,0,.43-.05l.83-.22.46-.12-.06-.46c-.21-1.53-1.62-3.25-3.94-4.8a37.57,37.57,0,0,0-5.22-2.82A13.36,13.36,0,0,1,11,21.19a3.36,3.36,0,0,1-.8-4.19c.41-.85.83-1.31,3.77-4.15,2.39-2.31,3.43-4.13,3.43-6a5.85,5.85,0,0,0-2.08-4.29c-.23-.21-.44-.43-.65-.65A2.5,2.5,0,0,1,15.27.69a10.6,10.6,0,0,1,2.91,2.78A4.16,4.16,0,0,1,19,6.16a4.91,4.91,0,0,1-.87,3c-.71,1.22-1.26,1.82-4.27,4.67a9.47,9.47,0,0,0-2.07,2.6,2.76,2.76,0,0,0-.33,1.54,2.76,2.76,0,0,0,.29,1.47c.57,1.21,2.23,2.55,4.65,3.73a32.41,32.41,0,0,1,5.82,3.24c2.16,1.6,3.2,3.16,3.2,4.8a1.94,1.94,0,0,0,.09.76,4.54,4.54,0,0,0,1.66-.4C27.29,31.42,27.29,31.37,27.14,30.86ZM6.1,7h0a3.77,3.77,0,0,1-1.46.45L4,7.51l.68-.83a25.09,25.09,0,0,0,3-4.82A12,12,0,0,1,8.28.76c.11-.12.77.32,1.53,1l.63.58-.57.84A10.34,10.34,0,0,1,6.1,7Zm5.71-1.78A9.77,9.77,0,0,1,9.24,7.18h0a5.25,5.25,0,0,1-1.17.28l-.58,0,.65-.78a21.29,21.29,0,0,0,2.1-3.12c.22-.41.42-.76.44-.79s.5.43.9,1.24L12,5ZM13.41,3a2.84,2.84,0,0,1-.45.64,11,11,0,0,1-.9-.91l-.84-.9.19-.45c.34-.79.39-.8,1-.31A9.4,9.4,0,0,1,13.8,2.33q-.18.34-.39.69Z" />
</svg>
<div class="app-name">
<div class="app-name__company">RanchiMall</div>
<h4 class="app-name__title">
Exchange
</h4>
<div class="grid">
<h4>RanchiMall Exchange</h4>
</div>
</div>
<theme-toggle id="theme_toggle"></theme-toggle>
@ -842,6 +839,7 @@
<h4 id="portfolio_popup__title" class="capitalize"></h4>
</header>
<sm-form id="portfolio_form">
<input type="text" id="sink_id" style="display: none;" hidden />
<sm-input id="get_receiver_id" placeholder="Receiver FLO ID" error-text="Invalid FLO ID" data-flo-id
required animate></sm-input>
<sm-input id="get_user_amount" placeholder="Quantity" type="number" min="0.00000001" step="0.00000001"
@ -2119,7 +2117,7 @@
entry.querySelector('.history-entry__token-action').textContent = `${type} ${asset}`
entry.querySelector('.history-entry__amount').textContent = amount
entry.querySelector('.history-entry__time').textContent = getFormattedTime(locktime)
entry.querySelector('.history-entry__txid').href = floBlockchainAPI.current_server + `tx/${txid}`
entry.querySelector('.history-entry__txid').href = `https://flosight.duckdns.org/tx/${txid}`
return entry;
}
}
@ -2813,6 +2811,7 @@
floExchangeAPI.getAccount(proxy.userID, await proxy.secret).then(async acc => {
document.body.classList.add('is-signed-in');
getRef('market_asset_rates').parentNode.remove()
location.hash = `#/exchange`
getRef('user_popup_button').addEventListener('click', () => openPopup('user_popup'));
getRef('trade_button').addEventListener('click', () => openPopup('confirm_trade_popup'));
accountDetails = acc
@ -2821,6 +2820,7 @@
document.querySelectorAll(".user-content").forEach(elem => elem.classList.remove('hidden'))
document.querySelectorAll(".my-flo-id").forEach(elem => elem.textContent = acc.floID)
getRef("user_id").value = acc.floID;
getRef("sink_id").value = acc.sinkID;
if (acc.subAdmin)
console.info("logged in as subAdmin");

View File

@ -1,13 +1,10 @@
(function (EXPORTS) { //btcOperator v1.1.3b
(function (EXPORTS) { //btcOperator v1.1.2a
/* BTC Crypto and API Operator */
const btcOperator = EXPORTS;
//This library uses API provided by chain.so (https://chain.so/)
const URL = "https://blockchain.info/";
const DUST_AMT = 546,
MIN_FEE_UPDATE = 219;
const fetch_api = btcOperator.fetch = function (api, json_res = true) {
return new Promise((resolve, reject) => {
console.debug(URL + api);
@ -403,12 +400,7 @@
return reject("Send amount is less than fee");
}
//remove all output with value less than DUST amount
let filtered_outputs = [], dust_value = 0;
tx.outs.forEach(o => o.value >= DUST_AMT ? filtered_outputs.push(o) : dust_value += o.value);
tx.outs = filtered_outputs;
//update result values
result.fee += util.Sat_to_BTC(dust_value);
tx.outs = tx.outs.filter(o => o.value != 0); //remove all output with value 0
result.output_size = output_size;
result.output_amount = total_amount - (fee_from_receiver ? result.fee : 0);
result.total_size = BASE_TX_SIZE + output_size + result.input_size;
@ -464,7 +456,7 @@
let size_per_input = _sizePerInput(addr, rs);
fetch_api(`unspent?active=${addr}`).then(result => {
let utxos = result.unspent_outputs;
//console.debug("add-utxo", addr, rs, required_amount, utxos);
console.debug("add-utxo", addr, rs, required_amount, utxos);
for (let i = 0; i < utxos.length && required_amount > 0; i++) {
if (!utxos[i].confirmations) //ignore unconfirmed utxo
continue;
@ -544,106 +536,6 @@
}
*/
function tx_fetch_for_editing(tx) {
return new Promise((resolve, reject) => {
if (typeof tx == 'string' && /^[0-9a-f]{64}$/i.test(tx)) { //tx is txid
getTx.hex(tx)
.then(txhex => resolve(deserializeTx(txhex)))
.catch(error => reject(error))
} else resolve(deserializeTx(tx));
})
}
btcOperator.editFee = function (tx_hex, new_fee, private_keys, change_only = true) {
return new Promise((resolve, reject) => {
if (!Array.isArray(private_keys))
private_keys = [private_keys];
tx_fetch_for_editing(tx_hex).then(tx => {
parseTransaction(tx).then(tx_parsed => {
if (tx_parsed.fee >= new_fee)
return reject("Fees can only be increased");
//editable addresses in output values (for fee increase)
var edit_output_address = new Set();
if (change_only === true) //allow only change values (ie, sender address) to be edited to inc fee
tx_parsed.inputs.forEach(inp => edit_output_address.add(inp.address));
else if (change_only === false) //allow all output values to be edited
tx_parsed.outputs.forEach(out => edit_output_address.add(out.address));
else if (typeof change_only == 'string') // allow only given receiver id output to be edited
edit_output_address.add(change_only);
else if (Array.isArray(change_only)) //allow only given set of receiver id outputs to be edited
change_only.forEach(id => edit_output_address.add(id));
//edit output values to increase fee
let inc_fee = util.BTC_to_Sat(new_fee - tx_parsed.fee);
if (inc_fee < MIN_FEE_UPDATE)
return reject(`Insufficient additional fee. Minimum increment: ${MIN_FEE_UPDATE}`);
for (let i = tx.outs.length - 1; i >= 0 && inc_fee > 0; i--) //reduce in reverse order
if (edit_output_address.has(tx_parsed.outputs[i].address)) {
let current_value = tx.outs[i].value;
if (current_value instanceof BigInteger) //convert BigInteger class to inv value
current_value = current_value.intValue();
//edit the value as required
if (current_value > inc_fee) {
tx.outs[i].value = current_value - inc_fee;
inc_fee = 0;
} else {
inc_fee -= current_value;
tx.outs[i].value = 0;
}
}
if (inc_fee > 0) {
let max_possible_fee = util.BTC_to_Sat(new_fee) - inc_fee; //in satoshi
return reject(`Insufficient output values to increase fee. Maximum fee possible: ${util.Sat_to_BTC(max_possible_fee)}`);
}
tx.outs = tx.outs.filter(o => o.value >= DUST_AMT); //remove all output with value less than DUST amount
//remove existing signatures and reset the scripts
let wif_keys = [];
for (let i in tx.ins) {
var addr = tx_parsed.inputs[i].address,
value = util.BTC_to_Sat(tx_parsed.inputs[i].value);
let addr_decode = coinjs.addressDecode(addr);
//find the correct key for addr
var privKey = private_keys.find(pk => verifyKey(addr, pk));
if (!privKey)
return reject(`Private key missing for ${addr}`);
//find redeemScript (if any)
const rs = _redeemScript(addr, privKey);
rs === false ? wif_keys.unshift(privKey) : wif_keys.push(privKey); //sorting private-keys (wif)
//reset the script for re-signing
var script;
if (!rs || !rs.length) {
//legacy script (derive from address)
let s = coinjs.script();
s.writeOp(118); //OP_DUP
s.writeOp(169); //OP_HASH160
s.writeBytes(addr_decode.bytes);
s.writeOp(136); //OP_EQUALVERIFY
s.writeOp(172); //OP_CHECKSIG
script = Crypto.util.bytesToHex(s.buffer);
} else if (((rs.match(/^00/) && rs.length == 44)) || (rs.length == 40 && rs.match(/^[a-f0-9]+$/gi)) || addr_decode.type === 'multisigBech32') {
//redeemScript for segwit/bech32 and multisig (bech32)
let s = coinjs.script();
s.writeBytes(Crypto.util.hexToBytes(rs));
s.writeOp(0);
s.writeBytes(coinjs.numToBytes(value.toFixed(0), 8));
script = Crypto.util.bytesToHex(s.buffer);
} else //redeemScript for multisig (segwit)
script = rs;
tx.ins[i].script = coinjs.script(script);
}
tx.witness = false; //remove all witness signatures
console.debug("Unsigned:", tx.serialize());
//re-sign the transaction
new Set(wif_keys).forEach(key => tx.sign(key, 1 /*sighashtype*/)); //Sign the tx using private key WIF
resolve(tx.serialize());
}).catch(error => reject(error))
}).catch(error => reject(error))
})
}
btcOperator.sendTx = function (senders, privkeys, receivers, amounts, fee = null, options = {}) {
return new Promise((resolve, reject) => {
createSignedTx(senders, privkeys, receivers, amounts, fee, options).then(result => {
@ -687,7 +579,7 @@
createTransaction(senders, redeemScripts, receivers, amounts, fee, options.change_address || senders[0], options.fee_from_receiver).then(result => {
let tx = result.transaction;
console.debug("Unsigned:", tx.serialize());
new Set(wif_keys).forEach(key => tx.sign(key, 1 /*sighashtype*/)); //Sign the tx using private key WIF
new Set(wif_keys).forEach(key => console.debug("Signing key:", key, tx.sign(key, 1 /*sighashtype*/))); //Sign the tx using private key WIF
console.debug("Signed:", tx.serialize());
resolve(result);
}).catch(error => reject(error));
@ -831,7 +723,7 @@
.catch(error => reject(error))
});
const parseTransaction = btcOperator.parseTransaction = function (tx) {
btcOperator.parseTransaction = function (tx) {
return new Promise((resolve, reject) => {
tx = deserializeTx(tx);
let result = {};
@ -888,7 +780,7 @@
.catch(error => reject(error))
})
const getTx = btcOperator.getTx = txid => new Promise((resolve, reject) => {
btcOperator.getTx = txid => new Promise((resolve, reject) => {
fetch_api(`rawtx/${txid}`).then(result => {
getLatestBlock().then(latest_block => resolve({
block: result.block_height,
@ -905,7 +797,7 @@
}).catch(error => reject(error))
});
getTx.hex = txid => new Promise((resolve, reject) => {
btcOperator.getTx.hex = txid => new Promise((resolve, reject) => {
fetch_api(`rawtx/${txid}?format=hex`, false)
.then(result => resolve(result))
.catch(error => reject(error))

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -1,6 +1,6 @@
'use strict';
(function (EXPORTS) { //floExchangeAPI v1.2.1
(function (EXPORTS) { //floExchangeAPI v1.2.0
const exchangeAPI = EXPORTS;
const DEFAULT = {
@ -608,7 +608,7 @@
BOBS_FUND: "bobs-fund"
}
const getSink = exchangeAPI.getSink = function (service = serviceList.EXCHANGE) {
exchangeAPI.getSink = function (service = serviceList.EXCHANGE) {
return new Promise((resolve, reject) => {
if (!(Object.values(serviceList).includes(service)))
return reject(ExchangeError(ExchangeError.BAD_REQUEST_CODE, 'service required', errorCode.INVALID_VALUE));
@ -1720,7 +1720,7 @@
const _l = key => DEFAULT.marketApp + '-' + key;
function refreshDataFromBlockchain() {
exchangeAPI.init = function refreshDataFromBlockchain() {
return new Promise((resolve, reject) => {
let nodes, trusted = new Set(), assets, tags, lastTx;
try {
@ -1731,12 +1731,13 @@
if (typeof nodes !== 'object' || nodes === null)
throw Error('nodes must be an object')
else
lastTx = localStorage.getItem(_l('lastTx'));
lastTx = parseInt(localStorage.getItem(_l('lastTx'))) || 0;
} catch (error) {
nodes = {};
trusted = new Set();
assets = new Set();
tags = new Set();
lastTx = undefined;
}
var query_options = { sentOnly: true, pattern: DEFAULT.marketApp };
@ -1783,7 +1784,7 @@
tags.add(t);
}
});
localStorage.setItem(_l('lastTx'), result.lastItem);
localStorage.setItem(_l('lastTx'), result.totalTxs);
localStorage.setItem(_l('nodes'), JSON.stringify(nodes));
localStorage.setItem(_l('trusted'), Array.from(trusted).join(","));
localStorage.setItem(_l('assets'), Array.from(assets).join(","));
@ -1796,17 +1797,6 @@
})
}
exchangeAPI.init = function (service = serviceList.EXCHANGE) {
return new Promise((resolve, reject) => {
refreshDataFromBlockchain().then(nodes => {
getSink(service)
.then(sinkID => floCrypto.validateAddr(sinkID) ? _sinkID = sinkID : undefined)
.catch(error => console.warn("Unable to fetch sinkID", error))
.finally(_ => resolve(nodes))
}).catch(error => reject(error))
})
}
const config = exchangeAPI.config = {
get trustedList() {
return new Set((localStorage.getItem(_l('trusted')) || "").split(','));
@ -1831,10 +1821,12 @@
}
//container for user ID and proxy private-key
var _userID, _publicKey, _privateKey, _sinkID;
const proxy = exchangeAPI.proxy = {
user: null,
private: null,
public: null,
async lock() {
if (!_privateKey)
if (!this.private)
return notify("No proxy key found!", 'error');
getPromptInput("Add password", 'This password applies to this browser only!', {
isPassword: true,
@ -1845,7 +1837,7 @@
else if (pwd.length < 4)
notify("Password minimum length is 4", 'error');
else {
let tmp = Crypto.AES.encrypt(_privateKey, pwd);
let tmp = Crypto.AES.encrypt(this.private, pwd);
localStorage.setItem(_l('proxy_secret'), "?" + tmp);
notify("Successfully locked with Password", 'success');
}
@ -1854,37 +1846,35 @@
clear() {
localStorage.removeItem(_l('proxy_secret'));
localStorage.removeItem(_l('user_ID'));
_userID = null;
_privateKey = null;
_publicKey = null;
this.user = null;
this.private = null;
this.public = null;
},
get sinkID() {
return _sinkID;
return getRef("sink_id").value;
},
set userID(id) {
localStorage.setItem(_l('user_ID'), id);
_userID = id;
this.user = id;
},
get userID() {
if (_userID)
return _userID;
if (this.user)
return this.user;
else {
let id = localStorage.getItem(_l('user_ID'));
return id ? _userID = id : undefined;
return id ? this.user = id : undefined;
}
},
get user() {
return this.userID;
},
set secret(key) {
localStorage.setItem(_l('proxy_secret'), key);
_privateKey = key;
_publicKey = floCrypto.getPubKeyHex(key);
this.private = key;
this.public = floCrypto.getPubKeyHex(key);
},
get secret() {
const self = this;
return new Promise((resolve, reject) => {
if (_privateKey)
return resolve(_privateKey);
if (self.private)
return resolve(self.private);
const Reject = reason => {
notify(reason, 'error');
@ -1892,9 +1882,9 @@
}
const setValues = priv => {
try {
_privateKey = priv;
_publicKey = floCrypto.getPubKeyHex(priv);
resolve(_privateKey);
self.private = priv;
self.public = floCrypto.getPubKeyHex(priv);
resolve(self.private);
} catch (error) {
Reject("Unable to fetch Proxy secret");
}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -48,7 +48,7 @@ function confirmDepositFLO() {
verifyTx.FLO = function (sender, txid, group) {
return new Promise((resolve, reject) => {
floBlockchainAPI.getTx(txid).then(tx => {
let vin_sender = tx.vin.filter(v => v.addresses[0] === sender)
let vin_sender = tx.vin.filter(v => v.addr === sender)
if (!vin_sender.length)
return reject([true, "Transaction not sent by the sender"]);
if (vin_sender.length !== tx.vin.length)
@ -129,24 +129,20 @@ function confirmDepositToken() {
verifyTx.token = function (sender, txid, group, currencyOnly = false) {
return new Promise((resolve, reject) => {
floTokenAPI.getTx(txid).then(tx => {
if (tx.type !== "transfer")
if (tx.parsedFloData.type !== "transfer")
return reject([true, "Transaction type not 'transfer'"]);
else if (tx.transferType !== "token")
else if (tx.parsedFloData.transferType !== "token")
return reject([true, "Transaction transfer is not 'token'"]);
var token = tx.tokenIdentification,
amount = tx.tokenAmount,
receiverAddress = tx.receiverAddress,
senderAddress = tx.senderAddress;
var token = tx.parsedFloData.tokenIdentification,
amount = tx.parsedFloData.tokenAmount;
if (currencyOnly && token !== floGlobals.currency)
return reject([true, "Token not currency"]);
else if (!currencyOnly && ((!assetList.includes(token) && token !== floGlobals.currency) || token === "FLO"))
return reject([true, "Token not authorised"]);
//let vin_sender = tx.vin.filter(v => v.addr === sender)
if (senderAddress != sender)
let vin_sender = tx.transactionDetails.vin.filter(v => v.addr === sender)
if (!vin_sender.length)
return reject([true, "Transaction not sent by the sender"]);
if (!keys.sink_chest.includes(group, receiverAddress))
return reject([true, "Transaction receiver is not market ID"]); //Maybe reject as false? (to compensate delay in chestsList loading from other nodes)
let flo_amount = tx.vout.reduce((a, v) => keys.sink_chest.includes(group, v.scriptPubKey.addresses[0]) ? a + v.value : a, 0);
let flo_amount = tx.transactionDetails.vout.reduce((a, v) => keys.sink_chest.includes(group, v.scriptPubKey.addresses[0]) ? a + v.value : a, 0);
if (flo_amount == 0)
return reject([true, "Transaction receiver is not market ID"]); //Maybe reject as false? (to compensate delay in chestsList loading from other nodes)
else
@ -189,7 +185,7 @@ function confirmVaultWithdraw() {
}).catch(error => console.error(error));
} else if (r.asset_type == pCode.ASSET_TYPE_TOKEN)
floTokenAPI.getTx(r.txid).then(tx => {
if (!tx.blockheight || !tx.confirmations) //Still not confirmed
if (!tx.transactionDetails.blockheight || !tx.transactionDetails.confirmations) //Still not confirmed
return;
DB.query("UPDATE VaultTransactions SET r_status=? WHERE id=?", [pCode.STATUS_SUCCESS, r.id])
.then(result => console.info("Token withdrawed:", r.floID, r.asset, r.amount))
@ -290,7 +286,7 @@ function confirmConvert() {
}).catch(error => console.error(error));
else if (r.mode == pCode.CONVERT_MODE_PUT)
floTokenAPI.getTx(r.out_txid).then(tx => {
if (!tx.blockheight || !tx.confirmations) //Still not confirmed
if (!tx.transactionDetails.blockheight || !tx.transactionDetails.confirmations) //Still not confirmed
return;
DB.query("UPDATE DirectConvert SET r_status=? WHERE id=?", [pCode.STATUS_SUCCESS, r.id])
.then(result => console.info(`${r.floID} converted ${r.quantity} BTC to ${r.amount}`))
@ -354,7 +350,7 @@ function confirmConvertFundWithdraw() {
}).catch(error => console.error(error));
} else if (r.mode == pCode.CONVERT_MODE_PUT) {//withdraw currency
floTokenAPI.getTx(r.txid).then(tx => {
if (!tx.blockheight || !tx.confirmations) //Still not confirmed
if (!tx.transactionDetails.blockheight || !tx.transactionDetails.confirmations) //Still not confirmed
return;
DB.query("UPDATE ConvertFund SET r_status=? WHERE id=?", [pCode.STATUS_SUCCESS, r.id])
.then(result => console.info(`Withdraw-fund ${r.amount} ${floGlobals.currency} successful`))
@ -411,7 +407,7 @@ function confirmConvertRefund() {
}).catch(error => console.error(error));
} else if (r.ASSET_TYPE_TOKEN)
floTokenAPI.getTx(r.out_txid).then(tx => {
if (!tx.blockheight || !tx.confirmations) //Still not confirmed
if (!tx.transactionDetails.blockheight || !tx.transactionDetails.confirmations) //Still not confirmed
return;
DB.query("UPDATE RefundConvert SET r_status=? WHERE id=?", [pCode.STATUS_SUCCESS, r.id])
.then(result => console.info(`Refunded ${r.amount} ${r.asset} to ${r.floID}`))
@ -504,10 +500,9 @@ function processAll() {
var lastSyncBlockHeight = 0;
function periodicProcess() {
floBlockchainAPI.promisedAPI('api/status').then(result => {
let blockbook_height = result.blockbook.bestHeight;
if (lastSyncBlockHeight < blockbook_height) {
lastSyncBlockHeight = blockbook_height;
floBlockchainAPI.promisedAPI('api/blocks?limit=1').then(result => {
if (lastSyncBlockHeight < result.blocks[0].height) {
lastSyncBlockHeight = result.blocks[0].height;
processAll();
console.log("Last Block :", lastSyncBlockHeight);
}

View File

@ -118,7 +118,7 @@ function sendAsset(floID, asset, quantity, type, id) {
balance_locked[sinkID][asset] -= quantity;
});
}
collectAndCall(SINK_GROUP[type], sinkID, callback); //TODO: add timeout to prevent infinite wait
collectAndCall(sinkID, callback); //TODO: add timeout to prevent infinite wait
callbackCollection[type][id] = callback;
if (!(sinkID in balance_locked))
balance_locked[sinkID] = {};