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

@integraledger/lcp

v0.2.0

Published

Assemble and hash an Agentic Transaction Record (ATR), and carry the hash in x402, MPP, AP2, ACP, UCP, ACK and card payments across chains and rails, and in A2A task metadata.

Readme

@integraledger/lcp

Assemble an Agentic Transaction Record, hash its exact bytes, and bind that hash into the payment, on x402, MPP, agentic checkouts and card networks, across every chain and rail they settle on.

npm License: Apache-2.0 Node >=26.10.0

@integraledger/lcp is the reference implementation of the Legal Context Protocol (LCP): the pattern in which the payment carries the hash of the agreement's record, so paying is agreeing to that exact record. The seller assembles the record and advertises its hash; the buyer fetches the record, compares it with the hash, and signs a payment that carries the hash; the seller reads the hash back from the payment and from the settlement.

The package is deterministic and small at its core. It holds no key, signs nothing, calls no network on its own, and carries no business or legal logic. What the agreement says is the parties' business; this package makes sure that what they agreed is the record the payment is bound to.

Key concepts

| Term | Meaning | |---|---| | Agentic Transaction Record (ATR) | The agreement's record, a JSON document the seller serves. | | ATR hash (H) | SHA-256 over the ATR's exact bytes. | | Legal Context Protocol (LCP) | The pattern this package implements: the payment carries H, so paying is agreeing to that exact record. | | Pairing | A payment protocol, scheme and rail combination, such as x402/exact/eip155/eip3009. | | Binding | How H rides in a pairing's payment: the field its specification defines. | | Buyer gate | The buyer-side check that compares the served bytes with H before anything is signed. | | Seller | The party serving the resource. | | Facilitator | The x402 role that verifies and settles. | | Vectors | The shared test cases that fix the rules byte for byte across languages. |

sequenceDiagram
  participant B as Buyer
  participant S as Seller
  B->>S: request
  Note over S: assemble the ATR, hash it (H), store the bytes at a link
  S-->>B: 402 challenge carrying H and the link
  B->>S: fetch the link
  S-->>B: the ATR's exact bytes
  Note over B: buyer gate: SHA-256(bytes) equals H, or stop
  Note over B: build the payment with H in its field, sign it
  B->>S: payment carrying H
  Note over S: bound(payment) equals H, then settle, then status reads H on the rail

Install

npm install @integraledger/lcp

The package is ESM only, with type declarations for every entry point. Its three dependencies are @noble/curves, @noble/hashes and @scure/base.

Some rails parse their wire formats with the rail's own library. Those libraries are optional peer dependencies: install the one for each rail you use, at the version the package names.

| Rail | Install | Used by | |---|---|---| | Solana | @solana/kit | the Solana pairings on x402 and MPP | | Stellar | @stellar/stellar-sdk | the Stellar pairings on x402 and MPP | | XRP Ledger | ripple-binary-codec | the XRPL pairings on x402 and MPP | | Sui | @mysten/sui | x402/exact/sui | | NEAR | @near-js/crypto, @near-js/transactions, borsh | x402/exact/near | | TON | @ton/core | x402/exact/tvm | | Algorand | algosdk | x402/exact/algorand | | Stacks | @stacks/transactions | mpp/charge/usdc/stacks |

Without its peer, a rail's functions refuse with <rail>/peer-missing, or the pairing serves no option. Every other rail, and every protocol surface, needs nothing more.

Quickstart

One x402 payment on x402/exact/eip155/eip3009, both sides, in one program. A Map stands in for the seller's storage and a random key for the buyer's signer, so it runs without a network. Signing uses viem (npm install viem); any EIP-712 signer works.

import { assemble, hash, hashEquals, isRefusal, newAtrId } from "@integraledger/lcp";
import {
  exactEip3009,
  requestCommitment,
  tie,
  type PaymentRequired,
  type PaymentRequirements,
} from "@integraledger/lcp/x402";
import type { TypedDataDefinition } from "viem";
import { generatePrivateKey, privateKeyToAccount } from "viem/accounts";

// The seller's x402 challenge: one option, USDC on Base Sepolia.
const option: PaymentRequirements = {
  scheme: "exact",
  network: "eip155:84532",
  amount: "10000",
  asset: "0x036CbD53842c5426634e7929541eC2318f3dCF7e",
  payTo: "0x209693Bc6afc0C5328bA36FaF03C514EF312287C",
  maxTimeoutSeconds: 60,
  extra: { name: "USDC", version: "2" },
};
const challenge: PaymentRequired = {
  x402Version: 2,
  resource: { url: "https://api.seller.example/v1/quote" },
  accepts: [option],
};

