Transfer transactions now support one-to-many

- receiver parameter now requires an object in the format
{floID1: amount1, floID2: amount2 ...}
- Transaction hash (id) for both trade and transfer transactions are now generated using SHA of JSON-string object
- Updated schema for one-to-many TransferTransactions
This commit is contained in:
sairajzero 2022-03-16 00:33:22 +05:30
parent f59c6b3f2a
commit 1823a46a98
5 changed files with 68 additions and 36 deletions

View File

@ -157,9 +157,9 @@ CREATE TABLE PriceHistory (
CREATE TABLE TransferTransactions (
id INT NOT NULL AUTO_INCREMENT,
sender CHAR(34) NOT NULL,
receiver CHAR(34) NOT NULL,
receiver TEXT NOT NULL,
token VARCHAR(64) NOT NULL,
amount FLOAT NOT NULL,
totalAmount FLOAT NOT NULL,
tx_time DATETIME DEFAULT CURRENT_TIMESTAMP,
txid VARCHAR(66) NOT NULL,
KEY(id),

View File

@ -396,26 +396,35 @@ function cancelOrder(type, id, floID, proxySecret) {
})
}
function transferToken(receiver, token, amount, floID, proxySecret) {
//receiver should be object eg {floID1: amount1, floID2: amount2 ...}
function transferToken(receiver, token, floID, proxySecret) {
return new Promise((resolve, reject) => {
if (!floCrypto.validateAddr(receiver))
return reject(INVALID(`Invalid receiver (${receiver})`));
else if (typeof amount !== "number" || amount <= 0)
return reject(`Invalid amount (${amount})`);
if (typeof receiver !== Object || receiver === null)
return reject("Invalid receiver: parameter is not an object");
let invalidIDs = [],
invalidAmt = [];
for (let f in receiver) {
if (!floCrypto.validateAddr(f))
invalidIDs.push(f);
else if (typeof receiver[f] !== "number" || receiver[f] <= 0)
invalidAmt.push(receiver[f])
}
if (invalidIDs.length)
return reject(INVALID(`Invalid receiver (${invalidIDs})`));
else if (invalidAmt.length)
return reject(`Invalid amount (${invalidAmt})`);
let request = {
floID: floID,
token: token,
receiver: receiver,
amount: amount,
timestamp: Date.now()
};
if (floCrypto.getFloID(proxySecret) === floID) //Direct signing (without proxy)
request.pubKey = floCrypto.getPubKeyHex(proxySecret);
request.sign = signRequest({
type: "transfer_token",
receiver: receiver,
receiver: JSON.stringify(receiver),
token: token,
amount: amount,
timestamp: request.timestamp
}, proxySecret);
console.debug(request);

View File

@ -118,7 +118,14 @@ function updateBalance(seller_best, buyer_best, txQueries, asset, cur_price, qua
txQueries.push(["INSERT INTO Vault(floID, asset, base, quantity) VALUES (?, ?, ?, ?)", [buyer_best.floID, asset, cur_price, quantity]])
//Record transaction
let time = Date.now();
let hash = TRADE_HASH_PREFIX + Crypto.SHA256([time, seller_best.floID, buyer_best.floID, asset, quantity, cur_price].join("|"));
let hash = TRADE_HASH_PREFIX + Crypto.SHA256(JSON.stringify({
seller: seller_best.floID,
buyer: buyer_best.floID,
asset: asset,
quantity: quantity,
unitValue: cur_price,
tx_time: time,
}));
txQueries.push([
"INSERT INTO TradeTransactions (seller, buyer, asset, quantity, unitValue, tx_time, txid) VALUES (?, ?, ?, ?, ?, ?, ?)",
[seller_best.floID, buyer_best.floID, asset, quantity, cur_price, global.convertDateToString(time), hash]

View File

@ -190,39 +190,56 @@ function getTransactionDetails(txid) {
if (result.length) {
let details = result[0];
details.type = type;
if (tableName === 'TransferTransactions') //As json object is stored for receiver in transfer (to support one-to-many)
details.receiver = JSON.parse(details.receiver);
resolve(details);
} else
reject(INVALID("Transaction not found"));
}).catch(error => reject(error))
}
function transferToken(sender, receiver, token, amount) {
function transferToken(sender, receivers, token) {
return new Promise((resolve, reject) => {
if (floCrypto.validateAddr(sender))
return reject(INVALID(`Invalid sender (${sender})`));
else if (floCrypto.validateAddr(receiver))
return reject(INVALID(`Invalid receiver (${receiver})`));
else if (typeof amount !== "number" || amount <= 0)
return reject(INVALID(`Invalid amount (${amount})`));
reject(INVALID(`Invalid sender (${sender})`));
else if (token !== floGlobals.currency && !assetList.includes(token))
return reject(INVALID(`Invalid token (${token})`));
getAssetBalance.check(senderID, token, amount).then(_ => {
consumeAsset(sender, token, amount).then(txQueries => {
if (token === floGlobals.currency)
txQueries.push(["INSERT INTO Cash (floID, balance) VALUE (?, ?) ON DUPLICATE KEY UPDATE balance=balance+?", [receiver, amount, amount]]);
reject(INVALID(`Invalid token (${token})`));
else {
let invalidIDs = [],
totalAmount = 0;
for (let floID in receivers)
if (!floCrypto.validateAddr(floID))
invalidIDs.push(floID);
else
txQueries.push(["INSERT INTO Vault(floID, quantity) VALUES (?, ?)", [receiver, amount]]);
let time = Date.now();
let hash = TRANSFER_HASH_PREFIX + Crypto.SHA256([time, sender, receiver, token, amount].join("|"));
txQueries.push([
"INSERT INTO TransferTransactions (sender, receiver, token, amount, tx_time, txid)",
[sender, receiver, token, amount, global.convertDateToString(time), hash]
]);
DB.transaction(txQueries)
.then(result => resolve(hash))
.catch(error => reject(error))
totalAmount += receivers[floID];
if (invalidIDs.length)
reject(INVALID(`Invalid receiver (${invalidIDs})`));
else getAssetBalance.check(senderID, token, totalAmount).then(_ => {
consumeAsset(sender, token, totalAmount).then(txQueries => {
if (token === floGlobals.currency)
for (let floID in receivers)
txQueries.push(["INSERT INTO Cash (floID, balance) VALUE (?, ?) ON DUPLICATE KEY UPDATE balance=balance+?", [floID, receivers[floID], receivers[floID]]]);
else
for (let floID in receivers)
txQueries.push(["INSERT INTO Vault(floID, quantity) VALUES (?, ?)", [floID, receivers[floID]]]);
let time = Date.now();
let hash = TRANSFER_HASH_PREFIX + Crypto.SHA256(JSON.stringify({
sender: sender,
receiver: receivers,
token: token,
totalAmount: totalAmount,
tx_time: time,
}));
txQueries.push([
"INSERT INTO TransferTransactions (sender, receiver, token, totalAmount, tx_time, txid)",
[sender, JSON.stringify(receiver), token, totalAmount, global.convertDateToString(time), hash]
]);
DB.transaction(txQueries)
.then(result => resolve(hash))
.catch(error => reject(error))
}).catch(error => reject(error))
}).catch(error => reject(error))
}).catch(error => reject(error))
}
})
}

View File

@ -275,12 +275,11 @@ function TransferToken(req, res) {
let data = req.body;
validateRequest({
type: "transfer_token",
receiver: data.receiver,
receiver: JSON.stringify(data.receiver),
token: data.token,
amount: data.amount,
timestamp: data.timestamp
}, data.sign, data.floID, data.pubKey).then(req_str => {
market.transferToken(data.floID, data.receiver, data.token, data.amount).then(result => {
market.transferToken(data.floID, data.receiver, data.token).then(result => {
storeRequest(data.floID, req_str, data.sign, !data.pubKey);
res.send(result);
}).catch(error => {