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

@metalntwx/metal-pay

v0.2.0

Published

Agent payments on Metal for the official x402 packages: the Metal devnet and testnet as `exact`-scheme networks priced in `*USDZ` for payers and sellers, a one-call payment client with a spending limit, Metal's seller token, the clearing lane for payers w

Readme

@metalntwx/metal-pay

Agent payments on Metal for the official x402 packages: registers the Metal devnet (eip155:1337) and testnet (eip155:63825) for the exact scheme, priced in *USDZ, for both sides of a payment, and adds Metal's clearing lane for payers who pay per call without a transaction each time, and mandates, which let an agent pay from its owner's account within limits Metal enforces.

npm install @metalntwx/metal-pay @x402/core viem

Payers. createMetalPaymentClient gives an agent a one-call payment client; registerMetalNetworks(client, { signer, networks? }) registers the scheme on an x402Client you already have. Both refuse, before signing, a Metal exact offer in any token but *USDZ or under any EIP-712 domain but USDZ's. createMetalPaymentClient also refuses any offer above maxAmount, a bigint in *USDZ base units. The default is DEFAULT_MAX_PAYMENT, 1 *USDZ. It works with @x402/* 2.21 and later. From 2.23 the stock client pays only tokens in its own table unless its spend controls list others; createMetalPaymentClient lists *USDZ there, capped at maxAmount. On a client of your own, add { network, asset: USDZ.address } to setSpendControls({ allowedAssets }). A paid request is never redirected to another origin, so no other site receives the payment. createMandatePaymentClient does the same.

import { privateKeyToAccount } from "viem/accounts";
import { createMetalPaymentClient } from "@metalntwx/metal-pay";

const { fetchWithPayment } = createMetalPaymentClient({
  account: privateKeyToAccount("0x…"),
  network: "devnet",
});
const response = await fetchWithPayment("http://127.0.0.1:4021/quote");

Payees. registerMetalScheme(server, { networks? }) registers the stock exact scheme on an x402ResourceServer with metalUsd, the money parser that prices dollar amounts in *USDZ and names the ERC-3009 message the payer signs (primaryType: "TransferWithAuthorization"); mount it with the official x402 middleware (@x402/hono, @x402/express). On a server that already registers ExactEvmScheme for other networks, add registerMoneyParser(metalUsd(network)) to it instead. Each network's facilitatorUrl is Metal's x402 facilitator for it: https://x402-testnet.metalntwx.com/x402/facilitator on testnet, and http://127.0.0.1:7090/x402/facilitator on devnet, where just x402-facilitator runs it. It settles exact payments for any seller; a seller Metal issued a token to sends it with sellerToken(token), the createAuthHeaders option, and clearing settlement needs one.

import { HTTPFacilitatorClient, x402ResourceServer } from "@x402/core/server";
import { paymentMiddleware } from "@x402/hono";
import { METAL_NETWORKS, registerMetalScheme } from "@metalntwx/metal-pay";

const facilitator = new HTTPFacilitatorClient({ url: METAL_NETWORKS.devnet.facilitatorUrl });
const server = registerMetalScheme(new x402ResourceServer(facilitator));
app.use(
  paymentMiddleware(
    { "GET /quote": { accepts: { scheme: "exact", network: "eip155:1337", payTo: "0x…", price: "0.01" } } },
    server,
  ),
);

Clearing. Sellers register ClearingDebitServerScheme next to the exact scheme and list a clearing-debit offer in a route's accepts; payers pass a ClearingDebitScheme as createMetalPaymentClient's clearing, which pays by clearing, and by exact while custody is short or when the seller cannot take clearing (the facilitator settles clearing only for sellers Metal issued a token), and fund custody with depositToClearing. Given the facilitator, it waits until the facilitator counts the deposit, so the next payment can draw on it. On an x402 client of your own, give it the scheme's selector, new x402Client(clearing.prefer), and its fetch, wrapFetchWithPayment(clearing.wrapFetch(fetch), client), so a Debit whose answer never arrived, or arrived as a bare server error, is presented again rather than paid twice, for as long as the client runs. withdrawFromClearing takes custody out once the epoch holding it has closed and passed its challenge window, and says so when that has not happened yet. @metalntwx/metal-pay/file-storage keeps a clearing payer's record across restarts (Node only). The facilitator's README covers the lane.

Mandates. @metalntwx/metal-pay/mandates lets an agent pay from its owner's account with a P-256 key of its own, within limits Metal enforces on chain. createCredential writes the limits (payees, the most per payment, a budget, how many payments, an expiry) as a Verifiable Intent mandate; ingestCredential verifies one against the issuers the owner trusts, and bindCall, replaceCall and revokeCall build the owner's transactions to its own MetalAccount. Wrap those calls with authorizeMandateCall(client, trustedFactory, call, signQuorum) to authorize an account self-call, or a list of them as one batch that runs whole or not at all, with its existing weighted quorum. The client must name its chain: the digest the quorum signs is computed from it, never read from the RPC endpoint. The callback supports the same EOA, P-256 and passkey signatures as ordinary account execution. Factory-created clones share an immutable VI verifier; budgets and replay protection live in each account. createMandatePaymentClient({ credential, signDigest, network }) is the payer, and MandateExactScheme the same payer as a scheme for an x402Client of your own: each payment is an ERC-3009 authorization from the owner's account whose signature is the agent's per-payment mandate, which the account accepts or refuses through ERC-1271. Sellers and facilitators see an ordinary exact payment. The client sets no limit of its own. readCheck names the limit behind a refusal, readMandateState reads the spend, and pullCall builds a direct payment with no seller. A credential's amounts are decimal, to the cent. verifyMandate and verifyMandatePayment trust the MetalAccountFactory METAL_NETWORKS names for the chain, or the accountFactory given, check the account's clone code against the factory's current implementation, and match the successful token transfer to the seller's requirements. The module runs on Node only.

RPC. Neither payers nor payees need one. Each network's rpc is its default JSON-RPC endpoint, { url } on devnet, or { consoleUrl } on testnet, where each user signs up in the console and creates an endpoint of their own. rpcUrlFor(network, override, how) returns the override or the default, and otherwise throws one line saying how to get an endpoint from the console and how to pass it.

viem is a peer dependency. Run pnpm test and pnpm typecheck.