Pull Payments

You want to introduce an additional duration parameter? Or is interval the duration integer and we always assume that it is denoted in hours?

Yes. Instead of having a text-based field thatā€™s either ā€œhourā€ or ā€œdayā€, you would have a duration field thatā€™s denominated in a unit such as hours so an hour would be 1, a day would be 24, and so on.

One of the most common intervals for a recurring payment is Month, and thereā€™s no good way to express that in terms of hours. We could do something like a duration object formatted as a datetime so that it has ms, s, m, h, days, months, years (maybe some subset of ISO 8601 - Wikipedia )

1 Like

I like that idea. The smallest entity should be hours given the concerns raised above so the interval parameter would be of the form 'P<years>Y<months>M<days>DT<hours>H'

This means we have the following parameters:

  • start time (start): ISO string 'YYYY-MM-DDThh:mm:ssZ'
  • amount (amount): Integer
  • refill interval (interval): ISO string 'P<years>Y<months>M<days>DT<hours>H'
  • number of repetitions (cycles): Integer
  • cap (cap): Boolean, false = no cap (amount keeps accumulating), true= cap (use it our lose it)

What is missing is something about the asset type and scale if we want to allow the pull payment to be denominated in an asset that is neither the clientā€™s nor the serverā€™s (for stability).

Also, one could think about some parameter that indicates that even though the bucket fills hourly at the minimum, only the amount accumulated to this second/minute can be pulled.

1 Like

Iā€™m still interested in sub-hour intervals for the subscription/non-bucket use case.

Iā€™ve been thinking about the different kinds of recurring payments. Assuming theyā€™re all based on a set rate (price/usage), it seems like they could be categorized as:

constant/regular usage irregular usage
regular pull frequency Subscription (Netflix, Amazon Prime, Codius) Bucket/Autopay (utility & credit card bills)
irregular pull frequency prorated subscription? Auto top-up (Twilio or toll road account for which the account balance is refilled whenever it drops below a certain amount)

I think the two on the right (bucket/autopay and auto top-up) can both be handled with a specified maximum authorized amount over whatever arbitrary time interval (use it or lose it).

Similarly, the ones on the left can both have a constantly/regularly incrementing authorized amount. Itā€™d be nice if we could treat all four like this for simplicityā€™s sake. If I say my utility company can pull as much as $200/month, then how much different is them taking $200 in both January and February vs $100 in January in $300 in February. The utility company could be overdrawing (based on my actual usage) in either scenario.

1 Like

Maybe we can introduce some restrictions of what the max amount per interval is to make sure that the payment can be processed. On generation of the payment pointer, we check that these restrictions are met. This way we can go as low as 1 second for an interval.

Thus they can all be seen as prepaid accounts that allow a certain amount to be pulled per interval. Depending on the nature of the payment, you adjust amount, interval, and cap. In a flat rate subscription scenario, it makes sense to have larger intervals and no no caps whereas in a pay-per-usage scenario, you may want smaller intervals and caps. This, however, still does not prevent the utility company to pull the full amount each interval. For this, we would need varying amounts.

I would define the most obvious use cases like this

Use Case Description Technical implementation
Checkout A user buys a product in an (online) shop. The merchant should be able to pull the predefined price (+ any additional fees) within a predefined time period out of the userā€™s wallet. amount = price + fees, interval = predefined period (letā€™s say 1 week), cap = true, cycles = 1, start = now
Subscription / Recurring Payment / Flatrate A user subscribes to a service. The service provider should be able to pull a predefined amount within a predefined time period or on a predefined date, recurring over a predefined time span, as long as the user does not cancel the plan. The user does not have to trust the service because it is a flat rate. amount = price, interval = predefined period (letā€™s say 1 month), cap = false, cycles = n, start = now
Pay per use - Scheduled payment A user signs up for a service but only pays the fees she accumulated over a time period. The service provider should be able to pull this amount (+ any additional fees) within a predefined time period or on a predefined date, as long as the user uses the service / does not cancel the agreement. The maximum pullable amount is caped. The user has to trust the service that it does not pull the full amount each interval. amount = max price per interval, interval = predefined period (letā€™s say 1 month), cap = true, cycles = n, start = now
Pay per use - Streaming The user signs up for a service and pays as she uses this service. Instead of her streaming the money to the service provider, the service provider pulls it constantly whenever the service is used (Coil inverse). It is implied that the client does not pull when the service is not used. There is no cap to allow for less frequent than constant pulling without the loss of funds. The user has to trust the service that it only pulls whenever she is using it but can cancel the agreement at all times. amount = price per interval, interval = 1 second, cap = false, cycles = n, start = now

I am probably forgetting some but these are probably the main ones that could all be realized with the parameters we have defined so far. However, there is a trust issue for the last two.

1 Like

Tangent: It might be overkill for what we need, but I found this recurrence rules spec while looking at the Google Calendar API:
https://tools.ietf.org/html/rfc5545#section-3.8.5

