interledger / rafiki

An open-source, comprehensive Interledger service for wallet providers, enabling them to provide Interledger functionality to their users.
https://rafiki.dev/
Apache License 2.0
226 stars 77 forks source link

Cannot send from asset scale 2 to asset scale 9 #2747

Closed mkurapov closed 4 weeks ago

mkurapov commented 1 month ago

Context

We are unable to send payments between asset scale 2 and asset scale 9 wallet addresses. This is because of how we are storing the results of the ilp quote exchange rates in the DB.

First, the ILP pay library starts the rate probe from 10^12 value packets: https://github.com/interledgerjs/interledgerjs/blob/9b740a831c5221172230dfb43d0f5198d3b56848/packages/pay/src/senders/rate-probe.ts#L35

and because the resulting exchange rate ends up being 1.00^7, ie 1^(9-2), we try to store 10000000000000000001 as the value for highEstimatedExchangeRate in the DB, and end up failing because highEstimatedExchangeRateNumerator (just like all of the other *numerator/denominator fields in the quotes table) is a type of bigint, with a max value of 9223372036854775807.

Additional details from @raducristianpopa's document:

I tried sending money from asset scale 2 to asset scale 9.

In WM, the extension/browser implementation should be able to send money without worrying about the scale and it just needs to make some adjustments. What I am currently testing with: Rate of pay (USD/h): $0.60/h Connected wallet address: USD, asset scale 2 Monetization link href (wallet address in a webpage): USD, asset scale 9

Since the connected wallet cannot send a payment every second (0.60 / 3600s = 0.000166…..), we need to adjust the amount that needs to be sent. The minimum amount for this use-case is 1 unit of asset scale 2 ($0.01), to which we add another unit, because @interledger/pay subtracts 1 unit when using a debit amount.

With the mentions from above we have: Minimum amount: $0.02 - 2 units in asset scale 2 Interval: not really important for the current issue, but it needs to be adjusted as well

Now, since we know how much we need to send through WM we can proceed by creating the quote + outgoing payment. When creating the quote, the debit amount is:

debitAmount: {
  value: "2",
  assetCode: "USD",
  assetScale: 2
}

But … when making the POST request to create it, I am getting back an Internal Server Error. When inspecting the logs, I see the following error:

…
{"type":"DataError","message":"insert into \"quotes\" (\"additionalFields\", \"assetId\", \"client\", \"debitAmountValue\", \"estimatedExchangeRate\", \"expiresAt\", \"feeId\", \"highEstimatedExchangeRateDenominator\", \"highEstimatedExchangeRateNumerator\", \"id\", \"lowEstimatedExchangeRateDenominator\", \"lowEstimatedExchangeRateNumerator\", \"maxPacketAmount\", \"minExchangeRateDenominator\", \"minExchangeRateNumerator\", \"receiveAmountAssetCode\", \"receiveAmountAssetScale\", \"receiveAmountValue\", \"receiver\", \"walletAddressId\") values ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16, $17, $18, $19, $20) returning \"id\" - value \"10000000000000000001\" is out of range for type bigint"
…

The big number represents the low/high estimated exchange rate. Output from Pay.startQuote (see additionalFields):

{
  "receiver": {
    "ilpAddress": "test.net.G7Q7M9cJOmrq64SnMqFKp_9obMXoYi7NlJnNCYRL1qS_8LH0rZQVKWMF8KXylnAzWuMkRzYrin2XAEnuxqmhoYTAZlJFYRc",
    "sharedSecret": { <redacted> },
    "assetCode": "USD",
    "assetScale": 9,
    "incomingPayment": {
      "id": "https://ilp.rafiki.money/incoming-payments/582a4e08-c284-44f6-bb07-6e0f9ea973bd",
      "walletAddress": "https://ilp.rafiki.money/radu-wm",
      "receivedAmount": {
        "value": "0",
        "assetCode": "USD",
        "assetScale": 9
      },
      "completed": false,
      "metadata": {
        "source": "Web Monetization"
      },
      "createdAt": "2024-05-23T05:44:00.789Z",
      "updatedAt": "2024-05-23T05:44:00.789Z",
      "expiresAt": "2024-05-23T06:44:00.473Z",
      "methods": <redacted>
    }
  },
  "walletAddress": <redacted>,
  "estimatedExchangeRate": 10000000,
  "debitAmount": {
    "value": "2",
    "assetCode": "USD",
    "assetScale": 2
  },
  "receiveAmount": {
    "value": "9900000",
    "assetCode": "USD",
    "assetScale": 9
  },
  "additionalFields": {
    "lowEstimatedExchangeRate": [
      "10000000000000000000",
      "1000000000000"
    ],
    "highEstimatedExchangeRate": [
      "10000000000000000001",
      "1000000000000"
    ],
    "minExchangeRate": [
      "9900000",
      "1"
    ],
    "maxPacketAmount": "18446744073709551615"
  }
}

Todos