diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..ded222f --- /dev/null +++ b/.dockerignore @@ -0,0 +1,3 @@ +node_modules +.env +.git \ No newline at end of file diff --git a/.gitignore b/.gitignore index c16ef02..2f5f8c8 100644 --- a/.gitignore +++ b/.gitignore @@ -9,6 +9,7 @@ npm-debug.log* yarn-debug.log* yarn-error.log* lerna-debug.log* +.env # OS .DS_Store @@ -31,4 +32,4 @@ lerna-debug.log* !.vscode/settings.json !.vscode/tasks.json !.vscode/launch.json -!.vscode/extensions.json \ No newline at end of file +!.vscode/extensions.json diff --git a/.prettierrc b/.prettierrc index 6dbc2e0..3e189a3 100644 --- a/.prettierrc +++ b/.prettierrc @@ -1,4 +1,5 @@ { "singleQuote": true, "trailingComma": "all", + "printWidth": 140 } diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..86f4498 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,9 @@ +FROM node:12 +WORKDIR /app + +COPY package.json yarn.lock ./ +RUN yarn && yarn cache clean --force +COPY . . + +EXPOSE 8000 +ENTRYPOINT ["yarn"] diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..e66eed7 --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,63 @@ +version: '2' + +services: + server: + image: tornadocash/relayer + restart: always + command: start:prod + env_file: .env + environment: + REDIS_URL: redis://redis/0 + nginx_proxy_read_timeout: 600 + depends_on: [redis] + links: + - redis + + redis: + image: redis + restart: always + command: [redis-server, --appendonly, 'yes'] + volumes: + - redis:/data + + nginx: + image: nginx:alpine + container_name: nginx + restart: always + ports: + - 80:80 + - 443:443 + volumes: + - conf:/etc/nginx/conf.d + - vhost:/etc/nginx/vhost.d + - html:/usr/share/nginx/html + - certs:/etc/nginx/certs + logging: + driver: none + + dockergen: + image: poma/docker-gen + container_name: dockergen + restart: always + command: -notify-sighup nginx -watch /etc/docker-gen/templates/nginx.tmpl /etc/nginx/conf.d/default.conf + volumes_from: + - nginx + volumes: + - /var/run/docker.sock:/var/run/docker.sock:ro + + letsencrypt: + image: jrcs/letsencrypt-nginx-proxy-companion + container_name: letsencrypt + restart: always + environment: + NGINX_DOCKER_GEN_CONTAINER: dockergen + volumes_from: + - nginx + - dockergen + +volumes: + conf: + vhost: + html: + certs: + redis: diff --git a/example.env b/example.env index 5e43c8e..429a903 100644 --- a/example.env +++ b/example.env @@ -1,3 +1,17 @@ -RPC_URL= -PRIVATE_KEY= +# DNS settings +VIRTUAL_HOST= +LETSENCRYPT_HOST= + +# server settings +PORT=8000 + +#commision for service SERVICE_FEE=0.05 + +# bull settings +REDIS_URL=redis://127.0.0.1:6379 + +# tx-manager settings +RPC_URL= +CHAIN_ID=1 +PRIVATE_KEY= diff --git a/package.json b/package.json index 32581bb..5ef4416 100644 --- a/package.json +++ b/package.json @@ -13,7 +13,7 @@ "start": "nest start", "start:dev": "nest start --watch", "start:debug": "nest start --debug --watch", - "start:prod": "node dist/main", + "start:prod": "yarn prebuild; yarn build; node dist/main", "lint": "eslint \"{src,apps,libs,test}/**/*.ts\" --fix", "test": "jest", "test:watch": "jest --watch", diff --git a/src/app.module.ts b/src/app.module.ts index a51171a..4f45eec 100644 --- a/src/app.module.ts +++ b/src/app.module.ts @@ -2,7 +2,7 @@ import { Module } from '@nestjs/common'; import { ConfigModule } from '@nestjs/config'; import { baseConfig } from '@/config'; -import { QueueModule, StatusModule } from '@/modules'; +import { QueueModule, ApiModule } from '@/modules'; @Module({ imports: [ @@ -10,8 +10,8 @@ import { QueueModule, StatusModule } from '@/modules'; load: [baseConfig], isGlobal: true, }), + ApiModule, QueueModule, - StatusModule, ], }) export class AppModule {} diff --git a/src/config/bull.config.ts b/src/config/bull.config.ts index 37a5cb4..32a38f3 100644 --- a/src/config/bull.config.ts +++ b/src/config/bull.config.ts @@ -1,6 +1,7 @@ import { registerAs } from '@nestjs/config'; export default registerAs('bull', () => ({ + name: 'withdrawal', redis: { host: 'localhost', port: 6379, diff --git a/src/config/configuration.ts b/src/config/configuration.ts index 7bb505f..1f68b7b 100644 --- a/src/config/configuration.ts +++ b/src/config/configuration.ts @@ -1,5 +1,6 @@ export const baseConfig = () => ({ + gasLimit: 600000, + serviceFee: process.env.SERVICE_FEE, + chainId: process.env.CHAIN_ID, port: parseInt(process.env.PORT, 10) || 8080, - gasLimit: 400000, - fee: process.env.SERVICE_FEE, }); diff --git a/src/constants/contracts.ts b/src/constants/contracts.ts index b0af696..da4d693 100644 --- a/src/constants/contracts.ts +++ b/src/constants/contracts.ts @@ -3,7 +3,7 @@ import { ChainId } from '@/types'; export const CONTRACT_NETWORKS: { [chainId in ChainId]: string } = { [ChainId.MAINNET]: '0x8Bfac9EF3d73cE08C7CEC339C0fE3B2e57814c1E', [ChainId.GOERLI]: '0x20a2D506cf52453D681F9E8E814A3437c6242B9e', - [ChainId.OPTIMISM]: '0xc436071dE853A4421c57ddD0CDDC116C735aa8b5', + [ChainId.OPTIMISM]: '0x1Ed4dcDB4b78985008199f451E88C6448C4EDd94', }; export const RPC_LIST: { [chainId in ChainId]: string } = { diff --git a/src/contracts/index.ts b/src/contracts/index.ts deleted file mode 100644 index cacf427..0000000 --- a/src/contracts/index.ts +++ /dev/null @@ -1,10 +0,0 @@ -import { ChainId } from '@/types'; -import { CONTRACT_NETWORKS } from '@/constants'; -import { getProviderWithSigner } from '@/services'; - -import { TornadoPool__factory as TornadoPoolFactory } from '@/artifacts'; - -export function getTornadoPool(chainId: ChainId) { - const provider = getProviderWithSigner(chainId); - return TornadoPoolFactory.connect(CONTRACT_NETWORKS[chainId], provider); -} diff --git a/src/modules/api/api.controller.ts b/src/modules/api/api.controller.ts new file mode 100644 index 0000000..710f951 --- /dev/null +++ b/src/modules/api/api.controller.ts @@ -0,0 +1,31 @@ +import { Controller, Body, Param, Get, Post } from '@nestjs/common'; +import { Job } from 'bull'; + +import { ApiService } from './api.service'; + +@Controller() +export class ApiController { + constructor(private readonly service: ApiService) {} + + @Get('/api') + async status(): Promise { + return await this.service.status(); + } + + @Get('/') + async main(): Promise { + return this.service.main(); + } + + @Get('/job/:jobId') + async getJob(@Param('jobId') jobId: string): Promise { + return await this.service.getJob(jobId); + } + + @Post('/withdrawal') + async withdrawal(_, @Body() { body }: any): Promise { + console.log('body', body); + + return await this.service.withdrawal(JSON.parse(body)); + } +} diff --git a/src/modules/status/stat.module.ts b/src/modules/api/api.module.ts similarity index 50% rename from src/modules/status/stat.module.ts rename to src/modules/api/api.module.ts index 02deb22..e5f00c0 100644 --- a/src/modules/status/stat.module.ts +++ b/src/modules/api/api.module.ts @@ -1,15 +1,15 @@ import { Module } from '@nestjs/common'; import { ConfigModule } from '@nestjs/config'; -import { StatusService } from './stat.service'; -import { StatusController } from './stat.controller'; +import { ApiService } from './api.service'; +import { ApiController } from './api.controller'; import { QueueModule } from '@/modules'; @Module({ imports: [ConfigModule, QueueModule], - providers: [StatusService], - controllers: [StatusController], + providers: [ApiService], + controllers: [ApiController], exports: [], }) -export class StatusModule {} +export class ApiModule {} diff --git a/src/modules/status/stat.service.ts b/src/modules/api/api.service.ts similarity index 63% rename from src/modules/status/stat.service.ts rename to src/modules/api/api.service.ts index f43342d..eb922c9 100644 --- a/src/modules/status/stat.service.ts +++ b/src/modules/api/api.service.ts @@ -1,9 +1,9 @@ -import { Injectable } from '@nestjs/common'; -import { Queue } from 'bull'; +import { Queue, Job } from 'bull'; import { InjectQueue } from '@nestjs/bull'; +import { Injectable } from '@nestjs/common'; @Injectable() -class StatusService { +class ApiService { constructor(@InjectQueue('withdrawal') private withdrawalQueue: Queue) {} async status(): Promise { @@ -17,11 +17,15 @@ class StatusService { return `This is tornado.cash Relayer service. Check the /status for settings`; } - async withdrawal(data): Promise { - const job = await this.withdrawalQueue.add(data) + async withdrawal(data: any): Promise { + const job = await this.withdrawalQueue.add(data); return String(job.id); } + + async getJob(id: string): Promise { + return await this.withdrawalQueue.getJob(id); + } } -export { StatusService }; +export { ApiService }; diff --git a/src/modules/status/stat.validator.ts b/src/modules/api/api.validator.ts similarity index 100% rename from src/modules/status/stat.validator.ts rename to src/modules/api/api.validator.ts diff --git a/src/modules/status/dto/create-subscribe.dto.ts b/src/modules/api/dto/create-subscribe.dto.ts similarity index 55% rename from src/modules/status/dto/create-subscribe.dto.ts rename to src/modules/api/dto/create-subscribe.dto.ts index d7996e7..e82c9f6 100644 --- a/src/modules/status/dto/create-subscribe.dto.ts +++ b/src/modules/api/dto/create-subscribe.dto.ts @@ -1,4 +1,4 @@ -export class CreateStatusDto { +export class CreateApiDto { error: boolean; status: string; } diff --git a/src/modules/status/dto/index.ts b/src/modules/api/dto/index.ts similarity index 100% rename from src/modules/status/dto/index.ts rename to src/modules/api/dto/index.ts diff --git a/src/modules/api/index.ts b/src/modules/api/index.ts new file mode 100644 index 0000000..bdb3557 --- /dev/null +++ b/src/modules/api/index.ts @@ -0,0 +1 @@ +export { ApiModule } from './api.module'; diff --git a/src/modules/status/types/index.ts b/src/modules/api/types/index.ts similarity index 100% rename from src/modules/status/types/index.ts rename to src/modules/api/types/index.ts diff --git a/src/modules/index.ts b/src/modules/index.ts index 2193d5d..5af8864 100644 --- a/src/modules/index.ts +++ b/src/modules/index.ts @@ -1,2 +1,2 @@ export * from './queue'; -export * from './status'; +export * from './api'; diff --git a/src/modules/queue/base.processor.ts b/src/modules/queue/base.processor.ts index 7cbb2b0..413407f 100644 --- a/src/modules/queue/base.processor.ts +++ b/src/modules/queue/base.processor.ts @@ -10,7 +10,6 @@ import { } from '@nestjs/bull'; import { Injectable, OnModuleDestroy } from '@nestjs/common'; import { Job, Queue } from 'bull'; -import { v4 as uuid } from 'uuid'; @Injectable() @Processor() @@ -54,17 +53,11 @@ export class BaseProcessor implements OnModuleDestroy { return this.updateTask(job); } - async updateTask(job: Job) { + private async updateTask(job: Job) { const currentJob = await this.queue.getJob(job.id); await currentJob.update(job.data); } - private async createTask({ request }) { - const id = uuid(); - await this.queue.add({ ...request, id }); - return id; - } - async onModuleDestroy() { if (this.queue) { await this.queue.close(); diff --git a/src/modules/queue/queue.module.ts b/src/modules/queue/queue.module.ts index 7f8d7e8..ecfcc8b 100644 --- a/src/modules/queue/queue.module.ts +++ b/src/modules/queue/queue.module.ts @@ -1,18 +1,15 @@ import { BullModule } from '@nestjs/bull'; import { Module } from '@nestjs/common'; +import { GasPriceService, ProviderService } from '@/services'; + import { WithdrawalProcessor } from './withdrawal.processor'; import bullConfig from '@/config/bull.config'; @Module({ - imports: [ - BullModule.registerQueue({ - ...bullConfig(), - name: 'withdrawal', - }), - ], - providers: [WithdrawalProcessor], + imports: [BullModule.registerQueue(bullConfig())], + providers: [GasPriceService, ProviderService, WithdrawalProcessor], exports: [BullModule], }) export class QueueModule {} diff --git a/src/modules/queue/withdrawal.processor.ts b/src/modules/queue/withdrawal.processor.ts index 0f9cc62..e39a418 100644 --- a/src/modules/queue/withdrawal.processor.ts +++ b/src/modules/queue/withdrawal.processor.ts @@ -7,11 +7,11 @@ import { ConfigService } from '@nestjs/config'; import { InjectQueue, Process, Processor } from '@nestjs/bull'; import { toWei } from '@/utilities'; -import { getGasPrice } from '@/services'; -import { getTornadoPool } from '@/contracts'; +import { GasPriceService, ProviderService } from '@/services'; import txMangerConfig from '@/config/txManager.config'; import { BaseProcessor } from './base.processor'; +import { ChainId } from '@/types'; export interface Withdrawal { args: string[]; @@ -27,6 +27,8 @@ export interface Withdrawal { export class WithdrawalProcessor extends BaseProcessor { constructor( @InjectQueue('withdrawal') public withdrawalQueue: Queue, + private gasPriceService: GasPriceService, + private providerService: ProviderService, private configService: ConfigService, ) { super(); @@ -49,12 +51,12 @@ export class WithdrawalProcessor extends BaseProcessor { } async submitTx(job: Job) { - const txManager = new TxManager(txMangerConfig()); - - const prepareTx = await this.prepareTransaction(job.data); - const tx = await txManager.createTx(prepareTx); - try { + const txManager = new TxManager(txMangerConfig()); + + const prepareTx = await this.prepareTransaction(job.data); + const tx = await txManager.createTx(prepareTx); + const receipt = await tx .send() .on('transactionHash', async (txHash: string) => { @@ -88,44 +90,52 @@ export class WithdrawalProcessor extends BaseProcessor { } } - async prepareTransaction({ proof, args, amount }) { - const contract = getTornadoPool(5); + async prepareTransaction({ proof, args }) { + const chainId = this.configService.get('chainId'); + + const contract = this.providerService.getTornadoPool(); - // eslint-disable-next-line @typescript-eslint/ban-ts-comment // @ts-ignore - const data = contract.interface.encodeFunctionData('transaction', [ - proof, - ...args, - ]); + const data = contract.interface.encodeFunctionData('transaction', [proof, ...args]); - const gasLimit = this.configService.get('gasLimit'); + let gasLimit = this.configService.get('gasLimit'); + + // need because optimism has dynamic gas limit + if (chainId === ChainId.OPTIMISM) { + // @ts-ignore + gasLimit = await contract.estimateGas.transaction(proof, ...args, { + value: BigNumber.from(0)._hex, + from: '0x1a5245ea5210C3B57B7Cfdf965990e63534A7b52', + gasPrice: toWei('0.015', 'gwei'), + }); + } + + const { fast } = await this.gasPriceService.getGasPrice(); return { data, gasLimit, - value: BigNumber.from(0)._hex, to: contract.address, + gasPrice: fast.toString(), + value: BigNumber.from(0)._hex, }; } async checkFee({ fee, amount }) { - const gasLimit = this.configService.get('gasLimit'); + const { gasLimit, serviceFee } = this.configService.get(''); - const { fast } = await getGasPrice(5); + const { fast } = await this.gasPriceService.getGasPrice(); - const expense = BigNumber.from(toWei(fast.toString(), 'gwei')).mul( - gasLimit, - ); + const expense = BigNumber.from(toWei(fast.toString(), 'gwei')).mul(gasLimit); - const serviceFee = this.configService.get('fee'); - const feePercent = BigNumber.from(amount).mul(serviceFee * 1e10).div(100 * 1e10) + const feePercent = BigNumber.from(amount) + .mul(serviceFee * 1e10) + .div(100 * 1e10); const desiredFee = expense.add(feePercent); if (BigNumber.from(fee).lt(desiredFee)) { - throw new Error( - 'Provided fee is not enough. Probably it is a Gas Price spike, try to resubmit.', - ); + throw new Error('Provided fee is not enough. Probably it is a Gas Price spike, try to resubmit.'); } } } diff --git a/src/modules/status/index.ts b/src/modules/status/index.ts deleted file mode 100644 index 766a223..0000000 --- a/src/modules/status/index.ts +++ /dev/null @@ -1 +0,0 @@ -export { StatusModule } from './stat.module'; diff --git a/src/modules/status/stat.controller.ts b/src/modules/status/stat.controller.ts deleted file mode 100644 index 41c64c4..0000000 --- a/src/modules/status/stat.controller.ts +++ /dev/null @@ -1,25 +0,0 @@ -import { Controller, Body, Get, Post } from '@nestjs/common'; - -import { StatusService } from './stat.service'; - -@Controller() -export class StatusController { - constructor(private readonly service: StatusService) {} - - @Get('/status') - async status(): Promise { - return await this.service.status(); - } - - @Get('/') - async main(): Promise { - return this.service.main(); - } - - @Post('/withdrawal') - async withdrawal(_, @Body() { body }: any): Promise { - console.log('body', body) - - return await this.service.withdrawal(JSON.parse(body)) - } -} diff --git a/src/services/ether.ts b/src/services/ether.ts deleted file mode 100644 index 6463279..0000000 --- a/src/services/ether.ts +++ /dev/null @@ -1,26 +0,0 @@ -import { ethers } from 'ethers'; - -import { ChainId } from '@/types'; -import { RPC_LIST } from '@/constants'; - -interface Options { - url: string; -} - -export class Provider { - public provider: ethers.providers.JsonRpcProvider; - - constructor(options: Options) { - this.provider = new ethers.providers.JsonRpcProvider(options.url); - } -} - -export function getProvider(chainId: ChainId): Provider { - return new Provider({ url: RPC_LIST[chainId] }); -} - -export function getProviderWithSigner( - chainId: ChainId, -): ethers.providers.BaseProvider { - return ethers.providers.getDefaultProvider(RPC_LIST[chainId]); -} diff --git a/src/services/flashbot.ts b/src/services/flashbot.ts deleted file mode 100644 index f6f2614..0000000 --- a/src/services/flashbot.ts +++ /dev/null @@ -1,91 +0,0 @@ -import { Wallet, PopulatedTransaction } from 'ethers'; -import { - FlashbotsBundleProvider, - FlashbotsBundleResolution, -} from '@flashbots/ethers-provider-bundle'; - -import { ChainId } from '@/types'; -import { numbers } from '@/constants'; -import { getProviderWithSigner } from '@/services'; - -const authSigner = Wallet.createRandom(); - -const FLASH_BOT_RPC: { [key in ChainId]: { name: string; url: string } } = { - [ChainId.GOERLI]: { - url: 'https://relay-goerli.flashbots.net/', - name: 'goerli', - }, - [ChainId.MAINNET]: { - url: '', - name: '', - }, -}; - -async function sendFlashBotTransaction( - transaction: PopulatedTransaction, - chainId: ChainId, -) { - const provider = getProviderWithSigner(chainId); - - const { url, name } = FLASH_BOT_RPC[chainId]; - - const flashBotsProvider = await FlashbotsBundleProvider.create( - provider, - authSigner, - url, - name, - ); - - const nonce = await provider.getTransactionCount(authSigner.address); - - const mergedTx = { - ...transaction, - nonce, - from: authSigner.address, - }; - - const signedTransaction = await authSigner.signTransaction(mergedTx); - - const TIME_10_BLOCK = 130; - - const blockNumber = await provider.getBlockNumber(); - const minTimestamp = (await provider.getBlock(blockNumber)).timestamp; - - const maxTimestamp = minTimestamp + TIME_10_BLOCK; - const targetBlockNumber = blockNumber + numbers.TWO; - - const simulation = await flashBotsProvider.simulate( - [signedTransaction], - targetBlockNumber, - ); - - if ('error' in simulation) { - console.log(`Simulation Error: ${simulation.error.message}`); - } else { - console.log( - `Simulation Success: ${JSON.stringify(simulation, null, numbers.TWO)}`, - ); - } - - const bundleSubmission = await flashBotsProvider.sendBundle( - [{ signedTransaction }], - targetBlockNumber, - { - minTimestamp, - maxTimestamp, - }, - ); - - if ('error' in bundleSubmission) { - throw new Error(bundleSubmission.error.message); - } - - const waitResponse = await bundleSubmission.wait(); - const bundleSubmissionSimulation = await bundleSubmission.simulate(); - console.log({ - bundleSubmissionSimulation, - waitResponse: FlashbotsBundleResolution[waitResponse], - }); -} - -export { sendFlashBotTransaction }; diff --git a/src/services/index.ts b/src/services/index.ts index d8c43d0..d8656bc 100644 --- a/src/services/index.ts +++ b/src/services/index.ts @@ -1,3 +1,2 @@ -export * from './ether'; -export * from './oracle'; -export * from './flashbot'; +export * from './oracle.service'; +export * from './provider.service'; diff --git a/src/services/oracle.service.ts b/src/services/oracle.service.ts new file mode 100644 index 0000000..0e0e18f --- /dev/null +++ b/src/services/oracle.service.ts @@ -0,0 +1,45 @@ +import { Injectable } from '@nestjs/common'; +import { ConfigService } from '@nestjs/config'; + +import { GasPriceOracle } from 'gas-price-oracle'; +import { GasPrice } from 'gas-price-oracle/lib/types'; + +import { ChainId } from '@/types'; +import { toWei } from '@/utilities'; +import { RPC_LIST, numbers } from '@/constants'; + +@Injectable() +export class GasPriceService { + private readonly chainId: number; + + constructor(private configService: ConfigService) { + this.chainId = this.configService.get('chainId'); + } + + async getGasPrice(): Promise { + if (this.chainId === ChainId.OPTIMISM) { + return GasPriceService.getOptimismPrice(); + } + + const TIMER = 10; + const INTERVAL = TIMER * numbers.SECOND; + + const instance = new GasPriceOracle({ + timeout: INTERVAL, + defaultRpc: RPC_LIST[ChainId.MAINNET], + }); + + return await instance.gasPrices(); + } + + private static getOptimismPrice() { + const OPTIMISM_GAS = toWei('0.015', 'gwei').toNumber(); + + return { + fast: OPTIMISM_GAS, + low: OPTIMISM_GAS, + instant: OPTIMISM_GAS, + standard: OPTIMISM_GAS, + }; + } +} diff --git a/src/services/oracle.ts b/src/services/oracle.ts deleted file mode 100644 index 99d6ccb..0000000 --- a/src/services/oracle.ts +++ /dev/null @@ -1,29 +0,0 @@ -import { GasPriceOracle } from 'gas-price-oracle'; -import { GasPrice } from 'gas-price-oracle/lib/types'; - -import { ChainId } from '@/types'; -import { RPC_LIST, numbers } from '@/constants'; - -const SECONDS = 10; -const TEN_SECOND = SECONDS * numbers.SECOND; - -const OPTIMISM_GAS_PRICE = { - fast: 0.015, - low: 0.015, - instant: 0.015, - standard: 0.015, -}; - -const getGasPrice = async (chainId: ChainId): Promise => { - if (chainId === ChainId.OPTIMISM) { - return OPTIMISM_GAS_PRICE; - } - - const instance = new GasPriceOracle({ - timeout: TEN_SECOND, - defaultRpc: RPC_LIST[ChainId.MAINNET], - }); - return await instance.gasPrices(); -}; - -export { getGasPrice }; diff --git a/src/services/provider.service.ts b/src/services/provider.service.ts new file mode 100644 index 0000000..abe2c77 --- /dev/null +++ b/src/services/provider.service.ts @@ -0,0 +1,27 @@ +import { ethers } from 'ethers'; +import { Injectable } from '@nestjs/common'; +import { ConfigService } from '@nestjs/config'; + +import { CONTRACT_NETWORKS, RPC_LIST } from '@/constants'; +import { TornadoPool__factory as TornadoPoolFactory } from '@/artifacts'; + +@Injectable() +export class ProviderService { + private readonly chainId: number; + + constructor(private configService: ConfigService) { + this.chainId = this.configService.get('chainId'); + } + + getProvider() { + return new ethers.providers.JsonRpcProvider(RPC_LIST[this.chainId]); + } + + getProviderWithSigner() { + return ethers.providers.getDefaultProvider(RPC_LIST[this.chainId]); + } + + getTornadoPool() { + return TornadoPoolFactory.connect(CONTRACT_NETWORKS[this.chainId], this.getProviderWithSigner()); + } +}