Conflux, as a new generation of fully decentralized, high-performance public chain, will soon usher in the launch of the main network. In addition to a performance improvement of two orders of magnitude over Ethereum, another highlight of the smart contract VM is solidity compatibility. This means that an Ethereum Dapp contract can be quickly deployed to the Conflux main chain with few modifications. Developers just need to switch the web3.js interaction to jS-Conflux-SDK. This article will demonstrate how to migrate an Ethereum Dapp to a Conflux network.
Here we use the template project CryptoPizza NFT provided by Ethereum Studio as an example to try to deploy it to a Conflux network. CryptoPizza is a contract for NFT (Non-fungible Tokens). NFT is different from ERC20. Each token is usually used to represent a unique entity. Every Pizza is different. The Dapp supports create, eat, and Gift operations of Pizza. Its user interface is as follows:
How to experience Ethereum CryptoPizza
Open Ethereum Studio and select create CryptoPizza template project; Then click the Deploy button to deploy the contract in the browser environment. Then we can experience the CryptoPizza application in the render window on the right.
- Enter a name and click Create to create a Pizza on the chain.
- You can view your Pizza on the Inventory page and perform the EAT and Gift operations.
You can experience it here
Preparing for migration
- Install the Conflux wallet (Portal), create an account and apply for a CFX (for sending transactions and deploying contracts)
- Conflux Basic concepts
- The installation
js-conflux-sdk
Conflux Portal
Portal is a browser-based lightweight wallet for Conflux plug-ins, based on the idea of not reinventing the wheel. The framework is based on MetaMask, so the usage method is basically the same as MetaMask. Portal manages the account (private key) of Conflux. The core function is to sign transactions with the private key and send transactions. Portal is therefore the key medium through which the user interacts with the Dapp. For details about how to install and use Portal, see the following section
The basic concept
- Epoch: In bitcoin and Ethereum, blockchains are chain-installed structures, and each block has an incremental number called block_number. In Conflux, the ledger structure of its data storage is a tree graph, and incremental numbers cannot be assigned to blocks, but in order to determine the full order of all blocks,
The concept of Epoch is defined. The sequence number of Epoch is monotonically increasing. There may be multiple blocks in each Epoch, and the blocks within the Epoch have their order (index). When ethereum sends a transaction, there is the concept of gasLimit, which is used to limit the maximum amount of money that can be spent to execute a transaction. Conflux can not only limit gasLimit, but also limit the storage of the transaction, namely storageLimit (unit byte). The chainId is a security mechanism used to prevent the transaction from being replayed. If the transaction is sent with an inconsistent chainId, it will not succeed. RPC: it is mainly used to obtain data from blockchain and send transactions. Ordinary users do not need to know, but contract developers need to know. In general, users can run the local node and use the RPC of the local node. Conflux network token, used to pay transaction fees, 1CFX=10^8Gdrip=10^ 18DRIP Transaction send value and gas_price unit are drip 6. The difference in address: The common account address of Conflux starts with 1, and the contract address starts with 8. Ethereum is not restricted. In conflux, receipt. OutcomeStatus indicates the execution status of the transaction 0- success, 1- failure as opposed to Ethereum
web3.js vs js-conflux-sdk
The two are the JavaScript SDKS for Ethereum and Conflux respectively. The main functions are to provide RPC call encapsulation, Contract interaction encapsulation, as well as some codec, unit, type conversion and other common methods. Here is a simple comparison of the use of both
- Installation method: NPM is used for both Node environments (SDK 0.13.2 is used in this article)
# web3
$ npm install web3
# js-conflux-sdk$NPM install [email protected]Copy the code
The corresponding front-end files can be found in the dist directory after NPM install in the browser environment
<! -- web3 -->
<script src="dist/web3.min.js"></script>
<! -- js-conflux-sdk -->
<script type="text/javascript" src="dist/js-conflux-sdk.umd.min.js">
Copy the code
- Initialization (the default port is different)
// web3
const Web3 = require('web3'); // In a browser environment, the require statement can be omitted
let web3 = new Web3(Web3.givenProvider || "ws://localhost:8545"); // The ws link is used here, or HTTP can be used
// conflux
// initalize a Conflux object
const {Conflux} = require('js-conflux-sdk');
const cfx = new Conflux({
url: 'http://localhost:12537'.logger: console.// for debug
});
Copy the code
- Call RPC to query the balance
// web3
const balance = await web3.eth.getBalance('0x1bd9e9be525ab967e633bcdaeac8bd5723ed4d6b');
// conflux
const balance = await cfx.getBalance('0x1bd9e9be525ab967e633bcdaeac8bd5723ed4d6b');
Copy the code
While the Conflux method call is very succinct and returns a promise, Web3 provides more complex functionality that supports both promises and callback
// web3 promise vs callback
const balance = await web3.eth.getBalance('0x1bd9e9be525ab967e633bcdaeac8bd5723ed4d6b');
web3.eth.getBalance('0x1bd9e9be525ab967e633bcdaeac8bd5723ed4d6b'.function(err, balance) {
if (err) {
console.log(err);
} else {
console.log(`balance is: ${balance}`); }});Copy the code
- Send a deal
// web3 uses the account in web3.eth. Accounts. Wallet to send transactions
let receipt = await web3.eth.sendTransaction({
from: '0xde0B295669a9FD93d5F28D9Ec85E40f4cb697BAe'.to: '0x11f4d0A3c12e86B4b5F39B213F7E19D048276DAe'.value: '1000000000000000'
});
// conflux
let account = conflux.Account("your_private_key");
const txHash = await cfx.sendTransaction({
from: account, // from account instance and will by sign by account.privateKey
to: "0x-another-address".// accept address string or account instance
value: util.unit.fromCFXToDrip(0.125), // use unit to transfer from CFX to Drip
});
Copy the code
- In a blockchain system, transactions are completed in several stages: send, package, execute, and confirm. The two SDKS have different acquisition methods for different stages.
// The way Web3 uses events
web3.eth.sendTransaction({from: '0x123... '.data: '0x432... '})
.once('sending'.function(payload){... }) .once('sent'.function(payload){... }) .once('transactionHash'.function(hash){... }) .once('receipt'.function(receipt){... }) .on('confirmation'.function(confNumber, receipt, latestBlockHash){... }) .on('error'.function(error){... }) .then(function(receipt){
// will be fired once the receipt is mined
});
// Conflux provides different methods to obtain information about different phases of TX
let txParameters = {
from: account,
to: "0x-a-address".value: "0x100"
};
const txHash = await cfx.sendTransaction(txParameters); // send the tx and return a hash
const tx = await cfx.sendTransaction(txParameters).get(); // will also get the tx by hash
const tx = await cfx.sendTransaction(txParameters).mined(); // wait tx mined and return the tx
const receipt = await cfx.sendTransaction(txParameters).executed(); // wait tx executed and return receipt
const receipt = await cfx.sendTransaction(txParameters).confirmed(); // wait tx confirmed and return receipt
Copy the code
- Contract instantiation & method call
// web3
var Contract = require('web3-eth-contract');
// set provider for all later instances to use
Contract.setProvider('ws://localhost:8546');
var contract = new Contract(jsonInterface, address);
myContract.methods.myMethod(123).call({from: 'address'}, function(error, result){});// or sending and using a promise
myContract.methods.myMethod(123).send({from: 'address'})
.then(function(receipt){});// js-conflux-sdk
let contract = cfx.Contract({
abi: this.Contract.abi,
address: this.Contract.address,
});
await contract.myMethod(123);
await contract.myMethod(123).sendTransaction({from: "addres"});
Copy the code
Deploy the contract to the Conflux network
After laying the groundwork, the migration can begin. Note: Download ABI or Bytecode in File Exporler or Exporler is available for downloading Zip packages. The exported file directory is as follows:
- App: HTML page code
- Build: contract compiled file
- Contracts: Source code for contracts
- Node_modules: nodeJS module code
The first thing to do after downloading is to install jS-Conflux-SDK. We can then write a script to deploy the contract by sending TX.
const privateKey = "0xxxxxx";
const fs = require('fs');
const account = cfx.Account(privateKey); // create account instance
async function main() {
let abi = JSON.parse(fs.readFileSync('./build/contracts/CryptoPizza/CryptoPizza.abi'));
let bytecode = fs.readFileSync('./build/contracts/CryptoPizza/CryptoPizza.bin');
const contract = cfx.Contract({
abi,
bytecode,
});
// deploy the contract, and get `contractCreated`
const receipt = await contract.constructor()
.sendTransaction({ from: account })
.confirmed();
console.log(receipt); // The contract address for the final deployment is: receipt. ContractCreated:
}
main().catch(e= > console.error(e));
Copy the code
Note: A balance account is required for deployment and its private key needs to be exported
Dapp front-end interaction part migration
The index.html in the App directory is a web page file. First we need to import the JS code of app.css, app.js and js-Conflux-SDK. You also need to introduce the ABI of the contract as js variables.
Then the main migration effort will be concentrated in app.js as we need to replace the web3.js related code with jS-conflux-SDK. In order to create Pizza using a Portal account, the Portal API needs to be integrated.
Connect portal
Because creating Pizza requires sending transactions, you need to connect to the Conflux Portal so that you can get the account address, initiate transactions, sign and send. Please refer to the document for the specific usage method. What I need to do here is to obtain the authorized connection when opening the page for the first time, set conflux as the SDK provider, and use the Portal account when sending transactions.
// 1. Add a button and when clicked, connect to portal
$(document).on('click'.'button.connect-portal'.async function() {
const accounts = await conflux.enable();
console.log('connected to portal');
});
// 2. Set provider
this.web3.provider = conflux;
// 3. Use selectdAddress to send txRun conflux.selectedAddress to obtain the portal account address conflux.selectedAddressCopy the code
The conflux instance was initialized. Procedure
var Contracts = {};
// Set the address and ABI of the contract
Contracts['CryptoPizza'] = {
abi: contract_abi,
address: "0x8b0d9204db0adf41aa49e3fe43e20447555c28a3".// this is the address of newly deployed contract
endpoint: "http://main.confluxrpc.org"
};
// below code is in Pizza.prototype.init
this.web3 = new window.Conflux.Conflux({
url: this.Contract.endpoint,
logger: console});if (conflux.isConnected()) {
this.web3.provider = conflux; // Use the Conflux object provided by the Portal as the SDK provider
}
this.instance = this.web3.Contract({
abi: this.Contract.abi,
address: this.Contract.address,
});
Copy the code
Contract getter method modified
Methods involved include: getRandomDna, getPizzasByOwner, waitForReceipt
// The original code uses web3's callback method to get data, which needs to be replaced with JS promise method
Pizza.prototype.getRandomDna = function(name, address, cb) {
this.instance.generateRandomDna(name, address, function(error, result) {
cb(error, result);
});
};
/ / replace
Pizza.prototype.getRandomDna = function(name, address, cb) {
// conflux-SDK returns a promise whose then method accepts two callback methods
this.instance.generateRandomDna(name, address)
.then(
function(result) {
cb(null, result[0]); // why return a array?
}, function(err) { cb(err); }); };Copy the code
Modify the contract status modification method
Modifying the contract state requires invoking the contract method and setting the state by sending a transaction. The main difference is in the way tx parameters are set and data is returned.
// The original invocation
this.instance.createRandomPizza(
name,
{
from: window.web3.eth.accounts[0].gas: 1000000.gasPrice: 1000000000.gasLimit: 1000000
},
cbk
)
/ / replace
this.instance
.createRandomPizza(name)
.sendTransaction({
from: conflux.selectedAddress
}).then(success_cbk, fail_cbk)
Copy the code
Methods involved include: createRandomPizza, giftPizza, eatPizza
After these modifications, we completed the migration of the Dapp interactive part of the code.
Finally, if you want to experience the Dapp, you can come here, and you need to install the Portal first.
other
- The JS-Conflux-SDK version used in this article is 0.13.2
- The Pizza list page has been changed to load data when tabbing
reference
- js-conflux-sdk
- conflux portal
- ethereum studio
- Article Sample code