Handling accounts
On this page, you’ll learn how to create a new account and how to fetch details of an account through a frontend.
On this page, you’ll learn:
-
How to create a new account through a UI.
-
How to fetch details of an account and display them on a UI.
The relevant files discussed in this guide are the newAccount.js and the getAccountDetails.js. |
1. Creating a new account
The newAccount.js
in the hello_frontend/src/components/ directory is specifically created to implement the account creation process.
The new accounts page will create a new account on a page load.
For that, we will use the passphrase
and cryptography
libraries of the klayr-client.
// [...]
// UI libraries import
import React, { useState, useEffect } from "react";
// Klayr libraries import
import { passphrase, cryptography } from '@klayr/client/browser';
function NewAccount() {
// State variables and function to store new account
const [accounts, createNewAccount] = useState('');
useEffect(() => {
createAccount()
}, [])
const createAccount = async () => {
// Default key path
const accountKeyPath = "m/44'/134'/0'";
// Randomly generated passphrase
const mnemonicPassphrase = passphrase.Mnemonic.generateMnemonic(256);
// Private key of new account
const privateKey = await cryptography.ed.getPrivateKeyFromPhraseAndPath(
mnemonicPassphrase,
accountKeyPath,
);
// Public key of new account
const publicKey = cryptography.ed.getPublicKeyFromPrivateKey(privateKey);
// Klayr32 address
const address = cryptography.address.getKlayr32AddressFromPublicKey(publicKey);
const credentials = {
address,
passphrase: mnemonicPassphrase,
privateKey: privateKey.toString('hex'),
publicKey: publicKey.toString('hex'),
};
createNewAccount(credentials);
return credentials;
};
// [...]
}
export default NewAccount;
The createAccount
function will generate a passphrase, a key pair (public and private), and a Klayr32 address of a new account by using the passphrase and cryptography libraries available in the klayr-client
package.
To display the credentials generated above, it will also be necessary to update the return
function.
// [...]
function NewAccount() {
// [...]
return (
<div>
<FixedMenuLayout />
<Container>
<div>
<div class="ui green segment">
<i class="lightbulb outline icon"></i><strong>TIP:</strong> Reload the page to generate a new account.
</div>
<h2>New account created!</h2>
<Divider></Divider>
<div className='App'>
<pre>{JSON.stringify(accounts, null, 2)}</pre>
</div>
</div>
</Container>
</div>
);
}
// [...]
Start the hello_frontend, and then click on the Account→Create Account option in the menu bar. Once the page has loaded, the credentials of the new account will be visible.
2. Getting account details
With a working account creation feature, let’s update the getAccountDetails.js
in the hello_frontend/src/components/ directory to support the fetching account details feature.
// [...]
// UI libraries import
import React, { useState } from "react";
// Import api.js
import * as api from '../api';
function GetAccountDetails() {
// State variables and function to store account details.
const [state, updateState] = useState({
address: '',
error: '',
account: {},
auth: {},
hello: {}
});
// Will get triggered when the value is changed in the input.
const handleChange = (event) => {
const { name, value } = event.target;
updateState({
...state,
[name]: value,
});
};
// Will get triggered on 'Submit'.
const handleSubmit = async (event) => {
event.preventDefault();
const client = await api.getClient();
let responseError = '';
let authenticationDetails;
let accountBalance;
let latestHello;
// Retrieves the account details from the blockchain, based on the provided address.
await client.invoke("token_getBalance", {
address: state.address,
tokenID: "0000000100000000" // It can be found in the genesis_assets.json file of the client.
}).then(async response => {
if (typeof response.error !== 'undefined') {
responseError = response.error.message
} else {
accountBalance = response;
const authDetails = await client.invoke("auth_getAuthAccount", {
address: state.address,
tokenID: "0000000100000000"
});
authenticationDetails = authDetails;
}
const helloMessage = await client.invoke("hello_getHello", {
address: state.address,
})
if (typeof helloMessage.message === 'string') {
latestHello = helloMessage;
}
else if (helloMessage.error.message.includes("does not exist")) {
latestHello = "message not found";
}
return [response, authenticationDetails, latestHello];
})
updateState({
...state,
error: responseError,
account: accountBalance,
auth: authenticationDetails,
hello: latestHello
});
};
// [...]
}
export default GetAccountDetails;
The handleSubmit
function will use the apiClient to invoke the token_getBalance
and auth_getAuthAccount
endpoints.
It will also invoke the hello_getHello
endpoint to fetch the latest hello message sent from the given address.
The response to these requests will be shown to the user with the displayData
function described in the following snippet:
// [...]
function GetAccountDetails() {
// [...]
const displayData = () => {
// If an error occurs, display the appropriate error.
if (state.error !== '') {
return (
<>
<div className="ui red segment" style={{ overflow: 'auto' }}>
<h3>Something went wrong! :(</h3>
<pre><strong>Error:</strong> {JSON.stringify(state.error, null, 2)}</pre>
</div>
</>
)
}
// If no hello message is found, only show account and auth details.
else if (state.hello === 'message not found') {
return (
<>
<h3>Your account details are:</h3>
<div className="ui green segment" style={{ overflow: 'auto' }}>
<pre>Account: {JSON.stringify(state.account, null, 2)}</pre>
<pre>Authentication details: {JSON.stringify(state.auth, null, 2)}</pre>
</div>
</>
)
}
// Check the values of the response received and display data accordingly.
else if (typeof state.account !== 'undefined' && state.account.availableBalance >= 0 && state.hello !== 'message not found') {
return (
<>
<h3>Your account details are:</h3>
<div className="ui green segment" style={{ overflow: 'auto' }}>
<pre>Account: {JSON.stringify(state.account, null, 2)}</pre>
<pre>Authentication details: {JSON.stringify(state.auth, null, 2)}</pre>
<pre>Latest Hello message: {JSON.stringify(state.hello, null, 2)}</pre>
</div>
</>
)
}
else {
return (<p></p>)
}
}
// [...]
}
// [...]
Finally, in the return
function, we will call the displayData
function to display the appropriate response.
// [...]
function GetAccountDetails() {
// [...]
return (
<div>
<FixedMenuLayout />
<Container>
<h2>Account details</h2>
<p>Get account details by submitting a Klayr32 address.</p>
<Divider></Divider>
<div className="ui two column doubling stackable grid container">
<div className="column">
<Form onSubmit={handleSubmit}>
<Form.Field>
<label>Klayr32 address:</label>
<input placeholder="Klayr32 address" id="address" name="address" onChange={handleChange} value={state.address} />
</Form.Field>
<Button type='submit' fluid size='large' style={{ backgroundColor: '#2BD67B', color: 'white' }}>Submit</Button>
</Form>
</div>
<div className='column'>
<>
{displayData()}
</>
</div>
</div>
</Container >
</div >
);
}
// [...]
Start the hello_client and ensure that the hello_frontend is running as well.
Create a new account using the Create Account page, copy the address, and open the Account→Account details page.
Paste the copied Klayr32 address and click on the Submit button. The UI will display the account details similar to the following snapshot:
In the case whereby an error occurs, it will be displayed in the UI, as in the displayData
function we have also implemented error handling.