How to create endpoints and methods
On this page, you’ll learn how to:
-
Create endpoints for a module
-
Create a method for a module
-
Request endpoints of a module
Modules introduce new data structures and manage their state changes on the blockchain. But by default, all data in the module stores is only accessible through the respective module itself. So how can other external services/tools access the data? For this, a module needs to provide dedicated Endpoints.
Modules can get data from other module stores via Methods, similar to Endpoints.
Moreover, methods also allow other modules to introduce state changes to the stores of another module.
For example, the Token module includes the transfer
method, that can be used by other modules to transfer tokens from one account to another.
1. Endpoints
For the Hello module, we want to implement the following two endpoints:
-
Two RPC endpoints:
-
hello_getHello
: Returns the Hello message of an account. Expects accountaddress
as parameter -
hello_getHelloCounter
: Returns the counter of total Hello messages sent in the network. Doesn’t expect any parameters.
-
All endpoints for the module are defined in the file endpoint.ts
inside the root folder of the module.
Initially, the modules don’t include any endpoints:
import { Modules } from 'klayr-sdk';
export class HelloEndpoint extends Modules.BaseEndpoint {
}
1.1. Get a Hello message by address
To create the endpoint for getting a Hello message by address, import the following libraries and classes:
-
ModuleEndpointContext
: Each endpoint typically has one parameter of typeModuleEndpointContext
. -
cryptography
: to validate the address and convert the address format. -
MessageStore
&MessageStoreData
: The message store which was created in the How to create stores guide.
import { cryptography, Modules, Types } from 'klayr-sdk';
import { MessageStore, MessageStoreData } from './stores/message';
export class HelloEndpoint extends Modules.BaseEndpoint {
public async getHello(ctx: Types.ModuleEndpointContext): Promise<MessageStoreData> {
// 1. Get message store
const messageSubStore = this.stores.get(MessageStore);
// 2. Get the address from the endpoint params
const { address } = ctx.params;
// 3. Validate address
if (typeof address !== 'string') {
throw new Error('Parameter address must be a string.');
}
cryptography.address.validateKlayr32Address(address);
// 4. Get the Hello message for the address from the message store
const helloMessage = await messageSubStore.get(
ctx,
cryptography.address.getAddressFromKlayr32Address(address),
);
// 5. Return the Hello message
return helloMessage;
}
}
1.2. Get Hello counter
To create the endpoint for getting the Hello counter, import the following:
-
CounterStore
&CounterStoreData
: The counter store which was created in the How to create stores guide.
import { cryptography, Modules, Types } from 'klayr-sdk';
import { MessageStore, MessageStoreData } from './stores/message';
import { counterKey, CounterStore, CounterStoreData } from './stores/counter';
export class HelloEndpoint extends Modules.BaseEndpoint {
public async getHello(ctx: Types.ModuleEndpointContext): Promise<MessageStoreData> {
// [...]
}
public async getHelloCounter(ctx: Types.ModuleEndpointContext): Promise<CounterStoreData> {
const counterSubStore = this.stores.get(CounterStore);
const helloCounter = await counterSubStore.get(
ctx,
counterKey,
);
return helloCounter;
}
}
2. Methods
For the Hello module, we implement the following method:
-
hello_getHello
: Works equally to the corresponding endpoint, but can be used by other modules.
All methods for the module are defined in the file method.ts
inside the root folder of the module.
Initially, the modules don’t include any methods:
import { Modules } from 'klayr-sdk';
export class HelloMethod extends Modules.BaseMethod {
}
2.1. Get a Hello message by address
To create the endpoint for getting a Hello message by address, import the following:
-
MessageStore
&MessageStoreData
: The message store which was created in the How to create stores guide. -
ImmutableMethodContext
from theklayr-sdk
package.
import { Modules, StateMachine } from 'klayr-sdk';
import { MessageStore, MessageStoreData } from './stores/message';
export class HelloMethod extends Modules.BaseMethod {
public async getHello(
methodContext: StateMachine.ImmutableMethodContext,
address: Buffer,
): Promise<MessageStoreData> {
// 1. Get message store
const messageSubStore = this.stores.get(MessageStore);
// 2. Get the Hello message for the address from the message store
const helloMessage = await messageSubStore.get(methodContext, address);
// 3. Return the Hello message
return helloMessage;
}
}
3. Add endpoint schemas to the module metadata
Don’t forget to update the module metadata with information about the newly created module endpoints. This information will be used by Klayr Service and similar software, to fetch information about the available API endpoints of the blockchain client.
First, import the related schemas into module.ts
:
import {
configSchema,
getHelloRequestSchema,
getHelloCounterResponseSchema,
getHelloResponseSchema,
} from './schema';
Then update the metadata
of the module as follows:
public metadata(): Modules.ModuleMetadata {
return {
endpoints: [
{
name: this.endpoint.getHello.name,
request: getHelloRequestSchema,
response: getHelloResponseSchema,
},
{
name: this.endpoint.getHelloCounter.name,
response: getHelloCounterResponseSchema,
},
],
commands: this.commands.map(command => ({
name: command.name,
params: command.schema,
})),
events: this.events.values().map(v => ({
name: v.name,
data: v.schema,
})),
assets: [],
stores: [],
};
}
4. Requesting data from the module
-
Rebuild the client:
npm run build
-
Start the client:
./bin/run start --config=config/custom_config.json
-
Send at least one "Create Hello" transaction to the node, as explained in How to create a command → Try the new command out
-
Sent RPC requests
-
hello_getHello
./bin/run endpoint:invoke hello_getHello '{"address": "klyuz5p98kz3mqzxnu68qdrjxtvdvr2o7pprtj4yv"}'
When the request is successful, the node will reply with the following:
{"message": "Hello Klayr SDKv6!"}
-
hello_getHelloCounter
./bin/run endpoint:invoke hello_getHelloCounter
When the request is successful, the node will return the current counter value:
{"counter": 1}
-