Robinhood Crypto, behind the DpExchange facade.
⚠️ EXPERIMENTAL
This package has not run in production. While it is 0.x the API may change without a
major version — pin all three segments. Maturity is declared per endpoint through
capabilities/0; do not read this banner as your check.
This module is the entire public API of this package.
This venue has no streaming API, and you cannot tell
Robinhood Crypto publishes no socket. subscribe/2 is served by a REST poll inside this
package, and it delivers the same Core.Types.Quote to the same subscriber as a
WebSocket venue would.
That is the sharpest test in the family of §6.0's claim that both endpoints always exist and a consumer never branches on transport. Before the facade, the absence travelled upward: the collection layer kept a poll set and decided which venues were exempt, and an operations page described these pairs in terms of a socket the venue does not have and has never claimed — sending readers hunting a streaming fault that cannot exist.
coverage/1 reports :internal_poll rather than :stream, which is the one place the
difference is visible — and it is visible as what is arriving, never as how.
Credentials are required for market data
Every Robinhood Crypto call is signed with an Ed25519 key, including the quotes. There is
no anonymous endpoint, so get_price/2 takes credentials:
{:ok, quote} = DpExchange.Robinhood.get_price("BTC-USD", credentials: %{
api_key: "…", private_key: "…"
})You hold the credentials; this package signs one request with them and keeps nothing.
The price is the ask
best_bid_ask returns the prices a taker would actually get. Where the venue sends no
separate price, the ask is used — a real quoted number, and the one a buyer pays. It
is not a mid and not a last trade, so a series built from it sits a spread above a
mid-based series from another venue. bid and ask are both carried; what a price
means is your decision, not this package's.
No candles, no order book, no volume
The venue publishes none of them. get_historical_prices/4, get_order_book/2 and
volume are :unsupported — the venue's shape, not a gap here. Route that work elsewhere
rather than discovering an empty series.
Supervision
children = [{DpExchange.Robinhood, credentials: my_credentials(), symbols: ["BTC-USD"]}]
Summary
Functions
The quote currencies this venue settles in.
Endpoints the venue does not serve, as distinct from ones this package has not ported.
Functions
@spec quotes() :: [String.t()]
The quote currencies this venue settles in.
Endpoints the venue does not serve, as distinct from ones this package has not ported.
Both answer {:error, :not_supported}, and a caller acts the same way on either — but
they mean different things to anyone deciding what to build next, so they are told apart
here rather than flattened into one list.