Skip to content

Commit 87903ab

Browse files
committed
ft_watcher: update logs
ft_watcher: this works ft_watcher: add mainnet solana addresses ft_watcher: add conditional to detect mainnet function selector ft_watcher: watcher runners update ft_watcher: update sdk const ft_watcher: update package-lock.json ft_watcher: handle missing vaa hash cases in testnet ft_watcher: fix evm time ft_watcher: update reference ft_watcher: clean up ft_watcher: update package-lock.json ft_watcher: plz fix ci ft_watcher: remove script ft_watcher: clean up Signed-off-by: bingyuyap <bingyu.yap.21@gmail.com>
1 parent cc55e94 commit 87903ab

11 files changed

+466
-220
lines changed

common/src/consts.ts

+5-1
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,11 @@ export const INITIAL_NTT_DEPLOYMENT_BLOCK_BY_NETWORK_AND_CHAIN: NetworkChainBloc
107107
};
108108

109109
export const INITIAL_FT_DEPLOYMENT_BLOCK_BY_NETWORK_AND_CHAIN: NetworkChainBlockMapping = {
110-
['Mainnet']: {},
110+
['Mainnet']: {
111+
Solana: '285350104',
112+
Arbitrum: '245882390',
113+
Base: '18956026',
114+
},
111115
['Testnet']: {
112116
Solana: '302162456',
113117
ArbitrumSepolia: '49505590',

common/src/utils.ts

+4
Original file line numberDiff line numberDiff line change
@@ -235,3 +235,7 @@ export async function retry<T>(
235235
}
236236
}
237237
}
238+
239+
export function stringifyWithBigInt(obj: any) {
240+
return JSON.stringify(obj, (_, value) => (typeof value === 'bigint' ? value.toString() : value));
241+
}

package-lock.json

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

watcher/package.json

+3-3
Original file line numberDiff line numberDiff line change
@@ -37,9 +37,9 @@
3737
"@solana/spl-token": "^0.4.6",
3838
"@solana/web3.js": "^1.73.0",
3939
"@types/bn.js": "^5.1.0",
40-
"@wormhole-foundation/example-liquidity-layer-definitions": "file:./sdk/wormhole-foundation-example-liquidity-layer-definitions-0.0.1.tgz",
41-
"@wormhole-foundation/example-liquidity-layer-evm": "file:./sdk/wormhole-foundation-example-liquidity-layer-evm-0.0.1.tgz",
42-
"@wormhole-foundation/example-liquidity-layer-solana": "file:./sdk/wormhole-foundation-example-liquidity-layer-solana-0.0.1.tgz",
40+
"@wormhole-foundation/example-liquidity-layer-definitions": "file:sdk/wormhole-foundation-example-liquidity-layer-definitions-0.0.1.tgz",
41+
"@wormhole-foundation/example-liquidity-layer-evm": "file:sdk/wormhole-foundation-example-liquidity-layer-evm-0.0.1.tgz",
42+
"@wormhole-foundation/example-liquidity-layer-solana": "file:sdk/wormhole-foundation-example-liquidity-layer-solana-0.0.1.tgz",
4343
"@wormhole-foundation/wormhole-monitor-common": "^0.0.1",
4444
"algosdk": "^2.4.0",
4545
"anchor-0.29.0": "npm:@coral-xyz/anchor@^0.29.0",
Binary file not shown.

watcher/src/fastTransfer/consts.ts

+48-12
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,19 @@
1-
import { Network } from '@wormhole-foundation/sdk-base';
1+
import { Chain, Network } from '@wormhole-foundation/sdk-base';
22

33
export type FastTransferContracts = 'MatchingEngine' | 'TokenRouter' | 'USDCMint';
44

5-
// Will define more as we know what the mainnet addresses are
6-
export type MatchingEngineProgramId = 'mPydpGUWxzERTNpyvTKdvS7v8kvw5sgwfiP8WQFrXVS';
7-
export type TokenRouterProgramId = 'tD8RmtdcV7bzBeuFgyrFc8wvayj988ChccEzRQzo6md';
8-
export type USDCMintAddress = '4zMMC9srt5Ri5X14GAgXhaHii3GnPAEERYPJgZJDncDU';
9-
export type SwapLayerProgramId = 'SwapLayer1111111111111111111111111111111111';
5+
export type MatchingEngineProgramId =
6+
| 'mPydpGUWxzERTNpyvTKdvS7v8kvw5sgwfiP8WQFrXVS'
7+
| 'HtkeCDdYY4i9ncAxXKjYTx8Uu3WM8JbtiLRYjtHwaVXb';
8+
export type TokenRouterProgramId =
9+
| 'tD8RmtdcV7bzBeuFgyrFc8wvayj988ChccEzRQzo6md'
10+
| '28topqjtJzMnPaGFmmZk68tzGmj9W9aMntaEK3QkgtRe';
11+
export type USDCMintAddress =
12+
| '4zMMC9srt5Ri5X14GAgXhaHii3GnPAEERYPJgZJDncDU'
13+
| 'EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v';
14+
export type SwapLayerProgramId =
15+
| 'SwapLayer1111111111111111111111111111111111'
16+
| '9Zv8ajzFjacRoYCgCPus4hq3pYjpNa9KkTFQ1sHa1h3d';
1017

