forest/dev/subcommands/tests_cmd/
wallet.rs1use super::helpers::*;
5use libtest_mimic::{Arguments, Trial};
6
7#[derive(Debug, clap::Args)]
9pub struct WalletTestCommand {}
10
11impl WalletTestCommand {
12 pub async fn run(self) -> anyhow::Result<()> {
13 let args = Arguments {
14 test_threads: Some(1),
15 ..Default::default()
16 };
17 libtest_mimic::run(&args, tests()).exit();
18 }
19}
20
21fn tests() -> Vec<Trial> {
22 vec![
23 Trial::test("export_import_roundtrip_local", || {
24 block_on(export_import_roundtrip(Backend::Local));
25 Ok(())
26 }),
27 Trial::test("export_import_roundtrip_remote", || {
28 block_on(export_import_roundtrip(Backend::Remote));
29 Ok(())
30 }),
31 Trial::test("import_as_default_local", || {
32 block_on(import_as_default(Backend::Local));
33 Ok(())
34 }),
35 Trial::test("import_as_default_remote", || {
36 block_on(import_as_default(Backend::Remote));
37 Ok(())
38 }),
39 Trial::test("market_add_balance_message_on_chain", || {
40 block_on(market_add_balance_message_on_chain());
41 Ok(())
42 }),
43 Trial::test("send_to_filecoin_address_local", || {
44 block_on(send_to_filecoin_address(Backend::Local));
45 Ok(())
46 }),
47 Trial::test("send_to_filecoin_address_remote", || {
48 block_on(send_to_filecoin_address(Backend::Remote));
49 Ok(())
50 }),
51 Trial::test("send_to_eth_equivalent_local", || {
52 block_on(send_to_eth_equivalent(Backend::Local));
53 Ok(())
54 }),
55 Trial::test("send_to_eth_equivalent_remote", || {
56 block_on(send_to_eth_equivalent(Backend::Remote));
57 Ok(())
58 }),
59 Trial::test("wallet_delete_local", || {
60 block_on(wallet_delete(Backend::Local));
61 Ok(())
62 }),
63 Trial::test("wallet_delete_remote", || {
64 block_on(wallet_delete(Backend::Remote));
65 Ok(())
66 }),
67 Trial::test("delegated_send_local", || {
68 block_on(delegated_send(Backend::Local));
69 Ok(())
70 }),
71 Trial::test("delegated_send_remote", || {
72 block_on(delegated_send(Backend::Remote));
73 Ok(())
74 }),
75 Trial::test("delegated_remote_send", || {
76 block_on(delegated_remote_send());
77 Ok(())
78 }),
79 ]
80}
81
82async fn export_import_roundtrip(backend: Backend) {
83 let addr = wallet(backend, &["new"]).unwrap();
84 let exported = export_to_temp_file(&addr, backend).unwrap();
85 let path = exported
86 .path()
87 .to_str()
88 .expect("temp path is not valid UTF-8");
89
90 let deleted = wallet(backend, &["delete", &addr]).unwrap();
91 eprintln!("delete output ({}): {deleted}", backend.label());
92
93 let imported = wallet(backend, &["import", path]).unwrap();
94 assert_eq!(
95 imported,
96 addr,
97 "round-trip mismatch on {} backend: {imported} != {addr}",
98 backend.label(),
99 );
100}
101
102async fn import_as_default(backend: Backend) {
103 let addr = wallet(backend, &["new"]).unwrap();
104 let exported = export_to_temp_file(&addr, backend).unwrap();
105 let path = exported
106 .path()
107 .to_str()
108 .expect("temp path is not valid UTF-8");
109
110 let deleted = wallet(backend, &["delete", &addr]).unwrap();
111 eprintln!("delete output ({}): {deleted}", backend.label());
112
113 let imported = wallet(backend, &["import", "--as-default", path]).unwrap();
114 assert_eq!(
115 imported,
116 addr,
117 "round-trip mismatch on {} backend: {imported} != {addr}",
118 backend.label(),
119 );
120 assert_eq!(wallet(backend, &["default"]).unwrap(), imported);
121}
122
123async fn market_add_balance_message_on_chain() {
124 const ATTO_FIL: &str = "23";
125 let result = rpc_call_with_retry(
126 "Filecoin.MarketAddBalance",
127 serde_json::json!([
128 FOREST_TEST_PRELOADED_ADDRESS.as_str(),
129 FOREST_TEST_PRELOADED_ADDRESS.as_str(),
130 ATTO_FIL,
131 ]),
132 )
133 .await
134 .unwrap();
135 let msg_cid = cid_from_lotus_json_result(&result).unwrap();
136 poll_until_state_search_msg(&msg_cid).await.unwrap();
137}
138
139async fn send_to_filecoin_address(backend: Backend) {
140 let target = wallet(backend, &["new"]).unwrap();
141 let msg = send_from(&FOREST_TEST_PRELOADED_ADDRESS, &target, FIL_AMT, backend).unwrap();
142 eprintln!("send to {target} ({}) msg: {msg}", backend.label());
143 let funded = poll_until_funded(&target, backend).await.unwrap();
144 eprintln!("{target} funded balance: {funded}");
145}
146
147async fn send_to_eth_equivalent(backend: Backend) {
148 let target = wallet(backend, &["new"]).unwrap();
149 let initial_msg = send_from(&FOREST_TEST_PRELOADED_ADDRESS, &target, FIL_AMT, backend).unwrap();
150 eprintln!(
151 "initial send to {target} ({}) msg: {initial_msg}",
152 backend.label(),
153 );
154 let baseline = poll_until_funded(&target, backend).await.unwrap();
155
156 let eth = filecoin_to_eth(&target).await.unwrap();
157 let eth_msg = send_from(&FOREST_TEST_PRELOADED_ADDRESS, ð, FIL_AMT, backend).unwrap();
158 eprintln!("send to ETH {eth} (mapped from {target}) msg: {eth_msg}");
159
160 let updated = poll_until_changed(&target, &baseline, backend)
161 .await
162 .unwrap();
163 assert!(
164 updated != baseline,
165 "{target} balance unchanged after ETH-equivalent send: {updated}",
166 );
167}
168
169async fn wallet_delete(backend: Backend) {
170 let addr = wallet(backend, &["new"]).unwrap();
171 let deleted = wallet(backend, &["delete", &addr]).unwrap();
172 eprintln!("delete output ({}): {deleted}", backend.label());
173 let listing = wallet(backend, &["list"]).unwrap();
174 assert!(
175 !listing.contains(&addr),
176 "deleted wallet {addr} still appears in `list`:\n{listing}",
177 );
178}
179
180async fn delegated_send(target_backend: Backend) {
181 let funded = funded_delegated_addr().await;
182 let target = wallet(target_backend, &["new", "delegated"]).unwrap();
183 let baseline = balance(&target, target_backend).unwrap();
185 let msg = send_from(funded, &target, FIL_AMT, Backend::Local).unwrap();
186 eprintln!(
187 "delegated send to {target} ({}) msg: {msg}",
188 target_backend.label(),
189 );
190 let observed = if baseline == FIL_ZERO {
191 poll_until_funded(&target, target_backend).await.unwrap()
192 } else {
193 poll_until_changed(&target, &baseline, target_backend)
194 .await
195 .unwrap()
196 };
197 assert!(
198 observed != baseline,
199 "{target} balance unchanged after delegated send: {observed}",
200 );
201}
202
203async fn delegated_remote_send() {
204 let funded = funded_delegated_addr().await;
205 let target = wallet(Backend::Remote, &["new", "delegated"]).unwrap();
206 let baseline = balance(&target, Backend::Remote).unwrap();
207 let msg = send_from(funded, &target, FIL_AMT, Backend::Remote).unwrap();
208 eprintln!("delegated --remote-wallet send to {target} msg: {msg}");
209 let observed = if baseline == FIL_ZERO {
210 poll_until_funded(&target, Backend::Remote).await.unwrap()
211 } else {
212 poll_until_changed(&target, &baseline, Backend::Remote)
213 .await
214 .unwrap()
215 };
216 assert!(
217 observed != baseline,
218 "{target} balance unchanged after delegated --remote-wallet send: {observed}",
219 );
220}