@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,268 @@
1
+ import { getTokensListWithCache } from "../../../libs/getTokensList";
2
+ import { getOnlyUserBalance } from "../../../libs/tokens/balances";
3
+ import { executeSimple } from "../../../utils/execute";
4
+ import { log } from "../../../utils/logger";
5
+ import { apiDbClient } from "../../../utils/prisma";
6
+ import { Prisma } from "../../../../database/api/.generated";
7
+ import { NETWORK_LABELS, bigIntToNumber } from "@sdk";
8
+ import { parseUnits } from "viem";
9
+ import { TokenRepository } from "./token.repository";
10
+ export class TokenService {
11
+ static hashId(token) {
12
+ return Bun.hash(`${token.chainId}${token.address}`).toString();
13
+ }
14
+ /**
15
+ * Fetches balances of provided tokens
16
+ */
17
+ static async fetchBalances(chainId, userAddress, tokens) {
18
+ const balances = await executeSimple(chainId, getOnlyUserBalance(chainId, userAddress, tokens.map(t => t.address)));
19
+ const tokensWithBalances = tokens.map(t => {
20
+ const balance = balances[t.address] ??
21
+ balances[Object.keys(balances).find(a => a?.toLowerCase() === t.address?.toLowerCase()) ?? ""];
22
+ return Object.assign(t, { balance: BigInt(balance?.balance ?? 0) });
23
+ });
24
+ return tokensWithBalances.sort((b, a) => {
25
+ const aN = parseUnits(a.balance.toString(), a.decimals);
26
+ const bN = parseUnits(b.balance.toString(), b.decimals);
27
+ return aN < bN ? -1 : aN > bN ? 1 : 0;
28
+ });
29
+ }
30
+ /**
31
+ * Fetches tokens and include balances
32
+ */
33
+ static async fetchTokensAndBalances(chainId, userAddress, addresses) {
34
+ const tokens = await TokenService.getManyOrCreate(addresses?.map(address => ({ chainId, address })));
35
+ return TokenService.fetchBalances(chainId, userAddress, tokens.filter(t => t !== undefined));
36
+ }
37
+ /**
38
+ * Fetches balances of verified tokens
39
+ * @info tokens that are popular and must be detected in the app are marked as 'verified'
40
+ * @param additionalTokens balances along with the verified ones
41
+ */
42
+ static async fetchVerifiedBalances(chainId, userAddress, additionalTokenAddresses) {
43
+ const verifiedTokens = await TokenService.findMany({ chainId: chainId, verified: true });
44
+ const additionalTokens = !!additionalTokenAddresses?.length
45
+ ? await TokenService.getManyOrCreate(additionalTokenAddresses?.map(address => ({ chainId, address })))
46
+ : [];
47
+ const allTokens = verifiedTokens.concat(additionalTokens.filter(t => t !== undefined));
48
+ return TokenService.fetchBalances(chainId, userAddress, allTokens);
49
+ }
50
+ static async fetchOnChain(token) {
51
+ const onchainData = await TokenRepository.getTokenInfo(token);
52
+ //TODO: find a way to get the icon
53
+ return {
54
+ chainId: token.chainId,
55
+ address: token.address,
56
+ icon: "",
57
+ ...Object.assign({ name: "unknown", decimals: 18, symbol: "UNKNOWN", verified: false }, onchainData),
58
+ };
59
+ }
60
+ static async fetchManyOnChain(chainId, addresses) {
61
+ const tokens = {};
62
+ //Batch onchain calls together when multiples
63
+ for (const address of addresses) {
64
+ tokens[address] = await TokenService.fetchOnChain({ chainId, address });
65
+ }
66
+ return tokens;
67
+ }
68
+ /**
69
+ * Updates price of tokens that share the same symbol
70
+ * @param symbol
71
+ * @param price value
72
+ * @param excludeAddresses to not update symbols that defined using addresses
73
+ */
74
+ static async updateSymbolPrices(symbol, price, excludeAddresses) {
75
+ return await TokenRepository.updateSymbolPrices(symbol, price, excludeAddresses);
76
+ }
77
+ /**
78
+ * Updates price of tokens that share the same address
79
+ * @param address
80
+ * @param price value
81
+ * @param chainId
82
+ */
83
+ static async updateAddressPrices(address, price, chainId) {
84
+ return await TokenRepository.updateAddressPrices(address, price, chainId);
85
+ }
86
+ /**
87
+ * Updates price of tokens that share the same symbol
88
+ * @param symbol
89
+ * @param price value
90
+ * @param excludeAddresses to not update symbols that defined using addresses
91
+ */
92
+ static async updatePrices(pricer) {
93
+ const pricedAddresses = Object.keys(pricer.prices).filter(address => address.startsWith("0x"));
94
+ const symbols = Object.keys(pricer.prices).filter(address => !address.startsWith("0x"));
95
+ for (const symbol of symbols) {
96
+ const price = await pricer.get({ symbol });
97
+ if (!price)
98
+ continue;
99
+ await TokenService.updateSymbolPrices(symbol, price, pricedAddresses);
100
+ }
101
+ for (const address of pricedAddresses) {
102
+ const price = await pricer.get({ address });
103
+ if (!price)
104
+ continue;
105
+ await TokenService.updateAddressPrices(address, price);
106
+ }
107
+ }
108
+ /**
109
+ * Get all tokens from https://github.com/AngleProtocol/angle-token-list and override icons from it
110
+ * TODO: use the bucket
111
+ */
112
+ static async fillTokenAndIconsFromTokenList() {
113
+ const tokenList = await getTokensListWithCache();
114
+ for (const chain of Object.keys(tokenList)) {
115
+ for (const [symbol, token] of Object.entries(tokenList[chain])) {
116
+ if (!(await TokenRepository.findUnique(TokenService.hashId({ chainId: Number.parseInt(chain), address: token.address })))) {
117
+ try {
118
+ const res = await TokenRepository.create({
119
+ id: TokenService.hashId({ chainId: Number.parseInt(chain), address: token.address }),
120
+ chainId: Number.parseInt(chain),
121
+ address: token.address,
122
+ name: token.name,
123
+ symbol: token.symbol,
124
+ verified: true,
125
+ decimals: token.decimals,
126
+ icon: token.logoURI,
127
+ });
128
+ log.local(`Token created: ${res?.symbol} on ${NETWORK_LABELS[Number.parseInt(chain)]}`);
129
+ }
130
+ catch (e) {
131
+ console.error(e);
132
+ }
133
+ try {
134
+ const res = await TokenRepository.create({
135
+ id: TokenService.hashId({ chainId: Number.parseInt(chain), address: token.address }),
136
+ chainId: Number.parseInt(chain),
137
+ address: token.address,
138
+ name: token.name,
139
+ symbol: token.symbol,
140
+ verified: true,
141
+ decimals: token.decimals,
142
+ icon: token.logoURI,
143
+ });
144
+ log.local(`Token created: ${res?.symbol} on ${NETWORK_LABELS[Number.parseInt(chain)]}`);
145
+ }
146
+ catch (e) {
147
+ console.error(e);
148
+ }
149
+ }
150
+ try {
151
+ await apiDbClient.token.update({
152
+ data: {
153
+ chainId: Number.parseInt(chain),
154
+ address: token.address,
155
+ name: token.name,
156
+ symbol: token.symbol,
157
+ verified: true,
158
+ decimals: token.decimals,
159
+ icon: token.logoURI,
160
+ },
161
+ where: {
162
+ chainId_address: {
163
+ chainId: Number.parseInt(chain),
164
+ address: token.address,
165
+ },
166
+ },
167
+ });
168
+ }
169
+ catch (e) {
170
+ console.error(e);
171
+ }
172
+ try {
173
+ const tokensWithSameSymbol = await apiDbClient.token.findMany({
174
+ select: { chainId: true, address: true },
175
+ where: { symbol: { equals: symbol, mode: "insensitive" } },
176
+ });
177
+ for (const dbToken of tokensWithSameSymbol) {
178
+ await apiDbClient.token.update({
179
+ data: { icon: token.logoURI },
180
+ where: {
181
+ chainId_address: {
182
+ chainId: dbToken.chainId,
183
+ address: dbToken.address,
184
+ },
185
+ },
186
+ });
187
+ }
188
+ }
189
+ catch (_err) { }
190
+ }
191
+ }
192
+ }
193
+ /**
194
+ * Create token on database
195
+ * @param chainId
196
+ * @param address
197
+ */
198
+ static async create(token) {
199
+ const id = TokenService.hashId(token);
200
+ return TokenRepository.upsert({ ...token, id });
201
+ }
202
+ /**
203
+ * Read token from database
204
+ * @param chainId
205
+ * @param address
206
+ */
207
+ static async findUniqueOrThrow(token) {
208
+ return await TokenRepository.findUniqueOrThrow(TokenService.hashId({ chainId: token.chainId, address: token.address }));
209
+ }
210
+ /**
211
+ * Get the list of tokens satisfying the query
212
+ * @param query
213
+ * @returns A list of tokens
214
+ */
215
+ static async findMany(query) {
216
+ return await TokenRepository.findMany(query);
217
+ }
218
+ /**
219
+ * Get value of tokens
220
+ * @param tokenAmounts address/chain + amount of token
221
+ * @returns the cumulated dollar value of all tokens
222
+ */
223
+ static async getValue(tokenAmounts) {
224
+ const tokens = await TokenService.getManyOrCreate(tokenAmounts.map(({ address, chainId }) => ({ address, chainId })));
225
+ return tokenAmounts.reduce((sum, { amount, address, chainId }) => {
226
+ const token = tokens
227
+ .filter(t => t !== undefined)
228
+ .find(({ address: addr, chainId: chain }) => addr === address && chainId === chain);
229
+ if (!token)
230
+ return sum;
231
+ const value = (bigIntToNumber(amount, token.decimals) ?? 0) * (token.price ?? 0);
232
+ return sum + value;
233
+ }, 0);
234
+ }
235
+ /**
236
+ * Counts the number of tokens that complies to query
237
+ * @description used for pagination purposes
238
+ * @param query
239
+ * @returns the number of tokens
240
+ */
241
+ static async countMany(query) {
242
+ return await TokenRepository.countMany(query);
243
+ }
244
+ static async findChains() {
245
+ return await TokenRepository.findChains();
246
+ }
247
+ /**
248
+ * Read token from DB or fetch onchain
249
+ * @param chainId
250
+ * @param address
251
+ */
252
+ static async getManyOrCreate(tokens) {
253
+ return await Promise.all(tokens.map(async (token) => {
254
+ const id = TokenService.hashId(token);
255
+ try {
256
+ return await TokenRepository.findUniqueOrThrow(id);
257
+ }
258
+ catch (err) {
259
+ if (err instanceof Prisma.PrismaClientKnownRequestError && err.code === "P2025") {
260
+ const newToken = await TokenService.fetchOnChain(token);
261
+ if (!newToken)
262
+ return;
263
+ return await TokenRepository.upsert({ ...newToken, id });
264
+ }
265
+ }
266
+ }));
267
+ }
268
+ }
@@ -0,0 +1,2 @@
1
+ export * from "./tvl.model";
2
+ export * from "./tvl.service";
@@ -0,0 +1 @@
1
+ "use strict";
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1 @@
1
+ "use strict";
@@ -0,0 +1,49 @@
1
+ import { TvlType } from "../../../../database/api/.generated";
2
+ import { Campaign } from "@sdk";
3
+ import moment from "moment";
4
+ export class TvlService {
5
+ static hashId(opportunityId, timestamp) {
6
+ return Bun.hash(`${opportunityId}${timestamp}`).toString();
7
+ }
8
+ static extractFromDynamicData(type, dynamicData, timestamp = BigInt(moment().unix())) {
9
+ const typesWithoutApr = [Campaign.INVALID, Campaign.JSON_AIRDROP, Campaign.ERC20_SNAPSHOT];
10
+ if (typesWithoutApr.includes(type))
11
+ return { timestamp, total: 0, breakdowns: [] };
12
+ const opportunitySummary = dynamicData.reduce((merged, c) => Object.assign(merged, c), {});
13
+ let breakdowns = [];
14
+ if (type === Campaign.CLAMM) {
15
+ breakdowns = [
16
+ {
17
+ identifier: opportunitySummary.campaignParameters.token0,
18
+ type: TvlType.TOKEN,
19
+ value: Number.isNaN(Number(opportunitySummary.poolBalanceToken0))
20
+ ? 0
21
+ : Number(opportunitySummary.poolBalanceToken0),
22
+ },
23
+ {
24
+ identifier: opportunitySummary.campaignParameters.token1,
25
+ type: TvlType.TOKEN,
26
+ value: Number.isNaN(Number(opportunitySummary.poolBalanceToken1))
27
+ ? 0
28
+ : Number(opportunitySummary.poolBalanceToken1),
29
+ },
30
+ ];
31
+ for (const campaign of dynamicData) {
32
+ if (campaign.forwarders) {
33
+ for (const forwarder of campaign.forwarders) {
34
+ breakdowns.push({
35
+ identifier: forwarder.label,
36
+ type: TvlType.PROTOCOL,
37
+ value: Number.isNaN(Number(forwarder.almTVL)) ? 0 : Number(forwarder.almTVL),
38
+ });
39
+ }
40
+ }
41
+ }
42
+ }
43
+ return {
44
+ timestamp,
45
+ total: Number.isNaN(Number(opportunitySummary.tvl)) ? 0 : Number(opportunitySummary.tvl),
46
+ breakdowns,
47
+ };
48
+ }
49
+ }
@@ -0,0 +1,4 @@
1
+ export * from "./uniswapV4.controller";
2
+ export * from "./uniswapV4.service";
3
+ export * from "./uniswapV4.repository";
4
+ export * from "./uniswapV4.model";
@@ -0,0 +1,11 @@
1
+ import Elysia, { t } from "elysia";
2
+ import { UniswapV4Service } from "./uniswapV4.service";
3
+ export const uniswapV4Controller = new Elysia().group("uniswapV4", app => {
4
+ return app.get("/pools", async ({ query }) => {
5
+ return await UniswapV4Service.getPoolsByChain(query.chainId);
6
+ }, {
7
+ query: t.Object({
8
+ chainId: t.Numeric(),
9
+ }),
10
+ });
11
+ });
@@ -0,0 +1,17 @@
1
+ import { t } from "elysia";
2
+ const UniswapV4PoolKeyDto = t.Object({
3
+ currency0: t.String(),
4
+ currency1: t.String(),
5
+ fee: t.Numeric(),
6
+ tickSpacing: t.Numeric(),
7
+ hooks: t.String(),
8
+ });
9
+ const UniswapV4PoolDto = t.Object({
10
+ poolKey: UniswapV4PoolKeyDto,
11
+ poolId: t.String(),
12
+ decimalsCurrency0: t.Numeric(),
13
+ decimalsCurrency1: t.Numeric(),
14
+ symbolCurrency0: t.String(),
15
+ symbolCurrency1: t.String(),
16
+ });
17
+ export const UniswapV4PoolsDto = t.Record(t.String(), UniswapV4PoolDto);
@@ -0,0 +1,2 @@
1
+ export class UniswapV4Repository {
2
+ }
@@ -0,0 +1,73 @@
1
+ import { safeFetchLogs } from "../../../libs/campaigns/utils/fetchLogs";
2
+ import { batchMulticallCallWithRetry } from "../../../utils/generic";
3
+ import { providers } from "../../../utils/providers";
4
+ import { ERC20Interface, UniswapV4PoolManager__factory } from "@sdk";
5
+ import { utils } from "ethers";
6
+ export const PoolManagerInterface = UniswapV4PoolManager__factory.createInterface();
7
+ export class UniswapV4Service {
8
+ static async getPoolsByChain(chainId) {
9
+ const lastBlock = await providers[chainId].getBlockNumber();
10
+ const logs = await safeFetchLogs(chainId, [PoolManagerInterface.getEventTopic("Initialize")], ["0xE8E23e97Fa135823143d6b9Cba9c699040D51F70"], 0, lastBlock);
11
+ const poolData = [];
12
+ const calls = [];
13
+ for (const log of logs) {
14
+ const poolId = utils.defaultAbiCoder.decode(["bytes32"], log.topics[1])[0];
15
+ const currency0 = utils.defaultAbiCoder.decode(["address"], log.topics[2])[0];
16
+ const currency1 = utils.defaultAbiCoder.decode(["address"], log.topics[3])[0];
17
+ const [_indexedPoolId, _indexedCurrency0, _indexedCurrency1, fee, tickSpacing, hooks, sqrtPriceX98, tick] = PoolManagerInterface.decodeEventLog("Initialize", log.data, log.topics);
18
+ poolData.push({
19
+ poolId,
20
+ poolKey: {
21
+ currency0,
22
+ currency1,
23
+ fee,
24
+ tickSpacing,
25
+ hooks,
26
+ },
27
+ });
28
+ calls.push({
29
+ allowFailure: true,
30
+ callData: ERC20Interface.encodeFunctionData("symbol"),
31
+ target: currency0,
32
+ }, {
33
+ allowFailure: true,
34
+ callData: ERC20Interface.encodeFunctionData("decimals"),
35
+ target: currency0,
36
+ }, {
37
+ allowFailure: true,
38
+ callData: ERC20Interface.encodeFunctionData("symbol"),
39
+ target: currency1,
40
+ }, {
41
+ allowFailure: true,
42
+ callData: ERC20Interface.encodeFunctionData("decimals"),
43
+ target: currency1,
44
+ });
45
+ }
46
+ const result = await batchMulticallCallWithRetry(chainId, { calls });
47
+ const res = {};
48
+ for (const [index, pool] of poolData.entries()) {
49
+ let symbolCurrency0 = "";
50
+ let decimalsCurrency0 = 0;
51
+ let symbolCurrency1 = "";
52
+ let decimalsCurrency1 = 0;
53
+ try {
54
+ symbolCurrency0 = ERC20Interface.decodeFunctionResult("symbol", result[index * 4].returnData)[0];
55
+ }
56
+ catch { }
57
+ try {
58
+ decimalsCurrency0 = ERC20Interface.decodeFunctionResult("decimals", result[index * 4 + 1].returnData)[0];
59
+ }
60
+ catch { }
61
+ try {
62
+ symbolCurrency1 = ERC20Interface.decodeFunctionResult("symbol", result[index * 4 + 2].returnData)[0];
63
+ }
64
+ catch { }
65
+ try {
66
+ decimalsCurrency1 = ERC20Interface.decodeFunctionResult("decimals", result[index * 4 + 3].returnData)[0];
67
+ }
68
+ catch { }
69
+ res[pool.poolId] = { ...pool, symbolCurrency0, decimalsCurrency0, symbolCurrency1, decimalsCurrency1 };
70
+ }
71
+ return res;
72
+ }
73
+ }
@@ -0,0 +1,3 @@
1
+ export * from "./user.controller";
2
+ export * from "./user.model";
3
+ export * from "./user.service";
@@ -0,0 +1,69 @@
1
+ import { AuthorizationHeadersDto, BackOfficeGuard } from "../../../guards/BackOffice.guard";
2
+ import { throwOnInvalidRequiredAddress, throwOnUnsupportedChainId } from "../../../utils/throw";
3
+ import { Elysia } from "elysia";
4
+ import { ChainArrayDto } from "../chain";
5
+ import { RewardService } from "../reward";
6
+ import { GetManyUserQuery, UpdateUserTagsDto, UserDto, UserUniqueDto } from "./user.model";
7
+ import { UserService } from "./user.service";
8
+ // ─── Users Controller ────────────────────────────────────────────────────────
9
+ export const UserController = new Elysia({ prefix: "/users", detail: { tags: ["Users"] } })
10
+ // ─── Get Many Users ──────────────────────────────────────────────────
11
+ .get("/", async ({ query }) => {
12
+ return await UserService.findMany(query);
13
+ }, { query: GetManyUserQuery })
14
+ // ─── Get All Tagged Users ─────────────────────────────────────────────
15
+ .get("/tags", async () => {
16
+ return await UserService.findManyWithTags();
17
+ }, { headers: AuthorizationHeadersDto, beforeHandle: BackOfficeGuard })
18
+ // ─── Get A User By Address ───────────────────────────────────────────
19
+ .get("/:address", async ({ params }) => {
20
+ return await UserService.findUnique(params.address);
21
+ })
22
+ // ─── Get User's Rewards With Breakdown And Details for our FE ────────
23
+ .get(
24
+ // TODO: redefine as /:address/rewards/breakdowns to follow REST standard (URI components should be nouns)
25
+ "/:address/rewards/full", async ({ params }) => {
26
+ const rewardsByChain = await RewardService.getUserRewardsByChain(params.address, true);
27
+ return RewardService.splitRewardsBreakdownByOpportunity(rewardsByChain);
28
+ }, {
29
+ params: UserUniqueDto,
30
+ beforeHandle: ({ params }) => {
31
+ params.address = throwOnInvalidRequiredAddress(params.address);
32
+ },
33
+ })
34
+ // ─── Get User's Rewards With Breakdown ──────────────────────────────
35
+ .get("/:address/rewards", async ({ params, query }) => {
36
+ const rewardsByChain = await RewardService.getUserRewardsByChain(params.address, false, typeof query.chainId === "number" ? [query.chainId] : query.chainId);
37
+ return RewardService.removeOpportunityFromRewardBreakdown(rewardsByChain);
38
+ }, {
39
+ params: UserUniqueDto,
40
+ query: ChainArrayDto,
41
+ beforeHandle: ({ query, params }) => {
42
+ params.address = throwOnInvalidRequiredAddress(params.address);
43
+ if (typeof query.chainId === "number") {
44
+ throwOnUnsupportedChainId(query.chainId);
45
+ }
46
+ else {
47
+ for (const chainId of query.chainId) {
48
+ throwOnUnsupportedChainId(chainId);
49
+ }
50
+ }
51
+ },
52
+ })
53
+ // ─── Create A User ───────────────────────────────────────────────────
54
+ .post("/", async ({ body }) => {
55
+ return await UserService.create(body);
56
+ }, { headers: AuthorizationHeadersDto, body: UserDto, beforeHandle: BackOfficeGuard })
57
+ // ─── Sync Creator Tags with Engine DB ─────────────────────────────────
58
+ .post("/sync", async () => {
59
+ return await UserService.syncTags();
60
+ }, { headers: AuthorizationHeadersDto, beforeHandle: BackOfficeGuard })
61
+ // ─── Update User's Tags ──────────────────────────────────────────────
62
+ .patch("/:address/tags", async ({ params, body }) => {
63
+ return await UserService.updateTags(params.address, body.tags);
64
+ }, {
65
+ headers: AuthorizationHeadersDto,
66
+ params: UserUniqueDto,
67
+ body: UpdateUserTagsDto,
68
+ beforeHandle: BackOfficeGuard,
69
+ });
@@ -0,0 +1,18 @@
1
+ import { t } from "elysia";
2
+ // ─── Dtos ────────────────────────────────────────────────────────────────────
3
+ export const UserUniqueDto = t.Object({
4
+ address: t.String(),
5
+ });
6
+ export const UserDto = t.Object({
7
+ address: t.String(),
8
+ tags: t.Array(t.String()),
9
+ });
10
+ export const GetManyUserQuery = t.Object({
11
+ address: t.Optional(t.String()),
12
+ tags: t.Optional(t.Array(t.String())),
13
+ page: t.Optional(t.Number()),
14
+ items: t.Optional(t.Number()),
15
+ });
16
+ export const UpdateUserTagsDto = t.Object({
17
+ tags: t.Array(t.String()),
18
+ });
@@ -0,0 +1,38 @@
1
+ import { apiDbClient } from "../../../utils/prisma";
2
+ // ─── Users Repository ────────────────────────────────────────────────────────
3
+ export class UserRepository {
4
+ static async findUnique(address) {
5
+ return await apiDbClient.user.findUnique({ where: { address } });
6
+ }
7
+ static async findMany(query) {
8
+ const { page: _page, items: _items, ...filters } = query;
9
+ const page = _page ? _page : 0;
10
+ const items = _items ? _items : 20;
11
+ return await apiDbClient.user.findMany({
12
+ take: items,
13
+ skip: page * items,
14
+ where: {
15
+ address: filters.address ? filters.address : undefined,
16
+ tags: filters.tags ? { hasEvery: filters.tags } : undefined,
17
+ },
18
+ });
19
+ }
20
+ static async findManyWithTags() {
21
+ return await apiDbClient.user.findMany({
22
+ where: {
23
+ tags: {
24
+ isEmpty: false,
25
+ },
26
+ },
27
+ });
28
+ }
29
+ static async create(user) {
30
+ return await apiDbClient.user.create({ data: user });
31
+ }
32
+ static async createMany(users) {
33
+ return await apiDbClient.user.createMany({ data: users, skipDuplicates: true });
34
+ }
35
+ static async updateTags(address, tags) {
36
+ return await apiDbClient.user.update({ where: { address }, data: { tags } });
37
+ }
38
+ }
@@ -0,0 +1,50 @@
1
+ import { log } from "../../../utils/logger";
2
+ import { engineDbClient } from "../../../utils/prisma";
3
+ import { UserRepository } from "./user.repository";
4
+ // ─── Users Services ──────────────────────────────────────────────────────────
5
+ export class UserService {
6
+ static async findUnique(address) {
7
+ return await UserRepository.findUnique(address);
8
+ }
9
+ static async findMany(query) {
10
+ return await UserRepository.findMany(query);
11
+ }
12
+ static async findManyWithTags() {
13
+ return await UserRepository.findManyWithTags();
14
+ }
15
+ static async create(user) {
16
+ return await UserRepository.create(user);
17
+ }
18
+ static async createMany(users) {
19
+ return await UserRepository.createMany(users);
20
+ }
21
+ static async updateTags(user, tags) {
22
+ return await UserRepository.updateTags(user, tags);
23
+ }
24
+ static async syncTags() {
25
+ // 1 - engine -> api db
26
+ const creatorTags = await engineDbClient.campaignCreators.findMany();
27
+ log.info(`syncing ${creatorTags.length} creator tags`);
28
+ await UserRepository.createMany(creatorTags.map(tag => {
29
+ return {
30
+ address: tag.address,
31
+ tags: [],
32
+ };
33
+ }));
34
+ for (const tag of creatorTags) {
35
+ await UserRepository.updateTags(tag.address, tag.tags.split(",").map(tag => tag.trim()));
36
+ }
37
+ // 2 - api -> engine db
38
+ const apiUsers = await UserRepository.findManyWithTags();
39
+ for (const tag of creatorTags) {
40
+ if (creatorTags.findIndex(t => t.address === tag.address) === -1) {
41
+ await engineDbClient.campaignCreators.create({
42
+ data: {
43
+ address: tag.address,
44
+ tags: apiUsers.find(u => u.address === tag.address)?.tags.join(",") || "",
45
+ },
46
+ });
47
+ }
48
+ }
49
+ }
50
+ }
@@ -0,0 +1,28 @@
1
+ import { BadRequestError, ConflictError, HttpError, NotFoundError, UnauthorizedError } from "../errors";
2
+ import { log } from "../utils/logger";
3
+ import Elysia from "elysia";
4
+ // ─── Error Handler Plugin ────────────────────────────────────────────────────
5
+ export const ErrorHandler = new Elysia()
6
+ // ─── Error Types ─────────────────────────────────────────────────────
7
+ .error({
8
+ HttpError,
9
+ BadRequestError,
10
+ ConflictError,
11
+ NotFoundError,
12
+ UnauthorizedError,
13
+ })
14
+ // ─── Error Handling ──────────────────────────────────────────────────
15
+ .onError(({ code, error, set }) => {
16
+ if (code === "HttpError") {
17
+ log.error("HttpError", error);
18
+ set.status = error.httpCode;
19
+ set.headers["content-type"] = "application/json";
20
+ return {
21
+ name: error.name,
22
+ message: error.message,
23
+ info: error.info,
24
+ };
25
+ }
26
+ log.error("Unknown error", error);
27
+ return error;
28
+ });