diff --git a/README.md b/README.md index b34c2e5..acb8368 100644 --- a/README.md +++ b/README.md @@ -21,7 +21,7 @@ echo '' | cargo run --bin tycho-encode Here's a complete example that encodes a swap from WETH to DAI using Uniswap V2: ```bash -echo '{"sender":"0x1234567890123456789012345678901234567890","receiver":"0x1234567890123456789012345678901234567890","given_token":"0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2","given_amount":"1000000000000000000","checked_token":"0x6B175474E89094C44Da98b954EedeAC495271d0F","exact_out":false,"slippage":0.01,"expected_amount":"1000000000000000000","check_amount":"990000000000000000","swaps":[{"component":{"id":"0x88e6A0c2dDD26FEEb64F039a2c41296FcB3f5640","protocol_system":"uniswap_v2","protocol_type_name":"UniswapV2Pool","chain":"ethereum","tokens":["0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2"],"contract_ids":["0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D"],"static_attributes":{"factory":"0x5C69bEe701ef814a2B6a3EDD4B1652CB9cc5aA6f"}},"token_in":"0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2","token_out":"0x6B175474E89094C44Da98b954EedeAC495271d0F","split":1.0}],"router_address":"0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D","direct_execution":true}' | cargo run --bin tycho-encode +echo '{"sender":"0x1234567890123456789012345678901234567890","receiver":"0x1234567890123456789012345678901234567890","given_token":"0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2","given_amount":"1000000000000000000","checked_token":"0x6B175474E89094C44Da98b954EedeAC495271d0F","exact_out":false,"slippage":0.01,"expected_amount":"1000000000000000000","check_amount":"990000000000000000","router_address":"0xaa820C29648D5EA543d712cC928377Bd7206a0E7","swaps":[{"component":{"id":"0x88e6A0c2dDD26FEEb64F039a2c41296FcB3f5640","protocol_system":"uniswap_v2","protocol_type_name":"UniswapV2Pool","chain":"ethereum","tokens":["0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2"],"contract_ids":["0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D"],"static_attributes":{"factory":"0x5c69bee701ef814a2b6a3edd4b1652cb9cc5aa6f"},"change":"Update","creation_tx":"0x0000000000000000000000000000000000000000000000000000000000000000","created_at":"2024-02-28T12:00:00"},"token_in":"0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2","token_out":"0x6B175474E89094C44Da98b954EedeAC495271d0F","split":1.0}],"direct_execution":false}' | cargo run ``` #### JSON Payload Structure diff --git a/src/bin/tycho-encode.rs b/src/bin/tycho-encode.rs index 9acf27a..e038115 100644 --- a/src/bin/tycho-encode.rs +++ b/src/bin/tycho-encode.rs @@ -16,10 +16,10 @@ mod lib { pub mod help; } -const DEFAULT_ROUTER_ADDRESS: &str = "0x1234567890123456789012345678901234567890"; +const DEFAULT_ROUTER_ADDRESS: &str = "0xaa820C29648D5EA543d712cC928377Bd7206a0E7"; const DEFAULT_EXECUTORS_FILE_PATH: &str = "src/encoding/config/executor_addresses.json"; const DEFAULT_PRIVATE_KEY: &str = - "0x123456789abcdef123456789abcdef123456789abcdef123456789abcdef1234"; + "0x938f4da9d3a947a4a6c53cfd8fcdd876641d6a4519243820b648af0bc3e67f7c"; fn main() -> Result<(), Box> { let args: Vec = std::env::args().collect(); diff --git a/src/encoding/mod.rs b/src/encoding/mod.rs index 502e336..be17c4a 100644 --- a/src/encoding/mod.rs +++ b/src/encoding/mod.rs @@ -2,6 +2,7 @@ mod errors; #[cfg(feature = "evm")] pub mod evm; pub mod models; +pub mod serde_primitives; pub mod strategy_encoder; mod swap_encoder; pub mod tycho_encoder; diff --git a/src/encoding/models.rs b/src/encoding/models.rs index 598b5bf..44504b5 100644 --- a/src/encoding/models.rs +++ b/src/encoding/models.rs @@ -2,6 +2,8 @@ use num_bigint::BigUint; use serde::{Deserialize, Serialize}; use tycho_core::{dto::ProtocolComponent, Bytes}; +use crate::encoding::serde_primitives::{biguint_string, biguint_string_option}; + #[derive(Clone, Default, Debug, Deserialize, Serialize)] #[serde(rename_all = "snake_case")] pub struct Solution { @@ -77,57 +79,3 @@ pub struct EncodingContext { pub exact_out: bool, pub router_address: Bytes, } - -// Custom serialization for BigUint as string -mod biguint_string { - use std::str::FromStr; - - use num_bigint::BigUint; - use serde::{self, Deserialize, Deserializer, Serializer}; - - pub fn serialize(value: &BigUint, serializer: S) -> Result - where - S: Serializer, - { - serializer.serialize_str(&value.to_string()) - } - - pub fn deserialize<'de, D>(deserializer: D) -> Result - where - D: Deserializer<'de>, - { - let s = String::deserialize(deserializer)?; - BigUint::from_str(&s).map_err(serde::de::Error::custom) - } -} - -// Custom serialization for Option as string -mod biguint_string_option { - use std::str::FromStr; - - use num_bigint::BigUint; - use serde::{self, Deserialize, Deserializer, Serializer}; - - pub fn serialize(value: &Option, serializer: S) -> Result - where - S: Serializer, - { - match value { - Some(v) => serializer.serialize_str(&v.to_string()), - None => serializer.serialize_none(), - } - } - - pub fn deserialize<'de, D>(deserializer: D) -> Result, D::Error> - where - D: Deserializer<'de>, - { - let opt = Option::::deserialize(deserializer)?; - match opt { - Some(s) => BigUint::from_str(&s) - .map(Some) - .map_err(serde::de::Error::custom), - None => Ok(None), - } - } -} diff --git a/src/encoding/serde_primitives.rs b/src/encoding/serde_primitives.rs new file mode 100644 index 0000000..9898815 --- /dev/null +++ b/src/encoding/serde_primitives.rs @@ -0,0 +1,60 @@ +use std::str::FromStr; + +use num_bigint::BigUint; +use serde::{self, Deserialize, Deserializer, Serializer}; + +fn serialize_biguint(value: &BigUint, serializer: S) -> Result +where + S: Serializer, +{ + serializer.serialize_str(&value.to_string()) +} + +fn deserialize_biguint<'de, D>(deserializer: D) -> Result +where + D: Deserializer<'de>, +{ + let s = String::deserialize(deserializer)?; + BigUint::from_str(&s).map_err(serde::de::Error::custom) +} + +pub mod biguint_string { + use super::*; + + pub fn serialize(value: &BigUint, serializer: S) -> Result + where + S: Serializer, + { + serialize_biguint(value, serializer) + } + + pub fn deserialize<'de, D>(deserializer: D) -> Result + where + D: Deserializer<'de>, + { + deserialize_biguint(deserializer) + } +} + +pub mod biguint_string_option { + use super::*; + + pub fn serialize(value: &Option, serializer: S) -> Result + where + S: Serializer, + { + match value { + Some(v) => serialize_biguint(v, serializer), + None => serializer.serialize_none(), + } + } + + pub fn deserialize<'de, D>(deserializer: D) -> Result, D::Error> + where + D: Deserializer<'de>, + { + Option::::deserialize(deserializer)? + .map(|s| BigUint::from_str(&s).map_err(serde::de::Error::custom)) + .transpose() + } +}