feat: Stellar family support (stellar, stellar-testnet) - #287
Closed
artemrootman wants to merge 11 commits into
Closed
feat: Stellar family support (stellar, stellar-testnet)#287artemrootman wants to merge 11 commits into
artemrootman wants to merge 11 commits into
Conversation
artemrootman
force-pushed
the
arootman/stellar-support
branch
from
July 20, 2026 09:12
bfcfe67 to
5f25d3a
Compare
artemrootman
force-pushed
the
arootman/ton-support
branch
from
July 20, 2026 09:25
3a6f7d8 to
12fc520
Compare
artemrootman
force-pushed
the
arootman/stellar-support
branch
from
July 20, 2026 09:26
5f25d3a to
0f8fbfb
Compare
artemrootman
force-pushed
the
arootman/ton-support
branch
from
July 20, 2026 14:34
12fc520 to
952f1ac
Compare
artemrootman
force-pushed
the
arootman/stellar-support
branch
from
July 20, 2026 14:35
67ad1f7 to
83f763e
Compare
artemrootman
force-pushed
the
arootman/ton-support
branch
from
July 20, 2026 14:45
952f1ac to
030abd6
Compare
Also bumps the public registry submodule to the stellar chain entry (drpcorg/public#239).
The first family with no dshackle surface to inherit - stellar was never actually served by dshackle (dead include-list entry); the method spec is the complete 12-method stellar-rpc (soroban-rpc) JSON-RPC API. - stellar_specific: poll head via getLatestLedger (SCP finality - ledgers are final on close, no reorgs). - stellar_validations: chain validation by getNetwork passphrase (the registry chain-ids ARE the network passphrases; compare is EqualFold because the registry loader lowercases chain-ids globally) and getHealth health mapping - the node polices its own >30s head staleness, data-store bootstrap maps to Syncing. - stellar_labels: stellar-rpc + version truncated at the commit suffix. - stellar_bounds: retention-window bounds from getHealth.oldestLedger as BLOCK+TX (no STATE - stellar-rpc has no historical state at all). - registry: Stellar BlockchainType + factory case + method-spec name; chains.yaml entries come from the drpcorg/public submodule bump (drpcorg/public#239).
Horizon is deprecated by SDF in favor of stellar-rpc, but with no shutdown date, ongoing protocol-compatibility releases (27.0.0 for Protocol 27), and a query surface much of which has NO RPC equivalent (all list-all endpoints, effects, trades, sub-resource joins - the official migration guidance is "use an indexer"). Clients still depend on it, so nodecore serves it. - stellar-horizon method spec: the full public REST surface, 51 path templates on the plain rest connector (no friendbot, no admin endpoints). Horizon errors are RFC-7807 problem+json with the status mirrored in the body - the existing REST error path classifies them as-is and bodies pass through byte-exact. - Deployment modes exactly like TON: split (recommended) - a standalone Horizon upstream (single rest connector) with fully independent accounting - or combined, where accounting follows the primary connector and a warning is logged. - Horizon accounting: head via GET /ledgers?order=desc&limit=1 (hash+sequence; the root endpoint has no ledger hash), health via GET /health (database_connected/core_up/core_synced, core_synced=false maps to Syncing), chain validation via the root network_passphrase, labels from horizon_version, lower bounds from history_elder_ledger - which moves BOTH ways (retention reaper up, db reingest range backfill down) and therefore opts into DecreasingBoundDetector like ripple and the ton v3 indexer. - SSE streaming is out of v1 scope: without the Accept header every endpoint serves plain JSON; documented.
…hile syncing A live Horizon answers /health with HTTP 503 while its captive core is catching up, with the health booleans still in the body. The validator was mapping the transport error straight to Unavailable; now the body is parsed regardless of status so core_synced=false correctly yields Syncing. Caught against our own node during its initial ingest - the unit fixtures had assumed a 200.
…ST upstreams Two generic REST-path bugs exposed by Horizon's form-urlencoded POST /transactions (the first non-JSON REST API in the fleet): - the REST handler rejected any non-empty body that wasn't valid JSON; JSON validity is now only enforced when the Content-Type says or implies JSON, other bodies pass through opaquely. - the connector pre-sets Content-Type: application/json and client headers were Add-ed behind it - upstreams read the first value and answered 415. A client-declared Content-Type now replaces the default. Both re-verified live against our testnet Horizon: POST /transactions and /transactions_async now pass through byte-exact (Horizon's own transaction_malformed 400).
…elf-contained spec wording
artemrootman
force-pushed
the
arootman/stellar-support
branch
from
July 20, 2026 15:03
83f763e to
3cc79d5
Compare
Contributor
Author
|
Superseded by #295 - same diff re-landed onto main (this one was stacked on the ton branch, so the merge target was wrong). |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
Adds the Stellar blockchain family (
BlockchainType = "stellar") served via stellar-rpc (Soroban RPC). The first family with no dshackle surface to inherit — stellar was never actually served by dshackle (its include-list entry references a chain dshackle doesn't know); the method spec is simply the complete 12-method stellar-rpc JSON-RPC API.Design doc:
docs/superpowers/specs/2026-07-18-stellar-support-design.md.Stacked on #286 (ton family). Depends on drpcorg/public#239 — this branch pins the registry submodule to that commit (stellar chain entries, chain-ids = network passphrases); re-pin to the merge commit once it lands.
How
The cleanest family in the stack — standard JSON-RPC 2.0, standard error codes, zero translations:
stellar_specific: poll head viagetLatestLedger(SCP finality — ledgers final on close, no reorgs).stellar_validations: chain validation bygetNetworkpassphrase (the registry chain-ids are the passphrases verbatim; EqualFold compare since the registry loader lowercases chain-ids globally); health viagetHealth— the node polices its own >30s head staleness, so unhealthy arrives as a -32603 error (bootstrap message → Syncing, staleness → Unavailable).stellar_labels:stellar-rpc+ version truncated at the commit suffix (getVersionInfo).stellar_bounds: retention-window bounds fromgetHealth.oldestLedgeras BLOCK+TX — deliberately no STATE bound, stellar-rpc has no historical state at all (getLedgerEntriesis live-only).sendTransactionstays default-dispatch: it's async enqueue with core statuses in the result (PENDING/DUPLICATE/TRY_AGAIN_LATER/ERROR); broadcast with DUPLICATE-as-success reconciliation is a follow-up.Horizon
Also adds Horizon support with TON-style deployment modes (per review discussion): the full 51-template REST surface on the plain
restconnector; split mode = a standalone Horizon upstream with fully independent accounting (head viaGET /ledgers?order=desc&limit=1,GET /healthhealth withcore_synced=false-> Syncing, rootnetwork_passphrasechain validation,horizon_versionlabels,history_elder_ledgerlower bounds with decrease support - the retention reaper moves it up,db reingest rangebackfill moves it down); combined mode = accounting via the primary connector + warning. Horizon SSE streaming is out of v1 scope (plain JSON works untouched). Smoke-validated against public SDF Horizon: 9/9, bounds exactly matching the advertised elder ledger, byte-identical problem+json error passthrough; full corpus against our own Horizon lands once its initial ingest completes.Testing