Skip to main content

Role-based Account Key

AccountKeyRoleBased represents a role-based key. If an account has an AccountKeyRoleBased object and the transaction type is one except account update, the validation process is done according to each roles like below:

Import necessary classes from the Web3j and kaia libraries(web3j-ext).

Create a Web3j instance with the specified BAOBAB_URL

Also, you can change the default provider. For example, using the alchemy provider.

Create 3 diffent credentials from private keys

Gas price and gas limit settings

Get chain ID from the network

Get the nonce for the sender's address

Generate new account keys and theirs weight for account update

Combine generated weight account keys into a list

Specify the role for each key, the possible role are transaction, update, fee payer.

Combine generated role key into a list

Set transaction type as ACCOUNT_UPDATE

Create a raw transaction for account update

Sign the transaction

Send the signed transaction to kaia network

Wait for the transaction to be completed and get the transaction receipt

Shut down the Web3j instance

Decode the raw transaction to get the transaction type

AccountUpdateWithRoleBasedExample.java

package org.web3j.example.accountKey;
import org.web3j.tx.response.PollingTransactionReceiptProcessor;
import org.web3j.tx.response.TransactionReceiptProcessor;
import org.web3j.example.keySample;
import java.io.IOException;
import java.math.BigInteger;
import java.util.List;
import org.web3j.crypto.KlayCredentials;
import org.web3j.crypto.KlayRawTransaction;
import org.web3j.crypto.KlayTransactionEncoder;
import org.web3j.crypto.transaction.account.AccountKey;
import org.web3j.crypto.transaction.account.AccountKeyPublic;
import org.web3j.crypto.transaction.account.AccountKeyRoleBased;
import org.web3j.crypto.transaction.account.AccountKeyWeightedMultiSig;
import org.web3j.crypto.transaction.account.AccountKeyWeightedMultiSig.WeightedPublicKey;
import org.web3j.crypto.transaction.type.TxType;
import org.web3j.crypto.transaction.type.TxTypeAccountUpdate;
import org.web3j.crypto.transaction.type.TxType.Type;
import org.web3j.protocol.core.DefaultBlockParameterName;
import org.web3j.protocol.core.methods.response.EthChainId;
import org.web3j.protocol.core.methods.response.EthSendTransaction;
import org.web3j.protocol.kaia.Web3j;
import org.web3j.protocol.http.HttpService;
import org.web3j.utils.Numeric;
import org.web3j.protocol.kaia.core.method.response.TransactionReceipt;
public class AccountUpdateWithRoleBasedExample {
public static void run() throws Exception {
Web3j web3j = Web3j.build(new HttpService(keySample.BAOBAB_URL));
KlayCredentials credential1 = KlayCredentials.create(keySample.ROLEBASED_KEY_transactionkey, keySample.ROLEBASED_KEY_address);
KlayCredentials credential2 = KlayCredentials.create(keySample.ROLEBASED_KEY_updatekey, keySample.ROLEBASED_KEY_address);
KlayCredentials credential3 = KlayCredentials.create(keySample.ROLEBASED_KEY_feepayer, keySample.ROLEBASED_KEY_address);
BigInteger GAS_PRICE = BigInteger.valueOf(50000000000L);
BigInteger GAS_LIMIT = BigInteger.valueOf(6721950);
String from = credential1.getAddress();
EthChainId EthchainId = web3j.ethChainId().send();
long chainId = EthchainId.getChainId().longValue();
BigInteger nonce = web3j.ethGetTransactionCount(from, DefaultBlockParameterName.LATEST).send()
.getTransactionCount();
BigInteger newPubkey1 = credential1.getEcKeyPair().getPublicKey();
BigInteger newPubkey2 = credential2.getEcKeyPair().getPublicKey();
BigInteger newPubkey3 = credential3.getEcKeyPair().getPublicKey();
AccountKeyPublic accountTransactionkey = AccountKeyPublic.create(newPubkey1);
AccountKeyPublic accountUpdateKey = AccountKeyPublic.create(newPubkey2);
AccountKeyPublic accountFeePayerKey = AccountKeyPublic.create(newPubkey3);
List<AccountKey> accountKeys = List.of(accountTransactionkey, accountUpdateKey, accountFeePayerKey);
AccountKeyRoleBased accountkey = AccountKeyRoleBased.create(accountKeys);
TxType.Type type = Type.ACCOUNT_UPDATE;
KlayRawTransaction raw = KlayRawTransaction.createTransaction(
type,
nonce,
GAS_PRICE,
GAS_LIMIT,
from,
accountkey);
byte[] signedMessage = KlayTransactionEncoder.signMessage(raw, chainId, credential2);
String hexValue = Numeric.toHexString(signedMessage);
EthSendTransaction transactionResponse = web3j.ethSendRawTransaction(hexValue).send();
System.out.println("TxHash : \n " + transactionResponse.getResult());
String txHash = transactionResponse.getResult();
int DEFAULT_POLLING_ATTEMPTS_PER_TX_HASH = 40;
int DEFAULT_BLOCK_TIME = 1 * 1000;
long DEFAULT_POLLING_FREQUENCY = DEFAULT_BLOCK_TIME;
TransactionReceiptProcessor transactionReceiptProcessor = new PollingTransactionReceiptProcessor(web3j,
DEFAULT_POLLING_FREQUENCY, DEFAULT_POLLING_ATTEMPTS_PER_TX_HASH);
org.web3j.protocol.core.methods.response.TransactionReceipt ethReceipt = transactionReceiptProcessor
.waitForTransactionReceipt(txHash);
System.out.println("Receipt from eth_getTransactionReceipt : \n" + ethReceipt);
TransactionReceipt receipt = web3j.klayGetTransactionReceipt(txHash).send().getResult();
System.out.println("Receipt from klay_getTransactionReceipt : \n" + receipt);
web3j.shutdown();
TxTypeAccountUpdate rawTransaction = TxTypeAccountUpdate.decodeFromRawTransaction(signedMessage);
System.out.println("TxType : " + rawTransaction.getKlayType());
}
}

