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:
parent
f59c6b3f2a
commit
1823a46a98
@ -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),
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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]
|
||||
|
||||
@ -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]]);
|
||||
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([time, sender, receiver, token, amount].join("|"));
|
||||
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, amount, tx_time, txid)",
|
||||
[sender, receiver, token, amount, global.convertDateToString(time), hash]
|
||||
"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))
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
@ -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 => {
|
||||
|
||||
Loading…
Reference in New Issue
Block a user