CLV Documentations
CLV DOC
CLV DOC
  • Intro to CLV
    • About CLV πŸ€
    • Clover Finance Rebrands to CLV
    • What is CLV Chain?
    • What is CLV Wallet?
    • What is $CLV Token?
    • πŸ“£ CLV Official Channels
    • 🏘 CLV Community Channels
  • Use CLV Chain
    • πŸ“š Beginner’s Guide
      • Setup CLV Wallet
      • Setup Metamask Wallet
      • How to Get $CLV
      • Bridge Other Assets to CLV P-Chain (Parachain)
    • 🌐 Network Details
    • 🏦 Economics
      • Tokenomics
      • Inflation Design
    • πŸ—³οΈGovernance
    • πŸ™‹πŸ» CLV Chain FAQ
    • CLV P-Chain EVM Explorer
    • $CLV Cross-Chain Explorer
    • $CLV Cross-Chain Transfer
  • CLV Validator & Staking
    • What are Nominator & Validator?
    • Stake as a Nominator
    • Running a Validator or RPC Node
    • Staking FAQ
  • Use CLV Wallet
    • πŸ’° Download CLV Wallet
      • Browser Extension (Google Chrome & Brave)
      • Apple iOS (Mobile)
      • Android (Mobile)
      • Web Wallet (Universal)
    • πŸ“± CLV Mobile Wallet
    • πŸ–₯ CLV Extension Wallet
    • πŸ•ΈοΈ CLV Web Wallet
  • CLV Chain Developer Guide
    • Getting Started
    • Using Local Node
      • Using MetaMask
      • Using Remix
      • Using Web3.js
    • Using Testnet
      • Create an account
      • Faucet
      • Run a Testnet Node
      • Connect to Testnet
    • dApp Example
      • Setup dApp project
      • Setup truffle
      • The Counter Contract
      • Deploy Contract
      • Counter Webapp
    • Test Cases
    • Technical Documentations
      • CLV EVM
      • Developers Incentive
      • CLV Accounts Binding
      • Virtual Ethereum Address Binding
      • Query Balance
      • Transaction Finality
      • Web3 Compatibility
        • eth_protocolVersion
        • eth_syncing
        • eth_hashrate
        • eth_coinbase
        • eth_mining
        • eth_chainId
        • eth_gasPrice
        • eth_accounts
        • eth_blockNumber
        • eth_getBalance
        • eth_getStorageAt
        • eth_getBlock
        • eth_getTransactionCount
        • eth_getBlockTransactionCount
        • eth_getBlockUncleCount
        • eth_getCode
        • eth_sendTransaction
        • eth_sendSignedTransaction
        • eth_call
        • eth_estimateGas
        • eth_getTransaction
        • eth_getTransactionByBlockHashAndIndex
        • eth_getTransactionByBlockNumberAndIndex
        • eth_getTransactionReceipt
        • eth_getUncle
        • eth_getLogs
        • eth_getWork
        • eth_submitWork
        • eth_submitHashrate
        • eth_subscribe
        • eth_unsubscribe
        • net_version
        • net_peerCount
        • net_listening
        • web3_clientVersion
        • web3_sha3
      • CLV P-Chain Integration
  • CLV Wallet Developer Guide
    • EVM dApp Integration
    • Substrate dApp Integration
    • Solana dApp Integration
    • Kadena dApp Integration
    • Aptos dApp Integration
    • Web Wallet dApp Integration
    • dApp Interaction Protocol
    • Wallet Integration QA
  • CLV Ecosystem
    • 🏞️ Ecosystem Partners
      • CLV Chain
      • CLV Wallet
    • 🌱 Incentive Programs
      • CLV Ecosystem Grant
      • CLV Wallet Integration Grant
      • CLV Bug Bounty Program
    • Whitelist Assets on Clover P-Chain
    • Bridge assets into CLV P-Chain
  • Assets
    • πŸ”€ Glossary
      • Blockchain (in General)
      • Polkadot
      • Wallet
    • 🎟️ CLV - Polkadot Parachain Auction 2021
      • Parachain Auction Rule Announcement
      • Parachain Winning Reward Announcement
    • πŸ›οΈ Brand Pack
    • πŸ“„ Whitepaper
Powered by GitBook
On this page
  • Start CLV dev node
  • Setup the private key provider
  • Write the migration
  • Deploy the counter contract
  • Interact with the Counter contract in the console
  1. CLV Chain Developer Guide
  2. dApp Example

Deploy Contract

Start CLV dev node

Now we will deploy the Counter smart contract to our CLV local dev node.

First make sure CLV is started using below command:

./clover --dev --alice

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.

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

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

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.

./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:

$ yarn add web3-provider-engine ethereumjs-wallet

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

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:

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.

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 .

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.

First create the migrations folder

$ mkdir migrations

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

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

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

Deploy the counter contract

It's time to deploy counter using below command!

$ truffle deploy --network development

You should get some output as below:

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.

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:

$ 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:

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.

PreviousThe Counter ContractNextCounter Webapp

Last updated 2 years ago

We wrote a standard truffle migration which load the Counter contract and deploy it to the chain in the migration function. Checkout for more details.

The source code of this chapter could be found at the revision 3e76c43d3 in the source repo.

truffle migration document
counter-dapp