Skip to content

Feat/seq bump #1909

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 24 commits into from
Apr 9, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
5c4ae70
Add tx edit subcommand
elizabethengelman Mar 6, 2025
8931ecc
Add tx edit seq-num bump command
elizabethengelman Mar 6, 2025
4dff945
Add tx edit seq-num bump it test
elizabethengelman Mar 6, 2025
06e422f
Factor out an it helper
elizabethengelman Mar 6, 2025
3339591
Merge branch 'main' into feat/seq-bump
elizabethengelman Mar 6, 2025
34ac90b
Apply cargo fmt changes
elizabethengelman Mar 6, 2025
81f531c
Clippy
elizabethengelman Mar 7, 2025
daf06fd
Check in generated docs
elizabethengelman Mar 7, 2025
84c7251
Add bump amount arg
elizabethengelman Mar 7, 2025
9a9e686
Fmt
elizabethengelman Mar 10, 2025
0c833a7
Bump -> increment
elizabethengelman Mar 10, 2025
bd985f2
Generated docs
elizabethengelman Mar 10, 2025
df032d3
Merge branch 'main' into feat/seq-bump
elizabethengelman Mar 11, 2025
a7648d8
Merge branch 'main' into feat/seq-bump
elizabethengelman Mar 11, 2025
4522e20
Merge branch 'main' into feat/seq-bump
elizabethengelman Mar 12, 2025
5ea223e
Implement tx edit seq-num next
elizabethengelman Mar 17, 2025
c6caa65
Move seq-num next to update subcommand
elizabethengelman Mar 17, 2025
b7069b0
Merge branch 'main' into feat/seq-bump
elizabethengelman Mar 17, 2025
e99245c
Update generated docs
elizabethengelman Mar 17, 2025
3a6473c
Cleanup
elizabethengelman Mar 17, 2025
cebc9b8
Merge branch 'main' into feat/seq-bump
elizabethengelman Apr 8, 2025
2dd1a08
Address pr feedback: use tx source acct for seq num
elizabethengelman Apr 8, 2025
3b728ae
Address feedback: update xdr error
elizabethengelman Apr 8, 2025
0897d28
Merge branch 'main' into feat/seq-bump
elizabethengelman Apr 9, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
42 changes: 42 additions & 0 deletions FULL_HELP_DOCS.md
Original file line number Diff line number Diff line change
Expand Up @@ -1575,6 +1575,7 @@ Sign, Simulate, and Send transactions

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

* `update` — Update the transaction
* `edit` — Edit a transaction envelope from stdin. This command respects the environment variables `STELLAR_EDITOR`, `EDITOR` and `VISUAL`, in that order
* `hash` — Calculate the hash of a transaction envelope
* `new` — Create a new transaction
Expand All @@ -1585,6 +1586,47 @@ Sign, Simulate, and Send transactions



## `stellar tx update`

Update the transaction

**Usage:** `stellar tx update <COMMAND>`

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

* `sequence-number` — Edit the sequence number on a transaction



## `stellar tx update sequence-number`

Edit the sequence number on a transaction

**Usage:** `stellar tx update sequence-number <COMMAND>`

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

* `next` — Fetch the source account's seq-num and increment for the given tx



## `stellar tx update sequence-number next`

Fetch the source account's seq-num and increment for the given tx

**Usage:** `stellar tx update sequence-number next [OPTIONS]`

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

* `--rpc-url <RPC_URL>` — RPC server endpoint
* `--rpc-header <RPC_HEADERS>` — RPC Header(s) to include in requests to the RPC provider
* `--network-passphrase <NETWORK_PASSPHRASE>` — Network passphrase to sign the transaction sent to the rpc server
* `-n`, `--network <NETWORK>` — Name of network to use from config
* `--global` — Use global config
* `--config-dir <CONFIG_DIR>` — Location of config directory, default is "."



## `stellar tx edit`

Edit a transaction envelope from stdin. This command respects the environment variables `STELLAR_EDITOR`, `EDITOR` and `VISUAL`, in that order.
Expand Down
8 changes: 4 additions & 4 deletions cmd/crates/soroban-test/tests/it/integration/custom_types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@ use serde_json::json;
use soroban_cli::commands;
use soroban_test::TestEnv;

use crate::integration::util::{deploy_custom, extend_contract};

use super::util::{invoke, invoke_with_roundtrip};
use crate::integration::util::{
deploy_custom, extend_contract, invoke, invoke_with_roundtrip, test_address,
};

