diff --git a/src/anchors/StellarTomlParser.ts b/src/anchors/StellarTomlParser.ts index e135af2..1654f43 100644 --- a/src/anchors/StellarTomlParser.ts +++ b/src/anchors/StellarTomlParser.ts @@ -10,10 +10,14 @@ // `toml` is a CommonJS package — we import it as a namespace. import * as toml from "toml"; +import { UnsupportedTomlVersionError } from "../errors.js"; // --------------------------------------------------------------------------- -// SEP-1 typed structures +// Supported stellar.toml schema versions (SEP-1) // --------------------------------------------------------------------------- +//** Accepted VERSION values. TOML documents with other versions are rejected. */ +export const SUPPORTED_TOML_VERSIONS = ["2.0", "2.1"]; + /** A single currency entry in the CURRENCIES array. */ export interface TomlCurrency { @@ -87,8 +91,18 @@ export interface TomlMetadata { } // --------------------------------------------------------------------------- +// Supported stellar.toml schema versions (SEP-1) +// --------------------------------------------------------------------------- +//** Accepted VERSION values. TOML documents with other versions are rejected. */ +export const SUPPORTED_TOML_VERSIONS = ["2.0", "2.1"]; + // Cache entry // --------------------------------------------------------------------------- +// Supported stellar.toml schema versions (SEP-1) +// --------------------------------------------------------------------------- +//** Accepted VERSION values. TOML documents with other versions are rejected. */ +export const SUPPORTED_TOML_VERSIONS = ["2.0", "2.1"]; + interface CacheEntry { metadata: TomlMetadata; @@ -96,8 +110,18 @@ interface CacheEntry { } // --------------------------------------------------------------------------- +// Supported stellar.toml schema versions (SEP-1) +// --------------------------------------------------------------------------- +//** Accepted VERSION values. TOML documents with other versions are rejected. */ +export const SUPPORTED_TOML_VERSIONS = ["2.0", "2.1"]; + // StellarTomlParser // --------------------------------------------------------------------------- +// Supported stellar.toml schema versions (SEP-1) +// --------------------------------------------------------------------------- +//** Accepted VERSION values. TOML documents with other versions are rejected. */ +export const SUPPORTED_TOML_VERSIONS = ["2.0", "2.1"]; + /** Options accepted by `StellarTomlParser`. */ export interface StellarTomlParserOptions { @@ -235,6 +259,12 @@ export class StellarTomlParser { ); } + // Validate VERSION before accepting the document + const version = parsed.VERSION; + if (version !== undefined && !SUPPORTED_TOML_VERSIONS.includes(String(version))) { + throw new UnsupportedTomlVersionError(String(version), SUPPORTED_TOML_VERSIONS); + } + return { domain, tomlUrl, diff --git a/src/errors.ts b/src/errors.ts index 02e444b..0e20bfb 100644 --- a/src/errors.ts +++ b/src/errors.ts @@ -2069,7 +2069,21 @@ export class StellarTomlFetchError extends StellarSplitError { this.name = "StellarTomlFetchError"; this.domain = domain; Object.setPrototypeOf(this, new.target.prototype); - } +} + +/** Thrown when a stellar.toml file has an unsupported VERSION field. */ +export class UnsupportedTomlVersionError extends StellarSplitError { + readonly version: string; + + constructor(version: string, supportedVersions: string[] = []) { + super( + `Unsupported stellar.toml schema version: ${version}. Supported: ${supportedVersions.join(", ")}`, + "UNSUPPORTED_TOML_VERSION", + { version, supportedVersions }, + ); + this.name = "UnsupportedTomlVersionError"; + this.version = version; + Object.setPrototypeOf(this, new.target.prototype); } /** Thrown when all channel accounts in the pool are busy and the acquire timeout elapses. */ diff --git a/test/stellarTomlParserVersion.test.ts b/test/stellarTomlParserVersion.test.ts new file mode 100644 index 0000000..edb11b4 --- /dev/null +++ b/test/stellarTomlParserVersion.test.ts @@ -0,0 +1,54 @@ +import { describe, it, expect } from "vitest"; +import { + StellarTomlParser, + SUPPORTED_TOML_VERSIONS, +} from "../src/anchors/StellarTomlParser.js"; +import { UnsupportedTomlVersionError } from "../src/errors.js"; + +describe("StellarTomlParser VERSION validation", () => { + it("accepts TOML with supported version 2.0", async () => { + const parser = new StellarTomlParser(); + // Mock the fetch by overriding _fetchRaw + (parser as any)._fetchRaw = async () => 'VERSION = "2.0"\n'; + const meta = await parser.fetch("example.com"); + expect(meta.VERSION).toBe("2.0"); + }); + + it("accepts TOML with supported version 2.1", async () => { + const parser = new StellarTomlParser(); + (parser as any)._fetchRaw = async () => 'VERSION = "2.1"\n'; + const meta = await parser.fetch("example.com"); + expect(meta.VERSION).toBe("2.1"); + }); + + it("throws UnsupportedTomlVersionError for unsupported version", async () => { + const parser = new StellarTomlParser(); + (parser as any)._fetchRaw = async () => 'VERSION = "3.0"\n'; + await expect(parser.fetch("example.com")).rejects.toThrow( + UnsupportedTomlVersionError, + ); + }); + + it("UnsupportedTomlVersionError names the encountered version", async () => { + const parser = new StellarTomlParser(); + (parser as any)._fetchRaw = async () => 'VERSION = "99.0"\n'; + try { + await parser.fetch("example.com"); + expect.fail("Should have thrown"); + } catch (err) { + expect(err).toBeInstanceOf(UnsupportedTomlVersionError); + expect((err as UnsupportedTomlVersionError).version).toBe("99.0"); + } + }); + + it("accepts TOML with no VERSION field", async () => { + const parser = new StellarTomlParser(); + (parser as any)._fetchRaw = async () => 'ACCOUNTS = ["GA..."]\n'; + const meta = await parser.fetch("example.com"); + expect(meta.ACCOUNTS).toEqual(["GA..."]); + }); + + it("exports SUPPORTED_TOML_VERSIONS as [2.0, 2.1]", () => { + expect(SUPPORTED_TOML_VERSIONS).toEqual(["2.0", "2.1"]); + }); +});