output

❯ java AccountUpdateWithRoleBasedExample.java
TxHash :
0xefdaed1bdfdaa26b7f4512d2d3cf413735e3ed56d3510a7a9101d2cee1d0181c
Receipt from eth_getTransactionReceipt :
TransactionReceipt{transactionHash='0xefdaed1bdfdaa26b7f4512d2d3cf413735e3ed56d3510a7a9101d2cee1d0181c', transactionIndex='0x1', blockHash='0xaff11b719196dc64d161fabce82d74f0dc91f8d6d9aa0bcbb721f9006d0029f4', blockNumber='0x90e5932', cumulativeGasUsed='0x377d6', gasUsed='0x13c68', contractAddress='null', root='null', status='0x1', from='0x5bd2fb3c21564c023a4a735935a2b7a238c4ccea', to='0x5bd2fb3c21564c023a4a735935a2b7a238c4ccea', logs=[], logsBloom='0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000', revertReason='null', type='0x0', effectiveGasPrice='0x5d21dba00'}
Receipt from klay_getTransactionReceipt :
class TransactionReceipt {
blockHash: 0xaff11b719196dc64d161fabce82d74f0dc91f8d6d9aa0bcbb721f9006d0029f4
blockNumber: 0x90e5932
codeFormat: null
contractAddress: null
feePayer: null
feePayerSignatures: []
feeRatio: null
from: 0x5bd2fb3c21564c023a4a735935a2b7a238c4ccea
gas: 0x66919e
effectiveGasPrice: 0x5d21dba00
gasPrice: 0xba43b7400
gasUsed: 0x13c68
humanReadable: null
key: 0x05f86ca302a103f26489914098c5da51f0f646e3000da4d6197217df082b4f7ce1530f0a0cbf2aa302a10263021199702b9fefca617bdcb2a9ed4a810dfa8d270d4e804a1e778450e63ec3a302a103dc9dccbd788c00fa98f7f4082f2f714e799bc0c29d63f04d48b54fe6250453cd
input: null
logs: []
logsBloom: 0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
nonce: 0x3e
senderTxHash: 0xefdaed1bdfdaa26b7f4512d2d3cf413735e3ed56d3510a7a9101d2cee1d0181c
signature: []
status: 0x1
txError: null
to: null
transactionHash: 0xefdaed1bdfdaa26b7f4512d2d3cf413735e3ed56d3510a7a9101d2cee1d0181c
transactionIndex: 0x1
type: TxTypeAccountUpdate
typeInt: 32
value: null
}
TxType : ACCOUNT_UPDATE