From 9f812754bd74495a59cd0b18002fce9db6bcadd9 Mon Sep 17 00:00:00 2001 From: Claudiu Lataretu Date: Fri, 21 Jul 2023 17:11:35 +0300 Subject: [PATCH 1/3] MEX-333: add fees collector field to pair model Signed-off-by: Claudiu Lataretu --- src/modules/pair/models/pair.model.ts | 7 +++++ src/modules/pair/pair.resolver.ts | 16 +++++++++++ src/modules/pair/services/pair.abi.service.ts | 27 +++++++++++++++++++ 3 files changed, 50 insertions(+) diff --git a/src/modules/pair/models/pair.model.ts b/src/modules/pair/models/pair.model.ts index 469b5b8fc..e9f5dcf63 100644 --- a/src/modules/pair/models/pair.model.ts +++ b/src/modules/pair/models/pair.model.ts @@ -3,6 +3,7 @@ import { PaginationArgs } from '../../dex.model'; import { EsdtToken } from 'src/modules/tokens/models/esdtToken.model'; import { PairInfoModel } from './pair-info.model'; import { SimpleLockModel } from 'src/modules/simple-lock/models/simple.lock.model'; +import { FeesCollectorModel } from 'src/modules/fees-collector/models/fees-collector.model'; @ArgsType() export class GetPairsArgs extends PaginationArgs {} @@ -126,6 +127,12 @@ export class PairModel { @Field(() => [FeeDestination]) feeDestinations: FeeDestination[]; + @Field(() => FeesCollectorModel, { + nullable: true, + description: 'Fees collector set for this pair', + }) + feesCollector: FeesCollectorModel; + constructor(init?: Partial) { Object.assign(this, init); } diff --git a/src/modules/pair/pair.resolver.ts b/src/modules/pair/pair.resolver.ts index a06f4d8a9..d81231885 100644 --- a/src/modules/pair/pair.resolver.ts +++ b/src/modules/pair/pair.resolver.ts @@ -25,6 +25,7 @@ import { EsdtToken } from '../tokens/models/esdtToken.model'; import { PairAbiService } from './services/pair.abi.service'; import { PairComputeService } from './services/pair.compute.service'; import { JwtOrNativeAdminGuard } from '../auth/jwt.or.native.admin.guard'; +import { FeesCollectorModel } from '../fees-collector/models/fees-collector.model'; @Resolver(() => PairModel) export class PairResolver { @@ -182,6 +183,21 @@ export class PairResolver { return this.pairAbi.feeDestinations(parent.address); } + @ResolveField() + async feesCollector( + @Parent() parent: PairModel, + ): Promise { + const feesCollectorAddress = await this.pairAbi.feesCollectorAddress( + parent.address, + ); + + return feesCollectorAddress + ? new FeesCollectorModel({ + address: feesCollectorAddress, + }) + : undefined; + } + @Query(() => String) async getAmountOut( @Args('pairAddress') pairAddress: string, diff --git a/src/modules/pair/services/pair.abi.service.ts b/src/modules/pair/services/pair.abi.service.ts index 8a906d3b8..68fa5bd06 100644 --- a/src/modules/pair/services/pair.abi.service.ts +++ b/src/modules/pair/services/pair.abi.service.ts @@ -15,6 +15,7 @@ import { EnumValue, Field, ResultsParser, + ReturnCode, Struct, TokenIdentifierValue, U64Value, @@ -702,4 +703,30 @@ export class PairAbiService ).toFixed(), }); } + + @ErrorLoggerAsync({ + className: PairAbiService.name, + logArgs: true, + }) + @GetOrSetCache({ + baseKey: 'pair', + remoteTtl: CacheTtlInfo.ContractState.remoteTtl, + localTtl: CacheTtlInfo.ContractState.localTtl, + }) + async feesCollectorAddress(pairAddress: string): Promise { + return await this.getFeesCollectorAddressRaw(pairAddress); + } + + async getFeesCollectorAddressRaw(address: string): Promise { + const contract = await this.mxProxy.getPairSmartContract(address); + const interaction: Interaction = + contract.methods.getFeesCollectorAddress([]); + const response = await this.getGenericData(interaction); + + if (response.returnCode.equals(ReturnCode.UserError)) { + return undefined; + } + + return new Address(response.firstValue.valueOf().toString()).bech32(); + } } From 8cf5c5e591130c22acae7124d4e37ab7d55c1671 Mon Sep 17 00:00:00 2001 From: Claudiu Lataretu Date: Fri, 21 Jul 2023 17:12:24 +0300 Subject: [PATCH 2/3] MEX-333: add fees collector cut percentage field to pair model Signed-off-by: Claudiu Lataretu --- src/modules/pair/models/pair.model.ts | 5 ++++ src/modules/pair/pair.resolver.ts | 11 ++++++++ src/modules/pair/services/pair.abi.service.ts | 26 +++++++++++++++++++ 3 files changed, 42 insertions(+) diff --git a/src/modules/pair/models/pair.model.ts b/src/modules/pair/models/pair.model.ts index e9f5dcf63..8a6872d77 100644 --- a/src/modules/pair/models/pair.model.ts +++ b/src/modules/pair/models/pair.model.ts @@ -103,6 +103,11 @@ export class PairModel { @Field() specialFeePercent: number; + @Field({ + description: 'Percentage of special fees that go to the fees collector', + }) + feesCollectorCutPercentage: number; + @Field(() => [String]) trustedSwapPairs: string[]; diff --git a/src/modules/pair/pair.resolver.ts b/src/modules/pair/pair.resolver.ts index d81231885..f14b2b2ad 100644 --- a/src/modules/pair/pair.resolver.ts +++ b/src/modules/pair/pair.resolver.ts @@ -26,6 +26,7 @@ import { PairAbiService } from './services/pair.abi.service'; import { PairComputeService } from './services/pair.compute.service'; import { JwtOrNativeAdminGuard } from '../auth/jwt.or.native.admin.guard'; import { FeesCollectorModel } from '../fees-collector/models/fees-collector.model'; +import { constantsConfig } from 'src/config'; @Resolver(() => PairModel) export class PairResolver { @@ -137,6 +138,16 @@ export class PairResolver { return this.pairAbi.specialFeePercent(parent.address); } + @ResolveField() + async feesCollectorCutPercentage( + @Parent() parent: PairModel, + ): Promise { + const fees = await this.pairAbi.feesCollectorCutPercentage( + parent.address, + ); + return fees / constantsConfig.SWAP_FEE_PERCENT_BASE_POINTS; + } + @ResolveField() async type(@Parent() parent: PairModel): Promise { return this.pairCompute.type(parent.address); diff --git a/src/modules/pair/services/pair.abi.service.ts b/src/modules/pair/services/pair.abi.service.ts index 68fa5bd06..161ca934b 100644 --- a/src/modules/pair/services/pair.abi.service.ts +++ b/src/modules/pair/services/pair.abi.service.ts @@ -729,4 +729,30 @@ export class PairAbiService return new Address(response.firstValue.valueOf().toString()).bech32(); } + + @ErrorLoggerAsync({ + className: PairAbiService.name, + logArgs: true, + }) + @GetOrSetCache({ + baseKey: 'pair', + remoteTtl: CacheTtlInfo.ContractState.remoteTtl, + localTtl: CacheTtlInfo.ContractState.localTtl, + }) + async feesCollectorCutPercentage(pairAddress: string): Promise { + return await this.getFeesCollectorCutPercentageRaw(pairAddress); + } + + async getFeesCollectorCutPercentageRaw(address: string): Promise { + const contract = await this.mxProxy.getPairSmartContract(address); + const interaction: Interaction = + contract.methods.getFeesCollectorCutPercentage([]); + const response = await this.getGenericData(interaction); + + if (response.returnCode.equals(ReturnCode.UserError)) { + return undefined; + } + + return response.firstValue.valueOf().toNumber(); + } } From 377c989c68dc3592231eff5dfa56a9d347b56daf Mon Sep 17 00:00:00 2001 From: Claudiu Lataretu Date: Fri, 21 Jul 2023 17:48:25 +0300 Subject: [PATCH 3/3] MEX-333: add pair fees collector address and cut percentage to cache warmer - removed unused setter methods from pair setter service Signed-off-by: Claudiu Lataretu --- .../pair/services/pair.setter.service.ts | 33 ++++--- .../crons/pair.cache.warmer.service.ts | 92 +++++++++++-------- 2 files changed, 74 insertions(+), 51 deletions(-) diff --git a/src/modules/pair/services/pair.setter.service.ts b/src/modules/pair/services/pair.setter.service.ts index bfba12074..486cb89de 100644 --- a/src/modules/pair/services/pair.setter.service.ts +++ b/src/modules/pair/services/pair.setter.service.ts @@ -321,17 +321,6 @@ export class PairSetterService extends GenericSetterService { ); } - async setExternSwapGasLimit( - pairAddress: string, - value: string, - ): Promise { - return await this.setData( - this.getCacheKey('externSwapGasLimit', pairAddress), - value, - oneHour(), - ); - } - async setWhitelistedAddresses( pairAddress: string, value: string[], @@ -351,11 +340,27 @@ export class PairSetterService extends GenericSetterService { ); } - async setTransferExecGasLimit(pairAddress: string, value: string) { + async setFeesCollectorAddress( + pairAddress: string, + value: string, + ): Promise { return await this.setData( - this.getCacheKey('transferExecGasLimit', pairAddress), + this.getCacheKey('feesCollectorAddress', pairAddress), value, - oneHour(), + CacheTtlInfo.ContractState.remoteTtl, + CacheTtlInfo.ContractState.localTtl, + ); + } + + async setFeesCollectorCutPercentage( + pairAddress: string, + value: number, + ): Promise { + return await this.setData( + this.getCacheKey('feesCollectorCutPercentage', pairAddress), + value, + CacheTtlInfo.ContractState.remoteTtl, + CacheTtlInfo.ContractState.localTtl, ); } } diff --git a/src/services/crons/pair.cache.warmer.service.ts b/src/services/crons/pair.cache.warmer.service.ts index bdc89eaa4..2acf0665b 100644 --- a/src/services/crons/pair.cache.warmer.service.ts +++ b/src/services/crons/pair.cache.warmer.service.ts @@ -159,45 +159,63 @@ export class PairCacheWarmerService { @Cron(CronExpression.EVERY_MINUTE) async cachePairsInfo(): Promise { - const pairsAddresses = await this.routerAbi.pairsAddress(); + Locker.lock('pairsInfo', async () => { + const pairsAddresses = await this.routerAbi.pairsAddress(); - for (const pairAddress of pairsAddresses) { - const [ - feesAPR, - state, - type, - feeState, - totalFeePercent, - specialFeePercent, - ] = await Promise.all([ - this.pairComputeService.computeFeesAPR(pairAddress), - this.pairAbi.getStateRaw(pairAddress), - this.pairComputeService.computeTypeFromTokens(pairAddress), - this.pairAbi.getFeeStateRaw(pairAddress), - this.pairAbi.getTotalFeePercentRaw(pairAddress), - this.pairAbi.getSpecialFeePercentRaw(pairAddress), - ]); + for (const pairAddress of pairsAddresses) { + const [ + feesAPR, + state, + type, + feeState, + totalFeePercent, + specialFeePercent, + feesCollectorAddress, + feesCollectorCutPercentage, + ] = await Promise.all([ + this.pairComputeService.computeFeesAPR(pairAddress), + this.pairAbi.getStateRaw(pairAddress), + this.pairComputeService.computeTypeFromTokens(pairAddress), + this.pairAbi.getFeeStateRaw(pairAddress), + this.pairAbi.getTotalFeePercentRaw(pairAddress), + this.pairAbi.getSpecialFeePercentRaw(pairAddress), + this.pairAbi.getFeesCollectorAddressRaw(pairAddress), + this.pairAbi.getFeesCollectorCutPercentageRaw(pairAddress), + ]); - const cachedKeys = await Promise.all([ - this.pairSetterService.setFeesAPR(pairAddress, feesAPR), - this.pairSetterService.setState(pairAddress, state), - this.pairSetterService.setType(pairAddress, type), - this.pairSetterService.setFeeState(pairAddress, feeState), - this.pairSetterService.setTotalFeePercent( - pairAddress, - new BigNumber(totalFeePercent) - .dividedBy(constantsConfig.SWAP_FEE_PERCENT_BASE_POINTS) - .toNumber(), - ), - this.pairSetterService.setSpecialFeePercent( - pairAddress, - new BigNumber(specialFeePercent) - .dividedBy(constantsConfig.SWAP_FEE_PERCENT_BASE_POINTS) - .toNumber(), - ), - ]); - await this.deleteCacheKeys(cachedKeys); - } + const cachedKeys = await Promise.all([ + this.pairSetterService.setFeesAPR(pairAddress, feesAPR), + this.pairSetterService.setState(pairAddress, state), + this.pairSetterService.setType(pairAddress, type), + this.pairSetterService.setFeeState(pairAddress, feeState), + this.pairSetterService.setTotalFeePercent( + pairAddress, + new BigNumber(totalFeePercent) + .dividedBy( + constantsConfig.SWAP_FEE_PERCENT_BASE_POINTS, + ) + .toNumber(), + ), + this.pairSetterService.setSpecialFeePercent( + pairAddress, + new BigNumber(specialFeePercent) + .dividedBy( + constantsConfig.SWAP_FEE_PERCENT_BASE_POINTS, + ) + .toNumber(), + ), + this.pairSetterService.setFeesCollectorAddress( + pairAddress, + feesCollectorAddress, + ), + this.pairSetterService.setFeesCollectorCutPercentage( + pairAddress, + feesCollectorCutPercentage, + ), + ]); + await this.deleteCacheKeys(cachedKeys); + } + }); } @Cron('*/12 * * * * *') // Update prices and reserves every 12 seconds