Skip to content

Commit 2e09106

Browse files
fix build
1 parent e186ac7 commit 2e09106

File tree

20 files changed

+206
-221
lines changed

20 files changed

+206
-221
lines changed

contract/src/assert.rs

-4
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,3 @@ use crate::jar::model::{Jar, JarV2};
66
pub(crate) fn assert_not_locked(jar: &JarV2) {
77
require!(!jar.is_pending_withdraw, "Another operation on this Jar is in progress");
88
}
9-
10-
pub(crate) fn assert_sufficient_balance(jar: &Jar, amount: TokenAmount) {
11-
require!(jar.principal >= amount, "Insufficient balance");
12-
}

contract/src/claim/api.rs

+14-6
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
use std::collections::HashMap;
22

33
use near_sdk::{env, ext_contract, json_types::U128, near_bindgen, AccountId, PromiseOrValue};
4-
use sweat_jar_model::{api::ClaimApi, claimed_amount_view::ClaimedAmountView, jar::AggregatedTokenAmountView};
4+
use sweat_jar_model::{
5+
api::ClaimApi, claimed_amount_view::ClaimedAmountView, jar::AggregatedTokenAmountView, ProductId, TokenAmount,
6+
};
57

68
use crate::{
79
event::{emit, EventKind},
@@ -46,12 +48,14 @@ impl Contract {
4648
let now = env::block_timestamp_ms();
4749

4850
let mut rollback_jars = HashMap::new();
49-
for (product_id, jar) in account.jars.iter_mut() {
51+
let mut interest_per_jar: HashMap<ProductId, (TokenAmount, u64)> = HashMap::new();
52+
53+
for (product_id, jar) in account.jars.iter() {
5054
if jar.is_pending_withdraw {
5155
continue;
5256
}
5357

54-
rollback_jars.insert(product_id, jar.to_rollback());
58+
rollback_jars.insert(product_id.clone(), jar.to_rollback());
5559

5660
let product = self.products.get(product_id).expect("Product is not found");
5761
let (interest, remainder) = product.terms.get_interest(account, jar);
@@ -60,14 +64,18 @@ impl Contract {
6064
continue;
6165
}
6266

63-
jar.claim(interest, remainder, now).lock();
64-
67+
interest_per_jar.insert(product_id.clone(), (interest, remainder));
6568
accumulator.add(product_id, interest);
6669
}
6770

71+
for (product_id, (interest, remainder)) in interest_per_jar {
72+
let jar = account.get_jar_mut(&product_id);
73+
jar.claim(interest, remainder, now).lock();
74+
}
75+
6876
let mut account_rollback = AccountV2Companion::default();
6977
account_rollback.score = Some(account.score);
70-
account_rollback.jars = Some(*rollback_jars);
78+
account_rollback.jars = Some(rollback_jars);
7179

7280
account.score.claim_score();
7381

contract/src/ft_receiver.rs

+53-53
Original file line numberDiff line numberDiff line change
@@ -1,56 +1,56 @@
1-
// use near_contract_standards::fungible_token::receiver::FungibleTokenReceiver;
2-
// use near_sdk::{json_types::U128, near, require, serde_json, AccountId, PromiseOrValue};
3-
// use sweat_jar_model::jar::CeFiJar;
4-
//
5-
// use crate::{jar::model::JarTicket, near_bindgen, Base64VecU8, Contract, ContractExt};
6-
//
7-
// /// The `FtMessage` enum represents various commands for actions available via transferring tokens to an account
8-
// /// where this contract is deployed, using the payload in `ft_transfer_call`.
9-
// #[near(serializers=[json])]
10-
// #[serde(tag = "type", content = "data", rename_all = "snake_case")]
11-
// pub enum FtMessage {
12-
// /// Represents a request to create a new jar for a corresponding product.
13-
// Stake(StakeMessage),
14-
//
15-
// /// Represents a request to create `DeFi` Jars from provided `CeFi` Jars.
16-
// Migrate(Vec<CeFiJar>),
17-
// }
18-
//
19-
// /// The `StakeMessage` struct represents a request to create a new jar for a corresponding product.
20-
// #[near(serializers=[json])]
21-
// pub struct StakeMessage {
22-
// /// Data of the `JarTicket` required for validating the request and specifying the product.
23-
// ticket: JarTicket,
24-
//
25-
// /// An optional ed25519 signature used to verify the authenticity of the request.
26-
// signature: Option<Base64VecU8>,
27-
//
28-
// /// An optional account ID representing the intended owner of the created jar.
29-
// receiver_id: Option<AccountId>,
30-
// }
31-
//
32-
// #[near_bindgen]
33-
// impl FungibleTokenReceiver for Contract {
34-
// fn ft_on_transfer(&mut self, sender_id: AccountId, amount: U128, msg: String) -> PromiseOrValue<U128> {
35-
// self.assert_from_ft_contract();
36-
//
37-
// let ft_message: FtMessage = serde_json::from_str(&msg).expect("Unable to deserialize msg");
38-
//
39-
// match ft_message {
40-
// FtMessage::Stake(message) => {
41-
// let receiver_id = message.receiver_id.unwrap_or(sender_id);
42-
// self.deposit(receiver_id, message.ticket, amount, message.signature);
43-
// }
44-
// FtMessage::Migrate(jars) => {
45-
// require!(sender_id == self.manager, "Migration can be performed only by admin");
46-
//
47-
// self.migrate_jars(jars, amount);
48-
// }
49-
// }
50-
//
51-
// PromiseOrValue::Value(0.into())
52-
// }
53-
// }
1+
use near_contract_standards::fungible_token::receiver::FungibleTokenReceiver;
2+
use near_sdk::{json_types::U128, near, require, serde_json, AccountId, PromiseOrValue};
3+
use sweat_jar_model::jar::CeFiJar;
4+
5+
use crate::{jar::model::JarTicket, near_bindgen, Base64VecU8, Contract, ContractExt};
6+
7+
/// The `FtMessage` enum represents various commands for actions available via transferring tokens to an account
8+
/// where this contract is deployed, using the payload in `ft_transfer_call`.
9+
#[near(serializers=[json])]
10+
#[serde(tag = "type", content = "data", rename_all = "snake_case")]
11+
pub enum FtMessage {
12+
/// Represents a request to create a new jar for a corresponding product.
13+
Stake(StakeMessage),
14+
15+
/// Represents a request to create `DeFi` Jars from provided `CeFi` Jars.
16+
Migrate(Vec<CeFiJar>),
17+
}
18+
19+
/// The `StakeMessage` struct represents a request to create a new jar for a corresponding product.
20+
#[near(serializers=[json])]
21+
pub struct StakeMessage {
22+
/// Data of the `JarTicket` required for validating the request and specifying the product.
23+
ticket: JarTicket,
24+
25+
/// An optional ed25519 signature used to verify the authenticity of the request.
26+
signature: Option<Base64VecU8>,
27+
28+
/// An optional account ID representing the intended owner of the created jar.
29+
receiver_id: Option<AccountId>,
30+
}
31+
32+
#[near_bindgen]
33+
impl FungibleTokenReceiver for Contract {
34+
fn ft_on_transfer(&mut self, sender_id: AccountId, amount: U128, msg: String) -> PromiseOrValue<U128> {
35+
self.assert_from_ft_contract();
36+
37+
let ft_message: FtMessage = serde_json::from_str(&msg).expect("Unable to deserialize msg");
38+
39+
match ft_message {
40+
FtMessage::Stake(message) => {
41+
let receiver_id = message.receiver_id.unwrap_or(sender_id);
42+
self.deposit(receiver_id, message.ticket, amount, message.signature);
43+
}
44+
FtMessage::Migrate(jars) => {
45+
require!(sender_id == self.manager, "Migration can be performed only by admin");
46+
47+
self.migrate_jars(jars, amount);
48+
}
49+
}
50+
51+
PromiseOrValue::Value(0.into())
52+
}
53+
}
5454
//
5555
// #[cfg(test)]
5656
// mod tests {

contract/src/internal.rs

+10-5
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,10 @@ use sweat_jar_model::jar::JarId;
55

66
use crate::{
77
env,
8-
jar::{account::versioned::Account, model::Jar},
8+
jar::{
9+
account::versioned::Account,
10+
model::{AccountJarsLegacy, Jar},
11+
},
912
AccountId, Contract,
1013
};
1114

@@ -46,16 +49,18 @@ impl Contract {
4649
self.accounts.get(account_id).map(|record| record.jars.clone())
4750
}
4851

49-
pub(crate) fn get_account_legacy(&self, account_id: &AccountId) -> Option<&Account> {
52+
pub(crate) fn get_account_legacy(&self, account_id: &AccountId) -> Option<Account> {
5053
if let Some(record) = self.account_jars_v1.get(account_id) {
51-
return Account::from(record).into();
54+
let account: Account = record.clone().into();
55+
return Some(account);
5256
}
5357

5458
if let Some(record) = self.account_jars_non_versioned.get(account_id) {
55-
return Account::from(record).into();
59+
let account: Account = record.clone().into();
60+
return Some(account);
5661
}
5762

58-
self.accounts.get(account_id)
63+
self.accounts.get(account_id).cloned()
5964
}
6065

6166
pub(crate) fn add_new_jar(&mut self, account_id: &AccountId, jar: Jar) {

contract/src/jar/account/v1.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ use crate::{
1010
};
1111

1212
#[near]
13-
#[derive(Default, Debug, PartialEq)]
13+
#[derive(Default, Debug, PartialEq, Clone)]
1414
pub struct AccountV1 {
1515
/// The last jar ID. Is used as nonce in `get_ticket_hash` method.
1616
pub last_id: JarId,

contract/src/jar/account/versioned.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ use crate::{
1616

1717
pub type Account = AccountVersioned;
1818

19-
#[derive(BorshSerialize, Debug, PartialEq)]
19+
#[derive(BorshSerialize, Debug, PartialEq, Clone)]
2020
#[borsh(crate = "near_sdk::borsh")]
2121
pub enum AccountVersioned {
2222
V1(AccountV1),

contract/src/jar/api.rs

+40-34
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use std::collections::HashMap;
1+
use std::{collections::HashMap, ops::Deref};
22

33
use near_sdk::{env, json_types::U128, near_bindgen, require, AccountId};
44
use sweat_jar_model::{
@@ -13,7 +13,7 @@ use crate::{
1313
model::Deposit,
1414
view::DetailedJarV2,
1515
},
16-
product::model::v2::ProductV2,
16+
product::model::v2::{InterestCalculator, ProductV2},
1717
Contract, ContractExt,
1818
};
1919

@@ -22,18 +22,43 @@ impl Contract {
2222
require!(product.is_enabled, "The product is disabled");
2323

2424
let account_id = env::predecessor_account_id();
25-
let account = self.get_account_mut(&account_id);
26-
let jar = account.get_jar_mut(&product.id);
27-
2825
let now = env::block_timestamp_ms();
26+
27+
let account = self.get_account(&account_id);
28+
let jar = account.get_jar(&product.id);
29+
2930
let (amount, partition_index) = jar.get_liquid_balance(&product.terms, now);
3031

3132
require!(amount > 0, "Nothing to restake");
3233

33-
self.update_jar_cache(account, &product.id);
34+
self.update_jar_cache(&account_id, &product.id);
35+
36+
let account = self.get_account_mut(&account_id);
37+
let jar = account.get_jar_mut(&product.id);
3438
jar.clean_up_deposits(partition_index);
3539
account.deposit(&product.id, amount);
3640
}
41+
42+
fn get_total_interest_for_account(&self, account: &AccountV2) -> AggregatedInterestView {
43+
let mut detailed_amounts = HashMap::<ProductId, U128>::new();
44+
let mut total_amount: TokenAmount = 0;
45+
46+
for (product_id, jar) in account.jars.iter() {
47+
let product = self.get_product(product_id);
48+
let interest = product.terms.get_interest(account, &jar).0;
49+
50+
detailed_amounts.insert(product_id.clone(), interest.into());
51+
total_amount += interest;
52+
}
53+
54+
AggregatedInterestView {
55+
amount: AggregatedTokenAmountView {
56+
detailed: detailed_amounts,
57+
total: U128(total_amount),
58+
},
59+
timestamp: env::block_timestamp_ms(),
60+
}
61+
}
3762
}
3863

3964
#[near_bindgen]
@@ -43,7 +68,11 @@ impl JarApi for Contract {
4368
return account
4469
.jars
4570
.iter()
46-
.flat_map(|(product_id, jar)| DetailedJarV2(product_id.clone(), jar.clone()).into())
71+
.flat_map(|(product_id, jar)| {
72+
let detailed_jar = &DetailedJarV2(product_id.clone(), jar.clone());
73+
let views: Vec<JarView> = detailed_jar.into();
74+
views
75+
})
4776
.collect();
4877
}
4978

@@ -54,14 +83,13 @@ impl JarApi for Contract {
5483
vec![]
5584
}
5685

57-
// TODO: add v2 support
5886
fn get_total_interest(&self, account_id: AccountId) -> AggregatedInterestView {
5987
if let Some(account) = self.try_get_account(&account_id) {
60-
return account.get_total_interest();
88+
return self.get_total_interest_for_account(account);
6189
}
6290

6391
if let Some(account) = self.get_account_legacy(&account_id) {
64-
return AccountV2::from(account).get_total_interest();
92+
return self.get_total_interest_for_account(&AccountV2::from(account.deref()));
6593
}
6694

6795
AggregatedInterestView::default()
@@ -85,6 +113,7 @@ impl JarApi for Contract {
85113
.jars
86114
.keys()
87115
.filter(|product_id| self.get_product(product_id).is_enabled)
116+
.cloned()
88117
.collect()
89118
});
90119
for product_id in product_ids.iter() {
@@ -105,29 +134,6 @@ impl JarApi for Contract {
105134
}
106135
}
107136

108-
impl AccountV2 {
109-
fn get_total_interest(&self) -> AggregatedInterestView {
110-
let mut detailed_amounts = HashMap::<JarIdView, U128>::new();
111-
let mut total_amount: TokenAmount = 0;
112-
113-
for (product_id, jar) in self.jars {
114-
let product = self.get_product(&product_id);
115-
let interest = product.terms.get_interest(self, &jar).0;
116-
117-
detailed_amounts.insert(product_id, interest.into());
118-
total_amount += interest;
119-
}
120-
121-
AggregatedInterestView {
122-
amount: AggregatedTokenAmountView {
123-
detailed: detailed_amounts,
124-
total: U128(total_amount),
125-
},
126-
timestamp: env::block_timestamp_ms(),
127-
};
128-
}
129-
}
130-
131137
impl From<&AccountV1> for AccountV2 {
132138
fn from(value: &AccountV1) -> Self {
133139
let mut account = AccountV2 {
@@ -137,7 +143,7 @@ impl From<&AccountV1> for AccountV2 {
137143
is_penalty_applied: false,
138144
};
139145

140-
for jar in value.jars {
146+
for jar in value.jars.iter() {
141147
let deposit = Deposit::new(jar.created_at, jar.principal);
142148
account.push(&jar.product_id, deposit);
143149

contract/src/jar/model/common.rs

+1-16
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ use near_sdk::{
66
use sweat_jar_model::{jar::JarId, Timezone, TokenAmount};
77

88
use crate::{
9-
common::Timestamp, jar::model::Jar, product::model::v2::Terms, score::AccountScore, Contract, JarsStorage,
9+
common::Timestamp, jar::model::Jar, product::model::v2::Terms, Contract, JarsStorage,
1010
};
1111

1212
/// The `JarTicket` struct represents a request to create a deposit jar for a corresponding product.
@@ -69,21 +69,6 @@ impl Contract {
6969
account.deposit(product_id, amount);
7070
}
7171

72-
pub(crate) fn get_score(&self, account: &AccountId) -> Option<&AccountScore> {
73-
self.accounts.get(account).and_then(|a| a.score())
74-
}
75-
76-
pub(crate) fn get_score_mut(&mut self, account: &AccountId) -> Option<&mut AccountScore> {
77-
self.accounts.get_mut(account).and_then(|a| a.score_mut())
78-
}
79-
80-
pub(crate) fn get_jar_mut_internal(&mut self, account: &AccountId, id: JarId) -> &mut Jar {
81-
self.accounts
82-
.get_mut(account)
83-
.unwrap_or_else(|| env::panic_str(&format!("Account '{account}' doesn't exist")))
84-
.get_jar_mut(id)
85-
}
86-
8772
#[mutants::skip]
8873
pub(crate) fn get_jar_internal(&self, account: &AccountId, id: JarId) -> Jar {
8974
if let Some(jars) = self.account_jars_v1.get(account) {

0 commit comments

Comments
 (0)