|
|
@ -60,119 +60,94 @@ module.exports = (shepherd) => { |
|
|
|
|
|
|
|
shepherd.log(json.length, true); |
|
|
|
let index = 0; |
|
|
|
|
|
|
|
const _getTransaction = (txid) => { |
|
|
|
return new shepherd.Promise((resolve, reject) => { |
|
|
|
if (!_inputTxs[txid]) { |
|
|
|
ecl.blockchainTransactionGet(txid) |
|
|
|
.then((_rawtxJSON) => { |
|
|
|
resolve(_rawtxJSON); |
|
|
|
}); |
|
|
|
} else { |
|
|
|
resolve(_inputTxs[txid]); |
|
|
|
} |
|
|
|
}); |
|
|
|
} ; |
|
|
|
|
|
|
|
async.eachOfSeries(json, (transaction, ind, callback) => { |
|
|
|
console.log(`index ${index}`); |
|
|
|
//return new shepherd.Promise((resolve, reject) => {
|
|
|
|
ecl.blockchainBlockGetHeader(transaction.height) |
|
|
|
.then((blockInfo) => { |
|
|
|
if (blockInfo && |
|
|
|
blockInfo.timestamp) { |
|
|
|
ecl.blockchainTransactionGet(transaction['tx_hash']) |
|
|
|
.then((_rawtxJSON) => { |
|
|
|
shepherd.log('electrum gettransaction ==>', true); |
|
|
|
shepherd.log((index + ' | ' + (_rawtxJSON.length - 1)), true); |
|
|
|
shepherd.log(_rawtxJSON, true); |
|
|
|
|
|
|
|
// decode tx
|
|
|
|
const _network = shepherd.getNetworkData(network); |
|
|
|
const decodedTx = shepherd.electrumJSTxDecoder(_rawtxJSON, network, _network); |
|
|
|
|
|
|
|
let txInputs = []; |
|
|
|
shepherd.log(`decodedtx network ${network}`, true); |
|
|
|
|
|
|
|
shepherd.log('decodedtx =>', true); |
|
|
|
shepherd.log(decodedTx.outputs, true); |
|
|
|
|
|
|
|
let index2 = 0; |
|
|
|
if (decodedTx && |
|
|
|
decodedTx.inputs) { |
|
|
|
async.eachOfSeries(decodedTx.inputs, (_decodedInput, index2, callback2) => { |
|
|
|
//shepherd.Promise.all(decodedTx.inputs.map((_decodedInput, index) => {
|
|
|
|
//return new shepherd.Promise((_resolve, _reject) => {
|
|
|
|
if (_decodedInput.txid !== '0000000000000000000000000000000000000000000000000000000000000000') { |
|
|
|
if (!_inputTxs[_decodedInput.txid]) { |
|
|
|
ecl.blockchainTransactionGet(_decodedInput.txid) |
|
|
|
.then((rawInput) => { |
|
|
|
_inputTxs[_decodedInput.txid] = rawInput; |
|
|
|
|
|
|
|
const decodedVinVout = shepherd.electrumJSTxDecoder(rawInput, network, _network); |
|
|
|
|
|
|
|
shepherd.log(`electrum raw input tx ${_decodedInput.txid} ==>`, true); |
|
|
|
|
|
|
|
if (decodedVinVout) { |
|
|
|
shepherd.log(decodedVinVout.outputs[_decodedInput.n], true); |
|
|
|
txInputs.push(decodedVinVout.outputs[_decodedInput.n]); |
|
|
|
index2++; |
|
|
|
callback2(); |
|
|
|
} else { |
|
|
|
index2++; |
|
|
|
callback2(); |
|
|
|
} |
|
|
|
}); |
|
|
|
} else { |
|
|
|
const decodedVinVout = shepherd.electrumJSTxDecoder(_inputTxs[_decodedInput.txid], network, _network); |
|
|
|
|
|
|
|
shepherd.log(`electrum raw one time cached input tx ${_decodedInput.txid} ==>`, true); |
|
|
|
|
|
|
|
if (decodedVinVout) { |
|
|
|
shepherd.log(decodedVinVout.outputs[_decodedInput.n], true); |
|
|
|
txInputs.push(decodedVinVout.outputs[_decodedInput.n]); |
|
|
|
index2++; |
|
|
|
callback2(); |
|
|
|
} else { |
|
|
|
index2++; |
|
|
|
callback2(); |
|
|
|
} |
|
|
|
} |
|
|
|
} else { |
|
|
|
index2++; |
|
|
|
callback2(); |
|
|
|
} |
|
|
|
ecl.blockchainBlockGetHeader(transaction.height) |
|
|
|
.then((blockInfo) => { |
|
|
|
if (blockInfo && |
|
|
|
blockInfo.timestamp) { |
|
|
|
_getTransaction(transaction['tx_hash']) |
|
|
|
.then((_rawtxJSON) => { |
|
|
|
if (!_inputTxs[transaction['tx_hash']]) { |
|
|
|
_inputTxs[transaction['tx_hash']] = _rawtxJSON; |
|
|
|
} |
|
|
|
shepherd.log('electrum gettransaction ==>', true); |
|
|
|
shepherd.log((index + ' | ' + (_rawtxJSON.length - 1)), true); |
|
|
|
// shepherd.log(_rawtxJSON, true);
|
|
|
|
|
|
|
|
// decode tx
|
|
|
|
const _network = shepherd.getNetworkData(network); |
|
|
|
const decodedTx = shepherd.electrumJSTxDecoder(_rawtxJSON, network, _network); |
|
|
|
|
|
|
|
let txInputs = []; |
|
|
|
shepherd.log(`decodedtx network ${network}`, true); |
|
|
|
|
|
|
|
shepherd.log('decodedtx =>', true); |
|
|
|
// shepherd.log(decodedTx.outputs, true);
|
|
|
|
|
|
|
|
let index2 = 0; |
|
|
|
if (decodedTx && |
|
|
|
decodedTx.inputs && |
|
|
|
decodedTx.inputs.length) { |
|
|
|
async.eachOfSeries(decodedTx.inputs, (_decodedInput, ind2, callback2) => { |
|
|
|
function checkLoop() { |
|
|
|
index2++; |
|
|
|
|
|
|
|
console.log(`${index2} | ${decodedTx.inputs.length - 1} => main callback`); |
|
|
|
if (index2 === decodedTx.inputs.length - 1) { |
|
|
|
index++; |
|
|
|
const _parsedTx = { |
|
|
|
network: decodedTx.network, |
|
|
|
format: decodedTx.format, |
|
|
|
inputs: txInputs, |
|
|
|
outputs: decodedTx.outputs, |
|
|
|
height: transaction.height, |
|
|
|
timestamp: Number(transaction.height) === 0 ? Math.floor(Date.now() / 1000) : blockInfo.timestamp, |
|
|
|
confirmations: Number(transaction.height) === 0 ? 0 : currentHeight - transaction.height, |
|
|
|
}; |
|
|
|
|
|
|
|
const formattedTx = shepherd.parseTransactionAddresses(_parsedTx, req.query.address, network); |
|
|
|
|
|
|
|
if (formattedTx.type) { |
|
|
|
formattedTx.height = transaction.height; |
|
|
|
formattedTx.blocktime = blockInfo.timestamp; |
|
|
|
formattedTx.timereceived = blockInfo.timereceived; |
|
|
|
formattedTx.hex = _rawtxJSON; |
|
|
|
formattedTx.inputs = decodedTx.inputs; |
|
|
|
formattedTx.outputs = decodedTx.outputs; |
|
|
|
formattedTx.locktime = decodedTx.format.locktime; |
|
|
|
_rawtx.push(formattedTx); |
|
|
|
} else { |
|
|
|
formattedTx[0].height = transaction.height; |
|
|
|
formattedTx[0].blocktime = blockInfo.timestamp; |
|
|
|
formattedTx[0].timereceived = blockInfo.timereceived; |
|
|
|
formattedTx[0].hex = _rawtxJSON; |
|
|
|
formattedTx[0].inputs = decodedTx.inputs; |
|
|
|
formattedTx[0].outputs = decodedTx.outputs; |
|
|
|
formattedTx[0].locktime = decodedTx.format.locktime; |
|
|
|
formattedTx[1].height = transaction.height; |
|
|
|
formattedTx[1].blocktime = blockInfo.timestamp; |
|
|
|
formattedTx[1].timereceived = blockInfo.timereceived; |
|
|
|
formattedTx[1].hex = _rawtxJSON; |
|
|
|
formattedTx[1].inputs = decodedTx.inputs; |
|
|
|
formattedTx[1].outputs = decodedTx.outputs; |
|
|
|
formattedTx[1].locktime = decodedTx.format.locktime; |
|
|
|
_rawtx.push(formattedTx[0]); |
|
|
|
_rawtx.push(formattedTx[1]); |
|
|
|
} |
|
|
|
callback(); |
|
|
|
if (index2 === decodedTx.inputs.length) { |
|
|
|
shepherd.log(`tx history decode inputs ${decodedTx.inputs.length} | ${index2} => main callback`, true); |
|
|
|
const _parsedTx = { |
|
|
|
network: decodedTx.network, |
|
|
|
format: decodedTx.format, |
|
|
|
inputs: txInputs, |
|
|
|
outputs: decodedTx.outputs, |
|
|
|
height: transaction.height, |
|
|
|
timestamp: Number(transaction.height) === 0 ? Math.floor(Date.now() / 1000) : blockInfo.timestamp, |
|
|
|
confirmations: Number(transaction.height) === 0 ? 0 : currentHeight - transaction.height, |
|
|
|
}; |
|
|
|
|
|
|
|
const formattedTx = shepherd.parseTransactionAddresses(_parsedTx, req.query.address, network); |
|
|
|
|
|
|
|
if (formattedTx.type) { |
|
|
|
formattedTx.height = transaction.height; |
|
|
|
formattedTx.blocktime = blockInfo.timestamp; |
|
|
|
formattedTx.timereceived = blockInfo.timereceived; |
|
|
|
formattedTx.hex = _rawtxJSON; |
|
|
|
formattedTx.inputs = decodedTx.inputs; |
|
|
|
formattedTx.outputs = decodedTx.outputs; |
|
|
|
formattedTx.locktime = decodedTx.format.locktime; |
|
|
|
_rawtx.push(formattedTx); |
|
|
|
} else { |
|
|
|
formattedTx[0].height = transaction.height; |
|
|
|
formattedTx[0].blocktime = blockInfo.timestamp; |
|
|
|
formattedTx[0].timereceived = blockInfo.timereceived; |
|
|
|
formattedTx[0].hex = _rawtxJSON; |
|
|
|
formattedTx[0].inputs = decodedTx.inputs; |
|
|
|
formattedTx[0].outputs = decodedTx.outputs; |
|
|
|
formattedTx[0].locktime = decodedTx.format.locktime; |
|
|
|
formattedTx[1].height = transaction.height; |
|
|
|
formattedTx[1].blocktime = blockInfo.timestamp; |
|
|
|
formattedTx[1].timereceived = blockInfo.timereceived; |
|
|
|
formattedTx[1].hex = _rawtxJSON; |
|
|
|
formattedTx[1].inputs = decodedTx.inputs; |
|
|
|
formattedTx[1].outputs = decodedTx.outputs; |
|
|
|
formattedTx[1].locktime = decodedTx.format.locktime; |
|
|
|
_rawtx.push(formattedTx[0]); |
|
|
|
_rawtx.push(formattedTx[1]); |
|
|
|
} |
|
|
|
index++; |
|
|
|
|
|
|
|
if (index === json.length) { |
|
|
|
ecl.close(); |
|
|
@ -181,82 +156,105 @@ module.exports = (shepherd) => { |
|
|
|
msg: 'success', |
|
|
|
result: _rawtx, |
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
res.end(JSON.stringify(successObj)); |
|
|
|
} |
|
|
|
//});
|
|
|
|
}); |
|
|
|
/*.then(promiseResult => { |
|
|
|
|
|
|
|
resolve(true); |
|
|
|
});*/ |
|
|
|
} else { |
|
|
|
const _parsedTx = { |
|
|
|
network: decodedTx.network, |
|
|
|
format: 'cant parse', |
|
|
|
inputs: 'cant parse', |
|
|
|
outputs: 'cant parse', |
|
|
|
height: transaction.height, |
|
|
|
timestamp: Number(transaction.height) === 0 ? Math.floor(Date.now() / 1000) : blockInfo.timestamp, |
|
|
|
confirmations: Number(transaction.height) === 0 ? 0 : currentHeight - transaction.height, |
|
|
|
}; |
|
|
|
callback(); |
|
|
|
shepherd.log(`tx history main loop ${json.length} | ${index}`, true); |
|
|
|
} |
|
|
|
callback2(); |
|
|
|
} |
|
|
|
|
|
|
|
const formattedTx = shepherd.parseTransactionAddresses(_parsedTx, req.query.address, network); |
|
|
|
_rawtx.push(formattedTx); |
|
|
|
index++; |
|
|
|
callback(); |
|
|
|
if (_decodedInput.txid !== '0000000000000000000000000000000000000000000000000000000000000000') { |
|
|
|
if (!_inputTxs[_decodedInput.txid]) { |
|
|
|
ecl.blockchainTransactionGet(_decodedInput.txid) |
|
|
|
.then((rawInput) => { |
|
|
|
_inputTxs[_decodedInput.txid] = rawInput; |
|
|
|
|
|
|
|
if (index === json.length) { |
|
|
|
ecl.close(); |
|
|
|
|
|
|
|
const successObj = { |
|
|
|
msg: 'success', |
|
|
|
result: _rawtx, |
|
|
|
}; |
|
|
|
|
|
|
|
res.end(JSON.stringify(successObj)); |
|
|
|
const decodedVinVout = shepherd.electrumJSTxDecoder(rawInput, network, _network); |
|
|
|
|
|
|
|
shepherd.log(`electrum raw input tx ${_decodedInput.txid} ==>`, true); |
|
|
|
|
|
|
|
if (decodedVinVout) { |
|
|
|
shepherd.log(decodedVinVout.outputs[_decodedInput.n], true); |
|
|
|
txInputs.push(decodedVinVout.outputs[_decodedInput.n]); |
|
|
|
} |
|
|
|
checkLoop(); |
|
|
|
}); |
|
|
|
} else { |
|
|
|
const decodedVinVout = shepherd.electrumJSTxDecoder(_inputTxs[_decodedInput.txid], network, _network); |
|
|
|
|
|
|
|
shepherd.log(`electrum raw one time cached input tx ${_decodedInput.txid} ==>`, true); |
|
|
|
|
|
|
|
if (decodedVinVout) { |
|
|
|
shepherd.log(decodedVinVout.outputs[_decodedInput.n], true); |
|
|
|
txInputs.push(decodedVinVout.outputs[_decodedInput.n]); |
|
|
|
} |
|
|
|
checkLoop(); |
|
|
|
} |
|
|
|
} else { |
|
|
|
checkLoop(); |
|
|
|
} |
|
|
|
}); |
|
|
|
} else { |
|
|
|
const _parsedTx = { |
|
|
|
network: decodedTx.network, |
|
|
|
format: 'cant parse', |
|
|
|
inputs: 'cant parse', |
|
|
|
outputs: 'cant parse', |
|
|
|
height: transaction.height, |
|
|
|
timestamp: Number(transaction.height) === 0 ? Math.floor(Date.now() / 1000) : blockInfo.timestamp, |
|
|
|
confirmations: Number(transaction.height) === 0 ? 0 : currentHeight - transaction.height, |
|
|
|
}; |
|
|
|
|
|
|
|
const formattedTx = shepherd.parseTransactionAddresses(_parsedTx, req.query.address, network); |
|
|
|
_rawtx.push(formattedTx); |
|
|
|
index++; |
|
|
|
|
|
|
|
if (index === json.length) { |
|
|
|
ecl.close(); |
|
|
|
|
|
|
|
const successObj = { |
|
|
|
msg: 'success', |
|
|
|
result: _rawtx, |
|
|
|
}; |
|
|
|
|
|
|
|
res.end(JSON.stringify(successObj)); |
|
|
|
} else { |
|
|
|
callback(); |
|
|
|
} |
|
|
|
}); |
|
|
|
} else { |
|
|
|
const _parsedTx = { |
|
|
|
network: 'cant parse', |
|
|
|
format: 'cant parse', |
|
|
|
inputs: 'cant parse', |
|
|
|
outputs: 'cant parse', |
|
|
|
height: transaction.height, |
|
|
|
timestamp: 'cant get block info', |
|
|
|
confirmations: Number(transaction.height) === 0 ? 0 : currentHeight - transaction.height, |
|
|
|
} |
|
|
|
}); |
|
|
|
} else { |
|
|
|
const _parsedTx = { |
|
|
|
network: 'cant parse', |
|
|
|
format: 'cant parse', |
|
|
|
inputs: 'cant parse', |
|
|
|
outputs: 'cant parse', |
|
|
|
height: transaction.height, |
|
|
|
timestamp: 'cant get block info', |
|
|
|
confirmations: Number(transaction.height) === 0 ? 0 : currentHeight - transaction.height, |
|
|
|
}; |
|
|
|
const formattedTx = shepherd.parseTransactionAddresses(_parsedTx, req.query.address, network); |
|
|
|
_rawtx.push(formattedTx); |
|
|
|
index++; |
|
|
|
|
|
|
|
if (index === json.length) { |
|
|
|
ecl.close(); |
|
|
|
|
|
|
|
const successObj = { |
|
|
|
msg: 'success', |
|
|
|
result: _rawtx, |
|
|
|
}; |
|
|
|
const formattedTx = shepherd.parseTransactionAddresses(_parsedTx, req.query.address, network); |
|
|
|
_rawtx.push(formattedTx); |
|
|
|
|
|
|
|
res.end(JSON.stringify(successObj)); |
|
|
|
} else { |
|
|
|
callback(); |
|
|
|
index++; |
|
|
|
} |
|
|
|
}); |
|
|
|
//});
|
|
|
|
|
|
|
|
if (index === json.length) { |
|
|
|
ecl.close(); |
|
|
|
|
|
|
|
const successObj = { |
|
|
|
msg: 'success', |
|
|
|
result: _rawtx, |
|
|
|
}; |
|
|
|
|
|
|
|
res.end(JSON.stringify(successObj)); |
|
|
|
} |
|
|
|
} |
|
|
|
}); |
|
|
|
}); |
|
|
|
/*.then(promiseResult => { |
|
|
|
ecl.close(); |
|
|
|
|
|
|
|
const successObj = { |
|
|
|
msg: 'success', |
|
|
|
result: _rawtx, |
|
|
|
}; |
|
|
|
|
|
|
|
res.end(JSON.stringify(successObj)); |
|
|
|
});*/ |
|
|
|
} else { |
|
|
|
ecl.close(); |
|
|
|
|
|
|
|