Skip to content

Commit

Permalink
quotes API is using UCID instead of symbol
Browse files Browse the repository at this point in the history
  • Loading branch information
bchamagne committed Jan 11, 2024
1 parent 124405a commit 1240826
Show file tree
Hide file tree
Showing 12 changed files with 127 additions and 203 deletions.
29 changes: 15 additions & 14 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,21 +1,22 @@
# ArchethicFrontApiServer

An API server that provides various off-chain resources.
Such as cryptocurrencies prices.
Such as cryptoassets prices.

## Envs

- ARCHETHIC_CMC_PRO_API_KEY: An API key for the CoinMarketCap provider

## Quotes

Cryptocurrencies handled:
Cryptoassets are identified by [Unified Cryptoasset ID (UCID)](https://support.coinmarketcap.com/hc/en-us/articles/20092704479515).
Available cryptoassets in this API:

- bitcoin
- bnb
- eth
- matic
- uco
- uco: 6887
- matic: 3890
- bnb: 1839
- btc: 1
- eth: 1027
- ... more later

Providers requested:
Expand All @@ -25,17 +26,17 @@ Providers requested:

### Latest

Return the latest available quotes from given cryptocurrencies. The result is an aggregate of multiple providers.
Return the latest available quotes from given cryptoassets. The result is an aggregate of multiple providers.
**The values are cached for an entire minute.**

`GET /api/v1/quotes/latest?currency=uco,bitcoin,bnb,matic,eth`
`GET /api/v1/quotes/latest?ucids=6887,1,1027,3890,1839`

```json
{
"bitcoin":46886.44559469423,
"bnb":301.88655780971703,
"eth":2263.032408397367,
"matic":0.790940929057782,
"uco":0.04767200156279931
"1": 46886.44559469423,
"1839": 301.88655780971703,
"1027": 2263.032408397367,
"3890": 0.790940929057782,
"6887": 0.04767200156279931
}
```
19 changes: 12 additions & 7 deletions config/config.exs
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,17 @@ import Config
# to minimize any confusion that may arise from assets that share identical tickers/symbols.
config :archethic_fas,
api_port: 3000,
ucids: %{
uco: 6887,
matic: 3890,
bnb: 1839,
btc: 1,
eth: 1027
}
ucids: [
# uco
6887,
# matic
3890,
# bnb
1839,
# btc
1,
# eth
1027
]

import_config("#{Mix.env()}.exs")
26 changes: 13 additions & 13 deletions lib/archethic_fas/quotes.ex
Original file line number Diff line number Diff line change
@@ -1,24 +1,24 @@
defmodule ArchethicFAS.Quotes do
@moduledoc """
Everything related to crypto assets quotes
Everything related to cryptoassets quotes
"""

alias __MODULE__.Cache
alias __MODULE__.Currency
alias __MODULE__.UCID
alias __MODULE__.Provider.CoinMarketCap

@doc """
Return the latest quotes of given currencies.
Return the latest quotes of given cryptoassets.
Behind a cache.
"""
@spec get_latest(list(Currency.t())) ::
{:ok, %{Currency.t() => float()}} | {:error, String.t()}
def get_latest(currencies) do
@spec get_latest(list(UCID.t())) ::
{:ok, %{UCID.t() => float()}} | {:error, String.t()}
def get_latest(ucids) do
case Cache.get_latest() do
{:ok, all_quotes} ->
{:ok,
Map.filter(all_quotes, fn {currency, _} ->
currency in currencies
Map.filter(all_quotes, fn {ucid, _} ->
ucid in ucids
end)}

{:error, reason} ->
Expand All @@ -27,12 +27,12 @@ defmodule ArchethicFAS.Quotes do
end

@doc """
Return the latest quotes of given currencies.
Return the latest quotes of given cryptoassets
Direct from providers.
"""
@spec fetch_latest(list(Currency.t())) ::
{:ok, %{Currency.t() => float()}} | {:error, String.t()}
def fetch_latest(currencies) do
CoinMarketCap.fetch_latest(currencies)
@spec fetch_latest(list(UCID.t())) ::
{:ok, %{UCID.t() => float()}} | {:error, String.t()}
def fetch_latest(ucids) do
CoinMarketCap.fetch_latest(ucids)
end
end
18 changes: 6 additions & 12 deletions lib/archethic_fas/quotes/cache.ex
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ defmodule ArchethicFAS.Quotes.Cache do
"""

alias ArchethicFAS.Quotes
alias ArchethicFAS.Quotes.Currency
alias ArchethicFAS.Quotes.UCID

use GenServer
require Logger
Expand All @@ -17,20 +17,14 @@ defmodule ArchethicFAS.Quotes.Cache do
GenServer.start_link(__MODULE__, opts, name: __MODULE__)
end

@spec get_latest() :: {:ok, %{Currency.t() => float()}} | {:error, String.t()}
@spec get_latest() :: {:ok, %{UCID.t() => float()}} | {:error, String.t()}
def get_latest() do
case :ets.lookup(@table, :latest) do
[{:latest, value}] ->
value
{:ok, value}

[] ->
case hydrate() do
{:ok, value} ->
value

{:error, _reason} ->
{:error, "Value not cached yet"}
end
hydrate()
end
end

Expand All @@ -45,9 +39,9 @@ defmodule ArchethicFAS.Quotes.Cache do
end

def handle_call(:hydrate, _from, state) do
case Quotes.fetch_latest(Currency.list()) do
case Quotes.fetch_latest(UCID.list()) do
{:ok, result} ->
:ets.insert(@table, {:latest, {:ok, result}})
:ets.insert(@table, {:latest, result})
{:reply, {:ok, result}, state}

e = {:error, reason} ->
Expand Down
70 changes: 0 additions & 70 deletions lib/archethic_fas/quotes/currency.ex

This file was deleted.

6 changes: 3 additions & 3 deletions lib/archethic_fas/quotes/provider.ex
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
defmodule ArchethicFAS.Quotes.Provider do
@moduledoc false

alias ArchethicFAS.Quotes.Currency
alias ArchethicFAS.Quotes.UCID

@callback fetch_latest(list(Currency.t())) ::
{:ok, %{Currency.t() => float()}} | {:error, String.t()}
@callback fetch_latest(list(UCID.t())) ::
{:ok, %{UCID.t() => float()}} | {:error, String.t()}
end
35 changes: 5 additions & 30 deletions lib/archethic_fas/quotes/provider/coin_market_cap.ex
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
defmodule ArchethicFAS.Quotes.Provider.CoinMarketCap do
@moduledoc false

alias ArchethicFAS.Quotes.Currency
alias ArchethicFAS.Quotes.UCID
alias ArchethicFAS.Quotes.Provider

@behaviour Provider
Expand All @@ -11,36 +11,11 @@ defmodule ArchethicFAS.Quotes.Provider.CoinMarketCap do
@doc """
Return the latest quotes of given currencies on this provider
"""
@spec fetch_latest(list(Currency.t())) ::
{:ok, %{Currency.t() => float()}} | {:error, String.t()}
def fetch_latest(currencies) do
ucids = currencies_to_ucids(currencies)
@spec fetch_latest(list(UCID.t())) ::
{:ok, %{UCID.t() => float()}} | {:error, String.t()}
def fetch_latest([]), do: {:ok, %{}}

case do_fetch_latest(ucids) do
{:ok, prices_by_ucid} ->
{:ok, convert_ucids_to_currencies(prices_by_ucid)}

{:error, reason} ->
{:error, reason}
end
end

defp currencies_to_ucids(currencies) do
currencies
|> Enum.map(&Currency.to_ucid/1)
end

defp convert_ucids_to_currencies(map) do
map
|> Enum.map(fn {ucid, usd_price} ->
{Currency.from_ucid(ucid), usd_price}
end)
|> Enum.into(%{})
end

defp do_fetch_latest([]), do: {:ok, %{}}

defp do_fetch_latest(ucids) do
def fetch_latest(ucids) do
query = URI.encode_query(%{id: Enum.join(ucids, ",")})
path = "/v2/cryptocurrency/quotes/latest?#{query}"
opts = [transport_opts: conf(:transport_opts, [])]
Expand Down
15 changes: 15 additions & 0 deletions lib/archethic_fas/quotes/ucid.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
defmodule ArchethicFAS.Quotes.UCID do
@moduledoc false

@ucids Application.compile_env!(:archethic_fas, :ucids)

@type t :: pos_integer()

@doc """
Return all handled ucids
"""
@spec list() :: list(t())
def list() do
@ucids
end
end
Loading

0 comments on commit 1240826

Please sign in to comment.