Skip to content

feat(integration): contract validation, testnet faucet, CID verification, webhook compression#1210

Open
temma02 wants to merge 1 commit into
Emmyt24:mainfrom
temma02:feat/integration-contract-validation-faucet-cid-webhook-compression
Open

feat(integration): contract validation, testnet faucet, CID verification, webhook compression#1210
temma02 wants to merge 1 commit into
Emmyt24:mainfrom
temma02:feat/integration-contract-validation-faucet-cid-webhook-compression

Conversation

@temma02
Copy link
Copy Markdown
Contributor

@temma02 temma02 commented May 30, 2026

Summary

Implements four integration improvements across the backend service:

Changes

File Change
backend/src/lib/contractAddressValidator.ts New — Soroban RPC contract existence check with XDR key construction and retry/backoff
backend/src/lib/testnet-faucet.ts New — Friendbot helper, Stellar keypair generation (no external SDK), network guard
backend/src/lib/ipfs/cidVerification.ts New — round-trip CID content verification via IPFS gateway
backend/src/lib/ipfs/pinata.ts Modified — call CID verification after upload when IPFS_VERIFY_CID=true
backend/src/services/webhookDeliveryService.ts Modified — gzip compression + 415 fallback
backend/src/__tests__/contractAddressValidator.test.ts New — 13 tests covering valid, missing, malformed, retry, exhaustion, non-retryable
backend/src/__tests__/testnetFaucet.test.ts New — 16 tests covering guard, success, retry, keypair format, composed helper
backend/src/__tests__/cidVerification.test.ts New — 12 tests covering match, mismatch, gateway failures, metadata wrapper
backend/src/__tests__/webhookCompression.test.ts New — 4 tests covering no-compression, gzip header, delivery success, 415 fallback

How it was verified

  • All 44 new tests pass (vitest run) using mocked external services (nock for HTTP, vi.fn() for fetch/Pinata).
  • No existing tests were modified.
  • Retry logic uses the existing calculateBackoffDelay / isRetryableError / sleep utilities from stellar-service-integration/rate-limiter.ts.
  • No credentials are logged; error messages contain contract IDs and network names only.

Configuration

Variable Default Description
IPFS_VERIFY_CID false Set to true to enable post-upload CID content verification
IPFS_VERIFY_GATEWAY_URL https://gateway.pinata.cloud/ipfs Gateway used for CID round-trip check
WEBHOOK_COMPRESSION_THRESHOLD_BYTES 1024 Payloads at or above this size (bytes) are gzip-compressed

Closes #1167
Closes #1168
Closes #1169
Closes #1170

…ion, webhook compression

Implements four integration improvements across the backend:

**Emmyt24#1169 — Validate deployed contract addresses match the active environment**
- Add `backend/src/lib/contractAddressValidator.ts` with
  `validateContractOnNetwork()`, which calls the Soroban JSON-RPC
  `getLedgerEntries` endpoint to confirm the configured contract ID exists
  on the active network at startup.
- The LedgerKey XDR is constructed locally (no external SDK dependency)
  by decoding the Soroban StrKey contract ID and building the binary key.
- Retries on transient network errors with exponential backoff (3 attempts,
  1 s base, ×2 factor); throws `ContractAddressError` immediately on format
  errors or missing contracts with a message that names the contract ID and
  STELLAR_NETWORK for operator diagnosis.
- Tests cover: existing contract, missing contract (empty entries), empty/
  malformed IDs (no RPC call made), transient retry, exhaustion, 4xx
  non-retryable, and correct JSON-RPC method/key format.

**Emmyt24#1168 — Integrate the Stellar testnet faucet for automated test setup**
- Add `backend/src/lib/testnet-faucet.ts` with:
  - `generateTestKeypair()` — generates a random Ed25519 keypair using
    Node.js `crypto` and encodes it as Stellar StrKey (G.../S... 56 chars)
    with CRC-16/XModem checksum; no external SDK required.
  - `fundTestAccount(publicKey, network, friendbotUrl)` — calls the
    Stellar Friendbot faucet; treats HTTP 400 (already funded) as success;
    retries on transient errors; throws `FaucetError` on non-testnet to
    prevent accidental mainnet calls.
  - `generateAndFundKeypair()` — composes the two helpers for test setup.
- Tests cover: mainnet/undefined guard, successful funding, transaction hash
  propagation, HTTP 400 treated as success, retry on ECONNRESET/ETIMEDOUT,
  exhaustion after max attempts, public-key inclusion in error, no retry on
  non-retryable 5xx, keypair format (G.../S..., 56 chars, uniqueness), and
  the combined generateAndFundKeypair flow.

**Emmyt24#1170 — Verify IPFS content addressing matches the returned CID**
- Add `backend/src/lib/ipfs/cidVerification.ts` with:
  - `verifyCIDContent(content, cid, gatewayBaseUrl)` — fetches the content
    stored under the CID from an IPFS gateway and compares it byte-for-byte
    against the original upload using SHA-256; throws `CIDMismatchError`
    (includes both hashes) on any mismatch or gateway failure.
  - `verifyMetadataCID(metadata, cid)` — convenience wrapper that
    serialises the object with `JSON.stringify` before comparing.
- Modify `backend/src/lib/ipfs/pinata.ts`:
  - Call `verifyCIDContent` after `pinFileToIPFS` and `verifyMetadataCID`
    after `pinJSONToIPFS` when `IPFS_VERIFY_CID=true`.
  - Gateway URL is configurable via `IPFS_VERIFY_GATEWAY_URL`
    (default: `https://gateway.pinata.cloud/ipfs`).
- Tests cover: matching content, URL construction, CID in error, SHA-256
  hashes in error, HTTP non-2xx, network error, error message wrapping,
  and JSON serialisation fidelity.

**Emmyt24#1167 — Compress large webhook payloads to reduce delivery overhead**
- Modify `backend/src/services/webhookDeliveryService.ts`:
  - Gzip-compress payloads whose JSON size meets or exceeds
    `WEBHOOK_COMPRESSION_THRESHOLD_BYTES` (default: 1024 bytes, instance-
    level so tests can override via env before construction).
  - Set `Content-Encoding: gzip` on compressed deliveries.
  - On HTTP 415 (Unsupported Media Type) the service clears the encoding
    and retries immediately with the uncompressed body; the existing 4xx
    non-retry rule continues to apply to all other 4xx codes.
- Tests cover: no compression below threshold, `Content-Encoding: gzip`
  above threshold, successful end-to-end compressed delivery, and the 415
  fallback round-trip showing gzip on attempt 1 and no encoding on attempt 2.

Closes Emmyt24#1167
Closes Emmyt24#1168
Closes Emmyt24#1169
Closes Emmyt24#1170
@drips-wave
Copy link
Copy Markdown

drips-wave Bot commented May 30, 2026

@temma02 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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

1 participant