<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[Kenny Rogers - Learn Stacks Development]]></title><description><![CDATA[Tutorials, Guides, and Philosophizings on Web3, Bitcoin, and Stacks]]></description><link>https://krgrs.dev</link><image><url>https://cdn.hashnode.com/res/hashnode/image/upload/v1675718178473/rtPiQteAp.png</url><title>Kenny Rogers - Learn Stacks Development</title><link>https://krgrs.dev</link></image><generator>RSS for Node</generator><lastBuildDate>Sun, 12 Apr 2026 19:10:16 GMT</lastBuildDate><atom:link href="https://krgrs.dev/rss.xml" rel="self" type="application/rss+xml"/><language><![CDATA[en]]></language><ttl>60</ttl><item><title><![CDATA[Getting Set Up with Stacks for Bitcoin App Development]]></title><description><![CDATA[Up until now, we've lived mainly inside of Bitcoin itself, learning about the internals of how it works.
During that, we've also been exposed to some of the main drawbacks of attempting to build fully decentralized applications on Bitcoin.
First, it ...]]></description><link>https://krgrs.dev/getting-set-up-with-stacks-for-bitcoin-app-development</link><guid isPermaLink="true">https://krgrs.dev/getting-set-up-with-stacks-for-bitcoin-app-development</guid><category><![CDATA[Bitcoin]]></category><category><![CDATA[Stacks]]></category><category><![CDATA[stacks.js]]></category><category><![CDATA[Web3]]></category><dc:creator><![CDATA[Kenny Rogers]]></dc:creator><pubDate>Wed, 22 Mar 2023 19:50:11 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1679514541844/36a612eb-3493-43f2-98e6-ef42596c1ece.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Up until now, we've lived mainly inside of Bitcoin itself, learning about the internals of how it works.</p>
<p>During that, we've also been exposed to some of the main drawbacks of attempting to build fully decentralized applications on Bitcoin.</p>
<p>First, it is difficult. The existing tooling for Bitcoin is not great for building apps like you would with Ethereum. It's confusing, clunky, and difficult to build robust apps, especially for someone used to making things on the web.</p>
<p>If you paid attention to the last tutorial, you might be wondering how we would actually go about creating our BitHealth app with a web interface.</p>
<p>For example, we talked about a hypothetical multisig setup where a member requests funding, and then a multisig is created to handle that.</p>
<p>What we would have to do here is create a web app where we would use a library like <a target="_blank" href="https://github.com/bitcoinjs/bitcoinjs-lib">BitcoinJS</a> to programmatically create a new P2SH wallet based on people that volunteered to contribute to that member's fund. Then members must use their own separate wallet app to pay to that address.</p>
<p>We could use something like the Hiro web wallet to make it easier for folks to utilize a web wallet with their Bitcoin. Using this we could programmatically generate a new address for each funding request.</p>
<p>Then when we created a funding request, funders could use their Hiro Bitcoin wallet to say that they are willing to fund a certain amount.</p>
<p>Then we would need to initiate a new PSBT on behalf of the request that all funders would have to sign in order for the funds to be sent to the specified wallet for the request.</p>
<p>Just this one piece of functionality alone requires a clunky, disjointed process that is difficult to use for both the user and the developer.</p>
<p>We could simplify it and make it so that all a funder does is send BTC directly to someone requesting the funding, but then all we are doing is facilitating payment, which introduces all kinds of elements of needing to trust third parties in order to have a fully-functioning app.</p>
<p>This brings us to the second major drawback of building on Bitcoin: everything except for the transfer of money itself has to be centralized.</p>
<p>The records of members and their status, a member proposing funding for a new health event, the history of that member, the records of verified providers, the approval of those providers by the community, the conditional agreement to fund that health event by other members, calculating and maintaining the generosity score, the claiming by the provider, the verification of the legitimacy of the claim, and the conditions under which the provider is paid from the hypothetical multisig we talked about are all centralized and need to be delegated to a trusted third party.</p>
<p>The payment itself, and its approval of disbursement by the community, are handled by the Bitcoin script and maybe something like a PSBT. Still, everything else is handled by a single centralized entity. Maybe this is fine, but if we want to build a decentralized economy on top of Bitcoin, we should be thinking about how we can build systems that are trust-minimized from end to end.</p>
<p>How can we decentralize the rest of the process and make both the user experience and developer experience better?</p>
<p>That's where Stacks comes in. Now we get to actually start building the fun stuff.</p>
<p>In this tutorial, we're going to be introduced to Stacks and the Hiro developer tools and get our BitHealth app set up, using a Bitcoin wallet to authenticate.</p>
<p>Coming up after this, we'll take a look at sBTC and Clarity and see how they enable us to build robust apps and smart contracts with Bitcoin.</p>
<p>If you aren't familiar with Stacks, how it works, or the problem it solves, <a target="_blank" href="https://docs.stacks.co/docs/intro">the documentation</a> is an excellent place to start.</p>
<p>Familiarize yourself a bit with Stacks, then come back here and we'll get started building.</p>
<h2 id="heading-setting-up-our-project">Setting up Our Project</h2>
<p>The first thing we need to do is get our project up and running. We're going to be using Next and Tailwind to build out our front end and a tool called <a target="_blank" href="https://github.com/hirosystems/clarinet">Clarinet</a> to manage the Stacks side of things.</p>
<p>For this project, I am running Node v18.7 with NPM 8.15. You'll need to have those installed to follow along.</p>
<p>For now, let's create our project with <code>mkdir bithealth &amp;&amp; cd bithealth</code> .</p>
<p>From inside there, we will initialize our frontend with next and Tailwind by running <code>npx create-next-app@latest frontend --typescript --eslint</code>.</p>
<p>Right now I'm just following the instructions on <a target="_blank" href="https://tailwindcss.com/docs/guides/nextjs">Tailwind's website</a>.</p>
<p>Next, we switch into that new directory and get everything installed with <code>npm install -D tailwindcss postcss autoprefixer</code> and initialize our Tailwind file with <code>npx tailwindcss init -p</code>.</p>
<p>Now it's time to open up our code editor and edit this <code>tailwind.config.js</code> file that was just created.</p>
<pre><code class="lang-javascript"><span class="hljs-comment">/** <span class="hljs-doctag">@type <span class="hljs-type">{import('tailwindcss').Config}</span> </span>*/</span>
<span class="hljs-built_in">module</span>.exports = {
  <span class="hljs-attr">content</span>: [
    <span class="hljs-string">"./app/**/*.{js,ts,jsx,tsx}"</span>,
    <span class="hljs-string">"./pages/**/*.{js,ts,jsx,tsx}"</span>,
    <span class="hljs-string">"./components/**/*.{js,ts,jsx,tsx}"</span>,

    <span class="hljs-comment">// Or if using `src` directory:</span>
    <span class="hljs-string">"./src/**/*.{js,ts,jsx,tsx}"</span>,
  ],
  <span class="hljs-attr">theme</span>: {
    <span class="hljs-attr">extend</span>: {},
  },
  <span class="hljs-attr">plugins</span>: [],
};
</code></pre>
<p>And we need to edit our <code>src/styles/globals.css</code> file.</p>
<pre><code class="lang-css"><span class="hljs-keyword">@tailwind</span> base;
<span class="hljs-keyword">@tailwind</span> components;
<span class="hljs-keyword">@tailwind</span> utilities;
</code></pre>
<p>Next let's modify the <code>src/pages/index.tsx</code> file.</p>
<pre><code class="lang-typescript"><span class="hljs-keyword">import</span> Head <span class="hljs-keyword">from</span> <span class="hljs-string">"next/head"</span>;
<span class="hljs-keyword">import</span> Image <span class="hljs-keyword">from</span> <span class="hljs-string">"next/image"</span>;
<span class="hljs-keyword">import</span> { Inter } <span class="hljs-keyword">from</span> <span class="hljs-string">"next/font/google"</span>;
<span class="hljs-keyword">import</span> styles <span class="hljs-keyword">from</span> <span class="hljs-string">"@/styles/Home.module.css"</span>;

