Ethereum Development Framework - Basic Use of Truffle

Truffle

Introduction to Truffle

The truffle unbox webpack command takes about 10
minutes to download many required modules, so let's take a look at Truffle first.

Truffle is currently the most popular Ethereum DApp development framework, (according to the official website) a
world -class development environment and testing framework, as well as an asset management channel for all blockchains that use EVM. It is based on JavaScript and is committed to making Development on Ethereum made easy.

Truffle has the following features:

 内置的智能合约编译,链接,部署和二进制文件的管理。
 合约自动测试,方便快速开发。
 脚本化的、可扩展的部署与发布框架。
 可部署到任意数量公网或私网的网络环境管理功能
 使用 EthPM 和 NPM 提供的包管理,使用 ERC190 标准。
 与合约直接通信的直接交互控制台(写完合约就可以命令行里验证了)。
 可配的构建流程,支持紧密集成。
 在 Truffle 环境里支持执行外部的脚本。

Truffle client

The smart contracts we write later must be deployed on the chain for testing, so the DApp built by
truffle must also select a chain for deployment. We can choose to deploy to some public test chains such as Rinkeby or Ropsten. The disadvantage is that the deployment and testing time is relatively long, and it takes a certain amount of time to earn fake tokens to prevent out of gas. Of course, for the formal process of DApp release, staging (simulation environment) should still be used to test the public chain.

Another way is to deploy to a private chain, which is the usual choice during the development phase. Truffle officially
recommends the following two clients:
 Ganache
 truffle develop

truffle develop is a built-in client of truffle, which is basically
similar to the command line version of Ganache. Enter bash in the truffle directory:

>truffle develop

The client can be opened, and like ganache, it will automatically generate 10 accounts for us.
The only thing to note is that when executing the truffle command in truffle develop, you need to omit the preceding
"truffle". For example, "truffle compile" only needs to type "compile".

Install Truffle

Start geth, then let's install truffle. truffle is a dapp development framework that
makes building and managing dapps very easy.

You can install using npm like this truffle: >npm install -g truffle
Then we create an empty directory and create the truffle project below:

>mkdir simple_voting_by_truffle_dapp
>cd simple_voting_by_truffle_dapp
>npm install -g webpack
>truffle unbox webpack

truffle init: Initialize a new empty truffle project in the current directory (project files only have
truffle-config.js and truffle.js; only Migrations.sol in the contracts directory; only 1_initial_migration.js in the migrations directory)

truffle unbox: Download a truffle box directly, that is, a pre-built truffle project;
the unboxing process is relatively long, and you should see this prompt after completion:

insert image description here
The webpack here is an official project framework (truffle box) based on the webpack build process . For
more truffle boxes, see https://truffleframework.com/boxes

Create project

When a truffle project is initialized, it creates all the necessary files
and directories to run a full dapp. We directly download the truffle box of webpack, and the directory in it is similar:

>ls
README.md contracts node_modules test 
webpack.config.js truffle.js app migrations 
package.json
>ls app/
index.html javascripts stylesheets
>ls contracts/
ConvertLib.sol MetaCoin.sol Migrations.sol
>ls migrations/
1_initial_migration.js 2_deploy_contracts.js

 app/ - the default directory where your application files will run. This includes recommended directories for javascript files
and css style files, but it is up to you to decide how to use these directories.
 contract/ - Truffle's default contract file storage directory.  migrations/ - the storage directory for deployment script files
test/ - the test file directory for testing applications and contracts Delete the ConvertLib.sol and MetaCoin.sol files in the contracts directory under the project.

>rm contracts/ConvertLib.sol contracts/MetaCoin.sol

Also, look for a configuration file called truffle.js in your project directory. It contains
a configuration for developing the network. Change the port number from 7545 to 8545, because our private chain and ganache will run on this port by default.

Migration

The concept
of migration It is important to understand the contents of the migrations directory. These migration files are used to deploy contracts
onto the blockchain.

In the previous project, the voting contract was deployed to the blockchain by calling VotingContract.new in the node console. In the future, we won't need to do this anymore, truffle will deploy and track all deployments.

Migrations are JavaScript files that are responsible for staging our deployment tasks, assuming that deployment needs will change over time. As the project grows, we should create new migration scripts to change the contract state on the chain. All run migration history records will be recorded on the chain through a special migration contract.

The first migration 1_initial_migration.js deploys a
contract called Migrations to the blockchain and is used to store the latest contract you have deployed. Every time you run a migration, truffle queries the blockchain for the latest deployed contracts, and then deploys any contracts that have not yet been deployed.

It then updates the last_completed_migration field in the Migrations contract to point to the latest deployed contract. You can simply think of it as a database table with a column
last_completed_migration that is always up-to-date.

