Siggg/culottes

View on GitHub
src/app/revolution/revolution.component.ts

Summary

Maintainability
D
2 days
Test Coverage
import { Component, OnInit } from "@angular/core";
import { Web3Service } from "../util/web3.service";
import { Router, ActivatedRoute } from '@angular/router';

declare let require: any;
const revolutionContractABI = require("../../../build/contracts/Revolution.json");
const factoryContractABI = require('../../../build/contracts/RevolutionFactory.json');

interface ICitizen {
   address: string;
   name: string;
   opened: boolean;
   matchesCriteria: boolean;
   sansculotteScale: number;
   privilegedScale: number
}

@Component({
  selector: "app-revolution",
  templateUrl: "./revolution.component.html",
  styleUrls: ["./revolution.component.css"]
})
export class RevolutionComponent implements OnInit {
  title: String = "<loading title>";
  criteria: String = "<loading criteria>";
  hashtag: String = "<loading hashtag>";
  hashtagWithoutSymbol: String = "<loading hashtag>";
  bastilleBalance: String = "?";
  distributionAmount: number = 0;
  distributionBlockPeriod: number = 0;
  distributionPeriod: number = 0;
  distributionPeriodUnit: String = "?";
  revolutionAddress: String = "0x0000000...";
  revolutionContract
  revolutionBlockchain: String = "";
  culottes: any;
  account: any;
  revolutionOwner: any;
  factoryOwner: any;
  web3Status: String = "Status of connection to your blockchain accounts";
  citizens: Array<ICitizen> = [];
  fullAddressShown: boolean = false;
  web3ModalActivity: String = "active";
  lockModalActivity: String = "";
  otherRevolutions = {};
  contractEvents: any;
  factoryAddress: string;
  canLockRevolution: boolean = false;
  citizensLoaderActivity: String = "active";
  loadingRevolutions: boolean = true;

  constructor(
    private web3Service: Web3Service,
    private route: ActivatedRoute,
    private router: Router) {}

  async ngOnInit() {
    // console.log("OnInit: " + this.web3Service);
    // console.log(this);
    this.getAddress();
    this.otherRevolutions = this.web3Service.revolutions;
    this.revolutionAddress = this
      .web3Service
      .revolutionAddress;
    this.revolutionContract = await this
      .web3Service
      .artifactsToContract(
        revolutionContractABI,
        this.revolutionAddress
      );
    this.revolutionBlockchain = this
      .web3Service
      .revolutionBlockchain;
    this.criteria = await this.revolutionContract.criteria();
    console.log("criteria: ", this.criteria);
    this.hashtag = await this.revolutionContract.hashtag()
      .then( (hashtag) => {
        if (hashtag == null || hashtag.length == 0) {
          hashtag = "#CulottesRevolution";
          this.hashtagWithoutSymbol = "CulottesRevolution";
        } else if (hashtag[0] != '#') {
            this.hashtagWithoutSymbol = hashtag;
            hashtag = '#' + hashtag;
        } else {
            this.hashtagWithoutSymbol = hashtag.substring(1);
        }
        return hashtag;
    });
    this.lockModalActivity = await this.revolutionContract.locked()
      .then( (locked) => {
        if (locked == true) {
          return "active";
        } else  {
          return "";
        }
      });
    this.bastilleBalance = await this.revolutionContract.bastilleBalance()
      .then( (result) => {
        if (result === null) {
          this
            .web3Service
            .web3Status
            .next("The balance of this bastille is null !");
          this
            .web3Service
            .checkNetwork();
        } else {
          this
            .web3Service
            .web3Status
            .next("Revolution ready.");
          this
            .web3Service
            .statusError = false;
          return this
            .web3Service
            .formatUnits(result, "ether");
        }
      })
      .catch( (error) => {
        this
          .web3Service
          .web3Status
          .next("An error occured while reading bastille balance: " + error);
      });
    this.distributionAmount = await this.revolutionContract.distributionAmount()
      .then( (result) => {
        if (result === null) {
          /* this
          .web3Service
          .web3Status
          .next("distributionAmount at this bastille is null!");*/
          this
            .web3Service
            .statusError = true;
        } else {
          return this
            .web3Service
            .formatUnits(result, "ether");
        }
      });
    this.distributionBlockPeriod = await this.revolutionContract
      .distributionBlockPeriod()
      .then( (blocks) => {
        // Convert distribution period from number of blocks to time units
        var seconds = blocks * 15; // about 15 seconds per block
        if (seconds < 60) {
          this.distributionPeriodUnit = "seconds";
          this.distributionPeriod = seconds;
        } else if (seconds < 3600) {
          this.distributionPeriodUnit = "minutes";
          this.distributionPeriod = seconds / 60;
        } else if (seconds < 3600 * 24) {
          this.distributionPeriodUnit = "hours";
          this.distributionPeriod = seconds / 3600;
        } else if (seconds < 3600 * 24 * 7) {
          this.distributionPeriodUnit = "days";
          this.distributionPeriod = seconds / 3600 / 24;
        } else if (seconds < 3600 * 24 * 30) {
          this.distributionPeriodUnit = "weeks";
          this.distributionPeriod = seconds / 3600 / 24 / 7;
        } else if (seconds < 3600 * 24 * 365) {
          this.distributionPeriodUnit = "months";
          this.distributionPeriod = seconds / 3600 / 24 / 30.5;
        } else {
          this.distributionPeriodUnit = "years";
          this.distributionPeriod = seconds / 3600 / 24 / 365.25;
        }
      return blocks;
    });
    if (this.web3Service.statusError) {
      this.web3ModalActivity = "active";
    } else {
      this.web3ModalActivity = "";
    }

    this.loadOtherRevolutionsThenCitizens();

    /* this.contractEvents = await this.revolutionContract
      .getPastEvents("allEvents", { fromBlock: 0, toBlock: "latest" })
      .then( (events) => {
        // console.log("All events: ", events);
        return events;
      })
      .catch( (error) => {
        console.error(error);
        this
          .web3Service
          .web3Status
          .next("An error occured while reading past events: " + error);
      }); */
    this.account = await this.web3Service.getSignerAddress();
    if (this.web3Service.statusError) {
        this.web3ModalActivity = "active";
      } else {
        this.web3ModalActivity = "";
      }
    console.log("account, revolutionOwner, factoryOwner: ", this.account, this.revolutionOwner, this.factoryOwner);
    if (this.account != undefined) {
      if (this.revolutionOwner == this.account || this.factoryOwner == this.account) {
        this.canLockRevolution = true;
      } else {
        this.canLockRevolution = false;
      }
    } else {
      this.canLockRevolution = false;
    }
  }

