#[derive(Clone, Copy, PartialEq, Eq, Hash)]
pub struct Address(pub [u8; 20]);
impl Address {
pub fn from_hex(s: &str) -> Result<Self, hex::FromHexError> {
let s = s.strip_prefix("0x").or_else(|| s.strip_prefix("0X")).unwrap_or(s);
let mut bytes = [0u8; 20];
hex::decode_to_slice(s, &mut bytes)?;
Ok(Self(bytes))
}
pub fn to_hex(&self) -> String {
format!("0x{}", hex::encode(self.0))
}
}
impl std::fmt::Debug for Address {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "Address({})", self.to_hex())
}
}
impl std::fmt::Display for Address {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{}", self.to_hex())
}
}
#[derive(Clone, Copy, PartialEq, Eq, Hash)]
pub struct Hash(pub [u8; 32]);
impl Hash {
pub fn to_hex(&self) -> String {
format!("0x{}", hex::encode(self.0))
}
pub fn is_zero(&self) -> bool {
self.0.iter().all(|&b| b == 0)
}
}
impl std::fmt::Debug for Hash {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "Hash({})", self.to_hex())
}
}
impl std::fmt::Display for Hash {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{}", self.to_hex())
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum KernelVersion {
V3_3,
}
impl KernelVersion {
pub(crate) fn to_c(self) -> i32 {
match self {
Self::V3_3 => 0,
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum GasMiddleware {
ZeroDev,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum PaymasterMiddleware {
None,
ZeroDev,
}
#[derive(Debug, Clone)]
pub struct UserOperationReceipt {
pub json: String,
pub user_op_hash: String,
pub entry_point: String,
pub sender: String,
pub nonce: String,
pub paymaster: Option<String>,
pub actual_gas_cost: String,
pub actual_gas_used: String,
pub success: bool,
pub reason: Option<String>,
}
impl UserOperationReceipt {
pub(crate) fn from_json(json: String) -> Self {
fn extract_string(json: &str, key: &str) -> String {
let needle = format!("\"{}\":\"", key);
if let Some(start) = json.find(&needle) {
let val_start = start + needle.len();
if let Some(end) = json[val_start..].find('"') {
return json[val_start..val_start + end].to_string();
}
}
String::new()
}
fn extract_bool(json: &str, key: &str) -> bool {
let needle = format!("\"{}\":", key);
if let Some(start) = json.find(&needle) {
let rest = &json[start + needle.len()..];
return rest.trim_start().starts_with("true");
}
false
}
fn extract_optional_string(json: &str, key: &str) -> Option<String> {
let s = extract_string(json, key);
if s.is_empty() { None } else { Some(s) }
}
Self {
user_op_hash: extract_string(&json, "userOpHash"),
entry_point: extract_string(&json, "entryPoint"),
sender: extract_string(&json, "sender"),
nonce: extract_string(&json, "nonce"),
paymaster: extract_optional_string(&json, "paymaster"),
actual_gas_cost: extract_string(&json, "actualGasCost"),
actual_gas_used: extract_string(&json, "actualGasUsed"),
success: extract_bool(&json, "success"),
reason: extract_optional_string(&json, "reason"),
json,
}
}
}
pub struct Call {
pub target: Address,
pub value: [u8; 32],
pub calldata: Vec<u8>,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Authorization {
pub chain_id: u64,
pub address: [u8; 20],
pub nonce: u64,
pub y_parity: u8,
pub r: [u8; 32],
pub s: [u8; 32],
}