<span class="hljs-keyword">const</span> inter = Inter({ subsets: [<span class="hljs-string">"latin"</span>] });

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">Home</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">return</span> (
    &lt;&gt;
      &lt;Head&gt;
        &lt;title&gt;Create Next App&lt;/title&gt;
        &lt;meta name=<span class="hljs-string">"description"</span> content=<span class="hljs-string">"Generated by create next app"</span> /&gt;
        &lt;meta name=<span class="hljs-string">"viewport"</span> content=<span class="hljs-string">"width=device-width, initial-scale=1"</span> /&gt;
        &lt;link rel=<span class="hljs-string">"icon"</span> href=<span class="hljs-string">"/favicon.ico"</span> /&gt;
      &lt;/Head&gt;
      &lt;div className=<span class="hljs-string">"flex items-center justify-center h-screen"</span>&gt;
        &lt;h1 className=<span class="hljs-string">"text-6xl font-bold text-gray-900"</span>&gt;Hello World&lt;/h1&gt;
      &lt;/div&gt;
    &lt;/&gt;
  );
}
</code></pre>
<p>Now we can see if it worked by running <code>npm run dev</code>.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1679344870322/bb52075c-e528-406d-81b8-1865a82a096f.png" alt class="image--center mx-auto" /></p>
<p>And with that setup out of the way, we can begin building our dapp.</p>
<p>Before we do that, we have one more step.</p>
<p>We need to get setup with the Hiro wallet.</p>
<p>If you don't have it yet, go ahead and install it from <a target="_blank" href="https://wallet.hiro.so/">Hiro's website</a>.</p>
<h2 id="heading-creating-local-stacks-and-bitcoin-networks">Creating Local Stacks and Bitcoin Networks</h2>
<p>Before we get started building our dapp, we need to set ourselves up with a local development network.</p>
<p>Remember from the previous tutorial that we used Bitcoin's <code>regtest</code> option to run a local Bitcoin network?</p>
<p>We need to do something similar here with both Bitcoin and Stacks. We can use another excellent Hiro tool called Clarinet to do that.</p>
<p>Follow the instructions to get Clarinet installed in the <a target="_blank" href="https://github.com/hirosystems/clarinet">GitHub repo</a>, then come back here and we'll get it running.</p>
<p>Once you have it installed, switch back into the main <code>bithealth</code> repo and run <code>clarinet new backend</code>.</p>
<p>This is where we'll be putting our Clarity smart contracts once we get those going. For now, we are just needing to get a local test network going.</p>
<p>But there's a catch here that we need to work around for now. The Hiro wallet doesn't support <code>regtest</code> yet, which means that we can't use the Hiro wallet in order to interact with our local Bitcoin environment.</p>
<p>We'll still use Clarinet for development purposes, but we'll need to interact with Bitcoin and Stacks testnet's for development for now.</p>
<h2 id="heading-getting-testnet-btc-and-stx">Getting Testnet BTC and STX</h2>
<p>We need to get our Bitcoin address set up with some testnet bitcoins.</p>
<p>Grab the testnet Bitcoin address from your Hiro wallet and head to [this testnet faucet](<a target="_blank" href="https://bitcoinfaucet.uo1.net/">https://bitcoinfaucet.uo1.net/</a>) to get some testnet BTC sent to it.</p>
<p>You can find your testnet address by clicking on 'Receive', and then the little QR code icon, which will bring up a menu option to copy your BTC address.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1679503478603/997fb359-c51d-4bc4-bf80-955fc48a3f6a.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1679503497874/04fb349c-43ed-457e-b9d3-4bf97a9e95b8.png" alt class="image--center mx-auto" /></p>
<p>Next, get some testnet STX from <a target="_blank" href="https://explorer.stacks.co/sandbox/faucet?chain=testnet">this faucet</a>.</p>
<p>Let's add some authentication while we wait for those to confirm.</p>
<h2 id="heading-setting-up-authentication">Setting Up Authentication</h2>
<p>Now we need to add the ability for users to authenticate into our app with their Hiro wallet.</p>
<p>Then we can use that wallet authentication in order to view their Bitcoin address using Stacks.js.</p>
<p>Stacks and Bitcoin addresses share a derivation path and are both generated deterministically from the same private key, meaning that every Stacks address automatically has a corresponding Bitcoin address.</p>
<p>First, let's intall the <code>@stacks/connect</code> package. This is what we'll use to set up our app with Hiro wallet authentication.</p>
<pre><code class="lang-bash">npm install @stacks/connect
</code></pre>
<p>After that installs we want to swap out the content of our <code>src/pages/index.tsx</code> file with this.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> Head <span class="hljs-keyword">from</span> <span class="hljs-string">"next/head"</span>;

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">Home</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">const</span> connectWallet = <span class="hljs-function">() =&gt;</span> {
    <span class="hljs-comment">// implement code</span>
  };

  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"flex flex-col items-center justify-center h-screen gap-8"</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">button</span>
        <span class="hljs-attr">className</span>=<span class="hljs-string">"p-4 text-white bg-indigo-500 rounded"</span>
        <span class="hljs-attr">onClick</span>=<span class="hljs-string">{connectWallet}</span>
      &gt;</span>
        Connect Wallet
      <span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">h1</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"text-6xl font-black"</span>&gt;</span>BitHealth<span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
  );
}

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> Home;
</code></pre>
<p>This is just a simple UI with a button placeholder that will allow us to connect our wallet with our app.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1679435100130/b9bd418e-e418-4b49-859d-9499529865da.png" alt class="image--center mx-auto" /></p>
<p>Now let's implement this button functionality. You should have the Hiro wallet installed, and before we get the wallet button connected, go ahead and switch to Testnet from within the Hiro wallet.</p>
<p>Then hit the menu button in Hiro (three dots in the top right), followed by "Change Network", then select "Testnet".</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1679506542311/71ad2a35-aaf2-4db5-8a56-bfc879f04cfa.png" alt class="image--center mx-auto" /></p>
<p>Next we need to import a few things from the <code>@stacks/connect</code> package.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> {
  AppConfig,
  UserSession,
  showConnect,
} <span class="hljs-keyword">from</span> <span class="hljs-string">"@stacks/connect"</span>;
</code></pre>
<p>The first things we need to do are get some setup done using <code>AppConfig</code> and <code>UserSession</code> which will provide some information for the wallet to read from and to store the user session itself using this config. We also need to provide some information for the wallet to display to users.</p>
<p>We can add these lines right above our stub <code>connectWallet</code> function.</p>
<pre><code class="lang-javascript">  <span class="hljs-keyword">const</span> appConfig = <span class="hljs-keyword">new</span> AppConfig([<span class="hljs-string">"store_write"</span>]);
  <span class="hljs-keyword">const</span> userSession = <span class="hljs-keyword">new</span> UserSession({ appConfig });

  <span class="hljs-keyword">const</span> appDetails = {
    <span class="hljs-attr">name</span>: <span class="hljs-string">"BitHealth"</span>,
    <span class="hljs-attr">icon</span>: <span class="hljs-string">"https://freesvg.org/img/Public-health-icon.png"</span>,
  };
</code></pre>
<p>This app config tells the wallet that we need permission to store and write data to the Stacks chain.</p>
<p>Next up we need to implement the <code>connectWallet</code> function itself.</p>
<p>Here we just need to use the <code>showConnect</code> import and the information we just created.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> connectWallet = <span class="hljs-function">() =&gt;</span> {
    showConnect({
      appDetails,
      <span class="hljs-attr">onFinish</span>: <span class="hljs-function">() =&gt;</span> <span class="hljs-built_in">window</span>.location.reload(),
      userSession,
    });
  };
</code></pre>
<p>the <code>onFinish</code> callback tells the wallet that when the wallet finishes connecting we need to reload the page.</p>
<p>We can't actually see that doing anything yet, so let's add some more code in order to store and display this user data we now have access to.</p>
<p>First we need to create a new state variable, so we'll need to import <code>useState</code> and create a new state variable to store our user data.</p>
<p>After that we need to add another chunk of code to conditionally show our use data if we have a logged in user. For now though, we'll just set up a <code>useEffect</code> call to pull the data on page load and log that info to the console.</p>
<p>Here's what our file looks like with those changes.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> Head <span class="hljs-keyword">from</span> <span class="hljs-string">"next/head"</span>;
<span class="hljs-keyword">import</span> { useState, useEffect } <span class="hljs-keyword">from</span> <span class="hljs-string">"react"</span>;

