├── client
├── contracts.clevis
├── stop.sh
├── attach.sh
├── tests
│ ├── fast.js
│ ├── full.js
│ ├── metamask.js
│ ├── publish.js
│ ├── version.js
│ ├── compile.js
│ ├── deploy.js
│ └── clevis.js
├── public
│ ├── favicon.ico
│ ├── manifest.json
│ └── index.html
├── src
│ ├── assets
│ │ ├── clock.png
│ │ ├── cloud.png
│ │ ├── copy.png
│ │ ├── pen.png
│ │ ├── tent.png
│ │ ├── user.png
│ │ ├── castle.png
│ │ ├── details.png
│ │ ├── github.png
│ │ ├── market.png
│ │ ├── shield.png
│ │ ├── tablet.png
│ │ ├── twitter.png
│ │ ├── arrow-left.png
│ │ ├── question.png
│ │ ├── treasure.png
│ │ ├── arrow-right.png
│ │ ├── instructions.png
│ │ ├── chelsea-hello.png
│ │ ├── chisel-process.png
│ │ └── ethereum-small.png
│ ├── components
│ │ ├── assets
│ │ │ ├── eth.png
│ │ │ ├── erc20.png
│ │ │ ├── ethereum.png
│ │ │ └── metamask.png
│ │ ├── dapparatus.css
│ │ ├── Navigation.js
│ │ ├── scaler.js
│ │ ├── button.js
│ │ ├── ContractLoaderCustom.js
│ │ ├── DapparatusCustom.js
│ │ └── transactionsCustom.js
│ ├── index.js
│ ├── index.css
│ ├── App.test.js
│ ├── playground.js
│ ├── App.css
│ ├── ethereum
│ │ ├── web3.js
│ │ ├── sampleABIOpenTriviaFactory.json
│ │ ├── sampleABI1.json
│ │ ├── registry.json
│ │ ├── sampleABIOpenTriviaGame.json
│ │ ├── sampleABI3.json
│ │ ├── sampleABI2.json
│ │ ├── troubleshootingFunctions.json
│ │ └── troubleshootingviews.json
│ └── registerServiceWorker.js
├── readme-resources
│ ├── eth.png
│ ├── gas.png
│ ├── clamp.png
│ ├── mocha.png
│ ├── wallet.png
│ ├── ganache.png
│ ├── solidity.png
│ ├── ganache-cli.png
│ ├── clevis-explainer
│ ├── compile-deploy.png
│ └── title-graphic.png
├── run.sh
├── clevis.json
├── package.json
├── .gitignore
└── README.md
├── screengrab.png
├── readme-assets
├── dapp.png
├── create.png
├── details.png
├── security.png
├── chelsea-hello.png
├── chisel-process.png
└── instructions.png
├── start-client.js
├── db
└── mongoose.js
├── models
├── user.js
└── contract.js
├── .gitignore
├── playgroundserver.js
├── LICENSE
├── package.json
├── notes.md
├── README.md
└── server.js
/client/contracts.clevis:
--------------------------------------------------------------------------------
1 | splitter
2 |
--------------------------------------------------------------------------------
/client/stop.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | docker stop clevis
3 |
--------------------------------------------------------------------------------
/client/attach.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | docker exec -ti clevis bash
3 |
--------------------------------------------------------------------------------
/client/tests/fast.js:
--------------------------------------------------------------------------------
1 | const clevis = require("./clevis.js")
2 | clevis.fast()
3 |
--------------------------------------------------------------------------------
/client/tests/full.js:
--------------------------------------------------------------------------------
1 | const clevis = require("./clevis.js")
2 | clevis.full()
3 |
--------------------------------------------------------------------------------
/client/tests/metamask.js:
--------------------------------------------------------------------------------
1 | const clevis = require("./clevis.js")
2 | clevis.metamask()
3 |
--------------------------------------------------------------------------------
/client/tests/publish.js:
--------------------------------------------------------------------------------
1 | const clevis = require("./clevis.js")
2 | clevis.publish()
3 |
--------------------------------------------------------------------------------
/client/tests/version.js:
--------------------------------------------------------------------------------
1 | const clevis = require("./clevis.js")
2 | clevis.version()
3 |
--------------------------------------------------------------------------------
/screengrab.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/oneclickdapp/oneclickdapp-v1/HEAD/screengrab.png
--------------------------------------------------------------------------------
/readme-assets/dapp.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/oneclickdapp/oneclickdapp-v1/HEAD/readme-assets/dapp.png
--------------------------------------------------------------------------------
/readme-assets/create.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/oneclickdapp/oneclickdapp-v1/HEAD/readme-assets/create.png
--------------------------------------------------------------------------------
/client/public/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/oneclickdapp/oneclickdapp-v1/HEAD/client/public/favicon.ico
--------------------------------------------------------------------------------
/client/src/assets/clock.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/oneclickdapp/oneclickdapp-v1/HEAD/client/src/assets/clock.png
--------------------------------------------------------------------------------
/client/src/assets/cloud.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/oneclickdapp/oneclickdapp-v1/HEAD/client/src/assets/cloud.png
--------------------------------------------------------------------------------
/client/src/assets/copy.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/oneclickdapp/oneclickdapp-v1/HEAD/client/src/assets/copy.png
--------------------------------------------------------------------------------
/client/src/assets/pen.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/oneclickdapp/oneclickdapp-v1/HEAD/client/src/assets/pen.png
--------------------------------------------------------------------------------
/client/src/assets/tent.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/oneclickdapp/oneclickdapp-v1/HEAD/client/src/assets/tent.png
--------------------------------------------------------------------------------
/client/src/assets/user.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/oneclickdapp/oneclickdapp-v1/HEAD/client/src/assets/user.png
--------------------------------------------------------------------------------
/readme-assets/details.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/oneclickdapp/oneclickdapp-v1/HEAD/readme-assets/details.png
--------------------------------------------------------------------------------
/readme-assets/security.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/oneclickdapp/oneclickdapp-v1/HEAD/readme-assets/security.png
--------------------------------------------------------------------------------
/client/src/assets/castle.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/oneclickdapp/oneclickdapp-v1/HEAD/client/src/assets/castle.png
--------------------------------------------------------------------------------
/client/src/assets/details.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/oneclickdapp/oneclickdapp-v1/HEAD/client/src/assets/details.png
--------------------------------------------------------------------------------
/client/src/assets/github.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/oneclickdapp/oneclickdapp-v1/HEAD/client/src/assets/github.png
--------------------------------------------------------------------------------
/client/src/assets/market.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/oneclickdapp/oneclickdapp-v1/HEAD/client/src/assets/market.png
--------------------------------------------------------------------------------
/client/src/assets/shield.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/oneclickdapp/oneclickdapp-v1/HEAD/client/src/assets/shield.png
--------------------------------------------------------------------------------
/client/src/assets/tablet.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/oneclickdapp/oneclickdapp-v1/HEAD/client/src/assets/tablet.png
--------------------------------------------------------------------------------
/client/src/assets/twitter.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/oneclickdapp/oneclickdapp-v1/HEAD/client/src/assets/twitter.png
--------------------------------------------------------------------------------
/client/readme-resources/eth.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/oneclickdapp/oneclickdapp-v1/HEAD/client/readme-resources/eth.png
--------------------------------------------------------------------------------
/client/readme-resources/gas.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/oneclickdapp/oneclickdapp-v1/HEAD/client/readme-resources/gas.png
--------------------------------------------------------------------------------
/client/src/assets/arrow-left.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/oneclickdapp/oneclickdapp-v1/HEAD/client/src/assets/arrow-left.png
--------------------------------------------------------------------------------
/client/src/assets/question.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/oneclickdapp/oneclickdapp-v1/HEAD/client/src/assets/question.png
--------------------------------------------------------------------------------
/client/src/assets/treasure.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/oneclickdapp/oneclickdapp-v1/HEAD/client/src/assets/treasure.png
--------------------------------------------------------------------------------
/readme-assets/chelsea-hello.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/oneclickdapp/oneclickdapp-v1/HEAD/readme-assets/chelsea-hello.png
--------------------------------------------------------------------------------
/readme-assets/chisel-process.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/oneclickdapp/oneclickdapp-v1/HEAD/readme-assets/chisel-process.png
--------------------------------------------------------------------------------
/readme-assets/instructions.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/oneclickdapp/oneclickdapp-v1/HEAD/readme-assets/instructions.png
--------------------------------------------------------------------------------
/client/readme-resources/clamp.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/oneclickdapp/oneclickdapp-v1/HEAD/client/readme-resources/clamp.png
--------------------------------------------------------------------------------
/client/readme-resources/mocha.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/oneclickdapp/oneclickdapp-v1/HEAD/client/readme-resources/mocha.png
--------------------------------------------------------------------------------
/client/readme-resources/wallet.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/oneclickdapp/oneclickdapp-v1/HEAD/client/readme-resources/wallet.png
--------------------------------------------------------------------------------
/client/run.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | docker run -ti --rm --name clevis -p 3000:3000 -p 8545:8545 -v ${PWD}:/dapp austingriffith/clevis
3 |
--------------------------------------------------------------------------------
/client/src/assets/arrow-right.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/oneclickdapp/oneclickdapp-v1/HEAD/client/src/assets/arrow-right.png
--------------------------------------------------------------------------------
/client/src/assets/instructions.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/oneclickdapp/oneclickdapp-v1/HEAD/client/src/assets/instructions.png
--------------------------------------------------------------------------------
/client/readme-resources/ganache.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/oneclickdapp/oneclickdapp-v1/HEAD/client/readme-resources/ganache.png
--------------------------------------------------------------------------------
/client/readme-resources/solidity.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/oneclickdapp/oneclickdapp-v1/HEAD/client/readme-resources/solidity.png
--------------------------------------------------------------------------------
/client/src/assets/chelsea-hello.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/oneclickdapp/oneclickdapp-v1/HEAD/client/src/assets/chelsea-hello.png
--------------------------------------------------------------------------------
/client/src/assets/chisel-process.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/oneclickdapp/oneclickdapp-v1/HEAD/client/src/assets/chisel-process.png
--------------------------------------------------------------------------------
/client/src/assets/ethereum-small.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/oneclickdapp/oneclickdapp-v1/HEAD/client/src/assets/ethereum-small.png
--------------------------------------------------------------------------------
/client/src/components/assets/eth.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/oneclickdapp/oneclickdapp-v1/HEAD/client/src/components/assets/eth.png
--------------------------------------------------------------------------------
/client/readme-resources/ganache-cli.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/oneclickdapp/oneclickdapp-v1/HEAD/client/readme-resources/ganache-cli.png
--------------------------------------------------------------------------------
/client/src/components/assets/erc20.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/oneclickdapp/oneclickdapp-v1/HEAD/client/src/components/assets/erc20.png
--------------------------------------------------------------------------------
/client/readme-resources/clevis-explainer:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/oneclickdapp/oneclickdapp-v1/HEAD/client/readme-resources/clevis-explainer
--------------------------------------------------------------------------------
/client/readme-resources/compile-deploy.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/oneclickdapp/oneclickdapp-v1/HEAD/client/readme-resources/compile-deploy.png
--------------------------------------------------------------------------------
/client/readme-resources/title-graphic.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/oneclickdapp/oneclickdapp-v1/HEAD/client/readme-resources/title-graphic.png
--------------------------------------------------------------------------------
/client/src/components/assets/ethereum.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/oneclickdapp/oneclickdapp-v1/HEAD/client/src/components/assets/ethereum.png
--------------------------------------------------------------------------------
/client/src/components/assets/metamask.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/oneclickdapp/oneclickdapp-v1/HEAD/client/src/components/assets/metamask.png
--------------------------------------------------------------------------------
/client/tests/compile.js:
--------------------------------------------------------------------------------
1 | const clevis = require("./clevis.js")
2 | for(let c in clevis.contracts){
3 | clevis.compile(clevis.contracts[c])
4 | }
5 |
--------------------------------------------------------------------------------
/client/tests/deploy.js:
--------------------------------------------------------------------------------
1 | const clevis = require("./clevis.js")
2 | for(let c in clevis.contracts){
3 | clevis.deploy(clevis.contracts[c],0)
4 | }
5 |
--------------------------------------------------------------------------------
/start-client.js:
--------------------------------------------------------------------------------
1 | const args = ["start"];
2 | const opts = { stdio: "inherit", cwd: "client", shell: true };
3 | require("child_process").spawn("npm", args, opts);
4 |
--------------------------------------------------------------------------------
/client/src/index.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import ReactDOM from 'react-dom';
3 | import './index.css';
4 | import App from './App';
5 |
6 | ReactDOM.render(

Instantly build a dApp with a simple URL to bookmark or share with a friend.:zap::wrench::link: :shipit:
7 | 8 |
9 |
24 |
71 |
223 |
44 |
45 | ## Planned
46 |
47 | - Ganache forking to emulate any mainnet dApp
48 | - IPFS for saving dApps
49 | - Custom ENS domains e.g., "myDapp.oneclickdapp.ETH"
50 | - Full decentralization for permanence and security
51 | - "Copy the code" button to build your own React app
52 | - Display Events and Transactions using Dapparatus
53 |
54 | ## Run the app locally
55 |
56 | 1. Run `npm install` in both root directory, and in `/client`
57 | 2. Create `config.js` in `./db/` and enter your mongoDB URL
58 | > process.env.MONGODB_URI = "mongodb://..."
59 | 3. cd to root directory and run `npm start`
60 |
61 | ## Contributions welcome!
62 |
63 | This tool is primarily maintained by a single person. It is self-funded and free to use.
64 |
65 | Please consider helping by submitting an issue or PR.
66 |
67 | ## Check out my other free blockchain resources
68 |
69 | - [Walrus Paper Wallet Generator](https://github.com/blockchainbuddha/Walrus-Paper-Wallet-Generator)- Print hundreds of paper wallets quickly.
70 | - [Smart Contract Troubleshooter](https://github.com/blockchainbuddha/Solidity-Troubleshooting-Guide)- A quick checklist to prevent ripping out your hair.
71 | - [Patrick's blockchain resources](https://github.com/blockchainbuddha/Intro-to-Blockchain)- If I taught it, you can find it here.
72 |
73 | ## Contact
74 |
75 | [Patrick](https://twitter.com/pi0neerpat),
76 | [Joseph](https://twitter.com/cupojoseph)
77 |
--------------------------------------------------------------------------------
/client/src/registerServiceWorker.js:
--------------------------------------------------------------------------------
1 | // In production, we register a service worker to serve assets from local cache.
2 |
3 | // This lets the app load faster on subsequent visits in production, and gives
4 | // it offline capabilities. However, it also means that developers (and users)
5 | // will only see deployed updates on the "N+1" visit to a page, since previously
6 | // cached resources are updated in the background.
7 |
8 | // To learn more about the benefits of this model, read https://goo.gl/KwvDNy.
9 | // This link also includes instructions on opting out of this behavior.
10 |
11 | const isLocalhost = Boolean(
12 | window.location.hostname === 'localhost' ||
13 | // [::1] is the IPv6 localhost address.
14 | window.location.hostname === '[::1]' ||
15 | // 127.0.0.1/8 is considered localhost for IPv4.
16 | window.location.hostname.match(
17 | /^127(?:\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}$/
18 | )
19 | );
20 |
21 | export default function register() {
22 | if (process.env.NODE_ENV === 'production' && 'serviceWorker' in navigator) {
23 | // The URL constructor is available in all browsers that support SW.
24 | const publicUrl = new URL(process.env.PUBLIC_URL, window.location);
25 | if (publicUrl.origin !== window.location.origin) {
26 | // Our service worker won't work if PUBLIC_URL is on a different origin
27 | // from what our page is served on. This might happen if a CDN is used to
28 | // serve assets; see https://github.com/facebookincubator/create-react-app/issues/2374
29 | return;
30 | }
31 |
32 | window.addEventListener('load', () => {
33 | const swUrl = `${process.env.PUBLIC_URL}/service-worker.js`;
34 |
35 | if (isLocalhost) {
36 | // This is running on localhost. Lets check if a service worker still exists or not.
37 | checkValidServiceWorker(swUrl);
38 |
39 | // Add some additional logging to localhost, pointing developers to the
40 | // service worker/PWA documentation.
41 | navigator.serviceWorker.ready.then(() => {
42 | console.log(
43 | 'This web app is being served cache-first by a service ' +
44 | 'worker. To learn more, visit https://goo.gl/SC7cgQ'
45 | );
46 | });
47 | } else {
48 | // Is not local host. Just register service worker
49 | registerValidSW(swUrl);
50 | }
51 | });
52 | }
53 | }
54 |
55 | function registerValidSW(swUrl) {
56 | navigator.serviceWorker
57 | .register(swUrl)
58 | .then(registration => {
59 | registration.onupdatefound = () => {
60 | const installingWorker = registration.installing;
61 | installingWorker.onstatechange = () => {
62 | if (installingWorker.state === 'installed') {
63 | if (navigator.serviceWorker.controller) {
64 | // At this point, the old content will have been purged and
65 | // the fresh content will have been added to the cache.
66 | // It's the perfect time to display a "New content is
67 | // available; please refresh." message in your web app.
68 | console.log('New content is available; please refresh.');
69 | } else {
70 | // At this point, everything has been precached.
71 | // It's the perfect time to display a
72 | // "Content is cached for offline use." message.
73 | console.log('Content is cached for offline use.');
74 | }
75 | }
76 | };
77 | };
78 | })
79 | .catch(error => {
80 | console.error('Error during service worker registration:', error);
81 | });
82 | }
83 |
84 | function checkValidServiceWorker(swUrl) {
85 | // Check if the service worker can be found. If it can't reload the page.
86 | fetch(swUrl)
87 | .then(response => {
88 | // Ensure service worker exists, and that we really are getting a JS file.
89 | if (
90 | response.status === 404 ||
91 | response.headers.get('content-type').indexOf('javascript') === -1
92 | ) {
93 | // No service worker found. Probably a different app. Reload the page.
94 | navigator.serviceWorker.ready.then(registration => {
95 | registration.unregister().then(() => {
96 | window.location.reload();
97 | });
98 | });
99 | } else {
100 | // Service worker found. Proceed as normal.
101 | registerValidSW(swUrl);
102 | }
103 | })
104 | .catch(() => {
105 | console.log(
106 | 'No internet connection found. App is running in offline mode.'
107 | );
108 | });
109 | }
110 |
111 | export function unregister() {
112 | if ('serviceWorker' in navigator) {
113 | navigator.serviceWorker.ready.then(registration => {
114 | registration.unregister();
115 | });
116 | }
117 | }
118 |
--------------------------------------------------------------------------------
/client/src/ethereum/registry.json:
--------------------------------------------------------------------------------
1 | [
2 | {
3 | "constant": false,
4 | "inputs": [
5 | {
6 | "name": "_address",
7 | "type": "address"
8 | },
9 | {
10 | "name": "_name",
11 | "type": "string"
12 | },
13 | {
14 | "name": "_ipfs",
15 | "type": "string"
16 | }
17 | ],
18 | "name": "addAddress",
19 | "outputs": [
20 | {
21 | "name": "",
22 | "type": "string"
23 | }
24 | ],
25 | "payable": true,
26 | "stateMutability": "payable",
27 | "type": "function"
28 | },
29 | {
30 | "constant": true,
31 | "inputs": [
32 | {
33 | "name": "",
34 | "type": "address"
35 | }
36 | ],
37 | "name": "adresses",
38 | "outputs": [
39 | {
40 | "name": "_address",
41 | "type": "address"
42 | },
43 | {
44 | "name": "_name",
45 | "type": "string"
46 | },
47 | {
48 | "name": "_ipfs",
49 | "type": "string"
50 | },
51 | {
52 | "name": "_selfAttested",
53 | "type": "bool"
54 | },
55 | {
56 | "name": "_curated",
57 | "type": "bool"
58 | },
59 | {
60 | "name": "_exists",
61 | "type": "bool"
62 | },
63 | {
64 | "name": "_submitter",
65 | "type": "address"
66 | }
67 | ],
68 | "payable": false,
69 | "stateMutability": "view",
70 | "type": "function"
71 | },
72 | {
73 | "constant": true,
74 | "inputs": [
75 | {
76 | "name": "a",
77 | "type": "address"
78 | }
79 | ],
80 | "name": "getByAddress",
81 | "outputs": [
82 | {
83 | "name": "",
84 | "type": "address"
85 | },
86 | {
87 | "name": "",
88 | "type": "string"
89 | },
90 | {
91 | "name": "",
92 | "type": "string"
93 | },
94 | {
95 | "name": "",
96 | "type": "bool"
97 | },
98 | {
99 | "name": "",
100 | "type": "bool"
101 | },
102 | {
103 | "name": "",
104 | "type": "address"
105 | }
106 | ],
107 | "payable": false,
108 | "stateMutability": "view",
109 | "type": "function"
110 | },
111 | {
112 | "constant": true,
113 | "inputs": [
114 | {
115 | "name": "a",
116 | "type": "uint256"
117 | }
118 | ],
119 | "name": "getByIndex",
120 | "outputs": [
121 | {
122 | "name": "",
123 | "type": "address"
124 | },
125 | {
126 | "name": "",
127 | "type": "string"
128 | },
129 | {
130 | "name": "",
131 | "type": "string"
132 | },
133 | {
134 | "name": "",
135 | "type": "bool"
136 | },
137 | {
138 | "name": "",
139 | "type": "bool"
140 | },
141 | {
142 | "name": "",
143 | "type": "address"
144 | }
145 | ],
146 | "payable": false,
147 | "stateMutability": "view",
148 | "type": "function"
149 | },
150 | {
151 | "constant": true,
152 | "inputs": [
153 | {
154 | "name": "a",
155 | "type": "address"
156 | },
157 | {
158 | "name": "i",
159 | "type": "uint256"
160 | }
161 | ],
162 | "name": "getHistoricalVersion",
163 | "outputs": [
164 | {
165 | "name": "",
166 | "type": "address"
167 | },
168 | {
169 | "name": "",
170 | "type": "string"
171 | },
172 | {
173 | "name": "",
174 | "type": "string"
175 | },
176 | {
177 | "name": "",
178 | "type": "bool"
179 | },
180 | {
181 | "name": "",
182 | "type": "bool"
183 | },
184 | {
185 | "name": "",
186 | "type": "address"
187 | }
188 | ],
189 | "payable": false,
190 | "stateMutability": "view",
191 | "type": "function"
192 | },
193 | {
194 | "constant": true,
195 | "inputs": [],
196 | "name": "getIndex",
197 | "outputs": [
198 | {
199 | "name": "",
200 | "type": "uint256"
201 | }
202 | ],
203 | "payable": false,
204 | "stateMutability": "view",
205 | "type": "function"
206 | },
207 | {
208 | "constant": true,
209 | "inputs": [],
210 | "name": "getPrice",
211 | "outputs": [
212 | {
213 | "name": "",
214 | "type": "uint256"
215 | }
216 | ],
217 | "payable": false,
218 | "stateMutability": "view",
219 | "type": "function"
220 | },
221 | {
222 | "constant": true,
223 | "inputs": [
224 | {
225 | "name": "a",
226 | "type": "address"
227 | }
228 | ],
229 | "name": "getVersions",
230 | "outputs": [
231 | {
232 | "name": "v",
233 | "type": "uint256"
234 | }
235 | ],
236 | "payable": false,
237 | "stateMutability": "view",
238 | "type": "function"
239 | },
240 | {
241 | "constant": true,
242 | "inputs": [
243 | {
244 | "name": "a",
245 | "type": "address"
246 | }
247 | ],
248 | "name": "isCurator",
249 | "outputs": [
250 | {
251 | "name": "",
252 | "type": "bool"
253 | }
254 | ],
255 | "payable": false,
256 | "stateMutability": "view",
257 | "type": "function"
258 | },
259 | {
260 | "constant": true,
261 | "inputs": [
262 | {
263 | "name": "",
264 | "type": "address"
265 | },
266 | {
267 | "name": "",
268 | "type": "uint256"
269 | }
270 | ],
271 | "name": "versionHistory",
272 | "outputs": [
273 | {
274 | "name": "_address",
275 | "type": "address"
276 | },
277 | {
278 | "name": "_name",
279 | "type": "string"
280 | },
281 | {
282 | "name": "_ipfs",
283 | "type": "string"
284 | },
285 | {
286 | "name": "_selfAttested",
287 | "type": "bool"
288 | },
289 | {
290 | "name": "_curated",
291 | "type": "bool"
292 | },
293 | {
294 | "name": "_exists",
295 | "type": "bool"
296 | },
297 | {
298 | "name": "_submitter",
299 | "type": "address"
300 | }
301 | ],
302 | "payable": false,
303 | "stateMutability": "view",
304 | "type": "function"
305 | }
306 | ]
307 |
--------------------------------------------------------------------------------
/server.js:
--------------------------------------------------------------------------------
1 | const Registry = require('eth-registry');
2 | const Web3 = require('web3');
3 |
4 | // Dependencies
5 | const _ = require('lodash');
6 | const express = require('express');
7 | const fs = require('fs');
8 | // Database toolds
9 | const bodyParser = require('body-parser');
10 |
11 | require('./db/config'); // Database login secrets
12 | var { db } = require('./db/mongoose');
13 | var { Contract } = require('./models/contract');
14 | var { User } = require('./models/user');
15 |
16 | var mnGen = require('mngen'); // Random word generator
17 | // process.env.NODE_ENV === 'production'
18 | var app = express();
19 | app.set('port', process.env.PORT || 3001);
20 | // Express only serves static assets in production
21 | app.use(bodyParser.json());
22 |
23 | app.post('/contracts', (req, res) => {
24 | const contractName = req.body.contractName;
25 | const abi = req.body.abi;
26 | const contractAddress = req.body.contractAddress;
27 | const network = req.body.network;
28 | const creatorAddress = req.body.creatorAddress.toLowerCase();
29 | // Generate the mnemonic word for the URL
30 | const mnemonic = mnGen.word(2);
31 | const currentTime = Date.now();
32 |
33 | console.log(' ');
34 | console.log('################## POST #####################');
35 | console.log(
36 | `Name: ${contractName}, network: ${network}, address: ${contractAddress}`
37 | );
38 | console.log(`Creator address: ${creatorAddress}`);
39 | console.log(`Current time: ${currentTime}`);
40 | console.log(`URL: www.oneclickdapp.com/${mnemonic}`);
41 | var contract = new Contract({
42 | contractName: contractName,
43 | abi: abi,
44 | contractAddress: contractAddress,
45 | network: network,
46 | mnemonic: mnemonic,
47 | createdAt: currentTime,
48 | creatorAddress
49 | });
50 |
51 | User.findOneAndUpdate(
52 | { creatorAddress },
53 | { $push: { savedDapps: mnemonic } },
54 | {
55 | upsert: true,
56 | new: true
57 | },
58 | function() {
59 | console.log('User created/updated successfully!');
60 | }
61 | );
62 |
63 | contract.save().then(
64 | doc => {
65 | res.send(doc);
66 | },
67 | e => {
68 | res.status(400).send(e);
69 | }
70 | );
71 | });
72 |
73 | app.get('/contracts/recentContracts', (req, res) => {
74 | Contract.find()
75 | .sort({ _id: -1 })
76 | .limit(50)
77 | .then(contractArray => {
78 | recentContracts = new Array();
79 | contractArray.forEach(contract => {
80 | var contractData = {
81 | contractName: contract.contractName,
82 | network: contract.network,
83 | mnemonic: contract.mnemonic,
84 | createdAt: contract._id.getTimestamp(),
85 | creatorAddress: contract.creatorAddress
86 | };
87 | recentContracts.push(contractData);
88 | });
89 | res.send({
90 | recentContracts
91 | });
92 | })
93 | .catch(function(err) {
94 | res.status(400).send(`Recent contracts not found...`);
95 | console.log(err.err);
96 | });
97 | });
98 |
99 | app.get('/contracts/externalContracts', (req, res) => {
100 | console.log(' ');
101 | console.log('################## GET #####################');
102 | console.log(`Retrieving external contracts`);
103 | let externalContracts = [];
104 | const path = './externalContracts/myEtherWallet/src/contracts/eth';
105 | fs.readdirSync(path).forEach(file => {
106 | const contract = JSON.parse(fs.readFileSync(`${path}/${file}`, 'utf8'));
107 | contract.source = 'MEW Ethereum-lists';
108 | contract.title = contract.name;
109 | externalContracts.push(contract);
110 | });
111 | res.send({
112 | externalContracts
113 | });
114 | });
115 |
116 | app.get('/contracts/:mnemonic', (req, res) => {
117 | var mnemonic = req.params.mnemonic.toLowerCase();
118 | console.log(' ');
119 | console.log('################## GET #####################');
120 | console.log(`Retrieving contract for mnemonic: ${mnemonic}`);
121 |
122 | Contract.find({ mnemonic: mnemonic })
123 | .then(contractArray => {
124 | if (contractArray.length) {
125 | var myContract = contractArray[0];
126 | const contractName = myContract.contractName;
127 | const abi = myContract.abi;
128 | const contractAddress = myContract.contractAddress;
129 | const network = myContract.network;
130 | const createdAt = myContract._id.getTimestamp();
131 |
132 | const provider = new Web3.providers.HttpProvider(
133 | `https://mainnet.infura.io/`
134 | );
135 | const registry = new Registry(provider);
136 | let metaData = {};
137 | registry
138 | .get(contractAddress)
139 | .then(res => {
140 | metaData = res;
141 | res.send({
142 | contractName,
143 | abi,
144 | contractAddress,
145 | network,
146 | createdAt,
147 | metaData
148 | });
149 | })
150 | .catch(e => {
151 | console.error(e);
152 | res.send({
153 | contractName,
154 | abi,
155 | contractAddress,
156 | network,
157 | createdAt,
158 | metaData
159 | });
160 | });
161 | } else {
162 | res.status(400).send(`Contract not found: ${mnemonic}`);
163 | return;
164 | }
165 | })
166 | .catch(function(err) {
167 | res.status(400).send(`Contract not found: ${mnemonic}`);
168 | console.log(err.err);
169 | });
170 | });
171 |
172 | app.get('/user/:creatorAddress', (req, res) => {
173 | var creatorAddress = req.params.creatorAddress.toLowerCase();
174 | console.log(' ');
175 | console.log('################## GET #####################');
176 | console.log(`Retrieving contracts for user address: ${creatorAddress}`);
177 |
178 | User.findOne({ creatorAddress })
179 | .then(user => {
180 | mnemonics = user.savedDapps;
181 | if (mnemonics !== undefined && mnemonics.length > 0) {
182 | Contract.find({ mnemonic: { $in: mnemonics } })
183 | .sort({ _id: -1 })
184 | .then(dapps => {
185 | // createdAt: dapp._id.getTimestamp();
186 | res.send(dapps);
187 | });
188 | } else {
189 | res.status(400).send(`User not found: ${creatorAddress}`);
190 | }
191 | })
192 | .catch(function(err) {
193 | res.status(400).send(`User not found`);
194 | console.log(err.err);
195 | });
196 | });
197 |
198 | // Return the front-end for all other GET calls
199 | if (process.env.NODE_ENV === 'production') {
200 | app.set('port', 80);
201 | app.use(express.static('client/build'));
202 | app.use('*', express.static('client/build'));
203 | }
204 |
205 | app.listen(app.get('port'), () => {
206 | console.log(
207 | `_______________________________________________________________`
208 | );
209 | console.log(` `);
210 | console.log(`################# oneClickDApp API Server ####################`);
211 | console.log(` `);
212 | console.log(`Started on port ${app.get('port')}`);
213 | console.log(`______________________________________________________________`);
214 | console.log(` `);
215 | });
216 |
217 | //allows export app to server.test.js
218 | module.exports = { app };
219 |
--------------------------------------------------------------------------------
/client/src/ethereum/sampleABIOpenTriviaGame.json:
--------------------------------------------------------------------------------
1 | [
2 | {
3 | "constant": true,
4 | "inputs": [],
5 | "name": "entryFee",
6 | "outputs": [
7 | {
8 | "name": "",
9 | "type": "uint256"
10 | }
11 | ],
12 | "payable": false,
13 | "stateMutability": "view",
14 | "type": "function"
15 | },
16 | {
17 | "constant": true,
18 | "inputs": [],
19 | "name": "highScore",
20 | "outputs": [
21 | {
22 | "name": "",
23 | "type": "uint256"
24 | }
25 | ],
26 | "payable": false,
27 | "stateMutability": "view",
28 | "type": "function"
29 | },
30 | {
31 | "constant": true,
32 | "inputs": [],
33 | "name": "getSummary",
34 | "outputs": [
35 | {
36 | "name": "",
37 | "type": "address"
38 | },
39 | {
40 | "name": "",
41 | "type": "string"
42 | },
43 | {
44 | "name": "",
45 | "type": "uint256"
46 | },
47 | {
48 | "name": "",
49 | "type": "uint256"
50 | },
51 | {
52 | "name": "",
53 | "type": "uint256"
54 | },
55 | {
56 | "name": "",
57 | "type": "uint256"
58 | },
59 | {
60 | "name": "",
61 | "type": "bool"
62 | },
63 | {
64 | "name": "",
65 | "type": "bool"
66 | },
67 | {
68 | "name": "",
69 | "type": "uint256"
70 | },
71 | {
72 | "name": "",
73 | "type": "address[]"
74 | },
75 | {
76 | "name": "",
77 | "type": "uint256"
78 | },
79 | {
80 | "name": "",
81 | "type": "string"
82 | }
83 | ],
84 | "payable": false,
85 | "stateMutability": "view",
86 | "type": "function"
87 | },
88 | {
89 | "constant": true,
90 | "inputs": [],
91 | "name": "hasStarted",
92 | "outputs": [
93 | {
94 | "name": "",
95 | "type": "bool"
96 | }
97 | ],
98 | "payable": false,
99 | "stateMutability": "view",
100 | "type": "function"
101 | },
102 | {
103 | "constant": true,
104 | "inputs": [],
105 | "name": "manager",
106 | "outputs": [
107 | {
108 | "name": "",
109 | "type": "address"
110 | }
111 | ],
112 | "payable": false,
113 | "stateMutability": "view",
114 | "type": "function"
115 | },
116 | {
117 | "constant": false,
118 | "inputs": [],
119 | "name": "withdrawPrize",
120 | "outputs": [],
121 | "payable": false,
122 | "stateMutability": "nonpayable",
123 | "type": "function"
124 | },
125 | {
126 | "constant": false,
127 | "inputs": [
128 | {
129 | "name": "thesis",
130 | "type": "string"
131 | }
132 | ],
133 | "name": "guess",
134 | "outputs": [],
135 | "payable": false,
136 | "stateMutability": "nonpayable",
137 | "type": "function"
138 | },
139 | {
140 | "constant": false,
141 | "inputs": [],
142 | "name": "startRound",
143 | "outputs": [],
144 | "payable": false,
145 | "stateMutability": "nonpayable",
146 | "type": "function"
147 | },
148 | {
149 | "constant": true,
150 | "inputs": [
151 | {
152 | "name": "player",
153 | "type": "address"
154 | }
155 | ],
156 | "name": "getPlayer",
157 | "outputs": [
158 | {
159 | "name": "",
160 | "type": "string"
161 | },
162 | {
163 | "name": "",
164 | "type": "bool"
165 | },
166 | {
167 | "name": "",
168 | "type": "uint8"
169 | },
170 | {
171 | "name": "",
172 | "type": "uint256"
173 | },
174 | {
175 | "name": "",
176 | "type": "uint256"
177 | }
178 | ],
179 | "payable": false,
180 | "stateMutability": "view",
181 | "type": "function"
182 | },
183 | {
184 | "constant": false,
185 | "inputs": [],
186 | "name": "endGame",
187 | "outputs": [],
188 | "payable": false,
189 | "stateMutability": "nonpayable",
190 | "type": "function"
191 | },
192 | {
193 | "constant": true,
194 | "inputs": [],
195 | "name": "description",
196 | "outputs": [
197 | {
198 | "name": "",
199 | "type": "string"
200 | }
201 | ],
202 | "payable": false,
203 | "stateMutability": "view",
204 | "type": "function"
205 | },
206 | {
207 | "constant": false,
208 | "inputs": [],
209 | "name": "endRound",
210 | "outputs": [],
211 | "payable": false,
212 | "stateMutability": "nonpayable",
213 | "type": "function"
214 | },
215 | {
216 | "constant": true,
217 | "inputs": [],
218 | "name": "currentRound",
219 | "outputs": [
220 | {
221 | "name": "",
222 | "type": "uint256"
223 | }
224 | ],
225 | "payable": false,
226 | "stateMutability": "view",
227 | "type": "function"
228 | },
229 | {
230 | "constant": true,
231 | "inputs": [
232 | {
233 | "name": "",
234 | "type": "uint256"
235 | }
236 | ],
237 | "name": "rounds",
238 | "outputs": [
239 | {
240 | "name": "question",
241 | "type": "string"
242 | },
243 | {
244 | "name": "answer",
245 | "type": "string"
246 | },
247 | {
248 | "name": "started",
249 | "type": "bool"
250 | },
251 | {
252 | "name": "complete",
253 | "type": "bool"
254 | }
255 | ],
256 | "payable": false,
257 | "stateMutability": "view",
258 | "type": "function"
259 | },
260 | {
261 | "constant": true,
262 | "inputs": [],
263 | "name": "numPlayers",
264 | "outputs": [
265 | {
266 | "name": "",
267 | "type": "uint256"
268 | }
269 | ],
270 | "payable": false,
271 | "stateMutability": "view",
272 | "type": "function"
273 | },
274 | {
275 | "constant": true,
276 | "inputs": [],
277 | "name": "numRounds",
278 | "outputs": [
279 | {
280 | "name": "",
281 | "type": "uint256"
282 | }
283 | ],
284 | "payable": false,
285 | "stateMutability": "view",
286 | "type": "function"
287 | },
288 | {
289 | "constant": true,
290 | "inputs": [
291 | {
292 | "name": "",
293 | "type": "uint256"
294 | }
295 | ],
296 | "name": "winners",
297 | "outputs": [
298 | {
299 | "name": "",
300 | "type": "address"
301 | }
302 | ],
303 | "payable": false,
304 | "stateMutability": "view",
305 | "type": "function"
306 | },
307 | {
308 | "constant": false,
309 | "inputs": [],
310 | "name": "reset",
311 | "outputs": [],
312 | "payable": false,
313 | "stateMutability": "nonpayable",
314 | "type": "function"
315 | },
316 | {
317 | "constant": true,
318 | "inputs": [
319 | {
320 | "name": "",
321 | "type": "address"
322 | }
323 | ],
324 | "name": "players",
325 | "outputs": [
326 | {
327 | "name": "name",
328 | "type": "string"
329 | },
330 | {
331 | "name": "isRegistered",
332 | "type": "bool"
333 | },
334 | {
335 | "name": "score",
336 | "type": "uint8"
337 | },
338 | {
339 | "name": "winnings",
340 | "type": "uint256"
341 | },
342 | {
343 | "name": "guessedThisRound",
344 | "type": "uint256"
345 | }
346 | ],
347 | "payable": false,
348 | "stateMutability": "view",
349 | "type": "function"
350 | },
351 | {
352 | "constant": true,
353 | "inputs": [],
354 | "name": "currentQuestion",
355 | "outputs": [
356 | {
357 | "name": "",
358 | "type": "string"
359 | }
360 | ],
361 | "payable": false,
362 | "stateMutability": "view",
363 | "type": "function"
364 | },
365 | {
366 | "constant": true,
367 | "inputs": [],
368 | "name": "hasEnded",
369 | "outputs": [
370 | {
371 | "name": "",
372 | "type": "bool"
373 | }
374 | ],
375 | "payable": false,
376 | "stateMutability": "view",
377 | "type": "function"
378 | },
379 | {
380 | "constant": false,
381 | "inputs": [
382 | {
383 | "name": "name",
384 | "type": "string"
385 | }
386 | ],
387 | "name": "register",
388 | "outputs": [],
389 | "payable": true,
390 | "stateMutability": "payable",
391 | "type": "function"
392 | },
393 | {
394 | "inputs": [
395 | {
396 | "name": "creator",
397 | "type": "address"
398 | },
399 | {
400 | "name": "fee",
401 | "type": "uint256"
402 | },
403 | {
404 | "name": "info",
405 | "type": "string"
406 | },
407 | {
408 | "name": "questions",
409 | "type": "string"
410 | },
411 | {
412 | "name": "answers",
413 | "type": "string"
414 | }
415 | ],
416 | "payable": false,
417 | "stateMutability": "nonpayable",
418 | "type": "constructor"
419 | }
420 | ]
421 |
--------------------------------------------------------------------------------
/client/src/ethereum/sampleABI3.json:
--------------------------------------------------------------------------------
1 | [
2 | {
3 | "constant": true,
4 | "inputs": [],
5 | "name": "name",
6 | "outputs": [{ "name": "", "type": "string" }],
7 | "payable": false,
8 | "type": "function"
9 | },
10 | {
11 | "constant": true,
12 | "inputs": [{ "name": "", "type": "uint256" }],
13 | "name": "punksOfferedForSale",
14 | "outputs": [
15 | { "name": "isForSale", "type": "bool" },
16 | { "name": "punkIndex", "type": "uint256" },
17 | { "name": "seller", "type": "address" },
18 | { "name": "minValue", "type": "uint256" },
19 | { "name": "onlySellTo", "type": "address" }
20 | ],
21 | "payable": false,
22 | "type": "function"
23 | },
24 | {
25 | "constant": false,
26 | "inputs": [{ "name": "punkIndex", "type": "uint256" }],
27 | "name": "enterBidForPunk",
28 | "outputs": [],
29 | "payable": true,
30 | "type": "function"
31 | },
32 | {
33 | "constant": true,
34 | "inputs": [],
35 | "name": "totalSupply",
36 | "outputs": [{ "name": "", "type": "uint256" }],
37 | "payable": false,
38 | "type": "function"
39 | },
40 | {
41 | "constant": false,
42 | "inputs": [
43 | { "name": "punkIndex", "type": "uint256" },
44 | { "name": "minPrice", "type": "uint256" }
45 | ],
46 | "name": "acceptBidForPunk",
47 | "outputs": [],
48 | "payable": false,
49 | "type": "function"
50 | },
51 | {
52 | "constant": true,
53 | "inputs": [],
54 | "name": "decimals",
55 | "outputs": [{ "name": "", "type": "uint8" }],
56 | "payable": false,
57 | "type": "function"
58 | },
59 | {
60 | "constant": false,
61 | "inputs": [
62 | { "name": "addresses", "type": "address[]" },
63 | { "name": "indices", "type": "uint256[]" }
64 | ],
65 | "name": "setInitialOwners",
66 | "outputs": [],
67 | "payable": false,
68 | "type": "function"
69 | },
70 | {
71 | "constant": false,
72 | "inputs": [],
73 | "name": "withdraw",
74 | "outputs": [],
75 | "payable": false,
76 | "type": "function"
77 | },
78 | {
79 | "constant": true,
80 | "inputs": [],
81 | "name": "imageHash",
82 | "outputs": [{ "name": "", "type": "string" }],
83 | "payable": false,
84 | "type": "function"
85 | },
86 | {
87 | "constant": true,
88 | "inputs": [],
89 | "name": "nextPunkIndexToAssign",
90 | "outputs": [{ "name": "", "type": "uint256" }],
91 | "payable": false,
92 | "type": "function"
93 | },
94 | {
95 | "constant": true,
96 | "inputs": [{ "name": "", "type": "uint256" }],
97 | "name": "punkIndexToAddress",
98 | "outputs": [{ "name": "", "type": "address" }],
99 | "payable": false,
100 | "type": "function"
101 | },
102 | {
103 | "constant": true,
104 | "inputs": [],
105 | "name": "standard",
106 | "outputs": [{ "name": "", "type": "string" }],
107 | "payable": false,
108 | "type": "function"
109 | },
110 | {
111 | "constant": true,
112 | "inputs": [{ "name": "", "type": "uint256" }],
113 | "name": "punkBids",
114 | "outputs": [
115 | { "name": "hasBid", "type": "bool" },
116 | { "name": "punkIndex", "type": "uint256" },
117 | { "name": "bidder", "type": "address" },
118 | { "name": "value", "type": "uint256" }
119 | ],
120 | "payable": false,
121 | "type": "function"
122 | },
123 | {
124 | "constant": true,
125 | "inputs": [{ "name": "", "type": "address" }],
126 | "name": "balanceOf",
127 | "outputs": [{ "name": "", "type": "uint256" }],
128 | "payable": false,
129 | "type": "function"
130 | },
131 | {
132 | "constant": false,
133 | "inputs": [],
134 | "name": "allInitialOwnersAssigned",
135 | "outputs": [],
136 | "payable": false,
137 | "type": "function"
138 | },
139 | {
140 | "constant": true,
141 | "inputs": [],
142 | "name": "allPunksAssigned",
143 | "outputs": [{ "name": "", "type": "bool" }],
144 | "payable": false,
145 | "type": "function"
146 | },
147 | {
148 | "constant": false,
149 | "inputs": [{ "name": "punkIndex", "type": "uint256" }],
150 | "name": "buyPunk",
151 | "outputs": [],
152 | "payable": true,
153 | "type": "function"
154 | },
155 | {
156 | "constant": false,
157 | "inputs": [
158 | { "name": "to", "type": "address" },
159 | { "name": "punkIndex", "type": "uint256" }
160 | ],
161 | "name": "transferPunk",
162 | "outputs": [],
163 | "payable": false,
164 | "type": "function"
165 | },
166 | {
167 | "constant": true,
168 | "inputs": [],
169 | "name": "symbol",
170 | "outputs": [{ "name": "", "type": "string" }],
171 | "payable": false,
172 | "type": "function"
173 | },
174 | {
175 | "constant": false,
176 | "inputs": [{ "name": "punkIndex", "type": "uint256" }],
177 | "name": "withdrawBidForPunk",
178 | "outputs": [],
179 | "payable": false,
180 | "type": "function"
181 | },
182 | {
183 | "constant": false,
184 | "inputs": [
185 | { "name": "to", "type": "address" },
186 | { "name": "punkIndex", "type": "uint256" }
187 | ],
188 | "name": "setInitialOwner",
189 | "outputs": [],
190 | "payable": false,
191 | "type": "function"
192 | },
193 | {
194 | "constant": false,
195 | "inputs": [
196 | { "name": "punkIndex", "type": "uint256" },
197 | { "name": "minSalePriceInWei", "type": "uint256" },
198 | { "name": "toAddress", "type": "address" }
199 | ],
200 | "name": "offerPunkForSaleToAddress",
201 | "outputs": [],
202 | "payable": false,
203 | "type": "function"
204 | },
205 | {
206 | "constant": true,
207 | "inputs": [],
208 | "name": "punksRemainingToAssign",
209 | "outputs": [{ "name": "", "type": "uint256" }],
210 | "payable": false,
211 | "type": "function"
212 | },
213 | {
214 | "constant": false,
215 | "inputs": [
216 | { "name": "punkIndex", "type": "uint256" },
217 | { "name": "minSalePriceInWei", "type": "uint256" }
218 | ],
219 | "name": "offerPunkForSale",
220 | "outputs": [],
221 | "payable": false,
222 | "type": "function"
223 | },
224 | {
225 | "constant": false,
226 | "inputs": [{ "name": "punkIndex", "type": "uint256" }],
227 | "name": "getPunk",
228 | "outputs": [],
229 | "payable": false,
230 | "type": "function"
231 | },
232 | {
233 | "constant": true,
234 | "inputs": [{ "name": "", "type": "address" }],
235 | "name": "pendingWithdrawals",
236 | "outputs": [{ "name": "", "type": "uint256" }],
237 | "payable": false,
238 | "type": "function"
239 | },
240 | {
241 | "constant": false,
242 | "inputs": [{ "name": "punkIndex", "type": "uint256" }],
243 | "name": "punkNoLongerForSale",
244 | "outputs": [],
245 | "payable": false,
246 | "type": "function"
247 | },
248 | { "inputs": [], "payable": true, "type": "constructor" },
249 | {
250 | "anonymous": false,
251 | "inputs": [
252 | { "indexed": true, "name": "to", "type": "address" },
253 | { "indexed": false, "name": "punkIndex", "type": "uint256" }
254 | ],
255 | "name": "Assign",
256 | "type": "event"
257 | },
258 | {
259 | "anonymous": false,
260 | "inputs": [
261 | { "indexed": true, "name": "from", "type": "address" },
262 | { "indexed": true, "name": "to", "type": "address" },
263 | { "indexed": false, "name": "value", "type": "uint256" }
264 | ],
265 | "name": "Transfer",
266 | "type": "event"
267 | },
268 | {
269 | "anonymous": false,
270 | "inputs": [
271 | { "indexed": true, "name": "from", "type": "address" },
272 | { "indexed": true, "name": "to", "type": "address" },
273 | { "indexed": false, "name": "punkIndex", "type": "uint256" }
274 | ],
275 | "name": "PunkTransfer",
276 | "type": "event"
277 | },
278 | {
279 | "anonymous": false,
280 | "inputs": [
281 | { "indexed": true, "name": "punkIndex", "type": "uint256" },
282 | { "indexed": false, "name": "minValue", "type": "uint256" },
283 | { "indexed": true, "name": "toAddress", "type": "address" }
284 | ],
285 | "name": "PunkOffered",
286 | "type": "event"
287 | },
288 | {
289 | "anonymous": false,
290 | "inputs": [
291 | { "indexed": true, "name": "punkIndex", "type": "uint256" },
292 | { "indexed": false, "name": "value", "type": "uint256" },
293 | { "indexed": true, "name": "fromAddress", "type": "address" }
294 | ],
295 | "name": "PunkBidEntered",
296 | "type": "event"
297 | },
298 | {
299 | "anonymous": false,
300 | "inputs": [
301 | { "indexed": true, "name": "punkIndex", "type": "uint256" },
302 | { "indexed": false, "name": "value", "type": "uint256" },
303 | { "indexed": true, "name": "fromAddress", "type": "address" }
304 | ],
305 | "name": "PunkBidWithdrawn",
306 | "type": "event"
307 | },
308 | {
309 | "anonymous": false,
310 | "inputs": [
311 | { "indexed": true, "name": "punkIndex", "type": "uint256" },
312 | { "indexed": false, "name": "value", "type": "uint256" },
313 | { "indexed": true, "name": "fromAddress", "type": "address" },
314 | { "indexed": true, "name": "toAddress", "type": "address" }
315 | ],
316 | "name": "PunkBought",
317 | "type": "event"
318 | },
319 | {
320 | "anonymous": false,
321 | "inputs": [{ "indexed": true, "name": "punkIndex", "type": "uint256" }],
322 | "name": "PunkNoLongerForSale",
323 | "type": "event"
324 | }
325 | ]
326 |
--------------------------------------------------------------------------------
/client/tests/clevis.js:
--------------------------------------------------------------------------------
1 | const clevis = require("clevis")
2 | const colors = require('colors')
3 | const chai = require("chai")
4 | const HDWalletProvider = require("truffle-hdwallet-provider")
5 | const assert = chai.assert
6 | const expect = chai.expect;
7 | const should = chai.should();
8 |
9 | const fs = require('fs')
10 | const Web3 = require('web3')
11 | const clevisConfig = JSON.parse(fs.readFileSync("clevis.json").toString().trim())
12 | const web3 = new Web3(
13 | clevisConfig.USE_INFURA ?
14 | new HDWalletProvider(
15 | process.env.mnemonic,
16 | clevisConfig.provider) :
17 | new Web3.providers.HttpProvider(clevisConfig.provider)
18 | );
19 |
20 | //console.log('clevisConfig.provider', clevisConfig.provider);
21 |
22 | function localContractAddress(contract){
23 | return fs.readFileSync(clevisConfig.CONTRACTS_FOLDER+"/"+contract+ "/" + contract + ".address").toString().trim()
24 | }
25 | function localContractAbi(contract){
26 | return JSON.parse(fs.readFileSync(clevisConfig.CONTRACTS_FOLDER+"/"+contract+ "/"+ contract +".abi").toString().trim())
27 | }
28 | function printTxResult(result){
29 | if(!result||!result.transactionHash){
30 | console.log("ERROR".red,"MISSING TX HASH".yellow)
31 | }else{
32 | console.log(tab,result.transactionHash.gray,(""+result.gasUsed).yellow)
33 | }
34 | }
35 | function bigHeader(str){
36 | return "########### "+str+" "+Array(128-str.length).join("#")
37 | }
38 | function rand(min, max) {
39 | return Math.floor( Math.random() * (max - min) + min );
40 | }
41 | function getPaddedHexFromNumber(num,digits){
42 | let hexIs = web3.utils.numberToHex(num).replace("0x","");
43 | while(hexIs.length
2 |
**️Clevis** project:
5 |
6 | _Target audience:_ You've written and deployed several smart contracts using [Remix](remix.ethereum.org). Now you need a robust development environment with automated testing tools, and an easy-to-use command line interface.
7 |
8 | ## Install
Clevis
9 |
10 | 0. Requirements: Install npm and node.js (see https://docs.npmjs.com/getting-started/installing-node).
11 |
12 | 1. Download and create a binary of Clevis
13 |
14 | ```
15 | git clone https://github.com/austintgriffith/clevis
16 | cd clevis
17 | npm install
18 | sudo npm link
19 | ```
20 |
21 | 2. Navigate to a new project folder, then
22 |
23 | ```
24 | npm link clevis
25 | clevis init
26 | ```
27 |
28 | (You may have to enter root password during this process.)
29 |
30 | 3. Check your web3 version, and be sure you are using the correct documentation for web3 ([learn more](https://github.com/blockchainbuddha/Intro-to-Blockchain#using-web3))
31 |
32 | ```
33 | clevis version
34 | ```
35 |
36 | 4. Test out a command.
37 |
38 | ```
39 | clevis sha3 "Hello World"
40 | >> SHA3
41 | >> 0x592fa743889fc7f92ac2a37bb1f5ba1daf2a5c84741ca0e0061d243a2e6707ba
42 | ```
43 |
44 | Great job!
45 |
46 | ## Set up a local
Ethereum network
47 |
48 | 5. Instead of developing on the main Ethereum network, or a test-network, we will install Ganache-CLI
to run a local instance, as well as a JavaScript test framework tool called mocha
.
49 |
50 | ```JavaScript
51 | npm install -g ganache-cli mocha
52 | ```
53 |
54 | > Ganache allows us to process transactions :zap: instantly! Pretty sweet right?
55 |
56 | 6. In a **new terminal**
57 |
58 | ```
59 | ganache-cli
60 | >> ... // (lots of stuff here)
61 | >> Listening on 127.0.0.1:8545
62 | ```
63 |
64 | This starts a local instance of the Ethereum Virtual Machine (EVM). Ganache-CLI also creates a new
wallet with multiple ethereum "accounts" (0xab23f...) and each are funded with 100 ETH. If you get stuck using Ganache-CLI [read the docs](https://github.com/trufflesuite/ganache-cli/blob/master/README.md).
65 |
66 | > _Go forth and make mistakes_! Ganache-CLI is merely an instanceof the EVM, and is _only running on your machine_.
67 |
68 | Here's how our set-up looks so far.
69 |
70 |
72 |
wallet accounts.
74 |
75 | ```javascript
76 | clevis accounts
77 | >> Reading Accounts...
78 | >> ['0xf2A0DD5999c23f53fE8819CBbc06d2e2B05b9093',
79 | >> '0x25a62dE56EF4fe5882336b05AbF202d1375272dD',
80 | >> '0x367347648F02A6c6e0f5126185652332e91f2d00',
81 | >> '0x5aB26450D93Bd70c66CD575e47B4c72E91df876B',...
82 | ```
83 |
84 | Now make a transaction by sending `0.2 ETH` from account 0 to account 1. The proper syntax is
85 |
86 | #### clevis send [amount][fromindex] [toindex]
87 |
88 | ```javascript
89 | clevis send 0.2 0 1
90 | ```
91 |
92 | This is a good spot to try out some other commands. See the full list with
93 |
94 | ```javascript
95 | clevis help
96 | ```
97 |
98 | Excellent work so far!
99 |
100 | ## Ceate your
Solidity contract
101 |
102 | > Note: these are usually referred to as "Smart Contracts." However they are neither smart, nor a contract. Can you think of a better term?
103 |
104 | 8. Create a new contract
105 |
106 | ```javascript
107 | clevis create Name
108 | ```
109 |
110 | Lets take a look at our project directory now
111 |
112 | ```java
113 | myproject
114 | │ accounts.json // Wallet accounts from Ganache-CLI (clevis accounts)
115 | │ clevis.json // Config. for network, gas price etc.
116 | │ contracts.clevis // Tracks contracts
117 | │ ...
118 | │
119 | └───contracts
120 | │ └───Name // Each contract has a folder
121 | │ │ arguments.js // Constructor arguments when deploying
122 | │ │ dependencies.js // Imports other contracts
123 | │ │ Name.sol
124 | │
125 | └───openzeppelin-solidity // Commonly used contracts
126 | └───src // Our application lives here
127 | └───tests // Useful test scripts
128 | ```
129 |
130 | 9. Paste in the example code:
131 |
132 | ```solidity
133 | pragma solidity ^0.4.24;
134 |
135 | import 'openzeppelin-solidity/contracts/ownership/Ownable.sol';
136 |
137 | contract Name is Ownable{
138 | string public name;
139 |
140 | constructor(string _name) public {
141 | name = _name;
142 | }
143 |
144 | function setName(string _name) onlyOwner public returns (bool){
145 | name = _name;
146 | return true;
147 | }
148 | }
149 | ```
150 |
151 | 10. Since we are importing a contract from the OpenZeppelin-Solidity, we must modify `dependencies.js` so the compiler will know where to look:
152 |
153 | ```js
154 | const fs = require('fs');
155 | module.exports = {
156 | 'openzeppelin-solidity/contracts/ownership/Ownable.sol': fs.readFileSync(
157 | 'openzeppelin-solidity/contracts/ownership/Ownable.sol',
158 | 'utf8'
159 | )
160 | };
161 | ```
162 |
163 | Our contract requires one argument when it's deployed. This is provided in `arguments.js`
164 |
165 | ```js
166 | module.exports = ['Hello world'];
167 | ```
168 |
169 | 11. Compile
170 |
171 | ```js
172 | clevis compile Name
173 | ```
174 |
175 | We now have some some new files in the contract folder
176 |
177 | ```java
178 | myproject
179 | └───contracts
180 | │ └───Name
181 | │ │ Name.sol
182 | │ │ ...
183 | | │ Name.abi // Application binary interface
184 | │ │ Name.bytecode // Bytecode for submitting to Ganache-CLI
185 | │ │ Name.compiled // Compiled contract + imported contracts
186 | │ │
187 | │ └───.clevis // Auto-generated test commands
188 | │ | eventOwnershipRenounced.js
189 | │ | setName.js
190 | │ | transferOwnership.js
191 | │ | ...
192 | │ ...
193 | ```
194 |
195 | ## Deploy your contract to
Ganache-CLI
196 |
197 | 12. Deploy from account 0 using this syntax
198 |
199 | #### clevis deploy [contractname][accountindex]
200 |
201 | ```js
202 | clevis deploy Name 0
203 | ```
204 |
205 | Notice even more new files in our contract folder.
206 |
207 | ```java
208 | myproject
209 | └───contracts
210 | │ └───Name
211 | │ │ Name.sol
212 | │ │ ...
213 | │ │ Name.address // Contract address on the Ganache-CLI network
214 | │ │ Name.blockNumber // Block number where contract was deployed
215 | │ │ Name.head.address // ???
216 | │ │ ...
217 | │ ...
218 | ```
219 |
220 | Let's review what just happened. During compilation, Clevis compiled our contract and arguments into bytecode, which is ready to be submitted to our Ganache-CLI blockchain. We also generated the contract Abi (Application binary interface) and some useful test scripts in the `.clevis` folder, whcih will allow us to communicate with our deployed contract.
221 |
222 |
224 |
gas transaction fee, so we didn't need to specify an account.
237 | Here is the code that Clevis just ran for us:
238 |
239 | ```javascript
240 | // Load dependencies for talking to Ganache-CLI using Web3
241 | const ganache = require("ganache-cli");
242 | const Web3 = require("web3");
243 | // Get information about our deployed contract
244 | const contractInterface = require("./contracts/Name/Name.abi");
245 | const contractAddress = require("./contracts/Name/Name.compiled");
246 | // Instantiate web3 object
247 | const web3 = new Web3(ganache.provider({ port: "127.0.0.1:8545" }));
248 | // Instantiate contract object at the correct address
249 | const name = await new web3.eth.Contract(contractInterface, contractAddress);
250 | // Finally, query our deployed Name contract using ".call()"
251 | const response = await contract.methods.name().call();
252 | console.log(response);
253 | ```
254 |
255 | Good thing you didn't need to write that!
256 |
257 | 14. Now lets make a transaction that Δ changes the state of the contact, which will require a
gas transaction fee. We will need to specify an account in our
wallet. Let's use the `setName` function by calling the appropriate Clevis test script.
258 |
259 | ```javascript
260 | clevis contract setName Name 0 "My new name"
261 | >>
262 | >> transactionHash:0x656600d6db9aa7fb814662c41657abe43074dc05b7bbb66edec5a6736c4e49b1
263 | >> { transactionHash: '0x656600d6db9aa7fb814662c41657abe43074dc05b7bbb66edec5a6736c4e49b1',
264 | >> transactionIndex: 0,
265 | >> blockHash: '0xa2918570f31743aaba0fd097dc0bed1fef0a311ee0d59a1d006b6578d5a27fb9',
266 | >> blockNumber: 7,
267 | >> gasUsed: 34010,
268 | >> cumulativeGasUsed: 34010,
269 | >> contractAddress: null,
270 | >> logs: [],
271 | >> status: true,
272 | >> ...
273 | ```
274 |
275 | If you're successful, you'll see a transaction hash (think of as a receipt), and `status: true`.
276 | Clevis just ran all the code from the previous step, except instead of `contract.methods.name().call()`, it ran the following.
277 |
278 | ```javascript
279 | const accounts = await web3.eth.getAccounts();
280 | await name.methods.setName("My new name").send({
281 | from: accounts[0],
282 | gas: 1300000
283 | });
284 | ```
285 |
286 | Remember that ".call()" functions do not require gas, and simply read the current state. However ".send()" functions modify the state of the contract, therefore we must specify an account to pay the
gas transaction fee.
287 |
288 | #### Congratulations! we now know how to create a new contract using Clevis, and how to read and write using the `clevis contract` commands. Next up is building out the front-end.
289 |
290 | ## Front-end Coming soon!
291 |
--------------------------------------------------------------------------------
/client/src/ethereum/sampleABI2.json:
--------------------------------------------------------------------------------
1 | [{"constant":true,"inputs":[{"name":"_interfaceID","type":"bytes4"}],"name":"supportsInterface","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"cfoAddress","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"_tokenId","type":"uint256"},{"name":"_preferredTransport","type":"string"}],"name":"tokenMetadata","outputs":[{"name":"infoUrl","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"promoCreatedCount","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"name","outputs":[{"name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_to","type":"address"},{"name":"_tokenId","type":"uint256"}],"name":"approve","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"ceoAddress","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"GEN0_STARTING_PRICE","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_address","type":"address"}],"name":"setSiringAuctionAddress","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"totalSupply","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"pregnantKitties","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"_kittyId","type":"uint256"}],"name":"isPregnant","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"GEN0_AUCTION_DURATION","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"siringAuction","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_from","type":"address"},{"name":"_to","type":"address"},{"name":"_tokenId","type":"uint256"}],"name":"transferFrom","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_address","type":"address"}],"name":"setGeneScienceAddress","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_newCEO","type":"address"}],"name":"setCEO","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_newCOO","type":"address"}],"name":"setCOO","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_kittyId","type":"uint256"},{"name":"_startingPrice","type":"uint256"},{"name":"_endingPrice","type":"uint256"},{"name":"_duration","type":"uint256"}],"name":"createSaleAuction","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[],"name":"unpause","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"","type":"uint256"}],"name":"sireAllowedToAddress","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"_matronId","type":"uint256"},{"name":"_sireId","type":"uint256"}],"name":"canBreedWith","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"","type":"uint256"}],"name":"kittyIndexToApproved","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_kittyId","type":"uint256"},{"name":"_startingPrice","type":"uint256"},{"name":"_endingPrice","type":"uint256"},{"name":"_duration","type":"uint256"}],"name":"createSiringAuction","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"val","type":"uint256"}],"name":"setAutoBirthFee","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_addr","type":"address"},{"name":"_sireId","type":"uint256"}],"name":"approveSiring","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_newCFO","type":"address"}],"name":"setCFO","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_genes","type":"uint256"},{"name":"_owner","type":"address"}],"name":"createPromoKitty","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"secs","type":"uint256"}],"name":"setSecondsPerBlock","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"paused","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[],"name":"withdrawBalance","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"_tokenId","type":"uint256"}],"name":"ownerOf","outputs":[{"name":"owner","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"GEN0_CREATION_LIMIT","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"newContractAddress","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_address","type":"address"}],"name":"setSaleAuctionAddress","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"_owner","type":"address"}],"name":"balanceOf","outputs":[{"name":"count","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_v2Address","type":"address"}],"name":"setNewAddress","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"secondsPerBlock","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[],"name":"pause","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"_owner","type":"address"}],"name":"tokensOfOwner","outputs":[{"name":"ownerTokens","type":"uint256[]"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_matronId","type":"uint256"}],"name":"giveBirth","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[],"name":"withdrawAuctionBalances","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"symbol","outputs":[{"name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"","type":"uint256"}],"name":"cooldowns","outputs":[{"name":"","type":"uint32"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"","type":"uint256"}],"name":"kittyIndexToOwner","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_to","type":"address"},{"name":"_tokenId","type":"uint256"}],"name":"transfer","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"cooAddress","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"autoBirthFee","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"erc721Metadata","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_genes","type":"uint256"}],"name":"createGen0Auction","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"_kittyId","type":"uint256"}],"name":"isReadyToBreed","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"PROMO_CREATION_LIMIT","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_contractAddress","type":"address"}],"name":"setMetadataAddress","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"saleAuction","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"_id","type":"uint256"}],"name":"getKitty","outputs":[{"name":"isGestating","type":"bool"},{"name":"isReady","type":"bool"},{"name":"cooldownIndex","type":"uint256"},{"name":"nextActionAt","type":"uint256"},{"name":"siringWithId","type":"uint256"},{"name":"birthTime","type":"uint256"},{"name":"matronId","type":"uint256"},{"name":"sireId","type":"uint256"},{"name":"generation","type":"uint256"},{"name":"genes","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_sireId","type":"uint256"},{"name":"_matronId","type":"uint256"}],"name":"bidOnSiringAuction","outputs":[],"payable":true,"stateMutability":"payable","type":"function"},{"constant":true,"inputs":[],"name":"gen0CreatedCount","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"geneScience","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_matronId","type":"uint256"},{"name":"_sireId","type":"uint256"}],"name":"breedWithAuto","outputs":[],"payable":true,"stateMutability":"payable","type":"function"},{"inputs":[],"payable":false,"stateMutability":"nonpayable","type":"constructor"},{"payable":true,"stateMutability":"payable","type":"fallback"},{"anonymous":false,"inputs":[{"indexed":false,"name":"owner","type":"address"},{"indexed":false,"name":"matronId","type":"uint256"},{"indexed":false,"name":"sireId","type":"uint256"},{"indexed":false,"name":"cooldownEndBlock","type":"uint256"}],"name":"Pregnant","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"from","type":"address"},{"indexed":false,"name":"to","type":"address"},{"indexed":false,"name":"tokenId","type":"uint256"}],"name":"Transfer","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"owner","type":"address"},{"indexed":false,"name":"approved","type":"address"},{"indexed":false,"name":"tokenId","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"owner","type":"address"},{"indexed":false,"name":"kittyId","type":"uint256"},{"indexed":false,"name":"matronId","type":"uint256"},{"indexed":false,"name":"sireId","type":"uint256"},{"indexed":false,"name":"genes","type":"uint256"}],"name":"Birth","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"newContract","type":"address"}],"name":"ContractUpgrade","type":"event"}]
2 |
--------------------------------------------------------------------------------
/client/src/components/DapparatusCustom.js:
--------------------------------------------------------------------------------
1 | import React, { Component } from 'react';
2 | import cookie from 'react-cookies';
3 | import deepmerge from 'deepmerge';
4 | import logo from './assets/metamask.png';
5 | import eth from './assets/ethereum.png';
6 | import Scaler from './scaler.js';
7 | import Blockies from 'react-blockies';
8 | import ENS from 'ethereum-ens';
9 | import Web3 from 'web3';
10 | import Button from './button.js';
11 | const queryString = require('query-string');
12 |
13 | let interval;
14 | let defaultConfig = {};
15 | defaultConfig.DEBUG = false;
16 | defaultConfig.POLLINTERVAL = 777;
17 | defaultConfig.showBalance = true;
18 |
19 | //metatx
20 | defaultConfig.metatxAccountGenerator = '//account.metatx.io';
21 |
22 | defaultConfig.onlyShowBlockie = false
23 |
24 | defaultConfig.hideNetworks = ['Mainnet'];
25 | defaultConfig.accountCutoff = 16;
26 | defaultConfig.outerBoxStyle = {
27 | float: 'right'
28 | };
29 | defaultConfig.ETHPRECISION = 10000;
30 | defaultConfig.boxStyle = {
31 | paddingRight: 75,
32 | marginTop: 0,
33 | paddingTop: 0,
34 | zIndex: 10,
35 | textAlign: 'right',
36 | width: 300
37 | };
38 | defaultConfig.boxStyleBefore = {
39 | zIndex: 9999,
40 | marginTop: 3,
41 | paddingTop: 7,
42 | zIndex: 10,
43 | color: '#666666',
44 | textAlign: 'right',
45 | width: 450
46 | };
47 | defaultConfig.textStyle = {
48 | fontSize: 20,
49 | fontWeight: 'bold',
50 | color: '#666666'
51 | };
52 | defaultConfig.warningStyle = {
53 | fontWeight: 'bold',
54 | fontSize: 24
55 | };
56 | defaultConfig.blockieStyle = {
57 | size: 6,
58 | top: 10,
59 | right: 15
60 | };
61 | defaultConfig.requiredNetwork = [
62 | 'Mainnet',
63 | 'Unknown' //allow local RPC for testing
64 | ];
65 |
66 | let burnMetaAccount = ()=>{
67 | const expires = new Date();
68 | expires.setDate(expires.getDate()-1);
69 | cookie.save('metaPrivateKey', 0, {
70 | path: '/',
71 | expires: expires
72 | });
73 | setTimeout(()=>{
74 | window.location.reload(true);
75 | },300)
76 | }
77 |
78 | class DapparatusCustom extends Component {
79 | constructor(props) {
80 | super(props);
81 | let config = defaultConfig;
82 |
83 | if (props.config) {
84 | config = deepmerge(config, props.config);
85 | if (props.config.requiredNetwork && props.config.requiredNetwork[0] != "") {
86 | config.requiredNetwork = props.config.requiredNetwork;
87 | }
88 | }
89 | let queryParams = queryString.parse(window.location.search);
90 | let metaPrivateKey = cookie.load('metaPrivateKey');
91 | let metaAccount;
92 | let account = 0;
93 | if (metaPrivateKey) {
94 | let tempweb3 = new Web3();
95 | metaAccount = tempweb3.eth.accounts.privateKeyToAccount(metaPrivateKey);
96 | account = metaAccount.address.toLowerCase();
97 | } else if (queryParams.privateKey) {
98 | const expires = new Date();
99 | expires.setDate(expires.getDate() + 365);
100 | cookie.save('metaPrivateKey', queryParams.privateKey, {
101 | path: '/',
102 | expires
103 | });
104 | window.location = window.location.href.split('?')[0];
105 | }
106 |
107 | console.log('!!!!DAPPARATUS~~~~~ ', config);
108 |
109 | this.state = {
110 | status: 'loading',
111 | network: 0,
112 | account: account,
113 | etherscan: '',
114 | config: config,
115 | avgBlockTime: 15000,
116 | lastBlockTime: 0,
117 | metaAccount: metaAccount,
118 | burnMetaAccount: burnMetaAccount,
119 | web3Fellback: false,
120 | hasRequestedAccess: false
121 | };
122 | }
123 | componentDidUpdate() {
124 | if (this.props.config) {
125 | const requiredNetwork = this.props.config.requiredNetwork;
126 | let config = this.state.config;
127 | if (requiredNetwork && requiredNetwork[0] != "" && config.requiredNetwork != requiredNetwork){
128 | config.requiredNetwork = requiredNetwork;
129 | this.setState({config: config});
130 | }
131 | }
132 | }
133 | componentDidMount() {
134 | interval = setInterval(
135 | this.checkMetamask.bind(this),
136 | this.state.config.POLLINTERVAL
137 | );
138 | this.checkMetamask();
139 | }
140 | componentWillUnmount() {
141 | clearInterval(interval);
142 | }
143 | checkMetamask() {
144 | if (this.state.config.DEBUG) console.log('DAPPARATUS - checking state...');
145 | if (typeof window.web3 == 'undefined') {
146 | console.log('Connecting to infura...');
147 | window.web3 = new Web3(this.props.fallbackWeb3Provider); //CORS ISSUES!//
148 | this.setState({ web3Fellback: true });
149 | //window.web3 = new Web3(new Web3.providers.WebsocketProvider('wss://rinkeby.infura.io/ws'))
150 | }
151 |
152 | if (typeof window.web3 == 'undefined') {
153 | if (this.state.config.DEBUG) console.log('DAPPARATUS - no web3');
154 | if (this.state.status == 'loading') {
155 | this.setState({ status: 'noweb3' }, () => {
156 | this.props.onUpdate(this.state);
157 | });
158 | } else if (this.state.status != 'noweb3') {
159 | if (this.state.config.DEBUG) console.log('DAPPARATUS - lost web3');
160 | window.location.reload(true);
161 | this.setState({ status: 'error' }, () => {
162 | this.props.onUpdate(this.state);
163 | });
164 | }
165 | } else {
166 | if (this.state.config.DEBUG) {
167 | console.log('DAPPARATUS - yes web 3', window.web3);
168 | }
169 | if (typeof window.web3.version.getNetwork != 'function') {
170 | window.window.web3.eth.net.getId((err, network) => {
171 | //console.log("NETWORK GETID",err,network)
172 | this.inspectNetwork(network);
173 | });
174 | } else {
175 | window.web3.version.getNetwork((err, network) => {
176 | this.inspectNetwork(network);
177 | });
178 | }
179 | }
180 | }
181 | inspectNetwork(network) {
182 | if (this.state.config.DEBUG) console.log('DAPPARATUS - network', network);
183 | let networkNumber = network
184 | network = translateNetwork(network);
185 | if(network=="Unknown"){
186 | if(window.web3 && window.web3.currentProvider && window.web3.currentProvider.host && window.web3.currentProvider.host.indexOf("dai.poa.network")){
187 | network="xDai"
188 | }else if(window.web3 && window.web3.currentProvider && window.web3.currentProvider.host && window.web3.currentProvider.host.indexOf("poa.network")){
189 | network="POA"
190 | }
191 | }
192 | if (this.state.config.DEBUG) console.log('DAPPARATUS - translated network', network);
193 | let accounts;
194 | try {
195 | if (this.state.config.DEBUG) console.log('DAPPARATUS - getting accounts...');
196 | window.web3.eth.getAccounts((err, _accounts) => {
197 | //console.log("ACCOUNTS",err,_accounts)
198 | if (!_accounts || _accounts.length <= 0 || this.state.web3Fellback) {
199 | if (!this.state.hasRequestedAccess) { // Prevent multiple prompts
200 | if (this.state.config.DEBUG) console.log('METAMASK - requesting access from user...');
201 | this.setState({ hasRequestedAccess: true},() => {
202 | this.props.onUpdate(this.state);
203 | });
204 | try{
205 | window.ethereum.enable().then(() => {
206 | window.location.reload(true);
207 | })
208 | } catch (e) {
209 | console.log(e);
210 | this.setState({ status: 'private', network: network },() => {
211 | this.props.onUpdate(this.state);
212 | });
213 | }
214 | }
215 | if (this.state.config.DEBUG) console.log('DAPPARATUS - no inject accounts - generate? ');
216 | if (!this.state.metaAccount || !this.state.metaAccount.address) {
217 | this.setState({ status: 'noaccount' }, () => {
218 | if (this.state.config.metatxAccountGenerator) {
219 | console.log('Connecting to ' + this.state.config.metatxAccountGenerator + '...');
220 | window.location = this.state.config.metatxAccountGenerator;
221 | } else {
222 | console.log("Generating account...")
223 | let result = window.web3.eth.accounts.create();
224 | //console.log("GENERATE",result)
225 | const expires = new Date();
226 | expires.setDate(expires.getDate() + 365);
227 | cookie.save('metaPrivateKey', result.privateKey, {
228 | path: '/',
229 | expires
230 | });
231 | setTimeout(()=>{
232 | window.location.reload(true);
233 | },300)
234 | this.setState({ metaAccount: result, account: result.address.toLowerCase(), burnMetaAccount:burnMetaAccount },()=>{
235 | this.props.onUpdate(this.state);
236 | });
237 | }
238 |
239 | });
240 | } else {
241 | let currentAccounts = [];
242 | //console.log("generated account",this.state.metaAccount)
243 | currentAccounts.push(this.state.metaAccount.address);
244 | //console.log("currentAccounts",currentAccounts)
245 | this.inspectAccounts(currentAccounts, network);
246 | }
247 | if(this.state.metaAccount){
248 | //console.log("metaAccount",this.state.metaAccount)
249 | this.loadBlockBalanceAndName(this.state.metaAccount.address, network);
250 | }else{
251 | //console.lob("no metaAccount")
252 | }
253 | } else {
254 | if (this.state.config.DEBUG)
255 | console.log('DAPPARATUS - injected account: ', _accounts);
256 | this.inspectAccounts(_accounts, network);
257 | this.setState({ metaAccount: false });
258 | }
259 | });
260 | } catch (e) {
261 | console.log(e);
262 | if (this.state.metamask != -1)
263 | this.setState({ metamask: -1, network: network, web3: web3 });
264 | }
265 | }
266 | inspectAccounts(currentAccounts, network) {
267 | if (this.state.config.DEBUG)
268 | console.log(
269 | 'DAPPARATUS - accounts:',
270 | currentAccounts,
271 | this.state.account
272 | );
273 | if (currentAccounts && this.state.account) {
274 | if (currentAccounts.length <= 0) {
275 | //window.location.reload(true);
276 | console.log('RELOAD BECAUSE LOST ACCOUNTS?');
277 | } else if (this.state.account != currentAccounts[0].toLowerCase()) {
278 | // window.location.reload(true);
279 | console.log('RELOAD BECAUSE DIFFERENT ACCOUNTS?');
280 | }
281 | }
282 | if (!currentAccounts) {
283 | if (this.state.status != 'error')
284 | this.setState({ status: 'error', network: network }, () => {
285 | this.props.onUpdate(this.state);
286 | });
287 | } else if (currentAccounts.length <= 0) {
288 | if (this.state.status != 'locked')
289 | this.setState({ status: 'locked', network: network }, () => {
290 | this.props.onUpdate(this.state);
291 | });
292 | } else {
293 | this.loadBlockBalanceAndName(currentAccounts[0].toLowerCase(), network);
294 | }
295 | }
296 | loadBlockBalanceAndName(account, network) {
297 |
298 | if (this.state.config.DEBUG) console.log("LOADING BALANCE...")
299 | window.web3.eth.getBlockNumber((err, block) => {
300 | if (this.state.config.DEBUG) console.log("BLOCK",err,block)
301 | window.web3.eth.getBalance('' + account, (err, balance, e) => {
302 | if (this.state.config.DEBUG) console.log("BALANCE",err,balance,e)
303 | if (typeof balance == 'string') {
304 | balance = parseFloat(balance) / 1000000000000000000;
305 | } else if (balance) {
306 | balance = balance.toNumber() / 1000000000000000000;
307 | }
308 | //if (this.state.config.DEBUG) console.log("Adjusted balance",balance)
309 | let etherscan = 'https://etherscan.io/';
310 | if (network) {
311 | if (network == 'Unknown' || network == 'private') {
312 | etherscan = 'http://localhost:8000/#/';
313 | } else if (network == 'POA') {
314 | etherscan = 'https://blockscout.com/poa/core/';
315 | } else if (network == 'xDai') {
316 | etherscan = 'https://blockscout.com/poa/dai/';
317 | } else if (network != 'Mainnet') {
318 | etherscan = 'https://' + network.toLowerCase() + '.etherscan.io/';
319 | }
320 | }
321 | if (this.state.config.DEBUG){
322 | console.log('DAPPARATUS - etherscan', etherscan);
323 | }
324 |
325 | if (
326 | this.state.status != 'ready' ||
327 | this.state.block != block ||
328 | this.state.balance != balance
329 | ) {
330 | web3 = new Web3(window.web3.currentProvider);
331 | let ens = new ENS(window.web3.currentProvider);
332 | if (this.state.config.DEBUG)
333 | console.log('attempting to ens reverse account....');
334 | try {
335 | var address = ens
336 | .reverse(account)
337 | .name()
338 | .catch(err => {
339 | if (this.state.config.DEBUG)
340 | console.log(
341 | 'catch ens error (probably just didn\'t find it, ignore silently)'
342 | );
343 | })
344 | .then(data => {
345 | console.log('ENS data', data);
346 | if (data) {
347 | this.setState({ ens: data }, () => {
348 | this.props.onUpdate(this.state);
349 | });
350 | }
351 | });
352 | } catch (e) {}
353 |
354 | console.log(
355 | 'Saving web3, generated account:',
356 | this.state.metaAccount,
357 | web3
358 | );
359 | let update = {
360 | status: 'ready',
361 | block: block,
362 | balance: balance,
363 | network: network,
364 | web3Provider: window.web3.currentProvider,
365 | etherscan: etherscan,
366 | account: account.toLowerCase(),
367 | metaAccount: this.state.metaAccount
368 | };
369 | if (block != this.state.block) {
370 | //block update
371 | if (this.state.lastBlockTime) {
372 | let timeItTook = Date.now() - this.state.lastBlockTime;
373 | update.avgBlockTime = Math.round(
374 | (this.state.avgBlockTime * 4) / 5 + timeItTook / 5
375 | );
376 | }
377 | update.lastBlockTime = Date.now();
378 | }
379 | this.setState(update, () => {
380 | this.props.onUpdate(this.state);
381 | });
382 | }
383 | });
384 | });
385 | }
386 | render() {
387 | let dapparatus = 'loading.';
388 | if (this.props.config.hide) {
389 | dapparatus = [];
390 | }
391 | else if (this.state.status == 'loading') {
392 | dapparatus = (
393 |
394 | loading...
395 |
399 |
400 | );
401 | } else if (this.state.status == 'noweb3') {
402 | dapparatus = (
403 |
404 | No Web3 Connection
405 |
409 |
410 | );
411 | } else if (this.state.status == 'noaccount') {
412 | let mmClick = () => {
413 | window.open('https://metamask.io', '_blank');
414 | };
415 | dapparatus = 'Generating Account...';
416 | } else if (this.state.status == 'locked') {
417 | dapparatus = (
418 |
426 |
436 |
459 |
502 | {balance}
503 |
504 |