I’ll let you know once I try (in a couple weeks or less). Apparently, Flutter works too if you don’t like RN.
For flutter devs, you can try our library
It’s in alpha stage, but you can try anyway. All the apis are similar to
documents are coming! Stay tuned
I’ll give it a try for sure although I have no experience with Flutter!
For native coder, I think we have to wait for swift/kotlin library published somehow
I have some examples of sending raw ingress message through http POST ic-qr-scanner/bare-agent.js at main · ninegua/ic-qr-scanner · GitHub
It is quite simple actually if you know how to craft an ingress message before sending it.
Thank you for the example! I’ve tried constructing an http request in Swift in a way similar to your example, but on a local host and with an anonymous sender. I got a reject error concerning not finding the canister. My guess it’s because the request expects the canister_id to be a blob. Not sure how to retrieve the canister_id as a Principal type outside agent-js.
So I’m trying the @dfinity/agent JS library with RN right now and I’m running into an issue. Documented in @dfinity/agent not working with React Native.
Fwiw, I track work for agent-js in GitHub, and React Native support is an open task for me. Issues · dfinity/agent-js · GitHub. I’ll respond to the other thread directly though
Sounds good. Is there a place I can list all the issues I’ve encountered so far?
Yes, you can create new issues directly in that GitHub page. I’m also happy to review and approve pull requests from the community, if you’re feeling generous
OK I finally got the
@dfinity/agent JS library working with React Native for both iOS and Android (at least for the emulators).
The process is quite involved, so it’s definitely not a straightforward integration like it is for web.
There are two core issues with using the agent JS library with RN:
- RN doesn’t provide direct access to the underlying byte stream for HTTP responses. Since canister responses are CBOR-encoded and therefore binary, reading those responses in JS land isn’t supported by RN out of the box.
- The agent JS library relies on a bunch of JS APIs that aren’t available in the default JS implementation shipped with RN apps. This is complicated by the fact that RN apps running on iOS actually use a different JS engine than RN apps running on Android.
Problem 1 can be solved by replacing the default
fetch() implementation with the one offered by
rn-fetch-blob does not work.) You’ll then need to patch both that fetch library as well as the
@dfinity/agent in your node_modules to configure it to work correctly, since it won’t work off the shelf. Basically, you need to make the fetch library pass base64-encoded bytes instead of blobs over the RN bridge.
Problem 2 is solved once these JS APIs are made available:
The first two can be polyfilled using
react-native-polyfill-globals, which incidentally is also the same library that polyfills the Fetch API implemented by the aforementioned
Buffer can be polyfilled using
buffer and an explicit
global.Buffer = buffer assignment.
The last two are the trickiest and the biggest pain in the ass. You could polyfill them using standard JS libraries like
webassemblyjs, but it won’t work because they’ll be too slow (or throw some cryptic errors). I’ve tried a bunch of polyfill libraries and none were performant enough for the BLS signature validation that is necessary for processing IC canister responses. (The one exception is
JSBI as a polyfill for
BigInt, which ran fast but required me to literally rewrite huge portions of the
@dfinity/candid source. So not technically a drop-in polyfill.)
One thing I forgot to mention is that both
WebAssembly if you use the JIT-enabled v8. Here is the catch: it executes wasm too slowly. The BLS signature validation wasm module hung for a few minutes before I killed it. I don’t know why v8 executed it slowly but iOS’s JSC was able to run it fast (under a second). To get around this, I manually converted the wasm bytes into JS code using
wasm2js and patched the
@dfinity/agent library again to run that JS code in lieu of wasm for validating BLS signatures. This reduced the execution time to under a second for Android, matching iOS. Now, update calls takes <5 seconds on both of my emulators, which I can work with.
Feel free to DM me if you’d like more details on how to get a RN mobile app set up to communicate with IC canisters. Hope this helps (if it hasn’t scared you away already).
This is marvelous work.
This is really fantastic, @jzxchiang! I’d like to work with you to avoid needing to modify
node_modules anywhere, and maybe we can release a package with the necessary polyfills and setup groundwork to make this easier for everyone
Awesome work! I was able to get React Native work on the iOS side with using Buffer and
patch-package. I tried following this approach to access the
Are you using the agent-js lib in a mobile web app, if not RN? What’s the error you’re seeing?
@dfinity/agent to be my API gateway. I bundled that file with webpack as I’ve mentioned. The error I see is:
ReferenceError: Can’t find variable: self"
and the stackt race info:
Thanks for great answer. Can you elaborate on what was your final workaround for BigInt issue and the whole connection between mobile app and canister? I am on the same boat and do not want to re-invent the wheel as it seems you got it working
OK so quick disclaimer: I’m not using Expo so not 100% how or if this will work.
BigInt should be available on iOS (at least iOS 14), but the issue is Android. The problem is that the default JSC bundled with an Android RN app doesn’t support BigInt AFAIK. I’m currently using v8 instead of JSC for Android. Make sure you enable JIT if you care about performance (see the docs).
You’ll probably hit errors with BigInt syntax for iOS and/or Android:
- The exponentiation ** operator might not be supported. You’ll have to manually patch the
@dfinity/agentlibrary to replace the ** code (in 6 files) with hardcoded static values.
- The BigInt
...nliteral syntax (e.g.
128n) might not be supported. You’ll also need to replace that with the BigInt constructor (e.g.
Some of these errors only happened when I built my RN app in release mode, so you might not see them initially… but they are there.
Oh yeah, after you solve BigInt, you’ll need to deal with WebAssembly.
Thank you. Trying to implment this in expo.
For some more discussion: Module Namespacing Support for Packages · Issue #161 · expo/snack · GitHub