<span class="hljs-keyword">import</span> {
  AppConfig,
  UserSession,
  showConnect,
} <span class="hljs-keyword">from</span> <span class="hljs-string">"@stacks/connect"</span>;

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">Home</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">const</span> [userData, setUserData] = useState({});

  <span class="hljs-keyword">const</span> appConfig = <span class="hljs-keyword">new</span> AppConfig([<span class="hljs-string">"store_write"</span>]);
  <span class="hljs-keyword">const</span> userSession = <span class="hljs-keyword">new</span> UserSession({ appConfig });

  <span class="hljs-keyword">const</span> appDetails = {
    <span class="hljs-attr">name</span>: <span class="hljs-string">"BitHealth"</span>,
    <span class="hljs-attr">icon</span>: <span class="hljs-string">"https://freesvg.org/img/Public-health-icon.png"</span>,
  };

  useEffect(<span class="hljs-function">() =&gt;</span> {
    <span class="hljs-keyword">if</span> (userSession.isSignInPending()) {
      userSession.handlePendingSignIn().then(<span class="hljs-function">(<span class="hljs-params">userData</span>) =&gt;</span> {
        setUserData(userData);
      });
    } <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (userSession.isUserSignedIn()) {
      setUserData(userSession.loadUserData());
    }
  }, []);

  <span class="hljs-built_in">console</span>.log(userData);

  <span class="hljs-keyword">const</span> connectWallet = <span class="hljs-function">() =&gt;</span> {
    showConnect({
      appDetails,
      <span class="hljs-attr">onFinish</span>: <span class="hljs-function">() =&gt;</span> <span class="hljs-built_in">window</span>.location.reload(),
      userSession,
    });
  };

  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"flex flex-col items-center justify-center h-screen gap-8"</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">button</span>
        <span class="hljs-attr">className</span>=<span class="hljs-string">"p-4 text-white bg-indigo-500 rounded"</span>
        <span class="hljs-attr">onClick</span>=<span class="hljs-string">{connectWallet}</span>
      &gt;</span>
        Connect Wallet
      <span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">h1</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"text-6xl font-black"</span>&gt;</span>BitHealth<span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
  );
}

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> Home;
</code></pre>
<p>And if we reload the page or re-connect our wallet we can see that data.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1679436161822/e44532d5-a561-4578-82bf-65d92d2bb067.png" alt class="image--center mx-auto" /></p>
<p>Now let's modify this code a bit to conditionally display our Bitcoin address if we are logged in.</p>
<pre><code class="lang-xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"flex flex-col items-center justify-center h-screen gap-8"</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">h1</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"text-6xl font-black"</span>&gt;</span>BitHealth<span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span>
      {!userData ? (
        <span class="hljs-tag">&lt;<span class="hljs-name">button</span>
          <span class="hljs-attr">className</span>=<span class="hljs-string">"p-4 text-white bg-indigo-500 rounded"</span>
          <span class="hljs-attr">onClick</span>=<span class="hljs-string">{connectWallet}</span>
        &gt;</span>
          Connect Wallet
        <span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
      ) : (
        <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>{userData.profile.btcAddress.p2wpkh.testnet}<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
      )}
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
</code></pre>
<p>Now we should see our Bitcoin address displaying.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1679503196755/465d2632-daf9-4cdd-b4a7-4bb3340ceff9.png" alt class="image--center mx-auto" /></p>
<p>How can we get the balance of this address we are using? We can see it in our Hiro wallet, but what if we want to display it in our app?</p>
<p>There is no simple way to get the balance of a Bitcoin address, as you have to calculate the balance of all the UTXOs on the chain, but we can use third-party services to make the process easier.</p>
<p>We can use a service like <a target="_blank" href="https://www.blockcypher.com/dev/bitcoin/?javascript#introduction">BlockCypher's API</a> to query the Bitcoin testnet to get the balance of our address.</p>
<p>There is a simple endpoint we can use for this by entering in the address given to us by the Hiro wallet.</p>
<p><a target="_blank" href="https://api.blockcypher.com/v1/btc/test3/addrs/tb1qtu8aq680jkn7v55y4fuz0ujrrlye89aka208he">https://api.blockcypher.com/v1/btc/test3/addrs/tb1qtu8aq680jkn7v55y4fuz0ujrrlye89aka208he</a></p>
<p>If we go there we can see our balance denoted in Satoshis.</p>
<pre><code class="lang-json">{
  <span class="hljs-attr">"address"</span>: <span class="hljs-string">"tb1qtu8aq680jkn7v55y4fuz0ujrrlye89aka208he"</span>,
  <span class="hljs-attr">"total_received"</span>: <span class="hljs-number">6000</span>,
  <span class="hljs-attr">"total_sent"</span>: <span class="hljs-number">0</span>,
  <span class="hljs-attr">"balance"</span>: <span class="hljs-number">6000</span>,
  <span class="hljs-attr">"unconfirmed_balance"</span>: <span class="hljs-number">0</span>,
  <span class="hljs-attr">"final_balance"</span>: <span class="hljs-number">6000</span>,
  <span class="hljs-attr">"n_tx"</span>: <span class="hljs-number">1</span>,
  <span class="hljs-attr">"unconfirmed_n_tx"</span>: <span class="hljs-number">0</span>,
  <span class="hljs-attr">"final_n_tx"</span>: <span class="hljs-number">1</span>,
  <span class="hljs-attr">"txrefs"</span>: [
    {
      <span class="hljs-attr">"tx_hash"</span>: <span class="hljs-string">"a85e167483c73c08a4f4e6505fb113caa8947e9bdf1859982e57182e0310a290"</span>,
      <span class="hljs-attr">"block_height"</span>: <span class="hljs-number">2425428</span>,
      <span class="hljs-attr">"tx_input_n"</span>: <span class="hljs-number">-1</span>,
      <span class="hljs-attr">"tx_output_n"</span>: <span class="hljs-number">0</span>,
      <span class="hljs-attr">"value"</span>: <span class="hljs-number">6000</span>,
      <span class="hljs-attr">"ref_balance"</span>: <span class="hljs-number">6000</span>,
      <span class="hljs-attr">"spent"</span>: <span class="hljs-literal">false</span>,
      <span class="hljs-attr">"confirmations"</span>: <span class="hljs-number">2</span>,
      <span class="hljs-attr">"confirmed"</span>: <span class="hljs-string">"2023-03-22T16:34:44Z"</span>,
      <span class="hljs-attr">"double_spend"</span>: <span class="hljs-literal">false</span>
    }
  ],
  <span class="hljs-attr">"tx_url"</span>: <span class="hljs-string">"https://api.blockcypher.com/v1/btc/test3/txs/"</span>
}
</code></pre>
<p>Let's add some more code to retrieve and display this data.</p>
<p>First we'll add a new state variable.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> [walletBalance, setWalletBalance] = useState(<span class="hljs-number">0</span>);
</code></pre>
<p>Next let's set up another <code>useEffect</code> to pull this data.</p>
<pre><code class="lang-javascript">useEffect(<span class="hljs-function">() =&gt;</span> {
    <span class="hljs-keyword">if</span> (userData.profile) {
fetch(<span class="hljs-string">`https://api.blockcypher.com/v1/btc/test3/addrs/<span class="hljs-subst">${userData.profile.btcAddress.p2wpkh.testnet}</span>`</span>
      )
        .then(<span class="hljs-function">(<span class="hljs-params">res</span>) =&gt;</span> res.json())
        .then(<span class="hljs-function">(<span class="hljs-params">data</span>) =&gt;</span> {
          setWalletBalance(data.balance);
        });
    }
  }, [userData]);
</code></pre>
<p>Here we are setting up another React effect hook that runs whenever our <code>userData</code> state object changes. Then we are just making sure the data we want is present before we call the API endpoint with our testnet address and updating the <code>walletBalance</code> state variable.</p>
<p>Finally, let's update the UI to show this.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"flex flex-col items-center justify-center h-screen gap-8"</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">h1</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"text-6xl font-black"</span>&gt;</span>BitHealth<span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span>
      {!userData.profile ? (
        <span class="hljs-tag">&lt;<span class="hljs-name">button</span>
          <span class="hljs-attr">className</span>=<span class="hljs-string">"p-4 text-white bg-indigo-500 rounded"</span>
          <span class="hljs-attr">onClick</span>=<span class="hljs-string">{connectWallet}</span>
        &gt;</span>
          Connect Wallet
        <span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
      ) : (
        <span class="hljs-tag">&lt;&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>{userData.profile.btcAddress.p2wpkh.testnet}<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>{walletBalance} Satoshis<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
        <span class="hljs-tag">&lt;/&gt;</span></span>
      )}
    &lt;/div&gt;
  );
</code></pre>
<p>After all this, here's what your <code>index.tsx</code> file should look like.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> Head <span class="hljs-keyword">from</span> <span class="hljs-string">"next/head"</span>;
<span class="hljs-keyword">import</span> { useState, useEffect } <span class="hljs-keyword">from</span> <span class="hljs-string">"react"</span>;

<span class="hljs-keyword">import</span> { AppConfig, UserSession, showConnect } <span class="hljs-keyword">from</span> <span class="hljs-string">"@stacks/connect"</span>;

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">Home</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">const</span> [userData, setUserData] = useState({});
  <span class="hljs-keyword">const</span> [walletBalance, setWalletBalance] = useState(<span class="hljs-number">0</span>);

  <span class="hljs-keyword">const</span> appConfig = <span class="hljs-keyword">new</span> AppConfig([<span class="hljs-string">"store_write"</span>]);
  <span class="hljs-keyword">const</span> userSession = <span class="hljs-keyword">new</span> UserSession({ appConfig });

  <span class="hljs-keyword">const</span> appDetails = {
    <span class="hljs-attr">name</span>: <span class="hljs-string">"BitHealth"</span>,
    <span class="hljs-attr">icon</span>: <span class="hljs-string">"https://freesvg.org/img/Public-health-icon.png"</span>,
  };

  useEffect(<span class="hljs-function">() =&gt;</span> {
    <span class="hljs-keyword">if</span> (userSession.isSignInPending()) {
      userSession.handlePendingSignIn().then(<span class="hljs-function">(<span class="hljs-params">userData</span>) =&gt;</span> {
        setUserData(userData);
      });
    } <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (userSession.isUserSignedIn()) {
      setUserData(userSession.loadUserData());
    }
  }, []);

  useEffect(<span class="hljs-function">() =&gt;</span> {
    <span class="hljs-keyword">if</span> (userData.profile) {
      fetch(
        <span class="hljs-string">`https://api.blockcypher.com/v1/btc/test3/addrs/<span class="hljs-subst">${userData.profile.btcAddress.p2wpkh.testnet}</span>`</span>
      )
        .then(<span class="hljs-function">(<span class="hljs-params">res</span>) =&gt;</span> res.json())
        .then(<span class="hljs-function">(<span class="hljs-params">data</span>) =&gt;</span> {
          setWalletBalance(data.balance);
        });
    }
  }, [userData]);

  <span class="hljs-keyword">const</span> connectWallet = <span class="hljs-function">() =&gt;</span> {
    showConnect({
      appDetails,
      <span class="hljs-attr">onFinish</span>: <span class="hljs-function">() =&gt;</span> <span class="hljs-built_in">window</span>.location.reload(),
      userSession,
    });
  };

  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"flex flex-col items-center justify-center h-screen gap-8"</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">h1</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"text-6xl font-black"</span>&gt;</span>BitHealth<span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span>
      {!userData.profile ? (
        <span class="hljs-tag">&lt;<span class="hljs-name">button</span>
          <span class="hljs-attr">className</span>=<span class="hljs-string">"p-4 text-white bg-indigo-500 rounded"</span>
          <span class="hljs-attr">onClick</span>=<span class="hljs-string">{connectWallet}</span>
        &gt;</span>
          Connect Wallet
        <span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
      ) : (
        <span class="hljs-tag">&lt;&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>{userData.profile.btcAddress.p2wpkh.testnet}<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>{walletBalance} Satoshis<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
        <span class="hljs-tag">&lt;/&gt;</span></span>
      )}
    &lt;/div&gt;
  );
}

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> Home;
</code></pre>
<p>And you should see your balance is displayed in the UI.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1679504971750/570a7621-0cb7-4372-9d67-fd06decd8ad2.png" alt class="image--center mx-auto" /></p>
<p>Awesome! We have a good start here. The next step is to create our join functionality. That's the main feature we'll be building over the rest of the series and it will give us the opportunity to learn how Stacks interacts with and uses Bitcoin, give us a chance to learn about and experiment with an alpha version of sBTC, the upcoming decentralized 1:1 BTC asset on Stacks.</p>
<p>sBTC is the core of what allows us to build Bitcoin-first dapps in a decentralized way. We'll get into the nitty gritty of it in the next tutorial.</p>
<p>sBTC is still under development and will be released later this year, but until then we can play around with an alpha version to learn how it works and prepare for testnet and mainnet release.</p>
]]></content:encoded></item></channel></rss>