Current section
Files
Jump to
Current section
Files
lib/digital_token.ex
defmodule DigitalToken do
@moduledoc """
Functions to validate, search and retrieve digital token
data sourced from the [DTIF registry](https://dtif.org).
"""
defstruct [
header: nil,
informative: nil,
metadata: nil,
normative: nil
]
@typedoc """
The structure of data matching that hosted in
the [DTIF registry](https://dtif.org)/
"""
@type t :: %__MODULE__{
header: map(),
informative: map(),
metadata: map(),
normative: map()
}
@typedoc """
token_id is a random 9-character
string defined by the [dtif registry](https://dtif.org)
that uniquely identifies a digital token.
"""
@type token_id :: String.t()
@typedoc """
A digital token may have zero of more short
names associated with it. They are arbitrary
strings, usually three or four characters in
length. For example "BTC", "ETH" and "DOGE".
"""
@type short_name :: String.t()
@typedoc """
A mapping of digital token identifiers
to the registry data for that token.
"""
@type token_map :: %{
token_id() => t()
}
@typedoc """
A mapping from a short name to token
identifier.
"""
@type short_name_map :: %{
short_name() => token_id()
}
@doc """
Returns a map of the digital tokens in the
[dtif registry](https://dtif.org).
"""
@spec tokens :: token_map()
def tokens do
DigitalToken.Data.tokens()
end
@doc """
Returns a mapping of digital token short
names to digital token identifiers.
"""
@spec short_names :: short_name_map()
def short_names do
DigitalToken.Data.short_names()
end
@doc """
Validates a token identifier or short name
and returns the token identifier or an error.
## Arguments
* `id` is any token identifier or short name
## Returns
* `{:ok, token_id}` or
* `{:error, {exception, id}}`
## Example
iex> DigitalToken.validate_token("BTC")
{:ok, "4H95J0R2X"}
iex> DigitalToken.validate_token("Bitcoin")
{:ok, "4H95J0R2X"}
iex> DigitalToken.validate_token "4H95J0R2X"
{:ok, "4H95J0R2X"}
iex> DigitalToken.validate_token("Nothing")
{:error, {DigitalToken.UnknownTokenError, "Nothing"}}
"""
@spec validate_token(token_id() | short_name()) ::
{:ok, token_id()} | {:error, {module(), any()}}
def validate_token(id) do
cond do
Map.has_key?(tokens(), id) ->
{:ok, id}
token = Map.get(short_names(), id) ->
{:ok, token}
id ->
{:error, unknown_token_error(id)}
end
end
@doc """
Returns the registry data for a given token
identifier.
## Arugments
* `id` is any token identifier or short name
## Returns
* `{:ok, registry_data}` or
* `{:error, {exception, id}}`
## Example
DigitalToken.get_token("BTC")
#=> {:ok,
%DigitalToken{
header: %{
dlt_type: :blockchain,
dti: "4H95J0R2X",
dti_type: :native,
template_version: #Version<1.0.0>
},
informative: %{
long_name: "Bitcoin",
public_distributed_ledger_indication: false,
short_names: ["BTC", "XBT"],
unit_multiplier: 100000000,
url: "https://github.com/bitcoin/bitcoin"
},
metadata: %{
.....
"""
@spec get_token(token_id() | short_name()) :: {:ok, t()} | {:error, {module(), any()}}
def get_token(id) do
with {:ok, token} <- validate_token(id) do
{:ok, Map.fetch!(tokens(), token)}
end
end
@doc """
Returns the registry data for a given token
identifier.
## Arugments
* `id` is any token identifier or short name
## Returns
* `registry_data` or
* raises an exception
## Example
DigitalToken.get_token("BTC")
#=> %DigitalToken{
header: %{
dlt_type: :blockchain,
dti: "4H95J0R2X",
dti_type: :native,
template_version: #Version<1.0.0>
},
informative: %{
long_name: "Bitcoin",
public_distributed_ledger_indication: false,
short_names: ["BTC", "XBT"],
unit_multiplier: 100000000,
url: "https://github.com/bitcoin/bitcoin"
},
metadata: %{
.....
"""
@spec get_token!(token_id() | short_name()) :: t() | no_return()
def get_token!(id) do
case get_token(id) do
{:ok, token} -> token
{:error, {exception, id}} -> raise exception, id
end
end
defp unknown_token_error(id) do
{DigitalToken.UnknownTokenError, id}
end
end