use amp_rs::signer::{LwkSoftwareSigner, Signer};
use amp_rs::ElementsRpc;
use chrono;
use dotenvy;
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
tracing_subscriber::fmt::init();
println!("๐ง Elements-First Wallet Setup Example");
println!("======================================");
dotenvy::dotenv().ok();
let elements_rpc = match ElementsRpc::from_env() {
Ok(rpc) => {
println!("โ
Elements RPC client created from environment variables");
rpc
}
Err(e) => {
println!("โ Failed to create Elements RPC client: {}", e);
println!("\nPlease set the following environment variables:");
println!(" ELEMENTS_RPC_URL=http://localhost:18884");
println!(" ELEMENTS_RPC_USER=your_rpc_user");
println!(" ELEMENTS_RPC_PASSWORD=your_rpc_password");
return Err(e.into());
}
};
match elements_rpc.get_network_info().await {
Ok(info) => {
println!("โ
Connected to Elements node");
println!(" Version: {}", info.version);
println!(" Connections: {}", info.connections);
}
Err(e) => {
println!("โ Failed to connect to Elements node: {}", e);
println!(" Please ensure your Elements node is running and accessible");
return Err(e.into());
}
}
println!("\n๐ฆ Step 1: Creating Elements Wallet");
println!("==================================");
let wallet_name = format!("elements_first_{}", chrono::Utc::now().timestamp());
println!(" Wallet name: {}", wallet_name);
match elements_rpc.create_elements_wallet(&wallet_name).await {
Ok(()) => {
println!("โ
Successfully created Elements wallet: {}", wallet_name);
}
Err(e) => {
println!("โ Failed to create Elements wallet: {}", e);
let error_msg = e.to_string();
if error_msg.contains("already exists") || error_msg.contains("Database already exists")
{
println!(" Wallet already exists, continuing with existing wallet");
} else {
return Err(e.into());
}
}
}
println!("\n๐ Step 2: Generating Native Segwit Address in Elements");
println!("======================================================");
let unconfidential_address = match elements_rpc
.get_new_address(&wallet_name, Some("bech32"))
.await
{
Ok(address) => {
println!(
"โ
Generated new unconfidential address in Elements: {}",
address
);
address
}
Err(e) => {
println!("โ Failed to generate address: {}", e);
return Err(e.into());
}
};
let confidential_address = match elements_rpc
.get_confidential_address(&wallet_name, &unconfidential_address)
.await
{
Ok(address) => {
println!("โ
Retrieved confidential address: {}", address);
address
}
Err(e) => {
println!("โ Failed to get confidential address: {}", e);
return Err(e.into());
}
};
println!("\n๐ Step 3: Exporting Private Key from Elements");
println!("==============================================");
let private_key = match elements_rpc
.dump_private_key(&wallet_name, &unconfidential_address)
.await
{
Ok(key) => {
println!("โ
Successfully exported private key");
println!(" Private key: {}...", &key[..10]); key
}
Err(e) => {
println!("โ Failed to export private key: {}", e);
return Err(e.into());
}
};
println!("\n๐ง Step 4: Creating LWK Signer from Elements Private Key");
println!("========================================================");
let lwk_signer = match LwkSoftwareSigner::from_elements_private_key(&private_key) {
Ok(signer) => {
println!("โ
Successfully created LWK signer from Elements private key");
println!(" Testnet mode: {}", signer.is_testnet());
signer
}
Err(e) => {
println!("โ Failed to create LWK signer: {}", e);
return Err(e.into());
}
};
println!("\n๐ Step 5: Verifying Address Compatibility");
println!("==========================================");
match lwk_signer.verify_elements_address(&unconfidential_address) {
Ok(verified_address) => {
println!("โ
Address verification successful");
println!(" Unconfidential address: {}", unconfidential_address);
println!(" Verified address: {}", verified_address);
if unconfidential_address == verified_address {
println!("โ
Addresses match perfectly!");
} else {
println!("โ ๏ธ Addresses differ - this may be expected depending on implementation");
}
}
Err(e) => {
println!("โ Address verification failed: {}", e);
return Err(e.into());
}
}
println!("\n๐งช Step 6: Testing Signer Functionality");
println!("=======================================");
match lwk_signer.sign_transaction("invalid_transaction_hex").await {
Ok(_) => {
println!("โ ๏ธ Unexpected: signer accepted invalid transaction");
}
Err(e) => {
println!("โ
Signer correctly rejected invalid transaction: {}", e);
}
}
match lwk_signer.sign_transaction("").await {
Ok(_) => {
println!("โ ๏ธ Unexpected: signer accepted empty transaction");
}
Err(e) => {
println!("โ
Signer correctly rejected empty transaction: {}", e);
}
}
println!("\n๐ฏ Elements-First Setup Complete!");
println!("=================================");
println!("โ
Elements wallet created: {}", wallet_name);
println!(
"โ
Unconfidential address generated: {}",
unconfidential_address
);
println!(
"โ
Confidential address retrieved: {}",
confidential_address
);
println!("โ
Private key exported from Elements");
println!("โ
LWK signer created from Elements private key");
println!("โ
Address compatibility verified");
println!();
println!("๐ Benefits of this approach:");
println!(" - Elements can definitely see transactions to both addresses");
println!(" - LWK can sign transactions using the imported private key");
println!(" - No descriptor import issues or blinding key problems");
println!(" - Direct compatibility between Elements and LWK");
println!(" - Confidential address supports blinded transactions");
println!();
println!("๐ก Next steps:");
println!(
" - Use '{}' as treasury address for asset issuance (confidential)",
confidential_address
);
println!(
" - Use '{}' for LWK signing operations (unconfidential)",
unconfidential_address
);
println!(" - Use the LWK signer for transaction signing");
println!(" - Elements wallet will automatically see incoming transactions");
println!();
println!("๐ง Manual verification commands:");
println!(
" - Check wallet: elements-cli -rpcwallet={} getwalletinfo",
wallet_name
);
println!(
" - List addresses: elements-cli -rpcwallet={} listreceivedbyaddress 0 true",
wallet_name
);
println!(
" - Check balance: elements-cli -rpcwallet={} getbalance",
wallet_name
);
Ok(())
}