Created
April 2, 2017 07:38
-
-
Save rob-Hitchens/a61c422baa08778a8fb08ffce8d69302 to your computer and use it in GitHub Desktop.
MODULE 2 - INITIAL STATE
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| /////////////////////////////////////////////////////////// | |
| // For training purposes. | |
| // Solidity Contract Factory | |
| // Initial Completed State | |
| // Copyright (c) 2017, Rob Hitchens, all rights reserved. | |
| // Not suitable for actual use | |
| ////////////////////////////////////////////////////////// | |
| var app = angular.module('campaignApp', []); | |
| // Configure preferences for the Angular App | |
| app.config(function( $locationProvider) { | |
| $locationProvider.html5Mode({ | |
| enabled: true, | |
| requireBase: false | |
| }); | |
| }); | |
| // Define an App Controller with some Angular features | |
| app.controller("campaignController", | |
| [ '$scope', '$location', '$http', '$q', '$window', '$timeout', | |
| function($scope, $location, $http, $q, $window, $timeout) { | |
| // Everything we do will be inside the App Controller | |
| $scope.contributionLog=[]; | |
| Campaign.deployed() | |
| .then(function(_instance) { | |
| $scope.contract = _instance; | |
| console.log("The contract:", $scope.contract); | |
| // don't want this to happen before the contract is known | |
| $scope.contributionWatcher = $scope.contract.LogContribution( {}, {fromBlock: 0}) | |
| .watch(function(err, newContribution) { | |
| if(err) { | |
| console.log("Error watching contribution events", err); | |
| } else { | |
| console.log("Contribution", newContribution); | |
| newContribution.args.amount = newContribution.args.amount.toString(10); | |
| $scope.contributionLog.push(newContribution); | |
| return $scope.getCampaignStatus(); | |
| } | |
| }) | |
| return $scope.getCampaignStatus(); | |
| }) | |
| // Contribute to the campaign | |
| $scope.contribute = function() { | |
| if(parseInt($scope.newContribution)<=0) return; | |
| console.log("contribution", $scope.newContribution); | |
| var newContribution = $scope.newContribution; | |
| $scope.newContribution = ""; | |
| $scope.contract.contribute({from: $scope.account, value: parseInt(newContribution), gas: 900000}) | |
| .then(function(txn) { | |
| console.log("Transaction Hash", txn); | |
| return $scope.getCampaignStatus(); | |
| }) | |
| .catch(function(error) { | |
| console.log("Error processing contribution", error); | |
| }); | |
| } | |
| // Get the campaign status | |
| $scope.getCampaignStatus = function() { | |
| return $scope.contract.fundsRaised({from: $scope.account}) | |
| .then(function(_fundsRaised) { | |
| console.log("fundsRaised", _fundsRaised.toString(10)); | |
| $scope.campaignFundsRaised = _fundsRaised.toString(10); | |
| return $scope.contract.goal({from: $scope.account}); | |
| }) | |
| .then(function(_goal) { | |
| console.log("goal", _goal.toString(10)); | |
| $scope.campaignGoal = _goal.toString(10); | |
| return $scope.contract.deadline({from: $scope.account}); | |
| }) | |
| .then(function(_deadline) { | |
| console.log("deadline", _deadline.toString(10)); | |
| $scope.campaignDeadline = _deadline.toString(10); | |
| return $scope.contract.owner({from: $scope.account}); | |
| }) | |
| .then(function(_owner) { | |
| console.log("owner", _owner); | |
| $scope.campaignOwner = _owner; | |
| return $scope.contract.isSuccess({from: $scope.account}); | |
| }) | |
| .then(function(_isSuccess) { | |
| console.log("isSuccess", _isSuccess); | |
| $scope.campaignIsSuccess = _isSuccess; | |
| return $scope.contract.hasFailed({from: $scope.account}); | |
| }) | |
| .then(function(_hasFailed) { | |
| console.log("hasFailed", _hasFailed); | |
| $scope.campaignHasFailed = _hasFailed; | |
| return $scope.getCurrentBlockNumber(); | |
| }) | |
| } | |
| // Get the Block Number | |
| $scope.getCurrentBlockNumber = function() { | |
| web3.eth.getBlockNumber(function(err, bn) { | |
| if(err) { | |
| console.log("error getting block number", err); | |
| } else { | |
| console.log("Current Block Number", bn); | |
| $scope.blockNumber = bn; | |
| $scope.$apply(); | |
| } | |
| }) | |
| } | |
| // Work with the first account | |
| web3.eth.getAccounts(function(err, accs) { | |
| if(err != null) { | |
| alert("There was an error fetching your accounts."); | |
| return; | |
| } | |
| if(accs.length==0) { | |
| alert("Couldn't get any accounts. Make sure your Ethereum client is configured correctly."); | |
| return; | |
| } | |
| $scope.accounts = accs; | |
| $scope.account = $scope.accounts[0]; | |
| console.log("using account", $scope.account); | |
| web3.eth.getBalance($scope.account, function(err, _balance) { | |
| $scope.balance = _balance.toString(10); | |
| console.log("balance",$scope.balance); | |
| $scope.balanceInEth = web3.fromWei($scope.balance, "ether"); | |
| $scope.$apply(); | |
| }); | |
| }); | |
| }]); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| /////////////////////////////////////////////////////////// | |
| // For training purposes. | |
| // Solidity Contract Factory | |
| // Initial Completed State | |
| // Copyright (c) 2017, Rob Hitchens, all rights reserved. | |
| // Not suitable for actual use | |
| ////////////////////////////////////////////////////////// | |
| pragma solidity ^0.4.6; | |
| contract Campaign { | |
| address public owner; | |
| uint public deadline; | |
| uint public goal; | |
| uint public fundsRaised; | |
| bool public refundsSent; | |
| struct FunderStruct { | |
| address funder; | |
| uint amount; | |
| } | |
| FunderStruct[] public funderStructs; | |
| event LogContribution(address sender, uint amount); | |
| event LogRefundSent(address funder, uint amount); | |
| event LogWithdrawal(address beneficiary, uint amount); | |
| function Campaign(uint campaignDuration, uint campaignGoal) { | |
| owner = msg.sender; | |
| deadline = block.number + campaignDuration; | |
| goal = campaignGoal; | |
| } | |
| function isSuccess() | |
| public | |
| constant | |
| returns(bool isIndeed) | |
| { | |
| return(fundsRaised >= goal); | |
| } | |
| function hasFailed() | |
| public | |
| constant | |
| returns(bool hasIndeed) | |
| { | |
| return(fundsRaised < goal && block.number > deadline); | |
| } | |
| function contribute() | |
| public | |
| payable | |
| returns(bool success) | |
| { | |
| if(msg.value==0) throw; | |
| if(isSuccess()) throw; | |
| if(hasFailed()) throw; | |
| fundsRaised += msg.value; | |
| FunderStruct memory newFunder; | |
| newFunder.funder = msg.sender; | |
| newFunder.amount = msg.value; | |
| funderStructs.push(newFunder); | |
| LogContribution(msg.sender, msg.value); | |
| return true; | |
| } | |
| function withdrawFunds() | |
| public | |
| returns(bool success) | |
| { | |
| if(msg.sender != owner) throw; | |
| if(!isSuccess()) throw; | |
| uint amount = this.balance; | |
| if(!owner.send(amount)) throw; | |
| LogWithdrawal(owner, amount); | |
| return true; | |
| } | |
| function sendRefunds() | |
| public | |
| returns(bool success) | |
| { | |
| if(msg.sender != owner) throw; | |
| if(refundsSent) throw; | |
| if(!hasFailed()) throw; | |
| uint funderCount = funderStructs.length; | |
| for(uint i=0; i<funderCount; i++) { | |
| if(!funderStructs[i].funder.send(funderStructs[i].amount)) { | |
| // to do: deal with the send failure case | |
| } | |
| LogRefundSent(funderStructs[i].funder, funderStructs[i].amount); | |
| } | |
| refundsSent = true; | |
| return true; | |
| } | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| <!-- | |
| /////////////////////////////////////////////////////////// | |
| // For training purposes. | |
| // Solidity Contract Factory | |
| // Initial Completed State | |
| // Copyright (c) 2017, Rob Hitchens, all rights reserved. | |
| // Not suitable for actual use | |
| ////////////////////////////////////////////////////////// | |
| --> | |
| <!DOCTYPE html> | |
| <html> | |
| <head> | |
| <base href="." /> | |
| <title>Campaign</title> | |
| <!-- Bootstrap CSS --> | |
| <link rel="stylesheet" | |
| type="text/css" href="http://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" | |
| crossorigin="anonymous" /> | |
| <!-- JQuery --> | |
| <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script> | |
| <!-- Bootstrap Javascript --> | |
| <script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script> | |
| <!-- App Stylesheet --> | |
| <link rel="stylesheet" type="text/css" href="./app.css" /> | |
| <!-- App Controller --> | |
| <script src="./app.js"></script> | |
| </head> | |
| <!-- Bind the Web Page to the App Controller --> | |
| <body ng-cloak ng-controller="campaignController"> | |
| <!-- Everything we do will go below here. --> | |
| <div class="container-fluid"> | |
| <div class="row"> | |
| <div class="col-md-12"> | |
| <h3><span class="black">Campaign</span>Status</h3> | |
| <h6>Your Account: {{ account }}: {{ balance }} (wei) {{ balanceInEth }} (ETH) </h6> | |
| <h6>Contract Address: {{ contract.address }} Owner: {{ campaignOwner }}</h6> | |
| <h4> | |
| Funds Raised: {{ campaignFundsRaised }} | |
| Deadline: {{ campaignDeadline }} | |
| Goal: {{ campaignGoal }} | |
| Block Number: {{ blockNumber }} | |
| <div class="green" ng-if="campaignIsSuccess">Success!</div> | |
| <div class="red" ng-if="campaignHasFailed">Failed!</div> | |
| </h4> | |
| <form id="contributeForm" ng-submit="contribute()"> | |
| <input type="text" name="newContribution" ng-model="newContribution" required/> | |
| <input type="submit" class="btn btn-primary" value="Contribute"/> | |
| </form> | |
| <br/> | |
| <div class="panel panel-default"> | |
| <div class="panel-body"> | |
| <table class="table table-striped table-bordered"> | |
| <tr> | |
| <th>Funder</th> | |
| <th>Block</th> | |
| <th>Amount</th> | |
| </tr> | |
| <tr ng-repeat="contribution in contributionLog"> | |
| <td>{{ contribution.args.sender }}</td> | |
| <td>{{ contribution.blockNumber }}</td> | |
| <td>{{ contribution.args.amount }}</td> | |
| </tr> | |
| </table> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| <!-- Everything we do will go above here. --> | |
| <!-- Wait for the document to load, then start the App Controller --> | |
| <script> | |
| window.addEventListener('load', function() { | |
| angular.bootstrap(document, ['campaignApp']); | |
| }); | |
| </script> | |
| </body> | |
| </html> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| /////////////////////////////////////////////////////////// | |
| // For training purposes. | |
| // Solidity Contract Factory | |
| // Initial Completed State | |
| // Copyright (c) 2017, Rob Hitchens, all rights reserved. | |
| // Not suitable for actual use | |
| /////////////////////////////////////////////////////////// | |
| var DefaultBuilder = require("truffle-default-builder"); | |
| module.exports = { | |
| build: new DefaultBuilder({ | |
| "index.html": "index.html", | |
| "app.js": [ | |
| "javascripts/_vendor/angular.min.js", | |
| "javascripts/app.js" | |
| ], | |
| "app.css": [ | |
| "stylesheets/app.css" | |
| ], | |
| "images/": "images/" | |
| }), | |
| networks: { | |
| development: { | |
| host: "localhost", | |
| port: 8545, | |
| network_id: "*" // Match any network id | |
| } | |
| } | |
| }; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment