From 8710d9406c498c5d4213d12bae2cae5f82627d9e Mon Sep 17 00:00:00 2001 From: Mario Sarcevic Date: Tue, 7 May 2024 10:44:52 +0200 Subject: [PATCH 1/2] fix: Fix mana calculation in OutputPage and AddressPage (don't use included.slot number!) --- client/src/app/routes/nova/OutputPage.tsx | 3 ++- client/src/helpers/nova/hooks/useAddressBalance.ts | 4 ++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/client/src/app/routes/nova/OutputPage.tsx b/client/src/app/routes/nova/OutputPage.tsx index 431167665..ba070d77d 100644 --- a/client/src/app/routes/nova/OutputPage.tsx +++ b/client/src/app/routes/nova/OutputPage.tsx @@ -11,6 +11,7 @@ import { useNetworkInfoNova } from "~/helpers/nova/networkInfo"; import { buildManaDetailsForOutput, OutputManaDetails } from "~/helpers/nova/manaUtils"; import { Converter } from "~/helpers/stardust/convertUtils"; import { useOutputManaRewards } from "~/helpers/nova/hooks/useOutputManaRewards"; +import { Utils } from "@iota/sdk-wasm-nova/web"; import "./OutputPage.scss"; interface OutputPageProps { @@ -54,7 +55,7 @@ const OutputPage: React.FC> = ({ const { blockId, included, spent } = outputMetadataResponse ?? {}; const transactionId = included?.transactionId ?? null; - const createdSlotIndex = (included?.slot as number) ?? null; + const createdSlotIndex = transactionId ? Utils.computeSlotIndex(transactionId) : null; const spentSlotIndex = (spent?.slot as number) ?? null; const isSpent = spentSlotIndex !== null; const transactionIdSpent = spent?.transactionId ?? null; diff --git a/client/src/helpers/nova/hooks/useAddressBalance.ts b/client/src/helpers/nova/hooks/useAddressBalance.ts index 2bbeb629f..f0ea120fb 100644 --- a/client/src/helpers/nova/hooks/useAddressBalance.ts +++ b/client/src/helpers/nova/hooks/useAddressBalance.ts @@ -1,4 +1,4 @@ -import { AddressType, NftOutput, AccountOutput, AnchorOutput, OutputMetadataResponse } from "@iota/sdk-wasm-nova/web"; +import { AddressType, NftOutput, AccountOutput, AnchorOutput, OutputMetadataResponse, Utils } from "@iota/sdk-wasm-nova/web"; import { useEffect, useState } from "react"; import { IManaBalance } from "~/models/api/nova/address/IAddressBalanceResponse"; import { IAddressDetails } from "~/models/api/nova/IAddressDetails"; @@ -64,7 +64,7 @@ export function useAddressBalance( // Output mana const { included, spent } = outputMetadata ?? {}; - const createdSlotIndex = (included?.slot as number) ?? null; + const createdSlotIndex = included?.transactionId ? Utils.computeSlotIndex(included.transactionId) : null; const spentSlotIndex = (spent?.slot as number) ?? null; if (output && createdSlotIndex !== null && protocolInfo) { From c2b7dab3ff097d905c19734a502b6bdabe8e5875 Mon Sep 17 00:00:00 2001 From: Mario Sarcevic Date: Tue, 7 May 2024 13:25:49 +0200 Subject: [PATCH 2/2] fix: Pass the slotIndex (spent) to getManaRewards --- api/src/models/api/nova/IRewardsRequest.ts | 5 +++++ api/src/routes/nova/output/rewards/get.ts | 6 +++--- api/src/services/nova/novaApiService.ts | 6 ++++-- client/src/app/routes/nova/OutputPage.tsx | 2 +- client/src/helpers/nova/hooks/useAccountAddressState.ts | 6 +++++- client/src/helpers/nova/hooks/useOutputManaRewards.ts | 2 +- client/src/models/api/nova/IRewardsRequest.ts | 5 +++++ client/src/services/nova/novaApiClient.ts | 3 ++- 8 files changed, 26 insertions(+), 9 deletions(-) diff --git a/api/src/models/api/nova/IRewardsRequest.ts b/api/src/models/api/nova/IRewardsRequest.ts index e1b9dd32f..c323f610f 100644 --- a/api/src/models/api/nova/IRewardsRequest.ts +++ b/api/src/models/api/nova/IRewardsRequest.ts @@ -8,4 +8,9 @@ export interface IRewardsRequest { * The output id to get the rewards for. */ outputId: string; + + /** + * The slot index to use as 'up to' to get the rewards for (like when the output was spent). + */ + slotIndex?: string; } diff --git a/api/src/routes/nova/output/rewards/get.ts b/api/src/routes/nova/output/rewards/get.ts index c9d0fe427..4d00f99a8 100644 --- a/api/src/routes/nova/output/rewards/get.ts +++ b/api/src/routes/nova/output/rewards/get.ts @@ -9,11 +9,11 @@ import { ValidationHelper } from "../../../../utils/validationHelper"; /** * Get the output rewards. - * @param config The configuration. + * @param _ The configuration. * @param request The request. * @returns The response. */ -export async function get(config: IConfiguration, request: IRewardsRequest): Promise { +export async function get(_: IConfiguration, request: IRewardsRequest): Promise { const networkService = ServiceFactory.get("network"); const networks = networkService.networkNames(); ValidationHelper.oneOf(request.network, networks, "network"); @@ -26,5 +26,5 @@ export async function get(config: IConfiguration, request: IRewardsRequest): Pro } const novaApiService = ServiceFactory.get(`api-service-${networkConfig.network}`); - return novaApiService.getRewards(request.outputId); + return novaApiService.getRewards(request.outputId, request.slotIndex); } diff --git a/api/src/services/nova/novaApiService.ts b/api/src/services/nova/novaApiService.ts index 475e37906..69896b144 100644 --- a/api/src/services/nova/novaApiService.ts +++ b/api/src/services/nova/novaApiService.ts @@ -578,10 +578,12 @@ export class NovaApiService { /** * Get the output mana rewards. * @param outputId The outputId to get the rewards for. + * @param slotIndex The slotIndex to get the rewards for. * @returns The mana rewards. */ - public async getRewards(outputId: string): Promise { - const manaRewardsResponse = await this.client.getOutputManaRewards(outputId); + public async getRewards(outputId: string, slotIndex?: string): Promise { + const parsedSlotIndex = slotIndex === undefined ? undefined : Number.parseInt(slotIndex, 10); + const manaRewardsResponse = await this.client.getOutputManaRewards(outputId, parsedSlotIndex); return manaRewardsResponse ? { outputId, manaRewards: manaRewardsResponse } : { outputId, message: "Rewards data not found" }; } diff --git a/client/src/app/routes/nova/OutputPage.tsx b/client/src/app/routes/nova/OutputPage.tsx index ba070d77d..9dace5235 100644 --- a/client/src/app/routes/nova/OutputPage.tsx +++ b/client/src/app/routes/nova/OutputPage.tsx @@ -32,7 +32,7 @@ const OutputPage: React.FC> = ({ }, }) => { const { output, outputMetadataResponse, error } = useOutputDetails(network, outputId); - const { manaRewards } = useOutputManaRewards(network, outputId); + const { manaRewards } = useOutputManaRewards(network, outputId, outputMetadataResponse?.spent?.slot); const { protocolInfo, latestConfirmedSlot } = useNetworkInfoNova((s) => s.networkInfo); if (error) { diff --git a/client/src/helpers/nova/hooks/useAccountAddressState.ts b/client/src/helpers/nova/hooks/useAccountAddressState.ts index ff0ecafaa..5c30408bd 100644 --- a/client/src/helpers/nova/hooks/useAccountAddressState.ts +++ b/client/src/helpers/nova/hooks/useAccountAddressState.ts @@ -109,7 +109,11 @@ export const useAccountAddressState = (address: AccountAddress): [IAccountAddres ); const { accountOutput, accountOutputMetadata, isLoading: isAccountDetailsLoading } = useAccountDetails(network, address.accountId); - const { manaRewards: outputManaRewards } = useOutputManaRewards(network, accountOutputMetadata?.outputId ?? ""); + const { manaRewards: outputManaRewards } = useOutputManaRewards( + network, + accountOutputMetadata?.outputId ?? "", + accountOutputMetadata?.spent?.slot, + ); const [addressBasicOutputs, isBasicOutputsLoading] = useAddressBasicOutputs(network, state.addressDetails?.bech32 ?? null); const [addressNftOutputs, isNftOutputsLoading] = useAddressNftOutputs(network, state.addressDetails?.bech32 ?? null); diff --git a/client/src/helpers/nova/hooks/useOutputManaRewards.ts b/client/src/helpers/nova/hooks/useOutputManaRewards.ts index 07f6c0029..2f1f03d78 100644 --- a/client/src/helpers/nova/hooks/useOutputManaRewards.ts +++ b/client/src/helpers/nova/hooks/useOutputManaRewards.ts @@ -36,7 +36,7 @@ export function useOutputManaRewards( // eslint-disable-next-line no-void void (async () => { apiClient - .getRewards({ network, outputId }) + .getRewards({ network, outputId, slotIndex }) .then((response) => { if (isMounted) { const manaRewards = response.manaRewards; diff --git a/client/src/models/api/nova/IRewardsRequest.ts b/client/src/models/api/nova/IRewardsRequest.ts index e1b9dd32f..52ed15ff8 100644 --- a/client/src/models/api/nova/IRewardsRequest.ts +++ b/client/src/models/api/nova/IRewardsRequest.ts @@ -8,4 +8,9 @@ export interface IRewardsRequest { * The output id to get the rewards for. */ outputId: string; + + /** + * The slot index to use as 'up to' to get the rewards for (like when the output was spent). + */ + slotIndex?: number; } diff --git a/client/src/services/nova/novaApiClient.ts b/client/src/services/nova/novaApiClient.ts index 549db86c3..a8281f8f1 100644 --- a/client/src/services/nova/novaApiClient.ts +++ b/client/src/services/nova/novaApiClient.ts @@ -287,7 +287,8 @@ export class NovaApiClient extends ApiClient { * @returns The response from the request. */ public async getRewards(request: IRewardsRequest): Promise { - return this.callApi(`nova/output/rewards/${request.network}/${request.outputId}`, "get"); + const params = FetchHelper.urlParams({ slotIndex: request.slotIndex }); + return this.callApi(`nova/output/rewards/${request.network}/${request.outputId}${params}`, "get"); } /**