Current section
Files
Jump to
Current section
Files
lib/terminus.ex
defmodule Terminus do
@moduledoc """
Terminus allows you to crawl and subscribe to Bitcoin transaction events using
[Bitbus](https://bitbus.network) and [Bitsocket](https://bitsocket.network),
and download binary data from [BitFS](https://bitfs.network).
> **terminus** — noun
> * the end of a railway or other transport route, or a station at such a point; a terminal.
> * a final point in space or time; an end or extremity.
Terminus provides a single unified interface for crawling and querying Bitbus,
Bitsocket and BitFS in a highly performant manner. Each request is a `GenStage`
process, enabling you to create powerful concurrent data flows. Terminus may
well be the most powerful way of querying Bitcoin in the Universe!
## Apis
Terminus can be used to interface with the following Planaria Corp APIs.
* [`Bitbus`](`Terminus.Bitbus`) - crawl filtered subsets of **confirmed** Bitcoin transactions in blocks.
* [`Bitsocket`](`Terminus.Bitsocket`) - subscribe to a live, filterable stream of realtime transaction events.
* [`BitFS`](`Terminus.BitFS`) - fetch raw binary data chunks (over 512kb) indexed from all Bitcoin transactions.
### Authentication
Both Bitbus and Bitsocket require a token to authenticate requests. *(The Bitsocket
`listen` API currently doesn't require a token but that is likely to change).*
Currently tokens are free with no usage limits. *(Also likely to change)*
**[Get your Planaria Token](https://token.planaria.network).**
### Query language
Both Bitbus and Bitsocket use the same MongoDB-like query language, known as
[Bitquery](https://bitquery.planaria.network). Terminus allows the optional
use of shorthand queries (just the `q` value).
iex> Terminus.Bitbus.fetch!(%{
...> find: %{ "out.s2" => "1LtyME6b5AnMopQrBPLk4FGN8UBuhxKqrn" },
...> sort: %{ "blk.i": -1 },
...> project: %{ "tx.h": 1 },
...> limit: 5
...> }, token: token)
[
%{"tx" => %{"h" => "fca7bdd7658613418c54872212811cf4c5b4f8ee16864eaf70cb1393fb0df6ca"}},
%{"tx" => %{"h" => "79ae3ca23d1067b9ab45aba7e8ff4de1943e383e9a33e562d5ffd8489f388c93"}},
%{"tx" => %{"h" => "5526989417f28da5e0c99b58863db58c1faf8862ac9325dc415ad4b11605c1b1"}},
%{"tx" => %{"h" => "0bac587681360f961dbccba4c49a5c8f1b6f0bef61fe8501a28dcfe981a920b5"}},
%{"tx" => %{"h" => "fa13a8f0f5688f761b2f34949bb35fa5d6fd14cb3d49c2c1617363b6984df162"}}
]
## Using Terminus
Terminus can be used as a simple client for crawling and querying Bitbus and
Bitsocket APIs, and fetching binary data from BitFS. For simple examples,
refer to the `Terminus.Bitbus`, `Terminus.Bitsocket` and `Terminus.BitFS`
documentation.
### Streams
Most Terminus functions return a streaming `t:Enumerable.t/0` allowing you to
compose data processing pipelines and operations.
iex> Terminus.Bitbus.crawl!(query, token: token)
...> |> Stream.map(&Terminus.BitFS.scan_tx/1)
...> |> Stream.each(&save_to_db/1)
...> |> Stream.run
:ok
### Concurrency
Under the hood, each Terminus request is a `GenStage` producer process, and
the bare [`pid`](`t:pid/0`) can be returned. This allows you to take full
advantage of Elixir's concurrency, by either using with your own `GenStage`
consumers or using a tool like `Flow` to create powerful concurrent pipelines.
# One stream of transactions will be distributed across eight concurrent
# processes for mapping and saving the data.
iex> {:ok, pid} = Terminus.Bitbus.crawl(query, token: token, stage: true)
iex> Flow.from_stages([pid], stages: 8)
...> |> Flow.map(&Terminus.BitFS.scan_tx/1)
...> |> Flow.map(&save_to_db/1)
...> |> Flow.run
:ok
"""
end
defmodule Terminus.Response do
@moduledoc false
@type t :: %__MODULE__{
status: integer,
headers: list,
data: binary
}
defstruct status: nil, headers: [], data: ""
end
defmodule Terminus.Message do
@moduledoc false
@type t :: %__MODULE__{
id: String.t,
event: String.t,
data: binary
}
defstruct id: nil, event: "message", data: ""
end
defmodule Terminus.HTTPError do
@moduledoc false
defexception [:status]
def message(exception),
do: "HTTP Error: #{:httpd_util.reason_phrase(exception.status)}"
end