Introduction

This guide will help you use the Phantom redirect-based connect feature on mobile. Instead of deeplinking into the Phantom in-app browser, your users can enjoy a redirect-based connection, where they are automatically redirected between the app and their wallet to faciliate the connect, sign and additional method calls.

Tutorial

mobileExperience prop

Make sure you set mobileExperience to redirect on your DynamicContextProvider:

<DynamicContextProvider
  settings={{
    mobileExperience: 'redirect'
    // ... other settings
  }}
>

With just this code, your users will connect with the redirect-based approach. If you want to learn how to make method calls (like signAndSendTransaction) and access the result, read on

Signer methods

The redirect-based approach makes it a little trickier to access the result, and soon we will offer an easy-to-use hook to do so. For now, you will need this code in your app:

import { useState, useEffect } from 'react';

import {
  VersionedTransaction,
  Transaction,
} from '@solana/web3.js';

import { useDynamicContext } from '@dynamic-labs/sdk-react-core';
import { ISolana } from '@dynamic-labs/solana';
import {
  isPhantomRedirectConnector,
  SignAndSendTransactionListener,
} from '@dynamic-labs/wallet-connector-core';

const useSignAndSendTransaction = () => {
  const { primaryWallet } = useDynamicContext();

  const [signature, setSignature] = useState<string | undefined>(undefined);
  const [errorCode, setErrorCode] = useState<string | undefined>(undefined);
  const [errorMessage, setErrorMessage] = useState<string | undefined>(
    undefined,
  );

  useEffect(() => {
    if (!isPhantomRedirectConnector(primaryWallet?.connector)) return;
    const handler: SignAndSendTransactionListener = (response) => {
      if (response.signature) {
        setSignature(response.signature);
      } else {
        setErrorCode(response.errorCode);
        setErrorMessage(response.errorMessage);
      }
    };

    primaryWallet.connector.on('signAndSendTransaction', handler);
    return () => {
      if (!isPhantomRedirectConnector(primaryWallet?.connector)) return;
      primaryWallet.connector.off('signAndSendTransaction', handler);
    };
  }, [primaryWallet?.connector]);

  const execute = async (transaction: Transaction | VersionedTransaction) => {
    if (!primaryWallet) return;
    const signer = await primaryWallet.connector.getSigner<ISolana>();
    await signer.signAndSendTransaction(transaction);
  };

  return { errorCode, errorMessage, execute, signature };
};

You can render this hook in your app, and call execute on a button you render. This will trigger a redirect to the user’s wallet for signing, and if they accept the transaction, they will be redirected back to your app. Upon your app re-loading, this hook should be rendered again, and it’s state values will be populated – in this case the signature will contain the signature of the transcation.