Skip to content

Commit

Permalink
feat: bbn wallet connect (#413)
Browse files Browse the repository at this point in the history
* feat: bbn wallet connect

* fix: review

* fix: bump wallet connect version
  • Loading branch information
totraev authored Dec 1, 2024
1 parent 30ed0cc commit 3cf2a9d
Show file tree
Hide file tree
Showing 16 changed files with 236 additions and 296 deletions.
68 changes: 59 additions & 9 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
"dependencies": {
"@babylonlabs-io/babylon-proto-ts": "0.0.3-canary.3",
"@babylonlabs-io/bbn-core-ui": "^0.2.0",
"@babylonlabs-io/bbn-wallet-connect": "^0.0.23",
"@babylonlabs-io/btc-staking-ts": "0.4.0-canary.3",
"@bitcoin-js/tiny-secp256k1-asmjs": "2.2.3",
"@bitcoinerlab/secp256k1": "^1.1.1",
Expand Down
6 changes: 4 additions & 2 deletions src/app/components/Connect/ConnectSmall.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,12 +20,14 @@ interface ConnectSmallProps {
loading?: boolean;
onConnect: () => void;
address: string;
connected: boolean;
btcWalletBalanceSat?: number;
onDisconnect: () => void;
}

export const ConnectSmall: React.FC<ConnectSmallProps> = ({
loading = false,
connected,
onConnect,
address,
btcWalletBalanceSat,
Expand Down Expand Up @@ -64,7 +66,7 @@ export const ConnectSmall: React.FC<ConnectSmallProps> = ({
);
};

return address ? (
return connected ? (
<div className="relative mr-[-10px] text-sm hidden md:flex" ref={ref}>
<button
className="flex cursor-pointer outline-none items-stretch"
Expand Down Expand Up @@ -143,7 +145,7 @@ export const ConnectSmall: React.FC<ConnectSmallProps> = ({
onClick={onConnect}
// Disable the button if the user is already connected
// or: API is not available, geo-blocked, or has an error
disabled={Boolean(address) || !isApiNormal}
disabled={connected || !isApiNormal}
>
<PiWalletBold size={20} className="flex md:hidden" />
<span className="hidden md:flex">Connect Wallets</span>
Expand Down
4 changes: 3 additions & 1 deletion src/app/components/Connect/ConnectedSmall.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,15 @@ import { LoadingSmall } from "../Loading/Loading";

interface ConnectedSmallProps {
loading?: boolean;
connected: boolean;
address: string;
onDisconnect: () => void;
btcWalletBalanceSat?: number;
}

export const ConnectedSmall: React.FC<ConnectedSmallProps> = ({
loading = false,
connected,
address,
btcWalletBalanceSat,
onDisconnect,
Expand All @@ -38,7 +40,7 @@ export const ConnectedSmall: React.FC<ConnectedSmallProps> = ({
const { coinName } = getNetworkConfig();

return (
address && (
connected && (
<div className="relative flex text-sm" ref={ref}>
<button
className="flex cursor-pointer outline-none items-stretch w-full justify-between"
Expand Down
6 changes: 4 additions & 2 deletions src/app/components/Header/Header.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { useWalletConnect } from "@babylonlabs-io/bbn-wallet-connect";
import { twJoin } from "tailwind-merge";

import { useBTCWallet } from "@/app/context/wallet/BTCWalletProvider";
import { useWalletConnection } from "@/app/context/wallet/WalletConnectionProvider";
import { useAppState } from "@/app/state";
import { shouldDisplayTestingMsg } from "@/config";

Expand All @@ -12,7 +12,7 @@ import { TestingInfo } from "../TestingInfo/TestingInfo";
import { ThemeToggle } from "../ThemeToggle/ThemeToggle";

export const Header = () => {
const { disconnect, open } = useWalletConnection();
const { connected, disconnect, open } = useWalletConnect();
const { address } = useBTCWallet();
const { totalBalance, isLoading: loading } = useAppState();

Expand All @@ -30,6 +30,7 @@ export const Header = () => {
</div>
<div className="flex items-center gap-4">
<ConnectSmall
connected={connected}
loading={loading}
onConnect={open}
address={address}
Expand All @@ -45,6 +46,7 @@ export const Header = () => {
)}
>
<ConnectedSmall
connected={connected}
loading={loading}
address={address}
btcWalletBalanceSat={totalBalance}
Expand Down
4 changes: 2 additions & 2 deletions src/app/components/Modals/FilterOrdinalsModal.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import { useWalletConnect } from "@babylonlabs-io/bbn-wallet-connect";
import { useEffect, useState } from "react";
import { IoMdClose } from "react-icons/io";
import { useLocalStorage } from "usehooks-ts";

import { FILTER_ORDINALS_MODAL_KEY } from "@/app/common/constants";
import { useBTCWallet } from "@/app/context/wallet/BTCWalletProvider";
import { useWalletConnection } from "@/app/context/wallet/WalletConnectionProvider";
import { useAppState } from "@/app/state";

import { GeneralModal } from "./GeneralModal";
Expand All @@ -23,7 +23,7 @@ export const FilterOrdinalsModal: React.FC<FilterOrdinalsModalProps> = ({}) => {
}));
};

const { isConnected } = useWalletConnection();
const { connected: isConnected } = useWalletConnect();
const { ordinalsExcluded, includeOrdinals, excludeOrdinals } = useAppState();

const [hasSeenFilterOrdinalsModal, setHasSeenFilterOrdinalsModal] =
Expand Down
85 changes: 33 additions & 52 deletions src/app/context/wallet/BTCWalletProvider.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,10 @@
import type { BTCProvider } from "@tomo-inc/tomo-wallet-provider";
"use client";
import {
BTCProvider,
useChainConnector,
useWalletConnect,
UTXO,
} from "@babylonlabs-io/bbn-wallet-connect";
import type { networks } from "bitcoinjs-lib";
import {
createContext,
Expand All @@ -21,12 +27,9 @@ import {
Fees,
InscriptionIdentifier,
Network,
UTXO,
} from "@/utils/wallet/btc_wallet_provider";
import { WalletError, WalletErrorType } from "@/utils/wallet/errors";

import { useWalletConnection } from "./WalletConnectionProvider";

interface BTCWalletContextProps {
network?: networks.Network;
publicKeyNoCoord: string;
Expand Down Expand Up @@ -79,7 +82,8 @@ export const BTCWalletProvider = ({ children }: PropsWithChildren) => {
const [address, setAddress] = useState("");

const { showError, captureError } = useError();
const { open, isConnected, providers } = useWalletConnection();
const btcConnector = useChainConnector("BTC");
const { open = () => {}, connected } = useWalletConnect();

const btcDisconnect = useCallback(() => {
setBTCWalletProvider(undefined);
Expand All @@ -89,12 +93,13 @@ export const BTCWalletProvider = ({ children }: PropsWithChildren) => {
}, []);

const connectBTC = useCallback(
async (walletProvider: BTCProvider) => {
async (walletProvider: BTCProvider | null) => {
if (!walletProvider) return;

const supportedNetworkMessage =
"Only Native SegWit and Taproot addresses are supported. Please switch the address type in your wallet and try again.";

try {
await walletProvider.connectWallet();
const address = await walletProvider.getAddress();
const supported = isSupportedAddressType(address);
if (!supported) {
Expand Down Expand Up @@ -140,19 +145,22 @@ export const BTCWalletProvider = ({ children }: PropsWithChildren) => {
[showError, captureError],
);

useEffect(() => {
const unsubscribe = btcConnector?.on("connect", (wallet) => {
connectBTC(wallet.provider);
});

return unsubscribe;
}, [btcConnector, connectBTC]);

// Listen for BTC account changes
useEffect(() => {
if (btcWalletProvider) {
let once = false;
btcWalletProvider.on("accountChanged", () => {
if (!once) {
connectBTC(btcWalletProvider);
}
});
return () => {
once = true;
};
}
if (!btcWalletProvider) return;

const cb = () => void connectBTC(btcWalletProvider);
btcWalletProvider.on("accountChanged", cb);

return () => void btcWalletProvider.off("accountChanged", cb);
}, [btcWalletProvider, connectBTC]);

const btcWalletMethods = useMemo(
Expand All @@ -165,8 +173,10 @@ export const BTCWalletProvider = ({ children }: PropsWithChildren) => {
btcWalletProvider?.signPsbts(psbtsHexes) ?? [],
getNetwork: async () =>
btcWalletProvider?.getNetwork() ?? ({} as Network),
signMessage: async (message: string, type?: "ecdsa" | "bip322-simple") =>
btcWalletProvider?.signMessage(message, type) ?? "",
signMessage: async (
message: string,
type: "ecdsa" | "bip322-simple" = "bip322-simple",
) => btcWalletProvider?.signMessage(message, type) ?? "",
getBalance: async () => btcWalletProvider?.getBalance() ?? 0,
getNetworkFees: async () =>
btcWalletProvider?.getNetworkFees() ?? ({} as Fees),
Expand All @@ -175,15 +185,7 @@ export const BTCWalletProvider = ({ children }: PropsWithChildren) => {
btcWalletProvider?.getUtxos(address, amount) ?? [],
getBTCTipHeight: async () => btcWalletProvider?.getBTCTipHeight() ?? 0,
getInscriptions: async (): Promise<InscriptionIdentifier[]> =>
btcWalletProvider
?.getInscriptions()
.then((result) =>
result.list.map((ordinal) => ({
txid: ordinal.inscriptionId,
vout: ordinal.outputValue,
})),
)
.catch((e) => []) ?? [],
btcWalletProvider?.getInscriptions() ?? [],
}),
[btcWalletProvider],
);
Expand All @@ -193,13 +195,13 @@ export const BTCWalletProvider = ({ children }: PropsWithChildren) => {
network,
publicKeyNoCoord,
address,
connected: Boolean(btcWalletProvider),
connected,
open,
disconnect: btcDisconnect,
...btcWalletMethods,
}),
[
btcWalletProvider,
connected,
network,
publicKeyNoCoord,
address,
Expand All @@ -209,27 +211,6 @@ export const BTCWalletProvider = ({ children }: PropsWithChildren) => {
],
);

useEffect(() => {
if (isConnected && providers.state) {
if (!btcWalletProvider && providers.bitcoinProvider) {
connectBTC(providers.bitcoinProvider);
}
}
}, [
connectBTC,
providers.bitcoinProvider,
providers.state,
isConnected,
btcWalletProvider,
]);

// Clean up the state when isConnected becomes false
useEffect(() => {
if (!isConnected) {
btcDisconnect();
}
}, [isConnected, btcDisconnect]);

return (
<BTCWalletContext.Provider value={btcContextValue}>
{children}
Expand Down
Loading

0 comments on commit 3cf2a9d

Please sign in to comment.