@algorandfoundation/algokit-utils 9.2.0 → 9.2.1-beta.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (340) hide show
  1. package/_virtual/_rolldown/runtime.js +33 -0
  2. package/_virtual/_rolldown/runtime.mjs +13 -0
  3. package/account/account.d.ts +25 -30
  4. package/account/account.js +151 -146
  5. package/account/account.js.map +1 -1
  6. package/account/account.mjs +149 -144
  7. package/account/account.mjs.map +1 -1
  8. package/account/get-account-config-from-environment.d.ts +7 -2
  9. package/account/get-account-config-from-environment.js +19 -21
  10. package/account/get-account-config-from-environment.js.map +1 -1
  11. package/account/get-account-config-from-environment.mjs +19 -19
  12. package/account/get-account-config-from-environment.mjs.map +1 -1
  13. package/account/get-account.d.ts +14 -12
  14. package/account/get-account.js +56 -59
  15. package/account/get-account.js.map +1 -1
  16. package/account/get-account.mjs +56 -57
  17. package/account/get-account.mjs.map +1 -1
  18. package/account/get-dispenser-account.d.ts +9 -5
  19. package/account/get-dispenser-account.js +20 -18
  20. package/account/get-dispenser-account.js.map +1 -1
  21. package/account/get-dispenser-account.mjs +20 -16
  22. package/account/get-dispenser-account.mjs.map +1 -1
  23. package/account/mnemonic-account.d.ts +7 -3
  24. package/account/mnemonic-account.js +17 -17
  25. package/account/mnemonic-account.js.map +1 -1
  26. package/account/mnemonic-account.mjs +15 -15
  27. package/account/mnemonic-account.mjs.map +1 -1
  28. package/amount.d.ts +40 -35
  29. package/amount.js +33 -34
  30. package/amount.js.map +1 -1
  31. package/amount.mjs +33 -32
  32. package/amount.mjs.map +1 -1
  33. package/app-client.d.ts +10 -6
  34. package/app-client.js +91 -86
  35. package/app-client.js.map +1 -1
  36. package/app-client.mjs +91 -84
  37. package/app-client.mjs.map +1 -1
  38. package/app-deploy.d.ts +26 -24
  39. package/app-deploy.js +235 -253
  40. package/app-deploy.js.map +1 -1
  41. package/app-deploy.mjs +233 -251
  42. package/app-deploy.mjs.map +1 -1
  43. package/app.d.ts +45 -46
  44. package/app.js +253 -271
  45. package/app.js.map +1 -1
  46. package/app.mjs +249 -267
  47. package/app.mjs.map +1 -1
  48. package/asset.d.ts +16 -12
  49. package/asset.js +116 -122
  50. package/asset.js.map +1 -1
  51. package/asset.mjs +116 -120
  52. package/asset.mjs.map +1 -1
  53. package/config.d.ts +7 -2
  54. package/config.js +5 -7
  55. package/config.js.map +1 -1
  56. package/config.mjs +5 -4
  57. package/config.mjs.map +1 -1
  58. package/debugging/debugging.d.ts +5 -1
  59. package/debugging/debugging.js +11 -11
  60. package/debugging/debugging.js.map +1 -1
  61. package/debugging/debugging.mjs +11 -9
  62. package/debugging/debugging.mjs.map +1 -1
  63. package/dispenser-client.d.ts +7 -2
  64. package/dispenser-client.js +23 -24
  65. package/dispenser-client.js.map +1 -1
  66. package/dispenser-client.mjs +23 -22
  67. package/dispenser-client.mjs.map +1 -1
  68. package/index.d.ts +27 -18
  69. package/index.js +140 -143
  70. package/index.mjs +27 -29
  71. package/indexer-lookup.d.ts +18 -11
  72. package/indexer-lookup.js +112 -120
  73. package/indexer-lookup.js.map +1 -1
  74. package/indexer-lookup.mjs +105 -118
  75. package/indexer-lookup.mjs.map +1 -1
  76. package/localnet/get-kmd-wallet-account.d.ts +9 -7
  77. package/localnet/get-kmd-wallet-account.js +28 -26
  78. package/localnet/get-kmd-wallet-account.js.map +1 -1
  79. package/localnet/get-kmd-wallet-account.mjs +28 -24
  80. package/localnet/get-kmd-wallet-account.mjs.map +1 -1
  81. package/localnet/get-localnet-dispenser-account.d.ts +7 -5
  82. package/localnet/get-localnet-dispenser-account.js +17 -15
  83. package/localnet/get-localnet-dispenser-account.js.map +1 -1
  84. package/localnet/get-localnet-dispenser-account.mjs +17 -13
  85. package/localnet/get-localnet-dispenser-account.mjs.map +1 -1
  86. package/localnet/get-or-create-kmd-wallet-account.d.ts +10 -8
  87. package/localnet/get-or-create-kmd-wallet-account.js +28 -26
  88. package/localnet/get-or-create-kmd-wallet-account.js.map +1 -1
  89. package/localnet/get-or-create-kmd-wallet-account.mjs +28 -24
  90. package/localnet/get-or-create-kmd-wallet-account.mjs.map +1 -1
  91. package/localnet/is-localnet.d.ts +7 -3
  92. package/localnet/is-localnet.js +9 -10
  93. package/localnet/is-localnet.js.map +1 -1
  94. package/localnet/is-localnet.mjs +9 -8
  95. package/localnet/is-localnet.mjs.map +1 -1
  96. package/network-client.d.ts +17 -15
  97. package/network-client.js +115 -116
  98. package/network-client.js.map +1 -1
  99. package/network-client.mjs +115 -114
  100. package/network-client.mjs.map +1 -1
  101. package/package.json +12 -3
  102. package/testing/account.d.ts +11 -9
  103. package/testing/account.js +31 -33
  104. package/testing/account.js.map +1 -1
  105. package/testing/account.mjs +29 -31
  106. package/testing/account.mjs.map +1 -1
  107. package/testing/fixtures/algokit-log-capture-fixture.d.ts +7 -2
  108. package/testing/fixtures/algokit-log-capture-fixture.js +36 -41
  109. package/testing/fixtures/algokit-log-capture-fixture.js.map +1 -1
  110. package/testing/fixtures/algokit-log-capture-fixture.mjs +36 -39
  111. package/testing/fixtures/algokit-log-capture-fixture.mjs.map +1 -1
  112. package/testing/fixtures/algorand-fixture.d.ts +9 -4
  113. package/testing/fixtures/algorand-fixture.js +67 -62
  114. package/testing/fixtures/algorand-fixture.js.map +1 -1
  115. package/testing/fixtures/algorand-fixture.mjs +66 -59
  116. package/testing/fixtures/algorand-fixture.mjs.map +1 -1
  117. package/testing/index.d.ts +7 -5
  118. package/testing/index.js +13 -18
  119. package/testing/index.mjs +7 -7
  120. package/testing/indexer.d.ts +5 -1
  121. package/testing/indexer.js +28 -37
  122. package/testing/indexer.js.map +1 -1
  123. package/testing/indexer.mjs +28 -35
  124. package/testing/indexer.mjs.map +1 -1
  125. package/testing/test-logger.d.ts +41 -36
  126. package/testing/test-logger.js +71 -76
  127. package/testing/test-logger.js.map +1 -1
  128. package/testing/test-logger.mjs +71 -74
  129. package/testing/test-logger.mjs.map +1 -1
  130. package/testing/transaction-logger.d.ts +30 -27
  131. package/testing/transaction-logger.js +77 -93
  132. package/testing/transaction-logger.js.map +1 -1
  133. package/testing/transaction-logger.mjs +74 -90
  134. package/testing/transaction-logger.mjs.map +1 -1
  135. package/transaction/legacy-bridge.js +100 -111
  136. package/transaction/legacy-bridge.js.map +1 -1
  137. package/transaction/legacy-bridge.mjs +97 -108
  138. package/transaction/legacy-bridge.mjs.map +1 -1
  139. package/transaction/perform-atomic-transaction-composer-simulate.d.ts +7 -5
  140. package/transaction/perform-atomic-transaction-composer-simulate.js +31 -36
  141. package/transaction/perform-atomic-transaction-composer-simulate.js.map +1 -1
  142. package/transaction/perform-atomic-transaction-composer-simulate.mjs +28 -33
  143. package/transaction/perform-atomic-transaction-composer-simulate.mjs.map +1 -1
  144. package/transaction/transaction.d.ts +34 -35
  145. package/transaction/transaction.js +716 -914
  146. package/transaction/transaction.js.map +1 -1
  147. package/transaction/transaction.mjs +713 -911
  148. package/transaction/transaction.mjs.map +1 -1
  149. package/transfer/transfer-algos.d.ts +9 -5
  150. package/transfer/transfer-algos.js +26 -27
  151. package/transfer/transfer-algos.js.map +1 -1
  152. package/transfer/transfer-algos.mjs +26 -25
  153. package/transfer/transfer-algos.mjs.map +1 -1
  154. package/transfer/transfer.d.ts +11 -8
  155. package/transfer/transfer.js +94 -100
  156. package/transfer/transfer.js.map +1 -1
  157. package/transfer/transfer.mjs +94 -98
  158. package/transfer/transfer.mjs.map +1 -1
  159. package/types/account-manager.d.ts +432 -429
  160. package/types/account-manager.js +591 -602
  161. package/types/account-manager.js.map +1 -1
  162. package/types/account-manager.mjs +587 -599
  163. package/types/account-manager.mjs.map +1 -1
  164. package/types/account.d.ts +192 -202
  165. package/types/account.js +91 -88
  166. package/types/account.js.map +1 -1
  167. package/types/account.mjs +88 -86
  168. package/types/account.mjs.map +1 -1
  169. package/types/algo-http-client-with-retry.d.ts +15 -10
  170. package/types/algo-http-client-with-retry.js +70 -92
  171. package/types/algo-http-client-with-retry.js.map +1 -1
  172. package/types/algo-http-client-with-retry.mjs +69 -90
  173. package/types/algo-http-client-with-retry.mjs.map +1 -1
  174. package/types/algorand-client-transaction-creator.d.ts +778 -771
  175. package/types/algorand-client-transaction-creator.js +733 -732
  176. package/types/algorand-client-transaction-creator.js.map +1 -1
  177. package/types/algorand-client-transaction-creator.mjs +732 -730
  178. package/types/algorand-client-transaction-creator.mjs.map +1 -1
  179. package/types/algorand-client-transaction-sender.d.ts +1090 -1360
  180. package/types/algorand-client-transaction-sender.js +930 -961
  181. package/types/algorand-client-transaction-sender.js.map +1 -1
  182. package/types/algorand-client-transaction-sender.mjs +927 -959
  183. package/types/algorand-client-transaction-sender.mjs.map +1 -1
  184. package/types/algorand-client.d.ts +239 -236
  185. package/types/algorand-client.js +322 -320
  186. package/types/algorand-client.js.map +1 -1
  187. package/types/algorand-client.mjs +321 -318
  188. package/types/algorand-client.mjs.map +1 -1
  189. package/types/amount.d.ts +47 -43
  190. package/types/amount.js +66 -70
  191. package/types/amount.js.map +1 -1
  192. package/types/amount.mjs +63 -68
  193. package/types/amount.mjs.map +1 -1
  194. package/types/app-arc56.d.ts +235 -272
  195. package/types/app-arc56.js +124 -170
  196. package/types/app-arc56.js.map +1 -1
  197. package/types/app-arc56.mjs +121 -168
  198. package/types/app-arc56.mjs.map +1 -1
  199. package/types/app-client.d.ts +1128 -2009
  200. package/types/app-client.js +1633 -1791
  201. package/types/app-client.js.map +1 -1
  202. package/types/app-client.mjs +1624 -1783
  203. package/types/app-client.mjs.map +1 -1
  204. package/types/app-deployer.d.ts +139 -141
  205. package/types/app-deployer.js +344 -384
  206. package/types/app-deployer.js.map +1 -1
  207. package/types/app-deployer.mjs +341 -382
  208. package/types/app-deployer.mjs.map +1 -1
  209. package/types/app-factory.d.ts +762 -932
  210. package/types/app-factory.js +496 -488
  211. package/types/app-factory.js.map +1 -1
  212. package/types/app-factory.mjs +491 -484
  213. package/types/app-factory.mjs.map +1 -1
  214. package/types/app-manager.d.ts +304 -310
  215. package/types/app-manager.js +422 -475
  216. package/types/app-manager.js.map +1 -1
  217. package/types/app-manager.mjs +419 -473
  218. package/types/app-manager.mjs.map +1 -1
  219. package/types/app-spec.d.ts +118 -117
  220. package/types/app-spec.js +125 -135
  221. package/types/app-spec.js.map +1 -1
  222. package/types/app-spec.mjs +121 -132
  223. package/types/app-spec.mjs.map +1 -1
  224. package/types/app.d.ts +229 -241
  225. package/types/app.js +36 -28
  226. package/types/app.js.map +1 -1
  227. package/types/app.mjs +33 -26
  228. package/types/app.mjs.map +1 -1
  229. package/types/asset-manager.d.ts +204 -199
  230. package/types/asset-manager.js +165 -174
  231. package/types/asset-manager.js.map +1 -1
  232. package/types/asset-manager.mjs +164 -172
  233. package/types/asset-manager.mjs.map +1 -1
  234. package/types/asset.d.ts +95 -91
  235. package/types/asset.js +0 -3
  236. package/types/asset.mjs +0 -2
  237. package/types/async-event-emitter.d.ts +18 -13
  238. package/types/async-event-emitter.js +37 -49
  239. package/types/async-event-emitter.js.map +1 -1
  240. package/types/async-event-emitter.mjs +36 -47
  241. package/types/async-event-emitter.mjs.map +1 -1
  242. package/types/client-manager.d.ts +453 -451
  243. package/types/client-manager.js +602 -598
  244. package/types/client-manager.js.map +1 -1
  245. package/types/client-manager.mjs +597 -594
  246. package/types/client-manager.mjs.map +1 -1
  247. package/types/composer.d.ts +1211 -1258
  248. package/types/composer.js +1436 -1498
  249. package/types/composer.js.map +1 -1
  250. package/types/composer.mjs +1430 -1493
  251. package/types/composer.mjs.map +1 -1
  252. package/types/config.d.ts +53 -48
  253. package/types/config.js +78 -77
  254. package/types/config.js.map +1 -1
  255. package/types/config.mjs +77 -75
  256. package/types/config.mjs.map +1 -1
  257. package/types/debugging.d.ts +25 -23
  258. package/types/debugging.js +9 -11
  259. package/types/debugging.js.map +1 -1
  260. package/types/debugging.mjs +8 -9
  261. package/types/debugging.mjs.map +1 -1
  262. package/types/dispenser-client.d.ts +57 -52
  263. package/types/dispenser-client.js +120 -141
  264. package/types/dispenser-client.js.map +1 -1
  265. package/types/dispenser-client.mjs +119 -139
  266. package/types/dispenser-client.mjs.map +1 -1
  267. package/types/expand.d.ts +5 -3
  268. package/types/expand.js +0 -3
  269. package/types/expand.mjs +0 -2
  270. package/types/indexer.d.ts +104 -100
  271. package/types/indexer.js +36 -31
  272. package/types/indexer.js.map +1 -1
  273. package/types/indexer.mjs +32 -30
  274. package/types/indexer.mjs.map +1 -1
  275. package/types/instance-of.d.ts +5 -3
  276. package/types/instance-of.js +0 -3
  277. package/types/instance-of.mjs +0 -2
  278. package/types/kmd-account-manager.d.ts +75 -70
  279. package/types/kmd-account-manager.js +150 -184
  280. package/types/kmd-account-manager.js.map +1 -1
  281. package/types/kmd-account-manager.mjs +147 -182
  282. package/types/kmd-account-manager.mjs.map +1 -1
  283. package/types/lifecycle-events.d.ts +13 -8
  284. package/types/lifecycle-events.js +10 -7
  285. package/types/lifecycle-events.js.map +1 -1
  286. package/types/lifecycle-events.mjs +9 -7
  287. package/types/lifecycle-events.mjs.map +1 -1
  288. package/types/logging.d.ts +15 -11
  289. package/types/logging.js +30 -31
  290. package/types/logging.js.map +1 -1
  291. package/types/logging.mjs +29 -29
  292. package/types/logging.mjs.map +1 -1
  293. package/types/logic-error.d.ts +33 -29
  294. package/types/logic-error.js +50 -49
  295. package/types/logic-error.js.map +1 -1
  296. package/types/logic-error.mjs +49 -47
  297. package/types/logic-error.mjs.map +1 -1
  298. package/types/network-client.d.ts +32 -27
  299. package/types/network-client.js +10 -9
  300. package/types/network-client.js.map +1 -1
  301. package/types/network-client.mjs +9 -7
  302. package/types/network-client.mjs.map +1 -1
  303. package/types/testing.d.ts +131 -132
  304. package/types/testing.js +0 -3
  305. package/types/testing.mjs +0 -2
  306. package/types/transaction.d.ts +110 -110
  307. package/types/transaction.js +0 -3
  308. package/types/transaction.mjs +0 -2
  309. package/types/transfer.d.ts +70 -66
  310. package/types/transfer.js +0 -3
  311. package/types/transfer.mjs +0 -2
  312. package/util.js +73 -118
  313. package/util.js.map +1 -1
  314. package/util.mjs +73 -116
  315. package/util.mjs.map +1 -1
  316. package/account/index.d.ts +0 -5
  317. package/debugging/index.d.ts +0 -1
  318. package/index.js.map +0 -1
  319. package/index.mjs.map +0 -1
  320. package/localnet/index.d.ts +0 -4
  321. package/testing/_asset.d.ts +0 -3
  322. package/testing/fixtures/index.d.ts +0 -2
  323. package/testing/index.js.map +0 -1
  324. package/testing/index.mjs.map +0 -1
  325. package/transaction/index.d.ts +0 -2
  326. package/transaction/legacy-bridge.d.ts +0 -35
  327. package/transfer/index.d.ts +0 -2
  328. package/types/asset.js.map +0 -1
  329. package/types/asset.mjs.map +0 -1
  330. package/types/expand.js.map +0 -1
  331. package/types/expand.mjs.map +0 -1
  332. package/types/instance-of.js.map +0 -1
  333. package/types/instance-of.mjs.map +0 -1
  334. package/types/testing.js.map +0 -1
  335. package/types/testing.mjs.map +0 -1
  336. package/types/transaction.js.map +0 -1
  337. package/types/transaction.mjs.map +0 -1
  338. package/types/transfer.js.map +0 -1
  339. package/types/transfer.mjs.map +0 -1
  340. package/util.d.ts +0 -48
