Amount and decimal helpers for converting human-readable amounts to base units.
All arithmetic is pure integer/string manipulation — no floating point. This
matches the mpp-rs parse_units and parse_dollar_amount implementations.
Examples
iex> MPP.Amount.parse_units("1.5", 6)
{:ok, "1500000"}
iex> MPP.Amount.parse_units("0.10", 6)
{:ok, "100000"}
iex> MPP.Amount.parse_dollar_amount("$1.50", 2)
{:ok, {"150", "usd", 2}}API Functions
| Function | Arity | Description | Param Kinds |
|---|---|---|---|
parse_dollar_amount | 2 | Parse a dollar-notation string into {base_units, currency, decimals}. | input: value, decimals: value |
with_base_units | 2 | Apply parse_units to any intent struct's amount field. | intent: value, decimals: value |
parse_units | 2 | Convert a human-readable amount to base units by scaling with 10^decimals. | amount: value, decimals: value |
Summary
Functions
Parse a dollar-notation string into {base_units, currency, decimals}.
Convert a human-readable amount to base units by scaling with 10^decimals.
Apply parse_units to any intent struct's amount field.
Functions
@spec parse_dollar_amount(String.t(), non_neg_integer()) :: {:ok, {String.t(), String.t(), non_neg_integer()}} | {:error, atom() | {atom(), String.t()}}
@spec parse_dollar_amount(term(), term()) :: {:error, :invalid_input}
Parse a dollar-notation string into {base_units, currency, decimals}.
Parameters
input- Dollar string like "$1.50", "€0.10", or "1.50 USD" (value)decimals- Number of decimal places for the currency (caller-supplied, not inferred from currency code) (value)
Returns
{:ok, {base_units, currency, decimals}} where currency is lowercase 3-letter code (tuple)
# descripex:contract
%{
params: %{
decimals: %{
description: "Number of decimal places for the currency (caller-supplied, not inferred from currency code)",
kind: :value
},
input: %{
description: "Dollar string like \"$1.50\", \"€0.10\", or \"1.50 USD\"",
kind: :value
}
},
returns: %{
type: :tuple,
description: "{:ok, {base_units, currency, decimals}} where currency is lowercase 3-letter code",
example: %{decimals: 2, currency: "usd", base_units: "150"}
}
}
@spec parse_units(String.t(), non_neg_integer()) :: {:ok, String.t()} | {:error, atom() | {atom(), String.t()}}
@spec parse_units(term(), term()) :: {:error, :invalid_input}
@spec parse_units(term(), term()) :: {:error, :invalid_input}
Convert a human-readable amount to base units by scaling with 10^decimals.
Parameters
amount- Human-readable amount string (e.g., "1.5", "100", "0.001") (value)decimals- Number of decimal places for the token (e.g., 6 for USDC, 18 for ETH) (value)
Returns
{:ok, base_units_string} or {:error, reason} (tuple)
Composes With
with_base_units
# descripex:contract
%{
params: %{
decimals: %{
description: "Number of decimal places for the token (e.g., 6 for USDC, 18 for ETH)",
kind: :value
},
amount: %{
description: "Human-readable amount string (e.g., \"1.5\", \"100\", \"0.001\")",
kind: :value
}
},
returns: %{
type: :tuple,
description: "{:ok, base_units_string} or {:error, reason}",
example: "1500000"
},
composes_with: [:with_base_units]
}
@spec with_base_units(map(), non_neg_integer()) :: {:ok, map()} | {:error, atom() | {atom(), String.t()}}
Apply parse_units to any intent struct's amount field.
Parameters
intent- Intent struct (Charge, Session, etc.) with an :amount field (value)decimals- Number of decimal places for the token (value)
Returns
{:ok, updated_intent} with amount in base units, or {:error, reason} (tuple)
Composes With
parse_units
# descripex:contract
%{
params: %{
decimals: %{
description: "Number of decimal places for the token",
kind: :value
},
intent: %{
description: "Intent struct (Charge, Session, etc.) with an :amount field",
kind: :value
}
},
returns: %{
type: :tuple,
description: "{:ok, updated_intent} with amount in base units, or {:error, reason}"
},
composes_with: [:parse_units]
}