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

@semore/ap2-adapter

v0.2.0

Published

AP2 (Agent Payments Protocol) Intent/Cart/Payment VC helpers — Ed25519 did:web signature chain scaffold.

Readme

@semore/ap2-adapter

CI License: Apache 2.0 npm status

Part of Semore — Agentic Commerce on the AI Grand Cycle. Korean vertical multi-adapter. (ADR-0111)

W3C Verifiable Credentials helpers for the AP2 (Agent Payments Protocol) Intent → Cart → Payment mandate chain.

AP2 establishes a three-step cryptographic chain that lets an AI agent make a payment on behalf of a user while every party (user, agent, merchant) can independently verify the scope and provenance of the authorisation.

What this means for an LLM agent. The mandate chain is how Semore exposes commerce capability overhang to you: you (the agent) author the IntentMandate the moment a user expresses a goal, refine it into a CartMandate against a live catalog, and surface a PaymentMandate at the merchant boundary — all without ever seeing PAN/CVV, and with every step independently verifiable. Capability that used to require a hosted-page redirect now lives inside the agent loop.

Source of Truth: this directory in the Semore monorepo until repo split. The production chain issuance (issueMandateVC, verifyChain) lives in the internal Semore API at apps/api/src/lib/ap2.ts. This package exposes the stable public shapes and a reference verifyMandateChain scaffold.

Standards-body posture [LEGAL-PENDING]: References to W3C Verifiable Credentials 2.0 and the AP2 Agent Payments Protocol are nominative fair use. Semore claims no endorsement by, affiliation with, or co-authorship of W3C or the AP2 working group. Any co-branded integration is (proposed, subject to joint agreement) with the respective body. [EXTERNAL-ADVISORY]

The 3-VC chain

IntentMandate   ──(parent)──▶   CartMandate   ──(parent)──▶   PaymentMandate
  issuer = user-DID               issuer = agent-DID            issuer = merchant-DID
  what user wants                 what agent picked             what will settle

Each mandate is a W3C VC 2.0 JWT (EdDSA) signed by its issuer DID. Semore issues the merchant-side link of the chain via did:web:semore.net.

Install

npm install @semore/ap2-adapter
# or
pnpm add @semore/ap2-adapter

Usage

import {
  createIntentMandate,
  createCartMandate,
  createPaymentMandate,
  verifyMandateChain,
} from "@semore/ap2-adapter";

const intent = createIntentMandate({
  issuerDid: "did:web:user.example",
  subjectDid: "did:web:user.example",
  claims: { naturalLanguage: "buy Korean sunscreen under $30" },
});

const cart = createCartMandate({
  issuerDid: "did:web:agent.example",
  subjectDid: "did:web:user.example",
  parentVcId: intent.id,
  claims: { items: [{ skuId: "sku_abc", qty: 1, priceUsd: "24.00" }] },
});

const payment = createPaymentMandate({
  issuerDid: "did:web:semore.net",
  subjectDid: "did:web:user.example",
  parentVcId: cart.id,
  claims: { paymentProof: { rail: "card", authCode: "auth_123" } },
});

const result = await verifyMandateChain([intent, cart, payment], {
  resolveDid: async (did) => fetchDidDocument(did),
});

What this package provides

  • Public shapes for IntentMandate, CartMandate, PaymentMandate (W3C VC 2.0).
  • create*Mandate(...) factories that assemble the VC envelope (signing is delegated to the caller — bring your own Ed25519 key via the sign option).
  • verifyMandateChain(chain, opts) — structural + parent-link + signature verification.

What this package does not provide

  • Key management. Use Cloudflare Workers Secrets, AWS KMS, HSM, or your preferred vault.
  • DID document resolution. Supply a resolveDid callback — the canonical did:web resolver is a single fetch(...).
  • The production Semore issuer. did:web:semore.net keys are not in this repo.

DID Resolution

Semore publishes its DID document at https://semore.net/.well-known/did.json. Your resolveDid callback fetches the document, walks verificationMethod, and imports each public JWK into a CryptoKey keyed by its id.

import type { VerifyChainOptions } from "@semore/ap2-adapter";

interface DidDocument {
  readonly id: string;
  readonly verificationMethod: ReadonlyArray<{
    readonly id: string;
    readonly type: string;
    readonly controller: string;
    readonly publicKeyJwk: JsonWebKey;
  }>;
}

const resolveDid: VerifyChainOptions["resolveDid"] = async (did) => {
  const url =
    did === "did:web:semore.net"
      ? "https://semore.net/.well-known/did.json"
      : `https://${did.replace("did:web:", "")}/.well-known/did.json`;
  const res = await fetch(url);
  const doc = (await res.json()) as DidDocument;
  const keys: Record<string, CryptoKey> = {};
  for (const vm of doc.verificationMethod) {
    keys[vm.id] = await crypto.subtle.importKey(
      "jwk",
      vm.publicKeyJwk,
      { name: "Ed25519" },
      true,
      ["verify"],
    );
  }
  return keys;
};

Cache the resolved keys per-DID (Cloudflare KV, an in-memory LRU, or your framework's cache primitive) to avoid re-fetching on every verify call.

Reference

License

Apache-2.0 — see LICENSE.

Copyright (c) Semore Founding Team.