JSONPaymentProtocol V2 (JPPv2) Token Support

Hi all,

Currently JSON Payment Protocol V2 has no standard/convention defined for amending tokens to outputs:

I’d like to put forward three proposals:

1. We amend the output payload format for BCH such that it looks something like this which would give JPPv2 BCH token support.

{
  address: string; // Same as current
  amount: number; // Same as current (think amount is in sats IIRC)
  // NEW: This is mostly lifted from LibAuth, but we hexify the Uint8Arrays
  // https://libauth.org/types/Output.html
  token?: {
    amount: number;
    category: string; // Hexified Uint8Array
    // I'm a little bit unsure whether the below is sane to include.
    nft?: {
      capability: 'minting' | 'mutable' | 'none',
      commitment: string; // Hexified Uint8Array
    }
  }
}

One concern with the above might be that existing wallet validations could ignore this Token object. However, most JPPv2 servers will validate the received transaction object for validity so, if this is missing from the constructed transaction, the JPPv2 server should reject it.

NOTE: As per official spec, wallets can fallback to broadcasting the tx themselves if the JPPv2 server rejects. But I am not aware of any wallets that actually implement this behaviour and advise against it. The intent here, as I understand it, was to invalidate the UTXOs such that the server cannot broadcast them later. But this can create problems where the Wallet broadcasts a payment the server deems incorrect (thus, it remains recorded on the server as unpaid), so I think the better approach would probably be to invalidate the UTXOs by sending them back to the wallet’s change address (if a wallet did want to implement that behaviour).

2. The address field can also take in lockingBytecode provided as hexadecimal.

JPPv2, although close to feature-parity with BIP70, lacks a standard/convention for OP_RETURN outputs. As it expects addresses (as opposed to lockingBytecode), this means there was no way to tack an OP_RETURN to an output using JPPv2 (whereas, in BIP70, outputs used lockingBytecode).

Behaviourally, this amendment would require wallets to check whether the value provided in the address field is actually a BCH address (e.g. bitcoincash:qr9z0h09sl5kkeach6kcj4hceu6whx3xp5rp2fttse) or hex that represents locking bytecode (e.g. 76a914ca27dde587e96b67b8bead8956f8cf34eb9a260d88ac) when constructing the signed transaction.

Note that this amendment should also future-proof us for Pay-2-Script (which takes raw lockingBytecode).

3. Standardizing on JPPv2 as opposed to BIP70

BIP70 is comparatively difficult to implement vs JPPv2: It requires Protobufs which is usually an extra dependency whereas many languages/frameworks now have the capability to work with JSON inbuilt.

And with the second amendment above, I think JPPv2 now reaches parity with BIP70.

The advantage of standardizing on JPPv2 over BIP70 from an eco-system point of view is that merchants no longer have to implement both. A typical payment request URL might look something like:

bitcoincash:?r=https://some-server.com/endpoint-to-retrieve-the-invoice

… and wallets indicate which protocol (JPPv2 or BIP70) they want to use via the use of HTTP headers. This meant, for broad wallet support, merchants had to support both and parse the headers conditionally to work out whether they should respond with a JPPv2 invoice or a BIP70 invoice.

I’ve dug around a bit and am not aware of any services still using BIP70. It seems they have standardized on JPPv2. If anyone knows of any that still use BIP70 exclusively, please let me know in this thread.

1 Like

This looks good to me. Also – does anybody happen to know of ANY payment services still using BIP70? IIRC Bitpay is on JPPv2… right?

IMHO BIP70 sucks – except it can do locking bytecode. If we amend the spec as you say to allow for hex-encoding locking bytecode we can do everything. And if we add tokens, all the better! Amended spec looks good to me!

1 Like

Yeah, that’s correct: BitPay is using JPPv2 (they created the spec because they were encountering wallet implementation problems with BIP70 - so they were trying to simplify it for implementers).

The only service I could find that might be using BIP70 still is something related to Bitcoin.com. I’m not sure what this is specifically though (and it looks like it may be a bit of mix-n-match of JPP/BIP70). I found mention of it in Paytaca’s source code:

Am also keen to hear whether anyone is aware of any others (my projects tried to support both - but I’d really like to ditch BIP70 because it’s painful to work with).

If my memory serves me the kimdotcom mass payment page (which I already forgot the name of) was using BIP-70 on bitcoin.com infrastructure.

1 Like

Thanks! The name’s escaping me too - but I’m pretty confident you’ll be correct: Bitcoin.com (last I checked) was a BIP70-based wallet and that Kimdotcom service used another (undocumented) Bitcoin.com service for the authentication. So, it would line up.

I’ll confirm when I can remember the name of it. :sweat_smile:

The service we were thinking of is CashRain ( https://cashrain.com/ )! I’m not sure if this is still active - the site has been in a maintenance mode for (at least) the past 24 hours I’ve been checking. That said, if a wallet already supports BIP70, it might be worth retaining the code for now and coding an exception in where domain.includes('bitcoin.com') in case the service returns.

With regard to Wallets and their current BIP70/JPP support, here’s a table as I currently understand it:

| Wallet        | Protocol(s) | Notes                    |
|---------------|-------------|--------------------------|
| Bitcoin.com   | BIP70       |                          |
| Cashonize     |             |                          |
| Edge Wallet   | JPPv2       |                          |
| Electron Cash | BIP70+JPPv2 | JPPv2 only on BitPay.com |
| Flowee        | BIP70       |                          |
| Paytaca       | JPPv2       |                          |
| Selene        | JPPv2       |                          |
| ZapIt         | JPPv2       |                          |

(Please let me know of any errors in the above).

With regards to Services and their current BIP70/JPP support, here’s a table of those that I’m aware of:

| Service        | Protocol(s) | Notes                                                                                |
|----------------|-------------|--------------------------------------------------------------------------------------|
| Bitcoin.com    | BIP70       | Probably Cashrain (currently offline). Might be non-standard implementation of BIP70 |
| BitPay         | JPPv2       | There may be BIP21 support - but Bitcoin.com and Electron use JPPv2 |
| CashPayServer  | BIP70+JPPv2 |                                                                                      |
| Stamps.Cash    | BIP70+JPPv2 | Uses CashPayServer                                                                   |
| ScanToPay.Cash | BIP70+JPPv2 | Uses CashPayServer                                                                   |
| CashTags       | BIP70+JPPv2 | Uses CashPayServer                                                                   |

(There are likely more - if you know of any, please let me know in this thread and I’ll amend this table)