From bb5be9fc2299432c5f1390f3d70a3e7c94f9a8f7 Mon Sep 17 00:00:00 2001 From: ahonn Date: Tue, 7 May 2024 19:23:00 +1000 Subject: [PATCH 1/3] fix: fix bitcoin client error message handle --- src/services/bitcoin/index.ts | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/src/services/bitcoin/index.ts b/src/services/bitcoin/index.ts index 1f66d46b..fcd1c4e4 100644 --- a/src/services/bitcoin/index.ts +++ b/src/services/bitcoin/index.ts @@ -115,11 +115,9 @@ export default class BitcoinClient implements IBitcoinClient { return result; } catch (err) { this.cradle.logger.error(err); - if ((err as AxiosError).isAxiosError) { - const error = new BitcoinClientAPIError((err as AxiosError).message); - if ((err as AxiosError).response) { - error.statusCode = (err as AxiosError).response?.status || 500; - } + if (err instanceof AxiosError) { + const error = new BitcoinClientAPIError(err.response?.data ?? err.message); + error.statusCode = err.response?.status || 500; throw error; } throw err; From 7d1e3a4f6770836b0b06d6f18d0090a1f674aebf Mon Sep 17 00:00:00 2001 From: ahonn Date: Tue, 7 May 2024 19:36:05 +1000 Subject: [PATCH 2/3] test: update test cases & snapshot --- src/services/bitcoin/index.ts | 4 +- .../__snapshots__/transaction.test.ts.snap | 6 + test/routes/bitcoin/transaction.test.ts | 4 +- .../__snapshots__/address.test.ts.snap | 194 -------------- .../bitcoind/__snapshots__/block.test.ts.snap | 31 --- .../__snapshots__/transaction.test.ts.snap | 109 -------- test/routes/bitcoind/address.test.ts | 236 ------------------ test/routes/bitcoind/block.test.ts | 84 ------- test/routes/bitcoind/info.test.ts | 49 ---- test/routes/bitcoind/transaction.test.ts | 110 -------- 10 files changed, 10 insertions(+), 817 deletions(-) delete mode 100644 test/routes/bitcoind/__snapshots__/address.test.ts.snap delete mode 100644 test/routes/bitcoind/__snapshots__/block.test.ts.snap delete mode 100644 test/routes/bitcoind/__snapshots__/transaction.test.ts.snap delete mode 100644 test/routes/bitcoind/address.test.ts delete mode 100644 test/routes/bitcoind/block.test.ts delete mode 100644 test/routes/bitcoind/info.test.ts delete mode 100644 test/routes/bitcoind/transaction.test.ts diff --git a/src/services/bitcoin/index.ts b/src/services/bitcoin/index.ts index fcd1c4e4..69d24a40 100644 --- a/src/services/bitcoin/index.ts +++ b/src/services/bitcoin/index.ts @@ -117,7 +117,9 @@ export default class BitcoinClient implements IBitcoinClient { this.cradle.logger.error(err); if (err instanceof AxiosError) { const error = new BitcoinClientAPIError(err.response?.data ?? err.message); - error.statusCode = err.response?.status || 500; + if (err.response?.status) { + error.statusCode = err.response.status; + } throw error; } throw err; diff --git a/test/routes/bitcoin/__snapshots__/transaction.test.ts.snap b/test/routes/bitcoin/__snapshots__/transaction.test.ts.snap index 79021174..49b396f0 100644 --- a/test/routes/bitcoin/__snapshots__/transaction.test.ts.snap +++ b/test/routes/bitcoin/__snapshots__/transaction.test.ts.snap @@ -1,5 +1,11 @@ // Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html +exports[`Get not exists transaction 1`] = ` +{ + "message": "Transaction not found", +} +`; + exports[`Get transaction by txid 1`] = ` { "fee": 141, diff --git a/test/routes/bitcoin/transaction.test.ts b/test/routes/bitcoin/transaction.test.ts index 04812be9..f0946872 100644 --- a/test/routes/bitcoin/transaction.test.ts +++ b/test/routes/bitcoin/transaction.test.ts @@ -58,9 +58,7 @@ describe('/bitcoin/v1/transaction', () => { const data = await response.json(); expect(response.statusCode).toBe(404); - expect(data).toEqual({ - message: 'Request failed with status code 404', - }); + expect(data).toMatchSnapshot(); await fastify.close(); }); diff --git a/test/routes/bitcoind/__snapshots__/address.test.ts.snap b/test/routes/bitcoind/__snapshots__/address.test.ts.snap deleted file mode 100644 index b0056eb5..00000000 --- a/test/routes/bitcoind/__snapshots__/address.test.ts.snap +++ /dev/null @@ -1,194 +0,0 @@ -// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html - -exports[`/bitcoin/v1/address > Get address balance 1`] = ` -{ - "address": "tb1qm4eyx777203zmajlawz958wn27z08envm2jelm", - "dust_satoshi": 0, - "pending_satoshi": 0, - "satoshi": 1000, - "utxo_count": 1, -} -`; - -exports[`/bitcoin/v1/address > Get address balance with min_satoshi param 1`] = ` -{ - "address": "tb1qm4eyx777203zmajlawz958wn27z08envm2jelm", - "dust_satoshi": 1000, - "pending_satoshi": 0, - "satoshi": 0, - "utxo_count": 1, -} -`; - -exports[`/bitcoin/v1/address > Get address transactions 1`] = ` -[ - { - "fee": 679, - "locktime": 0, - "size": 340, - "status": { - "block_hash": "0000000000960b9bc86db1c241e3b22690ae9e0360a960141f1923e87eb53ea8", - "block_height": 2585607, - "block_time": 1712556136, - "confirmed": true, - }, - "txid": "b7a7863485661d8e03fedcc39bbf4de25d703e34e0c065f2eec8e85706d93eb7", - "version": 2, - "vin": [ - { - "is_coinbase": false, - "prevout": { - "scriptpubkey": "0014f8d0addc86183d385061ee80c1b16b1975eacf42", - "scriptpubkey_address": "tb1qlrg2mhyxrq7ns5rpa6qvrvttr9674n6z0trymp", - "scriptpubkey_asm": "OP_0 OP_PUSHBYTES_20 f8d0addc86183d385061ee80c1b16b1975eacf42", - "scriptpubkey_type": "v0_p2wpkh", - "value": 890, - }, - "scriptsig": "", - "scriptsig_asm": "", - "sequence": 4294967295, - "txid": "b91c5bfddea79135de6a23de329b31c2696c673661ef90970e5c247ccf8bb7b1", - "vout": 0, - "witness": [ - "304402201c38168040ecb9fd312a18a2770ec303195c2d56c735fbfce5d7081fc33e7d6f02201f8bdaa14c424900f8d52872b10f77628fb30b104c04aa89b466610c9253a3f201", - "02d05848540f152d730e272bc9628dd4e4a5f4126fdf118ad6a4fd6afd26b08313", - ], - }, - { - "is_coinbase": false, - "prevout": { - "scriptpubkey": "0014f8d0addc86183d385061ee80c1b16b1975eacf42", - "scriptpubkey_address": "tb1qlrg2mhyxrq7ns5rpa6qvrvttr9674n6z0trymp", - "scriptpubkey_asm": "OP_0 OP_PUSHBYTES_20 f8d0addc86183d385061ee80c1b16b1975eacf42", - "scriptpubkey_type": "v0_p2wpkh", - "value": 789, - }, - "scriptsig": "", - "scriptsig_asm": "", - "sequence": 4294967295, - "txid": "03c4e6b25192823fec378a553b063e07ff20d526eb223352279a4be004f95cca", - "vout": 1, - "witness": [ - "3045022100cef667e1370b7e73a01f3b59c7f7f402932da59ba173f1ecb705ad4e40f986fb0220572e96ba212077e1076a253514e9308db11164fc1b16d0ca162209442f25aef101", - "02d05848540f152d730e272bc9628dd4e4a5f4126fdf118ad6a4fd6afd26b08313", - ], - }, - ], - "vout": [ - { - "scriptpubkey": "0014dd72437bde53e22df65feb845a1dd35784f3e66c", - "scriptpubkey_address": "tb1qm4eyx777203zmajlawz958wn27z08envm2jelm", - "scriptpubkey_asm": "OP_0 OP_PUSHBYTES_20 dd72437bde53e22df65feb845a1dd35784f3e66c", - "scriptpubkey_type": "v0_p2wpkh", - "value": 1000, - }, - ], - "weight": 709, - }, - { - "fee": 110, - "locktime": 0, - "size": 192, - "status": { - "block_hash": "00000000000000037864097e5c7beff520ee329289b1623f7c521132e5268a66", - "block_height": 2585601, - "block_time": 1712551024, - "confirmed": true, - }, - "txid": "b91c5bfddea79135de6a23de329b31c2696c673661ef90970e5c247ccf8bb7b1", - "version": 2, - "vin": [ - { - "is_coinbase": false, - "prevout": { - "scriptpubkey": "0014dd72437bde53e22df65feb845a1dd35784f3e66c", - "scriptpubkey_address": "tb1qm4eyx777203zmajlawz958wn27z08envm2jelm", - "scriptpubkey_asm": "OP_0 OP_PUSHBYTES_20 dd72437bde53e22df65feb845a1dd35784f3e66c", - "scriptpubkey_type": "v0_p2wpkh", - "value": 1000, - }, - "scriptsig": "", - "scriptsig_asm": "", - "sequence": 4294967295, - "txid": "9706131c1e327a068a6aafc16dc69a46c50bc7c65f180513896bdad39a6babfc", - "vout": 0, - "witness": [ - "3045022100f6373e6ce8e3206b9f1254e8322dbbd0c5f4990f214997fef1e4bb6cb535a00602205eb0665a34fb7e9b3789cb55e45d05b1f0daca9e53f5e3a1393cab44725caa0801", - "020b4e7dba2f094598f41e40f2eedbe274293f4248e6cac4672322dbb0b510d38f", - ], - }, - ], - "vout": [ - { - "scriptpubkey": "0014f8d0addc86183d385061ee80c1b16b1975eacf42", - "scriptpubkey_address": "tb1qlrg2mhyxrq7ns5rpa6qvrvttr9674n6z0trymp", - "scriptpubkey_asm": "OP_0 OP_PUSHBYTES_20 f8d0addc86183d385061ee80c1b16b1975eacf42", - "scriptpubkey_type": "v0_p2wpkh", - "value": 890, - }, - ], - "weight": 438, - }, - { - "fee": 141, - "locktime": 0, - "size": 223, - "status": { - "block_hash": "000000000000000cef4a1d6264fe63f543128518a466d31c7e2a8d6395b52522", - "block_height": 2579043, - "block_time": 1708580004, - "confirmed": true, - }, - "txid": "9706131c1e327a068a6aafc16dc69a46c50bc7c65f180513896bdad39a6babfc", - "version": 2, - "vin": [ - { - "is_coinbase": false, - "prevout": { - "scriptpubkey": "0014f8d0addc86183d385061ee80c1b16b1975eacf42", - "scriptpubkey_address": "tb1qlrg2mhyxrq7ns5rpa6qvrvttr9674n6z0trymp", - "scriptpubkey_asm": "OP_0 OP_PUSHBYTES_20 f8d0addc86183d385061ee80c1b16b1975eacf42", - "scriptpubkey_type": "v0_p2wpkh", - "value": 181793, - }, - "scriptsig": "", - "scriptsig_asm": "", - "sequence": 4294967295, - "txid": "d0189f19978fc47ddfe33319d01a6a66dea5a521e1f37b7e73469a3549e81531", - "vout": 0, - "witness": [ - "3045022100f50e2e6ee5ea04e4f7029d29a28e80266969f91357055e1d53b0715b768c448102204ccd9dbb38d0cc007e07b9c8b4088d4fac4ab65fef49774bafe27acbfc3d111101", - "02d05848540f152d730e272bc9628dd4e4a5f4126fdf118ad6a4fd6afd26b08313", - ], - }, - ], - "vout": [ - { - "scriptpubkey": "0014dd72437bde53e22df65feb845a1dd35784f3e66c", - "scriptpubkey_address": "tb1qm4eyx777203zmajlawz958wn27z08envm2jelm", - "scriptpubkey_asm": "OP_0 OP_PUSHBYTES_20 dd72437bde53e22df65feb845a1dd35784f3e66c", - "scriptpubkey_type": "v0_p2wpkh", - "value": 1000, - }, - { - "scriptpubkey": "0014f8d0addc86183d385061ee80c1b16b1975eacf42", - "scriptpubkey_address": "tb1qlrg2mhyxrq7ns5rpa6qvrvttr9674n6z0trymp", - "scriptpubkey_asm": "OP_0 OP_PUSHBYTES_20 f8d0addc86183d385061ee80c1b16b1975eacf42", - "scriptpubkey_type": "v0_p2wpkh", - "value": 180652, - }, - ], - "weight": 562, - }, -] -`; - -exports[`/bitcoin/v1/address > Get address unspent transaction outputs with only_confirmed = undefined 1`] = ` -{ - "address": "tb1qm4eyx777203zmajlawz958wn27z08envm2jelm", - "dust_satoshi": 1000, - "pending_satoshi": 0, - "satoshi": 0, - "utxo_count": 1, -} -`; diff --git a/test/routes/bitcoind/__snapshots__/block.test.ts.snap b/test/routes/bitcoind/__snapshots__/block.test.ts.snap deleted file mode 100644 index 4e4d1c70..00000000 --- a/test/routes/bitcoind/__snapshots__/block.test.ts.snap +++ /dev/null @@ -1,31 +0,0 @@ -// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html - -exports[`/bitcoin/v1/block > Get block by hash 1`] = ` -{ - "bits": 436273151, - "difficulty": 16777216, - "height": 2091140, - "id": "000000000000009c08dc77c3f224d9f5bbe335a78b996ec1e0701e065537ca81", - "mediantime": 1630621997, - "merkle_root": "5d10d8d158bb8eb217d01fecc435bd10eda028043a913dc2bfe0ccf536a51cc9", - "nonce": 1600805744, - "previousblockhash": "0000000000000073f95d1fc0a93d449f82a754410c635e46264ec6c7c4d5741e", - "size": 575, - "timestamp": 1630625150, - "tx_count": 2, - "version": 543162372, - "weight": 1865, -} -`; - -exports[`/bitcoin/v1/block > Get block hash by height 1`] = ` -{ - "hash": "000000000933ea01ad0ee984209779baaec3ced90fa3f408719526f8d77f4943", -} -`; - -exports[`/bitcoin/v1/block > Get block header by hash 1`] = ` -{ - "header": "0000202000af62594f79b6390c6ee3de56aad6658d35a9481cd8bb0ce047523800000000652cad111d076bf8aa3417670781154fd79533fb91fe782d70d300e9e95b4c5b6d60dd6518fe27190343494f", -} -`; diff --git a/test/routes/bitcoind/__snapshots__/transaction.test.ts.snap b/test/routes/bitcoind/__snapshots__/transaction.test.ts.snap deleted file mode 100644 index 9604b77f..00000000 --- a/test/routes/bitcoind/__snapshots__/transaction.test.ts.snap +++ /dev/null @@ -1,109 +0,0 @@ -// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html - -exports[`Get not exists transaction 1`] = ` -{ - "fee": 141, - "locktime": 0, - "size": 223, - "status": { - "block_hash": "000000000000000cef4a1d6264fe63f543128518a466d31c7e2a8d6395b52522", - "block_height": 2579043, - "block_time": 1708580004, - "confirmed": true, - }, - "txid": "9706131c1e327a068a6aafc16dc69a46c50bc7c65f180513896bdad39a6babfc", - "version": 2, - "vin": [ - { - "is_coinbase": false, - "prevout": { - "scriptpubkey": "0014f8d0addc86183d385061ee80c1b16b1975eacf42", - "scriptpubkey_address": "tb1qlrg2mhyxrq7ns5rpa6qvrvttr9674n6z0trymp", - "scriptpubkey_asm": "OP_0 OP_PUSHBYTES_20 f8d0addc86183d385061ee80c1b16b1975eacf42", - "scriptpubkey_type": "v0_p2wpkh", - "value": 181793, - }, - "scriptsig": "", - "scriptsig_asm": "", - "sequence": 4294967295, - "txid": "d0189f19978fc47ddfe33319d01a6a66dea5a521e1f37b7e73469a3549e81531", - "vout": 0, - "witness": [ - "3045022100f50e2e6ee5ea04e4f7029d29a28e80266969f91357055e1d53b0715b768c448102204ccd9dbb38d0cc007e07b9c8b4088d4fac4ab65fef49774bafe27acbfc3d111101", - "02d05848540f152d730e272bc9628dd4e4a5f4126fdf118ad6a4fd6afd26b08313", - ], - }, - ], - "vout": [ - { - "scriptpubkey": "0014dd72437bde53e22df65feb845a1dd35784f3e66c", - "scriptpubkey_address": "tb1qm4eyx777203zmajlawz958wn27z08envm2jelm", - "scriptpubkey_asm": "OP_0 OP_PUSHBYTES_20 dd72437bde53e22df65feb845a1dd35784f3e66c", - "scriptpubkey_type": "v0_p2wpkh", - "value": 1000, - }, - { - "scriptpubkey": "0014f8d0addc86183d385061ee80c1b16b1975eacf42", - "scriptpubkey_address": "tb1qlrg2mhyxrq7ns5rpa6qvrvttr9674n6z0trymp", - "scriptpubkey_asm": "OP_0 OP_PUSHBYTES_20 f8d0addc86183d385061ee80c1b16b1975eacf42", - "scriptpubkey_type": "v0_p2wpkh", - "value": 180652, - }, - ], - "weight": 562, -} -`; - -exports[`Get transaction by txid 1`] = ` -{ - "fee": 141, - "locktime": 0, - "size": 223, - "status": { - "block_hash": "000000000000000cef4a1d6264fe63f543128518a466d31c7e2a8d6395b52522", - "block_height": 2579043, - "block_time": 1708580004, - "confirmed": true, - }, - "txid": "9706131c1e327a068a6aafc16dc69a46c50bc7c65f180513896bdad39a6babfc", - "version": 2, - "vin": [ - { - "is_coinbase": false, - "prevout": { - "scriptpubkey": "0014f8d0addc86183d385061ee80c1b16b1975eacf42", - "scriptpubkey_address": "tb1qlrg2mhyxrq7ns5rpa6qvrvttr9674n6z0trymp", - "scriptpubkey_asm": "OP_0 OP_PUSHBYTES_20 f8d0addc86183d385061ee80c1b16b1975eacf42", - "scriptpubkey_type": "v0_p2wpkh", - "value": 181793, - }, - "scriptsig": "", - "scriptsig_asm": "", - "sequence": 4294967295, - "txid": "d0189f19978fc47ddfe33319d01a6a66dea5a521e1f37b7e73469a3549e81531", - "vout": 0, - "witness": [ - "3045022100f50e2e6ee5ea04e4f7029d29a28e80266969f91357055e1d53b0715b768c448102204ccd9dbb38d0cc007e07b9c8b4088d4fac4ab65fef49774bafe27acbfc3d111101", - "02d05848540f152d730e272bc9628dd4e4a5f4126fdf118ad6a4fd6afd26b08313", - ], - }, - ], - "vout": [ - { - "scriptpubkey": "0014dd72437bde53e22df65feb845a1dd35784f3e66c", - "scriptpubkey_address": "tb1qm4eyx777203zmajlawz958wn27z08envm2jelm", - "scriptpubkey_asm": "OP_0 OP_PUSHBYTES_20 dd72437bde53e22df65feb845a1dd35784f3e66c", - "scriptpubkey_type": "v0_p2wpkh", - "value": 1000, - }, - { - "scriptpubkey": "0014f8d0addc86183d385061ee80c1b16b1975eacf42", - "scriptpubkey_address": "tb1qlrg2mhyxrq7ns5rpa6qvrvttr9674n6z0trymp", - "scriptpubkey_asm": "OP_0 OP_PUSHBYTES_20 f8d0addc86183d385061ee80c1b16b1975eacf42", - "scriptpubkey_type": "v0_p2wpkh", - "value": 180652, - }, - ], - "weight": 562, -} -`; diff --git a/test/routes/bitcoind/address.test.ts b/test/routes/bitcoind/address.test.ts deleted file mode 100644 index 3cdf3eea..00000000 --- a/test/routes/bitcoind/address.test.ts +++ /dev/null @@ -1,236 +0,0 @@ -import { describe, expect, test, beforeEach, vi } from 'vitest'; -import { buildFastify } from '../../../src/app'; -import { afterEach } from 'node:test'; -import BitcoinClient from '../../../src/services/bitcoin'; - -let token: string; - -describe('/bitcoin/v1/address', () => { - beforeEach(async () => { - const fastify = buildFastify(); - await fastify.ready(); - - const response = await fastify.inject({ - method: 'POST', - url: '/token/generate', - payload: { - app: 'test', - domain: 'test.com', - }, - }); - const data = response.json(); - token = data.token; - - await fastify.close(); - }); - - afterEach(() => { - vi.resetAllMocks(); - }); - - test('Get address balance', async () => { - const fastify = buildFastify(); - await fastify.ready(); - - const response = await fastify.inject({ - method: 'GET', - url: '/bitcoin/v1/address/tb1qm4eyx777203zmajlawz958wn27z08envm2jelm/balance', - headers: { - Authorization: `Bearer ${token}`, - Origin: 'https://test.com', - }, - }); - const data = response.json(); - - expect(response.statusCode).toBe(200); - expect(data).toMatchSnapshot(); - - await fastify.close(); - }); - - test('Get address balance with min_satoshi param', async () => { - const fastify = buildFastify(); - await fastify.ready(); - - const response = await fastify.inject({ - method: 'GET', - url: '/bitcoin/v1/address/tb1qm4eyx777203zmajlawz958wn27z08envm2jelm/balance?min_satoshi=10000', - headers: { - Authorization: `Bearer ${token}`, - Origin: 'https://test.com', - }, - }); - const data = response.json(); - - expect(response.statusCode).toBe(200); - expect(data).toMatchSnapshot(); - - await fastify.close(); - }); - - test('Get address balance with invalid address', async () => { - const fastify = buildFastify(); - await fastify.ready(); - - const response = await fastify.inject({ - method: 'GET', - url: '/bitcoin/v1/address/tb1qlrg2mhyxrq7ns5rpa6qvrvttr9674n6z0try/balance', - headers: { - Authorization: `Bearer ${token}`, - Origin: 'https://test.com', - }, - }); - const data = response.json(); - - expect(response.statusCode).toBe(400); - expect(data.message).toBe('Invalid bitcoin address'); - - await fastify.close(); - }); - - test('Get address unspent transaction outputs', async () => { - const fastify = buildFastify(); - await fastify.ready(); - - const bitcoin: BitcoinClient = fastify.container.resolve('bitcoin'); - const originalGetAddressTxsUtxo = bitcoin.getAddressTxsUtxo; - vi.spyOn(bitcoin, 'getAddressTxsUtxo').mockResolvedValue([ - { - txid: '9706131c1e327a068a6aafc16dc69a46c50bc7c65f180513896bdad39a6babfc', - vout: 0, - status: { - confirmed: true, - }, - value: 100000, - }, - { - txid: '1706131c1e327a068a6aafc16dc69a46c50bc7c65f180513896bdad39a6babfc', - vout: 0, - status: { - confirmed: false, - }, - value: 100000, - }, - ]); - - const response = await fastify.inject({ - method: 'GET', - url: '/bitcoin/v1/address/tb1qm4eyx777203zmajlawz958wn27z08envm2jelm/unspent', - headers: { - Authorization: `Bearer ${token}`, - Origin: 'https://test.com', - }, - }); - const data = response.json(); - bitcoin.getAddressTxsUtxo = originalGetAddressTxsUtxo; - - expect(response.statusCode).toBe(200); - expect(data.length).toBe(1); - - await fastify.close(); - }); - - test('Get address unspent transaction outputs with unconfirmed', async () => { - const fastify = buildFastify(); - await fastify.ready(); - - const bitcoin: BitcoinClient = fastify.container.resolve('bitcoin'); - const originalGetAddressTxsUtxo = bitcoin.getAddressTxsUtxo; - vi.spyOn(bitcoin, 'getAddressTxsUtxo').mockResolvedValue([ - { - txid: '9706131c1e327a068a6aafc16dc69a46c50bc7c65f180513896bdad39a6babfc', - vout: 0, - status: { - confirmed: true, - }, - value: 100000, - }, - { - txid: '1706131c1e327a068a6aafc16dc69a46c50bc7c65f180513896bdad39a6babfc', - vout: 0, - status: { - confirmed: false, - }, - value: 100000, - }, - ]); - - const response = await fastify.inject({ - method: 'GET', - url: '/bitcoin/v1/address/tb1qm4eyx777203zmajlawz958wn27z08envm2jelm/unspent?only_confirmed=false', - headers: { - Authorization: `Bearer ${token}`, - Origin: 'https://test.com', - }, - }); - const data = response.json(); - bitcoin.getAddressTxsUtxo = originalGetAddressTxsUtxo; - - expect(response.statusCode).toBe(200); - expect(data.length).toBe(2); - - await fastify.close(); - }); - - test('Get address unspent transaction outputs with only_confirmed = undefined', async () => { - const fastify = buildFastify(); - await fastify.ready(); - - const bitcoin: BitcoinClient = fastify.container.resolve('bitcoin'); - const originalGetAddressTxsUtxo = bitcoin.getAddressTxsUtxo; - vi.spyOn(bitcoin, 'getAddressTxsUtxo').mockResolvedValue([ - { - txid: '9706131c1e327a068a6aafc16dc69a46c50bc7c65f180513896bdad39a6babfc', - vout: 0, - status: { - confirmed: true, - }, - value: 100000, - }, - { - txid: '1706131c1e327a068a6aafc16dc69a46c50bc7c65f180513896bdad39a6babfc', - vout: 0, - status: { - confirmed: false, - }, - value: 100000, - }, - ]); - - const response = await fastify.inject({ - method: 'GET', - url: '/bitcoin/v1/address/tb1qm4eyx777203zmajlawz958wn27z08envm2jelm/unspent?only_confirmed=undefined', - headers: { - Authorization: `Bearer ${token}`, - Origin: 'https://test.com', - }, - }); - const data = response.json(); - bitcoin.getAddressTxsUtxo = originalGetAddressTxsUtxo; - - expect(response.statusCode).toBe(200); - expect(data.length).toBe(1); - - await fastify.close(); - }); - - test('Get address transactions', async () => { - const fastify = buildFastify(); - await fastify.ready(); - - const response = await fastify.inject({ - method: 'GET', - url: '/bitcoin/v1/address/tb1qm4eyx777203zmajlawz958wn27z08envm2jelm/txs', - headers: { - Authorization: `Bearer ${token}`, - Origin: 'https://test.com', - }, - }); - const data = response.json(); - - expect(response.statusCode).toBe(200); - expect(data).toMatchSnapshot(); - - await fastify.close(); - }); -}); diff --git a/test/routes/bitcoind/block.test.ts b/test/routes/bitcoind/block.test.ts deleted file mode 100644 index e7759be0..00000000 --- a/test/routes/bitcoind/block.test.ts +++ /dev/null @@ -1,84 +0,0 @@ -import { describe, beforeEach, expect, test } from 'vitest'; -import { buildFastify } from '../../../src/app'; - -describe('/bitcoin/v1/block', () => { - let token: string; - - beforeEach(async () => { - const fastify = buildFastify(); - await fastify.ready(); - - const response = await fastify.inject({ - method: 'POST', - url: '/token/generate', - payload: { - app: 'test', - domain: 'test.com', - }, - }); - const data = response.json(); - token = data.token; - - await fastify.close(); - }); - - test('Get block by hash', async () => { - const fastify = buildFastify(); - await fastify.ready(); - - const response = await fastify.inject({ - method: 'GET', - url: '/bitcoin/v1/block/000000000000009c08dc77c3f224d9f5bbe335a78b996ec1e0701e065537ca81', - headers: { - Authorization: `Bearer ${token}`, - Origin: 'https://test.com', - }, - }); - const data = response.json(); - - expect(response.statusCode).toBe(200); - expect(data).toMatchSnapshot(); - - await fastify.close(); - }); - - test('Get block header by hash', async () => { - const fastify = buildFastify(); - await fastify.ready(); - - const response = await fastify.inject({ - method: 'GET', - url: '/bitcoin/v1/block/0000000000000005ae0b929ee3afbf2956aaa0059f9d7608dc396cf5f8f4dda6/header', - headers: { - Authorization: `Bearer ${token}`, - Origin: 'https://test.com', - }, - }); - const data = response.json(); - - expect(response.statusCode).toBe(200); - expect(data).toMatchSnapshot(); - - await fastify.close(); - }); - - test('Get block hash by height', async () => { - const fastify = buildFastify(); - await fastify.ready(); - - const response = await fastify.inject({ - method: 'GET', - url: '/bitcoin/v1/block/height/0', - headers: { - Authorization: `Bearer ${token}`, - Origin: 'https://test.com', - }, - }); - const data = response.json(); - - expect(response.statusCode).toBe(200); - expect(data).toMatchSnapshot(); - - await fastify.close(); - }); -}); diff --git a/test/routes/bitcoind/info.test.ts b/test/routes/bitcoind/info.test.ts deleted file mode 100644 index 1a87f59e..00000000 --- a/test/routes/bitcoind/info.test.ts +++ /dev/null @@ -1,49 +0,0 @@ -import { beforeEach, expect, test } from 'vitest'; -import { buildFastify } from '../../../src/app'; -import { describe } from 'node:test'; - -let token: string; - -describe('/bitcoin/v1/info', () => { - beforeEach(async () => { - const fastify = buildFastify(); - await fastify.ready(); - - const response = await fastify.inject({ - method: 'POST', - url: '/token/generate', - payload: { - app: 'test', - domain: 'test.com', - }, - }); - const data = response.json(); - token = data.token; - - await fastify.close(); - }); - - test('Get blockchain info', async () => { - const fastify = buildFastify(); - await fastify.ready(); - - const response = await fastify.inject({ - method: 'GET', - url: '/bitcoin/v1/info', - headers: { - Authorization: `Bearer ${token}`, - Origin: 'https://test.com', - }, - }); - const data = response.json(); - - expect(response.statusCode).toBe(200); - expect(data).toHaveProperty('bestblockhash'); - expect(data).toHaveProperty('blocks'); - expect(data).toHaveProperty('chain'); - expect(data).toHaveProperty('difficulty'); - expect(data).toHaveProperty('mediantime'); - - await fastify.close(); - }); -}); diff --git a/test/routes/bitcoind/transaction.test.ts b/test/routes/bitcoind/transaction.test.ts deleted file mode 100644 index 04812be9..00000000 --- a/test/routes/bitcoind/transaction.test.ts +++ /dev/null @@ -1,110 +0,0 @@ -import { beforeEach, expect, test } from 'vitest'; -import { buildFastify } from '../../../src/app'; -import { describe } from 'node:test'; - -let token: string; - -describe('/bitcoin/v1/transaction', () => { - beforeEach(async () => { - const fastify = buildFastify(); - await fastify.ready(); - - const response = await fastify.inject({ - method: 'POST', - url: '/token/generate', - payload: { - app: 'test', - domain: 'test.com', - }, - }); - const data = response.json(); - token = data.token; - - await fastify.close(); - }); - - test('Get transaction by txid', async () => { - const fastify = buildFastify(); - await fastify.ready(); - - const response = await fastify.inject({ - method: 'GET', - url: '/bitcoin/v1/transaction/9706131c1e327a068a6aafc16dc69a46c50bc7c65f180513896bdad39a6babfc', - headers: { - Authorization: `Bearer ${token}`, - Origin: 'https://test.com', - }, - }); - const data = response.json(); - - expect(response.statusCode).toBe(200); - expect(data).toMatchSnapshot(); - - await fastify.close(); - }); - - test('Get not exists transaction', async () => { - const fastify = buildFastify(); - await fastify.ready(); - - const response = await fastify.inject({ - method: 'GET', - url: '/bitcoin/v1/transaction/9706131c1e327a068a6aafc16dc69a46c50bc7c65f180513896bdad39a6babf1', - headers: { - Authorization: `Bearer ${token}`, - Origin: 'https://test.com', - }, - }); - const data = await response.json(); - - expect(response.statusCode).toBe(404); - expect(data).toEqual({ - message: 'Request failed with status code 404', - }); - - await fastify.close(); - }); - - test('Get transaction hex', async () => { - const fastify = buildFastify(); - await fastify.ready(); - - const response = await fastify.inject({ - method: 'GET', - url: '/bitcoin/v1/transaction/9706131c1e327a068a6aafc16dc69a46c50bc7c65f180513896bdad39a6babfc/hex', - headers: { - Authorization: `Bearer ${token}`, - Origin: 'https://test.com', - }, - }); - const data = await response.json(); - - expect(response.statusCode).toBe(200); - expect(data).toEqual({ - hex: '020000000001013115e849359a46737e7bf3e121a5a5de666a1ad01933e3df7dc48f97199f18d00000000000ffffffff02e803000000000000160014dd72437bde53e22df65feb845a1dd35784f3e66cacc1020000000000160014f8d0addc86183d385061ee80c1b16b1975eacf4202483045022100f50e2e6ee5ea04e4f7029d29a28e80266969f91357055e1d53b0715b768c448102204ccd9dbb38d0cc007e07b9c8b4088d4fac4ab65fef49774bafe27acbfc3d1111012102d05848540f152d730e272bc9628dd4e4a5f4126fdf118ad6a4fd6afd26b0831300000000', - }); - - await fastify.close(); - }); - - test('Send exists raw transaction', async () => { - const fastify = buildFastify(); - await fastify.ready(); - - const response = await fastify.inject({ - method: 'POST', - url: '/bitcoin/v1/transaction', - headers: { - Authorization: `Bearer ${token}`, - Origin: 'https://test.com', - }, - body: { - txhex: - '02000000000101fe7b9cd0f75741e2ec1e3a6142eab945e64fab0ef15de4a66c635c0a789e986f0100000000ffffffff02e803000000000000160014dbf4360c0791098b0b14679e5e78015df3f2caad6a88000000000000160014dbf4360c0791098b0b14679e5e78015df3f2caad02473044022065829878f51581488f44c37064b46f552ea7354196fae5536906797b76b370bf02201c459081578dc4e1098fbe3ab68d7d56a99e8e9810bf2806d10053d6b36ffa4d0121037dff8ff2e0bd222690d785f9277e0c4800fc88b0fad522f1442f21a8226253ce00000000', - }, - }); - - expect(response.statusCode).toBe(400); - await fastify.close(); - }); -}); From 7356146a786fdeebab3e2a0f564c93cb5acfa651 Mon Sep 17 00:00:00 2001 From: ahonn Date: Tue, 7 May 2024 19:47:38 +1000 Subject: [PATCH 3/3] fix: use isAxiosError to get axios error type --- src/plugins/sentry.ts | 4 ++-- src/services/bitcoin/index.ts | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/plugins/sentry.ts b/src/plugins/sentry.ts index b0c9a043..6c7a733a 100644 --- a/src/plugins/sentry.ts +++ b/src/plugins/sentry.ts @@ -3,7 +3,7 @@ import fastifySentry from '@immobiliarelabs/fastify-sentry'; import { ProfilingIntegration } from '@sentry/profiling-node'; import pkg from '../../package.json'; import { env } from '../env'; -import { HttpStatusCode, AxiosError } from 'axios'; +import { HttpStatusCode, isAxiosError } from 'axios'; import { BitcoinClientAPIError } from '../services/bitcoin'; export default fp(async (fastify) => { @@ -23,7 +23,7 @@ export default fp(async (fastify) => { return; } - if (error instanceof AxiosError) { + if (isAxiosError(error)) { const { response } = error; reply.status(response?.status ?? HttpStatusCode.InternalServerError).send({ message: response?.data ?? error.message, diff --git a/src/services/bitcoin/index.ts b/src/services/bitcoin/index.ts index 69d24a40..191ecc81 100644 --- a/src/services/bitcoin/index.ts +++ b/src/services/bitcoin/index.ts @@ -1,4 +1,4 @@ -import { AxiosError, HttpStatusCode } from 'axios'; +import { HttpStatusCode, isAxiosError } from 'axios'; import * as Sentry from '@sentry/node'; import { Cradle } from '../../container'; import { IBitcoinBroadcastBackuper, IBitcoinDataProvider } from './interface'; @@ -115,7 +115,7 @@ export default class BitcoinClient implements IBitcoinClient { return result; } catch (err) { this.cradle.logger.error(err); - if (err instanceof AxiosError) { + if (isAxiosError(err)) { const error = new BitcoinClientAPIError(err.response?.data ?? err.message); if (err.response?.status) { error.statusCode = err.response.status;