npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@buyhatke-dev/wallet-kit

v0.2.0

Published

Headless, UI-agnostic wallet kit for EVM, Solana, Tron, Bitcoin, and Stellar (Reown AppKit + ethers), shared across Buyhatke apps.

Downloads

1,018

Readme

@buyhatke-dev/wallet-kit

Headless, UI-agnostic wallet kit shared across Buyhatke apps. The package owns wallet connection, normalized connection state, message and transaction signing, balance reads, and native/token sends across EVM, Solana, Tron, Bitcoin, and Stellar — desktop (Reown AppKit, injected TronLink, Stellar's own picker) and mobile deep links (Phantom, Solflare, TronLink). Tron has all three: an injected extension flow, a WalletConnect flow through AppKit, and a deep link — separate, and never auto-selected.

The kit is deliberately narrow: no UI, no framework dependency, no env reads, and no backend of its own. Auth handshakes, API calls, transaction-confirmation polling, product UI, and app store shapes stay in the consuming app. Where a backend is genuinely unavoidable — mobile deep-link channels, Tron mobile balance reads — the kit takes an injected function rather than an endpoint: it decides only when to call and what the result shape means, while your app owns the URL, auth, and API shape. The only network I/O the kit performs itself is chain RPC — Solana JSON-RPC, Stellar Horizon, an Esplora-compatible Bitcoin API, and TronGrid (the WalletConnect Tron flow only) — each pointed wherever you want via rpcUrls.

Documentation

| Doc | What's in it | | --- | --- | | docs/api.md | Full API reference: config, every method, error codes, unit helpers, subpaths, per-chain packages | | docs/architecture.md | Design principles, internals, and how each flow works end to end | | docs/chains-and-networks.md | Chain model, defaults, the ~700-chain EVM DB, network switching, name/symbol resolution, per-chain support matrix | | docs/integration-guide.md | Wiring the kit into an app: event bridging, error copy, bundler setup, migration sketches | | docs/mobile-deep-links.md | Mobile flows: the injected-channel contract, backend API shapes, the pre-mint auth pattern | | docs/limitations-and-roadmap.md | Honest current limitations and what's planned | | CHANGELOG.md | Version history |

Install

npm i @buyhatke-dev/wallet-kit

Core chain SDKs arrive transitively: Reown AppKit and chain adapters, ethers, @solana/web3.js, and @stellar/stellar-sdk. Install only the optional Solana or Tron wallet adapters and Stellar picker your app enables. Drop duplicate direct copies so one version tree exists. Svelte is also an optional peer for the glue subpath:

npm i svelte   # ./svelte subpath only

Stellar's SDKs are imported lazily at connect('stellar') and build into their own chunk, so apps that never connect Stellar never load them — details in api.md §8.1.

Quickstart

import { createWalletKit, isWalletKitError } from '@buyhatke-dev/wallet-kit';

const kit = createWalletKit({
	projectId: '<walletconnect-project-id>',
	metadata: { name: 'My App', url: 'https://myapp.com', icons: [] },
	rpcUrls: { solana: 'https://your-solana-rpc.example.com' }, // always set this
});

await kit.connect('ethereum');   // Reown modal (any numeric EVM chain id also works)
await kit.connect('solana');     // Reown modal, Solana adapters
await kit.connect('tron');       // injected TronLink, no modal
await kit.connect('bitcoin');    // Reown modal; AppKit discovers bip122 wallets itself
await kit.connect('stellar');    // Stellar's own picker, no AppKit modal

// Tron's other browser flow: Reown's Tron modal, i.e. WalletConnect pairing,
// so a desktop user can connect the wallet on their phone. Separate from the
// line above — offer whichever you want, or both as two buttons.
await kit.connect('tron', { connector: 'appkit' });

// Rendering your own wallet list? Connect one wallet directly, no picker.
// Installed → injected provider with no modal; otherwise WalletConnect.
await kit.connect('ethereum', { wallet: 'metamask' });

// THE event stream — full snapshots on every change. NOTE: subscribe() does
// not emit on registration; seed with getConnection() first (the ./svelte
// helpers do this for you). Contract: docs/api.md → subscribe.
walletStore.set(kit.getConnection());
kit.subscribe((c) => walletStore.set(c));
const sig = await kit.signMessage('hello');   // every chain but Stellar

// Sign WITHOUT broadcasting — for challenge-response auth (Stellar SEP-10),
// whose wallets have no arbitrary-message signing and whose challenge must
// never be submitted. Also works on EVM and Solana.
const signedXdr = await kit.signTransaction(challengeXdr);

const balance = await kit.getBalance({ token: 'native' });
// { raw: '1000000000000000000', decimals: 18, formatted: '1', exists: true }

const { hash } = await kit.sendToken({
	to: '<recipient>',
	token: '<contract-or-mint>',   // or 'native'
	amount: '10.5',                // human-readable; BigInt math internally
	memo: 'order-42',              // destination tag — see below
});

Errors are typed everywhere:

try {
	await kit.sendToken(params);
} catch (e) {
	if (isWalletKitError(e)) console.log(e.code, e.message);
	// USER_REJECTED · CONNECTION_CANCELLED · TIMEOUT · NO_WALLET · NO_ADDRESS
	// UNSUPPORTED_CHAIN · UNSUPPORTED_CONNECTOR · WRONG_NETWORK
	// INSUFFICIENT_BALANCE · INVALID_AMOUNT · RPC_ERROR · WALLET_ERROR
}

Mobile deep links are explicit opt-in (never auto-detected) and require app-injected delivery channels — see docs/mobile-deep-links.md:

await kit.connect('phantom', 'mobile');
await kit.sendToken({ to, token, amount, decimals, meta: { orderId } });

Behavior highlights

  • Serialized lifecycle: rapid prepare/connect calls are latest-request-wins; superseded requests reject with CONNECTION_CANCELLED instead of racing.
  • EVM sends absorb the ethers "network changed" rejection — re-align to the intended chain and retry (max 3), recovering any embedded broadcast hash first so a retry can never double-send.
  • Any EVM chain works even if not listed in your config — resolved on demand from Reown's ~700-network DB (names and symbols too).
  • Decimal-safe money math end to end (string/BigInt, never floats); formatUnits/parseUnits are exported for app-side use.
  • Same Balance shape on every chain, with account-existence semantics (exists) for a missing Solana ATA, an unfunded Stellar account, or a missing trustline.
  • memo is safe to pass unconditionally — applied as MEMO_TEXT on Stellar, ignored where there's no memo concept. Exchange deposit addresses are shared; a deposit sent without its memo is credited to nobody.
  • Bitcoin balances read the Esplora /address/:addr summary, not /utxo — Esplora caps that endpoint at 500 outputs, which turns any reused address into a hard read failure.

Subpaths

  • @buyhatke-dev/wallet-kit — the kit.
  • @buyhatke-dev/wallet-kit/solanabuildSplSendInstructions: client-side SPL transfer instructions without @solana/spl-token.
  • @buyhatke-dev/wallet-kit/sveltebindWalletKit / connectionStore.

Bitcoin and Stellar each build into their own chunk, so apps that never touch them never load them.

Scope & versioning

v1 targets EVM + Solana + Tron + Bitcoin + Stellar with a single active connection. TON, Ledger flows, and concurrent/aux wallets stay app-side for now — see limitations & roadmap. Every chain works with the kit alone — Stellar's SDKs ship as kit dependencies (§8.1). Rollout order: 0fiat (done) → echo-money → onramp, per the integration guide.

Publishing

Source: GitHub Buyhatke/wallet-kit (private). Package: npmjs under the @buyhatke-dev org (public access). npm version patch && npm publish && git push --follow-tags. Prereleases go out off latest: npm version prerelease && npm publish --tag next.

Dev

npm install
npm run typecheck
npm run lint
npm run build     # tsup -> dist (ESM + d.ts)
npm test          # vitest (unit, no network)
npm run test:live # WK_LIVE=1 — real endpoints, cross-checked against a second source