Skip to content

Commit 29afd79

Browse files
committed
feat: execute all available claims
1 parent c7ba5f8 commit 29afd79

4 files changed

Lines changed: 111 additions & 18 deletions

File tree

src/backend_task/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,7 @@ pub enum BackendTaskSuccessResult {
9999
},
100100
UpdatedThemePreference(crate::ui::theme::ThemeMode),
101101
PlatformInfo(PlatformInfoTaskResult),
102+
TokensClaimed(TokenAmount),
102103
}
103104

104105
impl BackendTaskSuccessResult {}

src/backend_task/tokens/claim_tokens.rs

Lines changed: 89 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,9 @@ use crate::backend_task::BackendTaskSuccessResult;
22
use crate::context::AppContext;
33
use crate::model::proof_log_item::{ProofLogItem, RequestType};
44
use 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;
58
use dash_sdk::dpp::data_contract::accessors::v1::DataContractV1Getters;
69
use dash_sdk::dpp::data_contract::associated_token::token_distribution_key::TokenDistributionType;
710
use dash_sdk::dpp::document::DocumentV0Getters;
@@ -14,8 +17,14 @@ use dash_sdk::{Error, Sdk};
1417
use std::sync::Arc;
1518

1619
impl 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
}

src/backend_task/tokens/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -488,7 +488,7 @@ impl AppContext {
488488
signing_key,
489489
public_note,
490490
} => self
491-
.claim_tokens(
491+
.claim_all_tokens(
492492
data_contract.clone(),
493493
*token_position,
494494
actor_identity,

src/ui/tokens/claim_tokens_screen.rs

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ use dash_sdk::dpp::identity::{KeyType, Purpose, SecurityLevel};
2020
use eframe::egui::{self, Color32, Context, Ui};
2121
use egui::RichText;
2222
use crate::app::{AppAction, BackendTasksExecutionMode};
23-
use crate::backend_task::BackendTask;
23+
use crate::backend_task::{BackendTask, BackendTaskSuccessResult};
2424
use crate::backend_task::tokens::TokenTask;
2525
use crate::context::AppContext;
2626
use crate::model::qualified_contract::QualifiedContract;
@@ -248,6 +248,25 @@ impl ClaimTokensScreen {
248248
}
249249

250250
impl ScreenLike for ClaimTokensScreen {
251+
fn display_task_result(
252+
&mut self,
253+
backend_task_success_result: crate::backend_task::BackendTaskSuccessResult,
254+
) {
255+
if let BackendTaskSuccessResult::TokensClaimed(amount) = backend_task_success_result {
256+
if amount > 0 {
257+
self.display_message(
258+
&format!("Claimed {} tokens successfully!", amount),
259+
MessageType::Success,
260+
);
261+
self.status = ClaimTokensStatus::Complete;
262+
} else {
263+
// self.display_message("No tokens available to claim.", MessageType::Error);
264+
self.status =
265+
ClaimTokensStatus::ErrorMessage("No tokens available to claim.".to_string());
266+
}
267+
}
268+
}
269+
251270
fn display_message(&mut self, message: &str, message_type: MessageType) {
252271
match message_type {
253272
MessageType::Success => {

0 commit comments

Comments
 (0)