Flutter for frontend

this is so lit :fire:

Hi everyone!
I am trying to call the IC from a regular Flutter app.
For this purpose, I forked the repository from this blog post

in order to execute Rust code from Dart via FFIs.
If you’re interested, come take a look at IC Flutter Template :grinning:
I changed the example web scrapper to the name “ic” and started by adding a query_call function that uses the QueryBuilder of the rust ic_agent package.
Unfortunately, cargo could not compile ic_agent (all other changes in the repo are commented out because of this).
Here are the errors:

  1. at …/ic-agent-0.3.0/src/identity/basic.rs:67:22
    |
    67 | let id_ed25519 = oid!(1, 3, 101, 112);
    | ^^^^^^^^^^^^^^^^^^^^ expected struct simple_asn1::BigUint, found struct num_bigint::BigUint
  2. at …/ic-agent-0.3.0/src/identity/secp256k1.rs:86:48
    |
    86 | let ec_public_key_id = ObjectIdentifier(0, oid!(1, 2, 840, 10045, 2, 1));
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected struct simple_asn1::BigUint, found struct num_bigint::BigUint
  3. at …/ic-agent-0.3.0/src/identity/secp256k1.rs:87:44
    |
    87 | let secp256k1_id = ObjectIdentifier(0, oid!(1, 3, 132, 0, 10));
    | ^^^^^^^^^^^^^^^^^^^^^^ expected struct simple_asn1::BigUint, found struct num_bigint::BigUint

These errors lead to cargo aborting the build.
Has anyone encountered this type problem before?

Hi everyone!

I’m a Flutter developer and I would love to help making flutter for frontend a reality.

Is there someone that it’s actively working on it? From the thread It seems like that the best way would be to make a Flutter plugin that uses the JS agent for flutter_web, and Rust agent for android and iOS.

If someone is working on a generic solution let me know, I have worked on flutter plugin development for a while, and native android/iOS code is not a problem for me

1 Like

Hi @neokree, I am working on a code in the dart that will call and query ic-canisters. A Candid library to en-code the canister-method-arguments is the only part that I need to write as a JS interop because there is no candid library written in the dart yet. If you can make a dart/flutter library for the Candid that uses js/rust/js-rust(for the *.did->js code-generation) interop, and that the library/plugin hides the js-interop that would be great. (or a candid library in straight dart)

https://github.com/dfinity/candid/blob/master/spec/Candid.md

p.s. the nns.ic0.app is running on flutter.

@neokree @levi I’m not sure if it will be useful here (probably not), but I wrote some Dart code that converts Candid strings coming from the Internet Computer, for example the response from calling a query method from the cli with dfx canister call myCanister myMethod, into a set of nested Records (Map<String, V>, where V can be a String, Double, Vector or another Record). I put the relevant code in a gist in case anyone’s interested: Candid parser in Dart

I only just finished it, so it’s not battle tested and likely has many issues and missing parts, but maybe something like this will be useful in creating a Dart agent. Probably not, but for now it works for my needs to get data from the IC into my Dart programs.

I’m very interested in using the IC in flutter apps, and am more than happy to put in some work if I can be of use!

2 Likes

Ok so from what I have understood:

  1. We need a way to convert Candid *.did files to dart code, in order to call our canisters from Flutter
  2. We need a way to connect with IC using an Agent, independently from the platform used
  3. Flutter is already used in production with the IC, on nns.ic0.app
    (just for web? It’s an open source project? There is a way to know how they connected with IC?)

For problem #1, we need a dart code generator that write Dart classes from the *.did files.
Normally these are written for the build_runner library in Flutter, so that you can run flutter pub run build_runner build from your project and wait for the magic to happen. :mage:
A little more configuration (like the path for *.did files) will be needed, but I already saw other packages doing it so I think it’s not a problem.

