Package Exports
- @gemini-wallet/core
- @gemini-wallet/core/package.json
Readme
@gemini-wallet/core
Complete SDK for integrating with Gemini Wallet, providing wallet connection, transaction signing, and EVM provider functionality.
Overview
@gemini-wallet/core is a comprehensive wallet SDK that provides everything needed to integrate Gemini Wallet into your application. It includes a complete EVM-compatible provider, wallet connection management, secure storage, and seamless popup-based user interactions.
Features
- 🔗 EVM Provider: Complete Ethereum provider implementation (EIP-1193 compatible)
- 🔒 Secure Communication: PostMessage-based cross-origin communication
- 🪟 Popup Management: Automatic popup window lifecycle management
- 💾 Storage Layer: Persistent storage with localStorage fallback
- 🔄 Event-Driven: Promise-based request/response pattern with event emitters
- ⛓️ Multi-Chain: Support for Ethereum, Polygon, Base, Arbitrum, and testnets
- 🖊️ Sign Operations: Message signing and EIP-712 typed data signing
- 💸 Transaction Support: Send transactions with built-in error handling
- 🌐 Cross-Platform: Works in web browsers and React Native
- ⚡ Lightweight: Minimal dependencies for optimal bundle size
Installation
bun add @gemini-wallet/core
# or
npm install @gemini-wallet/core
# or
yarn add @gemini-wallet/core
# or
pnpm add @gemini-wallet/core⚠️ YOU MIGHT NOT NEED THIS
For most applications, you should use Wagmi's built-in Gemini connector instead:
import { gemini } from "wagmi/connectors";
import { createConfig } from "wagmi";
const config = createConfig({
connectors: [
gemini({
appMetadata: {
name: "My DApp",
url: "https://mydapp.com",
},
}),
],
// ... rest of wagmi config
});🎯 Wagmi Integration: Gemini Wallet is available as a default connector in wagmi@2.16.3+ & @wagmi/connectors@5.9.3+ 📚 Wagmi Docs: https://wagmi.sh/core/api/connectors/gemini
⭐ Status: Readily available
Usage
This core SDK provides multiple integration levels for advanced use cases:
🚀 Level 1: EVM Provider (Recommended for Custom Implementations)
Use when you need direct provider access or aren't using Wagmi:
import { GeminiWalletProvider } from "@gemini-wallet/core";
const provider = new GeminiWalletProvider({
appMetadata: {
name: "My DApp",
url: "https://mydapp.com",
},
chain: { id: 42161 }, // Arbitrum One
});
// Connect and get accounts
const accounts = await provider.request({
method: "eth_requestAccounts",
});
// Send transaction
const txHash = await provider.request({
method: "eth_sendTransaction",
params: [
{
from: accounts[0],
to: "0x742E4C3B7dcD26e7Ca95C0Ad2F38C61f6F02C4c0",
value: "0x38D7EA4C68000", // 0.001 ETH
},
],
});
// Listen for events
provider.on("accountsChanged", (accounts) => {
console.log("Accounts changed:", accounts);
});⚡ Level 2: Direct Wallet API
Use the wallet class for fine-grained control:
import { GeminiWallet } from "@gemini-wallet/core";
const wallet = new GeminiWallet({
appMetadata: {
name: "My DApp",
url: "https://mydapp.com",
},
chain: { id: 42161 },
});
// Connect
const accounts = await wallet.connect();
// Send transaction with error handling
const result = await wallet.sendTransaction({
to: "0x742E4C3B7dcD26e7Ca95C0Ad2F38C61f6F02C4c0",
value: "1000000000000000000", // 1 ETH in wei
});
if (result.error) {
console.error("Transaction failed:", result.error);
} else {
console.log("Transaction hash:", result.hash);
}⚙️ Level 3: Low-Level Communication
For maximum control over the popup communication:
import { Communicator, GeminiSdkEvent } from "@gemini-wallet/core";
const communicator = new Communicator({
appMetadata: {
name: "My DApp",
url: "https://mydapp.com",
},
});
// Send connect request
const response = await communicator.postRequestAndWaitForResponse({
event: GeminiSdkEvent.SDK_CONNECT,
requestId: crypto.randomUUID(),
chainId: 42161,
origin: window.location.origin,
});
console.log("Connected address:", response.data.address);
// Listen for specific events
communicator
.onMessage((message) => message.event === GeminiSdkEvent.SDK_DISCONNECT)
.then(() => {
console.log("User disconnected");
});API Reference
GeminiWalletProvider
EIP-1193 compatible Ethereum provider implementation.
interface GeminiProviderConfig {
appMetadata: AppMetadata;
chain: Chain;
onDisconnectCallback?: () => void;
storage?: IStorage;
}Methods
request<T>(args: RpcRequestArgs): Promise<T>- Send RPC requestsdisconnect(): Promise<void>- Disconnect walletopenSettings(): Promise<void>- Open wallet settings
Events
accountsChanged- Emitted when accounts changechainChanged- Emitted when chain changesconnect- Emitted on connectiondisconnect- Emitted on disconnection
GeminiWallet
Direct wallet interface for advanced use cases.
interface GeminiWalletConfig {
appMetadata: AppMetadata;
chain?: Chain;
onDisconnectCallback?: () => void;
storage?: IStorage;
}Methods
connect(): Promise<Address[]>- Connect to walletsendTransaction(tx: TransactionRequest): Promise<SendTransactionResponse>- Send transactionsignData(params: SignMessageParameters): Promise<SignMessageResponse>- Sign messagesignTypedData(params: SignTypedDataParameters): Promise<SignTypedDataResponse>- Sign typed dataswitchChain(params: SwitchChainParameters): Promise<string | null>- Switch chainsopenSettings(): Promise<void>- Open wallet settings
GeminiStorage
Storage interface for persisting wallet state.
interface IStorage {
setItem(key: string, value: string): Promise<void>;
getItem(key: string): Promise<string | null>;
removeItem(key: string): Promise<void>;
storeObject<T>(key: string, item: T): Promise<void>;
loadObject<T>(key: string, fallback: T): Promise<T>;
}Communicator
Low-level communication class.
interface CommunicatorConfigParams {
appMetadata: AppMetadata;
onDisconnectCallback?: () => void;
}Methods
postMessage(message: GeminiSdkMessage): Promise<void>- Send messagepostRequestAndWaitForResponse<M, R>(request: GeminiSdkMessage): Promise<R>- Send request and waitonMessage<M, R>(predicate: (message: Partial<M>) => boolean): Promise<R>- Listen for messageswaitForPopupLoaded(): Promise<Window>- Wait for popup to load
Message Types
GeminiSdkEvent
Enumeration of all supported events:
POPUP_LOADED- Popup window has loadedPOPUP_UNLOADED- Popup window was closedPOPUP_APP_CONTEXT- App metadata sent to popupSDK_CONNECT- Connect wallet requestSDK_DISCONNECT- Disconnect wallet requestSDK_SEND_TRANSACTION- Send transaction requestSDK_SIGN_MESSAGE- Sign message requestSDK_SIGN_TYPED_DATA- Sign typed data requestSDK_SWITCH_CHAIN- Switch chain requestACCOUNTS_CHANGED- Accounts changed eventCHAIN_CHANGED- Chain changed eventDISCONNECT- Disconnect event
Supported Chains
Gemini Wallet supports the following networks:
Mainnets:
- Ethereum (1)
- Arbitrum One (42161) - Default
- OP Mainnet (10)
- Base (8453)
- Polygon (137)
Testnets:
- Sepolia (11155111)
- Arbitrum Sepolia (421614)
- OP Sepolia (11155420)
- Base Sepolia (84532)
- Polygon Amoy (80002)
Constants
SDK_BACKEND_URL:"https://keys.gemini.com"DEFAULT_CHAIN_ID:42161(Arbitrum One)SUPPORTED_CHAIN_IDS: Array of supported chain IDsPOPUP_WIDTH:420POPUP_HEIGHT:650
Security Considerations
- Origin Validation: All messages are validated against the expected origin
- Request ID Matching: Responses are matched to requests using unique IDs
- User Consent: All actions require explicit user approval in the popup
- No Private Keys: The SDK never handles private keys directly
Browser Support
- Chrome/Edge 80+
- Firefox 78+
- Safari 14+
- Opera 67+
Try Gemini Wallet
Experience Gemini Wallet in action:
🔗 keys.gemini.com - Try the wallet interface and see how the SDK integrations work
Integration Examples
The core SDK enables various integration patterns:
- ✅ EIP-1193 compatible provider for any web3 library
- ✅ Custom storage implementations for mobile platforms
- ✅ Event-driven architecture with TypeScript support
- ✅ Multi-chain support with automatic chain switching
- ✅ Error handling with user-friendly error messages
Development
This project uses Bun as the package manager and build tool.
Setup
# Install dependencies
bun install
# Run tests
bun test
# Run tests in watch mode
bun test --watch
# Type checking
bun run typecheck
# Build the package
bun run build
# Development mode (watch mode)
bun run devAvailable Scripts
bun run build- Build the package for productionbun run dev- Build in watch mode for developmentbun run test- Run testsbun run test:watch- Run tests in watch modebun run typecheck- Run TypeScript type checkingbun run lint- Run ESLint (requires configuration)bun run lint:fix- Fix ESLint issues automatically
Build Output
The build process generates:
dist/index.js- ESM bundle for Node.jsdist/index.d.ts- TypeScript declarationsdist/*.d.ts.map- Source maps for declarations
Contributing
We welcome contributions! Please see our Contributing Guide for details.
License
MIT License - see LICENSE for details.