@ledgerhq/coin-stellar 6.26.0 → 6.26.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 (281) hide show
  1. package/.oxlintrc.json +7 -0
  2. package/CHANGELOG.md +12 -0
  3. package/LICENSE +194 -0
  4. package/knip.json +12 -0
  5. package/lib/api/index.d.ts +5 -5
  6. package/lib/api/index.d.ts.map +1 -1
  7. package/lib/api/index.js +12 -10
  8. package/lib/api/index.js.map +1 -1
  9. package/lib/config.d.ts +1 -1
  10. package/lib/config.d.ts.map +1 -1
  11. package/lib/config.js +2 -0
  12. package/lib/config.js.map +1 -1
  13. package/lib/constants.d.ts.map +1 -1
  14. package/lib/constants.js +3 -1
  15. package/lib/constants.js.map +1 -1
  16. package/lib/logic/broadcast.d.ts.map +1 -1
  17. package/lib/logic/broadcast.js +2 -0
  18. package/lib/logic/broadcast.js.map +1 -1
  19. package/lib/logic/combine.d.ts +1 -1
  20. package/lib/logic/combine.d.ts.map +1 -1
  21. package/lib/logic/combine.js +2 -0
  22. package/lib/logic/combine.js.map +1 -1
  23. package/lib/logic/common.d.ts +1 -1
  24. package/lib/logic/common.d.ts.map +1 -1
  25. package/lib/logic/common.js +4 -2
  26. package/lib/logic/common.js.map +1 -1
  27. package/lib/logic/craftTransaction.d.ts +1 -1
  28. package/lib/logic/craftTransaction.d.ts.map +1 -1
  29. package/lib/logic/craftTransaction.js +10 -8
  30. package/lib/logic/craftTransaction.js.map +1 -1
  31. package/lib/logic/estimateFees.d.ts.map +1 -1
  32. package/lib/logic/estimateFees.js +2 -0
  33. package/lib/logic/estimateFees.js.map +1 -1
  34. package/lib/logic/getBalance.d.ts +1 -1
  35. package/lib/logic/getBalance.d.ts.map +1 -1
  36. package/lib/logic/getBalance.js +4 -2
  37. package/lib/logic/getBalance.js.map +1 -1
  38. package/lib/logic/getBlock.d.ts +1 -1
  39. package/lib/logic/getBlock.d.ts.map +1 -1
  40. package/lib/logic/getBlock.js +39 -34
  41. package/lib/logic/getBlock.js.map +1 -1
  42. package/lib/logic/getBlockInfo.d.ts +1 -1
  43. package/lib/logic/getBlockInfo.d.ts.map +1 -1
  44. package/lib/logic/getBlockInfo.js +2 -0
  45. package/lib/logic/getBlockInfo.js.map +1 -1
  46. package/lib/logic/index.d.ts +12 -12
  47. package/lib/logic/index.d.ts.map +1 -1
  48. package/lib/logic/index.js +2 -0
  49. package/lib/logic/index.js.map +1 -1
  50. package/lib/logic/lastBlock.d.ts +1 -1
  51. package/lib/logic/lastBlock.d.ts.map +1 -1
  52. package/lib/logic/lastBlock.js +2 -0
  53. package/lib/logic/lastBlock.js.map +1 -1
  54. package/lib/logic/listOperations.d.ts +1 -1
  55. package/lib/logic/listOperations.d.ts.map +1 -1
  56. package/lib/logic/listOperations.js +6 -4
  57. package/lib/logic/listOperations.js.map +1 -1
  58. package/lib/logic/sdkWrapper.d.ts +1 -1
  59. package/lib/logic/sdkWrapper.d.ts.map +1 -1
  60. package/lib/logic/sdkWrapper.js +2 -0
  61. package/lib/logic/sdkWrapper.js.map +1 -1
  62. package/lib/logic/utils.d.ts.map +1 -1
  63. package/lib/logic/utils.js +4 -2
  64. package/lib/logic/utils.js.map +1 -1
  65. package/lib/logic/validateAddress.d.ts +1 -1
  66. package/lib/logic/validateAddress.d.ts.map +1 -1
  67. package/lib/logic/validateAddress.js +2 -0
  68. package/lib/logic/validateAddress.js.map +1 -1
  69. package/lib/logic/validateIntent.d.ts +2 -2
  70. package/lib/logic/validateIntent.d.ts.map +1 -1
  71. package/lib/logic/validateIntent.js +21 -19
  72. package/lib/logic/validateIntent.js.map +1 -1
  73. package/lib/logic/validateMemo.d.ts +1 -1
  74. package/lib/logic/validateMemo.d.ts.map +1 -1
  75. package/lib/logic/validateMemo.js +7 -5
  76. package/lib/logic/validateMemo.js.map +1 -1
  77. package/lib/network/horizon.d.ts +6 -7
  78. package/lib/network/horizon.d.ts.map +1 -1
  79. package/lib/network/horizon.js +48 -95
  80. package/lib/network/horizon.js.map +1 -1
  81. package/lib/network/horizonErrorBody.d.ts +29 -0
  82. package/lib/network/horizonErrorBody.d.ts.map +1 -0
  83. package/lib/network/horizonErrorBody.js +139 -0
  84. package/lib/network/horizonErrorBody.js.map +1 -0
  85. package/lib/network/horizonLedgerErrors.d.ts.map +1 -1
  86. package/lib/network/horizonLedgerErrors.js +28 -4
  87. package/lib/network/horizonLedgerErrors.js.map +1 -1
  88. package/lib/network/index.d.ts +1 -1
  89. package/lib/network/index.d.ts.map +1 -1
  90. package/lib/network/index.js +2 -0
  91. package/lib/network/index.js.map +1 -1
  92. package/lib/network/serialization.d.ts +6 -4
  93. package/lib/network/serialization.d.ts.map +1 -1
  94. package/lib/network/serialization.js +95 -91
  95. package/lib/network/serialization.js.map +1 -1
  96. package/lib/polyfill.d.ts.map +1 -1
  97. package/lib/polyfill.js +6 -4
  98. package/lib/polyfill.js.map +1 -1
  99. package/lib/supportedFeatures.d.ts +1 -1
  100. package/lib/supportedFeatures.d.ts.map +1 -1
  101. package/lib/supportedFeatures.js +3 -1
  102. package/lib/supportedFeatures.js.map +1 -1
  103. package/lib/types/errors.d.ts.map +1 -1
  104. package/lib/types/errors.js +14 -12
  105. package/lib/types/errors.js.map +1 -1
  106. package/lib/types/index.d.ts +2 -2
  107. package/lib/types/index.d.ts.map +1 -1
  108. package/lib/types/index.js +2 -0
  109. package/lib/types/index.js.map +1 -1
  110. package/lib/types/model.d.ts +6 -6
  111. package/lib/types/model.d.ts.map +1 -1
  112. package/lib/types/model.js +7 -5
  113. package/lib/types/model.js.map +1 -1
  114. package/lib-es/api/index.d.ts +5 -5
  115. package/lib-es/api/index.d.ts.map +1 -1
  116. package/lib-es/api/index.js +20 -18
  117. package/lib-es/api/index.js.map +1 -1
  118. package/lib-es/config.d.ts +1 -1
  119. package/lib-es/config.d.ts.map +1 -1
  120. package/lib-es/config.js +3 -1
  121. package/lib-es/config.js.map +1 -1
  122. package/lib-es/constants.d.ts.map +1 -1
  123. package/lib-es/constants.js +3 -1
  124. package/lib-es/constants.js.map +1 -1
  125. package/lib-es/logic/broadcast.d.ts.map +1 -1
  126. package/lib-es/logic/broadcast.js +3 -1
  127. package/lib-es/logic/broadcast.js.map +1 -1
  128. package/lib-es/logic/combine.d.ts +1 -1
  129. package/lib-es/logic/combine.d.ts.map +1 -1
  130. package/lib-es/logic/combine.js +3 -1
  131. package/lib-es/logic/combine.js.map +1 -1
  132. package/lib-es/logic/common.d.ts +1 -1
  133. package/lib-es/logic/common.d.ts.map +1 -1
  134. package/lib-es/logic/common.js +5 -3
  135. package/lib-es/logic/common.js.map +1 -1
  136. package/lib-es/logic/craftTransaction.d.ts +1 -1
  137. package/lib-es/logic/craftTransaction.d.ts.map +1 -1
  138. package/lib-es/logic/craftTransaction.js +15 -13
  139. package/lib-es/logic/craftTransaction.js.map +1 -1
  140. package/lib-es/logic/estimateFees.d.ts.map +1 -1
  141. package/lib-es/logic/estimateFees.js +3 -1
  142. package/lib-es/logic/estimateFees.js.map +1 -1
  143. package/lib-es/logic/getBalance.d.ts +1 -1
  144. package/lib-es/logic/getBalance.d.ts.map +1 -1
  145. package/lib-es/logic/getBalance.js +5 -3
  146. package/lib-es/logic/getBalance.js.map +1 -1
  147. package/lib-es/logic/getBlock.d.ts +1 -1
  148. package/lib-es/logic/getBlock.d.ts.map +1 -1
  149. package/lib-es/logic/getBlock.js +42 -37
  150. package/lib-es/logic/getBlock.js.map +1 -1
  151. package/lib-es/logic/getBlockInfo.d.ts +1 -1
  152. package/lib-es/logic/getBlockInfo.d.ts.map +1 -1
  153. package/lib-es/logic/getBlockInfo.js +3 -1
  154. package/lib-es/logic/getBlockInfo.js.map +1 -1
  155. package/lib-es/logic/index.d.ts +12 -12
  156. package/lib-es/logic/index.d.ts.map +1 -1
  157. package/lib-es/logic/index.js +14 -12
  158. package/lib-es/logic/index.js.map +1 -1
  159. package/lib-es/logic/lastBlock.d.ts +1 -1
  160. package/lib-es/logic/lastBlock.d.ts.map +1 -1
  161. package/lib-es/logic/lastBlock.js +3 -1
  162. package/lib-es/logic/lastBlock.js.map +1 -1
  163. package/lib-es/logic/listOperations.d.ts +1 -1
  164. package/lib-es/logic/listOperations.d.ts.map +1 -1
  165. package/lib-es/logic/listOperations.js +7 -5
  166. package/lib-es/logic/listOperations.js.map +1 -1
  167. package/lib-es/logic/sdkWrapper.d.ts +1 -1
  168. package/lib-es/logic/sdkWrapper.d.ts.map +1 -1
  169. package/lib-es/logic/sdkWrapper.js +4 -2
  170. package/lib-es/logic/sdkWrapper.js.map +1 -1
  171. package/lib-es/logic/utils.d.ts.map +1 -1
  172. package/lib-es/logic/utils.js +6 -4
  173. package/lib-es/logic/utils.js.map +1 -1
  174. package/lib-es/logic/validateAddress.d.ts +1 -1
  175. package/lib-es/logic/validateAddress.d.ts.map +1 -1
  176. package/lib-es/logic/validateAddress.js +3 -1
  177. package/lib-es/logic/validateAddress.js.map +1 -1
  178. package/lib-es/logic/validateIntent.d.ts +2 -2
  179. package/lib-es/logic/validateIntent.d.ts.map +1 -1
  180. package/lib-es/logic/validateIntent.js +30 -28
  181. package/lib-es/logic/validateIntent.js.map +1 -1
  182. package/lib-es/logic/validateMemo.d.ts +1 -1
  183. package/lib-es/logic/validateMemo.d.ts.map +1 -1
  184. package/lib-es/logic/validateMemo.js +8 -6
  185. package/lib-es/logic/validateMemo.js.map +1 -1
  186. package/lib-es/network/horizon.d.ts +6 -7
  187. package/lib-es/network/horizon.d.ts.map +1 -1
  188. package/lib-es/network/horizon.js +57 -104
  189. package/lib-es/network/horizon.js.map +1 -1
  190. package/lib-es/network/horizonErrorBody.d.ts +29 -0
  191. package/lib-es/network/horizonErrorBody.d.ts.map +1 -0
  192. package/lib-es/network/horizonErrorBody.js +134 -0
  193. package/lib-es/network/horizonErrorBody.js.map +1 -0
  194. package/lib-es/network/horizonLedgerErrors.d.ts.map +1 -1
  195. package/lib-es/network/horizonLedgerErrors.js +30 -6
  196. package/lib-es/network/horizonLedgerErrors.js.map +1 -1
  197. package/lib-es/network/index.d.ts +1 -1
  198. package/lib-es/network/index.d.ts.map +1 -1
  199. package/lib-es/network/index.js +3 -1
  200. package/lib-es/network/index.js.map +1 -1
  201. package/lib-es/network/serialization.d.ts +6 -4
  202. package/lib-es/network/serialization.d.ts.map +1 -1
  203. package/lib-es/network/serialization.js +97 -95
  204. package/lib-es/network/serialization.js.map +1 -1
  205. package/lib-es/polyfill.d.ts.map +1 -1
  206. package/lib-es/polyfill.js +7 -5
  207. package/lib-es/polyfill.js.map +1 -1
  208. package/lib-es/supportedFeatures.d.ts +1 -1
  209. package/lib-es/supportedFeatures.d.ts.map +1 -1
  210. package/lib-es/supportedFeatures.js +3 -1
  211. package/lib-es/supportedFeatures.js.map +1 -1
  212. package/lib-es/types/errors.d.ts.map +1 -1
  213. package/lib-es/types/errors.js +15 -13
  214. package/lib-es/types/errors.js.map +1 -1
  215. package/lib-es/types/index.d.ts +2 -2
  216. package/lib-es/types/index.d.ts.map +1 -1
  217. package/lib-es/types/index.js +4 -2
  218. package/lib-es/types/index.js.map +1 -1
  219. package/lib-es/types/model.d.ts +6 -6
  220. package/lib-es/types/model.d.ts.map +1 -1
  221. package/lib-es/types/model.js +7 -5
  222. package/lib-es/types/model.js.map +1 -1
  223. package/package.json +13 -16
  224. package/src/api/index.integ.test.ts +168 -163
  225. package/src/api/index.test.ts +106 -103
  226. package/src/api/index.ts +49 -46
  227. package/src/api/index_error.test.ts +48 -25
  228. package/src/config.ts +15 -12
  229. package/src/constants.ts +4 -1
  230. package/src/globals.d.ts +7 -5
  231. package/src/logic/broadcast.integ.test.ts +22 -19
  232. package/src/logic/broadcast.ts +5 -2
  233. package/src/logic/combine.test.ts +18 -15
  234. package/src/logic/combine.ts +8 -5
  235. package/src/logic/common.ts +9 -6
  236. package/src/logic/craftTransaction.test.ts +76 -75
  237. package/src/logic/craftTransaction.ts +46 -43
  238. package/src/logic/estimateFees.ts +6 -3
  239. package/src/logic/getBalance.test.ts +31 -28
  240. package/src/logic/getBalance.ts +13 -10
  241. package/src/logic/getBlock.integ.test.ts +40 -39
  242. package/src/logic/getBlock.test.ts +462 -415
  243. package/src/logic/getBlock.ts +142 -127
  244. package/src/logic/getBlockInfo.test.ts +72 -69
  245. package/src/logic/getBlockInfo.ts +15 -12
  246. package/src/logic/index.ts +15 -12
  247. package/src/logic/lastBlock.ts +6 -3
  248. package/src/logic/listOperations.ts +14 -11
  249. package/src/logic/listOperations.unit.test.ts +212 -209
  250. package/src/logic/networkWrappers.test.ts +32 -29
  251. package/src/logic/sdkWrapper.ts +19 -16
  252. package/src/logic/utils.ts +13 -10
  253. package/src/logic/validateAddress.test.ts +21 -18
  254. package/src/logic/validateAddress.ts +7 -4
  255. package/src/logic/validateIntent.test.ts +62 -59
  256. package/src/logic/validateIntent.ts +87 -84
  257. package/src/logic/validateMemo.test.ts +50 -47
  258. package/src/logic/validateMemo.ts +16 -13
  259. package/src/network/broadcastTransaction.test.ts +83 -63
  260. package/src/network/fetchLedgerOperations.unit.test.ts +155 -0
  261. package/src/network/horizon.integ.test.ts +45 -42
  262. package/src/network/horizon.test.ts +17 -14
  263. package/src/network/horizon.ts +244 -314
  264. package/src/network/horizon.unit.test.ts +238 -237
  265. package/src/network/horizonErrorBody.test.ts +133 -0
  266. package/src/network/horizonErrorBody.ts +178 -0
  267. package/src/network/horizonLedgerErrors.test.ts +150 -78
  268. package/src/network/horizonLedgerErrors.ts +47 -20
  269. package/src/network/index.ts +4 -1
  270. package/src/network/registerHorizonInterceptors.test.ts +163 -160
  271. package/src/network/serialization.ts +232 -227
  272. package/src/network/serialization.unit.test.ts +801 -798
  273. package/src/polyfill.ts +18 -15
  274. package/src/supportedFeatures.ts +6 -3
  275. package/src/types/errors.ts +33 -32
  276. package/src/types/index.ts +5 -2
  277. package/src/types/model.ts +55 -52
  278. package/tsconfig.json +1 -1
  279. package/.unimportedrc.json +0 -17
  280. package/LICENSE.txt +0 -21
  281. package/src/network/fetchLedgerOperations.nock.unit.test.ts +0 -156
