sui_cluster_test/test_case/
native_transfer_test.rs1use async_trait::async_trait;
5use tracing::info;
6
7use sui_rpc_api::client::ExecutedTransaction;
8use sui_types::{
9 base_types::{ObjectID, SuiAddress},
10 crypto::{AccountKeyPair, get_key_pair},
11 object::Owner,
12};
13
14use crate::{
15 TestCaseImpl, TestContext,
16 helper::{BalanceChangeChecker, ObjectChecker},
17};
18
19pub struct NativeTransferTest;
20
21#[async_trait]
22impl TestCaseImpl for NativeTransferTest {
23 fn name(&self) -> &'static str {
24 "NativeTransfer"
25 }
26
27 fn description(&self) -> &'static str {
28 "Test tranferring SUI coins natively"
29 }
30
31 async fn run(&self, ctx: &mut TestContext) -> Result<(), anyhow::Error> {
32 info!("Testing gas coin transfer");
33 let mut sui_objs = ctx.get_sui_from_faucet(Some(1)).await;
34 let gas_obj = ctx.get_sui_from_faucet(Some(1)).await.swap_remove(0);
35
36 let signer = ctx.get_wallet_address();
37 let (recipient_addr, _): (_, AccountKeyPair) = get_key_pair();
38 let gas_budget = 2_000_000;
39
40 let obj_to_transfer: ObjectID = *sui_objs.swap_remove(0).id();
44 let gas_ref = ctx.current_object_ref(*gas_obj.id()).await;
45 let builder = ctx.get_grpc_client().transaction_builder();
46 let data = builder
47 .transfer_object(
48 signer,
49 obj_to_transfer,
50 Some(gas_ref.0),
51 gas_budget,
52 recipient_addr,
53 )
54 .await?;
55 let response = ctx.sign_and_execute(data, "coin transfer").await;
56 Self::examine_response(ctx, &response, signer, recipient_addr, obj_to_transfer).await;
57
58 let mut sui_objs_2 = ctx.get_sui_from_faucet(Some(1)).await;
60 let obj_to_transfer_2 = *sui_objs_2.swap_remove(0).id();
61 let gas_ref = ctx.current_object_ref(*gas_obj.id()).await;
63 let builder = ctx.get_grpc_client().transaction_builder();
64 let data = builder
65 .transfer_object(
66 signer,
67 obj_to_transfer_2,
68 Some(gas_ref.0),
69 gas_budget,
70 recipient_addr,
71 )
72 .await?;
73 let response = ctx.sign_and_execute(data, "coin transfer").await;
74
75 Self::examine_response(ctx, &response, signer, recipient_addr, obj_to_transfer_2).await;
78 Ok(())
79 }
80}
81
82impl NativeTransferTest {
83 async fn examine_response(
84 ctx: &TestContext,
85 response: &ExecutedTransaction,
86 signer: SuiAddress,
87 recipient: SuiAddress,
88 obj_to_transfer_id: ObjectID,
89 ) {
90 let mut balance_changes = response.balance_changes.clone();
91 assert_eq!(
94 balance_changes.len(),
95 2,
96 "Expect 2 balance changes emitted, but got {}",
97 balance_changes.len()
98 );
99 let signer_sdk: sui_sdk_types::Address = signer.into();
102 if balance_changes[0].address == signer_sdk {
103 balance_changes.reverse()
104 }
105 BalanceChangeChecker::new()
106 .address(recipient)
107 .coin_type("0x2::sui::SUI")
108 .check(&balance_changes.remove(0));
109 BalanceChangeChecker::new()
110 .address(signer)
111 .coin_type("0x2::sui::SUI")
112 .check(&balance_changes.remove(0));
113
114 ObjectChecker::new(obj_to_transfer_id)
118 .owner(Owner::AddressOwner(recipient))
119 .check(&ctx.get_grpc_client())
120 .await
121 .expect("transferred object must be readable and owned by the recipient");
122 }
123}