defmodule Stellar.Horizon.PaymentPaths do @moduledoc """ Exposes functions to interact with Paths in Horizon. You can: * Lists the paths a payment can take based on the amount of an asset you want the recipient to receive. * Lists the paths a payment can take based on the amount of an asset you want to send. Horizon API reference: https://developers.stellar.org/api/aggregations/paths/ """ alias Stellar.Horizon.{Error, Paths, Request, RequestParams} @type args :: Keyword.t() @type opt :: atom() @type path :: String.t() @type resource :: Paths.t() @type response :: {:ok, resource()} | {:error, Error.t()} @endpoint "paths" @doc """ List Payment Paths ## Parameters * `source_account`: The Stellar address of the sender. * `destination_asset` :native or [code: `destination_asset_code`, issuer: `destination_asset_issuer`] * `destination_amount`: The amount of the destination asset that should be received. ## Options * `destination_account`: The Stellar address of the reciever. ## Examples iex> PaymentPaths.list_paths(source_account: "GBRSLTT74SKP62KJ7ENTMP5V4R7UGB6E5UQESNIIRWUNRCCUO4ZMFM4C", destination_asset: :native, destination_amount: 5 ) {:ok, %Paths{records: [%Path{}, ...]}} # list with `destination_account` iex> PaymentPaths.list_paths(source_account: "GBRSLTT74SKP62KJ7ENTMP5V4R7UGB6E5UQESNIIRWUNRCCUO4ZMFM4C", destination_asset: :native, destination_amount: 5, destination_account: "GBRSLTT74SKP62KJ7ENTMP5V4R7UGB6E5UQESNIIRWUNRCCUO4ZMFM4C" ) {:ok, %Paths{records: [%Path{}, ...]}} # list with more options iex> PaymentPaths.list_paths(source_account: "GBRSLTT74SKP62KJ7ENTMP5V4R7UGB6E5UQESNIIRWUNRCCUO4ZMFM4C", destination_asset: [ code: "TEST", issuer: "GA654JC6QLA3ZH4O5V7X5NPM7KEWHKRG5GJA4PETK4SOFBUJLCCN74KQ" ], destination_amount: 5, destination_account: "GBRSLTT74SKP62KJ7ENTMP5V4R7UGB6E5UQESNIIRWUNRCCUO4ZMFM4C" ) {:ok, %Paths{records: [%Path{}, ...]}} """ @spec list_paths(args :: args()) :: response() def list_paths(args \\ []) do destination_asset = RequestParams.build_assets_params(args, :destination_asset) params = args |> Keyword.delete(:destination_asset) |> Keyword.merge(destination_asset) :get |> Request.new(@endpoint) |> Request.add_query(params, extra_params: allowed_query_options(:list_paths)) |> Request.perform() |> Request.results(as: Paths) end @doc """ List Strict Receive Payment Paths ## Parameters Using either `source_account` or `source_assets` as an argument is required for strict receive path payments. * `destination_asset`: :native or [code: `destination_asset_code`, issuer: `destination_asset_issuer`] * `destination_amount`: The amount of the destination asset that should be received. ## Options * `source_account`: The Stellar address of the sender. * `source_assets`: A comma-separated list of assets available to the sender. ## Examples # list with `source_account` iex> PaymentPaths.list_receive_paths(destination_asset: :native, destination_amount: 5, source_account: "GBTKSXOTFMC5HR25SNL76MOVQW7GA3F6CQEY622ASLUV4VMLITI6TCOO" ) {:ok, %Paths{records: [%Path{}, ...]}} # list with `source_assets` iex> PaymentPaths.list_receive_paths(destination_asset: :native, destination_amount: 5, source_assets: :native ) {:ok, %Paths{records: [%Path{}, ...]}} # list with more options iex> PaymentPaths.list_receive_paths(source_assets: "CNY:GAREELUB43IRHWEASCFBLKHURCGMHE5IF6XSE7EXDLACYHGRHM43RFOX", destination_asset: [ code: "BB1", issuer: "GD5J6HLF5666X4AZLTFTXLY46J5SW7EXRKBLEYPJP33S33MXZGV6CWFN" ], destination_amount: 5 ) {:ok, %Paths{records: [%Path{}, ...]}} """ @spec list_receive_paths(args :: args()) :: response() def list_receive_paths(args \\ []) do destination_asset = RequestParams.build_assets_params(args, :destination_asset) params = args |> Keyword.delete(:destination_asset) |> Keyword.merge(destination_asset) :get |> Request.new(@endpoint, path: "strict-receive") |> Request.add_query(params, extra_params: allowed_query_options(:list_receive)) |> Request.perform() |> Request.results(as: Paths) end @doc """ List Strict Send Payment Paths ## Parameters Using either `destination_account` or `destination_assets` as an argument is required for strict send path payments. * `source_asset`: :native or [code: `source_asset_code`, issuer: `source_asset_issuer`] * `source_amount`: The amount of the source asset that should be sent. ## Options * `destination_account`: The Stellar address of the reciever. * `destination_assets`: A comma-separated list of assets that the recipient can receive. ## Examples * list with `destination_account` iex> PaymentPaths.list_send_paths(source_asset: :native, source_amount: 5, destination_account: "GBTKSXOTFMC5HR25SNL76MOVQW7GA3F6CQEY622ASLUV4VMLITI6TCOO" ) {:ok, %Paths{records: [%Path{}, ...]}} * list with `destination_assets` iex> PaymentPaths.list_send_paths(source_asset: :native, source_amount: 5, destination_assets: "TEST:GA654JC6QLA3ZH4O5V7X5NPM7KEWHKRG5GJA4PETK4SOFBUJLCCN74KQ" ) {:ok, %Paths{records: [%Path{}, ...]}} # list with more options iex> PaymentPaths.list_send_paths(destination_account: "GAYOLLLUIZE4DZMBB2ZBKGBUBZLIOYU6XFLW37GBP2VZD3ABNXCW4BVA", source_asset: [ code: "BRL", issuer: "GDVKY2GU2DRXWTBEYJJWSFXIGBZV6AZNBVVSUHEPZI54LIS6BA7DVVSP" ], source_amount: 400 ) {:ok, %Paths{records: [%Path{}, ...]}} """ @spec list_send_paths(args :: args()) :: response() def list_send_paths(args \\ []) do source_asset = RequestParams.build_assets_params(args, :source_asset) params = args |> Keyword.delete(:source_asset) |> Keyword.merge(source_asset) :get |> Request.new(@endpoint, path: "strict-send") |> Request.add_query(params, extra_params: allowed_query_options(:list_send)) |> Request.perform() |> Request.results(as: Paths) end @spec allowed_query_options(opt :: opt()) :: list() defp allowed_query_options(:list_paths) do [ :source_account, :destination_asset_type, :destination_amount, :destination_account, :destination_asset_issuer, :destination_asset_code ] end defp allowed_query_options(:list_receive) do [ :destination_asset_type, :destination_amount, :source_account, :source_assets, :destination_asset_issuer, :destination_asset_code ] end defp allowed_query_options(:list_send) do [ :source_asset_type, :source_amount, :source_asset_issuer, :source_asset_code, :destination_account, :destination_assets ] end end