RPC Client

Most of the interactions with Substrate network is made through RPC interface.

Basic RPC interface is declared this way:

public protocol Rpc: AnyObject {
    func send<Request: Encodable, Response: Decodable>(
        _ rpcRequest: RpcRequest<Request>,
        completion: @escaping (RpcResponse<Response>?, RpcError?) -> Void
    )
    
    func send<Request: Encodable, Response: Decodable>(
        _ rpcRequest: RpcRequest<Request>
    ) async throws -> RpcResponse<Response>
    
    func sendRequest<Request: Encodable, Response: Decodable>(
        _ request: Request,
        method: String,
        completion: @escaping (Response?, RpcError?) -> Void
    )
    
    func sendRequest<Request: Encodable, Response: Decodable>(
        _ request: Request,
        method: String
    ) async throws -> Response?
    
    func sendRequest<Response: Decodable>(
        method: String,
        completion: @escaping (Response?, RpcError?) -> Void
    )
    
    func sendRequest<Response: Decodable>(
        method: String
    ) async throws -> Response?
}

So, basically all you can do is send and recieve requests.

Requests can be sent in 3 ways:

1. Using RpcRequest generic struct, which looks like that:

public struct RpcRequest<T: Encodable>: Encodable {
    public var jsonrpc = "2.0"
    public var id: Int32
    public var method: String
    public var params: T
}

Here is how one can create an RpcRequest:

let request = RpcRequest(
    id: 0,
    method: "non_existing_method",
    params: Nothing()
)

Nothing here is an empty struct representing nothing, used in RPC client for empty requests or responses:

public struct Nothing: Codable {}

2. By creating a custom Encodable request and providing the required method's name:

func sendRequest<Request: Encodable, Response: Decodable>(
        _ request: Request,
        method: String,
        completion: @escaping (Response?, RpcError?) -> Void
)

3. By providing only the required method's name:

func sendRequest<Response: Decodable>(
        method: String
) async throws -> Response?

Results can be recieved via closures or async-await interface:

func sendRequest<Request: Encodable, Response: Decodable>(
    _ request: Request,
    method: String,
    completion: @escaping (Response?, RpcError?) -> Void
)

func sendRequest<Request: Encodable, Response: Decodable>(
    _ request: Request,
    method: String
) async throws -> Response?    

Last updated