feat: simplify
This commit is contained in:
36
src/bin/lib/help.rs
Normal file
36
src/bin/lib/help.rs
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
pub const HELP_TEXT: &str = "\
|
||||||
|
USAGE:
|
||||||
|
tycho-encode [ROUTER_ADDRESS]
|
||||||
|
|
||||||
|
ARGS:
|
||||||
|
ROUTER_ADDRESS The address of the router contract [default: 0x1234567890123456789012345678901234567890]
|
||||||
|
|
||||||
|
The program reads a JSON object from stdin containing the swap details and outputs the encoded transaction.
|
||||||
|
The JSON object should have the following structure:
|
||||||
|
{
|
||||||
|
\"sender\": \"0x...\",
|
||||||
|
\"receiver\": \"0x...\",
|
||||||
|
\"given_token\": \"0x...\",
|
||||||
|
\"given_amount\": \"123...\",
|
||||||
|
\"checked_token\": \"0x...\",
|
||||||
|
\"exact_out\": false,
|
||||||
|
\"slippage\": 0.01,
|
||||||
|
\"expected_amount\": \"123...\",
|
||||||
|
\"check_amount\": \"123...\",
|
||||||
|
\"swaps\": [{
|
||||||
|
\"component\": {
|
||||||
|
\"id\": \"...\",
|
||||||
|
\"protocol_system\": \"...\",
|
||||||
|
\"protocol_type_name\": \"...\",
|
||||||
|
\"chain\": \"ethereum\",
|
||||||
|
\"tokens\": [\"0x...\"],
|
||||||
|
\"contract_ids\": [\"0x...\"],
|
||||||
|
\"static_attributes\": {\"key\": \"0x...\"}
|
||||||
|
},
|
||||||
|
\"token_in\": \"0x...\",
|
||||||
|
\"token_out\": \"0x...\",
|
||||||
|
\"split\": 1.0
|
||||||
|
}],
|
||||||
|
\"router_address\": \"0x...\",
|
||||||
|
\"direct_execution\": false
|
||||||
|
}";
|
||||||
210
src/bin/lib/parse.rs
Normal file
210
src/bin/lib/parse.rs
Normal file
@@ -0,0 +1,210 @@
|
|||||||
|
use std::str::FromStr;
|
||||||
|
|
||||||
|
use chrono::Utc;
|
||||||
|
use num_bigint::BigUint;
|
||||||
|
use serde_json::Value;
|
||||||
|
use tycho_core::{
|
||||||
|
dto::{Chain, ProtocolComponent},
|
||||||
|
Bytes,
|
||||||
|
};
|
||||||
|
use tycho_execution::encoding::models::{Solution, Swap};
|
||||||
|
|
||||||
|
pub fn parse_solution(input: Value) -> Result<Solution, Box<dyn std::error::Error>> {
|
||||||
|
let obj = input
|
||||||
|
.as_object()
|
||||||
|
.ok_or("Input must be a JSON object")?;
|
||||||
|
|
||||||
|
Ok(Solution {
|
||||||
|
sender: parse_bytes(
|
||||||
|
obj.get("sender")
|
||||||
|
.ok_or("sender is required")?,
|
||||||
|
)?,
|
||||||
|
receiver: parse_bytes(
|
||||||
|
obj.get("receiver")
|
||||||
|
.ok_or("receiver is required")?,
|
||||||
|
)?,
|
||||||
|
given_token: parse_bytes(
|
||||||
|
obj.get("given_token")
|
||||||
|
.ok_or("given_token is required")?,
|
||||||
|
)?,
|
||||||
|
given_amount: parse_biguint(
|
||||||
|
obj.get("given_amount")
|
||||||
|
.ok_or("given_amount is required")?,
|
||||||
|
)?,
|
||||||
|
checked_token: parse_bytes(
|
||||||
|
obj.get("checked_token")
|
||||||
|
.ok_or("checked_token is required")?,
|
||||||
|
)?,
|
||||||
|
exact_out: obj
|
||||||
|
.get("exact_out")
|
||||||
|
.and_then(|v| v.as_bool())
|
||||||
|
.unwrap_or(false),
|
||||||
|
slippage: obj
|
||||||
|
.get("slippage")
|
||||||
|
.and_then(|v| v.as_f64()),
|
||||||
|
expected_amount: obj
|
||||||
|
.get("expected_amount")
|
||||||
|
.map(parse_biguint)
|
||||||
|
.transpose()?,
|
||||||
|
check_amount: obj
|
||||||
|
.get("check_amount")
|
||||||
|
.map(parse_biguint)
|
||||||
|
.transpose()?,
|
||||||
|
swaps: parse_swaps(
|
||||||
|
obj.get("swaps")
|
||||||
|
.ok_or("swaps is required")?,
|
||||||
|
)?,
|
||||||
|
router_address: obj
|
||||||
|
.get("router_address")
|
||||||
|
.map(parse_bytes)
|
||||||
|
.transpose()?,
|
||||||
|
native_action: None, // TODO: Implement if needed
|
||||||
|
direct_execution: obj
|
||||||
|
.get("direct_execution")
|
||||||
|
.and_then(|v| v.as_bool())
|
||||||
|
.unwrap_or(false),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
fn parse_bytes(value: &Value) -> Result<Bytes, Box<dyn std::error::Error>> {
|
||||||
|
let s = value
|
||||||
|
.as_str()
|
||||||
|
.ok_or("Expected string for bytes")?;
|
||||||
|
Ok(Bytes::from_str(s)?)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn parse_biguint(value: &Value) -> Result<BigUint, Box<dyn std::error::Error>> {
|
||||||
|
let s = value
|
||||||
|
.as_str()
|
||||||
|
.ok_or("Expected string for BigUint")?;
|
||||||
|
Ok(BigUint::from_str(s)?)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn parse_swaps(value: &Value) -> Result<Vec<Swap>, Box<dyn std::error::Error>> {
|
||||||
|
let arr = value
|
||||||
|
.as_array()
|
||||||
|
.ok_or("Expected array for swaps")?;
|
||||||
|
let mut swaps = Vec::new();
|
||||||
|
|
||||||
|
for swap in arr {
|
||||||
|
let obj = swap
|
||||||
|
.as_object()
|
||||||
|
.ok_or("Swap must be an object")?;
|
||||||
|
swaps.push(Swap {
|
||||||
|
component: parse_protocol_component(
|
||||||
|
obj.get("component")
|
||||||
|
.ok_or("component is required")?,
|
||||||
|
)?,
|
||||||
|
token_in: parse_bytes(
|
||||||
|
obj.get("token_in")
|
||||||
|
.ok_or("token_in is required")?,
|
||||||
|
)?,
|
||||||
|
token_out: parse_bytes(
|
||||||
|
obj.get("token_out")
|
||||||
|
.ok_or("token_out is required")?,
|
||||||
|
)?,
|
||||||
|
split: obj
|
||||||
|
.get("split")
|
||||||
|
.and_then(|v| v.as_f64())
|
||||||
|
.unwrap_or(0.0),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(swaps)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn parse_protocol_component(obj: &Value) -> Result<ProtocolComponent, Box<dyn std::error::Error>> {
|
||||||
|
let obj = obj
|
||||||
|
.as_object()
|
||||||
|
.ok_or("Expected object for ProtocolComponent")?;
|
||||||
|
|
||||||
|
Ok(ProtocolComponent {
|
||||||
|
id: obj
|
||||||
|
.get("id")
|
||||||
|
.and_then(|v| v.as_str())
|
||||||
|
.ok_or("id is required")?
|
||||||
|
.to_string(),
|
||||||
|
protocol_system: obj
|
||||||
|
.get("protocol_system")
|
||||||
|
.and_then(|v| v.as_str())
|
||||||
|
.ok_or("protocol_system is required")?
|
||||||
|
.to_string(),
|
||||||
|
protocol_type_name: obj
|
||||||
|
.get("protocol_type_name")
|
||||||
|
.and_then(|v| v.as_str())
|
||||||
|
.ok_or("protocol_type_name is required")?
|
||||||
|
.to_string(),
|
||||||
|
chain: obj
|
||||||
|
.get("chain")
|
||||||
|
.and_then(|v| v.as_str())
|
||||||
|
.map(|s| match s.to_lowercase().as_str() {
|
||||||
|
"ethereum" => Chain::Ethereum,
|
||||||
|
"starknet" => Chain::Starknet,
|
||||||
|
"zksync" => Chain::ZkSync,
|
||||||
|
"arbitrum" => Chain::Arbitrum,
|
||||||
|
_ => Chain::Ethereum, // Default to Ethereum
|
||||||
|
})
|
||||||
|
.unwrap_or(Chain::Ethereum),
|
||||||
|
tokens: obj
|
||||||
|
.get("tokens")
|
||||||
|
.and_then(|v| v.as_array())
|
||||||
|
.ok_or("tokens is required")?
|
||||||
|
.iter()
|
||||||
|
.map(|v| {
|
||||||
|
v.as_str()
|
||||||
|
.map(|s| Bytes::from_str(s).unwrap())
|
||||||
|
})
|
||||||
|
.collect::<Option<Vec<_>>>()
|
||||||
|
.ok_or("Invalid token address format")?,
|
||||||
|
contract_ids: obj
|
||||||
|
.get("contract_ids")
|
||||||
|
.and_then(|v| v.as_array())
|
||||||
|
.ok_or("contract_ids is required")?
|
||||||
|
.iter()
|
||||||
|
.map(|v| {
|
||||||
|
v.as_str()
|
||||||
|
.map(|s| Bytes::from_str(s).unwrap())
|
||||||
|
})
|
||||||
|
.collect::<Option<Vec<_>>>()
|
||||||
|
.ok_or("Invalid contract address format")?,
|
||||||
|
static_attributes: obj
|
||||||
|
.get("static_attributes")
|
||||||
|
.and_then(|v| v.as_object())
|
||||||
|
.ok_or("static_attributes is required")?
|
||||||
|
.iter()
|
||||||
|
.map(|(k, v)| {
|
||||||
|
Ok((
|
||||||
|
k.clone(),
|
||||||
|
Bytes::from_str(
|
||||||
|
v.as_str()
|
||||||
|
.ok_or("Invalid attribute value")?,
|
||||||
|
)?,
|
||||||
|
))
|
||||||
|
})
|
||||||
|
.collect::<Result<_, Box<dyn std::error::Error>>>()?,
|
||||||
|
change: obj
|
||||||
|
.get("change")
|
||||||
|
.and_then(|v| v.as_str())
|
||||||
|
.map(|s| match s.to_lowercase().as_str() {
|
||||||
|
"update" => tycho_core::dto::ChangeType::Update,
|
||||||
|
"deletion" => tycho_core::dto::ChangeType::Deletion,
|
||||||
|
"creation" => tycho_core::dto::ChangeType::Creation,
|
||||||
|
_ => tycho_core::dto::ChangeType::Unspecified,
|
||||||
|
})
|
||||||
|
.unwrap_or(tycho_core::dto::ChangeType::Update),
|
||||||
|
creation_tx: Bytes::from_str(
|
||||||
|
obj.get("creation_tx")
|
||||||
|
.and_then(|v| v.as_str())
|
||||||
|
.unwrap_or("0x"),
|
||||||
|
)?,
|
||||||
|
created_at: obj
|
||||||
|
.get("created_at")
|
||||||
|
.and_then(|v| v.as_str())
|
||||||
|
.map(|s| {
|
||||||
|
chrono::DateTime::parse_from_rfc3339(s)
|
||||||
|
.unwrap()
|
||||||
|
.naive_utc()
|
||||||
|
})
|
||||||
|
.unwrap_or_else(|| Utc::now().naive_utc()),
|
||||||
|
})
|
||||||
|
}
|
||||||
@@ -1,64 +1,24 @@
|
|||||||
use std::{
|
use std::io::{self, Read};
|
||||||
io::{self, Read},
|
|
||||||
str::FromStr,
|
|
||||||
};
|
|
||||||
|
|
||||||
use chrono::Utc;
|
|
||||||
use hex;
|
use hex;
|
||||||
use num_bigint::BigUint;
|
|
||||||
use serde_json::Value;
|
use serde_json::Value;
|
||||||
use tycho_core::{
|
use tycho_core::dto::Chain;
|
||||||
dto::{Chain, ProtocolComponent},
|
|
||||||
Bytes,
|
|
||||||
};
|
|
||||||
use tycho_execution::encoding::{
|
use tycho_execution::encoding::{
|
||||||
evm::{
|
evm::{
|
||||||
strategy_encoder::strategy_encoder_registry::EVMStrategyEncoderRegistry,
|
strategy_encoder::strategy_encoder_registry::EVMStrategyEncoderRegistry,
|
||||||
tycho_encoder::EVMTychoEncoder,
|
tycho_encoder::EVMTychoEncoder,
|
||||||
},
|
},
|
||||||
models::{Solution, Swap},
|
|
||||||
strategy_encoder::StrategyEncoderRegistry,
|
strategy_encoder::StrategyEncoderRegistry,
|
||||||
tycho_encoder::TychoEncoder,
|
tycho_encoder::TychoEncoder,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
mod lib {
|
||||||
|
pub mod help;
|
||||||
|
pub mod parse;
|
||||||
|
}
|
||||||
|
|
||||||
const DEFAULT_ROUTER_ADDRESS: &str = "0x1234567890123456789012345678901234567890";
|
const DEFAULT_ROUTER_ADDRESS: &str = "0x1234567890123456789012345678901234567890";
|
||||||
const DEFAULT_EXECUTORS_FILE_PATH: &str = "src/encoding/config/executor_addresses.json";
|
const DEFAULT_EXECUTORS_FILE_PATH: &str = "src/encoding/config/executor_addresses.json";
|
||||||
const HELP_TEXT: &str = "\
|
|
||||||
USAGE:
|
|
||||||
tycho-encode [ROUTER_ADDRESS]
|
|
||||||
|
|
||||||
ARGS:
|
|
||||||
ROUTER_ADDRESS The address of the router contract [default: 0x1234567890123456789012345678901234567890]
|
|
||||||
|
|
||||||
The program reads a JSON object from stdin containing the swap details and outputs the encoded transaction.
|
|
||||||
The JSON object should have the following structure:
|
|
||||||
{
|
|
||||||
\"sender\": \"0x...\",
|
|
||||||
\"receiver\": \"0x...\",
|
|
||||||
\"given_token\": \"0x...\",
|
|
||||||
\"given_amount\": \"123...\",
|
|
||||||
\"checked_token\": \"0x...\",
|
|
||||||
\"exact_out\": false,
|
|
||||||
\"slippage\": 0.01,
|
|
||||||
\"expected_amount\": \"123...\",
|
|
||||||
\"check_amount\": \"123...\",
|
|
||||||
\"swaps\": [{
|
|
||||||
\"component\": {
|
|
||||||
\"id\": \"...\",
|
|
||||||
\"protocol_system\": \"...\",
|
|
||||||
\"protocol_type_name\": \"...\",
|
|
||||||
\"chain\": \"ethereum\",
|
|
||||||
\"tokens\": [\"0x...\"],
|
|
||||||
\"contract_ids\": [\"0x...\"],
|
|
||||||
\"static_attributes\": {\"key\": \"0x...\"}
|
|
||||||
},
|
|
||||||
\"token_in\": \"0x...\",
|
|
||||||
\"token_out\": \"0x...\",
|
|
||||||
\"split\": 1.0
|
|
||||||
}],
|
|
||||||
\"router_address\": \"0x...\",
|
|
||||||
\"direct_execution\": false
|
|
||||||
}";
|
|
||||||
|
|
||||||
#[tokio::main]
|
#[tokio::main]
|
||||||
async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||||
@@ -66,7 +26,7 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
|||||||
|
|
||||||
// Show help text if requested
|
// Show help text if requested
|
||||||
if args.len() > 1 && (args[1] == "-h" || args[1] == "--help") {
|
if args.len() > 1 && (args[1] == "-h" || args[1] == "--help") {
|
||||||
println!("{}", HELP_TEXT);
|
println!("{}", lib::help::HELP_TEXT);
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -83,7 +43,7 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
|||||||
|
|
||||||
if buffer.trim().is_empty() {
|
if buffer.trim().is_empty() {
|
||||||
eprintln!("Error: No input provided");
|
eprintln!("Error: No input provided");
|
||||||
eprintln!("{}", HELP_TEXT);
|
eprintln!("{}", lib::help::HELP_TEXT);
|
||||||
std::process::exit(1);
|
std::process::exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -104,212 +64,10 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_solution(input: Value) -> Result<Solution, Box<dyn std::error::Error>> {
|
|
||||||
let obj = input
|
|
||||||
.as_object()
|
|
||||||
.ok_or("Input must be a JSON object")?;
|
|
||||||
|
|
||||||
Ok(Solution {
|
|
||||||
sender: parse_bytes(
|
|
||||||
obj.get("sender")
|
|
||||||
.ok_or("sender is required")?,
|
|
||||||
)?,
|
|
||||||
receiver: parse_bytes(
|
|
||||||
obj.get("receiver")
|
|
||||||
.ok_or("receiver is required")?,
|
|
||||||
)?,
|
|
||||||
given_token: parse_bytes(
|
|
||||||
obj.get("given_token")
|
|
||||||
.ok_or("given_token is required")?,
|
|
||||||
)?,
|
|
||||||
given_amount: parse_biguint(
|
|
||||||
obj.get("given_amount")
|
|
||||||
.ok_or("given_amount is required")?,
|
|
||||||
)?,
|
|
||||||
checked_token: parse_bytes(
|
|
||||||
obj.get("checked_token")
|
|
||||||
.ok_or("checked_token is required")?,
|
|
||||||
)?,
|
|
||||||
exact_out: obj
|
|
||||||
.get("exact_out")
|
|
||||||
.and_then(|v| v.as_bool())
|
|
||||||
.unwrap_or(false),
|
|
||||||
slippage: obj
|
|
||||||
.get("slippage")
|
|
||||||
.and_then(|v| v.as_f64()),
|
|
||||||
expected_amount: obj
|
|
||||||
.get("expected_amount")
|
|
||||||
.map(parse_biguint)
|
|
||||||
.transpose()?,
|
|
||||||
check_amount: obj
|
|
||||||
.get("check_amount")
|
|
||||||
.map(parse_biguint)
|
|
||||||
.transpose()?,
|
|
||||||
swaps: parse_swaps(
|
|
||||||
obj.get("swaps")
|
|
||||||
.ok_or("swaps is required")?,
|
|
||||||
)?,
|
|
||||||
router_address: obj
|
|
||||||
.get("router_address")
|
|
||||||
.map(parse_bytes)
|
|
||||||
.transpose()?,
|
|
||||||
native_action: None, // TODO: Implement if needed
|
|
||||||
direct_execution: obj
|
|
||||||
.get("direct_execution")
|
|
||||||
.and_then(|v| v.as_bool())
|
|
||||||
.unwrap_or(false),
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
fn parse_bytes(value: &Value) -> Result<Bytes, Box<dyn std::error::Error>> {
|
|
||||||
let s = value
|
|
||||||
.as_str()
|
|
||||||
.ok_or("Expected string for bytes")?;
|
|
||||||
Ok(Bytes::from_str(s)?)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn parse_biguint(value: &Value) -> Result<BigUint, Box<dyn std::error::Error>> {
|
|
||||||
let s = value
|
|
||||||
.as_str()
|
|
||||||
.ok_or("Expected string for BigUint")?;
|
|
||||||
Ok(BigUint::from_str(s)?)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn parse_swaps(value: &Value) -> Result<Vec<Swap>, Box<dyn std::error::Error>> {
|
|
||||||
let arr = value
|
|
||||||
.as_array()
|
|
||||||
.ok_or("Expected array for swaps")?;
|
|
||||||
let mut swaps = Vec::new();
|
|
||||||
|
|
||||||
for swap in arr {
|
|
||||||
let obj = swap
|
|
||||||
.as_object()
|
|
||||||
.ok_or("Swap must be an object")?;
|
|
||||||
swaps.push(Swap {
|
|
||||||
component: parse_protocol_component(
|
|
||||||
obj.get("component")
|
|
||||||
.ok_or("component is required")?,
|
|
||||||
)?,
|
|
||||||
token_in: parse_bytes(
|
|
||||||
obj.get("token_in")
|
|
||||||
.ok_or("token_in is required")?,
|
|
||||||
)?,
|
|
||||||
token_out: parse_bytes(
|
|
||||||
obj.get("token_out")
|
|
||||||
.ok_or("token_out is required")?,
|
|
||||||
)?,
|
|
||||||
split: obj
|
|
||||||
.get("split")
|
|
||||||
.and_then(|v| v.as_f64())
|
|
||||||
.unwrap_or(0.0),
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(swaps)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn parse_protocol_component(obj: &Value) -> Result<ProtocolComponent, Box<dyn std::error::Error>> {
|
|
||||||
let obj = obj
|
|
||||||
.as_object()
|
|
||||||
.ok_or("Expected object for ProtocolComponent")?;
|
|
||||||
|
|
||||||
Ok(ProtocolComponent {
|
|
||||||
id: obj
|
|
||||||
.get("id")
|
|
||||||
.and_then(|v| v.as_str())
|
|
||||||
.ok_or("id is required")?
|
|
||||||
.to_string(),
|
|
||||||
protocol_system: obj
|
|
||||||
.get("protocol_system")
|
|
||||||
.and_then(|v| v.as_str())
|
|
||||||
.ok_or("protocol_system is required")?
|
|
||||||
.to_string(),
|
|
||||||
protocol_type_name: obj
|
|
||||||
.get("protocol_type_name")
|
|
||||||
.and_then(|v| v.as_str())
|
|
||||||
.ok_or("protocol_type_name is required")?
|
|
||||||
.to_string(),
|
|
||||||
chain: obj
|
|
||||||
.get("chain")
|
|
||||||
.and_then(|v| v.as_str())
|
|
||||||
.map(|s| match s.to_lowercase().as_str() {
|
|
||||||
"ethereum" => Chain::Ethereum,
|
|
||||||
"starknet" => Chain::Starknet,
|
|
||||||
"zksync" => Chain::ZkSync,
|
|
||||||
"arbitrum" => Chain::Arbitrum,
|
|
||||||
_ => Chain::Ethereum, // Default to Ethereum
|
|
||||||
})
|
|
||||||
.unwrap_or(Chain::Ethereum),
|
|
||||||
tokens: obj
|
|
||||||
.get("tokens")
|
|
||||||
.and_then(|v| v.as_array())
|
|
||||||
.ok_or("tokens is required")?
|
|
||||||
.iter()
|
|
||||||
.map(|v| {
|
|
||||||
v.as_str()
|
|
||||||
.map(|s| Bytes::from_str(s).unwrap())
|
|
||||||
})
|
|
||||||
.collect::<Option<Vec<_>>>()
|
|
||||||
.ok_or("Invalid token address format")?,
|
|
||||||
contract_ids: obj
|
|
||||||
.get("contract_ids")
|
|
||||||
.and_then(|v| v.as_array())
|
|
||||||
.ok_or("contract_ids is required")?
|
|
||||||
.iter()
|
|
||||||
.map(|v| {
|
|
||||||
v.as_str()
|
|
||||||
.map(|s| Bytes::from_str(s).unwrap())
|
|
||||||
})
|
|
||||||
.collect::<Option<Vec<_>>>()
|
|
||||||
.ok_or("Invalid contract address format")?,
|
|
||||||
static_attributes: obj
|
|
||||||
.get("static_attributes")
|
|
||||||
.and_then(|v| v.as_object())
|
|
||||||
.ok_or("static_attributes is required")?
|
|
||||||
.iter()
|
|
||||||
.map(|(k, v)| {
|
|
||||||
Ok((
|
|
||||||
k.clone(),
|
|
||||||
Bytes::from_str(
|
|
||||||
v.as_str()
|
|
||||||
.ok_or("Invalid attribute value")?,
|
|
||||||
)?,
|
|
||||||
))
|
|
||||||
})
|
|
||||||
.collect::<Result<_, Box<dyn std::error::Error>>>()?,
|
|
||||||
change: obj
|
|
||||||
.get("change")
|
|
||||||
.and_then(|v| v.as_str())
|
|
||||||
.map(|s| match s.to_lowercase().as_str() {
|
|
||||||
"update" => tycho_core::dto::ChangeType::Update,
|
|
||||||
"deletion" => tycho_core::dto::ChangeType::Deletion,
|
|
||||||
"creation" => tycho_core::dto::ChangeType::Creation,
|
|
||||||
_ => tycho_core::dto::ChangeType::Unspecified,
|
|
||||||
})
|
|
||||||
.unwrap_or(tycho_core::dto::ChangeType::Update),
|
|
||||||
creation_tx: Bytes::from_str(
|
|
||||||
obj.get("creation_tx")
|
|
||||||
.and_then(|v| v.as_str())
|
|
||||||
.unwrap_or("0x"),
|
|
||||||
)?,
|
|
||||||
created_at: obj
|
|
||||||
.get("created_at")
|
|
||||||
.and_then(|v| v.as_str())
|
|
||||||
.map(|s| {
|
|
||||||
chrono::DateTime::parse_from_rfc3339(s)
|
|
||||||
.unwrap()
|
|
||||||
.naive_utc()
|
|
||||||
})
|
|
||||||
.unwrap_or_else(|| Utc::now().naive_utc()),
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
fn encode_swaps(input: &str, router_address: &str) -> Result<Value, Box<dyn std::error::Error>> {
|
fn encode_swaps(input: &str, router_address: &str) -> Result<Value, Box<dyn std::error::Error>> {
|
||||||
// Parse the input JSON
|
|
||||||
let input_json: Value = serde_json::from_str(input)?;
|
let input_json: Value = serde_json::from_str(input)?;
|
||||||
let solution = parse_solution(input_json)?;
|
let solution = lib::parse::parse_solution(input_json)?;
|
||||||
|
|
||||||
// Create encoder and encode the solution
|
|
||||||
let strategy_selector =
|
let strategy_selector =
|
||||||
EVMStrategyEncoderRegistry::new(Chain::Ethereum, DEFAULT_EXECUTORS_FILE_PATH, None)?;
|
EVMStrategyEncoderRegistry::new(Chain::Ethereum, DEFAULT_EXECUTORS_FILE_PATH, None)?;
|
||||||
let encoder = EVMTychoEncoder::new(strategy_selector, router_address.to_string())?;
|
let encoder = EVMTychoEncoder::new(strategy_selector, router_address.to_string())?;
|
||||||
|
|||||||
Reference in New Issue
Block a user