├── .gitignore ├── LICENSE ├── README.md ├── package.json ├── public ├── images │ └── blue-q_icon.svg └── index.html ├── src ├── components │ ├── codeSample.js │ ├── index.js │ ├── log.js │ ├── methodCall.js │ ├── methodList.js │ ├── navBar.js │ ├── needLibMessage.js │ ├── needMethodMessage.js │ ├── needURLMessage.js │ ├── sponsoredAd.js │ ├── statusBar.js │ └── web3Menu.js ├── containers │ ├── codeSampleContainer.js │ ├── index.js │ ├── logsContainer.js │ ├── methodCallContainer.js │ ├── navBarContainer.js │ ├── sponsoredAdContainer.js │ ├── statusBarContainer.js │ └── web3MenuContainer.js ├── context │ ├── appProvider.js │ ├── index.js │ ├── logProvider.js │ └── web3Provider.js ├── helpers │ ├── buildProvider.js │ ├── contracts.js │ ├── libs │ │ ├── curl.js │ │ ├── ethers.js │ │ ├── index.js │ │ └── web3js.js │ ├── web3Config.js │ └── web3State.js ├── index.js ├── tailwind.css └── tailwind.output.css ├── tailwind.config.js └── yarn.lock /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | build 3 | .DS_Store -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021 Auston Bunsen 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |
2 |

EtherFlow

3 | 4 |

5 | A tool for interacting/debugging with Ethereum JSON-RPC and generating sample code. 6 |
7 | View Demo 8 | · 9 | Report Bug 10 | · 11 | Request Feature 12 |

