@teleportdao/bitcoin 1.0.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.
- package/dist/bitcoin-base.d.ts +56 -0
- package/dist/bitcoin-base.d.ts.map +1 -0
- package/dist/bitcoin-base.js +138 -0
- package/dist/bitcoin-base.js.map +1 -0
- package/dist/bitcoin-interface-utils.d.ts +18 -0
- package/dist/bitcoin-interface-utils.d.ts.map +1 -0
- package/dist/bitcoin-interface-utils.js +31 -0
- package/dist/bitcoin-interface-utils.js.map +1 -0
- package/dist/bitcoin-interface.d.ts +154 -0
- package/dist/bitcoin-interface.d.ts.map +1 -0
- package/dist/bitcoin-interface.js +248 -0
- package/dist/bitcoin-interface.js.map +1 -0
- package/dist/bitcoin-utils.d.ts +70 -0
- package/dist/bitcoin-utils.d.ts.map +1 -0
- package/dist/bitcoin-utils.js +388 -0
- package/dist/bitcoin-utils.js.map +1 -0
- package/dist/helper/burn-request-helper.d.ts +7 -0
- package/dist/helper/burn-request-helper.d.ts.map +1 -0
- package/dist/helper/burn-request-helper.js +26 -0
- package/dist/helper/burn-request-helper.js.map +1 -0
- package/dist/helper/teleport-request-helper.d.ts +45 -0
- package/dist/helper/teleport-request-helper.d.ts.map +1 -0
- package/dist/helper/teleport-request-helper.js +141 -0
- package/dist/helper/teleport-request-helper.js.map +1 -0
- package/dist/index.d.ts +7 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +15 -0
- package/dist/index.js.map +1 -0
- package/dist/sign/sign-transaction.d.ts +8 -0
- package/dist/sign/sign-transaction.d.ts.map +1 -0
- package/dist/sign/sign-transaction.js +41 -0
- package/dist/sign/sign-transaction.js.map +1 -0
- package/dist/teleport-dao-payments.d.ts +92 -0
- package/dist/teleport-dao-payments.d.ts.map +1 -0
- package/dist/teleport-dao-payments.js +203 -0
- package/dist/teleport-dao-payments.js.map +1 -0
- package/dist/transaction-builder/bitcoin-transaction-builder.d.ts +12 -0
- package/dist/transaction-builder/bitcoin-transaction-builder.d.ts.map +1 -0
- package/dist/transaction-builder/bitcoin-transaction-builder.js +50 -0
- package/dist/transaction-builder/bitcoin-transaction-builder.js.map +1 -0
- package/dist/transaction-builder/transaction-builder-common.d.ts +80 -0
- package/dist/transaction-builder/transaction-builder-common.d.ts.map +1 -0
- package/dist/transaction-builder/transaction-builder-common.js +170 -0
- package/dist/transaction-builder/transaction-builder-common.js.map +1 -0
- package/dist/transaction-builder/transaction-builder.d.ts +19 -0
- package/dist/transaction-builder/transaction-builder.d.ts.map +1 -0
- package/dist/transaction-builder/transaction-builder.js +130 -0
- package/dist/transaction-builder/transaction-builder.js.map +1 -0
- package/dist/utils/networks.d.ts +36 -0
- package/dist/utils/networks.d.ts.map +1 -0
- package/dist/utils/networks.js +30 -0
- package/dist/utils/networks.js.map +1 -0
- package/dist/utils/tools.d.ts +13 -0
- package/dist/utils/tools.d.ts.map +1 -0
- package/dist/utils/tools.js +65 -0
- package/dist/utils/tools.js.map +1 -0
- package/package.json +34 -0
- package/src/bitcoin-base.js +174 -0
- package/src/bitcoin-interface-utils.js +42 -0
- package/src/bitcoin-interface.js +267 -0
- package/src/bitcoin-utils.js +443 -0
- package/src/helper/burn-request-helper.js +27 -0
- package/src/helper/teleport-request-helper.js +162 -0
- package/src/index.js +15 -0
- package/src/sign/sign-transaction.js +36 -0
- package/src/teleport-dao-payments.js +276 -0
- package/src/transaction-builder/bitcoin-transaction-builder.js +37 -0
- package/src/transaction-builder/transaction-builder-common.js +228 -0
- package/src/transaction-builder/transaction-builder.js +135 -0
- package/src/utils/networks.js +31 -0
- package/src/utils/tools.js +72 -0
- package/tsconfig.json +9 -0
|
@@ -0,0 +1,174 @@
|
|
|
1
|
+
const bip39 = require("bip39")
|
|
2
|
+
const bip32 = require("bip32")
|
|
3
|
+
const hdWalletNetworksPath = require("@teleportdao/configs").hdWalletPath
|
|
4
|
+
|
|
5
|
+
const networks = require("./utils/networks")
|
|
6
|
+
|
|
7
|
+
const TransactionBuilder = require("./transaction-builder/bitcoin-transaction-builder")
|
|
8
|
+
const BitcoinSign = require("./sign/sign-transaction")
|
|
9
|
+
|
|
10
|
+
class BitcoinBase {
|
|
11
|
+
constructor(
|
|
12
|
+
networkName,
|
|
13
|
+
connectionInfo = {
|
|
14
|
+
api: {
|
|
15
|
+
enabled: true,
|
|
16
|
+
provider: "BlockStream",
|
|
17
|
+
},
|
|
18
|
+
},
|
|
19
|
+
) {
|
|
20
|
+
this.network = networks[networkName]
|
|
21
|
+
this.hdWalletPath = hdWalletNetworksPath[networkName.replace("_testnet", "")]
|
|
22
|
+
|
|
23
|
+
this.transactionBuilder = new TransactionBuilder(connectionInfo, networkName, this.network)
|
|
24
|
+
this.btcInterface = this.transactionBuilder.btcInterface
|
|
25
|
+
|
|
26
|
+
this.signer = new BitcoinSign(this.network)
|
|
27
|
+
|
|
28
|
+
this.currentAccount = null
|
|
29
|
+
this.currentAccountType = null
|
|
30
|
+
|
|
31
|
+
this.privateKey = null
|
|
32
|
+
this.publicKey = null
|
|
33
|
+
// todo multisig
|
|
34
|
+
this.publicKeys = []
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
setMultiSigAccount(accountType = "p2sh") {
|
|
38
|
+
/* eslint-disable no-unreachable */
|
|
39
|
+
// todo : not completed
|
|
40
|
+
switch (accountType) {
|
|
41
|
+
// case 'p2sh':
|
|
42
|
+
// this.currentAccount = ''
|
|
43
|
+
// break
|
|
44
|
+
// case 'p2wsh':
|
|
45
|
+
// this.currentAccount = ''
|
|
46
|
+
// break
|
|
47
|
+
// case 'p2sh-p2wsh':
|
|
48
|
+
// this.currentAccount = ''
|
|
49
|
+
// break
|
|
50
|
+
default:
|
|
51
|
+
throw new Error("accountType is incorrect")
|
|
52
|
+
}
|
|
53
|
+
this.currentAccountType = accountType
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
setAccountPrivateKey(privateKeyHex) {
|
|
57
|
+
this.privateKey = Buffer.from(privateKeyHex, "hex")
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
setAccountPublicKey(publicKeyHex) {
|
|
61
|
+
this.publicKey = Buffer.from(publicKeyHex, "hex")
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
setAccountPrivateKeyByMnemonic({
|
|
65
|
+
mnemonic,
|
|
66
|
+
mnemonicPassword = "",
|
|
67
|
+
index = 0,
|
|
68
|
+
walletNumber = 0,
|
|
69
|
+
addressType = "p2sh-p2wpkh",
|
|
70
|
+
}) {
|
|
71
|
+
if (!bip39.validateMnemonic(mnemonic)) throw new Error("invalid mnemonic")
|
|
72
|
+
const seed = bip39.mnemonicToSeedSync(mnemonic, mnemonicPassword)
|
|
73
|
+
const node = bip32.fromSeed(seed)
|
|
74
|
+
|
|
75
|
+
if (!this.hdWalletPath[addressType]) throw new Error("incorrect path or addressType")
|
|
76
|
+
|
|
77
|
+
const path = `${this.hdWalletPath[addressType]}/${walletNumber}`
|
|
78
|
+
const account = node.derivePath(path)
|
|
79
|
+
const userKeyPair = account.derive(index)
|
|
80
|
+
this.setAccountPrivateKey(userKeyPair.privateKey.toString("hex"))
|
|
81
|
+
this.setAccountPublicKey(userKeyPair.publicKey.toString("hex"))
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
setAccount(accountType = "p2pkh") {
|
|
85
|
+
let addressObj = this.transactionBuilder.createAddressObject({
|
|
86
|
+
addressType: accountType,
|
|
87
|
+
publicKey: this.publicKey,
|
|
88
|
+
})
|
|
89
|
+
this.currentAccount = addressObj.address
|
|
90
|
+
this.currentAccountType = accountType
|
|
91
|
+
this.addressObj = addressObj
|
|
92
|
+
return addressObj.address
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
*
|
|
97
|
+
* @param {Object} signerInfo
|
|
98
|
+
* @param {String} signerInfo.address
|
|
99
|
+
* @param {String} signerInfo.addressType
|
|
100
|
+
* @param {String?} signerInfo.publicKey
|
|
101
|
+
* *@param {Array?} signerInfo.publicKeys // todo not used yet- used in multi sig
|
|
102
|
+
* @param {String?} signerInfo.derivationPath
|
|
103
|
+
* @param {String?} signerInfo.privateKeyId
|
|
104
|
+
* @returns
|
|
105
|
+
*/
|
|
106
|
+
async getExtendedUtxo({ address, addressType, publicKey, derivationPath }) {
|
|
107
|
+
return this.transactionBuilder.getExtendedUtxo({
|
|
108
|
+
address,
|
|
109
|
+
addressType,
|
|
110
|
+
publicKey,
|
|
111
|
+
derivationPath,
|
|
112
|
+
})
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
static checkBalanceIsSufficient({
|
|
116
|
+
targets,
|
|
117
|
+
extendedUtxo,
|
|
118
|
+
changeAddress,
|
|
119
|
+
feeRate,
|
|
120
|
+
fullAmount = false,
|
|
121
|
+
}) {
|
|
122
|
+
try {
|
|
123
|
+
TransactionBuilder.helperHandleInputsAndOutputs({
|
|
124
|
+
targets,
|
|
125
|
+
extendedUtxo,
|
|
126
|
+
changeAddress,
|
|
127
|
+
feeRate,
|
|
128
|
+
fullAmount,
|
|
129
|
+
})
|
|
130
|
+
return true
|
|
131
|
+
} catch (err) {
|
|
132
|
+
return false
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
async send({ receiverAddress, amount, fullAmount = false, speed = "normal" }) {
|
|
137
|
+
let extendedUtxo = await this.getExtendedUtxo({
|
|
138
|
+
address: this.currentAccount,
|
|
139
|
+
addressType: this.currentAccountType,
|
|
140
|
+
publicKey: this.publicKey.toString("hex"),
|
|
141
|
+
})
|
|
142
|
+
let feeRate = await this.transactionBuilder._getFeeRate(speed)
|
|
143
|
+
let unsignedTx = await this.transactionBuilder.processUnsignedTransaction({
|
|
144
|
+
extendedUtxo,
|
|
145
|
+
targets: [
|
|
146
|
+
{
|
|
147
|
+
address: receiverAddress,
|
|
148
|
+
value: amount,
|
|
149
|
+
},
|
|
150
|
+
],
|
|
151
|
+
changeAddress: this.currentAccount,
|
|
152
|
+
feeRate,
|
|
153
|
+
fullAmount,
|
|
154
|
+
})
|
|
155
|
+
let signedPsbt = await this.signer.signPsbt(unsignedTx, this.privateKey)
|
|
156
|
+
let signedTx = this.signer.finalizePsbts([signedPsbt])
|
|
157
|
+
let txId = await this.transactionBuilder.sendTx(signedTx)
|
|
158
|
+
return txId
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
async sendSignedPsbt(signedPsbt) {
|
|
162
|
+
let signedTx = this.signer.finalizePsbts([signedPsbt])
|
|
163
|
+
let txId = await this.transactionBuilder.sendTx(signedTx)
|
|
164
|
+
return txId
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
async sendMultiSignedPsbt(signedPsbts = []) {
|
|
168
|
+
let signedTx = this.signer.finalizePsbts(signedPsbts)
|
|
169
|
+
let txId = await this.transactionBuilder.sendTx(signedTx)
|
|
170
|
+
return txId
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
module.exports = BitcoinBase
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
const networks = require("./utils/networks")
|
|
2
|
+
const {
|
|
3
|
+
createAddressObjectByHash,
|
|
4
|
+
createAddressObjectByAddress,
|
|
5
|
+
createAddressObjectByPublicKey,
|
|
6
|
+
} = require("./bitcoin-utils")
|
|
7
|
+
|
|
8
|
+
class BitcoinInterfaceUtils {
|
|
9
|
+
constructor(networkName) {
|
|
10
|
+
this.testnet = networkName.includes("_testnet")
|
|
11
|
+
this.network = networks[networkName]
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
convertHashToAddress(hashHex, addressType) {
|
|
15
|
+
let addressObj = createAddressObjectByHash(
|
|
16
|
+
{ addressType, hash: Buffer.from(hashHex, "hex") },
|
|
17
|
+
this.network,
|
|
18
|
+
)
|
|
19
|
+
return addressObj.address
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
convertAddressToScript(address) {
|
|
23
|
+
let { addressObject, addressType } = createAddressObjectByAddress(address, this.network)
|
|
24
|
+
return {
|
|
25
|
+
script: addressObject.output,
|
|
26
|
+
hash: addressObject.hash,
|
|
27
|
+
addressType,
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
convertAddressToObject(address) {
|
|
32
|
+
let addObj = createAddressObjectByAddress(address, this.network)
|
|
33
|
+
return addObj
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
createAddressObjectByPublicKey(address, addressType) {
|
|
37
|
+
let addObj = createAddressObjectByPublicKey({ address, addressType }, this.network)
|
|
38
|
+
return addObj
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
module.exports = BitcoinInterfaceUtils
|
|
@@ -0,0 +1,267 @@
|
|
|
1
|
+
const { getRpcProvider, getApiProvider } = require("@teleportdao/providers").bitcoin
|
|
2
|
+
const { runWithRetries, sleep } = require("./utils/tools")
|
|
3
|
+
const {
|
|
4
|
+
parseRawTransaction,
|
|
5
|
+
calculateMerkleProof,
|
|
6
|
+
parseBlockHeader,
|
|
7
|
+
extractTransactionsAndBlockInfoFromRawBlock,
|
|
8
|
+
} = require("./bitcoin-utils")
|
|
9
|
+
const { checkAndParseProtocolRequest } = require("./helper/teleport-request-helper")
|
|
10
|
+
const { getBurnTransactionInfo } = require("./helper/burn-request-helper")
|
|
11
|
+
const BitcoinInterfaceUtils = require("./bitcoin-interface-utils")
|
|
12
|
+
|
|
13
|
+
class BitcoinInterface extends BitcoinInterfaceUtils {
|
|
14
|
+
constructor(connectionInfo, networkName, config = { minTeleporterFeeAmount: 0 }) {
|
|
15
|
+
super(networkName)
|
|
16
|
+
if (connectionInfo.rpc?.enabled) {
|
|
17
|
+
this.rpcProvider = getRpcProvider(connectionInfo.rpc)
|
|
18
|
+
} else if (connectionInfo.api.provider !== "BlockStream") {
|
|
19
|
+
throw new Error("if rpc is disabled, we just support BlockStream as api provider")
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
if (connectionInfo.api.enabled) {
|
|
23
|
+
this.apiProviderName = connectionInfo.api.provider
|
|
24
|
+
this.apiProvider = getApiProvider(connectionInfo.api, networkName)
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
this.minTeleporterFeeAmount = config.minTeleporterFeeAmount
|
|
28
|
+
this.provider = this.rpcProvider || this.apiProvider
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
// rpc + api
|
|
32
|
+
|
|
33
|
+
// general
|
|
34
|
+
async getLatestBlockNumber() {
|
|
35
|
+
let latestHeight = await this.provider.getLatestBlockNumber()
|
|
36
|
+
return latestHeight
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
async getBlockHash(blockNumber) {
|
|
40
|
+
let headerHash = await runWithRetries(() => this.provider.getBlockHash(blockNumber))
|
|
41
|
+
return headerHash
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
async getBlockHeaderHex(blockNumber) {
|
|
45
|
+
let headerHex = await runWithRetries(() => this.provider.getBlockHeaderHex(blockNumber))
|
|
46
|
+
return headerHex
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
async getTransaction(txId) {
|
|
50
|
+
return this.provider.getTransaction(txId)
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
// speed : low normal fast
|
|
54
|
+
async getFeeRate(speed = "normal") {
|
|
55
|
+
if (!(speed === "normal" || speed === "slow" || speed === "fast")) {
|
|
56
|
+
throw new Error("incorrect speed")
|
|
57
|
+
}
|
|
58
|
+
let fee = await this.provider.getFeeRate(speed)
|
|
59
|
+
return fee
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
// ----------- specific
|
|
63
|
+
|
|
64
|
+
// relayer
|
|
65
|
+
async getHexBlockHeaders(startBlockNumber, endBlockNumber) {
|
|
66
|
+
const blockHeaders = []
|
|
67
|
+
let difficulty = null
|
|
68
|
+
let hexBlockHeaders = ""
|
|
69
|
+
|
|
70
|
+
let fromBlockNumber = startBlockNumber
|
|
71
|
+
for (let blockNumber = startBlockNumber; blockNumber <= endBlockNumber; blockNumber += 1) {
|
|
72
|
+
let blockHeader = await this.getBlockHeaderHex(blockNumber)
|
|
73
|
+
console.log("block", blockNumber)
|
|
74
|
+
let parsedBlockHeader = parseBlockHeader(blockHeader)
|
|
75
|
+
if (difficulty && parsedBlockHeader.difficulty !== difficulty) {
|
|
76
|
+
blockHeaders.push({
|
|
77
|
+
hexBlockHeaders,
|
|
78
|
+
fromBlockNumber,
|
|
79
|
+
toBlockNumber: blockNumber - 1,
|
|
80
|
+
difficulty,
|
|
81
|
+
})
|
|
82
|
+
hexBlockHeaders = blockHeader
|
|
83
|
+
fromBlockNumber = blockNumber
|
|
84
|
+
} else {
|
|
85
|
+
hexBlockHeaders += blockHeader
|
|
86
|
+
}
|
|
87
|
+
difficulty = parsedBlockHeader.difficulty
|
|
88
|
+
}
|
|
89
|
+
if (hexBlockHeaders) {
|
|
90
|
+
blockHeaders.push({
|
|
91
|
+
hexBlockHeaders,
|
|
92
|
+
fromBlockNumber,
|
|
93
|
+
toBlockNumber: endBlockNumber,
|
|
94
|
+
difficulty,
|
|
95
|
+
})
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
return blockHeaders
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
async getRequestProof(transaction) {
|
|
102
|
+
let transactionHex =
|
|
103
|
+
transaction.hex || (await this.provider.getRawTransaction(transaction.txId))
|
|
104
|
+
|
|
105
|
+
let txInfo
|
|
106
|
+
if (!(transaction.blockHash && transaction.blockNumber)) {
|
|
107
|
+
txInfo = await this.provider.getTransaction(transaction.txId)
|
|
108
|
+
}
|
|
109
|
+
let blockHash = transaction.blockHash || txInfo.blockHash
|
|
110
|
+
let blockNumber = transaction.blockNumber || txInfo.blockNumber
|
|
111
|
+
let parsedTx = parseRawTransaction(transactionHex)
|
|
112
|
+
let merkleProof =
|
|
113
|
+
transaction.merkleProof || (await this.getMerkleProof(transaction.txId, blockHash))
|
|
114
|
+
|
|
115
|
+
return {
|
|
116
|
+
parsedTx,
|
|
117
|
+
merkleProof,
|
|
118
|
+
blockNumber,
|
|
119
|
+
blockHash,
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
async getMerkleProof(txId, blockHash) {
|
|
124
|
+
let txIds = await this.provider.getBlockTransactionIds(blockHash)
|
|
125
|
+
// let a = await this.provider.getMerkleProof(txId)
|
|
126
|
+
let proof = calculateMerkleProof(txIds, txId)
|
|
127
|
+
// console.log(a.intermediateNodes === proof.intermediateNodes)
|
|
128
|
+
return proof
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
// ------------------ utxo providers --------------------------------
|
|
132
|
+
|
|
133
|
+
// teleporter + locker
|
|
134
|
+
async getAddressesUtxo(addresses) {
|
|
135
|
+
if (!this.apiProvider) {
|
|
136
|
+
throw new Error("this function need an api provider")
|
|
137
|
+
}
|
|
138
|
+
const allPromises = []
|
|
139
|
+
for (let address of addresses) {
|
|
140
|
+
let promise = await this.apiProvider.getUtxos(address)
|
|
141
|
+
allPromises.push(promise)
|
|
142
|
+
}
|
|
143
|
+
let result = await Promise.all(allPromises)
|
|
144
|
+
return result.flat(1)
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
async getBalance(address) {
|
|
148
|
+
if (!this.apiProvider) {
|
|
149
|
+
throw new Error("this function need an api provider")
|
|
150
|
+
}
|
|
151
|
+
let utxos = (await this.apiProvider.getUtxos(address)) ?? []
|
|
152
|
+
return utxos.reduce((a, tx) => a + Number(tx.value), 0)
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
// ------------------ utxo provider + rpc or blockstream----------------
|
|
156
|
+
// teleporter
|
|
157
|
+
async getBlockTransactions(addresses, blockNumber) {
|
|
158
|
+
let utxos = await this.getAddressesUtxo(addresses)
|
|
159
|
+
let rawBlockHex = await this.rpcProvider.getBlockByBlockNumber(blockNumber, 0)
|
|
160
|
+
let { withdrawTxs, depositTxs } = extractTransactionsAndBlockInfoFromRawBlock(
|
|
161
|
+
rawBlockHex,
|
|
162
|
+
blockNumber,
|
|
163
|
+
addresses,
|
|
164
|
+
utxos,
|
|
165
|
+
this.network,
|
|
166
|
+
)
|
|
167
|
+
// todo : check
|
|
168
|
+
return depositTxs.concat(withdrawTxs)
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
// teleporter
|
|
172
|
+
async getMultipleBlocksTransactions(addresses, startBlockNumber, endBlockNumber) {
|
|
173
|
+
if (endBlockNumber - startBlockNumber > 20) {
|
|
174
|
+
throw new Error("cant get more than 20 block per function call")
|
|
175
|
+
}
|
|
176
|
+
let blockTxs = []
|
|
177
|
+
for (let blockNumber = +startBlockNumber + 1; blockNumber <= endBlockNumber; blockNumber += 1) {
|
|
178
|
+
console.log("get block transactions. blockNumber: ", blockNumber)
|
|
179
|
+
const response = this.getBlockTransactions(addresses, blockNumber)
|
|
180
|
+
blockTxs.push(response)
|
|
181
|
+
await sleep(200)
|
|
182
|
+
}
|
|
183
|
+
blockTxs = await Promise.all(blockTxs)
|
|
184
|
+
return blockTxs.flat(1)
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
// teleporter
|
|
188
|
+
async getTransactionHistory(addresses, startBlockNumber, endBlockNumber) {
|
|
189
|
+
if (this.rpcProvider) {
|
|
190
|
+
let endBlock = endBlockNumber || (await this.getLatestBlockNumber())
|
|
191
|
+
let startBlock = Math.max(+startBlockNumber, +endBlock - 20)
|
|
192
|
+
return this.getMultipleBlocksTransactions(addresses, startBlock, endBlock)
|
|
193
|
+
}
|
|
194
|
+
if (this.apiProviderName !== "BlockStream") {
|
|
195
|
+
throw new Error("just support BlockStream as api provider for this function")
|
|
196
|
+
}
|
|
197
|
+
let txs = await this.apiProvider.getTransactionHistoryForMultipleAddresses(
|
|
198
|
+
addresses,
|
|
199
|
+
startBlockNumber,
|
|
200
|
+
)
|
|
201
|
+
return txs.flat(1)
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
// ------------------just blockstream----------------------
|
|
205
|
+
async getMempoolTransactionHistory(addresses) {
|
|
206
|
+
if (this.apiProviderName !== "BlockStream") {
|
|
207
|
+
throw new Error("teleporter just support BlockStream as api provider")
|
|
208
|
+
}
|
|
209
|
+
let txs = await this.apiProvider.getMempoolTransactionHistoryForMultipleAddresses(addresses)
|
|
210
|
+
return txs.flat(1)
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
//
|
|
214
|
+
|
|
215
|
+
async getTeleporterRequests(addresses, startblockNumber, endBlockNumber, mempool = false) {
|
|
216
|
+
// transaction in StartBlock is not returned --> (startblockNumber,endBlockNumber]
|
|
217
|
+
let transactions = mempool
|
|
218
|
+
? await this.getMempoolTransactionHistory(addresses)
|
|
219
|
+
: await this.getTransactionHistory(addresses, startblockNumber, endBlockNumber)
|
|
220
|
+
|
|
221
|
+
let requests = []
|
|
222
|
+
let invalidRequests = []
|
|
223
|
+
for (let transaction of transactions) {
|
|
224
|
+
console.log(`received tx to check for teleport: ${transaction.txId}`)
|
|
225
|
+
|
|
226
|
+
let address = transaction.address
|
|
227
|
+
let request = checkAndParseProtocolRequest(transaction.vout, address, {
|
|
228
|
+
minTeleporterFeeAmount: this.minTeleporterFeeAmount,
|
|
229
|
+
})
|
|
230
|
+
let lockerLockingScript =
|
|
231
|
+
transaction.addressScript || this.convertAddressToScript(address).script.toString("hex")
|
|
232
|
+
if (request.status) {
|
|
233
|
+
requests.push({ transaction, request, lockerAddress: address, lockerLockingScript })
|
|
234
|
+
} else if (request.code !== "NO_OP_RETURN") {
|
|
235
|
+
invalidRequests.push({ transaction, request, lockerAddress: address, lockerLockingScript })
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
return { requests, invalidRequests }
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
async getLockersBurnTransactions(addresses, startBlockNumber, endBlockNumber, mempool = false) {
|
|
242
|
+
let transactions = mempool
|
|
243
|
+
? await this.getMempoolTransactionHistory(addresses)
|
|
244
|
+
: await this.getTransactionHistory(addresses, startBlockNumber, endBlockNumber)
|
|
245
|
+
|
|
246
|
+
let validTxs = []
|
|
247
|
+
for (let transaction of transactions) {
|
|
248
|
+
let address = transaction.address
|
|
249
|
+
console.log(`received tx to check burn: ${transaction.txId}`)
|
|
250
|
+
// check if its a transaction to spend btc
|
|
251
|
+
let burnInfo = getBurnTransactionInfo(address, transaction.vin, transaction.vout)
|
|
252
|
+
if (burnInfo) {
|
|
253
|
+
validTxs.push({
|
|
254
|
+
transaction,
|
|
255
|
+
burnInfo,
|
|
256
|
+
lockerAddress: address,
|
|
257
|
+
lockerLockingScript:
|
|
258
|
+
transaction.addressScript ||
|
|
259
|
+
this.convertAddressToScript(address).script.toString("hex"),
|
|
260
|
+
})
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
return validTxs
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
module.exports = BitcoinInterface
|