Skip to content
SavituraPublic

About

No description, website, or topics provided.

Resources

Code of conduct

Contributing

Security policy

Stars

0 stars

Watchers

0 watching

Forks

Latest commit

 

History

500 Commits

Folders and files

Repository files navigation

SaviTools

License: MIT PRs Welcome

Fluxa's Developer Console & Workstation for building on Stellar.

SaviTools is the official developer console in the Savitura ecosystem, purpose-built for Fluxa payment infrastructure. It provides interactive API playgrounds, webhook testing, SDK generation, and SEP debugging against hosted sandboxes — without needing a terminal, Rust toolchain, or deep protocol knowledge.

Live Deployment (Testnet Only): https://savitools.savitura.com
Live API: https://savitools-api.savitura.com
Status: Public testnet preview. Mainnet signing is strictly locked out across all tools (Composer, Wallet Sandbox, and API).


Strategic Focus: Fluxa Developer Console

To avoid surface-area duplication with the official, free Stellar Lab, SaviTools focuses strictly on serving as Fluxa's Developer Console. Core focus is placed on SEP-10/24 debugging, webhook testing, API playground, and SDK generation against the hosted Fluxa sandbox. Generic protocol tools that overlap with Stellar Lab are frozen. Feature requests expanding Lab overlap (e.g. #75) are closed / labelled wontfix/stellar-lab-overlap.

Tools

Fluxa Developer Console & Core Workstations

Tool What it does Status
API Playground Interactive request builder for Fluxa (mock/sandbox) and CrowdPay (Railway) APIs Active (Core)
Webhook Tester Fire sample CrowdPay / Fluxa webhook payloads at your endpoint; inspect the response Active (Core)
SDK Generator Generate copy-paste client code (JS, Python, Go, cURL) from Fluxa/CrowdPay endpoints Active (Core)
Federation & TOML Resolve federation addresses, inspect stellar.toml files, check SEP compliance (SEP-10/24) Active (Core)
Wallet Sandbox Generate testnet keypairs, fund via Friendbot, send test payments (testnet-locked) Active
Payment Simulator Find path payment routes between assets; preview hops, rates, and fees Active
Ledger Monitor Watch a Stellar address or contract for live activity; set threshold alerts Active
Network Status Live Stellar network health: ledger close time, fee tracker, Horizon latency Active
Liquidity Pool Explorer Search Stellar AMM pools, calculate LP share values, and track favorite pools Active
Asset Control Inspect issuer authorization flags, audit trustlines, assemble clawback/flag txs Active
Slippage Lab Price slippage tolerances against adverse rate moves in path payments Active
Multisig Simulator Check threshold clearance and identify outstanding signers Active
Soroban RPC Schema-aware read-only Soroban JSON-RPC method invocation and response viewer Active
QR Handoff Move unsigned/signed transactions across air gaps via animated checksummed QR frames Active
Soroban Storage Inspect contract storage entries across Instance, Persistent, and Temporary storage Active
Sequence Planner Plan fee bumps and sequence numbers for queued Stellar transactions Active

Frozen Tools (Stellar Lab Overlap)

The following tools duplicate capabilities provided natively by official Stellar Lab. They remain functional in testnet MVP but are frozen to prioritize Fluxa and CrowdPay:

Tool What it does Status Alternative
Transaction Inspector Decode any tx hash, Stellar address, or raw XDR Frozen (MVP) Stellar Lab View XDR
Transaction Composer Visual builder for multi-operation Stellar transactions Frozen (MVP, Testnet-only) Stellar Lab Build Tx
Contract Deployer Upload and deploy Soroban WASM files to testnet Frozen (MVP) Stellar CLI / Lab
Order Book Live DEX order book and spread analytics Frozen (MVP) Stellar.expert / Lab
Account Graph Visualize signer networks, offers, and payment relationships Frozen (MVP) Stellar.expert
Contract Events Decode, filter, and replay Soroban contract events from ScVal XDR Frozen (MVP) Stellar RPC / Lab

See the Contract Events guide for filter criteria, limits, and API usage.


Architecture

Browser ──────────────────────────────────────────────────────────────────
  Next.js 15 (App Router) │ TypeScript │ Tailwind CSS │ shadcn/ui
──────────────────────────────────────────────────────────────────────────
                           │ HTTP
                           ▼
API ──────────────────────────────────────────────────────────────────────
  NestJS (Fastify adapter) │ TypeORM │ BullMQ │ Swagger at /api/docs
  ┌─────────────────────────────────────────────────────────────────┐
  │ modules: transaction · wallet · simulator · webhook · monitor   │
  │          playground · contracts · sdkgen · network · federation │
  │          metrics · sandbox · workspace · stellar · auth         │
  └─────────────────────────────────────────────────────────────────┘
          │                    │                    │
          ▼                    ▼                    ▼
    PostgreSQL              Redis             Stellar Horizon
    (workspaces,        (BullMQ queues,       (testnet +
    watches, history)    rate cache)           mainnet)

Monorepo layout (Turborepo)

savitools/
├── apps/
│   ├── web/                      # Next.js 15 frontend
│   │   └── src/app/
│   │       ├── page.tsx          # Home / onboarding
│   │       ├── inspector/        # Transaction Inspector & Account Graph
│   │       ├── sandbox/          # Wallet Sandbox & Asset Control
│   │       ├── composer/         # Transaction Composer
│   │       ├── simulator/        # Payment Simulator, Order Book & Slippage Lab
│   │       ├── webhooks/         # Webhook Tester
│   │       ├── monitor/          # Ledger Monitor
│   │       ├── playground/       # API Playground
│   │       ├── contracts/        # Soroban Deploy Helper & Contract Events
│   │       ├── sdk/              # SDK Generator
│   │       ├── network/          # Network Status
│   │       ├── multisig/         # Multisig Simulator
│   │       ├── rpc/              # Soroban RPC Runner
│   │       ├── qr-handoff/       # Air-gapped QR transaction handoff
│   │       ├── liquidity-pools/  # Liquidity Pool Explorer
│   │       └── [locale]/         # Localized routes (i18n)
│   │           ├── soroban-storage/  # Soroban Storage Explorer
│   │           ├── sep10/            # SEP-10 WebAuth Helper
│   │           ├── sequence-planner/ # Sequence Bump Planner
│   │           └── stellar-toml/     # Stellar TOML Inspector
│   │
│   └── api/                      # NestJS backend
│       └── src/modules/
│           ├── transaction/       # Horizon lookups, XDR decode
│           ├── wallet/            # Keypair gen, Friendbot, balances
│           ├── simulator/         # Path payment route simulation
│           ├── webhook/           # Test endpoint registration + firing
│           ├── monitor/           # Horizon SSE streaming, alert rules
│           ├── playground/        # Spec proxy, API forwarding
│           ├── contracts/         # Soroban WASM upload + deploy
│           ├── sdkgen/            # Client code generation
│           ├── network/           # Fee stats, ledger health
│           ├── federation/        # TOML and address resolution
│           ├── metrics/           # Prometheus metrics export
│           ├── sandbox/           # Wallet sandbox and Friendbot
│           ├── workspace/         # Multi-tenant workspace mgmt
│           ├── stellar/           # Stellar network / RPC helpers
│           └── auth/              # User accounts, JWT, Fluxa SSO
│
├── src/                          # Standalone SEP-10 & SEP-24 Debugger library
│   ├── debugger/
│   │   ├── SEP10Debugger.ts      # SEP-10 WebAuth challenge/response authentication
│   │   └── SEP24Debugger.ts      # SEP-24 interactive deposit/withdrawal workflow runner
│   ├── util/                     # URL validation, TOML resolution, redactor
│   └── index.ts                  # Library entrypoint exports
│
├── tests/                        # Tests for root debugger library (SEP24Debugger.test.ts)
├── docker-compose.yml
├── turbo.json
└── .env.example

SEP-10 & SEP-24 Debugger Library (src/)

Located at the repository root in src/, this standalone TypeScript library provides protocol-level debugging and automation for Stellar anchors implementing SEP-10 (Stellar Web Authentication) and SEP-24 (Interactive Deposit & Withdrawal):

  • SEP10Debugger (src/debugger/SEP10Debugger.ts):

    • Handles the SEP-10 challenge-response authentication handshake.
    • Fetches the challenge transaction from the anchor's web auth endpoint.
    • Cryptographically verifies and signs the transaction with client keypairs.
    • Submits the signed transaction to exchange for a JWT token, managing token caching and expiration.
  • SEP24Debugger (src/debugger/SEP24Debugger.ts):

    • Resolves stellar.toml to automatically discover TRANSFER_SERVER_SEP0024 and WEB_AUTH_ENDPOINT.
    • Executes authenticated SEP-10 authentication to obtain authorization.
    • Initiates interactive deposit or withdrawal flows (/transactions/deposit/interactive or /transactions/withdraw/interactive).
    • Polls transaction status and generates a comprehensive, redacted diagnostic timeline of every request and response.

Usage Example

import { SEP10Debugger, SEP24Debugger } from './src';

// 1. Initialize SEP-10 authenticator
const sep10 = new SEP10Debugger({
  anchorDomain: 'testanchor.stellar.org',
  testnet: true,
});

// 2. Initialize SEP-24 workflow runner
const sep24 = new SEP24Debugger(
  {
    anchorDomain: 'testanchor.stellar.org',
    asset: 'USDC',
    flowType: 'deposit',
    testnet: true,
    timeout: 60000,
  },
  sep10
);

// 3. Run interactive flow and retrieve diagnostic timeline
const result = await sep24.startFlow();
console.log('Interactive URL:', result.interactiveUrl);
console.log('Transaction ID:', result.transactionId);
console.log('Diagnostic Timeline:', result.timeline);
console.log('Final Status:', result.finalStatus);

Getting Started

Prerequisites

  • Node.js 20+
  • Docker (for local Postgres + Redis)

1. Install dependencies

git clone https://github.com/Savitura/Savitools
cd Savitools
npm install

2. Configure environment

Two templates, two scopes - create both:

cp .env.example .env                    # root: infrastructure + compose ports
cp apps/api/.env.example apps/api/.env  # API runtime variables

The compose files interpolate the root .env (Compose loads it automatically); the per-app files are read by each app at runtime. The full-stack compose file treats the per-app files as optional overrides, so the stack still boots when they are missing.

Variable Description Default / Example
DATABASE_URL PostgreSQL connection string postgresql://postgres:password@localhost:5432/savitools
REDIS_URL Redis connection string redis://localhost:6379
STELLAR_NETWORK Stellar network (testnet or futurenet; the API refuses to start on mainnet/public) testnet
STELLAR_HORIZON_URL Horizon API URL https://horizon-testnet.stellar.org
STELLAR_RPC_URL Soroban RPC URL https://soroban-rpc-testnet.stellar.org
STELLAR_NETWORK_PASSPHRASE Passphrase matching the network (optional — falls back to the well-known passphrase) "Test SDF Network ; September 2015"
JWT_SECRET JWT signing secret (required; ≥32 chars in production) Generate with openssl rand -hex 32
ENCRYPTION_SECRET Master secret for per-user key derivation (required in production) Generate with openssl rand -base64 48
DEPLOYER_SECRET_KEY Stellar secret key required to boot — ContractsService reads it with getOrThrow and parses it with Keypair.fromSecret during construction; a throwaway testnet key is enough (Required)
RESEND_FROM_EMAIL From address for all transactional email SaviTools <noreply@savitools.dev>
WEB_ORIGIN Allowed origin for API and WebSocket CORS http://localhost:3000
THROTTLE_TTL Rate limiting sliding window size in milliseconds 60000 (1 minute)
THROTTLE_LIMIT Max requests allowed in the rate limit window 100
CONTRACT_ADMIN_EMAILS Comma-separated emails allowed to deploy/invoke contracts (empty denies everyone) (empty)
CONTRACT_DAILY_DEPLOY_QUOTA Contract deploys each user may make per UTC day 10
CONTRACT_DAILY_INVOKE_QUOTA Contract invocations each user may make per UTC day 100
NEXT_PUBLIC_API_URL Frontend → API URL http://localhost:3001/api

DEPLOYER_SECRET_KEY is required to boot the API. ContractsService reads it with getOrThrow and parses it with Keypair.fromSecret while the module is being constructed, so the API cannot start without a syntactically valid Stellar secret key (56 characters, starting with S). A throwaway, unfunded testnet key is enough to start the stack - funding it is only necessary if you actually deploy a contract. Generate one after npm install:

node -p "require('@stellar/stellar-sdk').Keypair.random().secret()"

The deployer account is shared. Every contract deploy, wizard deploy and invoke made through the API is signed by, and paid for from, this one DEPLOYER_SECRET_KEY account — no matter which user made the request. Access is limited to the CONTRACT_ADMIN_EMAILS allowlist, and each allowlisted user has a daily quota (CONTRACT_DAILY_DEPLOY_QUOTA, CONTRACT_DAILY_INVOKE_QUOTA, counted per UTC day in Redis) so one user cannot drain the account. Because the key is shared, the contracts module is testnet/futurenet only: the API refuses to start when STELLAR_NETWORK is mainnet/public or STELLAR_NETWORK_PASSPHRASE is the public network passphrase. Never put a key that holds real XLM here.

The full list of runtime-read variables lives in apps/api/.env.example. On startup, apps/api/src/config/env-validation.ts validates the configuration and fails fast with an aggregated error listing every problem: missing required URLs, non-HTTPS public URLs in production, placeholder auth or encryption secrets, and feature variables (e.g. RESEND_API_KEY without RESEND_FROM_EMAIL) that an enabled feature needs.

Security & Rate Limiting

SaviTools protects its REST APIs and WebSocket connections by restricting allowed origins and rate limiting requests:

  • CORS Protection: The WebSocket gateway and HTTP endpoints restrict incoming connections using WEB_ORIGIN (defaulting to http://localhost:3000). Make sure this is set to your frontend origin in staging/production deployments.
  • Rate Limiting: SaviTools implements global rate limiting using @nestjs/throttler. By default, it allows a maximum of 100 requests within a 60000 ms (1 minute) sliding window per IP address. When exceeded, the API returns a 429 Too Many Requests response.
    • Rate limits can be configured in your environment using THROTTLE_LIMIT (number of requests) and THROTTLE_TTL (time-to-live window in milliseconds).

Webhook Signature Verification

Every outbound delivery — the Webhook Tester, contract-event replay, and monitor alerts — uses one signing contract, so a single receiver implementation verifies all of them. Each delivery is signed whenever a signing secret is in play: the per-request secret if you send one, otherwise WEBHOOK_SIGNING_SECRET. Check what your deployment emits:

curl http://localhost:3001/api/webhooks/signing
# => {"enabled":true,"algorithm":"hmac-sha256","signatureHeader":"X-SaviTools-Signature",
#     "timestampHeader":"X-SaviTools-Timestamp","replayWindowSeconds":300,
#     "signedPayloadFormat":"<timestamp>.<body>","signatureFormat":"sha256=<hex>",
#     "signedPayloadEncoding":"utf-8","maxSkewSeconds":60,
#     "perRequestSecretSupported":true}

Every signed request carries two headers, and nothing else:

  • X-SaviTools-Timestamp: the Unix time in seconds when the request was built
  • X-SaviTools-Signature: sha256=<hex>, where the hex is HMAC-SHA256 of the UTF-8 bytes of <timestamp>.<body> — the exact request body as sent
# Reference verification, straight from the wire.
printf '%s.%s' "$X_SAVITOOLS_TIMESTAMP" "$BODY_BYTES" \
  | openssl dgst -sha256 -hmac "$WEBHOOK_SECRET"
# compare to the X-SaviTools-Signature value, in constant time

To verify a signature, recompute the HMAC with your secret over the timestamp and body you received, compare it in constant time, and reject requests whose timestamp is older than replayWindowSeconds (300 s) or more than maxSkewSeconds (60 s) in the future. The API exposes this exact logic as a testable utility: apps/api/src/modules/webhook/signature.ts (signBody / verifySignature). A request whose timestamp is older than the replay window should be rejected as a potential replay.

If signing is not enabled (enabled: false), webhook payloads are sent unsigned — set WEBHOOK_SIGNING_SECRET before pointing receivers at your deployment. Monitor alerts always sign with the per-webhook secret stored for that monitor, never the env var.

Migrating from the legacy body-only signature

Earlier builds signed the Webhook Tester's body alone and labelled the result X-Webhook-Signature, alongside an ISO-8601 X-Timestamp. That format has no timestamp inside the MAC, so a captured request could be replayed verbatim, and it does not verify against the contract above. If you still receive either legacy header:

  • Receivers must implement the timestamped pair. To keep accepting old deliveries during a rollout, try the timestamped verification first and fall back to the body-only HMAC only when X-SaviTools-Timestamp is absent — then stop, since a request carrying a timestamp but failing the timestamped check is a forgery, not a legacy delivery.
  • Senders do not need to do anything: all three paths emit the new pair, and the old headers are no longer produced. Replaying a delivery recorded under the old format strips the stale headers and re-signs it under the current contract, and the Webhook Tester marks those history entries legacy so it is clear the replay no longer matches the original.

3. Start infrastructure

docker compose up -d     # Postgres + Redis (docker-compose.yml)

Postgres and Redis are published on loopback only (127.0.0.1); change POSTGRES_PORT / REDIS_PORT in the root .env if either port is taken.

Compose files & Hosting options

  • docker-compose.yml - Postgres + Redis only for local host development. Start with docker compose up -d or make infra.
  • docker-compose.dev.yml - Full local dev stack in Docker (make dev).
  • docker-compose.prod.yml - Production stack locked to testnet (docker compose -f docker-compose.prod.yml up -d).
  • render.yaml - Declarative blueprint for one-click deployment on Render (or compatible cloud platforms) running apps/web/Dockerfile and apps/api/Dockerfile with managed PostgreSQL and Redis.
make dev                                            # full stack in Docker
docker compose -f docker-compose.dev.yml config -q   # validate without starting
docker compose -f docker-compose.prod.yml config -q  # validate production config

It caches node_modules in named volumes, parameterises every published port, and starts web only once api reports healthy, so the first request no longer races the API's boot.

4. Run development servers

npm run dev
Service URL
Frontend http://localhost:3000
API http://localhost:3001/api
Swagger docs http://localhost:3001/api/docs

5. Run individual apps

cd apps/web && npm run dev    # frontend only
cd apps/api && npm run dev    # API only

Development Commands

npm run dev        # start all apps in watch mode (Turborepo)
npm run build      # production build
npm run lint       # ESLint across all apps
npm run format     # Prettier
npm test           # run all tests
make seed          # seed network_samples, sandbox wallets, and webhook config (requires make dev)

How it connects to Savitura

SaviTools is a standalone product with its own users and branding, but it's purpose-built to serve the Savitura ecosystem:

  • The API Playground is pre-wired to Fluxa and CrowdPay APIs
  • The Webhook Tester ships sample payloads for every CrowdPay and Fluxa event
  • The Contract Deploy Helper makes it easy to deploy the CrowdPay Soroban escrow contract
  • Connect your Fluxa account in settings to use your real API keys inside SaviTools tools

Other Savitura projects:

  • Fluxa — payment infrastructure API
  • CrowdPay — crowdfunding platform

Documentation

Complete guides and API reference for integrating with SaviTools:

Resource Purpose
API Reference Complete endpoint catalog with examples, parameters, and error codes
Quickstart Guide End-to-end walkthrough: generate keypair → fund → send payment in 5 minutes
Ledger Monitor Load Test Recorded result from the one-hour, 50-connection SSE load test
Swagger UI Interactive API explorer (available in dev/staging; disabled in production)

Quick Links


Contributing

See CONTRIBUTING.md.

License

MIT

Observability

The API includes a Prometheus-compatible GET /metrics endpoint with HTTP, Soroban RPC, contract invocation, Horizon, Redis, and Node.js runtime metrics. See API metrics for access control, Prometheus scrape configuration, and the Grafana dashboard import template.

About

No description, website, or topics provided.

Resources

Code of conduct

Contributing

Security policy

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages