Flutter web-hosted app doesn't recognize external functions
After reading your original post on connecting a Phantom wallet with Flutter, I decided to try it out myself, and I eventually ran into the same issue as you, down the to exact function call!
The solution (workaround) for me was to use standalone functions instead of methods.
I do not know why, but for some reason the Dart-JS interop stopped working on class instances after flutter build web
. My minified JS code with class instances played nice with flutter run -d chrome
.
Edit:
This is the phantom.ts
I got working.
const solanaWeb3 = require('@solana/web3.js');
export async function connect(): solanaWeb3.PublicKey {
const resp = await window.solana.connect();
return new solanaWeb3.PublicKey(resp.publicKey.toString());
}
export function disconnect() {
window.solana.disconnect();
}
export function isPhantomInstalled(): bool {
return window.solana && window.solana.isPhantom;
}
export async function signTransaction(tx: solanaWeb3.Transaction): solanaWeb3.Transaction {
return await window.solana.signTransaction(tx);
}
Then Dart-side, the interop is the same, just no class definition. I'm going to write a Medium post / release a GitHub repo with an example soon.
Edit 2: Medium post / repo can be found here
ggiurca
Updated on December 01, 2022Comments
-
ggiurca over 1 year
I'm hosting a web made on Flutter on GitHub pages and I'm using Dart-JS interop for connecting a Solana wallet. When I test locally I can connect to it and works fine but once I host the web on GitHub Pages I get the following error: Uncaught TypeError: p.isPhantomInstalled is not a function
This is my Dart code:
@JS('walletModule.ClientWallet') class ClientWallet { external Future<void> connect(); external void disconnect(); external String get address; external Future<void> signTransaction(); external bool isPhantomInstalled(); } class WalletController extends GetxController { Future<void> connectWallet(context) async { ClientWallet wallet = ClientWallet(); if (wallet.isPhantomInstalled()) { await promiseToFuture(wallet.connect()); createSnackbar('success', 'Wallet Connected'); } else { createSnackbar('error', 'No Phantom wallet detected'); } }
This is my JS code:
class ClientWallet { constructor() { this.address = ''; } async connect() { const resp = await window.solana.connect(); this.address = resp.publicKey.toString(); } address() { return this.address; } isPhantomInstalled() { return window.solana && window.solana.isPhantom; } disconnect() { window.solana.disconnect(); } } var walletModule = { ClientWallet: ClientWallet };
It seems that when hosted, the app doesn't recognize the external functions? I have no clue why or how to solve it.
-
ggiurca over 2 yearsGlad to know that code was useful to someone! Can you share a code snippet on how you made it work? I was able to use standalone functions instead of methods and it works locally but it still doesn't work when served.
-
HelmetFace over 2 yearsI edited my original example to show what I got working. It sounds like your problem is more related to paths and namespaces than anything else. How are you injecting the JS into your Flutter build / HTML?
-
ggiurca over 2 yearsThanks @HelmetFace, worked like a charm. Please, do not hesitate to link here the Medium article, I'll be waiting to read it!
-
murock over 2 yearsI'm also very interested in this. I've been struggling to work out how to get the metadata json for an NFT in Flutter. I think your article may help me!
-
HelmetFace over 2 yearsHere's the article and accompanying GitHub repo for those interested. blog.auguron.com/flutter-dapps-on-solana-364e81fe73ca