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

@windstack/wallet-plugin-wisp

v2.3.4

Published

WindStack session plugin for Vexanium transaction signing with Wisp Wallet.

Downloads

1,276

Readme

@windstack/wallet-plugin-wisp

Overview

@windstack/wallet-plugin-wisp connects WindStack applications to Wisp Wallet on Vexanium Mainnet. It supports the injected Vexanium provider used by browser wallets and the Wisp Telegram handoff transport used by web applications that open Wisp as a Telegram Mini App.

The injected-wallet plugin selects the Wisp provider identified by com.wisp.wallet unless a provider or client is supplied explicitly. The Telegram transport keeps the same wallet-authoritative session model without exposing private keys or wallet unlock secrets.

Connection restore and interactive connection are deliberately separate. Applications should try restore() during startup, finish that state transition, and only call connect() from an explicit user action when no valid session was restored. A persisted session pointer is never treated as a live connection before restore succeeds.

Installation

npm install @windstack/wallet-plugin-wisp @windstack/vexanium

Usage

Browser provider

import { SessionManager } from "@windstack/session";
import { vexNative } from "@windstack/vexanium";
import { WispWalletPlugin } from "@windstack/wallet-plugin-wisp";

const sessionManager = new SessionManager({
  appName: "Example App",
  chains: [
    {
      id: vexNative.chainId,
      url: vexNative.rpcUrl,
      contracts: vexNative.contracts,
    },
  ],
  walletPlugins: [new WispWalletPlugin()],
});

// Startup: finish restore before rendering the disconnected/connect state.
const restoredSession = await sessionManager.restore();

if (restoredSession) {
  console.log("Restored", restoredSession.identity);
}

// User action only, for example inside a Connect Wallet button handler.
async function connectWisp() {
  return sessionManager.login();
}

async function transfer(session = restoredSession) {
  if (!session) throw new Error("Connect Wisp before transacting");

  const action = await session
    .account()
    .transfer("bob", "1.0000 VEX", "Example transfer");

  return session.transact({ actions: [action] });
}

// User disconnect action. Revokes the wallet session and clears local state.
async function disconnectWisp() {
  await sessionManager.logout();
}

Do not write restore() ?? login() during application bootstrap. A failed/empty restore means the application is disconnected; it does not mean the application has permission to open an interactive wallet connection automatically.

The plugin signs the canonical transaction resolved by the session and returns the wallet signatures to @windstack/session. Structured transaction data is retained for wallet review while the canonical serialized bytes remain the authoritative signing payload.

Telegram transport

Use the WindStack-owned Telegram transport for connect, resumable server-sent event delivery, session persistence, VSR construction, restore, disconnect, and Telegram return navigation. WindStack 2.2 does not downgrade an active Telegram request to legacy status polling.

import { createVexaniumClient } from "@windstack/vexanium";
import { createWispTelegramTransport } from "@windstack/wallet-plugin-wisp";

const vex = await createVexaniumClient({
  dapp: {
    name: "Example App",
    url: window.location.origin,
  },
});

const wisp = createWispTelegramTransport({
  apiUrl: "https://api.windcrypto.com/wisp/v1",
  // For a Telegram Mini App, provide its own Telegram return link.
  // Omit this for ordinary browser use.
  telegramReturnUrl: "https://t.me/example_bot/example_app",
  dapp: {
    name: "Example App",
    origin: window.location.origin,
    url: window.location.href,
    icon: `${window.location.origin}/icon.png`,
  },
});

// Startup: restore first and wait for the authoritative result.
const restored = await wisp.restore();
console.log("connected", wisp.connected());

if (restored) {
  console.log(restored.account.permissionLevel);
  console.log(await wisp.getSessionId());
  console.log(await wisp.getAccounts());
}

// User action only. Do not call this automatically because restore returned null.
async function connectWisp() {
  const session = await wisp.connect();
  console.log(session.account.permissionLevel);
  return session;
}

async function transfer() {
  return wisp.transact(vex, {
    actions: [
      {
        account: "vex.token",
        name: "transfer",
        data: {
          from: (await wisp.getAccounts())[0]?.actor,
          to: "bob",
          quantity: "1.0000 VEX",
          memo: "Example transfer",
        },
      },
    ],
  });
}

async function disconnectWisp() {
  await wisp.disconnect();
}

