# `MPP.Client.MultiProvider`
[🔗](https://github.com/ZenHive/mpp/blob/v0.10.0/lib/mpp/client/multi_provider.ex#L1)

Wraps multiple payment providers and dispatches to the first match.

`MultiProvider` holds a list of `{module, config}` tuples, each implementing
`MPP.Client.PaymentProvider`. When `pay/2` is called, it iterates through
providers and delegates to the first whose `supports?/3` returns `true`.

## Usage

    provider = MPP.Client.MultiProvider.new([
      {MyApp.TempoProvider, %{rpc_url: "https://rpc.tempo.xyz", private_key: key}},
      {MyApp.StripeProvider, %{api_key: "sk_test_..."}}
    ])

    # Dispatches to TempoProvider for tempo challenges, StripeProvider for stripe
    {:ok, credential} = MPP.Client.MultiProvider.pay(provider, challenge)

## Design

Providers are tried in order — the first that supports the challenge's
method+intent wins. This means provider ordering matters when multiple
providers support the same method+intent (first wins).

## API Functions
| Function | Arity | Description | Param Kinds |
| --- | --- | --- | --- |
| `pay` | 2 | Execute payment by dispatching to the first matching provider. | `multi: value`, `challenge: value` |
| `supports?` | 3 | Check if any provider in this MultiProvider supports the method+intent. | `multi: value`, `method: value`, `intent: value` |
| `add` | 3 | Add a provider to an existing MultiProvider. | `multi: value`, `module: value`, `config: value` |
| `new` | 1 | Create a MultiProvider from a list of {module, config} tuples. | `providers: value` |

# `provider_entry`

```elixir
@type provider_entry() :: {module(), map()}
```

# `t`

```elixir
@type t() :: %MPP.Client.MultiProvider{providers: [provider_entry()]}
```

# `add`

```elixir
@spec add(t(), module(), map()) :: t()
```

Add a provider to an existing MultiProvider.

New providers are appended to the end of the list (lower priority than existing).

# `new`

```elixir
@spec new([provider_entry()]) :: t()
```

Create a MultiProvider from a list of `{module, config}` tuples.

Each module must implement the `MPP.Client.PaymentProvider` behaviour.

# `pay`

```elixir
@spec pay(t(), MPP.Challenge.t()) :: {:ok, MPP.Credential.t()} | {:error, term()}
```

Execute payment by dispatching to the first matching provider.

Iterates through providers in order, delegating to the first whose
`supports?/3` returns `true` for the challenge's method and intent.

Returns `{:error, :unsupported_payment_method}` if no provider matches.

# `supports?`

```elixir
@spec supports?(t(), String.t(), String.t()) :: boolean()
```

Check if any provider in this MultiProvider supports the method+intent.

---

*Consult [api-reference.md](api-reference.md) for complete listing*
