diff --git a/CHANGELOG.md b/CHANGELOG.md
index 8e60f4d0b..faa007d5b 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -39,6 +39,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### Features
+- [#717](https://github.com/alleslabs/celatone-frontend/pull/717) Add total value for contract detail
- [#711](https://github.com/alleslabs/celatone-frontend/pull/711) Refactor assetInfos and add movePoolInfos to tx details
- [#724](https://github.com/alleslabs/celatone-frontend/pull/724) Add stone-13
diff --git a/src/lib/pages/account-details/components/TotalAccountValue.tsx b/src/lib/components/TotalValue.tsx
similarity index 70%
rename from src/lib/pages/account-details/components/TotalAccountValue.tsx
rename to src/lib/components/TotalValue.tsx
index c207032f4..ed410ce5c 100644
--- a/src/lib/pages/account-details/components/TotalAccountValue.tsx
+++ b/src/lib/components/TotalValue.tsx
@@ -1,32 +1,35 @@
import { Flex, Heading, Skeleton, Text } from "@chakra-ui/react";
-import { useAccountTotalValue } from "../data";
+import { useAccountTotalValue } from "lib/model/account";
import type { BechAddr } from "lib/types";
import { formatPrice } from "lib/utils";
-interface TotalAccountValueProps {
- accountAddress: BechAddr;
+interface TotalValueProps {
+ address: BechAddr;
+ label?: string;
+ isCompact?: boolean;
}
-export const TotalAccountValue = ({
- accountAddress,
-}: TotalAccountValueProps) => {
- const { totalAccountValue, isLoading } = useAccountTotalValue(accountAddress);
+export const TotalValue = ({
+ address,
+ label = "Total Account Value",
+ isCompact = false,
+}: TotalValueProps) => {
+ const { totalAccountValue, isLoading } = useAccountTotalValue(address);
return (
- Total Account Value
+ {label}
{isLoading ? (
diff --git a/src/lib/components/links/GitHubLink.tsx b/src/lib/components/links/GitHubLink.tsx
index e71c54d68..12076b9fc 100644
--- a/src/lib/components/links/GitHubLink.tsx
+++ b/src/lib/components/links/GitHubLink.tsx
@@ -5,14 +5,20 @@ import { trackSocial } from "lib/amplitude";
interface GitHubLinkProps {
github: string;
+ hasMinW?: boolean;
}
-export const GitHubLink = ({ github }: GitHubLinkProps) => {
+export const GitHubLink = ({ github, hasMinW = false }: GitHubLinkProps) => {
const [, , , org, repo] = github.split("/");
return (
-
- GitHub:
+
+ GitHub{!hasMinW && ":"}
;
+ isValidator: Option;
+ totalBonded: Option>;
+ totalDelegations: Option>;
+ delegations: Option;
+ totalUnbondings: Option>;
+ unbondings: Option;
+ totalRewards: Option>;
+ rewards: Option>;
+ redelegations: Option;
+ totalCommission: Option>;
+}
+
+// ------------------------------------------//
+// ----------------DELEGATIONS---------------//
+// ------------------------------------------//
+
+const calBonded = (
+ totalDelegations: Option>,
+ totalUnbondings: Option>
+) => {
+ if (!totalDelegations || !totalUnbondings) return undefined;
+
+ return Object.keys(totalDelegations).reduce>(
+ (total, denom) => ({
+ ...total,
+ [denom]: addTokenWithValue(
+ totalUnbondings[denom],
+ totalDelegations[denom]
+ ),
+ }),
+ {}
+ );
+};
+
+export const useAccountDelegationInfos = (address: BechAddr) => {
+ const { data: assetInfos, isLoading: isLoadingAssetInfos } = useAssetInfos({
+ withPrices: true,
+ });
+ const { data: movePoolInfos, isLoading: isLoadingMovePoolInfos } =
+ useMovePoolInfos({
+ withPrices: true,
+ });
+
+ const { data: accountDelegations, isLoading: isLoadingAccountDelegations } =
+ useDelegationsByAddress(address);
+
+ const isLoading =
+ isLoadingAccountDelegations ||
+ isLoadingAssetInfos ||
+ isLoadingMovePoolInfos;
+
+ const data: UserDelegationsData = {
+ isLoading,
+ stakingParams: undefined,
+ isValidator: undefined,
+ totalBonded: undefined,
+ totalDelegations: undefined,
+ delegations: undefined,
+ totalUnbondings: undefined,
+ unbondings: undefined,
+ totalRewards: undefined,
+ rewards: undefined,
+ redelegations: undefined,
+ totalCommission: undefined,
+ };
+
+ if (accountDelegations) {
+ data.stakingParams = {
+ ...accountDelegations.stakingParams,
+ bondDenoms: accountDelegations.stakingParams.bondDenoms.map((denom) =>
+ coinToTokenWithValue(denom, "0", assetInfos, movePoolInfos)
+ ),
+ };
+
+ data.isValidator = accountDelegations.isValidator;
+
+ data.delegations = accountDelegations.delegations.map(
+ (raw) => ({
+ validator: raw.validator,
+ balances: raw.balance
+ .map((coin) =>
+ coinToTokenWithValue(
+ coin.denom,
+ coin.amount,
+ assetInfos,
+ movePoolInfos
+ )
+ )
+ .sort(compareTokenWithValues),
+ })
+ );
+ data.totalDelegations = data.delegations?.reduce<
+ Record
+ >(
+ (total, delegation) =>
+ delegation.balances.reduce(
+ (acc, balance) => ({
+ ...acc,
+ [balance.denom]: addTokenWithValue(acc[balance.denom], balance),
+ }),
+ total
+ ),
+ {}
+ );
+
+ data.unbondings = accountDelegations.unbondings.map((raw) => ({
+ validator: raw.validator,
+ completionTime: raw.completionTime,
+ balances: raw.balance
+ .map((coin) =>
+ coinToTokenWithValue(
+ coin.denom,
+ coin.amount,
+ assetInfos,
+ movePoolInfos
+ )
+ )
+ .sort(compareTokenWithValues),
+ }));
+ data.totalUnbondings = data.unbondings?.reduce<
+ Record
+ >(
+ (total, unbonding) =>
+ unbonding.balances.reduce(
+ (acc, balance) => ({
+ ...acc,
+ [balance.denom]: addTokenWithValue(acc[balance.denom], balance),
+ }),
+ total
+ ),
+ {}
+ );
+
+ data.rewards = accountDelegations.delegationRewards.rewards.reduce<
+ Record
+ >(
+ (prev, raw) => ({
+ ...prev,
+ [raw.validator.validatorAddress]: raw.reward
+ .map((coin) =>
+ coinToTokenWithValue(
+ coin.denom,
+ coin.amount,
+ assetInfos,
+ movePoolInfos
+ )
+ )
+ .sort(compareTokenWithValues),
+ }),
+ {}
+ );
+ data.totalRewards = accountDelegations.delegationRewards.total.reduce<
+ Record
+ >(
+ (total, raw) => ({
+ ...total,
+ [raw.denom]: coinToTokenWithValue(
+ raw.denom,
+ raw.amount,
+ assetInfos,
+ movePoolInfos
+ ),
+ }),
+ {}
+ );
+
+ data.redelegations = accountDelegations.redelegations.map(
+ (raw) => ({
+ srcValidator: raw.srcValidator,
+ dstValidator: raw.dstValidator,
+ completionTime: raw.completionTime,
+ balances: raw.balance
+ .map((coin) =>
+ coinToTokenWithValue(
+ coin.denom,
+ coin.amount,
+ assetInfos,
+ movePoolInfos
+ )
+ )
+ .sort(compareTokenWithValues),
+ })
+ );
+
+ data.totalCommission = accountDelegations.commissions.reduce<
+ Record
+ >(
+ (commission, raw) => ({
+ ...commission,
+ [raw.denom]: coinToTokenWithValue(
+ raw.denom,
+ raw.amount,
+ assetInfos,
+ movePoolInfos
+ ),
+ }),
+ {}
+ );
+
+ data.totalBonded = calBonded(data.totalDelegations, data.totalUnbondings);
+ }
+
+ return data;
+};
+
+export const useAccountTotalValue = (address: BechAddr) => {
+ const defaultValue = big(0) as USD;
+
+ const {
+ chainConfig: {
+ extra: { disableDelegation },
+ },
+ } = useCelatoneApp();
+ const {
+ totalSupportedAssetsValue = defaultValue,
+ isLoading: isLoadingTotalSupportedAssetsValue,
+ } = useBalanceInfos(address);
+ const {
+ isLoading,
+ stakingParams,
+ totalBonded,
+ totalRewards,
+ totalCommission,
+ } = useAccountDelegationInfos(address);
+
+ if (disableDelegation)
+ return {
+ totalAccountValue: totalSupportedAssetsValue,
+ isLoading: false,
+ };
+
+ if (isLoading || isLoadingTotalSupportedAssetsValue)
+ return { totalAccountValue: undefined, isLoading: true };
+
+ if (!stakingParams || !totalBonded || !totalRewards || !totalCommission)
+ return { totalAccountValue: undefined, isLoading: false };
+
+ return {
+ totalAccountValue: totalSupportedAssetsValue
+ .add(totalValueTokenWithValue(totalBonded, defaultValue))
+ .add(totalValueTokenWithValue(totalRewards, defaultValue))
+ .add(totalValueTokenWithValue(totalCommission, defaultValue)) as USD,
+ isLoading: false,
+ };
+};
diff --git a/src/lib/pages/account-details/components/AccountHeader.tsx b/src/lib/pages/account-details/components/AccountHeader.tsx
index a56ed9bd4..e7d6f1a43 100644
--- a/src/lib/pages/account-details/components/AccountHeader.tsx
+++ b/src/lib/pages/account-details/components/AccountHeader.tsx
@@ -10,12 +10,11 @@ import {
RemoveSavedAccountModal,
} from "lib/components/modal";
import { PrimaryNameMark } from "lib/components/PrimaryNameMark";
+import { TotalValue } from "lib/components/TotalValue";
import { useAccountStore } from "lib/providers/store";
import type { AccountData } from "lib/services/account";
import type { HexAddr, BechAddr, Option } from "lib/types";
-import { TotalAccountValue } from "./TotalAccountValue";
-
interface AccounHeaderProps {
accountData: Option;
accountAddress: BechAddr;
@@ -182,7 +181,7 @@ export const AccountHeader = observer(
)}
-
+
);
diff --git a/src/lib/pages/account-details/components/delegations/index.tsx b/src/lib/pages/account-details/components/delegations/index.tsx
index f3cb51b1f..7e89c1ec3 100644
--- a/src/lib/pages/account-details/components/delegations/index.tsx
+++ b/src/lib/pages/account-details/components/delegations/index.tsx
@@ -5,7 +5,7 @@ import { useEffect } from "react";
import { AmpEvent, track } from "lib/amplitude";
import { Loading } from "lib/components/Loading";
import { ErrorFetching } from "lib/components/state";
-import { useUserDelegationInfos } from "lib/pages/account-details/data";
+import { useAccountDelegationInfos } from "lib/model/account";
import type { BechAddr } from "lib/types";
import { getTokenLabel } from "lib/utils";
@@ -38,7 +38,7 @@ export const DelegationsSection = ({
rewards,
redelegations,
totalCommission,
- } = useUserDelegationInfos(address);
+ } = useAccountDelegationInfos(address);
useEffect(() => {
onClose();
diff --git a/src/lib/pages/account-details/data.ts b/src/lib/pages/account-details/data.ts
index 10676e00e..351f239e4 100644
--- a/src/lib/pages/account-details/data.ts
+++ b/src/lib/pages/account-details/data.ts
@@ -1,40 +1,18 @@
-import type { Big } from "big.js";
-import big from "big.js";
-
-import { useCelatoneApp } from "lib/app-provider";
import { useCodeStore, useContractStore } from "lib/providers/store";
import { useAccountTableCounts } from "lib/services/accountService";
-import { useAssetInfos } from "lib/services/assetService";
-import { useBalanceInfos, useBalances } from "lib/services/balanceService";
+import { useBalances } from "lib/services/balanceService";
import { useCodesByAddress } from "lib/services/codeService";
import {
useAdminContractsByAddress,
useInstantiatedContractsByAddress,
} from "lib/services/contractService";
-import { useDelegationsByAddress } from "lib/services/delegationService";
-import { useMovePoolInfos } from "lib/services/move";
import type {
BechAddr,
CodeInfo,
ContractInfo,
Nullish,
Option,
- TokenWithValue,
- USD,
} from "lib/types";
-import {
- addTokenWithValue,
- coinToTokenWithValue,
- totalValueTokenWithValue,
- compareTokenWithValues,
-} from "lib/utils";
-
-import type {
- Delegation,
- Redelegation,
- StakingParams,
- Unbonding,
-} from "./types";
// ------------------------------------------//
// ---------------TABLE COUNTS---------------//
@@ -173,252 +151,3 @@ export const useAccountCodes = (
isLoading,
};
};
-
-// ------------------------------------------//
-// ----------------DELEGATIONS---------------//
-// ------------------------------------------//
-
-interface UserDelegationsData {
- isLoading: boolean;
- stakingParams: Option;
- isValidator: Option;
- totalBonded: Option>;
- totalDelegations: Option>;
- delegations: Option;
- totalUnbondings: Option>;
- unbondings: Option;
- totalRewards: Option>;
- rewards: Option>;
- redelegations: Option;
- totalCommission: Option>;
-}
-
-const calBonded = (
- totalDelegations: Option>,
- totalUnbondings: Option>
-) => {
- if (!totalDelegations || !totalUnbondings) return undefined;
-
- return Object.keys(totalDelegations).reduce>(
- (total, denom) => ({
- ...total,
- [denom]: addTokenWithValue(
- totalUnbondings[denom],
- totalDelegations[denom]
- ),
- }),
- {}
- );
-};
-
-export const useUserDelegationInfos = (address: BechAddr) => {
- const { data: assetInfos, isLoading: isLoadingAssetInfos } = useAssetInfos({
- withPrices: true,
- });
- const { data: movePoolInfos, isLoading: isLoadingMovePoolInfos } =
- useMovePoolInfos({
- withPrices: true,
- });
-
- const { data: accountDelegations, isLoading: isLoadingAccountDelegations } =
- useDelegationsByAddress(address);
-
- const isLoading =
- isLoadingAccountDelegations ||
- isLoadingAssetInfos ||
- isLoadingMovePoolInfos;
-
- const data: UserDelegationsData = {
- isLoading,
- stakingParams: undefined,
- isValidator: undefined,
- totalBonded: undefined,
- totalDelegations: undefined,
- delegations: undefined,
- totalUnbondings: undefined,
- unbondings: undefined,
- totalRewards: undefined,
- rewards: undefined,
- redelegations: undefined,
- totalCommission: undefined,
- };
-
- if (accountDelegations) {
- data.stakingParams = {
- ...accountDelegations.stakingParams,
- bondDenoms: accountDelegations.stakingParams.bondDenoms.map((denom) =>
- coinToTokenWithValue(denom, "0", assetInfos, movePoolInfos)
- ),
- };
-
- data.isValidator = accountDelegations.isValidator;
-
- data.delegations = accountDelegations.delegations.map(
- (raw) => ({
- validator: raw.validator,
- balances: raw.balance
- .map((coin) =>
- coinToTokenWithValue(
- coin.denom,
- coin.amount,
- assetInfos,
- movePoolInfos
- )
- )
- .sort(compareTokenWithValues),
- })
- );
- data.totalDelegations = data.delegations?.reduce<
- Record
- >(
- (total, delegation) =>
- delegation.balances.reduce(
- (acc, balance) => ({
- ...acc,
- [balance.denom]: addTokenWithValue(acc[balance.denom], balance),
- }),
- total
- ),
- {}
- );
-
- data.unbondings = accountDelegations.unbondings.map((raw) => ({
- validator: raw.validator,
- completionTime: raw.completionTime,
- balances: raw.balance
- .map((coin) =>
- coinToTokenWithValue(
- coin.denom,
- coin.amount,
- assetInfos,
- movePoolInfos
- )
- )
- .sort(compareTokenWithValues),
- }));
- data.totalUnbondings = data.unbondings?.reduce<
- Record
- >(
- (total, unbonding) =>
- unbonding.balances.reduce(
- (acc, balance) => ({
- ...acc,
- [balance.denom]: addTokenWithValue(acc[balance.denom], balance),
- }),
- total
- ),
- {}
- );
-
- data.rewards = accountDelegations.delegationRewards.rewards.reduce<
- Record
- >(
- (prev, raw) => ({
- ...prev,
- [raw.validator.validatorAddress]: raw.reward
- .map((coin) =>
- coinToTokenWithValue(
- coin.denom,
- coin.amount,
- assetInfos,
- movePoolInfos
- )
- )
- .sort(compareTokenWithValues),
- }),
- {}
- );
- data.totalRewards = accountDelegations.delegationRewards.total.reduce<
- Record
- >(
- (total, raw) => ({
- ...total,
- [raw.denom]: coinToTokenWithValue(
- raw.denom,
- raw.amount,
- assetInfos,
- movePoolInfos
- ),
- }),
- {}
- );
-
- data.redelegations = accountDelegations.redelegations.map(
- (raw) => ({
- srcValidator: raw.srcValidator,
- dstValidator: raw.dstValidator,
- completionTime: raw.completionTime,
- balances: raw.balance
- .map((coin) =>
- coinToTokenWithValue(
- coin.denom,
- coin.amount,
- assetInfos,
- movePoolInfos
- )
- )
- .sort(compareTokenWithValues),
- })
- );
-
- data.totalCommission = accountDelegations.commissions.reduce<
- Record
- >(
- (commission, raw) => ({
- ...commission,
- [raw.denom]: coinToTokenWithValue(
- raw.denom,
- raw.amount,
- assetInfos,
- movePoolInfos
- ),
- }),
- {}
- );
-
- data.totalBonded = calBonded(data.totalDelegations, data.totalUnbondings);
- }
-
- return data;
-};
-
-export const useAccountTotalValue = (address: BechAddr) => {
- const defaultValue = big(0) as USD;
-
- const {
- chainConfig: {
- extra: { disableDelegation },
- },
- } = useCelatoneApp();
- const {
- totalSupportedAssetsValue = defaultValue,
- isLoading: isLoadingTotalSupportedAssetsValue,
- } = useBalanceInfos(address);
- const {
- isLoading,
- stakingParams,
- totalBonded,
- totalRewards,
- totalCommission,
- } = useUserDelegationInfos(address);
-
- if (disableDelegation)
- return {
- totalAccountValue: totalSupportedAssetsValue,
- isLoading: false,
- };
-
- if (isLoading || isLoadingTotalSupportedAssetsValue)
- return { totalAccountValue: undefined, isLoading: true };
-
- if (!stakingParams || !totalBonded || !totalRewards || !totalCommission)
- return { totalAccountValue: undefined, isLoading: false };
-
- return {
- totalAccountValue: totalSupportedAssetsValue
- .add(totalValueTokenWithValue(totalBonded, defaultValue))
- .add(totalValueTokenWithValue(totalRewards, defaultValue))
- .add(totalValueTokenWithValue(totalCommission, defaultValue)) as USD,
- isLoading: false,
- };
-};
diff --git a/src/lib/pages/code-details/components/code-info/CodeTopInfo.tsx b/src/lib/pages/code-details/components/code-info/CodeTopInfo.tsx
index 7febee732..732a5d10f 100644
--- a/src/lib/pages/code-details/components/code-info/CodeTopInfo.tsx
+++ b/src/lib/pages/code-details/components/code-info/CodeTopInfo.tsx
@@ -72,7 +72,7 @@ export const CodeTopInfo = ({ codeId, codeDataState }: CodeTopInfoProps) => {
/>
diff --git a/src/lib/pages/contract-details/components/ContractTop.tsx b/src/lib/pages/contract-details/components/ContractTop.tsx
index 18512d618..c13f6df47 100644
--- a/src/lib/pages/contract-details/components/ContractTop.tsx
+++ b/src/lib/pages/contract-details/components/ContractTop.tsx
@@ -18,6 +18,7 @@ import {
EditContractDetailsModal,
SaveContractDetailsModal,
} from "lib/components/modal";
+import { TotalValue } from "lib/components/TotalValue";
import type { Contract } from "lib/services/contract";
import type { ContractLocalInfo } from "lib/stores/contract";
import type {
@@ -127,19 +128,15 @@ export const ContractTop = ({
justify="space-between"
mt={{ base: 3, md: 6 }}
direction={{ base: "column", md: "row" }}
- gap={{ md: 4 }}
+ gap={{ md: 8 }}
>
-
+
- Contract Address:
+ Contract Address
-
- Label:
+
+ Label
{contract.label}
@@ -200,65 +198,74 @@ export const ContractTop = ({
direction={{ base: "column", md: "row" }}
gap={{ base: 0, md: 2 }}
>
-
- Public Contract Name:
+
+ Public Name
{publicInfo.name}
)}
- {publicInfo?.github && }
-
-
- {!isMobile && (
-
+ {publicInfo?.github && (
+
)}
-
- }
- onClick={goToQuery}
- size={{ base: "sm", md: "md" }}
- >
- Query
-
-
- {!isMobile && (
-
- {contractLocalInfo && (
- }
- />
- }
- />
- )}
- {renderSaveButton()}
-
- )}
+ {!isMobile && (
+
+ )}
+ }
+ onClick={goToQuery}
+ size={{ base: "sm", md: "md" }}
+ >
+ Query
+
+ }
+ onClick={goToExecute}
+ size={{ base: "sm", md: "md" }}
+ >
+ Execute
+
+ {!isMobile && (
+
+ {contractLocalInfo && (
+ }
+ />
+ }
+ />
+ )}
+ {renderSaveButton()}
+
+ )}
+
+