Skip to content

Commit ed78002

Browse files
refactor(tangle-dapp): Claim migration and liquid staking improvements (#3091)
Co-authored-by: Claude Opus 4.5 <[email protected]>
1 parent 4cd1545 commit ed78002

File tree

8 files changed

+831
-24
lines changed

8 files changed

+831
-24
lines changed

apps/tangle-dapp/src/pages/claim/migration/hooks/useClaimEligibility.ts

Lines changed: 725 additions & 7 deletions
Large diffs are not rendered by default.

apps/tangle-dapp/src/pages/claim/migration/hooks/useGenerateProof.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -197,7 +197,7 @@ async function pollForProof(
197197
for (let attempt = 0; attempt < maxAttempts; attempt++) {
198198
await new Promise((resolve) => setTimeout(resolve, interval));
199199

200-
setProgress(`Waiting for proof... (${attempt + 1}/${maxAttempts})`);
200+
setProgress(`Waiting for proof...`);
201201

202202
const response = await fetch(`${PROVER_API_URL}/status/${jobId}`);
203203
const result = await response.json();

apps/tangle-dapp/src/pages/claim/migration/hooks/useSubmitClaim.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -272,6 +272,10 @@ const useSubmitClaim = () => {
272272
? relayerError
273273
: writeError || confirmError;
274274

275+
// Track if we switched from relayer to wallet mode (indicates relayer failure)
276+
const switchedToWalletMode =
277+
defaultSubmissionMode === 'relayer' && submissionMode === 'wallet';
278+
275279
return {
276280
submitClaim,
277281
reset,
@@ -281,6 +285,9 @@ const useSubmitClaim = () => {
281285
isConfirmed: isConfirmedCombined,
282286
error: errorCombined,
283287
contractConfigured: !!migrationAddress,
288+
submissionMode,
289+
isRelayerConfigured: !!CLAIM_RELAYER_URL,
290+
switchedToWalletMode,
284291
};
285292
};
286293

apps/tangle-dapp/src/pages/claim/migration/index.tsx

Lines changed: 29 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -147,6 +147,7 @@ const MigrationClaimPage: FC = () => {
147147
isConfirming,
148148
isConfirmed,
149149
error: submitError,
150+
switchedToWalletMode,
150151
} = useSubmitClaim();
151152

152153
// Validate recipient address
@@ -782,7 +783,6 @@ const MigrationClaimPage: FC = () => {
782783
>
783784
{proofProgress && (
784785
<div className="flex items-center justify-center gap-3 p-3 rounded-lg bg-blue-0 dark:bg-blue-120">
785-
<div className="w-4 h-4 border-2 border-blue-50 border-t-transparent rounded-full animate-spin" />
786786
<Typography variant="body2" className="text-blue-50">
787787
{proofProgress}
788788
</Typography>
@@ -815,6 +815,30 @@ const MigrationClaimPage: FC = () => {
815815
exit={{ opacity: 0, y: -10 }}
816816
className="space-y-3"
817817
>
818+
{switchedToWalletMode && (
819+
<div className="p-4 rounded-xl bg-orange-500/10 border border-orange-500/20">
820+
<div className="flex items-start gap-3">
821+
<Alert className="w-5 h-5 text-orange-400 flex-shrink-0 mt-0.5" />
822+
<div>
823+
<Typography
824+
variant="body2"
825+
fw="semibold"
826+
className="text-orange-400"
827+
>
828+
Wallet Mode Active
829+
</Typography>
830+
<Typography
831+
variant="body2"
832+
className="text-orange-400/80 mt-1"
833+
>
834+
The relayer is unavailable. You will pay gas fees
835+
directly from your wallet.
836+
</Typography>
837+
</div>
838+
</div>
839+
</div>
840+
)}
841+
818842
{submitError && (
819843
<div className="p-4 rounded-xl bg-red-500/10 border border-red-500/20">
820844
<div className="flex items-start gap-3">
@@ -837,6 +861,7 @@ const MigrationClaimPage: FC = () => {
837861
</div>
838862
</div>
839863
)}
864+
840865
<Button
841866
isFullWidth
842867
onClick={handleSubmitClaim}
@@ -845,7 +870,9 @@ const MigrationClaimPage: FC = () => {
845870
isConfirming ? 'Confirming...' : 'Submitting...'
846871
}
847872
>
848-
Claim {Number(formattedAmount).toLocaleString()} TNT
873+
{switchedToWalletMode
874+
? `Claim ${Number(formattedAmount).toLocaleString()} TNT (Pay Gas)`
875+
: `Claim ${Number(formattedAmount).toLocaleString()} TNT`}
849876
</Button>
850877
</motion.div>
851878
)}
Lines changed: 18 additions & 0 deletions
Loading

libs/tangle-shared-ui/src/data/graphql/useDelegator.ts

Lines changed: 17 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,15 @@
66

77
import { useQuery } from '@tanstack/react-query';
88
import { Address } from 'viem';
9-
import { useChainId } from 'wagmi';
9+
import { useAccount, useChainId } from 'wagmi';
1010
import {
1111
executeEnvioGraphQL,
1212
gql,
1313
EnvioNetwork,
14+
getEnvioNetworkFromChainId,
1415
} from '../../utils/executeEnvioGraphQL';
1516
import { useEnvioHealthCheckByChainId } from '../../utils/checkEnvioHealth';
17+
import useNetworkStore from '../../context/useNetworkStore';
1618

1719
// Request status enum
1820
export type RequestStatus = 'PENDING' | 'READY' | 'EXECUTED' | 'CANCELLED';
@@ -278,22 +280,26 @@ export const useDelegator = (
278280
) => {
279281
const { network, enabled = true } = options ?? {};
280282
const chainId = useChainId();
283+
const { isConnected } = useAccount();
284+
const networkChainId = useNetworkStore((store) => store.network2?.evmChainId);
285+
const activeChainId = isConnected ? chainId : (networkChainId ?? chainId);
286+
const resolvedNetwork = network ?? getEnvioNetworkFromChainId(activeChainId);
281287

282288
// Check if indexer is healthy before querying
283289
const { data: isIndexerHealthy, isLoading: isCheckingHealth } =
284-
useEnvioHealthCheckByChainId(chainId);
290+
useEnvioHealthCheckByChainId(activeChainId);
285291

286292
const healthCheckComplete = !isCheckingHealth;
287293
const shouldQuery = healthCheckComplete && isIndexerHealthy === true;
288294

289295
const queryResult = useQuery({
290-
queryKey: ['envio', 'delegator', address, network],
296+
queryKey: ['envio', 'delegator', address, resolvedNetwork],
291297
queryFn: async () => {
292298
if (!address) return null;
293299
const result = await executeEnvioGraphQL<
294300
DelegatorQueryResult,
295301
{ id: string }
296-
>(DELEGATOR_QUERY, { id: address.toLowerCase() }, network);
302+
>(DELEGATOR_QUERY, { id: address.toLowerCase() }, resolvedNetwork);
297303
return result.data.Delegator_by_pk
298304
? parseDelegator(result.data.Delegator_by_pk)
299305
: null;
@@ -412,14 +418,19 @@ export const useDelegatorCount = (options?: {
412418
enabled?: boolean;
413419
}) => {
414420
const { network, enabled = true } = options ?? {};
421+
const chainId = useChainId();
422+
const { isConnected } = useAccount();
423+
const networkChainId = useNetworkStore((store) => store.network2?.evmChainId);
424+
const activeChainId = isConnected ? chainId : (networkChainId ?? chainId);
425+
const resolvedNetwork = network ?? getEnvioNetworkFromChainId(activeChainId);
415426

416427
return useQuery({
417-
queryKey: ['envio', 'delegatorCount', network],
428+
queryKey: ['envio', 'delegatorCount', resolvedNetwork],
418429
queryFn: async () => {
419430
const result = await executeEnvioGraphQL<
420431
DelegatorCountQueryResult,
421432
Record<string, never>
422-
>(DELEGATOR_COUNT_QUERY, {}, network);
433+
>(DELEGATOR_COUNT_QUERY, {}, resolvedNetwork);
423434
return result.data.Delegator?.length ?? 0;
424435
},
425436
enabled,

libs/tangle-shared-ui/src/data/graphql/useOperators.ts

Lines changed: 24 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,14 @@
55

66
import { useQuery } from '@tanstack/react-query';
77
import { Address } from 'viem';
8+
import { useAccount, useChainId } from 'wagmi';
89
import {
910
executeEnvioGraphQL,
1011
gql,
1112
EnvioNetwork,
13+
getEnvioNetworkFromChainId,
1214
} from '../../utils/executeEnvioGraphQL';
15+
import useNetworkStore from '../../context/useNetworkStore';
1316

1417
// Operator status enum matching the Envio schema
1518
export type RestakingOperatorStatus = 'ACTIVE' | 'LEAVING' | 'INACTIVE';
@@ -170,10 +173,15 @@ export const useOperators = (options?: {
170173
offset = 0,
171174
enabled = true,
172175
} = options ?? {};
176+
const chainId = useChainId();
177+
const { isConnected } = useAccount();
178+
const networkChainId = useNetworkStore((store) => store.network2?.evmChainId);
179+
const activeChainId = isConnected ? chainId : (networkChainId ?? chainId);
180+
const resolvedNetwork = network ?? getEnvioNetworkFromChainId(activeChainId);
173181

174182
return useQuery({
175-
queryKey: ['envio', 'operators', network, status, limit, offset],
176-
queryFn: () => fetchOperators(network, status, limit, offset),
183+
queryKey: ['envio', 'operators', resolvedNetwork, status, limit, offset],
184+
queryFn: () => fetchOperators(resolvedNetwork, status, limit, offset),
177185
enabled,
178186
staleTime: 30_000, // 30 seconds
179187
refetchInterval: 30_000,
@@ -188,12 +196,17 @@ export const useOperatorMap = (options?: {
188196
enabled?: boolean;
189197
}) => {
190198
const { network, status, enabled = true } = options ?? {};
199+
const chainId = useChainId();
200+
const { isConnected } = useAccount();
201+
const networkChainId = useNetworkStore((store) => store.network2?.evmChainId);
202+
const activeChainId = isConnected ? chainId : (networkChainId ?? chainId);
203+
const resolvedNetwork = network ?? getEnvioNetworkFromChainId(activeChainId);
191204

192205
return useQuery({
193-
queryKey: ['envio', 'operatorMap', network, status],
206+
queryKey: ['envio', 'operatorMap', resolvedNetwork, status],
194207
queryFn: async () => {
195208
// Use limit/offset for Hasura pagination
196-
const operators = await fetchOperators(network, status, 1000, 0);
209+
const operators = await fetchOperators(resolvedNetwork, status, 1000, 0);
197210
const map = new Map<Address, Operator>();
198211
for (const op of operators) {
199212
map.set(op.id as Address, op);
@@ -216,6 +229,11 @@ export const useOperator = (
216229
},
217230
) => {
218231
const { network, enabled = true } = options ?? {};
232+
const chainId = useChainId();
233+
const { isConnected } = useAccount();
234+
const networkChainId = useNetworkStore((store) => store.network2?.evmChainId);
235+
const activeChainId = isConnected ? chainId : (networkChainId ?? chainId);
236+
const resolvedNetwork = network ?? getEnvioNetworkFromChainId(activeChainId);
219237

220238
const OPERATOR_QUERY = gql`
221239
query Operator($id: String!) {
@@ -236,13 +254,13 @@ export const useOperator = (
236254
`;
237255

238256
return useQuery({
239-
queryKey: ['envio', 'operator', address, network],
257+
queryKey: ['envio', 'operator', address, resolvedNetwork],
240258
queryFn: async () => {
241259
if (!address) return null;
242260
const result = await executeEnvioGraphQL<
243261
{ Operator_by_pk: OperatorsQueryResult['Operator'][number] | null },
244262
{ id: string }
245-
>(OPERATOR_QUERY, { id: address.toLowerCase() }, network);
263+
>(OPERATOR_QUERY, { id: address.toLowerCase() }, resolvedNetwork);
246264

247265
return result.data.Operator_by_pk
248266
? parseOperator(result.data.Operator_by_pk)

libs/tangle-shared-ui/src/data/graphql/useRestakingRound.ts

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,14 @@
44
*/
55

66
import { useQuery } from '@tanstack/react-query';
7+
import { useAccount, useChainId } from 'wagmi';
78
import {
89
executeEnvioGraphQL,
910
gql,
1011
EnvioNetwork,
12+
getEnvioNetworkFromChainId,
1113
} from '../../utils/executeEnvioGraphQL';
14+
import useNetworkStore from '../../context/useNetworkStore';
1215

1316
// Restaking round type
1417
export interface RestakingRound {
@@ -68,10 +71,15 @@ export const useRestakingRound = (options?: {
6871
enabled?: boolean;
6972
}) => {
7073
const { network, enabled = true } = options ?? {};
74+
const chainId = useChainId();
75+
const { isConnected } = useAccount();
76+
const networkChainId = useNetworkStore((store) => store.network2?.evmChainId);
77+
const activeChainId = isConnected ? chainId : (networkChainId ?? chainId);
78+
const resolvedNetwork = network ?? getEnvioNetworkFromChainId(activeChainId);
7179

7280
return useQuery({
73-
queryKey: ['envio', 'restakingRound', network],
74-
queryFn: () => fetchCurrentRound(network),
81+
queryKey: ['envio', 'restakingRound', resolvedNetwork],
82+
queryFn: () => fetchCurrentRound(resolvedNetwork),
7583
enabled,
7684
staleTime: 30_000, // 30 seconds
7785
refetchInterval: 60_000, // Refetch every minute

0 commit comments

Comments
 (0)