├── public ├── robots.txt ├── favicon.ico ├── logo192.png ├── logo512.png ├── manifest.json └── index.html ├── src ├── assets │ └── images │ │ ├── algorandicon.webp │ │ ├── screenshots │ │ ├── Screenshot1.png │ │ ├── Screenshot2.png │ │ ├── Screenshot3.png │ │ ├── Screenshot4.png │ │ ├── Screenshot5.png │ │ └── Screenshot6.png │ │ └── caution.svg ├── App.jsx ├── App.test.js ├── services │ └── algorandsdk.js ├── App.css ├── index.css ├── components │ ├── pages │ │ ├── multisigtransactionpage.jsx │ │ ├── transactionpage.jsx │ │ ├── accountpage.jsx │ │ ├── createaccountpage.jsx │ │ └── restoreaccountcomponent.jsx │ ├── stateful │ │ ├── suggestedfeecomponent.jsx │ │ ├── accountcomponent.jsx │ │ ├── transactionofflinecomponent.jsx │ │ ├── predictedroundrangecomponent.jsx │ │ ├── transactioncomponent.jsx │ │ └── multisigtransactioncomponent.jsx │ └── stateless │ │ ├── createaccountbutton.jsx │ │ ├── restoreaccountbutton.jsx │ │ ├── appRouter.jsx │ │ ├── headercomponent.jsx │ │ ├── accounttransactioncomponent.jsx │ │ ├── transactionrow.jsx │ │ └── accountdetailcomponent.jsx ├── index.js ├── serviceWorker.js └── logo.svg ├── .gitignore ├── package.json ├── README.md └── LICENSE /public/robots.txt: -------------------------------------------------------------------------------- 1 | # https://www.robotstxt.org/robotstxt.html 2 | User-agent: * 3 | -------------------------------------------------------------------------------- /public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rekpero/algorand-sdk-react-component/HEAD/public/favicon.ico -------------------------------------------------------------------------------- /public/logo192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rekpero/algorand-sdk-react-component/HEAD/public/logo192.png -------------------------------------------------------------------------------- /public/logo512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rekpero/algorand-sdk-react-component/HEAD/public/logo512.png -------------------------------------------------------------------------------- /src/assets/images/algorandicon.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rekpero/algorand-sdk-react-component/HEAD/src/assets/images/algorandicon.webp -------------------------------------------------------------------------------- /src/assets/images/screenshots/Screenshot1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rekpero/algorand-sdk-react-component/HEAD/src/assets/images/screenshots/Screenshot1.png -------------------------------------------------------------------------------- /src/assets/images/screenshots/Screenshot2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rekpero/algorand-sdk-react-component/HEAD/src/assets/images/screenshots/Screenshot2.png -------------------------------------------------------------------------------- /src/assets/images/screenshots/Screenshot3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rekpero/algorand-sdk-react-component/HEAD/src/assets/images/screenshots/Screenshot3.png -------------------------------------------------------------------------------- /src/assets/images/screenshots/Screenshot4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rekpero/algorand-sdk-react-component/HEAD/src/assets/images/screenshots/Screenshot4.png -------------------------------------------------------------------------------- /src/assets/images/screenshots/Screenshot5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rekpero/algorand-sdk-react-component/HEAD/src/assets/images/screenshots/Screenshot5.png -------------------------------------------------------------------------------- /src/assets/images/screenshots/Screenshot6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rekpero/algorand-sdk-react-component/HEAD/src/assets/images/screenshots/Screenshot6.png -------------------------------------------------------------------------------- /src/App.jsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import Header from "./components/stateless/headercomponent"; 3 | 4 | function App(props) { 5 | return ( 6 |
7 |
8 | {props.children} 9 |
10 | ); 11 | } 12 | 13 | export default App; 14 | -------------------------------------------------------------------------------- /src/App.test.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ReactDOM from 'react-dom'; 3 | import App from './App'; 4 | 5 | it('renders without crashing', () => { 6 | const div = document.createElement('div'); 7 | ReactDOM.render(, div); 8 | ReactDOM.unmountComponentAtNode(div); 9 | }); 10 | -------------------------------------------------------------------------------- /src/services/algorandsdk.js: -------------------------------------------------------------------------------- 1 | import algosdk from 'algosdk'; 2 | 3 | const token = "ef920e2e7e002953f4b29a8af720efe8e4ecc75ff102b165e0472834b25832c1"; 4 | const server = "http://hackathon.algodev.network"; 5 | const port = 9100; 6 | 7 | // algod client 8 | const AlgorandClient = new algosdk.Algod(token, server, port); 9 | export default AlgorandClient; -------------------------------------------------------------------------------- /src/App.css: -------------------------------------------------------------------------------- 1 | .App { 2 | text-align: center; 3 | } 4 | 5 | .App-logo { 6 | height: 40vmin; 7 | } 8 | 9 | .App-header { 10 | background-color: #282c34; 11 | min-height: 100vh; 12 | display: flex; 13 | flex-direction: column; 14 | align-items: center; 15 | justify-content: center; 16 | font-size: calc(10px + 2vmin); 17 | color: white; 18 | } 19 | 20 | .App-link { 21 | color: #09d3ac; 22 | } 23 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /node_modules 5 | /.pnp 6 | .pnp.js 7 | 8 | # testing 9 | /coverage 10 | 11 | # production 12 | /build 13 | 14 | # misc 15 | .DS_Store 16 | .env.local 17 | .env.development.local 18 | .env.test.local 19 | .env.production.local 20 | 21 | npm-debug.log* 22 | yarn-debug.log* 23 | yarn-error.log* 24 | -------------------------------------------------------------------------------- /src/index.css: -------------------------------------------------------------------------------- 1 | body { 2 | margin: 0; 3 | font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", "Oxygen", 4 | "Ubuntu", "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue", 5 | sans-serif; 6 | -webkit-font-smoothing: antialiased; 7 | -moz-osx-font-smoothing: grayscale; 8 | } 9 | 10 | code { 11 | font-family: source-code-pro, Menlo, Monaco, Consolas, "Courier New", 12 | monospace; 13 | } 14 | -------------------------------------------------------------------------------- /public/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "short_name": "React App", 3 | "name": "Create React App Sample", 4 | "icons": [ 5 | { 6 | "src": "favicon.ico", 7 | "sizes": "64x64 32x32 24x24 16x16", 8 | "type": "image/x-icon" 9 | }, 10 | { 11 | "src": "logo192.png", 12 | "type": "image/png", 13 | "sizes": "192x192" 14 | }, 15 | { 16 | "src": "logo512.png", 17 | "type": "image/png", 18 | "sizes": "512x512" 19 | } 20 | ], 21 | "start_url": ".", 22 | "display": "standalone", 23 | "theme_color": "#000000", 24 | "background_color": "#ffffff" 25 | } 26 | -------------------------------------------------------------------------------- /src/components/pages/multisigtransactionpage.jsx: -------------------------------------------------------------------------------- 1 | import * as React from "react"; 2 | import MultisigTransactionComponent from "../stateful/multisigtransactioncomponent"; 3 | 4 | /** 5 | * This component contain multi signature transaction components. 6 | * 7 | * @author [Mitrasish Mukherjee](https://github.com/mmitrasish) 8 | */ 9 | const MultisigTransactionPage = () => { 10 | return ( 11 |
12 |
13 |
14 | 15 |
16 |
17 |
18 | ); 19 | }; 20 | export default MultisigTransactionPage; 21 | -------------------------------------------------------------------------------- /src/index.js: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import ReactDOM from "react-dom"; 3 | import "./index.css"; 4 | import "../node_modules/popper.js/dist/popper.min"; 5 | import "../node_modules/bootstrap/dist/js/bootstrap.min"; 6 | import "../node_modules/bootstrap/dist/css/bootstrap.min.css"; 7 | import * as serviceWorker from "./serviceWorker"; 8 | import AppRouter from "./components/stateless/appRouter"; 9 | 10 | ReactDOM.render(, document.getElementById("root")); 11 | 12 | // If you want your app to work offline and load faster, you can change 13 | // unregister() to register() below. Note this comes with some pitfalls. 14 | // Learn more about service workers: https://bit.ly/CRA-PWA 15 | serviceWorker.unregister(); 16 | -------------------------------------------------------------------------------- /src/assets/images/caution.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "algorand-sdk-react-component", 3 | "version": "0.1.0", 4 | "private": true, 5 | "dependencies": { 6 | "algosdk": "^1.3.1", 7 | "bootstrap": "^4.3.1", 8 | "clipboard-copy": "^3.1.0", 9 | "jquery": "^3.4.1", 10 | "popper.js": "^1.15.0", 11 | "react": "^16.10.1", 12 | "react-dom": "^16.10.1", 13 | "react-router-dom": "^5.0.1", 14 | "react-scripts": "3.1.2" 15 | }, 16 | "scripts": { 17 | "start": "react-scripts start", 18 | "build": "react-scripts build", 19 | "test": "react-scripts test", 20 | "eject": "react-scripts eject" 21 | }, 22 | "eslintConfig": { 23 | "extends": "react-app" 24 | }, 25 | "browserslist": { 26 | "production": [ 27 | ">0.2%", 28 | "not dead", 29 | "not op_mini all" 30 | ], 31 | "development": [ 32 | "last 1 chrome version", 33 | "last 1 firefox version", 34 | "last 1 safari version" 35 | ] 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /src/components/stateful/suggestedfeecomponent.jsx: -------------------------------------------------------------------------------- 1 | import * as React from "react"; 2 | import AlgorandClient from "../../services/algorandsdk"; 3 | 4 | /** 5 | * This component will show you suggested fee. 6 | * @state suggestedFee: number -> store suggessted fee from the sdk 7 | * 8 | * @author [Mitrasish Mukherjee](https://github.com/mmitrasish) 9 | */ 10 | export default class SuggestedFeeComponent extends React.Component { 11 | constructor(props) { 12 | super(props); 13 | this.state = { 14 | suggestedFee: 0 15 | }; 16 | } 17 | componentDidMount = async () => { 18 | // getting the suggested fee 19 | let suggestedFee = await AlgorandClient.suggestedFee(); 20 | this.setState({ suggestedFee: suggestedFee.fee * 1000 }); 21 | }; 22 | render() { 23 | return ( 24 |
25 | 26 | {this.state.suggestedFee} microAlgos 27 |
28 | ); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/components/stateless/createaccountbutton.jsx: -------------------------------------------------------------------------------- 1 | import * as React from "react"; 2 | import algosdk from "algosdk"; 3 | 4 | /** 5 | * This component will generate a new account with a click of generate button. 6 | * @props createAccount: (keys) => void -> this will get the account keys as arg from props 7 | * 8 | * @author [Mitrasish Mukherjee](https://github.com/mmitrasish) 9 | */ 10 | const CreateAccountButton = props => { 11 | // this will create a new account and push it to props createAccount 12 | let generateAccount = () => { 13 | // generating new account 14 | let keys = algosdk.generateAccount(); 15 | 16 | // calling the props createAccount 17 | props.createAccount(keys); 18 | }; 19 | 20 | return ( 21 | 28 | ); 29 | }; 30 | export default CreateAccountButton; 31 | -------------------------------------------------------------------------------- /src/components/stateless/restoreaccountbutton.jsx: -------------------------------------------------------------------------------- 1 | import * as React from "react"; 2 | import algosdk from "algosdk"; 3 | 4 | /** 5 | * This component will restore your account given mnemonic from props with a click of restore button. 6 | * @props mnemonic: string -> get the mnemonic provided to the component 7 | * @props restoreAccount: (keys) => void -> this will get the account keys as arg from props 8 | * 9 | * @author [Mitrasish Mukherjee](https://github.com/mmitrasish) 10 | */ 11 | const RestoreAccountButton = props => { 12 | // this will create a new account and push it to props createAccount 13 | let restoreAccount = () => { 14 | // generating new account 15 | var keys = algosdk.mnemonicToSecretKey(props.mnemonic); 16 | 17 | // calling the props createAccount 18 | props.restoreAccount(keys); 19 | }; 20 | 21 | return ( 22 | 29 | ); 30 | }; 31 | export default RestoreAccountButton; 32 | -------------------------------------------------------------------------------- /src/components/pages/transactionpage.jsx: -------------------------------------------------------------------------------- 1 | import * as React from "react"; 2 | import TransactionComponent from "../stateful/transactioncomponent"; 3 | import TransactionOfflineComponent from "../stateful/transactionofflinecomponent"; 4 | import PredictedRoundRangeComponent from "../stateful/predictedroundrangecomponent"; 5 | 6 | /** 7 | * This component contain transaction components. 8 | * 9 | * @author [Mitrasish Mukherjee](https://github.com/mmitrasish) 10 | */ 11 | const TransactionPage = () => { 12 | return ( 13 |
14 |
15 |
16 | 17 |
18 |
19 |
20 |
21 |
22 | 23 |
24 |
25 | 26 |
27 |
28 |
29 |
30 | ); 31 | }; 32 | export default TransactionPage; 33 | -------------------------------------------------------------------------------- /src/components/stateless/appRouter.jsx: -------------------------------------------------------------------------------- 1 | import * as React from "react"; 2 | import { BrowserRouter as Router, Route, Redirect } from "react-router-dom"; 3 | import App from "../../App"; 4 | import CreateAccountPage from "../pages/createaccountpage"; 5 | import TransactionPage from "../pages/transactionpage"; 6 | import RestoreAccountPage from "../pages/restoreaccountcomponent"; 7 | import AccountPage from "../pages/accountpage"; 8 | import MultisigTransactionPage from "../pages/multisigtransactionpage"; 9 | 10 | const AppRouter = () => { 11 | return ( 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 23 | localStorage.getItem("address") !== null ? ( 24 | 25 | ) : ( 26 | 27 | ) 28 | } 29 | /> 30 | 31 | 32 | ); 33 | }; 34 | export default AppRouter; 35 | -------------------------------------------------------------------------------- /src/components/pages/accountpage.jsx: -------------------------------------------------------------------------------- 1 | import * as React from "react"; 2 | import AccountComponent from "../stateful/accountcomponent"; 3 | 4 | /** 5 | * This component contain account component 6 | * 7 | * @state address: string -> store account address from the localstorage 8 | * @state mnemonic: string -> store account mnemonic from the localstorage 9 | * @state accountList: list of accounts -> store the list of accounts from the localstorage 10 | * 11 | * @author [Mitrasish Mukherjee](https://github.com/mmitrasish) 12 | */ 13 | class AccountPage extends React.Component { 14 | constructor(props) { 15 | super(props); 16 | this.state = { 17 | address: localStorage.getItem("address"), 18 | mnemonic: localStorage.getItem("mnemonic"), 19 | accountList: localStorage.getItem("accountList") 20 | }; 21 | } 22 | changeAccount = account => { 23 | console.log(account.address); 24 | localStorage.setItem("address", account.address); 25 | localStorage.setItem("mnemonic", account.mnemonic); 26 | this.setState({ 27 | address: localStorage.getItem("address"), 28 | mnemonic: localStorage.getItem("mnemonic"), 29 | accountList: localStorage.getItem("accountList") 30 | }); 31 | }; 32 | render() { 33 | return ( 34 | 40 | ); 41 | } 42 | } 43 | export default AccountPage; 44 | -------------------------------------------------------------------------------- /src/components/stateless/headercomponent.jsx: -------------------------------------------------------------------------------- 1 | import * as React from "react"; 2 | import { Link } from "react-router-dom"; 3 | 4 | const Header = props => { 5 | return ( 6 |
7 | 44 |
45 | ); 46 | }; 47 | 48 | export default Header; 49 | -------------------------------------------------------------------------------- /src/components/stateless/accounttransactioncomponent.jsx: -------------------------------------------------------------------------------- 1 | import * as React from "react"; 2 | import algosdk from "algosdk"; 3 | import TransactionRow from "./transactionrow"; 4 | 5 | /** 6 | * This component will show account transaction list for the address 7 | * @props transactions: list of transaction -> list of account transaction 8 | * @props transactionLoaded: boolean -> true when all transaction loaded 9 | * 10 | * 11 | * @author [Mitrasish Mukherjee](https://github.com/mmitrasish) 12 | */ 13 | const AccountTransactionComponent = props => { 14 | return ( 15 |
16 |
17 |

Recent Transactions

18 | {props.transactionLoaded === false ? ( 19 |
20 | Loading... 21 |
22 | ) : null} 23 |
24 |
25 | {props.transactions.length === 0 ? ( 26 | props.transactionLoaded === true ? ( 27 | No recent transaction found 28 | ) : null 29 | ) : ( 30 | props.transactions.map(txt => ( 31 | 41 | )) 42 | )} 43 |
44 |
45 | ); 46 | }; 47 | export default AccountTransactionComponent; 48 | -------------------------------------------------------------------------------- /public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 15 | 16 | 25 | Algorand React App 26 | 27 | 28 | 29 | 30 |
31 | 41 | 42 | 43 | -------------------------------------------------------------------------------- /src/components/pages/createaccountpage.jsx: -------------------------------------------------------------------------------- 1 | import * as React from "react"; 2 | import algosdk from "algosdk"; 3 | import { withRouter, Link } from "react-router-dom"; 4 | import CreateAccountButton from "../stateless/createaccountbutton"; 5 | 6 | /** 7 | * This component will generate a new account with a click of generate button 8 | * Also the restore button will redirect you to restore acount page. 9 | * 10 | * @author [Mitrasish Mukherjee](https://github.com/mmitrasish) 11 | */ 12 | const CreateAccountPage = ({ history }) => { 13 | // this will create a new account and push it to localstorage 14 | let createAccount = keys => { 15 | // pushing account address and mnemonic to localstorage 16 | localStorage.setItem("address", keys.addr); 17 | localStorage.setItem("mnemonic", algosdk.secretKeyToMnemonic(keys.sk)); 18 | 19 | // pushing account to localstorage using json stringify 20 | let accountList = JSON.parse(localStorage.getItem("accountList")) || []; 21 | accountList.push({ 22 | address: keys.addr, 23 | mnemonic: algosdk.secretKeyToMnemonic(keys.sk) 24 | }); 25 | localStorage.setItem("accountList", JSON.stringify(accountList)); 26 | 27 | // redirecting to account page 28 | history.push("/account"); 29 | }; 30 | 31 | return ( 32 |
33 |
34 |
38 |
39 | 40 |
41 |
42 |
43 | 44 | Already have an account?{" "} 45 | 46 | Restore Account 47 | 48 | 49 |
50 |
51 |
52 | Powered by Algorand 53 |
54 |
55 |
56 | ); 57 | }; 58 | export default withRouter(CreateAccountPage); 59 | -------------------------------------------------------------------------------- /src/components/stateless/transactionrow.jsx: -------------------------------------------------------------------------------- 1 | import * as React from "react"; 2 | import algosicon from "../../assets/images/algorandicon.webp"; 3 | 4 | /** 5 | * This component will show account transaction list for the address 6 | * @props transactionId: string -> transaction id 7 | * @props amount: number -> amount sent (in Algos) 8 | * @props addressFrom: string -> address from where the pay is sent 9 | * @props addressTo: string -> address to where the pay is sent 10 | * @props note: string -> note added with the pay 11 | * 12 | * 13 | * @author [Mitrasish Mukherjee](https://github.com/mmitrasish) 14 | */ 15 | const TransactionRow = props => { 16 | return ( 17 |
18 |
19 |
20 | algos icon 26 |
27 |
28 |
29 |
30 |
31 | {props.transactionId.substr(0, 10)} 32 | ... 33 | {props.transactionId.substr(-5, 5)} 34 |
35 |
36 |
37 |
44 | {props.addressFrom === localStorage.getItem("address") 45 | ? -props.amount / 1000000 46 | : props.amount / 1000000}{" "} 47 | ALGOS 48 |
49 |
50 |
51 |
52 |
53 | from: 54 | 55 | {props.addressFrom.substr(0, 5)} 56 | ... 57 | {props.addressFrom.substr(-4, 4)} 58 | 59 |
60 |
61 | to: 62 | 63 | {props.addressTo.substr(0, 5)} 64 | ... 65 | {props.addressTo.substr(-4, 4)} 66 | 67 |
68 |
69 |
70 |
71 | note: 72 | {props.note} 73 |
74 |
75 |
76 |
77 |
78 | ); 79 | }; 80 | export default TransactionRow; 81 | -------------------------------------------------------------------------------- /src/components/pages/restoreaccountcomponent.jsx: -------------------------------------------------------------------------------- 1 | import * as React from "react"; 2 | import { withRouter, Link } from "react-router-dom"; 3 | import RestoreAccountButton from "../stateless/restoreaccountbutton"; 4 | 5 | /** 6 | * This component will restore your account given mnemonic 7 | * @state mnemonic: string -> store account mnemonic from textarea 8 | * 9 | * @author [Mitrasish Mukherjee](https://github.com/mmitrasish) 10 | */ 11 | class RestoreAccountPage extends React.Component { 12 | constructor(props) { 13 | super(props); 14 | this.state = { 15 | mnemonic: "" 16 | }; 17 | } 18 | 19 | // load mnemonic from user 20 | loadMnemonic = event => { 21 | this.setState({ mnemonic: event.target.value }); 22 | }; 23 | 24 | // getting the restored account keys from restoreaccountbutton component and pushing it to localstorage 25 | restoreAccount = keys => { 26 | console.log(keys); 27 | 28 | // adding to localstorage 29 | localStorage.setItem("address", keys.addr); 30 | localStorage.setItem("mnemonic", this.state.mnemonic); 31 | 32 | // pushing account to localstorage account list 33 | let accountList = JSON.parse(localStorage.getItem("accountList")) || []; 34 | accountList.push({ 35 | address: keys.addr, 36 | mnemonic: this.state.mnemonic 37 | }); 38 | localStorage.setItem("accountList", JSON.stringify(accountList)); 39 | 40 | // redirecting to account page 41 | this.props.history.push("/account"); 42 | }; 43 | 44 | render() { 45 | return ( 46 |
47 |
48 |
52 |
53 | 54 |