@teleportdao/bitcoin 1.4.8 → 1.5.0

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 (37) hide show
  1. package/.tmp/check.ts +16 -0
  2. package/dist/bitcoin-base.d.ts +7 -0
  3. package/dist/bitcoin-base.d.ts.map +1 -1
  4. package/dist/bitcoin-base.js +21 -1
  5. package/dist/bitcoin-base.js.map +1 -1
  6. package/dist/bitcoin-interface-utils.d.ts +2 -2
  7. package/dist/bitcoin-interface.d.ts +2 -2
  8. package/dist/bitcoin-interface.d.ts.map +1 -1
  9. package/dist/bitcoin-interface.js +6 -9
  10. package/dist/bitcoin-interface.js.map +1 -1
  11. package/dist/bitcoin-utils-2.d.ts +2 -0
  12. package/dist/bitcoin-utils-2.d.ts.map +1 -0
  13. package/dist/bitcoin-utils-2.js +13 -0
  14. package/dist/bitcoin-utils-2.js.map +1 -0
  15. package/dist/bitcoin-utils.d.ts +6 -6
  16. package/dist/bitcoin-utils.d.ts.map +1 -1
  17. package/dist/bitcoin-utils.js +58 -31
  18. package/dist/bitcoin-utils.js.map +1 -1
  19. package/dist/bundle.js +9 -5
  20. package/dist/helper/teleport-request-helper.d.ts.map +1 -1
  21. package/dist/helper/teleport-request-helper.js +2 -2
  22. package/dist/helper/teleport-request-helper.js.map +1 -1
  23. package/dist/sign/sign-transaction.d.ts.map +1 -1
  24. package/dist/sign/sign-transaction.js +60 -2
  25. package/dist/sign/sign-transaction.js.map +1 -1
  26. package/dist/teleport-dao-payments.d.ts +5 -3
  27. package/dist/teleport-dao-payments.d.ts.map +1 -1
  28. package/dist/teleport-dao-payments.js +6 -5
  29. package/dist/teleport-dao-payments.js.map +1 -1
  30. package/package.json +15 -11
  31. package/src/bitcoin-base.ts +29 -2
  32. package/src/bitcoin-interface.ts +18 -9
  33. package/src/bitcoin-utils.ts +72 -73
  34. package/src/helper/teleport-request-helper.js +5 -3
  35. package/src/sign/sign-transaction.ts +49 -48
  36. package/src/teleport-dao-payments.ts +8 -2
  37. package/src/mempool-space.ts +0 -255
@@ -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
  }
