-
Notifications
You must be signed in to change notification settings - Fork 75
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
9d7bee9
commit 4aafe3f
Showing
9 changed files
with
817 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
use clap::Parser; | ||
|
||
pub mod send; | ||
pub mod sign; | ||
pub mod simulate; | ||
pub mod xdr; | ||
|
||
use stellar_xdr::cli as xdr_cli; | ||
|
||
#[derive(Debug, Parser)] | ||
pub enum Cmd { | ||
/// Add a new identity (keypair, ledger, macOS keychain) | ||
Inspect(xdr_cli::Root), | ||
/// Given an identity return its address (public key) | ||
Sign(sign::Cmd), | ||
/// Submit a transaction to the network | ||
Send(send::Cmd), | ||
/// Simulate a transaction | ||
Simulate(simulate::Cmd), | ||
} | ||
|
||
#[derive(thiserror::Error, Debug)] | ||
pub enum Error { | ||
/// An error during the simulation | ||
#[error(transparent)] | ||
Simulate(#[from] simulate::Error), | ||
/// An error during the inspect | ||
#[error(transparent)] | ||
Inspect(#[from] xdr_cli::Error), | ||
/// An error during the sign | ||
#[error(transparent)] | ||
Sign(#[from] sign::Error), | ||
/// An error during the send | ||
#[error(transparent)] | ||
Send(#[from] send::Error), | ||
} | ||
|
||
impl Cmd { | ||
pub async fn run(&self) -> Result<(), Error> { | ||
match self { | ||
Cmd::Inspect(cmd) => cmd.run()?, | ||
Cmd::Sign(cmd) => cmd.run().await?, | ||
Cmd::Send(cmd) => cmd.run().await?, | ||
Cmd::Simulate(cmd) => cmd.run().await?, | ||
}; | ||
Ok(()) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
use soroban_rpc::GetTransactionResponse; | ||
|
||
#[derive(thiserror::Error, Debug)] | ||
pub enum Error { | ||
#[error(transparent)] | ||
XdrArgs(#[from] super::xdr::Error), | ||
#[error(transparent)] | ||
Config(#[from] super::super::config::Error), | ||
#[error(transparent)] | ||
Rpc(#[from] crate::rpc::Error), | ||
} | ||
|
||
#[derive(Debug, clap::Parser, Clone)] | ||
#[group(skip)] | ||
pub struct Cmd { | ||
#[clap(flatten)] | ||
pub xdr_args: super::xdr::Args, | ||
#[clap(flatten)] | ||
pub config: super::super::config::Args, | ||
} | ||
|
||
impl Cmd { | ||
pub async fn run(&self) -> Result<(), Error> { | ||
let response = self.send().await?; | ||
println!("{response:#?}"); | ||
Ok(()) | ||
} | ||
|
||
pub async fn send(&self) -> Result<GetTransactionResponse, Error> { | ||
let txn_env = self.xdr_args.txn_envelope()?; | ||
let network = self.config.get_network()?; | ||
let client = crate::rpc::Client::new(&network.rpc_url)?; | ||
Ok(client.send_transaction(&txn_env).await?) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,97 @@ | ||
use std::io; | ||
|
||
// use crossterm::{ | ||
// event::{self, Event, KeyCode, KeyEvent, KeyModifiers}, | ||
// execute, | ||
// terminal::{self, EnterAlternateScreen, LeaveAlternateScreen}, | ||
// }; | ||
use soroban_sdk::xdr::{self, Limits, TransactionEnvelope, WriteXdr}; | ||
|
||
use crate::signer::{self, InMemory, Stellar}; | ||
|
||
#[derive(thiserror::Error, Debug)] | ||
pub enum Error { | ||
#[error(transparent)] | ||
XdrArgs(#[from] super::xdr::Error), | ||
#[error(transparent)] | ||
Signer(#[from] signer::Error), | ||
#[error(transparent)] | ||
Config(#[from] super::super::config::Error), | ||
#[error(transparent)] | ||
StellarStrkey(#[from] stellar_strkey::DecodeError), | ||
#[error(transparent)] | ||
Xdr(#[from] xdr::Error), | ||
#[error(transparent)] | ||
Io(#[from] io::Error), | ||
#[error("User cancelled signing, perhaps need to add -y")] | ||
UserCancelledSigning, | ||
} | ||
|
||
#[derive(Debug, clap::Parser, Clone)] | ||
#[group(skip)] | ||
pub struct Cmd { | ||
/// Confirm that a signature can be signed by the given keypair automatically. | ||
#[arg(long, short = 'y')] | ||
yes: bool, | ||
#[clap(flatten)] | ||
pub xdr_args: super::xdr::Args, | ||
#[clap(flatten)] | ||
pub config: super::super::config::Args, | ||
} | ||
|
||
impl Cmd { | ||
#[allow(clippy::unused_async)] | ||
pub async fn run(&self) -> Result<(), Error> { | ||
let envelope = self.sign()?; | ||
println!("{}", envelope.to_xdr_base64(Limits::none())?.trim()); | ||
Ok(()) | ||
} | ||
|
||
pub fn sign(&self) -> Result<TransactionEnvelope, Error> { | ||
let source = &self.config.source_account; | ||
tracing::debug!("signing transaction with source account {}", source); | ||
let txn = self.xdr_args.txn()?; | ||
let key = self.config.key_pair()?; | ||
let address = | ||
stellar_strkey::ed25519::PublicKey::from_payload(key.verifying_key().as_bytes())?; | ||
let in_memory = InMemory { | ||
network_passphrase: self.config.get_network()?.network_passphrase, | ||
keypairs: vec![key], | ||
}; | ||
self.prompt_user()?; | ||
Ok(in_memory.sign_txn(txn, &stellar_strkey::Strkey::PublicKeyEd25519(address))?) | ||
} | ||
|
||
pub fn prompt_user(&self) -> Result<(), Error> { | ||
if self.yes { | ||
return Ok(()); | ||
} | ||
Err(Error::UserCancelledSigning) | ||
// TODO use crossterm to prompt user for confirmation | ||
// // Set up the terminal | ||
// let mut stdout = io::stdout(); | ||
// execute!(stdout, EnterAlternateScreen)?; | ||
// terminal::enable_raw_mode()?; | ||
|
||
// println!("Press 'y' or 'Y' for yes, any other key for no:"); | ||
|
||
// loop { | ||
// if let Event::Key(KeyEvent { | ||
// code, | ||
// modifiers: KeyModifiers::NONE, | ||
// .. | ||
// }) = event::read()? | ||
// { | ||
// match code { | ||
// KeyCode::Char('y' | 'Y') => break, | ||
// _ => return Err(Error::UserCancelledSigning), | ||
// } | ||
// } | ||
// } | ||
|
||
// // Clean up the terminal | ||
// terminal::disable_raw_mode()?; | ||
// execute!(stdout, LeaveAlternateScreen)?; | ||
// Ok(()) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
use soroban_rpc::Assembled; | ||
use soroban_sdk::xdr::{self, WriteXdr}; | ||
|
||
#[derive(thiserror::Error, Debug)] | ||
pub enum Error { | ||
#[error(transparent)] | ||
XdrArgs(#[from] super::xdr::Error), | ||
#[error(transparent)] | ||
Config(#[from] super::super::config::Error), | ||
#[error(transparent)] | ||
Rpc(#[from] crate::rpc::Error), | ||
#[error(transparent)] | ||
Xdr(#[from] xdr::Error), | ||
} | ||
|
||
#[derive(Debug, clap::Parser, Clone)] | ||
#[group(skip)] | ||
pub struct Cmd { | ||
#[clap(flatten)] | ||
pub xdr_args: super::xdr::Args, | ||
#[clap(flatten)] | ||
pub config: super::super::config::Args, | ||
} | ||
|
||
impl Cmd { | ||
pub async fn run(&self) -> Result<(), Error> { | ||
let res = self.simulate().await?; | ||
println!("{}", res.transaction().to_xdr_base64(xdr::Limits::none())?); | ||
Ok(()) | ||
} | ||
|
||
pub async fn simulate(&self) -> Result<Assembled, Error> { | ||
let tx = self.xdr_args.txn()?; | ||
let network = self.config.get_network()?; | ||
let client = crate::rpc::Client::new(&network.rpc_url)?; | ||
Ok(client.create_assembled_transaction(&tx).await?) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,67 @@ | ||
use std::{ | ||
io::{stdin, Read}, | ||
path::PathBuf, | ||
}; | ||
|
||
use soroban_env_host::xdr::ReadXdr; | ||
use soroban_sdk::xdr::{Limits, Transaction, TransactionEnvelope}; | ||
|
||
#[derive(Debug, thiserror::Error)] | ||
pub enum Error { | ||
#[error("failed to decode XDR from base64")] | ||
Base64Decode, | ||
#[error("failed to decode XDR from file: {0}")] | ||
FileDecode(PathBuf), | ||
#[error("failed to decode XDR from stdin")] | ||
StdinDecode, | ||
#[error(transparent)] | ||
Io(#[from] std::io::Error), | ||
} | ||
|
||
/// XDR input, either base64 encoded or file path and stdin if neither is provided | ||
#[derive(Debug, clap::Args, Clone)] | ||
#[group(skip)] | ||
pub struct Args { | ||
/// Base64 encoded XDR transaction | ||
#[arg( | ||
long = "xdr-base64", | ||
env = "STELLAR_TXN_XDR_BASE64", | ||
conflicts_with = "xdr_file" | ||
)] | ||
pub xdr_base64: Option<String>, | ||
//// File containing Binary encoded data | ||
#[arg( | ||
long = "xdr-file", | ||
env = "STELLAR_TXN_XDR_FILE", | ||
conflicts_with = "xdr_base64" | ||
)] | ||
pub xdr_file: Option<PathBuf>, | ||
} | ||
|
||
impl Args { | ||
pub fn xdr<T: ReadXdr>(&self) -> Result<T, Error> { | ||
match (self.xdr_base64.as_ref(), self.xdr_file.as_ref()) { | ||
(Some(xdr_base64), None) => { | ||
T::from_xdr_base64(xdr_base64, Limits::none()).map_err(|_| Error::Base64Decode) | ||
} | ||
(_, Some(xdr_file)) => T::from_xdr(std::fs::read(xdr_file)?, Limits::none()) | ||
.map_err(|_| Error::FileDecode(xdr_file.clone())), | ||
|
||
_ => { | ||
let mut buf = String::new(); | ||
let _ = stdin() | ||
.read_to_string(&mut buf) | ||
.map_err(|_| Error::StdinDecode)?; | ||
T::from_xdr_base64(buf.trim(), Limits::none()).map_err(|_| Error::StdinDecode) | ||
} | ||
} | ||
} | ||
|
||
pub fn txn(&self) -> Result<Transaction, Error> { | ||
self.xdr::<Transaction>() | ||
} | ||
|
||
pub fn txn_envelope(&self) -> Result<TransactionEnvelope, Error> { | ||
self.xdr::<TransactionEnvelope>() | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.