Repository: iotaledger/iota
Pull request #6284: feat(ts-sdk): New `getLatestIotaSystemState` 
Author: login: marc2332
Labels: name: tooling
description: Issues related to the Tooling team
name: wallet
description: Issues related to the IOTA Wallet
name: ts-sdk
description: Issues related to the TS SDK
name: explorer
description: Issues related to the Explorer
name: wallet-dashboard
description: Issues related to the Wallet Dashboard dApp
Created: 2025-04-07T14:23:33Z | Merged: 2025-04-23T15:14:35Z

Closes https://github.com/iotaledger/iota/issues/5665
closes https://github.com/iotaledger/iota/issues/6260


Diff:
diff --git a/.changeset/itchy-eyes-smoke.md b/.changeset/itchy-eyes-smoke.md
new file mode 100644
index 00000000000..0c1c982bf26
--- /dev/null
+++ b/.changeset/itchy-eyes-smoke.md
@@ -0,0 +1,7 @@
+---
+'@iota/graphql-transport': minor
+'@iota/iota-sdk': minor
+'@iota/kiosk': minor
+---
+
+Rename `getLatestIotaSystemState` to `getLatestIotaSystemStateV1` and add a new backwards-compatible and future-proof `getLatestIotaSystemState` method that dinamically calls ``getLatestIotaSystemStateV1`or`getLatestIotaSystemStateV2` based on the protocol version of the node.
diff --git a/apps/core/src/components/stake/StakedCard.tsx b/apps/core/src/components/stake/StakedCard.tsx
index 9e8e92854f5..4bc5df15921 100644
--- a/apps/core/src/components/stake/StakedCard.tsx
+++ b/apps/core/src/components/stake/StakedCard.tsx
@@ -6,7 +6,8 @@ import { Card, CardImage, CardType, CardBody, CardAction, CardActionType } from
 import { useMemo } from 'react';
 import { ImageIcon } from '../icon';
 import { ExtendedDelegatedStake } from '../../utils';
-import { useFormatCoin, useGetLatestIotaSystemState, useStakeRewardStatus } from '../../hooks';
+import { useFormatCoin, useStakeRewardStatus } from '../../hooks';
+import { useIotaClientQuery } from '@iota/dapp-kit';
 
 interface StakedCardProps {
     extendedStake: ExtendedDelegatedStake;
@@ -37,7 +38,7 @@ export function StakedCard({
         balance: inactiveValidator ? BigInt(principal) + rewards : principal,
     });
 
-    const { data } = useGetLatestIotaSystemState();
+    const { data } = useIotaClientQuery('getLatestIotaSystemState');
 
     const validatorMeta = useMemo(() => {
         if (!data) return null;
diff --git a/apps/core/src/hooks/index.ts b/apps/core/src/hooks/index.ts
index 90d52d92183..0cfe0294c8b 100644
--- a/apps/core/src/hooks/index.ts
+++ b/apps/core/src/hooks/index.ts
@@ -58,7 +58,6 @@ export * from './useAssetGasBudgetEstimation';
 export * from './useRecognizedPackages';
 export * from './useGetAllBalances';
 export * from './useCoinsReFetchingConfig';
-export * from './useGetLatestIotaSystemState';
 
 export * from './stake';
 export * from './ui';
diff --git a/apps/core/src/hooks/stake/useValidatorInfo.ts b/apps/core/src/hooks/stake/useValidatorInfo.ts
index bfbcd9856ec..b3d5b9833f9 100644
--- a/apps/core/src/hooks/stake/useValidatorInfo.ts
+++ b/apps/core/src/hooks/stake/useValidatorInfo.ts
@@ -1,13 +1,14 @@
 // Copyright (c) 2024 IOTA Stiftung
 // SPDX-License-Identifier: Apache-2.0
-import { useGetLatestIotaSystemState, useGetValidatorsApy } from '..';
+import { useIotaClientQuery } from '@iota/dapp-kit';
+import { useGetValidatorsApy } from '..';
 
 export function useValidatorInfo({ validatorAddress }: { validatorAddress: string }) {
     const {
         data: system,
         isPending: isPendingValidators,
         isError: errorValidators,
-    } = useGetLatestIotaSystemState();
+    } = useIotaClientQuery('getLatestIotaSystemState');
     const { data: rollingAverageApys } = useGetValidatorsApy();
 
     const validatorSummary =
diff --git a/apps/core/src/hooks/useGetLatestIotaSystemState.ts b/apps/core/src/hooks/useGetLatestIotaSystemState.ts
deleted file mode 100644
index 513165caf59..00000000000
--- a/apps/core/src/hooks/useGetLatestIotaSystemState.ts
+++ /dev/null
@@ -1,71 +0,0 @@
-// Copyright (c) 2025 IOTA Stiftung
-// SPDX-License-Identifier: Apache-2.0
-
-import { useIotaClient } from '@iota/dapp-kit';
-import type { IotaSystemStateSummary, IotaValidatorSummary } from '@iota/iota-sdk/client';
-import { useQuery } from '@tanstack/react-query';
-
-export type IotaSystemStateSummaryCompat = {
-    activeValidators: IotaValidatorSummary[];
-    committeeMembers: IotaValidatorSummary[];
-    atRiskValidators: [string, string][];
-    epoch: string;
-    epochDurationMs: string;
-    epochStartTimestampMs: string;
-    pendingActiveValidatorsId: string;
-    pendingActiveValidatorsSize: string;
-    protocolVersion: string;
-    inactivePoolsId: string;
-};
-
-export function useGetLatestIotaSystemState() {
-    const iotaClient = useIotaClient();
-    return useQuery<IotaSystemStateSummaryCompat>({
-        queryKey: ['system', 'state'],
-        async queryFn() {
-            const protocolConfig = await iotaClient.getProtocolConfig();
-            const isV2Supported = Number(protocolConfig.maxSupportedProtocolVersion) >= 5;
-
-            const iotaSystemStateSummary: IotaSystemStateSummary = isV2Supported
-                ? await iotaClient.getLatestIotaSystemStateV2()
-                : {
-                      V1: await iotaClient.getLatestIotaSystemState(),
-                  };
-
-            return 'V2' in iotaSystemStateSummary
-                ? {
-                      activeValidators: iotaSystemStateSummary.V2.activeValidators,
-                      committeeMembers: iotaSystemStateSummary.V2.committeeMembers.map(
-                          (committeeMemberIndex) =>
-                              iotaSystemStateSummary.V2.activeValidators[
-                                  Number(committeeMemberIndex)
-                              ],
-                      ),
-                      atRiskValidators: iotaSystemStateSummary.V2.atRiskValidators,
-                      epoch: iotaSystemStateSummary.V2.epoch,
-                      epochDurationMs: iotaSystemStateSummary.V2.epochDurationMs,
-                      epochStartTimestampMs: iotaSystemStateSummary.V2.epochStartTimestampMs,
-                      pendingActiveValidatorsId:
-                          iotaSystemStateSummary.V2.pendingActiveValidatorsId,
-                      pendingActiveValidatorsSize:
-                          iotaSystemStateSummary.V2.pendingActiveValidatorsSize,
-                      protocolVersion: iotaSystemStateSummary.V2.protocolVersion,
-                      inactivePoolsId: iotaSystemStateSummary.V2.inactivePoolsId,
-                  }
-                : {
-                      activeValidators: iotaSystemStateSummary.V1.activeValidators,
-                      committeeMembers: iotaSystemStateSummary.V1.activeValidators,
-                      atRiskValidators: iotaSystemStateSummary.V1.atRiskValidators,
-                      epoch: iotaSystemStateSummary.V1.epoch,
-                      epochDurationMs: iotaSystemStateSummary.V1.epochDurationMs,
-                      epochStartTimestampMs: iotaSystemStateSummary.V1.epochStartTimestampMs,
-                      pendingActiveValidatorsId:
-                          iotaSystemStateSummary.V1.pendingActiveValidatorsId,
-                      pendingActiveValidatorsSize:
-                          iotaSystemStateSummary.V1.pendingActiveValidatorsSize,
-                      protocolVersion: iotaSystemStateSummary.V1.protocolVersion,
-                      inactivePoolsId: iotaSystemStateSummary.V1.inactivePoolsId,
-                  };
-        },
-    });
-}
diff --git a/apps/core/src/hooks/useGetStakingValidatorDetails.ts b/apps/core/src/hooks/useGetStakingValidatorDetails.ts
index e11bc624723..7a41b852989 100644
--- a/apps/core/src/hooks/useGetStakingValidatorDetails.ts
+++ b/apps/core/src/hooks/useGetStakingValidatorDetails.ts
@@ -14,7 +14,7 @@ import {
     getValidatorCommission,
 } from '../utils';
 import { useFormatCoin } from './useFormatCoin';
-import { useGetLatestIotaSystemState } from './useGetLatestIotaSystemState';
+import { useIotaClientQuery } from '@iota/dapp-kit';
 
 interface UseGetStakingValidatorDetailsArgs {
     accountAddress: string | null;
@@ -29,7 +29,7 @@ export function useGetStakingValidatorDetails({
     validatorAddress,
     unstake,
 }: UseGetStakingValidatorDetailsArgs) {
-    const systemDataResult = useGetLatestIotaSystemState();
+    const systemDataResult = useIotaClientQuery('getLatestIotaSystemState');
 
     const delegatedStakeDataResult = useGetDelegatedStake({
         address: accountAddress || '',
diff --git a/apps/core/src/hooks/useGetTimeBeforeEpochNumber.ts b/apps/core/src/hooks/useGetTimeBeforeEpochNumber.ts
index a2365c32998..2aefe684ac3 100644
--- a/apps/core/src/hooks/useGetTimeBeforeEpochNumber.ts
+++ b/apps/core/src/hooks/useGetTimeBeforeEpochNumber.ts
@@ -2,12 +2,12 @@
 // Modifications Copyright (c) 2024 IOTA Stiftung
 // SPDX-License-Identifier: Apache-2.0
 
-import { useGetLatestIotaSystemState } from './useGetLatestIotaSystemState';
+import { useIotaClientQuery } from '@iota/dapp-kit';
 
 // Get time between current epoch and specified epoch
 // Get the period between the current epoch and next epoch
 export function useGetTimeBeforeEpochNumber(epoch: number) {
-    const data = useGetLatestIotaSystemState();
+    const data = useIotaClientQuery('getLatestIotaSystemState');
     // Current epoch
     const currentEpoch = Number(data.data?.epoch || 0);
     const currentEpochStartTime = Number(data.data?.epochStartTimestampMs || 0);
diff --git a/apps/explorer/src/components/activity/EpochsActivityTable.tsx b/apps/explorer/src/components/activity/EpochsActivityTable.tsx
index 954a98ee34b..6054ff72b77 100644
--- a/apps/explorer/src/components/activity/EpochsActivityTable.tsx
+++ b/apps/explorer/src/components/activity/EpochsActivityTable.tsx
@@ -3,8 +3,8 @@
 // SPDX-License-Identifier: Apache-2.0
 
 import { InfoBox, InfoBoxStyle, InfoBoxType, Select, SelectSize } from '@iota/apps-ui-kit';
-import { useIotaClient, useIotaClientInfiniteQuery } from '@iota/dapp-kit';
-import { useCursorPagination, useGetLatestIotaSystemState } from '@iota/core';
+import { useIotaClient, useIotaClientInfiniteQuery, useIotaClientQuery } from '@iota/dapp-kit';
+import { useCursorPagination } from '@iota/core';
 import { Warning } from '@iota/apps-ui-icons';
 import { useQuery } from '@tanstack/react-query';
 import { useState } from 'react';
@@ -27,7 +27,7 @@ export function EpochsActivityTable({
 }: EpochsActivityTableProps): JSX.Element {
     const [limit, setLimit] = useState(initialLimit);
     const client = useIotaClient();
-    const { data: systemState } = useGetLatestIotaSystemState();
+    const { data: systemState } = useIotaClientQuery('getLatestIotaSystemState');
     const { data: count } = useQuery({
         queryKey: ['epochs', 'current'],
         queryFn: async () => client.getCurrentEpoch(),
diff --git a/apps/explorer/src/components/network/NetworkSelector.tsx b/apps/explorer/src/components/network/NetworkSelector.tsx
index f7b57ce306a..05f56f46e5e 100644
--- a/apps/explorer/src/components/network/NetworkSelector.tsx
+++ b/apps/explorer/src/components/network/NetworkSelector.tsx
@@ -13,7 +13,6 @@ import { type NetworkId, getAllNetworks } from '@iota/iota-sdk/client';
 import { Button, ButtonSize, ButtonType, Dropdown, ListItem } from '@iota/apps-ui-kit';
 import { ArrowDown, CheckmarkFilled } from '@iota/apps-ui-icons';
 import { Transition } from '@headlessui/react';
-import { useGetLatestIotaSystemState } from '@iota/core';
 
 interface NetworkOption {
     id: string;
@@ -23,7 +22,7 @@ interface NetworkOption {
 export function NetworkSelector(): JSX.Element {
     const elementRef = useRef<HTMLDivElement>(null);
     const [network, setNetwork] = useContext(NetworkContext);
-    const { data } = useGetLatestIotaSystemState();
+    const { data } = useIotaClientQuery('getLatestIotaSystemState');
     const { data: binaryVersion } = useIotaClientQuery('getRpcApiVersion');
     const [isDropdownOpen, setIsDropdownOpen] = useState(false);
 
diff --git a/apps/explorer/src/components/top-validators-card/TopValidatorsCard.tsx b/apps/explorer/src/components/top-validators-card/TopValidatorsCard.tsx
index f4bdc0d2312..8f7ef6cad38 100644
--- a/apps/explorer/src/components/top-validators-card/TopValidatorsCard.tsx
+++ b/apps/explorer/src/components/top-validators-card/TopValidatorsCard.tsx
@@ -16,7 +16,7 @@ import {
 } from '@iota/apps-ui-kit';
 import { ErrorBoundary } from '../error-boundary/ErrorBoundary';
 import { Warning } from '@iota/apps-ui-icons';
-import { useGetLatestIotaSystemState } from '@iota/core';
+import { useIotaClientQuery } from '@iota/dapp-kit';
 
 const NUMBER_OF_VALIDATORS = 10;
 
@@ -26,7 +26,7 @@ type TopValidatorsCardProps = {
 };
 
 export function TopValidatorsCard({ limit, showIcon }: TopValidatorsCardProps): JSX.Element {
-    const { data, isPending, isSuccess, isError } = useGetLatestIotaSystemState();
+    const { data, isPending, isSuccess, isError } = useIotaClientQuery('getLatestIotaSystemState');
 
     const topCommitteeMembers =
         data?.committeeMembers.slice(0, limit || NUMBER_OF_VALIDATORS) ?? [];
diff --git a/apps/explorer/src/hooks/useSearch.ts b/apps/explorer/src/hooks/useSearch.ts
index b5fb4ab19e5..8ec8f2e8ac9 100644
--- a/apps/explorer/src/hooks/useSearch.ts
+++ b/apps/explorer/src/hooks/useSearch.ts
@@ -2,9 +2,8 @@
 // Modifications Copyright (c) 2024 IOTA Stiftung
 // SPDX-License-Identifier: Apache-2.0
 
-import { type IotaSystemStateSummaryCompat, useGetLatestIotaSystemState } from '@iota/core';
-import { useIotaClient } from '@iota/dapp-kit';
-import type { IotaClient } from '@iota/iota-sdk/client';
+import { useIotaClient, useIotaClientQuery } from '@iota/dapp-kit';
+import type { IotaClient, LatestIotaSystemStateSummary } from '@iota/iota-sdk/client';
 import {
     isValidTransactionDigest,
     isValidIotaAddress,
@@ -97,7 +96,7 @@ const getResultsForAddress = async (client: IotaClient, query: string): Promise<
 
 // Query for validator by pool id or iota address.
 const getResultsForValidatorByPoolIdOrIotaAddress = async (
-    systemStateSummary: IotaSystemStateSummaryCompat | null,
+    systemStateSummary: LatestIotaSystemStateSummary | null,
     query: string,
 ): Promise<Results | null> => {
     const normalized = normalizeIotaObjectId(query);
@@ -125,7 +124,7 @@ const getResultsForValidatorByPoolIdOrIotaAddress = async (
 
 export function useSearch(query: string): UseQueryResult<Results, Error> {
     const client = useIotaClient();
-    const { data: systemStateSummary } = useGetLatestIotaSystemState();
+    const { data: systemStateSummary } = useIotaClientQuery('getLatestIotaSystemState');
 
     return useQuery<Results, Error>({
         // eslint-disable-next-line @tanstack/query/exhaustive-deps
diff --git a/apps/explorer/src/pages/epochs/EpochDetail.tsx b/apps/explorer/src/pages/epochs/EpochDetail.tsx
index 732750f5630..3dc6deee4ff 100644
--- a/apps/explorer/src/pages/epochs/EpochDetail.tsx
+++ b/apps/explorer/src/pages/epochs/EpochDetail.tsx
@@ -28,9 +28,10 @@ import { TokenStats } from './stats/TokenStats';
 import { EpochTopStats } from './stats/EpochTopStats';
 import { getEpochStorageFundFlow } from '~/lib/utils';
 import { Warning } from '@iota/apps-ui-icons';
-import { useGetLatestIotaSystemState, VALIDATORS_EVENTS_QUERY } from '@iota/core';
+import { VALIDATORS_EVENTS_QUERY } from '@iota/core';
 import { useEndOfEpochTransactionFromCheckpoint } from '~/hooks/useEndOfEpochTransactionFromCheckpoint';
 import { type IotaEvent } from '@iota/iota-sdk/src/client';
+import { useIotaClientQuery } from '@iota/dapp-kit';
 
 enum EpochTabs {
     Checkpoints = 'checkpoints',
@@ -41,7 +42,7 @@ export function EpochDetail() {
     const [activeTabId, setActiveTabId] = useState(EpochTabs.Checkpoints);
     const { id } = useParams();
     const enhancedRpc = useEnhancedRpcClient();
-    const { data: systemState } = useGetLatestIotaSystemState();
+    const { data: systemState } = useIotaClientQuery('getLatestIotaSystemState');
     const { data, isPending, isError } = useQuery({
         queryKey: ['epoch', id],
         queryFn: async () =>
diff --git a/apps/explorer/src/pages/epochs/stats/ValidatorStatus.tsx b/apps/explorer/src/pages/epochs/stats/ValidatorStatus.tsx
index 792138d0b2f..c7910ccc20f 100644
--- a/apps/explorer/src/pages/epochs/stats/ValidatorStatus.tsx
+++ b/apps/explorer/src/pages/epochs/stats/ValidatorStatus.tsx
@@ -3,11 +3,12 @@
 // SPDX-License-Identifier: Apache-2.0
 
 import { IOTA_PRIMITIVES_COLOR_PALETTE, Panel, Title } from '@iota/apps-ui-kit';
-import { Theme, useGetLatestIotaSystemState, useTheme } from '@iota/core';
+import { Theme, useTheme } from '@iota/core';
+import { useIotaClientQuery } from '@iota/dapp-kit';
 import { RingChart, RingChartLegend } from '~/components/ui';
 
 export function ValidatorStatus(): JSX.Element | null {
-    const { data } = useGetLatestIotaSystemState();
+    const { data } = useIotaClientQuery('getLatestIotaSystemState');
     const { theme } = useTheme();
 
     if (!data) return null;
diff --git a/apps/explorer/src/pages/epochs/utils.ts b/apps/explorer/src/pages/epochs/utils.ts
index 39590a4d1d5..8afeab198d6 100644
--- a/apps/explorer/src/pages/epochs/utils.ts
+++ b/apps/explorer/src/pages/epochs/utils.ts
@@ -2,8 +2,9 @@
 // Modifications Copyright (c) 2024 IOTA Stiftung
 // SPDX-License-Identifier: Apache-2.0
 
+import { useTimeAgo } from '@iota/core';
+import { useIotaClientQuery } from '@iota/dapp-kit';
 import { useEffect } from 'react';
-import { useGetLatestIotaSystemState, useTimeAgo } from '@iota/core';
 
 interface EpochProgress {
     epoch?: number;
@@ -14,7 +15,7 @@ interface EpochProgress {
 }
 
 export function useEpochProgress(suffix: string = 'left'): EpochProgress {
-    const { data, refetch } = useGetLatestIotaSystemState();
+    const { data, refetch } = useIotaClientQuery('getLatestIotaSystemState');
     const start = data?.epochStartTimestampMs ? Number(data.epochStartTimestampMs) : undefined;
     const duration = data?.epochDurationMs ? Number(data.epochDurationMs) : undefined;
     const end = start !== undefined && duration !== undefined ? start + duration : undefined;
diff --git a/apps/explorer/src/pages/validator/ValidatorDetails.tsx b/apps/explorer/src/pages/validator/ValidatorDetails.tsx
index fe84b8b3e5e..b552afa8443 100644
--- a/apps/explorer/src/pages/validator/ValidatorDetails.tsx
+++ b/apps/explorer/src/pages/validator/ValidatorDetails.tsx
@@ -2,12 +2,7 @@
 // Modifications Copyright (c) 2024 IOTA Stiftung
 // SPDX-License-Identifier: Apache-2.0
 
-import {
-    type IotaSystemStateSummaryCompat,
-    useGetLatestIotaSystemState,
-    useGetValidatorsApy,
-    useGetValidatorsEvents,
-} from '@iota/core';
+import { useGetValidatorsApy, useGetValidatorsEvents } from '@iota/core';
 import { useParams } from 'react-router-dom';
 import { InactiveValidators, PageLayout, ValidatorMeta, ValidatorStats } from '~/components';
 import { VALIDATOR_LOW_STAKE_GRACE_PERIOD } from '~/lib/constants';
@@ -15,13 +10,13 @@ import { getValidatorMoveEvent } from '~/lib/utils';
 import { InfoBox, InfoBoxStyle, InfoBoxType, LoadingIndicator } from '@iota/apps-ui-kit';
 import { Warning } from '@iota/apps-ui-icons';
 import { useQuery } from '@tanstack/react-query';
-import type { IotaClient } from '@iota/iota-sdk/client';
+import type { IotaClient, LatestIotaSystemStateSummary } from '@iota/iota-sdk/client';
 import { normalizeIotaAddress, toB64 } from '@iota/iota-sdk/utils';
-import { useIotaClient } from '@iota/dapp-kit';
+import { useIotaClient, useIotaClientQuery } from '@iota/dapp-kit';
 import { z } from 'zod';
 
 const getAtRiskRemainingEpochs = (
-    data: IotaSystemStateSummaryCompat | undefined,
+    data: LatestIotaSystemStateSummary | undefined,
     validatorId: string | undefined,
 ): number | null => {
     if (!data || !validatorId) return null;
@@ -128,8 +123,9 @@ const getInactiveValidatorsData = async (
 
 function ValidatorDetails(): JSX.Element {
     const { id } = useParams();
-    const { data: systemStateData, isLoading: isLoadingSystemState } =
-        useGetLatestIotaSystemState();
+    const { data: systemStateData, isLoading: isLoadingSystemState } = useIotaClientQuery(
+        'getLatestIotaSystemState',
+    );
 
     const iotaClient = useIotaClient();
 
diff --git a/apps/explorer/src/pages/validators/Validators.tsx b/apps/explorer/src/pages/validators/Validators.tsx
index b892b08e85a..e6bb6590fa0 100644
--- a/apps/explorer/src/pages/validators/Validators.tsx
+++ b/apps/explorer/src/pages/validators/Validators.tsx
@@ -11,7 +11,6 @@ import {
     useGetValidatorsApy,
     useGetValidatorsEvents,
     useMultiGetObjects,
-    useGetLatestIotaSystemState,
 } from '@iota/core';
 import {
     Badge,
@@ -36,7 +35,7 @@ import { sanitizePendingValidators } from '~/lib';
 import { IOTA_TYPE_ARG, normalizeIotaAddress } from '@iota/iota-sdk/utils';
 
 function ValidatorPageResult(): JSX.Element {
-    const { data, isPending, isSuccess, isError } = useGetLatestIotaSystemState();
+    const { data, isPending, isSuccess, isError } = useIotaClientQuery('getLatestIotaSystemState');
     const activeValidators = data?.activeValidators;
     const numberOfValidators = activeValidators?.length || 0;
 
diff --git a/apps/wallet-dashboard/app/(protected)/(feature-controlled)/vesting/page.tsx b/apps/wallet-dashboard/app/(protected)/(feature-controlled)/vesting/page.tsx
index 57f9b295b1e..473536bc3c9 100644
--- a/apps/wallet-dashboard/app/(protected)/(feature-controlled)/vesting/page.tsx
+++ b/apps/wallet-dashboard/app/(protected)/(feature-controlled)/vesting/page.tsx
@@ -49,9 +49,13 @@ import {
     GAS_BALANCE_TOO_LOW_ID,
     MIN_NUMBER_IOTA_TO_STAKE,
     NOT_ENOUGH_BALANCE_ID,
-    useGetLatestIotaSystemState,
 } from '@iota/core';
-import { useCurrentAccount, useIotaClient, useSignAndExecuteTransaction } from '@iota/dapp-kit';
+import {
+    useCurrentAccount,
+    useIotaClient,
+    useIotaClientQuery,
+    useSignAndExecuteTransaction,
+} from '@iota/dapp-kit';
 import { IotaValidatorSummary } from '@iota/iota-sdk/client';
 import { Calendar, StarHex, Warning } from '@iota/apps-ui-icons';
 import { useState } from 'react';
@@ -67,7 +71,7 @@ export default function VestingDashboardPage(): JSX.Element {
     const account = useCurrentAccount();
     const address = account?.address || '';
     const iotaClient = useIotaClient();
-    const { data: system } = useGetLatestIotaSystemState();
+    const { data: system } = useIotaClientQuery('getLatestIotaSystemState');
     const [isVestingScheduleDialogOpen, setIsVestingScheduleDialogOpen] = useState(false);
     const { mutateAsync: signAndExecuteTransaction } = useSignAndExecuteTransaction();
     const { theme } = useTheme();
diff --git a/apps/wallet-dashboard/app/(protected)/staking/page.tsx b/apps/wallet-dashboard/app/(protected)/staking/page.tsx
index c5ef8250208..c25fb0e6bfc 100644
--- a/apps/wallet-dashboard/app/(protected)/staking/page.tsx
+++ b/apps/wallet-dashboard/app/(protected)/staking/page.tsx
@@ -34,16 +34,15 @@ import {
     DELEGATED_STAKES_QUERY_STALE_TIME,
     StakedCard,
     useFormatCoin,
-    useGetLatestIotaSystemState,
 } from '@iota/core';
-import { useCurrentAccount, useIotaClient } from '@iota/dapp-kit';
+import { useCurrentAccount, useIotaClient, useIotaClientQuery } from '@iota/dapp-kit';
 import { Warning } from '@iota/apps-ui-icons';
 import { useMemo } from 'react';
 import { IotaSignAndExecuteTransactionOutput } from '@iota/wallet-standard';
 
 function StakingDashboardPage(): React.JSX.Element {
     const account = useCurrentAccount();
-    const { data: system } = useGetLatestIotaSystemState();
+    const { data: system } = useIotaClientQuery('getLatestIotaSystemState');
     const committeeMembers = system?.committeeMembers;
     const iotaClient = useIotaClient();
 
diff --git a/apps/wallet-dashboard/components/StakeRewardsPanel.tsx b/apps/wallet-dashboard/components/StakeRewardsPanel.tsx
index 012fbd7267d..ab510684804 100644
--- a/apps/wallet-dashboard/components/StakeRewardsPanel.tsx
+++ b/apps/wallet-dashboard/components/StakeRewardsPanel.tsx
@@ -2,13 +2,8 @@
 // SPDX-License-Identifier: Apache-2.0
 
 import { Divider, KeyValueInfo, Panel } from '@iota/apps-ui-kit';
-import {
-    TimeUnit,
-    useFormatCoin,
-    useGetLatestIotaSystemState,
-    useGetTimeBeforeEpochNumber,
-    useTimeAgo,
-} from '@iota/core';
+import { TimeUnit, useFormatCoin, useGetTimeBeforeEpochNumber, useTimeAgo } from '@iota/core';
+import { useIotaClientQuery } from '@iota/dapp-kit';
 
 interface StakeRewardsPanelProps {
     stakingRewards: string | number | undefined;
@@ -20,7 +15,7 @@ export function StakeRewardsPanel({
     totalStaked,
     isTimelocked,
 }: StakeRewardsPanelProps) {
-    const { epoch = '0' } = useGetLatestIotaSystemState()?.data || {};
+    const { epoch = '0' } = useIotaClientQuery('getLatestIotaSystemState')?.data || {};
     const [rewards, symbol] = useFormatCoin({ balance: stakingRewards ?? 0 });
     const [stakedBalance] = useFormatCoin({ balance: totalStaked });
     const [stakedAndRewards] = useFormatCoin({
diff --git a/apps/wallet-dashboard/components/dialogs/staking/StakeDialog.tsx b/apps/wallet-dashboard/components/dialogs/staking/StakeDialog.tsx
index 07848d239c7..fc2f38ffb2b 100644
--- a/apps/wallet-dashboard/components/dialogs/staking/StakeDialog.tsx
+++ b/apps/wallet-dashboard/components/dialogs/staking/StakeDialog.tsx
@@ -10,10 +10,9 @@ import {
     useBalance,
     createValidationSchema,
     MIN_NUMBER_IOTA_TO_STAKE,
-    useGetLatestIotaSystemState,
 } from '@iota/core';
 import { FormikProvider, useFormik } from 'formik';
-import { useCurrentAccount } from '@iota/dapp-kit';
+import { useCurrentAccount, useIotaClientQuery } from '@iota/dapp-kit';
 import { IOTA_TYPE_ARG } from '@iota/iota-sdk/utils';
 import { Dialog } from '@iota/apps-ui-kit';
 import { DetailsView } from './views';
@@ -79,7 +78,7 @@ export function StakeDialog({
         validateOnMount: true,
     });
 
-    const { data: systemState } = useGetLatestIotaSystemState();
+    const { data: systemState } = useIotaClientQuery('getLatestIotaSystemState');
     const validatorAddresses = (systemState?.activeValidators ?? []).map(
         (validator) => validator.iotaAddress,
     );
diff --git a/apps/wallet-dashboard/components/dialogs/staking/views/EnterAmountDialogLayout.tsx b/apps/wallet-dashboard/components/dialogs/staking/views/EnterAmountDialogLayout.tsx
index 4ee4b119d01..26b6b677bcc 100644
--- a/apps/wallet-dashboard/components/dialogs/staking/views/EnterAmountDialogLayout.tsx
+++ b/apps/wallet-dashboard/components/dialogs/staking/views/EnterAmountDialogLayout.tsx
@@ -1,13 +1,7 @@
 // Copyright (c) 2024 IOTA Stiftung
 // SPDX-License-Identifier: Apache-2.0
 
-import {
-    CoinFormat,
-    useFormatCoin,
-    useGetLatestIotaSystemState,
-    useStakeTxnInfo,
-    Validator,
-} from '@iota/core';
+import { CoinFormat, useFormatCoin, useStakeTxnInfo, Validator } from '@iota/core';
 import {
     Button,
     ButtonType,
@@ -25,6 +19,7 @@ import { Field, type FieldProps, useFormikContext } from 'formik';
 import { Exclamation, Loader } from '@iota/apps-ui-icons';
 import { StakedInfo } from './StakedInfo';
 import { DialogLayout, DialogLayoutBody, DialogLayoutFooter } from '../../layout';
+import { useIotaClientQuery } from '@iota/dapp-kit';
 import React from 'react';
 
 interface FormValues {
@@ -60,7 +55,7 @@ export function EnterAmountDialogLayout({
     handleStake,
     renderInputAction,
 }: EnterAmountDialogLayoutProps): JSX.Element {
-    const { data: system } = useGetLatestIotaSystemState();
+    const { data: system } = useIotaClientQuery('getLatestIotaSystemState');
     const { values, errors } = useFormikContext<FormValues>();
     const amount = values.amount;
 
diff --git a/apps/wallet-dashboard/components/dialogs/unstake/views/UnstakeTimelockedObjectsView.tsx b/apps/wallet-dashboard/components/dialogs/unstake/views/UnstakeTimelockedObjectsView.tsx
index bf934730731..ca30f364be8 100644
--- a/apps/wallet-dashboard/components/dialogs/unstake/views/UnstakeTimelockedObjectsView.tsx
+++ b/apps/wallet-dashboard/components/dialogs/unstake/views/UnstakeTimelockedObjectsView.tsx
@@ -3,7 +3,7 @@
 
 import { StakeRewardsPanel, ValidatorStakingData } from '@/components';
 import { DialogLayout, DialogLayoutBody, DialogLayoutFooter } from '../../layout';
-import { useGetLatestIotaSystemState, Validator } from '@iota/core';
+import { Validator } from '@iota/core';
 import { useNewUnstakeTimelockedTransaction } from '@/hooks';
 import { Collapsible, TimeUnit, useFormatCoin, useTimeAgo, toast } from '@iota/core';
 import {
@@ -23,7 +23,11 @@ import {
     InfoBoxStyle,
     InfoBoxType,
 } from '@iota/apps-ui-kit';
-import { useCurrentAccount, useSignAndExecuteTransaction } from '@iota/dapp-kit';
+import {
+    useCurrentAccount,
+    useIotaClientQuery,
+    useSignAndExecuteTransaction,
+} from '@iota/dapp-kit';
 import { IotaSignAndExecuteTransactionOutput } from '@iota/wallet-standard';
 import { ampli } from '@/lib/utils/analytics';
 import { Warning } from '@iota/apps-ui-icons';
@@ -47,7 +51,7 @@ export function UnstakeTimelockedObjectsView({
     const reductionSize = useRef(0);
     const [isMaxTransactionSizeError, setIsMaxTransactionSizeError] = useState(false);
     const activeAddress = useCurrentAccount()?.address ?? '';
-    const { data: systemState } = useGetLatestIotaSystemState();
+    const { data: systemState } = useIotaClientQuery('getLatestIotaSystemState');
 
     const stakes = (() => {
         if (isMaxTransactionSizeError) {
diff --git a/apps/wallet-dashboard/hooks/useIsValidatorCommitteeMember.ts b/apps/wallet-dashboard/hooks/useIsValidatorCommitteeMember.ts
index 0f68f35ec16..fcb92777ff6 100644
--- a/apps/wallet-dashboard/hooks/useIsValidatorCommitteeMember.ts
+++ b/apps/wallet-dashboard/hooks/useIsValidatorCommitteeMember.ts
@@ -1,11 +1,11 @@
 // Copyright (c) 2025 IOTA Stiftung
 // SPDX-License-Identifier: Apache-2.0
 
+import { useIotaClientQuery } from '@iota/dapp-kit';
 import { useCallback } from 'react';
-import { useGetLatestIotaSystemState } from '@iota/core';
 
 export function useIsValidatorCommitteeMember() {
-    const { data: systemState } = useGetLatestIotaSystemState();
+    const { data: systemState } = useIotaClientQuery('getLatestIotaSystemState');
 
     const isCommitteeMember = useCallback(
         (address: string) =>
diff --git a/apps/wallet/src/ui/app/staking/delegation-detail/DelegationDetailCard.tsx b/apps/wallet/src/ui/app/staking/delegation-detail/DelegationDetailCard.tsx
index 0cd3093c895..d15c6105dbc 100644
--- a/apps/wallet/src/ui/app/staking/delegation-detail/DelegationDetailCard.tsx
+++ b/apps/wallet/src/ui/app/staking/delegation-detail/DelegationDetailCard.tsx
@@ -17,7 +17,6 @@ import {
     Validator,
     getValidatorCommission,
     toast,
-    useGetLatestIotaSystemState,
 } from '@iota/core';
 import { Network, type StakeObject } from '@iota/iota-sdk/client';
 import { NANOS_PER_IOTA, IOTA_TYPE_ARG } from '@iota/iota-sdk/utils';
@@ -39,6 +38,7 @@ import {
 } from '@iota/apps-ui-kit';
 import { useNavigate } from 'react-router-dom';
 import { Warning } from '@iota/apps-ui-icons';
+import { useIotaClientQuery } from '@iota/dapp-kit';
 
 interface DelegationDetailCardProps {
     validatorAddress: string;
@@ -51,7 +51,7 @@ export function DelegationDetailCard({ validatorAddress, stakedId }: DelegationD
         data: system,
         isPending: loadingValidators,
         isError: errorValidators,
-    } = useGetLatestIotaSystemState();
+    } = useIotaClientQuery('getLatestIotaSystemState');
 
     const accountAddress = useActiveAddress();
 
diff --git a/apps/wallet/src/ui/app/staking/validators/SelectValidatorCard.tsx b/apps/wallet/src/ui/app/staking/validators/SelectValidatorCard.tsx
index ac30e7dc080..7479199f756 100644
--- a/apps/wallet/src/ui/app/staking/validators/SelectValidatorCard.tsx
+++ b/apps/wallet/src/ui/app/staking/validators/SelectValidatorCard.tsx
@@ -3,17 +3,13 @@
 // SPDX-License-Identifier: Apache-2.0
 
 import { ampli } from '_src/shared/analytics/ampli';
-import {
-    calculateStakeShare,
-    useGetLatestIotaSystemState,
-    useGetValidatorsApy,
-    Validator,
-} from '@iota/core';
+import { calculateStakeShare, useGetValidatorsApy, Validator } from '@iota/core';
 import cl from 'clsx';
 import { useCallback, useMemo, useState } from 'react';
 import { Button, InfoBox, InfoBoxStyle, InfoBoxType, LoadingIndicator } from '@iota/apps-ui-kit';
 import { useNavigate } from 'react-router-dom';
 import { Warning } from '@iota/apps-ui-icons';
+import { useIotaClientQuery } from '@iota/dapp-kit';
 
 type Validator = {
     name: string;
@@ -28,7 +24,7 @@ export function SelectValidatorCard() {
 
     const navigate = useNavigate();
 
-    const { data, isPending, isError, error } = useGetLatestIotaSystemState();
+    const { data, isPending, isError, error } = useIotaClientQuery('getLatestIotaSystemState');
     const { data: rollingAverageApys } = useGetValidatorsApy();
 
     const selectValidator = (validator: Validator) => {
diff --git a/apps/wallet/src/ui/app/staking/validators/ValidatorsCard.tsx b/apps/wallet/src/ui/app/staking/validators/ValidatorsCard.tsx
index d71f4cf4c7e..7a03711246d 100644
--- a/apps/wallet/src/ui/app/staking/validators/ValidatorsCard.tsx
+++ b/apps/wallet/src/ui/app/staking/validators/ValidatorsCard.tsx
@@ -12,7 +12,6 @@ import {
     DELEGATED_STAKES_QUERY_STALE_TIME,
     useFormatCoin,
     StakedCard,
-    useGetLatestIotaSystemState,
 } from '@iota/core';
 import { useMemo } from 'react';
 import { useActiveAddress } from '_hooks';
@@ -29,6 +28,7 @@ import {
 } from '@iota/apps-ui-kit';
 import { useNavigate } from 'react-router-dom';
 import { Warning } from '@iota/apps-ui-icons';
+import { useIotaClientQuery } from '@iota/dapp-kit';
 
 export function ValidatorsCard() {
     const accountAddress = useActiveAddress();
@@ -44,7 +44,7 @@ export function ValidatorsCard() {
     });
     const navigate = useNavigate();
 
-    const { data: system } = useGetLatestIotaSystemState();
+    const { data: system } = useIotaClientQuery('getLatestIotaSystemState');
     const committeeMembers = system?.committeeMembers;
     const delegatedStake = delegatedStakeData ? formatDelegatedStake(delegatedStakeData) : [];
 
diff --git a/sdk/graphql-transport/README.md b/sdk/graphql-transport/README.md
index cfffce0e963..abee38d4a36 100644
--- a/sdk/graphql-transport/README.md
+++ b/sdk/graphql-transport/README.md
@@ -68,7 +68,7 @@ If an unsupported parameter is used, the request will error, or fallback to JSON
   - missing `id` for `events`
 - `getStakes` and `getStakesByIds`
   - missing `validatorAddress`
-- `getLatestIotaSystemState`
+- `getLatestIotaSystemState` and `getLatestIotaSystemStateV2`
   - missing `stakingPoolMappingsId`, `inactivePoolsId`, `pendingActiveValidatorsId`,
     `validatorCandidatesId`
   - missing `reportRecords` on validators
@@ -96,7 +96,7 @@ Some may require multiple requests to properly resolve:
   - may require additional requests to load all `friends`, `functions`, and `structs`
 - `getCheckpoint` and `getCheckpoints`,
   - may require additional requests to load all `transactionBlocks` and `validators`
-- `getLatestIotaSystemState`, `getCurrentEpoch`, `getValidatorsApy` and `getCommitteeInfo`:
+- `getLatestIotaSystemState`,`getLatestIotaSystemStateV2`, `getCurrentEpoch`, `getValidatorsApy` and `getCommitteeInfo`:
   - may require additional requests to load all `validators`
 
 ### Pagination
diff --git a/sdk/graphql-transport/src/methods.ts b/sdk/graphql-transport/src/methods.ts
index 9c51156bb39..d1a368999ea 100644
--- a/sdk/graphql-transport/src/methods.ts
+++ b/sdk/graphql-transport/src/methods.ts
@@ -775,7 +775,7 @@ export const RPC_METHODS: {
 
         return mapGraphQLStakeToRpcStake(stakes);
     },
-    async getLatestIotaSystemState(transport) {
+    async getLatestIotaSystemStateV2(transport) {
         const systemState = await transport.graphqlQuery(
             {
                 query: GetLatestIotaSystemStateDocument,
@@ -830,61 +830,75 @@ export const RPC_METHODS: {
         }
 
         return {
-            activeValidators: systemState.validatorSet?.activeValidators?.nodes.map(
-                mapGraphQlValidatorToRpcValidator,
-            )!,
-            committeeMembers: systemState.validatorSet?.committeeMembers?.nodes?.map(
-                mapGraphQlValidatorToRpcValidator,
-            )!,
-            atRiskValidators: systemState.validatorSet?.activeValidators.nodes
-                ?.filter((validator) => validator.atRisk)
-                .map((validator) => [validator.address.address!, validator.atRisk!.toString()])!,
-            epoch: String(systemState.epochId),
-            epochDurationMs: String(
-                new Date(systemState.endTimestamp).getTime() -
-                    new Date(systemState.startTimestamp).getTime(),
-            ),
-            epochStartTimestampMs: String(new Date(systemState.startTimestamp).getTime()),
-            inactivePoolsSize: String(systemState.validatorSet?.inactivePoolsSize),
-            iotaTotalSupply: String(systemState.iotaTotalSupply),
-            iotaTreasuryCapId: String(systemState.iotaTreasuryCapId),
-            maxValidatorCount: String(systemState.systemParameters?.maxValidatorCount),
-            minValidatorCount: String(systemState.systemParameters?.minValidatorCount),
-            minValidatorJoiningStake: String(
-                systemState.systemParameters?.minValidatorJoiningStake,
-            ),
-            pendingActiveValidatorsSize: String(
-                systemState.validatorSet?.pendingActiveValidatorsSize,
-            ),
-            pendingRemovals:
-                systemState.validatorSet?.pendingRemovals?.map((idx) => String(idx)) ?? [],
-            protocolVersion: String(systemState.protocolConfigs?.protocolVersion),
-            referenceGasPrice: String(systemState.referenceGasPrice),
-            safeMode: systemState.safeMode?.enabled!,
-            safeModeComputationRewards: String(systemState.safeMode?.gasSummary?.computationCost),
-            safeModeNonRefundableStorageFee: String(
-                systemState.safeMode?.gasSummary?.nonRefundableStorageFee,
-            ),
-            safeModeStorageRebates: String(systemState.safeMode?.gasSummary?.storageRebate),
-            safeModeStorageCharges: String(systemState.safeMode?.gasSummary?.storageCost),
-            stakingPoolMappingsSize: String(systemState.validatorSet?.stakingPoolMappingsSize),
-            storageFundNonRefundableBalance: String(systemState.storageFund?.nonRefundableBalance),
-            storageFundTotalObjectStorageRebates: String(
-                systemState.storageFund?.totalObjectStorageRebates,
-            ),
-            systemStateVersion: String(systemState.systemStateVersion),
-            totalStake: systemState.validatorSet?.totalStake,
-            validatorCandidatesSize: systemState.validatorSet?.validatorCandidatesSize?.toString()!,
-            validatorLowStakeGracePeriod:
-                systemState.systemParameters?.validatorLowStakeGracePeriod,
-            validatorLowStakeThreshold: systemState.systemParameters?.validatorLowStakeThreshold,
-            validatorReportRecords: [], // TODO
-            validatorVeryLowStakeThreshold:
-                systemState.systemParameters?.validatorVeryLowStakeThreshold,
-            validatorCandidatesId: systemState.validatorSet?.validatorCandidatesId,
-            inactivePoolsId: systemState.validatorSet?.inactivePoolsId,
-            pendingActiveValidatorsId: systemState.validatorSet?.pendingActiveValidatorsId,
-            stakingPoolMappingsId: systemState.validatorSet?.stakingPoolMappingsId,
+            V2: {
+                activeValidators: systemState.validatorSet?.activeValidators?.nodes.map(
+                    mapGraphQlValidatorToRpcValidator,
+                )!,
+                committeeMembers: systemState.validatorSet?.committeeMembers?.nodes?.map(
+                    (_, index) => index.toString(),
+                )!,
+                atRiskValidators: systemState.validatorSet?.activeValidators.nodes
+                    ?.filter((validator) => validator.atRisk)
+                    .map((validator) => [
+                        validator.address.address!,
+                        validator.atRisk!.toString(),
+                    ])!,
+                epoch: String(systemState.epochId),
+                epochDurationMs: String(
+                    new Date(systemState.endTimestamp).getTime() -
+                        new Date(systemState.startTimestamp).getTime(),
+                ),
+                epochStartTimestampMs: String(new Date(systemState.startTimestamp).getTime()),
+                inactivePoolsSize: String(systemState.validatorSet?.inactivePoolsSize),
+                iotaTotalSupply: String(systemState.iotaTotalSupply),
+                iotaTreasuryCapId: String(systemState.iotaTreasuryCapId),
+                maxValidatorCount: String(systemState.systemParameters?.maxValidatorCount),
+                minValidatorCount: String(systemState.systemParameters?.minValidatorCount),
+                minValidatorJoiningStake: String(
+                    systemState.systemParameters?.minValidatorJoiningStake,
+                ),
+                pendingActiveValidatorsSize: String(
+                    systemState.validatorSet?.pendingActiveValidatorsSize,
+                ),
+                pendingRemovals:
+                    systemState.validatorSet?.pendingRemovals?.map((idx) => String(idx)) ?? [],
+                protocolVersion: String(systemState.protocolConfigs?.protocolVersion),
+                referenceGasPrice: String(systemState.referenceGasPrice),
+                safeMode: systemState.safeMode?.enabled!,
+                safeModeComputationCharges: String(
+                    systemState.safeMode?.gasSummary?.computationCost,
+                ),
+                safeModeComputationChargesBurned: String(
+                    systemState.safeMode?.gasSummary?.computationCostBurned,
+                ),
+                safeModeNonRefundableStorageFee: String(
+                    systemState.safeMode?.gasSummary?.nonRefundableStorageFee,
+                ),
+                safeModeStorageRebates: String(systemState.safeMode?.gasSummary?.storageRebate),
+                safeModeStorageCharges: String(systemState.safeMode?.gasSummary?.storageCost),
+                stakingPoolMappingsSize: String(systemState.validatorSet?.stakingPoolMappingsSize),
+                storageFundNonRefundableBalance: String(
+                    systemState.storageFund?.nonRefundableBalance,
+                ),
+                storageFundTotalObjectStorageRebates: String(
+                    systemState.storageFund?.totalObjectStorageRebates,
+                ),
+                systemStateVersion: String(systemState.systemStateVersion),
+                totalStake: systemState.validatorSet?.totalStake,
+                validatorCandidatesSize:
+                    systemState.validatorSet?.validatorCandidatesSize?.toString()!,
+                validatorLowStakeGracePeriod:
+                    systemState.systemParameters?.validatorLowStakeGracePeriod,
+                validatorLowStakeThreshold:
+                    systemState.systemParameters?.validatorLowStakeThreshold,
+                validatorReportRecords: [], // TODO
+                validatorVeryLowStakeThreshold:
+                    systemState.systemParameters?.validatorVeryLowStakeThreshold,
+                validatorCandidatesId: systemState.validatorSet?.validatorCandidatesId,
+                inactivePoolsId: systemState.validatorSet?.inactivePoolsId,
+                pendingActiveValidatorsId: systemState.validatorSet?.pendingActiveValidatorsId,
+                stakingPoolMappingsId: systemState.validatorSet?.stakingPoolMappingsId,
+            },
         };
     },
     async queryEvents(transport, [query, cursor, limit, descending]) {
diff --git a/sdk/typescript/src/client/client.ts b/sdk/typescript/src/client/client.ts
index 815e36cf5fc..484cb8e69ca 100644
--- a/sdk/typescript/src/client/client.ts
+++ b/sdk/typescript/src/client/client.ts
@@ -90,6 +90,7 @@ import type {
     DelegatedTimelockedStake,
     GetTimelockedStakesByIdsParams,
     IotaSystemStateSummaryV1,
+    LatestIotaSystemStateSummary,
     ParticipationMetrics,
     IotaCirculatingSupply,
     GetDynamicFieldObjectV2Params,
@@ -552,8 +553,9 @@ export class IotaClient {
     /**
      * Return the latest IOTA system state object on networks supporting protocol version `< 5`.
      * These are networks with node software release version `< 0.11`.
+     * @deprecated Use `getLatestIotaSystemState` instead.
      */
-    async getLatestIotaSystemState(): Promise<IotaSystemStateSummaryV1> {
+    async getLatestIotaSystemStateV1(): Promise<IotaSystemStateSummaryV1> {
         return await this.transport.request({
             method: 'iotax_getLatestIotaSystemState',
             params: [],
@@ -563,14 +565,55 @@ export class IotaClient {
     /**
      * Return the latest IOTA system state object on networks supporting protocol version `>= 5`.
      * These are networks with node software release version `>= 0.11`.
+     *
+     * You probably want to use `getLatestIotaSystemState` instead to prevent issues with future deprecations
+     * or in case the node does not support protocol version `>= 5`.
      */
     async getLatestIotaSystemStateV2(): Promise<IotaSystemStateSummary> {
-        return await this.transport.request({
+        return await this.transport.request<IotaSystemStateSummary>({
             method: 'iotax_getLatestIotaSystemStateV2',
             params: [],
         });
     }
 
+    /**
+     * Return the latest supported IOTA system state object.
+     *
+     * This returns a backwards-compatible system state object that dynamically uses the V1 or V2
+     * depending on the protocol version supported by the node. This method will continue to be supported
+     * as more protocol versions are released with changes to the system state.
+     *
+     * This is quite useful in case your app does not know in advance what node is it going to be using,
+     * this way you as developer dont need to handle each possible system state variant,
+     * this is already handled by this method.
+     */
+    async getLatestIotaSystemState(): Promise<LatestIotaSystemStateSummary> {
+        const protocolConfig = await this.getProtocolConfig();
+        const isV2Supported = Number(protocolConfig.maxSupportedProtocolVersion) >= 5;
+
+        const iotaSystemStateSummary: IotaSystemStateSummary = isV2Supported
+            ? await this.getLatestIotaSystemStateV2()
+            : {
+                  V1: await this.getLatestIotaSystemStateV1(),
+              };
+
+        return 'V2' in iotaSystemStateSummary
+            ? {
+                  ...iotaSystemStateSummary.V2,
+                  committeeMembers: iotaSystemStateSummary.V2.committeeMembers.map(
+                      (committeeMemberIndex) =>
+                          iotaSystemStateSummary.V2.activeValidators[Number(committeeMemberIndex)],
+                  ),
+              }
+            : {
+                  ...iotaSystemStateSummary.V1,
+                  committeeMembers: iotaSystemStateSummary.V1.activeValidators,
+                  safeModeComputationCharges: iotaSystemStateSummary.V1.safeModeComputationRewards,
+                  safeModeComputationChargesBurned:
+                      iotaSystemStateSummary.V1.safeModeComputationRewards,
+              };
+    }
+
     /**
      * Get events for a given query criteria
      */
diff --git a/sdk/typescript/src/client/types/chain.ts b/sdk/typescript/src/client/types/chain.ts
index 79e96127eb7..75a101e96b6 100644
--- a/sdk/typescript/src/client/types/chain.ts
+++ b/sdk/typescript/src/client/types/chain.ts
@@ -11,7 +11,9 @@ import type {
     IotaCallArg,
     IotaMoveNormalizedModule,
     IotaParsedData,
+    IotaSystemStateSummaryV2,
     IotaTransaction,
+    IotaValidatorSummary,
 } from './generated.js';
 
 export type EpochPage = {
@@ -58,3 +60,7 @@ export type ProgrammableTransaction = {
     transactions: IotaTransaction[];
     inputs: IotaCallArg[];
 };
+
+export type LatestIotaSystemStateSummary = {
+    committeeMembers: IotaValidatorSummary[];
+} & Omit<IotaSystemStateSummaryV2, 'committeeMembers'>;


Reviews:
user: login: evavirseda
body: tiny nits :pray: 
maybe we should update the README too? also thinking the skipped test could have a clearer name, wdyt?
state: CHANGES_REQUESTED
author_association: MEMBER
submitted_at: 2025-04-08T11:51:19Z
user: login: begonaalvarezd
body: nits
state: CHANGES_REQUESTED
author_association: MEMBER
submitted_at: 2025-04-11T10:49:47Z
user: login: marc2332
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-14T05:40:18Z
user: login: evavirseda
body: cis are failing
state: CHANGES_REQUESTED
author_association: MEMBER
submitted_at: 2025-04-14T06:59:41Z
user: login: evavirseda
state: APPROVED
author_association: MEMBER
submitted_at: 2025-04-21T06:48:36Z
user: login: msarcev
state: APPROVED
author_association: COLLABORATOR
submitted_at: 2025-04-23T13:54:09Z
user: login: begonaalvarezd
state: APPROVED
author_association: MEMBER
submitted_at: 2025-04-23T15:09:48Z

Review comments:
diff_hunk: @@ -491,8 +491,8 @@ describe('GraphQL IotaClient compatibility', () => {
     });
 
     test.skip('getLatestIotaSystemState', async () => {
path: sdk/graphql-transport/test/compatibility.test.ts
user: login: evavirseda
body: ```suggestion
    test.skip('getSupportedIotaSystemState', async () => {
```
created_at: 2025-04-08T11:47:35Z
author_association: MEMBER
diff_hunk: @@ -0,0 +1,8 @@
+---
+'@iota/graphql-transport': minor
+'@iota/iota-sdk': minor
+'@iota/apps-ui-kit': minor
+'@iota/kiosk': minor
+---
+
+Add `getSupportedIotaSystemState`
path: .changeset/itchy-eyes-smoke.md
user: login: begonaalvarezd
body: We should also mention that this deprecated `getLatestIotaSystemState` in favor of `getLatestIotaSystemStateV2`
created_at: 2025-04-11T10:44:29Z
author_association: MEMBER
diff_hunk: @@ -551,14 +553,46 @@ export class IotaClient {
     /**
      * Return the latest IOTA system state object on networks supporting protocol version `>= 5`.
      * These are networks with node software release version `>= 0.11`.
+     *
+     * You probably want to use `getSupportedIotaSystemState` instead.
path: sdk/typescript/src/client/client.ts
user: login: begonaalvarezd
body: I would say "you probably want to use" but rather explain the other exists and why is it useful
created_at: 2025-04-11T10:46:55Z
author_association: MEMBER
diff_hunk: @@ -551,14 +553,46 @@ export class IotaClient {
     /**
      * Return the latest IOTA system state object on networks supporting protocol version `>= 5`.
      * These are networks with node software release version `>= 0.11`.
+     *
+     * You probably want to use `getSupportedIotaSystemState` instead.
      */
     async getLatestIotaSystemStateV2(): Promise<IotaSystemStateSummary> {
-        return await this.transport.request({
+        return await this.transport.request<IotaSystemStateSummary>({
             method: 'iotax_getLatestIotaSystemStateV2',
             params: [],
         });
     }
 
+    /**
+     * Return the latest supported IOTA system state object.
path: sdk/typescript/src/client/client.ts
user: login: begonaalvarezd
body: I would explaina bit more what this does and why is useful, i would personally be much more verbose here
created_at: 2025-04-11T10:47:08Z
author_association: MEMBER
diff_hunk: @@ -68,7 +68,7 @@ If an unsupported parameter is used, the request will error, or fallback to JSON
   - missing `id` for `events`
 - `getStakes` and `getStakesByIds`
   - missing `validatorAddress`
-- `getLatestIotaSystemState`
+- `getSupportedIotaSystemState`
path: sdk/graphql-transport/README.md
user: login: begonaalvarezd
body: would you remove `getLatestIotaSystemState` and replace it by this? maybe we could keep both, and actually i think we might be missing here the v2 version?
created_at: 2025-04-11T10:48:51Z
author_association: MEMBER
diff_hunk: @@ -96,7 +96,7 @@ Some may require multiple requests to properly resolve:
   - may require additional requests to load all `friends`, `functions`, and `structs`
 - `getCheckpoint` and `getCheckpoints`,
   - may require additional requests to load all `transactionBlocks` and `validators`
-- `getLatestIotaSystemState`, `getCurrentEpoch`, `getValidatorsApy` and `getCommitteeInfo`:
+- `getSupportedIotaSystemState`, `getCurrentEpoch`, `getValidatorsApy` and `getCommitteeInfo`:
path: sdk/graphql-transport/README.md
user: login: begonaalvarezd
body: same comment as above
created_at: 2025-04-11T10:49:03Z
author_association: MEMBER
diff_hunk: @@ -68,7 +68,7 @@ If an unsupported parameter is used, the request will error, or fallback to JSON
   - missing `id` for `events`
 - `getStakes` and `getStakesByIds`
   - missing `validatorAddress`
-- `getLatestIotaSystemState`
+- `getSupportedIotaSystemState`
path: sdk/graphql-transport/README.md
user: login: marc2332
body: I would not remove `getLatestIotaSystemState`, but maybe we could rename it to `getLatestIotaSystemStateV1`, wdyt?
created_at: 2025-04-14T05:40:17Z
author_association: CONTRIBUTOR

PR comments:
user: login: vercel[bot]
created_at: 2025-04-07T14:23:37Z
body: [vc]: #vLzGGPG4aExCwgaGCvqDuS7TysfkpVeLgDNjp2Su1R0=:eyJpc01vbm9yZXBvIjp0cnVlLCJ0eXBlIjoiZ2l0aHViIiwicHJvamVjdHMiOlt7Im5hbWUiOiJhcHBzLXVpLWtpdCIsInJvb3REaXJlY3RvcnkiOiJhcHBzL3VpLWtpdC8iLCJpbnNwZWN0b3JVcmwiOiJodHRwczovL3ZlcmNlbC5jb20vaW90YS9hcHBzLXVpLWtpdC84TGtBcUQ4RThkUEh2cmU0NkgxM1o4N1dBR3JOIiwicHJldmlld1VybCI6ImFwcHMtdWkta2l0LWdpdC10b29saW5nLXNkay1pbnRyb2R1Y2Utc3VwcG9ydGVkLWlvLWZlODdkMi1pb3RhMS52ZXJjZWwuYXBwIiwibmV4dENvbW1pdFN0YXR1cyI6IklHTk9SRUQiLCJsaXZlRmVlZGJhY2siOnsicmVzb2x2ZWQiOjAsInVucmVzb2x2ZWQiOjAsInRvdGFsIjowLCJsaW5rIjoiYXBwcy11aS1raXQtZ2l0LXRvb2xpbmctc2RrLWludHJvZHVjZS1zdXBwb3J0ZWQtaW8tZmU4N2QyLWlvdGExLnZlcmNlbC5hcHAifX0seyJuYW1lIjoid2FsbGV0LWRhc2hib2FyZCIsInJvb3REaXJlY3RvcnkiOiJhcHBzL3dhbGxldC1kYXNoYm9hcmQiLCJpbnNwZWN0b3JVcmwiOiJodHRwczovL3ZlcmNlbC5jb20vaW90YS93YWxsZXQtZGFzaGJvYXJkL0I2c2hoNURVRnROanp3MW14bkgyU1RjZ0p4NTUiLCJwcmV2aWV3VXJsIjoid2FsbGV0LWRhc2hib2FyZC1naXQtdG9vbGluZy1zZGstaW50cm9kdWNlLXN1cHBvcnQtMTlkNDBlLWlvdGExLnZlcmNlbC5hcHAiLCJuZXh0Q29tbWl0U3RhdHVzIjoiSUdOT1JFRCIsImxpdmVGZWVkYmFjayI6eyJyZXNvbHZlZCI6MCwidW5yZXNvbHZlZCI6MCwidG90YWwiOjAsImxpbmsiOiJ3YWxsZXQtZGFzaGJvYXJkLWdpdC10b29saW5nLXNkay1pbnRyb2R1Y2Utc3VwcG9ydC0xOWQ0MGUtaW90YTEudmVyY2VsLmFwcCJ9fSx7Im5hbWUiOiJyZWJhc2VkLWV4cGxvcmVyIiwicm9vdERpcmVjdG9yeSI6ImFwcHMvZXhwbG9yZXIiLCJpbnNwZWN0b3JVcmwiOiJodHRwczovL3ZlcmNlbC5jb20vaW90YS9yZWJhc2VkLWV4cGxvcmVyLzI3VG9teTZaYWJ2ZEF4aEpQS0pORnppTmVaODMiLCJwcmV2aWV3VXJsIjoicmViYXNlZC1leHBsb3Jlci1naXQtdG9vbGluZy1zZGstaW50cm9kdWNlLXN1cHBvcnQtMGQ5YTMwLWlvdGExLnZlcmNlbC5hcHAiLCJuZXh0Q29tbWl0U3RhdHVzIjoiSUdOT1JFRCIsImxpdmVGZWVkYmFjayI6eyJyZXNvbHZlZCI6MCwidW5yZXNvbHZlZCI6MCwidG90YWwiOjAsImxpbmsiOiIifX0seyJuYW1lIjoiYXBwcy1iYWNrZW5kIiwicm9vdERpcmVjdG9yeSI6ImFwcHMvYXBwcy1iYWNrZW5kIiwiaW5zcGVjdG9yVXJsIjoiaHR0cHM6Ly92ZXJjZWwuY29tL2lvdGEvYXBwcy1iYWNrZW5kLzhnUmRZY2ZYQlhZSENiYUh5MWUxekRSVERNZlMiLCJwcmV2aWV3VXJsIjoiYXBwcy1iYWNrZW5kLWdpdC10b29saW5nLXNkay1pbnRyb2R1Y2Utc3VwcG9ydGVkLWktNTEyNzUyLWlvdGExLnZlcmNlbC5hcHAiLCJuZXh0Q29tbWl0U3RhdHVzIjoiSUdOT1JFRCIsImxpdmVGZWVkYmFjayI6eyJyZXNvbHZlZCI6MCwidW5yZXNvbHZlZCI6MCwidG90YWwiOjAsImxpbmsiOiIifX1dfQ==
**The latest updates on your projects**. Learn more about [Vercel for Git ↗︎](https://vercel.link/github-learn-more)


<details><summary>4 Skipped Deployments</summary>

| Name | Status | Preview | Comments | Updated (UTC) |
| :--- | :----- | :------ | :------- | :------ |
| **apps-backend** | ⬜️ Ignored ([Inspect](https://vercel.com/iota/apps-backend/8gRdYcfXBXYHCbaHy1e1zDRTDMfS)) | [Visit Preview](https://apps-backend-git-tooling-sdk-introduce-supported-i-512752-iota1.vercel.app) |  | Apr 23, 2025 2:38pm |
| **apps-ui-kit** | ⬜️ Ignored ([Inspect](https://vercel.com/iota/apps-ui-kit/8LkAqD8E8dPHvre46H13Z87WAGrN)) | [Visit Preview](https://apps-ui-kit-git-tooling-sdk-introduce-supported-io-fe87d2-iota1.vercel.app) | 💬 [**Add feedback**](https://vercel.live/open-feedback/apps-ui-kit-git-tooling-sdk-introduce-supported-io-fe87d2-iota1.vercel.app?via=pr-comment-feedback-link) | Apr 23, 2025 2:38pm |
| **rebased-explorer** | ⬜️ Ignored ([Inspect](https://vercel.com/iota/rebased-explorer/27Tomy6ZabvdAxhJPKJNFziNeZ83)) | [Visit Preview](https://rebased-explorer-git-tooling-sdk-introduce-support-0d9a30-iota1.vercel.app) |  | Apr 23, 2025 2:38pm |
| **wallet-dashboard** | ⬜️ Ignored ([Inspect](https://vercel.com/iota/wallet-dashboard/B6shh5DUFtNjzw1mxnH2STcgJx55)) | [Visit Preview](https://wallet-dashboard-git-tooling-sdk-introduce-support-19d40e-iota1.vercel.app) | 💬 [**Add feedback**](https://vercel.live/open-feedback/wallet-dashboard-git-tooling-sdk-introduce-support-19d40e-iota1.vercel.app?via=pr-comment-feedback-link) | Apr 23, 2025 2:38pm |
</details>





author_association: NONE
user: login: marc2332
created_at: 2025-04-14T07:24:55Z
body: > cis are failing

![image](https://media.tenor.com/c_YU3p6py2AAAAAM/meme-crying.gif)

author_association: CONTRIBUTOR