@bigmi/core 0.6.3-alpha.1 → 0.6.3-alpha.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (43) hide show
  1. package/dist/cjs/version.d.ts +1 -1
  2. package/dist/cjs/version.js +1 -1
  3. package/dist/esm/version.d.ts +1 -1
  4. package/dist/esm/version.js +1 -1
  5. package/dist/types/version.d.ts +1 -1
  6. package/package.json +10 -1
  7. package/src/version.ts +1 -1
  8. package/.env +0 -4
  9. package/CHANGELOG.md +0 -158
  10. package/package.json.tmp +0 -73
  11. package/src/chains/signet.spec.ts +0 -33
  12. package/src/transports/ankr/__mocks__/getBalance/valid.json +0 -9
  13. package/src/transports/ankr/__mocks__/getTransactionFee/invalid.json +0 -3
  14. package/src/transports/ankr/__mocks__/getTransactionFee/valid.json +0 -51
  15. package/src/transports/ankr/__mocks__/getTransactions/valid.json +0 -1186
  16. package/src/transports/ankr/ankr.spec.ts +0 -103
  17. package/src/transports/blockchair/__mocks__/getBalance/invalidAddress.json +0 -29
  18. package/src/transports/blockchair/__mocks__/getBalance/valid.json +0 -29
  19. package/src/transports/blockchair/__mocks__/getBalance/zeroBalance.json +0 -29
  20. package/src/transports/blockchair/__mocks__/getTransactionFee/invalid.json +0 -7
  21. package/src/transports/blockchair/__mocks__/getTransactionFee/valid.json +0 -37
  22. package/src/transports/blockchair/__mocks__/getUTXOs/invalidAddress.json +0 -28
  23. package/src/transports/blockchair/__mocks__/getUTXOs/rateLimited.json +0 -28
  24. package/src/transports/blockchair/__mocks__/getUTXOs/valid.json +0 -95
  25. package/src/transports/blockchair/__mocks__/getUTXOs/validPaginated.json +0 -869
  26. package/src/transports/blockchair/blockchair.spec.ts +0 -284
  27. package/src/transports/blockcypher/__mocks__/getBalance/invalid.json +0 -3
  28. package/src/transports/blockcypher/__mocks__/getBalance/valid.json +0 -13
  29. package/src/transports/blockcypher/__mocks__/getTransactionFee/invalid.json +0 -3
  30. package/src/transports/blockcypher/__mocks__/getTransactionFee/valid.json +0 -22
  31. package/src/transports/blockcypher/__mocks__/getUTXOs/empty.json +0 -12
  32. package/src/transports/blockcypher/__mocks__/getUTXOs/paginated.json +0 -2786
  33. package/src/transports/blockcypher/__mocks__/getUTXOs/rateLimited.json +0 -3
  34. package/src/transports/blockcypher/__mocks__/getUTXOs/valid.json +0 -27
  35. package/src/transports/blockcypher/blockcyper.spec.ts +0 -161
  36. package/src/transports/fallback.spec.ts +0 -128
  37. package/src/transports/mempool/__mocks__/getBalance/invalid.json +0 -1
  38. package/src/transports/mempool/__mocks__/getBalance/valid.json +0 -17
  39. package/src/transports/mempool/__mocks__/getTransactionFee/invalid.json +0 -1
  40. package/src/transports/mempool/__mocks__/getTransactionFee/valid.json +0 -58
  41. package/src/transports/mempool/__mocks__/getTransactions/valid.json +0 -1268
  42. package/src/transports/mempool/mempool.spec.ts +0 -126
  43. package/tsconfig.json +0 -12
