use alloy::primitives::{Bytes, U256};
use degenbot_executor::composers::PathInfo;
use crate::gate::{AssessRule, FeePolicy, ProbeSpecs};
use crate::payload::{ComposeError, ComposeOptions, ComposerInputs, PayloadComposer};
use crate::solve_result::SolveResult;
pub trait ExecutionAdapter {
fn encode(&self, path: &PathInfo, inputs: &ComposerInputs<'_>) -> Result<Bytes, ComposeError>;
fn probe_spec(&self) -> &ProbeSpecs;
fn assess_rule(&self) -> Option<AssessRule> {
Some(AssessRule::SumOfDeltas)
}
fn min_net_profit(&self) -> U256 {
U256::ZERO
}
fn fee_policy(&self) -> FeePolicy {
FeePolicy::default()
}
fn assess(
&self,
deltas: &[i128],
gas_used: u64,
base_fee_next: u128,
) -> crate::gate::ExecutionResult {
let gross_profit = crate::gate::ExecutionResult::deltas_to_gross(deltas);
let priority_fee = self.fee_policy().priority_fee();
let gas_cost =
(U256::from(gas_used)) * (U256::from(base_fee_next) + U256::from(priority_fee));
let (net_profit, passed) = match gross_profit.checked_sub(gas_cost) {
Some(net) => (net, net >= self.min_net_profit()),
None => (U256::ZERO, false),
};
crate::gate::ExecutionResult {
gross_profit,
net_profit,
gas_used,
base_fee_next,
priority_fee,
passed,
deltas: deltas.to_vec(),
}
}
fn compose_view(&self, path: &PathInfo, result: &SolveResult) -> Result<Bytes, ComposeError> {
let optimal_input = crate::payload::narrow_u256_to_u128(result.optimal_input)
.ok_or_else(|| ComposeError::encode("optimal_input does not fit int128"))?;
let hop_outputs: Vec<u128> = result
.hop_outputs
.iter()
.map(|v| {
crate::payload::narrow_u256_to_u128(*v)
.ok_or_else(|| ComposeError::encode("hop_output does not fit int128"))
})
.collect::<Result<_, _>>()?;
let consumed_inputs: Vec<u128> = result
.consumed_inputs
.iter()
.map(|v| {
crate::payload::narrow_u256_to_u128(*v)
.ok_or_else(|| ComposeError::encode("consumed_input does not fit int128"))
})
.collect::<Result<_, _>>()?;
let inputs = ComposerInputs {
optimal_input,
hop_outputs: &hop_outputs,
consumed_inputs: &consumed_inputs,
opts: ComposeOptions,
};
self.encode(path, &inputs)
}
}
impl<P: PayloadComposer> ExecutionAdapter for P {
fn encode(&self, path: &PathInfo, inputs: &ComposerInputs<'_>) -> Result<Bytes, ComposeError> {
PayloadComposer::compose(self, path, inputs)
}
fn probe_spec(&self) -> &ProbeSpecs {
static EMPTY: ProbeSpecs = Vec::new();
&EMPTY
}
}