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

@opaqueprivacy/merchant-sdk

v0.1.0-alpha.0

Published

Opaque Pay Merchant SDK — accept private crypto payments on your site.

Downloads

96

Readme

@opaqueprivacy/merchant-sdk

Drop-in SDK for accepting private crypto payments on your site. The amount and sender are hidden on-chain; you still get a signed receipt and a webhook when payment lands.

v1 alpha. APIs may change. Don't rely on this for production revenue yet — treat early integrations as demos. File issues at the main repo.


Install

npm install @opaqueprivacy/merchant-sdk

Get an API key

  1. Go to the Opaque dashboard → Merchant SDK tab.
  2. Click Generate key and copy the op_live_... value. It's shown exactly once.
  3. Paste it into your server's env as OPAQUE_API_KEY.

You also need to have made at least one deposit on Opaque from the wallet you generated the key under — that provisions the intermediate wallet that receives payments.

Server: create a checkout

import { OpaquePay } from "@opaqueprivacy/merchant-sdk";

const opaque = new OpaquePay({ apiKey: process.env.OPAQUE_API_KEY! });

const checkout = await opaque.createCheckout({
  amount: 9.99,
  serviceId: "order_1234",          // your own order ID
  expirationHours: 1,
  callbackUrl: "https://shop.com/webhooks/opaque",
});

// Send the customer to checkout.url, or hand the URL to the browser widget.

Browser: drop-in widget

<button id="pay">Pay with Opaque</button>
<script type="module">
  import { openCheckout } from "@opaqueprivacy/merchant-sdk/browser";

  document.getElementById("pay").onclick = async () => {
    // Ask your server to create a checkout, then open the URL.
    const { url } = await fetch("/api/create-checkout", { method: "POST" })
      .then((r) => r.json());

    try {
      const result = await openCheckout({ url });
      console.log("paid", result.transactionSignature);
    } catch (err) {
      // CheckoutCancelledError if the user closed the popup
    }
  };
</script>

The widget opens /pay/<id> in a popup, listens for a postMessage from the Opaque gateway, and resolves with { requestId, transactionSignature, amount, token } when the on-chain settle lands.

Server: verify the webhook

When the payment lands, Opaque POSTs a JSON event to your callbackUrl and signs it with an ed25519 key. Always verify — anyone could POST anything to your endpoint, but only Opaque can sign with the gateway key.

import express from "express";
import { OpaquePay } from "@opaqueprivacy/merchant-sdk";

const opaque = new OpaquePay({ apiKey: process.env.OPAQUE_API_KEY! });
const app = express();

// Capture the raw body — needed for signature verification.
app.post(
  "/webhooks/opaque",
  express.raw({ type: "*/*" }),
  (req, res) => {
    const sig = req.headers["x-opaque-receipt-signature"] as string;
    try {
      const event = opaque.verifyWebhook(req.body.toString("utf8"), sig);
      // event.requestId, event.amount, event.transactionSignature, …
      // Mark order paid in your DB here.
      res.json({ ok: true });
    } catch (err) {
      res.status(400).json({ error: (err as Error).message });
    }
  },
);

The webhook is best-effort, single attempt in v1 alpha. If your server is down when the gateway tries, the payment still settles on-chain — you can pull the latest state with opaque.retrieveCheckout(id) and reconcile.

Reference

new OpaquePay({ apiKey, baseUrl?, fetch? })

  • apiKey — required. op_live_... from the dashboard.
  • baseUrl — defaults to https://opaque.privacy.
  • fetch — optional custom fetch (defaults to global).

opaque.createCheckout(input)

| Field | Type | Notes | | ----------------- | -------- | -------------------------------------------------- | | amount | number | Human units (9.99 = 9.99 USDC). Required. | | serviceId | string | Your own order/cart ID. Max 200 chars. Required. | | expirationHours | number | Default 24, max 720. | | callbackUrl | string | https:// only. Required if you want a webhook. |

Returns a Checkout with id, url, status, expiresAt, etc.

opaque.retrieveCheckout(id)

Returns the latest state of a checkout. Use this to reconcile if a webhook is missed.

opaque.verifyWebhook(rawBody, signatureHeader)

Verifies the ed25519 receipt signature against the gateway's public key. Returns the parsed WebhookEvent if valid, throws otherwise.

openCheckout({ url, width?, height?, timeoutMs? }) (browser)

Opens the checkout URL in a popup, resolves when the customer pays. Rejects with CheckoutCancelledError if they close the window.

Example

A full Express app is in examples/express/. Run it with:

OPAQUE_API_KEY=op_live_xxx node examples/express/index.js

Then visit http://localhost:3000/pay.html.

Security notes

  • Never embed your API key in client-side code. Always create checkouts from your server.
  • Always verify webhook signatures. Webhooks come from the public internet — only the signature proves they came from Opaque.
  • The plaintext API key is shown once at creation. Revoke and rotate from the dashboard.