fn invoke_custom(e: &TestEnv, id: &str, func: &str) -> assert_cmd::Command {
let mut s = e.new_assert_cmd("contract");
Expand Down Expand Up @@ -241,7 +241,7 @@ async fn account_address(sandbox: &TestEnv, id: &str) {

async fn account_address_with_alias(sandbox: &TestEnv, id: &str) {
let res = invoke(sandbox, id, "addresse", &json!("test").to_string()).await;
let test = format!("\"{}\"", super::tx::operations::test_address(sandbox));
let test = format!("\"{}\"", test_address(sandbox));
assert_eq!(test, res);
}

Expand Down
45 changes: 44 additions & 1 deletion cmd/crates/soroban-test/tests/it/integration/tx.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@ use soroban_cli::assembled::simulate_and_assemble_transaction;
use soroban_cli::xdr::{Limits, ReadXdr, TransactionEnvelope, WriteXdr};
use soroban_test::{AssertExt, TestEnv};

use crate::integration::util::{deploy_contract, DeployKind, DeployOptions, HELLO_WORLD};
use crate::integration::util::{
deploy_contract, test_address, DeployKind, DeployOptions, HELLO_WORLD,
};

pub mod operations;

Expand Down Expand Up @@ -60,6 +62,47 @@ async fn simulate() {
);
}

fn test_tx_string(sandbox: &TestEnv) -> String {
sandbox
.new_assert_cmd("contract")
.arg("install")
.args([
"--wasm",
HELLO_WORLD.path().as_os_str().to_str().unwrap(),
"--build-only",
])
.assert()
.success()
.stdout_as_str()
}

#[tokio::test]
async fn sequence_number_next() {
let sandbox = &TestEnv::new();
let tx_base64 = test_tx_string(sandbox);
let test = test_address(sandbox);
let client = sandbox.network.rpc_client().unwrap();
let test_account = client.get_account(&test).await.unwrap();
let test_account_seq_num = test_account.seq_num.as_ref();

let updated_tx = sandbox
.new_assert_cmd("tx")
.arg("update")
.arg("seq-num")
.arg("next")
.write_stdin(tx_base64.as_bytes())
.assert()
.success()
.stdout_as_str();

let updated_tx_env = TransactionEnvelope::from_xdr_base64(&updated_tx, Limits::none()).unwrap();
let tx = soroban_cli::commands::tx::xdr::unwrap_envelope_v1(updated_tx_env).unwrap();
assert_eq!(
tx.seq_num,
soroban_cli::xdr::SequenceNumber(test_account_seq_num + 1)
);
}

#[tokio::test]
async fn txn_hash() {
let sandbox = &TestEnv::new();
Expand Down
13 changes: 2 additions & 11 deletions cmd/crates/soroban-test/tests/it/integration/tx/operations.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,24 +4,15 @@ use soroban_cli::{
utils::contract_id_hash_from_asset,
xdr::{self, ReadXdr, SequenceNumber},
};

use soroban_rpc::LedgerEntryResult;
use soroban_test::{AssertExt, TestEnv};

use crate::integration::{
hello_world::invoke_hello_world,
util::{deploy_contract, DeployOptions, HELLO_WORLD},
util::{deploy_contract, test_address, DeployOptions, HELLO_WORLD},
};

pub fn test_address(sandbox: &TestEnv) -> String {
sandbox
.new_assert_cmd("keys")
.arg("address")
.arg("test")
.assert()
.success()
.stdout_as_str()
}

fn new_account(sandbox: &TestEnv, name: &str) -> String {
sandbox.generate_account(name, None).assert().success();
sandbox
Expand Down
12 changes: 11 additions & 1 deletion cmd/crates/soroban-test/tests/it/integration/util.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use soroban_cli::{
commands,
xdr::{Limits, WriteXdr},
};
use soroban_test::{TestEnv, Wasm};
use soroban_test::{AssertExt, TestEnv, Wasm};
use std::fmt::Display;

pub const HELLO_WORLD: &Wasm = &Wasm::Custom("test-wasms", "test_hello_world");
Expand Down Expand Up @@ -125,3 +125,13 @@ pub async fn extend(sandbox: &TestEnv, id: &str, value: Option<&str>) {
.assert()
.success();
}

pub fn test_address(sandbox: &TestEnv) -> String {
sandbox
.new_assert_cmd("keys")
.arg("address")
.arg("test")
.assert()
.success()
.stdout_as_str()
}
7 changes: 7 additions & 0 deletions cmd/soroban-cli/src/commands/tx/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,16 @@ pub mod op;
pub mod send;
pub mod sign;
pub mod simulate;
pub mod update;
pub mod xdr;

pub use args::Args;

#[derive(Debug, clap::Subcommand)]
pub enum Cmd {
/// Update the transaction
#[command(subcommand)]
Update(update::Cmd),
/// Edit a transaction envelope from stdin. This command respects the environment variables
/// `STELLAR_EDITOR`, `EDITOR` and `VISUAL`, in that order.
///
Expand Down Expand Up @@ -61,6 +65,8 @@ pub enum Error {
Args(#[from] args::Error),
#[error(transparent)]
Simulate(#[from] simulate::Error),
#[error(transparent)]
Update(#[from] update::Error),
}

impl Cmd {
Expand All @@ -73,6 +79,7 @@ impl Cmd {
Cmd::Send(cmd) => cmd.run(global_args).await?,
Cmd::Sign(cmd) => cmd.run(global_args).await?,
Cmd::Simulate(cmd) => cmd.run(global_args).await?,
Cmd::Update(cmd) => cmd.run(global_args).await?,
};
Ok(())
}
Expand Down
25 changes: 25 additions & 0 deletions cmd/soroban-cli/src/commands/tx/update/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
use super::global;

pub mod sequence_number;

#[derive(Debug, clap::Subcommand)]
pub enum Cmd {
/// Edit the sequence number on a transaction
#[command(subcommand, visible_alias = "seq-num")]
SequenceNumber(sequence_number::Cmd),
}

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

impl Cmd {
pub async fn run(&self, global_args: &global::Args) -> Result<(), Error> {
match self {
Cmd::SequenceNumber(cmd) => cmd.run(global_args).await?,
};
Ok(())
}
}
25 changes: 25 additions & 0 deletions cmd/soroban-cli/src/commands/tx/update/sequence_number/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
use super::global;

mod next;

#[derive(Debug, clap::Subcommand)]
pub enum Cmd {
/// Fetch the source account's seq-num and increment for the given tx
#[command()]
Next(next::Cmd),
}

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

impl Cmd {
pub async fn run(&self, global_args: &global::Args) -> Result<(), Error> {
match self {
Cmd::Next(cmd) => cmd.run(global_args).await?,
};
Ok(())
}
}
75 changes: 75 additions & 0 deletions cmd/soroban-cli/src/commands/tx/update/sequence_number/next.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
use stellar_xdr::curr::MuxedAccount;

use crate::{
commands::{
global,
tx::xdr::{tx_envelope_from_input, Error as XdrParsingError},
},
config::{self, locator, network},
xdr::{self, SequenceNumber, TransactionEnvelope, WriteXdr},
};

#[derive(clap::Parser, Debug, Clone)]
pub struct Cmd {
#[command(flatten)]
pub network: network::Args,
#[command(flatten)]
pub locator: locator::Args,
}

#[derive(thiserror::Error, Debug)]
pub enum Error {
#[error(transparent)]
XdrStdin(#[from] XdrParsingError),
#[error(transparent)]
Xdr(#[from] xdr::Error),
#[error("V0 and fee bump transactions are not supported")]
Unsupported,
#[error(transparent)]
RpcClient(#[from] crate::rpc::Error),
#[error(transparent)]
Config(#[from] config::Error),
#[error(transparent)]
Network(#[from] config::network::Error),
}

impl Cmd {
pub async fn run(&self, global_args: &global::Args) -> Result<(), Error> {
let mut tx = tx_envelope_from_input(&None)?;
self.update_tx_env(&mut tx, global_args).await?;
println!("{}", tx.to_xdr_base64(xdr::Limits::none())?);
Ok(())
}

pub async fn update_tx_env(
&self,
tx_env: &mut TransactionEnvelope,
_global: &global::Args,
) -> Result<(), Error> {
match tx_env {
TransactionEnvelope::Tx(transaction_v1_envelope) => {
let tx_source_acct = &transaction_v1_envelope.tx.source_account;
let current_seq_num = self.current_seq_num(tx_source_acct).await?;
let next_seq_num = current_seq_num + 1;
transaction_v1_envelope.tx.seq_num = SequenceNumber(next_seq_num);
}
TransactionEnvelope::TxV0(_) | TransactionEnvelope::TxFeeBump(_) => {
return Err(Error::Unsupported);
}
};
Ok(())
}

async fn current_seq_num(&self, tx_source_acct: &MuxedAccount) -> Result<i64, Error> {
let network = &self.network.get(&self.locator)?;
let client = network.rpc_client()?;
client
.verify_network_passphrase(Some(&network.network_passphrase))
.await?;

let address = tx_source_acct.to_string();

let account = client.get_account(&address).await?;
Ok(*account.seq_num.as_ref())
}
}
Loading