use super::*;
pub struct AsyncX402 {
db: Arc<PostgresDatabase>,
}
impl AsyncX402 {
pub(crate) const fn new(db: Arc<PostgresDatabase>) -> Self {
Self { db }
}
pub async fn create_intent(&self, input: CreateX402PaymentIntent) -> Result<X402PaymentIntent> {
self.db.x402_payment_intents().create_async(input).await
}
pub async fn get_intent(&self, id: Uuid) -> Result<Option<X402PaymentIntent>> {
self.db.x402_payment_intents().get_async(id).await
}
pub async fn sign_intent(
&self,
id: Uuid,
input: SignX402PaymentIntent,
) -> Result<X402PaymentIntent> {
self.db.x402_payment_intents().sign_async(id, input).await
}
pub async fn mark_sequenced(
&self,
id: Uuid,
sequence_number: u64,
batch_id: Uuid,
) -> Result<X402PaymentIntent> {
self.db.x402_payment_intents().mark_sequenced_async(id, sequence_number, batch_id).await
}
pub async fn mark_settled(
&self,
id: Uuid,
tx_hash: &str,
block_number: u64,
) -> Result<X402PaymentIntent> {
self.db.x402_payment_intents().mark_settled_async(id, tx_hash, block_number).await
}
pub async fn mark_failed(&self, id: Uuid, reason: &str) -> Result<X402PaymentIntent> {
self.db.x402_payment_intents().mark_failed_async(id, reason).await
}
pub async fn mark_expired(&self, id: Uuid) -> Result<X402PaymentIntent> {
self.db.x402_payment_intents().mark_expired_async(id).await
}
pub async fn cancel_intent(&self, id: Uuid) -> Result<X402PaymentIntent> {
self.db.x402_payment_intents().cancel_async(id).await
}
pub async fn intents_for_cart(&self, cart_id: Uuid) -> Result<Vec<X402PaymentIntent>> {
self.db.x402_payment_intents().for_cart_async(cart_id).await
}
pub async fn intents_for_order(&self, order_id: Uuid) -> Result<Vec<X402PaymentIntent>> {
self.db.x402_payment_intents().for_order_async(order_id).await
}
pub async fn get_next_nonce(&self, payer_address: &str) -> Result<u64> {
self.db.x402_payment_intents().get_next_nonce_async(payer_address).await
}
pub async fn list_intents(
&self,
filter: X402PaymentIntentFilter,
) -> Result<Vec<X402PaymentIntent>> {
self.db.x402_payment_intents().list_async(filter).await
}
pub async fn count_intents(&self, filter: X402PaymentIntentFilter) -> Result<u64> {
self.db.x402_payment_intents().count_async(filter).await
}
pub async fn expire_stale_intents(&self) -> Result<u64> {
self.db.x402_payment_intents().expire_stale_intents_async().await
}
pub async fn intents_by_status(
&self,
status: X402IntentStatus,
) -> Result<Vec<X402PaymentIntent>> {
self.list_intents(X402PaymentIntentFilter { status: Some(status), ..Default::default() })
.await
}
pub async fn pending_intents(&self) -> Result<Vec<X402PaymentIntent>> {
self.intents_by_status(X402IntentStatus::Created).await
}
pub async fn signed_intents(&self) -> Result<Vec<X402PaymentIntent>> {
self.intents_by_status(X402IntentStatus::Signed).await
}
pub async fn settled_intents(&self) -> Result<Vec<X402PaymentIntent>> {
self.intents_by_status(X402IntentStatus::Settled).await
}
pub async fn get_credit_account(
&self,
payer_address: &str,
asset: X402Asset,
network: X402Network,
) -> Result<Option<X402CreditAccount>> {
self.db.x402_credits().get_account_async(payer_address, asset, network).await
}
pub async fn get_or_create_credit_account(
&self,
payer_address: &str,
asset: X402Asset,
network: X402Network,
) -> Result<X402CreditAccount> {
self.db.x402_credits().get_or_create_account_async(payer_address, asset, network).await
}
pub async fn get_credit_balance(
&self,
payer_address: &str,
asset: X402Asset,
network: X402Network,
) -> Result<u64> {
self.db.x402_credits().get_balance_async(payer_address, asset, network).await
}
pub async fn adjust_credit_balance(
&self,
input: X402CreditAdjustment,
) -> Result<X402CreditTransaction> {
self.db.x402_credits().adjust_balance_async(input).await
}
#[allow(clippy::too_many_arguments)]
pub async fn credit_account(
&self,
payer_address: &str,
asset: X402Asset,
network: X402Network,
amount: u64,
reason: Option<String>,
reference_id: Option<String>,
metadata: Option<String>,
) -> Result<X402CreditTransaction> {
self.adjust_credit_balance(X402CreditAdjustment {
payer_address: payer_address.to_string(),
asset,
network,
direction: X402CreditDirection::Credit,
amount,
reason,
reference_id,
metadata,
})
.await
}
#[allow(clippy::too_many_arguments)]
pub async fn debit_account(
&self,
payer_address: &str,
asset: X402Asset,
network: X402Network,
amount: u64,
reason: Option<String>,
reference_id: Option<String>,
metadata: Option<String>,
) -> Result<X402CreditTransaction> {
self.adjust_credit_balance(X402CreditAdjustment {
payer_address: payer_address.to_string(),
asset,
network,
direction: X402CreditDirection::Debit,
amount,
reason,
reference_id,
metadata,
})
.await
}
pub async fn list_credit_transactions(
&self,
filter: X402CreditTransactionFilter,
) -> Result<Vec<X402CreditTransaction>> {
self.db.x402_credits().list_transactions_async(filter).await
}
pub async fn register_agent(&self, input: CreateAgentCard) -> Result<AgentCard> {
self.db.agent_cards().create_async(input).await
}
pub async fn get_agent(&self, id: Uuid) -> Result<Option<AgentCard>> {
self.db.agent_cards().get_async(id).await
}
pub async fn get_agent_by_wallet(&self, wallet_address: &str) -> Result<Option<AgentCard>> {
self.db.agent_cards().get_by_wallet_async(wallet_address).await
}
pub async fn update_agent(&self, id: Uuid, input: UpdateAgentCard) -> Result<AgentCard> {
self.db.agent_cards().update_async(id, input).await
}
pub async fn delete_agent(&self, id: Uuid) -> Result<()> {
self.db.agent_cards().delete_async(id).await
}
pub async fn list_agents(&self, filter: AgentCardFilter) -> Result<Vec<AgentCard>> {
self.db.agent_cards().list_async(filter).await
}
pub async fn count_agents(&self, filter: AgentCardFilter) -> Result<u64> {
self.db.agent_cards().count_async(filter).await
}
pub async fn verify_agent(&self, id: Uuid) -> Result<AgentCard> {
self.db.agent_cards().verify_async(id, TrustLevel::Verified, "system").await
}
pub async fn suspend_agent(&self, id: Uuid, reason: &str) -> Result<AgentCard> {
self.db.agent_cards().suspend_async(id, reason).await
}
pub async fn reactivate_agent(&self, id: Uuid) -> Result<AgentCard> {
self.db.agent_cards().reactivate_async(id).await
}
pub async fn discover_agents(
&self,
network: Option<X402Network>,
asset: Option<X402Asset>,
skill: Option<A2ASkill>,
min_trust_level: Option<TrustLevel>,
) -> Result<Vec<AgentCard>> {
self.db
.agent_cards()
.discover_async(AgentCardFilter {
network,
asset,
skill,
trust_level: None,
min_trust_level,
active: Some(true),
..Default::default()
})
.await
}
pub async fn active_agents(&self) -> Result<Vec<AgentCard>> {
self.list_agents(AgentCardFilter { active: Some(true), ..Default::default() }).await
}
pub async fn agents_by_trust_level(&self, level: TrustLevel) -> Result<Vec<AgentCard>> {
self.list_agents(AgentCardFilter {
trust_level: Some(level),
active: Some(true),
..Default::default()
})
.await
}
pub async fn verified_agents(&self) -> Result<Vec<AgentCard>> {
self.agents_by_trust_level(TrustLevel::Verified).await
}
pub async fn create_cart_payment(
&self,
cart_id: Uuid,
payer_address: &str,
payee_address: &str,
amount: rust_decimal::Decimal,
network: X402Network,
asset: X402Asset,
) -> Result<X402PaymentIntent> {
self.create_intent(CreateX402PaymentIntent {
payer_address: payer_address.to_string(),
payee_address: payee_address.to_string(),
amount: to_smallest_unit(amount, asset),
asset,
network,
cart_id: Some(cart_id),
..Default::default()
})
.await
}
pub async fn active_intent_for_cart(&self, cart_id: Uuid) -> Result<Option<X402PaymentIntent>> {
let intents = self.intents_for_cart(cart_id).await?;
Ok(intents.into_iter().find(|intent| {
matches!(
intent.status,
X402IntentStatus::Created
| X402IntentStatus::Signed
| X402IntentStatus::Sequenced
| X402IntentStatus::Settled
)
}))
}
pub async fn is_ready_for_settlement(&self, id: Uuid) -> Result<bool> {
if let Some(intent) = self.get_intent(id).await? {
let now = Utc::now().timestamp() as u64;
Ok(intent.status == X402IntentStatus::Signed && intent.valid_until > now)
} else {
Ok(false)
}
}
pub async fn has_valid_signature(&self, id: Uuid) -> Result<bool> {
if let Some(intent) = self.get_intent(id).await? {
if !intent.is_signed() {
return Ok(false);
}
Ok(intent.verify_signature().unwrap_or(false))
} else {
Ok(false)
}
}
pub async fn create_quote(&self, input: CreateA2AQuote) -> Result<SkillQuote> {
self.db.a2a_quotes().create_quote_async(input).await
}
pub async fn get_quote(&self, id: Uuid) -> Result<Option<SkillQuote>> {
self.db.a2a_quotes().get_quote_async(id).await
}
pub async fn get_quote_by_number(&self, quote_number: &str) -> Result<Option<SkillQuote>> {
self.db.a2a_quotes().get_quote_by_number_async(quote_number).await
}
pub async fn update_quote_status(&self, id: Uuid, status: QuoteStatus) -> Result<SkillQuote> {
self.db.a2a_quotes().update_quote_status_async(id, status).await
}
pub async fn list_quotes(&self, filter: SkillQuoteFilter) -> Result<Vec<SkillQuote>> {
self.db.a2a_quotes().list_quotes_async(filter).await
}
pub async fn count_quotes(&self, filter: SkillQuoteFilter) -> Result<u64> {
self.db.a2a_quotes().count_quotes_async(filter).await
}
pub async fn create_purchase(&self, input: CreateA2APurchase) -> Result<A2APurchase> {
self.db.a2a_purchases().create_purchase_async(input).await
}
pub async fn get_purchase(&self, id: Uuid) -> Result<Option<A2APurchase>> {
self.db.a2a_purchases().get_purchase_async(id).await
}
pub async fn get_purchase_by_number(
&self,
purchase_number: &str,
) -> Result<Option<A2APurchase>> {
self.db.a2a_purchases().get_purchase_by_number_async(purchase_number).await
}
pub async fn update_purchase_status(
&self,
id: Uuid,
status: PurchaseStatus,
) -> Result<A2APurchase> {
self.db.a2a_purchases().update_purchase_status_async(id, status).await
}
pub async fn link_purchase_to_order(
&self,
purchase_id: Uuid,
order_id: Uuid,
) -> Result<A2APurchase> {
self.db.a2a_purchases().link_purchase_to_order_async(purchase_id, order_id).await
}
pub async fn confirm_delivery(
&self,
purchase_id: Uuid,
signature: &str,
rating: Option<u8>,
feedback: Option<&str>,
) -> Result<A2APurchase> {
self.db
.a2a_purchases()
.confirm_delivery_async(purchase_id, signature, rating, feedback)
.await
}
pub async fn list_purchases(&self, filter: A2APurchaseFilter) -> Result<Vec<A2APurchase>> {
self.db.a2a_purchases().list_purchases_async(filter).await
}
pub async fn count_purchases(&self, filter: A2APurchaseFilter) -> Result<u64> {
self.db.a2a_purchases().count_purchases_async(filter).await
}
}