@@ -1,94 +1,72 @@
1
- 'use strict';
2
-
3
- var algosdk = require('algosdk');
4
- var client = require('algosdk/client');
5
- var config = require('../config.js');
6
-
1
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
+ const require_config = require("../config.js");
3
+ let algosdk = require("algosdk");
4
+ let algosdk_client = require("algosdk/client");
5
+ //#region src/types/algo-http-client-with-retry.ts
7
6
  /** A HTTP Client that wraps the Algorand SDK HTTP Client with retries */
8
- class AlgoHttpClientWithRetry extends client.URLTokenBaseHTTPClient {
9
- async callWithRetry(func) {
10
- let response;
11
- let numTries = 1;
12
- do {
13
- try {
14
- response = await func();
15
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
16
- }
17
- catch (err) {
18
- if (numTries >= AlgoHttpClientWithRetry.MAX_TRIES) {
19
- throw err;
20
- }
21
- // Only retry for one of the hardcoded conditions
22
- if (!(AlgoHttpClientWithRetry.RETRY_ERROR_CODES.includes(err.code) ||
23
- AlgoHttpClientWithRetry.RETRY_STATUS_CODES.includes(Number(err.status)) ||
24
- ('response' in err && AlgoHttpClientWithRetry.RETRY_STATUS_CODES.includes(Number(err.response.status))))) {
25
- throw err;
26
- }
27
- // Retry immediately the first time, then exponentially backoff.
28
- const delayTimeMs = numTries == 1 ? 0 : Math.min(1000 * Math.pow(2, numTries - 1), AlgoHttpClientWithRetry.MAX_BACKOFF_MS);
29
- if (delayTimeMs > 0) {
30
- await new Promise((r) => setTimeout(r, delayTimeMs));
31
- }
32
- config.Config.logger.warn(`algosdk request failed ${numTries} times. Retrying in ${delayTimeMs}ms: ${err}`);
33
- }
34
- } while (!response && ++numTries <= AlgoHttpClientWithRetry.MAX_TRIES);
35
- return response;
36
- }
37
- async get(relativePath, query, requestHeaders = {}) {
38
- const response = await this.callWithRetry(() => super.get(relativePath, query, requestHeaders));
39
- if (relativePath.startsWith('/v2/accounts/') &&
40
- relativePath.endsWith('/created-applications') &&
41
- response.status === 200 &&
42
- query?.['include-all']?.toString() === 'true') {
43
- // todo: Temporary hack
44
- // Indexer get created applications by account returns approvalProgram and clearStateProgram as null, which breaks the algosdk@3 decoder
45
- // instead we will detect this call and set them to empty byte arrays
46
- try {
47
- const json = algosdk.parseJSON(Buffer.from(response.body).toString(), { intDecoding: algosdk.IntDecoding.MIXED });
48
- if (json.applications) {
49
- for (const app of json.applications) {
50
- if (app.params) {
51
- if (app.params['approval-program'] === null) {
52
- app.params['approval-program'] = '';
53
- }
54
- if (app.params['clear-state-program'] === null) {
55
- app.params['clear-state-program'] = '';
56
- }
57
- }
58
- }
59
- response.body = Buffer.from(algosdk.stringifyJSON(json));
60
- }
61
- }
62
- catch (e) {
63
- // Make this hack resilient so we never break the app
64
- config.Config.logger.warn('Failed to fix indexer response for created applications', e);
65
- }
66
- }
67
- return response;
68
- }
69
- async post(relativePath, data, query, requestHeaders = {}) {
70
- return await this.callWithRetry(() => super.post(relativePath, data, query, requestHeaders));
71
- }
72
- async delete(relativePath, data, query, requestHeaders = {}) {
73
- return await this.callWithRetry(() => super.delete(relativePath, data, query, requestHeaders));
74
- }
75
- }
76
- AlgoHttpClientWithRetry.MAX_TRIES = 5;
77
- AlgoHttpClientWithRetry.MAX_BACKOFF_MS = 10000;
78
- // These lists come from https://visionmedia.github.io/superagent/#retrying-requests
79
- // which is the underlying library used by algosdk - but the CloudFlare specific 52X status codes have been removed
80
- AlgoHttpClientWithRetry.RETRY_STATUS_CODES = [408, 413, 429, 500, 502, 503, 504];
81
- AlgoHttpClientWithRetry.RETRY_ERROR_CODES = [
82
- 'ETIMEDOUT',
83
- 'ECONNRESET',
84
- 'EADDRINUSE',
85
- 'ECONNREFUSED',
86
- 'EPIPE',
87
- 'ENOTFOUND',
88
- 'ENETUNREACH',
89
- 'EAI_AGAIN',
90
- 'EPROTO', // We get this intermittently with AlgoNode API
91
- ];
92
-
7
+ var AlgoHttpClientWithRetry = class AlgoHttpClientWithRetry extends algosdk_client.URLTokenBaseHTTPClient {
8
+ static MAX_TRIES = 5;
9
+ static MAX_BACKOFF_MS = 1e4;
10
+ static RETRY_STATUS_CODES = [
11
+ 408,
12
+ 413,
13
+ 429,
14
+ 500,
15
+ 502,
16
+ 503,
17
+ 504
18
+ ];
19
+ static RETRY_ERROR_CODES = [
20
+ "ETIMEDOUT",
21
+ "ECONNRESET",
22
+ "EADDRINUSE",
23
+ "ECONNREFUSED",
24
+ "EPIPE",
25
+ "ENOTFOUND",
26
+ "ENETUNREACH",
27
+ "EAI_AGAIN",
28
+ "EPROTO"
29
+ ];
30
+ async callWithRetry(func) {
31
+ let response;
32
+ let numTries = 1;
33
+ do
34
+ try {
35
+ response = await func();
36
+ } catch (err) {
37
+ if (numTries >= AlgoHttpClientWithRetry.MAX_TRIES) throw err;
38
+ if (!(AlgoHttpClientWithRetry.RETRY_ERROR_CODES.includes(err.code) || AlgoHttpClientWithRetry.RETRY_STATUS_CODES.includes(Number(err.status)) || "response" in err && AlgoHttpClientWithRetry.RETRY_STATUS_CODES.includes(Number(err.response.status)))) throw err;
39
+ const delayTimeMs = numTries == 1 ? 0 : Math.min(1e3 * Math.pow(2, numTries - 1), AlgoHttpClientWithRetry.MAX_BACKOFF_MS);
40
+ if (delayTimeMs > 0) await new Promise((r) => setTimeout(r, delayTimeMs));
41
+ require_config.Config.logger.warn(`algosdk request failed ${numTries} times. Retrying in ${delayTimeMs}ms: ${err}`);
42
+ }
43
+ while (!response && ++numTries <= AlgoHttpClientWithRetry.MAX_TRIES);
44
+ return response;
45
+ }
46
+ async get(relativePath, query, requestHeaders = {}) {
47
+ const response = await this.callWithRetry(() => super.get(relativePath, query, requestHeaders));
48
+ if (relativePath.startsWith("/v2/accounts/") && relativePath.endsWith("/created-applications") && response.status === 200 && query?.["include-all"]?.toString() === "true") try {
49
+ const json = (0, algosdk.parseJSON)(Buffer.from(response.body).toString(), { intDecoding: algosdk.IntDecoding.MIXED });
50
+ if (json.applications) {
51
+ for (const app of json.applications) if (app.params) {
52
+ if (app.params["approval-program"] === null) app.params["approval-program"] = "";
53
+ if (app.params["clear-state-program"] === null) app.params["clear-state-program"] = "";
54
+ }
55
+ response.body = Buffer.from((0, algosdk.stringifyJSON)(json));
56
+ }
57
+ } catch (e) {
58
+ require_config.Config.logger.warn("Failed to fix indexer response for created applications", e);
59
+ }
60
+ return response;
61
+ }
62
+ async post(relativePath, data, query, requestHeaders = {}) {
63
+ return await this.callWithRetry(() => super.post(relativePath, data, query, requestHeaders));
64
+ }
65
+ async delete(relativePath, data, query, requestHeaders = {}) {
66
+ return await this.callWithRetry(() => super.delete(relativePath, data, query, requestHeaders));
67
+ }
68
+ };
69
+ //#endregion
93
70
  exports.AlgoHttpClientWithRetry = AlgoHttpClientWithRetry;
94
- //# sourceMappingURL=algo-http-client-with-retry.js.map
71
+
72
+ //# sourceMappingURL=algo-http-client-with-retry.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"algo-http-client-with-retry.js","sources":["../../src/types/algo-http-client-with-retry.ts"],"sourcesContent":["import { IntDecoding, parseJSON, stringifyJSON } from 'algosdk'\nimport { BaseHTTPClientResponse, Query, URLTokenBaseHTTPClient } from 'algosdk/client'\nimport { Config } from '../config'\n\n/** A HTTP Client that wraps the Algorand SDK HTTP Client with retries */\nexport class AlgoHttpClientWithRetry extends URLTokenBaseHTTPClient {\n private static readonly MAX_TRIES = 5\n private static readonly MAX_BACKOFF_MS = 10000\n\n // These lists come from https://visionmedia.github.io/superagent/#retrying-requests\n // which is the underlying library used by algosdk - but the CloudFlare specific 52X status codes have been removed\n private static readonly RETRY_STATUS_CODES = [408, 413, 429, 500, 502, 503, 504]\n private static readonly RETRY_ERROR_CODES = [\n 'ETIMEDOUT',\n 'ECONNRESET',\n 'EADDRINUSE',\n 'ECONNREFUSED',\n 'EPIPE',\n 'ENOTFOUND',\n 'ENETUNREACH',\n 'EAI_AGAIN',\n 'EPROTO', // We get this intermittently with AlgoNode API\n ]\n\n private async callWithRetry(func: () => Promise<BaseHTTPClientResponse>): Promise<BaseHTTPClientResponse> {\n let response: BaseHTTPClientResponse | undefined\n let numTries = 1\n do {\n try {\n response = await func()\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n } catch (err: any) {\n if (numTries >= AlgoHttpClientWithRetry.MAX_TRIES) {\n throw err\n }\n // Only retry for one of the hardcoded conditions\n if (\n !(\n AlgoHttpClientWithRetry.RETRY_ERROR_CODES.includes(err.code) ||\n AlgoHttpClientWithRetry.RETRY_STATUS_CODES.includes(Number(err.status)) ||\n ('response' in err && AlgoHttpClientWithRetry.RETRY_STATUS_CODES.includes(Number(err.response.status)))\n )\n ) {\n throw err\n }\n // Retry immediately the first time, then exponentially backoff.\n const delayTimeMs = numTries == 1 ? 0 : Math.min(1000 * Math.pow(2, numTries - 1), AlgoHttpClientWithRetry.MAX_BACKOFF_MS)\n if (delayTimeMs > 0) {\n await new Promise((r) => setTimeout(r, delayTimeMs))\n }\n Config.logger.warn(`algosdk request failed ${numTries} times. Retrying in ${delayTimeMs}ms: ${err}`)\n }\n } while (!response && ++numTries <= AlgoHttpClientWithRetry.MAX_TRIES)\n return response!\n }\n\n async get(relativePath: string, query?: Query<string>, requestHeaders: Record<string, string> = {}): Promise<BaseHTTPClientResponse> {\n const response = await this.callWithRetry(() => super.get(relativePath, query, requestHeaders))\n if (\n relativePath.startsWith('/v2/accounts/') &&\n relativePath.endsWith('/created-applications') &&\n response.status === 200 &&\n query?.['include-all']?.toString() === 'true'\n ) {\n // todo: Temporary hack\n // Indexer get created applications by account returns approvalProgram and clearStateProgram as null, which breaks the algosdk@3 decoder\n // instead we will detect this call and set them to empty byte arrays\n try {\n const json = parseJSON(Buffer.from(response.body).toString(), { intDecoding: IntDecoding.MIXED })\n if (json.applications) {\n for (const app of json.applications) {\n if (app.params) {\n if (app.params['approval-program'] === null) {\n app.params['approval-program'] = ''\n }\n if (app.params['clear-state-program'] === null) {\n app.params['clear-state-program'] = ''\n }\n }\n }\n response.body = Buffer.from(stringifyJSON(json))\n }\n } catch (e) {\n // Make this hack resilient so we never break the app\n Config.logger.warn('Failed to fix indexer response for created applications', e)\n }\n }\n return response\n }\n\n async post(\n relativePath: string,\n data: Uint8Array,\n query?: Query<string>,\n requestHeaders: Record<string, string> = {},\n ): Promise<BaseHTTPClientResponse> {\n return await this.callWithRetry(() => super.post(relativePath, data, query, requestHeaders))\n }\n\n async delete(\n relativePath: string,\n data: Uint8Array,\n query?: Query<string>,\n requestHeaders: Record<string, string> = {},\n ): Promise<BaseHTTPClientResponse> {\n return await this.callWithRetry(() => super.delete(relativePath, data, query, requestHeaders))\n }\n}\n"],"names":["URLTokenBaseHTTPClient","Config","parseJSON","IntDecoding","stringifyJSON"],"mappings":"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"}
1
+ {"version":3,"file":"algo-http-client-with-retry.js","names":["URLTokenBaseHTTPClient","IntDecoding"],"sources":["../../src/types/algo-http-client-with-retry.ts"],"sourcesContent":["import { IntDecoding, parseJSON, stringifyJSON } from 'algosdk'\nimport { BaseHTTPClientResponse, Query, URLTokenBaseHTTPClient } from 'algosdk/client'\nimport { Config } from '../config'\n\n/** A HTTP Client that wraps the Algorand SDK HTTP Client with retries */\nexport class AlgoHttpClientWithRetry extends URLTokenBaseHTTPClient {\n private static readonly MAX_TRIES = 5\n private static readonly MAX_BACKOFF_MS = 10000\n\n // These lists come from https://visionmedia.github.io/superagent/#retrying-requests\n // which is the underlying library used by algosdk - but the CloudFlare specific 52X status codes have been removed\n private static readonly RETRY_STATUS_CODES = [408, 413, 429, 500, 502, 503, 504]\n private static readonly RETRY_ERROR_CODES = [\n 'ETIMEDOUT',\n 'ECONNRESET',\n 'EADDRINUSE',\n 'ECONNREFUSED',\n 'EPIPE',\n 'ENOTFOUND',\n 'ENETUNREACH',\n 'EAI_AGAIN',\n 'EPROTO', // We get this intermittently with AlgoNode API\n ]\n\n private async callWithRetry(func: () => Promise<BaseHTTPClientResponse>): Promise<BaseHTTPClientResponse> {\n let response: BaseHTTPClientResponse | undefined\n let numTries = 1\n do {\n try {\n response = await func()\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n } catch (err: any) {\n if (numTries >= AlgoHttpClientWithRetry.MAX_TRIES) {\n throw err\n }\n // Only retry for one of the hardcoded conditions\n if (\n !(\n AlgoHttpClientWithRetry.RETRY_ERROR_CODES.includes(err.code) ||\n AlgoHttpClientWithRetry.RETRY_STATUS_CODES.includes(Number(err.status)) ||\n ('response' in err && AlgoHttpClientWithRetry.RETRY_STATUS_CODES.includes(Number(err.response.status)))\n )\n ) {\n throw err\n }\n // Retry immediately the first time, then exponentially backoff.\n const delayTimeMs = numTries == 1 ? 0 : Math.min(1000 * Math.pow(2, numTries - 1), AlgoHttpClientWithRetry.MAX_BACKOFF_MS)\n if (delayTimeMs > 0) {\n await new Promise((r) => setTimeout(r, delayTimeMs))\n }\n Config.logger.warn(`algosdk request failed ${numTries} times. Retrying in ${delayTimeMs}ms: ${err}`)\n }\n } while (!response && ++numTries <= AlgoHttpClientWithRetry.MAX_TRIES)\n return response!\n }\n\n async get(relativePath: string, query?: Query<string>, requestHeaders: Record<string, string> = {}): Promise<BaseHTTPClientResponse> {\n const response = await this.callWithRetry(() => super.get(relativePath, query, requestHeaders))\n if (\n relativePath.startsWith('/v2/accounts/') &&\n relativePath.endsWith('/created-applications') &&\n response.status === 200 &&\n query?.['include-all']?.toString() === 'true'\n ) {\n // todo: Temporary hack\n // Indexer get created applications by account returns approvalProgram and clearStateProgram as null, which breaks the algosdk@3 decoder\n // instead we will detect this call and set them to empty byte arrays\n try {\n const json = parseJSON(Buffer.from(response.body).toString(), { intDecoding: IntDecoding.MIXED })\n if (json.applications) {\n for (const app of json.applications) {\n if (app.params) {\n if (app.params['approval-program'] === null) {\n app.params['approval-program'] = ''\n }\n if (app.params['clear-state-program'] === null) {\n app.params['clear-state-program'] = ''\n }\n }\n }\n response.body = Buffer.from(stringifyJSON(json))\n }\n } catch (e) {\n // Make this hack resilient so we never break the app\n Config.logger.warn('Failed to fix indexer response for created applications', e)\n }\n }\n return response\n }\n\n async post(\n relativePath: string,\n data: Uint8Array,\n query?: Query<string>,\n requestHeaders: Record<string, string> = {},\n ): Promise<BaseHTTPClientResponse> {\n return await this.callWithRetry(() => super.post(relativePath, data, query, requestHeaders))\n }\n\n async delete(\n relativePath: string,\n data: Uint8Array,\n query?: Query<string>,\n requestHeaders: Record<string, string> = {},\n ): Promise<BaseHTTPClientResponse> {\n return await this.callWithRetry(() => super.delete(relativePath, data, query, requestHeaders))\n }\n}\n"],"mappings":";;;;;;AAKA,IAAa,0BAAb,MAAa,gCAAgCA,eAAAA,uBAAuB;CAClE,OAAwB,YAAY;CACpC,OAAwB,iBAAiB;CAIzC,OAAwB,qBAAqB;EAAC;EAAK;EAAK;EAAK;EAAK;EAAK;EAAK;CAAG;CAC/E,OAAwB,oBAAoB;EAC1C;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;CACF;CAEA,MAAc,cAAc,MAA8E;EACxG,IAAI;EACJ,IAAI,WAAW;EACf;GACE,IAAI;IACF,WAAW,MAAM,KAAK;GAExB,SAAS,KAAU;IACjB,IAAI,YAAY,wBAAwB,WACtC,MAAM;IAGR,IACE,EACE,wBAAwB,kBAAkB,SAAS,IAAI,IAAI,KAC3D,wBAAwB,mBAAmB,SAAS,OAAO,IAAI,MAAM,CAAC,KACrE,cAAc,OAAO,wBAAwB,mBAAmB,SAAS,OAAO,IAAI,SAAS,MAAM,CAAC,IAGvG,MAAM;IAGR,MAAM,cAAc,YAAY,IAAI,IAAI,KAAK,IAAI,MAAO,KAAK,IAAI,GAAG,WAAW,CAAC,GAAG,wBAAwB,cAAc;IACzH,IAAI,cAAc,GAChB,MAAM,IAAI,SAAS,MAAM,WAAW,GAAG,WAAW,CAAC;IAErD,eAAA,OAAO,OAAO,KAAK,0BAA0B,SAAS,sBAAsB,YAAY,MAAM,KAAK;GACrG;SACO,CAAC,YAAY,EAAE,YAAY,wBAAwB;EAC5D,OAAO;CACT;CAEA,MAAM,IAAI,cAAsB,OAAuB,iBAAyC,CAAC,GAAoC;EACnI,MAAM,WAAW,MAAM,KAAK,oBAAoB,MAAM,IAAI,cAAc,OAAO,cAAc,CAAC;EAC9F,IACE,aAAa,WAAW,eAAe,KACvC,aAAa,SAAS,uBAAuB,KAC7C,SAAS,WAAW,OACpB,QAAQ,cAAc,EAAE,SAAS,MAAM,QAKvC,IAAI;GACF,MAAM,QAAA,GAAA,QAAA,UAAA,CAAiB,OAAO,KAAK,SAAS,IAAI,CAAC,CAAC,SAAS,GAAG,EAAE,aAAaC,QAAAA,YAAY,MAAM,CAAC;GAChG,IAAI,KAAK,cAAc;IACrB,KAAK,MAAM,OAAO,KAAK,cACrB,IAAI,IAAI,QAAQ;KACd,IAAI,IAAI,OAAO,wBAAwB,MACrC,IAAI,OAAO,sBAAsB;KAEnC,IAAI,IAAI,OAAO,2BAA2B,MACxC,IAAI,OAAO,yBAAyB;IAExC;IAEF,SAAS,OAAO,OAAO,MAAA,GAAA,QAAA,cAAA,CAAmB,IAAI,CAAC;GACjD;EACF,SAAS,GAAG;GAEV,eAAA,OAAO,OAAO,KAAK,2DAA2D,CAAC;EACjF;EAEF,OAAO;CACT;CAEA,MAAM,KACJ,cACA,MACA,OACA,iBAAyC,CAAC,GACT;EACjC,OAAO,MAAM,KAAK,oBAAoB,MAAM,KAAK,cAAc,MAAM,OAAO,cAAc,CAAC;CAC7F;CAEA,MAAM,OACJ,cACA,MACA,OACA,iBAAyC,CAAC,GACT;EACjC,OAAO,MAAM,KAAK,oBAAoB,MAAM,OAAO,cAAc,MAAM,OAAO,cAAc,CAAC;CAC/F;AACF"}
@@ -1,92 +1,71 @@
1
- import { parseJSON, IntDecoding, stringifyJSON } from 'algosdk';
2
- import { URLTokenBaseHTTPClient } from 'algosdk/client';
3
- import { Config } from '../config.mjs';
4
-
1
+ import { Config } from "../config.mjs";
2
+ import { IntDecoding, parseJSON, stringifyJSON } from "algosdk";
3
+ import { URLTokenBaseHTTPClient } from "algosdk/client";
4
+ //#region src/types/algo-http-client-with-retry.ts
5
5
  /** A HTTP Client that wraps the Algorand SDK HTTP Client with retries */
6
- class AlgoHttpClientWithRetry extends URLTokenBaseHTTPClient {
7
- async callWithRetry(func) {
8
- let response;
9
- let numTries = 1;
10
- do {
11
- try {
12
- response = await func();
13
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
14
- }
15
- catch (err) {
16
- if (numTries >= AlgoHttpClientWithRetry.MAX_TRIES) {
17
- throw err;
18
- }
19
- // Only retry for one of the hardcoded conditions
20
- if (!(AlgoHttpClientWithRetry.RETRY_ERROR_CODES.includes(err.code) ||
21
- AlgoHttpClientWithRetry.RETRY_STATUS_CODES.includes(Number(err.status)) ||
22
- ('response' in err && AlgoHttpClientWithRetry.RETRY_STATUS_CODES.includes(Number(err.response.status))))) {
23
- throw err;
24
- }
25
- // Retry immediately the first time, then exponentially backoff.
26
- const delayTimeMs = numTries == 1 ? 0 : Math.min(1000 * Math.pow(2, numTries - 1), AlgoHttpClientWithRetry.MAX_BACKOFF_MS);
27
- if (delayTimeMs > 0) {
28
- await new Promise((r) => setTimeout(r, delayTimeMs));
29
- }
30
- Config.logger.warn(`algosdk request failed ${numTries} times. Retrying in ${delayTimeMs}ms: ${err}`);
31
- }
32
- } while (!response && ++numTries <= AlgoHttpClientWithRetry.MAX_TRIES);
33
- return response;
34
- }
35
- async get(relativePath, query, requestHeaders = {}) {
36
- const response = await this.callWithRetry(() => super.get(relativePath, query, requestHeaders));
37
- if (relativePath.startsWith('/v2/accounts/') &&
38
- relativePath.endsWith('/created-applications') &&
39
- response.status === 200 &&
40
- query?.['include-all']?.toString() === 'true') {
41
- // todo: Temporary hack
42
- // Indexer get created applications by account returns approvalProgram and clearStateProgram as null, which breaks the algosdk@3 decoder
43
- // instead we will detect this call and set them to empty byte arrays
44
- try {
45
- const json = parseJSON(Buffer.from(response.body).toString(), { intDecoding: IntDecoding.MIXED });
46
- if (json.applications) {
47
- for (const app of json.applications) {
48
- if (app.params) {
49
- if (app.params['approval-program'] === null) {
50
- app.params['approval-program'] = '';
51
- }
52
- if (app.params['clear-state-program'] === null) {
53
- app.params['clear-state-program'] = '';
54
- }
55
- }
56
- }
57
- response.body = Buffer.from(stringifyJSON(json));
58
- }
59
- }
60
- catch (e) {
61
- // Make this hack resilient so we never break the app
62
- Config.logger.warn('Failed to fix indexer response for created applications', e);
63
- }
64
- }
65
- return response;
66
- }
67
- async post(relativePath, data, query, requestHeaders = {}) {
68
- return await this.callWithRetry(() => super.post(relativePath, data, query, requestHeaders));
69
- }
70
- async delete(relativePath, data, query, requestHeaders = {}) {
71
- return await this.callWithRetry(() => super.delete(relativePath, data, query, requestHeaders));
72
- }
73
- }
74
- AlgoHttpClientWithRetry.MAX_TRIES = 5;
75
- AlgoHttpClientWithRetry.MAX_BACKOFF_MS = 10000;
76
- // These lists come from https://visionmedia.github.io/superagent/#retrying-requests
77
- // which is the underlying library used by algosdk - but the CloudFlare specific 52X status codes have been removed
78
- AlgoHttpClientWithRetry.RETRY_STATUS_CODES = [408, 413, 429, 500, 502, 503, 504];
79
- AlgoHttpClientWithRetry.RETRY_ERROR_CODES = [
80
- 'ETIMEDOUT',
81
- 'ECONNRESET',
82
- 'EADDRINUSE',
83
- 'ECONNREFUSED',
84
- 'EPIPE',
85
- 'ENOTFOUND',
86
- 'ENETUNREACH',
87
- 'EAI_AGAIN',
88
- 'EPROTO', // We get this intermittently with AlgoNode API
89
- ];
90
-
6
+ var AlgoHttpClientWithRetry = class AlgoHttpClientWithRetry extends URLTokenBaseHTTPClient {
7
+ static MAX_TRIES = 5;
8
+ static MAX_BACKOFF_MS = 1e4;
9
+ static RETRY_STATUS_CODES = [
10
+ 408,
11
+ 413,
12
+ 429,
13
+ 500,
14
+ 502,
15
+ 503,
16
+ 504
17
+ ];
18
+ static RETRY_ERROR_CODES = [
19
+ "ETIMEDOUT",
20
+ "ECONNRESET",
21
+ "EADDRINUSE",
22
+ "ECONNREFUSED",
23
+ "EPIPE",
24
+ "ENOTFOUND",
25
+ "ENETUNREACH",
26
+ "EAI_AGAIN",
27
+ "EPROTO"
28
+ ];
29
+ async callWithRetry(func) {
30
+ let response;
31
+ let numTries = 1;
32
+ do
33
+ try {
34
+ response = await func();
35
+ } catch (err) {
36
+ if (numTries >= AlgoHttpClientWithRetry.MAX_TRIES) throw err;
37
+ if (!(AlgoHttpClientWithRetry.RETRY_ERROR_CODES.includes(err.code) || AlgoHttpClientWithRetry.RETRY_STATUS_CODES.includes(Number(err.status)) || "response" in err && AlgoHttpClientWithRetry.RETRY_STATUS_CODES.includes(Number(err.response.status)))) throw err;
38
+ const delayTimeMs = numTries == 1 ? 0 : Math.min(1e3 * Math.pow(2, numTries - 1), AlgoHttpClientWithRetry.MAX_BACKOFF_MS);
39
+ if (delayTimeMs > 0) await new Promise((r) => setTimeout(r, delayTimeMs));
40
+ Config.logger.warn(`algosdk request failed ${numTries} times. Retrying in ${delayTimeMs}ms: ${err}`);
41
+ }
42
+ while (!response && ++numTries <= AlgoHttpClientWithRetry.MAX_TRIES);
43
+ return response;
44
+ }
45
+ async get(relativePath, query, requestHeaders = {}) {
46
+ const response = await this.callWithRetry(() => super.get(relativePath, query, requestHeaders));
47
+ if (relativePath.startsWith("/v2/accounts/") && relativePath.endsWith("/created-applications") && response.status === 200 && query?.["include-all"]?.toString() === "true") try {
48
+ const json = parseJSON(Buffer.from(response.body).toString(), { intDecoding: IntDecoding.MIXED });
49
+ if (json.applications) {
50
+ for (const app of json.applications) if (app.params) {
51
+ if (app.params["approval-program"] === null) app.params["approval-program"] = "";
52
+ if (app.params["clear-state-program"] === null) app.params["clear-state-program"] = "";
53
+ }
54
+ response.body = Buffer.from(stringifyJSON(json));
55
+ }
56
+ } catch (e) {
57
+ Config.logger.warn("Failed to fix indexer response for created applications", e);
58
+ }
59
+ return response;
60
+ }
61
+ async post(relativePath, data, query, requestHeaders = {}) {
62
+ return await this.callWithRetry(() => super.post(relativePath, data, query, requestHeaders));
63
+ }
64
+ async delete(relativePath, data, query, requestHeaders = {}) {
65
+ return await this.callWithRetry(() => super.delete(relativePath, data, query, requestHeaders));
66
+ }
67
+ };
68
+ //#endregion
91
69
  export { AlgoHttpClientWithRetry };
92
- //# sourceMappingURL=algo-http-client-with-retry.mjs.map
70
+
71
+ //# sourceMappingURL=algo-http-client-with-retry.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"algo-http-client-with-retry.mjs","sources":["../../src/types/algo-http-client-with-retry.ts"],"sourcesContent":["import { IntDecoding, parseJSON, stringifyJSON } from 'algosdk'\nimport { BaseHTTPClientResponse, Query, URLTokenBaseHTTPClient } from 'algosdk/client'\nimport { Config } from '../config'\n\n/** A HTTP Client that wraps the Algorand SDK HTTP Client with retries */\nexport class AlgoHttpClientWithRetry extends URLTokenBaseHTTPClient {\n private static readonly MAX_TRIES = 5\n private static readonly MAX_BACKOFF_MS = 10000\n\n // These lists come from https://visionmedia.github.io/superagent/#retrying-requests\n // which is the underlying library used by algosdk - but the CloudFlare specific 52X status codes have been removed\n private static readonly RETRY_STATUS_CODES = [408, 413, 429, 500, 502, 503, 504]\n private static readonly RETRY_ERROR_CODES = [\n 'ETIMEDOUT',\n 'ECONNRESET',\n 'EADDRINUSE',\n 'ECONNREFUSED',\n 'EPIPE',\n 'ENOTFOUND',\n 'ENETUNREACH',\n 'EAI_AGAIN',\n 'EPROTO', // We get this intermittently with AlgoNode API\n ]\n\n private async callWithRetry(func: () => Promise<BaseHTTPClientResponse>): Promise<BaseHTTPClientResponse> {\n let response: BaseHTTPClientResponse | undefined\n let numTries = 1\n do {\n try {\n response = await func()\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n } catch (err: any) {\n if (numTries >= AlgoHttpClientWithRetry.MAX_TRIES) {\n throw err\n }\n // Only retry for one of the hardcoded conditions\n if (\n !(\n AlgoHttpClientWithRetry.RETRY_ERROR_CODES.includes(err.code) ||\n AlgoHttpClientWithRetry.RETRY_STATUS_CODES.includes(Number(err.status)) ||\n ('response' in err && AlgoHttpClientWithRetry.RETRY_STATUS_CODES.includes(Number(err.response.status)))\n )\n ) {\n throw err\n }\n // Retry immediately the first time, then exponentially backoff.\n const delayTimeMs = numTries == 1 ? 0 : Math.min(1000 * Math.pow(2, numTries - 1), AlgoHttpClientWithRetry.MAX_BACKOFF_MS)\n if (delayTimeMs > 0) {\n await new Promise((r) => setTimeout(r, delayTimeMs))\n }\n Config.logger.warn(`algosdk request failed ${numTries} times. Retrying in ${delayTimeMs}ms: ${err}`)\n }\n } while (!response && ++numTries <= AlgoHttpClientWithRetry.MAX_TRIES)\n return response!\n }\n\n async get(relativePath: string, query?: Query<string>, requestHeaders: Record<string, string> = {}): Promise<BaseHTTPClientResponse> {\n const response = await this.callWithRetry(() => super.get(relativePath, query, requestHeaders))\n if (\n relativePath.startsWith('/v2/accounts/') &&\n relativePath.endsWith('/created-applications') &&\n response.status === 200 &&\n query?.['include-all']?.toString() === 'true'\n ) {\n // todo: Temporary hack\n // Indexer get created applications by account returns approvalProgram and clearStateProgram as null, which breaks the algosdk@3 decoder\n // instead we will detect this call and set them to empty byte arrays\n try {\n const json = parseJSON(Buffer.from(response.body).toString(), { intDecoding: IntDecoding.MIXED })\n if (json.applications) {\n for (const app of json.applications) {\n if (app.params) {\n if (app.params['approval-program'] === null) {\n app.params['approval-program'] = ''\n }\n if (app.params['clear-state-program'] === null) {\n app.params['clear-state-program'] = ''\n }\n }\n }\n response.body = Buffer.from(stringifyJSON(json))\n }\n } catch (e) {\n // Make this hack resilient so we never break the app\n Config.logger.warn('Failed to fix indexer response for created applications', e)\n }\n }\n return response\n }\n\n async post(\n relativePath: string,\n data: Uint8Array,\n query?: Query<string>,\n requestHeaders: Record<string, string> = {},\n ): Promise<BaseHTTPClientResponse> {\n return await this.callWithRetry(() => super.post(relativePath, data, query, requestHeaders))\n }\n\n async delete(\n relativePath: string,\n data: Uint8Array,\n query?: Query<string>,\n requestHeaders: Record<string, string> = {},\n ): Promise<BaseHTTPClientResponse> {\n return await this.callWithRetry(() => super.delete(relativePath, data, query, requestHeaders))\n }\n}\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"algo-http-client-with-retry.mjs","names":[],"sources":["../../src/types/algo-http-client-with-retry.ts"],"sourcesContent":["import { IntDecoding, parseJSON, stringifyJSON } from 'algosdk'\nimport { BaseHTTPClientResponse, Query, URLTokenBaseHTTPClient } from 'algosdk/client'\nimport { Config } from '../config'\n\n/** A HTTP Client that wraps the Algorand SDK HTTP Client with retries */\nexport class AlgoHttpClientWithRetry extends URLTokenBaseHTTPClient {\n private static readonly MAX_TRIES = 5\n private static readonly MAX_BACKOFF_MS = 10000\n\n // These lists come from https://visionmedia.github.io/superagent/#retrying-requests\n // which is the underlying library used by algosdk - but the CloudFlare specific 52X status codes have been removed\n private static readonly RETRY_STATUS_CODES = [408, 413, 429, 500, 502, 503, 504]\n private static readonly RETRY_ERROR_CODES = [\n 'ETIMEDOUT',\n 'ECONNRESET',\n 'EADDRINUSE',\n 'ECONNREFUSED',\n 'EPIPE',\n 'ENOTFOUND',\n 'ENETUNREACH',\n 'EAI_AGAIN',\n 'EPROTO', // We get this intermittently with AlgoNode API\n ]\n\n private async callWithRetry(func: () => Promise<BaseHTTPClientResponse>): Promise<BaseHTTPClientResponse> {\n let response: BaseHTTPClientResponse | undefined\n let numTries = 1\n do {\n try {\n response = await func()\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n } catch (err: any) {\n if (numTries >= AlgoHttpClientWithRetry.MAX_TRIES) {\n throw err\n }\n // Only retry for one of the hardcoded conditions\n if (\n !(\n AlgoHttpClientWithRetry.RETRY_ERROR_CODES.includes(err.code) ||\n AlgoHttpClientWithRetry.RETRY_STATUS_CODES.includes(Number(err.status)) ||\n ('response' in err && AlgoHttpClientWithRetry.RETRY_STATUS_CODES.includes(Number(err.response.status)))\n )\n ) {\n throw err\n }\n // Retry immediately the first time, then exponentially backoff.\n const delayTimeMs = numTries == 1 ? 0 : Math.min(1000 * Math.pow(2, numTries - 1), AlgoHttpClientWithRetry.MAX_BACKOFF_MS)\n if (delayTimeMs > 0) {\n await new Promise((r) => setTimeout(r, delayTimeMs))\n }\n Config.logger.warn(`algosdk request failed ${numTries} times. Retrying in ${delayTimeMs}ms: ${err}`)\n }\n } while (!response && ++numTries <= AlgoHttpClientWithRetry.MAX_TRIES)\n return response!\n }\n\n async get(relativePath: string, query?: Query<string>, requestHeaders: Record<string, string> = {}): Promise<BaseHTTPClientResponse> {\n const response = await this.callWithRetry(() => super.get(relativePath, query, requestHeaders))\n if (\n relativePath.startsWith('/v2/accounts/') &&\n relativePath.endsWith('/created-applications') &&\n response.status === 200 &&\n query?.['include-all']?.toString() === 'true'\n ) {\n // todo: Temporary hack\n // Indexer get created applications by account returns approvalProgram and clearStateProgram as null, which breaks the algosdk@3 decoder\n // instead we will detect this call and set them to empty byte arrays\n try {\n const json = parseJSON(Buffer.from(response.body).toString(), { intDecoding: IntDecoding.MIXED })\n if (json.applications) {\n for (const app of json.applications) {\n if (app.params) {\n if (app.params['approval-program'] === null) {\n app.params['approval-program'] = ''\n }\n if (app.params['clear-state-program'] === null) {\n app.params['clear-state-program'] = ''\n }\n }\n }\n response.body = Buffer.from(stringifyJSON(json))\n }\n } catch (e) {\n // Make this hack resilient so we never break the app\n Config.logger.warn('Failed to fix indexer response for created applications', e)\n }\n }\n return response\n }\n\n async post(\n relativePath: string,\n data: Uint8Array,\n query?: Query<string>,\n requestHeaders: Record<string, string> = {},\n ): Promise<BaseHTTPClientResponse> {\n return await this.callWithRetry(() => super.post(relativePath, data, query, requestHeaders))\n }\n\n async delete(\n relativePath: string,\n data: Uint8Array,\n query?: Query<string>,\n requestHeaders: Record<string, string> = {},\n ): Promise<BaseHTTPClientResponse> {\n return await this.callWithRetry(() => super.delete(relativePath, data, query, requestHeaders))\n }\n}\n"],"mappings":";;;;;AAKA,IAAa,0BAAb,MAAa,gCAAgC,uBAAuB;CAClE,OAAwB,YAAY;CACpC,OAAwB,iBAAiB;CAIzC,OAAwB,qBAAqB;EAAC;EAAK;EAAK;EAAK;EAAK;EAAK;EAAK;CAAG;CAC/E,OAAwB,oBAAoB;EAC1C;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;CACF;CAEA,MAAc,cAAc,MAA8E;EACxG,IAAI;EACJ,IAAI,WAAW;EACf;GACE,IAAI;IACF,WAAW,MAAM,KAAK;GAExB,SAAS,KAAU;IACjB,IAAI,YAAY,wBAAwB,WACtC,MAAM;IAGR,IACE,EACE,wBAAwB,kBAAkB,SAAS,IAAI,IAAI,KAC3D,wBAAwB,mBAAmB,SAAS,OAAO,IAAI,MAAM,CAAC,KACrE,cAAc,OAAO,wBAAwB,mBAAmB,SAAS,OAAO,IAAI,SAAS,MAAM,CAAC,IAGvG,MAAM;IAGR,MAAM,cAAc,YAAY,IAAI,IAAI,KAAK,IAAI,MAAO,KAAK,IAAI,GAAG,WAAW,CAAC,GAAG,wBAAwB,cAAc;IACzH,IAAI,cAAc,GAChB,MAAM,IAAI,SAAS,MAAM,WAAW,GAAG,WAAW,CAAC;IAErD,OAAO,OAAO,KAAK,0BAA0B,SAAS,sBAAsB,YAAY,MAAM,KAAK;GACrG;SACO,CAAC,YAAY,EAAE,YAAY,wBAAwB;EAC5D,OAAO;CACT;CAEA,MAAM,IAAI,cAAsB,OAAuB,iBAAyC,CAAC,GAAoC;EACnI,MAAM,WAAW,MAAM,KAAK,oBAAoB,MAAM,IAAI,cAAc,OAAO,cAAc,CAAC;EAC9F,IACE,aAAa,WAAW,eAAe,KACvC,aAAa,SAAS,uBAAuB,KAC7C,SAAS,WAAW,OACpB,QAAQ,cAAc,EAAE,SAAS,MAAM,QAKvC,IAAI;GACF,MAAM,OAAO,UAAU,OAAO,KAAK,SAAS,IAAI,CAAC,CAAC,SAAS,GAAG,EAAE,aAAa,YAAY,MAAM,CAAC;GAChG,IAAI,KAAK,cAAc;IACrB,KAAK,MAAM,OAAO,KAAK,cACrB,IAAI,IAAI,QAAQ;KACd,IAAI,IAAI,OAAO,wBAAwB,MACrC,IAAI,OAAO,sBAAsB;KAEnC,IAAI,IAAI,OAAO,2BAA2B,MACxC,IAAI,OAAO,yBAAyB;IAExC;IAEF,SAAS,OAAO,OAAO,KAAK,cAAc,IAAI,CAAC;GACjD;EACF,SAAS,GAAG;GAEV,OAAO,OAAO,KAAK,2DAA2D,CAAC;EACjF;EAEF,OAAO;CACT;CAEA,MAAM,KACJ,cACA,MACA,OACA,iBAAyC,CAAC,GACT;EACjC,OAAO,MAAM,KAAK,oBAAoB,MAAM,KAAK,cAAc,MAAM,OAAO,cAAc,CAAC;CAC7F;CAEA,MAAM,OACJ,cACA,MACA,OACA,iBAAyC,CAAC,GACT;EACjC,OAAO,MAAM,KAAK,oBAAoB,MAAM,OAAO,cAAc,MAAM,OAAO,cAAc,CAAC;CAC/F;AACF"}