Multiple requests and error handling using HTTPoison wrappers

Hey all,
Elixir noob here and first time working with external apis with it. I’m using HTTPoison and later plan to use Oban to run things in the background but not entirely sure on the following:

  • How to handle multiple requests?
  • Should I hide away the logic in the HTTPoison.Base wrapper?
  • How to handle errors?

So here’s my code where I’ve inlined some comments to highlight my some of my thoughts.

HTTPoison wrapper:

defmodule Fin.Wallets.Swyftx do
  use HTTPoison.Base

  # Not sure what to return here. The raw response? Just the token? A tuple?
  # What do I do if the response is an error?
  def get_token(api_key) do
    case __MODULE__.post("/auth/refresh/", %{apiKey: api_key}) do
      {:ok, %{body: %{"accessToken" => token}}} -> {:ok, token}
      response -> response
    end

    # alternatively no case needed?
    # {:ok, %{body: %{"accessToken" => token}}} =
    #   __MODULE__.post("/auth/refresh/", %{apiKey: api_key})
    #
    # token
  end

  # Also not sure what to return here. The raw response? Just the token? A tuple?
  # What do I do if the response is an error?
  def get_orders(api_key) do
    {:ok, token} = get_orders(api_key)

    {:ok, %{body: %{"orders" => orders}}} =
      __MODULE__.get("/orders/?limit=-1", Authorization: "Bearer #{token}")

    orders
  end

  # HTTPoison overrides

  def process_request_url(url) do
    "https://api.swyftx.com.au" <> url
  end

  def process_request_headers(headers) do
    ["Content-Type": "application/json"] ++ headers
  end

  def process_request_body(%{} = body) do
    Jason.encode!(body)
  end

  def process_request_body(body) do
    body
  end

  def process_response_body(body) do
    Jason.decode!(body)
  end
end

Context module consuming the HTTPoison wrapper:

defmodule Fin.Wallets do
  import Ecto.Query, warn: false
  alias Fin.Repo

  alias Fin.Wallets.Wallet
  alias Fin.WalletTxns
  alias Fin.Wallets.Swyftx

  # Approach 1
  # Without abstracting away some of the logic. Looks very verbose
  # How should I be handling errors here?
  def sync_swyftx(wallet) do
    {:ok, %{body: %{"access_token" => token}}} =
      Swyftx.post("/auth/refresh/", %{apiKey: wallet.api_key})

    {:ok, %{body: %{"orders" => orders}}} =
      Swyftx.get("/orders/?limit=1", Authorization: "Bearer #{token}")

    # what happens if create_wallet_txn fails? How to handle this?
    Enum.each(orders, fn order ->
      WalletTxns.create_wallet_txn(wallet, order)
    end)
  end

  # Approach 2
  # Abstracting hitting the auth endpoint and functions for each endpoint
  # How shold I be hanlding errors here?
  def sync_swyftx(wallet) do
    orders = Swyftx.get_orders(wallet.api_key)

    # what happens if create_wallet_txn fails? How to handle this?
    Enum.each(orders, fn order ->
      WalletTxns.create_wallet_txn(wallet, order)
    end)
  end
end

Any help appreciated :grimacing: