@slide-computer/signer-web
Version:
JavaScript and TypeScript library to communicate with web signers on the Internet Computer
170 lines • 8.58 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 _AgentChannel_instances, _AgentChannel_agent, _AgentChannel_closeListeners, _AgentChannel_responseListeners, _AgentChannel_closed, _AgentChannel_createResponse;
import { fromBase64, INVALID_REQUEST_ERROR, isJsonRpcRequest, NOT_SUPPORTED_ERROR, toBase64, } from "@slide-computer/signer";
import { AgentTransportError } from "./agentTransport";
import { scopes, supportedStandards } from "./constants";
import { DelegationChain, DelegationIdentity } from "@dfinity/identity";
import { Cbor, HttpAgent, polling } from "@dfinity/agent";
import { Principal } from "@dfinity/principal";
export class AgentChannel {
constructor(agent) {
_AgentChannel_instances.add(this);
_AgentChannel_agent.set(this, void 0);
_AgentChannel_closeListeners.set(this, new Set());
_AgentChannel_responseListeners.set(this, new Set());
_AgentChannel_closed.set(this, false);
__classPrivateFieldSet(this, _AgentChannel_agent, agent, "f");
}
get closed() {
return __classPrivateFieldGet(this, _AgentChannel_closed, "f");
}
addEventListener(...[event, listener]) {
switch (event) {
case "close":
__classPrivateFieldGet(this, _AgentChannel_closeListeners, "f").add(listener);
return () => {
__classPrivateFieldGet(this, _AgentChannel_closeListeners, "f").delete(listener);
};
case "response":
__classPrivateFieldGet(this, _AgentChannel_responseListeners, "f").add(listener);
return () => {
__classPrivateFieldGet(this, _AgentChannel_responseListeners, "f").delete(listener);
};
}
}
async send(request) {
if (this.closed) {
throw new AgentTransportError("Communication channel is closed");
}
// Ignore one way messages
const id = request.id;
if (id === undefined) {
return;
}
// Create response and call listeners
const response = await __classPrivateFieldGet(this, _AgentChannel_instances, "m", _AgentChannel_createResponse).call(this, Object.assign({ id }, request));
__classPrivateFieldGet(this, _AgentChannel_responseListeners, "f").forEach((listener) => listener(response));
}
async close() {
__classPrivateFieldSet(this, _AgentChannel_closed, true, "f");
__classPrivateFieldGet(this, _AgentChannel_closeListeners, "f").forEach((listener) => listener());
}
}
_AgentChannel_agent = new WeakMap(), _AgentChannel_closeListeners = new WeakMap(), _AgentChannel_responseListeners = new WeakMap(), _AgentChannel_closed = new WeakMap(), _AgentChannel_instances = new WeakSet(), _AgentChannel_createResponse = async function _AgentChannel_createResponse(request) {
var _a, _b;
const id = request.id;
if (!isJsonRpcRequest(request)) {
return {
id,
jsonrpc: "2.0",
error: { code: INVALID_REQUEST_ERROR, message: "Invalid request" },
};
}
switch (request.method) {
case "icrc25_supported_standards":
return {
id,
jsonrpc: "2.0",
result: { supportedStandards },
};
case "icrc25_permissions":
case "icrc25_request_permissions":
return {
id,
jsonrpc: "2.0",
result: { scopes },
};
case "icrc27_accounts":
const owner = (await __classPrivateFieldGet(this, _AgentChannel_agent, "f").getPrincipal()).toText();
return {
id,
jsonrpc: "2.0",
result: {
accounts: [{ owner }],
},
};
case "icrc34_delegation":
const delegationRequest = request;
const identity = __classPrivateFieldGet(this, _AgentChannel_agent, "f").config.identity;
const delegationChain = identity instanceof DelegationIdentity
? identity.getDelegation()
: undefined;
const expiration = new Date(Date.now() +
Number(delegationRequest.params.maxTimeToLive
? BigInt(delegationRequest.params.maxTimeToLive) /
BigInt(1000000)
: BigInt(8) * BigInt(3600000)));
const signedDelegationChain = await DelegationChain.create(identity, { toDer: () => fromBase64(delegationRequest.params.publicKey) }, expiration, {
previous: delegationChain,
targets: (_a = delegationRequest.params.targets) === null || _a === void 0 ? void 0 : _a.map((target) => Principal.fromText(target)),
});
return {
id,
jsonrpc: "2.0",
result: {
publicKey: toBase64(signedDelegationChain.publicKey),
signerDelegation: signedDelegationChain.delegations.map(({ delegation, signature }) => ({
delegation: Object.assign({ pubkey: toBase64(delegation.pubkey), expiration: delegation.expiration.toString() }, (delegation.targets
? {
targets: delegation.targets.map((target) => target.toText()),
}
: {})),
signature: toBase64(signature),
})),
},
};
case "icrc49_call_canister":
const callCanisterRequest = request;
const { pollForResponse, defaultStrategy } = polling;
const canisterId = Principal.fromText(callCanisterRequest.params.canisterId);
if (((_b = callCanisterRequest.params) === null || _b === void 0 ? void 0 : _b.sender) !==
__classPrivateFieldGet(this, _AgentChannel_agent, "f").getPrincipal().toString()) {
throw new AgentTransportError("Sender does not match Agent identity");
}
const agent = await HttpAgent.from(__classPrivateFieldGet(this, _AgentChannel_agent, "f"));
let contentMap;
agent.addTransform("update", async (agentRequest) => {
contentMap = Cbor.encode(agentRequest.body);
return agentRequest;
});
const submitResponse = await agent.call(canisterId, {
effectiveCanisterId: canisterId,
methodName: callCanisterRequest.params.method,
arg: fromBase64(callCanisterRequest.params.arg),
});
await pollForResponse(agent, canisterId, submitResponse.requestId, defaultStrategy());
const { certificate } = await agent.readState(canisterId, {
paths: [
[
new TextEncoder().encode("request_status"),
submitResponse.requestId,
],
],
});
return {
id,
jsonrpc: "2.0",
result: {
contentMap: toBase64(contentMap),
certificate: toBase64(certificate),
},
};
default:
return {
id,
jsonrpc: "2.0",
error: { code: NOT_SUPPORTED_ERROR, message: "Not supported" },
};
}
};
//# sourceMappingURL=agentChannel.js.map