@teleportdao/bitcoin 1.4.7 → 1.4.9

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 (34) hide show
  1. package/dist/bitcoin-base.d.ts.map +1 -1
  2. package/dist/bitcoin-base.js +3 -1
  3. package/dist/bitcoin-base.js.map +1 -1
  4. package/dist/bitcoin-interface-utils.d.ts +2 -2
  5. package/dist/bitcoin-interface.d.ts +8 -61
  6. package/dist/bitcoin-interface.d.ts.map +1 -1
  7. package/dist/bitcoin-interface.js +8 -8
  8. package/dist/bitcoin-interface.js.map +1 -1
  9. package/dist/bitcoin-utils-2.d.ts +2 -0
  10. package/dist/bitcoin-utils-2.d.ts.map +1 -0
  11. package/dist/bitcoin-utils-2.js +13 -0
  12. package/dist/bitcoin-utils-2.js.map +1 -0
  13. package/dist/bitcoin-utils.d.ts +6 -6
  14. package/dist/bitcoin-utils.d.ts.map +1 -1
  15. package/dist/bitcoin-utils.js +58 -31
  16. package/dist/bitcoin-utils.js.map +1 -1
  17. package/dist/bundle.js +9 -5
  18. package/dist/mempool-space.d.ts +69 -0
  19. package/dist/mempool-space.d.ts.map +1 -0
  20. package/dist/mempool-space.js +266 -0
  21. package/dist/mempool-space.js.map +1 -0
  22. package/dist/sign/sign-transaction.d.ts.map +1 -1
  23. package/dist/sign/sign-transaction.js +60 -2
  24. package/dist/sign/sign-transaction.js.map +1 -1
  25. package/dist/transaction-builder/transaction-builder.d.ts.map +1 -1
  26. package/dist/transaction-builder/transaction-builder.js +23 -21
  27. package/dist/transaction-builder/transaction-builder.js.map +1 -1
  28. package/package.json +15 -11
  29. package/src/bitcoin-base.ts +5 -2
  30. package/src/bitcoin-interface.ts +16 -15
  31. package/src/bitcoin-utils.ts +72 -73
  32. package/src/mempool-space.ts +255 -0
  33. package/src/sign/sign-transaction.ts +49 -48
  34. package/src/transaction-builder/transaction-builder.ts +38 -20
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@teleportdao/bitcoin",
3
- "version": "1.4.7",
3
+ "version": "1.4.9",
4
4
  "description": "teleswap bitcoin package",
5
5
  "main": "dist/index.js",
6
6
  "browser": "dist/bundle.js",
@@ -8,30 +8,34 @@
8
8
  "scripts": {
9
9
  "test": "echo \"Error: no test specified\" && exit 2",
10
10
  "build:tsc": "tsc",
11
- "build:watch": "npx webpack --watch",
11
+ "build:watch": "npx tsc --watch",
12
12
  "build": "npx tsc && npx webpack"
13
13
  },
14
14
  "author": "",
15
15
  "license": "ISC",
16
16
  "dependencies": {
17
+ "@bitcoinerlab/secp256k1": "^1.0.5",
17
18
  "@teleportdao/configs": "^1.4.6",
18
- "@teleportdao/providers": "^1.4.6",
19
+ "@teleportdao/providers": "^1.4.9",
19
20
  "axios": "^0.27.2",
20
21
  "bignumber.js": "^9.1.1",
21
- "bip32": "^2.0.6",
22
- "bip39": "^3.0.4",
23
- "bitcoinjs-lib": "^5.2.0",
24
- "buffer": "^6.0.3",
22
+ "bip32": "^4.0.0",
23
+ "bip39": "^3.1.0",
24
+ "bitcoinjs-ecpair": "npm:bitcoinjs-lib@^5.2.0",
25
+ "bitcoinjs-lib": "^6.1.5",
25
26
  "coinselect": "^3.1.13",
26
- "ecpair": "^2.1.0",
27
+ "ecpair": "^2.0.1",
27
28
  "merkle-lib": "^2.0.10",
28
29
  "merkle-patricia-tree": "^2.3.2",
29
- "stream": "^0.0.2",
30
- "tiny-secp256k1": "^2.2.1",
30
+ "npm": "^10.2.3",
31
+ "uninstall": "^0.0.0",
31
32
  "varuint-bitcoin": "^1.1.2"
32
33
  },
