diff --git a/backend/src/api/bitcoin/bitcoin-api-abstract-factory.ts b/backend/src/api/bitcoin/bitcoin-api-abstract-factory.ts index 5201d47a5..53c731e1f 100644 --- a/backend/src/api/bitcoin/bitcoin-api-abstract-factory.ts +++ b/backend/src/api/bitcoin/bitcoin-api-abstract-factory.ts @@ -12,6 +12,7 @@ export interface AbstractBitcoinApi { $getAddressTransactions(address: string, lastSeenTxId: string): Promise; $getAddressPrefix(prefix: string): string[]; $sendRawTransaction(rawTransaction: string): Promise; + $getOutspends(txId: string): Promise; } export interface BitcoinRpcCredentials { host: string; diff --git a/backend/src/api/bitcoin/bitcoin-api.ts b/backend/src/api/bitcoin/bitcoin-api.ts index 42d213ff7..79505d5c3 100644 --- a/backend/src/api/bitcoin/bitcoin-api.ts +++ b/backend/src/api/bitcoin/bitcoin-api.ts @@ -102,6 +102,18 @@ class BitcoinApi implements AbstractBitcoinApi { return this.bitcoindClient.sendRawTransaction(rawTransaction); } + async $getOutspends(txId: string): Promise { + const outSpends: IEsploraApi.Outspend[] = []; + const tx = await this.$getRawTransaction(txId, true, false); + for (let i = 0; i < tx.vout.length; i++) { + const txOut = await this.bitcoindClient.getTxOut(txId, i); + outSpends.push({ + spent: txOut === null, + }); + } + return outSpends; + } + protected async $convertTransaction(transaction: IBitcoinApi.Transaction, addPrevout: boolean): Promise { let esploraTransaction: IEsploraApi.Transaction = { txid: transaction.txid, diff --git a/backend/src/api/bitcoin/esplora-api.interface.ts b/backend/src/api/bitcoin/esplora-api.interface.ts index 7ac4e1675..73ccbd88f 100644 --- a/backend/src/api/bitcoin/esplora-api.interface.ts +++ b/backend/src/api/bitcoin/esplora-api.interface.ts @@ -113,9 +113,9 @@ export namespace IEsploraApi { export interface Outspend { spent: boolean; - txid: string; - vin: number; - status: Status; + txid?: string; + vin?: number; + status?: Status; } export interface Asset { diff --git a/backend/src/api/bitcoin/esplora-api.ts b/backend/src/api/bitcoin/esplora-api.ts index 142815c02..d92bba1bf 100644 --- a/backend/src/api/bitcoin/esplora-api.ts +++ b/backend/src/api/bitcoin/esplora-api.ts @@ -60,6 +60,10 @@ class ElectrsApi implements AbstractBitcoinApi { $sendRawTransaction(rawTransaction: string): Promise { throw new Error('Method not implemented.'); } + + $getOutspends(): Promise { + throw new Error('Method not implemented.'); + } } export default ElectrsApi; diff --git a/backend/src/routes.ts b/backend/src/routes.ts index 8484ec2ab..1d98c9f4e 100644 --- a/backend/src/routes.ts +++ b/backend/src/routes.ts @@ -716,8 +716,13 @@ class Routes { } } - public getTransactionOutspends(req: Request, res: Response) { - res.status(501).send('Not implemented'); + public async getTransactionOutspends(req: Request, res: Response) { + try { + const result = await bitcoinApi.$getOutspends(req.params.txId); + res.json(result); + } catch (e) { + res.status(500).send(e instanceof Error ? e.message : e); + } } public getDifficultyChange(req: Request, res: Response) { diff --git a/frontend/src/app/components/transactions-list/transactions-list.component.html b/frontend/src/app/components/transactions-list/transactions-list.component.html index c017b41be..36aed7fe6 100644 --- a/frontend/src/app/components/transactions-list/transactions-list.component.html +++ b/frontend/src/app/components/transactions-list/transactions-list.component.html @@ -189,9 +189,14 @@ - + + + + + +