eco-solver 0.0.1-security → 1.5.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of eco-solver might be problematic. Click here for more details.

Files changed (244) hide show
  1. package/.eslintignore +8 -0
  2. package/.eslintrc.js +24 -0
  3. package/.github/workflows/ci.yaml +38 -0
  4. package/.nvmrc +1 -0
  5. package/.prettierignore +3 -0
  6. package/.prettierrc +8 -0
  7. package/Dockerfile +11 -0
  8. package/LICENSE +21 -0
  9. package/README.md +29 -5
  10. package/config/default.ts +135 -0
  11. package/config/development.ts +95 -0
  12. package/config/preproduction.ts +17 -0
  13. package/config/production.ts +17 -0
  14. package/config/staging.ts +17 -0
  15. package/config/test.ts +7 -0
  16. package/index.js +43 -0
  17. package/jest.config.ts +14 -0
  18. package/nest-cli.json +8 -0
  19. package/package.json +117 -6
  20. package/src/api/api.module.ts +27 -0
  21. package/src/api/balance.controller.ts +41 -0
  22. package/src/api/quote.controller.ts +54 -0
  23. package/src/api/tests/balance.controller.spec.ts +113 -0
  24. package/src/api/tests/quote.controller.spec.ts +83 -0
  25. package/src/app.module.ts +74 -0
  26. package/src/balance/balance.module.ts +14 -0
  27. package/src/balance/balance.service.ts +230 -0
  28. package/src/balance/balance.ws.service.ts +104 -0
  29. package/src/balance/types.ts +16 -0
  30. package/src/bullmq/bullmq.helper.ts +41 -0
  31. package/src/bullmq/processors/eth-ws.processor.ts +47 -0
  32. package/src/bullmq/processors/inbox.processor.ts +55 -0
  33. package/src/bullmq/processors/interval.processor.ts +54 -0
  34. package/src/bullmq/processors/processor.module.ts +14 -0
  35. package/src/bullmq/processors/signer.processor.ts +41 -0
  36. package/src/bullmq/processors/solve-intent.processor.ts +73 -0
  37. package/src/bullmq/processors/tests/solve-intent.processor.spec.ts +3 -0
  38. package/src/bullmq/utils/queue.ts +22 -0
  39. package/src/chain-monitor/chain-monitor.module.ts +12 -0
  40. package/src/chain-monitor/chain-sync.service.ts +134 -0
  41. package/src/chain-monitor/tests/chain-sync.service.spec.ts +190 -0
  42. package/src/commander/.eslintrc.js +6 -0
  43. package/src/commander/balance/balance-command.module.ts +12 -0
  44. package/src/commander/balance/balance.command.ts +73 -0
  45. package/src/commander/command-main.ts +15 -0
  46. package/src/commander/commander-app.module.ts +31 -0
  47. package/src/commander/eco-config.command.ts +20 -0
  48. package/src/commander/safe/safe-command.module.ts +11 -0
  49. package/src/commander/safe/safe.command.ts +70 -0
  50. package/src/commander/transfer/client.command.ts +24 -0
  51. package/src/commander/transfer/transfer-command.module.ts +26 -0
  52. package/src/commander/transfer/transfer.command.ts +138 -0
  53. package/src/commander/utils.ts +8 -0
  54. package/src/common/chains/definitions/arbitrum.ts +12 -0
  55. package/src/common/chains/definitions/base.ts +21 -0
  56. package/src/common/chains/definitions/eco.ts +54 -0
  57. package/src/common/chains/definitions/ethereum.ts +22 -0
  58. package/src/common/chains/definitions/helix.ts +53 -0
  59. package/src/common/chains/definitions/mantle.ts +12 -0
  60. package/src/common/chains/definitions/optimism.ts +22 -0
  61. package/src/common/chains/definitions/polygon.ts +12 -0
  62. package/src/common/chains/supported.ts +26 -0
  63. package/src/common/chains/transport.ts +19 -0
  64. package/src/common/errors/eco-error.ts +155 -0
  65. package/src/common/events/constants.ts +3 -0
  66. package/src/common/events/viem.ts +22 -0
  67. package/src/common/logging/eco-log-message.ts +74 -0
  68. package/src/common/redis/constants.ts +55 -0
  69. package/src/common/redis/redis-connection-utils.ts +106 -0
  70. package/src/common/routes/constants.ts +3 -0
  71. package/src/common/utils/objects.ts +34 -0
  72. package/src/common/utils/strings.ts +49 -0
  73. package/src/common/utils/tests/objects.spec.ts +23 -0
  74. package/src/common/utils/tests/strings.spec.ts +22 -0
  75. package/src/common/viem/contracts.ts +25 -0
  76. package/src/common/viem/tests/utils.spec.ts +115 -0
  77. package/src/common/viem/utils.ts +78 -0
  78. package/src/contracts/ERC20.contract.ts +389 -0
  79. package/src/contracts/EntryPoint.V6.contract.ts +1309 -0
  80. package/src/contracts/KernelAccount.abi.ts +87 -0
  81. package/src/contracts/OwnableExecutor.abi.ts +128 -0
  82. package/src/contracts/SimpleAccount.contract.ts +524 -0
  83. package/src/contracts/inbox.ts +8 -0
  84. package/src/contracts/index.ts +9 -0
  85. package/src/contracts/intent-source.ts +55 -0
  86. package/src/contracts/interfaces/index.ts +1 -0
  87. package/src/contracts/interfaces/prover.interface.ts +22 -0
  88. package/src/contracts/prover.ts +9 -0
  89. package/src/contracts/tests/erc20.contract.spec.ts +59 -0
  90. package/src/contracts/utils.ts +31 -0
  91. package/src/decoder/decoder.interface.ts +3 -0
  92. package/src/decoder/tests/utils.spec.ts +36 -0
  93. package/src/decoder/utils.ts +24 -0
  94. package/src/decorators/cacheable.decorator.ts +48 -0
  95. package/src/eco-configs/aws-config.service.ts +75 -0
  96. package/src/eco-configs/eco-config.module.ts +44 -0
  97. package/src/eco-configs/eco-config.service.ts +220 -0
  98. package/src/eco-configs/eco-config.types.ts +278 -0
  99. package/src/eco-configs/interfaces/config-source.interface.ts +3 -0
  100. package/src/eco-configs/tests/aws-config.service.spec.ts +52 -0
  101. package/src/eco-configs/tests/eco-config.service.spec.ts +137 -0
  102. package/src/eco-configs/tests/utils.spec.ts +84 -0
  103. package/src/eco-configs/utils.ts +49 -0
  104. package/src/fee/fee.module.ts +10 -0
  105. package/src/fee/fee.service.ts +467 -0
  106. package/src/fee/tests/fee.service.spec.ts +909 -0
  107. package/src/fee/tests/utils.spec.ts +49 -0
  108. package/src/fee/types.ts +44 -0
  109. package/src/fee/utils.ts +23 -0
  110. package/src/flags/flags.module.ts +10 -0
  111. package/src/flags/flags.service.ts +112 -0
  112. package/src/flags/tests/flags.service.spec.ts +68 -0
  113. package/src/flags/utils.ts +22 -0
  114. package/src/health/constants.ts +1 -0
  115. package/src/health/health.controller.ts +23 -0
  116. package/src/health/health.module.ts +25 -0
  117. package/src/health/health.service.ts +40 -0
  118. package/src/health/indicators/balance.indicator.ts +196 -0
  119. package/src/health/indicators/eco-redis.indicator.ts +23 -0
  120. package/src/health/indicators/git-commit.indicator.ts +67 -0
  121. package/src/health/indicators/mongodb.indicator.ts +11 -0
  122. package/src/health/indicators/permission.indicator.ts +64 -0
  123. package/src/intent/create-intent.service.ts +129 -0
  124. package/src/intent/feasable-intent.service.ts +80 -0
  125. package/src/intent/fulfill-intent.service.ts +318 -0
  126. package/src/intent/intent.controller.ts +199 -0
  127. package/src/intent/intent.module.ts +49 -0
  128. package/src/intent/schemas/intent-call-data.schema.ts +16 -0
  129. package/src/intent/schemas/intent-data.schema.ts +114 -0
  130. package/src/intent/schemas/intent-source.schema.ts +33 -0
  131. package/src/intent/schemas/intent-token-amount.schema.ts +14 -0
  132. package/src/intent/schemas/reward-data.schema.ts +48 -0
  133. package/src/intent/schemas/route-data.schema.ts +52 -0
  134. package/src/intent/schemas/watch-event.schema.ts +32 -0
  135. package/src/intent/tests/create-intent.service.spec.ts +215 -0
  136. package/src/intent/tests/feasable-intent.service.spec.ts +155 -0
  137. package/src/intent/tests/fulfill-intent.service.spec.ts +564 -0
  138. package/src/intent/tests/utils-intent.service.spec.ts +308 -0
  139. package/src/intent/tests/utils.spec.ts +62 -0
  140. package/src/intent/tests/validate-intent.service.spec.ts +297 -0
  141. package/src/intent/tests/validation.service.spec.ts +337 -0
  142. package/src/intent/utils-intent.service.ts +168 -0
  143. package/src/intent/utils.ts +37 -0
  144. package/src/intent/validate-intent.service.ts +176 -0
  145. package/src/intent/validation.sevice.ts +223 -0
  146. package/src/interceptors/big-int.interceptor.ts +30 -0
  147. package/src/intervals/interval.module.ts +18 -0
  148. package/src/intervals/retry-infeasable-intents.service.ts +89 -0
  149. package/src/intervals/tests/retry-infeasable-intents.service.spec.ts +167 -0
  150. package/src/kms/errors.ts +0 -0
  151. package/src/kms/kms.module.ts +12 -0
  152. package/src/kms/kms.service.ts +65 -0
  153. package/src/kms/tests/kms.service.spec.ts +60 -0
  154. package/src/liquidity-manager/jobs/check-balances-cron.job.ts +229 -0
  155. package/src/liquidity-manager/jobs/liquidity-manager.job.ts +52 -0
  156. package/src/liquidity-manager/jobs/rebalance.job.ts +61 -0
  157. package/src/liquidity-manager/liquidity-manager.module.ts +29 -0
  158. package/src/liquidity-manager/processors/base.processor.ts +117 -0
  159. package/src/liquidity-manager/processors/eco-protocol-intents.processor.ts +34 -0
  160. package/src/liquidity-manager/processors/grouped-jobs.processor.ts +103 -0
  161. package/src/liquidity-manager/queues/liquidity-manager.queue.ts +48 -0
  162. package/src/liquidity-manager/schemas/rebalance-token.schema.ts +32 -0
  163. package/src/liquidity-manager/schemas/rebalance.schema.ts +32 -0
  164. package/src/liquidity-manager/services/liquidity-manager.service.ts +188 -0
  165. package/src/liquidity-manager/services/liquidity-provider.service.ts +25 -0
  166. package/src/liquidity-manager/services/liquidity-providers/LiFi/lifi-provider.service.spec.ts +125 -0
  167. package/src/liquidity-manager/services/liquidity-providers/LiFi/lifi-provider.service.ts +117 -0
  168. package/src/liquidity-manager/services/liquidity-providers/LiFi/utils/get-transaction-hashes.ts +16 -0
  169. package/src/liquidity-manager/tests/liquidity-manager.service.spec.ts +142 -0
  170. package/src/liquidity-manager/types/token-state.enum.ts +5 -0
  171. package/src/liquidity-manager/types/types.d.ts +52 -0
  172. package/src/liquidity-manager/utils/address.ts +5 -0
  173. package/src/liquidity-manager/utils/math.ts +9 -0
  174. package/src/liquidity-manager/utils/serialize.spec.ts +24 -0
  175. package/src/liquidity-manager/utils/serialize.ts +47 -0
  176. package/src/liquidity-manager/utils/token.ts +91 -0
  177. package/src/main.ts +63 -0
  178. package/src/nest-redlock/nest-redlock.config.ts +14 -0
  179. package/src/nest-redlock/nest-redlock.interface.ts +5 -0
  180. package/src/nest-redlock/nest-redlock.module.ts +64 -0
  181. package/src/nest-redlock/nest-redlock.service.ts +59 -0
  182. package/src/prover/proof.service.ts +184 -0
  183. package/src/prover/prover.module.ts +10 -0
  184. package/src/prover/tests/proof.service.spec.ts +154 -0
  185. package/src/quote/dto/quote.intent.data.dto.ts +35 -0
  186. package/src/quote/dto/quote.reward.data.dto.ts +67 -0
  187. package/src/quote/dto/quote.route.data.dto.ts +71 -0
  188. package/src/quote/dto/types.ts +18 -0
  189. package/src/quote/errors.ts +215 -0
  190. package/src/quote/quote.module.ts +17 -0
  191. package/src/quote/quote.service.ts +299 -0
  192. package/src/quote/schemas/quote-call.schema.ts +16 -0
  193. package/src/quote/schemas/quote-intent.schema.ts +27 -0
  194. package/src/quote/schemas/quote-reward.schema.ts +24 -0
  195. package/src/quote/schemas/quote-route.schema.ts +30 -0
  196. package/src/quote/schemas/quote-token.schema.ts +14 -0
  197. package/src/quote/tests/quote.service.spec.ts +444 -0
  198. package/src/sign/atomic-signer.service.ts +24 -0
  199. package/src/sign/atomic.nonce.service.ts +114 -0
  200. package/src/sign/kms-account/kmsToAccount.ts +73 -0
  201. package/src/sign/kms-account/signKms.ts +30 -0
  202. package/src/sign/kms-account/signKmsTransaction.ts +37 -0
  203. package/src/sign/kms-account/signKmsTypedData.ts +21 -0
  204. package/src/sign/nonce.service.ts +89 -0
  205. package/src/sign/schemas/nonce.schema.ts +36 -0
  206. package/src/sign/sign.controller.ts +52 -0
  207. package/src/sign/sign.helper.ts +23 -0
  208. package/src/sign/sign.module.ts +27 -0
  209. package/src/sign/signer-kms.service.ts +27 -0
  210. package/src/sign/signer.service.ts +26 -0
  211. package/src/solver/filters/tests/valid-smart-wallet.service.spec.ts +87 -0
  212. package/src/solver/filters/valid-smart-wallet.service.ts +58 -0
  213. package/src/solver/solver.module.ts +10 -0
  214. package/src/transaction/multichain-public-client.service.ts +15 -0
  215. package/src/transaction/smart-wallets/kernel/actions/encodeData.kernel.ts +57 -0
  216. package/src/transaction/smart-wallets/kernel/create-kernel-client-v2.account.ts +183 -0
  217. package/src/transaction/smart-wallets/kernel/create.kernel.account.ts +270 -0
  218. package/src/transaction/smart-wallets/kernel/index.ts +2 -0
  219. package/src/transaction/smart-wallets/kernel/kernel-account-client-v2.service.ts +90 -0
  220. package/src/transaction/smart-wallets/kernel/kernel-account-client.service.ts +107 -0
  221. package/src/transaction/smart-wallets/kernel/kernel-account.client.ts +105 -0
  222. package/src/transaction/smart-wallets/kernel/kernel-account.config.ts +34 -0
  223. package/src/transaction/smart-wallets/simple-account/create.simple.account.ts +19 -0
  224. package/src/transaction/smart-wallets/simple-account/index.ts +2 -0
  225. package/src/transaction/smart-wallets/simple-account/simple-account-client.service.ts +42 -0
  226. package/src/transaction/smart-wallets/simple-account/simple-account.client.ts +83 -0
  227. package/src/transaction/smart-wallets/simple-account/simple-account.config.ts +5 -0
  228. package/src/transaction/smart-wallets/smart-wallet.types.ts +38 -0
  229. package/src/transaction/smart-wallets/utils.ts +14 -0
  230. package/src/transaction/transaction.module.ts +25 -0
  231. package/src/transaction/viem_multichain_client.service.ts +100 -0
  232. package/src/transforms/viem-address.decorator.ts +14 -0
  233. package/src/utils/bigint.ts +44 -0
  234. package/src/utils/types.ts +18 -0
  235. package/src/watch/intent/tests/watch-create-intent.service.spec.ts +257 -0
  236. package/src/watch/intent/tests/watch-fulfillment.service.spec.ts +141 -0
  237. package/src/watch/intent/watch-create-intent.service.ts +106 -0
  238. package/src/watch/intent/watch-event.service.ts +133 -0
  239. package/src/watch/intent/watch-fulfillment.service.ts +115 -0
  240. package/src/watch/watch.module.ts +13 -0
  241. package/test/app.e2e-spec.ts +21 -0
  242. package/test/jest-e2e.json +9 -0
  243. package/tsconfig.build.json +4 -0
  244. package/tsconfig.json +29 -0
@@ -0,0 +1,176 @@
1
+ import { Injectable, Logger, OnModuleInit } from '@nestjs/common'
2
+ import { EcoConfigService } from '../eco-configs/eco-config.service'
3
+ import { EcoLogMessage } from '../common/logging/eco-log-message'
4
+ import { IntentProcessData, UtilsIntentService } from './utils-intent.service'
5
+ import { QUEUES } from '../common/redis/constants'
6
+ import { JobsOptions, Queue } from 'bullmq'
7
+ import { InjectQueue } from '@nestjs/bullmq'
8
+ import { getIntentJobId } from '../common/utils/strings'
9
+ import { Solver } from '../eco-configs/eco-config.types'
10
+ import { IntentSourceModel } from './schemas/intent-source.schema'
11
+ import { Hex } from 'viem'
12
+ import { EcoError } from '../common/errors/eco-error'
13
+ import { ValidationChecks, ValidationService, validationsFailed } from '@/intent/validation.sevice'
14
+ import { MultichainPublicClientService } from '@/transaction/multichain-public-client.service'
15
+ import { IntentSourceAbi } from '@eco-foundation/routes-ts'
16
+ import { IntentDataModel } from '@/intent/schemas/intent-data.schema'
17
+
18
+ /**
19
+ * Type that merges the {@link ValidationChecks} with the intentFunded check
20
+ */
21
+ export type IntentValidations = ValidationChecks & {
22
+ intentFunded: boolean
23
+ }
24
+
25
+ /**
26
+ * Service class that acts as the main validation service for intents.
27
+ * Validation {@license ValidationService}:
28
+ * 1. Supports the prover
29
+ * 2. Supports the targets
30
+ * 3. Supports the selectors
31
+ * 4. Has a valid transfer limit
32
+ * 5. Has a valid expiration time
33
+ * 6. Fulfill chain not same as source chain
34
+ *
35
+ * Validates that the intent was also funded:
36
+ * 1. The intent was funded on chain in the IntentSource
37
+ *
38
+ * As well as some structural checks on the intent model
39
+ */
40
+ @Injectable()
41
+ export class ValidateIntentService implements OnModuleInit {
42
+ private logger = new Logger(ValidateIntentService.name)
43
+ private intentJobConfig: JobsOptions
44
+
45
+ constructor(
46
+ @InjectQueue(QUEUES.SOURCE_INTENT.queue) private readonly intentQueue: Queue,
47
+ private readonly validationService: ValidationService,
48
+ private readonly multichainPublicClientService: MultichainPublicClientService,
49
+ private readonly utilsIntentService: UtilsIntentService,
50
+ private readonly ecoConfigService: EcoConfigService,
51
+ ) {}
52
+
53
+ onModuleInit() {
54
+ this.intentJobConfig = this.ecoConfigService.getRedis().jobs.intentJobConfig
55
+ }
56
+
57
+ /**
58
+ * @param intentHash the hash of the intent to fulfill
59
+ */
60
+ async validateIntent(intentHash: Hex) {
61
+ this.logger.debug(
62
+ EcoLogMessage.fromDefault({
63
+ message: `validateIntent ${intentHash}`,
64
+ properties: {
65
+ intentHash: intentHash,
66
+ },
67
+ }),
68
+ )
69
+
70
+ const { model, solver } = await this.destructureIntent(intentHash)
71
+ if (!model || !solver) {
72
+ return false
73
+ }
74
+
75
+ if (!(await this.assertValidations(model, solver))) {
76
+ return false
77
+ }
78
+
79
+ const jobId = getIntentJobId('validate', intentHash, model.intent.logIndex)
80
+ this.logger.debug(
81
+ EcoLogMessage.fromDefault({
82
+ message: `validateIntent ${intentHash}`,
83
+ properties: {
84
+ intentHash,
85
+ jobId,
86
+ },
87
+ }),
88
+ )
89
+ //add to processing queue
90
+ await this.intentQueue.add(QUEUES.SOURCE_INTENT.jobs.feasable_intent, intentHash, {
91
+ jobId,
92
+ ...this.intentJobConfig,
93
+ })
94
+
95
+ return true
96
+ }
97
+
98
+ /**
99
+ * Executes all the validations we have on the model and solver
100
+ *
101
+ * @param model the source intent model
102
+ * @param solver the solver for the source chain
103
+ * @returns true if they all pass, false otherwise
104
+ */
105
+ async assertValidations(model: IntentSourceModel, solver: Solver): Promise<boolean> {
106
+ const validations = (await this.validationService.assertValidations(
107
+ model.intent,
108
+ solver,
109
+ )) as IntentValidations
110
+ validations.intentFunded = await this.intentFunded(model)
111
+
112
+ if (validationsFailed(validations)) {
113
+ await this.utilsIntentService.updateInvalidIntentModel(model, validations)
114
+ this.logger.log(
115
+ EcoLogMessage.fromDefault({
116
+ message: EcoError.IntentValidationFailed(model.intent.hash).message,
117
+ properties: {
118
+ model,
119
+ validations,
120
+ },
121
+ }),
122
+ )
123
+ return false
124
+ }
125
+
126
+ return true
127
+ }
128
+
129
+ /**
130
+ * Makes on onchain read call to make sure that the intent was funded in the IntentSource
131
+ * contract.
132
+ * @Notice An event emitted is not enough to guarantee that the intent was funded
133
+ * @param model the source intent model
134
+ * @returns
135
+ */
136
+ async intentFunded(model: IntentSourceModel): Promise<boolean> {
137
+ const sourceChainID = Number(model.intent.route.source)
138
+ const client = await this.multichainPublicClientService.getClient(sourceChainID)
139
+ const intentSource = this.ecoConfigService.getIntentSource(sourceChainID)
140
+ if (!intentSource) {
141
+ this.logger.error(
142
+ EcoLogMessage.fromDefault({
143
+ message: EcoError.IntentSourceNotFound(sourceChainID).message,
144
+ properties: {
145
+ model,
146
+ },
147
+ }),
148
+ )
149
+ return false
150
+ }
151
+
152
+ const isIntentFunded = await client.readContract({
153
+ address: intentSource.sourceAddress,
154
+ abi: IntentSourceAbi,
155
+ functionName: 'isIntentFunded',
156
+ args: [IntentDataModel.toChainIntent(model.intent)],
157
+ })
158
+ return isIntentFunded
159
+ }
160
+
161
+ /**
162
+ * Fetches the intent from the db and its solver and model from configs. Validates
163
+ * that both are returned without any error
164
+ *
165
+ * @param intentHash the hash of the intent to find in the db
166
+ * @returns
167
+ */
168
+ private async destructureIntent(intentHash: Hex): Promise<IntentProcessData> {
169
+ const data = await this.utilsIntentService.getIntentProcessData(intentHash)
170
+ const { model, solver, err } = data ?? {}
171
+ if (!data || !model || !solver) {
172
+ throw EcoError.ValidateIntentDescructureFailed(err)
173
+ }
174
+ return data
175
+ }
176
+ }
@@ -0,0 +1,223 @@
1
+ import { EcoLogMessage } from '@/common/logging/eco-log-message'
2
+ import { EcoConfigService } from '@/eco-configs/eco-config.service'
3
+ import { Solver } from '@/eco-configs/eco-config.types'
4
+ import { FeeService } from '@/fee/fee.service'
5
+ import { getTransactionTargetData } from '@/intent/utils'
6
+ import { ProofService } from '@/prover/proof.service'
7
+ import { QuoteIntentDataInterface } from '@/quote/dto/quote.intent.data.dto'
8
+ import { Injectable, Logger } from '@nestjs/common'
9
+ import { difference } from 'lodash'
10
+ import { Hex } from 'viem'
11
+
12
+ interface IntentModelWithHashInterface {
13
+ hash?: Hex
14
+ }
15
+
16
+ /**
17
+ * Validation type that mixes the QuoteIntentDataDTO with the hash. This is used to
18
+ * merge quotes and intents validations
19
+ */
20
+ export interface ValidationIntentInterface
21
+ extends QuoteIntentDataInterface,
22
+ IntentModelWithHashInterface {}
23
+
24
+ /**
25
+ * Type that holds all the possible validations that can fail
26
+ */
27
+ export type ValidationChecks = {
28
+ supportedProver: boolean
29
+ supportedTargets: boolean
30
+ supportedSelectors: boolean
31
+ validTransferLimit: boolean
32
+ validExpirationTime: boolean
33
+ validDestination: boolean
34
+ fulfillOnDifferentChain: boolean
35
+ }
36
+
37
+ /**
38
+ * Validates that all of the validations succeeded
39
+ * @param validations the validations to check
40
+ * @returns true if all of the validations passed
41
+ */
42
+ export function validationsSucceeded(validations: ValidationType): boolean {
43
+ return Object.values(validations).every((v) => v)
44
+ }
45
+
46
+ /**
47
+ * Checks that at least one of the validations failed
48
+ * @param validations the validations to check
49
+ * @returns true if any of the validations failed
50
+ */
51
+ export function validationsFailed(validations: ValidationType): boolean {
52
+ return !validationsSucceeded(validations)
53
+ }
54
+
55
+ /**
56
+ * Type that holds all the possible validations that can fail
57
+ */
58
+ export type ValidationType = {
59
+ [key: string]: boolean
60
+ }
61
+
62
+ @Injectable()
63
+ export class ValidationService {
64
+ private readonly logger = new Logger(ValidationService.name)
65
+
66
+ constructor(
67
+ private readonly proofService: ProofService,
68
+ private readonly feeService: FeeService,
69
+ private readonly ecoConfigService: EcoConfigService,
70
+ ) {}
71
+
72
+ /**
73
+ * Executes all the validations we have on the model and solver
74
+ *
75
+ * @param intent the source intent model
76
+ * @param solver the solver for the source chain
77
+ * @returns true if they all pass, false otherwise
78
+ */
79
+ async assertValidations(
80
+ intent: ValidationIntentInterface,
81
+ solver: Solver,
82
+ ): Promise<ValidationChecks> {
83
+ const supportedProver = this.supportedProver({
84
+ sourceChainID: intent.route.source,
85
+ prover: intent.reward.prover,
86
+ })
87
+ const supportedTargets = this.supportedTargets(intent, solver)
88
+ const supportedSelectors = this.supportedSelectors(intent, solver)
89
+ const validTransferLimit = await this.validTransferLimit(intent)
90
+ const validExpirationTime = this.validExpirationTime(intent)
91
+ const validDestination = this.validDestination(intent)
92
+ const fulfillOnDifferentChain = this.fulfillOnDifferentChain(intent)
93
+
94
+ return {
95
+ supportedProver,
96
+ supportedTargets,
97
+ supportedSelectors,
98
+ validTransferLimit,
99
+ validExpirationTime,
100
+ validDestination,
101
+ fulfillOnDifferentChain,
102
+ }
103
+ }
104
+
105
+ /**
106
+ * Checks if the IntentCreated event is using a supported prover. It first finds the source intent contract that is on the
107
+ * source chain of the event. Then it checks if the prover is supported by the source intent. In the
108
+ * case that there are multiple matching source intent contracts on the same chain, as long as any of
109
+ * them support the prover, the function will return true.
110
+ *
111
+ * @param ops the intent info
112
+ * @returns
113
+ */
114
+ supportedProver(ops: { sourceChainID: bigint; prover: Hex }): boolean {
115
+ const srcSolvers = this.ecoConfigService.getIntentSources().filter((intent) => {
116
+ return BigInt(intent.chainID) == ops.sourceChainID
117
+ })
118
+
119
+ return srcSolvers.some((intent) => {
120
+ return intent.provers.some((prover) => prover == ops.prover)
121
+ })
122
+ }
123
+
124
+ /**
125
+ * Verifies that the intent targets and data arrays are equal in length, and
126
+ * that every target-data can be decoded
127
+ *
128
+ * @param intent the intent model
129
+ * @param solver the solver for the intent
130
+ * @returns
131
+ */
132
+ supportedSelectors(intent: ValidationIntentInterface, solver: Solver): boolean {
133
+ if (intent.route.calls.length == 0) {
134
+ this.logger.log(
135
+ EcoLogMessage.fromDefault({
136
+ message: `supportedSelectors: Target/data invalid`,
137
+ }),
138
+ )
139
+ return false
140
+ }
141
+ return intent.route.calls.every((call) => {
142
+ const tx = getTransactionTargetData(solver, call)
143
+ return tx
144
+ })
145
+ }
146
+
147
+ /**
148
+ * Verifies that all the intent targets are supported by the solver
149
+ *
150
+ * @param intent the intent model
151
+ * @param solver the solver for the intent
152
+ * @returns
153
+ */
154
+ supportedTargets(intent: ValidationIntentInterface, solver: Solver): boolean {
155
+ const intentTargets = intent.route.calls.map((call) => call.target)
156
+ const solverTargets = Object.keys(solver.targets)
157
+ //all targets are included in the solver targets array
158
+ const exist = solverTargets.length > 0 && intentTargets.length > 0
159
+ const targetsSupported = exist && difference(intentTargets, solverTargets).length == 0
160
+
161
+ if (!targetsSupported) {
162
+ this.logger.debug(
163
+ EcoLogMessage.fromDefault({
164
+ message: `Targets not supported for intent ${intent.hash ? intent.hash : 'quote'}`,
165
+ properties: {
166
+ ...(intent.hash && {
167
+ intentHash: intent.hash,
168
+ source: intent.route.source,
169
+ }),
170
+ },
171
+ }),
172
+ )
173
+ }
174
+ return targetsSupported
175
+ }
176
+
177
+ /**
178
+ * Checks if the transfer total is within the bounds of the solver, ie below a certain threshold
179
+ * @param intent the source intent model
180
+ * @returns true if the transfer is within the bounds
181
+ */
182
+ async validTransferLimit(intent: ValidationIntentInterface): Promise<boolean> {
183
+ const { totalFillNormalized, error } = await this.feeService.getTotalFill(intent)
184
+ if (error) {
185
+ return false
186
+ }
187
+ const limitFillBase6 = this.feeService.getFeeConfig({ intent }).limitFillBase6
188
+ return totalFillNormalized <= limitFillBase6
189
+ }
190
+
191
+ /**
192
+ *
193
+ * @param intent the source intent model
194
+ * @param solver the solver for the source chain
195
+ * @returns
196
+ */
197
+ validExpirationTime(intent: ValidationIntentInterface): boolean {
198
+ //convert to milliseconds
199
+ const time = Number.parseInt(`${intent.reward.deadline as bigint}`) * 1000
200
+ const expires = new Date(time)
201
+ return this.proofService.isIntentExpirationWithinProofMinimumDate(intent.reward.prover, expires)
202
+ }
203
+
204
+ /**
205
+ * Checks that the intent destination is supported by the solver
206
+ * @param intent the source intent model
207
+ * @returns
208
+ */
209
+ validDestination(intent: ValidationIntentInterface): boolean {
210
+ return this.ecoConfigService.getSupportedChains().includes(intent.route.destination)
211
+ }
212
+
213
+ /**
214
+ * Checks that the intent fulfillment is on a different chain than its source
215
+ * Needed since some proving methods(Hyperlane) cant prove same chain
216
+ * @param intent the source intent
217
+ * @param solver the solver used to fulfill
218
+ * @returns
219
+ */
220
+ fulfillOnDifferentChain(intent: ValidationIntentInterface): boolean {
221
+ return intent.route.destination !== intent.route.source
222
+ }
223
+ }
@@ -0,0 +1,30 @@
1
+ import { CallHandler, ExecutionContext, Injectable, NestInterceptor } from '@nestjs/common'
2
+ import { Observable } from 'rxjs'
3
+ import { map } from 'rxjs/operators'
4
+
5
+ @Injectable()
6
+ export class BigIntToStringInterceptor implements NestInterceptor {
7
+ intercept(context: ExecutionContext, next: CallHandler): Observable<any> {
8
+ return next.handle().pipe(map((data) => this.transformBigInt(data)))
9
+ }
10
+
11
+ private transformBigInt(data: any): any {
12
+ if (data === null || data === undefined) return data
13
+
14
+ if (typeof data === 'bigint') {
15
+ return data.toString()
16
+ }
17
+
18
+ if (Array.isArray(data)) {
19
+ return data.map((item) => this.transformBigInt(item))
20
+ }
21
+
22
+ if (typeof data === 'object') {
23
+ return Object.fromEntries(
24
+ Object.entries(data).map(([key, value]) => [key, this.transformBigInt(value)]),
25
+ )
26
+ }
27
+
28
+ return data
29
+ }
30
+ }
@@ -0,0 +1,18 @@
1
+ import { Module } from '@nestjs/common'
2
+ import { RetryInfeasableIntentsService } from '@/intervals/retry-infeasable-intents.service'
3
+ import { initBullMQ } from '@/bullmq/bullmq.helper'
4
+ import { QUEUES } from '@/common/redis/constants'
5
+ import { IntentModule } from '@/intent/intent.module'
6
+ import { ProverModule } from '@/prover/prover.module'
7
+ import { IntervalProcessor } from '@/bullmq/processors/interval.processor'
8
+
9
+ @Module({
10
+ imports: [
11
+ initBullMQ(QUEUES.INTERVAL),
12
+ initBullMQ(QUEUES.SOURCE_INTENT),
13
+ IntentModule,
14
+ ProverModule,
15
+ ],
16
+ providers: [RetryInfeasableIntentsService, IntervalProcessor],
17
+ })
18
+ export class IntervalModule {}
@@ -0,0 +1,89 @@
1
+ import { EcoLogMessage } from '@/common/logging/eco-log-message'
2
+ import { QUEUES } from '@/common/redis/constants'
3
+ import { getIntentJobId } from '@/common/utils/strings'
4
+ import { Proofs } from '@/contracts'
5
+ import { EcoConfigService } from '@/eco-configs/eco-config.service'
6
+ import { IntentSourceModel } from '@/intent/schemas/intent-source.schema'
7
+ import { ProofService } from '@/prover/proof.service'
8
+ import { InjectQueue } from '@nestjs/bullmq'
9
+ import { Injectable, Logger, OnApplicationBootstrap } from '@nestjs/common'
10
+ import { InjectModel } from '@nestjs/mongoose'
11
+ import { JobsOptions, Queue } from 'bullmq'
12
+ import { Model } from 'mongoose'
13
+
14
+ @Injectable()
15
+ export class RetryInfeasableIntentsService implements OnApplicationBootstrap {
16
+ private logger = new Logger(RetryInfeasableIntentsService.name)
17
+ private intentJobConfig: JobsOptions
18
+
19
+ constructor(
20
+ @InjectQueue(QUEUES.INTERVAL.queue) private readonly intervalQueue: Queue,
21
+ @InjectQueue(QUEUES.SOURCE_INTENT.queue) private readonly intentQueue: Queue,
22
+ @InjectModel(IntentSourceModel.name) private intentModel: Model<IntentSourceModel>,
23
+ private readonly proofService: ProofService,
24
+ private readonly ecoConfigService: EcoConfigService,
25
+ ) {}
26
+
27
+ async onModuleInit() {
28
+ this.intentJobConfig = this.ecoConfigService.getIntervals().retryInfeasableIntents.jobTemplate
29
+ .opts as JobsOptions
30
+ }
31
+
32
+ async onApplicationBootstrap() {
33
+ const config = this.ecoConfigService.getIntervals().retryInfeasableIntents
34
+ config.repeatOpts = { ...config.repeatOpts, immediately: true }
35
+ config.jobTemplate = {
36
+ ...config.jobTemplate,
37
+ name: QUEUES.INTERVAL.jobs.retry_infeasable_intents,
38
+ }
39
+ this.intervalQueue.upsertJobScheduler(
40
+ QUEUES.INTERVAL.jobs.RETRY_INFEASABLE_INTENTS,
41
+ config.repeatOpts,
42
+ config.jobTemplate,
43
+ )
44
+ }
45
+
46
+ /**
47
+ * Retries intents that are infeasable but still within the proof expiration window.
48
+ * Sends them on the {@link QUEUES.SOURCE_INTENT.jobs.retry_intent} queue to validate
49
+ */
50
+ async retryInfeasableIntents() {
51
+ const models = await this.getInfeasableIntents()
52
+ this.logger.debug(
53
+ EcoLogMessage.fromDefault({
54
+ message: `retryInfeasableIntents`,
55
+ properties: {
56
+ models,
57
+ },
58
+ }),
59
+ )
60
+
61
+ const retryTasks = models.map(async (model) => {
62
+ const jobId = getIntentJobId('retry', model.intent.hash, model.intent.logIndex)
63
+
64
+ //add to processing queue
65
+ await this.intentQueue.add(QUEUES.SOURCE_INTENT.jobs.retry_intent, model.intent.hash, {
66
+ jobId,
67
+ ...this.intentJobConfig,
68
+ })
69
+ })
70
+
71
+ await Promise.all(retryTasks)
72
+ }
73
+
74
+ private async getInfeasableIntents() {
75
+ return await this.intentModel.find({
76
+ status: 'INFEASABLE',
77
+ $or: [
78
+ {
79
+ 'intent.expiration': { $gt: this.proofService.getProofMinimumDate(Proofs.Hyperlane) },
80
+ 'intent.prover': { $in: this.proofService.getProvers(Proofs.Hyperlane) },
81
+ },
82
+ {
83
+ 'intent.expiration': { $gt: this.proofService.getProofMinimumDate(Proofs.Storage) },
84
+ 'intent.prover': { $in: this.proofService.getProvers(Proofs.Storage) },
85
+ },
86
+ ],
87
+ })
88
+ }
89
+ }