@@ -1,10 +1,12 @@
1
- import type { Operation, Page } from "@ledgerhq/coin-module-framework/api/types";
2
- import { LedgerAPI4xx, LedgerAPI5xx, NetworkDown } from "@ledgerhq/errors";
3
- import type { CacheRes } from "@ledgerhq/live-network/cache";
4
- import { makeLRUCache } from "@ledgerhq/live-network/cache";
5
- import { log } from "@ledgerhq/logs";
1
+ // SPDX-FileCopyrightText: © 2026 LEDGER SAS
2
+ // SPDX-License-Identifier: Apache-2.0
3
+
4
+ import type { Operation, Page } from '@ledgerhq/coin-module-framework/api/types'
5
+ import type { CacheRes } from '@ledgerhq/live-network/cache'
6
+ import { LedgerAPI4xx, LedgerAPI5xx, NetworkDown } from '@ledgerhq/errors'
7
+ import { makeLRUCache } from '@ledgerhq/live-network/cache'
8
+ import { log } from '@ledgerhq/logs'
6
9
  import {
7
- BadResponseError,
8
10
  BASE_FEE,
9
11
  Horizon,
10
12
  MuxedAccount,
@@ -14,140 +16,73 @@ import {
14
16
  Transaction as StellarSdkTransaction,
15
17
  StrKey,
16
18
  xdr,
17
- } from "@stellar/stellar-sdk";
18
- import { BigNumber } from "bignumber.js";
19
- import coinConfig from "../config";
20
- import { patchHermesTypedArraysIfNeeded, unpatchHermesTypedArrays } from "../polyfill";
21
- import { StellarBroadcastFailedError, type StellarDecodedResultXdr } from "../types/errors";
19
+ } from '@stellar/stellar-sdk'
20
+ import { BigNumber } from 'bignumber.js'
21
+ import coinConfig from '../config'
22
+ import { parseAPIValue } from '../logic/common'
23
+ import { patchHermesTypedArraysIfNeeded, unpatchHermesTypedArrays } from '../polyfill'
22
24
  import {
23
25
  type BalanceAsset,
24
26
  type NetworkInfo,
25
27
  type RawOperation,
26
28
  type Signer,
27
29
  NetworkCongestionLevel,
28
- } from "../types";
29
- import { getReservedBalance, rawOperationsToOperations } from "./serialization";
30
- import { throwHorizonLedgerOrOperationsError } from "./horizonLedgerErrors";
31
- import { parseAPIValue } from "../logic/common";
32
-
33
- const FALLBACK_BASE_FEE = 100;
34
- const TRESHOLD_LOW = 0.5;
35
- const TRESHOLD_MEDIUM = 0.75;
36
- const FETCH_LIMIT = 100;
30
+ } from '../types'
31
+ import { StellarBroadcastFailedError, type StellarDecodedResultXdr } from '../types/errors'
32
+ import {
33
+ documentationSummaryFromHorizonBody,
34
+ getHorizonErrorBody,
35
+ type HorizonErrorBody,
36
+ } from './horizonErrorBody'
37
+ import { throwHorizonLedgerOrOperationsError } from './horizonLedgerErrors'
38
+ import { getReservedBalance, rawOperationsToOperations } from './serialization'
39
+
40
+ const FALLBACK_BASE_FEE = 100
41
+ const TRESHOLD_LOW = 0.5
42
+ const TRESHOLD_MEDIUM = 0.75
43
+ const FETCH_LIMIT = 100
37
44
 
38
45
  const STELLAR_TX_RESULT_CODES_DOC_URL =
39
- "https://developers.stellar.org/docs/data/apis/horizon/api-reference/errors/result-codes/transactions";
40
-
41
- /** Horizon `extras.result_codes.transaction` → one-line description (Stellar docs). */
42
- const HORIZON_TRANSACTION_RESULT_CODE_DOCUMENTATION: Record<string, string> = {
43
- tx_success: "The transaction succeeded.",
44
- tx_failed: "One of the operations failed (none were applied).",
45
- tx_too_early: "The ledger closeTime was before the minTime.",
46
- tx_too_late: "The ledger closeTime was after the maxTime.",
47
- tx_missing_operation: "No operation was specified.",
48
- tx_bad_seq: "Sequence number does not match source account.",
49
- tx_bad_auth: "Too few valid signatures / wrong network.",
50
- tx_insufficient_balance: "Fee would bring account below reserve.",
51
- tx_no_source_account: "Source account not found.",
52
- tx_insufficient_fee: "Fee is too small.",
53
- tx_bad_auth_extra: "Unused signatures attached to transaction.",
54
- tx_internal_error: "An unknown error occurred.",
55
- tx_fee_bump_inner_success: "Fee bump inner transaction succeeded.",
56
- tx_fee_bump_inner_failed: "Fee bump inner transaction failed.",
57
- tx_not_supported: "Transaction type not supported.",
58
- tx_bad_sponsorship: "Sponsorship is invalid.",
59
- tx_bad_min_seq_age_or_gap: "Minimum sequence age or gap precondition failed.",
60
- tx_malformed: "Transaction is malformed.",
61
- tx_soroban_invalid: "Soroban transaction is invalid.",
62
- };
63
-
64
- type HorizonSubmitErrorBody = {
65
- type?: string;
66
- title?: string;
67
- status?: number;
68
- detail?: string;
69
- extras?: {
70
- envelope_xdr?: string;
71
- result_xdr?: string;
72
- result_codes?: {
73
- transaction?: string;
74
- operations?: string[];
75
- };
76
- };
77
- };
78
-
79
- function isHorizonSubmitErrorBody(data: unknown): data is HorizonSubmitErrorBody {
80
- return !!(
81
- data &&
82
- typeof data === "object" &&
83
- "extras" in data &&
84
- typeof data.extras === "object" &&
85
- data.extras !== null &&
86
- "result_codes" in data.extras &&
87
- data.extras.result_codes !== undefined &&
88
- typeof data.extras.result_codes === "object"
89
- );
90
- }
91
-
92
- /**
93
- * Horizon submit failures are usually {@link BadResponseError} with `response` = problem+json body.
94
- * In practice axios rejects with `AxiosError` first; the SDK's `.catch` forwards it unchanged (see js-stellar-sdk horizon/server.js),
95
- * so the Horizon body lives on `error.response.data`.
96
- */
97
- function getHorizonBodyFromSubmitFailure(error: unknown): HorizonSubmitErrorBody | null {
98
- if (error instanceof BadResponseError && isHorizonSubmitErrorBody(error.response)) {
99
- return error.response;
100
- }
101
- if (error && typeof error === "object" && "response" in error) {
102
- const data = (error as { response?: { data?: unknown } }).response?.data;
103
- if (isHorizonSubmitErrorBody(data)) {
104
- return data;
105
- }
106
- }
107
- return null;
108
- }
46
+ 'https://developers.stellar.org/docs/data/apis/horizon/api-reference/errors/result-codes/transactions'
109
47
 
