Siggg/culottes

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

Summary

Maintainability
Test Coverage
<div>
  <h1 class="ui header">The {{ hashtag }} revolution</h1>
  <div class="field" style="text-align:right;">
   <div class="ui action input">
    <div class="ui right aligned big label" style="text-align:right;">{{ bastilleBalance }} ETH = {{ convertToFiat(bastilleBalance) }}</div>
   <select (change)="onCurrencyChange($event)" class="ui compact dropdown label" style="max-width:6em;">
    <option value="EUR" [selected]="currency() == 'EUR'">€</option>
    <option value="USD" [selected]="currency() == 'USD'">$</option>
    <option [selected]="currency() == 'AUD'">AUD</option>
    <option [selected]="currency() == 'CAD'">CAD</option>
    <option [selected]="currency() == 'CNY'">CNY</option>
    <option value="GBP" [selected]="currency() == 'GBP'">£</option>
    <option value="JPY" [selected]="currency() == 'JPY'">¥</option>
   </select>
   <a class="ui button primary" href="#donate">
    <i class="heart icon"></i>
   </a>
    </div>
   </div>
  <p>Up to {{ convertToFiat(distributionAmount) }} {{ currency() }} ({{ distributionAmount }} ETH) automatically distributed every {{ distributionPeriod.toFixed(1) }} {{ distributionPeriodUnit }} to any unique Ethereum address promoted by: <strong>{{ criteria }}</strong>.</p>
  <div class="field ui basic segment" style="text-align:right;">
   <select (change)="onRevolutionChange($event)" class="ui compact dropdown label">
    <option value="menu" [selected]="true">Other revolutions...</option>
    <option *ngFor="let revolution of otherRevolutions | keyvalue" value="{{ revolution.key }}">{{ revolution.value }}</option>
    <option *ngIf="loadingRevolutions">(reading from blockchain, please wait)</option>
   </select>
  </div>


 <div class="ui segment" id="discuss">
  <h3 class="ui header">1. Who or what does or does not match this criteria?</h3>
  <div class="content">Discover it <a href="https://twitter.com/hashtag/{{ hashtagWithoutSymbol }}" target="_blank">on social media using the <span id="hashtag">{{ hashtag }}</span> hashtag</a>. Or by offline discussions. Demand proofs that this really is the address of <strong>{{ criteria }}</strong>. Fact check it. Challenge it. Debate it. Build your own opinion.</div>
 </div>
 

 <div class="ui segment" id="vote">
  <h3 class="ui header">2. Which addresses have been put on trial?</h3>
  <div class="ui relaxed celled list">
   <div class="item">
    <div class="content">
     <div class="header"><label>Bet and vote on their trial, challenge the consensual verdicts.</label></div>
    </div>
   </div>
  </div>
  <div class="ui relaxed celled list" *ngFor="let citizen of citizens">
   <div class="item">
    <i class="large balance scale middle aligned icon"></i>
    <div class="content" #userInput>
     <div
      class="ui basic button"
      *ngIf="otherRevolutions[citizen.address]"
      (click)="onRevolutionRedirectTo(citizen.address)"
      attr.data-tooltip="Ethereum address of the '{{ citizen.name }}' revolution: {{ citizen.address }}"
      data-position="top left">
      <a
       *ngIf="otherRevolutions[citizen.address]"
       [routerLink]="['/revolution', citizen.address]">
       <span *ngIf="citizen.name">
        <span *ngIf="citizen.name.length > 14">{{ (citizen.name | slice:0:12)+'...' }}</span>
        <span *ngIf="citizen.name.length <= 14">{{ citizen.name }}</span>
       </span>
      </a>
     </div>
     <div
      class="ui large label"
      *ngIf="!otherRevolutions[citizen.address]"
      attr.data-tooltip="{{ citizen.name }} Their Ethereum address: {{ citizen.address }}"
      data-position="top left">
      <span *ngIf="citizen.name">
       <span *ngIf="citizen.name.length > 14">{{ (citizen.name | slice:0:12)+'...' }}</span>
       <span *ngIf="citizen.name.length <= 14">{{ citizen.name }}</span>
      </span>
      {{ (citizen.address | slice:0:8)+'...' }}
     </div>
     <button
      class="ui icon tiny button"
      type="button"
      ngxClipboard
      [cbContent]="citizen.address"
      (cbOnSuccess)="copied = citizen.address"
      [class.btn-success]="copied == citizen.address"
      data-tooltip="Click to copy the Ethereum address"
      data-position="top left">
      <i class="copy icon"></i>
      <span *ngIf="copied == citizen.address">Copied</span>
     </button>
     <a [routerLink]="['/citizen', citizen.address]">
      <div *ngIf="citizen.opened" class="ui tag label">No consensual verdict yet: {{ citizen.sansculotteScale / 1000000000000000000 }} ETH on YES vs. {{ citizen.privilegedScale / 1000000000000000000 }} ETH on NO</div>
      <div *ngIf="!citizen.opened && citizen.matchesCriteria" class="ui green tag label"><i class="thumbs up icon"></i> Consensual verdict: YES, they are.{{ (citizen.sansculotteScale != 0) ? ' And '+(citizen.sansculotteScale / 1000000000000000000)+' ETH more is on YES.':'' }}</div>
      <div *ngIf="!citizen.opened && !citizen.matchesCriteria"  class="ui red tag label"><i class="thumbs down icon"></i> Consensual verdict: NO, they are not.{{ (citizen.privilegedScale != 0) ? ' And '+(citizen.privilegedScale / 1000000000000000000)+' ETH is still on NO.':'' }}</div>
      <button class="ui left labeled icon tiny button secondary" data-tooltip="Click to vote and bet." data-position="top right"><i class="envelope icon"></i><span *ngIf="citizen.opened">Cast your vote and bet: YES or NO ?</span><span *ngIf="!citizen.opened">Re-open their trial</span></button>
     </a>
    </div>
   </div>
  </div>
  <div class="ui {{ citizensLoaderActivity }} text inline loader">Reading from the blockchain</div>
 </div>
 
 
  <div class="ui segment" id="add">
  <h3 class="ui header">3. What additional address to be put on trial?</h3>
  <div class="content">You can add any Ethereum address (even yours) if it indeed is the address of <strong>{{ criteria }}</strong>. Your own address can be copied from your Ethereum wallet (Metamask, Coinbase, Trust, ...). If you don't know the proper Ethereum address to use, you can <a routerLink="/factory">create a new revolution using a full name or precise definition as its criteria and a short name or pseudonyme as a hashtag</a>, then use the address of that new revolution in order to put it on trial.</div>
  <div class="content"><a routerLink="/citizen">
   <button class="ui left labeled icon secondary button" data-tooltip="Click to register a new address and bet and vote about it.">
    <i class="envelope scale icon"></i>
    Add the Ethereum address of <strong>{{ criteria }}</strong>
   </button>
  </a></div>
 </div>
 
 
  <div class="ui segment form" id="donate">
  <h3 class="ui header">4. Donate Eth to be distributed</h3>
  This revolution collects donations sent to the address <strong>{{ revolutionAddress }}</strong> on the Ethereum {{ revolutionBlockchain }} blockchain. 100% of these donations are directly re-distributed as income, minus transaction safety fees (also known as network mining fees).

  <div class="field">
   <label>Current amount in this revolution:</label>
   <div class="ui action input">
    <div class="ui right aligned big label" style="text-align:right;"><span id="balance">{{ bastilleBalance }}</span> ETH = {{ convertToFiat(bastilleBalance) }}</div>
   <select (change)="onCurrencyChange($event)" class="ui compact dropdown label" style="max-width:6em;">
    <option value="EUR" [selected]="currency() == 'EUR'">€</option>
    <option value="USD" [selected]="currency() == 'USD'">$</option>
    <option [selected]="currency() == 'AUD'">AUD</option>
    <option [selected]="currency() == 'CAD'">CAD</option>
    <option [selected]="currency() == 'CNY'">CNY</option>
    <option value="GBP" [selected]="currency() == 'GBP'">£</option>
    <option value="JPY" [selected]="currency() == 'JPY'">¥</option>
   </select>
    </div>
   </div>
   <a class="ui button primary" routerLink="/donate">
    <i class="heart icon"></i>
    Donate to this revolution
   </a>
 </div>
 
 <div class="ui segment" id="intro">
  <iframe width="100%" height="100%" src="https://www.youtube.com/embed/yZBNfpnjqVM" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
 </div>
  
 <div class="ui segment" id="trust">
  <h3 class="ui header">5. How much can you trust this app?</h3>
  <p id="criteriaLabel"> The Ethereum addresses listed above receive an income from this application if and only if they are the address of <strong class="criteria" id="criteria">{{ criteria }}</strong> according to the consensual verdict of their trial. The income received is then, at most, of {{ distributionAmount }} ETH every {{ distributionBlockPeriod }} blocks of the Ethereum {{ revolutionBlockchain }} blockchain (about {{ convertToFiat(distributionAmount) }} {{ currency() }} every {{ distributionPeriod.toFixed(1) }} {{ distributionPeriodUnit }}) unless this revolution is empty and needs further donations. First addresses added above get their income first. Last addresses may not get any income during this distribution round if the revolution is empty. Distribution rounds are triggered by new votes. Voters pay mining fees. Voters earn ETH if the consensual verdict is aligned with their vote and loose their bet otherwise. </p>
  <ul>If you are a skillful smart contract auditor, you can :
    <li><a href="https://github.com/siggg/culottes" target="_blank">read and check the open source code of this application and smart contract on Github</a></li>
    <li><a href="https://{{ revolutionBlockchain == 'Main' || revolutionBlockchain == 'Mainnet' || revolutionBlockchain == 'Unknown' ? 'www' : revolutionBlockchain.toLowerCase() }}.etherscan.io/address/{{ revolutionAddress }}" target="_blank">scan the blockchain at the address of this revolution and check that this smart contract was created by the factory contract which indeed runs the source code seen on Github (the factory contract should have been verified on Etherscan)</a></li>
  </ul>
 </div>


 <!--div class="ui segment">Technical status:
  <div [innerHTML]="web3Status"></div>
  <div class="field">
   <label>Address of this revolution</label>
   <div class="ui label">{{ revolutionAddress }} on the {{ revolutionBlockchain }} blockchain</div>
  </div-->
  <div *ngIf="canLockRevolution == true">
   <a class="ui button red" (click)="lockRevolution()">
    <i class="lock icon"></i>Lock the {{ hashtag }} revolution
   </a>
  </div>
 <!--/div-->

