├── .babelrc ├── .circleci └── config.yml ├── .eslintrc ├── .gitignore ├── .nvmrc ├── .vscode └── extensions.json ├── CONTRIBUTING.md ├── LICENSE ├── README.md ├── TERMS-OF-USE.md ├── configs ├── default.env ├── devServer.config.js └── index.js ├── package-lock.json ├── package.json ├── src ├── App.js ├── App.scss ├── components │ ├── AccountUpdate.js │ ├── AccountUpdate.scss │ ├── AccountUpdateFD.js │ ├── AccountUpdateFDRatio.js │ ├── AddToken.js │ ├── AddToken.scss │ ├── Button.js │ ├── Button.scss │ ├── BytecodeExample.js │ ├── BytecodeExample.scss │ ├── Dropdown.js │ ├── Dropdown.scss │ ├── FeeDelegation.js │ ├── FeeDelegation.scss │ ├── GithubLink.js │ ├── GithubLink.scss │ ├── Input.js │ ├── Input.scss │ ├── Message.js │ ├── Message.scss │ ├── Nav.js │ ├── Nav.scss │ ├── SignMessage.js │ ├── SmartContractDeploy.js │ ├── SmartContractDeployFD.js │ ├── SmartContractDeployFDRatio.js │ ├── SmartContractDeployLegacy.js │ ├── SmartContractExecution.js │ ├── SmartContractExecutionFD.js │ ├── SmartContractExecutionFDRatio.js │ ├── SmartContractExecutionLegacy.js │ ├── TxResult.js │ ├── TxResult.scss │ ├── ValueTransfer.js │ ├── ValueTransferFD.js │ ├── ValueTransferFDRatio.js │ ├── ValueTransferLegacy.js │ ├── ValueTransferMemo.js │ ├── ValueTransferMemoFD.js │ ├── ValueTransferMemoFDRatio.js │ ├── WalletInfo.js │ └── WalletInfo.scss ├── constants │ ├── networks.js │ └── url.js ├── index.js ├── index.scss ├── klaytn │ └── caver.js ├── pages │ ├── KaikasPage.js │ └── KaikasPage.scss └── styles │ ├── _colors.scss │ ├── _fonts.scss │ ├── _mixins.scss │ ├── _sizes.scss │ └── _variables.scss ├── static ├── fonts │ ├── SFUIText-Bold.ttf │ ├── SFUIText-Light.ttf │ ├── SFUIText-Medium.ttf │ ├── SFUIText-Regular.ttf │ └── SFUIText-Semibold.ttf ├── images │ ├── favicon@16.png │ ├── ico-error.svg │ ├── ico-receipt.svg │ ├── icon-close.png │ ├── icon-downArrow.svg │ ├── icon-github.svg │ ├── icon-tx.svg │ ├── icon-upArrow.svg │ ├── icon-wallet.png │ ├── kaikas-tutorial-screen.png │ ├── klaytn-logo.png │ ├── logo-kaikas-tutorial.png │ └── logo.svg └── index.html ├── webpack.base.js ├── webpack.dev.js └── webpack.prod.js /.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": [ 3 | [ 4 | "@babel/preset-env", 5 | { 6 | "targets": { 7 | "ie": 10, 8 | } 9 | } 10 | ], 11 | "@babel/preset-react" 12 | ], 13 | "plugins": [ 14 | "@babel/plugin-proposal-class-properties", 15 | ] 16 | } 17 | -------------------------------------------------------------------------------- /.circleci/config.yml: -------------------------------------------------------------------------------- 1 | version: 2.1 2 | 3 | default: &defaults 4 | working_directory: ~/kaikas-tutorial 5 | docker: 6 | - image: circleci/node:10 7 | 8 | jobs: 9 | deploy: 10 | <<: *defaults 11 | steps: 12 | - checkout 13 | - restore_cache: 14 | keys: node_modules-{{ checksum "package-lock.json" }} 15 | - run: | 16 | npm install 17 | npm run build 18 | sudo apt-get install awscli 19 | aws s3 sync dist/ s3://$FRONTEND_BUCKET/dist 20 | - save_cache: 21 | key: node_modules-{{ checksum "package-lock.json" }} 22 | paths: 23 | - node_modules 24 | 25 | 26 | workflows: 27 | deploy: 28 | jobs: 29 | - deploy: 30 | filters: 31 | branches: 32 | only: master 33 | -------------------------------------------------------------------------------- /.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "globals": { 3 | "window": true, 4 | "document": true, 5 | "DEV": true, 6 | "DEPLOYED_ADDRESS": true, 7 | "artifacts": true, 8 | }, 9 | "parser": "babel-eslint", 10 | "extends": [ 11 | "eslint:recommended", 12 | "plugin:react/recommended", 13 | "airbnb" 14 | ], 15 | "rules": { 16 | "no-undef": "off", 17 | "arrow-parens": ["error", "always"], 18 | "comma-dangle": ["error", "always-multiline"], 19 | "global-require": 0, 20 | "func-names": 0, 21 | "function-paren-newline": 0, 22 | "semi": 0, 23 | "prefer-arrow-callback": 0, 24 | "eqeqeq": 0, 25 | "wrap-iife": 0, 26 | "no-unused-expressions": 0, 27 | "no-console": 0, 28 | "no-bitwise": 0, 29 | "no-plusplus": 0, 30 | "no-multi-assign": 0, 31 | "jsx-a11y/anchor-is-valid": 0, 32 | "jsx-a11y/no-static-element-interactions": 0, 33 | "jsx-a11y/click-events-have-key-events": 0, 34 | "jsx-a11y/alt-text": 0, 35 | "jsx-a11y/label-has-for": "off", 36 | "import/no-unresolved": false, 37 | "import/prefer-default-export": false, 38 | "import/extensions": false, 39 | "import/no-extraneous-dependencies": 0, 40 | "react/jsx-filename-extension": false, 41 | "react/prop-types": "off" 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | build/ 3 | dist/ -------------------------------------------------------------------------------- /.nvmrc: -------------------------------------------------------------------------------- 1 | 10 -------------------------------------------------------------------------------- /.vscode/extensions.json: -------------------------------------------------------------------------------- 1 | { 2 | // See http://go.microsoft.com/fwlink/?LinkId=827846 to learn about workspace recommendations. 3 | // Extension identifier format: ${publisher}.${name}. Example: vscode.csharp 4 | 5 | // List of extensions which should be recommended for users of this workspace. 6 | "recommendations": [ 7 | 8 | ], 9 | // List of extensions recommended by VS Code that should not be recommended for users of this workspace. 10 | "unwantedRecommendations": [ 11 | 12 | ] 13 | } -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing Guidelines 2 | 3 | Thank you for your interest in contributing to Kaikas Tutorial. As an open source project, Kaikas Tutorial is always open to the developer community and we welcome your contribution. Please read the guideline below and follow it in all interactions with the project. 4 | 5 | ## How to Contribute 6 | 7 | 1. Read this [contributing document](./CONTRIBUTING.md). 8 | 2. Sign [Contributor Licensing Agreement (CLA)](#contributor-license-agreement-cla). 9 | 3. Submit an issue with proper [labeling](#usage-of-labels). 10 | 4. Please wait until the label changes to `contribution welcome` - otherwise, it is not ready to be worked on. 11 | 5. After the label changed to `contribution welcome`, you can start working on the implementation. To avoid any duplicate efforts, it is recommended to update the issue so that other developers see someone working on the issue. 12 | 6. Before making a PR, please make sure you fully tested the code. It is highly recommended to provide the test code as well. After submitting the PR, wait for code review and approval. The reviewer may ask you for additional commits or changes. 13 | 7. Once the change has been approved, the PR is merged by the project moderator. 14 | 8. After merging the PR, we close the pull request. You can then delete the now obsolete branch. 15 | 16 | ## Types of Contribution 17 | There are various ways to contribute and participate. Please read the guidelines below regarding the process of each type of contribution. 18 | 19 | - [Issues and Bugs](#issues-and-bugs) 20 | - [Feature Requests](#feature-requests) 21 | - [Code Contribution](#code-contribution) 22 | 23 | ### Issues and Bugs 24 | 25 | If you find a bug or other issues in Kaikas Tutorial, please [submit an issue](https://github.com/klaytn/kaikas-tutorial/issues). Before submitting an issue, please invest some extra time to figure out that: 26 | 27 | - The issue is not a duplicate issue. 28 | - The issue has not been fixed in the latest release of Kaikas Tutorial. 29 | Please do not use the issue tracker for personal support requests. Use developer@klaytn.com for the personal support requests. 30 | 31 | When you report a bug, please make sure that your report has the following information. 32 | - Steps to reproduce the issue. 33 | - A clear and complete description of the issue. 34 | - Code and/or screen captures are highly recommended. 35 | 36 | After confirming your report meets the above criteria, [submit the issue](https://github.com/klaytn/kaikas-tutorial/issues). Please use [labels](#usage-of-labels) to categorize your issue. 37 | 38 | ### Feature Requests 39 | 40 | You can also use the [issue tracker](https://github.com/klaytn/kaikas-tutorial/issues) to request a new feature or enhancement. Note that any code contribution without an issue link will not be accepted. Please submit an issue explaining your proposal first so that Kaikas Tutorial community can fully understand and discuss the idea. Please use [labels](#usage-of-labels) for your feature request as well. 41 | 42 | #### Usage of Labels 43 | 44 | You can use the following labels: 45 | 46 | Labels for initial issue categories: 47 | 48 | - bug: Issues with the code-level bugs. 49 | - documentation: Issues with the documentation. 50 | - enhancement: Issues for enhancement requests. 51 | 52 | Status of open issues (will be tagged by the project moderators): 53 | 54 | - (no label): The default status. 55 | - need more information : The issue's creator needs to provide additional information to review. 56 | - reviewing: The issue is under review. 57 | - re-label needed: The label needs to be changed to confirmed as being a `bug` or future `enhancement`. 58 | - approved: The issue is confirmed as being a `bug` to be fixed or `enhancement` to be developed. 59 | - contribution welcome: The fix or enhancement is approved and you are invited to contribute to it. 60 | 61 | Status of closed issues: 62 | 63 | - fixed: A fix for the issue was provided. 64 | - duplicate: The issue is also reported in a different issue and is being managed there. 65 | - invalid: The issue cannot be reproduced. 66 | - reject: The issue is rejected after review. 67 | 68 | ### Code Contribution 69 | 70 | Please follow the coding style and quality requirements to satisfy the product standards. You must follow the coding style as best as you can when submitting code. Take note of naming conventions, separation of concerns, and formatting rules. 71 | 72 | ## Contributor License Agreement (CLA) 73 | 74 | Keep in mind when you submit your pull request, you'll need to sign the CLA via [CLA-Assistant](https://cla-assistant.io/klaytn/kaikas-tutorial) for legal purposes. You will have to sign the CLA just one time, either as an individual or corporation. 75 | 76 | You will be prompted to sign the agreement by CLA Assistant (bot) when you open a Pull Request for the first time. 77 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 Kaikas Tutorial Authors 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of 6 | this software and associated documentation files (the "Software"), to deal in 7 | the Software without restriction, including without limitation the rights to 8 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 9 | the Software, and to permit persons to whom the Software is furnished to do so, 10 | 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, FITNESS 17 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 18 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 19 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 20 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Notice 2 | The features on this repo are integrated into the https://github.com/klaytn/klaytn-online-toolkit. 3 | 4 | # Kaikas Tutorial 5 | 6 | > [tutorial.kaikas.io](tutorial.kaikas.io) 7 | 8 | ![kaikas-tutorial-screen](./static/images/kaikas-tutorial-screen.png) 9 | 10 | ### 1) Introduction 11 | Kaikas Tutorial is a reference BApp that works with Kaikas. You can send Klaytn's various types of transactions in the Kaikas tutorial and refer to the source code to create your BApp. 12 | 13 | ### 2) Getting started 14 | 1. Open terminal 15 | 2. Clone the repo by running `git clone https://github.com/klaytn/kaikas-tutorial.git` 16 | 3. `cd kaikas-tutorial` 17 | 4. Run `npm install` to install node packages 18 | 5. Run `npm run local` 19 | 6. App should be running on https://localhost:8888 20 | 21 | #### Builds the app for production 22 | 1. Run `npm run build` to build app 23 | 2. Run `npm start` 24 | 3. App should be running on https://localhost:5555 25 | 26 | 27 | ### 3) npm package information 28 | > dependencies 29 | ``` 30 | The Kaikas Tutorial project is optimized for caver-js version "1.3.2". 31 | caver-js needs confirmation before updating. 32 | ``` 33 | 34 | ### 4) Directory Structure 35 | > Folder structure 36 | ``` 37 | webpack.base.js // Base webpack settings 38 | webpack.dev.js // Settings for local development 39 | webpack.prod.js // Settings for build. (note: NODE_ENV= must be set to production) 40 | 41 | dist // Files built with 'npm run build' 42 | static // Contains static resources (index.html, images, font files etc...) 43 | 44 | 1. src 45 | src - pages // React page components 46 | src - components // React components 47 | src - constants // Constants used throughout the project 48 | src - klaytn // Klaytn related definition folder 49 | src - styles // Style util files. Contains color, size, font info and etc. as well as Sass at-rules 50 | index.js // Project build entry point. 51 | index.scss // .scss file for index.js mentioned above. 52 | ``` 53 | 54 | ### 5) Web browser support scope 55 | > Supported browsers. 56 | 57 | Chrome | Safari | Firefox | IE Edge* 58 | ---------------------- | ---------------------- | ---------------------- | ---------------------- 59 | Supported (Optimized) | Supported | Supported | Not supported 60 | 61 | ### 6) License 62 | Kaikas Tutorial is released under the [MIT license](./LICENSE). 63 | 64 | ``` 65 | MIT License 66 | 67 | Copyright (c) 2020 Kaikas Tutorial Authors 68 | 69 | Permission is hereby granted, free of charge, to any person obtaining a copy 70 | of this software and associated documentation files (the "Software"), to deal 71 | in the Software without restriction, including without limitation the rights 72 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 73 | copies of the Software, and to permit persons to whom the Software is 74 | furnished to do so, subject to the following conditions: 75 | 76 | The above copyright notice and this permission notice shall be included in 77 | all copies or substantial portions of the Software. 78 | 79 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 80 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 81 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 82 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 83 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 84 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 85 | THE SOFTWARE. 86 | ``` 87 | 88 | ### 7) Contributing 89 | 90 | As an open source project, Kaikas Tutorial is always welcoming your contribution. Please read our [CONTTIBUTING.md](./CONTRIBUTING.md) for a walk-through of the contribution process. 91 | -------------------------------------------------------------------------------- /TERMS-OF-USE.md: -------------------------------------------------------------------------------- 1 | # Terms of Use 2 | 3 | ## 1. Your Use of Open Source Software 4 | 5 | We may make (but are not obligated to make) the source code of Klaytn Blockchain Network Platform ("Platform"), the software on the Platform, etc. for download as open source software. If you use this open source software, you agree to be bound by and comply with any license that applies to this open source software. You will not indicate that you are associated with us in connection with your use, modifications or distributions of this open source software. 6 | 7 | ## 2. Services Provided on the Platform 8 | 9 | The Platform is a combination of peer-to-peer subnetworks of nodes transmitting transactions and blocks to execute value transfers and run smart contracts. The Core Cell Network ("CCN"), which is one of the subnetworks that constitute the Platform, verifies and executes transactions that occur on the Platform. The CCN is operated by Klaytn Governance Council, which is a collective group of Core Cell Operators, and Klaytn is not directly involved in any services that are provided in or individual transactions that occur on the Platform. 10 | 11 | ## 3. Your Installation of BApp on the Platform 12 | 13 | Your use of open source software is free of charge. However, you may be required to pay a certain number of KLAY as a transaction fee in order to execute a transaction on the Platform, including the installation of the BApp on the Platform. 14 | 15 | Once transaction is executed successfully and respective block generation is verified successfully by the Platform’s mechanism, the block is irreversibly stored in the blockchain. As such, your installation of the BApp and any other transactions on the Platform, as well as the submission of transaction fee is final and irrevocable. 16 | 17 | ## 4. User Content 18 | 19 | If you or the users of your BApp post, upload, input, provide or submit any content on the Platform (collectively, your "User Content"), you must ensure that the User Content provided by you or the users of your BApp at that or at any other time is true, accurate, up to date and complete and that any User Content you or the users of your BApp post, upload, input, provide or submit via the Platform do not breach or infringe legal rights of any third party. To the extent that is technically possible, you agree to prevent, remove or block access of any User Content that you or the users of your BApp post, upload, input, provide or submit via the Platform that violate or may violate legal rights (such as rights of privacy and publicity) of others or any applicable laws or regulations. We do not own, control or endorse any User Content that is transmitted, stored or processed via the Platform or sent to us and we are not responsible or liable for any User Content. We make no assurance that any of Your Content will be secured or that such content will remain confidential. 20 | 21 | You are solely responsible and liable for all of your User Content and for your use of any interactive features, links or information or content on the Platform, and you represent and warrant that (i) you own all intellectual property rights (or have obtained all necessary permissions) to provide your User Content and to grant the licenses in these Terms of Use; (ii) your User Content will not violate any agreements or confidentiality obligations; and (iii) your User Content will not violate, infringe or misappropriate any intellectual property right or other proprietary right, including the right of publicity or privacy, of any person or entity. 22 | 23 | You shall not include in User Content, or upload, transmit to or create or include in the Services environment any production data or any sensitive, proprietary, confidential or other data with particular data protection requirements such as personal data or personally identifiable information relating to an identified or identifiable natural person. 24 | 25 | You are prohibited from using the Platform to post or transmit any threatening, libellous, defamatory, obscene, scandalous, inflammatory, pornographic or profane material, any material that is contrary to applicable local, federal, or international laws and regulations, or any material that could constitute or encourage unlawful conduct. You must ensure that your User Content do not include such materials. We may from time to time monitor or review material transmitted or posted using the Network, and we reserve the right to delete any material we deem inappropriate. 26 | 27 | We are under no obligation to do so and assume no responsibility or liability arising from any material transmitted or posted using the Platform. 28 | 29 | You understand that any information you or users of your BApp upload to the Platform will be distributed among the blockchain nodes and may not removable due to technical limitations of the blockchain technology. 30 | 31 | You are entirely responsible for any and all activities that occur under your account or your BApp (if any). You agree to notify us immediately of any unauthorized use of your User Content, your BApp or account or any other breach of security. We will not be liable for any loss or damages that you may incur as a result of someone else using your User Content, your BApp or account, either with or without your knowledge. However, you could be held liable for losses incurred by us or another party due to someone else using your User Content, your BApp or account. You may not use anyone else’s User Content, your BApp or account at any time without the permission of such person or entity. 32 | 33 | By posting, uploading, inputting, providing or submitting your User Content to the Platform, you grant to participants of the Platform and any necessary sub-licensees a non-exclusive, worldwide, perpetual, right and permission to use, reproduce, copy, edit, modify, translate, reformat, create derivative works from, distribute, transmit, publicly perform and publicly display your User Content and sub-license such rights to others. 34 | 35 | If we have reason to believe that there is likely to be a breach of security, breach or misuse of the Platform or if you breach any of your obligations under these terms, we may suspend your use of the Platform at any time and for any reason. 36 | -------------------------------------------------------------------------------- /configs/default.env: -------------------------------------------------------------------------------- 1 | PORT=8888 2 | API_HOST='http://localhost' 3 | API_PORT='8888' 4 | -------------------------------------------------------------------------------- /configs/devServer.config.js: -------------------------------------------------------------------------------- 1 | const path = require('path') 2 | 3 | module.exports = { 4 | contentBase: path.resolve(__dirname, '../static'), 5 | host: '0.0.0.0', 6 | port: 8888, 7 | compress: true, 8 | historyApiFallback: true, 9 | hot: true, 10 | inline: true, 11 | open: true, 12 | } 13 | -------------------------------------------------------------------------------- /configs/index.js: -------------------------------------------------------------------------------- 1 | 2 | const path = require('path') 3 | const dotenv = require('dotenv') 4 | 5 | const envFilename = process.env.ENV_FILENAME || '' 6 | const envPath = path.resolve(__dirname, `${envFilename}.env`) 7 | const defaultEnvPath = path.resolve(__dirname, 'default.env') 8 | 9 | // load system env -> .env -> default.env 10 | dotenv.config({ path: envPath }); 11 | dotenv.config({ path: defaultEnvPath }); 12 | 13 | module.exports = { 14 | envPath, 15 | defaultEnvPath, 16 | } 17 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "kaikas-tutorial", 3 | "version": "1.0.0", 4 | "description": "Kaikas Reference BApp", 5 | "main": "index.js", 6 | "author": "developer@klaytn.com", 7 | "license": "MIT", 8 | "scripts": { 9 | "build": "webpack --config ./webpack.prod.js", 10 | "start": "serve ./dist -p 5555", 11 | "local": "webpack-dev-server --config webpack.dev.js" 12 | }, 13 | "repository": { 14 | "type": "git" 15 | }, 16 | "dependencies": { 17 | "caver-js": "^1.3.2", 18 | "classnames": "^2.2.6", 19 | "dotenv": "^8.0.0", 20 | "dotenv-webpack": "^1.7.0", 21 | "git-revision-webpack-plugin": "^3.0.4", 22 | "lodash": "^4.17.15", 23 | "mini-css-extract-plugin": "^0.9.0", 24 | "optimize-css-assets-webpack-plugin": "^5.0.3", 25 | "react": "^16.8.6", 26 | "react-dom": "^16.8.6", 27 | "serve": "^11.3.0", 28 | "webpack-merge": "^4.2.2" 29 | }, 30 | "devDependencies": { 31 | "@babel/core": "^7.5.5", 32 | "@babel/plugin-proposal-class-properties": "^7.5.5", 33 | "@babel/polyfill": "^7.4.4", 34 | "@babel/preset-env": "^7.5.5", 35 | "@babel/preset-react": "^7.0.0", 36 | "@babel/register": "^7.5.5", 37 | "babel-eslint": "^10.0.2", 38 | "babel-loader": "^8.0.6", 39 | "clean-webpack-plugin": "^1.0.0", 40 | "compression-webpack-plugin": "^3.0.0", 41 | "copy-webpack-plugin": "^5.0.3", 42 | "css-loader": "^3.1.0", 43 | "eslint": "^6.1.0", 44 | "eslint-config-airbnb": "^17.1.1", 45 | "eslint-plugin-import": "^2.18.2", 46 | "eslint-plugin-jsx-a11y": "^6.2.3", 47 | "eslint-plugin-react": "^7.14.3", 48 | "extract-text-webpack-plugin": "^4.0.0-beta.0", 49 | "html-webpack-plugin": "^3.2.0", 50 | "node-sass": "^4.12.0", 51 | "opn": "^6.0.0", 52 | "react-hot-loader": "^4.12.9", 53 | "redux-devtools-extension": "^2.13.8", 54 | "sass-loader": "^7.1.0", 55 | "style-loader": "^0.23.1", 56 | "uglifyjs-webpack-plugin": "^2.1.3", 57 | "webpack": "^4.37.0", 58 | "webpack-cli": "^3.3.6", 59 | "webpack-dev-middleware": "^3.7.0", 60 | "webpack-dev-server": "^3.7.2", 61 | "webpack-hot-middleware": "^2.25.0" 62 | }, 63 | "eslintConfig": { 64 | "env": { 65 | "browser": true, 66 | "node": true 67 | } 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /src/App.js: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import KaikasPage from 'pages/KaikasPage' 3 | 4 | import './App.scss' 5 | 6 | const App = () => { 7 | return ( 8 |
9 | 10 |
11 | ) 12 | } 13 | 14 | export default App 15 | -------------------------------------------------------------------------------- /src/App.scss: -------------------------------------------------------------------------------- 1 | .App { 2 | position: relative; 3 | width: 100%; 4 | height: 1px; 5 | min-width: 414px; 6 | min-height: 100%; 7 | } 8 | -------------------------------------------------------------------------------- /src/components/AccountUpdate.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react' 2 | import caver from 'klaytn/caver' 3 | import Input from 'components/Input' 4 | import Button from 'components/Button' 5 | import TxResult from 'components/TxResult' 6 | 7 | import './AccountUpdate.scss' 8 | 9 | class AccountUpdate extends Component { 10 | constructor(props) { 11 | super(props) 12 | this.state = { 13 | from: props.from, 14 | publicKey: '', 15 | walletKey: '', 16 | gas: 3000000, 17 | txHash: null, 18 | receipt: null, 19 | error: null, 20 | } 21 | } 22 | 23 | static getDerivedStateFromProps = (nextProps, prevState) => { 24 | if (nextProps.from !== prevState.from) { 25 | return { from: nextProps.from } 26 | } 27 | return null 28 | } 29 | 30 | handleChange = (e) => { 31 | this.setState({ 32 | [e.target.name]: e.target.value, 33 | }) 34 | } 35 | 36 | handleGenerateKeypair = () => { 37 | const { privateKey } = caver.klay.accounts.create() 38 | const publicKey = caver.klay.accounts.privateKeyToPublicKey(privateKey) 39 | const walletKey = `${privateKey}0x00${this.state.from}` 40 | this.setState({ publicKey, walletKey }) 41 | } 42 | 43 | signTransaction = () => { 44 | const { from, gas, publicKey } = this.state 45 | 46 | caver.klay.sendTransaction({ 47 | type: 'ACCOUNT_UPDATE', 48 | from, 49 | publicKey, 50 | gas, 51 | }) 52 | .once('transactionHash', (transactionHash) => { 53 | console.log('txHash', transactionHash) 54 | this.setState({ txHash: transactionHash }) 55 | }) 56 | .once('receipt', (receipt) => { 57 | console.log('receipt', receipt) 58 | this.setState({ receipt: JSON.stringify(receipt) }) 59 | }) 60 | .once('error', (error) => { 61 | console.log('error', error) 62 | this.setState({ error: error.message }) 63 | }) 64 | } 65 | 66 | render() { 67 | const { from, publicKey, walletKey, gas, txHash, receipt, error } = this.state 68 | 69 | return ( 70 |
71 |
72 |
85 |
86 | 93 | 100 | 107 |
112 | 117 |
118 | ) 119 | } 120 | } 121 | 122 | export default AccountUpdate 123 | -------------------------------------------------------------------------------- /src/components/AccountUpdate.scss: -------------------------------------------------------------------------------- 1 | .AccountUpdate { 2 | margin-bottom: 30px; 3 | } 4 | 5 | .AccountUpdate__generateKeypair { 6 | margin-bottom: 30px; 7 | padding: 20px; 8 | border: 1px solid $middle-grey; 9 | border-radius: 10px; 10 | 11 | & > .Input { margin-bottom: 0; } 12 | } 13 | 14 | .AccountUpdate__generateButton { 15 | margin-bottom: 10px; 16 | } 17 | -------------------------------------------------------------------------------- /src/components/AccountUpdateFD.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react' 2 | import caver from 'klaytn/caver' 3 | import Input from 'components/Input' 4 | import Button from 'components/Button' 5 | import Message from 'components/Message' 6 | import FeeDelegation from './FeeDelegation'; 7 | 8 | import './AccountUpdate.scss' 9 | 10 | class AccountUpdateFD extends Component { 11 | constructor(props) { 12 | super(props) 13 | this.state = { 14 | from: props.from, 15 | publicKey: '', 16 | walletKey: '', 17 | gas: 3000000, 18 | senderRawTransaction: null, 19 | } 20 | } 21 | 22 | static getDerivedStateFromProps = (nextProps, prevState) => { 23 | if (nextProps.from !== prevState.from) { 24 | return { from: nextProps.from } 25 | } 26 | return null 27 | } 28 | 29 | handleChange = (e) => { 30 | this.setState({ 31 | [e.target.name]: e.target.value, 32 | }) 33 | } 34 | 35 | handleGenerateKeypair = () => { 36 | const { privateKey } = caver.klay.accounts.create() 37 | const publicKey = caver.klay.accounts.privateKeyToPublicKey(privateKey) 38 | const walletKey = `${privateKey}0x00${this.state.from}` 39 | this.setState({ publicKey, walletKey }) 40 | } 41 | 42 | signTransaction = async () => { 43 | const { from, publicKey, gas } = this.state 44 | 45 | const txData = { 46 | type: 'FEE_DELEGATED_ACCOUNT_UPDATE', 47 | from, 48 | publicKey, 49 | gas, 50 | } 51 | 52 | const { rawTransaction: senderRawTransaction } = await caver.klay.signTransaction(txData) 53 | 54 | this.setState({ 55 | senderAddress: from, 56 | senderRawTransaction, 57 | }) 58 | } 59 | 60 | render() { 61 | const { from, publicKey, walletKey, ratio, gas, senderRawTransaction } = this.state 62 | 63 | return ( 64 |
65 |
66 |
79 |
80 | 87 | 94 | 101 |
112 | 116 |
117 | ) 118 | } 119 | } 120 | 121 | export default AccountUpdateFD 122 | -------------------------------------------------------------------------------- /src/components/AccountUpdateFDRatio.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react' 2 | import caver from 'klaytn/caver' 3 | import Input from 'components/Input' 4 | import Button from 'components/Button' 5 | import Message from 'components/Message' 6 | import FeeDelegation from './FeeDelegation'; 7 | 8 | import './AccountUpdate.scss' 9 | 10 | class AccountUpdateFDRatio extends Component { 11 | constructor(props) { 12 | super(props) 13 | this.state = { 14 | from: props.from, 15 | publicKey: '', 16 | walletKey: '', 17 | ratio: '', 18 | gas: 3000000, 19 | senderRawTransaction: null, 20 | } 21 | } 22 | 23 | static getDerivedStateFromProps = (nextProps, prevState) => { 24 | if (nextProps.from !== prevState.from) { 25 | return { from: nextProps.from } 26 | } 27 | return null 28 | } 29 | 30 | handleChange = (e) => { 31 | this.setState({ 32 | [e.target.name]: e.target.value, 33 | }) 34 | } 35 | 36 | handleGenerateKeypair = () => { 37 | const { privateKey } = caver.klay.accounts.create() 38 | const publicKey = caver.klay.accounts.privateKeyToPublicKey(privateKey) 39 | const walletKey = `${privateKey}0x00${this.state.from}` 40 | this.setState({ publicKey, walletKey }) 41 | } 42 | 43 | signTransaction = async () => { 44 | const { from, publicKey, ratio, gas } = this.state 45 | 46 | const txData = { 47 | type: 'FEE_DELEGATED_ACCOUNT_UPDATE_WITH_RATIO', 48 | from, 49 | publicKey, 50 | feeRatio: ratio, 51 | gas, 52 | } 53 | 54 | const { rawTransaction: senderRawTransaction } = await caver.klay.signTransaction(txData) 55 | 56 | this.setState({ 57 | senderAddress: from, 58 | senderRawTransaction, 59 | }) 60 | } 61 | 62 | render() { 63 | const { from, publicKey, walletKey, ratio, gas, senderRawTransaction } = this.state 64 | 65 | return ( 66 |
67 |
68 |
81 |
82 | 89 | 96 | 103 | 110 |
121 | 125 |
126 | ) 127 | } 128 | } 129 | 130 | export default AccountUpdateFDRatio 131 | -------------------------------------------------------------------------------- /src/components/AddToken.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react' 2 | import Input from 'components/Input' 3 | import Button from 'components/Button' 4 | 5 | import './AddToken.scss' 6 | 7 | const BongToken = { 8 | tokenAddress: '0xEa51fb63dD8cfc8574BB158054D86CA786e00F87', 9 | tokenSymbol: 'BONG', 10 | tokenDecimals: 18, 11 | tokenImage: 'https://avatars3.githubusercontent.com/u/32095134?s=460&v=4', 12 | } 13 | class AddToken extends Component { 14 | state = { 15 | tokenAddress: '', 16 | tokenSymbol: '', 17 | tokenDecimals: '', 18 | tokenImage: '', 19 | } 20 | 21 | handleChange = (e) => { 22 | this.setState({ 23 | [e.target.name]: e.target.value, 24 | }) 25 | } 26 | 27 | handleAddToken = () => { 28 | const { tokenAddress, tokenSymbol, tokenDecimals, tokenImage } = this.state 29 | klaytn.sendAsync({ 30 | method: 'wallet_watchAsset', 31 | params: { 32 | type: 'ERC20', 33 | options: { 34 | address: tokenAddress, 35 | symbol: tokenSymbol, 36 | decimals: tokenDecimals, 37 | image: tokenImage, 38 | }, 39 | }, 40 | id: Math.round(Math.random() * 100000), 41 | }, (err, result) => console.log(err, result)) 42 | } 43 | 44 | addExampleToken = () => { 45 | const { tokenAddress, tokenSymbol, tokenDecimals, tokenImage } = BongToken 46 | this.setState({ 47 | tokenAddress, 48 | tokenSymbol, 49 | tokenDecimals, 50 | tokenImage, 51 | }, () => this.handleAddToken()) 52 | } 53 | 54 | render() { 55 | const { tokenAddress, tokenSymbol, tokenDecimals, tokenImage } = this.state 56 | return ( 57 |
58 |
59 |

# Sample Token

60 |
61 | BongToken image 66 |
67 |

{`BongToken (${BongToken.tokenSymbol})`}

68 |

{BongToken.tokenAddress}

69 |

{`Decimals: ${BongToken.tokenDecimals}`}

70 |
75 |
76 |
77 |
78 |

# Custom Token

79 | 86 | 93 | 100 | 107 |
112 |
113 | ) 114 | } 115 | } 116 | 117 | export default AddToken 118 | -------------------------------------------------------------------------------- /src/components/AddToken.scss: -------------------------------------------------------------------------------- 1 | .AddToken { 2 | .Input { margin-bottom: 10px; } 3 | } 4 | 5 | .AddToken__section { 6 | &:first-child { 7 | margin-bottom: 25px; 8 | padding-bottom: 25px; 9 | border-bottom: 1px solid $light-grey; 10 | } 11 | } 12 | 13 | .AddToken__title { 14 | color: $brownish-grey; 15 | margin-bottom: 15px; 16 | } 17 | 18 | .AddToken__sample { 19 | width: 530px; 20 | padding: 15px; 21 | line-height: 1.5; 22 | border: 1px solid $light-grey; 23 | border-radius: 5px; 24 | @include clear-both(); 25 | } 26 | 27 | .AddToken__sampleImage { 28 | float: left; 29 | width: 50px; 30 | margin-right: 10px; 31 | border-radius: 50%; 32 | } 33 | 34 | .AddToken__sampleContent { 35 | float: right; 36 | } 37 | 38 | .AddToken__sampleName { 39 | font-size: 20px; 40 | font-weight: bold; 41 | color: $dark-brown; 42 | } 43 | 44 | .AddToken__sampleAddress { 45 | font-size: 16px; 46 | font-weight: bold; 47 | color: $brown-grey; 48 | } 49 | 50 | .AddToken__sampleDecimals { 51 | font-size: 12px; 52 | color: $brown-grey; 53 | margin-bottom: 10px; 54 | } 55 | -------------------------------------------------------------------------------- /src/components/Button.js: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import cx from 'classnames' 3 | 4 | import './Button.scss' 5 | 6 | const Button = ({ 7 | className, 8 | title, 9 | onClick, 10 | icon, 11 | disabled, 12 | }) => { 13 | const iconStyle = { 14 | paddingLeft: '18px', 15 | background: `left / 12px no-repeat url('/images/${icon}')`, 16 | } 17 | 18 | return ( 19 | 28 | ) 29 | } 30 | 31 | export default Button 32 | -------------------------------------------------------------------------------- /src/components/Button.scss: -------------------------------------------------------------------------------- 1 | .Button { 2 | -webkit-appearance: none; 3 | width: 100%; 4 | background-color: $light-grey; 5 | color: $brown-grey; 6 | border-radius: 5px; 7 | text-align: center; 8 | font-size: 12px; 9 | font-weight: bold; 10 | padding: 23px; 11 | cursor: pointer; 12 | outline: none; 13 | 14 | &:hover, 15 | &:active { 16 | background-color: $dark-brown; 17 | color: $white; 18 | } 19 | } -------------------------------------------------------------------------------- /src/components/BytecodeExample.js: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import './BytecodeExample.scss' 3 | 4 | const BytecodeExample = ({ network }) => ( 5 |
6 |

# bytecode example (GX Token contract)

7 |

Copy and Paste bytecode into data field. Deploy 9999 GroundX Tokens!

8 |
9 | 0x60806040523480156200001157600080fd5b506040516200141b3803806200141b833981018060405260808110156200003757600080fd5b8101908080516401000000008111156200005057600080fd5b828101905060208101848111156200006757600080fd5b81518560018202830111640100000000821117156200008557600080fd5b50509291906020018051640100000000811115620000a257600080fd5b82810190506020810184811115620000b957600080fd5b8151856001820283011164010000000082111715620000d757600080fd5b5050929190602001805190602001909291908051906020019092919050505083600390805190602001906200010e929190620003c9565b50826004908051906020019062000127929190620003c9565b5081600560006101000a81548160ff021916908360ff1602179055506200016c33600560009054906101000a900460ff1660ff16600a0a83026200017660201b60201c565b5050505062000478565b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1614156200021a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601f8152602001807f45524332303a206d696e7420746f20746865207a65726f20616464726573730081525060200191505060405180910390fd5b62000236816002546200034060201b62000e511790919060201c565b60028190555062000294816000808573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020546200034060201b62000e511790919060201c565b6000808473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055508173ffffffffffffffffffffffffffffffffffffffff16600073ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef836040518082815260200191505060405180910390a35050565b600080828401905083811015620003bf576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601b8152602001807f536166654d6174683a206164646974696f6e206f766572666c6f77000000000081525060200191505060405180910390fd5b8091505092915050565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f106200040c57805160ff19168380011785556200043d565b828001600101855582156200043d579182015b828111156200043c5782518255916020019190600101906200041f565b5b5090506200044c919062000450565b5090565b6200047591905b808211156200047157600081600090555060010162000457565b5090565b90565b610f9380620004886000396000f3fe608060405234801561001057600080fd5b50600436106100a95760003560e01c80633950935111610071578063395093511461025f57806370a08231146102c557806395d89b411461031d578063a457c2d7146103a0578063a9059cbb14610406578063dd62ed3e1461046c576100a9565b806306fdde03146100ae578063095ea7b31461013157806318160ddd1461019757806323b872dd146101b5578063313ce5671461023b575b600080fd5b6100b66104e4565b6040518080602001828103825283818151815260200191508051906020019080838360005b838110156100f65780820151818401526020810190506100db565b50505050905090810190601f1680156101235780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b61017d6004803603604081101561014757600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190505050610582565b604051808215151515815260200191505060405180910390f35b61019f610599565b6040518082815260200191505060405180910390f35b610221600480360360608110156101cb57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803590602001909291905050506105a3565b604051808215151515815260200191505060405180910390f35b610243610654565b604051808260ff1660ff16815260200191505060405180910390f35b6102ab6004803603604081101561027557600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190505050610667565b604051808215151515815260200191505060405180910390f35b610307600480360360208110156102db57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919050505061070c565b6040518082815260200191505060405180910390f35b610325610754565b6040518080602001828103825283818151815260200191508051906020019080838360005b8381101561036557808201518184015260208101905061034a565b50505050905090810190601f1680156103925780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b6103ec600480360360408110156103b657600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803590602001909291905050506107f2565b604051808215151515815260200191505060405180910390f35b6104526004803603604081101561041c57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190505050610897565b604051808215151515815260200191505060405180910390f35b6104ce6004803603604081101561048257600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff1690602001909291905050506108ae565b6040518082815260200191505060405180910390f35b60038054600181600116156101000203166002900480601f01602080910402602001604051908101604052809291908181526020018280546001816001161561010002031660029004801561057a5780601f1061054f5761010080835404028352916020019161057a565b820191906000526020600020905b81548152906001019060200180831161055d57829003601f168201915b505050505081565b600061058f338484610935565b6001905092915050565b6000600254905090565b60006105b0848484610b2c565b610649843361064485600160008a73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054610dc890919063ffffffff16565b610935565b600190509392505050565b600560009054906101000a900460ff1681565b600061070233846106fd85600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008973ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054610e5190919063ffffffff16565b610935565b6001905092915050565b60008060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020549050919050565b60048054600181600116156101000203166002900480601f0160208091040260200160405190810160405280929190818152602001828054600181600116156101000203166002900480156107ea5780601f106107bf576101008083540402835291602001916107ea565b820191906000526020600020905b8154815290600101906020018083116107cd57829003601f168201915b505050505081565b600061088d338461088885600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008973ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054610dc890919063ffffffff16565b610935565b6001905092915050565b60006108a4338484610b2c565b6001905092915050565b6000600160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054905092915050565b600073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1614156109bb576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526024815260200180610f446024913960400191505060405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff161415610a41576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526022815260200180610efd6022913960400191505060405180910390fd5b80600160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055508173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925836040518082815260200191505060405180910390a3505050565b600073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff161415610bb2576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526025815260200180610f1f6025913960400191505060405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff161415610c38576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526023815260200180610eda6023913960400191505060405180910390fd5b610c89816000808673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054610dc890919063ffffffff16565b6000808573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002081905550610d1c816000808573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054610e5190919063ffffffff16565b6000808473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055508173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef836040518082815260200191505060405180910390a3505050565b600082821115610e40576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601e8152602001807f536166654d6174683a207375627472616374696f6e206f766572666c6f77000081525060200191505060405180910390fd5b600082840390508091505092915050565b600080828401905083811015610ecf576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601b8152602001807f536166654d6174683a206164646974696f6e206f766572666c6f77000000000081525060200191505060405180910390fd5b809150509291505056fe45524332303a207472616e7366657220746f20746865207a65726f206164647265737345524332303a20617070726f766520746f20746865207a65726f206164647265737345524332303a207472616e736665722066726f6d20746865207a65726f206164647265737345524332303a20617070726f76652066726f6d20746865207a65726f2061646472657373a165627a7a723058202a10b39ea88b3c0eb48f5612d90a75e7ed5eeef2ac4cff2306e32940f8e220c30029000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000c00000000000000000000000000000000000000000000000000000000000000012000000000000000000000000000000000000000000000000000000000000270f000000000000000000000000000000000000000000000000000000000000000d47726f756e645820546f6b656e0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000024758000000000000000000000000000000000000000000000000000000000000 10 |
11 |
12 | ) 13 | 14 | export default BytecodeExample 15 | -------------------------------------------------------------------------------- /src/components/BytecodeExample.scss: -------------------------------------------------------------------------------- 1 | .BytecodeExample { 2 | padding: 20px 15px; 3 | margin-bottom: 20px; 4 | border: 1px solid #e1e1e1; 5 | border-radius: 5px; 6 | 7 | h3 { 8 | color: #707070; 9 | margin-bottom: 15px; 10 | } 11 | 12 | p { 13 | color: #999999; 14 | margin-bottom: 10px; 15 | } 16 | 17 | &__code { 18 | width: 100%; 19 | height: 70px; 20 | padding: 10px; 21 | background-color: #eaeaea; 22 | border-radius: 5px; 23 | word-break: break-all; 24 | overflow: scroll; 25 | } 26 | } -------------------------------------------------------------------------------- /src/components/Dropdown.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react' 2 | import cx from 'classnames' 3 | 4 | import './Dropdown.scss' 5 | 6 | class Dropdown extends Component { 7 | constructor(props) { 8 | super(props); 9 | this.setWrapperRef = this.setWrapperRef.bind(this); 10 | this.handleClickOutside = this.handleClickOutside.bind(this); 11 | } 12 | 13 | state = { 14 | isShow: false, 15 | } 16 | 17 | setWrapperRef(node) { 18 | this.wrapperRef = node; 19 | } 20 | 21 | componentDidMount() { 22 | document.addEventListener('mousedown', this.handleClickOutside); 23 | } 24 | 25 | componentWillUnmount() { 26 | document.removeEventListener('mousedown', this.handleClickOutside); 27 | } 28 | 29 | handleToggle = () => this.setState({ isShow: !this.state.isShow }) 30 | 31 | handleClose = () => this.setState({ isShow: false }) 32 | 33 | handleSelect = (item) => { 34 | this.props.handleSelect(item) 35 | this.handleClose() 36 | } 37 | 38 | handleClickOutside(event) { 39 | if (this.wrapperRef && !this.wrapperRef.contains(event.target)) { 40 | this.handleClose() 41 | } 42 | } 43 | 44 | render() { 45 | const { placeholder, list, className, selectedItem } = this.props 46 | const { isShow } = this.state 47 | 48 | return ( 49 |
55 |
59 | {selectedItem || placeholder} 60 |
61 | {isShow && 62 |
63 | {list.map((item) => ( 64 |
this.handleSelect(item)} 68 | > 69 | {item} 70 |
71 | ))} 72 |
73 | } 74 |
75 | ) 76 | } 77 | } 78 | 79 | export default Dropdown 80 | -------------------------------------------------------------------------------- /src/components/Dropdown.scss: -------------------------------------------------------------------------------- 1 | .Dropdown { 2 | position: relative; 3 | text-align: left; 4 | color: $brown-grey; 5 | cursor: pointer; 6 | @include font-style('font-3'); 7 | } 8 | 9 | .Dropdown__title { 10 | position: relative; 11 | color: $dark-brown; 12 | text-align: center; 13 | font-size: 16px; 14 | padding: 15px 24px 14px; 15 | border-radius: 3px; 16 | border: 1px solid $light-grey; 17 | background-color: white; 18 | 19 | &::after { 20 | content:""; 21 | position: absolute; 22 | top: 18px; 23 | right: 16px; 24 | display: inline-block; 25 | width: 12px; 26 | height: 12px; 27 | background: center / contain no-repeat url('/images/icon-downArrow.svg'); 28 | } 29 | 30 | .Dropdown--active &::after { 31 | background: center / contain no-repeat url('/images/icon-upArrow.svg'); 32 | } 33 | } 34 | 35 | .Dropdown__list { 36 | position: absolute; 37 | padding: 12px 0; 38 | border-bottom-left-radius: 3px; 39 | border-bottom-right-radius: 3px; 40 | background-color: #fff; 41 | box-shadow: 0 4px 4px 0 rgba(0, 0, 0, 0.08); 42 | 43 | width: 100%; 44 | border: 1px solid $light-grey; 45 | border-radius: 3px; 46 | z-index: 10; 47 | } 48 | 49 | .Dropdown__listItem { 50 | text-align: left; 51 | padding: 16px 24px 15px; 52 | 53 | &:hover { 54 | color: $dark-brown; 55 | background-color: $light-grey; 56 | } 57 | &:nth-child(4) { border-top: 1px solid $light-grey; } 58 | &:nth-child(6) { border-top: 1px solid $light-grey; } 59 | &:nth-child(9) { border-top: 1px solid $light-grey; } 60 | &:nth-child(12) { border-top: 1px solid $light-grey; } 61 | &:nth-child(15) { border-top: 1px solid $light-grey; } 62 | &:nth-child(18) { border-top: 1px solid $light-grey; } 63 | 64 | &--white { 65 | color: $brown-grey; 66 | text-align: center; 67 | &:hover { 68 | background-color: $brown-grey; 69 | } 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /src/components/FeeDelegation.js: -------------------------------------------------------------------------------- 1 | import React, { PureComponent } from 'react' 2 | import Caver from 'caver-js' 3 | import Input from 'components/Input' 4 | import Button from 'components/Button' 5 | import TxResult from 'components/TxResult' 6 | 7 | import './FeeDelegation.scss' 8 | 9 | class FeeDelegation extends PureComponent { 10 | constructor(props) { 11 | super(props) 12 | this.state = { 13 | feePayerAddress: props.feePayerAddress, 14 | txHash: null, 15 | receipt: null, 16 | error: null, 17 | } 18 | } 19 | 20 | static getDerivedStateFromProps = (nextProps, prevState) => { 21 | if (nextProps.feePayerAddress !== prevState.feePayerAddress) { 22 | return { feePayerAddress: nextProps.feePayerAddress } 23 | } 24 | return null 25 | } 26 | 27 | handleChange = (e) => { 28 | this.setState({ 29 | [e.target.name]: e.target.value, 30 | }) 31 | } 32 | 33 | sendTransaction = () => { 34 | const { feePayerAddress } = this.state 35 | const caver = new Caver(window.klaytn) 36 | caver.klay.sendTransaction({ 37 | senderRawTransaction: this.props.senderRawTransaction, 38 | feePayer: feePayerAddress, 39 | }) 40 | .once('transactionHash', (transactionHash) => { 41 | console.log('txHash', transactionHash) 42 | this.setState({ txHash: transactionHash }) 43 | }) 44 | .once('receipt', (receipt) => { 45 | console.log('receipt', receipt) 46 | this.setState({ receipt: JSON.stringify(receipt) }) 47 | }) 48 | .once('error', (error) => { 49 | console.log('error', error) 50 | this.setState({ error: error.message }) 51 | }) 52 | } 53 | 54 | render() { 55 | const { feePayerAddress, txHash, receipt, error } = this.state 56 | return ( 57 |
58 |

Fee Payer

59 | 66 |
76 | ) 77 | } 78 | } 79 | 80 | export default FeeDelegation -------------------------------------------------------------------------------- /src/components/FeeDelegation.scss: -------------------------------------------------------------------------------- 1 | .FeeDelegation { 2 | padding-top: 20px; 3 | margin-top: 20px; 4 | border-top: 1px dashed #ccc; 5 | } 6 | -------------------------------------------------------------------------------- /src/components/GithubLink.js: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import './GithubLink.scss' 3 | 4 | const GithubLink = ({ className, component }) => ( 5 | 11 | View source code 12 | 13 | ) 14 | 15 | export default GithubLink 16 | -------------------------------------------------------------------------------- /src/components/GithubLink.scss: -------------------------------------------------------------------------------- 1 | .GithubLink { 2 | display: inline-block; 3 | width: 120px; 4 | margin-left: 8px; 5 | color: $brown-grey; 6 | text-align: right; 7 | font-size: 12px; 8 | cursor: pointer; 9 | 10 | &:hover { text-decoration: underline; } 11 | 12 | &::before { 13 | content: ''; 14 | display: inline-block; 15 | width: 12px; 16 | height: 12px; 17 | vertical-align: text-top; 18 | margin-right: 3px; 19 | background: center / 12px no-repeat url('/images/icon-github.svg'); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/components/Input.js: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import cx from 'classnames' 3 | 4 | import './Input.scss' 5 | 6 | const Input = ({ 7 | className, 8 | type, 9 | name, 10 | label, 11 | value, 12 | onChange, 13 | placeholder, 14 | err, 15 | readOnly, 16 | }) => ( 17 |
18 | { 19 | label && 20 | 23 | } 24 | 40 | { 41 | err && 42 |

{err}

43 | } 44 |
45 | ) 46 | 47 | export default Input 48 | -------------------------------------------------------------------------------- /src/components/Input.scss: -------------------------------------------------------------------------------- 1 | .Input { 2 | position: relative; 3 | margin-bottom: 10px; 4 | } 5 | 6 | .Input__label { 7 | display: block; 8 | font-size: 12px; 9 | font-weight: bold; 10 | color: $brown-grey; 11 | margin-bottom: 8px; 12 | } 13 | 14 | .Input__input { 15 | width: 100%; 16 | font-size: 14px; 17 | border: 1px solid $light-grey; 18 | padding: 22px 24px; 19 | border-radius: 5px; 20 | 21 | &::placeholder { color: $middle-grey; } 22 | &--err { border-color: $alert-red; } 23 | &--readOnly { 24 | color: $middle-grey; 25 | } 26 | } 27 | 28 | .Input__err { 29 | position: absolute; 30 | top: 0; 31 | right: 0; 32 | font-size: 12px; 33 | color: $alert-red; 34 | } 35 | -------------------------------------------------------------------------------- /src/components/Message.js: -------------------------------------------------------------------------------- 1 | import React, { Fragment } from 'react' 2 | import cx from 'classnames' 3 | 4 | import './Message.scss' 5 | 6 | const Message = ({ 7 | className, 8 | type, 9 | message, 10 | }) => { 11 | return ( 12 |
21 |
22 | {type === 'error' && 'error'} 23 | {type === 'txHash' && 'txHash'} 24 | {type === 'receipt' && 'receipt'} 25 | {type === 'signedMessage' && ( 26 | 27 | Signed
28 | Message 29 |
30 | )} 31 | {type === 'rawTransaction' && ( 32 | 33 | Signed
34 | Transaction 35 |
36 | )} 37 |
38 |
39 | {message} 40 |
41 |
42 | ) 43 | } 44 | 45 | export default Message 46 | -------------------------------------------------------------------------------- /src/components/Message.scss: -------------------------------------------------------------------------------- 1 | .Message { 2 | @include font-style('font-4'); 3 | display: flex; 4 | align-items: center; 5 | padding: 10px 10px 10px 0; 6 | margin-bottom: 10px; 7 | border-radius: 5px; 8 | background-color: $black; 9 | word-break: break-all; 10 | color: white; 11 | 12 | &--error { 13 | .Message__status { 14 | color: $alert-red; 15 | background-image: url('/images/ico-error.svg'); 16 | } 17 | .Message__message { color: $alert-red; } 18 | } 19 | 20 | &--txHash { 21 | .Message__status { 22 | padding-top: 0; 23 | color: $warning-yellow; 24 | background-image: none; 25 | .Message__message { color: $warning-yellow; } 26 | } 27 | } 28 | 29 | &--receipt { 30 | .Message__status { 31 | background-image: url('/images/ico-receipt.svg'); 32 | } 33 | } 34 | 35 | &--rawTransaction, 36 | &--signedMessage { 37 | margin-top: 20px; 38 | .Message__status { 39 | padding-top: 25px; 40 | background-size: 22px 22px; 41 | background-image: url('/images/icon-tx.svg'); 42 | } 43 | } 44 | } 45 | 46 | .Message__status { 47 | display: inline-block; 48 | width: 80px; 49 | padding-top: 18px; 50 | line-height: 1.1; 51 | background-repeat: no-repeat; 52 | background-position: top center; 53 | background-size: 14px 14px; 54 | text-align: center; 55 | font-weight: bold; 56 | color: white; 57 | } 58 | 59 | .Message__message { 60 | display: inline-block; 61 | width: calc(100% - 80px); 62 | max-height: 150px; 63 | overflow: scroll; 64 | font-size: 14px; 65 | color: white; 66 | } 67 | -------------------------------------------------------------------------------- /src/components/Nav.js: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import cx from 'classnames' 3 | import { isNull } from 'lodash' 4 | import networks from 'constants/networks' 5 | import './Nav.scss' 6 | 7 | const Nav = ({ network }) => ( 8 |
9 |
10 |

11 | 12 | Kaikas Tutorial 16 | 17 |

18 |
22 | 23 | {isNull(network) ? 'No connection' : networks[network]} 24 |
25 |
26 |
27 | ) 28 | 29 | export default Nav 30 | -------------------------------------------------------------------------------- /src/components/Nav.scss: -------------------------------------------------------------------------------- 1 | .Nav { 2 | width: 100%; 3 | height: 75px; 4 | position: sticky; 5 | top: 0; 6 | left: 0; 7 | z-index: 100; 8 | @include cardBox(); 9 | } 10 | 11 | .Nav__inner { 12 | max-width: $max-page-width; 13 | height: 100%; 14 | margin: 0 auto; 15 | padding: 0 20px; 16 | display: flex; 17 | justify-content: space-between; 18 | align-items: center; 19 | } 20 | 21 | .Nav__logo { 22 | width: 160px; 23 | overflow: hidden; 24 | img { width: 180px; } 25 | } 26 | 27 | .Nav__network { 28 | padding: 2px 15px; 29 | border: 1px solid $dark-brown; 30 | border-radius: 12px; 31 | font-size: 12px; 32 | color: $dark-brown; 33 | text-align: center; 34 | 35 | &--loading { 36 | color: $brown-grey; 37 | border-color: $brown-grey; 38 | } 39 | 40 | &--error { 41 | color: $alert-red; 42 | border-color: $alert-red; 43 | } 44 | 45 | span { 46 | display: inline-block; 47 | margin-right: 6px; 48 | font-size: 10px; 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /src/components/SignMessage.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react' 2 | import Input from 'components/Input' 3 | import Button from 'components/Button' 4 | import Message from 'components/Message' 5 | 6 | class SignMessage extends Component { 7 | constructor(props) { 8 | super(props) 9 | this.state = { 10 | from: props.from, 11 | message: '', 12 | signedMessage: null, 13 | } 14 | } 15 | 16 | static getDerivedStateFromProps = (nextProps, prevState) => { 17 | if (nextProps.from !== prevState.from) { 18 | return { from: nextProps.from } 19 | } 20 | return null 21 | } 22 | 23 | handleChange = (e) => { 24 | this.setState({ 25 | [e.target.name]: e.target.value, 26 | }) 27 | } 28 | 29 | signMessage = async () => { 30 | const { from, message } = this.state 31 | const signedMessage = await caver.klay.sign(message, from) 32 | this.setState({ signedMessage }) 33 | } 34 | 35 | render() { 36 | const { 37 | from, 38 | message, 39 | signedMessage, 40 | } = this.state 41 | 42 | return ( 43 |
44 |
45 | 52 | 59 |
71 |
72 | ) 73 | } 74 | } 75 | 76 | export default SignMessage 77 | -------------------------------------------------------------------------------- /src/components/SmartContractDeploy.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react' 2 | import caver from 'klaytn/caver' 3 | import Input from 'components/Input' 4 | import Button from 'components/Button' 5 | import TxResult from 'components/TxResult' 6 | import BytecodeExample from 'components/BytecodeExample' 7 | 8 | class SmartContractDeploy extends Component { 9 | constructor(props) { 10 | super(props) 11 | this.state = { 12 | from: props.from, 13 | data: '', 14 | value: 0, 15 | gas: 3000000, 16 | txHash: null, 17 | receipt: null, 18 | error: null, 19 | } 20 | } 21 | 22 | static getDerivedStateFromProps = (nextProps, prevState) => { 23 | if (nextProps.from !== prevState.from) { 24 | return { from: nextProps.from } 25 | } 26 | return null 27 | } 28 | 29 | handleChange = (e) => { 30 | this.setState({ 31 | [e.target.name]: e.target.value, 32 | }) 33 | } 34 | 35 | signTransaction = () => { 36 | const { from, data, value, gas } = this.state 37 | 38 | caver.klay.sendTransaction({ 39 | type: 'SMART_CONTRACT_DEPLOY', 40 | from, 41 | data, 42 | value: caver.utils.toPeb(value.toString(), 'KLAY'), 43 | gas, 44 | }) 45 | .once('transactionHash', (transactionHash) => { 46 | console.log('txHash', transactionHash) 47 | this.setState({ txHash: transactionHash }) 48 | }) 49 | .once('receipt', (receipt) => { 50 | console.log('receipt', receipt) 51 | this.setState({ receipt: JSON.stringify(receipt) }) 52 | }) 53 | .once('error', (error) => { 54 | console.log('error', error) 55 | this.setState({ error: error.message }) 56 | }) 57 | } 58 | 59 | render() { 60 | const { from, data, value, gas, txHash, receipt, error } = this.state 61 | 62 | return ( 63 |
64 | 65 | 73 | 80 | 87 | 94 |
104 | ) 105 | } 106 | } 107 | 108 | export default SmartContractDeploy 109 | -------------------------------------------------------------------------------- /src/components/SmartContractDeployFD.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react' 2 | import caver from 'klaytn/caver' 3 | import Input from 'components/Input' 4 | import Button from 'components/Button' 5 | import Message from 'components/Message' 6 | import FeeDelegation from 'components/FeeDelegation' 7 | import BytecodeExample from 'components/BytecodeExample' 8 | 9 | class SmartContractDeployFD extends Component { 10 | constructor(props) { 11 | super(props) 12 | this.state = { 13 | from: props.from, 14 | data: '', 15 | value: 0, 16 | gas: 3000000, 17 | senderAddress: '', 18 | senderRawTransaction: null, 19 | } 20 | } 21 | 22 | static getDerivedStateFromProps = (nextProps, prevState) => { 23 | if (nextProps.from !== prevState.from) { 24 | return { from: nextProps.from } 25 | } 26 | return null 27 | } 28 | 29 | handleChange = (e) => { 30 | this.setState({ 31 | [e.target.name]: e.target.value, 32 | }) 33 | } 34 | 35 | signTransaction = async () => { 36 | const { from, data, gas, value } = this.state 37 | 38 | const txData = { 39 | type: 'FEE_DELEGATED_SMART_CONTRACT_DEPLOY', 40 | from, 41 | data, 42 | gas, 43 | value: caver.utils.toPeb(value.toString(), 'KLAY'), 44 | } 45 | 46 | const { rawTransaction: senderRawTransaction } = await caver.klay.signTransaction(txData) 47 | 48 | this.setState({ 49 | senderAddress: from, 50 | senderRawTransaction 51 | }) 52 | } 53 | 54 | render() { 55 | const { from, data, gas, value, senderRawTransaction } = this.state 56 | 57 | return ( 58 |
59 | 60 |

