eco-solver 0.0.1-security → 1.5.0

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

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 +66 -0
  17. package/jest.config.ts +14 -0
  18. package/nest-cli.json +8 -0
  19. package/package.json +115 -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,73 @@
1
+ import { signKms } from '@/sign/kms-account/signKms'
2
+ import { signKmsTransaction } from '@/sign/kms-account/signKmsTransaction'
3
+ import { signKmsTypedData } from '@/sign/kms-account/signKmsTypedData'
4
+ import { Signer } from '@web3-kms-signer/core'
5
+ import { KMSWallets } from '@web3-kms-signer/kms-wallets'
6
+ import {
7
+ CustomSource,
8
+ getAddress,
9
+ hashMessage,
10
+ LocalAccount,
11
+ NonceManager,
12
+ Prettify,
13
+ toHex,
14
+ } from 'viem'
15
+ import { toAccount } from 'viem/accounts'
16
+
17
+ export type KmsToAccountOptions = {
18
+ nonceManager?: NonceManager | undefined
19
+ keyID: string
20
+ }
21
+
22
+ /**
23
+ * @description Creates an Account from a KMS signer.
24
+ *
25
+ * @returns A Private Key Account.
26
+ */
27
+ export async function kmsToAccount(
28
+ signer: Signer,
29
+ wallets: KMSWallets,
30
+ options: KmsToAccountOptions,
31
+ ): Promise<KmsAccount> {
32
+ const { nonceManager, keyID } = options
33
+ const publicKey = toHex(await wallets.getPublickey(keyID))
34
+ const addressHex = getAddress(await wallets.getAddressHex(keyID))
35
+ const addressBuffer = await wallets.getAddress(keyID)
36
+
37
+ const account = toAccount({
38
+ address: addressHex,
39
+ nonceManager,
40
+ async sign({ hash }) {
41
+ return await signKms({ hash, signer, keyID, addressBuffer, to: 'hex' })
42
+ },
43
+ async signMessage({ message }) {
44
+ return await signKms({ hash: hashMessage(message), signer, keyID, addressBuffer, to: 'hex' })
45
+ },
46
+ async signTransaction(transaction, { serializer } = {}) {
47
+ return await signKmsTransaction({
48
+ transaction,
49
+ serializer,
50
+ config: { signer, keyID, addressBuffer },
51
+ })
52
+ },
53
+ async signTypedData(typedData) {
54
+ return await signKmsTypedData({
55
+ ...typedData,
56
+ config: { signer, keyID, addressBuffer },
57
+ } as any)
58
+ },
59
+ })
60
+
61
+ return {
62
+ ...account,
63
+ publicKey,
64
+ source: 'kms',
65
+ } as KmsAccount
66
+ }
67
+
68
+ export type KmsAccount = Prettify<
69
+ LocalAccount<'kms'> & {
70
+ // TODO(v3): This will be redundant.
71
+ sign: NonNullable<CustomSource['sign']>
72
+ }
73
+ >
@@ -0,0 +1,30 @@
1
+ import { Signer } from '@web3-kms-signer/core'
2
+ import { Hex, parseSignature } from 'viem'
3
+ import { SignReturnType } from 'viem/accounts'
4
+
5
+ export type To = 'object' | 'bytes' | 'hex'
6
+
7
+ export type KmsSignParameters<to extends To = 'object'> = {
8
+ hash: Hex
9
+ signer: Signer
10
+ keyID: string
11
+ addressBuffer: Buffer
12
+ to?: to | To | undefined
13
+ }
14
+ /**
15
+ * @description Signs a hash using a KMS signer.
16
+ *
17
+ * @returns A signature.
18
+ */
19
+ export async function signKms<to extends To = 'object'>(
20
+ config: KmsSignParameters<to>,
21
+ ): Promise<SignReturnType<to>> {
22
+ const { hash, signer, keyID, addressBuffer, to = 'object' } = config
23
+ const hexSig = (await signer.signDigest({ keyId: keyID, address: addressBuffer }, hash)) as Hex
24
+ return (() => {
25
+ if (to === 'bytes' || to === 'hex') {
26
+ return hexSig
27
+ }
28
+ return parseSignature(hexSig)
29
+ })() as SignReturnType<to>
30
+ }
@@ -0,0 +1,37 @@
1
+ import { signKms, KmsSignParameters } from '@/sign/kms-account/signKms'
2
+ import {
3
+ keccak256,
4
+ serializeTransaction,
5
+ SerializeTransactionFn,
6
+ TransactionSerializable,
7
+ } from 'viem'
8
+ import { SignTransactionParameters, SignTransactionReturnType } from 'viem/accounts'
9
+
10
+ export async function signKmsTransaction<
11
+ serializer extends
12
+ SerializeTransactionFn<TransactionSerializable> = SerializeTransactionFn<TransactionSerializable>,
13
+ transaction extends Parameters<serializer>[0] = Parameters<serializer>[0],
14
+ >(
15
+ parameters: Omit<SignTransactionParameters<serializer, transaction>, 'privateKey'> & {
16
+ config: Omit<KmsSignParameters, 'hash'>
17
+ },
18
+ ): Promise<SignTransactionReturnType<serializer, transaction>> {
19
+ const { transaction, serializer = serializeTransaction, config } = parameters
20
+
21
+ const signableTransaction = (() => {
22
+ // For EIP-4844 Transactions, we want to sign the transaction payload body (tx_payload_body) without the sidecars (ie. without the network wrapper).
23
+ // See: https://github.com/ethereum/EIPs/blob/e00f4daa66bd56e2dbd5f1d36d09fd613811a48b/EIPS/eip-4844.md#networking
24
+ if (transaction.type === 'eip4844')
25
+ return {
26
+ ...transaction,
27
+ sidecars: false,
28
+ }
29
+ return transaction
30
+ })()
31
+ const signature = await signKms({
32
+ ...config,
33
+ hash: keccak256(serializer(signableTransaction)),
34
+ to: 'object',
35
+ })
36
+ return serializer(transaction, signature) as SignTransactionReturnType<serializer, transaction>
37
+ }
@@ -0,0 +1,21 @@
1
+ import { KmsSignParameters, signKms } from '@/sign/kms-account/signKms'
2
+ import { hashTypedData, SignTypedDataReturnType, TypedData } from 'viem'
3
+ import { SignTypedDataParameters } from 'viem/accounts'
4
+
5
+ export async function signKmsTypedData<
6
+ const typedData extends TypedData | Record<string, unknown>,
7
+ primaryType extends keyof typedData | 'EIP712Domain',
8
+ >(
9
+ parameters: Omit<SignTypedDataParameters<typedData, primaryType>, 'privateKey'> & {
10
+ config: Omit<KmsSignParameters, 'hash'>
11
+ },
12
+ ): Promise<SignTypedDataReturnType> {
13
+ const { config, ...typedData } = parameters as unknown as SignTypedDataParameters & {
14
+ config: Omit<KmsSignParameters, 'hash'>
15
+ }
16
+ return await signKms({
17
+ hash: hashTypedData(typedData),
18
+ ...config,
19
+ to: 'hex',
20
+ })
21
+ }
@@ -0,0 +1,89 @@
1
+ import { Injectable, Logger, OnApplicationBootstrap } from '@nestjs/common'
2
+ import { InjectModel } from '@nestjs/mongoose'
3
+ import { Model } from 'mongoose'
4
+ import { Nonce } from './schemas/nonce.schema'
5
+ import { JobsOptions, Queue } from 'bullmq'
6
+ import { QUEUES } from '../common/redis/constants'
7
+ import { InjectQueue } from '@nestjs/bullmq'
8
+ import { EcoConfigService } from '../eco-configs/eco-config.service'
9
+ import { entries } from 'lodash'
10
+ import { AtomicKeyClientParams, AtomicNonceService } from './atomic.nonce.service'
11
+ import { createPublicClient, extractChain, Hex, sha256 } from 'viem'
12
+ import { SignerService } from './signer.service'
13
+ import { getTransport } from '../common/chains/transport'
14
+ import { ChainsSupported } from '../common/chains/supported'
15
+
16
+ /**
17
+ * TODO this class needs to be assigned to an EAO, a userOp gets its nonce throught the alchemy sdk
18
+ * which pulls its fromt the rpc bundler
19
+ */
20
+ @Injectable()
21
+ export class NonceService extends AtomicNonceService<Nonce> implements OnApplicationBootstrap {
22
+ protected logger = new Logger(NonceService.name)
23
+ private intentJobConfig: JobsOptions
24
+
25
+ constructor(
26
+ @InjectModel(Nonce.name) private nonceModel: Model<Nonce>,
27
+ @InjectQueue(QUEUES.SIGNER.queue) private readonly signerQueue: Queue,
28
+ private readonly signerService: SignerService,
29
+ private readonly ecoConfigService: EcoConfigService,
30
+ ) {
31
+ super(nonceModel)
32
+ }
33
+ async onApplicationBootstrap() {
34
+ this.intentJobConfig = this.ecoConfigService.getRedis().jobs.intentJobConfig
35
+ this.syncQueue()
36
+ }
37
+
38
+ async syncQueue() {
39
+ const { should, hash } = await this.shouldSync()
40
+ if (should) {
41
+ await this.signerQueue.add(
42
+ QUEUES.SIGNER.jobs.nonce_sync,
43
+ {},
44
+ {
45
+ jobId: hash,
46
+ ...this.intentJobConfig,
47
+ },
48
+ )
49
+ }
50
+ }
51
+
52
+ protected override async getSyncParams(): Promise<AtomicKeyClientParams[]> {
53
+ const address = this.signerService.getAccount().address
54
+ const apiKey = this.ecoConfigService.getAlchemy().apiKey
55
+ const paramsAsync = entries(this.ecoConfigService.getSolvers()).map(async ([chainIdString]) => {
56
+ const chainID = parseInt(chainIdString)
57
+ const chain = extractChain({
58
+ chains: ChainsSupported,
59
+ id: chainID,
60
+ })
61
+ const client = createPublicClient({
62
+ chain,
63
+ transport: getTransport(chain, apiKey),
64
+ } as any)
65
+ return { address, client } as AtomicKeyClientParams
66
+ })
67
+
68
+ return await Promise.all(paramsAsync)
69
+ }
70
+
71
+ async getLastSynceAt(): Promise<Date> {
72
+ const meta = await this.nonceModel
73
+ .findOne({ updatedAt: { $exists: true } })
74
+ .sort({ updatedAt: -1 })
75
+ .exec()
76
+ if (!meta) {
77
+ return new Date(0)
78
+ }
79
+ return meta.updatedAt
80
+ }
81
+
82
+ async shouldSync(): Promise<{ should: boolean; hash: string }> {
83
+ const lastSyncAt = await this.getLastSynceAt()
84
+ const should =
85
+ Date.now() - lastSyncAt.getTime() > this.ecoConfigService.getEth().nonce.update_interval_ms
86
+ const input = `0x${lastSyncAt.toISOString()}` as Hex
87
+ return { should, hash: sha256(input) }
88
+ }
89
+ }
@@ -0,0 +1,36 @@
1
+ import { Prop, Schema, SchemaFactory } from '@nestjs/mongoose'
2
+ import { now } from 'mongoose'
3
+ import { AtomicKeyParams } from '../atomic.nonce.service'
4
+ import { Hex } from 'viem'
5
+ import { getAtomicNonceVals } from '../sign.helper'
6
+
7
+ @Schema({ timestamps: true })
8
+ export class Nonce {
9
+ @Prop({ required: true, unique: true })
10
+ key: string
11
+
12
+ @Prop({ required: true, default: 0 })
13
+ nonce: number
14
+
15
+ @Prop({ required: true })
16
+ chainID: number
17
+
18
+ @Prop({ required: true })
19
+ address: Hex
20
+
21
+ @Prop({ required: true, default: now() })
22
+ createdAt: Date
23
+
24
+ @Prop({ required: true, default: now() })
25
+ updatedAt: Date
26
+
27
+ toString(): string {
28
+ return `${this.key}:${this.nonce}`
29
+ }
30
+
31
+ getAtomicNonceVals(): AtomicKeyParams {
32
+ return getAtomicNonceVals(this.key)
33
+ }
34
+ }
35
+
36
+ export const NonceSchema = SchemaFactory.createForClass(Nonce)
@@ -0,0 +1,52 @@
1
+ import { Controller, Get } from '@nestjs/common'
2
+ import { Logger } from '@nestjs/common'
3
+ import { SignerService } from './signer.service'
4
+
5
+ @Controller('sign')
6
+ export class SignController {
7
+ private logger = new Logger(SignController.name)
8
+ constructor(
9
+ // private readonly aa: MultichainSmartAccountService,
10
+ private readonly signer: SignerService,
11
+ ) {}
12
+ @Get()
13
+ async fake() {
14
+ await this.fakeSign()
15
+
16
+ return
17
+ }
18
+
19
+ async fakeSign() {
20
+ // const smartAccountClient = await this.aa.getClient(84532)
21
+ // let ans = await smartAccountClient.account.getImplementationAddress()
22
+ // console.log(ans, smartAccountClient.account.address)
23
+ // await smartAccountClient.signUserOperation({
24
+ // // @ts-ignore
25
+ // uoStruct: this.getUo().flat(),
26
+ // account: this.atomicSigner.getSigner() as any,
27
+ // })
28
+ // // @ts-ignore
29
+ // const uo = await smartAccountClient.sendUserOperation({
30
+ // uo: this.getUo().flat(),
31
+ // })
32
+ // const receipt = await smartAccountClient.waitForUserOperationTransaction(uo)
33
+ // console.log(receipt)
34
+ // ans = await smartAccountClient.account.getNonce()
35
+ // console.log(ans, smartAccountClient.account.address)
36
+ }
37
+
38
+ // getUo(){
39
+ // const transferSolverAmount = encodeFunctionData({
40
+ // abi: erc20Abi,
41
+ // functionName: 'transfer',
42
+ // args: ['0x3A322Ff8ef24592e5e50D2EB4E630cDA87Bd83A6' as Hex, BigInt(10)],
43
+ // })
44
+
45
+ // return [
46
+ // {
47
+ // target: '0xd3F4Bef596a04e2be4fbeB17Dd70f02F717c5a6c' as Hex,
48
+ // data: transferSolverAmount,
49
+ // },
50
+ // ]
51
+ // }
52
+ }
@@ -0,0 +1,23 @@
1
+ import { Hex, NonceManagerSource, PrivateKeyAccount } from 'viem'
2
+ import { privateKeyToAccount } from 'viem/accounts'
3
+ import { createNonceManager } from 'viem/nonce'
4
+ import { AtomicKeyParams } from './atomic.nonce.service'
5
+
6
+ export function privateKeyAndNonceToAccountSigner(
7
+ atomicNonceSource: NonceManagerSource,
8
+ privateKey: Hex,
9
+ ): PrivateKeyAccount {
10
+ const nonceManager = createNonceManager({
11
+ source: atomicNonceSource,
12
+ })
13
+ return privateKeyToAccount(privateKey, { nonceManager })
14
+ }
15
+
16
+ export function getAtomicNonceKey(params: AtomicKeyParams) {
17
+ return `${params.address}.${params.chainId}`
18
+ }
19
+
20
+ export function getAtomicNonceVals(key: string): AtomicKeyParams {
21
+ const [address, chainId] = key.split('.')
22
+ return { address: address as Hex, chainId: parseInt(chainId) }
23
+ }
@@ -0,0 +1,27 @@
1
+ import { Module } from '@nestjs/common'
2
+ import { MongooseModule } from '@nestjs/mongoose'
3
+ import { Nonce, NonceSchema } from './schemas/nonce.schema'
4
+ import { initBullMQ } from '../bullmq/bullmq.helper'
5
+ import { QUEUES } from '../common/redis/constants'
6
+ import { SignerService } from './signer.service'
7
+ import { AtomicSignerService } from './atomic-signer.service'
8
+ import { NonceService } from './nonce.service'
9
+ import { SignerKmsService } from '@/sign/signer-kms.service'
10
+ import { KmsModule } from '@/kms/kms.module'
11
+
12
+ @Module({
13
+ imports: [
14
+ KmsModule,
15
+ MongooseModule.forFeature([{ name: Nonce.name, schema: NonceSchema }]),
16
+ initBullMQ(QUEUES.SIGNER),
17
+ ],
18
+ providers: [SignerService, SignerKmsService, NonceService, AtomicSignerService],
19
+ exports: [
20
+ AtomicSignerService,
21
+ SignerService,
22
+ SignerKmsService,
23
+ NonceService,
24
+ MongooseModule, //add SignModule to the rest of the modules that import intents
25
+ ],
26
+ })
27
+ export class SignModule {}
@@ -0,0 +1,27 @@
1
+ import { KmsService } from '@/kms/kms.service'
2
+ import { KmsAccount, kmsToAccount } from '@/sign/kms-account/kmsToAccount'
3
+ import { Injectable, OnModuleInit } from '@nestjs/common'
4
+
5
+ /**
6
+ * A signer service that creates a {@link KmsAccount} from a KMS signer.
7
+ * Uses the {@link KmsService} to get the KMS signer from aws.
8
+ */
9
+ @Injectable()
10
+ export class SignerKmsService implements OnModuleInit {
11
+ private account: KmsAccount
12
+ constructor(readonly kmsService: KmsService) {}
13
+
14
+ async onModuleInit() {
15
+ this.account = await this.buildAccount()
16
+ }
17
+
18
+ getAccount() {
19
+ return this.account
20
+ }
21
+
22
+ protected async buildAccount(): Promise<KmsAccount> {
23
+ return await kmsToAccount(this.kmsService.signer, this.kmsService.wallets, {
24
+ keyID: this.kmsService.getKmsKeyId(),
25
+ })
26
+ }
27
+ }
@@ -0,0 +1,26 @@
1
+ import { Injectable, OnModuleInit } from '@nestjs/common'
2
+ import { EcoConfigService } from '../eco-configs/eco-config.service'
3
+ import { Hex, PrivateKeyAccount } from 'viem'
4
+ import { privateKeyToAccount } from 'viem/accounts'
5
+
6
+ @Injectable()
7
+ export class SignerService implements OnModuleInit {
8
+ private account: PrivateKeyAccount
9
+ constructor(readonly ecoConfigService: EcoConfigService) {}
10
+
11
+ async onModuleInit() {
12
+ this.account = this.buildAccount()
13
+ }
14
+
15
+ getAccount() {
16
+ return this.account
17
+ }
18
+
19
+ protected buildAccount(): PrivateKeyAccount {
20
+ return privateKeyToAccount(this.getPrivateKey())
21
+ }
22
+
23
+ protected getPrivateKey(): Hex {
24
+ return this.ecoConfigService.getEth().simpleAccount.signerPrivateKey
25
+ }
26
+ }
@@ -0,0 +1,87 @@
1
+ import { createMock, DeepMocked } from '@golevelup/ts-jest'
2
+ import { ValidSmartWalletService } from '../valid-smart-wallet.service'
3
+ import { MultichainPublicClientService } from '../../../transaction/multichain-public-client.service'
4
+ import { EcoConfigService } from '../../../eco-configs/eco-config.service'
5
+ import { Test, TestingModule } from '@nestjs/testing'
6
+
7
+ describe('ValidSmartWalletService Tests', () => {
8
+ let validWalletService: ValidSmartWalletService
9
+ let publicClientService: DeepMocked<MultichainPublicClientService>
10
+ let ecoConfigService: DeepMocked<EcoConfigService>
11
+
12
+ beforeEach(async () => {
13
+ const validMod: TestingModule = await Test.createTestingModule({
14
+ providers: [
15
+ ValidSmartWalletService,
16
+ {
17
+ provide: MultichainPublicClientService,
18
+ useValue: createMock<MultichainPublicClientService>(),
19
+ },
20
+ { provide: EcoConfigService, useValue: createMock<EcoConfigService>() },
21
+ ],
22
+ }).compile()
23
+
24
+ validWalletService = validMod.get(ValidSmartWalletService)
25
+ publicClientService = validMod.get(MultichainPublicClientService)
26
+ ecoConfigService = validMod.get(EcoConfigService)
27
+ })
28
+
29
+ afterEach(async () => {
30
+ // restore the spy created with spyOn
31
+ jest.restoreAllMocks()
32
+ })
33
+ const entryPoint = '0x123'
34
+ const factory = '0x456'
35
+
36
+ describe('on startup', () => {
37
+ it('should initialize the entry point and factory addresses', async () => {
38
+ const contracts = {
39
+ entryPoint: { contractAddress: entryPoint },
40
+ simpleAccountFactory: { contractAddress: factory },
41
+ }
42
+ ecoConfigService.getEth = jest.fn().mockReturnValue({ simpleAccount: { contracts } })
43
+
44
+ validWalletService.onModuleInit()
45
+
46
+ expect(validWalletService['entryPointAddress']).toEqual(entryPoint)
47
+ expect(validWalletService['factoryAddress']).toEqual(factory)
48
+ })
49
+ })
50
+
51
+ describe('on validate smart wallet', () => {
52
+ beforeEach(() => {
53
+ validWalletService['entryPointAddress'] = entryPoint
54
+ validWalletService['factoryAddress'] = factory
55
+ })
56
+
57
+ it('should return false if there are no deploy events for a SA address', async () => {
58
+ publicClientService.getClient = jest.fn().mockImplementation(async (chainID) => {
59
+ return {
60
+ getContractEvents: jest.fn().mockReturnValue([]),
61
+ }
62
+ })
63
+ const result = await validWalletService.validateSmartWallet('0x789', 1n)
64
+ expect(result).toEqual(false)
65
+ })
66
+
67
+ it('should return false if the SA address is from another factory', async () => {
68
+ publicClientService.getClient = jest.fn().mockImplementation(async (chainID) => {
69
+ return {
70
+ getContractEvents: jest.fn().mockReturnValue([{ args: { factory: '0xabc' } }]),
71
+ }
72
+ })
73
+ const result = await validWalletService.validateSmartWallet('0x789', 1n)
74
+ expect(result).toEqual(false)
75
+ })
76
+
77
+ it('should return true if the SA is from our factory', async () => {
78
+ publicClientService.getClient = jest.fn().mockImplementation(async (chainID) => {
79
+ return {
80
+ getContractEvents: jest.fn().mockReturnValue([{ args: { factory: factory } }]),
81
+ }
82
+ })
83
+ const result = await validWalletService.validateSmartWallet('0x789', 1n)
84
+ expect(result).toEqual(true)
85
+ })
86
+ })
87
+ })
@@ -0,0 +1,58 @@
1
+ import { Injectable, Logger, OnModuleInit } from '@nestjs/common'
2
+ import { MultichainPublicClientService } from '../../transaction/multichain-public-client.service'
3
+ import { EcoConfigService } from '../../eco-configs/eco-config.service'
4
+ import { Hex } from 'viem'
5
+ import { EntryPointAbi_v6 } from '../../contracts/EntryPoint.V6.contract'
6
+ import { EcoLogMessage } from '../../common/logging/eco-log-message'
7
+
8
+ @Injectable()
9
+ export class ValidSmartWalletService implements OnModuleInit {
10
+ private logger = new Logger(ValidSmartWalletService.name)
11
+
12
+ private entryPointAddress: Hex
13
+ private factoryAddress: Hex
14
+ constructor(
15
+ private readonly publicClient: MultichainPublicClientService,
16
+ private readonly ecoConfigService: EcoConfigService,
17
+ ) {}
18
+
19
+ onModuleInit() {
20
+ const contracts = this.ecoConfigService.getEth().simpleAccount.contracts
21
+ this.entryPointAddress = contracts.entryPoint.contractAddress
22
+ this.factoryAddress = contracts.simpleAccountFactory.contractAddress
23
+ }
24
+ /**
25
+ * Validates that the smart wallet account that posts and creates an IntentCreated event on chain
26
+ * for the IntentSource contract, is from the correct smart wallet factory.
27
+ *
28
+ * @param smartWalletAddress the address of the smart wallet to validate
29
+ * @param chainID the chain id of the transaction the event is from
30
+ */
31
+ async validateSmartWallet(smartWalletAddress: Hex, chainID: bigint): Promise<boolean> {
32
+ const client = await this.publicClient.getClient(Number(chainID))
33
+ try {
34
+ const deployedEvents = await client.getContractEvents({
35
+ address: this.entryPointAddress,
36
+ abi: EntryPointAbi_v6,
37
+ eventName: 'AccountDeployed',
38
+ args: { sender: smartWalletAddress },
39
+ fromBlock: 0n,
40
+ toBlock: 'latest',
41
+ })
42
+ //should be only one event, but comes as an array
43
+ return (
44
+ deployedEvents && deployedEvents.some((event) => event.args.factory === this.factoryAddress)
45
+ )
46
+ } catch (error) {
47
+ this.logger.error(
48
+ EcoLogMessage.fromDefault({
49
+ message: `RPC: getContractEvents error`,
50
+ properties: {
51
+ error,
52
+ },
53
+ }),
54
+ )
55
+ return false
56
+ }
57
+ }
58
+ }
@@ -0,0 +1,10 @@
1
+ import { Module } from '@nestjs/common'
2
+ import { ValidSmartWalletService } from './filters/valid-smart-wallet.service'
3
+ import { TransactionModule } from '../transaction/transaction.module'
4
+
5
+ @Module({
6
+ imports: [TransactionModule],
7
+ providers: [ValidSmartWalletService],
8
+ exports: [ValidSmartWalletService],
9
+ })
10
+ export class SolverModule {}
@@ -0,0 +1,15 @@
1
+ import { Injectable } from '@nestjs/common'
2
+ import { createPublicClient, PublicClient, PublicClientConfig } from 'viem'
3
+ import { ViemMultichainClientService } from './viem_multichain_client.service'
4
+
5
+ @Injectable()
6
+ export class MultichainPublicClientService extends ViemMultichainClientService<
7
+ PublicClient,
8
+ PublicClientConfig
9
+ > {
10
+ protected override async createInstanceClient(
11
+ configs: PublicClientConfig,
12
+ ): Promise<PublicClient> {
13
+ return createPublicClient(configs)
14
+ }
15
+ }
@@ -0,0 +1,57 @@
1
+ import { encode7579Calls } from 'permissionless'
2
+ import { KernelVersion } from 'permissionless/accounts'
3
+ import { type Address, type Hex, encodeFunctionData } from 'viem'
4
+ import { isKernelV2 } from '../kernel-account.config'
5
+ import { KernelExecuteAbi } from '../../../../contracts'
6
+
7
+ export const encodeKernelExecuteCallData = ({
8
+ kernelVersion,
9
+ calls,
10
+ }: {
11
+ calls: readonly {
12
+ to: Address
13
+ value?: bigint | undefined
14
+ data?: Hex | undefined
15
+ }[]
16
+ kernelVersion: KernelVersion<'0.6' | '0.7'>
17
+ }) => {
18
+ if (isKernelV2(kernelVersion)) {
19
+ if (calls.length > 1) {
20
+ // Encode a batched call
21
+ return encodeFunctionData({
22
+ abi: KernelExecuteAbi,
23
+ functionName: 'executeBatch',
24
+ args: [
25
+ calls.map((tx) => ({
26
+ to: tx.to,
27
+ value: tx.value ?? 0n,
28
+ data: tx.data ?? '0x',
29
+ })),
30
+ ],
31
+ })
32
+ }
33
+
34
+ const call = calls.length === 0 ? undefined : calls[0]
35
+
36
+ if (!call) {
37
+ throw new Error('No calls to encode')
38
+ }
39
+
40
+ // Encode a simple call
41
+ return encodeFunctionData({
42
+ abi: KernelExecuteAbi,
43
+ functionName: 'execute',
44
+ args: [call.to, call.value ?? 0n, call.data ?? '0x', 0],
45
+ })
46
+ }
47
+
48
+ return encode7579Calls({
49
+ mode: {
50
+ type: calls.length > 1 ? 'batchcall' : 'call',
51
+ revertOnError: false,
52
+ selector: '0x',
53
+ context: '0x',
54
+ },
55
+ callData: calls,
56
+ })
57
+ }