@@ -123,7 +123,7 @@ use crate::types::string::UntrustedString;
123123use crate::util::config::{ChannelConfig, ChannelConfigOverrides, ChannelConfigUpdate, UserConfig};
124124use crate::util::errors::APIError;
125125use crate::util::logger::{Level, Logger, WithContext};
126- use crate::util::scid_utils::fake_scid;
126+ use crate::util::scid_utils::{ fake_scid, SCID_SELF_PAYMENT} ;
127127use crate::util::ser::{
128128	BigSize, FixedLengthReader, LengthReadable, MaybeReadable, Readable, ReadableArgs, VecWriter,
129129	Writeable, Writer,
@@ -4906,6 +4906,11 @@ where
49064906			path, payment_hash, recipient_onion, total_value, cur_height, payment_id, keysend_preimage,
49074907			invoice_request, bolt12_invoice, session_priv_bytes
49084908		} = args;
4909+ 
4910+ 		if path.hops.first().unwrap().short_channel_id == SCID_SELF_PAYMENT {
4911+ 			return self.handle_self_payment(&payment_hash, &recipient_onion, total_value, payment_id, &keysend_preimage);
4912+ 		}
4913+ 
49094914		// The top-level caller should hold the total_consistency_lock read lock.
49104915		debug_assert!(self.total_consistency_lock.try_write().is_err());
49114916		let prng_seed = self.entropy_source.get_secure_random_bytes();
@@ -5078,6 +5083,88 @@ where
50785083			|args| self.send_payment_along_path(args),
50795084		)
50805085	}
5086+     
5087+     /// Send a payment to ourselves (self-payment).
5088+     ///
5089+     /// This method creates a payment route from the node to itself, enabling testing
5090+     /// of payment functionality and providing a way to generate payment events locally.
5091+     ///
5092+     /// # Arguments
5093+     /// * `payment_preimage` - The preimage for the payment hash
5094+     /// * `recipient_onion` - The recipient onion fields for the payment
5095+     /// * `payment_id` - A unique identifier for this payment
5096+     ///
5097+     /// # Returns
5098+     /// Returns the payment hash on success, or an APIError on failure.
5099+     pub fn send_self_payment(
5100+ 		&self, payment_preimage: PaymentPreimage, recipient_onion: RecipientOnionFields,
5101+ 		payment_id: PaymentId, final_value_msat: u64
5102+ 	) -> Result<PaymentHash, APIError> {
5103+ 		// Create route parameters for self-payment
5104+ 		let payment_params = PaymentParameters::from_node_id(
5105+ 			self.get_our_node_id(), 
5106+ 			MIN_FINAL_CLTV_EXPIRY_DELTA as u32
5107+ 		);
5108+ 		let route_params = RouteParameters::from_payment_params_and_value(
5109+ 			payment_params, 
5110+ 			final_value_msat// Amount in msat
5111+ 		);
5112+ 		
5113+ 		// Use existing spontaneous payment infrastructure
5114+ 		self.send_spontaneous_payment(
5115+ 			Some(payment_preimage),
5116+ 			recipient_onion,
5117+ 			payment_id,
5118+ 			route_params,
5119+ 			Retry::Attempts(0)
5120+ 		).map_err(|e| APIError::APIMisuseError { 
5121+ 			err: format!("Self-payment failed: {:?}", e) 
5122+ 		})
5123+ 	}
5124+     
5125+ 	fn handle_self_payment(
5126+ 		&self, payment_hash: &PaymentHash, recipient_onion: &RecipientOnionFields,
5127+ 		total_value: u64, payment_id: PaymentId, keysend_preimage: &Option<PaymentPreimage>
5128+ 	) -> Result<(), APIError> {
5129+ 		// For self-payments, we need to:
5130+ 		// 1. Validate the payment secret/preimage
5131+ 		// 2. Generate a PaymentClaimable event
5132+ 		// 3. The user can then claim_funds() to complete the payment
5133+ 		
5134+ 		let payment_preimage = if let Some(preimage) = keysend_preimage {
5135+ 			*preimage
5136+ 		} else {
5137+ 			// For non-keysend self-payments, try to find the preimage
5138+ 			// This would require looking up the payment in inbound_payment_key
5139+ 			return Err(APIError::APIMisuseError {
5140+ 				err: "Self-payment without keysend preimage not yet supported".to_owned()
5141+ 			});
5142+ 		};
5143+ 		
5144+ 		// Validate payment hash matches preimage
5145+ 		if PaymentHash(Sha256::hash(&payment_preimage.0).to_byte_array()) != *payment_hash {
5146+ 			return Err(APIError::APIMisuseError {
5147+ 				err: "Payment hash does not match preimage".to_owned()
5148+ 			});
5149+ 		}
5150+ 		
5151+ 		// Create payment claimable event
5152+ 		let purpose = events::PaymentPurpose::SpontaneousPayment(payment_preimage);
5153+ 		let payment_claimable = events::Event::PaymentClaimable {
5154+ 			receiver_node_id: Some(self.get_our_node_id()),
5155+ 			payment_hash: *payment_hash,
5156+ 			onion_fields: Some(recipient_onion.clone()),
5157+ 			amount_msat: total_value,
5158+ 			counterparty_skimmed_fee_msat: 0,
5159+ 			purpose,
5160+ 			via_channel_ids: vec![],
5161+ 			claim_deadline: None,
5162+ 			payment_id: Some(payment_id),
5163+ 		};
5164+ 		
5165+ 		self.pending_events.lock().unwrap().push_back((payment_claimable, None));
5166+ 		Ok(())
5167+ 	}
50815168
50825169	#[cfg(any(test, feature = "_externalize_tests"))]
50835170	pub(super) fn test_send_payment_internal(
0 commit comments