├── .babelrc ├── .eslintrc.js ├── .flowconfig ├── .gitignore ├── .watchmanconfig ├── App.js ├── README.md ├── app.json ├── assets ├── expo.png ├── icon.png ├── sample.gif └── splash.png ├── build └── contracts │ └── Voting.json ├── libdefs.js ├── package.json ├── src ├── Candidates │ ├── CandidateList.js │ ├── Item.js │ ├── Main.js │ ├── Star.js │ └── Vote.js ├── Container.js ├── Stats.js └── types.js ├── truffle.js └── yarn.lock /.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": ["babel-preset-expo", "babel-preset-react-native-web3"], 3 | "env": { 4 | "development": { 5 | "plugins": ["transform-react-jsx-source"] 6 | } 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | parser: require.resolve('babel-eslint'), 3 | 4 | env: { 5 | es6: true, 6 | }, 7 | parserOptions: { 8 | sourceType: 'module', 9 | ecmaFeatures: { 10 | jsx: true, 11 | }, 12 | }, 13 | plugins: ['import', 'react'], 14 | 15 | rules: { 16 | 'constructor-super': 'error', 17 | 'no-case-declarations': 'error', 18 | 'no-class-assign': 'error', 19 | 'no-cond-assign': 'error', 20 | 'no-const-assign': 'error', 21 | 'no-constant-condition': 'error', 22 | 'no-control-regex': 'error', 23 | 'no-delete-var': 'error', 24 | 'no-dupe-args': 'error', 25 | 'no-dupe-class-members': 'error', 26 | 'no-dupe-keys': 'error', 27 | 'no-duplicate-case': 'error', 28 | 'no-empty': 'error', 29 | 'no-empty-character-class': 'error', 30 | 'no-empty-pattern': 'error', 31 | 'no-ex-assign': 'error', 32 | 'no-extra-boolean-cast': 'error', 33 | 'no-extra-semi': 'error', 34 | 'no-fallthrough': 'error', 35 | 'no-func-assign': 'error', 36 | 'no-inner-declarations': 'error', 37 | 'no-invalid-regexp': 'error', 38 | 'no-new-symbol': 'error', 39 | 'no-obj-calls': 'error', 40 | 'no-octal': 'error', 41 | 'no-redeclare': 'error', 42 | 'no-regex-spaces': 'error', 43 | 'no-self-assign': 'error', 44 | 'no-sparse-arrays': 'error', 45 | 'no-this-before-super': 'error', 46 | 'no-unexpected-multiline': 'error', 47 | 'no-unreachable': 'error', 48 | 'no-unsafe-finally': 'error', 49 | 'no-unused-labels': 'error', 50 | 'no-unused-vars': 'warn', 51 | 'require-yield': 'error', 52 | 'use-isnan': 'error', 53 | 'valid-typeof': 'error', 54 | 55 | 'import/no-unresolved': 'warn', 56 | 'import/named': 'error', 57 | 'import/default': 'off', 58 | 'import/namespace': 'off', 59 | 'import/export': 'error', 60 | 'import/no-named-as-default': 'off', 61 | 'import/no-named-as-default-member': 'off', 62 | 'import/no-deprecated': 'off', 63 | 'import/no-extraneous-dependencies': 'off', 64 | 'import/no-commonjs': 'warn', 65 | 'import/no-amd': 'error', 66 | 'import/no-nodejs-modules': 'off', 67 | 'import/imports-first': 'error', 68 | 'import/no-duplicates': 'error', 69 | 'import/no-namespace': 'off', 70 | 'import/extensions': ['error', { js: 'never', json: 'always' }], 71 | 'import/order': 'off', 72 | 73 | 'react/display-name': 'off', 74 | 'react/forbid-prop-types': 'off', 75 | 'react/no-danger': 'error', 76 | 'react/no-deprecated': 'error', 77 | 'react/no-did-mount-set-state': 'error', 78 | 'react/no-did-update-set-state': 'error', 79 | 'react/no-direct-mutation-state': 'error', 80 | 'react/no-is-mounted': 'error', 81 | 'react/no-multi-comp': 'off', 82 | 'react/no-set-state': 'off', 83 | 'react/no-string-refs': 'error', 84 | 'react/no-unknown-property': 'error', 85 | 'react/prefer-es6-class': 'error', 86 | 'react/prop-types': 'off', 87 | 'react/react-in-jsx-scope': 'error', 88 | 'react/require-render-return': 'error', 89 | 'react/self-closing-comp': 'error', 90 | 'react/sort-comp': 'error', 91 | 'react/sort-prop-types': 'off', 92 | 'react/jsx-boolean-value': ['error', 'never'], 93 | 'react/jsx-handler-names': 'off', 94 | 'react/jsx-key': 'error', 95 | 'react/jsx-no-bind': 'off', 96 | 'react/jsx-no-duplicate-props': 'error', 97 | 'react/jsx-no-literals': 'off', 98 | 'react/jsx-no-undef': 'error', 99 | 'react/jsx-pascal-case': 'error', 100 | 'react/jsx-sort-props': 'off', 101 | 'react/jsx-uses-react': 'error', 102 | 'react/jsx-uses-vars': 'error', 103 | 'react/prefer-stateless-function': 'off', 104 | }, 105 | settings: { 106 | 'import/resolver': { 107 | node: { 108 | extensions: ['.js', '.native.js', 'json'], 109 | }, 110 | }, 111 | }, 112 | }; 113 | -------------------------------------------------------------------------------- /.flowconfig: -------------------------------------------------------------------------------- 1 | [ignore] 2 | /node_modules 3 | .*/*[.]android.js 4 | [include] 5 | 6 | [libs] 7 | ./libdefs.js 8 | 9 | [lints] 10 | 11 | [options] 12 | emoji=true 13 | module.system=haste 14 | module.file_ext=.js 15 | module.file_ext=.native.js 16 | module.file_ext=.json 17 | 18 | suppress_type=$FlowIssue 19 | suppress_type=$FlowFixMe 20 | suppress_type=$FixMe 21 | 22 | suppress_comment=\\(.\\|\n\\)*\\$FlowFixMe\\($\\|[^(]\\|(\\(>=0\\.\\(3[0-8]\\|[1-2][0-9]\\|[0-9]\\).[0-9]\\)? *\\(site=[a-z,_]*react_native[a-z,_]*\\)?)\\) 23 | suppress_comment=\\(.\\|\n\\)*\\$FlowIssue\\((\\(>=0\\.\\(3[0-8]\\|1[0-9]\\|[1-2][0-9]\\).[0-9]\\)? *\\(site=[a-z,_]*react_native[a-z,_]*\\)?)\\)?:? #[0-9]+ 24 | suppress_comment=\\(.\\|\n\\)*\\$FlowFixedInNextDeploy 25 | suppress_comment=\\(.\\|\n\\)*\\$FlowIgnore 26 | 27 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules/**/* 2 | .expo/* 3 | npm-debug.* 4 | yarn-error.log -------------------------------------------------------------------------------- /.watchmanconfig: -------------------------------------------------------------------------------- 1 | {} 2 | -------------------------------------------------------------------------------- /App.js: -------------------------------------------------------------------------------- 1 | /* @flow */ 2 | import * as React from 'react'; 3 | // $FlowFixMe 4 | import 'babel-preset-react-native-web3/globals'; 5 | 6 | import HDWalletProvider from 'truffle-hdwallet-provider'; 7 | 8 | import { createMaterialTopTabNavigator } from 'react-navigation'; 9 | 10 | import Web3 from 'web3'; 11 | 12 | import Main from './src/Candidates/Main'; 13 | import Container from './src/Container'; 14 | import Stats from './src/Stats'; 15 | 16 | import truffleConfig from './truffle'; 17 | 18 | const network = truffleConfig.networks.ropsten; 19 | const TESTRPC_ADDRESS = `${network.protocol}://${network.host}/`; 20 | 21 | const mnemonic = 'YOUR_MNEMONIC_HERE'; // 12 word mnemonic 22 | 23 | const web3Provider = new HDWalletProvider(mnemonic, TESTRPC_ADDRESS); 24 | 25 | const web3 = new Web3(web3Provider); 26 | 27 | class MainScreen extends React.PureComponent<{}> { 28 | static navigationOptions = { 29 | tabBarVisible: false, 30 | }; 31 | render() { 32 | return
; 33 | } 34 | } 35 | 36 | class SetupScreen extends React.PureComponent<{}> { 37 | static navigationOptions = { 38 | tabBarVisible: false, 39 | }; 40 | render() { 41 | return ; 42 | } 43 | } 44 | 45 | export default class App extends React.PureComponent<{}> { 46 | render() { 47 | return ( 48 | 49 | 50 | 51 | ); 52 | } 53 | } 54 | const AppNavigation = createMaterialTopTabNavigator( 55 | { 56 | Main: { screen: MainScreen }, 57 | Setup: { screen: SetupScreen }, 58 | }, 59 | { 60 | animationEnabled: true, 61 | swipeEnabled: true, 62 | } 63 | ); 64 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # react-native-blockchain-poll 2 | 3 | [![code style: prettier](https://img.shields.io/badge/code_style-prettier-ff69b4.svg?style=flat-square)](https://github.com/prettier/prettier) 4 | 5 | > This is just in an early stage and can fail. 6 | 7 | A simple mobile decentralized app ( dApp ) done as a prototype for [React Native](https://facebook.github.io/react-native/) and [expo](https://expo.io) to handle cryptopunks ranking on the ethereum blockchain. 8 | 9 | ## Overview 10 | 11 | * It's basically a mobile dapp for iOS and android done using `react-native` and `web3`. 12 | 13 | * It uses [flow](https://flow.org/) as a javascript typechecker and [babel-preset-react-native-web3](https://github.com/agrcrobles/babel-preset-react-native-web3) to polyfill crypto 14 | 15 | ## Getting started in localhost 16 | 17 | Configure `Ropsten Testnet Network` mnemonic key in `App.js` 18 | 19 | ```bash 20 | # Install dependencies 21 | yarn 22 | 23 | # and from a separate shell Run the mobile app 24 | exp start 25 | ``` 26 | 27 | For more information about configuring the cross platform app look into the [React Native](https://facebook.github.io/react-native/docs/getting-started.html) and [expo](https://docs.expo.io/versions/latest/index.html) getting started guides. 28 | 29 | ### React Native dependencies 30 | 31 | * [victory-native](https://formidable.com/open-source/victory/docs/victory-pie/) Victory bar Charts 32 | * [react-navigation](https://github.com/react-community/react-navigation) to navigate among scenes 33 | * among other cool ones such as `react-native-pull-to-refresh` and `react-native-star-rating` 34 | 35 | ### Ethereum dependencies 36 | 37 | * [web3](https://github.com/ethereum/web3.js) as the Etherum Javascript API 38 | * [truffle-contract](https://github.com/trufflesuite/truffle-contract) to parse the abstraction of the smart contract 39 | * [truffle-hdwallet-provider](https://github.com/trufflesuite/truffle-hdwallet-provider) to sign transactions via a deterministic wallet provider 40 | 41 | ## Expo 42 | 43 | ![expo](https://raw.githubusercontent.com/agrcrobles/react-native-blockchain-poll/master/assets/expo.png) 44 | 45 | ## Sample 46 | 47 | ![playing with the app](https://raw.githubusercontent.com/agrcrobles/react-native-blockchain-poll/master/assets/sample.gif) 48 | 49 | ## Ropsten 50 | 51 | * Smart Contract - https://ropsten.etherscan.io/address/0x25cee65ac493a0c965f12a2d0c46fe82e09d6d44 52 | * Coinbase - https://ropsten.etherscan.io/address/0x712f06642990a90f151a89990594365c4b32dec5 53 | 54 | ## More info 55 | 56 | * For more info about the ethereum configuration, see the following [gist](https://gist.github.com/agrcrobles/e03151b27ad4753827de227929677db3) 57 | 58 | ## Contributing 59 | 60 | Intended for personal purposes stars ✭ and issue reporting, welcome! 61 | 62 | ## License 63 | 64 | MIT @ zetta -------------------------------------------------------------------------------- /app.json: -------------------------------------------------------------------------------- 1 | { 2 | "expo": { 3 | "name": "react-native-blockchain-poll", 4 | "description": "A mobile dapp to rank cryptopunks", 5 | "slug": "react-native-blockchain-poll", 6 | "privacy": "public", 7 | "sdkVersion": "30.0.0", 8 | "platforms": [ 9 | "ios", 10 | "android" 11 | ], 12 | "version": "1.0.0", 13 | "orientation": "portrait", 14 | "icon": "./assets/icon.png", 15 | "splash": { 16 | "image": "./assets/splash.png", 17 | "resizeMode": "contain", 18 | "backgroundColor": "#ffffff" 19 | }, 20 | "ios": { 21 | "supportsTablet": true 22 | } 23 | } 24 | } -------------------------------------------------------------------------------- /assets/expo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/agrcrobles/react-native-blockchain-poll/63f831ccc9397acabe2e6cf38d26f2396dde0637/assets/expo.png -------------------------------------------------------------------------------- /assets/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/agrcrobles/react-native-blockchain-poll/63f831ccc9397acabe2e6cf38d26f2396dde0637/assets/icon.png -------------------------------------------------------------------------------- /assets/sample.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/agrcrobles/react-native-blockchain-poll/63f831ccc9397acabe2e6cf38d26f2396dde0637/assets/sample.gif -------------------------------------------------------------------------------- /assets/splash.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/agrcrobles/react-native-blockchain-poll/63f831ccc9397acabe2e6cf38d26f2396dde0637/assets/splash.png -------------------------------------------------------------------------------- /build/contracts/Voting.json: -------------------------------------------------------------------------------- 1 | { 2 | "contractName": "Voting", 3 | "abi": [ 4 | { 5 | "constant": true, 6 | "inputs": [ 7 | { 8 | "name": "candidate", 9 | "type": "bytes32" 10 | } 11 | ], 12 | "name": "totalVotesFor", 13 | "outputs": [ 14 | { 15 | "name": "", 16 | "type": "uint8" 17 | } 18 | ], 19 | "payable": false, 20 | "stateMutability": "view", 21 | "type": "function" 22 | }, 23 | { 24 | "constant": true, 25 | "inputs": [ 26 | { 27 | "name": "candidate", 28 | "type": "bytes32" 29 | } 30 | ], 31 | "name": "validCandidate", 32 | "outputs": [ 33 | { 34 | "name": "", 35 | "type": "bool" 36 | } 37 | ], 38 | "payable": false, 39 | "stateMutability": "view", 40 | "type": "function" 41 | }, 42 | { 43 | "constant": true, 44 | "inputs": [ 45 | { 46 | "name": "", 47 | "type": "bytes32" 48 | } 49 | ], 50 | "name": "votesReceived", 51 | "outputs": [ 52 | { 53 | "name": "", 54 | "type": "uint8" 55 | } 56 | ], 57 | "payable": false, 58 | "stateMutability": "view", 59 | "type": "function" 60 | }, 61 | { 62 | "constant": true, 63 | "inputs": [], 64 | "name": "allCandidates", 65 | "outputs": [ 66 | { 67 | "name": "", 68 | "type": "bytes32[]" 69 | } 70 | ], 71 | "payable": false, 72 | "stateMutability": "view", 73 | "type": "function" 74 | }, 75 | { 76 | "constant": true, 77 | "inputs": [ 78 | { 79 | "name": "", 80 | "type": "uint256" 81 | } 82 | ], 83 | "name": "candidateList", 84 | "outputs": [ 85 | { 86 | "name": "", 87 | "type": "bytes32" 88 | } 89 | ], 90 | "payable": false, 91 | "stateMutability": "view", 92 | "type": "function" 93 | }, 94 | { 95 | "constant": false, 96 | "inputs": [ 97 | { 98 | "name": "candidate", 99 | "type": "bytes32" 100 | }, 101 | { 102 | "name": "votes", 103 | "type": "uint8" 104 | } 105 | ], 106 | "name": "voteForCandidate", 107 | "outputs": [], 108 | "payable": false, 109 | "stateMutability": "nonpayable", 110 | "type": "function" 111 | }, 112 | { 113 | "inputs": [ 114 | { 115 | "name": "candidateNames", 116 | "type": "bytes32[]" 117 | } 118 | ], 119 | "payable": false, 120 | "stateMutability": "nonpayable", 121 | "type": "constructor" 122 | } 123 | ], 124 | "bytecode": "0x6060604052341561000f57600080fd5b6040516104d13803806104d1833981016040528080518201919050508060019080519060200190610041929190610048565b50506100c0565b82805482825590600052602060002090810192821561008a579160200282015b82811115610089578251829060001916905591602001919060010190610068565b5b509050610097919061009b565b5090565b6100bd91905b808211156100b95760008160009055506001016100a1565b5090565b90565b610402806100cf6000396000f300606060405260043610610078576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff1680632f265cf71461007d578063392e6678146100be5780637021939f146100fd57806381c407151461013e578063b13c744b146101a8578063f2ab823d146101e7575b600080fd5b341561008857600080fd5b6100a260048080356000191690602001909190505061021a565b604051808260ff1660ff16815260200191505060405180910390f35b34156100c957600080fd5b6100e360048080356000191690602001909190505061025f565b604051808215151515815260200191505060405180910390f35b341561010857600080fd5b6101226004808035600019169060200190919050506102bf565b604051808260ff1660ff16815260200191505060405180910390f35b341561014957600080fd5b6101516102df565b6040518080602001828103825283818151815260200191508051906020019060200280838360005b83811015610194578082015181840152602081019050610179565b505050509050019250505060405180910390f35b34156101b357600080fd5b6101c96004808035906020019091905050610341565b60405180826000191660001916815260200191505060405180910390f35b34156101f257600080fd5b61021860048080356000191690602001909190803560ff16906020019091905050610365565b005b60006102258261025f565b151561023057600080fd5b600080836000191660001916815260200190815260200160002060009054906101000a900460ff169050919050565b600080600090505b6001805490508110156102b457826000191660018281548110151561028857fe5b9060005260206000209001546000191614156102a757600191506102b9565b8080600101915050610267565b600091505b50919050565b60006020528060005260406000206000915054906101000a900460ff1681565b6102e76103c2565b600180548060200260200160405190810160405280929190818152602001828054801561033757602002820191906000526020600020905b8154600019168152602001906001019080831161031f575b5050505050905090565b60018181548110151561035057fe5b90600052602060002090016000915090505481565b61036e8261025f565b151561037957600080fd5b80600080846000191660001916815260200190815260200160002060008282829054906101000a900460ff160192506101000a81548160ff021916908360ff1602179055505050565b6020604051908101604052806000815250905600a165627a7a72305820d29f03c85207aca2a2290ca789332b706efd660d0e83f03582b26d5c1087b0e60029", 125 | "deployedBytecode": "0x606060405260043610610078576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff1680632f265cf71461007d578063392e6678146100be5780637021939f146100fd57806381c407151461013e578063b13c744b146101a8578063f2ab823d146101e7575b600080fd5b341561008857600080fd5b6100a260048080356000191690602001909190505061021a565b604051808260ff1660ff16815260200191505060405180910390f35b34156100c957600080fd5b6100e360048080356000191690602001909190505061025f565b604051808215151515815260200191505060405180910390f35b341561010857600080fd5b6101226004808035600019169060200190919050506102bf565b604051808260ff1660ff16815260200191505060405180910390f35b341561014957600080fd5b6101516102df565b6040518080602001828103825283818151815260200191508051906020019060200280838360005b83811015610194578082015181840152602081019050610179565b505050509050019250505060405180910390f35b34156101b357600080fd5b6101c96004808035906020019091905050610341565b60405180826000191660001916815260200191505060405180910390f35b34156101f257600080fd5b61021860048080356000191690602001909190803560ff16906020019091905050610365565b005b60006102258261025f565b151561023057600080fd5b600080836000191660001916815260200190815260200160002060009054906101000a900460ff169050919050565b600080600090505b6001805490508110156102b457826000191660018281548110151561028857fe5b9060005260206000209001546000191614156102a757600191506102b9565b8080600101915050610267565b600091505b50919050565b60006020528060005260406000206000915054906101000a900460ff1681565b6102e76103c2565b600180548060200260200160405190810160405280929190818152602001828054801561033757602002820191906000526020600020905b8154600019168152602001906001019080831161031f575b5050505050905090565b60018181548110151561035057fe5b90600052602060002090016000915090505481565b61036e8261025f565b151561037957600080fd5b80600080846000191660001916815260200190815260200160002060008282829054906101000a900460ff160192506101000a81548160ff021916908360ff1602179055505050565b6020604051908101604052806000815250905600a165627a7a72305820d29f03c85207aca2a2290ca789332b706efd660d0e83f03582b26d5c1087b0e60029", 126 | "sourceMap": "101:1606:1:-;;;797:90;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;868:14;852:13;:30;;;;;;;;;;;;:::i;:::-;;797:90;101:1606;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;:::o;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;:::-;;;;;;;", 127 | "deployedSourceMap": "101:1606:1:-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;1056:152;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;1481:224;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;326:47;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;890:88;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;23:1:-1;8:100;33:3;30:1;27:2;8:100;;;99:1;94:3;90;84:5;80:1;75:3;71;64:6;52:2;49:1;45:3;40:15;;8:100;;;12:14;3:109;;;;;;;;;;;;;;;;;546:30:1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;1328:149;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;1056:152;1119:5;1140:25;1155:9;1140:14;:25::i;:::-;1132:34;;;;;;;;1179:13;:24;1193:9;1179:24;;;;;;;;;;;;;;;;;;;;;;;;;;;1172:31;;1056:152;;;:::o;1481:224::-;1545:4;1561:6;1570:1;1561:10;;1557:126;1577:13;:20;;;;1573:1;:24;1557:126;;;1636:9;1616:29;;;:13;1630:1;1616:16;;;;;;;;;;;;;;;;;;;:29;;;;1612:65;;;1664:4;1657:11;;;;1612:65;1599:3;;;;;;;1557:126;;;1695:5;1688:12;;1481:224;;;;;:::o;326:47::-;;;;;;;;;;;;;;;;;;;;;;:::o;890:88::-;936:9;;:::i;:::-;960:13;953:20;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;890:88;:::o;546:30::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;1328:149::-;1407:25;1422:9;1407:14;:25::i;:::-;1399:34;;;;;;;;1467:5;1439:13;:24;1453:9;1439:24;;;;;;;;;;;;;;;;;;:33;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;1328:149;;:::o;101:1606::-;;;;;;;;;;;;;;;:::o", 128 | "source": "pragma solidity ^0.4.18;\n// We have to specify what version of compiler this code will compile with\n\ncontract Voting {\n /* mapping field below is equivalent to an associative array or hash.\n The key of the mapping is candidate name stored as type bytes32 and value is\n an unsigned integer to store the vote count\n */\n \n mapping (bytes32 => uint8) public votesReceived;\n \n /* Solidity doesn't let you pass in an array of strings in the constructor (yet).\n We will use an array of bytes32 instead to store the list of candidates\n */\n \n bytes32[] public candidateList;\n\n /* This is the constructor which will be called once when you\n deploy the contract to the blockchain. When we deploy the contract,\n we will pass an array of candidates who will be contesting in the election\n */\n function Voting(bytes32[] candidateNames) public {\n candidateList = candidateNames;\n }\n function allCandidates() view public returns (bytes32[]) {\n return candidateList;\n }\n // This function returns the total votes a candidate has received so far\n function totalVotesFor(bytes32 candidate) view public returns (uint8) {\n require(validCandidate(candidate));\n return votesReceived[candidate];\n }\n\n // This function increments the vote count for the specified candidate. This\n // is equivalent to casting a vote\n function voteForCandidate(bytes32 candidate, uint8 votes) public {\n require(validCandidate(candidate));\n votesReceived[candidate] += votes;\n }\n\n function validCandidate(bytes32 candidate) view public returns (bool) {\n for(uint i = 0; i < candidateList.length; i++) {\n if (candidateList[i] == candidate) {\n return true;\n }\n }\n return false;\n }\n}\n", 129 | "sourcePath": "/home/zetta/develop/voting-deploy/contracts/Voting.sol", 130 | "ast": { 131 | "attributes": { 132 | "absolutePath": "/home/zetta/develop/voting-deploy/contracts/Voting.sol", 133 | "exportedSymbols": { 134 | "Voting": [ 135 | 156 136 | ] 137 | } 138 | }, 139 | "children": [ 140 | { 141 | "attributes": { 142 | "literals": [ 143 | "solidity", 144 | "^", 145 | "0.4", 146 | ".18" 147 | ] 148 | }, 149 | "id": 58, 150 | "name": "PragmaDirective", 151 | "src": "0:24:1" 152 | }, 153 | { 154 | "attributes": { 155 | "baseContracts": [ 156 | null 157 | ], 158 | "contractDependencies": [ 159 | null 160 | ], 161 | "contractKind": "contract", 162 | "documentation": null, 163 | "fullyImplemented": true, 164 | "linearizedBaseContracts": [ 165 | 156 166 | ], 167 | "name": "Voting", 168 | "scope": 157 169 | }, 170 | "children": [ 171 | { 172 | "attributes": { 173 | "constant": false, 174 | "name": "votesReceived", 175 | "scope": 156, 176 | "stateVariable": true, 177 | "storageLocation": "default", 178 | "type": "mapping(bytes32 => uint8)", 179 | "value": null, 180 | "visibility": "public" 181 | }, 182 | "children": [ 183 | { 184 | "attributes": { 185 | "type": "mapping(bytes32 => uint8)" 186 | }, 187 | "children": [ 188 | { 189 | "attributes": { 190 | "name": "bytes32", 191 | "type": "bytes32" 192 | }, 193 | "id": 59, 194 | "name": "ElementaryTypeName", 195 | "src": "335:7:1" 196 | }, 197 | { 198 | "attributes": { 199 | "name": "uint8", 200 | "type": "uint8" 201 | }, 202 | "id": 60, 203 | "name": "ElementaryTypeName", 204 | "src": "346:5:1" 205 | } 206 | ], 207 | "id": 61, 208 | "name": "Mapping", 209 | "src": "326:26:1" 210 | } 211 | ], 212 | "id": 62, 213 | "name": "VariableDeclaration", 214 | "src": "326:47:1" 215 | }, 216 | { 217 | "attributes": { 218 | "constant": false, 219 | "name": "candidateList", 220 | "scope": 156, 221 | "stateVariable": true, 222 | "storageLocation": "default", 223 | "type": "bytes32[] storage ref", 224 | "value": null, 225 | "visibility": "public" 226 | }, 227 | "children": [ 228 | { 229 | "attributes": { 230 | "length": null, 231 | "type": "bytes32[] storage pointer" 232 | }, 233 | "children": [ 234 | { 235 | "attributes": { 236 | "name": "bytes32", 237 | "type": "bytes32" 238 | }, 239 | "id": 63, 240 | "name": "ElementaryTypeName", 241 | "src": "546:7:1" 242 | } 243 | ], 244 | "id": 64, 245 | "name": "ArrayTypeName", 246 | "src": "546:9:1" 247 | } 248 | ], 249 | "id": 65, 250 | "name": "VariableDeclaration", 251 | "src": "546:30:1" 252 | }, 253 | { 254 | "attributes": { 255 | "constant": false, 256 | "implemented": true, 257 | "isConstructor": true, 258 | "modifiers": [ 259 | null 260 | ], 261 | "name": "Voting", 262 | "payable": false, 263 | "scope": 156, 264 | "stateMutability": "nonpayable", 265 | "superFunction": null, 266 | "visibility": "public" 267 | }, 268 | "children": [ 269 | { 270 | "children": [ 271 | { 272 | "attributes": { 273 | "constant": false, 274 | "name": "candidateNames", 275 | "scope": 76, 276 | "stateVariable": false, 277 | "storageLocation": "default", 278 | "type": "bytes32[] memory", 279 | "value": null, 280 | "visibility": "internal" 281 | }, 282 | "children": [ 283 | { 284 | "attributes": { 285 | "length": null, 286 | "type": "bytes32[] storage pointer" 287 | }, 288 | "children": [ 289 | { 290 | "attributes": { 291 | "name": "bytes32", 292 | "type": "bytes32" 293 | }, 294 | "id": 66, 295 | "name": "ElementaryTypeName", 296 | "src": "813:7:1" 297 | } 298 | ], 299 | "id": 67, 300 | "name": "ArrayTypeName", 301 | "src": "813:9:1" 302 | } 303 | ], 304 | "id": 68, 305 | "name": "VariableDeclaration", 306 | "src": "813:24:1" 307 | } 308 | ], 309 | "id": 69, 310 | "name": "ParameterList", 311 | "src": "812:26:1" 312 | }, 313 | { 314 | "attributes": { 315 | "parameters": [ 316 | null 317 | ] 318 | }, 319 | "children": [], 320 | "id": 70, 321 | "name": "ParameterList", 322 | "src": "846:0:1" 323 | }, 324 | { 325 | "children": [ 326 | { 327 | "children": [ 328 | { 329 | "attributes": { 330 | "argumentTypes": null, 331 | "isConstant": false, 332 | "isLValue": false, 333 | "isPure": false, 334 | "lValueRequested": false, 335 | "operator": "=", 336 | "type": "bytes32[] storage ref" 337 | }, 338 | "children": [ 339 | { 340 | "attributes": { 341 | "argumentTypes": null, 342 | "overloadedDeclarations": [ 343 | null 344 | ], 345 | "referencedDeclaration": 65, 346 | "type": "bytes32[] storage ref", 347 | "value": "candidateList" 348 | }, 349 | "id": 71, 350 | "name": "Identifier", 351 | "src": "852:13:1" 352 | }, 353 | { 354 | "attributes": { 355 | "argumentTypes": null, 356 | "overloadedDeclarations": [ 357 | null 358 | ], 359 | "referencedDeclaration": 68, 360 | "type": "bytes32[] memory", 361 | "value": "candidateNames" 362 | }, 363 | "id": 72, 364 | "name": "Identifier", 365 | "src": "868:14:1" 366 | } 367 | ], 368 | "id": 73, 369 | "name": "Assignment", 370 | "src": "852:30:1" 371 | } 372 | ], 373 | "id": 74, 374 | "name": "ExpressionStatement", 375 | "src": "852:30:1" 376 | } 377 | ], 378 | "id": 75, 379 | "name": "Block", 380 | "src": "846:41:1" 381 | } 382 | ], 383 | "id": 76, 384 | "name": "FunctionDefinition", 385 | "src": "797:90:1" 386 | }, 387 | { 388 | "attributes": { 389 | "constant": true, 390 | "implemented": true, 391 | "isConstructor": false, 392 | "modifiers": [ 393 | null 394 | ], 395 | "name": "allCandidates", 396 | "payable": false, 397 | "scope": 156, 398 | "stateMutability": "view", 399 | "superFunction": null, 400 | "visibility": "public" 401 | }, 402 | "children": [ 403 | { 404 | "attributes": { 405 | "parameters": [ 406 | null 407 | ] 408 | }, 409 | "children": [], 410 | "id": 77, 411 | "name": "ParameterList", 412 | "src": "912:2:1" 413 | }, 414 | { 415 | "children": [ 416 | { 417 | "attributes": { 418 | "constant": false, 419 | "name": "", 420 | "scope": 85, 421 | "stateVariable": false, 422 | "storageLocation": "default", 423 | "type": "bytes32[] memory", 424 | "value": null, 425 | "visibility": "internal" 426 | }, 427 | "children": [ 428 | { 429 | "attributes": { 430 | "length": null, 431 | "type": "bytes32[] storage pointer" 432 | }, 433 | "children": [ 434 | { 435 | "attributes": { 436 | "name": "bytes32", 437 | "type": "bytes32" 438 | }, 439 | "id": 78, 440 | "name": "ElementaryTypeName", 441 | "src": "936:7:1" 442 | } 443 | ], 444 | "id": 79, 445 | "name": "ArrayTypeName", 446 | "src": "936:9:1" 447 | } 448 | ], 449 | "id": 80, 450 | "name": "VariableDeclaration", 451 | "src": "936:9:1" 452 | } 453 | ], 454 | "id": 81, 455 | "name": "ParameterList", 456 | "src": "935:11:1" 457 | }, 458 | { 459 | "children": [ 460 | { 461 | "attributes": { 462 | "functionReturnParameters": 81 463 | }, 464 | "children": [ 465 | { 466 | "attributes": { 467 | "argumentTypes": null, 468 | "overloadedDeclarations": [ 469 | null 470 | ], 471 | "referencedDeclaration": 65, 472 | "type": "bytes32[] storage ref", 473 | "value": "candidateList" 474 | }, 475 | "id": 82, 476 | "name": "Identifier", 477 | "src": "960:13:1" 478 | } 479 | ], 480 | "id": 83, 481 | "name": "Return", 482 | "src": "953:20:1" 483 | } 484 | ], 485 | "id": 84, 486 | "name": "Block", 487 | "src": "947:31:1" 488 | } 489 | ], 490 | "id": 85, 491 | "name": "FunctionDefinition", 492 | "src": "890:88:1" 493 | }, 494 | { 495 | "attributes": { 496 | "constant": true, 497 | "implemented": true, 498 | "isConstructor": false, 499 | "modifiers": [ 500 | null 501 | ], 502 | "name": "totalVotesFor", 503 | "payable": false, 504 | "scope": 156, 505 | "stateMutability": "view", 506 | "superFunction": null, 507 | "visibility": "public" 508 | }, 509 | "children": [ 510 | { 511 | "children": [ 512 | { 513 | "attributes": { 514 | "constant": false, 515 | "name": "candidate", 516 | "scope": 103, 517 | "stateVariable": false, 518 | "storageLocation": "default", 519 | "type": "bytes32", 520 | "value": null, 521 | "visibility": "internal" 522 | }, 523 | "children": [ 524 | { 525 | "attributes": { 526 | "name": "bytes32", 527 | "type": "bytes32" 528 | }, 529 | "id": 86, 530 | "name": "ElementaryTypeName", 531 | "src": "1079:7:1" 532 | } 533 | ], 534 | "id": 87, 535 | "name": "VariableDeclaration", 536 | "src": "1079:17:1" 537 | } 538 | ], 539 | "id": 88, 540 | "name": "ParameterList", 541 | "src": "1078:19:1" 542 | }, 543 | { 544 | "children": [ 545 | { 546 | "attributes": { 547 | "constant": false, 548 | "name": "", 549 | "scope": 103, 550 | "stateVariable": false, 551 | "storageLocation": "default", 552 | "type": "uint8", 553 | "value": null, 554 | "visibility": "internal" 555 | }, 556 | "children": [ 557 | { 558 | "attributes": { 559 | "name": "uint8", 560 | "type": "uint8" 561 | }, 562 | "id": 89, 563 | "name": "ElementaryTypeName", 564 | "src": "1119:5:1" 565 | } 566 | ], 567 | "id": 90, 568 | "name": "VariableDeclaration", 569 | "src": "1119:5:1" 570 | } 571 | ], 572 | "id": 91, 573 | "name": "ParameterList", 574 | "src": "1118:7:1" 575 | }, 576 | { 577 | "children": [ 578 | { 579 | "children": [ 580 | { 581 | "attributes": { 582 | "argumentTypes": null, 583 | "isConstant": false, 584 | "isLValue": false, 585 | "isPure": false, 586 | "isStructConstructorCall": false, 587 | "lValueRequested": false, 588 | "names": [ 589 | null 590 | ], 591 | "type": "tuple()", 592 | "type_conversion": false 593 | }, 594 | "children": [ 595 | { 596 | "attributes": { 597 | "argumentTypes": [ 598 | { 599 | "typeIdentifier": "t_bool", 600 | "typeString": "bool" 601 | } 602 | ], 603 | "overloadedDeclarations": [ 604 | null 605 | ], 606 | "referencedDeclaration": 171, 607 | "type": "function (bool) pure", 608 | "value": "require" 609 | }, 610 | "id": 92, 611 | "name": "Identifier", 612 | "src": "1132:7:1" 613 | }, 614 | { 615 | "attributes": { 616 | "argumentTypes": null, 617 | "isConstant": false, 618 | "isLValue": false, 619 | "isPure": false, 620 | "isStructConstructorCall": false, 621 | "lValueRequested": false, 622 | "names": [ 623 | null 624 | ], 625 | "type": "bool", 626 | "type_conversion": false 627 | }, 628 | "children": [ 629 | { 630 | "attributes": { 631 | "argumentTypes": [ 632 | { 633 | "typeIdentifier": "t_bytes32", 634 | "typeString": "bytes32" 635 | } 636 | ], 637 | "overloadedDeclarations": [ 638 | null 639 | ], 640 | "referencedDeclaration": 155, 641 | "type": "function (bytes32) view returns (bool)", 642 | "value": "validCandidate" 643 | }, 644 | "id": 93, 645 | "name": "Identifier", 646 | "src": "1140:14:1" 647 | }, 648 | { 649 | "attributes": { 650 | "argumentTypes": null, 651 | "overloadedDeclarations": [ 652 | null 653 | ], 654 | "referencedDeclaration": 87, 655 | "type": "bytes32", 656 | "value": "candidate" 657 | }, 658 | "id": 94, 659 | "name": "Identifier", 660 | "src": "1155:9:1" 661 | } 662 | ], 663 | "id": 95, 664 | "name": "FunctionCall", 665 | "src": "1140:25:1" 666 | } 667 | ], 668 | "id": 96, 669 | "name": "FunctionCall", 670 | "src": "1132:34:1" 671 | } 672 | ], 673 | "id": 97, 674 | "name": "ExpressionStatement", 675 | "src": "1132:34:1" 676 | }, 677 | { 678 | "attributes": { 679 | "functionReturnParameters": 91 680 | }, 681 | "children": [ 682 | { 683 | "attributes": { 684 | "argumentTypes": null, 685 | "isConstant": false, 686 | "isLValue": true, 687 | "isPure": false, 688 | "lValueRequested": false, 689 | "type": "uint8" 690 | }, 691 | "children": [ 692 | { 693 | "attributes": { 694 | "argumentTypes": null, 695 | "overloadedDeclarations": [ 696 | null 697 | ], 698 | "referencedDeclaration": 62, 699 | "type": "mapping(bytes32 => uint8)", 700 | "value": "votesReceived" 701 | }, 702 | "id": 98, 703 | "name": "Identifier", 704 | "src": "1179:13:1" 705 | }, 706 | { 707 | "attributes": { 708 | "argumentTypes": null, 709 | "overloadedDeclarations": [ 710 | null 711 | ], 712 | "referencedDeclaration": 87, 713 | "type": "bytes32", 714 | "value": "candidate" 715 | }, 716 | "id": 99, 717 | "name": "Identifier", 718 | "src": "1193:9:1" 719 | } 720 | ], 721 | "id": 100, 722 | "name": "IndexAccess", 723 | "src": "1179:24:1" 724 | } 725 | ], 726 | "id": 101, 727 | "name": "Return", 728 | "src": "1172:31:1" 729 | } 730 | ], 731 | "id": 102, 732 | "name": "Block", 733 | "src": "1126:82:1" 734 | } 735 | ], 736 | "id": 103, 737 | "name": "FunctionDefinition", 738 | "src": "1056:152:1" 739 | }, 740 | { 741 | "attributes": { 742 | "constant": false, 743 | "implemented": true, 744 | "isConstructor": false, 745 | "modifiers": [ 746 | null 747 | ], 748 | "name": "voteForCandidate", 749 | "payable": false, 750 | "scope": 156, 751 | "stateMutability": "nonpayable", 752 | "superFunction": null, 753 | "visibility": "public" 754 | }, 755 | "children": [ 756 | { 757 | "children": [ 758 | { 759 | "attributes": { 760 | "constant": false, 761 | "name": "candidate", 762 | "scope": 123, 763 | "stateVariable": false, 764 | "storageLocation": "default", 765 | "type": "bytes32", 766 | "value": null, 767 | "visibility": "internal" 768 | }, 769 | "children": [ 770 | { 771 | "attributes": { 772 | "name": "bytes32", 773 | "type": "bytes32" 774 | }, 775 | "id": 104, 776 | "name": "ElementaryTypeName", 777 | "src": "1354:7:1" 778 | } 779 | ], 780 | "id": 105, 781 | "name": "VariableDeclaration", 782 | "src": "1354:17:1" 783 | }, 784 | { 785 | "attributes": { 786 | "constant": false, 787 | "name": "votes", 788 | "scope": 123, 789 | "stateVariable": false, 790 | "storageLocation": "default", 791 | "type": "uint8", 792 | "value": null, 793 | "visibility": "internal" 794 | }, 795 | "children": [ 796 | { 797 | "attributes": { 798 | "name": "uint8", 799 | "type": "uint8" 800 | }, 801 | "id": 106, 802 | "name": "ElementaryTypeName", 803 | "src": "1373:5:1" 804 | } 805 | ], 806 | "id": 107, 807 | "name": "VariableDeclaration", 808 | "src": "1373:11:1" 809 | } 810 | ], 811 | "id": 108, 812 | "name": "ParameterList", 813 | "src": "1353:32:1" 814 | }, 815 | { 816 | "attributes": { 817 | "parameters": [ 818 | null 819 | ] 820 | }, 821 | "children": [], 822 | "id": 109, 823 | "name": "ParameterList", 824 | "src": "1393:0:1" 825 | }, 826 | { 827 | "children": [ 828 | { 829 | "children": [ 830 | { 831 | "attributes": { 832 | "argumentTypes": null, 833 | "isConstant": false, 834 | "isLValue": false, 835 | "isPure": false, 836 | "isStructConstructorCall": false, 837 | "lValueRequested": false, 838 | "names": [ 839 | null 840 | ], 841 | "type": "tuple()", 842 | "type_conversion": false 843 | }, 844 | "children": [ 845 | { 846 | "attributes": { 847 | "argumentTypes": [ 848 | { 849 | "typeIdentifier": "t_bool", 850 | "typeString": "bool" 851 | } 852 | ], 853 | "overloadedDeclarations": [ 854 | null 855 | ], 856 | "referencedDeclaration": 171, 857 | "type": "function (bool) pure", 858 | "value": "require" 859 | }, 860 | "id": 110, 861 | "name": "Identifier", 862 | "src": "1399:7:1" 863 | }, 864 | { 865 | "attributes": { 866 | "argumentTypes": null, 867 | "isConstant": false, 868 | "isLValue": false, 869 | "isPure": false, 870 | "isStructConstructorCall": false, 871 | "lValueRequested": false, 872 | "names": [ 873 | null 874 | ], 875 | "type": "bool", 876 | "type_conversion": false 877 | }, 878 | "children": [ 879 | { 880 | "attributes": { 881 | "argumentTypes": [ 882 | { 883 | "typeIdentifier": "t_bytes32", 884 | "typeString": "bytes32" 885 | } 886 | ], 887 | "overloadedDeclarations": [ 888 | null 889 | ], 890 | "referencedDeclaration": 155, 891 | "type": "function (bytes32) view returns (bool)", 892 | "value": "validCandidate" 893 | }, 894 | "id": 111, 895 | "name": "Identifier", 896 | "src": "1407:14:1" 897 | }, 898 | { 899 | "attributes": { 900 | "argumentTypes": null, 901 | "overloadedDeclarations": [ 902 | null 903 | ], 904 | "referencedDeclaration": 105, 905 | "type": "bytes32", 906 | "value": "candidate" 907 | }, 908 | "id": 112, 909 | "name": "Identifier", 910 | "src": "1422:9:1" 911 | } 912 | ], 913 | "id": 113, 914 | "name": "FunctionCall", 915 | "src": "1407:25:1" 916 | } 917 | ], 918 | "id": 114, 919 | "name": "FunctionCall", 920 | "src": "1399:34:1" 921 | } 922 | ], 923 | "id": 115, 924 | "name": "ExpressionStatement", 925 | "src": "1399:34:1" 926 | }, 927 | { 928 | "children": [ 929 | { 930 | "attributes": { 931 | "argumentTypes": null, 932 | "isConstant": false, 933 | "isLValue": false, 934 | "isPure": false, 935 | "lValueRequested": false, 936 | "operator": "+=", 937 | "type": "uint8" 938 | }, 939 | "children": [ 940 | { 941 | "attributes": { 942 | "argumentTypes": null, 943 | "isConstant": false, 944 | "isLValue": true, 945 | "isPure": false, 946 | "lValueRequested": true, 947 | "type": "uint8" 948 | }, 949 | "children": [ 950 | { 951 | "attributes": { 952 | "argumentTypes": null, 953 | "overloadedDeclarations": [ 954 | null 955 | ], 956 | "referencedDeclaration": 62, 957 | "type": "mapping(bytes32 => uint8)", 958 | "value": "votesReceived" 959 | }, 960 | "id": 116, 961 | "name": "Identifier", 962 | "src": "1439:13:1" 963 | }, 964 | { 965 | "attributes": { 966 | "argumentTypes": null, 967 | "overloadedDeclarations": [ 968 | null 969 | ], 970 | "referencedDeclaration": 105, 971 | "type": "bytes32", 972 | "value": "candidate" 973 | }, 974 | "id": 117, 975 | "name": "Identifier", 976 | "src": "1453:9:1" 977 | } 978 | ], 979 | "id": 118, 980 | "name": "IndexAccess", 981 | "src": "1439:24:1" 982 | }, 983 | { 984 | "attributes": { 985 | "argumentTypes": null, 986 | "overloadedDeclarations": [ 987 | null 988 | ], 989 | "referencedDeclaration": 107, 990 | "type": "uint8", 991 | "value": "votes" 992 | }, 993 | "id": 119, 994 | "name": "Identifier", 995 | "src": "1467:5:1" 996 | } 997 | ], 998 | "id": 120, 999 | "name": "Assignment", 1000 | "src": "1439:33:1" 1001 | } 1002 | ], 1003 | "id": 121, 1004 | "name": "ExpressionStatement", 1005 | "src": "1439:33:1" 1006 | } 1007 | ], 1008 | "id": 122, 1009 | "name": "Block", 1010 | "src": "1393:84:1" 1011 | } 1012 | ], 1013 | "id": 123, 1014 | "name": "FunctionDefinition", 1015 | "src": "1328:149:1" 1016 | }, 1017 | { 1018 | "attributes": { 1019 | "constant": true, 1020 | "implemented": true, 1021 | "isConstructor": false, 1022 | "modifiers": [ 1023 | null 1024 | ], 1025 | "name": "validCandidate", 1026 | "payable": false, 1027 | "scope": 156, 1028 | "stateMutability": "view", 1029 | "superFunction": null, 1030 | "visibility": "public" 1031 | }, 1032 | "children": [ 1033 | { 1034 | "children": [ 1035 | { 1036 | "attributes": { 1037 | "constant": false, 1038 | "name": "candidate", 1039 | "scope": 155, 1040 | "stateVariable": false, 1041 | "storageLocation": "default", 1042 | "type": "bytes32", 1043 | "value": null, 1044 | "visibility": "internal" 1045 | }, 1046 | "children": [ 1047 | { 1048 | "attributes": { 1049 | "name": "bytes32", 1050 | "type": "bytes32" 1051 | }, 1052 | "id": 124, 1053 | "name": "ElementaryTypeName", 1054 | "src": "1505:7:1" 1055 | } 1056 | ], 1057 | "id": 125, 1058 | "name": "VariableDeclaration", 1059 | "src": "1505:17:1" 1060 | } 1061 | ], 1062 | "id": 126, 1063 | "name": "ParameterList", 1064 | "src": "1504:19:1" 1065 | }, 1066 | { 1067 | "children": [ 1068 | { 1069 | "attributes": { 1070 | "constant": false, 1071 | "name": "", 1072 | "scope": 155, 1073 | "stateVariable": false, 1074 | "storageLocation": "default", 1075 | "type": "bool", 1076 | "value": null, 1077 | "visibility": "internal" 1078 | }, 1079 | "children": [ 1080 | { 1081 | "attributes": { 1082 | "name": "bool", 1083 | "type": "bool" 1084 | }, 1085 | "id": 127, 1086 | "name": "ElementaryTypeName", 1087 | "src": "1545:4:1" 1088 | } 1089 | ], 1090 | "id": 128, 1091 | "name": "VariableDeclaration", 1092 | "src": "1545:4:1" 1093 | } 1094 | ], 1095 | "id": 129, 1096 | "name": "ParameterList", 1097 | "src": "1544:6:1" 1098 | }, 1099 | { 1100 | "children": [ 1101 | { 1102 | "children": [ 1103 | { 1104 | "attributes": { 1105 | "assignments": [ 1106 | 131 1107 | ] 1108 | }, 1109 | "children": [ 1110 | { 1111 | "attributes": { 1112 | "constant": false, 1113 | "name": "i", 1114 | "scope": 155, 1115 | "stateVariable": false, 1116 | "storageLocation": "default", 1117 | "type": "uint256", 1118 | "value": null, 1119 | "visibility": "internal" 1120 | }, 1121 | "children": [ 1122 | { 1123 | "attributes": { 1124 | "name": "uint", 1125 | "type": "uint256" 1126 | }, 1127 | "id": 130, 1128 | "name": "ElementaryTypeName", 1129 | "src": "1561:4:1" 1130 | } 1131 | ], 1132 | "id": 131, 1133 | "name": "VariableDeclaration", 1134 | "src": "1561:6:1" 1135 | }, 1136 | { 1137 | "attributes": { 1138 | "argumentTypes": null, 1139 | "hexvalue": "30", 1140 | "isConstant": false, 1141 | "isLValue": false, 1142 | "isPure": true, 1143 | "lValueRequested": false, 1144 | "subdenomination": null, 1145 | "token": "number", 1146 | "type": "int_const 0", 1147 | "value": "0" 1148 | }, 1149 | "id": 132, 1150 | "name": "Literal", 1151 | "src": "1570:1:1" 1152 | } 1153 | ], 1154 | "id": 133, 1155 | "name": "VariableDeclarationStatement", 1156 | "src": "1561:10:1" 1157 | }, 1158 | { 1159 | "attributes": { 1160 | "argumentTypes": null, 1161 | "commonType": { 1162 | "typeIdentifier": "t_uint256", 1163 | "typeString": "uint256" 1164 | }, 1165 | "isConstant": false, 1166 | "isLValue": false, 1167 | "isPure": false, 1168 | "lValueRequested": false, 1169 | "operator": "<", 1170 | "type": "bool" 1171 | }, 1172 | "children": [ 1173 | { 1174 | "attributes": { 1175 | "argumentTypes": null, 1176 | "overloadedDeclarations": [ 1177 | null 1178 | ], 1179 | "referencedDeclaration": 131, 1180 | "type": "uint256", 1181 | "value": "i" 1182 | }, 1183 | "id": 134, 1184 | "name": "Identifier", 1185 | "src": "1573:1:1" 1186 | }, 1187 | { 1188 | "attributes": { 1189 | "argumentTypes": null, 1190 | "isConstant": false, 1191 | "isLValue": true, 1192 | "isPure": false, 1193 | "lValueRequested": false, 1194 | "member_name": "length", 1195 | "referencedDeclaration": null, 1196 | "type": "uint256" 1197 | }, 1198 | "children": [ 1199 | { 1200 | "attributes": { 1201 | "argumentTypes": null, 1202 | "overloadedDeclarations": [ 1203 | null 1204 | ], 1205 | "referencedDeclaration": 65, 1206 | "type": "bytes32[] storage ref", 1207 | "value": "candidateList" 1208 | }, 1209 | "id": 135, 1210 | "name": "Identifier", 1211 | "src": "1577:13:1" 1212 | } 1213 | ], 1214 | "id": 136, 1215 | "name": "MemberAccess", 1216 | "src": "1577:20:1" 1217 | } 1218 | ], 1219 | "id": 137, 1220 | "name": "BinaryOperation", 1221 | "src": "1573:24:1" 1222 | }, 1223 | { 1224 | "children": [ 1225 | { 1226 | "attributes": { 1227 | "argumentTypes": null, 1228 | "isConstant": false, 1229 | "isLValue": false, 1230 | "isPure": false, 1231 | "lValueRequested": false, 1232 | "operator": "++", 1233 | "prefix": false, 1234 | "type": "uint256" 1235 | }, 1236 | "children": [ 1237 | { 1238 | "attributes": { 1239 | "argumentTypes": null, 1240 | "overloadedDeclarations": [ 1241 | null 1242 | ], 1243 | "referencedDeclaration": 131, 1244 | "type": "uint256", 1245 | "value": "i" 1246 | }, 1247 | "id": 138, 1248 | "name": "Identifier", 1249 | "src": "1599:1:1" 1250 | } 1251 | ], 1252 | "id": 139, 1253 | "name": "UnaryOperation", 1254 | "src": "1599:3:1" 1255 | } 1256 | ], 1257 | "id": 140, 1258 | "name": "ExpressionStatement", 1259 | "src": "1599:3:1" 1260 | }, 1261 | { 1262 | "children": [ 1263 | { 1264 | "attributes": { 1265 | "falseBody": null 1266 | }, 1267 | "children": [ 1268 | { 1269 | "attributes": { 1270 | "argumentTypes": null, 1271 | "commonType": { 1272 | "typeIdentifier": "t_bytes32", 1273 | "typeString": "bytes32" 1274 | }, 1275 | "isConstant": false, 1276 | "isLValue": false, 1277 | "isPure": false, 1278 | "lValueRequested": false, 1279 | "operator": "==", 1280 | "type": "bool" 1281 | }, 1282 | "children": [ 1283 | { 1284 | "attributes": { 1285 | "argumentTypes": null, 1286 | "isConstant": false, 1287 | "isLValue": true, 1288 | "isPure": false, 1289 | "lValueRequested": false, 1290 | "type": "bytes32" 1291 | }, 1292 | "children": [ 1293 | { 1294 | "attributes": { 1295 | "argumentTypes": null, 1296 | "overloadedDeclarations": [ 1297 | null 1298 | ], 1299 | "referencedDeclaration": 65, 1300 | "type": "bytes32[] storage ref", 1301 | "value": "candidateList" 1302 | }, 1303 | "id": 141, 1304 | "name": "Identifier", 1305 | "src": "1616:13:1" 1306 | }, 1307 | { 1308 | "attributes": { 1309 | "argumentTypes": null, 1310 | "overloadedDeclarations": [ 1311 | null 1312 | ], 1313 | "referencedDeclaration": 131, 1314 | "type": "uint256", 1315 | "value": "i" 1316 | }, 1317 | "id": 142, 1318 | "name": "Identifier", 1319 | "src": "1630:1:1" 1320 | } 1321 | ], 1322 | "id": 143, 1323 | "name": "IndexAccess", 1324 | "src": "1616:16:1" 1325 | }, 1326 | { 1327 | "attributes": { 1328 | "argumentTypes": null, 1329 | "overloadedDeclarations": [ 1330 | null 1331 | ], 1332 | "referencedDeclaration": 125, 1333 | "type": "bytes32", 1334 | "value": "candidate" 1335 | }, 1336 | "id": 144, 1337 | "name": "Identifier", 1338 | "src": "1636:9:1" 1339 | } 1340 | ], 1341 | "id": 145, 1342 | "name": "BinaryOperation", 1343 | "src": "1616:29:1" 1344 | }, 1345 | { 1346 | "children": [ 1347 | { 1348 | "attributes": { 1349 | "functionReturnParameters": 129 1350 | }, 1351 | "children": [ 1352 | { 1353 | "attributes": { 1354 | "argumentTypes": null, 1355 | "hexvalue": "74727565", 1356 | "isConstant": false, 1357 | "isLValue": false, 1358 | "isPure": true, 1359 | "lValueRequested": false, 1360 | "subdenomination": null, 1361 | "token": "bool", 1362 | "type": "bool", 1363 | "value": "true" 1364 | }, 1365 | "id": 146, 1366 | "name": "Literal", 1367 | "src": "1664:4:1" 1368 | } 1369 | ], 1370 | "id": 147, 1371 | "name": "Return", 1372 | "src": "1657:11:1" 1373 | } 1374 | ], 1375 | "id": 148, 1376 | "name": "Block", 1377 | "src": "1647:30:1" 1378 | } 1379 | ], 1380 | "id": 149, 1381 | "name": "IfStatement", 1382 | "src": "1612:65:1" 1383 | } 1384 | ], 1385 | "id": 150, 1386 | "name": "Block", 1387 | "src": "1604:79:1" 1388 | } 1389 | ], 1390 | "id": 151, 1391 | "name": "ForStatement", 1392 | "src": "1557:126:1" 1393 | }, 1394 | { 1395 | "attributes": { 1396 | "functionReturnParameters": 129 1397 | }, 1398 | "children": [ 1399 | { 1400 | "attributes": { 1401 | "argumentTypes": null, 1402 | "hexvalue": "66616c7365", 1403 | "isConstant": false, 1404 | "isLValue": false, 1405 | "isPure": true, 1406 | "lValueRequested": false, 1407 | "subdenomination": null, 1408 | "token": "bool", 1409 | "type": "bool", 1410 | "value": "false" 1411 | }, 1412 | "id": 152, 1413 | "name": "Literal", 1414 | "src": "1695:5:1" 1415 | } 1416 | ], 1417 | "id": 153, 1418 | "name": "Return", 1419 | "src": "1688:12:1" 1420 | } 1421 | ], 1422 | "id": 154, 1423 | "name": "Block", 1424 | "src": "1551:154:1" 1425 | } 1426 | ], 1427 | "id": 155, 1428 | "name": "FunctionDefinition", 1429 | "src": "1481:224:1" 1430 | } 1431 | ], 1432 | "id": 156, 1433 | "name": "ContractDefinition", 1434 | "src": "101:1606:1" 1435 | } 1436 | ], 1437 | "id": 157, 1438 | "name": "SourceUnit", 1439 | "src": "0:1708:1" 1440 | }, 1441 | "compiler": { 1442 | "name": "solc", 1443 | "version": "0.4.18+commit.9cf6e910.Emscripten.clang" 1444 | }, 1445 | "networks": { 1446 | "3": { 1447 | "events": {}, 1448 | "links": {}, 1449 | "address": "0xbb5f4afe9e81a6f60218dd1df25b74ad54fedcc8" 1450 | } 1451 | }, 1452 | "schemaVersion": "1.0.1", 1453 | "updatedAt": "2018-01-28T18:54:54.148Z" 1454 | } -------------------------------------------------------------------------------- /libdefs.js: -------------------------------------------------------------------------------- 1 | // @flow 2 | 3 | declare module 'react-native' { 4 | declare module.exports: any; 5 | } 6 | declare module '@expo/vector-icons' { 7 | declare module.exports: any; 8 | } 9 | declare module 'web3' { 10 | declare module.exports: any; 11 | } 12 | declare module 'truffle-contract' { 13 | declare module.exports: any; 14 | } 15 | declare module 'react-native-star-rating' { 16 | declare module.exports: any; 17 | } 18 | declare module 'react-navigation' { 19 | declare module.exports: any; 20 | } 21 | declare module 'react-native-pull-to-refresh' { 22 | declare module.exports: any; 23 | } 24 | declare module 'victory-native' { 25 | declare module.exports: any; 26 | } 27 | declare module 'truffle-hdwallet-provider' { 28 | declare module.exports: any; 29 | } 30 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "main": "node_modules/expo/AppEntry.js", 3 | "private": true, 4 | "scripts": { 5 | "lint": "eslint src/", 6 | "format": "prettier --ignore-path .gitignore --single-quote --use-tabs --trailing-comma es5 --write '**/*.js'", 7 | "flow": "flow ." 8 | }, 9 | "author": "Alejandro Garcia ", 10 | "engines": { 11 | "node": ">=6.0.0" 12 | }, 13 | "keywords": [ 14 | "react-native", 15 | "ethereum", 16 | "dapp", 17 | "poll", 18 | "web3" 19 | ], 20 | "dependencies": { 21 | "expo": "^30.0.0", 22 | "react": "16.3.1", 23 | "react-native": "https://github.com/expo/react-native/archive/sdk-30.0.0.tar.gz", 24 | "react-native-pull-to-refresh": "^2.1.3", 25 | "react-native-star-rating": "^1.0.8", 26 | "react-navigation": "^2.18.2", 27 | "truffle-contract": "^3.0.2", 28 | "truffle-hdwallet-provider": "^0.0.3", 29 | "victory-native": "^0.16.6", 30 | "web3": "^0.20.2" 31 | }, 32 | "devDependencies": { 33 | "babel-eslint": "^8.2.1", 34 | "babel-preset-react-native-web3": "0.0.4", 35 | "eslint": "^4.15.0", 36 | "eslint-plugin-import": "^2.8.0", 37 | "eslint-plugin-react": "^7.5.1", 38 | "flow-bin": "^0.71.0" 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /src/Candidates/CandidateList.js: -------------------------------------------------------------------------------- 1 | /* @flow */ 2 | 3 | import React, { PureComponent } from 'react'; 4 | import { ScrollView, ActivityIndicator } from 'react-native'; 5 | import type { CandidateType } from '../types'; 6 | 7 | import Item from './Item'; 8 | type Props = { 9 | candidates: Array, 10 | Voting: *, 11 | web3: *, 12 | }; 13 | 14 | export default class CandidateList extends PureComponent { 15 | render() { 16 | return ( 17 | 18 | {this.props.candidates && this.props.candidates.length > 0 ? ( 19 | this.props.candidates.map(candidate => ( 20 | 26 | )) 27 | ) : ( 28 | 29 | )} 30 | 31 | ); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/Candidates/Item.js: -------------------------------------------------------------------------------- 1 | /* @flow */ 2 | 3 | import React, { PureComponent } from 'react'; 4 | import { 5 | StyleSheet, 6 | View, 7 | Text, 8 | Image, 9 | TouchableOpacity, 10 | Linking, 11 | } from 'react-native'; 12 | import Vote from './Vote'; 13 | import type { CandidateType } from '../types'; 14 | 15 | export default class Item extends PureComponent<{ 16 | candidate: CandidateType, 17 | Voting: *, 18 | web3: *, 19 | }> { 20 | render() { 21 | const { candidate, Voting, web3 } = this.props; 22 | return ( 23 | 24 | 25 | 27 | Linking.openURL( 28 | `https://www.larvalabs.com/cryptopunks/details/${ 29 | candidate.index 30 | }` 31 | ) 32 | } 33 | > 34 | 42 | 43 | 44 | 45 | 46 | {candidate.name} 47 | 48 | CryptoPunk #{candidate.index} 49 | 50 | 51 | 52 | 53 | 54 | ); 55 | } 56 | } 57 | 58 | const styles = StyleSheet.create({ 59 | caption: { 60 | fontSize: 18, 61 | color: 'grey', 62 | }, 63 | icon: { 64 | paddingHorizontal: 10, 65 | }, 66 | rowContentSubTitle: { 67 | color: 'grey', 68 | }, 69 | rowContentTitle: { 70 | fontSize: 16, 71 | }, 72 | rowContent: { 73 | flexDirection: 'column', 74 | justifyContent: 'space-between', 75 | }, 76 | image: { width: 40, height: 40, borderRadius: 20 }, 77 | main: { 78 | flexDirection: 'row', 79 | alignItems: 'center', 80 | flex: 1, 81 | marginVertical: 2, 82 | }, 83 | votes: { 84 | fontSize: 16, 85 | marginHorizontal: 5, 86 | color: 'yellow', 87 | }, 88 | row: { 89 | flexDirection: 'row', 90 | borderBottomWidth: 1, 91 | alignItems: 'center', 92 | flex: 1, 93 | borderBottomColor: '#CCC', 94 | justifyContent: 'space-between', 95 | }, 96 | }); 97 | -------------------------------------------------------------------------------- /src/Candidates/Main.js: -------------------------------------------------------------------------------- 1 | /* @flow */ 2 | 3 | import React, { Component } from 'react'; 4 | import CandidateList from './CandidateList'; 5 | 6 | import Contract from 'truffle-contract'; 7 | import { View, StyleSheet } from 'react-native'; 8 | 9 | import type { CandidateType } from '../types'; 10 | 11 | import VotingArtifact from '../../build/contracts/Voting.json'; 12 | 13 | const Voting = Contract(VotingArtifact); 14 | 15 | const styles = StyleSheet.create({ 16 | box: { flex: 1 }, 17 | spacer: { flex: 1 }, 18 | }); 19 | 20 | type Props = { 21 | web3: *, 22 | }; 23 | type State = { 24 | candidates: Array, 25 | }; 26 | class Main extends Component { 27 | state = { 28 | candidates: [], 29 | }; 30 | componentWillMount() { 31 | Voting.setProvider(this.props.web3.currentProvider); 32 | } 33 | componentDidMount() { 34 | this.populateCandidates(); 35 | } 36 | 37 | /* Instead of hardcoding the candidates hash, we now fetch the candidate list from 38 | * the blockchain and populate the array. Once we fetch the candidates, we setup the 39 | * table in the UI with all the candidates and the votes they have received. 40 | */ 41 | populateCandidates: Function; 42 | populateCandidates = () => { 43 | return Voting.deployed().then(contractInstance => { 44 | return contractInstance.allCandidates.call().then(raw => { 45 | const candidates = raw.map((hash, index) => { 46 | return { 47 | hash, 48 | name: this.props.web3.toUtf8(hash), 49 | index, 50 | }; 51 | }); 52 | this.setState({ 53 | candidates, 54 | }); 55 | }); 56 | }); 57 | }; 58 | 59 | render() { 60 | return ( 61 | 62 | 67 | 68 | 69 | ); 70 | } 71 | } 72 | 73 | export default Main; 74 | -------------------------------------------------------------------------------- /src/Candidates/Star.js: -------------------------------------------------------------------------------- 1 | /* @flow */ 2 | 3 | import React, { Component } from 'react'; 4 | 5 | import { View, StyleSheet } from 'react-native'; 6 | import StarRating from 'react-native-star-rating'; 7 | 8 | class Star extends Component< 9 | { 10 | onPress: (rating: string) => void, 11 | }, 12 | { 13 | starCount: number, 14 | } 15 | > { 16 | state = { 17 | starCount: 0, 18 | }; 19 | onStarRatingPress: Function; 20 | onStarRatingPress = rating => { 21 | if (this.state.starCount !== 0) { 22 | return; 23 | } 24 | this.setState({ 25 | starCount: rating, 26 | }); 27 | this.props.onPress(rating); 28 | }; 29 | render() { 30 | return ( 31 | 32 | 39 | 40 | ); 41 | } 42 | } 43 | 44 | const styles = StyleSheet.create({ 45 | container: { 46 | padding: 10, 47 | width: 50, 48 | marginHorizontal: 5, 49 | }, 50 | }); 51 | export default Star; 52 | -------------------------------------------------------------------------------- /src/Candidates/Vote.js: -------------------------------------------------------------------------------- 1 | /* @flow */ 2 | 3 | import React, { Component } from 'react'; 4 | 5 | import Star from './Star'; 6 | 7 | import type { CandidateType } from '../types'; 8 | import { Alert, Linking } from 'react-native'; 9 | 10 | class Container extends Component<{ 11 | Voting: *, 12 | web3: *, 13 | candidate: CandidateType, 14 | }> { 15 | onPress = (candidate: *, star: *): void => { 16 | const { Voting } = this.props; 17 | Alert.alert( 18 | 'Vote has been submitted.', 19 | 'The vote count will increment as soon as the vote is recorded on the blockchain. Please wait.', 20 | [ 21 | { 22 | text: 'OK', 23 | onPress: () => { 24 | new Promise((resolve: *) => { 25 | this.props.web3.eth.getAccounts((error, result) => { 26 | if (error) { 27 | return console.error(error); 28 | } 29 | Voting.deployed().then(contractInstance => { 30 | return contractInstance 31 | .voteForCandidate(candidate, star, { 32 | // configure here the priority of the vote 33 | gas: 140000, 34 | // using coinbase 35 | from: result[0], 36 | }) 37 | .then(result => { 38 | Alert.alert( 39 | 'Great Choice!', 40 | 'Yeah, thanks for voting, it has been submitted to the blockchain...', 41 | [ 42 | { 43 | text: 'Transaction', 44 | onPress: () => { 45 | Linking.openURL( 46 | 'https://ropsten.etherscan.io/address/0x9004c442d310e9c3acc52500c897a9daf80794a8' 47 | ); 48 | resolve(); 49 | }, 50 | }, 51 | { 52 | text: 'OK', 53 | onPress: () => { 54 | resolve(); 55 | console.log('ok!'); 56 | }, 57 | }, 58 | ], 59 | { cancelable: false } 60 | ); 61 | }) 62 | .catch(err => { 63 | Alert.alert( 64 | 'Configure coinbase account before voting', 65 | err.toString() 66 | ); 67 | }); 68 | }); 69 | }); 70 | }); 71 | }, 72 | }, 73 | ] 74 | ); 75 | }; 76 | render() { 77 | const { candidate } = this.props; 78 | return this.onPress(candidate.hash, args)} />; 79 | } 80 | } 81 | 82 | export default Container; 83 | -------------------------------------------------------------------------------- /src/Container.js: -------------------------------------------------------------------------------- 1 | /* @flow */ 2 | 3 | import React, { PureComponent } from 'react'; 4 | import { Text, View, StyleSheet } from 'react-native'; 5 | 6 | import { MaterialIcons } from '@expo/vector-icons'; 7 | 8 | export default class Container extends PureComponent<{ 9 | children?: any, 10 | }> { 11 | render() { 12 | return ( 13 | 14 | 15 | 16 | 17 | 18 | Star your favorite crypto punk 19 | 20 | {this.props.children} 21 | 22 | MIT License @ zetta 23 | 24 | 25 | ); 26 | } 27 | } 28 | 29 | const styles = StyleSheet.create({ 30 | Container: { 31 | flex: 1, 32 | }, 33 | Header: { 34 | paddingTop: 40, 35 | paddingBottom: 20, 36 | paddingHorizontal: 12, 37 | backgroundColor: '#37474f', 38 | alignItems: 'center', 39 | }, 40 | titleContainer: { 41 | paddingHorizontal: 12, 42 | paddingVertical: 5, 43 | backgroundColor: '#62727b', 44 | }, 45 | footerContainer: { 46 | alignItems: 'center', 47 | paddingHorizontal: 12, 48 | paddingVertical: 8, 49 | backgroundColor: '#333', 50 | }, 51 | title: { 52 | alignItems: 'center', 53 | fontSize: 14, 54 | paddingVertical: 5, 55 | color: 'white', 56 | }, 57 | footer: { 58 | alignItems: 'center', 59 | fontSize: 12, 60 | paddingVertical: 5, 61 | color: 'white', 62 | }, 63 | }); 64 | -------------------------------------------------------------------------------- /src/Stats.js: -------------------------------------------------------------------------------- 1 | /* @flow */ 2 | 3 | import React, { Component } from 'react'; 4 | 5 | import Contract from 'truffle-contract'; 6 | import { View, StyleSheet, Text, Dimensions, ScrollView } from 'react-native'; 7 | import PTRView from 'react-native-pull-to-refresh'; 8 | 9 | import VotingArtifact from '../build/contracts/Voting.json'; 10 | 11 | import type { CandidateType } from './types'; 12 | 13 | import { withNavigation } from 'react-navigation'; 14 | import { VictoryBar, VictoryChart } from 'victory-native'; 15 | 16 | const Voting = Contract(VotingArtifact); 17 | 18 | type Props = { 19 | web3: *, 20 | navigation: *, 21 | }; 22 | type State = { 23 | candidates: Array, 24 | isLoading: boolean, 25 | }; 26 | 27 | class Stats extends Component { 28 | state = { 29 | candidates: [], 30 | isLoading: true, 31 | }; 32 | componentWillMount() { 33 | Voting.setProvider(this.props.web3.currentProvider); 34 | } 35 | componentDidMount() { 36 | this.populateCandidates(); 37 | } 38 | 39 | getCandidateBalances: Function; 40 | getCandidateBalances = () => { 41 | /* We store the candidate names as bytes32 on the blockchain. We use the 42 | * handy toUtf8 method to convert from bytes32 to string 43 | */ 44 | return new Promise((resolve: Function) => { 45 | const promiseN = this.state.candidates.map(({ hash }) => { 46 | return this.getCandidateVote(hash).then(votes => { 47 | return { 48 | name: this.props.web3.toUtf8(hash), 49 | hash, 50 | x: this.props.web3.toUtf8(hash).substr(0, 2), 51 | y: parseInt(votes.toString()), 52 | }; 53 | }); 54 | }); 55 | Promise.all(promiseN).then(candidates => { 56 | this.setState( 57 | { 58 | candidates, 59 | isLoading: false, 60 | }, 61 | () => { 62 | resolve(); 63 | } 64 | ); 65 | }); 66 | }); 67 | }; 68 | getCandidateVote: Function; 69 | getCandidateVote = hash => { 70 | return Voting.deployed() 71 | .then(zetta => { 72 | return zetta.totalVotesFor.call(hash); 73 | }) 74 | .catch(function(e) { 75 | console.log(e); 76 | throw e; 77 | }); 78 | }; 79 | 80 | /* Instead of hardcoding the candidates hash, we now fetch the candidate list from 81 | * the blockchain and populate the array. Once we fetch the candidates, we setup the 82 | * table in the UI with all the candidates and the votes they have received. 83 | */ 84 | populateCandidates: Function; 85 | populateCandidates = () => { 86 | return Voting.deployed().then(contractInstance => { 87 | return contractInstance.allCandidates.call().then(raw => { 88 | const candidates = raw.map(hash => { 89 | return { 90 | name: this.props.web3.toUtf8(hash), 91 | hash, 92 | x: this.props.web3.toUtf8(hash).substr(0, 2), 93 | y: 0, 94 | }; 95 | }); 96 | this.setState({ 97 | candidates, 98 | }); 99 | }); 100 | }); 101 | }; 102 | 103 | render() { 104 | if (this.state.isLoading) { 105 | return ( 106 | 107 | 108 | Pull to refresh the stats 109 | 110 | 111 | ); 112 | } 113 | return ( 114 | 115 | 116 | Stats 117 | 118 | The result of the poll is persisted on the blockchain, public and 119 | everyone can access to it. Gas per vote is 140000, that is 120 | expensive, but that asures the transaction to be included by miners 121 | in the next block. 122 | 123 | 124 | 125 | 131 | 135 | 136 | 137 | 138 | ); 139 | } 140 | } 141 | export default withNavigation(Stats); 142 | 143 | const styles = StyleSheet.create({ 144 | info: { 145 | alignItems: 'center', 146 | paddingVertical: 5, 147 | }, 148 | refresh: { 149 | fontSize: 16, 150 | }, 151 | header: { 152 | alignItems: 'flex-start', 153 | padding: 10, 154 | flexDirection: 'column', 155 | borderBottomWidth: 1, 156 | borderBottomColor: '#CCC', 157 | }, 158 | contentSubTitle: { 159 | textAlign: 'left', 160 | color: 'grey', 161 | fontSize: 13, 162 | paddingVertical: 5, 163 | }, 164 | contentTitle: { 165 | textAlign: 'left', 166 | paddingTop: 5, 167 | fontSize: 20, 168 | }, 169 | container: { 170 | alignItems: 'center', 171 | justifyContent: 'center', 172 | flex: 1, 173 | }, 174 | }); 175 | -------------------------------------------------------------------------------- /src/types.js: -------------------------------------------------------------------------------- 1 | /* @flow */ 2 | 3 | export type CandidateType = { 4 | hash: string, 5 | name: string, 6 | index: number, 7 | votes: string, 8 | }; 9 | -------------------------------------------------------------------------------- /truffle.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | networks: { 3 | ropsten: { 4 | protocol: 'https', 5 | host: 'ropsten.infura.io', 6 | port: 8545, 7 | network_id: 3, 8 | }, 9 | }, 10 | }; 11 | --------------------------------------------------------------------------------