use super::*;
use alloy::sol_types::{eip712_domain, SolValue};
pub(super) async fn place(
announcer: Announcer<'_>, mut input: PlaceInput, signer: Arc<dyn Signer>,
allow_trade: bool, config: ChainConfig,
) -> Result<PlaceOutcome> {
let owner = order_types::parse_address(&input.proxy_owner)?;
if signer.address() != owner {
return Err(eyre!("Ethereum intents require the owner signer; agent delegation is unavailable on Ethereum (1)"));
}
if input.deadline_secs.is_some() {
return Err(eyre!("--deadline-secs applies to agent authorization; Ethereum owner intents expire at --duration-secs"));
}
input.dry_run |= !allow_trade;
let provider = evm::read_provider_checked(&evm::rpc_url(config), config.id).await?;
verify_raw_token_addresses(&provider, config.id, &input).await?;
let order = build_order(&input, owner, config.id).await?;
enforce_cap(&order, input.max_amount.as_deref())?;
let proxy = UserProxyV6::new(proxy_for(&provider, config, owner).await?, provider.clone());
let settler = IntentSettlerV3::new(config.settler, provider);
let digest = owner_digest(config, &order);
if settler.orderHash(order.clone()).call().await? != order_types::order_id(&order)
|| settler.orderDigest(order.clone()).call().await? != digest {
return Err(eyre!("local owner intent hash or digest does not match the settler"));
}
let mut outcome = PlaceOutcome {
dry_run: input.dry_run, chain_id: config.id, order: order_types::dto_from_order(&order),
id: format!("{:?}", order_types::order_id(&order)), authorization: None,
envelope: None, digest: format!("{digest:?}"), signature: None, relay: None, broadcast: None,
tx_hash: None, tx_status: None, tx_error: None, tx_explorer_url: None,
};
if input.dry_run { return Ok(outcome); }
let signature = signer.sign_hash(digest).await?;
let envelope = owner_envelope(Bytes::copy_from_slice(&signature.as_bytes()));
proxy.isIntentAuthorized(order.clone(), envelope.clone()).from(config.settler)
.call().await.map_err(authorization_error)?;
submission::announce(announcer, &input, signer, config, &order, &envelope, &mut outcome).await?;
outcome.signature = Some(format!("0x{}", hex::encode(signature.as_bytes())));
outcome.envelope = Some(hex_bytes(&envelope));
Ok(outcome)
}
fn owner_digest(config: ChainConfig, order: &Order) -> B256 {
order_types::signing_hash(order, &eip712_domain! {
name: "AgentSwap IntentSettler", version: "3",
chain_id: config.id, verifying_contract: config.settler,
})
}
fn owner_envelope(signature: Bytes) -> Bytes {
let payload: Bytes = signature.abi_encode().into();
order_types::IntentAbiCodec::encodeEnvelopeCall { kind: 0, payload }
.abi_encode()[4..].to_vec().into()
}
#[cfg(test)]
mod tests;