-
Notifications
You must be signed in to change notification settings - Fork 261
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
"Transaction is outdated" error when running the official transfer example #1921
Comments
This appears to be a ndoe error (see https://github.com/paritytech/polkadot-sdk/blob/2970ab151402a94c146800c769953cf6fdb6ef1d/substrate/primitives/runtime/src/transaction_validity.rs#L108). I think the ususal reason for that is that the transaction is being submitted with a nonce equal to or lower than the current account nonce. Subxt should get the right nonce automatically. Is something else incrementing the account nonce at the same time I wonder, so that there is arace and subxt submits with an outdated one? Does the error happen every time you run the example, and even with a fresh instance of the node started? One way to check the nonce of an account is to use the PJS UI and point it at your local node, ie go to https://polkadot.js.org/apps/?rpc=ws%3A%2F%2F127.0.0.1%3A9944#/runtime and then run the |
Hi, thank you for response. When I executed the following Rust code with a fresh instance of the node started (also with #![allow(missing_docs)]
use subxt::{OnlineClient, PolkadotConfig};
use subxt_signer::sr25519::dev;
#[subxt::subxt(runtime_metadata_path = "metadata.scale")]
pub mod polkadot {}
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
// Create a new API client, configured to talk to Polkadot nodes.
let api = OnlineClient::<PolkadotConfig>::new().await?;
// Build a balance transfer extrinsic.
let dest = dev::bob().public_key().into();
let balance_transfer_tx = polkadot::tx().balances().transfer_allow_death(dest, 10_000);
// Submit the balance transfer extrinsic from Alice, and wait for it to be successful
// and in a finalized block. We get back the extrinsic events if all is well.
let from = dev::alice();
let events = api
.tx()
.sign_and_submit_then_watch_default(&balance_transfer_tx, &from)
.await?
.wait_for_finalized_success()
.await?;
// Find a Transfer event and print it.
let transfer_event = events.find_first::<polkadot::balances::events::Transfer>()?;
if let Some(event) = transfer_event {
println!("Balance transfer success: {event:?}");
}
Ok(())
} First execution:
Second execution:
Execute the following Rust code: use subxt::{OnlineClient, PolkadotConfig};
use subxt_signer::sr25519::dev;
#[subxt::subxt(runtime_metadata_path = "metadata.scale")]
pub mod polkadot {}
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
println!("Starting program...");
let api = OnlineClient::<PolkadotConfig>::new().await?;
println!("API client created successfully");
let dest = dev::bob().public_key().into();
let from = dev::alice();
println!("Building transfer transaction...");
let balance_transfer_tx = polkadot::tx().balances().transfer_allow_death(dest, 10_000);
let block = api.blocks().at_latest().await?;
println!("Current block number: {}", block.number());
println!("Submitting transaction...");
let tx = api
.tx()
.sign_and_submit_then_watch_default(&balance_transfer_tx, &from)
.await?;
println!("Transaction submitted, waiting for confirmation...");
match tx.wait_for_in_block().await {
Ok(in_block) => {
println!("Transaction included in block: {:?}", in_block.block_hash());
match in_block.wait_for_success().await {
Ok(events) => {
println!("Transaction successful!");
if let Some(event) = events.find_first::<polkadot::balances::events::Transfer>()? {
println!("Transfer event: {:?}", event);
}
}
Err(e) => println!("Transaction failed: {:?}", e),
}
}
Err(e) => println!("Failed to get in block: {:?}", e),
}
println!("Program completed");
Ok(())
} The first execution succeeds, with output like this:
The second execution fails, with the following error:
Any insights into this issue would be appreciated. Thanks! |
Additionally, I noticed that during the successful transaction execution, on the Polkadot.js UI at https://polkadot.js.org/apps/?rpc=ws%3A%2F%2F127.0.0.1%3A9944#/runtime, under Alice's account, when checking submit runtime call → accountNonceApi.accountNonce: u32, the nonce increased from 0 to 1. |
Any insights into this issue would be appreciated. Thanks! |
Hey @Erio-Harrison As James said, can you double-check that you don't have any concurrent applications that uses the account "//Alice" that send transactions? However, subxt is using I don't remember how the API looks like like v0.32 but if you update to the latest version you could do something like: let rpc = RpcClient::from_url("ws://localhost:9944".to_string()).await?;
let client = OnlineClient::from_rpc_client(rpc.clone()));
let from = dev::alice();
let dest = dev::bob().public_key().into();
let balance_transfer_tx = polkadot::tx().balances().transfer_allow_death(dest, 10_000);
let nonce = client.rpc().system_account_next_index(signer.account_id()).await?;
let xt_cfg = DefaultExtrinsicParamsBuilder::default().nonce(nonce).build();
let xt = client.tx().create_signed(balance_transfer_tx, &from.into(), xt_cfg).await?;
let events = xt.submit_and_watch().await?.wait_for_finalized_success().await?; Anyway, this should only occur if you concurrent transactions in the tx pool otherwise I have no hunch what's is going on. |
@Erio-Harrison I did the following:
#![allow(missing_docs)]
use subxt::{OnlineClient, PolkadotConfig};
use subxt_signer::sr25519::dev;
#[subxt::subxt(runtime_metadata_path = "../artifacts/polkadot_metadata_full.scale")]
pub mod polkadot {}
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
// Create a new API client, configured to talk to Polkadot nodes.
let api = OnlineClient::<PolkadotConfig>::new().await?;
// Build a balance transfer extrinsic.
let dest = dev::bob().public_key().into();
let balance_transfer_tx = polkadot::tx().balances().transfer_allow_death(dest, 10_000);
// Submit the balance transfer extrinsic from Alice, and wait for it to be successful
// and in a finalized block. We get back the extrinsic events if all is well.
let from = dev::alice();
let events = api
.tx()
.sign_and_submit_then_watch_default(&balance_transfer_tx, &from)
.await?
.wait_for_finalized_success()
.await?;
// Find a Transfer event and print it.
let transfer_event = events.find_first::<polkadot::balances::events::Transfer>()?;
if let Some(event) = transfer_event {
println!("Balance transfer success: {event:?}");
}
Ok(())
} I ran this a few times and didn't run into any issue. This at least tells me that there is something with the |
Thanks a lot. I will try to use different API. |
Thanks a lot. Yeah, the |
Description
When running the balance transfer example from the subxt documentation with a local substrate-contracts-node, I'm consistently receiving a "Transaction is outdated" error. The node is running in dev mode and the metadata is up to date, but the transaction fails to submit.
Environment
Steps to Reproduce
subxt metadata -f bytes > metadata.scale
and either:
subxt metadata --url ws://127.0.0.1:9944 -f bytes > metadata.scale
Error Output
Additional Information
Questions
What I've Tried
The text was updated successfully, but these errors were encountered: