├── .gitignore ├── ipfs └── using_ipfs_with_caver │ ├── resources │ └── ipfs.txt │ └── index.js ├── .eslintignore ├── .prettierrc.js ├── .env ├── .github ├── ISSUE_TEMPLATE │ ├── --questions-and-others.md │ ├── ---enhancement.md │ └── ---bug-report.md ├── workflows │ └── CLA.yml ├── PULL_REQUEST_TEMPLATE.md └── CODEOWNERS ├── resources ├── KVstore.sol └── KVstore.abi ├── package.json ├── setup.sh ├── LICENSE ├── .eslintrc.js ├── assets └── index.js ├── hello_world └── index.js ├── wallet ├── create_multiple_eoas │ └── index.js └── sign_transaction │ └── index.js ├── transaction ├── send_klay │ └── index.js └── send_klay_with_keystore_file │ └── index.js ├── kct ├── deploy_kip7_token_contract_with_keystore_file │ └── index.js └── deploy_kip7_token_contract │ └── index.js ├── rpc └── klay_get_block_receipts │ └── index.js ├── contract ├── execute_smart_contract │ └── index.js ├── deploy_smart_contract │ └── index.js └── fee_delegation │ └── index.js ├── README.ko.md ├── account ├── update_account_with_account_key_public │ └── index.js ├── update_account_with_account_key_weighted_multisig │ └── index.js └── update_account_with_account_key_role_based │ └── index.js ├── utils └── play_with_units_in_klaytn │ └── index.js ├── CONTRIBUTING.md └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | .idea 3 | -------------------------------------------------------------------------------- /ipfs/using_ipfs_with_caver/resources/ipfs.txt: -------------------------------------------------------------------------------- 1 | Text which will be stored on IPFS 2 | -------------------------------------------------------------------------------- /.eslintignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | *.swp 3 | */**/*un~ 4 | *un~ 5 | */**/.DS_Store 6 | npm-debug.log 7 | .npm/ 8 | node_modules/ 9 | .idea/ 10 | .npm/ 11 | .vscode/ 12 | package-lock.json 13 | .git 14 | dist/* 15 | caver-cli -------------------------------------------------------------------------------- /.prettierrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | semi: false, 3 | printWidth: 140, 4 | singleQuote: true, 5 | arrowParens: 'avoid', 6 | bracketSpacing: true, 7 | tabWidth: 4, 8 | trailingComma: 'es5', 9 | } 10 | -------------------------------------------------------------------------------- /.env: -------------------------------------------------------------------------------- 1 | NODE_API_URL="https://node-api.klaytnapi.com/v1/klaytn" 2 | ACCESS_KEY_ID="" 3 | SECRET_ACCESS_KEY="" 4 | CHAIN_ID="1001" 5 | DEPLOYER_ADDRESS="" 6 | DEPLOYER_PRIVATE_KEY="" 7 | SENDER_ADDRESS="" 8 | SENDER_PRIVATE_KEY="" 9 | FEE_PAYER_ADDRESS="" 10 | FEE_PAYER_PRIVATE_KEY="" 11 | RECIPIENT_ADDRESS="" 12 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/--questions-and-others.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: "❓ Questions and Others" 3 | about: Questions regarding caver-js-examples or other issues not related to bug nor feature 4 | request 5 | title: '' 6 | labels: '' 7 | assignees: '' 8 | 9 | --- 10 | 11 | Freely describe your questions or issues here. 12 | -------------------------------------------------------------------------------- /resources/KVstore.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.5.6; 2 | 3 | contract KVstore { 4 | mapping(string=>string) store; 5 | constructor (string memory key, string memory value) public { 6 | store[key] = value; 7 | } 8 | function get(string memory key) public view returns (string memory) { 9 | return store[key]; 10 | } 11 | function set(string memory key, string memory value) public { 12 | store[key] = value; 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /resources/KVstore.abi: -------------------------------------------------------------------------------- 1 | [{"constant":true,"inputs":[{"name":"key","type":"string"}],"name":"get","outputs":[{"name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"key","type":"string"},{"name":"value","type":"string"}],"name":"set","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"inputs":[{"name":"key","type":"string"},{"name":"value","type":"string"}],"payable":false,"stateMutability":"nonpayable","type":"constructor"}] -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "caver-js-examples", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1", 8 | "lint": "eslint './**/*.js'", 9 | "lintFix": "eslint './**/*.js' --fix" 10 | }, 11 | "author": "", 12 | "license": "ISC", 13 | "dependencies": { 14 | "caver-js": "^1.6.3", 15 | "dotenv": "^8.2.0" 16 | }, 17 | "devDependencies": { 18 | "eslint": "^7.30.0", 19 | "eslint-config-airbnb": "^18.2.1", 20 | "eslint-config-prettier": "^8.3.0", 21 | "eslint-plugin-prettier": "^3.4.0", 22 | "prettier": "^2.3.2" 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/---enhancement.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: "\U0001F9E9 Enhancement" 3 | about: Suggest an improvement idea for this project 4 | title: '' 5 | labels: enhancement 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Is your request related to a problem? Please describe.** 11 | A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] 12 | 13 | **Describe the solution you'd like** 14 | A clear and concise description of what you want to happen. 15 | 16 | **Describe alternatives you've considered** 17 | A clear and concise description of any alternative solutions or features you've considered. 18 | 19 | **Additional context** 20 | Add any other context or screenshots about the feature request here. 21 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/---bug-report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: "\U0001F41C Bug report" 3 | about: Create a report to help us improve 4 | title: '' 5 | labels: bug 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Describe the bug** 11 | A clear and concise description of what the bug is. 12 | 13 | **How to reproduce** 14 | Steps to reproduce the behavior: 15 | 16 | **Expected behavior** 17 | A clear and concise description of what you expected to happen. 18 | 19 | **Attachments** 20 | If applicable, add data, logs or screenshots to help explain your problem. 21 | 22 | **Environment (please complete the following information)** 23 | - caver-js version or git revision that exhibits the issue 24 | - OS and its version [e.g. macOS/10.14] 25 | 26 | **Additional context** 27 | Add any other context about the problem here. 28 | -------------------------------------------------------------------------------- /setup.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | ## How to use this shell script 4 | # caver-js-examples$ ./setup.sh / 5 | # e.g. $ ./setup.sh account/update_account_with_account_key_weighted_multisig 6 | ## 7 | 8 | PROJECT_ROOT_DIR=$PWD 9 | ASSETS_DIR=$PROJECT_ROOT_DIR/assets 10 | BOILER_PLATE_TEMPLATE=$ASSETS_DIR/index.js 11 | NEW_SCENARIO=$1 12 | 13 | ## Tokenize $NEW_SCENARIO 14 | # input: account/update_account_with_account_key_weighted_multisig 15 | # then => COMMON_ARCHITECTURE_LAYER: account, SCENARIO_NAME: update_account_with_account_key_weighted_multisig 16 | ARR_IN=(${NEW_SCENARIO//\// }) 17 | ARR_LEN=${#ARR_IN[@]} 18 | COMMON_ARCHITECTURE_LAYER_NAME=${ARR_IN[0]} 19 | SCENARIO_NAME=${ARR_IN[$ARR_LEN - 1]} 20 | ## 21 | 22 | if [ ! -d $NEW_SCENARIO ]; then 23 | echo "Create project structure for $NEW_SCENARIO\n" 24 | mkdir -p $NEW_SCENARIO 25 | cp $BOILER_PLATE_TEMPLATE $NEW_SCENARIO 26 | fi 27 | -------------------------------------------------------------------------------- /.github/workflows/CLA.yml: -------------------------------------------------------------------------------- 1 | name: "CLA Assistant" 2 | on: 3 | issue_comment: 4 | types: [created] 5 | pull_request_target: 6 | types: [opened, closed, synchronize] 7 | 8 | jobs: 9 | CLAssistant: 10 | runs-on: ubuntu-latest 11 | steps: 12 | - name: "CLA Assistant" 13 | if: (github.event.comment.body == 'recheck' || github.event.comment.body == 'I have read the CLA Document and I hereby sign the CLA') || github.event_name == 'pull_request_target' 14 | uses: cla-assistant/github-action@v2.1.3-beta 15 | env: 16 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 17 | PERSONAL_ACCESS_TOKEN: ${{ secrets.CLA_PERSONAL_ACCESS_TOKEN }} 18 | with: 19 | path-to-signatures: "${{ github.event.repository.name }}/signatures/version1/cla.json" 20 | path-to-document: "https://gist.github.com/e78f99e1c527225637e269cff1bc7e49" # Klaytn Gist 21 | branch: "master" 22 | allowlist: dependabot[bot] 23 | remote-repository-name: ${{ secrets.CLA_REPOSITORY }} 24 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021 caver-js-examples 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 | -------------------------------------------------------------------------------- /.github/PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | ## Proposed changes 2 | 3 | - Describe your changes to communicate to the maintainers why we should accept this pull request. 4 | - If it fixes a bug or resolves a feature request, be sure to link to that issue. 5 | 6 | ## Types of changes 7 | 8 | Please put an x in the boxes related to your change. 9 | 10 | - [ ] Bugfix 11 | - [ ] New feature or enhancement 12 | - [ ] Others 13 | 14 | ## Checklist 15 | 16 | *Put an x in the boxes that apply. You can also fill these out after creating the PR. If you're unsure about any of them, don't hesitate to ask. We're here to help! This is simply a reminder of what we are going to look for before merging your code.* 17 | 18 | - [ ] I have read the [CONTRIBUTING GUIDELINES](https://github.com/klaytn/caver-js-examples/blob/master/CONTRIBUTING.md) doc 19 | - [ ] I have signed the [CLA](https://cla-assistant.io/klaytn/caver-js-examples) 20 | - [ ] Lint and unit tests pass locally with my changes 21 | - [ ] I have added tests that prove my fix is effective or that my feature works 22 | - [ ] I have added necessary documentation (if appropriate) 23 | - [ ] Any dependent changes have been merged and published in downstream modules 24 | 25 | ## Related issues 26 | 27 | - Please leave the issue numbers or links related to this PR here. 28 | 29 | ## Further comments 30 | 31 | If this is a relatively large or complex change, kick off the discussion by explaining why you chose the solution you did and what alternatives you considered, etc... 32 | -------------------------------------------------------------------------------- /.github/CODEOWNERS: -------------------------------------------------------------------------------- 1 | # This is a comment. 2 | # Each line is a file pattern followed by one or more owners. 3 | 4 | # These owners will be the default owners for everything in 5 | # the repo. Unless a later match takes precedence, 6 | # @global-owner1 and @global-owner2 will be requested for 7 | # review when someone opens a pull request. 8 | #* @global-owner1 @global-owner2 9 | * @kjhman21 @jimni1222 @sirano11 @aeharvlee 10 | 11 | # Order is important; the last matching pattern takes the most 12 | # precedence. When someone opens a pull request that only 13 | # modifies JS files, only @js-owner and not the global 14 | # owner(s) will be requested for a review. 15 | #*.js @js-owner 16 | 17 | # You can also use email addresses if you prefer. They'll be 18 | # used to look up users just like we do for commit author 19 | # emails. 20 | #*.go docs@example.com 21 | 22 | # In this example, @doctocat owns any files in the build/logs 23 | # directory at the root of the repository and any of its 24 | # subdirectories. 25 | #/build/logs/ @doctocat 26 | 27 | # The `docs/*` pattern will match files like 28 | # `docs/getting-started.md` but not further nested files like 29 | # `docs/build-app/troubleshooting.md`. 30 | #docs/* docs@example.com 31 | 32 | # In this example, @octocat owns any file in an apps directory 33 | # anywhere in your repository. 34 | #apps/ @octocat 35 | 36 | # In this example, @doctocat owns any file in the `/docs` 37 | # directory in the root of your repository. 38 | #/docs/ @doctocat 39 | -------------------------------------------------------------------------------- /.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | extends: ['airbnb', 'prettier'], 3 | env: { 4 | commonjs: true, 5 | node: true, 6 | mocha: true, 7 | }, 8 | plugins: ['prettier'], 9 | rules: { 10 | 'prettier/prettier': ['error'], 11 | radix: 0, 12 | eqeqeq: 0, 13 | 'new-cap': 0, 14 | 'no-empty': 0, 15 | 'no-console': 0, 16 | 'no-bitwise': 0, 17 | 'func-names': 0, 18 | 'no-continue': 0, 19 | 'no-plusplus': 0, 20 | 'no-sequences': 0, 21 | 'default-case': 0, 22 | 'guard-for-in': 0, 23 | 'prefer-spread': 0, 24 | 'global-require': 0, 25 | 'no-await-in-loop': 0, 26 | 'no-control-regex': 0, 27 | 'object-shorthand': 0, 28 | 'no-return-assign': 0, 29 | 'consistent-return': 0, 30 | 'no-nested-ternary': 0, 31 | 'no-param-reassign': 0, 32 | 'prefer-rest-params': 0, 33 | 'no-use-before-define': 0, 34 | 'no-restricted-syntax': 0, 35 | 'no-underscore-dangle': 0, 36 | 'prefer-destructuring': 0, 37 | 'no-case-declarations': 0, 38 | 'no-restricted-globals': 0, 39 | 'array-callback-return': 0, 40 | 'no-unused-expressions': 0, 41 | 'import/no-dynamic-require': 0, 42 | 'import/no-extraneous-dependencies': 0, 43 | 'import/no-named-as-default': 0, 44 | 'import/no-named-as-default-member': 0, 45 | 'no-prototype-builtins': 0, 46 | 'no-proto': 1, 47 | 'prefer-const': 1, 48 | 'no-multi-assign': 1, 49 | 'class-methods-use-this': 1, 50 | 'no-undef': 1, 51 | 'no-unused-vars': 1, 52 | 'no-useless-constructor': 1, 53 | 'no-empty-function': 1, 54 | }, 55 | } 56 | -------------------------------------------------------------------------------- /assets/index.js: -------------------------------------------------------------------------------- 1 | const path = require('path') 2 | const dotenv = require('dotenv') 3 | const Caver = require('caver-js') 4 | 5 | const ROOT_DIR = path.join(__dirname, '../..') // Path can be changed based on its actual location. 6 | 7 | // You can directly input values for the variables below, or you can enter values in the caver-js-examples/.env file. 8 | let nodeApiUrl = '' // e.g. 'https://node-api.klaytnapi.com/v1/klaytn' 9 | let accessKeyId = '' // e.g. 'KASK1LVNO498YT6KJQFUPY8S' 10 | let secretAccessKey = '' // e.g. 'aP/reVYHXqjw3EtQrMuJP4A3/hOb69TjnBT3ePKG' 11 | let chainId = '' // e.g. '1001' or '8217' 12 | let senderAddress = '' // e.g. '0xeb709d59954f4cdc6b6f3bfcd8d531887b7bd199' 13 | let senderPrivateKey = '' // e.g. '0x39a6375b608c2572fadb2ed9fd78c5c456ca3aa860c43192ad910c3269727fc1' 14 | 15 | /** 16 | * Example code about "How to ..." 17 | * Related article - Korean: 18 | * Related article - English: 19 | */ 20 | async function main() { 21 | try { 22 | loadEnv() 23 | await run() 24 | } catch (err) { 25 | console.error(err) 26 | } 27 | } 28 | 29 | main() 30 | 31 | function loadEnv() { 32 | envs = dotenv.config({ path: `${ROOT_DIR}/.env` }) 33 | if (envs.error) { 34 | throw envs.error 35 | } 36 | 37 | nodeApiUrl = nodeApiUrl === '' ? envs.parsed.NODE_API_URL : nodeApiUrl 38 | accessKeyId = accessKeyId === '' ? envs.parsed.ACCESS_KEY_ID : accessKeyId 39 | secretAccessKey = secretAccessKey === '' ? envs.parsed.SECRET_ACCESS_KEY : secretAccessKey 40 | chainId = chainId === '' ? envs.parsed.CHAIN_ID : chainId 41 | senderAddress = senderAddress === '' ? envs.parsed.SENDER_ADDRESS : senderAddress 42 | senderPrivateKey = senderPrivateKey === '' ? envs.parsed.SENDER_PRIVATE_KEY : senderPrivateKey 43 | } 44 | 45 | async function run() { 46 | const option = { 47 | headers: [ 48 | { 49 | name: 'Authorization', 50 | value: `Basic ${Buffer.from(`${accessKeyId}:${secretAccessKey}`).toString('base64')}`, 51 | }, 52 | { name: 'x-chain-id', value: chainId }, 53 | ], 54 | } 55 | const caver = new Caver(new Caver.providers.HttpProvider(nodeApiUrl, option)) 56 | 57 | // Write your own index.js... 58 | } 59 | -------------------------------------------------------------------------------- /hello_world/index.js: -------------------------------------------------------------------------------- 1 | const path = require('path') 2 | const dotenv = require('dotenv') 3 | const Caver = require('caver-js') 4 | 5 | const ROOT_DIR = path.join(__dirname, '..') // Path can be changed based on its actual location. 6 | 7 | // You can directly input values for the variables below, or you can enter values in the caver-js-examples/.env file. 8 | let nodeApiUrl = 'https://node-api.klaytnapi.com/v1/klaytn' // e.g. 'https://node-api.klaytnapi.com/v1/klaytn' 9 | let accessKeyId = '' // e.g. 'KASK1LVNO498YT6KJQFUPY8S' 10 | let secretAccessKey = '' // e.g. 'aP/reVYHXqjw3EtQrMuJP4A3/hOb69TjnBT3ePKG' 11 | let chainId = '1001' // e.g. '1001' or '8217' 12 | 13 | /** 14 | * Hello world for caver-js Klaytn SDK! Please read the README before starting :) 15 | * Related article - Korean: https://ko.docs.klaytn.com/bapp/sdk/caver-js/getting-started 16 | * Related reference - English: https://docs.klaytn.com/bapp/sdk/caver-js/getting-started 17 | */ 18 | async function main() { 19 | try { 20 | loadEnv() 21 | await run() 22 | } catch (err) { 23 | console.error(err) 24 | } 25 | } 26 | 27 | main() 28 | 29 | function loadEnv() { 30 | envs = dotenv.config({ path: `${ROOT_DIR}/.env` }) 31 | if (envs.error) { 32 | throw envs.error 33 | } 34 | 35 | nodeApiUrl = nodeApiUrl === '' ? envs.parsed.NODE_API_URL : nodeApiUrl 36 | accessKeyId = accessKeyId === '' ? envs.parsed.ACCESS_KEY_ID : accessKeyId 37 | secretAccessKey = secretAccessKey === '' ? envs.parsed.SECRET_ACCESS_KEY : secretAccessKey 38 | chainId = chainId === '' ? envs.parsed.CHAIN_ID : chainId 39 | } 40 | 41 | async function run() { 42 | // In the caver, almost everything starts with the caver. Let's create a caver instance 43 | const option = { 44 | headers: [ 45 | { 46 | name: 'Authorization', 47 | value: `Basic ${Buffer.from(`${accessKeyId}:${secretAccessKey}`).toString('base64')}`, 48 | }, 49 | { name: 'x-chain-id', value: chainId }, 50 | ], 51 | } 52 | const caver = new Caver(new Caver.providers.HttpProvider(nodeApiUrl, option)) 53 | 54 | // Now that we have created the caver instance, we can do whatever we want with the caver. 55 | // Write your own code below using Caver instance :) 56 | const singleKeyring = caver.wallet.keyring.generate() 57 | console.log(singleKeyring) 58 | } 59 | -------------------------------------------------------------------------------- /wallet/create_multiple_eoas/index.js: -------------------------------------------------------------------------------- 1 | const path = require('path') 2 | const dotenv = require('dotenv') 3 | const Caver = require('caver-js') 4 | 5 | const ROOT_DIR = path.join(__dirname, '../..') // Path can be changed based on its actual location. 6 | 7 | // You can directly input values for the variables below, or you can enter values in the caver-js-examples/.env file. 8 | let nodeApiUrl = '' // e.g. 'https://node-api.klaytnapi.com/v1/klaytn' 9 | let accessKeyId = '' // e.g. 'KASK1LVNO498YT6KJQFUPY8S' 10 | let secretAccessKey = '' // e.g. 'aP/reVYHXqjw3EtQrMuJP4A3/hOb69TjnBT3ePKG' 11 | let chainId = '' // e.g. '1001' or '8217' 12 | let senderAddress = '' // e.g. '0xeb709d59954f4cdc6b6f3bfcd8d531887b7bd199' 13 | let senderPrivateKey = '' // e.g. '0x39a6375b608c2572fadb2ed9fd78c5c456ca3aa860c43192ad910c3269727fc1' 14 | 15 | /** 16 | * Example code about "How to create many EOAs easily." 17 | * Related reference - Korean: https://ko.docs.klaytn.com/klaytn/design/accounts#externally-owned-accounts-eoas 18 | * Related reference - English: https://docs.klaytn.com/klaytn/design/accounts#externally-owned-accounts-eoas 19 | */ 20 | async function main() { 21 | try { 22 | loadEnv() 23 | await run() 24 | } catch (err) { 25 | console.error(err) 26 | } 27 | } 28 | 29 | main() 30 | 31 | function loadEnv() { 32 | envs = dotenv.config({ path: `${ROOT_DIR}/.env` }) 33 | if (envs.error) { 34 | throw envs.error 35 | } 36 | 37 | nodeApiUrl = nodeApiUrl === '' ? envs.parsed.NODE_API_URL : nodeApiUrl 38 | accessKeyId = accessKeyId === '' ? envs.parsed.ACCESS_KEY_ID : accessKeyId 39 | secretAccessKey = secretAccessKey === '' ? envs.parsed.SECRET_ACCESS_KEY : secretAccessKey 40 | chainId = chainId === '' ? envs.parsed.CHAIN_ID : chainId 41 | senderAddress = senderAddress === '' ? envs.parsed.SENDER_ADDRESS : senderAddress 42 | senderPrivateKey = senderPrivateKey === '' ? envs.parsed.SENDER_PRIVATE_KEY : senderPrivateKey 43 | } 44 | 45 | async function run() { 46 | const option = { 47 | headers: [ 48 | { 49 | name: 'Authorization', 50 | value: `Basic ${Buffer.from(`${accessKeyId}:${secretAccessKey}`).toString('base64')}`, 51 | }, 52 | { name: 'x-chain-id', value: chainId }, 53 | ], 54 | } 55 | const caver = new Caver(new Caver.providers.HttpProvider(nodeApiUrl, option)) 56 | 57 | const numEOAs = 10 58 | const eoas = [] 59 | for (let i = 0; i < numEOAs; i++) { 60 | eoas.push(caver.wallet.keyring.generate()) 61 | } 62 | console.log(`Succeed to create ${numEOAs} EOAs using SingleKey.`) 63 | console.log(eoas) 64 | } 65 | -------------------------------------------------------------------------------- /transaction/send_klay/index.js: -------------------------------------------------------------------------------- 1 | const path = require('path') 2 | const dotenv = require('dotenv') 3 | const Caver = require('caver-js') 4 | 5 | const ROOT_DIR = path.join(__dirname, '../..') // Path can be changed based on its actual location. 6 | 7 | // You can directly input values for the variables below, or you can enter values in the caver-js-examples/.env file. 8 | let nodeApiUrl = '' // e.g. 'https://node-api.klaytnapi.com/v1/klaytn' 9 | let accessKeyId = '' // e.g. 'KASK1LVNO498YT6KJQFUPY8S' 10 | let secretAccessKey = '' // e.g. 'aP/reVYHXqjw3EtQrMuJP4A3/hOb69TjnBT3ePKG' 11 | let chainId = '' // e.g. '1001' or '8217' 12 | let senderAddress = '' // e.g. '0xeb709d59954f4cdc6b6f3bfcd8d531887b7bd199' 13 | let senderPrivateKey = '' // e.g. '0x39a6375b608c2572fadb2ed9fd78c5c456ca3aa860c43192ad910c3269727fc1' 14 | let recipientAddress = '' // e.g. '0xeb709d59954f4cdc6b6f3bfcd8d531887b7bd199' 15 | 16 | /** 17 | * Example code about "How to send Klay." 18 | * Related reference - Korean: https://ko.docs.klaytn.com/bapp/sdk/caver-js/getting-started#sending-klay-at-a-glance 19 | * Related reference - English: https://docs.klaytn.com/bapp/sdk/caver-js/getting-started#sending-klay-at-a-glance 20 | */ 21 | async function main() { 22 | try { 23 | loadEnv() 24 | await run() 25 | } catch (err) { 26 | console.error(err) 27 | } 28 | } 29 | 30 | main() 31 | 32 | function loadEnv() { 33 | envs = dotenv.config({ path: `${ROOT_DIR}/.env` }) 34 | if (envs.error) { 35 | throw envs.error 36 | } 37 | 38 | nodeApiUrl = nodeApiUrl === '' ? envs.parsed.NODE_API_URL : nodeApiUrl 39 | accessKeyId = accessKeyId === '' ? envs.parsed.ACCESS_KEY_ID : accessKeyId 40 | secretAccessKey = secretAccessKey === '' ? envs.parsed.SECRET_ACCESS_KEY : secretAccessKey 41 | chainId = chainId === '' ? envs.parsed.CHAIN_ID : chainId 42 | senderAddress = senderAddress === '' ? envs.parsed.SENDER_ADDRESS : senderAddress 43 | senderPrivateKey = senderPrivateKey === '' ? envs.parsed.SENDER_PRIVATE_KEY : senderPrivateKey 44 | recipientAddress = recipientAddress === '' ? envs.parsed.RECIPIENT_ADDRESS : recipientAddress 45 | } 46 | 47 | async function run() { 48 | const option = { 49 | headers: [ 50 | { 51 | name: 'Authorization', 52 | value: `Basic ${Buffer.from(`${accessKeyId}:${secretAccessKey}`).toString('base64')}`, 53 | }, 54 | { name: 'x-chain-id', value: chainId }, 55 | ], 56 | } 57 | const caver = new Caver(new Caver.providers.HttpProvider(nodeApiUrl, option)) 58 | 59 | const senderKeyring = caver.wallet.keyring.create(senderAddress, senderPrivateKey) 60 | caver.wallet.add(senderKeyring) 61 | 62 | // Send 1 KLAY. 63 | const vt = caver.transaction.valueTransfer.create({ 64 | from: senderKeyring.address, 65 | to: recipientAddress, 66 | value: caver.utils.convertToPeb(1, caver.utils.klayUnit.KLAY.unit), 67 | gas: 25000, 68 | }) 69 | await caver.wallet.sign(senderKeyring.address, vt) 70 | const receipt = await caver.rpc.klay.sendRawTransaction(vt) 71 | console.log(receipt) 72 | } 73 | -------------------------------------------------------------------------------- /wallet/sign_transaction/index.js: -------------------------------------------------------------------------------- 1 | const path = require('path') 2 | const dotenv = require('dotenv') 3 | const Caver = require('caver-js') 4 | 5 | const ROOT_DIR = path.join(__dirname, '../..') // Path can be changed based on its actual location. 6 | 7 | // You can directly input values for the variables below, or you can enter values in the caver-js-examples/.env file. 8 | let nodeApiUrl = '' // e.g. 'https://node-api.klaytnapi.com/v1/klaytn' 9 | let accessKeyId = '' // e.g. 'KASK1LVNO498YT6KJQFUPY8S' 10 | let secretAccessKey = '' // e.g. 'aP/reVYHXqjw3EtQrMuJP4A3/hOb69TjnBT3ePKG' 11 | let chainId = '' // e.g. '1001' or '8217' 12 | let senderAddress = '' // e.g. '0xeb709d59954f4cdc6b6f3bfcd8d531887b7bd199' 13 | let senderPrivateKey = '' // e.g. '0x39a6375b608c2572fadb2ed9fd78c5c456ca3aa860c43192ad910c3269727fc1' 14 | let recipientAddress = '' // e.g. '0xeb709d59954f4cdc6b6f3bfcd8d531887b7bd199' 15 | 16 | /** 17 | * Example code about "How to sign transaction using Wallet" 18 | * Related reference - Korean: https://ko.docs.klaytn.com/bapp/sdk/caver-js/getting-started#sending-a-value-transfer-transaction 19 | * Related reference - English: https://docs.klaytn.com/bapp/sdk/caver-js/getting-started#sending-a-value-transfer-transaction 20 | */ 21 | async function main() { 22 | try { 23 | loadEnv() 24 | await run() 25 | } catch (err) { 26 | console.error(err) 27 | } 28 | } 29 | 30 | main() 31 | 32 | function loadEnv() { 33 | envs = dotenv.config({ path: `${ROOT_DIR}/.env` }) 34 | if (envs.error) { 35 | throw envs.error 36 | } 37 | 38 | nodeApiUrl = nodeApiUrl === '' ? envs.parsed.NODE_API_URL : nodeApiUrl 39 | accessKeyId = accessKeyId === '' ? envs.parsed.ACCESS_KEY_ID : accessKeyId 40 | secretAccessKey = secretAccessKey === '' ? envs.parsed.SECRET_ACCESS_KEY : secretAccessKey 41 | chainId = chainId === '' ? envs.parsed.CHAIN_ID : chainId 42 | senderAddress = senderAddress === '' ? envs.parsed.SENDER_ADDRESS : senderAddress 43 | senderPrivateKey = senderPrivateKey === '' ? envs.parsed.SENDER_PRIVATE_KEY : senderPrivateKey 44 | recipientAddress = recipientAddress === '' ? envs.parsed.RECIPIENT_ADDRESS : recipientAddress 45 | } 46 | 47 | async function run() { 48 | const option = { 49 | headers: [ 50 | { 51 | name: 'Authorization', 52 | value: `Basic ${Buffer.from(`${accessKeyId}:${secretAccessKey}`).toString('base64')}`, 53 | }, 54 | { name: 'x-chain-id', value: chainId }, 55 | ], 56 | } 57 | const caver = new Caver(new Caver.providers.HttpProvider(nodeApiUrl, option)) 58 | 59 | const senderKeyring = caver.wallet.keyring.create(senderAddress, senderPrivateKey) 60 | 61 | const vt = caver.transaction.valueTransfer.create({ 62 | from: senderKeyring.address, 63 | to: recipientAddress, 64 | value: caver.utils.convertToPeb(1, caver.utils.klayUnit.KLAY.unit), 65 | gas: 25000, 66 | }) 67 | console.log('Before sign the transaction using wallet, there is no signatures.') 68 | console.log(vt.signatures) 69 | 70 | // Signing process 71 | console.log('Add a senderKeyring to `caver.wallet`.') 72 | caver.wallet.add(senderKeyring) 73 | console.log('Sign the transaction using `caver.wallet`.') 74 | await caver.wallet.sign(senderKeyring.address, vt) 75 | console.log('Signature was added, so we can see the signature of sender.') 76 | console.log(vt.signatures) 77 | } 78 | -------------------------------------------------------------------------------- /kct/deploy_kip7_token_contract_with_keystore_file/index.js: -------------------------------------------------------------------------------- 1 | const fs = require('fs') 2 | const path = require('path') 3 | const dotenv = require('dotenv') 4 | const Caver = require('caver-js') 5 | const BigNumber = require('bignumber.js') 6 | 7 | const ROOT_DIR = path.join(__dirname, '../..') // Path can be changed based on its actual location. 8 | 9 | // You can directly input values for the variables below, or you can enter values in the caver-js-examples/.env file. 10 | let nodeApiUrl = '' // e.g. 'https://node-api.klaytnapi.com/v1/klaytn' 11 | let accessKeyId = '' // e.g. 'KASK1LVNO498YT6KJQFUPY8S' 12 | let secretAccessKey = '' // e.g. 'aP/reVYHXqjw3EtQrMuJP4A3/hOb69TjnBT3ePKG' 13 | let chainId = '' // e.g. '1001' or '8217' 14 | let recipientAddress = '' // e.g. '0xeb709d59954f4cdc6b6f3bfcd8d531887b7bd199' 15 | 16 | /** 17 | * Example code about "How to deploy my own KIP7 token with keystore file." 18 | * Related article - Korean: https://medium.com/klaytn/common-architecture-of-caver-f7a7a1c554de 19 | * Related article - English: https://medium.com/klaytn/common-architecture-of-caver-a714224a0047 20 | */ 21 | async function main() { 22 | try { 23 | loadEnv() 24 | await run() 25 | } catch (err) { 26 | console.error(err) 27 | } 28 | } 29 | 30 | main() 31 | 32 | function loadEnv() { 33 | envs = dotenv.config({ path: `${ROOT_DIR}/.env` }) 34 | if (envs.error) { 35 | throw envs.error 36 | } 37 | 38 | nodeApiUrl = nodeApiUrl === '' ? envs.parsed.NODE_API_URL : nodeApiUrl 39 | accessKeyId = accessKeyId === '' ? envs.parsed.ACCESS_KEY_ID : accessKeyId 40 | secretAccessKey = secretAccessKey === '' ? envs.parsed.SECRET_ACCESS_KEY : secretAccessKey 41 | chainId = chainId === '' ? envs.parsed.CHAIN_ID : chainId 42 | recipientAddress = recipientAddress === '' ? envs.parsed.RECIPIENT_ADDRESS : recipientAddress 43 | } 44 | 45 | async function run() { 46 | const option = { 47 | headers: [ 48 | { 49 | name: 'Authorization', 50 | value: `Basic ${Buffer.from(`${accessKeyId}:${secretAccessKey}`).toString('base64')}`, 51 | }, 52 | { name: 'x-chain-id', value: chainId }, 53 | ], 54 | } 55 | const caver = new Caver(new Caver.providers.HttpProvider(nodeApiUrl, option)) 56 | 57 | // 1. Create your own keystore file at "https://baobab.wallet.klaytn.com/create". 58 | // 2. Rename that keystore file name with `keystore.json` or change the filename in line 60. 59 | // 3. Place that keystore file at `caver-js-examples/kct/deploy_kip7_token_contract_with_keystore_file/resources`. 60 | // 4. Get 5 KLAY at "https://baobab.wallet.klaytn.com/faucet". 61 | const keystore = fs.readFileSync(`${__dirname}/resources/keystore.json`, 'utf8') 62 | const password = '' // Put your password here. 63 | const deployerKeyring = caver.wallet.keyring.decrypt(keystore, password) 64 | caver.wallet.add(deployerKeyring) 65 | 66 | const initialSupply = new BigNumber('1000000000000000000') 67 | const params = { name: 'TestToken', symbol: 'TTK', decimals: 18, initialSupply } 68 | const kip7 = await caver.kct.kip7.deploy(params, deployerKeyring.address) 69 | console.log(`Deployed address of KIP7 token contract: ${kip7.options.address}`) 70 | 71 | const name = await kip7.name() 72 | console.log(`The name of the KIP-7 token contract: ${name}`) 73 | 74 | const opts = { from: deployerKeyring.address } 75 | const value = 1 76 | const receipt = await kip7.transfer(recipientAddress, value, opts) 77 | console.log(receipt) 78 | } 79 | -------------------------------------------------------------------------------- /kct/deploy_kip7_token_contract/index.js: -------------------------------------------------------------------------------- 1 | const path = require('path') 2 | const dotenv = require('dotenv') 3 | const Caver = require('caver-js') 4 | const BigNumber = require('bignumber.js') 5 | 6 | const ROOT_DIR = path.join(__dirname, '../..') // Path can be changed based on its actual location. 7 | 8 | // You can directly input values for the variables below, or you can enter values in the caver-js-examples/.env file. 9 | let nodeApiUrl = '' // e.g. 'https://node-api.klaytnapi.com/v1/klaytn' 10 | let accessKeyId = '' // e.g. 'KASK1LVNO498YT6KJQFUPY8S' 11 | let secretAccessKey = '' // e.g. 'aP/reVYHXqjw3EtQrMuJP4A3/hOb69TjnBT3ePKG' 12 | let chainId = '' // e.g. '1001' or '8217' 13 | let deployerAddress = '' // e.g. '0xeb709d59954f4cdc6b6f3bfcd8d531887b7bd199' 14 | let deployerPrivateKey = '' // e.g. '0x39a6375b608c2572fadb2ed9fd78c5c456ca3aa860c43192ad910c3269727fc1' 15 | let recipientAddress = '' // e.g. '0xeb709d59954f4cdc6b6f3bfcd8d531887b7bd199' 16 | 17 | /** 18 | * Example code about "How to deploy my own KIP7 token." 19 | * Related reference - Korean: https://ko.docs.klaytn.com/bapp/sdk/caver-js/api-references/caver.kct/kip7 20 | * Related reference - English: https://docs.klaytn.com/bapp/sdk/caver-js/api-references/caver.kct/kip7 21 | */ 22 | async function main() { 23 | try { 24 | loadEnv() 25 | await run() 26 | } catch (err) { 27 | console.error(err) 28 | } 29 | } 30 | 31 | main() 32 | 33 | function loadEnv() { 34 | envs = dotenv.config({ path: `${ROOT_DIR}/.env` }) 35 | if (envs.error) { 36 | throw envs.error 37 | } 38 | 39 | nodeApiUrl = nodeApiUrl === '' ? envs.parsed.NODE_API_URL : nodeApiUrl 40 | accessKeyId = accessKeyId === '' ? envs.parsed.ACCESS_KEY_ID : accessKeyId 41 | secretAccessKey = secretAccessKey === '' ? envs.parsed.SECRET_ACCESS_KEY : secretAccessKey 42 | chainId = chainId === '' ? envs.parsed.CHAIN_ID : chainId 43 | deployerAddress = deployerAddress === '' ? envs.parsed.DEPLOYER_ADDRESS : deployerAddress 44 | deployerPrivateKey = deployerPrivateKey === '' ? envs.parsed.DEPLOYER_PRIVATE_KEY : deployerPrivateKey 45 | recipientAddress = recipientAddress === '' ? envs.parsed.RECIPIENT_ADDRESS : recipientAddress 46 | } 47 | 48 | async function run() { 49 | const option = { 50 | headers: [ 51 | { 52 | name: 'Authorization', 53 | value: `Basic ${Buffer.from(`${accessKeyId}:${secretAccessKey}`).toString('base64')}`, 54 | }, 55 | { name: 'x-chain-id', value: chainId }, 56 | ], 57 | } 58 | const caver = new Caver(new Caver.providers.HttpProvider(nodeApiUrl, option)) 59 | 60 | // Deployer account must have KLAY enough to deploy contract. 61 | // If you are testing on the Baobab testnet, 62 | // you can get 5 KLAY at "https://baobab.wallet.klaytn.com/faucet". 63 | const deployerKeyring = caver.wallet.keyring.create(deployerAddress, deployerPrivateKey) 64 | caver.wallet.add(deployerKeyring) 65 | 66 | const initialSupply = new BigNumber('1000000000000000000') 67 | const params = { name: 'TestToken', symbol: 'TTK', decimals: 18, initialSupply } 68 | const kip7 = await caver.kct.kip7.deploy(params, deployerKeyring.address) 69 | console.log(`Deployed address of KIP7 token contract: ${kip7.options.address}`) 70 | 71 | const name = await kip7.name() 72 | console.log(`The name of the KIP-7 token contract: ${name}`) 73 | 74 | const opts = { from: deployerKeyring.address } 75 | const value = 1 76 | const receipt = await kip7.transfer(recipientAddress, value, opts) 77 | console.log(receipt) 78 | } 79 | -------------------------------------------------------------------------------- /transaction/send_klay_with_keystore_file/index.js: -------------------------------------------------------------------------------- 1 | const fs = require('fs') 2 | const path = require('path') 3 | const dotenv = require('dotenv') 4 | const Caver = require('caver-js') 5 | 6 | const ROOT_DIR = path.join(__dirname, '../..') // Path can be changed based on its actual location. 7 | 8 | // You can directly input values for the variables below, or you can enter values in the caver-js-examples/.env file. 9 | let nodeApiUrl = '' // e.g. 'https://node-api.klaytnapi.com/v1/klaytn' 10 | let accessKeyId = '' // e.g. 'KASK1LVNO498YT6KJQFUPY8S' 11 | let secretAccessKey = '' // e.g. 'aP/reVYHXqjw3EtQrMuJP4A3/hOb69TjnBT3ePKG' 12 | let chainId = '' // e.g. '1001' or '8217' 13 | let senderAddress = '' // e.g. '0xeb709d59954f4cdc6b6f3bfcd8d531887b7bd199' 14 | let senderPrivateKey = '' // e.g. '0x39a6375b608c2572fadb2ed9fd78c5c456ca3aa860c43192ad910c3269727fc1' 15 | let recipientAddress = '' // e.g. '0xeb709d59954f4cdc6b6f3bfcd8d531887b7bd199' 16 | 17 | /** 18 | * Example code about "How to send KLAY with keystore file." 19 | * Related article - Korean: https://medium.com/klaytn/common-architecture-of-caver-f7a7a1c554de 20 | * Related article - English: https://medium.com/klaytn/common-architecture-of-caver-a714224a0047 21 | */ 22 | async function main() { 23 | try { 24 | loadEnv() 25 | await run() 26 | } catch (err) { 27 | console.error(err) 28 | } 29 | } 30 | 31 | main() 32 | 33 | function loadEnv() { 34 | envs = dotenv.config({ path: `${ROOT_DIR}/.env` }) 35 | if (envs.error) { 36 | throw envs.error 37 | } 38 | 39 | nodeApiUrl = nodeApiUrl === '' ? envs.parsed.NODE_API_URL : nodeApiUrl 40 | accessKeyId = accessKeyId === '' ? envs.parsed.ACCESS_KEY_ID : accessKeyId 41 | secretAccessKey = secretAccessKey === '' ? envs.parsed.SECRET_ACCESS_KEY : secretAccessKey 42 | chainId = chainId === '' ? envs.parsed.CHAIN_ID : chainId 43 | senderAddress = senderAddress === '' ? envs.parsed.SENDER_ADDRESS : senderAddress 44 | senderPrivateKey = senderPrivateKey === '' ? envs.parsed.SENDER_PRIVATE_KEY : senderPrivateKey 45 | recipientAddress = recipientAddress === '' ? envs.parsed.RECIPIENT_ADDRESS : recipientAddress 46 | } 47 | 48 | async function run() { 49 | const option = { 50 | headers: [ 51 | { 52 | name: 'Authorization', 53 | value: `Basic ${Buffer.from(`${accessKeyId}:${secretAccessKey}`).toString('base64')}`, 54 | }, 55 | { name: 'x-chain-id', value: chainId }, 56 | ], 57 | } 58 | const caver = new Caver(new Caver.providers.HttpProvider(nodeApiUrl, option)) 59 | 60 | // 1. Create your own keystore file at "https://baobab.wallet.klaytn.com/create". 61 | // 2. Rename that keystore file name with `keystore.json` or change the filename in line 63. 62 | // 3. Place that keystore file at `caver-js-examples/kct/deploy_kip7_token_contract_with_keystore_file/resources`. 63 | // 4. Get 5 KLAY at "https://baobab.wallet.klaytn.com/faucet". 64 | const keystore = fs.readFileSync(`${__dirname}/resources/keystore.json`, 'utf8') 65 | const password = '' // Put your password here. 66 | const senderKeyring = caver.wallet.keyring.decrypt(keystore, password) 67 | caver.wallet.add(senderKeyring) 68 | 69 | // Send 1 KLAY. 70 | const vt = caver.transaction.valueTransfer.create({ 71 | from: senderKeyring.address, 72 | to: recipientAddress, 73 | value: caver.utils.convertToPeb(1, caver.utils.klayUnit.KLAY.unit), 74 | gas: 25000, 75 | }) 76 | await caver.wallet.sign(senderKeyring.address, vt) 77 | const receipt = await caver.rpc.klay.sendRawTransaction(vt) 78 | console.log(receipt) 79 | } 80 | -------------------------------------------------------------------------------- /rpc/klay_get_block_receipts/index.js: -------------------------------------------------------------------------------- 1 | const path = require('path') 2 | const dotenv = require('dotenv') 3 | const Caver = require('caver-js') 4 | 5 | const ROOT_DIR = path.join(__dirname, '../..') // Path can be changed based on its actual location. 6 | 7 | // You can directly input values for the variables below, or you can enter values in the caver-js-examples/.env file. 8 | let nodeApiUrl = '' // e.g. 'https://node-api.klaytnapi.com/v1/klaytn' 9 | let accessKeyId = '' // e.g. 'KASK1LVNO498YT6KJQFUPY8S' 10 | let secretAccessKey = '' // e.g. 'aP/reVYHXqjw3EtQrMuJP4A3/hOb69TjnBT3ePKG' 11 | let chainId = '' // e.g. '1001' or '8217' 12 | let senderAddress = '' // e.g. '0xeb709d59954f4cdc6b6f3bfcd8d531887b7bd199' 13 | let senderPrivateKey = '' // e.g. '0x39a6375b608c2572fadb2ed9fd78c5c456ca3aa860c43192ad910c3269727fc1' 14 | 15 | /** 16 | * Example code about "How to get receipts included in a block." 17 | * Related reference - Korean: https://ko.docs.klaytn.com/bapp/json-rpc/api-references/klay/block#klay_getblockreceipts 18 | * Related reference - English: https://docs.klaytn.com/bapp/json-rpc/api-references/klay/block#klay_getblockreceipts 19 | */ 20 | async function main() { 21 | try { 22 | loadEnv() 23 | await run() 24 | } catch (err) { 25 | console.error(err) 26 | } 27 | } 28 | 29 | main() 30 | 31 | function loadEnv() { 32 | envs = dotenv.config({ path: `${ROOT_DIR}/.env` }) 33 | if (envs.error) { 34 | throw envs.error 35 | } 36 | 37 | nodeApiUrl = nodeApiUrl === '' ? envs.parsed.NODE_API_URL : nodeApiUrl 38 | accessKeyId = accessKeyId === '' ? envs.parsed.ACCESS_KEY_ID : accessKeyId 39 | secretAccessKey = secretAccessKey === '' ? envs.parsed.SECRET_ACCESS_KEY : secretAccessKey 40 | chainId = chainId === '' ? envs.parsed.CHAIN_ID : chainId 41 | senderAddress = senderAddress === '' ? envs.parsed.SENDER_ADDRESS : senderAddress 42 | senderPrivateKey = senderPrivateKey === '' ? envs.parsed.SENDER_PRIVATE_KEY : senderPrivateKey 43 | } 44 | 45 | async function run() { 46 | const option = { 47 | headers: [ 48 | { 49 | name: 'Authorization', 50 | value: `Basic ${Buffer.from(`${accessKeyId}:${secretAccessKey}`).toString('base64')}`, 51 | }, 52 | { name: 'x-chain-id', value: chainId }, 53 | ], 54 | } 55 | const caver = new Caver(new Caver.providers.HttpProvider(nodeApiUrl, option)) 56 | 57 | // This is for testing Baobab Network (Test-net) 58 | // If there are no transactions in the block being looked up, the returned data will be empty. 59 | const baobabBlockHashEmpty = '0x0f7f242e97dd0334c1c3d76b2f39846064b3766072fd4f2350c62d288477de21' 60 | let blockTransactionReceipts = await caver.rpc.klay.getBlockReceipts(baobabBlockHashEmpty) 61 | console.log(blockTransactionReceipts) 62 | 63 | const baobabBlockHash = '0x28fdc2fdce29513105fdaa605384a75ee15623ccb2271febc5b73554f17ab09d' 64 | blockTransactionReceipts = await caver.rpc.klay.getBlockReceipts(baobabBlockHash) 65 | console.log(blockTransactionReceipts) 66 | 67 | // // This is for testing Cypress Network (Main-net) 68 | // // If there are no transactions in the block being looked up, the returned data will be empty. 69 | // const cypressBlockHashEmpty = '0xacb410b0c43e5dcddaa27c55533699a6cbe95b150e38e67c04ba2b9e9d7a47dd' 70 | // let blockTransactionReceipts = await caver.rpc.klay.getBlockReceipts(cypressBlockHashEmpty) 71 | // console.log(blockTransactionReceipts) 72 | 73 | // const cypressBlockHash = '0xaaec69d70a85504db43a01599d92c22b74c8e03776b499258f4dd7b2fc2957d1' 74 | // blockTransactionReceipts = await caver.rpc.klay.getBlockReceipts(cypressBlockHash) 75 | // console.log(blockTransactionReceipts) 76 | } 77 | -------------------------------------------------------------------------------- /ipfs/using_ipfs_with_caver/index.js: -------------------------------------------------------------------------------- 1 | const path = require('path') 2 | const dotenv = require('dotenv') 3 | const Caver = require('caver-js') 4 | 5 | const ROOT_DIR = path.join(__dirname, '../..') // Path can be changed based on its actual location. 6 | 7 | // You can directly input values for the variables below, or you can enter values in the caver-js-examples/.env file. 8 | let nodeApiUrl = '' // e.g. 'https://node-api.klaytnapi.com/v1/klaytn' 9 | let accessKeyId = '' // e.g. 'KASK1LVNO498YT6KJQFUPY8S' 10 | let secretAccessKey = '' // e.g. 'aP/reVYHXqjw3EtQrMuJP4A3/hOb69TjnBT3ePKG' 11 | let chainId = '' // e.g. '1001' or '8217' 12 | let senderAddress = '' // e.g. '0xeb709d59954f4cdc6b6f3bfcd8d531887b7bd199' 13 | let senderPrivateKey = '' // e.g. '0x39a6375b608c2572fadb2ed9fd78c5c456ca3aa860c43192ad910c3269727fc1' 14 | let recipientAddress = '' // e.g. '0xeb709d59954f4cdc6b6f3bfcd8d531887b7bd199' 15 | 16 | /** 17 | * Example code about "Using IPFS with Caver." 18 | * Related article - Korean: https://medium.com/klaytn/caver%EB%A5%BC-%EC%9D%B4%EC%9A%A9%ED%95%9C-ipfs-%EC%82%AC%EC%9A%A9%EB%B2%95-4889a3b29c0b 19 | * Related article - English: https://medium.com/klaytn/using-ipfs-with-caver-964e1f721bfe 20 | */ 21 | async function main() { 22 | try { 23 | loadEnv() 24 | await run() 25 | } catch (err) { 26 | console.error(err) 27 | } 28 | } 29 | 30 | main() 31 | 32 | function loadEnv() { 33 | envs = dotenv.config({ path: `${ROOT_DIR}/.env` }) 34 | if (envs.error) { 35 | throw envs.error 36 | } 37 | 38 | nodeApiUrl = nodeApiUrl === '' ? envs.parsed.NODE_API_URL : nodeApiUrl 39 | accessKeyId = accessKeyId === '' ? envs.parsed.ACCESS_KEY_ID : accessKeyId 40 | secretAccessKey = secretAccessKey === '' ? envs.parsed.SECRET_ACCESS_KEY : secretAccessKey 41 | chainId = chainId === '' ? envs.parsed.CHAIN_ID : chainId 42 | senderAddress = senderAddress === '' ? envs.parsed.SENDER_ADDRESS : senderAddress 43 | senderPrivateKey = senderPrivateKey === '' ? envs.parsed.SENDER_PRIVATE_KEY : senderPrivateKey 44 | recipientAddress = recipientAddress === '' ? envs.parsed.RECIPIENT_ADDRESS : recipientAddress 45 | } 46 | 47 | async function run() { 48 | const option = { 49 | headers: [ 50 | { 51 | name: 'Authorization', 52 | value: `Basic ${Buffer.from(`${accessKeyId}:${secretAccessKey}`).toString('base64')}`, 53 | }, 54 | { name: 'x-chain-id', value: chainId }, 55 | ], 56 | } 57 | const caver = new Caver(new Caver.providers.HttpProvider(nodeApiUrl, option)) 58 | 59 | // Set connection with IPFS Node 60 | caver.ipfs.setIPFSNode('ipfs.infura.io', 5001, true) 61 | // `ipfs.txt` is located at `caver-js-examples/ipfs/using_ipfs_with_caver/resources`. 62 | const testFile = `${__dirname}/resources/ipfs.txt` 63 | 64 | // Add a file to IPFS with file path 65 | const cid = await caver.ipfs.add(testFile) 66 | console.log(`cid: ${cid}`) 67 | 68 | // // Add a file to IPFS with file contents 69 | // const contents = Buffer.from('test data') 70 | // const cid = await caver.ipfs.add(contents) 71 | 72 | // Download a file from IPFS 73 | const buffer = await caver.ipfs.get(cid) 74 | console.log(`Contents downloaded from IPFS: ${buffer.toString('utf8')}`) 75 | 76 | // Convert from CID to multihash(hex formatted) 77 | const multihash = await caver.ipfs.toHex(cid) 78 | console.log(`multihash: ${multihash}`) 79 | 80 | // Add keyring to in-memory wallet 81 | const senderKeyring = caver.wallet.keyring.create(senderAddress, senderPrivateKey) 82 | caver.wallet.add(senderKeyring) 83 | 84 | // Create ValueTransferMemo transaction 85 | const tx = caver.transaction.valueTransferMemo.create({ 86 | from: senderKeyring.address, 87 | to: recipientAddress, 88 | value: 1, 89 | input: multihash, 90 | gas: 30000, 91 | }) 92 | 93 | // Sign to the transaction 94 | await caver.wallet.sign(senderKeyring.address, tx) 95 | 96 | // Send a signed transaction to Klaytn 97 | const receipt = await caver.rpc.klay.sendRawTransaction(tx) 98 | console.log(receipt) 99 | } 100 | -------------------------------------------------------------------------------- /contract/execute_smart_contract/index.js: -------------------------------------------------------------------------------- 1 | const path = require('path') 2 | const dotenv = require('dotenv') 3 | const Caver = require('caver-js') 4 | 5 | const ROOT_DIR = path.join(__dirname, '../..') // Path can be changed based on its actual location. 6 | 7 | // You can directly input values for the variables below, or you can enter values in the caver-js-examples/.env file. 8 | let nodeApiUrl = '' // e.g. 'https://node-api.klaytnapi.com/v1/klaytn' 9 | let accessKeyId = '' // e.g. 'KASK1LVNO498YT6KJQFUPY8S' 10 | let secretAccessKey = '' // e.g. 'aP/reVYHXqjw3EtQrMuJP4A3/hOb69TjnBT3ePKG' 11 | let chainId = '' // e.g. '1001' or '8217' 12 | let deployerAddress = '' // e.g. '0xeb709d59954f4cdc6b6f3bfcd8d531887b7bd199' 13 | let deployerPrivateKey = '' // e.g. '0x39a6375b608c2572fadb2ed9fd78c5c456ca3aa860c43192ad910c3269727fc1' 14 | 15 | /** 16 | * Example code about "How to execute Smart Contract." 17 | * Related reference - Korean: https://ko.docs.klaytn.com/bapp/sdk/caver-js/getting-started#smart-contract 18 | * Related reference - English: https://docs.klaytn.com/bapp/sdk/caver-js/getting-started#smart-contract 19 | */ 20 | async function main() { 21 | try { 22 | loadEnv() 23 | await run() 24 | } catch (err) { 25 | console.error(err) 26 | } 27 | } 28 | 29 | main() 30 | 31 | function loadEnv() { 32 | envs = dotenv.config({ path: `${ROOT_DIR}/.env` }) 33 | if (envs.error) { 34 | throw envs.error 35 | } 36 | 37 | nodeApiUrl = nodeApiUrl === '' ? envs.parsed.NODE_API_URL : nodeApiUrl 38 | accessKeyId = accessKeyId === '' ? envs.parsed.ACCESS_KEY_ID : accessKeyId 39 | secretAccessKey = secretAccessKey === '' ? envs.parsed.SECRET_ACCESS_KEY : secretAccessKey 40 | chainId = chainId === '' ? envs.parsed.CHAIN_ID : chainId 41 | deployerAddress = deployerAddress === '' ? envs.parsed.DEPLOYER_ADDRESS : deployerAddress 42 | deployerPrivateKey = deployerPrivateKey === '' ? envs.parsed.DEPLOYER_PRIVATE_KEY : deployerPrivateKey 43 | } 44 | 45 | async function run() { 46 | const option = { 47 | headers: [ 48 | { 49 | name: 'Authorization', 50 | value: `Basic ${Buffer.from(`${accessKeyId}:${secretAccessKey}`).toString('base64')}`, 51 | }, 52 | { name: 'x-chain-id', value: chainId }, 53 | ], 54 | } 55 | const caver = new Caver(new Caver.providers.HttpProvider(nodeApiUrl, option)) 56 | 57 | // abi is extracted by compiling caver-js-examples/resources/KVstore.sol using solc(solidity compiler) 58 | const abi = [ 59 | { 60 | constant: true, 61 | inputs: [{ name: 'key', type: 'string' }], 62 | name: 'get', 63 | outputs: [{ name: '', type: 'string' }], 64 | payable: false, 65 | stateMutability: 'view', 66 | type: 'function', 67 | }, 68 | { 69 | constant: false, 70 | inputs: [ 71 | { name: 'key', type: 'string' }, 72 | { name: 'value', type: 'string' }, 73 | ], 74 | name: 'set', 75 | outputs: [], 76 | payable: false, 77 | stateMutability: 'nonpayable', 78 | type: 'function', 79 | }, 80 | { 81 | inputs: [ 82 | { name: 'key', type: 'string' }, 83 | { name: 'value', type: 'string' }, 84 | ], 85 | payable: false, 86 | stateMutability: 'nonpayable', 87 | type: 'constructor', 88 | }, 89 | ] 90 | // You can get contract address 91 | // by running caver-js-examples/contract/deploy/index.js :) 92 | const contractAddress = '0x{contractAddress}' 93 | const deployerKeyring = caver.wallet.keyring.create(deployerAddress, deployerPrivateKey) 94 | caver.wallet.add(deployerKeyring) 95 | 96 | contract = caver.contract.create(abi, contractAddress) 97 | const receipt = await contract.send( 98 | { 99 | from: deployerKeyring.address, 100 | gas: 1000000, 101 | }, 102 | 'set', 103 | 'k1', 104 | 'v1' 105 | ) 106 | console.log(receipt) 107 | 108 | const callResult = await contract.call('get', 'k1') 109 | console.log(`Result of calling get function with key: ${callResult}`) 110 | } 111 | -------------------------------------------------------------------------------- /README.ko.md: -------------------------------------------------------------------------------- 1 | # caver-js-examples 2 | **caver-js-examples**는 Klaytn SDK([caver-js](https://github.com/klaytn/caver-js))를 더 쉽고 빠르게 사용할 수 있도록 예제 코드를 제공하는 프로젝트입니다. 3 | 다양한 상황에 맞는 예제 코드를 확인하고 직접 실행해 볼 수 있습니다. 4 | 5 | ## 1. 선행 작업 6 | ### 1.1 소프트웨어 설치 7 | 실습을 원활히 진행하려면 [문서](https://ko.docs.klaytn.com/bapp/sdk/caver-js/getting-started#prerequisites)에 작성된 소프트웨어를 먼저 설치해야 합니다. 해당 문서에는 본 프로젝트를 구성할 때 필요한 소프트웨어를 기술하고 있습니다. 8 | 9 | ### 1.2 KAS 회원가입 10 | Klaytn SDK([caver-js](https://github.com/klaytn/caver-js))는 Klaytn 네트워크를 구성하는 노드를 연결해 사용할 수 있는데, caver-js-examples 프로젝트에서는 [KAS](https://klaytnapi.com)의 [Node API](https://refs.klaytnapi.com/en/node/latest)를 사용합니다. 따라서 사용자는 [엔드포인트 노드(EN)](https://docs.klaytn.com/node/endpoint-node)를 직접 운영하지 않아도 예제코드를 테스트 할 수 있습니다. 11 | 12 | KAS를 사용하려면 먼저 [KAS](https://klaytnapi.com)에 가입하고, 예제코드 실행에 필요한 `AccessKey ID`와 `Secret AccessKey`를 발급 받습니다. 13 | 발급 받은 `AccessKey ID`와 `Secret AccessKey`의 사용 방법은 [2. 사용법](https://github.com/klaytn/caver-js-examples/blob/master/README.ko.md#2-%EC%82%AC%EC%9A%A9%EB%B2%95)에서 확인할 수 있습니다. 14 | 15 | ### 1.3 계정 준비 16 | 예제 코드를 실행하려면 테스트넷 KLAY를 충분히 보유한 테스트 계정이 준비되어야 합니다. 17 | 예제 코드 역시 Klaytn에 트랜잭션을 전송하기 때문에 최소 1개의 테스트 계정이 필요합니다. 만약 계정 키를 업데이트해서 기존에 사용하던 테스트 계정을 더이상 사용할 수 없다면 새로운 계정을 생성할 수 있습니다. 아래 설명에 따라 테스트 계정을 생성하고 5 테스트넷 KLAY를 충전하세요. 예제 종류에 따라 여러 개의 테스트 계정이 필요할 수 있으며, 이 경우에는 아래 절차를 반복해 여러 개의 테스트 계정을 생성할 수 있습니다. 18 | 1. [Klaytn Wallet 테스트넷](https://baobab.wallet.klaytn.com/create)에서 테스트 계정을 생성합니다. 19 | * 생성된 계정의 주소와 개인 키는 테스트에 활용되기 때문에 반드시 기록해두고 잊지 않도록 합니다. 20 | * 생성 시 저장한 키스토어 파일을 별도 보관하세요. 일부 예제 시나리오에서 키스토어 파일을 활용합니다. 21 | 2. [Baobab Klaytn Wallet의 Faucet](https://baobab.wallet.klaytn.com/faucet)에서 5 테스트넷 KLAY를 충전합니다. 22 | 23 | ## 2. 사용법 24 | 1. 이 프로젝트를 클론합니다. 터미널에서 `$ git clone https://github.com/klaytn/caver-js-examples.git`을 실행하세요. 25 | 2. 예제를 실행하려면 [KAS Console](https://console.klaytnapi.com/ko/security/credential)에서 발급받은 Credential(AccessKey ID와 Secret AccessKey)과 [Klaytn Wallet 테스트넷](https://baobab.wallet.klaytn.com/create)에서 발급받은 Klaytn 계정을 설정해야 합니다. 실습에 사용하는 계정은 테스트 용도로만 사용할 것을 권장합니다. 26 | * 옵션 1(권장): **caver-js-examples/.env** 파일에 발급 받은 Credential과 Klaytn 계정을 정의합니다. 이 파일에 정의된 내용은 모든 시나리오에 공통 적용됩니다. 각 시나리오의 **index.js** 파일 `loadEnv` 함수에서 **.env** 파일에 정의한 변수들을 읽어오는 코드가 있으니 참고하시기 바랍니다. 27 | * 옵션 2: 원하는 시나리오에 해당하는 **index.js** 파일을 열고 상단에 let 키워드로 선언된 변수의 값을 채웁니다. 28 | 3. 터미널에서 `node /<시나리오>/index.js`로 예제 코드를 실행합니다. 29 | * 예시 1: `$ node account/update_account_with_account_key_public/index.js` 30 | * 예시 2: `$ node contract/fee_delegation/index.js` 31 | 32 | ### 2.1 Hello World 33 | 시나리오에 관계없이 caver를 바로 사용해보고 싶다면 `hello_world`를 실행해보세요. 아래 명령어 중 하나를 사용해 실행할 수 있습니다. 34 | * `$ cd hello_world && node ./index.js` 35 | * `$ node hello_world/index.js` 36 | 37 | **caver-js-examples/hello_world/index.js** 파일의 `run` 함수에 caver를 사용하는 코드를 자유롭게 작성하고 테스트해 보세요. 38 | 39 | ## 3. 프로젝트 구조 40 | caver-js-examples 프로젝트 구조를 설명합니다. 41 | ### 3.1 CA-Layer/시나리오 42 | 43 | 디렉토리 트리의 첫 번째 레벨에는 [Common Architecture를 구성하는 레이어](https://kips.klaytn.com/KIPs/kip-34#layer-diagram-of-the-common-architecture)가 위치합니다. 이하 `CA-Layers`라고 표기합니다. 44 | ``` 45 | . 46 | ├── abi 47 | ├── account 48 | ├── ... 49 | └── wallet 50 | ``` 51 | 52 | `CA-Layers` 하위 레벨에는 **예제 시나리오**가 위치하게 됩니다. 예를 들어 `account` 레이어 디렉토리 내부에 위치하는 예제 시나리오는 다음과 같습니다. 53 | ``` 54 | account 55 | ├── update_account_with_account_key_public 56 | ├── update_account_with_account_key_role_based 57 | └── update_account_with_account_key_weighted_multisig 58 | ``` 59 | * 각 시나리오는 단일 **index.js** 파일을 포함하며, 해당 시나리오에 특정 파일이 필요한 경우 `resources` 디렉토리를 구성합니다. 60 | * 이는 사용자가 예제를 바로 실행해 볼 수 있도록 구성하기 위함입니다. 61 | 62 | ### 3.2 Summary 63 | caver-js-example 프로젝트는 여러 개의 `CA-Layer/시나리오`로 이루어져 있으며, 프로젝트의 루트 디렉토리에서 `node CA-Layer/시나리오/index.js` 또는 해당하는 시나리오 디렉토리에서 `node ./index.js`로 예제 코드를 실행할 수 있도록 지원합니다. 64 | 65 | ## License 66 | **caver-js-examples** is released under the [MIT license](./LICENSE). 67 | 68 | ``` 69 | MIT License 70 | 71 | Copyright (c) 2021 caver-js-examples Authors 72 | 73 | Permission is hereby granted, free of charge, to any person obtaining a copy 74 | of this software and associated documentation files (the "Software"), to deal 75 | in the Software without restriction, including without limitation the rights 76 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 77 | copies of the Software, and to permit persons to whom the Software is 78 | furnished to do so, subject to the following conditions: 79 | 80 | The above copyright notice and this permission notice shall be included in all 81 | copies or substantial portions of the Software. 82 | 83 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 84 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 85 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 86 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 87 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 88 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 89 | SOFTWARE. 90 | ``` 91 | -------------------------------------------------------------------------------- /account/update_account_with_account_key_public/index.js: -------------------------------------------------------------------------------- 1 | const path = require('path') 2 | const dotenv = require('dotenv') 3 | const Caver = require('caver-js') 4 | 5 | const ROOT_DIR = path.join(__dirname, '../..') // Path can be changed based on its actual location. 6 | 7 | // You can directly input values for the variables below, or you can enter values in the caver-js-examples/.env file. 8 | let nodeApiUrl = '' // e.g. 'https://node-api.klaytnapi.com/v1/klaytn' 9 | let accessKeyId = '' // e.g. 'KASK1LVNO498YT6KJQFUPY8S' 10 | let secretAccessKey = '' // e.g. 'aP/reVYHXqjw3EtQrMuJP4A3/hOb69TjnBT3ePKG' 11 | let chainId = '' // e.g. '1001' or '8217' 12 | let senderAddress = '' // e.g. '0xeb709d59954f4cdc6b6f3bfcd8d531887b7bd199' 13 | let senderPrivateKey = '' // e.g. '0x39a6375b608c2572fadb2ed9fd78c5c456ca3aa860c43192ad910c3269727fc1' 14 | let recipientAddress = '' // e.g. '0xeb709d59954f4cdc6b6f3bfcd8d531887b7bd199' 15 | 16 | /** 17 | * Example code about "How to Update Klaytn Account Keys with Caver #1 — AccountKeyPublic" 18 | * Related article - Korean: https://medium.com/klaytn/caver-caver%EB%A1%9C-klaytn-%EA%B3%84%EC%A0%95%EC%9D%98-%ED%82%A4%EB%A5%BC-%EB%B0%94%EA%BE%B8%EB%8A%94-%EB%B0%A9%EB%B2%95-1-accountkeypublic-7f8a7197e2d4 19 | * Related article - English: https://medium.com/klaytn/caver-how-to-update-klaytn-account-keys-with-caver-1-accountkeypublic-30336b8f0b50 20 | */ 21 | async function main() { 22 | try { 23 | loadEnv() 24 | await run() 25 | } catch (err) { 26 | console.error(err) 27 | } 28 | } 29 | 30 | main() 31 | 32 | function loadEnv() { 33 | envs = dotenv.config({ path: `${ROOT_DIR}/.env` }) 34 | if (envs.error) { 35 | throw envs.error 36 | } 37 | 38 | nodeApiUrl = nodeApiUrl === '' ? envs.parsed.NODE_API_URL : nodeApiUrl 39 | accessKeyId = accessKeyId === '' ? envs.parsed.ACCESS_KEY_ID : accessKeyId 40 | secretAccessKey = secretAccessKey === '' ? envs.parsed.SECRET_ACCESS_KEY : secretAccessKey 41 | chainId = chainId === '' ? envs.parsed.CHAIN_ID : chainId 42 | senderAddress = senderAddress === '' ? envs.parsed.SENDER_ADDRESS : senderAddress 43 | senderPrivateKey = senderPrivateKey === '' ? envs.parsed.SENDER_PRIVATE_KEY : senderPrivateKey 44 | recipientAddress = recipientAddress === '' ? envs.parsed.RECIPIENT_ADDRESS : recipientAddress 45 | } 46 | 47 | async function run() { 48 | console.log(`=====> Update AccountKey to AccountKeyPublic`) 49 | const option = { 50 | headers: [ 51 | { 52 | name: 'Authorization', 53 | value: `Basic ${Buffer.from(`${accessKeyId}:${secretAccessKey}`).toString('base64')}`, 54 | }, 55 | { name: 'x-chain-id', value: chainId }, 56 | ], 57 | } 58 | const caver = new Caver(new Caver.providers.HttpProvider(nodeApiUrl, option)) 59 | 60 | // Add keyring to in-memory wallet 61 | const senderKeyring = caver.wallet.keyring.create(senderAddress, senderPrivateKey) 62 | caver.wallet.add(senderKeyring) 63 | 64 | // Create new private key 65 | const newKey = caver.wallet.keyring.generateSingleKey() 66 | console.log(`new private key: ${newKey}`) 67 | 68 | // Create new Keyring instance with new private key 69 | const newKeyring = caver.wallet.keyring.create(senderKeyring.address, newKey) 70 | // Create an Account instance that includes the address and the public key 71 | const account = newKeyring.toAccount() 72 | console.log(account) 73 | 74 | // Create account update transaction object 75 | const accountUpdate = caver.transaction.accountUpdate.create({ 76 | from: senderKeyring.address, 77 | account: account, 78 | gas: 50000, 79 | }) 80 | 81 | // Sign the transaction 82 | await caver.wallet.sign(senderKeyring.address, accountUpdate) 83 | // Send transaction 84 | const receipt = await caver.rpc.klay.sendRawTransaction(accountUpdate) 85 | console.log(`Account Update Transaction receipt => `) 86 | console.log(receipt) 87 | 88 | // Get accountKey from network 89 | const accountKey = await caver.rpc.klay.getAccountKey(senderKeyring.address) 90 | console.log(`Result of account key update to AccountKeyPublic`) 91 | console.log(`Account address: ${senderKeyring.address}`) 92 | console.log(`accountKey =>`) 93 | console.log(accountKey) 94 | 95 | // Update keyring with new private key in in-memory wallet 96 | caver.wallet.updateKeyring(newKeyring) 97 | // Send 1 Peb to recipient to test whether updated accountKey is well-working or not. 98 | const vt = caver.transaction.valueTransfer.create({ 99 | from: senderKeyring.address, 100 | to: recipientAddress, 101 | value: 1, 102 | gas: 25000, 103 | }) 104 | 105 | // Sign the transaction with updated keyring 106 | await caver.wallet.sign(senderKeyring.address, vt) 107 | // Send transaction 108 | const vtReceipt = await caver.rpc.klay.sendRawTransaction(vt) 109 | console.log(`Receipt of value transfer transaction after account update => `) 110 | console.log(vtReceipt) 111 | } 112 | -------------------------------------------------------------------------------- /utils/play_with_units_in_klaytn/index.js: -------------------------------------------------------------------------------- 1 | const path = require('path') 2 | const dotenv = require('dotenv') 3 | const Caver = require('caver-js') 4 | 5 | const ROOT_DIR = path.join(__dirname, '../..') // Path can be changed based on its actual location. 6 | 7 | // You can directly input values for the variables below, or you can enter values in the caver-js-examples/.env file. 8 | let nodeApiUrl = '' // e.g. 'https://node-api.klaytnapi.com/v1/klaytn' 9 | let accessKeyId = '' // e.g. 'KASK1LVNO498YT6KJQFUPY8S' 10 | let secretAccessKey = '' // e.g. 'aP/reVYHXqjw3EtQrMuJP4A3/hOb69TjnBT3ePKG' 11 | let chainId = '' // e.g. '1001' or '8217' 12 | let senderAddress = '' // e.g. '0xeb709d59954f4cdc6b6f3bfcd8d531887b7bd199' 13 | let senderPrivateKey = '' // e.g. '0x39a6375b608c2572fadb2ed9fd78c5c456ca3aa860c43192ad910c3269727fc1' 14 | let recipientAddress = '' // e.g. '0xeb709d59954f4cdc6b6f3bfcd8d531887b7bd199' 15 | 16 | /** 17 | * Example code about "How to use Klay Units." 18 | * Related reference - Korean: https://ko.docs.klaytn.com/klaytn/design/klaytn-native-coin-klay#units-of-klay 19 | * Related reference - English: https://docs.klaytn.com/klaytn/design/klaytn-native-coin-klay#units-of-klay 20 | */ 21 | async function main() { 22 | try { 23 | loadEnv() 24 | await run() 25 | } catch (err) { 26 | console.error(err) 27 | } 28 | } 29 | 30 | main() 31 | 32 | function loadEnv() { 33 | envs = dotenv.config({ path: `${ROOT_DIR}/.env` }) 34 | if (envs.error) { 35 | throw envs.error 36 | } 37 | 38 | nodeApiUrl = nodeApiUrl === '' ? envs.parsed.NODE_API_URL : nodeApiUrl 39 | accessKeyId = accessKeyId === '' ? envs.parsed.ACCESS_KEY_ID : accessKeyId 40 | secretAccessKey = secretAccessKey === '' ? envs.parsed.SECRET_ACCESS_KEY : secretAccessKey 41 | chainId = chainId === '' ? envs.parsed.CHAIN_ID : chainId 42 | senderAddress = senderAddress === '' ? envs.parsed.SENDER_ADDRESS : senderAddress 43 | senderPrivateKey = senderPrivateKey === '' ? envs.parsed.SENDER_PRIVATE_KEY : senderPrivateKey 44 | recipientAddress = recipientAddress === '' ? envs.parsed.RECIPIENT_ADDRESS : recipientAddress 45 | } 46 | 47 | async function run() { 48 | const option = { 49 | headers: [ 50 | { 51 | name: 'Authorization', 52 | value: `Basic ${Buffer.from(`${accessKeyId}:${secretAccessKey}`).toString('base64')}`, 53 | }, 54 | { name: 'x-chain-id', value: chainId }, 55 | ], 56 | } 57 | const caver = new Caver(new Caver.providers.HttpProvider(nodeApiUrl, option)) 58 | 59 | const senderKeyring = caver.wallet.keyring.create(senderAddress, senderPrivateKey) 60 | caver.wallet.add(senderKeyring) 61 | 62 | // Because a field "value" always interprets its value as a unit "peb", 63 | // you must take care what is the actual value when you sending some KLAY. 64 | const vt = caver.transaction.valueTransfer.create({ 65 | from: senderKeyring.address, 66 | to: recipientAddress, 67 | gas: 25000, 68 | value: 1, 69 | }) 70 | // Example-1: Sending 0.5 KLAY to recipient 71 | // option-1 (Recommended): Use klayUnit. 72 | vt.value = caver.utils.convertToPeb('0.5', caver.utils.klayUnit.KLAY.unit) 73 | console.log(`Example-1) The value what we set using option-1 is ${vt.value}`) 74 | 75 | // option-2 (Not recommended): Set actual peb value directly to ValueTransfer transaction object. 76 | // 1 KLAY is actually 10^18(=1000000000000000000) peb. So if you want send 0.5 KLAY, 77 | // you must set 500000000000000000(= 5 * (10^17) as a value of Transaction. 78 | vt.value = '500000000000000000' // 5 * (10^17) 79 | console.log(`Example-1) The value what we set using option-2 is ${vt.value}`) 80 | 81 | // Example-2: Sending 0.05 KLAY to recipient 82 | // option-1 (Recommended): Use klayUnit. 83 | vt.value = caver.utils.convertToPeb('0.05', caver.utils.klayUnit.KLAY.unit) 84 | console.log(`Example-2) The value what we set using option-1 is ${vt.value}`) 85 | 86 | // option-2 (Not recommended): Set actual peb value directly to ValueTransfer transaction object. 87 | // 1 KLAY is actually 10^18(=1000000000000000000) peb. So if you want send 0.05 KLAY, 88 | // you must set 50000000000000000(= 5 * (10^16) as a value of Transaction. 89 | vt.value = '50000000000000000' // 5 * (10^16) 90 | console.log(`Example-2) The value what we set using option-2 is ${vt.value}`) 91 | 92 | // Example-3: Sending 0.005 KLAY to recipient 93 | // option-1 (Recommended): Use klayUnit. 94 | vt.value = caver.utils.convertToPeb('5', caver.utils.klayUnit.mKLAY.unit) 95 | console.log(`Example-3) The value what we set using option-1 is ${vt.value}`) 96 | 97 | // option-2 (Not recommended): Set actual peb value directly to ValueTransfer transaction object. 98 | // 1 KLAY is actually 10^18(=1000000000000000000) peb. So if you want send 0.005 KLAY, 99 | // you must set 5000000000000000(= 5 * (10^15) as a value of Transaction. 100 | vt.value = '5000000000000000' // 5 * (10^15) 101 | console.log(`Example-3) The value what we set using option-2 is ${vt.value}`) 102 | } 103 | -------------------------------------------------------------------------------- /account/update_account_with_account_key_weighted_multisig/index.js: -------------------------------------------------------------------------------- 1 | const path = require('path') 2 | const dotenv = require('dotenv') 3 | const Caver = require('caver-js') 4 | 5 | const ROOT_DIR = path.join(__dirname, '../..') // Path can be changed based on its actual location. 6 | 7 | // You can directly input values for the variables below, or you can enter values in the caver-js-examples/.env file. 8 | let nodeApiUrl = '' // e.g. 'https://node-api.klaytnapi.com/v1/klaytn' 9 | let accessKeyId = '' // e.g. 'KASK1LVNO498YT6KJQFUPY8S' 10 | let secretAccessKey = '' // e.g. 'aP/reVYHXqjw3EtQrMuJP4A3/hOb69TjnBT3ePKG' 11 | let chainId = '' // e.g. '1001' or '8217' 12 | let senderAddress = '' // e.g. '0xeb709d59954f4cdc6b6f3bfcd8d531887b7bd199' 13 | let senderPrivateKey = '' // e.g. '0x39a6375b608c2572fadb2ed9fd78c5c456ca3aa860c43192ad910c3269727fc1' 14 | let recipientAddress = '' // e.g. '0xeb709d59954f4cdc6b6f3bfcd8d531887b7bd199' 15 | 16 | /** 17 | * Example code about "How to Update Klaytn Account Keys with Caver #2 — AccountKeyWeightedMultiSig" 18 | * Related article - Korean: https://medium.com/klaytn/caver-caver%EB%A1%9C-klaytn-%EA%B3%84%EC%A0%95%EC%9D%98-%ED%82%A4%EB%A5%BC-%EB%B0%94%EA%BE%B8%EB%8A%94-%EB%B0%A9%EB%B2%95-2-accountkeyweightedmultisig-c317a785299 19 | * Related article - English: https://medium.com/klaytn/caver-how-to-update-klaytn-account-keys-with-caver-2-accountkeyweightedmultisig-ed897b4e5b5b 20 | */ 21 | async function main() { 22 | try { 23 | loadEnv() 24 | await run() 25 | } catch (err) { 26 | console.error(err) 27 | } 28 | } 29 | 30 | main() 31 | 32 | function loadEnv() { 33 | envs = dotenv.config({ path: `${ROOT_DIR}/.env` }) 34 | if (envs.error) { 35 | throw envs.error 36 | } 37 | 38 | nodeApiUrl = nodeApiUrl === '' ? envs.parsed.NODE_API_URL : nodeApiUrl 39 | accessKeyId = accessKeyId === '' ? envs.parsed.ACCESS_KEY_ID : accessKeyId 40 | secretAccessKey = secretAccessKey === '' ? envs.parsed.SECRET_ACCESS_KEY : secretAccessKey 41 | chainId = chainId === '' ? envs.parsed.CHAIN_ID : chainId 42 | senderAddress = senderAddress === '' ? envs.parsed.SENDER_ADDRESS : senderAddress 43 | senderPrivateKey = senderPrivateKey === '' ? envs.parsed.SENDER_PRIVATE_KEY : senderPrivateKey 44 | recipientAddress = recipientAddress === '' ? envs.parsed.RECIPIENT_ADDRESS : recipientAddress 45 | } 46 | 47 | async function run() { 48 | console.log(`=====> Update AccountKey to AccountKeyWeightedMultiSig`) 49 | const option = { 50 | headers: [ 51 | { 52 | name: 'Authorization', 53 | value: `Basic ${Buffer.from(`${accessKeyId}:${secretAccessKey}`).toString('base64')}`, 54 | }, 55 | { name: 'x-chain-id', value: chainId }, 56 | ], 57 | } 58 | const caver = new Caver(new Caver.providers.HttpProvider(nodeApiUrl, option)) 59 | 60 | // Add keyring to in-memory wallet 61 | const senderKeyring = caver.wallet.keyring.create(senderAddress, senderPrivateKey) 62 | caver.wallet.add(senderKeyring) 63 | 64 | // Create new private keys 65 | const newKeys = caver.wallet.keyring.generateMultipleKeys(3) 66 | console.log(`new private keys: ${JSON.stringify(newKeys)}`) 67 | 68 | // Create new Keyring instance with new private keys 69 | const newKeyring = caver.wallet.keyring.create(senderKeyring.address, newKeys) 70 | // Create an Account instance that includes the address and the weighted multisig key 71 | const account = newKeyring.toAccount({ threshold: 3, weights: [2, 1, 1] }) 72 | console.log(account) 73 | 74 | // Create account update transaction object 75 | const accountUpdate = caver.transaction.accountUpdate.create({ 76 | from: senderKeyring.address, 77 | account: account, 78 | gas: 100000, 79 | }) 80 | 81 | // Sign the transaction 82 | await caver.wallet.sign(senderKeyring.address, accountUpdate) 83 | // Send transaction 84 | const receipt = await caver.rpc.klay.sendRawTransaction(accountUpdate) 85 | console.log(`Account Update Transaction receipt => `) 86 | console.log(receipt) 87 | 88 | // Get accountKey from network 89 | const accountKey = await caver.rpc.klay.getAccountKey(senderKeyring.address) 90 | console.log(`Result of account key update to AccountKeyWeightedMultiSig`) 91 | console.log(`Account address: ${senderKeyring.address}`) 92 | console.log(`accountKey =>`) 93 | console.log(accountKey) 94 | 95 | // Update keyring with new private key in in-memory wallet 96 | caver.wallet.updateKeyring(newKeyring) 97 | // Send 1 Peb to recipient to test whether updated accountKey is well-working or not. 98 | const vt = caver.transaction.valueTransfer.create({ 99 | from: senderKeyring.address, 100 | to: recipientAddress, 101 | value: 1, 102 | gas: 100000, 103 | }) 104 | 105 | // Sign the transaction with updated keyring 106 | // This sign function will sign the transaction with all private keys in the keyring 107 | await caver.wallet.sign(senderKeyring.address, vt) 108 | // Send transaction 109 | const vtReceipt = await caver.rpc.klay.sendRawTransaction(vt) 110 | console.log(`Receipt of value transfer transaction after account update => `) 111 | console.log(vtReceipt) 112 | } 113 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing Guidelines 2 | 3 | Thank you for your interest in contributing to caver-js-examples. As an open source project, caver-js-examples 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 caver-js-examples, please [submit an issue](https://github.com/klaytn/caver-js-examples/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 caver-js-examples. 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/caver-js-examples/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/caver-js-examples/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 Klaytn 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 | - issue/bug: Issues with the code-level bugs. 49 | - issue/documentation: Issues with the documentation. 50 | - issue/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 | - open/need more information : The issue's creator needs to provide additional information to review. 56 | - open/reviewing: The issue is under review. 57 | - open/re-label needed: The label needs to be changed to confirmed as being a `bug` or future `enhancement`. 58 | - open/approved: The issue is confirmed as being a `bug` to be fixed or `enhancement` to be developed. 59 | - open/contribution welcome: The fix or enhancement is approved and you are invited to contribute to it. 60 | 61 | Status of closed issues: 62 | 63 | - closed/fixed: A fix for the issue was provided. 64 | - closed/duplicate: The issue is also reported in a different issue and is being managed there. 65 | - closed/invalid: The issue cannot be reproduced. 66 | - closed/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 | For the coding style of JavaScript, please refer to the following websites: 73 | - https://www.w3schools.com/js/js_conventions.asp 74 | - https://google.github.io/styleguide/jsguide.html 75 | 76 | caver-js-examples uses eslint with prettier. The linting rules inherit from airbnb. 77 | 78 | Before you submit a pull request, please run `npm run lint` and correct any errors. 79 | Otherwise, the test on CircleCI will fail, and this prevents merging. 80 | 81 | Formatting errors can be easily fixed by running `npm run lintFix`. 82 | 83 | ## Contributor License Agreement (CLA) 84 | 85 | Keep in mind when you submit your pull request, you'll need to sign the CLA via [CLA-Assistant](https://cla-assistant.io/klaytn/caver-js-examples) for legal purposes. You will have to sign the CLA just one time, either as an individual or corporation. 86 | 87 | You will be prompted to sign the agreement by CLA Assistant (bot) when you open a Pull Request for the first time. 88 | -------------------------------------------------------------------------------- /account/update_account_with_account_key_role_based/index.js: -------------------------------------------------------------------------------- 1 | const path = require('path') 2 | const dotenv = require('dotenv') 3 | const Caver = require('caver-js') 4 | 5 | const ROOT_DIR = path.join(__dirname, '../..') // Path can be changed based on its actual location. 6 | 7 | // You can directly input values for the variables below, or you can enter values in the caver-js-examples/.env file. 8 | let nodeApiUrl = '' // e.g. 'https://node-api.klaytnapi.com/v1/klaytn' 9 | let accessKeyId = '' // e.g. 'KASK1LVNO498YT6KJQFUPY8S' 10 | let secretAccessKey = '' // e.g. 'aP/reVYHXqjw3EtQrMuJP4A3/hOb69TjnBT3ePKG' 11 | let chainId = '' // e.g. '1001' or '8217' 12 | let senderAddress = '' // e.g. '0xeb709d59954f4cdc6b6f3bfcd8d531887b7bd199' 13 | let senderPrivateKey = '' // e.g. '0x39a6375b608c2572fadb2ed9fd78c5c456ca3aa860c43192ad910c3269727fc1' 14 | let recipientAddress = '' // e.g. '0xeb709d59954f4cdc6b6f3bfcd8d531887b7bd199' 15 | 16 | /** 17 | * Example code about "How to Update Klaytn Account Keys with Caver #3 — AccountKeyRoleBased" 18 | * Related article - Korean: https://medium.com/klaytn/caver-caver%EB%A1%9C-klaytn-%EA%B3%84%EC%A0%95%EC%9D%98-%ED%82%A4%EB%A5%BC-%EB%B0%94%EA%BE%B8%EB%8A%94-%EB%B0%A9%EB%B2%95-3-accountkeyrolebased-88c20b405f18 19 | * Related article - English: https://medium.com/klaytn/caver-how-to-update-klaytn-account-keys-with-caver-3-accountkeyrolebased-eb06433ff8da 20 | */ 21 | async function main() { 22 | try { 23 | loadEnv() 24 | await run() 25 | } catch (err) { 26 | console.error(err) 27 | } 28 | } 29 | 30 | main() 31 | 32 | function loadEnv() { 33 | envs = dotenv.config({ path: `${ROOT_DIR}/.env` }) 34 | if (envs.error) { 35 | throw envs.error 36 | } 37 | 38 | nodeApiUrl = nodeApiUrl === '' ? envs.parsed.NODE_API_URL : nodeApiUrl 39 | accessKeyId = accessKeyId === '' ? envs.parsed.ACCESS_KEY_ID : accessKeyId 40 | secretAccessKey = secretAccessKey === '' ? envs.parsed.SECRET_ACCESS_KEY : secretAccessKey 41 | chainId = chainId === '' ? envs.parsed.CHAIN_ID : chainId 42 | senderAddress = senderAddress === '' ? envs.parsed.SENDER_ADDRESS : senderAddress 43 | senderPrivateKey = senderPrivateKey === '' ? envs.parsed.SENDER_PRIVATE_KEY : senderPrivateKey 44 | recipientAddress = recipientAddress === '' ? envs.parsed.RECIPIENT_ADDRESS : recipientAddress 45 | } 46 | 47 | async function run() { 48 | console.log(`=====> Update AccountKey to AccountKeyRoleBased`) 49 | const option = { 50 | headers: [ 51 | { 52 | name: 'Authorization', 53 | value: `Basic ${Buffer.from(`${accessKeyId}:${secretAccessKey}`).toString('base64')}`, 54 | }, 55 | { name: 'x-chain-id', value: chainId }, 56 | ], 57 | } 58 | const caver = new Caver(new Caver.providers.HttpProvider(nodeApiUrl, option)) 59 | 60 | // Add keyring to in-memory wallet 61 | const senderKeyring = caver.wallet.keyring.create(senderAddress, senderPrivateKey) 62 | caver.wallet.add(senderKeyring) 63 | 64 | // Create new private keys 65 | const newRoleBasedKeys = caver.wallet.keyring.generateRoleBasedKeys([2, 1, 3]) 66 | console.log(`new private keys by role: ${JSON.stringify(newRoleBasedKeys)}`) 67 | 68 | // Create new Keyring instance with new private keys by role 69 | const newKeyring = caver.wallet.keyring.create(senderKeyring.address, newRoleBasedKeys) 70 | // Create an Account instance that includes the address and the role based key 71 | const account = newKeyring.toAccount([{ threshold: 2, weights: [1, 1] }, {}, { threshold: 3, weights: [2, 1, 1] }]) 72 | console.log(account) 73 | 74 | // Create account update transaction object 75 | const accountUpdate = caver.transaction.accountUpdate.create({ 76 | from: senderKeyring.address, 77 | account: account, 78 | gas: 150000, 79 | }) 80 | 81 | // Sign the transaction 82 | await caver.wallet.sign(senderKeyring.address, accountUpdate) 83 | // Send transaction 84 | const receipt = await caver.rpc.klay.sendRawTransaction(accountUpdate) 85 | console.log(`Account Update Transaction receipt => `) 86 | console.log(receipt) 87 | 88 | // Get accountKey from network 89 | const accountKey = await caver.rpc.klay.getAccountKey(senderKeyring.address) 90 | console.log(`Result of account key update to AccountKeyRoleBased`) 91 | console.log(`Account address: ${senderKeyring.address}`) 92 | console.log(`accountKey =>`) 93 | console.log(accountKey) 94 | 95 | // Update keyring with new private key in in-memory wallet 96 | caver.wallet.updateKeyring(newKeyring) 97 | // Send 1 Peb to recipient to test whether updated accountKey is well-working or not. 98 | const vt = caver.transaction.valueTransfer.create({ 99 | from: senderKeyring.address, 100 | to: recipientAddress, 101 | value: 1, 102 | gas: 150000, 103 | }) 104 | 105 | // Sign the transaction with updated keyring 106 | // This sign function will sign the transaction with all private keys in RoleTrasnsactionKey in the keyring 107 | await caver.wallet.sign(senderKeyring.address, vt) 108 | // Send transaction 109 | const vtReceipt = await caver.rpc.klay.sendRawTransaction(vt) 110 | console.log(`Receipt of value transfer transaction after account update => `) 111 | console.log(vtReceipt) 112 | } 113 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | *Read this in Korean:* [Korean](https://github.com/klaytn/caver-js-examples/blob/master/README.ko.md) 2 | 3 | # caver-js-examples 4 | **caver-js-examples** provide code samples to help you use the Klaytn SDK([caver-js](https://github.com/klaytn/caver-js)) easier and faster. Here you can find and test code samples conceived for different scenarios. 5 | 6 | ## 1. Prerequisites 7 | ### 1.1 Installing Software 8 | In order to follow this tutorial, you have to first install the software as listed on [Docs](https://docs.klaytn.com/bapp/sdk/caver-js/getting-started#prerequisites). The link explains which software you need for creating this project. 9 | 10 | ### 1.2 Sign Up on KAS 11 | You can use the Klaytn SDK([caver-js](https://github.com/klaytn/caver-js)) by connecting to one of the nodes that comprise the Klaytn network. But for the caver-js-examples project, we are using the [Node API](https://refs.klaytnapi.com/en/node/latest) of [KAS](https://klaytnapi.com), which means that you don't have to run an [Endpoint Node (EN)](https://docs.klaytn.com/node/endpoint-node) yourself to test the code samples. 12 | 13 | To use KAS, first sign up on [KAS](https://klaytnapi.com), and obtain the `AccessKey ID` and `Secret AccessKey`. 14 | You can find detailed instructions on how to use the `AccessKey ID` and `Secret AccessKey` in [2. How to Use](https://github.com/klaytn/caver-js-examples#2-how-to-use). 15 | 16 | ### 1.3 Creating Account 17 | In order to execute the code samples, you need a test account with a sufficient balance of testnet KLAY. 18 | Because the code samples also involves sending a transaction to Klaytn, you need at least one test account. If you have updated your account key, and your old test account is rendered unusable, you can create a new account. Create a test account following the instructions below and obtain your 5 testnet KLAY. Depending on the scenarios, you may need multiple test accounts. In that case, just repeat the process to create multiple test accounts. 19 | 1. Create a test account at [Klaytn Wallet Testnet](https://baobab.wallet.klaytn.com/create). 20 | * Have the address and private key of the new account written down, because you will need them for testing the code samples. 21 | * Make sure to also save the keystore file, because some scenarios require it. 22 | 2. Obtain 5 testnet KLAY on [Baobab Klaytn Wallet Faucet](https://baobab.wallet.klaytn.com/faucet). 23 | 24 | ## 2. How to Use 25 | 1. Clone this project and then execute `$ git clone https://github.com/klaytn/caver-js-examples.git` in Terminal. 26 | 2. To run the samples, you need to set the Credential (AccessKey ID and Secret AccessKey) which can be obtained on [KAS Console](https://console.klaytnapi.com/ko/security/credential) as well as a Klaytn account obtained on [Klaytn Wallet Testnet](https://baobab.wallet.klaytn.com/create). We recommend using the test account just for testing. 27 | * Option 1 (recommended): Define the Credential information and your Klaytn account in the **caver-js-examples/.env** file. The variables defined in this file apply for all scenarios. You can find the code for retrieving the variables defined in the **.env** file in the `loadEnv` function within **index.js** of each scenario. 28 | * Option 2: Open the **index.js** file for the scenario and fill in the variables declared with the keyword `let`. 29 | 3. In Terminal, execute the code sample using `node //index.js`. 30 | * Example 1: `$ node account/update_account_with_account_key_public/index.js` 31 | * Example 2: `$ node contract/fee_delegation/index.js` 32 | 33 | ### 2.1 Hello World 34 | If you want to jump right into using caver regardless of the scenarios, try printing `hello_world` using one of the commands below: 35 | * `$ cd hello_world && node ./index.js` 36 | * `$ node hello_world/index.js` 37 | 38 | Explore and test code using caver with the `run` function in the **caver-js-examples/hello_world/index.js** file. 39 | 40 | ## 3. Project Sturcture 41 | Below is an explanation of the caver-js-examples project structure. 42 | ### 3.1 CA-Layer/Scenario 43 | 44 | On the first level of the directory tree, you will find [Layers that Comprise the Common Architecture](https://kips.klaytn.com/KIPs/kip-34#layer-diagram-of-the-common-architecture). This will be refered to as `CA-Layers` from now on. 45 | ``` 46 | . 47 | ├── abi 48 | ├── account 49 | ├── ... 50 | └── wallet 51 | ``` 52 | 53 | Under the `CA-Layers` level, you will find **Sample Scenarios**. For example, the sample scenarios within the directory of the `account` layer look like this: 54 | ``` 55 | account 56 | ├── update_account_with_account_key_public 57 | ├── update_account_with_account_key_role_based 58 | └── update_account_with_account_key_weighted_multisig 59 | ``` 60 | * Each scenario includes a **index.js** file, and if the scenario requires a specific file, it employs a `resources` directory. 61 | * This allows the users to execute the samples right away. 62 | 63 | ### 3.2 Summary 64 | The caver-js-example project consists of multiple `CA-Layer/Scenario`, and lets you run the code samples with `node CA-Layer/Scenario/index.js` in the project root directory or `node ./index.js` in the scenario's directory. 65 | 66 | ## License 67 | **caver-js-examples** is released under the [MIT license](./LICENSE). 68 | 69 | ``` 70 | MIT License 71 | 72 | Copyright (c) 2021 caver-js-examples Authors 73 | 74 | Permission is hereby granted, free of charge, to any person obtaining a copy 75 | of this software and associated documentation files (the "Software"), to deal 76 | in the Software without restriction, including without limitation the rights 77 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 78 | copies of the Software, and to permit persons to whom the Software is 79 | furnished to do so, subject to the following conditions: 80 | 81 | The above copyright notice and this permission notice shall be included in all 82 | copies or substantial portions of the Software. 83 | 84 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 85 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 86 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 87 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 88 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 89 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 90 | SOFTWARE. 91 | ``` 92 | -------------------------------------------------------------------------------- /contract/deploy_smart_contract/index.js: -------------------------------------------------------------------------------- 1 | const path = require('path') 2 | const dotenv = require('dotenv') 3 | const Caver = require('caver-js') 4 | 5 | const ROOT_DIR = path.join(__dirname, '../..') // Path can be changed based on its actual location. 6 | 7 | // You can directly input values for the variables below, or you can enter values in the caver-js-examples/.env file. 8 | let nodeApiUrl = '' // e.g. 'https://node-api.klaytnapi.com/v1/klaytn' 9 | let accessKeyId = '' // e.g. 'KASK1LVNO498YT6KJQFUPY8S' 10 | let secretAccessKey = '' // e.g. 'aP/reVYHXqjw3EtQrMuJP4A3/hOb69TjnBT3ePKG' 11 | let chainId = '' // e.g. '1001' or '8217' 12 | let deployerAddress = '' // e.g. '0xeb709d59954f4cdc6b6f3bfcd8d531887b7bd199' 13 | let deployerPrivateKey = '' // e.g. '0x39a6375b608c2572fadb2ed9fd78c5c456ca3aa860c43192ad910c3269727fc1' 14 | 15 | /** 16 | * Example code about "How to deploy Smart Contract." 17 | * Related reference - Korean: https://ko.docs.klaytn.com/bapp/sdk/caver-js/getting-started#smart-contract 18 | * Related reference - English: https://docs.klaytn.com/bapp/sdk/caver-js/getting-started#smart-contract 19 | */ 20 | async function main() { 21 | try { 22 | loadEnv() 23 | await run() 24 | } catch (err) { 25 | console.error(err) 26 | } 27 | } 28 | 29 | main() 30 | 31 | function loadEnv() { 32 | envs = dotenv.config({ path: `${ROOT_DIR}/.env` }) 33 | if (envs.error) { 34 | throw envs.error 35 | } 36 | 37 | nodeApiUrl = nodeApiUrl === '' ? envs.parsed.NODE_API_URL : nodeApiUrl 38 | accessKeyId = accessKeyId === '' ? envs.parsed.ACCESS_KEY_ID : accessKeyId 39 | secretAccessKey = secretAccessKey === '' ? envs.parsed.SECRET_ACCESS_KEY : secretAccessKey 40 | chainId = chainId === '' ? envs.parsed.CHAIN_ID : chainId 41 | deployerAddress = deployerAddress === '' ? envs.parsed.DEPLOYER_ADDRESS : deployerAddress 42 | deployerPrivateKey = deployerPrivateKey === '' ? envs.parsed.DEPLOYER_PRIVATE_KEY : deployerPrivateKey 43 | } 44 | 45 | async function run() { 46 | const option = { 47 | headers: [ 48 | { 49 | name: 'Authorization', 50 | value: `Basic ${Buffer.from(`${accessKeyId}:${secretAccessKey}`).toString('base64')}`, 51 | }, 52 | { name: 'x-chain-id', value: chainId }, 53 | ], 54 | } 55 | // Add keyring to in-memory wallet 56 | const caver = new Caver(new Caver.providers.HttpProvider(nodeApiUrl, option)) 57 | 58 | // byteCode and abi are extracted by compiling caver-js-examples/resources/KVstore.sol using solc(solidity compiler) 59 | const byteCode = 60 | '0x608060405234801561001057600080fd5b5060405161072d38038061072d8339810180604052604081101561003357600080fd5b81019080805164010000000081111561004b57600080fd5b8281019050602081018481111561006157600080fd5b815185600182028301116401000000008211171561007e57600080fd5b5050929190602001805164010000000081111561009a57600080fd5b828101905060208101848111156100b057600080fd5b81518560018202830111640100000000821117156100cd57600080fd5b5050929190505050806000836040518082805190602001908083835b6020831061010c57805182526020820191506020810190506020830392506100e9565b6001836020036101000a0380198251168184511680821785525050505050509050019150509081526020016040518091039020908051906020019061015292919061015a565b5050506101ff565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f1061019b57805160ff19168380011785556101c9565b828001600101855582156101c9579182015b828111156101c85782518255916020019190600101906101ad565b5b5090506101d691906101da565b5090565b6101fc91905b808211156101f85760008160009055506001016101e0565b5090565b90565b61051f8061020e6000396000f3fe608060405234801561001057600080fd5b50600436106100365760003560e01c8063693ec85e1461003b578063e942b5161461016f575b600080fd5b6100f46004803603602081101561005157600080fd5b810190808035906020019064010000000081111561006e57600080fd5b82018360208201111561008057600080fd5b803590602001918460018302840111640100000000831117156100a257600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f8201169050808301925050505050505091929192905050506102c1565b6040518080602001828103825283818151815260200191508051906020019080838360005b83811015610134578082015181840152602081019050610119565b50505050905090810190601f1680156101615780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b6102bf6004803603604081101561018557600080fd5b81019080803590602001906401000000008111156101a257600080fd5b8201836020820111156101b457600080fd5b803590602001918460018302840111640100000000831117156101d657600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f8201169050808301925050505050505091929192908035906020019064010000000081111561023957600080fd5b82018360208201111561024b57600080fd5b8035906020019184600183028401116401000000008311171561026d57600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f8201169050808301925050505050505091929192905050506103cc565b005b60606000826040518082805190602001908083835b602083106102f957805182526020820191506020810190506020830392506102d6565b6001836020036101000a03801982511681845116808217855250505050505090500191505090815260200160405180910390208054600181600116156101000203166002900480601f0160208091040260200160405190810160405280929190818152602001828054600181600116156101000203166002900480156103c05780601f10610395576101008083540402835291602001916103c0565b820191906000526020600020905b8154815290600101906020018083116103a357829003601f168201915b50505050509050919050565b806000836040518082805190602001908083835b6020831061040357805182526020820191506020810190506020830392506103e0565b6001836020036101000a0380198251168184511680821785525050505050509050019150509081526020016040518091039020908051906020019061044992919061044e565b505050565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f1061048f57805160ff19168380011785556104bd565b828001600101855582156104bd579182015b828111156104bc5782518255916020019190600101906104a1565b5b5090506104ca91906104ce565b5090565b6104f091905b808211156104ec5760008160009055506001016104d4565b5090565b9056fea165627a7a72305820adabefbb9574a90843d986f100c723c37f37e79f289b16aa527705b5341499aa0029' 61 | const abi = [ 62 | { 63 | constant: true, 64 | inputs: [{ name: 'key', type: 'string' }], 65 | name: 'get', 66 | outputs: [{ name: '', type: 'string' }], 67 | payable: false, 68 | stateMutability: 'view', 69 | type: 'function', 70 | }, 71 | { 72 | constant: false, 73 | inputs: [ 74 | { name: 'key', type: 'string' }, 75 | { name: 'value', type: 'string' }, 76 | ], 77 | name: 'set', 78 | outputs: [], 79 | payable: false, 80 | stateMutability: 'nonpayable', 81 | type: 'function', 82 | }, 83 | { 84 | inputs: [ 85 | { name: 'key', type: 'string' }, 86 | { name: 'value', type: 'string' }, 87 | ], 88 | payable: false, 89 | stateMutability: 'nonpayable', 90 | type: 'constructor', 91 | }, 92 | ] 93 | const deployerKeyring = caver.wallet.keyring.create(deployerAddress, deployerPrivateKey) 94 | caver.wallet.add(deployerKeyring) 95 | 96 | let contract = caver.contract.create(abi) 97 | contract = await contract.deploy( 98 | { 99 | from: deployerKeyring.address, 100 | gas: 4000000, 101 | }, 102 | byteCode, 103 | 'magicKey', 104 | 'magicValue' 105 | ) 106 | console.log(`The address of deployed smart contract: ${contract.options.address}`) 107 | 108 | const callResult = await contract.call('get', 'magicKey') 109 | console.log(`Result of calling get function with key: ${callResult}`) 110 | } 111 | -------------------------------------------------------------------------------- /contract/fee_delegation/index.js: -------------------------------------------------------------------------------- 1 | const path = require('path') 2 | const dotenv = require('dotenv') 3 | const Caver = require('caver-js') 4 | 5 | const ROOT_DIR = path.join(__dirname, '../..') // Path can be changed based on its actual location. 6 | 7 | // You can directly input values for the variables below, or you can enter values in the caver-js-examples/.env file. 8 | let nodeApiUrl = '' // e.g. 'https://node-api.klaytnapi.com/v1/klaytn' 9 | let accessKeyId = '' // e.g. 'KASK1LVNO498YT6KJQFUPY8S' 10 | let secretAccessKey = '' // e.g. 'aP/reVYHXqjw3EtQrMuJP4A3/hOb69TjnBT3ePKG' 11 | let chainId = '' // e.g. '1001' or '8217' 12 | let deployerAddress = '' // e.g. '0xeb709d59954f4cdc6b6f3bfcd8d531887b7bd199' 13 | let deployerPrivateKey = '' // e.g. '0x39a6375b608c2572fadb2ed9fd78c5c456ca3aa860c43192ad910c3269727fc1' 14 | let feePayerAddress = '' // e.g. '0xeb709d59954f4cdc6b6f3bfcd8d531887b7bd199' 15 | let feePayerPrivateKey = '' // e.g. '0x39a6375b608c2572fadb2ed9fd78c5c456ca3aa860c43192ad910c3269727fc1' 16 | 17 | /** 18 | * Example code about "How to use Fee Delegation with Contract." 19 | * Related article - Korean: https://medium.com/klaytn/caver-contract%EB%A5%BC-%EC%82%AC%EC%9A%A9%ED%95%98%EC%97%AC-%EC%88%98%EC%88%98%EB%A3%8C%EB%A5%BC-%EB%8C%80%EB%82%A9%ED%95%B4%EB%B3%B4%EC%9E%90-4c046900c4ed 20 | * Related article - English: https://medium.com/klaytn/caver-how-to-use-fee-delegation-with-contract-c599388c7cc0 21 | */ 22 | async function main() { 23 | try { 24 | loadEnv() 25 | await run() 26 | } catch (err) { 27 | console.error(err) 28 | } 29 | } 30 | 31 | main() 32 | 33 | function loadEnv() { 34 | envs = dotenv.config({ path: `${ROOT_DIR}/.env` }) 35 | if (envs.error) { 36 | throw envs.error 37 | } 38 | 39 | nodeApiUrl = nodeApiUrl === '' ? envs.parsed.NODE_API_URL : nodeApiUrl 40 | accessKeyId = accessKeyId === '' ? envs.parsed.ACCESS_KEY_ID : accessKeyId 41 | secretAccessKey = secretAccessKey === '' ? envs.parsed.SECRET_ACCESS_KEY : secretAccessKey 42 | chainId = chainId === '' ? envs.parsed.CHAIN_ID : chainId 43 | deployerAddress = deployerAddress === '' ? envs.parsed.DEPLOYER_ADDRESS : deployerAddress 44 | deployerPrivateKey = deployerPrivateKey === '' ? envs.parsed.DEPLOYER_PRIVATE_KEY : deployerPrivateKey 45 | feePayerAddress = feePayerAddress === '' ? envs.parsed.FEE_PAYER_ADDRESS : feePayerAddress 46 | feePayerPrivateKey = feePayerPrivateKey === '' ? envs.parsed.FEE_PAYER_PRIVATE_KEY : feePayerPrivateKey 47 | } 48 | 49 | async function run() { 50 | const option = { 51 | headers: [ 52 | { 53 | name: 'Authorization', 54 | value: `Basic ${Buffer.from(`${accessKeyId}:${secretAccessKey}`).toString('base64')}`, 55 | }, 56 | { name: 'x-chain-id', value: chainId }, 57 | ], 58 | } 59 | const caver = new Caver(new Caver.providers.HttpProvider(nodeApiUrl, option)) 60 | 61 | // Add keyrings to in-memory wallet 62 | const deployerKeyring = caver.wallet.keyring.create(deployerAddress, deployerPrivateKey) 63 | caver.wallet.add(deployerKeyring) 64 | const feePayerKeyring = caver.wallet.keyring.create(feePayerAddress, feePayerPrivateKey) 65 | caver.wallet.add(feePayerKeyring) 66 | 67 | // byteCode are extracted by compiling caver-js-examples/resources/KVstore.sol using solc(solidity compiler) 68 | const byteCode = 69 | '0x608060405234801561001057600080fd5b5060405161072d38038061072d8339810180604052604081101561003357600080fd5b81019080805164010000000081111561004b57600080fd5b8281019050602081018481111561006157600080fd5b815185600182028301116401000000008211171561007e57600080fd5b5050929190602001805164010000000081111561009a57600080fd5b828101905060208101848111156100b057600080fd5b81518560018202830111640100000000821117156100cd57600080fd5b5050929190505050806000836040518082805190602001908083835b6020831061010c57805182526020820191506020810190506020830392506100e9565b6001836020036101000a0380198251168184511680821785525050505050509050019150509081526020016040518091039020908051906020019061015292919061015a565b5050506101ff565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f1061019b57805160ff19168380011785556101c9565b828001600101855582156101c9579182015b828111156101c85782518255916020019190600101906101ad565b5b5090506101d691906101da565b5090565b6101fc91905b808211156101f85760008160009055506001016101e0565b5090565b90565b61051f8061020e6000396000f3fe608060405234801561001057600080fd5b50600436106100365760003560e01c8063693ec85e1461003b578063e942b5161461016f575b600080fd5b6100f46004803603602081101561005157600080fd5b810190808035906020019064010000000081111561006e57600080fd5b82018360208201111561008057600080fd5b803590602001918460018302840111640100000000831117156100a257600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f8201169050808301925050505050505091929192905050506102c1565b6040518080602001828103825283818151815260200191508051906020019080838360005b83811015610134578082015181840152602081019050610119565b50505050905090810190601f1680156101615780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b6102bf6004803603604081101561018557600080fd5b81019080803590602001906401000000008111156101a257600080fd5b8201836020820111156101b457600080fd5b803590602001918460018302840111640100000000831117156101d657600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f8201169050808301925050505050505091929192908035906020019064010000000081111561023957600080fd5b82018360208201111561024b57600080fd5b8035906020019184600183028401116401000000008311171561026d57600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f8201169050808301925050505050505091929192905050506103cc565b005b60606000826040518082805190602001908083835b602083106102f957805182526020820191506020810190506020830392506102d6565b6001836020036101000a03801982511681845116808217855250505050505090500191505090815260200160405180910390208054600181600116156101000203166002900480601f0160208091040260200160405190810160405280929190818152602001828054600181600116156101000203166002900480156103c05780601f10610395576101008083540402835291602001916103c0565b820191906000526020600020905b8154815290600101906020018083116103a357829003601f168201915b50505050509050919050565b806000836040518082805190602001908083835b6020831061040357805182526020820191506020810190506020830392506103e0565b6001836020036101000a0380198251168184511680821785525050505050509050019150509081526020016040518091039020908051906020019061044992919061044e565b505050565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f1061048f57805160ff19168380011785556104bd565b828001600101855582156104bd579182015b828111156104bc5782518255916020019190600101906104a1565b5b5090506104ca91906104ce565b5090565b6104f091905b808211156104ec5760008160009055506001016104d4565b5090565b9056fea165627a7a72305820adabefbb9574a90843d986f100c723c37f37e79f289b16aa527705b5341499aa0029' 70 | const abi = [ 71 | { 72 | constant: true, 73 | inputs: [{ name: 'key', type: 'string' }], 74 | name: 'get', 75 | outputs: [{ name: '', type: 'string' }], 76 | payable: false, 77 | stateMutability: 'view', 78 | type: 'function', 79 | }, 80 | { 81 | constant: false, 82 | inputs: [ 83 | { name: 'key', type: 'string' }, 84 | { name: 'value', type: 'string' }, 85 | ], 86 | name: 'set', 87 | outputs: [], 88 | payable: false, 89 | stateMutability: 'nonpayable', 90 | type: 'function', 91 | }, 92 | { 93 | inputs: [ 94 | { name: 'key', type: 'string' }, 95 | { name: 'value', type: 'string' }, 96 | ], 97 | payable: false, 98 | stateMutability: 'nonpayable', 99 | type: 'constructor', 100 | }, 101 | ] 102 | 103 | let contract = caver.contract.create(abi) 104 | 105 | const keyString = 'keyString' 106 | 107 | // Send a FeeDelegatedSmartContractDeploy transaction to Klaytn directly. 108 | contract = await contract.deploy( 109 | { 110 | from: deployerKeyring.address, 111 | feeDelegation: true, 112 | feePayer: feePayerKeyring.address, 113 | gas: 1000000, 114 | }, 115 | byteCode, 116 | keyString, 117 | 'valueString' 118 | ) 119 | console.log(`The address of deployed smart contract: ${contract.options.address}`) 120 | 121 | // // The deployer and fee payer each sign the transaction to deploy a smart contract. 122 | // const deployTx = await contract.sign({ 123 | // from: deployerKeyring.address, 124 | // feeDelegation: true, 125 | // gas: 1000000, 126 | // }, 'constructor', byteCode, keyString, 'valueString') 127 | // console.log(`Deployer signed transaction: `) 128 | // console.log(deployTx) 129 | 130 | // await caver.wallet.signAsFeePayer(feePayerKeyring.address, deployTx) // Signs the transaction as a fee payer 131 | // const receipt = await caver.rpc.klay.sendRawTransaction(deployTx) 132 | // console.log(`The address of deployed smart contract: ${receipt.contractAddress}`) 133 | // contract = caver.contract.create(abi, receipt.contractAddress) 134 | 135 | // Read value string from the smart contract. 136 | let valueString = await contract.call('get', keyString) 137 | console.log(`key: ${keyString} / value: ${valueString}`) 138 | 139 | // Send a FeeDelegatedSmartContractExecutionWithRatio transaction to Klaytn directly. 140 | const setResult = await contract.send( 141 | { 142 | from: deployerKeyring.address, 143 | feeDelegation: true, 144 | feePayer: feePayerKeyring.address, 145 | feeRatio: 50, // Without feeRatio, `send` will use FeeDelegatedSmartContractExecution 146 | gas: 1000000, 147 | }, 148 | 'set', 149 | keyString, 150 | 'anotherValue' 151 | ) 152 | 153 | // // The deployer and fee payer each sign the transaction to execute a smart contract. 154 | // const executionTx = await contract.sign({ 155 | // from: deployerKeyring.address, 156 | // feeDelegation: true, 157 | // feeRatio: 50, // Withour feeRatio, `send` will use FeeDelegatedSmartContractExecution 158 | // gas: 1000000, 159 | // }, 'set', keyString, 'anotherValue') 160 | // console.log(`Deployer signed transaction: `) 161 | // console.log(executionTx) 162 | 163 | // await caver.wallet.signAsFeePayer(feePayerKeyring.address, executionTx) // Signs the transaction as a fee payer 164 | // const setResult = await caver.rpc.klay.sendRawTransaction(executionTx) 165 | 166 | console.log(`The set function execution result: ${setResult.status} / Transaction Type: ${setResult.type}`) 167 | 168 | // Read value string from the smart contract. 169 | valueString = await contract.call('get', keyString) 170 | console.log(`After executing set function => key: ${keyString} / value: ${valueString}`) 171 | } 172 | --------------------------------------------------------------------------------