diff --git a/client/src/app/components/stardust/address/AddressBalance.tsx b/client/src/app/components/stardust/address/AddressBalance.tsx index c548a674f..432690d4f 100644 --- a/client/src/app/components/stardust/address/AddressBalance.tsx +++ b/client/src/app/components/stardust/address/AddressBalance.tsx @@ -21,13 +21,13 @@ interface AddressBalanceProps { /** * The storage rent balance. */ - readonly storageRentBalance: number | null; + readonly storageDeposit: number | null; } const CONDITIONAL_BALANCE_INFO = "These funds reside within outputs with additional unlock conditions which might be potentially un-lockable"; -const AddressBalance: React.FC = ({ balance, spendableBalance, storageRentBalance }) => { +const AddressBalance: React.FC = ({ balance, spendableBalance, storageDeposit }) => { const { name: network, tokenInfo } = useContext(NetworkContext); const [formatBalanceFull, setFormatBalanceFull] = useState(false); const [formatConditionalBalanceFull, setFormatConditionalBalanceFull] = useState(false); @@ -101,14 +101,7 @@ const AddressBalance: React.FC = ({ balance, spendableBalan false, conditionalBalance, )} - {buildBalanceView( - "Storage Deposit", - formatStorageBalanceFull, - setFormatStorageBalanceFull, - false, - false, - storageRentBalance, - )} + {buildBalanceView("Storage Deposit", formatStorageBalanceFull, setFormatStorageBalanceFull, false, false, storageDeposit)} ); diff --git a/client/src/app/routes/stardust/AddressPage.tsx b/client/src/app/routes/stardust/AddressPage.tsx index 8972379d8..f5a8deeb5 100644 --- a/client/src/app/routes/stardust/AddressPage.tsx +++ b/client/src/app/routes/stardust/AddressPage.tsx @@ -24,7 +24,7 @@ const AddressPage: React.FC> = ({ bech32AddressDetails, balance, availableBalance, - storageRentBalance, + storageDeposit, isBasicOutputsLoading, isAliasOutputsLoading, isNftOutputsLoading, @@ -88,7 +88,7 @@ const AddressPage: React.FC> = ({ )} diff --git a/client/src/app/routes/stardust/AddressState.ts b/client/src/app/routes/stardust/AddressState.ts index 19d7ec90b..17fb0c1ab 100644 --- a/client/src/app/routes/stardust/AddressState.ts +++ b/client/src/app/routes/stardust/AddressState.ts @@ -1,17 +1,20 @@ import { Bech32Helper } from "@iota/iota.js"; import { - HexEncodedString, + AddressType, AliasOutput, + BasicOutput, + FeatureType, + HexEncodedString, MetadataFeature, + Output, OutputResponse, OutputType, - AddressType, - Output, - BasicOutput, - FeatureType, } from "@iota/sdk-wasm/web"; import { Reducer, useContext, useEffect, useReducer } from "react"; import { useLocation, useParams } from "react-router-dom"; +import { useAliasContainsDID } from "~/helpers/hooks/useAliasContainsDID"; +import { useResolvedDID } from "~/helpers/hooks/useResolvedDID"; +import { IDIDResolverResponse } from "~/models/api/IDIDResolverResponse"; import { useAddressAliasOutputs } from "~helpers/hooks/useAddressAliasOutputs"; import { useAddressBalance } from "~helpers/hooks/useAddressBalance"; import { useAddressBasicOutputs } from "~helpers/hooks/useAddressBasicOutputs"; @@ -30,15 +33,12 @@ import { IBech32AddressDetails } from "~models/api/IBech32AddressDetails"; import { IParticipation } from "~models/api/stardust/participation/IParticipation"; import NetworkContext from "../../context/NetworkContext"; import { AddressRouteProps } from "../AddressRouteProps"; -import { useAliasContainsDID } from "~/helpers/hooks/useAliasContainsDID"; -import { useResolvedDID } from "~/helpers/hooks/useResolvedDID"; -import { IDIDResolverResponse } from "~/models/api/IDIDResolverResponse"; export interface IAddressState { bech32AddressDetails: IBech32AddressDetails | null; balance: number | null; availableBalance: number | null; - storageRentBalance: number | null; + storageDeposit: number | null; addressOutputs: OutputResponse[] | null; addressBasicOutputs: OutputResponse[] | null; isBasicOutputsLoading: boolean; @@ -70,7 +70,7 @@ const initialState = { bech32AddressDetails: null, balance: null, availableBalance: null, - storageRentBalance: null, + storageDeposit: null, addressOutputs: null, addressBasicOutputs: null, isBasicOutputsLoading: true, @@ -121,13 +121,16 @@ export const useAddressPageState = (): [IAddressState, React.Dispatch { - if (addressBasicOutputs && addressAliasOutputs && addressNftOutputs) { - const mergedOutputResponses = [...addressBasicOutputs, ...addressAliasOutputs, ...addressNftOutputs]; - const outputs = mergedOutputResponses.map((or) => or.output); - const storageRentBalanceUpdate = TransactionsHelper.computeStorageRentBalance(outputs, rentStructure); - - setState({ - addressOutputs: mergedOutputResponses, - storageRentBalance: storageRentBalanceUpdate, - }); + const addressOutputs = + [...(addressBasicOutputs ?? []), ...(addressAliasOutputs ?? []), ...(addressNftOutputs ?? [])].filter((o) => o !== null) ?? []; + let outputsComputedInStorageDeposit = addressOutputs?.map((or) => or.output); + const addressOutputItself = nftOutput ?? aliasOutput; + if (addressOutputItself) { + outputsComputedInStorageDeposit = [...outputsComputedInStorageDeposit, addressOutputItself]; } + const storageDeposit = TransactionsHelper.computeStorageDeposit(outputsComputedInStorageDeposit, rentStructure); + + setState({ + addressOutputs, + storageDeposit, + }); if (addressBasicOutputs && !state.participations) { let foundParticipations: IParticipation[] = []; for (const outputResponse of addressBasicOutputs) { @@ -231,7 +237,7 @@ export const useAddressPageState = (): [IAddressState, React.Dispatch(`api-client-${STARDUST}`)); const [balance, setBalance] = useState(null); @@ -19,20 +26,33 @@ export function useAddressBalance(network: string, address: string | null): [num useEffect(() => { setIsLoading(true); - if (address) { + const address = addressDetails?.bech32; + const needsOutputToProceed = addressDetails?.type === AddressType.Alias || addressDetails?.type === AddressType.Nft; + const canLoad = address && (!needsOutputToProceed || (needsOutputToProceed && output)); + if (canLoad) { // eslint-disable-next-line no-void void (async () => { const response = await apiClient.addressBalanceChronicle({ network, address }); if (response?.totalBalance !== undefined && isMounted) { - setBalance(response.totalBalance); - setAvailableBalance(response.availableBalance ?? null); + let totalBalance = response.totalBalance; + let availableBalance = response.availableBalance ?? 0; + if (output) { + totalBalance = Number(totalBalance) + Number(output.amount); + availableBalance = Number(availableBalance) + Number(output.amount); + } + setBalance(totalBalance); + setAvailableBalance(availableBalance > 0 ? availableBalance : null); } else if (isMounted) { // Fallback balance from iotajs (node) const addressDetailsWithBalance = await apiClient.addressBalance({ network, address }); if (addressDetailsWithBalance && isMounted) { - setBalance(Number(addressDetailsWithBalance.balance)); + let totalBalance = Number(addressDetailsWithBalance.balance); + if (output) { + totalBalance = Number(totalBalance) + Number(output.amount); + } + setBalance(totalBalance); setAvailableBalance(null); } } @@ -40,7 +60,7 @@ export function useAddressBalance(network: string, address: string | null): [num } else { setIsLoading(false); } - }, [network, address]); + }, [network, addressDetails, output]); return [balance, availableBalance, isLoading]; } diff --git a/client/src/helpers/stardust/transactionsHelper.ts b/client/src/helpers/stardust/transactionsHelper.ts index 3fd705069..1a04615db 100644 --- a/client/src/helpers/stardust/transactionsHelper.ts +++ b/client/src/helpers/stardust/transactionsHelper.ts @@ -237,7 +237,7 @@ export class TransactionsHelper { return HexHelper.toBigInt256(nftId).eq(bigInt.zero) ? Utils.computeNftId(outputId) : nftId; } - public static computeStorageRentBalance(outputs: Output[], rentStructure: IRent): number { + public static computeStorageDeposit(outputs: Output[], rentStructure: IRent): number { const outputsWithoutSdruc = outputs.filter((output) => { if (output.type === OutputType.Treasury) { return false;