Core SDK for Gemini Wallet integration with popup communication
npm install @gemini-wallet/coreComplete SDK for integrating with Gemini Wallet, providing wallet connection, transaction signing, and EVM provider functionality.
@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.
- š 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
``bash`
bun add @gemini-wallet/coreor
npm install @gemini-wallet/coreor
yarn add @gemini-wallet/coreor
pnpm add @gemini-wallet/core
For most applications, you should use Wagmi's built-in Gemini connector instead:
`typescript
import { gemini } from "wagmi/connectors";
import { createConfig } from "wagmi";
const config = createConfig({
connectors: [
gemini({
appMetadata: {
name: "My DApp",
url: "https://mydapp.com",
icon: "https://mydapp.com/icon.png",
},
}),
],
// ... 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
This core SDK provides multiple integration levels for advanced use cases:
Use when you need direct provider access or aren't using Wagmi:
`typescript
import { GeminiWalletProvider } from "@gemini-wallet/core";
const provider = new GeminiWalletProvider({
appMetadata: {
name: "My DApp",
url: "https://mydapp.com",
icon: "https://mydapp.com/icon.png",
},
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);
});
`
Use the wallet class for fine-grained control:
`typescript
import { GeminiWallet } from "@gemini-wallet/core";
const wallet = new GeminiWallet({
appMetadata: {
name: "My DApp",
url: "https://mydapp.com",
icon: "https://mydapp.com/icon.png",
},
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);
}
`
For maximum control over the popup communication:
`typescript
import { Communicator, GeminiSdkEvent } from "@gemini-wallet/core";
const communicator = new Communicator({
appMetadata: {
name: "My DApp",
url: "https://mydapp.com",
icon: "https://mydapp.com/icon.png",
},
});
// 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");
});
`
EIP-1193 compatible Ethereum provider implementation.
`typescript`
interface GeminiProviderConfig {
appMetadata: AppMetadata;
chain: Chain;
onDisconnectCallback?: () => void;
storage?: IStorage;
}
#### Methods
- request - Send RPC requestsdisconnect(): Promise
- - Disconnect walletopenSettings(): Promise
- - Open wallet settings
#### Events
- accountsChanged - Emitted when accounts changechainChanged
- - Emitted when chain changesconnect
- - Emitted on connectiondisconnect
- - Emitted on disconnection
Direct wallet interface for advanced use cases.
`typescript`
interface GeminiWalletConfig {
appMetadata: AppMetadata;
chain?: Chain;
onDisconnectCallback?: () => void;
storage?: IStorage;
}
#### Methods
- connect(): Promise
- Connect to wallet
- sendTransaction(tx: TransactionRequest): Promise - Send transaction
- signData(params: SignMessageParameters): Promise - Sign message
- signTypedData(params: SignTypedDataParameters): Promise - Sign typed data
- switchChain(params: SwitchChainParameters): Promise - Switch chains
- openSettings(): Promise - Open wallet settings$3
Storage interface for persisting wallet state.
`typescript
interface IStorage {
setItem(key: string, value: string): Promise;
getItem(key: string): Promise;
removeItem(key: string): Promise;
storeObject(key: string, item: T): Promise;
loadObject(key: string, fallback: T): Promise;
}
`$3
Low-level communication class.
`typescript
interface CommunicatorConfigParams {
appMetadata: AppMetadata;
onDisconnectCallback?: () => void;
}
`#### Methods
-
postMessage(message: GeminiSdkMessage): Promise - Send message
- postRequestAndWaitForResponse - Send request and wait
- onMessage - Listen for messages
- waitForPopupLoaded(): Promise - Wait for popup to load$3
#### GeminiSdkEvent
Enumeration of all supported events:
-
POPUP_LOADED - Popup window has loaded
- POPUP_UNLOADED - Popup window was closed
- POPUP_APP_CONTEXT - App metadata sent to popup
- SDK_CONNECT - Connect wallet request
- SDK_DISCONNECT - Disconnect wallet request
- SDK_SEND_TRANSACTION - Send transaction request
- SDK_SIGN_MESSAGE - Sign message request
- SDK_SIGN_TYPED_DATA - Sign typed data request
- SDK_SWITCH_CHAIN - Switch chain request
- ACCOUNTS_CHANGED - Accounts changed event
- CHAIN_CHANGED - Chain changed event
- DISCONNECT - Disconnect event$3
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)
$3
-
SDK_BACKEND_URL: "https://keys.gemini.com"
- DEFAULT_CHAIN_ID: 42161 (Arbitrum One)
- SUPPORTED_CHAIN_IDS: Array of supported chain IDs
- POPUP_WIDTH: 420
- POPUP_HEIGHT: 650Security Considerations
1. Origin Validation: All messages are validated against the expected origin
2. Request ID Matching: Responses are matched to requests using unique IDs
3. User Consent: All actions require explicit user approval in the popup
4. 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.
$3
`bash
Install dependencies
bun installRun tests
bun testRun tests in watch mode
bun test --watchType checking
bun run typecheckBuild the package
bun run buildDevelopment mode (watch mode)
bun run dev
`$3
-
bun run build - Build the package for production
- bun run dev - Build in watch mode for development
- bun run test - Run tests
- bun run test:watch - Run tests in watch mode
- bun run typecheck - Run TypeScript type checking
- bun run lint - Run ESLint (requires configuration)
- bun run lint:fix - Fix ESLint issues automatically$3
The build process generates:
-
dist/index.js - ESM bundle for Node.js
- dist/index.d.ts - TypeScript declarations
- dist/*.d.ts.map` - Source maps for declarationsWe welcome contributions! Please see our Contributing Guide for details.
MIT License - see LICENSE for details.