# About CLV 🍀

This site provides documentation for CLV, an Operating System parachain on the Polkadot network. Here, you'll find both high-level and technical information for developers, collators, end users, and other CLV network participants.

This site will be updated from as CLV evolves. We welcome everyone joins the CLV community and contribute to this site and the project.

### CLV - Passport to the Omniverse

CLV is a one-stop infrastructure platform for cross-chain and decentralized applications. The CLV chain is a Substrate-based specialized Layer-1 chain that is EVM compatible, cross-chain interoperable, and also functions as a Parachain in the Polkadot ecosystem. Infrastructure made ready for scaling dApp in the multi-chain universe. CLV wallet is a cross-chain all-in-one wallet, for Day-to-Day, DeFi, Metaverse and Gaming purposes. With multi-dimensional products lineup, including CLV Multi-Chain Wallets, CLV dApp Interaction Protocol, CLV Chain EVM and Universal Cross-Chain Support, CLV uniquely positioned itself as “Passport to the Omniverse.”

### Built on Substrate

Substrate is technically fit for CLV. By building on top of Substrate, CLV is able to leverage the extensive functionalities that Substrate provides out-of-the-box, rather than needing to build them from scratch. These functionalities include peer-to-peer networking, consensus mechanisms, governance functionality, EVM implementation, and more. Overall, using Substrate will dramatically reduce the time and work needed to implement CLV. Substrate allows a great degree of customization, which is compulsory when achieving compatibility with Ethereum. Meanwhile, by adopting Rust, CLV will gain both safety guarantee and performance enhancement.

### CLV History&#x20;

CLV's journey started in May 2020, where it saw the emerging need for blockchains' interoperability and compatibility.&#x20;

In Feb of 2021, after months of development, CLV was listed as one of the CoinList Seed Winter 2021 alumni, and later successfully held the initial token offering event on CoinList in April 2021.&#x20;

Since the token generation event, CLV's native token $CLV has quickly been made available to trade on all major exchanges, including Binance, Coinbase, FTX, Huobi, OKX, KuCoin, Bithumb Global, Gate.io, MEXC and so on by July 2021.&#x20;

In addition to the existing wallet platforms line-up that was introduced back in May, CLV launched an all-new Web Wallet in October 2021. This enables social login and brings easy-of-use for crypto wallet to a new level.

By November 2021, CLV wallet apps have achieved 350k cumulative downloads from all platforms.

Winning the 5th Parachain slot on Polkadot in December 2021 enables CLV to be one of the first to bring full-suite decentralized applications to the Polkadot ecosystem.


# Clover Finance Rebrands to CLV

#### On March 10th, 2022, Clover Finance proudly announced the rebrand to CLV, committing a Move further into the Web3 Future. Below is the original announcement.

TL;DR: Amid the upcoming release of new Wallet and Chain products, Clover Finance is rebranding to CLV in pursuit of an easier approach to a wider audience group. $CLV token remains as the centerpiece for securing and governing the parachain network in the CLV ecosystem; more utilities will be enabled in the future as development advances.

Today is one of the big days for our project. We are excited to announce that Clover Finance is rebranding to CLV, a move further into the web3 future.

**What is CLV?**

CLV stands for Connectivity, Legible, Versatile.

Built with interoperability and cross-chain in mind, CLV products offer great connectivity within the ever-growing and expanding crypto space.

Usability has been an issue with decentralized applications, users are easily lost in tons of options. CLV aims to provide legible, easy-to-use Web3 products that are accommodating to a wider range of users.

We all want swiss-knives that are versatile enough to combat any circumstances. CLV product line includes CLV Chain and CLV Wallet are all for decentralized day-to-day use, it can fulfil users’ DeFi, Social, Gaming and any other need in Web3.

