-
Notifications
You must be signed in to change notification settings - Fork 71
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: decode warp route information (#176)
Leverage #144, to implement this: Decodes warp route message to show more information about the warp token transfer Fixes #78 - Update the store to include a WarpRouteChainAddressMap, this is a custom type that is of `ChainMap<Record<Address, TokenArgs>>;`, the last string would be the token symbol - Create `parseWarpRouteDetails()` function to decode the information about the warp transfer, a few checks are done to identify if the message is an actual warp route transfer - Upgrade `hyperlane` packages ![image](https://github.com/user-attachments/assets/694019d8-8425-4540-a092-c1a23c8846e1) ![image](https://github.com/user-attachments/assets/24db2578-64d7-41b7-85a5-e216f395c6dd)
- Loading branch information
Showing
15 changed files
with
245 additions
and
67 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
144 changes: 144 additions & 0 deletions
144
src/features/messages/cards/WarpTransferDetailsCard.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,144 @@ | ||
import { MultiProvider } from '@hyperlane-xyz/sdk'; | ||
import { | ||
bytesToProtocolAddress, | ||
fromHexString, | ||
fromWei, | ||
parseWarpRouteMessage, | ||
} from '@hyperlane-xyz/utils'; | ||
import { Tooltip } from '@hyperlane-xyz/widgets'; | ||
import Image from 'next/image'; | ||
import { Card } from '../../../components/layout/Card'; | ||
import SendMoney from '../../../images/icons/send-money.svg'; | ||
import { useMultiProvider, useStore } from '../../../store'; | ||
import { Message, WarpRouteChainAddressMap, WarpRouteDetails } from '../../../types'; | ||
import { logger } from '../../../utils/logger'; | ||
import { getTokenFromWarpRouteChainAddressMap } from '../../../utils/token'; | ||
import { KeyValueRow } from './KeyValueRow'; | ||
|
||
interface Props { | ||
message: Message; | ||
blur: boolean; | ||
} | ||
|
||
export function WarpTransferDetailsCard({ message, blur }: Props) { | ||
const multiProvider = useMultiProvider(); | ||
const { warpRouteChainAddressMap } = useStore((s) => ({ | ||
warpRouteChainAddressMap: s.warpRouteChainAddressMap, | ||
})); | ||
const warpRouteDetails = parseWarpRouteDetails(message, warpRouteChainAddressMap, multiProvider); | ||
|
||
if (!warpRouteDetails) return null; | ||
|
||
const { | ||
amount, | ||
destinationTokenAddress, | ||
transferRecipient, | ||
originTokenAddress, | ||
originTokenSymbol, | ||
} = warpRouteDetails; | ||
|
||
return ( | ||
<Card className="w-full space-y-4"> | ||
<div className="flex items-center justify-between"> | ||
<Image src={SendMoney} width={28} height={28} alt="" className="opacity-80" /> | ||
<div className="flex items-center pb-1"> | ||
<h3 className="mr-2 text-md font-medium text-blue-500">Warp Transfer Details</h3> | ||
<Tooltip | ||
id="warp-route-info" | ||
content="Information about the warp route transfer such as the end recipient and amount transferred" | ||
/> | ||
</div> | ||
</div> | ||
<div className="flex flex-wrap gap-x-6 gap-y-4"> | ||
<KeyValueRow | ||
label="Amount:" | ||
labelWidth="w-20 sm:w-32" | ||
display={`${amount} ${originTokenSymbol}`} | ||
displayWidth="w-64 sm:w-96" | ||
blurValue={blur} | ||
showCopy | ||
/> | ||
<KeyValueRow | ||
label="Origin token:" | ||
labelWidth="w-20 sm:w-32" | ||
display={originTokenAddress} | ||
displayWidth="w-64 sm:w-96" | ||
showCopy={true} | ||
blurValue={blur} | ||
/> | ||
<KeyValueRow | ||
label="Destination token:" | ||
labelWidth="w-20 sm:w-32" | ||
display={destinationTokenAddress} | ||
displayWidth="w-64 sm:w-96" | ||
showCopy={true} | ||
blurValue={blur} | ||
/> | ||
<KeyValueRow | ||
label="Transfer recipient:" | ||
labelWidth="w-20 sm:w-32" | ||
display={transferRecipient} | ||
displayWidth="w-64 sm:w-96" | ||
blurValue={blur} | ||
showCopy | ||
/> | ||
</div> | ||
</Card> | ||
); | ||
} | ||
|
||
export function parseWarpRouteDetails( | ||
message: Message, | ||
warpRouteChainAddressMap: WarpRouteChainAddressMap, | ||
multiProvider: MultiProvider, | ||
): WarpRouteDetails | undefined { | ||
try { | ||
const { | ||
body, | ||
origin: { to }, | ||
originDomainId, | ||
destinationDomainId, | ||
recipient, | ||
} = message; | ||
|
||
const originMetadata = multiProvider.tryGetChainMetadata(originDomainId); | ||
const destinationMetadata = multiProvider.tryGetChainMetadata(destinationDomainId); | ||
|
||
if (!body || !originMetadata || !destinationMetadata) return undefined; | ||
|
||
const originToken = getTokenFromWarpRouteChainAddressMap( | ||
originMetadata, | ||
to, | ||
warpRouteChainAddressMap, | ||
); | ||
const destinationToken = getTokenFromWarpRouteChainAddressMap( | ||
destinationMetadata, | ||
recipient, | ||
warpRouteChainAddressMap, | ||
); | ||
|
||
// If tokens are not found with the addresses, it means the message | ||
// is not a warp transfer between tokens known to the registry | ||
if (!originToken || !destinationToken) return undefined; | ||
|
||
const parsedMessage = parseWarpRouteMessage(body); | ||
const bytes = fromHexString(parsedMessage.recipient); | ||
const address = bytesToProtocolAddress( | ||
bytes, | ||
destinationMetadata.protocol, | ||
destinationMetadata.bech32Prefix, | ||
); | ||
|
||
return { | ||
amount: fromWei(parsedMessage.amount.toString(), originToken.decimals || 18), | ||
transferRecipient: address, | ||
originTokenAddress: to, | ||
originTokenSymbol: originToken.symbol, | ||
destinationTokenAddress: recipient, | ||
destinationTokenSymbol: destinationToken.symbol, | ||
}; | ||
} catch (err) { | ||
logger.error('Error parsing warp route details:', err); | ||
return undefined; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
import { ChainMetadata } from '@hyperlane-xyz/sdk'; | ||
import { objKeys } from '@hyperlane-xyz/utils'; | ||
import { WarpRouteChainAddressMap } from '../types'; | ||
|
||
export function getTokenFromWarpRouteChainAddressMap( | ||
chainMetadata: ChainMetadata, | ||
address: Address, | ||
warpRouteChainAddressMap: WarpRouteChainAddressMap, | ||
) { | ||
const { name } = chainMetadata; | ||
if (objKeys(warpRouteChainAddressMap).includes(name)) { | ||
const chain = warpRouteChainAddressMap[name]; | ||
if (objKeys(chain).includes(address)) { | ||
return chain[address]; | ||
} | ||
} | ||
|
||
return undefined; | ||
} |
Oops, something went wrong.