MPP.Amount (mpp v0.6.1)

Copy Markdown View Source

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

FunctionArityDescriptionParam Kinds
parse_dollar_amount2Parse a dollar-notation string into {base_units, currency, decimals}.input: value, decimals: value
with_base_units2Apply parse_units to any intent struct's amount field.intent: value, decimals: value
parse_units2Convert 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

parse_dollar_amount(input, decimals)

@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"}
  }
}

parse_units(amount, decimals)

@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]
}

with_base_units(intent, decimals)

@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]
}