// Seller: assemble the ATR for this request, store its bytes, and advertise H.
const request = await requestCommitment({ method: "GET", target: "/v1/quote", body: new Uint8Array() });
if (isRefusal(request)) throw new Error(request.code);
const terms = new TextEncoder().encode('{"text":"One quote for 10000 base units of USDC."}');
const atr = await assemble(newAtrId(), tie(challenge.accepts, request), [["terms", terms]]);
if (isRefusal(atr)) throw new Error(atr.code);
const link = `https://atr.seller.example/${atr.atrHash}`;
const storage = new Map([[link, atr.bytes]]);
const advertised = exactEip3009.advertise(challenge, atr.atrHash, link, option);
if (isRefusal(advertised)) throw new Error(advertised.code);

// Buyer: read H and the link, fetch the bytes, and compare before signing anything.
const offer = exactEip3009.read(advertised);
if (isRefusal(offer)) throw new Error(offer.code);
const served = storage.get(offer.link);
if (served === undefined || !hashEquals(await hash(served), offer.h)) throw new Error("the ATR does not match H");

// Buyer: build the EIP-3009 authorization whose nonce is H, sign it, and complete the payment.
const payer = privateKeyToAccount(generatePrivateKey());
const unsigned = await exactEip3009.build(
  { required: advertised, accepted: offer.offer.options[0]!, from: payer.address, now: Math.floor(Date.now() / 1000) },
  offer.h,
);
if (isRefusal(unsigned)) throw new Error(unsigned.code);
const payment = unsigned.complete(await payer.signTypedData(unsigned.typedData as TypedDataDefinition));
if (isRefusal(payment)) throw new Error(payment.code);

// Seller: read H from what the payer signed, and match it to the H it issued.
const bound = await exactEip3009.bound(payment);
if (typeof bound !== "string") throw new Error(bound.code);
console.log("the signed nonce is H:", hashEquals(bound, atr.atrHash));
the signed nonce is H: true

Each pairing's functions return their result or a refusal, { refused: true, code }, whose code names what is wrong, such as x402/link-not-https. isRefusal(result) tells the two apart. Only the package makes refusals: a value you pass in is never returned to you as one, whatever members it carries (refusals).

Guides

The documentation covers each flow with runnable examples:

API

Each entry point is imported by its subpath. The core:

| Export | What it does | |---|---| | assemble(id, binding, content, limits?) | Writes the ATR's bytes in fixed order and returns them with H, or a refusal. | | newAtrId() | A random RFC 9562 version 4 UUID for the ATR's id. | | hash(bytes) | SHA-256 over the bytes as given, as 0x and lowercase hex. | | hashEquals(a, b) | True when both are 32-byte hashes, in either case, with the same bytes. | | isRefusal(v) | True only for a refusal this package made: how a caller tells a refusal from a result. | | toLcpString(h), fromLcpString(s) | H as lcp:sha256:0x… (LCP §8.1), and back. | | toLegalContext(h, url, spelling?), fromLegalContext(o) | H and the link as { legalContext: { type, value, legalContextUrl } } (LCP §8.1), and back. | | toRawBytes(h), fromRawBytes(b) | H as 32 raw bytes, and back. | | isHttpsLink(s) | The one rule every link to an ATR meets. | | digestJson(v), canonicalJson(v) | SHA-256 over the RFC 8785 form of a JSON value, and that form. | | parseJson(text), jsonWithinDepth(text), MAX_JSON_DEPTH | JSON reading capped at 64 levels of nesting. | | BINDINGS | Every pairing this package implements. | | pairingOf(option) | The x402 pairing that serves an x402 option. | | pairingsOfPlaced(challenge) | The MPP pairings a placed MPP challenge offers. | | canonicalTx(binding, tx) | A transaction id in the one spelling a record keeps. |

The protocol and rail entry points:

| Entry point | Holds | |---|---| | @integraledger/lcp/x402 | x402 documents, the legalContext extension, the request commitment, and the EVM exact, upto and auth-capture pairings. | | @integraledger/lcp/x402-batch-settlement | x402 batch-settlement on EVM, Solana and Cloudflare: one ATR per channel. | | @integraledger/lcp/x402-exact-solana, …/x402-upto-solana, …/x402-exact-stellar, …/x402-exact-xrpl | The x402 pairings on Solana, Stellar and the XRP Ledger. | | @integraledger/lcp/mpp | MPP challenges, H as the challenge id, and every MPP charge, session and subscription pairing. | | @integraledger/lcp/acp, …/ucp, …/ap2, …/ack | Agentic checkouts: ACP, UCP, AP2 and ACK. | | @integraledger/lcp/card | Visa TAP, Mastercard Verifiable Intent and the plain card checkout. | | @integraledger/lcp/a2a | H and the link in an A2A Task's metadata. | | @integraledger/lcp/discovery | The discovery document at /.well-known/legal-context.json (LCP §2). | | @integraledger/lcp/evm, …/tempo, …/svm, …/stellar, …/xrpl, …/hedera, …/avm, …/aptos, …/cardano, …/casper, …/ccd, …/near, …/polkadot, …/starknet, …/sui, …/tron, …/tvm, …/lightning, …/stacks | Each rail's pieces and pairings: its signed form, where H rides, and the settlement read. |

The entry point reference lists every export of every entry point, and the API reference gives each signature.

