diff --git a/ethereum/env/.env.hyperliquid.testnet b/ethereum/env/.env.hyperliquid.testnet new file mode 100644 index 0000000000..c264c3237a --- /dev/null +++ b/ethereum/env/.env.hyperliquid.testnet @@ -0,0 +1,19 @@ +# Hyperliquid testnet env +# Rename to .env + +# Common config for forge deployment +RPC_URL="https://api.hyperliquid-testnet.xyz/evm" + +# Wormhole Core Migrations +INIT_SIGNERS=["0x13947Bd48b18E53fdAeEe77F3473391aC727C638"] +INIT_CHAIN_ID=47 +INIT_GOV_CHAIN_ID=0x1 +INIT_GOV_CONTRACT=0x0000000000000000000000000000000000000000000000000000000000000004 +INIT_EVM_CHAIN_ID=998 + +# Bridge Migrations +BRIDGE_INIT_CHAIN_ID=47 +BRIDGE_INIT_GOV_CHAIN_ID=0x1 +BRIDGE_INIT_GOV_CONTRACT=0x0000000000000000000000000000000000000000000000000000000000000004 +BRIDGE_INIT_WETH=0xADcb2f358Eae6492F61A5F87eb8893d09391d160 +BRIDGE_INIT_FINALITY=1 \ No newline at end of file diff --git a/node/cmd/guardiand/node.go b/node/cmd/guardiand/node.go index 0b2275502f..e981115ebc 100644 --- a/node/cmd/guardiand/node.go +++ b/node/cmd/guardiand/node.go @@ -201,6 +201,9 @@ var ( inkRPC *string inkContract *string + hyperliquidRPC *string + hyperliquidContract *string + sepoliaRPC *string sepoliaContract *string @@ -422,6 +425,9 @@ func init() { inkRPC = node.RegisterFlagWithValidationOrFail(NodeCmd, "inkRPC", "Ink RPC URL", "ws://eth-devnet:8545", []string{"ws", "wss"}) inkContract = NodeCmd.Flags().String("inkContract", "", "Ink contract address") + hyperliquidRPC = node.RegisterFlagWithValidationOrFail(NodeCmd, "hyperliquidRPC", "Hyperliquid RPC URL", "ws://eth-devnet:8545", []string{"ws", "wss"}) + hyperliquidContract = NodeCmd.Flags().String("hyperliquidContract", "", "Hyperliquid contract address") + arbitrumSepoliaRPC = node.RegisterFlagWithValidationOrFail(NodeCmd, "arbitrumSepoliaRPC", "Arbitrum on Sepolia RPC URL", "ws://eth-devnet:8545", []string{"ws", "wss"}) arbitrumSepoliaContract = NodeCmd.Flags().String("arbitrumSepoliaContract", "", "Arbitrum on Sepolia contract address") @@ -812,6 +818,7 @@ func runNode(cmd *cobra.Command, args []string) { *unichainContract = checkEvmArgs(logger, *unichainRPC, *unichainContract, "unichain", false) *worldchainContract = checkEvmArgs(logger, *worldchainRPC, *worldchainContract, "worldchain", true) *inkContract = checkEvmArgs(logger, *inkRPC, *inkContract, "ink", false) + *hyperliquidContract = checkEvmArgs(logger, *hyperliquidRPC, *hyperliquidContract, "hyperliquid", false) // These chains will only ever be testnet / devnet. *sepoliaContract = checkEvmArgs(logger, *sepoliaRPC, *sepoliaContract, "sepolia", false) @@ -928,6 +935,7 @@ func runNode(cmd *cobra.Command, args []string) { rpcMap["celoRPC"] = *celoRPC rpcMap["ethRPC"] = *ethRPC rpcMap["fantomRPC"] = *fantomRPC + rpcMap["hyperliquidRPC"] = *hyperliquidRPC rpcMap["ibcBlockHeightURL"] = *ibcBlockHeightURL rpcMap["ibcLCD"] = *ibcLCD rpcMap["ibcWS"] = *ibcWS @@ -1429,6 +1437,18 @@ func runNode(cmd *cobra.Command, args []string) { watcherConfigs = append(watcherConfigs, wc) } + if shouldStart(hyperliquidRPC) { + wc := &evm.WatcherConfig{ + NetworkID: "hyperliquid", + ChainID: vaa.ChainIDHyperliquid, + Rpc: *hyperliquidRPC, + Contract: *hyperliquidContract, + CcqBackfillCache: *ccqBackfillCache, + } + + watcherConfigs = append(watcherConfigs, wc) + } + if shouldStart(terraWS) { wc := &cosmwasm.WatcherConfig{ NetworkID: "terra", diff --git a/node/pkg/query/query.go b/node/pkg/query/query.go index ce82605db5..161b39862d 100644 --- a/node/pkg/query/query.go +++ b/node/pkg/query/query.go @@ -141,6 +141,7 @@ var perChainConfig = map[vaa.ChainID]PerChainConfig{ vaa.ChainIDOptimismSepolia: {NumWorkers: 1, TimestampCacheSupported: true}, vaa.ChainIDPolygonSepolia: {NumWorkers: 1, TimestampCacheSupported: true}, vaa.ChainIDMonadDevnet: {NumWorkers: 1, TimestampCacheSupported: true}, + vaa.ChainIDHyperliquid: {NumWorkers: 1, TimestampCacheSupported: true}, } // GetPerChainConfig returns the config for the specified chain. If the chain is not configured it returns an empty struct, diff --git a/node/pkg/watchers/evm/watcher.go b/node/pkg/watchers/evm/watcher.go index 67f611f509..d31654168d 100644 --- a/node/pkg/watchers/evm/watcher.go +++ b/node/pkg/watchers/evm/watcher.go @@ -720,6 +720,7 @@ func (w *Watcher) getFinality(ctx context.Context) (bool, bool, error) { w.chainID == vaa.ChainIDBSC || w.chainID == vaa.ChainIDEthereum || w.chainID == vaa.ChainIDHolesky || + w.chainID == vaa.ChainIDHyperliquid || w.chainID == vaa.ChainIDInk || w.chainID == vaa.ChainIDKarura || w.chainID == vaa.ChainIDMantle || diff --git a/sdk/testnet_consts.go b/sdk/testnet_consts.go index 85a00dc559..907d0e36b3 100644 --- a/sdk/testnet_consts.go +++ b/sdk/testnet_consts.go @@ -43,6 +43,7 @@ var knownTestnetTokenbridgeEmitters = map[vaa.ChainID]string{ vaa.ChainIDUnichain: "000000000000000000000000a10f2eF61dE1f19f586ab8B6F2EbA89bACE63F7a", vaa.ChainIDWorldchain: "000000000000000000000000430855B4D43b8AEB9D2B9869B74d58dda79C0dB2", vaa.ChainIDInk: "000000000000000000000000376428e7f26D5867e69201b275553C45B09EE090", + vaa.ChainIDHyperliquid: "0000000000000000000000004a8bc80Ed5a4067f1CCf107057b8270E0cC11A78", vaa.ChainIDSepolia: "000000000000000000000000DB5492265f6038831E89f495670FF909aDe94bd9", vaa.ChainIDHolesky: "00000000000000000000000076d093BbaE4529a342080546cAFEec4AcbA59EC6", vaa.ChainIDArbitrumSepolia: "000000000000000000000000C7A204bDBFe983FCD8d8E61D02b475D4073fF97e", diff --git a/sdk/vaa/structs.go b/sdk/vaa/structs.go index 4b59d6bacb..0c1eba0ffe 100644 --- a/sdk/vaa/structs.go +++ b/sdk/vaa/structs.go @@ -217,6 +217,8 @@ func (c ChainID) String() string { return "worldchain" case ChainIDInk: return "ink" + case ChainIDHyperliquid: + return "hyperliquid" case ChainIDCosmoshub: return "cosmoshub" case ChainIDEvmos: @@ -342,6 +344,8 @@ func ChainIDFromString(s string) (ChainID, error) { return ChainIDWorldchain, nil case "ink": return ChainIDInk, nil + case "hyperliquid": + return ChainIDHyperliquid, nil case "cosmoshub": return ChainIDCosmoshub, nil case "seievm": @@ -425,6 +429,7 @@ func GetAllNetworkIDs() []ChainID { ChainIDUnichain, ChainIDWorldchain, ChainIDInk, + ChainIDHyperliquid, ChainIDWormchain, ChainIDCosmoshub, ChainIDEvmos, @@ -531,6 +536,8 @@ const ( ChainIDWorldchain ChainID = 45 // ChainIDInk is the ChainID of Ink ChainIDInk ChainID = 46 + // ChainIDHyperliquid is the ChainID of Hyperliquid + ChainIDHyperliquid ChainID = 47 //ChainIDWormchain is the ChainID of Wormchain ChainIDWormchain ChainID = 3104 // ChainIDCosmoshub is the ChainID of Cosmoshub diff --git a/sdk/vaa/structs_test.go b/sdk/vaa/structs_test.go index 78bbb2b630..fcf005caaa 100644 --- a/sdk/vaa/structs_test.go +++ b/sdk/vaa/structs_test.go @@ -69,6 +69,7 @@ func TestChainIDFromString(t *testing.T) { {input: "unichain", output: ChainIDUnichain}, {input: "worldchain", output: ChainIDWorldchain}, {input: "ink", output: ChainIDInk}, + {input: "hyperliquid", output: ChainIDHyperliquid}, {input: "seievm", output: ChainIDSeiEVM}, {input: "wormchain", output: ChainIDWormchain}, {input: "cosmoshub", output: ChainIDCosmoshub}, @@ -129,6 +130,7 @@ func TestChainIDFromString(t *testing.T) { {input: "Unichain", output: ChainIDUnichain}, {input: "Worldchain", output: ChainIDWorldchain}, {input: "Ink", output: ChainIDInk}, + {input: "Hyperliquid", output: ChainIDHyperliquid}, {input: "SeiEVM", output: ChainIDSeiEVM}, {input: "Wormchain", output: ChainIDWormchain}, {input: "Cosmoshub", output: ChainIDCosmoshub}, @@ -330,6 +332,7 @@ func TestChainId_String(t *testing.T) { {input: 44, output: "unichain"}, {input: 45, output: "worldchain"}, {input: 46, output: "ink"}, + {input: 47, output: "hyperliquid"}, {input: 3104, output: "wormchain"}, {input: 4000, output: "cosmoshub"}, {input: 4001, output: "evmos"},