@upshiftfinance/sdk 0.0.0-stage → 0.1.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 (346) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +408 -2
  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 +953 -0
  40. package/lib/abis/SwapRouter.js +1228 -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 +249 -0
  65. package/lib/adapters/evm/index.d.ts +539 -0
  66. package/lib/adapters/evm/index.js +656 -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/confirm.d.ts +88 -0
  70. package/lib/adapters/solana/confirm.js +291 -0
  71. package/lib/adapters/solana/constants.d.ts +42 -0
  72. package/lib/adapters/solana/constants.js +59 -0
  73. package/lib/adapters/solana/getters.d.ts +42 -0
  74. package/lib/adapters/solana/getters.js +275 -0
  75. package/lib/adapters/solana/idl/vault-idl.d.ts +700 -0
  76. package/lib/adapters/solana/idl/vault-idl.js +2101 -0
  77. package/lib/adapters/solana/idl/withdrawal-queue-idl.d.ts +795 -0
  78. package/lib/adapters/solana/idl/withdrawal-queue-idl.js +1864 -0
  79. package/lib/adapters/solana/index.d.ts +372 -0
  80. package/lib/adapters/solana/index.js +459 -0
  81. package/lib/adapters/solana/pricing.d.ts +184 -0
  82. package/lib/adapters/solana/pricing.js +239 -0
  83. package/lib/adapters/solana/queue-hints.d.ts +29 -0
  84. package/lib/adapters/solana/queue-hints.js +59 -0
  85. package/lib/adapters/solana/queue.actions.d.ts +97 -0
  86. package/lib/adapters/solana/queue.actions.js +468 -0
  87. package/lib/adapters/solana/token-reads.d.ts +108 -0
  88. package/lib/adapters/solana/token-reads.js +145 -0
  89. package/lib/adapters/solana/types.d.ts +325 -0
  90. package/lib/adapters/solana/types.js +3 -0
  91. package/lib/adapters/solana/utils.d.ts +229 -0
  92. package/lib/adapters/solana/utils.js +773 -0
  93. package/lib/adapters/solana/vault.actions.d.ts +140 -0
  94. package/lib/adapters/solana/vault.actions.js +657 -0
  95. package/lib/adapters/solana/withdrawal-queue.d.ts +125 -0
  96. package/lib/adapters/solana/withdrawal-queue.js +301 -0
  97. package/lib/adapters/stellar/actions.d.ts +41 -0
  98. package/lib/adapters/stellar/actions.js +126 -0
  99. package/lib/adapters/stellar/constants.d.ts +43 -0
  100. package/lib/adapters/stellar/constants.js +53 -0
  101. package/lib/adapters/stellar/getters.d.ts +68 -0
  102. package/lib/adapters/stellar/getters.js +290 -0
  103. package/lib/adapters/stellar/index.d.ts +126 -0
  104. package/lib/adapters/stellar/index.js +187 -0
  105. package/lib/adapters/stellar/invocation.d.ts +55 -0
  106. package/lib/adapters/stellar/invocation.js +92 -0
  107. package/lib/adapters/stellar/soroban.d.ts +131 -0
  108. package/lib/adapters/stellar/soroban.js +617 -0
  109. package/lib/adapters/stellar/submit.d.ts +42 -0
  110. package/lib/adapters/stellar/submit.js +195 -0
  111. package/lib/adapters/stellar/types.d.ts +57 -0
  112. package/lib/adapters/stellar/types.js +6 -0
  113. package/lib/adapters/stellar/utils.d.ts +24 -0
  114. package/lib/adapters/stellar/utils.js +34 -0
  115. package/lib/adapters/sui/constants.d.ts +1 -0
  116. package/lib/adapters/sui/constants.js +9 -0
  117. package/lib/adapters/sui/getters.d.ts +24 -0
  118. package/lib/adapters/sui/getters.js +134 -0
  119. package/lib/adapters/sui/index.d.ts +53 -0
  120. package/lib/adapters/sui/index.js +96 -0
  121. package/lib/adapters/sui/transformer.d.ts +10 -0
  122. package/lib/adapters/sui/transformer.js +115 -0
  123. package/lib/adapters/sui/types.d.ts +70 -0
  124. package/lib/adapters/sui/types.js +3 -0
  125. package/lib/adapters/sui/utils.d.ts +8 -0
  126. package/lib/adapters/sui/utils.js +17 -0
  127. package/lib/core/analytics/app-name.d.ts +27 -0
  128. package/lib/core/analytics/app-name.js +48 -0
  129. package/lib/core/analytics/chain-name.d.ts +9 -0
  130. package/lib/core/analytics/chain-name.js +34 -0
  131. package/lib/core/analytics/constants.d.ts +15 -0
  132. package/lib/core/analytics/constants.js +28 -0
  133. package/lib/core/analytics/env.d.ts +46 -0
  134. package/lib/core/analytics/env.js +147 -0
  135. package/lib/core/analytics/index.d.ts +39 -0
  136. package/lib/core/analytics/index.js +83 -0
  137. package/lib/core/analytics/instrumentation.d.ts +29 -0
  138. package/lib/core/analytics/instrumentation.js +292 -0
  139. package/lib/core/analytics/method-taxonomy.d.ts +19 -0
  140. package/lib/core/analytics/method-taxonomy.js +156 -0
  141. package/lib/core/analytics/metrics.d.ts +48 -0
  142. package/lib/core/analytics/metrics.js +142 -0
  143. package/lib/core/analytics/sanitize.d.ts +57 -0
  144. package/lib/core/analytics/sanitize.js +272 -0
  145. package/lib/core/analytics/sentry-runtime.d.ts +15 -0
  146. package/lib/core/analytics/sentry-runtime.js +131 -0
  147. package/lib/core/analytics/sentry.d.ts +100 -0
  148. package/lib/core/analytics/sentry.js +696 -0
  149. package/lib/core/analytics/types.d.ts +55 -0
  150. package/lib/core/analytics/types.js +3 -0
  151. package/lib/core/analytics/user-identity.d.ts +55 -0
  152. package/lib/core/analytics/user-identity.js +218 -0
  153. package/lib/core/analytics/version.d.ts +6 -0
  154. package/lib/core/analytics/version.js +10 -0
  155. package/lib/core/attribution.d.ts +159 -0
  156. package/lib/core/attribution.js +194 -0
  157. package/lib/core/auth/index.d.ts +1 -0
  158. package/lib/core/auth/index.js +18 -0
  159. package/lib/core/auth/verify.d.ts +2 -0
  160. package/lib/core/auth/verify.js +35 -0
  161. package/lib/core/base.class.d.ts +193 -0
  162. package/lib/core/base.class.js +163 -0
  163. package/lib/core/cache.d.ts +9 -0
  164. package/lib/core/cache.js +31 -0
  165. package/lib/core/constants/adapters.d.ts +103 -0
  166. package/lib/core/constants/adapters.js +180 -0
  167. package/lib/core/constants/core.d.ts +162 -0
  168. package/lib/core/constants/core.js +281 -0
  169. package/lib/core/constants/swap-router.d.ts +180 -0
  170. package/lib/core/constants/swap-router.js +203 -0
  171. package/lib/core/constants/vaults.d.ts +93 -0
  172. package/lib/core/constants/vaults.js +277 -0
  173. package/lib/core/constants/web3.d.ts +106 -0
  174. package/lib/core/constants/web3.js +251 -0
  175. package/lib/core/errors/index.d.ts +177 -0
  176. package/lib/core/errors/index.js +257 -0
  177. package/lib/core/fetcher.d.ts +237 -0
  178. package/lib/core/fetcher.js +1103 -0
  179. package/lib/core/helpers/adapters.d.ts +13 -0
  180. package/lib/core/helpers/adapters.js +39 -0
  181. package/lib/core/helpers/chain-address.d.ts +13 -0
  182. package/lib/core/helpers/chain-address.js +47 -0
  183. package/lib/core/helpers/chain-error.d.ts +207 -0
  184. package/lib/core/helpers/chain-error.js +697 -0
  185. package/lib/core/helpers/chain-support.d.ts +98 -0
  186. package/lib/core/helpers/chain-support.js +139 -0
  187. package/lib/core/helpers/concurrency.d.ts +51 -0
  188. package/lib/core/helpers/concurrency.js +79 -0
  189. package/lib/core/helpers/core.d.ts +92 -0
  190. package/lib/core/helpers/core.js +368 -0
  191. package/lib/core/helpers/explorer-link.d.ts +16 -0
  192. package/lib/core/helpers/explorer-link.js +26 -0
  193. package/lib/core/helpers/multicall.d.ts +68 -0
  194. package/lib/core/helpers/multicall.js +103 -0
  195. package/lib/core/helpers/revert-decode.d.ts +248 -0
  196. package/lib/core/helpers/revert-decode.js +515 -0
  197. package/lib/core/helpers/signer.d.ts +61 -0
  198. package/lib/core/helpers/signer.js +184 -0
  199. package/lib/core/helpers/swap-router.d.ts +269 -0
  200. package/lib/core/helpers/swap-router.js +542 -0
  201. package/lib/core/helpers/vault-version.d.ts +24 -0
  202. package/lib/core/helpers/vault-version.js +83 -0
  203. package/lib/core/helpers/vaults.d.ts +89 -0
  204. package/lib/core/helpers/vaults.js +241 -0
  205. package/lib/core/helpers/web3.d.ts +366 -0
  206. package/lib/core/helpers/web3.js +1034 -0
  207. package/lib/core/index.d.ts +23 -0
  208. package/lib/core/index.js +40 -0
  209. package/lib/core/logger/curator-alert.d.ts +217 -0
  210. package/lib/core/logger/curator-alert.js +276 -0
  211. package/lib/core/logger/index.d.ts +99 -0
  212. package/lib/core/logger/index.js +163 -0
  213. package/lib/core/logger/slack.d.ts +49 -0
  214. package/lib/core/logger/slack.js +111 -0
  215. package/lib/core/vault-metadata.d.ts +12 -0
  216. package/lib/core/vault-metadata.js +42 -0
  217. package/lib/core/version-check.d.ts +58 -0
  218. package/lib/core/version-check.js +182 -0
  219. package/lib/evm/index.d.ts +2 -0
  220. package/lib/evm/index.js +19 -0
  221. package/lib/evm/methods/crossChainVault.d.ts +132 -0
  222. package/lib/evm/methods/crossChainVault.js +857 -0
  223. package/lib/evm/methods/crossChainVaultRegistry.d.ts +92 -0
  224. package/lib/evm/methods/crossChainVaultRegistry.js +239 -0
  225. package/lib/evm/methods/index.d.ts +2 -0
  226. package/lib/evm/methods/index.js +19 -0
  227. package/lib/evm/types/crossChain.d.ts +363 -0
  228. package/lib/evm/types/crossChain.js +20 -0
  229. package/lib/evm/types/index.d.ts +1 -0
  230. package/lib/evm/types/index.js +18 -0
  231. package/lib/index.d.ts +30 -0
  232. package/lib/index.js +52 -0
  233. package/lib/main.d.ts +596 -0
  234. package/lib/main.js +681 -0
  235. package/lib/modules/api/fetcher.d.ts +108 -0
  236. package/lib/modules/api/fetcher.js +187 -0
  237. package/lib/modules/api/index.d.ts +1 -0
  238. package/lib/modules/api/index.js +6 -0
  239. package/lib/modules/api/main.d.ts +587 -0
  240. package/lib/modules/api/main.js +911 -0
  241. package/lib/modules/sub-accounts/fetcher.d.ts +53 -0
  242. package/lib/modules/sub-accounts/fetcher.js +96 -0
  243. package/lib/modules/sub-accounts/index.d.ts +2 -0
  244. package/lib/modules/sub-accounts/index.js +19 -0
  245. package/lib/modules/sub-accounts/main.d.ts +249 -0
  246. package/lib/modules/sub-accounts/main.js +211 -0
  247. package/lib/modules/sub-accounts/utils.d.ts +106 -0
  248. package/lib/modules/sub-accounts/utils.js +112 -0
  249. package/lib/modules/vaults/adapter.helpers.d.ts +84 -0
  250. package/lib/modules/vaults/adapter.helpers.js +202 -0
  251. package/lib/modules/vaults/fetcher.d.ts +147 -0
  252. package/lib/modules/vaults/fetcher.js +357 -0
  253. package/lib/modules/vaults/getters.d.ts +1060 -0
  254. package/lib/modules/vaults/getters.js +4079 -0
  255. package/lib/modules/vaults/index.d.ts +20 -0
  256. package/lib/modules/vaults/index.js +44 -0
  257. package/lib/modules/vaults/main.d.ts +607 -0
  258. package/lib/modules/vaults/main.js +1687 -0
  259. package/lib/modules/vaults/prefetch.d.ts +65 -0
  260. package/lib/modules/vaults/prefetch.js +120 -0
  261. package/lib/modules/vaults/read.actions.d.ts +406 -0
  262. package/lib/modules/vaults/read.actions.js +891 -0
  263. package/lib/modules/vaults/types.d.ts +149 -0
  264. package/lib/modules/vaults/types.js +3 -0
  265. package/lib/modules/vaults/utils/call-data-decoder.d.ts +61 -0
  266. package/lib/modules/vaults/utils/call-data-decoder.js +194 -0
  267. package/lib/modules/vaults/utils/date-utils.d.ts +50 -0
  268. package/lib/modules/vaults/utils/date-utils.js +84 -0
  269. package/lib/modules/vaults/utils.d.ts +153 -0
  270. package/lib/modules/vaults/utils.js +818 -0
  271. package/lib/modules/vaults/write.actions.d.ts +812 -0
  272. package/lib/modules/vaults/write.actions.js +2377 -0
  273. package/lib/polyfills.d.ts +1 -0
  274. package/lib/polyfills.js +12 -0
  275. package/lib/sdk.d.ts +30154 -0
  276. package/lib/services/coingecko/fetcher.d.ts +15 -0
  277. package/lib/services/coingecko/fetcher.js +67 -0
  278. package/lib/services/coingecko/index.d.ts +2 -0
  279. package/lib/services/coingecko/index.js +19 -0
  280. package/lib/services/coingecko/utils.d.ts +1 -0
  281. package/lib/services/coingecko/utils.js +24 -0
  282. package/lib/services/debank/fetcher.d.ts +126 -0
  283. package/lib/services/debank/fetcher.js +47 -0
  284. package/lib/services/debank/index.d.ts +2 -0
  285. package/lib/services/debank/index.js +19 -0
  286. package/lib/services/debank/utils.d.ts +50 -0
  287. package/lib/services/debank/utils.js +325 -0
  288. package/lib/services/layerzero/deposits.d.ts +55 -0
  289. package/lib/services/layerzero/deposits.js +174 -0
  290. package/lib/services/layerzero/redeems.d.ts +20 -0
  291. package/lib/services/layerzero/redeems.js +92 -0
  292. package/lib/services/layerzero/utils.d.ts +9 -0
  293. package/lib/services/layerzero/utils.js +22 -0
  294. package/lib/services/octavfi/fetcher.d.ts +33 -0
  295. package/lib/services/octavfi/fetcher.js +39 -0
  296. package/lib/services/octavfi/index.d.ts +3 -0
  297. package/lib/services/octavfi/index.js +20 -0
  298. package/lib/services/octavfi/types.d.ts +34 -0
  299. package/lib/services/octavfi/types.js +3 -0
  300. package/lib/services/octavfi/utils.d.ts +16 -0
  301. package/lib/services/octavfi/utils.js +244 -0
  302. package/lib/services/subgraph/fetcher.d.ts +2 -0
  303. package/lib/services/subgraph/fetcher.js +66 -0
  304. package/lib/services/subgraph/index.d.ts +2 -0
  305. package/lib/services/subgraph/index.js +19 -0
  306. package/lib/services/subgraph/schema.d.ts +48 -0
  307. package/lib/services/subgraph/schema.js +87 -0
  308. package/lib/services/subgraph/vaults.d.ts +83 -0
  309. package/lib/services/subgraph/vaults.js +1282 -0
  310. package/lib/services/swap-quotes/index.d.ts +105 -0
  311. package/lib/services/swap-quotes/index.js +77 -0
  312. package/lib/services/swap-quotes/paraswap.d.ts +51 -0
  313. package/lib/services/swap-quotes/paraswap.js +138 -0
  314. package/lib/services/untangled/fetcher.d.ts +40 -0
  315. package/lib/services/untangled/fetcher.js +110 -0
  316. package/lib/services/untangled/index.d.ts +3 -0
  317. package/lib/services/untangled/index.js +20 -0
  318. package/lib/services/untangled/types.d.ts +83 -0
  319. package/lib/services/untangled/types.js +10 -0
  320. package/lib/services/untangled/utils.d.ts +91 -0
  321. package/lib/services/untangled/utils.js +339 -0
  322. package/lib/types/api.d.ts +498 -0
  323. package/lib/types/api.js +3 -0
  324. package/lib/types/index.d.ts +12 -0
  325. package/lib/types/index.js +28 -0
  326. package/lib/types/points.d.ts +28 -0
  327. package/lib/types/points.js +3 -0
  328. package/lib/types/pools.d.ts +144 -0
  329. package/lib/types/pools.js +3 -0
  330. package/lib/types/staking.d.ts +28 -0
  331. package/lib/types/staking.js +3 -0
  332. package/lib/types/sub-accounts.d.ts +150 -0
  333. package/lib/types/sub-accounts.js +3 -0
  334. package/lib/types/subgraph.d.ts +84 -0
  335. package/lib/types/subgraph.js +3 -0
  336. package/lib/types/typed-contract.d.ts +102 -0
  337. package/lib/types/typed-contract.js +3 -0
  338. package/lib/types/user.d.ts +1 -0
  339. package/lib/types/user.js +3 -0
  340. package/lib/types/vaults.d.ts +886 -0
  341. package/lib/types/vaults.js +30 -0
  342. package/lib/types/web3.d.ts +81 -0
  343. package/lib/types/web3.js +14 -0
  344. package/lib/types/webserver.d.ts +730 -0
  345. package/lib/types/webserver.js +3 -0
  346. package/package.json +78 -3
@@ -0,0 +1,696 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.getSDKVersion = getSDKVersion;
4
+ exports.resetErrorDedupe = resetErrorDedupe;
5
+ exports.initializeSentry = initializeSentry;
6
+ exports.updateUser = updateUser;
7
+ exports.clearUser = clearUser;
8
+ exports.isAnalyticsEnabled = isAnalyticsEnabled;
9
+ exports.getSpanAttributes = getSpanAttributes;
10
+ exports.getSentry = getSentry;
11
+ exports.resetAnalytics = resetAnalytics;
12
+ exports.captureSdkException = captureSdkException;
13
+ const logger_1 = require("../logger");
14
+ const app_name_1 = require("./app-name");
15
+ const constants_1 = require("./constants");
16
+ const env_1 = require("./env");
17
+ const sentry_runtime_1 = require("./sentry-runtime");
18
+ const user_identity_1 = require("./user-identity");
19
+ /** Track initialization state */
20
+ let isInitialized = false;
21
+ /** Track if analytics is enabled */
22
+ let isEnabled = true;
23
+ /** Current user identity */
24
+ let currentIdentity = null;
25
+ /** Cached API key for identity updates */
26
+ let cachedApiKey;
27
+ /** Identity tags resolved at init, mirrored onto every `sdk.method` span. */
28
+ let spanAttributes = {};
29
+ /**
30
+ * The Upshift SDK build version, read from the generated `version.ts`.
31
+ * Falls back to `'development'` in an unbuilt checkout, where that file does
32
+ * not exist. Shared by the Sentry `release` tag and the
33
+ * `x-august-sdk-version` request header so the two can never disagree.
34
+ *
35
+ * @internal
36
+ */
37
+ function getSDKVersion() {
38
+ try {
39
+ // version.ts is generated at publish time and gitignored
40
+ return require('./version').SDK_VERSION || 'development';
41
+ }
42
+ catch {
43
+ // version.ts doesn't exist in dev - use fallback
44
+ return 'development';
45
+ }
46
+ }
47
+ /**
48
+ * Safely set a Sentry tag. Silently fails on error.
49
+ */
50
+ function safeSetTag(key, value) {
51
+ try {
52
+ const sdk = (0, sentry_runtime_1.getSentrySDK)();
53
+ sdk?.setTag(key, value);
54
+ }
55
+ catch {
56
+ // Silently fail - analytics should never break SDK
57
+ }
58
+ }
59
+ /**
60
+ * Safely set Sentry user. Silently fails on error.
61
+ */
62
+ function safeSetUser(user) {
63
+ try {
64
+ const sdk = (0, sentry_runtime_1.getSentrySDK)();
65
+ sdk?.setUser(user);
66
+ }
67
+ catch {
68
+ // Silently fail - analytics should never break SDK
69
+ }
70
+ }
71
+ /**
72
+ * Chains whose errors are dropped before reaching Sentry.
73
+ *
74
+ * Mezo is muted by request: its public dRPC endpoint is unreliable enough that
75
+ * its failures dominated the error stream without ever describing an SDK
76
+ * defect. This is a deliberate blind spot — Mezo bugs (bad vault data, reverts,
77
+ * decode failures) are silenced along with the transport noise. Remove the
78
+ * entry to restore reporting; nothing else needs to change.
79
+ *
80
+ * Keyed by both the `chainIdToTagValue` slug and the numeric chain ID, because
81
+ * the two arrive on different events.
82
+ */
83
+ const MUTED_CHAIN_SLUGS = new Set(['mezo']);
84
+ /** Numeric chain IDs matching {@link MUTED_CHAIN_SLUGS}. */
85
+ const MUTED_CHAIN_IDS = new Set(['31612']);
86
+ /**
87
+ * Substrings that identify an event as Mezo-related regardless of tags.
88
+ *
89
+ * Tag-based matching alone is not enough: `sdk.chain` / `sdk.last_chainId`
90
+ * record the last *instrumented method's* chain, not the chain of the RPC that
91
+ * actually failed — the production Mezo batch-rejection events are tagged
92
+ * `sdk.chain: ethereum` while carrying `"requestUrl": "https://mezo.drpc.org"`
93
+ * in the message. Matching the message body catches those.
94
+ */
95
+ const MUTED_CHAIN_MESSAGE_PATTERNS = [/mezo/i];
96
+ /**
97
+ * Whether an event belongs to a muted chain and must not be sent.
98
+ *
99
+ * Checks, in order: the chain tags, then the event message and every exception
100
+ * value/type in the chain (an RPC failure's identifying detail often lives in a
101
+ * wrapped inner error rather than the top-level message).
102
+ *
103
+ * @param event - The Sentry event about to be sent.
104
+ * @returns `true` when the event should be dropped.
105
+ */
106
+ function isMutedChainEvent(event) {
107
+ const chainTag = event.tags?.['sdk.chain'];
108
+ if (typeof chainTag === 'string' && MUTED_CHAIN_SLUGS.has(chainTag)) {
109
+ return true;
110
+ }
111
+ const chainIdTag = event.tags?.['sdk.last_chainId'];
112
+ if (typeof chainIdTag === 'string' && MUTED_CHAIN_IDS.has(chainIdTag)) {
113
+ return true;
114
+ }
115
+ const haystacks = [];
116
+ if (typeof event.message === 'string')
117
+ haystacks.push(event.message);
118
+ for (const exception of event.exception?.values ?? []) {
119
+ if (typeof exception.value === 'string')
120
+ haystacks.push(exception.value);
121
+ if (typeof exception.type === 'string')
122
+ haystacks.push(exception.type);
123
+ }
124
+ return haystacks.some((text) => MUTED_CHAIN_MESSAGE_PATTERNS.some((pattern) => pattern.test(text)));
125
+ }
126
+ /**
127
+ * Rolling window, in milliseconds, over which identical errors are counted.
128
+ */
129
+ const ERROR_DEDUPE_WINDOW_MS = 60_000;
130
+ /**
131
+ * Maximum captures of one error signature per {@link ERROR_DEDUPE_WINDOW_MS}.
132
+ * Chosen so a genuine, ongoing failure is still visible (and its rate
133
+ * observable via `sdk.suppressed_since_last`) while a hot loop hammering a
134
+ * broken RPC or a 404-per-borrower fan-out cannot bill thousands of identical
135
+ * events. Beyond this, further captures in the window are dropped.
136
+ */
137
+ const ERROR_DEDUPE_MAX_PER_WINDOW = 3;
138
+ /** Hard cap on tracked signatures, so the map cannot grow without bound. */
139
+ const ERROR_DEDUPE_MAX_KEYS = 500;
140
+ /**
141
+ * Per-signature capture bookkeeping for the dedupe window.
142
+ *
143
+ * Deliberately process-global, matching the Sentry client it feeds: the client
144
+ * is a singleton, so every `UpshiftSDK` instance in the process shares one
145
+ * event stream and one quota. The signature intentionally omits partner/app
146
+ * identity — a host serving several partners reports an identical upstream
147
+ * failure ≤{@link ERROR_DEDUPE_MAX_PER_WINDOW} times per window in aggregate,
148
+ * not per partner, because the failure is one event regardless of how many
149
+ * tenants observed it. Per-tenant attribution comes from the `partner.id` tag
150
+ * on the events that are sent, and `sdk.suppressed_since_last` preserves the
151
+ * true rate. `resetAnalytics()` clears this map for the whole process.
152
+ */
153
+ const errorDedupeState = new Map();
154
+ /**
155
+ * Strip the per-request variables out of an error message.
156
+ *
157
+ * Truncating at 120 characters is not enough on its own: the variable part is
158
+ * usually a vault or wallet address near the FRONT of the message
159
+ * (`Request timeout after 90s: /subaccount/0x3F13…/otc_positions`), so one
160
+ * failure mode still produced a distinct signature — and therefore its own
161
+ * private rate-limit allowance and its own Sentry issue — per address. That is
162
+ * how a single backend timeout became 5k events across a dozen issues in a day.
163
+ *
164
+ * Placeholders are kept structural (`/subaccount/<addr>/otc_positions`) so
165
+ * genuinely different endpoints and failure modes stay separate.
166
+ *
167
+ * @param message - The raw error message.
168
+ * @returns The message with addresses, numbers, and query strings masked.
169
+ */
170
+ function normalizeErrorMessage(message) {
171
+ return message
172
+ .replace(/0x[0-9a-fA-F]{6,}/g, '<addr>')
173
+ .replace(/\?[^\s]*/g, '')
174
+ .replace(/\b\d{4,}\b/g, '<n>');
175
+ }
176
+ /**
177
+ * Build a low-cardinality signature for an error.
178
+ *
179
+ * The message is normalized (see {@link normalizeErrorMessage}) and then capped
180
+ * at 120 characters — enough to separate distinct failure modes without
181
+ * splitting one failure mode into thousands of unique keys.
182
+ *
183
+ * @param error - The normalized error being captured.
184
+ * @param origin - The `sdk.origin` call-site tag, when present.
185
+ * @returns A stable key identifying this class of failure.
186
+ */
187
+ function errorSignature(error, origin) {
188
+ const tag = typeof origin === 'string' ? origin : '';
189
+ const message = normalizeErrorMessage(error.message || '').slice(0, 120);
190
+ return `${tag}|${error.name}|${message}`;
191
+ }
192
+ /**
193
+ * Decide whether an error should be sent to Sentry, applying a per-signature
194
+ * rolling rate limit.
195
+ *
196
+ * Why this exists: the SDK is called from server-rendered pages that fan out
197
+ * per vault and per borrower, so a single upstream condition (a 502 from the
198
+ * backend, an RPC rejecting a batch) reproduces on every iteration of every
199
+ * request. Those are the same event, and paying Sentry per copy buys no extra
200
+ * signal.
201
+ *
202
+ * Side effect: mutates {@link errorDedupeState}.
203
+ *
204
+ * @param error - The normalized error about to be captured.
205
+ * @param origin - The `sdk.origin` call-site tag, when present.
206
+ * @returns `send: false` to drop the event. When `send: true`, `suppressed` is
207
+ * the number of copies dropped since the last event that was sent, and is
208
+ * attached to the outgoing event so the true rate stays recoverable.
209
+ */
210
+ function admitError(error, origin) {
211
+ const key = errorSignature(error, origin);
212
+ const now = Date.now();
213
+ const entry = errorDedupeState.get(key);
214
+ // Touch the key on every access so iteration order is true
215
+ // least-recently-used, not first-inserted: a Map's `set` on an existing key
216
+ // does NOT reorder it, so without the delete a signature that keeps
217
+ // recurring would hold its original position and be evicted ahead of a stale
218
+ // one-shot signature registered after it — silently handing the hot
219
+ // signature a fresh allowance every time it churned out of the map.
220
+ errorDedupeState.delete(key);
221
+ if (!entry || now - entry.windowStart >= ERROR_DEDUPE_WINDOW_MS) {
222
+ // Bound the map: drop the least-recently-used signature before inserting.
223
+ if (errorDedupeState.size >= ERROR_DEDUPE_MAX_KEYS) {
224
+ const oldest = errorDedupeState.keys().next();
225
+ if (!oldest.done)
226
+ errorDedupeState.delete(oldest.value);
227
+ }
228
+ const suppressed = entry?.suppressed ?? 0;
229
+ errorDedupeState.set(key, { windowStart: now, captured: 1, suppressed: 0 });
230
+ return { send: true, suppressed };
231
+ }
232
+ errorDedupeState.set(key, entry);
233
+ if (entry.captured < ERROR_DEDUPE_MAX_PER_WINDOW) {
234
+ // `suppressed` can only be non-zero once the allowance is exhausted, so
235
+ // inside the allowance there is never a carried count to report.
236
+ entry.captured += 1;
237
+ return { send: true, suppressed: 0 };
238
+ }
239
+ entry.suppressed += 1;
240
+ return { send: false, suppressed: entry.suppressed };
241
+ }
242
+ /**
243
+ * Clear the error dedupe bookkeeping. Test-only — the rate limiter is process
244
+ * lifetime state and would otherwise leak between test cases.
245
+ *
246
+ * @internal
247
+ */
248
+ function resetErrorDedupe() {
249
+ errorDedupeState.clear();
250
+ }
251
+ /**
252
+ * Build the SDK's internal Sentry sink — the bridge that forwards
253
+ * `Logger.log.*` output to the resolved Sentry SDK. Errors are captured as
254
+ * issues; warnings are recorded as breadcrumbs (see the severity policy on
255
+ * `SDKSentrySink`). The SDK reference is resolved lazily on each call so the
256
+ * sink tracks runtime swaps and stays correct under the test harness's mock.
257
+ *
258
+ * Every method is fully wrapped: a telemetry failure must never propagate back
259
+ * into the caller that was only trying to log.
260
+ */
261
+ function createSentrySink() {
262
+ return {
263
+ captureException(error, context) {
264
+ try {
265
+ const sdk = (0, sentry_runtime_1.getSentrySDK)();
266
+ if (!sdk)
267
+ return;
268
+ const normalized = error instanceof Error ? error : new Error(String(error));
269
+ // Rate-limit identical failures before touching Sentry at all — the
270
+ // scope work and the event payload are both wasted if it is dropped.
271
+ const admission = admitError(normalized, context?.tag);
272
+ if (!admission.send)
273
+ return;
274
+ sdk.withScope((scope) => {
275
+ // `beforeSend` drops any event not tagged as ours; the tag is global
276
+ // already, but set it on the scope defensively in case a future
277
+ // Sentry version starts withScope() from a clean slate.
278
+ scope.setTag('sdk', 'august-digital');
279
+ if (context) {
280
+ for (const [key, value] of Object.entries(context)) {
281
+ // Promote the call-site label (e.g. 'getVault:loans') to a
282
+ // scoped tag for grouping/filtering. Cardinality is bounded by
283
+ // the number of Logger call sites (~150) and the tag is
284
+ // event-scoped, not a global sticky tag — so it does not run
285
+ // afoul of the bounded-tag rule in CLAUDE.md §8.4.
286
+ if (key === 'tag' && typeof value === 'string') {
287
+ scope.setTag('sdk.origin', value);
288
+ }
289
+ else {
290
+ scope.setExtra(key, value);
291
+ }
292
+ }
293
+ }
294
+ // Preserve the true failure rate even though copies were dropped.
295
+ if (admission.suppressed > 0) {
296
+ scope.setExtra('sdk.suppressed_since_last', admission.suppressed);
297
+ }
298
+ // Group by the same normalized signature the rate limiter uses.
299
+ // Sentry's default grouping keys on the raw message, so one backend
300
+ // timeout fans out into an issue per vault/wallet address — the
301
+ // per-issue notification volume that flooded the on-call webhook.
302
+ // Addresses stay recoverable from the event message and tags.
303
+ scope.setFingerprint?.([
304
+ 'sdk',
305
+ typeof context?.tag === 'string' ? context.tag : 'untagged',
306
+ normalized.name,
307
+ normalizeErrorMessage(normalized.message || '').slice(0, 120),
308
+ ]);
309
+ sdk.captureException(normalized);
310
+ });
311
+ }
312
+ catch {
313
+ // Telemetry must never break the SDK.
314
+ }
315
+ },
316
+ addBreadcrumb(breadcrumb) {
317
+ try {
318
+ (0, sentry_runtime_1.getSentrySDK)()?.addBreadcrumb(breadcrumb);
319
+ }
320
+ catch {
321
+ // Telemetry must never break the SDK.
322
+ }
323
+ },
324
+ };
325
+ }
326
+ /**
327
+ * Initialize Sentry with SDK-specific configuration. Idempotent: re-calls
328
+ * only refresh user identity and the cached API-key hash.
329
+ *
330
+ * Breaking change in v9: `appName` moved from the optional fifth parameter
331
+ * to the required third parameter, so every telemetry stream carries an
332
+ * application identity (the `UpshiftSDK` constructor has required it since
333
+ * v5). Callers on the old positional order get a synchronous validation
334
+ * error rather than silently anonymous events.
335
+ *
336
+ * @param config - Analytics configuration. Pass `tracesSampleRate` to
337
+ * override the default of `0.1`, and `surface` to label the emitting
338
+ * surface (`sdk.surface` tag; defaults to `'sdk'`).
339
+ * @param environment - Current environment (DEV or PROD).
340
+ * @param appName - App-name slug, required. Set as the global `app.name`
341
+ * tag on every event and used to derive `partner.id`. Identifier-shaped:
342
+ * 3–64 chars, `[a-zA-Z0-9._-]` only, and not an EVM address — the same
343
+ * rules the `UpshiftSDK` constructor enforces.
344
+ * @param walletAddress - Optional wallet address for user identification.
345
+ * @param apiKey - Optional API key (hashed for identification).
346
+ * @throws UpshiftValidationError (code `INVALID_INPUT`) when `appName` is
347
+ * missing, empty, mis-typed, out of the allowed length range, contains
348
+ * disallowed characters, or is shaped like an EVM address. Thrown before
349
+ * any analytics state mutates, even when analytics would be disabled by
350
+ * config or environment gates.
351
+ */
352
+ function initializeSentry(config, environment, appName, walletAddress, apiKey) {
353
+ // Enforce the identity contract before anything else — including the
354
+ // idempotency short-circuit and the disable gates — so a bad appName is
355
+ // equally loud on every call path and in every environment.
356
+ const validatedAppName = (0, app_name_1.validateAppName)(appName);
357
+ // SDK construction runs this multiple times (base + adapter constructors).
358
+ // Short-circuit so the disable-reason logs only once per process.
359
+ if (isInitialized) {
360
+ if (isEnabled) {
361
+ // Refresh cached apiKey before updateUser — otherwise a second SDK
362
+ // instance built with a different key is attributed to the first hash.
363
+ if (apiKey !== undefined && apiKey !== cachedApiKey) {
364
+ cachedApiKey = apiKey;
365
+ updateUser(walletAddress, environment);
366
+ }
367
+ else if (walletAddress !== currentIdentity?.walletAddress ||
368
+ environment !== currentIdentity?.environment) {
369
+ updateUser(walletAddress, environment);
370
+ }
371
+ }
372
+ return;
373
+ }
374
+ // Constructor config wins outright — no env override can re-enable it.
375
+ if (config.enabled === false) {
376
+ isEnabled = false;
377
+ isInitialized = true;
378
+ logger_1.Logger.log.info('analytics.disabled', { reason: 'config' });
379
+ return;
380
+ }
381
+ const forced = (0, env_1.isAnalyticsForcedOnViaEnv)();
382
+ if (!forced && (0, env_1.isAnalyticsDisabledViaEnv)()) {
383
+ isEnabled = false;
384
+ isInitialized = true;
385
+ logger_1.Logger.log.info('analytics.disabled', {
386
+ reason: 'UPSHIFT_SDK_DISABLE_ANALYTICS',
387
+ });
388
+ return;
389
+ }
390
+ if (!forced && (0, env_1.isNodeDevOrTestEnv)()) {
391
+ isEnabled = false;
392
+ isInitialized = true;
393
+ logger_1.Logger.log.info('analytics.disabled', {
394
+ reason: 'NODE_ENV',
395
+ nodeEnv: (0, env_1.readEnv)('NODE_ENV'),
396
+ hint: 'set UPSHIFT_SDK_FORCE_ANALYTICS=1 to override',
397
+ });
398
+ return;
399
+ }
400
+ if (!forced && (0, env_1.isLocalhost)()) {
401
+ isEnabled = false;
402
+ isInitialized = true;
403
+ logger_1.Logger.log.info('analytics.disabled', { reason: 'localhost' });
404
+ return;
405
+ }
406
+ cachedApiKey = apiKey;
407
+ try {
408
+ const sdk = (0, sentry_runtime_1.getSentrySDK)();
409
+ if (!sdk) {
410
+ // Both @sentry/node and @sentry/browser failed to resolve. Surface this
411
+ // because the alternative is silent telemetry loss.
412
+ logger_1.Logger.log.warn('analytics.init.sentry-unavailable', {
413
+ runtime: (0, sentry_runtime_1.getSentryRuntime)(),
414
+ hint: 'Confirm @sentry/browser (or @sentry/node) is installed and reachable.',
415
+ });
416
+ isEnabled = false;
417
+ return;
418
+ }
419
+ // Clamp to Sentry's accepted [0, 1] so a typo'd rate doesn't silently
420
+ // reject the init.
421
+ const rawSampleRate = typeof config.tracesSampleRate === 'number' &&
422
+ Number.isFinite(config.tracesSampleRate)
423
+ ? config.tracesSampleRate
424
+ : 0.1; // Phase 2 default — verified partners can opt into 1.0 explicitly
425
+ const tracesSampleRate = Math.max(0, Math.min(1, rawSampleRate));
426
+ // Hoisted so `release`, `august.sdk_version`, and the deprecated
427
+ // `sdk.version` are provably the same value rather than three separate
428
+ // reads of `./version`.
429
+ const sdkVersion = getSDKVersion();
430
+ sdk.init({
431
+ dsn: constants_1.SENTRY_DSN,
432
+ tracesSampleRate,
433
+ enableTracing: true,
434
+ environment: environment.toLowerCase(),
435
+ release: `august-sdk@${sdkVersion}`,
436
+ sendDefaultPii: true,
437
+ // SDK errors route through Logger.setSentrySink → captureException directly,
438
+ // so captureConsoleIntegration is redundant here. Omitting it also prevents
439
+ // consumer app console.error calls from being billed as SDK error events (the
440
+ // global sdk:'august-digital' tag would otherwise cause them to pass beforeSend).
441
+ integrations: [],
442
+ // Drop classes of event that are never SDK signal, as a backstop to the
443
+ // call-site demotions (see `logChainError` / `isUserRejectionError`).
444
+ // Scope is deliberately narrow: only categories that are noise in EVERY
445
+ // code path. Generic contract reverts (`CALL_EXCEPTION` / "missing revert
446
+ // data") are intentionally NOT listed — a reverted *write* tx is a real
447
+ // error we keep at `error` level, and only read-path reverts are demoted
448
+ // (surgically, at the call site).
449
+ ignoreErrors: [
450
+ // Wallet user-rejections are normal product behaviour, not an SDK fault.
451
+ /user rejected/i,
452
+ /user denied/i,
453
+ 'ACTION_REJECTED',
454
+ // Local dev/test node leaking into a prod DSN: :8545 is the canonical
455
+ // Anvil/Hardhat port and is never a production RPC endpoint.
456
+ /ECONNREFUSED .*:8545/,
457
+ // UpshiftHistoryUnavailableError is a designed, documented outcome:
458
+ // the getter refuses to return a fabricated number when the indexer
459
+ // has no deposit/withdrawal history. It is thrown to the caller, who
460
+ // renders "temporarily unavailable" — the SDK is behaving correctly,
461
+ // so it is not an SDK issue. Indexer health is monitored separately.
462
+ /transaction history unavailable/i,
463
+ ],
464
+ beforeSend(event) {
465
+ // Only send events tagged as SDK-related
466
+ if (event.tags?.sdk !== 'august-digital') {
467
+ return null;
468
+ }
469
+ // Muted chains (see MUTED_CHAIN_SLUGS) are dropped wholesale.
470
+ if (isMutedChainEvent(event)) {
471
+ return null;
472
+ }
473
+ return event;
474
+ },
475
+ });
476
+ // Set initial user identity
477
+ updateUser(walletAddress, environment);
478
+ // Set global SDK tags
479
+ safeSetTag('sdk', 'august-digital');
480
+ // `august.sdk_version` is the queryable dimension for "which SDK build is
481
+ // this partner on" — the question that decides whether an error is a live
482
+ // defect or an already-shipped fix the consumer hasn't picked up.
483
+ //
484
+ // It exists because `sdk.version` (set below, kept for back-compat) is a
485
+ // RESERVED Sentry field: Sentry populates it with the version of its own
486
+ // client (`@sentry/core`). The custom tag is still stored, but a bare
487
+ // `sdk.version` in Discover resolves to Sentry's value, so the natural
488
+ // query silently answers the wrong question — uniform across every
489
+ // consumer, which makes it look like a working answer. Reaching the real
490
+ // value requires `tags[sdk.version]`, which nobody remembers to type.
491
+ //
492
+ // Both are low-cardinality version strings, so carrying the pair costs
493
+ // nothing against the tag budget (CLAUDE.md §8.4).
494
+ safeSetTag('august.sdk_version', sdkVersion);
495
+ /**
496
+ * @deprecated Shadowed by Sentry's reserved `sdk.version` field. Query
497
+ * `august.sdk_version` instead. Retained so existing saved queries,
498
+ * dashboards, and alert rules keep resolving; remove in the next major.
499
+ */
500
+ safeSetTag('sdk.version', sdkVersion);
501
+ const runtime = (0, sentry_runtime_1.getSentryRuntime)();
502
+ safeSetTag('sdk.runtime', runtime);
503
+ // `app.name` is the dimension we filter on in Sentry to attribute
504
+ // events to a specific consuming application — see SDK quickstart docs.
505
+ safeSetTag('app.name', validatedAppName);
506
+ // `unverified:` prefix until the backend API-key → partner-id endpoint exists.
507
+ const partnerId = `unverified:${validatedAppName}`;
508
+ safeSetTag('partner.id', partnerId);
509
+ // First-party apps are labelled so `partner.tier:unverified` already
510
+ // means "external integrator" before verification exists.
511
+ const partnerTier = constants_1.FIRST_PARTY_APP_NAMES.has(validatedAppName)
512
+ ? 'internal'
513
+ : 'unverified';
514
+ safeSetTag('partner.tier', partnerTier);
515
+ const surface = config.surface ?? 'sdk';
516
+ safeSetTag('sdk.surface', surface);
517
+ // Scope tags land only on the root span of a trace; child `sdk.method`
518
+ // spans get these copied on as attributes by `withMethodTracking`.
519
+ spanAttributes = {
520
+ 'app.name': validatedAppName,
521
+ 'partner.id': partnerId,
522
+ 'partner.tier': partnerTier,
523
+ 'sdk.runtime': runtime,
524
+ 'sdk.surface': surface,
525
+ 'august.sdk_version': sdkVersion,
526
+ };
527
+ // Bridge the SDK's structured logger into Sentry now that the SDK is live.
528
+ // Without this, Logger.log.error/warn are no-ops in production (no
529
+ // SDKLogger/structured logger is wired by default), so SDK-internal
530
+ // diagnostics never reach the dashboard. Errors → issues, warns →
531
+ // breadcrumbs.
532
+ logger_1.Logger.setSentrySink(createSentrySink());
533
+ isInitialized = true;
534
+ logger_1.Logger.log.info('analytics.initialized', {
535
+ runtime: (0, sentry_runtime_1.getSentryRuntime)(),
536
+ hint: 'Disable with { analytics: { enabled: false } } or UPSHIFT_SDK_DISABLE_ANALYTICS=1',
537
+ });
538
+ }
539
+ catch (err) {
540
+ logger_1.Logger.log.warn('analytics.init.failed', {
541
+ runtime: (0, sentry_runtime_1.getSentryRuntime)(),
542
+ error: err instanceof Error ? err.message : String(err),
543
+ });
544
+ isEnabled = false;
545
+ }
546
+ }
547
+ /**
548
+ * Update the current user identity in Sentry.
549
+ * Called when wallet address changes.
550
+ *
551
+ * @param walletAddress - New wallet address (or undefined to clear)
552
+ * @param environment - Current environment
553
+ */
554
+ function updateUser(walletAddress, environment = 'PROD') {
555
+ if (!isEnabled)
556
+ return;
557
+ try {
558
+ currentIdentity = (0, user_identity_1.createUserIdentity)(cachedApiKey, walletAddress, environment);
559
+ const userId = (0, user_identity_1.getUserId)(currentIdentity);
560
+ safeSetUser({
561
+ id: userId,
562
+ username: userId, // Duplicate to username which is less likely to be filtered
563
+ ip_address: '{{auto}}',
564
+ data: {
565
+ userId, // Also store in data for redundancy
566
+ sessionId: currentIdentity.sessionId,
567
+ fingerprint: currentIdentity.fingerprint,
568
+ hasWallet: !!walletAddress,
569
+ hasApiKey: !!currentIdentity.apiKeyHash,
570
+ environment: currentIdentity.environment,
571
+ walletAddress: walletAddress || undefined,
572
+ },
573
+ });
574
+ }
575
+ catch {
576
+ // Silently fail
577
+ }
578
+ }
579
+ /**
580
+ * Clear wallet from user identity.
581
+ * Called when user disconnects wallet.
582
+ */
583
+ function clearUser() {
584
+ if (!isEnabled)
585
+ return;
586
+ try {
587
+ const environment = currentIdentity?.environment || 'PROD';
588
+ currentIdentity = (0, user_identity_1.createUserIdentity)(cachedApiKey, undefined, environment);
589
+ const userId = (0, user_identity_1.getUserId)(currentIdentity);
590
+ safeSetUser({
591
+ id: userId,
592
+ username: userId,
593
+ ip_address: '{{auto}}',
594
+ data: {
595
+ userId,
596
+ sessionId: currentIdentity.sessionId,
597
+ fingerprint: currentIdentity.fingerprint,
598
+ hasWallet: false,
599
+ hasApiKey: !!currentIdentity.apiKeyHash,
600
+ environment: currentIdentity.environment,
601
+ },
602
+ });
603
+ }
604
+ catch {
605
+ // Silently fail
606
+ }
607
+ }
608
+ /**
609
+ * Check if analytics is enabled and initialized.
610
+ */
611
+ function isAnalyticsEnabled() {
612
+ return isEnabled && isInitialized;
613
+ }
614
+ /**
615
+ * Identity tags resolved by `initializeSentry`, for `withMethodTracking` to
616
+ * copy onto each span as attributes. Sentry's span dataset carries scope tags
617
+ * on the root span only, so without this copy child `sdk.method` rows cannot
618
+ * be filtered by `app.name` or `partner.id`.
619
+ *
620
+ * @returns The tag snapshot, or `{}` until analytics has been enabled.
621
+ * @internal
622
+ */
623
+ function getSpanAttributes() {
624
+ return spanAttributes;
625
+ }
626
+ /**
627
+ * Get the current Sentry instance for advanced usage.
628
+ * Returns null if analytics is disabled.
629
+ */
630
+ function getSentry() {
631
+ if (!isAnalyticsEnabled())
632
+ return null;
633
+ return (0, sentry_runtime_1.getSentrySDK)();
634
+ }
635
+ /**
636
+ * Reset analytics state (useful for testing).
637
+ */
638
+ function resetAnalytics() {
639
+ isInitialized = false;
640
+ isEnabled = true;
641
+ currentIdentity = null;
642
+ cachedApiKey = undefined;
643
+ spanAttributes = {};
644
+ logger_1.Logger.setSentrySink(null);
645
+ (0, sentry_runtime_1.resetSentryRuntime)();
646
+ // The error rate limiter is process-lifetime state; a reset analytics layer
647
+ // must not inherit a half-full dedupe window from the previous one.
648
+ resetErrorDedupe();
649
+ }
650
+ /**
651
+ * Capture an exception into Sentry with SDK-specific context. Use from
652
+ * top-level error handlers (CLI, middleware, unhandled rejections) to
653
+ * report failures that don't flow through the auto-instrumented method
654
+ * surface. No-ops when analytics is disabled.
655
+ *
656
+ * @param error - Thrown value. Non-Error values are wrapped.
657
+ * @param options - `surface` ('cli' | 'mcp' | 'sdk' | 'react' | string)
658
+ * overriding the init-time `sdk.surface` tag for this event, extra `tags`,
659
+ * `extra` data, and a `flushTimeoutMs` to await before resolving (needed
660
+ * in Node when the process is about to exit).
661
+ */
662
+ async function captureSdkException(error, options) {
663
+ if (!isAnalyticsEnabled())
664
+ return;
665
+ try {
666
+ const sdk = (0, sentry_runtime_1.getSentrySDK)();
667
+ if (!sdk)
668
+ return;
669
+ sdk.withScope((scope) => {
670
+ // Required so `beforeSend` doesn't drop the event.
671
+ scope.setTag('sdk', 'august-digital');
672
+ if (options?.surface) {
673
+ scope.setTag('sdk.surface', options.surface);
674
+ }
675
+ if (options?.tags) {
676
+ for (const [k, v] of Object.entries(options.tags)) {
677
+ scope.setTag(k, v);
678
+ }
679
+ }
680
+ if (options?.extra) {
681
+ for (const [k, v] of Object.entries(options.extra)) {
682
+ scope.setExtra(k, v);
683
+ }
684
+ }
685
+ const normalized = error instanceof Error ? error : new Error(String(error));
686
+ sdk.captureException(normalized);
687
+ });
688
+ if (options?.flushTimeoutMs && options.flushTimeoutMs > 0) {
689
+ await sdk.flush(options.flushTimeoutMs);
690
+ }
691
+ }
692
+ catch {
693
+ // Silently fail - analytics should never block error propagation
694
+ }
695
+ }
696
+ //# sourceMappingURL=sentry.js.map