Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- pragma solidity ^0.4.18;
- import "./Ownable.sol";
- contract RentalContract is Ownable {
- struct Article{
- uint id;
- address seller;
- address buyer;
- string propaddress;
- uint256 rental_price;
- string description;
- bool available;
- string contact;
- }
- mapping(uint => Article) public articles;
- uint articleCounter;
- event LogSellArticle(
- uint indexed _id,
- address indexed _seller,
- string _propaddress,
- uint256 _rental_price,
- string _description,
- bool _available,
- string _contact
- );
- event LogBuyArticle(
- uint indexed _id,
- address indexed _seller,
- address indexed _buyer,
- string _propaddress,
- uint256 _rental_price,
- string _description,
- bool _available,
- string _contact
- );
- function kill() public onlyOwner {
- selfdestruct(owner);
- }
- function sellArticle(string _propaddress, uint256 _rental_price, string _description, bool _available, string _contact) public {
- articleCounter++;
- articles[articleCounter] = Article(
- articleCounter,
- msg.sender,
- 0x0,
- _propaddress,
- _rental_price,
- _description,
- _available,
- _contact
- );
- LogSellArticle(articleCounter, msg.sender, _propaddress, _rental_price, _description, _available, _contact);
- }
- function getNumberOfArticles() public view returns (uint){
- return articleCounter;
- }
- function getArticlesForSale() public view returns (uint[]){
- uint[] memory articleIds = new uint[](articleCounter);
- uint numberOfArticlesForSale = 0;
- for(uint i = 1; i <= articleCounter; i++){
- if(articles[i].buyer == 0x0){
- articleIds[numberOfArticlesForSale] = articles[i].id;
- numberOfArticlesForSale++;
- }
- }
- uint[] memory forSale = new uint[](numberOfArticlesForSale);
- for(uint j = 0; j < numberOfArticlesForSale; j++){
- forSale[j] = articleIds[j];
- }
- return forSale;
- }
- function buyArticle(uint _id) payable public {
- require(articleCounter > 0);
- require(_id > 0 && _id <= articleCounter);
- Article storage article = articles[_id];
- require(article.buyer == 0x0);
- require(msg.sender != article.seller);
- require(msg.value == article.rental_price);
- article.buyer = msg.sender;
- article.seller.transfer(msg.value);
- LogBuyArticle(_id, article.seller, article.buyer, article.propaddress, article.rental_price, article.description, article.available, article.contact);
- }
- }
- <!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>Rent My Place</title>
- <!-- Title will appear as a tab in browser on webpage -->
- <!-- 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]-->
- <!-- Application -->
- <link href="css/app.css" rel="stylesheet">
- </head>
- <body>
- <div class="container">
- <!-- container that contains title panel-->
- <div class="jumbotron text-center">
- <p style="font-size:80px;padding: 1em;padding-top: 10px;padding-bottom: 10px; border:10px;border-style:solid;border-color:#c3c3c3;">
- <font color = "#880015" >Rent My Place</font></p>
- </div>
- <div class="col-md-12" id="article-list">
- <div class="row">
- <div class="col-lg-12">
- <p id="account" class="welcome pull-right"></p>
- <p id="accountBalance" class="welcome pull-left"></p>
- </div>
- </div>
- <div class="row panel panel-default">
- <div class="panel-heading clearfix">
- <div class="panel-title">
- <p style="font-size:24px;padding: 1em;padding-top: 10px;padding-bottom: 10px; border:5px;border-style:solid;border-color:#c3c3c3;">
- <font color = "#880015">Renter's Tip: </font><font color = "#000000">Inspect the property before you send money.</font><br><font color = "#880015">Landlord's Tip: </font><font color = "#000000">Meet prospective tenants in person.</font></p>
- <!-- Button that opens second window to a form to fill out-->
- <button class="btn btn-info btn-lg pull-right" data-toggle="modal" data-target="#sellArticle">Post a Rental</button>
- </div>
- </div>
- <!-- when the event button gets click, it will show the list-->
- <ul id="events" class="collapse list-group"></ul>
- </div>
- <div id="articlesRow" class="row">
- <!-- ARTICLES with pertinent item information LOAD HERE -->
- </div>
- </div>
- </div>
- <!--Result that is displayed after input-->
- <div id="articleTemplate" style="display: none;">
- <div class="row-lg-12">
- <div class="panel panel-default panel-article">
- <div class="panel-heading">
- <h3 class="panel-title"></h3>
- </div>
- <div class="panel-body">
- <strong>Baths</strong>: <span class="baths"></span><br/>-->
- <strong>Address</strong>: <span class="propaddress"></span><br/>
- <strong>Rental Price</strong>: <span class="rental_price"></span><br/>
- <strong>Description</strong>: <span class="description"></span><br/>
- <strong>Property is available for showing</strong>: <span class="available"></span><br/>
- <strong>Contact Email</strong>: <span class="contact"></span><br/>
- </div>
- <div class="panel-footer">
- <button type="button" class= "btn btn-primary btn-success btn-buy" onclick="App.buyArticle(); return false;">Buy</button>
- </div>
- </div>
- </div>
- </div>
- <!-- Modal form to sell an article -->
- <div class="modal fade" id="sellArticle" role="dialog">
- <div class="modal-dialog">
- <!-- Modal content-->
- <div class="modal-content">
- <div class="modal-header">
- <button type="button" class="close" data-dismiss="modal">×</button>
- <h4 class="modal-title">Rent Your Place</h4>
- </div>
- <div class="modal-body">
- <div class="row">
- <div class="col-lg-12">
- <form>
- <div class="form-group">
- <label for="propaddress">Address</label>
- <input type="text" class="form-control" id="propaddress" placeholder="Enter the address">
- </div>
- <div class="form-group">
- <label for="rental_price">Rent (in USD) </label>
- <input type="text" class="form-control" id="rental_price" placeholder="$" pattern="[0-9]+([.,][0-9]+)?">
- </div>
- <div class="form-group">
- <label for="description">Description</label>
- <textarea type="text" class="form-control vresize" id="description" placeholder="Describe your property" maxlength="255"></textarea>
- </div>
- <div class="form-group">
- <label for="available"></label>
- <input type="checkbox" id="available"> Property is available for showing
- </div>
- <div class="form-group">
- <label for="contact">Contact Email</label>
- <input type="text" class="form-control" id="contact" placeholder="Enter your contact email" >
- </div>
- </form>
- </div>
- </div>
- </div>
- <div class="modal-footer">
- <button type="button" class="btn btn-primary btn-success" data-dismiss="modal" onclick="App.sellArticle(); return false;">Submit</button>
- <button type="button" class="btn" data-dismiss="modal">Close</button>
- </div>
- </div>
- </div>
- </div>
- <div id="footer" class="container">
- <nav class="navbar navbar-default navbar-fixed-bottom">
- <div class="navbar-inner navbar-content-center text-center">
- <p class="text-muted" credit><a href="http://www.axbean.com">AXbean</a> - © 2018</a></p>
- </div>
- </nav>
- </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/RentalApp.js"></script>
- <script src="js/bootstrap.min.js"></script>
- <script src="js/web3.min.js"></script>
- <script src="js/truffle-contract.js"></script>
- </body>
- </html>
- App = {
- web3Provider: null,
- contracts: {},
- account: 0x0,
- loading: false,
- init: function() {
- return App.initWeb3();
- },
- initWeb3: function() {
- // initialize web3
- if(typeof web3 !== 'undefined') {
- //reuse the provider of the Web3 object injected by Metamask
- App.web3Provider = web3.currentProvider;
- } else {
- //create a new provider and plug it directly into our local node
- App.web3Provider = new Web3.providers.HttpProvider('http://localhost:7545');
- }
- web3 = new Web3(App.web3Provider);
- App.displayAccountInfo();
- return App.initContract();
- },
- displayAccountInfo: function() {
- web3.eth.getCoinbase(function(err, account) {
- if(err === null) {
- App.account = account;
- $('#account').text(account);
- web3.eth.getBalance(account, function(err, balance) {
- if(err === null) {
- $('#accountBalance').text(web3.fromWei(balance, "ether") + " ETH");
- }
- })
- }
- });
- },
- initContract: function() {
- $.getJSON('RentalContract.json', function(chainListArtifact) {
- // get the contract artifact file and use it to instantiate a truffle contract abstraction
- App.contracts.RentalContract = TruffleContract(chainListArtifact);
- // set the provider for our contracts
- App.contracts.RentalContract.setProvider(App.web3Provider);
- // listen to events
- App.listenToEvents();
- // retrieve the article from the contract
- return App.reloadArticles();
- });
- },
- reloadArticles: function() {
- //avoid reentry bugs
- if(App.loading){
- return;
- }
- App.loading = true;
- // refresh account information because the balance might have changed
- App.displayAccountInfo();
- var chainListInstance;
- App.contracts.RentalContract.deployed().then(function(instance) {
- chainListInstance = instance;
- return chainListInstance.getArticlesForSale();
- }).then(function(articlesIds) {
- // retrieve the article placeholder and clear it
- $('#articlesRow').empty();
- for(var i = 0; i < articlesIds.length; i++){
- var articleId = articlesIds[i];
- chainListInstance.articles(articleId.toNumber()).then(function(article){
- App.displayArticle(article[0], article[1], article[3], article[4], article[5], article[6], article[7]);
- });
- }
- App.loading = false;
- }).catch(function(err) {
- console.error(err.message);
- App.loading = false;
- });
- },
- displayArticle: function(id, seller, propaddress, rental_price, description, available, contact) {
- var articlesRow = $('#articlesRow');
- var articleTemplate = $("#articleTemplate");
- articleTemplate.find('.propaddress').text(propaddress);
- articleTemplate.find('.rental_price').text('$' + rental_price);
- articleTemplate.find('.description').text(description);
- articleTemplate.find('.available').text(available);
- articleTemplate.find('.contact').text(contact);
- articleTemplate.find('.btn-buy').attr('data-id', id);
- //seller
- if(seller == App.account){
- articleTemplate.find('.article-seller').text("You");
- articleTemplate.find('.btn-buy').hide();
- }else{
- articleTemplate.find('.article-seller').text(seller);
- articleTemplate.find('.btn-buy').show();
- }
- //add this new article
- articlesRow.append(articleTemplate.html());
- },
- sellArticle: function() {
- // retrieve the detail of the article
- var _description = $('#description').val();
- var _propaddress = $('#propaddress').val();
- var _rental_price = $('#rental_price').val();
- var _available = $('#available').val();
- var _contact = $('#contact').val();
- App.contracts.RentalContract.deployed().then(function(instance) {
- //return instance.sellArticle(_description, _beds, _baths, _propaddress, _rental_price, _property_type, _available, _contact_email, {
- return instance.sellArticle(_propaddress, _rental_price, _description, _available, _contact,{
- from: App.account,
- gas: 500000
- });
- }).then(function(result) {
- }).catch(function(err) {
- console.error(err);
- });
- },
- // listen to events triggered by the contract
- listenToEvents: function() {
- App.contracts.RentalContract.deployed().then(function(instance) {
- instance.LogSellArticle({}, {}).watch(function(error, event) {
- if (!error) {
- $("#events").append('<li class="list-group-item">' + event.args._propaddress + ' is now for sale</li>');
- } else {
- console.error(error);
- }
- App.reloadArticles();
- });
- instance.LogBuyArticle({}, {}).watch(function(error, event) {
- if (!error) {
- $("#events").append('<li class="list-group-item">' + event.args._buyer + ' bought ' + event.args._propaddress + '</li>');
- } else {
- console.error(error);
- }
- App.reloadArticles();
- });
- });
- },
- buyArticle: function() {
- event.preventDefault();
- // retrieve the article price and data
- var _articleId = $(event.target).data('id');
- var _price = parseFloat($(event.target).data('value'));
- App.contracts.RentalContract.deployed().then(function(instance){
- return instance.buyArticle(_articleId, {
- from: App.account,
- value: web3.toWei(_price, "ether"),
- gas: 500000
- });
- }).catch(function(error) {
- console.error(error);
- });
- }
- };
- $(function() {
- $(window).load(function() {
- App.init();
- });
- });
Add Comment
Please, Sign In to add comment