diff --git a/packages/hooks/src/hooks/useDepositAddressStatus.ts b/packages/hooks/src/hooks/useDepositAddressStatus.ts new file mode 100644 index 000000000..6cb20593a --- /dev/null +++ b/packages/hooks/src/hooks/useDepositAddressStatus.ts @@ -0,0 +1,91 @@ +import { useMemo } from 'react' +import { + useQuery, + type DefaultError, + type QueryKey +} from '@tanstack/react-query' +import { MAINNET_RELAY_API } from '@relayprotocol/relay-sdk' +import { queryRequests } from './useRequests.js' + +export type DepositAddressStatusResponse = { + status?: 'refund' | 'waiting' | 'failure' | 'pending' | 'success' + details?: string + txHashes?: string[] + inTxHashes?: string[] +} + +type QueryType = typeof useQuery< + DepositAddressStatusResponse | undefined, + DefaultError, + DepositAddressStatusResponse | undefined, + QueryKey +> +type QueryOptions = Parameters['0'] + +type DepositAddressStatusParams = { + depositAddress: string +} + +export const queryDepositAddressStatus = async function ( + baseApiUrl: string = MAINNET_RELAY_API, + options?: DepositAddressStatusParams +): Promise { + if (!options?.depositAddress) { + return undefined + } + + const response = await queryRequests(baseApiUrl, { + user: options.depositAddress + }) + + const request = response?.requests?.[0] + if (!request) { + return undefined + } + + return { + status: request.status, + details: request.data?.failReason, + txHashes: request.data?.outTxs + ?.map((tx) => tx.hash) + .filter((hash): hash is string => Boolean(hash)), + inTxHashes: request.data?.inTxs + ?.map((tx) => tx.hash) + .filter((hash): hash is string => Boolean(hash)) + } +} + +export default function useDepositAddressStatus( + options?: DepositAddressStatusParams, + baseApiUrl?: string, + queryOptions?: Partial +) { + const response = (useQuery as QueryType)({ + queryKey: ['useDepositAddressStatus', options?.depositAddress], + queryFn: () => queryDepositAddressStatus(baseApiUrl, options), + enabled: options?.depositAddress !== undefined, + retry: false, + ...queryOptions + }) + + return useMemo( + () => + ({ + ...response, + data: response.error ? undefined : response.data, + queryKey: ['useDepositAddressStatus', options?.depositAddress] + }) as Omit, 'data'> & { + data?: DepositAddressStatusResponse + queryKey: QueryKey + }, + [ + response.data, + response.error, + response.isLoading, + response.isFetching, + response.isRefetching, + response.dataUpdatedAt, + options?.depositAddress + ] + ) +} diff --git a/packages/hooks/src/index.ts b/packages/hooks/src/index.ts index dc7cc1401..dafffe7a1 100644 --- a/packages/hooks/src/index.ts +++ b/packages/hooks/src/index.ts @@ -17,6 +17,10 @@ export { default as useExecutionStatus, queryExecutionStatus } from './hooks/useExecutionStatus.js' +export { + default as useDepositAddressStatus, + queryDepositAddressStatus +} from './hooks/useDepositAddressStatus.js' export { default as useTokenPrice, queryTokenPrice @@ -29,3 +33,4 @@ export { //types export type { CurrencyList, Currency } from './hooks/useTokenList.js' export type { QuoteResponse } from './hooks/useQuote.js' +export type { DepositAddressStatusResponse } from './hooks/useDepositAddressStatus.js' diff --git a/packages/ui/src/components/common/TransactionModal/DepositAddressModalRenderer.tsx b/packages/ui/src/components/common/TransactionModal/DepositAddressModalRenderer.tsx index 71c5ce88c..ba86998ca 100644 --- a/packages/ui/src/components/common/TransactionModal/DepositAddressModalRenderer.tsx +++ b/packages/ui/src/components/common/TransactionModal/DepositAddressModalRenderer.tsx @@ -21,8 +21,9 @@ import { import type { Token } from '../../../types/index.js' import { useRequests, - useExecutionStatus, - queryQuote + useDepositAddressStatus, + queryQuote, + type DepositAddressStatusResponse } from '@relayprotocol/relay-kit-hooks' import { useRelayClient } from '../../../hooks/index.js' import { EventNames } from '../../../constants/events.js' @@ -62,7 +63,7 @@ export type ChildrenProps = { fillTime: string requestId: string | null depositAddress?: string - executionStatus?: ReturnType['data'] + executionStatus?: DepositAddressStatusResponse isLoadingTransaction: boolean toChain?: RelayChain | null timeEstimate?: { time: number; formattedTime: string } @@ -83,7 +84,7 @@ type Props = { children: (props: ChildrenProps) => ReactNode onSuccess?: ( quote?: Execute | null, - executionStatus?: ReturnType['data'] + executionStatus?: DepositAddressStatusResponse ) => void onAnalyticEvent?: (eventName: string, data?: any) => void onSwapError?: (error: string, data?: Execute) => void @@ -226,22 +227,18 @@ export const DepositAddressModalRenderer: FC = ({ // eslint-disable-next-line react-hooks/exhaustive-deps }, [open]) - const { data: executionStatus } = useExecutionStatus( - relayClient ? relayClient : undefined, - { - requestId: requestId ?? undefined, - referrer: relayClient?.source - }, - undefined, - undefined, + const { data: executionStatus } = useDepositAddressStatus( + depositAddress ? { depositAddress } : undefined, + relayClient?.baseApiUrl, { - enabled: requestId !== null && open, + enabled: depositAddress !== undefined && open, refetchInterval(query) { const observableStates = ['waiting', 'pending'] if ( !query.state.data?.status || - (requestId && observableStates.includes(query.state.data?.status)) + (depositAddress && + observableStates.includes(query.state.data?.status)) ) { return 1000 } diff --git a/packages/ui/src/components/widgets/OnrampWidget/modals/OnrampModal.tsx b/packages/ui/src/components/widgets/OnrampWidget/modals/OnrampModal.tsx index 54baa639a..b0d8af898 100644 --- a/packages/ui/src/components/widgets/OnrampWidget/modals/OnrampModal.tsx +++ b/packages/ui/src/components/widgets/OnrampWidget/modals/OnrampModal.tsx @@ -10,7 +10,7 @@ import type { FiatCurrency, Token } from '../../../../types/index.js' import useRelayClient from '../../../../hooks/useRelayClient.js' import { EventNames } from '../../../../constants/events.js' import { - useExecutionStatus, + useDepositAddressStatus, useQuote, useRequests, useTokenPrice @@ -223,22 +223,21 @@ export const OnrampModal: FC = ({ [quote] ) - const { data: executionStatus } = useExecutionStatus( - client ? client : undefined, - { - requestId: requestId ?? undefined, - referrer: client?.source - }, - undefined, - undefined, + const { data: executionStatus } = useDepositAddressStatus( + depositAddress ? { depositAddress } : undefined, + client?.baseApiUrl, { - enabled: requestId !== null && step === OnrampStep.Processing && open, + enabled: + depositAddress !== undefined && + step === OnrampStep.Processing && + open, refetchInterval(query) { const observableStates = ['waiting', 'pending'] if ( !query.state.data?.status || - (requestId && observableStates.includes(query.state.data?.status)) + (depositAddress && + observableStates.includes(query.state.data?.status)) ) { return 1000 }