The real pain start with problem #2, since we need to use PlatformChannels, that will connect with Rust using ffi for native platforms, and JS for the web. Using PlatformChannels it is not possible to pass complex data structures (normally they are converted to Lists/Maps, so a method call would need to be converted in the method’s name, and a list of his parameters). That would be ok for JS, since it have reflection, but not for Rust since it doesn’t implement it (just looked up on Google, I don’t know Rust or how the rust library works so feel free to tell me I’m wrong).
Anyway it does not seem to me an easily maintainable solution to me, since each time the JS library or Rust library changes I would need to change it as well.

The other option I see would be to write a Dart Agent, but I don’t know how much work that would be, or if it would be feasible. From a simply design perspective, this way we could skip the data transmission to native code completely and the only dependency would be the Candid spec, which I think it will be much more stable than a client library in the long run.

Let me know what you think about it

1 Like

Thank you! I will surely check it out

@neokree Yes! it is way better to have an agent written in dart itself and have the only interop-pendency of the candid library. I am working on some ic-tools that are in the language of the dart, cord to the the internet-computer-specification (not an interop with js or rust agent). It has the functions for the call of a canister update or query call. I have the pieces written in the dart, the thing that needs to use outside code with is the candid library.

For the nns.ic0.app, the front page says that it is in beta but im sure it won’t be sometime. It Looks like they are using a jsdart interop for some thing but I think it might be for the whole js-dfinity-agent, the frontend is downloads a file looks browserified dfinity_agent.js

1 Like

Ok in this case I think we can start building the candid-dart package!

Just to be sure we aren’t reinventing the wheel I opened a support ticked with the DFINITY team, asking if this development have already been made for nns.ic0.app but it’s not public yet.

In the middle time, please send me your github username (here or with a PM) so that I could add you on the repo as a collaborator.

@mymikemiller If you want to be a collaborator and help us you are welcome too! :v:

1 Like

I’d love to help! Same username: mymikemiller

We don’t have plans on building a candid-dart package, so community contribution is very much welcome and appreciated!

Just want to point out some resources from the official candid repo:

5 Likes

My team is planning to do it, and maybe applying a grant later

3 Likes

Do share the repository when you start, may be able to allot one of my team to contribute.

2 Likes

@neokree Awesome, my GitHub username is levifeldman , let’s do it, once candid library is in the dart then flutter will have each feature to call the ic!

1 Like

Wasm support is not supported by Dart.
Candid is not enough for accessing replica, I think we need to make agent work for dart/flutter, either porting the agent-rs to agent-dart or use FFI to interop.

Any teams are working on mobile wallet or mobile SDK?
Been poked by many token holders and investors saying they cannot use any mobile wallet app on IC. When “mainstream” devs come to build mobile native/hybrid apps on IC, javascript or web sdks are not enough. It’s inevitable to prepare such tools for them and us.

Maybe we should open another topic focusing on mobile device client?

3 Likes

We are officially woking on agent-dart now.

7 Likes

Can anyone help me fix this, please? How do you handle these options in Flutter?

The image argument can be null or can store a string value

var addReview = await SignIn.newActor!
          .getFunc(FieldsMethod.addReviews)
          ?.call([rating, title, review, image, reviewee_id]);

my integration.dart , IDL:

FieldsMethod.addReviews: IDL.Func(
        [IDL.Float64, IDL.Text, IDL.Text, IDL.Opt(IDL.Text), IDL.Text],
        [reviews],
        []
      ),

Review struct:

struct Reviews {
    pub ratings: f64,
    pub title: String,
    pub review: String,
    pub image: Option<String>,
    pub reviewer: String,
}

my backend, .did:

add_reviews : (float64, text, text, opt text, text) -> (Reviews);

Function:

#[update]
fn add_reviews(ratings: f64, title: String, review: String, image: Option<String>, profile_reviewed: String) -> Reviews {
    let mut profile = get(profile_reviewed);
    let me = get_self();

    // Create a new review
    let new_review = Reviews {
        ratings,
        title,
        review,
        image,
        reviewer: me.fullname,
    };


    profile.reviews.push(new_review.clone());

    new_review
}

Error:

@neeboo

use candid dart to generate IDLs easily and automatically

2 Likes

Thanks for sharing, I will look into it.