Skip to content

fix(poller): put transaction fetching behind a source trait - #176

Merged
Valreb001 merged 2 commits into
Tx-wats:mainfrom
ayomidearegbeshola29-dev:docs/issue-4-data-source-abstraction
Sep 30, 2026
Merged

Valreb001 merged 2 commits into
Tx-wats:mainfrom
ayomidearegbeshola29-dev:docs/issue-4-data-source-abstraction

Conversation

@ayomidearegbeshola29-dev

@ayomidearegbeshola29-dev ayomidearegbeshola29-dev commented Sep 29, 2026 •

Copy link
Copy Markdown
Contributor

What

Routes poll_contract through a new TransactionSource trait, with
HorizonSource as the only implementation today, so a Soroban RPC backend can
be added later without touching the polling logic.

Also surfaces Horizon's error body, which was being discarded.

closes #4

Why

Horizon's /accounts/{id} routes only accept G-addresses. A watched contract
(C…) address is rejected with HTTP 400, so the current single source cannot
actually poll a contract. An RPC source is the fix, but it is not a drop-in:
RPC can only enumerate the events a contract emitted, not the transactions it
took part in, so a reverted invocation is invisible to it, and there is no
pagingToken to advance a cursor with. Putting the seam behind a trait first
means that work is additive.

This PR does not fix C-address polling. It makes the limitation a
documented, tested property of one implementation rather than a hard-wired
assumption in the poller.

Error bodies

Horizon explains a rejection in the body, not the status line. That body was
being thrown away, so a rejected contract address logged only HTTP 400 —
indistinguishable from any other 400, and hard to diagnose from the field. It
now reports the offending field and reason:

Horizon returned HTTP 400 Bad Request for https://horizon-testnet.stellar.org/accounts/C…/transactions?…: account_id: Account ID must start with `G` and contain 56 alphanum characters

A rejected contract is counted as a poll failure rather than aborting the
cycle, so the operational symptom is a watch that silently never sees anything.

Also included

An earlier uncommitted fix rode along: include_failed=true on the
transactions request (#2). Without it Horizon omits failed transactions and the
TransactionFailed rule can never fire.

Tests

  • horizon_c_address_rejection_names_the_account_id_field (unit) — pins the
    status and field name from the recorded Horizon response.
  • horizon_rejects_a_contract_address_on_the_accounts_endpoint (integration) —
    replays the recorded 400 and asserts the contract is counted as a poll
    failure, with no transactions or alerts.

cargo test --workspace and workspace clippy are clean.

Follow-up

fetch_soroban_details discards its error body the same way. Left alone here
to keep this change scoped.

Adds TransactionSource with HorizonSource as the only implementation and
routes poll_contract through it, so a Soroban RPC backend can be added later.
Horizon's /accounts/{id} routes only accept G-addresses, so a contract (C...)
address is rejected with HTTP 400; the trait is what lets a second source
replace that without touching poll_contract.

Surface Horizon's error body, which was being discarded. A rejected contract
address used to log only "HTTP 400", indistinguishable from any other 400; it
now reports the offending field and reason, e.g. "account_id: Account ID must
start with `G` and contain 56 alphanum characters". A rejected contract is
counted as a poll failure rather than aborting the cycle, so the operational
symptom is a watch that silently never sees anything.

Carries an earlier uncommitted fix: include_failed=true on the transactions
request (Tx-wats#2). Without it Horizon omits failed transactions and the
TransactionFailed rule can never fire.
@drips-wave

drips-wave Bot commented Sep 29, 2026

Copy link
Copy Markdown

@ayomidearegbeshola29-dev Great news! 🎉 Based on an automated assessment of this PR, the linked Wave issue(s) no longer count against your application limits.

You can now already apply to more issues while waiting for a review of this PR. Keep up the great work! 🚀

Learn more about application limits

@Valreb001
Valreb001 merged commit b8f8d8d into Tx-wats:main Sep 30, 2026
1 of 10 checks passed
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.

Horizon /accounts endpoint does not index Soroban contract (C…) addresses

2 participants