110
48
  function decodeTransactionResultFields(resultXdrBase64: string | undefined):
111
49
  | {
112
- feeChargedStroops?: string;
113
- resultXdrSwitchName?: string;
114
- decodedResultXdr: StellarDecodedResultXdr;
50
+ feeChargedStroops?: string
51
+ resultXdrSwitchName?: string
52
+ decodedResultXdr: StellarDecodedResultXdr
115
53
  }
116
54
  | undefined {
117
55
  if (!resultXdrBase64) {
118
- return undefined;
56
+ return undefined
119
57
  }
120
58
  try {
121
- const tr = xdr.TransactionResult.fromXDR(resultXdrBase64, "base64");
122
- const feeChargedStroops = tr.feeCharged().toString();
123
- const resultXdrSwitchName = tr.result().switch().name;
59
+ const tr = xdr.TransactionResult.fromXDR(resultXdrBase64, 'base64')
60
+ const feeChargedStroops = tr.feeCharged().toString()
61
+ const resultXdrSwitchName = tr.result().switch().name
124
62
  const decodedResultXdr: StellarDecodedResultXdr = {
125
63
  feeChargedStroops,
126
64
  resultSwitch: resultXdrSwitchName,
127
- };
128
- return { feeChargedStroops, resultXdrSwitchName, decodedResultXdr };
65
+ }
66
+ return { feeChargedStroops, resultXdrSwitchName, decodedResultXdr }
129
67
  } catch {
130
68
  return {
131
69
  decodedResultXdr: { decodeFailed: true, rawResultXdrBase64: resultXdrBase64 },
132
- };
70
+ }
133
71
  }
134
72
  }
135
73
 
136
- function makeBroadcastFailedError(body: HorizonSubmitErrorBody, cause: Error): Error {
137
- const extras = body.extras;
138
- const horizonTransactionCode = extras?.result_codes?.transaction ?? "";
139
- const horizonOperationCodes = extras?.result_codes?.operations;
140
- const documentationSummary =
141
- (horizonTransactionCode &&
142
- HORIZON_TRANSACTION_RESULT_CODE_DOCUMENTATION[horizonTransactionCode]) ||
143
- "Unknown transaction result code.";
144
- const decodedResult = decodeTransactionResultFields(extras?.result_xdr);
145
- const feeChargedStroops = decodedResult?.feeChargedStroops;
146
- const resultXdrSwitchName = decodedResult?.resultXdrSwitchName;
147
- const decodedResultXdr = decodedResult?.decodedResultXdr;
148
- const envelopeXdr = extras?.envelope_xdr ?? "";
74
+ function makeBroadcastFailedError(body: HorizonErrorBody, cause: Error): Error {
75
+ const extras = body.extras
76
+ const horizonTransactionCode = extras?.result_codes?.transaction ?? ''
77
+ const horizonOperationCodes = extras?.result_codes?.operations
78
+ const documentationSummary = documentationSummaryFromHorizonBody(body)
79
+ const decodedResult = decodeTransactionResultFields(extras?.result_xdr)
80
+ const feeChargedStroops = decodedResult?.feeChargedStroops
81
+ const resultXdrSwitchName = decodedResult?.resultXdrSwitchName
82
+ const decodedResultXdr = decodedResult?.decodedResultXdr
83
+ const envelopeXdr = extras?.envelope_xdr ?? ''
149
84
  const message =
150
- body.detail || body.title || `Transaction submission failed (${body.status ?? "unknown"}).`;
85
+ body.detail || body.title || `Transaction submission failed (${body.status ?? 'unknown'}).`
151
86
 
152
87
  return new StellarBroadcastFailedError(
153
88
  message,
@@ -161,28 +96,28 @@ function makeBroadcastFailedError(body: HorizonSubmitErrorBody, cause: Error): E
161
96
  decodedResultXdr,
162
97
  envelopeXdr,
163
98
  },
164
- { cause },
165
- );
99
+ { cause }
100
+ )
166
101
  }
167
102
 
168
103
  // Horizon client instance is cached to avoid costly rebuild at every request
169
104
  // Watch out: cache key is the URL, coin module can be instantiated several times with different URLs
170
- const servers = new Map<string, Horizon.Server>();
105
+ const servers = new Map<string, Horizon.Server>()
171
106
  function getServer(): Horizon.Server {
172
- const url = coinConfig.getCoinConfig().explorer.url;
173
- let server = servers.get(url);
107
+ const url = coinConfig.getCoinConfig().explorer.url
108
+ let server = servers.get(url)
174
109
  if (server === undefined) {
175
- server = new Horizon.Server(url);
176
- servers.set(url, server);
110
+ server = new Horizon.Server(url)
111
+ servers.set(url, server)
177
112
  }
178
- return server;
113
+ return server
179
114
  }
180
115
 
181
116
  // Tracks request start times for response-duration logging.
182
117
  // WeakMap avoids mutating the feaxios request config (whose type doesn't include `metadata`).
183
- const requestStartTimes = new WeakMap<object, number>();
118
+ const requestStartTimes = new WeakMap<object, number>()
184
119
 
185
- let interceptorsRegistered = false;
120
+ let interceptorsRegistered = false
186
121
 
187
122
  /**
188
123
  * Register logging and URL-fix interceptors on Horizon.AxiosClient.
@@ -193,83 +128,83 @@ let interceptorsRegistered = false;
193
128
  * InterceptorManager types rather than importing live-network's axios-typed interceptors.
194
129
  */
