我正在尝试使用Blockchain在松露框架上制作投票应用程序。来自网络的数据不会在网页上呈现。仅显示加载,但即使我已通过区块链帐户从Ganache连接到我的元掩码扩展,也不会显示实际内容。这是我的代码:
Election.sol
pragma solidity ^0.5.0;
contract Election {
// Model a Candidate for first past the post system
struct Candidatepost {
uint id;
string name;
uint voteCount;
}
// Model as candidate for proportional party system
struct Candidateparty {
uint id;
string name;
uint voteCount;
}
// Store accounts that have voted
mapping(address => bool) public voters;
// Store Candidates
// Fetch Candidate
mapping(uint => Candidatepost) public cand_post;
mapping(uint => Candidateparty) public cand_party;
// Store Candidates Count
uint public partyCount;
uint public postCount;
uint[] public candidatesCount = [postCount,partyCount];
constructor () public {
addpostCandidate("Candidate 1");
addpostCandidate("Candidate 2");
addpartyCandidate("Candidate 1");
addpartyCandidate("Candidate 2");
candidatesCount = [postCount,partyCount];
}
function addpostCandidate (string memory _name) private {
postCount ++;
cand_post[postCount] = Candidatepost(postCount, _name, 0);
}
function addpartyCandidate (string memory _name) private {
partyCount ++;
cand_party[partyCount] = Candidateparty(partyCount, _name, 0);
}
// voted event
event votedEvent (
uint indexed _candidateId1,
uint indexed _candidateId2
);
function vote (uint _candidateId1, uint _candidateId2) public {
// require that they haven't voted before
require(!voters[msg.sender]);
// require a valid candidate
require(_candidateId1 > 0 && _candidateId1 <= postCount && _candidateId2 > 0 && _candidateId2 <= partyCount);
// record that voter has voted
voters[msg.sender] = true;
// update candidate vote Count
cand_post[_candidateId1].voteCount ++;
cand_party[_candidateId2].voteCount ++;
// trigger voted event
emit votedEvent(_candidateId1, _candidateId2);
}
}
App.js
App = {
web3Provider: null,
contracts: {},
account: '0x0',
init: function() {
return App.initWeb3();
},
initWeb3: function() {
// TODO: refactor conditional
if (typeof web3 !== 'undefined') {
// If a web3 instance is already provided by Meta Mask.
App.web3Provider = web3.currentProvider;
web3 = new Web3(web3.currentProvider);
} else {
// Specify default instance if no web3 instance provided
App.web3Provider = new Web3.providers.HttpProvider('http://localhost:7545');
web3 = new Web3(App.web3Provider);
}
return App.initContract();
},
initContract: function() {
$.getJSON("Election.json", function(election) {
// Instantiate a new truffle contract from the artifact
App.contracts.Election = TruffleContract(election);
// Connect provider to interact with contract
App.contracts.Election.setProvider(App.web3Provider);
App.listenForEvents();
return App.render();
});
},
// Listen for events emitted from the contract
listenForEvents: function() {
App.contracts.Election.deployed().then(function(instance) {
// Restart Chrome if you are unable to receive this event
// This is a known issue with Metamask
// https://github.com/MetaMask/metamask-extension/issues/2393
instance.votedEvent({}, {
fromBlock: 0,
toBlock: 'latest'
}).watch(function(error, event) {
console.log("event triggered", event)
// Reload when a new vote is recorded
App.render();
});
});
},
render: function() {
var electionInstance;
var loader = $("#loader");
var content = $("#content");
loader.show();
content.hide();
// Load account data
web3.eth.getCoinbase(function(err, account) {
if (err === null) {
App.account = account;
$("#accountAddress").html("Your Account: " + account);
}
});
//load contract data
App.contracts.Election.deployed().then(function(instance) {
electionInstance = instance;
return electionInstance.candidatesCount();
}).then(function(1) {
var postcandidatesResults = $("#postcandidatesResults");
postcandidatesResults.empty();
var partycandidatesResults = $("#partycandidatesResults");
partycandidatesResults.empty();
var postcandidatesSelect = $('#postcandidatesSelect');
postcandidatesSelect.empty();
var partycandidatesSelect = $('#partycandidatesSelect');
partycandidatesSelect.empty();
for (var i = 1; i <= 2; i++) {
electionInstance.cand_post(i).then(function(candidate) {
var id = candidate[0];
var name = candidate[1];
var voteCount = candidate[2];
// Render candidate Result
var candidateTemplate = "<tr><th>" + id + "</th><td>" + name + "</td><td>" + voteCount + "</td></tr>";
postcandidatesResults.append(candidateTemplate);
// Render candidate ballot option
var candidateOption = "<option value='" + id + "' >" + name + "</ option>";
postcandidatesSelect.append(candidateOption);
});
}
for (var j = 1; j <= 2; j++) {
electionInstance.cand_party(i).then(function(candidate) {
var id2 = candidate[0];
var name2 = candidate[1];
var voteCount2 = candidate[2];
// Render candidate Result
var candidateTemplate2 = "<tr><th>" + id2 + "</th><td>" + name2 + "</td><td>" + voteCount2 + "</td></tr>";
partycandidatesResults.append(candidateTemplate2);
// Render candidate ballot option
var candidateOption2 = "<option value='" + id2 + "' >" + name2 + "</ option>";
partycandidatesSelect.append(candidateOption2);
});
}
return electionInstance.voters(App.account);
}).then(function(hasVoted) {
// Do not allow a user to vote
if(hasVoted) {
$('form').hide();
}
loader.hide();
content.show();
}).catch(function(error) {
console.warn(error);
});
},
castVote: function() {
var candidateId1 = $('#postcandidatesSelect').val();
var candidateId2 = $('#partycandidatesSelect').val();
App.contracts.Election.deployed().then(function(instance) {
return instance.vote(candidateId1, candidateId2, { from: App.account });
}).then(function(result) {
// Wait for votes to update
$("#content").hide();
$("#loader").show();
}).catch(function(err) {
console.error(err);
});
}
};
$(function() {
$(window).load(function() {
App.init();
});
});
的index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<!-- The above 3 meta tags *must* come first in the head; any other head content must come *after* these tags -->
<title>Election Results</title>
<!-- Bootstrap -->
<link href="css/bootstrap.min.css" rel="stylesheet">
<!-- HTML5 shim and Respond.js for IE8 support of HTML5 elements and media queries -->
<!-- WARNING: Respond.js doesn't work if you view the page via file:// -->
<!--[if lt IE 9]>
<script src="https://oss.maxcdn.com/html5shiv/3.7.3/html5shiv.min.js"></script>
<script src="https://oss.maxcdn.com/respond/1.4.2/respond.min.js"></script>
<![endif]-->
</head>
<body>
<div class="container" style="width: 650px;">
<div class="row">
<div class="col-lg-12">
<h1 class="text-center">
<div class="row d-flex justify-content-center" style="border:none;background:white;">
<div class="col-md-1 col-3">
<img class="mx-auto d-block img-fluid" src="images/logo.png" style="" alt="">
</div>
</div></h1>
<hr/>
<br/>
<h1 class="text-center">National Election-2075</h1>
<h1 class="text-center">Election Updates</h1>
<div id="loader">
<p class="text-center">Loading...</p>
</div>
<div id="content" style="display: none;">
<table class="table">
<thead>
<tr>
<th scope="col">#</th>
<th scope="col">Name</th>
<th scope="col">Votes</th>
</tr>
</thead>
<tbody id="postcandidatesResults">
</tbody>
</table>
<hr/>
<table class="table">
<thead>
<tr>
<th scope="col">#</th>
<th scope="col">Name</th>
<th scope="col">Votes</th>
</tr>
</thead>
<tbody id="partycandidatesResults">
</tbody>
</table>
<hr/>
<form onSubmit="App.castVote(); return false;">
<div class="form-group">
<label for="postcandidatesSelect">Select Candidate</label>
<select class="form-control" id="postcandidatesSelect">
</select>
</div>
<div class="form-group">
<label for="partycandidatesSelect">Select Candidate</label>
<select class="form-control" id="partycandidatesSelect">
</select>
</div>
<button type="submit" class="btn btn-primary">Vote</button>
<hr />
</form>
<p id="accountAddress" class="text-center"></p>
</div>
</div>
</div>
</div>
<!-- jQuery (necessary for Bootstrap's JavaScript plugins) -->
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script>
<!-- Include all compiled plugins (below), or include individual files as needed -->
<script src="js/bootstrap.min.js"></script>
<script src="js/web3.min.js"></script>
<script src="js/truffle-contract.js"></script>
<script src="js/app.js"></script>
</body>
</html>
对区块链的任何调用都是异步(返回一个promise)。您需要使用.then()处理promise或者您可以使用async await。在选举实例之后链接的任何东西基本上都是异步的。例如:
electionInstance.candidatesCount();
electionInstance.cand_party
electionInstance.voters