Skip to content

Build Stellar TOML metadata parser and on-chain anchor verifier #487

Description

@Kingsman-99

Description

Anchor-issued assets used in StellarSplit invoices must have a valid stellar.toml file published at the asset issuer's home domain, but the SDK does not validate this before accepting custom assets. This issue adds a StellarTomlParser that fetches and parses stellar.toml files according to SEP-1, and an AnchorVerifier that cross-references the TOML metadata with on-chain account data to confirm the issuer account's home_domain points back to the TOML file (bidirectional verification).

Technical Context

  • New file: src/anchors/StellarTomlParser.ts and src/anchors/AnchorVerifier.ts; parsed result type: TomlMetadata mirrors the SEP-1 top-level fields
  • StellarTomlParser.fetch(domain: string): Promise<TomlMetadata> uses fetch() to retrieve https://{domain}/.well-known/stellar.toml and parses it with a lightweight TOML parser (@iarna/toml or equivalent)
  • AnchorVerifier.verify(assetIssuer: string, assetCode: string): Promise<VerificationResult> performs: (1) load issuer account from Horizon to get home_domain, (2) fetch TOML from home_domain, (3) assert TOML CURRENCIES array contains an entry matching assetCode and issuer
  • VerificationResult: { verified: boolean; tomlUrl: string; currencyEntry?: TomlCurrency; issues: string[] }
  • TOML responses are cached for tomlCacheTtlMs (default 3 600 000 ms) per domain

Acceptance Criteria

  • fetch('example.com') retrieves and correctly parses all SEP-1 TOML sections (ACCOUNTS, CURRENCIES, VALIDATORS, DOCUMENTATION)
  • verify('GABC...', 'USDC') returns { verified: true } when the issuer's home_domain TOML contains a matching CURRENCIES entry
  • verify() returns { verified: false, issues: ['no_home_domain'] } when the issuer account has no home_domain set
  • verify() returns { verified: false, issues: ['currency_not_found'] } when the TOML exists but lacks the assetCode entry
  • TOML is served from cache on a second fetch() call within TTL; after TTL, a fresh HTTP request is made
  • All CI checks (npm test, npm run build, ESLint) pass and the branch has no merge conflicts

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions