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.