Skip to content

Commit

Permalink
feat: add tomo connector
Browse files Browse the repository at this point in the history
  • Loading branch information
totraev committed Dec 2, 2024
1 parent 3cf2a9d commit 300ce68
Show file tree
Hide file tree
Showing 10 changed files with 328 additions and 30 deletions.
35 changes: 16 additions & 19 deletions package-lock.json

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

4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +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/bbn-wallet-connect": "^0.1.4",
"@babylonlabs-io/btc-staking-ts": "0.4.0-canary.3",
"@bitcoin-js/tiny-secp256k1-asmjs": "2.2.3",
"@bitcoinerlab/secp256k1": "^1.1.1",
Expand All @@ -40,7 +40,7 @@
"@sentry/nextjs": "^8.30.0",
"@tanstack/react-query": "^5.28.14",
"@tanstack/react-query-next-experimental": "^5.28.14",
"@tomo-inc/wallet-connect-sdk": "0.2.16",
"@tomo-inc/wallet-connect-sdk": "^0.3.3",
"@uidotdev/usehooks": "^2.4.1",
"axios": "^1.7.4",
"bitcoinjs-lib": "6.1.5",
Expand Down
80 changes: 80 additions & 0 deletions src/app/context/tomo/BBNConnector.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
import {
createExternalWallet,
IBBNProvider,
useChainConnector,
useWidgetState,
} from "@babylonlabs-io/bbn-wallet-connect";
import {
CosmosProvider,
useTomoProviders,
useTomoWalletConnect,
useTomoWalletState,
useWalletList,
} from "@tomo-inc/wallet-connect-sdk";
import { memo, useCallback, useEffect, useMemo } from "react";

const createProvider = (provider: CosmosProvider): IBBNProvider => {
return {
connectWallet: async () => void provider.connectWallet(),
getAddress: () => provider.getAddress(),
getPublicKeyHex: async () => "",
getSigningStargateClient: () => provider.getSigningStargateClient(),
getBalance: (searchDenom) => provider.getBalance(searchDenom),
};
};

export const TomoBBNConnector = memo(() => {
const tomoWalletState = useTomoWalletState();
const walletList = useWalletList();
const { cosmosProvider: connectedProvider } = useTomoProviders();
const tomoWalletConnect = useTomoWalletConnect();

const { visible } = useWidgetState();
const connector = useChainConnector("BBN");

const connectedWallet = useMemo(() => {
const { connected, walletId } = tomoWalletState.cosmos ?? {};

return connected && walletId
? (walletList.find((wallet: any) => wallet.id === walletId) ?? null)
: null;
}, [tomoWalletState.cosmos, walletList]);

const connect = useCallback(
async (btcWallet: any, btcProvider: CosmosProvider) => {
if (!connector) return;

const wallet = createExternalWallet({
id: "tomo-bbn-connector",
name: btcWallet.name,
icon: btcWallet.img,
provider: createProvider(btcProvider),
});

await connector.connect(wallet);
},
[connector],
);

useEffect(() => {
if (visible && connectedWallet && connectedProvider) {
connect(connectedWallet, connectedProvider);
}
}, [visible, connectedWallet, connectedProvider, connect]);

useEffect(() => {
if (!connector) return;

const unsubscribe = connector.on("disconnect", (wallet) => {
if (wallet.id === "tomo-bbn-connector") {
tomoWalletConnect.disconnect();
}
});

return unsubscribe;
}, [connector, tomoWalletConnect]);

return null;
});

TomoBBNConnector.displayName = "TomoBBNConnector";
104 changes: 104 additions & 0 deletions src/app/context/tomo/BTCConnector.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
import {
createExternalWallet,
IBTCProvider,
useChainConnector,
useWidgetState,
} from "@babylonlabs-io/bbn-wallet-connect";
import {
BTCProvider,
useTomoProviders,
useTomoWalletConnect,
useTomoWalletState,
useWalletList,
} from "@tomo-inc/wallet-connect-sdk";
import { memo, useCallback, useEffect, useMemo } from "react";

const createProvider = (provider: BTCProvider): IBTCProvider => {
return {
connectWallet: async () => void provider.connectWallet(),
getAddress: () => provider.getAddress(),
getPublicKeyHex: () => provider.getPublicKeyHex(),
signPsbt: (psbtHex: string) => provider.signPsbt(psbtHex),
signPsbts: (psbtsHexes: string[]) => provider.signPsbts(psbtsHexes),
getNetwork: () => provider.getNetwork(),
signMessageBIP322: (message: string) => provider.signMessageBIP322(message),
signMessage: (message: string, type: "ecdsa" | "bip322-simple") =>
provider.signMessage(message, type),
on: (eventName: string, callBack: () => void) =>
provider.on(eventName, callBack),
off: (eventName: string, callBack: () => void) =>
provider.off(eventName, callBack),
getBalance: () => provider.getBalance(),
getNetworkFees: () => provider.getNetworkFees(),
pushTx: (txHex: string) => provider.pushTx(txHex),
getUtxos: (address: string, amount?: number) =>
provider.getUtxos(address, amount),
getBTCTipHeight: () => provider.getBTCTipHeight(),
getInscriptions: () =>
provider
.getInscriptions()
.then((result) =>
result.list.map((ordinal) => ({
txid: ordinal.inscriptionId,
vout: ordinal.outputValue,
})),
)
.catch((e) => []),
};
};

export const TomoBTCConnector = memo(() => {
const tomoWalletState = useTomoWalletState();
const walletList = useWalletList();
const { bitcoinProvider: connectedProvider } = useTomoProviders();
const tomoWalletConnect = useTomoWalletConnect();

const { visible } = useWidgetState();
const connector = useChainConnector("BTC");

const connectedWallet = useMemo(() => {
const { connected, walletId } = tomoWalletState.bitcoin ?? {};

return connected && walletId
? (walletList.find((wallet: any) => wallet.id === walletId) ?? null)
: null;
}, [tomoWalletState.bitcoin, walletList]);

const connect = useCallback(
async (btcWallet: any, btcProvider: BTCProvider) => {
if (!connector) return;

const wallet = createExternalWallet({
id: "tomo-btc-connector",
name: btcWallet.name,
icon: btcWallet.img,
provider: createProvider(btcProvider),
});

await connector.connect(wallet);
},
[connector],
);

useEffect(() => {
if (visible && connectedWallet && connectedProvider) {
connect(connectedWallet, connectedProvider);
}
}, [visible, connectedWallet, connectedProvider, connect]);

useEffect(() => {
if (!connector) return;

const unsubscribe = connector.on("disconnect", (wallet) => {
if (wallet.id === "tomo-btc-connector") {
tomoWalletConnect.disconnect();
}
});

return unsubscribe;
}, [connector, tomoWalletConnect]);

return null;
});

TomoBTCConnector.displayName = "TomoBTCConnector";
38 changes: 38 additions & 0 deletions src/app/context/tomo/ConnectButton.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import { Text } from "@babylonlabs-io/bbn-core-ui";
import {
useWidgetState,
WalletButton,
} from "@babylonlabs-io/bbn-wallet-connect";
import { useTomoModalControl } from "@tomo-inc/wallet-connect-sdk";
import { useCallback } from "react";

import logo from "./tomo.png";

const CHAINS = {
bitcoin: "BTC",
cosmos: "BBN",
};

export const ConnectButton = ({
chainName,
}: {
chainName: "bitcoin" | "cosmos";
}) => {
const tomoModal = useTomoModalControl();
const { displayWallets } = useWidgetState();

const open = useCallback(async () => {
const result = await tomoModal.open(chainName);

if (!result) {
displayWallets?.(CHAINS[chainName]);
}
}, [tomoModal, chainName, displayWallets]);

return (
<div className="sticky inset-x-0 bottom-0 bg-[#ffffff] pt-10">
<Text className="mb-4">More wallets with Tomo Connect</Text>
<WalletButton logo={logo.src} name="Tomo Connect" onClick={open} />
</div>
);
};
49 changes: 49 additions & 0 deletions src/app/context/tomo/TomoProvider.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
import { TomoContextProvider } from "@tomo-inc/wallet-connect-sdk";
import "@tomo-inc/wallet-connect-sdk/style.css";
import { useTheme } from "next-themes";
import { type PropsWithChildren } from "react";

import { getNetworkConfig } from "@/config/network.config";
import { bbnDevnet } from "@/config/wallet/babylon";

export const TomoConnectionProvider = ({ children }: PropsWithChildren) => {
const { resolvedTheme } = useTheme();

const { mempoolApiUrl, network, networkName } = getNetworkConfig();
const bitcoinChain = {
id: 1,
name: networkName,
type: "bitcoin" as any,
network: network,
backendUrls: {
mempoolUrl: mempoolApiUrl + "/api/",
},
};

return (
<TomoContextProvider
bitcoinChains={[bitcoinChain]}
chainTypes={["bitcoin", "cosmos"]}
cosmosChains={[
{
id: 2,
name: "Babylon Devnet 7",
type: "cosmos",
network: "devnet-7",
modularData: bbnDevnet,
backendUrls: {
rpcRrl: "https://rpc.devnet.babylonlabs.io",
},
logo: "https://raw.githubusercontent.com/chainapsis/keplr-chain-registry/main/images/bbn-dev/chain.png",
},
]}
style={{
rounded: "medium",
theme: resolvedTheme as "dark" | "light",
primaryColor: "#FF7C2A",
}}
>
{children}
</TomoContextProvider>
);
};
Binary file added src/app/context/tomo/tomo.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading

0 comments on commit 300ce68

Please sign in to comment.