RootSoft / walletconnect-dart-sdk

Open protocol for connecting dApps to mobile wallets with QR code scanning or deep linking.
MIT License
102 stars 61 forks source link

Deep linking not working on iOS with Pera #55

Closed 2i2i closed 2 years ago

2i2i commented 2 years ago

It seems that iOS needs a different treatment - pls see the discussion here: https://github.com/perawallet/pera-wallet/issues/81#issuecomment-1166356023

2i2i commented 2 years ago

is it the bridge url that needs to be changed for iOS Pera to work?

2i2i commented 2 years ago

Works as follows for me (need to change bridge for Pera):

final connector = WalletConnect(
      bridge: 'https://wallet-connect-a.perawallet.app',
      clientMeta: PeerMeta(
        name: 'WalletConnect',
        description: 'WalletConnect Developer App',
        url: 'https://walletconnect.org',
        icons: ['https://gblobscdn.gitbook.com/spaces%2F-LJJeCjcLrr53DcT1Ml7%2Favatar.png?alt=media'],
      ),
    );

    connector.on('connect', (session) => print('connect session=$session'));
    connector.on('session_update', (payload) => print('session_update payload=$payload'));
    connector.on('disconnect', (session) => print('disconnect session=$session'));

    if (!connector.connected) {
      print('!connector.connected');
      final session = await connector.createSession(
        chainId: 4160,
        onDisplayUri: (uri) async {
          print('uri=$uri');
          final uriObj = Uri(
            scheme: 'algorand-wc',
            host: 'wc',
            queryParameters: {'uri': uri},
          );
          print(uriObj.toString());
          launchUrl(uriObj);
        },
      );
    } else {
      print('connector.connected');
    }
RootSoft commented 2 years ago

@2i2i this is how I did it on my app:

/// Launch the Pera Algo Wallet.
Future<bool> launchPera(String uri) async {
  final isiOS = Environment.isiOS || Environment.isiOSInWeb;

  if (isiOS) {
    uri = 'algorand-wc://wc?uri=${Uri.encodeComponent(uri)}';
  }

  bool launched = false;
  try {
    if (!isiOS) {
      launched = await launch(uri);
    } else {
      launched = await launch(uri, universalLinksOnly: true);
    }
    if (!launched) {
      // launch alternative method
      logger.d('Fallback launch with universalLinksOnly true');
      launched = await launch(uri, universalLinksOnly: true);
    }
  } catch (ex) {
    logger.e(ex);
    launched = false;
  }

  return launched;
}

When signing a transaction:

    final session = connector.session;
    var uri =
        '${session.protocol}:${session.handshakeTopic}@${session.version}';

    bool launched = await launchPera(uri);

I've noticed in iOS for Pera, it is recommended to perform the signing transaction request before launching Pera wallet.

  @override
  Future<List<Uint8List>> signTransactions(
    String address,
    List<RawTransaction> transactions, {
    int delay = 2,
  }) async {
    final c = Completer<List<Uint8List>>();
    final isiOS = Environment.isiOS || Environment.isiOSInWeb;

    // For iOS, the signing request should be done first
    if (isiOS) {
      // Audio hack to keep ws alive (Flutter Web)
      final audioPlayer = AudioPlayer();
      audioPlayer.play();

      c.complete(
        provider.signTransactions(
          transactions.map((tx) => tx.toBytes()).toList(),
        ),
      );

      if (!Environment.isiOSInWeb) {
        await Future.delayed(const Duration(seconds: 1));
      }
    }

    final session = connector.session;
    var uri =
        '${session.protocol}:${session.handshakeTopic}@${session.version}';

    bool launched = await launchPera(uri);

    if (!launched) {
      throw WalletConnectException(
          'Do you have the Pera Algo Wallet installed?');
    }

    if (!isiOS) {
      // Wait x seconds
      await Future.delayed(Duration(seconds: delay));

      // Sign the transaction
      c.complete(
        provider.signTransactions(
          transactions.map((tx) => tx.toBytes()).toList(),
        ),
      );
    }

    return await c.future;
  }