Skip to content

Commit a6bae90

Browse files
authored
fix: fixed bugs discovered while testing the mobile app on testnet (#72)
* test: testnet migration * test: sandbox jar creation after migration * test: create jar on testnet wip * fix: restore event format * fix: migrate in signature verification * fix: skip new filed only in event * fix: simpler event serialization
1 parent ba4021c commit a6bae90

File tree

7 files changed

+156
-20
lines changed

7 files changed

+156
-20
lines changed

contract/src/event.rs

+82-8
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,15 @@ use near_sdk::{
44
serde::{Deserialize, Serialize},
55
serde_json, AccountId,
66
};
7-
use sweat_jar_model::{jar::JarId, ProductId};
8-
9-
use crate::{common::Timestamp, env, jar::model::Jar, product::model::Product, PACKAGE_NAME, VERSION};
7+
use sweat_jar_model::{jar::JarId, ProductId, TokenAmount};
8+
9+
use crate::{
10+
common::Timestamp,
11+
env,
12+
jar::model::{JarCache, JarV1},
13+
product::model::Product,
14+
PACKAGE_NAME, VERSION,
15+
};
1016

1117
#[derive(Serialize, Deserialize, Debug)]
1218
#[serde(
@@ -17,7 +23,7 @@ use crate::{common::Timestamp, env, jar::model::Jar, product::model::Product, PA
1723
)]
1824
pub enum EventKind {
1925
RegisterProduct(Product),
20-
CreateJar(Jar),
26+
CreateJar(EventJar),
2127
Claim(Vec<ClaimEventItem>),
2228
Withdraw(WithdrawData),
2329
Migration(Vec<MigrationEventItem>),
@@ -29,6 +35,36 @@ pub enum EventKind {
2935
TopUp(TopUpData),
3036
}
3137

38+
#[derive(Serialize, Deserialize, Debug)]
39+
#[serde(crate = "near_sdk::serde", rename_all = "snake_case")]
40+
pub struct EventJar {
41+
id: JarId,
42+
account_id: AccountId,
43+
product_id: ProductId,
44+
created_at: Timestamp,
45+
principal: TokenAmount,
46+
cache: Option<JarCache>,
47+
claimed_balance: TokenAmount,
48+
is_pending_withdraw: bool,
49+
is_penalty_applied: bool,
50+
}
51+
52+
impl From<JarV1> for EventJar {
53+
fn from(value: JarV1) -> Self {
54+
Self {
55+
id: value.id,
56+
account_id: value.account_id,
57+
product_id: value.product_id,
58+
created_at: value.created_at,
59+
principal: value.principal,
60+
cache: value.cache,
61+
claimed_balance: value.claimed_balance,
62+
is_pending_withdraw: value.is_pending_withdraw,
63+
is_penalty_applied: value.is_penalty_applied,
64+
}
65+
}
66+
}
67+
3268
#[derive(Serialize, Deserialize, Debug)]
3369
#[serde(crate = "near_sdk::serde", rename_all = "snake_case")]
3470
struct SweatJarEvent {
@@ -142,16 +178,19 @@ impl SweatJarEvent {
142178

143179
#[cfg(test)]
144180
mod test {
145-
use near_sdk::json_types::U128;
181+
use near_sdk::{json_types::U128, AccountId};
146182

147-
use crate::event::{EventKind, SweatJarEvent, TopUpData};
183+
use crate::{
184+
event::{EventKind, SweatJarEvent, TopUpData},
185+
jar::model::JarV1,
186+
};
148187

149188
#[test]
150189
fn event_to_string() {
151190
assert_eq!(
152191
SweatJarEvent::from(EventKind::TopUp(TopUpData {
153192
id: 10,
154-
amount: U128(50)
193+
amount: U128(50),
155194
}))
156195
.to_json_event_string(),
157196
r#"EVENT_JSON:{
@@ -163,6 +202,41 @@ mod test {
163202
"amount": "50"
164203
}
165204
}"#
166-
)
205+
);
206+
207+
assert_eq!(
208+
SweatJarEvent::from(EventKind::CreateJar(
209+
JarV1 {
210+
id: 555,
211+
account_id: AccountId::new_unchecked("bob.near".to_string()),
212+
product_id: "some_product".to_string(),
213+
created_at: 1234324235,
214+
principal: 78685678567,
215+
cache: None,
216+
claimed_balance: 4324,
217+
is_pending_withdraw: false,
218+
is_penalty_applied: false,
219+
claim_remainder: 55555,
220+
}
221+
.into()
222+
))
223+
.to_json_event_string(),
224+
r#"EVENT_JSON:{
225+
"standard": "sweat_jar",
226+
"version": "1.0.0",
227+
"event": "create_jar",
228+
"data": {
229+
"id": 555,
230+
"account_id": "bob.near",
231+
"product_id": "some_product",
232+
"created_at": 1234324235,
233+
"principal": 78685678567,
234+
"cache": null,
235+
"claimed_balance": 4324,
236+
"is_pending_withdraw": false,
237+
"is_penalty_applied": false
238+
}
239+
}"#
240+
);
167241
}
168242
}

contract/src/jar/model/v1.rs

+3-1
Original file line numberDiff line numberDiff line change
@@ -236,7 +236,7 @@ impl Contract {
236236

237237
self.add_new_jar(&account_id, jar.clone());
238238

239-
emit(EventKind::CreateJar(jar.clone()));
239+
emit(EventKind::CreateJar(jar.inner().into()));
240240

241241
jar.into()
242242
}
@@ -314,6 +314,8 @@ impl Contract {
314314
ticket: &JarTicket,
315315
signature: Option<Base64VecU8>,
316316
) {
317+
self.migrate_account_jars_if_needed(account_id.clone());
318+
317319
let last_jar_id = self.account_jars.get(account_id).map(|jars| jars.last_id);
318320
let product = self.get_product(&ticket.product_id);
319321

contract/src/jar/model/versioned.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ impl JarVersioned {
7070
.into()
7171
}
7272

73-
fn inner(&self) -> JarV1 {
73+
pub fn inner(&self) -> JarV1 {
7474
match self {
7575
Self::V1(jar) => jar.clone(),
7676
}

integration-tests/src/jar_contract_extensions.rs

+4-4
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,7 @@ impl JarContractExtensions for SweatJarContract<'_> {
108108
product_id: String,
109109
amount: u128,
110110
ft_contract_id: &near_workspaces::AccountId,
111-
) -> anyhow::Result<U128> {
111+
) -> Result<U128> {
112112
println!(
113113
"▶️ Create jar(product = {:?}) for user {:?} with {:?} tokens",
114114
product_id,
@@ -137,7 +137,7 @@ impl JarContractExtensions for SweatJarContract<'_> {
137137
signature: String,
138138
valid_until: u64,
139139
ft_contract_id: &near_workspaces::AccountId,
140-
) -> anyhow::Result<U128> {
140+
) -> Result<U128> {
141141
println!(
142142
"▶️ Create premium jar(product = {:?}) for user {:?} with {:?} tokens",
143143
product_id,
@@ -165,7 +165,7 @@ impl JarContractExtensions for SweatJarContract<'_> {
165165
jar_id: JarId,
166166
amount: U128,
167167
ft_contract_id: &near_workspaces::AccountId,
168-
) -> anyhow::Result<U128> {
168+
) -> Result<U128> {
169169
let msg = json!({
170170
"type": "top_up",
171171
"data": jar_id,
@@ -229,7 +229,7 @@ impl JarContractExtensions for SweatJarContract<'_> {
229229
receiver_id.id(),
230230
product_id,
231231
amount,
232-
last_jar_id.map_or_else(String::new, |value| value,),
232+
last_jar_id.map_or_else(String::new, |value| value),
233233
valid_until,
234234
)
235235
}

integration-tests/src/migrations/claim_rounding.rs

+65-5
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,23 @@
11
use anyhow::Result;
22
use fake::Fake;
3-
use integration_utils::contract_call::set_integration_logs_enabled;
3+
use integration_utils::{contract_call::set_integration_logs_enabled, misc::ToNear};
44
use near_sdk::AccountId;
55
use near_workspaces::types::NearToken;
6-
use sweat_jar_model::api::{IntegrationTestMethodsIntegration, MigrationToClaimRemainderIntegration, SweatJarContract};
6+
use sweat_jar_model::{
7+
api::{
8+
IntegrationTestMethodsIntegration, JarApiIntegration, MigrationToClaimRemainderIntegration, SweatJarContract,
9+
},
10+
jar::JarView,
11+
};
712

813
use crate::{
914
context::{prepare_contract, IntegrationContext},
15+
jar_contract_extensions::JarContractExtensions,
1016
migrations::helpers::load_wasm,
1117
product::RegisterProductCommand,
1218
};
1319

1420
#[tokio::test]
15-
#[ignore]
1621
async fn migrate_to_claim_roundings() -> Result<()> {
1722
use std::time::Instant;
1823
let now = Instant::now();
@@ -21,18 +26,20 @@ async fn migrate_to_claim_roundings() -> Result<()> {
2126

2227
let jar_before_rounding = load_wasm("res/sweat_jar_before_rounding.wasm");
2328

24-
let context = prepare_contract(
29+
let mut context = prepare_contract(
2530
jar_before_rounding.into(),
2631
[
2732
RegisterProductCommand::Locked12Months12Percents,
2833
RegisterProductCommand::Locked6Months6Percents,
2934
RegisterProductCommand::Locked6Months6PercentsWithWithdrawFee,
3035
],
3136
)
32-
.await?;
37+
.await?;
3338

3439
let jar_account = context.sweat_jar().contract.as_account().clone();
3540

41+
let alice = context.alice().await?;
42+
3643
let elapsed = now.elapsed();
3744
println!("Elapsed: {:.2?}", elapsed);
3845

@@ -66,6 +73,23 @@ async fn migrate_to_claim_roundings() -> Result<()> {
6673
let elapsed = now.elapsed();
6774
println!("Created jars elapsed: {:.2?}", elapsed);
6875

76+
const PRINCIPAL: u128 = 100000;
77+
78+
context
79+
.sweat_jar()
80+
.create_jar(
81+
&alice,
82+
RegisterProductCommand::Locked6Months6Percents.id(),
83+
PRINCIPAL,
84+
context.ft_contract().contract.as_account().id(),
85+
)
86+
.await?;
87+
88+
let alice_jars_before = context.sweat_jar().get_jars_for_account(alice.to_near()).await?;
89+
let alice_principal = context.sweat_jar().get_total_principal(alice.to_near()).await?;
90+
91+
assert_eq!(alice_principal.total.0, PRINCIPAL);
92+
6993
let jar_after_rounding = load_wasm("res/sweat_jar.wasm");
7094
let jar_after_rounding = jar_account.deploy(&jar_after_rounding).await?.into_result()?;
7195
let jar_after_rounding = SweatJarContract {
@@ -79,6 +103,42 @@ async fn migrate_to_claim_roundings() -> Result<()> {
79103

80104
jar_after_rounding.migrate_state_to_claim_remainder().await?;
81105

106+
let alice_jars_after = context.sweat_jar().get_jars_for_account(alice.to_near()).await?;
107+
let alice_principal_after = context.sweat_jar().get_total_principal(alice.to_near()).await?;
108+
109+
assert_eq!(alice_jars_before, alice_jars_after);
110+
assert_eq!(alice_principal, alice_principal_after);
111+
assert_eq!(alice_principal_after.total.0, PRINCIPAL);
112+
113+
context
114+
.sweat_jar()
115+
.create_jar(
116+
&alice,
117+
RegisterProductCommand::Locked6Months6Percents.id(),
118+
PRINCIPAL,
119+
context.ft_contract().contract.as_account().id(),
120+
)
121+
.await?;
122+
123+
let alice_principal_2_jars = context.sweat_jar().get_total_principal(alice.to_near()).await?;
124+
assert_eq!(alice_principal_2_jars.total.0, PRINCIPAL * 2);
125+
126+
let alice_2_jars = context.sweat_jar().get_jars_for_account(alice.to_near()).await?;
127+
128+
let jar = alice_jars_before.into_iter().next().unwrap();
129+
130+
assert_eq!(
131+
alice_2_jars.clone(),
132+
vec![
133+
jar.clone(),
134+
JarView {
135+
id: alice_2_jars[1].id,
136+
created_at: alice_2_jars[1].created_at,
137+
..jar
138+
},
139+
]
140+
);
141+
82142
for accs in accounts.chunks(600) {
83143
jar_after_rounding
84144
.migrate_accounts_to_claim_remainder(accs.to_vec())

model/src/jar.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ pub type JarId = u32;
1414

1515
pub type JarIdView = U32;
1616

17-
#[derive(Serialize, Deserialize, Debug, PartialEq)]
17+
#[derive(Clone, Serialize, Deserialize, Debug, PartialEq)]
1818
#[serde(crate = "near_sdk::serde")]
1919
pub struct JarView {
2020
pub id: JarIdView,

res/sweat_jar.wasm

2.9 KB
Binary file not shown.

0 commit comments

Comments
 (0)