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