# Welcome to The New Reality!

Metaverse is **one of the first public Blockchains in China** and has been operating successfully for four years. Our Mission is to drive **blockchain technology adoption** by building **developer-friendly tools** as well as **easy-to-use user interfaces** so that non-technical users are equally empowered to use this disruptive technology in both their business and daily life.   &#x20;

Thank you for taking the time to read our Docs. We hope this documentation will improve your understanding of our technology stack and how you can use Metaverse to build your Dapps!

**Old Metaverse Documentation**: [docs.mvs.org](https://docs.mvs.org/)

## Our Tool Kit

Since our inception, we have developed tools for third-party developers to build decentralized applications.  In 2020, we decided to revise our strategy to further promote the use of our technologies by a wider developer community and started building **Metaverse on Substrate**.&#x20;

Metaverse on Substrate (MOS) provides all the unique features and technologies that make Metaverse a unique platform as well as new modules, which will allow us to broaden our community. All our current features are listed below:

* Entropy: Our Native Token
* Smart Assets
* Digital Identity
* Smart Contracts

### Follow us on social media

[*Facebook*](https://www.facebook.com/mvsofficial/)– Share everything about Metaverse with your friends and family

[*Twitter*](https://twitter.com/mvs_org)– The place to learn all about Metaverse latest developments

[*Telegram*](https://t.me/Metaverse_Blockchain)– A friendly chat room for people to exchange and learn more about Metaverse

[*Discord*](https://discord.gg/56ky6fb)– The place to discuss tech and solve development issues

[*Medium*](https://medium.com/metaverse-blockchain)– Publications related to Metaverse&#x20;

[*Reddit*](https://www.reddit.com/r/Metaverse_Blockchain/)– The OG Club


# Introduction

Metaverse provides unique developer tools with a strong focus on Digital Assets, Digital Identities and Smart Contracts.

Metaverse offers easy-to-use development kits that power the future of Finance and the Digital Economy. We support developers of decentralized applications by reducing transaction and deployment costs without compromising on security. Through the  Hyperspace Blockchain, we have implemented one of the first functional dual-consensus (POW – POS) block production mechanisms, which ensures both low latency and security.

Continuing the legacy of a successful and innovative platform, we are proud to introduce the next evolutionary step, The New Metaverse Platform. As its predecessor, the New Metaverse Platform is an infrastructure layer of blockchain technology aimed to contribute to the decentralization of the ecosystem. In the new iteration, at its core, we enable the network layer and secure the layer using the Substrate modular framework in order to achieve higher scalability, long-term expansion, and to connect decentralized applications and services. We will also allow other independent blockchains to connect, exchange information and transactions.

## Why Substrate?

Substrate offers a modular development framework, which allowed Metaverse developers to use core DLT primitives built by Parity Technologies and adapt them to the specific needs of our platform. The development path our team chose was to do a custom implementation for our own node, RPC synchronization, cryptography, networking, storage, consensus, a light client and telemetry using a combination of the Substrate Core, Substrate Runtime Module Library and Substrate Node in the first phase (explanation of each element below).

Building on a modular framework will also facilitate the development of smart contracts on the Metaverse platform, which is a core element missing in our former implementation. Smart Contracts will be executed in our own Metaverse Virtual Machine (MVM), an Ethereum-compatible VM. This will allow Ethereum developers to seamlessly run their Solidity code on the Metaverse Hyperspace Blockchain, and benefit from considerably lower execution and transaction costs. The major difference is that code is run in the Substrate runtime and not on Ethereum mainnet. This feature is extremely useful as it will allow us to onboard talented developer teams from the vibrant Ethereum community and gradually introduce them to Metaverse platform functionalities.

In the new Metaverse platform, we have also incorporated a  DiD pallet, which will allow us to introduce advanced self-sovereign digital identity tools. Although we have basic DiD tools available on our current platform, the modular framework pallet will considerably increase the versatility of our DiD solution. For instance, it will allow us to add attributes on- and off-chain. It will also allow digital identities to sign off-chain transactions, a useful property to leverage off-chain information.

## How does Substrate Work?

Substrate can be used in three different ways: Substrate Node, Substrate FRAME, and Substrate Core. A Substrate Node allows developers to run their own blockchain by submitting a configuration file (JSON file) that includes all parameters to create the Genesis Block.

Substrate FRAME is the method used by Substrate Node. This method includes customizable library modules, also called pallets, and allows developers to create their own pallet. Substrate Core allows developers to fully express their creativity and does not require them to use FRAME. This allows them to develop a runtime in any language they are familiar with and that is compatible with WebAssembly. Although this tool tends to be more difficult to use because of the additional configuration work required, they offer considerably more development freedom than existing framework and libraries.

To summarize, building The New Metaverse platform on Substrate modular framework, encompasses all the knowledge of previously built blockchain implementations (Bitcoin and Ethereum). Functionalities like balances, governance, accounts and smart contracts can be implemented similar to plugging in a library. Finally, a key feature is that Substrate also comes with the ability to implement forkless runtime upgrades.


# Metaverse Litepaper


# Entropy ($ETP)

Entropy (ETP) is Metaverse's Token. This name is inspired by the second law of thermodynamics, which describes the chaos in a system's microscopic particles.&#x20;

Our circulating supply will be capped to **100 million ETP** and our smallest denomination is 10^-8. ETP is a foundational element of our Blockchain ecosystem as it incentivizes miners and stakers to **secure our Blockchain**. ETP's security is guaranteed by Elliptic Curve Digital Signature Algorithms (ECDSA).

Besides acting as a core incentive to secure our blockchain, ETP has also become a **core element of our DeFi ecosystem**, Gene Finance, and has allowed our community to earn Liquidity Mining rewards. As our DeFi ecosystem expands, we look forward to working with the community in bringing more utility to ETP holders.&#x20;

On the new Metaverse, ETP is used to pay for **transaction fees** and ensure the proper **execution of smart contracts** similar to Gas on Ethereum. Similar to our legacy chain, ETP can be used to pay for the **creation of digital assets and digital identities.**


# UTXO ETP to VM ETP (Hyperspace/New Frontier) migration

Metaverse original chain, created in 2017, is based on the UTXO model like Bitcoin. Since 2021, the Metaverse Virtual Machine (VM) has been launched in order to allow smart contracts.

{% hint style="danger" %}
This Swap service is a **one-way swap** from the UTXO chain to the Virtual Machine Chain.&#x20;

**You will not be able to swap back to the UTXO chain.**&#x20;

Most exchanges currently only support the UTXO chain at the moment.&#x20;

We recommend you only swap the amount of ETP you plan to use in the Metaverse Virtual Machine.&#x20;
{% endhint %}

This guide is designed to introduce the swap of UTXO ETP ("old ETP") to VM ETP ("new ETP"). &#x20;

{% hint style="info" %}
Note this tutorial is based on MyETPWallet.&#x20;

**Make sure you are connected to the Mainnet.**&#x20;

Log in to your wallet and follow the instructions below:&#x20;

<http://app.myetpwallet.com>
{% endhint %}

After you have logged in, your ETP wallet should look like this:

![](/files/-MUQ7L2TBvrwqamesmWg)

Next, click on **Identities** as shown below:

![](/files/-MUQ7l2uWdyvr71x54Cz)

Once in the Identities tab, you should either see a prompt to **create your VM addres**s or the **VM address that was created for you** automatically. If the VM address was already created for you, you can directly jump to the step Swap UTXO ETP for VM ETP.

## **Create your VM Address**

First, click on **Create VM address**.

![](/files/-MUQ9kijHb27oLfB88vr)

Second, enter your wallet password and click on **Generate VM address:**

![](/files/-MUQBH3VQRst_bd4a_cH)

After you have created your VM address, it should appear at the top of your **Identities** tab as shown below:

![](/files/-MUQBsTWdwj8oVwZ_I8u)

## **Swap UTXO ETP for New ETP**

Now that you have created your VM address, you can go to the **Swap** tab as illustrated below:

![](/files/-MUQDFB0VCSYNUg4ye-K)

In the Swap tab, enter the amount of ETP you would like to transfer to the New Metaverse ETP Chain and click on **Next** as shown in the image below:

![](/files/-MUQEsnZCoShOKbl5pff)

Review the transaction data. Then, enter your password and click on **Sign and Send**.&#x20;

![](/files/-MUQFYXidqIQcEjTu6LK)

If your transaction was successful, you should see a similar notification on your screen and make sure to keep a record of your transaction ID (shown in grey below):

![](/files/-MUQFnjgoQIZkJqTctmx)

After we complete the swap for you, you simply need to use your current backup words (also called seed phrase) to have access to your ETP in the new MetaverseVM browser extension. We may need up to 12 hours to make sure your ETP has been properly transferred to the new chain. Please download the Metaverse VM extension on [Google Chrome](https://chrome.google.com/webstore/detail/metaversevm/bnkgokfnchhoiipnofiibeohpmnbaelb).


# Hyperspace to New Frontiers migration

Hyperspace is the original Virtual Machine of Metaverse, launched in 2021. It will then migrate to New Frontiers in 2022, in order to drastically increase blockspeed.

### I have ETP on Hyperspace, how can I migrate to New Frontiers?

You don't need to do anything. New Frontiers is initialized using Hyperspace state, so all your assets and balances will automatically appear in New Frontiers.

The official RPC endpoints will also be migrated, meaning your wallet will automatically connect to New Frontiers once launched.

### I'm running a node, how can I migrate?

If you are running a node, simply stop your Hyperspace node and setup a New Frontiers node from scratch. You can find the node setup tutorial on mvs-org [Github](https://github.com/mvs-org/new-frontiers)


# MetaverseVM Browser Extension

First, make sure you are using the **latest version of our Browser extension: 0.11.10.**

You can find our **latest software** on [Google Chrome](https://chrome.google.com/webstore/detail/metaversevm/bnkgokfnchhoiipnofiibeohpmnbaelb).

## About Metaverse Browser Plug-in

The Metaverse Browser plug-in is a solution inspired by Metamask, which allows our users to interact with Metaverse Virtual Machine in a seamless manner. It is based on the latest MIT licensed code of MetaMask.&#x20;

This guide assumes you are using our **Chrome extension**.&#x20;

## **Tutorial**

This tutorial explains both how to create a wallet and how to import a wallet.

### Create a Wallet

First, click on the **Add to Chrome** button.

![](/files/-MYQIUzzdpErwK1GTlDN)

Then, click on the **Add Extension** button.

![](/files/-MYQIjxqrMNIepyaUUUl)

Next, click on **Get Started**.

![](/files/-MYQJGW0UmRf3BGH8NL1)

After doing so, you should now see the page below and click on **Create a Wallet.**

![](/files/-MTBBaw514WvKltkqyoX)

You will first need to create a password as shown below. After you are done, **check the box** next to "I have read and agreed to the Terms of Use" and click on the **Create** button.

![](/files/-MTBD_6SSOncUKNCsnUV)

You will then see the Secret Backup Phrase page. This is the most important step because your secret backup phase is the only way to recover your assets. Your secret backup phrase could also be used to steal your digital assets.&#x20;

Simply **click on the lock** and follow the tips to save your backup phrase.

![](/files/-MTBH41WkOqL6kHut2ID)

Once you are done with this, **complete the puzzle** to **confirm you are the owner** of the backup phrase.&#x20;

![](/files/-MTBHXAadHpOQ0AsJg_3)

**CONGRATULATIONS!** You are done with the set up of your Metaverse browser plug in. Please carefully **read the tips**, make sure to **add Metaverse to your favorite plug-ins** and test that your **Metaverse plug-in is operational**.

![](/files/-MTBINLLw5Mp7ZbakMSU)

To add Metaverse plug-in to your favorite plug-in, first click again on the **Extension** button.

![](/files/-MTLOQyc0UxSvyEQxxWA)

Click on the **pin** button next to the application called **Metaverse**.&#x20;

![](/files/-MTLPSEib_f-Lu_Fjfzv)

After this, you should be able to see the **Metaverse plug-in in your browser** as shown below.

**Congratulations!** You can now start using MetaverseVM Browser wallet.

### Import a wallet

If you already have a New Metaverse wallet (most MyETPWallet users should have one already), you can simply import it in the following manner.

First, click on the **Import Wallet** button.

![](/files/-MYQKaPChkuaqqTwi8z3)

Enter your **seed phrase and password**. Make sure you have **ticked the box** next to "I have read and agree to the Terms of Use." Finally, click on the **Import** button.

![](/files/-MYQLn1fDbTCk8DvtAhG)

Congratulations! You should now see your ETP balance after clicking on the **All Done** butto&#x6E;**.**

![](/files/-MYQMcTUwMs49u3-_AhI)


# Metamask

To connect to Metaverse mainnet using Metamask, simply add a new network using the following parameters:

* **Network Name:** Metaverse
* **New RPC URL:** <https://vm-rpc-us.mvs.org>
* **Chain ID**: 23
* **Symbol**: ETP
* **Block Explorer URL:** <https://vm-explorer.mvs.org/mainnet>


# Assets Tutorials


# Add Metaverse Smart Tokens (MST) in MetaverseVM Browser wallet

## Introduction

Metaverse Smart Tokens are tokens, which follow a given list of standards and rules (e.g. transfer, transaction approval, token supply, data access, etc.). &#x20;

MSTs currently exist in **two different forms**: **MRC-20 MSTs** and **UTXO MSTs**. MRC-20 tokens exist in the MetaverseVM while UTXO MSTs exist on the UTXO Chain and can be accessed via MyETP Wallet. MRC-20 tokens and UTXO MSTs exist on two different ledgers. As a result, an asset issued on the UTXO chain will not appear on the MetaverseVM.

Metaverse technical team is working towards a solution to transfer UTXO MSTs to the Metaverse VM as MRC-20 tokens. Once a solution is found, we will advise the Metaverse community on how to proceed with the migration of UTXO MSTs to the new ledger. &#x20;

In the following guide, we introduce how to add MRC-20 tokens to the MetaverseVM Browser wallet.&#x20;

## Tutorial

First, **log in to your MetaverseVM browser wallet** by entering your password and click on **Unlock**.

![](/files/-MU7F_TPzaqFxeuvJoQQ)

Next, go to the following website: <https://dapp-brrr.mvs.org/> and click on **Connect to MetaverseVM Extension**.

![](/files/-MU7G5X0-NmOoXi_AVyT)

Then, click on **Next** and **Connect** to connect your wallet to the **Brrr dapp**. This dapp will allow users to familiarize themselves with the process to add new MRC-20 assets to their MetaverseVM Browser wallet.&#x20;

First, click on **Add token**:&#x20;

![](/files/-MU7JpIDLK-WVLISByrT)

Then, click on the **Custom Token** tab:

![](/files/-MU7KOvnhtu5DfKrkw_d)

Once you see the form above, copy-paste the following address in the Token Contract Address box: **0x40Ef64282A61f7ae4d9a8E2D5a7C05E415B951D3** and click on **Next.**

![](/files/-MU7Liz_CajWkRTTKJGk)

Once you arrive on the Add tokens page,  click on the **Add Tokens**.

If you have successfully added BRRR token, you should see the following page in your wallet:

![](/files/-MU7MWoquuLH1g88FyEZ)

After you have successfully added the BRRR token, click on **Click here to make the printer go brrr.**&#x20;

![](/files/-MU9DenNYNHT2L_rAJKm)

Then, click **Confirm** in your wallet.

&#x20;

![](/files/-MU7N9wdqpDUru6KKkqd)

After you confirmed, you should see the following confirmation page.&#x20;

![](/files/-MU9LgcNu_y9mdfQ_9uP)

After your transaction is confirmed, you will see the notification at the bottom.

![](/files/-MU9LobEuBrchVGmEDsL)


# Metaverse Identifiable Tokens (MIT)

*Coming soon...*


# Avatars

*Coming soon...*


# KILT Protocol

KILT is a protocol that will allow Metaverse to offer self-sovereign identities to all its users as well as revocable credentials.  Self-sovereign identities allow users to become owners of their data and help them to regain control over which data they want to share.&#x20;

&#x20;KILT protocol over other solutions is developer-friendly and allows developers to easily build applications leveraging sovereign digital identities thanks to their JavaScript SDK.&#x20;

***Tutorials coming soon....***


# Testnet Set Up

In this section, developers will find&#x20;the technical documentation and information on how you can run our Alpha testnet node and connect to the Betelgeuse testnet blockchain. Our testnet is a great environment to test your code before deploying it on the testnet.&#x20;

**Important notice** – once your node is set up and ready to run, please send us your testnet address, and we will send you 50 testnet ETP tokens because you will need them to test our new features.

Contact us on [Discord](https://discord.gg/56ky6fb) should you have any additional questions or concerns.

**Useful resources** – Betelgeuse Testnet: <https://github.com/mvs-org/betelgeuse>


# MetaverseVM Browser Extension - Testnet Version

We welcome the community to test Metaverse Browser plug-in and provide feedback on their user experience.&#x20;

First, make sure you are using the **latest version of our Browser extension: 0.11.4.**

You can find our **latest software** on [Github](https://github.com/mvs-org/metaverse-vm-extension/releases).

## About Metaverse Browser Plug-in

The Metaverse Browser plug-in is a solution inspired by Metamask, which allows our users to interact with Metaverse Virtual Machine in a seamless manner. It is based on the latest MIT licensed code of MetaMask. We currently support **4 browsers** including Brave, Chrome, Firefox, and Opera.  &#x20;

This guide assumes you are using our **Chrome extension**.&#x20;

## **Tutorial**

**Click on the Browser you are using** to download our extension automatically.

* [Brave](https://github.com/mvs-org/metaverse-vm-extension/releases/download/prototype/metaversevm-brave-0.11.4.zip)
* [Chrome](https://github.com/mvs-org/metaverse-vm-extension/releases/download/prototype/metaversevm-chrome-0.11.4.zip)
* [Firefox](https://github.com/mvs-org/metaverse-vm-extension/releases/download/prototype/metaversevm-firefox-0.11.4.zip)
* [Opera](https://github.com/mvs-org/metaverse-vm-extension/releases/download/prototype/metaversevm-opera-0.11.4.zip)

After the download is complete, **unzip the ZIP file** and import it to your Chrome browser as illustrated below. &#x20;

First, click on the **Extension** button.&#x20;

![](/files/-MTLNK1SfLN9pXnMpmHS)

Then, click on **Manage Extensions**.

![](/files/-MTLNxNYHPC6IwOsz1EV)

Next, make sure **Developer Mode** is **turned on**, click on **Load Unpacked** and **select the file** you just unzipped before (it should be located on your computer in your Downloads folder if you did not save it to another location).

![](/files/-MTfL1SaZsL6jKffUY04)

After doing so, you should now see the page below and click on **Create a Wallet.**

![](/files/-MTBBaw514WvKltkqyoX)

You will first need to create a password as shown below. After you are done, **check the box** next to "I have read and agreed to the Terms of Use" and click on the **Create** button.

![](/files/-MTBD_6SSOncUKNCsnUV)

You will then see the Secret Back Up Phrase page. This is the most important step because your secret back up phase is the only way to recover your assets. Your secret back up phrase could also be used to steal your digital assets.&#x20;

Simply **click on the lock** and follow the tips to save your back up phrase.

![](/files/-MTBH41WkOqL6kHut2ID)

Once you are done with this, **complete the puzzle** to **confirm you are the owner** of the backup phrase.&#x20;

![](/files/-MTBHXAadHpOQ0AsJg_3)

**CONGRATULATIONS!** You are done with the set up of your Metaverse browser plug in. Please carefully **read the tips**, make sure to **add Metaverse to your favorite plug-ins** and test that your **Metaverse plug-in is operational**.

![](/files/-MTBINLLw5Mp7ZbakMSU)

To add Metaverse plug-in to your favorite plug-in, first click again on the **Extension** button.

![](/files/-MTLOQyc0UxSvyEQxxWA)

Click on the **pin** button next to the application called **Metaverse**.&#x20;

![](/files/-MTLPSEib_f-Lu_Fjfzv)

After this, you should be able to see the **Metaverse plug-in in your browser** as shown below.

![](/files/-MTLPqlIcZQMgh58kH-Z)

**Last step!**  Let's make sure your Metaverse plug-in functions using a **fun DAPP (decentralized application)**.

First, go to the following website: <https://dapp-counter.mvs.org>

Once you are on this page, click on **Connect to MetaverseVM Extension**.&#x20;

![](/files/-MTZkp8A6fEJl-V65YdE)

After you clicked, the Metaverse plug-in should automatically launch in a new window as illustrated below. Next, **enter your password** and click **Unlock**.&#x20;

![](/files/-MTZku_CVCkDU0mIz6Y6)

If you cannot see the Window, click on the **extension icon shown below** and it should directly appear in your browser:

![](/files/-MTZlf6StnYTM8kGeDxe)

&#x20;After you have connected your plug-in to the dapp, you should see the application below. Then, click on the **Click here to raise your hand** button.&#x20;

![](/files/-MTZmLNGs3g2qAQiiKzE)

You should now see the page below in your wallet and click on **Confirm**:

![](/files/-MTZmkDn_438u4V0UChl)

After you click on confirm, **wait for your transaction to be confirmed**. You will see the page below:

![](/files/-MTZnGGb9J-glcpJWGvY)

Once the transaction is confirmed, you will see a **notification** at the bottom of your screen similar to the one shown below:

![](/files/-MTZnkGONP3w-hdHUWrB)

&#x20;


# Metamask - Testnet version

To connect to Metaverse testnet using Metamask, simply add a new network using the following parameters:

* **Network Name:** Metaverse Testnet
* **New RPC URL:** <https://nf-testnet-rpc.mvs.org>
* **Chain ID**: 43
* **Symbol**: ETP
* **Block Explorer URL:** <https://vm-explorer.mvs.org/testnet>


# RPC

The client exposes HTTP and WS endpoints for RPC connections. The default ports are 9933 for HTTP and 9944 for WS but can be specified running the client with the following parameters:`--ws-port 7949  --rpc-port 7939.`

To **run a full node without mining and expose certain RPC and HTTP port**, use the following command:

```typescript
betelgeuse --chain betelgeuse.json --port 41337  --ws-port 7949  --rpc-port 7939 --rpc-methods 'Unsafe' --unsafe-ws-external --unsafe-rpc-external --rpc-cors "all"
```

To **get a list of all RPC methods**, the node has an RPC endpoint called `rpc_methods`:

```typescript
$ curl -H "Content-Type: application/json" -d '{"id":1, "jsonrpc":"2.0", "method": "rpc_methods"}' http://localhost:9933/
```

*Response:*

`{"jsonrpc":"2.0","result":{"methods":["account_nextIndex","author_hasKey","author_hasSessionKeys","author_insertKey","author_pendingExtrinsics","author_removeExtrinsic","author_rotateKeys","author_submitAndWatchExtrinsic","author_submitExtrinsic","author_unwatchExtrinsic","chain_getBlock","chain_getBlockHash","chain_getFinalisedHead","chain_getFinalizedHead","chain_getHead","chain_getHeader","chain_getRuntimeVersion","chain_subscribeAllHeads","chain_subscribeFinalisedHeads","chain_subscribeFinalizedHeads","chain_subscribeNewHead","chain_subscribeNewHeads","chain_subscribeRuntimeVersion","chain_unsubscribeAllHeads","chain_unsubscribeFinalisedHeads","chain_unsubscribeFinalizedHeads","chain_unsubscribeNewHead","chain_unsubscribeNewHeads","chain_unsubscribeRuntimeVersion","offchain_localStorageGet","offchain_localStorageSet","payment_queryInfo","state_call","state_callAt","state_getChildKeys","state_getChildStorage","state_getChildStorageHash","state_getChildStorageSize","state_getKeys","state_getKeysPaged","state_getKeysPagedAt","state_getMetadata","state_getPairs","state_getRuntimeVersion","state_getStorage","state_getStorageAt","state_getStorageHash","state_getStorageHashAt","state_getStorageSize","state_getStorageSizeAt","state_queryStorage","state_subscribeRuntimeVersion","state_subscribeStorage","state_unsubscribeRuntimeVersion","state_unsubscribeStorage","subscribe_newHead","system_accountNextIndex","system_addReservedPeer","system_chain","system_health","system_name","system_networkState","system_nodeRoles","system_peers","system_properties","system_removeReservedPeer","system_version","unsubscribe_newHead"],"version":1},"id":1}`

**Add parameters in the call**. For example, get a block by its hash value:

```typescript
$ curl -H "Content-Type: application/json" -d '{"id":1, "jsonrpc":"2.0", "method": "chain_getBlock", "params":["0x3fa6a530850324391fde50bdf0094bdc17ee17ec84aca389b4047ef54fea0037"]}' http://localhost:9933
```

*Response:*

`{"jsonrpc":"2.0","result":{"block":{"extrinsics":["0x280402000b50055ee97001","0x1004140000"],"header":{"digest":{"logs":["0x06424142453402af000000937fbd0f00000000","0x054241424501011e38401b0aab22f4d72ebc95329c3798445786b92ca1ae69366aacb6e1584851f5fcdfcc0f518df121265c343059c62ab0a34e8e88fda8578810fbe508b6f583"]},"extrinsicsRoot":"0x0e354333c062892e774898e7ff5e23bf1cdd8314755fac15079e25c1a7765f06","number":"0x16c28c","parentHash":"0xe3bf2e8f0e901c292de24d07ebc412d67224ce52a3d1ffae76dc4bd78351e8ac","stateRoot":"0xd582f0dfeb6a7c73c47db735ae82d37fbeb5bada67ee8abcd43479df0f8fc8d8"}},"justification":null},"id":1}`

Betelgeuse node uses [SCALE encoding](https://substrate.dev/docs/en/knowledgebase/advanced/codec) as a format that is suitable for resource-constrained execution environments. You will need to decode the information and use the chain [metadata](https://substrate.dev/docs/en/knowledgebase/runtime/metadata) (`state_getMetadata`) to obtain human-readable information.

### **Tracking the Chain Head**

Use the RPC endpoint`chain_subscribeFinalizedHeads`to subscribe to a stream of hashes of finalized headers, or`chain_FinalizedHeads`to fetch the finalized header's latest hash. Use`chain_getBlock`to get the block associated with a given hash. `chain_getBlock`only accepts block hashes, so if you need to query intermediate blocks, use`chain_getBlockHash`to get the block hash from a block number.


# Substrate API Sidecar

Parity maintains an RPC client, written in TypeScript, that exposes a limited set of endpoints. It handles the metadata and codec logic so that you are always dealing with decoded information. It also aggregates information that a business may need for accounting and auditing (e.g. transaction fees).

The sidecar facilitates the following operations:&#x20;

* Fetch blocks
* Get the balance of an address atomically (i.e., with a corresponding block number)
* Get the chain's metadata
* Get a transaction fee prediction
* Calculate outstanding staking rewards for an address
* Submit transactions to a node's transaction queue
* etc.

The client runs on an HTTP host. The following examples use python3, but you can query any way you prefer at [http://HOST:PORT/](https://learn.mvs.org/developer-guides/testnet/http:/HOST:PORT). The default is <http://127.0.0.1:8080>.

## Fetching a Block

Fetch a block using the`block/number`endpoint. To get the chain tip, omit the block number.

```python
import requests
import json

url = 'http://127.0.0.1:8080/block/2077200'
response = requests.get(url)
if response.ok:
    block_info = json.loads(response.text)
    print(block_info)
```

This returns a fully decoded block. In the`balances.transfer`extrinsic, the `partialFee` item is the transaction fee. It is called a "partial fee" because the total fee would include the`tip`field. Notice that some extrinsics do not have a signature. These are inherents.

When tracking transaction fees, the`extrinsics.paysFee`value is not sufficient for determining if the extrinsic had a fee. This field only means that it would require a fee if submitted as a transaction. In order to charge a fee, a transaction also needs to be signed. So in the following example, the`timestamp.set`extrinsic does not pay a fee because it is an inherent, put in the block by the block author.

`{'number': '1419394', 'hash': '0xaa4ebb82c0fe2a0afddb02872f6fd72cc9b68de1990e54d351d8152da040681e','parentHash':'0x9022a1fe7192366553c0caa3e1d0d9f7d9fd2eab601ea4a26e49ba66375fb735','stateRoot':'0x6b4c0b81bc86e3104ea15b38e457e9f2d2395d997a8737a7072c2c1b2aa057ce','extrinsicsRoot':'0x9a66295996ccfab5b71924f1816a68854bfa4bae92e196770235b8c5ebf67f8a','authorId': '15V6NjwmKkZihe644Tyr8GVLxjEzBAHktf6ZcJCTx7RPCoYS','logs': [{'type': 'PreRuntime','index': '6','value': ['BABE','0x03a0000000be9ce20f000000001815f7649023d7af85be14fe902084fec2bf2bc10175b6c49f5fd37556b58f7b128e4c1de5d4b6df0ef5bcd817b8c2337a381b9e15bdb3b9a831a1308cf797091484ae9f861b7978852164dd018b4dddd6ef7e438a8d2d9b5644567ebec9700d']},{'type': 'Seal','index': '5','value': ['BABE','0x5809634ab178c8484724b19f07035510dd6e6457bfa0423ba74887d67bc4b135713d926a93d62e76950f31750aabd57f93065b6fad273fb77e84b3185645a58d']}],'onInitialize': {'events': []},'extrinsics': [{'method': 'timestamp.set','signature': None,'nonce': '0','args': {'now': '1599057012000'},'tip': '0','hash': '0x830017ff2f8971d488ae4d35c851c389ce74271c4c1daf8aea70baffda018a0b','info': {},'events': [{'method': 'system.ExtrinsicSuccess','data': [{'weight': '158000000','class': 'Mandatory','paysFee': 'Yes'}]}],'success': True,'paysFee': True},{'method': 'parachains.setHeads','signature': None,'nonce': '0','args': {'heads': []},'tip': '0','hash': '0xcf52705d1ade64fc0b05859ac28358c0770a217dd76b75e586ae848c56ae810d','info': {},'events': [{'method': 'system.ExtrinsicSuccess','data': [{'weight': '1000000000','class': 'Mandatory','paysFee': 'Yes'}]}],'success': True,'paysFee': True},{'method': 'staking.bondExtra','signature': {'signature': '0x92b50d7d4317503971f5f670a88adfe1e8e3e5aa4ba62c1d8792590abfd4805dad8ac8d442af8610236af7c3c48269d9487584486dca684dd6b89aed4c7f3d83','signer': '15x3TLV67TVAde2pcuQsNCs8KNWGG769UvzjfNtzex9mL6Ld'},'nonce': '2','args': {'max_additional': '1000000000000'},'tip': '0','hash': '0xab2b0a862a7d4c18a1f7294d2db181af3a7fe00bde70de88b61cefe4f9f74012','info': {'weight': '355000000','class': 'Normal','partialFee': '122000000'},'events': [{'method': 'staking.Bonded','data': ['15x3TLV67TVAde2pcuQsNCs8KNWGG769UvzjfNtzex9mL6Ld','1000000000000']},{'method': 'treasury.Deposit', 'data': ['97600000']},{'method': 'balances.Deposit','data': ['15V6NjwmKkZihe644Tyr8GVLxjEzBAHktf6ZcJCTx7RPCoYS', '24400000']},{'method': 'system.ExtrinsicSuccess','data': [{'weight': '355000000', 'class': 'Normal', 'paysFee': 'Yes'}]}],'success': True,'paysFee': True},{'method': 'balances.transfer','signature': {'signature': '0x5c63107916871286a946c8d06052a0ac7c50c6a052c5a9dee87f26dce3dac64a18f24cf07a4de69dc56733ad9e0a2aa5b95a11428203ed32603c22544369d902','signer': '1JVrK16XZm9vyZjHoYVPjtZ35LvTQ4oyufMoUFTFpAUhath'},'nonce': '3017','args': {'dest': '12YFp3fPi73U3pwRqK9Hwa1iVhaGSTq3e3XaTbM5UfuP1LpX','value': '18539953920000'},'tip': '0','hash': '0x0e7692706202dad75c2a468aff6bf78b88d505ef7031b82b6e9d5220817f082b','info': {'weight': '195000000','class': 'Normal','partialFee': '156000000'},'events': [{'method': 'balances.Transfer','data': ['1JVrK16XZm9vyZjHoYVPjtZ35LvTQ4oyufMoUFTFpAUhath','12YFp3fPi73U3pwRqK9Hwa1iVhaGSTq3e3XaTbM5UfuP1LpX','18539953920000']},{'method': 'treasury.Deposit', 'data': ['124800000']},{'method': 'balances.Deposit','data': ['15V6NjwmKkZihe644Tyr8GVLxjEzBAHktf6ZcJCTx7RPCoYS', '31200000']},{'method': 'system.ExtrinsicSuccess','data': [{'weight': '195000000', 'class': 'Normal', 'paysFee': 'Yes'}]}],'success': True,'paysFee': True}], 'onFinalize': {'events': []}}`\
The JS number type is a 53-bit precision float. There is no guarantee that the numerical values in the response will have a numerical type. Any numbers larger than`2**53-1`will have a string type.

## Submitting a transaction

Submit a serialized transaction using the tx endpoint with an HTTP POST request.

```python
import requests
import json

url = 'http://127.0.0.1:8080/tx/'
tx_headers = {'Content-type' : 'application/json', 'Accept' : 'text/plain'}
response = requests.post(
    url,
    data='{"tx": "0xed0...000"}', # A serialized tx.
    headers=tx_headers
)
tx_response = json.loads(response.text)
```

If successful, this endpoint returns a JSON with the transaction hash. In case of error, it will return an error report, e.g.:

`{`\
`"error": "Failed to parse a tx" | "Failed to submit a tx",`\
`"cause": "Upstream error description"`\
`}`

‌<br>


# Transaction Construction and Signing

This page will discuss the transaction format in Betelgeuse and how to create, sign, and broadcast transactions. Like the other pages in this guide, this page demonstrates some of the available tools. Always refer to each tool's documentation when integrating.<br>

## Transaction **Construction**

Betelgeuse provides some basic information common to all transactions.

* **Address**: The SS58-encoded address of the sending account.
* **Block Hash**: The hash of the checkpoint block.
* **Block Number**: The number of the checkpoint block.
* **Genesis Hash**: The genesis hash of the chain.
* **Metadata**: The SCALE-encoded metadata for the runtime when submitted.
* **Nonce**: The nonce for this transaction.\*
* **Spec Version**: The current spec version for the runtime.
* **Transaction Version**: The current version for transaction format.
* **Tip**: Optional, the tip to increase transaction priority.
* **Era Period**: Optional, the number of blocks after the checkpoint for which a transaction is valid. If zero, the transaction is immortal.

\*The nonce queried from the System module does not account for pending transactions. You must track and increment the nonce manually if you want to submit multiple valid transactions simultaneously.

Each transaction will have its own (or no) parameters to add. For example, the`transferKeepAlive`function from the Balances pallet will take:

* `dest`: Destination address
* `#[compact] value`: Number of tokens (compact encoding)

Once you have all the necessary information, you will need to:

1. Construct an unsigned transaction.
2. Create a signing payload.
3. Sign the payload.
4. Serialize the signed payload into a transaction.
5. Submit the serialized transaction.

Parity provides the following tools to help perform these steps:

### **Betelgeuse-JS Tools**

Betelgeuse Web wallet contains a set of command line tools for interacting with a Substrate client, including "Signer CLI" to create, sign, and broadcast transactions.

This example will use the`signer submit`command, which will create and submit the transaction. The`signersendOffline`command has the same API but will not broadcast the transaction. `submit` and`sendOffline`must be connected to a node to fetch the current metadata and construct a valid transaction. Their API has the format:

```typescript
yarn run:signer <submit|sendOffline> --account <from-account-ss58> --ws <endpoint> <module.method> [param1] [...] [paramX]
```

Signing:

```typescript
yarn run:signer sign --account <from-account-ss58> --seed <seed> --type <sr25519|ed25519> <payload>
```

For example, let's send 0.5 ETP3 from`121X5bEgTZcGQx5NZjwuTjqqKoiG8B2wEAvrUFjuw24ZGZf2` to `15vrtLsCQFG3qRYUcaEeeEih4JwepocNJHkpsrqojqnZPc2y`.

```typescript
yarn run:signer submit --account 121X5bEgTZcGQx5NZjwuTjqqKoiG8B2wEAvrUFjuw24ZGZf2 --ws ws://127.0.0.1:9944 balances.transferKeepAlive 15vrtLsCQFG3qRYUcaEeeEih4JwepocNJHkpsrqojqnZPc2y 500000000000
```

This will return a payload to sign and an input waiting for a signature. Take this payload and use your normal signing environment (e.g., air-gapped machine, VM, etc.). Sign the payload:

```typescript
yarn run:signer sign --account 121X5bEgTZcGQx5NZjwuTjqqKoiG8B2wEAvrUFjuw24ZGZf2 --seed "pulp gaze fuel ... mercy inherit equal" --type sr25519 0x040300ff4a83f1...a8239139ff3ff7c3f6
```

Save the output and bring it to the machine that you will broadcast from, enter it into the `submit`'s signature field, and send the transaction (or return the serialized transaction if using `sendOffline`).

### TX Wrapper

Parity provides an SDK called TxWrapper to generate and sign transactions offline if you do not want to use the CLI for signing operations.

* **Import private key**

```typescript
import { importPrivateKey } from '@substrate/txwrapper';

const keypair = importPrivateKey(“pulp gaze fuel ... mercy inherit equal”);
```

* **Derive an address from a public key**

```typescript
import { deriveAddress } from '@substrate/txwrapper';

// Public key, can be either hex string, or Uint8Array
const publicKey = “0x2ca17d26ca376087dc30ed52deb74bf0f64aca96fe78b05ec3e720a72adb1235”;
const address = deriveAddress(publicKey);
```

* **Construct a transaction offline**

```typescript
import { methods } from "@substrate/txwrapper";

const unsigned = methods.balances.transferKeepAlive(
  {
    dest: "15vrtLsCQFG3qRYUcaEeeEih4JwepocNJHkpsrqojqnZPc2y",
    value: 500000000000,
  },
  {
    address: "121X5bEgTZcGQx5NZjwuTjqqKoiG8B2wEAvrUFjuw24ZGZf2",
    blockHash: "0x1fc7493f3c1e9ac758a183839906475f8363aafb1b1d3e910fe16fab4ae1b582",
    blockNumber: 4302222,
    genesisHash: "0xe3777fa922cafbff200cadeaea1a76bd7898ad5b89f7848999058b50e715f636",
    metadataRpc, // must import from client RPC call state_getMetadata
    nonce: 2,
    specVersion: 1019,
    tip: 0,
    eraPeriod: 64, // number of blocks from checkpoint that transaction is valid
    transactionVersion: 1,
  },
  {
    metadataRpc,
    registry, // Type registry
  }
);
```

* **Construct a signing payload**

```typescript
import { methods, createSigningPayload } from '@substrate/txwrapper';

// See "Construct a transaction offline" for "{...}"
const unsigned = methods.balances.transferKeepAlive({...}, {...}, {...});
const signingPayload = createSigningPayload(unsigned, { registry });
```

* **Serialize a signed transaction**

```typescript
import { createSignedTx } from "@substrate/txwrapper";

// Example code, replace `signWithAlice` with actual remote signer.
// An example is given here:
// https://github.com/paritytech/txwrapper/blob/630c38d/examples/index.ts#L50-L68
const signature = await signWithAlice(signingPayload);
const signedTx = createSignedTx(unsigned, signature, { metadataRpc, registry });
```

* **Decode payload types**

You may want to decode payloads to verify their contents prior to submission.

```typescript
import { decode } from "@substrate/txwrapper";

// Decode an unsigned tx
const txInfo = decode(unsigned, { metadataRpc, registry });

// Decode a signing payload
const txInfo = decode(signingPayload, { metadataRpc, registry });

// Decode a signed tx
const txInfo = decode(signedTx, { metadataRpc, registry });
```

* **Check a transaction's hash**

```typescript
import { getTxHash } from ‘@substrate/txwrapper’;
const txHash = getTxHash(signedTx);
```

## Transaction Signing

There are several ways to submit a signed payload:

1. Signer CLI (`yarn run:signer submit --tx <signed-transaction> --ws <endpoint>`)
2. Substrate API Sidecar
3. **RPC** with `author_submitExtrinsic` or `author_submitAndWatchExtrinsic`, the latter of which will subscribe you to events to be notified as a transaction gets validated and included in the chain.


# Smart Contracts


# Metaverse VM: An Ethereum Compatible VM

## Introduction

The Metaverse VM (MVM)  is based on Ethereum-compatible smart contract Substrate pallet and SputnikVM: A Blockchain Virtual Machine.

SputnikVM is an implementation of an Ethereum Virtual Machine. It aims to be an efficient, pluggable virtual machine for different Ethereum-based blockchains.

A VM can be started given a Context and a BlockHeader. The user can then fire or step to run it. Those functions would only fail if it needs some information (accounts in the current block, or block hashes of previous blocks). If this happens, one can use the function commit\_account and commit\_blockhash to commit that information to the VM, and fire or step again until it succeeds. The current VM status can always be obtained using the status function.

MVM is a developer-oriented blockchain that strives to provide compatibility with the existing Ethereum developer toolchain and network. It does this by providing a full EVM implementation, a Web3-compatible API, and bridges that connect the MVM to existing Ethereum networks. This allows developers to deploy existing Solidity smart contracts and DApp frontends to MVM with minimal changes.

## Features

* Standalone - can be launched as an independent process or integrated into other apps
* Universal - supports different Ethereum chains, such as ETC, ETH or private ones
* Stateless - only an execution environment connected to independent State storage
* Fast - main focus is on performance
* IoT compatible - designed to support hardware used in embedded devices
* FFI, Protobuf and JSON interface
* Written in Rust, can be used as a binary, cargo crate or shared library

### Structs

| Structs Name                                                                                                          | Description                                                                                                            |
| --------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------- |
| [AccountState](https://docs.rs/sputnikvm/0.10.1/sputnikvm/struct.AccountState.html)                                   | A struct that manages the current account state for one EVM.                                                           |
| &#xD; [BlockhashState](https://docs.rs/sputnikvm/0.10.1/sputnikvm/struct.BlockhashState.html)                         | A struct that manages the current blockhash state for one EVM.                                                         |
| [Context](https://docs.rs/sputnikvm/0.10.1/sputnikvm/struct.Context.html)                                             | A VM context. See the Yellow Paper for more information.                                                               |
| [ContextVM](https://docs.rs/sputnikvm/0.10.1/sputnikvm/struct.ContextVM.html)                                         | A VM that executes using a context and block information.                                                              |
| [ECRECPrecompiled](https://docs.rs/sputnikvm/0.10.1/sputnikvm/struct.ECRECPrecompiled.html)                           | ECREC precompiled contract.                                                                                            |
| [EmbeddedAccountPatch](https://docs.rs/sputnikvm/0.10.1/sputnikvm/struct.EmbeddedAccountPatch.html)                   | Mainnet account patch                                                                                                  |
| [EmbeddedByzantiumAccountPatch](https://docs.rs/sputnikvm/0.10.1/sputnikvm/struct.EmbeddedByzantiumAccountPatch.html) | Mainnet account patch                                                                                                  |
| [EmbeddedByzantiumPatch](https://docs.rs/sputnikvm/0.10.1/sputnikvm/struct.EmbeddedByzantiumPatch.html)               | Embedded Patch                                                                                                         |
| [EmbeddedPatch](https://docs.rs/sputnikvm/0.10.1/sputnikvm/struct.EmbeddedPatch.html)                                 | Embedded Patch                                                                                                         |
| [HeaderParams](https://docs.rs/sputnikvm/0.10.1/sputnikvm/struct.HeaderParams.html)                                   | Block Header                                                                                                           |
| [IDPrecompiled](https://docs.rs/sputnikvm/0.10.1/sputnikvm/struct.IDPrecompiled.html)                                 | ID precompiled Contract                                                                                                |
| [Log](https://docs.rs/sputnikvm/0.10.1/sputnikvm/struct.Log.html)                                                     | Log                                                                                                                    |
| [Machine](https://docs.rs/sputnikvm/0.10.1/sputnikvm/struct.Machine.html)                                             | A VM state with PC.                                                                                                    |
| [PC](https://docs.rs/sputnikvm/0.10.1/sputnikvm/struct.PC.html)                                                       | Represents a program counter in EVM.                                                                                   |
| [PCMut](https://docs.rs/sputnikvm/0.10.1/sputnikvm/struct.PCMut.html)                                                 | Represents a mutable program counter in EVM.                                                                           |
| [RIP160Precompiled](https://docs.rs/sputnikvm/0.10.1/sputnikvm/struct.RIP160Precompiled.html)                         | RIP160 precompiled contract                                                                                            |
| [Runtime](https://docs.rs/sputnikvm/0.10.1/sputnikvm/struct.Runtime.html)                                             | A VM runtime. Only available in eval.                                                                                  |
| [SHA256Precompiled](https://docs.rs/sputnikvm/0.10.1/sputnikvm/struct.SHA256Precompiled.html)                         | SHA256 precompiled contract.                                                                                           |
| [SeqMemory](https://docs.rs/sputnikvm/0.10.1/sputnikvm/struct.SeqMemory.html)                                         | A sequential memory. It uses Rust's Vec for internal representation.                                                   |
| [Stack](https://docs.rs/sputnikvm/0.10.1/sputnikvm/struct.Stack.html)                                                 | Represents an EVM stack.                                                                                               |
| [State](https://docs.rs/sputnikvm/0.10.1/sputnikvm/struct.State.html)                                                 | A VM state without PC.                                                                                                 |
| [Storage](https://docs.rs/sputnikvm/0.10.1/sputnikvm/struct.Storage.html)                                             | Internal representation of an account storage. It will return a RequireError if trying to access non-existing storage. |
| [TransactionVM](https://docs.rs/sputnikvm/0.10.1/sputnikvm/struct.TransactionVM.html)                                 | A VM that executes using a transaction and block information.                                                          |
| [UntrustedTransaction](https://docs.rs/sputnikvm/0.10.1/sputnikvm/struct.UntrustedTransaction.html)                   | Represents an untrusted Ethereum transaction.                                                                          |
| [VMTestPatch](https://docs.rs/sputnikvm/0.10.1/sputnikvm/struct.VMTestPatch.html)                                     | Patch sepcific for the jsontests crate.                                                                                |
| [ValidTransaction](https://docs.rs/sputnikvm/0.10.1/sputnikvm/struct.ValidTransaction.html)                           | Represents an Ethereum transaction.                                                                                    |
| [Valids](https://docs.rs/sputnikvm/0.10.1/sputnikvm/struct.Valids.html)                                               | Mapping of valid jump destination from code.                                                                           |

### Enums

| Enums Name                                                                                  | Description                                                                                                   |
| ------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------- |
| [AccountChange](https://docs.rs/sputnikvm/0.10.1/sputnikvm/enum.AccountChange.html)         | Represents an account. This is usually returned by the EVM.                                                   |
| [AccountCommitment](https://docs.rs/sputnikvm/0.10.1/sputnikvm/enum.AccountCommitment.html) | A single account commitment.                                                                                  |
| [Instruction](https://docs.rs/sputnikvm/0.10.1/sputnikvm/enum.Instruction.html)             | Instructions for the program counter. This is the same as Opcode except PUSH, which might take longer length. |
| [MachineStatus](https://docs.rs/sputnikvm/0.10.1/sputnikvm/enum.MachineStatus.html)         | Represents the current runtime status.                                                                        |
| [Opcode](https://docs.rs/sputnikvm/0.10.1/sputnikvm/enum.Opcode.html)                       | Opcode enum. One-to-one corresponding to an u8 value.                                                         |
| [TransactionAction](https://docs.rs/sputnikvm/0.10.1/sputnikvm/enum.TransactionAction.html) | Transaction Actions                                                                                           |
| [VMStatus](https://docs.rs/sputnikvm/0.10.1/sputnikvm/enum.VMStatus.html)                   | VM Status                                                                                                     |

### Statics

| Statics Name                                                                                           | Description                                  |
| ------------------------------------------------------------------------------------------------------ | -------------------------------------------- |
| [ECREC\_PRECOMPILED](https://docs.rs/sputnikvm/0.10.1/sputnikvm/static.ECREC_PRECOMPILED.html)         | Static value of ECREC precompiled contract.  |
| [EMBEDDED\_PRECOMPILEDS](https://docs.rs/sputnikvm/0.10.1/sputnikvm/static.EMBEDDED_PRECOMPILEDS.html) | Default precompiled collections.             |
| [ID\_PRECOMPILED](https://docs.rs/sputnikvm/0.10.1/sputnikvm/static.ID_PRECOMPILED.html)               | Static value of ID precompiled contract.     |
| [RIP160\_PRECOMPILED](https://docs.rs/sputnikvm/0.10.1/sputnikvm/static.RIP160_PRECOMPILED.html)       | Static value of RIP160 precompiled contract. |
| [SHA256\_PRECOMPILED](https://docs.rs/sputnikvm/0.10.1/sputnikvm/static.SHA256_PRECOMPILED.html)       | Static value of SHA256 precompiled contract. |

### Traits

| Traits Name                                                                        | Description                                                                         |
| ---------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------- |
| [AccountPatch](https://docs.rs/sputnikvm/0.10.1/sputnikvm/trait.AccountPatch.html) | Account patch for account related variables.                                        |
| [Memory](https://docs.rs/sputnikvm/0.10.1/sputnikvm/trait.Memory.html)             | Represent a memory in EVM. Read should always succeed. Write can fall.              |
| [Patch](https://docs.rs/sputnikvm/0.10.1/sputnikvm/trait.Patch.html)               | Represents different block range context.                                           |
| [Precompiled](https://docs.rs/sputnikvm/0.10.1/sputnikvm/trait.Precompiled.html)   | Represent a precompiled contract.                                                   |
| [VM](https://docs.rs/sputnikvm/0.10.1/sputnikvm/trait.VM.html)                     | Represents an EVM. This is usually the main interface for clients to interact with. |

### Type Definitions

| Type                                                                                      | Description                                                                                    |
| ----------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------- |
| [SeqContextVM](https://docs.rs/sputnikvm/0.10.1/sputnikvm/type.SeqContextVM.html)         | A sequencial VM. It uses sequencial memory representation and hash map storage for accounts.   |
| [SeqTransactionVM](https://docs.rs/sputnikvm/0.10.1/sputnikvm/type.SeqTransactionVM.html) | A sequencial transaction VM. This is same as SeqContextVM except it runs at transaction level. |


# Deploy a Contract in the MVM

## Install the MetaMask Extension[#](https://newdocs.mvs.org/docs/dev/metamask#install-the-metamask-extension)

We start with a fresh [MetaMask](https://metamask.io/) installation from the Chrome or Firefox store. Download the extension and follow the "get started" guide. You need to create a wallet, set a password, and store your secret backup phrase (make sure to store these in a secure place). This will generate an Ethereum-compatible address:

![Metamask import Account](/files/-MTLSQuCGp-CQiE8OC2l)

From the “Settings -Networks” dropdown menu select the **RPC network**. Name it as you like and add the new RPC URL and use the following parameters to connect to the EVM:

*Testnet Deployment*

* New RPC URL: [https://vm.mvs.org/testnet\_rpc/](< https://vm.mvs.org/testnet_rpc/>)
* Chain ID: 43
* Currency Symbol: ETP

*Mainnet Deployment*

* New RPC URL: [ ](< https://vm.mvs.org/testnet_rpc/>)[https://vm.mvs.org/mainnet\_rpc/ ](< https://vm.mvs.org/mainnet_rpc/ &#xA;>)
* Chain ID: 23
* Currency Symbol: ETP

![](/files/-MTLVp1izaR3Er2CsGYR)

From Metamask select your new added Network:

![Metamask select network](/files/-MTLVxkoC_C7H5YaoalW)

## Using Remix[#](https://newdocs.mvs.org/docs/dev/metamask#using-remix)

Getting Started with Remix?&#x20;

Now let’s fire up Remix to exercise some more advanced functionalities in MVM module. Launch Remix by navigating to <https://remix.ethereum.org/>. In the main screen, under Environments, select Solidity to configure Remix for Solidity development, then navigate to the File Explorers view:

![Remix screenshot 1](/files/-MTLWwWmycgmIHrHAsP4)

We will create a new file to save the Solidity smart contract. Hit the + button under File Explorers and enter the name "MyToken.sol" (or whatever name you want) into the popup dialog.

![Remix screenshot 2](/files/-MTLX41PMAvflJ2ilUjo)

Now let's paste the following smart contract into the editor tab that comes up: //begin codepragma solidity ^0.7.0;import '<https://github.com/OpenZeppelin/openzeppelin-contracts/blob/release-v3.2.0-solc-0.7/contracts/token/ERC20/ERC20.sol';//> This ERC-20 contract mints the specified amount of tokens to the contract creator.contract MyToken is ERC20 { constructor(uint256 initialSupply) ERC20("MyToken", "MYTOK") public { \_mint(msg.sender, initialSupply); }}//end codeCopy

This is a simple ERC-20 contract based on the current Open Zeppelin ERC-20 template. It creates MyToken with symbol MYTOK and mints the entirety of the initial supply to the creator of the contract. Once you have pasted the contract into the editor it should look like this. Now navigate to the compile sidebar option to press the “Compile MyToken.sol” button:

![Remix screenshot 3](/files/-MTLXDgVC_8b5S6LPAWY)

These are default settings but you can choose your version of Solidity.

## Deploying a Contract to the MVM Using Remix[#](https://newdocs.mvs.org/docs/dev/metamask#deploying-a-contract-to-etp-evm-using-remix)

Now we can deploy the contract by navigating to the Deployment sidebar option. You need to change the topmost “Environment” dropdown from “JavaScript VM” to “Injected Web3” which tells Remix to use the MetaMask injected provider, which will point it to your RPC standalone node. As soon as you select this you will be prompted to allow Remix to connect to your MetaMask account:

![Remix screenshot 4](/files/-MTLXjP3vxmL8cgC2Dqp)

Select from MetaMask the account to be used for deployment and then click next on Metamask button.

Press “Next” in Metamask to allow Remix to access the selected account. Back on the Remix side, you should see the account to be used for deployment as the one that is managed by MetaMask. Next to the Deploy button, let’s specify an initial supply of 8M tokens. Since this contract uses the default of 18 decimals, the value to put in the box is 8000000000000000000000000:

![Remix screenshot 5](/files/-MTLXsgMY-AmKKQwD_GP)

Once you have entered this value hit the Deploy button. You will be prompted in MetaMask to confirm the contract deployment transaction:

![Remix screenshot 6](/files/-MTLY2FGO_akPR8gmGDW)

After you press confirm and the deployment is complete, you will see the transaction listed in MetaMask and the contract will appear under Deployed Contracts in Remix.&#x20;

Once the contract is deployed, you can interact with it from within Remix. Drill down on the contract under “Deployed Contracts.” Clicking on name, symbol, and totalSupply should return “MyToken,” “MYTOK,” and “8000000000000000000000000” respectively. If you copy the address from which you deployed the contract, and paste it into the balanceOf field, you should see the entirety of the balance of the ERC20 as belonging to that user. Also copy the contract addres by click the button next to the contract name and address.


# Assets


# Interact with an MRC-20 in MetaMask

Now, open MetaMask to add the newly deployed MRC-20 tokens. Before doing so, make sure you have copied the contract's address from Remix. Back in MetaMask, click on “Add Token” as shown below. Make sure you are in the account that deployed the token contract:

![Metamask add token screenshot 1](/files/-MTLYHC01UYyuScSCm_x)

Paste the copied contract address into the “Custom Token” field. The “Token Symbol” and “Decimals of Precision” fields should be automatically populated:

![Metamask add token screenshot 2](/files/-MTLZ-WP7DSqOOXj1wIM)

Now we can send some of these MRC-20 tokens to the other account that we have set up in MetaMask. Hit “send” to initiate the transfer of 500 MyTokens and select the destination account.

After you press confirm and the deployment is complete, you will see the transaction listed in MetaMask and the contract will appear under Deployed Contracts in Remix:

![Contract interaction screenshot 1](/files/-MTLZLwiUFebgP9GPlnC)

You will be able then to interact with all methods of your contract:

![Contract interaction screenshot 2](/files/-MTLZTvc0Ss_xDOeHsKM)


# Remote Procedure Calls

Remote Procedure Calls, or RPCs, are a way for an external program (eg. a frontend) to communicate with a node. They are used for checking storage values, submitting transactions, and querying the current consensus authorities with any client that speaks json RPC. One widely available option for using RPC is curl.

Example:

```
\#!/bin/bash
"curl -H "Content-Type: application/json" -d '{"id":"1",
"jsonrpc":"2.0", "method":"state\_getRuntimeVersion", "params":\[\]}'
https://vm.mvs.org/mainnet\_rpc"
```

List of calls: \* calls marked with an asterix are under development \*

**account\_nextIndex** (*account: AccountId)*\
Returns the next valid index (aka nonce) for given account. This method takes into consideration all pending transactions currently in the pool and if no transactions are found in the pool it fallbacks to query the index from the runtime (aka. state nonce).

**author\_hasKey** (*public\_key: Bytes,*\
*key\_type: String*)\
Checks if the keystore has private keys for the given public key and key type. Returns \`true\` if a private key could be found.

**author\_hasSessionKeys** (*session\_keys: Bytes*)\
Checks if the keystore has private keys for the given session public keys. \`session\_keys\` is the SCALE encoded session keys object from theruntime. Returns \`true\` iff all private keys could be found.

**author\_insertKey** (*key\_type: String,suri: String,*\
*public: Bytes*)\
Insert a key into the keystore.

**author\_pendingExtrinsics** ()\
Returns all pending extrinsics, potentially grouped by sender.

**author\_removeExtrinsic** (*bytes\_or\_hash:Vec\<hash::ExtrinsicOrHash\<Hash>>*)\
Remove given extrinsic from the pool and temporarily ban it to prevent reimporting.

**author\_rotateKeys** ()\
Generate new session keys and returns the corresponding public keys.

**author\_submitAndWatchExtrinsic** (*metadata: Self::Metadata,* subscriber: Subscriber\<TransactionStatus\<Hash, BlockHash>>, *bytes: Bytes*)\
Submit an extrinsic to watch. See \[\`TransactionStatus\`]\(sp\_transaction\_pool::TransactionStatus) for details on transaction life cycle.

**author\_submitExtrinsic** (*extrinsic: Bytes*)\
Submit hex-encoded extrinsic for inclusion in block.

**author\_unwatchExtrinsic** (*metadata: Option\<Self::Metadata>,* *id: SubscriptionId*)\
Unsubscribe from extrinsic watching.

**babe\_epochAuthorship** ()\
Returns data about which slots (primary or secondary) can be claimed in the current epoch with the keys in the keystore.

**balances\_usableBalance** (*instance: u8,* *who: AccountId*)\
Node-specific RPC methods for interaction with balances.

**chain\_getBlock** (*hash: Option\<Hash>*)\
Get header and body of a relay chain block.

**chain\_getBlockHash** (*hash:Option\<ListOrValue\<NumberOrHex>>*)\
Get hash of the n-th block in the canon chain. By default returns latest block hash.

**chain\_getFinalisedHead** ()\
Get hash of the last finalized block in the canon chain.

**chain\_getHead** (*hash:Option\<ListOrValue\<NumberOrHex>>*)\
Get hash of the n-th block in the canon chain. By default returns latest block hash.

**chain\_getHeader** (*hash: Option\<Hash>*)\
Get header of a relay chain block.

**chain\_getRuntimeVersion** (*hash: Option\<Hash>*)\
Get the runtime version.

**chain\_subscribeAllHeads** (*metadata: Self::Metadata,* *subscriber: Subscriber\<Header>*)\
Finalized head subscription operations.

**All head subscription** (*metadata: Self::Metadata,*\
*subscriber: Subscriber\<Header>*)\
Finalized head subscription operations.

**chain\_subscribeNewHead** (*metadata: Self::Metadata,*\
*subscriber: Subscriber\<Header>*)\
Finalized head subscription operations.

**chain\_subscribeNewHeads** (*metadata: Self::Metadata,*\
*subscriber: Subscriber\<Header>*)\
Finalized head subscription operations.

**chain\_subscribeRuntimeVersion** (*metadata: Self::Metadata,*\
*subscriber: Subscriber\<RuntimeVersion>*)\
Unsubscribe runtime version.

**chain\_unsubscribeAllHeads** (*metadata: Option\<Self::Metadata>,*\
*id: SubscriptionId*)\
Unsubscribe all heads.

**chain\_unsubscribeFinalisedHeads()** alias **chain\_unsubscribeAllHeads**

**chain\_unsubscribeNewHead** alias **chain\_unsubscribeAllHeads**

**chain\_unsubscribeNewHeads** (metadata: Option\<Self::Metadata>,\
id: SubscriptionId\*) Unsubscribe all heads.

**chain\_unsubscribeRuntimeVersion**(*metadata:Option\<Self::Metadata>,* *id: SubscriptionId*)\
Finalized head and RuntimeVersion unsubscription operations.

**childstate\_getKeys** (*child\_storage\_key: PrefixedStorageKey,*\
prefix: StorageKey,\
*hash: Option\<Hash>*)\
Returns the keys with prefix from a child storage, leave empty to get all the keys

**childstate\_getStorage** (*child\_storage\_key: PrefixedStorageKey,*\
key: StorageKey,\
*hash: Option\<Hash>*)\
Returns a child storage entry at a specific block's state

**childstate\_getStorageSize** (*child\_storage\_key: PrefixedStorageKey,*\
key: StorageKey,\
*hash: Option\<Hash>*)\
Returns the size of a child storage entry at a block's state.

**eth\_accounts** ()\*\
Returns EVM accounts list.

**eth\_blockNumber** ()\
Returns highest block number from EVM perspective.

**eth\_call** (*\_: CallRequest,*\
*\_: Option\<BlockNumber>*)\
Call contract, returning the output data.

**eth\_chainId** ()\
Returns the chain ID used for transaction signing at the current best block. None is returned if not.

**eth\_estimateGas** (*\_: CallRequest,*\
*\_: Option\<BlockNumber>*)\
Estimate gas needed for execution of given contract.

**eth\_gasPrice** ()\
Returns current gas\_price.

**eth\_getBalance** (*\_: H160,*\
*\_: Option\<BlockNumber>*)\
Returns balance of the given account.

**eth\_getBlockByHash** (*\_: H256,*\
*\_: bool*)\
Returns block with given hash.

**eth\_getBlockByNumber** (*\_: BlockNumber,*\
*\_: bool*)\
Returns block with given number.

**eth\_getBlockTransactionCountByHash** (*\_: H256*)\
Returns the number of transactions in a block with given hash.

**eth\_getBlockTransactionCountByNumber** (*\_: BlockNumber*)\
Returns the number of transactions in a block with given block number.

**eth\_getCode** (*\_: H160,*\
*\_: Option\<BlockNumber>*)\
Returns the code at given address at given time (block number).

**eth\_getLogs** (*\_: Filter*)\
Returns logs matching given filter object.

**eth\_getStorageAt** (*\_: H160,*\
\_: U256,\
*\_: Option \<BlockNumber>*)\
Returns content of the storage at given address.

**eth\_getTransactionByBlockHashAndIndex** ( *\_: H256,*\
*\_: Index*)\
Returns transaction at given block hash and index.

**eth\_getTransactionByBlockNumberAndIndex**( *v\_: BlockNumber,*\
*\_: Index*)\
Returns transaction by given block number and index.

**eth\_getTransactionByHash** (*\_: H256*)\
Get transaction by its hash.

**eth\_getTransactionCount** (*\_: H160,*\
*\_: Option\<BlockNumber>*)\
Returns the number of transactions sent from given address at given time (block number).

**eth\_getTransactionReceipt** (*\_: H256*)\
Returns transaction receipt by transaction hash.

**eth\_getUncleByBlockHashAndIndex** (*\_: H256,*\
*\_: Index*)\
Returns Unlce by block hash and index

**eth\_getUncleByBlockNumberAndIndex** (*\_: BlockNumber,*\
*\_: Index*)\
Returns an uncle at given block and index.

**eth\_getUncleCountByBlockHash** (*\_: H256*)\
Returns the number of uncles in a block with given hash.

**eth\_getUncleCountByBlockNumber** (*\_: BlockNumber*)\
Returns the number of uncles in a block with given block number.

**eth\_getWork** ()\*\
Returns the hash of the current block, the seedHash, and the boundary condition to be met.

**eth\_hashrate** ()\
Returns the number of hashes per second that the node is mining with.

**eth\_mining** ()\
Returns true if client is actively mining new blocks.

**eth\_protocolVersion** ()\
Returns protocol version encoded as a string (quotes are necessary here).

**eth\_sendRawTransaction** (*\_: Bytes*)\
Sends signed transaction, returning its hash.

**eth\_sendTransaction** (*\_: TransactionRequest*)\
Sends transaction; will block waiting for signer to return the transaction hash.

**eth\_submitHashrate** (*\_: U256,*\
*\_: H256*)\
Used for submitting mining hashrate.

**eth\_submitWork** ( *\_: H64,*\
\_: H256,\
*\_: H256*)\
Used for submitting a proof-of-work solution.

**eth\_subscribe** (*\_: Self::Metadata,*\
\_: typed::Subscriber\<pubsub::Result>,\
\_: pubsub::Kind,\
*\_: Option\<pubsub::Params>*)\
Subscribe to Eth subscription.

**eth\_syncing** ()\
Returns an object with data about the sync status or false.

**eth\_unsubscribe** (*\_: Option\<Self::Metadata>,*\
*\_: SubscriptionId*)\
Unsubscribe from existing Eth subscription.

**grandpa\_proveFinality** ( *begin: Hash,*\
end: Hash,\
*authorities\_set\_id: u64*)\
Prove finality for the given block number by returning the justification for the last block in the set and all the intermediary headers to link them together.

**grandpa\_roundState** ()\
Returns the state of the current best round state as well as the ongoing background rounds.

**grandpa\_subscribeJustifications** (*metadata: Self::Metadata,*\
*subscriber: Subscriber\<Notification>*)\
Returns the block most recently finalized by Grandpa, alongside side its justification.

**grandpa\_unsubscribeJustifications** (*metadata:*\
*Option\<Self::Metadata>,*\
*id: SubscriptionId*)\
Unsubscribe from receiving notifications about recently finalized blocks.

**headerMMR\_genProof** (*block\_number\_of\_member\_leaf: u64,*\
*block\_number\_of\_last\_leaf: u64*)\
Get the MMR proof for a certain height, block number of member leaf, block number of the lastest leafnet\_listening, Returns true if client is actively listening for network connections. Otherwise false.

**net\_peerCount** () = Returns number of peers connected to node.

**net\_version** ()\
Returns protocol version.

**offchain\_localStorageGet** (*kind: StorageKind,*\
*key: Bytes*)\
Get offchain local storage under given key and prefix.

**offchain\_localStorageSet** (*kind: StorageKind,*\
key: Bytes,\
*value: Bytes*)\
Set offchain local storage under given key and prefix.

**payment\_queryFeeDetails** (*encoded\_xt: Bytes,*\
*at: Option\<BlockHash>*)\
Query the fee of a payment

**payment\_queryInfo** (*encoded\_xt: Bytes,*\
*at: Option\<BlockHash>*)\
Get details regarding payment fee.

**staking\_powerOf** (*who: AccountId*)\
Retrunt the power on a certain AccountId in a staking context.

**state\_call** (*name: String,*\
bytes: Bytes,\
*hash: Option\<Hash>*)\
Call a contract's block state

**state\_callAt** (*name: String,*\
bytes: Bytes,\
*hash: Option\<Hash>*)\
Call a contract at a block's state.

**state\_getKeys** (*prefix: StorageKey,*\
*hash: Option\<Hash>*)\
Returns the keys with prefix, leave empty to get all the keys.

**state\_getKeysPaged** (*prefix: Option\<StorageKey>,*\
count: u32,\
start\_key: Option\<StorageKey>,\
*hash: Option\<Hash>*)\
Returns the keys with prefix with pagination support. Up to \`count\` keys will be returned. If \`start\_key\` is passed, return next keys in storage in lexicographic order.

**state\_getKeysPagedAt** (*prefix: Option\<StorageKey>,*\
count: u32,\
start\_key: Option\<StorageKey>,\
*hash: Option\<Hash>*)\
Returns the keys with prefix with pagination support. Up to \`count\` keys will be returned. If \`start\_key\` is passed, return next keys in storage in lexicographic order.

**state\_getMetadata** ()\
Returns the runtime metadata as an opaque blob.state\_getPairs, Returns the keys with prefix, leave empty to get all the keys

**state\_getReadProof** (*keys: Vec\<StorageKey>,*\
*hash: Option\<Hash>*)\
Returns proof of storage entries at a specific block's state.

**state\_getRuntimeVersion** (*hash: Option\<Hash>*)\
Get the runtime version.

**state\_getStorage** (*key: StorageKey,*\
*hash: Option\<Hash>*)\
Returns a storage entry at a specific block's state.

**state\_getStorageAt** (*key: StorageKey,*\
*hash: Option\<Hash*>)\
Returns the hash of a storage entry at a block's state.

**state\_getStorageHash** (*key: StorageKey,*\
*hash: Option\<Hash>*)\
Returns the hash of a storage entry at a block's state.

**state\_getStorageHashAt** (*key: StorageKey,*\
*hash: Option\<Hash*>)\
Returns the hash of a storage entry at a block's state.

**state\_getStorageSize** (*key: StorageKey,*\
*hash: Option\<Hash*)\
Returns the size of a storage entry at a block's state.

**state\_queryStorage** (*keys: Vec\<StorageKey>,*\
block: Hash,\
*hash: Option\<Hash>*)\
Query historical storage entries (by key) starting from a block given as the second parameter. NOTE: This first returned result contains the initial state of storage for all keys. Subsequent values in the vector represent changes to the previous state (diffs).

**state\_queryStorageAt** (*keys: Vec\<StorageKey>,*\
*at: Option\<Hash>*)\
Query storage entries (by key) starting at block hash given as the second parameter.

**state\_subscribeRuntimeVersion** (*metadata: Self::Metadata,*\
*subscriber: Subscriber\<RuntimeVersion*)\
New runtime version subscription.

**state\_subscribeStorage** (*metadata: Self::Metadata,*\
subscriber: Subscriber\<StorageChangeSet\<Hash>>,\
*keys: Option\<Vec\<StorageKey>*)\
New storage subscription.

**state\_unsubscribeRuntimeVersion** (*metadata: Option\<Self::Metadata>,*\
*id: SubscriptionId*)\
Unsubscribe from runtime subscription

**state\_unsubscribeStorage** (*metadata: Option\<Self::Metadata>,*\
*id: SubscriptionId*)\
Unsubscribe from storage subscription

**subscribe\_newHead** (*metadata: Option\<Self::Metadata>,*\
*id: SubscriptionId*)\
New head subscription

**sync\_state\_genSyncSpec** (*raw: bool*)\
Returns the json-serialized chainspec running the node, with a sync state.

**system\_accountNextIndex** (*account: AccountId*)\
Returns the next valid index (aka nonce) for given account. This method takes into consideration all pending transactions currently in the pool and if no transactions are found in the pool it fallbacks to query the index from the runtime (aka. state nonce).

**system\_addLogFilter** (*directives: String*)\
Adds the supplied directives to the current log filter. The syntax is identical to the CLI \`\<target>=\<level>\`:\`sync=debug,state=trace\`

**system\_addReservedPeer** (peer: String)\
Adds a reserved peer. Returns the empty string or an error. The string parameter should encode a \`p2p\` multiaddr.

**system\_chain** ()\
Get the chain's name. Given as a string identifier.

**system\_chainType** ()\
Get the chain's type.

**system\_dryRun** (*extrinsic: Bytes*,\
at: Option\<BlockHash>\*)\
Dry run an extrinsic at a given block. Return SCALE encoded ApplyExtrinsicResult.

**system\_dryRunAt** (*extrinsic: Bytes,*\
*at: Option\<BlockHash>*)\
Dry run an extrinsic at a given block. Return SCALE encoded ApplyExtrinsicResult

**system\_health** ()\
Return health status of the node. Node is considered healthy if it is:

* connected to some peers (unless running in dev mode)
* not performing a major sync

**system\_localListenAddresses** ()\
Returns the multiaddresses that the local node is listening on. The addresses include a trailing \`/p2p/\` with the local PeerId, and are thus suitable to be passed to \`system\_addReservedPeer\` or as a bootnode address for example.

**system\_localPeerId** ()\
Returns the base58-encoded PeerId of the node.

**system\_name** ()\
Get the node's implementation name. Plain old string.

**system\_networkState** ()\
Return the current network state

**system\_nodeRoles** ()\
Returns the roles the node is running as.

**system\_peers** ()\
Returns currently connected peers

**system\_properties** ()\
Get a custom set of properties as a JSON object, defined in the chain spec.

**system\_removeReservedPeer** (*peer\_id: String*)\
Remove a reserved peer. Returns the empty string or an error. The string should encode only the PeerId.

**system\_resetLogFilter** ()\
Resets the log filter to defaults.

**system\_syncState**()\
Returns the state of the syncing of the node: starting block, current best block, highest known block.

**system\_version**()\
Get the node implementation's version. Should be a semver string.

**unsubscribe\_newHead** (*metadata: Option\<Self::Metadata>,*\
*id: SubscriptionId*)

**web3\_clientVersion** ()\
Returns current client version.

**web3\_sha3** (*\_: Bytes*)\
Returns sha3 of the given data.


# Metaverse Full Node Interface


# Mining & Staking


# POS Node Set Up

## Hyperspace Mainnet

Hyperspace Mainnet Node - Stage 1 - PoS Consensus Mode

First, clone our GitHub:

```
git clone https://github.com/mvs-org/Hyperspace
```

## Setting up environment

Install Substrate pre-requisites (including Rust):&#x20;

For Unix-based operating systems, run the following commands:

```
curl https://sh.rustup.rs -sSf | sh
source ~/.cargo/env

rustup default nightly
rustup target add wasm32-unknown-unknown
```

You will also need to install the following packages:

Linux:

```
sudo apt install cmake pkg-config libssl-dev git clang libclang-dev
```

Linux on ARM: rust-lld is required for linking wasm, but is missing on non-Tier 1 platforms. So, use this script to build lld and create the symlink /usr/bin/rust-lld to the build binary.

Mac:

```
brew install cmake pkg-config openssl git llvm
```

## Build the corresponding binary file

```
cd Hyperspace
cargo build --release
```

The first build takes a long time because all necessary libraries need to be compiled.

## To start the node you just compiled

```
./target/release/hyperspace --chain=hyperspace.json --name MyNode1
```


# Miners List and Fees

These are available **miners for Metaverse Hyperspace**. Mining software developer fees are also presented in the table below. Usually, each mining software sends mining rewards to the developer's wallet every hour for a short period of time.

|    Miner Name    |  Fees  |                       Github                      |
| :--------------: | :----: | :-----------------------------------------------: |
|   Pheonix miner  |  0.65% |  <https://github.com/Ethermine-pool/PhoenixMiner> |
|     Lolminer     |  0.7%  | <https://github.com/Lolliedieb/lolMiner-releases> |
|      Gminer      |  0.65% |  <https://github.com/develsoftware/GMinerRelease> |
|       T-rex      |   1%   |        <https://github.com/trexminer/T-Rex>       |
|   TeamRedMiner   |   1%   |      <https://github.com/todxx/teamredminer>      |
|     Ethminer     |   0%   |   <https://github.com/ethereum-mining/ethminer>   |
|     Nanominer    |   1%   |      <https://github.com/nanopool/nanominer>      |
|      Nbminer     |   1%   |       <https://github.com/NebuTech/NBMiner>       |
|      Bminer      |  0.65% |        <https://github.com/nanopool/bminer>       |
| Hyperspace miner | -0.05% |                        TBA                        |


# Stratum V2

Metaverse developers' team has **implemented Stratum V2 for the first time** on Metaverse Mainnet. &#x20;

The implementation of Stratum V2 on Metaverse will allow miners to continue mining ETP on the new Metaverse mainnet seamlessly. Indeed, this important piece of infrastructure will ensure **backward compatibility with the DaggerHasimoto** (POW) **algorithm** currently used on Metaverse ETP Blockchain. After our mainnet launch, miners will need to make the switch using our Stratum V2 implementation to keep mining rewards. This important upgrade will also allow **ETP** **to be** **minable on DaggerHash**.&#x20;

\
We decided to select Stratum V2 for several key reasons:<br>

* **Reduced bandwidth consumption** by using binary data and avoiding unnecessary data transfers
* **Efficient cashing** to reduce server CPU load
* **Job distribution latency** by splitting the prevhash and the rest of the predefined block data
* **Protocol Security** through authenticated encryption with associated data (AEAD)
* **Enhanced decentralization** by allowing miners to select their own transactions

‌\
N.B.: Please note that we will release Metaverse implementation of Stratum V2 as we release our mainnet and this feature is not available on Betelgeuse testnet.&#x20;


# Welcome to The New Reality!

## Our Tool Kit

### Follow us on social media

[*Facebook*](https://www.facebook.com/mvsofficial/)– Share everything about Metaverse with your friends and family

[*Twitter*](https://twitter.com/mvs_org)– The place to learn all about Metaverse latest developments

[*Telegram*](https://t.me/Metaverse_Blockchain)– A friendly chat room for people to exchange and learn more about Metaverse

[*Discord*](https://discord.gg/56ky6fb)– The place to discuss tech and solve development issues

[*Medium*](https://medium.com/metaverse-blockchain)– Publications related to Metaverse&#x20;

[*Reddit*](https://www.reddit.com/r/Metaverse_Blockchain/)– The OG Club


# ⚙️关于元界浏览器插件钱包

\
元界浏览器插件钱包是受元界团队启发的解决方案，它使我们的用户可以易用地与元界虚拟机进行交互。

本指南假定您正在使用浏览器的插件钱包：<https://github.com/mvs-org/metaverse-vm-extension/releases/download/0.11.10/metaversevm-firefox-0.11.10.zip>。

\
**教程**
------

本教程说明了如何创建钱包以及如何导入钱包。

### 创建**新**钱包

**Step1**

请先下载最新版本的**火狐浏览器**，官方下载地址：<http://www.firefox.com.cn/download/>

![](/files/-MYiIhI_iUZbqSuBIK44)

**Step2**

打开火狐浏览器，复制以下安装包链接至浏览器中。

<https://github.com/mvs-org/metaverse-vm-extension/releases/download/0.11.10/metaversevm-firefox-0.11.10.zip>

选&#x62E9;**“打开，通过Archive Utility（默认）”**&#x9009;项，点击**确定**。将安装包zip文件选择您需要的路径，如桌面，进行保存。（如果一直未弹出以上截图的界面，请多尝试几次）

![](/files/-MYiIoA6Faoz5PQRahai)

**Step3**

重新打开火狐浏览器，点击右上角的设置面板，选&#x62E9;**“扩展和主题”**&#x6253;开。

![](/files/-MYiItQ0W4u1IjdV60xz)

**Step4**

点击图中设置图标，点&#x51FB;**“添加附加组件”**。

![](/files/-MYiJE-wqI-mEBu0WlAi)

![](/files/-MYiJ9CJpl-AVPxSDV7N)

**Step5**

跳转至心标签页后，点&#x51FB;**“临时载入附加组件”**，在弹出的窗口选&#x62E9;**“metaversevm-firefox-0.11.10.zip”**&#x6587;件**打开**。

![](/files/-MYiJlHlhQp7jIedVxoe)

![](/files/-MYiJvn2FSQfG3m8ihp7)

**Step6**

跳转至最新标签页后，点&#x51FB;**“Get Started”**，即可创建您的MetaverseVM钱包。

![](/files/-MYiK4bLzZxWX4Qo-YxF)

这样做之后，您现在应该看到下面的页面，然后单击**Create a Wallet.**

![](/files/-MYcrQXMb2az0FUKHMf2)

您首先需要创建一个密码，如下所示。 完成后，**选中旁边的框** I have read and agreed to the Terms of Use (我已阅读并同意使用条款)然后点击**创建**按钮。

![](/files/-MYcrZXtXdwYCrPDhVnj)

然后，您将看到“Secret Backup Phrase机密备份短语”页面。 这是最重要的步骤，因为秘密备份阶段是恢复资产的唯一方法。 您的秘密备份短语也可以用来窃取您的数字资产。

只需点击锁，然后按照提示保存您的备份短语。

![](/files/-MYcrfQCwwfoz6w-D1tr)

完成此操作后，完成拼图以确认您是备份短语的所有者。

![](/files/-MYcroty4JAnnBM4ujcH)

恭喜！ 您已完成元界浏览器插件钱包的设置。请仔细阅读提示，确保将元界添加到您喜欢的插件中，并测试您的元界插件钱包是否可运行。

![](/files/-MYcs86XRuaTGvnQlbJU)

### **汇入钱包**

如果您已经拥有一个新的元界钱包（大多数MyETPWallet用户应该已经拥有一个），则可以按照以下方式简单地导入它。

首先，点击导入钱包按钮Import Wallet。

![](/files/-MYcswq7BPjnyN_Obxtg)

输入您的**种子短语和密码**。 确保您已选中“我已阅读并同意使用条款”旁边的框。 最后，单击导入按钮。

![](/files/-MYct26pYueOQofC5RsJ)

&#x20;单击“All Done全部完成”按钮后，您现在应该可以看到您的ETP余额。

![](/files/-MYct5VQhsmm_IwqJrxj)


# 将UTXO ETP交换为新ETP

{% hint style="danger" %}

此交换服务是从UTXO链到虚拟机链的单向交换。

**您将无法换回UTXO链。**

目前，大多数交易所目前仅支持UTXO链。
{% endhint %}

本指南旨在介绍UTXO ETP（“旧ETP”）到新ETP的交换。

{% hint style="info" %}
请注意，本教程基于MyETPWallet。

**确保您已连接到主网。**

登录到您的钱包，并按照以下说明进行操作：

[http://app.myetpwallet.com](http://app.myetpwallet.com/)
{% endhint %}

登录后，您的ETP钱包应如下所示：

![](/files/-MYcu_Vcl20Yrb874V01)

接下来，单击身份，如下所示：

![](/files/-MYcukw8v_VYwSFsI4JF)

进入“Identities”选项后，您应该会看到创建虚拟机地址的提示或为您自动创建的虚拟机地址。 如果已经为您创建了虚拟机地址，则可以直接跳到“**将UTXO ETP交换为新ETP**”步骤。

## **创建您的虚拟机地址**

首先，单击创建虚拟机地址。

![](/files/-MYcvLqsK6nzFJzDAx90)

其次，输入您的钱包密码，然后单击Generate VM address：

![](/files/-MYcvTEU71Wpb1wQyfnU)

创建虚拟机地址后，它应显示在“Identities”选项卡的顶部，如下所示：

![](/files/-MYcvXtkJK0gWZWNEDg2)

**将UTXO ETP交换为新ETP**

现在，您已经创建了虚拟机地址，可以转到“Swap”选项卡，如下图所示：

![](/files/-MYcveKuona1BOyMv7bY)

在“Swap”选项卡中，输入要转移到新的Metaverse ETP链中的ETP量，然后单击“下一步”，如下图所示：

![](/files/-MYcvjtf1daAkQtyIdKd)

查看交易数据。 然后，输入您的密码，然后单击“**签名并发送**”。

![](/files/-MYcvoo-Sy59dyeRLtQ-)

如果您的交易成功，则您应该在屏幕上看到类似的通知，并确保保留交易ID的记录（下面以灰色显示）：

![](/files/-MYcvtiu4kULSlkwKi3T)

为您完成交换之后，您只需使用当前的备用单词（也称为种子短语）即可在新的元界插件钱包中访问您的ETP余额。 我们最多需要12个小时来确保您的ETP已正确转移到新连链。

**请在谷歌浏览器上下载**[**元界插件钱包**](https://chrome.google.com/webstore/detail/metaversevm/bnkgokfnchhoiipnofiibeohpmnbaelb)**:** [**https://chrome.google.com/webstore/detail/metaversevm/bnkgokfnchhoiipnofiibeohpmnbaelb**](https://chrome.google.com/webstore/detail/metaversevm/bnkgokfnchhoiipnofiibeohpmnbaelb)