33
34
  "publishConfig": {
34
35
  "access": "public"
35
36
  },
36
- "gitHead": "a32e568d407d5718e12599fabc55ee0166918f40"
37
+ "gitHead": "cb98230f4b9dddad7318f3830bc1890e20a3cda4",
38
+ "devDependencies": {
39
+ "@babel/preset-react": "^7.23.3"
40
+ }
37
41
  }
@@ -6,13 +6,17 @@ import type { ExtendedUtxo, SignerInfo, Target } from "./transaction-builder/tra
6
6
  import BitcoinSign from "./sign/sign-transaction"
7
7
 
8
8
  import * as bip39 from "bip39"
9
- import * as bip32 from "bip32"
10
9
  import { hdWalletPath } from "@teleportdao/configs"
11
10
  import { getPubKeyFromPrivateKeyHex } from "./bitcoin-utils"
12
11
  import networks from "./utils/networks"
13
12
  import { Network, Payment } from "bitcoinjs-lib"
14
13
  import { BitcoinInterface } from "./bitcoin-interface"
15
14
 
15
+ import BIP32Factory from "bip32"
16
+ import ecc from "@bitcoinerlab/secp256k1"
17
+
18
+ const bip32 = BIP32Factory(ecc)
19
+
16
20
  class BitcoinBase {
17
21
  network: Network
18
22
  hdWalletPath: {
@@ -244,5 +248,4 @@ class BitcoinBase {
244
248
  return txId
245
249
  }
246
250
  }
247
-
248
251
  export { BitcoinBase }
@@ -11,14 +11,15 @@ import { getBurnTransactionInfo } from "./helper/burn-request-helper"
11
11
  import { BitcoinInterfaceUtils } from "./bitcoin-interface-utils"
12
12
  import type { BitcoinConnectionInfo } from "./transaction-builder/bitcoin-transaction-builder"
13
13
  import type { SignerInfo } from "./transaction-builder/transaction-builder"
14
+ import ms from "./mempool-space"
14
15
 
15
16
  export class BitcoinInterface extends BitcoinInterfaceUtils {
16
17
  rpcProvider?: bitcoinProvider.RPC
17
18
  apiProviderName!: string
18
19
  // todo : add provider type
19
20
  minTeleporterFeeAmount: number
20
- provider: bitcoinProvider.ApiProviders.BlockStream | bitcoinProvider.RPC
21
- apiProvider!: bitcoinProvider.ApiProviders.BlockStream
21
+ provider: any
22
+ apiProvider!: bitcoinProvider.ApiProviders.BlockStream | bitcoinProvider.ApiProviders.NowNodes
22
23
  constructor(
23
24
  connectionInfo: BitcoinConnectionInfo,
24
25
  networkName: string,
@@ -33,7 +34,7 @@ export class BitcoinInterface extends BitcoinInterfaceUtils {
33
34
 
34
35
  if (connectionInfo.api.enabled) {
35
36
  this.apiProviderName = connectionInfo.api.provider
36
- this.apiProvider = bitcoinProvider.getApiProvider(connectionInfo.api as any, networkName)
37
+ this.apiProvider = bitcoinProvider.getApiProvider(connectionInfo.api as any, networkName)!
37
38
  }
38
39
 
39
40
  this.minTeleporterFeeAmount = config.minTeleporterFeeAmount
@@ -63,12 +64,8 @@ export class BitcoinInterface extends BitcoinInterfaceUtils {
63
64
  }
64
65
 
65
66
  // speed : low normal fast
66
- async getFeeRate(speed: "normal" | "slow" | "fast" = "normal") {
67
- if (!(speed === "normal" || speed === "slow" || speed === "fast")) {
68
- throw new Error("incorrect speed")
69
- }
70
- let fee = await this.provider.getFeeRate(speed)
71
- return +fee
67
+ async getFeeRate(speed?: "normal" | "slow" | "fast") {
68
+ return new ms(this.testnet).getRecommendedFeeRate(speed)
72
69
  }
73
70
 
74
71
  // ----------- specific
@@ -219,7 +216,7 @@ export class BitcoinInterface extends BitcoinInterfaceUtils {
219
216
  results.push(
220
217
  result
221
218
  .map((utxos, i) =>
222
- utxos.map((tx) => ({
219
+ utxos.map((tx: any) => ({
223
220
  hash: tx.txId,
224
221
  value: tx.value,
225
222
  index: tx.index,
@@ -237,7 +234,7 @@ export class BitcoinInterface extends BitcoinInterfaceUtils {
237
234
  throw new Error("this function need an api provider")
238
235
  }
239
236
  let utxos = (await this.apiProvider.getUtxos(address)) ?? []
240
- return utxos.reduce((a, tx) => a + Number(tx.value), 0)
237
+ return utxos.reduce((a: any, tx: any) => a + Number(tx.value), 0)
241
238
  }
242
239
 
243
240
  // ------------------ utxo provider + rpc or blockstream----------------
@@ -269,9 +266,11 @@ export class BitcoinInterface extends BitcoinInterfaceUtils {
269
266
  }
270
267
  let blockTxs = []
271
268
  for (let blockNumber = +startBlockNumber + 1; blockNumber <= endBlockNumber; blockNumber += 1) {
272
- const response = this.getBlockTransactions(addresses, blockNumber, inputTxIds)
269
+ console.log(blockNumber)
270
+
271
+ const response = await this.getBlockTransactions(addresses, blockNumber, inputTxIds)
273
272
  blockTxs.push(response)
274
- await sleep(200)
273
+ // await sleep(200)
275
274
  }
276
275
  blockTxs = await Promise.all(blockTxs)
277
276
  return blockTxs.flat(1)
@@ -291,7 +290,7 @@ export class BitcoinInterface extends BitcoinInterfaceUtils {
291
290
  if (this.apiProviderName !== "BlockStream") {
292
291
  throw new Error("just support BlockStream as api provider for this function")
293
292
  }
294
- let txs = await this.apiProvider.getTransactionHistoryForMultipleAddresses(
293
+ let txs = await (this.apiProvider as any).getTransactionHistoryForMultipleAddresses(
295
294
  addresses,
296
295
  startBlockNumber,
297
296
  )
@@ -303,7 +302,9 @@ export class BitcoinInterface extends BitcoinInterfaceUtils {
303
302
  if (this.apiProviderName !== "BlockStream") {
304
303
  throw new Error("teleporter just support BlockStream as api provider")
305
304
  }
306
- let txs = await this.apiProvider.getMempoolTransactionHistoryForMultipleAddresses(addresses)
305
+ let txs = await (this.apiProvider as any).getMempoolTransactionHistoryForMultipleAddresses(
306
+ addresses,
307
+ )
307
308
  return txs.flat(1)
308
309
  }
309
310
 
@@ -1,15 +1,13 @@
1
- import * as bip39 from "bip39"
2
- import * as bip32 from "bip32"
3
1
  import networks from "./utils/networks"
4
2
 
5
- // import BIP32Factory from "bip32"
6
- // import ECPairFactory from "ecpair"
7
- // import * as ecc from "tiny-secp256k1"
3
+ import * as bip39 from "bip39"
4
+ import BIP32Factory from "bip32"
5
+ import * as ecc from "@bitcoinerlab/secp256k1"
8
6
  import * as bitcoin from "bitcoinjs-lib"
7
+ import * as bitcoinEcPair from "bitcoinjs-ecpair"
9
8
 
10
- // bitcoin.initEccLib(ecc)
11
- // const bip32 = BIP32Factory(ecc)
12
- const ECPair = bitcoin.ECPair
9
+ const bip32 = BIP32Factory(ecc)
10
+ const ECPair = bitcoinEcPair.ECPair
13
11
 
14
12
  let varUnit = require("varuint-bitcoin")
15
13
  const fastRoot = require("merkle-lib/fastRoot")
@@ -46,6 +44,44 @@ export function generateMnemonic() {
46
44
  return mnemonic
47
45
  }
48
46
 
47
+ export function reverseBytes(hexInput: string) {
48
+ return Buffer.from(hexInput, "hex").reverse().toString("hex")
49
+ }
50
+
51
+ export function getPublicKeyHexByXpubAndIndex(
52
+ xpub: string,
53
+ index = 0,
54
+ isChange = false,
55
+ network = networks.bitcoin,
56
+ ) {
57
+ const node = bip32.fromBase58(xpub, network)
58
+ return node
59
+ .derive(isChange ? 1 : 0)
60
+ .derive(index)
61
+ .publicKey.toString("hex")
62
+ }
63
+
64
+ export function getPubKeyFromPrivateKeyWIF(
65
+ privateKeyWIF: string,
66
+ network = bitcoin.networks.bitcoin,
67
+ ) {
68
+ let key = ECPair.fromWIF(privateKeyWIF, network)
69
+ return key.publicKey
70
+ }
71
+
72
+ export function getPubKeyFromPrivateKeyHex(
73
+ privateKeyHex: string,
74
+ network = bitcoin.networks.bitcoin,
75
+ ) {
76
+ let key = ECPair.fromPrivateKey(Buffer.from(privateKeyHex, "hex"), { network })
77
+ return key.publicKey
78
+ }
79
+
80
+ export function getPrivateKeyHexFromWIF(privateKeyWIF: string, network = bitcoin.networks.bitcoin) {
81
+ let key = ECPair.fromWIF(privateKeyWIF, network)
82
+ return key.privateKey!.toString("hex")
83
+ }
84
+
49
85
  export function parseRawTransaction(rawTransaction: string) {
50
86
  const size = {
51
87
  version: 4,
@@ -102,44 +138,6 @@ export function parseRawTransaction(rawTransaction: string) {
102
138
  return { version, flag, vin, vout, witness, locktime }
103
139
  }
104
140
 
105
- export function reverseBytes(hexInput: string) {
106
- return Buffer.from(hexInput, "hex").reverse().toString("hex")
107
- }
108
-
109
- export function getPublicKeyHexByXpubAndIndex(
110
- xpub: string,
111
- index = 0,
112
- isChange = false,
113
- network = networks.bitcoin,
114
- ) {
115
- const node = bip32.fromBase58(xpub, network)
116
- return node
117
- .derive(isChange ? 1 : 0)
118
- .derive(index)
119
- .publicKey.toString("hex")
120
- }
121
-
122
- export function getPubKeyFromPrivateKeyWIF(
123
- privateKeyWIF: string,
124
- network = bitcoin.networks.bitcoin,
125
- ) {
126
- let key = bitcoin.ECPair.fromWIF(privateKeyWIF, network)
127
- return key.publicKey
128
- }
129
-
130
- export function getPubKeyFromPrivateKeyHex(
131
- privateKeyHex: string,
132
- network = bitcoin.networks.bitcoin,
133
- ) {
134
- let key = bitcoin.ECPair.fromPrivateKey(Buffer.from(privateKeyHex, "hex"), { network })
135
- return key.publicKey
136
- }
137
-
138
- export function getPrivateKeyHexFromWIF(privateKeyWIF: string, network = bitcoin.networks.bitcoin) {
139
- let key = bitcoin.ECPair.fromWIF(privateKeyWIF, network)
140
- return key.privateKey!.toString("hex")
141
- }
142
-
143
141
  export function calculateMerkleProof(
144
142
  blockTransactions: string[],
145
143
  txId: string,
@@ -202,6 +200,7 @@ export function parseBlockHeader(headerHex: string) {
202
200
  }
203
201
  }
204
202
 
203
+ // used in block parser functions ( newt 2 functions )
205
204
  export function convertBitcoinScriptToAddress(script: Buffer, network = bitcoin.networks.bitcoin) {
206
205
  try {
207
206
  return bitcoin.address.fromOutputScript(script, network)
@@ -414,11 +413,11 @@ function toXOnlyPublicKey(pubKey: Buffer) {
414
413
 
415
414
  export function getAddressType(address: string, network = bitcoin.networks.bitcoin) {
416
415
  if (address.startsWith(`${network.bech32}1p`)) {
417
- // todo : check length - it could be p2wsh
416
+ // todo validate p2tr address
418
417
  return "p2tr"
419
418
  }
420
419
  if (address.startsWith(network.bech32)) {
421
- // todo : check length - it could be p2wsh
420
+ bitcoin.address.fromBech32(address)
422
421
  return "p2wpkh"
423
422
  }
424
423
  let base58Data = bitcoin.address.fromBase58Check(address)
@@ -462,12 +461,12 @@ export function createAddressObjectByScript(
462
461
  network,
463
462
  })
464
463
  break
465
- // case "p2tr":
466
- // addressObject = bitcoin.payments.p2tr({
467
- // output: script,
468
- // network,
469
- // })
470
- // break
464
+ case "p2tr":
465
+ addressObject = bitcoin.payments.p2tr({
466
+ output: script,
467
+ network,
468
+ })
469
+ break
471
470
  default:
472
471
  throw new Error("address type is incorrect")
473
472
  }
@@ -504,13 +503,13 @@ export function createAddressObjectByHash(
504
503
  network,
505
504
  })
506
505
  break
507
- // case "p2tr":
508
- // // here hash is the public key of tweaked private key
509
- // addressObject = bitcoin.payments.p2tr({
510
- // pubkey: hash,
511
- // network,
512
- // })
513
- // break
506
+ case "p2tr":
507
+ // here hash is the public key of tweaked private key (internal public key)
508
+ addressObject = bitcoin.payments.p2tr({
509
+ pubkey: hash,
510
+ network,
511
+ })
512
+ break
514
513
  default:
515
514
  throw new Error("address type is incorrect")
516
515
  }
@@ -544,12 +543,12 @@ export function createAddressObjectByPublicKey(
544
543
  })
545
544
  break
546
545
  case "p2tr":
547
- // // this public key is public key of main private key
548
- // addressObject = bitcoin.payments.p2tr({
549
- // internalPubkey: toXOnlyPublicKey(publicKey),
550
- // network,
551
- // })
552
- // break
546
+ // this public key is public key of main private key
547
+ addressObject = bitcoin.payments.p2tr({
548
+ internalPubkey: toXOnlyPublicKey(publicKey),
549
+ network,
550
+ })
551
+ break
553
552
  default:
554
553
  throw new Error("address type is incorrect")
555
554
  }
@@ -578,12 +577,12 @@ export function createAddressObjectByAddress(address: string, network = bitcoin.
578
577
  network,
579
578
  })
580
579
  break
581
- // case "p2tr":
582
- // addressObject = bitcoin.payments.p2tr({
583
- // address,
584
- // network,
585
- // })
586
- // break
580
+ case "p2tr":
581
+ addressObject = bitcoin.payments.p2tr({
582
+ address,
583
+ network,
584
+ })
585
+ break
587
586
  default:
588
587
  throw new Error("address type is incorrect")
589
588
  }
@@ -0,0 +1,255 @@
1
+ import { AxiosInstance } from "axios"
2
+ import { getAxiosInstance } from "./utils/tools"
3
+
4
+ class BlockStream {
5
+ api: AxiosInstance
6
+ constructor(
7
+ testnet = false,
8
+ // not used yet
9
+ _config?: {
10
+ token?: string
11
+ },
12
+ ) {
13
+ const baseUrl = testnet
14
+ ? "https://mempool.space/testnet/api/v1"
15
+ : "https://mempool.space/api/v1"
16
+ this.api = getAxiosInstance({
17
+ baseUrl,
18
+ } as any)
19
+ }
20
+
21
+ async getOutspend(txId: string, index: number) {
22
+ let response = await this.api.get(`/tx/${txId}/outspend/${index}`)
23
+ return response.data
24
+ }
25
+ async getOutspends(txId: string) {
26
+ let response = await this.api.get(`/tx/${txId}/outspends`)
27
+ return response.data
28
+ }
29
+
30
+ async getLatestBlockNumber() {
31
+ const result = await this.api.get(`/blocks/tip/height`)
32
+ return result.data
33
+ }
34
+
35
+ async getBlockHash(blockNumber: number) {
36
+ const result = await this.api.get(`/block-height/${blockNumber}`)
37
+ return result.data
38
+ }
39
+
40
+ async getBlockHeaderHex(blockNumber: number) {
41
+ const hash = await this.getBlockHash(blockNumber)
42
+ const result = await this.api.get(`/block/${hash}/header`)
43
+ return result.data
44
+ }
45
+
46
+ // --------------
47
+
48
+ async getConfirmedTransactions(userAddress: string, lastReceivedTxId = "") {
49
+ const result = await this.api.get(`/address/${userAddress}/txs/chain/${lastReceivedTxId}`)
50
+ return result.data
51
+ }
52
+
53
+ async getMempoolTransactions(userAddress: string) {
54
+ const result = await this.api.get(`/address/${userAddress}/txs/mempool`)
55
+ return result.data
56
+ }
57
+
58
+ async getTransaction(txId: string) {
59
+ const result = await this.api.get(`/tx/${txId}`)
60
+ let tx = result.data
61
+ return {
62
+ txId: tx.txid,
63
+ version: tx.version,
64
+ locktime: tx.locktime,
65
+ blockTime: tx.status.block_time,
66
+ blockNumber: tx.status.block_height || null,
67
+ blockHash: tx.status.block_hash || null,
68
+ vout: tx.vout.map((vo: any) => ({
69
+ address: vo.scriptpubkey_address || null,
70
+ script: vo.scriptpubkey,
71
+ value: vo.value,
72
+ })),
73
+ vin: tx.vin.map((vi: any) => ({
74
+ txId: vi.txid,
75
+ index: vi.vout,
76
+ address: vi.prevout.scriptpubkey_address || null,
77
+ script: vi.prevout.scriptpubkey,
78
+ value: vi.prevout.value,
79
+ })),
80
+ }
81
+ }
82
+
83
+ async getRawTransaction(txId: string) {
84
+ const result = await this.api.get(`/tx/${txId}/hex`)
85
+ return result.data
86
+ }
87
+
88
+ async getTransactionHistory(userAddress: string, blockNumber = 0, lastSeenTxId = undefined) {
89
+ let maximumTxsLength = 15
90
+ // get transactions from lastSeenTxId to the end
91
+ let fetchTxs = true
92
+ let allResults = []
93
+ let lastReceivedTxId = ""
94
+ while (fetchTxs) {
95
+ let result = await this.getConfirmedTransactions(userAddress, lastReceivedTxId)
96
+ let lastSeenTxIdIndex = result.findIndex((tx: any) => tx.txid === lastSeenTxId)
97
+ result = result.filter((_value: any) => +_value.status.block_height > blockNumber)
98
+ result =
99
+ lastSeenTxIdIndex < 0
100
+ ? result
101
+ : result.filter((_value: any, index: number) => index < lastSeenTxIdIndex)
102
+ allResults.push(...result)
103
+ lastReceivedTxId = result[result.length - 1]?.txid
104
+ fetchTxs = result.length === maximumTxsLength && lastSeenTxIdIndex < 0 && result.length !== 0
105
+ }
106
+
107
+ return allResults.map((tx) => ({
108
+ address: userAddress,
109
+ txId: tx.txid,
110
+ version: tx.version,
111
+ locktime: tx.locktime,
112
+ blockNumber: tx.status.block_height || null,
113
+ blockHash: tx.status.block_hash || null,
114
+ blockTime: tx.status.block_time || null,
115
+ vout: tx.vout.map((vo: any) => ({
116
+ address: vo.scriptpubkey_address || null,
117
+ script: vo.scriptpubkey,
118
+ value: vo.value,
119
+ })),
120
+ vin: tx.vin.map((vi: any) => ({
121
+ txId: vi.txid,
122
+ index: vi.vout,
123
+ address: vi.prevout.scriptpubkey_address || null,
124
+ script: vi.prevout.scriptpubkey,
125
+ value: vi.prevout.value,
126
+ })),
127
+ }))
128
+ }
129
+
130
+ async getMempoolTransactionHistory(userAddress: string) {
131
+ let result = await this.getMempoolTransactions(userAddress)
132
+ return result.map((tx: any) => ({
133
+ address: userAddress,
134
+ txId: tx.txid,
135
+ version: tx.version,
136
+ locktime: tx.locktime,
137
+ vout: tx.vout.map((vo: any) => ({
138
+ address: vo.scriptpubkey_address || null,
139
+ script: vo.scriptpubkey,
140
+ value: vo.value,
141
+ })),
142
+ vin: tx.vin.map((vi: any) => ({
143
+ txId: vi.txid,
144
+ index: vi.vout,
145
+ address: vi.prevout.scriptpubkey_address || null,
146
+ script: vi.prevout.scriptpubkey,
147
+ value: vi.prevout.value,
148
+ })),
149
+ }))
150
+ }
151
+
152
+ async getMempoolTransactionHistoryForMultipleAddresses(addresses: string[], blockNumber = 0) {
153
+ const allPromises = []
154
+ for (let address of addresses) {
155
+ let promise = await this.getMempoolTransactionHistory(address)
156
+ allPromises.push(promise)
157
+ }
158
+ let result = await Promise.all(allPromises)
159
+ return result
160
+ }
161
+
162
+ async getTransactionHistoryForMultipleAddresses(userAddresses: string[], blockNumber = 0) {
163
+ const allPromises = []
164
+ for (let address of userAddresses) {
165
+ let promise = await this.getTransactionHistory(address, blockNumber)
166
+ allPromises.push(promise)
167
+ }
168
+ let result = await Promise.all(allPromises)
169
+ return result
170
+ }
171
+
172
+ async getUtxos(userAddress: string): Promise<
173
+ {
174
+ address: string
175
+ txId: string
176
+ index: number
177
+ value: number
178
+ blockNumber?: number
179
+ }[]
180
+ > {
181
+ const result = await this.api.get(`/address/${userAddress}/utxo`)
182
+ return result.data.map((tx: any) => ({
183
+ address: userAddress,
184
+ txId: tx.txid,
185
+ index: tx.vout,
186
+ value: tx.value,
187
+ blockNumber: tx.status?.block_height || undefined,
188
+ }))
189
+ }
190
+
191
+ async getBalance(address: string) {
192
+ let utxos = await this.getUtxos(address)
193
+ return utxos.reduce((a: any, tx: any) => a + Number(tx.value), 0)
194
+ }
195
+
196
+ async getBlockTransactionIds(blockHash: string) {
197
+ let result = await this.api.get(`/block/${blockHash}/txids`)
198
+ return result.data
199
+ }
200
+
201
+ async getFeeRate(speed: "normal" | "slow" | "fast" = "normal") {
202
+ let result = await this.api.get(`/fee-estimates`)
203
+ let fees = {
204
+ slow: +result.data[10],
205
+ normal: +result.data[6],
206
+ fast: +result.data[3],
207
+ }
208
+ return fees[speed] || fees.normal
209
+ }
210
+ async getRecommendedFeeRate(speed: "normal" | "slow" | "fast" = "normal") {
211
+ let result = await this.api.get(`/fees/recommended`)
212
+
213
+ let fees = {
214
+ slow: +result.data.economyFee,
215
+ normal: +result.data.halfHourFee,
216
+ fast: +result.data.fastestFee,
217
+ }
218
+ return fees[speed] || fees.normal
219
+ }
220
+
221
+ async sendRawTransaction(rawTransaction: string) {
222
+ const result = await this.api.post(`/tx`, rawTransaction)
223
+ return result.data
224
+ }
225
+
226
+ // not used
227
+
228
+ async getMerkleProof(txId: string) {
229
+ let result = (await this.api.get(`/tx/${txId}/merkle-proof`)).data
230
+ let intermediateNodes = result.merkle.reduce(
231
+ (a: any, merkle: any) => a + Buffer.from(merkle, "hex").reverse().toString("hex"),
232
+ "0x",
233
+ )
234
+ let transactionIndex = result.pos
235
+ return {
236
+ intermediateNodes,
237
+ transactionIndex,
238
+ }
239
+ }
240
+
241
+ async getLatestBlock() {
242
+ const result = await this.api.get(`/blocks`)
243
+ // 10 newest blocks
244
+ const blocks = result.data
245
+ return blocks[0]
246
+ }
247
+
248
+ async getBlock(blockNumber: number) {
249
+ const blockHash = await this.getBlockHash(blockNumber)
250
+ const result = await this.api.get(`/block/${blockHash}`)
251
+ return result.data
252
+ }
253
+ }
254
+
255
+ export default BlockStream