@gemini-wallet/rainbow
Version:
RainbowKit connector for Gemini Wallet integration
494 lines (411 loc) • 11.9 kB
Markdown
# @gemini-wallet/rainbow
RainbowKit connector for seamless Gemini Wallet integration with beautiful UI components.
## Overview
`@gemini-wallet/rainbow` provides a RainbowKit wallet adapter that enables easy integration of Gemini Wallet into applications using RainbowKit. It offers a polished, customizable wallet connection experience with minimal setup.
## Features
- 🎨 **Beautiful UI**: Leverages RainbowKit's polished interface
- 🔌 **Simple Integration**: Drop-in replacement for wallet connectors
- 🎯 **Type Safe**: Full TypeScript support
- 📱 **Responsive**: Works seamlessly on desktop and mobile
- 🔐 **Secure**: Built on @gemini-wallet/wagmi and @gemini-wallet/core
## Installation
```bash
npm install @gemini-wallet/rainbow
# or
yarn add @gemini-wallet/rainbow
# or
pnpm add @gemini-wallet/rainbow
# or
bun add @gemini-wallet/rainbow
```
## 🚀 Try the Example App
We've included a complete working example that you can run immediately:
```bash
cd example
bun install
bun run dev
# Open http://localhost:3000
```
The example demonstrates:
- ✅ Proper connector setup (wrapped in a function)
- ✅ Multi-chain configuration
- ✅ Beautiful RainbowKit UI
- ✅ Zero configuration - works out of the box!
## Quick Start
### ⚠️ Important: Correct Usage
The Gemini wallet connector **MUST** be wrapped in a function when used with `connectorsForWallets`:
```typescript
// ✅ CORRECT - Wrapped in a function
wallets: [
() => geminiRainbowKitConnector({ ... }),
]
// ❌ WRONG - Will cause "createWallet is not a function" error
wallets: [
geminiRainbowKitConnector({ ... }),
]
```
### Basic Setup
```typescript
import '@rainbow-me/rainbowkit/styles.css';
import { connectorsForWallets, RainbowKitProvider } from '@rainbow-me/rainbowkit';
import { WagmiProvider, createConfig, http } from 'wagmi';
import { mainnet, polygon, optimism, arbitrum } from 'wagmi/chains';
import { QueryClientProvider, QueryClient } from '@tanstack/react-query';
import { geminiRainbowKitConnector } from '@gemini-wallet/rainbow';
import {
rainbowWallet,
metaMaskWallet,
coinbaseWallet,
walletConnectWallet,
} from '@rainbow-me/rainbowkit/wallets';
const projectId = 'YOUR_PROJECT_ID'; // Get from https://cloud.walletconnect.com/
const connectors = connectorsForWallets(
[
{
groupName: 'Recommended',
wallets: [
// 🌟 Gemini Wallet - No API key needed!
// IMPORTANT: Must wrap in a function () => ...
() => geminiRainbowKitConnector({
appName: 'My DApp', // Required
appLogoUrl: 'https://mydapp.com/logo.png', // Optional
}),
// Other wallets
rainbowWallet,
metaMaskWallet,
coinbaseWallet,
walletConnectWallet,
],
},
],
{
appName: 'My DApp',
projectId,
}
);
const config = createConfig({
connectors,
chains: [mainnet, polygon, optimism, arbitrum],
transports: {
[mainnet.id]: http(),
[polygon.id]: http(),
[optimism.id]: http(),
[arbitrum.id]: http(),
},
ssr: true,
});
const queryClient = new QueryClient();
function App() {
return (
<WagmiProvider config={config}>
<QueryClientProvider client={queryClient}>
<RainbowKitProvider>
<YourApp />
</RainbowKitProvider>
</QueryClientProvider>
</WagmiProvider>
);
}
```
### With ConnectButton
```tsx
import { ConnectButton } from '@rainbow-me/rainbowkit';
function YourApp() {
return (
<div>
<ConnectButton />
{/* Your app content */}
</div>
);
}
```
## Advanced Usage
### Custom Wallet Groups
```typescript
import { connectorsForWallets } from '@rainbow-me/rainbowkit';
import { geminiRainbowKitConnector } from '@gemini-wallet/rainbow';
import {
metaMaskWallet,
walletConnectWallet,
coinbaseWallet
} from '@rainbow-me/rainbowkit/wallets';
const connectors = connectorsForWallets(
[
{
groupName: 'Recommended',
wallets: [
// Remember: Gemini must be wrapped in a function!
() => geminiRainbowKitConnector({
appName: 'My DApp',
appLogoUrl: 'https://mydapp.com/logo.png',
}),
metaMaskWallet,
],
},
{
groupName: 'Other',
wallets: [
walletConnectWallet,
coinbaseWallet,
],
},
],
{
appName: 'My DApp',
projectId: 'YOUR_PROJECT_ID',
}
);
```
### Custom Theme
```typescript
import { RainbowKitProvider, darkTheme } from '@rainbow-me/rainbowkit';
function App() {
return (
<RainbowKitProvider
theme={darkTheme({
accentColor: '#7b3ff2',
accentColorForeground: 'white',
borderRadius: 'large',
fontStack: 'system',
})}
>
<YourApp />
</RainbowKitProvider>
);
}
```
### Custom Connect Button
```tsx
import { ConnectButton } from '@rainbow-me/rainbowkit';
export const CustomConnectButton = () => {
return (
<ConnectButton.Custom>
{({
account,
chain,
openAccountModal,
openChainModal,
openConnectModal,
authenticationStatus,
mounted,
}) => {
const ready = mounted && authenticationStatus !== 'loading';
const connected =
ready &&
account &&
chain &&
(!authenticationStatus ||
authenticationStatus === 'authenticated');
return (
<div
{...(!ready && {
'aria-hidden': true,
'style': {
opacity: 0,
pointerEvents: 'none',
userSelect: 'none',
},
})}
>
{(() => {
if (!connected) {
return (
<button onClick={openConnectModal} type="button">
Connect Wallet
</button>
);
}
if (chain.unsupported) {
return (
<button onClick={openChainModal} type="button">
Wrong network
</button>
);
}
return (
<div style={{ display: 'flex', gap: 12 }}>
<button
onClick={openChainModal}
style={{ display: 'flex', alignItems: 'center' }}
type="button"
>
{chain.hasIcon && (
<div
style={{
background: chain.iconBackground,
width: 12,
height: 12,
borderRadius: 999,
overflow: 'hidden',
marginRight: 4,
}}
>
{chain.iconUrl && (
<img
alt={chain.name ?? 'Chain icon'}
src={chain.iconUrl}
style={{ width: 12, height: 12 }}
/>
)}
</div>
)}
{chain.name}
</button>
<button onClick={openAccountModal} type="button">
{account.displayName}
{account.displayBalance
? ` (${account.displayBalance})`
: ''}
</button>
</div>
);
})()}
</div>
);
}}
</ConnectButton.Custom>
);
};
```
## API Reference
### `geminiRainbowKitConnector(appMetadata?)`
Creates a RainbowKit wallet configuration for Gemini Wallet.
#### Parameters
- `appMetadata` (optional): Application metadata
- `appName`: Your application name (required)
- `appLogo`: Your application logo URL (optional)
#### Returns
A RainbowKit `Wallet` object with:
- `id`: `"gemini"`
- `name`: `"Gemini"`
- `iconUrl`: Gemini logo URL
- `iconAccent`: `"#000"`
- `iconBackground`: `"#000"`
### Configuration Object
The default configuration can be accessed via `geminiRainbowKitConfig`:
```typescript
import { geminiRainbowKitConfig } from '@gemini-wallet/rainbow';
console.log(geminiRainbowKitConfig);
// {
// desktop: {},
// downloadUrls: {},
// iconAccent: "#000",
// iconBackground: "#000",
// iconUrl: "https://cdn.worldvectorlogo.com/logos/gemini-4.svg",
// id: "gemini",
// mobile: {},
// name: "Gemini",
// }
```
## Styling
### Using RainbowKit Themes
```typescript
import {
RainbowKitProvider,
lightTheme,
darkTheme,
midnightTheme
} from '@rainbow-me/rainbowkit';
// Light theme
<RainbowKitProvider theme={lightTheme()}>
// Dark theme
<RainbowKitProvider theme={darkTheme()}>
// Custom theme
<RainbowKitProvider
theme={lightTheme({
accentColor: '#00D4AA',
accentColorForeground: 'white',
borderRadius: 'medium',
})}
>
```
### CSS Variables
RainbowKit provides CSS variables that can be customized:
```css
:root {
--rk-blurs-modalOverlay: blur(0px);
--rk-fonts-body: -apple-system, BlinkMacSystemFont, 'Segoe UI';
--rk-radii-connectButton: 12px;
}
```
## Best Practices
1. **Always include styles**: Import RainbowKit styles at the app's root
2. **Provide app metadata**: Helps users identify your application
3. **Use project ID**: Required for WalletConnect functionality
4. **Handle chain switching**: Implement proper UX for unsupported chains
5. **Mobile optimization**: Test thoroughly on mobile devices
## Examples
### Multi-Chain Configuration
```typescript
import { createConfig, http } from 'wagmi';
import { connectorsForWallets } from '@rainbow-me/rainbowkit';
import { geminiRainbowKitConnector } from '@gemini-wallet/rainbow';
import {
mainnet,
polygon,
optimism,
arbitrum,
base,
zora
} from 'wagmi/chains';
const connectors = connectorsForWallets(
[
{
groupName: 'Recommended',
wallets: [
() => geminiRainbowKitConnector({
appName: 'Multi-Chain App',
}),
// Add other wallets as needed
],
},
],
{
appName: 'Multi-Chain App',
projectId: 'YOUR_PROJECT_ID',
}
);
const config = createConfig({
connectors,
chains: [mainnet, polygon, optimism, arbitrum, base, zora],
transports: {
[mainnet.id]: http(),
[polygon.id]: http(),
[optimism.id]: http(),
[arbitrum.id]: http(),
[base.id]: http(),
[zora.id]: http(),
},
});
```
### With Authentication
```typescript
import { RainbowKitProvider } from '@rainbow-me/rainbowkit';
import { RainbowKitAuthenticationProvider } from '@rainbow-me/rainbowkit';
function App() {
const [authStatus, setAuthStatus] = useState('unauthenticated');
return (
<RainbowKitAuthenticationProvider
adapter={authenticationAdapter}
status={authStatus}
>
<RainbowKitProvider>
<YourApp />
</RainbowKitProvider>
</RainbowKitAuthenticationProvider>
);
}
```
## Troubleshooting
### Common Issues
1. **"createWallet is not a function" Error**
- **Cause**: Not wrapping the Gemini connector in a function
- **Solution**: Always use `() => geminiRainbowKitConnector({ ... })` not just `geminiRainbowKitConnector({ ... })`
2. **Styles not loading**: Ensure `@rainbow-me/rainbowkit/styles.css` is imported at the top of your app
3. **Wallet not appearing**: Check that you're using `connectorsForWallets` and not the deprecated `getDefaultWallets`
4. **Chain not supported**: Add required chains to the configuration and their corresponding transports
5. **Popup blocked**: Ensure browser allows popups for wallet connection
## Contributing
We welcome contributions! Please see our [Contributing Guide](CONTRIBUTING.md) for details.
## License
MIT License - see [LICENSE](LICENSE) for details.