195
130
  export function registerHorizonInterceptors(): void {
196
- if (interceptorsRegistered) return;
197
- interceptorsRegistered = true;
131
+ if (interceptorsRegistered) return
132
+ interceptorsRegistered = true
198
133
 
199
- Horizon.AxiosClient.interceptors.request.use(config => {
200
- let enableNetworkLogs = false;
134
+ Horizon.AxiosClient.interceptors.request.use((config) => {
135
+ let enableNetworkLogs = false
201
136
  try {
202
- enableNetworkLogs = !!coinConfig.getCoinConfig().enableNetworkLogs;
137
+ enableNetworkLogs = !!coinConfig.getCoinConfig().enableNetworkLogs
203
138
  } catch {
204
- return config;
139
+ return config
205
140
  }
206
141
  if (enableNetworkLogs) {
207
- const { baseURL, url, method = "", data } = config;
208
- log("network", `${method} ${baseURL ?? ""}${url}`, { data });
209
- requestStartTimes.set(config, Date.now());
142
+ const { baseURL, url, method = '', data } = config
143
+ log('network', `${method} ${baseURL ?? ''}${url}`, { data })
144
+ requestStartTimes.set(config, Date.now())
210
145
  }
211
- return config;
212
- });
146
+ return config
147
+ })
213
148
 
214
- Horizon.AxiosClient.interceptors.response.use(response => {
215
- let enableNetworkLogs = false;
149
+ Horizon.AxiosClient.interceptors.response.use((response) => {
150
+ let enableNetworkLogs = false
216
151
  try {
217
- enableNetworkLogs = !!coinConfig.getCoinConfig().enableNetworkLogs;
152
+ enableNetworkLogs = !!coinConfig.getCoinConfig().enableNetworkLogs
218
153
  } catch {
219
154
  // coinConfig not initialised on this instance; skip logging and leave URLs untouched
220
155
  }
221
156
  if (enableNetworkLogs) {
222
157
  // response.config is typed as `any` in stellar-sdk's HttpClientResponse
223
- const startTime = requestStartTimes.get(response.config) ?? 0;
224
- requestStartTimes.delete(response.config);
158
+ const startTime = requestStartTimes.get(response.config) ?? 0
159
+ requestStartTimes.delete(response.config)
225
160
  log(
226
- "network-success",
227
- `${response.status} ${response.config?.method ?? ""} ${response.config?.baseURL ?? ""}${response.config?.url ?? ""} (${(Date.now() - startTime).toFixed(0)}ms)`,
228
- { data: response.data },
229
- );
161
+ 'network-success',
162
+ `${response.status} ${response.config?.method ?? ''} ${response.config?.baseURL ?? ''}${response.config?.url ?? ''} (${(Date.now() - startTime).toFixed(0)}ms)`,
163
+ { data: response.data }
164
+ )
230
165
  }
231
166
 
232
167
  // FIXME: workaround for the Stellar SDK not using the correct URL: the "next" URL
233
168
  // included in server responses points to the node itself instead of our reverse proxy...
234
169
  // (https://github.com/stellar/js-stellar-sdk/issues/637)
235
- const next_href = response?.data?._links?.next?.href;
170
+ const next_href = response?.data?._links?.next?.href
236
171
  if (next_href) {
237
- response.data._links.next.href = useConfigHostAndProtocol(next_href);
172
+ response.data._links.next.href = useConfigHostAndProtocol(next_href)
238
173
  }
239
174
  response?.data?._embedded?.records?.forEach((r: any) => {
240
- const href = r.transaction?._links?.ledger?.href;
241
- if (href) r.transaction._links.ledger.href = useConfigHostAndProtocol(href);
242
- });
175
+ const href = r.transaction?._links?.ledger?.href
176
+ if (href) r.transaction._links.ledger.href = useConfigHostAndProtocol(href)
177
+ })
243
178
 
244
- return response;
245
- });
179
+ return response
180
+ })
246
181
  }
247
182
 
248
183
  // It replaces the host and the protocol of the URL returned with the original ones.
249
184
  export function useConfigHostAndProtocol(url: string): string {
250
- const originalUrl = new URL(coinConfig.getCoinConfig().explorer.url);
185
+ const originalUrl = new URL(coinConfig.getCoinConfig().explorer.url)
251
186
  // URL.protocol setter silently fails when changing between special (https://) and
252
187
  // non-special (injected://) schemes, so reconstruct via string replacement instead.
253
- return url.replace(/^[^:]+:\/\/[^/]+/, `${originalUrl.protocol}//${originalUrl.host}`);
188
+ return url.replace(/^[^:]+:\/\/[^/]+/, `${originalUrl.protocol}//${originalUrl.host}`)
254
189
  }
255
190
 
256
191
  const getMinimumBalance = (account: Horizon.ServerApi.AccountRecord): BigNumber => {
257
- return parseAPIValue(getReservedBalance(account).toString());
258
- };
192
+ return parseAPIValue(getReservedBalance(account).toString())
193
+ }
259
194
 
260
195
  export async function getAccountSpendableBalance(
261
196
  balance: BigNumber,
262
- account: Horizon.ServerApi.AccountRecord,
197
+ account: Horizon.ServerApi.AccountRecord
263
198
  ): Promise<BigNumber> {
264
- const minimumBalance = getMinimumBalance(account);
265
- const { recommendedFee } = await fetchBaseFee();
266
- return BigNumber.max(balance.minus(minimumBalance).minus(recommendedFee), 0);
199
+ const minimumBalance = getMinimumBalance(account)
200
+ const { recommendedFee } = await fetchBaseFee()
201
+ return BigNumber.max(balance.minus(minimumBalance).minus(recommendedFee), 0)
267
202
  }
268
203
 
269
204
  export async function fetchBaseFee(): Promise<{
270
- baseFee: number;
271
- recommendedFee: number;
272
- networkCongestionLevel: NetworkCongestionLevel;
205
+ baseFee: number
206
+ recommendedFee: number
207
+ networkCongestionLevel: NetworkCongestionLevel
273
208
  }> {
274
209
  // For tests
275
210
  if (coinConfig.getCoinConfig().useStaticFees) {
@@ -277,27 +212,27 @@ export async function fetchBaseFee(): Promise<{
277
212
  baseFee: 100,
278
213
  recommendedFee: 100,
279
214
  networkCongestionLevel: NetworkCongestionLevel.LOW,
280
- };
215
+ }
281
216
  }
282
217
 
283
- const baseFee = new BigNumber(BASE_FEE).toNumber() || FALLBACK_BASE_FEE;
284
- let recommendedFee = baseFee;
285
- let networkCongestionLevel = NetworkCongestionLevel.MEDIUM;
218
+ const baseFee = new BigNumber(BASE_FEE).toNumber() || FALLBACK_BASE_FEE
219
+ let recommendedFee = baseFee
220
+ let networkCongestionLevel = NetworkCongestionLevel.MEDIUM
286
221
 
