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

@permaweb/web-wallet

v0.2.0

Published

Secure iframe client transport for the PermawebOS wallet

Readme

@permaweb/web-wallet

This package embeds PermawebOS as a constrained sandboxed iframe when the browser extension provider is not available. It owns the versioned transport, exact source/origin validation, binary serialization, request timeouts, wallet events, interactive-request presentation state, and wallet-origin top-level approval lifecycle.

Production clients and the hosted wallet must use separate HTTPS origins. Local development may use loopback HTTP origins such as http://localhost:3000 and http://localhost:5173.

import {
	createWebWalletClientProvider,
	openWebWallet,
	resolveWebWalletConnectionUrl,
} from '@permaweb/web-wallet';
import { WebWalletWindow } from '@permaweb/web-wallet/react';

const provider = createWebWalletClientProvider({
	walletUrl: 'https://wallet.example',
});

export function WalletFallback() {
	const source = resolveWebWalletConnectionUrl(window.location, 'https://wallet.example').href;

	return <WebWalletWindow provider={provider} source={source} title="PermawebOS wallet" />;
}

export function OpenWalletButton() {
	return <button onClick={() => openWebWallet(provider)}>Open wallet</button>;
}

WebWalletWindow stays mounted for wallet session continuity and automatically appears for interactive requests. Its iframe defaults to the extension's 390 × 600 viewport, with a compact drag bar above it. The window starts 16px from the application's top-right corner, can be dragged with a pointer or the keyboard, can be resized from its native resize handle, and includes a close button. Its header follows validated live theme colors sent by the hosted wallet. Closing it dismisses the current view without approving or rejecting the pending wallet request; a later request opens it again. Clients can also call openWebWallet(provider) (or provider.open()) from an explicit user action to show the wallet without starting a signing or connection request.

Sensitive provider calls must begin in a user gesture. They open a separate wallet-origin approval window directly over the embedded wallet's live screen rectangle, matching its outer position and size, including the header. Wallet-origin approval and management popups request that same validated live geometry before moving over the iframe, and resize themselves after opening so browser chrome does not make them taller than the embedded window. They fail closed if the browser blocks or closes them. While that top-level window is active, WebWalletWindow covers and disables only its embedded wallet surface with an approval notice; the surrounding client application remains interactive. The notice is removed as soon as the request completes or the secure window closes. The iframe cannot grant itself HID, USB, downloads, forms, clipboard-read, or network capabilities through component props; its sandbox and permission policy are wallet-controlled constants. Wallet management actions that handle keys, passwords, Ledger devices, signing, or settings likewise move to a trusted top-level wallet window while retaining the iframe's canonical runtime and vault.

Every sensitive request still needs explicit approval in that top-level window. After a JWK wallet is unlocked, later approvals reuse only its wallet-origin in-memory session, so they do not repeat the password prompt until the wallet is locked, the session expires, or the iframe is reloaded or removed.

The hosted wallet must set VITE_WEB_WALLET_ALLOWED_ORIGINS and send matching CSP frame-ancestors response headers.

Use WebWalletFrame and useWebWalletPresentation from the same React entry point when an application needs a fully custom presentation. WebWalletWindow also accepts isOpen and onClose for controlled usage, plus dimension, position-inset, z-index, class, and style overrides.

Use the same provider object wherever the application expects an Arweave browser wallet. Prefer a validated window.permawebConnect provider when it exists, and mount the iframe fallback only when the extension is absent.