Klaytn Docs Archive
Getting StartedBuild a dAppNode OperationDeveloper Hub
  • Klaytn Docs
  • -
    • Klaytn Overview
      • Why Klaytn
      • Klaytn Design
        • Consensus Mechanism
        • Accounts
        • Transactions
          • Basic
          • Fee Delegation
          • Partial Fee Delegation
          • Ethereum
        • Computation
          • Klaytn Smart Contract
          • Execution Model
          • Computation Cost
            • Computation Cost (Previous docs)
          • Klaytn Virtual Machine
            • Klaytn Virtual Machine (Previous docs)
        • Storage
          • State Migration
          • StateDB Live Pruning
        • Transaction Fees
          • Transaction Fees (Previous docs)
        • Klaytn native coin - KLAY
        • Token Economy
        • Governance
        • Multi-Channel
        • KNI
      • Scaling Solutions
    • Getting Started
      • Deploying Smart Contract Using Foundry
      • Deploying Smart Contract Using Hardhat
      • Deploying Smart Contract Using Thirdweb
      • Deploying Smart Contract Using KEN
        • Launch an Endpoint Node
        • Top up your Account
        • Install Development Tools
        • Deploy a Smart Contract
        • Check the Deployment
        • Account Management
          • Creating Accounts
          • Managing Accounts
      • Development Environment
      • Getting KLAY
    • Smart Contract
      • Solidity - Smart Contract Language
      • Precompiled Contracts
        • Precompiled Contracts (Previous docs)
      • IDE and Tools
        • Truffle
      • Sample Contracts
        • KlaytnGreeter
        • ERC-20
          • 1. Writing ERC-20 Smart Contract
          • 2. Deploying Smart Contract
          • 3. Interacting with ERC-20 token from Klaytn Wallet
        • ERC-721
          • 1. Writing ERC-721 Smart Contract
          • 2. Deploying Smart Contract
      • Testing Guide
      • Deployment Guide
      • Klaytn Compatible Tokens
      • Porting Ethereum Contract
    • Run a Node
      • Deployment
        • Endpoint Node
          • System Requirements
          • Installation Guide
            • Download
            • Installation Guide
            • Configuration
            • Startup the EN
            • Testing the Installation
          • ken CLI commands
          • JSON-RPC APIs
        • Core Cell
          • System Requirements
          • Network Configuration
          • Installation Guide
            • Download
            • Before You Install
            • Consensus Node Setup
              • Installation Guide
              • Configuration
              • Startup the CN
            • Proxy Node Setup
              • Installation Guide
              • Configuration
              • Startup the PN
            • Testing the Core Cell
          • Monitoring Setup
          • H/A Setup
        • Service Chain
          • Getting Started
            • Setting up a 4-node Service Chain
            • Connecting to Baobab
            • Cross-Chain Value Transfer
            • HA(High Availability) for ServiceChain
            • Nested ServiceChain
            • Value Transfer between Sibling ServiceChains
          • Reference Manuals
            • System Requirements
            • Download
            • SCN User Guide
              • Installation
              • Configuration
              • Starting/Stopping SCN
              • Checking Node Status
              • kscn commands
              • homi commands
            • SPN/SEN User Guide
              • Installation
              • Configuration
              • Starting/Stopping Node
              • Checking Node Status
            • Bridge Configuration
            • Anchoring
            • KAS Anchoring
            • Value Transfer
            • Configuration Files
            • Log Files
            • Genesis JSON
            • Upgrade & Hard Fork
          • How-To Guides
        • Download Node Packages
          • v1.12.0
          • v1.11.1
          • v1.11.0
          • v1.10.2
          • v1.10.1
          • v1.10.0
          • v1.9.1
          • v1.9.0
          • v1.8.4
          • v1.8.3
          • v1.8.2
          • v1.8.1
          • v1.8.0
          • v1.7.3
          • v1.7.2
          • v1.7.1
          • v1.7.0
          • v1.6.4
          • v1.6.3
          • v1.6.2
          • v1.6.1
          • v1.6.0
          • v1.5.3
          • v1.5.2
          • v1.5.1
          • v1.5.0
          • v1.4.2
          • v1.4.1
          • v1.4.0
          • v1.3.0
          • v1.2.0
          • v1.1.1
          • v1.0.0
          • v0.9.6
          • v0.8.2
    • Operation Guide
      • Configuration
      • Node Log
      • Log operation
      • Errors & Troubleshooting
      • Klaytn Command
      • Chaindata Change
      • Chaindata Migration
    • dApp Developers
      • JSON-RPC APIs
        • API references
          • eth
            • Caution
            • Account
            • Block
            • Transaction
            • Config
            • Filter
            • Gas
            • Miscellaneous
          • klay
            • Account
            • Block
            • Transaction
              • Working with Klaytn Transaction Types
            • Configuration
            • Filter
            • Gas
            • Miscellaneous
          • net
          • debug
            • Logging
            • Profiling
            • Runtime Tracing
            • Runtime Debugging
            • VM Tracing
            • VM Standard Tracing
            • Blockchain Inspection
          • admin
          • personal
          • txpool
          • governance
        • Service Chain API references
          • mainbridge
          • subbridge
        • Transaction Error Codes
      • RPC Service Providers
        • Public Endpoints
      • SDK & Libraries for interacting with Klaytn Node
        • caver-js
          • Getting Started
          • Sending a sample transaction
          • API references
            • caver.account
            • caver.wallet
              • caver.wallet.keyring
            • caver.transaction
              • Basic
              • Fee Delegation
              • Partial Fee Delegation
            • caver.rpc
              • caver.rpc.klay
              • caver.rpc.net
              • caver.rpc.governance
            • caver.contract
            • caver.abi
            • caver.kct
              • caver.kct.kip7
              • caver.kct.kip17
              • caver.kct.kip37
            • caver.validator
            • caver.utils
            • caver.ipfs
          • caver-js ~v1.4.1
            • Getting Started (~v1.4.1)
            • API references
              • caver.klay
                • Account
                • Block
                • Transaction
                  • Legacy
                  • Value Transfer
                  • Value Transfer Memo
                  • Account Update
                  • Smart Contract Deploy
                  • Smart Contract Execution
                  • Cancel
                • Configuration
                • Filter
                • Miscellaneous
              • caver.klay.net
              • caver.klay.accounts
              • caver.klay.Contract
              • caver.klay.KIP7
              • caver.klay.KIP17
              • caver.klay.abi
              • caver.utils (~v1.4.1)
            • Porting from web3.js
        • caver-java
          • Getting Started
          • API references
          • caver-java ~v1.4.0
            • Getting Started (~v1.4.0)
            • Porting from web3j
        • ethers.js
        • web3.js
      • Tutorials
        • Klaytn Online Toolkit
        • Fee Delegation Example
        • Count DApp
          • 1. Environment Setup
          • 2. Clone Count DApp
          • 3. Directory Structure
          • 4. Write Smart Contract
          • 5. Frontend Code Overview
            • 5-1. Blocknumber Component
            • 5-2. Auth Component
            • 5-3. Count Component
          • 6. Deploy Contract
          • 7. Run App
        • Klaystagram
          • 1. Environment Setup
          • 2. Clone Klaystagram DApp
          • 3. Directory Structure
          • 4. Write Klaystagram Smart Contract
          • 5. Deploy Contract
          • 6. Frontend Code Overview
          • 7. FeedPage
            • 7-1. Connect Contract to Frontend
            • 7-2. UploadPhoto Component
            • 7-3. Feed Component
            • 7-4. TransferOwnership Component
          • 8. Run App
        • Building a Buy Me a Coffee dApp
          • 1. Project Setup
          • 2. Creating a BMC Smart Contract
          • 3. Testing the contract using scripts
          • 4. Deploying BMC Smart contract
          • 5. Building the BMC Frontend with React and Web3Onboard
          • 6. Deploying Frontend code on IPFS using Fleek
          • 7. Conclusion
        • Migrating Ethereum App to Klaytn
        • Connecting MetaMask
        • Connecting Remix
        • Verifying Smart Contracts Using Block Explorers
      • Developer Tools
        • Wallets
          • Kaikas
          • Klaytn Wallet
          • Klaytn Safe
            • Klaytn Safe Design
            • Create a Safe
            • Add assets
            • Send assets
            • Contract Interaction
            • Transaction Builder
            • Points to Note
            • Frequently Asked Questions
          • SafePal S1
          • Wallet Libraries
            • Web3Auth
            • Web3Modal
            • Web3-Onboard
            • Particle Network
        • Oracles
          • Orakl Network
          • Witnet
          • SupraOracles
        • Indexers
          • SubQuery
        • Cross-chain
          • LayerZero
        • Block Explorers
          • Klaytnscope
          • Klaytnfinder
        • Klaytn Contracts Wizard
    • Glossary
  • ---
    • Klaytn Hard Fork History
    • Klaytn 2.0
      • Metaverse Package
      • Finality and Improvements
      • Ethereum Compatibility
      • Decentralizing Governance
      • Massive Eco Fund
    • FAQ
    • Open Source
    • Terms of Use
    • Languages
  • ℹ️Latest Klaytn Docs
