Skip to content

Commit d2f8af7

Browse files
authored
Merge pull request #44 from iotaledger/feat/add-examples
feat: add e2e tests and examples
2 parents 711341f + 333a4c2 commit d2f8af7

18 files changed

Lines changed: 1318 additions & 16 deletions

.github/workflows/build-and-test-move.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
name: Build and Test
1+
name: Build and Test Move
22

33
on:
44
pull_request:
@@ -37,7 +37,7 @@ jobs:
3737
- run: |
3838
# this run step does nothing, but is needed to get the job output
3939
40-
build-and-test:
40+
build-and-test-move:
4141
runs-on: ${{ matrix.os }}
4242
needs: check-for-run-condition
4343
if: ${{ needs.check-for-run-condition.outputs.should-run == 'true' && github.event_name != 'workflow_dispatch' }}

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ rust-version = "1.65"
88

99
[workspace]
1010
resolver = "2"
11-
members = ["notarization-rs"]
11+
members = ["notarization-rs", "examples"]
1212

1313
[workspace.dependencies]
1414
anyhow = "1.0"
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
// Copyright 2020-2025 IOTA Stiftung
2+
// SPDX-License-Identifier: Apache-2.0
3+
4+
use std::time::{SystemTime, UNIX_EPOCH};
5+
6+
use anyhow::Result;
7+
use examples::get_funded_client;
8+
use notarization::core::state::State;
9+
use notarization::core::timelock::TimeLock;
10+
use notarization::core::NotarizationMethod;
11+
12+
#[tokio::main]
13+
async fn main() -> Result<()> {
14+
println!("Creating a locked notarization example");
15+
16+
// Create a notarization client
17+
let notarization_client = get_funded_client().await?;
18+
19+
// Calculate unlock time (24 hours from now)
20+
let now_ts = SystemTime::now().duration_since(UNIX_EPOCH).unwrap().as_secs();
21+
let unlock_at = now_ts + 86400; // 24 hours
22+
23+
println!("Creating locked notarization with delete lock until: {}", unlock_at);
24+
25+
// Create a locked notarization with state and delete lock
26+
let locked_notarization = notarization_client
27+
.create_locked_notarization()
28+
.with_state(State::from_string(
29+
"Important document content".to_string(),
30+
Some("Document metadata".to_string()),
31+
))
32+
.with_immutable_description("Critical legal document".to_string())
33+
.with_updateable_metadata("Initial document metadata".to_string())
34+
.with_delete_at(TimeLock::UnlockAt(unlock_at as u32))
35+
.finish()?
36+
.build_and_execute(&notarization_client)
37+
.await?
38+
.output;
39+
40+
println!("✅ Locked notarization created successfully!");
41+
println!("Notarization ID: {:?}", locked_notarization.id);
42+
println!("Method: {:?}", locked_notarization.method);
43+
println!("Description: {:?}", locked_notarization.immutable_metadata.description);
44+
println!("Updateable metadata: {:?}", locked_notarization.updateable_metadata);
45+
println!("State version count: {}", locked_notarization.state_version_count);
46+
47+
// Verify the notarization method is locked
48+
assert_eq!(locked_notarization.method, NotarizationMethod::Locked);
49+
50+
// Check if it has locking metadata
51+
assert!(locked_notarization.immutable_metadata.locking.is_some());
52+
53+
println!("🔒 The notarization is locked and cannot be updated or transferred until destroyed");
54+
println!("🗑️ The notarization can only be destroyed after the delete lock expires");
55+
56+
Ok(())
57+
}
Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
// Copyright 2020-2025 IOTA Stiftung
2+
// SPDX-License-Identifier: Apache-2.0
3+
4+
use std::time::{SystemTime, UNIX_EPOCH};
5+
6+
use anyhow::Result;
7+
use examples::get_funded_client;
8+
use notarization::core::state::State;
9+
use notarization::core::timelock::TimeLock;
10+
use notarization::core::NotarizationMethod;
11+
12+
#[tokio::main]
13+
async fn main() -> Result<()> {
14+
println!("Creating a dynamic notarization example");
15+
16+
// Create a notarization client
17+
let notarization_client = get_funded_client().await?;
18+
19+
println!("Creating a simple dynamic notarization without locks...");
20+
21+
// Create a simple dynamic notarization
22+
let simple_notarization = notarization_client
23+
.create_dynamic_notarization()
24+
.with_state(State::from_string(
25+
"Live document content".to_string(),
26+
Some("Version 1.0".to_string()),
27+
))
28+
.with_immutable_description("Dynamic document".to_string())
29+
.with_updateable_metadata("Initial metadata".to_string())
30+
.finish()
31+
.build_and_execute(&notarization_client)
32+
.await?
33+
.output;
34+
35+
println!("✅ Simple dynamic notarization created!");
36+
println!("ID: {:?}", simple_notarization.id);
37+
38+
// Calculate unlock time for transfer lock example
39+
let now_ts = SystemTime::now().duration_since(UNIX_EPOCH).unwrap().as_secs();
40+
let unlock_at = now_ts + 3600; // 1 hour
41+
42+
println!("\nCreating a dynamic notarization with transfer lock...");
43+
44+
// Create a dynamic notarization with transfer lock
45+
let locked_transfer_notarization = notarization_client
46+
.create_dynamic_notarization()
47+
.with_state(State::from_string("Transfer-locked content".to_string(), None))
48+
.with_immutable_description("Transfer-locked document".to_string())
49+
.with_transfer_lock(TimeLock::UnlockAt(unlock_at as u32))
50+
.finish()
51+
.build_and_execute(&notarization_client)
52+
.await?
53+
.output;
54+
55+
println!("✅ Transfer-locked dynamic notarization created!");
56+
println!("ID: {:?}", locked_transfer_notarization.id);
57+
58+
// Verify both are dynamic notarizations
59+
assert_eq!(simple_notarization.method, NotarizationMethod::Dynamic);
60+
assert_eq!(locked_transfer_notarization.method, NotarizationMethod::Dynamic);
61+
62+
// Check transfer lock status
63+
let is_transfer_locked = notarization_client
64+
.is_transfer_locked(*locked_transfer_notarization.id.object_id())
65+
.await?;
66+
67+
println!("\n📊 Notarization Status:");
68+
println!("Simple notarization - Method: {:?}", simple_notarization.method);
69+
println!("Transfer-locked notarization - Transfer locked: {}", is_transfer_locked);
70+
println!("\n🔄 Dynamic notarizations can be updated and transferred (unless transfer-locked)");
71+
println!("📝 State and metadata can be modified over time");
72+
73+
Ok(())
74+
}
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
// Copyright 2020-2025 IOTA Stiftung
2+
// SPDX-License-Identifier: Apache-2.0
3+
4+
use anyhow::Result;
5+
use examples::get_funded_client;
6+
use notarization::core::state::State;
7+
8+
#[tokio::main]
9+
async fn main() -> Result<()> {
10+
println!("Demonstrating update on dynamic notarization");
11+
12+
let notarization_client = get_funded_client().await?;
13+
14+
println!("Creating a dynamic notarization...");
15+
16+
// Create a dynamic notarization
17+
let dynamic_notarization_id = notarization_client
18+
.create_dynamic_notarization()
19+
.with_state(State::from_string(
20+
"Original content".to_string(),
21+
Some("Original metadata".to_string()),
22+
))
23+
.with_immutable_description("Dynamic document for update test".to_string())
24+
.with_updateable_metadata("Initial updateable metadata".to_string())
25+
.finish()
26+
.build_and_execute(&notarization_client)
27+
.await?
28+
.output
29+
.id;
30+
31+
println!("✅ Dynamic notarization created with ID: {:?}", dynamic_notarization_id);
32+
33+
let current_state = notarization_client.state(*dynamic_notarization_id.object_id()).await?;
34+
println!("Initial state: {}", current_state.data.as_text()?);
35+
println!("Initial state metadata: {:?}", current_state.metadata);
36+
37+
println!("\n🔄 Updating state on dynamic notarization...");
38+
let new_state = State::from_string("Updated content".to_string(), Some("New metadata".to_string()));
39+
40+
let state_update_result = notarization_client
41+
.update_state(new_state, *dynamic_notarization_id.object_id())
42+
.build_and_execute(&notarization_client)
43+
.await;
44+
45+
match state_update_result {
46+
Ok(_) => println!("✅ State update succeeded"),
47+
Err(e) => println!("❌ State update failed - {}", e),
48+
}
49+
50+
println!("\n📝 Updating metadata on dynamic notarization...");
51+
let new_metadata = Some("Updated metadata".to_string());
52+
53+
let metadata_update_result = notarization_client
54+
.update_metadata(new_metadata, *dynamic_notarization_id.object_id())
55+
.build_and_execute(&notarization_client)
56+
.await;
57+
58+
match metadata_update_result {
59+
Ok(_) => println!("✅ Metadata update succeeded"),
60+
Err(e) => println!("❌ Metadata update failed - {}", e),
61+
}
62+
63+
let current_state = notarization_client.state(*dynamic_notarization_id.object_id()).await?;
64+
println!("Updated state: {}", current_state.data.as_text()?);
65+
println!("Updated state metadata: {:?}", current_state.metadata);
66+
67+
println!("\n🔒 Dynamic notarizations are mutable - state and metadata can be changed");
68+
69+
Ok(())
70+
}
Lines changed: 166 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,166 @@
1+
// Copyright 2020-2025 IOTA Stiftung
2+
// SPDX-License-Identifier: Apache-2.0
3+
4+
use std::time::{SystemTime, UNIX_EPOCH};
5+
6+
use anyhow::Result;
7+
use examples::get_funded_client;
8+
use notarization::core::state::State;
9+
use notarization::core::timelock::TimeLock;
10+
11+
#[tokio::main]
12+
async fn main() -> Result<()> {
13+
println!("Demonstrating notarization destruction scenarios");
14+
15+
// Create a notarization client
16+
let notarization_client = get_funded_client().await?;
17+
18+
// Scenario 1: Destroy an unlocked dynamic notarization (should succeed)
19+
println!("📝 Scenario 1: Creating and destroying an unlocked dynamic notarization...");
20+
21+
let unlocked_dynamic_id = notarization_client
22+
.create_dynamic_notarization()
23+
.with_state(State::from_string("Unlocked content".to_string(), None))
24+
.with_immutable_description("Unlocked dynamic document".to_string())
25+
.finish()
26+
.build_and_execute(&notarization_client)
27+
.await?
28+
.output
29+
.id;
30+
31+
println!("✅ Created unlocked dynamic notarization: {:?}", unlocked_dynamic_id);
32+
33+
// Check if destroy is allowed
34+
let is_destroy_allowed = notarization_client
35+
.is_destroy_allowed(*unlocked_dynamic_id.object_id())
36+
.await?;
37+
38+
println!("🔍 Destroy allowed: {}", is_destroy_allowed);
39+
40+
// Destroy the unlocked notarization
41+
let destroy_result = notarization_client
42+
.destroy(*unlocked_dynamic_id.object_id())
43+
.build_and_execute(&notarization_client)
44+
.await;
45+
46+
match destroy_result {
47+
Ok(_) => println!("✅ Successfully destroyed unlocked dynamic notarization"),
48+
Err(e) => println!("❌ Failed to destroy: {}", e),
49+
}
50+
51+
// Scenario 2: Try to destroy a transfer-locked dynamic notarization (should fail)
52+
println!("\n📝 Scenario 2: Creating a transfer-locked dynamic notarization...");
53+
54+
let now_ts = SystemTime::now().duration_since(UNIX_EPOCH).unwrap().as_secs();
55+
let unlock_at = now_ts + 86400; // 24 hours
56+
57+
let transfer_locked_id = notarization_client
58+
.create_dynamic_notarization()
59+
.with_state(State::from_string("Transfer-locked content".to_string(), None))
60+
.with_immutable_description("Transfer-locked document".to_string())
61+
.with_transfer_lock(TimeLock::UnlockAt(unlock_at as u32))
62+
.finish()
63+
.build_and_execute(&notarization_client)
64+
.await?
65+
.output
66+
.id;
67+
68+
println!(
69+
"✅ Created transfer-locked dynamic notarization: {:?}",
70+
transfer_locked_id
71+
);
72+
73+
let is_destroy_allowed = notarization_client
74+
.is_destroy_allowed(*transfer_locked_id.object_id())
75+
.await?;
76+
77+
println!("🔍 Destroy allowed: {}", is_destroy_allowed);
78+
79+
// Try to destroy the transfer-locked notarization
80+
let destroy_result = notarization_client
81+
.destroy(*transfer_locked_id.object_id())
82+
.build_and_execute(&notarization_client)
83+
.await;
84+
85+
match destroy_result {
86+
Ok(_) => println!("❌ Unexpected: Destruction succeeded (should have failed)"),
87+
Err(e) => println!("✅ Expected: Destruction failed - {}", e),
88+
}
89+
90+
// Scenario 3: Create and try to destroy a time-locked locked notarization (should fail)
91+
println!("\n📝 Scenario 3: Creating a time-locked locked notarization...");
92+
93+
let delete_locked_id = notarization_client
94+
.create_locked_notarization()
95+
.with_state(State::from_string("Delete-locked content".to_string(), None))
96+
.with_immutable_description("Delete-locked document".to_string())
97+
.with_delete_at(TimeLock::UnlockAt(unlock_at as u32))
98+
.finish()?
99+
.build_and_execute(&notarization_client)
100+
.await?
101+
.output
102+
.id;
103+
104+
println!("✅ Created delete-locked locked notarization: {:?}", delete_locked_id);
105+
106+
let is_destroy_allowed = notarization_client
107+
.is_destroy_allowed(*delete_locked_id.object_id())
108+
.await?;
109+
110+
println!("🔍 Destroy allowed: {}", is_destroy_allowed);
111+
112+
// Try to destroy the delete-locked notarization
113+
let destroy_result = notarization_client
114+
.destroy(*delete_locked_id.object_id())
115+
.build_and_execute(&notarization_client)
116+
.await;
117+
118+
match destroy_result {
119+
Ok(_) => println!("❌ Unexpected: Destruction succeeded (should have failed)"),
120+
Err(e) => println!("✅ Expected: Destruction failed - {}", e),
121+
}
122+
123+
// Scenario 4: Create and destroy a locked notarization with no delete lock (should succeed)
124+
println!("\n📝 Scenario 4: Creating a locked notarization with no delete lock...");
125+
126+
let no_delete_lock_id = notarization_client
127+
.create_locked_notarization()
128+
.with_state(State::from_string("No delete lock content".to_string(), None))
129+
.with_immutable_description("No delete lock document".to_string())
130+
.with_delete_at(TimeLock::None)
131+
.finish()?
132+
.build_and_execute(&notarization_client)
133+
.await?
134+
.output
135+
.id;
136+
137+
println!(
138+
"✅ Created locked notarization with no delete lock: {:?}",
139+
no_delete_lock_id
140+
);
141+
142+
let is_destroy_allowed = notarization_client
143+
.is_destroy_allowed(*no_delete_lock_id.object_id())
144+
.await?;
145+
146+
println!("🔍 Destroy allowed: {}", is_destroy_allowed);
147+
148+
// Destroy the notarization with no delete lock
149+
let destroy_result = notarization_client
150+
.destroy(*no_delete_lock_id.object_id())
151+
.build_and_execute(&notarization_client)
152+
.await;
153+
154+
match destroy_result {
155+
Ok(_) => println!("✅ Successfully destroyed locked notarization with no delete lock"),
156+
Err(e) => println!("❌ Failed to destroy: {}", e),
157+
}
158+
159+
println!("\n📋 Summary:");
160+
println!("🔓 Unlocked notarizations can be destroyed immediately");
161+
println!("🔒 Transfer-locked dynamic notarizations cannot be destroyed");
162+
println!("⏰ Time-locked locked notarizations cannot be destroyed before lock expires");
163+
println!("🆓 Locked notarizations with TimeLock::None can be destroyed");
164+
165+
Ok(())
166+
}

0 commit comments

Comments
 (0)