@@ -1,3 +0,0 @@
1
- {
2
- "error": "Rate limit exceeded"
3
- }
@@ -1,27 +0,0 @@
1
- {
2
- "address": "bc1qpvk0kjdg0kantu9z78qz7gqk53q643auz33yaw",
3
- "total_received": 190653,
4
- "total_sent": 157447,
5
- "balance": 33206,
6
- "unconfirmed_balance": 0,
7
- "final_balance": 33206,
8
- "n_tx": 19,
9
- "unconfirmed_n_tx": 0,
10
- "final_n_tx": 19,
11
- "txrefs": [
12
- {
13
- "tx_hash": "4b6ee974f1dd179071d027562e1fd1c83965efa4a171ec84f00b6c638e36fa4e",
14
- "block_height": 897002,
15
- "tx_input_n": -1,
16
- "tx_output_n": 2,
17
- "value": 33206,
18
- "ref_balance": 80786,
19
- "spent": false,
20
- "confirmations": 526,
21
- "confirmed": "2025-05-16T19:17:40Z",
22
- "double_spend": false,
23
- "script": "00140b2cfb49a87dbb35f0a2f1c02f2016a441aac7bc"
24
- }
25
- ],
26
- "tx_url": "https://api.blockcypher.com/v1/btc/main/txs/"
27
- }
@@ -1,161 +0,0 @@
1
- import { beforeEach, describe, expect, it, vi } from 'vitest'
2
- import { getBalance } from '../../actions/getBalance.js'
3
- import { getTransactionFee } from '../../actions/getTransactionFee.js'
4
- import { getUTXOs } from '../../actions/getUTXOs.js'
5
- import { bitcoin } from '../../chains/bitcoin.js'
6
- import { InsufficientUTXOBalanceError } from '../../errors/utxo.js'
7
- import { createClient, rpcSchema } from '../../factories/createClient.js'
8
- import { createMockResponse } from '../../test/utils.js'
9
- import {
10
- INVALID_TX_ID,
11
- TX_FEE,
12
- VALID_TX_ID,
13
- } from '../__mocks__/getTransactionFee.js'
14
- import type { UTXOSchema } from '../types.js'
15
- import getBalanceInValidResponse from './__mocks__/getBalance/invalid.json'
16
- import getBalanceValidResponse from './__mocks__/getBalance/valid.json'
17
- import getTransactionFeeInvalidResponse from './__mocks__/getTransactionFee/invalid.json'
18
- import getTransactionFeeValidResponse from './__mocks__/getTransactionFee/valid.json'
19
- import getUTXOsEmptyReponse from './__mocks__/getUTXOs/empty.json'
20
- import getUTXOsPaginatedReponse from './__mocks__/getUTXOs/paginated.json'
21
- import getUTXOsValidReponse from './__mocks__/getUTXOs/valid.json'
22
- import { blockcypher } from './blockcypher.js'
23
- import type {
24
- BlockcypherBalanceResponse,
25
- BlockcypherErrorResponse,
26
- BlockcypherUTXOsResponse,
27
- } from './blockcypher.types.js'
28
-
29
- const apiKey = import.meta.env.VITE_TEST_BLOCKCYPHER_API_KEY
30
-
31
- const USE_MOCK = true
32
-
33
- const publicClient = createClient({
34
- chain: bitcoin,
35
- rpcSchema: rpcSchema<UTXOSchema>(),
36
- transport: blockcypher({
37
- apiKey,
38
- }),
39
- })
40
-
41
- const address = import.meta.env.VITE_TEST_ADDRESS
42
-
43
- describe('Blockcypher Transport', () => {
44
- beforeEach(() => {
45
- vi.restoreAllMocks()
46
- })
47
-
48
- describe('getBalance action', () => {
49
- it('should fetch correct balance', async () => {
50
- vi.spyOn(global, 'fetch').mockResolvedValue(
51
- createMockResponse(
52
- getBalanceValidResponse as BlockcypherBalanceResponse
53
- )
54
- )
55
- const balance = await getBalance(publicClient, { address })
56
- expect(balance).toBeTypeOf('bigint')
57
- })
58
-
59
- it('should throw an error for invalid address response', async () => {
60
- vi.spyOn(global, 'fetch').mockResolvedValue(
61
- createMockResponse(
62
- getBalanceInValidResponse as BlockcypherErrorResponse
63
- )
64
- )
65
-
66
- const nonExistentAddress =
67
- '1A1zP1eP5QGefi2DMPTfTL5SLmv7DivfNaNUIBNSUENopnoidsacn'
68
- await expect(
69
- getBalance(publicClient, { address: nonExistentAddress })
70
- ).rejects.toThrow()
71
- })
72
- })
73
-
74
- describe('getUTXOs action', async () => {
75
- it('should return utxos with correct structure', async () => {
76
- vi.spyOn(global, 'fetch').mockResolvedValue(
77
- createMockResponse(getUTXOsValidReponse as BlockcypherUTXOsResponse)
78
- )
79
- const utxos = await getUTXOs(publicClient, { address })
80
- expect(utxos.length).toBeGreaterThan(0)
81
- expect(utxos[0]).toMatchObject({
82
- blockHeight: expect.any(Number),
83
- scriptHex: expect.any(String),
84
- txId: expect.any(String),
85
- value: expect.any(Number),
86
- vout: expect.any(Number),
87
- })
88
- })
89
-
90
- it('should throw error when minValue exceeds balance', async () => {
91
- vi.spyOn(global, 'fetch').mockResolvedValue(
92
- createMockResponse(getUTXOsValidReponse as BlockcypherUTXOsResponse)
93
- )
94
- const hugeValue = 999999999999999999n
95
- await expect(
96
- getUTXOs(publicClient, {
97
- address,
98
- minValue: Number(hugeValue),
99
- })
100
- ).rejects.toThrow(InsufficientUTXOBalanceError)
101
- })
102
-
103
- it('should handle empty UTXO', async () => {
104
- vi.spyOn(global, 'fetch').mockResolvedValue(
105
- createMockResponse(getUTXOsEmptyReponse as BlockcypherBalanceResponse)
106
- )
107
- const emptyAddress = '12LRT14SgNFFQ3hMRThAyXNao24BBy5cyU'
108
- const utxos = await getUTXOs(publicClient, { address: emptyAddress })
109
- expect(utxos.length).toBe(0)
110
- })
111
-
112
- it('should handle pagination correcly', async () => {
113
- const addressWithManyUTXOs = '1GrwDkr33gT6LuumniYjKEGjTLhsL5kmqC'
114
- const minValue = 5_610_592_350
115
- vi.spyOn(global, 'fetch').mockResolvedValue(
116
- createMockResponse(getUTXOsPaginatedReponse as BlockcypherUTXOsResponse)
117
- )
118
-
119
- const utxos = await getUTXOs(publicClient, {
120
- address: addressWithManyUTXOs,
121
- minValue,
122
- })
123
-
124
- expect(utxos.length).toBeGreaterThan(0)
125
- expect(new Set(utxos.map((utxo) => utxo.txId)).size).toBe(utxos.length)
126
- expect(global.fetch).toHaveBeenCalled()
127
- const totalValue = utxos.reduce((sum, utxo) => sum + utxo.value, 0)
128
- expect(totalValue).toBeGreaterThanOrEqual(minValue)
129
- })
130
- })
131
-
132
- describe('getTransactionFee', () => {
133
- it('should fetch correct transaction fee for valid transaction', async () => {
134
- if (USE_MOCK) {
135
- getTransactionFeeValidResponse.hash = VALID_TX_ID
136
- getTransactionFeeValidResponse.fees = TX_FEE
137
- vi.spyOn(global, 'fetch').mockResolvedValue(
138
- createMockResponse(getTransactionFeeValidResponse)
139
- )
140
- }
141
-
142
- const result = await getTransactionFee(publicClient, {
143
- txId: VALID_TX_ID,
144
- })
145
- expect(result).toBeDefined()
146
- expect(result).toBe(BigInt(TX_FEE))
147
- })
148
-
149
- it('should throw error for non-existent transaction', async () => {
150
- if (USE_MOCK) {
151
- vi.spyOn(global, 'fetch').mockResolvedValue(
152
- createMockResponse(getTransactionFeeInvalidResponse)
153
- )
154
- }
155
-
156
- await expect(
157
- getTransactionFee(publicClient, { txId: INVALID_TX_ID })
158
- ).rejects.toThrow()
159
- })
160
- })
161
- })
@@ -1,128 +0,0 @@
1
- import { beforeEach, describe, expect, it, vi } from 'vitest'
2
- import { getUTXOs } from '../actions/getUTXOs.js'
3
- import { bitcoin } from '../chains/bitcoin.js'
4
- import { AllTransportsFailedError } from '../errors/transport.js'
5
- import { InsufficientUTXOBalanceError } from '../errors/utxo.js'
6
- import { createClient, rpcSchema } from '../factories/createClient.js'
7
- import { createMockResponse } from '../test/utils.js'
8
- import blockchairZeroBalanceResponse from './blockchair/__mocks__/getBalance/zeroBalance.json'
9
- import blockchairLimitedResponse from './blockchair/__mocks__/getUTXOs/rateLimited.json'
10
- import blockchairValidResponse from './blockchair/__mocks__/getUTXOs/valid.json'
11
- import { blockchair } from './blockchair/blockchair.js'
12
- import blockcypherLimitedResponse from './blockcypher/__mocks__/getUTXOs/rateLimited.json'
13
- import blockcypherValidResponse from './blockcypher/__mocks__/getUTXOs/valid.json'
14
- import { blockcypher } from './blockcypher/blockcypher.js'
15
- import { fallback } from './fallback.js'
16
- import type { UTXOSchema } from './types.js'
17
-
18
- const address = import.meta.env.VITE_TEST_ADDRESS
19
- const apiKey = import.meta.env.VITE_TEST_BLOCKCHAIR_KEY
20
- const blockCypherKey = import.meta.env.VITE_TEST_BLOCKCYPHER_API_KEY
21
-
22
- const publicClient = createClient({
23
- chain: bitcoin,
24
- rpcSchema: rpcSchema<UTXOSchema>(),
25
- transport: fallback([
26
- blockcypher({ apiKey: blockCypherKey }),
27
- blockchair({ apiKey }),
28
- ]),
29
- })
30
-
31
- const blockchairFirstClient = createClient({
32
- chain: bitcoin,
33
- rpcSchema: rpcSchema<UTXOSchema>(),
34
- transport: fallback([
35
- blockchair({ apiKey }),
36
- blockcypher({ apiKey: blockCypherKey }),
37
- ]),
38
- })
39
-
40
- describe('Fallback Transport', () => {
41
- beforeEach(() => {
42
- vi.restoreAllMocks()
43
- })
44
-
45
- describe('getUTXOs', () => {
46
- it('should use blockcypher when it succeeds', async () => {
47
- vi.spyOn(global, 'fetch').mockResolvedValue(
48
- createMockResponse(blockcypherValidResponse)
49
- )
50
-
51
- const utxos = await getUTXOs(publicClient, { address })
52
- expect(utxos.length).toBeGreaterThan(0)
53
- })
54
-
55
- it('should fallback to blockchair when blockcypher fails', async () => {
56
- vi.spyOn(global, 'fetch').mockImplementation((request) => {
57
- const url = new URL(request.toString())
58
- if (url.hostname.includes('blockcypher')) {
59
- return Promise.resolve(
60
- createMockResponse(blockcypherLimitedResponse, { status: 429 })
61
- )
62
- }
63
-
64
- return Promise.resolve(createMockResponse(blockchairValidResponse))
65
- })
66
-
67
- const utxos = await getUTXOs(publicClient, { address })
68
- expect(utxos.length).toBeGreaterThan(0)
69
- })
70
-
71
- it('blockchair first client should fallback to blockcypher when fetching with a zero balance address', async () => {
72
- vi.spyOn(global, 'fetch').mockImplementation((request) => {
73
- const url = new URL(request.toString())
74
- if (url.hostname.includes('blockcypher')) {
75
- return Promise.resolve(createMockResponse(blockcypherValidResponse))
76
- }
77
-
78
- return Promise.resolve(
79
- createMockResponse(blockchairZeroBalanceResponse)
80
- )
81
- })
82
- const utxos = await getUTXOs(blockchairFirstClient, { address })
83
- expect(utxos.length).toBeGreaterThan(0)
84
- })
85
-
86
- it('should throw error when both transports fail', async () => {
87
- vi.spyOn(global, 'fetch').mockImplementation((request) => {
88
- const url = new URL(request.toString())
89
- if (url.hostname.includes('blockcypher')) {
90
- return Promise.resolve(
91
- createMockResponse(blockcypherLimitedResponse, { status: 429 })
92
- )
93
- }
94
- return Promise.resolve(
95
- createMockResponse(blockchairLimitedResponse, { status: 429 })
96
- )
97
- })
98
-
99
- await expect(getUTXOs(publicClient, { address })).rejects.toThrow(
100
- AllTransportsFailedError
101
- )
102
- })
103
-
104
- it('should not call blockchair if user has insufficientUTXOs', async () => {
105
- const blockchairSpy = vi
106
- .spyOn(global, 'fetch')
107
- .mockImplementation((request) => {
108
- const url = new URL(request.toString())
109
- if (url.hostname.includes('blockcypher')) {
110
- return Promise.resolve(createMockResponse(blockcypherValidResponse))
111
- }
112
-
113
- return Promise.resolve(createMockResponse(blockchairValidResponse))
114
- })
115
-
116
- await expect(
117
- getUTXOs(publicClient, {
118
- address,
119
- minValue: 1000000,
120
- })
121
- ).rejects.toThrow(InsufficientUTXOBalanceError)
122
-
123
- expect(blockchairSpy).not.toHaveBeenCalledWith(
124
- expect.stringContaining('blockchair')
125
- )
126
- })
127
- })
128
- })
@@ -1 +0,0 @@
1
- "Invalid Bitcoin address"
@@ -1,17 +0,0 @@
1
- {
2
- "address": "bc1qpvk0kjdg0kantu9z78qz7gqk53q643auz33yaw",
3
- "chain_stats": {
4
- "funded_txo_count": 18,
5
- "funded_txo_sum": 424052,
6
- "spent_txo_count": 17,
7
- "spent_txo_sum": 390846,
8
- "tx_count": 19
9
- },
10
- "mempool_stats": {
11
- "funded_txo_count": 0,
12
- "funded_txo_sum": 0,
13
- "spent_txo_count": 0,
14
- "spent_txo_sum": 0,
15
- "tx_count": 0
16
- }
17
- }
@@ -1 +0,0 @@
1
- "Invalid hex string"
@@ -1,58 +0,0 @@
1
- {
2
- "txid": "4b6ee974f1dd179071d027562e1fd1c83965efa4a171ec84f00b6c638e36fa4e",
3
- "version": 2,
4
- "locktime": 0,
5
- "vin": [
6
- {
7
- "txid": "e77cbe6d061f43672968834bce324a1984797f5cfbb463697df238bd385917be",
8
- "vout": 0,
9
- "prevout": {
10
- "scriptpubkey": "00140b2cfb49a87dbb35f0a2f1c02f2016a441aac7bc",
11
- "scriptpubkey_asm": "OP_0 OP_PUSHBYTES_20 0b2cfb49a87dbb35f0a2f1c02f2016a441aac7bc",
12
- "scriptpubkey_type": "v0_p2wpkh",
13
- "scriptpubkey_address": "bc1qpvk0kjdg0kantu9z78qz7gqk53q643auz33yaw",
14
- "value": 47580
15
- },
16
- "scriptsig": "",
17
- "scriptsig_asm": "",
18
- "witness": [
19
- "3045022100f7f01395cd1522fa63977f658bc72410a59e576b35cbf2a606dad1ed98e9c01402201d7994777edf3967ea2cf90e9f95eb9b9b5e6635aa934defb0094f7b313609e301",
20
- "025873f7163097c81372cb414f25e79204a422fbcf43495a18d8043466fd4e7c99"
21
- ],
22
- "is_coinbase": false,
23
- "sequence": 4294967293
24
- }
25
- ],
26
- "vout": [
27
- {
28
- "scriptpubkey": "001496d086eea328c1648231a3bca6f395f44fa95dae",
29
- "scriptpubkey_asm": "OP_0 OP_PUSHBYTES_20 96d086eea328c1648231a3bca6f395f44fa95dae",
30
- "scriptpubkey_type": "v0_p2wpkh",
31
- "scriptpubkey_address": "bc1qjmggdm4r9rqkfq335w72duu47386jhdw6wye0m",
32
- "value": 10000
33
- },
34
- {
35
- "scriptpubkey": "6a473d3a613a3078424435354332463330364339374664316433453741303233663763343833346132463437323833343a3a6c6966692f2d5f3a302f32307c30783134323835626439",
36
- "scriptpubkey_asm": "OP_RETURN OP_PUSHBYTES_71 3d3a613a3078424435354332463330364339374664316433453741303233663763343833346132463437323833343a3a6c6966692f2d5f3a302f32307c30783134323835626439",
37
- "scriptpubkey_type": "op_return",
38
- "value": 0
39
- },
40
- {
41
- "scriptpubkey": "00140b2cfb49a87dbb35f0a2f1c02f2016a441aac7bc",
42
- "scriptpubkey_asm": "OP_0 OP_PUSHBYTES_20 0b2cfb49a87dbb35f0a2f1c02f2016a441aac7bc",
43
- "scriptpubkey_type": "v0_p2wpkh",
44
- "scriptpubkey_address": "bc1qpvk0kjdg0kantu9z78qz7gqk53q643auz33yaw",
45
- "value": 33206
46
- }
47
- ],
48
- "size": 305,
49
- "weight": 890,
50
- "sigops": 1,
51
- "fee": 4374,
52
- "status": {
53
- "confirmed": true,
54
- "block_height": 897002,
55
- "block_hash": "00000000000000000000aa525233832b8fcf408b8de79677c994b3a014686134",
56
- "block_time": 1747423060
57
- }
58
- }