XDM Wallet Communications Substrate
Last updated
Was this helpful?
Last updated
Was this helpful?
Ty Everett (ty@projectbabbage.com)
Cross-document messaging enables web-based applications to communicate with one another in a secure manner, without allowing the two applications to manipulate each other's DOM trees. It defines a mechanism by which messages can be sent and received, with browser-based attestation of the origin of each message. We define the framework and conventions for operating a wallet over XDM, enabling a parent page that runs a wallet to communicate with one or multiple child pages that run applications.
defines a suite of abstract messages used by applications and wallets to facilitate various Bitcoin and MetaNet operations that enable micropayments, protect user privacy and ensure secure authentication without the need for each application to maintain a separate user account. While defines a method of using a wallet over HTTP on the local machine, some mobile devices are unable to support running HTTP servers due to platform-specific limitations. Additionally, it is sometimes desirable for a MetaNet environment to run fully in the browser, enabling users to access their identities on devices or platforms where a desktop-based client cannot be installed. This specification provides a ubiquitous communications substrate enabling the use of functionality across a wide range of devices and deployment contexts, including fully in-browser experiences.
We specify that the parent page runs the wallet, responding to messages from child pages. This has several advantages:
The wallet can always pop-up any necessary permission popups or user-interactive authorization screens without interference from client pages
When the user visits the parent page, they log in once, then they can access any applications after login
Multiple applications, all running in the same parent page, can access and utilize the wallet at once
Reducing the number of wallets running in parallel reduces the chances of UTXO synchronization or corruption issues
It is possible to run the parent wallet page locally, connecting to remote services only when required by specific applications
If a specific application was the parent and the wallet was a child, failure of the parent page to respond could constitute failure of a user to access their identity or assets, which might otherwise be available through another application
We start with the message relay interface defined by XDM. JavaScript code for sending messages from the application to the wallet is as follows:
We stipulate that:
All messages (requests, responses and errors) have a type
property equal to CWI
(this value, which stands for Computing with Integrity, is historical)
A random message ID is generated by the application
The application listens for new, incoming response messages. As part of the listener, the application:
Drops any events without the correct type
in the event data
Drops any events where isTrusted
is not true
Drops any events where the event data contains the isInvocation
flag, denoting any outgoing messages that were echoed back
Drops any events where the event data contains an id
field other than the one generated by step 2
Handles any error messages if the event's data contains a status
field equal to error
, relying on the code
and description
fields to construct an appropriate error
Otherwise, if no errors are detected, the application is now free to make use of the result
field from the event's data payload, which will be the response from the wallet as specified by the relevant BRC standard for the specific message being sent
With the listener in place and ready to process the response when it arrives, the application now constructs and sends the message to the wallet through the parent window:
Like all messages, the outgoing message contains a type
field equal to CWI
An isInvocation
flag is set to true
, allowing listeners to easily drop outgoing messages rather than trying to process them as responses
The id
that was generated in step 2 is included. The same id
must be used by wallets when sending back the response
The call
determines which message is being sent. Specific call
values are defined below
The params
field comprises the specific parameters as specified in BRCs that define specific message types
The wallet listens for incoming messages and replies to the originator with appropriate responses after obtaining permission from the user (if applicable) and processing the request. Some JavaScript code that implements this functionality is provided:
We stipulate, before any client applications are loaded which might send any messages to the wallet, that the wallet running on the parent page must bind a message event handler that:
Upon receipt of a message with an event data field type
not equal to CWI
will drop the message
Upon receipt of an untrusted message, or one without a call
will drop the message
Upon receipt of a message with an unknown or unsupported call
will proceed to step 6
Based on the call
and params
will perform the necessary steps as required by the relevant BRC specifications for the specific operation
Compose a response message and send it back to the originator, the response message comprising an event payload with the following fields:
A type
value of CWI
The id
that was specified by the application when the message was created
A result
value that is the result of the operation being performed, as specified by the particular operation
In case of any errors with the operation, the wallet will instead send back a response message comprising an event payload with the following fields:
A type
value of CWI
A status
value of error
The id
that was specified by the application when the message was created
A relevant code
for the error, as specified by the particular operation in question
A human-readable description
for the error
call
Associated with Various Message TypesMessage Pair
call
Value
Specific Implementation Notes
createAction
encrypt
decrypt
createSignature
verifySignature
createCertificate
proveCertificate
createHmac
verifyHmac
getPublicKey
ninja.findCertificates
This call name prefix is historical and retained for compatibility
getVersion
getNetwork
isAuthenticated
waitForAuthentication
Implementation questions should be directed to the author.
This application-side interface facilitates exchanging and receiving messages with the wallet over XDM. We now proceed to how the wallet handles its side of the interaction.
For each of the message pairs (request and response) incorporated into , we specify the existence of a corresponding XDM message pair with a specific call
value:
Transaction Creation
Encryption
Decryption
Signature Creation
Signature Verification
Certificate Creation
Certificate Verification
HMAC Creation
HMAC Verification
Public Key Derivation
Certificate List
Version Request
Network Request
Authentication Request
Async Auth Request
Implementers of applications and wallets will need to create and process XDM messages in the manner described, according to the various fields and properties as required by , and in a manner consistent with the reference implementation, which is the 's XDM substrate functionality.
One (crude) example of a deployed architecture in which a parent page uses XDM to communicate with child application pages, facilitating the operation of multiple client applications which communicate with the parent wallet, has been implemented by the Babbage team at .