From a77f7d77d6a9a54e627b6d21c4a7f367e11b14d4 Mon Sep 17 00:00:00 2001 From: sairajzero Date: Thu, 12 May 2022 01:40:31 +0530 Subject: [PATCH] Error codes - Added error codes for floExchangeAPI --- docs/scripts/floExchangeAPI.js | 97 +++++++++++++++++++++-------- src/_constants.js | 1 - src/market.js | 82 ++++++++++++------------ src/request.js | 110 ++++++++++++++++++--------------- 4 files changed, 175 insertions(+), 115 deletions(-) diff --git a/docs/scripts/floExchangeAPI.js b/docs/scripts/floExchangeAPI.js index 94d496c..e7e5a56 100644 --- a/docs/scripts/floExchangeAPI.js +++ b/docs/scripts/floExchangeAPI.js @@ -468,7 +468,7 @@ return new Promise((resolve, reject) => { let curPos = fetch_api.curPos || 0; if (curPos >= nodeList.length) - return reject(ExchangeError(ExchangeError.NODES_OFFLINE_CODE, 'No Node online! Try again later')); + return reject(ExchangeError(ExchangeError.NODES_OFFLINE_CODE, 'No Node online! Try again later', errorCode.NODES_OFFLINE)); let url = "https://" + nodeURL[nodeList[curPos]]; (options ? fetch(url + api, options) : fetch(url + api)) .then(result => resolve(result)).catch(error => { @@ -482,17 +482,62 @@ }) } - function ExchangeError(status, message) { - if (message === ExchangeError.INVALID_SERVER_MSG) - location.reload(); - else if (this instanceof ExchangeError) { - this.message = message; - this.status = status; - } else - return new ExchangeError(status, message); + const errorCode = exchangeAPI.errorCode = { + INCORRECT_SERVER: '000', + + //INVALID INPUTS: 0XX + INVALID_REQUEST_FORMAT: '001', + ACCESS_DENIED: '002', + INVALID_FLO_ID: '011', + INVALID_LOGIN_CODE: '012', + INVALID_PRIVATE_KEY: '013', + INVALID_PUBLIC_KEY: '014', + INVALID_SIGNATURE: '015', + EXPIRED_SIGNATURE: '016', + DUPLICATE_SIGNATURE: '017', + SESSION_INVALID: '018', + SESSION_EXPIRED: '019', + INVALID_TOKEN_NAME: '021', + INVALID_NUMBER: '022', + INVALID_TYPE: '023', + INVALID_TX_ID: '024', + INVALID_TAG: '025', + MISSING_PARAMETER: '099', + + //INCORRECT DATA: 1XX + NOT_FOUND: '101', + NOT_OWNER: '102', + DUPLICATE_ENTRY: '103', + + //INSUFFICIENT: 2XX + INSUFFICIENT_BALANCE: '201', + INSUFFICIENT_SELLCHIP: '203', + GREATER_SELLCHIP_BASE: '204', + + //OTHERS + NODES_OFFLINE: '404', + INTERNAL_ERROR: '500' + }; + + const parseErrorCode = exchangeAPI.parseErrorCode = function(message) { + let code = message.match(/^E\d{3}:/g); + if (!code || !code.length) + return null; + else + return code[0].substring(1, 4); + } + + function ExchangeError(status, message, code = null) { + if (parseErrorCode(message) === errorCode.INCORRECT_SERVER) + location.reload(); + else if (this instanceof ExchangeError) { + this.code = code || parseErrorCode(message); + this.message = message.replace(/^E\d{3}:/g, '').trim(); + this.status = status; + } else + return new ExchangeError(status, message, code); } - ExchangeError.INVALID_SERVER_MSG = "INCORRECT_SERVER_ERROR"; ExchangeError.BAD_REQUEST_CODE = 400; ExchangeError.BAD_RESPONSE_CODE = 500; ExchangeError.NODES_OFFLINE_CODE = 404; @@ -594,7 +639,7 @@ 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")); + return reject(ExchangeError(ExchangeError.BAD_REQUEST_CODE, "Need atleast one argument", errorCode.MISSING_PARAMETER)); let queryStr = (floID ? "floID=" + floID : "") + (floID && token ? "&" : "") + (token ? "token=" + token : ""); @@ -609,7 +654,7 @@ exchangeAPI.getTx = function(txid) { return new Promise((resolve, reject) => { if (!txid) - return reject(ExchangeError(ExchangeError.BAD_REQUEST_CODE, 'txid required')); + return reject(ExchangeError(ExchangeError.BAD_REQUEST_CODE, 'txid required', errorCode.MISSING_PARAMETER)); fetch_api('/get-transaction?txid=' + txid) .then(result => responseParse(result) .then(result => resolve(result)) @@ -639,7 +684,7 @@ exchangeAPI.signUp = function (privKey, code, hash) { return new Promise((resolve, reject) => { if (!code || !hash) - return reject(ExchangeError(ExchangeError.BAD_REQUEST_CODE, "Login Code missing")); + return reject(ExchangeError(ExchangeError.BAD_REQUEST_CODE, "Login Code missing", errorCode.MISSING_PARAMETER)); let request = { pubKey: floCrypto.getPubKeyHex(privKey), floID: floCrypto.getFloID(privKey), @@ -671,7 +716,7 @@ 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")); + return reject(ExchangeError(ExchangeError.BAD_REQUEST_CODE, "Login Code missing", errorCode.MISSING_PARAMETER)); let request = { proxyKey: proxyKey, floID: floCrypto.getFloID(privKey), @@ -681,7 +726,7 @@ hash: hash }; if (!privKey || !request.floID) - return reject(ExchangeError(ExchangeError.BAD_REQUEST_CODE, "Invalid Private key")); + return reject(ExchangeError(ExchangeError.BAD_REQUEST_CODE, "Invalid Private key", errorCode.INVALID_PRIVATE_KEY)); request.sign = signRequest({ type: "login", random: code, @@ -733,9 +778,9 @@ 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})`)); + return reject(ExchangeError(ExchangeError.BAD_REQUEST_CODE, `Invalid quantity (${quantity})`, errorCode.INVALID_NUMBER)); else if (typeof max_price !== "number" || max_price <= 0) - return reject(ExchangeError(ExchangeError.BAD_REQUEST_CODE, `Invalid max_price (${max_price})`)); + return reject(ExchangeError(ExchangeError.BAD_REQUEST_CODE, `Invalid max_price (${max_price})`, errorCode.INVALID_NUMBER)); let request = { floID: floID, asset: asset, @@ -771,9 +816,9 @@ 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})`)); + return reject(ExchangeError(ExchangeError.BAD_REQUEST_CODE, `Invalid quantity (${quantity})`, errorCode.INVALID_NUMBER)); else if (typeof min_price !== "number" || min_price <= 0) - return reject(ExchangeError(ExchangeError.BAD_REQUEST_CODE, `Invalid min_price (${min_price})`)); + return reject(ExchangeError(ExchangeError.BAD_REQUEST_CODE, `Invalid min_price (${min_price})`, errorCode.INVALID_NUMBER)); let request = { floID: floID, asset: asset, @@ -809,7 +854,7 @@ 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`)); + return reject(ExchangeError(ExchangeError.BAD_REQUEST_CODE, `Invalid type (${type}): type should be sell (or) buy`, errorCode.INVALID_TYPE)); let request = { floID: floID, orderType: type, @@ -843,7 +888,7 @@ 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")); + return reject(ExchangeError(ExchangeError.BAD_REQUEST_CODE, "Invalid receiver: parameter is not an object", errorCode.INVALID_FLO_ID)); let invalidIDs = [], invalidAmt = []; for (let f in receiver) { @@ -853,9 +898,9 @@ invalidAmt.push(receiver[f]) } if (invalidIDs.length) - return reject(ExchangeError(ExchangeError.BAD_REQUEST_CODE, `Invalid receiver (${invalidIDs})`)); + return reject(ExchangeError(ExchangeError.BAD_REQUEST_CODE, `Invalid receiver (${invalidIDs})`, errorCode.INVALID_FLO_ID)); else if (invalidAmt.length) - return reject(ExchangeError(ExchangeError.BAD_REQUEST_CODE, `Invalid amount (${invalidAmt})`)); + return reject(ExchangeError(ExchangeError.BAD_REQUEST_CODE, `Invalid amount (${invalidAmt})`, errorCode.INVALID_NUMBER)); let request = { floID: floID, token: token, @@ -888,7 +933,9 @@ 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})`)); + return reject(ExchangeError(ExchangeError.BAD_REQUEST_CODE, `Invalid quantity (${quantity})`, errorCode.INVALID_NUMBER)); + else if (!floCrypto.verifyPrivKey(privKey, floID)) + return reject(ExchangeError(ExchangeError.BAD_REQUEST_CODE, "Invalid Private Key", errorCode.INVALID_PRIVATE_KEY)); floBlockchainAPI.sendTx(floID, sinkID, quantity, privKey, '(deposit in market)').then(txid => { let request = { floID: floID, @@ -950,7 +997,7 @@ 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")); + return reject(ExchangeError(ExchangeError.BAD_REQUEST_CODE, "Invalid Private Key", errorCode.INVALID_PRIVATE_KEY)); floTokenAPI.sendToken(privKey, quantity, sinkID, '(deposit in market)', token).then(txid => { let request = { floID: floID, diff --git a/src/_constants.js b/src/_constants.js index 8e641ec..c15abd0 100644 --- a/src/_constants.js +++ b/src/_constants.js @@ -5,7 +5,6 @@ module.exports = { request: { SIGN_EXPIRE_TIME: 5 * 60 * 1000, //5 mins MAX_SESSION_TIMEOUT: 30 * 24 * 60 * 60 * 1000, //30 days - INVALID_SERVER_MSG: "INCORRECT_SERVER_ERROR" //Should be reflected in public backend script }, market: { PERIOD_INTERVAL: 5 * 60 * 1000, //5 min, diff --git a/src/market.js b/src/market.js index 3ea95a7..034df99 100644 --- a/src/market.js +++ b/src/market.js @@ -11,6 +11,8 @@ const { TRANSFER_HASH_PREFIX } = require('./_constants')["market"]; +const eCode = require('../docs/scripts/floExchangeAPI').errorCode; + const updateBalance = coupling.updateBalance; var DB, assetList; //container for database and allowed assets @@ -36,7 +38,7 @@ function logout(floID) { function getRateHistory(asset, duration) { return new Promise((resolve, reject) => { if (!asset || !assetList.includes(asset)) - reject(INVALID(`Invalid asset(${asset})`)); + reject(INVALID(eCode.INVALID_TOKEN_NAME, `Invalid asset(${asset})`)); else coupling.price.getHistory(asset, duration) .then(result => resolve(result)) @@ -47,11 +49,11 @@ function getRateHistory(asset, duration) { function getBalance(floID, token) { return new Promise((resolve, reject) => { if (floID && !floCrypto.validateAddr(floID)) - reject(INVALID(`Invalid floID(${floID})`)); + reject(INVALID(eCode.INVALID_FLO_ID, `Invalid floID(${floID})`)); else if (token && token !== floGlobals.currency && !assetList.includes(token)) - reject(INVALID(`Invalid token(${token})`)); + reject(INVALID(eCode.INVALID_TOKEN_NAME, `Invalid token(${token})`)); else if (!floID && !token) - reject(INVALID('Missing parameters: requires atleast one (floID, token)')); + reject(INVALID(eCode.MISSING_PARAMETER, 'Missing parameters: requires atleast one (floID, token)')); else { var promise; if (floID && token) @@ -114,9 +116,9 @@ const getAssetBalance = (floID, asset) => new Promise((resolve, reject) => { getAssetBalance.check = (floID, asset, amount) => new Promise((resolve, reject) => { getAssetBalance(floID, asset).then(balance => { if (balance.total < amount) - reject(INVALID(`Insufficient ${asset}`)); + reject(INVALID(eCode.INSUFFICIENT_BALANCE, `Insufficient ${asset}`)); else if (balance.net < amount) - reject(INVALID(`Insufficient ${asset} (Some are locked in orders)`)); + reject(INVALID(eCode.INSUFFICIENT_BALANCE, `Insufficient ${asset} (Some are locked in orders)`)); else resolve(true); }).catch(error => reject(error)) @@ -125,13 +127,13 @@ getAssetBalance.check = (floID, asset, amount) => new Promise((resolve, reject) function addSellOrder(floID, asset, quantity, min_price) { return new Promise((resolve, reject) => { if (!floCrypto.validateAddr(floID)) - return reject(INVALID(`Invalid floID (${floID})`)); + return reject(INVALID(eCode.INVALID_FLO_ID, `Invalid floID (${floID})`)); else if (typeof quantity !== "number" || quantity <= 0) - return reject(INVALID(`Invalid quantity (${quantity})`)); + return reject(INVALID(eCode.INVALID_NUMBER, `Invalid quantity (${quantity})`)); else if (typeof min_price !== "number" || min_price <= 0) - return reject(INVALID(`Invalid min_price (${min_price})`)); + return reject(INVALID(eCode.INVALID_NUMBER, `Invalid min_price (${min_price})`)); else if (!assetList.includes(asset)) - return reject(INVALID(`Invalid asset (${asset})`)); + return reject(INVALID(eCode.INVALID_TOKEN_NAME, `Invalid asset (${asset})`)); getAssetBalance.check(floID, asset, quantity).then(_ => { checkSellRequirement(floID, asset, quantity, min_price).then(_ => { DB.query("INSERT INTO SellOrder(floID, asset, quantity, minPrice) VALUES (?, ?, ?, ?)", [floID, asset, quantity, min_price]).then(result => { @@ -151,7 +153,7 @@ const checkSellRequirement = (floID, asset, quantity, min_price) => new Promise( let total = result[0][0].total_chips, locked = result[1][0].locked; if (total < locked + quantity) - reject(INVALID(`Insufficient sell-chips for ${asset}`)); + reject(INVALID(eCode.INSUFFICIENT_SELLCHIP, `Insufficient sell-chips for ${asset}`)); else Promise.all([ DB.query("SELECT IFNULL(SUM(quantity), 0) AS total_chips FROM SellChips WHERE floID=? AND asset=? AND base<=?", [floID, asset, min_price]), DB.query("SELECT IFNULL(SUM(quantity), 0) AS locked FROM SellOrder WHERE floID=? AND asset=? AND minPrice<=?", [floID, asset, min_price]) @@ -164,7 +166,7 @@ const checkSellRequirement = (floID, asset, quantity, min_price) => new Promise( if (l_locked > l_total) rem -= l_locked - l_total; if (rem < quantity) - reject(INVALID(`Cannot sell below purchased price`)); + reject(INVALID(eCode.GREATER_SELLCHIP_BASE, `Cannot sell below purchased price`)); else resolve(true); }).catch(error => reject(error)) @@ -174,13 +176,13 @@ const checkSellRequirement = (floID, asset, quantity, min_price) => new Promise( function addBuyOrder(floID, asset, quantity, max_price) { return new Promise((resolve, reject) => { if (!floCrypto.validateAddr(floID)) - return reject(INVALID(`Invalid floID (${floID})`)); + return reject(INVALID(eCode.INVALID_FLO_ID, `Invalid floID (${floID})`)); else if (typeof quantity !== "number" || quantity <= 0) - return reject(INVALID(`Invalid quantity (${quantity})`)); + return reject(INVALID(eCode.INVALID_NUMBER, `Invalid quantity (${quantity})`)); else if (typeof max_price !== "number" || max_price <= 0) - return reject(INVALID(`Invalid max_price (${max_price})`)); + return reject(INVALID(eCode.INVALID_NUMBER, `Invalid max_price (${max_price})`)); else if (!assetList.includes(asset)) - return reject(INVALID(`Invalid asset (${asset})`)); + return reject(INVALID(eCode.INVALID_TOKEN_NAME, `Invalid asset (${asset})`)); getAssetBalance.check(floID, floGlobals.currency, quantity * max_price).then(_ => { DB.query("INSERT INTO BuyOrder(floID, asset, quantity, maxPrice) VALUES (?, ?, ?, ?)", [floID, asset, quantity, max_price]).then(result => { resolve('Buy Order placed successfully'); @@ -193,19 +195,19 @@ function addBuyOrder(floID, asset, quantity, max_price) { function cancelOrder(type, id, floID) { return new Promise((resolve, reject) => { if (!floCrypto.validateAddr(floID)) - return reject(INVALID(`Invalid floID (${floID})`)); + return reject(INVALID(eCode.INVALID_FLO_ID, `Invalid floID (${floID})`)); let tableName; if (type === "buy") tableName = "BuyOrder"; else if (type === "sell") tableName = "SellOrder"; else - return reject(INVALID("Invalid Order type! Order type must be buy (or) sell")); + return reject(INVALID(eCode.INVALID_TYPE, "Invalid Order type! Order type must be buy (or) sell")); DB.query(`SELECT floID, asset FROM ${tableName} WHERE id=?`, [id]).then(result => { if (result.length < 1) - return reject(INVALID("Order not found!")); + return reject(INVALID(eCode.NOT_FOUND, "Order not found!")); else if (result[0].floID !== floID) - return reject(INVALID("Order doesnt belong to the current user")); + return reject(INVALID(eCode.NOT_OWNER, "Order doesnt belong to the current user")); let asset = result[0].asset; //Delete the order DB.query(`DELETE FROM ${tableName} WHERE id=?`, [id]).then(result => { @@ -262,7 +264,7 @@ function getTransactionDetails(txid) { tableName = 'TradeTransactions'; type = 'trade'; } else - return reject(INVALID("Invalid TransactionID")); + return reject(INVALID(eCode.INVALID_TX_ID, "Invalid TransactionID")); DB.query(`SELECT * FROM ${tableName} WHERE txid=?`, [txid]).then(result => { if (result.length) { let details = result[0]; @@ -271,7 +273,7 @@ function getTransactionDetails(txid) { details.receiver = JSON.parse(details.receiver); resolve(details); } else - reject(INVALID("Transaction not found")); + reject(INVALID(eCode.NOT_FOUND, "Transaction not found")); }).catch(error => reject(error)) }) } @@ -279,9 +281,9 @@ function getTransactionDetails(txid) { function transferToken(sender, receivers, token) { return new Promise((resolve, reject) => { if (!floCrypto.validateAddr(sender)) - reject(INVALID(`Invalid sender (${sender})`)); + reject(INVALID(eCode.INVALID_FLO_ID, `Invalid sender (${sender})`)); else if (token !== floGlobals.currency && !assetList.includes(token)) - reject(INVALID(`Invalid token (${token})`)); + reject(INVALID(eCode.INVALID_TOKEN_NAME, `Invalid token (${token})`)); else { let invalidIDs = [], totalAmount = 0; @@ -291,7 +293,7 @@ function transferToken(sender, receivers, token) { else totalAmount += receivers[floID]; if (invalidIDs.length) - reject(INVALID(`Invalid receiver (${invalidIDs})`)); + reject(INVALID(eCode.INVALID_FLO_ID, `Invalid receiver (${invalidIDs})`)); else getAssetBalance.check(sender, token, totalAmount).then(_ => { let txQueries = []; txQueries.push(updateBalance.consume(sender, token, totalAmount)); @@ -328,11 +330,11 @@ function depositFLO(floID, txid) { if (result.length) { switch (result[0].status) { case "PENDING": - return reject(INVALID("Transaction already in process")); + return reject(INVALID(eCode.DUPLICATE_ENTRY, "Transaction already in process")); case "REJECTED": - return reject(INVALID("Transaction already rejected")); + return reject(INVALID(eCode.DUPLICATE_ENTRY, "Transaction already rejected")); case "SUCCESS": - return reject(INVALID("Transaction already used to add coins")); + return reject(INVALID(eCode.DUPLICATE_ENTRY, "Transaction already used to add coins")); } } else DB.query("INSERT INTO InputFLO(txid, floID, status) VALUES (?, ?, ?)", [txid, floID, "PENDING"]) @@ -417,9 +419,9 @@ confirmDepositFLO.addSellChipsIfLaunchSeller = function(floID, quantity) { function withdrawFLO(floID, amount) { return new Promise((resolve, reject) => { if (!floCrypto.validateAddr(floID)) - return reject(INVALID(`Invalid floID (${floID})`)); + return reject(INVALID(eCode.INVALID_FLO_ID, `Invalid floID (${floID})`)); else if (typeof amount !== "number" || amount <= 0) - return reject(INVALID(`Invalid amount (${amount})`)); + return reject(INVALID(eCode.INVALID_NUMBER, `Invalid amount (${amount})`)); getAssetBalance.check(floID, "FLO", amount).then(_ => { let txQueries = []; txQueries.push(updateBalance.consume(floID, "FLO", amount)); @@ -477,11 +479,11 @@ function depositToken(floID, txid) { if (result.length) { switch (result[0].status) { case "PENDING": - return reject(INVALID("Transaction already in process")); + return reject(INVALID(eCode.DUPLICATE_ENTRY, "Transaction already in process")); case "REJECTED": - return reject(INVALID("Transaction already rejected")); + return reject(INVALID(eCode.DUPLICATE_ENTRY, "Transaction already rejected")); case "SUCCESS": - return reject(INVALID("Transaction already used to add tokens")); + return reject(INVALID(eCode.DUPLICATE_ENTRY, "Transaction already used to add tokens")); } } else DB.query("INSERT INTO InputToken(txid, floID, status) VALUES (?, ?, ?)", [txid, floID, "PENDING"]) @@ -550,11 +552,11 @@ confirmDepositToken.checkTx = function(sender, txid) { function withdrawToken(floID, token, amount) { return new Promise((resolve, reject) => { if (!floCrypto.validateAddr(floID)) - return reject(INVALID(`Invalid floID (${floID})`)); + return reject(INVALID(eCode.INVALID_FLO_ID, `Invalid floID (${floID})`)); else if (typeof amount !== "number" || amount <= 0) - return reject(INVALID(`Invalid amount (${amount})`)); + return reject(INVALID(eCode.INVALID_NUMBER, `Invalid amount (${amount})`)); else if ((!assetList.includes(token) && token !== floGlobals.currency) || token === "FLO") - return reject(INVALID("Invalid Token")); + return reject(INVALID(eCode.INVALID_TOKEN_NAME, "Invalid Token")); //Check for FLO balance (transaction fee) let required_flo = floGlobals.sendAmt + floGlobals.fee; getAssetBalance.check(floID, "FLO", required_flo).then(_ => { @@ -614,9 +616,9 @@ function addTag(floID, tag) { .then(result => resolve(`Added ${floID} to ${tag}`)) .catch(error => { if (error.code === "ER_DUP_ENTRY") - reject(INVALID(`${floID} already in ${tag}`)); + reject(INVALID(eCode.DUPLICATE_ENTRY, `${floID} already in ${tag}`)); else if (error.code === "ER_NO_REFERENCED_ROW") - reject(INVALID(`Invalid Tag`)); + reject(INVALID(eCode.INVALID_TAG, `Invalid Tag`)); else reject(error); }); @@ -645,9 +647,9 @@ function addDistributor(floID, asset) { .then(result => resolve(`Added ${asset} distributor: ${floID}`)) .catch(error => { if (error.code === "ER_DUP_ENTRY") - reject(INVALID(`${floID} is already ${asset} disributor`)); + reject(INVALID(eCode.DUPLICATE_ENTRY, `${floID} is already ${asset} disributor`)); else if (error.code === "ER_NO_REFERENCED_ROW") - reject(INVALID(`Invalid Asset`)); + reject(INVALID(eCode.INVALID_TOKEN_NAME, `Invalid Asset`)); else reject(error); }); diff --git a/src/request.js b/src/request.js index 753e0f5..f9c110e 100644 --- a/src/request.js +++ b/src/request.js @@ -4,18 +4,24 @@ const market = require("./market"); const { SIGN_EXPIRE_TIME, - MAX_SESSION_TIMEOUT, - INVALID_SERVER_MSG + MAX_SESSION_TIMEOUT } = require("./_constants")["request"]; +const eCode = require('../docs/scripts/floExchangeAPI').errorCode; + var DB, trustedIDs, secret; //container for database -global.INVALID = function(message) { +global.INVALID = function(ecode, message) { if (!(this instanceof INVALID)) - return new INVALID(message); + return new INVALID(ecode, message); this.message = message; + this.ecode = ecode; } INVALID.e_code = 400; +INVALID.prototype.toString = function() { + return "E" + this.ecode + ": " + this.message; +} +INVALID.str = (ecode, message) => INVALID(ecode, message).toString(); global.INTERNAL = function INTERNAL(message) { if (!(this instanceof INTERNAL)) @@ -23,31 +29,37 @@ global.INTERNAL = function INTERNAL(message) { this.message = message; } INTERNAL.e_code = 500; +INTERNAL.prototype.toString = function() { + return "E" + eCode.INTERNAL_ERROR + ": " + this.message; +} +INTERNAL.str = (ecode, message) => INTERNAL(ecode, message).toString(); + +const INCORRECT_SERVER_ERROR = INVALID(eCode.INCORRECT_SERVER, "Incorrect server"); var serving; function validateRequest(request, sign, floID, pubKey) { return new Promise((resolve, reject) => { if (!serving) - reject(INVALID(INVALID_SERVER_MSG)); + reject(INCORRECT_SERVER_ERROR); else if (!request.timestamp) - reject(INVALID("Timestamp parameter missing")); + reject(INVALID(eCode.MISSING_PARAMETER, "Timestamp parameter missing")); else if (Date.now() - SIGN_EXPIRE_TIME > request.timestamp) - reject(INVALID("Signature Expired")); + reject(INVALID(eCode.EXPIRED_SIGNATURE, "Signature Expired")); else if (!floCrypto.validateAddr(floID)) - reject(INVALID("Invalid floID")); + reject(INVALID(eCode.INVALID_FLO_ID, "Invalid floID")); else if (typeof request !== "object") - reject(INVALID("Request is not an object")); + reject(INVALID(eCode.INVALID_REQUEST_FORMAT, "Request is not an object")); else validateRequest.getSignKey(floID, pubKey).then(signKey => { let req_str = Object.keys(request).sort().map(r => r + ":" + request[r]).join("|"); try { if (!floCrypto.verifySign(req_str, sign, signKey)) - reject(INVALID("Invalid request signature! Re-login if this error occurs frequently")); + reject(INVALID(eCode.INVALID_SIGNATURE, "Invalid request signature")); else validateRequest.checkIfSignUsed(sign) .then(result => resolve(req_str)) .catch(error => reject(error)) } catch { - reject(INVALID("Corrupted sign/key")); + reject(INVALID(eCode.INVALID_SIGNATURE, "Corrupted sign/key")); } }).catch(error => reject(error)); }); @@ -57,22 +69,22 @@ validateRequest.getSignKey = (floID, pubKey) => new Promise((resolve, reject) => if (!pubKey) DB.query("SELECT session_time, proxyKey FROM UserSession WHERE floID=?", [floID]).then(result => { if (result.length < 1) - reject(INVALID("Session not active")); + reject(INVALID(eCode.SESSION_INVALID, "Session not active")); else if (result[0].session_time + MAX_SESSION_TIMEOUT < Date.now()) - reject(INVALID("Session Expired! Re-login required")); + reject(INVALID(eCode.SESSION_EXPIRED, "Session Expired! Re-login required")); else resolve(result[0].proxyKey); }).catch(error => reject(error)); else if (floCrypto.getFloID(pubKey) === floID) resolve(pubKey); else - reject(INVALID("Invalid pubKey")); + reject(INVALID(eCode.INVALID_PUBLIC_KEY, "Invalid pubKey")); }); validateRequest.checkIfSignUsed = sign => new Promise((resolve, reject) => { DB.query("SELECT id FROM RequestLog WHERE sign=?", [sign]).then(result => { if (result.length) - reject(INVALID("Duplicate signature")); + reject(INVALID(eCode.DUPLICATE_SIGNATURE, "Duplicate signature")); else resolve(true); }).catch(error => reject(error)) @@ -91,18 +103,18 @@ function processRequest(res, rText, validateObj, sign, floID, pubKey, marketFn) res.send(result); }).catch(error => { if (error instanceof INVALID) - res.status(INVALID.e_code).send(error.message); + res.status(INVALID.e_code).send(error.toString()); else { console.error(error); - res.status(INTERNAL.e_code).send(rText + " failed! Try again later!"); + res.status(INTERNAL.e_code).send(INTERNAL.str(rText + " failed! Try again later!")); } }) }).catch(error => { if (error instanceof INVALID) - res.status(INVALID.e_code).send(error.message); + res.status(INVALID.e_code).send(error.toString()); else { console.error(error); - res.status(INTERNAL.e_code).send("Request processing failed! Try again later!"); + res.status(INTERNAL.e_code).send(INTERNAL.str("Request processing failed! Try again later!")); } }) } @@ -123,10 +135,10 @@ function Account(req, res) { }); }).catch(error => { if (error instanceof INVALID) - res.status(INVALID.e_code).send(error.message); + res.status(INVALID.e_code).send(error.toString()); else { console.error(error); - res.status(INTERNAL.e_code).send("Request processing failed! Try again later!"); + res.status(INTERNAL.e_code).send(INTERNAL.str("Request processing failed! Try again later!")); } }); } @@ -134,9 +146,9 @@ function Account(req, res) { function Login(req, res) { let data = req.body; if (!data.code || data.hash != Crypto.SHA1(data.code + secret)) - res.status(INVALID.e_code).send("Invalid Code"); + res.status(INVALID.e_code).send(INVALID.str(eCode.INVALID_LOGIN_CODE, "Invalid Code")); else if (!data.pubKey) - res.status(INVALID.e_code).send("Public key missing"); + res.status(INVALID.e_code).send(INVALID.str(eCode.MISSING_PARAMETER, "Public key missing")); else processRequest(res, "Login", { type: "login", @@ -256,7 +268,7 @@ function WithdrawToken(req, res) { function AddUserTag(req, res) { let data = req.body; if (!trustedIDs.includes(data.floID)) - res.status(INVALID.e_code).send("Access Denied"); + res.status(INVALID.e_code).send(INVALID.str(eCode.ACCESS_DENIED, "Access Denied")); else processRequest(res, "Add user-tag", { type: "add_tag", user: data.user, @@ -270,7 +282,7 @@ function AddUserTag(req, res) { function RemoveUserTag(req, res) { let data = req.body; if (!trustedIDs.includes(data.floID)) - res.status(INVALID.e_code).send("Access Denied"); + res.status(INVALID.e_code).send(INVALID.str(eCode.ACCESS_DENIED, "Access Denied")); else processRequest(res, "Remove user-tag", { type: "remove_tag", user: data.user, @@ -284,7 +296,7 @@ function RemoveUserTag(req, res) { function AddDistributor(req, res) { let data = req.body; if (!trustedIDs.includes(data.floID)) - res.status(INVALID.e_code).send("Access Denied"); + res.status(INVALID.e_code).send(INVALID.str(eCode.ACCESS_DENIED, "Access Denied")); else processRequest(res, "Add distributor", { type: "add_distributor", distributor: data.distributor, @@ -298,7 +310,7 @@ function AddDistributor(req, res) { function RemoveDistributor(req, res) { let data = req.body; if (!trustedIDs.includes(data.floID)) - res.status(INVALID.e_code).send("Access Denied"); + res.status(INVALID.e_code).send(INVALID.str(eCode.ACCESS_DENIED, "Access Denied")); else processRequest(res, "Remove distributor", { type: "remove_distributor", distributor: data.distributor, @@ -313,7 +325,7 @@ function RemoveDistributor(req, res) { function GetLoginCode(req, res) { if (!serving) - res.status(INVALID.e_code).send(INVALID_SERVER_MSG); + res.status(INVALID.e_code).send(INCORRECT_SERVER_ERROR.toString()); else { let randID = floCrypto.randString(8, true) + Math.round(Date.now() / 1000); let hash = Crypto.SHA1(randID + secret); @@ -326,11 +338,11 @@ function GetLoginCode(req, res) { function ListSellOrders(req, res) { if (!serving) - res.status(INVALID.e_code).send(INVALID_SERVER_MSG); + res.status(INVALID.e_code).send(INCORRECT_SERVER_ERROR.toString()); else { let asset = req.query.asset; if (asset && !market.assetList.includes(asset)) - res.status(INVALID.e_code).send("Invalid asset parameter"); + res.status(INVALID.e_code).send(INVALID.str(eCode.INVALID_TOKEN_NAME, "Invalid asset parameter")); else DB.query("SELECT SellOrder.floID, SellOrder.asset, SellOrder.minPrice, SellOrder.quantity, SellOrder.time_placed FROM SellOrder" + " INNER JOIN UserBalance ON UserBalance.floID = SellOrder.floID AND UserBalance.token = SellOrder.asset" + @@ -345,7 +357,7 @@ function ListSellOrders(req, res) { .then(result => res.send(result)) .catch(error => { console.error(error); - res.status(INTERNAL.e_code).send("Try again later!") + res.status(INTERNAL.e_code).send(INTERNAL.str("Try again later!")); }); } @@ -353,11 +365,11 @@ function ListSellOrders(req, res) { function ListBuyOrders(req, res) { if (!serving) - res.status(INVALID.e_code).send(INVALID_SERVER_MSG); + res.status(INVALID.e_code).send(INCORRECT_SERVER_ERROR.toString()); else { let asset = req.query.asset; if (asset && !market.assetList.includes(asset)) - res.status(INVALID.e_code).send("Invalid asset parameter"); + res.status(INVALID.e_code).send(INVALID.str(eCode.INVALID_TOKEN_NAME, "Invalid asset parameter")); else DB.query("SELECT BuyOrder.floID, BuyOrder.asset, BuyOrder.maxPrice, BuyOrder.quantity, BuyOrder.time_placed FROM BuyOrder" + " INNER JOIN UserBalance ON UserBalance.floID = BuyOrder.floID AND UserBalance.token = ?" + @@ -371,18 +383,18 @@ function ListBuyOrders(req, res) { .then(result => res.send(result)) .catch(error => { console.error(error); - res.status(INTERNAL.e_code).send("Try again later!") + res.status(INTERNAL.e_code).send(INTERNAL.str("Try again later!")); }); } } function ListTradeTransactions(req, res) { if (!serving) - res.status(INVALID.e_code).send(INVALID_SERVER_MSG); + res.status(INVALID.e_code).send(INCORRECT_SERVER_ERROR.toString()); else { let asset = req.query.asset; if (asset && !market.assetList.includes(asset)) - res.status(INVALID.e_code).send("Invalid asset parameter"); + res.status(INVALID.e_code).send(INVALID.str(eCode.INVALID_TOKEN_NAME, "Invalid asset parameter")); else DB.query("SELECT * FROM TradeTransactions" + (asset ? " WHERE asset = ?" : "") + @@ -390,14 +402,14 @@ function ListTradeTransactions(req, res) { .then(result => res.send(result)) .catch(error => { console.error(error); - res.status(INTERNAL.e_code).send("Try again later!") + res.status(INTERNAL.e_code).send(INTERNAL.str("Try again later!")); }); } } function GetRates(req, res) { if (!serving) - res.status(INVALID.e_code).send(INVALID_SERVER_MSG); + res.status(INVALID.e_code).send(INCORRECT_SERVER_ERROR.toString()); else { let asset = req.query.asset, rates = market.rates, @@ -410,7 +422,7 @@ function GetRates(req, res) { countDown: countDown[asset] }); else - res.status(INVALID.e_code).send("Invalid asset parameter"); + res.status(INVALID.e_code).send(INVALID.str(eCode.INVALID_TOKEN_NAME, "Invalid asset parameter")); } else res.send({ rates, @@ -421,7 +433,7 @@ function GetRates(req, res) { function GetRateHistory(req, res) { if (!serving) - res.status(INVALID.e_code).send(INVALID_SERVER_MSG); + res.status(INVALID.e_code).send(INCORRECT_SERVER_ERROR.toString()); else { let asset = req.query.asset, duration = req.query.duration || ""; @@ -429,10 +441,10 @@ function GetRateHistory(req, res) { .then(result => res.send(result)) .catch(error => { if (error instanceof INVALID) - res.status(INVALID.e_code).send(error.message); + res.status(INVALID.e_code).send(error.toString()); else { console.error(error); - res.status(INTERNAL.e_code).send("Unable to process! Try again later!"); + res.status(INTERNAL.e_code).send(INTERNAL.str("Unable to process! Try again later!")); } }); } @@ -440,19 +452,19 @@ function GetRateHistory(req, res) { function GetTransaction(req, res) { if (!serving) - res.status(INVALID.e_code).send(INVALID_SERVER_MSG); + res.status(INVALID.e_code).send(INCORRECT_SERVER_ERROR.toString()); else { let txid = req.query.txid; if (!txid) - res.status(INVALID.e_code).send("txid (transactionID) parameter missing"); + res.status(INVALID.e_code).send(INVALID.str(eCode.MISSING_PARAMETER, "txid (transactionID) parameter missing")); else market.getTransactionDetails(txid) .then(result => res.send(result)) .catch(error => { if (error instanceof INVALID) - res.status(INVALID.e_code).send(error.message); + res.status(INVALID.e_code).send(error.toString()); else { console.error(error); - res.status(INTERNAL.e_code).send("Unable to process! Try again later!"); + res.status(INTERNAL.e_code).send(INTERNAL.str("Unable to process! Try again later!")); } }); } @@ -460,7 +472,7 @@ function GetTransaction(req, res) { function GetBalance(req, res) { if (!serving) - res.status(INVALID.e_code).send(INVALID_SERVER_MSG); + res.status(INVALID.e_code).send(INCORRECT_SERVER_ERROR.toString()); else { let floID = req.query.floID || req.query.addr, token = req.query.token || req.query.asset; @@ -468,10 +480,10 @@ function GetBalance(req, res) { .then(result => res.send(result)) .catch(error => { if (error instanceof INVALID) - res.status(INVALID.e_code).send(error.message); + res.status(INVALID.e_code).send(error.toString()); else { console.error(error); - res.status(INTERNAL.e_code).send("Unable to process! Try again later!"); + res.status(INTERNAL.e_code).send(INTERNAL.str("Unable to process! Try again later!")); } }); }