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

@euvena/qr

v0.2.0

Published

Encode and decode European payment QR codes: EPC069-12 (EPC QR / GiroCode) and EPC024-22 (MSCT QR, basis of EN 18184)

Readme

@euvena/qr

Encode and decode European payment QR codes in TypeScript, with zero runtime dependencies.

Two codecs are included:

  • EPC069-12 ("EPC QR code" / GiroCode): the line-based payload many European banking apps can scan today to prefill a SEPA Credit Transfer. Ideal for invoices, donations, and pay-me screens.
  • EPC024-22 (MSCT QR, the specification underlying EN 18184:2025): the URL-based QR format for Mobile Initiated SEPA (Instant) Credit Transfers, covering merchant-presented and payer-presented codes for P2P, C2B, B2B and B2C payments.

This library produces and parses QR payloads. Render them with any QR library (EPC069-12 requires error correction level M):

import QRCode from "qrcode";
import { encodeEpcQr } from "@euvena/qr";

const payload = encodeEpcQr({
  name: "Franz Mustermann",
  iban: "DE71 1102 2033 0123 4567 89",
  amount: 12.3,
  text: "Invoice 2026-001",
});
await QRCode.toDataURL(payload, { errorCorrectionLevel: "M" });

EPC069-12

import { encodeEpcQr, decodeEpcQr } from "@euvena/qr";

const payload = encodeEpcQr({
  name: "Red Cross of Belgium",
  iban: "BE72000000001616",
  amount: "1",          // number or numeric string, 0.01..999999999.99
  purpose: "CHAR",       // optional AT-44 purpose code
  text: "Urgency fund",  // or `reference` for an ISO 11649 RF creditor reference
});

const { data } = decodeEpcQr(scannedText);
// data.name, data.iban, data.amount, ...

Validation covers IBAN check digits and country lengths, BIC format, the version 001 BIC requirement, ISO 11649 RF reference check digits, amount range, mutually exclusive remittance fields, character set constraints, and the 331 byte payload limit. Both official examples from the specification are reproduced byte for byte in the test suite.

decodeEpcQr(text, { strict: false }) returns structurally readable payloads together with a list of issues instead of throwing.

EPC024-22 / EN 18184

An MSCT QR code is an https URL:

https://<domain>/<version>/<type>/<MSCT service provider ID>/?<payload>

where type is the payment context: m (POI), e (e-commerce), i (invoice), p (person-to-person), w (webview). Three payee-presented payload profiles exist (token, proxy, all data in clear) plus a payer-presented token profile:

import { encodeMsctPayeeClear, decodeMsctQr } from "@euvena/qr";

const url = encodeMsctPayeeClear({
  domain: "qr.example.org", // your MSCT framework or scheme domain
  providerId: "AB1",         // 3-character MSCT service provider ID
  issuer: "XY9",             // 3-character payload issuer ID
  context: "p",
  name: "Alice Example",
  iban: "BE72000000001616",
  instrument: "INST",        // SEPA Instant ("SCT" for regular)
  amount: 24.5,
  remittance: "lunch",
});

const { data } = decodeMsctQr(scannedUrl);
if (data.kind === "payee-clear") {
  // data.name, data.iban, data.amount, data.instrument, ...
}

A note on parameter names

EPC024-22 standardises the URL structure and the payload content, but explicitly leaves the query parameter names to the payload issuer. The names used by default here (iss, tok, prx, nm, iban, ins, cur, amt, ...) are the Euvena profile v1, an open naming proposal. Every encode and decode function accepts a keys mapping to interoperate with issuers that made different choices, and decodeMsctQr always returns the raw URLSearchParams.

payto handoff (RFC 8905)

A payto://iban URI carries the same SEPA credit transfer request as an EPC069-12 code, as a link one app can hand to another on the same phone. The mapping, the rules for reading and what a banking app registers to receive them are in the payto handoff profile.

import { decodeEpcQr, decodePaytoUri, encodeEpcQr, encodePaytoUri } from "@euvena/qr";

// A scanned code as a handoff. No payto option carries a structured
// reference, so it is refused unless the caller leaves it out and shows it.
const { data } = decodeEpcQr(scannedText);
const uri = encodePaytoUri(data, { omitReference: true });
// payto://iban/DE33100205000001194700?amount=EUR:13.05&receiver-name=...

// An incoming URI, in a banking app. Throws PaytoError with a `code`.
const transfer = decodePaytoUri(uri);
const payload = encodeEpcQr(transfer); // the same request as a code

Both directions hold every element to the EPC069-12 checks. isPaytoUri tells a payto URI from other input.

Utilities

isValidIban, normalizeIban, IBAN_LENGTHS, isValidRfReference, formatAmount, isValidAmountString, byteLength, isLatin1.

Specifications

  • EPC069-12 v3.1, Quick Response Code: Guidelines to Enable the Data Capture for the Initiation of a SEPA Credit Transfer (EPC, 19 March 2024)
  • EPC024-22 v2.10, Standardisation of QR-codes for Mobile Initiated SEPA (Instant) Credit Transfers (EPC, 17 June 2024)
  • RFC 8905, The 'payto' URI Scheme for Payments (October 2020)

Both are freely available from the EPC document library. This is an independent implementation written from the freely published EPC documents; it is not endorsed by the European Payments Council.

License

Apache-2.0