Every pairing has the same members: id, pattern (what a payment through it proves), tie (the ATR's binding slot), advertise and read (H into and out of the challenge), build (what the buyer signs, with H in its place), and bound (H back out of the payment). Pairings that settle on a readable rail add reference, status and, where the rail keeps H, recover. EVM pull pairings add authorizer, the account whose signature authorises the pull.

Supported pairings

Generated from BINDINGS by scripts/docs-reference.mjs, which CI runs to check this list against the registry.

67 pairings on 7 surfaces.

| Surface | Pairings | |---|---| | ack (1) | ack/payment-request | | acp (2) | acp/checkout/delegated, acp/checkout/undelegated | | ap2 (1) | ap2/checkout-mandate | | card (4) | card/mastercard-vi/autonomous, card/mastercard-vi/immediate, card/seller-reference, card/visa-tap | | mpp (26) | mpp/charge/card, mpp/charge/evm/authorization, mpp/charge/evm/hash, mpp/charge/evm/permit2, mpp/charge/evm/transaction, mpp/charge/hedera, mpp/charge/lightning, mpp/charge/nearintents, mpp/charge/solana, mpp/charge/stellar, mpp/charge/stripe, mpp/charge/tempo/memo, mpp/charge/tempo/push, mpp/charge/usdc/evm, mpp/charge/usdc/gateway, mpp/charge/usdc/solana, mpp/charge/usdc/stacks, mpp/charge/xrpl, mpp/session/evm, mpp/session/hedera, mpp/session/lightning, mpp/session/solana, mpp/session/tempo, mpp/session/xrpl, mpp/subscription/stripe, mpp/subscription/tempo | | ucp (4) | ucp/booking/ap2-mandate, ucp/booking/unsigned, ucp/checkout/ap2-mandate, ucp/checkout/unsigned | | x402 (29) | x402/auth-capture/eip155/eip3009, x402/auth-capture/eip155/permit2, x402/batch-settlement/cloudflare, x402/batch-settlement/eip155, x402/batch-settlement/solana, x402/exact/algorand, x402/exact/aptos, x402/exact/cardano, x402/exact/casper, x402/exact/ccd, x402/exact/eip155/eip3009, x402/exact/eip155/erc7710, x402/exact/eip155/erc7710-salt, x402/exact/eip155/permit2, x402/exact/hedera, x402/exact/hedera/transfer-executor, x402/exact/lnbtc, x402/exact/lnbtc/invoice-named, x402/exact/near, x402/exact/polkadot/lcp-assets-remark, x402/exact/solana, x402/exact/starknet, x402/exact/stellar, x402/exact/sui, x402/exact/tron/lcp-trc20-memo, x402/exact/tvm, x402/exact/xrpl, x402/upto/eip155/permit2, x402/upto/solana |

The pairings reference gives each one's binding pattern, whether the buyer signs H, whether H is on chain, and the sentence its record states about what the payment proves.

What it guarantees, and what it does not

It does:

  • write an ATR's bytes deterministically, and hash exactly those bytes;
  • compare hashes by their 32 bytes, in either case;
  • place H, and the link to the seller's copy, where each pairing's specification provides a place;
  • build what the buyer signs with H in its place, and read H back from what was signed;
  • read settlement through a reader you supply, with a bounded number of calls, and treat a failed read as pending, never as failed;
  • state, for every pairing, what a payment through it proves, and never claim more. Where the buyer's approval does not sign H, the record says so.

It does not:

  • decide what an ATR contains, or read the parties' content;
  • check amount, payee, asset, timing or payer against the ATR's content: a discrepancy is between the parties, and the record is what they agreed;
  • hold keys, sign, move funds, call a facilitator or fetch anything on its own;
  • store ATRs: the seller and the buyer each keep their own copy;
  • verify every signature it reads: each pairing's proves names which signatures the rail or network verifies and which this package checks.

Vectors and conformance

The package ships its test vectors in vectors/: one JSON file per entry point or pairing, each with an about that names where its expected values come from (published specification examples, standard test values, live network reads and independent tools). They fix the ATR's exact bytes and hash, each refusal, the link rule, the buyer gate's rows, and for each pairing the placed challenge, what the payer signs, H read back, and the settlement read. Any implementation that passes them agrees with this one byte for byte. The package's own tests run every file, and the buyer packages in integra-agentic-terms run them from TypeScript and Python.

The LCP profiles this package implements ship in profiles/, one Markdown file per profile, each stating its binding's rules.

Requirements

  • Node.js >=26.10.0.
  • ESM. TypeScript users need "moduleResolution": "nodenext" (or "bundler") to resolve the subpath exports.
  • Cloudflare Workers, with or without the nodejs_compat flag. Install the optional peer dependencies before bundling: without them, wrangler's bundler cannot resolve @mysten/sui/bcs, @mysten/sui/utils, @near-js/crypto, @near-js/transactions and borsh.

Related packages

Contributing

See the repository README and CONTRIBUTING.md.

License

Apache-2.0.