Sender

61 | 68 | 75 | 82 | 89 |
104 | ) 105 | } 106 | } 107 | 108 | export default SmartContractDeployFD 109 | -------------------------------------------------------------------------------- /src/components/SmartContractDeployFDRatio.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react' 2 | import caver from 'klaytn/caver' 3 | import Input from 'components/Input' 4 | import Button from 'components/Button' 5 | import Message from 'components/Message' 6 | import FeeDelegation from 'components/FeeDelegation' 7 | import BytecodeExample from 'components/BytecodeExample' 8 | 9 | class SmartContractDeployFDRatio extends Component { 10 | constructor(props) { 11 | super(props) 12 | this.state = { 13 | from: props.from, 14 | data: '', 15 | value: 0, 16 | ratio: '', 17 | gas: 3000000, 18 | senderAddress: '', 19 | senderRawTransaction: null, 20 | } 21 | } 22 | 23 | static getDerivedStateFromProps = (nextProps, prevState) => { 24 | if (nextProps.from !== prevState.from) { 25 | return { from: nextProps.from } 26 | } 27 | return null 28 | } 29 | 30 | handleChange = (e) => { 31 | this.setState({ 32 | [e.target.name]: e.target.value, 33 | }) 34 | } 35 | 36 | signTransaction = async () => { 37 | const { from, data, value, ratio, gas } = this.state 38 | 39 | const txData = { 40 | type: 'FEE_DELEGATED_SMART_CONTRACT_DEPLOY_WITH_RATIO', 41 | from, 42 | data, 43 | value: caver.utils.toPeb(value.toString(), 'KLAY'), 44 | feeRatio: ratio, 45 | gas, 46 | } 47 | 48 | const { rawTransaction: senderRawTransaction } = await caver.klay.signTransaction(txData) 49 | 50 | this.setState({ 51 | senderAddress: from, 52 | senderRawTransaction 53 | }) 54 | } 55 | 56 | render() { 57 | const { from, data, value, ratio, gas, senderRawTransaction } = this.state 58 | 59 | return ( 60 |
61 | 62 |

