Search code examples
fluttergithub-pagesflutter-websolanadart-js-interop

Flutter web-hosted app doesn't recognize external functions


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.


Solution

  • 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