From 70ac0abe8c59e989ddd640290d133e35183e7031 Mon Sep 17 00:00:00 2001 From: sprites0 <199826320+sprites0@users.noreply.github.com> Date: Sun, 22 Jun 2025 14:54:37 -0400 Subject: [PATCH] feat: System transaction map --- src/node/mod.rs | 1 + src/node/spot_meta.rs | 66 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 67 insertions(+) create mode 100644 src/node/spot_meta.rs diff --git a/src/node/mod.rs b/src/node/mod.rs index da5e127da..4d39eb1a7 100644 --- a/src/node/mod.rs +++ b/src/node/mod.rs @@ -37,6 +37,7 @@ pub mod evm; pub mod network; pub mod primitives; pub mod rpc; +pub mod spot_meta; pub mod storage; pub mod types; diff --git a/src/node/spot_meta.rs b/src/node/spot_meta.rs new file mode 100644 index 000000000..71b483550 --- /dev/null +++ b/src/node/spot_meta.rs @@ -0,0 +1,66 @@ +use alloy_primitives::{Address, U256}; +use eyre::{Error, Result}; +use serde::{Deserialize, Serialize}; +use std::collections::BTreeMap; + +pub(crate) const MAINNET_CHAIN_ID: u64 = 999; +pub(crate) const TESTNET_CHAIN_ID: u64 = 998; + +#[derive(Debug, Clone, Serialize, Deserialize)] +struct EvmContract { + address: Address, +} + +#[derive(Debug, Clone, Serialize, Deserialize)] +struct SpotToken { + index: u64, + #[serde(rename = "evmContract")] + evm_contract: Option, +} + +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct SpotMeta { + tokens: Vec, +} + +#[derive(Debug, Clone)] +pub(crate) struct SpotId { + pub index: u64, +} + +impl SpotId { + pub(crate) fn to_s(&self) -> U256 { + let mut addr = [0u8; 32]; + addr[12] = 0x20; + addr[24..32].copy_from_slice(self.index.to_be_bytes().as_ref()); + U256::from_be_bytes(addr) + } +} + +async fn fetch_spot_meta(chain_id: u64) -> Result { + let url = match chain_id { + MAINNET_CHAIN_ID => "https://api.hyperliquid.xyz/info", + TESTNET_CHAIN_ID => "https://api.hyperliquid-testnet.xyz/info", + _ => return Err(Error::msg("unknown chain id")), + }; + let client = reqwest::Client::new(); + let response = client + .post(url) + .json(&serde_json::json!({"type": "spotMeta"})) + .send() + .await?; + Ok(response.json().await?) +} + +pub(crate) async fn erc20_contract_to_spot_token( + chain_id: u64, +) -> Result> { + let meta = fetch_spot_meta(chain_id).await?; + let mut map = BTreeMap::new(); + for token in &meta.tokens { + if let Some(evm_contract) = &token.evm_contract { + map.insert(evm_contract.address, SpotId { index: token.index }); + } + } + Ok(map) +}