Powered by GitBook
On this page
  • Table of Contents
  • 1. Introduction
  • 2. Klaytn has Ethereum compatibility
  • 3. Change node connection from Ethereum to Klaytn
  • 4. Interact with Klaytn node: BlockNumber component
  • 5. Interact with the contract: Count component
  • 5-1. Deploy Count contract on Klaytn
  • 5-2. Create a contract instance
  • 5-3. Interact with contract
  1. -
  2. dApp Developers
  3. Tutorials

Migrating Ethereum App to Klaytn

Previous7. ConclusionNextConnecting MetaMask

Last updated 2 years ago

Table of Contents

1. Introduction

This tutorial is intended to give a guide to migrate an Ethereum App to Klaytn. No previous Klaytn experience is needed. A simple blockchain app will be used as a sample to show how to migrate an Ethereum App to Klaytn.

We will focus only on the code modifications required to migrate an Ethereum App to Klaytn. If you need details on creating a Klaytn dApp, Please refer to .

Source Code Complete source code can be found on GitHub at

Intended Audience

  • We assume that you have basic knowledge on . Sample code is made with React.

  • Basic knowledge and experience in Blockchain app is required, but no previous Klaytn experience is needed.

Testing Environment

CountDApp is tested in the following environment.

  • MacOS Mojave 10.14.5

  • Node 10.16.0 (LTS)

  • npm 6.9.0

  • Python 2.7.10

