Skip to content

Commit

Permalink
feat(deployment): implement deployment top up dry run
Browse files Browse the repository at this point in the history
to ease testing in deployed env

refs #395
  • Loading branch information
ygrishajev committed Nov 11, 2024
1 parent 858d6d5 commit 5e93c58
Show file tree
Hide file tree
Showing 7 changed files with 40 additions and 25 deletions.
5 changes: 2 additions & 3 deletions apps/api/src/console.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ import { container } from "tsyringe";
import { WalletController } from "@src/billing/controllers/wallet/wallet.controller";
import { chainDb } from "@src/db/dbConnection";
import { TopUpDeploymentsController } from "@src/deployment/controllers/deployment/deployment.controller";
import { TopUpManagedDeploymentsService } from "@src/deployment/services/top-up-managed-deployments/top-up-managed-deployments.service";

const program = new Command();

Expand All @@ -29,11 +28,11 @@ program

program
.command("top-up-deployments")
.option("-d, --dry-run", "Dry run the top up deployments", false)
.description("Refill deployments with auto top up enabled")
.action(async (options, command) => {
await executeCliHandler(command.name(), async () => {
await container.resolve(TopUpManagedDeploymentsService).topUpDeployments();
await container.resolve(TopUpDeploymentsController).topUpDeployments();
await container.resolve(TopUpDeploymentsController).topUpDeployments({ dryRun: options.dryRun });
});
});

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,20 @@ import { singleton } from "tsyringe";

import { StaleManagedDeploymentsCleanerService } from "@src/deployment/services/stale-managed-deployments-cleaner/stale-managed-deployments-cleaner.service";
import { TopUpCustodialDeploymentsService } from "@src/deployment/services/top-up-custodial-deployments/top-up-custodial-deployments.service";
import { TopUpManagedDeploymentsService } from "@src/deployment/services/top-up-managed-deployments/top-up-managed-deployments.service";
import { TopUpDeploymentsOptions } from "@src/deployment/types/deployments-refiller";

@singleton()
export class TopUpDeploymentsController {
constructor(
private readonly topUpDeploymentsService: TopUpCustodialDeploymentsService,
private readonly topUpManagedDeploymentsService: TopUpManagedDeploymentsService,
private readonly staleDeploymentsCleanerService: StaleManagedDeploymentsCleanerService
) {}

async topUpDeployments() {
await this.topUpDeploymentsService.topUpDeployments();
async topUpDeployments(options: TopUpDeploymentsOptions) {
await this.topUpDeploymentsService.topUpDeployments(options);
await this.topUpManagedDeploymentsService.topUpDeployments(options);
}

async cleanUpStaleDeployment() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -154,7 +154,7 @@ describe(TopUpCustodialDeploymentsService.name, () => {
jest.spyOn(drainingDeploymentService, "calculateTopUpAmount").mockImplementation(async () => faker.number.int({ min: 3500000, max: 4000000 }));

it("should top up draining deployment given owners have sufficient grants and balances", async () => {
await topUpDeploymentsService.topUpDeployments();
await topUpDeploymentsService.topUpDeployments({ dryRun: false });

expect(uaktMasterSigningClientService.executeTx).toHaveBeenCalledTimes(3);
expect(usdtMasterSigningClientService.executeTx).toHaveBeenCalledTimes(2);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { ExecDepositDeploymentMsgOptions, MasterSigningClientService, RpcMessage
import { ErrorService } from "@src/core/services/error/error.service";
import { DrainingDeploymentService } from "@src/deployment/services/draining-deployment/draining-deployment.service";
import { TopUpToolsService } from "@src/deployment/services/top-up-tools/top-up-tools.service";
import { DeploymentsRefiller, TopUpDeploymentsOptions } from "@src/deployment/types/deployments-refiller";

interface Balances {
denom: string;
Expand All @@ -15,7 +16,7 @@ interface Balances {
}

@singleton()
export class TopUpCustodialDeploymentsService {
export class TopUpCustodialDeploymentsService implements DeploymentsRefiller {
private readonly CONCURRENCY = 10;

private readonly MIN_FEES_AVAILABLE = 5000;
Expand All @@ -31,21 +32,21 @@ export class TopUpCustodialDeploymentsService {
private readonly errorService: ErrorService
) {}

async topUpDeployments() {
async topUpDeployments(options: TopUpDeploymentsOptions) {
const topUpAllCustodialDeployments = this.topUpToolsService.pairs.map(async ({ wallet, client }) => {
const address = await wallet.getFirstAddress();
await this.allowanceHttpService.paginateDeploymentGrants({ grantee: address, limit: this.CONCURRENCY }, async grants => {
await Promise.all(
grants.map(async grant => {
await this.errorService.execWithErrorHandler({ grant, event: "TOP_UP_ERROR" }, () => this.topUpForGrant(grant, client));
await this.errorService.execWithErrorHandler({ grant, event: "TOP_UP_ERROR" }, () => this.topUpForGrant(grant, client, options));
})
);
});
});
await Promise.all(topUpAllCustodialDeployments);
}

private async topUpForGrant(grant: DeploymentAllowance, client: MasterSigningClientService) {
private async topUpForGrant(grant: DeploymentAllowance, client: MasterSigningClientService, options: TopUpDeploymentsOptions) {
const owner = grant.granter;
const { grantee } = grant;

Expand All @@ -72,7 +73,8 @@ export class TopUpCustodialDeploymentsService {
owner,
grantee
},
client
client,
options
);
}
}
Expand Down Expand Up @@ -104,12 +106,13 @@ export class TopUpCustodialDeploymentsService {
return balances.deploymentLimit > amount && balances.feesLimit > this.MIN_FEES_AVAILABLE && balances.balance > amount + this.MIN_FEES_AVAILABLE;
}

async topUpDeployment({ grantee, ...messageInput }: ExecDepositDeploymentMsgOptions, client: MasterSigningClientService) {
async topUpDeployment({ grantee, ...messageInput }: ExecDepositDeploymentMsgOptions, client: MasterSigningClientService, options: TopUpDeploymentsOptions) {
const message = this.rpcClientService.getExecDepositDeploymentMsg({ grantee, ...messageInput });
this.logger.info({ event: "TOP_UP_DEPLOYMENT", params: { ...messageInput, masterWallet: grantee } });
this.logger.info({ event: "TOP_UP_DEPLOYMENT", params: { ...messageInput, masterWallet: grantee }, dryRun: options.dryRun });

await client.executeTx([message]);

this.logger.info({ event: "TOP_UP_DEPLOYMENT_SUCCESS" });
if (!options.dryRun) {
await client.executeTx([message]);
this.logger.info({ event: "TOP_UP_DEPLOYMENT_SUCCESS" });
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ describe(TopUpManagedDeploymentsService.name, () => {
});

it("should top up draining deployment given owners have sufficient balances", async () => {
await topUpDeploymentsService.topUpDeployments();
await topUpDeploymentsService.topUpDeployments({ dryRun: false });

let count = 0;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,10 @@ import { BalancesService } from "@src/billing/services/balances/balances.service
import { TxSignerService } from "@src/billing/services/tx-signer/tx-signer.service";
import { ErrorService } from "@src/core/services/error/error.service";
import { DrainingDeploymentService } from "@src/deployment/services/draining-deployment/draining-deployment.service";
import { DeploymentsRefiller, TopUpDeploymentsOptions } from "@src/deployment/types/deployments-refiller";

@singleton()
export class TopUpManagedDeploymentsService {
export class TopUpManagedDeploymentsService implements DeploymentsRefiller {
private readonly CONCURRENCY = 10;

private readonly logger = new LoggerService({ context: TopUpManagedDeploymentsService.name });
Expand All @@ -27,17 +28,17 @@ export class TopUpManagedDeploymentsService {
private readonly errorService: ErrorService
) {}

async topUpDeployments() {
async topUpDeployments(options: TopUpDeploymentsOptions) {
await this.userWalletRepository.paginate({ limit: this.CONCURRENCY }, async wallets => {
await Promise.all(
wallets.map(async wallet => {
await this.errorService.execWithErrorHandler({ wallet, event: "TOP_UP_ERROR" }, () => this.topUpForWallet(wallet));
await this.errorService.execWithErrorHandler({ wallet, event: "TOP_UP_ERROR" }, () => this.topUpForWallet(wallet, options));
})
);
});
}

private async topUpForWallet(wallet: UserWalletOutput) {
private async topUpForWallet(wallet: UserWalletOutput, options: TopUpDeploymentsOptions) {
const owner = wallet.address;
const denom = this.billingConfig.DEPLOYMENT_GRANT_DENOM;
const drainingDeployments = await this.drainingDeploymentService.findDeployments(owner, denom);
Expand All @@ -55,11 +56,12 @@ export class TopUpManagedDeploymentsService {
balance -= amount;
const messageInput = { dseq: deployment.dseq, amount, denom, owner, depositor };
const message = this.rpcClientService.getDepositDeploymentMsg(messageInput);
this.logger.info({ event: "TOP_UP_DEPLOYMENT", params: messageInput });
this.logger.info({ event: "TOP_UP_DEPLOYMENT", params: messageInput, dryRun: options.dryRun });

await signer.signAndBroadcast([message]);

this.logger.info({ event: "TOP_UP_SUCCESS" });
if (!options.dryRun) {
await signer.signAndBroadcast([message]);
this.logger.info({ event: "TOP_UP_SUCCESS" });
}
}
}
}
7 changes: 7 additions & 0 deletions apps/api/src/deployment/types/deployments-refiller.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
export interface TopUpDeploymentsOptions {
dryRun: boolean;
}

export interface DeploymentsRefiller {
topUpDeployments(options: TopUpDeploymentsOptions): Promise<void>;
}

0 comments on commit 5e93c58

Please sign in to comment.