Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

@dfinity/agent

Package Overview
Dependencies
Maintainers
10
Versions
123
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@dfinity/agent - npm Package Compare versions

Comparing version 2.0.1-beta.0 to 2.1.0

lib/cjs/agent/http/calculateReplicaTime.d.ts

43

lib/cjs/actor.js

@@ -14,2 +14,3 @@ "use strict";

const buffer_2 = require("./utils/buffer");
const certificate_1 = require("./certificate");
const management_idl_1 = __importDefault(require("./canisters/management_idl"));

@@ -243,2 +244,4 @@ class ActorCallError extends errors_1.AgentError {

const arg = candid_1.IDL.encode(func.argTypes, args);
if (agent.rootKey == null)
throw new errors_1.AgentError('Agent root key not initialized before making call');
const { requestId, response, requestDetails } = await agent.call(cid, {

@@ -249,12 +252,34 @@ methodName,

});
requestId;
response;
requestDetails;
if (!response.ok || response.body /* IC-1462 */) {
throw new UpdateCallRejectedError(cid, methodName, requestId, response);
let reply;
let certificate;
const certTime = agent.replicaTime
? agent.replicaTime
: undefined;
certTime;
if (response.body && response.body.certificate) {
const cert = response.body.certificate;
certificate = await certificate_1.Certificate.create({
certificate: (0, candid_1.bufFromBufLike)(cert),
rootKey: agent.rootKey,
canisterId: principal_1.Principal.from(canisterId),
certTime,
});
const path = [new TextEncoder().encode('request_status'), requestId];
const status = new TextDecoder().decode((0, certificate_1.lookupResultToBuffer)(certificate.lookup([...path, 'status'])));
switch (status) {
case 'replied':
reply = (0, certificate_1.lookupResultToBuffer)(certificate.lookup([...path, 'reply']));
break;
case 'rejected':
throw new UpdateCallRejectedError(cid, methodName, requestId, response);
}
}
const pollStrategy = pollingStrategyFactory();
// Contains the certificate and the reply from the boundary node
const { certificate, reply } = await (0, polling_1.pollForResponse)(agent, ecid, requestId, pollStrategy, blsVerify);
reply;
// Fall back to polling if we recieve an Accepted response code
if (response.status === 202) {
const pollStrategy = pollingStrategyFactory();
// Contains the certificate and the reply from the boundary node
const response = await (0, polling_1.pollForResponse)(agent, ecid, requestId, pollStrategy, blsVerify);
certificate = response.certificate;
reply = response.reply;
}
const shouldIncludeHttpDetails = func.annotations.includes(exports.ACTOR_METHOD_WITH_HTTP_DETAILS);

@@ -261,0 +286,0 @@ const shouldIncludeCertificate = func.annotations.includes(exports.ACTOR_METHOD_WITH_CERTIFICATE);

@@ -97,4 +97,4 @@ import { Principal } from '@dfinity/principal';

/**
* An effective canister ID, used for routing. This should only be mentioned if
* it's different from the canister ID.
* An effective canister ID, used for routing. Usually the canister ID, except for management canister calls.
* @see https://internetcomputer.org/docs/current/references/ic-interface-spec/#http-effective-canister-id
*/

@@ -105,2 +105,3 @@ effectiveCanisterId: Principal | string;

certificate: ArrayBuffer;
replicaTime?: Date;
}

@@ -117,2 +118,3 @@ export interface SubmitResponse {

reject_message: string;
certificate?: ArrayBuffer;
} | null;

@@ -119,0 +121,0 @@ headers: HttpHeaderField[];

@@ -0,1 +1,2 @@

import { HttpAgent } from '.';
import { AgentError } from '../../errors';

@@ -7,1 +8,6 @@ import { HttpDetailsResponse } from '../api';

}
export declare class ReplicaTimeError extends AgentError {
readonly replicaTime: Date;
readonly agent: HttpAgent;
constructor(message: string, replicaTime: Date, agent: HttpAgent);
}
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.AgentHTTPResponseError = void 0;
exports.ReplicaTimeError = exports.AgentHTTPResponseError = void 0;
const errors_1 = require("../../errors");

@@ -14,2 +14,12 @@ class AgentHTTPResponseError extends errors_1.AgentError {

exports.AgentHTTPResponseError = AgentHTTPResponseError;
class ReplicaTimeError extends errors_1.AgentError {
constructor(message, replicaTime, agent) {
super(message);
this.name = 'ReplicaTimeError';
this.replicaTime = replicaTime;
this.agent = agent;
Object.setPrototypeOf(this, new.target.prototype);
}
}
exports.ReplicaTimeError = ReplicaTimeError;
//# sourceMappingURL=errors.js.map

@@ -63,2 +63,10 @@ import { JsonObject } from '@dfinity/candid';

logToConsole?: boolean;
/**
* Provide an expected replica time. This can be used to set the baseline for the time to use when making requests against the replica.
*/
replicaTime?: Date;
/**
* Alternate root key to use for verifying certificates. If not provided, the default IC root key will be used.
*/
rootKey?: ArrayBuffer;
}

@@ -91,2 +99,4 @@ interface V1HttpAgentInterface {

config: HttpAgentOptions;
get replicaTime(): Date;
set replicaTime(replicaTime: Date);
get waterMark(): number;

@@ -111,6 +121,7 @@ log: ObservableLog;

effectiveCanisterId?: Principal | string;
callSync?: boolean;
}, identity?: Identity | Promise<Identity>): Promise<SubmitResponse>;
query(canisterId: Principal | string, fields: QueryFields, identity?: Identity | Promise<Identity>): Promise<ApiQueryResponse>;
createReadStateRequest(fields: ReadStateOptions, identity?: Identity | Promise<Identity>): Promise<any>;
readState(canisterId: Principal | string, fields: ReadStateOptions, identity?: Identity | Promise<Identity>, request?: any): Promise<ReadStateResponse>;
readState(canisterId: Principal | string, fields: ReadStateOptions, identity?: Identity | Promise<Identity>, request?: Request): Promise<ReadStateResponse>;
parseTimeFromResponse(response: ReadStateResponse): Promise<number>;

@@ -120,2 +131,3 @@ /**

* @param {Principal} canisterId - Pass a canister ID if you need to sync the time with a particular replica. Uses the management canister by default
* @throws {ReplicaTimeError} - this method is not guaranteed to work if the device's clock is off by more than 30 seconds. In such cases, the agent will throw an error.
*/

@@ -122,0 +134,0 @@ syncTime(canisterId?: Principal): Promise<void>;

@@ -39,3 +39,3 @@ "use strict";

};
var _HttpAgent_instances, _HttpAgent_identity, _HttpAgent_fetch, _HttpAgent_fetchOptions, _HttpAgent_callOptions, _HttpAgent_timeDiffMsecs, _HttpAgent_credentials, _HttpAgent_rootKeyFetched, _HttpAgent_retryTimes, _HttpAgent_backoffStrategy, _HttpAgent_waterMark, _HttpAgent_queryPipeline, _HttpAgent_updatePipeline, _HttpAgent_subnetKeys, _HttpAgent_verifyQuerySignatures, _HttpAgent_requestAndRetryQuery, _HttpAgent_requestAndRetry, _HttpAgent_verifyQueryResponse;
var _HttpAgent_instances, _HttpAgent_identity, _HttpAgent_fetch, _HttpAgent_fetchOptions, _HttpAgent_callOptions, _HttpAgent_credentials, _HttpAgent_rootKeyFetched, _HttpAgent_retryTimes, _HttpAgent_backoffStrategy, _HttpAgent_waterMark, _HttpAgent_initialClientTime, _HttpAgent_initialReplicaTime, _HttpAgent_queryPipeline, _HttpAgent_updatePipeline, _HttpAgent_subnetKeys, _HttpAgent_verifyQuerySignatures, _HttpAgent_requestAndRetryQuery, _HttpAgent_requestAndRetry, _HttpAgent_verifyQueryResponse, _HttpAgent_handleReplicaTimeError;
Object.defineProperty(exports, "__esModule", { value: true });

@@ -60,2 +60,3 @@ exports.HttpAgent = exports.IdentityInvalidError = exports.MANAGEMENT_CANISTER_ID = exports.IC_ROOT_KEY = exports.RequestStatusResponseStatus = exports.makeNonce = void 0;

const backoff_1 = require("../../polling/backoff");
const calculateReplicaTime_1 = require("./calculateReplicaTime");
__exportStar(require("./transforms"), exports);

@@ -184,3 +185,2 @@ var types_2 = require("./types");

_HttpAgent_instances.add(this);
this.rootKey = (0, buffer_1.fromHex)(exports.IC_ROOT_KEY);
_HttpAgent_identity.set(this, void 0);

@@ -190,3 +190,2 @@ _HttpAgent_fetch.set(this, void 0);

_HttpAgent_callOptions.set(this, void 0);
_HttpAgent_timeDiffMsecs.set(this, 0);
_HttpAgent_credentials.set(this, void 0);

@@ -201,2 +200,5 @@ _HttpAgent_rootKeyFetched.set(this, false);

_HttpAgent_waterMark.set(this, 0);
// Manage the time offset between the client and the replica
_HttpAgent_initialClientTime.set(this, new Date(Date.now()));
_HttpAgent_initialReplicaTime.set(this, new Date(Date.now()));
this.log = new observable_1.ObservableLog();

@@ -267,2 +269,11 @@ _HttpAgent_queryPipeline.set(this, []);

});
_HttpAgent_handleReplicaTimeError.set(this, (error) => {
const message = error.message;
if (message === null || message === void 0 ? void 0 : message.includes('ingress_expiry')) {
{
const replicaTime = (0, calculateReplicaTime_1.calculateReplicaTime)(message);
throw new errors_2.ReplicaTimeError(message, replicaTime, this);
}
}
});
this.config = options;

@@ -272,2 +283,3 @@ __classPrivateFieldSet(this, _HttpAgent_fetch, options.fetch || getDefaultFetch() || fetch.bind(global), "f");

__classPrivateFieldSet(this, _HttpAgent_callOptions, options.callOptions, "f");
this.rootKey = options.rootKey ? options.rootKey : (0, buffer_1.fromHex)(exports.IC_ROOT_KEY);
const host = determineHost(options.host);