13 |
14 | 15 | # About 16 | 17 | EtherFlow is a tool for sending requests to Ethereum JSON-RPC endpoints without having to write code. It supports most standard RPC methods and the [trace module for Parity/OpenEthereum](https://openethereum.github.io/wiki/JSONRPC-trace-module#trace_transaction). It updates the URL and embeds your RPC endpoint, preferred library, method call and params in the URL for easy sharing to any relevant parties. 18 | 19 | # Quik Start 20 | 21 | If you don't want to install anything just go here: https://etherflow.quiknode.io 22 | 23 | You can also just run this in your terminal: 24 | 25 | ``` 26 | git clone git@github.com:abunsen/etherflow.git && cd etherflow && npm install && npm start 27 | ``` 28 | 29 | # Adding a new lib 30 | 31 | There is a folder `etherflow -> src -> helpers -> libs` [link](src/helpers/libs) that contains all of the supported libraries. If you'd like to add a new front end library, it's easy enough: 32 | 33 | 1. Add a file in the above folder with the `.js` 34 | 2. Add a every single supported RPC method from [here](src/helpers/web3Config.js) to an exported object 35 | 3. Add `exec`, `codeSample` and `args` to each method 36 | 4. Test it 37 | 5. You're done! 38 | 39 | If you'd like to add a new back end library, please [open an issue](https://github.com/abunsen/etherflow/issues/new?assignees=&labels=&template=feature_request.md&title=New+Backend+Lib+Support) so we can discuss the best way to support this! 40 | 41 | # Contributing 42 | 43 | Please feel free to add tests, change the code so it has better organization, etc. I'm very happy to receive PRs. 44 | 45 | # Wishlist (in order of priority) 46 | 47 | - [x] Enable ABI upload for smart contracts on eth_call 48 | - [x] Make trace_call use the ABI from point above (docs: https://openethereum.github.io/wiki/JSONRPC-trace-module) 49 | - [ ] Enable eth_newFilter for web3.js 50 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "etherflow", 3 | "version": "1.0.0", 4 | "description": "A web interface for debugging ethereum nodes", 5 | "main": "src/index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1", 8 | "build:tailwind": "tailwindcss build src/tailwind.css -o src/tailwind.output.css", 9 | "prestart": "npm run build:tailwind", 10 | "prebuild": "npm run build:tailwind", 11 | "start": "concurrently \"react-scripts start\"" 12 | }, 13 | "keywords": [ 14 | "ethereum", 15 | "web3", 16 | "ethers.js" 17 | ], 18 | "author": "Auston Bunsen", 19 | "license": "MIT", 20 | "dependencies": { 21 | "@reach/router": "^1.3.4", 22 | "@tailwindcss/ui": "^0.3.1", 23 | "bootstrap": "^4.5.0", 24 | "concurrently": "^5.2.0", 25 | "console-feed": "^3.0.0", 26 | "cors": "^2.8.5", 27 | "ethers": "^5.0.5", 28 | "express": "^4.17.1", 29 | "lodash": "^4.17.19", 30 | "react": "^16.13.1", 31 | "react-dom": "^16.13.1", 32 | "react-scripts": "^3.4.3", 33 | "react-syntax-highlighter": "^12.2.1", 34 | "tailwindcss": "^1.5.1", 35 | "web3": "^1.2.11" 36 | }, 37 | "eslintConfig": { 38 | "extends": "react-app" 39 | }, 40 | "prettier": { 41 | "singleQuote": true, 42 | "semi": true 43 | }, 44 | "browserslist": { 45 | "production": [ 46 | ">0.2%", 47 | "not dead", 48 | "not op_mini all" 49 | ], 50 | "development": [ 51 | "last 1 chrome version", 52 | "last 1 firefox version", 53 | "last 1 safari version" 54 | ] 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /public/images/blue-q_icon.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 16 | EtherFlow - Ethereum Node Tester & RPC Call Composer 17 | 18 | 19 | 20 | 21 |
22 | 32 | 33 | 34 | -------------------------------------------------------------------------------- /src/components/codeSample.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import SyntaxHighlighter from 'react-syntax-highlighter'; 3 | import { docco } from 'react-syntax-highlighter/dist/esm/styles/hljs'; 4 | import Web3RpcCalls from '../helpers/web3Config'; 5 | 6 | const CodeSample = ({ 7 | web3Lib, 8 | args, 9 | currentMethod, 10 | hideCodeSample, 11 | url, 12 | visible, 13 | }) => { 14 | const codeSampleText = 15 | currentMethod && 16 | web3Lib && 17 | url && 18 | Web3RpcCalls[currentMethod][web3Lib]['codeSample'](url, ...args); 19 | const classes = `${visible ? '' : 'hidden'} fixed inset-0 overflow-hidden`; 20 | 21 | return ( 22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |

30 | Code Sample for{' '} 31 |
{currentMethod}
32 |

33 |
34 | 53 |
54 |
55 |
56 |
57 |
58 | 66 | {codeSampleText} 67 | 68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 | ); 76 | }; 77 | 78 | export { CodeSample }; 79 | -------------------------------------------------------------------------------- /src/components/index.js: -------------------------------------------------------------------------------- 1 | import { Logs } from './log'; 2 | import { MethodCall } from './methodCall'; 3 | import { StatusBar } from './statusBar'; 4 | import { CodeSample } from './codeSample'; 5 | import { NavBar } from './navBar'; 6 | import { Web3Menu } from './web3Menu'; 7 | import { NeedMethodMessage } from './needMethodMessage'; 8 | import { NeedURLMessage } from './needURLMessage'; 9 | import { SponsoredAd } from './sponsoredAd'; 10 | 11 | export { 12 | CodeSample, 13 | Logs, 14 | MethodCall, 15 | NavBar, 16 | NeedMethodMessage, 17 | NeedURLMessage, 18 | SponsoredAd, 19 | StatusBar, 20 | Web3Menu, 21 | }; 22 | -------------------------------------------------------------------------------- /src/components/log.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { Console } from 'console-feed'; 3 | 4 | const Logs = ({ logs }) => { 5 | return ( 6 |
7 |

8 | Logs 9 |

10 |
11 | 12 |
13 |
14 | ); 15 | }; 16 | 17 | export { Logs }; 18 | -------------------------------------------------------------------------------- /src/components/methodCall.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | const Textarea = ({ placeholder, updateValue, initialVal }) => { 4 | return ( 5 | 13 | ); 14 | }; 15 | 16 | const TextField = ({ placeholder, updateValue, initialVal }) => { 17 | return ( 18 | 19 | updateValue(e.target.value)} 24 | defaultValue={initialVal} 25 | /> 26 | 27 | ); 28 | }; 29 | 30 | const BooleanSelect = ({ initialVal, updateValue }) => { 31 | return ( 32 | 48 | ); 49 | }; 50 | 51 | const Dropdown = ({ dropdownOptions = [], updateValue, disabled, val }) => { 52 | return ( 53 | 71 | ); 72 | }; 73 | 74 | const Field = ({ 75 | description, 76 | placeholder, 77 | type, 78 | val, 79 | updateValue, 80 | dropdownOptions, 81 | disabled, 82 | }) => { 83 | let actualField; 84 | switch (type) { 85 | case 'dropdown': 86 | actualField = ( 87 | 93 | ); 94 | break; 95 | case 'textfield': 96 | actualField = ( 97 | 102 | ); 103 | break; 104 | case 'boolean': 105 | actualField = ( 106 | 107 | ); 108 | break; 109 | default: 110 | actualField = ( 111 |