UNPKG

pic-js-mops

Version:

An Internet Computer Protocol canister testing library for TypeScript and JavaScript.

167 lines 7.27 kB
import { Http2Client } from './http2-client.js'; import { decodeGetTopologyResponse, encodeGetStableMemoryRequest, decodeGetStableMemoryResponse, encodeSetStableMemoryRequest, encodeAddCyclesRequest, decodeAddCyclesResponse, decodeGetCyclesBalanceResponse, encodeGetCyclesBalanceRequest, encodeGetSubnetIdRequest, decodeGetSubnetIdResponse, decodeGetTimeResponse, encodeSetTimeRequest, encodeCanisterCallRequest, decodeUploadBlobResponse, encodeUploadBlobRequest, encodeCreateInstanceRequest, encodeGetPubKeyRequest, decodeCanisterCallResponse, decodeGetPendingHttpsOutcallsResponse, encodeMockPendingHttpsOutcallRequest, decodeSubmitCanisterCallResponse, encodeSubmitCanisterCallRequest, encodeIngressStatusRequest, decodeIngressStatusResponse, encodeAwaitCanisterCallRequest, decodeGetControllersResponse, encodeGetControllersRequest, } from './pocket-ic-client-types.js'; import { isNotNil } from './util/index.js'; const PROCESSING_TIME_VALUE_MS = 30_000; const AWAIT_INGRESS_STATUS_ROUNDS = 100; export class PocketIcClient { serverClient; instancePath; isInstanceDeleted = false; constructor(serverClient, instancePath) { this.serverClient = serverClient; this.instancePath = instancePath; } static async create(url, req) { const processingTimeoutMs = req?.processingTimeoutMs ?? PROCESSING_TIME_VALUE_MS; const serverClient = new Http2Client(url, processingTimeoutMs); const res = await serverClient.jsonPost({ path: '/instances', body: 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; return new PocketIcClient(serverClient, `/instances/${instanceId}`); } 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', encodeGetControllersRequest(req)); return decodeGetControllersResponse(res); } async tick() { this.assertInstanceNotDeleted(); return await this.post('/update/tick', {}); } async getPubKey(req) { this.assertInstanceNotDeleted(); return await this.post('/read/pub_key', encodeGetPubKeyRequest(req)); } async getTopology() { this.assertInstanceNotDeleted(); const res = await this.get('/_/topology'); return decodeGetTopologyResponse(res); } async getTime() { this.assertInstanceNotDeleted(); const res = await this.get('/read/get_time'); return decodeGetTimeResponse(res); } async setTime(req) { this.assertInstanceNotDeleted(); await this.post('/update/set_time', encodeSetTimeRequest(req)); } async setCertifiedTime(req) { this.assertInstanceNotDeleted(); await this.post('/update/set_certified_time', encodeSetTimeRequest(req)); } async getSubnetId(req) { this.assertInstanceNotDeleted(); const res = await this.post('/read/get_subnet', encodeGetSubnetIdRequest(req)); return decodeGetSubnetIdResponse(res); } async getCyclesBalance(req) { this.assertInstanceNotDeleted(); const res = await this.post('/read/get_cycles', encodeGetCyclesBalanceRequest(req)); return decodeGetCyclesBalanceResponse(res); } async addCycles(req) { this.assertInstanceNotDeleted(); const res = await this.post('/update/add_cycles', encodeAddCyclesRequest(req)); return decodeAddCyclesResponse(res); } async uploadBlob(req) { this.assertInstanceNotDeleted(); const res = await this.serverClient.request({ method: 'POST', path: '/blobstore', body: encodeUploadBlobRequest(req), }); const body = await res.text(); return decodeUploadBlobResponse(body); } async setStableMemory(req) { this.assertInstanceNotDeleted(); await this.serverClient.jsonPost({ path: `${this.instancePath}/update/set_stable_memory`, body: encodeSetStableMemoryRequest(req), }); } async getStableMemory(req) { this.assertInstanceNotDeleted(); const res = await this.post('/read/get_stable_memory', encodeGetStableMemoryRequest(req)); return decodeGetStableMemoryResponse(res); } async getPendingHttpsOutcalls() { this.assertInstanceNotDeleted(); const res = await this.get('/read/get_canister_http'); return decodeGetPendingHttpsOutcallsResponse(res); } async mockPendingHttpsOutcall(req) { this.assertInstanceNotDeleted(); await this.post('/update/mock_canister_http', 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', encodeCanisterCallRequest(req)); return decodeCanisterCallResponse(res); } async submitCall(req) { this.assertInstanceNotDeleted(); const res = await this.post('/update/submit_ingress_message', encodeSubmitCanisterCallRequest(req)); return decodeSubmitCanisterCallResponse(res); } async ingressStatus(req) { this.assertInstanceNotDeleted(); const res = await this.post('/read/ingress_status', encodeIngressStatusRequest(req)); return decodeIngressStatusResponse(res); } async awaitCall(req) { this.assertInstanceNotDeleted(); const encodedReq = { messageId: 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 < AWAIT_INGRESS_STATUS_ROUNDS; i++) { await this.tick(); const result = await this.ingressStatus(encodedReq); if (isNotNil(result)) { return result; } } throw new Error(`PocketIC did not complete the update call within ${AWAIT_INGRESS_STATUS_ROUNDS} rounds`); } async post(endpoint, body) { return await this.serverClient.jsonPost({ path: `${this.instancePath}${endpoint}`, body, }); } async get(endpoint) { return await this.serverClient.jsonGet({ path: `${this.instancePath}${endpoint}`, }); } assertInstanceNotDeleted() { if (this.isInstanceDeleted) { throw new Error('Instance was deleted'); } } } //# sourceMappingURL=pocket-ic-client.js.map