apiUrl is the Wisp API base, including its deployed path prefix. WindStack appends telegram/dapp/* beneath that base and preserves /wisp/v1; it does not use the shared domain's root /telegram/*, /rpc, /v1/*, or /v3/* routes.

connect() is interactive and creates a new wallet authorization. It rejects when a live session is already connected, and it also rejects when a persisted pointer still needs restore() so an application cannot accidentally replace an unresolved session.

restore() is the startup/session-recovery operation. It asks Wisp to validate the exact persisted session against DApp origin, Vexanium chain, account, permission, expiry, and revocation state. When Wisp already knows the session, restore completes from the authoritative session registry without opening the wallet Mini App. If the session is expired, revoked, or mismatched, restore returns no active session and clears the stale pointer. It never falls back to connect().

connected() and getSession() describe only the session validated in the current runtime. getSessionId() and getAccounts() likewise expose only the active restored/connected session. getStoredSession() is intentionally lower-level: it may return an opaque persisted pointer with validatedAt: 0, which is not proof that the wallet is currently connected.

signSigningRequest() and transact() require an active session in the current runtime. After a hard reload, call restore() before signing. They never promote a local storage pointer into a connected session implicitly.

disconnect() transitions the DApp to disconnected local state immediately using the captured opaque session pointer, then requests authoritative wallet-side revocation. A known already-invalid/revoked session is treated as disconnected. Other transport failures are surfaced to the application; the local runtime nevertheless remains disconnected and must not silently reuse the old pointer. clearSession() is deliberately lower level and only resets the local cache; applications should normally use disconnect().

telegramReturnUrl is an optional transport-only return policy for Telegram Mini Apps. It must be a credential-free https://t.me/ link to the originating Mini App or bot. Wisp carries it with each handoff and uses it only after terminal approval/rejection; it is never part of DApp identity, trust, account binding, session authorization, or signing scope. If it is omitted, Wisp falls back to Telegram host close/return behavior. This mirrors the purpose of TON Connect's TMA return URL and OKX's Telegram redirect without claiming wire compatibility with either protocol.

getChain() and getCapabilities() describe the transport's supported Vexanium scope. Telegram Mini Apps use Telegram's native link-opening API when available; non-Telegram browsers use the browser fallback.

transact() accepts one or more structured Vexanium actions, resolves them through the configured VexaniumClient, creates one canonical VSR, opens one Wisp signing handoff, and returns the wallet-broadcast transaction id. Multi-action transactions are never split into independent signatures.

For an existing VSR, use signSigningRequest(vsr) directly after a successful connect() or restore(). The Telegram transport expects a broadcasting VSR and returns the wallet-broadcast transaction id. Signature-only VSRs are not supported by this transport. Every signing handoff is bound to the active session id, origin, chain, account, and permission. Sessionless Telegram signing is not supported.

DApp identity manifest

For Telegram connections, DApp-provided name, icon, and description are hints only. Wisp does not treat those fields as authoritative identity.

A standard DApp must publish a public manifest at:

https://your-dapp.example/wisp-wallet-manifest.json

Minimum manifest:

{
  "url": "https://your-dapp.example",
  "name": "Example App",
  "iconUrl": "https://your-dapp.example/icon-180.png"
}

Optional fields are description, termsOfUseUrl, and privacyPolicyUrl. All URLs must use credential-free HTTPS, and the manifest url origin must exactly match the origin requesting the Wisp connection.

The manifest must be available through an unauthenticated public GET request and must be reachable by the Wisp wallet web runtime. Configure CORS so the wallet can fetch the JSON; do not require cookies, bearer tokens, Telegram initData, or other DApp-session credentials to read the manifest. Wisp does not follow manifest redirects: the requesting HTTPS origin must serve its identity document directly.

DApps that are already marked verified in Wisp's bundled registry use that wallet-owned registry entry as the identity anchor. A manifest can never mark itself verified or trusted. Trusted-session privileges remain wallet-owned policy.

This follows the same security purpose as the TON Connect app manifest: identity shown for connection approval is resolved independently from arbitrary labels inside a connect request. Wisp uses its own WindStack/Wisp wire protocol and does not claim TON Connect wire compatibility.

Runtime

The package targets browser and Telegram Mini App consumers. Injected Wisp providers use the Vexanium provider bridge. External Wisp Telegram flows use the public Wisp handoff API, a resumable server-sent event stream, and Telegram-native link opening when the Telegram WebApp runtime is present. EventSource reconnect remains part of the primary transport; there is no client-side status-poll fallback in WindStack 2.2.

Persistent restore does not depend on an old JavaScript runtime remaining alive. The consumer keeps an opaque session pointer, while Wisp validates authoritative session state. A valid restore can therefore complete after a hard reload or later runtime without reopening the wallet; an expired, revoked, or mismatched session fails closed.

A DApp should model at least these UI states:

restoring -> connected
restoring -> disconnected
user connect -> connecting -> connected
connected -> signing/review -> connected
disconnecting -> disconnected

Do not show the Connect action until the startup restore attempt has settled. Do not treat connection as wallet unlock, and do not treat connection as transaction approval.

The runtime never stores private keys or wallet unlock secrets. Vault unlock and transaction approval remain wallet-owned even while a DApp connection is restored.

Security model

A persistent DApp connection is separate from wallet unlock and transaction approval. Restoring a session does not unlock the vault and does not grant silent signing. Wisp remains responsible for secure unlock, review UI, signing policy, revocation, and session expiry.

Application-supplied display metadata is not an authorization source. Wisp resolves approval identity from its wallet-owned verified registry or from the independently fetched origin manifest described above. Wallet authorization is then bound to the wallet-issued session and exact DApp origin.

A chain other than Vexanium Mainnet is rejected. The package never stores private keys.

License

MIT License.

Created by Gilang Ramadan. Copyright © 2026 PT WIND KRIPTOGRAFI TEKNOLOGI.