//! Concrete swap provider enum for dynamic dispatch. //! //! Since the `SwapProvider` trait has generic methods, it cannot be made into //! a trait object. This module provides a concrete enum that can be used //! for dynamic dispatch while maintaining type safety. use near_primitives::views::FinalExecutionStatus; use near_sdk::AccountId; use templar_common::asset::{AssetClass, FungibleAsset, FungibleAssetAmount}; use crate::rpc::AppResult; use super::{oneclick::OneClickSwap, r#ref::RefSwap, SwapProvider}; /// Concrete swap provider implementation that can be used for dynamic dispatch. /// /// This enum wraps all supported swap providers and implements `SwapProvider`, /// allowing it to be used where dynamic dispatch is needed. #[derive(Debug, Clone)] pub enum SwapProviderImpl { /// Ref Finance classic AMM provider (v2.ref-finance.near) RefFinance(RefSwap), /// 1-Click API provider for NEP-245 cross-chain swaps OneClick(OneClickSwap), } impl SwapProviderImpl { /// Creates a Ref Finance provider variant. pub fn ref_finance(provider: RefSwap) -> Self { Self::RefFinance(provider) } /// Creates a 1-Click API provider variant. pub fn oneclick(provider: OneClickSwap) -> Self { Self::OneClick(provider) } } #[async_trait::async_trait] impl SwapProvider for SwapProviderImpl { async fn quote( &self, from_asset: &FungibleAsset, to_asset: &FungibleAsset, output_amount: FungibleAssetAmount, ) -> AppResult> { match self { Self::RefFinance(provider) => provider.quote(from_asset, to_asset, output_amount).await, Self::OneClick(provider) => provider.quote(from_asset, to_asset, output_amount).await, } } async fn swap( &self, from_asset: &FungibleAsset, to_asset: &FungibleAsset, amount: FungibleAssetAmount, ) -> AppResult { match self { Self::RefFinance(provider) => provider.swap(from_asset, to_asset, amount).await, Self::OneClick(provider) => provider.swap(from_asset, to_asset, amount).await, } } fn provider_name(&self) -> &'static str { match self { Self::RefFinance(provider) => provider.provider_name(), Self::OneClick(provider) => provider.provider_name(), } } fn supports_assets( &self, from_asset: &FungibleAsset, to_asset: &FungibleAsset, ) -> bool { match self { Self::RefFinance(provider) => provider.supports_assets(from_asset, to_asset), Self::OneClick(provider) => provider.supports_assets(from_asset, to_asset), } } async fn ensure_storage_registration( &self, token_contract: &FungibleAsset, account_id: &AccountId, ) -> AppResult<()> { match self { Self::RefFinance(provider) => { provider .ensure_storage_registration(token_contract, account_id) .await } Self::OneClick(provider) => { provider .ensure_storage_registration(token_contract, account_id) .await } } } }