Compile-time JSON spec loader for exchange specifications.
Reads exchange specs from priv/specs/json/output/ and decodes them for use
by the generator macro (CCXT.Exchange). Specs are loaded at compile time
inside the generator — this module provides the loading functions but does
not store specs as module attributes.
Usage
# In generator macro (compile time):
spec = CCXT.Spec.load!("bybit")
# List available exchanges:
CCXT.Spec.exchanges()
#=> ["aftermath", "alpaca", "apex", ...]Schema Version
load!/1 and load_manifest!/0 enforce schema_version major 3
(ccxt_extract Schema 3.0.0+). Per-exchange specs must also carry a
non-empty top-level _provenance map (RFC 6901 pointer keys →
"raw" / "derived" / "override"); the manifest does not.
A mismatch raises with a specific message naming the spec and the
offending field, so a stale priv/specs/json/output/ surfaces as a
clear compile-time failure instead of a downstream MatchError.
Dead Weight Stripping
load!/1 removes extraction-only data (structure.interface_signatures
and structure.methods) that is only useful for static analysis, not
runtime code generation. This reduces memory for Macro.escape/1.
Summary
Functions
Returns the list of available exchange IDs from the manifest.
Loads and decodes an exchange spec by ID.
Loads and decodes the manifest file.
Returns the absolute path to the manifest file.
Returns the absolute path to a spec file for the given exchange ID.
Validates a decoded manifest map against the Schema 3.0.0+ contract.
Validates a decoded per-exchange spec map against the Schema 3.0.0+ contract:
schema_version must be a string whose numeric major equals 3,
and _provenance must be a non-empty top-level map. On mismatch, raises with
a message naming the exchange and the offending field.
Functions
@spec exchanges() :: [String.t()]
Returns the list of available exchange IDs from the manifest.
Examples
CCXT.Spec.exchanges()
#=> ["aftermath", "alpaca", "apex", "arkham", ...]
Loads and decodes an exchange spec by ID.
Reads the JSON file, decodes it, and strips extraction-only data from
structure. Returns a map with string keys.
Raises File.Error if the spec file doesn't exist, or Jason.DecodeError
on invalid JSON.
Examples
spec = CCXT.Spec.load!("bybit")
spec["exchange"]["id"]
#=> "bybit"
@spec load_manifest!() :: map()
Loads and decodes the manifest file.
Returns the decoded _manifest.json containing exchange list,
CCXT version, and extraction metadata.
Examples
manifest = CCXT.Spec.load_manifest!()
manifest["ccxt_version"]
#=> "4.5.46"
manifest["exchange_count"]
#=> 23
@spec manifest_path() :: String.t()
Returns the absolute path to the manifest file.
Examples
CCXT.Spec.manifest_path()
#=> "/path/to/priv/specs/json/output/_manifest.json"
Returns the absolute path to a spec file for the given exchange ID.
Examples
CCXT.Spec.spec_path("bybit")
#=> "/path/to/priv/specs/json/output/bybit.json"
Validates a decoded manifest map against the Schema 3.0.0+ contract.
Only the schema_version major is enforced — manifests have no _provenance
by design (different document type from per-exchange specs). Raises on
mismatch; returns the manifest unchanged on success. Exposed for test
coverage of the guard branches.
Validates a decoded per-exchange spec map against the Schema 3.0.0+ contract:
schema_version must be a string whose numeric major equals 3,
and _provenance must be a non-empty top-level map. On mismatch, raises with
a message naming the exchange and the offending field.
Returns the spec unchanged on success. Called internally from load!/1;
exposed publicly so test suites can exercise every branch against in-memory
maps without writing fixture files into the live spec directory.