105 lines
3.3 KiB
Rust
105 lines
3.3 KiB
Rust
use std::io::{self, Read};
|
|
|
|
use serde_json::Value;
|
|
use tycho_core::dto::Chain;
|
|
use tycho_execution::encoding::{
|
|
evm::{
|
|
strategy_encoder::strategy_encoder_registry::EVMStrategyEncoderRegistry,
|
|
tycho_encoder::EVMTychoEncoder,
|
|
},
|
|
strategy_encoder::StrategyEncoderRegistry,
|
|
tycho_encoder::TychoEncoder,
|
|
};
|
|
|
|
mod lib {
|
|
pub mod help;
|
|
pub mod parse;
|
|
}
|
|
|
|
const DEFAULT_ROUTER_ADDRESS: &str = "0x1234567890123456789012345678901234567890";
|
|
const DEFAULT_EXECUTORS_FILE_PATH: &str = "src/encoding/config/executor_addresses.json";
|
|
const DEFAULT_PRIVATE_KEY: &str =
|
|
"0x123456789abcdef123456789abcdef123456789abcdef123456789abcdef1234";
|
|
|
|
fn main() -> Result<(), Box<dyn std::error::Error>> {
|
|
let args: Vec<String> = std::env::args().collect();
|
|
|
|
// Show help text if requested
|
|
if args.len() > 1 && (args[1] == "-h" || args[1] == "--help") {
|
|
println!("{}", lib::help::HELP_TEXT);
|
|
return Ok(());
|
|
}
|
|
|
|
let router_address = args
|
|
.get(1)
|
|
.map(|s| s.as_str())
|
|
.unwrap_or(DEFAULT_ROUTER_ADDRESS);
|
|
|
|
let private_key = args
|
|
.get(2)
|
|
.map(|s| s.to_string())
|
|
.or_else(|| Some(DEFAULT_PRIVATE_KEY.to_string()));
|
|
|
|
// Read from stdin until EOF
|
|
let mut buffer = String::new();
|
|
io::stdin()
|
|
.read_to_string(&mut buffer)
|
|
.map_err(|e| format!("Failed to read from stdin: {}", e))?;
|
|
|
|
if buffer.trim().is_empty() {
|
|
eprintln!("Error: No input provided");
|
|
eprintln!("{}", lib::help::HELP_TEXT);
|
|
std::process::exit(1);
|
|
}
|
|
|
|
// Parse the JSON input to verify it's valid
|
|
let input_json: Value =
|
|
serde_json::from_str(&buffer).map_err(|e| format!("Failed to parse JSON input: {}", e))?;
|
|
|
|
// Check if direct_execution is false and private_key is missing
|
|
if let Some(obj) = input_json.as_object() {
|
|
if let Some(direct_execution) = obj
|
|
.get("direct_execution")
|
|
.and_then(|v| v.as_bool())
|
|
{
|
|
if !direct_execution && private_key.is_none() {
|
|
eprintln!("Error: Private key is required when direct_execution is false");
|
|
eprintln!("{}", lib::help::HELP_TEXT);
|
|
std::process::exit(1);
|
|
}
|
|
}
|
|
}
|
|
|
|
// Encode the solution
|
|
let encoded = encode_swaps(&buffer, router_address, private_key)?;
|
|
|
|
// Output the encoded result as JSON to stdout
|
|
println!(
|
|
"{}",
|
|
serde_json::to_string(&encoded)
|
|
.map_err(|e| format!("Failed to serialize output: {}", e))?
|
|
);
|
|
|
|
Ok(())
|
|
}
|
|
|
|
fn encode_swaps(
|
|
input: &str,
|
|
router_address: &str,
|
|
private_key: Option<String>,
|
|
) -> Result<Value, Box<dyn std::error::Error>> {
|
|
let input_json: Value = serde_json::from_str(input)?;
|
|
let solution = lib::parse::parse_solution(input_json)?;
|
|
|
|
let strategy_selector =
|
|
EVMStrategyEncoderRegistry::new(Chain::Ethereum, DEFAULT_EXECUTORS_FILE_PATH, private_key)?;
|
|
let encoder = EVMTychoEncoder::new(strategy_selector, router_address.to_string())?;
|
|
let transactions = encoder.encode_router_calldata(vec![solution])?;
|
|
|
|
Ok(serde_json::json!({
|
|
"to": format!("0x{}", hex::encode(&transactions[0].to)),
|
|
"value": format!("0x{}", hex::encode(transactions[0].value.to_bytes_be())),
|
|
"data": format!("0x{}", hex::encode(&transactions[0].data)),
|
|
}))
|
|
}
|