Getting Started (~v1.4.1)

Prerequisites

Dependencies

The following packages are required to use the caver-js library.

참고 caver-js는 Node.js 버전 8 및 10에서 실행할 수 있으며, 권장 버전은 다음과 같습니다:

다른 버전의 Node(가령 Node v12)를 이미 사용중인 경우, Node Version Manager(NVM)를 사용해 caver-js가 지원하는 버전을 설치하고 사용합니다.

Installation

To try it out, install caver-js with npm using the following command:

$ npm install caver-js

Note: package.json file should exist on the same install path. 만일 존재하지 않으면, npm init을 통해 package.json가 생성되어야 합니다.

To install a specific version of caver-js, try the following command:

$ npm install caver-js@X.X.X

caver-js 시작하기

caver-js 설치가 끝나면 이제 caver-js를 Klaytn 노드와 연결할 수 있습니다.

아래 예시와 같이 caver-js 모듈을 가져와 Baobab 테스트넷의 Klaytn 노드에 연결할 수 있습니다:

$ node
> const Caver = require('caver-js')
> const caver = new Caver('https://public-en-baobab.klaytn.net/')

If you are running an EN, you can connect it to your own node by changing the host and port like below:

$ node
> const Caver = require('caver-js')
> const caver = new Caver('https://your.en.url:8651/')

Managing Accounts

Creating an Account

아래와 같이 계정을 생성하기 위해 caver-js를 사용할 수 있습니다. Klaytn Wallet을 통해 계정을 생성할 수 있습니다.

> const account = caver.klay.accounts.create()

> account
{ address: '0x3bd32d55e64d6cbe54bec4f5200e678ee8d1a990',
  privateKey: '0x{private key}',
  ... }

Note: Functions associated with caver.klay.accounts have no effect on the actual Klaytn network.

caver-js에 계정 추가하기

caver-js에서 제공하는 인메모리 지갑을 사용하면 쉽게 계정을 사용할 수 있습니다. 다음 예시는 계정 객체 및 Klaytn Wallet이 생성한 키스토어 파일을 사용해 지갑에 계정을 추가하는 방법을 보여줍니다.

// Using an account object
> caver.klay.accounts.wallet.add(caver.klay.accounts.create())
{ 
    address: '0xebec0df19ed2f8b4070dec94d55a69077c544403',
    privateKey: '0x{private key}',
    signTransaction: [Function: signTransaction],
    sign: [Function: sign],
    encrypt: [Function: encrypt],
    getKlaytnWalletKey: [Function: getKlaytnWalletKey],
    index: 0 
}

// Using a keystore file.
> const decryptedAccount = caver.klay.accounts.decrypt({
        "version": 3,
        "id": "7c05d545-85ce-46c9-b6e9-9110d6597931",
        "address": "0x460406d822b5908504353deabc890e0de61eb42b",
        "crypto": {
            "ciphertext": "d2a84b99312215ca2d8ea43b251dc94fd55c3fc4a0c283538ef114d20251bf4a",
            "cipherparams": {
                "iv": "21b4298e33b8a61549f6abbecbd4d347"
            },
            "cipher": "aes-128-ctr",
            "kdf": "scrypt",
            "kdfparams": {
                "dklen": 32,
                "salt": "6c7a1618ee5525b10ddbcf0f0879214200984f583faf55af5dd2a7a0b7a58fd6",
                "n": 4096,
                "r": 8,
                "p": 1
            },
            "mac": "99e4c25ac8acf1571d4161f2c40db92a391aefd42ec871e23601a7af446432a7"
        }
    }, 'password')
> caver.klay.accounts.wallet.add(decryptedAccount)
{ 
    address: '0x460406d822b5908504353deabc890e0de61eb42b',
    privateKey: '0x{private key}',
    signTransaction: [Function: signTransaction],
    sign: [Function: sign],
    encrypt: [Function: encrypt],
    getKlaytnWalletKey: [Function: getKlaytnWalletKey] 
}

caver-js 지갑에 추가된 계정은 sendTransaction에 사용될 수 있습니다.

Sending a Transaction

이 장에서는 Baobab 네트워크에서 caver-js를 사용하여 KLAY를 보내는 방법을 보여줍니다.

Getting KLAY via Baobab Faucet

테스트를 위해 KLAY가 필요한 경우 Klaytn Wallet에서 Baobab testnet KLAY를 얻을 수 있습니다. Log in to the Klaytn Wallet using the private key or the keystore file and receive Baobab testnet KLAY via the faucet for testing.

Sending a Value Transfer Transaction

트랜잭션 서명은 caver-js 지갑을 통해 할 수 있습니다. 만약 caver-js 지갑에 계정이 있다면, caver.klay.sendTransaction을 실행할 때 caver-js 지갑에 저장된 개인키로 서명이 생성됩니다. 이때 caver.klay.sendTransaction은 서명 생성과 트랜잭션 제출을 동시에 처리합니다.

// 아직 caver-js 지갑에 계정을 추가하지 않았다면 'caver.klay.accounts.wallet.add'를 실행하여 지갑에 계정을 추가하세요.
// 동일한 계정이 이미 지갑에 있는 경우 'Error: Account exists with {hex in address}'가 출력됩니다. 이 경우 출력된 주소값을 'from' 필드에 입력하여 해당 계정을 참조할 수 있습니다.

> const account = caver.klay.accounts.wallet.add('0x{private key}')

> caver.klay.sendTransaction({
    type: 'VALUE_TRANSFER',
    from: account.address',
    to: '0xeF5cd886C7f8d85fbe8023291761341aCBb4DA01',
    gas: '300000',
    value: 1,
  }).then(console.log)
{ 
    blockHash: '0x5e9f427c9550a6f7575bcf60aba9257634884519a6273a23e8eefee2a696cce4',
    blockNumber: 3841096,
    contractAddress: null,
    from: '0x3bd32d55e64d6cbe54bec4f5200e678ee8d1a990',
    ...
    status: true,
    to: '0xef5cd886c7f8d85fbe8023291761341acbb4da01',
    transactionHash: '0xb09f6d26734074a259f6cbe4d509d2bf40f6f0a4559081354527ae211dd9d00f',
    transactionIndex: 1,
    type: 'TxTypeValueTransfer',
    typeInt: 8,
    value: '0x1' 
}

