2020-12-21 17:08:34 +01:00
|
|
|
import bitcoinApi from './bitcoin/bitcoin-api-factory';
|
|
|
|
import logger from '../logger';
|
2020-12-27 22:47:22 +01:00
|
|
|
import { TransactionExtended, TransactionMinerInfo } from '../mempool.interfaces';
|
|
|
|
import { IEsploraApi } from './bitcoin/esplora-api.interface';
|
2020-12-21 17:08:34 +01:00
|
|
|
|
|
|
|
class TransactionUtils {
|
|
|
|
constructor() { }
|
|
|
|
|
|
|
|
public async $addPrevoutsToTransaction(transaction: TransactionExtended): Promise<TransactionExtended> {
|
2020-12-27 22:47:22 +01:00
|
|
|
if (transaction.vin[0].is_coinbase) {
|
2020-12-21 17:08:34 +01:00
|
|
|
return transaction;
|
|
|
|
}
|
|
|
|
for (const vin of transaction.vin) {
|
|
|
|
const innerTx = await bitcoinApi.$getRawTransaction(vin.txid);
|
2020-12-27 22:47:22 +01:00
|
|
|
vin.prevout = innerTx.vout[vin.vout];
|
2020-12-21 17:08:34 +01:00
|
|
|
}
|
2020-12-27 22:47:22 +01:00
|
|
|
return transaction;
|
2020-12-21 17:08:34 +01:00
|
|
|
}
|
|
|
|
|
2020-12-27 22:47:22 +01:00
|
|
|
public extendTransaction(transaction: IEsploraApi.Transaction): TransactionExtended {
|
2020-12-22 00:04:31 +01:00
|
|
|
transaction['vsize'] = Math.round(transaction.weight / 4);
|
|
|
|
transaction['feePerVsize'] = Math.max(1, (transaction.fee || 0) / (transaction.weight / 4));
|
2020-12-27 22:47:22 +01:00
|
|
|
if (!transaction.status.confirmed) {
|
2020-12-22 00:04:31 +01:00
|
|
|
transaction['firstSeen'] = Math.round((new Date().getTime() / 1000));
|
|
|
|
}
|
2020-12-21 17:08:34 +01:00
|
|
|
// @ts-ignore
|
2020-12-22 00:04:31 +01:00
|
|
|
return transaction;
|
2020-12-21 17:08:34 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
public stripCoinbaseTransaction(tx: TransactionExtended): TransactionMinerInfo {
|
|
|
|
return {
|
|
|
|
vin: [{
|
|
|
|
scriptsig: tx.vin[0].scriptsig || tx.vin[0]['coinbase']
|
|
|
|
}],
|
|
|
|
vout: tx.vout
|
|
|
|
.map((vout) => ({
|
|
|
|
scriptpubkey_address: vout.scriptpubkey_address,
|
|
|
|
value: vout.value
|
|
|
|
}))
|
|
|
|
.filter((vout) => vout.value)
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
2020-12-27 22:47:22 +01:00
|
|
|
public async $getTransactionExtended(txId: string, inMempool = false, addPrevouts = false): Promise<TransactionExtended | null> {
|
2020-12-21 17:08:34 +01:00
|
|
|
try {
|
2020-12-27 22:47:22 +01:00
|
|
|
let transaction: IEsploraApi.Transaction;
|
2020-12-21 17:08:34 +01:00
|
|
|
if (inMempool) {
|
2020-12-27 22:47:22 +01:00
|
|
|
transaction = await bitcoinApi.$getRawTransactionBitcoind(txId, false, addPrevouts);
|
2020-12-21 17:08:34 +01:00
|
|
|
} else {
|
2020-12-27 22:47:22 +01:00
|
|
|
transaction = await bitcoinApi.$getRawTransaction(txId, false, addPrevouts);
|
2020-12-21 17:08:34 +01:00
|
|
|
}
|
|
|
|
return this.extendTransaction(transaction);
|
|
|
|
} catch (e) {
|
|
|
|
logger.debug('getTransactionExtended error: ' + (e.message || e));
|
|
|
|
console.log(e);
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
export default new TransactionUtils();
|