Skip to content
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

feat: support intents #392

Draft
wants to merge 8 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
172 changes: 170 additions & 2 deletions src/consts/warpRoutes.ts
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';

// 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: {},
};
5 changes: 4 additions & 1 deletion src/features/tokens/TokenListModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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';
Expand Down Expand Up @@ -143,7 +144,9 @@ export function TokenList({
</div>
<div className="ml-2 min-w-0 shrink text-left">
<div className="w-full truncate text-xs">
{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>
Expand Down
2 changes: 1 addition & 1 deletion src/features/tokens/warpCoreConfig.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ function filterToIds(
function dedupeTokens(tokens: WarpCoreConfig['tokens']): WarpCoreConfig['tokens'] {
const idToToken: Record<string, WarpCoreConfig['tokens'][number]> = {};
for (const token of tokens) {
const id = `${token.chainName}|${token.addressOrDenom?.toLowerCase()}`;
const id = `${token.chainName}|${token.addressOrDenom?.toLowerCase()}|${token.collateralAddressOrDenom?.toLocaleLowerCase()}`;
idToToken[id] = objMerge(idToToken[id] || {}, token);
}
return Object.values(idToToken);
Expand Down
16 changes: 12 additions & 4 deletions src/features/transfer/TransferTokenForm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import { TextField } from '../../components/input/TextField';
import { WARP_QUERY_PARAMS } from '../../consts/args';
import { config } from '../../consts/config';
import { Color } from '../../styles/Color';
import { isIntentStandard } from '../../utils/intents';
import { logger } from '../../utils/logger';
import { getQueryParams, updateQueryParam } from '../../utils/queryParams';
import { ChainConnectionWarning } from '../chains/ChainConnectionWarning';
Expand Down Expand Up @@ -478,12 +479,18 @@ function ReviewDetails({ visible }: { visible: boolean }) {
</div>
)}
<div>
<h4>{`Transaction${isApproveRequired ? ' 2' : ''}: Transfer Remote`}</h4>
<h4>{`Transaction${isApproveRequired ? ' 2' : ''}:
${destinationToken && isIntentStandard(destinationToken.standard) ? 'Open Order' : 'Transfer Remote'}
`}</h4>
<div className="ml-1.5 mt-1.5 space-y-1.5 border-l border-gray-300 pl-2 text-xs">
{destinationToken?.addressOrDenom && (
<p className="flex">
<span className="min-w-[6.5rem]">Remote Token</span>
<span>{destinationToken.addressOrDenom}</span>
<span>
{isIntentStandard(destinationToken.standard)
? (destinationToken.collateralAddressOrDenom ?? 'Native chain token')
: destinationToken.addressOrDenom}
</span>
</p>
)}
<p className="flex">
Expand All @@ -493,15 +500,15 @@ function ReviewDetails({ visible }: { visible: boolean }) {
{fees?.localQuote && fees.localQuote.amount > 0n && (
<p className="flex">
<span className="min-w-[6.5rem]">Local Gas (est.)</span>
<span>{`${fees.localQuote.getDecimalFormattedAmount().toFixed(4) || '0'} ${
<span>{`${fees.localQuote.getDecimalFormattedAmount().toFixed(18) || '0'} ${
fees.localQuote.token.symbol || ''
}`}</span>
</p>
)}
{fees?.interchainQuote && fees.interchainQuote.amount > 0n && (
<p className="flex">
<span className="min-w-[6.5rem]">Interchain Gas</span>
<span>{`${fees.interchainQuote.getDecimalFormattedAmount().toFixed(4) || '0'} ${
<span>{`${fees.interchainQuote.getDecimalFormattedAmount().toFixed(18) || '0'} ${
fees.interchainQuote.token.symbol || ''
}`}</span>
</p>
Expand Down Expand Up @@ -578,6 +585,7 @@ async function validateForm(
origin,
accounts,
);

const result = await warpCore.validateTransfer({
originTokenAmount: token.amount(amountWei),
destination,
Expand Down
5 changes: 5 additions & 0 deletions src/utils/intents.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import { TokenStandard } from '@hyperlane-xyz/sdk';

export function isIntentStandard(standard: TokenStandard): boolean {
return standard === TokenStandard.EvmIntent || standard === TokenStandard.EvmIntentNative;
}