2. Klaytn has Ethereum compatibility

Klaytn runtime environment is compatible with Ethereum Virtual Machine and executes smart contracts written in Solidity. Klaytn's RPC APIs and other client libraries maintain almost identical API specifications with Ethereum's whenever available. Therefore, it is fairly straightforward to migrate Ethereum Apps to Klaytn. This helps developers easily move to a new blockchain platform.

3. Change node connection from Ethereum to Klaytn

  • Ethereum

    • web3 library connects to and communicates with Ethereum node.

    • Ropsten testnet URL is assigned to 'rpcURL' .

  • Klaytn

    • caver-js library is used to connect to and communicate with Klaytn node.

    • Baobab testnet URL is assigned to 'rpcURL'.

src/klaytn/caver.js

// import Web3 from 'web3'
import Caver from 'caver-js'

// const ROPSTEN_TESTNET_RPC_URL = 'https://ropsten.infura.io/'
const BAOBAB_TESTNET_RPC_URL = 'https://public-en-baobab.klaytn.net/'

// const rpcURL = ROPSTEN_TESTNET_RPC_URL
const rpcURL = BAOBAB_TESTNET_RPC_URL

// const web3 = new Web3(rpcURL)
const caver = new Caver(rpcURL)

// export default web3
export default caver

4. Interact with Klaytn node: BlockNumber component

BlockNumber component gets the current block number every 1 second (1000ms).

By simply replacing the web3 library with caver-js, you can sync Klaytn's BlockNumber in real-time instead of Ethereum's BlockNumber.

// import web3 from 'ethereum/web3'
import caver from 'klaytn/caver'

class BlockNumber extends Component {
  state = { currentBlockNumber: '...loading' }

  getBlockNumber = async () => {
    // const blockNumber = await web3.eth.getBlockNumber()
    const blockNumber = await caver.klay.getBlockNumber()

    this.setState({ currentBlockNumber: blockNumber })
  }
  // ...
}

export default BlockNumber

5. Interact with the contract: Count component

To interact with the contract, we need to create an instance of the deployed contract. With the instance, we can read and write the contract's data.

Let's learn step by step how to migrate CountDApp from Ethereum to Klaytn!

  • 5-1. Deploy Count contract on Klaytn

  • 5-2. Create a contract instance

  • 5-3. Interact with contract

5-1. Deploy Count contract on Klaytn

  1. Change network properties in truffle-config.js to deploy the contract on Klaytn.

  2. Type $ truffle deploy --network baobab --reset

  3. Count contract will be deployed on Baobab testnet, Klaytn.

truffle-config.js

// const HDWalletProvider = require("truffle-hdwallet-provider")
const HDWalletProvider = require("truffle-hdwallet-provider-klaytn")

// const NETWORK_ID = '3' // Ethereum, Ropsten testnet's network id
const NETWORK_ID = '1001' // Klaytn, Baobab testnet's network id

// const RPC_URL = 'https://ropsten.infura.io/'
const RPC_URL = 'https://public-en-baobab.klaytn.net'

// Change it to your own private key that has enough KLAY to deploy contract
const PRIVATE_KEY = '0x3de0c90ce7e440f19eff6439390c29389f611725422b79c95f9f48c856b58277'


module.exports = {
  networks: {
    /* ropsten: {
      provider: () => new HDWalletProvider(PRIVATE_KEY, RPC_URL),
      network_id: NETWORK_ID,
      gas: '8500000',
      gasPrice: null,
    }, */

    baobab: {
      provider: () => new HDWalletProvider(PRIVATE_KEY, RPC_URL),
      network_id: NETWORK_ID,
      gas: '8500000',
      gasPrice: null,
    },
  },
  compilers: {
    solc: {
      version: '0.5.6',
    },
  },
}

5-2. Create a contract instance

You can create a contract instance with the caver-js API. The contract instance creates a connection to Count contract. You can invoke contract methods through this instance.

src/components/Count.js

// import web3 from 'ethereum/web3'
import caver from 'klaytn/caver'

class Count extends Component {
  constructor() {
    /* const CountContract = DEPLOYED_ABI
      && DEPLOYED_ADDRESS
      && new web3.eth.Contract(DEPLOYED_ABI, DEPLOYED_ADDRESS) */

    this.countContract = DEPLOYED_ABI
      && DEPLOYED_ADDRESS
      && new cav.klay.Contract(DEPLOYED_ABI, DEPLOYED_ADDRESS)
  }

  // ...
}
export default Count

5-3. Interact with contract

The ABI (Application Binary Interface) used to create the Count contract instance allows the caver-js to invoke contract's methods as below. You can interact with Count contract as if it were a JavaScript object.

  • Read data (call) CountContract.methods.count().call()

  • Write data (send) CountContract.methods.plus().send({ ... }) CountContract.methods.minus().send({ ... })

Once you created a contract instance as in the previous step, you don't need to modify any code in using the contract methods afterward. dApp migration has been completed!

Full code: Count component

src/components/Count.js

import React, { Component } from 'react'
import cx from 'classnames'

import caver from 'klaytn/caver'

import './Count.scss'

class Count extends Component {
  constructor() {
    super()
    // ** 1. Create contract instance **
    // ex:) new caver.klay.Contract(DEPLOYED_ABI, DEPLOYED_ADDRESS)
    // You can call contract method through this instance.
    // Now you can access the instance by `this.countContract` variable.
    this.countContract = DEPLOYED_ABI
      && DEPLOYED_ADDRESS
      && new caver.klay.Contract(DEPLOYED_ABI, DEPLOYED_ADDRESS)
    this.state = {
      count: '',
      lastParticipant: '',
      isSetting: false,
    }
  }

  intervalId = null

  getCount = async () => {
    // ** 2. Call contract method (CALL) **
    // ex:) this.countContract.methods.methodName(arguments).call()
    // You can call contract method (CALL) like above.
    // For example, your contract has a method called `count`.
    // You can call it like below:
    // ex:) this.countContract.methods.count().call()
    // It returns promise, so you can access it by .then() or, use async-await.
    const count = await this.countContract.methods.count().call()
    const lastParticipant = await this.countContract.methods.lastParticipant().call()
    this.setState({
      count,
      lastParticipant,
    })
  }

  setPlus = () => {
    const walletInstance = caver.klay.accounts.wallet && caver.klay.accounts.wallet[0]

    // Need to integrate wallet for calling contract method.
    if (!walletInstance) return

    this.setState({ settingDirection: 'plus' })

    // 3. ** Call contract method (SEND) **
    // ex:) this.countContract.methods.methodName(arguments).send(txObject)
    // You can call contract method (SEND) like above.
    // For example, your contract has a method called `plus`.
    // You can call it like below:
    // ex:) this.countContract.methods.plus().send({
    //   from: '0x952A8dD075fdc0876d48fC26a389b53331C34585', // PUT YOUR ADDRESS
    //   gas: '200000',
    // })
    this.countContract.methods.plus().send({
      from: walletInstance.address,
      gas: '200000',
    })
      .once('transactionHash', (txHash) => {
        console.log(`
          Sending a transaction... (Call contract's function 'plus')
          txHash: ${txHash}
          `
        )
      })
      .once('receipt', (receipt) => {
        console.log(`
          Received receipt! It means your transaction(calling plus function)
          is in klaytn block(#${receipt.blockNumber})
        `, receipt)
        this.setState({
          settingDirection: null,
          txHash: receipt.transactionHash,
        })
      })
      .once('error', (error) => {
        alert(error.message)
        this.setState({ settingDirection: null })
      })
  }

