162 lines
5.6 KiB
JavaScript
162 lines
5.6 KiB
JavaScript
(function (EXPORTS) {
|
|
/*FLO Web Wallet operations*/
|
|
'use strict';
|
|
const floWebWallet = EXPORTS;
|
|
|
|
//generate a new Address triplet : resolves Object(floID,pubKey,privKey)
|
|
floWebWallet.generateNewAddr = function () {
|
|
return new Promise((resolve, reject) => {
|
|
try {
|
|
var triplet = floCrypto.generateNewID();
|
|
resolve(triplet);
|
|
} catch (error) {
|
|
reject(error);
|
|
}
|
|
})
|
|
}
|
|
|
|
//recover triplet from given privKey : resolves Object(floID,pubKey,privKey)
|
|
floWebWallet.recoverAddr = function (privKey) {
|
|
return new Promise((resolve, reject) => {
|
|
try {
|
|
var triplet = {}
|
|
triplet.privKey = privKey;
|
|
triplet.pubKey = floCrypto.getPubKeyHex(triplet.privKey);
|
|
triplet.floID = floCrypto.getFloID(triplet.pubKey);
|
|
resolve(triplet);
|
|
} catch (error) {
|
|
reject(error);
|
|
}
|
|
})
|
|
}
|
|
|
|
//get balance of address using API : resolves (balance)
|
|
floWebWallet.getBalance = function (address) {
|
|
return new Promise((resolve, reject) => {
|
|
floBlockchainAPI.getBalance(address)
|
|
.then(txid => resolve(txid))
|
|
.catch(error => reject(error))
|
|
})
|
|
}
|
|
|
|
//send transaction to the blockchain using API : resolves (txid)
|
|
floWebWallet.sendTransaction = function (sender, receiver, amount, floData, privKey) {
|
|
return new Promise((resolve, reject) => {
|
|
floBlockchainAPI.sendTx(sender, receiver, amount, privKey, floData)
|
|
.then(txid => resolve(txid))
|
|
.catch(error => reject(error))
|
|
})
|
|
}
|
|
|
|
function formatTx(address, tx) {
|
|
const result = {
|
|
time: tx.time,
|
|
block: tx.blockheight,
|
|
blockhash: tx.blockhash,
|
|
txid: tx.txid,
|
|
floData: tx.floData,
|
|
confirmations: tx.confirmations
|
|
};
|
|
|
|
// ---- Receivers (outputs) ----
|
|
const receivers = {};
|
|
for (const vout of tx.vout || []) {
|
|
const outAddrs =
|
|
(vout.addresses && vout.addresses.length ? vout.addresses :
|
|
vout.scriptPubKey && vout.scriptPubKey.addresses ? vout.scriptPubKey.addresses : null);
|
|
if (outAddrs && outAddrs.length) {
|
|
const id = outAddrs[0];
|
|
receivers[id] = (receivers[id] || 0) + Number(vout.value || 0);
|
|
}
|
|
}
|
|
result.receivers = receivers;
|
|
|
|
// ---- Coinbase vs normal ----
|
|
const isCoinbase = !!(tx.vin && tx.vin[0] && tx.vin[0].coinbase);
|
|
|
|
if (isCoinbase) {
|
|
const coinbase = tx.vin[0].coinbase; // string
|
|
result.mine = coinbase;
|
|
result.mined = { [coinbase]: Number(tx.valueOut || 0) };
|
|
return result;
|
|
}
|
|
|
|
// ---- Normal tx: senders, fees, first-party heuristics ----
|
|
result.fees = tx.fees;
|
|
|
|
const firstInAddr = (tx.vin && tx.vin[0] && tx.vin[0].addresses && tx.vin[0].addresses[0]) || undefined;
|
|
const firstOutAddrs =
|
|
(tx.vout && tx.vout[0] &&
|
|
((tx.vout[0].addresses && tx.vout[0].addresses[0]) ||
|
|
(tx.vout[0].scriptPubKey && tx.vout[0].scriptPubKey.addresses && tx.vout[0].scriptPubKey.addresses[0]))) || undefined;
|
|
if (firstInAddr) result.sender = firstInAddr;
|
|
if (firstOutAddrs) result.receiver = firstOutAddrs;
|
|
|
|
const senders = {};
|
|
for (const vin of tx.vin || []) {
|
|
const inAddrs = vin.addresses;
|
|
if (inAddrs && inAddrs.length) {
|
|
const id = inAddrs[0];
|
|
senders[id] = (senders[id] || 0) + Number(vin.value || 0);
|
|
}
|
|
}
|
|
result.senders = senders;
|
|
|
|
// ---- Remove change (net flow) ----
|
|
for (const id of Object.keys(senders)) {
|
|
if (receivers[id] != null) {
|
|
if (senders[id] > receivers[id]) {
|
|
senders[id] -= receivers[id];
|
|
delete receivers[id];
|
|
} else if (senders[id] < receivers[id]) {
|
|
receivers[id] -= senders[id];
|
|
delete senders[id];
|
|
} else {
|
|
// equal -> cancel both
|
|
delete senders[id];
|
|
delete receivers[id];
|
|
}
|
|
}
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
|
|
floWebWallet.listTransactions = function (address, page_options = {}) {
|
|
return new Promise((resolve, reject) => {
|
|
let options = {};
|
|
if (Number.isInteger(page_options.page))
|
|
options.page = page_options.page;
|
|
if (Number.isInteger(page_options.pageSize))
|
|
options.pageSize = page_options.pageSize;
|
|
floBlockchainAPI.readTxs(address, options).then(response => {
|
|
const result = {}
|
|
result.items = response.txs.map(tx => formatTx(address, tx));
|
|
result.page = response.page;
|
|
result.totalPages = response.totalPages;
|
|
resolve(result);
|
|
}).catch(error => reject(error))
|
|
})
|
|
}
|
|
|
|
//get address-label pairs from IDB : resolves Object(floID:label)
|
|
floWebWallet.getLabels = function () {
|
|
return new Promise((resolve, reject) => {
|
|
compactIDB.readAllData('labels')
|
|
.then(IDBresult => resolve(IDBresult))
|
|
.catch(error => reject(error))
|
|
})
|
|
}
|
|
|
|
//bulk transfer tokens
|
|
floWebWallet.bulkTransferTokens = function (sender, privKey, token, receivers) {
|
|
return new Promise((resolve, reject) => {
|
|
floTokenAPI.bulkTransferTokens(sender, privKey, token, receivers)
|
|
.then(result => resolve(result))
|
|
.catch(error => reject(error))
|
|
})
|
|
}
|
|
|
|
})(window.floWebWallet = {});
|