use super::types::TempoMethodDetails;
use crate::error::{MppError, Result};
use crate::evm::{parse_address, parse_amount, Address, U256};
use crate::protocol::intents::ChargeRequest;
pub trait TempoChargeExt {
fn amount_u256(&self) -> Result<U256>;
fn recipient_address(&self) -> Result<Address>;
fn currency_address(&self) -> Result<Address>;
fn chain_id(&self) -> Option<u64>;
fn tempo_method_details(&self) -> Result<TempoMethodDetails>;
fn fee_payer(&self) -> bool;
fn is_tempo_moderato(&self) -> bool;
}
impl TempoChargeExt for ChargeRequest {
fn amount_u256(&self) -> Result<U256> {
parse_amount(&self.amount)
}
fn recipient_address(&self) -> Result<Address> {
let recipient = self.recipient.as_ref().ok_or_else(|| {
MppError::invalid_challenge_reason("No recipient specified".to_string())
})?;
parse_address(recipient)
}
fn currency_address(&self) -> Result<Address> {
parse_address(&self.currency)
}
fn chain_id(&self) -> Option<u64> {
self.method_details
.as_ref()
.and_then(|v| v.get("chainId"))
.and_then(|v| v.as_u64())
}
fn tempo_method_details(&self) -> Result<TempoMethodDetails> {
match &self.method_details {
Some(value) => serde_json::from_value(value.clone()).map_err(|e| {
MppError::invalid_challenge_reason(format!("Invalid Tempo method details: {}", e))
}),
None => Ok(TempoMethodDetails::default()),
}
}
fn fee_payer(&self) -> bool {
self.method_details
.as_ref()
.and_then(|v| v.get("feePayer"))
.and_then(|v| v.as_bool())
.unwrap_or(false)
}
fn is_tempo_moderato(&self) -> bool {
self.chain_id() == Some(super::CHAIN_ID)
}
}
#[cfg(test)]
mod tests {
use super::*;
fn test_charge_request() -> ChargeRequest {
ChargeRequest {
amount: "1000000".to_string(),
currency: "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48".to_string(),
recipient: Some("0x742d35Cc6634C0532925a3b844Bc9e7595f1B0F2".to_string()),
expires: Some("2024-01-01T00:00:00Z".to_string()),
description: None,
external_id: None,
method_details: Some(serde_json::json!({
"chainId": 42431,
"feePayer": true
})),
}
}
#[test]
fn test_tempo_method_details() {
let req = test_charge_request();
let details = req.tempo_method_details().unwrap();
assert_eq!(details.chain_id, Some(42431));
assert!(details.fee_payer());
}
#[test]
fn test_fee_payer() {
let req = test_charge_request();
assert!(req.fee_payer());
let req_no_fee = ChargeRequest {
method_details: None,
..test_charge_request()
};
assert!(!req_no_fee.fee_payer());
}
#[test]
fn test_is_tempo_moderato() {
let req = test_charge_request();
assert!(req.is_tempo_moderato());
let req_other_chain = ChargeRequest {
method_details: Some(serde_json::json!({"chainId": 1})),
..test_charge_request()
};
assert!(!req_other_chain.is_tempo_moderato());
}
}