Account Abstraction with BTC Connect

An initial introduction and step-by-step guide to working with BTC Connect on Botanix through the SDK.

Particle Network's BTC Connect is the first account abstraction protocol for the Bitcoin ecosystem. It unifies smart accounts on Bitcoin Layer-2s and standard BTC accounts through native wallet interfaces. To achieve this, Particle Network has deployed ERC-4337 AA infrastructure natively on Botanix, which developers can tap into to leverage smart accounts.

BTC Connect achieves this by, firstly, allowing users to connect to your dApp with their UniSat, OKX, TokenPocket, Bybit, or Bitget wallet. Upon connecting, a smart account is generated on Botanix and assigned to their BTC account. This smart account can then be used and authenticated directly through their BTC wallet, providing native Bitcoin users a simple interface to interact with applications on Botanix.

BTC Connect natively supports Botanix within its flagship SDK, @particle-network/btc-connectkit, and has been deployed on Testnet.This document will provide an initial introduction and step-by-step guide to working with BTC Connect on Botanix through the SDK.

Introduction

This guide aims to showcase BTC Connect's granular integration process within a standard create-react-app application structure. After following the steps outlined in this document, you'll be prepared to build an application on Botanix that can fully utilize BTC Connect in under 50 lines of code.

Currently, this is done exclusively through Particle Network's React-based SDK, @particle-network/btc-connectkit, which facilitates the configuration, initialization, and implementation of BTC Connect.

Prerequisites

Before getting started, you'll need to meet two essential prerequisites:

  1. Generating your project’s authentication keys on the Particle dashboard.

  2. Fulfilling three dependencies from Particle Network.

Dashboard Configuration

Particle Network requires the retrieval and usage of three keys to authenticate BTC Connect. These are your Project ID, Client Key, and App ID.

To retrieve these values, head over to the Particle dashboard and do the following:

  1. Create a new project for your application. Click on it to enter its project dashboard.

  2. Within the project dashboard, create an application.

  3. Finally, with an application made, copy your Project ID, Client Key, and App ID. If applicable, save these as environment variables within your application.

Dependency Installation

Additionally, you'll need to install a number of dependencies to use BTC Connect to its full extent. We'll be focusing on three libraries from Particle Network, including:

  • @particle-network/btc-connectkit, the primary SDK driving implementation of BTC Connect.

  • @particle-network/chains, a library that contains the BotanixTestnet object for connecting to Botanix.

Any standard package manager can facilitate the installation of these dependencies, although the below example will focus on npm and yarn.

yarn add @particle-network/btc-connectkit @particle-network/chains


# OR


npm install @particle-network/btc-connectkit @particle-network/chains

Step 1: Configuration

Within this example, we'll be integrating BTC Connect into an application following a standard create-react-app structure. As such, we'll need to begin by configuring and initializing @particle-network/btc-connectkit within our index.tsx file (or on top of your application’s JSX leveraging BTX Connect).

BTC Connect is configured through a React component. This wraps your application component (in this example, App) and contains various parameters, such as the aforementioned projectId, clientKey, and appId keys.

You can start by importing the following objects from @particle-network/btc-connectkit:

  • ConnectProvider, the React component used for initialization.

  • OKXConnector

  • UnisatConnector

  • BitgetConnector

  • TokenPocketConnector

  • BybitConnector

Between the five wallet connectors listed above, you can pick those that are best suited for your application. We'll use them in a moment to define the wallet supported by BTC Connect.

For now, we'll need to configure options within the ConnectProvider component, populating the following parameters:

  • projectId, clientKey, appId. Your authentication keys, previously retrieved from the Particle dashboard.

  • aaOptions, which contains accountContracts.

    • BTC, the type of smart account we'll be leveraging.

      • chainIds, an array of supported chains intended to use within the application. This should be BotanixTestnet.id.

      • version, the version of the smart account you're using. This should be '2.0.0' for now, as Botanix is only supported within version 2 of Particle Network’s BTC smart account implementation.

  • walletOptions, which contains:

    • visible, a Boolean determining whether or not Particle Network's embedded wallet modal will be shown after a user connects their Bitcoin wallet. If set to true, users will have direct access to their associated smart accounts through this embedded interface. Otherwise, if false, developers will need to retrieve and reflect core wallet information, such as balances, independently.

With options defined, you'll additionally need to specify the native Bitcoin wallets you intend to support within your application through the connectors property.

connectors is an array of objects corresponding with the previously imported wallet connectors; each connector instance should be expressed similarly to: new UnisatConnector().

Now that you've configured both options and connectors within the ConnectProvider component, you're ready to move on to your primary application file (App.tsx in this example).

Below is an example of what a complete index.tsx file may look like in this context.

import React from 'react';
import ReactDOM from 'react-dom/client';
import {
  ConnectProvider,
  OKXConnector, //
  UnisatConnector, //
  BitgetConnector, // -- Only one connector is required, although any combination of these five may be used.
  TokenPocketConnector, //
  BybitConnector // 
} from '@particle-network/btc-connectkit';
import { BotanixTestnet } from '@particle-network/chains';


// The component in which you're using BTC Connect
import App from './App';


ReactDOM.createRoot(document.getElementById('root') as HTMLElement).render(
  <React.StrictMode>
    <ConnectProvider
      options={{
        projectId: process.env.REACT_APP_PROJECT_ID, //
        clientKey: process.env.REACT_APP_CLIENT_KEY, // -- Retrieved from https://dashboard.particle.network
        appId: process.env.REACT_APP_APP_ID, //
        aaOptions: {
          accountContracts: {
            BTC: [
              {
                chainIds: [BotanixTestnet.id],
                version: '2.0.0',
              }
            ]
          }
        },
        walletOptions: {
          visible: true
        }
      }}
      connectors={[new UnisatConnector(), new OKXConnector(), new BitgetConnector(), new TokenPocketConnector(), new BybitConnector()]}
    >
      <App />
    </ConnectProvider>
  </React.StrictMode>
)

Step 2: Application Implementation

At this point, you have:

  • Created a new project and application on the Particle dashboard.

  • Installed various libraries from Particle Network.

  • Configured BTC Connect through ConnectProvider from @particle-network/btc-connectkit.

