Skip to content

Commit 2061a03

Browse files
authored
Aptos CCTP support (#3175)
* first commit * fix aptos token explorer urls * fixes * bump sdk for aptos route
1 parent f3e2348 commit 2061a03

File tree

10 files changed

+312
-209
lines changed

10 files changed

+312
-209
lines changed

wormhole-connect/package-lock.json

+180-165
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

wormhole-connect/package.json

+16-16
Original file line numberDiff line numberDiff line change
@@ -36,8 +36,8 @@
3636
"@solana/spl-token": "^0.3.9",
3737
"@solana/wallet-adapter-wallets": "^0.19.25",
3838
"@solana/web3.js": "^1.95.8",
39-
"@wormhole-foundation/sdk": "1.4.0",
40-
"@wormhole-foundation/sdk-definitions": "1.4.0",
39+
"@wormhole-foundation/sdk": "1.5.0-beta.0",
40+
"@wormhole-foundation/sdk-definitions": "1.5.0-beta.0",
4141
"@wormhole-foundation/sdk-definitions-ntt": "^0.6.1",
4242
"@wormhole-foundation/sdk-evm-ntt": "^0.6.1",
4343
"@wormhole-foundation/sdk-icons": "^1.0.0",
@@ -163,28 +163,28 @@
163163
"axios": "1.4.0"
164164
},
165165
"@mayanfinance/wormhole-sdk-route": {
166-
"@wormhole-foundation/sdk-connect": "1.4.0",
167-
"@wormhole-foundation/sdk-evm": "1.4.0",
168-
"@wormhole-foundation/sdk-solana": "1.4.0"
166+
"@wormhole-foundation/sdk-connect": "1.5.0-beta.0",
167+
"@wormhole-foundation/sdk-evm": "1.5.0-beta.0",
168+
"@wormhole-foundation/sdk-solana": "1.5.0-beta.0"
169169
},
170170
"@wormhole-foundation/sdk-definitions-ntt": {
171-
"@wormhole-foundation/sdk-base": "1.4.0",
172-
"@wormhole-foundation/sdk-definitions": "1.4.0"
171+
"@wormhole-foundation/sdk-base": "1.5.0-beta.0",
172+
"@wormhole-foundation/sdk-definitions": "1.5.0-beta.0"
173173
},
174174
"@wormhole-foundation/sdk-evm-ntt": {
175-
"@wormhole-foundation/sdk-base": "1.4.0",
176-
"@wormhole-foundation/sdk-definitions": "1.4.0",
177-
"@wormhole-foundation/sdk-evm": "1.4.0",
178-
"@wormhole-foundation/sdk-evm-core": "1.4.0"
175+
"@wormhole-foundation/sdk-base": "1.5.0-beta.0",
176+
"@wormhole-foundation/sdk-definitions": "1.5.0-beta.0",
177+
"@wormhole-foundation/sdk-evm": "1.5.0-beta.0",
178+
"@wormhole-foundation/sdk-evm-core": "1.5.0-beta.0"
179179
},
180180
"@wormhole-foundation/sdk-route-ntt": {
181-
"@wormhole-foundation/sdk-connect": "1.4.0"
181+
"@wormhole-foundation/sdk-connect": "1.5.0-beta.0"
182182
},
183183
"@wormhole-foundation/sdk-solana-ntt": {
184-
"@wormhole-foundation/sdk-base": "1.4.0",
185-
"@wormhole-foundation/sdk-definitions": "1.4.0",
186-
"@wormhole-foundation/sdk-solana": "1.4.0",
187-
"@wormhole-foundation/sdk-solana-core": "1.4.0"
184+
"@wormhole-foundation/sdk-base": "1.5.0-beta.0",
185+
"@wormhole-foundation/sdk-definitions": "1.5.0-beta.0",
186+
"@wormhole-foundation/sdk-solana": "1.5.0-beta.0",
187+
"@wormhole-foundation/sdk-solana-core": "1.5.0-beta.0"
188188
},
189189
"@wormhole-foundation/wormhole-connect": {
190190
"aptos": "1.5.0"

wormhole-connect/src/config/mainnet/tokens.ts

+14
Original file line numberDiff line numberDiff line change
@@ -417,6 +417,20 @@ export const MAINNET_TOKENS: TokensConfig = {
417417
color: '#8457EF',
418418
decimals: 8,
419419
},
420+
USDCapt: {
421+
key: 'USDCapt',
422+
symbol: 'USDC',
423+
nativeChain: 'Aptos',
424+
tokenId: {
425+
chain: 'Aptos',
426+
address:
427+
'0xbae207659db88bea0cbead6da0ed00aac12edcdda169e591cd41c94180b46f3b',
428+
},
429+
icon: TokenIcon.USDC,
430+
coinGeckoId: 'usd-coin',
431+
color: '#2774CA',
432+
decimals: 6,
433+
},
420434
ETHarbitrum: {
421435
key: 'ETHarbitrum',
422436
symbol: 'ETH',

wormhole-connect/src/config/testnet/tokens.ts

+14
Original file line numberDiff line numberDiff line change
@@ -202,6 +202,20 @@ export const TESTNET_TOKENS: TokensConfig = {
202202
color: '#8457EF',
203203
decimals: 8,
204204
},
205+
USDCapt: {
206+
key: 'USDCapt',
207+
symbol: 'USDC',
208+
nativeChain: 'Aptos',
209+
tokenId: {
210+
chain: 'Aptos',
211+
address:
212+
'0x69091fbab5f7d635ee7ac5098cf0c1efbe31d68fec0f2cd565e8d168daf52832',
213+
},
214+
icon: TokenIcon.USDC,
215+
coinGeckoId: 'usd-coin',
216+
color: '#2774CA',
217+
decimals: 6,
218+
},
205219
KLAY: {
206220
key: 'KLAY',
207221
symbol: 'KLAY',
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
import { useMemo } from 'react';
2+
import { Chain } from '@wormhole-foundation/sdk';
3+
import { WalletData } from '../store/wallet';
4+
import { type AvailableWallets } from '@aptos-labs/wallet-adapter-core';
5+
6+
export type WalletCompatibilityResult = {
7+
isCompatible: boolean;
8+
warning?: string;
9+
};
10+
11+
export const useWalletCompatibility = ({
12+
sendingWallet,
13+
receivingWallet,
14+
sourceChain,
15+
destChain,
16+
routes,
17+
}: {
18+
sendingWallet: WalletData;
19+
receivingWallet: WalletData;
20+
sourceChain?: Chain;
21+
destChain?: Chain;
22+
routes: string[];
23+
}): WalletCompatibilityResult => {
24+
return useMemo(() => {
25+
const isManualCCTPRoute = routes.length === 1 && routes[0] === 'ManualCCTP';
26+
27+
if (isManualCCTPRoute) {
28+
// Aptos CCTP requires modern (AIP-62 standard) wallets with support for signing move script transaction types
29+
const compatibleWallets: AvailableWallets[] = [
30+
'Pontem Wallet',
31+
'Nightly',
32+
];
33+
if (
34+
(sourceChain === 'Aptos' &&
35+
!compatibleWallets.includes(
36+
sendingWallet.name as AvailableWallets,
37+
)) ||
38+
(destChain === 'Aptos' &&
39+
!compatibleWallets.includes(receivingWallet.name as AvailableWallets))
40+
) {
41+
return {
42+
isCompatible: false,
43+
warning: `Please use ${compatibleWallets.join(
44+
' or ',
45+
)} with the Aptos CCTP route.`,
46+
};
47+
}
48+
}
49+
50+
return { isCompatible: true };
51+
}, [sendingWallet, receivingWallet, sourceChain, destChain, routes]);
52+
};

wormhole-connect/src/utils/index.ts

+7-1
Original file line numberDiff line numberDiff line change
@@ -363,12 +363,18 @@ export const isEmptyObject = (value: object | null | undefined) => {
363363
return true;
364364
};
365365

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

370370
if (chain === 'Sui') {
371371
explorerUrl = `${chainConfig.explorerUrl}coin/${address}`;
372+
} else if (chain === 'Aptos') {
373+
if (isHexString(address)) {
374+
explorerUrl = `${chainConfig.explorerUrl}fungible_asset/${address}`;
375+
} else {
376+
explorerUrl = `${chainConfig.explorerUrl}coin/${address}`;
377+
}
372378
} else {
373379
explorerUrl = `${chainConfig.explorerUrl}address/${address}`;
374380
}
+12-22
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,15 @@
11
import { Wallet } from '@xlabs-libs/wallet-aggregator-core';
22
import type { Network as AptosNetwork } from '@aptos-labs/wallet-adapter-core';
33
import { AptosWallet } from '@xlabs-libs/wallet-aggregator-aptos';
4+
import { Aptos } from '@aptos-labs/ts-sdk';
45

56
import { Network } from '@wormhole-foundation/sdk';
67
import {
78
AptosUnsignedTransaction,
89
AptosChains,
910
} from '@wormhole-foundation/sdk-aptos';
1011

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

1414
export function fetchOptions() {
1515
const aptosWalletConfig = {
@@ -25,25 +25,12 @@ export function fetchOptions() {
2525
return aptosWallets;
2626
}
2727

28-
function isInputEntryFunctionData(data: any): data is InputEntryFunctionData {
29-
return (
30-
data &&
31-
typeof data === 'object' &&
32-
'function' in data &&
33-
'functionArguments' in data
34-
);
35-
}
36-
3728
export async function signAndSendTransaction(
3829
request: AptosUnsignedTransaction<Network, AptosChains>,
3930
wallet: Wallet | undefined,
4031
) {
4132
const payload = request.transaction;
42-
if (!isInputEntryFunctionData(payload)) {
43-
throw new Error('Unsupported transaction type');
44-
}
4533
// The wallets do not handle Uint8Array serialization
46-
// const payload = request.transaction as Types.EntryFunctionPayload;
4734
payload.functionArguments = payload.functionArguments.map((a: any) => {
4835
if (a instanceof Uint8Array) {
4936
return Array.from(a);
@@ -54,16 +41,19 @@ export async function signAndSendTransaction(
5441
}
5542
});
5643

44+
const context = await getWormholeContextV2();
45+
const aptos = context.getPlatform('Aptos');
46+
const rpc = (await aptos.getRpc('Aptos')) as Aptos;
47+
5748
const tx = await (wallet as AptosWallet).signAndSendTransaction({
5849
data: payload,
50+
options: {
51+
// this is set to 5 minutes in case the user takes a while to sign the transaction
52+
expireTimestamp: Math.floor(Date.now() / 1000) + 60 * 5,
53+
},
5954
});
60-
/*
61-
* TODO SDKV2
62-
const aptosClient = (
63-
config.wh.getContext('Aptos') as AptosContext<WormholeContext>
64-
).aptosClient;
65-
await aptosClient.waitForTransaction(tx.id);
66-
*/
55+
56+
await rpc.waitForTransaction({ transactionHash: tx.id });
6757

6858
return tx;
6959
}

wormhole-connect/src/views/v2/Bridge/AssetPicker/ChainList.tsx

+1-1
Original file line numberDiff line numberDiff line change
@@ -115,7 +115,7 @@ const ChainList = (props: Props) => {
115115
return (
116116
<List component={Stack} direction="row">
117117
{topChains.map((chain: ChainConfig) => (
118-
<Tooltip title={chain.displayName}>
118+
<Tooltip key={chain.key} title={chain.displayName}>
119119
<ListItemButton
120120
key={chain.key}
121121
selected={selectedChainConfig?.key === chain.key}

wormhole-connect/src/views/v2/Bridge/AssetPicker/TokenItem.tsx

+2-2
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ import TokenIcon from 'icons/TokenIcons';
1515
import { TokenConfig } from 'config/types';
1616

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

2121
const useStyles = makeStyles()((theme) => ({
@@ -65,7 +65,7 @@ function TokenItem(props: TokenItemProps) {
6565
getWrappedToken(token),
6666
chain,
6767
)?.toString();
68-
const explorerURL = address ? getExplorerUrl(chain, address) : undefined;
68+
const explorerURL = address ? getTokenExplorerUrl(chain, address) : undefined;
6969
const addressDisplay = `${address?.slice(0, 4)}...${address?.slice(-4)}`;
7070

7171
const displayName = getDisplayName(token, chain);

wormhole-connect/src/views/v2/Bridge/index.tsx

+14-2
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ import { useFetchTokenPrices } from 'hooks/useFetchTokenPrices';
4444
import type { Chain } from '@wormhole-foundation/sdk';
4545
import { amount as sdkAmount } from '@wormhole-foundation/sdk';
4646
import { useAmountValidation } from 'hooks/useAmountValidation';
47+
import { useWalletCompatibility } from 'hooks/useWalletCompatibility';
4748
import useGetTokenBalances from 'hooks/useGetTokenBalances';
4849

4950
const useStyles = makeStyles()((theme) => ({
@@ -406,20 +407,31 @@ const Bridge = () => {
406407
);
407408
}, [sourceChain, destChain, sendingWallet, receivingWallet]);
408409

410+
const { isCompatible: isWalletCompatible, warning: walletWarning } =
411+
useWalletCompatibility({
412+
sendingWallet,
413+
receivingWallet,
414+
sourceChain,
415+
destChain,
416+
routes: sortedRoutes,
417+
});
418+
409419
const hasError = !!amountValidation.error;
410420

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

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

415-
const showRoutes = hasConnectedWallets && hasEnteredAmount && !hasError;
425+
const showRoutes =
426+
hasConnectedWallets && isWalletCompatible && hasEnteredAmount && !hasError;
416427

417428
const reviewTransactionDisabled =
418429
!sourceChain ||
419430
!sourceToken ||
420431
!destChain ||
421432
!destToken ||
422433
!hasConnectedWallets ||
434+
!isWalletCompatible ||
423435
!selectedRoute ||
424436
!isValid ||
425437
isFetchingQuotes ||
@@ -476,7 +488,7 @@ const Bridge = () => {
476488
<AmountInput
477489
supportedSourceTokens={supportedSourceTokens}
478490
error={amountValidation.error}
479-
warning={amountValidation.warning}
491+
warning={amountValidation.warning || walletWarning}
480492
/>
481493
{showRoutes && (
482494
<Routes

0 commit comments

Comments
 (0)