@@ -23,6 +23,7 @@ use soroban_sdk::{contract, contractimpl, token::TokenClient, Address, BytesN, E
2323
2424pub use errors:: ContractError ;
2525pub use types:: {
26+ ArbitrationConfig , DisclosureGrant , DisputeResolution , Proposal , ProposalAction ,
2627 ArbitrationConfig , ArbitratorVote , DisclosureGrant , DisputeResolution , MultiSigConfig ,
2728 Proposal , ProposalAction , ProposalStatus , Subscription , SubscriptionTier , TierConfig ,
2829 TemplateTerms , TemplateVersion , Trade , TradePrivacy , TradeStatus , TradeTemplate ,
@@ -1901,6 +1902,125 @@ impl StellarEscrowContract {
19011902 pub fn amm_get_lp_position ( env : Env , pool_id : u64 , provider : Address ) -> amm:: LpPosition {
19021903 amm:: get_lp_position ( & env, pool_id, & provider)
19031904 }
1905+
1906+ // -------------------------------------------------------------------------
1907+ // Trade Templates
1908+ // -------------------------------------------------------------------------
1909+
1910+ /// Create a reusable trade template. Owner must authenticate.
1911+ pub fn create_template (
1912+ env : Env ,
1913+ owner : Address ,
1914+ name : soroban_sdk:: String ,
1915+ terms : TemplateTerms ,
1916+ ) -> Result < u64 , ContractError > {
1917+ require_initialized ( & env) ?;
1918+ owner. require_auth ( ) ;
1919+ templates:: create_template ( & env, & owner, name, terms)
1920+ }
1921+
1922+ /// Update a template with new terms, bumping its version number.
1923+ /// Only the template owner may call this.
1924+ pub fn update_template (
1925+ env : Env ,
1926+ caller : Address ,
1927+ template_id : u64 ,
1928+ name : soroban_sdk:: String ,
1929+ terms : TemplateTerms ,
1930+ ) -> Result < ( ) , ContractError > {
1931+ require_initialized ( & env) ?;
1932+ caller. require_auth ( ) ;
1933+ templates:: update_template ( & env, & caller, template_id, name, terms)
1934+ }
1935+
1936+ /// Deactivate a template so it can no longer be used to create trades.
1937+ /// Only the template owner may call this.
1938+ pub fn deactivate_template (
1939+ env : Env ,
1940+ caller : Address ,
1941+ template_id : u64 ,
1942+ ) -> Result < ( ) , ContractError > {
1943+ require_initialized ( & env) ?;
1944+ caller. require_auth ( ) ;
1945+ templates:: deactivate_template ( & env, & caller, template_id)
1946+ }
1947+
1948+ /// Create a trade from a template, inheriting its default arbitrator and
1949+ /// metadata. If the template has a `fixed_amount`, `amount` must match.
1950+ pub fn create_trade_from_template (
1951+ env : Env ,
1952+ seller : Address ,
1953+ buyer : Address ,
1954+ template_id : u64 ,
1955+ amount : u64 ,
1956+ ) -> Result < u64 , ContractError > {
1957+ require_initialized ( & env) ?;
1958+ require_not_paused ( & env) ?;
1959+ if amount == 0 {
1960+ return Err ( ContractError :: InvalidAmount ) ;
1961+ }
1962+ seller. require_auth ( ) ;
1963+
1964+ let ( terms, version) = templates:: resolve_terms ( & env, template_id) ?;
1965+
1966+ if let Some ( fixed) = terms. fixed_amount {
1967+ if amount != fixed {
1968+ return Err ( ContractError :: TemplateAmountMismatch ) ;
1969+ }
1970+ }
1971+ if let Some ( ref arb) = terms. default_arbitrator {
1972+ if !has_arbitrator ( & env, arb) {
1973+ return Err ( ContractError :: ArbitratorNotRegistered ) ;
1974+ }
1975+ }
1976+
1977+ let trade_id = increment_trade_counter ( & env) ?;
1978+ let fee = calc_fee ( & env, & seller, amount) ?;
1979+ let trade = Trade {
1980+ id : trade_id,
1981+ seller : seller. clone ( ) ,
1982+ buyer : buyer. clone ( ) ,
1983+ amount,
1984+ fee,
1985+ arbitrator : terms. default_arbitrator . map ( ArbitrationConfig :: Single ) ,
1986+ status : TradeStatus :: Created ,
1987+ expiry_time : None ,
1988+ currency : get_usdc_token ( & env) ?,
1989+ metadata : terms. default_metadata ,
1990+ } ;
1991+ save_trade ( & env, trade_id, & trade) ;
1992+ events:: emit_trade_created ( & env, trade_id, seller, buyer, amount, trade. currency ) ;
1993+ events:: emit_template_trade ( & env, trade_id, template_id, version) ;
1994+ Ok ( trade_id)
1995+ }
1996+
1997+ /// Fetch a template by ID.
1998+ pub fn get_template ( env : Env , template_id : u64 ) -> Result < TradeTemplate , ContractError > {
1999+ storage:: get_template ( & env, template_id)
2000+ }
2001+
2002+ /// Fetch a specific version of a template's terms by version number.
2003+ pub fn get_template_version (
2004+ env : Env ,
2005+ template_id : u64 ,
2006+ version : u32 ,
2007+ ) -> Result < TemplateVersion , ContractError > {
2008+ let template = storage:: get_template ( & env, template_id) ?;
2009+ for i in 0 ..template. versions . len ( ) {
2010+ let v = template. versions . get ( i) . unwrap ( ) ;
2011+ if v. version == version {
2012+ return Ok ( v) ;
2013+ }
2014+ }
2015+ Err ( ContractError :: TemplateNotFound )
2016+ }
2017+
2018+ /// Returns true if the template exists and is active.
2019+ pub fn is_template_valid ( env : Env , template_id : u64 ) -> bool {
2020+ storage:: get_template ( & env, template_id)
2021+ . map ( |t| t. active )
2022+ . unwrap_or ( false )
2023+ }
19042024}
19052025
19062026
0 commit comments