diff --git a/react-app-rewired/headers/csps/chainflip.ts b/react-app-rewired/headers/csps/chainflip.ts index 776467dc639..2c2395b64d7 100644 --- a/react-app-rewired/headers/csps/chainflip.ts +++ b/react-app-rewired/headers/csps/chainflip.ts @@ -1,5 +1,8 @@ import type { Csp } from '../types' export const csp: Csp = { - 'connect-src': ['https://chainflip-broker.io/'], + 'connect-src': [ + 'https://explorer-service-processor.chainflip.io/graphql', + 'https://chainflip-broker.io/', + ], } diff --git a/src/components/MultiHopTrade/components/MultiHopTradeConfirm/components/HopTransactionStep.tsx b/src/components/MultiHopTrade/components/MultiHopTradeConfirm/components/HopTransactionStep.tsx index 6893425d2c2..4caa1f54135 100644 --- a/src/components/MultiHopTrade/components/MultiHopTradeConfirm/components/HopTransactionStep.tsx +++ b/src/components/MultiHopTrade/components/MultiHopTradeConfirm/components/HopTransactionStep.tsx @@ -20,6 +20,7 @@ import { MiddleEllipsis } from 'components/MiddleEllipsis/MiddleEllipsis' import { useGetTradeQuotes } from 'components/MultiHopTrade/hooks/useGetTradeQuotes/useGetTradeQuotes' import { RawText, Text } from 'components/Text' import { getChainAdapterManager } from 'context/PluginProvider/chainAdapterSingleton' +import { useChainflipSwapIdQuery } from 'hooks/queries/useChainflipSwapIdQuery' import { useSafeTxQuery } from 'hooks/queries/useSafeTx' import { useLocaleFormatter } from 'hooks/useLocaleFormatter/useLocaleFormatter' import { bn, bnOrZero } from 'lib/bignumber/bignumber' @@ -118,6 +119,11 @@ export const HopTransactionStep = ({ accountId: sellAssetAccountId, }) + const { data: maybeChainflipSwapId } = useChainflipSwapIdQuery({ + txHash: sellTxHash, + swapperName, + }) + const txLinks = useMemo(() => { const txLinks = [] if (buyTxHash) { @@ -141,6 +147,7 @@ export const HopTransactionStep = ({ defaultExplorerBaseUrl: tradeQuoteStep.sellAsset.explorerTxLink, accountId: sellAssetAccountId, maybeSafeTx, + maybeChainflipSwapId, ...(tradeQuoteStep.source === SwapperName.CowSwap ? { tradeId: sellTxHash, @@ -156,6 +163,7 @@ export const HopTransactionStep = ({ return txLinks }, [ buyTxHash, + maybeChainflipSwapId, maybeSafeTx, sellAssetAccountId, sellTxHash, diff --git a/src/components/MultiHopTrade/components/TradeConfirm/TxLabel.tsx b/src/components/MultiHopTrade/components/TradeConfirm/TxLabel.tsx index 1a94dff907c..ae8dab1943a 100644 --- a/src/components/MultiHopTrade/components/TradeConfirm/TxLabel.tsx +++ b/src/components/MultiHopTrade/components/TradeConfirm/TxLabel.tsx @@ -2,6 +2,7 @@ import { Link } from '@chakra-ui/react' import type { AccountId } from '@shapeshiftoss/caip' import type { SwapSource } from '@shapeshiftoss/swapper' import { MiddleEllipsis } from 'components/MiddleEllipsis/MiddleEllipsis' +import { useChainflipSwapIdQuery } from 'hooks/queries/useChainflipSwapIdQuery' import { useSafeTxQuery } from 'hooks/queries/useSafeTx' import { getTxLink } from 'lib/getTxLink' @@ -23,12 +24,18 @@ export const TxLabel = ({ accountId, }) + const { data: maybeChainflipSwapId } = useChainflipSwapIdQuery({ + txHash, + swapperName, + }) + const txLink = getTxLink({ defaultExplorerBaseUrl: explorerBaseUrl, maybeSafeTx, accountId, name: swapperName, ...(isBuyTxHash ? { txId: txHash } : { tradeId: txHash }), + maybeChainflipSwapId, }) return txLink ? ( diff --git a/src/hooks/queries/useChainflipSwapIdQuery.ts b/src/hooks/queries/useChainflipSwapIdQuery.ts new file mode 100644 index 00000000000..b1f0f0b25bb --- /dev/null +++ b/src/hooks/queries/useChainflipSwapIdQuery.ts @@ -0,0 +1,59 @@ +import type { SwapSource } from '@shapeshiftoss/swapper' +import { SwapperName } from '@shapeshiftoss/swapper' +import type { UseQueryResult } from '@tanstack/react-query' +import { skipToken, useQuery } from '@tanstack/react-query' +import axios from 'axios' + +type UseChainflipSwapIdArgs = { + txHash: string | undefined + swapperName: SwapSource | undefined +} + +type SwapIdResponse = { + data: { + txRefs: { + nodes: { + swap: { + nativeId: string | undefined + } + }[] + } + } +} + +const nativeSwapIdQuery = ` + query GetStringSearchResults($searchString: String!) { + txRefs: allTransactionRefs(filter: {ref: {equalTo: $searchString}}) { + nodes { + swap: swapRequestBySwapRequestId { + nativeId + } + } + } + } +` + +export const useChainflipSwapIdQuery = ({ + txHash, + swapperName, +}: UseChainflipSwapIdArgs): UseQueryResult => { + return useQuery({ + queryKey: ['chainflipSwapId', { txHash }], + queryFn: + txHash && swapperName?.includes(SwapperName.Chainflip) + ? () => + // Yes, this is ugly, just another day in "we're doing inline raw GraphQL queries with http" + // Note, this is undocumented but is actually the exact same query fragment CF UI uses to go from Tx hash to swap ID (though only a fragment of it, + // actually stripped out to the bare minimum here vs. cf UI) + axios.post('https://explorer-service-processor.chainflip.io/graphql', { + query: nativeSwapIdQuery, + variables: { + searchString: txHash, + }, + }) + : skipToken, + select: ({ data: { data } }) => data.txRefs.nodes[0].swap.nativeId, + // Long-poll until swap by initiating Txid is indexed + refetchInterval: 10_000, + }) +} diff --git a/src/lib/getTxLink.ts b/src/lib/getTxLink.ts index 3fb672c7626..fd0d9dcc7b5 100644 --- a/src/lib/getTxLink.ts +++ b/src/lib/getTxLink.ts @@ -2,6 +2,11 @@ import type { AccountId } from '@shapeshiftoss/caip' import { fromAccountId } from '@shapeshiftoss/caip' import type { SafeTxInfo, SwapSource } from '@shapeshiftoss/swapper' import { SwapperName } from '@shapeshiftoss/swapper' +import { + CHAINFLIP_BOOST_SWAP_SOURCE, + CHAINFLIP_DCA_BOOST_SWAP_SOURCE, + CHAINFLIP_DCA_SWAP_SOURCE, +} from '@shapeshiftoss/swapper/dist/swappers/ChainflipSwapper/constants' import { THORCHAIN_LONGTAIL_STREAMING_SWAP_SOURCE, THORCHAIN_LONGTAIL_SWAP_SOURCE, @@ -33,6 +38,7 @@ type GetTxLink = GetTxBaseUrl & ({ txId: string; tradeId?: never } | { tradeId: string; txId?: never }) & { accountId: AccountId | undefined maybeSafeTx: SafeTxInfo | undefined + maybeChainflipSwapId?: string | undefined } export const getTxBaseUrl = ({ name, defaultExplorerBaseUrl, isOrder }: GetTxBaseUrl): string => { @@ -46,6 +52,11 @@ export const getTxBaseUrl = ({ name, defaultExplorerBaseUrl, isOrder }: GetTxBas case THORCHAIN_LONGTAIL_SWAP_SOURCE: case THORCHAIN_LONGTAIL_STREAMING_SWAP_SOURCE: return 'https://viewblock.io/thorchain/tx/' + case SwapperName.Chainflip: + case CHAINFLIP_BOOST_SWAP_SOURCE: + case CHAINFLIP_DCA_SWAP_SOURCE: + case CHAINFLIP_DCA_BOOST_SWAP_SOURCE: + return 'https://scan.chainflip.io/swaps/' default: return defaultExplorerBaseUrl } @@ -58,6 +69,7 @@ export const getTxLink = ({ tradeId, maybeSafeTx, accountId, + maybeChainflipSwapId, }: GetTxLink): string => { const isSafeTxHash = maybeSafeTx?.isSafeTxHash const id = txId ?? tradeId @@ -72,6 +84,13 @@ export const getTxLink = ({ case THORCHAIN_LONGTAIL_SWAP_SOURCE: case THORCHAIN_LONGTAIL_STREAMING_SWAP_SOURCE: return `${baseUrl}${id.replace(/^0x/, '')}` + case SwapperName.Chainflip: + case CHAINFLIP_BOOST_SWAP_SOURCE: + case CHAINFLIP_DCA_SWAP_SOURCE: + case CHAINFLIP_DCA_BOOST_SWAP_SOURCE: + return maybeChainflipSwapId + ? `${baseUrl}${maybeChainflipSwapId}` + : `${defaultExplorerBaseUrl}${id}` default: return `${baseUrl}${id}` }