Azle rewrites did files?

Hi @lastmjs, I’m trying out Azle for the first time and have successfully migrated a simple Rust canister. Everything was really straight forward, great stuff!

I have run into one small thing though. It seems Azle generates new did files and overwrites any manually created ones? I have this did from my Rust canister:

type Name = text;
type AvatarUrl = text;

type UserProfile = record {
  address : text;
  name : text;
  avatar_url : text;
};

type GetMyProfileResponse = variant {
  Ok : UserProfile;
  Err : text;
};
  
type SaveMyProfileResponse = variant {
  Ok : UserProfile;
  Err : text;
};

type ListProfilesResponse = variant {
  Ok : vec record { text; UserProfile };
  Err : text;
};

service : (principal) -> {
  "get_my_profile" : () -> (GetMyProfileResponse) query;
  "list_profiles" : () -> (ListProfilesResponse) query;
  "save_my_profile" : (Name, AvatarUrl) -> (SaveMyProfileResponse);
};

Which turns into this after building with Azle:

service: (principal) -> {
    get_my_profile: () -> (variant {Ok:record {avatar_url:text; name:text; address:text}; Err:text}) query;
    list_profiles: () -> (variant {Ok:vec record {text; record {avatar_url:text; name:text; address:text}}; Err:text}) query;
    save_my_profile: (text, text) -> (variant {Ok:record {avatar_url:text; name:text; address:text}; Err:text});
}

So, those are essentially the same, except for the named response types. But I like having named response types in the did, it increases readability and makes the frontend code happier. Is there an option perhaps, not to compact the did? Or am I doing something weird elsewhere that causes this?

2 Likes

Hey! Glad you are liking Azle.

There is currently no option to turn off automatic Candid generation in Azle. We could of course add the feature but this is the first time anyone has really asked (we’ve discussed it before).

1 Like

We aren’t really recommending Candid anymore also, trying to move away from it: Get Started - The Azle Book

Especially with a simple app like this that looks like it wants to be consumed by a more traditional client like a web application, have a look at the new REST-based Azle paradigm.

I should be able to get this to you in the next release, I’ll post here when there’s a release candidate you can use from npm

1 Like

Nice! One alternative to turning generation off would be to generate the types if properly specified in the code. This approach takes more work of course.

const GetMyProfileResponse = Variant({
  Ok: UserProfile,
  Err: text,
});

export type GetMyProfileResponse = typeof GetMyProfileResponse.tsType;

export const get_my_profile = query(
  [],
  GetMyProfileResponse,
  (): GetMyProfileResponse => {
    const profile = profileStore.profiles[ic.caller().toString()];
    if (!profile) return { Err: "No profile found for the given address" };
    return { Ok: profile };
  }
);

Like, if a return type is specified and the type is exported, then include it in the did.

Yes, I like that approach, it is good for folks familiar with Express and Node.

I believe the Candid approach has its merits as well though. Especially for a simple app like the demo I’m working on. With a properly typed DID, the DX for setting up a small app is great!

  1. Implement backend Canister with Azle. Fully typed DID is generated on build. :slight_smile:
  2. dfx generate is included as part of the frontend build script = frontend gets access to the DID types.
  3. Add ic-use-actor to the frontend (React) and connect the hook with your did and idlFactory
import {
  createActorContext,
  createUseActorHook,
} from "ic-use-actor";
import { _SERVICE } from "path-to/your-service.did";

const actorContext = createActorContext<_SERVICE>();
export const useActor = createUseActorHook<_SERVICE>(actorContext);
  1. Use the created hook in your components and enjoy fully typed responses. Changes made to the backend are always available to the frontend without having to manage any separate type files.

Adding Express on top of the RPC functionality that IC already provides is I’m sure a good idea in some circumstances. Ideally, the developer have the option to choose. Not overwriting manually created DIDs (or generating fully typed) leaves the choice with the dev.

