diff --git a/example_solver/Cargo.lock b/example_solver/Cargo.lock index ab036ba..4c8187b 100644 --- a/example_solver/Cargo.lock +++ b/example_solver/Cargo.lock @@ -793,7 +793,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4114279215a005bc675e386011e594e1d9b800918cea18fcadadcce864a2046b" dependencies = [ "borsh-derive 0.10.3", - "hashbrown 0.12.3", + "hashbrown 0.13.2", ] [[package]] @@ -901,7 +901,7 @@ dependencies = [ "base64 0.21.7", "bytemuck", "cf-guest 0.0.0 (git+https://github.com/ComposableFi/emulated-light-client.git?branch=upgrade)", - "derive_more", + "derive_more 0.99.17", "guestchain 0.0.0 (git+https://github.com/ComposableFi/emulated-light-client.git?branch=upgrade)", "hex-literal", "ibc", @@ -1104,7 +1104,7 @@ source = "git+https://github.com/ComposableFi/emulated-light-client.git?branch=f dependencies = [ "borsh 0.10.3", "bytemuck", - "derive_more", + "derive_more 0.99.17", "guestchain 0.0.0 (git+https://github.com/ComposableFi/emulated-light-client.git?branch=fast-bridge)", "ibc-client-tendermint-types", "ibc-core-client-context", @@ -1128,7 +1128,7 @@ source = "git+https://github.com/ComposableFi/emulated-light-client.git?branch=u dependencies = [ "borsh 0.10.3", "bytemuck", - "derive_more", + "derive_more 0.99.17", "guestchain 0.0.0 (git+https://github.com/ComposableFi/emulated-light-client.git?branch=upgrade)", "ibc-client-tendermint-types", "ibc-core-client-context", @@ -1677,6 +1677,26 @@ dependencies = [ "syn 1.0.109", ] +[[package]] +name = "derive_more" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4a9b99b9cbbe49445b21764dc0625032a89b145a2642e67603e1c936f5458d05" +dependencies = [ + "derive_more-impl", +] + +[[package]] +name = "derive_more-impl" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb7330aeadfbe296029522e6c40f315320aba36fc43a5b3632f3795348f3bd22" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.66", +] + [[package]] name = "dialoguer" version = "0.10.4" @@ -2328,12 +2348,15 @@ dependencies = [ "base64 0.22.1", "bincode", "bridge-escrow", + "derive_more 1.0.0", "dotenv", + "env_logger", "ethers", "futures", "hex", "lazy_static", "lib 0.0.0 (git+https://github.com/ComposableFi/emulated-light-client.git?branch=fast-bridge)", + "log", "num-bigint 0.4.5", "num-traits", "reqwest", @@ -2687,7 +2710,7 @@ source = "git+https://github.com/ComposableFi/emulated-light-client.git?branch=f dependencies = [ "borsh 0.10.3", "bytemuck", - "derive_more", + "derive_more 0.99.17", "ibc-core-client-context", "ibc-core-commitment-types", "ibc-core-host", @@ -2709,7 +2732,7 @@ source = "git+https://github.com/ComposableFi/emulated-light-client.git?branch=u dependencies = [ "borsh 0.10.3", "bytemuck", - "derive_more", + "derive_more 0.99.17", "ibc-core-client-context", "ibc-core-commitment-types", "ibc-core-host", @@ -2766,9 +2789,6 @@ name = "hashbrown" version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" -dependencies = [ - "ahash 0.7.8", -] [[package]] name = "hashbrown" @@ -3065,7 +3085,7 @@ version = "0.50.0" source = "git+https://github.com/mina86/ibc-rs?rev=f07276383091f75b7ee8bff6fd434f8214ac5054#f07276383091f75b7ee8bff6fd434f8214ac5054" dependencies = [ "borsh 0.10.3", - "derive_more", + "derive_more 0.99.17", "displaydoc", "ibc-core", "ibc-proto", @@ -3087,7 +3107,7 @@ name = "ibc-client-tendermint" version = "0.50.0" source = "git+https://github.com/mina86/ibc-rs?rev=f07276383091f75b7ee8bff6fd434f8214ac5054#f07276383091f75b7ee8bff6fd434f8214ac5054" dependencies = [ - "derive_more", + "derive_more 0.99.17", "ibc-client-tendermint-types", "ibc-core-client", "ibc-core-commitment-types", @@ -3178,7 +3198,7 @@ version = "0.50.0" source = "git+https://github.com/mina86/ibc-rs?rev=f07276383091f75b7ee8bff6fd434f8214ac5054#f07276383091f75b7ee8bff6fd434f8214ac5054" dependencies = [ "borsh 0.10.3", - "derive_more", + "derive_more 0.99.17", "displaydoc", "ibc-core-client-types", "ibc-core-commitment-types", @@ -3211,7 +3231,7 @@ name = "ibc-core-client-context" version = "0.50.0" source = "git+https://github.com/mina86/ibc-rs?rev=f07276383091f75b7ee8bff6fd434f8214ac5054#f07276383091f75b7ee8bff6fd434f8214ac5054" dependencies = [ - "derive_more", + "derive_more 0.99.17", "displaydoc", "ibc-client-tendermint-types", "ibc-core-client-types", @@ -3229,7 +3249,7 @@ version = "0.50.0" source = "git+https://github.com/mina86/ibc-rs?rev=f07276383091f75b7ee8bff6fd434f8214ac5054#f07276383091f75b7ee8bff6fd434f8214ac5054" dependencies = [ "borsh 0.10.3", - "derive_more", + "derive_more 0.99.17", "displaydoc", "ibc-core-commitment-types", "ibc-core-host-types", @@ -3246,7 +3266,7 @@ version = "0.50.0" source = "git+https://github.com/mina86/ibc-rs?rev=f07276383091f75b7ee8bff6fd434f8214ac5054#f07276383091f75b7ee8bff6fd434f8214ac5054" dependencies = [ "borsh 0.10.3", - "derive_more", + "derive_more 0.99.17", "displaydoc", "ibc-primitives", "ibc-proto", @@ -3273,7 +3293,7 @@ version = "0.50.0" source = "git+https://github.com/mina86/ibc-rs?rev=f07276383091f75b7ee8bff6fd434f8214ac5054#f07276383091f75b7ee8bff6fd434f8214ac5054" dependencies = [ "borsh 0.10.3", - "derive_more", + "derive_more 0.99.17", "displaydoc", "ibc-core-client-types", "ibc-core-commitment-types", @@ -3307,7 +3327,7 @@ version = "0.50.0" source = "git+https://github.com/mina86/ibc-rs?rev=f07276383091f75b7ee8bff6fd434f8214ac5054#f07276383091f75b7ee8bff6fd434f8214ac5054" dependencies = [ "borsh 0.10.3", - "derive_more", + "derive_more 0.99.17", "displaydoc", "ibc-core-channel-types", "ibc-core-client-types", @@ -3327,7 +3347,7 @@ name = "ibc-core-host" version = "0.50.0" source = "git+https://github.com/mina86/ibc-rs?rev=f07276383091f75b7ee8bff6fd434f8214ac5054#f07276383091f75b7ee8bff6fd434f8214ac5054" dependencies = [ - "derive_more", + "derive_more 0.99.17", "displaydoc", "ibc-core-channel-types", "ibc-core-client-context", @@ -3346,7 +3366,7 @@ version = "0.50.0" source = "git+https://github.com/mina86/ibc-rs?rev=f07276383091f75b7ee8bff6fd434f8214ac5054#f07276383091f75b7ee8bff6fd434f8214ac5054" dependencies = [ "borsh 0.10.3", - "derive_more", + "derive_more 0.99.17", "displaydoc", "ibc-app-transfer-types", "ibc-client-tendermint", @@ -3370,7 +3390,7 @@ version = "0.50.0" source = "git+https://github.com/mina86/ibc-rs?rev=f07276383091f75b7ee8bff6fd434f8214ac5054#f07276383091f75b7ee8bff6fd434f8214ac5054" dependencies = [ "borsh 0.10.3", - "derive_more", + "derive_more 0.99.17", "displaydoc", "ibc-primitives", "serde", @@ -3381,7 +3401,7 @@ name = "ibc-core-router" version = "0.50.0" source = "git+https://github.com/mina86/ibc-rs?rev=f07276383091f75b7ee8bff6fd434f8214ac5054#f07276383091f75b7ee8bff6fd434f8214ac5054" dependencies = [ - "derive_more", + "derive_more 0.99.17", "displaydoc", "ibc-core-channel-types", "ibc-core-host-types", @@ -3396,7 +3416,7 @@ version = "0.50.0" source = "git+https://github.com/mina86/ibc-rs?rev=f07276383091f75b7ee8bff6fd434f8214ac5054#f07276383091f75b7ee8bff6fd434f8214ac5054" dependencies = [ "borsh 0.10.3", - "derive_more", + "derive_more 0.99.17", "displaydoc", "ibc-core-host-types", "ibc-primitives", @@ -3422,7 +3442,7 @@ version = "0.50.0" source = "git+https://github.com/mina86/ibc-rs?rev=f07276383091f75b7ee8bff6fd434f8214ac5054#f07276383091f75b7ee8bff6fd434f8214ac5054" dependencies = [ "borsh 0.10.3", - "derive_more", + "derive_more 0.99.17", "displaydoc", "ibc-proto", "prost", @@ -3760,7 +3780,7 @@ dependencies = [ "borsh 0.10.3", "bs58 0.5.1", "bytemuck", - "derive_more", + "derive_more 0.99.17", "sha2 0.10.8", "solana-program", "stdx 0.0.0 (git+https://github.com/ComposableFi/emulated-light-client.git?branch=fast-bridge)", @@ -3775,7 +3795,7 @@ dependencies = [ "borsh 0.10.3", "bs58 0.5.1", "bytemuck", - "derive_more", + "derive_more 0.99.17", "sha2 0.10.8", "solana-program", "stdx 0.0.0 (git+https://github.com/ComposableFi/emulated-light-client.git?branch=upgrade)", @@ -3938,7 +3958,7 @@ name = "memory" version = "0.0.0" source = "git+https://github.com/ComposableFi/emulated-light-client.git?branch=fast-bridge#d843604e1a027c53abe06dfd211da754bec4521a" dependencies = [ - "derive_more", + "derive_more 0.99.17", ] [[package]] @@ -3946,7 +3966,7 @@ name = "memory" version = "0.0.0" source = "git+https://github.com/ComposableFi/emulated-light-client.git?branch=upgrade#a78423c40abb0798232cab888431be722dc3c8f5" dependencies = [ - "derive_more", + "derive_more 0.99.17", ] [[package]] @@ -4819,7 +4839,7 @@ version = "0.0.0" source = "git+https://github.com/ComposableFi/emulated-light-client.git?branch=fast-bridge#d843604e1a027c53abe06dfd211da754bec4521a" dependencies = [ "const_format", - "derive_more", + "derive_more 0.99.17", "ibc-core-client-context", "ibc-proto", "prost", @@ -4831,7 +4851,7 @@ version = "0.0.0" source = "git+https://github.com/ComposableFi/emulated-light-client.git?branch=upgrade#a78423c40abb0798232cab888431be722dc3c8f5" dependencies = [ "const_format", - "derive_more", + "derive_more 0.99.17", "ibc-core-client-context", "ibc-proto", "prost", @@ -5357,7 +5377,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "eca070c12893629e2cc820a9761bedf6ce1dcddc9852984d1dc734b8bd9bd024" dependencies = [ "cfg-if", - "derive_more", + "derive_more 0.99.17", "parity-scale-codec", "scale-info-derive", ] @@ -5440,7 +5460,7 @@ dependencies = [ "base64 0.21.7", "borsh 0.10.3", "bytemuck", - "derive_more", + "derive_more 0.99.17", "lib 0.0.0 (git+https://github.com/ComposableFi/emulated-light-client.git?branch=fast-bridge)", "memory 0.0.0 (git+https://github.com/ComposableFi/emulated-light-client.git?branch=fast-bridge)", "sha2 0.10.8", @@ -5457,7 +5477,7 @@ dependencies = [ "base64 0.21.7", "borsh 0.10.3", "bytemuck", - "derive_more", + "derive_more 0.99.17", "lib 0.0.0 (git+https://github.com/ComposableFi/emulated-light-client.git?branch=upgrade)", "memory 0.0.0 (git+https://github.com/ComposableFi/emulated-light-client.git?branch=upgrade)", "sha2 0.10.8", @@ -5989,7 +6009,7 @@ dependencies = [ "base64 0.21.7", "bytemuck", "cf-guest 0.0.0 (git+https://github.com/ComposableFi/emulated-light-client.git?branch=fast-bridge)", - "derive_more", + "derive_more 0.99.17", "guestchain 0.0.0 (git+https://github.com/ComposableFi/emulated-light-client.git?branch=fast-bridge)", "hex-literal", "ibc", @@ -6027,7 +6047,7 @@ dependencies = [ "base64 0.21.7", "bytemuck", "cf-guest 0.0.0 (git+https://github.com/ComposableFi/emulated-light-client.git?branch=upgrade)", - "derive_more", + "derive_more 0.99.17", "guestchain 0.0.0 (git+https://github.com/ComposableFi/emulated-light-client.git?branch=upgrade)", "hex-literal", "ibc", @@ -6449,7 +6469,7 @@ dependencies = [ "base64 0.21.7", "borsh 0.10.3", "bytemuck", - "derive_more", + "derive_more 0.99.17", "guestchain 0.0.0 (git+https://github.com/ComposableFi/emulated-light-client.git?branch=fast-bridge)", "lib 0.0.0 (git+https://github.com/ComposableFi/emulated-light-client.git?branch=fast-bridge)", "solana-program", @@ -6464,7 +6484,7 @@ dependencies = [ "base64 0.21.7", "borsh 0.10.3", "bytemuck", - "derive_more", + "derive_more 0.99.17", "guestchain 0.0.0 (git+https://github.com/ComposableFi/emulated-light-client.git?branch=upgrade)", "lib 0.0.0 (git+https://github.com/ComposableFi/emulated-light-client.git?branch=upgrade)", "solana-program", @@ -7456,7 +7476,7 @@ version = "0.34.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9b8090d0eef9ad57b1b913b5e358e26145c86017e87338136509b94383a4af25" dependencies = [ - "derive_more", + "derive_more 0.99.17", "flex-error", "serde", "tendermint", @@ -7834,7 +7854,7 @@ dependencies = [ "base64 0.21.7", "borsh 0.10.3", "bytemuck", - "derive_more", + "derive_more 0.99.17", "ibc-core-channel-types", "ibc-core-client-types", "ibc-core-connection-types", @@ -7851,7 +7871,7 @@ dependencies = [ "base64 0.21.7", "borsh 0.10.3", "bytemuck", - "derive_more", + "derive_more 0.99.17", "ibc-core-channel-types", "ibc-core-client-types", "ibc-core-connection-types", @@ -8096,7 +8116,7 @@ version = "0.0.0" source = "git+https://github.com/ComposableFi/emulated-light-client.git?branch=fast-bridge#d843604e1a027c53abe06dfd211da754bec4521a" dependencies = [ "const_format", - "derive_more", + "derive_more 0.99.17", "ibc-core-client-context", "ibc-core-commitment-types", "ibc-primitives", @@ -8112,7 +8132,7 @@ version = "0.0.0" source = "git+https://github.com/ComposableFi/emulated-light-client.git?branch=upgrade#a78423c40abb0798232cab888431be722dc3c8f5" dependencies = [ "const_format", - "derive_more", + "derive_more 0.99.17", "ibc-core-client-context", "ibc-core-commitment-types", "ibc-primitives", @@ -8207,7 +8227,7 @@ dependencies = [ "arrayvec", "base64 0.21.7", "bytes", - "derive_more", + "derive_more 0.99.17", "ethabi", "ethereum-types", "futures", diff --git a/example_solver/Cargo.toml b/example_solver/Cargo.toml index 308bf75..e843c5f 100644 --- a/example_solver/Cargo.toml +++ b/example_solver/Cargo.toml @@ -35,6 +35,9 @@ web3 = "0.19.0" bridge-escrow = { git = "https://github.com/ComposableFi/emulated-light-client.git", branch = "upgrade", package = "bridge-escrow" } solana-ibc = { git = "https://github.com/ComposableFi/emulated-light-client.git", branch = "fast-bridge", features = ["cpi"] } lib = { git = "https://github.com/ComposableFi/emulated-light-client.git", branch = "fast-bridge", features = ["solana-program"] } +derive_more = { version = "1.0.0", features = ["deref", "deref_mut"] } +log = "0.4.21" +env_logger = "0.9.3" [patch.crates-io] # aes-gcm-siv 0.10.3 and curve25519-dalek 3.x pin zeroize to <1.4 @@ -49,6 +52,3 @@ lib = { git = "https://github.com/ComposableFi/emulated-light-client.git", branc # https://github.com/dalek-cryptography/curve25519-dalek/pull/606 aes-gcm-siv = { git = "https://github.com/RustCrypto/AEADs", rev = "6105d7a5591aefa646a95d12b5e8d3f55a9214ef" } curve25519-dalek = { git = "https://github.com/dalek-cryptography/curve25519-dalek", rev = "8274d5cbb6fc3f38cdc742b4798173895cd2a290" } - - - diff --git a/example_solver/src/chains/mod.rs b/example_solver/src/chains/mod.rs index b2fc4b2..66ed7be 100644 --- a/example_solver/src/chains/mod.rs +++ b/example_solver/src/chains/mod.rs @@ -5,7 +5,7 @@ pub mod solana; use lazy_static::lazy_static; use std::collections::HashMap; -use crate::env; +use crate::{env, SignedPayload}; use ethers::prelude::*; use ethers::signers::LocalWallet; use ethers::utils::hash_message; @@ -144,26 +144,23 @@ pub fn get_token_info(token: &str, blockchain: &str) -> Option<(&'static str, u3 Some((address, info.decimals)) } -pub async fn create_keccak256_signature( - json_data: &mut Value, +pub async fn create_keccak256_signature( + json_data: T, private_key: String, -) -> Result<(), Box> { - let json_str = json_data.to_string(); +) -> Result, Box> { + let json_str = serde_json::to_string(&json_data)?; let json_bytes = json_str.as_bytes(); - let hash = keccak256(json_bytes); - let hash_hex = hex::encode(hash); + let hash = H256(keccak256(json_bytes)); let wallet: LocalWallet = private_key.parse().unwrap(); let eth_message_hash = hash_message(hash); let signature: Signature = wallet.sign_hash(H256::from(eth_message_hash)).unwrap(); - let signature_hex = signature.to_string(); - if let Some(msg) = json_data.get_mut("msg") { - msg["hash"] = Value::String(hash_hex); - msg["signature"] = Value::String(signature_hex); - } - - Ok(()) + Ok(SignedPayload { + payload: json_data, + hash, + signature, + }) } diff --git a/example_solver/src/main.rs b/example_solver/src/main.rs index c254746..9f2bb84 100644 --- a/example_solver/src/main.rs +++ b/example_solver/src/main.rs @@ -12,176 +12,415 @@ use crate::chains::SOLVER_ADDRESSES; use crate::chains::SOLVER_ID; use crate::chains::SOLVER_PRIVATE_KEY; use crate::routers::get_simulate_swap_intent; -use chains::create_keccak256_signature; +use chains::{create_keccak256_signature, get_token_info, SwapTransferInput, SwapTransferOutput}; +use derive_more::{Deref, DerefMut}; +use ethers::abi::Address; +use ethers::core::rand; +use ethers::prelude::{Signature, H256}; use ethers::types::U256; +use futures::stream::SplitSink; use futures::{SinkExt, StreamExt}; +use log::{debug, error}; +use num_bigint::BigInt; +use num_traits::Num; +use serde::{Deserialize, Serialize}; use serde_json::json; use serde_json::Value; +use solana_sdk::pubkey::Pubkey; use spl_associated_token_account::get_associated_token_address; use std::env; -use tokio_tungstenite::connect_async; +use std::str::FromStr; +use std::sync::atomic::AtomicU32; +use std::sync::Arc; +use tokio::net::TcpStream; +use tokio::sync::Mutex; use tokio_tungstenite::tungstenite::protocol::Message; +use tokio_tungstenite::tungstenite::Error; +use tokio_tungstenite::{connect_async, MaybeTlsStream, WebSocketStream}; + +type RequestId = u32; +type SolverId = String; + +#[derive(Serialize)] +#[serde(tag = "type", rename_all = "snake_case")] +enum ClientMessage { + SolverRegister(SignedPayload), + AuctionBid(SignedPayload), + QuoteResponse(QuoteResponse), + ErrorResponse(ErrorResponse), +} + +#[derive(Deserialize)] +#[serde(tag = "type", rename_all = "snake_case")] +enum ServerMessage { + SolverRegisterResponse(SolverRegisterResponse), + NewIntent(NewIntentMessage), + AuctionResult(AuctionResultMessage), + ErrorResponse(ErrorResponse), + QuoteRequest(QuoteRequest), +} + +#[derive(Serialize, Deserialize)] +struct QuoteRequest { + pub src_chain: Network, + pub src_address: String, + pub token_in: String, + pub amount_in: String, + pub dst_chain: Network, + pub dst_address: String, + pub token_out: String, +} + +#[derive(Deserialize, Serialize)] +struct QuoteResponse { + pub token_out: String, + pub amount_out: String, +} + +#[derive(Deserialize, Serialize)] +struct SolverQuoteResponse { + solver_id: SolverId, + #[serde(flatten)] + response: QuoteResponse, +} + +#[derive(Serialize)] +struct SolverRegisterRequest { + solver_id: String, + solver_addresses: Vec, +} + +#[derive(Deserialize)] +struct SolverRegisterResponse { + message: String, +} + +#[derive(Serialize)] +struct AuctionBidRequest { + intent_id: String, + solver_id: String, + amount: String, +} + +#[derive(Serialize)] +struct SignedPayload { + payload: T, + hash: H256, + signature: Signature, +} + +#[derive(Serialize, Deserialize, Deref, DerefMut)] +pub struct Identified { + #[deref] + #[deref_mut] + payload: T, + pub(crate) id: RequestId, +} + +impl Identified { + pub fn new(payload: T, id: RequestId) -> Self { + Identified { payload, id } + } +} + +#[derive(Deserialize)] +struct NewIntentMessage { + intent_id: String, + intent: PostIntentInfo, +} + +#[derive(Deserialize)] +struct AuctionResultMessage { + intent_id: String, + amount: Option, + message: String, +} + +#[derive(Deserialize, Serialize)] +struct ErrorResponse { + message: String, +} + +struct Solver { + solver_id: SolverId, + request_id: Arc, + ws_sender: SplitSink>, Message>, +} + +#[derive(Copy, Clone, Debug, PartialEq, Eq, Serialize, Deserialize)] +#[serde(rename_all = "snake_case")] +enum Network { + Solana, + Ethereum, +} + +impl ToString for Network { + fn to_string(&self) -> String { + format!("{:?}", self).to_lowercase() + } +} + +const BRIDGE_TOKEN: &'static str = "USDT"; #[tokio::main] async fn main() { dotenv::dotenv().ok(); - let server_addr = env::var("COMPOSABLE_ENDPOINT").unwrap_or_else(|_| String::from("")); + env_logger::init(); + let server_addr = + env::var("COMPOSABLE_ENDPOINT").unwrap_or_else(|_| String::from("ws://34.78.217.187:8080")); - let (ws_stream, _) = connect_async(server_addr).await.expect("Failed to connect"); + let (ws_stream, _) = connect_async(format!("{}/ws", server_addr)) + .await + .expect("Failed to connect"); let (mut ws_sender, mut ws_receiver) = ws_stream.split(); - let mut json_data = json!({ - "code": 1, - "msg": { - "solver_id": SOLVER_ID.to_string(), - "solver_addresses": SOLVER_ADDRESSES, + let mut solver = Solver { + solver_id: SOLVER_ID.to_string(), + request_id: Arc::new(AtomicU32::new(0)), + ws_sender, + }; + + let register_request = SolverRegisterRequest { + solver_id: solver.solver_id.clone(), + solver_addresses: SOLVER_ADDRESSES + .into_iter() + .map(ToString::to_string) + .collect(), + }; + + let register_request = + create_keccak256_signature(register_request, SOLVER_PRIVATE_KEY.to_string()) + .await + .unwrap(); + + // Serialize the message + let message = ClientMessage::SolverRegister(register_request); + solver.identify_and_send(&message).await.unwrap(); + + while let Some(msg) = ws_receiver.next().await { + if let Err(e) = solver.handle_message(msg).await { + error!("Error handling message: {}", e); } - }); + } - create_keccak256_signature(&mut json_data, SOLVER_PRIVATE_KEY.to_string()) - .await - .unwrap(); + // TODO: auto-reconnect + println!("Auctioneer went down, please reconnect"); +} - if json_data.get("code").unwrap() == "0" { - println!("{:#?}", json_data); - return; +impl Solver { + pub async fn send_raw(&mut self, val: &T) -> anyhow::Result<()> { + let val = serde_json::to_string(val)?; + let message = Message::Text(val); + self.ws_sender.send(message).await?; + Ok(()) } - ws_sender - .send(Message::Text(json_data.to_string())) - .await - .expect("Failed to send initial message"); + pub async fn identify_and_send(&mut self, val: &T) -> anyhow::Result<()> { + let req_id = self + .request_id + .fetch_add(1, std::sync::atomic::Ordering::SeqCst); + let ident_val = Identified::new(val, req_id); + self.send_raw(&ident_val).await + } - while let Some(msg) = ws_receiver.next().await { + pub async fn reply( + &mut self, + val: &T, + request_id: RequestId, + ) -> anyhow::Result<()> { + let ident_val = Identified::new(val, request_id); + self.send_raw(&ident_val).await + } + + async fn handle_message(&mut self, msg: Result) -> anyhow::Result> { match msg { Ok(Message::Text(text)) => { - let parsed: Value = serde_json::from_str(&text).unwrap(); - let code = parsed.get("code").unwrap().as_u64().unwrap(); - - println!("{:#?}", parsed); - - if code == 0 { - // error - } else if code == 1 { - // participate auction - let intent_id = parsed - .get("msg") - .unwrap() - .get("intent_id") - .and_then(Value::as_str) - .unwrap(); - let intent_str = parsed - .get("msg") - .unwrap() - .get("intent") - .unwrap() - .to_string(); - let intent_value: Value = serde_json::from_str(&intent_str).unwrap(); - let intent_info: PostIntentInfo = serde_json::from_value(intent_value).unwrap(); - - // calculate best quote - let final_amount = get_simulate_swap_intent( - &intent_info, - &intent_info.src_chain, - &intent_info.dst_chain, - &String::from("USDT"), + debug!("Received message: {}", text); + let ident_server_message: Identified = + match serde_json::from_str(&text) { + Ok(msg) => msg, + Err(err) => { + eprintln!("Failed to parse server message: {:?}", err); + return Ok(Some(())); + } + }; + + let id = ident_server_message.id; + if let Err(e) = self.process_server_message(ident_server_message).await { + error!("Error processing server message: {}", e); + self.reply( + &ClientMessage::ErrorResponse(ErrorResponse { + message: format!("Error processing message: {}", e), + }), + id, ) - .await; + .await?; + } + Ok(Some(())) + } + Ok(Message::Close(_)) | Err(_) => Ok(None), + _ => Ok(Some(())), + } + } - // decide if participate or not - let mut amount_out_min = U256::zero(); + async fn process_server_message( + &mut self, + ident_server_message: Identified, + ) -> anyhow::Result<()> { + let server_message = ident_server_message.payload; + let req_id = ident_server_message.id; + match server_message { + ServerMessage::SolverRegisterResponse(response) => { + println!("Solver registered: {}", response.message); + } + ServerMessage::NewIntent(new_intent) => { + // Participate in auction + let intent_id = new_intent.intent_id; + let intent_info = new_intent.intent; + + // Calculate best quote + let final_amount = get_simulate_swap_intent( + &intent_info, + &intent_info.src_chain, + &intent_info.dst_chain, + BRIDGE_TOKEN, + ) + .await; + + // Decide whether to participate + let amount_out_min = if let OperationOutput::SwapTransfer(transfer_output) = &intent_info.outputs { - amount_out_min = U256::from_dec_str(&transfer_output.amount_out).unwrap(); - } + U256::from_dec_str(&transfer_output.amount_out).unwrap_or(U256::zero()) + } else { + U256::zero() + }; - let final_amount = U256::from_dec_str(&final_amount).unwrap(); + let final_amount_u256 = U256::from_dec_str(&final_amount).unwrap_or(U256::zero()); - println!("User wants {amount_out_min} token_out, you can provide {final_amount} token_out (after FLAT_FEES + COMISSION)"); + println!( + "User wants {} token_out, you can provide {} token_out (after fees and commission)", + amount_out_min, final_amount_u256 + ); - if final_amount > amount_out_min { - let mut json_data = json!({ - "code": 2, - "msg": { - "intent_id": intent_id, - "solver_id": SOLVER_ID.to_string(), - "amount": final_amount.to_string() - } - }); + if final_amount_u256 > amount_out_min { + // Create AuctionBidRequest + let auction_bid_request = AuctionBidRequest { + intent_id: intent_id.clone(), + solver_id: SOLVER_ID.to_string(), + amount: final_amount.clone(), + }; - create_keccak256_signature(&mut json_data, SOLVER_PRIVATE_KEY.to_string()) - .await - .unwrap(); + // Create signature + let auction_bid_request = create_keccak256_signature( + auction_bid_request, + SOLVER_PRIVATE_KEY.to_string(), + ) + .await + .unwrap(); - ws_sender - .send(Message::text(json_data.to_string())) - .await - .expect("Failed to send message"); + // Serialize the message + let message = ClientMessage::AuctionBid(auction_bid_request); + self.reply(&message, req_id).await.unwrap(); + // Store the intent + { let mut intents = INTENTS.write().await; - intents.insert(intent_id.to_string(), intent_info); - drop(intents); + intents.insert(intent_id.clone(), intent_info); } - } else if code == 3 { - // solver registered - } else if code == 4 { - let intent_id = parsed - .get("msg") - .unwrap() - .get("intent_id") - .and_then(Value::as_str) - .unwrap(); - let amount = parsed - .get("msg") - .unwrap() - .get("amount") - .and_then(Value::as_str); - - if let Some(amount) = amount { - let msg = parsed - .get("msg") - .unwrap() - .get("msg") - .and_then(Value::as_str) - .unwrap() - .to_string(); - - if msg.contains("won") { - let intent; - { - let intents = INTENTS.read().await; - intent = intents.get(intent_id).unwrap().clone(); - drop(intents); - } + } + } + ServerMessage::AuctionResult(auction_result) => { + let intent_id = auction_result.intent_id; + let intent_id_u256 = intent_id.parse::().map_err(|e| anyhow::anyhow!(e))?; + let amount = auction_result.amount; - if intent.dst_chain == "solana" { - handle_solana_execution(&intent, intent_id, amount) - .await - .unwrap(); - } else if intent.dst_chain == "ethereum" { - handle_ethereum_execution(&intent, U256::from_dec_str(intent_id).unwrap(), amount, intent.src_chain == intent.dst_chain) - .await - .unwrap(); - } else if intent.dst_chain == "mantis" { - handle_mantis_execution(&intent, intent_id) + if let Some(amount) = amount { + println!( + "Auction result for {}: {}", + intent_id, auction_result.message + ); + + // Retrieve the intent + let intent = { + let intents = INTENTS.read().await; + intents.get(&intent_id).cloned() + }; + + if let Some(intent) = intent { + if auction_result.message.contains("won") { + // Handle execution + let handle_result = match intent.dst_chain.as_str() { + "solana" => { + handle_solana_execution(&intent, &intent_id, &amount).await + } + "ethereum" => { + handle_ethereum_execution( + &intent, + intent_id_u256, + &amount, + intent.src_chain == intent.dst_chain, + ) .await - .unwrap(); - } + } + "mantis" => handle_mantis_execution(&intent, &intent_id).await, + _ => Err("Unsupported destination chain".to_string()), + }; - // ws_sender.send(Message::text(msg)).await.expect("Failed to send message"); + if let Err(err) = handle_result { + eprintln!("Failed to handle execution: {}", err); + } } + // Remove the intent { let mut intents = INTENTS.write().await; - intents.remove(&intent_id.to_string()); - drop(intents); + intents.remove(&intent_id); } + } else { + eprintln!("Intent not found for intent_id: {}", intent_id); } } } - Ok(Message::Close(_)) | Err(_) => break, - _ => {} + ServerMessage::ErrorResponse(error_response) => { + eprintln!("Error from server: {}", error_response.message); + } + ServerMessage::QuoteRequest(req) => { + let quote_market = self.quote_market(&req).await; + let message = ClientMessage::QuoteResponse(QuoteResponse { + token_out: req.token_out, + amount_out: quote_market, + }); + self.reply(&message, req_id).await.unwrap(); + } } + Ok(()) } - println!("Auctioner went down, please reconnect"); + async fn quote_market(&self, quote_request: &QuoteRequest) -> String { + let src_chain = "e_request.src_chain; + let dst_chain = "e_request.dst_chain; + let intent_info = PostIntentInfo { + function_name: "".to_string(), + src_chain: src_chain.to_string(), + dst_chain: dst_chain.to_string(), + inputs: OperationInput::SwapTransfer(SwapTransferInput { + token_in: quote_request.token_in.clone(), + amount_in: quote_request.amount_in.clone(), + src_chain_user: quote_request.src_address.clone(), + timeout: "".to_string(), + }), + outputs: OperationOutput::SwapTransfer(SwapTransferOutput { + token_out: quote_request.token_out.clone(), + amount_out: "1".to_string(), + dst_chain_user: quote_request.dst_address.clone(), + }), + }; + get_simulate_swap_intent( + &intent_info, + &src_chain.to_string(), + &dst_chain.to_string(), + BRIDGE_TOKEN, + ) + .await + } } diff --git a/example_solver/src/routers/mod.rs b/example_solver/src/routers/mod.rs index b8db8c5..8703ed7 100644 --- a/example_solver/src/routers/mod.rs +++ b/example_solver/src/routers/mod.rs @@ -41,7 +41,7 @@ pub async fn get_simulate_swap_intent( intent_info: &PostIntentInfo, mut src_chain: &str, mut dst_chain: &str, - bridge_token: &String, + bridge_token: &str, ) -> String { // Extracting values from OperationInput let (mut token_in, amount_in, src_chain_user) = match &intent_info.inputs {