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

@megaeth-labs/wallet-merchant

v0.1.4

Published

Server-side merchant (sponsor) for MegaETH wallet's wallet_sendCalls flow.

Readme

@megaeth-labs/wallet-merchant

Server-side merchant (gas sponsor) for the MegaETH wallet's sponsored wallet_sendCalls flow. The wallet builds the unsigned V0.6 intent locally (it owns the chain client) and POSTs it to the merchant; the merchant overrides payer + paymentMaxAmount, signs the gas-independent PaymentAuthorization digest, embeds the signature, recomputes txEntryGas / gasFloor / digest, and returns the result. The wallet then adds the user's signature over the new digest and submits to the relay.

The merchant never reads chain state — every input it needs (intent fields, assembled calls, EIP-712 domain, and the user's signing key type) is in the request body.

Install

pnpm add @megaeth-labs/wallet-merchant

For local development the consumer (wallet-backend) uses a file: dep:

{
    "dependencies": {
        "@megaeth-labs/wallet-merchant": "*"
    }
}

Prerequisites

address must be a porto-upgraded (EIP-7702) merchant account. If key is the merchant account's own secp256k1 root key, the signer emits a raw root signature. If key is a session key, P256 key, or non-root secp256k1 key, it must be authorized on the merchant account via a prior authorize(...) call; the signer emits the porto-wrapped form (sig + keyHash + prehash), and the orchestrator must be able to find keyHash in the merchant account's keyStorage. Production setups should use a session key with spend permission for the payment token and amount the merchant is willing to cover.

Usage

import { Hono } from 'hono';
import { merchant } from '@megaeth-labs/wallet-merchant';

const router = new Hono();

router.route(
    '/',
    merchant({
        address: process.env.MERCHANT_ADDRESS as `0x${string}`,
        // Plain hex defaults to secp256k1.
        key: process.env.MERCHANT_PRIVATE_KEY as `0x${string}`,
    }),
);

P256 keys are also accepted, matching porto's merchant.Options.key:

merchant({
    address: process.env.MERCHANT_ADDRESS as `0x${string}`,
    key: {
        type: 'p256',
        privateKey: process.env.MERCHANT_PRIVATE_KEY as `0x${string}`,
    },
});

When paymentMaxAmount is omitted, the merchant derives its own cap from the wallet-provided paymentPerGas and ESTIMATED_GAS_BUDGET. This avoids retaining the wallet SDK's generic default cap, which is too large for lower-decimal fee tokens. Set paymentMaxAmount only when you want a fixed merchant spend cap, or set paymentGasBudget to tune the derived cap.

Funding a merchant key

To generate fresh merchant credentials and fund the new account, run this from a checkout of this repository:

pnpm create-merchant \
    --network testnet \
    --funder-key <0x...>

The script always generates a new secp256k1 EOA. It transfers native ETH and USDm from the --funder-key account to that new address, then uses @megaeth-labs/wallet-intent to submit the 7702 upgrade through the relay. USDm is sent through ERC20 0x15e9f2b0a747ac05c7446559306687085d161e5c. If the funder account is already delegated, funding is submitted through the relay as a single bundled call to avoid delegated-account in-flight raw transaction limits when the delegation target matches the current relay account proxy. Older or otherwise incompatible delegated funders fall back to serialized raw transactions with retry.

On success the script prints MERCHANT_ADDRESS / MERCHANT_PRIVATE_KEY.

Flags:

  • --network testnet|mainnet — selects chain ID + RPC preset (testnet: 6343 / https://carrot.megaeth.com/rpc, mainnet: 4326 / https://mainnet.megaeth.com/rpc).
  • --funder-key <0x...> — secp256k1 private key for the funding account.
  • --merchant-key <0x...> with --upgrade-only — resume a run after funding succeeded but the 7702 upgrade failed.
  • --eth-amount <amount> — native ETH amount to transfer. Defaults to 0.001.
  • --usdm-amount <amount> — USDm amount to transfer. Defaults to 10.
  • --chain-id <n> / --rpc-url <url> — override the preset.
  • --relay-url <url> — override the preset relay URL (testnet: https://carrot.megaeth.com/relay, mainnet: https://mainnet.megaeth.com/relay).
  • --write-env — append the credentials to ./.env (use --force to overwrite existing merchant credentials).

The script does not call the merchant service; it uses the same wallet-intent relay path as the wallet.

Demo service

Add merchant credentials to .env:

MERCHANT_ADDRESS=0x...
MERCHANT_PRIVATE_KEY=0x...

Run a minimal local Hono service that mounts the merchant route at /. pnpm demo builds the package, loads .env, and starts a PM2 process named wallet-merchant-demo:

pnpm demo

The service listens on http://localhost:3000/ by default:

curl http://localhost:3000/

Set PORT if you need something other than 3000:

PORT=4319 pnpm demo

Stop the local demo when finished:

pnpm exec pm2 delete wallet-merchant-demo

The same demo/index.ts file is also the Vercel Hono entrypoint. It exports the app for Vercel and only starts the local Node listener when VERCEL is not set. Vercel reads MERCHANT_ADDRESS and MERCHANT_PRIVATE_KEY from the project environment variables; do not commit those values.

Vercel deployment

The Vercel project is configured by vercel.json to use the Hono runtime with demo/index.ts as the entrypoint. Validate the production build locally:

vercel build --prod --yes --scope mega-eth

Deploy the prebuilt output:

vercel deploy --prebuilt --prod --scope mega-eth

The production alias is:

https://wallet-merchant.vercel.app/

Wire format

POST / with JSON body:

{
    intent: JsonRpcIntent;   // wallet-built unsigned intent
    domain: { name; version; chainId; verifyingContract }; // orchestrator EIP-712 domain
    keyType?: 'address' | 'p256' | 'secp256k1' | 'webauthn-p256';
}

The bundled calls are decoded from intent.executionData on the merchant side, so the wallet does not send them separately. keyType is used to mirror wallet-side signature-verification gas buffers, including the WebAuthn buffer.

Successful response (200):

{ intent: JsonRpcIntent; digest: Hex }

Errors are returned as { error: { code: number; message: string } } with a 4xx/5xx status (400 invalid request, 403 sponsor declined, 500 internal).

Options

type MerchantOptions = {
    /**
     * Porto-upgraded merchant account address, used as `intent.payer`.
     * With a root-key setup, this is the EOA derived from `key`; with an
     * admin/session-key setup, this is the upgraded EOA that authorized `key`.
     */
    address: `0x${string}`;
    /**
     * Merchant key used to sign `paymentSignature`. If this is the merchant
     * account's root secp256k1 key, the route emits a raw root signature.
     * Otherwise, the key must be registered on `address` (via
     * `authorize(...)`) before the route can produce valid wrapped signatures.
     * When this is a session key, it must have spend permission for the
     * payment token and covered amount.
     *
     * Accepts a `Hex` private key (treated as secp256k1) or
     * `{ type: 'secp256k1' | 'p256'; privateKey: Hex }` for explicit
     * selection, mirroring porto's `merchant.Options.key`.
     */
    key:
        | `0x${string}`
        | { type: 'secp256k1' | 'p256'; privateKey: `0x${string}` };
    /** Decide per-request whether to sponsor. Defaults to `true`. */
    sponsor?: boolean | ((request: SponsorRequest) => boolean | Promise<boolean>);
    /**
     * Max amount of `paymentToken` (raw base units) the merchant is willing
     * to pay per request — the merchant's own spend cap. Overrides whatever
     * the wallet sent. When omitted, the merchant derives a cap from
     * `paymentGasBudget` and the wallet-provided `paymentPerGas`.
     */
    paymentMaxAmount?: bigint;
    /**
     * Gas budget used to derive the default merchant spend cap when
     * `paymentMaxAmount` is omitted. Defaults to `ESTIMATED_GAS_BUDGET`.
     */
    paymentGasBudget?: bigint;
    /** Hono base path. Defaults to `/`. */
    basePath?: string;
    /** Hono CORS options. */
    cors?: Parameters<typeof import('hono/cors').cors>[0];
};