  setMinus = () => {
    const walletInstance = caver.klay.accounts.wallet && caver.klay.accounts.wallet[0]

    // Need to integrate wallet for calling contract method.
    if (!walletInstance) return

    this.setState({ settingDirection: 'minus' })

    // 3. ** Call contract method (SEND) **
    // ex:) this.countContract.methods.methodName(arguments).send(txObject)
    // You can call contract method (SEND) like above.
    // For example, your contract has a method called `minus`.
    // You can call it like below:
    // ex:) this.countContract.methods.minus().send({
    //   from: '0x952A8dD075fdc0876d48fC26a389b53331C34585', // PUT YOUR ADDRESS
    //   gas: '200000',
    // })

    // It returns event emitter, so after sending, you can listen on event.
    // Use .on('transactionHash') event,
    // : if you want to handle logic after sending transaction.
    // Use .once('receipt') event,
    // : if you want to handle logic after your transaction is put into block.
    // ex:) .once('receipt', (data) => {
    //   console.log(data)
    // })
    this.countContract.methods.minus().send({
      from: walletInstance.address,
      gas: '200000',
    })
      .once('transactionHash', (txHash) => {
        console.log(`
          Sending a transaction... (Call contract's function 'minus')
          txHash: ${txHash}
          `
        )
      })
      .once('receipt', (receipt) => {
        console.log(`
          Received receipt which means your transaction(calling minus function)
          is in klaytn block(#${receipt.blockNumber})
        `, receipt)
        this.setState({
          settingDirection: null,
          txHash: receipt.transactionHash,
        })
      })
      .once('error', (error) => {
        alert(error.message)
        this.setState({ settingDirection: null })
      })
  }

  componentDidMount() {
    this.intervalId = setInterval(this.getCount, 1000)
  }

  componentWillUnmount() {
    clearInterval(this.intervalId)
  }

  render() {
    const { lastParticipant, count, settingDirection, txHash } = this.state
    return (
      <div className="Count">
        {Number(lastParticipant) !== 0 && (
          <div className="Count__lastParticipant">
            last participant: {lastParticipant}
          </div>
        )}
        <div className="Count__count">COUNT: {count}</div>
        <button
          onClick={this.setPlus}
          className={cx('Count__button', {
            'Count__button--setting': settingDirection === 'plus',
          })}
        >
          +
        </button>
        <button
          onClick={this.setMinus}
          className={cx('Count__button', {
            'Count__button--setting': settingDirection === 'minus',
          })}
        >
          -
        </button>
        {txHash && (
          <div className="Count__lastTransaction">
            <p className="Count__lastTransactionMessage">
              You can check your last transaction in klaytnscope:
            </p>
            <a
              target="_blank"
              href={`https://scope.klaytn.com/transaction/${txHash}`}
              className="Count__lastTransactionLink"
            >
              {txHash}
            </a>
          </div>
        )}
      </div>
    )
  }
}

export default Count

First, you need to change the library that makes a connection to the node. Then you will specify the node URL in 'rpcURL'. (FYI. )

Ethereum: Klaytn:

For more detail about BlockNumber component, see .

The first step is deploying Count contract on Klaytn and get the contract address. Most of the cases, you can use Etherem contracts on Klaytn without modification. See . In this guide, we will use Truffle to deploy the contract.

Top up your account using .

For more details about deploying contracts, See .

Ethereum : Klaytn :

The Ropsten testnet in ethereum will be shut down in Q4 2022.
CountDApp tutorial - Blocknumber Component
Porting Etherem Contract
KLAY faucet
CountDapp tutorial - Deploy Contract
CountDApp Tutorial
https://github.com/klaytn/countbapp
React
1. Introduction
2. Klaytn has Ethereum compatibility
3. Change node connection from Ethereum to Klaytn
4. Interact with Klaytn node: BlockNumber component
5. Interact with the contract: Count component
5-1. Deploy Count contract on Klaytn
5-2. Create a contract instance
5-3. Interact with contract
web3.eth.getBlockNumber()
web3.eth.Contract(ABI, address)
caver.klay.Contract(ABI, address)
blocknumber component
count component
caver.klay.getBlockNumber()