Skip to content

Commit

Permalink
Merge pull request #1112 from multiversx/MEX-333-pair-fees-collector-…
Browse files Browse the repository at this point in the history
…address

[MEX-333] pair fees collector
  • Loading branch information
claudiulataretu authored Jul 25, 2023
2 parents 4600abe + 377c989 commit f805fe3
Show file tree
Hide file tree
Showing 5 changed files with 166 additions and 51 deletions.
12 changes: 12 additions & 0 deletions src/modules/pair/models/pair.model.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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 {}
Expand Down Expand Up @@ -102,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[];

Expand All @@ -126,6 +132,12 @@ export class PairModel {
@Field(() => [FeeDestination])
feeDestinations: FeeDestination[];

@Field(() => FeesCollectorModel, {
nullable: true,
description: 'Fees collector set for this pair',
})
feesCollector: FeesCollectorModel;

constructor(init?: Partial<PairModel>) {
Object.assign(this, init);
}
Expand Down
27 changes: 27 additions & 0 deletions src/modules/pair/pair.resolver.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@ 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';
import { constantsConfig } from 'src/config';

@Resolver(() => PairModel)
export class PairResolver {
Expand Down Expand Up @@ -136,6 +138,16 @@ export class PairResolver {
return this.pairAbi.specialFeePercent(parent.address);
}

@ResolveField()
async feesCollectorCutPercentage(
@Parent() parent: PairModel,
): Promise<number> {
const fees = await this.pairAbi.feesCollectorCutPercentage(
parent.address,
);
return fees / constantsConfig.SWAP_FEE_PERCENT_BASE_POINTS;
}

@ResolveField()
async type(@Parent() parent: PairModel): Promise<string> {
return this.pairCompute.type(parent.address);
Expand Down Expand Up @@ -182,6 +194,21 @@ export class PairResolver {
return this.pairAbi.feeDestinations(parent.address);
}

@ResolveField()
async feesCollector(
@Parent() parent: PairModel,
): Promise<FeesCollectorModel> {
const feesCollectorAddress = await this.pairAbi.feesCollectorAddress(
parent.address,
);

return feesCollectorAddress
? new FeesCollectorModel({
address: feesCollectorAddress,
})
: undefined;
}

@Query(() => String)
async getAmountOut(
@Args('pairAddress') pairAddress: string,
Expand Down
53 changes: 53 additions & 0 deletions src/modules/pair/services/pair.abi.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import {
EnumValue,
Field,
ResultsParser,
ReturnCode,
Struct,
TokenIdentifierValue,
U64Value,
Expand Down Expand Up @@ -702,4 +703,56 @@ 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<string> {
return await this.getFeesCollectorAddressRaw(pairAddress);
}

async getFeesCollectorAddressRaw(address: string): Promise<string> {
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();
}

@ErrorLoggerAsync({
className: PairAbiService.name,
logArgs: true,
})
@GetOrSetCache({
baseKey: 'pair',
remoteTtl: CacheTtlInfo.ContractState.remoteTtl,
localTtl: CacheTtlInfo.ContractState.localTtl,
})
async feesCollectorCutPercentage(pairAddress: string): Promise<number> {
return await this.getFeesCollectorCutPercentageRaw(pairAddress);
}

async getFeesCollectorCutPercentageRaw(address: string): Promise<number> {
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();
}
}
33 changes: 19 additions & 14 deletions src/modules/pair/services/pair.setter.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -321,17 +321,6 @@ export class PairSetterService extends GenericSetterService {
);
}

async setExternSwapGasLimit(
pairAddress: string,
value: string,
): Promise<string> {
return await this.setData(
this.getCacheKey('externSwapGasLimit', pairAddress),
value,
oneHour(),
);
}

async setWhitelistedAddresses(
pairAddress: string,
value: string[],
Expand All @@ -351,11 +340,27 @@ export class PairSetterService extends GenericSetterService {
);
}

async setTransferExecGasLimit(pairAddress: string, value: string) {
async setFeesCollectorAddress(
pairAddress: string,
value: string,
): Promise<string> {
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<string> {
return await this.setData(
this.getCacheKey('feesCollectorCutPercentage', pairAddress),
value,
CacheTtlInfo.ContractState.remoteTtl,
CacheTtlInfo.ContractState.localTtl,
);
}
}
92 changes: 55 additions & 37 deletions src/services/crons/pair.cache.warmer.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -159,45 +159,63 @@ export class PairCacheWarmerService {

@Cron(CronExpression.EVERY_MINUTE)
async cachePairsInfo(): Promise<void> {
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
Expand Down

0 comments on commit f805fe3

Please sign in to comment.