@@ -166,6 +166,116 @@ fn success() {
166166 ) ;
167167}
168168
169+ #[ cfg( feature = "electrum" ) ]
170+ #[ test]
171+ #[ parallel]
172+ fn filters ( ) {
173+ initialize ( ) ;
174+
175+ let amount: u64 = 66 ;
176+
177+ let mut party = get_funded_party ! ( ) ;
178+ let mut rcv_party = get_funded_party ! ( ) ;
179+
180+ let asset_nia = party. issue_asset_nia ( None ) ;
181+ let asset_cfa = party. issue_asset_cfa ( None , None ) ;
182+
183+ // one batch tx carrying transfers of both assets
184+ let receive_nia = rcv_party. blind_receive ( ) ;
185+ let receive_cfa = rcv_party. blind_receive ( ) ;
186+ let recipient_map = HashMap :: from ( [
187+ (
188+ asset_nia. asset_id . clone ( ) ,
189+ vec ! [ Recipient {
190+ assignment: Assignment :: Fungible ( amount) ,
191+ recipient_id: receive_nia. recipient_id. clone( ) ,
192+ witness_data: None ,
193+ transport_endpoints: TRANSPORT_ENDPOINTS . clone( ) ,
194+ } ] ,
195+ ) ,
196+ (
197+ asset_cfa. asset_id . clone ( ) ,
198+ vec ! [ Recipient {
199+ assignment: Assignment :: Fungible ( amount) ,
200+ recipient_id: receive_cfa. recipient_id. clone( ) ,
201+ witness_data: None ,
202+ transport_endpoints: TRANSPORT_ENDPOINTS . clone( ) ,
203+ } ] ,
204+ ) ,
205+ ] ) ;
206+ let txid = party. send_retry ( & recipient_map) ;
207+ assert ! ( !txid. is_empty( ) ) ;
208+
209+ // AnyOrNone + txid: the tx's transfers across all assets
210+ let by_txid = party. list_transfers_filtered ( AssetFilter :: AnyOrNone , Some ( & txid) ) ;
211+ assert_eq ! ( by_txid. len( ) , 2 ) ;
212+ assert ! ( by_txid. iter( ) . all( |t| t. txid == Some ( txid. clone( ) ) ) ) ;
213+
214+ // Id + txid: intersection, restricted to the given asset
215+ let nia_by_txid =
216+ party. list_transfers_filtered ( AssetFilter :: Id ( asset_nia. asset_id . clone ( ) ) , Some ( & txid) ) ;
217+ assert_eq ! ( nia_by_txid. len( ) , 1 ) ;
218+ let expected: Vec < i32 > = party
219+ . list_transfers ( Some ( & asset_nia. asset_id ) )
220+ . into_iter ( )
221+ . filter ( |t| t. txid == Some ( txid. clone ( ) ) )
222+ . map ( |t| t. idx )
223+ . collect ( ) ;
224+ assert_eq ! ( vec![ nia_by_txid[ 0 ] . idx] , expected) ;
225+
226+ // AnyOrNone + no txid: the whole history (2 issuances + 2 sends)
227+ let all = party. list_transfers_filtered ( AssetFilter :: AnyOrNone , None ) ;
228+ assert_eq ! ( all. len( ) , 4 ) ;
229+
230+ // None: receiver's pending blind receives not yet tied to an asset
231+ let pending = rcv_party. list_transfers_filtered ( AssetFilter :: None , None ) ;
232+ assert_eq ! ( pending. len( ) , 2 ) ;
233+
234+ // extra receive that nothing is sent to, stays asset-less
235+ let receive_extra = rcv_party. blind_receive ( ) ;
236+
237+ // settle the batch so the change is spendable again
238+ rcv_party. wait_for_refresh ( None ) ;
239+ // the refresh tied the 2 receives to their assets, only the extra one stays asset-less
240+ let all_rcv = rcv_party. list_transfers_filtered ( AssetFilter :: AnyOrNone , None ) ;
241+ assert_eq ! ( all_rcv. len( ) , 3 ) ;
242+ let pending = rcv_party. list_transfers_filtered ( AssetFilter :: None , None ) ;
243+ assert_eq ! ( pending. len( ) , 1 ) ;
244+ assert_eq ! ( pending[ 0 ] . recipient_id, Some ( receive_extra. recipient_id) ) ;
245+ // receiver side: the tx's transfers span 2 batch transfers sharing the same txid
246+ let rcv_by_txid = rcv_party. list_transfers_filtered ( AssetFilter :: AnyOrNone , Some ( & txid) ) ;
247+ assert_eq ! ( rcv_by_txid. len( ) , 2 ) ;
248+ party. wait_for_refresh ( None ) ;
249+ mine ( false ) ;
250+ rcv_party. wait_for_refresh ( None ) ;
251+ party. wait_for_refresh ( None ) ;
252+
253+ // Id + txid of a tx not carrying that asset: empty
254+ let receive_nia_2 = rcv_party. blind_receive ( ) ;
255+ let recipient_map = HashMap :: from ( [ (
256+ asset_nia. asset_id . clone ( ) ,
257+ vec ! [ Recipient {
258+ assignment: Assignment :: Fungible ( amount) ,
259+ recipient_id: receive_nia_2. recipient_id. clone( ) ,
260+ witness_data: None ,
261+ transport_endpoints: TRANSPORT_ENDPOINTS . clone( ) ,
262+ } ] ,
263+ ) ] ) ;
264+ let txid_2 = party. send_retry ( & recipient_map) ;
265+ assert ! (
266+ party
267+ . list_transfers_filtered( AssetFilter :: Id ( asset_cfa. asset_id. clone( ) ) , Some ( & txid_2) )
268+ . is_empty( )
269+ ) ;
270+
271+ // unknown txid: empty
272+ assert ! (
273+ party
274+ . list_transfers_filtered( AssetFilter :: AnyOrNone , Some ( FAKE_TXID ) )
275+ . is_empty( )
276+ ) ;
277+ }
278+
169279#[ test]
170280#[ parallel]
171281fn fail ( ) {
@@ -174,4 +284,9 @@ fn fail() {
174284 // asset not found
175285 let result = party. list_transfers_result ( Some ( "rgb1inexistent" ) ) ;
176286 assert ! ( matches!( result, Err ( Error :: AssetNotFound { asset_id: _ } ) ) ) ;
287+
288+ // asset not found also when a txid is given
289+ let result = party
290+ . list_transfers_filtered_result ( AssetFilter :: Id ( s ! ( "rgb1inexistent" ) ) , Some ( FAKE_TXID ) ) ;
291+ assert ! ( matches!( result, Err ( Error :: AssetNotFound { asset_id: _ } ) ) ) ;
177292}
0 commit comments