get-transact API

- Get user's deposit and withdraw history (private request: ie, requires signing)
- Update floTokenAPI
This commit is contained in:
sairajzero 2022-05-25 03:55:55 +05:30
parent 56e571606c
commit 166778e7f8
5 changed files with 240 additions and 180 deletions

View File

@ -1,6 +1,6 @@
'use strict';
(function (EXPORTS) { //floExchangeAPI v1.1.2
(function(EXPORTS) { //floExchangeAPI v1.1.2
const exchangeAPI = EXPORTS;
/*Kademlia DHT K-bucket implementation as a binary tree.*/
@ -46,7 +46,7 @@
this.arbiter = options.arbiter || this.arbiter
this.metadata = Object.assign({}, options.metadata)
this.createNode = function () {
this.createNode = function() {
return {
contacts: [],
dontSplit: false,
@ -55,7 +55,7 @@
}
}
this.ensureInt8 = function (name, val) {
this.ensureInt8 = function(name, val) {
if (!(val instanceof Uint8Array)) {
throw new TypeError(name + ' is not a Uint8Array')
}
@ -66,7 +66,7 @@
* @param {Uint8Array} array2
* @return {Boolean}
*/
this.arrayEquals = function (array1, array2) {
this.arrayEquals = function(array1, array2) {
if (array1 === array2) {
return true
}
@ -94,7 +94,7 @@
* @param {Object} candidate Contact being added to the k-bucket.
* @return {Object} Contact to updated the k-bucket with.
*/
this.arbiter = function (incumbent, candidate) {
this.arbiter = function(incumbent, candidate) {
return incumbent.vectorClock > candidate.vectorClock ? incumbent : candidate
}
@ -107,7 +107,7 @@
* @return {Number} Integer The XOR distance between firstId
* and secondId.
*/
this.distance = function (firstId, secondId) {
this.distance = function(firstId, secondId) {
let distance = 0
let i = 0
const min = Math.min(firstId.length, secondId.length)
@ -124,7 +124,7 @@
*
* @param {Object} contact the contact object to add
*/
this.add = function (contact) {
this.add = function(contact) {
this.ensureInt8('contact.id', (contact || {}).id)
let bitIndex = 0
@ -172,7 +172,7 @@
* closest contacts to return
* @return {Array} Array Maximum of n closest contacts to the node id
*/
this.closest = function (id, n = Infinity) {
this.closest = function(id, n = Infinity) {
this.ensureInt8('id', id)
if ((!Number.isInteger(n) && n !== Infinity) || n <= 0) {
@ -204,7 +204,7 @@
*
* @return {Number} The number of contacts held in the tree
*/
this.count = function () {
this.count = function() {
// return this.toArray().length
let count = 0
for (const nodes = [this.root]; nodes.length > 0;) {
@ -225,7 +225,7 @@
* to check in the id Uint8Array.
* @return {Object} left leaf if id at bitIndex is 0, right leaf otherwise.
*/
this._determineNode = function (node, id, bitIndex) {
this._determineNode = function(node, id, bitIndex) {
// *NOTE* remember that id is a Uint8Array and has granularity of
// bytes (8 bits), whereas the bitIndex is the bit index (not byte)
@ -267,7 +267,7 @@
* @param {Uint8Array} id The ID of the contact to fetch.
* @return {Object|Null} The contact if available, otherwise null
*/
this.get = function (id) {
this.get = function(id) {
this.ensureInt8('id', id)
let bitIndex = 0
@ -291,7 +291,7 @@
* @return {Number} Integer Index of contact with provided id if it
* exists, -1 otherwise.
*/
this._indexOf = function (node, id) {
this._indexOf = function(node, id) {
for (let i = 0; i < node.contacts.length; ++i) {
if (this.arrayEquals(node.contacts[i].id, id)) return i
}
@ -305,7 +305,7 @@
* @param {Uint8Array} id The ID of the contact to remove.
* @return {Object} The k-bucket itself.
*/
this.remove = function (id) {
this.remove = function(id) {
this.ensureInt8('the id as parameter 1', id)
let bitIndex = 0
@ -332,7 +332,7 @@
* @param {Number} bitIndex the bitIndex to which byte to check in the
* Uint8Array for navigating the binary tree
*/
this._split = function (node, bitIndex) {
this._split = function(node, bitIndex) {
node.left = this.createNode()
node.right = this.createNode()
@ -360,7 +360,7 @@
*
* @return {Array} All of the contacts in the tree, as an array
*/
this.toArray = function () {
this.toArray = function() {
let result = []
for (const nodes = [this.root]; nodes.length > 0;) {
const node = nodes.pop()
@ -386,7 +386,7 @@
* calculation)
* @param {Object} contact The contact object to update.
*/
this._update = function (node, index, contact) {
this._update = function(node, index, contact) {
// sanity check
if (!this.arrayEquals(node.contacts[index].id, contact.id)) {
throw new Error('wrong index for _update')
@ -405,7 +405,7 @@
}
const K_Bucket = exchangeAPI.K_Bucket = function K_Bucket(masterID, backupList) {
const decodeID = function (floID) {
const decodeID = function(floID) {
let k = bitjs.Base58.decode(floID);
k.shift();
k.splice(-4, 4);
@ -431,7 +431,7 @@
get: () => Array.from(orderedList)
});
self.closestNode = function (id, N = 1) {
self.closestNode = function(id, N = 1) {
let decodedId = decodeID(id);
let n = N || orderedList.length;
let cNodes = _KB.closest(decodedId, n)
@ -444,7 +444,7 @@
self.isPrev = (source, target) => orderedList.indexOf(target) === orderedList.indexOf(source) - 1;
self.isNext = (source, target) => orderedList.indexOf(target) === orderedList.indexOf(source) + 1;
self.prevNode = function (id, N = 1) {
self.prevNode = function(id, N = 1) {
let n = N || orderedList.length;
if (!orderedList.includes(id))
throw Error(`${id} is not in KB list`);
@ -452,7 +452,7 @@
return (N == 1 ? pNodes[0] : pNodes);
};
self.nextNode = function (id, N = 1) {
self.nextNode = function(id, N = 1) {
let n = N || orderedList.length;
if (!orderedList.includes(id))
throw Error(`${id} is not in KB list`);
@ -519,7 +519,7 @@
INTERNAL_ERROR: '500'
};
const parseErrorCode = exchangeAPI.parseErrorCode = function (message) {
const parseErrorCode = exchangeAPI.parseErrorCode = function(message) {
let code = message.match(/^E\d{3}:/g);
if (!code || !code.length)
return null;
@ -559,7 +559,7 @@
});
}
exchangeAPI.getAccount = function (floID, proxySecret) {
exchangeAPI.getAccount = function(floID, proxySecret) {
return new Promise((resolve, reject) => {
let request = {
floID: floID,
@ -586,7 +586,7 @@
});
}
exchangeAPI.getBuyList = function (asset = null) {
exchangeAPI.getBuyList = function(asset = null) {
return new Promise((resolve, reject) => {
fetch_api('/list-buyorders' + (asset ? "?asset=" + asset : ""))
.then(result => responseParse(result)
@ -596,7 +596,7 @@
});
}
exchangeAPI.getSellList = function (asset = null) {
exchangeAPI.getSellList = function(asset = null) {
return new Promise((resolve, reject) => {
fetch_api('/list-sellorders' + (asset ? "?asset=" + asset : ""))
.then(result => responseParse(result)
@ -606,7 +606,7 @@
});
}
exchangeAPI.getTradeList = function (asset = null) {
exchangeAPI.getTradeList = function(asset = null) {
return new Promise((resolve, reject) => {
fetch_api('/list-trades' + (asset ? "?asset=" + asset : ""))
.then(result => responseParse(result)
@ -616,7 +616,7 @@
});
}
exchangeAPI.getRates = function (asset = null) {
exchangeAPI.getRates = function(asset = null) {
return new Promise((resolve, reject) => {
fetch_api('/get-rates' + (asset ? "?asset=" + asset : ""))
.then(result => responseParse(result)
@ -626,7 +626,7 @@
});
}
exchangeAPI.getRateHistory = function (asset, duration = null) {
exchangeAPI.getRateHistory = function(asset, duration = null) {
return new Promise((resolve, reject) => {
fetch_api('/rate-history?asset=' + asset + (duration ? '&duration=' + duration : ""))
.then(result => responseParse(result)
@ -636,7 +636,7 @@
});
}
exchangeAPI.getBalance = function (floID = null, token = null) {
exchangeAPI.getBalance = function(floID = null, token = null) {
return new Promise((resolve, reject) => {
if (!floID && !token)
return reject(ExchangeError(ExchangeError.BAD_REQUEST_CODE, "Need atleast one argument", errorCode.MISSING_PARAMETER));
@ -651,7 +651,7 @@
})
}
exchangeAPI.getTx = function (txid) {
exchangeAPI.getTx = function(txid) {
return new Promise((resolve, reject) => {
if (!txid)
return reject(ExchangeError(ExchangeError.BAD_REQUEST_CODE, 'txid required', errorCode.MISSING_PARAMETER));
@ -670,7 +670,7 @@
return floCrypto.signData(req_str, signKey);
}
exchangeAPI.getLoginCode = function () {
exchangeAPI.getLoginCode = function() {
return new Promise((resolve, reject) => {
fetch_api('/get-login-code')
.then(result => responseParse(result)
@ -713,7 +713,7 @@
}
*/
exchangeAPI.login = function (privKey, proxyKey, code, hash) {
exchangeAPI.login = function(privKey, proxyKey, code, hash) {
return new Promise((resolve, reject) => {
if (!code || !hash)
return reject(ExchangeError(ExchangeError.BAD_REQUEST_CODE, "Login Code missing", errorCode.MISSING_PARAMETER));
@ -748,7 +748,7 @@
})
}
exchangeAPI.logout = function (floID, proxySecret) {
exchangeAPI.logout = function(floID, proxySecret) {
return new Promise((resolve, reject) => {
let request = {
floID: floID,
@ -775,7 +775,7 @@
})
}
exchangeAPI.buy = function (asset, quantity, max_price, floID, proxySecret) {
exchangeAPI.buy = function(asset, quantity, max_price, floID, proxySecret) {
return new Promise((resolve, reject) => {
if (typeof quantity !== "number" || quantity <= 0)
return reject(ExchangeError(ExchangeError.BAD_REQUEST_CODE, `Invalid quantity (${quantity})`, errorCode.INVALID_NUMBER));
@ -813,7 +813,7 @@
}
exchangeAPI.sell = function (asset, quantity, min_price, floID, proxySecret) {
exchangeAPI.sell = function(asset, quantity, min_price, floID, proxySecret) {
return new Promise((resolve, reject) => {
if (typeof quantity !== "number" || quantity <= 0)
return reject(ExchangeError(ExchangeError.BAD_REQUEST_CODE, `Invalid quantity (${quantity})`, errorCode.INVALID_NUMBER));
@ -851,7 +851,7 @@
}
exchangeAPI.cancelOrder = function (type, id, floID, proxySecret) {
exchangeAPI.cancelOrder = function(type, id, floID, proxySecret) {
return new Promise((resolve, reject) => {
if (type !== "buy" && type !== "sell")
return reject(ExchangeError(ExchangeError.BAD_REQUEST_CODE, `Invalid type (${type}): type should be sell (or) buy`, errorCode.INVALID_TYPE));
@ -885,7 +885,7 @@
}
//receiver should be object eg {floID1: amount1, floID2: amount2 ...}
exchangeAPI.transferToken = function (receiver, token, floID, proxySecret) {
exchangeAPI.transferToken = function(receiver, token, floID, proxySecret) {
return new Promise((resolve, reject) => {
if (typeof receiver !== 'object' || receiver === null)
return reject(ExchangeError(ExchangeError.BAD_REQUEST_CODE, "Invalid receiver: parameter is not an object", errorCode.INVALID_FLO_ID));
@ -930,7 +930,7 @@
})
}
exchangeAPI.depositFLO = function (quantity, floID, sinkID, privKey, proxySecret = null) {
exchangeAPI.depositFLO = function(quantity, floID, sinkID, privKey, proxySecret = null) {
return new Promise((resolve, reject) => {
if (typeof quantity !== "number" || quantity <= floGlobals.fee)
return reject(ExchangeError(ExchangeError.BAD_REQUEST_CODE, `Invalid quantity (${quantity})`, errorCode.INVALID_NUMBER));
@ -965,7 +965,7 @@
})
}
exchangeAPI.withdrawFLO = function (quantity, floID, proxySecret) {
exchangeAPI.withdrawFLO = function(quantity, floID, proxySecret) {
return new Promise((resolve, reject) => {
let request = {
floID: floID,
@ -994,7 +994,7 @@
})
}
exchangeAPI.depositToken = function (token, quantity, floID, sinkID, privKey, proxySecret = null) {
exchangeAPI.depositToken = function(token, quantity, floID, sinkID, privKey, proxySecret = null) {
return new Promise((resolve, reject) => {
if (!floCrypto.verifyPrivKey(privKey, floID))
return reject(ExchangeError(ExchangeError.BAD_REQUEST_CODE, "Invalid Private Key", errorCode.INVALID_PRIVATE_KEY));
@ -1027,7 +1027,7 @@
})
}
exchangeAPI.withdrawToken = function (token, quantity, floID, proxySecret) {
exchangeAPI.withdrawToken = function(token, quantity, floID, proxySecret) {
return new Promise((resolve, reject) => {
let request = {
floID: floID,
@ -1058,7 +1058,34 @@
})
}
exchangeAPI.addUserTag = function (tag_user, tag, floID, proxySecret) {
exchangeAPI.getUserTransacts = function(floID, proxySecret) {
return new Promise((resolve, reject) => {
let request = {
floID: floID,
timestamp: Date.now()
};
if (floCrypto.getFloID(proxySecret) === floID) //Direct signing (without proxy)
request.pubKey = floCrypto.getPubKeyHex(proxySecret);
request.sign = signRequest({
type: "get_transact",
timestamp: request.timestamp
}, proxySecret);
console.debug(request);
fetch_api('/get-transact', {
method: "POST",
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(request)
}).then(result => responseParse(result)
.then(result => resolve(result))
.catch(error => reject(error)))
.catch(error => reject(error))
})
}
exchangeAPI.addUserTag = function(tag_user, tag, floID, proxySecret) {
return new Promise((resolve, reject) => {
let request = {
floID: floID,
@ -1089,7 +1116,7 @@
})
}
exchangeAPI.removeUserTag = function (tag_user, tag, floID, proxySecret) {
exchangeAPI.removeUserTag = function(tag_user, tag, floID, proxySecret) {
return new Promise((resolve, reject) => {
let request = {
floID: floID,
@ -1120,7 +1147,7 @@
})
}
exchangeAPI.addDistributor = function (distributor, asset, floID, proxySecret) {
exchangeAPI.addDistributor = function(distributor, asset, floID, proxySecret) {
return new Promise((resolve, reject) => {
let request = {
floID: floID,
@ -1151,7 +1178,7 @@
})
}
exchangeAPI.removeDistributor = function (distributor, asset, floID, proxySecret) {
exchangeAPI.removeDistributor = function(distributor, asset, floID, proxySecret) {
return new Promise((resolve, reject) => {
let request = {
floID: floID,
@ -1242,7 +1269,7 @@
})
}
exchangeAPI.clearAllLocalData = function () {
exchangeAPI.clearAllLocalData = function() {
localStorage.removeItem('exchange-nodes');
localStorage.removeItem('exchange-assets');
localStorage.removeItem('exchange-tags');

View File

@ -1,4 +1,4 @@
(function(EXPORTS) { //floTokenAPI v1.0.3a
(function(EXPORTS) { //floTokenAPI v1.0.3b
/* Token Operator to send/receive tokens via blockchain using API calls*/
'use strict';
const tokenAPI = EXPORTS;
@ -20,6 +20,13 @@
if (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) {
return new Promise((resolve, reject) => {
console.log(DEFAULT.apiURL + apicall);

View File

@ -83,6 +83,7 @@ module.exports = function App(secret, DB) {
app.post('/withdraw-flo', Request.WithdrawFLO);
app.post('/deposit-token', Request.DepositToken);
app.post('/withdraw-token', Request.WithdrawToken);
app.post('/get-transact', Request.GetUserTransacts);
//Manage user tags (Access to trusted IDs only)
app.post('/add-tag', Request.AddUserTag);

View File

@ -254,6 +254,18 @@ function getAccountDetails(floID) {
});
}
function getUserTransacts(floID) {
return new Promise((resolve, reject) => {
DB.query("(SELECT 'deposit' as type, txid, floID, token, amount, status FROM InputToken WHERE floID=?)" +
"UNION (SELECT 'deposit' as type, txid, floID, 'FLO' as token, amount, status FROM InputFLO WHERE floID=?)" +
"UNION (SELECT 'withdraw' as type, txid, floID, token, amount, status FROM OutputToken WHERE floID=?)" +
"UNION (SELECT 'withdraw' as type, txid, floID, 'FLO' as token, amount, status FROM OutputFLO WHERE floID=?)",
[floID, floID, floID, floID])
.then(result => resolve(result))
.catch(error => reject(error))
})
}
function getTransactionDetails(txid) {
return new Promise((resolve, reject) => {
let tableName, type;
@ -712,6 +724,7 @@ function blockchainReCheck() {
retryWithdrawalToken();
confirmWithdrawalFLO();
confirmWithdrawalToken();
console.debug("Last Block :", lastSyncBlockHeight);
}
}).catch(error => console.error(error));
}
@ -731,6 +744,7 @@ module.exports = {
getRateHistory,
getBalance,
getAccountDetails,
getUserTransacts,
getTransactionDetails,
transferToken,
depositFLO,

View File

@ -265,6 +265,16 @@ function WithdrawToken(req, res) {
);
}
function GetUserTransacts(req, res) {
let data = req.body;
processRequest(res, "User Transacts", {
type: "get_transact",
timestamp: data.timestamp
}, data.sign, data.floID, data.pubKey,
() => market.getUserTransacts(data.floID)
);
}
function AddUserTag(req, res) {
let data = req.body;
if (!trustedIDs.includes(data.floID))
@ -509,6 +519,7 @@ module.exports = {
WithdrawFLO,
DepositToken,
WithdrawToken,
GetUserTransacts,
AddUserTag,
RemoveUserTag,
AddDistributor,