1118
export interface SolanaContractAddresses {
1219
MatchingEngine: MatchingEngineProgramId;
@@ -27,15 +34,30 @@ export type ContractAddresses = SolanaContractAddresses | EthereumContractAddres
2734

2835
export type FastTransferContractAddresses = {
2936
[key in Network]?: {
30-
Solana?: SolanaContractAddresses;
31-
ArbitrumSepolia?: EthereumContractAddresses;
32-
Ethereum?: EthereumContractAddresses;
37+
// For each chain, use SolanaContractAddresses if it's Solana, otherwise use EthereumContractAddresses
38+
[chain in Chain]?: chain extends 'Solana' ? SolanaContractAddresses : EthereumContractAddresses;
3339
};
3440
};
3541

3642
// Will add more chains as needed
3743
export const FAST_TRANSFER_CONTRACTS: FastTransferContractAddresses = {
38-
Mainnet: {},
44+
Mainnet: {
45+
Solana: {
46+
MatchingEngine: 'HtkeCDdYY4i9ncAxXKjYTx8Uu3WM8JbtiLRYjtHwaVXb',
47+
TokenRouter: '28topqjtJzMnPaGFmmZk68tzGmj9W9aMntaEK3QkgtRe',
48+
USDCMint: 'EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v',
49+
// TODO: uncomment this when SwapLayer is deployed on Solana Mainnet
50+
// SwapLayer: '9Zv8ajzFjacRoYCgCPus4hq3pYjpNa9KkTFQ1sHa1h3d',
51+
},
52+
Arbitrum: {
53+
TokenRouter: '0x70287c79ee41C5D1df8259Cd68Ba0890cd389c47',
54+
CircleBridge: '0x19330d10D9Cc8751218eaf51E8885D058642E08A',
55+
},
56+
Base: {
57+
TokenRouter: '0x70287c79ee41C5D1df8259Cd68Ba0890cd389c47',
58+
CircleBridge: '0x1682Ae6375C4E4A97e4B583BC394c861A46D8962',
59+
},
60+
},
3961
Testnet: {
4062
Solana: {
4163
MatchingEngine: 'mPydpGUWxzERTNpyvTKdvS7v8kvw5sgwfiP8WQFrXVS',
@@ -49,5 +71,19 @@ export const FAST_TRANSFER_CONTRACTS: FastTransferContractAddresses = {
4971
},
5072
};
5173

52-
// Will add more chains as needed
53-
export type FTChains = 'ArbitrumSepolia';
74+
// Separate testnet and mainnet chains
75+
export type FTEVMMainnetChain = 'Arbitrum' | 'Base';
76+
export type FTEVMTestnetChain = 'ArbitrumSepolia';
77+
export type FTEVMChain = FTEVMMainnetChain | FTEVMTestnetChain;
78+
79+
export const FTEVMMainnetChains: FTEVMMainnetChain[] = ['Arbitrum', 'Base'];
80+
export const FTEVMTestnetChains: FTEVMTestnetChain[] = ['ArbitrumSepolia'];
81+
82+
export const isFTEVMChain = (chain: Chain, network: Network): chain is FTEVMChain => {
83+
if (network === 'Mainnet') {
84+
return FTEVMMainnetChains.includes(chain as FTEVMMainnetChain);
85+
} else if (network === 'Testnet') {
86+
return FTEVMTestnetChains.includes(chain as FTEVMTestnetChain);
87+
}
88+
return false;
89+
};

watcher/src/fastTransfer/tokenRouter/parser.ts

+16-12
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ import {
1010
contracts,
1111
toChainId,
1212
} from '@wormhole-foundation/sdk-base';
13-
import { FAST_TRANSFER_CONTRACTS, FTChains } from '../consts';
13+
import { FAST_TRANSFER_CONTRACTS, FTEVMChain } from '../consts';
1414
import isNotNull from '../../../src/utils/isNotNull';
1515
import { MarketOrder } from '../types';
1616

@@ -19,17 +19,8 @@ class TokenRouterParser {
1919
private evmTokenRouter: EvmTokenRouter;
2020
private network: Network;
2121
private chain: Chain;
22-
// the only 2 functions we care about
23-
private functionSelectors = [
24-
ethers.utils
25-
.id('placeFastMarketOrder(uint64,uint64,uint16,bytes32,bytes,address,uint64,uint32)')
26-
.substring(0, 10),
27-
ethers.utils
28-
.id('placeFastMarketOrder(uint64,uint16,bytes32,bytes,uint64,uint32)')
29-
.substring(0, 10),
30-
];
31-
32-
constructor(network: Network, chain: FTChains, provider: ethers.providers.JsonRpcProvider) {
22+
private functionSelectors: string[];
23+
constructor(network: Network, chain: FTEVMChain, provider: ethers.providers.JsonRpcProvider) {
3324
this.provider = provider;
3425
this.evmTokenRouter = new EvmTokenRouter(
3526
this.provider,
@@ -38,6 +29,19 @@ class TokenRouterParser {
3829
);
3930
this.network = network;
4031
this.chain = chain;
32+
// on Mainnet the TokenRouter is called via a SwapLayer proxy contract using the `initiate` method
33+
// on Testnet there is no Swaplayer so we check using the primitive methods
34+
this.functionSelectors =
35+
this.network === 'Mainnet'
36+
? [ethers.utils.id('initiate(uint16,bytes32,bytes)').substring(0, 10)]
37+
: [
38+
ethers.utils
39+
.id('placeFastMarketOrder(uint64,uint64,uint16,bytes32,bytes,address,uint64,uint32)')
40+
.substring(0, 10),
41+
ethers.utils
42+
.id('placeFastMarketOrder(uint64,uint16,bytes32,bytes,uint64,uint32)')
43+
.substring(0, 10),
44+
];
4145
}
4246

4347
async parseFastMarketOrder(txHash: string): Promise<LiquidityLayerTransactionResult | null> {

watcher/src/index.ts

+3-1
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import { initDb } from './databases/utils';
55
import { Mode, getNetwork, getMode } from '@wormhole-foundation/wormhole-monitor-common';
66
import { startSupervisor } from './workers/supervisor';
77
import { Chain, Network } from '@wormhole-foundation/sdk-base';
8+
import { FTEVMMainnetChains, FTEVMTestnetChains } from './fastTransfer/consts';
89

910
initDb();
1011

@@ -93,7 +94,8 @@ const supportedNTTChains: Chain[] =
9394
? ['Solana', 'Sepolia', 'ArbitrumSepolia', 'BaseSepolia', 'OptimismSepolia']
9495
: ['Solana', 'Ethereum', 'Fantom', 'Arbitrum', 'Optimism', 'Base'];
9596

96-
const supportedFTChains: Chain[] = network === 'Testnet' ? ['Solana', 'ArbitrumSepolia'] : [];
97+
const supportedFTChains: Chain[] =
98+
network === 'Testnet' ? ['Solana', ...FTEVMTestnetChains] : ['Solana', ...FTEVMMainnetChains];
9799

98100
if (mode === 'vaa') {
99101
startSupervisor(supportedChains);

watcher/src/watchers/FTEVMWatcher.ts

+4-4
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import knex, { Knex } from 'knex';
22
import { Watcher } from './Watcher';
33
import { Network } from '@wormhole-foundation/sdk-base';
44
import { assertEnvironmentVariable } from '@wormhole-foundation/wormhole-monitor-common';
5-
import { FAST_TRANSFER_CONTRACTS, FTChains } from '../fastTransfer/consts';
5+
import { FAST_TRANSFER_CONTRACTS, FTEVMChain } from '../fastTransfer/consts';
66
import { ethers } from 'ethers';
77
import { AXIOS_CONFIG_JSON, RPCS_BY_CHAIN } from '../consts';
88
import { makeBlockKey } from '../databases/utils';
@@ -29,7 +29,7 @@ export class FTEVMWatcher extends Watcher {
2929

3030
constructor(
3131
network: Network,
32-
chain: FTChains,
32+
chain: FTEVMChain,
3333
finalizedBlockTag: BlockTag = 'latest',
3434
isTest = false
3535
) {
@@ -154,8 +154,8 @@ export class FTEVMWatcher extends Watcher {
154154
}
155155

156156
// we do not need to compare the lastBlockTime from tokenRouter and swapLayer as they both use toBlock
157-
const lastBlockTime = tokenRouterResults.lastBlockTime;
158-
return makeBlockKey(toBlock.toString(), lastBlockTime.toString());
157+
const lastBlockTime = new Date(tokenRouterResults.lastBlockTime * 1000);
158+
return makeBlockKey(toBlock.toString(), lastBlockTime.toISOString());
159159
}
160160

161161
// saves items in smaller batches to reduce the impact in any case anything fails

0 commit comments

Comments
 (0)