This project failed for technical reaasons: We need to go through all intermediary versions when doing a package upgrade, to run all migration functions. So, I had the idea to update the remote repo on Git commits. But the binaries for the production and localhost tests may be different, this makes it nearly impossible to do correctly. If you have an idea how to save my project, please I to hear you.
To create an app for IC Pack package manager (a remote, installable app), you follow these guidelines.
Choice of programming language
- Motoko (a special programming language for ICP blockchain). Don’t afraid of a new language: Motoko is a easy as Python to learn, meanwhile having features of a strict type system, helping you to eliminate stupid errors due to messed types and increasing code execution speed (and reducing costs).
- Rust (A bit of advice: because we hold all data in VM memory, not on disk files or an external database, memory corruption would be especially bad, so I recommend to never use
unsafe
Rust feature. To create circular data structures Better useRc
orArc
reference counting pointers than to resort tounsafe
.) - TypeScript or JavaScript (Azle);
- Python (Kybra);
- C++ (icpp-pro).
So, if you write a new software for Internet Computer (including software for our project IC Pack), choose either Motoko or Rust. If you decide to translate existing software, Rust, TypeScript, javaScript, Python, or C++ may be good choices.
Do development using ICP blockchain
Learn to develop software using ICP blockchain. It is easier than to develop for AWS or GCP.
Creating a package
For your software to be compatible with IC Pack, you need to package it (or, in other words, create a package). IC Pack dev docs explain how to do it.
Use wallet app (src/wallet_backend/
and src/wallet_frontend/
) as an example how a package should work, especially, how to initialize package’s owner principal in a secure manner.
You can optionally make your package paid (see paid-wallet
package for an example). You specify the (non-zero) price and developer account for a paid package. Your customers pay us a 10% fee for installing a paid package. If you omit the developer account, 100% will be paid to us.
Module initialization arguments
Every module of your package receives the following arguments on installation:
{
packageManager: Principal; // `backend` module of the package manager
mainIndirect: Principal; // `main_indirect` module of the package manager
simpleIndirect: Principal; // `simple_indirect` module of the package manager
battery: Principal; // `battery` module of the package manager
user: Principal; // user, ignore it for now, use install key instead installationId: Nat; // installation ID of the currently installed package
upgradeId: ?Nat; // `null` for newly installed packages
userArg: Blob; // normally `to_candid({})` but maybe any value
}
Example package receiving arguments:
persistent actor class Wallet({
installationId: Nat;
packageManager: Principal;
}) = this {
// ...
}
Usually, you need to set the owner of your backend canister. The highly recommended (because it has enhanced security) way to do it is:
Frontend JS code:
import { urlSafeBase64ToUint8Array, signPrincipal } from '../../../icpack-js';
const params = new URLSearchParams(window.location.search);
const installKey = params.get('installationPrivKey');
try {
privBytes = urlSafeBase64ToUint8Array(props.installationPrivKey);
} catch (_) {
alert('Invalid installation key.');
return;
}
const privKey = await window.crypto.subtle.importKey(
"pkcs8", privBytes, {name: 'ECDSA', namedCurve: 'P-256'/*prime256v1*/}, true, ["sign"]
);
const signature = new Uint8Array(await signPrincipal(privKey, principal));
await backend.setOwner(signature); // the code that you use to set your canister owner
In the backend, check the user’s cryptographic signature before setting the owner. Here is the Motoko code:
import UserAuth "mo:icpack-lib/UserAuth";
public shared({caller}) func setOwner(signature: Blob): async () {
await* UserAuth.checkOwnerSignature(packageManager, installationId, caller, signature); // traps on error
owner := caller;
};
Distribute your software
Distributing your software is the simplest task! Just create a link, as IC Pack dev docs explain.