Before BTC Connect is ready to be used within your application, you'll need to:

  • Decide and configure the mechanism for interacting with Botanix through BTC Connect (such as Ethers, as we'll do in this example).

  • Create a "Connect Wallet" button.

  • Test your BTC Connect implementation by executing transactions on both Botanix and native Bitcoin.

We'll start by focusing on the first item there, configuring our point of interaction with the smart account generated by BTC Connect.

Transactions on Botanix can be executed through BTC Connect with one of two mechanisms: either directly through the useETHProvider hook or by using a standard Web3 library such as Ethers. Let's walk through the latter.


To begin, it's important to understand that BTC Connect is primarily controlled through React hooks, such as useConnectModal, useETHProvider, useBTCProvider, and so on. Therefore, to configure our Ethers object, we'll need to use provider from the useETHProvider hook.

provider is the EIP-1193 Ethereum provider object associated with the smart account, which allows you to use existing Web3 libraries (such as Ethers) as an interface with the account. We’ll be using provider to construct a custom Ethers object.

Below is an example of what this flow may look like with the above objects imported and defined.

import React, { useState, useEffect } from 'react';
import { useETHProvider, useBTCProvider, useConnectModal, useConnector } from '@particle-network/btc-connectkit';
import { ethers } from 'ethers';
import './App.css';


const App = () => {
  const { provider } = useETHProvider();
  
  const customProvider = new ethers.providers.Web3Provider(provider, "any");


  ...
}

With a mechanism of interacting with the user's smart account established, you'll also need to determine the mechanism by which you'll facilitate wallet connection on the front end.

By default, BTC Connect has a built-in connection modal accessible through the openConnectModal function from the useConnectModal hook. Upon calling openConnectModal, an interface aggregating each wallet previously defined within connectors on ConnectProvider will be shown.

In this scenario, openConnectModal can be tied directly to a "Connect Wallet" button. After a user chooses a wallet and connects, the resulting account will populate provider and therefore your Ethers object.

An example of defining and using openConnectModal can be found below.

import React, { useState, useEffect } from 'react';
import { useETHProvider, useBTCProvider, useConnectModal, useConnector } from '@particle-network/btc-connectkit';
import { ethers } from 'ethers';
import './App.css';


const App = () => {
  const { openConnectModal } = useConnectModal();
    
  ...
  
  openConnectModal();


  ...
}

Alternatively, if you'd rather build your own interface to facilitate wallet connection, you'll need to define the connect function from the useConnector hook.

connect will allow you to pass a specific wallet you'd like to shortcut connection to, bypassing the built-in connection interface and allowing you to build your own, as is shown below.

import React, { useState, useEffect } from 'react';
import { useETHProvider, useBTCProvider, useConnector, useConnector } from '@particle-network/btc-connectkit';
import { ethers } from 'ethers';
import './App.css';


const App = () => {
  const { connect } = useConnector();
    
  ...
  
  connect('unisat');
  // Or 'okx', 'bybit', etc.
    
  ...
}

Step 3: Transaction Execution

Botanix

Using the smart account, which we've configured through ConnectProvider and loaded into an Ethers object through provider, we'll be able to execute any type of transaction on Botanix.

In this case, we'll execute a gasless (sponsored) burn of 0.001 BTC.

Because the smart account (attached to the connected Bitcoin wallet) is used as the signer within our Ethers object, we can construct and execute a standard transaction by simply:

  1. Loading the signer (customProvider.getSigner()).

  2. Constructing the transaction (an object containing fields such as to, value, data, etc.)

  3. Sending the transaction (signer.sendTransaction(tx)).

Upon sending the transaction, the user will need to confirm (sign) it through a prompt within their connected Bitcoin wallet. BTC Connect will automatically convert this signature to an EVM-compatible one and authenticate the transaction.

Below is an example of this flow, as described above.

const executeTxEvm = async () => {
    const signer = customProvider.getSigner();


    const tx = {
      to: "0x000000000000000000000000000000000000dEaD", // Burn address
      value: ethers.utils.parseEther('0.001'), // 0.001 BTC
      data: "0x" // Optional
    };


    // Gasless due to usage of SendTransactonMode.Gasless within customProvider
    const txResponse = await signer.sendTransaction(tx);
    const txReceipt = await txResponse.wait();


    notification.success({
      message: "Transaction Successful",
      description: (
        <div>
          Transaction Hash: <a href={`https://3xpl.com/botanix/transaction/${txReceipt.transactionHash}`} target="_blank" rel="noopener noreferrer">{txReceipt.transactionHash}</a>
        </div>
      )
    });
};

Bitcoin (Layer-1)

Through the mechanism of connecting their native Bitcoin wallet, users can send transactions both on Botanix (through their assigned smart account, as covered above) and native Bitcoin.

BTC Connect features a hook, useBTCProvider, for interacting with Bitcoin through a user's connected wallet.

Specifically, from this hook, we'll need to define sendBitcoin for the execution of a standard P2P transaction, as shown below.

import React, { useState, useEffect } from 'react';
import { useETHProvider, useBTCProvider, useConnector, useConnector } from '@particle-network/btc-connectkit';
import { ethers } from 'ethers';
import './App.css';


const App = () => {
  const { sendBitcoin, accounts } = useBTCProvider();
    
  ...
}

sendBitcoin is a simple function that, upon calling, will construct a transaction and request a signature from the user, leading to execution on Bitcoin. This function takes the following parameters:

  • toAddress, the recipient of the transaction. This should be a Bitcoin address of any type, such as Native Segwit, Taproot, etc.

    • In this example, we'll be defining toAddress as accounts[0] to send this BTC back to the address executing the transaction.

  • satoshis, the value of the transaction (amount to be sent), denominated in satoshis.

  • Optionally, options can be defined to specify:

    • feeRate, used for making manual adjustments to the transaction's gas fee.

In this example, we'll wrap sendBitcoin within executeTxBtc, which should look similar to the snippet below.

const executeTxBtc = async () => {
    // Sends 1 satoshi back to the sender
    const hash = await sendBitcoin(accounts[0], 1);


    notification.success({
      message: 'Transaction Successful',
      description: (
        <div>
          Transaction Hash: <a href={`https://live.blockcypher.com/btc-testnet/tx/${hash}`} target="_blank" rel="noopener noreferrer">{hash}</a>
        </div>
      )
    });
  };

Conclusion

As a result of this tutorial, you should have now built an application that:

  1. Onboards a user through their native Bitcoin wallet (such as UniSat).

  2. Assigns and handles an attached smart account on Botanix.

  3. Executes a sample transaction on Botanix using this smart account.

  4. Sends BTC on native Bitcoin through the same connected wallet.

To view and try the complete demo application based on the snippets shown in this guide, visit their dedicated GitHub repository.

Particle Network has extensive documentation covering the implementation of BTC Connect within applications built on Botanix, which can be found here.

Video Tutorial

Last updated