Overview

This guide outlines how to integrate and use external cryptocurrency wallets with our Flutter SDK. It covers the setup, deep-linking protocols, authentication, and transaction signing processes for wallets such as MetaMask and Phantom.

Deeplinking

Our Flutter SDK communicates with other apps via deeplinking. To enable deeplinking for your application, you will need to modify the AndroidManifest.xml for android and Info.plist for iOS.

For Android, add an intent filter, which should look like this.

<activity
    android:name="com.linusu.flutter_web_auth_2.CallbackActivity"
    android:exported="true">
    <intent-filter android:label="flutter_web_auth_2">
        <action android:name="android.intent.action.VIEW" />
        <category android:name="android.intent.category.DEFAULT" />
        <category android:name="android.intent.category.BROWSABLE" />
        <data android:scheme="<YOUR_SCHEME_HERE>" />
    </intent-filter>
</activity>

For iOS go to TARGETS > App Name > Info > URL Types and add a new URL type. In the URL Schemes field, add your scheme. This can be any string you want, but it must be unique to your app.

Phantom Connector

Setup

In the same place where you instantiate the Para Client, you will need to also instantiate the Phantom Connector.

final para = Para(
  environment: Environment.beta,
  apiKey: apiKey,
);

final phantomConnector = ParaPhantomConnector(
    para: para, appUrl: <YOUR_APP_URL>, deepLink: "<YOUR_APP_DEEPLINK_SCHEME>");

Connecting

After setup, all you need to do is call

phantomConnector.connect();

This will open the Phantom wallet and connect it to your app.

Sign Message

To sign a message, you can call

phantomConnector
  .signMessage("Message to sign! Hello World")
  .then((onValue) => {
    print(onValue); // Do whatever you want with the signed message
  });

Sign Transaction

This assumes usage of the solana_web3 package.

To sign a transaction, you can call

final cluster = Cluster.mainnet;
final connection = Connection(cluster);

final BlockhashWithExpiryBlockHeight blockhash =
    await connection.getLatestBlockhash();

final transaction = Transaction.v0(
    payer:
        Pubkey.fromBase58("Ez9MDm59vRftZS63KSbTdM4ujUEwftRC3wkRmMxu5XWz"),
    recentBlockhash: blockhash.blockhash,
    instructions: [
      SystemProgram.transfer(
        fromPubkey: Pubkey.fromBase58(
            "Ez9MDm59vRftZS63KSbTdM4ujUEwftRC3wkRmMxu5XWz"),
        toPubkey: Pubkey.fromBase58(
            "HVMgc1okoZ1fzkpSAABoirViU83rqNRnVcEisjtgdNZC"),
        lamports: solToLamports(0.5),
      ),
    ]);

final signedTransaction =
    await phantomConnector.signTransaction(transaction);

Sign and Send Transaction

This assumes usage of the solana_web3 package.

To sign a transaction, you can call

final cluster = Cluster.mainnet;
final connection = Connection(cluster);

final BlockhashWithExpiryBlockHeight blockhash =
    await connection.getLatestBlockhash();

final transaction = Transaction.v0(
    payer:
        Pubkey.fromBase58("Ez9MDm59vRftZS63KSbTdM4ujUEwftRC3wkRmMxu5XWz"),
    recentBlockhash: blockhash.blockhash,
    instructions: [
      SystemProgram.transfer(
        fromPubkey: Pubkey.fromBase58(
            "Ez9MDm59vRftZS63KSbTdM4ujUEwftRC3wkRmMxu5XWz"),
        toPubkey: Pubkey.fromBase58(
            "HVMgc1okoZ1fzkpSAABoirViU83rqNRnVcEisjtgdNZC"),
        lamports: solToLamports(0.5),
      ),
    ]);

final signature =
    await phantomConnector.signAndSendTransaction(transaction);

MetaMask Connector

Setup

In the same place where you instantiate the Para Client, you will need to also instantiate the Phantom Connector.

final para = Para(
  environment: Environment.beta,
  apiKey: apiKey,
);

final metamaskConnector = ParaMetaMaskConnector(
    para: para, appUrl: <YOUR_APP_URL>, deepLink: "<YOUR_APP_DEEPLINK_SCHEME>");

Connecting

After setup, all you need to do is call

metamaskConnector.connect();

This will open the MetaMask wallet and connect it to your app.

Sign Message

To sign a message, you can call

metamaskConnector
    .signMessage(
        "Message to sign! Hello World", metamaskConnector.accounts.first) // you can select whichever account if multiple
    .then((onValue) => {
        print(onValue); // Do whatever you want with the signed message
    });

Send Transaction

This assumes usage of the web3dart package.

To send a transaction, you can call

final transaction = Transaction(
    from: EthereumAddress.fromHex(metamaskConnector.accounts.first),
    to: EthereumAddress.fromHex('0x13158486860B81Dee9e43Dd0391e61c2F82B577F'),
    value: EtherAmount.inWei(BigInt.from(10000000000000000)),
    maxGas: 100000,
    gasPrice: EtherAmount.inWei(BigInt.from(1000000000)),
);

metamaskConnector
    .sendTransaction(transaction, metamaskConnector.accounts.first)
    .then((onValue) => {
        ScaffoldMessenger.of(context).showSnackBar(
        SnackBar(
            content: Text('Transaction signed: $onValue'),
        ),
        )
    });