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,215 @@
1
+ const mockDecodeCreateIntentLog = jest.fn()
2
+ import { createMock, DeepMocked } from '@golevelup/ts-jest'
3
+ import { EcoConfigService } from '../../eco-configs/eco-config.service'
4
+ import { Test, TestingModule } from '@nestjs/testing'
5
+ import { getModelToken } from '@nestjs/mongoose'
6
+ import { IntentSourceModel } from '../schemas/intent-source.schema'
7
+ import { Model } from 'mongoose'
8
+ import { BullModule, getQueueToken } from '@nestjs/bullmq'
9
+ import { QUEUES } from '../../common/redis/constants'
10
+ import { Queue } from 'bullmq'
11
+ import { CreateIntentService } from '../create-intent.service'
12
+ import { ValidSmartWalletService } from '../../solver/filters/valid-smart-wallet.service'
13
+ import { IntentDataModel } from '../schemas/intent-data.schema'
14
+ import { FlagService } from '../../flags/flags.service'
15
+
16
+ jest.mock('../../contracts', () => {
17
+ return {
18
+ ...jest.requireActual('../../contracts'),
19
+ decodeCreateIntentLog: mockDecodeCreateIntentLog,
20
+ }
21
+ })
22
+
23
+ describe('CreateIntentService', () => {
24
+ let createIntentService: CreateIntentService
25
+ let validSmartWalletService: DeepMocked<ValidSmartWalletService>
26
+ let flagService: DeepMocked<FlagService>
27
+ let ecoConfigService: DeepMocked<EcoConfigService>
28
+ let intentSourceModel: DeepMocked<Model<IntentSourceModel>>
29
+ let queue: DeepMocked<Queue>
30
+ const mockLogDebug = jest.fn()
31
+ const mockLogLog = jest.fn()
32
+
33
+ beforeEach(async () => {
34
+ const chainMod: TestingModule = await Test.createTestingModule({
35
+ providers: [
36
+ CreateIntentService,
37
+ { provide: ValidSmartWalletService, useValue: createMock<ValidSmartWalletService>() },
38
+ { provide: FlagService, useValue: createMock<FlagService>() },
39
+ { provide: EcoConfigService, useValue: createMock<EcoConfigService>() },
40
+ {
41
+ provide: getModelToken(IntentSourceModel.name),
42
+ useValue: createMock<Model<IntentSourceModel>>(),
43
+ },
44
+ ],
45
+ imports: [
46
+ BullModule.registerQueue({
47
+ name: QUEUES.SOURCE_INTENT.queue,
48
+ }),
49
+ ],
50
+ })
51
+ .overrideProvider(getQueueToken(QUEUES.SOURCE_INTENT.queue))
52
+ .useValue(createMock<Queue>())
53
+ .compile()
54
+ //turn off the services from logging durring testing
55
+ chainMod.useLogger(false)
56
+
57
+ createIntentService = chainMod.get(CreateIntentService)
58
+ validSmartWalletService = chainMod.get(ValidSmartWalletService)
59
+ flagService = chainMod.get(FlagService)
60
+ ecoConfigService = chainMod.get(EcoConfigService)
61
+ intentSourceModel = chainMod.get(getModelToken(IntentSourceModel.name))
62
+ queue = chainMod.get(getQueueToken(QUEUES.SOURCE_INTENT.queue))
63
+
64
+ createIntentService['logger'].debug = mockLogDebug
65
+ createIntentService['logger'].log = mockLogLog
66
+ })
67
+
68
+ afterEach(async () => {
69
+ // restore the spy created with spyOn
70
+ jest.restoreAllMocks()
71
+ mockLogDebug.mockClear()
72
+ mockLogLog.mockClear()
73
+ })
74
+
75
+ describe('on createIntent', () => {
76
+ const mockEvent = {
77
+ creator: '0xaaa',
78
+ data: '0xda',
79
+ transactionHash: '0x123',
80
+ topics: ['0x456'],
81
+ sourceChainID: 85432,
82
+ }
83
+ const mockIntent = {
84
+ reward: { creator: '0xaaa' },
85
+ hash: mockEvent.transactionHash,
86
+ logIndex: 1,
87
+ }
88
+ beforeEach(() => {
89
+ mockDecodeCreateIntentLog.mockReturnValue({ hash: mockEvent.transactionHash })
90
+ const mockIntentSourceEvent = jest.fn()
91
+ IntentDataModel.fromEvent = mockIntentSourceEvent
92
+ mockIntentSourceEvent.mockReturnValue(mockIntent)
93
+ })
94
+
95
+ it('should decode the event', async () => {
96
+ createIntentService.createIntent(mockEvent as any)
97
+ expect(mockLogDebug).toHaveBeenCalledWith({
98
+ msg: `createIntent ${mockEvent.transactionHash}`,
99
+ intentHash: mockEvent.transactionHash,
100
+ })
101
+ expect(mockDecodeCreateIntentLog).toHaveBeenCalledWith(mockEvent.data, mockEvent.topics)
102
+ })
103
+
104
+ it('should return if model has already been created in db', async () => {
105
+ const mockFindOne = jest.fn().mockReturnValue({ hash: mockEvent.transactionHash })
106
+ intentSourceModel.findOne = mockFindOne
107
+ await createIntentService.createIntent(mockEvent as any)
108
+ expect(mockFindOne).toHaveBeenCalledWith({ 'intent.hash': mockEvent.transactionHash })
109
+ expect(mockLogDebug).toHaveBeenNthCalledWith(2, {
110
+ msg: `Record for intent already exists ${mockEvent.transactionHash}`,
111
+ intentHash: mockIntent.hash,
112
+ intent: mockIntent,
113
+ })
114
+ expect(validSmartWalletService.validateSmartWallet).not.toHaveBeenCalled()
115
+ })
116
+
117
+ it('should check if the bendWalletOnly flag is up', async () => {
118
+ const mockFindOne = jest.fn().mockReturnValue(undefined)
119
+ intentSourceModel.findOne = mockFindOne
120
+ const mockFlag = jest.spyOn(flagService, 'getFlagValue').mockReturnValue(false)
121
+ const mockValidateSmartWallet = jest.fn().mockReturnValue(true)
122
+ validSmartWalletService.validateSmartWallet = mockValidateSmartWallet
123
+ await createIntentService.createIntent(mockEvent as any)
124
+ expect(mockFlag).toHaveBeenCalledTimes(1)
125
+ expect(mockValidateSmartWallet).toHaveBeenCalledTimes(0)
126
+ })
127
+
128
+ it('should validate the intent is from a bend wallet', async () => {
129
+ const mockFindOne = jest.fn().mockReturnValue(undefined)
130
+ intentSourceModel.findOne = mockFindOne
131
+ const mockValidateSmartWallet = jest.fn().mockReturnValue(true)
132
+ jest.spyOn(flagService, 'getFlagValue').mockReturnValue(true)
133
+ validSmartWalletService.validateSmartWallet = mockValidateSmartWallet
134
+ await createIntentService.createIntent(mockEvent as any)
135
+ expect(mockValidateSmartWallet).toHaveBeenCalledTimes(1)
136
+ expect(mockValidateSmartWallet).toHaveBeenCalledWith(
137
+ mockIntent.reward.creator,
138
+ mockEvent.sourceChainID,
139
+ )
140
+ })
141
+
142
+ it('should create an intent model in the database', async () => {
143
+ const mockFindOne = jest.fn().mockReturnValue(undefined)
144
+ intentSourceModel.findOne = mockFindOne
145
+ const mockValidateSmartWallet = jest.fn().mockReturnValue(true)
146
+ jest.spyOn(flagService, 'getFlagValue').mockReturnValue(true)
147
+ validSmartWalletService.validateSmartWallet = mockValidateSmartWallet
148
+ const mockCreate = jest.fn()
149
+ intentSourceModel.create = mockCreate
150
+ await createIntentService.createIntent(mockEvent as any)
151
+ expect(mockCreate).toHaveBeenCalledWith({
152
+ event: mockEvent,
153
+ intent: mockIntent,
154
+ receipt: null,
155
+ status: 'PENDING',
156
+ })
157
+
158
+ mockCreate.mockClear()
159
+ mockValidateSmartWallet.mockResolvedValueOnce(false)
160
+ await createIntentService.createIntent(mockEvent as any)
161
+ expect(mockCreate).toHaveBeenCalledWith({
162
+ event: mockEvent,
163
+ intent: mockIntent,
164
+ receipt: null,
165
+ status: 'NON-BEND-WALLET',
166
+ })
167
+ })
168
+
169
+ it('should not enqueue a job if the intent is not from a bend wallet', async () => {
170
+ const mockFindOne = jest.fn().mockReturnValue(undefined)
171
+ const mockQueueAdd = jest.fn()
172
+ intentSourceModel.findOne = mockFindOne
173
+ intentSourceModel.create = jest.fn().mockReturnValue({ intent: mockIntent })
174
+ queue.add = mockQueueAdd
175
+ jest.spyOn(flagService, 'getFlagValue').mockReturnValue(true)
176
+ validSmartWalletService.validateSmartWallet = jest.fn().mockReturnValue(false)
177
+
178
+ await createIntentService.createIntent(mockEvent as any)
179
+ expect(mockQueueAdd).not.toHaveBeenCalled()
180
+ expect(mockLogLog).toHaveBeenNthCalledWith(1, {
181
+ msg: `Recorded intent ${mockEvent.transactionHash}`,
182
+ intentHash: mockIntent.hash,
183
+ intent: mockIntent,
184
+ validWallet: false,
185
+ })
186
+ })
187
+
188
+ it('should enqueue a job if the intent is from a bend wallet', async () => {
189
+ const mockFindOne = jest.fn().mockReturnValue(undefined)
190
+ const mockQueueAdd = jest.fn()
191
+ intentSourceModel.findOne = mockFindOne
192
+ intentSourceModel.create = jest.fn().mockReturnValue({ intent: mockIntent })
193
+ queue.add = mockQueueAdd
194
+ jest.spyOn(flagService, 'getFlagValue').mockReturnValue(true)
195
+ validSmartWalletService.validateSmartWallet = jest.fn().mockReturnValue(true)
196
+
197
+ const jobId = `create-${mockIntent.hash}-${mockIntent.logIndex}`
198
+ await createIntentService.createIntent(mockEvent as any)
199
+ expect(mockQueueAdd).toHaveBeenCalledTimes(1)
200
+ expect(mockQueueAdd).toHaveBeenCalledWith(
201
+ QUEUES.SOURCE_INTENT.jobs.validate_intent,
202
+ mockIntent.hash,
203
+ { jobId },
204
+ )
205
+
206
+ expect(mockLogLog).toHaveBeenNthCalledWith(1, {
207
+ msg: `Recorded intent ${mockEvent.transactionHash}`,
208
+ intentHash: mockIntent.hash,
209
+ intent: mockIntent,
210
+ validWallet: true,
211
+ jobId,
212
+ })
213
+ })
214
+ })
215
+ })
@@ -0,0 +1,155 @@
1
+ import { createMock, DeepMocked } from '@golevelup/ts-jest'
2
+ import { EcoConfigService } from '../../eco-configs/eco-config.service'
3
+ import { Test, TestingModule } from '@nestjs/testing'
4
+ import { getModelToken } from '@nestjs/mongoose'
5
+ import { IntentSourceModel } from '../schemas/intent-source.schema'
6
+ import { Model } from 'mongoose'
7
+ import { UtilsIntentService } from '../utils-intent.service'
8
+ import { BullModule, getQueueToken } from '@nestjs/bullmq'
9
+ import { QUEUES } from '../../common/redis/constants'
10
+ import { Queue } from 'bullmq'
11
+ import { FeasableIntentService } from '../feasable-intent.service'
12
+ import { Hex } from 'viem'
13
+ import { FeeService } from '@/fee/fee.service'
14
+ import { QuoteError } from '@/quote/errors'
15
+
16
+ describe('FeasableIntentService', () => {
17
+ let feasableIntentService: FeasableIntentService
18
+ let feeService: DeepMocked<FeeService>
19
+ let utilsIntentService: DeepMocked<UtilsIntentService>
20
+ let ecoConfigService: DeepMocked<EcoConfigService>
21
+ let queue: DeepMocked<Queue>
22
+ const mockLogDebug = jest.fn()
23
+ const mockLogLog = jest.fn()
24
+ const mockLogError = jest.fn()
25
+ const address1 = '0x1111111111111111111111111111111111111111'
26
+ const address2 = '0x2222222222222222222222222222222222222222'
27
+ beforeEach(async () => {
28
+ const chainMod: TestingModule = await Test.createTestingModule({
29
+ providers: [
30
+ FeasableIntentService,
31
+ { provide: FeeService, useValue: createMock<FeeService>() },
32
+ { provide: UtilsIntentService, useValue: createMock<UtilsIntentService>() },
33
+ { provide: EcoConfigService, useValue: createMock<EcoConfigService>() },
34
+ {
35
+ provide: getModelToken(IntentSourceModel.name),
36
+ useValue: createMock<Model<IntentSourceModel>>(),
37
+ },
38
+ ],
39
+ imports: [
40
+ BullModule.registerQueue({
41
+ name: QUEUES.SOURCE_INTENT.queue,
42
+ }),
43
+ ],
44
+ })
45
+ .overrideProvider(getQueueToken(QUEUES.SOURCE_INTENT.queue))
46
+ .useValue(createMock<Queue>())
47
+ .compile()
48
+
49
+ feasableIntentService = chainMod.get(FeasableIntentService)
50
+ feeService = chainMod.get(FeeService)
51
+ utilsIntentService = chainMod.get(UtilsIntentService)
52
+ ecoConfigService = chainMod.get(EcoConfigService)
53
+ queue = chainMod.get(getQueueToken(QUEUES.SOURCE_INTENT.queue))
54
+
55
+ feasableIntentService['logger'].debug = mockLogDebug
56
+ feasableIntentService['logger'].log = mockLogLog
57
+ feasableIntentService['logger'].error = mockLogError
58
+ })
59
+
60
+ const mockData = { model: { intent: { logIndex: 1, hash: '0x123' as Hex } }, solver: {} }
61
+ const intentHash = mockData.model.intent.hash
62
+ const jobId = `feasable-${intentHash}-${mockData.model.intent.logIndex}`
63
+ afterEach(async () => {
64
+ // restore the spy created with spyOn
65
+ jest.restoreAllMocks()
66
+ mockLogDebug.mockClear()
67
+ mockLogLog.mockClear()
68
+ })
69
+
70
+ describe('onModuleInit', () => {
71
+ it('should set the intentJobConfig', async () => {
72
+ const mockConfig = { foo: 'bar' }
73
+ jest
74
+ .spyOn(ecoConfigService, 'getRedis')
75
+ .mockReturnValue({ jobs: { intentJobConfig: mockConfig } } as any)
76
+ await feasableIntentService.onModuleInit()
77
+ expect(feasableIntentService['intentJobConfig']).toEqual(mockConfig)
78
+ })
79
+ })
80
+
81
+ describe('on feasableIntent', () => {
82
+ it('should error out if processing intent data fails', async () => {
83
+ jest.spyOn(utilsIntentService, 'getIntentProcessData').mockResolvedValue(undefined)
84
+ await expect(feasableIntentService.feasableIntent(intentHash)).resolves.not.toThrow()
85
+
86
+ const error = new Error('noo')
87
+ jest
88
+ .spyOn(utilsIntentService, 'getIntentProcessData')
89
+ .mockResolvedValue({ err: error } as any)
90
+ await expect(feasableIntentService.feasableIntent(intentHash)).rejects.toThrow(error)
91
+ })
92
+
93
+ it('should fail if intent has more than 1 target call', async () => {
94
+ const mockModel = {
95
+ intent: {
96
+ route: {
97
+ calls: [
98
+ { data: '0x', target: address1 },
99
+ { data: '0x', target: address2 },
100
+ ],
101
+ },
102
+ logIndex: 1,
103
+ },
104
+ }
105
+ const errData = { solver: mockData.solver, model: mockModel } as any
106
+ jest.spyOn(utilsIntentService, 'getIntentProcessData').mockResolvedValue(errData)
107
+ jest.spyOn(feeService, 'isRouteFeasible').mockResolvedValue({
108
+ error: QuoteError.MultiFulfillRoute(),
109
+ } as any)
110
+ await feasableIntentService.feasableIntent(intentHash)
111
+ expect(utilsIntentService.updateInfeasableIntentModel).toHaveBeenCalledWith(
112
+ errData.model,
113
+ QuoteError.MultiFulfillRoute(),
114
+ )
115
+ expect(mockLogDebug).toHaveBeenCalledTimes(2)
116
+ expect(mockLogDebug).toHaveBeenNthCalledWith(2, {
117
+ msg: `FeasableIntent intent ${intentHash}`,
118
+ feasable: false,
119
+ })
120
+ expect(queue.add).not.toHaveBeenCalled()
121
+ })
122
+
123
+ it('should update the db intent model if the intent is not feasable', async () => {
124
+ jest.spyOn(utilsIntentService, 'getIntentProcessData').mockResolvedValue(mockData as any)
125
+ jest
126
+ .spyOn(feeService, 'isRouteFeasible')
127
+ .mockResolvedValue({ error: QuoteError.MultiFulfillRoute() })
128
+
129
+ await feasableIntentService.feasableIntent(intentHash)
130
+
131
+ expect(utilsIntentService.updateInfeasableIntentModel).toHaveBeenCalledWith(
132
+ mockData.model,
133
+ QuoteError.MultiFulfillRoute(),
134
+ )
135
+ })
136
+
137
+ it('should add the intent when its feasable to the queue to be processed', async () => {
138
+ jest.spyOn(utilsIntentService, 'getIntentProcessData').mockResolvedValue(mockData as any)
139
+ jest.spyOn(feeService, 'isRouteFeasible').mockResolvedValue({ calls: [] } as any)
140
+
141
+ await feasableIntentService.feasableIntent(intentHash)
142
+
143
+ expect(mockLogDebug).toHaveBeenCalledTimes(2)
144
+ expect(mockLogDebug).toHaveBeenNthCalledWith(2, {
145
+ msg: `FeasableIntent intent ${intentHash}`,
146
+ feasable: true,
147
+ jobId,
148
+ })
149
+ expect(queue.add).toHaveBeenCalledWith(QUEUES.SOURCE_INTENT.jobs.fulfill_intent, intentHash, {
150
+ jobId,
151
+ ...feasableIntentService['intentJobConfig'],
152
+ })
153
+ })
154
+ })
155
+ })