⚠️ IMPORTANT — Not for production useThe Sandbox module must only be enabled in
developmentandtestenvironments. Register it conditionally inapp.module.ts:// app.module.ts – guard sandbox behind environment check ...(process.env.NODE_ENV !== 'production' ? [SandboxModule] : []),
The Sandbox module provides a structured developer / training mode for the Nestera backend. It exposes HTTP endpoints that allow authorised administrators to:
- Generate configurable test data – users, wallets, transactions, and savings goals with customisable counts.
- Simulate Soroban contract events – inject synthetic
Deposit,Withdraw, orYieldevents without touching the real Stellar ledger. - Reset sandbox state – truncate sandbox tables back to a clean slate (requires a confirmation token to prevent accidental triggers).
- Manage sandbox API keys – create and list API keys used by automated test suites.
- Inspect usage analytics – review what endpoints have been called during a sandbox session.
All sandbox endpoints are protected by two layers of authentication and authorisation:
| Guard | Purpose |
|---|---|
JwtAuthGuard |
Validates the JWT bearer token sent in the Authorization header |
RolesGuard + @Roles(Role.ADMIN) |
Ensures the authenticated user holds the ADMIN role |
Any request that lacks a valid JWT or that belongs to a non-admin user will
receive a 401 Unauthorized or 403 Forbidden response respectively.
# Authenticate as an admin user
curl -X POST http://localhost:3001/auth/login \
-H "Content-Type: application/json" \
-d '{"email": "admin@example.com", "password": "yourpassword"}'Use the access_token value from the response as the bearer token for all
sandbox requests:
export TOKEN="<access_token>"/sandbox
Create a new sandbox API key.
Request body
{
"name": "my-ci-key",
"userId": "optional-uuid"
}Response 201 Created
{
"id": "uuid",
"key": "sb_xxxx-xxxx-xxxx",
"name": "my-ci-key",
"isActive": true,
"requestCount": 0,
"createdAt": "2026-06-30T00:00:00.000Z"
}List all sandbox API keys.
Response 200 OK — array of SandboxApiKey objects.
Generate configurable test data.
Request body (all fields optional)
{
"userCount": 5,
"transactionsPerUser": 5,
"savingsGoalsPerUser": 2
}| Field | Type | Default | Range | Description |
|---|---|---|---|---|
userCount |
integer | 5 |
1–50 | Number of test users to create |
transactionsPerUser |
integer | 5 |
1–20 | Transactions per user |
savingsGoalsPerUser |
integer | 2 |
1–10 | Savings goals per user |
Response 201 Created
{
"users": [...],
"transactions": [...],
"savingsGoals": [...],
"summary": {
"usersCreated": 5,
"transactionsCreated": 25,
"savingsGoalsCreated": 10,
"options": { "userCount": 5, "transactionsPerUser": 5, "savingsGoalsPerUser": 2 }
}
}Simulate a Soroban contract event.
Request body
{
"eventType": "Deposit",
"publicKey": "GABC...XYZ",
"amount": "250.00",
"ledger": 1234567,
"contractId": "CABC...DEF"
}| Field | Type | Required | Description |
|---|---|---|---|
eventType |
"Deposit" | "Withdraw" | "Yield" |
✅ | Type of contract event to simulate |
publicKey |
string | ✅ | Stellar public key (or wallet address) of the target user |
amount |
string | ✅ | Token amount as a string (preserves decimal precision) |
ledger |
integer | ❌ | Simulated ledger sequence (random if omitted) |
contractId |
string | ❌ | Simulated contract ID (random if omitted) |
Response 200 OK
{
"simulated": true,
"eventType": "Deposit",
"eventId": "sandbox:deposit:uuid",
"ledgerSequence": 1234567,
"contractId": "CABC...DEF",
"publicKey": "GABC...XYZ",
"amount": "250.00",
"message": "Deposit event simulation completed for sandbox. Use the eventId to look up downstream processing results."
}Reset all sandbox data.
⚠️ Destructive operation. This truncates thesandbox_api_keysandsandbox_usage_analyticstables. A confirmation token is required.
Request body
{
"confirm": "CONFIRM_RESET"
}Omitting the confirmation token or providing any other value returns 400 Bad Request.
Response 200 OK
{
"message": "Sandbox data reset successfully"
}Retrieve sandbox usage analytics (recent calls first).
Response 200 OK — array of SandboxUsageAnalytics objects.
[
{
"id": "uuid",
"apiKeyId": "sandbox-simulate",
"endpoint": "/sandbox/simulate-event",
"method": "POST",
"statusCode": 200,
"responseTimeMs": 0,
"userAgent": "SandboxSimulator/Deposit",
"createdAt": "2026-06-30T00:00:00.000Z"
}
]All examples use $TOKEN set from the login step above.
# Generate 3 users with 10 transactions each
curl -X POST http://localhost:3001/sandbox/test-data \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"userCount": 3, "transactionsPerUser": 10, "savingsGoalsPerUser": 2}'
# Simulate a Deposit event
curl -X POST http://localhost:3001/sandbox/simulate-event \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"eventType": "Deposit",
"publicKey": "GABC123XYZ",
"amount": "500.00",
"ledger": 9999999
}'
# Simulate a Withdraw event
curl -X POST http://localhost:3001/sandbox/simulate-event \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"eventType": "Withdraw", "publicKey": "GABC123XYZ", "amount": "100.00"}'
# Reset the sandbox (requires confirmation)
curl -X POST http://localhost:3001/sandbox/reset \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"confirm": "CONFIRM_RESET"}'
# List usage analytics
curl http://localhost:3001/sandbox/usage-analytics \
-H "Authorization: Bearer $TOKEN"- Isolation: The sandbox module uses its own database tables
(
sandbox_api_keys,sandbox_usage_analytics). It does NOT write to production-domain tables during simulation; thesimulateContractEventendpoint returns a description of what the blockchain event handlers would do, enabling integration testing without side effects. - Guards:
JwtAuthGuard+RolesGuard(ADMIN)are applied at the controller class level so every route inherits the same access policy. - Structured logging: All sandbox operations emit structured log entries compatible with the project-wide pino logger, making it easy to correlate sandbox activity with other backend logs.
- Closing issues: This module resolves GitHub issue #1066 — Add Structured Training/Developer Mode Endpoints (Sandbox).