赞
踩
下面是基于 Linux的安装指南。这要求预先安装 nodeis 和 npm,再用 npm安装 ganache-cli、web3 和 solc0.4.25(当时版本)
mkdir simple_voting.dapp
cd simple_voting.dapp
npm init
npm install ganache-cli web3@0.20.1 solc
node node_modules/.bin/ganache-cli
输出以下内容则成功
Ganache-cli是一个用于以太坊开发和测试的命令行工具。它提供了一个本地的以太坊区块链环境,可以用于开发智能合约、部署合约和进行交易等操作。使用ganache-cli,开发者可以在本地快速搭建一个私有的以太坊网络,而无需连接到真实的以太坊网络。它还提供了一些方便的功能,如创建模拟账户、生成测试数据、调整区块链状态等,有助于简化以太坊应用程序的开发和测试过程。
Voting 的合约,这个合约有以下内容:
pragma solidity ^0.4.22; // 选举合约 contract Voting { // 候选人列表 bytes32[] public candidateList; // 候选人得票数映射 mapping(bytes32 => uint8) public votesReceived; // 构造函数,初始化候选人列表 constructor(bytes32[] candiListNames) public { candidateList = candiListNames; } // 检查候选人是否有效 function validcandidate(bytes32 candidateName) internal view returns(bool) { for (uint8 i = 0; i < candidateList.length; i++) { if (candidateName == candidateList[i]) return true; } return false; } // 投票函数 function vote(bytes32 candidateName) public { require(validcandidate(candidateName)); // 确保候选人有效 votesReceived[candidateName] += 1; // 增加候选人得票数 } // 查询某候选人的总得票数 function totalVotesFor(bytes32 candidateName) view public returns(uint8) { require(validcandidate(candidateName)); // 确保候选人有效 return votesReceived[candidateName]; } }
在 node console输入以下命令
// 引入Web3库 var Web3 = require('web3') // 创建一个Web3实例,连接到本地的以太坊节点 var web3 = new Web3(new Web3.providers.HttpProvider("http://localhost:8545")) // 引入Solidity编译器 var solc = require('solc') // 读取Voting.sol文件中的源代码 var SourceCode = fs.readFileSync('Voting.sol').toString() // 编译Solidity源代码 var compiledCode = solc.compile(SourceCode) // 从编译结果中提取合约的ABI(应用程序二进制接口) var abi = JSON.parse(compiledCode.contracts[':Voting'].interface) // 获取编译后的字节码 var bytecode = compiledCode.contracts[':Voting'].bytecode // 使用ABI和字节码创建Voting合约对象 var Votingcontract = web3.eth.contract(abi) // 构造部署智能合约的交易对象 var deployTxObj = { data: bytecode, // 合约的字节码 from: web3.eth.accounts[0], // 从哪个账户发送部署交易 gas: 3000000 // 设定gas限制 } // 部署智能合约并创建合约实例,传入候选人名单['Alice','Bob','Cary'] var contractInstance = Votingcontract.new(['Alice','Bob','cary'], deployTxObj) // 给Alice投票 contractInstance.vote("Alice", {from: web3.eth.accounts[0]}); // 查询Alice的总得票数 contractInstance.totalVotesFor("Alice"); contractInstance.totalVotesFor("Alice").toString(); // 查询Bob的总得票数 contractInstance.totalVotesFor.call("Bob").toString(); // 给Cary投票 contractInstance.vote("Cary", {from: web3.eth.accounts[0]}); // 查询Cary的总得票数 contractInstance.totalVotesFor.call("Cary").toString();
<!DOCTYPE html> <html> <head> <title>Voting DApp</title> <link href='https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css' rel='stylesheet' type='text/css'> </head> <body class="container"> <h1>Simple Voting DApp</h1> <div> <table class="table table-bordered"> <thead> <tr> <th>Candidate</th> <th>Vote Count</th> </tr> </thead> <tbody> <tr> <td>Alice</td> <td id="candidate-1"></td> </tr> <tr> <td>Bod</td> <td id="candidate-2"></td> </tr> <tr> <td>Cary</td> <td id="candidate-3"></td> </tr> </tbody> </table> <input type="text" id="candidate" /> <a href="#" onclick="voteForCandidate" class="btn btn-primary">Vote</a> </div> </body> <script src="https://code.jquery.com/jquery-3.1.1.slim.min.js"></script> <script src="https://cdn.jsdelivr.net/npm/web3@4.8.0/dist/web3.min.js"></script> <script src="./index.js"></script> </html>
var web3 = new Web3(new Web3.providers.HttpProvider("http://localhost:8545")) var abi = JSON.parse('[{"constant":true,"inputs":[{"name":"candidate","type":"string"}],"name":"totalVotesFor","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"candidate","type":"string"}],"name":"votesReceived","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"candidate","type":"string"}],"name":"vote","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"candidateList","outputs":[{"name":"","type":"bytes32[]"}],"payable":false,"stateMutability":"view","type":"function"},{"inputs":[{"name":"candidateNames","type":"bytes32[]"}],"payable":false,"stateMutability":"nonpayable","type":"constructor"}]'); var contractAddr = "0x69c93bc7ef2cc9b0be438387204cee27b43281f6"; var VotingContract = web3.eth.contract(abi); var contractInstance = VotingContract.at(contractAddr); var candidates = { "Alice": "candidate-1", "Bod": "candidate-2", "Cary": "candidate-3" }; function voteForCandidate() { let candidateName = $("#candidate").val(); try { contractInstance.vote(candidateName, { from: web3.eth.accounts[0] },(err, res)=> { if(err) { console.log("Error:", err); } else { let id =candidates[candidateName]; let count =contractInstance.totalVotesFor(candidateName).toString(); $("#"+ id).html(count); } }) }catch (err){} } $(document).ready(function () { var candidateList = Object.keys(candidates); for (let i = 0; i < candidateList.length; i++){ let name = candidateList[i]; let count = contractInstance.totalVotesFor(name).toString(); $("#" + candidates[name]).html(count); } });
// 引入必要的模块 const fs = require('fs-extra'); // 用于文件操作的模块 const solc = require('solc'); // Solidity 编译器 const path = require('path'); // 用于处理文件路径的模块 // 定义合约编译结果存储的路径 const compiledPath = path.resolve(__dirname, '../compiled'); // 绝对路径 fs.readFileSync(compiledPath); // 读取编译路径的内容 fs.ensureDirSync(compiledPath); // 确保编译路径存在,如果不存在则创建 // 定义智能合约文件路径和读取合约源代码 const contractPath = path.resolve(__direname, '../contracts', 'Car.sol'); // 合约文件路径 const contractSource = fs.readFileSync(contractPath, 'utf-8'); // 读取合约源代码 // 使用 Solidity 编译器编译合约源代码 let compileResult = solc.compile(contractSource, 1); // 对合约源代码进行编译 // 输出编译结果 //consile.log(compileResult); // 检查是否有编译错误,如果有则抛出异常 if (Array.isArray(compileResult.errors) && compileResult.errors.length) { throw new Error(compileResult.errors[0]); } // 遍历编译结果中的合约对象 Object.keys(compileResult.contracts).forEach(name => { let contractName = name.replace(/^:/, ''); // 获取合约名称 let filePath = path.resolve(compiledPath, '../compiled', '$(contractName).json'); // 确定 JSON 文件的路径 fs.outputJsonSync(filePath, compileResult.contracts[name]); // 将合约编译结果写入 JSON 文件 console.log("Saying json file to", filePath); // 输出 JSON 文件的保存路径 })
// 引入web3库 const Web3 = require('web3'); // 创建web3实例并连接到本地节点 const web3 = new Web3(new Web3.providers.HttpProvider("http://localhost:8545")); // 引入文件系统模块 const fs = require('fs-extra'); // 引入路径模块 const path = require('path'); // 引入readline模块的Interface类 const { Interface } = require('readline'); // 指定合约编译后的JSON文件路径 const filePath = path.resolve(__dirname, '../compiled.json'); // 从指定路径读取合约编译后的JSON文件,并获取其中的Interface和bytecode字段 const { Interface, bytecode } = require(filePath); // 使用异步函数自执行 (async () => { // 获取以太坊节点上的账户列表 let accounts = await web3.eth.getAccounts(); // 计时开始 console.time("deploy time"); // 部署合约并返回部署结果 let result = await new web3.eth.Contract(JSON.parse(Interface)) .deploy({ data: bytecode, arguments: ["BMW"] }) .send({ from: accounts[0], gas: 500000 }); // 计时结束 console.timeEnd("deploy time"); // 打印合约地址 console.log("contract address", result.options.address); })();
const assert = require('assert') const path = require("path") const Web3 = require('web3') const ganache = require('ganache-cli'); const { describe, before, beforeEach } = require('node:test'); const web3 = new Web3(ganache.provider()); const contractPath = path.resolve(__dirname, './compiled/Car.json'); const { interface, bytecode } = require(contractPath); let contract; let accounts; const initialBrand = 'BMN'; describe('#contract', () => { beforeEach(async () => { accounts = await web3.eth.getAccounts(); contract = await web3.eth.Contract(JOSN.parse(interface)) .deploy({ data: bytecode, arguments: [initialBrand] }) .send({ from: accounts[0], gas: 300000 }); console.log('合约已部署!!'); }) it("deployed contract successfully", () => { assert.ok(contract.options.address); }) it ('should has ainitial brand', async () => { const brand = await contract.methods.brand().call(); assert.equal(brand, initialBrand); }); it ('should set a new brand', async () => { const newBrand = 'Audi'; await contract.methods.setBrand(newBrand) .send({ from: accounts[0] }); const brand = await contract.methods.brand().call(); assert.equal(brand, newBrand); }) })
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。