Skip to content

Merge conflict scenario - #167

Closed
Danielobito009 wants to merge 170 commits into
SwiftChainn:mainfrom
Danielobito009:merge-conflict-scenario
Closed

Merge conflict scenario#167
Danielobito009 wants to merge 170 commits into
SwiftChainn:mainfrom
Danielobito009:merge-conflict-scenario

Conversation

@Danielobito009

@Danielobito009 Danielobito009 commented Aug 29, 2026

Copy link
Copy Markdown
Contributor

Merge: Multi-Feature Integration Branch

Overview

Consolidated merge of four feature branches into a single integration branch containing comprehensive test suites and feature implementations for the escrow lifecycle, delivery QR code verification, event indexing, and real-time socket location tracking.
Closes #20 (QR code delivery verification)
Closes #39 (Escrow event indexer handlers)
Closes #110 (E2E escrow lifecycle tests)
Closes #111 (Socket.io location event tests)

Merged Branches

1. Issue #110: E2E Escrow Lifecycle Tests

Branch: test/e2e-escrow-lifecycle

Complete end-to-end test suite for escrow workflow with 40+ test cases covering:

  • Step-by-step escrow creation, funding, and release
  • Query operations by delivery/contract ID
  • Error scenarios (400, 401, 404, 409 responses)
  • Idempotency verification with Idempotency-Key header
  • Real MongoDB (MongoMemoryServer) with Soroban mocks

Files Added:

  • tests/e2e/escrow.test.ts (673 lines)
  • tests/e2e/helpers/db.ts (47 lines)
  • tests/e2e/helpers/auth.ts (75 lines)
  • tests/e2e/helpers/soroban.mock.ts (97 lines)

2. Issue #20: QR Code Delivery Verification

Branch: feat/delivery-qrcode-verification

New QR code endpoint for secure delivery handoff verification with:

  • Secure token generation (256-bit entropy via crypto.randomBytes)
  • Token scoped to ASSIGNED/IN_PROGRESS status with 24h expiry
  • Base64-encoded PNG QR code containing deliveryId + token
  • Full OpenAPI documentation
  • 40+ test cases with comprehensive error coverage
  • Strict Controller→Service→Model layering

Features:

  • GET /api/v1/deliveries/:id/qrcode endpoint
  • MongoDB persistence for token verification
  • TypeScript strict mode compliance

Files Added/Modified:

  • src/controllers/delivery.controller.ts (+33 lines)
  • src/models/Delivery.ts (+11 lines)
  • src/routes/delivery.routes.ts (+83 lines)
  • src/services/delivery.service.ts (+81 lines)
  • tests/delivery.qrcode.test.ts (473 lines)
  • GITHUB_ISSUE_20_DESIGN.md (752 lines - design documentation)
  • package.json (+2 dependencies)

3. Issue #39: Escrow Event Indexer Handlers

Branch: feat/indexer-escrow-resolved

Implement indexer handlers for escrow_released and escrow_refunded events with:

  • Event parsing and validation (parseEscrowReleasedEvent, parseEscrowRefundedEvent)
  • Event handlers with batch processing (handleEscrowReleasedEvent, handleEscrowRefundedEvent)
  • Distributed Redis locking for race condition prevention
  • Idempotent operations via transaction hash tracking
  • State machine enforcement: LOCKED → RELEASED/REFUNDED (terminal states)
  • Full audit trail in transactions array

Features:

  • refundEscrow() service method with distributed locking
  • RefundEscrowInput interface for refund operations
  • Status updates with proper timestamps
  • Related delivery status synchronization (COMPLETED/CANCELLED)
  • Comprehensive error handling with AppError
  • Debug/info/warn/error logging throughout

Files Added/Modified:

  • src/indexer/escrowHandlers.ts (+286 lines, 1 modified)
  • src/services/escrow.service.ts (+121 lines)
  • tests/integration/escrowHandlers.test.ts (589 lines)

Test Coverage: 30+ integration tests with MongoMemoryServer, idempotency verification, state machine transitions, and edge case handling.


4. Issue #111: Socket.io Location Event E2E Tests

Branch: test/socket-location-events

Comprehensive E2E integration tests for real-time driver location tracking with 35 tests across 9 suites:

Test Suites:

  1. Socket Connection (4 tests)
  2. Delivery Room Joining (3 tests)
  3. Location Update Events (6 tests)
  4. Deduplication & Race Conditions (3 tests)
  5. Payload Validation (12 tests)
  6. Authentication (2 tests)
  7. Offline Sync (1 test)
  8. Multiple Deliveries (1 test)
  9. Concurrent Operations (2 tests)

Coverage:

  • Real MongoDB integration (MongoMemoryServer)
  • Real socket.io-client WebSocket connections
  • Full TypeScript typing (zero 'any' types)
  • Event payload validation
  • Connection/room isolation
  • Error handling and edge cases
  • 60s timeouts for MongoDB, 10s for socket operations

Files Added:

  • tests/integration/socketLocation.test.ts (983 lines)
  • tests/integration/SOCKETLOCATION_IMPLEMENTATION.md (522 lines)
  • tests/integration/SOCKETLOCATION_REFERENCE.md (501 lines)
  • tests/integration/SOCKETLOCATION_TESTS.md (427 lines)
  • FINAL_VERIFICATION_REPORT.md (607 lines)
  • READY_TO_PUSH.txt (267 lines)
  • package.json (+2 dependencies)

Summary Statistics

  • Total Files Changed: 20
  • Total Lines Added: 6,631+
  • Test Coverage: 100+ new test cases
  • Merge Status: All merges completed cleanly without conflicts
  • Architecture: Verified Controller→Service→Model layering in all changes

Testing Recommendations

Before merging to main:

# Run all tests
npm run test

# Run E2E tests
npm run test tests/e2e/escrow.test.ts --runInBand

# Run integration tests
npm run test tests/integration/

# Lint verification
npm run lint
Merge Conflicts
None detected. All branches modified distinct file paths with auto-merge resolution for package.json dependencies.

Related Issues
Closes #20 (QR code delivery verification)
Closes #39 (Escrow event indexer handlers)
Closes #110 (E2E escrow lifecycle tests)
Closes #111 (Socket.io location event tests)

Add a dedicated security configuration module that restricts cross-origin
requests to an allow-list of frontend origins and applies production-grade
HTTP security headers via Helmet.

- Parse allowed origins from the comma-separated CORS_ORIGIN env variable
- Reject disallowed origins with a 403 via a typed CorsNotAllowedError
- Permit credentialed and preflight (OPTIONS) requests for allowed origins
- Configure Helmet with a strict CSP, HSTS, and referrer policy
- Apply both middlewares globally across all API routes
- Document multi-origin CORS configuration in .env.example
- Add unit tests covering header hardening and CORS allow/deny behaviour

Closes SwiftChainn#7
Add a POST /api/v1/auth/register endpoint following the Controller ->
Service -> Model architecture. Passwords are securely hashed with bcrypt
and the hash is never returned to clients.

- User model with schema validation, a unique email index, a bcrypt
  pre-save hook, a comparePassword method, and a toJSON transform that
  strips the password hash and exposes id instead of _id
- authService.registerUser handles duplicate-email detection (including
  the unique-index race condition) and returns sanitized user data
- authController.register validates input and returns 201 with the user
- authValidator performs strict, typed validation of the request body
- ApiError and asyncHandler utilities for consistent error handling
- Wire auth routes under /api/v1/auth
- Integration tests covering success, duplicate email, and validation

Closes SwiftChainn#9
- Add Delivery Mongoose schema with sender, recipient, status, and tracking fields
- POST /api/v1/deliveries — stores off-chain delivery metadata with auto-generated trackingId
- GET /api/v1/deliveries — paginated list with status filter and date sort
- GET /api/v1/deliveries/:id — fetch single delivery, returns 404 if not found
- PUT /api/v1/deliveries/:id/assign — assigns a driver to a pending delivery

Closes SwiftChainn#15, Closes SwiftChainn#16, Closes SwiftChainn#17, Closes SwiftChainn#18
…cation middleware

- Set up Socket.io server infrastructure integrated with Express HTTP server in `server.ts`
- Implement robust connection/disconnection event logging
- Create `socketAuth.ts` middleware to intercept handshakes and verify JWTs
- Reject unauthorized socket connections with strict error handling and strong TypeScript typings

