upshift-finance 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (316) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +349 -0
  3. package/lib/abis/AddressResolver.d.ts +28 -0
  4. package/lib/abis/AddressResolver.js +23 -0
  5. package/lib/abis/ChainlinkV3.d.ts +87 -0
  6. package/lib/abis/ChainlinkV3.js +117 -0
  7. package/lib/abis/ERC20.d.ts +168 -0
  8. package/lib/abis/ERC20.js +226 -0
  9. package/lib/abis/ERC20_Bytes32.d.ts +139 -0
  10. package/lib/abis/ERC20_Bytes32.js +196 -0
  11. package/lib/abis/ERC4626.d.ts +364 -0
  12. package/lib/abis/ERC4626.js +507 -0
  13. package/lib/abis/ERC721.d.ts +231 -0
  14. package/lib/abis/ERC721.js +321 -0
  15. package/lib/abis/FeeOracle.d.ts +120 -0
  16. package/lib/abis/FeeOracle.js +162 -0
  17. package/lib/abis/LendingPool.d.ts +1393 -0
  18. package/lib/abis/LendingPool.js +1807 -0
  19. package/lib/abis/LendingPoolV2.d.ts +1413 -0
  20. package/lib/abis/LendingPoolV2.js +1833 -0
  21. package/lib/abis/LendingPoolV3.d.ts +1677 -0
  22. package/lib/abis/LendingPoolV3.js +1160 -0
  23. package/lib/abis/Loan.d.ts +837 -0
  24. package/lib/abis/Loan.js +1080 -0
  25. package/lib/abis/MultiAssetNativeDepositWrapper.d.ts +137 -0
  26. package/lib/abis/MultiAssetNativeDepositWrapper.js +125 -0
  27. package/lib/abis/Multicall3.d.ts +30 -0
  28. package/lib/abis/Multicall3.js +97 -0
  29. package/lib/abis/OFT.d.ts +116 -0
  30. package/lib/abis/OFT.js +85 -0
  31. package/lib/abis/PoolAdapter.d.ts +36 -0
  32. package/lib/abis/PoolAdapter.js +51 -0
  33. package/lib/abis/RewardDistributor.d.ts +267 -0
  34. package/lib/abis/RewardDistributor.js +352 -0
  35. package/lib/abis/RwaRedeemSubaccount.d.ts +747 -0
  36. package/lib/abis/RwaRedeemSubaccount.js +548 -0
  37. package/lib/abis/SmartAccount.d.ts +17 -0
  38. package/lib/abis/SmartAccount.js +19 -0
  39. package/lib/abis/SwapRouter.d.ts +1043 -0
  40. package/lib/abis/SwapRouter.js +740 -0
  41. package/lib/abis/TextResolver.d.ts +16 -0
  42. package/lib/abis/TextResolver.js +16 -0
  43. package/lib/abis/TokenizedVaultV2.d.ts +1364 -0
  44. package/lib/abis/TokenizedVaultV2.js +1041 -0
  45. package/lib/abis/TokenizedVaultV2DepositWithPermit.d.ts +1456 -0
  46. package/lib/abis/TokenizedVaultV2DepositWithPermit.js +1878 -0
  47. package/lib/abis/TokenizedVaultV2Receipt.d.ts +1568 -0
  48. package/lib/abis/TokenizedVaultV2Receipt.js +1061 -0
  49. package/lib/abis/TokenizedVaultV2SenderAllocationWhitelist.d.ts +454 -0
  50. package/lib/abis/TokenizedVaultV2SenderAllocationWhitelist.js +327 -0
  51. package/lib/abis/TokenizedVaultV2WhitelistedAllocation.d.ts +1466 -0
  52. package/lib/abis/TokenizedVaultV2WhitelistedAllocation.js +1092 -0
  53. package/lib/abis/TokenizedVaultV2WhitelistedAssets.d.ts +274 -0
  54. package/lib/abis/TokenizedVaultV2WhitelistedAssets.js +167 -0
  55. package/lib/abis/UniversalResolverResolve.d.ts +69 -0
  56. package/lib/abis/UniversalResolverResolve.js +35 -0
  57. package/lib/abis/UniversalSignatureValidator.d.ts +17 -0
  58. package/lib/abis/UniversalSignatureValidator.js +30 -0
  59. package/lib/abis/WrapperAdapter.d.ts +71 -0
  60. package/lib/abis/WrapperAdapter.js +77 -0
  61. package/lib/abis/index.d.ts +34 -0
  62. package/lib/abis/index.js +51 -0
  63. package/lib/adapters/evm/getters.d.ts +19 -0
  64. package/lib/adapters/evm/getters.js +209 -0
  65. package/lib/adapters/evm/index.d.ts +353 -0
  66. package/lib/adapters/evm/index.js +434 -0
  67. package/lib/adapters/evm/utils.d.ts +8 -0
  68. package/lib/adapters/evm/utils.js +51 -0
  69. package/lib/adapters/solana/constants.d.ts +33 -0
  70. package/lib/adapters/solana/constants.js +52 -0
  71. package/lib/adapters/solana/getters.d.ts +11 -0
  72. package/lib/adapters/solana/getters.js +165 -0
  73. package/lib/adapters/solana/idl/vault-idl.d.ts +272 -0
  74. package/lib/adapters/solana/idl/vault-idl.js +1084 -0
  75. package/lib/adapters/solana/index.d.ts +233 -0
  76. package/lib/adapters/solana/index.js +291 -0
  77. package/lib/adapters/solana/types.d.ts +67 -0
  78. package/lib/adapters/solana/types.js +3 -0
  79. package/lib/adapters/solana/utils.d.ts +141 -0
  80. package/lib/adapters/solana/utils.js +595 -0
  81. package/lib/adapters/solana/vault.actions.d.ts +57 -0
  82. package/lib/adapters/solana/vault.actions.js +379 -0
  83. package/lib/adapters/stellar/actions.d.ts +28 -0
  84. package/lib/adapters/stellar/actions.js +77 -0
  85. package/lib/adapters/stellar/constants.d.ts +43 -0
  86. package/lib/adapters/stellar/constants.js +53 -0
  87. package/lib/adapters/stellar/getters.d.ts +68 -0
  88. package/lib/adapters/stellar/getters.js +290 -0
  89. package/lib/adapters/stellar/index.d.ts +114 -0
  90. package/lib/adapters/stellar/index.js +175 -0
  91. package/lib/adapters/stellar/soroban.d.ts +123 -0
  92. package/lib/adapters/stellar/soroban.js +613 -0
  93. package/lib/adapters/stellar/submit.d.ts +34 -0
  94. package/lib/adapters/stellar/submit.js +149 -0
  95. package/lib/adapters/stellar/types.d.ts +58 -0
  96. package/lib/adapters/stellar/types.js +6 -0
  97. package/lib/adapters/stellar/utils.d.ts +24 -0
  98. package/lib/adapters/stellar/utils.js +34 -0
  99. package/lib/adapters/sui/constants.d.ts +14 -0
  100. package/lib/adapters/sui/constants.js +29 -0
  101. package/lib/adapters/sui/getters.d.ts +9 -0
  102. package/lib/adapters/sui/getters.js +60 -0
  103. package/lib/adapters/sui/index.d.ts +45 -0
  104. package/lib/adapters/sui/index.js +101 -0
  105. package/lib/adapters/sui/transformer.d.ts +10 -0
  106. package/lib/adapters/sui/transformer.js +107 -0
  107. package/lib/adapters/sui/types.d.ts +66 -0
  108. package/lib/adapters/sui/types.js +3 -0
  109. package/lib/adapters/sui/utils.d.ts +10 -0
  110. package/lib/adapters/sui/utils.js +29 -0
  111. package/lib/core/analytics/chain-name.d.ts +9 -0
  112. package/lib/core/analytics/chain-name.js +34 -0
  113. package/lib/core/analytics/constants.d.ts +5 -0
  114. package/lib/core/analytics/constants.js +9 -0
  115. package/lib/core/analytics/env.d.ts +29 -0
  116. package/lib/core/analytics/env.js +59 -0
  117. package/lib/core/analytics/index.d.ts +36 -0
  118. package/lib/core/analytics/index.js +79 -0
  119. package/lib/core/analytics/instrumentation.d.ts +29 -0
  120. package/lib/core/analytics/instrumentation.js +277 -0
  121. package/lib/core/analytics/method-taxonomy.d.ts +19 -0
  122. package/lib/core/analytics/method-taxonomy.js +128 -0
  123. package/lib/core/analytics/metrics.d.ts +33 -0
  124. package/lib/core/analytics/metrics.js +116 -0
  125. package/lib/core/analytics/sanitize.d.ts +44 -0
  126. package/lib/core/analytics/sanitize.js +260 -0
  127. package/lib/core/analytics/sentry-runtime.d.ts +15 -0
  128. package/lib/core/analytics/sentry-runtime.js +97 -0
  129. package/lib/core/analytics/sentry.d.ts +67 -0
  130. package/lib/core/analytics/sentry.js +613 -0
  131. package/lib/core/analytics/types.d.ts +48 -0
  132. package/lib/core/analytics/types.js +3 -0
  133. package/lib/core/analytics/user-identity.d.ts +41 -0
  134. package/lib/core/analytics/user-identity.js +141 -0
  135. package/lib/core/analytics/version.d.ts +6 -0
  136. package/lib/core/analytics/version.js +10 -0
  137. package/lib/core/attribution.d.ts +111 -0
  138. package/lib/core/attribution.js +142 -0
  139. package/lib/core/auth/index.d.ts +1 -0
  140. package/lib/core/auth/index.js +18 -0
  141. package/lib/core/auth/verify.d.ts +2 -0
  142. package/lib/core/auth/verify.js +31 -0
  143. package/lib/core/base.class.d.ts +152 -0
  144. package/lib/core/base.class.js +172 -0
  145. package/lib/core/cache.d.ts +9 -0
  146. package/lib/core/cache.js +31 -0
  147. package/lib/core/constants/adapters.d.ts +103 -0
  148. package/lib/core/constants/adapters.js +180 -0
  149. package/lib/core/constants/core.d.ts +133 -0
  150. package/lib/core/constants/core.js +209 -0
  151. package/lib/core/constants/swap-router.d.ts +150 -0
  152. package/lib/core/constants/swap-router.js +169 -0
  153. package/lib/core/constants/vaults.d.ts +93 -0
  154. package/lib/core/constants/vaults.js +273 -0
  155. package/lib/core/constants/web3.d.ts +91 -0
  156. package/lib/core/constants/web3.js +229 -0
  157. package/lib/core/errors/index.d.ts +114 -0
  158. package/lib/core/errors/index.js +183 -0
  159. package/lib/core/fetcher.d.ts +198 -0
  160. package/lib/core/fetcher.js +903 -0
  161. package/lib/core/helpers/adapters.d.ts +13 -0
  162. package/lib/core/helpers/adapters.js +39 -0
  163. package/lib/core/helpers/chain-address.d.ts +13 -0
  164. package/lib/core/helpers/chain-address.js +47 -0
  165. package/lib/core/helpers/chain-error.d.ts +207 -0
  166. package/lib/core/helpers/chain-error.js +682 -0
  167. package/lib/core/helpers/chain-support.d.ts +80 -0
  168. package/lib/core/helpers/chain-support.js +115 -0
  169. package/lib/core/helpers/core.d.ts +68 -0
  170. package/lib/core/helpers/core.js +285 -0
  171. package/lib/core/helpers/explorer-link.d.ts +16 -0
  172. package/lib/core/helpers/explorer-link.js +26 -0
  173. package/lib/core/helpers/multicall.d.ts +68 -0
  174. package/lib/core/helpers/multicall.js +103 -0
  175. package/lib/core/helpers/revert-decode.d.ts +248 -0
  176. package/lib/core/helpers/revert-decode.js +515 -0
  177. package/lib/core/helpers/signer.d.ts +52 -0
  178. package/lib/core/helpers/signer.js +145 -0
  179. package/lib/core/helpers/swap-router.d.ts +211 -0
  180. package/lib/core/helpers/swap-router.js +480 -0
  181. package/lib/core/helpers/vault-version.d.ts +23 -0
  182. package/lib/core/helpers/vault-version.js +75 -0
  183. package/lib/core/helpers/vaults.d.ts +89 -0
  184. package/lib/core/helpers/vaults.js +235 -0
  185. package/lib/core/helpers/web3.d.ts +353 -0
  186. package/lib/core/helpers/web3.js +992 -0
  187. package/lib/core/index.d.ts +23 -0
  188. package/lib/core/index.js +40 -0
  189. package/lib/core/logger/index.d.ts +98 -0
  190. package/lib/core/logger/index.js +144 -0
  191. package/lib/core/logger/slack.d.ts +16 -0
  192. package/lib/core/logger/slack.js +57 -0
  193. package/lib/core/vault-metadata.d.ts +12 -0
  194. package/lib/core/vault-metadata.js +42 -0
  195. package/lib/core/version-check.d.ts +58 -0
  196. package/lib/core/version-check.js +182 -0
  197. package/lib/evm/index.d.ts +2 -0
  198. package/lib/evm/index.js +19 -0
  199. package/lib/evm/methods/crossChainVault.d.ts +128 -0
  200. package/lib/evm/methods/crossChainVault.js +853 -0
  201. package/lib/evm/methods/crossChainVaultRegistry.d.ts +93 -0
  202. package/lib/evm/methods/crossChainVaultRegistry.js +240 -0
  203. package/lib/evm/methods/index.d.ts +2 -0
  204. package/lib/evm/methods/index.js +19 -0
  205. package/lib/evm/types/crossChain.d.ts +363 -0
  206. package/lib/evm/types/crossChain.js +20 -0
  207. package/lib/evm/types/index.d.ts +1 -0
  208. package/lib/evm/types/index.js +18 -0
  209. package/lib/index.d.ts +30 -0
  210. package/lib/index.js +52 -0
  211. package/lib/main.d.ts +527 -0
  212. package/lib/main.js +601 -0
  213. package/lib/modules/api/fetcher.d.ts +82 -0
  214. package/lib/modules/api/fetcher.js +150 -0
  215. package/lib/modules/api/index.d.ts +1 -0
  216. package/lib/modules/api/index.js +6 -0
  217. package/lib/modules/api/main.d.ts +313 -0
  218. package/lib/modules/api/main.js +479 -0
  219. package/lib/modules/sub-accounts/fetcher.d.ts +53 -0
  220. package/lib/modules/sub-accounts/fetcher.js +120 -0
  221. package/lib/modules/sub-accounts/index.d.ts +2 -0
  222. package/lib/modules/sub-accounts/index.js +19 -0
  223. package/lib/modules/sub-accounts/main.d.ts +243 -0
  224. package/lib/modules/sub-accounts/main.js +205 -0
  225. package/lib/modules/sub-accounts/utils.d.ts +106 -0
  226. package/lib/modules/sub-accounts/utils.js +112 -0
  227. package/lib/modules/vaults/adapter.helpers.d.ts +64 -0
  228. package/lib/modules/vaults/adapter.helpers.js +184 -0
  229. package/lib/modules/vaults/fetcher.d.ts +147 -0
  230. package/lib/modules/vaults/fetcher.js +368 -0
  231. package/lib/modules/vaults/getters.d.ts +570 -0
  232. package/lib/modules/vaults/getters.js +3051 -0
  233. package/lib/modules/vaults/index.d.ts +20 -0
  234. package/lib/modules/vaults/index.js +44 -0
  235. package/lib/modules/vaults/main.d.ts +601 -0
  236. package/lib/modules/vaults/main.js +1623 -0
  237. package/lib/modules/vaults/prefetch.d.ts +65 -0
  238. package/lib/modules/vaults/prefetch.js +120 -0
  239. package/lib/modules/vaults/read.actions.d.ts +225 -0
  240. package/lib/modules/vaults/read.actions.js +596 -0
  241. package/lib/modules/vaults/types.d.ts +71 -0
  242. package/lib/modules/vaults/types.js +3 -0
  243. package/lib/modules/vaults/utils/call-data-decoder.d.ts +61 -0
  244. package/lib/modules/vaults/utils/call-data-decoder.js +194 -0
  245. package/lib/modules/vaults/utils/date-utils.d.ts +50 -0
  246. package/lib/modules/vaults/utils/date-utils.js +84 -0
  247. package/lib/modules/vaults/utils.d.ts +140 -0
  248. package/lib/modules/vaults/utils.js +799 -0
  249. package/lib/modules/vaults/write.actions.d.ts +529 -0
  250. package/lib/modules/vaults/write.actions.js +1749 -0
  251. package/lib/polyfills.d.ts +1 -0
  252. package/lib/polyfills.js +12 -0
  253. package/lib/sdk.d.ts +26721 -0
  254. package/lib/services/coingecko/fetcher.d.ts +15 -0
  255. package/lib/services/coingecko/fetcher.js +67 -0
  256. package/lib/services/coingecko/index.d.ts +2 -0
  257. package/lib/services/coingecko/index.js +19 -0
  258. package/lib/services/coingecko/utils.d.ts +1 -0
  259. package/lib/services/coingecko/utils.js +24 -0
  260. package/lib/services/debank/fetcher.d.ts +126 -0
  261. package/lib/services/debank/fetcher.js +47 -0
  262. package/lib/services/debank/index.d.ts +2 -0
  263. package/lib/services/debank/index.js +19 -0
  264. package/lib/services/debank/utils.d.ts +38 -0
  265. package/lib/services/debank/utils.js +297 -0
  266. package/lib/services/layerzero/deposits.d.ts +49 -0
  267. package/lib/services/layerzero/deposits.js +166 -0
  268. package/lib/services/layerzero/redeems.d.ts +20 -0
  269. package/lib/services/layerzero/redeems.js +92 -0
  270. package/lib/services/layerzero/utils.d.ts +9 -0
  271. package/lib/services/layerzero/utils.js +22 -0
  272. package/lib/services/octavfi/fetcher.d.ts +9 -0
  273. package/lib/services/octavfi/fetcher.js +103 -0
  274. package/lib/services/octavfi/index.d.ts +3 -0
  275. package/lib/services/octavfi/index.js +20 -0
  276. package/lib/services/octavfi/types.d.ts +34 -0
  277. package/lib/services/octavfi/types.js +3 -0
  278. package/lib/services/octavfi/utils.d.ts +16 -0
  279. package/lib/services/octavfi/utils.js +212 -0
  280. package/lib/services/subgraph/fetcher.d.ts +2 -0
  281. package/lib/services/subgraph/fetcher.js +61 -0
  282. package/lib/services/subgraph/index.d.ts +2 -0
  283. package/lib/services/subgraph/index.js +19 -0
  284. package/lib/services/subgraph/schema.d.ts +45 -0
  285. package/lib/services/subgraph/schema.js +75 -0
  286. package/lib/services/subgraph/vaults.d.ts +25 -0
  287. package/lib/services/subgraph/vaults.js +1106 -0
  288. package/lib/services/swap-quotes/index.d.ts +105 -0
  289. package/lib/services/swap-quotes/index.js +77 -0
  290. package/lib/services/swap-quotes/paraswap.d.ts +51 -0
  291. package/lib/services/swap-quotes/paraswap.js +138 -0
  292. package/lib/types/api.d.ts +280 -0
  293. package/lib/types/api.js +3 -0
  294. package/lib/types/index.d.ts +12 -0
  295. package/lib/types/index.js +28 -0
  296. package/lib/types/points.d.ts +28 -0
  297. package/lib/types/points.js +3 -0
  298. package/lib/types/pools.d.ts +144 -0
  299. package/lib/types/pools.js +3 -0
  300. package/lib/types/staking.d.ts +28 -0
  301. package/lib/types/staking.js +3 -0
  302. package/lib/types/sub-accounts.d.ts +140 -0
  303. package/lib/types/sub-accounts.js +3 -0
  304. package/lib/types/subgraph.d.ts +74 -0
  305. package/lib/types/subgraph.js +3 -0
  306. package/lib/types/typed-contract.d.ts +102 -0
  307. package/lib/types/typed-contract.js +3 -0
  308. package/lib/types/user.d.ts +1 -0
  309. package/lib/types/user.js +3 -0
  310. package/lib/types/vaults.d.ts +714 -0
  311. package/lib/types/vaults.js +24 -0
  312. package/lib/types/web3.d.ts +51 -0
  313. package/lib/types/web3.js +14 -0
  314. package/lib/types/webserver.d.ts +698 -0
  315. package/lib/types/webserver.js +3 -0
  316. package/package.json +78 -0