The naming of migration files has special requirements: the prefix is ​​a number (required), which is used to mark
whether the migration runs successfully; the suffix is ​​a descriptive word, just to improve readability and facilitate understanding.

artifacts.require()

At the beginning of the script, we use the artifacts.require() method to tell truffle which contract we want to deploy and migrate
, which is very similar to require in node. However, it should be noted that the latest official documentation warns that you should pass in the defined contract name, not the file name - because a .sol file may contain multiple contracts.

functions of exports

The exports function in migration js needs to receive a deployer object as the first
parameter. This object is mainly used to provide clear syntax support in the process of deploying and publishing, and also provide some common contract deployment responsibilities, such as saving deployed files for later use.

deployer object

The deployer object is the main interface for staging deployment tasks.
Like all other code in Truffle, Truffle provides
contract abstractions for our own code, and is initialized so that you can easily interact with the Ethereum network. These abstract interfaces are all part of the deployment process.

Update migration files

Update the content of 2_deploy_contracts.js with the following information:

var Voting = artifacts.require("./Voting.sol");
module.exports = function(deployer) {
    
    
deployer.deploy(Voting, ['Alice', 'Bob', 'Cary'], {
    
    gas:
290000});
};

As you can see from the above, the deployer expects the first parameter to be the contract name, following the constructor parameter.

In our case, there is only one parameter, which is an array of candidates. The third parameter is a hash that we use to specify the gas required to deploy the code. The amount of gas will vary with the size of your contract. For voting contracts, 290000 is enough.

Update the truffle configuration file

Update the contents of truffle.js like this:

require('babel-register')
module.exports = {
    
    
networks: {
    
     
development: {
    
     
host: 'localhost', 
port: 8545, 
network_id: '*', 
gas: 470000 
} } }

You'll notice that the only difference between the previous truffle.js and our updated file is the gas option.
This is a global variable that applies to all migrations. For example, if you don't specify
a gas value of 290000 in 2_deploy_contracts.js, migration will default to 470000.

The contract code Voting.sol
has been coded before and can be used for truffle without additional changes. Just copy the files from the
simple_voting_dapp to the contracts directory.

Create an account (you can use the account transfer on metamask)

Before we can deploy the contract, we need an account with some ether in it. When we used
ganache, it created 10 test accounts with 100 test ethers in each account
. But for testnet and mainnet, we have to create our own account and put some ether into it.

In the previous ganache application, we had started a single node console and initialized
the web3 object. When we execute the truffle console, truffle does everything for us and we have a web3 object ready to use. Now we have an account with address
'0x95a94979d86d9c32d1d2ab5ace2dcc8d1b446fa1' (you will get a different address) with a balance of 0.

 >truffle console
