-
Notifications
You must be signed in to change notification settings - Fork 10
Rpc
This component contains known RPC sections and their methods that are available for Remote Calls to the node by default. Currently not all of them are implemented.
Also this component provides tools for defining such a section. These tools help to generate code for calling RPC methods or subscribing to them. This approach reduces the boilerplate code.
The Rpc
interface represents known sections. Each one of them contains proper RPC methods and subscriptions. Sections that are not included in this interface can be defined manually.
For all interfaces annotated with RpcInterface
the processor will generate the appropriate implementation.
Example of a section:
@RpcInterface("chain")
public interface Chain {
@RpcCall("getFinalizedHead")
@Scale
CompletableFuture<BlockHash> getFinalizedHead();
@RpcSubscription(type = "newHead", subscribeMethod = "subscribeNewHead", unsubscribeMethod = "unsubscribeNewHead")
CompletableFuture<Supplier<CompletableFuture<Boolean>>> subscribeNewHeads(BiConsumer<Exception, Header> callback);
@RpcCall("getBlockHash")
@Scale
CompletableFuture<BlockHash> getBlockHash(long number);
@RpcCall("getBlock")
CompletableFuture<SignedBlock> getBlock(@Scale BlockHash hash);
}
Where:
-
RpcInterface
indicates an RPC section and itsvalue()
is the name of the section; -
RpcCall
indicates the RPC method and itsvalue()
is the name of the method; -
RpcSubscription
indicates the RPC subscription:-
type()
is the type of the subscription; -
subscribeMethod
- the name of the method to subscribe; -
unsubscribeMethod
- the name of the method to unsubscribe.
-
Parameters of RPC methods or subscriptions including the return parameters are encoded/decoded to/from SCALE (if they are annotated properly) or encoded/decoded to/from RpcObject
.
RpcGeneratedSectionFactory
allows to create an instance of a section. The RpcGeneratedSectionFactory.create
method requires the class of the section and an instance of the ProviderInterface
.
Example:
try (WsProvider wsProvider = WsProvider.builder()
.setEndpoint("ws://127.0.0.1:9944")
.build()) {
wsProvider.connect().join();
Chain chainSection = RpcGeneratedSectionFactory.create(Chain.class, wsProvider);
}
When a client communicates with the node, it encodes/decodes DTOs to/from RpcObject
s. Proper encoders/decoders (RpcEncoder
and RpcDecoder
) must be put into RpcEncoderRegistry
and RpcDecoderRegistry
respectively.
Standard types have decoders/encoders which are already registered.
The RpcEncoder
and RpcDecoder
annotations generate proper encoders/decoders for the entities and put them into registries. Annotated entities will be (de-)serialized from/to JSON. The code generation processor will go through each field and find the appropriate encoder/decoder for it (by its type) in the registry or will consider the Scale
annotation that represents the field as SCALE.
Example:
@RpcDecoder
@NoArgsConstructor
@Getter
@Setter
public class StorageChangeSet {
@Scale
private BlockHash block;
private List<Pair<StorageKey, StorageData>> changes;
}
The RpcEncoder
and RpcDecoder
can also be implemented manually. The annotation AutoRegister
makes possible to register an encoder/decoder in the registry and it to be resolvable by the types()
specified.