@@ -120,7 +120,7 @@ impl RefundBuilder {
120
120
let refund = RefundContents {
121
121
payer : PayerContents ( metadata) , metadata : None , description, absolute_expiry : None ,
122
122
issuer : None , paths : None , chain : None , amount_msats,
123
- features : InvoiceRequestFeatures :: empty ( ) , payer_id, payer_note : None ,
123
+ features : InvoiceRequestFeatures :: empty ( ) , quantity : None , payer_id, payer_note : None ,
124
124
} ;
125
125
126
126
Ok ( RefundBuilder { refund } )
@@ -162,6 +162,20 @@ impl RefundBuilder {
162
162
self
163
163
}
164
164
165
+ /// Sets [`Refund::quantity`] of items. This is purely for informational purposes. It is useful
166
+ /// when the refund pertains to an [`Invoice`] that paid for more than one item from an
167
+ /// [`Offer`] as specified by [`InvoiceRequest::quantity`].
168
+ ///
169
+ /// Successive calls to this method will override the previous setting.
170
+ ///
171
+ /// [`Invoice`]: crate::offers::invoice::Invoice
172
+ /// [`InvoiceRequest::quantity`]: crate::offers::invoice_request::InvoiceRequest::quantity
173
+ /// [`Offer`]: crate::offers::offer::Offer
174
+ pub fn quantity ( mut self , quantity : u64 ) -> Self {
175
+ self . refund . quantity = Some ( quantity) ;
176
+ self
177
+ }
178
+
165
179
/// Sets the [`Refund::payer_note`].
166
180
///
167
181
/// Successive calls to this method will override the previous setting.
@@ -224,6 +238,7 @@ pub(super) struct RefundContents {
224
238
chain : Option < ChainHash > ,
225
239
amount_msats : u64 ,
226
240
features : InvoiceRequestFeatures ,
241
+ quantity : Option < u64 > ,
227
242
payer_id : PublicKey ,
228
243
payer_note : Option < String > ,
229
244
}
@@ -285,6 +300,11 @@ impl Refund {
285
300
& self . contents . features
286
301
}
287
302
303
+ /// The quantity of an item that refund is for.
304
+ pub fn quantity ( & self ) -> Option < u64 > {
305
+ self . contents . quantity
306
+ }
307
+
288
308
/// A public node id to send to in the case where there are no [`paths`]. Otherwise, a possibly
289
309
/// transient pubkey.
290
310
///
@@ -396,7 +416,7 @@ impl RefundContents {
396
416
chain : self . chain . as_ref ( ) ,
397
417
amount : Some ( self . amount_msats ) ,
398
418
features,
399
- quantity : None ,
419
+ quantity : self . quantity ,
400
420
payer_id : Some ( & self . payer_id ) ,
401
421
payer_note : self . payer_note . as_ref ( ) ,
402
422
} ;
@@ -514,11 +534,6 @@ impl TryFrom<RefundTlvStream> for RefundContents {
514
534
515
535
let features = features. unwrap_or_else ( InvoiceRequestFeatures :: empty) ;
516
536
517
- // TODO: Check why this isn't in the spec.
518
- if quantity. is_some ( ) {
519
- return Err ( SemanticError :: UnexpectedQuantity ) ;
520
- }
521
-
522
537
let payer_id = match payer_id {
523
538
None => return Err ( SemanticError :: MissingPayerId ) ,
524
539
Some ( payer_id) => payer_id,
@@ -527,7 +542,7 @@ impl TryFrom<RefundTlvStream> for RefundContents {
527
542
// TODO: Should metadata be included?
528
543
Ok ( RefundContents {
529
544
payer, metadata, description, absolute_expiry, issuer, paths, chain, amount_msats,
530
- features, payer_id, payer_note,
545
+ features, quantity , payer_id, payer_note,
531
546
} )
532
547
}
533
548
}
@@ -755,6 +770,24 @@ mod tests {
755
770
assert_eq ! ( tlv_stream. chain, Some ( & testnet) ) ;
756
771
}
757
772
773
+ #[ test]
774
+ fn builds_refund_with_quantity ( ) {
775
+ let refund = RefundBuilder :: new ( "foo" . into ( ) , vec ! [ 1 ; 32 ] , payer_pubkey ( ) , 1000 ) . unwrap ( )
776
+ . quantity ( 10 )
777
+ . build ( ) . unwrap ( ) ;
778
+ let ( _, _, tlv_stream) = refund. as_tlv_stream ( ) ;
779
+ assert_eq ! ( refund. quantity( ) , Some ( 10 ) ) ;
780
+ assert_eq ! ( tlv_stream. quantity, Some ( 10 ) ) ;
781
+
782
+ let refund = RefundBuilder :: new ( "foo" . into ( ) , vec ! [ 1 ; 32 ] , payer_pubkey ( ) , 1000 ) . unwrap ( )
783
+ . quantity ( 10 )
784
+ . quantity ( 1 )
785
+ . build ( ) . unwrap ( ) ;
786
+ let ( _, _, tlv_stream) = refund. as_tlv_stream ( ) ;
787
+ assert_eq ! ( refund. quantity( ) , Some ( 1 ) ) ;
788
+ assert_eq ! ( tlv_stream. quantity, Some ( 1 ) ) ;
789
+ }
790
+
758
791
#[ test]
759
792
fn builds_refund_with_payer_note ( ) {
760
793
let refund = RefundBuilder :: new ( "foo" . into ( ) , vec ! [ 1 ; 32 ] , payer_pubkey ( ) , 1000 ) . unwrap ( )
@@ -888,6 +921,7 @@ mod tests {
888
921
. path ( paths[ 1 ] . clone ( ) )
889
922
. chain ( Network :: Testnet )
890
923
. features_unchecked ( InvoiceRequestFeatures :: unknown ( ) )
924
+ . quantity ( 10 )
891
925
. payer_note ( "baz" . into ( ) )
892
926
. build ( )
893
927
. unwrap ( ) ;
@@ -900,6 +934,7 @@ mod tests {
900
934
assert_eq ! ( refund. issuer( ) , Some ( PrintableString ( "bar" ) ) ) ;
901
935
assert_eq ! ( refund. chain( ) , ChainHash :: using_genesis_block( Network :: Testnet ) ) ;
902
936
assert_eq ! ( refund. features( ) , & InvoiceRequestFeatures :: unknown( ) ) ;
937
+ assert_eq ! ( refund. quantity( ) , Some ( 10 ) ) ;
903
938
assert_eq ! ( refund. payer_note( ) , Some ( PrintableString ( "baz" ) ) ) ;
904
939
} ,
905
940
Err ( e) => panic ! ( "error parsing refund: {:?}" , e) ,
@@ -967,16 +1002,6 @@ mod tests {
967
1002
assert_eq ! ( e, ParseError :: InvalidSemantics ( SemanticError :: UnexpectedSigningPubkey ) ) ;
968
1003
} ,
969
1004
}
970
-
971
- let mut tlv_stream = refund. as_tlv_stream ( ) ;
972
- tlv_stream. 2 . quantity = Some ( 10 ) ;
973
-
974
- match Refund :: try_from ( tlv_stream. to_bytes ( ) ) {
975
- Ok ( _) => panic ! ( "expected error" ) ,
976
- Err ( e) => {
977
- assert_eq ! ( e, ParseError :: InvalidSemantics ( SemanticError :: UnexpectedQuantity ) ) ;
978
- } ,
979
- }
980
1005
}
981
1006
982
1007
#[ test]
0 commit comments