287
222
  try {
288
- const feeStats = await getServer().feeStats();
289
- const ledgerCapacityUsage = feeStats.ledger_capacity_usage;
290
- recommendedFee = new BigNumber(feeStats.fee_charged.mode).toNumber();
223
+ const feeStats = await getServer().feeStats()
224
+ const ledgerCapacityUsage = feeStats.ledger_capacity_usage
225
+ recommendedFee = new BigNumber(feeStats.fee_charged.mode).toNumber()
291
226
 
292
227
  if (
293
228
  new BigNumber(ledgerCapacityUsage).toNumber() > TRESHOLD_LOW &&
294
229
  new BigNumber(ledgerCapacityUsage).toNumber() <= TRESHOLD_MEDIUM
295
230
  ) {
296
- networkCongestionLevel = NetworkCongestionLevel.MEDIUM;
231
+ networkCongestionLevel = NetworkCongestionLevel.MEDIUM
297
232
  } else if (new BigNumber(ledgerCapacityUsage).toNumber() > TRESHOLD_MEDIUM) {
298
- networkCongestionLevel = NetworkCongestionLevel.HIGH;
233
+ networkCongestionLevel = NetworkCongestionLevel.HIGH
299
234
  } else {
300
- networkCongestionLevel = NetworkCongestionLevel.LOW;
235
+ networkCongestionLevel = NetworkCongestionLevel.LOW
301
236
  }
302
237
  } catch {
303
238
  // do nothing, will use defaults
@@ -307,7 +242,7 @@ export async function fetchBaseFee(): Promise<{
307
242
  baseFee,
308
243
  recommendedFee,
309
244
  networkCongestionLevel,
310
- };
245
+ }
311
246
  }
312
247
 
313
248
  /**
@@ -317,39 +252,39 @@ export async function fetchBaseFee(): Promise<{
317
252
  * @param {string} addr
318
253
  */
319
254
  export async function fetchAccount(addr: string): Promise<{
320
- blockHeight: number;
321
- balance: BigNumber;
322
- spendableBalance: BigNumber;
323
- assets: BalanceAsset[];
255
+ blockHeight: number
256
+ balance: BigNumber
257
+ spendableBalance: BigNumber
258
+ assets: BalanceAsset[]
324
259
  }> {
325
- let account: Horizon.ServerApi.AccountRecord = {} as Horizon.ServerApi.AccountRecord;
326
- let assets: BalanceAsset[] = [];
327
- let balance = "0";
260
+ let account: Horizon.ServerApi.AccountRecord = {} as Horizon.ServerApi.AccountRecord
261
+ let assets: BalanceAsset[] = []
262
+ let balance = '0'
328
263
 
329
264
  try {
330
- account = await getServer().accounts().accountId(addr).call();
265
+ account = await getServer().accounts().accountId(addr).call()
331
266
  balance =
332
- account.balances?.find(balance => {
333
- return balance.asset_type === "native";
334
- })?.balance || "0";
267
+ account.balances?.find((balance) => {
268
+ return balance.asset_type === 'native'
269
+ })?.balance || '0'
335
270
  // Getting all non-native (XLM) assets on the account
336
- assets = account.balances?.filter(balance => {
337
- return balance.asset_type !== "native";
338
- }) as BalanceAsset[];
271
+ assets = account.balances?.filter((balance) => {
272
+ return balance.asset_type !== 'native'
273
+ }) as BalanceAsset[]
339
274
  } catch {
340
- balance = "0";
275
+ balance = '0'
341
276
  }
342
277
 
343
- const formattedBalance = parseAPIValue(balance);
278
+ const formattedBalance = parseAPIValue(balance)
344
279
 
345
- const spendableBalance = await getAccountSpendableBalance(formattedBalance, account);
280
+ const spendableBalance = await getAccountSpendableBalance(formattedBalance, account)
346
281
 
347
282
  return {
348
283
  blockHeight: account.sequence ? new BigNumber(account.sequence).toNumber() : 0,
349
284
  balance: formattedBalance,
350
285
  spendableBalance,
351
286
  assets,
352
- };
287
+ }
353
288
  }
354
289
 
