mempool/backend/src/repositories/TransactionRepository.ts

123 lines
3.2 KiB
TypeScript
Raw Normal View History

2022-11-27 13:46:23 +09:00
import DB from '../database';
import logger from '../logger';
import { Ancestor, CpfpInfo } from '../mempool.interfaces';
2023-01-09 10:24:12 -06:00
import cpfpRepository from './CpfpRepository';
2022-11-27 13:46:23 +09:00
class TransactionRepository {
2023-01-09 10:24:12 -06:00
public async $setCluster(txid: string, clusterRoot: string): Promise<void> {
2022-11-27 13:46:23 +09:00
try {
await DB.query(
`
2023-01-09 10:24:12 -06:00
INSERT INTO compact_transactions
2022-11-27 13:46:23 +09:00
(
txid,
cluster
)
2023-01-09 10:24:12 -06:00
VALUE (UNHEX(?), UNHEX(?))
2022-11-27 13:46:23 +09:00
ON DUPLICATE KEY UPDATE
2023-01-09 10:24:12 -06:00
cluster = UNHEX(?)
2022-11-27 13:46:23 +09:00
;`,
2023-01-09 10:24:12 -06:00
[txid, clusterRoot, clusterRoot]
2022-11-27 13:46:23 +09:00
);
} catch (e: any) {
logger.err(`Cannot save transaction cpfp cluster into db. Reason: ` + (e instanceof Error ? e.message : e));
throw e;
}
}
2023-06-22 11:52:43 -04:00
public buildBatchSetQuery(txs: { txid: string, cluster: string }[]): { query, params } {
let query = `
2023-01-10 17:13:11 -06:00
INSERT IGNORE INTO compact_transactions
(
txid,
cluster
)
VALUES
`;
2023-06-22 11:52:43 -04:00
query += txs.map(tx => {
return (' (UNHEX(?), UNHEX(?))');
}) + ';';
const values = txs.map(tx => [tx.txid, tx.cluster]).flat();
return {
query,
params: values,
};
}
public async $batchSetCluster(txs): Promise<void> {
try {
const query = this.buildBatchSetQuery(txs);
2023-01-10 17:13:11 -06:00
await DB.query(
2023-06-22 11:52:43 -04:00
query.query,
query.params,
2023-01-10 17:13:11 -06:00
);
} catch (e: any) {
logger.err(`Cannot save cpfp transactions into db. Reason: ` + (e instanceof Error ? e.message : e));
throw e;
}
}
2022-11-27 13:46:23 +09:00
public async $getCpfpInfo(txid: string): Promise<CpfpInfo | void> {
try {
2023-01-09 10:24:12 -06:00
const [txRows]: any = await DB.query(
`
SELECT HEX(txid) as id, HEX(cluster) as root
FROM compact_transactions
WHERE txid = UNHEX(?)
`,
[txid]
);
if (txRows.length && txRows[0].root != null) {
const txid = txRows[0].id.toLowerCase();
const clusterId = txRows[0].root.toLowerCase();
const cluster = await cpfpRepository.$getCluster(clusterId);
if (cluster) {
return this.convertCpfp(txid, cluster);
}
2022-11-27 13:46:23 +09:00
}
} catch (e) {
logger.err('Cannot get transaction cpfp info from db. Reason: ' + (e instanceof Error ? e.message : e));
throw e;
}
}
2023-01-09 10:24:12 -06:00
public async $removeTransaction(txid: string): Promise<void> {
try {
await DB.query(
`
DELETE FROM compact_transactions
WHERE txid = UNHEX(?)
`,
[txid]
);
} catch (e) {
logger.warn('Cannot delete transaction cpfp info from db. Reason: ' + (e instanceof Error ? e.message : e));
throw e;
}
2023-01-09 10:24:12 -06:00
}
private convertCpfp(txid, cluster): CpfpInfo {
2022-11-27 13:46:23 +09:00
const descendants: Ancestor[] = [];
const ancestors: Ancestor[] = [];
let matched = false;
2023-01-09 10:24:12 -06:00
for (const tx of (cluster?.txs || [])) {
2023-01-09 10:24:12 -06:00
if (tx.txid === txid) {
2022-11-27 13:46:23 +09:00
matched = true;
} else if (!matched) {
descendants.push(tx);
} else {
ancestors.push(tx);
}
}
return {
descendants,
ancestors,
effectiveFeePerVsize: cluster.effectiveFeePerVsize,
2022-11-27 13:46:23 +09:00
};
}
}
export default new TransactionRepository();