Skip to content

Commit 1a1d6ce

Browse files
ted-palmerclaude
andauthored
Refactor deposit address transaction tracking to use requests API (#928)
Switch OnrampModal and DepositAddressModalRenderer from polling /intents/status/v2 (via useExecutionStatus) to polling /requests/v2 (via new useDepositAddressStatus hook) using the deposit address as the user param. The new hook wraps useRequests and maps the response to match the existing executionStatus interface, minimizing changes to consuming components. Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
1 parent 1e51455 commit 1a1d6ce

File tree

4 files changed

+117
-25
lines changed

4 files changed

+117
-25
lines changed
Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
import { useMemo } from 'react'
2+
import {
3+
useQuery,
4+
type DefaultError,
5+
type QueryKey
6+
} from '@tanstack/react-query'
7+
import { MAINNET_RELAY_API } from '@relayprotocol/relay-sdk'
8+
import { queryRequests } from './useRequests.js'
9+
10+
export type DepositAddressStatusResponse = {
11+
status?: 'refund' | 'waiting' | 'failure' | 'pending' | 'success'
12+
details?: string
13+
txHashes?: string[]
14+
inTxHashes?: string[]
15+
}
16+
17+
type QueryType = typeof useQuery<
18+
DepositAddressStatusResponse | undefined,
19+
DefaultError,
20+
DepositAddressStatusResponse | undefined,
21+
QueryKey
22+
>
23+
type QueryOptions = Parameters<QueryType>['0']
24+
25+
type DepositAddressStatusParams = {
26+
depositAddress: string
27+
}
28+
29+
export const queryDepositAddressStatus = async function (
30+
baseApiUrl: string = MAINNET_RELAY_API,
31+
options?: DepositAddressStatusParams
32+
): Promise<DepositAddressStatusResponse | undefined> {
33+
if (!options?.depositAddress) {
34+
return undefined
35+
}
36+
37+
const response = await queryRequests(baseApiUrl, {
38+
user: options.depositAddress
39+
})
40+
41+
const request = response?.requests?.[0]
42+
if (!request) {
43+
return undefined
44+
}
45+
46+
return {
47+
status: request.status,
48+
details: request.data?.failReason,
49+
txHashes: request.data?.outTxs
50+
?.map((tx) => tx.hash)
51+
.filter((hash): hash is string => Boolean(hash)),
52+
inTxHashes: request.data?.inTxs
53+
?.map((tx) => tx.hash)
54+
.filter((hash): hash is string => Boolean(hash))
55+
}
56+
}
57+
58+
export default function useDepositAddressStatus(
59+
options?: DepositAddressStatusParams,
60+
baseApiUrl?: string,
61+
queryOptions?: Partial<QueryOptions>
62+
) {
63+
const response = (useQuery as QueryType)({
64+
queryKey: ['useDepositAddressStatus', options?.depositAddress],
65+
queryFn: () => queryDepositAddressStatus(baseApiUrl, options),
66+
enabled: options?.depositAddress !== undefined,
67+
retry: false,
68+
...queryOptions
69+
})
70+
71+
return useMemo(
72+
() =>
73+
({
74+
...response,
75+
data: response.error ? undefined : response.data,
76+
queryKey: ['useDepositAddressStatus', options?.depositAddress]
77+
}) as Omit<ReturnType<QueryType>, 'data'> & {
78+
data?: DepositAddressStatusResponse
79+
queryKey: QueryKey
80+
},
81+
[
82+
response.data,
83+
response.error,
84+
response.isLoading,
85+
response.isFetching,
86+
response.isRefetching,
87+
response.dataUpdatedAt,
88+
options?.depositAddress
89+
]
90+
)
91+
}

packages/hooks/src/index.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,10 @@ export {
1717
default as useExecutionStatus,
1818
queryExecutionStatus
1919
} from './hooks/useExecutionStatus.js'
20+
export {
21+
default as useDepositAddressStatus,
22+
queryDepositAddressStatus
23+
} from './hooks/useDepositAddressStatus.js'
2024
export {
2125
default as useTokenPrice,
2226
queryTokenPrice
@@ -29,3 +33,4 @@ export {
2933
//types
3034
export type { CurrencyList, Currency } from './hooks/useTokenList.js'
3135
export type { QuoteResponse } from './hooks/useQuote.js'
36+
export type { DepositAddressStatusResponse } from './hooks/useDepositAddressStatus.js'

packages/ui/src/components/common/TransactionModal/DepositAddressModalRenderer.tsx

Lines changed: 11 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,9 @@ import {
2121
import type { Token } from '../../../types/index.js'
2222
import {
2323
useRequests,
24-
useExecutionStatus,
25-
queryQuote
24+
useDepositAddressStatus,
25+
queryQuote,
26+
type DepositAddressStatusResponse
2627
} from '@relayprotocol/relay-kit-hooks'
2728
import { useRelayClient } from '../../../hooks/index.js'
2829
import { EventNames } from '../../../constants/events.js'
@@ -62,7 +63,7 @@ export type ChildrenProps = {
6263
fillTime: string
6364
requestId: string | null
6465
depositAddress?: string
65-
executionStatus?: ReturnType<typeof useExecutionStatus>['data']
66+
executionStatus?: DepositAddressStatusResponse
6667
isLoadingTransaction: boolean
6768
toChain?: RelayChain | null
6869
timeEstimate?: { time: number; formattedTime: string }
@@ -83,7 +84,7 @@ type Props = {
8384
children: (props: ChildrenProps) => ReactNode
8485
onSuccess?: (
8586
quote?: Execute | null,
86-
executionStatus?: ReturnType<typeof useExecutionStatus>['data']
87+
executionStatus?: DepositAddressStatusResponse
8788
) => void
8889
onAnalyticEvent?: (eventName: string, data?: any) => void
8990
onSwapError?: (error: string, data?: Execute) => void
@@ -226,22 +227,18 @@ export const DepositAddressModalRenderer: FC<Props> = ({
226227
// eslint-disable-next-line react-hooks/exhaustive-deps
227228
}, [open])
228229

229-
const { data: executionStatus } = useExecutionStatus(
230-
relayClient ? relayClient : undefined,
231-
{
232-
requestId: requestId ?? undefined,
233-
referrer: relayClient?.source
234-
},
235-
undefined,
236-
undefined,
230+
const { data: executionStatus } = useDepositAddressStatus(
231+
depositAddress ? { depositAddress } : undefined,
232+
relayClient?.baseApiUrl,
237233
{
238-
enabled: requestId !== null && open,
234+
enabled: depositAddress !== undefined && open,
239235
refetchInterval(query) {
240236
const observableStates = ['waiting', 'pending']
241237

242238
if (
243239
!query.state.data?.status ||
244-
(requestId && observableStates.includes(query.state.data?.status))
240+
(depositAddress &&
241+
observableStates.includes(query.state.data?.status))
245242
) {
246243
return 1000
247244
}

packages/ui/src/components/widgets/OnrampWidget/modals/OnrampModal.tsx

Lines changed: 10 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ import type { FiatCurrency, Token } from '../../../../types/index.js'
1010
import useRelayClient from '../../../../hooks/useRelayClient.js'
1111
import { EventNames } from '../../../../constants/events.js'
1212
import {
13-
useExecutionStatus,
13+
useDepositAddressStatus,
1414
useQuote,
1515
useRequests,
1616
useTokenPrice
@@ -223,22 +223,21 @@ export const OnrampModal: FC<OnrampModalProps> = ({
223223
[quote]
224224
)
225225

226-
const { data: executionStatus } = useExecutionStatus(
227-
client ? client : undefined,
228-
{
229-
requestId: requestId ?? undefined,
230-
referrer: client?.source
231-
},
232-
undefined,
233-
undefined,
226+
const { data: executionStatus } = useDepositAddressStatus(
227+
depositAddress ? { depositAddress } : undefined,
228+
client?.baseApiUrl,
234229
{
235-
enabled: requestId !== null && step === OnrampStep.Processing && open,
230+
enabled:
231+
depositAddress !== undefined &&
232+
step === OnrampStep.Processing &&
233+
open,
236234
refetchInterval(query) {
237235
const observableStates = ['waiting', 'pending']
238236

239237
if (
240238
!query.state.data?.status ||
241-
(requestId && observableStates.includes(query.state.data?.status))
239+
(depositAddress &&
240+
observableStates.includes(query.state.data?.status))
242241
) {
243242
return 1000
244243
}

0 commit comments

Comments
 (0)