Sender

63 | 70 | 77 | 84 | 91 | 98 |
113 | ) 114 | } 115 | } 116 | 117 | export default SmartContractDeployFDRatio 118 | -------------------------------------------------------------------------------- /src/components/SmartContractDeployLegacy.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react' 2 | import caver from 'klaytn/caver' 3 | import Input from 'components/Input' 4 | import Button from 'components/Button' 5 | import TxResult from 'components/TxResult' 6 | import BytecodeExample from 'components/BytecodeExample' 7 | 8 | class SmartContractDeployLegacy extends Component { 9 | constructor(props) { 10 | super(props) 11 | this.state = { 12 | from: props.from, 13 | data: '', 14 | gas: 3000000, 15 | txHash: null, 16 | receipt: null, 17 | error: null, 18 | } 19 | } 20 | 21 | static getDerivedStateFromProps = (nextProps, prevState) => { 22 | if (nextProps.from !== prevState.from) { 23 | return { from: nextProps.from } 24 | } 25 | return null 26 | } 27 | 28 | handleChange = (e) => { 29 | this.setState({ 30 | [e.target.name]: e.target.value, 31 | }) 32 | } 33 | 34 | handleSmartContractDeploy = () => { 35 | const { from, data, gas } = this.state 36 | 37 | caver.klay.sendTransaction({ 38 | from, 39 | data, 40 | gas, 41 | }) 42 | .once('transactionHash', (transactionHash) => { 43 | console.log('txHash', transactionHash) 44 | this.setState({ txHash: transactionHash }) 45 | }) 46 | .once('receipt', (receipt) => { 47 | console.log('receipt', receipt) 48 | this.setState({ receipt: JSON.stringify(receipt) }) 49 | }) 50 | .once('error', (error) => { 51 | console.log('error', error) 52 | this.setState({ error: error.message }) 53 | }) 54 | } 55 | 56 | render() { 57 | const { from, data, gas, txHash, receipt, error } = this.state 58 | 59 | return ( 60 |
61 | 62 | 69 | 76 | 83 |
93 | ) 94 | } 95 | } 96 | 97 | export default SmartContractDeployLegacy 98 | -------------------------------------------------------------------------------- /src/components/SmartContractExecution.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react' 2 | import caver from 'klaytn/caver' 3 | import Input from 'components/Input' 4 | import Button from 'components/Button' 5 | import TxResult from 'components/TxResult' 6 | 7 | class SmartContractExecution extends Component { 8 | constructor(props) { 9 | super(props) 10 | this.state = { 11 | from: props.from, 12 | to: '', 13 | amount: '', 14 | contractAddress: '', 15 | gas: 3000000, 16 | txHash: null, 17 | receipt: null, 18 | error: null, 19 | decimal: 18 20 | } 21 | } 22 | 23 | static getDerivedStateFromProps = (nextProps, prevState) => { 24 | if (nextProps.from !== prevState.from) { 25 | return { from: nextProps.from } 26 | } 27 | return null 28 | } 29 | 30 | handleChange = e => { 31 | this.setState({ 32 | [e.target.name]: e.target.value 33 | }) 34 | } 35 | 36 | signTransaction = () => { 37 | const { from, contractAddress, to, amount, gas, decimal } = this.state 38 | if (decimal > 20) { 39 | return alert('decimal should be less than 21') 40 | } 41 | 42 | const data = caver.klay.abi.encodeFunctionCall( 43 | { 44 | name: 'transfer', 45 | type: 'function', 46 | inputs: [ 47 | { 48 | type: 'address', 49 | name: 'recipient' 50 | }, 51 | { 52 | type: 'uint256', 53 | name: 'amount' 54 | } 55 | ] 56 | }, 57 | [ 58 | to, 59 | caver.utils 60 | .toBN(amount) 61 | .mul(caver.utils.toBN(Number(`1e${decimal}`))) 62 | .toString() 63 | ] 64 | ) 65 | 66 | caver.klay 67 | .sendTransaction({ 68 | type: 'SMART_CONTRACT_EXECUTION', 69 | from, 70 | to: contractAddress, 71 | data, 72 | gas 73 | }) 74 | .on('transactionHash', transactionHash => { 75 | console.log('txHash', transactionHash) 76 | this.setState({ txHash: transactionHash }) 77 | }) 78 | .on('receipt', receipt => { 79 | console.log('receipt', receipt) 80 | this.setState({ receipt: JSON.stringify(receipt) }) 81 | }) 82 | .on('error', error => { 83 | console.log('error', error) 84 | this.setState({ error: error.message }) 85 | }) 86 | } 87 | 88 | render() { 89 | const { 90 | from, 91 | to, 92 | amount, 93 | contractAddress, 94 | gas, 95 | txHash, 96 | receipt, 97 | error, 98 | decimal 99 | } = this.state 100 | 101 | return ( 102 |
103 | 110 | 117 | 124 | 131 | 138 | 145 |
148 | ) 149 | } 150 | } 151 | 152 | export default SmartContractExecution 153 | -------------------------------------------------------------------------------- /src/components/SmartContractExecutionFD.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react' 2 | import caver from 'klaytn/caver' 3 | import Input from 'components/Input' 4 | import Button from 'components/Button' 5 | import Message from 'components/Message' 6 | import FeeDelegation from 'components/FeeDelegation' 7 | 8 | class SmartContractExecutionFD extends Component { 9 | constructor(props) { 10 | super(props) 11 | this.state = { 12 | from: props.from, 13 | to: '', 14 | amount: '', 15 | contractAddress: '', 16 | gas: 3000000, 17 | senderAddress: '', 18 | senderRawTransaction: null, 19 | decimal: 18 20 | } 21 | } 22 | 23 | static getDerivedStateFromProps = (nextProps, prevState) => { 24 | if (nextProps.from !== prevState.from) { 25 | return { from: nextProps.from } 26 | } 27 | return null 28 | } 29 | 30 | handleChange = e => { 31 | this.setState({ 32 | [e.target.name]: e.target.value 33 | }) 34 | } 35 | 36 | signTransaction = async () => { 37 | const { from, to, amount, contractAddress, gas, decimal } = this.state 38 | if (decimal > 20) { 39 | return alert('decimal should be less than 21') 40 | } 41 | 42 | const data = caver.klay.abi.encodeFunctionCall( 43 | { 44 | name: 'transfer', 45 | type: 'function', 46 | inputs: [ 47 | { 48 | type: 'address', 49 | name: 'recipient' 50 | }, 51 | { 52 | type: 'uint256', 53 | name: 'amount' 54 | } 55 | ] 56 | }, 57 | [ 58 | to, 59 | caver.utils 60 | .toBN(amount) 61 | .mul(caver.utils.toBN(Number(`1e${decimal}`))) 62 | .toString() 63 | ] 64 | ) 65 | 66 | const txData = { 67 | type: 'FEE_DELEGATED_SMART_CONTRACT_EXECUTION', 68 | from, 69 | to: contractAddress, 70 | gas, 71 | data 72 | } 73 | 74 | const { 75 | rawTransaction: senderRawTransaction 76 | } = await caver.klay.signTransaction(txData) 77 | 78 | this.setState({ 79 | senderAddress: from, 80 | senderRawTransaction 81 | }) 82 | } 83 | 84 | render() { 85 | const { 86 | from, 87 | to, 88 | amount, 89 | contractAddress, 90 | gas, 91 | senderRawTransaction, 92 | decimal 93 | } = this.state 94 | 95 | return ( 96 |
97 | 104 | 111 | 118 | 125 | 132 | 139 |
151 | ) 152 | } 153 | } 154 | 155 | export default SmartContractExecutionFD 156 | -------------------------------------------------------------------------------- /src/components/SmartContractExecutionFDRatio.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react' 2 | import caver from 'klaytn/caver' 3 | import Input from 'components/Input' 4 | import Button from 'components/Button' 5 | import Message from 'components/Message' 6 | import FeeDelegation from 'components/FeeDelegation' 7 | 8 | class SmartContractExecutionFDRatio extends Component { 9 | constructor(props) { 10 | super(props) 11 | this.state = { 12 | from: props.from, 13 | to: '', 14 | amount: '', 15 | contractAddress: '', 16 | ratio: '', 17 | gas: 3000000, 18 | senderAddress: '', 19 | senderRawTransaction: null, 20 | decimal: 18 21 | } 22 | } 23 | 24 | static getDerivedStateFromProps = (nextProps, prevState) => { 25 | if (nextProps.from !== prevState.from) { 26 | return { from: nextProps.from } 27 | } 28 | return null 29 | } 30 | 31 | handleChange = e => { 32 | this.setState({ 33 | [e.target.name]: e.target.value 34 | }) 35 | } 36 | 37 | signTransaction = async () => { 38 | const { 39 | from, 40 | to, 41 | amount, 42 | contractAddress, 43 | ratio, 44 | gas, 45 | decimal 46 | } = this.state 47 | if (decimal > 20) { 48 | return alert('decimal should be less than 21') 49 | } 50 | 51 | const data = caver.klay.abi.encodeFunctionCall( 52 | { 53 | name: 'transfer', 54 | type: 'function', 55 | inputs: [ 56 | { 57 | type: 'address', 58 | name: 'recipient' 59 | }, 60 | { 61 | type: 'uint256', 62 | name: 'amount' 63 | } 64 | ] 65 | }, 66 | [ 67 | to, 68 | caver.utils 69 | .toBN(amount) 70 | .mul(caver.utils.toBN(Number(`1e${decimal}`))) 71 | .toString() 72 | ] 73 | ) 74 | 75 | const txData = { 76 | type: 'FEE_DELEGATED_SMART_CONTRACT_EXECUTION_WITH_RATIO', 77 | from, 78 | to: contractAddress, 79 | data, 80 | feeRatio: ratio, 81 | gas 82 | } 83 | 84 | const { 85 | rawTransaction: senderRawTransaction 86 | } = await caver.klay.signTransaction(txData) 87 | 88 | this.setState({ 89 | senderAddress: from, 90 | senderRawTransaction 91 | }) 92 | } 93 | 94 | render() { 95 | const { 96 | from, 97 | to, 98 | amount, 99 | contractAddress, 100 | gas, 101 | ratio, 102 | senderRawTransaction, 103 | decimal 104 | } = this.state 105 | 106 | return ( 107 |
108 | 115 | 122 | 129 | 136 | 143 | 150 | 157 |
169 | ) 170 | } 171 | } 172 | 173 | export default SmartContractExecutionFDRatio 174 | -------------------------------------------------------------------------------- /src/components/SmartContractExecutionLegacy.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react' 2 | import caver from 'klaytn/caver' 3 | import Input from 'components/Input' 4 | import Button from 'components/Button' 5 | import TxResult from 'components/TxResult' 6 | 7 | class SmartContractExecutionLegacy extends Component { 8 | constructor(props) { 9 | super(props) 10 | this.state = { 11 | from: props.from, 12 | to: '', 13 | amount: '', 14 | contractAddress: '', 15 | gas: '3000000', 16 | txHash: null, 17 | receipt: null, 18 | error: null, 19 | decimal: 18 20 | } 21 | } 22 | 23 | static getDerivedStateFromProps = (nextProps, prevState) => { 24 | if (nextProps.from !== prevState.from) { 25 | return { from: nextProps.from } 26 | } 27 | return null 28 | } 29 | 30 | handleChange = e => { 31 | this.setState({ 32 | [e.target.name]: e.target.value 33 | }) 34 | } 35 | 36 | signTransaction = () => { 37 | const { from, contractAddress, to, amount, gas, decimal } = this.state 38 | if (decimal > 20) { 39 | return alert('decimal should be less than 21') 40 | } 41 | 42 | const data = caver.klay.abi.encodeFunctionCall( 43 | { 44 | name: 'transfer', 45 | type: 'function', 46 | inputs: [ 47 | { 48 | type: 'address', 49 | name: 'recipient' 50 | }, 51 | { 52 | type: 'uint256', 53 | name: 'amount' 54 | } 55 | ] 56 | }, 57 | [ 58 | to, 59 | caver.utils 60 | .toBN(amount) 61 | .mul(caver.utils.toBN(Number(`1e${decimal}`))) 62 | .toString() 63 | ] 64 | ) 65 | 66 | caver.klay 67 | .sendTransaction({ 68 | from, 69 | to: contractAddress, 70 | data, 71 | gas 72 | }) 73 | .on('transactionHash', transactionHash => { 74 | console.log('txHash', transactionHash) 75 | this.setState({ txHash: transactionHash }) 76 | }) 77 | .on('receipt', receipt => { 78 | console.log('receipt', receipt) 79 | this.setState({ receipt: JSON.stringify(receipt) }) 80 | }) 81 | .on('error', error => { 82 | console.log('error', error) 83 | this.setState({ error: error.message }) 84 | }) 85 | } 86 | 87 | render() { 88 | const { 89 | from, 90 | to, 91 | amount, 92 | contractAddress, 93 | gas, 94 | txHash, 95 | receipt, 96 | error, 97 | decimal 98 | } = this.state 99 | 100 | return ( 101 |
102 | 109 | 116 | 123 | 130 | 137 | 144 |
147 | ) 148 | } 149 | } 150 | 151 | export default SmartContractExecutionLegacy 152 | -------------------------------------------------------------------------------- /src/components/TxResult.js: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import cx from 'classnames' 3 | import Message from 'components/Message' 4 | 5 | import './TxResult.scss' 6 | 7 | const TxResult = ({ className, txHash, receipt, error }) => ( 8 |
9 |

Transaction Result

10 | {txHash && ( 11 | 15 | )} 16 | {receipt && ( 17 | 21 | )} 22 | {error && ( 23 | 27 | )} 28 |
29 | ) 30 | 31 | export default TxResult 32 | -------------------------------------------------------------------------------- /src/components/TxResult.scss: -------------------------------------------------------------------------------- 1 | .TxResult { 2 | padding-top: 20px; 3 | margin-top: 20px; 4 | border-top: 1px dashed $middle-grey; 5 | } 6 | -------------------------------------------------------------------------------- /src/components/ValueTransfer.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react' 2 | import caver from 'klaytn/caver' 3 | import Input from 'components/Input' 4 | import Button from 'components/Button' 5 | import TxResult from 'components/TxResult' 6 | 7 | class ValueTransfer extends Component { 8 | constructor(props) { 9 | super(props) 10 | this.state = { 11 | from: props.from, 12 | to: '', 13 | value: '', 14 | gas: 3000000, 15 | txHash: null, 16 | receipt: null, 17 | error: null, 18 | rawTransaction: null, 19 | } 20 | } 21 | 22 | static getDerivedStateFromProps = (nextProps, prevState) => { 23 | if (nextProps.from !== prevState.from) { 24 | return { from: nextProps.from } 25 | } 26 | return null 27 | } 28 | 29 | handleChange = (e) => { 30 | this.setState({ 31 | [e.target.name]: e.target.value, 32 | }) 33 | } 34 | 35 | signTransaction = () => { 36 | const { from, to, value, gas } = this.state 37 | 38 | caver.klay.sendTransaction({ 39 | type: 'VALUE_TRANSFER', 40 | from, 41 | to, 42 | value: caver.utils.toPeb(value.toString(), 'KLAY'), 43 | gas, 44 | }) 45 | .once('transactionHash', (transactionHash) => { 46 | console.log('txHash', transactionHash) 47 | this.setState({ txHash: transactionHash }) 48 | }) 49 | .once('receipt', (receipt) => { 50 | console.log('receipt', receipt) 51 | this.setState({ receipt: JSON.stringify(receipt) }) 52 | }) 53 | .once('error', (error) => { 54 | console.log('error', error) 55 | this.setState({ error: error.message }) 56 | }) 57 | } 58 | 59 | render() { 60 | const { from, to, value, gas, txHash, receipt, error } = this.state 61 | 62 | return ( 63 |
64 | 71 | 78 | 85 | 92 |
102 | ) 103 | } 104 | } 105 | 106 | export default ValueTransfer 107 | -------------------------------------------------------------------------------- /src/components/ValueTransferFD.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react' 2 | import caver from 'klaytn/caver' 3 | import Input from 'components/Input' 4 | import Button from 'components/Button' 5 | import Message from 'components/Message' 6 | import FeeDelegation from 'components/FeeDelegation' 7 | 8 | class ValueTransferFDRatio extends Component { 9 | constructor(props) { 10 | super(props) 11 | this.state = { 12 | from: props.from, 13 | to: '', 14 | value: '', 15 | gas: 3000000, 16 | senderAddress: '', 17 | senderRawTransaction: null, 18 | } 19 | } 20 | 21 | static getDerivedStateFromProps = (nextProps, prevState) => { 22 | if (nextProps.from !== prevState.from) { 23 | return { from: nextProps.from } 24 | } 25 | return null 26 | } 27 | 28 | handleChange = (e) => { 29 | this.setState({ 30 | [e.target.name]: e.target.value, 31 | }) 32 | } 33 | 34 | signTransaction = async () => { 35 | const { from, to, value, gas } = this.state 36 | 37 | const txData = { 38 | type: 'FEE_DELEGATED_VALUE_TRANSFER', 39 | from, 40 | to, 41 | gas, 42 | value: caver.utils.toPeb(value, 'KLAY'), 43 | } 44 | 45 | const { rawTransaction: senderRawTransaction} = await caver.klay.signTransaction(txData) 46 | 47 | this.setState({ 48 | senderAddress: from, 49 | senderRawTransaction 50 | }) 51 | } 52 | 53 | render() { 54 | const { from, to, value, gas, senderAddress, senderRawTransaction } = this.state 55 | 56 | return ( 57 |
58 |

