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

@easycryptopay/node

v0.2.1

Published

Official Node.js SDK for the EasyCryptoPay crypto payment API

Readme

@easycryptopay/node

Official Node.js SDK for the EasyCryptoPay crypto payment API.

Install

npm install @easycryptopay/node

Requires Node.js 18+ (for native fetch and crypto).

Quick start

import EasyCryptoPay from "@easycryptopay/node";

const client = new EasyCryptoPay({
    apiKey: process.env.ECP_API_KEY!, // ecp_live_… or ecp_test_…
});

// 1. Create a payment. POST a USD amount — the customer picks the currency
//    and network on the hosted /pay page.
const payment = await client.createDeposit({
    amount: 99.99,
    metadata: { order_id: "order_12345" }, // echoed back on every webhook
    idempotencyKey: "order_12345", // safe to retry without dupes
});

console.log(payment.paymentLink); // https://easycryptopay.xyz/pay/inv_abc
console.log(payment.expiresAt);   // ISO timestamp — 7-day window

// 2. Poll status (or use webhooks — see below). Works with the paymentToken
//    or any deposit id created off it on the /pay page.
const status = await client.getDepositStatus(payment.paymentToken);
if (status.status === "completed") {
    console.log("Credited:", status.totalCreditedUSD);
}

Webhooks

Configure your webhook URL in the Branding page, copy the signing secret, and verify every incoming request:

import express from "express";
import { verifyWebhookSignature } from "@easycryptopay/node";

const app = express();

// IMPORTANT: use `express.raw()` — the HMAC is computed over the raw bytes.
app.post("/webhook", express.raw({ type: "application/json" }), (req, res) => {
    const ok = verifyWebhookSignature({
        rawBody: req.body.toString("utf8"),
        signatureHeader: req.header("X-ECP-Signature") || "",
        secret: process.env.ECP_WEBHOOK_SECRET!,
    });
    if (!ok) return res.status(401).end("Invalid signature");

    const event = JSON.parse(req.body.toString("utf8"));
    switch (event.event) {
        case "deposit.completed":
            // event.data.metadata.order_id, event.data.receivedAmountUsd, etc.
            break;
        case "invoice.paid":
            break;
        case "deposit.expired":
            break;
    }
    res.json({ received: true });
});

Test mode

Use an ecp_test_* API key and payments are created in a sandbox — no exchange needed, no real money:

const client = new EasyCryptoPay({ apiKey: process.env.ECP_TEST_KEY! });

// Create a sandbox payment.
const payment = await client.createDeposit({ amount: 25 });

// Open `payment.paymentLink` in a browser and pick a currency. That
// materialises a real (but TEST_-flagged) deposit. Then poll /check to
// grab its id and drive it to completion on demand:
const status = await client.getDepositStatus(payment.paymentToken);
// once status moves past "pending", grab the deposit id from your dashboard
// (or via /api/payments) and:
// await client.completeTestDeposit(depositId);

Test payments are excluded from your balance and volume stats.

Idempotency

Pass an idempotencyKey on any mutating request. Retrying with the same key within 24 hours returns the original response — no duplicate deposits even if your network dropped halfway through a request.

await client.createDeposit({
    amount: 100,
    idempotencyKey: crypto.randomUUID(),
});

If you reuse the key with a different body, you get a 409 so you notice the collision.

API reference

| Method | Description | |---|---| | createDeposit(params) | Create a deposit, returns address + payment link | | getDepositStatus(idOrToken) | Poll a deposit by id or payment token | | getPayment(idOrToken) | Fetch the full deposit record by id or payment token | | completeTestDeposit(idOrToken) | Drive a test deposit to completed (test-mode only) | | createInvoice(params) | Create an invoice with a shareable payment link | | getInvoice(idOrToken) | Fetch a single invoice by id or payment token | | listInvoices(opts?) | List invoices | | listPayments(opts?) | List deposits | | listCustomers(opts?) | List customers (filter by search / status) | | getBalance() | Current balance + volume stats (live only) | | listCurrencies() | Available currencies and networks |

Errors

Every non-2xx response throws an EasyCryptoPayError with .status, .code (if present), and .body:

try {
    await client.createDeposit({ amount: -1 });
} catch (err) {
    if (err.status === 400) {
        console.error("Validation failed:", err.message);
    }
}

Security & supply chain

This package has zero runtime dependencies and runs no install scripts — nothing executes when you npm install it. Its only network access is the API client itself: every request goes to the baseUrl you configure (default https://easycryptopay.xyz) and nowhere else. Pass the fetchImpl option to inspect, proxy, or stub the transport. Supply-chain scanners (e.g. Socket) surface a "network access" note because this is an HTTP client — that's expected for a payments SDK, and the request target is always your own configured host.

License

MIT