This document answers one question precisely: which components of the Stellar integration live in this open repository.
Short answer: all of them. Every component involved in discovering, pricing, selecting, executing and tracking a swap runs in this package and is readable here. The SDK talks to the swap providers directly and has no backend of any kind.
| # | Component | Where it runs | Source |
|---|---|---|---|
| 1 | Provider adapters — one per venue | This repo | src/providers/*/index.ts |
| 2 | Quote fetching — the upstream calls | This repo | each adapter + src/providers/http.ts |
| 3 | Quote normalization — venue response → canonical amounts, fees, floors | This repo | each adapter |
| 4 | Route construction — the Route + execution block |
This repo | src/routing/route.ts |
| 5 | Route discovery / provider fan-out | This repo | registry.ts, fanout.ts |
| 6 | Routing / solver logic — route selection | This repo | src/core/selection.ts |
| 7 | Developer-facing SDK | This repo | src/StellarSwapSDK.ts, src/react |
| 8 | Execution — signing, submission, the broker session | This repo | src/execution |
| 9 | Outcome tracking — settled amounts, read from the chain | This repo | src/tracking |
Nothing in this pipeline depends on a hosted service.
Each is a plain getQuote(request, context, signal) => Promise<Route> function. Each also carries
the venue-specific corrections that production use demands — those corrections are the substance of
the integration, and they are documented inline at the point where each applies.
| Provider | Upstream | Execution | Enforced floor | Notable adapter logic |
|---|---|---|---|---|
| STELLARBROKER | GET /quote (unauthenticated) |
interactive WebSocket session | none — live re-quote in session | partner-key gate on commit; trader-only settlement |
| SOROSWAP | POST /quote + /quote/build (bearer key) |
signed Stellar envelope | on-chain, clamped | aqua venue exclusion; price-impact gate; otherAmountThreshold clamp |
| AQUARIUS | POST /find-path/ (public) |
signed Soroban invoke | on-chain out_min |
gross-vs-net fee math; mandatory simulation |
| STELLAR_DEX | Horizon /paths/strict-send |
signed path payment | on-chain destMin |
robustness-weighted path selection |
| NEAR | 1Click /v0/quote |
deposit to address | contractual | catalog resolution; memo-mode deposits |
| AXELAR_ITS | Axelarscan GMP + chain RPC | signed Soroban invoke / EVM tx | 1:1, deterministic | static ITS catalog; dual chain-name encodings |
Three of these carry corrections that change which route wins, and are worth calling out because they are the difference between an adapter and a proxy:
- Soroswap's
aquaexclusion. Soroswap's Aquarius integration ignoresslippageBpsand routes through stale pools that quote far off market while reporting near-zero price impact. Excluding the venue loses nothing: the fan-out carries the direct Aquarius adapter, which prices the same liquidity honestly. - Soroswap's threshold clamp.
otherAmountThresholdcomes back equal toamountOuton some routes — a floor with no buffer. Taken verbatim it would produce a transaction that reverts on any drift, and aminBuyAmountthat reads as fully enforced when it is not. - STELLAR_DEX path selection. Taking the highest-output path loses swaps: thin exotic hops outbid the direct order book at quote time and then evaporate before ledger inclusion. The adapter prefers the fewest-hop path within a tolerance of the best price.
const sdk = new StellarSwapSDK() // no arguments requiredEvery upstream host serves CORS-enabled responses (verified across all six), so the whole stack runs in a browser as well as in Node.
Two upstreams take a key: Soroswap (required) and 1Click (optional, for rate limits). A key placed in a browser bundle is public by construction. The SDK does not pretend otherwise:
- Server-side / trusted environments — pass keys via
credentials. - Public web apps — leave
credentialsunset and pointconfig.fetchat your own proxy, which attaches keys server-side.examples/nextjsuses the demo-onlyNEXT_PUBLIC_form and spells out the route handler to replace it with.
Without a Soroswap key the adapter declines with a clear per-provider error and the other three Stellar providers still serve the pair.
Each provider is followed wherever its truth actually lives:
| Provider | Followed via | Keyed by |
|---|---|---|
| STELLARBROKER / SOROSWAP / AQUARIUS / STELLAR_DEX | Horizon transaction + effects | transaction hash |
| NEAR | 1Click GET /v0/status |
deposit address (+ memo) |
| AXELAR_ITS | Axelarscan GMP searchGMP |
source-chain hash, across two hub hops |
The settled amount is always read, never taken on trust: for a Stellar swap it is summed from
the recipient's account_credited effects in the buy asset, which works uniformly across classic
path payments and Soroban SAC transfers. A successful transaction that decodes no matching credit
reports completion without an amount rather than a false zero.
What a committed route carries for this is a tracking handle built by the adapter that produced
it — the identifiers its venue is keyed by. That handle travels on the route, so tracking needs no
stored record anywhere: sdk.track(route, hash) is enough. A uuid also works for a route
committed by the same SDK instance, but that registry is in-memory; persist the route to survive a
reload.
The one thing a server does that a page cannot is keep polling after the page is gone. For a cross-chain route settling minutes later, persist the handle and resume on the next visit.
One known limitation: StellarBroker may split a large order across several transactions in one ledger, and a single reported hash covers only that transaction's share — so a split fill's tracked amount is a lower bound. The session result carries the true totals.
Three things sit just outside the boundary:
- Fee resolution from a database. Service fees are plain configuration (
serviceFees), defaulting to no fee. The fee math — each venue's mechanism, the gross/net split conventions — is implemented in full; only the question of whose fee applies is left to the caller. - Operational concerns of running a hosted service — sanction haircuts, analytics, metrics counters, swap records, affiliate splits, provider suspension flags. None of them changes which route wins or what it pays out, and a library is the wrong place for them.
- Deposit transaction building for non-Stellar chains. A committed NEAR route returns the full deposit instruction and the connected wallet sends it, because building that transaction for the twenty-odd origin chains NEAR supports is wallet work on those chains rather than a Stellar SDK's remit. Stellar-origin deposits are built here.
One runtime dependency: @stellar/stellar-sdk. React is an optional peer.
That is deliberate, and it is why there is no HTTP client, no EVM library and no vendor SDK here:
the adapters use fetch, speak the 1Click REST contract directly, and rely on a
~60-line ABI encoder for the single EVM call Axelar needs — asserted
against a viem-generated reference vector in test/routing.test.mjs.