Push Payments and Invoices

While working on an update to enable pull payments, I ended up making three individual specs out of the SPSP spec:

  1. A plain SPSP spec: It only describes what SPSP is for, namely exchanging connection details for STREAM.
  2. An SPSP pull payments spec: as discussed in Pull Payments
  3. An SPSP push payments spec: focus of this discussion.

To me, this is a very natural split because cramming everything (SPSP push + invoices and pull) into one spec makes it too overloaded and dealing with push payments and invoices in the general SPSP spec but having a different one for pull payments is inconsistent. Feel free to disagree.

The current SPSP spec contains information about optional response body fields like balance, asset_info, and receiver_info. These fields are very much tailored towards invoices and when I started working on that, I thought this was the agreed upon standard for invoices. However, in the Anypay Protocol discussion it seems like there is consensus that there should not be a standard for invoices. Maybe we should make these fields exemplary instead of optional or at least making this point more clear.

If those fields stay, there is the question of whether the balance parts (balance.maximum and balance.current) should contain positive or negative values. In the case of invoices one can argue that it makes sense to have negative balances because the clients owes money. This would then mirror positive balances in the case of pull payment agreements (if we decide to store this information within the endpoint query response).
In the case of an accounting system (I want to keep track of who is sending me what), it makes more sense to have positive values. However, I wonder why one would need a balance.maximum there.

2 Likes

I think you’re right that it makes sense to split the three aspects of “SPSP” that have previously been grouped together.

When you say “standard for invoices”, do you mean a full format like Invoice - Schema.org Type or the fields we currently have in the SPSP response like the total amount to pay, the amount already paid, currency details, etc?

It seems like at minimum we need a standard way to communicate the amount left to pay (denominated in the receivers units). The asset details were included for display purposes, though they’re also being sent through STREAM now.

I meant the current fields in SPSP.

I agree. That means we need something like balance.current, which could just be balance because everything else is defined in standards like Invoice - Schema.org Type, where balance.maximum = totalPaymentDue.
The question then is, what is balance? Is it the sum of all incoming chunks (as it is defined now), or is it the amount still outstanding?
Also, is it a positive or a negative number? @adrianhopebailie had suggested negative numbers before. At that moment, I liked it, but now I’m not so sure anymore because it will probably not work well with other invoice schemas.

A general point I want to caution about is that making standards more minimal and having more different standards doesn’t always help. The Interledger stack already has a lot of different protocols you need to understand if you want to see how it works. Having more optionality is better in the long-term but definitely makes it harder to grok and use in the short term.

To play devils advocate, why not just adopt an invoice standard like the schema.org one? Arguably, anyone using ILP for this use case will need some format and it might be easier for them to use Interledger if we say “use this standard” instead of “use whatever you want, we leave that choice up to you”. (Curious to hear what @stevenzeiler thinks about this)

If we were making the most minimal standard possible, I would only include the amount left to send and I’d make it a positive number for simplicity’s sake.

1 Like

I don’t think that is a bad idea as long as it is a specific spec for invoices and not included in the push payment spec. In this case, push payments would only describe sending money to any endpoint without any accounting (no balance increase etc.).

Seems reasonable to me.

So your proposal is that there would be 3 different specs for:

  • “Base” SPSP that only specifies the ILP address and STREAM secret in HTTP headers
  • A pull payment protocol that would extend the base SPSP
  • An invoice protocol that would extend the base SPSP

And that simple peer-to-peer push payments would use the plain base SPSP protocol. Is that right?

Yes, that is my proposal. The simple push payment is the simplest use case for “base SPSP” and can be part of that spec. The other two are extensions.

If others agree (@justmoon, @adrianhopebailie, @sharafian), we can further discuss how the invoice spec should look like.

Some other things to think about related to how data (and money) transfer should happen over STREAM (these haven’t been well-defined before):

  • If you want to send a message or memo with your P2P payment, how do you send that over STREAM? Is there a specific data format or text encoding you should use? What stream number should you send it on? Is there a limit to the memo size?
  • How should extensions to that protocol send data? Should they put it as the HTTP response body for the SPSP query or transmit it through the STREAM connection? In either case, what data format should they use or is it up to them?
  • Does it matter what stream ID is used to send money? Should all of them be treated as interchangeable?
  • Is there a way to know you’ve connected to the wrong STREAM server if, for example, a pull payment client connects to a server that’s only set up to receive p2p payments or invoice payments?

I agree that this should be speced out, however, does this belong here or should we have another discussion and spec for ‘data transmission over STREAM’?

This belongs in SPSP because it’s up to different applications built on STREAM to define what type of data they want to send. STREAM specifies how byte streams are sent over it and it’s up to whatever is sending those bytes to determine what they mean.

You are right. Would you consider that to be part of ‘base SPSP’ or is that an extension and should get its own spec?

I would say that depends on how well we want it to be speced out. If it is very simple, one could add it to ‘base SPSP’ but only if it is as simple as ‘you open a STREAM connection and send data, no longer than 140 characters, utf-8 encoded’. This is the equivalent to simple push payments.
If it is more complicated than that, I would suggests mentioning that transmitting data is possible but link to another spec that defines how that should look like.

Nevertheless, I would like to open a new topic for these data related questions and concentrate on push payments and invoices here. Otherwise, it will become too confusing.

I like the idea of specifying something very simple for p2p payments and leaving the invoice details in the HTTP response so we don’t need to define a complete way of sending data over STREAM right now. For the p2p memos, I’d say something more like 1024 characters at least, since that’s how long an ILP address can be.

The base spec could say that extensions of it may define more complex ways of sending data over STREAM.

My example of 140 characters was random. 1024 sounds reasonable.

To summarize and to figure out whether I got it: We want a base SPSP spec that describes how

  • STREAM parameters are exchanged
  • a simple push payment is made
  • simple data transmission works

Additionally, we want an additional spec for each: invoices, pull payments, and complex data transmission.

I know, and I’m also not sure that’s the right size either.

I’d agree with all of that except for the spec related to more complex data transmission. I don’t think we need a spec for that in general, but any other protocols built on STREAM may need to define how they’re going to handle it.

Is there a particular reason why one would want to cap the length of the data?

Fair enough.

If an unknown party is sending you data, you want to be able to cap it to make sure they can’t DoS you with it. Imagine you’re building a UI that shows those memos; how many characters should you display?

I agree but I think every use case should be able to define that cap itself. Some use cases may want to send and receive JSON blobs that are way longer. Every UI may want to have different lengths for their memos. There is also no definition of how big a payment can be in the simple push payment scenario. Both parties just set their sendMax and receiveMax suited for the use case.

That’s true, it can be handled on the STREAM level

1 Like

Is that already possible, i.e. are there equivalents to sentMax and receiveMax for data?

https://interledger.org/rfcs/0029-stream/#5312-streammaxdata-frame

1 Like