| 
					
				 | 
			
			
				@@ -11,7 +11,9 @@ pub enum PrimaryFilter { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     /// By revision ID 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     Revision(Vec<RevId>), 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     /// By accounts 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    Account(Vec<AccountId>), 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    Spends(Vec<AccountId>), 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    /// By accounts 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    Receives(Vec<AccountId>), 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     /// By transaction type 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     Type(Vec<Type>), 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     /// By transaction status 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -34,7 +36,9 @@ pub enum FilterableValue { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     /// Revision ID 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     Revision(RevId), 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     /// Account 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    Account(AccountId), 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    Spends(AccountId), 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    /// Account 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    Receives(AccountId), 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     /// Status 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     Status(Status), 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     /// Transaction type 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -53,9 +57,13 @@ impl From<PrimaryFilter> for Vec<FilterableValue> { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                 .into_iter() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                 .map(FilterableValue::Revision) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                 .collect(), 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            PrimaryFilter::Account(accounts) => { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                accounts.into_iter().map(FilterableValue::Account).collect() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            PrimaryFilter::Spends(accounts) => { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                accounts.into_iter().map(FilterableValue::Spends).collect() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            PrimaryFilter::Receives(accounts) => accounts 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                .into_iter() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                .map(FilterableValue::Receives) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                .collect(), 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             PrimaryFilter::Status(statuses) => { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                 statuses.into_iter().map(FilterableValue::Status).collect() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             } 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -78,9 +86,12 @@ pub struct Filter { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     /// List of revisions to query 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     #[serde(skip_serializing_if = "Vec::is_empty", default)] 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     pub revisions: Vec<RevId>, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    /// List of accounts to query their transactions 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    /// List of accounts spending funds to query their transactions 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     #[serde(skip_serializing_if = "Vec::is_empty", default)] 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    pub accounts: Vec<AccountId>, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    pub spends: Vec<AccountId>, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    /// List of accounts receiving funds to query their transactions 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    #[serde(skip_serializing_if = "Vec::is_empty", default)] 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    pub receives: Vec<AccountId>, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     /// List of transaction types-kind 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     #[serde(rename = "type", skip_serializing_if = "Vec::is_empty", default)] 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     pub typ: Vec<Type>, 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -120,8 +131,10 @@ impl Filter { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             PrimaryFilter::Revision(std::mem::take(&mut self.revisions)) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         } else if !self.ids.is_empty() { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             PrimaryFilter::TxId(std::mem::take(&mut self.ids)) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        } else if !self.accounts.is_empty() { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            PrimaryFilter::Account(std::mem::take(&mut self.accounts)) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        } else if !self.spends.is_empty() { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            PrimaryFilter::Spends(std::mem::take(&mut self.spends)) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        } else if !self.receives.is_empty() { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            PrimaryFilter::Receives(std::mem::take(&mut self.receives)) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         } else if !self.typ.is_empty() { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             PrimaryFilter::Type(std::mem::take(&mut self.typ)) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         } else if !self.tags.is_empty() { 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -139,7 +152,8 @@ impl Filter { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     pub fn prepare(mut self) -> Self { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         self.ids.sort(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         self.revisions.sort(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        self.accounts.sort(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        self.spends.sort(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        self.receives.sort(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         self.typ.sort(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         self.status.sort(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         self.tags.sort(); 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -149,7 +163,7 @@ impl Filter { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     /// Check if the base transaction and the revision matches the current cursor filter 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     /// 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     /// Before this function is called, the filter needs to be prepareted with `prepare` function 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    pub fn matches(&self, base: &BaseTx, revision: &Revision) -> bool { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    pub fn matches(&self, base: &BaseTx, revision: &Revision, revision_id: &RevId) -> bool { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         let since = self 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             .since 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             .map(|since| since <= base.created_at) 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -172,12 +186,7 @@ impl Filter { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             return false; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        if !self.revisions.is_empty() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            && self 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                .revisions 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                .binary_search(&revision.rev_id().expect("vv")) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                .is_err() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        if !self.revisions.is_empty() && self.revisions.binary_search(&revision_id).is_err() { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             return false; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -185,6 +194,34 @@ impl Filter { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             return false; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        let accounts = base.accounts(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        if !self.spends.is_empty() { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            let mut found = false; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            for account in accounts.spends.iter() { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                if self.spends.binary_search(account).is_ok() { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    found = true; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    break; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            if !found { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                return false; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        if !self.receives.is_empty() { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            let mut found = false; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            for account in accounts.receives.iter() { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                if self.receives.binary_search(account).is_ok() { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    found = true; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    break; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            if !found { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                return false; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         if !self.tags.is_empty() { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             let mut found = false; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             for tag in revision.tags.iter() { 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -207,9 +244,15 @@ impl Filter { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         self 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    /// Adds a given tag to the filter 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    pub fn account(mut self, account: AccountId) -> Self { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        self.accounts.push(account); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    /// Adds a spending account to the filter 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    pub fn spends(mut self, account: AccountId) -> Self { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        self.spends.push(account); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        self 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    /// Adds a receiving account to the filter 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    pub fn receives(mut self, account: AccountId) -> Self { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        self.receives.push(account); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         self 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -256,7 +299,7 @@ impl From<RevId> for Filter { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 impl From<AccountId> for Filter { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     fn from(value: AccountId) -> Self { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         Filter { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            accounts: vec![value], 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            spends: vec![value], 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             ..Default::default() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     } 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -329,8 +372,16 @@ mod test { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             ..Default::default() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         .prepare(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        assert!(!filter_until.matches(¤t.transaction, ¤t.revision)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        assert!(filter_since.matches(¤t.transaction, ¤t.revision)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        assert!(!filter_until.matches( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            ¤t.transaction, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            ¤t.revision, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            ¤t.revision_id 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        )); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        assert!(filter_since.matches( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            ¤t.transaction, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            ¤t.revision, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            ¤t.revision_id 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        )); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     #[test] 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -356,7 +407,15 @@ mod test { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             ..Default::default() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         .prepare(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        assert!(!filter_foo.matches(¤t.transaction, ¤t.revision)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        assert!(filter_settled.matches(¤t.transaction, ¤t.revision)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        assert!(!filter_foo.matches( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            ¤t.transaction, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            ¤t.revision, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            ¤t.revision_id 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        )); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        assert!(filter_settled.matches( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            ¤t.transaction, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            ¤t.revision, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            ¤t.revision_id 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        )); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 } 
			 |