feat(integration): verify receipts, schema validation, wallet persistence, account-merge handling#1208
Merged
Emmyt24 merged 1 commit intoMay 30, 2026
Conversation
…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
|
@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! 🚀 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
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:
checkTransactionStatus()with exponential backoff (reuses existingcalculateBackoffDelay/USER_RETRY_CONFIG).failed.timeoutMs(defaults to the monitor's configured timeout).Polling policy: same interval and backoff as the existing
startMonitoringpath — 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.tswith avalidateMetadataSchema()function.IPFSService.uploadMetadata()now validates the constructed metadata object before pinning and throws a descriptive error on failure.Schema versions:
name,description,image— all required non-empty strings.attributesarray ({ trait_type: string; value: string | number }).schemaVersionfield is treated as v1.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:
useWalletnow persists the connectedaddressandnetworktolocalStorage(key:nova_wallet_state) in addition to the existing boolean flag (nova_wallet_connected).Storage approach:
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 typedAccountLookupResultdiscriminated union instead of throwing.Detection logic: error messages containing
not found,404, ordoes not existmap toreason: 'missing'(covers both missing and merged accounts); all other errors map toreason: '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
services/transactionMonitor.tsverifyTransactionReceipt()services/metadataSchema.tsservices/IPFSService.tsvalidateMetadataSchema()before pinninghooks/useWallet.tsservices/stellar.service.tsAccountLookupResulttype +getAccountSafe()test/integration/tx-receipt-verification.integration.test.tstest/integration/metadata-schema-validation.integration.test.tstest/integration/wallet-state-persistence.integration.test.tstest/integration/account-merge-handling.integration.test.tsTotal: 28 new tests, all passing.
Closes #1162
Closes #1165
Closes #1161
Closes #1166