ps. Just published the demo: GitHub - kristoferlund/ic-siwe-react-demo-ts: React/Vite/TypeScript demo of the ic-siwe library, allowing ethereum apps to extend to the Internet Computer using Sign In with Ethereum (SIWE)

Live demo here :point_down::point_down::point_down:

https://zwsg3-myaaa-aaaal-qdf7q-cai.icp0.io

1 Like

I have the feature working well locally, this should come out in the next few days in Azle 0.20.2.

You’ll just add "candid_gen": "custom" to your dfx.json and Azle will leave it alone.

3 Likes

Nice, that’s a great fix!

1 Like

This feature is now live in Azle 0.20.2

1 Like

I was about to upgrade to new Azle version but ran into an issue. podman has not been required prior to this version, right? Unfortunately, it reliably crashes my computer during the build. No errors or warnings, just freeze and reboot. Mac M1, OS 12.2.1

1 Like

You ran brew install podman? Can you follow these steps if so? Deployment - The Azle Book

Yup, installed with brew. Crash happens on dfx deploy.

1 Like

Can you follow the linked steps? You may be running into the exact problem linked to in those steps. I am also very interested to know the output you get after deploying with AZLE_VERBOSE=true, especially knowing what the last output is before the hang/crash.

Also if you run brew outdated does podman or qemu come up? I wonder if you need to run brew update before brew install podman.

brew outdated:

bash (5.2.15) < 5.2.26
bat (0.23.0) < 0.24.0
bdw-gc (8.2.2) < 8.2.6
caddy (2.6.4) < 2.7.6
cmake (3.26.4) < 3.28.3
coreutils (9.3) < 9.4
dav1d (1.3.0) < 1.4.0
deno (1.32.4) < 1.40.5
evernote2md (0.19.0) < 0.21.0
gh (2.27.0) < 2.44.1
git (2.40.0) < 2.43.2
gnu-tar (1.34_1) < 1.35
highway (1.0.7) < 1.1.0
imath (3.1.9) < 3.1.10
jq (1.6) < 1.7.1
kompose (1.28.0) < 1.32.0
kubernetes-cli (1.27.1) < 1.29.2
libpthread-stubs (0.4) < 0.5
libuv (1.47.0) < 1.48.0
minikube (1.30.1) < 1.32.0
mongodb/brew/mongodb-community (6.0.5) < 7.0.2
mongodb/brew/mongodb-database-tools (100.7.0) < 100.9.4
mongosh (2.1.3) < 2.1.5
moreutils (0.67) < 0.68
mpg123 (1.32.4) < 1.32.5
node (21.6.1) < 21.6.2
numpy (1.26.3) < 1.26.4
nvm (0.39.3) < 0.39.7
oniguruma (6.9.8) < 6.9.9
openexr (3.2.1) < 3.2.2
openssl@1.1 (1.1.1u) < 1.1.1w
pnpm (8.8.0) < 8.15.3
python@3.12 (3.12.1_1) < 3.12.2
python@3.9 (3.9.17) < 3.9.18_2
telnet (69) < 294
tree (2.1.0) < 2.1.1_1
android-platform-tools (34.0.1) != 35.0.0
ngrok (3.2.2,dRdWsQNE9tG,a) != 3.6.0,qZzy6MZGEs,a

Will try the steps you outline now, mobile camera ready to snap a real screen shot before the crash. :grinning:

I followed the steps you outline but podman crashes at the “Waiting fo WM…” step. I also tried some of the tricks in the referenced issue, such as installing podman desktop. But, no luck so far, podman desktop also crashes, no Azle reference.

1 Like

Can you tell me the exact versions of Podman and Qemu installed?

Is it possible you’re running out of disk space? Another dev with a Mac had some initial problems with Podman and it ended up being that Podman was taking a lot of disk space…he was able to limit the disk space somehow, if that seems to be the issue i can find out exactly how he fixed it.