@@ -86,9 +86,11 @@ function parseRawRequest(opReturnData) {
86
86
  let appId = Number(`0x${appIdHex}`) // 2 bytes
87
87
 
88
88
  // get type base on appId
89
- let requestType = teleportRequestsType.find(
90
- (rs) => appId >= rs.appIdRange[0] && appId <= rs.appIdRange[1],
91
- )?.type
89
+ let requestType = Object.keys(teleportRequestsType).find(
90
+ (key) =>
91
+ appId >= teleportRequestsType[key].appIdRange[0] &&
92
+ appId <= teleportRequestsType[key].appIdRange[1],
93
+ )
92
94
 
93
95
  switch (requestType) {
94
96
  case "transfer":
@@ -1,16 +1,44 @@
1
- import { Psbt, crypto, Network, ECPair } from "bitcoinjs-lib"
2
- // import ECPairFactory from "ecpair"
3
- // import * as ecc from "tiny-secp256k1"
4
- import { ExtendedUnsignedTransaction } from "../transaction-builder/transaction-builder"
5
- // import * as bitcoin from "bitcoinjs-lib"
1
+ import { Psbt, crypto, Network } from "bitcoinjs-lib"
2
+ // import BIP32Factory from "bip32"
3
+ import ecc from "@bitcoinerlab/secp256k1"
4
+ import * as bitcoinEcPair from "bitcoinjs-ecpair"
5
+ const ECPair = bitcoinEcPair.ECPair
6
6
 
7
- // bitcoin.initEccLib(ecc)
8
- // // const bip32 = BIP32Factory(ecc)
9
- // const ECPair = ECPairFactory(ecc)
7
+ function tapTweakHash(pubKey: Buffer, h?: Buffer) {
8
+ return crypto.taggedHash("TapTweak", Buffer.concat(h ? [pubKey, h] : [pubKey]))
9
+ }
10
+
11
+ function tweakSigner(
12
+ privateKey: Buffer,
13
+ opts = {} as {
14
+ [key: string]: Buffer
15
+ },
16
+ network: Network,
17
+ ) {
18
+ let newPrv = privateKey
19
+ let keyPair = ECPair.fromPrivateKey(privateKey, {
20
+ network: network,
21
+ compressed: true,
22
+ })
23
+
24
+ if (!keyPair.privateKey) throw new Error("private key not exist")
25
+
26
+ if (keyPair.publicKey.toString("hex").startsWith("03")) {
27
+ newPrv = ecc.privateNegate(keyPair.privateKey) as Buffer
28
+ }
29
+
30
+ const tweakedPrivateKey = ecc.privateAdd(
31
+ newPrv,
32
+ tapTweakHash(Buffer.from(keyPair.publicKey.toString("hex").slice(2), "hex"), opts?.tweakHash),
33
+ )
34
+ if (!tweakedPrivateKey) {
35
+ throw new Error("Invalid tweaked private key!")
36
+ }
10
37
 
11
- // function tapTweakHash(pubKey: Buffer, h?: Buffer) {
12
- // return crypto.taggedHash('TapTweak', Buffer.concat(h ? [pubKey, h] : [pubKey]))
13
- // }
38
+ return ECPair.fromPrivateKey(Buffer.from(tweakedPrivateKey), {
39
+ network: network,
40
+ })
41
+ }
14
42
 
15
43
  class BitcoinLikeSignTransaction {
16
44
  network: Network
@@ -18,38 +46,6 @@ class BitcoinLikeSignTransaction {
18
46
  this.network = network
19
47
  }
20
48
 
21
- // tweakSigner(
22
- // privateKey: Buffer,
23
- // opts = {} as {
24
- // [key: string]: Buffer
25
- // },
26
- // ) {
27
- // let newPrv = privateKey
28
- // let keyPair = ECPair.fromPrivateKey(privateKey, {
29
- // network: this.network,
30
- // compressed: true,
31
- // })
32
-
33
- // if (!keyPair.privateKey) throw new Error("private key not exist")
34
-
35
- // if (keyPair.publicKey.toString("hex").startsWith("03")) {
36
- // newPrv = ecc.privateNegate(keyPair.privateKey) as Buffer
37
- // }
38
-
39
- // const tweakedPrivateKey = ecc.privateAdd(
40
- // newPrv,
41
- // tapTweakHash(Buffer.from(keyPair.publicKey.toString("hex").slice(2), "hex"), opts?.tweakHash),
42
- // )
43
- // if (!tweakedPrivateKey) {
44
- // throw new Error("Invalid tweaked private key!")
45
- // }
46
-
47
- // return ECPair.fromPrivateKey(Buffer.from(tweakedPrivateKey), {
48
- // network: this.network,
49
- // })
50
- // }
51
-
52
- // todo : change to psbt
53
49
  async signPsbt(
54
50
  unsignedPsbt: {
55
51
  unsignedTransaction: string
@@ -68,7 +64,13 @@ class BitcoinLikeSignTransaction {
68
64
  let numberOfInputs = psbt.inputCount
69
65
 
70
66
  for (let i = 0; i < numberOfInputs; i += 1) {
71
- await psbt.signInputAsync(i, keyPair)
67
+ let type = psbt.getInputType(i)
68
+ if (type === "nonstandard") {
69
+ let a = tweakSigner(privateKey, undefined, this.network)
70
+ await psbt.signInputAsync(i, a)
71
+ } else {
72
+ await psbt.signInputAsync(i, keyPair)
73
+ }
72
74
  }
73
75
 
74
76
  // psbt.signAllInputs(keyPair)
@@ -82,13 +84,12 @@ class BitcoinLikeSignTransaction {
82
84
  )
83
85
  const psbt =
84
86
  finals.length === 1 ? finals[0] : new Psbt({ network: this.network }).combine(...finals)
87
+
85
88
  psbt.finalizeAllInputs()
86
89
 
87
- // psbt.finalizeAllInputs()
88
- // const tx = psbt.extractTransaction()
89
- // const rawTx = tx.toBuffer()
90
- // const hex = rawTx.toString("hex")
91
90
  let finalizeTx = psbt.extractTransaction()
91
+ // const rawTx = finalizeTx.toBuffer()
92
+ // const hex = rawTx.toString("hex")
92
93
  return finalizeTx.toHex()
93
94
  }
94
95
  }
@@ -18,6 +18,7 @@ export type TransferRequest = {
18
18
  deadline?: number // 4 bytes
19
19
  isFixedToken?: boolean // 1 byte
20
20
  feeSpeed?: "normal" | "fast" | "slow"
21
+ staticFeeRate?: number
21
22
  }
22
23
  export class TeleportDaoPayment extends BitcoinBase {
23
24
  // payment
@@ -62,6 +63,7 @@ export class TeleportDaoPayment extends BitcoinBase {
62
63
  deadline, // 4 bytes
63
64
  isFixedToken = false, // 1 byte
64
65
  feeSpeed = "normal",
66
+ staticFeeRate,
65
67
  }: TransferRequest) {
66
68
  if (!this.currentAccount || !this.currentAccountType || !this.publicKey || !this.privateKey) {
67
69
  throw new Error("account not initialized")
@@ -89,6 +91,7 @@ export class TeleportDaoPayment extends BitcoinBase {
89
91
  deadline,
90
92
  isFixedToken,
91
93
  feeSpeed,
94
+ staticFeeRate,
92
95
  })
93
96
  let signedPsbt = await this.signer.signPsbt(unsignedTx, this.privateKey)
94
97
  let txId = await this.sendSignedPsbt(signedPsbt)
@@ -154,10 +157,11 @@ export class TeleportDaoPayment extends BitcoinBase {
154
157
  deadline = 0, // 4 bytes
155
158
  isFixedToken = false, // 1 byte
156
159
  feeSpeed = "normal",
160
+ staticFeeRate,
157
161
  }: TransferRequest & {
158
162
  extendedUtxo: ExtendedUtxo[]
159
163
  }) {
160
- let feeRate = await this.transactionBuilder._getFeeRate(feeSpeed)
164
+ let feeRate = staticFeeRate || (await this.transactionBuilder._getFeeRate(feeSpeed))
161
165
  let targets = await this.getBitcoinToEthTargetOutputs({
162
166
  lockerAddress,
163
167
  amount,
@@ -196,6 +200,7 @@ export class TeleportDaoPayment extends BitcoinBase {
196
200
  isBorrow = false,
197
201
  tokenAddress = "0x0000000000000000000000000000000000000000", // 20 bytes
198
202
  borrowAmount = 0, // 28 bytes
203
+ staticFeeRate,
199
204
  }: {
200
205
  lockerAddress: string
201
206
  amount: number
@@ -203,6 +208,7 @@ export class TeleportDaoPayment extends BitcoinBase {
203
208
  appId: number
204
209
  recipientAddress: string // 20 bytes
205
210
  percentageFee: number // 2 bytes in satoshi
211
+ staticFeeRate: number
206
212
  mode?: 0 | 1 | boolean // 1 byte
207
213
  isBorrow?: boolean
208
214
  tokenAddress?: string // 20 bytes
@@ -239,7 +245,7 @@ export class TeleportDaoPayment extends BitcoinBase {
239
245
  opTarget,
240
246
  ],
241
247
  changeAddress: this.currentAccount,
242
- feeRate: 1,
248
+ feeRate: staticFeeRate,
243
249
  fullAmount: false,
244
250
  })
245
251
  let signedPsbt = await this.signer.signPsbt(unsignedTx, this.privateKey)
@@ -1,255 +0,0 @@
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