caver-js 지갑 없이 해당 개인키로부터 서명을 직접 생성하고자 하는 경우 다음과 같이 진행할 수 있습니다.

  1. caver.klay.accounts.signTransaction를 실행하세요. - 개인키로 트랜잭션을 서명하고 RLP 인코딩합니다.

  2. caver.klay.sendSignedTransaction을 실행하세요. - caver-js와 연결된 노드에게 RLP 인코딩된 트랜잭션을 전송합니다.

먼저 트랜잭션을 서명하려면 아래와 같이 발신자, 수신자, 개인키를 지정하세요.

참고: 발신자의 잔액은 송금하려는 KLAY보다 많아야 합니다.

> caver.klay.accounts.signTransaction({
    type: 'VALUE_TRANSFER',
    from: '0x71959675eeb7c7ec1e0c74f206a9c488d7f178d4',
    to: '0xeF5cd886C7f8d85fbe8023291761341aCBb4DA01',
    gas: '300000',
    value: caver.utils.toPeb('1', 'KLAY'),
  }, '0x{private key}').then((result)=>{
      rawTransaction = result.rawTransaction
  })

You can get a RLP-encoded transaction (rawTransaction) using caver.klay.accounts.signTransaction as above and use this to transfer the transaction to the Klaytn network as below.

> caver.klay.sendSignedTransaction(rawTransaction).on('transactionHash', console.log)
0xac418c96f7386a3343d149eeb29e48e28905525dda2e5afe55b0661f9ab01aca

위 예시처럼 .on(‘transactionHash’, console.log)를 호출하여 제출한 트랜잭션의 해시를 요청하고 이벤트 이미터(event emitter)로 받아올 수 있어요.

Checking Receipts

caver.klay.sendSignedTransaction 또는 caver.klay.sendTransaction을 통해 트랜잭션을 전송할 때 프로미스(promise)나 이벤트 이미터(event emitter)를 사용하여 트랜잭션의 영수증을 받아올 수 있습니다.

다음 예시는 프로미스(promise) 및 이벤트 이미터(event emitter)를 사용하여 영수증을 받는 과정입니다.

// 프로미스(promise) 사용
> caver.klay.sendSignedTransaction(rawTransaction).then(console.log)
{ 
    blockHash: '0x6ccef34eb59fab927705d344f080f449b576c0626e4aa3e20f569feb8df6e283',
    blockNumber: 19097,
    contractAddress: null,
    from: '0x71959675eeb7c7ec1e0c74f206a9c488d7f178d4',
    ...
    status: true,
    to: '0xef5cd886c7f8d85fbe8023291761341acbb4da01',
    transactionHash: '0xac418c96f7386a3343d149eeb29e48e28905525dda2e5afe55b0661f9ab01aca',
    transactionIndex: 0,
    type: 'TxTypeValueTransfer',
    typeInt: 8,
    value: '0xde0b6b3a7640000' 
}

// 이벤트 이미터(event emitter) 사용
> caver.klay.sendSignedTransaction(rawTransaction).on('receipt', console.log)
{ 
    blockHash: '0x6ccef34eb59fab927705d344f080f449b576c0626e4aa3e20f569feb8df6e283',
    blockNumber: 19097,
    contractAddress: null,
    from: '0x71959675eeb7c7ec1e0c74f206a9c488d7f178d4',
    ...
    status: true,
    to: '0xef5cd886c7f8d85fbe8023291761341acbb4da01',
    transactionHash: '0xac418c96f7386a3343d149eeb29e48e28905525dda2e5afe55b0661f9ab01aca',
    transactionIndex: 0,
    type: 'TxTypeValueTransfer',
    typeInt: 8,
    value: '0xde0b6b3a7640000' 
}

위 예시와 같이 프로미스(promise)와 이벤트 이미터(event emitter)를 통해 트랜잭션을 전송한 결과를 가져올 수 있습니다. And also, if you know the transaction hash, you can query the transaction receipt using the caver.klay.getTransactionReceipt RPC call. The example below shows how to get a receipt using the caver.klay.getTransactionReceipt RPC call.

> caver.klay.getTransactionReceipt('0xbad4dd6d80beda6c04d90f1db7e4179557ab48423d4f14295b33e38a9418e59f').then(console.log)
{ 
    blockHash: '0xd56ac90d552f924f228683f78854c0ffd9f29498f985892f726326a860378a53',
    blockNumber: 3827075,
    contractAddress: null,
    from: '0x3bd32d55e64d6cbe54bec4f5200e678ee8d1a990',
    gas: '0x493e0',
    gasPrice: '0x5d21dba00',
    gasUsed: 21000,
    logs: [],
    logsBloom: '0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000',
    nonce: '0x2',
    senderTxHash: '0xbad4dd6d80beda6c04d90f1db7e4179557ab48423d4f14295b33e38a9418e59f',
    signatures: [ 
        { 
            V: '0x7f5',
            R: '0x30222c5c4a16e9053492ab90b1555585f2f4da3712de9f3e1f9ca8ce952f4aeb',
            S: '0x621d65429322d3ed961ca04a00cf050ee85b35fa69aaa300a41bf483febdc91' 
        } 
    ],
    status: true,
    to: '0xef5cd886c7f8d85fbe8023291761341acbb4da01',
    transactionHash: '0xbad4dd6d80beda6c04d90f1db7e4179557ab48423d4f14295b33e38a9418e59f',
    transactionIndex: 2,
    type: 'TxTypeValueTransfer',
    typeInt: 8,
    value: '0xde0b6b3a7640000' 
}

