@xchainjs/xchain-utxo-providers 0.1.2 → 0.2.1

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/lib/index.js CHANGED
@@ -5,21 +5,24 @@ Object.defineProperty(exports, '__esModule', { value: true });
5
5
  var xchainUtil = require('@xchainjs/xchain-util');
6
6
  var axios = require('axios');
7
7
  var xchainClient = require('@xchainjs/xchain-client');
8
+ var PromisePool = require('@supercharge/promise-pool');
8
9
 
9
10
  function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
10
11
 
11
12
  var axios__default = /*#__PURE__*/_interopDefaultLegacy(axios);
13
+ var PromisePool__default = /*#__PURE__*/_interopDefaultLegacy(PromisePool);
12
14
 
13
- (function (SochainNetwork) {
14
- SochainNetwork["BTC"] = "BTC";
15
- SochainNetwork["BTCTEST"] = "BTCTEST";
16
- SochainNetwork["LTC"] = "LTC";
17
- SochainNetwork["LTCTEST"] = "LTCTEST";
18
- SochainNetwork["DOGE"] = "DOGE";
19
- SochainNetwork["DOGETEST"] = "DOGETEST";
15
+ exports.SochainNetwork = void 0;
16
+ (function (SochainNetwork) {
17
+ SochainNetwork["BTC"] = "BTC";
18
+ SochainNetwork["BTCTEST"] = "BTCTEST";
19
+ SochainNetwork["LTC"] = "LTC";
20
+ SochainNetwork["LTCTEST"] = "LTCTEST";
21
+ SochainNetwork["DOGE"] = "DOGE";
22
+ SochainNetwork["DOGETEST"] = "DOGETEST";
20
23
  })(exports.SochainNetwork || (exports.SochainNetwork = {}));
21
24
 
22
- /*! *****************************************************************************
25
+ /******************************************************************************
23
26
  Copyright (c) Microsoft Corporation.
24
27
 
25
28
  Permission to use, copy, modify, and/or distribute this software for any
@@ -44,1836 +47,999 @@ function __awaiter(thisArg, _arguments, P, generator) {
44
47
  });
45
48
  }
46
49
 
47
- /**
48
- * Get transaction by hash.
49
- *
50
- * @see https://sochain.com/api#get-tx
51
- *
52
- * @param {string} sochainUrl The sochain node url.
53
- * @param {string} network network id
54
- * @param {string} hash The transaction hash.
55
- * @returns {Transactions}
56
- */
57
- const getTx = ({ apiKey, sochainUrl, network, hash }) => __awaiter(void 0, void 0, void 0, function* () {
58
- const url = `${sochainUrl}/transaction/${network}/${hash}`;
59
- const response = yield axios__default['default'].get(url, { headers: { 'API-KEY': apiKey } });
60
- const tx = response.data;
61
- return tx.data;
62
- });
63
- /**
64
- * Get transactions
65
- *
66
- * @see https://sochain.com/api#get-tx
67
- *
68
- * @param {string} sochainUrl The sochain node url.
69
- * @param {string} network network id
70
- * @param {string} hash The transaction hash.
71
- * @returns {Transactions}
72
- */
73
- const getTxs = ({ apiKey, address, sochainUrl, network, page, }) => __awaiter(void 0, void 0, void 0, function* () {
74
- const url = `${sochainUrl}/transactions/${network}/${address}/${page}`; //TODO support paging
75
- const response = yield axios__default['default'].get(url, { headers: { 'API-KEY': apiKey } });
76
- const txs = response.data;
77
- return txs.data;
78
- });
79
- /**
80
- * Get address balance.
81
- *
82
- * @see https://sochain.com/api#get-balance
83
- *
84
- * @param {string} sochainUrl The sochain node url.
85
- * @param {string} network Network
86
- * @param {string} address Address
87
- * @param {boolean} confirmedOnly Flag whether to get balances of confirmed txs only or for all
88
- * @returns {number}
89
- */
90
- const getBalance = ({ apiKey, sochainUrl, network, address, confirmedOnly, assetDecimals, }) => __awaiter(void 0, void 0, void 0, function* () {
91
- const url = `${sochainUrl}/balance/${network}/${address}`;
92
- const response = yield axios__default['default'].get(url, { headers: { 'API-KEY': apiKey } });
93
- const balanceResponse = response.data;
94
- const confirmed = xchainUtil.assetAmount(balanceResponse.data.confirmed, assetDecimals);
95
- const unconfirmed = xchainUtil.assetAmount(balanceResponse.data.unconfirmed, assetDecimals);
96
- const netAmt = confirmedOnly ? confirmed : confirmed.plus(unconfirmed);
97
- const result = xchainUtil.assetToBase(netAmt);
98
- return result;
99
- });
100
- /**
101
- * Get unspent txs
102
- *
103
- * @see https://sochain.com/api#get-unspent-tx
104
- *
105
- * @param {string} sochainUrl The sochain node url.
106
- * @param {string} network
107
- * @param {string} address
108
- * @returns {AddressUTXO[]}
109
- */
110
- const getUnspentTxs = ({ apiKey, sochainUrl, network, address, page, }) => __awaiter(void 0, void 0, void 0, function* () {
111
- const url = [sochainUrl, 'unspent_outputs', network, address, page].filter((v) => !!v).join('/');
112
- const resp = yield axios__default['default'].get(url, { headers: { 'API-KEY': apiKey } });
113
- const response = resp.data;
114
- const txs = response.data.outputs;
115
- if (txs.length === 10) {
116
- //fetch the next batch
117
- const nextBatch = yield getUnspentTxs({
118
- apiKey,
119
- sochainUrl,
120
- network,
121
- address,
122
- page: page + 1,
123
- });
124
- return txs.concat(nextBatch);
125
- }
126
- else {
127
- return txs;
128
- }
129
- });
130
- /**
131
- * Get address balance.
132
- *
133
- * @see https://sochain.com/api#get-balance
134
- *
135
- * @param {string} sochainUrl The sochain node url.
136
- * @param {string} network Network
137
- * @param {string} address Address
138
- * @param {boolean} confirmedOnly Flag whether to get balances of confirmed txs only or for all
139
- * @returns {number}
140
- */
141
- const broadcastTx = ({ apiKey, sochainUrl, network, txHex, }) => __awaiter(void 0, void 0, void 0, function* () {
142
- const url = `${sochainUrl}/broadcast_transaction/${network}`;
143
- const response = yield axios__default['default'].post(url, { tx_hex: txHex }, { headers: { 'API-KEY': apiKey } });
144
- const broadcastResponse = response.data;
145
- return broadcastResponse.tx_hex;
50
+ /**
51
+ * Get transaction by hash.
52
+ *
53
+ * @see https://sochain.com/api#get-tx
54
+ *
55
+ * @param {string} sochainUrl The sochain node url.
56
+ * @param {string} network network id
57
+ * @param {string} hash The transaction hash.
58
+ * @returns {Transactions}
59
+ */
60
+ const getTx$2 = ({ apiKey, sochainUrl, network, hash }) => __awaiter(void 0, void 0, void 0, function* () {
61
+ const url = `${sochainUrl}/transaction/${network}/${hash}`;
62
+ const response = yield axios__default["default"].get(url, { headers: { 'API-KEY': apiKey } });
63
+ const tx = response.data;
64
+ return tx.data;
146
65
  });
147
-
148
- class SochainProvider {
149
- constructor(baseUrl = 'https://sochain.com/api/v3', apiKey, chain, asset, assetDecimals, sochainNetwork) {
150
- this.baseUrl = baseUrl;
151
- this._apiKey = apiKey;
152
- this.chain = chain;
153
- this.asset = asset;
154
- this.assetDecimals = assetDecimals;
155
- this.sochainNetwork = sochainNetwork;
156
- this.asset;
157
- this.chain;
158
- }
159
- get apiKey() {
160
- return this._apiKey;
161
- }
162
- set apiKey(value) {
163
- this._apiKey = value;
164
- }
165
- broadcastTx(txHex) {
166
- return __awaiter(this, void 0, void 0, function* () {
167
- return yield broadcastTx({
168
- apiKey: this._apiKey,
169
- sochainUrl: this.baseUrl,
170
- network: this.sochainNetwork,
171
- txHex,
172
- });
173
- });
174
- }
175
- getConfirmedUnspentTxs(address) {
176
- return __awaiter(this, void 0, void 0, function* () {
177
- const allUnspent = yield getUnspentTxs({
178
- apiKey: this._apiKey,
179
- sochainUrl: this.baseUrl,
180
- network: this.sochainNetwork,
181
- address,
182
- page: 1,
183
- });
184
- const confirmedUnspent = allUnspent.filter((i) => i.block); //if it has a block noumber it's been confirmed
185
- return this.mapUTXOs(confirmedUnspent);
186
- });
187
- }
188
- getUnspentTxs(address) {
189
- return __awaiter(this, void 0, void 0, function* () {
190
- const allUnspent = yield getUnspentTxs({
191
- apiKey: this._apiKey,
192
- sochainUrl: this.baseUrl,
193
- network: this.sochainNetwork,
194
- address,
195
- page: 1,
196
- });
197
- return this.mapUTXOs(allUnspent);
198
- });
199
- }
200
- getBalance(address, assets /*ignored*/, confirmedOnly) {
201
- return __awaiter(this, void 0, void 0, function* () {
202
- try {
203
- const amount = yield getBalance({
204
- apiKey: this._apiKey,
205
- sochainUrl: this.baseUrl,
206
- network: this.sochainNetwork,
207
- address,
208
- confirmedOnly: !!confirmedOnly,
209
- assetDecimals: this.assetDecimals,
210
- });
211
- return [{ amount, asset: this.asset }];
212
- }
213
- catch (error) {
214
- throw new Error(`Could not get balances for address ${address}`);
215
- }
216
- });
217
- }
218
- /**
219
- * Get transaction history of a given address with pagination options.
220
- * By default it will return the transaction history of the current wallet.
221
- *
222
- * @param {TxHistoryParams} params The options to get transaction history. (optional)
223
- * @returns {TxsPage} The transaction history.
224
- */
225
- getTransactions(params) {
226
- var _a;
227
- return __awaiter(this, void 0, void 0, function* () {
228
- const offset = (_a = params === null || params === void 0 ? void 0 : params.offset) !== null && _a !== void 0 ? _a : 0;
229
- const limit = (params === null || params === void 0 ? void 0 : params.limit) || 10;
230
- if (offset < 0 || limit < 0)
231
- throw Error('ofset and limit must be equal or greater than 0');
232
- const firstPage = Math.floor(offset / 10) + 1;
233
- const lastPage = limit > 10 ? firstPage + Math.floor(limit / 10) : firstPage;
234
- const offsetOnFirstPage = offset % 10;
235
- const txHashesToFetch = [];
236
- let page = firstPage;
237
- try {
238
- while (page <= lastPage) {
239
- const response = yield getTxs({
240
- apiKey: this._apiKey,
241
- sochainUrl: this.baseUrl,
242
- network: this.sochainNetwork,
243
- address: `${params === null || params === void 0 ? void 0 : params.address}`,
244
- page,
245
- });
246
- if (response.transactions.length === 0)
247
- break;
248
- if (page === firstPage && response.transactions.length > offsetOnFirstPage) {
249
- //start from offset
250
- const txsToGet = response.transactions.slice(offsetOnFirstPage);
251
- this.addArrayUpToLimit(txHashesToFetch, txsToGet.map((i) => i.hash), limit);
252
- }
253
- else {
254
- this.addArrayUpToLimit(txHashesToFetch, response.transactions.map((i) => i.hash), limit);
255
- }
256
- page++;
257
- }
258
- }
259
- catch (error) {
260
- console.error(error);
261
- //an errors means no more results
262
- }
263
- const total = txHashesToFetch.length;
264
- const transactions = yield Promise.all(txHashesToFetch.map((hash) => this.getTransactionData(hash)));
265
- const result = {
266
- total,
267
- txs: transactions,
268
- };
269
- return result;
270
- });
271
- }
272
- /**
273
- * Get the transaction details of a given transaction id.
274
- *
275
- * @param {string} txId The transaction id.
276
- * @returns {Tx} The transaction details of the given transaction id.
277
- */
278
- getTransactionData(txId) {
279
- return __awaiter(this, void 0, void 0, function* () {
280
- try {
281
- const rawTx = yield getTx({
282
- apiKey: this._apiKey,
283
- sochainUrl: this.baseUrl,
284
- network: this.sochainNetwork,
285
- hash: txId,
286
- });
287
- return {
288
- asset: this.asset,
289
- from: rawTx.inputs.map((i) => ({
290
- from: i.address,
291
- amount: xchainUtil.assetToBase(xchainUtil.assetAmount(i.value, this.assetDecimals)),
292
- })),
293
- to: rawTx.outputs
294
- .filter((i) => i.type !== 'nulldata') //filter out op_return outputs
295
- .map((i) => ({ to: i.address, amount: xchainUtil.assetToBase(xchainUtil.assetAmount(i.value, this.assetDecimals)) })),
296
- date: new Date(rawTx.time * 1000),
297
- type: xchainClient.TxType.Transfer,
298
- hash: rawTx.hash,
299
- };
300
- }
301
- catch (error) {
302
- console.error(error);
303
- throw error;
304
- }
305
- });
306
- }
307
- mapUTXOs(utxos) {
308
- return utxos.map((utxo) => ({
309
- hash: utxo.hash,
310
- index: utxo.index,
311
- value: xchainUtil.assetToBase(xchainUtil.assetAmount(utxo.value, this.assetDecimals)).amount().toNumber(),
312
- witnessUtxo: {
313
- value: xchainUtil.assetToBase(xchainUtil.assetAmount(utxo.value, this.assetDecimals)).amount().toNumber(),
314
- script: Buffer.from(utxo.script, 'hex'),
315
- },
316
- txHex: utxo.tx_hex,
317
- }));
318
- }
319
- /**
320
- * helper function tto limit adding to an array
321
- *
322
- * @param arr array to be added to
323
- * @param toAdd elements to add
324
- * @param limit do not add more than this limit
325
- */
326
- addArrayUpToLimit(arr, toAdd, limit) {
327
- for (let index = 0; index < toAdd.length; index++) {
328
- const element = toAdd[index];
329
- if (arr.length < limit) {
330
- arr.push(element);
331
- }
332
- }
333
- }
334
- }
335
-
336
- /**
337
- * Haskoin API types
338
- */
339
- (function (HaskoinNetwork) {
340
- HaskoinNetwork["BTC"] = "btc";
341
- HaskoinNetwork["BTCTEST"] = "btctest";
342
- HaskoinNetwork["BCH"] = "bch";
343
- HaskoinNetwork["BCHTEST"] = "bchtest";
344
- })(exports.HaskoinNetwork || (exports.HaskoinNetwork = {}));
345
-
346
- /**
347
- * Module to interact with Haskoin API
348
- *
349
- * Doc (SwaggerHub) https://app.swaggerhub.com/apis/eligecode/blockchain-api/0.0.1-oas3
350
- *
351
- */
352
- /**
353
- * Check error response.
354
- *
355
- * @param {any} response The api response.
356
- * @returns {boolean}
357
- */
358
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
359
- const isErrorResponse = (response) => {
360
- return !!response.error;
361
- };
362
- /**
363
- * Get account from address.
364
- *
365
- * @param {string} haskoinUrl The haskoin API url.
366
- * @param {string} address The BCH address.
367
- * @returns {AddressBalance}
368
- *
369
- * @throws {"failed to query account by a given address"} thrown if failed to query account by a given address
370
- */
371
- const getAccount = ({ haskoinUrl, network, address }) => __awaiter(void 0, void 0, void 0, function* () {
372
- const url = `${haskoinUrl}/${network}/address/${address}/balance`;
373
- const result = (yield axios__default['default'].get(url)).data;
374
- if (!result || isErrorResponse(result))
375
- throw new Error(`failed to query account by given address ${address}`);
376
- return result;
377
- });
378
- /**
379
- * Get address information.
380
- *
381
- * @param {string} haskoinUrl The haskoin node url.
382
- * @param {string} network
383
- * @param {string} address
384
- * @returns {AddressDTO}
385
- */
386
- const getAddress = ({ haskoinUrl, network, address }) => __awaiter(void 0, void 0, void 0, function* () {
387
- const url = `${haskoinUrl}/${network}/address/${address}/balance`;
388
- const response = yield axios__default['default'].get(url);
389
- const addressResponse = response.data;
390
- return addressResponse.data;
391
- });
392
- /**
393
- * Get transaction by hash.
394
- *
395
- * @param {string} haskoinUrl The haskoin API url.
396
- * @param {string} txId The transaction id.
397
- * @returns {Transaction}
398
- *
399
- * @throws {"failed to query transaction by a given hash"} thrown if failed to query transaction by a given hash
400
- */
401
- const getTx$1 = ({ haskoinUrl, txId, network }) => __awaiter(void 0, void 0, void 0, function* () {
402
- const result = (yield axios__default['default'].get(`${haskoinUrl}/${network}/transaction/${txId}`)).data;
403
- if (!result || isErrorResponse(result))
404
- throw new Error(`failed to query transaction by a given hash ${txId}`);
405
- return result;
406
- });
407
- /**
408
- * Get raw transaction by hash.
409
- *
410
- * @param {string} haskoinUrl The haskoin API url.
411
- * @param {string} txId The transaction id.
412
- * @returns {Transaction}
413
- *
414
- * @throws {"failed to query transaction by a given hash"} thrown if failed to query raw transaction by a given hash
415
- */
416
- const getRawTransaction = ({ haskoinUrl, network, txId }) => __awaiter(void 0, void 0, void 0, function* () {
417
- const result = (yield axios__default['default'].get(`${haskoinUrl}/${network}/transaction/${txId}/raw`))
418
- .data;
419
- if (!result || isErrorResponse(result))
420
- throw new Error(`failed to query transaction by a given hash ${txId}`);
421
- return result.result;
422
- });
423
- /**
424
- * Get transactions
425
- *
426
- * @see https://haskoin.com/api#get-tx
427
- *
428
- * @param {string} haskoinUrl The haskoin node url.
429
- * @param {string} network network id
430
- * @param {string} hash The transaction hash.
431
- * @returns {Transactions}
432
- */
433
- const getTxs$1 = ({ address, haskoinUrl, network, limit, offset, }) => __awaiter(void 0, void 0, void 0, function* () {
434
- const params = { limit: `${limit}`, offset: `${offset}` };
435
- const url = `${haskoinUrl}/${network}/address/${address}/transactions/full`;
436
- const result = (yield axios__default['default'].get(url, { params })).data;
437
- if (!result || isErrorResponse(result))
438
- throw new Error('failed to query transactions');
439
- return result;
440
- });
441
- /**
442
- *
443
- * @param param
444
- * @returns Returns BaseAmount
445
- */
446
- const getBalance$1 = ({ haskoinUrl, haskoinNetwork, address, confirmedOnly, assetDecimals, }) => __awaiter(void 0, void 0, void 0, function* () {
447
- const { data: { confirmed, unconfirmed }, } = yield axios__default['default'].get(`${haskoinUrl}/${haskoinNetwork}/address/${address}/balance`);
448
- const confirmedAmount = xchainUtil.baseAmount(confirmed, assetDecimals);
449
- const unconfirmedAmount = xchainUtil.baseAmount(unconfirmed, assetDecimals);
450
- return confirmedOnly ? confirmedAmount : confirmedAmount.plus(unconfirmedAmount);
451
- });
452
- /**
453
- * Get unspent transactions.
454
- *
455
- * @param {string} haskoinUrl The haskoin API url.
456
- * @param {string} address The BCH address.
457
- * @returns {TxUnspent[]}
458
- *
459
- * @throws {"failed to query unspent transactions"} thrown if failed to query unspent transactions
460
- */
461
- const getUnspentTxs$1 = ({ haskoinUrl, network, address }) => __awaiter(void 0, void 0, void 0, function* () {
462
- // Get transaction count for a given address.
463
- const account = yield getAccount({ haskoinUrl, network, address });
464
- // Set limit to the transaction count to be all the utxos.
465
- const result = (yield axios__default['default'].get(`${haskoinUrl}/${network}/address/${address}/unspent?limit${account === null || account === void 0 ? void 0 : account.utxo}`)).data;
466
- if (!result || isErrorResponse(result))
467
- throw new Error('failed to query unspent transactions');
468
- return result;
469
- });
470
- /**
471
- * Get Tx Confirmation status
472
- *
473
- * @param {string} haskoinUrl The haskoin node url.
474
- * @param {Network} network
475
- * @param {string} hash tx id
476
- * @returns {TxConfirmedStatus}
477
- */
478
- const getIsTxConfirmed = ({ haskoinUrl, network, txId }) => __awaiter(void 0, void 0, void 0, function* () {
479
- const tx = yield getTx$1({ haskoinUrl, network, txId });
480
- return {
481
- network: network,
482
- txid: txId,
483
- confirmations: tx.confirmations,
484
- is_confirmed: tx.confirmations >= 1,
485
- };
486
- });
487
- /**
488
- * List of confirmed txs
489
- *
490
- * Stores a list of confirmed txs (hashes) in memory to avoid requesting same data
491
- */
492
- const confirmedTxs = [];
493
- /**
494
- * Helper to get `confirmed` status of a tx.
495
- *
496
- * It will get it from cache or try to get it from haskoin (if not cached before)
497
- */
498
- const getConfirmedTxStatus = ({ txHash, haskoinUrl, network, }) => __awaiter(void 0, void 0, void 0, function* () {
499
- // try to get it from cache
500
- if (confirmedTxs.includes(txHash))
501
- return true;
502
- // or get status from haskoin
503
- const { is_confirmed } = yield getIsTxConfirmed({
504
- haskoinUrl,
505
- network,
506
- txId: txHash,
507
- });
508
- // cache status
509
- confirmedTxs.push(txHash);
510
- return is_confirmed;
511
- });
512
- /**
513
- * Get unspent txs and filter out pending UTXOs
514
- *
515
- * @see https://haskoin.com/api#get-unspent-tx
516
- *
517
- * @param {string} haskoinUrl The haskoin node url.
518
- * @param {Network} network
519
- * @param {string} address
520
- * @returns {AddressUTXO[]}
521
- */
522
- const getConfirmedUnspentTxs = ({ haskoinUrl, network, address }) => __awaiter(void 0, void 0, void 0, function* () {
523
- const txs = yield getUnspentTxs$1({
524
- haskoinUrl,
525
- network,
526
- address,
527
- });
528
- const confirmedUTXOs = [];
529
- yield Promise.all(txs.map((tx) => __awaiter(void 0, void 0, void 0, function* () {
530
- const confirmed = yield getConfirmedTxStatus({
531
- haskoinUrl,
532
- network,
533
- txHash: tx.txid,
534
- });
535
- if (confirmed) {
536
- confirmedUTXOs.push(tx);
537
- }
538
- })));
539
- return confirmedUTXOs;
540
- });
541
- // Stores list of txHex in memory to avoid requesting same data
542
- const txHexMap = {};
543
- /**
544
- * Helper to get `hex` of `Tx`
545
- *
546
- * It will try to get it from cache before requesting it from Sochain
547
- */
548
- const getTxHex = ({ haskoinUrl, network, txId }) => __awaiter(void 0, void 0, void 0, function* () {
549
- // try to get hex from cache
550
- let txHex = txHexMap[txId];
551
- if (!!txHex)
552
- return txHex;
553
- // or get it from Haskoin
554
- txHex = yield getRawTransaction({ haskoinUrl, txId: txId, network: network });
555
- // cache it
556
- txHexMap[txId] = txHex;
557
- return txHex;
558
- });
559
- /**
560
- * Get unspent transactions.
561
- *
562
- * @param {string} haskoinUrl The haskoin API url.
563
- * @param {string} address The BCH address.
564
- * @returns {TxUnspent[]}
565
- *
566
- * @throws {"failed to query unspent transactions"} thrown if failed to query unspent transactions
567
- */
568
- const getUnspentTransactions = ({ haskoinUrl, network, address }) => __awaiter(void 0, void 0, void 0, function* () {
569
- // Get transaction count for a given address.
570
- const account = yield getAccount({ haskoinUrl, network, address });
571
- // Set limit to the transaction count to be all the utxos.
572
- const result = (yield axios__default['default'].get(`${haskoinUrl}/${network}/address/${address}/unspent?limit${account === null || account === void 0 ? void 0 : account.utxo}`)).data;
573
- if (!result || isErrorResponse(result))
574
- throw new Error('failed to query unspent transactions');
575
- return result;
576
- });
577
- /**
578
- * Broadcast transaction.
579
- *
580
- * @see https://app.swaggerhub.com/apis/eligecode/blockchain-api/0.0.1-oas3#/blockchain/sendTransaction
581
- *
582
- * Note: Because of an Haskoin issue (@see https://github.com/haskoin/haskoin-store/issues/25),
583
- * we need to broadcast same tx several times in case of `500` errors
584
- * @see https://github.com/xchainjs/xchainjs-lib/issues/492
585
- *
586
- * @param {BroadcastTxParams} params
587
- * @returns {TxHash} Transaction hash.
588
- */
589
- const broadcastTx$1 = ({ txHex, haskoinUrl, haskoinNetwork, }) => __awaiter(void 0, void 0, void 0, function* () {
590
- var _a;
591
- const MAX_RETRIES = 5;
592
- let retries = 0;
593
- const axiosInstance = axios__default['default'].create();
594
- const url = `${haskoinUrl}/${haskoinNetwork}/transactions`;
595
- while (retries < MAX_RETRIES) {
596
- try {
597
- const response = yield axiosInstance.post(url, txHex);
598
- const { txid } = response.data;
599
- return txid;
600
- }
601
- catch (error) {
602
- if (((_a = error.response) === null || _a === void 0 ? void 0 : _a.status) === 500) {
603
- retries++;
604
- yield xchainUtil.delay(200 * retries);
605
- }
606
- else {
607
- return Promise.reject(error);
608
- }
609
- }
610
- }
611
- return Promise.reject(new Error('Max retries exceeded'));
66
+ /**
67
+ * Get transactions
68
+ *
69
+ * @see https://sochain.com/api#get-tx
70
+ *
71
+ * @param {string} sochainUrl The sochain node url.
72
+ * @param {string} network network id
73
+ * @param {string} hash The transaction hash.
74
+ * @returns {Transactions}
75
+ */
76
+ const getTxs$2 = ({ apiKey, address, sochainUrl, network, page, }) => __awaiter(void 0, void 0, void 0, function* () {
77
+ const url = `${sochainUrl}/transactions/${network}/${address}/${page}`; //TODO support paging
78
+ const response = yield axios__default["default"].get(url, { headers: { 'API-KEY': apiKey } });
79
+ const txs = response.data;
80
+ return txs.data;
612
81
  });
613
-
614
- class HaskoinProvider {
615
- constructor(baseUrl = 'https://api.haskoin.com/', chain, asset, assetDecimals, haskoinNetwork) {
616
- this.baseUrl = baseUrl;
617
- this.chain = chain;
618
- this.asset = asset;
619
- this.assetDecimals = assetDecimals;
620
- this.haskoinNetwork = haskoinNetwork;
621
- this.asset;
622
- this.chain;
623
- }
624
- broadcastTx(txHex) {
625
- return __awaiter(this, void 0, void 0, function* () {
626
- return yield broadcastTx$1({
627
- haskoinUrl: this.baseUrl,
628
- haskoinNetwork: this.haskoinNetwork,
629
- txHex,
630
- });
631
- });
632
- }
633
- getConfirmedUnspentTxs(address) {
634
- return __awaiter(this, void 0, void 0, function* () {
635
- const allUnspent = yield getUnspentTransactions({
636
- haskoinUrl: this.baseUrl,
637
- network: this.haskoinNetwork,
638
- address,
639
- });
640
- const confirmedUnspent = allUnspent.filter((i) => i.block); //if it has a block noumber it's been confirmed
641
- return this.mapUTXOs(confirmedUnspent);
642
- });
643
- }
644
- getUnspentTxs(address) {
645
- return __awaiter(this, void 0, void 0, function* () {
646
- const allUnspent = yield getUnspentTxs$1({
647
- haskoinUrl: this.baseUrl,
648
- network: this.haskoinNetwork,
649
- address,
650
- });
651
- return yield this.mapUTXOs(allUnspent);
652
- });
653
- }
654
- getBalance(address, assets /*ignored*/, confirmedOnly) {
655
- return __awaiter(this, void 0, void 0, function* () {
656
- const amount = yield getBalance$1({
657
- haskoinUrl: this.baseUrl,
658
- haskoinNetwork: this.haskoinNetwork,
659
- address,
660
- confirmedOnly: !!confirmedOnly,
661
- assetDecimals: this.assetDecimals,
662
- });
663
- return [{ amount, asset: this.asset }];
664
- });
665
- }
666
- /**
667
- * Get transaction history of a given address with pagination options.
668
- * By default it will return the transaction history of the current wallet.
669
- *
670
- * @param {TxHistoryParams} params The options to get transaction history. (optional)
671
- * @returns {TxsPage} The transaction history.
672
- */
673
- getTransactions(params) {
674
- var _a;
675
- return __awaiter(this, void 0, void 0, function* () {
676
- const offset = (_a = params === null || params === void 0 ? void 0 : params.offset) !== null && _a !== void 0 ? _a : 0;
677
- const limit = (params === null || params === void 0 ? void 0 : params.limit) || 10;
678
- if (offset + limit > 2000)
679
- throw Error('cannot fetch more than last 2000 txs');
680
- if (offset < 0 || limit < 0)
681
- throw Error('ofset and limit must be equal or greater than 0');
682
- const response = yield getTxs$1({
683
- address: `${params === null || params === void 0 ? void 0 : params.address}`,
684
- haskoinUrl: this.baseUrl,
685
- network: this.haskoinNetwork,
686
- limit: limit,
687
- offset,
688
- });
689
- const txs = response.map((i) => this.mapTransactionToTx(i));
690
- const result = {
691
- total: txs.length,
692
- txs: txs,
693
- };
694
- return result;
695
- });
696
- }
697
- mapTransactionToTx(rawTx) {
698
- return {
699
- asset: this.asset,
700
- from: rawTx.inputs.map((i) => ({
701
- from: i.address,
702
- amount: xchainUtil.baseAmount(i.value, this.assetDecimals),
703
- })),
704
- to: rawTx.outputs
705
- .filter((i) => i.script !== 'null-data') //filter out op_return outputs
706
- .map((i) => ({ to: i.address, amount: xchainUtil.baseAmount(i.value, this.assetDecimals) })),
707
- date: new Date(rawTx.time),
708
- type: xchainClient.TxType.Transfer,
709
- hash: rawTx.txid,
710
- };
711
- }
712
- /**
713
- * Get the transaction details of a given transaction id.
714
- *
715
- * @param {string} txId The transaction id.
716
- * @returns {Tx} The transaction details of the given transaction id.
717
- */
718
- getTransactionData(txId) {
719
- return __awaiter(this, void 0, void 0, function* () {
720
- try {
721
- const rawTx = yield getTx$1({
722
- haskoinUrl: this.baseUrl,
723
- network: this.haskoinNetwork,
724
- txId: txId,
725
- });
726
- return this.mapTransactionToTx(rawTx);
727
- }
728
- catch (error) {
729
- console.error(error);
730
- throw error;
731
- }
732
- });
733
- }
734
- /**
735
- *
736
- * @param utxos
737
- * @returns utxo array
738
- */
739
- mapUTXOs(utxos) {
740
- return __awaiter(this, void 0, void 0, function* () {
741
- return yield Promise.all(utxos.map((utxo) => __awaiter(this, void 0, void 0, function* () {
742
- return ({
743
- hash: utxo.txid,
744
- index: utxo.index,
745
- value: xchainUtil.baseAmount(utxo.value, this.assetDecimals).amount().toNumber(),
746
- witnessUtxo: {
747
- value: xchainUtil.baseAmount(utxo.value, this.assetDecimals).amount().toNumber(),
748
- script: Buffer.from(utxo.pkscript, 'hex'),
749
- },
750
- txHex: yield getTxHex({ haskoinUrl: this.baseUrl, txId: utxo.txid, network: this.haskoinNetwork }),
751
- });
752
- })));
753
- });
754
- }
755
- }
756
-
757
- var commonjsGlobal = typeof globalThis !== 'undefined' ? globalThis : typeof window !== 'undefined' ? window : typeof global !== 'undefined' ? global : typeof self !== 'undefined' ? self : {};
758
-
759
- function unwrapExports (x) {
760
- return x && x.__esModule && Object.prototype.hasOwnProperty.call(x, 'default') ? x['default'] : x;
761
- }
762
-
763
- function createCommonjsModule(fn, module) {
764
- return module = { exports: {} }, fn(module, module.exports), module.exports;
765
- }
766
-
767
- var promisePoolError = createCommonjsModule(function (module, exports) {
768
- Object.defineProperty(exports, "__esModule", { value: true });
769
- exports.PromisePoolError = void 0;
770
- class PromisePoolError extends Error {
771
- /**
772
- * Create a new instance for the given `message` and `item`.
773
- *
774
- * @param error The original error
775
- * @param item The item causing the error
776
- */
777
- constructor(error, item) {
778
- super();
779
- this.raw = error;
780
- this.item = item;
781
- this.name = this.constructor.name;
782
- this.message = this.messageFrom(error);
783
- Error.captureStackTrace(this, this.constructor);
784
- }
785
- /**
786
- * Returns a new promise pool error instance wrapping the `error` and `item`.
787
- *
788
- * @param {*} error
789
- * @param {*} item
790
- *
791
- * @returns {PromisePoolError}
792
- */
793
- static createFrom(error, item) {
794
- return new this(error, item);
795
- }
796
- /**
797
- * Returns the error message from the given `error`.
798
- *
799
- * @param {*} error
800
- *
801
- * @returns {String}
802
- */
803
- messageFrom(error) {
804
- if (error instanceof Error) {
805
- return error.message;
806
- }
807
- if (typeof error === 'object') {
808
- return error.message;
809
- }
810
- if (typeof error === 'string' || typeof error === 'number') {
811
- return error.toString();
812
- }
813
- return '';
814
- }
815
- }
816
- exports.PromisePoolError = PromisePoolError;
817
- });
818
-
819
- unwrapExports(promisePoolError);
820
- var promisePoolError_1 = promisePoolError.PromisePoolError;
821
-
822
- var stopThePromisePoolError = createCommonjsModule(function (module, exports) {
823
- Object.defineProperty(exports, "__esModule", { value: true });
824
- exports.StopThePromisePoolError = void 0;
825
- class StopThePromisePoolError extends Error {
826
- }
827
- exports.StopThePromisePoolError = StopThePromisePoolError;
82
+ /**
83
+ * Get address balance.
84
+ *
85
+ * @see https://sochain.com/api#get-balance
86
+ *
87
+ * @param {string} sochainUrl The sochain node url.
88
+ * @param {string} network Network
89
+ * @param {string} address Address
90
+ * @param {boolean} confirmedOnly Flag whether to get balances of confirmed txs only or for all
91
+ * @returns {number}
92
+ */
93
+ const getBalance$2 = ({ apiKey, sochainUrl, network, address, confirmedOnly, assetDecimals, }) => __awaiter(void 0, void 0, void 0, function* () {
94
+ const url = `${sochainUrl}/balance/${network}/${address}`;
95
+ const response = yield axios__default["default"].get(url, { headers: { 'API-KEY': apiKey } });
96
+ const balanceResponse = response.data;
97
+ const confirmed = xchainUtil.assetAmount(balanceResponse.data.confirmed, assetDecimals);
98
+ const unconfirmed = xchainUtil.assetAmount(balanceResponse.data.unconfirmed, assetDecimals);
99
+ const netAmt = confirmedOnly ? confirmed : confirmed.plus(unconfirmed);
100
+ const result = xchainUtil.assetToBase(netAmt);
101
+ return result;
828
102
  });
829
-
830
- unwrapExports(stopThePromisePoolError);
831
- var stopThePromisePoolError_1 = stopThePromisePoolError.StopThePromisePoolError;
832
-
833
- var validationError = createCommonjsModule(function (module, exports) {
834
- Object.defineProperty(exports, "__esModule", { value: true });
835
- exports.ValidationError = void 0;
836
- class ValidationError extends Error {
837
- /**
838
- * Create a new instance for the given `message`.
839
- *
840
- * @param message The error message
841
- */
842
- constructor(message) {
843
- super(message);
844
- Error.captureStackTrace(this, this.constructor);
103
+ /**
104
+ * Get unspent txs
105
+ *
106
+ * @see https://sochain.com/api#get-unspent-tx
107
+ *
108
+ * @param {string} sochainUrl The sochain node url.
109
+ * @param {string} network
110
+ * @param {string} address
111
+ * @returns {AddressUTXO[]}
112
+ */
113
+ const getUnspentTxs$1 = ({ apiKey, sochainUrl, network, address, page, }) => __awaiter(void 0, void 0, void 0, function* () {
114
+ const url = [sochainUrl, 'unspent_outputs', network, address, page].filter((v) => !!v).join('/');
115
+ const resp = yield axios__default["default"].get(url, { headers: { 'API-KEY': apiKey } });
116
+ const response = resp.data;
117
+ const txs = response.data.outputs;
118
+ if (txs.length === 10) {
119
+ //fetch the next batch
120
+ const nextBatch = yield getUnspentTxs$1({
121
+ apiKey,
122
+ sochainUrl,
123
+ network,
124
+ address,
125
+ page: page + 1,
126
+ });
127
+ return txs.concat(nextBatch);
845
128
  }
846
- /**
847
- * Returns a validation error with the given `message`.
848
- */
849
- static createFrom(message) {
850
- return new this(message);
129
+ else {
130
+ return txs;
851
131
  }
852
- }
853
- exports.ValidationError = ValidationError;
132
+ });
133
+ /**
134
+ * Get address balance.
135
+ *
136
+ * @see https://sochain.com/api#get-balance
137
+ *
138
+ * @param {string} sochainUrl The sochain node url.
139
+ * @param {string} network Network
140
+ * @param {string} address Address
141
+ * @param {boolean} confirmedOnly Flag whether to get balances of confirmed txs only or for all
142
+ * @returns {number}
143
+ */
144
+ const broadcastTx$2 = ({ apiKey, sochainUrl, network, txHex, }) => __awaiter(void 0, void 0, void 0, function* () {
145
+ const url = `${sochainUrl}/broadcast_transaction/${network}`;
146
+ const response = yield axios__default["default"].post(url, { tx_hex: txHex }, { headers: { 'API-KEY': apiKey } });
147
+ const broadcastResponse = response.data;
148
+ return broadcastResponse.tx_hex;
854
149
  });
855
150
 
856
- unwrapExports(validationError);
857
- var validationError_1 = validationError.ValidationError;
858
-
859
- var promisePoolExecutor = createCommonjsModule(function (module, exports) {
860
- Object.defineProperty(exports, "__esModule", { value: true });
861
- exports.PromisePoolExecutor = void 0;
862
-
863
-
864
-
865
-
866
- class PromisePoolExecutor {
867
- /**
868
- * Creates a new promise pool executer instance with a default concurrency of 10.
869
- */
870
- constructor() {
871
- this.meta = {
872
- tasks: [],
873
- items: [],
874
- errors: [],
875
- results: [],
876
- stopped: false,
877
- concurrency: 10,
878
- shouldResultsCorrespond: false,
879
- processedItems: [],
880
- taskTimeout: 0
881
- };
882
- this.handler = () => { };
883
- this.errorHandler = undefined;
884
- this.onTaskStartedHandlers = [];
885
- this.onTaskFinishedHandlers = [];
886
- }
887
- /**
888
- * Set the number of tasks to process concurrently the promise pool.
889
- *
890
- * @param {Integer} concurrency
891
- *
892
- * @returns {PromisePoolExecutor}
893
- */
894
- useConcurrency(concurrency) {
895
- if (!this.isValidConcurrency(concurrency)) {
896
- throw validationError.ValidationError.createFrom(`"concurrency" must be a number, 1 or up. Received "${concurrency}" (${typeof concurrency})`);
897
- }
898
- this.meta.concurrency = concurrency;
899
- return this;
900
- }
901
- /**
902
- * Determine whether the given `concurrency` value is valid.
903
- *
904
- * @param {Number} concurrency
905
- *
906
- * @returns {Boolean}
907
- */
908
- isValidConcurrency(concurrency) {
909
- return typeof concurrency === 'number' && concurrency >= 1;
910
- }
911
- /**
912
- * Set the timeout in ms for the pool handler
913
- *
914
- * @param {Number} timeout
915
- *
916
- * @returns {PromisePool}
917
- */
918
- withTaskTimeout(timeout) {
919
- this.meta.taskTimeout = timeout;
920
- return this;
921
- }
922
- /**
923
- * Returns the number of concurrently processed tasks.
924
- *
925
- * @returns {Number}
926
- */
927
- concurrency() {
928
- return this.meta.concurrency;
929
- }
930
- /**
931
- * Assign whether to keep corresponding results between source items and resulting tasks.
932
- */
933
- useCorrespondingResults(shouldResultsCorrespond) {
934
- this.meta.shouldResultsCorrespond = shouldResultsCorrespond;
935
- return this;
936
- }
937
- /**
938
- * Determine whether to keep corresponding results between source items and resulting tasks.
939
- */
940
- shouldUseCorrespondingResults() {
941
- return this.meta.shouldResultsCorrespond;
942
- }
943
- /**
944
- * Returns the task timeout in milliseconds.
945
- */
946
- taskTimeout() {
947
- return this.meta.taskTimeout;
948
- }
949
- /**
950
- * Set the items to be processed in the promise pool.
951
- *
952
- * @param {Array} items
953
- *
954
- * @returns {PromisePoolExecutor}
955
- */
956
- for(items) {
957
- this.meta.items = items;
958
- return this;
959
- }
960
- /**
961
- * Returns the list of items to process.
962
- *
963
- * @returns {T[]}
964
- */
965
- items() {
966
- return this.meta.items;
967
- }
968
- /**
969
- * Returns the number of items to process.
970
- *
971
- * @returns {Number}
972
- */
973
- itemsCount() {
974
- return this.items().length;
975
- }
976
- /**
977
- * Returns the list of active tasks.
978
- *
979
- * @returns {Array}
980
- */
981
- tasks() {
982
- return this.meta.tasks;
983
- }
984
- /**
985
- * Returns the number of currently active tasks.
986
- *
987
- * @returns {Number}
988
- *
989
- * @deprecated use the `activeTasksCount()` method (plural naming) instead
990
- */
991
- activeTaskCount() {
992
- return this.activeTasksCount();
993
- }
994
- /**
995
- * Returns the number of currently active tasks.
996
- *
997
- * @returns {Number}
998
- */
999
- activeTasksCount() {
1000
- return this.tasks().length;
1001
- }
1002
- /**
1003
- * Returns the list of processed items.
1004
- *
1005
- * @returns {T[]}
1006
- */
1007
- processedItems() {
1008
- return this.meta.processedItems;
1009
- }
1010
- /**
1011
- * Returns the number of processed items.
1012
- *
1013
- * @returns {Number}
1014
- */
1015
- processedCount() {
1016
- return this.processedItems().length;
1017
- }
1018
- /**
1019
- * Returns the percentage progress of items that have been processed.
1020
- */
1021
- processedPercentage() {
1022
- return (this.processedCount() / this.itemsCount()) * 100;
1023
- }
1024
- /**
1025
- * Returns the list of results.
1026
- *
1027
- * @returns {R[]}
1028
- */
1029
- results() {
1030
- return this.meta.results;
1031
- }
1032
- /**
1033
- * Returns the list of errors.
1034
- *
1035
- * @returns {Array<PromisePoolError<T>>}
1036
- */
1037
- errors() {
1038
- return this.meta.errors;
1039
- }
1040
- /**
1041
- * Set the handler that is applied to each item.
1042
- *
1043
- * @param {Function} action
1044
- *
1045
- * @returns {PromisePoolExecutor}
1046
- */
1047
- withHandler(action) {
1048
- this.handler = action;
1049
- return this;
1050
- }
1051
- /**
1052
- * Determine whether a custom error handle is available.
1053
- *
1054
- * @returns {Boolean}
1055
- */
1056
- hasErrorHandler() {
1057
- return !!this.errorHandler;
1058
- }
1059
- /**
1060
- * Set the error handler function to execute when an error occurs.
1061
- *
1062
- * @param {Function} errorHandler
1063
- *
1064
- * @returns {PromisePoolExecutor}
1065
- */
1066
- handleError(handler) {
1067
- this.errorHandler = handler;
1068
- return this;
1069
- }
1070
- /**
1071
- * Set the handler function to execute when started a task.
1072
- *
1073
- * @param {Function} handler
1074
- *
1075
- * @returns {this}
1076
- */
1077
- onTaskStarted(handlers) {
1078
- this.onTaskStartedHandlers = handlers;
1079
- return this;
1080
- }
1081
- /**
1082
- * Assign the given callback `handler` function to run when a task finished.
1083
- *
1084
- * @param {OnProgressCallback<T>} handlers
1085
- *
1086
- * @returns {this}
1087
- */
1088
- onTaskFinished(handlers) {
1089
- this.onTaskFinishedHandlers = handlers;
1090
- return this;
1091
- }
1092
- /**
1093
- * Determines whether the number of active tasks is greater or equal to the concurrency limit.
1094
- *
1095
- * @returns {Boolean}
1096
- */
1097
- hasReachedConcurrencyLimit() {
1098
- return this.activeTasksCount() >= this.concurrency();
1099
- }
1100
- /**
1101
- * Stop a promise pool processing.
1102
- */
1103
- stop() {
1104
- this.markAsStopped();
1105
- throw new stopThePromisePoolError.StopThePromisePoolError();
1106
- }
1107
- /**
1108
- * Mark the promise pool as stopped.
1109
- *
1110
- * @returns {PromisePoolExecutor}
1111
- */
1112
- markAsStopped() {
1113
- this.meta.stopped = true;
1114
- return this;
151
+ class SochainProvider {
152
+ constructor(baseUrl = 'https://sochain.com/api/v3', apiKey, chain, asset, assetDecimals, sochainNetwork) {
153
+ this.baseUrl = baseUrl;
154
+ this._apiKey = apiKey;
155
+ this.chain = chain;
156
+ this.asset = asset;
157
+ this.assetDecimals = assetDecimals;
158
+ this.sochainNetwork = sochainNetwork;
159
+ this.asset;
160
+ this.chain;
161
+ }
162
+ get apiKey() {
163
+ return this._apiKey;
164
+ }
165
+ set apiKey(value) {
166
+ this._apiKey = value;
167
+ }
168
+ broadcastTx(txHex) {
169
+ return __awaiter(this, void 0, void 0, function* () {
170
+ return yield broadcastTx$2({
171
+ apiKey: this._apiKey,
172
+ sochainUrl: this.baseUrl,
173
+ network: this.sochainNetwork,
174
+ txHex,
175
+ });
176
+ });
1115
177
  }
1116
- /**
1117
- * Determine whether the pool is stopped.
1118
- *
1119
- * @returns {Boolean}
1120
- */
1121
- isStopped() {
1122
- return this.meta.stopped;
178
+ getConfirmedUnspentTxs(address) {
179
+ return __awaiter(this, void 0, void 0, function* () {
180
+ const allUnspent = yield getUnspentTxs$1({
181
+ apiKey: this._apiKey,
182
+ sochainUrl: this.baseUrl,
183
+ network: this.sochainNetwork,
184
+ address,
185
+ page: 1,
186
+ });
187
+ const confirmedUnspent = allUnspent.filter((i) => i.block); //if it has a block noumber it's been confirmed
188
+ return this.mapUTXOs(confirmedUnspent);
189
+ });
1123
190
  }
1124
- /**
1125
- * Start processing the promise pool.
1126
- *
1127
- * @returns {ReturnValue}
1128
- */
1129
- async start() {
1130
- return await this
1131
- .validateInputs()
1132
- .prepareResultsArray()
1133
- .process();
191
+ getUnspentTxs(address) {
192
+ return __awaiter(this, void 0, void 0, function* () {
193
+ const allUnspent = yield getUnspentTxs$1({
194
+ apiKey: this._apiKey,
195
+ sochainUrl: this.baseUrl,
196
+ network: this.sochainNetwork,
197
+ address,
198
+ page: 1,
199
+ });
200
+ return this.mapUTXOs(allUnspent);
201
+ });
1134
202
  }
1135
- /**
1136
- * Determine whether the pool should stop.
1137
- *
1138
- * @returns {PromisePoolExecutor}
1139
- *
1140
- * @throws
1141
- */
1142
- validateInputs() {
1143
- if (typeof this.handler !== 'function') {
1144
- throw validationError.ValidationError.createFrom('The first parameter for the .process(fn) method must be a function');
1145
- }
1146
- const timeout = this.taskTimeout();
1147
- if (!(timeout == null || (typeof timeout === 'number' && timeout >= 0))) {
1148
- throw validationError.ValidationError.createFrom(`"timeout" must be undefined or a number. A number must be 0 or up. Received "${String(timeout)}" (${typeof timeout})`);
1149
- }
1150
- if (!Array.isArray(this.items())) {
1151
- throw validationError.ValidationError.createFrom(`"items" must be an array. Received "${typeof this.items()}"`);
1152
- }
1153
- if (this.errorHandler && typeof this.errorHandler !== 'function') {
1154
- throw validationError.ValidationError.createFrom(`The error handler must be a function. Received "${typeof this.errorHandler}"`);
1155
- }
1156
- this.onTaskStartedHandlers.forEach(handler => {
1157
- if (handler && typeof handler !== 'function') {
1158
- throw validationError.ValidationError.createFrom(`The onTaskStarted handler must be a function. Received "${typeof handler}"`);
203
+ getBalance(address, assets /*ignored*/, confirmedOnly) {
204
+ return __awaiter(this, void 0, void 0, function* () {
205
+ try {
206
+ const amount = yield getBalance$2({
207
+ apiKey: this._apiKey,
208
+ sochainUrl: this.baseUrl,
209
+ network: this.sochainNetwork,
210
+ address,
211
+ confirmedOnly: !!confirmedOnly,
212
+ assetDecimals: this.assetDecimals,
213
+ });
214
+ return [{ amount, asset: this.asset }];
1159
215
  }
1160
- });
1161
- this.onTaskFinishedHandlers.forEach(handler => {
1162
- if (handler && typeof handler !== 'function') {
1163
- throw validationError.ValidationError.createFrom(`The error handler must be a function. Received "${typeof handler}"`);
216
+ catch (error) {
217
+ throw new Error(`Could not get balances for address ${address}`);
1164
218
  }
1165
219
  });
1166
- return this;
1167
- }
1168
- /**
1169
- * Prefill the results array with `notRun` symbol values if results should correspond.
1170
- */
1171
- prepareResultsArray() {
1172
- if (this.shouldUseCorrespondingResults()) {
1173
- this.meta.results = Array(this.items().length).fill(promisePool.PromisePool.notRun);
1174
- }
1175
- return this;
1176
220
  }
1177
221
  /**
1178
- * Starts processing the promise pool by iterating over the items
1179
- * and running each item through the async `callback` function.
222
+ * Get transaction history of a given address with pagination options.
223
+ * By default it will return the transaction history of the current wallet.
1180
224
  *
1181
- * @param {Function} callback
1182
- *
1183
- * @returns {Promise}
225
+ * @param {TxHistoryParams} params The options to get transaction history. (optional)
226
+ * @returns {TxsPage} The transaction history.
1184
227
  */
1185
- async process() {
1186
- for (const [index, item] of this.items().entries()) {
1187
- if (this.isStopped()) {
1188
- break;
228
+ getTransactions(params) {
229
+ var _a;
230
+ return __awaiter(this, void 0, void 0, function* () {
231
+ const offset = (_a = params === null || params === void 0 ? void 0 : params.offset) !== null && _a !== void 0 ? _a : 0;
232
+ const limit = (params === null || params === void 0 ? void 0 : params.limit) || 10;
233
+ if (offset < 0 || limit < 0)
234
+ throw Error('ofset and limit must be equal or greater than 0');
235
+ const firstPage = Math.floor(offset / 10) + 1;
236
+ const lastPage = limit > 10 ? firstPage + Math.floor(limit / 10) : firstPage;
237
+ const offsetOnFirstPage = offset % 10;
238
+ const txHashesToFetch = [];
239
+ let page = firstPage;
240
+ try {
241
+ while (page <= lastPage) {
242
+ const response = yield getTxs$2({
243
+ apiKey: this._apiKey,
244
+ sochainUrl: this.baseUrl,
245
+ network: this.sochainNetwork,
246
+ address: `${params === null || params === void 0 ? void 0 : params.address}`,
247
+ page,
248
+ });
249
+ if (response.transactions.length === 0)
250
+ break;
251
+ if (page === firstPage && response.transactions.length > offsetOnFirstPage) {
252
+ //start from offset
253
+ const txsToGet = response.transactions.slice(offsetOnFirstPage);
254
+ this.addArrayUpToLimit(txHashesToFetch, txsToGet.map((i) => i.hash), limit);
255
+ }
256
+ else {
257
+ this.addArrayUpToLimit(txHashesToFetch, response.transactions.map((i) => i.hash), limit);
258
+ }
259
+ page++;
260
+ }
1189
261
  }
1190
- await this.waitForProcessingSlot();
1191
- this.startProcessing(item, index);
1192
- }
1193
- return await this.drained();
1194
- }
1195
- /**
1196
- * Wait for one of the active tasks to finish processing.
1197
- */
1198
- async waitForProcessingSlot() {
1199
- /**
1200
- * We’re using a while loop here because it’s possible to decrease the pool’s
1201
- * concurrency at runtime. We need to wait for as many tasks as needed to
1202
- * finish processing before moving on to process the remaining tasks.
1203
- */
1204
- while (this.hasReachedConcurrencyLimit()) {
1205
- await this.waitForActiveTaskToFinish();
1206
- }
1207
- }
1208
- /**
1209
- * Wait for the next, currently active task to finish processing.
1210
- */
1211
- async waitForActiveTaskToFinish() {
1212
- await Promise.race(this.tasks());
262
+ catch (error) {
263
+ console.error(error);
264
+ //an errors means no more results
265
+ }
266
+ const total = txHashesToFetch.length;
267
+ const transactions = yield Promise.all(txHashesToFetch.map((hash) => this.getTransactionData(hash)));
268
+ const result = {
269
+ total,
270
+ txs: transactions,
271
+ };
272
+ return result;
273
+ });
1213
274
  }
1214
275
  /**
1215
- * Create a processing function for the given `item`.
1216
- *
1217
- * @param {T} item
1218
- * @param {number} index
1219
- */
1220
- startProcessing(item, index) {
1221
- const task = this.createTaskFor(item, index)
1222
- .then(result => {
1223
- this.save(result, index).removeActive(task);
1224
- })
1225
- .catch(async (error) => {
1226
- await this.handleErrorFor(error, item, index);
1227
- this.removeActive(task);
1228
- })
1229
- .finally(() => {
1230
- this.processedItems().push(item);
1231
- this.runOnTaskFinishedHandlers(item);
276
+ * Get the transaction details of a given transaction id.
277
+ *
278
+ * @param {string} txId The transaction id.
279
+ * @returns {Tx} The transaction details of the given transaction id.
280
+ */
281
+ getTransactionData(txId) {
282
+ return __awaiter(this, void 0, void 0, function* () {
283
+ try {
284
+ const rawTx = yield getTx$2({
285
+ apiKey: this._apiKey,
286
+ sochainUrl: this.baseUrl,
287
+ network: this.sochainNetwork,
288
+ hash: txId,
289
+ });
290
+ return {
291
+ asset: this.asset,
292
+ from: rawTx.inputs.map((i) => ({
293
+ from: i.address,
294
+ amount: xchainUtil.assetToBase(xchainUtil.assetAmount(i.value, this.assetDecimals)),
295
+ })),
296
+ to: rawTx.outputs
297
+ .filter((i) => i.type !== 'nulldata') //filter out op_return outputs
298
+ .map((i) => ({ to: i.address, amount: xchainUtil.assetToBase(xchainUtil.assetAmount(i.value, this.assetDecimals)) })),
299
+ date: new Date(rawTx.time * 1000),
300
+ type: xchainClient.TxType.Transfer,
301
+ hash: rawTx.hash,
302
+ };
303
+ }
304
+ catch (error) {
305
+ console.error(error);
306
+ throw error;
307
+ }
1232
308
  });
1233
- this.tasks().push(task);
1234
- this.runOnTaskStartedHandlers(item);
1235
309
  }
1236
- /**
1237
- * Ensures a returned promise for the processing of the given `item`.
1238
- *
1239
- * @param {T} item
1240
- * @param {number} index
1241
- *
1242
- * @returns {*}
1243
- */
1244
- async createTaskFor(item, index) {
1245
- if (this.taskTimeout() === undefined) {
1246
- return this.handler(item, index, this);
310
+ mapUTXOs(utxos) {
311
+ return utxos.map((utxo) => ({
312
+ hash: utxo.hash,
313
+ index: utxo.index,
314
+ value: xchainUtil.assetToBase(xchainUtil.assetAmount(utxo.value, this.assetDecimals)).amount().toNumber(),
315
+ witnessUtxo: {
316
+ value: xchainUtil.assetToBase(xchainUtil.assetAmount(utxo.value, this.assetDecimals)).amount().toNumber(),
317
+ script: Buffer.from(utxo.script, 'hex'),
318
+ },
319
+ txHex: utxo.tx_hex,
320
+ }));
321
+ }
322
+ /**
323
+ * helper function tto limit adding to an array
324
+ *
325
+ * @param arr array to be added to
326
+ * @param toAdd elements to add
327
+ * @param limit do not add more than this limit
328
+ */
329
+ addArrayUpToLimit(arr, toAdd, limit) {
330
+ for (let index = 0; index < toAdd.length; index++) {
331
+ const element = toAdd[index];
332
+ if (arr.length < limit) {
333
+ arr.push(element);
334
+ }
1247
335
  }
1248
- return Promise.race([
1249
- this.handler(item, index, this),
1250
- this.createTaskTimeout(item)
1251
- ]);
1252
336
  }
1253
- /**
1254
- * Returns a promise that times-out after the configured task timeout.
1255
- */
1256
- async createTaskTimeout(item) {
1257
- return new Promise((_resolve, reject) => {
1258
- setTimeout(() => {
1259
- reject(new promisePoolError.PromisePoolError(`Promise in pool timed out after ${this.taskTimeout()}ms`, item));
1260
- }, this.taskTimeout());
337
+ }
338
+
339
+ /**
340
+ * Haskoin API types
341
+ */
342
+ exports.HaskoinNetwork = void 0;
343
+ (function (HaskoinNetwork) {
344
+ HaskoinNetwork["BTC"] = "btc";
345
+ HaskoinNetwork["BTCTEST"] = "btctest";
346
+ HaskoinNetwork["BCH"] = "bch";
347
+ HaskoinNetwork["BCHTEST"] = "bchtest";
348
+ })(exports.HaskoinNetwork || (exports.HaskoinNetwork = {}));
349
+
350
+ /**
351
+ * Module to interact with Haskoin API
352
+ *
353
+ * Doc (SwaggerHub) https://app.swaggerhub.com/apis/eligecode/blockchain-api/0.0.1-oas3
354
+ *
355
+ */
356
+ /**
357
+ * Check error response.
358
+ *
359
+ * @param {any} response The api response.
360
+ * @returns {boolean}
361
+ */
362
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
363
+ const isErrorResponse = (response) => {
364
+ return !!response.error;
365
+ };
366
+ /**
367
+ * Get account from address.
368
+ *
369
+ * @param {string} haskoinUrl The haskoin API url.
370
+ * @param {string} address The BCH address.
371
+ * @returns {AddressBalance}
372
+ *
373
+ * @throws {"failed to query account by a given address"} thrown if failed to query account by a given address
374
+ */
375
+ const getAccount = ({ haskoinUrl, network, address }) => __awaiter(void 0, void 0, void 0, function* () {
376
+ const url = `${haskoinUrl}/${network}/address/${address}/balance`;
377
+ const result = (yield axios__default["default"].get(url)).data;
378
+ if (!result || isErrorResponse(result))
379
+ throw new Error(`failed to query account by given address ${address}`);
380
+ return result;
381
+ });
382
+ /**
383
+ * Get address information.
384
+ *
385
+ * @param {string} haskoinUrl The haskoin node url.
386
+ * @param {string} network
387
+ * @param {string} address
388
+ * @returns {AddressDTO}
389
+ */
390
+ const getAddress = ({ haskoinUrl, network, address }) => __awaiter(void 0, void 0, void 0, function* () {
391
+ const url = `${haskoinUrl}/${network}/address/${address}/balance`;
392
+ const response = yield axios__default["default"].get(url);
393
+ const addressResponse = response.data;
394
+ return addressResponse.data;
395
+ });
396
+ /**
397
+ * Get transaction by hash.
398
+ *
399
+ * @param {string} haskoinUrl The haskoin API url.
400
+ * @param {string} txId The transaction id.
401
+ * @returns {Transaction}
402
+ *
403
+ * @throws {"failed to query transaction by a given hash"} thrown if failed to query transaction by a given hash
404
+ */
405
+ const getTx$1 = ({ haskoinUrl, txId, network }) => __awaiter(void 0, void 0, void 0, function* () {
406
+ const result = (yield axios__default["default"].get(`${haskoinUrl}/${network}/transaction/${txId}`)).data;
407
+ if (!result || isErrorResponse(result))
408
+ throw new Error(`failed to query transaction by a given hash ${txId}`);
409
+ return result;
410
+ });
411
+ /**
412
+ * Get raw transaction by hash.
413
+ *
414
+ * @param {string} haskoinUrl The haskoin API url.
415
+ * @param {string} txId The transaction id.
416
+ * @returns {Transaction}
417
+ *
418
+ * @throws {"failed to query transaction by a given hash"} thrown if failed to query raw transaction by a given hash
419
+ */
420
+ const getRawTransaction = ({ haskoinUrl, network, txId }) => __awaiter(void 0, void 0, void 0, function* () {
421
+ const result = (yield axios__default["default"].get(`${haskoinUrl}/${network}/transaction/${txId}/raw`))
422
+ .data;
423
+ if (!result || isErrorResponse(result))
424
+ throw new Error(`failed to query transaction by a given hash ${txId}`);
425
+ return result.result;
426
+ });
427
+ /**
428
+ * Get transactions
429
+ *
430
+ * @see https://haskoin.com/api#get-tx
431
+ *
432
+ * @param {string} haskoinUrl The haskoin node url.
433
+ * @param {string} network network id
434
+ * @param {string} hash The transaction hash.
435
+ * @returns {Transactions}
436
+ */
437
+ const getTxs$1 = ({ address, haskoinUrl, network, limit, offset, }) => __awaiter(void 0, void 0, void 0, function* () {
438
+ const params = { limit: `${limit}`, offset: `${offset}` };
439
+ const url = `${haskoinUrl}/${network}/address/${address}/transactions/full`;
440
+ const result = (yield axios__default["default"].get(url, { params })).data;
441
+ if (!result || isErrorResponse(result))
442
+ throw new Error('failed to query transactions');
443
+ return result;
444
+ });
445
+ /**
446
+ *
447
+ * @param param
448
+ * @returns Returns BaseAmount
449
+ */
450
+ const getBalance$1 = ({ haskoinUrl, haskoinNetwork, address, confirmedOnly, assetDecimals, }) => __awaiter(void 0, void 0, void 0, function* () {
451
+ const { data: { confirmed, unconfirmed }, } = yield axios__default["default"].get(`${haskoinUrl}/${haskoinNetwork}/address/${address}/balance`);
452
+ const confirmedAmount = xchainUtil.baseAmount(confirmed, assetDecimals);
453
+ const unconfirmedAmount = xchainUtil.baseAmount(unconfirmed, assetDecimals);
454
+ return confirmedOnly ? confirmedAmount : confirmedAmount.plus(unconfirmedAmount);
455
+ });
456
+ /**
457
+ * Get unspent transactions.
458
+ *
459
+ * @param {string} haskoinUrl The haskoin API url.
460
+ * @param {string} address The BCH address.
461
+ * @returns {TxUnspent[]}
462
+ *
463
+ * @throws {"failed to query unspent transactions"} thrown if failed to query unspent transactions
464
+ */
465
+ const getUnspentTxs = ({ haskoinUrl, network, address }) => __awaiter(void 0, void 0, void 0, function* () {
466
+ // Get transaction count for a given address.
467
+ const account = yield getAccount({ haskoinUrl, network, address });
468
+ // Set limit to the transaction count to be all the utxos.
469
+ const result = (yield axios__default["default"].get(`${haskoinUrl}/${network}/address/${address}/unspent?limit${account === null || account === void 0 ? void 0 : account.utxo}`)).data;
470
+ if (!result || isErrorResponse(result))
471
+ throw new Error('failed to query unspent transactions');
472
+ return result;
473
+ });
474
+ /**
475
+ * Get Tx Confirmation status
476
+ *
477
+ * @param {string} haskoinUrl The haskoin node url.
478
+ * @param {Network} network
479
+ * @param {string} hash tx id
480
+ * @returns {TxConfirmedStatus}
481
+ */
482
+ const getIsTxConfirmed = ({ haskoinUrl, network, txId }) => __awaiter(void 0, void 0, void 0, function* () {
483
+ const tx = yield getTx$1({ haskoinUrl, network, txId });
484
+ return {
485
+ network: network,
486
+ txid: txId,
487
+ confirmations: tx.confirmations,
488
+ is_confirmed: tx.confirmations >= 1,
489
+ };
490
+ });
491
+ /**
492
+ * List of confirmed txs
493
+ *
494
+ * Stores a list of confirmed txs (hashes) in memory to avoid requesting same data
495
+ */
496
+ const confirmedTxs = [];
497
+ /**
498
+ * Helper to get `confirmed` status of a tx.
499
+ *
500
+ * It will get it from cache or try to get it from haskoin (if not cached before)
501
+ */
502
+ const getConfirmedTxStatus = ({ txHash, haskoinUrl, network, }) => __awaiter(void 0, void 0, void 0, function* () {
503
+ // try to get it from cache
504
+ if (confirmedTxs.includes(txHash))
505
+ return true;
506
+ // or get status from haskoin
507
+ const { is_confirmed } = yield getIsTxConfirmed({
508
+ haskoinUrl,
509
+ network,
510
+ txId: txHash,
511
+ });
512
+ // cache status
513
+ confirmedTxs.push(txHash);
514
+ return is_confirmed;
515
+ });
516
+ /**
517
+ * Get unspent txs and filter out pending UTXOs
518
+ *
519
+ * @see https://haskoin.com/api#get-unspent-tx
520
+ *
521
+ * @param {string} haskoinUrl The haskoin node url.
522
+ * @param {Network} network
523
+ * @param {string} address
524
+ * @returns {AddressUTXO[]}
525
+ */
526
+ const getConfirmedUnspentTxs = ({ haskoinUrl, network, address }) => __awaiter(void 0, void 0, void 0, function* () {
527
+ const txs = yield getUnspentTxs({
528
+ haskoinUrl,
529
+ network,
530
+ address,
531
+ });
532
+ const confirmedUTXOs = [];
533
+ yield Promise.all(txs.map((tx) => __awaiter(void 0, void 0, void 0, function* () {
534
+ const confirmed = yield getConfirmedTxStatus({
535
+ haskoinUrl,
536
+ network,
537
+ txHash: tx.txid,
1261
538
  });
1262
- }
1263
- /**
1264
- * Save the given calculation `result`, possibly at the provided `position`.
1265
- *
1266
- * @param {*} result
1267
- * @param {number} position
1268
- *
1269
- * @returns {PromisePoolExecutor}
1270
- */
1271
- save(result, position) {
1272
- this.shouldUseCorrespondingResults()
1273
- ? this.results()[position] = result
1274
- : this.results().push(result);
1275
- return this;
1276
- }
1277
- /**
1278
- * Remove the given `task` from the list of active tasks.
1279
- *
1280
- * @param {Promise} task
1281
- */
1282
- removeActive(task) {
1283
- this.tasks().splice(this.tasks().indexOf(task), 1);
1284
- return this;
1285
- }
1286
- /**
1287
- * Create and save an error for the the given `item`.
1288
- *
1289
- * @param {Error} error
1290
- * @param {T} item
1291
- * @param {number} index
1292
- */
1293
- async handleErrorFor(error, item, index) {
1294
- if (this.shouldUseCorrespondingResults()) {
1295
- this.results()[index] = promisePool.PromisePool.failed;
1296
- }
1297
- if (this.isStoppingThePoolError(error)) {
1298
- return;
539
+ if (confirmed) {
540
+ confirmedUTXOs.push(tx);
1299
541
  }
1300
- if (this.isValidationError(error)) {
1301
- this.markAsStopped();
1302
- throw error;
1303
- }
1304
- this.hasErrorHandler()
1305
- ? await this.runErrorHandlerFor(error, item)
1306
- : this.saveErrorFor(error, item);
1307
- }
1308
- /**
1309
- * Determine whether the given `error` is a `StopThePromisePoolError` instance.
1310
- *
1311
- * @param {Error} error
1312
- *
1313
- * @returns {Boolean}
1314
- */
1315
- isStoppingThePoolError(error) {
1316
- return error instanceof stopThePromisePoolError.StopThePromisePoolError;
1317
- }
1318
- /**
1319
- * Determine whether the given `error` is a `ValidationError` instance.
1320
- *
1321
- * @param {Error} error
1322
- *
1323
- * @returns {Boolean}
1324
- */
1325
- isValidationError(error) {
1326
- return error instanceof validationError.ValidationError;
1327
- }
1328
- /**
1329
- * Run the user’s error handler, if available.
1330
- *
1331
- * @param {Error} processingError
1332
- * @param {T} item
1333
- */
1334
- async runErrorHandlerFor(processingError, item) {
1335
- var _a;
542
+ })));
543
+ return confirmedUTXOs;
544
+ });
545
+ // Stores list of txHex in memory to avoid requesting same data
546
+ const txHexMap = {};
547
+ /**
548
+ * Helper to get `hex` of `Tx`
549
+ *
550
+ * It will try to get it from cache before requesting it from Sochain
551
+ */
552
+ const getTxHex = ({ haskoinUrl, network, txId }) => __awaiter(void 0, void 0, void 0, function* () {
553
+ // try to get hex from cache
554
+ let txHex = txHexMap[txId];
555
+ if (!!txHex)
556
+ return txHex;
557
+ // or get it from Haskoin
558
+ txHex = yield getRawTransaction({ haskoinUrl, txId: txId, network: network });
559
+ // cache it
560
+ txHexMap[txId] = txHex;
561
+ return txHex;
562
+ });
563
+ /**
564
+ * Get unspent transactions.
565
+ *
566
+ * @param {string} haskoinUrl The haskoin API url.
567
+ * @param {string} address The BCH address.
568
+ * @returns {TxUnspent[]}
569
+ *
570
+ * @throws {"failed to query unspent transactions"} thrown if failed to query unspent transactions
571
+ */
572
+ const getUnspentTransactions = ({ haskoinUrl, network, address }) => __awaiter(void 0, void 0, void 0, function* () {
573
+ // Get transaction count for a given address.
574
+ const account = yield getAccount({ haskoinUrl, network, address });
575
+ // Set limit to the transaction count to be all the utxos.
576
+ const result = (yield axios__default["default"].get(`${haskoinUrl}/${network}/address/${address}/unspent?limit${account === null || account === void 0 ? void 0 : account.utxo}`)).data;
577
+ if (!result || isErrorResponse(result))
578
+ throw new Error('failed to query unspent transactions');
579
+ return result;
580
+ });
581
+ /**
582
+ * Broadcast transaction.
583
+ *
584
+ * @see https://app.swaggerhub.com/apis/eligecode/blockchain-api/0.0.1-oas3#/blockchain/sendTransaction
585
+ *
586
+ * Note: Because of an Haskoin issue (@see https://github.com/haskoin/haskoin-store/issues/25),
587
+ * we need to broadcast same tx several times in case of `500` errors
588
+ * @see https://github.com/xchainjs/xchainjs-lib/issues/492
589
+ *
590
+ * @param {BroadcastTxParams} params
591
+ * @returns {TxHash} Transaction hash.
592
+ */
593
+ const broadcastTx$1 = ({ txHex, haskoinUrl, haskoinNetwork, }) => __awaiter(void 0, void 0, void 0, function* () {
594
+ var _a;
595
+ const MAX_RETRIES = 5;
596
+ let retries = 0;
597
+ const axiosInstance = axios__default["default"].create();
598
+ const url = `${haskoinUrl}/${haskoinNetwork}/transactions`;
599
+ while (retries < MAX_RETRIES) {
1336
600
  try {
1337
- await ((_a = this.errorHandler) === null || _a === void 0 ? void 0 : _a.call(this, processingError, item, this));
601
+ const response = yield axiosInstance.post(url, txHex);
602
+ const { txid } = response.data;
603
+ return txid;
1338
604
  }
1339
605
  catch (error) {
1340
- this.rethrowIfNotStoppingThePool(error);
606
+ if (((_a = error.response) === null || _a === void 0 ? void 0 : _a.status) === 500) {
607
+ retries++;
608
+ yield xchainUtil.delay(200 * retries);
609
+ }
610
+ else {
611
+ return Promise.reject(error);
612
+ }
1341
613
  }
1342
614
  }
1343
- /**
1344
- * Run the onTaskStarted handlers.
1345
- */
1346
- runOnTaskStartedHandlers(item) {
1347
- this.onTaskStartedHandlers.forEach(handler => {
1348
- handler(item, this);
615
+ return Promise.reject(new Error('Max retries exceeded'));
616
+ });
617
+
618
+ class HaskoinProvider {
619
+ constructor(baseUrl = 'https://api.haskoin.com/', chain, asset, assetDecimals, haskoinNetwork) {
620
+ this.baseUrl = baseUrl;
621
+ this.chain = chain;
622
+ this.asset = asset;
623
+ this.assetDecimals = assetDecimals;
624
+ this.haskoinNetwork = haskoinNetwork;
625
+ this.asset;
626
+ this.chain;
627
+ }
628
+ broadcastTx(txHex) {
629
+ return __awaiter(this, void 0, void 0, function* () {
630
+ return yield broadcastTx$1({
631
+ haskoinUrl: this.baseUrl,
632
+ haskoinNetwork: this.haskoinNetwork,
633
+ txHex,
634
+ });
1349
635
  });
1350
636
  }
1351
- /**
1352
- * Run the onTaskFinished handlers.
1353
- */
1354
- runOnTaskFinishedHandlers(item) {
1355
- this.onTaskFinishedHandlers.forEach(handler => {
1356
- handler(item, this);
637
+ getConfirmedUnspentTxs(address) {
638
+ return __awaiter(this, void 0, void 0, function* () {
639
+ const allUnspent = yield getUnspentTransactions({
640
+ haskoinUrl: this.baseUrl,
641
+ network: this.haskoinNetwork,
642
+ address,
643
+ });
644
+ const confirmedUnspent = allUnspent.filter((i) => i.block); //if it has a block noumber it's been confirmed
645
+ return this.mapUTXOs(confirmedUnspent);
1357
646
  });
1358
647
  }
1359
- /**
1360
- * Rethrow the given `error` if it’s not an instance of `StopThePromisePoolError`.
1361
- *
1362
- * @param {Error} error
1363
- */
1364
- rethrowIfNotStoppingThePool(error) {
1365
- if (this.isStoppingThePoolError(error)) {
1366
- return;
1367
- }
1368
- throw error;
648
+ getUnspentTxs(address) {
649
+ return __awaiter(this, void 0, void 0, function* () {
650
+ const allUnspent = yield getUnspentTxs({
651
+ haskoinUrl: this.baseUrl,
652
+ network: this.haskoinNetwork,
653
+ address,
654
+ });
655
+ return yield this.mapUTXOs(allUnspent);
656
+ });
1369
657
  }
1370
- /**
1371
- * Create and save an error for the the given `item`.
1372
- *
1373
- * @param {T} item
1374
- */
1375
- saveErrorFor(error, item) {
1376
- this.errors().push(promisePoolError.PromisePoolError.createFrom(error, item));
658
+ getBalance(address, assets /*ignored*/, confirmedOnly) {
659
+ return __awaiter(this, void 0, void 0, function* () {
660
+ const amount = yield getBalance$1({
661
+ haskoinUrl: this.baseUrl,
662
+ haskoinNetwork: this.haskoinNetwork,
663
+ address,
664
+ confirmedOnly: !!confirmedOnly,
665
+ assetDecimals: this.assetDecimals,
666
+ });
667
+ return [{ amount, asset: this.asset }];
668
+ });
1377
669
  }
1378
670
  /**
1379
- * Wait for all active tasks to finish. Once all the tasks finished
1380
- * processing, returns an object containing the results and errors.
671
+ * Get transaction history of a given address with pagination options.
672
+ * By default it will return the transaction history of the current wallet.
1381
673
  *
1382
- * @returns {Object}
674
+ * @param {TxHistoryParams} params The options to get transaction history. (optional)
675
+ * @returns {TxsPage} The transaction history.
1383
676
  */
1384
- async drained() {
1385
- await this.drainActiveTasks();
677
+ getTransactions(params) {
678
+ var _a;
679
+ return __awaiter(this, void 0, void 0, function* () {
680
+ const offset = (_a = params === null || params === void 0 ? void 0 : params.offset) !== null && _a !== void 0 ? _a : 0;
681
+ const limit = (params === null || params === void 0 ? void 0 : params.limit) || 10;
682
+ if (offset + limit > 2000)
683
+ throw Error('cannot fetch more than last 2000 txs');
684
+ if (offset < 0 || limit < 0)
685
+ throw Error('ofset and limit must be equal or greater than 0');
686
+ const response = yield getTxs$1({
687
+ address: `${params === null || params === void 0 ? void 0 : params.address}`,
688
+ haskoinUrl: this.baseUrl,
689
+ network: this.haskoinNetwork,
690
+ limit: limit,
691
+ offset,
692
+ });
693
+ const txs = response.map((i) => this.mapTransactionToTx(i));
694
+ const result = {
695
+ total: txs.length,
696
+ txs: txs,
697
+ };
698
+ return result;
699
+ });
700
+ }
701
+ mapTransactionToTx(rawTx) {
1386
702
  return {
1387
- errors: this.errors(),
1388
- results: this.results()
703
+ asset: this.asset,
704
+ from: rawTx.inputs.map((i) => ({
705
+ from: i.address,
706
+ amount: xchainUtil.baseAmount(i.value, this.assetDecimals),
707
+ })),
708
+ to: rawTx.outputs
709
+ .filter((i) => i.script !== 'null-data') //filter out op_return outputs
710
+ .map((i) => ({ to: i.address, amount: xchainUtil.baseAmount(i.value, this.assetDecimals) })),
711
+ date: new Date(rawTx.time),
712
+ type: xchainClient.TxType.Transfer,
713
+ hash: rawTx.txid,
1389
714
  };
1390
715
  }
1391
716
  /**
1392
- * Wait for all of the active tasks to finish processing.
1393
- */
1394
- async drainActiveTasks() {
1395
- await Promise.all(this.tasks());
1396
- }
1397
- }
1398
- exports.PromisePoolExecutor = PromisePoolExecutor;
1399
- });
1400
-
1401
- unwrapExports(promisePoolExecutor);
1402
- var promisePoolExecutor_1 = promisePoolExecutor.PromisePoolExecutor;
1403
-
1404
- var promisePool = createCommonjsModule(function (module, exports) {
1405
- Object.defineProperty(exports, "__esModule", { value: true });
1406
- exports.PromisePool = void 0;
1407
-
1408
- class PromisePool {
1409
- /**
1410
- * Instantiates a new promise pool with a default `concurrency: 10` and `items: []`.
717
+ * Get the transaction details of a given transaction id.
1411
718
  *
1412
- * @param {Object} options
719
+ * @param {string} txId The transaction id.
720
+ * @returns {Tx} The transaction details of the given transaction id.
1413
721
  */
1414
- constructor(items) {
1415
- this.timeout = undefined;
1416
- this.concurrency = 10;
1417
- this.shouldResultsCorrespond = false;
1418
- this.items = items !== null && items !== void 0 ? items : [];
1419
- this.errorHandler = undefined;
1420
- this.onTaskStartedHandlers = [];
1421
- this.onTaskFinishedHandlers = [];
722
+ getTransactionData(txId) {
723
+ return __awaiter(this, void 0, void 0, function* () {
724
+ try {
725
+ const rawTx = yield getTx$1({
726
+ haskoinUrl: this.baseUrl,
727
+ network: this.haskoinNetwork,
728
+ txId: txId,
729
+ });
730
+ return this.mapTransactionToTx(rawTx);
731
+ }
732
+ catch (error) {
733
+ console.error(error);
734
+ throw error;
735
+ }
736
+ });
1422
737
  }
1423
738
  /**
1424
- * Set the number of tasks to process concurrently in the promise pool.
1425
- *
1426
- * @param {Integer} concurrency
1427
739
  *
1428
- * @returns {PromisePool}
1429
- */
1430
- withConcurrency(concurrency) {
1431
- this.concurrency = concurrency;
1432
- return this;
740
+ * @param utxos
741
+ * @returns utxo array
742
+ */
743
+ mapUTXOs(utxos) {
744
+ return __awaiter(this, void 0, void 0, function* () {
745
+ return yield Promise.all(utxos.map((utxo) => __awaiter(this, void 0, void 0, function* () {
746
+ return ({
747
+ hash: utxo.txid,
748
+ index: utxo.index,
749
+ value: xchainUtil.baseAmount(utxo.value, this.assetDecimals).amount().toNumber(),
750
+ witnessUtxo: {
751
+ value: xchainUtil.baseAmount(utxo.value, this.assetDecimals).amount().toNumber(),
752
+ script: Buffer.from(utxo.pkscript, 'hex'),
753
+ },
754
+ txHex: yield getTxHex({ haskoinUrl: this.baseUrl, txId: utxo.txid, network: this.haskoinNetwork }),
755
+ });
756
+ })));
757
+ });
1433
758
  }
1434
- /**
1435
- * Set the number of tasks to process concurrently in the promise pool.
1436
- *
1437
- * @param {Number} concurrency
1438
- *
1439
- * @returns {PromisePool}
1440
- */
1441
- static withConcurrency(concurrency) {
1442
- return new this().withConcurrency(concurrency);
759
+ }
760
+
761
+ /**
762
+ * Get transaction by hash.
763
+ *
764
+ *
765
+ * @param {string} baseUrl The sochain node url.
766
+ * @param {string} network network id
767
+ * @param {string} hash The transaction hash.
768
+ * @returns {Transactions}
769
+ */
770
+ const getTx = ({ apiKey, baseUrl, network, hash }) => __awaiter(void 0, void 0, void 0, function* () {
771
+ const params = { includeHex: 'true' };
772
+ if (apiKey)
773
+ params['token'] = apiKey;
774
+ const url = `${baseUrl}/${network}/txs/${hash}`;
775
+ const response = yield axios__default["default"].get(url, { params });
776
+ const tx = response.data;
777
+ return tx;
778
+ });
779
+ /**
780
+ * Get transactions
781
+ *
782
+ *
783
+ * @param {string} baseUrl The sochain node url.
784
+ * @param {string} network network id
785
+ * @param {string} hash The transaction hash.
786
+ * @returns {Transactions}
787
+ */
788
+ const getTxs = ({ apiKey, address, baseUrl, network, beforeBlock, limit, unspentOnly, }) => __awaiter(void 0, void 0, void 0, function* () {
789
+ const params = { limit: `${limit}`, unspentOnly: `${unspentOnly}` };
790
+ const url = `${baseUrl}/${network}/addrs/${address}`;
791
+ if (apiKey)
792
+ params['token'] = apiKey;
793
+ if (beforeBlock)
794
+ params['before'] = `${beforeBlock}`;
795
+ const response = yield axios__default["default"].get(url, { params });
796
+ const txs = response.data;
797
+ return txs;
798
+ });
799
+ /**
800
+ * Get address balance.
801
+ *
802
+ *
803
+ * @param {string} baseUrl The sochain node url.
804
+ * @param {string} network Network
805
+ * @param {string} address Address
806
+ * @param {boolean} confirmedOnly Flag whether to get balances of confirmed txs only or for all
807
+ * @returns {number}
808
+ */
809
+ const getBalance = ({ apiKey, baseUrl, network, address, confirmedOnly, assetDecimals, }) => __awaiter(void 0, void 0, void 0, function* () {
810
+ const params = {};
811
+ const url = `${baseUrl}/${network}/addrs/${address}/balance`;
812
+ if (apiKey)
813
+ params['token'] = apiKey;
814
+ const response = yield axios__default["default"].get(url, { params });
815
+ const balanceResponse = response.data;
816
+ const confirmedAmount = xchainUtil.baseAmount(balanceResponse.balance, assetDecimals);
817
+ const finalBalance = xchainUtil.baseAmount(balanceResponse.final_balance, assetDecimals);
818
+ return confirmedOnly ? confirmedAmount : finalBalance;
819
+ });
820
+ const broadcastTx = ({ apiKey, baseUrl, network, txHex, }) => __awaiter(void 0, void 0, void 0, function* () {
821
+ const params = {};
822
+ const url = `${baseUrl}/${network}/txs/push`;
823
+ if (apiKey)
824
+ params['token'] = apiKey;
825
+ const response = yield axios__default["default"].post(url, { tx: txHex }, { params });
826
+ const broadcastResponse = response.data;
827
+ return broadcastResponse.tx.hash;
828
+ });
829
+
830
+ class BlockcypherProvider {
831
+ constructor(baseUrl = 'https://api.blockcypher.com/v1/', chain, asset, assetDecimals, blockcypherNetwork, apiKey) {
832
+ this.baseUrl = baseUrl;
833
+ this._apiKey = apiKey;
834
+ this.chain = chain;
835
+ this.asset = asset;
836
+ this.assetDecimals = assetDecimals;
837
+ this.blockcypherNetwork = blockcypherNetwork;
838
+ this.asset;
839
+ this.chain;
840
+ }
841
+ get apiKey() {
842
+ return this._apiKey;
843
+ }
844
+ set apiKey(value) {
845
+ this._apiKey = value;
846
+ }
847
+ broadcastTx(txHex) {
848
+ return __awaiter(this, void 0, void 0, function* () {
849
+ return yield broadcastTx({
850
+ apiKey: this._apiKey,
851
+ baseUrl: this.baseUrl,
852
+ network: this.blockcypherNetwork,
853
+ txHex,
854
+ });
855
+ });
1443
856
  }
1444
- /**
1445
- * Set the timeout in milliseconds for the pool handler.
1446
- *
1447
- * @param {Number} timeout
1448
- *
1449
- * @returns {PromisePool}
1450
- */
1451
- withTaskTimeout(timeout) {
1452
- this.timeout = timeout;
1453
- return this;
857
+ getConfirmedUnspentTxs(address) {
858
+ return __awaiter(this, void 0, void 0, function* () {
859
+ const allUnspent = yield this.getRawTransactions({ address, offset: 0, limit: 2000 }, true);
860
+ return this.mapUTXOs(address, allUnspent.filter((i) => i.confirmed));
861
+ });
1454
862
  }
1455
- /**
1456
- * Set the timeout in milliseconds for the pool handler.
1457
- *
1458
- * @param {Number} timeout
1459
- *
1460
- * @returns {PromisePool}
1461
- */
1462
- static withTaskTimeout(timeout) {
1463
- return new this().withTaskTimeout(timeout);
863
+ getUnspentTxs(address) {
864
+ return __awaiter(this, void 0, void 0, function* () {
865
+ const allUnspent = yield this.getRawTransactions({ address, offset: 0, limit: 2000 }, true);
866
+ return this.mapUTXOs(address, allUnspent);
867
+ });
1464
868
  }
1465
- /**
1466
- * Set the items to be processed in the promise pool.
1467
- *
1468
- * @param {T[]} items
1469
- *
1470
- * @returns {PromisePool}
1471
- */
1472
- for(items) {
1473
- return typeof this.timeout === 'number'
1474
- ? new PromisePool(items).withConcurrency(this.concurrency).withTaskTimeout(this.timeout)
1475
- : new PromisePool(items).withConcurrency(this.concurrency);
869
+ getBalance(address, assets /*ignored*/, confirmedOnly) {
870
+ return __awaiter(this, void 0, void 0, function* () {
871
+ const amount = yield getBalance({
872
+ apiKey: this._apiKey,
873
+ baseUrl: this.baseUrl,
874
+ network: this.blockcypherNetwork,
875
+ address,
876
+ confirmedOnly: !!confirmedOnly,
877
+ assetDecimals: this.assetDecimals,
878
+ });
879
+ return [{ amount, asset: this.asset }];
880
+ });
1476
881
  }
1477
882
  /**
1478
- * Set the items to be processed in the promise pool.
1479
- *
1480
- * @param {T[]} items
883
+ * Get transaction history of a given address with pagination options.
884
+ * By default it will return the transaction history of the current wallet.
1481
885
  *
1482
- * @returns {PromisePool}
886
+ * @param {TxHistoryParams} params The options to get transaction history. (optional)
887
+ * @returns {TxsPage} The transaction history.
1483
888
  */
1484
- static for(items) {
1485
- return new this().for(items);
889
+ getTransactions(params, unspentOnly = false) {
890
+ return __awaiter(this, void 0, void 0, function* () {
891
+ const rawTxs = yield this.getRawTransactions(params, unspentOnly);
892
+ const txs = rawTxs.map((i) => this.mapTransactionToTx(i));
893
+ const result = {
894
+ total: txs.length,
895
+ txs,
896
+ };
897
+ return result;
898
+ });
1486
899
  }
1487
900
  /**
1488
- * Set the error handler function to execute when an error occurs.
1489
- *
1490
- * @param {ErrorHandler<T>} handler
901
+ * Get the transaction details of a given transaction id.
1491
902
  *
1492
- * @returns {PromisePool}
903
+ * @param {string} txId The transaction id.
904
+ * @returns {Tx} The transaction details of the given transaction id.
1493
905
  */
1494
- handleError(handler) {
1495
- this.errorHandler = handler;
1496
- return this;
906
+ getTransactionData(txId) {
907
+ return __awaiter(this, void 0, void 0, function* () {
908
+ try {
909
+ const rawTx = yield getTx({
910
+ apiKey: this._apiKey,
911
+ baseUrl: this.baseUrl,
912
+ network: this.blockcypherNetwork,
913
+ hash: txId,
914
+ });
915
+ return this.mapTransactionToTx(rawTx);
916
+ }
917
+ catch (error) {
918
+ console.error(error);
919
+ throw error;
920
+ }
921
+ });
1497
922
  }
1498
- /**
1499
- * Assign the given callback `handler` function to run when a task starts.
1500
- *
1501
- * @param {OnProgressCallback<T>} handler
1502
- *
1503
- * @returns {PromisePool}
1504
- */
1505
- onTaskStarted(handler) {
1506
- this.onTaskStartedHandlers.push(handler);
1507
- return this;
923
+ mapTransactionToTx(rawTx) {
924
+ return {
925
+ asset: this.asset,
926
+ from: rawTx.inputs.map((i) => ({
927
+ from: i.addresses[0],
928
+ amount: xchainUtil.baseAmount(i.output_value, this.assetDecimals),
929
+ })),
930
+ to: rawTx.outputs
931
+ .filter((i) => i.script_type !== 'null-data') //filter out op_return outputs
932
+ .map((i) => ({ to: i.addresses[0], amount: xchainUtil.baseAmount(i.value, this.assetDecimals) })),
933
+ date: new Date(rawTx.confirmed),
934
+ type: xchainClient.TxType.Transfer,
935
+ hash: rawTx.hash,
936
+ };
937
+ }
938
+ mapUTXOs(address, utxos) {
939
+ const utxosOut = [];
940
+ for (let index = 0; index < utxos.length; index++) {
941
+ const utxo = utxos[index];
942
+ for (let index2 = 0; index2 < utxo.outputs.length; index2++) {
943
+ const output = utxo.outputs[index2];
944
+ if (output.addresses && output.addresses[0] === address) {
945
+ const utxoOut = {
946
+ hash: utxo.hash,
947
+ index: index2,
948
+ value: xchainUtil.baseAmount(output.value, this.assetDecimals).amount().toNumber(),
949
+ witnessUtxo: {
950
+ value: xchainUtil.baseAmount(output.value, this.assetDecimals).amount().toNumber(),
951
+ script: Buffer.from(output.script, 'hex'),
952
+ },
953
+ txHex: utxo.hex,
954
+ };
955
+ utxosOut.push(utxoOut);
956
+ }
957
+ }
958
+ }
959
+ return utxosOut;
1508
960
  }
1509
961
  /**
1510
- * Assign the given callback `handler` function to run when a task finished.
1511
- *
1512
- * @param {OnProgressCallback<T>} handler
962
+ * helper function tto limit adding to an array
1513
963
  *
1514
- * @returns {PromisePool}
964
+ * @param arr array to be added to
965
+ * @param toAdd elements to add
966
+ * @param limit do not add more than this limit
1515
967
  */
1516
- onTaskFinished(handler) {
1517
- this.onTaskFinishedHandlers.push(handler);
1518
- return this;
968
+ addArrayUpToLimit(arr, toAdd, limit) {
969
+ for (let index = 0; index < toAdd.length; index++) {
970
+ const element = toAdd[index];
971
+ if (arr.length < limit) {
972
+ arr.push(element);
973
+ }
974
+ }
1519
975
  }
1520
- /**
1521
- * Assign whether to keep corresponding results between source items and resulting tasks.
1522
- */
1523
- useCorrespondingResults() {
1524
- this.shouldResultsCorrespond = true;
1525
- return this;
976
+ delay(ms) {
977
+ return new Promise((resolve) => setTimeout(resolve, ms));
1526
978
  }
1527
979
  /**
1528
- * Starts processing the promise pool by iterating over the items
1529
- * and running each item through the async `callback` function.
1530
- *
1531
- * @param {ProcessHandler} The async processing function receiving each item from the `items` array.
980
+ * Get transaction history of a given address with pagination options.
981
+ * By default it will return the transaction history of the current wallet.
1532
982
  *
1533
- * @returns Promise<{ results, errors }>
983
+ * @param {TxHistoryParams} params The options to get transaction history. (optional)
984
+ * @returns {TxsPage} The transaction history.
1534
985
  */
1535
- async process(callback) {
1536
- return new promisePoolExecutor.PromisePoolExecutor()
1537
- .useConcurrency(this.concurrency)
1538
- .useCorrespondingResults(this.shouldResultsCorrespond)
1539
- .withTaskTimeout(this.timeout)
1540
- .withHandler(callback)
1541
- .handleError(this.errorHandler)
1542
- .onTaskStarted(this.onTaskStartedHandlers)
1543
- .onTaskFinished(this.onTaskFinishedHandlers)
1544
- .for(this.items)
1545
- .start();
1546
- }
1547
- }
1548
- exports.PromisePool = PromisePool;
1549
- PromisePool.notRun = Symbol('notRun');
1550
- PromisePool.failed = Symbol('failed');
1551
- });
1552
-
1553
- unwrapExports(promisePool);
1554
- var promisePool_1 = promisePool.PromisePool;
1555
-
1556
- var contracts = createCommonjsModule(function (module, exports) {
1557
- Object.defineProperty(exports, "__esModule", { value: true });
1558
- });
1559
-
1560
- unwrapExports(contracts);
1561
-
1562
- var returnValue = createCommonjsModule(function (module, exports) {
1563
- Object.defineProperty(exports, "__esModule", { value: true });
1564
- });
1565
-
1566
- unwrapExports(returnValue);
1567
-
1568
- var dist = createCommonjsModule(function (module, exports) {
1569
- var __createBinding = (commonjsGlobal && commonjsGlobal.__createBinding) || (Object.create ? (function(o, m, k, k2) {
1570
- if (k2 === undefined) k2 = k;
1571
- var desc = Object.getOwnPropertyDescriptor(m, k);
1572
- if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
1573
- desc = { enumerable: true, get: function() { return m[k]; } };
986
+ getRawTransactions(params, unspentOnly = false) {
987
+ var _a;
988
+ return __awaiter(this, void 0, void 0, function* () {
989
+ const offset = (_a = params === null || params === void 0 ? void 0 : params.offset) !== null && _a !== void 0 ? _a : 0;
990
+ const limit = (params === null || params === void 0 ? void 0 : params.limit) || 10;
991
+ if (offset + limit > 2000)
992
+ throw Error('cannot fetch more than last 2000 txs');
993
+ if (offset < 0 || limit < 0)
994
+ throw Error('ofset and limit must be equal or greater than 0');
995
+ const txHashesToFetch = [];
996
+ try {
997
+ const response = yield getTxs({
998
+ apiKey: this._apiKey,
999
+ baseUrl: this.baseUrl,
1000
+ network: this.blockcypherNetwork,
1001
+ address: `${params === null || params === void 0 ? void 0 : params.address}`,
1002
+ limit: 2000,
1003
+ unspentOnly,
1004
+ });
1005
+ //remove duplicates
1006
+ const txs = response.txrefs.map((i) => i.tx_hash);
1007
+ const uniqTxs = [...new Set(txs)];
1008
+ const start = offset >= uniqTxs.length ? uniqTxs.length : offset;
1009
+ const end = offset + limit >= uniqTxs.length ? uniqTxs.length : offset + limit;
1010
+ const txsToFetch = uniqTxs.slice(start, end);
1011
+ // console.log(JSON.stringify(txsToFetch, null, 2))
1012
+ this.addArrayUpToLimit(txHashesToFetch, txsToFetch, limit);
1013
+ }
1014
+ catch (error) {
1015
+ console.error(error);
1016
+ //an errors means no more results
1017
+ }
1018
+ //note: blockcypher has rate of 3 req/sec --> https://www.blockcypher.com/dev/bitcoin/#rate-limits-and-tokens
1019
+ const batchResult = yield PromisePool__default["default"].for(txHashesToFetch)
1020
+ .withConcurrency(3)
1021
+ .useCorrespondingResults()
1022
+ .process((hash) => __awaiter(this, void 0, void 0, function* () {
1023
+ yield this.delay(1000);
1024
+ const rawTx = yield getTx({
1025
+ apiKey: this._apiKey,
1026
+ baseUrl: this.baseUrl,
1027
+ network: this.blockcypherNetwork,
1028
+ hash,
1029
+ });
1030
+ return rawTx;
1031
+ }));
1032
+ return batchResult.results;
1033
+ });
1574
1034
  }
1575
- Object.defineProperty(o, k2, desc);
1576
- }) : (function(o, m, k, k2) {
1577
- if (k2 === undefined) k2 = k;
1578
- o[k2] = m[k];
1579
- }));
1580
- var __exportStar = (commonjsGlobal && commonjsGlobal.__exportStar) || function(m, exports) {
1581
- for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
1582
- };
1583
- Object.defineProperty(exports, "__esModule", { value: true });
1584
-
1585
- exports.default = promisePool.PromisePool;
1586
- __exportStar(contracts, exports);
1587
- __exportStar(promisePool, exports);
1588
- __exportStar(promisePoolError, exports);
1589
- __exportStar(returnValue, exports);
1590
- __exportStar(stopThePromisePoolError, exports);
1591
- __exportStar(validationError, exports);
1592
- });
1593
-
1594
- var PromisePool = unwrapExports(dist);
1595
-
1596
- /**
1597
- * Get transaction by hash.
1598
- *
1599
- *
1600
- * @param {string} baseUrl The sochain node url.
1601
- * @param {string} network network id
1602
- * @param {string} hash The transaction hash.
1603
- * @returns {Transactions}
1604
- */
1605
- const getTx$2 = ({ apiKey, baseUrl, network, hash }) => __awaiter(void 0, void 0, void 0, function* () {
1606
- const params = { includeHex: 'true' };
1607
- if (apiKey)
1608
- params['token'] = apiKey;
1609
- const url = `${baseUrl}/${network}/txs/${hash}`;
1610
- const response = yield axios__default['default'].get(url, { params });
1611
- const tx = response.data;
1612
- return tx;
1613
- });
1614
- /**
1615
- * Get transactions
1616
- *
1617
- *
1618
- * @param {string} baseUrl The sochain node url.
1619
- * @param {string} network network id
1620
- * @param {string} hash The transaction hash.
1621
- * @returns {Transactions}
1622
- */
1623
- const getTxs$2 = ({ apiKey, address, baseUrl, network, beforeBlock, limit, unspentOnly, }) => __awaiter(void 0, void 0, void 0, function* () {
1624
- const params = { limit: `${limit}`, unspentOnly: `${unspentOnly}` };
1625
- const url = `${baseUrl}/${network}/addrs/${address}`;
1626
- if (apiKey)
1627
- params['token'] = apiKey;
1628
- if (beforeBlock)
1629
- params['before'] = `${beforeBlock}`;
1630
- const response = yield axios__default['default'].get(url, { params });
1631
- const txs = response.data;
1632
- return txs;
1633
- });
1634
- /**
1635
- * Get address balance.
1636
- *
1637
- *
1638
- * @param {string} baseUrl The sochain node url.
1639
- * @param {string} network Network
1640
- * @param {string} address Address
1641
- * @param {boolean} confirmedOnly Flag whether to get balances of confirmed txs only or for all
1642
- * @returns {number}
1643
- */
1644
- const getBalance$2 = ({ apiKey, baseUrl, network, address, confirmedOnly, assetDecimals, }) => __awaiter(void 0, void 0, void 0, function* () {
1645
- const params = {};
1646
- const url = `${baseUrl}/${network}/addrs/${address}/balance`;
1647
- if (apiKey)
1648
- params['token'] = apiKey;
1649
- const response = yield axios__default['default'].get(url, { params });
1650
- const balanceResponse = response.data;
1651
- const confirmedAmount = xchainUtil.baseAmount(balanceResponse.balance, assetDecimals);
1652
- const finalBalance = xchainUtil.baseAmount(balanceResponse.final_balance, assetDecimals);
1653
- return confirmedOnly ? confirmedAmount : finalBalance;
1654
- });
1655
- const broadcastTx$2 = ({ apiKey, baseUrl, network, txHex, }) => __awaiter(void 0, void 0, void 0, function* () {
1656
- const params = {};
1657
- const url = `${baseUrl}/${network}/txs/push`;
1658
- if (apiKey)
1659
- params['token'] = apiKey;
1660
- const response = yield axios__default['default'].post(url, { tx: txHex }, { params });
1661
- const broadcastResponse = response.data;
1662
- return broadcastResponse.tx.hash;
1663
- });
1664
-
1665
- class BlockcypherProvider {
1666
- constructor(baseUrl = 'https://api.blockcypher.com/v1/', chain, asset, assetDecimals, blockcypherNetwork, apiKey) {
1667
- this.baseUrl = baseUrl;
1668
- this._apiKey = apiKey;
1669
- this.chain = chain;
1670
- this.asset = asset;
1671
- this.assetDecimals = assetDecimals;
1672
- this.blockcypherNetwork = blockcypherNetwork;
1673
- this.asset;
1674
- this.chain;
1675
- }
1676
- get apiKey() {
1677
- return this._apiKey;
1678
- }
1679
- set apiKey(value) {
1680
- this._apiKey = value;
1681
- }
1682
- broadcastTx(txHex) {
1683
- return __awaiter(this, void 0, void 0, function* () {
1684
- return yield broadcastTx$2({
1685
- apiKey: this._apiKey,
1686
- baseUrl: this.baseUrl,
1687
- network: this.blockcypherNetwork,
1688
- txHex,
1689
- });
1690
- });
1691
- }
1692
- getConfirmedUnspentTxs(address) {
1693
- return __awaiter(this, void 0, void 0, function* () {
1694
- const allUnspent = yield this.getRawTransactions({ address, offset: 0, limit: 2000 }, true);
1695
- return this.mapUTXOs(address, allUnspent.filter((i) => i.confirmed));
1696
- });
1697
- }
1698
- getUnspentTxs(address) {
1699
- return __awaiter(this, void 0, void 0, function* () {
1700
- const allUnspent = yield this.getRawTransactions({ address, offset: 0, limit: 2000 }, true);
1701
- return this.mapUTXOs(address, allUnspent);
1702
- });
1703
- }
1704
- getBalance(address, assets /*ignored*/, confirmedOnly) {
1705
- return __awaiter(this, void 0, void 0, function* () {
1706
- const amount = yield getBalance$2({
1707
- apiKey: this._apiKey,
1708
- baseUrl: this.baseUrl,
1709
- network: this.blockcypherNetwork,
1710
- address,
1711
- confirmedOnly: !!confirmedOnly,
1712
- assetDecimals: this.assetDecimals,
1713
- });
1714
- return [{ amount, asset: this.asset }];
1715
- });
1716
- }
1717
- /**
1718
- * Get transaction history of a given address with pagination options.
1719
- * By default it will return the transaction history of the current wallet.
1720
- *
1721
- * @param {TxHistoryParams} params The options to get transaction history. (optional)
1722
- * @returns {TxsPage} The transaction history.
1723
- */
1724
- getTransactions(params, unspentOnly = false) {
1725
- return __awaiter(this, void 0, void 0, function* () {
1726
- const rawTxs = yield this.getRawTransactions(params, unspentOnly);
1727
- const txs = rawTxs.map((i) => this.mapTransactionToTx(i));
1728
- const result = {
1729
- total: txs.length,
1730
- txs,
1731
- };
1732
- return result;
1733
- });
1734
- }
1735
- /**
1736
- * Get the transaction details of a given transaction id.
1737
- *
1738
- * @param {string} txId The transaction id.
1739
- * @returns {Tx} The transaction details of the given transaction id.
1740
- */
1741
- getTransactionData(txId) {
1742
- return __awaiter(this, void 0, void 0, function* () {
1743
- try {
1744
- const rawTx = yield getTx$2({
1745
- apiKey: this._apiKey,
1746
- baseUrl: this.baseUrl,
1747
- network: this.blockcypherNetwork,
1748
- hash: txId,
1749
- });
1750
- return this.mapTransactionToTx(rawTx);
1751
- }
1752
- catch (error) {
1753
- console.error(error);
1754
- throw error;
1755
- }
1756
- });
1757
- }
1758
- mapTransactionToTx(rawTx) {
1759
- return {
1760
- asset: this.asset,
1761
- from: rawTx.inputs.map((i) => ({
1762
- from: i.addresses[0],
1763
- amount: xchainUtil.baseAmount(i.output_value, this.assetDecimals),
1764
- })),
1765
- to: rawTx.outputs
1766
- .filter((i) => i.script_type !== 'null-data') //filter out op_return outputs
1767
- .map((i) => ({ to: i.addresses[0], amount: xchainUtil.baseAmount(i.value, this.assetDecimals) })),
1768
- date: new Date(rawTx.confirmed),
1769
- type: xchainClient.TxType.Transfer,
1770
- hash: rawTx.hash,
1771
- };
1772
- }
1773
- mapUTXOs(address, utxos) {
1774
- const utxosOut = [];
1775
- for (let index = 0; index < utxos.length; index++) {
1776
- const utxo = utxos[index];
1777
- for (let index2 = 0; index2 < utxo.outputs.length; index2++) {
1778
- const output = utxo.outputs[index2];
1779
- if (output.addresses && output.addresses[0] === address) {
1780
- const utxoOut = {
1781
- hash: utxo.hash,
1782
- index: index2,
1783
- value: xchainUtil.baseAmount(output.value, this.assetDecimals).amount().toNumber(),
1784
- witnessUtxo: {
1785
- value: xchainUtil.baseAmount(output.value, this.assetDecimals).amount().toNumber(),
1786
- script: Buffer.from(output.script, 'hex'),
1787
- },
1788
- txHex: utxo.hex,
1789
- };
1790
- utxosOut.push(utxoOut);
1791
- }
1792
- }
1793
- }
1794
- return utxosOut;
1795
- }
1796
- /**
1797
- * helper function tto limit adding to an array
1798
- *
1799
- * @param arr array to be added to
1800
- * @param toAdd elements to add
1801
- * @param limit do not add more than this limit
1802
- */
1803
- addArrayUpToLimit(arr, toAdd, limit) {
1804
- for (let index = 0; index < toAdd.length; index++) {
1805
- const element = toAdd[index];
1806
- if (arr.length < limit) {
1807
- arr.push(element);
1808
- }
1809
- }
1810
- }
1811
- delay(ms) {
1812
- return new Promise((resolve) => setTimeout(resolve, ms));
1813
- }
1814
- /**
1815
- * Get transaction history of a given address with pagination options.
1816
- * By default it will return the transaction history of the current wallet.
1817
- *
1818
- * @param {TxHistoryParams} params The options to get transaction history. (optional)
1819
- * @returns {TxsPage} The transaction history.
1820
- */
1821
- getRawTransactions(params, unspentOnly = false) {
1822
- var _a;
1823
- return __awaiter(this, void 0, void 0, function* () {
1824
- const offset = (_a = params === null || params === void 0 ? void 0 : params.offset) !== null && _a !== void 0 ? _a : 0;
1825
- const limit = (params === null || params === void 0 ? void 0 : params.limit) || 10;
1826
- if (offset + limit > 2000)
1827
- throw Error('cannot fetch more than last 2000 txs');
1828
- if (offset < 0 || limit < 0)
1829
- throw Error('ofset and limit must be equal or greater than 0');
1830
- const txHashesToFetch = [];
1831
- try {
1832
- const response = yield getTxs$2({
1833
- apiKey: this._apiKey,
1834
- baseUrl: this.baseUrl,
1835
- network: this.blockcypherNetwork,
1836
- address: `${params === null || params === void 0 ? void 0 : params.address}`,
1837
- limit: 2000,
1838
- unspentOnly,
1839
- });
1840
- //remove duplicates
1841
- const txs = response.txrefs.map((i) => i.tx_hash);
1842
- const uniqTxs = [...new Set(txs)];
1843
- const start = offset >= uniqTxs.length ? uniqTxs.length : offset;
1844
- const end = offset + limit >= uniqTxs.length ? uniqTxs.length : offset + limit;
1845
- const txsToFetch = uniqTxs.slice(start, end);
1846
- // console.log(JSON.stringify(txsToFetch, null, 2))
1847
- this.addArrayUpToLimit(txHashesToFetch, txsToFetch, limit);
1848
- }
1849
- catch (error) {
1850
- console.error(error);
1851
- //an errors means no more results
1852
- }
1853
- //note: blockcypher has rate of 3 req/sec --> https://www.blockcypher.com/dev/bitcoin/#rate-limits-and-tokens
1854
- const batchResult = yield PromisePool.for(txHashesToFetch)
1855
- .withConcurrency(3)
1856
- .useCorrespondingResults()
1857
- .process((hash) => __awaiter(this, void 0, void 0, function* () {
1858
- yield this.delay(1000);
1859
- const rawTx = yield getTx$2({
1860
- apiKey: this._apiKey,
1861
- baseUrl: this.baseUrl,
1862
- network: this.blockcypherNetwork,
1863
- hash,
1864
- });
1865
- return rawTx;
1866
- }));
1867
- return batchResult.results;
1868
- });
1869
- }
1870
1035
  }
1871
1036
 
1872
- (function (BlockcypherNetwork) {
1873
- BlockcypherNetwork["BTC"] = "btc/main";
1874
- BlockcypherNetwork["BTCTEST"] = "btc/test3";
1875
- BlockcypherNetwork["LTC"] = "ltc/main";
1876
- BlockcypherNetwork["DOGE"] = "doge/main";
1037
+ exports.BlockcypherNetwork = void 0;
1038
+ (function (BlockcypherNetwork) {
1039
+ BlockcypherNetwork["BTC"] = "btc/main";
1040
+ BlockcypherNetwork["BTCTEST"] = "btc/test3";
1041
+ BlockcypherNetwork["LTC"] = "ltc/main";
1042
+ BlockcypherNetwork["DOGE"] = "doge/main";
1877
1043
  })(exports.BlockcypherNetwork || (exports.BlockcypherNetwork = {}));
1878
1044
 
1879
1045
  exports.BlockcypherProvider = BlockcypherProvider;
@@ -1888,4 +1054,4 @@ exports.getConfirmedUnspentTxs = getConfirmedUnspentTxs;
1888
1054
  exports.getIsTxConfirmed = getIsTxConfirmed;
1889
1055
  exports.getTx = getTx$1;
1890
1056
  exports.getTxs = getTxs$1;
1891
- exports.getUnspentTxs = getUnspentTxs$1;
1057
+ exports.getUnspentTxs = getUnspentTxs;