<div class="ui fullscreen longer {{ lockModalActivity }} modal">
   <i class="close outline icon" (click)="onCloseLockModal()"></i>
   <div class="ui icon header">
    <i class="lock icon"></i>
    Locked
  </div>
  <div class="ui content">
    <p>This contract has been locked by its owner. You can still vote for and against addresses as long as there is some ETH left in this revolution. But you can't donate any more ETH to this revolution. And votes are closed once this revolution is empty.</p>
    <p>This "locked" mode is meant to limit the risks that the contract is used or exploited in a malicious way. It's probably been locked because it is being exploited in such a way and a new version of the contract is on its way for deployment. Locking is the only function of the contract under the central control of its owner. Please come back as soon as an unlocked version of this contract is deployed. For more information, contact sig at akasig dot org (see "About" link at the top right of this page).</p>
  </div>
</div>

<div class="ui fullscreen longer {{ web3ModalActivity }} modal">
  <div class="ui icon header">
    <i class="spinner loading icon"></i>
    Connecting to the blockchain
  </div>
  <div class="ui list">
   <div class="item" *ngIf="dappStatus()['statusWeb3']">
    <i class="check icon"></i>
    <div class="content">
      you are using an Ethereum browser
    </div>
   </div>
   <div class="item" *ngIf="!dappStatus()['statusWeb3']">
    <i class="x icon"></i>
    <div class="content">
      you must install and use an Ethereum browser
      <a href="https://metamask.io/" target="_blank"><button class="ui left labeled icon primary button">
       <i class="plug icon"></i>Install Metamask on PC
      </button></a>
      <a href="https://www.trustwallet.com/" target="_blank"><button class="ui left labeled icon primary button">
       <i class="plug icon"></i>Install Trust Wallet on mobile
      </button></a>
    </div>
   </div>
   <div class="item" *ngIf="dappStatus()['statusNetwork']">
    <i class="check icon"></i>
    <div class="content">
      your Ethereum browser is connected to the {{ revolutionBlockchain }} Ethereum blockchain network
    </div>
   </div>
   <div class="item" *ngIf="!dappStatus()['statusNetwork']">
    <i class="x icon"></i>
    <div class="content">
      your Ethereum browser must be connected to the {{ revolutionBlockchain }} Ethereum blockchain network
    </div>
   </div>
   <!--div class="item" *ngIf="dappStatus()['statusAccount']">
    <i class="check icon"></i>
    <div class="content">
      you are connected to a wallet within this Ethereum browser
    </div>
   </div>
   <div class="item" *ngIf="!dappStatus()['statusAccount']">
    <i class="x icon"></i>
    <div class="content">
      you must connect to a wallet within your Ethereum browser, (create a wallet if needed)
    </div>
   </div>
   <div class="item" *ngIf="dappStatus()['statusAuthorized']">
    <i class="check icon"></i>
    <div class="content">
      your Ethereum browser authorized interactions with the blockchain
    </div>
   </div>
   <div class="item" *ngIf="!dappStatus()['statusAuthorized']">
    <i class="x icon"></i>
    <div class="content">
      your Ethereum browser must authorize interactions with the blockchain
    </div>
   </div-->
 </div>
  <div class="content" [innerHTML]="web3Status">
  </div>
</div>

<!--div class="ui segment">
 <div class="header">
  <a href="https://{{ revolutionBlockchain == 'Main' || revolutionBlockchain == 'Mainnet' || revolutionBlockchain == 'Unknown' ? 'www' : revolutionBlockchain.toLowerCase() }}.etherscan.io/address/{{ revolutionAddress }}#events" target="_blank">Events of this revolution</a>
 </div-->
 <!-- div *ngIf="contractEvents">
 <div class="content" *ngFor="let cEvent of contractEvents.slice().reverse()">
  <a href="https://{{ revolutionBlockchain == 'Main' || revolutionBlockchain == 'Mainnet' || revolutionBlockchain == 'Unknown' ? 'www' : revolutionBlockchain.toLowerCase() }}.etherscan.io/tx/{{ cEvent.transactionHash }}#eventlog">#{{ cEvent.blockNumber }}{{ cEvent.logIndex ? ',' + cEvent.logIndex : '' }}: 
  <span *ngIf="cEvent.event == 'RevolutionCreated'">
      this {{ cEvent.returnValues._hashtag }} revolution was created.
  </span>
  <span *ngIf="cEvent.event == 'TrialOpened'">
   the trial of {{ cEvent.returnValues._citizen | slice:0:8 }} opened.
  </span>
  <span *ngIf="cEvent.event == 'TrialClosed'">
   the trial of {{ cEvent.returnValues._citizen | slice:0:8 }} closed.
  </span>
  <span *ngIf="cEvent.event == 'VoteReceived'">
   {{ cEvent.returnValues._citizen | slice:0:8 }} received a  {{ cEvent.returnValues._vote ? 'YES' : 'NO' }} vote.
  </span>
  <span *ngIf="cEvent.event == 'Distribution'">
   {{ cEvent.returnValues._distributionAmount /  1000000000000000000 }} ETH was distributed to {{ cEvent.returnValues._citizen | slice:0:8 }}.
  </span>
  </a>
 </div>
 </div>
</div-->