  public onCurrencyChange(event): void {  // event will give you full breif of action
    this.web3Service.currency = event.target.value;
  }
  
  public convertToFiat(amount) {
    return this
      .web3Service
      .convertToFiat(amount);
  }
  
  public currency() {
    return this.web3Service.currency;
  }
  
  public dappStatus() {
    return this.web3Service.dappStatus();
  }
  
  public onRevolutionRedirectTo(revolutionAddress): void {
    console.log("redirect to: /revolution/" + revolutionAddress);
    if (revolutionAddress == "menu") {
      return;
    } else {
      this.router
        .navigateByUrl('/revolution/' + revolutionAddress)
        .then( nav => {
            console.log("redirect succeeded: ", nav);
            this.ngOnInit();
            window.location.reload();
          }, err => {
        console.log("redirect failed: ", err);
          });
    }
  }

  public onRevolutionChange(event): void {  
    this.onRevolutionRedirectTo(event.target.value);
  }

  onCloseLockModal(): void {
    console.log("Closing lock modal");
    this.lockModalActivity = "";
  }
  
  getAddress(): void { 
    var ra = "";
    ra = this.route.snapshot.paramMap.get('address');
    if (ra != "" && ra != null) {
      this.revolutionAddress = ra;
      this.web3Service.revolutionAddress = ra;
    }
  }
  
  lockRevolution(): void {
    console.log("Trying to lock revolution");
    this.revolutionContract
      .lock()
      .send({from: this.account, value: 0, gas: 1000000})
      .on('transactionHash', function(hash) {
        /* component.transactionPending = true;
        component.confirmationProgress = 0;
        component.confirmationPercent = 0;
        component.transactionHashes.push(hash); */
        console.log('lock transactionHash received');
      })
      .on('confirmation', function(confirmationNumber, receipt) {
        /* component.transactionPending = true;
        component.confirmationProgress += 1; //confirmationNumber; // up to 24
        component.confirmationPercent = Math.round(100 * component.confirmationProgress / 24); */
        console.log('lock confirmation received, with number: ', confirmationNumber); // , component.confirmationPercent);
      })
      .on('receipt', function(receipt){
        // receipt example
        console.log('vote receipt received: ', receipt);
        /* component.transactionPending = false;
        component.transactionConfirmed = true; */
      })
      .on('error', function(error, receipt){
    console.log("lock error with receipt: ", receipt);
        console.error;
        /* this.showErrorMessageForVote = true;
        this.errorDuringVote = error; */
      }); // If there's an out of gas error the second parameter is the receipt.
    console.log("Tried locking revolution");
  }
  
  private async loadOtherRevolutionsThenCitizens() {
    this.revolutionOwner = await this.revolutionContract.owner();
    console.log("Revolution owner: ", this.revolutionOwner);
    console.log("Getting other revolutions from this factory");
    this.factoryAddress = await this.revolutionContract.factory();
    if (this.factoryAddress == null) {
      console.log("factoryAddress is null !");
      // TODO : figure out a way for web3 to work properly in e2e protractor tests
      this.factoryAddress = "0x598Bbb5819E8349Eb4D06D4f5aF149444aD8a11D";
    }
    console.log("factoryAddress: ", this.factoryAddress);
    let factoryContract = await this
      .web3Service
      .artifactsToContract(
        factoryContractABI,
        this.factoryAddress
      );
    console.log("Got factoryContract");
    this.factoryOwner = await factoryContract.owner();
    console.log("Factory owner: ", this.factoryOwner);
    let revolutionIndex = 0;
    let revolutionHashtag = "";
    let otherRevolution;
    do {
      console.log('revolutionIndex: ', revolutionIndex);
      try {
        revolutionHashtag = await factoryContract.hashtags(revolutionIndex);
      } catch (error) {
        console.log('error while retrieving hashtag: ', error);
        revolutionHashtag = null;
      }
      console.log('revolutionHashTag: ', revolutionHashtag);
      if (revolutionHashtag != null) {
        otherRevolution = await factoryContract.getRevolution(revolutionHashtag);
        console.log('  with revolution: ', otherRevolution);
      let otherRevolutionContract = await this
        .web3Service
        .artifactsToContract(
          revolutionContractABI,
          otherRevolution
        );
      let otherLocked = await otherRevolutionContract.locked();
        console.log('  is locked ? ', otherLocked);
        let otherBalance = await otherRevolutionContract.bastilleBalance();
        console.log('  with empty bastille balance? ', otherBalance.isZero());
        if (otherLocked != true || otherBalance.isZero() == false) {
          this.otherRevolutions[otherRevolution] = revolutionHashtag;
        }
        revolutionIndex += 1;
      }
    } while (revolutionHashtag != null);
    console.log('hashtags: ', this.otherRevolutions);
    this.loadingRevolutions = false;

    await this.web3Service.updateWeb3Status(revolutionContractABI, this.revolutionAddress);
    console.log("Getting citzens");
    let i = 0;
    let citizenAddress = "";
    let citizen: ICitizen;
    while (citizenAddress != null) {
      citizenAddress = await this.revolutionContract
        .citizens(i)
        .then( (result) => {
          return result;
        })
        .catch( (error) => {
          this
            .web3Service
            .web3Status
            .next("An error occured while reading citizen " + i.toString() + " : " + error);
          return null;
      });
      console.log("read citizen: ", citizenAddress);
      if (citizenAddress != "" && citizenAddress != null) {
        citizen = await this.revolutionContract
          .trialStatus(citizenAddress)
          .then( (result) => {
            console.log("citizen result: ", result);
            let name;
            try {
              name = result[4];
            } catch(e) {
              name = undefined;
              console.log("Could read name from contract: ", e);
            }
            if (citizenAddress in this.otherRevolutions) {
              name = this.otherRevolutions[citizenAddress];
            }
            return {
              address: citizenAddress,
              opened: result[0],
              matchesCriteria: result[1],
              sansculotteScale: result[2],
              privilegedScale: result[3],
              name: name
            };
          })
          .catch( (error) => {
            console.log("error: ", error);
            this
              .web3Service
              .web3Status
              .next("An error occured while reading trialStatus of citizen #" + i.toString() + " : " + error);
          });
        if (citizen != undefined) {
          this.citizens.push(citizen);
        }
      }
      i += 1;
    }
    this.citizensLoaderActivity="";
    // this.web3Service.web3Status.next("Here are the citizens known at this bastille : " + this.citizens.toString());
  }

}