diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..b68d3c0 --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2022 Giorgio Azzinnaro + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/README.md b/README.md index 2df2cc7..78b2aae 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,62 @@ # ExTwelveData -**TODO: Add description** +Unofficial Elixir client for [Twelve Data](https://twelvedata.com/). + +Currently, it only covers the real-time prices WebSocket API. + +Happy to accept contributions to support the other endpoints. + +## Usage + +### Real-time prices client + +Twelve Data offers a WebSocket based API for real-time prices[^1]. +ExTwelveData uses the [WebSockex](https://github.com/Azolo/websockex) +library to access this endpoint. +Because of this, the WebSocket client runs as a supervised process. + +The `ExTwelveData.RealTimePrices.Handler` behaviour requires a single callback, +invoked whenever the client receives a price update from Twelve Data. + +```elixir +defmodule Your.Handler do + @behaviour ExTwelveData.RealTimePrices.Handler + + @impl true + def handle_price_update(price) do + # Here you can process inbound price updates + :ok + end +end + +defmodule Your.Application do + use Application + alias ExTwelveData.RealTimePrices + + def start(_type, _args) do + children = [ + {RealTimePrices, name: Your.Name, api_key: "abc", handler: Your.Handler}, + ] + + Supervisor.start_link(children, strategy: :one_for_one) + end +end +``` + +With the process running, you can now subscribe, unsubscribe, and reset the subscriptions. + +```elixir +# Send a list of Twelve Data symbols to subscribe to +ExTwelveData.RealTimePrices.subscribe(Your.Name, ["BTC/USD", "AAPL"]) + +# Use the PID or process name to address the messages +ExTwelveData.RealTimePrices.unsubscribe(Your.Name, ["AAPL"]) + +# This stops listening for all updates, while keeping the client running +ExTwelveData.RealTimePrices.reset(Your.Name) +``` + +The client currently takes care of reconnecting, and sending the heartbeat every 10 seconds. ## Installation @@ -19,3 +75,6 @@ Documentation can be generated with [ExDoc](https://github.com/elixir-lang/ex_do and published on [HexDocs](https://hexdocs.pm). Once published, the docs can be found at . +## Reference + +[^1]: https://twelvedata.com/docs#real-time-price-websocket diff --git a/mix.exs b/mix.exs index cfbec32..8c55eb6 100644 --- a/mix.exs +++ b/mix.exs @@ -7,7 +7,13 @@ defmodule ExTwelveData.MixProject do version: "0.1.0", elixir: "~> 1.13", start_permanent: Mix.env() == :prod, - deps: deps() + description: description(), + package: package(), + deps: deps(), + + # Docs + name: "ExTwelveData", + source_url: "https://github.com/borgoat/ex_twelve_data/" ] end @@ -18,14 +24,27 @@ defmodule ExTwelveData.MixProject do ] end + defp description do + "Elixir client for Twelve Data." + end + + defp package do + [ + licenses: ["MIT"], + links: %{ + "GitHub" => "https://github.com/borgoat/ex_twelve_data/", + "API Documentation - Twelve Data" => "https://twelvedata.com/docs" + } + ] + end + # Run "mix help deps" to learn about dependencies. defp deps do [ {:castore, "~> 0.1.0"}, {:jason, "~> 1.3"}, - {:websockex, "~> 0.4.3"} - # {:dep_from_hexpm, "~> 0.3.0"}, - # {:dep_from_git, git: "https://github.com/elixir-lang/my_dep.git", tag: "0.1.0"} + {:websockex, "~> 0.4.3"}, + {:ex_doc, "~> 0.27", only: :dev, runtime: false} ] end end diff --git a/mix.lock b/mix.lock index 475c074..9a7ec8e 100644 --- a/mix.lock +++ b/mix.lock @@ -1,5 +1,11 @@ %{ "castore": {:hex, :castore, "0.1.17", "ba672681de4e51ed8ec1f74ed624d104c0db72742ea1a5e74edbc770c815182f", [:mix], [], "hexpm", "d9844227ed52d26e7519224525cb6868650c272d4a3d327ce3ca5570c12163f9"}, + "earmark_parser": {:hex, :earmark_parser, "1.4.28", "0bf6546eb7cd6185ae086cbc5d20cd6dbb4b428aad14c02c49f7b554484b4586", [:mix], [], "hexpm", "501cef12286a3231dc80c81352a9453decf9586977f917a96e619293132743fb"}, + "ex_doc": {:hex, :ex_doc, "0.28.5", "3e52a6d2130ce74d096859e477b97080c156d0926701c13870a4e1f752363279", [:mix], [{:earmark_parser, "~> 1.4.19", [hex: :earmark_parser, repo: "hexpm", optional: false]}, {:makeup_elixir, "~> 0.14", [hex: :makeup_elixir, repo: "hexpm", optional: false]}, {:makeup_erlang, "~> 0.1", [hex: :makeup_erlang, repo: "hexpm", optional: false]}], "hexpm", "d2c4b07133113e9aa3e9ba27efb9088ba900e9e51caa383919676afdf09ab181"}, "jason": {:hex, :jason, "1.3.0", "fa6b82a934feb176263ad2df0dbd91bf633d4a46ebfdffea0c8ae82953714946", [:mix], [{:decimal, "~> 1.0 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: true]}], "hexpm", "53fc1f51255390e0ec7e50f9cb41e751c260d065dcba2bf0d08dc51a4002c2ac"}, + "makeup": {:hex, :makeup, "1.1.0", "6b67c8bc2882a6b6a445859952a602afc1a41c2e08379ca057c0f525366fc3ca", [:mix], [{:nimble_parsec, "~> 1.2.2 or ~> 1.3", [hex: :nimble_parsec, repo: "hexpm", optional: false]}], "hexpm", "0a45ed501f4a8897f580eabf99a2e5234ea3e75a4373c8a52824f6e873be57a6"}, + "makeup_elixir": {:hex, :makeup_elixir, "0.16.0", "f8c570a0d33f8039513fbccaf7108c5d750f47d8defd44088371191b76492b0b", [:mix], [{:makeup, "~> 1.0", [hex: :makeup, repo: "hexpm", optional: false]}, {:nimble_parsec, "~> 1.2.3", [hex: :nimble_parsec, repo: "hexpm", optional: false]}], "hexpm", "28b2cbdc13960a46ae9a8858c4bebdec3c9a6d7b4b9e7f4ed1502f8159f338e7"}, + "makeup_erlang": {:hex, :makeup_erlang, "0.1.1", "3fcb7f09eb9d98dc4d208f49cc955a34218fc41ff6b84df7c75b3e6e533cc65f", [:mix], [{:makeup, "~> 1.0", [hex: :makeup, repo: "hexpm", optional: false]}], "hexpm", "174d0809e98a4ef0b3309256cbf97101c6ec01c4ab0b23e926a9e17df2077cbb"}, + "nimble_parsec": {:hex, :nimble_parsec, "1.2.3", "244836e6e3f1200c7f30cb56733fd808744eca61fd182f731eac4af635cc6d0b", [:mix], [], "hexpm", "c8d789e39b9131acf7b99291e93dae60ab48ef14a7ee9d58c6964f59efb570b0"}, "websockex": {:hex, :websockex, "0.4.3", "92b7905769c79c6480c02daacaca2ddd49de936d912976a4d3c923723b647bf0", [:mix], [], "hexpm", "95f2e7072b85a3a4cc385602d42115b73ce0b74a9121d0d6dbbf557645ac53e4"}, }