X402.Utils (X402 v0.3.3)

Copy Markdown View Source

Shared utility functions for the X402 library.

Centralises helpers for Base64 decoding, map access, decimal parsing, and decimal comparison that are used across payment processing modules.

Summary

Functions

Compares two {value, scale} decimal tuples.

Decodes a Base64 string with or without padding.

Finds the first non-nil value in a list.

Deletes both string and atom versions of a key from a map.

Puts a value into a map, preferring the existing key type (string over atom).

Retrieves a value from a map using either a string or atom key.

Retrieves a nested value from a map using a list of string/atom key pairs.

Parses a decimal value (integer or string) into a {value, scale} tuple where value / 10^scale equals the original number.

Functions

compare_decimal(arg1, arg2)

(since 0.1.0)
@spec compare_decimal(
  {non_neg_integer(), non_neg_integer()},
  {non_neg_integer(), non_neg_integer()}
) ::
  :lt | :eq | :gt

Compares two {value, scale} decimal tuples.

Returns :lt, :eq, or :gt.

Examples

iex> X402.Utils.compare_decimal({10, 1}, {1, 0})
:eq

iex> X402.Utils.compare_decimal({5, 1}, {1, 0})
:lt

iex> X402.Utils.compare_decimal({15, 1}, {1, 0})
:gt

decode_base64(value)

(since 0.1.0)
@spec decode_base64(String.t()) :: {:ok, String.t()} | {:error, :invalid_base64}

Decodes a Base64 string with or without padding.

Examples

iex> X402.Utils.decode_base64("")
{:error, :invalid_base64}

iex> X402.Utils.decode_base64("aGVsbG8=")
{:ok, "hello"}

iex> X402.Utils.decode_base64("not-valid-!!!")
{:error, :invalid_base64}

first_present(list)

(since 0.1.0)
@spec first_present([term()]) :: term() | nil

Finds the first non-nil value in a list.

Examples

iex> X402.Utils.first_present([nil, nil, "found"])
"found"

iex> X402.Utils.first_present([nil, nil])
nil

iex> X402.Utils.first_present([false, "other"])
false

map_delete(map, arg)

(since 0.1.0)
@spec map_delete(
  map(),
  {String.t(), atom()}
) :: map()

Deletes both string and atom versions of a key from a map.

map_put(map, arg, value)

(since 0.1.0)
@spec map_put(map(), {String.t(), atom()}, term()) :: map()

Puts a value into a map, preferring the existing key type (string over atom).

map_value(map, arg)

(since 0.1.0)
@spec map_value(
  map(),
  {String.t(), atom()}
) :: term()

Retrieves a value from a map using either a string or atom key.

Prefers the string key if present, falls back to atom key.

Examples

iex> X402.Utils.map_value(%{"key" => "string_val"}, {"key", :key})
"string_val"

iex> X402.Utils.map_value(%{key: "atom_val"}, {"key", :key})
"atom_val"

iex> X402.Utils.map_value(%{}, {"key", :key})
nil

nested_map_value(map, arg2)

(since 0.1.0)
@spec nested_map_value(map(), [{String.t(), atom()}]) :: term()

Retrieves a nested value from a map using a list of string/atom key pairs.

parse_decimal(value)

(since 0.1.0)
@spec parse_decimal(term()) :: {:ok, {non_neg_integer(), non_neg_integer()}} | :error

Parses a decimal value (integer or string) into a {value, scale} tuple where value / 10^scale equals the original number.

Returns :error for negative integers, non-numeric strings, or strings without a leading digit (e.g. ".5").

Examples

iex> X402.Utils.parse_decimal(42)
{:ok, {42, 0}}

iex> X402.Utils.parse_decimal("12.50")
{:ok, {125, 1}}

iex> X402.Utils.parse_decimal("0.001")
{:ok, {1, 3}}

iex> X402.Utils.parse_decimal(".5")
:error

iex> X402.Utils.parse_decimal("")
:error

iex> X402.Utils.parse_decimal(-1)
:error