stellar / stellar-protocol

Developer discussion about possible changes to the protocol.
518 stars 304 forks source link

SEP-24 improvements #1491

Closed jopmiddelkamp closed 1 month ago

jopmiddelkamp commented 3 months ago

We propose an enhancement to the POST TRANSFER_SERVER_SEP0024/transactions/deposit/interactive endpoint, allowing the definition of delivery_methods to restrict user payment methods, similar to how asset_code operates for specifying asset types.

Current implementation for asset_code: asset_code string The code of the stellar asset the user wants to receive for their deposit with the anchor. The value passed must match one of the codes listed in the /info response’s deposit object. When quote_id is specified, asset_code must match the quote’s buy_asset asset code.
Proposed addition for delivery_method: delivery_method string Specifies the method of delivery for the user’s deposit. The value must match one of the delivery methods listed in the /info response’s deposit object. Possible values include: cash: The deposit will be delivered in cash. bank: The deposit will be transferred to a bank account. This can be ACH, IBAN, PIX, etc. card: The deposit will be made to a prepaid, debit or credit card. crypto: The deposit will be transferred to a specified cryptocurrency wallet. This parameter ensures that the user can only use the specified delivery method for their deposit, similar to how asset_code restricts the asset type. This is particularly useful for anchors that support multiple delivery methods for the same asset.

To support this, we need to extend the /info response with additional data:

{
  "deposit": {
    "USDC": {
      "delivery_methods": {
        "cash": {
          "enabled": true,
          "min_amount": 25.0,
          "max_amount": 1000.0
        },
        "bank": {
          "enabled": true,
          "min_amount": 1.0,
          "max_amount": 10000.0,
          "fee_fixed": 1.0,
          "fee_percent": 1.0
        },
        "card": {
          "enabled": true,
          "min_amount": 1.0,
          "max_amount": 10000.0,
          "min_fee": 1.0,
          "fee_percent": 3.0
        }
      }
    }
  }
}

However, this addition alone isn’t sufficient for many anchors. For instance, some anchors allow users to buy USDC with various local fiat currencies, but the delivery method may vary based on the currency. This creates a scenario where multiple local currency options exist, but only one USDC entry can be specified, limiting the granularity of delivery method options.

For example, card might be supported from USD to USDC but not from ARS to USDC. This indicates that SEP-24 was designed with the assumption that anchors distribute stablecoins primarily in their preferred currency.

Given this limitation, it appears that SEP-24 might not fully accommodate anchors with such diverse setups without introducing breaking changes. To address this, we need to consider:

  1. Modifying SEP-24 to support more granular delivery method configurations based on local currencies.
  2. Developing a new SEP to cater to these requirements without disrupting existing implementations.

We kind of expect something like this for the protocol:

{
  "deposit": [
    {
      "sending_asset": "iso4217:USD",
      "receiving_asset": "stellar:USDC:GA5ZSEJYB37JRC5AVCIA5MOP4RHTM335X2KGX3IHOJAPP5RE34K4KZVN",
      "delivery_methods": {
        "cash": {
          "enabled": true,
          "min_amount": 10.0,
          "max_amount": 1000.0
        },
        "bank": {
          "enabled": true,
          "min_amount": 1.0,
          "max_amount": 10000.0,
          "fee_fixed": 1.0,
          "fee_percent": 1.0
        },
        "card": {
          "enabled": true,
          "min_amount": 1.0,
          "max_amount": 10000.0,
          "min_fee": 1.0,
          "fee_percent": 3.0
        }
      }
    }
  ]
}

To implement this, we propose the following changes to the interactive endpoint to replace asset_code, source_asset, and destination_asset with sending_asset and receiving_asset:

sending_asset string The code of the fiat or cryptocurrency asset the user wants to send for their deposit with the anchor. The value must match one of the sending assets listed in the /info response’s deposit object.
receiving_asset string The code of the Stellar asset the user wants to receive for their deposit with the anchor. The value must match one of the receiving assets listed in the /info response’s deposit object.

Additionally, we would like to include an approximate exchange rate in the /info response to provide users with an estimation of the exchange rate in the deposit/withdrawal option cards:

exchangeRateApproximation string An approximate exchange rate for converting the sending asset to the receiving asset.

This allows users to see a close estimation of the exchange rate before initiating the transaction. To handle more complex fee structures, we propose updating the fee structure to allow for advanced configurations:

fees array An array of fee structures specifying different tiers based on the amount being transferred. Each tier can have a from amount, fee_fixed, and fee_percent. This allows for flexible and complex fee structures to be defined by the anchors.

With these additional improvements, we would expect something like this for the protocol:

{
  "deposit": [
    // Cross currency
    {
      "sending_asset": "iso4217:PHP",
      "receiving_asset": "stellar:USDC:GA5ZSEJYB37JRC5AVCIA5MOP4RHTM335X2KGX3IHOJAPP5RE34K4KZVN",
      "exchange_rate_approximation": "0.017",
      "delivery_methods": {
        "bank": {
          "enabled": true,
          "min_amount": 1.0,
          "max_amount": 10000.0,
          "fees": [
            {
                "from": 0.0,
                "fee_fixed": 1.0,
                "fee_percent": 1.0
            }
          ]
        }
      }
    },
    // Same currency
    {
      "sending_asset": "iso4217:NGNC",
      "receiving_asset": "stellar:NGNC:GASBV6W7GGED66MXEVC7YZHTWWYMSVYEY35USF2HJZBLABLYIFQGXZY6",
      "exchange_rate_approximation": "1",
      "delivery_methods": {
        "bank": {
          "enabled": true,
          "min_amount": 1500.0,
          "max_amount": 15000000.0,
          "fees": [
            {
                "from": 0.0,
                "fee_fixed": 55.0,
                "fee_percent": 1.0
            },
            {
                "from": 65000.0,
                "fee_fixed": 700.0,
                "fee_percent": 0.0
            },
            {
                "from": 220000.0,
                "fee_fixed": 0.0,
                "fee_percent": 0.3
            }
          ]
        }
      }
    }
  ]
}

We seek feedback on whether such changes can be integrated into SEP-24 or if a new SEP should be created to accommodate anchors with varied delivery method requirements based on local fiat currencies. We hope some people will join the conversation on this topic!

edelmann7 commented 3 months ago

I find this proposal as reasonable as we currently rely only on delivery_currency in the case

jopmiddelkamp commented 3 months ago

What do you think about this @JakeUrban?

JakeUrban commented 3 months ago

Hey @jopmiddelkamp, I think we already have solutions to the requirements defined in the issue description.

Because SEP-24 has the interactive web view, all of this can be encompassed in the UX, and we can avoid having to communicate this info via API:

  1. Wallet initiates the deposit using the typical asset_code and optionally source_asset
  2. Wallet opens webview for the user
  3. Anchor uses the webview to do the following: a. asks the user what payment rail they want to use b. provides an estimated or firm exchange rate for the asset pair & selected delivery method c. describes the fees that will be taken for processing the transaction

If we're trying to avoid using the webview for this, anchors can optionally offer a SEP-38 API to expose information about exchange rates, fees, and deliver methods.

Using SEP-38 is a more flexible approach than trying to include exchange rate, min/max amounts, and supported payment rails all via SEP-24's GET /info.

github-actions[bot] commented 2 months ago

This issue is stale because it has been open for 30 days with no activity. It will be closed in 30 days unless the stale label is removed.