Closes SwiftChainn#23
Closes SwiftChainn#24
…up (SwiftChainn#26)

- Add socket.io@4.7.2 to dependencies
- Create src/sockets/socket.types.ts: strongly-typed interfaces for
  connection metadata, ping/pong payloads, server/client events, and
  HealthCheckResult
- Create src/sockets/socket.service.ts: SocketService class (business
  logic layer) with:
  * Connection registration and in-memory tracking
  * Ping/pong health-check loop with configurable interval and
    max-missed-pong threshold (env: SOCKET_PING_INTERVAL_MS,
    SOCKET_MAX_MISSED_PONGS)
  * Stale connection eviction after exceeding missed-pong threshold
  * Room join/leave tracking for clean state on disconnect
  * Full Winston logging for connect, pong, disconnect, and eviction events
- Create src/sockets/connectionHandler.ts: controller layer that
  initialises the typed Socket.IO server, registers per-socket event
  handlers, and exposes initializeSocketServer / shutdownSocketServer
- Update src/server.ts: wrap Express in http.Server, attach Socket.IO,
  include Socket.IO in graceful shutdown sequence
- Add tests/socket.service.test.ts: 22 unit tests covering all service
  methods including health-check tick eviction logic

Closes SwiftChainn#26
…tChainn#27)

Model layer:
- Add src/models/LocationUpdate.ts: Mongoose schema with driverId,
  deliveryId, coordinates (lat/lng), capturedAt, isOfflineSync flag,
  status (pending|processed|failed), and compound indexes for efficient
  per-driver chronological queries

Service layer:
- Add src/sockets/sync.service.ts: SyncService class with processBatch()
  * Validates each OfflineLocationPoint (capturedAt, lat/lng bounds,
    deliveryId ObjectId format)
  * Detects duplicates against DB (driverId + capturedAt) and within
    the same batch using a Set
  * Bulk-inserts valid unique points via insertMany(ordered:false)
  * Returns full LocationSyncAck with per-item SyncItemResult breakdown
  * Enforces configurable SYNC_BATCH_SIZE_LIMIT (default 500)

Controller layer:
- Add src/sockets/syncHandler.ts: registerSyncHandler() wires the
  location_sync socket event, guards unauthenticated sockets, delegates
  to SyncService, emits location_sync_ack (success or error fallback)
- Update src/sockets/connectionHandler.ts: call registerSyncHandler
  inside io.on('connection')

Types:
- Extend src/sockets/socket.types.ts with OfflineLocationPoint,
  LocationSyncPayload, SyncItemResult, LocationSyncAck; add
  location_sync to ClientToServerEvents and location_sync_ack to
  ServerToClientEvents

Tests:
- Add tests/sync.service.test.ts: 23 unit tests using MongoMemoryServer
  covering persistence, deduplication (DB + within-batch), validation
  (boundary values, invalid fields), guard rails, and ack shape
- Update jest.config.js: set testTimeout=30000 for MongoMemoryServer

Closes SwiftChainn#27
…wiftChainn#28)

- Install @stellar/stellar-sdk@13.1.0

Config layer (src/config/stellar.ts):
  * resolveStellarConfig() validates env vars at startup (fast-fail on
    bad config); resolves SOROBAN_RPC_URL, STELLAR_NETWORK_PASSPHRASE,
    STELLAR_NETWORK, SOROBAN_RPC_TIMEOUT_MS with sensible defaults
  * createSorobanRpcClient() factory for rpc.Server instances
  * Pre-built sorobanRpcClient singleton for production code paths
  * Supports mainnet | testnet | futurenet

Service layer (src/blockchain/soroban.service.ts):
  * SorobanService.checkConnectivity(): calls getHealth() and
    getLatestLedger() in parallel; returns typed ConnectivityCheckResult
    on success or ConnectivityCheckError on failure (never throws)
  * SorobanService.getLatestLedger(): returns ledger sequence number
  * SorobanService.getNetworkInfo(): returns raw getNetwork() response
  * Client injected via constructor for testability

Controller layer (src/controllers/stellar.controller.ts):
  * StellarController.checkHealth(): 200 on healthy, 503 on unhealthy
  * StellarController.getNetworkInfo(): 200 with passphrase + protocol
  * StellarController.getLatestLedger(): 200 with sequence number

Routes (src/routes/stellar.routes.ts, src/routes/index.ts):
  * GET /api/v1/stellar/health
  * GET /api/v1/stellar/network
  * GET /api/v1/stellar/ledger/latest

Tests (tests/soroban.service.test.ts): 11 unit tests
  * Healthy node: correct fields, parallel calls, latency, ISO dates
  * Unhealthy node: ECONNREFUSED, timeout, non-Error throws, rpcUrl present
  * getLatestLedger: success and error propagation
  * getNetworkInfo: success and error propagation

.env.example: added SOROBAN_RPC_URL, STELLAR_NETWORK_PASSPHRASE,
  STELLAR_NETWORK, SOROBAN_RPC_TIMEOUT_MS with documentation comments

Closes SwiftChainn#28
…on broadcasting (SwiftChainn#25)

Types (src/sockets/socket.types.ts):
  * Add DriverLocationUpdatePayload: deliveryId, lat, lng, capturedAt
  * Add LocationBroadcastPayload: deliveryId, driverId, lat, lng,
    capturedAt, receivedAt (ISO)
  * Add LocationUpdateAck: success flag, locationId, optional error
  * Add driver_location_update to ClientToServerEvents
  * Add location:update and location_update_ack to ServerToClientEvents

Service layer (src/sockets/location.service.ts):
  * LocationService.processLiveUpdate():
    - Validates payload (driverId, deliveryId ObjectId, lat/lng bounds,
      capturedAt epoch)
    - Persists to MongoDB via LocationUpdate model (isOfflineSync=false,
      status=pending)
    - Broadcasts location:update to delivery:<deliveryId> room via io.to()
    - Returns typed LocationUpdateAck (never throws)
  * deliveryRoom() helper for canonical room name construction
  * DELIVERY_ROOM_PREFIX constant exported for reuse

Controller layer (src/sockets/locationHandler.ts):
  * registerLocationHandler(io, socket):
    - Auth guard: rejects unauthenticated drivers with ack error
    - Payload guard: rejects malformed objects
    - Delegates to LocationService, emits location_update_ack back to driver
    - Adds delivery-specific validation/logging to join_room for
      delivery: prefixed rooms

Integration (src/sockets/connectionHandler.ts):
  * Wire registerLocationHandler(io, socket) inside io.on('connection')

Tests (tests/location.service.test.ts): 20 unit tests using MongoMemoryServer
  * deliveryRoom helper: prefix format, uniqueness
  * processLiveUpdate success: ack shape, DB persistence (isOfflineSync,
    coordinates, deliveryId), broadcast to correct room, receivedAt ISO,
    fallback capturedAt, single emit
  * processLiveUpdate validation: invalid driverId, empty/invalid deliveryId,
    lat/lng OOB, NaN, capturedAt=0, boundary values, no-broadcast on failure,
    no-persist on failure

Closes SwiftChainn#25
- Add GET /api/v1/deliveries/:id/eta endpoint
- Implement routing service with Google Maps API and fallback Haversine calculation
- Follow strict Controller -> Service -> Model pattern
- Use MongoDB for data persistence
- Add seed script for test data
- Add environment variables for configuration
- Successfully tested with real MongoDB and API response
- Response verified: ETA calculated successfully for DEL-001

Closes SwiftChainn#22
Danielobito009 and others added 25 commits August 7, 2026 04:00
…schema-treasury-members-metadata

feat: enhance Fleet schema with treasury, members, and business metadata
…shutdown

Stop accepting new requests on SIGTERM/SIGINT, wait for in-flight HTTP and tracked Mongo sessions, disconnect Socket.IO clients, then close the DB pool before exit.

Co-authored-by: Cursor <cursoragent@cursor.com>
…wiftChainn#145)

Closes SwiftChainn#145

## What changed

### New files
- src/middlewares/idempotency.ts
  requireIdempotencyKey Express middleware that enforces the
  Idempotency-Key header on protected POST endpoints. Intercepts
  res.json to capture response bodies and replays cached responses
  for duplicate requests.

- src/services/idempotency.service.ts
  IdempotencyService with dual-store strategy:
    - Redis (primary)  when REDIS_URL is configured; uses SET NX for
      atomic first-write protection against concurrent duplicates.
    - MongoDB (fallback) when Redis is absent; uses findOneAndUpdate
      with  for the same atomicity guarantee.
  Exposes get / markProcessing / markCompleted / markFailed methods.

- src/models/IdempotencyRecord.ts
  Mongoose model with a composite unique index on (key, endpoint) and
  a TTL index on expiresAt for automatic record expiry.

- src/config/redis.ts
  Lazy ioredis singleton with exponential back-off retry and graceful
  degradation — when REDIS_URL is absent or Redis is unreachable the
  app continues using the MongoDB fallback store.

### Modified files
- src/routes/delivery.routes.ts
  Added requireIdempotencyKey before the POST / handler so every
  delivery creation request must carry an Idempotency-Key header.

- src/routes/escrow.routes.ts
  Added POST /fund endpoint protected by requireIdempotencyKey +
  validateRequest(fundEscrowBodySchema). Mounted escrow routes in
  src/routes/index.ts at /api/v1/escrow.

- src/routes/index.ts
  Mounted escrow routes so /api/v1/escrow/* is now reachable.

- src/controllers/escrow.controller.ts
  Added fund() handler that delegates to EscrowService.fund().

- src/services/escrow.service.ts
  Added fund() method as the HTTP-layer entry point for escrow
  funding; delegates to existing recordEscrowFunded() for write
  logic and re-fetches the persisted document for the response.

- src/validators/escrowValidator.ts
  Added fundEscrowBodySchema (Zod v4) for request-body validation
  of the POST /fund endpoint.

- src/models/Escrow.ts
  Fixed pre-existing duplicate-schema merge bug that caused 37
  TypeScript errors; retained the EscrowLockStatus / transactions
  schema that the service layer depends on.

- src/config/env.ts
  Added REDIS_URL (optional) and IDEMPOTENCY_TTL_SECONDS (default
  86400 s) to envSchema and EnvConfig interface.

- package.json / package-lock.json
  Added ioredis@5.3.2 runtime dependency.

- .env.example
  Documented REDIS_URL and IDEMPOTENCY_TTL_SECONDS variables.

## Idempotency behaviour
- Missing header       -> 422 Unprocessable Entity
- First request        -> processed normally; response cached under key
- Duplicate (complete) -> 200/201 replayed from cache, no DB writes
- Duplicate (in-flight)-> 409 Conflict
- Key TTL              -> configurable via IDEMPOTENCY_TTL_SECONDS (default 24 h)
…SwiftChainn#144)

Closes SwiftChainn#144

## What changed

### New files
- src/utils/circuitBreaker.ts
  Generic createCircuitBreaker<TArgs, TResult> factory built on opossum.
  Accepts typed CircuitBreakerOptions (errorThresholdPercentage,
  rollingWindowMs, resetTimeoutMs, volumeThreshold, timeoutMs) and an
  optional fallback function. Registers every breaker in a module-level
  registry. Full event hooks: open / halfOpen / close / fallback /
  timeout / reject / success / failure — all routed through the Winston
  logger. Exports getAllCircuitBreakerStatuses() for the health endpoint
  and fireWithBreaker() for action-agnostic fire calls.

- src/controllers/circuitBreakerController.ts
  GET /api/v1/health/circuit-breakers handler. Returns 200 when all
  breakers are CLOSED, 206 when any is OPEN or HALF-OPEN, with a per-
  breaker state + rolling stats payload and a summary object.

- src/routes/healthRoutes.ts
  Router for /api/v1/health — mounts the circuit-breaker status endpoint.

### Modified files
- src/services/routingService.ts
  Google Maps Directions API call wrapped in a dedicated 'google-maps'
  circuit breaker. Fallback: Haversine estimate returned immediately when
  the circuit is OPEN. ETAResponse now includes isFallback: boolean so
  callers can distinguish live vs degraded results. axios timeout aligned
  with CB_GOOGLE_MAPS_TIMEOUT_MS.

- src/blockchain/soroban.service.ts
  All RPC calls (getHealth, getLatestLedger, getNetwork) go through
  callWithRetryAndBreaker() which stacks the existing exponential-backoff
  retry inside a 'soroban-rpc' circuit breaker. Fallback returns a typed
  DegradedLedgerResult sentinel. checkConnectivity() and getLatestLedger()
  handle the sentinel and never throw on open circuit.

- src/services/transactionService.ts
  Dedicated 'soroban-rpc-tx' circuit breaker for transaction-building RPC
  calls (getAccount + prepareTransaction). When the circuit is OPEN both
  methods throw AppError(503) immediately instead of waiting for a TCP
  timeout, preventing request pile-up during node outages.

- src/config/env.ts
  10 new circuit-breaker env vars added to both EnvConfig interface and
  envSchema with production-safe defaults:
    CB_GOOGLE_MAPS_ERROR_THRESHOLD_PERCENTAGE (50)
    CB_GOOGLE_MAPS_ROLLING_WINDOW_MS          (30000)
    CB_GOOGLE_MAPS_RESET_TIMEOUT_MS           (60000)
    CB_GOOGLE_MAPS_VOLUME_THRESHOLD           (5)
    CB_GOOGLE_MAPS_TIMEOUT_MS                 (10000)
    CB_SOROBAN_ERROR_THRESHOLD_PERCENTAGE     (50)
    CB_SOROBAN_ROLLING_WINDOW_MS              (30000)
    CB_SOROBAN_RESET_TIMEOUT_MS               (60000)
    CB_SOROBAN_VOLUME_THRESHOLD               (3)
    CB_SOROBAN_TIMEOUT_MS                     (15000)

- .env.example  — all 10 vars documented with explanations.
- package.json  — opossum@8.1.2 (runtime), @types/opossum@8.1.4 (dev).
- src/routes/index.ts — /api/v1/health mounted.

## Circuit-breaker behaviour

| State     | Google Maps                  | Soroban RPC                         |
|-----------|------------------------------|-------------------------------------|
| CLOSED    | Live Directions API call     | Live RPC call (with retry)          |
| OPEN      | Haversine fallback (instant) | DegradedLedgerResult / 503 AppError |
| HALF-OPEN | Single probe call            | Single probe call                   |

## Health endpoint
GET /api/v1/health/circuit-breakers
  200 — all breakers CLOSED
  206 — one or more breakers OPEN or HALF-OPEN
…itialised (SwiftChainn#143)

Closes SwiftChainn#143

## Problem
Drivers could be assigned to deliveries whose Soroban escrow contract had
never been funded or was in a non-ready state (pending, released, refunded,
disputed), creating a mismatch between on-chain escrow state and off-chain
delivery state.

## Solution
Added a dedicated assignDriver flow in the service layer that queries the
Escrow collection for the delivery and rejects the assignment with a clear,
actionable error message unless the escrow lockStatus is LOCKED.

## Changes

### src/services/delivery.service.ts  (implementation directory per issue)
- Imported Escrow model and EscrowLockStatus enum.
- Added AssignDriverInput interface { deliveryId, driverId }.
- Added assignDriver(input) method with five ordered guard checks:
    1. Invalid delivery ObjectId format -> 400
    2. Delivery not found              -> 404
    3. Terminal status (completed /
       cancelled)                      -> 409
    4. Already assigned                -> 409
    5. No escrow record (contract
       never initialised)              -> 422
    6. Escrow exists but lockStatus
       is not LOCKED (pending /
       released / refunded / disputed) -> 409 with status-specific message
  On success: sets delivery.driverId and advances status to ASSIGNED in
  a single document save (no partial-update window).

### src/controllers/delivery.controller.ts
- Imported AssignDriverInput.
- Added assignDriver() handler that delegates to deliveryService.assignDriver()
  and returns 200 { status: 'success', message, data: delivery }.

### src/routes/delivery.routes.ts
- Imported assignDriverSchema, authenticate, requireRole, UserRole.
- Added PATCH /api/v1/deliveries/:id/assign-driver route:
    authenticate -> requireRole(ADMIN) -> validateRequest(assignDriverSchema)
    -> deliveryController.assignDriver
  Full OpenAPI doc comment documents all response codes (200/400/401/403/
  404/409/422).
…SwiftChainn#141)

Closes SwiftChainn#141

## Problem
Stellar transaction submissions could fail with tx_bad_seq (sequence number
mismatch) when a concurrent submission from the same account incremented the
sequence number between the XDR build and the submission. The error was not
caught or retried, causing permanent transaction failures under concurrent load.

## Solution
Created src/services/stellarService.ts (the implementation directory per
issue), which provides a dedicated submitEscrowLock() method with:
  - Two-path tx_bad_seq detection (XDR decode via xdr.TransactionResult +
    string-match fallback) covering all SDK error shapes.
  - Automatic sequence refresh: on tx_bad_seq the account is re-fetched from
    the RPC node to obtain the current sequence number.
  - Full transaction rebuild: the operation is reconstructed from live DB data
    (no hardcoded values) and re-simulated via prepareTransaction to attach
    updated resource fees and footprint.
  - Bounded retry loop capped by STELLAR_BAD_SEQ_MAX_RETRIES (default 3).
  - pollForCompletion(): polls getTransaction() with exponential back-off
    (500 ms -> 5 s cap) until SUCCESS, FAILED, or polling window exhausted.

## Changes

### src/services/stellarService.ts  (NEW — implementation directory)
  - StellarService class with:
      submitEscrowLock(input)       — submit signed XDR with bad-seq retry
      rebuildWithFreshSequence()    — public helper, re-fetches account +
                                      rebuilds from DB + re-simulates
      pollForCompletion(hash)       — waits for ledger inclusion
      isBadSeqError()               — detects tx_bad_seq in both response
                                      and thrown error shapes
  - SubmitEscrowLockInput and SubmitEscrowLockResult interfaces exported.
  - All delivery/contract data sourced from MongoDB (no inline mocks).

### src/config/env.ts
  - Added 4 env vars to EnvConfig interface and Zod envSchema:
      SOROBAN_RPC_MAX_RETRIES        (default 3)
      SOROBAN_RPC_RETRY_BASE_MS      (default 250)
      SOROBAN_RPC_RETRY_MAX_MS       (default 8000)
      STELLAR_BAD_SEQ_MAX_RETRIES    (default 3)
  - Fixes the pre-existing gap where soroban.service.ts referenced these
    vars but they were absent from the validated schema.

### src/validators/transactionValidator.ts
  - Added submitTransactionSchema (deliveryId, payerAddress, signedXdr).
  - Added SubmitTransactionBody type export.

### src/controllers/transactionController.ts
  - Imported stellarService and SubmitTransactionBody.
  - Added submitEscrowLockTransaction() handler (POST /transactions/submit).

### src/routes/transactionRoutes.ts
  - Added POST /api/v1/transactions/submit route:
      apiLimiter -> validateRequest(submitTransactionSchema)
      -> transactionController.submitEscrowLockTransaction
  - Full OpenAPI doc comment with all response codes.

### .env.example
  - Documented all 4 new env vars with explanations.

## Retry behaviour

| Scenario                        | Result                                    |
|---------------------------------|-------------------------------------------|
| First submission succeeds       | 200 with hash + ledger                    |
| tx_bad_seq, retry succeeds      | 200 with retriedOnBadSeq=true             |
| tx_bad_seq exhausts all retries | 409 Conflict                              |
| Other submission error          | 502 Bad Gateway                           |
| Not confirmed in poll window    | 504 Gateway Timeout                       |
…lations

Cache ETA results in Redis using geohash-based keys with configurable TTL, check cache before external routing APIs, and wire Redis into docker-compose and server startup.

Co-authored-by: Cursor <cursoragent@cursor.com>
…own-drain

fix(SwiftChainn#149): drain HTTP, Socket.IO, and DB work on graceful shutdown
feat: add idempotency keys to delivery creation and escrow funding (SwiftChainn#145)
…er-apis

feat: implement circuit breaker for Google Maps and Stellar RPC calls (SwiftChainn#144)
…ent-escrow-check

fix: prevent driver assignment when Soroban escrow contract is not initialised (SwiftChainn#143)
fix: handle Stellar tx_bad_seq errors with sequence refresh and retry (SwiftChainn#141)
…age-guarantees

feat: add socket message ACK queue and reconnect replay
feat(SwiftChainn#148): add Redis caching layer for delivery ETA calculations
@drips-wave

drips-wave Bot commented Aug 29, 2026

Copy link
Copy Markdown

@Danielobito009 Great news! 🎉 Based on an automated assessment of this PR, the linked Wave issue(s) no longer count against your application limits.

You can now already apply to more issues while waiting for a review of this PR. Keep up the great work! 🚀

Learn more about application limits

@Tybravo

Tybravo commented Aug 30, 2026

Copy link
Copy Markdown
Collaborator

@Danielobito009
Please why do you have @Alu-card19 contributing to these issues not with your account.

You are the one I assigned this issues to. Please fix this matter.

@Danielobito009
Danielobito009 force-pushed the merge-conflict-scenario branch from 7c07a57 to c50cb11 Compare September 1, 2026 10:32
@Danielobito009
Danielobito009 deleted the merge-conflict-scenario branch September 1, 2026 10:53
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

2 participants