diff --git a/common/primitives/core/src/omni/intent.rs b/common/primitives/core/src/omni/intent.rs index 5515a3eff0..dc061748f4 100644 --- a/common/primitives/core/src/omni/intent.rs +++ b/common/primitives/core/src/omni/intent.rs @@ -93,8 +93,11 @@ pub enum SingleChainSwapProvider { pub struct PumpxConfig { pub order_type: PumpxOrderType, pub swap_type: u32, // 1:buy 2:sell - pub chain_id: u32, // to align with pumpx: sol:10000 eth:1 bsc:56 base:8453 - pub token_ca: BoundedVec, + pub from_chain_id: u32, + pub from_token_ca: BoundedVec, + pub to_chain_id: u32, + pub to_token_ca: BoundedVec, + pub from_amount: BoundedVec, pub double_out: bool, pub is_one_click: bool, pub is_anti_mev: bool, diff --git a/tee-worker/omni-executor/Cargo.lock b/tee-worker/omni-executor/Cargo.lock index 7f240abe62..f4d9260263 100644 --- a/tee-worker/omni-executor/Cargo.lock +++ b/tee-worker/omni-executor/Cargo.lock @@ -7348,10 +7348,13 @@ dependencies = [ name = "pumpx" version = "0.1.0" dependencies = [ + "base58", "executor-core", "executor-crypto", + "executor-primitives", "hex", "jsonrpsee", + "libsecp256k1 0.7.2", "log", "parity-scale-codec", "rand 0.8.5", diff --git a/tee-worker/omni-executor/Cargo.toml b/tee-worker/omni-executor/Cargo.toml index 3baab99f2e..5be317eae1 100644 --- a/tee-worker/omni-executor/Cargo.toml +++ b/tee-worker/omni-executor/Cargo.toml @@ -50,6 +50,7 @@ hex-literal = "0.4" hmac = "0.12.1" jsonrpsee = { version = "0.24", features = ["server"] } jsonwebtoken = "9.3.0" +libsecp256k1 = "0.7.1" log = "0.4.22" mockall = "0.13.1" parity-scale-codec = "3.6.12" diff --git a/tee-worker/omni-executor/executor-core/src/native_task.rs b/tee-worker/omni-executor/executor-core/src/native_task.rs index e6e0ddff08..f1c8ac8ced 100644 --- a/tee-worker/omni-executor/executor-core/src/native_task.rs +++ b/tee-worker/omni-executor/executor-core/src/native_task.rs @@ -49,6 +49,7 @@ pub enum NativeTask { #[codec(index = 24)] PumpxTransferWidthdraw( Identity, + Option, // request_id u32, // chain_id u32, // wallet_index String, // recipient_address diff --git a/tee-worker/omni-executor/executor-primitives/src/lib.rs b/tee-worker/omni-executor/executor-primitives/src/lib.rs index b7a29d8e0f..971ae911b7 100644 --- a/tee-worker/omni-executor/executor-primitives/src/lib.rs +++ b/tee-worker/omni-executor/executor-primitives/src/lib.rs @@ -25,8 +25,8 @@ pub use auth::*; pub mod signature; pub mod utils; pub use heima_primitives::{ - omni::*, teebag::DcapQuote, AccountId, BlockNumber, Hash, Identity, MrEnclave, Nonce, - ShardIdentifier, Web2IdentityType, + omni::*, teebag::DcapQuote, AccountId, BlockNumber, ChainAsset, Hash, Identity, MrEnclave, + Nonce, ShardIdentifier, Web2IdentityType, }; use std::fmt::Debug; diff --git a/tee-worker/omni-executor/intent/executors/cross-chain/src/lib.rs b/tee-worker/omni-executor/intent/executors/cross-chain/src/lib.rs index 94bd0e6b9b..3b9b2c7689 100644 --- a/tee-worker/omni-executor/intent/executors/cross-chain/src/lib.rs +++ b/tee-worker/omni-executor/intent/executors/cross-chain/src/lib.rs @@ -17,7 +17,6 @@ use async_trait::async_trait; use executor_core::intent_executor::IntentExecutor; use executor_primitives::utils::hex::ToHexPrefixed; -use executor_primitives::ChainAsset; use executor_primitives::Intent; use executor_primitives::IntentId; use executor_primitives::PumpxOrderType; @@ -34,7 +33,6 @@ use heima_authentication::auth_token::AUTH_TOKEN_ACCESS_TYPE; use parity_scale_codec::Encode; use pumpx::signer_client::ChainType; use pumpx::signer_client::SignerClient; -use pumpx::types::ChainId; use pumpx::types::CreateCrossOrderData; use pumpx::types::CrossOrderInfo; use pumpx::types::GasType; @@ -43,6 +41,7 @@ use pumpx::types::NewLimitOrder; use pumpx::types::NewMarketOrder; use pumpx::types::SwapType; use pumpx::PumpxApi; +use pumpx::{pubkey_to_evm_address, pubkey_to_solana_address}; use std::collections::HashMap; use std::marker::PhantomData; use std::sync::Arc; @@ -136,7 +135,7 @@ impl< intent: Intent, ) -> Result>, ()> { match intent { - Intent::Swap(ref swap_order, ref _ccsp, ref scsp) => { + Intent::Swap(ref _swap_order, ref _ccsp, ref scsp) => { let Ok(mut rpc_client) = self.parentchain_rpc_client_factory.new_client().await else { log::error!("Failed to create rpc client"); @@ -188,12 +187,6 @@ impl< // )?; // - let from_amount_string = std::str::from_utf8(&swap_order.from_amount) - .map_err(|_| { - log::error!("Failed to parse from_amount_string"); - }) - .map(|v| v.to_string())?; - let intent_accepted_event_emit_call = parentchain_api_interface::tx() .omni_account() .intent_accepted(account_id.to_subxt_type(), intent_id, intent.to_subxt_type()); @@ -211,31 +204,29 @@ impl< // TODO: update this when we have more providers let SingleChainSwapProvider::Pumpx(pumpx_config) = scsp; - let chain_id = match swap_order.to_asset { - ChainAsset::Ethereum(..) => ChainId::EVM, - ChainAsset::Solana(_) => ChainId::Solana, - }; let usd_worth = std::str::from_utf8(&pumpx_config.usd_worth) .map_err(|_| { log::error!("Failed to parse usd_worth"); }) .map(|v| v.to_string())?; - let token_ca = std::str::from_utf8(&pumpx_config.token_ca) + + let from_token_ca = std::str::from_utf8(&pumpx_config.from_token_ca) .map_err(|_| { - log::error!("Failed to parse token_ca"); + log::error!("Failed to parse from_token_ca"); + }) + .map(|v| v.to_string())?; + + let to_token_ca = std::str::from_utf8(&pumpx_config.to_token_ca) + .map_err(|_| { + log::error!("Failed to parse to_token_ca"); }) .map(|v| v.to_string())?; - let Some(chain_type) = ChainType::from_pumpx_chain_id(chain_id.to_number() as u32) - else { - log::error!("Unsupported chain id: {:?}", chain_id); - return Err(()); - }; - let wallet_address = self - .pumpx_signer_client - .request_wallet(chain_type, pumpx_config.wallet_index, *account_id.as_ref()) - .await - .map_err(|e| log::error!("Could not get wallet from pumpx-signer: {:?}", e))?; + let from_amount = std::str::from_utf8(&pumpx_config.from_amount) + .map_err(|_| { + log::error!("Failed to parse from_amount"); + }) + .map(|v| v.to_string())?; let storage = PumpxJwtStorage::new(self.storage_db.clone()); let Some(access_token) = storage.get(&(account_id.clone(), AUTH_TOKEN_ACCESS_TYPE)) @@ -246,18 +237,27 @@ impl< let pumpx_order_response: Option>; - if swap_order.from_asset.is_same_chain(&swap_order.to_asset) { - let user_trade_info = - self.pumpx_api.get_user_trade_info(&access_token).await.map_err(|_| { - log::error!("Failed to get user trade info"); + if pumpx_config.from_chain_id == pumpx_config.to_chain_id { + let Some(chain_type) = ChainType::from_pumpx_chain_id(pumpx_config.to_chain_id) + else { + log::error!("Unsupported to_chain_id: {}", pumpx_config.to_chain_id); + return Err(()); + }; + + let wallet_address = self + .pumpx_signer_client + .request_wallet(chain_type, pumpx_config.wallet_index, *account_id.as_ref()) + .await + .map_err(|e| { + log::error!("Could not get wallet from pumpx-signer: {:?}", e) })?; let order_response = match pumpx_config.order_type { PumpxOrderType::Market => { let new_market_order = NewMarketOrder { request_id: intent_id, - chain_id: chain_id.clone(), - token_ca, + chain_id: pumpx_config.to_chain_id, + token_ca: to_token_ca.clone(), swap_type: match pumpx_config.swap_type { 1 => SwapType::Buy, 2 => SwapType::Sell, @@ -269,12 +269,19 @@ impl< return Err(()); }, }, - amount_in: from_amount_string.clone(), + amount_in: from_amount.clone(), double_out: pumpx_config.double_out, is_one_click: pumpx_config.is_one_click, - address: wallet_address.to_hex(), - is_anti_mev: user_trade_info.data.is_anti_mev, - is_auto_slippage: user_trade_info.data.is_auto_slippage, + address: match chain_type { + ChainType::Evm => pubkey_to_evm_address(&wallet_address)?, + ChainType::Solana => pubkey_to_solana_address(&wallet_address)?, + _ => { + log::error!("Unsupported {:?} wallet address", chain_type); + return Err(()); + }, + }, + is_anti_mev: pumpx_config.is_anti_mev, + is_auto_slippage: pumpx_config.is_auto_slippage, gas_type: match pumpx_config.gas_type { 1 => GasType::Slow, 2 => GasType::Medium, @@ -287,10 +294,10 @@ impl< return Err(()); }, }, - slippage: user_trade_info.data.slippage, + slippage: pumpx_config.slippage, wallet_index: pumpx_config.wallet_index, }; - let market_order_unsigned_tx = self + let market_order_unsigned_tx_res = self .pumpx_api .create_market_order_unsigned_tx(&access_token, new_market_order) .await @@ -298,7 +305,7 @@ impl< log::error!("Failed to create market order unsigned tx"); })?; - let tx_data = market_order_unsigned_tx.data.tx_data; + let tx_data = market_order_unsigned_tx_res.data.tx_data; let mut messages_to_sign = Vec::new(); for tx in tx_data { let tx_cleaned = tx.strip_prefix("0x").unwrap_or(&tx); @@ -312,13 +319,6 @@ impl< messages_to_sign.push(tx_bytes); } - let Some(chain_type) = - ChainType::from_pumpx_chain_id(chain_id.to_number() as u32) - else { - log::error!("Unsupported chain id: {:?}", chain_id); - return Err(()); - }; - let signatures = match self .pumpx_signer_client .request_signatures( @@ -344,13 +344,13 @@ impl< .collect(); let market_order_tx = MarketOrderTx { - order_id: market_order_unsigned_tx.data.order_id, + order_id: market_order_unsigned_tx_res.data.order_id, + chain_id: market_order_unsigned_tx_res.data.chain_id, tx_data: signed_tx_data, - chain_id: chain_id.clone(), }; let market_order_tx_res = self .pumpx_api - .send_market_order_tx(&access_token, market_order_tx) + .send_order_tx(&access_token, market_order_tx) .await .map_err(|_| { log::error!("Failed to send market order tx"); @@ -381,9 +381,9 @@ impl< let new_limit_order = NewLimitOrder { request_id: intent_id, - chain_id: chain_id.clone(), - token_ca, - amount: from_amount_string.clone(), + chain_id: pumpx_config.to_chain_id, + token_ca: to_token_ca, + amount: from_amount, swap_type: match pumpx_config.swap_type { 1 => SwapType::Buy, 2 => SwapType::Sell, @@ -401,9 +401,16 @@ impl< trailing_percent: pumpx_config .trailing_percent .map(|v| v.to_string()), - address: wallet_address.to_hex(), - is_anti_mev: user_trade_info.data.is_anti_mev, - is_auto_slippage: user_trade_info.data.is_auto_slippage, + address: match chain_type { + ChainType::Evm => pubkey_to_evm_address(&wallet_address)?, + ChainType::Solana => pubkey_to_solana_address(&wallet_address)?, + _ => { + log::error!("Unsupported {:?} wallet address", chain_type); + return Err(()); + }, + }, + is_anti_mev: pumpx_config.is_anti_mev, + is_auto_slippage: pumpx_config.is_auto_slippage, gas_type: match pumpx_config.gas_type { 1 => GasType::Slow, 2 => GasType::Medium, @@ -416,10 +423,10 @@ impl< return Err(()); }, }, - slippage: user_trade_info.data.slippage, + slippage: pumpx_config.slippage, wallet_index: pumpx_config.wallet_index, }; - let limit_order_response = self + let limit_order_res = self .pumpx_api .create_limit_order(&access_token, new_limit_order) .await @@ -427,22 +434,79 @@ impl< log::error!("Failed to create limit order"); })?; - limit_order_response.encode() + limit_order_res.encode() }, }; pumpx_order_response = Some(order_response); } else { // notify backend about it + let Some(from_chain_type) = + ChainType::from_pumpx_chain_id(pumpx_config.from_chain_id) + else { + log::error!("Unsupported from_chain_id: {}", pumpx_config.from_chain_id); + return Err(()); + }; + + let Some(to_chain_type) = + ChainType::from_pumpx_chain_id(pumpx_config.to_chain_id) + else { + log::error!("Unsupported to_chain_id: {}", pumpx_config.to_chain_id); + return Err(()); + }; + + let from_wallet_address = self + .pumpx_signer_client + .request_wallet( + from_chain_type, + pumpx_config.wallet_index, + *account_id.as_ref(), + ) + .await + .map_err(|e| { + log::error!("Could not get from_wallet from pumpx-signer: {:?}", e) + })?; + + let _to_wallet_address = self + .pumpx_signer_client + .request_wallet( + to_chain_type, + pumpx_config.wallet_index, + *account_id.as_ref(), + ) + .await + .map_err(|e| { + log::error!("Could not get to_wallet from pumpx-signer: {:?}", e) + })?; + let cross_order_data = CreateCrossOrderData { request_id: intent_id, - chain_id: chain_id.clone(), - info: vec![CrossOrderInfo { - chain_id: chain_id.clone(), + chain_id: pumpx_config.to_chain_id, + token_ca: to_token_ca, + swap_type: match pumpx_config.swap_type { + 1 => SwapType::Buy, + 2 => SwapType::Sell, + _ => { + log::error!("Unsupported swap type: {}", pumpx_config.swap_type); + return Err(()); + }, + }, + is_one_click: pumpx_config.is_one_click, + cross_info: vec![CrossOrderInfo { + chain_id: pumpx_config.from_chain_id, wallet_index: pumpx_config.wallet_index, - address: wallet_address.to_hex(), - amount: from_amount_string.clone(), + address: match from_chain_type { + ChainType::Evm => pubkey_to_evm_address(&from_wallet_address)?, + ChainType::Solana => { + pubkey_to_solana_address(&from_wallet_address)? + }, + _ => { + log::error!("Unsupported {:?} wallet address", from_chain_type); + return Err(()); + }, + }, + amount: from_amount, usd: usd_worth, - token_ca: token_ca.clone(), + token_ca: from_token_ca, }], }; self.pumpx_api diff --git a/tee-worker/omni-executor/native-task-handler/src/lib.rs b/tee-worker/omni-executor/native-task-handler/src/lib.rs index 57c2d14d1f..2ad238b426 100644 --- a/tee-worker/omni-executor/native-task-handler/src/lib.rs +++ b/tee-worker/omni-executor/native-task-handler/src/lib.rs @@ -32,6 +32,7 @@ use parentchain_signer::TxSigner; use parity_scale_codec::{Decode, Encode}; use pumpx::{ signer_client::{ChainType, SignerClient}, + types::{TransferTx, TransferUnsignedTx}, PumpxApi, }; use std::{marker::PhantomData, sync::Arc}; @@ -784,6 +785,7 @@ async fn handle_native_task< }, NativeTask::PumpxTransferWidthdraw( sender, + request_id, chain_id, wallet_index, recipient_address, @@ -831,17 +833,17 @@ async fn handle_native_task< } // 3. Create an unsigned tx with Pumpx backend + let unsigned_tx = TransferUnsignedTx { + request_id, + chain_id, + wallet_index, + recipient_address: recipient_address.to_string(), + token_ca: token_ca.to_string(), + amount: amount.to_string(), + }; let create_transfer_res = match ctx .pumpx_api - .create_transfer_unsigned_tx( - &access_token, - chain_id, - wallet_index, - &recipient_address, - &token_ca, - &amount, - language.clone(), - ) + .create_transfer_unsigned_tx(&access_token, unsigned_tx, language.clone()) .await { Ok(res) => res, @@ -925,9 +927,10 @@ async fn handle_native_task< signatures.into_iter().map(|sig| sig.to_hex()).collect(); // 5. Send the signed tx to the Pumpx backend + let signed_transfer_tx = TransferTx { chain_id, tx_data: signed_tx_data, transfer_id }; match ctx .pumpx_api - .send_transfer_tx(&access_token, transfer_id, chain_id, signed_tx_data, language) + .send_transfer_tx(&access_token, signed_transfer_tx, language) .await { Ok(res) => { diff --git a/tee-worker/omni-executor/parentchain/api-interface/artifacts/metadata.scale b/tee-worker/omni-executor/parentchain/api-interface/artifacts/metadata.scale index 7dd26c2e94..ee7b738cc9 100644 Binary files a/tee-worker/omni-executor/parentchain/api-interface/artifacts/metadata.scale and b/tee-worker/omni-executor/parentchain/api-interface/artifacts/metadata.scale differ diff --git a/tee-worker/omni-executor/parentchain/api-interface/src/interface.rs b/tee-worker/omni-executor/parentchain/api-interface/src/interface.rs index 85c311da68..47a696d9dc 100644 --- a/tee-worker/omni-executor/parentchain/api-interface/src/interface.rs +++ b/tee-worker/omni-executor/parentchain/api-interface/src/interface.rs @@ -1306,9 +1306,9 @@ pub mod api { "query_call_info", types::QueryCallInfo { call, len }, [ - 240u8, 63u8, 149u8, 182u8, 206u8, 132u8, 148u8, 147u8, 230u8, 44u8, - 174u8, 48u8, 241u8, 219u8, 160u8, 142u8, 115u8, 133u8, 22u8, 64u8, 2u8, - 74u8, 236u8, 130u8, 99u8, 48u8, 232u8, 148u8, 187u8, 59u8, 53u8, 29u8, + 248u8, 15u8, 73u8, 67u8, 45u8, 156u8, 204u8, 198u8, 245u8, 8u8, 195u8, + 142u8, 34u8, 132u8, 212u8, 36u8, 249u8, 234u8, 48u8, 205u8, 105u8, + 179u8, 32u8, 99u8, 66u8, 188u8, 46u8, 45u8, 95u8, 224u8, 236u8, 226u8, ], ) } @@ -1326,10 +1326,9 @@ pub mod api { "query_call_fee_details", types::QueryCallFeeDetails { call, len }, [ - 18u8, 140u8, 148u8, 211u8, 96u8, 42u8, 145u8, 49u8, 144u8, 88u8, 41u8, - 141u8, 156u8, 36u8, 29u8, 132u8, 129u8, 125u8, 225u8, 11u8, 113u8, - 180u8, 221u8, 85u8, 17u8, 97u8, 155u8, 233u8, 100u8, 89u8, 105u8, - 121u8, + 175u8, 170u8, 86u8, 53u8, 199u8, 52u8, 167u8, 68u8, 250u8, 88u8, 72u8, + 163u8, 28u8, 45u8, 30u8, 115u8, 214u8, 103u8, 167u8, 37u8, 86u8, 118u8, + 178u8, 235u8, 53u8, 132u8, 43u8, 95u8, 55u8, 250u8, 36u8, 231u8, ], ) } @@ -3070,9 +3069,9 @@ pub mod api { .hash(); runtime_metadata_hash == [ - 69u8, 129u8, 102u8, 154u8, 15u8, 99u8, 178u8, 22u8, 124u8, 109u8, 8u8, 176u8, - 137u8, 218u8, 231u8, 239u8, 29u8, 185u8, 143u8, 22u8, 199u8, 186u8, 37u8, 30u8, - 248u8, 150u8, 59u8, 253u8, 157u8, 87u8, 135u8, 178u8, + 55u8, 231u8, 61u8, 12u8, 174u8, 33u8, 144u8, 82u8, 146u8, 214u8, 98u8, 186u8, + 149u8, 53u8, 137u8, 246u8, 101u8, 219u8, 95u8, 185u8, 233u8, 223u8, 201u8, 109u8, + 184u8, 122u8, 129u8, 46u8, 43u8, 214u8, 125u8, 232u8, ] } pub mod system { @@ -4225,10 +4224,9 @@ pub mod api { "Events", (), [ - 130u8, 196u8, 219u8, 162u8, 105u8, 35u8, 60u8, 167u8, 240u8, 88u8, - 193u8, 116u8, 139u8, 25u8, 197u8, 233u8, 56u8, 61u8, 101u8, 225u8, - 184u8, 201u8, 200u8, 169u8, 59u8, 20u8, 53u8, 124u8, 5u8, 134u8, 242u8, - 79u8, + 224u8, 95u8, 86u8, 40u8, 202u8, 98u8, 210u8, 60u8, 177u8, 213u8, 35u8, + 104u8, 152u8, 248u8, 186u8, 227u8, 22u8, 230u8, 243u8, 120u8, 86u8, + 73u8, 129u8, 228u8, 83u8, 76u8, 85u8, 161u8, 8u8, 61u8, 49u8, 209u8, ], ) } @@ -6566,10 +6564,9 @@ pub mod api { auth_type, }, [ - 161u8, 116u8, 23u8, 170u8, 185u8, 247u8, 10u8, 14u8, 8u8, 135u8, 153u8, - 196u8, 91u8, 117u8, 115u8, 181u8, 222u8, 177u8, 120u8, 92u8, 149u8, - 205u8, 233u8, 176u8, 12u8, 80u8, 233u8, 206u8, 69u8, 49u8, 182u8, - 245u8, + 52u8, 136u8, 169u8, 135u8, 53u8, 247u8, 129u8, 253u8, 82u8, 237u8, + 161u8, 249u8, 140u8, 1u8, 60u8, 2u8, 83u8, 234u8, 84u8, 61u8, 63u8, + 255u8, 121u8, 95u8, 92u8, 70u8, 47u8, 38u8, 220u8, 113u8, 199u8, 171u8, ], ) } @@ -6589,10 +6586,9 @@ pub mod api { auth_type, }, [ - 80u8, 145u8, 240u8, 174u8, 102u8, 128u8, 138u8, 122u8, 187u8, 241u8, - 74u8, 192u8, 26u8, 222u8, 154u8, 54u8, 1u8, 24u8, 41u8, 82u8, 72u8, - 112u8, 104u8, 193u8, 153u8, 109u8, 20u8, 218u8, 47u8, 189u8, 57u8, - 153u8, + 127u8, 80u8, 37u8, 228u8, 18u8, 204u8, 253u8, 251u8, 8u8, 68u8, 103u8, + 87u8, 240u8, 68u8, 137u8, 51u8, 244u8, 67u8, 84u8, 200u8, 134u8, 65u8, + 219u8, 47u8, 202u8, 214u8, 150u8, 1u8, 213u8, 187u8, 78u8, 75u8, ], ) } @@ -6675,9 +6671,10 @@ pub mod api { "request_intent", types::RequestIntent { intent }, [ - 165u8, 243u8, 176u8, 208u8, 170u8, 154u8, 197u8, 187u8, 86u8, 155u8, - 26u8, 158u8, 48u8, 33u8, 218u8, 95u8, 239u8, 167u8, 160u8, 21u8, 160u8, - 238u8, 186u8, 81u8, 36u8, 94u8, 104u8, 25u8, 103u8, 70u8, 180u8, 50u8, + 156u8, 25u8, 96u8, 192u8, 164u8, 226u8, 211u8, 208u8, 143u8, 25u8, + 255u8, 188u8, 88u8, 132u8, 142u8, 138u8, 37u8, 86u8, 10u8, 112u8, 97u8, + 0u8, 123u8, 199u8, 172u8, 188u8, 229u8, 137u8, 138u8, 246u8, 255u8, + 80u8, ], ) } @@ -6747,10 +6744,9 @@ pub mod api { "intent_accepted", types::IntentAccepted { who, intent_id, intent }, [ - 141u8, 203u8, 77u8, 226u8, 21u8, 175u8, 234u8, 1u8, 65u8, 66u8, 136u8, - 34u8, 158u8, 195u8, 159u8, 16u8, 235u8, 6u8, 165u8, 233u8, 119u8, - 225u8, 202u8, 112u8, 154u8, 103u8, 241u8, 24u8, 178u8, 181u8, 130u8, - 168u8, + 51u8, 207u8, 128u8, 217u8, 220u8, 124u8, 19u8, 213u8, 92u8, 69u8, 68u8, + 87u8, 16u8, 19u8, 161u8, 141u8, 210u8, 254u8, 230u8, 103u8, 101u8, + 79u8, 3u8, 11u8, 176u8, 162u8, 117u8, 194u8, 6u8, 103u8, 85u8, 22u8, ], ) } @@ -7346,10 +7342,10 @@ pub mod api { "Intents", (), [ - 80u8, 46u8, 182u8, 0u8, 14u8, 217u8, 0u8, 122u8, 106u8, 29u8, 126u8, - 105u8, 126u8, 251u8, 242u8, 163u8, 176u8, 101u8, 15u8, 212u8, 37u8, - 105u8, 128u8, 187u8, 61u8, 192u8, 34u8, 150u8, 228u8, 134u8, 237u8, - 219u8, + 196u8, 10u8, 114u8, 203u8, 154u8, 118u8, 138u8, 53u8, 183u8, 32u8, + 42u8, 219u8, 162u8, 224u8, 212u8, 96u8, 233u8, 17u8, 139u8, 107u8, + 216u8, 80u8, 137u8, 60u8, 113u8, 73u8, 169u8, 185u8, 243u8, 12u8, + 159u8, 252u8, ], ) } @@ -7372,10 +7368,10 @@ pub mod api { _0.borrow(), ), [ - 80u8, 46u8, 182u8, 0u8, 14u8, 217u8, 0u8, 122u8, 106u8, 29u8, 126u8, - 105u8, 126u8, 251u8, 242u8, 163u8, 176u8, 101u8, 15u8, 212u8, 37u8, - 105u8, 128u8, 187u8, 61u8, 192u8, 34u8, 150u8, 228u8, 134u8, 237u8, - 219u8, + 196u8, 10u8, 114u8, 203u8, 154u8, 118u8, 138u8, 53u8, 183u8, 32u8, + 42u8, 219u8, 162u8, 224u8, 212u8, 96u8, 233u8, 17u8, 139u8, 107u8, + 216u8, 80u8, 137u8, 60u8, 113u8, 73u8, 169u8, 185u8, 243u8, 12u8, + 159u8, 252u8, ], ) } @@ -7409,10 +7405,10 @@ pub mod api { ), ), [ - 80u8, 46u8, 182u8, 0u8, 14u8, 217u8, 0u8, 122u8, 106u8, 29u8, 126u8, - 105u8, 126u8, 251u8, 242u8, 163u8, 176u8, 101u8, 15u8, 212u8, 37u8, - 105u8, 128u8, 187u8, 61u8, 192u8, 34u8, 150u8, 228u8, 134u8, 237u8, - 219u8, + 196u8, 10u8, 114u8, 203u8, 154u8, 118u8, 138u8, 53u8, 183u8, 32u8, + 42u8, 219u8, 162u8, 224u8, 212u8, 96u8, 233u8, 17u8, 139u8, 107u8, + 216u8, 80u8, 137u8, 60u8, 113u8, 73u8, 169u8, 185u8, 243u8, 12u8, + 159u8, 252u8, ], ) } @@ -8371,10 +8367,10 @@ pub mod api { "batch", types::Batch { calls }, [ - 120u8, 242u8, 105u8, 144u8, 123u8, 222u8, 74u8, 191u8, 114u8, 81u8, - 77u8, 15u8, 160u8, 189u8, 31u8, 107u8, 161u8, 61u8, 81u8, 235u8, 208u8, - 58u8, 182u8, 185u8, 62u8, 213u8, 166u8, 218u8, 205u8, 165u8, 108u8, - 33u8, + 82u8, 165u8, 205u8, 19u8, 66u8, 25u8, 85u8, 206u8, 51u8, 79u8, 9u8, + 52u8, 160u8, 253u8, 111u8, 149u8, 125u8, 40u8, 73u8, 94u8, 150u8, + 252u8, 122u8, 230u8, 104u8, 97u8, 192u8, 197u8, 119u8, 209u8, 232u8, + 48u8, ], ) } @@ -10341,10 +10337,20 @@ pub mod api { pub order_type: runtime_types::core_primitives::omni::intent::PumpxOrderType, pub swap_type: ::core::primitive::u32, - pub chain_id: ::core::primitive::u32, - pub token_ca: runtime_types::bounded_collections::bounded_vec::BoundedVec< - ::core::primitive::u8, - >, + pub from_chain_id: ::core::primitive::u32, + pub from_token_ca: + runtime_types::bounded_collections::bounded_vec::BoundedVec< + ::core::primitive::u8, + >, + pub to_chain_id: ::core::primitive::u32, + pub to_token_ca: + runtime_types::bounded_collections::bounded_vec::BoundedVec< + ::core::primitive::u8, + >, + pub from_amount: + runtime_types::bounded_collections::bounded_vec::BoundedVec< + ::core::primitive::u8, + >, pub double_out: ::core::primitive::bool, pub is_one_click: ::core::primitive::bool, pub is_anti_mev: ::core::primitive::bool, diff --git a/tee-worker/omni-executor/pumpx/Cargo.toml b/tee-worker/omni-executor/pumpx/Cargo.toml index 46e62a9084..aee01556e2 100644 --- a/tee-worker/omni-executor/pumpx/Cargo.toml +++ b/tee-worker/omni-executor/pumpx/Cargo.toml @@ -5,8 +5,10 @@ authors = ['Trust Computing GmbH '] edition.workspace = true [dependencies] +base58 = { workspace = true } hex = { workspace = true } jsonrpsee = { workspace = true, features = ["client"] } +libsecp256k1 = { workspace = true } log = { workspace = true } parity-scale-codec = { workspace = true } rand = { workspace = true } @@ -23,6 +25,7 @@ url = { workspace = true } # Local dependencies executor-core = { workspace = true } executor-crypto = { workspace = true } +executor-primitives = { workspace = true } [lints] workspace = true diff --git a/tee-worker/omni-executor/pumpx/src/lib.rs b/tee-worker/omni-executor/pumpx/src/lib.rs index acf1c395e2..4e22343a8f 100644 --- a/tee-worker/omni-executor/pumpx/src/lib.rs +++ b/tee-worker/omni-executor/pumpx/src/lib.rs @@ -20,3 +20,40 @@ pub mod signer_client; mod pumpx_api; pub use pumpx_api::*; + +use base58::ToBase58; +use executor_primitives::ChainAsset; +use log::error; +use sp_core::keccak_256; + +pub fn chain_asset_to_pumpx_chain_id(asset: &ChainAsset) -> u32 { + match asset { + ChainAsset::Ethereum(id, _) => *id, + ChainAsset::Solana(_) => constants::SOLANA_CHAIN_ID, + } +} + +pub fn pubkey_to_evm_address(pubkey: &[u8]) -> Result { + let pubkey: [u8; 33] = pubkey.try_into().map_err(|_| { + error!("wrong pubkey length: expect 33 bytes"); + })?; + let uncompressed_pubkey = libsecp256k1::PublicKey::parse_slice( + &pubkey, + Some(libsecp256k1::PublicKeyFormat::Compressed), + ) + .map_err(|_| { + error!("libsecp256k1 can't parse pubkey"); + })? + .serialize(); + + let address: String = + format!("0x{}", hex::encode(&keccak_256(&uncompressed_pubkey[1..])[12..])); + Ok(address.to_lowercase()) +} + +pub fn pubkey_to_solana_address(pubkey: &[u8]) -> Result { + let pubkey: [u8; 32] = pubkey.try_into().map_err(|_| { + error!("wrong pubkey length: expect 32 bytes"); + })?; + Ok(pubkey.to_base58()) +} diff --git a/tee-worker/omni-executor/pumpx/src/pumpx_api/mod.rs b/tee-worker/omni-executor/pumpx/src/pumpx_api/mod.rs index c3753bb5f4..295ccb246c 100644 --- a/tee-worker/omni-executor/pumpx/src/pumpx_api/mod.rs +++ b/tee-worker/omni-executor/pumpx/src/pumpx_api/mod.rs @@ -170,12 +170,12 @@ impl PumpxApi { }) } - pub async fn send_market_order_tx( + pub async fn send_order_tx( &self, access_token: &str, market_order_tx: MarketOrderTx, ) -> Result { - let endpoint = format!("{}/v3/trade/send_tx", self.base_url); + let endpoint = format!("{}/v3/trade/send_order_tx", self.base_url); let response = self .http_client .post(&endpoint) @@ -242,7 +242,7 @@ impl PumpxApi { }) } - pub async fn cross_order_failed( + pub async fn cross_fail( &self, access_token: &str, data: CrossOrderFailData, @@ -272,22 +272,10 @@ impl PumpxApi { pub async fn create_transfer_unsigned_tx( &self, access_token: &str, - chain_id: u32, - wallet_index: u32, - recipient_address: &str, - token_ca: &str, - amount: &str, + unsigned_tx: TransferUnsignedTx, language: Option, ) -> Result { let endpoint = format!("{}/v3/trade/create_transfer_unsigned_tx", self.base_url); - let unsigned_tx = TransferUnsignedTx { - chain_id, - wallet_index, - recipient_address: recipient_address.to_string(), - token_ca: token_ca.to_string(), - amount: amount.to_string(), - }; - let response = self .http_client .post(&endpoint) @@ -320,20 +308,16 @@ impl PumpxApi { pub async fn send_transfer_tx( &self, access_token: &str, - transfer_id: u64, - chain_id: u32, - tx_data: Vec, + signed_transfer_tx: TransferTx, language: Option, ) -> Result { let endpoint = format!("{}/v3/trade/send_transfer_tx", self.base_url); - let signed_tx = TransferTx { chain_id, tx_data, transfer_id }; - let response = self .http_client .post(&endpoint) .header("X-Language", language.unwrap_or("en".to_string())) .bearer_auth(access_token) - .json(&signed_tx) + .json(&signed_transfer_tx) .send() .await .map_err(|e| { diff --git a/tee-worker/omni-executor/pumpx/src/pumpx_api/types.rs b/tee-worker/omni-executor/pumpx/src/pumpx_api/types.rs index dde3758ba4..eb755e2224 100644 --- a/tee-worker/omni-executor/pumpx/src/pumpx_api/types.rs +++ b/tee-worker/omni-executor/pumpx/src/pumpx_api/types.rs @@ -24,8 +24,8 @@ pub type SendTransferTxResponse = ApiResponse; #[serde(rename_all = "camelCase")] pub struct TransferUnsignedTxData { pub tx_data: Option>, - pub transfer_id: u64, - pub chain_id: u64, + pub transfer_id: u32, + pub chain_id: u32, } #[derive(Deserialize, Serialize, Encode, Decode, PartialEq, Eq, Debug, Clone)] @@ -37,6 +37,7 @@ pub struct TransferTxData { #[derive(Serialize)] #[serde(rename_all = "camelCase")] pub struct TransferUnsignedTx { + pub request_id: Option, pub chain_id: u32, pub wallet_index: u32, pub recipient_address: String, @@ -49,29 +50,12 @@ pub struct TransferUnsignedTx { pub struct TransferTx { pub chain_id: u32, pub tx_data: Vec, - pub transfer_id: u64, + pub transfer_id: u32, } #[derive(Deserialize, Serialize, Encode, Decode, PartialEq, Eq, Debug, Clone, Default)] pub struct EmptyResponse {} -#[derive(Deserialize_repr, Serialize_repr, Clone, Debug)] -#[allow(clippy::upper_case_acronyms)] -#[repr(u8)] -pub enum ChainId { - EVM = 1, - Solana = 2, -} - -impl ChainId { - pub fn to_number(&self) -> u8 { - match self { - ChainId::EVM => 1, - ChainId::Solana => 2, - } - } -} - #[derive(Deserialize, Serialize)] #[serde(rename_all = "camelCase")] pub struct ConnectUser { @@ -141,7 +125,7 @@ impl GasType { #[serde(rename_all = "camelCase")] pub struct NewMarketOrder { pub request_id: u32, - pub chain_id: ChainId, + pub chain_id: u32, pub token_ca: String, pub swap_type: SwapType, pub amount_in: String, @@ -158,22 +142,23 @@ pub struct NewMarketOrder { #[derive(Deserialize, Encode, Decode)] #[serde(rename_all = "camelCase")] pub struct MarketOrderUnsignedTx { - pub order_id: String, + pub chain_id: u32, + pub order_id: u32, pub tx_data: Vec, } #[derive(Serialize)] #[serde(rename_all = "camelCase")] pub struct MarketOrderTx { - pub order_id: String, + pub chain_id: u32, + pub order_id: u32, pub tx_data: Vec, - pub chain_id: ChainId, } #[derive(Deserialize, Serialize, Encode, Decode, Clone)] #[serde(rename_all = "camelCase")] pub struct TxData { - pub tx_hash: String, + pub tx_hash: Option>, } #[derive(Deserialize, Encode, Decode)] @@ -194,7 +179,7 @@ pub struct UserTradeInfo { #[serde(rename_all = "camelCase")] pub struct NewLimitOrder { pub request_id: u32, - pub chain_id: ChainId, + pub chain_id: u32, pub token_ca: String, pub amount: String, pub swap_type: SwapType, @@ -213,7 +198,7 @@ pub struct NewLimitOrder { #[derive(Deserialize, Serialize, Encode, Decode, Clone)] #[serde(rename_all = "camelCase")] pub struct OrderInfo { - pub order_id: String, + pub order_id: u32, } #[derive(Serialize)] @@ -230,14 +215,17 @@ pub struct DataResult { #[serde(rename_all = "camelCase")] pub struct CreateCrossOrderData { pub request_id: u32, - pub chain_id: ChainId, - pub info: Vec, + pub chain_id: u32, + pub token_ca: String, + pub swap_type: SwapType, + pub is_one_click: bool, + pub cross_info: Vec, } #[derive(Serialize)] #[serde(rename_all = "camelCase")] pub struct CrossOrderInfo { - pub chain_id: ChainId, + pub chain_id: u32, pub wallet_index: u32, pub address: String, pub token_ca: String, diff --git a/tee-worker/omni-executor/pumpx/src/signer_client.rs b/tee-worker/omni-executor/pumpx/src/signer_client.rs index f0df0b6613..a1660e14ca 100644 --- a/tee-worker/omni-executor/pumpx/src/signer_client.rs +++ b/tee-worker/omni-executor/pumpx/src/signer_client.rs @@ -98,7 +98,7 @@ struct AesOutput { pub nonce: Aes256KeyNonce, } -#[derive(Debug, Serialize, Deserialize, Clone)] +#[derive(Debug, Copy, Serialize, Deserialize, Clone)] pub enum ChainType { Evm, Solana, diff --git a/tee-worker/omni-executor/rpc-server/src/methods/pumpx/submit_swap_order.rs b/tee-worker/omni-executor/rpc-server/src/methods/pumpx/submit_swap_order.rs index c3267e3c37..38d23e622d 100644 --- a/tee-worker/omni-executor/rpc-server/src/methods/pumpx/submit_swap_order.rs +++ b/tee-worker/omni-executor/rpc-server/src/methods/pumpx/submit_swap_order.rs @@ -165,9 +165,6 @@ pub fn register_submit_swap_order(module: &mut RpcModule) { return Err(ErrorCode::InvalidParams); }, }; - let token_ca = - BoundedVec::try_from(params.to_token_ca.unwrap_or_default().as_bytes().to_vec()) - .map_err(|_| ErrorCode::InvalidParams)?; let token_cap = params .token_cap .map(|token_ca| { @@ -185,11 +182,22 @@ pub fn register_submit_swap_order(module: &mut RpcModule) { let usd_worth = BoundedVec::try_from(params.usd_worth.as_bytes().to_vec()) .map_err(|_| ErrorCode::InvalidParams)?; + // TODO: optimise these BoundedVec conversion to have better readability let pumpx_config = PumpxConfig { order_type: params.order_type.clone(), swap_type: params.swap_type.to_number() as u32, - chain_id: params.to_chain_id, - token_ca, + from_chain_id: params.from_chain_id, + from_token_ca: BoundedVec::try_from( + params.from_token_ca.unwrap_or("".to_string()).as_bytes().to_vec(), + ) + .map_err(|_| ErrorCode::InvalidParams)?, + to_chain_id: params.to_chain_id, + to_token_ca: BoundedVec::try_from( + params.to_token_ca.unwrap_or("".to_string()).as_bytes().to_vec(), + ) + .map_err(|_| ErrorCode::InvalidParams)?, + from_amount: BoundedVec::try_from(params.from_amount.as_bytes().to_vec()) + .map_err(|_| ErrorCode::InvalidParams)?, double_out: params.double_out, is_one_click: params.is_one_click, is_anti_mev: user_trade_info.data.is_anti_mev, @@ -210,7 +218,10 @@ pub fn register_submit_swap_order(module: &mut RpcModule) { ccs_provider = Some(CrossChainSwapProvider::Binance(BinanceConfig {})); } + // TODO: `swap_order` isn't actively used - we mainly rely on pumpx_config to call pumpx API + // we construct `swap_order` mainly to upload it onto heima let intent = Intent::Swap(swap_order, ccs_provider, scs_provider); + let wrapper = NativeTaskWrapper { task: NativeTask::RequestIntent(user_identity, params.intent_id, intent), nonce: None, diff --git a/tee-worker/omni-executor/rpc-server/src/methods/pumpx/transfer_widthdraw.rs b/tee-worker/omni-executor/rpc-server/src/methods/pumpx/transfer_widthdraw.rs index 87dbc8f045..06800ab9b1 100644 --- a/tee-worker/omni-executor/rpc-server/src/methods/pumpx/transfer_widthdraw.rs +++ b/tee-worker/omni-executor/rpc-server/src/methods/pumpx/transfer_widthdraw.rs @@ -13,6 +13,7 @@ use serde::Serialize; #[derive(Debug, Deserialize)] pub struct TransferWithdrawParams { pub user_email: String, + pub request_id: Option, pub chain_id: u32, pub wallet_index: PumxWalletIndex, pub recipient_address: String, @@ -33,6 +34,7 @@ impl From for NativeTaskWrapper { Self { task: NativeTask::PumpxTransferWidthdraw( Identity::from_web2_account(p.user_email.as_str(), Web2IdentityType::Email), + p.request_id, p.chain_id, p.wallet_index, p.recipient_address,