MESC is a standard for how crypto tools configure their RPC endpoints. By following this specification, a user creates a single RPC configuration that can be shared by all crypto tools on their system.
MESC has two main design goals:
- make it easy to share RPC configuration data across tools, languages, and environments
- make it easy to manage the configuration of a large number of RPC endpoints
MESC is formally defined in SPECIFICATION.md.
Additional information can be found in the MESC Documentation.
Reference implementations are provided for each of the following:
- cli
- go [WIP]
- python
- rust
- typescript [WIP]
These implementations provide a consistent language-agnostic interface while still obeying the best practices of each language.
The quickest way to use MESC is:
- create a
mesc.json
config file - set the
MESC_PATH
environment variable to the path of this file
These steps can be performed automatically using the interactive mesc
CLI tool:
- Install:
cargo install mesc_cli
- Perform interactive setup:
mesc setup
Installing the mesc
cli on some linux distributions may require installing ssl libraries (e.g. sudo apt-get install pkg-config libssl-dev
on ubunutu)
Below is a brief tutorial on MESC. For more detail, see the MESC Specification and Documentation.
Topics:
MESC tracks the following information:
- a list of RPC endpoints, including their
name
,chain_id
, andurl
- the default RPC endpoint to use
- the default RPC endpoint to use for each network
MESC can also track other information like metadata and tool-specific defaults. Configuration data is stored in a JSON file. To create this file, follow the Quickstart instructions above.
All reference MESC implementations use the same common interface.
Here is a comparison between the python interface and the rust interface:
import mesc
# check whether mesc is enabled
enabled: bool = mesc.is_mesc_enabled()
# get the default endpoint
endpoint: Endpoint | None = mesc.get_default_endpoint()
# get the default endpoint of a network
endpoint: Endpoint | None = mesc.get_endpoint_by_network(5)
# get the default endpoint for a particular tool
endpoint: Endpoint | None = mesc.get_default_endpoint(profile='xyz_tool')
# get the default endpoint of a network for a particular tool
endpoint: Endpoint | None = mesc.get_endpoint_by_network(5, profile='xyz_tool')
# get an endpoint by name
endpoint: Endpoint | None = mesc.get_endpoint_by_name('local_goerli')
# parse a user-provided string into a matching endpoint
# (first try 1. endpoint name, then 2. chain id, then 3. network name)
endpoint: Endpoint | None = mesc.get_endpoint_by_query(user_str, profile='xyz_tool')
# find all endpoints matching given criteria
endpoints: list[Endpoint] = mesc.find_endpoints(chain_id=5)
use mesc::{MescError, Endpoint};
use std::collections::HashMap;
type OptionalResult = Result<Option<Endpoint>, MescError>;
type MultiResult = Result<Vec<Endpoint>, MescError>;
type MetadataResult = Result<HashMap<String, serde_json::Value>, MescError>;
// check whether mesc is enabled
let enabled: bool = mesc::is_mesc_enabled();
// get the default endpoint
let endpoint: OptionalResult = mesc::get_default_endpoint(None);
// get the default endpoint of a network
let endpoint: OptionalResult = mesc::get_endpoint_by_network("5", None);
// get the default network for a particular tool
let chain_id: OptionalResult = mesc::get_default_endpoint(Some("xyz_tool"));
// get the default endpoint of a network for a particular tool
let endpoint: OptionalResult = mesc::get_endpoint_by_network("5", Some("xyz_tool"));
// get an endpoint by name
let endpoint: OptionalResult = mesc::get_endpoint_by_name("local_goerli");
// parse a user-provided string into a matching endpoint
// (first try 1. endpoint name, then 2. chain id, then 3. network name)
let user_str = "local_goerli";
let endpoint: OptionalResult = mesc::get_endpoint_by_query(user_str, Some("xyz_tool"));
// find all endpoints matching given criteria
let query = mesc::MultiEndpointQuery::new().chain_id("5").unwrap();
let endpoints: MultiResult = mesc::find_endpoints(query);
Imagine a crypto cli tool xyz
. This tool has an argument -r <RPC_URL>
that specifies which RPC endpoint to use.
If xyz
uses MESC, then -r
can become a much more versatile argument. Instead of just accepting a plain URL, -r
can accept 1. an endpoint name, 2. chain id, or 3. a network name. Each of the following might resolve to the same RPC url:
xyz -r localhost:8545
(url)xyz -r local_goerli
(endpoint name)xyz -r 5
(chain id)xyz -r goerli
(network name)
This url resolution can implemented within xyz
using:
# python code used by xyz tool
endpoint = mesc.get_endpoint_by_query(user_input, profile='xyz')
url = endpoint['url']
// rust code used by xyz tool
let endpoint = mesc::get_endpoint_by_query(user_input, Some("xyz"))?;
let url = endpoint.url;