2018-04-24 - Future - Tony Finch
Some further refinements of the API behind shopping-cart style prepared transactions:
On the server side, the prepared transaction is a JSON-RPC request blob which can be updated with HTTP PUT or PATCH. Ideally the server should be able to verify that the result of the PATCH is a valid JSON-RPC blob so that it doesn't later try to perform an invalid request. I am planning to do API validity checks using JSON schema.
This design allows the prepared transaction storage to be just a simple JSON blob store, ignorant of what the blob is for except that it has to match a given schema. (I'm not super keen on nanoservices so I'll just use a table in the ipreg database to store it, but in principle there can be some nice decoupling here.)
It also suggests a more principled API design: An immediate
transaction (typically requested by an API client) might look like the
following (based on JSON-RPC version 1.0 system.multicall
syntax):
{ jsonrpc: "2.0", id: 0, method: "rpc.transaction", params: [ { jsonrpc: "2.0", id: 1, method: ... }, { jsonrpc: "2.0", id: 2, method: ... }, ... ] }
When a prepared transaction is requested (typically by the browser UI) it will look like:
{ jsonrpc: "2.0", id: 0, method: "rpc.transaction", params: { prepared: "#" } }
The "#" is a relative URI referring to the blob stored on the JSON-RPC endpoint (managed by the HTTP methods other than POST) - but it could in principle be any URI. (Tho this needs some thinking about SSRF security!) And I haven't yet decided if I should allow an arbitrary JSON pointer in the fragment identifier :-)
If we bring back rpc.multicall
(JSON-RPC changed the reserved prefix
from system.
to rpc.
) we gain support for prepared
non-transactional batches. The native batch request format becomes a
special case abbreviation of an in-line rpc.multicall
request.