![](https://miro.medium.com/max/1400/0*qSoOZTkLb5GyHcDm)

Now, we’re keeping the Clover’s old history as a greenish gradient but more dynamic and sharp!

**What’s not changed?**

Our core value proposition has never been changed — we are here to build a foundational platform that serves decentralized applications to people.

$CLV token remains as the centerpiece for securing and governing the parachain network in the CLV ecosystem. At the same time, we are actively looking for more ways for users to engage and participate in the CLV ecosystem using $CLV token.

**What’s next?**

CLV team have been working on expanding CLV’s scope and partnerships in the past a few months, and we will continue to do so and to bring more exciting news and updates to you. CLV is fully devoted to building a welcoming web3 community via our products.

Thank you all, and we look forward to a great Web3 future ahead with all of you together.


# What is CLV Chain?

## CLV Chain Features Multi-Blockchain Structure

CLV Chain is a set of specialized chains that is cross-chain interoperable, and currently consists of:

* CLV Mainnet (M-Chain) - a Governance & Exchange Chain, and
* CLV Parachain (P-Chain) - a Smart Contract Chain that is EVM compatible

Both blockchains are validated and secured by the Substrate framework.

### CLV Chain Key Features

* Compatible with Ethereum, supporting seamless migration of existing dApps to CLV P-Chain&#x20;
* CLV EVM economic incentive mechanism&#x20;
* CLV universal cross-chain modules&#x20;
* Smart contracts governance - malicious smart contracts can be blocked through on-chain governance&#x20;
* Upgradeable smart contract support - CLV EVM has built-in support for seamless upgrade of smart contracts&#x20;
* CLV Chain supports direct transactions between substrate accounts and EVM accounts

### CLV Mainnet (M-Chain)

CLV Mainnet (M-Chain) is used for governance and exchange purpose. $CLV token is issued on CLV Mainnet, and users can freely cross-chain transfer to Ethereum, BSC and CLV Parachain.

{% hint style="info" %}
Staking and governance features are enabled only on CLV mainnet, there is no EVM support.
{% endhint %}

### CLV Parachain (P-Chain)

CLV Parachain (P-Chain) is EVM compatible smart contract chain that is currently connected to Polkadot Mainnet as one of the Parachains. Developers can easily migrate their existing Solidity smart contracts to CLV Parachain without any modification.

{% hint style="info" %}
CLV EVM is enabled only on CLV Parachain (P-Chain).
{% endhint %}

## CLV EVM vs. Ethereum

The main differences between CLV EVM and Ethereum are:

1. CLV P-Chain uses NPoS consensus, and Ethereum use PoW (for now).&#x20;
2. CLV P-Chain utilizes a unique dual-blockchain structure, it both supports EVM transactions as well as Polkadot like transactions.
3. CLV P-Chain has lower gas fee than Ethereum.
4. CLV P-Chain has higher throughput, around 1000 transactions a second


# What is CLV Wallet?

### **Introduction**

CLV Wallet is a non-custodial, Multi-Chain, Multi-Platform application which helps users to manage crypto assets and interact with all types of decentralized applications.

### **Key Features**

CLV Wallet is available on both mobile (Android/iOS), desktop (Chrome Extension) and universally on Web.

* Non-Custodial, Safe and Easy Account Management
* Users could import accounts by Mnemonics, Raw Seed and Keystone. Encrypt type Sr/Ed25519 are both supported
* Support Substrate-based-blockchains, such as Polkadot, CLV Chain and etc
* Support EVM-Compatiable chains, such as Ethereum, Binance Smart Chain, Fantom, Polygon and so on
* Support Solana
* Create, import and manage multi-chain accounts in one wallet
* Easy management and switch between multiple wallets
* Support NFT assets on Ethereum, BSC, Solana, Fantom, etc
* Easy Cross-chain Transfer of tokens in one wallet
* Interact with dApps on all supported chains

### **Technology**

CLV Mobile Wallet is developed based on the flutter framework, which could develop applications for Android and iOS. And Polkadot/API is injected into WebView as JavaScript extension for web page and native app features.


# What is $CLV Token?

## What is $CLV Token?

**$CLV** is the native token of CLV M-Chain, and is used for staking to take part in network consensus, transaction fees, platform rewards, and network governance.

* **Opt-in Fees:** Pay gas fee in $CLV, or have the option to pay with any network token.
* **Governance:** Lock $CLV to elect council members and guide the development through on-chain governance.
* **Validation:** Stake $CLV to validate the network with your validator infrastructure.
* **Treasury:** Get your projects funded from the treasury.
* **Nomination:** Stake $CLV to nominate your own node validator using a single-click deployment.
* **Deployment:** Use $CLV to deploy your smart contracts and dApps on CLV Chain.

## Token Info

{% hint style="info" %}
**$CLV token lives on 4 chains -**&#x20;

* as an ERC20 token on Ethereum Mainnet
* as a BEP20 token on BNB Chain (previously called Binance Smart Chain)
* as a Substrate Native token on CLV M-Chain
* as an EVM Native token on CLV P-Chain
  {% endhint %}

**Smart Contract Address**

* **$CLV ERC-20:** 0x80C62FE4487E1351b47Ba49809EBD60ED085bf52
* **$CLV BEP-20:** 0x09E889BB4D5b474f561db0491C38702F367A4e4d

**Block Explorer**

* **$CLV ERC-20:** [Etherscan](https://etherscan.io/token/0x80C62FE4487E1351b47Ba49809EBD60ED085bf52)
* **$CLV BEP-20:** [Bscscan](https://bscscan.com/token/0x09E889BB4D5b474f561db0491C38702F367A4e4d)
* **$CLV M-Chain:** [Subscan](https://clover.subscan.io/)
* **$CLV P-Chain:** [Subscan](https://clv.subscan.io/)
* **$CLV Cross-Chain Transaction Explorer:** [CloverScan](https://tx.clover.finance/#/)

## How to Store $CLV?

Download CLV Multi-Chain Wallet, or any other compatible crypto wallet.

## How to Trade $CLV?

#### $CLV token is trading on all major crypto exchanges, including Binance, Coinbase, FTX, Coinlist Pro, Huobi, OKX, KuCoin, Gate, MEXC etc.&#x20;

* **Binance:** [CLV/USDT](https://www.binance.com/en/trade/CLV_USDT), [CLV/BUSD](https://www.binance.com/en/trade/CLV_BUSD), [CLV/BNB](https://www.binance.com/en/trade/CLV_BNB), [CLV/BTC](https://www.binance.com/en/trade/CLV_BTC)
* **Coinbase Pro:** [CLV/USDT](https://pro.coinbase.com/trade/CLV-USDT), [CLV/USD](https://pro.coinbase.com/trade/CLV-USD), [CLV/GBP](https://pro.coinbase.com/trade/CLV-GBP), [CLV/EUR](https://pro.coinbase.com/trade/CLV-EUR)
* **FTX:** [CLV/USD](https://ftx.com/trade/CLV/USD)
* **Coinlist Pro:** [CLV/USDT](https://pro.coinlist.co/trader/CLV-USDT), [CLV/USD](https://pro.coinlist.co/trader/CLV-USD)
* **Huobi:** [CLV/USDT](https://www.huobi.com/en-us/exchange/clv_usdt), [CLV/BTC](https://www.huobi.com/en-us/exchange/clv_btc)
* **OKX:** [CLV/USDT](https://www.okex.com/trade-spot/clv-usdt)
* **KuCoin:** [CLV/USDT](https://trade.kucoin.com/CLV-USDT)
* **CoinEx:** [CLV/USDT](https://www.coinex.com/exchange/CLV-USDT)
* **Gate:** [CLV/USDT](https://www.gate.io/trade/CLV_USDT)
* **MEXC:** [CLV/USDT](https://www.mexc.com/zh-CN/exchange/CLV_USDT)
* **Hoo:** [CLV/USDT](https://hoo.com/innovation/clv-usdt)
* **Bithumb Global:** [CLV/USDT](https://www.bithumb.pro/en-us/spot/trade?q=CLV-USDT)
* **Pionex**: [CLV/USDT](https://www.pionex.com/en-US/trade/CLV_USDT)


# 📣  CLV Official Channels

### Website

* &#x20;<https://clv.org/>

### Twitter

* CLV Official Twitter: <https://twitter.com/clv_org>
* CLV Wallet Twitter: <https://twitter.com/clover_finance>

### Telegram Announcement

* <https://t.me/clover_ann>

### LinkedIn

* <https://vg.linkedin.com/company/clv-org>

### GitHub

* <https://github.com/clover-network>

### Medium

* <https://medium.com/@clv_org/>

### Documentation

* <https://docs.clv.org>


# 🏘  CLV Community Channels

### 🍀 Official Community

* Discord: <https://discord.com/invite/M6SxuXqMVB>
* Telegram: <https://t.me/clvorg>&#x20;
* Dev Group: <https://t.me/clover_dev>

### 🌍 Global Community

* 🇹🇷 Turkey Türkçe: <https://t.me/Clover_Turkish>
* 🇻🇳 Vietnam Tiếng Việt: <https://t.me/CloverVN>
* 🇫🇷 French Français: <https://t.me/cloverFrance>
* 🇪🇸 Spanish Español: <https://t.me/Cloverhispano>
* 🇰🇷 Korean 한국어: [https://t.me/CloverKorean ](<https://t.me/CloverKorean >)
* 🇨🇳 Chinese 中文: <https://t.me/CloverCN>
* 💵 Trade discussion: <https://t.me/Clovertraders>

{% hint style="info" %}
Global Community groups are unofficial and moderated by volunteers
{% endhint %}


# 📚  Beginner’s Guide


# Setup CLV Wallet

### Installing CLV Wallet

If you have not yet installed CLV Extension Wallet on your Chrome or Brave browser, please do so via [**this link**](https://chrome.google.com/webstore/detail/clover-wallet/nhnkbkgjikgcigadomkphalanndcapjk).

{% hint style="danger" %}
Remember to save your password and seed phrase in a secure location.&#x20;

**Never share this information with anyone.**
{% endhint %}

#### CLV Wallet has built-in support for CLV M-Chain and CLV P-Chain, you do not have to manually add a new network.&#x20;

For more information on how you can use your CLV wallet, please follow [our guide here](/use-clv-wallet/clv-extension-wallet).&#x20;

{% hint style="warning" %}
IMPORTANT: To use the CLV chain, you must have $CLV for transaction gas fees. **0.02 $CLV** is recommended, it will be more than enough to get you started on CLV Chain. See how you can [withdraw and bridge $CLV to CLV P-Chain.](/use-clv-chain/beginners-guide/how-to-get-usdclv)
{% endhint %}


# Setup Metamask Wallet

### Installing Metamask

If you have not yet installed MetaMask on your Chrome, Brave or Firefox browser, please do so via [**this link**](https://metamask.io/).

{% hint style="danger" %}
Remember to save your password and seed phrase in a secure location.&#x20;

**Never share this information with anyone.**
{% endhint %}

### Connect Metamask to CLV Chain

1. Login to MetaMask&#x20;
2. In the top right corner of the page, select the Network dropdown menu.
3. Select **Add Network**.
4. Continue to fill in the CLV Network information:\
   \
   \- **Network Name:** CLV Parachain\
   \- **New RPC URL:** <https://api-para.clover.finance\\>
   \- **Chain ID:** 1024\
   \- **Symbol:** CLV\
   \- **Explorer:** <https://clvscan.com/>
5. Select **Save**.

![](/files/o5EXVRcysRuEFYFpTD6O)

### Add CLV Compatible Tokens

All your CLV compatible tokens will be viewable in this network once you have imported the token information.&#x20;

1. Navigate to the bottom of the CLV Network page in MetaMask and select **Import Token**.&#x20;
2. Enter the information for the token you wish to import (you can find this on blockchain explorers such as [CLVscan](https://clvscan.com/)).&#x20;
3. The token information will usually autofill. Always double-check the token contract address to make sure it is not a fake version.&#x20;
4. Select **Add Custom Token** to save.&#x20;

![](/files/NPejMWtZQWq8VGyyoTdl)

{% hint style="warning" %}
IMPORTANT: To use the CLV chain, you must have $CLV for transaction gas fees. **0.02 $CLV** is recommended, it will be more than enough to get you started on CLV Chain. See how you can [withdraw and bridge $CLV to CLV Parachain.](/use-clv-chain/beginners-guide/how-to-get-usdclv)
{% endhint %}


# How to Get $CLV

{% hint style="info" %}
**$CLV token lives on 4 chains -**&#x20;

* as an ERC20 token on Ethereum Mainnet
* as a BEP20 token on BNB Chain (previously called Binance Smart Chain)
* as a Substrate Native token on CLV M-Chain
* as an EVM Native token on CLV P-Chain
  {% endhint %}

{% hint style="success" %}
**To get $CLV on CLV P-Chain and start using decentralized applications, please follow the guide below ⬇️**
{% endhint %}

![](/files/YbdRGAWCrH9zeOw0LjHT)

![](/files/WSVt5oWT5sUVFmfB92Z5)

### 1. Transfer $CLV from Crypto Exchanges to Your Wallet on Ethereum or BNB Chain

$CLV token is trading on all major crypto exchanges, including Binance, Coinbase, FTX, Coinlist Pro, Huobi, OKX, KuCoin, Gate, MEXC etc.&#x20;

* **Binance:** [CLV/USDT](https://www.binance.com/en/trade/CLV_USDT), [CLV/BUSD](https://www.binance.com/en/trade/CLV_BUSD), [CLV/BNB](https://www.binance.com/en/trade/CLV_BNB), [CLV/BTC](https://www.binance.com/en/trade/CLV_BTC)
* **Coinbase Pro:** [CLV/USDT](https://pro.coinbase.com/trade/CLV-USDT), [CLV/USD](https://pro.coinbase.com/trade/CLV-USD), [CLV/GBP](https://pro.coinbase.com/trade/CLV-GBP), [CLV/EUR](https://pro.coinbase.com/trade/CLV-EUR)
* **FTX:** [CLV/USD](https://ftx.com/trade/CLV/USD)
* **Coinlist Pro:** [CLV/USDT](https://pro.coinlist.co/trader/CLV-USDT), [CLV/USD](https://pro.coinlist.co/trader/CLV-USD)
* **Huobi:** [CLV/USDT](https://www.huobi.com/en-us/exchange/clv_usdt), [CLV/BTC](https://www.huobi.com/en-us/exchange/clv_btc)
* **OKX:** [CLV/USDT](https://www.okx.com/trade-spot/clv-usdt)
* **KuCoin:** [CLV/USDT](https://trade.kucoin.com/CLV-USDT)
* **CoinEx:** [CLV/USDT](https://www.coinex.com/exchange/CLV-USDT)
* **Gate:** [CLV/USDT](https://www.gate.io/trade/CLV_USDT)
* **MEXC:** [CLV/USDT](https://www.mexc.com/zh-CN/exchange/CLV_USDT)
* **Hoo:** [CLV/USDT](https://hoo.com/innovation/clv-usdt)
* **Bithumb Global:** [CLV/USDT](https://www.bithumb.pro/en-us/spot/trade?q=CLV-USDT)
* **Pionex**: [CLV/USDT](https://www.pionex.com/en-US/trade/CLV_USDT)

Once having $CLV in your exchange account, you can head to the 'Asset' page, find $CLV and click on withdraw.&#x20;

In the withdrawal window, fill in your MetaMask or CLV Wallet address (it should start with '0x...') and choose Ethereum or BNB Chain as the destination.&#x20;

We recommend you withdraw to BNB Chain due to less gas fee used on the chain.

{% hint style="warning" %}
At the moment, withdrawal from CEXs is only available to Ethereum (ERC20) and BNB Chain (BEP20).&#x20;
{% endhint %}

### 2. Bridge your $CLV from Ethereum or BNB Chain to CLV M-Chain <a href="#clv-bridge" id="clv-bridge"></a>

After receiving $CLV token in your CLV wallet, you can now bridge your Ethereum and or BNB chain $CLV tokens to CLV M-Chain. This can be done using the Cross-Chain Bridge.

{% hint style="warning" %}
For now, $CLV cross-chain bridge is available to CLV wallet application.&#x20;

We recommend using CLV Extension wallet on desktop platforms, download here: [CLV Chrome Extension Wallet](https://chrome.google.com/webstore/detail/clover-wallet/nhnkbkgjikgcigadomkphalanndcapjk)
{% endhint %}

#### First, search and add the corresponding $CLV token to your asset's list. &#x20;

<figure><img src="/files/e3a0KCMyUubyM2rwKQ7t" alt=""><figcaption></figcaption></figure>

#### Second, scroll down on the Assets page, and select your $CLV on your chosen chain (Ethereum, or Binance Smart Chain)

<figure><img src="/files/mH87lxTP4lffy9Gmq8M1" alt=""><figcaption></figcaption></figure>

#### Third, select the "Cross-Chain" action button, then input your CLV M-Chain address (starts with '5....') and select continue. You will need to input the amount of $CLV you would like to bridge to CLV M-Chain. Afterwards, select "Continue" and "Confirm" transaction.&#x20;

*Note that this cross-chain transfer is from \[Ethereum or BNB] to CLV M-Chain, thus you need to input a CLV M-Chain address as destination.* &#x20;

*CLV M-Chain address can be viewed when you select the $CLV M-Chain token under Assets page and select "Receive".*

*Cross-chain transfers on the CLV M-Chain cost roughly 0.5 $CLV, 1 $CLV on Binance, and up to 20 $CLV on the Ethereum mainnet due to high gas fees on the Ethereum network.*

<figure><img src="/files/2UMIhuRvz1q0Lk5sIQad" alt=""><figcaption></figcaption></figure>

### 3. Convert your $CLV from CLV M-Chain to CLV P-Chain&#x20;

Converting $CLV from CLV M-Chain to CLV P-Chain is very similar to the bridging process.

{% hint style="warning" %}
For now, this conversion can only be done using CLV Extension wallet. Download here: [CLV Chrome Extension Wallet](https://chrome.google.com/webstore/detail/clover-wallet/nhnkbkgjikgcigadomkphalanndcapjk)
{% endhint %}

#### First, from the Assets page, select your $CLV on CLV M-Chain

<img src="/files/0iPxw7t5adiFI1sGbZdt" alt="" data-size="original">

#### Second, select the "Cross-Chain" action button, then choose CLV P-Chain and select continue. You will need to input the amount of $CLV you would like to convert to CLV P-Chain. Afterwards, select "Continue" and "Confirm" transaction.&#x20;

*Note that cross-chain transfers Fee for the CLV M-Chain to CLV P-Chain conversion cost roughly 0.5 $CLV, with an additional Txn Fee that is currently 0.001411 $CLV.*

<figure><img src="/files/4djqorxuyxNtiES91C08" alt=""><figcaption></figcaption></figure>

{% hint style="success" %}
Now you have got your $CLV token on CLV P-Chain, start using decentralized applications!
{% endhint %}


# Bridge Other Assets to CLV P-Chain (Parachain)


# 🌐  Network Details

## CLV P-Chain

* **Docker Image**: [clover-para:polkadot-v0.9.16-1](https://hub.docker.com/layers/clover-para/cloverio/clover-para/polkadot-v0.9.16.1/images/sha256-50792e2b78c495220210e611c561861e99634c399f433e5a9fb39a25c98621e7?context=explore)
* **Apps Portal**: [https://apps-ivy.clv.org](https://apps-ivy.clv.org/)
* **EVM Blockchain Explorer:** <https://clvscan.com>
* **EVM Network ID:** 1024
* **RPC Endpoints**:
  * <https://api-para.clv.org>
* **API Endpoints**:

  * wss\://rpc-para.clv.org

  <div data-gb-custom-block data-tag="hint" data-style="info" class="hint hint-info"><p>CLV EVM is enabled only on CLV Parachain (P-Chain)</p></div>

## CLV Mainnet

* **Docker Image**: [cloverio/clover-ivy:0.1.23 ](https://hub.docker.com/r/cloverio/clover-ivy/tags?page=1\&ordering=last_updated)
* **Apps Portal**: [https://apps-ivy.clv.org](https://apps-ivy.clv.org/)
* **Blockchain Explorer:** <https://clover.subscan.io/>
* **RPC Endpoints**:
  * <https://rpc-ivy.clv.org>
  * <https://rpc-ivy-2.clv.org>
  * <https://rpc-ivy-3.clv.org>
* **API Endpoints**:
  * wss\://api-ivy-elastic.clv.org
  * wss\://api-ivy-2.clv.org
  * wss\://api-ivy-3.clv.org

{% hint style="info" %}
Staking and governance features are enabled only on mainnet.
{% endhint %}

## CLV Testnet

* **Docker Image**: [cloverio/clover-iris:0.1.15 ](https://hub.docker.com/r/cloverio/clover-iris/tags?page=1\&ordering=last_updated)
* **Apps Portal**: <https://apps.clv.org>
* **EVM Network ID:** 1023
* **RPC Endpoints**:
  * <https://rpc.clv.org>
  * <https://rpc-2.clv.org>
  * <https://rpc-3.clv.org>
* **API Endpoints**:
  * wss\://api.clv.org
  * wss\://api-2.clv.org
  * wss\://api-3.clv.org


# 🏦  Economics


# Tokenomics

## Tokenomics at Genesis

The total supply at Genesis is 1,000,000,000 CLV

| Type                | Allocation | Vesting Terms                                                                            |
| ------------------- | ---------- | ---------------------------------------------------------------------------------------- |
| Public Sale         | 15%        | With 3 options (40 days, 6-month and 12-months lockup)                                   |
| Private Sale        | 2.5%       | 6-months locked  / 12-months vesting                                                     |
| Early Backers       | 10%        | 36-months vesting (28% unlock at parachain launch, linearly release over next 23 months) |
| Team                | 10%        | 36-month vesting                                                                         |
| Marketing           | 7.5%       | 36-months vesting (28% unlock at parachain launch, linearly release over next 23 months) |
| Ecosystem Incentive | 20%        | 1-month locked  / 36-months vesting                                                      |
| Parachain Offering  | 20%        | 1-month locked  / 36-months vesting                                                      |
| Foundation          | 12%        | 36-months vesting (28% unlock at parachain launch, linearly release over next 23 months) |
| Contributors Grant  | 3%         | 36-months vesting (28% unlock at parachain launch, linearly release over next 23 months) |

## Token Release Schedule

#### Coinlist Sale

* Round 1 was unlocked on July 15, 2022&#x20;
* Round 2 vesting started on January 15, 2022&#x20;
* Round 3 was distributed 40 days after TGE

#### Monthly Release Time

\- 15th of every month: CLV Parachain Reward

\- 15th of every month: Coinlist Round 2&#x20;

\- 16th of every month: CLV Private Sale\ <br>

<figure><img src="/files/f7HeXg1cl0gqtXUXoCpc" alt=""><figcaption></figcaption></figure>

## Actual  tokenomics figures for CLV (including inflation) &#x20;

* **Total Circulating Supply**: 1,224,140,929 tokens\*
* **Total Supply**: 2,000,000,000 tokens
* **Max Supply**: ∞ (infinite)\
  \
  \**as of  08/11/ 2024;  circulcing supply will increase overtime* &#x20;


# Inflation Design

The CLV chain adopts the same inflation design as Polkadot's, as it's a proven and long-term economical design that we think fulfills the future development of the CLV ecosystem.&#x20;

Inflation to validators is dynamic, between 2.25% - 20% annually, depending on $CLV staking rate on CLV Mainnet.&#x20;

Although the total number of $CLV in circulation is the combination of the number of tokens on 4 chains ($CLV on Ethereum, BNB Chain, CLV Parachain and CLV Mainnet), the inflation model is only subject to the amount of $CLV circulating on the CLV Mainnet.

<table><thead><tr><th width="162">Staking Rate</th><th width="168.58426966292134">Inflation to Stakers</th><th width="177.76761711420752">Monthly Reward Rate</th><th>Yearly Reward Rate</th></tr></thead><tbody><tr><td>0%</td><td>2.25%</td><td>>125%</td><td>>1,500%</td></tr><tr><td>5%</td><td>3.25%</td><td>5.42%</td><td>65%</td></tr><tr><td>10%</td><td>4%</td><td>3.33%</td><td>40%</td></tr><tr><td>20%</td><td>5.5%</td><td>2.29%</td><td>27.5%</td></tr><tr><td>25%</td><td>6.25%</td><td>2.08%</td><td>25%</td></tr><tr><td>30%</td><td>7%</td><td>1.94%</td><td>23.3%</td></tr><tr><td>40%</td><td>8.5%</td><td>1.78%</td><td>21.3%</td></tr><tr><td>50%</td><td>10%</td><td>1.67%</td><td>20%</td></tr><tr><td>60%</td><td>4.38%</td><td>0.61%</td><td>7.3%</td></tr><tr><td>70%</td><td>2.97%</td><td>0.35%</td><td>4.2%</td></tr><tr><td>80%</td><td>2.62%</td><td>0.28%</td><td>3.3%</td></tr><tr><td>90%</td><td>2.53%</td><td>0.23%</td><td>2.8%</td></tr><tr><td>100%</td><td>2.51%</td><td>0.21%</td><td>2.51%</td></tr></tbody></table>

### Inflation & Staking Rate Formula <a href="#dd3b" id="dd3b"></a>

![Formula for inflation and interest rate](/files/x2PZwueQp3Jx0khsvyma)

The value of the staking rate should lie between 30% and 60% - **ideally at 50%.** If it falls, the security is compromised, so we should give strong incentives to $CLV holders to stake more of their assets. If it rises, we lose liquidity, so we should decrease the incentives sharply.

`x = staking rate(x is always a value between 0 and 1)`\
\&#xNAN;*`green graph`*` ``= i (x) yearly`` `*`interest rate`*\
\&#xNAN;*`blue graph =`*` ``I (x)`` `*`inflation rate to stakers`*

x-axis represents the total staking rate, y-axis interest rate (green) or inflation to validator rate (blue)

![](https://miro.medium.com/max/1218/1*vgRfVT0i1-oc8-bBC46l0Q.png)

1. &#x20;Number 1 displayed in the graph is the minimum of the inflation to stakers (i.e. when neither validators nor nominators are staking $CLV). It’s the inflation “starting” point; 0.025 → 2.5% in this case goes away for validator rewards.
2. The second number shows a linear increase of inflation if the staking rate is between 0 and 50%. There is a linear correlation between the staking rate and inflation till 0.5 is reached. The inflation rate is 5% if the staking rate is at 25%. If the staking rate doubles to 50%, so does the inflation rate to 10%. But remember: It is only linear till 50% staking rate is reached.&#x20;
3. The red line at number 3 is the ideal staking rate of 50%. In this case, the annual staking reward is at 20%. But if the staking rates exceeds 50%, there is an exponential decay in inflation, which results in a strong decay of staking rewards. The reason for that is that the network needs liquidity and decreases the incentives sharply if the staking rate exceeds 50%.&#x20;

\
\
For Further Reference (Polkadot inflation design 2021):

1. [Polkadot’s Tokenomics and Interoperability](https://www.coinbase.com/en-sg/institutional/research-insights/research/tokenomics-review/polkadot-interoperability) - Coinbase Research
2. [Polkadot Inflation and Staking Reward Analysis](https://swiss-staking.medium.com/polkadot-inflation-staking-reward-4ea753380e0e) - Swiss Staking
3. &#x20;[Economics of Polkadot](https://polkadot-blockchain-academy.github.io/pba-book/economics/economics-of-polkadot/page.html) - Polkadot Blockchain Academy
4. [Web3 Foundation’s Overview of Polkadot’s Token Economics](https://research.web3.foundation/en/latest/polkadot/overview/2-token-economics.html) - Web3 Foundation


# Governance

At CLV, we believe in empowering our community through a decentralized governance system. This governance framework ensures that $CLV token holders can actively participate in shaping the platform’s future, driving its growth, and enhancing its utility.

**Governance Overview**

The governance mechanism provides a structured and transparent process for $CLV token holders to propose, discuss, and vote on changes that impact the ecosystem. From protocol upgrades to community-driven initiatives, every stakeholder has a voice in decision-making. The Snapshot platform will serve as the foundation for all proposals and voting activities, ensuring accessibility and transparency.

**Participation in Governance**

* Eligibility: All $CLV token holders can participate in governance by creating proposals or voting on active proposals.
* Snapshot Platform: The Snapshot platform allows governance activities to be conducted off-chain while maintaining full transparency and trust.

**Governance Process**

1. Proposal Creation:

* Any $CLV holder can draft a proposal outlining the intended change, its rationale, and expected benefits or impacts.
* Proposals should follow a clear template to ensure consistency and completeness.

2. Community Discussion:

* Before a proposal is put to vote, it undergoes a discussion phase on the Snapshot platform or official forums.
* This phase allows community members to provide feedback, suggest improvements, and build consensus around the proposal.

3. Voting Phase:

* Once the discussion phase is complete, the proposal enters the voting phase on Snapshot.
* Voting power is proportional to the number of $CLV tokens held, ensuring alignment between token ownership and decision-making influence.

4. Implementation:

* Proposals that meet the required quorum and approval thresholds will be executed by the development team in collaboration with the community.
* Updates on implementation progress will be shared transparently with the community.

**Proposal Categories**

Governance proposals can cover a wide range of topics, including but not limited to:

* Protocol Upgrades: Enhancements to the platform’s performance, security, or functionality.
* Parameter Adjustments: Changes to staking rewards, transaction fees, or other system parameters.
* Asset Listings: Proposals to list new tokens or assets on the CLV platform.
* Community Initiatives: Programs that foster user engagement, education, or ecosystem growth.
* Treasury Utilization: Decisions regarding the allocation or use of funds in the community treasury.

**Voting Mechanism**

* Quorum Requirements: A minimum percentage of total $CLV tokens must participate in the vote for it to be valid. This ensures proposals reflect the will of the broader community.
* Approval Threshold: A specific percentage of 'Yes' votes is required for a proposal to pass. These thresholds will be clearly defined for each proposal type.

**Continuous Evolution**

Governance at CLV is designed to evolve alongside the ecosystem. Regular reviews and community feedback will help refine the process, ensuring it remains fair, efficient, and aligned with the community’s goals.

With this governance mechanism, CLV aims to foster a truly decentralized and collaborative environment where every token holder can contribute to the platform’s growth and success. Together, we’re building a future that reflects the shared vision of our community.

<br>

<br>


# 🙋🏻  CLV Chain FAQ

### Is there an "Existential Deposit" for CLV Chain?

No, you can keep any amount of $CLV in your wallet without worrying your fund being destroyed.&#x20;

### What is the TPS of CLV Chain?

Estimated TPS is around 1000 transactions per second.&#x20;

### What is the minimum gas price?

50 gwei

### What is the block gas limit?

30,000,000 gwei

### What is the transaction gas limit?

30,000,000 gwei

### What is the target block time?

12 seconds (expected to be 6 seconds)


# $CLV Cross-Chain Explorer

CLV Cross-Chain Explorer (<https://tx.clover.finance/>) shows all the information about the CLV cross chain transactions

## Cross-chain Transaction Summary

The summary section will show:

* Total cross-chain transaction happened
* Total cross-chain volume in $CLV
* Total number of addresses who participate the cross-chain
* Current cross-chain fees.  CLV M-Chain <-> Ethereum and CLV M-Chain <-> BSC

Also users can search all the cross-chain transactions by hash or their $CLV (Native token, ERC20, BEP20) token address

## Cross-chain Transaction Record

cross-chain transaction list will show all the details, like:

* From address, with the source blockchain info
* To address, with the target blockchain info
* Amount of $CLV transferred
* The cross-chain transaction time, fee, duration, and status

![Cross-chain Tx List](/files/-MeAgU7HyzsdYRjmtVj4)

## Cross-chain Transaction Details

You can click the cross-chain transaction record to expand the details:

* Burn info, including the transaction hash, block number, block confirmations, etc. You can also view the burn transaction on Etherscan or Subscan
* Mint info
* Claim info, including the claim transaction hash, claim block, claim time, etc.

![Cross-chain Details](/files/-MeAhI9Kh-oGK1rO35g-)

## Claim Your $CLV

In some rare cases, for example you uninstall the CLV mobile or extension wallet which contains pending cross-chain transactions, you will need to manually claim your $CLV.

There are two ways to claim your $CLV:

### Using Cross-Chain Explorer

1. First, click the "Claim $CLV" button on the right upper corner
2. Fill in the claim form:

Blockchain: you need to select the blockchain where the transaction happened.

Transaction Hash: you need to copy your transaction hash from [Etherscan](https://etherscan.io/) or [BscScan](https://bscscan.com/)

CLV chain Address: **make sure the CLV chain address is yours, otherwise you may lose your $CLV forever!**

Private Key: the private key or seed phrase of your **Ethereum/BSC** account (CLV will **never save** your private key, it will only be used in your computer, and deleted from any cache once you close the claim dialog!).

3\. Confirm the claim

4\. Check your balance after claim succeed

### Using CLV Extension Wallet

* First, you need to install CLV intension wallet and import the same account from which you sent the previous cross-chain transaction
* Connect you wallet to the cross-chain transaction explorer
* Search your address or the pending transaction hash
* Expand the detail, and click the "Claim" button
* Input your claiming CLV chain address trigger the claim process

![Claim CLV from Cross-chain Transaction Explorer](/files/-MeDVvh8nK5iJ-rZxJkJ)

Once you input your CLV chain address, just click "claim" to invoke CLV extension wallet to sign your claim request.

![Sign your Claim Request ](/files/-MeDWrFYfjfdamM8xDw4)

Once your claim is successful, you can view your claim transaction detail in Subscan.

![Claim Success](/files/-MeDXboB-KyVDxUT-4pR)


# $CLV Cross-Chain Transfer

Using CLV mobile wallet or extension wallet. You can cross-chain transfer your CLV M-Chain $CLV token to Ethereum , BSC and CLV P-Chain.  This is mostly an automatic process, without the need to claim.

## $CLV Tokens

{% hint style="danger" %}
**DO NOT send $CLV cross-chain transfer to any of the addresses listed below or you will risk losing your assets, these are only example addresses or contract addresses which the team DOES NOT have access to. Please send the cross-chain transfer only directly to your own address or input address on an exchange account.**&#x20;
{% endhint %}

Currently, there are three kinds of $CLV assets:

### 1. CLV M-Chain $CLV native token

This is the token issued on CLV M-Chain. The address format is like: **5CyngUVPJD2MnAbrYR9F72CA5YX1VekR6ip9n2QuuBWcKXKB**. You can view your balance in Subscan, the url is like (you need to change the address to your own!):  <https://clover.subscan.io/account/5CyngUVPJD2MnAbrYR9F72CA5YX1VekR6ip9n2QuuBWcKXKB>

### 2. $CLV ERC20 token

This is the erc20 token deployed on Ethereum. The address format is like: **0xcdbf90174493dcc418f177a4d7b2604a95997e1f**. The smart contract address is: [0x80C62FE4487E1351b47Ba49809EBD60ED085bf52](https://etherscan.io/address/0x80C62FE4487E1351b47Ba49809EBD60ED085bf52)

### 3. $CLV BEP20 token

This is the bep20 token deployed on BSC. The address format is like: **0xcdbf90174493dcc418f177a4d7b2604a95997e1f**. The smart contract address is: [0x09E889BB4D5b474f561db0491C38702F367A4e4d](https://bscscan.com/address/0x09E889BB4D5b474f561db0491C38702F367A4e4d)

### 4. CLV P-Chain $CLV native token

This is the token issued on CLV P-Chain. The address format is like: **0xcdbf90174493dcc418f177a4d7b2604a95997e1f**. You can view your balance in CLVscan, the url is like (you need to change the address to your own!):  <https://clvscan.com/address/0x09E889BB4D5b474f561db0491C38702F367A4e4d>

## CLV M-Chain $CLV Native Token

If you install CLV extension wallet, you should see $CLV token:

![](/files/60TgAepUDSwAle77SESm)

Please note that this is CLV M-Chain native token (the address format has a prefix of 5)

## Add $CLV Wrapped Tokens

When you wan to make a cross-chain transfer, you may need to add CLV wrapped tokens on target networks, such as Ethereum, BSC. You can click the 'Add Token' button on the bottom of the main page:

<figure><img src="/files/C8XLVScrUWcR6hY31zeY" alt=""><figcaption></figcaption></figure>

## Make a Cross-Chain Transfer

If you have the knowledge of the four different $CLV assets. It is time to make a cross-chain transfer. Let us give an example of **how to transfer native $CLV token to Ethereum**. Here we will use extension wallet to explain (You can use mobile wallet to do cross-chain transfer as well !).

#### Select the "Cross-Chain" action button, then input your Ethereum address (starts with '0x....') and select continue. You will need to input the amount of $CLV you would like to bridge to Ethereum. Afterwards, select "Continue" and "Confirm" transaction.&#x20;

<figure><img src="/files/kjREedRQIw6DRzcdjsbv" alt=""><figcaption></figcaption></figure>

Before you click Continue button, please make sure:

* The target chain is correct, here we use BSC
* The recipient address is correct.
* The transfer amount (There is a minimum amount for cross-chain)

Please noted that:&#x20;

* If you cross-chain transfer $CLV to Ethereum or BSC, there will be a cross-chain fee + transaction fee charged.  However, users don't need to pay ETH or BNB as cross-chain fee.
* You can check current cross-chain fee at <https://tx.clv.org>
* *Cross-chain transfers on the CLV M-Chain cost roughly 0.5 $CLV, 1 $CLV on Binance, and up to 20 $CLV on the Ethereum mainnet due to high gas fees on the Ethereum network.*
* *Ethereum address can be viewed when you select the ETH token under Assets page and select "Receive".*

### 4. Confirm your cross-chain transaction

Once you confirm and send the cross-chain transaction, you can just wait for your transaction to be successful. You can check your cross-chain transaction in your wallet or CLV's cross-chain transaction explorer at <https://tx.clv.org>

<figure><img src="/files/4EODts3KCTqekg1HY0w0" alt=""><figcaption></figcaption></figure>


# What are Nominator & Validator?

CLV chain uses NPOS (Nominated Proof-of-Stake) as its consensus mechanism, which is the same as [Polkadot](https://polkadot.network/) uses. CLV users can participate in the consensus as nominators.

You may have an account with $CLV and want to stake $CLV to earn more. You could do so as **validator**, which requires a node running 24/7. If you do not have such a node or do not want to bother, you can still earn $CLV by nominating one or more validators. By doing so, you become a **nominator** for the validator(s) of your choice.

* Learn Nominator: [Nominator · Polkadot Wiki](https://wiki.polkadot.network/docs/learn-nominator)
* Learn Validator: [Validator · Polkadot Wiki](https://wiki.polkadot.network/docs/learn-validator)


# Stake as a Nominator

In this page you will find guide stake your $CLV token as a nominator.

{% tabs %}
{% tab title="Staking via CLV Wallet" %}

## Prerequisite

You need to have CLV mobile wallet installed.

* [Android version](https://play.google.com/store/apps/details?id=com.clover.finance.wallet\&hl=en_US\&gl=US)
* [iOS version](https://apps.apple.com/app/clover-wallet/id1570072858)

## Stake $CLV

The following guide shows how to stake $CLV on CLV mobile wallet.

### Click the Stake to Earn Button and choose CLV Staking

### ![](/files/X9hK9ATBYTfwa6eBmQpM)&#x20;

### Input $CLV Amount for Staking

![](/files/4h0yC3TNyxWP3WL1Nqz4)

### Select Validators to Nominate

![](/files/rjAVpFLYsN6OkwC9b82A)

### Sign the Transaction

![](/files/TMXUAXzC26WQA7OGb5eB)

## More Actions

Once you successfully stake your $CLV, you can view the transactions on the staking detail page. You can do more actions there, for example:

* Stake more $CLV
* Change validators
* Unstake $CLV

![](/files/gdtQcuPKeLE3oM7QhRuT)

Please note that&#x20;

1. The staked tokens will be locked for about 24 days on CLV blockchain after unstaking.
2. You need at least 1 CLV remain to keep your account alive
3. CLV will claim the staking reward and add it to your staked fund automatically. All your funds and reward can transfer back to your account after your unstaking.
4. According to current staking rules of NPOS staking, only top 256 nominators can get rewards from a validator. If you’re not in the list, an oversubscribed tag will show up in the validator list page. Please try to nominate other validators or stake more.
   {% endtab %}
   {% endtabs %}


# Running a Validator or RPC Node

{% tabs %}
{% tab title="Running a Validator" %}
This guide will instruct you how to set up a CLV validator node on CLV networks (Testnet/Sakura/Mainnet).&#x20;

## :point\_right: Must Read Before Start…

Running a validator is a serious thing, you have a lot of responsibility for the staked tokens of you and nominators.  You take the risk of losing your staked tokens, as a slash might happen if your validator node is not properly configured. Please make sure you or your team have the necessary knowledge to run a validator node.

[Polkadot Wiki ](https://wiki.polkadot.network/docs/en/maintain-guides-how-to-validate-polkadot)has an awesome introduction of running a validator node on the [Polkadot network](https://polkadot.network/).  As a member of the Polkadot ecosystem, CLV follows the similar process to run and set up a validator node. We may skip some basics steps in this tutorial.

## :tools: Hardware Requirements

* **CPU** - Recent released high-end CPU, e.g., Intel Core i7-10700/AMD Ryzen 7 5800X or above
* **Memory** - 32 GB for Testnet, 64 GB for Sakura and Mainnet.
* **Storage** - 300 GB SSD, Storage usage could increase by time, you might need to increase the capacity as the chain data grows.
* **OS**: Linux, Debian/Ubuntu LTS distributions are recommended.

## :wrench: Prepare Environment

We'll use [docker](https://docs.docker.com/engine/) and [docker-compose](https://docs.docker.com/compose/) to run the validator in this guide. You need to install docker and docker-compose firstly.  Please follow the installation guide in the docs.

* [Docker Install Document](https://docs.docker.com/engine/install/)
* [Docker-Compose Install Document](https://docs.docker.com/compose/install/)

{% hint style="info" %}
We're using docker to simplify the setup process. You can use the tools which you're familiar with.
{% endhint %}

### :satellite\_orbital: Firewall Setup

Below ports need to be exposed:

* **30333** - The p2p port of the chain

### :file\_folder: Create Directories

Create the config and data directories using the below command:

```bash
sudo mkdir -p /opt/data/
sudo mkdir -p /opt/compose/
# secure the data access
sudo chmod 0700 /opt/data
sudo chmod 0700 /opt/compose 
```

## :gear: Setup CLV Validator Node

Currently, we only have CLV **Testnet** (iris) and CLV **Mainnet** (ivy) launched. CLV Testnet opens for validators to join.  CLV *Mainnet operates in the POA mode and maintained by 6 nodes  belongs to* CLV *foundation*.&#x20;

Validator Configuration for CLV Mainnet will be updated later once it's ready for staking and validators can join.

### :pencil: Create the Compose configure file

Create `/opt/compose/docker-compose.yaml` and set the content as below:

```yaml
version: "3.8"
services:
  clover-validator:
    image: "cloverio/clover-ivy:0.1.23"
    restart: always
    command:
      - /opt/clover/bin/clover
      - --chain 
      - /opt/specs/clover-ivy.json  
      - --base-path 
      - /opt/chaindata
      - --validator
      - --name 
      - 🍀clover-validatornode
      - --port 
      - "30333"
      - --ws-port 
      - "9944"
      - --rpc-port 
      - "9933"
      - --rpc-cors=all 
      - --execution
      - wasm
      - --wasm-execution
      - compiled
    ports:
      - "30333:30333"
      - "9933:9933"
      - "9944:9944"
    volumes:
      - /opt/data/clover:/opt/chaindata
```

{% hint style="info" %}
You can edit the `docker-compose.yaml` and include your customizations by updating below arguments:

* image: the docker image used to launch the node, for CLV mainnet, use `cloverio/clover-ivy:0.1.16.`For a full list of clover networks please check out the [CLV Network List](broken://pages/-MYhDyMWo8dJUd4qGMdz) page.
* \--*name*:  The node name of your validator, the name could be found in the telemetry node list.
* *--unsafe-rpc-external:*  You might need this flag to call the `author_rotateKeys` api, make sure to remove this flag later on for better security.
* Ensure enable the `--exeuction wasm` flag, This is required for all validator nodes.
  {% endhint %}

## :rocket: Bring up the validator node

Use below command to bring up the validator node:

```bash
cd /opt/compose # goto the compose file directory
docker-compose up # bring up the validator node in the foreground
## check whether the node starts up normally
## Ctrl-C stop the node
docker-compose up -d # start the validator node in the daemon mode.
```

You need to check the node logs using `docker-compose logs` command. Wait until the node is synced and the block numbers syncs with the latest number on the chain.

## :chart: Bond CLV

Checkout [Staking](/clv-validator-and-staking/stake-as-a-nominator) documentation.

## :key2: Set the session keys

Checkout [Polkadot Session Keys](https://wiki.polkadot.network/docs/en/maintain-guides-how-to-validate-polkadot#option-2-cli) documentation.

## :stars: Validate

Checkout [Polkadot Validate](https://wiki.polkadot.network/docs/en/maintain-guides-how-to-validate-polkadot#validate) documentation.

## :trident: Links

* [CLV Testnet Apps](https://apps.clover.finance)
* [CLV Mainnet Apps](https://apps-ivy.clover.finance)
  {% endtab %}

{% tab title="Running a RPC Node" %}
CLV Foundation provides the RPC services for the public. Sometimes it's necessary to run a self hosted CLV RPC service if the public services can't satisfy your needs. <br>

With a self hosted CLV RPC service you could gain below benefits:

* Faster access speed - a Self-hosted RPC node could provide better performance
* Better security - transactions could be sent to to the self-hosted RPC server instead of the public service.
* Better Availability<br>

CLV is a fully decentralized network, anyone can setup a CLV node by following this tutorial!

## &#x20;:four\_leaf\_clover: Types Of CLV RPC Nodes

Generally speaking, there are two kind of RPC nodes:<br>

* **Archive node**\
  An archive node keeps all the past blocks data. And client can't query data in any of the past blocks.<br>
* **Full node**\
  A full is node is pruned. which means it keeps only a few of the past blocks data (256 by default, which could be adjusted using the `--pruning` command line arguments.<br>

An archive nodes consumes much more disk spaces it stores more data than a full node. You need to take the decision based on your business model and requirements. E.g. block explorer and historical analysis tools normally requires an archive node to query the full historical data. Wallets on the other hand normally only requires a full node to be able to query the current state(e.g. the balance of an account) and submit transactions to the CLV Network.

## :tools: Hardware requirements

* **CPU** - Recent released high end cpu, e.g. Intel Core i7-10700/AMD Ryzen 7 5800X or above
* **Memory** - 32GB for Testnet, 64GB for Sakura and Mainnet.
* **Storage** - 300GB SSD, Storage usage could increase by time, you might need to increase the capacity as the chain data grows..
* **OS**: Linux, Debian/Ubuntu LTS distributions are recommended.

## Prepare Environment

We'll use [docker](https://docs.docker.com/engine/) and [docker-compose](https://docs.docker.com/compose/) to run the validator in this guide. You need to install docker and docker-compose firstly.  Please follow the installation guide in the docs.

* [Docker Install Document](https://docs.docker.com/engine/install/)
* [Docker-Compose Install Document](https://docs.docker.com/compose/install/)

{% hint style="info" %}
We're using docker to simplify the setup process. You can use the tools which you're familiar with.
{% endhint %}

### :satellite\_orbital: Firewall Setup

Below ports need to be exposed:

* **30333** - The p2p port of the chain
* ***9933** - The http endpoint of the RPC service*
* ***9944** - The websocket endpoint of the RPC service.*

{% hint style="info" %}
**You may not expose 9933/9944 ports directly.** Instead a reverse proxy server could be setup in front and proxy requests to the rpc backend.
{% endhint %}

### :file\_folder: Create Directories

Create the config and data directories using below command:

```bash
sudo mkdir -p /opt/data/
sudo mkdir -p /opt/compose/
# secure the data access
sudo chmod 0700 /opt/data
sudo chmod 0700 /opt/compose 
```

## :gear: Setup CLV RPC Node

Currently we only have CLV **Testnet**(iris) and CLV **Mainnet**(ivy) launched.

Rpc Configuration for CLV Mainnet will be updated later.

### :pencil: Create the Compose configure file

Create `/opt/compose/docker-compose.yaml` and set the content as below:

&#x20;

```yaml
version: "3.8"
services:
  clover-validator:
    image: "cloverio/clover-ivy:0.1.15"
    restart: always
    command:
      - /opt/clover/bin/clover
      - --chain 
      - /opt/specs/clover-preview-iris.json  
      - --base-path 
      - /opt/chaindata
      - --pruning
      - archive
      - --name 
      - 🍀clover-rpc-node
      - --port 
      - "30333"
      - --ws-port 
      - "9944"
      - --rpc-port 
      - "9933"
      - --rpc-cors=all
      - --ws-max-connections
      - "2000"
      - --ws-external 
      - --rpc-external
      - --execution
      - wasm
    ports:
      - "30333:30333"
      - "9933:9933"
      - "9944:9944"
    volumes:
      - /opt/data/clover:/opt/chaindata
```

{% hint style="info" %}
You can edit the `docker-compose.yaml` and include your customizations by updating below arguments:

* image: the docker image used to launch the node, for CLV Testnet, use `cloverio/clover-iris:0.1.15.` For a full list of clover networks please check out the [Clover Network List](broken://pages/-MYhDyMWo8dJUd4qGMdz) page.
* \--*name*:  The node name of your validator, the name could be found in the telemetry node list
* *--pruning*: we're using the `archive` mode for the pruning argument, which means it will keep all the historical block data. You can provide numeric parameters for it, to let it just keep the provided number of blocks data.
* *--ws-extenral/--rpc-external:* it enable the outer access for the RPC service.
* `Enabling --execution wasm` will spped up wasm code execution quite a lot, it's recommended for rpc nodes.
  {% endhint %}

## :rocket: Bring up the RPC node

Use below command to bring up the validator node:

```bash
cd /opt/compose # goto the compose file directory
docker-compose up # bring up the rpc node in the foreground
## check whether the node starts up normally
## Ctrl-C stop the node
docker-compose up -d # start the rpc node in the daemon mode.
```

You need to check the node logs using `docker-compose logs` command. Wait until the node is synced and the block numbers syncs with the latest number on the chain.

## :satellite: Post Setup

You may want to setup a reverse proxy server or load balancer for the RPC service. There're some known tools for you to start with, please checkout:

* [Nginx](https://www.nginx.com/) - High Performance Load Balancer, Web Server, & Reverse Proxy
* [Caddy](https://caddyserver.com/) -  Powerful, enterprise-ready, open source web server with automatic HTTPS written in Go
  {% endtab %}
  {% endtabs %}

## Docker Compose file templates

Below are several docker compose file templates for ClV networks.

{% tabs %}
{% tab title="CLV Mainnet (M-Chain)" %}

```yaml
version: "3.8"
services:
    clover-rpc:
        image: 'cloverio/clover-ivy:0.1.23'
        restart: always
        environment:
           ARGS: "--base-path /opt/chaindata --chain /opt/specs/clover-ivy.json --port 30333 --ws-port 9944 --rpc-port 9933 --pruning archive --name ivy-a-rpc4 --rpc-cors=all  --ws-max-connections 5000 --ws-external --rpc-external --wasm-execution compiled"
        ports:
           - "9933:9933"
           - "9944:9944"
           - "30333:30333"
           - "9615:9615"
        volumes:
          - /opt/data/chains/ivy:/opt/chaindata
          - /opt/data/config:/opt/config
```

{% endtab %}

{% tab title="CLV ParaChain (P-Chain)" %}

```yaml
version: "3.3"
services:
  clover-para-node:
    image: "cloverio/clover-para:polkadot-v0.9.16.1"
    restart: always
    command:
      - /opt/clover/bin/clover
      - --parachain-id
      - "2002"
      - --chain
      -  /opt/specs/clover-para-raw.json
      - --base-path
      - /opt/chaindata
      - --name
      - clover-para-rpc
      - --bootnodes
      - /dns/boot1.para.clover.finance/tcp/40335/ws/p2p/12D3KooWFWYYwimRBexvZokZmNnmSdXcLCz8WmMTHDCAhzm5tLM6
      - /dns/boot2.para.clover.finance/tcp/40335/ws/p2p/12D3KooWSvvxYi9nkyGJ17hEjwmytNRMrSsQtSrGsHzUaLTcUUea
      - --pruning # you can remove the pruning parameter if you don't need a full archive node
      - archive   #
      - --ws-port
      - "9946"
      - --rpc-port
      - "20194"
      - --port
      - "40335"
      - "--rpc-cors=all"
      - --rpc-external
      - --ws-external
      - --execution
      - wasm
      - --ws-max-connections
      - "5000"
      - --
      - --execution
      - wasm
      - --ws-port
      - "10194"
      - --rpc-port
      - "10195"
      - --chain
      - polkadot
      - --port
      - "30335"
    ports:
      - "9946:9946"
      - "20194:20194"
      - "40335:40335"
      - "30335:30335"
    volumes:
      - /data/data/chains/bootnode:/opt/chaindata
      - /data/data/config:/opt/config
    logging:
       driver: "json-file"
       options:
          max-size: "25m"
          max-file: "2"

```

{% endtab %}
{% endtabs %}


# Staking FAQ

### Is there a minimum amount to stake?

First, CLV P-Chain does not have staking feature, only CLV M-Chain has. &#x20;

The minimum amount to stake is dynamic. It can move up or down depending on the nominations and the election solutions. Nominators with a stake smaller than this amount may not currently be receiving staking rewards.

### What is the maximum number of delegators per candidate?

256

### What is the maximum number of delegations per account?

16

### How long is a period (ERA)?

About 6 hours

### What is the bond duration?&#x20;

Next ERA, which means the maximum is 6 hours

### What is the unbond duration?

24 Days

### How is the staking reward distributed?

It's distributed by ERA, anyone can make the claim at any time, while CLV will also claim for user once every day automatically. The reward will not be slashed.&#x20;


# 💰  Download CLV Wallet


# 📱  CLV Mobile Wallet

## **Getting Started**

### Download CLV Mobile Wallet

**Firstly:** do not download CLV Wallet from anywhere other than through the guideline on [official website (https://clv.org/)](https://clv.org/) appropriate to your device/OS. Cloned versions of CLV Wallet are out there that are programmed to record your Secret Recovery Phrase as soon as it's generated. To avoid falling victim to these scams, make sure you download the official CLV Wallet app through the guideline on[ ](https://clv.org/)[the official website (https://clv.org/)](https://clv.org/) , and not from any other source.&#x20;

#### IOS:&#x20;

1. Open the App Store and hit the search button in the bottom right. Input CLV Wallet into the search bar.
2. Either click 'Get' or tap on the name of the app to see more details. Complete the usual App Store download confirmation process.\
   ![](https://lh3.googleusercontent.com/RVxB6W4Gi-he-DulbkDl0UERZHznO6LNwibT5MZNKJvUdFNoRlBZBOh5bYGAjLhm2ysY1nV_8-4RS01OCYhCxD2m0JthqiN4pihkrJRpTkUjtzbEFv3izxM2A8XaUts8UOaA9bGvwiPZhcfhpcht8TUwipshxaPcVjxpMo5AWH1cxPus1K_RhVv-Akb67pvozcunyg)
3. Once installed, open the app and follow the prompts to create your wallet.&#x20;
4. Back up your Secret Recovery Phrase somewhere safe and offline!

#### Android:&#x20;

1. Visit <https://clv.org/?type=wallet>
2. Click the “Google Play”
3. On the pop-up, hit the “download” to install clover.apk, then follow the reminder to finish the whole process.

<figure><img src="https://lh5.googleusercontent.com/MJ8AOGujUWMGih5sKf36T-AgFthWnWCzOWkaVoFxaWeViZdnRbYBkL2WpK2vH6KviCspCi2ZaxKbhRQSC8hbK_Mzs9WZBSuwN9zxrqkDVucHpreFCNMUNfPqfw-2jZUcaJLvyRTmqi3zbBWjnLE7Q6xIJ__0R1tZzHFnTjxmsnjW7lnpAb9W6Szl7YnqYolh9eMrdQ" alt=""><figcaption></figcaption></figure>

### **Create a New Wallet**

1. Open "CLV Wallet" and choose "I don't have a wallet".
2. Set your login password (a minimum of 8 characters).
3. Swipe your finger across the blurred image to reveal your seed phrase.
4. Make sure to write down the seed phrases in the correct order without any spelling mistakes. *Note: It is* extremely important to never share your seed phrase with anyone else. If someone has the seed phrase, they can get your funds even without your password. The seed phrase is also used when you need to import or recover your wallet on a new device, so please keep it in a safe place.
5. To verify, enter the 12-word seed phrase in the correct order.
6. Click "Continue" to complete the process.

<figure><img src="/files/3hCuL0tXuorVehhEkjN2" alt=""><figcaption></figcaption></figure>

### **Import an Existing Wallet**

1. Open "CLV Wallet" and click on "l already have a wallet".
2. Set your login password (a minimum of 8 characters).
3. Type your "Seed Phrase" and set your login password. Note: Words separated by single spaces, and the password is a minimum 8 characters.
4. Click "Continue" to complete the process.

<figure><img src="/files/6k9Ln9ijlOWGNwPT2YLR" alt=""><figcaption></figcaption></figure>

### Reset my password

Please note that when resetting your wallet, any accounts (addresses) that do NOT ORIGINATE from your phrase will not be recovered afterwards. These imported accounts, either hardware wallet or imported via private key, are NOT INCLUDED under the Secret Recovery Phrase and will need to be re-added manually. Please be sure to verify that you have the private key details for any imported accounts before proceeding with the reset process.

When resetting your password for your CLV wallet, you will need your 12-word secret Recovery Phrase. If you do not already have your Secret Recovery Phrase saved someplace safe, please make sure to read How to Reveal Your Secret Recovery Phrase.

1. Click “Forgot password?”
2. Read through the contents and hit the “reset”&#x20;
3. Restart the process of importing wallet from create password page

!\[图形用户界面, 应用程序

描述已自动生成]\(<https://lh4.googleusercontent.com/sWCJSq-O6802fiAdPa3ExuaEE45zQfyrqigVi8trngQNNmwU-h6l9Ww-IJ5l__NEneh4cVnPP48_LyWl5L6_Yv4H-OjB-aF3t7MpgVozrl_AHR79ftfJJpQmFjeAaxqHdrkxaZAuVwHhpYUkvPewEz-UnocK-_nHFRJzut1Wdq90o5Vj2rNxI0tI5m9lS4nyCGrGSQ>)

### **Reveal my secret recovery phrase**

Firstly, DO NOT share this phrase with anyone! These words can be used to steal all your accounts. You can't edit or change your Secret Recovery Phrase.

If for some reason you forgot to record your 12-word Secret Recovery Phrase or you lost the original copy, as long as your CLV Wallet account is still unlocked, you can reveal your Seed Phrase / Secret Recovery Phrase, so you can back it up again.

1. Open the setting page and click “Wallet”
2. Click “…” and hit “reveal the seed phrase”
3. After inputting the password, you will see the seed phrase

<figure><img src="/files/fdPtI99kwYQwofuMLUwZ" alt=""><figcaption></figcaption></figure>

### **Log out or lock the wallet**

Open the settings page and click “Lock”

![](https://lh5.googleusercontent.com/_9QAlpvcgzTB30REIDReM1uyChrNKRCtraoI3arlq757JCfPSjlAAFIsukilcpXFQJUJjpK-24AjRnsBBNx0TzUlLRjEyuXsLEOAXFRi_T-pM99NxzZzpTV3HC5O8-RbJIJO_WLS9nSCGFhsjzQaxLppLuLDuHuqVZZeTpeUwp4N4x2zLkX_1v32hq04pypffwiVEg)

### **View and send NFTs in CLV wallet**

Currently, CLV Wallet only support ERC721 standard NFTs

1. Open the account page and hit the “Collectibles”
2. Hit one of the NFTs to see the details, click the send on the top-right to send the NFTs to the other addresses through CLV Wallet.
3. Send the NFT to the other addresses in the same Network<br>

<figure><img src="/files/dZSKUNeiZVAqAFsqFLrZ" alt=""><figcaption></figcaption></figure>

### Add a Whitelisted Token

1. To add a token, click the “add token” under the 'Tokens' tab on your homepage
2. Select the network listed in the left and switch on the tokens you want to add\
   !\[图形用户界面, 应用程序

   描述已自动生成]\(<https://lh5.googleusercontent.com/ybjf84hvFq3Pdg5aLn9ScBe4-JWT9TiflhTY615d_Q9WnK_H6evSITmMeUs0JwAOsK6KRvu9EcQFSzh7Mgiuny-U15Yr8Tacc0zMEg_gCo8qVfwVUhhN8jqgpMMR4iuo8tmKianJkgQ1C_XGmPhJWw4FjInIPF5SJzqXVRbUYLx9hMDnWWENNT2PQgLKVxlztKYg9w)![图形用户界面>, 应用程序

   描述已自动生成]\(<https://lh5.googleusercontent.com/75B1KIL6ON2rRQ6RHkd2u4gzkco01kBkHkfbgoRqxn0hc-TiVzZ-LIDix9yQQzZMZ8f8cswAErVeseD20a8HyXP9mV2Cu-Fh5LvYexiXNltUvpeqJQVnYG0H0voTA6IdPNlsdDnDb98wrIgRziGOOmjsulMAqHlDrtmdP1wysJbLSkFWUhFCfodiu40LeGrXEPYb9A>)

### **Add unlisted tokens (custom tokens)**

1. To add a custom token, click the “add token” under the 'Tokens' tab on your homepage.
2. Click “add custom token” in the top right
3. DYOR: choose the right network and fulfill the required data for the custom token<br>

<figure><img src="/files/KZ2SXDhbPzOvdE7snGZv" alt=""><figcaption></figcaption></figure>


# 🖥  CLV Extension Wallet

## **Getting Started**

### **Download CLV Extension Wallet**

1. Visit [Google Chrome CLV Wallet page](https://chrome.google.com/webstore/detail/clv-wallet/nhnkbkgjikgcigadomkphalanndcapjk)
2. Click “Add to Chrome”
3. On the pop-up, Hit “Add extension”

<figure><img src="https://lh3.googleusercontent.com/PACdFUmmPraZQY4LAs8F8UmcTyvobEZH81atxuebvSZIiLMifHoHno2G6_t7KwUpKBlzn7-iS0LLG2CFJb4fQvtyGmjPQCm0N2G5SJWWChekO8B5JKoVkfeYF042J0MXWJgPOzLS5OS_Em4HwcomUShI5Qsy524HfWYz8HPrp5sLr-d1C627AX2iL5UuWamN8MKLAw" alt=""><figcaption></figcaption></figure>

!\[图形用户界面, 文本, 应用程序

描述已自动生成]\(<https://lh5.googleusercontent.com/2g6QlFbsq_dt1fcbzWGvHoRQXuAiwn7ibhVj8VAqZt10hp4-DvRNPypDRsPF5XJ2GRgsnniRdUmNCN-mr9WfJVkQMBVYK_nj81keYeFU130MlMqu-XRCNAROHVMRVvjBrtnH32hubfbfhTStDRrU3mKZ5cLMTtSGAnx25eZilo__0Fmml5UUw7ZrvmPk3VzSTLUwJQ>)

### Create **a** New Wallet

1. Open the extension wallet and choose "I don't have a wallet".
2. Set your login password (a minimum of 10 characters).
3. Click on the blurred image to reveal your seed phrase.
4. Make sure to write down the seed phrases in the correct order without any spelling mistakes. *Note: It is* extremely important to never share your seed phrase with anyone else. If someone has the seed phrase, they can get your funds even without your password. The seed phrase is also used when you need to import or recover your wallet on a new device, so please keep it in a safe place.
5. To verify, enter the 12-word seed phrase in the correct order.
6. Click "Continue" to complete the process.

![](/files/NBzJTy2OxKbA5k1hIcab)

### **Import an Existing Wallet**

1. Open CLV extension wallet and click on "l already have a wallet".
2. Give a name to your wallet and set your login password.
3. Type your "Seed Phrase"  Note: Words separated by single spaces and the password is a minimum 8 characters.
4. Click "Continue" to complete the process.

<figure><img src="/files/y6ekGXGj9os37yybLAsG" alt=""><figcaption></figcaption></figure>

Note: If you open the "Advanced" option, you will find that CLV wallet supports two keypair types, SR25519 and ED25519, for substrate networks. CLV wallet uses SR25519 by default.

### **View Wallet Seed Phrase**

To check the seed phrase of your account, first click the setting button on the bottom navigation bar. Then click the 'Accounts' item, then select the Account's action button.

Please note that you may input your password in order to view your seed phrase.

<figure><img src="/files/P9uyaAIscLUCtRLd6xbe" alt=""><figcaption></figcaption></figure>

## Interacting with CLV Extension Wallet

### Add a Whitelisted Token

CLV Wallet supports 20+ major blockchains and supports a lot of on-chain assets, such as ERC20, BEP20, TRC20, etc. Users can use the "Add Token" button at the bottom of the main page to add their favorite tokens.

1. Click on the “add token” button under the 'Tokens' tab on your homepage.
2. Select the network listed in the left and switch on the tokens you want to add.

<figure><img src="/files/4WWqPRExNnM9qaA3mp3i" alt=""><figcaption></figcaption></figure>

You can search for token symbols and add them. For example, if you search **USDT**, you may find the following assets:

* Tether USD on Ethereum
* Compound Tether cUSDT on Ethereum
* Wrapped USDT on Solana
* ......

![](/files/MXiF6yQHitwALiiJ5tqE)

### **Add Custom Token**

* To add a custom token asset, you need to select the related blockchain network where your assets belong to. Then put the token contract address and click the 'Continue' to add that token to your asset list.

<figure><img src="/files/SzR9iE6imMqlO03z54dn" alt=""><figcaption></figcaption></figure>

### Send Token

1. To send tokens to another address, click the action button at the bottom of the asset detail page.&#x20;
2. Select "Send", choose your preferred asset <br>

   <figure><img src="/files/MMOByFraPxJHm5RStC1x" alt=""><figcaption></figcaption></figure>
3. Input the recipient's wallet address, then "Continue".
4. Input the amount you wish to send then select "Continue", then "Confirm" transaction on the next page. CLV charges a really low gas fee, typically a fraction of a cent.<br>

   <figure><img src="/files/pdIeqVEkY1IV8mxre7rd" alt=""><figcaption></figcaption></figure>

**More Options:** If you send EVM assets, you can customize the transaction fee

![](/files/7qQikhE9fgLIrHg7WjAY)

### **Switch between EVM Networks**

CLV wallet is capable of connecting to multiple blockchain networks simultaneously. Details are:

* CLV wallet connects to all non-EVM networks simultaneously, such as Polkadot, Solana, Tron, etc.
* For EVM networks, if dApp developers use the CLV Wallet dApp interaction protocol, then there is no need for their users to manually switch between EVM networks. Otherwise, users need to switch between them (please refer to the following step):

1. Click the Active dApp networks bar on the main page.
2. Click one EVM network you want to switch to. Note that only networks related to the tokens you add to the list will be displayed. Go to add token page and active more native tokens if you want to show more networks.

<figure><img src="/files/6gQV7jIpMxpdpiz6ckWt" alt=""><figcaption></figcaption></figure>

### **$CLV Cross-Chain Transaction**

CLV lets you make $CLV token cross-chain transactions between the Ethereum mainnet, the BNB Chain, CLV M-Chain, and CLV P-Chain (Parachain) with just a few clicks.

Please click the link below to learn details of the $CLV Cross-chain Transaction.

{% content-ref url="/pages/5pE0nVzeGA4YYorL9lNy" %}
[How to Get $CLV](/use-clv-chain/beginners-guide/how-to-get-usdclv)
{% endcontent-ref %}

###

### **General Cross-Chain Transaction**

The CLV wallet allows you to bridge assets from multiple mainnets of your choice using the swap/bridge feature. You can also perform direct swaps between assets.

* To bridge assets between chains, click the action button at the bottom of the asset detail page, then select "Bridge." Choose your preferred mainnets and corresponding tokens, then click "Approve."
* Note that Cross chain Fee is \~0.4% with a minimum for different assets. Time of CrossChainArrival is 10-30 min.

<figure><img src="/files/tXftJJTwC4v42LcKn8XJ" alt=""><figcaption></figcaption></figure>

### Fiat On-Ramp

The CLV wallet supports fiat on-ramp. This means you can buy your preferred assets with fiat currency directly from your CLV wallet without switching between various platforms. CLV makes it easy and secure to buy crypto assets via credit/debit card, Apple Pay, or bank transfer.

1. To perform a fiat on-ramp, click the action button at the bottom of the asset detail page, then select "Buy".
2. Choose a provider to continue, for instance, click "Buy with Wyre". Input the desired amount, then click "Next," enter your credit card information, and click "Submit."\ <br>

   <figure><img src="/files/kGSAbHgPsP2ncWz3VtuT" alt=""><figcaption></figcaption></figure>


# 🕸️  CLV Web Wallet

## What is CLV Web Wallet

CLV web wallet is the most secure decentralized web-based digital wallet. It has a lot of great features:

### 1. OAuth social logins without password

Usually, a crypto wallet needs users to provide a seed phrase or a private key to secure their crypto assets. This may lead to two risks:&#x20;

* Users may forget their seed phrase or private key, and they will never get back of their assets.
* Users may have their seed phrase or private key hacked, and they will permanently lose their assets.

CLV web wallet provides a OAuth social login mechanism, no passwords and no downloads.  Users can connect their wallet account by Google, Facebook, Twitter, etc. No more complicated seed phrases or private keys.&#x20;

CLV web wallet inherits traditional account recovery systems that allow users to recover their account via email/social login. And users don't need to worry about that if they lose access to their accounts.

### 2. Noncustodial Key Management

CLV web wallet never stores users' private key or seed phrase in cloud service.  All the credential info are accessible only by users. CLV web wallet is powered by decentralized noncustodial PKI infrastructure that is maintained by users themselves and IPFS with encryption.

### 3. Send and receive digital currencies via email

Using CLV web wallet, users don't need to remember the complicated addresses of their contacts. They can send and receive digital currencies via email.

### 4. Multichain support

CLV web wallet is multichain based. It supports most of the main blockchains, such as Ethereum, BSC, Polkadot, Kusama, Polygon, OKX chain, Fantom, etc.


# Getting Started

## Prerequisites

Developing a dApp requires you familiar with several tools. We'll use some tools in this tutorial but we assume you have at least basic knowledge with them.&#x20;

#### :tools: [Solidity](https://docs.soliditylang.org/en/v0.7.5/)

{% hint style="info" %}
Solidity is an object-oriented, high-level language for implementing smart contracts. Smart contracts are programs which govern the behavior of accounts within the CLV state.
{% endhint %}

&#x20;We'll use to solidity as the programming language to write on-chain logic.&#x20;

#### :pineapple: [Javascript](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Introduction)

{% hint style="info" %}
JavaScript is a cross-platform, object-oriented scripting language used to make webpages interactive (e.g., having complex animations, clickable buttons, popup menus, etc.). There are also more advanced server side versions of JavaScript such as Node.js, which allow you to add more functionality to a website than downloading files (such as realtime collaboration between multiple computers). Inside a host environment (for example, a web browser), JavaScript can be connected to the objects of its environment to provide programmatic control over them.
{% endhint %}

We'll implement the frontend UI logic using javascript.&#x20;

#### :watermelon: [Reactjs](https://reactjs.org/)

{% hint style="info" %}
React is a declarative, efficient, and flexible JavaScript library for building user interfaces. It lets you compose complex UIs from small and isolated pieces of code called “components”.&#x20;
{% endhint %}

## Setup environment

### Install required tools

We're going to develop DApp using truffle and react. So you need to have at least the following tools installed.

#### :tangerine: [Nodejs](https://nodejs.org)

Nodejs is the essential tool to develop both smart contract and create the front end app. Install the recent version of node would be enough, by writing this document, we're using v15.4.0.

{% hint style="info" %}
&#x20;Super-powers are granted randomly so please submit an issue if you're not happy with yours.
{% endhint %}

#### :tools: [Truffle](https://www.trufflesuite.com/truffle)&#x20;

Truffle is a world class development environment, testing framework and asset pipeline for blockchains using the Ethereum Virtual Machine (EVM), aiming to make life as a developer easier.&#x20;

{% hint style="info" %}
CLV provides fully compatible with Ethereum tools and we can use existing power tools like truffle, remix to develop smart contracts on CLV.
{% endhint %}

```bash
npm install truffle -g
```

#### :lemon: [Create-React-App](https://github.com/facebook/create-react-app)

{% hint style="info" %}
Create React App is an officially supported way to create single-page React applications. It offers a modern build setup with no configuration.
{% endhint %}

```bash
# No need to install create-react-app,
# just use 'npx create-react-app' to invoke it.
npx create-react-app
```

#### :rocket: CLV local node

We assume you start your CLV local node using below command, you might need to adjust some settings if you start CLV use a different command arguments.

```bash
./target/release/clover --dev --alice
```


# Using Local Node

This guide outlines steps to create a standalone local node to test CLV compatibility with Ethereum. Follow this guide and you will have a CLV node running in your local environment, which can be connected to the default Polkadot JS GUI.

## 1. Install build tools & libraries <a href="#docusaurus" id="docusaurus"></a>

CLV is the easiest to be set up on Unix-based operating systems like macOS or Linux. Here is the instruction on installing Rust's toolchains. If you have already done this, please go to the Step 3.

#### macOS

Open the Terminal application and execute the following commands:

```bash
# Install Homebrew if necessary https://brew.sh/
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install.sh)"

# Make sure Homebrew is up-to-date, install openssl and cmake
brew update
brew install openssl cmake
```

#### Ubuntu/Debian

Use a terminal shell to execute the following commands:

```bash
sudo apt update
# May prompt for location information
sudo apt install -y cmake pkg-config libssl-dev git build-essential clang libclang-dev curl
```

#### Arch Linux

Run these commands from a terminal:

```bash
pacman -Syu --needed --noconfirm cmake gcc openssl-1.0 pkgconf git clang
export OPENSSL_LIB_DIR="/usr/lib/openssl-1.0"
export OPENSSL_INCLUDE_DIR="/usr/include/openssl-1.0"
```

## 2. Install Rust toolchain

This guide uses [`rustup`](https://rustup.rs/) to help manage the Rust toolchain. First, install and configure `rustup`:

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

## 3. Compile the node

Let's start by cloning the master branch of the CLV repo that you can find here: <https://github.com/clover-network/clover>

```bash
git clone git@github.com:clover-network/clover.git
cd clover
```

Once you have followed all of the steps above, it's time to build the standalone node by running:

```bash
cargo build --release --features clover-testnet
```

{% hint style="info" %}
The initial build will take a while, depending on your hardware. It may take 30 minutes for the build process to complete.
{% endhint %}

## 4. Run the Node

Then you will want to run the node in dev mode using the following command:

```
./target/release/clover --dev --rpc-cors=all  --unsafe-rpc-external  --unsafe-ws-external --validator --tmp -lruntime=debug
```

You should see an output that looks like the following, showing that blocks are being produced:

![](/files/-MP3TbJbBsNdpWlNlJ7x)

{% hint style="info" %}
The local standalone CLV node provides two RPC endpoints:

* HTTP: `http://127.0.0.1:9933`
* WS: `ws://127.0.0.1:9944`
  {% endhint %}

### Connecting Polkadot JS Apps to a Local CLV Node <a href="#connecting-polkadot-js-apps-to-a-local-moonbeam-node" id="connecting-polkadot-js-apps-to-a-local-moonbeam-node"></a>

The locally-running CLV node is a Substrate-based node, so we can interact with it using standard Substrate tools. Let’s start by connecting it with CLV JS Apps.\
Visit <https://apps.clover.finance/#/explorer> and you will see Polkadot JS Apps and are automatically connected to the Polkadot MainNet.

![](/files/-MPhQ3KHsku_KwVkk6DW)

Click on the top left corner to open the menu and configure the networks, then navigate down to open the Development sub-menu. Select the "Local Node" option which points Polkadot JS Apps to `ws://127.0.0.1:9944`. Next, click on the Switch button and the site should be successfully connected to your standalone CLV node.

![](/files/-MPhQVOkybG95rpXZHiS)

With Polkadot JS Apps connected, you will see the standalone CLV node producing blocks.

![](/files/-MPhQzxWO4uq6i7IgAFA)


# Using MetaMask

Interacting with a CLV Node Using MetaMask

## Using Metamask for Local Node

This guide will show you how to use MetaMask wallet connecting to a self-run CLV standalone node, and sending tokens between accounts. There are two ways to interact with CLV: using Substrate RPC endpoints, or by using Web3-compatible RPC endpoints, which is served from the same Substrate RPC RPC server. In this tutorial, we will use Web3 RPC endpoints.

### Installing MetaMask Chrome Extension <a href="#install-the-metamask-extension" id="install-the-metamask-extension"></a>

First of all, install the [MetaMask](https://metamask.io/) Extension from the Chrome Store. After installation is done, follow the "Get Started" guide to create a wallet, set a password, and keep your secret backup phrases in a secure place.&#x20;

Now import the development account:

![](/files/-MPs8nDQMHP9nZvum-c5)

The information for the pre-funded development account for standalone build are:

* Private key: `0xa504b64992e478a6846670237a68ad89b6e42e90de0490273e28e74f084c03c8`
* Public address: `0xe6206C7f064c7d77C6d8e3eD8601c9AA435419cE`

Select “Private Key” and paste the key on the "Import" page, then click the "import" button.

![](/files/-MPsCc_XMSRWJIob261c)

You will see an imported “Account 2” looks like this:

![](/files/-MPsCzs9aHXPJAaH3R7o)

### Connecting to the Local CLV Node <a href="#connect-to-the-local-moonbeam-node" id="connect-to-the-local-moonbeam-node"></a>

Now connect MetaMask to your locally running CLV node. It should be producing blocks now:

![](/files/-MP3TbJbBsNdpWlNlJ7x)

Back to MetaMask, navigate to Settings -> Networks -> Add Network. Fill in the following Contents:

* Network Name: `CLV Dev`
* New RPC URL: `http://127.0.0.1:9933`
* ChainID: `1023`
* Symbol (Optional): `CLV`

![](/files/-MPsEone1JIpohkC6C7Q)

When done, click on the "save" button. MetaMask should be connected to the local CLV standalone node via its Web3 RPC. Now you should see the CLV dev account with a balance of 10,000,000 CLV.

![](/files/-MPsFQh5At5aGpY2OTNc)

### Initiating a Transfer <a href="#initiating-a-transfer" id="initiating-a-transfer"></a>

Now we can try sending tokens with MetaMask. Let's transfer from this dev account to the account we just created while setting up MetaMask, so that we can simply use the “Transfer between my accounts” option.&#x20;

First let’s send 100 tokens. Input an amount of 100 ETH and leave all other settings as default.&#x20;

Note that the token name may be changed to ETH when you re-login,  which is OK for the development purpose.

![](/files/-MPsJJbXo2WRmRtRFrBT)

Then Click the "Confirm" button to confirm the transaction:

![](/files/-MPsKUUaf2GBLIM_7-P4)

Once done, you will see the status as “pending” until it is confirmed after a short period.

![](/files/-MPsKfh8Sm23xb7DD139)

The Account 2 balance should now have been decreased by the amount sent plus a gas fee. When switch to Account 1, you should see the 100 tokens has arrived:

![](/files/-MPsKmwPBDwy1ynQz6UK)


# Using Remix

Interacting Remix with CLV

This guide shows how to create and deploy a Solidity-based smart contract to a CLV standalone node using the [Remix IDE](https://remix.ethereum.org/).&#x20;

Remix is one of the most popular Solidity IDE used to write, compile and debug Solidity code. With CLV Ethereum compatibility features, Remix can be used directly with a CLV node.

This guide assumes that you have a running local CLV node running in `--dev` mode, and that you have a [MetaMask](https://metamask.io/) installation configured to use this local node. If you don't know how to do it, you can find instructions for running a local CLV node [here](https://clover-network.gitbook.io/portal/quick-start/local-node/setting-up-a-node) and to connect MetaMask to it [here](https://clover-network.gitbook.io/portal/quick-start/local-node/using-metamask).

### Checking Prerequisites <a href="#checking-prerequisites" id="checking-prerequisites"></a>

We assume you have followed the guides above, and have a local CLV node producing blocks. It should look like this:

![](/files/-MP3TbJbBsNdpWlNlJ7x)

And you should have installed MetaMask connected to your local CLV dev node. You should have at least one account that has a balance. It should look like this (expanded view):

![](/files/-MPsKmwPBDwy1ynQz6UK)

### Getting Started with Remix <a href="#getting-started-with-remix" id="getting-started-with-remix"></a>

Now that we can start with Remix to exercise some advanced functionalities in CLV.

To launch Remix, you need to navigate to <https://remix.ethereum.org/>. In the main screen, select Solidity to configure Remix for Solidity development, then navigate to the File Explorers view:

![](/files/-MQ506NHF-haXE7eIq2E)

Now we can create a new file to save the Solidity smart contract. Click the "+" button under "File Explorers" at the top left. Give it a name "MyToken.sol" in the popup box.

![](/files/-MQ52y-DHv7PyKLxzOz2)

Now paste the following smart contract code into the editor tab on the right side:

```go
// SPDX-License-Identifier: MIT
pragma solidity ^0.6.2;

import "https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v3.3.0/contracts/token/ERC20/ERC20.sol";

contract Token is ERC20 {

    constructor (uint256 initialSupply) public ERC20("MyToken", "ABC") {
        _mint(msg.sender, initialSupply);
    }
}
```

This is a simple ERC-20 contract based on the current Open Zeppelin ERC-20 template. It creates MyToken with symbol ABC and mints the entirety of the initial supply to the creator of the contract.

Now the editor should look like this:

![](/files/-MQ541fXoDDpYddS98Kh)

Now navigate to the compile sidebar option first and then click the “Compile MyToken.sol” button at the bottom left:

![](/files/-MQ54rHKT-3Wb0swQj5f)

You will see Remix download all of the Open Zeppelin dependencies and compile the contract.

### Deploying a Contract to CLV Using Remix <a href="#deploying-a-contract-to-moonbeam-using-remix" id="deploying-a-contract-to-moonbeam-using-remix"></a>

To deploy the contract, you need to navigate to the Deployment sidebar option on the left. Change the topmost “Environment” dropdown from “JavaScript VM” to “Injected Web3”. Thus you can use the MetaMask injected provider, which will point it to your CLV standalone node.&#x20;

Note that you should allow Remix to access your MetaMask account after selecting "Injected Web3", by clicking the "Next" and then the "Connect" button.

![](/files/-MQ5BJk5KUG8UlEelkbQ)

Now you should see the account in metamask showing up on the Remix side, ready for deployment. Let’s specify an initial supply of 5M tokens in the box next to the Deploy button. Since this contract uses *the* default of 18 decimals, the value is `5000000000000000000000000`. &#x20;

![](/files/-MQ5AI87QhzwSz0W2Isd)

Then, click the Deploy button. You will need to confirm the contract deployment transaction in Metamask.

![](/files/-MQ5BoWF4QeAFluDqnN5)

After the deployment is complete, you will see the transaction record listed in MetaMask. Also, the contract will appear under Deployed Contracts in Remix.

![](/files/-MQ5CQwOKbRf3StB06t3)

After the contract is deployed, you can interact with it from within Remix.

Now you can try clicking on name, symbol, and totalSupply. There should return “MyToken,” “ABC,” and “5000000000000000000000000” respectively. If you copy the address and paste it into the balanceOf field, you should see the entirety of the balance of the ERC20 as belonging to that user.&#x20;

![](/files/-MQ5D_wEEuHdViz1yNu9)

### Interacting with a CLV-based ERC-20 from MetaMask <a href="#interacting-with-a-moonbeam-based-erc-20-from-metamask" id="interacting-with-a-moonbeam-based-erc-20-from-metamask"></a>

To add the newly deployed ERC-20 tokens, you need to copy the contract's address from Remix first. Then back in MetaMask, click on “Add Token” as shown below. Make sure you are in the account that deployed the token contract.

![](/files/-MQ5E5OnTuHYfBnju_68)

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

![](/files/-MQ5EUB0hUwQHzgGJYUO)

Then click the “Next” and then the “Add Tokens” button, you should see a balance of 5M MyTokens in MetaMask:

![](/files/-MQ5Ekz_gpBran9nl6se)

Now we can send some of these ERC-20 tokens to the other account. Hit “send” to initiate the transfer of 500 MyTokens. Select the destination account and hit “next,” you will be asked to confirm this transaction as shown below.

![](/files/-MQ5FJhgB9Pu3lCu22_8)

Click “Confirm” to send. After the transaction is complete, you will see a confirmation and a reduction of the account balance from the sender account in MetaMask:

![](/files/-MQ5Fcb9_vcbnxMlrji-)

If you own the account which you send to, you can check the account balance to verify that the transaction has been successfully.


# Using Web3.js

Using Web3.js to interact with CLV

## Introduction <a href="#introduction" id="introduction"></a>

This guide walks through the process of using [web3.js](https://github.com/ethereum/web3.js/) to manually sign and send a transaction to a CLV standalone node. For this example, we will use Node.js and straightforward JavaScript code.

The guide assumes that you have a local CLV node running in `--dev` mode. You can find instructions to set up a local CLV node [here](https://clover-network.gitbook.io/portal/quick-start/local-node/setting-up-a-node).

## Prerequisites <a href="#checking-prerequisites" id="checking-prerequisites"></a>

#### 1. Start CLV node

Start your standalone CLV node, which can successfully produce blocks in your local environment.

#### 2. Install Node.js and NPM

To install Node.js (we'll go for v12.x, you can choose other versions, such as the latest version v15.x)  and NPM package manager. You can do this by running the following commands in your terminal:

For Mac users:

```
brew update
brew install node
```

For Debian users:

```
curl -sL https://deb.nodesource.com/setup_12.x | sudo bash -
sudo apt-get install -y nodejs
```

For Centos/Redhat users:

```
curl -sL https://deb.nodesource.com/setup_12.x | sudo bash -
sudo yum install nodejs
```

We can verify that everything installed correctly by querying the version for each package:

```
node -v
npm -v
```

#### 3. Create your Node.js project

You can create a repository on your local environment by running:

```
mkdir clover-web3 && cd clover-web3/
npm init --yes
npm install web3 --save
```

## Query Balance

We can easily do this by leveraging the Ethereum compatibility features of CLV.

First let's create a file *balance.js* under the project we've created. Here we just query the balance of the genesis account, and the genesis account is endowed with **10,000,000** ETH by your local CLV node under the development mode. To get the balances of the account, we need to make an asynchronous function that uses the `web3.eth.getBalance(address)` command. We can take advantage of the `web3.utils.fromWei()` function to transform the balance into a more readable number in ETH.

The file looks like this:

```typescript
const Web3 = require('web3')

const web3 = new Web3(new Web3.providers.HttpProvider('http://localhost:9933'));
const GENESIS_ACCOUNT = '0xe6206C7f064c7d77C6d8e3eD8601c9AA435419cE';

async function getBalance(account) {
  const balance = await web3.eth.getBalance(account);
  const balanceOfEther = web3.utils.fromWei(balance, "ether");
  console.log(`${account} has balance: ${balanceOfEther} ETH`);
}

getBalance(GENESIS_ACCOUNT);
```

#### Running the Script

You can run the above script using command :

```
node balance.js
```

The output of the execution is as following:

![](/files/-MPsATkYN08OpGK5Xc1S)

## Send Transaction

For our example, we only need a single JavaScript file (arbitrarily named *transaction.js*) to create and send the transaction, which we will run using the `node` command in the terminal. The script will transfer 100 CLV from the genesis account to another address. For simplicity, the file is divided into three sections: variable definition, create transaction, and send transaction.

We need to set a couple of values in the variable definitions, then construct and sign the transaction:

1. Create your Web3 constructor (`Web3`).
2. Specify the received address, CLV amount, gas price and gas limit.
3. Sign the transaction and broadcast it the CLV chain

The code looks like:

```javascript
const Web3 = require('web3')

const web3 = new Web3(new Web3.providers.HttpProvider('http://localhost:9933'));
const GENESIS_ACCOUNT = '0xe6206C7f064c7d77C6d8e3eD8601c9AA435419cE';

async function webTransfer(account, etherValue) {
  try {
    const before = await web3.eth.getBalance(account);
    console.log(`before transfer: ${account}, has balance ${web3.utils.fromWei(before, "ether")}`);

    const nonce = await web3.eth.getTransactionCount(GENESIS_ACCOUNT);
    const signedTransaction = await web3.eth.accounts.signTransaction({
      from: GENESIS_ACCOUNT,
      to: account,
      value: web3.utils.toWei(etherValue.toString(), "ether"),
      gasPrice: web3.utils.toWei("100", "gwei"),
      gas: "0x5208",
      nonce: nonce
    }, 'your private key configured somewhere');
    await web3.eth.sendSignedTransaction(signedTransaction.rawTransaction);
    const after = await web3.eth.getBalance(account);
    console.log(`after transfer: ${account}, has balance ${web3.utils.fromWei(after, "ether")}`);
    return { success: true };
  } catch (e) {
    return { success: false, message: e.toString() };
  }
}

webTransfer('0x1874FC5f915aa9Fd24C379fE7F9ec40607CEf78A', 100).then(console.log)
```

#### Running the Script

You can run the above script using command :

```
node transaction.js
```


# Using Testnet

This section shows how to connect to CLV TestNet using MetaMask or Remix

## CLV Test Net

Please refer to the following details for CLV TestNet:

* Network Name: `CLV TestNet`
* RPC URL:&#x20;
  * `https://rpc.clover.finance`&#x20;
  * `https://rpc-2.clover.finance`&#x20;
  * `https://rpc-3.clover.finance`
* Web Socket URL:
  * `wss://api.clover.finance`
  * `wss://api-2.clover.finance`
  * `wss://api-3.clover.finance`
* ChainID: `1023`
* Symbol (Optional): `CLV`

{% hint style="info" %}
For a full list of CLV networks please check out the [Clover Network List](/use-clv-chain/network-details) page.
{% endhint %}

## Using MetaMask for TestNet

In MetaMask, navigate to Settings -> Networks -> Add Network and fill in the above details:

![](/files/-MQKiQoZejd7CwSWvoB2)

Then the MetaMask can connect to CLV TestNet. You can apply CLV for test via the faucet <https://faucet-iris.clover.finance/>

## Using Remix for Test Net

Make sure your MetaMask is connected to CLV TestNet as described above.  The screenshot is as follows:

![](/files/-MQKy6yTmCfK4rGR3CkE)

## Connect to CLV TestNet

If you want to set up a local node, which can connect to CLV TestNet, please use the following command to start your local node:

```bash
./target/release/clover --chain specs/clover-preview-iris.json \
    --port 30333 --ws-port 9944 --rpc-port 9933  \
    --name myNode --rpc-cors=all --rpc-methods=Unsafe \
    --validator --unsafe-ws-external --unsafe-rpc-external \
    --execution wasm
```


# Create an account

Firstly, open [CLV Apps portal](https://apps.clover.finance/#/explorer) and select the "CLV" node in the network list in the left side navigation bar.

![](/files/-MRsVR295QguK0xoHi2T)

## Generate an account using CLV Apps

#### Click the "Accounts" menu item in the top navigation bar.

![](/files/-MRsVUX3VPZNbA-1nL-3)

#### New Account

There're several buttons to add an account: "Add account", "Restore JSON", "Add via Qr", etc.

![](/files/-MRsWCZGP3kVe4F0smxm)

Click "Add account" to create a new account.

![](/files/-MRsWH71Y4MaRdEDTNo5)

After setting the account information click the **"Next"** button.

![](/files/-MRsWVm_RHN2vkpu_3L6)

Click the **"Save"** button, the account will be created and the backup file will be promoted to download. Save the backup file to a safe location and keep it secret.

#### Restore account from backup

You can restore an account by restoring it from the json backup file.

Click **"Restore JSON"** button

![](/files/-MRsXWcOM0JVmD9rSNVs)

Select your backup json file and fill the password of the json file then click the "**Restore**" Button. The account will be restored to the account list.


# Faucet

Using CLV Faucet to get CLV for testing

Open your browser, and navigate to <https://faucet-iris.clover.finance/> . Click the **Twitter** link to compose a tweet with your CLV address (can be EVM format address or Polkadot format address), Paste your Twitter link and acquire CLV, the screenshot is as follows:

![](/files/-MVzupbVhObiqFXxpILS)


# Run a Testnet Node

If you're building dapps or products on a Substrate-based chain like CLV or a custom Substrate implementation, you probably want the ability to run a node-as-a-back-end. After all, it's always better to rely on your own infrastructure than on a third-party-hosted one in this brave new decentralized world.

This guide will show you how to connect to CLV network, but the same process applies to any other [Substrate](https://substrate.dev/docs/en/)-based chain. First, let's clarify the term *full node*.

### Using Docker and Docker Compose

Make sure you have docker and docker-compose installed using below command:

```bash
curl -fsSL https://get.docker.com -o get-docker.sh
sh get-docker.sh
```

To run a CLV full node, create a `docker-compose.yaml` file with below content:

```yaml
version: "3.8"
services:
  clover-node:
    image: "cloverio/clover-iris:0.1.15"
    restart: always
    environment:
        ARGS: "--base-path /opt/chaindata --chain /opt/specs/clover-preview-iris.json --port 30333 --ws-port 9944 --rpc-port 9933 --name "clover-node" --rpc-cors=all --validator --unsafe-ws-external --unsafe-rpc-external --rpc-methods=Unsafe"
    ports:
      - "9933:9933"
      - "9944:9944"
      - "30333:30333"
      - "9615:9615"
    volumes:
      - /opt/data/dev:/opt/chaindata
```

You're free to edit the name of this node in the ARGS field.&#x20;

Now launch the node with below command:

```bash
docker-compose up -d 
```

You should get CLV node runs and syncing data from the test net now. You can monitor the logs with:

```bash
docker-compose logs -f --tail 10 clover-node
```

## Get Substrate

Follow instructions as outlined [here](https://substrate.dev/docs/en/knowledgebase/getting-started) - note that Windows users will have their work cut out for them. It's better to use a virtual machine instead.

Test if the installation was successful by running `cargo --version`.

```
λ cargo --version
cargo 1.41.0 (626f0f40e 2019-12-03)
```

## Clone and Build

The [clover-network/clover](https://github.com/clover-network/clover) repo's master branch contains the latest CLV code.

```
git clone https://github.com/clover-network/clover
cd clover
./scripts/init.sh
cargo build --release
```

Alternatively, if you wish to use a specific release, you can check out a specific tag (`v0.8.3` in the example below):

```
git clone https://github.com/clover-network/clover
cd clover
git checkout tags/v0.8.3
./scripts/init.sh
cargo build --release
```

## Run

The built binary will be in the `target/release` folder, called clover.

```
./target/release/clover --name "My node's name" --chain specs/clover-cc1-raw.json
```

Use the `--help` flag to find out which flags you can use when running the node. For example, if [connecting to your node remotely](https://app.gitbook.com/@clover-network/s/portal/maintain/nodes-and-dapps/set-up-secure-websocket-for-remote-connections/@drafts), you'll probably want to use `--ws-external` and `--rpc-cors all`.

The syncing process will take a while depending on your bandwidth, processing power, disk speed and RAM. On a $10 DigitalOcean droplet, the process can complete in some 36 hours.

Congratulations, you're now syncing with Clover. Keep in mind that the process is identical when using any other Substrate chain.

## Running an Archive Node

When running as a simple sync node (above), only the state of the past 256 blocks will be kept. When validating, it defaults to archive mode. To keep the full state use the `--pruning` flag:

```
./target/release/clover --name "My node's name" --pruning archive
```

It is possible to almost quadruple synchronization speed by using an additional flag: `--wasm-execution Compiled`. Note that this uses much more CPU and RAM, so it should be turned off after the node is in sync.

## Using Docker

Finally, you can use Docker to run your node in a container. Doing this is a bit more advanced so it's best left up to those that either already have familiarity with docker, or have completed the other set-up instructions in this guide. If you would like to connect to your node's WebSockets ensure that you run you node with the `--rpc-external` and `--ws-external` commands.

```
docker run -p 9944:9944 clover-network/clover-iris:0.1.15 --name "calling_home_from_a_docker_container" --rpc-external --ws-external
```


# Connect to Testnet

Please refer to the following details for CLV TestNet:

* Network Name: `CLV TestNet`
* RPC URL:&#x20;
  * `https://rpc.clover.finance`&#x20;
  * `https://rpc-2.clover.finance`&#x20;
  * `https://rpc-3.clover.finance`
* Web Socket URL:
  * `wss://api.clover.finance`
  * `wss://api-2.clover.finance`
  * `wss://api-3.clover.finance`
* ChainID: `1023`
* Symbol (Optional): `CLV`

## Using MetaMask for TestNet

In MetaMask, navigate to Settings -> Networks -> Add Network and fill in the above details:

![](/files/-MQKiQoZejd7CwSWvoB2)

Then the MetaMask can connect to CLV TestNet. You can apply CLV for test via the faucet <http://faucet.clovernode.com/>

## Using Remix for TestNet

Make sure your MetaMask is connected to CLV TestNet as described above.  The screenshot is as follows:

![](/files/-MQKy6yTmCfK4rGR3CkE)

##


# dApp Example

In this tutorial we'll start from building a simple Counter DApp.

It's a very simple DApp, which has one state variable "counter" and a function to write the state. We'll build a web application to interact with the Counter smart contract.

The source code of this tutorial could be found at: <https://github.com/clover-network/example-counter-dapp> .


# Setup dApp project

## :corn: Create a project using create-react-app

Let's start with creating a frontend project using create-react-app.&#x20;

```
npx create-react-app counter-dapp
```

{% hint style="info" %}
&#x20;This command takes a little while to complete, be pertinent. You need to confirm the installation of create-react-app if it's your first time using this command.
{% endhint %}

Once the command complete, start the web app:

```bash
cd counter-dapp
yarn start
```

{% hint style="info" %}
A browser window will be opened and who the web app. You can visit <http://localhost:3000/> either.&#x20;
{% endhint %}

## :tools: Add counter state and buttons

We'll add a simple text to show the current value of the counter state.

"Inc" and "Dec" buttons to update the counter state.&#x20;

Edit `src/App.js` and set the `App()` function looks like below:

```jsx
function App() {
  return (
    <div className="App">
      <header className="App-header">
        <h1>Counter Example</h1>
        <p>
            Current value: n/a
        </p>
        <button className="CounterButton">Inc Counter</button>
        <button className="CounterButton">Dec Counter</button>
      </header>
    </div>
  );
}
```

Edit `src/App.css` and add the css class `CounterButton`. You can make your customizations as you like.

```css
.CounterButton {
  background-color: #4CAF50;
  border: none;
  color: white;
  margin-top: 15px;
  padding: 15px 32px;
  text-align: center;
  text-decoration: none;
  display: inline-block;
  font-size: 16px;
  width: 200px;
}
```

The webpage will be reloaded after you saved the files.

Now you can see we're having the basic page layout!

{% hint style="info" %}
The source code of this chapter could be found at the revision `fdb1b9e5f` in the [`counter-dapp`](https://github.com/clover-network/example-counter-dapp) source repo.
{% endhint %}


# Setup truffle

## :pencil: Truffle config

create and edit `truffle-config.js`:

{% code title="truffle-config.js" %}

```javascript
module.exports = {
  contracts_build_directory: "./src/contract_build",
  compilers: {
    solc: {
      version: '0.5.2'
    }
  },
};
```

{% endcode %}

We specified to use `solc` version `0.5.2` as the contract compiler and we set the contract build directory to `./src/contract_build` because the default build directory is `./build` which conflicts with react application build folder. Another reason is later on we'll use react to load the `Counter.json` from the build directory which must be located inside the `src` directory.

## :red\_car: Test out

You can check if it's setup correctly by running `truffle compile`

```bash
truffle compile
```

The command will success and print something like:

```bash
Compiling your contracts...
===========================
> Everything is up to date, there is nothing to compile.
```

{% hint style="info" %}
truffle compile will check the contracts which needs compile to evm byte code. Truffle thinks everything is update to date since we're not having any smart contract in this project.
{% endhint %}


# The Counter Contract

## :pencil: The Code

Smart contracts are put at the contracts folder. Create the contract folder using:

```bash
mkdir contracts
```

{% hint style="info" %}
Placing smart contracts in the contracts folder is a convention of truffle. You can specify a different directory by modifying truffle configuration. Checkout the [conracts\_directory](https://www.trufflesuite.com/docs/truffle/reference/configuration#contracts_directory) section in truffles document.
{% endhint %}

Once created the contracts folder , create the `Counter.sol` file with contents below:

{% code title="Counter.sol" %}

```bash
pragma solidity >=0.5.0 <0.7.0;

contract Counter {
  uint32 public current_value;

  function inc() public {
    require(current_value < 10000, "Counter: max value");
    current_value = current_value + 1;
  }

  function dec() public {
    require(current_value > 0, "Counter: min value");
    current_value = current_value - 1;
  }
}
```

{% endcode %}

## :star2: Explain

The contract code is quite self explain:&#x20;

* A state variable `current_value` which is an unsigned integer.&#x20;
* inc() method, which increase the current\_value by one.&#x20;
* dec() method, which decrease the current\_value by one.
* current\_value has a bound of \[0, 10000] which was checked in inc and dec methods.

## :red\_car: Test out

Run command `truffle compile`, it will find and compiles the Counter contract. you should looks outputs like:

```bash
Compiling your contracts...
===========================
> Compiling ./contracts/Counter.sol
> Artifacts written to ~/counter-dapp/build/contracts
> Compiled successfully using:
   - solc: 0.5.2+commit.1df8f40c.Emscripten.clang
```

{% hint style="info" %}
Truffle command will download solidity compiler at the first time. There could be some messages related to the compiler setup. It's normal.
{% endhint %}

&#x20;


# Deploy Contract

## Start CLV dev node

Now we will deploy the Counter smart contract to our CLV local dev node.&#x20;

First make sure CLV is started using below command:

```bash
./clover --dev --alice
```

{% hint style="info" %}
&#x20;In the following steps we assume you're using the local CLV node. You may need to adjust some parameters if you're connecting to other CLV nodes.
{% endhint %}

Once CLV is started, you could see it's producing blocks every 6 seconds.&#x20;

{% code title="hello.sh" %}

```bash
# Ain't no code for that yet, sorry
echo 'You got to trust me on this, I saved the world'
```

{% endcode %}

{% hint style="warning" %}
Sometimes the local node stop producing blocks and reports the error "unexpected era change", it normally happens in dev node. To fix this problem, the simplest method is purge the chain using below command and start over.
{% endhint %}

```bash
./clover purge-chain --dev --alice
```

## Setup the private key provider

We need to access our local node using the key keys preimported in the dev chain. We need setup a custom private key provider for truffle. Install required packages using:

```bash
$ yarn add web3-provider-engine ethereumjs-wallet
```

Create `private-provider.js` and set the content as below:

```javascript
const ProviderEngine = require("web3-provider-engine");
const WalletSubprovider = require('web3-provider-engine/subproviders/wallet');
const RpcSubprovider = require('web3-provider-engine/subproviders/rpc');
const EthereumjsWallet = require('ethereumjs-wallet');



function ChainIdSubProvider(chainId) {
  this.chainId = chainId;
}

ChainIdSubProvider.prototype.setEngine = function (engine) {
  const self = this
  if (self.engine) return
  self.engine = engine
}
ChainIdSubProvider.prototype.handleRequest = function (payload, next, end) {
  if (payload.method == "eth_sendTransaction" && payload.params.length > 0 && typeof payload.params[0].chainId == "undefined") {
    payload.params[0].chainId = this.chainId;
  }
  next()
}


function NonceSubProvider() {
}

NonceSubProvider.prototype.setEngine = function (engine) {
  const self = this
  if (self.engine) return
  self.engine = engine
}
NonceSubProvider.prototype.handleRequest = function (payload, next, end) {
  if (payload.method == "eth_sendTransaction") {
    this.engine.sendAsync({
      jsonrpc: "2.0",
      id: Math.ceil(Math.random() * 4415011859092441),
      method: "eth_getTransactionCount",
      params: [payload.params[0].from, "latest"]
    }, (err, result) => {
      const nonce = typeof result.result == "string" ?
        result.result == "0x" ? 0 : parseInt(result.result.substring(2), 16) : 0;
      payload.params[0].nonce = '0x' + (nonce || 0);
      next();
    })
  } else {
    next()
  }
}

function PrivateKeyProvider(privateKey, providerUrl, chainId) {
  if (!privateKey) {
    throw new Error(`Private Key missing, non-empty string expected, got "${privateKey}"`);
  }

  if (!providerUrl) {
    throw new Error(`Provider URL missing, non-empty string expected, got "${providerUrl}"`);
  }

  this.wallet = EthereumjsWallet.default.fromPrivateKey(new Buffer(privateKey, "hex"));
  this.address = "0x" + this.wallet.getAddress().toString("hex");

  this.engine = new ProviderEngine({ useSkipCache: false });

  this.engine.addProvider(new ChainIdSubProvider(chainId));
  this.engine.addProvider(new NonceSubProvider());
  this.engine.addProvider(new WalletSubprovider(this.wallet, {}));
  this.engine.addProvider(new RpcSubprovider({ rpcUrl: providerUrl }));

  this.engine.start();

}


PrivateKeyProvider.prototype.sendAsync = function (payload, callback) {
  return this.engine.sendAsync.apply(this.engine, arguments);
};

PrivateKeyProvider.prototype.send = function () {
  return this.engine.send.apply(this.engine, arguments);
};

module.exports = PrivateKeyProvider;
```

Edit the `truffle-config.js` and set it to below:

```javascript
const pkProvider = require('./private-provider')

const privateKey = '03183f27e9d78698a05c24eb6732630eb17725fcf2b53ee3a6a635d6ff139680'

module.exports = {
  contracts_build_directory: "./src/contract_build",
  compilers: {
    solc: {
      version: '0.5.2'
    }
  },
  networks: {
    development: {
      provider: () => new pkProvider(privateKey, `http://127.0.0.1:9933`, 1337),
      network_id: 1337,
      gas: 55000000,
      gasPrice: 10_000_000_000,
      confirmations: 2,
      timeoutBlocks: 200,
      skipDryRun: true,
    },
  },
};
```

Here we imported the `private-provider` package and added the network section in the configuration. We defined the `development` network by using the `pkProvider` which uses the private key  and connects to the local clover rpc port.&#x20;

The private key is defined in the dev chain and has enough CLV for testing. It's important to use the `private-provider.js` here because we need add some customization to make truffle pass the correct information to the clover chain.

Clover node uses the `1337` network id and it supports a higher gas limit.  We specified the gas price in the configuration. because clover limits the gas price to be at least `1 gwei` . &#x20;

## Write the migration

Migrations are used to do stuff like contract migration and initialization scripts. We'll just write a simple migration to deploy the Counter contract.&#x20;

First create the `migrations` folder

```javascript
$ mkdir migrations
```

Add the `1_deploy_counter.js` file, set the content to:

```javascript
const CounterContract = artifacts.require("Counter");

module.exports = async function(deployer, network) {
  await deployer.deploy(CounterContract)
}
```

We wrote a standard truffle migration which load the `Counter` contract and deploy it to the chain in the migration function. Checkout [truffle migration document](https://www.trufflesuite.com/docs/truffle/getting-started/running-migrations) for more details.

## Deploy the counter contract

It's time to deploy counter using below command!

```javascript
$ truffle deploy --network development
```

You should get some output as below:

```javascript
truffle deploy --network development

Compiling your contracts...
===========================
> Everything is up to date, there is nothing to compile.



Starting migrations...
======================
> Network name:    'development'
> Network id:      1337
> Block gas limit: 0 (0x0)


1_deploy_counter.js
===================

   Deploying 'Counter'
   -------------------
   > transaction hash:    0x18eacdeebbd40fec104a3de505e9c1065c89b21ff68664b722834cea9a6f0ea9
   > Blocks: 0            Seconds: 0
   > contract address:    0xeB1c50679f8fe33542C44a4A6D779Fb47886E27f
   > block number:        5
   > block timestamp:     1609225848
   > account:             0xAEd40f2261ba43b4dFFE484265ce82D8fFE2B4DB
   > balance:             9999999.99813969
   > gas used:            186031 (0x2d6af)
   > gas price:           10 gwei
   > value sent:          0 ETH
   > total cost:          0.00186031 ETH

   Pausing for 2 confirmations...
   ------------------------------
   > confirmation number: 1 (block: 6)
   > confirmation number: 2 (block: 7)
   > Saving artifacts
   -------------------------------------
   > Total cost:          0.00186031 ETH


Summary
=======
> Total deployments:   1
> Final cost:          0.00186031 ETH
```

It says that the counter contract was deployed successfully to the network and the deployed contract address is `0xeB1c50679f8fe33542C44a4A6D779Fb47886E27f` . It also include the transaction details like the gas price, gas used and total cost in the output.&#x20;

## Interact with the Counter contract in the console

We can interact with the counter contract instance using the truffle console from cli. Start truffle console using:

```bash
$ truffle console --network development
truffle(development)> 
```

Truffle console shows the `truffle(development)>` prompt and waiting for our input.

type below commands and checkout the output:

```bash
truffle(development> let instance = Counter.deployed()
undefined
truffle(development> instance
....
truffle(development> let counterValue = await instance.current_value()
truffle(development> counterValue.toNumber()
0
truffle(development> let result = await instance.inc()
truffle(development>  result
{
  tx: '0xd5ac7b80244d1251782df0dd8411b843e527d1fa92fd580f4849cbc1d9139811',
  receipt: {
    blockHash: '0x75f72177aedfc2e0d27ff20d0b39c5688f320d165095dead0d0ba5986c64f0bb',
    blockNumber: 148,
    contractAddress: null,
    cumulativeGasUsed: 43793,
    from: '0xaed40f2261ba43b4dffe484265ce82d8ffe2b4db',
    gasUsed: 43793,
    internalTransactions: [ [Object] ],
    logs: [],
    logsBloom: '0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000',
    status: true,
    to: '0xeb1c50679f8fe33542c44a4a6d779fb47886e27f',
    transactionHash: '0xd5ac7b80244d1251782df0dd8411b843e527d1fa92fd580f4849cbc1d9139811',
    transactionIndex: 0,
    rawLogs: []
  },
  logs: []
}
truffle(development> let newValue = await instance.current_value()
truffle(development> newValue.toNumber()
1
```

In above commands we can use read the state `current_value` using `instance.current_value()` And we use the `instance.inc()` method to send a transaction which results the current value was increased by 1.

The result of the `instance.inc()` call was the transaction details which includes the block, block hash, events and fee information.

{% hint style="info" %}
The source code of this chapter could be found at the revision `3e76c43d3` in the [`counter-dapp`](https://github.com/clover-network/example-counter-dapp) source repo.
{% endhint %}


# Counter Webapp

Now we have the `Counter` smart contract and deployed it to the CLV local node. It's time to make changes to the web app so that it can interact with the `Counter` smart contract instance.&#x20;

## Preparation

### Setup the browser wallet

As it's a web application, make sure you've setup a `browser wallet` that connects to the local node. Follow the tutorials in the [Quick Start](broken://pages/-MOiXzNnIYZhBmKx4sCD) section if you have set it up yet. In this guide, we assume you connect to the local node using the [MetaMask](/clv-chain-developer-guide/using-local-node/using-metamask) wallet.&#x20;

{% hint style="info" %}
&#x20;MetaMask is the most commonly used browser wallet for Ethereum like blockchain networks. We can use MetaMask to connect to CLV network since CLV is fully compatible with Ethereum.&#x20;
{% endhint %}

After you have the wallet installed, import the `dev account` , you can import the dev account using the seed phase:

> bottom drive obey lake curtain smoke basket hold race lonely fit walk

Or using just the private key:

> 0x03183f27e9d78698a05c24eb6732630eb17725fcf2b53ee3a6a635d6ff139680

{% hint style="danger" %}
Do not use this key or seed phase in any real chain to store your assets! It's for test only, you will lose your money if you used them  in any real chain!
{% endhint %}

### Install Packges

Install necessary packages before we start:

```bash
$ yarn add @web3-react/core @web3-react/injected-connector @ethersproject/providers
```

The `@web3-react` packages provide pretty good web3 utilities for react application to talk with web3 compatible blockchain. `@ethersproject/providers` give use the web3 providers.

## Connecting to the wallet

The first step is connect our Counter DApp to the browser wallet. Firstly we need to create several files.

{% code title="connector.js" %}

```javascript
import { InjectedConnector } from '@web3-react/injected-connector'

export const injected = new InjectedConnector({ supportedChainIds: [1337] })
```

{% endcode %}

We make a `InjectedConnector` and specified the supported chain id to include the CLV chain id `1337`.

{% code title="hooks.js" %}

```javascript
import { useState, useEffect } from 'react'
import { useWeb3React } from '@web3-react/core'
import { injected } from './connectors'

export function useEagerConnect() {
  const { activate, active } = useWeb3React()

  const [tried, setTried] = useState(false)

  useEffect(() => {
    injected.isAuthorized().then((isAuthorized) => {
      if (isAuthorized) {
        activate(injected, undefined, true).catch(() => {
          setTried(true)
        })
      } else {
        setTried(true)
      }
    })
  }, []) // intentionally only running on mount (make sure it's only mounted once :))

  // if the connection worked, wait until we get confirmation of that to flip the flag
  useEffect(() => {
    if (!tried && active) {
      setTried(true)
    }
  }, [tried, active])

  return tried
}

export function useInactiveListener(suppress = false) {
  const { active, error, activate } = useWeb3React()

  useEffect(() => {
    const { ethereum } = window
    if (ethereum && ethereum.on && !active && !error && !suppress) {
      const handleConnect = () => {
        console.log("Handling 'connect' event")
        activate(injected)
      }
      const handleChainChanged = (chainId) => {
        console.log("Handling 'chainChanged' event with payload", chainId)
        activate(injected)
      }
      const handleAccountsChanged = (accounts) => {
        console.log("Handling 'accountsChanged' event with payload", accounts)
        if (accounts.length > 0) {
          activate(injected)
        }
      }
      const handleNetworkChanged = (networkId) => {
        console.log("Handling 'networkChanged' event with payload", networkId)
        activate(injected)
      }

      ethereum.on('connect', handleConnect)
      ethereum.on('chainChanged', handleChainChanged)
      ethereum.on('accountsChanged', handleAccountsChanged)
      ethereum.on('networkChanged', handleNetworkChanged)

      return () => {
        if (ethereum.removeListener) {
          ethereum.removeListener('connect', handleConnect)
          ethereum.removeListener('chainChanged', handleChainChanged)
          ethereum.removeListener('accountsChanged', handleAccountsChanged)
          ethereum.removeListener('networkChanged', handleNetworkChanged)
        }
      }
    }
  }, [active, error, suppress, activate])
}

```

{% endcode %}

`hooks.js` provides several hooks to help connect with the wallet.

{% code title="Spinner.js" %}

```javascript
import React from 'react'

// <!-- By Sam Herbert (@sherb), for everyone. More @ http://goo.gl/7AJzbL -->
export function Spinner(props) {
  const { color, ...rest } = props
  return (
    <svg width="38" height="38" viewBox="0 0 38 38" xmlns="http://www.w3.org/2000/svg" stroke={color} {...rest}>
      <g fill="none" fillRule="evenodd">
        <g transform="translate(1 1)" strokeWidth="2">
          <circle strokeOpacity=".5" cx="18" cy="18" r="18" />
          <path d="M36 18c0-9.94-8.06-18-18-18">
            <animateTransform
              attributeName="transform"
              type="rotate"
              from="0 18 18"
              to="360 18 18"
              dur="1s"
              repeatCount="indefinite"
            />
          </path>
        </g>
      </g>
    </svg>
  )
}
```

{% endcode %}

`Spinner.js` implements a simple spinner component which could be used as the loading status.

Update the `App.js` to set its content to:

{% code title="App.js" %}

```javascript
import { Web3ReactProvider, useWeb3React, } from '@web3-react/core'
import { Web3Provider } from '@ethersproject/providers'
import { useEagerConnect, useInactiveListener } from './hooks'

import './App.css';

function getLibrary(provider) {
  const library = new Web3Provider(provider)
  library.pollingInterval = 5000
  return library
}

function ChainId() {
  const { chainId, library } = useWeb3React()

  return (
    <div className="ChainIdWrapper">
      <span>Chain Id</span>
      <span role="img" aria-label="chain">
        ⛓
      </span>
      <span className="ChainIdText">{chainId ?? 'Not Connected'}</span>
    </div>
  )
}

function App() {
  const triedEager = useEagerConnect()

  return (
      <div className="App">
        <header className="App-header">
          <h1>Counter Example </h1>
          <ChainId/>
          <p>
            Current value: n/a
        </p>
          <button className="CounterButton">Inc Counter</button>
          <button className="CounterButton">Dec Counter</button>
        </header>
      </div>
  );
}


export default function() {
  return (
    <Web3ReactProvider getLibrary={getLibrary}>
      <App />
    </Web3ReactProvider>
  )
}
```

{% endcode %}

We added the `Web3ReactProvider` to the root of the application and include the `useEagerConnect` hooks in the `App` component. We also includes the `ChainId` component which will show the connected chain id and show `not connected` if no connection detected.&#x20;

Start the application you will see the `not connected` in the ChainId component. It's find since we haven't implement the connection logic. But you can test it by manually connect to the web app from `MetaMask`, try to figure out how to do it by yourself.

### Add the Connect Button

Now let's add a button to trigger the wallet connect dialog.&#x20;

Edit `App.js` to add some imports:

```javascript
import React from 'react'
import { Spinner } from './Spiner'
import { injected } from './connectors'
```

And create the `ConnectChain` component:

```javascript
function ConnectChain(props) {
  const context = useWeb3React()
  const { connector, library, chainId, account, activate, deactivate, active, error } = context

  const [activatingConnector, setActivatingConnector] = React.useState()
  React.useEffect(() => {
    if (activatingConnector && activatingConnector === connector) {
      setActivatingConnector(undefined)
    }
  }, [activatingConnector, connector])

  const activating = injected === activatingConnector
  const connected = injected === connector
  const disabled = !props.triedEager || !!activatingConnector || !!error

  useInactiveListener(!props.triedEager || !!activatingConnector)

  let isDisconnect = !error && chainId
  const buttonText = isDisconnect ? 'Disconnect' : (activating ? 'Connectting' : 'Connect' )

  return (
    <button
      style={{
        borderColor: activating ? 'orange' : connected ? 'green' : 'unset',
        cursor: disabled ? 'unset' : 'pointer',
        position: 'relative',
      }}
      className="ConnectButton"
      disabled={disabled}
      onClick={() => {
        if (!isDisconnect) {
          setActivatingConnector(injected)
          activate(injected)
        } else {
          deactivate()
        }
      }}
    >
      <div
        style={{
          position: 'absolute',
          top: '0',
          left: '0',
          height: '100%',
          display: 'flex',
          alignItems: 'center',
          color: 'black',
          margin: '0 0 0 1rem'
        }}
      >
        {activating && <Spinner color={'red'} style={{ height: '50%', marginLeft: '-1rem' }} />}
      </div>
      { buttonText }
    </button>
  )
}
```

and the css class for the button

{% code title="App.css" %}

```css
.ConnectButton {
  background-color: #4CAF50;
  border: none;
  color: white;
  margin-top: 15px;
  margin-bottom: 15px;
  padding: 15px 32px;
  text-align: center;
  text-decoration: none;
  display: inline-block;
  font-size: 16px;
  width: 200px;
}

.ConnectButton:disabled {
  background-color: grey;
  color: black;
}
```

{% endcode %}

The `ConnectChain` component simple renders a button if it's not connected, click it will trigger the web3 connection dialog.&#x20;

Let's add the `ConnectChain` component to the `App` component, you could place it under the `<h1>` title or somewhere else as you like.

```javascript
<ConnectChain triedEager={triedEager} />
```

Reload the page, the `Connect` button will show up and you can click it to open the connect dialog.  After connected to the wallet, click the button will disconnect it.

## Read contract state

First install the `@ethersproject/contracts` package, i

```bash
$ yarn add @ethersproject/contracts
```

{% hint style="info" %}
`@ethersproject/contracts` is a sub module of the ethers project.It is creating (at run-time) an object which interacts with an on-chain contract as a native JavaScript object.
{% endhint %}

We need add extra hooks to interact with the contract:

{% code title="hooks.js" %}

```javascript
import { Contract } from '@ethersproject/contracts'

export function useBlockNumber() {
  const { library }= useWeb3React()
  const [blockNumber, setBlockNumber] = useState(-1)

  useEffect(() =>  {
    if (!library) {
      return
    }
    const t = setInterval(async () => {
      try {
        setBlockNumber(await library.getBlockNumber())
      } catch(ex) {
        console.error('failed to get block number', ex)
      }
      return () => {
        clearInterval(t)
      }
    }, 1000)

  }, [library])
  return blockNumber
}

export function useContract(contractJson) {
  const { chainId, library, account}= useWeb3React()

  if (!chainId || !contractJson.networks || !contractJson.networks[chainId]) {
    return null
  }

  const signer = library.getSigner(account).connectUnchecked()
  return new Contract(contractJson.networks[chainId].address, contractJson.abi, signer)
}

export function useContractCallData(contract, methodName, args) {
  const blockNumber = useBlockNumber()
  const [ result, setResult ] = useState(null)
  useEffect(() => {
    if (!contract || !methodName) {
      return null
    }
    async function loadData() {
      try {
        const result = await contract[methodName](...args)
        setResult(result)
      } catch (ex) {
        console.log(`failed call contract method ${methodName}: `, ex)
      }
    }
    loadData()
  }, [blockNumber])
  return result
}
```

{% endcode %}

1. We add 3 hooks, the `useBlockNumber`hook returns the latest block number from the chain (we emulate the data with 1 second refresh interval).
2. The `useContract` hook creates a smart contract instance from the json definition which was created by truffle. It will automatically detect the smart contract address on the chain.
3. The `useContractCallData` hook calls the contract method and will keep up to date with the latest block.

Now edit `App.js` and update it's content:

```javascript
import { useEagerConnect, useInactiveListener, useContract, useContractCallData } from './hooks'


function App() {
  const triedEager = useEagerConnect()
  const counter = useContract(CounterContract)
  const currentValue = useContractCallData(counter, 'current_value', [])
  const currentValueText = (currentValue === undefined || currentValue === null) ? 'N/A' : currentValue

  return (
      <div className="App">
        <header className="App-header">
          <h1>Counter Example </h1>
          <ConnectChain triedEager={triedEager} />
          <ChainId/>
          <p>
            Current value: {currentValueText}
          </p>

          <button className="CounterButton">Inc Counter</button>
          <button className="CounterButton">Dec Counter</button>
        </header>
      </div>
  );
}
```

Here we create the counter contract using the `useContract` hook. And then we use the `useContractCallData` hook to fetch the `current_value` state from the smart contract.&#x20;

In the renderer function, we set the current value text to the value on the chain.&#x20;

Save `App.js` and reload the webpage, you should see the current counter value on the page.

## Write contract state

Now we can work on the inc/dec buttons, we'll add the `onClick` handler to them and call the `inc`/`dec` method correspondingly.&#x20;

```javascript
function App() {
  const triedEager = useEagerConnect()
  const counter = useContract(CounterContract)
  const [loading, setLoading] = useState(false)
  const currentValue = useContractCallData(counter, 'current_value', [])

  const currentValueText = (currentValue === undefined || currentValue === null) ? 'N/A' : currentValue
  const callMethod = async (name) => {
    if (loading) {
      return
    }
    setLoading(true)
    try {
      await counter[name]()
    } catch(ex) {
      console.error('transaction error: ', ex)
    } finally {
      setLoading(false)
    }
  }

  return (
      <div className="App">
        <header className="App-header">
          <h1>Counter Example </h1>
          <ConnectChain triedEager={triedEager} />
          <ChainId/>
          <p>
            Current value: {currentValueText}
          </p>

          {loading && <Spinner color={'red'} style={{ height: '40px', marginLeft: '-1rem' }} />}
          <button className="CounterButton" onClick={() => callMethod('inc')}>Inc Counter</button>
          <button className="CounterButton" onClick={() => callMethod('dec')}>Dec Counter</button>
        </header>
      </div>
  );
}
```

Besides calling the `inc`/`dec`method, we also added a loading state to indicate we're waiting for some operation.

Save `App.js` and reload the webpage.

Click the Inc or Dec button, the sign transaction dialog will show up, click confirm to sign and send the transaction. The current value will be updated after a short while (\~around 10 seconds).

That's it! We've implemented read/write the smart contracts in the DApp.

{% hint style="info" %}
The source code of this chapter could be found at the revision `fc93d686aab`in the [`counter-dapp`](https://github.com/clover-network/example-counter-dapp) source repo.
{% endhint %}

## Conclusion

In this tutorial we completed an e2e DApp development process which includes smart contract development, deployment and setup a frontend application to interact with the smart contract.

There're several things to improve which you can do:

1. The smart contract should send the update when the current value changes.
2. Implement a real time `useBlockNumber` hook
3. The current value was not updated in real time, improve it
4. The loading spinner shows when the `confirm transaction` dialog open, improve it so that it will wait for the transaction completes.

As we only demo a smallest DApp development, some code/functions are not written in a performant style, you should adjust them if you want to use them in a real project.


# Test Cases

In order to make CLV as secure and high performance multi-chain. There are lots of test cases have been made to support.

## EVM Compatibility Tests

### Balance Tests

1. The CLV EVM should provide the same interface for balance transfer and query.
2. The balance transfer should run correctly and related balance updated.

Test cases can be viewed here: <https://github.com/clover-network/clover-sdk/blob/main/tests/test-balance.ts>

### Block Tests

1. The CLV EVM can return correct genesis block.
2. CLV EVM can support query block by number or hash.
3. The returned block should contain transactions and correct transaction root.
4. The newly generated block should has valid timestamp and includes previous block as parent

Test cases can be viewed here: <https://github.com/clover-network/clover-sdk/blob/main/tests/test-block.ts>

### Bloom Tests

The transaction receipt should contains correct bloom data

Test cases can be viewed here: <https://github.com/clover-network/clover-sdk/blob/main/tests/test-bloom.ts>

### Smart Contract Creation Tests

1. Smart contract can be correctly  created by CLV EVM.
2. Smart contract creation can return transaction hash.

Test cases can be viewed here: <https://github.com/clover-network/clover-sdk/blob/main/tests/test-contract.ts>

### Smart Contract Call Tests

1. CLV EVM should support the invoke of smart contract call.
2. The smart contract call should return expected result.
3. The smart contract call should fail in case of invalid parameters.

Test cases can be viewed here: <https://github.com/clover-network/clover-sdk/blob/main/tests/test-contract-methods.ts>

### Gas Fee Tests

1. CLV EVM should support estimation of gas fee.
2. The gas limit should decrease on next block if gas unused.
3. The estimated gas should be correct for smart contract creation or method call.

Test cases can be viewed here: <https://github.com/clover-network/clover-sdk/blob/main/tests/test-gas.ts>

### Other Tests

1. CLV EVM should support correct nonce query.
2. CLV EVM should return the revert reason in case of failure.
3. CLV EVM should return a valid transaction receipt for a successful or failed transaction.

Test cases can be viewed here: <https://github.com/clover-network/clover-sdk/tree/main/tests>

## End to End Tests

In order to test the full functionality of CLV EVM, we provide a script which can automatically deploy Uniswap on CLV for one-shot.

1. It can deploy Uniswap ERC20 token to CLV
2. It can deploy Uniswap V2 Factory smart contract to CLV
3. It can deploy WETH ERC20 token to CLV
4. It can deploy Uniswap V2 Router smart contract to CLV
5. It can deploy Multicall smart contract to CLV

Please find the cool script here: <https://github.com/clover-network/clover-sdk/blob/main/tests/e2e-tests/test/test-uniswap.js>

## Complex Gas Fee Tests

CLV EVM is based on Frontier, we find that the gas fee estimation under some cases may fail, such as nested smart contract call.  CLV provides a binary search based solution to solve the problem. Please find the details here:

{% embed url="<https://github.com/paritytech/frontier/pull/252>" %}

After the fix, CLV EVM can support all kinds of gas estimation correctly, please find the test case here: <https://github.com/clover-network/clover-sdk/blob/main/tests/inner-contract-tests/test/test-inner-contract.js>

## CLV Account Binding Tests

CLV has a powerful dual-chain architecture, which will empower its users to build their decentralized apps and digital assets on one blockchain (CLV EVM powered) and take advantage of Polkadot chain on the other. Thus CLV account binding is very important, it enables users to do all the staffs under one unified account. Also the bound accounts can share the same balance, as well as the integration of the cool features on the dual-chain.

The related test cases can be found here: <https://github.com/clover-network/clover-sdk/blob/main/tests/account-bind-tests/test-account-bind.js>

## CLV TPS Tests

In order to test the performance of CLV chain, test cases have been carried out both on EVM and CLV Parachain.

The EVM TPS tests can be found at: <https://github.com/clover-network/clover-sdk/blob/main/tests/tps-tests/test-web3-tps.js>

The CLV Parachain tests can be found at: <https://github.com/clover-network/clover-sdk/blob/main/tests/tps-tests/test-polkadot-tps.js>


# Technical Documentations


# CLV EVM

CLV EVM is based on Frontier, but we make a lot of changes to support unique CLV designs and features. Please see the following details.

## New Gas Estimation Feature

CLV EVM is based on Frontier, we find that the gas fee estimation under some cases may fail, such as nested smart contract call.  CLV provides a binary search based solution to solve the problem. Please find the details here:

{% embed url="<https://github.com/paritytech/frontier/pull/252>" %}

## New EVM Economic Incentives

In order to make developer easily do the development on CLV.  CLV EVM support a new economic incentives. The smart contract owner will receive partial of the transaction fee once their contracts are called. Details are:

* Up to 40% of the transaction fee will be sent to the smart contract owner.
* Up to 60% of the transaction fee will be sent to the miner.

## Other EVM Configurations

CLV change the create\_contract\_limit from 0x6000 to 0xc000,  try to reduce the chances that smart contract deployer has to split their big contract for deployment.


# Developers Incentive

The Developer Incentive Program (DIP) is made of two respective implementations, a foundational-layer coinbase rule activation and a following smart contract implementation.

## Coinbase Rule Activation

CLV users contribute to the program indirectly with transaction fees, this is so that a new fee schedule is not committed to the transaction structure itself. Wallet softwares functions the same as usual without breaking backwards compatibility.

The coinbase transaction which spends the block reward and all transaction fees to an address of the validators choosing follows a subsequent transaction where 49 percent of txFee reward is respectively transferred to DIP contract. The amount of total CLV a successful validator can claim for himself is therefore changed from blockReward + txnFees to blockReward + txnFees*51/100.* Whenever a block is propagated, every node will check whether the block adheres to the rules where the sum of all transaction outputs in a block must be equal or smaller than all transaction inputs and the block reward: sum(blockOutputs) ¡ sum(blockInputs) + (blockReward + txnFees51/100) + txnFees\*49/100

## Smart Contract Implementation

External contract registration and reward distribution are done through DIP contract, a trust- less autonomous contract that lives on the CLV parachain. This implementation is made of three main phases; registration, invocation and reward distribution.

### Registration

Third party CLV developers can benefit from the Developer Incentive Program upon registering their compiled contract with DIP contract pre-deployment. An external contract willing to register Developer Incentive Program should include an internal method called transactAndInvokeDIP which is used to trigger reward incrementation, and another internal method called claimRewards which is used to trigger reward settlement.

Right before contract deployment, the respective developer submits contract ABI and contract hexadecimal representation to DIP contract via registerExternalContract method. Given parameters registerExternalContract registers submission upon checking whether the contract is well-formatted and transactAndInvokeDIP is well-structured.

![New Contract Registration Logic](/files/-MQLlj4Aod02NMrYAk6v)

### Invocation

transactAndInvokeDIP adds a new standard to contracts on the CLV network which can be called internally within the external contract with the additional data provided. Whenever a CLV user interacts with a registered external contract, transactAndInvokeDIP invokes DIP contract’s function listenInvokeDIP and triggers an event incrementRewardNonce(address), following the convention set in ERC677.

![Invocation Logic](/files/-MQLlvQjG1BMs7XvDmhQ)

### Reward Distribution

Registered third party CLV developers can claim their rewards, in a predefined period of time, upon calling internal claimRewards function which triggers a set of events to distribute a portion of associated rewards based on external contract’s reward nonce and DIP contract’s total reward pool from coinbase txFee rewards.

![Reward Distribution Logic](/files/-MQLm5-HUda6aDlXzprH)


# CLV Accounts Binding

## Why need Account Binding

As explained in this [section](/intro-to-clv/what-is-clv-chain), CLV Parachain is a dual blockchain which support both EVM transactions as well as Polkadot like transactions.

Account binding only happens on CLV Parachain, you can bind your CLV address to a CLV EVM address. Once you bind the accounts,  you can use one account to interact with both EVM-based dApps as well as Substrate-based dApps.&#x20;

Here are the features of CLV accounts binding (suppose you have done the accounts binding, for example bind your CLV address: **5DyCG7icXFuq8WtLd7iLi3umczKf84SAvp7w7Rw44RFEU8Yf** with EVM address: **0xe6206C7f064c7d77C6d8e3eD8601c9AA435419cE**)

1. The above addresses will have the same balance. Other people can send CLV to any of the above account, and you can receive the CLV.  At the same time, you can send CLV to other people using any of the above account.
2. If you only have CLV in **0xe6206C7f064c7d77C6d8e3eD8601c9AA435419cE**,  you can't deploy or interact with CLV smart contract. Once you bind the account with a EVM address, you are able to deploy and interact with CLV smart contract.

## How to Bind the Account

1. Using CLV Wallet, the version should be above 1.0.3
2. Using the following sample code：

```javascript
const API = require("@polkadot/api")
const Web3 = require("web3")
const web3 = new Web3("https://rpc-2.clover.finance")
const cloverTypes = require('@clover-network/node-types')

const PUB_KEY = "0xe6206C7f064c7d77C6d8e3eD8601c9AA435419cE"
const PRIV_KEY = "0xa504b64992e478a6846670237a68ad89b6e42e90de0490273e28e74f084c03c8"
const CLOVER_SEEDS = "your 12 seed words"

async function run() {
    const wsProvider = new API.WsProvider('wss://api-2.clover.finance');
    const api = await API.ApiPromise.create({
        provider: wsProvider,
        types: cloverTypes
    });
    const keyring = new API.Keyring({ type: 'sr25519' });
    const alice = keyring.addFromUri(CLOVER_SEEDS);
    let nonce = await api.rpc.system.accountNextIndex(alice.address);
    web3.eth.accounts.wallet.add(PRIV_KEY);
    let signature = await web3.eth.sign(`clover evm:${web3.utils.bytesToHex(alice.publicKey).slice(2)}`, PUB_KEY);

    await api.tx.evmAccounts
        .claimAccount(PUB_KEY, web3.utils.hexToBytes(signature))
        .signAndSend(alice, {
            nonce,
        }, ({ events = [], status }) => {
            if (status.isFinalized) {
                console.log(`${alice.address} has bound with EVM address: ${PUB_KEY}`)
            }
        });
}

run()
```

�


# Virtual Ethereum Address Binding

CLV and ETH address Binding is mandatory. CLV Chain will check whether the address is bound every time before a user signs. If the address is unbound, the following process will be triggered.

![](/files/-MQLwc0rYLLq_5unPKSK)

After binding, the CLV assets of the two accounts will be mapped and the data is shared.<br>


# Query Balance

This section shows how to connect to CLV mainnet and query the account balance

## **Prerequisites**

Install @polkadot/api, the suggested version is ^4.15.1 (equal or above 4.15.1)

## Sample code

```javascript
const API = require("@polkadot/api")
const cloverTypes = require('@clover-network/node-types');

async function getBalance(address) {
    const wsProvider = new API.WsProvider('wss://api-ivy.clover.finance');
    const api = await API.ApiPromise.create({
        provider: wsProvider,
        types: cloverTypes
    });
    const { parentHash } = await api.rpc.chain.getHeader();
    const {
        data: { free: balance },
    } = await api.query.system.account.at(parentHash, address);
    return balance.toString();
}

getBalance('5DZabq7G2m12g1GUuqs66CCAVcmzdWRkXsGxpi4dgXFEcLEb').then(console.log)
```

Furthermore you may use **formatBalance** from **@polkadot/util** to format the display

�


# Transaction Finality

PolkadotJS API provides **signAndSend** function to send a transaction, the callback will yield information around the transaction pool status as well as any events when `isInBlock` or `isFinalized`.  If you receive the `isFinalized` event, then your transaction is considered as finality and will never be reverted.

## Sample Code

```javascript
const API = require("@polkadot/api");
const cloverTypes = require('@clover-network/node-types');

async function sendCLV(address, amount) {
  const wsProvider = new API.WsProvider('wss://api-ivy.clover.finance');
  const api = await API.ApiPromise.create({
    provider: wsProvider,
    types: cloverTypes
  });
  const nonce = await api.rpc.system.accountNextIndex('your CLV address configured somewhere');
  const keyring = new API.Keyring({ type: 'sr25519' });
  const signer = keyring.addFromUri('your seeds configured somewhere');
  return new Promise( (resolve, reject) => {
    api.tx.balances
      .transfer(address, amount)
      .signAndSend(signer, {
        nonce,
      }, ({ events = [], status }) => {
        if (status.isFinalized) {
          // filter events and check balances.transfer is succeed
          resolve({ success: true });
        }
        if (status.isDropped || status.isInvalid || status.isUsurped) {
          resolve({ success: false });
        }
      });
  });
}
```


# Web3 Compatibility

CLV is also a Polkadot smart contract chain, which has a full compatibility with web3 application.

For developers, please use the following web3 http provider to access CLV chain:

```
const Web3 = require("web3");
const web3 = new Web3("https://rpc.clover.finance");
```


# eth\_protocolVersion

Returns protocol version encoded as a string

```
web3.eth.getProtocolVersion([callback])
```

#### Returns

Promise returns String: the protocol version.

#### Example

```
> web3.eth.getProtocolVersion().then(console.log)
> 1
```


# eth\_syncing

Returns an object with data about the sync status or false

```
web3.eth.isSyncing([callback])
```

#### Returns

A sync object when the node is currently syncing or `false`:

> * `startingBlock` - `Number`: The block number where the sync started.
> * `currentBlock` - `Number`: The block number where the node is currently synced to.
> * `highestBlock` - `Number`: The estimated block number to sync to.
> * `knownStates` - `Number`: The number of estimated states to download.
> * `pulledStates` - `Number`: The number of already downloaded states.

#### Example

```
> web3.eth.isSyncing().then(console.log)
> false
```


# eth\_hashrate

Returns the number of hashes per second that the node is mining with

```
web3.eth.getHashrate([callback])
```

#### Returns

Number of hashes per second

#### Example

```
> web3.eth.getHashrate().then(console.log)
> 0
```


# eth\_coinbase

Returns the coinbase address to which mining rewards will go.

```
web3.eth.getCoinbase([callback])
```

#### Returns

The coinbase address set in the node for mining rewards

#### Example

```
> web3.eth.getCoinbase().then(console.log)
> 0x0000000000000000000000000000000000000000
```


# eth\_mining

Returns true if client is actively mining new blocks

```
web3.eth.isMining([callback])
```

#### Returns

`true` if the node is mining, otherwise `false`

#### Example

```
> web3.eth.isMining().then(console.log)
> true
```


# eth\_chainId

Returns the chain ID used for transaction signing at the current best block. None is returned if not available

```
web3.eth.getChainId([callback])
```

#### Returns

Returns chain ID.

#### Example

```
> web3.eth.getChainId().then(console.log);
> 1023
```


# eth\_gasPrice

Returns the current gas price oracle. The gas price is determined by the last few blocks median gas price.

```
web3.eth.getGasPrice([callback])
```

#### Returns

Number string of the current gas price in wei

#### Example

```
> web3.eth.getGasPrice().then(console.log)
> 1000000000
```


# eth\_accounts

Returns accounts list

```
web3.eth.getAccounts([callback])
```

#### Returns

An array of addresses controlled by node

#### Example

```
> web3.eth.getAccounts().then(console.log)
> [ '0x19E7E376E7C213B7E7e7e46cc70A5dD086DAff2A' ]
```


# eth\_blockNumber

Returns highest block number

```
web3.eth.getBlockNumber([callback])
```

#### Returns

The number of the most recent block.

#### Example

```
> web3.eth.getBlockNumber().then(console.log)
> 114913
```


# eth\_getBalance

Returns balance of the given account

```
web3.eth.getBalance(address [, defaultBlock] [, callback])
```

#### Parameters

1、The address to get the balance of.

2、(optional) If you pass this parameter it will not use the default block set with [web3.eth.defaultBlock](https://web3js.readthedocs.io/en/v1.3.0/web3-eth.html#eth-defaultblock). Pre-defined block numbers as `"earliest"`,"latest" and `"pending"` can also be used.

3、(optional) Optional callback, returns an error object as first parameter and the result as second.

#### Returns

The current balance for the given address in wei.

#### Example

```
> web3.eth.getBalance("0x063eBCD1dB02320814Acc0721e65f14b8755Ff41").then(console.log)
> 98999296192000000000
```


# eth\_getStorageAt

Returns content of the storage at given address

```
web3.eth.getStorageAt(address, position [, defaultBlock] [, callback]
```

#### Parameters

1、The address to get the storage from.

2、The index position of the storage.

3、(optional) If you pass this parameter it will not use the default block set with [web3.eth.defaultBlock](https://web3js.readthedocs.io/en/v1.3.0/web3-eth.html#eth-defaultblock). Pre-defined block numbers as `"earliest"`, `"latest"` and `"pending"` can also be used.

4、(optional) Optional callback, returns an error object as first parameter and the result as second.

#### Returns

The value in storage at the given position.

#### Example

```
> web3.eth.getStorageAt("0x063eBCD1dB02320814Acc0721e65f14b8755Ff41", 0).then(console.log)
> 0x0000000000000000000000000000000000000000000000000000000000000000
```


# eth\_getBlock

Returns block with given number

```
web3.eth.getBlock(blockHashOrBlockNumber [, returnTransactionObjects] [, callback])
```

#### Parameters

1. The block number or block hash. Or the string `"earliest"`, `"latest"` or `"pending"` as in the [default block parameter](https://web3js.readthedocs.io/en/v1.3.0/web3-eth.html#eth-defaultblock).
2. (optional, default `false`) If specified `true`, the returned block will contain all transactions as objects. If `false` it will only contains the transaction hashes.
3. (optional) Optional callback, returns an error object as first parameter and the result as second.

#### Returns

The block object:

> * `number`: The block number. `null` if a pending block.
> * `hash`: Hash of the block. `null` if a pending block.
> * `parentHash`: Hash of the parent block
> * `sha3Uncles` : SHA3 of the uncles data in the block.
> * `logsBloom`: The bloom filter for the logs of the block. `null` if a pending block.
> * `transactionsRoot`: The root of the transaction trie of the block.
> * `stateRoot` : The root of the final state trie of the block.
> * `miner` : The address of the beneficiary to whom the mining rewards were given.
> * `difficulty` : Integer of the difficulty for this block.
> * `totalDifficulty`: Integer of the total difficulty of the chain until this block.
> * `extraData`: The “extra data” field of this block.
> * `size`: Integer the size of this block in bytes.
> * `gasLimit`: The maximum gas allowed in this block.
> * `gasUsed`: The total used gas by all transactions in this block.
> * `timestamp`: The unix timestamp for when the block was collated.
> * `transactions`: Array of transaction objects, or 32 Bytes transaction hashes depending on the `returnTransactionObjects` parameter.
> * `uncles`: Array of uncle hashes.
> * &#x20; author ：
> * &#x20; receiptsRoot ：
> * &#x20; sealFields ：
>
> #### Example

> ```
> //block number
> > web3.eth.getBlock(43458).then(console.log);
> > {
>   author: '0xe4a61e41ac64a0e18c22bc3bf0f0e6c9ded3c08d',
>   difficulty: '0',
>   extraData: '0x',
>   gasLimit: 0,
>   gasUsed: 0,
>   hash: '0x0098d4eb6ec05bf6a7c727310b64ae9bfe1c5fb3ff57a3449bcededa00858015',
>   logsBloom: '0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000',
>   miner: '0xE4A61E41ac64a0e18c22bc3bF0F0E6c9DeD3C08d',
>   number: 43458,
>   parentHash: '0x0dd1bb45074703797fbfcb970df49b17e27f72db05af9784279ded0692bbaafd',
>   receiptsRoot: '0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347',
>   sealFields: [
>     '0x0000000000000000000000000000000000000000000000000000000000000000',
>     '0x0000000000000000'
>   ],
>   sha3Uncles: '0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347',
>   size: 509,
>   stateRoot: '0x341e4f8c138596ef775ee35c82d196b1b97dc5ee2b4c474bff0d0437da9e355c',
>   timestamp: 1609917924,
>   totalDifficulty: null,
>   transactions: [],
>   transactionsRoot: '0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421',
>   uncles: []
> }
> ```

```
//block hash
> web3.eth.getBlock("0x0098d4eb6ec05bf6a7c727310b64ae9bfe1c5fb3ff57a3449bcededa00858015",true).then(console.log)
> {
  author: '0xe4a61e41ac64a0e18c22bc3bf0f0e6c9ded3c08d',
  difficulty: '0',
  extraData: '0x',
  gasLimit: 0,
  gasUsed: 0,
  hash: '0x0098d4eb6ec05bf6a7c727310b64ae9bfe1c5fb3ff57a3449bcededa00858015',
  logsBloom: '0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000',
  miner: '0xE4A61E41ac64a0e18c22bc3bF0F0E6c9DeD3C08d',
  number: 43458,
  parentHash: '0x0dd1bb45074703797fbfcb970df49b17e27f72db05af9784279ded0692bbaafd',
  receiptsRoot: '0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347',
  sealFields: [
    '0x0000000000000000000000000000000000000000000000000000000000000000',
    '0x0000000000000000'
  ],
  sha3Uncles: '0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347',
  size: 509,
  stateRoot: '0x341e4f8c138596ef775ee35c82d196b1b97dc5ee2b4c474bff0d0437da9e355c',
  timestamp: 1609917924,
  totalDifficulty: null,
  transactions: [],
  transactionsRoot: '0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421',
  uncles: []
}

```


# eth\_getTransactionCount

Returns the number of transactions sent from given address at given time (block number)

```
web3.eth.getTransactionCount(address [, defaultBlock] [, callback])
```

#### Parameters

1. The address to get the numbers of transactions from.
2. (optional) If you pass this parameter it will not use the default block set with [web3.eth.defaultBlock](https://web3js.readthedocs.io/en/v1.3.0/web3-eth.html#eth-defaultblock). Pre-defined block numbers as `"earliest"`, `"latest"` and `"pending"` can also be used.
3. &#x20;(optional) Optional callback, returns an error object as first parameter and the result as second.

#### Returns

The number of transactions sent from the given address.

#### Example

```
> web3.eth.getTransactionCount("0x063eBCD1dB02320814Acc0721e65f14b8755Ff41").then(console.log)
> 12
```


# eth\_getBlockTransactionCount

Returns the number of transactions in a block with given block number

```
web3.eth.getBlockTransactionCount(blockHashOrBlockNumber [, callback])
```

#### Parameters

1. The block number or hash. Or the string `"earliest"`, `"latest"` or `"pending"` as in the [default block parameter](https://web3js.readthedocs.io/en/v1.3.0/web3-eth.html#eth-defaultblock).
2. &#x20;(optional) Optional callback, returns an error object as first parameter and the result as second.

#### Returns

The number of transactions in the given block.

#### Example

```
> web3.eth.getBlockTransactionCount(43458).then(console.log)
> 0
```


# eth\_getBlockUncleCount

Returns the number of uncles in a block with given hash

```
web3.eth.getBlockUncleCount(blockHashOrBlockNumber [, callback])
```

#### Parameters

1. The block number or hash. Or the string `"earliest"`, `"latest"` or `"pending"` as in the [default block parameter](https://web3js.readthedocs.io/en/v1.3.0/web3-eth.html#eth-defaultblock).
2. (optional) Optional callback, returns an error object as first parameter and the result as second.

#### Returns

The number of transactions in the given block.

#### Example

```
> web3.eth.getBlockUncleCount(43458).then(console.log)
> 0
```


# eth\_getCode

Returns the code at given address at given time (block number)

```
web3.eth.getCode(address [, defaultBlock] [, callback])
```

#### Parameters

1. The address to get the code from.
2. (optional) If you pass this parameter it will not use the default block set with [web3.eth.defaultBlock](https://web3js.readthedocs.io/en/v1.3.0/web3-eth.html#eth-defaultblock). Pre-defined block numbers as `"earliest"`, `"latest"` and `"pending"` can also be used.
3. &#x20;Optional callback, returns an error object as first parameter and the result as second.

#### Returns

The data at given address `address`

#### Example

```
> web3.eth.getCode("0x063eBCD1dB02320814Acc0721e65f14b8755Ff41").then(console.log);
> 0x
```


# eth\_sendTransaction

Sends transaction; will block waiting for signer to return the transaction hash


# eth\_sendSignedTransaction

Sends signed transaction, returning its hash

```
web3.eth.sendSignedTransaction(signedTransactionData [, callback])
```

#### Parameters

1. Signed transaction data in HEX format
2. (optional) Optional callback, returns an error object as first parameter and the result as second

#### Returns

The callback will return the 32 bytes transaction hash.

#### Example

```
> web3.eth.accounts.signTransaction({
        from : "0x063eBCD1dB02320814Acc0721e65f14b8755Ff41",
        to : "0x69d8fa34508C43C8533a32ab278aDDDE2820556b",
        value : web3.utils.toWei('0.1', 'ether'),
        gas : web3.utils.toHex(21000),
        gasPrice : web3.utils.toWei("1", "gwei"),
        nonce : 19
    },"e0855c1ec13690c826ee767be03937fa5bce1d621ca780d2ac487574bf8d74d2",function(err,raw){
        if(!err){
            web3.eth.sendSignedTransaction(raw.rawTransaction, function(error, result){
                if(!error){
                    console.log(result)
                }else{
                    console.log(error)
                }
            })
        }else{
            console.log(err)
        }
    });
> 0x52e5f6347bdbf6fe1d8acb07bb460ce31d82bb36e80acfdc8aca798e28415334
```


# eth\_call

Call contract, returning the output data

```
web3.eth.call(callObject [, defaultBlock] [, callback])
```

#### Parameters

1. A transaction object, see [web3.eth.sendTransaction](https://web3js.readthedocs.io/en/v1.3.0/web3-eth.html#eth-sendtransaction-return). For calls the `from` property is optional however it is highly recommended to explicitly set it or it may default to address(0) depending on your node or provider.
2. &#x20;(optional) If you pass this parameter it will not use the default block set with [web3.eth.defaultBlock](https://web3js.readthedocs.io/en/v1.3.0/web3-eth.html#eth-defaultblock). Pre-defined block numbers as `"earliest"`, `"latest"` and `"pending"` can also be used.
3. (optional) Optional callback, returns an error object as first parameter and the result as second.

#### Returns

The returned data of the call, e.g. a smart contract functions return value.

#### Example

```
const abi = JSON.parse('[{\"inputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"constant\":true,\"inputs\":[],\"name\":\"get\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"string\",\"name\":\"_value\",\"type\":\"string\"}],\"name\":\"set\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]')
bytecode = '0x608060405234801561001057600080fd5b506040518060400160405280600781526020017f6d7956616c7565000000000000000000000000000000000000000000000000008152506000908051906020019061005c929190610062565b50610107565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f106100a357805160ff19168380011785556100d1565b828001600101855582156100d1579182015b828111156100d05782518255916020019190600101906100b5565b5b5090506100de91906100e2565b5090565b61010491905b808211156101005760008160009055506001016100e8565b5090565b90565b61030f806101166000396000f3fe608060405234801561001057600080fd5b50600436106100365760003560e01c80634ed3885e1461003b5780636d4ce63c146100f6575b600080fd5b6100f46004803603602081101561005157600080fd5b810190808035906020019064010000000081111561006e57600080fd5b82018360208201111561008057600080fd5b803590602001918460018302840111640100000000831117156100a257600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f820116905080830192505050505050509192919290505050610179565b005b6100fe610193565b6040518080602001828103825283818151815260200191508051906020019080838360005b8381101561013e578082015181840152602081019050610123565b50505050905090810190601f16801561016b5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b806000908051906020019061018f929190610235565b5050565b606060008054600181600116156101000203166002900480601f01602080910402602001604051908101604052809291908181526020018280546001816001161561010002031660029004801561022b5780601f106102005761010080835404028352916020019161022b565b820191906000526020600020905b81548152906001019060200180831161020e57829003601f168201915b5050505050905090565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f1061027657805160ff19168380011785556102a4565b828001600101855582156102a4579182015b828111156102a3578251825591602001919060010190610288565b5b5090506102b191906102b5565b5090565b6102d791905b808211156102d35760008160009055506001016102bb565b5090565b9056fea265627a7a723158209f9d9ab8ca3378404a8af028da3bb61aa36dd8b9e4847ae0c51ce64fbb32b8b164736f6c63430005110032'
const contract = new web3.eth.Contract(abi)
const transaction = contract.deploy({data: bytecode})
web3.eth.call({
  to : account1,
  data : transaction.encodeABI()
}, function(error, result) {
  if(!error){
    console.log(result)
  }else{
    console.log(error)
  }
});
> 0x
```


# eth\_estimateGas

Estimate gas needed for execution of given contract

```
web3.eth.estimateGas(callObject [, callback])
```

#### Parameters

1. A transaction object.
2. (optional) Optional callback, returns an error object as first parameter and the result as second.

#### Returns

the used gas for the simulated call/transaction.

#### Example

```
web3.eth.estimateGas({
    from : account1,
    to : account2
}).then(console.log);
> 21000
```


# eth\_getTransaction

Get transaction by its hash

```
web3.eth.getTransaction(transactionHash [, callback])
```

#### Parameters

1. The transaction hash.
2. (optional) Optional callback, returns an error object as first parameter and the result as second.

#### Returns

A transaction object its hash `transactionHash`:

> * `hash`: Hash of the transaction.
> * `nonce`: The number of transactions made by the sender prior to this one.
> * `blockHash`: Hash of the block where this transaction was in. `null` if pending.
> * `blockNumber`: Block number where this transaction was in. `null` if pending.
> * `transactionIndex`: Integer of the transactions index position in the block. `null` if pending.
> * `from`: Address of the sender.
> * `to`: Address of the receiver. `null` if it’s a contract creation transaction.
> * `value`: Value transferred in wei.
> * `gasPrice`: Gas price provided by the sender in wei.
> * `gas` : Gas provided by the sender.
> * `input` : The data sent along with the transaction.
> * `chainId` : chain ID of the current connected node
> * `creates`
> * `piblicKey`
> * `r`: First 32 bytes of the signature
> * `raw`The RLP encoded transaction
> * `s`: Next 32 bytes of the signature
> * `standardV`
> * `v`: Recovery value + 27
>
> #### Example

> ```
> web3.eth.getTransaction('0xe4cb9e145ecefdcccdb033989cef9f371f146a6e3a884b97f4766cc9e7a9d6fe').then(console.log)
> > {
>   blockHash: '0xad92691ed2094fcd96d8b7c9afbf5f0516afe786ef3682f40c175bc3038dc04b',
>   blockNumber: 73198,
>   chainId: '0x539',
>   creates: '0x2b6c183c31235f64d954f21105fef3e451a1c57b',
>   from: '0x063eBCD1dB02320814Acc0721e65f14b8755Ff41',
>   gas: 246904,
>   gasPrice: '1000000000',
>   hash: '0xe4cb9e145ecefdcccdb033989cef9f371f146a6e3a884b97f4766cc9e7a9d6fe',
>   input: '0x608060405234801561001057600080fd5b506040518060400160405280600781526020017f6d7956616c7565000000000000000000000000000000000000000000000000008152506000908051906020019061005c929190610062565b50610107565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f106100a357805160ff19168380011785556100d1565b828001600101855582156100d1579182015b828111156100d05782518255916020019190600101906100b5565b5b5090506100de91906100e2565b5090565b61010491905b808211156101005760008160009055506001016100e8565b5090565b90565b61030f806101166000396000f3fe608060405234801561001057600080fd5b50600436106100365760003560e01c80634ed3885e1461003b5780636d4ce63c146100f6575b600080fd5b6100f46004803603602081101561005157600080fd5b810190808035906020019064010000000081111561006e57600080fd5b82018360208201111561008057600080fd5b803590602001918460018302840111640100000000831117156100a257600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f820116905080830192505050505050509192919290505050610179565b005b6100fe610193565b6040518080602001828103825283818151815260200191508051906020019080838360005b8381101561013e578082015181840152602081019050610123565b50505050905090810190601f16801561016b5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b806000908051906020019061018f929190610235565b5050565b606060008054600181600116156101000203166002900480601f01602080910402602001604051908101604052809291908181526020018280546001816001161561010002031660029004801561022b5780601f106102005761010080835404028352916020019161022b565b820191906000526020600020905b81548152906001019060200180831161020e57829003601f168201915b5050505050905090565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f1061027657805160ff19168380011785556102a4565b828001600101855582156102a4579182015b828111156102a3578251825591602001919060010190610288565b5b5090506102b191906102b5565b5090565b6102d791905b808211156102d35760008160009055506001016102bb565b5090565b9056fea265627a7a723158209f9d9ab8ca3378404a8af028da3bb61aa36dd8b9e4847ae0c51ce64fbb32b8b164736f6c63430005110032',
>   nonce: 10,
>   publicKey: '0xcddc4fbba9625085aa0facaa028c31b8d78cb554848d18c3d946328b60af60e8a77813a41bde38217bb5745c157e6bc10cd40f41358902e1b916549952f746db',
>   r: '0x5723a09fa84a50d5caa4bb995bc22cca68d1fc680bdb46f6d8e500a5e3464587',
>   raw: '0xf904790a843b9aca008303c4788080b90425608060405234801561001057600080fd5b506040518060400160405280600781526020017f6d7956616c7565000000000000000000000000000000000000000000000000008152506000908051906020019061005c929190610062565b50610107565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f106100a357805160ff19168380011785556100d1565b828001600101855582156100d1579182015b828111156100d05782518255916020019190600101906100b5565b5b5090506100de91906100e2565b5090565b61010491905b808211156101005760008160009055506001016100e8565b5090565b90565b61030f806101166000396000f3fe608060405234801561001057600080fd5b50600436106100365760003560e01c80634ed3885e1461003b5780636d4ce63c146100f6575b600080fd5b6100f46004803603602081101561005157600080fd5b810190808035906020019064010000000081111561006e57600080fd5b82018360208201111561008057600080fd5b803590602001918460018302840111640100000000831117156100a257600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f820116905080830192505050505050509192919290505050610179565b005b6100fe610193565b6040518080602001828103825283818151815260200191508051906020019080838360005b8381101561013e578082015181840152602081019050610123565b50505050905090810190601f16801561016b5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b806000908051906020019061018f929190610235565b5050565b606060008054600181600116156101000203166002900480601f01602080910402602001604051908101604052809291908181526020018280546001816001161561010002031660029004801561022b5780601f106102005761010080835404028352916020019161022b565b820191906000526020600020905b81548152906001019060200180831161020e57829003601f168201915b5050505050905090565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f1061027657805160ff19168380011785556102a4565b828001600101855582156102a4579182015b828111156102a3578251825591602001919060010190610288565b5b5090506102b191906102b5565b5090565b6102d791905b808211156102d35760008160009055506001016102bb565b5090565b9056fea265627a7a723158209f9d9ab8ca3378404a8af028da3bb61aa36dd8b9e4847ae0c51ce64fbb32b8b164736f6c63430005110032820a96a05723a09fa84a50d5caa4bb995bc22cca68d1fc680bdb46f6d8e500a5e3464587a05bd5d104e1b22f0b34f428996a22d5cd2050d14b6772bec2573c88a6ddc42d81',
>   s: '0x5bd5d104e1b22f0b34f428996a22d5cd2050d14b6772bec2573c88a6ddc42d81',
>   standardV: '0x1',
>   to: null,
>   transactionIndex: 0,
>   v: '0xa96',
>   value: '0'
> }
> ```


# eth\_getTransactionByBlockHashAndIndex

Returns a transaction based on a block hash and the transaction’s index position.

```
web3.eth.getTransactionByBlockHashAndIndex(BlockHash, indexNumber [, callback])
```

#### Parameters

1. A block hash .
2. The transaction’s index position.
3. Optional callback, returns an error object as first parameter and the result as second.

#### Returns

A transaction object its hash `transactionHash`:

> * `hash` : Hash of the transaction.
> * `nonce`: The number of transactions made by the sender prior to this one.
> * `blockHash`: Hash of the block where this transaction was in. `null` if pending.
> * `blockNumber`: Block number where this transaction was in. `null` if pending.
> * `transactionIndex`: Integer of the transactions index position in the block. `null` if pending.
> * `from`: Address of the sender.
> * `to`: Address of the receiver. `null` if it’s a contract creation transaction.
> * `value`: Value transferred in wei.
> * `gasPrice`: Gas price provided by the sender in wei.
> * `gas`: Gas provided by the sender.
> * `input` : The data sent along with the transaction.

#### Example

```
web3.eth.getTransactionByBlockHashAndIndex("0xfb8d7ee8fb5f4fbebf41a55caa5e988a480a0ce277813cd1ec4443c54f601ddd",0).then(console.log)
> {
    "blockHash":"0xfb8d7ee8fb5f4fbebf41a55caa5e988a480a0ce277813cd1ec4443c54f601ddd",
    "blockNumber":"0x8",
    "chainId":"0x539",
    "creates":null,
    "from":"0xe6206c7f064c7d77c6d8e3ed8601c9aa435419ce",
    "gas":"0x5208",
    "gasPrice":"0x3b9aca00",
    "hash":"0x7893da51d25cad2c10ab946e5b770a21a99b9c9ccff8f595f8222dd9f2e2013b",
    "input":"0x",
    "nonce":"0x0",
    "publicKey":"0x8c9a51a90433508cec6ce29b993284a0e8d0835b38d3ced62216800db588a6d55fa2c114fab798977763ffe94a03b1a591c48d972d4daa6ba7810c80528644f4",
    "r":"0x8f59b2e2a2a07e82067fea3903402a30e7a78176e50827678075271decd19179",
    "raw":"0xf86e80843b9aca00825208942193517101eb10ef22f2fa67ef452f66c51839d3896c6b935b8bbd40000080820a96a08f59b2e2a2a07e82067fea3903402a30e7a78176e50827678075271decd19179a01d0c193a99e5ecce21a40ff18e20e0bf4e1751e5308b3e09acc42d0a53b4b3d7",
    "s":"0x1d0c193a99e5ecce21a40ff18e20e0bf4e1751e5308b3e09acc42d0a53b4b3d7",
    "standardV":"0x1","to":"0x2193517101eb10ef22f2fa67ef452f66c51839d3",
    "transactionIndex":"0x0",
    "v":"0xa96",
    "value":"0x6c6b935b8bbd400000"
    }
```


# eth\_getTransactionByBlockNumberAndIndex

Returns a transaction based on a block number and the transaction’s index position.

```
web3.eth.getTransactionByBlockNumberAndIndex(BlockNumber, indexNumber [, callback])
```

#### Parameters

1. A block number .
2. The transaction’s index position.
3. Optional callback, returns an error object as first parameter and the result as second.

#### Returns

A transaction object its hash `transactionHash`:

> * `hash` : Hash of the transaction.
> * `nonce`: The number of transactions made by the sender prior to this one.
> * `blockHash`: Hash of the block where this transaction was in. `null` if pending.
> * `blockNumber`: Block number where this transaction was in. `null` if pending.
> * `transactionIndex`: Integer of the transactions index position in the block. `null` if pending.
> * `from`: Address of the sender.
> * `to`: Address of the receiver. `null` if it’s a contract creation transaction.
> * `value`: Value transferred in wei.
> * `gasPrice`: Gas price provided by the sender in wei.
> * `gas`: Gas provided by the sender.
> * `input` : The data sent along with the transaction.

#### Example

```
web3.eth.getTransactionByBlockNumberAndIndex("0x8",0).then(console.log)
> {
    "blockHash":"0xfb8d7ee8fb5f4fbebf41a55caa5e988a480a0ce277813cd1ec4443c54f601ddd",
    "blockNumber":"0x8",
    "chainId":"0x539",
    "creates":null,
    "from":"0xe6206c7f064c7d77c6d8e3ed8601c9aa435419ce",
    "gas":"0x5208",
    "gasPrice":"0x3b9aca00",
    "hash":"0x7893da51d25cad2c10ab946e5b770a21a99b9c9ccff8f595f8222dd9f2e2013b",
    "input":"0x",
    "nonce":"0x0",
    "publicKey":"0x8c9a51a90433508cec6ce29b993284a0e8d0835b38d3ced62216800db588a6d55fa2c114fab798977763ffe94a03b1a591c48d972d4daa6ba7810c80528644f4",
    "r":"0x8f59b2e2a2a07e82067fea3903402a30e7a78176e50827678075271decd19179",
    "raw":"0xf86e80843b9aca00825208942193517101eb10ef22f2fa67ef452f66c51839d3896c6b935b8bbd40000080820a96a08f59b2e2a2a07e82067fea3903402a30e7a78176e50827678075271decd19179a01d0c193a99e5ecce21a40ff18e20e0bf4e1751e5308b3e09acc42d0a53b4b3d7",
    "s":"0x1d0c193a99e5ecce21a40ff18e20e0bf4e1751e5308b3e09acc42d0a53b4b3d7",
    "standardV":"0x1","to":"0x2193517101eb10ef22f2fa67ef452f66c51839d3",
    "transactionIndex":"0x0",
    "v":"0xa96",
    "value":"0x6c6b935b8bbd400000"
    }
```


# eth\_getTransactionReceipt

Returns transaction receipt by transaction hash

```
web3.eth.getTransactionReceipt(hash [, callback])
```

#### Parameters

1. The transaction hash.
2. (optional) Optional callback, returns an error object as first parameter and the result as second.

#### Returns

&#x20;A transaction receipt object, or `null` if no receipt was found:

> * `status`: `TRUE` if the transaction was successful, `FALSE` if the EVM reverted the transaction.
> * `blockHash`: Hash of the block where this transaction was in.
> * `blockNumber`: Block number where this transaction was in.
> * `transactionHash`: Hash of the transaction.
> * `transactionIndex`: Integer of the transactions index position in the block.
> * `from`: Address of the sender.
> * `to`: Address of the receiver. `null` when it’s a contract creation transaction.
> * `contractAddress`: The contract address created, if the transaction was a contract creation, otherwise `null`.
> * `cumulativeGasUsed`: The total amount of gas used when this transaction was executed in the block.
> * `gasUsed`: The amount of gas used by this specific transaction alone.
> * `logs`: Array of log objects, which this transaction generated.
> * `internalTransactions`:
> * `logsBloom`:
>
> #### Example

> ```
> web3.eth.getTransactionReceipt('0x6d7d750cea87c11ade7852ce02a0a10617f1877995591057f99f66c4d9a350a3').then(console.log)
> > {
>   blockHash: '0x79275dcda076bd6d07774318ae7cd74b9f7141b4e6242b1501b2ca25edb35684',
>   blockNumber: 54550,
>   contractAddress: null,
>   cumulativeGasUsed: 21000,
>   from: '0x063ebcd1db02320814acc0721e65f14b8755ff41',
>   gasUsed: 21000,
>   internalTransactions: [
>     {
>       developer: null,
>       developerReward: null,
>       from: '0x063ebcd1db02320814acc0721e65f14b8755ff41',
>       gasUsed: '0x0',
>       to: '0x69d8fa34508c43c8533a32ab278addde2820556b'
>     }
>   ],
>   logs: [],
>   logsBloom: '0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000',
>   status: true,
>   to: '0x69d8fa34508c43c8533a32ab278addde2820556b',
>   transactionHash: '0x6d7d750cea87c11ade7852ce02a0a10617f1877995591057f99f66c4d9a350a3',
>   transactionIndex: 0
> }
> ```
>
> ####


# eth\_getUncle

Returns an uncles at given block and index

```
web3.eth.getUncle(blockHashOrBlockNumber, uncleIndex [, returnTransactionObjects] [, callback])
```

#### Parameters

1. The block number or hash. Or the string `"earliest"`, `"latest"` or `"pending"` as in the [default block parameter](https://web3js.readthedocs.io/en/v1.3.0/web3-eth.html#eth-defaultblock).
2. The index position of the uncle.
3. (optional, default `false`) If specified `true`, the returned block will contain all transactions as objects. By default it is `false` so, there is no need to explictly specify false. And, if `false` it will only contains the transaction hashes.
4. &#x20;(optional) Optional callback, returns an error object as first parameter and the result as second.

#### Returns

the returned uncle

```
```


# eth\_getLogs

Returns logs matching given filter object


# eth\_getWork

Returns the hash of the current block, the seedHash, and the boundary condition to be met

```
web3.eth.getWork([callback])
```

#### Parameters

1. (optional) Optional callback, returns an error object as first parameter and the result as second.

#### Returns

&#x20;the mining work with the following structure:

> * current block header pow-hash
> * the seed hash used for the DAG.
> * the boundary condition (“target”), 2^256 / difficulty.
>
> #### Example

```
web3.eth.getWork().then(console.log)
> [
  '0x0000000000000000000000000000000000000000000000000000000000000000',
  '0x0000000000000000000000000000000000000000000000000000000000000000',
  '0x0000000000000000000000000000000000000000000000000000000000000000'
]
```


# eth\_submitWork

Used for submitting a proof-of-work solution


# eth\_submitHashrate

Used for submitting mining hashrate


# eth\_subscribe

Subscribe to Eth subscription


# eth\_unsubscribe

Unsubscribe from existing Eth subscription


# net\_version

Returns the current network id

```
web3.net.version
```

**Parameters**

none

**Returns**

The current network id.

**Example**

```
var version = web3.net.version;
console.log(version);
> 1023
```


# net\_peerCount

Returns number of peers connected to node

```
web3.net.peerCount
```

#### Parameters

none

#### Returns

The number of other Ethereum nodes connected to the node.

#### Example

```
var peerCount = web3.net.peerCount;
console.log(peerCount);
> 5
```


# net\_listening

Returns true if client is actively listening for network connections. Otherwise false

```
web3.eth.net.Listening
```

#### Parameters

none

#### Returns

returns `Boolean：`that the connected node is listening for network requests.

#### Example

```
const Listening = web3.net.Listening
console.log(Listening);
> true
```


# web3\_clientVersion

Returns current client version

```
web3.clientVersion
```

#### Returns

The current version.

#### Example

```
const clientVersion = web3.clientVersion
console.log(clientVersion)
> clover/v11.1/fc-rpc-0.1.0-clover
```


# web3\_sha3

Returns sha3 of the given data

```
web3.sha3(SHA3hash)
```

**Parameters**

the data to convert into a SHA3 hash

**Returns**

The SHA3 result of the given string

**Example**

```
const sha3 = web3.sha3("0x68656c6c6f20776f726c64");
console.log(sha3)
> 0x47173285a8d7341e5e972fc677286384f802f8ef42a5ec5f03bbfa254cb01fad
```


# CLV P-Chain Integration

## Evm Chain Information

Clover P-Chain is an EVM-compatible network which means ecosystem partners can use the standard web3 protocol to integrate with CLV P-Chain.

The Chain Id of CLV P-Chain is **1024 (0x400 in hex)**. &#x20;

The minimum accepted gas price is **50 Gwei** currently, please make sure to the  gas price is no less than **50Gwei** to send a transaction.&#x20;

## Public RPC endpoints <a href="#public-rpc-endpoints" id="public-rpc-endpoints"></a>

Below are a list of public RPC endpoints for CLV P-Chain.

| Provider       | RPC URL                            |
| -------------- | ---------------------------------- |
| CLV foundation | <https://api-para.clover.finance/> |
| OnFinality     | TBD                                |

## Self-hosted RPC nodes

### Hardware requirements

| Hardware | Recommended |
| -------- | ----------- |
| CPU      | 16C         |
| Memory   | 32G         |
| Disk     | 500G ssd    |
| Network  | 20Mbps      |

### Configuration

CLV provides a docker image to help setting up a self-hosted rpc node. Below is a sample compose file for reference(which uses the **20194** port as the rpc port.)

```yaml
version: "3.3"
services:  clover-bootnode:
    image: "cloverio/clover-para:polkadot-v0.9.16.1"
    restart: always
    command:
      - /opt/clover/bin/clover
      - --parachain-id
      - "2002"
      - --chain
      -  /opt/specs/clover-para-raw.json
      - --base-path
      - /opt/chaindata
      - --bootnodes
      - /dns/boot1.para.clover.finance/tcp/40335/ws/p2p/12D3KooWFWYYwimRBexvZokZmNnmSdXcLCz8WmMTHDCAhzm5tLM6
      - /dns/boot2.para.clover.finance/tcp/40335/ws/p2p/12D3KooWSvvxYi9nkyGJ17hEjwmytNRMrSsQtSrGsHzUaLTcUUea
      - --pruning
      - 2000   # adjust the max blocks to keep, use "archive" if you want keep all blocks
      - --ws-port
      - "9946"
      - --rpc-port
      - "20194"
      - --port
      - "40335"
      - "--rpc-cors=all"
      - --rpc-external
      - --ws-external
      - --ethapi
      - debug,trace
      - --execution
      - wasm
      - --max-runtime-instances
      - "128"
      - --ws-max-connections
      - "5000"
      - --
      - --execution
      - wasm
      - --ws-port
      - "10194"
      - --rpc-port
      - "10195"
      - --chain
      - polkadot
      - --port
      - "30335"
    ports:
      - "9946:9946"
      - "20194:20194"
      - "40335:40335"
      - "30335:30335"
    volumes:
      - /data/data/chains/bootnode:/opt/chaindata
      - /data/data/config:/opt/config
    logging:
       driver: "json-file"
       options:
          max-size: "25m"
          max-file: "2"
```


# EVM dApp Integration

### Integrated with JS

CLV Extension Wallet injected into web pages a varible, which named 'clover'. DApp developer could integrate with the wallet with window\.clover. Below snippet shows how to use it to interact between dapp and the wallet.

```javascript
const example = async () => {
    // connect to wallet and get accounts
    const accounts = await window.clover.request({ method: 'eth_requestAccounts' })
    
    // the first account is the selected account
    const currAccount = accounts[0]
        
    // get chain id
    const chainId = await window.clover.request({ method: 'eth_chainId' });
    
    const transactionParameters = {
        nonce: '0x05',
        gasPrice: '0x3e95ba80', // could set by user
        gas: '0x2710', // could set by user
        to: '0x66cb476bdbd6b55804644072255a1156e6977b23',
        from: currAccount,
        value: '0x2386f26fc10000',
        chainId: chainId,
    };
    
    const txHash = await window.clover.request({
      method: 'eth_sendTransaction',
      params: [transactionParameters],
    });
}

const handleAccountsChanged = async (accounts) => {
    // here could set current account with accounts[0]
}
window.clover.on('accountsChanged', handleAccountsChanged);

const handleChainChanged = async (chainId) => {
  // do something when chain changed
}
window.clover.on('chainChanged', handleChainChanged)

```

CLV Extension Wallet supports dApp to add custom EVM chain and will support to switch to specified EVM Chain(from version 5.6.0 which will release soon). Below sample code shows how dApp to do these two operations.

```javascript
// Add custom EVM chain, if the chain exists in wallet, it will switch to the chain.
if (window.clover) {
  try {
    await window.clover.request({
    method: 'wallet_addEthereumChain',
    params: [
      {
        chainId: '0x400',
        chainName: 'CLV ParaChain',
        nativeCurrency: {
            name: 'CLV',
            symbol: 'CLV',
            decimals: 18,
        },
        rpcUrls: ['https://api-para.clover.finance'],
        blockExplorerUrls: ['https://clvscan.com/'],
      },
    ]})
    return true
  } catch (error) {
  }
}

// Switch to specific EVM chain, if the chain does not exist in wallet yet, it 
// will throw error 4902
if (window.clover) {
  try {
    await window.clover.request({
      method: 'wallet_switchEthereumChain',
      params: [{ chainId: '0x400' }], // chainId must be in hexadecimal numbers
    });
  } catch (error) {
    if (error.code === 4902) {
      // could add chain here
    }
  }
}
```

### Integrated with web3-react

First, install clover connector as dependency to your project:

```javascript
npm i @clover-network/clover-connector
or 
yarn add @clover-network/clover-connector
```

Second, Web3ReactProvider and getLibrary should be used as provider as below:

```javascript
<Web3ReactProvider getLibrary={getLibrary}>
    {/* <...> */}
</Web3ReactProvider>

```

Then, initialize cloverConnector, which could be used as connector to connect to Clover Extension Wallet.

```javascript
const cloverConnector = new CloverConnector({ supportedChainIds: [1, 3] })
```

At last, we could use cloverConnector to connect to and communicate with the wallet

```javascript
const { activate, deactivate, library, account, error } = useWeb3React()

useEffect(() => {
    activate(cloverConnector, async (error) => {
        if (error instanceof UnsupportedChainIdError) {
            setToast('error', 'Unsupported chain id')
        } else {
            if (error instanceof NoEthereumProviderError) {
                setToast('error', 'No provider was found')
            } else if (
                error instanceof UserRejectedRequestErrorInjected
            ) {
                setToast('error', 'Please authorize to access your account')
            } else {
                setToast('error', error.message)
            }
        }
    })
}, [activate])

useEffect(() => {
    const send = async () => {
        if (account !== undefined) {
            const chainId = '0x3';
    
            const transaction = {
                nonce: '0x05',
                to: account,
                from: account,
                value: '0x2386f26fc10000',
                chainId: chainId,
            };
            
            const txHash = await library.request({
              method: 'eth_sendTransaction',
              params: [transaction],
            });
        }
    }
    send()
}, [account, library])

```


# Substrate dApp Integration

CLV Extension Wallet uses method '**injectExtension**' of **@polkadot/extension-inject** to inject an object into dApp's web page, and dApp can invoke the wallet by calling web3Enable(). The sample code is as follows:

```typescript
import { web3Accounts, web3Enable } from '@polkadot/extension-dapp';

// find clover extension wallet injector
const findCloverInjected = async () => {
  const injected = await web3Enable('clv');
  if (!injected.length) {
    return {
      message: "Not found wallet",
      status: 'error'
    };
  }

  const cloverInjector = injected.find(injected, (w) => isCloverWallet(w))
  return cloverInjector
}

// sign message
const polkadotSignMessage = async () => {
    const polkadotAddress = await web3Accounts({ ss58Format: 42 });
    const wrapped = u8aWrapBytes(polkadotAddress.toLowerCase());
    const ret = await currentInjected.signer.signRaw({
      data: u8aToHex(wrapped),
      address: polkadotAddress,
      type: "bytes",
    });
  }
  
// send transaction
polkadotSignTransaction = async () => {
  const wsProvider = new WsProvider('wss://rpc.polkadot.io');
  const api = await ApiPromise.create({provider: wsProvider});
  const polkadotAddress = await web3Accounts({ ss58Format: 42 });
  const currentClvAccount = polkadotAddress
  const injected = await web3FromAddress(currentClvAccount)
  api.setSigner(injected.signer)
  const unsub = await api.tx.balances
    .transfer(currentClvAccount, 0)
    .signAndSend(currentClvAccount, (result) => {

      if (result.status.isInBlock) {
        // in block
      } else if (result.status.isFinalized) {
        unsub();
      }
    })
  }
```


# Solana dApp Integration

Once CLV extension wallet is installed, it will inject the following to window object:

```
window.clover_solana = {
    isCloverWallet: true,
    getAccount: async() => {...}
    signTransaction: async (paload) => {...}
}
```

dApps can use the above injected object to integrate with CLV extension wallet.

## dApp Development Documents

### RPC document

<https://docs.solana.com/>

### Wallet Adapter API (lib for communicating with web wallet or extension)

{% embed url="<https://github.com/project-serum/sol-wallet-adapter>" %}

### Web3 JS (create transactions in frontend)

{% embed url="<https://github.com/solana-labs/solana-web3.js>" %}


# Kadena dApp Integration

CLV extension wallet will inject clover\_kadena to window object, dApp could use it to integrate with CLV extension wallet.

```
window.clover_kadena = {
  isCloverWallet: true,
  getAccount: async ()=> {...},
  sign: async (paload) => {...}
}
```

## Sample Code

Below is an example for dApp to integrate CLV extension wallet

```
signKdaTransaction = async () => {
    if (!window.clover_kadena) {
      this.console('wallet not injected!')
    }

    var mkReq = function(cmd) {
      return {
        headers: {
          "Content-Type": "application/json"
        },
        method: "POST",
        body: JSON.stringify(cmd)
      };
    };

    try {
      const account = await window.clover_kadena.getAccount()
      await new Promise((resolve) => setTimeout(resolve, 3000))
      const signCmd = {
        pactCode: `(free.hello-world.set-message ${JSON.stringify('hello test')})`,
        caps: [
          Pact.lang.mkCap("Gas capability", "description of gas cap", "coin.GAS", []).cap,
        ],
        sender: account,
        gasLimit: 10000,
        chainId: "0",
        ttl: 28800,
        envData: {}
      }

      const result = await window.clover_kadena.sign(signCmd)
      const txRes = await fetch(`https://api.testnet.chainweb.com/chainweb/0.0/testnet04/chain/0/pact/api/v1/send`, mkReq(result));
      const tx = await txRes.json();
    } catch (e) {
      console.log(e)
    }
  }
```


# Aptos dApp Integration

## Install CLV Wallet

To use CLV Wallet for your Aptos dApp, your users need to install [CLV Wallet Chrome extension](https://chrome.google.com/webstore/detail/clv-wallet/nhnkbkgjikgcigadomkphalanndcapjk) in their browser. CLV Wallet injects an <mark style="color:blue;">clover\_aptos</mark> object into the [window](https://developer.mozilla.org/en-US/docs/Web/API/Window) of any dApp that the user visits.

To check whether the user has installed CLV Wallet, please use the following check:

```javascript
const isCLVInstalled = window.clover_aptos
```

If CLV Wallet is not installed, you can navigate user to install CLV Wallet first. For example

<pre class="language-javascript"><code class="lang-javascript">const getCLVWallet = () => {
    if ('clover_aptos' in window) {
        return window.clover_aptos;
    } else {
        window.open('https://clv.org/?type=wallet', `_blank`);
    }
<strong>}
</strong></code></pre>

## Connect to CLV Wallet

After <mark style="color:blue;">clover\_aptos</mark> object is injected into the dApp, we can connect to CLV Wallet by calling <mark style="color:blue;">wallet.connect()</mark>. When this function is called, it will prompt user a dialog to approve or reject the interactions between your web app and CLV Wallet. Once connection is approved, you can easily get user's current wallet address. Sample code:

```javascript
const wallet = getCLVWallet();
try {
    const response = await wallet.connect();
    console.log(response); // { address: string, publicKey: string }

    const account = await wallet.account();
    console.log(account); // { address: string, publicKey: string }
} catch (error) {
    // { code: 500, message: "The request was cancelled."}
}
```

## Disconnect CLV Wallet

If you want the dApp to disconnect from CLV Wallet, you should just call <mark style="color:blue;">wallet.disconnect()</mark>.&#x20;

```javascript
await wallet.disconnect();
```

## Transaction Signing

Once your dApp is connected with CLV Wallet, it can prompt to user to sign and send transactions to the Aptos blockchain.

### Case 1: Sign and Submit

```javascript
const wallet = getCLVWallet();

const transaction = {
    arguments: [address, '1'],
    function: '0x1::coin::transfer',
    type: 'entry_function_payload',
    type_arguments: ['0x1::aptos_coin::MyCoin'],
};

try {
    const tx = await wallet.signAndSubmitTransaction(transaction);
    console.log(tx.hash); // this is the transaction hash
    
    return tx;
} catch (error) {
    // see "Errors"
}
```

### Case 2: Sign only

```javascript
const wallet = getAptosWallet(); // see "Connecting"

// Example Transaction
const transaction = {
    arguments: [address, '1'],
    function: '0x1::coin::transfer',
    type: 'entry_function_payload',
    type_arguments: ['0x1::aptos_coin::MyCoin'],
};

try {
    const signTransaction = await wallet.signTransaction(transaction);
    console.log(signTransaction); // Uint8Arry for signed transaction
} catch (error) {
    // see "Errors"
}
```

## Message Signing

A dApp can call <mark style="color:blue;">wallet.signMessage(payload: SignMessagePayload)</mark> to sign a message using CLV Wallet.

The above function call will return <mark style="color:blue;">Promise\<SignMessageResponse></mark>. Types info are:

```javascript
export interface SignMessagePayload {
  address?: boolean; // Should we include the address of the account in the message
  application?: boolean; // Should we include the domain of the dapp
  chainId?: boolean; // Should we include the current chain id the wallet is connected to
  message: string; // The message to be signed and displayed to the user
  nonce: string; // A nonce the dapp should generate
}

export interface SignMessageResponse {
  address: string;
  application: string;
  chainId: number;
  fullMessage: string; // The message that was generated to sign
  message: string; // The message passed in by the user
  nonce: string,
  prefix: string, // Should always be APTOS
  signature: string; // The signed full message
}
```

### Example message and response

```javascript
signMessage({nonce: 1234, message: "Welcome to CLV Wallet!" });
```

The above would generate a full message to be signed and returned as the signature:

```json
APTOS
nonce: 1234
message: Welcome to CLV Wallet!
```

### Signature Verifying

```javascript
import nacl from 'tweetnacl';

const message = "hello";
const nonce = "random_string"

try {
  const response = await window.clover_aptos.signMessage({
    message,
    nonce,
  });
  const { publicKey } = await window.clover_aptos.account();
  // Remove the 0x prefix
  const key = publicKey!.slice(2, 66);
  const verified = nacl.sign.detached.verify(
    Buffer.from(response.fullMessage), 
    Buffer.from(response.signature, 'hex'), 
    Buffer.from(key, 'hex')
  );
  console.log(verified);
} catch (error) {
  console.error(error);
}
```


# Web Wallet dApp Integration

dApps can easily integrate CLV Web Wallet for transaction & message signing. The SDK **@clover-network/web-wallet-sdk** is needed for the integration.

The SDK can be installed as follows:

```shell
yarn add @clover-network/web-wallet-sdk
```

### Substrate Blockchains Integration

CLV web wallet supports dApps on substrate-based blockchains, such as Polkadot, Kusama, Acala, etc.  The sample code is as follows:

```typescript
import CloverWebInjected from '@clover-network/web-wallet-sdk';
import { web3Enable, web3Accounts, web3FromAddress } from "@polkadot/extension-dapp";

const clvInject = new CloverWebInjected({ zIndex: 99999 });

const initInjector = async () => {
    await clvInject.init({
      network: {
        chainId: '0x1',
      },
      enableLogging: true,
    });
    
    await clvInject.polkadotLogin(); // After this success, the injector has been injected into web page
    const injected: any = await web3Enable('clv'); // injector could be get in standard way
}

// sign message
const polkadotSignMessage = async () => {
    const polkadotAddress = await web3Accounts({ ss58Format: 42 });
    const wrapped = u8aWrapBytes(polkadotAddress.toLowerCase());
    const ret = await currentInjected.signer.signRaw({
      data: u8aToHex(wrapped),
      address: polkadotAddress,
      type: "bytes",
    });
  }
  
// send transaction
polkadotSignTransaction = async () => {
  const wsProvider = new WsProvider('wss://rpc.polkadot.io');
  const api = await ApiPromise.create({provider: wsProvider});
  const polkadotAddress = await web3Accounts({ ss58Format: 42 });
  const currentClvAccount = polkadotAddress
  const injected = await web3FromAddress(currentClvAccount)
  api.setSigner(injected.signer)
  const unsub = await api.tx.balances
    .transfer(currentClvAccount, 0)
    .signAndSend(currentClvAccount, (result) => {

      if (result.status.isInBlock) {
        // in block
      } else if (result.status.isFinalized) {
        unsub();
      }
    })
  }

```

### EVM Blockchains Integration

CLV web wallet supports dApps on EVM blockchains, such as Ethereum, CLV Parachain (P-Chain), Moonbeam and etc. The sample code is as follows:

```typescript
import CloverWebInjected from '@clover-network/web-wallet-sdk';

const clvInject = new CloverWebInjected({ zIndex: 99999 });

const initInjector = async () => {
    await clvInject.init({
      network: {
        chainId: '0x1',
      },
      enableLogging: true,
    });
    
    await clvInject.login();
    clvInject.provider.on('accountsChanged', (accounts) => {
      // do something
    });
}tye

// send transaction
const send = (): void => {
  const web3 = new Web3(clvInject.provider)
  const accounts = await web3.eth.getAccounts();
  const publicAddress = accounts[0]
  web3.eth.sendTransaction({ 
      from: publicAddress, 
      to: publicAddress, 
      value: web3.utils.toWei('0.01') 
    })
}

// eth_sign
const signMessage = (): void => {
  const web3 = new Web3(clvInject.provider)
  const accounts = await web3.eth.getAccounts();
  const publicAddress = accounts[0]
  // hex message
  const message = '0x000000000000000000000000000000000000';
  web3.currentProvider.send(
    {
      method: 'eth_sign',
      params: [publicAddress, message],
      jsonrpc: '2.0',
    },
    (err: Error, result: any) => {
      // error handle
    },
  );
}

// personal message
const signPersonalMsg = async () => {
    try {
      const web3 = new Web3(clvInject.provider)
      const accounts = await web3.eth.getAccounts();
      const publicAddress = accounts[0]
      const message = 'Example';
      const hash = web3.utils.sha3(message);
      const sig = await web3.eth.personal.sign(hash, publicAddress, '');
    } catch (error) {
      //error
    }
  }

// eth_signTypedData, eth_signTypedData_v3, eth_signTypedData_v4 are also supported

```

### Solana Blockchain Integration

CLV web wallet supports dApps on Solana. The sample code is as follows:

```typescript
import CloverWebInjected from '@clover-network/web-wallet-sdk';

const clvInject = new CloverWebInjected({ zIndex: 99999 });

const initInjector = async () => {
  await clvInject.init({
    network: {
      chainId: '0x1',
    },
    enableLogging: true,
  });
  
  await clvInject.solLogin();
}

const sendSolana = async () => {
  const solAddress = await clvInject.clover_solana.getAccount();
  const connection = new solanaWeb3.Connection(
    solanaWeb3.clusterApiUrl('mainnet-beta'),
    'confirmed',
  );
  const fromPubkey = new solanaWeb3.PublicKey(solAddress);
  const toPubkey = new solanaWeb3.PublicKey(solAddress);
  const transaction = new solanaWeb3.Transaction().add(
    solanaWeb3.SystemProgram.transfer({
      fromPubkey: fromPubkey,
      toPubkey: toPubkey,
      lamports: solanaWeb3.LAMPORTS_PER_SOL * 0,
    }),
  );

  const block = await connection.getRecentBlockhash('max');
  transaction.recentBlockhash = block.blockhash;
  transaction.setSigners(fromPubkey);

  const sss = await clvInject.clover_solana.signTransaction(transaction);
  const rawTransaction = sss.serialize();
  const a = await connection.sendRawTransaction(rawTransaction, {
    skipPreflight: false,
    preflightCommitment: 'single',
  });

  this.console('transaction hash:' + a);
}

const sendSolanaAll = async () => {
  const solAddress = await clvInject.clover_solana.getAccount();
  const connection = new solanaWeb3.Connection(
    solanaWeb3.clusterApiUrl('mainnet-beta'),
    'confirmed',
  );
  const fromPubkey = new solanaWeb3.PublicKey(solAddress);
  const toPubkey = new solanaWeb3.PublicKey(solAddress);
  const transaction = new solanaWeb3.Transaction().add(
    solanaWeb3.SystemProgram.transfer({
      fromPubkey: fromPubkey,
      toPubkey: toPubkey,
      lamports: solanaWeb3.LAMPORTS_PER_SOL * 0,
    }),
  );

  const block = await connection.getRecentBlockhash('max');
  transaction.recentBlockhash = block.blockhash;
  transaction.setSigners(fromPubkey);

  const sss = await clvInject.clover_solana.signAllTransactions([transaction]);
  const rawTransaction = sss[0].serialize();
  const a = await connection.sendRawTransaction(rawTransaction, {
    skipPreflight: false,
    preflightCommitment: 'single',
  });

  this.console('transaction hash:' + a);
}

```


# dApp Interaction Protocol

CLV extension wallet implemented  a brand-new dApp interaction protocol, it can support multiple active blockchains. dApps can use the above protocol to interact with different blockchains, **without the need to switch between them!**

## Demo

In order to show how CLV extension wallet interacts with multiple active blockchains, we build a demo at: <https://wallet-demo.clover.finance/>

![](/files/-MeXr2kFNhzDH5I0vSgt)

### 1. Install CLV Extension Wallet

In order to play with the demo, you need to install CLV extension wallet, and make sure the version is above **2.5.0**. Then connect with your wallet:

![Connect to your wallet](/files/-MeY0c_TNpXqNcRMUh8W)

### 2. Sign Message with Different Blockchains

You can click "Sign with Ethereum", it will invoke CLV intension wallet to interact with Ethereum chain:

![Sign with Ethereum](/files/-MeY15WjhpJf5hABYpJL)

You can click "Sign with BSC", it will invoke CLV intension wallet to interact with BSC:

![Sign with BSC](/files/-MeY1Qa4Lgbe9MfwuSNB)

You can click "Sign with Polkadot", it will invoke CLV intension wallet to interact with Polkadot:

![Sign with Polkadot](/files/-MeY2Grh9bi06jS6K0cP)

## Github

Please refer to our the code repo of the demo: <https://github.com/clover-network/clover-multichain-wallet-demo>


# Wallet Integration QA

## Asset Integration

if you need your blockchain assets supported by CLV Wallet, please provide the javascript SDK for your blockchain. For example:

| Assets | SDK             | Description |
| ------ | --------------- | ----------- |
| DOT    | @polkadot/api   |             |
| SOL    | @solana/web3.js |             |
| ...    |                 |             |

If your chain is EVM compatible, you only need to provide the following information:

* Chain ID
* Chain RPC
* Native Token Symbol
* Native Token Decimal

## dApp Integration

If your dApp is a Solana dApp, please refer to the following integration demo:

{% embed url="<https://github.com/Bonfida/audaces-perps-ui/pull/5/commits/7a31c4004dda4dce9cbcdd11c84c0a90e159550e>" %}

If your dApp is a EVM compatible dApp, please refer to the following integration demo:

{% embed url="<https://github.com/sushiswap/sushiswap-interface/pull/401/commits/aba48d0650813f349f08e8ca61067b15ff2b0f3f>" %}


# 🏞️  Ecosystem Partners


# CLV Chain

### DEX & Lending

SeasonSwap - <https://www.seasonswap.com/>




---

[Next Page](/llms-full.txt/1)

