BTC Connect for Web

BTC Connect is the first ERC-4337 account abstraction protocol on Bitcoin. Essentially, BTC Connect allows Layer-1 Bitcoin wallets to own and control smart accounts on Bitcoin Layer-2s. This is facilitated by a Bitcoin-specific wallet connection modal which allows a user to connect with Unisat, BitGet, OKX, Bybit, Bitget, or TokenPocket and immediately begin controlling both their native Bitcoin wallet and a directly associated smart account on various EVM-compatible chains without ever leaving the application or wallet.

Developers building with BTC Connect can seamlessly bridge interaction between Bitcoin Layer-2s (using smart accounts) and Bitcoin Layer-1, bringing the EVM landscape to their applications in under 100 lines of code and ushering in new possibilities for consumer-facing applications on Bitcoin.

Currently, BTC Connect is in its initial alpha release phase, and therefore only supports Web. The BTC Connect SDK (@particle-network/btc-connectkit) acts as the sole library for integrating BTC Connect, facilitating wallet connection (through the aforementioned unified modal), smart account assignment and interaction, native Bitcoin transactions, etc.

In this page, you’ll find a complete rundown of what you need to know when using @particle-network/btc-connectkit.

To learn more about BTC Connect, see Introduction to BTC Connect or take a look at the GitHub repository.

Getting Started

BTC Connect follows Particle Network’s AA SDK and Particle Auth Core very closely in terms of structure, so if you’ve used either of these SDKs before, you may find this process familiar.

Before diving into the process of configuring and initializing the SDK, you’ll need to go through the installation process and retrieve a few required values from the Particle dashboard.

Installation

BTC Connect is driven by one primary SDK, @particle-network/btc-connectkit, and can be installed through either of the two following commands:

Terminal
yarn add @particle-network/btc-connectkit

# OR

npm install @particle-network/btc-connectkit

Setting up the Particle dashboard

Every Particle Network SDK requires the retrieval of three key values, your projectId, clientKey, and appId.

These are used primarily to authenticate API requests and tie your project to the Particle dashboard, allowing you to track users, spin up RPC endpoints, fund your Paymaster for gasless transactions, and so on.

Follow the quickstart tutorial to set up a project and find the required keys: Create a new project.

Initialization

Now that you’ve installed @particle-network/btc-connectkit, you’ll need to configure and initialize it through the ConnectProvider object. ConnectProvider should, like AuthCoreContextProvider from Particle Auth Core, wrap your primary App either directly within its JSX or through your index file. Essentially, ConnectProvider controls the EVM chains you’d like to support, the wallets available through the connection modal, and other core configurations required to initialize BTC Connect. ConnectProvider takes the following within its options parameter:

  • projectId, previously retrieved from the Particle dashboard.
  • clientKey, previously retrieved from the Particle dashboard.
  • appId, previously retrieved from the Particle dashboard.
  • aaOptions, an object containing:
    • accountContracts, which should be another object with:
      • BTC, an array of objects that take:
        • chainIds, an array of chain IDs representing the blockchains you intend to use within your application (these chains are also supported within @particle-network/chains, in which you can export dedicated objects containing the chain ID, such as PolygonMumbai.id).
        • version, which dictates the smart account version you’d like to use. Currently, both 1.0.0 and 2.0.0 are supported, depending on the chain (chainIds) you define. 2.0.0 is a newer implementation with better gas optimizations.
Check the Network Coverage page to see which version of smart accounts is supported by each chain.
  • walletOptions, an optional object containing:
    • visible, a Boolean determining whether or not the Particle Wallet modal is shown after connection. In this case, the wallet modal can be used to control the smart account, although if you intend to implement equivalent functionality within your application, such as user-defined transactions, you may not need this.

Then, outside of the options parameter (which expects the above values), you’ll also need to define connectors, an object containing an array of wallet connector instances imported from @particle-network/btc-connectkit, such as:

  • UnisatConnector
  • OKXConnector
  • BitgetConnector
  • TokenPocketConnector
  • BybitConnector
  • WizzConnector
  • XverseConnector

Below is a code snippet showcasing a complete configuration of ConnectProvider within a standard index file setup, following the structure covered above:

TypeScript
import React from 'react';
import ReactDOM from 'react-dom/client';
import {
  ConnectProvider,
  OKXConnector,
  UnisatConnector,
  BitgetConnector,
  TokenPocketConnector,
  BybitConnector,
  WizzConnector,
  XverseConnector
} from '@particle-network/btc-connectkit';
import App from './App';

import { MerlinTestnet, Merlin, LumiBitTestnet, PolygonMumbai, BEVMTestnet, BEVM, MAPProtocolTestnet, MAPProtocol, SatoshiVMTestnet, BSquaredTestnet, AINNTestnet, Mantle, BitlayerTestnet, BotanixTestnet, PolygonzkEVMCardona  } from '@particle-network/chains';

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: [MerlinTestnet.id, Merlin.id, LumiBitTestnet.id, PolygonMumbai.id, BEVMTestnet.id, BEVM.id, MAPProtocolTestnet.id, MAPProtocol.id, SatoshiVMTestnet.id],
                version: '1.0.0',
              },
            	{
      					chainIds: [BitlayerTestnet.id, BotanixTestnet.id, PolygonzkEVMCardona.id, BSquaredTestnet.id, Mantle.id, AINNTestnet.id],
      					version: '2.0.0',
    					},
            ],
          },
        },
        walletOptions: {
          visible: true,
        }
      }}
      connectors={[new UnisatConnector(), new OKXConnector(), new BitgetConnector(), new TokenPocketConnector(), new BybitConnector(), new WizzConnector(), new XverseConnector()]}
    >
    <App />
    </ConnectProvider>
  </React.StrictMode>
);

Examples of Utilization

Like Particle Auth Core, BTC Connect functions primarily based on hooks (available from @particle-network/btc-connectkit) for functions such as facilitating wallet connection, using the smart account, sending BTC, etc. Below, we’ll review the four primary hooks within BTC Connect.

useConnectModal (for wallet connection)

Wallet connection within BTC Connect happens through a unified connection modal with wallet options according to your connectors parameter within ConnectProvider. useConnectModal exposes two functions for this:

  • openConnectModal. This will open the aforementioned modal immediately upon being called.
  • disconnect. Similarly, disconnect will reset the wallet/account state (log a user out). See the snippet below for an example of defining and using these functions from useConnectModal:
TypeScript
import { useConnectModal } from '@particle-network/btc-connectkit';

const { openConnectModal, disconnect } = useConnectModal();

// Opens the wallet connection model; this is often bound to a "Connect" button
const onOpenConnectModal = () => {
    openConnectModal();
}

// Disconnects the wallet; this is often bound to a "Disconnect" button
const onDisconnect = () => {
    disconnect();
}

Upon calling openConnectModal, the user will be presented with a menu that looks like the following (deviating depending only on connectors from ConnectProvider).

useAccounts (and associated address retrieval methods)

Given that with BTC Connect users will have two addresses (one for their Layer-1 Bitcoin account, and one for their EVM smart account). It’s important to retrieve, reflect, and manage these addresses.

BTC Connect has three primary mechanisms in place for address retrieval:

  1. BTC address retrieval through useAccounts or useBTCProvider, and:
  2. EVM account retrieval through useETHProvider with account.

useAccounts and useBTCProvider both expose accounts, an array of connected Bitcoin addresses (which will change based on whether a user is connected to the Livenet or Testnet). Additionally, useETHProvider has account, a string representing the associated smart account address.

Below is an example of defining each of these variables:

TypeScript
import { useAccounts, useBTCProvider, useETHProvider } from '@particle-network/btc-connectkit';

// BTC accounts through useAccounts
const { accounts } = useAccounts();

// BTC accounts through useBTCProvider (returns the same as accounts from useAccounts)
const { accounts } = useBTCProvider();

// EVM account through useETHProvider
const { account } = useETHProvider();

useBTCProvider (for native Bitcoin functions)

useBTCProvider acts as the primary hook allowing to sign messages, send transactions, and retrieve additional wallet information (such as the network, public key, etc.) with the user’s native Bitcoin account. Confirmations will be routed through the same wallet as useETHProvider, but these transactions will be executed on either the Bitcoin Livenet or Testnet. useBTCProvider has the following functions:

  • getNetwork, for retrieving the current network of the wallet (Livenet or Testnet).
  • switchNetwork, to forcibly switch the network. Takes a string, either ‘livenet’ or ‘testnet’.
  • signMessage, to request that a user signs a message. Takes any string (the message to be signed).
  • getPublicKey, for retrieving the public key of the wallet.
  • sendBitcoin, for sending a standard Bitcoin transaction. This function takes the following:
    • toAddress, the recipient of the transaction.
    • satoshis, the value of the transaction in satoshis.
    • options, an optional object containing:
      • feeRate, for adjusting transaction fees.

An example of leveraging useBTCProvider has been included below:

useETHProvider (for controlling the associated smart account)

Most importantly, useETHProvider acts as the single mechanism for driving interaction through the associated EVM smart account. Interaction is driven through one of two ways:

  1. With native UserOperation construction and execution functions, such as buildUserOp and sendUserOp, which will mimic similar functions found within Particle Network’s AA SDK for managing transactions.
  2. Through the attached EIP-1193 provider object, enabling utilization of the smart account through a standard Web3 library such as Ethers, Web3.js, viem, etc.

Below is the full list of functions derived from useETHProvider:

  • chainId, the ID for the currently connected chain.
    • For a complete list of networks supported within BTC Connect, see Network Coverage.
  • account, the smart account address (automatically populated upon login).
  • getSmartAccountInfo, get smart account info(version, isDeployed, etc.).
  • switchChain, for forcibly changing the EVM chain used through the smart account. This takes a specific chainId (should be one of the aforementioned supported chains).
  • provider, the EIP-1193 provider object associated with the smart account.
  • getFeeQuotes, for retrieving fee quotes (a collection of UserOperation structures based upon different fee payment mechanisms); this is equivalent to getFeeQuotes.
  • buildUserOp, to build a execution-ready UserOperation with a standard transaction object.
  • sendUserOp, for sending UserOperations (either objects derived from getFeeQuotes/buildUserOp, or standard transaction objects).
  • publicClient, the viem PublicClient object for making standard JSON-RPC requests.

The following snippet is an example of defining and using each of these methods:


Master reference

For a direct, raw view into every method provided through useAccount, useETHProvider, useBTCProvider, and useConnectModal, below is a table containing every relevant one alongside specific parameters and a short description. For methods listed that weren’t covered in the above examples, live implementation often mimics the common structure covered throughout this document.

HookFunctionParameters (* indicates optional)
useConnectModalopenConnectModalN/A
useConnectModaldisconnectN/A
useAccountsaccountsN/A
useBTCProviderproviderN/A
useBTCProvideraccountsN/A
useBTCProvidergetPublicKeyN/A
useBTCProvidersignMessagemessage: string
useBTCProvidergetNetworkN/A
useBTCProviderswitchNetworknetwork: ‘livenet’ | ‘testnet’
useBTCProvidersendBitcointoAddress: string, satoshis: number, options*: {feeRate: number}
useETHProvideraccountN/A
useETHProvidergetSmartAccountInfoN/A
useETHProviderproviderN/A
useETHProviderswitchChainchainId: number
useETHProviderchainIdN/A
useETHProvidergetFeeQuotestx: Transaction | Transaction[]
useETHProviderbuildUserOp{ tx: Transaction | Transaction\[], feeQuote: FeeQuote, tokenPaymasterAddress: string }
useETHProvidersendUserOpparams: SendTransactionParams, forceHideConfirmModal?: boolean
useETHProviderpublicClientN/A