{"id":1805,"date":"2022-01-07T08:52:15","date_gmt":"2022-01-07T14:52:15","guid":{"rendered":"https:\/\/www.becomebetterprogrammer.com\/?p=1805"},"modified":"2022-04-25T09:37:11","modified_gmt":"2022-04-25T14:37:11","slug":"web3-react-connect-to-phantom","status":"publish","type":"post","link":"https:\/\/www.becomebetterprogrammer.com\/staging\/4563\/web3-react-connect-to-phantom\/","title":{"rendered":"How to Connect a Web3 React App to Phantom using TypeScript"},"content":{"rendered":"\n<p>If you are interested in web3 development, one of the fundamental aspects of developing a web3 app is to establish a connection between the app and a wallet. In fact, chances are this is the initial step to &#8220;authenticate&#8221; or &#8220;login&#8221; users without the need of having a database to store their account information.<\/p>\n\n\n\n<p>In this tutorial, you are going to learn how to connect a Web3 React app to a Phantom Wallet. Although it might sound complicated, it is not as hard as it sounds. Also, take into account you don&#8217;t have to use React to connect to a Phantom wallet. Once you learn the core concepts, you can use any other JavaScript frontend framework or library to establish a connection to a Phantom wallet.<\/p>\n\n\n\n<div id=\"ez-toc-container\" class=\"ez-toc-v2_0_82_2 counter-hierarchy ez-toc-counter ez-toc-custom ez-toc-container-direction\">\n<div class=\"ez-toc-title-container\"><p class=\"ez-toc-title\" style=\"cursor:inherit\">Table of Contents<\/p>\n<\/div><nav><ul class='ez-toc-list ez-toc-list-level-1 ' ><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-1\" href=\"https:\/\/www.becomebetterprogrammer.com\/staging\/4563\/web3-react-connect-to-phantom\/#What_is_Phantom\" >What is Phantom?<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-2\" href=\"https:\/\/www.becomebetterprogrammer.com\/staging\/4563\/web3-react-connect-to-phantom\/#Step-by-Step_Connect_a_Web3_React_App_to_a_Phantom_Wallet\" >Step-by-Step: Connect a Web3 React App to a Phantom Wallet<\/a><ul class='ez-toc-list-level-3' ><li class='ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-3\" href=\"https:\/\/www.becomebetterprogrammer.com\/staging\/4563\/web3-react-connect-to-phantom\/#Pre-requisites\" >Pre-requisites<\/a><ul class='ez-toc-list-level-4' ><li class='ez-toc-heading-level-4'><a class=\"ez-toc-link ez-toc-heading-4\" href=\"https:\/\/www.becomebetterprogrammer.com\/staging\/4563\/web3-react-connect-to-phantom\/#Use_Chrome_Brave_Firefox_or_Edge_Browser\" >Use Chrome, Brave, Firefox, or Edge Browser<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-4'><a class=\"ez-toc-link ez-toc-heading-5\" href=\"https:\/\/www.becomebetterprogrammer.com\/staging\/4563\/web3-react-connect-to-phantom\/#Create_a_Phantom_Wallet\" >Create a Phantom Wallet<\/a><\/li><\/ul><\/li><li class='ez-toc-page-1 ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-6\" href=\"https:\/\/www.becomebetterprogrammer.com\/staging\/4563\/web3-react-connect-to-phantom\/#Creating_the_React_App_using_TypeScript\" >Creating the React App using TypeScript<\/a><ul class='ez-toc-list-level-4' ><li class='ez-toc-heading-level-4'><a class=\"ez-toc-link ez-toc-heading-7\" href=\"https:\/\/www.becomebetterprogrammer.com\/staging\/4563\/web3-react-connect-to-phantom\/#Install_dependencies\" >Install dependencies<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-4'><a class=\"ez-toc-link ez-toc-heading-8\" href=\"https:\/\/www.becomebetterprogrammer.com\/staging\/4563\/web3-react-connect-to-phantom\/#Detect_Phantom_Provider_Exists\" >Detect Phantom Provider Exists<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-4'><a class=\"ez-toc-link ez-toc-heading-9\" href=\"https:\/\/www.becomebetterprogrammer.com\/staging\/4563\/web3-react-connect-to-phantom\/#Connect_to_Phantom_Wallet\" >Connect to Phantom Wallet<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-4'><a class=\"ez-toc-link ez-toc-heading-10\" href=\"https:\/\/www.becomebetterprogrammer.com\/staging\/4563\/web3-react-connect-to-phantom\/#Display_Account_and_Hide_%E2%80%9CConnect_to_Wallet%E2%80%9D_button\" >Display Account and Hide &#8220;Connect to Wallet&#8221; button<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-4'><a class=\"ez-toc-link ez-toc-heading-11\" href=\"https:\/\/www.becomebetterprogrammer.com\/staging\/4563\/web3-react-connect-to-phantom\/#Add_button_to_disconnect_from_the_Phantom_Wallet\" >Add button to disconnect from the Phantom Wallet<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-4'><a class=\"ez-toc-link ez-toc-heading-12\" href=\"https:\/\/www.becomebetterprogrammer.com\/staging\/4563\/web3-react-connect-to-phantom\/#Final_Code\" >Final Code<\/a><\/li><\/ul><\/li><\/ul><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-13\" href=\"https:\/\/www.becomebetterprogrammer.com\/staging\/4563\/web3-react-connect-to-phantom\/#Conclusion\" >Conclusion<\/a><\/li><\/ul><\/nav><\/div>\n<h2 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"What_is_Phantom\"><\/span>What is Phantom?<span class=\"ez-toc-section-end\"><\/span><\/h2>\n\n\n\n<p><a href=\"https:\/\/phantom.app\/\" target=\"_blank\" rel=\"noreferrer noopener\">Phantom<\/a> is a crypto wallet that enables users to send and receive tokens, collect NFTs, and even allow to connect to a hardware wallet. Phantom developed a browser extension to not only have quick access to your wallet but also enable web3 apps to access JavaScript <code>solana<\/code> to detect if the Phantom provider is available.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"Step-by-Step_Connect_a_Web3_React_App_to_a_Phantom_Wallet\"><\/span>Step-by-Step: Connect a Web3 React App to a Phantom Wallet<span class=\"ez-toc-section-end\"><\/span><\/h2>\n\n\n\n<p>This is the workflow of this tutorial: We are going to start by creating our React app. Then, we will detect if the Phantom provider is available. We will create a button to establish a connection to a Phantom wallet. Once we are connected to the account, we will generate another button to disconnect from the wallet.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"Pre-requisites\"><\/span>Pre-requisites<span class=\"ez-toc-section-end\"><\/span><\/h3>\n\n\n\n<h4 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"Use_Chrome_Brave_Firefox_or_Edge_Browser\"><\/span>Use Chrome, Brave, Firefox, or Edge Browser<span class=\"ez-toc-section-end\"><\/span><\/h4>\n\n\n\n<p>As previously mentioned, Phantom has a browser extension to &#8220;turn your browser to a crypto wallet&#8221;, just like they say on their <a href=\"https:\/\/phantom.app\/\" target=\"_blank\" rel=\"noreferrer noopener\">site<\/a>. At the moment of this writing, the Phantom browser extension is available in the following browsers:<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li>Chrome<\/li><li>Brave<\/li><li>Firefox<\/li><li>Edge<\/li><\/ul>\n\n\n\n<p>Therefore, make sure to use any of those browsers when testing the application.<\/p>\n\n\n\n<p><strong>Note<\/strong>: this tutorial was tested in chrome <\/p>\n\n\n\n<h4 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"Create_a_Phantom_Wallet\"><\/span>Create a Phantom Wallet<span class=\"ez-toc-section-end\"><\/span><\/h4>\n\n\n\n<p>Before we move forward, make sure you have an existing wallet. Feel free to skip this section if you already have an existing wallet you can use to establish a connection. On the other hand, if you don&#8217;t have a wallet, make sure to create one.<\/p>\n\n\n\n<h5 class=\"wp-block-heading\">Install Phantom Browser Extension<\/h5>\n\n\n\n<p>Install the phantom browser extension to the browser you want to use:<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li><a href=\"https:\/\/chrome.google.com\/webstore\/detail\/phantom\/bfnaelmomeimhlpmgjnjophhpkkoljpa\" target=\"_blank\" rel=\"noopener\">Chrome Phantom Browser Extension<\/a><\/li><li><a href=\"https:\/\/chrome.google.com\/webstore\/detail\/phantom\/bfnaelmomeimhlpmgjnjophhpkkoljpa\/related\" target=\"_blank\" rel=\"noreferrer noopener\">Brave Phantom Browser Extension<\/a><\/li><li><a href=\"https:\/\/addons.mozilla.org\/en-US\/firefox\/addon\/phantom-app\/\" target=\"_blank\" rel=\"noreferrer noopener\">Firefox Phantom Browser Extension<\/a><\/li><li><a href=\"https:\/\/chrome.google.com\/webstore\/detail\/phantom\/bfnaelmomeimhlpmgjnjophhpkkoljpa\" target=\"_blank\" rel=\"noreferrer noopener\">Edge Phantom Browser Extension<\/a><\/li><\/ul>\n\n\n\n<h5 class=\"wp-block-heading\">Create a New Wallet<\/h5>\n\n\n\n<p>Once the Phantom Browser Extension is installed, you will be redirected to a page to create a new wallet. Click on &#8220;Create New Wallet&#8221;.<\/p>\n\n\n\n<div class=\"wp-block-image\"><figure class=\"aligncenter size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"547\" height=\"633\" src=\"https:\/\/www.becomebetterprogrammer.com\/wp-content\/uploads\/2022\/01\/Create-new-phantom-wallet.png\" alt=\"\" class=\"wp-image-1811\" title=\"Create a New Phantom Wallet\" srcset=\"https:\/\/www.becomebetterprogrammer.com\/staging\/4563\/wp-content\/uploads\/2022\/01\/Create-new-phantom-wallet.png 547w, https:\/\/www.becomebetterprogrammer.com\/staging\/4563\/wp-content\/uploads\/2022\/01\/Create-new-phantom-wallet-259x300.png 259w\" sizes=\"auto, (max-width: 547px) 100vw, 547px\" \/><figcaption>Create a New Phantom Wallet<\/figcaption><\/figure><\/div>\n\n\n\n<h5 class=\"wp-block-heading\">Save Recovery Phrase<\/h5>\n\n\n\n<p>After creating your Phantom wallet, you will be given a secret recovery phrase. Save it in a safe place. I recommend using a password manager to save this information.<\/p>\n\n\n\n<div class=\"wp-block-image\"><figure class=\"aligncenter size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"547\" height=\"623\" src=\"https:\/\/www.becomebetterprogrammer.com\/wp-content\/uploads\/2022\/01\/Save-secret-recovery-phrase-1.png\" alt=\"\" class=\"wp-image-1813\" title=\"Save secret recovery phrase\" srcset=\"https:\/\/www.becomebetterprogrammer.com\/staging\/4563\/wp-content\/uploads\/2022\/01\/Save-secret-recovery-phrase-1.png 547w, https:\/\/www.becomebetterprogrammer.com\/staging\/4563\/wp-content\/uploads\/2022\/01\/Save-secret-recovery-phrase-1-263x300.png 263w\" sizes=\"auto, (max-width: 547px) 100vw, 547px\" \/><figcaption>Save secret recovery phrase<\/figcaption><\/figure><\/div>\n\n\n\n<p>Once you save it, click on &#8220;OK, I saved it somewhere&#8221;.<\/p>\n\n\n\n<h5 class=\"wp-block-heading\">Create a password for your Phantom Wallet<\/h5>\n\n\n\n<p>After saving the recovery phrase, it will prompt you to create a password. Go ahead and create your password. Agree to terms of service and click &#8220;Continue&#8221;.<\/p>\n\n\n\n<div class=\"wp-block-image\"><figure class=\"aligncenter size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"551\" height=\"627\" src=\"https:\/\/www.becomebetterprogrammer.com\/wp-content\/uploads\/2022\/01\/Create-a-password-for-your-wallet.png\" alt=\"\" class=\"wp-image-1814\" srcset=\"https:\/\/www.becomebetterprogrammer.com\/staging\/4563\/wp-content\/uploads\/2022\/01\/Create-a-password-for-your-wallet.png 551w, https:\/\/www.becomebetterprogrammer.com\/staging\/4563\/wp-content\/uploads\/2022\/01\/Create-a-password-for-your-wallet-264x300.png 264w\" sizes=\"auto, (max-width: 551px) 100vw, 551px\" \/><figcaption>Create a password for your Phantom Wallet<\/figcaption><\/figure><\/div>\n\n\n\n<p>Once you do this, you can access your Phantom wallet by clicking the browser extension.<\/p>\n\n\n\n<div class=\"wp-block-image\"><figure class=\"aligncenter size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"521\" height=\"733\" src=\"https:\/\/www.becomebetterprogrammer.com\/wp-content\/uploads\/2022\/01\/Accessing-wallet-using-Phantom-browser-extension.png\" alt=\"\" class=\"wp-image-1815\" title=\"Accessing wallet using Phantom browser extension\" srcset=\"https:\/\/www.becomebetterprogrammer.com\/staging\/4563\/wp-content\/uploads\/2022\/01\/Accessing-wallet-using-Phantom-browser-extension.png 521w, https:\/\/www.becomebetterprogrammer.com\/staging\/4563\/wp-content\/uploads\/2022\/01\/Accessing-wallet-using-Phantom-browser-extension-213x300.png 213w\" sizes=\"auto, (max-width: 521px) 100vw, 521px\" \/><figcaption>Accessing wallet using the Phantom browser extension<\/figcaption><\/figure><\/div>\n\n\n\n<h3 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"Creating_the_React_App_using_TypeScript\"><\/span>Creating the React App using TypeScript<span class=\"ez-toc-section-end\"><\/span><\/h3>\n\n\n\n<p>Time to start building the app. First, generate a new react project using Typescript using the following command.<\/p>\n\n\n\n<p><strong>Note<\/strong>: Feel free to name your project to other than <code>web3-connect-phantom-wallet<\/code>.<\/p>\n\n\n\n<pre class=\"wp-block-code language-bash\"><code>npx create-react-app web3-connect-phantom-wallet --template typescript<\/code><\/pre>\n\n\n\n<h4 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"Install_dependencies\"><\/span>Install dependencies<span class=\"ez-toc-section-end\"><\/span><\/h4>\n\n\n\n<p>For this tutorial, we need to install <a href=\"https:\/\/www.npmjs.com\/package\/@solana\/web3.js\" target=\"_blank\" rel=\"noreferrer noopener\">@solana\/web3.js<\/a>. Go ahead and add it.<\/p>\n\n\n\n<pre class=\"wp-block-code language-bash\"><code>yarn add @solana\/web3.js<\/code><\/pre>\n\n\n\n<h4 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"Detect_Phantom_Provider_Exists\"><\/span>Detect Phantom Provider Exists<span class=\"ez-toc-section-end\"><\/span><\/h4>\n\n\n\n<p>Prior to attempting to connect to a wallet, we need to first detect the existence of the wallet provider, in other words, whoever is providing with software to hold, store, or transfer digital currency. In this case, we are looking to detect if Phantom exists.<\/p>\n\n\n\n<h5 class=\"wp-block-heading\">Adding PhantomProvider Interface<\/h5>\n\n\n\n<p>First, we need to generate TypeScript interfaces to easily identify all the properties of the Phantom provider inside the <em>App.tsx<\/em> file.<\/p>\n\n\n\n<pre class=\"wp-block-code language-typescript\"><code>import {\n  PublicKey,\n  Transaction,\n} from \"@solana\/web3.js\";\n\n\n\ntype DisplayEncoding = \"utf8\" | \"hex\";\ntype PhantomEvent = \"disconnect\" | \"connect\" | \"accountChanged\";\ntype PhantomRequestMethod =\n  | \"connect\"\n  | \"disconnect\"\n  | \"signTransaction\"\n  | \"signAllTransactions\"\n  | \"signMessage\";\n\ninterface ConnectOpts {\n  onlyIfTrusted: boolean;\n}\n\ninterface PhantomProvider {\n  publicKey: PublicKey | null;\n  isConnected: boolean | null;\n  signTransaction: (transaction: Transaction) =&gt; Promise&lt;Transaction&gt;;\n  signAllTransactions: (transactions: Transaction&#91;]) =&gt; Promise&lt;Transaction&#91;]&gt;;\n  signMessage: (\n    message: Uint8Array | string,\n    display?: DisplayEncoding\n  ) =&gt; Promise&lt;any&gt;;\n  connect: (opts?: Partial&lt;ConnectOpts&gt;) =&gt; Promise&lt;{ publicKey: PublicKey }&gt;;\n  disconnect: () =&gt; Promise&lt;void&gt;;\n  on: (event: PhantomEvent, handler: (args: any) =&gt; void) =&gt; void;\n  request: (method: PhantomRequestMethod, params: any) =&gt; Promise&lt;unknown&gt;;\n}<\/code><\/pre>\n\n\n\n<h5 class=\"wp-block-heading\">Generate function to get provider<\/h5>\n\n\n\n<p>Next, add inside the App component a <code>getProvider<\/code> variable to store a function that gets a wallet provider.<\/p>\n\n\n\n<pre class=\"wp-block-code language-typescript\"><code>  \/**\n   * @description gets Phantom provider, if it exists\n   *\/\n  const getProvider = (): PhantomProvider | undefined =&gt; {\n    if (\"solana\" in window) {\n      \/\/ @ts-ignore\n      const provider = window.solana as any;\n      if (provider.isPhantom) return provider as PhantomProvider;\n    }\n  };<\/code><\/pre>\n\n\n\n<p>If you have worked in web development, you will find as a surprise the existence of a <code>solana<\/code> key property as part of the <code>window<\/code> object. This doesn&#8217;t mean the <code>window.solana<\/code> property has always existed. What happens is, the Phantom browser extension injects the <code>solana<\/code> object as a key of the <code>window<\/code> object to make easy the process of detecting the existence of a wallet provider.<\/p>\n\n\n\n<p>Having said that, if the Phantom browser extension is enabled in the browser, our app will identify the existence of the provider. On the other hand, if you decide to disable the browser extension, the app will not find the Phantom provider.<\/p>\n\n\n\n<h5 class=\"wp-block-heading\">Store the state of the provider<\/h5>\n\n\n\n<p>We are going to store the state of the provider in our app. This will help us determine what to display to the user based on whether the Phantom provider exists or not.<\/p>\n\n\n\n<p>First, import <code>useEffect<\/code> and <code>useState<\/code> from <code>react<\/code>.<\/p>\n\n\n\n<pre class=\"wp-block-code language-typescript\"><code>import { useEffect, useState } from \"react\";<\/code><\/pre>\n\n\n\n<p>Then, inside the App component, generate the variables to store and update the state of the provider.<\/p>\n\n\n\n<pre class=\"wp-block-code language-typescript\"><code>const &#91;provider, setProvider] = useState&lt;PhantomProvider | undefined&gt;(\n    undefined\n  );<\/code><\/pre>\n\n\n\n<p>Now, add the following logic below the <code>getProvider<\/code> variable to set the state of the provider.<\/p>\n\n\n\n<pre class=\"wp-block-code language-typescript\"><code>\/\/ detect phantom provider exists\n  useEffect(() =&gt; {\n    const provider = getProvider();\n\n    if (provider) setProvider(provider);\n    else setProvider(undefined);\n  }, &#91;]);<\/code><\/pre>\n\n\n\n<p>Notice this code will only execute once the component mounts <a href=\"https:\/\/reactjs.org\/docs\/hooks-effect.html\" target=\"_blank\" rel=\"noreferrer noopener\">because we are using an empty array <code>[]<\/code> as a second argument of the <code>useEffect<\/code> function.<\/a> This is important as we don&#8217;t want to constantly update the provider every time the app re-renders.<\/p>\n\n\n\n<h5 class=\"wp-block-heading\">Add logic to display content based on state of the provider<\/h5>\n\n\n\n<p>Finally, update the UI based on the state of the provider. If the provider exists, add a button to connect to the Phantom wallet. Otherwise, show a message suggesting the user to install the Phantom Browser extension.<\/p>\n\n\n\n<pre class=\"wp-block-code language-typescript\"><code>return (\n    &lt;div className=\"App\"&gt;\n      &lt;header className=\"App-header\"&gt;\n        &lt;h2&gt;Tutorial: Connect to Phantom Wallet&lt;\/h2&gt;\n        {provider &amp;&amp; (\n          &lt;button\n            style={{\n              fontSize: \"16px\",\n              padding: \"15px\",\n              fontWeight: \"bold\",\n              borderRadius: \"5px\",\n            }}\n          &gt;\n            Connect to Phantom Wallet\n          &lt;\/button&gt;\n        )}\n\n        {!provider &amp;&amp; (\n          &lt;p&gt;\n            No provider found. Install{\" \"}\n            &lt;a href=\"https:\/\/phantom.app\/\"&gt;Phantom Browser extension&lt;\/a&gt;\n          &lt;\/p&gt;\n        )}\n\n        &lt;p&gt;\n          Built by{\" \"}\n          &lt;a\n            href=\"https:\/\/twitter.com\/arealesramirez\"\n            target=\"_blank\"\n            rel=\"noreferrer\"\n            className=\"twitter-link\"\n          &gt;\n            @arealesramirez\n          &lt;\/a&gt;\n        &lt;\/p&gt;\n      &lt;\/header&gt;\n    &lt;\/div&gt;<\/code><\/pre>\n\n\n\n<p>Open the<em> App.css<\/em> to add some styling to the links and buttons we added.<\/p>\n\n\n\n<pre class=\"wp-block-code language-css\"><code>a {\n  color: white;\n}\n.twitter-link {\n  color: \"white\";\n  font-size: \"16px\";\n  margin-top: \"15px\";\n  margin-bottom: \"15px\";\n}<\/code><\/pre>\n\n\n\n<h5 class=\"wp-block-heading\">Test the logic<\/h5>\n\n\n\n<p>That was quite a bit of explanation, which hopefully will make sense once we start running our app.<\/p>\n\n\n\n<pre class=\"wp-block-code language-bash\"><code>yarn start<\/code><\/pre>\n\n\n\n<p>Notice how the &#8220;Connect to Phantom Wallet&#8221; button is displayed whenever the Phantom browser extension is available.<\/p>\n\n\n\n<div class=\"wp-block-image\"><figure class=\"aligncenter size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"1024\" src=\"https:\/\/www.becomebetterprogrammer.com\/wp-content\/uploads\/2022\/01\/Connect-to-Phantom-Wallet-button-displayed-1024x1024.png\" alt=\"\" class=\"wp-image-1819\" title=\"Connect to Phantom Wallet button displayed\" srcset=\"https:\/\/www.becomebetterprogrammer.com\/staging\/4563\/wp-content\/uploads\/2022\/01\/Connect-to-Phantom-Wallet-button-displayed-1024x1024.png 1024w, https:\/\/www.becomebetterprogrammer.com\/staging\/4563\/wp-content\/uploads\/2022\/01\/Connect-to-Phantom-Wallet-button-displayed-300x300.png 300w, https:\/\/www.becomebetterprogrammer.com\/staging\/4563\/wp-content\/uploads\/2022\/01\/Connect-to-Phantom-Wallet-button-displayed-150x150.png 150w, https:\/\/www.becomebetterprogrammer.com\/staging\/4563\/wp-content\/uploads\/2022\/01\/Connect-to-Phantom-Wallet-button-displayed-768x768.png 768w, https:\/\/www.becomebetterprogrammer.com\/staging\/4563\/wp-content\/uploads\/2022\/01\/Connect-to-Phantom-Wallet-button-displayed.png 1200w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><figcaption>Connect to Phantom Wallet button displayed<\/figcaption><\/figure><\/div>\n\n\n\n<p>Now, go ahead and disable the Phantom browser extension from your browser. Then, refresh the page. You should see a message prompting the user to install the browser extension.<\/p>\n\n\n\n<div class=\"wp-block-image\"><figure class=\"aligncenter size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"585\" src=\"https:\/\/www.becomebetterprogrammer.com\/wp-content\/uploads\/2022\/01\/Message-displayed-when-Phantom-browser-extensiosn-is-not-available-1024x585.png\" alt=\"\" class=\"wp-image-1820\" title=\"Message displayed when Phantom browser extension is not available\" srcset=\"https:\/\/www.becomebetterprogrammer.com\/staging\/4563\/wp-content\/uploads\/2022\/01\/Message-displayed-when-Phantom-browser-extensiosn-is-not-available-1024x585.png 1024w, https:\/\/www.becomebetterprogrammer.com\/staging\/4563\/wp-content\/uploads\/2022\/01\/Message-displayed-when-Phantom-browser-extensiosn-is-not-available-300x171.png 300w, https:\/\/www.becomebetterprogrammer.com\/staging\/4563\/wp-content\/uploads\/2022\/01\/Message-displayed-when-Phantom-browser-extensiosn-is-not-available-768x439.png 768w, https:\/\/www.becomebetterprogrammer.com\/staging\/4563\/wp-content\/uploads\/2022\/01\/Message-displayed-when-Phantom-browser-extensiosn-is-not-available-1536x877.png 1536w, https:\/\/www.becomebetterprogrammer.com\/staging\/4563\/wp-content\/uploads\/2022\/01\/Message-displayed-when-Phantom-browser-extensiosn-is-not-available.png 1599w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><figcaption>Message displayed when Phantom browser extension is not available<\/figcaption><\/figure><\/div>\n\n\n\n<p>Once proving the logic works, enable Phantom browser extension one more time.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"Connect_to_Phantom_Wallet\"><\/span>Connect to Phantom Wallet<span class=\"ez-toc-section-end\"><\/span><\/h4>\n\n\n\n<p>We have a &#8220;Connect to Phantom Wallet&#8221; button that doesn&#8217;t do anything as of now. Let&#8217;s create a function to trigger once the user clicks the button.<\/p>\n\n\n\n<p>First, generate a <code>walletKey<\/code> to store the public key of the connected account.<\/p>\n\n\n\n<pre class=\"wp-block-code language-typescript\"><code>const &#91;walletKey, setWalletKey] = useState&lt;PhantomProvider | undefined&gt;(\n    undefined\n  );<\/code><\/pre>\n\n\n\n<p>Then, add a <code>connectWallet<\/code> variable storing the function that makes the request to connect to the wallet below <code>getProvider<\/code>.<\/p>\n\n\n\n<pre class=\"wp-block-code language-typescript\"><code>\/**\n   * @description prompts user to connect wallet if it exists\n   *\/\n  const connectWallet = async () =&gt; {\n    \/\/ @ts-ignore\n    const { solana } = window;\n\n    if (solana) {\n      try {\n        const response = await solana.connect();\n        console.log('wallet account ', response.publicKey.toString());\n        setWalletKey(response.publicKey.toString());\n      } catch (err) {\n       \/\/ { code: 4001, message: 'User rejected the request.' }\n      }\n    }\n  };\n<\/code><\/pre>\n\n\n\n<p>Finally, wire up the button to trigger <code>connectWallet<\/code> once the button is clicked.<\/p>\n\n\n\n<pre class=\"wp-block-code language-typescript\"><code>&lt;button\n            style={{\n              fontSize: \"16px\",\n              padding: \"15px\",\n              fontWeight: \"bold\",\n              borderRadius: \"5px\",\n            }}\n            onClick={connectWallet}\n          &gt;\n            Connect to Phantom Wallet\n          &lt;\/button&gt;<\/code><\/pre>\n\n\n\n<p>Test the logic by going back to the browser and clicking on the &#8220;Connect to Phantom Wallet&#8221; button. You should see a Phantom browser extension prompting you to whether connect the app.<\/p>\n\n\n\n<div class=\"wp-block-image\"><figure class=\"aligncenter size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"343\" height=\"565\" src=\"https:\/\/www.becomebetterprogrammer.com\/wp-content\/uploads\/2022\/01\/After-clicking-button-to-connect-to-the-wallet-for-the-first-time.png\" alt=\"\" class=\"wp-image-1821\" title=\"After clicking button to connect to the wallet for the first time\" srcset=\"https:\/\/www.becomebetterprogrammer.com\/staging\/4563\/wp-content\/uploads\/2022\/01\/After-clicking-button-to-connect-to-the-wallet-for-the-first-time.png 343w, https:\/\/www.becomebetterprogrammer.com\/staging\/4563\/wp-content\/uploads\/2022\/01\/After-clicking-button-to-connect-to-the-wallet-for-the-first-time-182x300.png 182w\" sizes=\"auto, (max-width: 343px) 100vw, 343px\" \/><figcaption>After clicking the button to connect to the wallet for the first time<\/figcaption><\/figure><\/div>\n\n\n\n<p>This is a mechanism to ensure we are trusting to connect our account with any site. Click on &#8220;Connect&#8221;. This will add our app as part of the list of trusted apps.<\/p>\n\n\n\n<h5 class=\"wp-block-heading\">Finding the list of trusted apps in the Phantom wallet<\/h5>\n\n\n\n<p>You can always verify the list of trusted apps in our Phantom wallet. To find them, <\/p>\n\n\n\n<ol class=\"wp-block-list\"><li>Click on the Phantom browser extension<\/li><li>Click on the Settings icon<\/li><li>Click on the &#8220;Trusted Apps&#8221; option<\/li><li>Verify our app is trusted by verifying the address, which is <em>localhost:3000<\/em> since we are currently developing in our local environment.<\/li><\/ol>\n\n\n\n<p><\/p>\n\n\n\n<div class=\"wp-block-image\"><figure class=\"aligncenter size-large is-resized\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/www.becomebetterprogrammer.com\/wp-content\/uploads\/2022\/01\/Finding-Phantom-wallet-trusted-apps-1024x1024.png\" alt=\"\" class=\"wp-image-1823\" width=\"819\" height=\"819\" srcset=\"https:\/\/www.becomebetterprogrammer.com\/staging\/4563\/wp-content\/uploads\/2022\/01\/Finding-Phantom-wallet-trusted-apps-1024x1024.png 1024w, https:\/\/www.becomebetterprogrammer.com\/staging\/4563\/wp-content\/uploads\/2022\/01\/Finding-Phantom-wallet-trusted-apps-300x300.png 300w, https:\/\/www.becomebetterprogrammer.com\/staging\/4563\/wp-content\/uploads\/2022\/01\/Finding-Phantom-wallet-trusted-apps-150x150.png 150w, https:\/\/www.becomebetterprogrammer.com\/staging\/4563\/wp-content\/uploads\/2022\/01\/Finding-Phantom-wallet-trusted-apps-768x768.png 768w, https:\/\/www.becomebetterprogrammer.com\/staging\/4563\/wp-content\/uploads\/2022\/01\/Finding-Phantom-wallet-trusted-apps.png 1200w\" sizes=\"auto, (max-width: 819px) 100vw, 819px\" \/><figcaption>Finding Phantom wallet trusted apps<\/figcaption><\/figure><\/div>\n\n\n\n<h4 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"Display_Account_and_Hide_%E2%80%9CConnect_to_Wallet%E2%80%9D_button\"><\/span>Display Account and Hide &#8220;Connect to Wallet&#8221; button<span class=\"ez-toc-section-end\"><\/span><\/h4>\n\n\n\n<p>Once the account is connected, it is not necessary to have available the &#8220;Connect to Phantom Wallet&#8221; button. Hence, we are going to check if the <code>walletKey<\/code> does not exist. If so, do not display the button. Also, add a check to verify the <code>walletKey<\/code> exists to display the account to the user.<\/p>\n\n\n\n<pre class=\"wp-block-code language-typescript\"><code>{provider &amp;&amp; !walletKey &amp;&amp; (\n          &lt;button\n            style={{\n              fontSize: \"16px\",\n              padding: \"15px\",\n              fontWeight: \"bold\",\n              borderRadius: \"5px\",\n            }}\n            onClick={connectWallet}\n          &gt;\n            Connect to Phantom Wallet\n          &lt;\/button&gt;\n        )}\n\n        {provider &amp;&amp; walletKey &amp;&amp; &lt;p&gt;Connected account {walletKey}&lt;\/p&gt;}\n<\/code><\/pre>\n\n\n\n<p>Refresh the app and verify the account is displayed once you connect to the wallet, and check the &#8220;Connect to wallet&#8221; button is no longer enabled.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"Add_button_to_disconnect_from_the_Phantom_Wallet\"><\/span>Add button to disconnect from the Phantom Wallet<span class=\"ez-toc-section-end\"><\/span><\/h4>\n\n\n\n<p>Just like when you log in to a traditional app, you want to have the option to log out. In this case, we want to connect and disconnect to a digital wallet.<\/p>\n\n\n\n<p>To allow users to disconnect the wallet, use the <code>disconnect()<\/code> function provided by Solana. To do this, we are going to create a <code>disconnectWallet<\/code> variable and assign the following function.<\/p>\n\n\n\n<pre class=\"wp-block-code language-typescript\"><code>\/**\n   * @description disconnect Phantom wallet \n   *\/\n  const disconnectWallet = async () =&gt; {\n    \/\/ @ts-ignore\n    const { solana } = window;\n\n    if (walletKey &amp;&amp; solana) {\n      await (solana as PhantomProvider).disconnect();\n      setWalletKey(undefined);\n    }\n  };<\/code><\/pre>\n\n\n\n<p>Add a disconnect button which will trigger the <code>disconnectWallet<\/code> function.<\/p>\n\n\n\n<pre class=\"wp-block-code language-typescript\"><code>{provider &amp;&amp; walletKey &amp;&amp; (\n          &lt;div&gt;\n            &lt;p&gt;Connected account {walletKey}&lt;\/p&gt;\n\n            &lt;button\n              style={{\n                fontSize: \"16px\",\n                padding: \"15px\",\n                fontWeight: \"bold\",\n                borderRadius: \"5px\",\n                margin: \"15px auto\",\n              }}\n              onClick={disconnectWallet}\n            &gt;\n              Disconnect\n            &lt;\/button&gt;\n          &lt;\/div&gt;\n        )}<\/code><\/pre>\n\n\n\n<p>Go to your browser and verify the account is not available after you click the &#8220;Disconnect&#8221; button.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"Final_Code\"><\/span>Final Code<span class=\"ez-toc-section-end\"><\/span><\/h4>\n\n\n\n<p>If for any reason something wasn&#8217;t working as expected and you are stuck trying to figure out what is going, feel free to compare it with the final code.<\/p>\n\n\n\n<pre class=\"wp-block-code language-typescript\"><code>import { useEffect, useState } from \"react\";\nimport { PublicKey, Transaction } from \"@solana\/web3.js\";\n\nimport \".\/App.css\";\n\ntype DisplayEncoding = \"utf8\" | \"hex\";\ntype PhantomEvent = \"disconnect\" | \"connect\" | \"accountChanged\";\ntype PhantomRequestMethod =\n  | \"connect\"\n  | \"disconnect\"\n  | \"signTransaction\"\n  | \"signAllTransactions\"\n  | \"signMessage\";\n\ninterface ConnectOpts {\n  onlyIfTrusted: boolean;\n}\n\ninterface PhantomProvider {\n  publicKey: PublicKey | null;\n  isConnected: boolean | null;\n  signTransaction: (transaction: Transaction) =&gt; Promise&lt;Transaction&gt;;\n  signAllTransactions: (transactions: Transaction&#91;]) =&gt; Promise&lt;Transaction&#91;]&gt;;\n  signMessage: (\n    message: Uint8Array | string,\n    display?: DisplayEncoding\n  ) =&gt; Promise&lt;any&gt;;\n  connect: (opts?: Partial&lt;ConnectOpts&gt;) =&gt; Promise&lt;{ publicKey: PublicKey }&gt;;\n  disconnect: () =&gt; Promise&lt;void&gt;;\n  on: (event: PhantomEvent, handler: (args: any) =&gt; void) =&gt; void;\n  request: (method: PhantomRequestMethod, params: any) =&gt; Promise&lt;unknown&gt;;\n}\n\nfunction App() {\n  const &#91;provider, setProvider] = useState&lt;PhantomProvider | undefined&gt;(\n    undefined\n  );\n  const &#91;walletKey, setWalletKey] = useState&lt;PhantomProvider | undefined&gt;(\n    undefined\n  );\n\n  \/**\n   * @description gets Phantom provider, if it exists\n   *\/\n  const getProvider = (): PhantomProvider | undefined =&gt; {\n    if (\"solana\" in window) {\n      \/\/ @ts-ignore\n      const provider = window.solana as any;\n      if (provider.isPhantom) return provider as PhantomProvider;\n    }\n  };\n\n  \/**\n   * @description prompts user to connect wallet if it exists\n   *\/\n  const connectWallet = async () =&gt; {\n    \/\/ @ts-ignore\n    const { solana } = window;\n\n    if (solana) {\n      try {\n        const response = await solana.connect();\n        console.log(\"wallet account \", response.publicKey.toString());\n        setWalletKey(response.publicKey.toString());\n      } catch (err) {\n        \/\/ { code: 4001, message: 'User rejected the request.' }\n      }\n    }\n  };\n\n  \/**\n   * @description disconnect Phantom wallet \n   *\/\n  const disconnectWallet = async () =&gt; {\n    \/\/ @ts-ignore\n    const { solana } = window;\n\n    if (walletKey &amp;&amp; solana) {\n      await (solana as PhantomProvider).disconnect();\n      setWalletKey(undefined);\n    }\n  };\n\n  \/\/ detect phantom provider exists\n  useEffect(() =&gt; {\n    const provider = getProvider();\n\n    if (provider) setProvider(provider);\n    else setProvider(undefined);\n  }, &#91;]);\n\n  return (\n    &lt;div className=\"App\"&gt;\n      &lt;header className=\"App-header\"&gt;\n        &lt;h2&gt;Tutorial: Connect to Phantom Wallet&lt;\/h2&gt;\n        {provider &amp;&amp; !walletKey &amp;&amp; (\n          &lt;button\n            style={{\n              fontSize: \"16px\",\n              padding: \"15px\",\n              fontWeight: \"bold\",\n              borderRadius: \"5px\",\n            }}\n            onClick={connectWallet}\n          &gt;\n            Connect to Phantom Wallet\n          &lt;\/button&gt;\n        )}\n\n        {provider &amp;&amp; walletKey &amp;&amp; (\n          &lt;div&gt;\n            &lt;p&gt;Connected account {walletKey}&lt;\/p&gt;\n\n            &lt;button\n              style={{\n                fontSize: \"16px\",\n                padding: \"15px\",\n                fontWeight: \"bold\",\n                borderRadius: \"5px\",\n                margin: \"15px auto\",\n              }}\n              onClick={disconnectWallet}\n            &gt;\n              Disconnect\n            &lt;\/button&gt;\n          &lt;\/div&gt;\n        )}\n\n        {!provider &amp;&amp; (\n          &lt;p&gt;\n            No provider found. Install{\" \"}\n            &lt;a href=\"https:\/\/phantom.app\/\"&gt;Phantom Browser extension&lt;\/a&gt;\n          &lt;\/p&gt;\n        )}\n\n        &lt;p&gt;\n          Built by{\" \"}\n          &lt;a\n            href=\"https:\/\/twitter.com\/arealesramirez\"\n            target=\"_blank\"\n            rel=\"noreferrer\"\n            className=\"twitter-link\"\n          &gt;\n            @arealesramirez\n          &lt;\/a&gt;\n        &lt;\/p&gt;\n      &lt;\/header&gt;\n    &lt;\/div&gt;\n  );\n}\n\nexport default App;<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"Conclusion\"><\/span>Conclusion<span class=\"ez-toc-section-end\"><\/span><\/h2>\n\n\n\n<p>This tutorial explained how to connect to the Phantom wallet using the Phantom browser extension in a React app. However, after understanding how to connect and disconnect the wallet, you can use other frontend frameworks as all that you need is to have access to the <code>solana<\/code> object injected by the Phantom browser extension.<\/p>\n\n\n\n<p><strong>Did you like this article?<\/strong><\/p>\n\n\n\n<p>Share your thoughts by replying on <a href=\"https:\/\/twitter.com\/bbprogrammer\" target=\"_blank\" rel=\"noreferrer noopener\">Twitter of Become A Better Programmer<\/a> or to <a href=\"https:\/\/twitter.com\/arealesramirez\" target=\"_blank\" rel=\"noreferrer noopener\">my personal Twitter account<\/a>.<\/p>\n\n\n\n<figure class=\"wp-block-embed aligncenter is-type-rich is-provider-twitter wp-block-embed-twitter\"><div class=\"wp-block-embed__wrapper\">\n<blockquote class=\"twitter-tweet\" data-width=\"550\" data-dnt=\"true\"><p lang=\"en\" dir=\"ltr\">Do you know what is good? Today is Friday.<br><br>Do you know what is even better? The weekend to learn something about web3<br><br>Yep! Our first-ever tutorial related to web3 development.<br><br>Learn how to connect to <a href=\"https:\/\/twitter.com\/phantom?ref_src=twsrc%5Etfw\" target=\"_blank\" rel=\"noopener\">@phantom<\/a> wallet using a react app.<a href=\"https:\/\/twitter.com\/hashtag\/web3?src=hash&amp;ref_src=twsrc%5Etfw\" target=\"_blank\" rel=\"noopener\">#web3<\/a> <a href=\"https:\/\/twitter.com\/hashtag\/ReactJS?src=hash&amp;ref_src=twsrc%5Etfw\" target=\"_blank\" rel=\"noopener\">#ReactJS<\/a> <a href=\"https:\/\/t.co\/qlKCZdKwU3\">https:\/\/t.co\/qlKCZdKwU3<\/a><\/p>&mdash; Become A Better Programmer (@bbprogrammer) <a href=\"https:\/\/twitter.com\/bbprogrammer\/status\/1479466466273636360?ref_src=twsrc%5Etfw\" target=\"_blank\" rel=\"noopener\">January 7, 2022<\/a><\/blockquote><script async src=\"https:\/\/platform.twitter.com\/widgets.js\" charset=\"utf-8\"><\/script>\n<\/div><\/figure>\n\n\n\n<p> <\/p>\n","protected":false},"excerpt":{"rendered":"<p>Learn how to create a react app that connects to a Phantom wallet in an easy step-by-step tutorial to connect a web3 app.<\/p>\n","protected":false},"author":1,"featured_media":1829,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"nf_dc_page":"","_monsterinsights_skip_tracking":false,"_monsterinsights_sitenote_active":false,"_monsterinsights_sitenote_note":"","_monsterinsights_sitenote_category":0,"footnotes":""},"categories":[14,29],"tags":[],"class_list":["post-1805","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-tutorial","category-web3","generate-columns","tablet-grid-50","mobile-grid-100","grid-parent","grid-50"],"_links":{"self":[{"href":"https:\/\/www.becomebetterprogrammer.com\/staging\/4563\/wp-json\/wp\/v2\/posts\/1805","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.becomebetterprogrammer.com\/staging\/4563\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.becomebetterprogrammer.com\/staging\/4563\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.becomebetterprogrammer.com\/staging\/4563\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.becomebetterprogrammer.com\/staging\/4563\/wp-json\/wp\/v2\/comments?post=1805"}],"version-history":[{"count":5,"href":"https:\/\/www.becomebetterprogrammer.com\/staging\/4563\/wp-json\/wp\/v2\/posts\/1805\/revisions"}],"predecessor-version":[{"id":2467,"href":"https:\/\/www.becomebetterprogrammer.com\/staging\/4563\/wp-json\/wp\/v2\/posts\/1805\/revisions\/2467"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.becomebetterprogrammer.com\/staging\/4563\/wp-json\/wp\/v2\/media\/1829"}],"wp:attachment":[{"href":"https:\/\/www.becomebetterprogrammer.com\/staging\/4563\/wp-json\/wp\/v2\/media?parent=1805"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.becomebetterprogrammer.com\/staging\/4563\/wp-json\/wp\/v2\/categories?post=1805"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.becomebetterprogrammer.com\/staging\/4563\/wp-json\/wp\/v2\/tags?post=1805"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}