@mezo-org/orangekit
v1.0.0-beta.40
Published
**Table of contents:**
Maintainers
Keywords
Readme
mezo-org/orangekit
Table of contents:
Introduction
Purpose
The OrangeKit 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, with it's underlying EVM account, 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 EVM 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. Each OrangeKit Bitcoin wallet has an underlying smart account on an EVM chain that validates signatures from the Bitcoin wallet and issues EVM transactions.
In essence, this package allows for a more flexible and integrated multi-chain wallet experience by enabling Bitcoin wallets to operate within an EVM environment, making it easier for users to access both Bitcoin and EVM functionalities through a unified connection interface.
Key Features
Wallet Management
The OrangeKit 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 OrangeKit 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 EVM ecosystems.
Getting started
Quick start
To quickly start a new project with OrangeKit integrated, you can use our sample dApp:
npm init @thesis/orange-template
# or
pnpm create @thesis/orange-template
# or
yarn create @thesis/orange-templateThe 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 library, RainbowKit and all of it's dependencies:
npm install @mezo-org/orangekit @rainbow-me/rainbowkit wagmi [email protected] @tanstack/react-queryConfigure
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
@mezo-org/orangekit lib. As of now, the lib supports three wallets:
- Unisat - for this we will use
getUnisatWalletfunction, - OKX - for this we will use
getOKXWalletfunction, - Xverse - for this we will use
getXverseWalletfunction.
Here's how to add them to wagmi config:
(...)
import { getDefaultConfig, WalletList } from "@rainbow-me/rainbowkit"
import {
getOKXWallet,
getUnisatWallet,
getXverseWallet,
} from "@mezo-org/orangekit"
(...)
const bitcoinWalletConfig = {
rpcUrl: <rpc_url>,
chainId: <evm_chain_id>,
relayApiKey: <gelato_relay_api_key>,
}
const unisatWallet = getUnisatWallet(bitcoinWalletConfig)
const okxWallet = getOKXWallet(bitcoinWalletConfig)
const xverseWallet = getXverseWallet(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: <evm_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 EVM blockchain network (like Ethereum, Mezo or Sepolia) so the app knows which network it's interacting with,
- relayApiKey - relayer api key needed to properly work with underlying EVM account.
We recommend to keep those values as environment variables.
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 "@mezo-org/orangekit"
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
}Evm account
To get an address and a balance of the underlying evm 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 useSendBitcoin hook from
@mezo-org/orangekit:
import { useSendBitcoin } from "@mezo-org/orangekit"
const { sendBitcoin } = useSendBitcoin()
const onSendBitcoin = async () => {
const txHash = await sendBitcoin("<btc_address>", 1500)
console.log("txHash: ", txHash)
}sendBitcoin function takes two arguments:
- address for which we want to send bitoins to
- amount of bitcoins (in satoshis) that we want to send
EVM transactions
Note: Make sure the gelato_relay_api_key is passed to bitcoinWalletConfig
before testing this.
To send EVM transactions from the underlying EVM account, we can use a
useSendTransaction hook from @mezo-org/orangekit:
import { useSendTransaction } from "@mezo-org/orangekit"
const { sendTransaction } = useSendTransaction()
const onSendTransaction = async () => {
const result = await sendTransaction(
"<eth_address>",
100000n,
"0x00",
)
console.log(result?.hash)
}sendTransaction 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