Sender

59 | 66 | 73 | 80 | 87 |
102 | ) 103 | } 104 | } 105 | 106 | export default ValueTransferFDRatio 107 | -------------------------------------------------------------------------------- /src/components/ValueTransferFDRatio.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react' 2 | import caver from 'klaytn/caver' 3 | import Input from 'components/Input' 4 | import Button from 'components/Button' 5 | import Message from 'components/Message' 6 | import FeeDelegation from 'components/FeeDelegation' 7 | 8 | class ValueTransferFD extends Component { 9 | constructor(props) { 10 | super(props) 11 | this.state = { 12 | from: props.from, 13 | to: '', 14 | value: '', 15 | ratio: '', 16 | gas: 3000000, 17 | senderAddress: '', 18 | senderRawTransaction: null, 19 | } 20 | } 21 | 22 | static getDerivedStateFromProps = (nextProps, prevState) => { 23 | if (nextProps.from !== prevState.from) { 24 | return { from: nextProps.from } 25 | } 26 | return null 27 | } 28 | 29 | handleChange = (e) => { 30 | this.setState({ 31 | [e.target.name]: e.target.value, 32 | }) 33 | } 34 | 35 | signTransaction = async () => { 36 | const { from, to, value, gas, ratio } = this.state 37 | 38 | const txData = { 39 | type: 'FEE_DELEGATED_VALUE_TRANSFER_WITH_RATIO', 40 | from, 41 | to, 42 | value: caver.utils.toPeb(value, 'KLAY'), 43 | feeRatio: ratio, 44 | gas, 45 | } 46 | 47 | const { rawTransaction: senderRawTransaction} = await caver.klay.signTransaction(txData) 48 | 49 | this.setState({ 50 | senderAddress: from, 51 | senderRawTransaction 52 | }) 53 | } 54 | 55 | render() { 56 | const { from, to, value, ratio, gas, senderAddress, senderRawTransaction } = this.state 57 | 58 | return ( 59 |
60 |

Sender

61 | 68 | 75 | 82 | 89 | 96 |
111 | ) 112 | } 113 | } 114 | 115 | export default ValueTransferFD 116 | -------------------------------------------------------------------------------- /src/components/ValueTransferLegacy.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react' 2 | import caver from 'klaytn/caver' 3 | import Input from 'components/Input' 4 | import Button from 'components/Button' 5 | import TxResult from 'components/TxResult' 6 | 7 | class ValueTransferLegacy extends Component { 8 | constructor(props) { 9 | super(props) 10 | this.state = { 11 | from: props.from, 12 | to: '', 13 | value: '', 14 | gas: 3000000, 15 | txHash: null, 16 | receipt: null, 17 | error: null, 18 | rawTransaction: null, 19 | } 20 | } 21 | 22 | static getDerivedStateFromProps = (nextProps, prevState) => { 23 | if (nextProps.from !== prevState.from) { 24 | return { from: nextProps.from } 25 | } 26 | return null 27 | } 28 | 29 | handleChange = (e) => { 30 | this.setState({ 31 | [e.target.name]: e.target.value, 32 | }) 33 | } 34 | 35 | signTransaction = () => { 36 | const { from, to, value, gas } = this.state 37 | 38 | caver.klay.sendTransaction({ 39 | from, 40 | to, 41 | value: caver.utils.toPeb(value.toString(), 'KLAY'), 42 | gas, 43 | }) 44 | .once('transactionHash', (transactionHash) => { 45 | console.log('txHash', transactionHash) 46 | this.setState({ txHash: transactionHash }) 47 | }) 48 | .once('receipt', (receipt) => { 49 | console.log('receipt', receipt) 50 | this.setState({ receipt: JSON.stringify(receipt) }) 51 | }) 52 | .once('error', (error) => { 53 | console.log('error', error) 54 | this.setState({ error: error.message }) 55 | }) 56 | } 57 | 58 | render() { 59 | const { from, to, value, gas, txHash, receipt, error } = this.state 60 | 61 | return ( 62 |
63 | 70 | 77 | 84 | 91 |
101 | ) 102 | } 103 | } 104 | 105 | export default ValueTransferLegacy 106 | -------------------------------------------------------------------------------- /src/components/ValueTransferMemo.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react' 2 | import caver from 'klaytn/caver' 3 | import Input from 'components/Input' 4 | import Button from 'components/Button' 5 | import TxResult from 'components/TxResult' 6 | 7 | class ValueTransfer extends Component { 8 | constructor(props) { 9 | super(props) 10 | this.state = { 11 | from: props.from, 12 | to: '', 13 | value: '', 14 | memo: '', 15 | gas: 3000000, 16 | txHash: null, 17 | receipt: null, 18 | error: null, 19 | rawTransaction: null, 20 | } 21 | } 22 | 23 | static getDerivedStateFromProps = (nextProps, prevState) => { 24 | if (nextProps.from !== prevState.from) { 25 | return { from: nextProps.from } 26 | } 27 | return null 28 | } 29 | 30 | handleChange = (e) => { 31 | this.setState({ 32 | [e.target.name]: e.target.value, 33 | }) 34 | } 35 | 36 | handleValueTransfer = () => { 37 | const { from, to, value, memo, gas } = this.state 38 | 39 | 40 | caver.klay.sendTransaction({ 41 | type: 'VALUE_TRANSFER_MEMO', 42 | from, 43 | to, 44 | value: caver.utils.toPeb(value.toString(), 'KLAY'), 45 | gas, 46 | data: memo, 47 | }) 48 | .once('transactionHash', (transactionHash) => { 49 | console.log('txHash', transactionHash) 50 | this.setState({ txHash: transactionHash }) 51 | }) 52 | .once('receipt', (receipt) => { 53 | console.log('receipt', receipt) 54 | this.setState({ receipt: JSON.stringify(receipt) }) 55 | }) 56 | .once('error', (error) => { 57 | console.log('error', error) 58 | this.setState({ error: error.message }) 59 | }) 60 | } 61 | 62 | render() { 63 | const { from, to, value, gas, memo, txHash, receipt, error } = this.state 64 | 65 | return ( 66 |
67 | 74 | 81 | 88 | 95 | 102 |
112 | ) 113 | } 114 | } 115 | 116 | export default ValueTransfer 117 | -------------------------------------------------------------------------------- /src/components/ValueTransferMemoFD.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react' 2 | import caver from 'klaytn/caver' 3 | import Input from 'components/Input' 4 | import Button from 'components/Button' 5 | import Message from 'components/Message' 6 | import FeeDelegation from 'components/FeeDelegation' 7 | 8 | class ValueTransferMemoFD extends Component { 9 | constructor(props) { 10 | super(props) 11 | this.state = { 12 | from: props.from, 13 | to: '', 14 | value: '', 15 | memo: '', 16 | gas: 3000000, 17 | senderAddress: '', 18 | senderRawTransaction: null, 19 | } 20 | } 21 | 22 | static getDerivedStateFromProps = (nextProps, prevState) => { 23 | if (nextProps.from !== prevState.from) { 24 | return { from: nextProps.from } 25 | } 26 | return null 27 | } 28 | 29 | handleChange = (e) => { 30 | this.setState({ 31 | [e.target.name]: e.target.value, 32 | }) 33 | } 34 | 35 | handleSignTransaction = async () => { 36 | const { from, to, value, memo, gas } = this.state 37 | 38 | const txData = { 39 | type: 'FEE_DELEGATED_VALUE_TRANSFER_MEMO', 40 | from, 41 | to, 42 | gas, 43 | value: caver.utils.toPeb(value, 'KLAY'), 44 | data: memo, 45 | } 46 | 47 | const { rawTransaction: senderRawTransaction} = await caver.klay.signTransaction(txData) 48 | 49 | this.setState({ 50 | senderAddress: from, 51 | senderRawTransaction 52 | }) 53 | } 54 | 55 | render() { 56 | const { from, to, value, memo, gas, senderAddress, senderRawTransaction } = this.state 57 | 58 | return ( 59 |
60 |

Sender

61 | 68 | 75 | 82 | 89 | 96 |
111 | ) 112 | } 113 | } 114 | 115 | export default ValueTransferMemoFD 116 | -------------------------------------------------------------------------------- /src/components/ValueTransferMemoFDRatio.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react' 2 | import caver from 'klaytn/caver' 3 | import Input from 'components/Input' 4 | import Button from 'components/Button' 5 | import Message from 'components/Message' 6 | import FeeDelegation from 'components/FeeDelegation' 7 | 8 | class ValueTransferMemoFDRatio extends Component { 9 | constructor(props) { 10 | super(props) 11 | this.state = { 12 | from: props.from, 13 | to: '', 14 | value: '', 15 | memo: '', 16 | ratio: '', 17 | gas: 3000000, 18 | senderAddress: '', 19 | senderRawTransaction: null, 20 | } 21 | } 22 | 23 | static getDerivedStateFromProps = (nextProps, prevState) => { 24 | if (nextProps.from !== prevState.from) { 25 | return { from: nextProps.from } 26 | } 27 | return null 28 | } 29 | 30 | handleChange = (e) => { 31 | this.setState({ 32 | [e.target.name]: e.target.value, 33 | }) 34 | } 35 | 36 | handleSignTransaction = async () => { 37 | const { from, to, value, memo, gas, ratio } = this.state 38 | 39 | const txData = { 40 | type: 'FEE_DELEGATED_VALUE_TRANSFER_MEMO_WITH_RATIO', 41 | from, 42 | to, 43 | gas, 44 | value: caver.utils.toPeb(value, 'KLAY'), 45 | data: memo, 46 | feeRatio: ratio, 47 | } 48 | 49 | const { rawTransaction: senderRawTransaction} = await caver.klay.signTransaction(txData) 50 | 51 | this.setState({ 52 | senderAddress: from, 53 | senderRawTransaction 54 | }) 55 | } 56 | 57 | render() { 58 | const { from, to, value, memo, ratio, gas, senderAddress, senderRawTransaction } = this.state 59 | 60 | return ( 61 |
62 |

Sender

