- 
                Notifications
    You must be signed in to change notification settings 
- Fork 196
feat: support intents #446
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
602cee8
              7decb6b
              f0c6a18
              bb270a2
              5dd8856
              fc7a3a0
              52b7874
              052c6ef
              File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | 
|---|---|---|
| @@ -1,9 +1,177 @@ | ||
| import { WarpCoreConfig } from '@hyperlane-xyz/sdk'; | ||
| import { TokenStandard, WarpCoreConfig } from '@hyperlane-xyz/sdk'; | ||
|  | ||
| const ROUTER = '0x6d2175B89315A9EB6c7eA71fDE54Ac0f294aDC34'; | ||
| const ITT = '0x5f94BC7Fb4A2779fef010F96b496cD36A909E818'; | ||
| 
      Comment on lines
    
      +3
     to 
      +4
    
   There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. can we have this in the  There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. sure, if you want to keep these in the codebase. My idea was to leave this file untocuched after the PR feedback (i.e.: roll back these changes). My intention was to share some implementation reference to help on the feedback. | ||
|  | ||
| // A list of Warp Route token configs | ||
| // These configs will be merged with the warp routes in the configured registry | ||
| // The input here is typically the output of the Hyperlane CLI warp deploy command | ||
| export const warpRouteConfigs: WarpCoreConfig = { | ||
| tokens: [], | ||
| tokens: [ | ||
| { | ||
| addressOrDenom: ROUTER, | ||
| chainName: 'optimismsepolia', | ||
| collateralAddressOrDenom: ITT, | ||
| connections: [ | ||
| { | ||
| token: 'ethereum|basesepolia|' + ITT, | ||
| }, | ||
| { | ||
| token: 'ethereum|arbitrumsepolia|' + ITT, | ||
| }, | ||
| { | ||
| token: 'ethereum|sepolia|' + ITT, | ||
| }, | ||
| ], | ||
| decimals: 18, | ||
| logoURI: '/deployments/warp_routes/ETH/logo.svg', | ||
| name: 'ITT', | ||
| standard: TokenStandard.EvmIntent, | ||
| symbol: 'ITT', | ||
| }, | ||
| { | ||
| addressOrDenom: ROUTER, | ||
| chainName: 'basesepolia', | ||
| collateralAddressOrDenom: ITT, | ||
| connections: [ | ||
| { | ||
| token: 'ethereum|optimismsepolia|' + ITT, | ||
| }, | ||
| { | ||
| token: 'ethereum|arbitrumsepolia|' + ITT, | ||
| }, | ||
| { | ||
| token: 'ethereum|sepolia|' + ITT, | ||
| }, | ||
| ], | ||
| decimals: 18, | ||
| logoURI: '/deployments/warp_routes/ETH/logo.svg', | ||
| name: 'ITT', | ||
| standard: TokenStandard.EvmIntent, | ||
| symbol: 'ITT', | ||
| }, | ||
| { | ||
| addressOrDenom: ROUTER, | ||
| chainName: 'arbitrumsepolia', | ||
| collateralAddressOrDenom: ITT, | ||
| connections: [ | ||
| { | ||
| token: 'ethereum|optimismsepolia|' + ITT, | ||
| }, | ||
| { | ||
| token: 'ethereum|basesepolia|' + ITT, | ||
| }, | ||
| { | ||
| token: 'ethereum|sepolia|' + ITT, | ||
| }, | ||
| ], | ||
| decimals: 18, | ||
| logoURI: '/deployments/warp_routes/ETH/logo.svg', | ||
| name: 'ITT', | ||
| standard: TokenStandard.EvmIntent, | ||
| symbol: 'ITT', | ||
| }, | ||
| { | ||
| addressOrDenom: ROUTER, | ||
| chainName: 'sepolia', | ||
| collateralAddressOrDenom: ITT, | ||
| connections: [ | ||
| { | ||
| token: 'ethereum|optimismsepolia|' + ITT, | ||
| }, | ||
| { | ||
| token: 'ethereum|arbitrumsepolia|' + ITT, | ||
| }, | ||
| { | ||
| token: 'ethereum|basesepolia|' + ITT, | ||
| }, | ||
| ], | ||
| decimals: 18, | ||
| logoURI: '/deployments/warp_routes/ETH/logo.svg', | ||
| name: 'ITT', | ||
| standard: TokenStandard.EvmIntent, | ||
| symbol: 'ITT', | ||
| }, | ||
| { | ||
| addressOrDenom: ROUTER, | ||
| chainName: 'optimismsepolia', | ||
| connections: [ | ||
| { | ||
| token: 'ethereum|basesepolia|', | ||
| }, | ||
| { | ||
| token: 'ethereum|arbitrumsepolia|', | ||
| }, | ||
| { | ||
| token: 'ethereum|sepolia|', | ||
| }, | ||
| ], | ||
| decimals: 18, | ||
| logoURI: '/deployments/warp_routes/ETH/logo.svg', | ||
| name: 'ETH', | ||
| standard: TokenStandard.EvmIntentNative, | ||
| symbol: 'ETH', | ||
| }, | ||
| { | ||
| addressOrDenom: ROUTER, | ||
| chainName: 'basesepolia', | ||
| connections: [ | ||
| { | ||
| token: 'ethereum|optimismsepolia|', | ||
| }, | ||
| { | ||
| token: 'ethereum|arbitrumsepolia|', | ||
| }, | ||
| { | ||
| token: 'ethereum|sepolia|', | ||
| }, | ||
| ], | ||
| decimals: 18, | ||
| logoURI: '/deployments/warp_routes/ETH/logo.svg', | ||
| name: 'ETH', | ||
| standard: TokenStandard.EvmIntentNative, | ||
| symbol: 'ETH', | ||
| }, | ||
| { | ||
| addressOrDenom: ROUTER, | ||
| chainName: 'arbitrumsepolia', | ||
| connections: [ | ||
| { | ||
| token: 'ethereum|optimismsepolia|', | ||
| }, | ||
| { | ||
| token: 'ethereum|basesepolia|', | ||
| }, | ||
| { | ||
| token: 'ethereum|sepolia|', | ||
| }, | ||
| ], | ||
| decimals: 18, | ||
| logoURI: '/deployments/warp_routes/ETH/logo.svg', | ||
| name: 'ETH', | ||
| standard: TokenStandard.EvmIntentNative, | ||
| symbol: 'ETH', | ||
| }, | ||
| { | ||
| addressOrDenom: ROUTER, | ||
| chainName: 'sepolia', | ||
| connections: [ | ||
| { | ||
| token: 'ethereum|optimismsepolia|', | ||
| }, | ||
| { | ||
| token: 'ethereum|arbitrumsepolia|', | ||
| }, | ||
| { | ||
| token: 'ethereum|basesepolia|', | ||
| }, | ||
| ], | ||
| decimals: 18, | ||
| logoURI: '/deployments/warp_routes/ETH/logo.svg', | ||
| name: 'ETH', | ||
| standard: TokenStandard.EvmIntentNative, | ||
| symbol: 'ETH', | ||
| }, | ||
| ], | ||
| options: {}, | ||
| }; | ||
| Original file line number | Diff line number | Diff line change | 
|---|---|---|
|  | @@ -47,7 +47,7 @@ export interface AppState { | |
| updateTransferStatus: ( | ||
| i: number, | ||
| s: TransferStatus, | ||
| options?: { msgId?: string; originTxHash?: string }, | ||
| options?: { msgId?: string; originTxHash?: string; orderId?: string; remoteTxHash?: string }, | ||
| ) => void; | ||
| failUnconfirmedTransfers: () => void; | ||
|  | ||
|  | @@ -114,6 +114,8 @@ export const useStore = create<AppState>()( | |
| txs[i].status = s; | ||
| txs[i].msgId ||= options?.msgId; | ||
| txs[i].originTxHash ||= options?.originTxHash; | ||
| txs[i].orderId ||= options?.orderId; | ||
| txs[i].remoteTxHash ||= options?.remoteTxHash; | ||
| 
      Comment on lines
    
      +117
     to 
      +118
    
   There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. | ||
| return { | ||
| transfers: txs, | ||
| }; | ||
|  | ||
| Original file line number | Diff line number | Diff line change | 
|---|---|---|
|  | @@ -6,6 +6,7 @@ import { TokenIcon } from '../../components/icons/TokenIcon'; | |
| import { TextInput } from '../../components/input/TextField'; | ||
| import { config } from '../../consts/config'; | ||
| import InfoIcon from '../../images/icons/info-circle.svg'; | ||
| import { isIntentStandard } from '../../utils/intents'; | ||
| import { useMultiProvider } from '../chains/hooks'; | ||
| import { getChainDisplayName } from '../chains/utils'; | ||
| import { useWarpCore } from './hooks'; | ||
|  | @@ -143,12 +144,22 @@ export function TokenList({ | |
| </div> | ||
| <div className="ml-2 min-w-0 shrink text-left"> | ||
| <div className="w-full truncate text-xs"> | ||
| {t.token.collateralAddressOrDenom || t.token.addressOrDenom || 'Native chain token'} | ||
| {(isIntentStandard(t.token.standard) | ||
| ? t.token.collateralAddressOrDenom | ||
| : t.token.addressOrDenom) ?? 'Native chain token'} | ||
| </div> | ||
| <div className="mt-0.5 flex space-x-1 text-xs"> | ||
| <span>{`Decimals: ${t.token.decimals}`}</span> | ||
| <span>-</span> | ||
| <span>{`Chain: ${getChainDisplayName(multiProvider, t.token.chainName)}`}</span> | ||
| {isIntentStandard(t.token.standard) && ( | ||
| <> | ||
| <span>-</span> | ||
| <span> | ||
| <i>via intents</i> | ||
| </span> | ||
| </> | ||
| )} | ||
| 
      Comment on lines
    
      +155
     to 
      +162
    
   There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. if it's an intent, we let the user know (this is useful in the case that the same token can be bridged via WR or intents) | ||
| </div> | ||
| </div> | ||
| {t.disabled && ( | ||
|  | ||
| Original file line number | Diff line number | Diff line change | 
|---|---|---|
| @@ -1,5 +1,6 @@ | ||
| import { Hyperlane7683__factory as Hyperlane7683Factory } from '@bootnodedev/intents-framework-core'; | ||
| import { IToken, MultiProtocolProvider, Token } from '@hyperlane-xyz/sdk'; | ||
| import { isValidAddress } from '@hyperlane-xyz/utils'; | ||
| import { assert, isValidAddress } from '@hyperlane-xyz/utils'; | ||
| import { useAccountAddressForChain } from '@hyperlane-xyz/widgets'; | ||
| import { useQuery } from '@tanstack/react-query'; | ||
| import { toast } from 'react-toastify'; | ||
|  | @@ -86,3 +87,47 @@ export function useEvmWalletBalance( | |
|  | ||
| return { balance: data, isError, isLoading }; | ||
| } | ||
| export async function checkOrderFilled({ | ||
| There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. polls for the destination chain Filling | ||
| destination, | ||
| orderId, | ||
| originToken, | ||
| multiProvider, | ||
| }: { | ||
| destination: ChainName; | ||
| orderId: string; | ||
| originToken: Token; | ||
| multiProvider: MultiProtocolProvider; | ||
| }): Promise<string> { | ||
| const provider = multiProvider.toMultiProvider().getProvider(destination); | ||
| const connection = originToken.getConnectionForChain(destination); | ||
|  | ||
| assert(connection?.token.addressOrDenom, 'No connection found for destination chain'); | ||
|  | ||
| const contract = Hyperlane7683Factory.connect(connection.token.addressOrDenom, provider); | ||
| const filter = contract.filters.Filled(); | ||
|  | ||
| const BLOCKS_TO_CHECK = 10; | ||
| const BLOCK_CHECK_INTERVAL = 4_000; | ||
|  | ||
| return new Promise((resolve, reject) => { | ||
| const intervalId = setInterval(async () => { | ||
| try { | ||
| const to = await provider.getBlockNumber(); | ||
| const from = to - BLOCKS_TO_CHECK; | ||
| const events = await contract.queryFilter(filter, from, to); | ||
|  | ||
| for (const event of events) { | ||
| const resolvedOrder = event.args.orderId; | ||
|  | ||
| if (resolvedOrder === orderId) { | ||
| clearInterval(intervalId); | ||
| resolve(event.transactionHash); | ||
| } | ||
| } | ||
| } catch (error) { | ||
| clearInterval(intervalId); | ||
| reject(error); | ||
| } | ||
| }, BLOCK_CHECK_INTERVAL); | ||
| }); | ||
| } | ||

There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Warning
an example file for testing purposes, this change should be removed before merging.