A utility to make ICP Canisters easier to handle. This package provides a simple interface for managing Internet Computer (ICP) canisters, handling both local development and mainnet environments.
- Automatic URL management for local and mainnet environments
- Support for localhost subdomains in Chrome
- Internet Identity URL management
- TypeScript support
- SSL configuration support for local development
- Expo development server support
- Actor creation for canister communication
npm install canister-manager
This package requires the following peer dependencies:
npm install @dfinity/agent @dfinity/candid
import { CanisterManager } from 'canister-manager';
// Initialize the manager
const manager = new CanisterManager({
dfxNetwork: 'local', // or 'ic' for mainnet, 'playground' for playground
localIPAddress: '192.168.0.210', // Your local IP address for external access
// Optional: customize ports
replicaPort: 4943, // Required for local development
// The following ports are only needed when accessing from a smartphone
canisterPort: 14943, // For canister communication via SSL
internetIdentityPort: 24943, // For Internet Identity via SSL
});
// Get backend URL for canister communication
const backendUrl = manager.getBackendCanisterURL('your-canister-id');
// Get frontend URL for canister access
const frontendUrl = manager.getFrontendCanisterURL('your-canister-id');
// Get Internet Identity URL
// Note: Internet Identity has a fixed canister ID: rdmx6-jaaaa-aaaaa-aaadq-cai
const iiUrl = manager.getInternetIdentityURL('rdmx6-jaaaa-aaaaa-aaadq-cai');
import { IDL } from '@dfinity/candid';
import { AnonymousIdentity } from '@dfinity/agent';
// Define your canister interface
const canisterInterface = IDL.Service({
// Your canister methods here
example_method: IDL.Func([IDL.Text], [IDL.Text], ['query']),
});
// Create an actor for your canister
const actor = manager.createActor({
canisterId: 'your-canister-id',
interfaceFactory: () => canisterInterface,
// Optional: provide a custom identity (defaults to AnonymousIdentity)
identity: new AnonymousIdentity(),
});
// Use the actor to call canister methods
const result = await actor.example_method('Hello, World!');
The manager automatically handles different environments:
For mainnet deployment, the manager provides the following URLs:
- Backend URLs:
https://<canister-id>.ic0.app/
- Example:
https://rrkah-fqaaa-aaaaa-aaaaq-cai.ic0.app/
- Example:
- Frontend URLs:
https://<canister-id>.icp0.io/
- Example:
https://rrkah-fqaaa-aaaaa-aaaaq-cai.icp0.io/
- Example:
- Internet Identity:
https://identity.ic0.app/
For playground deployment, the manager provides the same URLs as mainnet:
- Backend URLs:
https://<canister-id>.ic0.app/
- Example:
https://rrkah-fqaaa-aaaaa-aaaaq-cai.ic0.app/
- Example:
- Frontend URLs:
https://<canister-id>.icp0.io/
- Example:
https://rrkah-fqaaa-aaaaa-aaaaq-cai.icp0.io/
- Example:
- Internet Identity:
https://identity.ic0.app/
For local development, the manager provides different URL formats depending on your browser and access method:
Chrome supports localhost subdomains, which provides a cleaner URL format:
- Backend URLs:
http://<canister-id>.localhost:4943/
- Example:
http://rrkah-fqaaa-aaaaa-aaaaq-cai.localhost:4943/
- Example:
- Frontend URLs:
http://<canister-id>.localhost:4943/
- Example:
http://rrkah-fqaaa-aaaaa-aaaaq-cai.localhost:4943/
- Example:
- Internet Identity:
http://<canister-id>.localhost:4943/
- Example:
http://rdmx6-jaaaa-aaaaa-aaadq-cai.localhost:4943/
- Note: Internet Identity has a fixed canister ID:
rdmx6-jaaaa-aaaaa-aaadq-cai
- Example:
Other browsers don't support localhost subdomains, so the manager falls back to query parameter URLs:
- Backend URLs:
http://localhost:4943/?canisterId=<canister-id>
- Example:
http://localhost:4943/?canisterId=rrkah-fqaaa-aaaaa-aaaaq-cai
- Example:
- Frontend URLs:
http://localhost:4943/?canisterId=<canister-id>
- Example:
http://localhost:4943/?canisterId=rrkah-fqaaa-aaaaa-aaaaq-cai
- Example:
- Internet Identity:
http://localhost:4943/?canisterId=<canister-id>
- Example:
http://localhost:4943/?canisterId=rdmx6-jaaaa-aaaaa-aaadq-cai
- Note: Internet Identity has a fixed canister ID:
rdmx6-jaaaa-aaaaa-aaadq-cai
- Example:
For accessing from a smartphone, SSL is required with custom ports:
- Backend URLs:
https://<local-ip>:14943/?canisterId=<canister-id>
- Example:
https://192.168.0.210:14943/?canisterId=rrkah-fqaaa-aaaaa-aaaaq-cai
- Example:
- Frontend URLs:
https://<local-ip>:14943/?canisterId=<canister-id>
- Example:
https://192.168.0.210:14943/?canisterId=rrkah-fqaaa-aaaaa-aaaaq-cai
- Example:
- Internet Identity:
https://<local-ip>:24943/?canisterId=<canister-id>
- Example:
https://192.168.0.210:24943/?canisterId=rdmx6-jaaaa-aaaaa-aaadq-cai
- Note: Internet Identity has a fixed canister ID:
rdmx6-jaaaa-aaaaa-aaadq-cai
- Example:
-
replicaPort
(default: 4943): Required for local development -
canisterPort
(default: 14943): Only needed for smartphone access via SSL -
internetIdentityPort
(default: 24943): Only needed for smartphone access via SSL
When developing locally with Chrome, you only need to specify the replicaPort
. The other ports are only required when you need to access the local development server from a smartphone.
To connect to a local replica from a web application or native app on a smartphone, SSL configuration is required. Here's how to set it up:
To access the development server on your PC from a smartphone, you need to set up a static IP address. This ensures the IP address remains unchanged even after PC restart, enabling stable connectivity.
- Open "System Settings" from the Apple menu
- Click "Network" in the sidebar
- Select your active network connection (Wi-Fi or Ethernet) and click "Details"
- Open the "TCP/IP" tab
- From the "Configure IPv4" dropdown menu, select "Using DHCP with manual address" and enter:
- IP Address: Recommended to use range 192.168.0.200-192.168.0.254 to avoid conflicts with DHCP dynamic assignments. For example, you could use 192.168.0.210.
mkcert is a tool for easily implementing HTTPS communication in local development environments.
brew install mkcert
brew install nss # Required if using Firefox
mkcert -install
mkcert -CAROOT
- Send rootCA.pem file to iOS device
- Install from "Profile Downloaded" in Settings app
- Enable mkcert certificate in Settings → General → About → Certificate Trust Settings
- Transfer rootCA.pem file to Android device
- Go to Settings → Security → More → Install from storage
- Select and install as CA certificate
Important Notes
- nss installation is mandatory when using Firefox
- Never share generated key files
- Root certificate installation process may vary depending on Android device model
mkdir .mkcert
cd .mkcert
mkcert [static IP address]
The following files will be generated:
-
[static IP address].pem
- Server certificate -
[static IP address]-key.pem
- Private key
Update your package.json with SSL proxy configurations:
{
"scripts": {
"ssl:canisters": "local-ssl-proxy --key ./.mkcert/[static IP address]-key.pem --cert ./.mkcert/[static IP address].pem --source 14943 --target 4943",
"ssl:ii": "local-ssl-proxy --key ./.mkcert/[static IP address]-key.pem --cert ./.mkcert/[static IP address].pem --source 24943 --target 4943"
}
}
Each configuration does the following:
-
ssl:canisters
: Provides HTTPS connection for Canisters (14943→4943) -
ssl:ii
: Provides HTTPS connection for Internet Identity (24943→4943)
Important Notes
- Replace
[static IP address]
with the static IP address you configured earlier - Ensure the server certificate and private key file paths match the location of files generated by mkcert
First, start DFX and deploy your canisters:
# Start DFX with SSL
dfx start --clean
# In a new terminal, deploy your canisters
dfx deploy
After DFX is running and canisters are deployed, launch the SSL proxy servers:
# Terminal 1: Start canister proxy
npm run ssl:canisters
# Terminal 2: Start Internet Identity proxy
npm run ssl:ii
These commands do the following:
-
ssl:canisters
provides HTTPS connection for Canisters (14943→4943) -
ssl:ii
provides HTTPS connection for Internet Identity (24943→4943)
Important Notes
- Run each command in a separate new terminal
- Before running commands, ensure target ports are not in use
- Verify SSL certificate paths are correctly configured
- After launch, each can be stopped individually with Ctrl+C
- Always start DFX and deploy canisters before starting the local-ssl-proxy servers
const manager = new CanisterManager({
dfxNetwork: 'local',
localIPAddress: '192.168.0.210', // Your local IP address for external access
// Use default ports unless you've configured custom ones
replicaPort: 4943,
canisterPort: 14943, // Only needed for smartphone access
internetIdentityPort: 24943, // Only needed for smartphone access
});
-
Web Browser: Use
https://<your-ip>:<port>/?canisterId=<canister-id>
- Mobile App: Use the same URL format as web browser
-
Chrome on Desktop: Supports localhost subdomains (
http://<canister-id>.localhost:4943
) -
Expo App: Use
https://<your-ip>:18081
to access the development server
-
SSL Certificate Errors:
- For development, you may need to accept self-signed certificates in your browser
- For mobile apps, you might need to configure certificate pinning or disable SSL verification in development
- Ensure mkcert root certificate is properly installed on all devices
- Verify that the server certificate matches your static IP address
-
Connection Issues:
- Ensure your device is on the same network as your development machine
- Check if your firewall allows connections to the specified ports
- Verify that the IP address is correct and accessible
- Make sure mkcert is properly installed and configured
- Confirm that your static IP address is properly set and not conflicting with other devices
- Verify that all local-ssl-proxy instances are running correctly
- For Expo development server, ensure the Expo server is running before starting the proxy
- Make sure DFX is running and canisters are deployed before starting local-ssl-proxy
-
Port Conflicts:
- If the default ports are in use, you can customize them in the configuration
- Make sure to update your DFX configuration to match the custom ports
- Verify that the local-ssl-proxy ports match your application configuration
- Check that no other services are using the required ports
- Ensure Expo development server is running on port 8081
type CanisterManagerConfig = {
/** The DFX network to connect to (e.g., 'local', 'ic', 'playground') */
dfxNetwork: string;
/** Local IP address for external access to local development server */
localIPAddress: string;
/** Port for the local replica (default: 4943) */
replicaPort?: number;
/** Port for canister communication via SSL (default: 14943). Only needed for smartphone access. */
canisterPort?: number;
/** Port for Internet Identity via SSL (default: 24943). Only needed for smartphone access. */
internetIdentityPort?: number;
};
- Clone the repository
- Install dependencies:
npm install
- Run tests:
npm test
- Build the project:
npm run build
MIT