Thereā€™s also a JavaScript library

@wilsonianb Thanks for sharing that. However, I agree with you assessment.

I found using ISO 8601 durations in combination with cycles to be very slim, understandable, and easy to implement.

This is great! I like the idea of supporting both the ā€œuse it or lose itā€ style and the constantly accumulating one.

I donā€™t think this is necessary. If you set it up with cap = true and an interval of 1 second, you might have some strange behavior but we can just put a recommendation in the spec that you may not want to do this rather than actually restricting it.

Originally I didnā€™t like this idea that much but thinking about it more, it does sound useful and not that difficult to implement. I was thinking we would need this to be calculated through the Interledger network, requiring landmarks and something along the lines of ilp-price. However, since this is just guidance for the provider, they can use whatever method they want to get the price (such as a simple external API).

The one thing to consider is how to handle the exchange rate changing over the interval period. Maybe you would just use the average exchange rate over the period since the last time you updated the pullable amount.


Overall, nice work @sabinebertram and @wilsonianb!

@sabinebertram are you working on an implementation of this already?

Fair enough.

This means that we have to keep track of when the last pull was made as well as exchange rates. It feels like overhead to me. The client can pull whenever she wants within the interval so she can pull when she likes the exchange rate. I would just use the spot rate at the moment of the pull. I guess you can argue that this is a disadvantage for the server but this incentivizes her to make good decisions about her currency as well as the pull agreement currency.

Yes I am. Here is the latest version, already including offline token generation support: ilp-spsp-pull-payment-server. I also updated ilp-protocol-spsp and ilp-spsp accordingly. Iā€™m working on an implementation that allows the client to pull less than the full amount per interval now and wanted to tackle the exchange rate topic next.
I have also already worked on an integration of pull payments within codius, however, this is still based on older versions of pull payment parameters.

One thing that is still not clear to me. What does the query of the token endpoint return? Only destination_account and shared_secret or also some information about the pull agreement that can be used to display it in e.g. the customers wallet? And if so, what do we want to include?

1 Like

Iā€™m ambivalent about including pull agreement details. They definitely shouldnā€™t be required (it should work with just destination_account and shared_secret) but could probably just be optional (like the push payment detail).

I agree. I would make them optional but include them to have a description of the parameters we discussed over the course of this forum thread.

On that point, do we want a different spec for the token negotiation and creation phase that makes the parameters we discussed mandatory? Or is that part of this spec?

A couple variations to consider:

  • Replace cycles with an expiration time
  • Make start, interval, cycles/expiration, and cap optional

Together, that would let you provide just an amount (and optionally expiration) for a one-off payment. An expiration (vs cycles) also seems advantageous for shorter (ex. 1 second) intervals.

edit: actually, cycles and expiration are probably distinct things. cycles could be used to specify when to stop increasing the available balance, whereas expiration would be used to set the available balance to zero / invalidate the endpoint.

I would argue against that. A time makes it way more complicated because what happens when the intervals do not fit exactly in the period between start time and expiration time?

We can still make start, interval, cycles, and cap optional, i.e. if only the amount is given, set the start to now, the interval to default (letā€™s say 1 day) and cap to false. This way, the amount is pullable forever.

This sounds reasonable. It also crossed my mind today that there is no clean-up functionality for payment pointers that are out of money yet.

edit: However, adding that for out-of-the-money pointer should be easy to get. The question is whether we want an expiry time for payment pointers that are still in the money.

I vote yes to that being an option

I donā€™t object. Iā€™m sure that will be useful in some cases. Iā€™ll add it to the spec as an optional field.

There is a new PR only containing the new pull payment spec ready for review: https://github.com/interledger/rfcs/pull/514

ā€¦ would any of you be interested in helping me put this to a ā€œtest caseā€ with a site that is dedicated to xrp, is a membership site and the service can work with 1xrp/day?

Hi Jason, Welcome to the thread!

I am not sure how practical such an implementation is at the moment because all of the members of your site would have to run their own pull payment SPSP server (plus moneyd). This is a lot of effort.
I have been talking to some wallet providers who are interested and willing to add the possibility to create pull pointers to their services. This would make pull payments 100 times more feasible. However, there is no provider yet that has that feature, at least not that I know of.
If you nevertheless want to give it a go, have a look at my ILP SPSP Pull Payment Server. This (or something similar) is what each of your members has to have running for you to pull 1xrp/day.

Ms. Sabine ā€¦ thnx for getting back to me so quickly. =) ā€¦ I know all about how difficult it is for ā€˜recurring paymentsā€™ with xrpl and ilp, as I have been chatting with multiple people like Wietse Wind from XRPL Labs about the project for many months now.

Since there are no wallet providers that are interested, I would think that the next best thing is to create the platform. I can attest to many people out in the cryptosphere (is that a word?) that would love the ability to have ā€˜recurring paymentsā€™ on their membership sites for premium content.

Is there a place where we can chat about this further without destroying this awesome thread you have put together here?