Integrating BTC Connect
As mentioned, the process of integrating BTC Connect starts with configuration.
Before jumping in, it's important to note that this example will follow a create-react-app
structure; thus, we'll repeatedly refer to the following files within this guide:
index.tsx
, our central location for the configuration of BTC Connect.App.tsx
, the central component containing our core application logic (wallet connection and transaction execution).
To begin, we'll need to install several required and optional dependencies, as will be covered below.
Setup: Dependencies
BTC Connect can be integrated and utilized solely through one SDK, @particle-network/btc-connectkit
. This library is responsible for handling all three steps of our example application. For the sake of programmatic simplicity, we'll be using a combination of the following libraries:
@particle-network/btc-connectkit
, the aforementioned key library for using BTC Connect.@particle-network/chains
, for connecting to SatoshiVM.@particle-network/aa
, to simplify interaction with the associated smart account.ethers
, used hand-in-hand with@particle-network/aa
to streamline the means of transaction execution.
To install these libraries, you'll need to run one of the two commands highlighted below at the root of your project:
Part 1: Configuration and Initialization
Now that you've installed various dependencies and understand the basic structure of this example, you're ready to proceed to the first part of implementing BTC Connect: the process of configuration.
Configuring BTC Connect entails usage of the ConnectProvider
component imported from @particle-network/btc-connectkit
.
ConnectProvider
acts as the central component for configuration, taking a variety of parameters responsible for instance authentication (API keys), wallet modal customization (we'll cover this more momentarily), and supported wallet customization (deciding the range of supported wallets within your application, such as UniSat, OKX, and so on).
Additionally, ConnectProvider
should wrap the component where you intend to use BTC Connect. This is where our previously defined usage of App.tsx
and index.tsx
resurface.
Configuration in this example will happen within index.tsx
. This file will import the App
component from App.tsx
, allowing ConnectProvider
to wrap it and enabling the usage of BTC Connect within our application (defined within App.tsx
).
With this established, you'll need to render ConnectProvider
with the following parameters defined (through the options
and connectors
parameters):
projectId
,clientKey
, andappId
. These are required values authenticating your instance of BTC Connect; they fundamentally tie your project to the Particle dashboard.To retrieve these keys, open the dashboard and create a new project alongside a new application; the corresponding Project ID, Client Key, and App ID will need to be defined within their respective parameters, detailed above.
aaOptions
, which containsaccountContracts
, taking:BTC
, an array of objects outlining chain-related configurations for the smart account. These parameters include:chainIds
, an array of chain IDs referring to the chains you intend to use within your application. Here, we'll be usingSatoshiVMTestnet.id
from@particle-network/chains
.version
, the version of the smart account you'd like to use. For now, only1.0.0
is supported.
walletOptions
, settings impacting the optional embedded wallet modal responsible for facilitating interaction with the smart account derived from a user's native Bitcoin wallet.This takes one parameter,
visible
. If set totrue
, the embedded wallet modal will be available through the bottom right corner of your application after the wallet connection. Otherwise, iffalse
, the modal will be omitted, leaving the handling of the smart account solely to your application.
Outside of options
, within connectors
:
An array of wallet connectors you'd like to support within your application (such as UniSat, Bitget, or OKX). These connections can be imported from
@particle-network/btc-connectkit
, through:OKXConnector
.UnisatConnector
.BitgetConnector
.
With these parameters filled in, your index.tsx
file (or its equivalent within your application) should look similar to the example below:
Part 2: Initiating Wallet Connection
With BTC Connect configured and initialized, you're ready to begin building your application (or integrating BTC Connect within an existing one).
We'll be doing this within the previously mentioned App.tsx
file (using the App
component we wrapped within ConnectProvider
).
Opening and taking a user through the wallet connection menu is quite simple and generally only takes one line of code, although it requires a preliminary setup.
First, it's important to understand how BTC Connect is used programmatically.
BTC Connect has four primary hooks that provide functions to control all core functionality. These are:
useETHProvider
, for managing the associated smart account on SatoshiVM.useBTCProvider
, to receive the user's Bitcoin address and execute native BTC transactions.useConnectModal
, for initiating a wallet connection.useAccounts
, for retrieving the user's addresses.
We'll walk through the process of leveraging useETHProvider
(alongside @particle-network/aa
and ethers
) and useBTCProvider
in part 3. For now, let's focus on useConnectModal
.
After importing useConnectModal
from @particle-network/btc-connectkit
, we'll need to define the openConnectModal
function (and optionally, the disconnect
function). An example of this has been included below:
openConnectModal
is the sole function responsible for both initiating and handling end-to-end wallet connections. In this example, we'll wrap openConnectModal
within a function, handleLogin
to ensure its execution only happens conditionally.
handleLogin
will only execute openConnectModal
if the user has yet to connect their wallet. This is indicated by the length of the accounts
array from useBTCProvider
, which is populated upon wallet connection.
Upon calling handleLogin
, if the user has yet to connect, a generalized connection interface will be displayed, allowing a user to choose between the wallets previously defined within the connectors
parameter through ConnectProvider
. After choosing and connecting a specific wallet, they'll be ready to use your application either through their native Bitcoin account or the newly assigned smart account (on SatoshiVM).
handleLogin
, or an equivalent function within your application, may look like the below example.
Part 3: Transaction Execution
Taking a few steps back, let's revisit the hooks discussed in part 2.
As mentioned, the useETHProvider
and useBTCProvider
hooks are used to control their associated accounts (smart account and native Bitcoin account).
We'll begin by focusing on useETHProvider
, using it to send a gasless burn transaction of 0.0001 BTC.
EVM Transaction
useETHProvider
exposes a few objects, but the most important one among them is smartAccount
. This is the sole object for controlling the smart account generated after the wallet connection.
smartAccount
can either be used independently, through methods like smartAccount.sendTransaction
, or it can be used alongside @particle-network/aa
to define an associated EIP-1193 provider to be used within an instance of Ethers.
The latter is what we’ll use in this example.
Specifically, you'll need to import the following from @particle-network/aa
:
AAWrapProvider
, for constructing the custom EIP-1193 provider.SendTransactionMode
, to designate the fee payment method for transactions sent through the Ethers instance.
This, in tandem with smartAccount
, a custom Ethers object, can be constructed through a flow similar to the following:
Therefore, this object, customProvider
, will allow for the construction and execution of transactions through standard Ethers syntax and structure while directly routing signatures through BTC Connect.
By including SendTransactionMode.Gasless
within the construction of AAWrapProvider
, we'll be requesting gas sponsorship on every transaction sent through customProvider
. Since we’re using the SatoshiVM Testnet, all transactions will be automatically sponsored (gasless). However, if this were on Mainnet, you'd need to deposit USDT to the Paymaster within the Particle dashboard.
:::info
This method of building a custom EIP-1193 provider with smartAccount
to use BTC Connect through a standard Web3 library is not exclusive to Ethers. AAWrapProvider
can be used within Web3.js, viem, or any other library with EIP-1193 compatibility.
:::
Using customProvider
to send a transaction is straightforward, following a typical Ethers flow. As such, developers familiar with Ethers might be used to this.
In this example, we'll be executing a burn transaction of 0.0001 BTC within executeTxEvm
. This function will construct a simple tx
object containing fields such as to
and value
.
Using a signer object retrieved through customProvider.getSigner()
, this raw tx
object can be used to execute a complete transaction (UserOperation).
To do this, we'll call signer.sendTransaction(tx)
, which will prompt the user for confirmation (signature) through the Bitcoin wallet they connected previously. Upon confirmation, the transaction will be executed on SatoshiVM.
Below, you'll find an example for what a function of this nature may look like.
BTC Transaction
Alternatively, the same wallet interface can be used to send a native (L1) Bitcoin transaction, using the account attached to the previously connected wallet.
We'll do this through the sendBitcoin
function from the useBTCProvider
hook (akin to smartAccount
from useETHProvider
, but solely for executing a Bitcoin transaction).
sendBitcoin
can be defined through useBTCProvider
using syntax adjacent to the example below.
Executing this function will be as simple as passing in two parameters (this is all that's needed for a P2P transaction on Bitcoin). These parameters are:
toAddress
, the recipient of the transaction. In this example, we'll define the recipient as accounts[0], which will send the BTC back to ourselves, just for the sake of demonstration.satoshis
, the value of the transaction denominated in satoshis.Optionally, the
options
parameter can be used to define:feeRate
, for making manual adjustments to the transaction's gas fee.
We'll execute sendBitcoin
through executeTxBtc
, which should look similar to the following snippet:
Upon calling executeTxBtc
, alike executeTxEvm
, the user will be prompted to confirm and sign the transaction. After this, it'll be sent to Bitcoin for execution.
Last updated