@dfinity/agent
Advanced tools
Comparing version 0.13.2 to 0.13.3
@@ -7,2 +7,3 @@ import { Agent, QueryResponseRejected, SubmitResponse } from './agent'; | ||
import { RequestId } from './request_id'; | ||
import { CreateCertificateOptions } from './certificate'; | ||
export declare class ActorCallError extends AgentError { | ||
@@ -63,2 +64,6 @@ readonly canisterId: Principal; | ||
queryTransform?(methodName: string, args: unknown[], callConfig: CallConfig): Partial<CallConfig> | void; | ||
/** | ||
* Polyfill for BLS Certificate verification in case wasm is not supported | ||
*/ | ||
blsVerify?: CreateCertificateOptions['blsVerify']; | ||
} | ||
@@ -65,0 +70,0 @@ /** |
@@ -124,3 +124,3 @@ "use strict"; | ||
for (const [methodName, func] of service._fields) { | ||
this[methodName] = _createActorMethod(this, methodName, func); | ||
this[methodName] = _createActorMethod(this, methodName, func, config.blsVerify); | ||
} | ||
@@ -153,3 +153,3 @@ } | ||
}; | ||
function _createActorMethod(actor, methodName, func) { | ||
function _createActorMethod(actor, methodName, func, blsVerify) { | ||
let caller; | ||
@@ -192,3 +192,3 @@ if (func.annotations.includes('query')) { | ||
const pollStrategy = pollingStrategyFactory(); | ||
const responseBytes = await (0, polling_1.pollForResponse)(agent, ecid, requestId, pollStrategy); | ||
const responseBytes = await (0, polling_1.pollForResponse)(agent, ecid, requestId, pollStrategy, blsVerify); | ||
if (responseBytes !== undefined) { | ||
@@ -195,0 +195,0 @@ return decodeReturnValue(func.retTypes, responseBytes); |
@@ -49,2 +49,3 @@ import { JsonObject } from '@dfinity/candid'; | ||
private readonly _fetch; | ||
private _timeDiffMsecs; | ||
private readonly _host; | ||
@@ -64,2 +65,7 @@ private readonly _credentials; | ||
readState(canisterId: Principal | string, fields: ReadStateOptions, identity?: Identity | Promise<Identity>, request?: any): Promise<ReadStateResponse>; | ||
/** | ||
* Allows agent to sync its time with the network. Can be called during intialization or mid-lifecycle if the device's clock has drifted away from the network time. This is necessary to set the Expiry for a request | ||
* @param {PrincipalLike} canisterId - Pass a canister ID if you need to sync the time with a particular replica. Uses the management canister by default | ||
*/ | ||
syncTime(canisterId?: Principal): Promise<void>; | ||
status(): Promise<JsonObject>; | ||
@@ -66,0 +72,0 @@ fetchRootKey(): Promise<ArrayBuffer>; |
@@ -116,2 +116,3 @@ "use strict"; | ||
this._pipeline = []; | ||
this._timeDiffMsecs = 0; | ||
this._rootKeyFetched = false; | ||
@@ -185,2 +186,7 @@ if (options.source) { | ||
const sender = 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 | ||
if (Math.abs(this._timeDiffMsecs) > 1000 * 30) { | ||
ingress_expiry = new transforms_1.Expiry(DEFAULT_INGRESS_EXPIRY_DELTA_IN_MSECS + this._timeDiffMsecs); | ||
} | ||
const submit = { | ||
@@ -192,3 +198,3 @@ request_type: types_1.SubmitRequestType.Call, | ||
sender, | ||
ingress_expiry: new transforms_1.Expiry(DEFAULT_INGRESS_EXPIRY_DELTA_IN_MSECS), | ||
ingress_expiry, | ||
}; | ||
@@ -302,2 +308,28 @@ // eslint-disable-next-line @typescript-eslint/no-explicit-any | ||
} | ||
/** | ||
* Allows agent to sync its time with the network. Can be called during intialization or mid-lifecycle if the device's clock has drifted away from the network time. This is necessary to set the Expiry for a request | ||
* @param {PrincipalLike} canisterId - Pass a canister ID if you need to sync the time with a particular replica. Uses the management canister by default | ||
*/ | ||
async syncTime(canisterId) { | ||
const CanisterStatus = await Promise.resolve().then(() => __importStar(require('../../canisterStatus'))); | ||
const callTime = Date.now(); | ||
try { | ||
if (!canisterId) { | ||
console.log('Syncing time with the IC. No canisterId provided, so falling back to ryjl3-tyaaa-aaaaa-aaaba-cai'); | ||
} | ||
const status = await CanisterStatus.request({ | ||
// Fall back with canisterId of the ICP Ledger | ||
canisterId: canisterId !== null && canisterId !== void 0 ? canisterId : principal_1.Principal.from('ryjl3-tyaaa-aaaaa-aaaba-cai'), | ||
agent: this, | ||
paths: ['time'], | ||
}); | ||
const replicaTime = status.get('time'); | ||
if (replicaTime) { | ||
this._timeDiffMsecs = Number(replicaTime) - Number(callTime); | ||
} | ||
} | ||
catch (error) { | ||
console.error('Caught exception while attempting to sync time:', error); | ||
} | ||
} | ||
async status() { | ||
@@ -304,0 +336,0 @@ const headers = this._credentials |
/** @module CanisterStatus */ | ||
import { Principal } from '@dfinity/principal'; | ||
import { HttpAgent } from '..'; | ||
import type { CreateCertificateOptions } from '..'; | ||
/** | ||
@@ -37,2 +38,3 @@ * Types of an entry on the canisterStatus map. | ||
paths?: Path[] | Set<Path>; | ||
blsVerify?: CreateCertificateOptions['blsVerify']; | ||
}; | ||
@@ -39,0 +41,0 @@ /** |
@@ -22,2 +22,3 @@ import { AgentError } from './errors'; | ||
export declare function hashTreeToString(tree: HashTree): string; | ||
declare type VerifyFunc = (pk: Uint8Array, sig: Uint8Array, msg: Uint8Array) => Promise<boolean>; | ||
export interface CreateCertificateOptions { | ||
@@ -38,2 +39,6 @@ /** | ||
canisterId: Principal; | ||
/** | ||
* BLS Verification strategy. Default strategy uses wasm for performance, but that may not be available in all contexts. | ||
*/ | ||
blsVerify?: VerifyFunc; | ||
} | ||
@@ -43,2 +48,3 @@ export declare class Certificate { | ||
private _canisterId; | ||
private _blsVerify; | ||
private readonly cert; | ||
@@ -45,0 +51,0 @@ /** |
@@ -30,5 +30,5 @@ "use strict"; | ||
const request_id_1 = require("./request_id"); | ||
const bls_1 = require("./utils/bls"); | ||
const buffer_1 = require("./utils/buffer"); | ||
const principal_1 = require("@dfinity/principal"); | ||
const bls = __importStar(require("./utils/bls")); | ||
/** | ||
@@ -100,5 +100,6 @@ * A certificate may fail verification with respect to the provided public key | ||
class Certificate { | ||
constructor(certificate, _rootKey, _canisterId) { | ||
constructor(certificate, _rootKey, _canisterId, _blsVerify) { | ||
this._rootKey = _rootKey; | ||
this._canisterId = _canisterId; | ||
this._blsVerify = _blsVerify; | ||
this.cert = cbor.decode(new Uint8Array(certificate)); | ||
@@ -118,3 +119,7 @@ } | ||
static async create(options) { | ||
const cert = new Certificate(options.certificate, options.rootKey, options.canisterId); | ||
let blsVerify = options.blsVerify; | ||
if (!blsVerify) { | ||
blsVerify = bls.blsVerify; | ||
} | ||
const cert = new Certificate(options.certificate, options.rootKey, options.canisterId, blsVerify); | ||
await cert.verify(); | ||
@@ -134,3 +139,3 @@ return cert; | ||
try { | ||
sigVer = await (0, bls_1.blsVerify)(new Uint8Array(key), new Uint8Array(sig), new Uint8Array(msg)); | ||
sigVer = await this._blsVerify(new Uint8Array(key), new Uint8Array(sig), new Uint8Array(msg)); | ||
} | ||
@@ -137,0 +142,0 @@ catch (err) { |
import { Principal } from '@dfinity/principal'; | ||
import { Agent, RequestStatusResponseStatus } from '../agent'; | ||
import { CreateCertificateOptions } from '../certificate'; | ||
import { RequestId } from '../request_id'; | ||
@@ -17,2 +18,2 @@ export * as strategy from './strategy'; | ||
*/ | ||
export declare function pollForResponse(agent: Agent, canisterId: Principal, requestId: RequestId, strategy: PollStrategy, request?: any): Promise<ArrayBuffer>; | ||
export declare function pollForResponse(agent: Agent, canisterId: Principal, requestId: RequestId, strategy: PollStrategy, request?: any, blsVerify?: CreateCertificateOptions['blsVerify']): Promise<ArrayBuffer>; |
@@ -44,3 +44,3 @@ "use strict"; | ||
// eslint-disable-next-line | ||
request) { | ||
request, blsVerify) { | ||
var _a; | ||
@@ -56,2 +56,3 @@ const path = [new TextEncoder().encode('request_status'), requestId]; | ||
canisterId: canisterId, | ||
blsVerify, | ||
}); | ||
@@ -58,0 +59,0 @@ const maybeBuf = cert.lookup([...path, new TextEncoder().encode('status')]); |
@@ -7,2 +7,3 @@ import { Agent, QueryResponseRejected, SubmitResponse } from './agent'; | ||
import { RequestId } from './request_id'; | ||
import { CreateCertificateOptions } from './certificate'; | ||
export declare class ActorCallError extends AgentError { | ||
@@ -63,2 +64,6 @@ readonly canisterId: Principal; | ||
queryTransform?(methodName: string, args: unknown[], callConfig: CallConfig): Partial<CallConfig> | void; | ||
/** | ||
* Polyfill for BLS Certificate verification in case wasm is not supported | ||
*/ | ||
blsVerify?: CreateCertificateOptions['blsVerify']; | ||
} | ||
@@ -65,0 +70,0 @@ /** |
@@ -118,3 +118,3 @@ import { Buffer } from 'buffer/'; | ||
for (const [methodName, func] of service._fields) { | ||
this[methodName] = _createActorMethod(this, methodName, func); | ||
this[methodName] = _createActorMethod(this, methodName, func, config.blsVerify); | ||
} | ||
@@ -146,3 +146,3 @@ } | ||
}; | ||
function _createActorMethod(actor, methodName, func) { | ||
function _createActorMethod(actor, methodName, func, blsVerify) { | ||
let caller; | ||
@@ -185,3 +185,3 @@ if (func.annotations.includes('query')) { | ||
const pollStrategy = pollingStrategyFactory(); | ||
const responseBytes = await pollForResponse(agent, ecid, requestId, pollStrategy); | ||
const responseBytes = await pollForResponse(agent, ecid, requestId, pollStrategy, blsVerify); | ||
if (responseBytes !== undefined) { | ||
@@ -188,0 +188,0 @@ return decodeReturnValue(func.retTypes, responseBytes); |
@@ -49,2 +49,3 @@ import { JsonObject } from '@dfinity/candid'; | ||
private readonly _fetch; | ||
private _timeDiffMsecs; | ||
private readonly _host; | ||
@@ -64,2 +65,7 @@ private readonly _credentials; | ||
readState(canisterId: Principal | string, fields: ReadStateOptions, identity?: Identity | Promise<Identity>, request?: any): Promise<ReadStateResponse>; | ||
/** | ||
* Allows agent to sync its time with the network. Can be called during intialization or mid-lifecycle if the device's clock has drifted away from the network time. This is necessary to set the Expiry for a request | ||
* @param {PrincipalLike} canisterId - Pass a canister ID if you need to sync the time with a particular replica. Uses the management canister by default | ||
*/ | ||
syncTime(canisterId?: Principal): Promise<void>; | ||
status(): Promise<JsonObject>; | ||
@@ -66,0 +72,0 @@ fetchRootKey(): Promise<ArrayBuffer>; |
@@ -85,2 +85,3 @@ import { Principal } from '@dfinity/principal'; | ||
this._pipeline = []; | ||
this._timeDiffMsecs = 0; | ||
this._rootKeyFetched = false; | ||
@@ -154,2 +155,7 @@ if (options.source) { | ||
const sender = 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 | ||
if (Math.abs(this._timeDiffMsecs) > 1000 * 30) { | ||
ingress_expiry = new Expiry(DEFAULT_INGRESS_EXPIRY_DELTA_IN_MSECS + this._timeDiffMsecs); | ||
} | ||
const submit = { | ||
@@ -161,3 +167,3 @@ request_type: SubmitRequestType.Call, | ||
sender, | ||
ingress_expiry: new Expiry(DEFAULT_INGRESS_EXPIRY_DELTA_IN_MSECS), | ||
ingress_expiry, | ||
}; | ||
@@ -271,2 +277,28 @@ // eslint-disable-next-line @typescript-eslint/no-explicit-any | ||
} | ||
/** | ||
* Allows agent to sync its time with the network. Can be called during intialization or mid-lifecycle if the device's clock has drifted away from the network time. This is necessary to set the Expiry for a request | ||
* @param {PrincipalLike} canisterId - Pass a canister ID if you need to sync the time with a particular replica. Uses the management canister by default | ||
*/ | ||
async syncTime(canisterId) { | ||
const CanisterStatus = await import('../../canisterStatus'); | ||
const callTime = Date.now(); | ||
try { | ||
if (!canisterId) { | ||
console.log('Syncing time with the IC. No canisterId provided, so falling back to ryjl3-tyaaa-aaaaa-aaaba-cai'); | ||
} | ||
const status = await CanisterStatus.request({ | ||
// Fall back with canisterId of the ICP Ledger | ||
canisterId: canisterId !== null && canisterId !== void 0 ? canisterId : Principal.from('ryjl3-tyaaa-aaaaa-aaaba-cai'), | ||
agent: this, | ||
paths: ['time'], | ||
}); | ||
const replicaTime = status.get('time'); | ||
if (replicaTime) { | ||
this._timeDiffMsecs = Number(replicaTime) - Number(callTime); | ||
} | ||
} | ||
catch (error) { | ||
console.error('Caught exception while attempting to sync time:', error); | ||
} | ||
} | ||
async status() { | ||
@@ -273,0 +305,0 @@ const headers = this._credentials |
/** @module CanisterStatus */ | ||
import { Principal } from '@dfinity/principal'; | ||
import { HttpAgent } from '..'; | ||
import type { CreateCertificateOptions } from '..'; | ||
/** | ||
@@ -37,2 +38,3 @@ * Types of an entry on the canisterStatus map. | ||
paths?: Path[] | Set<Path>; | ||
blsVerify?: CreateCertificateOptions['blsVerify']; | ||
}; | ||
@@ -39,0 +41,0 @@ /** |
@@ -22,2 +22,3 @@ import { AgentError } from './errors'; | ||
export declare function hashTreeToString(tree: HashTree): string; | ||
declare type VerifyFunc = (pk: Uint8Array, sig: Uint8Array, msg: Uint8Array) => Promise<boolean>; | ||
export interface CreateCertificateOptions { | ||
@@ -38,2 +39,6 @@ /** | ||
canisterId: Principal; | ||
/** | ||
* BLS Verification strategy. Default strategy uses wasm for performance, but that may not be available in all contexts. | ||
*/ | ||
blsVerify?: VerifyFunc; | ||
} | ||
@@ -43,2 +48,3 @@ export declare class Certificate { | ||
private _canisterId; | ||
private _blsVerify; | ||
private readonly cert; | ||
@@ -45,0 +51,0 @@ /** |
import * as cbor from './cbor'; | ||
import { AgentError } from './errors'; | ||
import { hash } from './request_id'; | ||
import { blsVerify } from './utils/bls'; | ||
import { concat, fromHex, toHex } from './utils/buffer'; | ||
import { Principal } from '@dfinity/principal'; | ||
import * as bls from './utils/bls'; | ||
/** | ||
@@ -71,5 +71,6 @@ * A certificate may fail verification with respect to the provided public key | ||
export class Certificate { | ||
constructor(certificate, _rootKey, _canisterId) { | ||
constructor(certificate, _rootKey, _canisterId, _blsVerify) { | ||
this._rootKey = _rootKey; | ||
this._canisterId = _canisterId; | ||
this._blsVerify = _blsVerify; | ||
this.cert = cbor.decode(new Uint8Array(certificate)); | ||
@@ -89,3 +90,7 @@ } | ||
static async create(options) { | ||
const cert = new Certificate(options.certificate, options.rootKey, options.canisterId); | ||
let blsVerify = options.blsVerify; | ||
if (!blsVerify) { | ||
blsVerify = bls.blsVerify; | ||
} | ||
const cert = new Certificate(options.certificate, options.rootKey, options.canisterId, blsVerify); | ||
await cert.verify(); | ||
@@ -105,3 +110,3 @@ return cert; | ||
try { | ||
sigVer = await blsVerify(new Uint8Array(key), new Uint8Array(sig), new Uint8Array(msg)); | ||
sigVer = await this._blsVerify(new Uint8Array(key), new Uint8Array(sig), new Uint8Array(msg)); | ||
} | ||
@@ -108,0 +113,0 @@ catch (err) { |
import { Principal } from '@dfinity/principal'; | ||
import { Agent, RequestStatusResponseStatus } from '../agent'; | ||
import { CreateCertificateOptions } from '../certificate'; | ||
import { RequestId } from '../request_id'; | ||
@@ -17,2 +18,2 @@ export * as strategy from './strategy'; | ||
*/ | ||
export declare function pollForResponse(agent: Agent, canisterId: Principal, requestId: RequestId, strategy: PollStrategy, request?: any): Promise<ArrayBuffer>; | ||
export declare function pollForResponse(agent: Agent, canisterId: Principal, requestId: RequestId, strategy: PollStrategy, request?: any, blsVerify?: CreateCertificateOptions['blsVerify']): Promise<ArrayBuffer>; |
@@ -17,3 +17,3 @@ import { RequestStatusResponseStatus } from '../agent'; | ||
// eslint-disable-next-line | ||
request) { | ||
request, blsVerify) { | ||
var _a; | ||
@@ -29,2 +29,3 @@ const path = [new TextEncoder().encode('request_status'), requestId]; | ||
canisterId: canisterId, | ||
blsVerify, | ||
}); | ||
@@ -31,0 +32,0 @@ const maybeBuf = cert.lookup([...path, new TextEncoder().encode('status')]); |
{ | ||
"name": "@dfinity/agent", | ||
"version": "0.13.2", | ||
"version": "0.13.3", | ||
"author": "DFINITY Stiftung <sdk@dfinity.org>", | ||
@@ -52,4 +52,4 @@ "license": "Apache-2.0", | ||
"peerDependencies": { | ||
"@dfinity/candid": "^0.13.2", | ||
"@dfinity/principal": "^0.13.2" | ||
"@dfinity/candid": "^0.13.3", | ||
"@dfinity/principal": "^0.13.3" | ||
}, | ||
@@ -79,6 +79,3 @@ "dependencies": { | ||
"whatwg-fetch": "^3.0.0" | ||
}, | ||
"jest": { | ||
"preset": "ts-jest" | ||
} | ||
} |
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
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
1022337
7471