near-connect
Near-Connect
Zero-dependency, secure, and lightweight wallet connector for the NEAR blockchain with easily updatable wallet code through sandboxed execution.
Overview
Near-Connect provides a secure sandbox execution environment for wallet integrations, eliminating the need for a monolithic registry of wallet code. Unlike near-wallet-selector, wallets host their own executor scripts which run in isolated sandboxed iframes, enabling independent updates without dApp code changes.
Key Features
- Zero Dependencies: Lightweight library with no external dependencies
- Sandbox Security: Wallets execute in isolated iframes with granular permissions
- Auto-Updates: Wallets update independently via manifest without dApp changes
- Multi-Wallet Support: 8+ wallets including custom WalletConnect support
- Dual Action Format: Supports both near-wallet-selector and near-api-js action formats
- Feature Filtering: Filter wallets by capabilities (signMessage, testnet support, etc.)
- Injected Wallets: Support for browser extension wallets via EIP-6963-like standard
Installation
yarn add @hot-labs/near-connect
CDN Usage (zero build step):
<script type="importmap">
{ "imports": { "@hot-labs/near-connect": "https://esm.sh/@hot-labs/near-connect" } }
</script>
<script type="module">
import { NearConnector } from "@hot-labs/near-connect";
</script>
Quick Start
Basic Dapp Integration
import { NearConnector } from "@hot-labs/near-connect";
const connector = new NearConnector({
network: "mainnet",
walletConnect: { // Optional, enables WalletConnect-based wallets
projectId: "your-project-id",
metadata: {
name: "My App",
description: "My NEAR App",
url: window.location.origin,
icons: ["https://example.com/icon.png"]
}
}
});
// Listen for sign in
connector.on("wallet:signIn", async ({ wallet, accounts }) => {
const address = accounts[0].accountId;
console.log("Connected:", address);
});
connector.on("wallet:signOut", async () => {
console.log("Disconnected");
});
// Connect wallet (shows selection popup)
await connector.connect();
// Or connect to specific wallet
await connector.connect("hot-wallet");
Check Existing Connection
try {
const wallet = await connector.wallet();
const accounts = await wallet.getAccounts();
console.log("Already connected:", accounts[0].accountId);
} catch (e) {
// Not connected yet
}
Send Transaction
const wallet = await connector.wallet();
// Using near-wallet-selector action format
const result = await wallet.signAndSendTransaction({
receiverId: "contract.near",
actions: [{
type: "FunctionCall",
params: {
methodName: "ft_transfer",
args: { receiver_id: "bob.near", amount: "1000000000000000000000000" },
gas: "30000000000000",
deposit: "1"
}
}]
});
// OR using near-api-js action format (recommended)
import { transactions } from "near-api-js";
const result = await wallet.signAndSendTransaction({
receiverId: "contract.near",
actions: [
transactions.functionCall(
"ft_transfer",
{ receiver_id: "bob.near", amount: "1000000000000000000000000" },
"30000000000000",
"1"
)
]
});
Sign NEP-413 Message
const signedMessage = await wallet.signMessage({
message: "Hello NEAR!",
recipient: "app.near",
nonce: new Uint8Array(32) // Random nonce
});
console.log(signedMessage.signature);
Core Concepts
NearConnector Options
interface NearConnectorOptions {
network?: "mainnet" | "testnet"; // Default: "mainnet"
features?: Partial<WalletFeatures>; // Filter wallets by features
excludedWallets?: string[]; // Wallet IDs to exclude
autoConnect?: boolean; // Default: true
walletConnect?: { projectId: string; metadata: any };
manifest?: string | { wallets: WalletManifest[]; version: string };
}
Feature Filtering
Filter available wallets by required capabilities:
const connector = new NearConnector({
features: {
signMessage: true, // Require NEP-413 support
testnet: true // Require testnet support
}
});
Available features:
signMessage- NEP-413 message signingsignTransaction- Transaction signing without sendingsignAndSendTransaction- Sign and send single transactionsignAndSendTransactions- Sign and send multiple transactionssignInWithoutAddKey- Connect without adding function call access keymainnet- Mainnet network supporttestnet- Testnet network support
NearConnector Methods
// Show wallet selector and connect
await connector.connect(walletId?: string): Promise<NearWalletBase>
// Disconnect current wallet
await connector.disconnect(): Promise<void>
// Get current or specific wallet instance
await connector.wallet(id?: string): Promise<NearWalletBase>
// Show wallet selector popup (returns wallet ID)
await connector.selectWallet(): Promise<string>
// Switch network (disconnects current wallet)
await connector.switchNetwork(network: "mainnet" | "testnet"): Promise<void>
// Get filtered list of available wallets
connector.availableWallets: NearWalletBase[]
Wallet Interface
All wallets implement NearWalletBase:
interface NearWalletBase {
manifest: WalletManifest;
signIn(data?: {
network?: Network;
contractId?: string;
methodNames?: string[];
}): Promise<Account[]>;
signOut(data?: { network?: Network }): Promise<void>;
getAccounts(data?: { network?: Network }): Promise<Account[]>;
signAndSendTransaction(params: {
signerId?: string;
receiverId: string;
actions: Action[];
network?: Network;
}): Promise<FinalExecutionOutcome>;
signAndSendTransactions(params: {
transactions: Transaction[];
network?: Network;
}): Promise<FinalExecutionOutcome[]>;
signMessage(params: {
message: string;
recipient: string;
nonce: Uint8Array;
network?: Network;
}): Promise<SignedMessage>;
}
Advanced Features
Limited Access Keys (Deprecated)
// Add limited-access key during sign in (not recommended for UX)
const connector = new NearConnector({
signIn: {
contractId: "game.near",
methodNames: ["play_move", "end_game"]
}
});
Better approach: Add limited-access key after user starts interacting with your app, not during initial connection.
Debug Wallet Integration
Test custom wallet implementations without modifying the manifest:
// Register debug wallet
await connector.registerDebugWallet({
id: "my-wallet",
name: "My Custom Wallet",
version: "1.0.0",
executor: "http://localhost:3000/wallet-executor.js",
type: "sandbox",
icon: "...",
website: "...",
features: { signMessage: true, signAndSendTransaction: true },
permissions: { storage: true }
});
// Remove debug wallet
await connector.removeDebugWallet("my-wallet");
Custom Manifest Source
// Use custom manifest URL
const connector = new NearConnector({
manifest: "https://my-server.com/wallets.json"
});
// Or provide manifest directly
const connector = new NearConnector({
manifest: {
version: "1.0.0",
wallets: [/* custom wallet manifests */]
}
});
Events
connector.on("wallet:signIn", ({ wallet, accounts, success }) => {
// Handle sign in
});
connector.on("wallet:signOut", ({ success }) => {
// Handle sign out
});
connector.on("selector:walletsChanged", () => {
// Available wallets changed (e.g., extension installed)
});
connector.on("selector:manifestUpdated", () => {
// Manifest reloaded
});
// Also available: once(), off(), removeAllListeners()
Wallet Integration Guide
To integrate your wallet with near-connect, see references/wallet_integration.md for detailed instructions on:
- Writing executor scripts
- Manifest specification and permissions
- Sandbox API and limitations
- Testing and debugging
Action Types Reference
Near-connect supports two action formats. See references/action_types.md for:
- Detailed action type specifications
- Examples of both formats
- Migration guide from near-wallet-selector
Sandbox Security Model
Wallet executor scripts run in sandboxed iframes. See references/sandbox_security.md for:
- Security architecture
- Permission system
- Isolation guarantees
- Audit scope
Integration Examples
See references/integration_examples.md for complete code examples:
- React integration with hooks
- Multiple account management
- Transaction batching
- Error handling patterns
Supported Wallets
- HOT Wallet - Multichain wallet with gas refueling
- Meteor Wallet - Simple and secure DeFi wallet
- Intear Wallet - Fast wallet for dApp interactions
- MyNearWallet - Web wallet for NEAR
- Nightly Wallet - Multichain metaverse wallet
- NEAR Mobile - Official NEAR mobile wallet
- Unity Wallet - Self-custodial Web3 wallet
- OKX Wallet - OKX ecosystem wallet
- WalletConnect - Connect any WalletConnect-compatible wallet
Troubleshooting
Connection Issues: Check browser console for detailed logs with logger option:
const connector = new NearConnector({
logger: { log: console.log }
});
Wallet Not Appearing: Verify feature requirements and network match wallet capabilities.
Transaction Failures: Ensure actions use correct format (see action_types.md) and adequate gas/deposit values.
Migration from near-wallet-selector
Near-connect is designed as a drop-in replacement for most near-wallet-selector use cases:
- Replace
setupWalletSelector()withnew NearConnector() - Use
connector.connect()instead ofselector.show() - Actions can remain unchanged (backward compatible format supported)
- Event names align with near-wallet-selector patterns
See references/integration_examples.md for migration examples.