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;