diff --git a/apps/api/mvm.lock b/apps/api/mvm.lock index eeba268dd..53019b90e 100644 --- a/apps/api/mvm.lock +++ b/apps/api/mvm.lock @@ -2,7 +2,7 @@ "dependencies": { "@akashnetwork/database": "1.0.0", "@akashnetwork/env-loader": "1.0.1", - "@akashnetwork/http-sdk": "1.0.8", + "@akashnetwork/http-sdk": "1.1.0", "@akashnetwork/logging": "2.0.2" } } diff --git a/apps/api/src/billing/services/balances/balances.service.ts b/apps/api/src/billing/services/balances/balances.service.ts index d795dad49..7199cf52c 100644 --- a/apps/api/src/billing/services/balances/balances.service.ts +++ b/apps/api/src/billing/services/balances/balances.service.ts @@ -1,4 +1,4 @@ -import { AllowanceHttpService } from "@akashnetwork/http-sdk"; +import { AuthzHttpService } from "@akashnetwork/http-sdk"; import { singleton } from "tsyringe"; import { BillingConfig, InjectBillingConfig } from "@src/billing/providers"; @@ -12,7 +12,7 @@ export class BalancesService { @InjectBillingConfig() private readonly config: BillingConfig, private readonly userWalletRepository: UserWalletRepository, @InjectWallet("MANAGED") private readonly masterWallet: Wallet, - private readonly allowanceHttpService: AllowanceHttpService + private readonly authzHttpService: AuthzHttpService ) {} async refreshUserWalletLimits(userWallet: UserWalletOutput, options?: { endTrial: boolean }): Promise { @@ -45,39 +45,29 @@ export class BalancesService { } async getFreshLimits(userWallet: UserWalletOutput): Promise<{ fee: number; deployment: number }> { - const [fee, deployment] = await Promise.all([this.retrieveAndCalcFeeLimit(userWallet), this.retrieveAndCalcDeploymentLimit(userWallet)]); + const [fee, deployment] = await Promise.all([this.retrieveAndCalcFeeLimit(userWallet), this.retrieveDeploymentLimit(userWallet)]); return { fee, deployment }; } private async retrieveAndCalcFeeLimit(userWallet: UserWalletOutput): Promise { - const feeAllowance = await this.allowanceHttpService.getFeeAllowancesForGrantee(userWallet.address); const masterWalletAddress = await this.masterWallet.getFirstAddress(); + const feeAllowance = await this.authzHttpService.getFeeAllowanceForGranterAndGrantee(masterWalletAddress, userWallet.address); - return feeAllowance.reduce((acc, allowance) => { - if (allowance.granter !== masterWalletAddress) { - return acc; - } - - return allowance.allowance.spend_limit.reduce((acc, { denom, amount }) => { - if (denom !== "uakt") { - return acc; - } + if (!feeAllowance) { + return 0; + } - return acc + parseInt(amount); - }, 0); - }, 0); + return feeAllowance.allowance.spend_limit.reduce((acc, { denom, amount }) => (denom === "uakt" ? acc + parseInt(amount) : acc), 0); } - async retrieveAndCalcDeploymentLimit(userWallet: Pick): Promise { - const deploymentAllowance = await this.allowanceHttpService.getDeploymentAllowancesForGrantee(userWallet.address); + async retrieveDeploymentLimit(userWallet: Pick): Promise { const masterWalletAddress = await this.masterWallet.getFirstAddress(); + const depositDeploymentGrant = await this.authzHttpService.getDepositDeploymentGrantsForGranterAndGrantee(masterWalletAddress, userWallet.address); - return deploymentAllowance.reduce((acc, allowance) => { - if (allowance.granter !== masterWalletAddress || allowance.authorization.spend_limit.denom !== this.config.DEPLOYMENT_GRANT_DENOM) { - return acc; - } + if (!depositDeploymentGrant || depositDeploymentGrant.authorization.spend_limit.denom !== this.config.DEPLOYMENT_GRANT_DENOM) { + return 0; + } - return acc + parseInt(allowance.authorization.spend_limit.amount); - }, 0); + return parseInt(depositDeploymentGrant.authorization.spend_limit.amount); } } diff --git a/apps/api/src/billing/services/managed-user-wallet/managed-user-wallet.service.ts b/apps/api/src/billing/services/managed-user-wallet/managed-user-wallet.service.ts index d349e9e96..e8014ab62 100644 --- a/apps/api/src/billing/services/managed-user-wallet/managed-user-wallet.service.ts +++ b/apps/api/src/billing/services/managed-user-wallet/managed-user-wallet.service.ts @@ -1,4 +1,4 @@ -import { AllowanceHttpService } from "@akashnetwork/http-sdk"; +import { AuthzHttpService } from "@akashnetwork/http-sdk"; import { LoggerService } from "@akashnetwork/logging"; import { stringToPath } from "@cosmjs/crypto"; import { DirectSecp256k1HdWallet, EncodeObject } from "@cosmjs/proto-signing"; @@ -38,7 +38,7 @@ export class ManagedUserWalletService { @InjectWallet("MANAGED") private readonly masterWallet: Wallet, private readonly managedSignerService: ManagedSignerService, private readonly rpcMessageService: RpcMessageService, - private readonly allowanceHttpService: AllowanceHttpService + private readonly authzHttpService: AuthzHttpService ) {} async createAndAuthorizeTrialSpending({ addressIndex }: { addressIndex: number }) { @@ -94,8 +94,9 @@ export class ManagedUserWalletService { private async authorizeFeeSpending(options: Omit) { const messages: EncodeObject[] = []; + const hasValidFeeAllowance = await this.authzHttpService.hasValidFeeAllowance(options.granter, options.grantee); - if (await this.allowanceHttpService.hasFeeAllowance(options.granter, options.grantee)) { + if (hasValidFeeAllowance) { messages.push(this.rpcMessageService.getRevokeAllowanceMsg(options)); } @@ -118,12 +119,12 @@ export class ManagedUserWalletService { deploymentGrant: false }; - if (await this.allowanceHttpService.hasFeeAllowance(params.granter, params.grantee)) { + if (await this.authzHttpService.hasValidFeeAllowance(params.granter, params.grantee)) { revokeSummary.feeAllowance = true; messages.push(this.rpcMessageService.getRevokeAllowanceMsg(params)); } - if (await this.allowanceHttpService.hasDeploymentGrant(params.granter, params.grantee)) { + if (await this.authzHttpService.hasValidDepositDeploymentGrant(params.granter, params.grantee)) { revokeSummary.deploymentGrant = true; messages.push(this.rpcMessageService.getRevokeDepositDeploymentGrantMsg(params)); } diff --git a/apps/api/src/billing/services/refill/refill.service.ts b/apps/api/src/billing/services/refill/refill.service.ts index fadc82993..9ac5451e1 100644 --- a/apps/api/src/billing/services/refill/refill.service.ts +++ b/apps/api/src/billing/services/refill/refill.service.ts @@ -55,7 +55,7 @@ export class RefillService { let currentLimit: number = 0; if (userWallet) { - currentLimit = await this.balancesService.retrieveAndCalcDeploymentLimit(userWallet); + currentLimit = await this.balancesService.retrieveDeploymentLimit(userWallet); } else { userWallet = await this.walletInitializerService.initialize(userId); } diff --git a/apps/api/src/core/providers/http-sdk.provider.ts b/apps/api/src/core/providers/http-sdk.provider.ts index 535714365..d8629aef5 100644 --- a/apps/api/src/core/providers/http-sdk.provider.ts +++ b/apps/api/src/core/providers/http-sdk.provider.ts @@ -1,8 +1,8 @@ -import { AllowanceHttpService, BalanceHttpService, BlockHttpService } from "@akashnetwork/http-sdk"; +import { AuthzHttpService, BalanceHttpService, BlockHttpService } from "@akashnetwork/http-sdk"; import { container } from "tsyringe"; import { apiNodeUrl } from "@src/utils/constants"; -const SERVICES = [BalanceHttpService, AllowanceHttpService, BlockHttpService]; +const SERVICES = [BalanceHttpService, AuthzHttpService, BlockHttpService]; SERVICES.forEach(Service => container.register(Service, { useValue: new Service({ baseURL: apiNodeUrl }) })); diff --git a/apps/api/src/deployment/services/top-up-custodial-deployments/top-up-custodial-deployments.service.spec.ts b/apps/api/src/deployment/services/top-up-custodial-deployments/top-up-custodial-deployments.service.spec.ts index 4dc858489..b8ebb32d4 100644 --- a/apps/api/src/deployment/services/top-up-custodial-deployments/top-up-custodial-deployments.service.spec.ts +++ b/apps/api/src/deployment/services/top-up-custodial-deployments/top-up-custodial-deployments.service.spec.ts @@ -1,6 +1,6 @@ import "@test/mocks/logger-service.mock"; -import { AllowanceHttpService, BalanceHttpService, Denom } from "@akashnetwork/http-sdk"; +import { AuthzHttpService, BalanceHttpService, Denom } from "@akashnetwork/http-sdk"; import { MsgExec } from "cosmjs-types/cosmos/authz/v1beta1/tx"; import { secondsInWeek } from "date-fns/constants"; import { describe } from "node:test"; @@ -42,7 +42,7 @@ describe(TopUpCustodialDeploymentsService.name, () => { }); }; - const allowanceHttpService = new AllowanceHttpService(); + const authzHttpService = new AuthzHttpService(); const balanceHttpService = new BalanceHttpService(); const blockHttpService = stub({ getCurrentHeight: jest.fn() }); const uaktMasterWallet = mockManagedWallet(UAKT_TOP_UP_MASTER_WALLET_ADDRESS); @@ -58,7 +58,7 @@ describe(TopUpCustodialDeploymentsService.name, () => { const topUpDeploymentsService = new TopUpCustodialDeploymentsService( topUpToolsService, - allowanceHttpService, + authzHttpService, balanceHttpService, drainingDeploymentService, new RpcMessageService(), @@ -177,10 +177,10 @@ describe(TopUpCustodialDeploymentsService.name, () => { }) ]; - jest.spyOn(allowanceHttpService, "paginateDeploymentGrants").mockImplementation(async (params, cb) => { + jest.spyOn(authzHttpService, "paginateDepositDeploymentGrants").mockImplementation(async (params, cb) => { return await cb(data.filter(({ grant }) => "grantee" in params && grant.grantee === params.grantee).map(({ grant }) => grant)); }); - jest.spyOn(allowanceHttpService, "getFeeAllowanceForGranterAndGrantee").mockImplementation(async (granter: string, grantee: string) => { + jest.spyOn(authzHttpService, "getFeeAllowanceForGranterAndGrantee").mockImplementation(async (granter: string, grantee: string) => { return data.find(({ grant }) => grant.granter === granter && grant.grantee === grantee)?.feeAllowance; }); jest.spyOn(balanceHttpService, "getBalance").mockImplementation(async (address: string, denom: Denom) => { @@ -271,7 +271,6 @@ describe(TopUpCustodialDeploymentsService.name, () => { ], { fee: { granter: owner } } ); - console.log("DEBUG res", res); } catch (e) { console.log("DEBUG e", e); diff --git a/apps/api/src/deployment/services/top-up-custodial-deployments/top-up-custodial-deployments.service.ts b/apps/api/src/deployment/services/top-up-custodial-deployments/top-up-custodial-deployments.service.ts index 9bbee3128..db0d03992 100644 --- a/apps/api/src/deployment/services/top-up-custodial-deployments/top-up-custodial-deployments.service.ts +++ b/apps/api/src/deployment/services/top-up-custodial-deployments/top-up-custodial-deployments.service.ts @@ -1,4 +1,4 @@ -import { AllowanceHttpService, BalanceHttpService, DeploymentAllowance } from "@akashnetwork/http-sdk"; +import { AuthzHttpService, BalanceHttpService, DepositDeploymentGrant } from "@akashnetwork/http-sdk"; import { LoggerService } from "@akashnetwork/logging"; import { singleton } from "tsyringe"; @@ -36,7 +36,7 @@ export class TopUpCustodialDeploymentsService implements DeploymentsRefiller { constructor( private readonly topUpToolsService: TopUpToolsService, - private readonly allowanceHttpService: AllowanceHttpService, + private readonly authzHttpService: AuthzHttpService, private readonly balanceHttpService: BalanceHttpService, private readonly drainingDeploymentService: DrainingDeploymentService, private readonly rpcClientService: RpcMessageService, @@ -50,7 +50,7 @@ export class TopUpCustodialDeploymentsService implements DeploymentsRefiller { 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 this.authzHttpService.paginateDepositDeploymentGrants({ grantee: address, limit: this.CONCURRENCY }, async grants => { await Promise.all( grants.map(async grant => { await this.errorService.execWithErrorHandler( @@ -69,7 +69,7 @@ export class TopUpCustodialDeploymentsService implements DeploymentsRefiller { } private async topUpForGrant( - grant: DeploymentAllowance, + grant: DepositDeploymentGrant, client: BatchSigningClientService, options: TopUpDeploymentsOptions, summary: TopUpSummarizer @@ -120,7 +120,7 @@ export class TopUpCustodialDeploymentsService implements DeploymentsRefiller { } } - private async collectWalletBalances(grant: DeploymentAllowance): Promise { + private async collectWalletBalances(grant: DepositDeploymentGrant): Promise { const denom = grant.authorization.spend_limit.denom; const deploymentLimit = parseFloat(grant.authorization.spend_limit.amount); @@ -140,7 +140,7 @@ export class TopUpCustodialDeploymentsService implements DeploymentsRefiller { } private async retrieveFeesLimit(granter: string, grantee: string) { - const feesAllowance = await this.allowanceHttpService.getFeeAllowanceForGranterAndGrantee(granter, grantee); + const feesAllowance = await this.authzHttpService.getFeeAllowanceForGranterAndGrantee(granter, grantee); const feesSpendLimit = feesAllowance.allowance.spend_limit.find(limit => limit.denom === "uakt"); return feesSpendLimit ? parseFloat(feesSpendLimit.amount) : 0; diff --git a/apps/api/src/deployment/services/top-up-managed-deployments/top-up-managed-deployments.service.spec.ts b/apps/api/src/deployment/services/top-up-managed-deployments/top-up-managed-deployments.service.spec.ts index 055d0a35b..0299f5449 100644 --- a/apps/api/src/deployment/services/top-up-managed-deployments/top-up-managed-deployments.service.spec.ts +++ b/apps/api/src/deployment/services/top-up-managed-deployments/top-up-managed-deployments.service.spec.ts @@ -21,7 +21,7 @@ import { stub } from "@test/services/stub"; describe(TopUpManagedDeploymentsService.name, () => { const CURRENT_BLOCK_HEIGHT = 7481457; const MANAGED_MASTER_WALLET_ADDRESS = AkashAddressSeeder.create(); - const balancesService = stub({ retrieveAndCalcDeploymentLimit: jest.fn() }); + const balancesService = stub({ retrieveDeploymentLimit: jest.fn() }); const userWalletRepository = stub({ paginate: jest.fn() }); const blockHttpService = stub({ getCurrentHeight: () => CURRENT_BLOCK_HEIGHT }); const managedSignerService = stub({ executeManagedTx: jest.fn() }); @@ -93,7 +93,7 @@ describe(TopUpManagedDeploymentsService.name, () => { return data.find(({ wallet }) => wallet.address == owner)?.drainingDeployments?.map(({ deployment }) => deployment) || []; }); jest.spyOn(drainingDeploymentService, "calculateTopUpAmount").mockImplementation(async () => faker.number.int({ min: 3500000, max: 4000000 })); - balancesService.retrieveAndCalcDeploymentLimit.mockImplementation(async wallet => { + balancesService.retrieveDeploymentLimit.mockImplementation(async wallet => { return parseInt(data.find(({ wallet: w }) => w.address == wallet.address)?.balance); }); diff --git a/apps/api/src/deployment/services/top-up-managed-deployments/top-up-managed-deployments.service.ts b/apps/api/src/deployment/services/top-up-managed-deployments/top-up-managed-deployments.service.ts index 47c945895..38edceef9 100644 --- a/apps/api/src/deployment/services/top-up-managed-deployments/top-up-managed-deployments.service.ts +++ b/apps/api/src/deployment/services/top-up-managed-deployments/top-up-managed-deployments.service.ts @@ -61,7 +61,7 @@ export class TopUpManagedDeploymentsService implements DeploymentsRefiller { return; } - let balance = await this.balancesService.retrieveAndCalcDeploymentLimit(wallet); + let balance = await this.balancesService.retrieveDeploymentLimit(wallet); let hasTopUp = false; for (const deployment of drainingDeployments) { diff --git a/apps/api/test/functional/stale-anonymous-users-cleanup.spec.ts b/apps/api/test/functional/stale-anonymous-users-cleanup.spec.ts index ce63b2147..278107eb3 100644 --- a/apps/api/test/functional/stale-anonymous-users-cleanup.spec.ts +++ b/apps/api/test/functional/stale-anonymous-users-cleanup.spec.ts @@ -1,4 +1,4 @@ -import { AllowanceHttpService } from "@akashnetwork/http-sdk"; +import { AuthzHttpService } from "@akashnetwork/http-sdk"; import subDays from "date-fns/subDays"; import { container } from "tsyringe"; @@ -19,7 +19,7 @@ describe("Users", () => { const userWalletRepository = container.resolve(UserWalletRepository); const walletService = new WalletTestingService(app); const controller = container.resolve(UserController); - const allowanceHttpService = container.resolve(AllowanceHttpService); + const authzHttpService = container.resolve(AuthzHttpService); const masterWalletService = resolveWallet("MANAGED"); let masterAddress: string; @@ -71,14 +71,14 @@ describe("Users", () => { ); await Promise.all([ - expect(allowanceHttpService.hasFeeAllowance(recent.wallet.address, masterAddress)).resolves.toBeFalsy(), - expect(allowanceHttpService.hasDeploymentGrant(recent.wallet.address, masterAddress)).resolves.toBeFalsy(), + expect(authzHttpService.hasValidFeeAllowance(recent.wallet.address, masterAddress)).resolves.toBeFalsy(), + expect(authzHttpService.hasValidDepositDeploymentGrant(recent.wallet.address, masterAddress)).resolves.toBeFalsy(), - expect(allowanceHttpService.hasFeeAllowance(reactivated.wallet.address, masterAddress)).resolves.toBeFalsy(), - expect(allowanceHttpService.hasDeploymentGrant(reactivated.wallet.address, masterAddress)).resolves.toBeFalsy(), + expect(authzHttpService.hasValidFeeAllowance(reactivated.wallet.address, masterAddress)).resolves.toBeFalsy(), + expect(authzHttpService.hasValidDepositDeploymentGrant(reactivated.wallet.address, masterAddress)).resolves.toBeFalsy(), - expect(allowanceHttpService.hasFeeAllowance(stale.wallet.address, masterAddress)).resolves.toBeFalsy(), - expect(allowanceHttpService.hasDeploymentGrant(stale.wallet.address, masterAddress)).resolves.toBeFalsy() + expect(authzHttpService.hasValidFeeAllowance(stale.wallet.address, masterAddress)).resolves.toBeFalsy(), + expect(authzHttpService.hasValidDepositDeploymentGrant(stale.wallet.address, masterAddress)).resolves.toBeFalsy() ]); }); }); diff --git a/apps/api/test/functional/start-trial.spec.ts b/apps/api/test/functional/start-trial.spec.ts index 2eae5a324..e7b3c0e06 100644 --- a/apps/api/test/functional/start-trial.spec.ts +++ b/apps/api/test/functional/start-trial.spec.ts @@ -1,4 +1,4 @@ -import { AllowanceHttpService } from "@akashnetwork/http-sdk"; +import { AuthzHttpService } from "@akashnetwork/http-sdk"; import { faker } from "@faker-js/faker"; import { eq } from "drizzle-orm"; import { container } from "tsyringe"; @@ -16,7 +16,7 @@ describe("start trial", () => { const config = container.resolve(BILLING_CONFIG); const db = container.resolve(POSTGRES_DB); const userWalletsQuery = db.query.UserWallets; - const allowanceHttpService = container.resolve(AllowanceHttpService); + const authzHttpService = container.resolve(AuthzHttpService); const dbService = container.resolve(DbTestingService); afterEach(async () => { @@ -42,8 +42,8 @@ describe("start trial", () => { const getWalletsResponse = await app.request(`/v1/wallets?userId=${userId}`, { headers }); const userWallet = await userWalletsQuery.findFirst({ where: eq(userWalletsTable.userId, userId) }); const allowances = await Promise.all([ - allowanceHttpService.getDeploymentAllowancesForGrantee(userWallet.address), - allowanceHttpService.getFeeAllowancesForGrantee(userWallet.address) + authzHttpService.getDepositDeploymentGrantsForGrantee(userWallet.address), + authzHttpService.getFeeAllowancesForGrantee(userWallet.address) ]); expect(createWalletResponse.status).toBe(200); diff --git a/apps/api/test/seeders/deployment-grant.seeder.ts b/apps/api/test/seeders/deployment-grant.seeder.ts index f99dd2f15..c1b00b5f3 100644 --- a/apps/api/test/seeders/deployment-grant.seeder.ts +++ b/apps/api/test/seeders/deployment-grant.seeder.ts @@ -1,4 +1,4 @@ -import type { DeploymentAllowance } from "@akashnetwork/http-sdk"; +import type { DepositDeploymentGrant } from "@akashnetwork/http-sdk"; import { faker } from "@faker-js/faker"; import { merge } from "lodash"; import type { PartialDeep } from "type-fest"; @@ -8,7 +8,7 @@ import { AkashAddressSeeder } from "./akash-address.seeder"; import { DenomSeeder } from "@test/seeders/denom.seeder"; export class DeploymentGrantSeeder { - static create(input: PartialDeep = {}): DeploymentAllowance { + static create(input: PartialDeep = {}): DepositDeploymentGrant { return merge( { granter: AkashAddressSeeder.create(), diff --git a/apps/deploy-web/mvm.lock b/apps/deploy-web/mvm.lock index 8b020adc1..37851a727 100644 --- a/apps/deploy-web/mvm.lock +++ b/apps/deploy-web/mvm.lock @@ -1,7 +1,7 @@ { "dependencies": { "@akashnetwork/env-loader": "1.0.1", - "@akashnetwork/http-sdk": "1.0.8", + "@akashnetwork/http-sdk": "1.1.0", "@akashnetwork/logging": "2.0.2", "@akashnetwork/network-store": "1.0.1", "@akashnetwork/ui": "1.0.0" diff --git a/apps/deploy-web/src/hooks/useAllowanceService.tsx b/apps/deploy-web/src/hooks/useAllowanceService.tsx index 6ebf7d593..2486df947 100644 --- a/apps/deploy-web/src/hooks/useAllowanceService.tsx +++ b/apps/deploy-web/src/hooks/useAllowanceService.tsx @@ -1,9 +1,9 @@ import { useMemo } from "react"; -import { AllowanceHttpService } from "@akashnetwork/http-sdk"; +import { AuthzHttpService } from "@akashnetwork/http-sdk"; import { useSettings } from "@src/context/SettingsProvider"; export const useAllowanceService = () => { const { settings } = useSettings(); - return useMemo(() => new AllowanceHttpService({ baseURL: settings.apiEndpoint }), [settings.apiEndpoint]); + return useMemo(() => new AuthzHttpService({ baseURL: settings.apiEndpoint }), [settings.apiEndpoint]); }; diff --git a/apps/deploy-web/src/hooks/useAutoTopUpLimits.tsx b/apps/deploy-web/src/hooks/useAutoTopUpLimits.tsx index 9bfa16d6f..c2bb4fafd 100644 --- a/apps/deploy-web/src/hooks/useAutoTopUpLimits.tsx +++ b/apps/deploy-web/src/hooks/useAutoTopUpLimits.tsx @@ -1,5 +1,5 @@ import { useCallback, useMemo } from "react"; -import { ExactDeploymentAllowance, FeeAllowance } from "@akashnetwork/http-sdk"; +import { ExactDepositDeploymentGrant, FeeAllowance } from "@akashnetwork/http-sdk"; import { isFuture } from "date-fns"; import invokeMap from "lodash/invokeMap"; @@ -62,7 +62,7 @@ export const useAutoTopUpLimits = () => { }; }; -function extractDeploymentLimit(deploymentGrant?: ExactDeploymentAllowance) { +function extractDeploymentLimit(deploymentGrant?: ExactDepositDeploymentGrant) { if (!deploymentGrant) { return undefined; } diff --git a/apps/deploy-web/src/queries/useExactDeploymentGrantsQuery.ts b/apps/deploy-web/src/queries/useExactDeploymentGrantsQuery.ts index 4c1dd3225..c875187f4 100644 --- a/apps/deploy-web/src/queries/useExactDeploymentGrantsQuery.ts +++ b/apps/deploy-web/src/queries/useExactDeploymentGrantsQuery.ts @@ -5,7 +5,11 @@ import { QueryKeys } from "@src/queries/queryKeys"; export function useExactDeploymentGrantsQuery(granter: string, grantee: string, { enabled = true } = {}) { const allowanceHttpService = useAllowanceService(); - return useQuery(QueryKeys.getDeploymentGrantsKey(granter, grantee), () => allowanceHttpService.getDeploymentGrantsForGranterAndGrantee(granter, grantee), { - enabled - }); + return useQuery( + QueryKeys.getDeploymentGrantsKey(granter, grantee), + () => allowanceHttpService.getDepositDeploymentGrantsForGranterAndGrantee(granter, grantee), + { + enabled + } + ); } diff --git a/package-lock.json b/package-lock.json index b77413f29..52cf74850 100644 --- a/package-lock.json +++ b/package-lock.json @@ -31,7 +31,7 @@ }, "apps/api": { "name": "@akashnetwork/console-api", - "version": "2.39.0", + "version": "2.41.1", "license": "Apache-2.0", "dependencies": { "@akashnetwork/akash-api": "^1.3.0", @@ -748,7 +748,8 @@ }, "node_modules/@akashnetwork/akash-api": { "version": "1.4.0", - "license": "Apache-2.0", + "resolved": "https://registry.npmjs.org/@akashnetwork/akash-api/-/akash-api-1.4.0.tgz", + "integrity": "sha512-xJTHjkSLHQRk2z1s+pk/fSTXQrJCTyzUzWHn+TvvJapjEsDPT0+AW2YhrmYLOpS0n4s/8GnoGB9swRuzgYYLbg==", "dependencies": { "rxjs": "^7.8.1" }, @@ -39307,6 +39308,7 @@ "license": "Apache-2.0", "dependencies": { "axios": "^1.7.2", + "date-fns": "^4.1.0", "lodash": "^4.17.21" }, "devDependencies": { @@ -39351,6 +39353,15 @@ "xstream": "^11.14.0" } }, + "packages/http-sdk/node_modules/date-fns": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-4.1.0.tgz", + "integrity": "sha512-Ukq0owbQXxa/U3EGtsdVBkR1w7KOQ5gIBqdH2hkvknzZPYvBxb/aa6E8L7tmjFtkwZBu3UXBbjIgPo/Ez4xaNg==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/kossnocorp" + } + }, "packages/logging": { "name": "@akashnetwork/logging", "version": "2.0.2", diff --git a/packages/http-sdk/package.json b/packages/http-sdk/package.json index 2a7d4c725..0bd66b9da 100644 --- a/packages/http-sdk/package.json +++ b/packages/http-sdk/package.json @@ -1,6 +1,6 @@ { "name": "@akashnetwork/http-sdk", - "version": "1.0.8", + "version": "1.1.0", "description": "Package containing http layer for Akash Network", "keywords": [], "license": "Apache-2.0", @@ -13,6 +13,7 @@ }, "dependencies": { "axios": "^1.7.2", + "date-fns": "^4.1.0", "lodash": "^4.17.21" }, "devDependencies": { diff --git a/packages/http-sdk/src/allowance/allowance-http.service.ts b/packages/http-sdk/src/allowance/allowance-http.service.ts deleted file mode 100644 index cd2b7d066..000000000 --- a/packages/http-sdk/src/allowance/allowance-http.service.ts +++ /dev/null @@ -1,123 +0,0 @@ -import { AxiosRequestConfig } from "axios"; - -import { HttpService } from "../http/http.service"; -import type { Denom } from "../types/denom.type"; - -export interface SpendLimit { - denom: Denom; - amount: string; -} - -export interface FeeAllowance { - granter: string; - grantee: string; - allowance: { - "@type": "/cosmos.feegrant.v1beta1.BasicAllowance"; - spend_limit: SpendLimit[]; - expiration: string; - }; -} - -export interface ExactDeploymentAllowance { - authorization: { - "@type": "/akash.deployment.v1beta3.DepositDeploymentAuthorization"; - spend_limit: SpendLimit; - }; - expiration: string; -} - -export interface DeploymentAllowance extends ExactDeploymentAllowance { - granter: string; - grantee: string; -} - -interface FeeAllowanceListResponse { - allowances: FeeAllowance[]; -} - -interface FeeAllowanceResponse { - allowance: FeeAllowance; -} - -interface DeploymentAllowanceResponse { - grants: T[]; - pagination: { - next_key: string | null; - }; -} - -export class AllowanceHttpService extends HttpService { - constructor(config?: Pick) { - super(config); - } - - async getFeeAllowancesForGrantee(address: string) { - const allowances = this.extractData(await this.get(`cosmos/feegrant/v1beta1/allowances/${address}`)); - return allowances.allowances.filter(allowance => allowance.allowance["@type"] === "/cosmos.feegrant.v1beta1.BasicAllowance"); - } - - async getFeeAllowanceForGranterAndGrantee(granter: string, grantee: string) { - try { - const allowances = this.extractData(await this.get(`cosmos/feegrant/v1beta1/allowance/${granter}/${grantee}`)); - return allowances.allowance.allowance["@type"] === "/cosmos.feegrant.v1beta1.BasicAllowance" ? allowances.allowance : undefined; - } catch (error) { - if (error.response.data.message.includes("fee-grant not found")) { - return undefined; - } - - throw error; - } - } - - async getDeploymentAllowancesForGrantee(address: string) { - const allowances = this.extractData(await this.get(`cosmos/authz/v1beta1/grants/grantee/${address}`)); - return allowances.grants.filter(grant => grant.authorization["@type"] === "/akash.deployment.v1beta3.DepositDeploymentAuthorization"); - } - - async getDeploymentGrantsForGranterAndGrantee(granter: string, grantee: string) { - const allowances = this.extractData( - await this.get>("cosmos/authz/v1beta1/grants", { - params: { - grantee: grantee, - granter: granter - } - }) - ); - return allowances.grants.find(grant => grant.authorization["@type"] === "/akash.deployment.v1beta3.DepositDeploymentAuthorization"); - } - - async hasFeeAllowance(granter: string, grantee: string) { - const feeAllowances = await this.getFeeAllowancesForGrantee(grantee); - return feeAllowances.some(allowance => allowance.granter === granter); - } - - async hasDeploymentGrant(granter: string, grantee: string) { - const feeAllowances = await this.getDeploymentAllowancesForGrantee(grantee); - return feeAllowances.some(allowance => allowance.granter === granter); - } - - async paginateDeploymentGrants( - options: ({ granter: string } | { grantee: string }) & { limit: number }, - cb: (page: DeploymentAllowanceResponse["grants"]) => Promise - ) { - let nextPageKey: string | null = null; - const side = "granter" in options ? "granter" : "grantee"; - const address = "granter" in options ? options.granter : options.grantee; - - do { - const response = this.extractData( - await this.get( - `cosmos/authz/v1beta1/grants/${side}/${address}`, - nextPageKey - ? { - params: { "pagination.key": nextPageKey, "pagination.limit": options.limit } - } - : undefined - ) - ); - nextPageKey = response.pagination.next_key; - - await cb(response.grants.filter(grant => grant.authorization["@type"] === "/akash.deployment.v1beta3.DepositDeploymentAuthorization")); - } while (nextPageKey); - } -} diff --git a/packages/http-sdk/src/authz/authz-http.service.ts b/packages/http-sdk/src/authz/authz-http.service.ts new file mode 100644 index 000000000..44527c16f --- /dev/null +++ b/packages/http-sdk/src/authz/authz-http.service.ts @@ -0,0 +1,136 @@ +import { AxiosRequestConfig } from "axios"; +import { isFuture } from "date-fns"; + +import { HttpService } from "../http/http.service"; +import type { Denom } from "../types/denom.type"; + +export interface SpendLimit { + denom: Denom; + amount: string; +} + +export interface FeeAllowance { + granter: string; + grantee: string; + allowance: { + "@type": "/cosmos.feegrant.v1beta1.BasicAllowance"; + spend_limit: SpendLimit[]; + expiration: string; + }; +} + +export interface ExactDepositDeploymentGrant { + authorization: { + "@type": "/akash.deployment.v1beta3.DepositDeploymentAuthorization"; + spend_limit: SpendLimit; + }; + expiration: string; +} + +export interface DepositDeploymentGrant extends ExactDepositDeploymentGrant { + granter: string; + grantee: string; +} + +interface FeeAllowanceListResponse { + allowances: FeeAllowance[]; +} + +interface FeeAllowanceResponse { + allowance: FeeAllowance; +} + +interface DepositDeploymentGrantResponse { + grants: T[]; + pagination: { + next_key: string | null; + }; +} + +export class AuthzHttpService extends HttpService { + private readonly DEPOSIT_DEPLOYMENT_GRANT_TYPE: ExactDepositDeploymentGrant['authorization']['@type'] = "/akash.deployment.v1beta3.DepositDeploymentAuthorization"; + + private readonly FEE_ALLOWANCE_TYPE: FeeAllowance['allowance']['@type'] = "/cosmos.feegrant.v1beta1.BasicAllowance"; + + constructor(config?: Pick) { + super(config); + } + + async getFeeAllowancesForGrantee(address: string) { + const allowances = this.extractData(await this.get(`cosmos/feegrant/v1beta1/allowances/${address}`)); + return allowances.allowances.filter(allowance => this.isValidFeeAllowance(allowance)); + } + + async getFeeAllowanceForGranterAndGrantee(granter: string, grantee: string): Promise { + try { + const response = this.extractData(await this.get(`cosmos/feegrant/v1beta1/allowance/${granter}/${grantee}`)); + return this.isValidFeeAllowance(response.allowance) ? response.allowance : undefined; + } catch (error) { + if (error.response.data.message.includes("fee-grant not found")) { + return undefined; + } + + throw error; + } + } + + async getDepositDeploymentGrantsForGrantee(address: string) { + const response = this.extractData(await this.get(`cosmos/authz/v1beta1/grants/grantee/${address}`)); + return response.grants.filter(grant => this.isValidDepositDeploymentGrant(grant)); + } + + async getDepositDeploymentGrantsForGranterAndGrantee(granter: string, grantee: string): Promise { + const response = this.extractData( + await this.get>("cosmos/authz/v1beta1/grants", { + params: { + grantee: grantee, + granter: granter + } + }) + ); + return response.grants.find(grant => this.isValidDepositDeploymentGrant(grant)); + } + + async hasValidFeeAllowance(granter: string, grantee: string) { + const feeAllowances = await this.getFeeAllowancesForGrantee(grantee); + return feeAllowances.some(allowance => allowance.granter === granter); + } + + async hasValidDepositDeploymentGrant(granter: string, grantee: string) { + const depositDeploymentGrants = await this.getDepositDeploymentGrantsForGrantee(grantee); + return depositDeploymentGrants.some(allowance => allowance.granter === granter); + } + + async paginateDepositDeploymentGrants( + options: ({ granter: string } | { grantee: string }) & { limit: number }, + cb: (page: DepositDeploymentGrantResponse["grants"]) => Promise + ) { + let nextPageKey: string | null = null; + const side = "granter" in options ? "granter" : "grantee"; + const address = "granter" in options ? options.granter : options.grantee; + + do { + const response = this.extractData( + await this.get( + `cosmos/authz/v1beta1/grants/${side}/${address}`, + nextPageKey + ? { + params: { "pagination.key": nextPageKey, "pagination.limit": options.limit } + } + : undefined + ) + ); + nextPageKey = response.pagination.next_key; + + await cb(response.grants.filter(grant => this.isValidDepositDeploymentGrant(grant))); + } while (nextPageKey); + } + + private isValidFeeAllowance({ allowance }: FeeAllowance) { + return allowance["@type"] === this.FEE_ALLOWANCE_TYPE && (!allowance.expiration || isFuture(new Date(allowance.expiration))); + } + + private isValidDepositDeploymentGrant({ authorization, expiration }: ExactDepositDeploymentGrant) { + return authorization["@type"] === this.DEPOSIT_DEPLOYMENT_GRANT_TYPE && (!expiration || isFuture(new Date(expiration))); + } +} diff --git a/packages/http-sdk/src/index.ts b/packages/http-sdk/src/index.ts index 56288ad70..43f275c4a 100644 --- a/packages/http-sdk/src/index.ts +++ b/packages/http-sdk/src/index.ts @@ -1,5 +1,5 @@ export * from "./http/http.service"; -export * from "./allowance/allowance-http.service"; +export * from "./authz/authz-http.service"; export * from "./api-http/api-http.service"; export * from "./tx-http/tx-http.service"; export * from "./managed-wallet-http/managed-wallet-http.service";