// Replace 'verystrongpassword' with a good strong password.
truffle(development)> 
web3.personal.newAccount('verystrongpassword') ' 0xbaeec91f6390a4eedad8729aea4bf47bf8769b15'
truffle(development)> 
web3.eth.getBalance('0xbaeec91f6390a4eedad8729aea4bf47bf8769b1
5')
{
    
     [String: '0'] s: 1, e: 0, c: [ 0 ] }
truffle(development)> 
web3.personal.unlockAccount('0xbaeec91f6390a4eedad8729aea4bf47
bf8769b15', 'verystrongpassword', 15000)

deploy

If we already have some ether, we can go ahead and compile and deploy the contract to the blockchain. You
can find the relevant commands below, and if all goes well, the following output will appear.

>truffle compile
Compiling Migrations.sol...Compiling Voting.sol...Writing 
artifacts to ./build/contracts
>truffle migrate
Running migration: 1_initial_migration.js
Deploying Migrations...
Migrations: 0x3cee101c94f8a06d549334372181bc5a7b3a8bee
Saving successful migration to network...
Saving artifacts...
Running migration: 2_deploy_contracts.js
Deploying Voting...
Voting: 0xd24a32f0ee12f5e9d233a2ebab5a53d4d4986203
Saving successful migration to network...
Saving artifacts...

If you have multiple accounts, make sure the related accounts are not locked. By default, the first account
web3.eth.accounts[0] will be used for deployment.

Possible problems and solutions

  1. If the deployment fails due to insufficient gas, try
    increasing the gas account in migrations/2_deploy_contracts.js to
    500000. For example: deployer.deploy(Voting, ['Rama', 'Nick', 'Jose'],
    {gas: 500000});
  2. If you have multiple accounts and prefer to choose an account instead of accounts[0], you can specify the address of the account you want to use in truffle.js.
    Add 'from: your address' after network_id and truffle will use the address you specify to deploy and interact.

If the deployment goes well, you can interact with the contract via the console and the web page

Create a new JavaScript file app/scripts/index.js

   // Import the page's CSS. Webpack will know what to do with it.
import "../styles/app.css";
// Import libraries we need.
import {
    
     default as Web3} from 'web3';
import {
    
     default as contract } from 'truffle-contract'
import voting_artifacts from '../../build/contracts/Voting.json'
var Voting = contract(voting_artifacts);
let candidates = {
    
    "Alice": "candidate-1", "Bob": "candidate-2", 
"Cary": "candidate-3"}
window.voteForCandidate = function(candidate) {
    
     
    let candidateName = $("#candidate").val(); 
    try {
    
     
        $("#msg").html("Vote has been submitted. The vote count 
        will increment as soon as the vote is recorded on the blockchain. 
        Please wait.") 
        $("#candidate").val("");
        Voting.deployed().then(function(contractInstance) {
    
     
            contractInstance.voteForCandidate(candidateName, 
            {
    
    gas: 140000,
            from:web3.eth.accounts[0]})
            .then(function() {
    
     
                let div_id = candidates[candidateName]; 
                return

                contractInstance.totalVotesFor
                .call(candidateName).then(function(v) {
    
     
                $("#" + div_id).html(v.toString()); 
                $("#msg").html(""); 
                }); 
            }); 
        }); 
    } catch (err) {
    
     
        console.log(err); 
    } 
}

$( document ).ready(function() {
    
     
    if (typeof web3 !== 'undefined') {
    
     
        console.warn("Using web3 detected from external 
        source like Metamask") // Use Mist/MetaMask's provider 
        window.web3 = new Web3(web3.currentProvider); 
    } else {
    
     
        console.warn("No web3 detected. Falling back to 
        http://localhost:8545. You should remove this fallback when you 
        deploy live, as it's inherently insecure. Consider switching to 
        Metamask for development. More info here: 
        http://truffleframework.com/tutorials/truffle-and-metamask"); 
        // fallback - use your fallback strategy (local node / hosted node 
        + in-dapp id mgmt / fail) 
        window.web3 = new Web3(new
        Web3.providers
        .HttpProvider("http://localhost:8545")); 
    }
    Voting.setProvider(web3.currentProvider); 
    let candidateNames = Object.keys(candidates); 
    for (var i = 0; i < candidateNames.length; i++) {
    
     
        let name = candidateNames[i]; 

        Voting.deployed().then(function(contractInstance) {
    
     
            contractInstance.totalVotesFor
            .call(name).then(function(v) {
    
     
            $("#" + candidates[name])
            .html(v.toString()); 
            }); 
        }); 
    }
});

Line 7: When you compile and deploy the voting contract, truffle will store the abi and deployed address
in a json file under the build directory. We've discussed abi before. We'll use
this information to start a voting abstraction. We will then use this abstraction to create an instance of the Voting contract.

Line 14: Voting.deployed() returns a contract instance. Every call to truffle returns
a promise, which is why we use then() on every transaction call.

Console interaction requires reopening a new console

>truffle console
truffle(default)> 
Voting.deployed().then(function(contractInstance) 
{
    
    contractInstance.voteForCandidate('Alice').then(function(v) 
{
    
    console.log(v)})})
{
    
     blockHash: 
'0x7229f668db0ac335cdd0c4c86e0394a35dd471a1095b8fafb52ebd76714
33156',
blockNumber: 469628,
contractAddress: null,
....
....
truffle(default)> 
Voting.deployed().then(function(contractInstance) 
{
    
    contractInstance.totalVotesFor.call('Alice').then(function(v) 
{
    
    console.log(v)})})
{
    
     [String: '1'] s: 1, e: 0, c: [ 1] }

You need to wait a bit after calling the voteForCandidate method, because it takes time to send
the transaction; note that all calls to truffle return a promise, which is why you see each
response wrapped under the then() function; also the totalVoteFor() method It can also be called directly without .call()
, and no transaction will be sent.

The outgoing transactions can be found in the log output file of geth; if we are connected to the test network
, it can be queried at https://rinkeby.etherscan.io on etherscan.

You can see that the default gasPrice of truffle is 100GWei. If you feel distressed, you can change it in truffle.js, add gasPrice: 1000000000 to change it to 1GWei, and restart the truffle console to take effect.

Web interaction
Start the server with webpack in the console:

>npm run dev

The default port is 8080. You can see the page by visiting localhost:8080 in the browser.
If metamask is installed, index.js will automatically detect and use metamask as the web3
provider; so we should pay attention to switch metamask to the network we are currently connected to.

Guess you like

Origin blog.csdn.net/david2000999/article/details/120472092