Skip to content

fix(contacts): keep federation-required memos and validate account ids - #1863

Merged
greatest0fallt1me merged 2 commits into
Streampay-Org:mainfrom
p70436464-prog:fix/contacts-federation-memo
Oct 24, 2026
Merged

greatest0fallt1me merged 2 commits into
Streampay-Org:mainfrom
p70436464-prog:fix/contacts-federation-memo

Conversation

@p70436464-prog

Copy link
Copy Markdown
Contributor

Closes #1686

Summary

Resolves the money-loss issue where contacts saved via Stellar federation addresses had their memo_type and memo discarded, and returned account_id values were trusted without checksum verification.

Money-Loss Scenario

Exchanges and custodial services rely on federation memos (e.g., account memo IDs) to route incoming payments and deposits to specific user balances. When a user saved a contact by federation address (e.g. user*exchange.com), StreamPay previously discarded the federation memo_type and memo, while allowing users to type a private note into a free-text memo field. Creating payment streams to such contacts without the required on-chain memo causes the exchange to receive funds with no destination metadata, leading to permanent loss or stuck customer funds.

What Was Done

  1. Federation Response Validation (app/utils/federation.ts):
    • Validates account_id using full StrKey base32 decoding and CRC-16 XMODEM checksum checks (isValidStellarPublicKey).
    • Validates memo_type against allowed values (text, id, hash).
    • Validates memo format for each type (utf-8 length <= 28 for text, uint64 string for id, 32-byte hex or base64 for hash).
    • Validates stellar_address matches query (case-insensitive).
    • Throws FederationError("...", "INVALID_RESPONSE") on failure.
    • Prevents caching of invalid responses.
  2. Memo Separation & Contact Interface (app/contacts/page.tsx):
    • Extended Contact with requiredMemo?: { type: "text" | "id" | "hash"; value: string }, distinct from the user's private memo note.
    • Added getContactPaymentTarget(contact) helper returning { address, memo? }.
    • Contact form displays the required memo in a read-only field with a "Required by <federationAddress>" badge (aria-readonly="true"). The user cannot edit or clear it.
    • Maintained backward compatibility for reading legacy contacts from localStorage.
  3. Checksum Verification & Demo Contacts:
    • Reject G-addresses that match length/regex but fail CRC-16 checksum with error "Invalid Stellar address".
    • Updated demo contacts to valid StrKey checksum addresses.

Test Results

@greatest0fallt1me
greatest0fallt1me merged commit c7a4771 into Streampay-Org:main Oct 24, 2026
3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Preserve federation-required memos and verify resolved account IDs when saving contacts

2 participants