From 6c95cd21491cfb377a14fd82f82e773a16d20d79 Mon Sep 17 00:00:00 2001 From: natsoni Date: Wed, 8 Jan 2025 15:07:37 +0100 Subject: [PATCH] Update local cpfp API to accept array of transactions --- backend/src/api/bitcoin/bitcoin.routes.ts | 23 +++++++++++-------- backend/src/api/cpfp.ts | 1 - .../transaction/transaction-raw.component.ts | 8 +++---- frontend/src/app/services/api.service.ts | 4 ++-- 4 files changed, 20 insertions(+), 16 deletions(-) diff --git a/backend/src/api/bitcoin/bitcoin.routes.ts b/backend/src/api/bitcoin/bitcoin.routes.ts index 545ad510c..d49cd95b2 100644 --- a/backend/src/api/bitcoin/bitcoin.routes.ts +++ b/backend/src/api/bitcoin/bitcoin.routes.ts @@ -55,7 +55,7 @@ class BitcoinRoutes { .get(config.MEMPOOL.API_URL_PREFIX + 'blocks-bulk/:from', this.getBlocksByBulk.bind(this)) .get(config.MEMPOOL.API_URL_PREFIX + 'blocks-bulk/:from/:to', this.getBlocksByBulk.bind(this)) .post(config.MEMPOOL.API_URL_PREFIX + 'prevouts', this.$getPrevouts) - .post(config.MEMPOOL.API_URL_PREFIX + 'cpfp', this.getCpfpLocalTx) + .post(config.MEMPOOL.API_URL_PREFIX + 'cpfp', this.getCpfpLocalTxs) // Temporarily add txs/package endpoint for all backends until esplora supports it .post(config.MEMPOOL.API_URL_PREFIX + 'txs/package', this.$submitPackage) ; @@ -989,25 +989,30 @@ class BitcoinRoutes { } } - private getCpfpLocalTx(req: Request, res: Response) { + private getCpfpLocalTxs(req: Request, res: Response) { try { - const tx = req.body; + const transactions = req.body; - if ( + if (!Array.isArray(transactions) || transactions.some(tx => !tx || typeof tx !== 'object' || - !tx.txid || typeof tx.txid !== 'string' || + !/^[a-fA-F0-9]{64}$/.test(tx.txid) || typeof tx.weight !== 'number' || typeof tx.sigops !== 'number' || typeof tx.fee !== 'number' || !Array.isArray(tx.vin) || !Array.isArray(tx.vout) - ) { - handleError(req, res, 400, 'Invalid transaction format'); + )) { + handleError(req, res, 400, 'Invalid transactions format'); return; } - const cpfpInfo = calculateLocalTxCpfp(tx, mempool.getMempool()); - res.json(cpfpInfo); + if (transactions.length > 1) { + handleError(req, res, 400, 'More than one transaction is not supported yet'); + return; + } + + const cpfpInfo = calculateLocalTxCpfp(transactions[0], mempool.getMempool()); + res.json([cpfpInfo]); } catch (e) { handleError(req, res, 500, 'Failed to calculate CPFP info'); diff --git a/backend/src/api/cpfp.ts b/backend/src/api/cpfp.ts index 3421d9c7a..2b9f90542 100644 --- a/backend/src/api/cpfp.ts +++ b/backend/src/api/cpfp.ts @@ -222,7 +222,6 @@ export function calculateMempoolTxCpfp(tx: MempoolTransactionExtended, mempool: }; } - /** * Takes an unbroadcasted transaction and a copy of the current mempool, and calculates an estimate * of the CPFP data if the transaction were to enter the mempool. This only returns potential ancerstors diff --git a/frontend/src/app/components/transaction/transaction-raw.component.ts b/frontend/src/app/components/transaction/transaction-raw.component.ts index 80f3eeb93..8917dce87 100644 --- a/frontend/src/app/components/transaction/transaction-raw.component.ts +++ b/frontend/src/app/components/transaction/transaction-raw.component.ts @@ -154,17 +154,17 @@ export class TransactionRawComponent implements OnInit, OnDestroy { if (this.hasPrevouts && this.fetchCpfp) { try { this.isLoadingCpfpInfo = true; - const cpfpInfo: CpfpInfo = await firstValueFrom(this.apiService.getCpfpLocalTx$({ + const cpfpInfo: CpfpInfo[] = await firstValueFrom(this.apiService.getCpfpLocalTx$([{ txid: transaction.txid, weight: transaction.weight, sigops: transaction.sigops, fee: transaction.fee, vin: transaction.vin, vout: transaction.vout - })); + }])); - if (cpfpInfo && cpfpInfo.ancestors.length > 0) { - const { ancestors, effectiveFeePerVsize } = cpfpInfo; + if (cpfpInfo?.[0]?.ancestors?.length) { + const { ancestors, effectiveFeePerVsize } = cpfpInfo[0]; transaction.effectiveFeePerVsize = effectiveFeePerVsize; this.cpfpInfo = { ancestors, effectiveFeePerVsize }; this.hasCpfp = true; diff --git a/frontend/src/app/services/api.service.ts b/frontend/src/app/services/api.service.ts index 698eede91..d958bfa25 100644 --- a/frontend/src/app/services/api.service.ts +++ b/frontend/src/app/services/api.service.ts @@ -569,8 +569,8 @@ export class ApiService { return this.httpClient.post(this.apiBaseUrl + this.apiBasePath + '/api/v1/prevouts', outpoints); } - getCpfpLocalTx$(tx: any): Observable { - return this.httpClient.post(this.apiBaseUrl + this.apiBasePath + '/api/v1/cpfp', tx); + getCpfpLocalTx$(tx: any[]): Observable { + return this.httpClient.post(this.apiBaseUrl + this.apiBasePath + '/api/v1/cpfp', tx); } // Cache methods