vault.curator
Documentation for eth_defi.vault.curator Python module.
Vault curator identification and metadata.
Vault curators are professional risk managers and strategy operators that brand their vaults by embedding their organisation name in the vault’s token name or display name. Examples include Gauntlet, RE7 Labs, Steakhouse Financial, and MEV Capital.
This module provides:
Curator identification — given a vault name, detect which curator manages it using word-boundary regex matching against known curator names loaded from YAML feeder files
Protocol-curated detection — some vaults are operated by the protocol itself (Ostium, Gains Network, Hyperliquid HLP, Lighter LLP) rather than a third-party curator; these are identified by address lookups against known system vault address sets
Curator metadata loading — load curator metadata from the shared feeder YAML files in
eth_defi/data/feeds/curators/R2 metadata export — upload per-curator metadata JSON and an aggregate index to Cloudflare R2 for frontend consumption
Curator YAML files use the shared feeder schema defined in
eth_defi.feed.sources. Each file lives under
eth_defi/data/feeds/curators/ and follows this format:
feeder-id: gauntlet
name: Gauntlet
role: curator
website: https://www.gauntlet.xyz
twitter: gauntlet_xyz
linkedin: gauntlet-xyz
rss: https://medium.com/feed/gauntlet-networks
short_description: Gauntlet is a DeFi risk manager.
long_description: |
Gauntlet builds risk management systems for lending markets,
vaults and other on-chain financial applications.
Canonical feeder aliases
When the same organisation appears as both a curator and a stablecoin
issuer or vault protocol, duplicate feed fetching is avoided by using
canonical-feeder-id. An alias YAML file contains identity and
description metadata, but no feed source fields (twitter, linkedin, rss):
feeder-id: ethena
name: Ethena
role: curator
canonical-feeder-id: usde
The priority order determines which role keeps the feed sources:
Stablecoin — highest priority, always keeps feeds
Protocol — keeps feeds only when no stablecoin overlap exists
Curator — lowest priority, defers to stablecoin or protocol
Metadata inheritance happens at export time:
build_curator_metadata_json() resolves the canonical feeder
YAML by role priority and inherits website, twitter, linkedin and rss
from it.
Post resolution happens at consumption time — consumers use
resolve_feeder_id() to map an alias
feeder_id to the canonical feeder_id, then look up posts under that
canonical feeder’s tracked sources. The canonical_feeder_id field
is included in the exported CuratorMetadata JSON so that
frontends can resolve without accessing YAML files.
Identification approach
The curator name is matched against the vault display name using
word-boundary regular expressions (\b). This avoids false
positives such as bare "Gamma" matching "GammaSwap V1" or
"August" matching "Prize imToken August Campaign".
For curators whose YAML name field alone is insufficient (e.g.
"RE7 Labs" vaults often appear as just "RE7 …"), additional
short patterns are registered in CURATOR_NAME_PATTERNS.
Protocol-curated vaults are identified before name matching:
Ostium and Gains Network — all vaults on these protocols are protocol-curated (no external curator)
Hyperliquid — system vaults (HLP parent, HLP children, Liquidator) are identified by address against
eth_defi.hyperliquid.constants.HYPERLIQUID_SYSTEM_VAULT_ADDRESSESLighter — the LLP system pool is identified by address against
eth_defi.lighter.constants.LIGHTER_SYSTEM_POOL_ADDRESSES
Usage example:
from eth_defi.vault.curator import identify_curator, get_curator_name
slug = identify_curator(
chain_id=1,
vault_token_symbol="gtUSDC",
vault_name="Gauntlet USDC Core",
vault_address="0x1234…",
protocol_slug="morpho",
)
assert slug == "gauntlet"
assert get_curator_name(slug) == "Gauntlet"
# Protocol-curated vault — returns the protocol slug itself
slug = identify_curator(
chain_id=999,
vault_token_symbol="HLP",
vault_name="Hyperliquid Liquidity Pool",
vault_address="0xdfc24b077bc1425ad1dea75bcb6f8158e10df303",
protocol_slug="hyperliquid",
)
assert slug == "hyperliquid"
assert get_curator_name(slug) == "Hyperliquid"
assert is_protocol_curator(slug)
Functions
|
Build the aggregate curator metadata index. |
|
Build a |
Check which logo variants are available for a curator. |
|
|
Look up the human-readable name for a curator slug. |
|
Identify the curator managing a vault. |
|
Check whether a curator slug represents a protocol-curated vault. |
Load all curator metadata from YAML files. |
|
|
Process and upload a single curator's metadata and logos to R2. |
|
Build and upload the aggregate curator index to R2. |
|
Upload metadata entries for all protocol-curated slugs to R2. |
Classes
Metadata for a single curator loaded from YAML. |
|
Logo URLs for a vault curator. |
|
Curator metadata as exported to JSON for R2 upload. |
- class CuratorInfo
Bases:
TypedDictMetadata for a single curator loaded from YAML.
Represents the in-memory view of a curator feeder file from
eth_defi/data/feeds/curators/.- __init__(*args, **kwargs)
- __new__(**kwargs)
- clear()
Remove all items from the dict.
- copy()
Return a shallow copy of the dict.
- fromkeys(value=None, /)
Create a new dictionary with keys from iterable and values set to value.
- get(key, default=None, /)
Return the value for key if key is in the dictionary, else default.
- items()
Return a set-like object providing a view on the dict’s items.
- keys()
Return a set-like object providing a view on the dict’s keys.
- pop(k[, d]) v, remove specified key and return the corresponding value.
If the key is not found, return the default if given; otherwise, raise a KeyError.
- popitem()
Remove and return a (key, value) pair as a 2-tuple.
Pairs are returned in LIFO (last-in, first-out) order. Raises KeyError if the dict is empty.
- setdefault(key, default=None, /)
Insert key with a value of default if key is not in the dictionary.
Return the value for key if key is in the dictionary, else default.
- update([E, ]**F) None. Update D from mapping/iterable E and F.
If E is present and has a .keys() method, then does: for k in E.keys(): D[k] = E[k] If E is present and lacks a .keys() method, then does: for k, v in E: D[k] = v In either case, this is followed by: for k in F: D[k] = F[k]
- values()
Return an object providing a view on the dict’s values.
- class CuratorLogos
Bases:
TypedDictLogo URLs for a vault curator.
Logo URLs point to 256x256 PNG files in R2 storage.
Noneif the logo variant is not available.- __init__(*args, **kwargs)
- __new__(**kwargs)
- clear()
Remove all items from the dict.
- copy()
Return a shallow copy of the dict.
- fromkeys(value=None, /)
Create a new dictionary with keys from iterable and values set to value.
- get(key, default=None, /)
Return the value for key if key is in the dictionary, else default.
- items()
Return a set-like object providing a view on the dict’s items.
- keys()
Return a set-like object providing a view on the dict’s keys.
- pop(k[, d]) v, remove specified key and return the corresponding value.
If the key is not found, return the default if given; otherwise, raise a KeyError.
- popitem()
Remove and return a (key, value) pair as a 2-tuple.
Pairs are returned in LIFO (last-in, first-out) order. Raises KeyError if the dict is empty.
- setdefault(key, default=None, /)
Insert key with a value of default if key is not in the dictionary.
Return the value for key if key is in the dictionary, else default.
- update([E, ]**F) None. Update D from mapping/iterable E and F.
If E is present and has a .keys() method, then does: for k in E.keys(): D[k] = E[k] If E is present and lacks a .keys() method, then does: for k, v in E: D[k] = v In either case, this is followed by: for k in F: D[k] = F[k]
- values()
Return an object providing a view on the dict’s values.
- class CuratorMetadata
Bases:
TypedDictCurator metadata as exported to JSON for R2 upload.
This is the public API shape consumed by the frontend. Twitter and LinkedIn fields are expanded to full URLs rather than bare handles/identifiers.
- __init__(*args, **kwargs)
- __new__(**kwargs)
- clear()
Remove all items from the dict.
- copy()
Return a shallow copy of the dict.
- fromkeys(value=None, /)
Create a new dictionary with keys from iterable and values set to value.
- get(key, default=None, /)
Return the value for key if key is in the dictionary, else default.
- items()
Return a set-like object providing a view on the dict’s items.
- keys()
Return a set-like object providing a view on the dict’s keys.
- pop(k[, d]) v, remove specified key and return the corresponding value.
If the key is not found, return the default if given; otherwise, raise a KeyError.
- popitem()
Remove and return a (key, value) pair as a 2-tuple.
Pairs are returned in LIFO (last-in, first-out) order. Raises KeyError if the dict is empty.
- setdefault(key, default=None, /)
Insert key with a value of default if key is not in the dictionary.
Return the value for key if key is in the dictionary, else default.
- update([E, ]**F) None. Update D from mapping/iterable E and F.
If E is present and has a .keys() method, then does: for k in E.keys(): D[k] = E[k] If E is present and lacks a .keys() method, then does: for k, v in E: D[k] = v In either case, this is followed by: for k in F: D[k] = F[k]
- values()
Return an object providing a view on the dict’s values.
- build_curator_index(public_url='')
Build the aggregate curator metadata index.
Loads all curator YAML files and appends synthetic entries for protocol-curated slugs. The result is suitable for JSON serialisation and R2 upload as
curator-metadata/index.json.- Parameters
public_url (str) – Public base URL for constructing logo URLs.
- Returns
List of
CuratorMetadatadicts for all known curators.- Return type
- build_curator_metadata_json(yaml_path, public_url='')
Build a
CuratorMetadatadict from a curator YAML file.Twitter handles are expanded to full
https://x.com/{handle}URLs. LinkedIn company identifiers are expanded to fullhttps://www.linkedin.com/company/{id}URLs.- Parameters
yaml_path (pathlib.Path) – Path to a curator YAML file.
public_url (str) – Public base URL for constructing logo URLs.
- Returns
Metadata dict ready for JSON serialisation.
- Return type
- get_curator_available_logos(slug)
Check which logo variants are available for a curator.
Curator and vault protocol logos share
eth_defi/data/vaults/formatted_logos/{slug}/.
- get_curator_name(slug)
Look up the human-readable name for a curator slug.
Handles both third-party curators (looked up from YAML) and protocol-curated slugs (looked up from
PROTOCOL_CURATOR_NAMES).- Parameters
slug (str) – Curator slug as returned by
identify_curator().- Returns
Human-readable curator name, or
Noneif not found.- Return type
- identify_curator(chain_id, vault_token_symbol, vault_name, vault_address, protocol_slug='', manager_name='')
Identify the curator managing a vault.
Checks protocol-curated status first (by protocol slug and vault address), then falls back to word-boundary regex matching against the vault display name and the manager name.
Some native marketplace protocols (notably GRVT) brand the curator in a separate
manager_namefield rather than the vault display name — the vault name there is the strategy name (e.g."Ethereum Moving Average Long/Short") while the curator identity (e.g."Gerhard - Bitcoin Strategy") is the manager. Passmanager_nameso these curators are detected. The vault name is matched first and takes precedence over the manager name.- Parameters
chain_id (int) – Chain ID where the vault is deployed.
vault_token_symbol (str) – The vault’s share token symbol (e.g.
"gtUSDC").vault_name (str) – The vault’s human-readable display name, which curators typically brand with their organisation name.
vault_address (str) – The vault’s on-chain address (hex or synthetic format).
protocol_slug (str) – Slugified protocol name from
eth_defi.research.vault_metrics.slugify_protocol()(e.g."morpho","hyperliquid","lighter").manager_name (str) – Optional name of the vault manager/operator, used by native marketplace protocols (e.g. GRVT) where the curator brand lives in the manager field rather than the vault name. Empty string when unknown.
- Returns
Curator slug (e.g.
"gauntlet","ostium","hyperliquid"), orNoneif no curator could be identified. For protocol-curated vaults the protocol slug itself is returned. Useis_protocol_curator()to distinguish protocol-curated from third-party curators.- Return type
- is_protocol_curator(slug)
Check whether a curator slug represents a protocol-curated vault.
Protocol-curated means the protocol itself operates the vault rather than a third-party risk manager.
- Parameters
slug (str) – Curator slug as returned by
identify_curator().- Returns
Trueif the slug identifies a protocol acting as its own curator.- Return type
- load_curator_map()
Load all curator metadata from YAML files.
Returns a dict mapping slug to
CuratorInfo. Cached in-process after first call (same pattern aseth_defi.stablecoin_metadata.load_all_stablecoin_metadata()).- Returns
Dict keyed by curator slug.
- Return type
- process_and_upload_curator_metadata(yaml_path, bucket_name, endpoint_url, access_key_id, secret_access_key, public_url='', key_prefix='')
Process and upload a single curator’s metadata and logos to R2.
Uploads:
curator-metadata/{key_prefix}{slug}/metadata.json— JSON metadatacurator-metadata/{key_prefix}{slug}/{variant}.png— 256x256 logo
- Parameters
yaml_path (pathlib.Path) – Path to the curator YAML file.
bucket_name (str) – R2 bucket name.
endpoint_url (str) – R2 API endpoint URL.
access_key_id (str) – R2 access key ID.
secret_access_key (str) – R2 secret access key.
public_url (str) – Public base URL for constructing logo URLs in metadata.
key_prefix (str) – Optional prefix for R2 keys (e.g.
"test-"for testing).
- Returns
The processed
CuratorMetadata.- Return type
- upload_curator_index(bucket_name, endpoint_url, access_key_id, secret_access_key, public_url='', key_prefix='')
Build and upload the aggregate curator index to R2.
Uploads to
curator-metadata/{key_prefix}index.json.- Parameters
- Returns
The full index list.
- Return type
- upload_protocol_curator_metadata(bucket_name, endpoint_url, access_key_id, secret_access_key, public_url='', key_prefix='')
Upload metadata entries for all protocol-curated slugs to R2.
Ensures that
curator-metadata/{slug}/metadata.jsonexists for every protocol inALL_PROTOCOL_CURATOR_SLUGSso that frontend slug lookups never 404.- Parameters
- Returns
List of uploaded
CuratorMetadataentries.- Return type