355
290
  /**
@@ -366,17 +301,17 @@ export async function fetchAccount(addr: string): Promise<{
366
301
  export async function fetchAllOperations(
367
302
  accountId: string,
368
303
  addr: string,
369
- order: "asc" | "desc",
370
- cursor: string = "",
371
- maxOperations?: number,
304
+ order: 'asc' | 'desc',
305
+ cursor: string = '',
306
+ maxOperations?: number
372
307
  ): Promise<Operation[]> {
373
308
  if (!addr) {
374
- return [];
309
+ return []
375
310
  }
376
311
 
377
- const limit = coinConfig.getCoinConfig().explorer.fetchLimit ?? FETCH_LIMIT;
378
- let operations: Operation[] = [];
379
- let fetchedOpsCount = limit;
312
+ const limit = coinConfig.getCoinConfig().explorer.fetchLimit ?? FETCH_LIMIT
313
+ let operations: Operation[] = []
314
+ let fetchedOpsCount = limit
380
315
 
381
316
  try {
382
317
  let rawOperations = await getServer()
@@ -386,50 +321,45 @@ export async function fetchAllOperations(
386
321
  .order(order)
387
322
  .cursor(cursor)
388
323
  .includeFailed(true)
389
- .join("transactions")
390
- .call();
324
+ .join('transactions')
325
+ .call()
391
326
 
392
327
  if (!rawOperations || !rawOperations.records.length) {
393
- return [];
328
+ return []
394
329
  }
395
330
 
396
331
  operations = operations.concat(
397
- await rawOperationsToOperations(rawOperations.records as RawOperation[], addr, accountId, 0),
398
- );
332
+ await rawOperationsToOperations(rawOperations.records as RawOperation[], addr, accountId, 0)
333
+ )
399
334
 
400
335
  while (rawOperations.records.length > 0) {
401
336
  if (maxOperations && fetchedOpsCount >= maxOperations) {
402
- break;
337
+ break
403
338
  }
404
- fetchedOpsCount += limit;
339
+ fetchedOpsCount += limit
405
340
 
406
- rawOperations = await rawOperations.next();
341
+ rawOperations = await rawOperations.next()
407
342
  operations = operations.concat(
408
- await rawOperationsToOperations(
409
- rawOperations.records as RawOperation[],
410
- addr,
411
- accountId,
412
- 0,
413
- ),
414
- );
343
+ await rawOperationsToOperations(rawOperations.records as RawOperation[], addr, accountId, 0)
344
+ )
415
345
  }
416
346
 
417
- return operations;
347
+ return operations
418
348
  } catch (e: unknown) {
419
349
  // FIXME: terrible hacks, because Stellar SDK fails to cast network failures to typed errors in react-native...
420
350
  // (https://github.com/stellar/js-stellar-sdk/issues/638)
421
- const errorMsg = e ? String(e) : "";
351
+ const errorMsg = e ? String(e) : ''
422
352
 
423
353
  if (e instanceof NotFoundError || errorMsg.match(/status code 404/)) {
424
- return [];
354
+ return []
425
355
  }
426
356
 
427
357
  if (errorMsg.match(/status code 4[0-9]{2}/)) {
428
- throw new LedgerAPI4xx();
358
+ throw new LedgerAPI4xx()
429
359
  }
430
360
 
431
361
  if (errorMsg.match(/status code 5[0-9]{2}/)) {
432
- throw new LedgerAPI5xx();
362
+ throw new LedgerAPI5xx()
433
363
  }
434
364
 
435
365
  if (
@@ -437,10 +367,10 @@ export async function fetchAllOperations(
437
367
  errorMsg.match(/ECONNRESET|ECONNREFUSED|ENOTFOUND|EPIPE|ETIMEDOUT/) ||
438
368
  errorMsg.match(/undefined is not an object/)
439
369
  ) {
440
- throw new NetworkDown();
370
+ throw new NetworkDown()
441
371
  }
442
372
 
443
- throw e;
373
+ throw e
444
374
  }
445
375
  }
446
376
 
@@ -453,19 +383,19 @@ export async function fetchOperations({
453
383
  cursor,
454
384
  limit,
455
385
  }: {
456
- accountId: string;
457
- addr: string;
458
- minHeight: number;
459
- order: "asc" | "desc";
460
- cursor: string | undefined;
461
- limit?: number | undefined;
386
+ accountId: string
387
+ addr: string
388
+ minHeight: number
389
+ order: 'asc' | 'desc'
390
+ cursor: string | undefined
391
+ limit?: number | undefined
462
392
  }): Promise<Page<Operation>> {
463
- const noResult: Page<Operation> = { items: [], next: "" };
393
+ const noResult: Page<Operation> = { items: [], next: '' }
464
394
  if (!addr) {
465
- return noResult;
395
+ return noResult
466
396
  }
467
397
 
468
- const requestedLimit = limit ?? coinConfig.getCoinConfig().explorer.fetchLimit ?? FETCH_LIMIT;
398
+ const requestedLimit = limit ?? coinConfig.getCoinConfig().explorer.fetchLimit ?? FETCH_LIMIT
469
399
 
470
400
  try {
471
401
  const rawOperations = await getServer()
@@ -473,41 +403,41 @@ export async function fetchOperations({
473
403
  .forAccount(addr)
474
404
  .limit(requestedLimit)
475
405
  .order(order)
476
- .cursor(cursor ?? "")
406
+ .cursor(cursor ?? '')
477
407
  .includeFailed(true)
478
- .join("transactions")
479
- .call();
408
+ .join('transactions')
409
+ .call()
480
410
 
481
411
  if (!rawOperations || !rawOperations.records.length) {
482
- return noResult;
412
+ return noResult
483
413
  }
484
414
 
485
- const rawOps = rawOperations.records as RawOperation[];
486
- const filteredOps = await rawOperationsToOperations(rawOps, addr, accountId, minHeight);
415
+ const rawOps = rawOperations.records as RawOperation[]
416
+ const filteredOps = await rawOperationsToOperations(rawOps, addr, accountId, minHeight)
487
417
 
488
418
  // Always return the cursor so the caller can continue pagination,
489
419
  // even when filteredOps is empty (e.g. page of unsupported types).
490
- const nextCursor = rawOps.length < requestedLimit ? "" : rawOps[rawOps.length - 1].paging_token;
420
+ const nextCursor = rawOps.length < requestedLimit ? '' : rawOps[rawOps.length - 1].paging_token
491
421
 
492
- return { items: filteredOps, next: nextCursor };
422
+ return { items: filteredOps, next: nextCursor }
493
423
  } catch (e: unknown) {
494
424
  // FIXME: terrible hacks, because Stellar SDK fails to cast network failures to typed errors in react-native...
495
425
  // (https://github.com/stellar/js-stellar-sdk/issues/638)
496
426
  // update 2025-04-01: in case of NetworkError, the error.response fields are undefined. Hence we cannot rely on status code
497
427
  // the only way to check is the errror message, which may break at some point
498
- const errorMsg = e ? String(e) : "";
428
+ const errorMsg = e ? String(e) : ''
499
429
 
500
430
  if (e instanceof NotFoundError || errorMsg.match(/status code 404/)) {
501
- return noResult;
431
+ return noResult
502
432
  }
503
433
  if (errorMsg.match(/too many requests/i)) {
504
- throw new LedgerAPI4xx("status code 4xx", { status: 429, url: undefined, method: "GET" });
434
+ throw new LedgerAPI4xx('status code 4xx', { status: 429, url: undefined, method: 'GET' })
505
435
  }
506
436
  if (errorMsg.match(/status code 4[0-9]{2}/)) {
507
- throw new LedgerAPI4xx();
437
+ throw new LedgerAPI4xx()
508
438
  }
509
439
  if (errorMsg.match(/status code 5[0-9]{2}/)) {
510
- throw new LedgerAPI5xx();
440
+ throw new LedgerAPI5xx()
511
441
  }
512
442
 
513
443
  if (
@@ -515,101 +445,101 @@ export async function fetchOperations({
515
445
  errorMsg.match(/ECONNRESET|ECONNREFUSED|ENOTFOUND|EPIPE|ETIMEDOUT/) ||
516
446
  errorMsg.match(/undefined is not an object/)
517
447
  ) {
518
- throw new NetworkDown();
448
+ throw new NetworkDown()
519
449
  }
520
450
 
521
- throw e;
451
+ throw e
522
452
  }
523
453
  }
524
454
 
525
455
  export async function fetchAccountNetworkInfo(account: string): Promise<NetworkInfo> {
526
456
  try {
527
- const extendedAccount = await getServer().accounts().accountId(account).call();
528
- const baseReserve = getReservedBalance(extendedAccount);
529
- const { recommendedFee, networkCongestionLevel, baseFee } = await fetchBaseFee();
457
+ const extendedAccount = await getServer().accounts().accountId(account).call()
458
+ const baseReserve = getReservedBalance(extendedAccount)
459
+ const { recommendedFee, networkCongestionLevel, baseFee } = await fetchBaseFee()
530
460
 
531
461
  return {
532
- family: "stellar",
462
+ family: 'stellar',
533
463
  fees: new BigNumber(recommendedFee.toString()),
534
464
  baseFee: new BigNumber(baseFee.toString()),
535
465
  baseReserve,
536
466
  networkCongestionLevel,
537
- };
467
+ }
538
468
  } catch {
539
469
  return {
540
- family: "stellar",
470
+ family: 'stellar',
541
471
  fees: new BigNumber(0),
542
472
  baseFee: new BigNumber(100),
543
473
  baseReserve: new BigNumber(0),
544
- };
474
+ }
545
475
  }
546
476
  }
547
477
 
548
478
  export async function fetchSequence(address: string): Promise<BigNumber> {
549
- const extendedAccount = await loadAccount(address);
550
- return extendedAccount ? new BigNumber(extendedAccount.sequence) : new BigNumber(0);
479
+ const extendedAccount = await loadAccount(address)
480
+ return extendedAccount ? new BigNumber(extendedAccount.sequence) : new BigNumber(0)
551
481
  }
552
482
 
553
483
  export async function fetchSigners(account: string): Promise<Signer[]> {
554
484
  try {
555
- const extendedAccount = await getServer().accounts().accountId(account).call();
556
- return extendedAccount.signers;
485
+ const extendedAccount = await getServer().accounts().accountId(account).call()
486
+ return extendedAccount.signers
557
487
  } catch {
558
- return [];
488
+ return []
559
489
  }
560
490
  }
561
491
 
562
492
  function interpretedError(error: unknown): unknown {
563
- const body = getHorizonBodyFromSubmitFailure(error);
493
+ const body = getHorizonErrorBody(error)
564
494
  if (body) {
565
- const cause = error instanceof Error ? error : new Error(String(error));
566
- return makeBroadcastFailedError(body, cause);
495
+ const cause = error instanceof Error ? error : new Error(String(error))
496
+ return makeBroadcastFailedError(body, cause)
567
497
  }
568
- return error;
498
+ return error
569
499
  }
570
500
 
571
501
  export async function broadcastTransaction(signedTransaction: string): Promise<string> {
572
502
  try {
573
- patchHermesTypedArraysIfNeeded();
574
- const transaction = new StellarSdkTransaction(signedTransaction, Networks.PUBLIC);
503
+ patchHermesTypedArraysIfNeeded()
504
+ const transaction = new StellarSdkTransaction(signedTransaction, Networks.PUBLIC)
575
505
 
576
506
  try {
577
507
  const res = await getServer().submitTransaction(transaction, {
578
508
  skipMemoRequiredCheck: true,
579
- });
580
- return res.hash;
509
+ })
510
+ return res.hash
581
511
  } catch (error: unknown) {
582
- throw interpretedError(error);
512
+ throw interpretedError(error)
583
513
  }
584
514
  } finally {
585
515
  // Restore
586
- unpatchHermesTypedArrays();
516
+ unpatchHermesTypedArrays()
587
517
  }
588
518
  }
589
519
 
590
520
  export async function loadAccount(addr: string): Promise<Horizon.AccountResponse | null> {
591
521
  if (!addr || !addr.length) {
592
- return null;
522
+ return null
593
523
  }
594
524
 
595
525
  try {
596
- return await getServer().loadAccount(addr);
526
+ return await getServer().loadAccount(addr)
597
527
  } catch {
598
- return null;
528
+ return null
599
529
  }
600
530
  }
601
531
 
602
532
  export async function getLastBlock(): Promise<{
603
- height: number;
604
- hash: string;
605
- time: Date;
533
+ height: number
534
+ hash: string
535
+ time: Date
606
536
  }> {
607
- const ledger = await getServer().ledgers().order("desc").limit(1).call();
537
+ const ledger = await getServer().ledgers().order('desc').limit(1).call()
608
538
  return {
609
539
  height: ledger.records[0].sequence,
610
540
  hash: ledger.records[0].hash,
611
541
  time: new Date(ledger.records[0].closed_at),
612
- };
542
+ }
613
543
  }
614
544
 
615
545
  /**
@@ -622,11 +552,11 @@ export async function getLastBlock(): Promise<{
622
552
  */
