Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions cli/api/actors.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import {Actor, HttpAgent, Identity} from '@dfinity/agent';
import {Principal} from '@dfinity/principal';
import {Actor, HttpAgent, Identity} from '@icp-sdk/core/agent';
import {Principal} from '@icp-sdk/core/principal';

import {_SERVICE, idlFactory} from '../declarations/main/main.did.js';
import {idlFactory as storageIdlFactory} from '../declarations/storage/storage.did.js';
Expand Down
2 changes: 1 addition & 1 deletion cli/api/downloadPackageFiles.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import {Principal} from '@dfinity/principal';
import {Principal} from '@icp-sdk/core/principal';
import {mainActor, storageActor} from './actors.js';
import {resolveVersion} from './resolveVersion.js';
import {parallel} from '../parallel.js';
Expand Down
421 changes: 232 additions & 189 deletions cli/bun.lock

Large diffs are not rendered by default.

30 changes: 21 additions & 9 deletions cli/commands/bench-replica.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import path from 'node:path';
import fs from 'node:fs';
import {execaCommand} from 'execa';
import {PocketIc, PocketIcServer} from 'pic-ic';
import {PocketIc as PocketIcMops, PocketIcServer as PocketIcServerMops} from 'pic-js-mops';
import {getRootDir, readConfig} from '../mops.js';
import {createActor, idlFactory} from '../declarations/bench/index.js';
import {toolchain} from './toolchain/index.js';
Expand All @@ -13,8 +14,8 @@ export class BenchReplica {
type : 'dfx' | 'pocket-ic' | 'dfx-pocket-ic';
verbose = false;
canisters : Record<string, {cwd : string; canisterId : string; actor : any;}> = {};
pocketIcServer ?: PocketIcServer;
pocketIc ?: PocketIc;
pocketIcServer ?: PocketIcServer | PocketIcServerMops;
pocketIc ?: PocketIc | PocketIcMops;

constructor(type : 'dfx' | 'pocket-ic' | 'dfx-pocket-ic', verbose = false) {
this.type = type;
Expand All @@ -35,14 +36,24 @@ export class BenchReplica {
else {
let pocketIcBin = await toolchain.bin('pocket-ic');
let config = readConfig();
if (config.toolchain?.['pocket-ic'] !== '4.0.0') {
console.error('Current Mops CLI only supports pocket-ic 4.0.0');
if (config.toolchain?.['pocket-ic'] !== '4.0.0' && !config.toolchain?.['pocket-ic']?.startsWith('9.')) {
console.error('Current Mops CLI only supports pocket-ic 9.x.x and 4.0.0');
process.exit(1);
}
this.pocketIcServer = await PocketIcServer.start({
binPath: pocketIcBin,
});
this.pocketIc = await PocketIc.create(this.pocketIcServer.getUrl());
// pocket-ic 9.x.x
if (config.toolchain?.['pocket-ic']?.startsWith('9.')) {
this.pocketIcServer = await PocketIcServerMops.start({
binPath: pocketIcBin,
});
this.pocketIc = await PocketIcMops.create(this.pocketIcServer.getUrl());
}
// pocket-ic 4.0.0
else {
this.pocketIcServer = await PocketIcServer.start({
binPath: pocketIcBin,
});
this.pocketIc = await PocketIc.create(this.pocketIcServer.getUrl());
}
Comment on lines +43 to +56

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Close server on client init failure and load Mops flavor dynamically.

Prevents orphaned processes if create() throws and avoids hard dependency on pic-js-mops when using v4.

-			// pocket-ic 9.x.x
-			if (config.toolchain?.['pocket-ic']?.startsWith('9.')) {
-				this.pocketIcServer = await PocketIcServerMops.start({
-					binPath: pocketIcBin,
-				});
-				this.pocketIc = await PocketIcMops.create(this.pocketIcServer.getUrl());
-			}
-			// pocket-ic 4.0.0
-			else {
-				this.pocketIcServer = await PocketIcServer.start({
-					binPath: pocketIcBin,
-				});
-				this.pocketIc = await PocketIc.create(this.pocketIcServer.getUrl());
-			}
+			// pocket-ic 9.x
+			if (/^v?9(\.|$)/.test(picVersion)) {
+				const { PocketIc: PocketIcMops, PocketIcServer: PocketIcServerMops } = await import('pic-js-mops');
+				this.pocketIcServer = await PocketIcServerMops.start({ binPath: pocketIcBin });
+				this.pocketIcMajor = 9;
+				try {
+					this.pocketIc = await PocketIcMops.create(this.pocketIcServer.getUrl());
+				} catch (e) {
+					await this.pocketIcServer.stop().catch(() => {});
+					throw e;
+				}
+			}
+			// pocket-ic 4.0.0
+			else {
+				this.pocketIcServer = await PocketIcServer.start({ binPath: pocketIcBin });
+				this.pocketIcMajor = 4;
+				try {
+					this.pocketIc = await PocketIc.create(this.pocketIcServer.getUrl());
+				} catch (e) {
+					await this.pocketIcServer.stop().catch(() => {});
+					throw e;
+				}
+			}
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
// pocket-ic 9.x.x
if (config.toolchain?.['pocket-ic']?.startsWith('9.')) {
this.pocketIcServer = await PocketIcServerMops.start({
binPath: pocketIcBin,
});
this.pocketIc = await PocketIcMops.create(this.pocketIcServer.getUrl());
}
// pocket-ic 4.0.0
else {
this.pocketIcServer = await PocketIcServer.start({
binPath: pocketIcBin,
});
this.pocketIc = await PocketIc.create(this.pocketIcServer.getUrl());
}
// pocket-ic 9.x
if (/^v?9(\.|$)/.test(picVersion)) {
// Dynamically load the Mops flavor only for v9
const { PocketIc: PocketIcMops, PocketIcServer: PocketIcServerMops } = await import('pic-js-mops');
this.pocketIcServer = await PocketIcServerMops.start({ binPath: pocketIcBin });
this.pocketIcMajor = 9;
try {
this.pocketIc = await PocketIcMops.create(this.pocketIcServer.getUrl());
} catch (e) {
// Ensure we always stop the server if client init fails
await this.pocketIcServer.stop().catch(() => {});
throw e;
}
}
// pocket-ic 4.0.0
else {
this.pocketIcServer = await PocketIcServer.start({ binPath: pocketIcBin });
this.pocketIcMajor = 4;
try {
this.pocketIc = await PocketIc.create(this.pocketIcServer.getUrl());
} catch (e) {
// Ensure we always stop the server if client init fails
await this.pocketIcServer.stop().catch(() => {});
throw e;
}
}
🤖 Prompt for AI Agents
In cli/commands/bench-replica.ts around lines 43–56, starting the pocket-ic
server then calling the client factory can leave an orphaned server if the
client create() throws and the current code also hard-depends on the Mops
package; wrap the server start + client create in a try/catch so that if
PocketIcMops.create or PocketIc.create throws you call
this.pocketIcServer?.stop() (or the server shutdown API) before rethrowing, and
instead of importing Mops statically require/import the Mops module dynamically
only when the version check selects the 9.x path (e.g. dynamic
import('pic-js-mops') vs import('pic-js') fallback) so the code doesn’t
hard-fail for v4 users.

}
}

Expand All @@ -69,7 +80,8 @@ export class BenchReplica {
this.canisters[name] = {cwd, canisterId, actor};
}
else if (this.pocketIc) {
let {canisterId, actor} = await this.pocketIc.setupCanister({idlFactory, wasm});
type PocketIcSetupCanister = PocketIcMops['setupCanister'] & PocketIc['setupCanister'];
let {canisterId, actor} = await (this.pocketIc.setupCanister as PocketIcSetupCanister)({idlFactory, wasm});
this.canisters[name] = {
cwd,
canisterId: canisterId.toText(),
Expand Down
2 changes: 1 addition & 1 deletion cli/commands/maintainer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import process from 'node:process';
import chalk from 'chalk';
import {checkConfigFile, getIdentity, readConfig} from '../mops.js';
import {mainActor} from '../api/actors.js';
import {Principal} from '@dfinity/principal';
import {Principal} from '@icp-sdk/core/principal';
import prompts from 'prompts';

export async function printMaintainers() {
Expand Down
2 changes: 1 addition & 1 deletion cli/commands/owner.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import process from 'node:process';
import chalk from 'chalk';
import {checkConfigFile, getIdentity, readConfig} from '../mops.js';
import {mainActor} from '../api/actors.js';
import {Principal} from '@dfinity/principal';
import {Principal} from '@icp-sdk/core/principal';
import prompts from 'prompts';

export async function printOwners() {
Expand Down
49 changes: 31 additions & 18 deletions cli/commands/replica.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,10 @@ import fs from 'node:fs';
import {PassThrough} from 'node:stream';
import {spawn as spawnAsync} from 'promisify-child-process';

import {IDL} from '@dfinity/candid';
import {Actor, HttpAgent} from '@dfinity/agent';
import {IDL} from '@icp-sdk/core/candid';
import {Actor, HttpAgent} from '@icp-sdk/core/agent';
import {PocketIc, PocketIcServer} from 'pic-ic';
import {PocketIc as PocketIcMops, PocketIcServer as PocketIcServerMops} from 'pic-js-mops';
import chalk from 'chalk';

import {readConfig} from '../mops.js';
Expand All @@ -25,8 +26,8 @@ export class Replica {
type : 'dfx' | 'pocket-ic' | 'dfx-pocket-ic' = 'dfx';
verbose = false;
canisters : Record<string, {cwd : string; canisterId : string; actor : any; stream : PassThrough;}> = {};
pocketIcServer ?: PocketIcServer;
pocketIc ?: PocketIc;
pocketIcServer ?: PocketIcServer | PocketIcServerMops;
pocketIc ?: PocketIc | PocketIcMops;
dfxProcess ?: ChildProcessWithoutNullStreams;
dir : string = ''; // absolute path (/.../.mops/.test/)
ttl = 60;
Expand Down Expand Up @@ -85,20 +86,32 @@ export class Replica {
else {
let pocketIcBin = await toolchain.bin('pocket-ic');

// eslint-disable-next-line
let config = readConfig();
if (config.toolchain?.['pocket-ic'] !== '4.0.0') {
console.error('Current Mops CLI only supports pocket-ic 4.0.0');
if (config.toolchain?.['pocket-ic'] !== '4.0.0' && !config.toolchain?.['pocket-ic']?.startsWith('9.')) {
console.error('Current Mops CLI only supports pocket-ic 9.x.x and 4.0.0');
process.exit(1);
}

this.pocketIcServer = await PocketIcServer.start({
showRuntimeLogs: false,
showCanisterLogs: false,
binPath: pocketIcBin,
ttl: this.ttl,
});
this.pocketIc = await PocketIc.create(this.pocketIcServer.getUrl());
// pocket-ic 9.x.x
if (config.toolchain?.['pocket-ic']?.startsWith('9.')) {
this.pocketIcServer = await PocketIcServerMops.start({
showRuntimeLogs: false,
showCanisterLogs: false,
binPath: pocketIcBin,
ttl: this.ttl,
});
this.pocketIc = await PocketIcMops.create(this.pocketIcServer.getUrl());
}
// pocket-ic 4.0.0
else {
this.pocketIcServer = await PocketIcServer.start({
showRuntimeLogs: false,
showCanisterLogs: false,
binPath: pocketIcBin,
ttl: this.ttl,
});
this.pocketIc = await PocketIc.create(this.pocketIcServer.getUrl());
}

// process canister logs
this._attachCanisterLogHandler(this.pocketIcServer.serverProcess as ChildProcessWithoutNullStreams);
Expand Down Expand Up @@ -224,17 +237,17 @@ export class Replica {
};
}
else if (this.pocketIc) {
// let {canisterId, actor} = await this.pocketIc.setupCanister(idlFactory, wasm);
let {canisterId, actor} = await this.pocketIc.setupCanister({
idlFactory,
type PocketIcSetupCanister = PocketIcMops['setupCanister'] & PocketIc['setupCanister'];
let {canisterId, actor} = await (this.pocketIc.setupCanister as PocketIcSetupCanister)({
wasm,
idlFactory,
});

if (signal?.aborted) {
return;
}

await this.pocketIc.addCycles(canisterId, 1_000_000_000_000);
await this.pocketIc.addCycles(canisterId as any, 1_000_000_000_000);

if (signal?.aborted) {
return;
Expand Down
2 changes: 1 addition & 1 deletion cli/commands/test/test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import {globSync} from 'glob';
import chokidar from 'chokidar';
import debounce from 'debounce';
import {SemVer} from 'semver';
import {ActorMethod} from '@dfinity/agent';
import {ActorMethod} from '@icp-sdk/core/agent';

import {sources} from '../sources.js';
import {getRootDir, readConfig} from '../../mops.js';
Expand Down
6 changes: 3 additions & 3 deletions cli/declarations/bench/bench.did.d.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import type { Principal } from '@dfinity/principal';
import type { ActorMethod } from '@dfinity/agent';
import type { IDL } from '@dfinity/candid';
import type { Principal } from '@icp-sdk/core/principal';
import type { ActorMethod } from '@icp-sdk/core/agent';
import type { IDL } from '@icp-sdk/core/candid';

export interface BenchResult {
'rts_stable_memory_size' : bigint,
Expand Down
6 changes: 3 additions & 3 deletions cli/declarations/bench/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@ import type {
HttpAgentOptions,
ActorConfig,
Agent,
} from "@dfinity/agent";
import type { Principal } from "@dfinity/principal";
import type { IDL } from "@dfinity/candid";
} from "@icp-sdk/core/agent";
import type { Principal } from "@icp-sdk/core/principal";
import type { IDL } from "@icp-sdk/core/candid";

import { _SERVICE } from './bench.did';

Expand Down
2 changes: 1 addition & 1 deletion cli/declarations/bench/index.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Actor, HttpAgent } from "@dfinity/agent";
import { Actor, HttpAgent } from "@icp-sdk/core/agent";

// Imports and re-exports candid interface
import { idlFactory } from "./bench.did.js";
Expand Down
6 changes: 3 additions & 3 deletions cli/declarations/main/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@ import type {
HttpAgentOptions,
ActorConfig,
Agent,
} from "@dfinity/agent";
import type { Principal } from "@dfinity/principal";
import type { IDL } from "@dfinity/candid";
} from "@icp-sdk/core/agent";
import type { Principal } from "@icp-sdk/core/principal";
import type { IDL } from "@icp-sdk/core/candid";

import { _SERVICE } from './main.did';

Expand Down
2 changes: 1 addition & 1 deletion cli/declarations/main/index.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Actor, HttpAgent } from "@dfinity/agent";
import { Actor, HttpAgent } from "@icp-sdk/core/agent";

// Imports and re-exports candid interface
import { idlFactory } from "./main.did.js";
Expand Down
6 changes: 3 additions & 3 deletions cli/declarations/main/main.did.d.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import type { Principal } from '@dfinity/principal';
import type { ActorMethod } from '@dfinity/agent';
import type { IDL } from '@dfinity/candid';
import type { Principal } from '@icp-sdk/core/principal';
import type { ActorMethod } from '@icp-sdk/core/agent';
import type { IDL } from '@icp-sdk/core/candid';

export interface Benchmark {
'gc' : string,
Expand Down
6 changes: 3 additions & 3 deletions cli/declarations/storage/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@ import type {
HttpAgentOptions,
ActorConfig,
Agent,
} from "@dfinity/agent";
import type { Principal } from "@dfinity/principal";
import type { IDL } from "@dfinity/candid";
} from "@icp-sdk/core/agent";
import type { Principal } from "@icp-sdk/core/principal";
import type { IDL } from "@icp-sdk/core/candid";

import { _SERVICE } from './storage.did';

Expand Down
8 changes: 4 additions & 4 deletions cli/declarations/storage/index.js
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
import { Actor, HttpAgent } from "@dfinity/agent";
import { Actor, HttpAgent } from "@icp-sdk/core/agent";

// Imports and re-exports candid interface
import { idlFactory } from './storage.did.js';
export { idlFactory } from './storage.did.js';

/**
*
* @param {string | import("@dfinity/principal").Principal} canisterId Canister ID of Agent
* @param {{agentOptions?: import("@dfinity/agent").HttpAgentOptions; actorOptions?: import("@dfinity/agent").ActorConfig}} [options]
* @return {import("@dfinity/agent").ActorSubclass<import("./storage.did.js")._SERVICE>}
* @param {string | import("@icp-sdk/core/principal").Principal} canisterId Canister ID of Agent
* @param {{agentOptions?: import("@icp-sdk/core/agent").HttpAgentOptions; actorOptions?: import("@icp-sdk/core/agent").ActorConfig}} [options]
* @return {import("@icp-sdk/core/agent").ActorSubclass<import("./storage.did.js")._SERVICE>}
*/
Comment on lines 7 to 12

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

JSDoc and runtime options out of sync with d.ts

The JSDoc omits options.agent and the implementation ignores it. Align with d.ts and main/index.js: accept agent, warn if agentOptions is also provided, and use the provided agent.

- * @param {{agentOptions?: import("@icp-sdk/core/agent").HttpAgentOptions; actorOptions?: import("@icp-sdk/core/agent").ActorConfig}} [options]
- * @return {import("@icp-sdk/core/agent").ActorSubclass<import("./storage.did.js")._SERVICE>}
+ * @param {{agent?: import("@icp-sdk/core/agent").Agent; agentOptions?: import("@icp-sdk/core/agent").HttpAgentOptions; actorOptions?: import("@icp-sdk/core/agent").ActorConfig}} [options]
+ * @return {import("@icp-sdk/core/agent").ActorSubclass<import("./storage.did.js")._SERVICE>}
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
/**
*
* @param {string | import("@dfinity/principal").Principal} canisterId Canister ID of Agent
* @param {{agentOptions?: import("@dfinity/agent").HttpAgentOptions; actorOptions?: import("@dfinity/agent").ActorConfig}} [options]
* @return {import("@dfinity/agent").ActorSubclass<import("./storage.did.js")._SERVICE>}
* @param {string | import("@icp-sdk/core/principal").Principal} canisterId Canister ID of Agent
* @param {{agentOptions?: import("@icp-sdk/core/agent").HttpAgentOptions; actorOptions?: import("@icp-sdk/core/agent").ActorConfig}} [options]
* @return {import("@icp-sdk/core/agent").ActorSubclass<import("./storage.did.js")._SERVICE>}
*/
/**
*
* @param {string | import("@icp-sdk/core/principal").Principal} canisterId Canister ID of Agent
* @param {{agent?: import("@icp-sdk/core/agent").Agent; agentOptions?: import("@icp-sdk/core/agent").HttpAgentOptions; actorOptions?: import("@icp-sdk/core/agent").ActorConfig}} [options]
* @return {import("@icp-sdk/core/agent").ActorSubclass<import("./storage.did.js")._SERVICE>}
*/
🤖 Prompt for AI Agents
In cli/declarations/storage/index.js around lines 7 to 12, the JSDoc and
implementation currently omit support for an `agent` option and ignore it at
runtime; update the JSDoc to include options.agent (typed to
import("@icp-sdk/core/agent").HttpAgent or similar) and modify the factory
implementation to accept an `agent` parameter: if `agent` is provided, use it to
create the actor; if both `agent` and `agentOptions` are provided, emit a
console.warn indicating `agent` takes precedence (for backward compatibility),
and only fall back to constructing a new agent from `agentOptions` when `agent`
is not supplied. Ensure types in JSDoc match the .d.ts and main/index.js
behavior and keep the existing actorOptions handling unchanged.

export const createActor = (canisterId, options) => {
const agent = new HttpAgent({ ...options?.agentOptions });
Expand Down
6 changes: 3 additions & 3 deletions cli/declarations/storage/storage.did.d.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import type { Principal } from '@dfinity/principal';
import type { ActorMethod } from '@dfinity/agent';
import type { IDL } from '@dfinity/candid';
import type { Principal } from '@icp-sdk/core/principal';
import type { ActorMethod } from '@icp-sdk/core/agent';
import type { IDL } from '@icp-sdk/core/candid';

export type Chunk = Array<number>;
export type Err = string;
Expand Down
2 changes: 1 addition & 1 deletion cli/mops.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import process from 'node:process';
import path from 'node:path';
import fs from 'node:fs';
import {Identity} from '@dfinity/agent';
import {Identity} from '@icp-sdk/core/agent';
import TOML from '@iarna/toml';
import chalk from 'chalk';
import prompts from 'prompts';
Expand Down
Loading
Loading