@merkl/api 0.10.129 → 0.10.131

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 (361) hide show
  1. package/dist/database/api/.generated/default.js +1 -0
  2. package/dist/database/api/.generated/edge.js +609 -0
  3. package/dist/database/api/.generated/index-browser.js +586 -0
  4. package/dist/database/api/.generated/index.js +638 -0
  5. package/dist/database/api/.generated/runtime/edge-esm.js +31 -0
  6. package/dist/database/api/.generated/runtime/edge.js +31 -0
  7. package/dist/database/api/.generated/runtime/index-browser.js +13 -0
  8. package/dist/database/api/.generated/runtime/library.js +143 -0
  9. package/dist/database/api/.generated/runtime/react-native.js +80 -0
  10. package/dist/database/api/.generated/runtime/wasm.js +32 -0
  11. package/dist/database/api/.generated/wasm.js +586 -0
  12. package/dist/database/api/seeder/resources/protocol.js +341 -0
  13. package/dist/database/engine/.generated/default.js +1 -0
  14. package/dist/database/engine/.generated/edge.js +438 -0
  15. package/dist/database/engine/.generated/index-browser.js +415 -0
  16. package/dist/database/engine/.generated/index.js +467 -0
  17. package/dist/database/engine/.generated/runtime/edge-esm.js +31 -0
  18. package/dist/database/engine/.generated/runtime/edge.js +31 -0
  19. package/dist/database/engine/.generated/runtime/index-browser.js +13 -0
  20. package/dist/database/engine/.generated/runtime/library.js +143 -0
  21. package/dist/database/engine/.generated/runtime/react-native.js +80 -0
  22. package/dist/database/engine/.generated/runtime/wasm.js +32 -0
  23. package/dist/database/engine/.generated/wasm.js +415 -0
  24. package/dist/src/backgroundJobs/index.js +44 -0
  25. package/dist/src/backgroundJobs/jobs/campaignsCacheUpdater.js +160 -0
  26. package/dist/src/backgroundJobs/jobs/health.js +15 -0
  27. package/dist/src/backgroundJobs/jobs/opportunityUpdater.js +63 -0
  28. package/dist/src/backgroundJobs/jobs/priceUpdater.js +16 -0
  29. package/dist/src/backgroundJobs/jobs/sync.js +33 -0
  30. package/dist/src/cache/declaration.js +146 -0
  31. package/dist/src/cache/index.js +152 -0
  32. package/dist/src/cache/redis.js +49 -0
  33. package/dist/src/constants.js +119 -0
  34. package/dist/src/entities/campaign.js +134 -0
  35. package/dist/src/entities/opportunity.js +549 -0
  36. package/dist/src/errors/BadRequest.error.js +7 -0
  37. package/dist/src/errors/Conflict.error.js +7 -0
  38. package/dist/src/errors/HttpError.js +11 -0
  39. package/dist/src/errors/NotFound.error.js +7 -0
  40. package/dist/src/errors/Opportunity.error.js +11 -0
  41. package/dist/src/errors/Unauthorized.error.js +7 -0
  42. package/dist/src/errors/index.js +5 -0
  43. package/dist/src/guards/BackOffice.guard.js +10 -0
  44. package/dist/src/guards/Engine.guard.js +10 -0
  45. package/dist/src/guards/TokenAuth.guard.js +10 -0
  46. package/dist/src/hooks/checkQueryAddressValidity.js +7 -0
  47. package/dist/src/hooks/checkQueryChainIdValidity.js +7 -0
  48. package/dist/src/index.js +79 -0
  49. package/dist/src/internal/controllers/endingCampaigns.js +41 -0
  50. package/dist/src/internal/controllers/unclaimed.js +36 -0
  51. package/dist/src/internal/index.js +30 -0
  52. package/dist/src/libs/campaigns/campaignTypes/AjnaDynamicData.js +111 -0
  53. package/dist/src/libs/campaigns/campaignTypes/BadgerDynamicData.js +93 -0
  54. package/dist/src/libs/campaigns/campaignTypes/CLAMMDynamicData.js +942 -0
  55. package/dist/src/libs/campaigns/campaignTypes/CompoundDynamicData.js +90 -0
  56. package/dist/src/libs/campaigns/campaignTypes/DolomiteDynamicData.js +60 -0
  57. package/dist/src/libs/campaigns/campaignTypes/ERC20DynamicData.js +162 -0
  58. package/dist/src/libs/campaigns/campaignTypes/ERC20DynamicDataRefacto.js +159 -0
  59. package/dist/src/libs/campaigns/campaignTypes/ERC20SubTypes/helpers/eulerVaultNames.js +13 -0
  60. package/dist/src/libs/campaigns/campaignTypes/ERC20SubTypes/helpers/factoryFinder.js +29 -0
  61. package/dist/src/libs/campaigns/campaignTypes/ERC20SubTypes/helpers/getBlacklistedSupply.js +22 -0
  62. package/dist/src/libs/campaigns/campaignTypes/ERC20SubTypes/helpers/metamorphoTvl.js +35 -0
  63. package/dist/src/libs/campaigns/campaignTypes/ERC20SubTypes/helpers/spliceTVL.js +21 -0
  64. package/dist/src/libs/campaigns/campaignTypes/ERC20SubTypes/helpers/tokenType.js +106 -0
  65. package/dist/src/libs/campaigns/campaignTypes/ERC20SubTypes/processor/AaveProcessor.js +26 -0
  66. package/dist/src/libs/campaigns/campaignTypes/ERC20SubTypes/processor/AssetProcessor.js +47 -0
  67. package/dist/src/libs/campaigns/campaignTypes/ERC20SubTypes/processor/AuraProcessor.js +103 -0
  68. package/dist/src/libs/campaigns/campaignTypes/ERC20SubTypes/processor/BalancerGaugeProcessor.js +83 -0
  69. package/dist/src/libs/campaigns/campaignTypes/ERC20SubTypes/processor/BalancerPoolProcessor.js +99 -0
  70. package/dist/src/libs/campaigns/campaignTypes/ERC20SubTypes/processor/BeefyProcessor.js +51 -0
  71. package/dist/src/libs/campaigns/campaignTypes/ERC20SubTypes/processor/CompoundProcessor.js +36 -0
  72. package/dist/src/libs/campaigns/campaignTypes/ERC20SubTypes/processor/EnzymeProcessor.js +51 -0
  73. package/dist/src/libs/campaigns/campaignTypes/ERC20SubTypes/processor/EulerBorrowProcessor.js +46 -0
  74. package/dist/src/libs/campaigns/campaignTypes/ERC20SubTypes/processor/EulerLendProcessor.js +47 -0
  75. package/dist/src/libs/campaigns/campaignTypes/ERC20SubTypes/processor/FluidProcessor.js +36 -0
  76. package/dist/src/libs/campaigns/campaignTypes/ERC20SubTypes/processor/FraxProcessor.js +41 -0
  77. package/dist/src/libs/campaigns/campaignTypes/ERC20SubTypes/processor/GearboxProcessor.js +44 -0
  78. package/dist/src/libs/campaigns/campaignTypes/ERC20SubTypes/processor/GenericProcessor.js +239 -0
  79. package/dist/src/libs/campaigns/campaignTypes/ERC20SubTypes/processor/MetamorphoProcessor.js +43 -0
  80. package/dist/src/libs/campaigns/campaignTypes/ERC20SubTypes/processor/PendleProcessor.js +31 -0
  81. package/dist/src/libs/campaigns/campaignTypes/ERC20SubTypes/processor/RadiantProcessor.js +58 -0
  82. package/dist/src/libs/campaigns/campaignTypes/ERC20SubTypes/processor/RfxProcessor.js +64 -0
  83. package/dist/src/libs/campaigns/campaignTypes/ERC20SubTypes/processor/SpliceProcessor.js +35 -0
  84. package/dist/src/libs/campaigns/campaignTypes/ERC20SubTypes/processor/SturdySiloProcessor.js +37 -0
  85. package/dist/src/libs/campaigns/campaignTypes/ERC20SubTypes/processor/TemplateProcessor.js +40 -0
  86. package/dist/src/libs/campaigns/campaignTypes/ERC20SubTypes/processor/TorosProcessor.js +33 -0
  87. package/dist/src/libs/campaigns/campaignTypes/ERC20SubTypes/processor/UniswapProcessor.js +48 -0
  88. package/dist/src/libs/campaigns/campaignTypes/ERC20SubTypes/processor/WoofiProcessor.js +40 -0
  89. package/dist/src/libs/campaigns/campaignTypes/ERC20SubTypes/processor/curveProcessor.js +68 -0
  90. package/dist/src/libs/campaigns/campaignTypes/ERC20SubTypes/processor/processorMapping.js +77 -0
  91. package/dist/src/libs/campaigns/campaignTypes/ERC20SubTypes/subtypesPrices.js +583 -0
  92. package/dist/src/libs/campaigns/campaignTypes/ERC20SubTypes/subtypesPricesRefactoFinal.js +24 -0
  93. package/dist/src/libs/campaigns/campaignTypes/ERC20SubTypes/subtypesRound1.js +1209 -0
  94. package/dist/src/libs/campaigns/campaignTypes/ERC20SubTypes/subtypesRound1RefactoFinal.js +194 -0
  95. package/dist/src/libs/campaigns/campaignTypes/ERC20SubTypes/subtypesRound2.js +645 -0
  96. package/dist/src/libs/campaigns/campaignTypes/ERC20SubTypes/subtypesRound2RefactoFinal.js +22 -0
  97. package/dist/src/libs/campaigns/campaignTypes/ERC20SubTypes/subtypesRound3.js +392 -0
  98. package/dist/src/libs/campaigns/campaignTypes/ERC20SubTypes/subtypesRound3RefactoFinal.js +22 -0
  99. package/dist/src/libs/campaigns/campaignTypes/ERC20SubTypes/subtypesRound4.js +323 -0
  100. package/dist/src/libs/campaigns/campaignTypes/ERC20SubTypes/subtypesRound4RefactoFinal.js +22 -0
  101. package/dist/src/libs/campaigns/campaignTypes/ERC20_SNAPSHOTDynamicData.js +38 -0
  102. package/dist/src/libs/campaigns/campaignTypes/EulerDynamicData.js +165 -0
  103. package/dist/src/libs/campaigns/campaignTypes/JSON_AIRDROPDynamicData.js +19 -0
  104. package/dist/src/libs/campaigns/campaignTypes/MORPHODynamicData.js +120 -0
  105. package/dist/src/libs/campaigns/campaignTypes/RadiantDynamicData.js +112 -0
  106. package/dist/src/libs/campaigns/campaignTypes/SILODynamicData.js +113 -0
  107. package/dist/src/libs/campaigns/campaignsDynamicData.js +83 -0
  108. package/dist/src/libs/campaigns/campaignsDynamicDataRefacto.js +78 -0
  109. package/dist/src/libs/campaigns/getCampaigns.js +18 -0
  110. package/dist/src/libs/campaigns/utils/fetchA51Strategies.js +44 -0
  111. package/dist/src/libs/campaigns/utils/fetchClamInfo.js +27 -0
  112. package/dist/src/libs/campaigns/utils/fetchLogs.js +91 -0
  113. package/dist/src/libs/campaigns/utils/getCompV2ForksVaults.js +122 -0
  114. package/dist/src/libs/campaigns/utils/getContractCreationBlock.js +44 -0
  115. package/dist/src/libs/campaigns/utils/getDolomiteMarkets.js +50 -0
  116. package/dist/src/libs/campaigns/utils/getEulerV2Vaults.js +87 -0
  117. package/dist/src/libs/campaigns/utils/getLastEligibilityRatio.js +56 -0
  118. package/dist/src/libs/computeFee.js +34 -0
  119. package/dist/src/libs/custom/twtParticipants.js +54 -0
  120. package/dist/src/libs/deprecated-merklv3/index.js +184 -0
  121. package/dist/src/libs/getTokensList.js +37 -0
  122. package/dist/src/libs/merklChainData.js +129 -0
  123. package/dist/src/libs/parse/marketsWithCache.js +8 -0
  124. package/dist/src/libs/positions/ajna/index.js +107 -0
  125. package/dist/src/libs/positions/badger/index.js +79 -0
  126. package/dist/src/libs/positions/clamm/index.js +419 -0
  127. package/dist/src/libs/positions/clamm/thegraph/fetchAlmPositions.js +35 -0
  128. package/dist/src/libs/positions/clamm/thegraph/fetchAmmPositions.js +35 -0
  129. package/dist/src/libs/positions/clamm/thegraph/fetchFarmedPositions.js +44 -0
  130. package/dist/src/libs/positions/clamm/thegraph/index.js +162 -0
  131. package/dist/src/libs/positions/compound/index.js +93 -0
  132. package/dist/src/libs/positions/dolomite/index.js +49 -0
  133. package/dist/src/libs/positions/erc20/index.js +55 -0
  134. package/dist/src/libs/positions/euler/index.js +57 -0
  135. package/dist/src/libs/positions/index.js +48 -0
  136. package/dist/src/libs/positions/morpho/index.js +177 -0
  137. package/dist/src/libs/positions/prepareFetch.js +339 -0
  138. package/dist/src/libs/positions/silo/index.js +67 -0
  139. package/dist/src/libs/positions/types.js +1 -0
  140. package/dist/src/libs/reports/campaignReport.js +37 -0
  141. package/dist/src/libs/reports/mainParameterRewards.js +48 -0
  142. package/dist/src/libs/rewards/userRewards.js +154 -0
  143. package/dist/src/libs/staticCampaigns.js +10 -0
  144. package/dist/src/libs/tokens/balances.js +126 -0
  145. package/dist/src/libs/tokens/tokenInfo.js +22 -0
  146. package/dist/src/modules/v4/accounting/accounting.controller.js +66 -0
  147. package/dist/src/modules/v4/accounting/accounting.model.js +32 -0
  148. package/dist/src/modules/v4/accounting/accounting.repository.js +100 -0
  149. package/dist/src/modules/v4/accounting/accounting.service.js +78 -0
  150. package/dist/src/modules/v4/accounting/index.js +3 -0
  151. package/dist/src/modules/v4/apr/apr.controller.js +1 -0
  152. package/dist/src/modules/v4/apr/apr.model.js +1 -0
  153. package/dist/src/modules/v4/apr/apr.repository.js +1 -0
  154. package/dist/src/modules/v4/apr/apr.service.js +40 -0
  155. package/dist/src/modules/v4/apr/index.js +2 -0
  156. package/dist/src/modules/v4/blacklist/blacklist.controller.js +45 -0
  157. package/dist/src/modules/v4/blacklist/blacklist.model.js +13 -0
  158. package/dist/src/modules/v4/blacklist/blacklist.repository.js +56 -0
  159. package/dist/src/modules/v4/blacklist/blacklist.service.js +24 -0
  160. package/dist/src/modules/v4/blacklist/index.js +3 -0
  161. package/dist/src/modules/v4/cache/cache.model.js +14 -0
  162. package/dist/src/modules/v4/cache/cache.repository.js +10 -0
  163. package/dist/src/modules/v4/cache/cache.service.js +44 -0
  164. package/dist/src/modules/v4/cache/index.js +1 -0
  165. package/dist/src/modules/v4/campaign/campaign.controller.js +56 -0
  166. package/dist/src/modules/v4/campaign/campaign.model.js +54 -0
  167. package/dist/src/modules/v4/campaign/campaign.repository.js +346 -0
  168. package/dist/src/modules/v4/campaign/campaign.service.js +203 -0
  169. package/dist/src/modules/v4/campaign/index.js +3 -0
  170. package/dist/src/modules/v4/chain/chain.controller.js +40 -0
  171. package/dist/src/modules/v4/chain/chain.model.js +17 -0
  172. package/dist/src/modules/v4/chain/chain.repository.js +64 -0
  173. package/dist/src/modules/v4/chain/chain.service.js +42 -0
  174. package/dist/src/modules/v4/chain/index.js +3 -0
  175. package/dist/src/modules/v4/dynamicData/dynamicData.controller.js +19 -0
  176. package/dist/src/modules/v4/dynamicData/dynamicData.model.js +6 -0
  177. package/dist/src/modules/v4/dynamicData/dynamicData.repository.js +1 -0
  178. package/dist/src/modules/v4/dynamicData/dynamicData.service.js +49 -0
  179. package/dist/src/modules/v4/dynamicData/index.js +3 -0
  180. package/dist/src/modules/v4/enso/enso.model.js +108 -0
  181. package/dist/src/modules/v4/enso/enso.service.js +46 -0
  182. package/dist/src/modules/v4/explorer/explorer.model.js +2 -0
  183. package/dist/src/modules/v4/explorer/explorer.repository.js +23 -0
  184. package/dist/src/modules/v4/explorer/explorer.service.js +24 -0
  185. package/dist/src/modules/v4/explorer/index.js +1 -0
  186. package/dist/src/modules/v4/index.js +4 -0
  187. package/dist/src/modules/v4/merklRoot/index.js +3 -0
  188. package/dist/src/modules/v4/merklRoot/merklRoot.controller.js +19 -0
  189. package/dist/src/modules/v4/merklRoot/merklRoot.model.js +6 -0
  190. package/dist/src/modules/v4/merklRoot/merklRoot.repository.js +31 -0
  191. package/dist/src/modules/v4/merklRoot/merklRoot.service.js +38 -0
  192. package/dist/src/modules/v4/opportunity/index.js +3 -0
  193. package/dist/src/modules/v4/opportunity/opportunity.controller.js +69 -0
  194. package/dist/src/modules/v4/opportunity/opportunity.model.js +36 -0
  195. package/dist/src/modules/v4/opportunity/opportunity.repository.d.ts +14 -0
  196. package/dist/src/modules/v4/opportunity/opportunity.repository.js +217 -0
  197. package/dist/src/modules/v4/opportunity/opportunity.service.d.ts +0 -15
  198. package/dist/src/modules/v4/opportunity/opportunity.service.js +180 -0
  199. package/dist/src/modules/v4/opportunity/subservices/getAjnaMetadata.service.js +50 -0
  200. package/dist/src/modules/v4/opportunity/subservices/getBadgerMetadata.service.js +23 -0
  201. package/dist/src/modules/v4/opportunity/subservices/getClammMetadata.service.js +33 -0
  202. package/dist/src/modules/v4/opportunity/subservices/getCompoundMetadata.service.js +18 -0
  203. package/dist/src/modules/v4/opportunity/subservices/getDolomiteMetadata.service.js +15 -0
  204. package/dist/src/modules/v4/opportunity/subservices/getErc20Metadata.service.js +63 -0
  205. package/dist/src/modules/v4/opportunity/subservices/getErc20SnapshotMetadata.service.js +8 -0
  206. package/dist/src/modules/v4/opportunity/subservices/getEulerMetadata.service.js +30 -0
  207. package/dist/src/modules/v4/opportunity/subservices/getJsonAirDropMetadata.service.js +36 -0
  208. package/dist/src/modules/v4/opportunity/subservices/getMorphoMetadata.service.js +19 -0
  209. package/dist/src/modules/v4/opportunity/subservices/getRadiantMetadata.service.js +9 -0
  210. package/dist/src/modules/v4/opportunity/subservices/getSiloMetadata.service.js +13 -0
  211. package/dist/src/modules/v4/opportunity/transform-id.pipe.js +6 -0
  212. package/dist/src/modules/v4/opportunity/validate-id.pipe.js +12 -0
  213. package/dist/src/modules/v4/participate/participate.controller.js +66 -0
  214. package/dist/src/modules/v4/participate/participate.model.js +24 -0
  215. package/dist/src/modules/v4/participate/participate.service.js +33 -0
  216. package/dist/src/modules/v4/price/index.js +3 -0
  217. package/dist/src/modules/v4/price/price.controller.js +62 -0
  218. package/dist/src/modules/v4/price/price.model.js +12 -0
  219. package/dist/src/modules/v4/price/price.repository.js +18 -0
  220. package/dist/src/modules/v4/price/price.service.js +44 -0
  221. package/dist/src/modules/v4/prisma/index.js +1 -0
  222. package/dist/src/modules/v4/protocol/index.js +3 -0
  223. package/dist/src/modules/v4/protocol/protocol.controller.js +23 -0
  224. package/dist/src/modules/v4/protocol/protocol.model.js +68 -0
  225. package/dist/src/modules/v4/protocol/protocol.repository.js +37 -0
  226. package/dist/src/modules/v4/protocol/protocol.service.js +77 -0
  227. package/dist/src/modules/v4/reward/index.js +3 -0
  228. package/dist/src/modules/v4/reward/reward.controller.js +52 -0
  229. package/dist/src/modules/v4/reward/reward.model.js +104 -0
  230. package/dist/src/modules/v4/reward/reward.repository.js +237 -0
  231. package/dist/src/modules/v4/reward/reward.service.js +283 -0
  232. package/dist/src/modules/v4/reward/rewardConvertor.service.js +136 -0
  233. package/dist/src/modules/v4/router.js +57 -0
  234. package/dist/src/modules/v4/status/index.js +3 -0
  235. package/dist/src/modules/v4/status/status.controller.js +48 -0
  236. package/dist/src/modules/v4/status/status.model.js +24 -0
  237. package/dist/src/modules/v4/status/status.repository.js +88 -0
  238. package/dist/src/modules/v4/status/status.service.js +60 -0
  239. package/dist/src/modules/v4/token/index.js +3 -0
  240. package/dist/src/modules/v4/token/token.controller.js +32 -0
  241. package/dist/src/modules/v4/token/token.model.js +23 -0
  242. package/dist/src/modules/v4/token/token.repository.js +128 -0
  243. package/dist/src/modules/v4/token/token.service.js +268 -0
  244. package/dist/src/modules/v4/tvl/index.js +2 -0
  245. package/dist/src/modules/v4/tvl/tvl.controller.js +1 -0
  246. package/dist/src/modules/v4/tvl/tvl.model.js +1 -0
  247. package/dist/src/modules/v4/tvl/tvl.repository.js +1 -0
  248. package/dist/src/modules/v4/tvl/tvl.service.js +49 -0
  249. package/dist/src/modules/v4/uniswapV4/index.js +4 -0
  250. package/dist/src/modules/v4/uniswapV4/uniswapV4.controller.js +11 -0
  251. package/dist/src/modules/v4/uniswapV4/uniswapV4.model.js +17 -0
  252. package/dist/src/modules/v4/uniswapV4/uniswapV4.repository.js +2 -0
  253. package/dist/src/modules/v4/uniswapV4/uniswapV4.service.js +73 -0
  254. package/dist/src/modules/v4/user/index.js +3 -0
  255. package/dist/src/modules/v4/user/user.controller.js +69 -0
  256. package/dist/src/modules/v4/user/user.model.js +18 -0
  257. package/dist/src/modules/v4/user/user.repository.js +38 -0
  258. package/dist/src/modules/v4/user/user.service.js +50 -0
  259. package/dist/src/plugins/error-handling.plugin.js +28 -0
  260. package/dist/src/plugins/logger.plugin.js +22 -0
  261. package/dist/src/routes/v1/allowances.js +115 -0
  262. package/dist/src/routes/v1/balances.js +25 -0
  263. package/dist/src/routes/v1/prices.js +11 -0
  264. package/dist/src/routes/v1/tokens.js +17 -0
  265. package/dist/src/routes/v2/merkl.js +13 -0
  266. package/dist/src/routes/v3/ERC20Campaigns.js +63 -0
  267. package/dist/src/routes/v3/app.js +18 -0
  268. package/dist/src/routes/v3/blacklist.js +18 -0
  269. package/dist/src/routes/v3/campaign/delay.js +78 -0
  270. package/dist/src/routes/v3/campaignClaims.js +24 -0
  271. package/dist/src/routes/v3/campaignReport.js +22 -0
  272. package/dist/src/routes/v3/campaignUnclaimed.js +28 -0
  273. package/dist/src/routes/v3/campaigns.js +101 -0
  274. package/dist/src/routes/v3/campaignsForMainParameter.js +19 -0
  275. package/dist/src/routes/v3/campaignsInfo.js +54 -0
  276. package/dist/src/routes/v3/campaignsRewardsReport.js +47 -0
  277. package/dist/src/routes/v3/claims.js +45 -0
  278. package/dist/src/routes/v3/compoundV2.js +9 -0
  279. package/dist/src/routes/v3/createCampaign.js +66 -0
  280. package/dist/src/routes/v3/dolomite.js +9 -0
  281. package/dist/src/routes/v3/euler.js +9 -0
  282. package/dist/src/routes/v3/exports/campaigns.js +28 -0
  283. package/dist/src/routes/v3/fetch.js +27 -0
  284. package/dist/src/routes/v3/health.js +13 -0
  285. package/dist/src/routes/v3/lostyield.js +98 -0
  286. package/dist/src/routes/v3/merkl.js +119 -0
  287. package/dist/src/routes/v3/morphoMarkets.js +27 -0
  288. package/dist/src/routes/v3/morphoVaults.js +22 -0
  289. package/dist/src/routes/v3/multiChainPositions.js +69 -0
  290. package/dist/src/routes/v3/opportunity.js +63 -0
  291. package/dist/src/routes/v3/overview.js +73 -0
  292. package/dist/src/routes/v3/parse.js +23 -0
  293. package/dist/src/routes/v3/payload.js +40 -0
  294. package/dist/src/routes/v3/poolInfo.js +88 -0
  295. package/dist/src/routes/v3/positions.js +62 -0
  296. package/dist/src/routes/v3/radiant.js +26 -0
  297. package/dist/src/routes/v3/recipients.js +20 -0
  298. package/dist/src/routes/v3/rewards.js +33 -0
  299. package/dist/src/routes/v3/rewardsReport.js +51 -0
  300. package/dist/src/routes/v3/rootForTimestamp.js +47 -0
  301. package/dist/src/routes/v3/silo.js +20 -0
  302. package/dist/src/routes/v3/token.js +24 -0
  303. package/dist/src/routes/v3/tokenUnclaimed.js +24 -0
  304. package/dist/src/routes/v3/twt/participants.js +11 -0
  305. package/dist/src/routes/v3/updates.js +47 -0
  306. package/dist/src/routes/v3/userRewards.js +59 -0
  307. package/dist/src/types/index.js +6 -0
  308. package/dist/src/types/parameters/Action.js +11 -0
  309. package/dist/src/types/parameters/Chain.js +13 -0
  310. package/dist/src/types/parameters/ChainCampaignId.js +13 -0
  311. package/dist/src/types/parameters/MainParameter.js +19 -0
  312. package/dist/src/types/parameters/OpportunityId.js +14 -0
  313. package/dist/src/types/parameters/Timestamp.js +16 -0
  314. package/dist/src/types/parameters/Type.js +15 -0
  315. package/dist/src/types/parameters/index.js +17 -0
  316. package/dist/src/types/returnTypes.js +1 -0
  317. package/dist/src/types/utils.js +1 -0
  318. package/dist/src/utils/addString.js +6 -0
  319. package/dist/src/utils/bigintToString.js +20 -0
  320. package/dist/src/utils/crypto.js +4 -0
  321. package/dist/src/utils/decodeCalls.js +170 -0
  322. package/dist/src/utils/encodeCalls.js +240 -0
  323. package/dist/src/utils/error.js +90 -0
  324. package/dist/src/utils/execute.js +41 -0
  325. package/dist/src/utils/generateCardName.js +89 -0
  326. package/dist/src/utils/generic.js +117 -0
  327. package/dist/src/utils/hashArray.js +4 -0
  328. package/dist/src/utils/lastBlockBefore.js +78 -0
  329. package/dist/src/utils/logger.js +52 -0
  330. package/dist/src/utils/pricer.js +180 -0
  331. package/dist/src/utils/prices/chainlinkRead.js +8 -0
  332. package/dist/src/utils/prices/curveVirtualPrice.js +7 -0
  333. package/dist/src/utils/prices/getDQUICK.js +8 -0
  334. package/dist/src/utils/prices/priceFetcherFactory.js +29 -0
  335. package/dist/src/utils/prices/priceService.js +328 -0
  336. package/dist/src/utils/prices/services/coinGeckoService.js +53 -0
  337. package/dist/src/utils/prices/services/defillamaService.js +53 -0
  338. package/dist/src/utils/prices/services/dexScreenerService.js +62 -0
  339. package/dist/src/utils/prices/services/erc4626Service.js +30 -0
  340. package/dist/src/utils/prices/services/getERC4626.js +11 -0
  341. package/dist/src/utils/prices/services/indexCoopService.js +55 -0
  342. package/dist/src/utils/prices/services/priceFetcher.js +1 -0
  343. package/dist/src/utils/prices/uniV2Price.js +40 -0
  344. package/dist/src/utils/prisma.js +12 -0
  345. package/dist/src/utils/providers.js +30 -0
  346. package/dist/src/utils/queries/activeCampaigns.js +22 -0
  347. package/dist/src/utils/queries/allCampaigns.js +51 -0
  348. package/dist/src/utils/queries/campaignsForMainParameter.js +23 -0
  349. package/dist/src/utils/queries/claimsOverTime.js +111 -0
  350. package/dist/src/utils/queries/endingCampaigns.js +21 -0
  351. package/dist/src/utils/queries/futureCampaigns.js +19 -0
  352. package/dist/src/utils/queries/mainParameterCampaigns.js +11 -0
  353. package/dist/src/utils/queries/rewardsAmount.js +106 -0
  354. package/dist/src/utils/queries/unclaimed.js +81 -0
  355. package/dist/src/utils/rateLimit.js +13 -0
  356. package/dist/src/utils/stryke.js +4 -0
  357. package/dist/src/utils/throw.js +27 -0
  358. package/dist/src/utils/validation.js +20 -0
  359. package/dist/tsconfig.package.tsbuildinfo +1 -1
  360. package/package.json +2 -2
  361. package/dist/package.json +0 -91
@@ -0,0 +1,942 @@
1
+ import { nftPositionByIdsQuery, positionMultipleOwnersQuery } from "../../positions/clamm/thegraph";
2
+ import { fetchFarmedPositionsV2 } from "../../positions/clamm/thegraph/fetchFarmedPositions";
3
+ import { A51Factory__factory, ALM, ALMMapping, AMM, AMMAlgorithm, AMMAlgorithmMapping, BN2Number, DecodeLiquidity, EAprBreakdownType, ERC20Interface, Forwarder, JonesDoubleRewardTracker__factory, Liquidity, NETWORK_LABELS, NitroInterface, PoolInterface, PoolState, PriorityAMM, SqrtPrice, almName, ammName, getAmountsForLiquidity, getTickAtSqrtRatio, isBlacklisted, isWhitelisted, merklSubgraphAMMEndpoints, shortenAddress, spNFTInterface, withTimeout, } from "@sdk";
4
+ import axios from "axios";
5
+ import { BigNumber, utils } from "ethers";
6
+ import request from "graphql-request";
7
+ import JSBI from "jsbi";
8
+ import moment from "moment";
9
+ import { MERKL_ALM_POSITION_FETCHING_TIMEOUT } from "../../../constants";
10
+ import { log } from "../../../utils/logger";
11
+ import { Pricer } from "../../../utils/pricer";
12
+ import { isStrykeCampaign } from "../../../utils/stryke";
13
+ import { fetchA51Strategies } from "../utils/fetchA51Strategies";
14
+ export async function CLAMMDynamicData(chainId, campaigns) {
15
+ const dynamicData = [];
16
+ const pricer = await Pricer.load();
17
+ const calls = [];
18
+ const A51Interface = A51Factory__factory.createInterface();
19
+ /** Dedupe pools from campaigns to build pool list */
20
+ let poolList = [];
21
+ for (const campaign of campaigns ?? []) {
22
+ /** Loop through all campaigns to add pools */
23
+ if (!poolList?.map(p => p.mainParameter.toLowerCase()).includes(campaign.mainParameter.toLowerCase())) {
24
+ if (AMMAlgorithmMapping[campaign.campaignParameters.amm] === undefined) {
25
+ console.log("Invalid AMM", campaign.campaignParameters.amm);
26
+ continue;
27
+ }
28
+ poolList.push({
29
+ address: campaign.campaignParameters.poolAddress,
30
+ mainParameter: campaign.mainParameter, // main parameter containes info of poolAddress + AMM (in case its a priority AMM)
31
+ alms: [],
32
+ amm: campaign.campaignParameters.amm,
33
+ });
34
+ }
35
+ /** Now we have an entry with campaign.mainParameter in poolList */
36
+ const poolIndex = poolList
37
+ ?.map(p => p.mainParameter.toLowerCase())
38
+ .findIndex(a => a === campaign.mainParameter.toLowerCase());
39
+ /** Fill ALMs per pools */
40
+ for (const forwarder of campaign.campaignParameters.forwarders
41
+ .filter(f => f.forwarderType === Forwarder.CLAMM)
42
+ .sort((a, b) => a.priority - b.priority)) {
43
+ const alm = {
44
+ address: forwarder.sender,
45
+ ...(!!forwarder.owner && { owner: forwarder.owner?.toLowerCase() }),
46
+ target: forwarder.target.toLowerCase(),
47
+ type: forwarder.type,
48
+ priority: forwarder.priority,
49
+ };
50
+ /** If the ALM is not found - add it */
51
+ if (poolList[poolIndex].alms.findIndex(a => alm.address === a.address && alm.target === a.target) === -1) {
52
+ poolList[poolIndex].alms.push(alm);
53
+ }
54
+ }
55
+ }
56
+ poolList = poolList.filter(p => p.amm !== undefined && p.amm !== null);
57
+ if (!!poolList) {
58
+ // Prepare A51 fetching
59
+ const A51Pools = [];
60
+ for (const pool of poolList) {
61
+ for (const _ of pool.alms.filter(a => a.type === ALM.A51)) {
62
+ A51Pools.push(pool.address.toLowerCase());
63
+ }
64
+ }
65
+ let A51Strategies = {};
66
+ if (A51Pools.length > 0) {
67
+ A51Strategies = await fetchA51Strategies(chainId, [...new Set(A51Pools)]);
68
+ }
69
+ for (const pool of poolList) {
70
+ const poolInterface = PoolInterface[AMMAlgorithmMapping[pool.amm]];
71
+ const d = campaigns?.filter(campaign => campaign.mainParameter.toLowerCase() === pool.mainParameter.toLowerCase())[0];
72
+ calls.push({
73
+ allowFailure: true,
74
+ callData: poolInterface.encodeFunctionData(Liquidity[AMMAlgorithmMapping[pool.amm]]),
75
+ target: pool.address,
76
+ }, {
77
+ allowFailure: true,
78
+ callData: poolInterface.encodeFunctionData(PoolState[AMMAlgorithmMapping[pool.amm]]),
79
+ target: pool.address,
80
+ }, {
81
+ allowFailure: true,
82
+ callData: ERC20Interface.encodeFunctionData("balanceOf", [pool.address]),
83
+ target: d.campaignParameters.token0,
84
+ }, {
85
+ allowFailure: true,
86
+ callData: ERC20Interface.encodeFunctionData("balanceOf", [pool.address]),
87
+ target: d.campaignParameters.token1,
88
+ });
89
+ /** Direct ALMs */
90
+ for (const alm of pool.alms.filter(a => a.target.toLowerCase() === pool.address.toLowerCase() && a.type !== ALM.A51)) {
91
+ let almAddress = alm.address;
92
+ if (alm.type === ALM.Beefy) {
93
+ almAddress = alm.owner ?? alm.address;
94
+ }
95
+ calls.push({
96
+ allowFailure: true,
97
+ callData: ERC20Interface.encodeFunctionData("totalSupply"),
98
+ target: alm.address,
99
+ });
100
+ calls.push({
101
+ allowFailure: true,
102
+ callData: ERC20Interface.encodeFunctionData("balanceOf", [almAddress]),
103
+ target: d.campaignParameters.token0,
104
+ });
105
+ calls.push({
106
+ allowFailure: true,
107
+ callData: ERC20Interface.encodeFunctionData("balanceOf", [almAddress]),
108
+ target: d.campaignParameters.token1,
109
+ });
110
+ }
111
+ /** Multi-hop ALMs */
112
+ for (const alm of pool.alms.filter(a => a.target !== pool.address.toLowerCase())) {
113
+ if (alm.type === ALM.spNFT) {
114
+ calls.push({
115
+ allowFailure: true,
116
+ callData: spNFTInterface.encodeFunctionData("getPoolInfo"),
117
+ target: alm.address,
118
+ });
119
+ }
120
+ else if (alm.type === ALM.kpNFT) {
121
+ calls.push({
122
+ allowFailure: true,
123
+ callData: spNFTInterface.encodeFunctionData("getPoolInfo"),
124
+ target: alm.address,
125
+ });
126
+ }
127
+ else if (alm.type === ALM.Nitro) {
128
+ calls.push({
129
+ allowFailure: true,
130
+ callData: NitroInterface.encodeFunctionData("totalDepositAmount"),
131
+ target: alm.address,
132
+ });
133
+ }
134
+ else if ([ALM.ConcentricStaker, ALM.GammaChef].includes(alm.type)) {
135
+ calls.push({
136
+ allowFailure: true,
137
+ callData: ERC20Interface.encodeFunctionData("balanceOf", [alm.address]),
138
+ target: alm.target,
139
+ });
140
+ }
141
+ else if (alm.type === ALM.JonesTracker) {
142
+ calls.push({
143
+ allowFailure: true,
144
+ callData: JonesDoubleRewardTracker__factory.createInterface().encodeFunctionData("totalStakedAmount"),
145
+ target: alm.address,
146
+ });
147
+ }
148
+ else {
149
+ calls.push({
150
+ allowFailure: true,
151
+ callData: ERC20Interface.encodeFunctionData("totalSupply"),
152
+ target: alm.address,
153
+ });
154
+ }
155
+ }
156
+ /** A51 Strategies */
157
+ for (const w of pool.alms.filter(a => a.type === ALM.A51)) {
158
+ const strategies = A51Strategies?.[pool.address.toLowerCase()]?.[w.address] ?? [];
159
+ for (const strategy of strategies) {
160
+ calls.push({
161
+ allowFailure: true,
162
+ callData: A51Interface.encodeFunctionData("strategies", [strategy.id]),
163
+ target: w.address,
164
+ });
165
+ }
166
+ }
167
+ }
168
+ /**
169
+ * Fetch all ALM vaults positions for the pools.
170
+ * @dev Do it in parallel with 1 call / AMM subgraph to save time.
171
+ */
172
+ const positions = {};
173
+ const positionsPromise = Object.keys(AMM)
174
+ .filter(amm => !!merklSubgraphAMMEndpoints[chainId][Number.parseInt(amm)])
175
+ .map(async (amm) => {
176
+ const tgURL = merklSubgraphAMMEndpoints[chainId][Number.parseInt(amm)];
177
+ let targetAddressesList = [];
178
+ if (!!poolList) {
179
+ for (const pool of poolList) {
180
+ if (pool.amm === Number.parseInt(amm)) {
181
+ /** Add direct alm addresses */
182
+ targetAddressesList = targetAddressesList.concat(pool.alms
183
+ .filter(a => a.target.toLowerCase() === pool.address.toLowerCase())
184
+ ?.map(w => {
185
+ return !!w?.owner && Number.parseInt(amm) !== AMM.Stryke
186
+ ? w.owner.toLowerCase()
187
+ : w.address.toLowerCase();
188
+ }) ?? []);
189
+ /** Add blacklisted / whitelisted addresses (optional) */
190
+ for (const campaign of campaigns.filter(campaign => campaign.mainParameter.toLowerCase() === pool.mainParameter.toLowerCase())) {
191
+ const distributionBlacklist = campaign.campaignId === "0x4a805dd97d823dfbc34d138af3d09536ac792b6ad73079573df082c71d4b057c"
192
+ ? [...campaign.campaignParameters.blacklist, "0x657e6d2073A99aF61952beb7EE564169616b90C1"]
193
+ : campaign.campaignParameters.blacklist;
194
+ if (!!distributionBlacklist && distributionBlacklist.length > 0)
195
+ targetAddressesList = targetAddressesList.concat(distributionBlacklist.map((address) => address.toLowerCase()));
196
+ let distributionWhitelist = campaign.campaignParameters?.whitelist;
197
+ if (distributionWhitelist.length === 1 &&
198
+ distributionWhitelist[0].toLowerCase() === "0xE4bA6740aF4c666325D49B3112E4758371386aDc".toLowerCase()) {
199
+ distributionWhitelist = ["0xe11d346757d052214686bCbC860C94363AfB4a9A"];
200
+ }
201
+ if (!isStrykeCampaign(pool.amm) && !!distributionWhitelist && distributionWhitelist.length > 0)
202
+ targetAddressesList = targetAddressesList.concat(distributionWhitelist.map((address) => address.toLowerCase()));
203
+ }
204
+ }
205
+ }
206
+ }
207
+ targetAddressesList = targetAddressesList.filter((a, index, self) => self.indexOf(a) === index); // Dedupe
208
+ if (targetAddressesList?.length > 0) {
209
+ positions[Number.parseInt(amm)] = [];
210
+ /** Fetch NFT Wrapper positions */
211
+ const farmedPositionsList = await fetchFarmedPositionsV2(chainId, targetAddressesList, Number(amm));
212
+ const farmedPositionsById = Object.keys(farmedPositionsList).reduce((acc, curr) => {
213
+ for (const pos of farmedPositionsList[curr]) {
214
+ acc[pos.id] = pos;
215
+ }
216
+ return acc;
217
+ }, {});
218
+ if (Object.keys(farmedPositionsById).length > 0) {
219
+ let hasFollowingPage = true;
220
+ let skip = 0;
221
+ const res = { nft: [] };
222
+ while (hasFollowingPage) {
223
+ const auxRes = await request(tgURL, nftPositionByIdsQuery, {
224
+ ids: Object.keys(farmedPositionsById),
225
+ skip,
226
+ });
227
+ res.nft = res.nft.concat(auxRes.nft ?? []);
228
+ if (auxRes.nft.length < 1000) {
229
+ hasFollowingPage = false;
230
+ }
231
+ skip += 1000;
232
+ }
233
+ if (!!res.nft) {
234
+ for (const pos of res.nft) {
235
+ positions[Number.parseInt(amm)]?.push({
236
+ ...pos,
237
+ owner: farmedPositionsById[pos.id].holder,
238
+ });
239
+ }
240
+ }
241
+ }
242
+ await withTimeout((async () => {
243
+ let hasFollowingPage = true;
244
+ let skip = 0;
245
+ const res = { direct: [], nft: [] };
246
+ while (hasFollowingPage) {
247
+ const auxRes = await request(tgURL, positionMultipleOwnersQuery, {
248
+ owners: targetAddressesList,
249
+ skip,
250
+ });
251
+ res.direct = res.direct.concat(auxRes.direct ?? []);
252
+ res.nft = res.nft.concat(auxRes.nft ?? []);
253
+ if (auxRes.direct.length < 1000 && auxRes.nft.length < 1000) {
254
+ hasFollowingPage = false;
255
+ }
256
+ skip += 1000;
257
+ }
258
+ return res;
259
+ })().then(res => {
260
+ if (!!res.direct) {
261
+ for (const pos of res.direct) {
262
+ positions[Number.parseInt(amm)]?.push(pos);
263
+ }
264
+ }
265
+ if (!!res.nft) {
266
+ for (const pos of res.nft) {
267
+ positions[Number.parseInt(amm)]?.push(pos);
268
+ }
269
+ }
270
+ }), MERKL_ALM_POSITION_FETCHING_TIMEOUT).catch(error => {
271
+ const service = `Merkl AMM Subgraph for ${NETWORK_LABELS[chainId]} ${AMM[Number.parseInt(amm)]}`;
272
+ log.error(service, error, service, tgURL);
273
+ });
274
+ }
275
+ });
276
+ return {
277
+ cached: false,
278
+ call: {
279
+ callData: calls,
280
+ handler: () => { },
281
+ reducer: async (result) => {
282
+ // Wait for position fetching before finalizing the data
283
+ await Promise.all(positionsPromise);
284
+ let i = 0;
285
+ if (!!poolList) {
286
+ for (const pool of poolList) {
287
+ const poolInterface = PoolInterface[AMMAlgorithmMapping[pool.amm]];
288
+ // This liquidity call gives the active liquidity on the pool. To get the total liquidity we would need to loop over all positions
289
+ let poolTotalLiquidity;
290
+ let sqrtPrice;
291
+ let poolBalanceToken0;
292
+ let poolBalanceToken1;
293
+ const d = campaigns?.filter(campaign => campaign.mainParameter.toLowerCase() === pool.mainParameter.toLowerCase())[0];
294
+ const decimalsToken0 = d.campaignParameters.decimalsToken0;
295
+ const decimalsToken1 = d.campaignParameters.decimalsToken1;
296
+ const symbolToken0 = d.campaignParameters.symbolToken0;
297
+ const symbolToken1 = d.campaignParameters.symbolToken1;
298
+ const prevI = i;
299
+ try {
300
+ poolTotalLiquidity = BN2Number(poolInterface.decodeFunctionResult(Liquidity[AMMAlgorithmMapping[pool.amm]], result[i++])[DecodeLiquidity[AMMAlgorithmMapping[pool.amm]]]);
301
+ sqrtPrice = poolInterface
302
+ .decodeFunctionResult(PoolState[AMMAlgorithmMapping[pool.amm]], result[i++])[SqrtPrice[AMMAlgorithmMapping[pool.amm]]].toString();
303
+ poolBalanceToken0 = BN2Number(ERC20Interface.decodeFunctionResult("balanceOf", result[i++])[0], decimalsToken0);
304
+ poolBalanceToken1 = BN2Number(ERC20Interface.decodeFunctionResult("balanceOf", result[i++])[0], decimalsToken1);
305
+ }
306
+ catch (e) {
307
+ log.warn(`merklDynamic data - failed to decode state of pool ${pool.address} on ${NETWORK_LABELS[chainId]}`);
308
+ i = prevI + 4;
309
+ continue;
310
+ }
311
+ const priceToken0 = (await pricer.get({
312
+ address: d.campaignParameters.token0,
313
+ chainId: chainId,
314
+ symbol: symbolToken0,
315
+ }));
316
+ const priceToken1 = (await pricer.get({
317
+ address: d.campaignParameters.token1,
318
+ chainId: chainId,
319
+ symbol: symbolToken1,
320
+ }));
321
+ const almDetails = [];
322
+ /** Direct ALMs */
323
+ for (const w of pool.alms.filter(a => a.target.toLowerCase() === pool.address.toLowerCase() && a.type !== ALM.A51)) {
324
+ const prevI = i;
325
+ try {
326
+ const totalSupply = BN2Number(ERC20Interface.decodeFunctionResult("totalSupply", result[i++])[0]);
327
+ const almIdleBalance0 = BN2Number(ERC20Interface.decodeFunctionResult("balanceOf", result[i++])[0], d.campaignParameters.decimalsToken0);
328
+ let almBalance0 = almIdleBalance0;
329
+ const almIdleBalance1 = BN2Number(ERC20Interface.decodeFunctionResult("balanceOf", result[i++])[0], d.campaignParameters.decimalsToken1);
330
+ let almBalance1 = almIdleBalance1;
331
+ let almTotalLiquidity = 0;
332
+ let almInRangeLiquidity = 0;
333
+ const almPositions = positions?.[pool.amm]?.filter(pos => pos.pool.id === pool.address.toLowerCase() &&
334
+ [w.address.toLowerCase(), ...[!!w?.owner && w.owner.toLowerCase()]].includes(pos.owner.toLowerCase()));
335
+ const almPositionsWithAPIType = [];
336
+ if (!!almPositions) {
337
+ for (const position of almPositions) {
338
+ const upperTick = Number.parseInt(position.tickUpper);
339
+ const lowerTick = Number.parseInt(position.tickLower);
340
+ const [amount0, amount1] = getAmountsForLiquidity(sqrtPrice, lowerTick, upperTick, BigNumber.from(position.liquidity));
341
+ const balance0 = BN2Number(amount0, decimalsToken0);
342
+ const balance1 = BN2Number(amount1, decimalsToken1);
343
+ const totalLiquidity = BN2Number(position.liquidity);
344
+ const inRangeLiquidity = balance0 > 0 && balance1 > 0 ? BN2Number(position.liquidity) ?? 0 : 0;
345
+ almTotalLiquidity += totalLiquidity;
346
+ almInRangeLiquidity += inRangeLiquidity;
347
+ almBalance0 += balance0;
348
+ almBalance1 += balance1;
349
+ almPositionsWithAPIType.push({
350
+ balance0,
351
+ balance1,
352
+ id: position.id,
353
+ inRangeLiquidity,
354
+ lowerTick,
355
+ totalLiquidity,
356
+ tvl: priceToken0 * balance0 + priceToken1 * balance1,
357
+ upperTick,
358
+ });
359
+ }
360
+ // The wrapper type can exist in the subgraph without being declared in the SDK which can lead to type errors
361
+ if (!!ALMMapping[pool.amm] && w.type in ALMMapping[pool.amm]) {
362
+ almDetails.push({
363
+ almAPR: 0, // filled later on
364
+ almAddress: utils.getAddress(w.address),
365
+ almBalance0,
366
+ almIdleBalance0,
367
+ almIdleBalance1,
368
+ almBalance1,
369
+ almInRangeLiquidity,
370
+ almTVL: almBalance0 * priceToken0 + almBalance1 * priceToken1,
371
+ almTotalLiquidity,
372
+ forwarderType: Forwarder.CLAMM,
373
+ label: `${ALMMapping[pool.amm]?.[w.type]} ${w.address}`,
374
+ origin: w.type,
375
+ positions: almPositionsWithAPIType,
376
+ priority: 0,
377
+ sender: utils.getAddress(w.address),
378
+ target: w.target,
379
+ owner: utils.getAddress(w.owner ?? w.address),
380
+ totalSupply,
381
+ type: w.type,
382
+ });
383
+ }
384
+ }
385
+ }
386
+ catch (e) {
387
+ log.warn(`merklDynamic data - failed to handle direct alm data of pool ${pool.address} on ${NETWORK_LABELS[chainId]} - ${w.address}`);
388
+ i = prevI + 3;
389
+ }
390
+ }
391
+ /** Multi-hop ALMs */
392
+ for (const w of pool.alms.filter(a => a.target !== pool.address.toLowerCase())) {
393
+ const prevI = i;
394
+ try {
395
+ let totalSupply;
396
+ if (w.type === ALM.spNFT) {
397
+ totalSupply = BN2Number(spNFTInterface.decodeFunctionResult("getPoolInfo", result[i++])[5]);
398
+ }
399
+ else if (w.type === ALM.kpNFT) {
400
+ totalSupply = BN2Number(spNFTInterface.decodeFunctionResult("getPoolInfo", result[i++])[5]);
401
+ }
402
+ else if (w.type === ALM.Nitro) {
403
+ totalSupply = BN2Number(NitroInterface.decodeFunctionResult("totalDepositAmount", result[i++])[0]);
404
+ }
405
+ else if ([ALM.ConcentricStaker, ALM.GammaChef].includes(w.type)) {
406
+ totalSupply = BN2Number(ERC20Interface.decodeFunctionResult("balanceOf", result[i++])[0]);
407
+ }
408
+ else if (w.type === ALM.JonesTracker) {
409
+ totalSupply = BN2Number(JonesDoubleRewardTracker__factory.createInterface().decodeFunctionResult("totalStakedAmount", result[i++])[0]);
410
+ }
411
+ else {
412
+ totalSupply = BN2Number(ERC20Interface.decodeFunctionResult("totalSupply", result[i++])[0]);
413
+ }
414
+ const wrappedALM = almDetails.filter(a => utils.getAddress(a.almAddress) === utils.getAddress(w.target))[0];
415
+ if (!!wrappedALM && !!wrappedALM.totalSupply) {
416
+ const ratio = totalSupply / wrappedALM.totalSupply;
417
+ almDetails.push({
418
+ almAPR: 0,
419
+ // filled later on
420
+ almAddress: w.address,
421
+ almIdleBalance0: 0,
422
+ almIdleBalance1: 0,
423
+ almBalance0: ratio * wrappedALM.almBalance0,
424
+ almBalance1: ratio * wrappedALM.almBalance1,
425
+ almInRangeLiquidity: ratio * wrappedALM.almInRangeLiquidity,
426
+ almTVL: ratio * wrappedALM.almTVL,
427
+ almTotalLiquidity: ratio * wrappedALM.almTotalLiquidity,
428
+ forwarderType: Forwarder.CLAMM,
429
+ label: `${ALMMapping[pool.amm]?.[w.type]} ${w.address}`,
430
+ origin: w.type,
431
+ positions: wrappedALM.positions.map(pos => {
432
+ return {
433
+ ...pos,
434
+ balance0: ratio * pos.balance0,
435
+ balance1: ratio * pos.balance1,
436
+ inRangeLiquidity: ratio * pos.inRangeLiquidity,
437
+ totalLiquidity: ratio * pos.totalLiquidity,
438
+ tvl: ratio * pos.tvl,
439
+ };
440
+ }),
441
+ priority: wrappedALM.priority + 1,
442
+ sender: utils.getAddress(w.address),
443
+ target: w.target,
444
+ owner: w.owner ?? w.address,
445
+ totalSupply,
446
+ type: w.type,
447
+ });
448
+ }
449
+ else {
450
+ log.local(`Target ALM not found (${NETWORK_LABELS[chainId]}). Address: ${w.address}, Target: ${w.target}`);
451
+ }
452
+ }
453
+ catch {
454
+ log.warn(`merklDynamic data - failed to handle multi hop alm data of pool ${pool.address} on ${NETWORK_LABELS[chainId]} - ${w.address}`);
455
+ i = prevI + 1;
456
+ }
457
+ }
458
+ /** A51 Strategies */
459
+ for (const w of pool.alms.filter(a => a.type === ALM.A51)) {
460
+ const prevI = i;
461
+ const strategies = A51Strategies?.[pool.address.toLowerCase()]?.[w.address] ?? [];
462
+ let j = 0;
463
+ for (const strategy of strategies) {
464
+ j++;
465
+ const almPositionsWithAPIType = [];
466
+ let almTotalLiquidity = 0;
467
+ let almInRangeLiquidity = 0;
468
+ let almBalance0 = 0;
469
+ let almBalance1 = 0;
470
+ try {
471
+ // struct StrategyData {
472
+ // StrategyKey key; 0
473
+ // address owner; 1
474
+ // bytes actions; 2
475
+ // bytes actionStatus; 3
476
+ // bool isCompound; 4
477
+ // bool isPrivate; 5
478
+ // uint256 managementFee; 6
479
+ // uint256 performanceFee; 7
480
+ // Account account; 8
481
+ // }
482
+ const strategyAccount = A51Interface.decodeFunctionResult("strategies", result[i++])[8];
483
+ // struct Account {
484
+ // uint256 fee0; 0
485
+ // uint256 fee1; 1
486
+ // uint256 balance0; 2
487
+ // uint256 balance1; 3
488
+ // uint256 totalShares; 4
489
+ // uint128 uniswapLiquidity;
490
+ // uint256 feeGrowthInside0LastX128;
491
+ // uint256 feeGrowthInside1LastX128;
492
+ // uint256 feeGrowthOutside0LastX128;
493
+ // uint256 feeGrowthOutside1LastX128;
494
+ // }
495
+ const a51Positions = positions?.[pool.amm]?.filter(pos => pos.pool.id === pool.address.toLowerCase() &&
496
+ pos.owner === w.address.toLowerCase() &&
497
+ pos.tickLower === strategy.tickLower.toString() &&
498
+ pos.tickUpper === strategy.tickUpper.toString());
499
+ if (!!a51Positions) {
500
+ for (const position of a51Positions) {
501
+ const upperTick = Number.parseInt(position.tickUpper);
502
+ const lowerTick = Number.parseInt(position.tickLower);
503
+ const [amount0, amount1] = getAmountsForLiquidity(sqrtPrice, lowerTick, upperTick, BigNumber.from(position.liquidity));
504
+ const balance0 = BN2Number(amount0, decimalsToken0);
505
+ const balance1 = BN2Number(amount1, decimalsToken1);
506
+ const totalLiquidity = BN2Number(position.liquidity);
507
+ const inRangeLiquidity = balance0 > 0 && balance1 > 0 ? BN2Number(position.liquidity) ?? 0 : 0;
508
+ almTotalLiquidity += totalLiquidity;
509
+ almInRangeLiquidity += inRangeLiquidity;
510
+ almBalance0 += balance0;
511
+ almBalance1 += balance1;
512
+ almPositionsWithAPIType.push({
513
+ balance0,
514
+ balance1,
515
+ id: position.id,
516
+ inRangeLiquidity,
517
+ lowerTick,
518
+ totalLiquidity,
519
+ tvl: priceToken0 * balance0 + priceToken1 * balance1,
520
+ upperTick,
521
+ });
522
+ }
523
+ }
524
+ if (!!ALMMapping[pool.amm] && w.type in ALMMapping[pool.amm]) {
525
+ almDetails.push({
526
+ almAPR: 0,
527
+ // filled later on
528
+ almAddress: utils.getAddress(w.address),
529
+ almBalance0,
530
+ almBalance1,
531
+ almIdleBalance0: 0,
532
+ almIdleBalance1: 0,
533
+ almInRangeLiquidity,
534
+ almTVL: almBalance0 * priceToken0 + almBalance1 * priceToken1,
535
+ almTotalLiquidity,
536
+ forwarderType: Forwarder.CLAMM,
537
+ label: `${ALMMapping[pool.amm]?.[w.type]} ${w.address} - ${strategy.id}`,
538
+ origin: w.type,
539
+ positions: almPositionsWithAPIType,
540
+ priority: 0,
541
+ sender: w.address,
542
+ target: w.target,
543
+ owner: w.owner ?? w.address,
544
+ totalSupply: strategyAccount[4].toString(),
545
+ type: w.type,
546
+ });
547
+ }
548
+ }
549
+ catch (e) {
550
+ log.warn(`merklDynamic data - failed to handle A51 data of pool ${pool.address} on ${NETWORK_LABELS[chainId]} - ${w.address}`);
551
+ i = prevI + j;
552
+ }
553
+ }
554
+ }
555
+ /** Iterate over distributions to compute APRs */
556
+ for (const campaign of campaigns.filter(campaign => campaign.mainParameter.toLowerCase() === pool.mainParameter.toLowerCase())) {
557
+ const c = campaign;
558
+ const amount = BN2Number(c.amount, c.campaignParameters.decimalsRewardToken);
559
+ const startTimestamp = BN2Number(c.startTimestamp, 0);
560
+ const endTimestamp = BN2Number(c.endTimestamp, 0);
561
+ const isLive = moment().unix() > startTimestamp && moment().unix() < endTimestamp;
562
+ const totalWeight = BN2Number(c.campaignParameters.weightFees, 4) +
563
+ BN2Number(c.campaignParameters.weightToken0, 4) +
564
+ BN2Number(c.campaignParameters.weightToken1, 4);
565
+ // Proportions in percentage
566
+ const propFees = (BN2Number(c.campaignParameters.weightFees, 4) / totalWeight) * 100;
567
+ const propToken0 = (BN2Number(c.campaignParameters.weightToken0, 4) / totalWeight) * 100;
568
+ const propToken1 = (BN2Number(c.campaignParameters.weightToken1, 4) / totalWeight) * 100;
569
+ let distributionMeanAPR = 0;
570
+ let blacklistedBalance0 = 0;
571
+ let blacklistedBalance1 = 0;
572
+ let blacklistedLiquidity = 0;
573
+ /**
574
+ * @dev In case there is a super amm handling some other amm lp positions,
575
+ * we only need to check the positions associated to this super amm subgraph
576
+ * in order to compute the APRs.
577
+ * Yet, the pool will still be labelled with the main amm
578
+ */
579
+ const amm = c.campaignParameters.whitelist.length > 0 &&
580
+ !!PriorityAMM?.[chainId]?.[c.campaignParameters.whitelist[0]]
581
+ ? PriorityAMM[chainId]?.[c.campaignParameters.whitelist[0]]
582
+ : pool.amm;
583
+ const aprs = {};
584
+ const aprBreakdowns = [];
585
+ /** Clear alm APRs */
586
+ const distributionForwarders = almDetails.map(x => ({ ...x }));
587
+ let priceRewardToken = 0;
588
+ if (isLive && c.campaignParameters.symbolRewardToken !== "aglaMerkl") {
589
+ priceRewardToken = (await pricer.get({
590
+ address: c.rewardToken,
591
+ chainId: chainId,
592
+ symbol: c.campaignParameters.symbolRewardToken,
593
+ }));
594
+ /**
595
+ * Handle whitelisted/blacklisted addresses to compute APR
596
+ */
597
+ if (c.campaignParameters.whitelist.length > 0) {
598
+ blacklistedBalance0 = poolBalanceToken0;
599
+ blacklistedBalance1 = poolBalanceToken1;
600
+ blacklistedLiquidity = poolTotalLiquidity;
601
+ positions?.[pool.amm]?.forEach(pos => {
602
+ if (pos.pool.id === pool.address.toLowerCase() &&
603
+ (isWhitelisted(pos.owner, c.campaignParameters.whitelist) || isStrykeCampaign(pool.amm))
604
+ // pool.alms.filter(a => a.owner === pos.owner || a.address === pos.owner).length > 0) // should be removed
605
+ ) {
606
+ let [amount0, amount1] = [BigNumber.from(0), BigNumber.from(0)];
607
+ try {
608
+ [amount0, amount1] = getAmountsForLiquidity(sqrtPrice, Number.parseInt(pos.tickLower), Number.parseInt(pos.tickUpper), BigNumber.from(pos.liquidity));
609
+ }
610
+ catch {
611
+ log.warn(`merklDynamic data - failed to handle whitelisted positions of pool ${pool.address} on ${NETWORK_LABELS[chainId]} - ${pos.owner} ${pos.tickLower} ${pos.tickUpper} ${pos.liquidity}`);
612
+ }
613
+ blacklistedBalance0 -= BN2Number(amount0, decimalsToken0);
614
+ blacklistedBalance1 -= BN2Number(amount1, decimalsToken1);
615
+ if (c.campaignParameters.isOutOfRangeIncentivized
616
+ ? BN2Number(amount0, decimalsToken0) > 0 || BN2Number(amount1, decimalsToken1) > 0
617
+ : BN2Number(amount0, decimalsToken0) > 0 && BN2Number(amount1, decimalsToken1) > 0)
618
+ blacklistedLiquidity -= BN2Number(pos.liquidity);
619
+ }
620
+ });
621
+ }
622
+ else if (c.campaignParameters.blacklist.length > 0) {
623
+ blacklistedBalance0 = 0;
624
+ blacklistedBalance1 = 0;
625
+ blacklistedLiquidity = 0;
626
+ for (const blacklistedAddress of c.campaignParameters.blacklist) {
627
+ const blackAddressPositions = positions?.[amm]?.filter(pos => pos.pool.id === pool.address.toLowerCase() && pos.owner === blacklistedAddress.toLowerCase());
628
+ if (!!blackAddressPositions) {
629
+ for (const position of blackAddressPositions) {
630
+ const [amount0, amount1] = getAmountsForLiquidity(sqrtPrice, Number.parseInt(position.tickLower), Number.parseInt(position.tickUpper), BigNumber.from(position.liquidity));
631
+ blacklistedBalance0 += BN2Number(amount0, decimalsToken0);
632
+ blacklistedBalance1 += BN2Number(amount1, decimalsToken1);
633
+ if (BN2Number(amount0, decimalsToken0) > 0 && BN2Number(amount1, decimalsToken1) > 0)
634
+ blacklistedLiquidity += BN2Number(position.liquidity);
635
+ }
636
+ }
637
+ }
638
+ }
639
+ /** Yearly rewards in $ */
640
+ const yearlyToken0Rewards = (propToken0 * priceRewardToken * amount * (365 * 24 * 3_600)) / (endTimestamp - startTimestamp);
641
+ const yearlyToken1Rewards = (propToken1 * priceRewardToken * amount * (365 * 24 * 3_600)) / (endTimestamp - startTimestamp);
642
+ const yearlyFeeRewards = (propFees * priceRewardToken * amount * (365 * 24 * 3_600)) / (endTimestamp - startTimestamp);
643
+ let poolAPRkey = "";
644
+ // /**
645
+ // * @notice Stryke users receive rewards with respect to their LP positions (they hold through
646
+ // * Stryke contracts and the `used liquidity` hold in the Stryke option market contracts
647
+ // */
648
+ // if (amm === AMM.Stryke || amm === AMM.StrykePCS) {
649
+ // try {
650
+ // poolBalanceToken0 +=
651
+ // BN2Number(
652
+ // await Erc20__factory.connect(c.campaignParameters.token0, providers[chainId]).balanceOf(
653
+ // DOPEX_OPTION_MARKET[pool.address.toLowerCase()]
654
+ // ),
655
+ // c.campaignParameters.decimalsToken0
656
+ // ) / 2;
657
+ // poolBalanceToken1 +=
658
+ // BN2Number(
659
+ // await Erc20__factory.connect(c.campaignParameters.token1, providers[chainId]).balanceOf(
660
+ // DOPEX_OPTION_MARKET[pool.address.toLowerCase()]
661
+ // ),
662
+ // c.campaignParameters.decimalsToken1
663
+ // ) / 2;
664
+ // } catch {
665
+ // log.error(
666
+ // "clamm dynamic data fetching",
667
+ // `failed to handle dopex option market - ${pool.address}`
668
+ // );
669
+ // }
670
+ // }
671
+ /**
672
+ * General APR (@notice potentially with a boost)
673
+ */
674
+ let poolBalanceToken0WithoutBlacklist = poolBalanceToken0 - (blacklistedBalance0 ?? 0);
675
+ poolBalanceToken0WithoutBlacklist = !!poolBalanceToken0WithoutBlacklist
676
+ ? poolBalanceToken0WithoutBlacklist
677
+ : 0.00001;
678
+ let poolBalanceToken1WithoutBlacklist = poolBalanceToken1 - (blacklistedBalance1 ?? 0);
679
+ poolBalanceToken1WithoutBlacklist = !!poolBalanceToken1WithoutBlacklist
680
+ ? poolBalanceToken1WithoutBlacklist
681
+ : 0.00001;
682
+ const poolLiquidityWithoutBlacklist = poolTotalLiquidity - (blacklistedLiquidity ?? 0);
683
+ const tvl = isStrykeCampaign(amm)
684
+ ? (await axios.get(`https://api.stryke.xyz/clamm/stats/tvl/${pool.address}?chainId=${chainId}`)).data
685
+ : poolBalanceToken0WithoutBlacklist * priceToken0 + poolBalanceToken1WithoutBlacklist * priceToken1;
686
+ distributionMeanAPR = (yearlyToken0Rewards + yearlyToken1Rewards + yearlyFeeRewards) / tvl;
687
+ distributionMeanAPR =
688
+ !distributionMeanAPR || Number.isNaN(distributionMeanAPR) ? 0 : distributionMeanAPR;
689
+ /**
690
+ * @dev We cannot include a whitelisted distrib apr into the mean APR
691
+ */
692
+ if (c.campaignParameters.whitelist.length === 0) {
693
+ poolAPRkey = "Average APR (rewards / pool TVL)";
694
+ if (!aprs[poolAPRkey])
695
+ aprs[poolAPRkey] = 0;
696
+ aprs[poolAPRkey] += distributionMeanAPR;
697
+ // @Hugo wip: new way to structure aprBreakdowns
698
+ aprBreakdowns.push({
699
+ address: pool.address,
700
+ value: distributionMeanAPR,
701
+ type: EAprBreakdownType.AVERAGE,
702
+ label: "Average APR (rewards / pool TVL)",
703
+ });
704
+ // APR per token
705
+ poolAPRkey = `APR for holding ${c.campaignParameters.symbolToken0} in pool`;
706
+ if (!aprs[poolAPRkey])
707
+ aprs[poolAPRkey] = 0;
708
+ aprs[poolAPRkey] += yearlyToken0Rewards / (poolBalanceToken0WithoutBlacklist * priceToken0);
709
+ // @Hugo wip: new way to structure aprBreakdowns
710
+ aprBreakdowns.push({
711
+ address: pool.address,
712
+ value: yearlyToken0Rewards / (poolBalanceToken0WithoutBlacklist * priceToken0),
713
+ type: EAprBreakdownType.TOKEN1,
714
+ label: c.campaignParameters.symbolToken0,
715
+ });
716
+ poolAPRkey = `APR for holding ${c.campaignParameters.symbolToken1} in pool`;
717
+ if (!aprs[poolAPRkey])
718
+ aprs[poolAPRkey] = 0;
719
+ aprs[poolAPRkey] += yearlyToken1Rewards / (poolBalanceToken1WithoutBlacklist * priceToken1);
720
+ // @Hugo wip: new way to structure aprBreakdowns
721
+ aprBreakdowns.push({
722
+ address: pool.address,
723
+ value: yearlyToken1Rewards / (poolBalanceToken1WithoutBlacklist * priceToken1),
724
+ type: EAprBreakdownType.TOKEN2,
725
+ label: c.campaignParameters.symbolToken1,
726
+ });
727
+ }
728
+ else {
729
+ for (const whitelistedAddress of c.campaignParameters.whitelist) {
730
+ const forwarderIndex = distributionForwarders.findIndex(f => utils.getAddress(f.almAddress) === utils.getAddress(whitelistedAddress));
731
+ const poolAPRkey = `Whitelisted campaign on ${ammName(amm)} via address ${shortenAddress(c.campaignParameters.whitelist[0])} Average APR`;
732
+ if (!aprs[poolAPRkey])
733
+ aprs[poolAPRkey] = 0;
734
+ // Account for idle liquidity
735
+ if (forwarderIndex > -1) {
736
+ // @Hugo wip: new way to structure aprBreakdowns
737
+ const breakdownWl = {
738
+ address: c.campaignParameters.whitelist[0],
739
+ value: 0,
740
+ type: EAprBreakdownType.WHITELIST,
741
+ label: ammName(amm),
742
+ };
743
+ if (distributionForwarders[forwarderIndex].priority === 2) {
744
+ distributionMeanAPR =
745
+ (yearlyToken0Rewards + yearlyToken1Rewards + yearlyFeeRewards) /
746
+ (tvl +
747
+ distributionForwarders[forwarderIndex].almBalance0 * priceToken0 +
748
+ distributionForwarders[forwarderIndex].almBalance1 * priceToken1);
749
+ }
750
+ else {
751
+ distributionMeanAPR =
752
+ (yearlyToken0Rewards + yearlyToken1Rewards + yearlyFeeRewards) /
753
+ (tvl +
754
+ distributionForwarders[forwarderIndex].almIdleBalance0 * priceToken0 +
755
+ distributionForwarders[forwarderIndex].almIdleBalance1 * priceToken1);
756
+ }
757
+ distributionMeanAPR =
758
+ !distributionMeanAPR || Number.isNaN(distributionMeanAPR) ? 0 : distributionMeanAPR;
759
+ // @Hugo wip: new way to structure aprBreakdowns
760
+ breakdownWl.value = distributionMeanAPR;
761
+ aprBreakdowns.push(breakdownWl);
762
+ }
763
+ }
764
+ aprs[poolAPRkey] += distributionMeanAPR;
765
+ }
766
+ /**
767
+ * ALM APRs
768
+ * @notice given a campaign
769
+ * */
770
+ distributionForwarders.forEach((alm, index) => {
771
+ const targetForwarder = distributionForwarders.filter(f => f.almAddress.toLowerCase() === alm.target.toLowerCase())?.[0];
772
+ // @Hugo wip: new way to structure aprBreakdowns
773
+ const aprsBreakdown = getForwarderAprbreakDown(distributionForwarders, alm, c, pool, yearlyToken0Rewards, yearlyToken1Rewards, yearlyFeeRewards, poolBalanceToken0WithoutBlacklist, poolBalanceToken1WithoutBlacklist, poolLiquidityWithoutBlacklist, tvl, distributionMeanAPR, index, chainId, amm);
774
+ // @Hugo wip: new way to structure aprBreakdowns
775
+ aprsBreakdown && aprBreakdowns.push(aprsBreakdown);
776
+ const isALMWhitelisted = c.campaignParameters.whitelist.length > 0
777
+ ? isStrykeCampaign(pool.amm)
778
+ ? true
779
+ : isWhitelisted(alm.sender, c.campaignParameters.whitelist) ||
780
+ isWhitelisted(alm.almAddress, c.campaignParameters.whitelist) ||
781
+ isWhitelisted(!!alm?.owner ? alm.owner : "", c.campaignParameters.whitelist) ||
782
+ isWhitelisted(!!alm?.target ? alm.target : "", c.campaignParameters.whitelist) ||
783
+ (!!targetForwarder?.owner &&
784
+ isWhitelisted(targetForwarder?.owner, c.campaignParameters.whitelist))
785
+ : true;
786
+ const isBlacklistedByCampaign = isBlacklisted(alm.sender, c.campaignParameters.blacklist) ||
787
+ isBlacklisted(alm.almAddress, c.campaignParameters.blacklist) ||
788
+ (!!alm?.target && isBlacklisted(alm?.target, c.campaignParameters.blacklist)) ||
789
+ !isALMWhitelisted;
790
+ if (!isBlacklistedByCampaign && !!alm.almTVL && alm.almTVL > 0) {
791
+ try {
792
+ poolAPRkey = `${almName(alm.origin)} ${alm.almAddress}`;
793
+ if (!aprs[poolAPRkey])
794
+ aprs[poolAPRkey] = 0;
795
+ // Token 0 APR
796
+ const almToken0APR = (yearlyToken0Rewards * (alm?.almBalance0 ?? 0 - alm?.almIdleBalance0 ?? 0)) /
797
+ poolBalanceToken0WithoutBlacklist /
798
+ alm.almTVL;
799
+ aprs[poolAPRkey] += almToken0APR;
800
+ // Token 1 APR
801
+ const almToken1APR = (yearlyToken1Rewards * (alm?.almBalance1 ?? 0 - alm?.almIdleBalance1 ?? 0)) /
802
+ poolBalanceToken1WithoutBlacklist /
803
+ alm.almTVL;
804
+ ((alm.almBalance1 / (alm?.almBalance1 ?? 0 + alm?.almIdleBalance1 ?? 0)) *
805
+ alm.almBalance1 *
806
+ yearlyToken1Rewards) /
807
+ poolBalanceToken1WithoutBlacklist /
808
+ alm.almTVL;
809
+ aprs[poolAPRkey] += almToken1APR;
810
+ // Fee APR
811
+ const almFeeAPR = (yearlyFeeRewards * (alm?.almInRangeLiquidity ?? 0)) /
812
+ poolLiquidityWithoutBlacklist /
813
+ alm.almTVL;
814
+ aprs[poolAPRkey] += almFeeAPR;
815
+ if (isStrykeCampaign(amm)) {
816
+ // computation is less precise here as we don't have the details of balances
817
+ aprs[poolAPRkey] = (yearlyToken0Rewards + yearlyToken1Rewards + yearlyFeeRewards) / tvl;
818
+ }
819
+ /** Fix to tackle discrepancies in the APRs when there is a whitelist */
820
+ if ((c.campaignParameters.whitelist?.length === 1 &&
821
+ (isWhitelisted(alm.sender, c.campaignParameters.whitelist) ||
822
+ isWhitelisted(alm.almAddress, c.campaignParameters.whitelist) ||
823
+ isWhitelisted(!!alm?.target ? alm.target : "", c.campaignParameters.whitelist) ||
824
+ isWhitelisted(!!alm?.owner ? alm.owner : "", c.campaignParameters.whitelist))) ||
825
+ (!!targetForwarder?.owner &&
826
+ isWhitelisted(targetForwarder?.owner, c.campaignParameters.whitelist))) {
827
+ if (aprs[poolAPRkey] < distributionMeanAPR || !aprs[poolAPRkey] || aprs[poolAPRkey] > 1e12) {
828
+ aprs[poolAPRkey] = distributionMeanAPR;
829
+ }
830
+ }
831
+ distributionForwarders[index].almAPR = aprs[poolAPRkey];
832
+ }
833
+ catch (e) {
834
+ log.error("CLAMMDynamicData", `failed to compute ALM APR for ${alm.almAddress} (sender ${alm.sender}) on ${NETWORK_LABELS[chainId]}: ${e}`);
835
+ }
836
+ }
837
+ });
838
+ }
839
+ dynamicData.push({
840
+ ...campaign,
841
+ amm: pool.amm,
842
+ ammAlgo: AMMAlgorithmMapping[pool.amm],
843
+ ammAlgoName: AMMAlgorithm[AMMAlgorithmMapping[pool.amm]],
844
+ ammName: AMM[pool.amm],
845
+ apr: distributionMeanAPR,
846
+ aprs,
847
+ aprBreakdowns,
848
+ blacklistedBalance0,
849
+ blacklistedBalance1,
850
+ blacklistedLiquidity,
851
+ forwarders: distributionForwarders,
852
+ isLive,
853
+ isMock: c.campaignParameters.symbolRewardToken === "aglaMerkl",
854
+ poolBalanceToken0,
855
+ poolBalanceToken1,
856
+ poolTotalLiquidity,
857
+ symbolToken0,
858
+ symbolToken1,
859
+ tick: getTickAtSqrtRatio(JSBI.BigInt(sqrtPrice)),
860
+ priceRewardToken: priceRewardToken,
861
+ tvl: isStrykeCampaign(pool.amm)
862
+ ? (await axios.get(`https://api.stryke.xyz/clamm/stats/tvl/${pool.address}?chainId=${chainId}`)).data
863
+ : poolBalanceToken0 * priceToken0 + poolBalanceToken1 * priceToken1,
864
+ });
865
+ }
866
+ }
867
+ }
868
+ return dynamicData;
869
+ },
870
+ },
871
+ };
872
+ }
873
+ // Fallback in case something fails
874
+ return {
875
+ cached: false,
876
+ call: {
877
+ callData: [],
878
+ handler: () => { },
879
+ reducer: async (_result) => {
880
+ return campaigns;
881
+ },
882
+ },
883
+ };
884
+ }
885
+ function getForwarderAprbreakDown(distributionForwarders, alm, campaign, pool, yearlyToken0Rewards, yearlyToken1Rewards, yearlyFeeRewards, poolBalanceToken0WithoutBlacklist, poolBalanceToken1WithoutBlacklist, poolLiquidityWithoutBlacklist, tvl, distributionMeanAPR, index, chainId, amm) {
886
+ if (!distributionForwarders)
887
+ return null;
888
+ let aprBreakdowns = null;
889
+ const targetForwarder = distributionForwarders.filter(f => f.almAddress.toLowerCase() === alm.target.toLowerCase())?.[0];
890
+ const isALMWhitelisted = campaign.campaignParameters.whitelist.length > 0
891
+ ? isStrykeCampaign(pool.amm)
892
+ ? true
893
+ : isWhitelisted(alm.sender, campaign.campaignParameters.whitelist) ||
894
+ isWhitelisted(alm.almAddress, campaign.campaignParameters.whitelist) ||
895
+ isWhitelisted(!!alm?.owner ? alm.owner : "", campaign.campaignParameters.whitelist) ||
896
+ isWhitelisted(!!alm?.target ? alm.target : "", campaign.campaignParameters.whitelist) ||
897
+ (!!targetForwarder?.owner && isWhitelisted(targetForwarder?.owner, campaign.campaignParameters.whitelist))
898
+ : true;
899
+ const isBlacklistedByCampaign = isBlacklisted(alm.sender, campaign.campaignParameters.blacklist) ||
900
+ isBlacklisted(alm.almAddress, campaign.campaignParameters.blacklist) ||
901
+ (!!alm?.target && isBlacklisted(alm?.target, campaign.campaignParameters.blacklist)) ||
902
+ !isALMWhitelisted;
903
+ if (!isBlacklistedByCampaign && !!alm.almTVL && alm.almTVL > 0) {
904
+ try {
905
+ // Token 0 APR
906
+ const almToken0APR = (yearlyToken0Rewards * (alm?.almBalance0 ?? 0 - alm?.almIdleBalance0 ?? 0)) /
907
+ poolBalanceToken0WithoutBlacklist /
908
+ alm.almTVL;
909
+ // Token 1 APR
910
+ const almToken1APR = (yearlyToken1Rewards * (alm?.almBalance1 ?? 0 - alm?.almIdleBalance1 ?? 0)) /
911
+ poolBalanceToken1WithoutBlacklist /
912
+ alm.almTVL;
913
+ // Fee APR
914
+ const almFeeAPR = (yearlyFeeRewards * (alm?.almInRangeLiquidity ?? 0)) / poolLiquidityWithoutBlacklist / alm.almTVL;
915
+ let aprValue = almToken0APR + almToken1APR + almFeeAPR;
916
+ // computation is less precise here as we don't have the details of balances
917
+ if (isStrykeCampaign(amm))
918
+ aprValue = (yearlyToken0Rewards + yearlyToken1Rewards + yearlyFeeRewards) / tvl;
919
+ /** Fix to tackle discrepancies in the APRs when there is a whitelist */
920
+ if ((campaign.campaignParameters.whitelist?.length === 1 &&
921
+ (isWhitelisted(alm.sender, campaign.campaignParameters.whitelist) ||
922
+ isWhitelisted(alm.almAddress, campaign.campaignParameters.whitelist) ||
923
+ isWhitelisted(!!alm?.target ? alm.target : "", campaign.campaignParameters.whitelist) ||
924
+ isWhitelisted(!!alm?.owner ? alm.owner : "", campaign.campaignParameters.whitelist))) ||
925
+ (!!targetForwarder?.owner && isWhitelisted(targetForwarder?.owner, campaign.campaignParameters.whitelist))) {
926
+ if (aprValue < distributionMeanAPR || !aprValue || aprValue > 1e12)
927
+ aprValue = distributionMeanAPR;
928
+ }
929
+ aprBreakdowns = {
930
+ address: pool.address,
931
+ value: aprValue,
932
+ type: EAprBreakdownType.FORWARDER,
933
+ label: almName(alm.origin),
934
+ };
935
+ distributionForwarders[index].almAPR = aprValue; // @Hugo wip: new way to structure aprBreakdowns + check this
936
+ }
937
+ catch (e) {
938
+ log.error("CLAMMDynamicData", `failed to compute ALM APR for ${alm.almAddress} (sender ${alm.sender}) on ${NETWORK_LABELS[chainId]}: ${e}`);
939
+ }
940
+ }
941
+ return aprBreakdowns;
942
+ }