623
553
  export async function fetchLedgerRecord(sequence: number): Promise<Horizon.ServerApi.LedgerRecord> {
624
554
  try {
625
- const record = await getServer().ledgers().ledger(sequence).call();
555
+ const record = await getServer().ledgers().ledger(sequence).call()
626
556
  // Horizon returns a single ledger; SDK typings still use CollectionPage for this builder.
627
- return record as unknown as Horizon.ServerApi.LedgerRecord;
557
+ return record as unknown as Horizon.ServerApi.LedgerRecord
628
558
  } catch (e: unknown) {
629
- throwHorizonLedgerOrOperationsError(e, `Stellar ledger ${sequence} not found`);
559
+ throwHorizonLedgerOrOperationsError(e, `Stellar ledger ${sequence} not found`)
630
560
  }
631
561
  }
632
562
 
@@ -637,95 +567,95 @@ export async function fetchLedgerRecord(sequence: number): Promise<Horizon.Serve
637
567
  * @throws Error when the ledger does not exist (Horizon 404).
638
568
  */
639
569
  export async function fetchAllLedgerOperations(ledgerSequence: number): Promise<RawOperation[]> {
640
- const limit = coinConfig.getCoinConfig().explorer.fetchLimit ?? FETCH_LIMIT;
570
+ const limit = coinConfig.getCoinConfig().explorer.fetchLimit ?? FETCH_LIMIT
641
571
 
642
572
  try {
643
573
  let response = await getServer()
644
574
  .operations()
645
575
  .forLedger(ledgerSequence)
646
576
  .includeFailed(true)
647
- .join("transactions")
648
- .order("asc")
577
+ .join('transactions')
578
+ .order('asc')
649
579
  .limit(limit)
650
- .call();
580
+ .call()
651
581
 
652
- const records: RawOperation[] = [...(response.records as RawOperation[])];
582
+ const records: RawOperation[] = [...(response.records as RawOperation[])]
653
583
 
654
584
  while (response.records.length === limit) {
655
- response = await response.next();
656
- records.push(...(response.records as RawOperation[]));
585
+ response = await response.next()
586
+ records.push(...(response.records as RawOperation[]))
657
587
  if (response.records.length === 0) {
658
- break;
588
+ break
659
589
  }
660
590
  }
661
591
 
662
- return records;
592
+ return records
663
593
  } catch (e: unknown) {
664
- throwHorizonLedgerOrOperationsError(e, `Stellar ledger ${ledgerSequence} not found`);
594
+ throwHorizonLedgerOrOperationsError(e, `Stellar ledger ${ledgerSequence} not found`)
665
595
  }
666
596
  }
667
597
 
668
598
  export const getRecipientAccount: CacheRes<
669
599
  Array<{
670
- recipient: string;
600
+ recipient: string
671
601
  }>,
672
602
  {
673
- id: string | null;
674
- isMuxedAccount: boolean;
675
- assetIds: string[];
603
+ id: string | null
604
+ isMuxedAccount: boolean
605
+ assetIds: string[]
676
606
  } | null
677
607
  > = makeLRUCache(
678
608
  async ({ recipient }) => await recipientAccount(recipient),
679
- extract => extract.recipient,
609
+ (extract) => extract.recipient,
680
610
  {
681
611
  max: 300,
682
612
  ttl: 5 * 60,
683
- }, // 5 minutes
684
- );
613
+ } // 5 minutes
614
+ )
685
615
 
686
616
  async function recipientAccount(address?: string): Promise<{
687
- id: string | null;
688
- isMuxedAccount: boolean;
689
- assetIds: string[];
617
+ id: string | null
618
+ isMuxedAccount: boolean
619
+ assetIds: string[]
690
620
  } | null> {
691
621
  if (!address) {
692
- return null;
622
+ return null
693
623
  }
694
624
 
695
- let accountAddress = address;
625
+ let accountAddress = address
696
626
 
697
- const isMuxedAccount = StrKey.isValidMed25519PublicKey(address);
627
+ const isMuxedAccount = StrKey.isValidMed25519PublicKey(address)
698
628
 
699
629
  if (isMuxedAccount) {
700
- const muxedAccount = MuxedAccount.fromAddress(address, "0");
701
- accountAddress = muxedAccount.baseAccount().accountId();
630
+ const muxedAccount = MuxedAccount.fromAddress(address, '0')
631
+ accountAddress = muxedAccount.baseAccount().accountId()
702
632
  }
703
633
 
704
- const account: Horizon.AccountResponse | null = await loadAccount(accountAddress);
634
+ const account: Horizon.AccountResponse | null = await loadAccount(accountAddress)
705
635
 
706
636
  if (!account) {
707
- return null;
637
+ return null
708
638
  }
709
639
 
710
640
  return {
711
641
  id: account.id,
712
642
  isMuxedAccount,
713
643
  assetIds: account.balances.reduce((allAssets: any[], balance: any) => {
714
- return [...allAssets, getBalanceId(balance)];
644
+ return [...allAssets, getBalanceId(balance)]
715
645
  }, []),
716
- };
646
+ }
717
647
  }
718
648
 
719
649
  function getBalanceId(balance: BalanceAsset): string | null {
720
650
  switch (balance.asset_type) {
721
- case "native":
722
- return "native";
723
- case "liquidity_pool_shares":
724
- return balance.liquidity_pool_id || null;
725
- case "credit_alphanum4":
726
- case "credit_alphanum12":
727
- return `${balance.asset_code}:${balance.asset_issuer}`;
651
+ case 'native':
652
+ return 'native'
653
+ case 'liquidity_pool_shares':
654
+ return balance.liquidity_pool_id || null
655
+ case 'credit_alphanum4':
656
+ case 'credit_alphanum12':
657
+ return `${balance.asset_code}:${balance.asset_issuer}`
728
658
  default:
729
- return null;
659
+ return null
730
660
  }
731
661
  }