63 | 70 | 77 | 84 | 91 | 98 | 105 |
120 | ) 121 | } 122 | } 123 | 124 | export default ValueTransferMemoFDRatio 125 | -------------------------------------------------------------------------------- /src/components/WalletInfo.js: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import { KLAY_FAUCET } from 'constants/url' 3 | 4 | import './WalletInfo.scss' 5 | 6 | const WalletInfo = ({ address, balance }) => { 7 | return ( 8 |
9 |

Wallet Information

10 |
11 |
12 | Wallet Address 13 | {address || 'Login with Kaikas :)'} 14 |
15 |
16 | Balance 17 | {balance} 18 | KLAY 19 |
20 |
21 |

22 | If you need small amount of Klay for testing. 23 | 29 | Run Klay Faucet 30 | 31 |

32 |
33 | ) 34 | } 35 | 36 | export default WalletInfo 37 | -------------------------------------------------------------------------------- /src/components/WalletInfo.scss: -------------------------------------------------------------------------------- 1 | .WalletInfo { 2 | width: 100%; 3 | padding-bottom: 20px; 4 | border-bottom: 1px solid $light-grey; 5 | } 6 | 7 | .WalletInfo__title { 8 | margin-bottom: 15px; 9 | } 10 | 11 | .WalletInfo__infoBox { 12 | width: 100%; 13 | font-size: 14px; 14 | margin-bottom: 10px; 15 | border: 1px solid $light-grey; 16 | border-radius: 5px; 17 | background-color: white; 18 | } 19 | 20 | .WalletInfo__info { 21 | @include textEllipsis(); 22 | display: inline-block; 23 | padding: 12px 18px; 24 | 25 | &:first-child { 26 | width: 60%; 27 | border-right: 1px solid $light-grey; 28 | } 29 | &:nth-child(2) { 30 | width: 40%; 31 | } 32 | } 33 | 34 | .WalletInfo__label { 35 | display: block; 36 | font-size: 12px; 37 | font-weight: bold; 38 | color: $brown-grey; 39 | margin-bottom: 3px; 40 | } 41 | 42 | .WalletInfo__balance { 43 | @include textEllipsis(); 44 | display: inline-block; 45 | max-width: calc(100% - 35px); 46 | vertical-align: bottom; 47 | } 48 | 49 | .WalletInfo__unit { 50 | display: inline-block; 51 | width: 35px; 52 | padding-left: 5px; 53 | text-align: right; 54 | } 55 | 56 | .WalletInfo__faucet { 57 | font-size: 12px; 58 | color: $brown-grey; 59 | text-align: right; 60 | padding-right: 10px; 61 | } 62 | 63 | .WalletInfo__link { 64 | display: inline-block; 65 | font-weight: bold; 66 | margin-left: 8px; 67 | cursor: pointer; 68 | &:hover { text-decoration: underline; } 69 | } -------------------------------------------------------------------------------- /src/constants/networks.js: -------------------------------------------------------------------------------- 1 | const networks = { 2 | 8217: 'Mainnet Network', 3 | 1001: 'Baobab Network', 4 | loading: 'Connecting...' 5 | } 6 | 7 | export default networks -------------------------------------------------------------------------------- /src/constants/url.js: -------------------------------------------------------------------------------- 1 | export const KLAY_FAUCET = 'https://baobab.wallet.klaytn.com/access?next=faucet' 2 | -------------------------------------------------------------------------------- /src/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import ReactDOM from 'react-dom' 3 | import App from './App' 4 | 5 | import './index.scss' 6 | 7 | const rootElement = document.getElementById('root') 8 | 9 | ReactDOM.render( 10 | , 11 | rootElement 12 | ) 13 | -------------------------------------------------------------------------------- /src/index.scss: -------------------------------------------------------------------------------- 1 | @font-face { 2 | font-family: 'SFUIText'; 3 | font-style: normal; 4 | font-weight: bold; 5 | src: url('/fonts/SFUIText-Bold.ttf') format('truetype'); 6 | font-display: swap; 7 | } 8 | 9 | @font-face { 10 | font-family: 'SFUIText'; 11 | font-style: normal; 12 | font-weight: 600; 13 | src: url('/fonts/SFUIText-Semibold.ttf') format('truetype'); 14 | font-display: swap; 15 | } 16 | 17 | @font-face { 18 | font-family: 'SFUIText'; 19 | font-style: normal; 20 | font-weight: normal; 21 | src: url('/fonts/SFUIText-Regular.ttf') format('truetype'); 22 | font-display: swap; 23 | } 24 | 25 | @font-face { 26 | font-family: 'SFUIText'; 27 | font-style: normal; 28 | font-weight: 300; 29 | src: url('/fonts/SFUIText-Medium.ttf') format('truetype'); 30 | font-display: swap; 31 | } 32 | 33 | @font-face { 34 | font-family: 'SFUIText'; 35 | font-style: normal; 36 | font-weight: 200; 37 | src: url('/fonts/SFUIText-Light.ttf') format('truetype'); 38 | font-display: swap; 39 | } 40 | 41 | html, body, #root { height: 100%; } 42 | 43 | html { font-size: 10px; } 44 | 45 | body { 46 | margin: 0; 47 | padding: 0; 48 | background-color: $bg-color; 49 | font-family: SFUIText, Apple SD Gothic Neo, sans-serif; 50 | font-size: 14px; 51 | line-height: 18px; 52 | color: $dark-brown; 53 | 54 | *, *::before, *::after { 55 | box-sizing: border-box; 56 | -webkit-font-smoothing: antialiased; 57 | -moz-osx-font-smoothing: grayscale; 58 | } 59 | 60 | a { 61 | color: inherit; 62 | text-decoration: none; 63 | } 64 | 65 | p, h1, h2, h3, h4, h5, h6 { 66 | margin: 0; 67 | } 68 | 69 | button, input, select, textarea { 70 | font-family: unset; 71 | } 72 | 73 | button { 74 | padding: unset; 75 | background-color: unset; 76 | border: unset; 77 | } 78 | 79 | ul { 80 | margin: 0; 81 | padding: 0; 82 | list-style: none; 83 | } 84 | } 85 | -------------------------------------------------------------------------------- /src/klaytn/caver.js: -------------------------------------------------------------------------------- 1 | import Caver from 'caver-js' 2 | 3 | const caver = new Caver(window.klaytn) 4 | 5 | export default caver 6 | -------------------------------------------------------------------------------- /src/pages/KaikasPage.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react' 2 | import caver from 'klaytn/caver' 3 | 4 | import Nav from 'components/Nav' 5 | import WalletInfo from 'components/WalletInfo' 6 | import Dropdown from 'components/Dropdown' 7 | import GithubLink from 'components/GithubLink' 8 | import ValueTransferLegacy from 'components/ValueTransferLegacy' 9 | import SmartContractExecutionLegacy from 'components/SmartContractExecutionLegacy' 10 | import SmartContractDeployLegacy from 'components/SmartContractDeployLegacy' 11 | import AddToken from 'components/AddToken' 12 | import SignMessage from 'components/SignMessage' 13 | import ValueTransfer from 'components/ValueTransfer' 14 | import ValueTransferFD from 'components/ValueTransferFD' 15 | import ValueTransferFDRatio from 'components/ValueTransferFDRatio' 16 | import ValueTransferMemo from 'components/ValueTransferMemo' 17 | import ValueTransferMemoFD from 'components/ValueTransferMemoFD' 18 | import ValueTransferMemoFDRatio from 'components/ValueTransferMemoFDRatio' 19 | import AccountUpdate from 'components/AccountUpdate' 20 | import AccountUpdateFD from 'components/AccountUpdateFD' 21 | import AccountUpdateFDRatio from 'components/AccountUpdateFDRatio' 22 | import SmartContractDeploy from 'components/SmartContractDeploy' 23 | import SmartContractDeployFD from 'components/SmartContractDeployFD' 24 | import SmartContractDeployFDRatio from 'components/SmartContractDeployFDRatio' 25 | import SmartContractExecution from 'components/SmartContractExecution' 26 | import SmartContractExecutionFD from 'components/SmartContractExecutionFD' 27 | import SmartContractExecutionFDRatio from 'components/SmartContractExecutionFDRatio' 28 | 29 | import './KaikasPage.scss' 30 | 31 | const txTypeList = { 32 | 'Value Transfer (Legacy)': 'ValueTransferLegacy', 33 | 'Smart Contract Deploy (Legacy)': 'SmartContractDeployLegacy', 34 | 'Token Transfer (Legacy)': 'SmartContractExecutionLegacy', 35 | 'Add Token': 'AddToken', 36 | 'Sign Message': 'SignMessage', 37 | 'Value Transfer': 'ValueTransfer', 38 | 'Value Transfer (Fee Delegation)': 'ValueTransferFD', 39 | 'Value Transfer (Fee Delegation with Ratio)': 'ValueTransferFDRatio', 40 | 'Value Transfer with Memo': 'ValueTransferMemo', 41 | 'Value Transfer with Memo (Fee Delegation)': 'ValueTransferMemoFD', 42 | 'Value Transfer with Memo (Fee Delegation with Ratio)': 'ValueTransferMemoFDRatio', 43 | 'Account Update': 'AccountUpdate', 44 | 'Account Update (Fee Delegation)': 'AccountUpdateFD', 45 | 'Account Update (Fee Delegation with Ratio)': 'AccountUpdateFDRatio', 46 | 'Smart Contract Deploy': 'SmartContractDeploy', 47 | 'Smart Contract Deploy (Fee Delegation)': 'SmartContractDeployFD', 48 | 'Smart Contract Deploy (Fee Delegation with Ratio)': 'SmartContractDeployFDRatio', 49 | 'Token Transfer': 'SmartContractExecution', 50 | 'Token Transfer (Fee Delegation)': 'SmartContractExecutionFD', 51 | 'Token Transfer (Fee Delegation with Ratio)': 'SmartContractExecutionFDRatio', 52 | } 53 | 54 | class KaikasPage extends Component { 55 | constructor(props) { 56 | super(props) 57 | this.state = { 58 | txType: null, 59 | account: '', 60 | balance: 0, 61 | network: null, 62 | } 63 | } 64 | 65 | componentDidMount() { 66 | this.loadAccountInfo() 67 | this.setNetworkInfo() 68 | } 69 | 70 | loadAccountInfo = async () => { 71 | const { klaytn } = window 72 | 73 | if (klaytn) { 74 | try { 75 | await klaytn.enable() 76 | this.setAccountInfo(klaytn) 77 | klaytn.on('accountsChanged', () => this.setAccountInfo(klaytn)) 78 | } catch (error) { 79 | console.log('User denied account access') 80 | } 81 | } else { 82 | console.log('Non-Kaikas browser detected. You should consider trying Kaikas!') 83 | } 84 | } 85 | 86 | setAccountInfo = async () => { 87 | const { klaytn } = window 88 | if (klaytn === undefined) return 89 | 90 | const account = klaytn.selectedAddress 91 | const balance = await caver.klay.getBalance(account) 92 | this.setState({ 93 | account, 94 | balance: caver.utils.fromPeb(balance, 'KLAY'), 95 | }) 96 | } 97 | 98 | setNetworkInfo = () => { 99 | const { klaytn } = window 100 | if (klaytn === undefined) return 101 | 102 | this.setState({ network: klaytn.networkVersion }) 103 | klaytn.on('networkChanged', () => this.setNetworkInfo(klaytn.networkVersion)) 104 | } 105 | 106 | selectTxType = (txType) => this.setState({ txType }) 107 | 108 | renderTxExample = (txType, from) => { 109 | switch (txType) { 110 | case 'Value Transfer (Legacy)': 111 | return 112 | case 'Smart Contract Deploy (Legacy)': 113 | return 114 | case 'Token Transfer (Legacy)': 115 | return 116 | case 'Add Token': 117 | return 118 | case 'Sign Message': 119 | return 120 | case 'Value Transfer': 121 | return 122 | case 'Value Transfer (Fee Delegation)': 123 | return 124 | case 'Value Transfer (Fee Delegation with Ratio)': 125 | return 126 | case 'Value Transfer with Memo': 127 | return 128 | case 'Value Transfer with Memo (Fee Delegation)': 129 | return 130 | case 'Value Transfer with Memo (Fee Delegation with Ratio)': 131 | return 132 | case 'Smart Contract Deploy': 133 | return 134 | case 'Smart Contract Deploy (Fee Delegation)': 135 | return 136 | case 'Smart Contract Deploy (Fee Delegation with Ratio)': 137 | return 138 | case 'Token Transfer': 139 | return 140 | case 'Token Transfer (Fee Delegation)': 141 | return 142 | case 'Token Transfer (Fee Delegation with Ratio)': 143 | return 144 | case 'Account Update': 145 | return 146 | case 'Account Update (Fee Delegation)': 147 | return 148 | case 'Account Update (Fee Delegation with Ratio)': 149 | return 150 | default: 151 | return (

Select a Transaction example :D

) 152 | } 153 | } 154 | 155 | render() { 156 | const { account, balance, txType, network } = this.state 157 | const txTypeTitles = Object.keys(txTypeList) 158 | 159 | return ( 160 |
161 |
185 | ) 186 | } 187 | } 188 | 189 | export default KaikasPage 190 | -------------------------------------------------------------------------------- /src/pages/KaikasPage.scss: -------------------------------------------------------------------------------- 1 | .KaikasPage { 2 | width: 100%; 3 | height: 100%; 4 | } 5 | 6 | .KaikasPage__githubLink { 7 | width: 32px; 8 | height: 32px; 9 | position: fixed; 10 | bottom: 35px; 11 | right: 35px; 12 | z-index: 9999; 13 | transition: opacity .2s; 14 | 15 | &:hover { opacity: .8; } 16 | } 17 | 18 | .KaikasPage__main { 19 | width: 100%; 20 | min-height: 100%; 21 | max-width: 700px; 22 | margin: 0 auto; 23 | padding-top: 70px; 24 | padding: 60px 10px; 25 | 26 | h3 { margin-bottom: 15px; } 27 | } 28 | 29 | .KaikasPage__content { 30 | padding: 40px 0; 31 | } 32 | 33 | .KaikasPage__txExample { 34 | padding: 15px 20px 20px 20px; 35 | } 36 | 37 | .KaikasPage__txExampleHeader { 38 | display: flex; 39 | justify-content: space-between; 40 | align-items: baseline; 41 | padding-bottom: 15px; 42 | } 43 | 44 | .KaikasPage__txExampleTitle { 45 | width: calc(100% - 120px); 46 | @include textEllipsis(); 47 | } 48 | 49 | .KaikasPage__dropdown { 50 | margin-bottom: 20px; 51 | } 52 | 53 | .KaikasPage__guide { 54 | padding: 30px 0; 55 | text-align: center; 56 | font-size: 18px; 57 | font-weight: bold; 58 | } -------------------------------------------------------------------------------- /src/styles/_colors.scss: -------------------------------------------------------------------------------- 1 | $alert-red: rgb(245,65,55); // #f54137 2 | $warning-yellow: rgb(245,166,10); // #f5a60a 3 | $bg-color: rgb(250,250,250); // #fafafa 4 | $border-grey: rgb(234,234,234); // #eaeaea 5 | $light-grey: rgb(225,225,225); // #e1e1e1 6 | $middle-grey: rgb(204,204,204); // #cccccc 7 | $brown-grey: rgb(153,153,153); // #999999 8 | $brownish-grey: rgb(112,112,112); // #707070 9 | $dark-brown: rgb(79,71,62); // #4f473e 10 | $black: rgb(19,20,31); // #13141F 11 | $white: rgb(255,255,255); // #ffffff 12 | -------------------------------------------------------------------------------- /src/styles/_fonts.scss: -------------------------------------------------------------------------------- 1 | @mixin font-style($type) { 2 | @if $type == 'font-1' { 3 | font-size: 11px; 4 | line-height: 18px; 5 | font-family: 'Roboto'; 6 | font-weight: bold; 7 | } 8 | 9 | @else if $type == 'font-2' { 10 | font-size: 11px; 11 | line-height: 18px; 12 | font-family: 'Roboto'; 13 | font-weight: normal; 14 | } 15 | 16 | @else if $type == 'font-3' { 17 | font-size: 14px; 18 | line-height: 18px; 19 | font-family: 'GoogleSans'; 20 | font-weight: bold; 21 | } 22 | 23 | @else if $type == 'font-4' { 24 | font-size: 12px; 25 | line-height: 18px; 26 | font-family: 'RobotoMono'; 27 | } 28 | 29 | @else if $type == 'font-5' { 30 | font-size: 10px; 31 | line-height: 18px; 32 | font-family: 'Roboto'; 33 | font-weight: bold; 34 | } 35 | 36 | @else if $type == 'font-6' { 37 | font-size: 10px; 38 | line-height: 18px; 39 | font-family: 'Roboto'; 40 | } 41 | 42 | @else if $type == 'font-7' { 43 | font-size: 10px; 44 | line-height: 18px; 45 | font-family: 'RobotoMono'; 46 | } 47 | 48 | @else if $type == 'font-8' { 49 | font-size: 13px; 50 | line-height: 18px; 51 | font-family: 'Roboto'; 52 | font-weight: normal; 53 | } 54 | 55 | @else if $type == 'font-9' { 56 | font-size: 13px; 57 | line-height: 18px; 58 | font-family: 'Roboto'; 59 | font-weight: bold; 60 | } 61 | 62 | @else if $type == 'font-10' { 63 | font-size: 12px; 64 | line-height: 18px; 65 | font-family: 'Roboto'; 66 | font-weight: normal; 67 | } 68 | 69 | @else if $type == 'font-11' { 70 | font-size: 12px; 71 | line-height: 18px; 72 | font-family: 'RobotoMono'; 73 | font-weight: normal; 74 | } 75 | 76 | @else if $type == 'font-12' { 77 | font-size: 12px; 78 | line-height: 18px; 79 | font-family: 'Roboto'; 80 | font-weight: bold; 81 | } 82 | } 83 | 84 | /* 85 | 1. 86 | font-size: 11px; 87 | line-height: 18px; 88 | font-family: 'Roboto'; 89 | font-weight: bold; 90 | 91 | 2. 92 | font-size: 11px; 93 | line-height: 18px; 94 | font-family: 'Roboto'; 95 | font-weight: normal; 96 | 97 | */ 98 | -------------------------------------------------------------------------------- /src/styles/_mixins.scss: -------------------------------------------------------------------------------- 1 | $max-page-width: 935px; 2 | $min-page-width: 320px; 3 | $max-card-width: 600px; 4 | 5 | @mixin breakpoint($breakpoint) { 6 | @if $breakpoint == "max-page" { 7 | @media screen and (max-width: $max-page-width - 1) { 8 | @content; 9 | } 10 | } 11 | @else if $breakpoint == "max-card" { 12 | @media screen and (max-width: $max-card-width - 1) { 13 | @content; 14 | } 15 | } 16 | } 17 | 18 | @mixin fixed-center() { 19 | position: fixed; 20 | top: 50%; 21 | left: 50%; 22 | transform: translate(-50%, -50%); 23 | } 24 | 25 | @mixin absolute-center() { 26 | position: absolute; 27 | top: 50%; 28 | left: 50%; 29 | transform: translate(-50%, -50%); 30 | } 31 | 32 | @mixin borderBox($radius){ 33 | background-color: #fff; 34 | border: 1px solid $light-grey; 35 | @if $radius == yes { 36 | border-radius: 3px; 37 | } 38 | } 39 | 40 | @mixin cardBox(){ 41 | background-color: #fff; 42 | border: 1px solid $light-grey; 43 | } 44 | 45 | @mixin imageReplacement($width, $height, $url, $bgColor) { 46 | width: $width; 47 | height: $height; 48 | overflow: hidden; 49 | &::after { 50 | content: ""; 51 | position: absolute; 52 | top: 0; 53 | left: 0; 54 | width: $width; 55 | height: $height; 56 | background: center / contain no-repeat url($url) $bgColor; 57 | } 58 | } 59 | 60 | @mixin clear-both() { 61 | &:after { 62 | content: ""; 63 | display: block; 64 | clear: both; 65 | } 66 | } 67 | 68 | @mixin textEllipsis() { 69 | overflow: hidden; 70 | text-overflow: ellipsis; 71 | white-space: nowrap; 72 | } 73 | 74 | @mixin breakWord() { 75 | overflow: hidden; 76 | white-space: normal; 77 | word-wrap: break-word; 78 | } -------------------------------------------------------------------------------- /src/styles/_sizes.scss: -------------------------------------------------------------------------------- 1 | $max-page-width: 935px; 2 | $max-card-width: 600px; 3 | -------------------------------------------------------------------------------- /src/styles/_variables.scss: -------------------------------------------------------------------------------- 1 | @import "./colors.scss"; 2 | @import "./sizes.scss"; 3 | @import "./mixins.scss"; 4 | @import "./fonts.scss"; -------------------------------------------------------------------------------- /static/fonts/SFUIText-Bold.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/klaytn/kaikas-tutorial/7a6b5f5d377b27cd8f3e412b4906da52fd3411fc/static/fonts/SFUIText-Bold.ttf -------------------------------------------------------------------------------- /static/fonts/SFUIText-Light.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/klaytn/kaikas-tutorial/7a6b5f5d377b27cd8f3e412b4906da52fd3411fc/static/fonts/SFUIText-Light.ttf -------------------------------------------------------------------------------- /static/fonts/SFUIText-Medium.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/klaytn/kaikas-tutorial/7a6b5f5d377b27cd8f3e412b4906da52fd3411fc/static/fonts/SFUIText-Medium.ttf -------------------------------------------------------------------------------- /static/fonts/SFUIText-Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/klaytn/kaikas-tutorial/7a6b5f5d377b27cd8f3e412b4906da52fd3411fc/static/fonts/SFUIText-Regular.ttf -------------------------------------------------------------------------------- /static/fonts/SFUIText-Semibold.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/klaytn/kaikas-tutorial/7a6b5f5d377b27cd8f3e412b4906da52fd3411fc/static/fonts/SFUIText-Semibold.ttf -------------------------------------------------------------------------------- /static/images/favicon@16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/klaytn/kaikas-tutorial/7a6b5f5d377b27cd8f3e412b4906da52fd3411fc/static/images/favicon@16.png -------------------------------------------------------------------------------- /static/images/ico-error.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /static/images/ico-receipt.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /static/images/icon-close.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/klaytn/kaikas-tutorial/7a6b5f5d377b27cd8f3e412b4906da52fd3411fc/static/images/icon-close.png -------------------------------------------------------------------------------- /static/images/icon-downArrow.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /static/images/icon-github.svg: -------------------------------------------------------------------------------- 1 | GitHub icon -------------------------------------------------------------------------------- /static/images/icon-tx.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /static/images/icon-upArrow.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /static/images/icon-wallet.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/klaytn/kaikas-tutorial/7a6b5f5d377b27cd8f3e412b4906da52fd3411fc/static/images/icon-wallet.png -------------------------------------------------------------------------------- /static/images/kaikas-tutorial-screen.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/klaytn/kaikas-tutorial/7a6b5f5d377b27cd8f3e412b4906da52fd3411fc/static/images/kaikas-tutorial-screen.png -------------------------------------------------------------------------------- /static/images/klaytn-logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/klaytn/kaikas-tutorial/7a6b5f5d377b27cd8f3e412b4906da52fd3411fc/static/images/klaytn-logo.png -------------------------------------------------------------------------------- /static/images/logo-kaikas-tutorial.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/klaytn/kaikas-tutorial/7a6b5f5d377b27cd8f3e412b4906da52fd3411fc/static/images/logo-kaikas-tutorial.png -------------------------------------------------------------------------------- /static/images/logo.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /static/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | Kaikas Tutorial 9 | 10 | 11 | 14 |
15 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /webpack.base.js: -------------------------------------------------------------------------------- 1 | const path = require('path') 2 | const CopyWebpackPlugin = require('copy-webpack-plugin') 3 | const Dotenv = require('dotenv-webpack') 4 | const { envPath, defaultEnvPath } = require('./configs') 5 | 6 | module.exports = { 7 | entry: [ 8 | '@babel/polyfill', 9 | path.resolve(__dirname, 'src/index.js'), 10 | ], 11 | module: { 12 | rules: [ 13 | { 14 | test: /\.js$/, 15 | exclude: /node_modules/, 16 | use: { 17 | loader: 'babel-loader', 18 | }, 19 | }, 20 | ], 21 | }, 22 | resolve: { 23 | modules: [ 24 | 'node_modules', 25 | path.resolve(__dirname, 'src'), 26 | ], 27 | extensions: ['.js'], 28 | }, 29 | plugins: [ 30 | new CopyWebpackPlugin([ 31 | { 32 | from: path.resolve(__dirname, 'static'), 33 | to: path.resolve(__dirname, 'dist'), 34 | ignore: ['*.ejs'], 35 | }, 36 | ]), 37 | new Dotenv({ 38 | path: envPath, 39 | defaults: defaultEnvPath, 40 | systemvars: true, 41 | }), 42 | ], 43 | } 44 | -------------------------------------------------------------------------------- /webpack.dev.js: -------------------------------------------------------------------------------- 1 | const path = require('path') 2 | const fs = require('fs') 3 | const merge = require('webpack-merge') 4 | const { HotModuleReplacementPlugin, DefinePlugin } = require('webpack') 5 | const HtmlWebpackPlugin = require('html-webpack-plugin') 6 | const GitRevisionPlugin = require('git-revision-webpack-plugin') 7 | 8 | const baseConfig = require('./webpack.base') 9 | const devServerConfig = require('./configs/devServer.config') 10 | 11 | const gitRevisionPlugin = new GitRevisionPlugin() 12 | 13 | module.exports = merge(baseConfig, { 14 | mode: 'development', 15 | devtool: 'inline-source-map', 16 | output: { 17 | filename: '[name].bundle.js', 18 | publicPath: '/', 19 | path: path.resolve(__dirname, 'dist'), 20 | }, 21 | devServer: devServerConfig, 22 | module: { 23 | rules: [ 24 | { 25 | test: /\.scss$/, 26 | use: [ 27 | 'style-loader', 28 | { 29 | loader: 'css-loader', 30 | options: { importLoaders: 1 }, 31 | }, 32 | { 33 | loader: 'sass-loader', 34 | options: { 35 | includePaths: [path.resolve(__dirname, 'src/styles')], 36 | data: '@import "./src/styles/_variables.scss";', 37 | }, 38 | }, 39 | ], 40 | }, 41 | ], 42 | }, 43 | plugins: [ 44 | new HtmlWebpackPlugin({ 45 | title: 'dev', 46 | template: path.resolve(__dirname, 'static/index.html'), 47 | inject: true, 48 | origin: `http://localhost:8888/`, 49 | }), 50 | new DefinePlugin({ 51 | DEV: true, 52 | 'process.env.version': JSON.stringify(gitRevisionPlugin.commithash().slice(0, 7)), // TODO: delete when real 53 | }), 54 | new HotModuleReplacementPlugin(), 55 | ], 56 | }) 57 | -------------------------------------------------------------------------------- /webpack.prod.js: -------------------------------------------------------------------------------- 1 | const path = require('path') 2 | const fs = require('fs') 3 | const merge = require('webpack-merge') 4 | const { DefinePlugin } = require('webpack') 5 | const CleanWebpackPlugin = require('clean-webpack-plugin') 6 | const MiniCssExtractPlugin = require('mini-css-extract-plugin') 7 | const OptimizeCssAssetsPlugin = require('optimize-css-assets-webpack-plugin') 8 | const CopyWebpackPlugin = require('copy-webpack-plugin') 9 | const HtmlWebpackPlugin = require('html-webpack-plugin') 10 | const CompressionPlugin = require('compression-webpack-plugin') 11 | const GitRevisionPlugin = require('git-revision-webpack-plugin') 12 | 13 | const baseConfig = require('./webpack.base') 14 | 15 | const gitRevisionPlugin = new GitRevisionPlugin() 16 | 17 | const ENV = process.env.NODE_ENV 18 | const isProduction = ENV === 'production' 19 | const isDev = ENV === 'dev' 20 | 21 | module.exports = merge(baseConfig, { 22 | mode: 'production', 23 | devtool: isDev ? 'cheap-eval-source-map' : false, 24 | output: { 25 | filename: '[name].[hash].bundle.js', 26 | chunkFilename: '[name].[chunkhash].js', 27 | publicPath: '/', 28 | path: path.resolve(__dirname, 'dist'), 29 | }, 30 | module: { 31 | rules: [ 32 | { 33 | test: /\.scss$/, 34 | use: [ 35 | MiniCssExtractPlugin.loader, 36 | { 37 | loader: 'css-loader', 38 | options: { importLoaders: 1 }, 39 | }, 40 | { 41 | loader: 'sass-loader', 42 | options: { 43 | includePaths: [path.resolve(__dirname, 'src/styles')], 44 | data: '@import "./src/styles/_variables.scss";', 45 | }, 46 | }, 47 | ], 48 | }, 49 | ], 50 | }, 51 | plugins: [ 52 | new CleanWebpackPlugin('dist', { root: __dirname }), 53 | new OptimizeCssAssetsPlugin(), 54 | new CopyWebpackPlugin([{ 55 | from: path.resolve(__dirname, 'static'), 56 | to: path.resolve(__dirname, 'dist'), 57 | ignore: ['*.ejs'], 58 | }]), 59 | new DefinePlugin({ 60 | DEV: false, 61 | 'process.env.NODE_ENV': JSON.stringify('production'), 62 | 'process.env.version': JSON.stringify(gitRevisionPlugin.commithash().slice(0, 7)), // TODO: delete when real 63 | }), 64 | new HtmlWebpackPlugin({ 65 | filename: 'index.html', 66 | template: path.resolve(__dirname, 'static/index.html'), 67 | inject: true, 68 | title: 'Klaytnscope', 69 | origin: process.env.SERVICE_URL, 70 | chunksSortMode: 'dependency', 71 | hash: true, 72 | }), 73 | new MiniCssExtractPlugin({ 74 | filename: 'bundle.[chunkHash].css', 75 | chunkFilename: 'bundle.[chunkHash].css', 76 | }), 77 | new CompressionPlugin({ 78 | filename: '[file].gz', 79 | algorithm: 'gzip', 80 | }), 81 | ], 82 | optimization: { 83 | splitChunks: { 84 | automaticNameDelimiter: '~', 85 | cacheGroups: { 86 | commons: { 87 | test: /[\\/]node_modules[\\/]/, 88 | chunks: 'all', 89 | name: 'vendor', 90 | enforce: true, 91 | }, 92 | styles: { 93 | name: 'styles', 94 | test: /\.css$/, 95 | chunks: 'all', 96 | enforce: true, 97 | }, 98 | }, 99 | }, 100 | }, 101 | }) 102 | --------------------------------------------------------------------------------