Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

When an actor is passed as a part of a struct, it isn't an Actor instance #775

Open
vporton opened this issue Sep 28, 2023 · 6 comments
Open

Comments

@vporton
Copy link

vporton commented Sep 28, 2023

Describe the bug
When an actor is passed as a part of a struct, it isn't an Actor instance (but should be).

To Reproduce
Create a Motoko and a JavaScript file (this repo):

Motoko:

actor class canvalue_backend() = this {
  public type R = {
    value: canvalue_backend;
  };
  public query func test() : async R {
    return { value = this };
  };
};

TypeScript:

import { Actor } from "@dfinity/agent";
import { canvalue_backend } from "../../declarations/canvalue_backend";

const ac = await canvalue_backend.test();
Actor.canisterIdOf(ac.value)

Error:

Argument of type 'canvalue_backend' is not assignable to parameter of type 'Actor'.
  Property '[metadataSymbol]' is missing in type 'canvalue_backend' but required in type 'Actor'.

Generate:

dfx generate

Inspect the TypeScript code src/canvalue_frontend/src/index.ts in a text editor (such as MS Code) capable to spot TypeScript type errors.

Expected behavior
ac should be an instance of Actor.

Desktop (please complete the following information):

  • OS: Ubuntu Linux
  • Version 23.04
@chenyan-dfinity
Copy link
Contributor

This is working as expected. Here is the did file from the Motoko code:

type canvalue_backend =
  service {
    test: () -> (R) query;
  };
type R = record {value: canvalue_backend;};
service : {
  test: () -> (R) query;
}

test() returns a record, and ac.value is a service reference (see https://internetcomputer.org/docs/current/references/candid-ref#type-service-), which contains the canister id as a Principal. It's not an Actor instance.

@vporton
Copy link
Author

vporton commented Sep 28, 2023

It's not an Actor instance.

But it should be an Actor instance. This is what I ask in my bug report.

@chenyan-dfinity
Copy link
Contributor

You can construct an Actor from the principal, but it's current not done automatically. It can be a feature request, but it's not a bug, the current format is specified in the doc.

@vporton
Copy link
Author

vporton commented Sep 28, 2023

You can construct an Actor from the principal

No, ac in my original message isn't a Principal. It is some value that I have no idea how to use it.

Moreover,

  public query func getRootItem(): async ?(CanDBPartition.CanDBPartition, Nat) {
    rootItem;
  };

(here CanDBPartition is an actor class).

    main.getRootItem().then((data) => {
    })

crashed with the browser console message Uncaught (in promise) Error: Illegal service definition: services can only contain functions. So, it apparently crashes on any access to the value. It is a bug.

@vporton
Copy link
Author

vporton commented Sep 28, 2023

The reverse case of passing an actor as an argument does work, but its value needs to be converted into a principal before passing. This seems to work:

actor class canvalue_backend() = this {
  public query func test(value: canvalue_backend) : async () {
  };
};
import { Actor } from "@dfinity/agent";
import { canvalue_backend } from "../../declarations/canvalue_backend";

await canvalue_backend.test(Actor.canisterIdOf(canvalue_backend));

A bad thing here is that if we allow (as it would be in an ideal world) passing directly an actor, this would create past compatibility problems (that however can be solved by expecting Actor | Principal.

@chenyan-dfinity
Copy link
Contributor

No, ac in my original message isn't a Principal. It is some value that I have no idea how to use it.

ac is a record. ac.value is a principal. If not, can you console.log(ac.value)?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants