diff --git a/example.env b/example.env index d2601a0..9fedc56 100644 --- a/example.env +++ b/example.env @@ -5,8 +5,11 @@ LETSENCRYPT_HOST= # server settings PORT=8000 -#commision for service -SERVICE_FEE=0.05 +# commission for service +# transfer fee is a fixed value in ether, 0.01 means 0.01 ether +TRANSFER_SERVICE_FEE=0.01 +# withdrawal fee is a percentage of the amount, 0.05 means 0.05% +WITHDRAWAL_SERVICE_FEE=0.05 REWARD_ADDRESS= # tx-manager settings diff --git a/src/config/configuration.ts b/src/config/configuration.ts index 12a00b7..6b60f1b 100644 --- a/src/config/configuration.ts +++ b/src/config/configuration.ts @@ -1,4 +1,5 @@ import { Wallet } from 'ethers'; +import { toWei } from '@/utilities'; import { NETWORKS_INFO } from '@/constants'; import { version } from '../../package.json'; @@ -8,7 +9,10 @@ export const baseConfig = () => ({ version, port: process.env.PORT, chainId: process.env.CHAIN_ID, - serviceFee: process.env.SERVICE_FEE, + serviceFee: { + transfer: toWei(process.env.TRANSFER_SERVICE_FEE).toString(), + withdrawal: Number(process.env.WITHDRAWAL_SERVICE_FEE), + }, rewardAddress: process.env.REWARD_ADDRESS, address: new Wallet(process.env.PRIVATE_KEY).address, gasLimit: NETWORKS_INFO[process.env.CHAIN_ID].gasLimit, diff --git a/src/constants/variables.ts b/src/constants/variables.ts index 7dc4a35..8fbdda9 100644 --- a/src/constants/variables.ts +++ b/src/constants/variables.ts @@ -3,11 +3,11 @@ import { ChainId } from '@/types'; const NETWORKS_INFO: { [chainId in ChainId] } = { [ChainId.MAINNET]: { - gasLimit: BigNumber.from(600000), + gasLimit: BigNumber.from(400000), minimumBalance: '0.5', }, [ChainId.GOERLI]: { - gasLimit: BigNumber.from(600000), + gasLimit: BigNumber.from(400000), minimumBalance: '0.5', }, [ChainId.OPTIMISM]: { @@ -20,6 +20,8 @@ const numbers = { ZERO: 0, ONE: 1, TWO: 2, + TEN: 10, + ONE_HUNDRED: 100, SECOND: 1000, ETH_DECIMALS: 18, MERKLE_TREE_HEIGHT: 23, diff --git a/src/modules/api/api.service.ts b/src/modules/api/api.service.ts index e0b2ede..3e637af 100644 --- a/src/modules/api/api.service.ts +++ b/src/modules/api/api.service.ts @@ -21,9 +21,9 @@ class ApiService { return { health, version, + serviceFee, rewardAddress, chainId: Number(chainId), - serviceFee: Number(serviceFee), }; } diff --git a/src/modules/api/api.validator.ts b/src/modules/api/api.validator.ts index f85ba73..fbfe0de 100644 --- a/src/modules/api/api.validator.ts +++ b/src/modules/api/api.validator.ts @@ -26,9 +26,6 @@ const arrayType = { type: 'array', items: bytes32Type }; const transactionSchema = { type: 'object', properties: { - amount: { - type: 'string', - }, extData: { type: 'object', properties: { @@ -55,7 +52,7 @@ const transactionSchema = { }, }, additionalProperties: false, - required: ['extData', 'args', 'amount'], + required: ['extData', 'args'], }; const validateTornadoTransaction = ajv.compile(transactionSchema); diff --git a/src/modules/api/types/index.ts b/src/modules/api/types/index.ts index 8296f2e..05b8c9a 100644 --- a/src/modules/api/types/index.ts +++ b/src/modules/api/types/index.ts @@ -3,10 +3,15 @@ type Health = { error: string; }; +type ServiceFee = { + transfer: string; + withdrawal: number; +}; + type Status = { health: Health; - rewardAddress: string; - version: string; - serviceFee: number; chainId: number; + version: string; + rewardAddress: string; + serviceFee: ServiceFee; }; diff --git a/src/modules/queue/transaction.processor.ts b/src/modules/queue/transaction.processor.ts index e553191..982cd92 100644 --- a/src/modules/queue/transaction.processor.ts +++ b/src/modules/queue/transaction.processor.ts @@ -7,7 +7,8 @@ import { Injectable } from '@nestjs/common'; import { ConfigService } from '@nestjs/config'; import { InjectQueue, Process, Processor } from '@nestjs/bull'; -import { toWei } from '@/utilities'; +import { numbers } from '@/constants'; +import { toWei, getToIntegerMultiplier } from '@/utilities'; import { GasPriceService, ProviderService } from '@/services'; import txMangerConfig from '@/config/txManager.config'; @@ -37,7 +38,6 @@ export type ArgsProof = { export interface Transaction { extData: ExtData; args: ArgsProof; - amount: string; txHash: string; status: string; confirmations: number; @@ -62,9 +62,9 @@ export class TransactionProcessor extends BaseProcessor { try { await job.isActive(); - const { extData, amount } = job.data; + const { extData } = job.data; - await this.checkFee({ fee: extData.fee, amount }); + await this.checkFee({ fee: extData.fee, externalAmount: extData.extAmount }); await this.submitTx(job); } catch (err) { await job.moveToFailed(err, true); @@ -140,16 +140,29 @@ export class TransactionProcessor extends BaseProcessor { }; } - async checkFee({ fee, amount }) { - const { gasLimit, serviceFee } = this.configService.get('base'); + getServiceFee(externalAmount) { + const amount = BigNumber.from(externalAmount); + const { serviceFee } = this.configService.get('base'); + + // for withdrawals the amount is negative + if (amount.isNegative()) { + const integerMultiplier = getToIntegerMultiplier(serviceFee.withdrawal); + return BigNumber.from(amount) + .mul(serviceFee.withdrawal * integerMultiplier) + .div(numbers.ONE_HUNDRED * integerMultiplier); + } + + return serviceFee.transfer; + } + + async checkFee({ fee, externalAmount }) { + const { gasLimit } = this.configService.get('base'); const { fast } = await this.gasPriceService.getGasPrice(); const expense = BigNumber.from(toWei(fast.toString(), 'gwei')).mul(gasLimit); - const feePercent = BigNumber.from(amount) - .mul(serviceFee * 1e10) - .div(100 * 1e10); + const feePercent = this.getServiceFee(externalAmount); const desiredFee = expense.add(feePercent); diff --git a/src/utilities/crypto.ts b/src/utilities/crypto.ts index 06cb8f2..ecc3a8c 100644 --- a/src/utilities/crypto.ts +++ b/src/utilities/crypto.ts @@ -10,7 +10,7 @@ export function toChecksumAddress(value: string): string { return utils.getAddress(value); } -export function toWei(value: string, uintName = 'wei') { +export function toWei(value: string, uintName = 'ether') { return utils.parseUnits(value, uintName); } @@ -25,3 +25,13 @@ export function numberToHex(value: number) { export function fromWei(balance: BigNumberish) { return utils.formatUnits(balance, numbers.ETH_DECIMALS); } + +export function getToIntegerMultiplier(value: number | string): number { + const [, decimals] = String(value).split('.'); + + if (!decimals) { + return numbers.ZERO; + } + + return Math.pow(numbers.TEN, decimals.length); +}