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

@angloqq03/gpv

v1.1.4

Published

OCR-powered GCash screenshot proof validation for Node.js using Tesseract.js and Brain.js.

Readme

@angloqq03/gpv

GPV is a GCash proof validator toolkit for Node.js.

It gives you two main paths:

  • OCR-only mode if you just want to extract text, reference, amount, and date
  • OCR + risk scoring mode if you also want Brain.js-based fraud signals

Under the hood, GPV uses:

  • tesseract.js for OCR
  • brain.js for risk scoring

It also ships with an interactive Express demo so developers can test everything in a browser before integrating it into a real app.

Why GPV? 💸

Payment proof screenshots are useful, but they can also be:

  • edited
  • cropped
  • reused
  • partially hidden
  • taken from different bank apps and passed off as something else

GPV helps you:

  • read proof screenshots
  • extract likely proof fields
  • compare them against expected transaction data
  • optionally score how suspicious the proof looks

Pick your mode ✨

1. OCR-only mode

Use this when you only want extraction and parsing.

Main functions:

  • extractTextFromImage()
  • parseProofText()
  • extractProofDetails()
  • isReferenceDetected()
  • isAmountDetected()
  • isDateDetected()

2. Default built-in model mode

Use this when you want OCR plus the package's built-in Brain.js JSON model.

Main functions:

  • validateProof()
  • fullAnalysis()
  • validateUploadedProof()
  • analyzeUploadedProof()
  • createExpressProofValidator()

3. Custom model mode

Use this when you want to train your own Brain.js model from real proof samples.

Main functions:

  • npm run train:model
  • loadFraudModelFromFile()
  • setFraudModel()
  • resetFraudModel()

Once you call setFraudModel(customModel), GPV uses your custom model for scoring.

Install 📦

npm install @angloqq03/gpv

The required dependencies are installed automatically through npm.

Super quick start 🚀

import { isRefValid, fullAnalysis } from "@angloqq03/gpv";

console.log(isRefValid("123456789012"));

const result = await fullAnalysis("./proof.png", {
  reference: "123456789012",
  amount: 499.99,
  date: "2026-04-03"
});

console.log(result.ok);
console.log(result.extracted);
console.log(result.risk);

Interactive demo server 🧪

If you want a browser playground for the package:

npm run demo

Then open:

http://localhost:3210/demo/

What you can do in the demo:

  • upload a proof image
  • switch between OCR only, Validate with model, and Full analysis
  • set expected reference, amount, date, bank, source bank, and destination
  • tweak OCR settings like pageSegMode
  • enable a custom OCR crop rectangle
  • inspect the live JSON result

You can also start the demo server in code:

import { startInteractiveDemoServer } from "@angloqq03/gpv";

startInteractiveDemoServer({
  port: 3210
});

OCR-only usage 🔎

Extract raw OCR text

import { extractTextFromImage } from "@angloqq03/gpv";

const ocr = await extractTextFromImage("./proof.png");

console.log(ocr.confidence);
console.log(ocr.text);

Extract likely proof fields

import { extractProofDetails } from "@angloqq03/gpv";

const details = await extractProofDetails("./proof.png");

console.log(details.extracted.reference);
console.log(details.extracted.amount);
console.log(details.extracted.date);

Parse OCR text manually

Useful if OCR happens elsewhere.

import { parseProofText } from "@angloqq03/gpv";

const parsed = parseProofText(`
Amount Paid PHP 3,000.00
Ref. No. 5695 5992 5
12 April 2022 01:46:01 PM
`);

console.log(parsed.extracted);

GPV now uses context-aware parsing, so it is better at:

  • preferring Ref. No. over Account Number
  • preferring Amount Paid over Fee
  • recognizing full month-name dates like 12 April 2022

Default model usage 🧠

Validate with the built-in model

import { validateProof } from "@angloqq03/gpv";

const result = await validateProof("./proof.png", {
  reference: "123456789012",
  amount: 250,
  date: "2026-04-03"
});

console.log(result.ok);
console.log(result.checks);
console.log(result.risk.level);

Full analysis with summary

import { fullAnalysis } from "@angloqq03/gpv";

const analysis = await fullAnalysis("./proof.png", {
  reference: "123456789012",
  amount: 250,
  date: "2026-04-03"
});

console.log(analysis.summary);
console.log(analysis.rawText);
console.log(analysis.candidates);

Express usage ⚡

Manual route style

npm install express multer
import express from "express";
import multer from "multer";
import { analyzeUploadedProof } from "@angloqq03/gpv";

const app = express();
const upload = multer({ dest: "uploads/" });

app.post("/upload-proof", upload.single("proof"), async (req, res, next) => {
  try {
    const expected = {
      reference: req.body.reference,
      amount: Number(req.body.amount),
      date: req.body.date
    };

    const result = await analyzeUploadedProof(req.file, expected, {
      amountTolerance: 0
    });

    res.json({
      success: true,
      validation: result
    });
  } catch (error) {
    next(error);
  }
});

Middleware style

import express from "express";
import multer from "multer";
import { createExpressProofValidator } from "@angloqq03/gpv";

const app = express();
const upload = multer({ dest: "uploads/" });

app.post(
  "/upload-proof",
  upload.single("proof"),
  createExpressProofValidator({
    attachToRequestAs: "proofAnalysis",
    run: "fullAnalysis",
    getExpected: async (req) => ({
      reference: req.body.reference,
      amount: Number(req.body.amount),
      date: req.body.date
    })
  }),
  (req, res) => {
    res.json({
      success: true,
      validation: req.proofAnalysis
    });
  }
);

Custom model workflow 🛠️

If you have real proof samples from:

  • GCash
  • CIMB to GCash
  • MariBank to GCash
  • other bank-to-GCash transfer flows

then you can train your own Brain.js JSON model.

Step 1: Add labeled samples

Put screenshots in proofsamples/ and describe them in proofsamples/labels.json.

Example:

{
  "language": "eng",
  "amountTolerance": 0,
  "logOcrProgress": false,
  "trainingOptions": {
    "iterations": 4000,
    "log": false
  },
  "samples": [
    {
      "name": "gcash-real-001",
      "image": "proofsamples/gcash-real-001.png",
      "bank": "gcash",
      "sourceBank": "gcash",
      "destination": "gcash",
      "route": "wallet_to_wallet",
      "legitimate": 1,
      "isEdited": false,
      "isSynthetic": false,
      "fraudType": "none",
      "tags": ["real", "wallet-to-wallet"],
      "notes": "Confirmed against real payment records.",
      "expected": {
        "reference": "123456789012",
        "amount": 250,
        "date": "2026-04-03"
      }
    }
  ]
}

Step 2: Train the model

npm run train:model

This generates:

  • models/custom-risk-model.json
  • models/last-training-dataset.json

Step 3: Load and use your model

import {
  loadFraudModelFromFile,
  setFraudModel,
  validateUploadedProof
} from "@angloqq03/gpv";

const customModel = await loadFraudModelFromFile("./models/custom-risk-model.json");
setFraudModel(customModel);

const result = await validateUploadedProof("./proofsamples/gcash-real-001.png", {
  reference: "123456789012",
  amount: 250,
  date: "2026-04-03"
});

console.log(result.risk);

Switch back to default model

import { resetFraudModel } from "@angloqq03/gpv";

resetFraudModel();

Helpful functions 🧩

OCR and parsing

  • extractTextFromImage(image, options?)
  • parseProofText(text, options?)
  • extractProofDetails(image, options?)

Validation and analysis

  • validateProof(image, expected?, options?)
  • fullAnalysis(image, expected?, options?)
  • validateUploadedProof(upload, expected?, options?)
  • analyzeUploadedProof(upload, expected?, options?)
  • createInteractiveDemoServer(config?)
  • startInteractiveDemoServer(config?)

Model helpers

  • createFraudDetectionModel()
  • trainFraudModelFromDataset()
  • buildDatasetFromProofSamples()
  • loadFraudModelFromFile()
  • saveFraudModelToFile()
  • setFraudModel()
  • resetFraudModel()

Comparison and detection

  • compareReference(reference, expectedReference)
  • compareAmount(amount, expectedAmount, tolerance?)
  • compareDate(date, expectedDate)
  • isReferenceDetected(image)
  • isAmountDetected(image)
  • isDateDetected(image)

Format and utility helpers

  • isRefValid(reference)
  • isValidReference(reference)
  • isReferenceFormatValid(reference)
  • isAmountFormatValid(amount)
  • isDateFormatValid(date)
  • normalizeReference(reference)
  • normalizeAmount(amount)
  • normalizeDate(date)
  • parseNumericAmount(amount)
  • toCleanText(text)
  • safeDate(date)
  • isDateRecent(date, maxAgeDays?)

Options 🎛️

const options = {
  language: "eng",
  amountTolerance: 0,
  pageSegMode: 6,
  rectangle: { top: 0, left: 0, width: 1080, height: 1920 },
  logger: (message) => console.log(message)
};

Notes:

  • pageSegMode: 6 is a solid default for proof screenshots and receipts
  • OCR text is rebuilt in top-to-bottom order from Tesseract block data
  • validateProof() and fullAnalysis() use the active model automatically

Testing with proof.png 🧪

If proof.png exists in the package root, npm test will print:

  • OCR confidence
  • extracted OCR text
  • parser helper output

Important note ❤️

GPV helps a lot, but it should not be your only fraud defense.

For best results, always compare against your own server-side order data:

  • expected amount
  • expected reference
  • expected payment date
  • order ownership
  • payment status in your own database