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
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
// Copyright (c) Mysten Labs, Inc.
// SPDX-License-Identifier: Apache-2.0

use crate::{helper::ObjectChecker, TestCaseImpl, TestContext};
use async_trait::async_trait;
use sui_json_rpc_types::{SuiExecutionStatus, SuiTransactionBlockEffectsAPI};
use sui_sdk::wallet_context::WalletContext;
use sui_test_transaction_builder::{increment_counter, publish_basics_package_and_make_counter};
use sui_types::object::Owner;
use tracing::info;

pub struct SharedCounterTest;

#[async_trait]
impl TestCaseImpl for SharedCounterTest {
    fn name(&self) -> &'static str {
        "SharedCounter"
    }

    fn description(&self) -> &'static str {
        "Test publishing basics packages and incrementing Counter (shared object)"
    }

    async fn run(&self, ctx: &mut TestContext) -> Result<(), anyhow::Error> {
        info!("Testing shared object transactions.");

        let sui_objs = ctx.get_sui_from_faucet(Some(1)).await;
        assert!(!sui_objs.is_empty());

        let wallet_context: &WalletContext = ctx.get_wallet();
        let address = ctx.get_wallet_address();
        let (package_ref, (counter_id, initial_counter_version, _)) =
            publish_basics_package_and_make_counter(wallet_context).await;
        let response = increment_counter(
            wallet_context,
            address,
            None,
            package_ref.0,
            counter_id,
            initial_counter_version,
        )
        .await;
        assert_eq!(
            *response.effects.as_ref().unwrap().status(),
            SuiExecutionStatus::Success,
            "Increment counter txn failed: {:?}",
            *response.effects.as_ref().unwrap().status()
        );

        response
            .effects
            .as_ref()
            .unwrap()
            .shared_objects()
            .iter()
            .find(|o| o.object_id == counter_id)
            .expect("Expect obj {counter_id} in shared_objects");

        let counter_version = response
            .effects
            .as_ref()
            .unwrap()
            .mutated()
            .iter()
            .find_map(|obj| {
                let Owner::Shared {
                    initial_shared_version,
                } = obj.owner
                else {
                    return None;
                };

                if obj.reference.object_id == counter_id
                    && initial_shared_version == initial_counter_version
                {
                    Some(obj.reference.version)
                } else {
                    None
                }
            })
            .expect("Expect obj {counter_id} in mutated");

        // Verify fullnode observes the txn
        ctx.let_fullnode_sync(vec![response.digest], 5).await;

        let counter_object = ObjectChecker::new(counter_id)
            .owner(Owner::Shared {
                initial_shared_version: initial_counter_version,
            })
            .check_into_object(ctx.get_fullnode_client())
            .await;

        assert_eq!(
            counter_object.version, counter_version,
            "Expect sequence number to be 2"
        );

        Ok(())
    }
}