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

stable-ci

v0.2.0

Published

Reliability CI for stablecoin payment integrations

Readme

stable-ci

Break your stablecoin integration before production.

stable-ci injects deterministic payment failures into stablecoin payment integrations and verifies that your application and ledger still converge to the expected financial state.

It is designed for CI: define your payment policy, run failure scenarios against your integration, and fail the build when money moves incorrectly.

What it catches

stable-ci currently tests:

  • Duplicate webhooks
  • Out-of-order webhooks
  • Missing webhooks
  • Provider timeout after broadcast
  • Late blockchain confirmation
  • Retry while settlement is unknown
  • Invalid webhook signatures
  • Underpayments
  • Overpayments
  • Late payments

It verifies outcomes such as:

  • exactly-once ledger posting
  • credited amount
  • final application state
  • retry behavior
  • webhook acceptance
  • recovery after missing events

Example

A broken overpayment handler:

FAIL  overpayment
      ledger_delta_equals_settlement_amount
      Expected USD 100.00, ledger credited USD 140.00.

Instead of only asking whether an API request succeeded, stable-ci checks whether the resulting financial state is correct.

Install

npm install --save-dev stable-ci

Or run it directly:

npx stable-ci --help

Quick start

Create stable-ci.yml:

provider: bvnk

webhookSecret: your-test-webhook-secret

target:
  name: payment-app
  baseUrl: http://127.0.0.1:4310
  endpoints:
    reset: /reset
    webhook: /webhook
    state: /state
    reconcile: /reconcile

payment:
  id: pay_test_001
  amount: 100
  asset: USDC

scenarios:
  - duplicate_webhook
  - out_of_order_webhook
  - missing_webhook
  - invalid_signature
  - underpayment
  - overpayment
  - late_payment

expectations:
  underpayment:
    applicationStatus: manual_review
    ledgerEntries: 0
    credit: none

  overpayment:
    applicationStatus: completed
    ledgerEntries: 1
    credit: exact_expected

  late_payment:
    applicationStatus: manual_review
    ledgerEntries: 0
    credit: none

Run:

npx stable-ci run --config stable-ci.yml

Example output:

Stablecoin Reliability CI
=========================
Adapter: payment-app [bvnk]

PASS  duplicate_webhook
PASS  out_of_order_webhook
PASS  missing_webhook
PASS  invalid_signature
PASS  underpayment
FAIL  overpayment
PASS  late_payment

6 passed, 1 failed

A failed scenario causes a non-zero exit code, so it can fail CI.

Working example

A complete external integration example is available here:

https://github.com/saldfsdk/stable-ci-example

The example repository installs stable-ci from npm, starts a test payment application, and runs saldfsdk/[email protected] as a GitHub Action from a separate repository.

Its CI verifies the full external integration path and produces a JUnit report.

Expected outcomes

Different applications may intentionally handle payment exceptions differently.

For example, an overpayment may credit only the requested amount:

expectations:
  overpayment:
    applicationStatus: completed
    ledgerEntries: 1
    credit: exact_expected

While another application may intentionally credit the entire received amount:

expectations:
  overpayment:
    applicationStatus: completed
    ledgerEntries: 1
    credit: received_amount

stable-ci tests against your declared financial policy instead of assuming that every integration has the same correct outcome.

GitHub Actions

This repository includes a composite GitHub Action.

steps:
  - uses: actions/checkout@v7

  - uses: saldfsdk/[email protected]
    with:
      config: stable-ci.yml
      junit: reports/stable-ci.xml

The action runs the configured scenarios and writes a JUnit report.

JUnit

You can generate a JUnit XML report directly:

npx stable-ci run \
  --config stable-ci.yml \
  --junit reports/stable-ci.xml

JUnit reports are written even when reliability scenarios fail.

JSON output

For machine-readable output:

npx stable-ci test --profile safe --json

Built-in scenarios

List all scenarios:

npx stable-ci scenarios

Current scenarios include:

  • duplicate_webhook
  • out_of_order_webhook
  • missing_webhook
  • provider_timeout_after_broadcast
  • late_chain_confirmation
  • retry_after_unknown_settlement
  • invalid_signature
  • underpayment
  • overpayment
  • late_payment

Custom webhook providers

stable-ci can test payment integrations that use providers without a built-in adapter.

Use JSON webhook fixtures to describe the provider payloads that your application already accepts.

Example stable-ci.yml:

provider: custom

webhookSecret: your-test-webhook-secret

customProvider:
  name: onswitch-like

  fixtures:
    pending: fixtures/pending.json
    completed: fixtures/completed.json
    underpaid: fixtures/underpaid.json
    expired: fixtures/expired.json

  signature:
    header: x-switch-signature
    algorithm: sha256
    encoding: base64

target:
  name: payment-app
  baseUrl: http://127.0.0.1:4310
  endpoints:
    reset: /reset
    webhook: /webhook
    state: /state
    reconcile: /reconcile

payment:
  id: pay_test_001
  amount: 100
  asset: USDC

scenarios:
  - duplicate_webhook
  - out_of_order_webhook
  - missing_webhook
  - invalid_signature
  - underpayment
  - overpayment
  - late_payment

A fixture can use placeholders:

{
  "id": "{{eventId}}",
  "paymentId": "{{paymentId}}",
  "status": "{{status}}",
  "amount": "{{amount}}",
  "actualAmount": "{{actualAmount}}",
  "asset": "{{asset}}",
  "eventType": "{{eventType}}"
}

Available placeholders:

  • {{eventId}}
  • {{paymentId}}
  • {{status}}
  • {{amount}}
  • {{actualAmount}}
  • {{asset}}
  • {{eventType}}

When a placeholder is the entire JSON string value, numbers remain numbers instead of being converted to strings.

Fixture paths are resolved relative to stable-ci.yml.

Custom headers may also contain placeholders:

customProvider:
  headers:
    x-payment-id: "{{paymentId}}"

For signed webhooks, stable-ci signs the final rendered raw JSON body. The signature header name is configurable, so providers using headers such as x-switch-signature can be tested without adding provider-specific code to stable-ci.

The target application still exposes the stable-ci test observer endpoints (reset, state, and optionally reconcile). These endpoints are intended for test and CI environments only.

Provider support

BVNK

The current BVNK adapter models payment webhook behavior including:

  • signed webhook delivery
  • statusChanged
  • transactionConfirmed
  • transactionLate
  • underpayments
  • overpayments
  • late payments

Provider payload fixtures are based on publicly documented behavior and are intended for reliability testing.

stable-ci is not affiliated with or endorsed by BVNK.

Generic

A generic provider adapter is also included for provider-independent testing.

Architecture

stable-ci.yml
     |
     v
Scenario Runner
     |
     v
Fault Injection
     |
     v
Provider / Webhook / Application
     |
     v
Observed State
     |
     v
Expected Outcome + Invariant Engine
     |
     +---- PASS
     |
     +---- FAIL
             |
             +-- CLI
             +-- JSON
             +-- JUnit

Why stable-ci?

Payment integrations can fail even when individual API calls appear successful.

Examples include:

  • the same webhook being delivered twice
  • lifecycle events arriving out of order
  • a payment being confirmed after an application timeout
  • retrying while settlement is still unknown
  • an invalid webhook being accepted
  • an underpayment being treated as fully paid
  • an overpayment being credited incorrectly
  • an expired payment being revived after late funds arrive

These are not only API correctness problems.

They are money movement correctness problems.

stable-ci is designed to test the final financial outcome, not only whether a request returned HTTP 200.

Current status

stable-ci is an early-stage developer tool.

The current version focuses on deterministic local and CI testing.

It does not yet provide full production blockchain observation or hosted monitoring.

Planned areas include:

  • additional provider adapters
  • richer CI reporting
  • blockchain/RPC observers
  • provider sandbox drift detection
  • hosted reliability testing

Development

Install dependencies:

npm install

Run all tests and build:

npm run check

Run the local safe demo:

npm run build
node dist/index.js test-http --profile safe

Expected result:

10 passed, 0 failed

Run the intentionally unsafe demo:

node dist/index.js test-http --profile unsafe

Expected result:

0 passed, 10 failed

The unsafe profile intentionally contains broken payment-handling behavior so that the reliability checks can demonstrate what they detect.

License

MIT