Skip to content

[mkdocs] docs: add monitoring status tutorial#890

Open
zero4862 wants to merge 1 commit into
NemProject:new-docsfrom
zero4862:docs-query-unconfirmed-txs
Open

[mkdocs] docs: add monitoring status tutorial#890
zero4862 wants to merge 1 commit into
NemProject:new-docsfrom
zero4862:docs-query-unconfirmed-txs

Conversation

@zero4862

@zero4862 zero4862 commented Jun 10, 2026

Copy link
Copy Markdown

Adapts the Symbol Monitoring Transaction Status tutorial to NEM.

The resulting tutorial is substantially different from Symbol.

NEM validates transactions at announcement time, so most rejections surface directly in the announce response. Then, tracking if confirmed is more or less trivial with the /transaction/get endpoint.

However, if the transaction does not get confirmed, tracking its status if far more complex than Symbol, because:

  • There is no endpoint to know if a transaction left the unconfirmed pool.
  • /account/unconfirmedTransactions returns at most the 25 most recent entries per address, with no pagination, leading to probable false negatives.
  • /account/unconfirmedTransactions response omits transaction hashes, so entries must be matched by signature.

For these reasons, the tutorial focuses on explaining the confirmation flow and the mechanisms NEM does provide, rather than offering a complete reusable status function. The two takeaways for readers are how to detect that a transaction is confirmed or still pending to be processed, and how to decide that it will not be longer be confirmed (its deadline has passed, so it can never be included in a block).

@zero4862 zero4862 requested a review from segfaultxavi June 10, 2026 16:52

@segfaultxavi segfaultxavi left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A few comments... and a request to rewrite the code :D

## Full Code

This tutorial uses polling to check the transaction status.
Polling is used here for illustration purposes, but it is not the recommended approach for production applications.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So what is the recommended approach? If NEM doesn't have WebSockets (I don't know) then maybe this whole paragraph can be removed.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yep, copy and paste mistake. Need to double-check that NEM actually supports WebSockets, though to add a link to the websocket tutorial or I'll remove it.

tutorial_level: beginner
---

# Monitoring Transaction Status

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why did you rewrite this intro? Wouldn't it be faster to adapt the Symbol one?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wanted to stress this part, which differs from Symbol:

An invalid transaction never gets that far: the receiving node: rejects it immediately when announced, as shown in the
Transfer XEM tutorial.

Also, the process is not as deterministic as in Symbol (where we check how it goes through unconfirmed to confirmed). In this case, they can see if a transaction is confirmed, and if not, know how to check if there is still a chance it can get confirmed.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm thinking I can make it a bit shorter and move as as a note that transactions are rejected when they are announced when explaining the code.

[Transfer XEM tutorial](./transfer-xem.md#announcing-the-transaction).

Acceptance is not confirmation, though.
The network exposes the transaction's progress but does not push it to the sender, so applications that need to react to

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"Push it" is a bit confusing here. Push the transaction to the sender? But isn't the sender the one that sent the transaction?
Maybe say that the network does not keep the sender informed?

@zero4862 zero4862 Jun 11, 2026

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

push the progress*. I will rewrite this part.

# [>step-4]
if wait_for_transaction_confirmation(transaction_hash):
print("\nTransaction confirmed!")
elif is_in_unconfirmed_pool(transaction_signature, signer_address):

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see what you did here. On Symbol, the same endpoint tells us confirmed/error/pending, but on NEM you need to check two endpoints.
Still, it's weird that we wait 2 minutes before checking if the tx is in the unconfirmed pool.
Because if it's not in the pool and it's not confirmed, we can already exit.

I would do something like

  • Confirmed? -> Report confirmed and exit
  • Not in the pool? -> Report not found and exit
  • Wait for confirmation.

So maybe take the loop out of wait_for_transaction_confirmation so you can call the function both in the initial check and later in the loop.

Or you can call is_in_unconfirmed_pool before waiting for the first time inside the loop, for an early exit.

If you do any of these changes you'll need to adapt the text, of course.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Valid point, I'll go with your first suggestion

Comment on lines +80 to +81
For long-term lookups, store `meta.height` on confirmation and fetch the block by height via
<post:/block/at/public>.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is an important message, I would emphasize it. Something like:

Transactions older than this retention span can only be recovered directly from the block in which they are confirmed.
If you submit a transaction that needs to be recovered much later, it is advised to store its confirmation block height along with their hash.
Otherwise, all blocks in the blockchain will need to be recovered searching for the transaction.

And then you add implementation details like the POST query.
You should also check with the team if my understanding is correct 😅

The function returns:

* `True`: the transaction is still in the unconfirmed pool, waiting for a block.
* `False`: the transaction is not in the response, because it has not arrived at this node yet, because it was dropped

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Or because it has already been confirmed (is this what "dropped from the pool" means?).
This case does not apply to your current implementation, but it does in the general case.


!!! warning "The pool view is capped at 25 entries"

The endpoint returns at most the 25 most recent entries involving the address.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We need to be clear here: the endpoint only returns 25 entries, or the pool can only hold 25 pending transactions?
The next sentence says that the tx remains in the pool, but the previous one seemed to suggest the tx was pushed out of the pool.

Incoming transactions count toward this cap too, so on a busy account the monitored transaction can drop out of
the response while it is still in the pool.

??? info "Alternative: hash-based matching"

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are we sure it is worth describing this method?
It looks very convoluted.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll drop it. I thought it was useful in case you have only the tx hash (common case), but without a code example it's confusing more than helping. And adding a code example is too much without a helper in the SDK that does the conversion from API response to serialized TX.

confirmation, {{ tutorial.var('is_in_unconfirmed_pool') }} diagnoses whether the transaction is still in the unconfirmed
pool.

!!! note "Detecting rejected transactions"

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is something weird about this box.

  • Why would a tx be dropped from a node and not from the rest?
  • The info about the deadline being the definitive verdict is interesting.
  • But why would you re-announce the same transaction if it has already been rejected once? Raising the fee does not help on NEM, does it?

So, I'm not understanding what idea you want to transmit here.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I want to transmit that, in NEM, if a transaction was not rejected on announcement, the only way to ensure it will never get confirmed is to wait until its deadline passes.

Why would a tx be dropped from a node and not from the rest?

Since each node has its own unconfirmed pool, I can imagine several (uncommon) scenarios where one node drops a tx while others keep it:

  • a node restarts and comes back with an empty unconfirmed pool
  • a node decides to reject all transactions coming from account X
  • a node is under attack and has too many unconfirmed transactions to process
  • ...

But why would you re-announce the same transaction if it has already been rejected once?

For example: a tx reaches a node and passes validation, but the node hangs and fails to propagate it.

Or, a tx that transfers XEM passes validation, but then a second tx that empties the account, announced to another node, gets processed first, so during revalidation the first one has to be dropped from the pool.

In both cases the tx itself is still valid, so re-announcing them can succeed (in the second case, the account needs to receive more XEM first).

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll review how can I transmit this idea clearly.

--8<-- 'devbook/transactions/monitoring_status.log'
```

The output shows:

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think adding line numbers to the output, highlighting lines, and referencing them from the text is clearer, even in this small output :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants