@@ -3,13 +3,13 @@ use std::{cmp, cmp::min};
3
3
use ed25519_dalek:: { Signature , VerifyingKey , PUBLIC_KEY_LENGTH , SIGNATURE_LENGTH } ;
4
4
use near_sdk:: {
5
5
env,
6
- env:: { panic_str, sha256} ,
6
+ env:: { block_timestamp_ms , panic_str, sha256} ,
7
7
json_types:: { Base64VecU8 , U128 , U64 } ,
8
8
near, require, AccountId ,
9
9
} ;
10
10
use sweat_jar_model:: {
11
11
jar:: { JarId , JarView } ,
12
- ProductId , TokenAmount , MS_IN_YEAR ,
12
+ AccountScore , ProductId , TokenAmount , MS_IN_DAY , MS_IN_YEAR ,
13
13
} ;
14
14
15
15
use crate :: {
@@ -50,8 +50,8 @@ impl JarLastVersion {
50
50
self . is_pending_withdraw = false ;
51
51
}
52
52
53
- pub ( crate ) fn apply_penalty ( & mut self , product : & Product , is_applied : bool , now : Timestamp ) {
54
- let current_interest = self . get_interest ( 0 , product, now) . 0 ;
53
+ pub ( crate ) fn apply_penalty ( & mut self , score : & AccountScore , product : & Product , is_applied : bool , now : Timestamp ) {
54
+ let current_interest = self . get_interest ( score , product, now) . 0 ;
55
55
56
56
self . cache = Some ( JarCache {
57
57
updated_at : now,
@@ -60,8 +60,14 @@ impl JarLastVersion {
60
60
self . is_penalty_applied = is_applied;
61
61
}
62
62
63
- pub ( crate ) fn top_up ( & mut self , amount : TokenAmount , product : & Product , now : Timestamp ) -> & mut Self {
64
- let current_interest = self . get_interest ( 0 , product, now) . 0 ;
63
+ pub ( crate ) fn top_up (
64
+ & mut self ,
65
+ score : & AccountScore ,
66
+ amount : TokenAmount ,
67
+ product : & Product ,
68
+ now : Timestamp ,
69
+ ) -> & mut Self {
70
+ let current_interest = self . get_interest ( score, product, now) . 0 ;
65
71
66
72
self . principal += amount;
67
73
self . cache = Some ( JarCache {
@@ -75,18 +81,32 @@ impl JarLastVersion {
75
81
& mut self ,
76
82
available_yield : TokenAmount ,
77
83
claimed_amount : TokenAmount ,
84
+ product : & Product ,
85
+ score : & AccountScore ,
78
86
now : Timestamp ,
79
87
) -> & mut Self {
80
88
self . claimed_balance += claimed_amount;
89
+
90
+ let updated_at = if product. is_score_product ( ) {
91
+ let block_timestamp = block_timestamp_ms ( ) ;
92
+ if block_timestamp - score. last_update >= MS_IN_DAY {
93
+ score. last_update + MS_IN_DAY
94
+ } else {
95
+ now
96
+ }
97
+ } else {
98
+ now
99
+ } ;
100
+
81
101
self . cache = Some ( JarCache {
82
- updated_at : now ,
102
+ updated_at,
83
103
interest : available_yield - claimed_amount,
84
104
} ) ;
85
105
self
86
106
}
87
107
88
- pub ( crate ) fn should_be_closed ( & self , product : & Product , now : Timestamp ) -> bool {
89
- !product. is_flexible ( ) && self . principal == 0 && self . get_interest ( 0 , product, now) . 0 == 0
108
+ pub ( crate ) fn should_be_closed ( & self , score : & AccountScore , product : & Product , now : Timestamp ) -> bool {
109
+ !product. is_flexible ( ) && self . principal == 0 && self . get_interest ( score , product, now) . 0 == 0
90
110
}
91
111
92
112
/// Indicates whether a user can withdraw tokens from the jar at the moment or not.
@@ -138,10 +158,17 @@ impl JarLastVersion {
138
158
)
139
159
}
140
160
141
- pub ( crate ) fn get_interest ( & self , score : u32 , product : & Product , now : Timestamp ) -> ( TokenAmount , u64 ) {
142
- let score = min ( product. score_cap , score) ;
143
- let apy = self . get_apy ( product) + Self :: get_score_apy ( score, product) ;
144
- self . get_interest_with_apy ( apy, product, now)
161
+ pub ( crate ) fn get_interest (
162
+ & self ,
163
+ account_score : & AccountScore ,
164
+ product : & Product ,
165
+ now : Timestamp ,
166
+ ) -> ( TokenAmount , u64 ) {
167
+ let ( score_apy, adjusted_timestamp) = Self :: get_score_apy ( account_score, product) ;
168
+
169
+ let apy = self . get_apy ( product) + score_apy;
170
+
171
+ self . get_interest_with_apy ( apy, product, adjusted_timestamp. unwrap_or ( now) )
145
172
}
146
173
147
174
pub ( crate ) fn get_apy ( & self , product : & Product ) -> UDecimal {
@@ -157,12 +184,24 @@ impl JarLastVersion {
157
184
}
158
185
}
159
186
160
- pub ( crate ) fn get_score_apy ( score : u32 , product : & Product ) -> UDecimal {
187
+ pub ( crate ) fn get_score_apy ( account_score : & AccountScore , product : & Product ) -> ( UDecimal , Option < Timestamp > ) {
161
188
if product. score_cap == 0 {
162
- return UDecimal :: default ( ) ;
189
+ return ( UDecimal :: default ( ) , None ) ;
163
190
}
164
191
165
- UDecimal :: new ( score. into ( ) , 5 )
192
+ let now = block_timestamp_ms ( ) ;
193
+
194
+ let score = min ( product. score_cap , account_score. score ) ;
195
+
196
+ let apy = UDecimal :: new ( score. into ( ) , 5 ) ;
197
+
198
+ // A 24 hours has passed since last steps update.
199
+ // We need to wait for the next update form the server before updating score interest
200
+ if now - account_score. last_update >= MS_IN_DAY {
201
+ ( apy, Some ( account_score. last_update + MS_IN_DAY ) )
202
+ } else {
203
+ ( apy, None )
204
+ }
166
205
}
167
206
168
207
fn get_interest_until_date ( & self , product : & Product , now : Timestamp ) -> Timestamp {
@@ -221,9 +260,11 @@ impl Contract {
221
260
222
261
let now = env:: block_timestamp_ms ( ) ;
223
262
263
+ let score = self . account_score . get ( account) . copied ( ) . unwrap_or_default ( ) ;
264
+
224
265
let principal = self
225
266
. get_jar_mut_internal ( account, jar_id)
226
- . top_up ( amount. 0 , & product, now)
267
+ . top_up ( & score , amount. 0 , & product, now)
227
268
. principal ;
228
269
229
270
emit ( EventKind :: TopUp ( TopUpData { id : jar_id, amount } ) ) ;
0 commit comments