트랜잭션의 실행 결과는 영수증의 상태를 통하여 확인할 수 있습니다. For a detailed description of the return values, see getTransactionReceipt. 만약 트랜잭션 실행이 실패한다면 에러에 대한 내용은 영수증의 txError에서 확인할 수 있습니다. For more information about txError, see txError: Detailed Information of Transaction Failures.

Executing Other Transaction Types

Klaytn provides various transaction types for extensibility and performance. 자세한 내용은 트랜잭션을 참고하세요. 이 장에서는 caver-js와 함께 사용할 수 있는 다양한 예시를 설명합니다.

Fee Delegation

Klaytn provides Fee Delegation feature. 예제 코드는 다음과 같습니다.

발신인인 경우 아래 코드를 사용하여 RLP로 인코딩된 트랜잭션 객체를 만드세요:

> caver.klay.accounts.signTransaction({
    type: 'FEE_DELEGATED_VALUE_TRANSFER',
    from: '0x3bd32d55e64d6cbe54bec4f5200e678ee8d1a990',
    to: '0xeF5cd886C7f8d85fbe8023291761341aCBb4DA01',
    gas: '300000',
    value: caver.utils.toPeb('1', 'KLAY'),
  }, '0x{private key}').then((ret)=>{rawTransaction = ret.rawTransaction})

> rawTransaction
'0x09f88d038505d21dba00830493e094ef5cd886c7f8d85fbe8023291761341acbb4da01880de0b6b3a7640000943bd32d55e64d6cbe54bec4f5200e678ee8d1a990f847f8458207f5a0a48374bbf227fbbdcb28f3360d0cc1f5e36922be409a3edd8b0c6fa5aa5c57dda07e15ebe1c9dd78d1c0f36a5f7970e578c2e57d9360cd25928674d1c05d7e161d80c4c3018080'

서명된 RLP 인코딩된 트랜잭션 객체 (rawTransaction)으로 트랜잭션 수수료 납부자는 서명을 첨부한 후 트랜잭션을 보낼 수 있습니다. 트랜잭션 수수료 납부자는 senderRawTransaction에 rawTransaction를 설정하고 아래 예시와 같이 트랜잭션 수수료 납부자의 주소로 서명합니다.

// 아직 caver-js 지갑에 트랜잭션 수수료 납부자의 계정을 추가하지 않았다면, 'caver.klay.accounts.wallet.add'를 실행하여 지갑에 계정을 추가하세요.
// 이미 계정이 지갑에 추가된 경우 'Error: Account exists with {hex in address}'가 출력됩니다. 이 경우 `feePayer.address` 대신 계정 주소를 사용하세요.
> const feePayer = caver.klay.accounts.wallet.add('0x{private key}')

> caver.klay.sendTransaction({
    senderRawTransaction: rawTransaction,
    feePayer: feePayer.address,
  }).then(console.log)
{ 
    blockHash: '0xf0c4ef717a674ffaea8bf68597c936ce8a3773dab1e1f6f42508963f124bc301',
    blockNumber: 3840725,
    ...
    transactionHash: '0x8d1fea7710bc351540257a4ae7f2274d66ddd7f62bcdb6f1f77893cecb659405',
    transactionIndex: 2,
    type: 'TxTypeFeeDelegatedValueTransfer',
    typeInt: 9,
    value: '0xde0b6b3a7640000' 
}

참고: 트랜잭션 수수료 납부자의 계정은 caver-js 지갑에 있어야 합니다.

Account Update

계정의 키를 변경하려면 아래와 같은 트랜잭션을 보내세요. Please check Account Update for the transaction field according to the key type.

// If you have not added an account to caver-js's wallet, add it to your wallet by running 'caver.klay.accounts.wallet.add'.
// If the same account is already in the wallet, 'Error: Account exists with {hex in address}' is returned. In this case, you can use the address string in the `from` field to reference the account in the wallet.
> const account = caver.klay.accounts.wallet.add('0x{private key}')

> caver.klay.sendTransaction({
    type: 'ACCOUNT_UPDATE',
    from: account.address,
    publicKey:  '0x9016de15ebb219b1e8bc732070df93a28903e5799d0cd24a807a5afabf4601f7e5ab312b5a682dd8c0e72e71e67552174d5082cde25db3626a5b025f97f8a005',
    gas: '300000',
}).then(console.log);

Smart Contract

The caver.klay.Contract package makes it easy to interact with smart contracts on Klaytn. 저수준 ABI(Application Binary Interface)가 주어지면 스마트 컨트랙트의 모든 메소드를 자동으로 자바스크립트 호출로 변환합니다. This allows you to interact with smart contracts as if they were JavaScript objects.

먼저 스마트 컨트랙트를 컴파일하여 바이트코드와 ABI를 얻습니다.

