Skip to content

Commit e5c762d

Browse files
authored
refactor: improve tx waiting, fees, and compatibility (#101)
* *Improves tx waiting, fees, and compatibility *Clarifies transaction lifecycle handling so sends can return on submission by default or wait for inclusion or finalization, with more accurate status reporting and safer post-submit behavior. *Improves transfer safety by parsing decimal amounts exactly, estimating fees before send and batch operations, and checking balances against amount, tip, and fee needs to avoid misleading success paths. *Tightens compatibility checks to require matching runtime and transaction versions, updates regeneration guidance and usage docs, and removes wallet debug output while rejecting duplicate developer wallet creation. * *fmt * fix: address Nikolaus PR review comments * *fix cargo audit issue * *Improves transfer validation and address handling *Centralizes balance and fee checks so single and batch transfers report shortages more consistently and avoid duplicated overflow logic. *Adds shared address-to-account conversion for transfer and recovery commands, reducing repeated parsing code and keeping wallet-name resolution consistent. *Refactors transaction status watching into smaller helpers for clearer success and failure handling, and separates finalization from the generic wait flag. * *fmt
1 parent f387b41 commit e5c762d

13 files changed

Lines changed: 1052 additions & 458 deletions

File tree

Cargo.lock

Lines changed: 11 additions & 53 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,6 @@ qp-wormhole-circuit-builder = { version = "2.0.1" }
9898

9999
[dev-dependencies]
100100
tempfile = "3.8.1"
101-
serial_test = "3.1"
102101
qp-poseidon-core = "1.4.0"
103102

104103
# Optimize build scripts and their dependencies in dev mode.

LIBRARY_USAGE.md

Lines changed: 26 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ This document explains how to use `quantus-cli` as a library in your Rust applic
88
[dependencies]
99
quantus-cli = { path = "." } # For local development
1010
# or
11-
quantus-cli = "0.1.0" # When published to crates.io
11+
quantus-cli = "1.3.3" # Replace with the latest published version on crates.io
1212
```
1313

1414
## Basic Usage
@@ -158,7 +158,7 @@ async fn query_balance() -> Result<(), Box<dyn std::error::Error>> {
158158
let storage_addr = api::storage().system().account(subxt_account_id);
159159
let account_info = client.client().storage().at(None).fetch_or_default(&storage_addr).await?;
160160

161-
println!("Balance: {} DEV", account_info.data.free);
161+
println!("Balance (raw units): {}", account_info.data.free);
162162

163163
Ok(())
164164
}
@@ -169,8 +169,9 @@ async fn query_balance() -> Result<(), Box<dyn std::error::Error>> {
169169
```rust
170170
use quantus_cli::{
171171
chain::client::QuantusClient,
172+
cli::common::ExecutionMode,
173+
transfer,
172174
wallet::WalletManager,
173-
AccountId32,
174175
};
175176

176177
async fn send_transaction() -> Result<(), Box<dyn std::error::Error>> {
@@ -181,38 +182,36 @@ async fn send_transaction() -> Result<(), Box<dyn std::error::Error>> {
181182
let wallet_data = wallet_manager.load_wallet("my_wallet", "password")?;
182183
let keypair = wallet_data.keypair;
183184

184-
// Parse recipient address
185+
// Recipient address
185186
let to_address = "qzkeicNBtW2AG2E7USjDcLzAL8d9WxTZnV2cbtXoDzWxzpHC2";
186-
let to_account_id = AccountId32::from_ss58check(to_address)?;
187-
188-
// Create transfer call
189-
use quantus_cli::chain::quantus_subxt::api;
190-
use subxt::tx::TxClient;
191-
192-
let to_account_bytes: [u8; 32] = *to_account_id.as_ref();
193-
let to_subxt_account_id = subxt::utils::AccountId32::from(to_account_bytes);
194-
195-
let transfer_call = api::tx().balances().transfer(
196-
to_subxt_account_id.into(),
197-
1000000000000, // 1 DEV
198-
);
199-
200-
// Submit transaction
201-
let tx_hash = client
202-
.client()
203-
.tx()
204-
.sign_and_submit_then_watch_default(&transfer_call, &keypair)
205-
.await?
206-
.wait_for_finalized_success()
207-
.await?
208-
.extrinsic_hash();
187+
188+
// Submit and wait for inclusion in a best block
189+
let tx_hash = transfer(
190+
&client,
191+
&keypair,
192+
to_address,
193+
1_000_000_000_000, // raw units, e.g. 1 token on a 12-decimal chain
194+
None,
195+
ExecutionMode {
196+
wait_for_transaction: true,
197+
finalized: false,
198+
},
199+
)
200+
.await?;
209201

210202
println!("Transaction hash: {:?}", tx_hash);
211203

212204
Ok(())
213205
}
214206
```
215207

208+
Passing `None` for the tip means no tip is attached. Use `Some(raw_tip)` only when you explicitly want one.
209+
210+
`ExecutionMode` semantics:
211+
- `wait_for_transaction = false`: return after submission (`submitted`)
212+
- `wait_for_transaction = true`: return after best-block inclusion (`included`)
213+
- `finalized = true`: return after finalization (`finalized`); this implies waiting
214+
216215
### Service Architecture
217216

218217
For web services or applications that need to manage multiple wallets:

README.md

Lines changed: 27 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -367,22 +367,35 @@ quantus wallet export --name my_wallet --format mnemonic
367367
### Sending Tokens
368368

369369
```bash
370-
# Simple transfer
370+
# Simple transfer (default: submit and return once the node accepts the extrinsic)
371371
quantus send --from crystal_alice --to <address> --amount 10.5
372372

373-
# With tip for priority
373+
# Wait for inclusion in a best block
374+
quantus send --from crystal_alice --to <address> --amount 10.5 --wait-for-transaction
375+
376+
# Wait for finalization (implies --wait-for-transaction)
377+
quantus send --from crystal_alice --to <address> --amount 10.5 --finalized-tx
378+
379+
# Optional advanced: add a tip to prioritize the transaction
374380
quantus send --from crystal_alice --to <address> --amount 10 --tip 0.1
375381

376382
# With manual nonce
377383
quantus send --from crystal_alice --to <address> --amount 10 --nonce 42
378384
```
379385

386+
Transaction status terms:
387+
- `submitted`: accepted by the node, but not yet known to be in a block
388+
- `included`: observed in a best block
389+
- `finalized`: observed in a finalized block
390+
391+
`--amount` and `--tip` use exact decimal parsing based on the chain's configured decimals. Malformed values, negative values, over-precision, or values that would round to zero are rejected. `--tip` is optional and omitted by default.
392+
380393
---
381394

382395
### Batch Transfers
383396

384397
```bash
385-
# From a JSON file
398+
# From a JSON file (amounts are raw smallest-unit integers)
386399
quantus batch send --from crystal_alice --batch-file transfers.json
387400

388401
# Generate identical test transfers
@@ -509,7 +522,7 @@ quantus call \
509522
| `quantus system --runtime` | Runtime version details |
510523
| `quantus metadata --pallet Balances` | Explore chain metadata |
511524
| `quantus version` | CLI version |
512-
| `quantus compatibility-check` | Check CLI/node compatibility |
525+
| `quantus compatibility-check` | Check CLI/node spec-version and transaction-version compatibility |
513526

514527
---
515528

@@ -820,12 +833,14 @@ The project includes a script to regenerate SubXT types and metadata when the bl
820833
1. **Updates metadata**: Downloads the latest chain metadata to `src/quantus_metadata.scale`
821834
2. **Generates types**: Creates type-safe Rust code in `src/chain/quantus_subxt.rs`
822835
3. **Formats code**: Automatically formats the generated code with `cargo fmt`
836+
4. **Prompts compatibility update**: Reminds you to update the supported runtime/transaction pair in `src/config/mod.rs`
823837

824838
**When to use:**
825839
- After updating the Quantus runtime
826840
- When new pallets are added to the chain
827841
- When existing pallet APIs change
828842
- To ensure CLI compatibility with the latest chain version
843+
- Before updating the `quantus compatibility-check` allowlist
829844

830845
**Requirements:**
831846
- `subxt-cli` must be installed: `cargo install subxt-cli`
@@ -849,7 +864,14 @@ Using node URL: ws://127.0.0.1:9944
849864
Updating metadata file at src/quantus_metadata.scale...
850865
Generating SubXT types to src/chain/quantus_subxt.rs...
851866
Formatting generated code...
867+
Reminder: update src/config/mod.rs with the new compatible spec/transaction version pair.
852868
Done!
853869
```
854870

855-
This ensures the CLI always has the latest type definitions and can interact with new chain features.
871+
After regeneration, re-run:
872+
873+
```bash
874+
quantus compatibility-check --node-url <node>
875+
```
876+
877+
The checked-in compatibility gate now requires both the runtime `spec_version` and `transaction_version` to match a supported pair.

regenerate_metadata.sh

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
#!/bin/bash
2+
set -euo pipefail
23

34
# Default node URL
45
NODE_URL="ws://127.0.0.1:9944"
@@ -32,6 +33,8 @@ echo "Generating SubXT types to src/chain/quantus_subxt.rs..."
3233
subxt codegen --url "$NODE_URL" > src/chain/quantus_subxt.rs
3334

3435
echo "Formatting generated code..."
36+
# Generated SubXT code may require nightly rustfmt.
3537
cargo +nightly fmt -- src/chain/quantus_subxt.rs
3638

37-
echo "Done!"
39+
echo "Reminder: update src/config/mod.rs with the new compatible spec/transaction version pair."
40+
echo "Done!"

0 commit comments

Comments
 (0)