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

Aptos CCTP Support #3181

Open
wants to merge 4 commits into
base: development
Choose a base branch
from
Open
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
345 changes: 180 additions & 165 deletions wormhole-connect/package-lock.json

Large diffs are not rendered by default.

32 changes: 16 additions & 16 deletions wormhole-connect/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,8 @@
"@solana/spl-token": "^0.3.9",
"@solana/wallet-adapter-wallets": "^0.19.25",
"@solana/web3.js": "^1.95.8",
"@wormhole-foundation/sdk": "1.4.0",
"@wormhole-foundation/sdk-definitions": "1.4.0",
"@wormhole-foundation/sdk": "1.5.0-beta.0",
"@wormhole-foundation/sdk-definitions": "1.5.0-beta.0",
"@wormhole-foundation/sdk-definitions-ntt": "^0.6.1",
"@wormhole-foundation/sdk-evm-ntt": "^0.6.1",
"@wormhole-foundation/sdk-icons": "^1.0.0",
Expand Down Expand Up @@ -163,28 +163,28 @@
"axios": "1.4.0"
},
"@mayanfinance/wormhole-sdk-route": {
"@wormhole-foundation/sdk-connect": "1.4.0",
"@wormhole-foundation/sdk-evm": "1.4.0",
"@wormhole-foundation/sdk-solana": "1.4.0"
"@wormhole-foundation/sdk-connect": "1.5.0-beta.0",
"@wormhole-foundation/sdk-evm": "1.5.0-beta.0",
"@wormhole-foundation/sdk-solana": "1.5.0-beta.0"
},
"@wormhole-foundation/sdk-definitions-ntt": {
"@wormhole-foundation/sdk-base": "1.4.0",
"@wormhole-foundation/sdk-definitions": "1.4.0"
"@wormhole-foundation/sdk-base": "1.5.0-beta.0",
"@wormhole-foundation/sdk-definitions": "1.5.0-beta.0"
},
"@wormhole-foundation/sdk-evm-ntt": {
"@wormhole-foundation/sdk-base": "1.4.0",
"@wormhole-foundation/sdk-definitions": "1.4.0",
"@wormhole-foundation/sdk-evm": "1.4.0",
"@wormhole-foundation/sdk-evm-core": "1.4.0"
"@wormhole-foundation/sdk-base": "1.5.0-beta.0",
"@wormhole-foundation/sdk-definitions": "1.5.0-beta.0",
"@wormhole-foundation/sdk-evm": "1.5.0-beta.0",
"@wormhole-foundation/sdk-evm-core": "1.5.0-beta.0"
},
"@wormhole-foundation/sdk-route-ntt": {
"@wormhole-foundation/sdk-connect": "1.4.0"
"@wormhole-foundation/sdk-connect": "1.5.0-beta.0"
},
"@wormhole-foundation/sdk-solana-ntt": {
"@wormhole-foundation/sdk-base": "1.4.0",
"@wormhole-foundation/sdk-definitions": "1.4.0",
"@wormhole-foundation/sdk-solana": "1.4.0",
"@wormhole-foundation/sdk-solana-core": "1.4.0"
"@wormhole-foundation/sdk-base": "1.5.0-beta.0",
"@wormhole-foundation/sdk-definitions": "1.5.0-beta.0",
"@wormhole-foundation/sdk-solana": "1.5.0-beta.0",
"@wormhole-foundation/sdk-solana-core": "1.5.0-beta.0"
},
"@wormhole-foundation/wormhole-connect": {
"aptos": "1.5.0"
Expand Down
14 changes: 14 additions & 0 deletions wormhole-connect/src/config/mainnet/tokens.ts
Original file line number Diff line number Diff line change
Expand Up @@ -417,6 +417,20 @@ export const MAINNET_TOKENS: TokensConfig = {
color: '#8457EF',
decimals: 8,
},
USDCapt: {
key: 'USDCapt',
symbol: 'USDC',
nativeChain: 'Aptos',
tokenId: {
chain: 'Aptos',
address:
'0xbae207659db88bea0cbead6da0ed00aac12edcdda169e591cd41c94180b46f3b',
},
icon: TokenIcon.USDC,
coinGeckoId: 'usd-coin',
color: '#2774CA',
decimals: 6,
},
ETHarbitrum: {
key: 'ETHarbitrum',
symbol: 'ETH',
Expand Down
14 changes: 14 additions & 0 deletions wormhole-connect/src/config/testnet/tokens.ts
Original file line number Diff line number Diff line change
Expand Up @@ -202,6 +202,20 @@ export const TESTNET_TOKENS: TokensConfig = {
color: '#8457EF',
decimals: 8,
},
USDCapt: {
key: 'USDCapt',
symbol: 'USDC',
nativeChain: 'Aptos',
tokenId: {
chain: 'Aptos',
address:
'0x69091fbab5f7d635ee7ac5098cf0c1efbe31d68fec0f2cd565e8d168daf52832',
},
icon: TokenIcon.USDC,
coinGeckoId: 'usd-coin',
color: '#2774CA',
decimals: 6,
},
KLAY: {
key: 'KLAY',
symbol: 'KLAY',
Expand Down
52 changes: 52 additions & 0 deletions wormhole-connect/src/hooks/useWalletCompatibility.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
import { useMemo } from 'react';
import { Chain } from '@wormhole-foundation/sdk';
import { WalletData } from '../store/wallet';
import { type AvailableWallets } from '@aptos-labs/wallet-adapter-core';

export type WalletCompatibilityResult = {
isCompatible: boolean;
warning?: string;
};

export const useWalletCompatibility = ({
sendingWallet,
receivingWallet,
sourceChain,
destChain,
routes,
}: {
sendingWallet: WalletData;
receivingWallet: WalletData;
sourceChain?: Chain;
destChain?: Chain;
routes: string[];
}): WalletCompatibilityResult => {
return useMemo(() => {
const isManualCCTPRoute = routes.length === 1 && routes[0] === 'ManualCCTP';

if (isManualCCTPRoute) {
// Aptos CCTP requires modern (AIP-62 standard) wallets with support for signing move script transaction types
const compatibleWallets: AvailableWallets[] = [
'Pontem Wallet',
'Nightly',
];
if (
(sourceChain === 'Aptos' &&
!compatibleWallets.includes(
sendingWallet.name as AvailableWallets,
)) ||
(destChain === 'Aptos' &&
!compatibleWallets.includes(receivingWallet.name as AvailableWallets))
) {
return {
isCompatible: false,
warning: `Please use ${compatibleWallets.join(
' or ',
)} with the Aptos CCTP route.`,
};
}
}

return { isCompatible: true };
}, [sendingWallet, receivingWallet, sourceChain, destChain, routes]);
};
8 changes: 7 additions & 1 deletion wormhole-connect/src/utils/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -363,12 +363,18 @@ export const isEmptyObject = (value: object | null | undefined) => {
return true;
};

export const getExplorerUrl = (chain: Chain, address: string) => {
export const getTokenExplorerUrl = (chain: Chain, address: string) => {
const chainConfig = config.chains[chain]!;
let explorerUrl = '';

if (chain === 'Sui') {
explorerUrl = `${chainConfig.explorerUrl}coin/${address}`;
} else if (chain === 'Aptos') {
if (isHexString(address)) {
explorerUrl = `${chainConfig.explorerUrl}fungible_asset/${address}`;
} else {
explorerUrl = `${chainConfig.explorerUrl}coin/${address}`;
}
} else {
explorerUrl = `${chainConfig.explorerUrl}address/${address}`;
}
Expand Down
34 changes: 12 additions & 22 deletions wormhole-connect/src/utils/wallet/aptos.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
import { Wallet } from '@xlabs-libs/wallet-aggregator-core';
import type { Network as AptosNetwork } from '@aptos-labs/wallet-adapter-core';
import { AptosWallet } from '@xlabs-libs/wallet-aggregator-aptos';
import { Aptos } from '@aptos-labs/ts-sdk';

import { Network } from '@wormhole-foundation/sdk';
import {
AptosUnsignedTransaction,
AptosChains,
} from '@wormhole-foundation/sdk-aptos';

import config from 'config';
import { InputEntryFunctionData } from '@aptos-labs/ts-sdk';
import config, { getWormholeContextV2 } from 'config';

export function fetchOptions() {
const aptosWalletConfig = {
Expand All @@ -25,25 +25,12 @@ export function fetchOptions() {
return aptosWallets;
}

function isInputEntryFunctionData(data: any): data is InputEntryFunctionData {
return (
data &&
typeof data === 'object' &&
'function' in data &&
'functionArguments' in data
);
}

export async function signAndSendTransaction(
request: AptosUnsignedTransaction<Network, AptosChains>,
wallet: Wallet | undefined,
) {
const payload = request.transaction;
if (!isInputEntryFunctionData(payload)) {
throw new Error('Unsupported transaction type');
}
// The wallets do not handle Uint8Array serialization
// const payload = request.transaction as Types.EntryFunctionPayload;
payload.functionArguments = payload.functionArguments.map((a: any) => {
if (a instanceof Uint8Array) {
return Array.from(a);
Expand All @@ -54,16 +41,19 @@ export async function signAndSendTransaction(
}
});

const context = await getWormholeContextV2();
const aptos = context.getPlatform('Aptos');
const rpc = (await aptos.getRpc('Aptos')) as Aptos;

const tx = await (wallet as AptosWallet).signAndSendTransaction({
data: payload,
options: {
// this is set to 5 minutes in case the user takes a while to sign the transaction
expireTimestamp: Math.floor(Date.now() / 1000) + 60 * 5,
},
});
/*
* TODO SDKV2
const aptosClient = (
config.wh.getContext('Aptos') as AptosContext<WormholeContext>
).aptosClient;
await aptosClient.waitForTransaction(tx.id);
*/

await rpc.waitForTransaction({ transactionHash: tx.id });

return tx;
}
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,7 @@ const ChainList = (props: Props) => {
return (
<List component={Stack} direction="row">
{topChains.map((chain: ChainConfig) => (
<Tooltip title={chain.displayName}>
<Tooltip key={chain.key} title={chain.displayName}>
<ListItemButton
key={chain.key}
selected={selectedChainConfig?.key === chain.key}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import TokenIcon from 'icons/TokenIcons';
import { TokenConfig } from 'config/types';

import type { Chain } from '@wormhole-foundation/sdk';
import { getDisplayName, getExplorerUrl, getWrappedToken } from 'utils';
import { getDisplayName, getTokenExplorerUrl, getWrappedToken } from 'utils';
import { getTokenBridgeWrappedTokenAddressSync } from 'utils/sdkv2';

const useStyles = makeStyles()((theme) => ({
Expand Down Expand Up @@ -65,7 +65,7 @@ function TokenItem(props: TokenItemProps) {
getWrappedToken(token),
chain,
)?.toString();
const explorerURL = address ? getExplorerUrl(chain, address) : undefined;
const explorerURL = address ? getTokenExplorerUrl(chain, address) : undefined;
const addressDisplay = `${address?.slice(0, 4)}...${address?.slice(-4)}`;

const displayName = getDisplayName(token, chain);
Expand Down
16 changes: 14 additions & 2 deletions wormhole-connect/src/views/v2/Bridge/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ import { useFetchTokenPrices } from 'hooks/useFetchTokenPrices';
import type { Chain } from '@wormhole-foundation/sdk';
import { amount as sdkAmount } from '@wormhole-foundation/sdk';
import { useAmountValidation } from 'hooks/useAmountValidation';
import { useWalletCompatibility } from 'hooks/useWalletCompatibility';
import useGetTokenBalances from 'hooks/useGetTokenBalances';

const useStyles = makeStyles()((theme) => ({
Expand Down Expand Up @@ -406,20 +407,31 @@ const Bridge = () => {
);
}, [sourceChain, destChain, sendingWallet, receivingWallet]);

const { isCompatible: isWalletCompatible, warning: walletWarning } =
useWalletCompatibility({
sendingWallet,
receivingWallet,
sourceChain,
destChain,
routes: sortedRoutes,
});

const hasError = !!amountValidation.error;

const hasEnteredAmount = amount && sdkAmount.whole(amount) > 0;

const hasConnectedWallets = sendingWallet.address && receivingWallet.address;

const showRoutes = hasConnectedWallets && hasEnteredAmount && !hasError;
const showRoutes =
hasConnectedWallets && isWalletCompatible && hasEnteredAmount && !hasError;

const reviewTransactionDisabled =
!sourceChain ||
!sourceToken ||
!destChain ||
!destToken ||
!hasConnectedWallets ||
!isWalletCompatible ||
!selectedRoute ||
!isValid ||
isFetchingQuotes ||
Expand Down Expand Up @@ -476,7 +488,7 @@ const Bridge = () => {
<AmountInput
supportedSourceTokens={supportedSourceTokens}
error={amountValidation.error}
warning={amountValidation.warning}
warning={amountValidation.warning || walletWarning}
/>
{showRoutes && (
<Routes
Expand Down
Loading