@@ -0,0 +1,613 @@
1
+ "use strict";
2
+ /**
3
+ * Shared Soroban RPC utilities
4
+ *
5
+ * Common transaction building and read-only query helpers used by
6
+ * actions, submit, and getters modules.
7
+ */
8
+ Object.defineProperty(exports, "__esModule", { value: true });
9
+ exports.createServer = createServer;
10
+ exports.resolveNetworkConfig = resolveNetworkConfig;
11
+ exports.resetHealthyServerCache = resetHealthyServerCache;
12
+ exports.redactRpcUrl = redactRpcUrl;
13
+ exports.getHealthyServer = getHealthyServer;
14
+ exports.isRetryableSorobanRpcError = isRetryableSorobanRpcError;
15
+ exports.isRetryableSimulationError = isRetryableSimulationError;
16
+ exports.withEndpointFailover = withEndpointFailover;
17
+ exports.toBigIntAmount = toBigIntAmount;
18
+ exports.queryContract = queryContract;
19
+ exports.buildSorobanTx = buildSorobanTx;
20
+ const stellar_sdk_1 = require("@stellar/stellar-sdk");
21
+ const core_1 = require("../../core");
22
+ const constants_1 = require("./constants");
23
+ function createServer(rpcUrl) {
24
+ return new stellar_sdk_1.rpc.Server(rpcUrl, {
25
+ allowHttp: rpcUrl.startsWith('http://'),
26
+ });
27
+ }
28
+ /**
29
+ * Ordered public Soroban RPC endpoints per network, for health-gated failover.
30
+ *
31
+ * The first entry is the default primary ({@link SOROBAN_RPC_URLS}); the rest
32
+ * are keyless public fallbacks. A provider node can stall — most visibly around
33
+ * a protocol upgrade, when it freezes behind the network head and every
34
+ * simulation fails with a snapshot error — so a single endpoint means one bad
35
+ * node takes down all reads, deposits, and submits. Module-private: an internal
36
+ * resilience detail, not part of the adapter's public surface.
37
+ */
38
+ const SOROBAN_FALLBACK_RPC_URLS = {
39
+ mainnet: [constants_1.SOROBAN_RPC_URLS.mainnet, 'https://mainnet.sorobanrpc.com'],
40
+ testnet: [constants_1.SOROBAN_RPC_URLS.testnet],
41
+ };
42
+ /**
43
+ * Resolve the ordered RPC endpoints and network passphrase for a Stellar network.
44
+ *
45
+ * When `overrideRpcUrl` is supplied (e.g. a consumer's keyed Alchemy endpoint),
46
+ * it becomes the primary with the built-in public endpoints kept behind it as
47
+ * failover — so opting into a premium provider still degrades to the public
48
+ * network rather than becoming a new single point of failure. The endpoint is
49
+ * injected rather than hardcoded, so the adapter depends on configuration, not a
50
+ * constant.
51
+ */
52
+ function resolveNetworkConfig(network, overrideRpcUrl) {
53
+ const defaults = SOROBAN_FALLBACK_RPC_URLS[network];
54
+ const rpcUrls = overrideRpcUrl
55
+ ? [overrideRpcUrl, ...defaults]
56
+ : [...defaults];
57
+ return {
58
+ rpcUrl: rpcUrls[0],
59
+ rpcUrls,
60
+ passphrase: constants_1.NETWORK_PASSPHRASES[network],
61
+ };
62
+ }
63
+ /** How long a health-checked endpoint choice is reused before re-probing. */
64
+ const HEALTHY_SERVER_TTL_MS = 30_000;
65
+ /**
66
+ * Shorter reuse window after a fully-failed probe (no endpoint healthy). Caps
67
+ * probe traffic during an outage — failing fast on the primary beats re-probing
68
+ * every endpoint on every call — while keeping recovery within a few seconds.
69
+ */
70
+ const NEGATIVE_CACHE_TTL_MS = 5_000;
71
+ /**
72
+ * Bound on a single `getHealth` probe so a *hung* (not erroring) node can't
73
+ * block the failover loop; a timeout is treated like an unhealthy endpoint.
74
+ */
75
+ const HEALTH_PROBE_TIMEOUT_MS = 3_000;
76
+ /**
77
+ * Bound on a single real RPC operation (simulate / getAccount / build) so an
78
+ * endpoint that passed `getHealth()` but then *hangs* on the actual call fails
79
+ * over instead of blocking indefinitely; a timeout is treated as retryable.
80
+ */
81
+ const RPC_OPERATION_TIMEOUT_MS = 15_000;
82
+ const healthyServerCache = new Map();
83
+ // De-dupes concurrent probes for the same endpoint set (e.g. the parallel reads
84
+ // a vault listing issues) so a cold cache costs one probe, not one per call.
85
+ const inFlightProbes = new Map();
86
+ /**
87
+ * Clear the health-check cache and any in-flight probes. Test-only seam.
88
+ * @internal
89
+ */
90
+ function resetHealthyServerCache() {
91
+ healthyServerCache.clear();
92
+ inFlightProbes.clear();
93
+ }
94
+ /**
95
+ * Host-only view of an RPC URL, safe for logs. Keyed provider endpoints put the
96
+ * API key in the path (e.g. Alchemy `/v2/<key>`), so logging the raw URL would
97
+ * leak the secret into SDK logs / crash reporters. Returns just protocol+host.
98
+ * @internal
99
+ */
100
+ function redactRpcUrl(url) {
101
+ try {
102
+ const { protocol, host } = new URL(url);
103
+ return `${protocol}//${host}`;
104
+ }
105
+ catch {
106
+ return '<invalid-url>';
107
+ }
108
+ }
109
+ /**
110
+ * Return a copy of `value` with every configured RPC URL reduced to protocol+host
111
+ * in any string it carries, so a keyed endpoint (e.g. Alchemy `/v2/<key>`) can't
112
+ * leak its API key through a thrown error's chained `cause`.
113
+ *
114
+ * Handles Errors, plain objects, and arrays — not just Errors: Soroban's
115
+ * JSON-RPC helper throws the raw `{ code, message, data }` object, which
116
+ * `AugustSDKError.toJSON()` serializes wholesale, so an unscrubbed object cause
117
+ * would leak the key. Cloned recursively (depth- and cycle-bounded); the
118
+ * original is never mutated.
119
+ */
120
+ function scrubErrorUrls(value, scrub, depth = 0, seen = new WeakSet()) {
121
+ if (typeof value === 'string')
122
+ return scrub(value);
123
+ if (value === null || typeof value !== 'object')
124
+ return value;
125
+ if (depth >= 4)
126
+ return '[TRUNCATED]';
127
+ if (seen.has(value))
128
+ return '[Circular]';
129
+ seen.add(value);
130
+ if (value instanceof Error) {
131
+ const clone = new Error(scrub(value.message));
132
+ clone.name = value.name;
133
+ if (value.stack)
134
+ clone.stack = scrub(value.stack);
135
+ // Carry over any extra own props (e.g. a JSON-RPC `code` / `data`), scrubbed.
136
+ for (const key of Object.getOwnPropertyNames(value)) {
137
+ if (key === 'message' || key === 'stack' || key === 'name')
138
+ continue;
139
+ clone[key] = scrubErrorUrls(value[key], scrub, depth + 1, seen);
140
+ }
141
+ return clone;
142
+ }
143
+ if (Array.isArray(value)) {
144
+ return value.map((v) => scrubErrorUrls(v, scrub, depth + 1, seen));
145
+ }
146
+ const out = {};
147
+ for (const [key, v] of Object.entries(value)) {
148
+ out[key] = scrubErrorUrls(v, scrub, depth + 1, seen);
149
+ }
150
+ return out;
151
+ }
152
+ /**
153
+ * Race a promise against a timeout so a hung call can't block indefinitely. The
154
+ * timer is always cleared, so a fast-resolving promise leaves nothing pending.
155
+ */
156
+ function withTimeout(promise, ms, label) {
157
+ let timer;
158
+ const timeout = new Promise((_resolve, reject) => {
159
+ timer = setTimeout(() => reject(new Error(`${label} timed out after ${ms}ms`)), ms);
160
+ });
161
+ return Promise.race([promise, timeout]).finally(() => clearTimeout(timer));
162
+ }
163
+ /**
164
+ * Return a Soroban RPC server backed by a healthy endpoint for `config`. Thin
165
+ * wrapper over {@link resolveHealthyServer} for callers (e.g. submission) that
166
+ * only need the server, not the URL it resolved to.
167
+ *
168
+ * @internal
169
+ */
170
+ function getHealthyServer(config) {
171
+ return resolveHealthyServer(config).then((r) => r.server);
172
+ }
173
+ /**
174
+ * Resolve a healthy endpoint for `config`, returning both the server and the URL
175
+ * it was built from.
176
+ *
177
+ * Probes `config.rpcUrls` in priority order via `getHealth()` and uses the first
178
+ * that reports healthy, so a stalled or lagging provider node is skipped instead
179
+ * of failing every call. The choice is cached for {@link HEALTHY_SERVER_TTL_MS},
180
+ * and concurrent callers on a cold cache share a single in-flight probe — so a
181
+ * burst of parallel reads costs one health probe, not one per call. When no
182
+ * endpoint reports healthy, falls back to the first reachable endpoint so the
183
+ * caller still attempts the request and surfaces the node's real error.
184
+ *
185
+ * The URL is returned (not just the server) so {@link withEndpointFailover} can
186
+ * skip the just-attempted endpoint and promote a working fallback into the cache.
187
+ */
188
+ function resolveHealthyServer(config) {
189
+ // Prefer the ordered failover list; fall back to the single primary for a
190
+ // hand-built config that predates `rpcUrls`.
191
+ const rpcUrls = config.rpcUrls && config.rpcUrls.length > 0
192
+ ? config.rpcUrls
193
+ : [config.rpcUrl];
194
+ // Key by the full ordered endpoint set, not just the primary: the same
195
+ // primary paired with different fallback lists selects a different server, so
196
+ // keying on `rpcUrls[0]` alone could return one endpoint set's choice for
197
+ // another during the TTL.
198
+ const cacheKey = rpcUrls.join('|');
199
+ const cached = healthyServerCache.get(cacheKey);
200
+ if (cached) {
201
+ // A fully-failed probe is cached only briefly (NEGATIVE_CACHE_TTL_MS) so an
202
+ // outage doesn't re-probe every endpoint on every call, yet recovers fast.
203
+ const ttl = cached.healthy ? HEALTHY_SERVER_TTL_MS : NEGATIVE_CACHE_TTL_MS;
204
+ if (Date.now() - cached.checkedAt < ttl) {
205
+ return Promise.resolve({
206
+ server: cached.server,
207
+ url: cached.url,
208
+ healthy: cached.healthy,
209
+ });
210
+ }
211
+ }
212
+ const existing = inFlightProbes.get(cacheKey);
213
+ if (existing)
214
+ return existing;
215
+ const probe = probeHealthyServer(rpcUrls, cacheKey).finally(() => {
216
+ inFlightProbes.delete(cacheKey);
217
+ });
218
+ inFlightProbes.set(cacheKey, probe);
219
+ return probe;
220
+ }
221
+ async function probeHealthyServer(rpcUrls, cacheKey) {
222
+ // The first endpoint we can even construct — the fallback when none report
223
+ // healthy. Tracked separately from `rpcUrls[0]` so a malformed primary (e.g. a
224
+ // typo'd consumer override) is skipped rather than disabling every call.
225
+ let firstConstructable;
226
+ let firstConstructableUrl;
227
+ for (const url of rpcUrls) {
228
+ let server;
229
+ try {
230
+ // Construct inside the guard: a malformed URL throws from the rpc.Server
231
+ // ctor, and must skip to the next endpoint rather than abort the loop and
232
+ // disable every fallback.
233
+ server = createServer(url);
234
+ }
235
+ catch (err) {
236
+ core_1.Logger.log.warn('getHealthyServer', 'Skipping invalid Soroban RPC endpoint; trying next endpoint', { url: redactRpcUrl(url), error: String(err) });
237
+ continue;
238
+ }
239
+ if (firstConstructable === undefined) {
240
+ firstConstructable = server;
241
+ firstConstructableUrl = url;
242
+ }
243
+ try {
244
+ const health = await withTimeout(server.getHealth(), HEALTH_PROBE_TIMEOUT_MS, 'getHealth');
245
+ if (health.status === 'healthy') {
246
+ healthyServerCache.set(cacheKey, {
247
+ server,
248
+ url,
249
+ checkedAt: Date.now(),
250
+ healthy: true,
251
+ });
252
+ return { server, url, healthy: true };
253
+ }
254
+ core_1.Logger.log.warn('getHealthyServer', `Soroban RPC reported status "${health.status}"; trying next endpoint`, { url: redactRpcUrl(url) });
255
+ }
256
+ catch (err) {
257
+ core_1.Logger.log.warn('getHealthyServer', 'Soroban RPC health check failed; trying next endpoint',
258
+ // Scrub the endpoint from the error message too — SDK errors often
259
+ // embed the request URL (key and all).
260
+ {
261
+ url: redactRpcUrl(url),
262
+ error: String(err).split(url).join(redactRpcUrl(url)),
263
+ });
264
+ }
265
+ }
266
+ if (firstConstructable === undefined) {
267
+ // Every configured URL was malformed — there is nothing to call.
268
+ throw new core_1.AugustSDKError('UNKNOWN', 'No valid Soroban RPC endpoint could be constructed from the configured URLs');
269
+ }
270
+ const fallbackUrl = firstConstructableUrl;
271
+ core_1.Logger.log.warn('getHealthyServer', 'No healthy Soroban RPC endpoint; falling back to first reachable endpoint', { primary: redactRpcUrl(fallbackUrl) });
272
+ // Negative-cache the fallback (short TTL) so a sustained outage fails fast
273
+ // instead of re-probing every endpoint on every call.
274
+ healthyServerCache.set(cacheKey, {
275
+ server: firstConstructable,
276
+ url: fallbackUrl,
277
+ checkedAt: Date.now(),
278
+ healthy: false,
279
+ });
280
+ return { server: firstConstructable, url: fallbackUrl, healthy: false };
281
+ }
282
+ /**
283
+ * A thrown RPC error is retryable on another endpoint UNLESS it is one of our
284
+ * typed domain errors. Those mark a *deterministic* outcome — a contract revert,
285
+ * an unfunded account, archived state needing restore, a bad input, or a local
286
+ * assembly failure — which reproduces identically on every node, so retrying
287
+ * elsewhere only wastes calls. Any other throw (a transport hang/reset, or a
288
+ * method-specific node error from an endpoint that still answered `getHealth()`)
289
+ * is worth the next endpoint.
290
+ *
291
+ * Exported so an operation with different semantics (e.g. an idempotency-aware
292
+ * submission path) can compose or replace this policy via
293
+ * {@link FailoverOptions.isRetryable} — extension without editing the core.
294
+ *
295
+ * Named distinctly from `core/helpers/chain-error`'s `isRetryableRpcError`
296
+ * (the EVM transport classifier, deliberately public) — the internal-dts
297
+ * leak check matches `@internal` tags by name across the whole `src.ts` tree,
298
+ * so a same-named pair would make it flag the public EVM one as a leak.
299
+ * @internal
300
+ */
301
+ function isRetryableSorobanRpcError(err) {
302
+ return !(err instanceof core_1.AugustValidationError || err instanceof core_1.AugustSDKError);
303
+ }
304
+ /**
305
+ * Signatures of simulation errors that indicate a stalled/lagging *node* rather
306
+ * than a deterministic contract revert. The canonical case is the Protocol 27
307
+ * boundary, where a node frozen behind the network head answered `getHealth()`
308
+ * but reported reads with a "not present in the snapshot" error. Extend this
309
+ * list as new node-side signatures surface.
310
+ */
311
+ const RETRYABLE_SIMULATION_ERROR_SIGNATURES = ['not present in the snapshot'];
312
+ /**
313
+ * Whether a simulation *error* string is a node/infrastructure failure (which
314
+ * clears on another endpoint) rather than a genuine contract revert (which
315
+ * reproduces on every node). `isSimulationError` alone can't tell these apart —
316
+ * both arrive as a populated `error` field — so callers use this to decide
317
+ * whether to fail over or treat the error as terminal.
318
+ * @internal
319
+ */
320
+ function isRetryableSimulationError(errorText) {
321
+ const lower = errorText.toLowerCase();
322
+ return RETRYABLE_SIMULATION_ERROR_SIGNATURES.some((sig) => lower.includes(sig));
323
+ }
324
+ /**
325
+ * Drop a cached endpoint choice so a server that just failed a *real* call is
326
+ * not re-used for the remainder of its {@link HEALTHY_SERVER_TTL_MS} window.
327
+ */
328
+ function dropCachedServer(rpcUrls) {
329
+ healthyServerCache.delete(rpcUrls.join('|'));
330
+ }
331
+ /**
332
+ * Run an idempotent, side-effect-free `operation` (a read or a tx build) against
333
+ * a Soroban endpoint, failing over to the remaining endpoints on a retryable
334
+ * failure.
335
+ *
336
+ * {@link getHealthyServer} only proves an endpoint answered `getHealth()`, and
337
+ * caches that choice for {@link HEALTHY_SERVER_TTL_MS} — but the node can still
338
+ * hang or return a method-specific error on the *real* call. So we run the op on
339
+ * the health-gated server first (the fast, cached path) and, on a retryable
340
+ * failure, drop that cached choice and retry the op against every endpoint in
341
+ * priority order. Deterministic contract/domain errors short-circuit (see
342
+ * {@link isRetryableSorobanRpcError}); each attempt is time-boxed so a hung node can't
343
+ * stall the loop.
344
+ *
345
+ * The `operation` is a strategy (dependency-injected), so new read/build calls
346
+ * reuse this failover without changing it; `options` keeps retry policy and
347
+ * timeout open for extension. Submission is deliberately NOT routed through here
348
+ * — re-sending a signed transaction across endpoints risks a double-submit, so
349
+ * it needs sequence/DUPLICATE-based idempotency rather than blind retry.
350
+ * @internal
351
+ */
352
+ async function withEndpointFailover(config, method, operation, options = {}) {
353
+ const isRetryable = options.isRetryable ?? isRetryableSorobanRpcError;
354
+ const timeoutMs = options.timeoutMs ?? RPC_OPERATION_TIMEOUT_MS;
355
+ const rpcUrls = config.rpcUrls && config.rpcUrls.length > 0
356
+ ? config.rpcUrls
357
+ : [config.rpcUrl];
358
+ const runOn = (server) => withTimeout(operation(server), timeoutMs, `Soroban ${method}`);
359
+ const cacheKey = rpcUrls.join('|');
360
+ // Reduce every configured endpoint URL to protocol+host in anything surfaced
361
+ // from here (logs, the thrown message, the chained cause). SDK errors embed the
362
+ // request URL — which for a keyed provider carries the API key in its path — so
363
+ // an unscrubbed `String(err)` would leak it. Belt-and-suspenders with the
364
+ // analytics sanitizer, and it also covers the thrown error that escapes to the
365
+ // caller (which our telemetry sanitizer never sees).
366
+ const scrub = (text) => rpcUrls.reduce((acc, u) => acc.split(u).join(redactRpcUrl(u)), text);
367
+ let lastError;
368
+ // A terminal "everything failed" error, scrubbed so a keyed endpoint can't
369
+ // leak through the message or chained cause.
370
+ const failAllEndpoints = () => new core_1.AugustSDKError('UNKNOWN', `Soroban ${method} failed on all endpoints: ${scrub(String(lastError))}`, { cause: scrubErrorUrls(lastError, scrub), context: { method } });
371
+ // Fast path: the health-gated, cross-call-cached endpoint.
372
+ const { server: primaryServer, url: primaryUrl, healthy, } = await resolveHealthyServer(config);
373
+ try {
374
+ return await runOn(primaryServer);
375
+ }
376
+ catch (err) {
377
+ if (!isRetryable(err))
378
+ throw err;
379
+ lastError = err;
380
+ if (!healthy) {
381
+ // The resolved endpoint is a negative-cached fallback: a prior probe found
382
+ // no healthy endpoint, so the whole set is down. Re-looping every endpoint
383
+ // (and re-probing on the next read) would only amplify load during the
384
+ // outage, so fail fast and leave the short-TTL negative entry in place —
385
+ // subsequent reads within NEGATIVE_CACHE_TTL_MS fast-fail on the primary too.
386
+ throw failAllEndpoints();
387
+ }
388
+ // A "healthy" endpoint failed the real call — drop it and fail over.
389
+ dropCachedServer(rpcUrls);
390
+ core_1.Logger.log.warn('withEndpointFailover', `Soroban ${method} failed on the health-gated endpoint; failing over`, { error: scrub(String(err)) });
391
+ }
392
+ // Failover: the remaining endpoints in priority order. Skip the one the fast
393
+ // path already tried (no point paying its timeout twice). On success, promote
394
+ // the working endpoint into the cache so the next call starts there instead of
395
+ // repeating the failed-primary-then-fallback sequence.
396
+ for (const url of rpcUrls) {
397
+ if (url === primaryUrl)
398
+ continue;
399
+ let server;
400
+ try {
401
+ server = createServer(url);
402
+ }
403
+ catch {
404
+ continue; // malformed endpoint URL — skip
405
+ }
406
+ try {
407
+ const result = await runOn(server);
408
+ healthyServerCache.set(cacheKey, {
409
+ server,
410
+ url,
411
+ checkedAt: Date.now(),
412
+ healthy: true,
413
+ });
414
+ return result;
415
+ }
416
+ catch (err) {
417
+ if (!isRetryable(err))
418
+ throw err;
419
+ lastError = err;
420
+ core_1.Logger.log.warn('withEndpointFailover', `Soroban ${method} failed; trying next endpoint`, {
421
+ url: redactRpcUrl(url),
422
+ error: scrub(String(err)),
423
+ });
424
+ }
425
+ }
426
+ // Every endpoint's real op failed even though one health-probed OK. Negative-
427
+ // cache the health-gated server (it constructed fine) so subsequent reads
428
+ // fast-fail within NEGATIVE_CACHE_TTL_MS instead of re-probing + re-looping the
429
+ // whole set during a sustained outage.
430
+ healthyServerCache.set(cacheKey, {
431
+ server: primaryServer,
432
+ url: primaryUrl,
433
+ checkedAt: Date.now(),
434
+ healthy: false,
435
+ });
436
+ throw failAllEndpoints();
437
+ }
438
+ /**
439
+ * Validate and convert a string amount to a non-negative BigInt.
440
+ * Throws a descriptive error if the value is not a valid non-negative integer string.
441
+ */
442
+ function toBigIntAmount(value, label) {
443
+ if (value === '') {
444
+ throw new core_1.AugustValidationError('INVALID_INPUT', `Invalid ${label}: value must not be empty`);
445
+ }
446
+ let result;
447
+ try {
448
+ result = BigInt(value);
449
+ }
450
+ catch {
451
+ throw new core_1.AugustValidationError('INVALID_INPUT', `Invalid ${label}: "${value}" is not a valid integer string`);
452
+ }
453
+ if (result < 0n) {
454
+ throw new core_1.AugustValidationError('INVALID_INPUT', `Invalid ${label}: value must be non-negative, got "${value}"`);
455
+ }
456
+ return result;
457
+ }
458
+ /**
459
+ * Query a read-only Soroban contract function via simulation.
460
+ * Uses a throwaway source account — simulation is off-chain and has no on-chain side effects.
461
+ * Returns the ScVal result, or null if the call fails.
462
+ */
463
+ function extractSimulationError(simulated) {
464
+ return 'error' in simulated
465
+ ? String(simulated.error)
466
+ : 'Unknown simulation error';
467
+ }
468
+ async function queryContract(config, contractId, method, args = []) {
469
+ try {
470
+ // Build the simulation tx once — it is endpoint-independent, so only the
471
+ // simulate call is failed over across endpoints (not the tx assembly).
472
+ const contract = new stellar_sdk_1.Contract(contractId);
473
+ const sourceKeypair = stellar_sdk_1.Keypair.random();
474
+ const account = new stellar_sdk_1.Account(sourceKeypair.publicKey(), '0');
475
+ // Minimal fee — simulation is off-chain; these values don't affect execution cost.
476
+ // Short timeout to avoid blocking vault listing if Soroban RPC is slow.
477
+ const tx = new stellar_sdk_1.TransactionBuilder(account, {
478
+ fee: '100',
479
+ networkPassphrase: config.passphrase,
480
+ })
481
+ .addOperation(contract.call(method, ...args))
482
+ .setTimeout(constants_1.QUERY_TIMEOUT_SECONDS)
483
+ .build();
484
+ return await withEndpointFailover(config, method, async (server) => {
485
+ const simulated = await server.simulateTransaction(tx);
486
+ if (stellar_sdk_1.rpc.Api.isSimulationError(simulated)) {
487
+ const errorText = extractSimulationError(simulated);
488
+ if (isRetryableSimulationError(errorText)) {
489
+ // A stalled/lagging node reports the read as a simulation error too
490
+ // (e.g. a post-upgrade snapshot gap) — not a real revert. Throw so the
491
+ // failover wrapper tries another endpoint instead of returning null.
492
+ throw new Error(`Soroban simulation node error for ${method}: ${errorText}`);
493
+ }
494
+ // A genuine contract revert is deterministic across nodes — surface null
495
+ // (best-effort read) rather than failing over to repeat it.
496
+ core_1.Logger.log.warn('queryContract', `Soroban simulation error for ${method}: ${errorText}`, { contractId });
497
+ return null;
498
+ }
499
+ if (stellar_sdk_1.rpc.Api.isSimulationSuccess(simulated) && simulated.result) {
500
+ return simulated.result.retval;
501
+ }
502
+ core_1.Logger.log.warn('queryContract', `Unexpected simulation state for ${method} — no result returned`, { contractId });
503
+ return null;
504
+ });
505
+ }
506
+ catch (err) {
507
+ core_1.Logger.log.warn('queryContract', `Soroban query failed: ${method}`, {
508
+ contractId,
509
+ error: String(err),
510
+ });
511
+ return null;
512
+ }
513
+ }
514
+ /**
515
+ * Read the network's wall-clock time (unix seconds) from the latest closed
516
+ * ledger, or null if the RPC can't report it.
517
+ *
518
+ * Soroban validators reject a transaction whose `maxTime` precedes the ledger
519
+ * close time (`txTOO_LATE`). Anchoring `maxTime` to the *network* clock instead
520
+ * of the signer's `Date.now()` immunises the deadline against a skewed device
521
+ * clock — a machine lagging behind real time was silently building
522
+ * already-expired transactions. Best-effort: on any RPC failure the caller
523
+ * falls back to the local clock, so this never regresses the prior behaviour.
524
+ */
525
+ async function getNetworkCloseTime(server) {
526
+ try {
527
+ const { sequence } = await server.getLatestLedger();
528
+ // `latestLedgerCloseTime` on the response envelope is the freshest network
529
+ // time; the single-ledger page is just the cheapest valid request shape.
530
+ const page = await server.getLedgers({
531
+ startLedger: sequence,
532
+ pagination: { limit: 1 },
533
+ });
534
+ return typeof page.latestLedgerCloseTime === 'number'
535
+ ? page.latestLedgerCloseTime
536
+ : null;
537
+ }
538
+ catch (err) {
539
+ core_1.Logger.log.warn('getNetworkCloseTime', `Network clock unavailable; falling back to local clock for tx timebounds: ${String(err)}`);
540
+ return null;
541
+ }
542
+ }
543
+ /**
544
+ * Build an unsigned Soroban contract invocation transaction.
545
+ * Fetches the real source account from the network (the account must exist and be funded).
546
+ * Simulates via Soroban RPC to attach resource footprint and auth entries,
547
+ * using MAX_FEE_STROOPS as the fee ceiling and incorporating the simulated resource fee.
548
+ */
549
+ async function buildSorobanTx(config, sourceAddress, contractId, method, args) {
550
+ const contract = new stellar_sdk_1.Contract(contractId);
551
+ // Build is idempotent (no on-chain side effects), so the whole account-fetch →
552
+ // simulate → assemble sequence is failed over across endpoints. Deterministic
553
+ // outcomes (unfunded account, simulation/restore/assembly errors) throw typed
554
+ // errors and short-circuit the failover; transport errors get the next node.
555
+ return withEndpointFailover(config, method, async (server) => {
556
+ // Read the network clock in parallel with the account fetch — it overlaps
557
+ // the account round-trip, so it adds no latency on the happy path.
558
+ const networkCloseTimePromise = getNetworkCloseTime(server);
559
+ let account;
560
+ try {
561
+ account = await server.getAccount(sourceAddress);
562
+ }
563
+ catch (err) {
564
+ // Soroban rpc currently throws plain `Error("Account not found: ...")`
565
+ // for unfunded accounts; check `NotFoundError` too so this survives an
566
+ // SDK refactor to typed errors. An unfunded account is deterministic
567
+ // across nodes (typed error → no failover); any other getAccount error is
568
+ // transport-ish and falls over.
569
+ const msg = err instanceof Error ? err.message : String(err);
570
+ const isAccountNotFound = err instanceof stellar_sdk_1.NotFoundError || /Account not found/.test(msg);
571
+ if (isAccountNotFound) {
572
+ throw new core_1.AugustValidationError('ACCOUNT_NOT_FUNDED', `Stellar account ${sourceAddress} is not funded. Send at least 1 XLM to this address to activate it before depositing or redeeming.`, { cause: err, context: { sourceAddress, method, contractId } });
573
+ }
574
+ throw err;
575
+ }
576
+ const builder = new stellar_sdk_1.TransactionBuilder(account, {
577
+ fee: constants_1.MAX_FEE_STROOPS,
578
+ networkPassphrase: config.passphrase,
579
+ }).addOperation(contract.call(method, ...args));
580
+ const networkCloseTime = await networkCloseTimePromise;
581
+ if (networkCloseTime !== null) {
582
+ // Absolute deadline anchored to the network clock — survives signer skew.
583
+ builder.setTimebounds(0, networkCloseTime + constants_1.TX_TIMEOUT_SECONDS);
584
+ }
585
+ else {
586
+ // RPC couldn't report network time; fall back to the local-clock window.
587
+ builder.setTimeout(constants_1.TX_TIMEOUT_SECONDS);
588
+ }
589
+ const tx = builder.build();
590
+ const simulated = await server.simulateTransaction(tx);
591
+ if (stellar_sdk_1.rpc.Api.isSimulationError(simulated)) {
592
+ const errorText = extractSimulationError(simulated);
593
+ if (isRetryableSimulationError(errorText)) {
594
+ // Node/snapshot error (a stale node), not a contract revert — throw a
595
+ // retryable error so the failover wrapper tries another endpoint.
596
+ throw new Error(`Soroban simulation node error for ${method}: ${errorText}`);
597
+ }
598
+ throw new core_1.AugustSDKError('UNKNOWN', `Soroban simulation failed: ${errorText}`, { context: { method, contractId } });
599
+ }
600
+ if ('restorePreamble' in simulated && simulated.restorePreamble) {
601
+ throw new core_1.AugustSDKError('UNKNOWN', `Contract ledger state needs restoration before invoking ${method}. ` +
602
+ 'Submit a restore footprint transaction first.', { context: { method, contractId } });
603
+ }
604
+ try {
605
+ const assembled = stellar_sdk_1.rpc.assembleTransaction(tx, simulated).build();
606
+ return assembled.toXDR();
607
+ }
608
+ catch (assemblyErr) {
609
+ throw new core_1.AugustSDKError('UNKNOWN', `Failed to assemble Soroban transaction for ${method}: ${String(assemblyErr)}`, { cause: assemblyErr, context: { method, contractId } });
610
+ }
611
+ });
612
+ }
613
+ //# sourceMappingURL=soroban.js.map
@@ -0,0 +1,34 @@
1
+ /**
2
+ * Stellar Transaction Submission
3
+ *
4
+ * Submits signed Soroban transactions and polls for confirmation.
5
+ */
6
+ import type { IStellarNetwork } from './types';
7
+ /**
8
+ * Submit a signed Soroban transaction and poll until confirmed.
9
+ *
10
+ * @param signedXdr - Base64-encoded XDR of the signed transaction
11
+ * @param network - Stellar network name
12
+ * @param sorobanRpcUrl - Optional override Soroban RPC endpoint (e.g. a keyed
13
+ * Alchemy URL); becomes the primary with the SDK's public endpoints kept as
14
+ * failover. Omit to use the public endpoints.
15
+ * @returns The transaction hash once the network confirms it as successful
16
+ * @throws {@link AugustTimeoutError} when the transaction is not confirmed
17
+ * within the poll budget (`MAX_POLL_ATTEMPTS`).
18
+ * @throws {@link AugustSDKError} when the RPC rejects the submission or the
19
+ * transaction confirms as failed. Its `context` carries `{ network, status }`
20
+ * plus, when the result XDR decodes, a `resultCode` string holding the
21
+ * transaction-level reason (e.g. `"txBadSeq"`, `"txTooLate"`); `resultCode`
22
+ * is `undefined` when the code cannot be decoded.
23
+ * @example
24
+ * ```ts
25
+ * try {
26
+ * const hash = await submitStellarTransaction(signedXdr, 'mainnet');
27
+ * } catch (err) {
28
+ * if (err instanceof AugustSDKError && err.context?.resultCode === 'txBadSeq') {
29
+ * // stale sequence number — rebuild the transaction and resubmit
30
+ * }
31
+ * }
32
+ * ```
33
+ */
34
+ export declare function submitStellarTransaction(signedXdr: string, network: IStellarNetwork, sorobanRpcUrl?: string): Promise<string>;