pub fn swap_start<'a, L, C, K>(
	wallet_inst: Arc<Mutex<Box<dyn WalletInst<'a, L, C, K>>>>,
	keychain_mask: Option<&SecretKey>,
	params: &SwapStartArgs,
) -> Result<String, Error>
where
	L: WalletLCProvider<'a, C, K>,
	C: NodeClient + 'a,
	K: Keychain + 'a,
{
	// Starting a swap trade.
	// This method only initialize and store the swap process. Nothing is done

	// First we need to define outputs that we can use.
	// Reading all output.
	let (_, outputs) = super::owner::retrieve_outputs(
		wallet_inst.clone(),
		keychain_mask,
		&None,
		false,
		false,
		None,
	)?;
	// Reading all swaps. We need to exclude

	let mut outs: HashMap<String, u64> = outputs
		.iter()
		.filter(|o| o.output.commit.is_some())
		.map(|o| (o.output.commit.clone().unwrap(), o.output.value))
		.collect();

	wallet_lock!(wallet_inst, w);
	let node_client = w.w2n_client().clone();
	let keychain = w.keychain(keychain_mask)?;
	let skey = get_swap_storage_key(&keychain)?;
	let height = node_client.get_chain_tip()?.0;

	let mut swap_reserved_amount = 0;

	// Searching to swaps that are started, but not locked
	let swap_id = trades::list_swap_trades()?;
	for sw_id in &swap_id {
		let swap_lock = trades::get_swap_lock(sw_id);
		let _l = swap_lock.lock();
		let (_, swap) = trades::get_swap_trade(sw_id.as_str(), &skey, &*swap_lock)?;

		if swap.is_seller() && !swap.state.is_final_state() {
			// Check if funds are not locked yet
			if swap.posted_lock.is_none() {
				// So funds are not posted, transaction doesn't exist and outpuyts are not locked.
				// We have to exclude those outputs
				for inp in swap.lock_slate.tx.body.inputs {
					let in_commit = to_hex(inp.commit.0.to_vec());
					if let Some(amount) = outs.remove(&in_commit) {
						swap_reserved_amount += amount;
					}
				}
			}
		}
	}

	if swap_reserved_amount > 0 {
		let swap_reserved_amount_str =
			mimble_core::core::amount_to_hr_string(swap_reserved_amount, true);
		info!("Running swaps reserved {} coins", swap_reserved_amount);
		println!("WARNING. This swap will need to reserve {} MWC. If you don't have enough funds, please cancel it.", swap_reserved_amount_str);
	}

	let outputs: Vec<&str> = outs.keys().map(AsRef::as_ref).collect();
	let secondary_currency = Currency::try_from(params.secondary_currency.as_str())?;
	let secondary_amount = secondary_currency.amount_from_hr_string(&params.secondary_amount)?;

	let mut swap_api = crate::swap::api::create_instance(&secondary_currency, node_client)?;

	let parent_key_id = w.parent_key_id(); // account is current one
	let (outputs, total, amount, fee) = crate::internal::selection::select_coins_and_fee(
		&mut **w,
		params.mwc_amount,
		height,
		params.minimum_confirmations.unwrap_or(10),
		500,
		1,
		false,
		&parent_key_id,
		&Some(outputs), // outputs to include into the transaction
		1,              // Number of resulting outputs. Normally it is 1
		false,
		0,
	)?;

	let context = create_context(
		&mut **w,
		keychain_mask,
		&mut swap_api,
		&keychain,
		secondary_currency,
		true,
		Some(
			outputs
				.iter()
				.map(|out| (out.key_id.clone(), out.mmr_index.clone(), out.value))
				.collect(),
		),
		total - amount - fee,
	)?;

	let swap = (*swap_api).create_swap_offer(
		&keychain,
		&context,
		params.mwc_amount, // mwc amount to sell
		secondary_amount,  // btc amount to buy
		secondary_currency,
		params.secondary_redeem_address.clone(),
		params.seller_lock_first,
		params.mwc_confirmations,
		params.secondary_confirmations,
		params.message_exchange_time_sec,
		params.redeem_time_sec,
		params.buyer_communication_method.clone(),
		params.buyer_communication_address.clone(),
	)?;

	// Store swap result into the file.
	let swap_id = swap.id.to_string();
	let swap_lock = trades::get_swap_lock(&swap_id);
	let _l = swap_lock.lock();
	if trades::get_swap_trade(swap_id.as_str(), &skey, &*swap_lock).is_ok() {
		// Should be impossible, uuid suppose to be unique. But we don't want to overwrite anything
		return Err(ErrorKind::TradeIoError(
			swap_id.clone(),
			"This trade record already exist".to_string(),
		)
		.into());
	}

	trades::store_swap_trade(&context, &swap, &skey, &*swap_lock)?;

	Ok(swap_id)
}
/// Start swap trade process. Return SwapID that can be used to check the status or perform further action.
Start swap trade process. Return SwapID that can be used to check the status or perform further action.
Start swap trade process . Return SwapID that can be used to check the status or perform further action .
pub fn swap_start<'a, L, C, K>(
	wallet_inst: Arc<Mutex<Box<dyn WalletInst<'a, L, C, K>>>>,
	keychain_mask: Option<&SecretKey>,
	params: &SwapStartArgs,
) -> Result<String, Error>
where
	L: WalletLCProvider<'a, C, K>,
	C: NodeClient + 'a,
	K: Keychain + 'a,
{
	// Starting a swap trade.
	// This method only initialize and store the swap process. Nothing is done
	// First we need to define outputs that we can use.
	// Reading all output.
	let (_, outputs) = super::owner::retrieve_outputs(
		wallet_inst.clone(),
		keychain_mask,
		&None,
		false,
		false,
		None,
	)?;
	// Reading all swaps. We need to exclude
	let mut outs: HashMap<String, u64> = outputs
		.iter()
		.filter(|o| o.output.commit.is_some())
		.map(|o| (o.output.commit.clone().unwrap(), o.output.value))
		.collect();
	wallet_lock!(wallet_inst, w);
	let node_client = w.w2n_client().clone();
	let keychain = w.keychain(keychain_mask)?;
	let skey = get_swap_storage_key(&keychain)?;
	let height = node_client.get_chain_tip()?.0;
	let mut swap_reserved_amount = 0;
	// Searching to swaps that are started, but not locked
	let swap_id = trades::list_swap_trades()?;
	for sw_id in &swap_id {
		let swap_lock = trades::get_swap_lock(sw_id);
		let _l = swap_lock.lock();
		let (_, swap) = trades::get_swap_trade(sw_id.as_str(), &skey, &*swap_lock)?;
		if swap.is_seller() && !swap.state.is_final_state() {
			// Check if funds are not locked yet
			if swap.posted_lock.is_none() {
				// So funds are not posted, transaction doesn't exist and outpuyts are not locked.
				// We have to exclude those outputs
				for inp in swap.lock_slate.tx.body.inputs {
					let in_commit = to_hex(inp.commit.0.to_vec());
					if let Some(amount) = outs.remove(&in_commit) {
						swap_reserved_amount += amount;
					}
				}
			}
		}
	}
	if swap_reserved_amount > 0 {
		let swap_reserved_amount_str =
			mimble_core::core::amount_to_hr_string(swap_reserved_amount, true);
		info!("Running swaps reserved {} coins", swap_reserved_amount);
		println!("WARNING. This swap will need to reserve {} MWC. If you don't have enough funds, please cancel it.", swap_reserved_amount_str);
	}
	let outputs: Vec<&str> = outs.keys().map(AsRef::as_ref).collect();
	let secondary_currency = Currency::try_from(params.secondary_currency.as_str())?;
	let secondary_amount = secondary_currency.amount_from_hr_string(&params.secondary_amount)?;
	let mut swap_api = crate::swap::api::create_instance(&secondary_currency, node_client)?;
	let parent_key_id = w.parent_key_id(); // account is current one
	let (outputs, total, amount, fee) = crate::internal::selection::select_coins_and_fee(
		&mut **w,
		params.mwc_amount,
		height,
		params.minimum_confirmations.unwrap_or(10),
		500,
		1,
		false,
		&parent_key_id,
		&Some(outputs), // outputs to include into the transaction
		1,              // Number of resulting outputs. Normally it is 1
		false,
		0,
	)?;
	let context = create_context(
		&mut **w,
		keychain_mask,
		&mut swap_api,
		&keychain,
		secondary_currency,
		true,
		Some(
			outputs
				.iter()
				.map(|out| (out.key_id.clone(), out.mmr_index.clone(), out.value))
				.collect(),
		),
		total - amount - fee,
	)?;
	let swap = (*swap_api).create_swap_offer(
		&keychain,
		&context,
		params.mwc_amount, // mwc amount to sell
		secondary_amount,  // btc amount to buy
		secondary_currency,
		params.secondary_redeem_address.clone(),
		params.seller_lock_first,
		params.mwc_confirmations,
		params.secondary_confirmations,
		params.message_exchange_time_sec,
		params.redeem_time_sec,
		params.buyer_communication_method.clone(),
		params.buyer_communication_address.clone(),
	)?;
	// Store swap result into the file.
	let swap_id = swap.id.to_string();
	let swap_lock = trades::get_swap_lock(&swap_id);
	let _l = swap_lock.lock();
	if trades::get_swap_trade(swap_id.as_str(), &skey, &*swap_lock).is_ok() {
		// Should be impossible, uuid suppose to be unique. But we don't want to overwrite anything
		return Err(ErrorKind::TradeIoError(
			swap_id.clone(),
			"This trade record already exist".to_string(),
		)
		.into());
	}
	trades::store_swap_trade(&context, &swap, &skey, &*swap_lock)?;
	Ok(swap_id)
}
pub fn swap_start < ' a , L , C , K > ( wallet_inst : Arc < Mutex < Box < dyn WalletInst < ' a , L , C , K > > > > , keychain_mask : Option < & SecretKey > , params : & SwapStartArgs , ) -> Result < String , Error > where L : WalletLCProvider < ' a , C , K > , C : NodeClient + ' a , K : Keychain + ' a , { // Starting a swap trade. // This method only initialize and store the swap process. Nothing is done // First we need to define outputs that we can use. // Reading all output. let ( _ , outputs ) = super :: owner :: retrieve_outputs ( wallet_inst . clone ( ) , keychain_mask , & None , false , false , None , ) ? ; // Reading all swaps. We need to exclude let mut outs : HashMap < String , u64 > = outputs . iter ( ) . filter ( | o | o . output . commit . is_some ( ) ) . map ( | o | ( o . output . commit . clone ( ) . unwrap ( ) , o . output . value ) ) . collect ( ) ; wallet_lock ! ( wallet_inst w ) ; let node_client = w . w2n_client ( ) . clone ( ) ; let keychain = w . keychain ( keychain_mask ) ? ; let skey = get_swap_storage_key ( & keychain ) ? ; let height = node_client . get_chain_tip ( ) ? . 0 ; let mut swap_reserved_amount = 0 ; // Searching to swaps that are started, but not locked let swap_id = trades :: list_swap_trades ( ) ? ; for sw_id in & swap_id { let swap_lock = trades :: get_swap_lock ( sw_id ) ; let _l = swap_lock . lock ( ) ; let ( _ , swap ) = trades :: get_swap_trade ( sw_id . as_str ( ) , & skey , & * swap_lock ) ? ; if swap . is_seller ( ) && ! swap . state . is_final_state ( ) { // Check if funds are not locked yet if swap . posted_lock . is_none ( ) { // So funds are not posted, transaction doesn't exist and outpuyts are not locked. // We have to exclude those outputs for inp in swap . lock_slate . tx . body . inputs { let in_commit = to_hex ( inp . commit . 0 . to_vec ( ) ) ; if let Some ( amount ) = outs . remove ( & in_commit ) { swap_reserved_amount += amount ; } } } } } if swap_reserved_amount > 0 { let swap_reserved_amount_str = mimble_core :: core :: amount_to_hr_string ( swap_reserved_amount , true ) ; info ! ( " " swap_reserved_amount ) ; println ! ( " " swap_reserved_amount_str ) ; } let outputs : Vec < & str > = outs . keys ( ) . map ( AsRef :: as_ref ) . collect ( ) ; let secondary_currency = Currency :: try_from ( params . secondary_currency . as_str ( ) ) ? ; let secondary_amount = secondary_currency . amount_from_hr_string ( & params . secondary_amount ) ? ; let mut swap_api = crate :: swap :: api :: create_instance ( & secondary_currency , node_client ) ? ; let parent_key_id = w . parent_key_id ( ) ; // account is current one let ( outputs , total , amount , fee ) = crate :: internal :: selection :: select_coins_and_fee ( & mut * * w , params . mwc_amount , height , params . minimum_confirmations . unwrap_or ( 10 ) , 500 , 1 , false , & parent_key_id , & Some ( outputs ) , // outputs to include into the transaction 1 , // Number of resulting outputs. Normally it is 1 false , 0 , ) ? ; let context = create_context ( & mut * * w , keychain_mask , & mut swap_api , & keychain , secondary_currency , true , Some ( outputs . iter ( ) . map ( | out | ( out . key_id . clone ( ) , out . mmr_index . clone ( ) , out . value ) ) . collect ( ) , ) , total - amount - fee , ) ? ; let swap = ( * swap_api ) . create_swap_offer ( & keychain , & context , params . mwc_amount , // mwc amount to sell secondary_amount , // btc amount to buy secondary_currency , params . secondary_redeem_address . clone ( ) , params . seller_lock_first , params . mwc_confirmations , params . secondary_confirmations , params . message_exchange_time_sec , params . redeem_time_sec , params . buyer_communication_method . clone ( ) , params . buyer_communication_address . clone ( ) , ) ? ; // Store swap result into the file. let swap_id = swap . id . to_string ( ) ; let swap_lock = trades :: get_swap_lock ( & swap_id ) ; let _l = swap_lock . lock ( ) ; if trades :: get_swap_trade ( swap_id . as_str ( ) , & skey , & * swap_lock ) . is_ok ( ) { // Should be impossible, uuid suppose to be unique. But we don't want to overwrite anything return Err ( ErrorKind :: TradeIoError ( swap_id . clone ( ) , " " . to_string ( ) , ) . into ( ) ) ; } trades :: store_swap_trade ( & context , & swap , & skey , & * swap_lock ) ? ; Ok ( swap_id ) }
Start swap trade process.
Start swap trade process .
wallet_inst
Arc<Mutex<Box<dyn WalletInst<'a, L, C, K>>>>
keychain_mask
Option<&SecretKey>
params
&SwapStartArgs
wallet_inst
Arc<Mutex<Box<dyn WalletInst<'a, L, C, K>>>>
keychain_mask
Option<&SecretKey>
params
&SwapStartArgs