orangekit/react
Table of contents:
Introduction
Purpose
The OrangeKit react package is built on top of RainbowKit, expanding its
functionality to provide additional wallet connection options specifically
tailored for Bitcoin wallets. With this package, developers can integrate
Bitcoin wallet support alongside existing Ethereum-compatible (EVM) wallets,
creating a more versatile connection experience for users.
One of the key features of this package is its ability to "masquerade" or
simulate Bitcoin wallets as EVM wallets, allowing them to interact with
Ethereum-based applications seamlessly. Under the hood, it manages a supporting
provider that enables standard EVM operations (such as reading data and
interacting with smart contracts) while keeping signing operations (such as
authorizing transactions) routed to the Bitcoin wallet itself.
Additionally, the package directs transaction execution to a "backing smart
account," which handles the technical details on the Ethereum side. This setup
enables users to use their Bitcoin wallet for both EVM-compatible transactions
and Bitcoin-specific signing operations without needing to switch wallets or
providers manually.
In essence, this package allows for a more flexible and integrated multi-chain
wallet experience by enabling Bitcoin wallets to operate within an Ethereum
environment, making it easier for users to access both Bitcoin and EVM
functionalities through a unified connection interface.
Key Features
-
Wallet Management
The React package provides a set of components that enable users to connect
their Bitcoin wallets to your dApp. Beyond simple connection and
disconnection, it also supports features like displaying balances, switching
networks, and more.
-
Interoperability
The React package provides integrations with the popular viem and wagmi
libraries, making it easier to incorporate Bitcoin wallet support into
applications that already utilize these libraries. By leveraging these
integrations, developers can seamlessly manage wallet connections and
streamline interactions across both Bitcoin and Ethereum ecosystems.
Getting started
Quick start
To quickly start a new project with OrangeKit integrated, you can use our sample
dApp:
npm init @thesis/mezo-integration
# or
pnpm create @thesis/mezo-integration
# or
yarn create @thesis/mezo-integration
The sample dApp will be created on top of Vite + RainbowKit + Wagmi + OrangeKit.
You can also set everything up manually in you existing (or fresh) project. For
manual setup please take a look at Step by step setup.
Step by step setup
Note: Because RainbowKit is a React library, OrangeKit is also designed as a
React library to ensure seamless integration.
Installation
Install OrangeKit react library, RainbowKit and all of it's dependencies:
npm install @orangekit/react @rainbow-me/rainbowkit wagmi viem@2.x @tanstack/react-query
Configure
Note: We recommend reading through RainbowKit documentation first to fully
understand the configuration process.
The configuration process is basically the same as in RainbowKit. We need to
create a wagmi config, which can be done using createDefaultConfig
from
RainbowKit.
import '@rainbow-me/rainbowkit/styles.css';
import { http } from "viem"
import { mainnet, sepolia } from "wagmi/chains"
import { getDefaultConfig } from "@rainbow-me/rainbowkit"
const rainbowKitConfig = {
appName,
transports: {
[mainnet.id]: http('https://mainnet.example.com'),
[sepolia.id]: http('https://sepolia.example.com'),
},
// If your dApp uses WalletConnect, then you have to provide the `projectId`
// here. OrangeKit itself does not require it.
projectId: "",
chains: [mainnet, sepolia],
multiInjectedProviderDiscovery: false,
}
const config = getDefaultConfig(rainbowKitConfig)
The key difference is that we need to add the bitcoin wallets we want to support
in our dApp. We can create a wallet by using specific function exported from
@orangekit/react
lib. As of now, the lib supports three wallets:
- Unisat - for this we will use
getOrangeKitUnisatWallet
function, - OKX - for this we will use
getOrangeKitOKXWallet
function, - Xverse - for this we will use
getOrangeKitXverseWallet
function.
Here's how to add them to wagmi config:
(...)
import { getDefaultConfig, WalletList } from "@rainbow-me/rainbowkit"
import {
getOrangeKitOKXWallet,
getOrangeKitUnisatWallet,
getOrangeKitXverseWallet,
} from "@orangekit/react"
(...)
const bitcoinWalletConfig = {
rpcUrl: <rpc_url>,
chainId: <ethereum_chain_id>,
relayApiKey: <gelato_relay_api_key>,
}
const unisatWallet = getOrangeKitUnisatWallet(bitcoinWalletConfig)
const okxWallet = getOrangeKitOKXWallet(bitcoinWalletConfig)
const xverseWallet = getOrangeKitXverseWallet(bitcoinWalletConfig)
export const orangeKitWallets: WalletList = [
{
groupName: "Orange Kit",
wallets: [unisatWallet, okxWallet, xverseWallet],
},
]
const config = getDefaultConfig({
...rainbowKitConfig,
wallets: orangeKitWallets,
})
Bitcoin wallet config
As you might have notice in the previous section, our wallet initialization
functions from OrangeKit requires some bitcoin wallet config passed:
const bitcoinWalletConfig = {
rpcUrl: <rpc_url>,
chainId: <ethereum_chain_id>,
relayApiKey: <gelato_relay_api_key>,
}
Here is a brief summary of what those values are:
- rpcUrl - the URL that connects your app to a blockchain network, allowing it
to send and receive data,
- chainId - a unique identifier for each blockchain network (like Ethereum or
Sepolia) so the app knows which network it's interacting with.
- relayApiKey - relayer api key needed to properly work with transaction relayer
Wrap providers
Wrap your application with RainbowKitProvider
, WagmiProvider
, and
QueryClientProvider
just like you would normally do with RainbowKit lib:
import { RainbowKitProvider } from "@rainbow-me/rainbowkit"
import { QueryClient, QueryClientProvider } from "@tanstack/react-query"
import { WagmiProvider } from "wagmi"
import "@rainbow-me/rainbowkit/styles.css"
const queryClient = new QueryClient()
ReactDOM.createRoot(document.getElementById("root")!).render(
<React.StrictMode>
<WagmiProvider config={config}>
<QueryClientProvider client={queryClient}>
<RainbowKitProvider>
{/* Your App component */}
</RainbowKitProvider>
</QueryClientProvider>
</WagmiProvider>
</React.StrictMode>,
)
Final steps
That's pretty much it when it comes to configuration! As stated earlier, we
recommend to read through the RainbowKit documentation for better understanding.
To start adding functionalities, please see
Connecting a wallet.
Connecting a wallet
There are two ways to connect the OrangeKit wallet:
- through Wagmi,
- through RainbowKit,
through Wagmi
We can connect to the specific wallet directly through wagmi
:
import {
useChainId,
useConnect,
} from "wagmi"
export const YourApp = () => {
const chainId = useChainId()
const { connectors, connect } = useConnect()
return (
<div>
{connectors.map((connector) => (
<button
type="button"
onClick={() => {
connect({ connector, chainId })
}}
key={connector.id}
>
{connector.name}
</button>
))}
</div>
)
};
This will render a button for each wallet that we've added to the rainbowKit
config. This gives us more control over connector and how we want it to be
displayed in our dApp.
through RainbowKit
We can also implement wallet connection through RainbowKit, where we import the
ConnectButton
component, which will handle the connection process under the
hood:
import { ConnectButton } from "@rainbow-me/rainbowkit"
export const YourApp = () => {
return <ConnectButton label="Connect wallet"/>;
};
Getting addresses and wallet balances
Bitcoin account
For bitcoin account OrangeKit exports a helper hook - useBitcoinAccount()
-
which can be used to obtain address and balance of the connected bitcoin
account:
import { useBitcoinAccount } from "@orangekit/react"
const { btcAddress, btcBalance } = useBitcoinAccount()
useEffect(() => {
console.log("btcAddress: ", btcAddress)
console.log("btcBalance (in satoshi): ", btcBalance.total)
}, [btcAddress, btcBalance])
This hook returns the bitcoin balance in satoshis, in the following format:
{
confirmed: number,
unconfirmed: number,
total: number
}
Ethereum account
To get an address and a balance of the underlying ethereum account, we can use
wagmi
hooks:
const { address } = useAccount()
const { data } = useBalance({ address })
useEffect(() => {
console.log("ethAddress: ", address)
console.log("ethBalance (in wei): ", data.value.toString())
}, [address, data])
Signing a message
The OrangeKit wallets supports message signing from wagmi
lib, so signing
functions the same way as it does in wagmi
:
import { useSignMessage } from 'wagmi'
function App() {
const { signMessage } = useSignMessage()
return (
<button onClick={() => signMessage({ message: 'hello world' })}>
Sign message
</button>
)
}
BTC transactions
To send BTC transactions we can use a useSendBitcoinTransaction
hook from
@orangekit/react
:
import { useSendBitcoinTransaction } from "@orangekit/react"
const { sendBitcoinTransaction } = useSendBitcoinTransaction()
const onSendBitcoinTransaction = async () => {
const txHash = await sendBtc("<btc_address>", 1500)
console.log("txHash: ", txHash)
}
sendBitcoinTransaction
function takes two arguments:
- address for which we want to send bitoins to
- amount of bitcoins (in satoshis) that we want to send
ETH transactions
Note: Make sure the gelato_relay_api_key
is passed to bitcoinWalletConfig
before testing this.
To send ETH transactions from the underlying ethereum account, we can use a
useSendEthereumTransaction
hook from @orangekit/react
:
import { useSendEthereumTransaction } from "@orangekit/react"
const { sendEthereumTransaction } = useSendEthereumTransaction()
const onSendEthTransaction = async () => {
const result = await sendEthereumTransaction(
"<eth_address>",
100000n,
"0x00",
)
console.log(result?.hash)
}
sendBitcoinTransaction
function takes three arguments:
- address for which we want to send eth to
- amount of eth (in wei) that we want to send
- additional data that we would like to send with the transaction