Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(billing): use specific endpoint to check managed wallet grants #594

Merged
merged 1 commit into from
Dec 30, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
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
Loading