-
Notifications
You must be signed in to change notification settings - Fork 8
Expand file tree
/
Copy pathmulti_agent.rs
More file actions
112 lines (96 loc) · 3.85 KB
/
Copy pathmulti_agent.rs
File metadata and controls
112 lines (96 loc) · 3.85 KB
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
101
102
103
104
105
106
107
108
109
110
111
112
//! Example: Multi-agent transaction
//!
//! This example demonstrates how to create a transaction that requires
//! signatures from multiple accounts.
//!
//! Run with: `cargo run --example multi_agent --features "ed25519,faucet"`
use aptos_sdk::{
Aptos, AptosConfig,
account::{Account, Ed25519Account},
transaction::{
EntryFunction, TransactionBuilder, TransactionPayload,
builder::sign_multi_agent_transaction, types::MultiAgentRawTransaction,
},
types::MoveModuleId,
};
#[tokio::main]
async fn main() -> anyhow::Result<()> {
// Create client for devnet
let aptos = Aptos::new(AptosConfig::devnet())?;
println!("Connected to devnet");
// Generate accounts
let primary_signer = Ed25519Account::generate();
let secondary_signer = Ed25519Account::generate();
println!("Primary signer: {}", primary_signer.address());
println!("Secondary signer: {}", secondary_signer.address());
// Fund both accounts
println!("\nFunding accounts...");
aptos
.fund_account(primary_signer.address(), 100_000_000)
.await?;
aptos
.fund_account(secondary_signer.address(), 100_000_000)
.await?;
tokio::time::sleep(std::time::Duration::from_secs(2)).await;
// For this example, we'll use a simple entry function
// In practice, you would use a function that actually requires multiple signers
// such as a multi-sig wallet or a swap that needs both parties to sign
// Build a payload (using a simple transfer for demonstration)
//
// IMPORTANT: This example demonstrates the multi-agent API mechanics, but uses
// `aptos_account::transfer` which only requires a single signer. In production,
// you would use an entry function that actually requires multiple signers, such as:
// - Atomic swaps between users (requires both parties to sign)
// - Multi-party escrow operations
// - Custom contracts with multiple signer parameters
//
// The secondary signer here is included to show how to construct and sign
// a multi-agent transaction, but doesn't affect the on-chain execution.
let payload = TransactionPayload::EntryFunction(EntryFunction {
module: MoveModuleId::from_str_strict("0x1::aptos_account")?,
function: "transfer".to_string(),
type_args: vec![],
args: vec![
aptos_bcs::to_bytes(&secondary_signer.address())?,
aptos_bcs::to_bytes(&1000u64)?,
],
});
// Get sequence number
let sequence_number = aptos.get_sequence_number(primary_signer.address()).await?;
// Build the raw transaction
let raw_txn = TransactionBuilder::new()
.sender(primary_signer.address())
.sequence_number(sequence_number)
.payload(payload)
.chain_id(aptos.chain_id())
.expiration_from_now(600)
.build()?;
// Create a multi-agent transaction
let multi_agent_txn = MultiAgentRawTransaction::new(raw_txn, vec![secondary_signer.address()]);
// Sign with both signers
let signed_txn = sign_multi_agent_transaction(
&multi_agent_txn,
&primary_signer,
&[&secondary_signer as &dyn Account],
)?;
// Submit the transaction
println!("\nSubmitting multi-agent transaction...");
let result = aptos.submit_and_wait(&signed_txn, None).await?;
let success = result
.data
.get("success")
.and_then(serde_json::value::Value::as_bool);
if success == Some(true) {
println!("Multi-agent transaction successful!");
let version = result.data.get("version").and_then(|v| v.as_str());
println!("Transaction version: {version:?}");
} else {
let vm_status = result
.data
.get("vm_status")
.and_then(|v| v.as_str())
.unwrap_or("unknown");
println!("Transaction failed: {vm_status}");
}
Ok(())
}