@@ -319,2 +331,10 @@ this.host = new URL(host);

}
get replicaTime() {
const offset = Date.now() - __classPrivateFieldGet(this, _HttpAgent_initialClientTime, "f").getTime();
return new Date(__classPrivateFieldGet(this, _HttpAgent_initialReplicaTime, "f").getTime() + offset);
}
set replicaTime(replicaTime) {
__classPrivateFieldSet(this, _HttpAgent_initialClientTime, new Date(Date.now()), "f");
__classPrivateFieldSet(this, _HttpAgent_initialReplicaTime, replicaTime, "f");
}
get waterMark() {

@@ -378,2 +398,4 @@ return __classPrivateFieldGet(this, _HttpAgent_waterMark, "f");

async call(canisterId, options, identity) {
var _a;
const callSync = (_a = options.callSync) !== null && _a !== void 0 ? _a : true;
const id = await (identity !== undefined ? await identity : await __classPrivateFieldGet(this, _HttpAgent_identity, "f"));

@@ -390,4 +412,5 @@ if (!id) {

// If the value is off by more than 30 seconds, reconcile system time with the network
if (Math.abs(__classPrivateFieldGet(this, _HttpAgent_timeDiffMsecs, "f")) > 1000 * 30) {
ingress_expiry = new transforms_1.Expiry(DEFAULT_INGRESS_EXPIRY_DELTA_IN_MSECS + __classPrivateFieldGet(this, _HttpAgent_timeDiffMsecs, "f"));
const timeDiffMsecs = this.replicaTime && this.replicaTime.getTime() - Date.now();
if (Math.abs(timeDiffMsecs) > 1000 * 30) {
ingress_expiry = new transforms_1.Expiry(DEFAULT_INGRESS_EXPIRY_DELTA_IN_MSECS + timeDiffMsecs);
}

@@ -422,25 +445,51 @@ const submit = {

const body = cbor.encode(transformedRequest.body);
this.log.print(`fetching "/api/v2/canister/${ecid.toText()}/call" with request:`, transformedRequest);
// Run both in parallel. The fetch is quite expensive, so we have plenty of time to
// calculate the requestId locally.
const backoff = __classPrivateFieldGet(this, _HttpAgent_backoffStrategy, "f").call(this);
const request = __classPrivateFieldGet(this, _HttpAgent_instances, "m", _HttpAgent_requestAndRetry).call(this, {
request: () => __classPrivateFieldGet(this, _HttpAgent_fetch, "f").call(this, '' + new URL(`/api/v2/canister/${ecid.toText()}/call`, this.host), Object.assign(Object.assign(Object.assign({}, __classPrivateFieldGet(this, _HttpAgent_callOptions, "f")), transformedRequest.request), { body })),
backoff,
tries: 0,
});
const [response, requestId] = await Promise.all([request, (0, request_id_1.requestIdOf)(submit)]);
const responseBuffer = await response.arrayBuffer();
const responseBody = (response.status === 200 && responseBuffer.byteLength > 0 ? cbor.decode(responseBuffer) : null);
return {
requestId,
response: {
ok: response.ok,
status: response.status,
statusText: response.statusText,
body: responseBody,
headers: (0, transforms_1.httpHeadersTransform)(response.headers),
},
requestDetails: submit,
};
try {
// Attempt v3 sync call
const requestSync = () => {
this.log.print(`fetching "/api/v3/canister/${ecid.toText()}/call" with request:`, transformedRequest);
return __classPrivateFieldGet(this, _HttpAgent_fetch, "f").call(this, '' + new URL(`/api/v3/canister/${ecid.toText()}/call`, this.host), Object.assign(Object.assign(Object.assign({}, __classPrivateFieldGet(this, _HttpAgent_callOptions, "f")), transformedRequest.request), { body }));
};
const requestAsync = () => {
this.log.print(`fetching "/api/v2/canister/${ecid.toText()}/call" with request:`, transformedRequest);
return __classPrivateFieldGet(this, _HttpAgent_fetch, "f").call(this, '' + new URL(`/api/v2/canister/${ecid.toText()}/call`, this.host), Object.assign(Object.assign(Object.assign({}, __classPrivateFieldGet(this, _HttpAgent_callOptions, "f")), transformedRequest.request), { body }));
};
const request = __classPrivateFieldGet(this, _HttpAgent_instances, "m", _HttpAgent_requestAndRetry).call(this, {
request: callSync ? requestSync : requestAsync,
backoff,
tries: 0,
});
const [response, requestId] = await Promise.all([request, (0, request_id_1.requestIdOf)(submit)]);
const responseBuffer = await response.arrayBuffer();
const responseBody = (response.status === 200 && responseBuffer.byteLength > 0
? cbor.decode(responseBuffer)
: null);
// Update the watermark with the latest time from consensus
if (responseBody === null || responseBody === void 0 ? void 0 : responseBody.certificate) {
const time = await this.parseTimeFromResponse({ certificate: responseBody.certificate });
__classPrivateFieldSet(this, _HttpAgent_waterMark, time, "f");
}
return {
requestId,
response: {
ok: response.ok,
status: response.status,
statusText: response.statusText,
body: responseBody,
headers: (0, transforms_1.httpHeadersTransform)(response.headers),
},
requestDetails: submit,
};
}
catch (error) {
// If the error is due to the v3 api not being supported, fall back to v2
if (error.message.includes('v3 api not supported.')) {
this.log.warn('v3 api not supported. Fall back to v2');
return this.call(canisterId, Object.assign(Object.assign({}, options), {
// disable v3 api
callSync: false }), identity);
}
this.log.error('Error while making call:', error);
throw error;
}
}

@@ -461,2 +510,8 @@ async query(canisterId, fields, identity) {

const sender = (id === null || id === void 0 ? void 0 : id.getPrincipal()) || principal_1.Principal.anonymous();
let ingress_expiry = new transforms_1.Expiry(DEFAULT_INGRESS_EXPIRY_DELTA_IN_MSECS);
// If the value is off by more than 30 seconds, reconcile system time with the network
const timeDiffMsecs = this.replicaTime && this.replicaTime.getTime() - Date.now();
if (Math.abs(timeDiffMsecs) > 1000 * 30) {
ingress_expiry = new transforms_1.Expiry(DEFAULT_INGRESS_EXPIRY_DELTA_IN_MSECS + timeDiffMsecs);
}
const request = {

@@ -468,3 +523,3 @@ request_type: "query" /* ReadRequestType.Query */,

sender,
ingress_expiry: new transforms_1.Expiry(DEFAULT_INGRESS_EXPIRY_DELTA_IN_MSECS),
ingress_expiry,
};

@@ -541,4 +596,8 @@ const requestId = await (0, request_id_1.requestIdOf)(request);

const sender = (id === null || id === void 0 ? void 0 : id.getPrincipal()) || principal_1.Principal.anonymous();
// TODO: remove this any. This can be a Signed or UnSigned request.
// eslint-disable-next-line @typescript-eslint/no-explicit-any
let ingress_expiry = new transforms_1.Expiry(DEFAULT_INGRESS_EXPIRY_DELTA_IN_MSECS);
// If the value is off by more than 30 seconds, reconcile system time with the network
const timeDiffMsecs = this.replicaTime && this.replicaTime.getTime() - Date.now();
if (Math.abs(timeDiffMsecs) > 1000 * 30) {
ingress_expiry = new transforms_1.Expiry(DEFAULT_INGRESS_EXPIRY_DELTA_IN_MSECS + timeDiffMsecs);
}
const transformedRequest = await this._transform({

@@ -554,3 +613,3 @@ request: {

sender,
ingress_expiry: new transforms_1.Expiry(DEFAULT_INGRESS_EXPIRY_DELTA_IN_MSECS),
ingress_expiry,
},

@@ -570,20 +629,26 @@ });

const backoff = __classPrivateFieldGet(this, _HttpAgent_backoffStrategy, "f").call(this);
const response = await __classPrivateFieldGet(this, _HttpAgent_instances, "m", _HttpAgent_requestAndRetry).call(this, {
request: () => __classPrivateFieldGet(this, _HttpAgent_fetch, "f").call(this, '' + new URL(`/api/v2/canister/${canister.toString()}/read_state`, this.host), Object.assign(Object.assign(Object.assign({}, __classPrivateFieldGet(this, _HttpAgent_fetchOptions, "f")), transformedRequest.request), { body })),
backoff,
tries: 0,
});
if (!response.ok) {
throw new Error(`Server returned an error:\n` +
` Code: ${response.status} (${response.statusText})\n` +
` Body: ${await response.text()}\n`);
try {
const response = await __classPrivateFieldGet(this, _HttpAgent_instances, "m", _HttpAgent_requestAndRetry).call(this, {
request: () => __classPrivateFieldGet(this, _HttpAgent_fetch, "f").call(this, '' + new URL(`/api/v2/canister/${canister.toString()}/read_state`, this.host), Object.assign(Object.assign(Object.assign({}, __classPrivateFieldGet(this, _HttpAgent_fetchOptions, "f")), transformedRequest.request), { body })),
backoff,
tries: 0,
});
if (!response.ok) {
throw new Error(`Server returned an error:\n` +
` Code: ${response.status} (${response.statusText})\n` +
` Body: ${await response.text()}\n`);
}
const decodedResponse = cbor.decode(await response.arrayBuffer());
this.log.print('Read state response:', decodedResponse);
const parsedTime = await this.parseTimeFromResponse(decodedResponse);
if (parsedTime > 0) {
this.log.print('Read state response time:', parsedTime);
__classPrivateFieldSet(this, _HttpAgent_waterMark, parsedTime, "f");
}
return decodedResponse;
}
const decodedResponse = cbor.decode(await response.arrayBuffer());
this.log.print('Read state response:', decodedResponse);
const parsedTime = await this.parseTimeFromResponse(decodedResponse);
if (parsedTime > 0) {
this.log.print('Read state response time:', parsedTime);
__classPrivateFieldSet(this, _HttpAgent_waterMark, parsedTime, "f");
catch (error) {
__classPrivateFieldGet(this, _HttpAgent_handleReplicaTimeError, "f").call(this, error);
}
return decodedResponse;
throw new errors_1.AgentError('Failed to read state');
}

@@ -620,6 +685,6 @@ async parseTimeFromResponse(response) {

* @param {Principal} canisterId - Pass a canister ID if you need to sync the time with a particular replica. Uses the management canister by default
* @throws {ReplicaTimeError} - this method is not guaranteed to work if the device's clock is off by more than 30 seconds. In such cases, the agent will throw an error.
*/
async syncTime(canisterId) {
const CanisterStatus = await Promise.resolve().then(() => __importStar(require('../../canisterStatus')));
const callTime = Date.now();
try {

@@ -637,3 +702,3 @@ if (!canisterId) {

if (replicaTime) {
__classPrivateFieldSet(this, _HttpAgent_timeDiffMsecs, Number(replicaTime) - Number(callTime), "f");
this.replicaTime = new Date(Number(replicaTime));
}

@@ -662,4 +727,5 @@ }

if (!__classPrivateFieldGet(this, _HttpAgent_rootKeyFetched, "f")) {
const status = await this.status();
// Hex-encoded version of the replica root key
this.rootKey = (await this.status()).root_key;
this.rootKey = status.root_key;
__classPrivateFieldSet(this, _HttpAgent_rootKeyFetched, true, "f");

@@ -706,3 +772,3 @@ }

exports.HttpAgent = HttpAgent;
_HttpAgent_identity = new WeakMap(), _HttpAgent_fetch = new WeakMap(), _HttpAgent_fetchOptions = new WeakMap(), _HttpAgent_callOptions = new WeakMap(), _HttpAgent_timeDiffMsecs = new WeakMap(), _HttpAgent_credentials = new WeakMap(), _HttpAgent_rootKeyFetched = new WeakMap(), _HttpAgent_retryTimes = new WeakMap(), _HttpAgent_backoffStrategy = new WeakMap(), _HttpAgent_waterMark = new WeakMap(), _HttpAgent_queryPipeline = new WeakMap(), _HttpAgent_updatePipeline = new WeakMap(), _HttpAgent_subnetKeys = new WeakMap(), _HttpAgent_verifyQuerySignatures = new WeakMap(), _HttpAgent_verifyQueryResponse = new WeakMap(), _HttpAgent_instances = new WeakSet(), _HttpAgent_requestAndRetryQuery = async function _HttpAgent_requestAndRetryQuery(args) {
_HttpAgent_identity = new WeakMap(), _HttpAgent_fetch = new WeakMap(), _HttpAgent_fetchOptions = new WeakMap(), _HttpAgent_callOptions = new WeakMap(), _HttpAgent_credentials = new WeakMap(), _HttpAgent_rootKeyFetched = new WeakMap(), _HttpAgent_retryTimes = new WeakMap(), _HttpAgent_backoffStrategy = new WeakMap(), _HttpAgent_waterMark = new WeakMap(), _HttpAgent_initialClientTime = new WeakMap(), _HttpAgent_initialReplicaTime = new WeakMap(), _HttpAgent_queryPipeline = new WeakMap(), _HttpAgent_updatePipeline = new WeakMap(), _HttpAgent_subnetKeys = new WeakMap(), _HttpAgent_verifyQuerySignatures = new WeakMap(), _HttpAgent_verifyQueryResponse = new WeakMap(), _HttpAgent_handleReplicaTimeError = new WeakMap(), _HttpAgent_instances = new WeakSet(), _HttpAgent_requestAndRetryQuery = async function _HttpAgent_requestAndRetryQuery(args) {
var _a, _b;

@@ -749,2 +815,4 @@ const { ecid, transformedRequest, body, requestId, backoff, tries } = args;

catch (error) {
this.log.error('Caught exception while attempting to read state', error);
__classPrivateFieldGet(this, _HttpAgent_handleReplicaTimeError, "f").call(this, error);
if (tries < __classPrivateFieldGet(this, _HttpAgent_retryTimes, "f")) {

@@ -815,5 +883,16 @@ this.log.warn(`Caught exception while attempting to make query:\n` +

const responseText = await response.clone().text();
if (response.status === 400 && responseText.includes('ingress_expiry')) {
__classPrivateFieldGet(this, _HttpAgent_handleReplicaTimeError, "f").call(this, new errors_1.AgentError(responseText));
}
const errorMessage = `Server returned an error:\n` +
` Code: ${response.status} (${response.statusText})\n` +
` Body: ${responseText}\n`;
if (response.status === 404 && response.url.includes('api/v3')) {
throw new errors_2.AgentHTTPResponseError('v3 api not supported. Fall back to v2', {
ok: response.ok,
status: response.status,
statusText: response.statusText,
headers: (0, transforms_1.httpHeadersTransform)(response.headers),
});
}
if (tries < __classPrivateFieldGet(this, _HttpAgent_retryTimes, "f")) {

@@ -820,0 +899,0 @@ return await __classPrivateFieldGet(this, _HttpAgent_instances, "m", _HttpAgent_requestAndRetry).call(this, { request, backoff, tries: tries + 1 });

@@ -77,6 +77,2 @@ "use strict";

}),
load_snapshot: IDL.Record({
canister_version: IDL.Nat64,
taken_at_timestamp: IDL.Nat64,
}),
controllers_change: IDL.Record({

@@ -148,7 +144,2 @@ controllers: IDL.Vec(IDL.Principal),

const delete_canister_args = IDL.Record({ canister_id: canister_id });
const snapshot_id = IDL.Vec(IDL.Nat8);
const delete_canister_snapshot_args = IDL.Record({
canister_id: canister_id,
snapshot_id: snapshot_id,
});
const deposit_cycles_args = IDL.Record({ canister_id: canister_id });

@@ -226,16 +217,2 @@ const ecdsa_curve = IDL.Variant({ secp256k1: IDL.Null });

});
const list_canister_snapshots_args = IDL.Record({
canister_id: canister_id,
});
const snapshot = IDL.Record({
id: snapshot_id,
total_size: IDL.Nat64,
taken_at_timestamp: IDL.Nat64,
});
const list_canister_snapshots_result = IDL.Vec(snapshot);
const load_canister_snapshot_args = IDL.Record({
canister_id: canister_id,
sender_canister_version: IDL.Opt(IDL.Nat64),
snapshot_id: snapshot_id,
});
const node_metrics_history_args = IDL.Record({

@@ -268,2 +245,18 @@ start_at_timestamp_nanos: IDL.Nat64,

const raw_rand_result = IDL.Vec(IDL.Nat8);
const schnorr_algorithm = IDL.Variant({
ed25519: IDL.Null,
bip340secp256k1: IDL.Null,
});
const schnorr_public_key_args = IDL.Record({
key_id: IDL.Record({
algorithm: schnorr_algorithm,
name: IDL.Text,
}),
canister_id: IDL.Opt(canister_id),
derivation_path: IDL.Vec(IDL.Vec(IDL.Nat8)),
});
const schnorr_public_key_result = IDL.Record({
public_key: IDL.Vec(IDL.Nat8),
chain_code: IDL.Vec(IDL.Nat8),
});
const sign_with_ecdsa_args = IDL.Record({

@@ -277,2 +270,13 @@ key_id: IDL.Record({ name: IDL.Text, curve: ecdsa_curve }),

});
const sign_with_schnorr_args = IDL.Record({
key_id: IDL.Record({
algorithm: schnorr_algorithm,
name: IDL.Text,
}),
derivation_path: IDL.Vec(IDL.Vec(IDL.Nat8)),
message: IDL.Vec(IDL.Nat8),
});
const sign_with_schnorr_result = IDL.Record({
signature: IDL.Vec(IDL.Nat8),
});
const start_canister_args = IDL.Record({ canister_id: canister_id });

@@ -282,7 +286,2 @@ const stop_canister_args = IDL.Record({ canister_id: canister_id });

const stored_chunks_result = IDL.Vec(chunk_hash);
const take_canister_snapshot_args = IDL.Record({
replace_snapshot: IDL.Opt(snapshot_id),
canister_id: canister_id,
});
const take_canister_snapshot_result = snapshot;
const uninstall_code_args = IDL.Record({

@@ -312,3 +311,2 @@ canister_id: canister_id,

delete_canister: IDL.Func([delete_canister_args], [], []),
delete_canister_snapshot: IDL.Func([delete_canister_snapshot_args], [], []),
deposit_cycles: IDL.Func([deposit_cycles_args], [], []),

@@ -320,4 +318,2 @@ ecdsa_public_key: IDL.Func([ecdsa_public_key_args], [ecdsa_public_key_result], []),

install_code: IDL.Func([install_code_args], [], []),
list_canister_snapshots: IDL.Func([list_canister_snapshots_args], [list_canister_snapshots_result], []),
load_canister_snapshot: IDL.Func([load_canister_snapshot_args], [], []),
node_metrics_history: IDL.Func([node_metrics_history_args], [node_metrics_history_result], []),

@@ -327,7 +323,8 @@ provisional_create_canister_with_cycles: IDL.Func([provisional_create_canister_with_cycles_args], [provisional_create_canister_with_cycles_result], []),

raw_rand: IDL.Func([], [raw_rand_result], []),
schnorr_public_key: IDL.Func([schnorr_public_key_args], [schnorr_public_key_result], []),
sign_with_ecdsa: IDL.Func([sign_with_ecdsa_args], [sign_with_ecdsa_result], []),
sign_with_schnorr: IDL.Func([sign_with_schnorr_args], [sign_with_schnorr_result], []),
start_canister: IDL.Func([start_canister_args], [], []),
stop_canister: IDL.Func([stop_canister_args], [], []),
stored_chunks: IDL.Func([stored_chunks_args], [stored_chunks_result], []),
take_canister_snapshot: IDL.Func([take_canister_snapshot_args], [take_canister_snapshot_result], []),
uninstall_code: IDL.Func([uninstall_code_args], [], []),

@@ -334,0 +331,0 @@ update_settings: IDL.Func([update_settings_args], [], []),

@@ -127,7 +127,2 @@ import type { Principal } from '@dfinity/principal';

} | {
load_snapshot: {
canister_version: bigint;
taken_at_timestamp: bigint;
};
} | {
controllers_change: {

@@ -174,6 +169,2 @@ controllers: Array<Principal>;

}
export interface delete_canister_snapshot_args {
canister_id: canister_id;
snapshot_id: snapshot_id;
}
export interface deposit_cycles_args {

@@ -245,11 +236,2 @@ canister_id: canister_id;

}
export interface list_canister_snapshots_args {
canister_id: canister_id;
}
export declare type list_canister_snapshots_result = Array<snapshot>;
export interface load_canister_snapshot_args {
canister_id: canister_id;
sender_canister_version: [] | [bigint];
snapshot_id: snapshot_id;
}
export declare type log_visibility = {

@@ -293,2 +275,19 @@ controllers: null;

export declare type satoshi = bigint;
export declare type schnorr_algorithm = {
ed25519: null;
} | {
bip340secp256k1: null;
};
export interface schnorr_public_key_args {
key_id: {
algorithm: schnorr_algorithm;
name: string;
};
canister_id: [] | [canister_id];
derivation_path: Array<Uint8Array | number[]>;
}
export interface schnorr_public_key_result {
public_key: Uint8Array | number[];
chain_code: Uint8Array | number[];
}
export interface sign_with_ecdsa_args {

@@ -305,8 +304,13 @@ key_id: {

}
export interface snapshot {
id: snapshot_id;
total_size: bigint;
taken_at_timestamp: bigint;
export interface sign_with_schnorr_args {
key_id: {
algorithm: schnorr_algorithm;
name: string;
};
derivation_path: Array<Uint8Array | number[]>;
message: Uint8Array | number[];
}
export declare type snapshot_id = Uint8Array | number[];
export interface sign_with_schnorr_result {
signature: Uint8Array | number[];
}
export interface start_canister_args {

@@ -322,7 +326,2 @@ canister_id: canister_id;

export declare type stored_chunks_result = Array<chunk_hash>;
export interface take_canister_snapshot_args {
replace_snapshot: [] | [snapshot_id];
canister_id: canister_id;
}
export declare type take_canister_snapshot_result = snapshot;
export interface uninstall_code_args {

@@ -360,3 +359,2 @@ canister_id: canister_id;

delete_canister: ActorMethod<[delete_canister_args], undefined>;
delete_canister_snapshot: ActorMethod<[delete_canister_snapshot_args], undefined>;
deposit_cycles: ActorMethod<[deposit_cycles_args], undefined>;

@@ -368,6 +366,2 @@ ecdsa_public_key: ActorMethod<[ecdsa_public_key_args], ecdsa_public_key_result>;

install_code: ActorMethod<[install_code_args], undefined>;
list_canister_snapshots: ActorMethod<[
list_canister_snapshots_args
], list_canister_snapshots_result>;
load_canister_snapshot: ActorMethod<[load_canister_snapshot_args], undefined>;
node_metrics_history: ActorMethod<[node_metrics_history_args], node_metrics_history_result>;

@@ -379,7 +373,8 @@ provisional_create_canister_with_cycles: ActorMethod<[

raw_rand: ActorMethod<[], raw_rand_result>;
schnorr_public_key: ActorMethod<[schnorr_public_key_args], schnorr_public_key_result>;
sign_with_ecdsa: ActorMethod<[sign_with_ecdsa_args], sign_with_ecdsa_result>;
sign_with_schnorr: ActorMethod<[sign_with_schnorr_args], sign_with_schnorr_result>;
start_canister: ActorMethod<[start_canister_args], undefined>;
stop_canister: ActorMethod<[stop_canister_args], undefined>;
stored_chunks: ActorMethod<[stored_chunks_args], stored_chunks_result>;
take_canister_snapshot: ActorMethod<[take_canister_snapshot_args], take_canister_snapshot_result>;
uninstall_code: ActorMethod<[uninstall_code_args], undefined>;

@@ -386,0 +381,0 @@ update_settings: ActorMethod<[update_settings_args], undefined>;

@@ -80,2 +80,3 @@ "use strict";

});
const certTime = agent.replicaTime ? agent.replicaTime : undefined;
const cert = await certificate_1.Certificate.create({

@@ -85,2 +86,3 @@ certificate: response.certificate,

canisterId: canisterId,
certTime,
});

@@ -87,0 +89,0 @@ const lookup = (cert, path) => {

@@ -25,3 +25,3 @@ import { AgentError } from './errors';

* Make a human readable string out of a hash tree.
* @param tree
* @param tree - the tree to stringify
*/

@@ -50,3 +50,3 @@ export declare function hashTreeToString(tree: HashTree): string;

/**
* BLS Verification strategy. Default strategy uses wasm for performance, but that may not be available in all contexts.
* BLS Verification strategy. Default strategy uses bls12_381 from @noble/curves
*/

@@ -61,4 +61,9 @@ blsVerify?: VerifyFunc;

maxAgeInMinutes?: number;
/**
* For comparing the time of the certificate to an expected date instead of the result of Date.now.
*/
certTime?: Date;
}
export declare class Certificate {
#private;
private _rootKey;

@@ -68,3 +73,3 @@ private _canisterId;

private _maxAgeInMinutes;
private readonly cert;
cert: Cert;
/**

@@ -96,3 +101,3 @@ * Create a new instance of a certificate, automatically verifying it. Throws a

/**
* @param t
* @param t - the tree to reconstruct
*/

@@ -127,2 +132,8 @@ export declare function reconstruct(t: HashTree): Promise<ArrayBuffer>;

declare type LabelLookupResult = LookupResult | LookupResultGreater | LookupResultLess;
/**
* Lookup a path in a tree
* @param path - the path to look up
* @param tree - the tree to search
* @returns LookupResult
*/
export declare function lookup_path(path: Array<ArrayBuffer | string>, tree: HashTree): LookupResult;

@@ -135,8 +146,16 @@ /**

export declare function flatten_forks(t: HashTree): HashTree[];
/**
* Find a label in a tree
* @param label - the label to find
* @param tree - the tree to search
* @returns LabelLookupResult
*/
export declare function find_label(label: ArrayBuffer, tree: HashTree): LabelLookupResult;
/**
* Check if a canister falls within a range of canisters
* @param canisterId Principal
* @param ranges [Principal, Principal][]
* @returns
* @param params - the parameters to check
* @param params.canisterId Principal
* @param params.subnetId Principal
* @param params.tree HashTree
* @returns boolean
*/

@@ -143,0 +162,0 @@ export declare function check_canister_ranges(params: {

@@ -25,2 +25,14 @@ "use strict";

};
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 _Certificate_certTime;
Object.defineProperty(exports, "__esModule", { value: true });

@@ -54,3 +66,3 @@ exports.check_canister_ranges = exports.find_label = exports.flatten_forks = exports.lookup_path = exports.LookupStatus = exports.reconstruct = exports.lookupResultToBuffer = exports.Certificate = exports.hashTreeToString = exports.NodeType = exports.CertificateVerificationError = void 0;

* Make a human readable string out of a hash tree.
* @param tree
* @param tree - the tree to stringify
*/

@@ -67,3 +79,3 @@ function hashTreeToString(tree) {

}
catch (e) {
catch (_a) {
return `data(...${label.byteLength} bytes)`;

@@ -132,3 +144,3 @@ }

// Default to 5 minutes
_maxAgeInMinutes = 5) {
_maxAgeInMinutes = 5, certTime) {
this._rootKey = _rootKey;

@@ -138,3 +150,5 @@ this._canisterId = _canisterId;

this._maxAgeInMinutes = _maxAgeInMinutes;
_Certificate_certTime.set(this, void 0);
this.cert = cbor.decode(new Uint8Array(certificate));
__classPrivateFieldSet(this, _Certificate_certTime, certTime, "f");
}

@@ -162,3 +176,3 @@ /**

}
return new Certificate(options.certificate, options.rootKey, options.canisterId, blsVerify, options.maxAgeInMinutes);
return new Certificate(options.certificate, options.rootKey, options.canisterId, blsVerify, options.maxAgeInMinutes, options.certTime);
}

@@ -187,4 +201,6 @@ lookup(path) {

const now = Date.now();
const earliestCertificateTime = now - MAX_AGE_IN_MSEC;
const fiveMinutesFromNow = now + FIVE_MINUTES_IN_MSEC;
// Use a provided time in case `Date.now()` is inaccurate
const compareTime = __classPrivateFieldGet(this, _Certificate_certTime, "f") || new Date(now);
const earliestCertificateTime = compareTime.getTime() - MAX_AGE_IN_MSEC;
const fiveMinutesFromNow = compareTime.getTime() + FIVE_MINUTES_IN_MSEC;
const certTime = (0, leb_1.decodeTime)(lookupTime);

@@ -195,3 +211,3 @@ if (certTime.getTime() < earliestCertificateTime) {

' Current time: ' +
new Date(now).toISOString());
compareTime.toISOString());
}

@@ -202,3 +218,3 @@ else if (certTime.getTime() > fiveMinutesFromNow) {

' Current time: ' +
new Date(now).toISOString());
compareTime.toISOString());
}

@@ -208,3 +224,3 @@ try {

}
catch (err) {
catch (_a) {
sigVer = false;

@@ -225,2 +241,3 @@ }

blsVerify: this._blsVerify,
certTime: __classPrivateFieldGet(this, _Certificate_certTime, "f"),
// Do not check max age for delegation certificates

@@ -249,2 +266,3 @@ maxAgeInMinutes: Infinity,

exports.Certificate = Certificate;
_Certificate_certTime = new WeakMap();
const DER_PREFIX = (0, buffer_1.fromHex)('308182301d060d2b0601040182dc7c0503010201060c2b0601040182dc7c05030201036100');

@@ -282,3 +300,3 @@ const KEY_LENGTH = 96;

/**
* @param t
* @param t - the tree to reconstruct
*/

@@ -318,2 +336,8 @@ async function reconstruct(t) {

})(LabelLookupStatus || (LabelLookupStatus = {}));
/**
* Lookup a path in a tree
* @param path - the path to look up
* @param tree - the tree to search
* @returns LookupResult
*/
function lookup_path(path, tree) {

@@ -385,2 +409,8 @@ if (path.length === 0) {

exports.flatten_forks = flatten_forks;
/**
* Find a label in a tree
* @param label - the label to find
* @param tree - the tree to search
* @returns LabelLookupResult
*/
function find_label(label, tree) {

@@ -415,2 +445,3 @@ switch (tree[0]) {

// search in the left node
// eslint-disable-next-line no-case-declarations
const leftLookupResult = find_label(label, tree[1]);

@@ -436,3 +467,3 @@ switch (leftLookupResult.status) {

case LookupStatus.Unknown: {
let rightLookupResult = find_label(label, tree[2]);
const rightLookupResult = find_label(label, tree[2]);
// if the label we're searching for is less than the right node lookup,

@@ -474,5 +505,7 @@ // then we also need to return an uncertain result

* Check if a canister falls within a range of canisters
* @param canisterId Principal
* @param ranges [Principal, Principal][]
* @returns
* @param params - the parameters to check
* @param params.canisterId Principal
* @param params.subnetId Principal
* @param params.tree HashTree
* @returns boolean
*/

@@ -479,0 +512,0 @@ function check_canister_ranges(params) {

@@ -28,2 +28,3 @@ import { ActorSubclass } from './actor';

export * as Cbor from './cbor';
export * from './polling';
export interface GlobalInternetComputer {

@@ -30,0 +31,0 @@ ic: {

@@ -47,2 +47,3 @@ "use strict";

exports.Cbor = __importStar(require("./cbor"));
__exportStar(require("./polling"), exports);
//# sourceMappingURL=index.js.map

@@ -19,5 +19,5 @@ import { Principal } from '@dfinity/principal';

*/
export declare function pollForResponse(agent: Agent, canisterId: Principal, requestId: RequestId, strategy: PollStrategy, request?: any, blsVerify?: CreateCertificateOptions['blsVerify']): Promise<{
export declare function pollForResponse(agent: Agent, canisterId: Principal, requestId: RequestId, strategy?: PollStrategy, request?: any, blsVerify?: CreateCertificateOptions['blsVerify']): Promise<{
certificate: Certificate;
reply: ArrayBuffer;
}>;

@@ -31,4 +31,5 @@ "use strict";

exports.strategy = __importStar(require("./strategy"));
var strategy_1 = require("./strategy");
Object.defineProperty(exports, "defaultStrategy", { enumerable: true, get: function () { return strategy_1.defaultStrategy; } });
const strategy_1 = require("./strategy");
var strategy_2 = require("./strategy");
Object.defineProperty(exports, "defaultStrategy", { enumerable: true, get: function () { return strategy_2.defaultStrategy; } });
/**

@@ -44,3 +45,3 @@ * Polls the IC to check the status of the given request then

*/
async function pollForResponse(agent, canisterId, requestId, strategy,
async function pollForResponse(agent, canisterId, requestId, strategy = (0, strategy_1.defaultStrategy)(),
// eslint-disable-next-line

@@ -54,2 +55,6 @@ request, blsVerify) {

throw new Error('Agent root key not initialized before polling');
// if agent has replicaTime, otherwise omit
const certTime = (agent === null || agent === void 0 ? void 0 : agent.replicaTime)
? agent === null || agent === void 0 ? void 0 : agent.replicaTime
: undefined;
const cert = await certificate_1.Certificate.create({

@@ -59,2 +64,3 @@ certificate: state.certificate,

canisterId: canisterId,
certTime: certTime,
blsVerify,

@@ -83,3 +89,3 @@ });

await strategy(canisterId, requestId, status);
return pollForResponse(agent, canisterId, requestId, strategy, currentRequest);
return pollForResponse(agent, canisterId, requestId, strategy, currentRequest, blsVerify);
case agent_1.RequestStatusResponseStatus.Rejected: {

@@ -86,0 +92,0 @@ const rejectCode = new Uint8Array((0, certificate_1.lookupResultToBuffer)(cert.lookup([...path, 'reject_code'])))[0];

import { Buffer } from 'buffer/';
import { getDefaultAgent, ReplicaRejectCode, } from './agent';
import { AgentError } from './errors';
import { IDL } from '@dfinity/candid';
import { bufFromBufLike, IDL } from '@dfinity/candid';
import { pollForResponse, strategy } from './polling';
import { Principal } from '@dfinity/principal';
import { toHex } from './utils/buffer';
import { Certificate, lookupResultToBuffer } from './certificate';
import managementCanisterIdl from './canisters/management_idl';

@@ -232,2 +233,4 @@ export class ActorCallError extends AgentError {

const arg = IDL.encode(func.argTypes, args);
if (agent.rootKey == null)
throw new AgentError('Agent root key not initialized before making call');
const { requestId, response, requestDetails } = await agent.call(cid, {

@@ -238,12 +241,34 @@ methodName,

});
requestId;
response;
requestDetails;
if (!response.ok || response.body /* IC-1462 */) {
throw new UpdateCallRejectedError(cid, methodName, requestId, response);
let reply;
let certificate;
const certTime = agent.replicaTime
? agent.replicaTime
: undefined;
certTime;
if (response.body && response.body.certificate) {
const cert = response.body.certificate;
certificate = await Certificate.create({
certificate: bufFromBufLike(cert),
rootKey: agent.rootKey,
canisterId: Principal.from(canisterId),
certTime,
});
const path = [new TextEncoder().encode('request_status'), requestId];
const status = new TextDecoder().decode(lookupResultToBuffer(certificate.lookup([...path, 'status'])));
switch (status) {
case 'replied':
reply = lookupResultToBuffer(certificate.lookup([...path, 'reply']));
break;
case 'rejected':
throw new UpdateCallRejectedError(cid, methodName, requestId, response);
}
}
const pollStrategy = pollingStrategyFactory();
// Contains the certificate and the reply from the boundary node
const { certificate, reply } = await pollForResponse(agent, ecid, requestId, pollStrategy, blsVerify);
reply;
// Fall back to polling if we recieve an Accepted response code
if (response.status === 202) {
const pollStrategy = pollingStrategyFactory();
// Contains the certificate and the reply from the boundary node
const response = await pollForResponse(agent, ecid, requestId, pollStrategy, blsVerify);
certificate = response.certificate;
reply = response.reply;
}
const shouldIncludeHttpDetails = func.annotations.includes(ACTOR_METHOD_WITH_HTTP_DETAILS);

@@ -250,0 +275,0 @@ const shouldIncludeCertificate = func.annotations.includes(ACTOR_METHOD_WITH_CERTIFICATE);

@@ -97,4 +97,4 @@ import { Principal } from '@dfinity/principal';

/**
* An effective canister ID, used for routing. This should only be mentioned if
* it's different from the canister ID.
* An effective canister ID, used for routing. Usually the canister ID, except for management canister calls.
* @see https://internetcomputer.org/docs/current/references/ic-interface-spec/#http-effective-canister-id
*/

@@ -105,2 +105,3 @@ effectiveCanisterId: Principal | string;

certificate: ArrayBuffer;
replicaTime?: Date;
}

@@ -117,2 +118,3 @@ export interface SubmitResponse {

reject_message: string;
certificate?: ArrayBuffer;
} | null;

@@ -119,0 +121,0 @@ headers: HttpHeaderField[];

@@ -0,1 +1,2 @@

import { HttpAgent } from '.';
import { AgentError } from '../../errors';

@@ -7,1 +8,6 @@ import { HttpDetailsResponse } from '../api';

}
export declare class ReplicaTimeError extends AgentError {
readonly replicaTime: Date;
readonly agent: HttpAgent;
constructor(message: string, replicaTime: Date, agent: HttpAgent);
}

@@ -10,2 +10,11 @@ import { AgentError } from '../../errors';

}
export class ReplicaTimeError extends AgentError {
constructor(message, replicaTime, agent) {
super(message);
this.name = 'ReplicaTimeError';
this.replicaTime = replicaTime;
this.agent = agent;
Object.setPrototypeOf(this, new.target.prototype);
}
}
//# sourceMappingURL=errors.js.map

@@ -63,2 +63,10 @@ import { JsonObject } from '@dfinity/candid';

logToConsole?: boolean;
/**
* Provide an expected replica time. This can be used to set the baseline for the time to use when making requests against the replica.
*/
replicaTime?: Date;
/**
* Alternate root key to use for verifying certificates. If not provided, the default IC root key will be used.
*/
rootKey?: ArrayBuffer;
}

@@ -91,2 +99,4 @@ interface V1HttpAgentInterface {

config: HttpAgentOptions;
get replicaTime(): Date;
set replicaTime(replicaTime: Date);
get waterMark(): number;

@@ -111,6 +121,7 @@ log: ObservableLog;

effectiveCanisterId?: Principal | string;
callSync?: boolean;
}, identity?: Identity | Promise<Identity>): Promise<SubmitResponse>;
query(canisterId: Principal | string, fields: QueryFields, identity?: Identity | Promise<Identity>): Promise<ApiQueryResponse>;
createReadStateRequest(fields: ReadStateOptions, identity?: Identity | Promise<Identity>): Promise<any>;
readState(canisterId: Principal | string, fields: ReadStateOptions, identity?: Identity | Promise<Identity>, request?: any): Promise<ReadStateResponse>;
readState(canisterId: Principal | string, fields: ReadStateOptions, identity?: Identity | Promise<Identity>, request?: Request): Promise<ReadStateResponse>;
parseTimeFromResponse(response: ReadStateResponse): Promise<number>;

@@ -120,2 +131,3 @@ /**

* @param {Principal} canisterId - Pass a canister ID if you need to sync the time with a particular replica. Uses the management canister by default
* @throws {ReplicaTimeError} - this method is not guaranteed to work if the device's clock is off by more than 30 seconds. In such cases, the agent will throw an error.
*/

@@ -122,0 +134,0 @@ syncTime(canisterId?: Principal): Promise<void>;

@@ -12,3 +12,3 @@ var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (receiver, state, value, kind, f) {

};
var _HttpAgent_instances, _HttpAgent_identity, _HttpAgent_fetch, _HttpAgent_fetchOptions, _HttpAgent_callOptions, _HttpAgent_timeDiffMsecs, _HttpAgent_credentials, _HttpAgent_rootKeyFetched, _HttpAgent_retryTimes, _HttpAgent_backoffStrategy, _HttpAgent_waterMark, _HttpAgent_queryPipeline, _HttpAgent_updatePipeline, _HttpAgent_subnetKeys, _HttpAgent_verifyQuerySignatures, _HttpAgent_requestAndRetryQuery, _HttpAgent_requestAndRetry, _HttpAgent_verifyQueryResponse;
var _HttpAgent_instances, _HttpAgent_identity, _HttpAgent_fetch, _HttpAgent_fetchOptions, _HttpAgent_callOptions, _HttpAgent_credentials, _HttpAgent_rootKeyFetched, _HttpAgent_retryTimes, _HttpAgent_backoffStrategy, _HttpAgent_waterMark, _HttpAgent_initialClientTime, _HttpAgent_initialReplicaTime, _HttpAgent_queryPipeline, _HttpAgent_updatePipeline, _HttpAgent_subnetKeys, _HttpAgent_verifyQuerySignatures, _HttpAgent_requestAndRetryQuery, _HttpAgent_requestAndRetry, _HttpAgent_verifyQueryResponse, _HttpAgent_handleReplicaTimeError;
import { Principal } from '@dfinity/principal';

@@ -22,3 +22,3 @@ import { AgentError } from '../../errors';

import { makeNonce, SubmitRequestType, } from './types';
import { AgentHTTPResponseError } from './errors';
import { AgentHTTPResponseError, ReplicaTimeError } from './errors';
import { request } from '../../canisterStatus';

@@ -32,2 +32,3 @@ import { CertificateVerificationError, LookupStatus, lookup_path, } from '../../certificate';

import { ExponentialBackoff } from '../../polling/backoff';
import { calculateReplicaTime } from './calculateReplicaTime';
export * from './transforms';

@@ -154,3 +155,2 @@ export { makeNonce } from './types';

_HttpAgent_instances.add(this);
this.rootKey = fromHex(IC_ROOT_KEY);
_HttpAgent_identity.set(this, void 0);

@@ -160,3 +160,2 @@ _HttpAgent_fetch.set(this, void 0);

_HttpAgent_callOptions.set(this, void 0);
_HttpAgent_timeDiffMsecs.set(this, 0);
_HttpAgent_credentials.set(this, void 0);

@@ -171,2 +170,5 @@ _HttpAgent_rootKeyFetched.set(this, false);

_HttpAgent_waterMark.set(this, 0);
// Manage the time offset between the client and the replica
_HttpAgent_initialClientTime.set(this, new Date(Date.now()));
_HttpAgent_initialReplicaTime.set(this, new Date(Date.now()));
this.log = new ObservableLog();

@@ -237,2 +239,11 @@ _HttpAgent_queryPipeline.set(this, []);

});
_HttpAgent_handleReplicaTimeError.set(this, (error) => {
const message = error.message;
if (message === null || message === void 0 ? void 0 : message.includes('ingress_expiry')) {
{
const replicaTime = calculateReplicaTime(message);
throw new ReplicaTimeError(message, replicaTime, this);
}
}
});
this.config = options;

@@ -242,2 +253,3 @@ __classPrivateFieldSet(this, _HttpAgent_fetch, options.fetch || getDefaultFetch() || fetch.bind(global), "f");

__classPrivateFieldSet(this, _HttpAgent_callOptions, options.callOptions, "f");
this.rootKey = options.rootKey ? options.rootKey : fromHex(IC_ROOT_KEY);
const host = determineHost(options.host);

@@ -289,2 +301,10 @@ this.host = new URL(host);

}
get replicaTime() {
const offset = Date.now() - __classPrivateFieldGet(this, _HttpAgent_initialClientTime, "f").getTime();
return new Date(__classPrivateFieldGet(this, _HttpAgent_initialReplicaTime, "f").getTime() + offset);
}
set replicaTime(replicaTime) {
__classPrivateFieldSet(this, _HttpAgent_initialClientTime, new Date(Date.now()), "f");
__classPrivateFieldSet(this, _HttpAgent_initialReplicaTime, replicaTime, "f");
}
get waterMark() {

@@ -348,2 +368,4 @@ return __classPrivateFieldGet(this, _HttpAgent_waterMark, "f");

async call(canisterId, options, identity) {
var _a;
const callSync = (_a = options.callSync) !== null && _a !== void 0 ? _a : true;
const id = await (identity !== undefined ? await identity : await __classPrivateFieldGet(this, _HttpAgent_identity, "f"));

@@ -360,4 +382,5 @@ if (!id) {

// If the value is off by more than 30 seconds, reconcile system time with the network
if (Math.abs(__classPrivateFieldGet(this, _HttpAgent_timeDiffMsecs, "f")) > 1000 * 30) {
ingress_expiry = new Expiry(DEFAULT_INGRESS_EXPIRY_DELTA_IN_MSECS + __classPrivateFieldGet(this, _HttpAgent_timeDiffMsecs, "f"));
const timeDiffMsecs = this.replicaTime && this.replicaTime.getTime() - Date.now();
if (Math.abs(timeDiffMsecs) > 1000 * 30) {
ingress_expiry = new Expiry(DEFAULT_INGRESS_EXPIRY_DELTA_IN_MSECS + timeDiffMsecs);
}

@@ -392,25 +415,51 @@ const submit = {

const body = cbor.encode(transformedRequest.body);
this.log.print(`fetching "/api/v2/canister/${ecid.toText()}/call" with request:`, transformedRequest);
// Run both in parallel. The fetch is quite expensive, so we have plenty of time to
// calculate the requestId locally.
const backoff = __classPrivateFieldGet(this, _HttpAgent_backoffStrategy, "f").call(this);
const request = __classPrivateFieldGet(this, _HttpAgent_instances, "m", _HttpAgent_requestAndRetry).call(this, {
request: () => __classPrivateFieldGet(this, _HttpAgent_fetch, "f").call(this, '' + new URL(`/api/v2/canister/${ecid.toText()}/call`, this.host), Object.assign(Object.assign(Object.assign({}, __classPrivateFieldGet(this, _HttpAgent_callOptions, "f")), transformedRequest.request), { body })),
backoff,
tries: 0,
});
const [response, requestId] = await Promise.all([request, requestIdOf(submit)]);
const responseBuffer = await response.arrayBuffer();
const responseBody = (response.status === 200 && responseBuffer.byteLength > 0 ? cbor.decode(responseBuffer) : null);
return {
requestId,
response: {
ok: response.ok,
status: response.status,
statusText: response.statusText,
body: responseBody,
headers: httpHeadersTransform(response.headers),
},
requestDetails: submit,
};
try {
// Attempt v3 sync call
const requestSync = () => {
this.log.print(`fetching "/api/v3/canister/${ecid.toText()}/call" with request:`, transformedRequest);
return __classPrivateFieldGet(this, _HttpAgent_fetch, "f").call(this, '' + new URL(`/api/v3/canister/${ecid.toText()}/call`, this.host), Object.assign(Object.assign(Object.assign({}, __classPrivateFieldGet(this, _HttpAgent_callOptions, "f")), transformedRequest.request), { body }));
};
const requestAsync = () => {
this.log.print(`fetching "/api/v2/canister/${ecid.toText()}/call" with request:`, transformedRequest);
return __classPrivateFieldGet(this, _HttpAgent_fetch, "f").call(this, '' + new URL(`/api/v2/canister/${ecid.toText()}/call`, this.host), Object.assign(Object.assign(Object.assign({}, __classPrivateFieldGet(this, _HttpAgent_callOptions, "f")), transformedRequest.request), { body }));
};
const request = __classPrivateFieldGet(this, _HttpAgent_instances, "m", _HttpAgent_requestAndRetry).call(this, {
request: callSync ? requestSync : requestAsync,
backoff,
tries: 0,
});
const [response, requestId] = await Promise.all([request, requestIdOf(submit)]);
const responseBuffer = await response.arrayBuffer();
const responseBody = (response.status === 200 && responseBuffer.byteLength > 0
? cbor.decode(responseBuffer)
: null);
// Update the watermark with the latest time from consensus
if (responseBody === null || responseBody === void 0 ? void 0 : responseBody.certificate) {
const time = await this.parseTimeFromResponse({ certificate: responseBody.certificate });
__classPrivateFieldSet(this, _HttpAgent_waterMark, time, "f");
}
return {
requestId,
response: {
ok: response.ok,
status: response.status,
statusText: response.statusText,
body: responseBody,
headers: httpHeadersTransform(response.headers),
},
requestDetails: submit,
};
}
catch (error) {
// If the error is due to the v3 api not being supported, fall back to v2
if (error.message.includes('v3 api not supported.')) {
this.log.warn('v3 api not supported. Fall back to v2');
return this.call(canisterId, Object.assign(Object.assign({}, options), {
// disable v3 api
callSync: false }), identity);
}
this.log.error('Error while making call:', error);
throw error;
}
}

@@ -431,2 +480,8 @@ async query(canisterId, fields, identity) {

const sender = (id === null || id === void 0 ? void 0 : id.getPrincipal()) || Principal.anonymous();
let ingress_expiry = new Expiry(DEFAULT_INGRESS_EXPIRY_DELTA_IN_MSECS);
// If the value is off by more than 30 seconds, reconcile system time with the network
const timeDiffMsecs = this.replicaTime && this.replicaTime.getTime() - Date.now();
if (Math.abs(timeDiffMsecs) > 1000 * 30) {
ingress_expiry = new Expiry(DEFAULT_INGRESS_EXPIRY_DELTA_IN_MSECS + timeDiffMsecs);
}
const request = {

@@ -438,3 +493,3 @@ request_type: "query" /* ReadRequestType.Query */,

sender,
ingress_expiry: new Expiry(DEFAULT_INGRESS_EXPIRY_DELTA_IN_MSECS),
ingress_expiry,
};

@@ -511,4 +566,8 @@ const requestId = await requestIdOf(request);

const sender = (id === null || id === void 0 ? void 0 : id.getPrincipal()) || Principal.anonymous();
// TODO: remove this any. This can be a Signed or UnSigned request.
// eslint-disable-next-line @typescript-eslint/no-explicit-any
let ingress_expiry = new Expiry(DEFAULT_INGRESS_EXPIRY_DELTA_IN_MSECS);
// If the value is off by more than 30 seconds, reconcile system time with the network
const timeDiffMsecs = this.replicaTime && this.replicaTime.getTime() - Date.now();
if (Math.abs(timeDiffMsecs) > 1000 * 30) {
ingress_expiry = new Expiry(DEFAULT_INGRESS_EXPIRY_DELTA_IN_MSECS + timeDiffMsecs);
}
const transformedRequest = await this._transform({

@@ -524,3 +583,3 @@ request: {

sender,
ingress_expiry: new Expiry(DEFAULT_INGRESS_EXPIRY_DELTA_IN_MSECS),
ingress_expiry,
},

@@ -540,20 +599,26 @@ });

const backoff = __classPrivateFieldGet(this, _HttpAgent_backoffStrategy, "f").call(this);
const response = await __classPrivateFieldGet(this, _HttpAgent_instances, "m", _HttpAgent_requestAndRetry).call(this, {
request: () => __classPrivateFieldGet(this, _HttpAgent_fetch, "f").call(this, '' + new URL(`/api/v2/canister/${canister.toString()}/read_state`, this.host), Object.assign(Object.assign(Object.assign({}, __classPrivateFieldGet(this, _HttpAgent_fetchOptions, "f")), transformedRequest.request), { body })),
backoff,
tries: 0,
});
if (!response.ok) {
throw new Error(`Server returned an error:\n` +
` Code: ${response.status} (${response.statusText})\n` +
` Body: ${await response.text()}\n`);
try {
const response = await __classPrivateFieldGet(this, _HttpAgent_instances, "m", _HttpAgent_requestAndRetry).call(this, {
request: () => __classPrivateFieldGet(this, _HttpAgent_fetch, "f").call(this, '' + new URL(`/api/v2/canister/${canister.toString()}/read_state`, this.host), Object.assign(Object.assign(Object.assign({}, __classPrivateFieldGet(this, _HttpAgent_fetchOptions, "f")), transformedRequest.request), { body })),
backoff,
tries: 0,
});
if (!response.ok) {
throw new Error(`Server returned an error:\n` +
` Code: ${response.status} (${response.statusText})\n` +
` Body: ${await response.text()}\n`);
}
const decodedResponse = cbor.decode(await response.arrayBuffer());
this.log.print('Read state response:', decodedResponse);
const parsedTime = await this.parseTimeFromResponse(decodedResponse);
if (parsedTime > 0) {
this.log.print('Read state response time:', parsedTime);
__classPrivateFieldSet(this, _HttpAgent_waterMark, parsedTime, "f");
}
return decodedResponse;
}
const decodedResponse = cbor.decode(await response.arrayBuffer());
this.log.print('Read state response:', decodedResponse);
const parsedTime = await this.parseTimeFromResponse(decodedResponse);
if (parsedTime > 0) {
this.log.print('Read state response time:', parsedTime);
__classPrivateFieldSet(this, _HttpAgent_waterMark, parsedTime, "f");
catch (error) {
__classPrivateFieldGet(this, _HttpAgent_handleReplicaTimeError, "f").call(this, error);
}
return decodedResponse;
throw new AgentError('Failed to read state');
}

@@ -590,6 +655,6 @@ async parseTimeFromResponse(response) {

* @param {Principal} canisterId - Pass a canister ID if you need to sync the time with a particular replica. Uses the management canister by default
* @throws {ReplicaTimeError} - this method is not guaranteed to work if the device's clock is off by more than 30 seconds. In such cases, the agent will throw an error.
*/
async syncTime(canisterId) {
const CanisterStatus = await import('../../canisterStatus');
const callTime = Date.now();
try {

@@ -607,3 +672,3 @@ if (!canisterId) {

if (replicaTime) {
__classPrivateFieldSet(this, _HttpAgent_timeDiffMsecs, Number(replicaTime) - Number(callTime), "f");
this.replicaTime = new Date(Number(replicaTime));
}

@@ -632,4 +697,5 @@ }

if (!__classPrivateFieldGet(this, _HttpAgent_rootKeyFetched, "f")) {
const status = await this.status();
// Hex-encoded version of the replica root key
this.rootKey = (await this.status()).root_key;
this.rootKey = status.root_key;
__classPrivateFieldSet(this, _HttpAgent_rootKeyFetched, true, "f");

@@ -675,3 +741,3 @@ }

}
_HttpAgent_identity = new WeakMap(), _HttpAgent_fetch = new WeakMap(), _HttpAgent_fetchOptions = new WeakMap(), _HttpAgent_callOptions = new WeakMap(), _HttpAgent_timeDiffMsecs = new WeakMap(), _HttpAgent_credentials = new WeakMap(), _HttpAgent_rootKeyFetched = new WeakMap(), _HttpAgent_retryTimes = new WeakMap(), _HttpAgent_backoffStrategy = new WeakMap(), _HttpAgent_waterMark = new WeakMap(), _HttpAgent_queryPipeline = new WeakMap(), _HttpAgent_updatePipeline = new WeakMap(), _HttpAgent_subnetKeys = new WeakMap(), _HttpAgent_verifyQuerySignatures = new WeakMap(), _HttpAgent_verifyQueryResponse = new WeakMap(), _HttpAgent_instances = new WeakSet(), _HttpAgent_requestAndRetryQuery = async function _HttpAgent_requestAndRetryQuery(args) {
_HttpAgent_identity = new WeakMap(), _HttpAgent_fetch = new WeakMap(), _HttpAgent_fetchOptions = new WeakMap(), _HttpAgent_callOptions = new WeakMap(), _HttpAgent_credentials = new WeakMap(), _HttpAgent_rootKeyFetched = new WeakMap(), _HttpAgent_retryTimes = new WeakMap(), _HttpAgent_backoffStrategy = new WeakMap(), _HttpAgent_waterMark = new WeakMap(), _HttpAgent_initialClientTime = new WeakMap(), _HttpAgent_initialReplicaTime = new WeakMap(), _HttpAgent_queryPipeline = new WeakMap(), _HttpAgent_updatePipeline = new WeakMap(), _HttpAgent_subnetKeys = new WeakMap(), _HttpAgent_verifyQuerySignatures = new WeakMap(), _HttpAgent_verifyQueryResponse = new WeakMap(), _HttpAgent_handleReplicaTimeError = new WeakMap(), _HttpAgent_instances = new WeakSet(), _HttpAgent_requestAndRetryQuery = async function _HttpAgent_requestAndRetryQuery(args) {
var _a, _b;

@@ -718,2 +784,4 @@ const { ecid, transformedRequest, body, requestId, backoff, tries } = args;

catch (error) {
this.log.error('Caught exception while attempting to read state', error);
__classPrivateFieldGet(this, _HttpAgent_handleReplicaTimeError, "f").call(this, error);
if (tries < __classPrivateFieldGet(this, _HttpAgent_retryTimes, "f")) {

@@ -784,5 +852,16 @@ this.log.warn(`Caught exception while attempting to make query:\n` +

const responseText = await response.clone().text();
if (response.status === 400 && responseText.includes('ingress_expiry')) {
__classPrivateFieldGet(this, _HttpAgent_handleReplicaTimeError, "f").call(this, new AgentError(responseText));
}
const errorMessage = `Server returned an error:\n` +
` Code: ${response.status} (${response.statusText})\n` +
` Body: ${responseText}\n`;
if (response.status === 404 && response.url.includes('api/v3')) {
throw new AgentHTTPResponseError('v3 api not supported. Fall back to v2', {
ok: response.ok,
status: response.status,
statusText: response.statusText,
headers: httpHeadersTransform(response.headers),
});
}
if (tries < __classPrivateFieldGet(this, _HttpAgent_retryTimes, "f")) {

@@ -789,0 +868,0 @@ return await __classPrivateFieldGet(this, _HttpAgent_instances, "m", _HttpAgent_requestAndRetry).call(this, { request, backoff, tries: tries + 1 });

@@ -75,6 +75,2 @@ /*

}),
load_snapshot: IDL.Record({
canister_version: IDL.Nat64,
taken_at_timestamp: IDL.Nat64,
}),
controllers_change: IDL.Record({

@@ -146,7 +142,2 @@ controllers: IDL.Vec(IDL.Principal),

const delete_canister_args = IDL.Record({ canister_id: canister_id });
const snapshot_id = IDL.Vec(IDL.Nat8);
const delete_canister_snapshot_args = IDL.Record({
canister_id: canister_id,
snapshot_id: snapshot_id,
});
const deposit_cycles_args = IDL.Record({ canister_id: canister_id });

@@ -224,16 +215,2 @@ const ecdsa_curve = IDL.Variant({ secp256k1: IDL.Null });

});
const list_canister_snapshots_args = IDL.Record({
canister_id: canister_id,
});
const snapshot = IDL.Record({
id: snapshot_id,
total_size: IDL.Nat64,
taken_at_timestamp: IDL.Nat64,
});
const list_canister_snapshots_result = IDL.Vec(snapshot);
const load_canister_snapshot_args = IDL.Record({
canister_id: canister_id,
sender_canister_version: IDL.Opt(IDL.Nat64),
snapshot_id: snapshot_id,
});
const node_metrics_history_args = IDL.Record({

@@ -266,2 +243,18 @@ start_at_timestamp_nanos: IDL.Nat64,

const raw_rand_result = IDL.Vec(IDL.Nat8);
const schnorr_algorithm = IDL.Variant({
ed25519: IDL.Null,
bip340secp256k1: IDL.Null,
});
const schnorr_public_key_args = IDL.Record({
key_id: IDL.Record({
algorithm: schnorr_algorithm,
name: IDL.Text,
}),
canister_id: IDL.Opt(canister_id),
derivation_path: IDL.Vec(IDL.Vec(IDL.Nat8)),
});
const schnorr_public_key_result = IDL.Record({
public_key: IDL.Vec(IDL.Nat8),
chain_code: IDL.Vec(IDL.Nat8),
});
const sign_with_ecdsa_args = IDL.Record({

@@ -275,2 +268,13 @@ key_id: IDL.Record({ name: IDL.Text, curve: ecdsa_curve }),

});
const sign_with_schnorr_args = IDL.Record({
key_id: IDL.Record({
algorithm: schnorr_algorithm,
name: IDL.Text,
}),
derivation_path: IDL.Vec(IDL.Vec(IDL.Nat8)),
message: IDL.Vec(IDL.Nat8),
});
const sign_with_schnorr_result = IDL.Record({
signature: IDL.Vec(IDL.Nat8),
});
const start_canister_args = IDL.Record({ canister_id: canister_id });

@@ -280,7 +284,2 @@ const stop_canister_args = IDL.Record({ canister_id: canister_id });

const stored_chunks_result = IDL.Vec(chunk_hash);
const take_canister_snapshot_args = IDL.Record({
replace_snapshot: IDL.Opt(snapshot_id),
canister_id: canister_id,
});
const take_canister_snapshot_result = snapshot;
const uninstall_code_args = IDL.Record({

@@ -310,3 +309,2 @@ canister_id: canister_id,

delete_canister: IDL.Func([delete_canister_args], [], []),
delete_canister_snapshot: IDL.Func([delete_canister_snapshot_args], [], []),
deposit_cycles: IDL.Func([deposit_cycles_args], [], []),

@@ -318,4 +316,2 @@ ecdsa_public_key: IDL.Func([ecdsa_public_key_args], [ecdsa_public_key_result], []),

install_code: IDL.Func([install_code_args], [], []),
list_canister_snapshots: IDL.Func([list_canister_snapshots_args], [list_canister_snapshots_result], []),
load_canister_snapshot: IDL.Func([load_canister_snapshot_args], [], []),
node_metrics_history: IDL.Func([node_metrics_history_args], [node_metrics_history_result], []),

@@ -325,7 +321,8 @@ provisional_create_canister_with_cycles: IDL.Func([provisional_create_canister_with_cycles_args], [provisional_create_canister_with_cycles_result], []),

raw_rand: IDL.Func([], [raw_rand_result], []),
schnorr_public_key: IDL.Func([schnorr_public_key_args], [schnorr_public_key_result], []),
sign_with_ecdsa: IDL.Func([sign_with_ecdsa_args], [sign_with_ecdsa_result], []),
sign_with_schnorr: IDL.Func([sign_with_schnorr_args], [sign_with_schnorr_result], []),
start_canister: IDL.Func([start_canister_args], [], []),
stop_canister: IDL.Func([stop_canister_args], [], []),
stored_chunks: IDL.Func([stored_chunks_args], [stored_chunks_result], []),
take_canister_snapshot: IDL.Func([take_canister_snapshot_args], [take_canister_snapshot_result], []),
uninstall_code: IDL.Func([uninstall_code_args], [], []),

@@ -332,0 +329,0 @@ update_settings: IDL.Func([update_settings_args], [], []),

@@ -127,7 +127,2 @@ import type { Principal } from '@dfinity/principal';

} | {
load_snapshot: {
canister_version: bigint;
taken_at_timestamp: bigint;
};
} | {
controllers_change: {

@@ -174,6 +169,2 @@ controllers: Array<Principal>;

}
export interface delete_canister_snapshot_args {
canister_id: canister_id;
snapshot_id: snapshot_id;
}
export interface deposit_cycles_args {

@@ -245,11 +236,2 @@ canister_id: canister_id;

}
export interface list_canister_snapshots_args {
canister_id: canister_id;
}
export declare type list_canister_snapshots_result = Array<snapshot>;
export interface load_canister_snapshot_args {
canister_id: canister_id;
sender_canister_version: [] | [bigint];
snapshot_id: snapshot_id;
}
export declare type log_visibility = {

@@ -293,2 +275,19 @@ controllers: null;

export declare type satoshi = bigint;
export declare type schnorr_algorithm = {
ed25519: null;
} | {
bip340secp256k1: null;
};
export interface schnorr_public_key_args {
key_id: {
algorithm: schnorr_algorithm;
name: string;
};
canister_id: [] | [canister_id];
derivation_path: Array<Uint8Array | number[]>;
}
export interface schnorr_public_key_result {
public_key: Uint8Array | number[];
chain_code: Uint8Array | number[];
}
export interface sign_with_ecdsa_args {

@@ -305,8 +304,13 @@ key_id: {

}
export interface snapshot {
id: snapshot_id;
total_size: bigint;
taken_at_timestamp: bigint;
export interface sign_with_schnorr_args {
key_id: {
algorithm: schnorr_algorithm;
name: string;
};
derivation_path: Array<Uint8Array | number[]>;
message: Uint8Array | number[];
}
export declare type snapshot_id = Uint8Array | number[];
export interface sign_with_schnorr_result {
signature: Uint8Array | number[];
}
export interface start_canister_args {

@@ -322,7 +326,2 @@ canister_id: canister_id;

export declare type stored_chunks_result = Array<chunk_hash>;
export interface take_canister_snapshot_args {
replace_snapshot: [] | [snapshot_id];
canister_id: canister_id;
}
export declare type take_canister_snapshot_result = snapshot;
export interface uninstall_code_args {

@@ -360,3 +359,2 @@ canister_id: canister_id;

delete_canister: ActorMethod<[delete_canister_args], undefined>;
delete_canister_snapshot: ActorMethod<[delete_canister_snapshot_args], undefined>;
deposit_cycles: ActorMethod<[deposit_cycles_args], undefined>;

@@ -368,6 +366,2 @@ ecdsa_public_key: ActorMethod<[ecdsa_public_key_args], ecdsa_public_key_result>;

install_code: ActorMethod<[install_code_args], undefined>;
list_canister_snapshots: ActorMethod<[
list_canister_snapshots_args
], list_canister_snapshots_result>;
load_canister_snapshot: ActorMethod<[load_canister_snapshot_args], undefined>;
node_metrics_history: ActorMethod<[node_metrics_history_args], node_metrics_history_result>;

@@ -379,7 +373,8 @@ provisional_create_canister_with_cycles: ActorMethod<[

raw_rand: ActorMethod<[], raw_rand_result>;
schnorr_public_key: ActorMethod<[schnorr_public_key_args], schnorr_public_key_result>;
sign_with_ecdsa: ActorMethod<[sign_with_ecdsa_args], sign_with_ecdsa_result>;
sign_with_schnorr: ActorMethod<[sign_with_schnorr_args], sign_with_schnorr_result>;
start_canister: ActorMethod<[start_canister_args], undefined>;
stop_canister: ActorMethod<[stop_canister_args], undefined>;
stored_chunks: ActorMethod<[stored_chunks_args], stored_chunks_result>;
take_canister_snapshot: ActorMethod<[take_canister_snapshot_args], take_canister_snapshot_result>;
uninstall_code: ActorMethod<[uninstall_code_args], undefined>;

@@ -386,0 +381,0 @@ update_settings: ActorMethod<[update_settings_args], undefined>;

@@ -53,2 +53,3 @@ /** @module CanisterStatus */

});
const certTime = agent.replicaTime ? agent.replicaTime : undefined;
const cert = await Certificate.create({

@@ -58,2 +59,3 @@ certificate: response.certificate,

canisterId: canisterId,
certTime,
});

@@ -60,0 +62,0 @@ const lookup = (cert, path) => {

@@ -25,3 +25,3 @@ import { AgentError } from './errors';

* Make a human readable string out of a hash tree.
* @param tree
* @param tree - the tree to stringify
*/

@@ -50,3 +50,3 @@ export declare function hashTreeToString(tree: HashTree): string;

/**
* BLS Verification strategy. Default strategy uses wasm for performance, but that may not be available in all contexts.
* BLS Verification strategy. Default strategy uses bls12_381 from @noble/curves
*/

@@ -61,4 +61,9 @@ blsVerify?: VerifyFunc;

maxAgeInMinutes?: number;
/**
* For comparing the time of the certificate to an expected date instead of the result of Date.now.
*/
certTime?: Date;
}
export declare class Certificate {
#private;
private _rootKey;

@@ -68,3 +73,3 @@ private _canisterId;

private _maxAgeInMinutes;
private readonly cert;
cert: Cert;
/**

@@ -96,3 +101,3 @@ * Create a new instance of a certificate, automatically verifying it. Throws a

/**
* @param t
* @param t - the tree to reconstruct
*/

@@ -127,2 +132,8 @@ export declare function reconstruct(t: HashTree): Promise<ArrayBuffer>;

declare type LabelLookupResult = LookupResult | LookupResultGreater | LookupResultLess;
/**
* Lookup a path in a tree
* @param path - the path to look up
* @param tree - the tree to search
* @returns LookupResult
*/
export declare function lookup_path(path: Array<ArrayBuffer | string>, tree: HashTree): LookupResult;

@@ -135,8 +146,16 @@ /**

export declare function flatten_forks(t: HashTree): HashTree[];
/**
* Find a label in a tree
* @param label - the label to find
* @param tree - the tree to search
* @returns LabelLookupResult
*/
export declare function find_label(label: ArrayBuffer, tree: HashTree): LabelLookupResult;
/**
* Check if a canister falls within a range of canisters
* @param canisterId Principal
* @param ranges [Principal, Principal][]
* @returns
* @param params - the parameters to check
* @param params.canisterId Principal
* @param params.subnetId Principal
* @param params.tree HashTree
* @returns boolean
*/

@@ -143,0 +162,0 @@ export declare function check_canister_ranges(params: {

@@ -0,1 +1,13 @@

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 _Certificate_certTime;
import * as cbor from './cbor';

@@ -26,3 +38,3 @@ import { AgentError } from './errors';

* Make a human readable string out of a hash tree.
* @param tree
* @param tree - the tree to stringify
*/

@@ -39,3 +51,3 @@ export function hashTreeToString(tree) {

}
catch (e) {
catch (_a) {
return `data(...${label.byteLength} bytes)`;

@@ -103,3 +115,3 @@ }

// Default to 5 minutes
_maxAgeInMinutes = 5) {
_maxAgeInMinutes = 5, certTime) {
this._rootKey = _rootKey;

@@ -109,3 +121,5 @@ this._canisterId = _canisterId;

this._maxAgeInMinutes = _maxAgeInMinutes;
_Certificate_certTime.set(this, void 0);
this.cert = cbor.decode(new Uint8Array(certificate));
__classPrivateFieldSet(this, _Certificate_certTime, certTime, "f");
}

@@ -133,3 +147,3 @@ /**

}
return new Certificate(options.certificate, options.rootKey, options.canisterId, blsVerify, options.maxAgeInMinutes);
return new Certificate(options.certificate, options.rootKey, options.canisterId, blsVerify, options.maxAgeInMinutes, options.certTime);
}

@@ -158,4 +172,6 @@ lookup(path) {

const now = Date.now();
const earliestCertificateTime = now - MAX_AGE_IN_MSEC;
const fiveMinutesFromNow = now + FIVE_MINUTES_IN_MSEC;
// Use a provided time in case `Date.now()` is inaccurate
const compareTime = __classPrivateFieldGet(this, _Certificate_certTime, "f") || new Date(now);
const earliestCertificateTime = compareTime.getTime() - MAX_AGE_IN_MSEC;
const fiveMinutesFromNow = compareTime.getTime() + FIVE_MINUTES_IN_MSEC;
const certTime = decodeTime(lookupTime);

@@ -166,3 +182,3 @@ if (certTime.getTime() < earliestCertificateTime) {

' Current time: ' +
new Date(now).toISOString());
compareTime.toISOString());
}

@@ -173,3 +189,3 @@ else if (certTime.getTime() > fiveMinutesFromNow) {

' Current time: ' +
new Date(now).toISOString());
compareTime.toISOString());
}

@@ -179,3 +195,3 @@ try {

}
catch (err) {
catch (_a) {
sigVer = false;

@@ -196,2 +212,3 @@ }

blsVerify: this._blsVerify,
certTime: __classPrivateFieldGet(this, _Certificate_certTime, "f"),
// Do not check max age for delegation certificates

@@ -219,2 +236,3 @@ maxAgeInMinutes: Infinity,

}
_Certificate_certTime = new WeakMap();
const DER_PREFIX = fromHex('308182301d060d2b0601040182dc7c0503010201060c2b0601040182dc7c05030201036100');

@@ -251,3 +269,3 @@ const KEY_LENGTH = 96;

/**
* @param t
* @param t - the tree to reconstruct
*/

@@ -286,2 +304,8 @@ export async function reconstruct(t) {

})(LabelLookupStatus || (LabelLookupStatus = {}));
/**
* Lookup a path in a tree
* @param path - the path to look up
* @param tree - the tree to search
* @returns LookupResult
*/
export function lookup_path(path, tree) {

@@ -351,2 +375,8 @@ if (path.length === 0) {

}
/**
* Find a label in a tree
* @param label - the label to find
* @param tree - the tree to search
* @returns LabelLookupResult
*/
export function find_label(label, tree) {

@@ -381,2 +411,3 @@ switch (tree[0]) {

// search in the left node
// eslint-disable-next-line no-case-declarations
const leftLookupResult = find_label(label, tree[1]);

@@ -402,3 +433,3 @@ switch (leftLookupResult.status) {

case LookupStatus.Unknown: {
let rightLookupResult = find_label(label, tree[2]);
const rightLookupResult = find_label(label, tree[2]);
// if the label we're searching for is less than the right node lookup,

@@ -439,5 +470,7 @@ // then we also need to return an uncertain result

* Check if a canister falls within a range of canisters
* @param canisterId Principal
* @param ranges [Principal, Principal][]
* @returns
* @param params - the parameters to check
* @param params.canisterId Principal
* @param params.subnetId Principal
* @param params.tree HashTree
* @returns boolean
*/

@@ -444,0 +477,0 @@ export function check_canister_ranges(params) {

@@ -28,2 +28,3 @@ import { ActorSubclass } from './actor';

export * as Cbor from './cbor';
export * from './polling';
export interface GlobalInternetComputer {

@@ -30,0 +31,0 @@ ic: {

@@ -18,2 +18,3 @@ export * from './actor';

export * as Cbor from './cbor';
export * from './polling';
//# sourceMappingURL=index.js.map

@@ -19,5 +19,5 @@ import { Principal } from '@dfinity/principal';

*/
export declare function pollForResponse(agent: Agent, canisterId: Principal, requestId: RequestId, strategy: PollStrategy, request?: any, blsVerify?: CreateCertificateOptions['blsVerify']): Promise<{
export declare function pollForResponse(agent: Agent, canisterId: Principal, requestId: RequestId, strategy?: PollStrategy, request?: any, blsVerify?: CreateCertificateOptions['blsVerify']): Promise<{
certificate: Certificate;
reply: ArrayBuffer;
}>;

@@ -5,2 +5,3 @@ import { RequestStatusResponseStatus } from '../agent';

export * as strategy from './strategy';
import { defaultStrategy } from './strategy';
export { defaultStrategy } from './strategy';

@@ -17,3 +18,3 @@ /**

*/
export async function pollForResponse(agent, canisterId, requestId, strategy,
export async function pollForResponse(agent, canisterId, requestId, strategy = defaultStrategy(),
// eslint-disable-next-line

@@ -27,2 +28,6 @@ request, blsVerify) {

throw new Error('Agent root key not initialized before polling');
// if agent has replicaTime, otherwise omit
const certTime = (agent === null || agent === void 0 ? void 0 : agent.replicaTime)
? agent === null || agent === void 0 ? void 0 : agent.replicaTime
: undefined;
const cert = await Certificate.create({

@@ -32,2 +37,3 @@ certificate: state.certificate,

canisterId: canisterId,
certTime: certTime,
blsVerify,

@@ -56,3 +62,3 @@ });

await strategy(canisterId, requestId, status);
return pollForResponse(agent, canisterId, requestId, strategy, currentRequest);
return pollForResponse(agent, canisterId, requestId, strategy, currentRequest, blsVerify);
case RequestStatusResponseStatus.Rejected: {

@@ -59,0 +65,0 @@ const rejectCode = new Uint8Array(lookupResultToBuffer(cert.lookup([...path, 'reject_code'])))[0];

{
"name": "@dfinity/agent",
"version": "2.0.1-beta.0",
"version": "2.1.0",
"author": "DFINITY Stiftung <sdk@dfinity.org>",

@@ -50,4 +50,4 @@ "license": "Apache-2.0",

"peerDependencies": {
"@dfinity/candid": "^2.0.1-beta.0",
"@dfinity/principal": "^2.0.1-beta.0"
"@dfinity/candid": "^2.1.0",
"@dfinity/principal": "^2.1.0"
},

@@ -54,0 +54,0 @@ "dependencies": {

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc