cypherpoker.js
cypherpoker.js copied to clipboard
Create native Monero client adapter for Desktop
Overview
CypherPoker.JS for Desktop requires that the Monero command line client be integrated into the application in order to enable support for the cryptocurrency. This is best accomplished by creating an adapter, similar to the current sqlite3.js adapter.
In short, such an adapter is responsible for spawning the command line client, with RPC functionality enabled, as a Node child_process, and providing async functions that CypherPoker.JS can interact with (especially the CP_Account API endpoint).
The adapter should simultaneously and transparently support Windows, macOS, and Linux Monero clients. If any existing NPM packages exist that are both reliable and support these specifications then they should be considered for inclusion into the adapter.
Additional information, including code documentation and formatting, can be found here: https://github.com/monicanagent/cypherpoker.js/issues/48
Configuration
Configuration options for adapters are currently stored in the desktop version's main.js file:
https://github.com/monicanagent/cypherpoker.js/blob/1a4e605e2dbbcf394e2adaf3a2d428a67ae125e8/src/desktop/main.js#L111-L119
However, these may be externalized (to a config.json file, for example), so they should not assume to exist at the application's root level and instead always be passed by reference (to a constructor function, for example).
Post-Install Configuration
One-time post-install configuration options for the adapter (after npm install completes), can be set in the desktop postinstall.js file.
Launching the Adapter
The adapter should be launched using a function similar to the one used to start the SQLite 3 database:
https://github.com/monicanagent/cypherpoker.js/blob/1a4e605e2dbbcf394e2adaf3a2d428a67ae125e8/src/desktop/main.js#L142-L161
A reference to the adapter should be included in the configuration data so that it can be accessed from the main.js process. For example:
https://github.com/monicanagent/cypherpoker.js/blob/1a4e605e2dbbcf394e2adaf3a2d428a67ae125e8/src/desktop/main.js#L143
Note that the adapter should exist in its own execution context (a JavaScript virtual machine), and is to be provided with available objects references and data exposed in the electronEnv.server.exposed_objects configuration object (see Configuration above).
Another thing to keep in mind when writing the adapter launcher is that other adapters will almost certainly be included in future versions so the launch process should be as modular and self-contained as possible (an async function rather than flat root-level code).
Adapter-Server Communication (Required)
Once launched, the adapter's data and functionality becomes available to the local server and all loaded API endpoints via the hostEnv property :
https://github.com/monicanagent/cypherpoker.js/blob/1a4e605e2dbbcf394e2adaf3a2d428a67ae125e8/src/server/server.js#L348
For example, this is how the SQLite 3 adapter is accessed from the main server.js process:
https://github.com/monicanagent/cypherpoker.js/blob/1a4e605e2dbbcf394e2adaf3a2d428a67ae125e8/src/server/server.js#L1085
...and here's how it's accessed from an API endpoint (CP_Account in this case):
https://github.com/monicanagent/cypherpoker.js/blob/1a4e605e2dbbcf394e2adaf3a2d428a67ae125e8/src/server/api/CP_Account.js#L762
In both cases the hostEnv.database.sqlite3 reference is the one set when the database adapter is started:
https://github.com/monicanagent/cypherpoker.js/blob/1a4e605e2dbbcf394e2adaf3a2d428a67ae125e8/src/desktop/main.js#L153
Here adapterData=electronEnv.database.sqlite3:
https://github.com/monicanagent/cypherpoker.js/blob/1a4e605e2dbbcf394e2adaf3a2d428a67ae125e8/src/desktop/main.js#L143
Adapter-Client Communication (Optional)
Although it's unlikely to be used, at least at the present time, the adapter can also be accessed using a synchronous IPC call from the web client when running as a Desktop application.
In main.js a new case block for the adapter should be added to:
https://github.com/monicanagent/cypherpoker.js/blob/1a4e605e2dbbcf394e2adaf3a2d428a67ae125e8/src/desktop/main.js#L232-L316
From the web client this is invoked via the IPCSend function:
https://github.com/monicanagent/cypherpoker.js/blob/1a4e605e2dbbcf394e2adaf3a2d428a67ae125e8/src/web/scripts/index.js#L203-L220
Messages may also be initiated in the opposite direction and received in the web client:
https://github.com/monicanagent/cypherpoker.js/blob/1a4e605e2dbbcf394e2adaf3a2d428a67ae125e8/src/web/scripts/index.js#L235-L254
Required Functional Support
In order to provide the full cryptocurrency functionality required by CypherPoker.JS, the adapter must support the following:
- Generate a HD wallet address from which child addresses can be derived (like BIP39), similarly to what's implemented in the
CP_AccountAPI endpoint:
https://github.com/monicanagent/cypherpoker.js/blob/1a4e605e2dbbcf394e2adaf3a2d428a67ae125e8/src/server/api/CP_Account.js#L487
- Derive an address from the HD wallet using child indexes. Note the use of the
startChainandstartIndexvalues which are maintained between sessions to always generate fresh deposit addresses:
https://github.com/monicanagent/cypherpoker.js/blob/1a4e605e2dbbcf394e2adaf3a2d428a67ae125e8/src/server/api/CP_Account.js#L558-L599
...or:
https://github.com/monicanagent/cypherpoker.js/blob/1a4e605e2dbbcf394e2adaf3a2d428a67ae125e8/src/server/api/CP_Account.js#L882
Derived address must also include private keys and related information required for sending transactions!
- A function capable of generating an address from, at least, a public key associated with the address:
https://github.com/monicanagent/cypherpoker.js/blob/1a4e605e2dbbcf394e2adaf3a2d428a67ae125e8/src/server/api/CP_Account.js#L535-L541
- A function to retrieve the live blockchain balance for an address:
https://github.com/monicanagent/cypherpoker.js/blob/1a4e605e2dbbcf394e2adaf3a2d428a67ae125e8/src/server/api/CP_Account.js#L833-L854
- A function to generate a new transaction object with customizable fees:
https://github.com/monicanagent/cypherpoker.js/blob/1a4e605e2dbbcf394e2adaf3a2d428a67ae125e8/src/server/api/CP_Account.js#L964-L1005
- A function to sign a generated transaction object with a private key:
https://github.com/monicanagent/cypherpoker.js/blob/1a4e605e2dbbcf394e2adaf3a2d428a67ae125e8/src/server/api/CP_Account.js#L1019-L1055
- A function to post the transaction to the peer-to-peer network and return a pending transaction hash:
https://github.com/monicanagent/cypherpoker.js/blob/1a4e605e2dbbcf394e2adaf3a2d428a67ae125e8/src/server/api/CP_Account.js#L1070-L1197
- A function to estimate the transaction fee for a given transaction:
https://github.com/monicanagent/cypherpoker.js/blob/1a4e605e2dbbcf394e2adaf3a2d428a67ae125e8/src/server/api/CP_Account.js#L1224-L1241
- A function to update the default transaction fees:
https://github.com/monicanagent/cypherpoker.js/blob/1a4e605e2dbbcf394e2adaf3a2d428a67ae125e8/src/server/api/CP_Account.js#L1260-L1309
For much of the above functionality, information such as the private key(s) for the root HD wallet, indexes of derived addresses, and default transaction fees, comes from the server configuration file:
https://github.com/monicanagent/cypherpoker.js/blob/1a4e605e2dbbcf394e2adaf3a2d428a67ae125e8/src/server/config.json#L35-L80
While none of the configuration sections for the new adapter are required to match the existing format or properties, it should be kept in mind that CypherPoker.JS should support both the Monero mainnet and any official testnets with independent configuration options for both.
It's also important to keep in mind that the configuration data is dynamic and is often updated at runtime after being loaded. For example:
https://github.com/monicanagent/cypherpoker.js/blob/1a4e605e2dbbcf394e2adaf3a2d428a67ae125e8/src/server/server.js#L918-L1043
As such, the data stored in the config.json includes only the basic, default options and any sensitive data such as private keys should be omitted from the file entirely and replaced with placeholders:
https://github.com/monicanagent/cypherpoker.js/blob/1a4e605e2dbbcf394e2adaf3a2d428a67ae125e8/src/server/config.json#L35-L46