feat(txs): support for partial txs and full bill logging
This commit is contained in:
parent
bb4336b78f
commit
55abaa1bb9
3 changed files with 172 additions and 109 deletions
179
lib/plugins.js
179
lib/plugins.js
|
|
@ -173,29 +173,93 @@ exports.logEvent = function event(rawEvent, deviceFingerprint) {
|
|||
db.recordDeviceEvent(deviceFingerprint, rawEvent);
|
||||
};
|
||||
|
||||
|
||||
// Just prompts plugin to send BTC
|
||||
function _sendBitcoins(tx, callback) {
|
||||
logger.debug('executing tx: %j', tx);
|
||||
db.changeTxStatus(tx.txId, 'executing');
|
||||
walletPlugin.sendBitcoins(
|
||||
tx.toAddress,
|
||||
tx.satoshis,
|
||||
cachedConfig.exchanges.settings.transactionFee,
|
||||
|
||||
function(err, txHash) {
|
||||
if (err) {
|
||||
var status = err.name === 'InsufficientFunds' ?
|
||||
'insufficientFunds' :
|
||||
'failed';
|
||||
|
||||
// report insufficient funds error
|
||||
db.changeTxStatus(tx.txId, status, {error: err.message});
|
||||
return callback(err);
|
||||
}
|
||||
|
||||
if (txHash) db.changeTxStatus(tx.txId, 'completed', {hash: txHash});
|
||||
else db.changeTxStatus(tx.txId, 'failed', {error: 'No txHash received'});
|
||||
|
||||
pollBalance();
|
||||
callback(null, txHash);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
function executeTransaction(deviceFingerprint, txId, autoTriggered, cb) {
|
||||
cb = typeof cb === 'function' ? cb : function() {};
|
||||
|
||||
clearSession(deviceFingerprint);
|
||||
|
||||
// get remaining amount to be sent
|
||||
db.getPendingAmount(txId, function(err, tx) {
|
||||
if (err) {
|
||||
logger.error(err);
|
||||
return cb(err);
|
||||
}
|
||||
|
||||
if (!tx) {
|
||||
logger.info('Nothing to send (%s)', txId);
|
||||
return cb(null, {statusCode: 304}); // Not Modified
|
||||
}
|
||||
|
||||
db.summonTransaction(deviceFingerprint, tx, function(err, txInfo) {
|
||||
if (err) return cb(err);
|
||||
|
||||
// actual sending
|
||||
if (!txInfo) {
|
||||
return _sendBitcoins(tx, function(err, txHash) {
|
||||
cb(null, {
|
||||
statusCode: 201, // Created
|
||||
txHash: txHash
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
// Out of bitcoins: special case
|
||||
var txErr = null;
|
||||
if (txInfo.err) {
|
||||
txErr = new Error(txInfo.err);
|
||||
if (txInfo.status === 'insufficientFunds') {
|
||||
txErr.name = 'InsufficientFunds';
|
||||
}
|
||||
}
|
||||
|
||||
pollBalance();
|
||||
cb(txErr, txInfo.txHash);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
// This is where we record starting trade balance at the beginning
|
||||
// of the user session
|
||||
exports.trade = function trade(rawTrade, deviceFingerprint) {
|
||||
var sessionInfo = sessions[deviceFingerprint];
|
||||
|
||||
if (!sessionInfo) {
|
||||
exports.trade = function trade(rawTrade, deviceFingerprint, cb) {
|
||||
if (!sessions[deviceFingerprint]) {
|
||||
sessions[deviceFingerprint] = {
|
||||
timestamp: Date.now(),
|
||||
reaper: setTimeout(function() {
|
||||
// NOTE: at this point we either have bills ONLY *or a partial tx*
|
||||
// TODO: deal with #1 from ^
|
||||
db.getPendingTransactions(rawTrade.txId, function(err, txs) {
|
||||
// NOTE: returns ARRAY of txs
|
||||
_sendBitcoins(txs[0], function() { });
|
||||
delete sessions[deviceFingerprint];
|
||||
});
|
||||
executeTransaction(deviceFingerprint, rawTrade.txId, true);
|
||||
}, SESSION_TIMEOUT)
|
||||
};
|
||||
}
|
||||
|
||||
// record (vel log) inserted bill
|
||||
db.recordBill(deviceFingerprint, rawTrade);
|
||||
|
||||
// add bill to trader queue (if trader is enabled)
|
||||
if (traderPlugin) {
|
||||
tradesQueue.push({
|
||||
|
|
@ -203,8 +267,16 @@ exports.trade = function trade(rawTrade, deviceFingerprint) {
|
|||
satoshis: rawTrade.satoshis
|
||||
});
|
||||
}
|
||||
|
||||
// record (vel log) inserted bill
|
||||
db.recordBill(deviceFingerprint, rawTrade, cb);
|
||||
};
|
||||
|
||||
exports.sendBitcoins = function sendBitcoins(deviceFingerprint, rawTx, callback) {
|
||||
executeTransaction(deviceFingerprint, rawTx.txId, false, callback);
|
||||
};
|
||||
|
||||
|
||||
exports.fiatBalance = function fiatBalance() {
|
||||
var rawRate = exports.getDeviceRate().rates.ask;
|
||||
var commission = cachedConfig.exchanges.settings.commission;
|
||||
|
|
@ -233,84 +305,6 @@ exports.fiatBalance = function fiatBalance() {
|
|||
return fiatTransferBalance;
|
||||
};
|
||||
|
||||
function _sendBitcoins(tx, callback) {
|
||||
logger.debug('executing tx: %j', tx);
|
||||
walletPlugin.sendBitcoins(
|
||||
tx.toAddress,
|
||||
tx.satoshis,
|
||||
cachedConfig.exchanges.settings.transactionFee,
|
||||
|
||||
function(err, txHash) {
|
||||
if (err) {
|
||||
var status = err.name === 'InsufficientFunds' ?
|
||||
'insufficientFunds' :
|
||||
'failed';
|
||||
|
||||
// report insufficient funds error
|
||||
db.changeTxStatus(tx.txId, status, {error: err.message});
|
||||
return callback(err);
|
||||
}
|
||||
|
||||
if (txHash) db.changeTxStatus(tx.txId, 'completed', {hash: txHash});
|
||||
else db.changeTxStatus(tx.txId, 'failed', {error: 'No txHash received'});
|
||||
|
||||
pollBalance();
|
||||
callback(null, txHash);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
exports.sendBitcoins = function sendBitcoins(deviceFingerprint, tx, callback) {
|
||||
db.summonTransaction(deviceFingerprint, tx, function(err, txInfo) {
|
||||
if (err) return callback(err);
|
||||
|
||||
if (!txInfo || txInfo.status === 'partial') {
|
||||
// TODO: make sure session exists, to prevent sending coins twice
|
||||
clearSession(deviceFingerprint);
|
||||
return _sendBitcoins(tx, callback);
|
||||
}
|
||||
|
||||
// Out of bitcoins: special case
|
||||
var txErr = null;
|
||||
if (txInfo.err) {
|
||||
txErr = new Error(txInfo.err);
|
||||
if (txInfo.status === 'insufficientFunds') {
|
||||
txErr.name = 'InsufficientFunds';
|
||||
}
|
||||
}
|
||||
|
||||
// transaction exists, but txHash might be null,
|
||||
// in which case ATM should continue polling
|
||||
pollBalance();
|
||||
callback(txErr, txInfo.txHash);
|
||||
});
|
||||
};
|
||||
|
||||
// NOTE: temporarily here
|
||||
exports.sendBitcoinians = function(deviceFingerprint, tx, callback) {
|
||||
db.summonTransaction(deviceFingerprint, tx, function(err, txInfo) {
|
||||
if (err) return callback(err);
|
||||
|
||||
if (txInfo) {
|
||||
if (txInfo.status === 'insufficientFunds') {
|
||||
|
||||
}
|
||||
|
||||
if (txInfo.status === 'executing') {
|
||||
|
||||
}
|
||||
|
||||
// TODO: check `part` and what has already been sent
|
||||
}
|
||||
|
||||
// no error & no tx record exists
|
||||
// TODO: should it be confirmed with bills?
|
||||
|
||||
|
||||
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* Polling livecycle
|
||||
|
|
@ -472,6 +466,7 @@ function executeTrades() {
|
|||
});
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* ID Verifier functions
|
||||
*/
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue