Skip to content
EsureorgPublic

About

Open-source Stellar Testnet scenario runner and dashboard for validating XLM and issued-asset payment flows with structured, sanitized reports.

Topics

Resources

Code of conduct

Contributing

Security policy

Stars

5 stars

Watchers

0 watching

Forks

Repository files navigation

Esure

Monorepo CI License: MIT Stellar: Testnet

Test with confidence. Build on Stellar.

Esure is an open-source testing and simulation toolkit that helps developers validate Stellar payment flows before integrating them into production applications. It turns multi-step Testnet operations into repeatable scenarios with structured reports, transaction links, balance changes, and readable failure explanations.

Important

Esure is an MVP built exclusively for Stellar Testnet. It must not be used for Mainnet transactions or real-value assets.

Live services

Service URL
Web dashboard esure-testnet.vercel.app
Backend health esure.onrender.com/health
OpenAPI document esure.onrender.com/openapi.json

The Render free service may sleep after inactivity, so its first response can take longer than subsequent requests.

Capabilities

  • 13 Bundled Scenarios: XLM payments, issued assets, trustlines, expected failures, multi-op transactions (Testnet only)
  • Developer-Friendly Errors: Plain-English explanations for 30+ Stellar error codes with causes and fix suggestions
  • Command-Line Interface: Run scenarios from terminal or CI pipelines (run from source; not yet published to npm)
  • CI/CD Integration: First-class GitHub Actions, GitLab CI, and CircleCI support
  • Declarative Testing: Bounded JSON/YAML scenario definitions with schema validation
  • Isolated Execution: Fresh Testnet accounts per run, no cross-run contamination
  • Comprehensive Reports: Steps, assertions, transaction hashes, balance changes, and readable failures
  • Security by Design: Testnet-only, rejects secrets/Mainnet, ephemeral keys, sanitized outputs
  • Optional Persistence: PostgreSQL-backed scenario catalogue and version history

See the MVP specification for the complete product scope.

Why Esure

A realistic Stellar payment test spans account creation, Friendbot funding, trustline configuration, transaction submission, ledger confirmation, and balance verification. Rebuilding that flow manually makes failures difficult to reproduce and easy to misdiagnose. Esure packages the full process into versioned scenarios that can be executed repeatedly and inspected through one consistent report format.

Esure is useful for:

  • payment and remittance teams validating integration assumptions;
  • wallet developers testing asset and trustline behavior;
  • educators demonstrating common Stellar transaction flows;
  • contributors reproducing protocol-level failures safely on Testnet; and
  • CI workflows that need deterministic validation without storing secret keys.

How Esure differs

Unlike Stellar Lab, which requires manual step-through and copy/paste workflow, Esure executes multi-step flows declaratively and generates structured reports. Unlike the Stellar Quickstart Docker image, Esure focuses on scenario-driven testing rather than node operation. Unlike hand-written SDK tests, Esure provides repeatable scenario definitions with expected-failure assertions and CI-friendly JSON output.

Bundled scenarios

Esure includes 13 bundled scenarios for Testnet integration testing:

Scenario Purpose Expected result
xlm-payment Fund two accounts, transfer 5 XLM, verify balance change Pass
issued-asset-payment Create TESTUSD trustline, issue 100 TESTUSD, verify balance Pass
missing-trustline Attempt issued-asset payment without recipient trustline Controlled op_no_trust failure
insufficient-xlm-balance Attempt to send more XLM than available in account Controlled op_underfunded failure
unfunded-destination Pay a generated destination that has not been funded or created on the ledger Controlled tx_failed/op_no_destination failure
payment-with-memo Send XLM with a text memo and verify it on the confirmed transaction Pass
multi-operation-transaction Execute trustline + payment atomically in single tx Pass
trustline-limit-exceeded Attempt payment exceeding trustline limit Controlled op_line_full failure
trustline-limit-exact Pay exactly the fractional trustline limit and verify the final balance Pass
trustline-already-exists Multiple payments using existing trustline Pass
basic-payment-with-checks Send XLM and verify both accounts exist after transaction Pass
minimum-xlm-payment Send minimum viable XLM amount (1 stroop = 0.0000001 XLM) Pass

Each run generates fresh Testnet accounts, so repeated executions remain isolated from previous runs. See SCENARIOS.md for complete scenario documentation.

How a run works

  1. The dashboard requests the published scenario catalogue from the backend.
  2. The user selects a scenario and starts a run through the same-origin proxy.
  3. The backend validates the bounded scenario definition before generating any accounts or making network requests.
  4. The runner creates isolated accounts, obtains Testnet funds, and executes each declared operation in order.
  5. Assertions compare the observed transaction result or balance with the scenario expectation.
  6. The frontend polls the run endpoint and renders progress, transaction links, assertions, and sanitized failures.
  7. The final structured report is available from the report endpoint.

Architecture

Browser
   |
   v
Next.js dashboard and same-origin proxy
   |
   v
Fastify API and scenario runner
   |----------------------|
   v                      v
Stellar Testnet      PostgreSQL (optional)
Directory Responsibility
esure-frontend Next.js dashboard and browser-facing API proxy
esure-backend Fastify API, validation, reporting, and Testnet execution
esure-cli Command-line interface for terminal and CI usage
esure-docs Product, API, architecture, scenario, CI, and persistence documentation
esure-contracts Design space for post-MVP Soroban fixtures
.github CI, issue templates, contribution guidance, and security policy

For deeper technical context, read the architecture documentation.

Quick start

Prerequisites

  • Git
  • Node.js 20 or newer
  • npm
  • Network access to Stellar Testnet for live runs

1. Clone and install

git clone https://github.com/Esureorg/Esure.git
cd Esure

cd esure-backend
npm ci
cd ../esure-frontend
npm ci
cd ..

2. Configure the applications

macOS and Linux:

cp esure-backend/.env.example esure-backend/.env
cp esure-frontend/.env.example esure-frontend/.env.local

Windows PowerShell:

Copy-Item esure-backend/.env.example esure-backend/.env
Copy-Item esure-frontend/.env.example esure-frontend/.env.local

The frontend defaults to a backend at http://127.0.0.1:3001. To use another backend, set ESURE_BACKEND_URL in esure-frontend/.env.local.

3. Start the backend

In the first terminal:

cd esure-backend
npm run dev

Verify the API:

curl http://127.0.0.1:3001/health
curl http://127.0.0.1:3001/api/v1/scenarios

4. Start the frontend

In a second terminal:

cd esure-frontend
npm run dev

Open http://localhost:3000.

5. Run a scenario from the API

curl -X POST http://127.0.0.1:3001/api/v1/runs \
  -H "content-type: application/json" \
  -d '{"scenarioId":"issued-asset-payment","inputs":{}}'

The response contains a run ID. Use it to retrieve progress and the final report:

curl http://127.0.0.1:3001/api/v1/runs/RUN_ID
curl http://127.0.0.1:3001/api/v1/runs/RUN_ID/report

CLI usage

Note

The CLI is not yet published to npm. Run it from source as shown below.

Esure includes a command-line interface for terminal and CI pipeline usage:

# Clone and build the CLI (one time)
git clone https://github.com/Esureorg/Esure.git
cd Esure/esure-cli
npm ci
npm run build

# List bundled scenarios
node dist/cli.js list

# Filter and sort scenarios
node dist/cli.js list --search payment --sort id

# Show a bundled scenario definition
node dist/cli.js show xlm-payment

# Validate a scenario file
node dist/cli.js validate ./my-scenario.yaml

# Validate a scenario from standard input
cat ./my-scenario.json | node dist/cli.js validate --stdin --format json

# Validate a directory of scenario files
node dist/cli.js validate-directory ./scenarios

# Run a bundled scenario
node dist/cli.js run xlm-payment

# Run a custom scenario with JSON output
node dist/cli.js run ./my-scenario.yaml --output json

CI integration

Add Esure to your CI pipeline:

# .github/workflows/stellar-tests.yml
- name: Install Esure CLI
  run: |
    cd esure-cli
    npm ci
    npm run build
    
- name: Run Stellar tests
  run: |
    cd esure-cli
    node dist/cli.js run ./tests/payment-flow.yaml --output json

See CI_INTEGRATION.md for complete CI/CD integration guide with GitHub Actions, GitLab CI, and CircleCI examples.

API overview

Method Endpoint Purpose
GET /health Confirm the API process is available
GET /ready Confirm dependencies are ready
GET /api/v1/scenarios List available scenarios
POST /api/v1/scenarios/validate Validate a scenario definition
POST /api/v1/runs Start a bundled scenario
GET /api/v1/runs/:runId Read current run state
GET /api/v1/runs/:runId/report Download a structured report

The complete contract is available from the deployed OpenAPI document and the API documentation.

Configuration reference

Frontend

Variable Default Description
ESURE_BACKEND_URL http://127.0.0.1:3001 Server-only backend origin used by the Next.js proxy

Restart the local frontend or redeploy it after changing ESURE_BACKEND_URL.

Backend

The accepted integer bounds are inclusive. Backend settings are derived from loadConfig and take effect when the backend starts; restart it after changing them.

Variable Default Accepted value / bounds Effect and applicability
HOST 127.0.0.1 String; not validated Backend bind address. Use 0.0.0.0 where the host must accept external connections. All modes.
PORT 3001 Integer, 1-65535 Backend HTTP port. Render supplies this automatically. All modes.
LOG_LEVEL info String; not validated Currently read by loadConfig but not applied by the server; changing it has no logging effect.
STELLAR_HORIZON_URL https://horizon-testnet.stellar.org Valid HTTPS URL containing testnet Horizon endpoint. Mainnet URLs are rejected. All modes.
STELLAR_FRIENDBOT_URL https://friendbot.stellar.org Must be this exact HTTPS URL Friendbot endpoint. Other URLs are rejected. All modes.
RUN_TIMEOUT_MS 120000 Milliseconds; integer, 1000-600000 Maximum total duration of one run. All modes.
STEP_TIMEOUT_MS 30000 Milliseconds; integer, 500-120000 Maximum duration of one scenario step. All modes.
MAX_CONCURRENT_RUNS 2 Active runs; integer, 1-20 Maximum simultaneous executions; excess starts are rejected, not queued. All modes.
METRICS_ENABLED false Literal true or false Enables the process-local aggregate GET /metrics endpoint. Disabled by default; when enabled, restrict access to trusted monitoring systems on a private network or behind an authenticated/allowlisted reverse proxy. Metrics reset on restart and are per process.
MAX_STORED_RUNS 500 Runs; integer, 10-10000 In-memory run-store capacity only; ignored by the PostgreSQL run store.
RUN_RETENTION_MS 3600000 Milliseconds; integer, 60000-86400000 Retention for completed run reports in either run store. PostgreSQL reports past this age are hidden from reads but not deleted by this setting.
RATE_LIMIT_MAX 120 Requests per window; integer, 1-10000 Per-IP fixed-window limit for requests other than run creation. All modes.
RUN_RATE_LIMIT_MAX 10 Requests per window; integer, 1-1000 Per-IP fixed-window limit for run-creation endpoints. All modes.
RATE_LIMIT_WINDOW_MS 60000 Milliseconds; integer, 1000-3600000 Shared fixed-window duration for both rate limits. All modes.
BODY_LIMIT_BYTES 16384 Bytes; integer, 1024-1048576 Maximum request-body size. All modes.
SCENARIO_DIRECTORY Unset Directory path; not validated Optional directory of additional bounded JSON/YAML scenarios, loaded at startup. All modes.
PERSISTENCE_MODE disabled disabled or published published enables the PostgreSQL scenario catalogue and requires DATABASE_URL; startup fails if migrations are not current.
RUN_PERSISTENCE_ENABLED false Literal true or false true persists run reports in PostgreSQL and requires PERSISTENCE_MODE=published; otherwise reports use the in-memory store.
DATABASE_URL Unset PostgreSQL connection URL Application login used by the running backend; required in published mode. Do not use migration credentials here.
DATABASE_MIGRATION_URL Unset PostgreSQL connection URL Migration login used only by the explicit db:migrate and db:reconcile commands; not used by the running backend.
DATABASE_POOL_MAX 5 Connections; integer, 1-20 Maximum PostgreSQL pool size. Used only in published mode.
DATABASE_CONNECTION_TIMEOUT_MS 5000 Milliseconds; integer, 500-30000 PostgreSQL connection timeout. Used only in published mode.
DATABASE_QUERY_TIMEOUT_MS 5000 Milliseconds; integer, 100-30000 PostgreSQL statement and query timeout. Used only in published mode.
DATABASE_IDLE_TIMEOUT_MS 10000 Milliseconds; integer, 1000-60000 Time before an idle PostgreSQL pool connection is closed. Used only in published mode.

RUN_TIMEOUT_MS limits the whole run while STEP_TIMEOUT_MS limits each individual step; either timeout can end execution first. MAX_CONCURRENT_RUNS limits active executions, while MAX_STORED_RUNS separately limits only the in-memory report store. When that store is full it evicts a terminal report; it does not evict active runs. RUN_RETENTION_MS applies to completed reports in memory and PostgreSQL, but PostgreSQL rows remain stored. The two rate limits share RATE_LIMIT_WINDOW_MS and are process-local.

DATABASE_URL is for the application role only. Set DATABASE_MIGRATION_URL for the one-shot migration commands, using the separate migration role; it does not require a backend restart because those commands read it when invoked. Replace credential placeholders with local or provider-managed credentials and never commit them. See esure-backend/.env.example and the persistence guide for setup details.

Development and testing

Run the same deterministic checks used by CI:

cd esure-backend
npm run check
npm run build

cd ../esure-frontend
npm run check

Normal automated tests do not submit real transactions. The opt-in Testnet smoke test is documented in the backend README.

Persistence

The default PERSISTENCE_MODE=disabled configuration keeps runtime state in memory. Published scenario catalogue persistence can be enabled with PostgreSQL after applying the checked migrations and configuring the required database roles. See the persistence guide before enabling it.

Deployment

Component Platform Root directory
Frontend Vercel esure-frontend
Backend Render esure-backend
Database PostgreSQL provider Not applicable

Set ESURE_BACKEND_URL in Vercel to the public Render backend origin. Keep secrets and migration credentials in the hosting provider environment settings; never commit them to the repository.

Keeping the backend awake

The Render free tier sleeps after 15 minutes of inactivity. To keep the backend responsive, use a free uptime monitoring service (UptimeRobot, Cron-job.org, or similar) to ping /health every 10-14 minutes. This prevents cold starts for dashboard users. See the troubleshooting section for cold-start delay behavior.

Current MVP status

Capability Shipped in this checkout Planned / proposal
Testnet scenarios and reports Bounded scenario validation, classic Stellar execution, expected-failure reporting, and dashboard reports are shipped. Mainnet is rejected. Mainnet use is out of scope.
Published scenario catalogue Optional PostgreSQL catalogue with version history and migration checks; see the persistence implementation. No additional catalogue phase is recorded.
Run history Reports are in memory by default. RUN_PERSISTENCE_ENABLED=true with PERSISTENCE_MODE=published opts into PostgreSQL report storage; see the run stores. Durable run execution, worker leases, and recovery are planned in #21.
Primary browser journey Playwright covers scenario selection, run start, polling, and passed/failed reports in the journey test; the monorepo workflow runs it. No additional primary-journey work is recorded.
Soroban contract testing Not in the MVP execution path. Design examples are proposals in esure-contracts.

Active work is tracked in GitHub Issues.

Troubleshooting

The deployed dashboard takes a long time to load

The free Render backend can sleep after inactivity. Wait for the first request to wake the service, then retry. Check the health endpoint if the delay continues.

The frontend cannot reach the backend

Confirm that ESURE_BACKEND_URL contains the backend origin without a trailing API path, for example https://esure.onrender.com, and redeploy the frontend after changing a Vercel environment variable.

The backend fails readiness in published mode

Published mode fails closed when DATABASE_URL is missing or migrations are stale. Apply the role bootstrap, migrations, and fixture reconciliation from the persistence guide, or return to PERSISTENCE_MODE=disabled while developing without PostgreSQL.

A live Testnet run fails during funding

Friendbot and Horizon are external Testnet services and can be temporarily unavailable or rate limited. Inspect the sanitized run error, wait briefly, and retry with a new isolated run.

Security

Esure rejects secret seeds, raw XDR, scripts, arbitrary URLs, unresolved references, unknown scenario properties, and Mainnet configuration. Generated Testnet secrets remain only in process memory during execution and are excluded from API responses, logs, and reports.

Please report vulnerabilities according to the security policy. Do not disclose sensitive findings in a public issue.

Contributing

Contributions are welcome. Before opening a pull request:

  1. Read the contribution guide.
  2. Choose or open a focused GitHub issue.
  3. Keep changes within the documented Testnet-only safety boundary.
  4. Run the relevant checks locally.
  5. Link the pull request to its issue.

License

Esure is released under the MIT License.

About

Open-source Stellar Testnet scenario runner and dashboard for validating XLM and issued-asset payment flows with structured, sanitized reports.

Topics

Resources

Code of conduct

Contributing

Security policy

Stars

5 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages