Skip to main content

Bitcoin Wallet Support: sats-wagmi

sats-wagmi is a library with a handful of BTC wallet connectors, leaving aside the need of the developer to integrate each one individually. The library also exports useful React hooks that mimic the standard followed in the EVM wagmi library.

Featuresโ€‹

  • BTC Wallet connectors:
    • Metamask Snap
    • Unisat
    • Leather
    • Xverse
    • Bitget
    • OKX Wallet
  • BTC functionality:
    • send BTC
    • sign PSBTs
  • React hooks

Installationโ€‹

To use sats-wagmi, all you need to do is install @gobob/sats-wagmi:

npm install @gobob/sats-wagmi

Connect Walletโ€‹

1. Wrap App in Context Providerโ€‹

To start, we will need to wrap our React App with Context so that our application is aware of sats-wagmi & React Query's reactive state and in-memory caching:

 // 1. Import modules
import { QueryClient, QueryClientProvider } from '@tanstack/react-query'
import { SatsWagmiConfig } from "@gobob/sats-wagmi";

// 2. Set up a React Query client.
const queryClient = new QueryClient()

function App() {
// 3. Wrap app with sats-wagmi and React Query context.
return (
<QueryClientProvider client={queryClient}>
<SatsWagmiConfig network="testnet" queryClient={queryClient}>
{/** ... */}
</SatsWagmiConfig>
</QueryClientProvider>
)
}

2. Display Wallet Optionsโ€‹

After that, we will create a WalletOptions component that will display our connectors. This will allow users to select a wallet and connect.

Below, we are rendering a list of connectors retrieved from useConnect. When the user clicks on a connector, the connect function will connect the users' wallet.

import * as React from 'react'
import { useConnect, SatsConnector } from "@gobob/sats-wagmi";

export function WalletOptions() {
const { connectors, connect } = useConnect()

return connectors.map((connector) => (
<button key={connector.name} onClick={() => connect({ connector })}>
{connector.name}
</button>
))
}

3. Display Connected Accountโ€‹

Lastly, if an account is connected, we want to show the connected address.

We are utilizing useAccount to extract the account and useDisconnect to show a "Disconnect" button so a user can disconnect their wallet.

import { useAccount, useDisconnect } from "@gobob/sats-wagmi";

function Account() {
const { address } = useAccount()
const { disconnect } = useDisconnect()

return (
<div>
<p>Address: {address}</p>
<button onClick={() => disconnect()}>Disconnect</button>
</div>
);
}

Send Transactionโ€‹

Create your SendTransaction component that will contain the send transaction logic.

import type { FormEvent } from 'react';
import { type Hex, parseUnits } from 'viem';
import { useSendTransaction } from "@gobob/sats-wagmi";

function SendTransaction() {
const { data: hash, error, isPending, sendTransaction } = useSendTransaction();

async function submit(e: FormEvent<HTMLFormElement>) {
e.preventDefault();
const formData = new FormData(e.target as HTMLFormElement);
const to = formData.get('address') as Hex;
const value = formData.get('value') as string;

sendTransaction({ to, value: parseUnits(value, 8) });
}

const { isLoading: isConfirming, isSuccess: isConfirmed } =
useWaitForTransactionReceipt({
hash,
})

return (
<div>
<h2>Send Transaction</h2>
<form onSubmit={submit}>
<input required name='address' placeholder='Address' />
<input required name='value' placeholder='Amount (BTC)' step='0.00000001' type='number' />
<button disabled={isPending} type='submit'>
{isPending ? 'Confirming...' : 'Send'}
</button>
</form>
{hash && <div>Transaction Hash: {hash}</div>}
{isConfirming && 'Waiting for confirmation...'}
{isConfirmed && 'Transaction confirmed.'}
{error && <div>Error: {error.message}</div>}
</div>
);
}