github.com/igggame/nebulas-go@v2.1.0+incompatible/nf/nvm/test/incentive_vote_contract.js (about)

     1  'use strict';
     2  
     3  // vote item
     4  var VoteItem = function(dappId, vote) {
     5      this.dappId = dappId;
     6      this.vote = vote;
     7  };
     8  
     9  var DappVote = function(str) {
    10      this.total = "0";
    11      this.voteItems = new Array();
    12      if (str !== undefined && str !== null) {
    13          this.parse(str);
    14      }
    15  };
    16  
    17  DappVote.prototype = {
    18      stringify: function() {
    19          return JSON.stringify(this);
    20      },
    21      parse: function(str) {
    22          var obj = JSON.parse(str);
    23          this.total = obj.total;
    24  
    25          var list = obj.voteItems;
    26          for (var i= 0; i < list.length; i++) {
    27              var item = list[i];
    28              var dappVote = new VoteItem(item.dappId, item.vote);
    29              this.voteItems.push(dappVote);
    30          }
    31      },
    32      vote: function(dappId, vote) {
    33          if (vote instanceof BigNumber) {
    34              vote = vote.toString(10);
    35          }
    36          var item = new VoteItem(dappId, vote);
    37          this.voteItems.push(item);
    38          var totalVote = new BigNumber(this.total);
    39          this.total = totalVote.add(vote).toString(10);
    40      },
    41      voteDappList: function() {
    42          var list = new Array();
    43          for(var i = 0; i < this.voteItems.length; i++) {
    44              list.push(this.voteItems[i].dappId);
    45          }
    46          return list;
    47      }
    48  };
    49  
    50  var IncentiveVoteContract = function() {
    51      LocalContractStorage.defineProperties(this, {
    52          name: null,     // incentive vote name
    53          lockAddress: null,  // the lock address of vote
    54          endHeight: null,   //end of vote height
    55          owner: null,        // owner
    56          totalPerVoters: {
    57              stringify: function(n) {
    58                  return n.toString(10);
    59              },
    60              parse: function(str) {
    61                  return new BigNumber(str);
    62              }
    63          }
    64      });
    65  
    66      // the list of dappId
    67      LocalContractStorage.defineMapProperty(this, "dappArray");
    68      // the count of dappId list
    69      LocalContractStorage.defineProperty(this, "dappCount");
    70  
    71      // the list of vote address
    72      LocalContractStorage.defineMapProperty(this, "addressArray");
    73      // the count of address list
    74      LocalContractStorage.defineProperty(this, "addressCount");
    75  
    76  
    77      // vote dapp data
    78      LocalContractStorage.defineMapProperty(this, "voteMap", {
    79          stringify: function(obj) {
    80              return JSON.stringify(obj);
    81          },
    82          parse: function(str) {
    83              return new DappVote(str);
    84          }
    85      });
    86      LocalContractStorage.defineMapProperty(this, "voteAddrArray");
    87      LocalContractStorage.defineProperty(this, "voteCount");
    88  };
    89  
    90  IncentiveVoteContract.prototype = {
    91      init: function(name, lockAddress, endHeight, totalPerVoters, dappArray, addressArray) {
    92          this.name = name;
    93          if (Blockchain.verifyAddress(lockAddress) != 0) {
    94              this.lockAddress = lockAddress;
    95          } else {
    96              throw new Error("invalid lock address");
    97          }
    98          if (Blockchain.block.height >= endHeight) {
    99              throw new Error("invalid end height of vote");
   100          }
   101          this.endHeight = endHeight;
   102          this.totalPerVoters = new BigNumber(totalPerVoters);
   103  
   104          for(var i = 0; i < dappArray.length; i++) {
   105              this.dappArray.set(i, dappArray[i]);
   106          }
   107          this.dappCount = dappArray.length;
   108       
   109          for(var i = 0; i < addressArray.length; i++) {
   110              this.addressArray.set(i, addressArray[i]);
   111          }
   112          this.addressCount = addressArray.length;
   113  
   114          this.voteCount = 0;
   115  
   116          this.owner = Blockchain.transaction.from;
   117      },
   118      getName: function() {
   119          return this.name;
   120      },
   121      vote: function(dappId) {
   122          if (this.endHeight < Blockchain.block.height) {
   123              throw new Error("over voting time");
   124          };
   125          if (Blockchain.transaction.value.lte(0)) {
   126              throw new Error("vote must bigger than 0");
   127          };
   128  
   129          if (!this._isValidDapp(dappId)) {
   130              throw new Error("invalid vote dapp");
   131          };
   132          var from = Blockchain.transaction.from;
   133          if (!this._isValidVoter(from)) {
   134              throw new Error("invalid voter address");
   135          };
   136  
   137          var dappVote = this.voteMap.get(from);
   138          var isFirstVote = false;
   139          if (dappVote === null) {
   140              dappVote = new DappVote();
   141              isFirstVote = true; 
   142          };
   143          var totalVote = new BigNumber(dappVote.total);
   144          totalVote = totalVote.add(Blockchain.transaction.value);
   145          if (totalVote.gt(this.totalPerVoters)) {
   146              throw new Error("out of the count votes per address");
   147          };
   148  
   149          // vote for the dapp
   150          dappVote.vote(dappId, Blockchain.transaction.value);
   151          this.voteMap.put(from, dappVote);
   152          if (isFirstVote) {
   153              this.voteAddrArray.set(this.voteCount, from);
   154              this.voteCount = this.voteCount + 1;
   155          };
   156          var result = Blockchain.transfer(this.lockAddress, Blockchain.transaction.value);
   157          if (!result) {
   158              throw new Error("vote transfer failed");
   159          }
   160      },
   161      _isValidDapp: function(dappId) {
   162          var count = this.dappCount;
   163          for (var i = 0; i < count; i++) {
   164              if (this.dappArray.get(i) === dappId) {
   165                  return true;
   166              }
   167          }
   168          return false;
   169      },
   170      _isValidVoter: function(addr) {
   171          var count = this.addressCount;
   172          for (var i = 0; i < count; i++) {
   173              if (this.addressArray.get(i) === addr) {
   174                  return true;
   175              }
   176          }
   177          return false;
   178      },
   179      updateEndHeight: function(height) {
   180          if (this.owner !== Blockchain.transaction.from) {
   181              throw new Error("only contract owner can update the end height");
   182          }
   183          this.endHeight = height;
   184      },
   185      getEndHeight: function() {
   186          return this.endHeight;
   187      },
   188      updateVoter: function(oldAddr, newAddr) {
   189          if (this.owner !== Blockchain.transaction.from) {
   190              throw new Error("only contract owner can update the voter");
   191          }
   192          if (this.endHeight < Blockchain.block.height) {
   193              throw new Error("over voting time");
   194          }
   195          if (!this._isValidVoter(oldAddr)) {
   196              throw new Error("invalid old voter address");
   197          }
   198          if (this.voteMap.get(oldAddr) !== null) {
   199              throw new Error("old address has voted dapp, can not be change!");
   200          }
   201  
   202          if (Blockchain.verifyAddress(newAddr) === 0) {
   203              throw new Error("invalid lock address");
   204          };
   205  
   206          var count = this.addressCount;
   207          for (var i = 0; i < count; i++) {
   208              if (this.addressArray.get(i) === oldAddr) {
   209                  this.addressArray.set(i, newAddr);
   210                  return;
   211              }
   212          }
   213      },
   214      getDappList: function() {
   215          var count = this.dappCount;
   216          var dappList = new Array();
   217          for (var i = 0; i < count; i++) {
   218              dappList.push(this.dappArray.get(i));
   219          }
   220          return dappList;
   221      },
   222      getVoterList: function() {
   223          var count = this.addressCount;
   224          var voterList = new Array();
   225          for (var i = 0; i < count; i++) {
   226              voterList.push(this.addressArray.get(i));
   227          }
   228          return voterList;
   229      },
   230      getAddrVotes: function (addr) {
   231          if (Blockchain.verifyAddress(addr) === 0) {
   232              throw new Error("invalid query address");
   233          };
   234          if (!this._isValidVoter(addr)) {
   235              throw new Error("query address is not the voter");
   236          }
   237          return this.voteMap.get(addr);
   238      },
   239      getAddrVotesList: function() {
   240          var count = this.addressCount;
   241          var dappVotes = {};
   242          for(var i = 0; i < count; i++) {
   243              var addr = this.addressArray.get(i);
   244              var dappVote = this.voteMap.get(addr);
   245              if (dappVote === null) {
   246                  dappVote = new DappVote();
   247              }
   248              dappVotes[addr] = dappVote;
   249          }
   250          return dappVotes;
   251      },
   252      getDappVotes: function() {
   253          var count = this.voteCount;
   254          var dappVotes = {};
   255          for(var i = 0; i < count; i++) {
   256              var addr = this.voteAddrArray.get(i);
   257              var dappVote = this.voteMap.get(addr);
   258              for (var j = 0; j < dappVote.voteItems.length; j++) {
   259                  var voteItem = dappVote.voteItems[j];
   260                  var vote = dappVotes[voteItem.dappId] || "0";
   261                  vote = new BigNumber(vote);
   262                  dappVotes[voteItem.dappId] = vote.add(voteItem.vote).toString(10);
   263              }
   264          }
   265  
   266          var count = this.dappCount;
   267          for (var i = 0; i < count; i++) {
   268              var dappId = this.dappArray.get(i);
   269              if (dappVotes[dappId] === undefined) {
   270                  dappVotes[dappId] = "0";
   271              }
   272          }
   273          return dappVotes;
   274      },
   275      withdrawal: function(value) {
   276          if (this.owner !== Blockchain.transaction.from) {
   277              throw new Error("only contract owner can handle the vote");
   278          }
   279          value = new BigNumber(value);
   280          if (value.lte(0)) {
   281              throw new Error("value must bigger than 0");
   282          }
   283          var result = Blockchain.transfer(this.lockAddress, value);
   284          if (!result) {
   285              throw new Error("withdrawal transfer failed");
   286          }
   287      },
   288      accept: function() {
   289          if (Blockchain.transaction.value.gt(0)) {
   290              throw new Error("vote contract not accept value without dappId");
   291          };
   292      }
   293  };
   294  
   295  module.exports = IncentiveVoteContract;