@metamask/kernel-rpc-methods
Version:
Utilities for implementing Ocap Kernel JSON-RPC methods
132 lines • 7.27 kB
JavaScript
var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (receiver, state, value, kind, f) {
if (kind === "m") throw new TypeError("Private method is not writable");
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter");
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it");
return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;
};
var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) {
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
};
var _RpcClient_instances, _RpcClient_methods, _RpcClient_prefix, _RpcClient_unresolvedMessages, _RpcClient_messageCounter, _RpcClient_sendMessage, _RpcClient_logger, _RpcClient_call, _RpcClient_assertResult, _RpcClient_createMessage, _RpcClient_nextMessageId;
import { makePromiseKit } from "@endo/promise-kit";
import { makeCounter, stringify } from "@metamask/kernel-utils";
import { Logger } from "@metamask/logger";
import { assert as assertStruct } from "@metamask/superstruct";
import { isJsonRpcFailure, isJsonRpcSuccess } from "@metamask/utils";
export class RpcClient {
constructor(methods, sendMessage, prefix, logger = new Logger('rpc-client')) {
_RpcClient_instances.add(this);
_RpcClient_methods.set(this, void 0);
_RpcClient_prefix.set(this, void 0);
_RpcClient_unresolvedMessages.set(this, new Map());
_RpcClient_messageCounter.set(this, makeCounter());
_RpcClient_sendMessage.set(this, void 0);
_RpcClient_logger.set(this, void 0);
__classPrivateFieldSet(this, _RpcClient_methods, methods, "f");
__classPrivateFieldSet(this, _RpcClient_sendMessage, sendMessage, "f");
__classPrivateFieldSet(this, _RpcClient_prefix, prefix, "f");
__classPrivateFieldSet(this, _RpcClient_logger, logger, "f");
}
/**
* Calls a JSON-RPC method and returns the result.
*
* @param method - The method to call.
* @param params - The parameters to pass to the method.
* @returns A promise that resolves to the result.
*/
async call(method, params) {
return await __classPrivateFieldGet(this, _RpcClient_instances, "m", _RpcClient_call).call(this, method, params, __classPrivateFieldGet(this, _RpcClient_instances, "m", _RpcClient_nextMessageId).call(this));
}
/**
* Sends a JSON-RPC notification. Recall that we do not receive responses to notifications
* for any reason.
*
* @param method - The method to notify.
* @param params - The parameters to pass to the method.
*/
async notify(method, params) {
await __classPrivateFieldGet(this, _RpcClient_sendMessage, "f").call(this, {
jsonrpc: '2.0',
method,
params,
}).catch((error) => __classPrivateFieldGet(this, _RpcClient_logger, "f").error(`Failed to send notification`, error));
}
/**
* Calls a JSON-RPC method and returns the message id and the result.
*
* @param method - The method to call.
* @param params - The parameters to pass to the method.
* @returns A promise that resolves to a tuple of the message id and the result.
*/
async callAndGetId(method, params) {
const id = __classPrivateFieldGet(this, _RpcClient_instances, "m", _RpcClient_nextMessageId).call(this);
return [id, await __classPrivateFieldGet(this, _RpcClient_instances, "m", _RpcClient_call).call(this, method, params, id)];
}
/**
* Handles a JSON-RPC response to a previously made method call.
*
* @param messageId - The id of the message to handle.
* @param response - The response to handle.
*/
handleResponse(messageId, response) {
const requestCallbacks = __classPrivateFieldGet(this, _RpcClient_unresolvedMessages, "f").get(messageId);
if (requestCallbacks === undefined) {
__classPrivateFieldGet(this, _RpcClient_logger, "f").debug(`Received response with unexpected id "${messageId}".`);
}
else {
__classPrivateFieldGet(this, _RpcClient_unresolvedMessages, "f").delete(messageId);
if (isJsonRpcSuccess(response)) {
requestCallbacks.resolve(response);
}
else if (isJsonRpcFailure(response)) {
requestCallbacks.reject(response.error);
}
else {
requestCallbacks.reject(new Error(`Invalid JSON-RPC response: ${stringify(response)}`));
}
}
}
/**
* Rejects all unresolved messages with an error.
*
* @param error - The error to reject the messages with.
*/
rejectAll(error) {
for (const [messageId, promiseCallback] of __classPrivateFieldGet(this, _RpcClient_unresolvedMessages, "f")) {
promiseCallback?.reject(error);
__classPrivateFieldGet(this, _RpcClient_unresolvedMessages, "f").delete(messageId);
}
}
}
_RpcClient_methods = new WeakMap(), _RpcClient_prefix = new WeakMap(), _RpcClient_unresolvedMessages = new WeakMap(), _RpcClient_messageCounter = new WeakMap(), _RpcClient_sendMessage = new WeakMap(), _RpcClient_logger = new WeakMap(), _RpcClient_instances = new WeakSet(), _RpcClient_call = async function _RpcClient_call(method, params, id) {
const response = await __classPrivateFieldGet(this, _RpcClient_instances, "m", _RpcClient_createMessage).call(this, id, {
id,
jsonrpc: '2.0',
method,
params,
});
__classPrivateFieldGet(this, _RpcClient_instances, "m", _RpcClient_assertResult).call(this, method, response.result);
return response.result;
}, _RpcClient_assertResult = function _RpcClient_assertResult(method, result) {
try {
// @ts-expect-error: For unknown reasons, TypeScript fails to recognize that
// `Method` must be a key of `this.#methods`.
assertStruct(result, __classPrivateFieldGet(this, _RpcClient_methods, "f")[method].result);
}
catch (error) {
throw new Error(`Invalid result: ${error.message}`);
}
}, _RpcClient_createMessage = async function _RpcClient_createMessage(messageId, payload) {
const { promise, reject, resolve } = makePromiseKit();
__classPrivateFieldGet(this, _RpcClient_unresolvedMessages, "f").set(messageId, {
resolve: resolve,
reject,
});
await __classPrivateFieldGet(this, _RpcClient_sendMessage, "f").call(this, payload);
return promise;
}, _RpcClient_nextMessageId = function _RpcClient_nextMessageId() {
return `${__classPrivateFieldGet(this, _RpcClient_prefix, "f")}${__classPrivateFieldGet(this, _RpcClient_messageCounter, "f").call(this)}`;
};
//# sourceMappingURL=RpcClient.mjs.map