Skip to content

feat(integration): verify receipts, schema validation, wallet persistence, account-merge handling#1208

Merged
Emmyt24 merged 1 commit into
Emmyt24:mainfrom
topsonDev:feat/integration-tasks-1161-1162-1165-1166
May 30, 2026
Merged

feat(integration): verify receipts, schema validation, wallet persistence, account-merge handling#1208
Emmyt24 merged 1 commit into
Emmyt24:mainfrom
topsonDev:feat/integration-tasks-1161-1162-1165-1166

Conversation

@topsonDev
Copy link
Copy Markdown
Contributor

Summary

This PR resolves four integration issues in a single focused change.


#1162 – Verify blockchain transaction receipts before confirming success

What changed: Added TransactionMonitor.verifyTransactionReceipt() — a polling method that waits for a terminal on-chain state (success / failed / timeout) before returning a result to the caller. The app no longer assumes success on submission.

How it works:

  • Polls checkTransactionStatus() with exponential backoff (reuses existing calculateBackoffDelay / USER_RETRY_CONFIG).
  • Transient network errors are retried; non-retryable errors surface immediately as failed.
  • Configurable timeoutMs (defaults to the monitor's configured timeout).

Polling policy: same interval and backoff as the existing startMonitoring path — 3 s base, capped at 30 s, 2-minute total timeout.

Tests: 6 integration tests covering success, failure, timeout, non-retryable error, and retry-then-success.


#1165 – Validate IPFS metadata against a versioned schema before acceptance

What changed: New services/metadataSchema.ts with a validateMetadataSchema() function. IPFSService.uploadMetadata() now validates the constructed metadata object before pinning and throws a descriptive error on failure.

Schema versions:

  • v1 (default, backwards-compatible): name, description, image — all required non-empty strings.
  • v2: extends v1 with an optional attributes array ({ trait_type: string; value: string | number }).
  • Metadata without a schemaVersion field is treated as v1.
  • Any other version is rejected with a clear error listing supported versions.

Tests: 11 integration tests covering valid v1/v2, missing required fields, empty strings, malformed attributes, and unsupported version numbers.


#1161 – Persist Freighter wallet connection state across reloads

What changed: useWallet now persists the connected address and network to localStorage (key: nova_wallet_state) in addition to the existing boolean flag (nova_wallet_connected).

Storage approach:

  • On connect / network change: both keys are written atomically.
  • On reload: persisted state is restored optimistically (no blank UI flash) while re-validation runs against the live Freighter API in the background.
  • On revocation / uninstall: both keys are cleared and the session is reset.
  • Malformed or incomplete storage is ignored and treated as no session.

Tests: 6 integration tests covering persist-on-connect, restore-on-reload, clear-on-disconnect, malformed JSON, missing address field, and revocation.


#1166 – Handle Stellar account-merge and missing-account scenarios gracefully

What changed: Added StellarService.getAccountSafe(address) returning a typed AccountLookupResult discriminated union instead of throwing.

type AccountLookupResult =
  | { found: true; account: any }
  | { found: false; reason: 'missing' | 'error'; error?: string };

Detection logic: error messages containing not found, 404, or does not exist map to reason: 'missing' (covers both missing and merged accounts); all other errors map to reason: 'error' with the original message attached.

Tests: 5 integration tests covering existing account, 404/not-found, merged account (does not exist), unexpected errors, and the no-throw guarantee.


Files changed

File Change
services/transactionMonitor.ts Add verifyTransactionReceipt()
services/metadataSchema.ts New — versioned schema validator
services/IPFSService.ts Call validateMetadataSchema() before pinning
hooks/useWallet.ts Persist address + network; restore on reload; clear on revocation
services/stellar.service.ts Add AccountLookupResult type + getAccountSafe()
test/integration/tx-receipt-verification.integration.test.ts New — 6 tests
test/integration/metadata-schema-validation.integration.test.ts New — 11 tests
test/integration/wallet-state-persistence.integration.test.ts New — 6 tests
test/integration/account-merge-handling.integration.test.ts New — 5 tests

Total: 28 new tests, all passing.

Closes #1162
Closes #1165
Closes #1161
Closes #1166

…ence, account-merge handling

Emmyt24#1162 – Verify blockchain transaction receipts before confirming success
- Add TransactionMonitor.verifyTransactionReceipt() that polls until a
  terminal on-chain state (success/failed/timeout) is reached before
  surfacing a result to the caller.
- Retries on transient network errors using existing backoff helpers;
  non-retryable errors surface immediately as 'failed'.
- Integration tests cover success, failure, timeout, and retry-then-success
  scenarios using a fully mocked transport.

Emmyt24#1165 – Validate IPFS metadata against a versioned schema before acceptance
- Introduce services/metadataSchema.ts with a versioned schema validator
  supporting v1 (name/description/image) and v2 (+ optional attributes).
- Metadata without a schemaVersion field defaults to v1 for backwards
  compatibility; unsupported versions are rejected with a clear error.
- IPFSService.uploadMetadata() now validates the constructed metadata object
  before pinning; throws with a descriptive message on failure.
- Integration tests cover valid v1/v2, missing fields, malformed attributes,
  and unsupported version numbers.

Emmyt24#1161 – Persist Freighter wallet connection state across reloads
- Extend useWallet to persist the connected address and network to
  localStorage (WALLET_STATE_KEY) in addition to the existing boolean flag.
- On reload, the persisted address/network is restored optimistically so the
  UI is not blank while re-validation runs against the live Freighter API.
- If the wallet is no longer authorised (revoked/uninstalled), both storage
  keys are cleared and the session is reset.
- Integration tests cover persist-on-connect, restore-on-reload, clear-on-
  disconnect, malformed storage, missing address, and revocation scenarios.

Emmyt24#1166 – Handle Stellar account-merge and missing-account scenarios gracefully
- Add StellarService.getAccountSafe() returning a typed AccountLookupResult
  discriminated union ({ found: true, account } | { found: false, reason }).
- Detects missing/merged accounts from 'not found', '404', and 'does not
  exist' error messages and maps them to reason: 'missing'; all other errors
  map to reason: 'error' with the original message attached.
- Callers can now branch on result.found without wrapping every getAccount
  call in a try/catch.
- Integration tests cover existing account, 404/not-found, merged account,
  unexpected errors, and the no-throw guarantee.

Closes Emmyt24#1162
Closes Emmyt24#1165
Closes Emmyt24#1161
Closes Emmyt24#1166
@drips-wave
Copy link
Copy Markdown

drips-wave Bot commented May 30, 2026

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

@Emmyt24 Emmyt24 merged commit 457f371 into Emmyt24:main May 30, 2026
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