signet_types/signing/
order.rs1use crate::signing::{permit_signing_info, SignedPermitError, SigningError};
2use alloy::{
3 network::TransactionBuilder, primitives::Address, rpc::types::TransactionRequest,
4 signers::Signer, sol_types::SolCall,
5};
6use chrono::Utc;
7use serde::{Deserialize, Serialize};
8use signet_zenith::RollupOrders::{
9 initiatePermit2Call, Order, Output, Permit2Batch, TokenPermissions,
10};
11use std::borrow::Cow;
12
13#[derive(Clone, Debug, Deserialize, Serialize, PartialEq, Eq)]
27pub struct SignedOrder {
28 #[serde(flatten)]
30 pub permit: Permit2Batch,
31 pub outputs: Vec<Output>,
33}
34
35impl SignedOrder {
36 pub const fn new(permit: Permit2Batch, outputs: Vec<Output>) -> Self {
38 Self { permit, outputs }
39 }
40
41 pub fn validate(&self, timestamp: u64) -> Result<(), SignedPermitError> {
46 let deadline = self.permit.permit.deadline.saturating_to::<u64>();
47 if timestamp > deadline {
48 return Err(SignedPermitError::DeadlinePassed { current: timestamp, deadline });
49 }
50
51 Ok(())
52 }
53
54 pub fn to_initiate_tx(
56 &self,
57 filler_token_recipient: Address,
58 order_contract: Address,
59 ) -> TransactionRequest {
60 let initiate_data = initiatePermit2Call {
62 tokenRecipient: filler_token_recipient,
63 outputs: self.outputs.clone(),
64 permit2: self.permit.clone(),
65 }
66 .abi_encode();
67
68 TransactionRequest::default().with_input(initiate_data).with_to(order_contract)
70 }
71}
72
73#[derive(Clone, Debug, Deserialize, Serialize, PartialEq, Eq)]
78pub struct UnsignedOrder<'a> {
79 order: Cow<'a, Order>,
80 nonce: Option<u64>,
81 rollup_chain_id: Option<u64>,
82 rollup_order_address: Option<Address>,
83}
84
85impl<'a> From<&'a Order> for UnsignedOrder<'a> {
86 fn from(order: &'a Order) -> Self {
87 UnsignedOrder::new(order)
88 }
89}
90
91impl<'a> UnsignedOrder<'a> {
92 pub fn new(order: &'a Order) -> Self {
94 Self { order: order.into(), nonce: None, rollup_chain_id: None, rollup_order_address: None }
95 }
96
97 pub fn with_nonce(self, nonce: u64) -> Self {
99 Self { nonce: Some(nonce), ..self }
100 }
101
102 pub fn with_chain(self, chain_id: u64, order_contract_address: Address) -> Self {
104 Self {
105 rollup_chain_id: Some(chain_id),
106 rollup_order_address: Some(order_contract_address),
107 ..self
108 }
109 }
110
111 pub async fn sign<S: Signer>(&self, signer: &S) -> Result<SignedOrder, SigningError> {
113 let nonce = self.nonce.unwrap_or(Utc::now().timestamp_micros() as u64);
115
116 let rollup_chain_id = self.rollup_chain_id.ok_or(SigningError::MissingChainId)?;
118 let rollup_order_contract =
119 self.rollup_order_address.ok_or(SigningError::MissingOrderContract(rollup_chain_id))?;
120
121 let outputs = self.order.outputs().to_vec();
123 let permitted: Vec<TokenPermissions> = self.order.inputs().iter().map(Into::into).collect();
125
126 let permit = permit_signing_info(
128 outputs,
129 permitted,
130 self.order.deadline(),
131 nonce,
132 rollup_chain_id,
133 rollup_order_contract,
134 );
135
136 let signature = signer.sign_hash(&permit.signing_hash).await?;
138
139 Ok(SignedOrder {
141 permit: Permit2Batch {
142 permit: permit.permit,
143 owner: signer.address(),
144 signature: signature.as_bytes().into(),
145 },
146 outputs: permit.outputs,
147 })
148 }
149}