@dfinity/pic
Version:
An Internet Computer Protocol canister testing library for TypeScript and JavaScript.
182 lines • 8.2 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.PocketIcClient = void 0;
const json_with_bigint_1 = require("json-with-bigint");
const http2_client_1 = require("./http2-client");
const pocket_ic_client_types_1 = require("./pocket-ic-client-types");
const util_1 = require("./util");
const PROCESSING_TIME_VALUE_MS = 30_000;
const AWAIT_INGRESS_STATUS_ROUNDS = 100;
class PocketIcClient {
serverClient;
instancePath;
ingressMaxRetries;
isInstanceDeleted = false;
constructor(serverClient, instancePath, ingressMaxRetries) {
this.serverClient = serverClient;
this.instancePath = instancePath;
this.ingressMaxRetries = ingressMaxRetries;
}
static async create(url, req) {
const processingTimeoutMs = req?.processingTimeoutMs ?? PROCESSING_TIME_VALUE_MS;
const serverClient = new http2_client_1.Http2Client(url, processingTimeoutMs);
const res = await serverClient.jsonPost({
path: '/instances',
body: (0, pocket_ic_client_types_1.encodeCreateInstanceRequest)(req),
});
if ('Error' in res) {
console.error('Error creating instance', res.Error.message);
throw new Error(res.Error.message);
}
const instanceId = res.Created.instance_id;
const ingressMaxRetries = req?.ingressMaxRetries ?? AWAIT_INGRESS_STATUS_ROUNDS;
return new PocketIcClient(serverClient, `/instances/${instanceId}`, ingressMaxRetries);
}
async deleteInstance() {
this.assertInstanceNotDeleted();
await this.serverClient.request({
method: 'DELETE',
path: this.instancePath,
});
this.isInstanceDeleted = true;
}
async getControllers(req) {
this.assertInstanceNotDeleted();
const res = await this.post('/read/get_controllers', (0, pocket_ic_client_types_1.encodeGetControllersRequest)(req));
return (0, pocket_ic_client_types_1.decodeGetControllersResponse)(res);
}
async tick() {
this.assertInstanceNotDeleted();
return await this.post('/update/tick', {});
}
async getPubKey(req) {
this.assertInstanceNotDeleted();
return await this.post('/read/pub_key', (0, pocket_ic_client_types_1.encodeGetPubKeyRequest)(req));
}
async getTopology() {
this.assertInstanceNotDeleted();
const res = await this.get('/_/topology');
return (0, pocket_ic_client_types_1.decodeGetTopologyResponse)(res);
}
async getDefaultEffectiveCanisterId() {
this.assertInstanceNotDeleted();
const res = await this.get('/_/topology');
return (0, util_1.base64DecodePrincipal)(res.default_effective_canister_id.canister_id);
}
async getTime() {
this.assertInstanceNotDeleted();
const res = await this.get('/read/get_time', json_with_bigint_1.JSONParse);
return (0, pocket_ic_client_types_1.decodeGetTimeResponse)(res);
}
async setTime(req) {
this.assertInstanceNotDeleted();
await this.post('/update/set_time', (0, pocket_ic_client_types_1.encodeSetTimeRequest)(req));
}
async setCertifiedTime(req) {
this.assertInstanceNotDeleted();
await this.post('/update/set_certified_time', (0, pocket_ic_client_types_1.encodeSetTimeRequest)(req));
}
async getSubnetId(req) {
this.assertInstanceNotDeleted();
const res = await this.post('/read/get_subnet', (0, pocket_ic_client_types_1.encodeGetSubnetIdRequest)(req));
return (0, pocket_ic_client_types_1.decodeGetSubnetIdResponse)(res);
}
async getCyclesBalance(req) {
this.assertInstanceNotDeleted();
const res = await this.post('/read/get_cycles', (0, pocket_ic_client_types_1.encodeGetCyclesBalanceRequest)(req), json_with_bigint_1.JSONParse);
return (0, pocket_ic_client_types_1.decodeGetCyclesBalanceResponse)(res);
}
async addCycles(req) {
this.assertInstanceNotDeleted();
const res = await this.post('/update/add_cycles', (0, pocket_ic_client_types_1.encodeAddCyclesRequest)(req), json_with_bigint_1.JSONParse);
return (0, pocket_ic_client_types_1.decodeAddCyclesResponse)(res);
}
async uploadBlob(req) {
this.assertInstanceNotDeleted();
const res = await this.serverClient.request({
method: 'POST',
path: '/blobstore',
body: (0, pocket_ic_client_types_1.encodeUploadBlobRequest)(req),
});
const body = await res.text();
return (0, pocket_ic_client_types_1.decodeUploadBlobResponse)(body);
}
async setStableMemory(req) {
this.assertInstanceNotDeleted();
await this.serverClient.jsonPost({
path: `${this.instancePath}/update/set_stable_memory`,
body: (0, pocket_ic_client_types_1.encodeSetStableMemoryRequest)(req),
});
}
async getStableMemory(req) {
this.assertInstanceNotDeleted();
const res = await this.post('/read/get_stable_memory', (0, pocket_ic_client_types_1.encodeGetStableMemoryRequest)(req));
return (0, pocket_ic_client_types_1.decodeGetStableMemoryResponse)(res);
}
async getPendingHttpsOutcalls() {
this.assertInstanceNotDeleted();
const res = await this.get('/read/get_canister_http');
return (0, pocket_ic_client_types_1.decodeGetPendingHttpsOutcallsResponse)(res);
}
async mockPendingHttpsOutcall(req) {
this.assertInstanceNotDeleted();
await this.post('/update/mock_canister_http', (0, pocket_ic_client_types_1.encodeMockPendingHttpsOutcallRequest)(req));
}
async updateCall(req) {
this.assertInstanceNotDeleted();
const res = await this.submitCall(req);
return await this.awaitCall(res);
}
async queryCall(req) {
this.assertInstanceNotDeleted();
const res = await this.post('/read/query', (0, pocket_ic_client_types_1.encodeCanisterCallRequest)(req));
return (0, pocket_ic_client_types_1.decodeCanisterCallResponse)(res);
}
async submitCall(req) {
this.assertInstanceNotDeleted();
const res = await this.post('/update/submit_ingress_message', (0, pocket_ic_client_types_1.encodeSubmitCanisterCallRequest)(req));
return (0, pocket_ic_client_types_1.decodeSubmitCanisterCallResponse)(res);
}
async ingressStatus(req) {
this.assertInstanceNotDeleted();
const res = await this.post('/read/ingress_status', (0, pocket_ic_client_types_1.encodeIngressStatusRequest)(req));
return (0, pocket_ic_client_types_1.decodeIngressStatusResponse)(res);
}
async awaitCall(req) {
this.assertInstanceNotDeleted();
const encodedReq = {
messageId: (0, pocket_ic_client_types_1.encodeAwaitCanisterCallRequest)(req),
// since this is always called immediately after making a call, there is no need to check the caller
// the `ingressStatus` method is not exposed publicly, so it is safe to assume that the caller is the same as the one who made the call
caller: undefined,
};
for (let i = 0; i < this.ingressMaxRetries; i++) {
await this.tick();
const result = await this.ingressStatus(encodedReq);
if ((0, util_1.isNotNil)(result)) {
return result;
}
}
throw new Error(`PocketIC did not complete the update call within ${this.ingressMaxRetries} rounds`);
}
async post(endpoint, body, responseJsonParser) {
return await this.serverClient.jsonPost({
path: `${this.instancePath}${endpoint}`,
body,
responseJsonParser,
});
}
async get(endpoint, responseJsonParser) {
return await this.serverClient.jsonGet({
path: `${this.instancePath}${endpoint}`,
responseJsonParser,
});
}
assertInstanceNotDeleted() {
if (this.isInstanceDeleted) {
throw new Error('Instance was deleted');
}
}
}
exports.PocketIcClient = PocketIcClient;
//# sourceMappingURL=pocket-ic-client.js.map