Skip to content

Commit

Permalink
feat: add payment command
Browse files Browse the repository at this point in the history
  • Loading branch information
willemneal committed Aug 19, 2024
1 parent a78d7ab commit 7d92aa0
Show file tree
Hide file tree
Showing 6 changed files with 179 additions and 16 deletions.
35 changes: 33 additions & 2 deletions FULL_HELP_DOCS.md
Original file line number Diff line number Diff line change
Expand Up @@ -1244,13 +1244,14 @@ Create a new transaction

###### **Subcommands:**

* `create-account` — Simulate a transaction envelope from stdin
* `create-account` — Create a new account using another account
* `payment` — Send a payment to an account



## `stellar tx new create-account`

Simulate a transaction envelope from stdin
Create a new account using another account

**Usage:** `stellar tx new create-account [OPTIONS] --source-account <SOURCE_ACCOUNT> --destination <DESTINATION>`

Expand All @@ -1275,6 +1276,36 @@ Simulate a transaction envelope from stdin



## `stellar tx new payment`

Send a payment to an account

**Usage:** `stellar tx new payment [OPTIONS] --source-account <SOURCE_ACCOUNT> --destination <DESTINATION> --amount <AMOUNT>`

###### **Options:**

* `--fee <FEE>` — fee amount for transaction, in stroops. 1 stroop = 0.0000001 xlm

Default value: `100`
* `--cost` — Output the cost execution to stderr
* `--instructions <INSTRUCTIONS>` — Number of instructions to simulate
* `--build-only` — Build the transaction and only write the base64 xdr to stdout
* `--sim-only` — Simulate the transaction and only write the base64 xdr to stdout
* `--rpc-url <RPC_URL>` — RPC server endpoint
* `--network-passphrase <NETWORK_PASSPHRASE>` — Network passphrase to sign the transaction sent to the rpc server
* `--network <NETWORK>` — Name of network to use from config
* `--source-account <SOURCE_ACCOUNT>` — Account that signs the final transaction. Alias `source`. Can be an identity (--source alice), a secret key (--source SC36…), or a seed phrase (--source "kite urban…")
* `--hd-path <HD_PATH>` — If using a seed phrase, which hierarchical deterministic path to use, e.g. `m/44'/148'/{hd_path}`. Example: `--hd-path 1`. Default: `0`
* `--global` — Use global config
* `--config-dir <CONFIG_DIR>` — Location of config directory, default is "."
* `--destination <DESTINATION>` — Account to send to
* `--asset <ASSET>` — Asset to send, default XLM

Default value: `native`
* `--amount <AMOUNT>` — Initial balance of the account, default 1 XLM



## `stellar xdr`

Decode and encode XDR
Expand Down
8 changes: 7 additions & 1 deletion cmd/soroban-cli/src/commands/tx/new/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,23 +3,29 @@ use clap::Parser;
use super::global;

pub mod create_account;
pub mod payment;

#[derive(Debug, Parser)]
pub enum Cmd {
/// Simulate a transaction envelope from stdin
/// Create a new account using another account
CreateAccount(create_account::Cmd),
/// Send a payment to an account
Payment(payment::Cmd),
}

#[derive(thiserror::Error, Debug)]
pub enum Error {
#[error(transparent)]
CreateAccount(#[from] create_account::Error),
#[error(transparent)]
Payment(#[from] payment::Error),
}

impl Cmd {
pub async fn run(&self, global_args: &global::Args) -> Result<(), Error> {
match self {
Cmd::CreateAccount(cmd) => cmd.run(global_args).await?,
Cmd::Payment(cmd) => cmd.run(global_args).await?,
};
Ok(())
}
Expand Down
95 changes: 95 additions & 0 deletions cmd/soroban-cli/src/commands/tx/new/payment.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
use std::{fmt::Debug, str::FromStr};

use clap::{command, Parser};

use soroban_sdk::xdr::{self, Limits, WriteXdr};

use crate::{
commands::{
global, tx,
txn_result::{TxnEnvelopeResult, TxnResult},
NetworkRunnable,
},
config::{self, data, network, secret},
rpc::{self},
tx::builder,
};

#[derive(Parser, Debug, Clone)]
#[group(skip)]
pub struct Cmd {
#[command(flatten)]
pub tx: tx::args::Args,
/// Account to send to
#[arg(long)]
pub destination: String,
/// Asset to send, default XLM
#[arg(long, default_value = "native")]
pub asset: builder::Asset,
/// Initial balance of the account, default 1 XLM
#[arg(long)]
pub amount: i64,
}

#[derive(thiserror::Error, Debug)]
pub enum Error {
#[error(transparent)]
Rpc(#[from] rpc::Error),
#[error(transparent)]
Network(#[from] network::Error),
#[error(transparent)]
Strkey(#[from] stellar_strkey::DecodeError),
#[error(transparent)]
Secret(#[from] secret::Error),
#[error(transparent)]
Config(#[from] config::Error),
#[error(transparent)]
Tx(#[from] tx::args::Error),
#[error(transparent)]
TxBuilder(#[from] builder::Error),
#[error(transparent)]
Data(#[from] data::Error),
#[error(transparent)]
Xdr(#[from] xdr::Error),
#[error(transparent)]
Asset(#[from] builder::asset::Error),
}

impl Cmd {
#[allow(clippy::too_many_lines)]
pub async fn run(&self, global_args: &global::Args) -> Result<(), Error> {
let res = self
.run_against_rpc_server(Some(global_args), None)
.await?
.to_envelope();
if let TxnEnvelopeResult::TxnEnvelope(tx) = res {
println!("{}", tx.to_xdr_base64(Limits::none())?);
};
Ok(())
}
}

#[async_trait::async_trait]
impl NetworkRunnable for Cmd {
type Error = Error;
type Result = TxnResult<()>;

async fn run_against_rpc_server(
&self,
args: Option<&global::Args>,
_: Option<&config::Args>,
) -> Result<TxnResult<()>, Error> {
let tx_build = self.tx.tx_builder().await?;
let destination = stellar_strkey::ed25519::PublicKey::from_str(&self.destination)?;
let op = builder::ops::Payment::new(destination, self.asset.clone(), self.amount)?;

self.tx
.handle_tx(
tx_build.add_operation_builder::<stellar_strkey::ed25519::PublicKey>(op, None),
&args.cloned().unwrap_or_default(),
)
.await?;

Ok(TxnResult::Res(()))
}
}
16 changes: 8 additions & 8 deletions cmd/soroban-cli/src/tx/builder.rs
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
pub mod operations;
pub use operations as ops;
pub use operations::Operation;

pub mod account_id;
pub mod asset;
pub mod muxed_account;
pub use muxed_account::MuxedAccount;
pub mod operations;
pub mod transaction;

pub mod account_id;
pub use account_id::AccountId;

pub mod transaction;
pub use asset::Asset;
pub use muxed_account::MuxedAccount;
pub use operations as ops;
pub use operations::Operation;
pub use transaction::Transaction;

#[derive(thiserror::Error, Debug)]
Expand Down
27 changes: 27 additions & 0 deletions cmd/soroban-cli/src/tx/builder/asset.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
use std::str::FromStr;

use crate::utils::parsing as asset;
use crate::xdr;

#[derive(Clone, Debug)]
pub struct Asset(pub xdr::Asset);

#[derive(thiserror::Error, Debug)]
pub enum Error {
#[error(transparent)]
AssetParsing(#[from] asset::Error),
}

impl FromStr for Asset {
type Err = Error;

fn from_str(value: &str) -> Result<Self, Self::Err> {
Ok(Asset(asset::parse_asset(value)?))
}
}

impl From<Asset> for xdr::Asset {
fn from(builder: Asset) -> Self {
builder.0
}
}
14 changes: 9 additions & 5 deletions cmd/soroban-cli/src/tx/builder/operations/payment.rs
Original file line number Diff line number Diff line change
@@ -1,19 +1,23 @@
use soroban_sdk::xdr::{OperationBody, PaymentOp};

use crate::tx::builder::MuxedAccount;
use crate::tx::builder::{Asset, MuxedAccount};
use crate::xdr;

use super::Operation;

pub struct Payment(pub PaymentOp);

impl Payment {
pub fn new(destination: impl Into<MuxedAccount>, asset: xdr::Asset, amount: i64) -> Self {
Self(PaymentOp {
pub fn new(
destination: impl Into<MuxedAccount>,
asset: Asset,
amount: i64,
) -> Result<Self, super::super::asset::Error> {
Ok(Self(PaymentOp {
destination: destination.into().into(),
asset,
asset: asset.into(),
amount,
})
}))
}
}
impl Operation for Payment {
Expand Down

0 comments on commit 7d92aa0

Please sign in to comment.