This skill should be used when building a dApp that connects to a 1Sat wallet — using @1sat/connect for wallet connection via popup or browser extension, @1sat/react for React hooks and components, or integrating with the BigBlocks shadcn registry. Triggers on 'connect wallet', 'dApp integration', 'wallet provider', 'ConnectButton', 'WalletProvider', 'useWallet', 'ConnectDialog', 'SigmaCallback', 'browser extension', 'popup wallet', 'BRC-100', 'Sigma OAuth', 'BigBlocks registry', or 'shadcn wallet components'.
From 1satnpx claudepluginhub b-open-io/claude-plugins --plugin 1satThis skill uses the workspace's default tool permissions.
Executes pre-written implementation plans: critically reviews, follows bite-sized steps exactly, runs verifications, tracks progress with checkpoints, uses git worktrees, stops on blockers.
Guides idea refinement into designs: explores context, asks questions one-by-one, proposes approaches, presents sections for approval, writes/review specs before coding.
Dispatches parallel agents to independently tackle 2+ tasks like separate test failures or subsystems without shared state or dependencies.
Build dApps that connect to 1Sat wallets using @1sat/connect (vanilla JS) and @1sat/react (React).
@1sat/react (React components + hooks)
└── @1sat/connect (Core connection logic)
├── BRC-100 auto-detection (extensions, Cicada, localhost, XDM)
├── Sigma OAuth (browser redirect flow)
└── OneSat popup (iframe/redirect transport)
import { WalletProvider, ConnectButton } from '@1sat/react'
function App() {
return (
<WalletProvider appName="My dApp">
<ConnectButton />
<Dashboard />
</WalletProvider>
)
}
function Dashboard() {
const { wallet, status, identityKey } = useWallet()
if (status !== 'connected' || !wallet) return <p>Not connected</p>
return <p>Connected: {identityKey?.slice(0, 8)}...</p>
}
All components from @1sat/react are deliberately unstyled — they provide functional primitives with minimal inline styles. Themed UI wrappers are distributed via the BigBlocks registry as shadcn-compatible registry items.
App-level context provider. Wrap the application root.
<WalletProvider
appName="My dApp" // Shown in wallet approval
autoReconnect={true} // Auto-reconnect on mount
providers={customProviders} // Custom wallet providers (optional)
>
{children}
</WalletProvider>
Unstyled button that triggers wallet connection. Supports render-prop children for full customization.
<ConnectButton
className="my-button"
connectLabel="Connect"
connectingLabel="Connecting..."
connectedLabel={(key) => `${key.slice(0,6)}...${key.slice(-4)}`}
onConnect={(result) => console.log(result)}
onDisconnect={() => console.log('disconnected')}
disconnectOnClick={true} // Click to disconnect when connected
/>
Controlled dialog for wallet provider selection. Requires open and onOpenChange props.
<ConnectDialog
open={isOpen}
onOpenChange={setIsOpen}
>
{({ providers, connect }) => (
<div>
{providers.map(p => (
<button key={p.type} onClick={() => connect(p.type)}>
{p.name} {p.detected ? '(detected)' : ''}
</button>
))}
</div>
)}
</ConnectDialog>
App-level provider that auto-opens the dialog when status becomes 'selecting'.
<WalletProvider appName="My dApp">
<ConnectDialogProvider>
<App />
</ConnectDialogProvider>
</WalletProvider>
// In any child component:
function ConnectTrigger() {
const { openConnectDialog } = useConnectDialog()
return <button onClick={openConnectDialog}>Connect</button>
}
Render-prop only component (no default UI). Lists providers with detection status.
Page component for Sigma OAuth redirect. Place at the OAuth callback route.
// app/auth/callback/page.tsx
import { SigmaCallback } from '@1sat/react'
export default function AuthCallback() {
return (
<SigmaCallback
redirectTo="/"
onComplete={(result) => console.log('Connected:', result)}
loadingContent={<p>Completing authentication...</p>}
renderError={(error) => <p>Error: {error.message}</p>}
/>
)
}
Primary hook for accessing wallet context:
interface WalletContextValue {
wallet: WalletInterface | null // @bsv/sdk WalletInterface
status: WalletStatus // 'disconnected'|'detecting'|'selecting'|'connecting'|'connected'
identityKey: string | null // Identity pubkey
providerType: string | null // 'brc100'|'onesat'|'sigma'|custom
availableProviders: AvailableProvider[]
connect: (providerType?: string) => Promise<void>
applyResult: (result: ConnectWalletResult) => void
disconnect: () => void
error: Error | null
}
import { createOneSat } from '@1sat/connect'
const onesat = createOneSat({ appName: 'My dApp' })
// Connect (auto-detects extension or opens popup)
const { paymentAddress, ordinalAddress, identityPubKey } = await onesat.connect()
// Operations
const { satoshis } = await onesat.getBalance()
const { signature } = await onesat.signMessage('Hello world')
const { rawtx, txid } = await onesat.signTransaction({ rawtx, description: 'Payment' })
await onesat.disconnect()
WalletProvider uses a two-tier detection flow:
'selecting' and ConnectDialogProvider auto-opens the provider selectorSigmaCallbackimport { isOneSatInjected, waitForOneSat, createOneSat } from '@1sat/connect'
if (isOneSatInjected()) { /* Extension present */ }
// Wait up to 3s for extension
const provider = await waitForOneSat(3000)
// Or let createOneSat handle detection
const onesat = createOneSat()
Full provider interface for dApp operations:
interface OneSatProvider {
connect(): Promise<ConnectResult>
disconnect(): Promise<void>
isConnected(): boolean
signTransaction(request: SignTransactionRequest): Promise<SignTransactionResult>
signMessage(message: string): Promise<SignMessageResult>
inscribe(request: InscribeRequest): Promise<InscribeResult>
sendOrdinals(request: SendOrdinalsRequest): Promise<SendResult>
createListing(request: CreateListingRequest): Promise<ListingResult>
purchaseListing(request: PurchaseListingRequest): Promise<SendResult>
cancelListing(request: CancelListingRequest): Promise<SendResult>
transferToken(request: TransferTokenRequest): Promise<SendResult>
getBalance(): Promise<BalanceResult>
getOrdinals(options?: ListOptions): Promise<OrdinalOutput[]>
getTokens(options?: ListOptions): Promise<TokenOutput[]>
getUtxos(): Promise<Utxo[]>
on(event: OneSatEvent, handler: EventHandler): void
off(event: OneSatEvent, handler: EventHandler): void
getAddresses(): { paymentAddress: string; ordinalAddress: string } | null
getIdentityPubKey(): string | null
}
onesat.on('connect', (result) => console.log('Connected:', result.paymentAddress))
onesat.on('disconnect', () => console.log('Disconnected'))
onesat.on('accountChange', (result) => console.log('Account:', result.paymentAddress))
import { saveConnection, loadConnection, clearConnection, hasStoredConnection } from '@1sat/connect'
const result = await onesat.connect()
saveConnection({ paymentAddress: result.paymentAddress, ordinalAddress: result.ordinalAddress, identityPubKey: result.identityPubKey, timestamp: Date.now() })
// On page load
if (hasStoredConnection()) {
const stored = loadConnection()
// Auto-reconnect using stored.providerType
}
clearConnection() // On disconnect
@1sat/react components are unstyled primitives. The BigBlocks registry serves 30 shadcn-themed blocks installable via:
npx bigblocks add <block>
# or
bunx shadcn@latest add https://registry.bigblocks.dev/r/<block>.json
Connection and wallet blocks that wrap @1sat/react:
| Block | Description |
|---|---|
connect-wallet | Wallet connection button with provider selection dialog and connected-state dropdown |
wallet-overview | Dashboard card with balance, addresses, identity key, and send/receive actions |
send-bsv | Send BSV dialog with sats/BSV toggle, fee estimate, and confirmation |
receive-address | QR code and deposit address with copy and optional rotation |
transaction-history | Transaction list with status indicators and pagination |
mnemonic-flow | Multi-mode seed phrase create/display/import/verify |
unlock-wallet | Passphrase and Touch ID unlock screen |
bigblocks-provider | Context provider for web-mode (API) or custom-mode (desktop RPC) data fetching |
BigBlocks components wrap @1sat/react primitives in shadcn UI (Button, Dialog, Drawer, DropdownMenu) with full theme support. The source for @1sat/react stays in this repo — BigBlocks serves them without duplicating code. See the full 30-block registry at https://bigblocks.dev.
# Vanilla JS
bun add @1sat/connect
# React
bun add @1sat/react # includes @1sat/connect
# Browser extensions
bun add @1sat/extension