Functions to validate, search and retrieve digital token data sourced from the DTIF registry.
A token is identified by its nine character token identifier
(DTI), which is unique. Short names such as "BTC" and long
names such as "Bitcoin" are informative and are not unique:
the same short name is carried by native tokens on several
chains, by wrapped tokens and by fungible token groups.
validate_token/2, get_token/1 and the other functions that
accept a name resolve it to one token with a documented, stable
precedence; search/1 and search/2 return every token that
carries a name so a caller can choose.
Summary
Types
A digital token may have zero or more short names associated with it. They are arbitrary strings, usually three or four characters in length. For example "BTC", "ETH" and "DOGE".
A mapping from a short name or long name, paired with a token type, to the token identifier that name resolves to for that type.
A mapping of digital token identifiers to a currency symbol for that token.
The structure of data matching that hosted in the DTIF registry/
token_id is a random 9-character string defined by the dtif registry that uniquely identifies a digital token.
A mapping of digital token identifiers to the registry data for that token.
The type of a token
Functions
Returns the registry data for a given token identifier.
Returns the registry data for a given token identifier.
Returns the long name of a digital token.
Returns every token that carries the given short name or long name.
Returns every token of one type that carries the given short name or long name.
Returns the short name of a digital token.
Returns a mapping of digital token short names and long names to digital token identifiers.
Returns a currency symbol used in number formatting.
Returns a mapping of digital token identifiers to a currency symbol.
Returns a map of the digital tokens in the dtif registry.
Validates a token identifier or short name and returns the token identifier or an error.
Types
@type short_name() :: String.t()
A digital token may have zero or 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_map() :: %{required({short_name(), token_type()}) => token_id()}
A mapping from a short name or long name, paired with a token type, to the token identifier that name resolves to for that type.
A mapping of digital token identifiers to a currency symbol for that token.
The structure of data matching that hosted in the DTIF registry/
@type token_id() :: String.t()
token_id is a random 9-character string defined by the dtif registry that uniquely identifies a digital token.
A mapping of digital token identifiers to the registry data for that token.
@type token_type() :: :native | :auxiliary | :distributed | :fungible
The type of a token
Functions
@spec get_token(token_id() | short_name()) :: {:ok, t()} | {:error, {module(), any()}}
Returns the registry data for a given token identifier.
Arguments
idis any token identifier, short name or long name. A name that several tokens carry resolves as described invalidate_token/2; usesearch/1to see every candidate.
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()) :: t() | no_return()
Returns the registry data for a given token identifier.
Arguments
idis any token identifier or short name
Returns
registry_dataorraises 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: %{
.....
Returns the long name of a digital token.
Arguments
token_idis any valid digital token identifier.
Returns
{:ok, long_name}wherelong_nameis the token's registered name.{:error, {exception, reason}}
Examples
iex> DigitalToken.long_name "BTC"
{:ok, "Bitcoin"}
iex> DigitalToken.long_name "4H95J0R2X"
{:ok, "Bitcoin"}
iex> DigitalToken.long_name "TV5T68SZJ"
{:ok, "Terra Classic"}
@spec search(String.t()) :: [{token_id(), token_type()}]
Returns every token that carries the given short name or long name.
Many tokens share a short name. "ETH", for example, names a native token on Ethereum and on each of its layer-two chains, wrapped tokens on other chains, and fungible token groups. This function returns all of them so a caller can choose.
Arguments
nameis a short name (e.g."BTC") or long name (e.g."Bitcoin").
Returns
- A list of
{token_id, dti_type}tuples in resolution order, or an empty list if no tokens match. The first entry is the token thatvalidate_token/2andget_token/1resolve the name to. The order is native before auxiliary before distributed before fungible and, within a type, tokens with a curated symbol before those without, then ascending token identifier.
Examples
iex> DigitalToken.search("Bitcoin") |> hd()
{"4H95J0R2X", :native}
iex> DigitalToken.search("ONT")
[
{"7Z13NV2QM", :auxiliary},
{"R9LRZNL89", :auxiliary},
{"WS6SFQ5D1", :auxiliary},
{"G7LQ0V9FF", :fungible},
{"HJVWQ4S40", :fungible},
{"M2W3DQB67", :fungible}
]
iex> DigitalToken.search("Nothing")
[]
@spec search(String.t(), token_type()) :: [{token_id(), token_type()}]
Returns every token of one type that carries the given short name or long name.
This narrows the result of search/1 when a short name like "ETH"
maps to many tokens across different types.
Arguments
nameis a short name (e.g."BTC") or long name (e.g."Bitcoin").dti_typeis one of:native,:auxiliary,:distributed, or:fungible.
Returns
- A list of
{token_id, dti_type}tuples matching both the name and the type, in the same order assearch/1, or an empty list if no tokens match.
Examples
iex> DigitalToken.search("ETH", :native) |> hd()
{"X9J9K872S", :native}
iex> DigitalToken.search("BTC", :native)
[{"4H95J0R2X", :native}]
iex> DigitalToken.search("ONT", :fungible)
[{"G7LQ0V9FF", :fungible}, {"HJVWQ4S40", :fungible}, {"M2W3DQB67", :fungible}]
iex> DigitalToken.search("Nothing", :native)
[]
Returns the short name of a digital token.
Arguments
token_idis any valid digital token identifier.
Returns
{:ok, short_name}whereshort_nameis either the first short name intoken.informative.short_namesor the token long name if there are no short names.{:error, {exception, reason}}
Examples
iex> DigitalToken.short_name "BTC"
{:ok, "BTC"}
iex> DigitalToken.short_name "4H95J0R2X"
{:ok, "BTC"}
iex> DigitalToken.short_name "TV5T68SZJ"
{:ok, "LUNC"}
@spec short_names() :: short_name_map()
Returns a mapping of digital token short names and long names to digital token identifiers.
Returns
- A map from
{name, dti_type}to the token identifier that name resolves to for that type, following the precedence described invalidate_token/2.
Examples
iex> DigitalToken.short_names() |> Map.fetch!({"BTC", :native})
"4H95J0R2X"
iex> DigitalToken.short_names() |> Map.fetch!({"ONT", :auxiliary})
"7Z13NV2QM"
Returns a currency symbol used in number formatting.
Arguments
token_idis any valid digital token identifier.styleis a number in the range1to4as follows:1is the token's symbol, if it exists2is the token's short name as a proxy for a currency code3is the token's long name4is the token's symbol as a proxy for a narrow currency symbol
Returns
{:ok, symbol}or{:error, {exception, reason}}
Examples
iex> DigitalToken.symbol "BTC", 1
{:ok, "₿"}
iex> DigitalToken.symbol "BTC", 2
{:ok, "BTC"}
iex> DigitalToken.symbol "BTC", 3
{:ok, "Bitcoin"}
iex> DigitalToken.symbol "BTC", 4
{:ok, "₿"}
iex> DigitalToken.symbol "ETH", 4
{:ok, "Ξ"}
iex> DigitalToken.symbol "DOGE", 4
{:ok, "Ð"}
iex> DigitalToken.symbol "DODGY", 4
{:error, {DigitalToken.UnknownTokenError, "DODGY"}}
@spec symbols() :: symbol_map()
Returns a mapping of digital token identifiers to a currency symbol.
Returns
- A map from token identifier to the curated Unicode symbol for that token. Only well-known tokens have an entry.
Examples
iex> DigitalToken.symbols() |> Map.fetch!("4H95J0R2X")
"₿"
iex> DigitalToken.symbols() |> Map.has_key?("7Z13NV2QM")
false
@spec tokens() :: token_map()
Returns a map of the digital tokens in the dtif registry.
Returns
- A map from token identifier to the
t/0registry data for that token.
Examples
iex> DigitalToken.tokens() |> Map.fetch!("4H95J0R2X") |> Map.fetch!(:informative) |> Map.fetch!(:long_name)
"Bitcoin"
iex> DigitalToken.tokens() |> map_size() > 5000
true
@spec validate_token(token_id() | short_name(), Keyword.t()) :: {:ok, token_id()} | {:error, {module(), any()}}
Validates a token identifier or short name and returns the token identifier or an error.
Arguments
idis any token identifier or short name.optionsis a keyword list of options.
Options
:dti_typerestricts a short name or long name lookup to one token type::native,:auxiliary,:distributedor:fungible.
Returns
{:ok, token_id}or{:error, {exception, id}}
Resolving ambiguous names
Short names and long names are not unique in the registry. "ETH",
for example, names a dozen native tokens (Ethereum Ether and one per
layer-two chain) as well as many wrapped and fungible tokens. When
id is not a token identifier, the first entry returned by
search/1 (or by search/2 when :dti_type is given) wins. That
order is native before auxiliary before distributed before fungible
and, within a type, tokens with a curated symbol before those
without, then ascending token identifier. It depends only on the
registry data, so the same name resolves to the same token on every
OTP release. Callers that need a specific token should pass the
token identifier, or choose one from search/1.
Examples
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("ONT")
{:ok, "7Z13NV2QM"}
iex> DigitalToken.validate_token("ONT", dti_type: :fungible)
{:ok, "G7LQ0V9FF"}
iex> DigitalToken.validate_token("BTC", dti_type: :distributed)
{:error, {DigitalToken.UnknownTokenError, "BTC"}}
iex> DigitalToken.validate_token("Nothing")
{:error, {DigitalToken.UnknownTokenError, "Nothing"}}