Multichain is a collection of functions, types, interfaces, and runtimes that can be implemented for any blockchain. Those familiar with the Rosetta spec by Coinbase will note similarities in goals. However, multichain's scope is limited to accounts, contract calls, and sending transactions — there is no block data extraction. Moreover, the chain (Harmony) would have to implement the appropriate functions to Ren's multichain repo as a pull request and undergo their review. The Ren Project notes that once Harmony has integrated with the multichain API, we have the possibility for support in the RenVM.
To help bridge the gap between Harmony and other chains, we must explore ways to integrate with chain agnostic interfaces. Having an API that is standard across multiple chains (notably BTC & ETH) will help reduce the friction of getting assets onto Harmony. This document will provide a high level (but technical) overview of the components needed to integrate with Multichain.
What APIs would be available:
What extra components are needed:
- Localnet with a docker file
- Supplementary testing account just for localnet (not funded on testnet)
- Gas price estimate RPC (optional)
What will NOT be built:
- Staking Compatability
- Block data extraction
- UTXO APIs
As a reference, we can follow this guide.
Note that we should only rely on imports from the core protocol repo as the go-SDK is subject to change soon.
We will use JSON-RPC 2.0 to communicate with a Harmony node.
We can choose to implement our own requester, or we can re-use solana's RPC requester here as they also use JSON-RPC 2.0.
We will be integrating with 1 shard ONLY (defined as the target-shard). This reduces the complexity of transaction functionalities and should be sufficient for the goals of multichain.
We may choose to add it as an option when creating a
Clientand propagating it to theTxBuilder(explained in the Account API). Alternatively, we can just hard code the shard to beacon-shard as it has the most assets.
Multichain requires a docker file to run a node for a chain's test. All docker files will get placed here and get triggered from here.
We do not have any easy way to run a localnet like ganache, therefore we will just replicate the debug localnet (from here) using the latest stable binary within a docker image (exposing the target-shard's explorer port) to provide a node for tests. Some of the leg work has been done here & here, however, some integration needs to be done to fit the necessary functionality.
The interface to implement is EncoderDecoder, which consists of the Encoder and Decoder interfaces.
Note that we should use the Bech-32 addresses (a string) cast as Address and the byte representation of the Bech-32 addresses cast as RawAddress. This way, we should not have to redefine/reimplement the Address and RawAddress types & methods. The alternative is to just use the already implemented ETH addresses here and re-export the Address.
Since we are using the Bech-32 addresses, it should be easy to create a simple address Encoder & Decoder. If we use the built-in ETH address, we do not have to implement a decoder/encoder — all we have to do is re-export it (similar to what Celo has done here).
The interfaces to implement are: Tx, TxBuilder, and Client.
Note that for signing transactions, we are always in post EIP115 epoch, therefore we must always use the EIP115 signer found here.
For the Tx interface, the Hash, From, To, Value, Nonce, and Payload methods should be easy to implement with a wrapper around the Harmony Transaction object. The Sighashes method's content can be found here. The Sign method's implementation can be found here & here. Lastly, the Serialize method is simply the RLP encoding to bytes to be submitted to the mem pool (example here).
Note that for signing transactions, we are always in post EIP115 epoch, therefore we can always use the EIP115 signer found here. Homestead signers are to be ignored. For the ChainID required by the EIP115 signer, we can store it as an attribute of the
Txobject and set it upon building a new transaction.
For the TxBuilder interface, we only have to implement the BuildTx method. Note that we must include the Chain ID for the EIP115 signer; this can be fetched from the node's metadata within the BuildTx method. We may also want to include an additional method for TxBuilder to fetch the appropriate nonce for the BuildTx param.
For the Client interface, the Tx method is simply a getTransactionByHash RPC call. The SubmitTx method is not clear as to if it should block until confirmation of tx or not. Since most APIs do not block on the submission of a transaction, we should implement it as such.
The interface to implement is Caller. The only method to implement is CallContract. Note that the CallData could be a byte or marshaled version of the call data struct used by the call RPC.
Note that we should keep the address consistent. Our RPC layer takes in hex addresses instead of the Bech-32 addresses for the
CallArgs. For consistency, we may want to take the call arguments in multichain as Bech-32 (fromAddressAPI) and convert them appropriately for the RPC call.Also note that it may be worth it to implement the
CallContractunder theClientobject from the Account API as some state variables may be shared.
The interface to implement is Estimator. The only method to implement is EstimateGasPrice. Note that we currently do not have a way to estimate the gas price. We can either hard code some value in multichain (citing 5sec block time as an excuse), or we can implement an RPC to get the average gas price in the mem-pool and call that as part of the EstimateGasPrice method.
Add ONE as a supported asset here & ensure tests pass for ALL supported chains.
| Discription | Target Date |
|---|---|
| Address API | 9/3 |
| Docker Localnet for Tests | 9/4 |
| Account API | TBD |
| Gas API [+ Gas Price Estimator RPC] | TBD |
| Contract API + Final Touchups | TBD |
This is where updates will be posted regarding current progress & hurdles.