> solc --abi --bin --allow-paths . ./test.sol
======= ./test.sol:Count =======
Binary: 
60806040526000805534801561001457600080fd5b50610123806100246000396000f3fe6080604052600436106053576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff16806306661abd14605857806342cbb15c146080578063d14e62b81460a8575b600080fd5b348015606357600080fd5b50606a60df565b6040518082815260200191505060405180910390f35b348015608b57600080fd5b50609260e5565b6040518082815260200191505060405180910390f35b34801560b357600080fd5b5060dd6004803603602081101560c857600080fd5b810190808035906020019092919050505060ed565b005b60005481565b600043905090565b806000819055505056fea165627a7a72305820e381897039d8e48bf74b4a096bb1c4ed02f331bd1a7a4add6217b72fa888f2f10029
Contract JSON ABI 
[{"constant":true,"inputs":[],"name":"count","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"getBlockNumber","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_count","type":"uint256"}],"name":"setCount","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"}]

참고: 스마트 컨트랙트를 컴파일하려면 솔리디티 컴파일러가 설치되어 있어야 합니다.

For smart contract deployment, you can use caver.klay.Contract to deploy it, or you can deploy it using SMART_CONTRACT_DEPLOY transaction. Here is an example of using caver.klay.Contract.

컨트랙트 인스턴스가 생성되면, 아래와 같이 바이트코드를 data 필드에 전달하는 것으로 배포할 수 있습니다:

// If you have not added an account to caver-js's wallet, add it to your wallet by running 'caver.klay.accounts.wallet.add'.
// If the same account is already in the wallet, 'Error: Account exists with {hex in address}' is returned. In this case, you can use the address string in the `from` field to reference the account in the wallet.
> const account = caver.klay.accounts.wallet.add('0x{private key}')

> contractInstance.deploy({
    data:  '60806040526000805534801561001457600080fd5b50610123806100246000396000f3fe6080604052600436106053576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff16806306661abd14605857806342cbb15c146080578063d14e62b81460a8575b600080fd5b348015606357600080fd5b50606a60df565b6040518082815260200191505060405180910390f35b348015608b57600080fd5b50609260e5565b6040518082815260200191505060405180910390f35b34801560b357600080fd5b5060dd6004803603602081101560c857600080fd5b810190808035906020019092919050505060ed565b005b60005481565b600043905090565b806000819055505056fea165627a7a72305820e381897039d8e48bf74b4a096bb1c4ed02f331bd1a7a4add6217b72fa888f2f10029',
}).send({
    from: account.address,
    gas: '0x4bfd200',
    value: '0x0',
}).then(console.log)
{ 
    blockHash: '0x71426773ed65f307bdfac5070ac54f11f406086bbe8dfa170215ed4190f176ed',
    blockNumber: 226,
    codeFormat: '0x0',
    contractAddress: '0xC9f0b868e5103b6823171a2Df85E7B696660E466',
    from: '0x71959675eeb7c7ec1e0c74f206a9c488d7f178d4',
    gas: '0x4bfd200',
    gasPrice: '0x5d21dba00',
    gasUsed: 149017,
    humanReadable: false,
    input: '0x60806040526000805534801561001457600080fd5b50610123806100246000396000f3fe6080604052600436106053576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff16806306661abd14605857806342cbb15c146080578063d14e62b81460a8575b600080fd5b348015606357600080fd5b50606a60df565b6040518082815260200191505060405180910390f35b348015608b57600080fd5b50609260e5565b6040518082815260200191505060405180910390f35b34801560b357600080fd5b5060dd6004803603602081101560c857600080fd5b810190808035906020019092919050505060ed565b005b60005481565b600043905090565b806000819055505056fea165627a7a72305820e381897039d8e48bf74b4a096bb1c4ed02f331bd1a7a4add6217b72fa888f2f10029',
    ...
    type: 'TxTypeSmartContractDeploy',
    typeInt: 40,
    value: '0x0',
    events: {} 
}

배포된 컨트랙트 주소는 트랜잭션 영수증의 contractAddress에서 찾을 수 있습니다. 스마트 컨트랙트 실행 트랜잭션을 보내기 전, 다음과 같이 주소를 컨트랙트 인스턴스의 주소로 설정하세요:

> contractInstance.options.address = '0xC9f0b868e5103b6823171a2Df85E7B696660E466'
'0xC9f0b868e5103b6823171a2Df85E7B696660E466'

One way to invoke a specific method of a smart contract is to use it with caver.klay.Contract or use SMART_CONTRACT_EXECUTION.

To transact with a smart contract:

// If you have not added an account to caver-js's wallet, add it to your wallet by running 'caver.klay.accounts.wallet.add'.
// If the same account is already in the wallet, 'Error: Account exists with {hex in address}' is returned. In this case, you can use the address string in the `from` field to reference the account in the wallet.
> const account = caver.klay.accounts.wallet.add('0x{private key}')

> contractInstance.methods.setCount(1).send({from:account.address, gas:'0x4bfd200'}).then(console.log)
{ 
    blockHash: '0x159f8515102951bca9c403b2b1b37850ca01a08dffb9a763837f55a6d518bbb6',
    blockNumber: 644,
    contractAddress: null,
    from: '0x71959675eeb7c7ec1e0c74f206a9c488d7f178d4',
    gas: '0x4bfd200',
    gasPrice: '0x5d21dba00',
    gasUsed: 44875,
    input: '0xd14e62b80000000000000000000000000000000000000000000000000000000000000001',
    ...
    type: 'TxTypeSmartContractExecution',
    typeInt: 48,
    value: '0x0',
    events: {} 
}

To call a smart contract:

> contractInstance.methods.getBlockNumber().call().then(console.log)
2194

See caver.klay.Contract for details.

Using various AccountKey Types

caver-js introduces new classes to support the various types of AccountKey supported by the platform.

아래 예제는 Node.js 파일에서의 예시를 설명합니다. 예제를 실습하려면, 먼저 아래처럼 작업 디렉토리에 테스트 파일을 생성하세요.

$ touch test.js

작업 디렉토리에 생성된 test.js 파일을 확인할 수 있을 것입니다.

test.js에 다음 코드를 작성하세요.

// test.js file
const Caver = require('caver-js')
const caver = new Caver('https://public-en-baobab.klaytn.net/')

async function testFunction() {
    const version = await caver.klay.getNodeInfo()
    console.log(version)
}

testFunction()

파일을 저장하고 콘솔에서 실행하세요.

$ node ./test.js

console.log 출력을 확인했다면, 아래 단계로 진행하세요.

참고 caver-js v1.2.0부터 이러한 클래스가 지원됩니다.

Account

Account는 계정의 주소와 키를 포함하는 클래스입니다. Account에는 AccountKeyPublic, AccountKeyMultiSig, 또는 AccountKeyRoleBased 중 하나인 AccountKey가 있습니다.

caver.klay.accounts 패키지는 개인키를 저장하고 관리하는 AccountKeyPublic을 기본으로 사용합니다.

다음 예제는 AccountKeyPublic을 AccountKey로 가지는 계정을 만듭니다.

// test.js file
async function testFunction() {
    // Create random account with accountKeyPublic by default
    const account = caver.klay.accounts.create()
    printAccount(account)

    // Create account with specific private key string
    const privateKey = caver.klay.accounts.create().privateKey
    const accountFromKey = caver.klay.accounts.privateKeyToAccount(privateKey)
    printAccount(accountFromKey)
}

function printAccount(account) {
    console.log(`address: ${account.address}`)
    console.log(`privateKey: ${account.privateKey}`)
    console.log(`accountKeyType: ${account.accountKeyType}`)
    console.log(`accountKey`)
    console.log(account.accountKey)
    console.log(`account.keys: ${account.keys}`)
    console.log(`account.transactionKey: ${account.transactionKey}`)
    console.log(`account.updateKey: ${account.updateKey}`)
    console.log(`account.feePayerKey: ${account.feePayerKey}\n`)
}

위의 printAccount는 계정 인스턴스의 속성을 사용하는 방법을 보여줍니다. 계정 내부의 속성은 다음과 같습니다.

참고 transactionKey, updateKey, 그리고 feePayerKey는 역할에 사용해야 하는 개인키 문자열 또는 개인키 문자열 배열을 반환합니다. 따라서 privateKey 속성을 사용하는 대신, accountKey 유형에 대한 걱정 없이 transactionKey, updateKey 그리고 feePayerKey를 적절하게 사용하는 것이 권장됩니다.

다양한 AccountKey 클래스에 대한 설명은 AccountKey 부분에서 제공됩니다.

AccountKey

AccountKey는 계정의 키를 저장하는 데이터 구조입니다. 계정에는 서명에 사용할 하나의 개인키 문자열 또는 여러 개인키 문자열이 있을 수 있습니다. 계정은 역할들로 개인키를 관리할 수도 있습니다.

이 구조를 지원하기 위해, caver-js는 AccountKeyPublic, AccountKeyMultiSig 및 AccountKeyRoleBased라는 새로운 클래스를 도입했습니다.

AccountKey를 만들려면 caver.klay.accounts.createAccountKey를 사용하세요. 이 함수는 매개변수 유형에 따라 생성할 AccountKey를 결정합니다. 개인키 문자열이 매개변수로 제공되면 AccountKeyPublic을 생성하고, 개인키 문자열 배열이 제공되면 AccountKeyMultiSig를 생성합니다. 각 역할마다 다른 키를 가진 객체가 있으면 AccountKeyRoleBased를 생성합니다.

참고 caver-js에서 정의된 AccountKey에 대한 클래스는 caver-js에서 개인키를 저장하기 위한 데이터 구조입니다. Klaytn 네트워크 계정의 키와 다를 수 있습니다.

AccountKeyPublic

AccountKeyPublic은 하나의 개인키 문자열을 저장하고 관리하기 위한 클래스입니다.

다음은 AccountKeyPublic으로 계정을 업데이트하는 방법에 대해 설명합니다. 다음 코드를 testFunction()에 작성하고 실행하세요.

const privateKey = caver.klay.accounts.create().privateKey
const accountKey = caver.klay.accounts.createAccountKey(privateKey)

console.log(accountKey)
console.log(`type: ${accountKey.type}`)
console.log(`keys: ${accountKey.keys}`)
console.log(`transactionKey: ${accountKey.transactionKey}`)
console.log(`updateKey: ${accountKey.updateKey}`)
console.log(`feePayerKey: ${accountKey.feePayerKey}`)

AccountKeyPublic는 개인키 문자열을 저장하고 관리하므로, 위의 예제를 실행하면, keys, transactionKey, updateKey 그리고 feePayerKey 모두 동일한 개인키 문자열을 나타내는 것을 볼 수 있을 것입니다.

AccountKeyPublic을 accountKey로 계정을 생성하는 예제는 아래를 참조하세요.

const privateKey = caver.klay.accounts.create().privateKey
const accountKey = caver.klay.accounts.createAccountKey(privateKey)

const address = caver.klay.accounts.create().address

// Create an Account instance with a private key string
const accountFromStringKey = caver.klay.accounts.createWithAccountKey(address, privateKey)

// Create an Account instance with an AccountKeyPublic instance
const accountFromAccountKey = caver.klay.accounts.createWithAccountKey(address, accountKey)

AccountKeyMultiSig

AccountKeyPublic은 여러 개인키 문자열을 저장하고 관리하기 위한 클래스입니다.

다음은 AccountKeyMultiSig으로 계정을 업데이트하는 방법에 대해 설명합니다. Write the following code into testFunction() and run it.

const privateKeyArray = [caver.klay.accounts.create().privateKey, caver.klay.accounts.create().privateKey, caver.klay.accounts.create().privateKey]
const accountKey = caver.klay.accounts.createAccountKey(privateKeyArray)

console.log(accountKey)
console.log(`type: ${accountKey.type}`)
console.log(`keys: ${accountKey.keys}`)
console.log(`transactionKey: ${accountKey.transactionKey}`)
console.log(`updateKey: ${accountKey.updateKey}`)
console.log(`feePayerKey: ${accountKey.feePayerKey}`)

AccountKeyPublic는 여러 개인키 문자열을 저장하고 관리하므로, 위의 예제를 실행하면, keys, transactionKey, updateKey 그리고 feePayerKey 모두 동일한 여러 개인키 문자열을 나타내는 것을 볼 수 있을 것입니다.

만일 트랜잭션을 서명할 때 사용할 개인키(또는 개인키 문자열의 배열)를 명시하지 않았다면, caver-js는 인메모리 지갑에서 from 또는 fee payer와 일치하는 계정을 찾아 서명합니다. 이 경우, 계정에 여러 개의 개인키가 있는 경우, caver-js는 모든 해당하는 키로 트랜잭션에 서명합니다.

AccountKeyMultiSig을 accountKey로 계정을 생성하는 예제는 아래를 참조하세요.

const privateKeyArray = [caver.klay.accounts.create().privateKey, caver.klay.accounts.create().privateKey]
const accountKey = caver.klay.accounts.createAccountKey(privateKeyArray)

const address = caver.klay.accounts.create().address

// Create Account instance with an array of private key strings
const accountFromStringKey = caver.klay.accounts.createWithAccountKey(address, privateKeyArray)

// Create Account instance with AccountKeyMultiSig instance
const accountFromAccountKey = caver.klay.accounts.createWithAccountKey(address, accountKey)

AccountKeyRoleBased

AccountKeyRoleBased는 각 역할의 키를 저장하고 관리하기 위한 클래스입니다. 각 역할은 하나의 개인키 문자열 또는 여러 개인키 문자열을 가질 수 있습니다.

다음은 AccountKeyRoleBased으로 계정을 업데이트하는 방법에 대해 설명합니다. Write the following code into testFunction() and run it.

const keyobject = {
    transactionKey: [caver.klay.accounts.create().privateKey, caver.klay.accounts.create().privateKey, caver.klay.accounts.create().privateKey],
    updateKey: caver.klay.accounts.create().privateKey,
    feePayerKey: [caver.klay.accounts.create().privateKey, caver.klay.accounts.create().privateKey, caver.klay.accounts.create().privateKey]
}
const accountKey = caver.klay.accounts.createAccountKey(keyobject)

console.log(accountKey)
console.log(`type: ${accountKey.type}`)
console.log(`keys:`)
console.log(accountKey.keys)
console.log(`transactionKey: ${accountKey.transactionKey}`)
console.log(`updateKey: ${accountKey.updateKey}`)
console.log(`feePayerKey: ${accountKey.feePayerKey}`)

AccountKeyRoleBased는 역할별로 키를 저장하고 관리하므로, 위의 예제를 실행하면, keys 속성에 정의된 세 가지 역할(transactionKey, updateKey, feePayerKey)을 확인할 수 있습니다. 따라서, 다른 AccountKey(AccountKeyPublic 또는 AccountKeyMultiSig)와 달리, transactionKey, updateKey 및 feePayerKey는 각각 다른 키를 나타냅니다.

AccountKeyRoleBased을 accountKey로 계정을 생성하는 예제는 아래를 참조하세요.

const keyobject = {
    transactionKey: [caver.klay.accounts.create().privateKey, caver.klay.accounts.create().privateKey, caver.klay.accounts.create().privateKey],
    updateKey: caver.klay.accounts.create().privateKey,
    feePayerKey: [caver.klay.accounts.create().privateKey, caver.klay.accounts.create().privateKey, caver.klay.accounts.create().privateKey]
}
const accountKey = caver.klay.accounts.createAccountKey(keyobject)

const address = caver.klay.accounts.create().address

// Create Account instance with an object that defines key by role
const accountFromStringKey = caver.klay.accounts.createWithAccountKey(address, keyobject)

// Create Account instance with AccountKeyRoleBased instance
const accountFromAccountKey = caver.klay.accounts.createWithAccountKey(address, accountKey)

위의 예제를 통해 caver-js에서 계정 및 다양한 AccountKey 유형을 사용하는 방법을 볼 수 있습니다.

이 예제는 Klaytn 네트워크에 영향을 미치지 않음을 유의하세요. AccountKeyPublic, AccountKeyMultiSig 또는 AccountKeyRoleBased와 같은 특정 계정 키 유형으로 계정을 사용하려면, Klaytn 네트워크에 계정 업데이트 트랜잭션을 보내야합니다.

다음 AccountForUpdate는 Klaytn 네트워크에 트랜잭션을 보내 계정을 업데이트하는 방법에 대해 설명합니다.

AccountForUpdate

AccountForUpdate는 계정 업데이트를 위한 트랜잭션을 보다 쉽게 사용할 수 있도록 설계한 클래스입니다.

AccountForUpdate는 계정 업데이트에 사용할 공개키와 업데이트 할 계정의 주소만 가지고 있습니다.

아래 예제는 accountKey로 계정을 업데이트하는 것으로 시작합니다. 계정에 테스트에 사용하기 충분한 KLAY가 있어야 합니다. Baobab 네트워크에서 사용할 테스트 KLAY는 Baobab Faucet에서 얻을 수 있습니다.

AccountForUpdate 생성하기

AccountForUpdate를 생성하는 것으로 시작하겠습니다.

업데이트할 계정 주소와 사용할 새로운 키로 createAccountForUpdate()를 호출하여 생성할 수 있습니다.

const account = caver.klay.accounts.create()

// AccountForUpdate with AccountKeyPublic
const privateKeyString = caver.klay.accounts.create().privateKey
const accountForUpdateForAccountKeyPublic = caver.klay.accounts.createAccountForUpdate(account.address, privateKeyString)

// AccountForUpdate with AccountKeyMultiSig
const privateKeyArray = [caver.klay.accounts.create().privateKey, caver.klay.accounts.create().privateKey]
const multiSigOptions = { threshold: 2, weight: [1, 1] }
const accountForUpdateForAccountKeyMultiSig = caver.klay.accounts.createAccountForUpdate(account.address, privateKeyArray, multiSigOptions)

// AccountForUpdate with AccountKeyRoleBased
const keyObject = {
    transactionKey: [caver.klay.accounts.create().privateKey, caver.klay.accounts.create().privateKey],
    updateKey: caver.klay.accounts.create().privateKey,
    feePayerKey: caver.klay.accounts.create().privateKey,
}
const roleBasedOptions = { transactionKey: { threshold: 2, weight: [1, 1] } }
const accountForUpdateForAccountKeyRoleBased = caver.klay.accounts.createAccountForUpdate(account.address, keyObject, roleBasedOptions)

// AccountForUpdate with LegacyKey
const accountForUpdateForLegacyKey = caver.klay.accounts.createAccountForUpdateWithLegacyKey(account.address)

// AccountForUpdate with FailKey
const accountForUpdateForFailKey = caver.klay.accounts.createAccountForUpdateWithFailKey(account.address)

참고 개인키 문자열 여러 개를 가지도록 업데이트 할 때는 option 개체에 임계 값과 가중치를 정의해야 합니다.

AccountForUpdate로 계정 업데이트

위에서 만든 AccountForUpdate를 사용하여 계정 업데이트 트랜잭션을 쉽게 만들 수 있습니다.

계정을 업데이트 하는데 사용하는 트랜잭션은 세 종류가 있습니다 : ACCOUNT_UPDATE, FEE_DELEGATED_ACCOUNT_UPDATE 그리고 FEE_DELEGATED_ACCOUNT_UPDATE_WITH_RATIO.

아래 예에서 account는 KLAY 잔액이 충분한 계정이며 accountForUpdate는 새로운 키와 변경하고자 하는 계정 주소를 가진 AccountForUpdate 객체입니다. accountForUpdate는 caver.klay.accounts.createAccountForUpdate를 사용하여 생성됩니다.

아래 예는 AccountForUpdate를 사용하여 트랜잭션을 생성하고 Klaytn 네트워크로 전송하는 방법을 보여줍니다.

const updateTx = {
    type: 'ACCOUNT_UPDATE',
    from: account.address,
    key: accountForUpdate,
    gas: 300000,
}

// Sign transaction with updateKey of account
const signed = await caver.klay.accounts.signTransaction(updateTx, account.updateKey)

// Send account update transaction
const receipt = await caver.klay.sendSignedTransaction(signed)
console.log(receipt)

// Get accountKey from Klaytn network
const updatedKey = await caver.klay.getAccountKey(account.address)
console.log(updatedKey)

FEE_DELEGATED_ACCOUNT_UPDATE 트랜잭션을 사용하는 방법은 아래 예를 참조하세요.

const updateTx = {
    type: 'FEE_DELEGATED_ACCOUNT_UPDATE',
    from: account.address,
    key: accountForUpdate,
    gas: 300000,
}

// Sender signs transaction with updateKey of account
const senderSigned = await caver.klay.accounts.signTransaction(updateTx, account.updateKey)

// Fee payer signs transaction with feePayerKey of fee payer
const feePayerSigned = await caver.klay.accounts.feePayerSignTransaction(senderSigned.rawTransaction, feePayer.address, feePayer.feePayerKey)

// Send fee delegated account update transaction
const receipt = await caver.klay.sendSignedTransaction(feePayerSigned)
console.log(receipt)

// Get accountKey from Klaytn network
const updatedKey = await caver.klay.getAccountKey(account.address)
console.log(updatedKey)

NOTE caver.klay.accounts.feePayerSignTransaction is supported since caver-js v1.2.0.

FEE_DELEGATED_ACCOUNT_UPDATE_WITH_RATIO 트랜잭션을 사용하려는경우 위의 예제에 updateTx를 아래와 같이 정의하세요.

const updateTx = {
    type: 'FEE_DELEGATED_ACCOUNT_UPDATE_WITH_RATIO',
    from: account.address,
    key: accountForUpdate,
    gas: 300000,
    feeRatio: 30,
}

계정이 성공적으로 업데이트되면 이전 키를 더 이상 사용할 수 없습니다. caver-js에 저장된 계정의 accountKey를 아래와 같이 업데이트 하세요.

계정의 accountKey 프로퍼티를 직접적으로 변경하고자 할 때, 할당하는 값은 AccountKeyPublic, AccountKeyMultiSig, 또는 AccountKeyRoleBased의 객체이어야만 합니다.

const accountKey = caver.klay.accounts.createAccountKey(newKey)
account.accountKey = accountKey

계정이 caver-js의 인메모리 지갑에 있는 경우, 아래와 같이 업데이트하세요.

// Add account to in-memory wallet
caver.klay.accounts.wallet.add(account)

caver.klay.accounts.wallet.updateAccountKey(account.address, newKey)

이제 caver-js에서 업데이트된 계정을 사용할 준비가 되었습니다.

다중 서명된 트랜잭션 보내기

계정의 accountKey가 AccountKeyMultiSig 또는 AccountKeyRoleBased인 경우 각 키를 관리하는 사람이 다를 수 있습니다.

This section describes how to collect signatures and send the transaction if there are multiple signers.

순차적 서명

The result object of caver.klay.accounts.signTransaction has a rawTransaction field.

rawTransaction은 RLP 인코딩된 트랜잭션으로 signaturesfeePayerSignatures를 가지고 있습니다. feePayerSignature is included only when the transaction is a fee delegated transaction.

다음 예제는 여러 개인 키를 사용하여 트랜잭션에 순차적으로 서명하는 방법을 보여줍니다. 계정의 transactionKey에 두 개의 개인키 문자열이 있다고 가정해보죠.

const tx = {
    type: 'VALUE_TRANSFER',
    from: account.address,
    to: caver.klay.accounts.create().address,
    value: 1,
    gas: 900000,
}

// Sign with transactionKey[0]
const user1Signed = await caver.klay.accounts.signTransaction(tx, account.transactionKey[0])

// Append sender's signatures with transactionKey[1]
const user2Signed = await caver.klay.accounts.signTransaction(user1Signed.rawTransaction, account.transactionKey[1])

const receipt = await caver.klay.sendSignedTransaction(user2Signed)
console.log(receipt)

AccountKeyRoleBased 타입의 수수료 납부자 키로 서명하려면 아래 예를 참조하십시오. 수수료 납부자는 feePayerKey에 3개의 개인키 문자열이 있다고 가정합니다.

const tx = {
    type: 'FEE_DELEGATED_VALUE_TRANSFER',
    from: account.address,
    to: caver.klay.accounts.create().address,
    value: 1,
    gas: 900000,
}

// Sign with transactionKey[0] and transactionKey[1]
const userSigned = await caver.klay.accounts.signTransaction(tx, [account.transactionKey[0], account.transactionKey[1]])

// Fee payer signs transaction with feePayerKey[0]
const feePayer1Signed = await caver.klay.accounts.feePayerSignTransaction(userSigned.rawTransaction, feePayer.address, feePayer.feePayerKey[0])

// Append feePayerSignatures with feePayerKey[1] and feePayerKey[2]
const feePayer2Signed = await caver.klay.accounts.feePayerSignTransaction(feePayer1Signed.rawTransaction, feePayer.address, [feePayer.feePayerKey[1], feePayer.feePayerKey[2]])

const receipt = await caver.klay.sendSignedTransaction(feePayer2Signed)
console.log(receipt)

NOTE caver.klay.accounts.feePayerSignTransaction is supported since caver-js v1.2.0.

사용하는 계정이 caver-js의 인메모리 지갑에 있으면 키를 signTransaction 또는 feePayerSignTransaction에 전달할 필요가 없습니다. See the example below.

const tx = {
    type: 'FEE_DELEGATED_VALUE_TRANSFER_WITH_RATIO',
    from: account.address,
    to: caver.klay.accounts.create().address,
    value: 1,
    gas: 900000,
    feeRatio: 10,
}

// Sign with transactionKey[0] and transactionKey[1]
const userSigned = await caver.klay.accounts.signTransaction(tx)

// Fee payer signs transaction with feePayerKey[0], feePayerKey[1] and feePayerKey[2]
const feePayerSigned = await caver.klay.accounts.feePayerSignTransaction(userSigned.rawTransaction, feePayer.address)

const receipt = await caver.klay.sendSignedTransaction(feePayerSigned)
console.log(receipt)

RawTransaction의 서명을 통합하기

여러 사람으로부터 caver.klay.accounts.signTransaction 또는 caver.klay.accounts.feePayerSignTransaction이 반환하는 오브젝트를 전달받은 경우, 모든 서명 정보를 포함한 하나의 RLP 인코딩된 트랜잭션을 생성할 수 있습니다.

아래 예제는 RLP 인코딩된 트랜잭션들을 하나로 통합하고 전송하는 방법을 보여줍니다.

const tx = {
    type: 'FEE_DELEGATED_VALUE_TRANSFER',
    from: account.address,
    to: caver.klay.accounts.create().address,
    value: 1,
    gas: 900000,
}

// Sign with transactionKey[0]
const user1Signed = await caver.klay.accounts.signTransaction(tx, account.transactionKey[0])

// Sign with transactionKey[1]
const user2Signed = await caver.klay.accounts.signTransaction(tx, account.transactionKey[1])

// Fee payer signs transaction with feePayerKey[0]
const feePayer1Signed = await caver.klay.accounts.feePayerSignTransaction(tx, feePayer.address, feePayer.feePayerKey[0])

// Fee payer signs transaction with feePayerKey[1]
const feePayer2Signed = await caver.klay.accounts.feePayerSignTransaction(tx, feePayer.address, feePayer.feePayerKey[1])

// Fee payer signs transaction with feePayerKey[2]
const feePayer3Signed = await caver.klay.accounts.feePayerSignTransaction(tx, feePayer.address, feePayer.feePayerKey[2])

const rawTransactionArray = [user1Signed.rawTransaction, user2Signed.rawTransaction, feePayer1Signed.rawTransaction, feePayer2Signed.rawTransaction, feePayer3Signed.rawTransaction]
const combined = await caver.klay.accounts.combineSignatures(rawTransactionArray)

const receipt = await caver.klay.sendSignedTransaction(combined)
console.log(receipt)

NOTE caver.klay.accounts.combineSignatures is supported since caver-js v1.2.0.

Signatures 및 FeePayerSignatures와 함께 트랜잭션 오브젝트 전송하기

여러 서명인로부터 signatures 또는 feePayerSignatures만을 전달받는 경우, 아래와 같이 트랜잭션을 전송할 수 있습니다.

const tx = {
    type: 'FEE_DELEGATED_VALUE_TRANSFER_WITH_RATIO',
    from: account.address,
    to: caver.klay.accounts.create().address,
    value: 1,
    gas: 900000,
    feeRatio: 10,
}

// Sign with transactionKey[0] and transactionKey[1]
const { signatures } = await caver.klay.accounts.signTransaction(tx)

// Fee payer signs transaction with feePayerKey[0], feePayerKey[1] and feePayerKey[2]
const { feePayerSignatures } = await caver.klay.accounts.feePayerSignTransaction(tx, feePayer.address)

// Fill in the missing information in the tx object.
tx.signatures = signatures
tx.feePayer = feePayer.address
tx.feePayerSignatures = feePayerSignatures

const receipt = await caver.klay.sendSignedTransaction(tx)
console.log(receipt)

또한, caver.klay.accounts.getRawTransactionWithSignatures을 호출하여 트랜잭션 오브젝트의 signatures와 feePayerSignatures를 포함한 RLP 인코딩된 트랜잭션을 얻을 수 있습니다.

const tx = {
    type: 'FEE_DELEGATED_VALUE_TRANSFER_WITH_RATIO',
    from: account.address,
    to: caver.klay.accounts.create().address,
    value: 1,
    gas: 900000,
    feeRatio: 10,
}

// Sign with transactionKey[0] and transactionKey[1]
const { signatures } = await caver.klay.accounts.signTransaction(tx)

// Fee payer signs transaction with feePayerKey[0], feePayerKey[1] and feePayerKey[2]
const { feePayerSignatures } = await caver.klay.accounts.feePayerSignTransaction(tx, feePayer.address)

// Fill in the missing information in the tx object.
tx.signatures = signatures
tx.feePayer = feePayer.address
tx.feePayerSignatures = feePayerSignatures

const { rawTransaction } = await caver.klay.accounts.getRawTransactionWithSignatures(tx)
console.log(rawTransaction)

NOTE caver.klay.accounts.getRawTransactionWithSignatures is supported since caver-js v1.2.0.

샘플 프로젝트

Sample projects for development of dApps (Decentralized Applications) using caver-js can be found below:

Last updated