@@ -121,6 +121,8 @@ async fn zero_amount_invoice() {
121121 let payload = SendPaymentRequest {
122122 invoice : invoice. clone ( ) ,
123123 amt_msat : Some ( payment_amount) ,
124+ asset_id : None ,
125+ asset_amount : None ,
124126 } ;
125127 let res = reqwest:: Client :: new ( )
126128 . post ( format ! ( "http://{node1_addr}/sendpayment" ) )
@@ -158,4 +160,177 @@ async fn zero_amount_invoice() {
158160 "Receiver payment should have the amount that was received, not zero"
159161 ) ;
160162 assert_eq ! ( payment_receiver. status, HTLCStatus :: Succeeded ) ;
163+
164+ // Also cover RGB invoice payment where RGB amount is provided at send time.
165+ let asset_id = issue_asset_nia ( node1_addr) . await . asset_id ;
166+ open_channel (
167+ node1_addr,
168+ & node2_pubkey,
169+ Some ( NODE2_PEER_PORT ) ,
170+ None ,
171+ Some ( 3_500_000 ) ,
172+ Some ( 600 ) ,
173+ Some ( & asset_id) ,
174+ )
175+ . await ;
176+
177+ let payload = LNInvoiceRequest {
178+ amt_msat : Some ( 3_000_000 ) ,
179+ expiry_sec : 900 ,
180+ asset_id : Some ( asset_id. clone ( ) ) ,
181+ asset_amount : None ,
182+ } ;
183+ let invoice_without_amount = reqwest:: Client :: new ( )
184+ . post ( format ! ( "http://{node2_addr}/lninvoice" ) )
185+ . json ( & payload)
186+ . send ( )
187+ . await
188+ . unwrap ( )
189+ . json :: < LNInvoiceResponse > ( )
190+ . await
191+ . unwrap ( )
192+ . invoice ;
193+
194+ let decoded_without_amount = decode_ln_invoice ( node1_addr, & invoice_without_amount) . await ;
195+ assert_eq ! ( decoded_without_amount. asset_id, Some ( asset_id. clone( ) ) ) ;
196+ assert_eq ! ( decoded_without_amount. asset_amount, None ) ;
197+
198+ // If the RGB invoice already includes asset_id and asset_amount, sendpayment can omit both.
199+ let payload = LNInvoiceRequest {
200+ amt_msat : Some ( 3_000_000 ) ,
201+ expiry_sec : 900 ,
202+ asset_id : Some ( asset_id. clone ( ) ) ,
203+ asset_amount : Some ( 50 ) ,
204+ } ;
205+ let invoice_with_amount = reqwest:: Client :: new ( )
206+ . post ( format ! ( "http://{node2_addr}/lninvoice" ) )
207+ . json ( & payload)
208+ . send ( )
209+ . await
210+ . unwrap ( )
211+ . json :: < LNInvoiceResponse > ( )
212+ . await
213+ . unwrap ( )
214+ . invoice ;
215+
216+ let decoded_with_amount = decode_ln_invoice ( node1_addr, & invoice_with_amount) . await ;
217+ assert_eq ! ( decoded_with_amount. asset_id, Some ( asset_id. clone( ) ) ) ;
218+ assert_eq ! ( decoded_with_amount. asset_amount, Some ( 50 ) ) ;
219+
220+ let payload = SendPaymentRequest {
221+ invoice : invoice_with_amount,
222+ amt_msat : Some ( 3_000_000 ) ,
223+ asset_id : None ,
224+ asset_amount : None ,
225+ } ;
226+ let res = reqwest:: Client :: new ( )
227+ . post ( format ! ( "http://{node1_addr}/sendpayment" ) )
228+ . json ( & payload)
229+ . send ( )
230+ . await
231+ . unwrap ( )
232+ . json :: < SendPaymentResponse > ( )
233+ . await
234+ . unwrap ( ) ;
235+ wait_for_ln_payment (
236+ node2_addr,
237+ & res. payment_hash . unwrap ( ) ,
238+ HTLCStatus :: Succeeded ,
239+ )
240+ . await ;
241+ let payment = get_payment ( node2_addr, & decoded_with_amount. payment_hash ) . await ;
242+ assert_eq ! ( payment. asset_id, Some ( asset_id. clone( ) ) ) ;
243+ assert_eq ! ( payment. asset_amount, Some ( 50 ) ) ;
244+
245+ // Attempting to pay without both RGB fields should fail.
246+ let payload = SendPaymentRequest {
247+ invoice : invoice_without_amount. clone ( ) ,
248+ amt_msat : Some ( 3_000_000 ) ,
249+ asset_id : None ,
250+ asset_amount : None ,
251+ } ;
252+ let res = reqwest:: Client :: new ( )
253+ . post ( format ! ( "http://{node1_addr}/sendpayment" ) )
254+ . json ( & payload)
255+ . send ( )
256+ . await
257+ . unwrap ( ) ;
258+ check_response_is_nok (
259+ res,
260+ reqwest:: StatusCode :: BAD_REQUEST ,
261+ "both the asset ID and amount are necessary" ,
262+ "IncompleteRGBInfo" ,
263+ )
264+ . await ;
265+
266+ // Providing an invalid RGB asset_id format should fail.
267+ let payload = SendPaymentRequest {
268+ invoice : invoice_without_amount. clone ( ) ,
269+ amt_msat : Some ( 3_000_000 ) ,
270+ asset_id : Some ( s ! ( "not-a-valid-contract-id" ) ) ,
271+ asset_amount : Some ( 100 ) ,
272+ } ;
273+ let res = reqwest:: Client :: new ( )
274+ . post ( format ! ( "http://{node1_addr}/sendpayment" ) )
275+ . json ( & payload)
276+ . send ( )
277+ . await
278+ . unwrap ( ) ;
279+ check_response_is_nok (
280+ res,
281+ reqwest:: StatusCode :: BAD_REQUEST ,
282+ "Invalid asset ID" ,
283+ "InvalidAssetID" ,
284+ )
285+ . await ;
286+
287+ // Providing a different but valid RGB asset_id should fail with contract mismatch.
288+ let other_asset_id = issue_asset_nia ( node1_addr) . await . asset_id ;
289+ let payload = SendPaymentRequest {
290+ invoice : invoice_without_amount. clone ( ) ,
291+ amt_msat : Some ( 3_000_000 ) ,
292+ asset_id : Some ( other_asset_id) ,
293+ asset_amount : Some ( 100 ) ,
294+ } ;
295+ let res = reqwest:: Client :: new ( )
296+ . post ( format ! ( "http://{node1_addr}/sendpayment" ) )
297+ . json ( & payload)
298+ . send ( )
299+ . await
300+ . unwrap ( ) ;
301+ check_response_is_nok (
302+ res,
303+ reqwest:: StatusCode :: BAD_REQUEST ,
304+ "contract ID doesn't match the requested one" ,
305+ "InvalidInvoice" ,
306+ )
307+ . await ;
308+
309+ // Providing the RGB fields in sendpayment should succeed.
310+ let payload = SendPaymentRequest {
311+ invoice : invoice_without_amount,
312+ amt_msat : Some ( 3_000_000 ) ,
313+ asset_id : Some ( asset_id) ,
314+ asset_amount : Some ( 100 ) ,
315+ } ;
316+ let res = reqwest:: Client :: new ( )
317+ . post ( format ! ( "http://{node1_addr}/sendpayment" ) )
318+ . json ( & payload)
319+ . send ( )
320+ . await
321+ . unwrap ( ) ;
322+ assert_eq ! (
323+ res. status( ) ,
324+ reqwest:: StatusCode :: OK ,
325+ "paying RGB invoice by providing asset_amount in sendpayment should succeed"
326+ ) ;
327+ let res = res. json :: < SendPaymentResponse > ( ) . await . unwrap ( ) ;
328+ wait_for_ln_payment (
329+ node2_addr,
330+ & res. payment_hash . unwrap ( ) ,
331+ HTLCStatus :: Succeeded ,
332+ )
333+ . await ;
334+ let payment = get_payment ( node2_addr, & decoded_without_amount. payment_hash ) . await ;
335+ assert_eq ! ( payment. asset_amount, Some ( 100 ) ) ;
161336}
0 commit comments