Skip to content

Commit

Permalink
fix(billing): use specific endpoint to check managed wallet grants
Browse files Browse the repository at this point in the history
  • Loading branch information
ygrishajev committed Dec 30, 2024
1 parent b473e52 commit d87d79f
Show file tree
Hide file tree
Showing 14 changed files with 87 additions and 104 deletions.
2 changes: 1 addition & 1 deletion apps/api/mvm.lock
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"dependencies": {
"@akashnetwork/database": "1.0.0",
"@akashnetwork/env-loader": "1.0.1",
"@akashnetwork/http-sdk": "1.1.2",
"@akashnetwork/http-sdk": "1.1.3",
"@akashnetwork/logging": "2.0.2"
}
}
2 changes: 1 addition & 1 deletion apps/deploy-web/mvm.lock
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"dependencies": {
"@akashnetwork/env-loader": "1.0.1",
"@akashnetwork/http-sdk": "1.1.1",
"@akashnetwork/http-sdk": "1.1.3",
"@akashnetwork/logging": "2.0.2",
"@akashnetwork/network-store": "1.0.1",
"@akashnetwork/ui": "1.0.0"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { AuthzHttpService } from "@akashnetwork/http-sdk";

import { useSettings } from "@src/context/SettingsProvider";

export const useAllowanceService = () => {
export const useAuthZService = () => {
const { settings } = useSettings();
return useMemo(() => new AuthzHttpService({ baseURL: settings.apiEndpoint }), [settings.apiEndpoint]);
};
57 changes: 27 additions & 30 deletions apps/deploy-web/src/hooks/useWalletBalance.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { useEffect, useState } from "react";
import { useCallback, useEffect, useState } from "react";

import { UAKT_DENOM } from "@src/config/denom.config";
import { useChainParam } from "@src/context/ChainParamProvider";
Expand Down Expand Up @@ -38,6 +38,21 @@ export const useWalletBalance = (): WalletBalanceReturnType => {
const { data: balances, isFetching: isLoadingBalances, refetch } = useBalances(address);
const [walletBalance, setWalletBalance] = useState<WalletBalance | null>(null);

const udenomToUsd = useCallback(
(amount: string, denom: string) => {
let value = 0;

if (denom === UAKT_DENOM) {
value = uaktToAKT(parseFloat(amount), 6) * (price || 0);
} else if (denom === usdcIbcDenom) {
value = udenomToDenom(parseFloat(amount), 6);
}

return value;
},
[price, usdcIbcDenom]
);

useEffect(() => {
if (isLoaded && balances && price) {
const aktUsdValue = uaktToAKT(balances.balanceUAKT, 6) * price;
Expand All @@ -49,44 +64,26 @@ export const useWalletBalance = (): WalletBalanceReturnType => {
udenomToUsd(d.escrowAccount.balance.amount, d.escrowAccount.balance.denom),
0
);
const totalDeploymentGrantsUSD = balances.deploymentGrants.reduce(
(acc, d) => acc + udenomToUsd(d.authorization.spend_limit.amount, d.authorization.spend_limit.denom),
0
);
const totalGrantsUAKT = balances.deploymentGrants
.filter(d => d.authorization.spend_limit.denom === UAKT_DENOM)
.reduce((acc, d) => acc + parseFloat(d.authorization.spend_limit.amount), 0);
const totalGrantsUUSDC = balances.deploymentGrants
.filter(d => d.authorization.spend_limit.denom === usdcIbcDenom)
.reduce((acc, d) => acc + parseFloat(d.authorization.spend_limit.amount), 0);
const { deploymentGrant, deploymentGrantsUAKT, deploymentEscrowUAKT } = balances;
const totalDeploymentGrantsUSD = deploymentGrant
? udenomToUsd(deploymentGrant.authorization.spend_limit.amount, deploymentGrant.authorization.spend_limit.denom)
: 0;

setWalletBalance({
totalUsd: aktUsdValue + totalUsdcValue + totalDeploymentEscrowUSD + totalDeploymentGrantsUSD,
balanceUAKT: balances.balanceUAKT + totalGrantsUAKT,
balanceUUSDC: balances.balanceUUSDC + totalGrantsUUSDC,
totalUAKT: balances.balanceUAKT + balances.deploymentEscrowUAKT + totalGrantsUAKT,
totalUUSDC: balances.balanceUUSDC + balances.deploymentEscrowUUSDC + totalGrantsUUSDC,
balanceUAKT: balances.balanceUAKT + deploymentGrantsUAKT,
balanceUUSDC: balances.balanceUUSDC + deploymentEscrowUAKT,
totalUAKT: balances.balanceUAKT + balances.deploymentEscrowUAKT + deploymentGrantsUAKT,
totalUUSDC: balances.balanceUUSDC + balances.deploymentEscrowUUSDC + deploymentEscrowUAKT,
totalDeploymentEscrowUAKT: balances.deploymentEscrowUAKT,
totalDeploymentEscrowUUSDC: balances.deploymentEscrowUUSDC,
totalDeploymentEscrowUSD: totalDeploymentEscrowUSD,
totalDeploymentGrantsUAKT: totalGrantsUAKT,
totalDeploymentGrantsUUSDC: totalGrantsUUSDC,
totalDeploymentGrantsUAKT: deploymentGrantsUAKT,
totalDeploymentGrantsUUSDC: deploymentEscrowUAKT,
totalDeploymentGrantsUSD: totalDeploymentGrantsUSD
});
}
}, [isLoaded, price, balances, isManaged]);

const udenomToUsd = (amount: string, denom: string) => {
let value = 0;

if (denom === UAKT_DENOM) {
value = uaktToAKT(parseFloat(amount), 6) * (price || 0);
} else if (denom === usdcIbcDenom) {
value = udenomToDenom(parseFloat(amount), 6);
}

return value;
};
}, [isLoaded, price, balances, isManaged, udenomToUsd]);

return {
balance: walletBalance,
Expand Down
39 changes: 15 additions & 24 deletions apps/deploy-web/src/queries/useBalancesQuery.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import { QueryKey, useQuery, UseQueryOptions } from "react-query";
import { AuthzHttpService } from "@akashnetwork/http-sdk";
import axios from "axios";

import { browserEnvConfig } from "@src/config/browser-env.config";
import { UAKT_DENOM } from "@src/config/denom.config";
import { getUsdcDenom } from "@src/hooks/useDenom";
import { Balances } from "@src/types";
Expand All @@ -11,35 +13,25 @@ import { deploymentToDto } from "@src/utils/deploymentDetailUtils";
import { useSettings } from "../context/SettingsProvider";
import { QueryKeys } from "./queryKeys";

// Account balances
async function getBalances(apiEndpoint: string, address?: string): Promise<Balances | undefined> {
if (!address || !apiEndpoint) return undefined;
const usdcIbcDenom = getUsdcDenom();
const authzHttpService = new AuthzHttpService({ baseURL: apiEndpoint });

const balancePromise = axios.get<RestApiBalancesResponseType>(ApiUrlService.balance(apiEndpoint, address));
// const authzBalancePromise = axios.get<RestApiAuthzGrantsResponseType>(ApiUrlService.granteeGrants(apiEndpoint, address));
const activeDeploymentsPromise = loadWithPagination<RpcDeployment[]>(ApiUrlService.deploymentList(apiEndpoint, address, true), "deployments", 1000);
const [balanceResponse, deploymentGrant, activeDeploymentsResponse] = await Promise.all([
axios.get<RestApiBalancesResponseType>(ApiUrlService.balance(apiEndpoint, address)),
authzHttpService.getDepositDeploymentGrantsForGranterAndGrantee(browserEnvConfig.NEXT_PUBLIC_MASTER_WALLET_ADDRESS, address),
loadWithPagination<RpcDeployment[]>(ApiUrlService.deploymentList(apiEndpoint, address, true), "deployments", 1000)
]);

const [balanceResponse, activeDeploymentsResponse] = await Promise.all([balancePromise, activeDeploymentsPromise]);
const deploymentGrantsUAKT = parseFloat(
deploymentGrant?.authorization.spend_limit.denom === UAKT_DENOM ? deploymentGrant.authorization.spend_limit.amount : "0"
);

// Authz Grants
// const deploymentGrants = authzBalanceResponse.data.grants.filter(
// b => b.authorization["@type"] === "/akash.deployment.v1beta3.DepositDeploymentAuthorization"
// );
// const deploymentGrants = authzBalanceResponse.data.grants.filter(
// b => b.authorization["@type"] === "/akash.deployment.v1beta3.DepositDeploymentAuthorization"
// );
// const deploymentGrantsUAKT = parseFloat(
// deploymentGrants.find(b => b.authorization.spend_limit.denom === UAKT_DENOM)?.authorization.spend_limit.amount || "0"
// );
//
// const deploymentGrantsUUSDC = parseFloat(
// deploymentGrants.find(b => b.authorization.spend_limit.denom === usdcIbcDenom)?.authorization.spend_limit.amount || "0"
// );
const deploymentGrantsUAKT = 0;
const deploymentGrantsUUSDC = parseFloat(
deploymentGrant && deploymentGrant.authorization.spend_limit.denom === usdcIbcDenom ? deploymentGrant.authorization.spend_limit.amount : "0"
);

const deploymentGrantsUUSDC = 0;
// Balance
const balanceData = balanceResponse.data;
const balanceUAKT =
balanceData.balances.some(b => b.denom === UAKT_DENOM) || deploymentGrantsUAKT > 0
Expand All @@ -50,7 +42,6 @@ async function getBalances(apiEndpoint: string, address?: string): Promise<Balan
? parseFloat(balanceData.balances.find(b => b.denom === usdcIbcDenom)?.amount || "0")
: 0;

// Deployment balances
const activeDeployments = activeDeploymentsResponse.map(d => deploymentToDto(d));
const aktActiveDeployments = activeDeployments.filter(d => d.denom === UAKT_DENOM);
const usdcActiveDeployments = activeDeployments.filter(d => d.denom === usdcIbcDenom);
Expand All @@ -65,7 +56,7 @@ async function getBalances(apiEndpoint: string, address?: string): Promise<Balan
deploymentGrantsUAKT,
deploymentGrantsUUSDC,
activeDeployments,
deploymentGrants: []
deploymentGrant
};
}

Expand Down
4 changes: 2 additions & 2 deletions apps/deploy-web/src/queries/useExactDeploymentGrantsQuery.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import { useQuery } from "react-query";

import { useAllowanceService } from "@src/hooks/useAllowanceService";
import { useAuthZService } from "@src/hooks/useAuthZService";
import { QueryKeys } from "@src/queries/queryKeys";

export function useExactDeploymentGrantsQuery(granter: string, grantee: string, { enabled = true } = {}) {
const allowanceHttpService = useAllowanceService();
const allowanceHttpService = useAuthZService();
return useQuery(
QueryKeys.getDeploymentGrantsKey(granter, grantee),
() => allowanceHttpService.getDepositDeploymentGrantsForGranterAndGrantee(granter, grantee),
Expand Down
4 changes: 2 additions & 2 deletions apps/deploy-web/src/queries/useExactFeeAllowanceQuery.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import { useQuery } from "react-query";

import { useAllowanceService } from "@src/hooks/useAllowanceService";
import { useAuthZService } from "@src/hooks/useAuthZService";
import { QueryKeys } from "@src/queries/queryKeys";

export function useExactFeeAllowanceQuery(granter: string, grantee: string, { enabled = true } = {}) {
const allowanceHttpService = useAllowanceService();
const allowanceHttpService = useAuthZService();
return useQuery(QueryKeys.getFeeAllowancesKey(granter, grantee), () => allowanceHttpService.getFeeAllowanceForGranterAndGrantee(granter, grantee), {
enabled
});
Expand Down
42 changes: 15 additions & 27 deletions apps/deploy-web/src/queries/useGrantsQuery.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { QueryObserverResult, useQuery } from "react-query";

import { useSettings } from "@src/context/SettingsProvider";
import { useAuthZService } from "@src/hooks/useAuthZService";
import { AllowanceType, GrantType } from "@src/types/grant";
import { ApiUrlService, loadWithPagination } from "@src/utils/apiUtils";
import { QueryKeys } from "./queryKeys";
Expand All @@ -9,13 +10,11 @@ async function getGranterGrants(apiEndpoint: string, address: string) {
if (!address || !apiEndpoint) return undefined;

const grants = await loadWithPagination<GrantType[]>(ApiUrlService.granterGrants(apiEndpoint, address), "grants", 1000);
const filteredGrants = grants.filter(
return grants.filter(
x =>
x.authorization["@type"] === "/akash.deployment.v1beta2.DepositDeploymentAuthorization" ||
x.authorization["@type"] === "/akash.deployment.v1beta3.DepositDeploymentAuthorization"
);

return filteredGrants;
}

export function useGranterGrants(address: string, options = {}) {
Expand All @@ -24,34 +23,25 @@ export function useGranterGrants(address: string, options = {}) {
return useQuery(QueryKeys.getGranterGrants(address), () => getGranterGrants(settings.apiEndpoint, address), options);
}

async function getGranteeGrants(apiEndpoint: string, address: string) {
if (!address || !apiEndpoint) return undefined;

// const grants = await loadWithPagination<GrantType[]>(ApiUrlService.granteeGrants(apiEndpoint, address), "grants", 1000);
const grants: GrantType[] = [];
const filteredGrants = grants.filter(
x =>
// TODO: this is not working
// Only the v1beta3 authorization are working
// x.authorization["@type"] === "/akash.deployment.v1beta2.DepositDeploymentAuthorization" ||
x.authorization["@type"] === "/akash.deployment.v1beta3.DepositDeploymentAuthorization"
);

return filteredGrants;
}

export function useGranteeGrants(address: string, options = {}) {
export function useGranteeGrants(address?: string, options: { enabled?: boolean; refetchInterval?: number } = { enabled: true }) {
const allowanceHttpService = useAuthZService();
const { settings } = useSettings();

return useQuery(QueryKeys.getGranteeGrants(address), () => getGranteeGrants(settings.apiEndpoint, address), options);
// TODO: ensure app is not loaded till settings are fetched
// Issue: https://github.com/akash-network/console/issues/600
options.enabled = !!address && !!settings.apiEndpoint;

return useQuery(
QueryKeys.getGranteeGrants(address || "UNDEFINED"),
() => (address ? allowanceHttpService.getAllDepositDeploymentGrants({ grantee: address, limit: 1000 }) : []),
options
);
}

async function getAllowancesIssued(apiEndpoint: string, address: string) {
if (!address || !apiEndpoint) return undefined;

const allowances = await loadWithPagination<AllowanceType[]>(ApiUrlService.allowancesIssued(apiEndpoint, address), "allowances", 1000);

return allowances;
return await loadWithPagination<AllowanceType[]>(ApiUrlService.allowancesIssued(apiEndpoint, address), "allowances", 1000);
}

export function useAllowancesIssued(address: string, options = {}) {
Expand All @@ -63,9 +53,7 @@ export function useAllowancesIssued(address: string, options = {}) {
async function getAllowancesGranted(apiEndpoint: string, address: string) {
if (!address || !apiEndpoint) return undefined;

const allowances = await loadWithPagination<AllowanceType[]>(ApiUrlService.allowancesGranted(apiEndpoint, address), "allowances", 1000);

return allowances;
return await loadWithPagination<AllowanceType[]>(ApiUrlService.allowancesGranted(apiEndpoint, address), "allowances", 1000);
}

export function useAllowancesGranted(address?: string, options = {}): QueryObserverResult<AllowanceType[]> {
Expand Down
3 changes: 0 additions & 3 deletions apps/deploy-web/src/queries/useTemplateQuery.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,10 @@
import { QueryKey, useMutation, useQuery, useQueryClient, UseQueryOptions } from "react-query";
import { UseQueryResult } from "react-query/types/react/types";
import { TemplateOutput } from "@akashnetwork/http-sdk/src/template/template-http.service";
import { Snackbar } from "@akashnetwork/ui/components";
import axios from "axios";
import { useRouter } from "next/navigation";
import { useSnackbar } from "notistack";

import { useCustomUser } from "@src/hooks/useCustomUser";
import { services } from "@src/services/http/http-browser.service";
import { ITemplate } from "@src/types";
import { ApiUrlService } from "@src/utils/apiUtils";
import { UrlService } from "@src/utils/urlUtils";
Expand Down
5 changes: 3 additions & 2 deletions apps/deploy-web/src/types/address.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { Grant } from "./balances";
import { ExactDepositDeploymentGrant } from "@akashnetwork/http-sdk";

import { DeploymentDto } from "./deployment";
import { TransactionDetail } from "./transaction";
import { IValidatorAddess } from "./validator";
Expand Down Expand Up @@ -45,5 +46,5 @@ export interface Balances {
deploymentGrantsUAKT: number;
deploymentGrantsUUSDC: number;
activeDeployments: DeploymentDto[];
deploymentGrants: Grant[];
deploymentGrant?: ExactDepositDeploymentGrant;
}
5 changes: 2 additions & 3 deletions apps/deploy-web/src/utils/apiUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -56,9 +56,6 @@ export class ApiUrlService {
static unbonding(apiEndpoint: string, address: string) {
return `${apiEndpoint}/cosmos/staking/v1beta1/delegators/${address}/unbonding_delegations`;
}
static granteeGrants(apiEndpoint: string, address: string) {
return `${apiEndpoint}/cosmos/authz/v1beta1/grants/grantee/${address}`;
}
static granterGrants(apiEndpoint: string, address: string) {
return `${apiEndpoint}/cosmos/authz/v1beta1/grants/granter/${address}`;
}
Expand Down Expand Up @@ -128,6 +125,8 @@ export class ApiUrlService {
}
}

// TODO: implement proper pagination on clients
// Issue: https://github.com/akash-network/console/milestone/7
export async function loadWithPagination<T>(baseUrl: string, dataKey: string, limit: number) {
let items = [];
let nextKey = null;
Expand Down
6 changes: 3 additions & 3 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion packages/http-sdk/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@akashnetwork/http-sdk",
"version": "1.1.2",
"version": "1.1.3",
"description": "Package containing http layer for Akash Network",
"keywords": [],
"license": "Apache-2.0",
Expand Down
Loading

0 comments on commit d87d79f

Please sign in to comment.