1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
use schemars::JsonSchema;
use serde::{Deserialize, Serialize};
use cosmwasm_std::{BlockInfo, CanonicalAddr, Deps, StdResult, Storage, Uint128};
use cw20::Expiration;
use cw_storage_plus::Map;
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)]
pub struct ClaimsResponse {
pub claims: Vec<Claim>,
}
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)]
pub struct Claim {
pub amount: Uint128,
pub release_at: Expiration,
}
pub const CLAIM: Map<&[u8], Vec<Claim>> = Map::new("claims");
pub fn create_claim(
storage: &mut dyn Storage,
addr: CanonicalAddr,
amount: Uint128,
release_at: Expiration,
) -> StdResult<()> {
CLAIM.update(storage, addr.as_slice(), |old| -> StdResult<_> {
let mut claims = old.unwrap_or_default();
claims.push(Claim { amount, release_at });
Ok(claims)
})?;
Ok(())
}
pub fn claim_tokens(
storage: &mut dyn Storage,
addr: CanonicalAddr,
block: &BlockInfo,
cap: Option<Uint128>,
) -> StdResult<Uint128> {
let mut to_send = Uint128(0);
CLAIM.update(storage, addr.as_slice(), |claim| -> StdResult<_> {
let (_send, waiting): (Vec<_>, _) =
claim.unwrap_or_default().iter().cloned().partition(|c| {
if c.release_at.is_expired(block) {
if let Some(limit) = cap {
if to_send + c.amount > limit {
return false;
}
}
to_send += c.amount;
true
} else {
false
}
});
Ok(waiting)
})?;
Ok(to_send)
}
pub fn query_claims(deps: Deps, address: String) -> StdResult<ClaimsResponse> {
let address_raw = deps.api.addr_canonicalize(address.as_str())?;
let claims = CLAIM
.may_load(deps.storage, address_raw.as_slice())?
.unwrap_or_default();
Ok(ClaimsResponse { claims })
}