@@ -2,6 +2,9 @@ use crate::backend_task::BackendTaskSuccessResult;
22use crate :: context:: AppContext ;
33use crate :: model:: proof_log_item:: { ProofLogItem , RequestType } ;
44use crate :: model:: qualified_identity:: QualifiedIdentity ;
5+ use dash_sdk:: dpp:: ProtocolError ;
6+ use dash_sdk:: dpp:: consensus:: ConsensusError ;
7+ use dash_sdk:: dpp:: consensus:: state:: state_error:: StateError ;
58use dash_sdk:: dpp:: data_contract:: accessors:: v1:: DataContractV1Getters ;
69use dash_sdk:: dpp:: data_contract:: associated_token:: token_distribution_key:: TokenDistributionType ;
710use dash_sdk:: dpp:: document:: DocumentV0Getters ;
@@ -14,8 +17,14 @@ use dash_sdk::{Error, Sdk};
1417use std:: sync:: Arc ;
1518
1619impl AppContext {
20+ /// Claim all pending token claims matching the provided parameters.
21+ ///
22+ /// This method iterates until all tokens are claimed or no more claims are available.
23+ ///
24+ /// If no tokens are available to claim, it returns `TokensClaimed(0)`
25+ /// (in contrary to the [AppContext::claim_token()] method which returns error).
1726 #[ allow( clippy:: too_many_arguments) ]
18- pub async fn claim_tokens (
27+ pub async fn claim_all_tokens (
1928 & self ,
2029 data_contract : Arc < DataContract > ,
2130 token_position : u16 ,
@@ -25,6 +34,71 @@ impl AppContext {
2534 public_note : Option < String > ,
2635 sdk : & Sdk ,
2736 ) -> Result < BackendTaskSuccessResult , String > {
37+ let mut total_claimed = 0 ;
38+ loop {
39+ let result = self
40+ . claim_token (
41+ data_contract. clone ( ) ,
42+ token_position,
43+ actor_identity,
44+ distribution_type,
45+ signing_key. clone ( ) ,
46+ public_note. clone ( ) ,
47+ sdk,
48+ )
49+ . await ;
50+
51+ match result {
52+ Ok ( BackendTaskSuccessResult :: TokensClaimed ( 0 ) ) => {
53+ // If no tokens were claimed, we can exit the loop
54+ break ;
55+ }
56+ Ok ( BackendTaskSuccessResult :: TokensClaimed ( amount) ) => {
57+ total_claimed += amount;
58+ // Continue to check for more tokens to claim
59+ }
60+ Err ( dash_sdk:: Error :: Protocol ( ProtocolError :: ConsensusError ( ce) ) )
61+ if matches ! (
62+ * ce,
63+ ConsensusError :: StateError ( StateError :: InvalidTokenClaimNoCurrentRewards (
64+ _
65+ ) ) ,
66+ ) =>
67+ {
68+ // No more rewards available, exit the loop
69+ break ;
70+ }
71+ // ConsensusError::StateError(StateError::InvalidTokenClaimNoCurrentRewards(as_refected)))) if as_expected,
72+
73+ // any other result we propagate
74+ Ok ( x) => return Ok ( x) ,
75+ Err ( e) => {
76+ return Err ( format ! (
77+ "Error claiming tokens: {}; claimed so far: {}" ,
78+ e, total_claimed
79+ ) ) ;
80+ }
81+ }
82+ }
83+
84+ // Return the total claimed amount.
85+ Ok ( BackendTaskSuccessResult :: TokensClaimed ( total_claimed) )
86+ }
87+
88+ /// Execute single token claim.
89+ ///
90+ /// This method will return error if no tokens were available to claim.
91+ #[ allow( clippy:: too_many_arguments) ]
92+ pub async fn claim_token (
93+ & self ,
94+ data_contract : Arc < DataContract > ,
95+ token_position : u16 ,
96+ actor_identity : & QualifiedIdentity ,
97+ distribution_type : TokenDistributionType ,
98+ signing_key : IdentityPublicKey ,
99+ public_note : Option < String > ,
100+ sdk : & Sdk ,
101+ ) -> Result < BackendTaskSuccessResult , dash_sdk:: Error > {
28102 // Build
29103 let mut builder = TokenClaimTransitionBuilder :: new (
30104 data_contract. clone ( ) ,
@@ -45,7 +119,7 @@ impl AppContext {
45119 let result = sdk
46120 . token_claim ( builder, & signing_key, actor_identity)
47121 . await
48- . map_err ( |e| match e {
122+ . inspect_err ( |e|{ match e {
49123 Error :: DriveProofError ( proof_error, proof_bytes, block_info) => {
50124 self . db
51125 . insert_proof_log_item ( ProofLogItem {
@@ -54,19 +128,18 @@ impl AppContext {
54128 verification_path_query_bytes : vec ! [ ] ,
55129 height : block_info. height ,
56130 time_ms : block_info. time_ms ,
57- proof_bytes,
131+ proof_bytes : proof_bytes . clone ( ) ,
58132 error : Some ( proof_error. to_string ( ) ) ,
59133 } )
60134 . ok ( ) ;
61- format ! (
62- "Error broadcasting ClaimTokens transition: {}, proof error logged" ,
63- proof_error
64- )
135+ tracing:: error!( error=?proof_error, "Error broadcasting ClaimTokens transition, proof error logged" ) ;
65136 }
66- e => format ! ( "Error broadcasting ClaimTokens transition: {}" , e) ,
67- } ) ?;
137+ e => tracing:: error!( error=?e, "Error broadcasting ClaimTokens transition" ) ,
138+ } ;
139+ } ) ?;
68140
69141 // Using the result, update the balance of the claimer identity
142+ let mut claimed_amount = 0 ;
70143 if let Some ( token_id) = data_contract. token_id ( token_position) {
71144 match result {
72145 // Standard claim result - extract claimer and amount from document
@@ -77,15 +150,15 @@ impl AppContext {
77150 if let ( Value :: Identifier ( claimer_bytes) , Value :: U64 ( amount) ) =
78151 ( claimer_value, amount_value)
79152 {
153+ claimed_amount = * amount;
80154 if let Ok ( claimer_id) = Identifier :: from_bytes ( claimer_bytes) {
81155 if let Err ( e) = self . insert_token_identity_balance (
82156 & token_id,
83157 & claimer_id,
84158 * amount,
85159 ) {
86- eprintln ! (
87- "Failed to update token balance from claim document: {}" ,
88- e
160+ tracing:: error!( error=?e, identity=?claimer_id, token_id=?token_id,
161+ "Failed to update token balance from claim document" ,
89162 ) ;
90163 }
91164 }
@@ -101,15 +174,15 @@ impl AppContext {
101174 if let ( Value :: Identifier ( claimer_bytes) , Value :: U64 ( amount) ) =
102175 ( claimer_value, amount_value)
103176 {
177+ claimed_amount = * amount;
104178 if let Ok ( claimer_id) = Identifier :: from_bytes ( claimer_bytes) {
105179 if let Err ( e) = self . insert_token_identity_balance (
106180 & token_id,
107181 & claimer_id,
108182 * amount,
109183 ) {
110- eprintln ! (
111- "Failed to update token balance from group action document: {}" ,
112- e
184+ tracing:: error!( error=?e, identity=?claimer_id, token_id=?token_id,
185+ "Failed to update token balance from group action document" ,
113186 ) ;
114187 }
115188 }
@@ -120,6 +193,6 @@ impl AppContext {
120193 }
121194
122195 // Return success
123- Ok ( BackendTaskSuccessResult :: Message ( "ClaimTokens" . to_string ( ) ) )
196+ Ok ( BackendTaskSuccessResult :: TokensClaimed ( claimed_amount ) )
124197 }
125198}
0 commit comments