Horizon
- provider
- create("horizon")
- auth
- none
- chains
- Stellar
- capabilities
- balance, history, tx detail, tokens, transfers, gas, block
- endpoint
- horizon.stellar.org
- default chain
- stellar
Address it
import { Horizon } from "@agntn/explorers/providers/horizon";
const horizon = new Horizon(); // or create("horizon"), or { baseUrl: "https://my.horizon" }
await horizon.getBalance("GAHK7EEG2WWHVKDNT4CEQFZGKF2LGDSW2IVM4S5DP42RBW3K6BTODB4A", "stellar");
await horizon.getGasData("stellar");
One chain, no key. baseUrl is the Horizon root and defaults to https://horizon.stellar.org, the instance the Stellar Development Foundation runs, which keeps one year of history and nothing older. Point it at any other Horizon if you need the rest. Any other chain is an UnsupportedChainError, and an account id that doesn't pass the Stellar checksum fails before a request goes out. That includes muxed M... addresses, which aren't accounts.
What it reads
| Operation | Route |
|---|---|
| balance | /accounts/{id}, the native entry |
| token holdings | /accounts/{id}, every credit_alphanum4 and credit_alphanum12 trustline |
| history | /accounts/{id}/payments?join=transactions, one row per operation |
| token transfers | the same payments, keeping the rows that moved an issued asset |
| one transaction | /transactions/{hash} plus /transactions/{hash}/operations |
| gas | /fee_stats, in stroops per operation |
| block | /ledgers/{sequence} |
No contracts and no unspent outputs. Soroban state lives behind RPC, not Horizon, and Stellar has accounts, not outputs.
Gotchas
- Stroops, seven decimals, for XLM and for every issued asset alike. Horizon prints amounts as decimal strings like
12.8193804, and the provider turns them into stroops without a float in sight. - An issued asset is
CODE:ISSUER, the SEP-11 spelling, incontracton holdings and transfers and as thetokenfilter. Liquidity pool shares sit in the same balances array and stay out, because a pool share isn't a token anyone sends. - History is Horizon's payments view, not its transactions view, so every row has a sender, a recipient and an amount. That covers payments, path payments, account creations, merges and contract calls that moved an asset. A transaction with a hundred payments in it is a hundred rows sharing one hash, and only a single-operation transaction carries its
feeon the row; the fee belongs to the transaction, andgetTxDetailalways has it. Failed operations come along withstatus: "failed"and no token transfers.rawkeeps the operation record with its joined transaction, memo included. - An account merge is a row with
value: "0", honestly. Horizon doesn't put the merged amount on the operation. limitup to 200 a page,pageup to 10. Horizon pages with cursors, so page 3 costs three requests, andstartBlockorendBlockthrow because there's no ledger filter on an account's payments. Token transfers have no asset filter on Horizon's side either, sogetTokenTransfersscans up to five pages of 200 payments and keeps what moved an issued asset. On a busy account that's the last thousand payments, not all of them.getTxDetailpicks the first payment-like operation as the row and lists every issued-asset movement undertokenTransfers. Soroban operations setisContractInteraction. A transaction that only manages offers or trustlines hasto: nullandvalue: "0".- Gas is
/fee_stats, and only two of its numbers survive the trip.baseFeeis the ledger's base fee.safeGasPriceis the fee most operations were charged over the last five ledgers, 100 stroops until surge pricing kicks in, then whatever the marginal bid was.fastGasPriceis the 95th percentile, and that one is Soroban's: contract calls pay resource fees on top, so it reads as a cap that clears them, not as what a payment costs. There's noproposedGasPrice, because every percentile in between averages a payment with a contract call and means nothing. - A ledger is a block with
txCountcounting successful and failed transactions,baseFeein stroops, an emptyminerand gas fields of"0", like every other chain without gas. getBalancereturns the whole balance, reserve and liabilities included, and the snapshot fields stay null because the account record doesn't say which ledger answered. An account the ledger never funded is a 404 and aNotFoundError, not a zero.- The Explorer has no live feed for Stellar. Search works, the hub says there's no tip.
Where it lives
src/providers/horizon.ts.
dcrdata
Decred through the Insight API of explorer.dcrdata.org. Balances with totals and the mempool delta. History and details and blocks. Atoms. No key.
Chains
The 25 chains the built-in providers serve. Which provider answers for each and which operations any of them cover. Read from the registry and not typed in.