erc_4626.vault_protocol.ipor.offchain_metadata

Documentation for eth_defi.erc_4626.vault_protocol.ipor.offchain_metadata Python module.

IPOR vault offchain metadata.

  • IPOR stores vault descriptions, logos and optional atomist names in a public S3-backed JSON file at api.ipor.io

  • We reverse-engineered the IPOR Fusion React SPA and discovered the /fusion/vaults-customization-list endpoint that serves vault metadata including descriptions, logos, links and optional curatorName values

  • The frontend bundle also contains the public IPOR app vault configuration. We parse only the address-keyed atomist values from this bundle, because production API rows currently expose curatorName sparsely.

  • Vault accessors fetch this metadata lazily on first access and then reuse the local disk cache and module-level in-process cache where available.

Data flow in the IPOR frontend

The vault info page loads descriptions from two sources and merges them:

description = customization?.description ?? config?.description

Where customization comes from the API and config is hardcoded in the JS bundle. Descriptions come from the API customisation source. Manager names prefer API curatorName and fall back to the frontend atomist value.

Reference:

  • IPOR Fusion app

  • API base URL: https://api.ipor.io

  • Customisation endpoint: GET /fusion/vaults-customization-list

Functions

fetch_ipor_atomist_names([cache_path, ...])

Fetch known IPOR atomist names for curator maintenance checks.

fetch_ipor_customisation_list([cache_path, ...])

Fetch and cache the IPOR vault customisation list.

fetch_ipor_frontend_atomists([cache_path, ...])

Fetch and cache IPOR frontend atomist metadata.

fetch_ipor_vault_atomist(web3, vault_address, *)

Fetch an IPOR vault atomist display name.

fetch_ipor_vault_metadata(web3, vault_address)

Fetch vault metadata from IPOR's offchain customisation API.

Classes

IPORVaultMetadata

Metadata about an IPOR vault from the offchain customisation API.

class IPORVaultMetadata

Bases: TypedDict

Metadata about an IPOR vault from the offchain customisation API.

Fetched from api.ipor.io/fusion/vaults-customization-list. Discovered by reverse-engineering the IPOR Fusion React SPA JavaScript bundles.

The customisation endpoint returns a flat JSON array. Each entry corresponds to a vault that has had its metadata edited by the vault’s atomist (operator). Not all IPOR vaults have customisation entries — only those whose atomists have set descriptions via the IPOR frontend.

Reference:

__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.

fetch_ipor_atomist_names(cache_path=PosixPath('/home/runner/.tradingstrategy/cache/ipor'), api_base_url='https://api.ipor.io', app_base_url='https://app.ipor.io', now_=None, max_cache_duration=datetime.timedelta(days=2))

Fetch known IPOR atomist names for curator maintenance checks.

This helper is for audits and tests that need the set of IPOR manager names, not a vault-specific lookup. Vault accessors should call fetch_ipor_vault_atomist() instead.

Parameters
Returns

Set of atomist display names IPOR exposes through API or frontend data.

Return type

set[str]

fetch_ipor_customisation_list(cache_path=PosixPath('/home/runner/.tradingstrategy/cache/ipor'), api_base_url='https://api.ipor.io', now_=None, max_cache_duration=datetime.timedelta(days=2))

Fetch and cache the IPOR vault customisation list.

The API returns a single JSON array covering all chains. We index by (chain_id, checksummed_address) for fast lookup.

  • Single JSON cache file for all chains

  • Multiprocess safe via file lock

Parameters
  • cache_path (pathlib.Path) – Directory for cache files (default ~/.tradingstrategy/cache/ipor/)

  • api_base_url (str) – IPOR data API base URL

  • now – Override current time (for testing)

  • max_cache_duration (datetime.timedelta) – How long before refreshing cache (default 2 days)

  • now_ (Optional[datetime.datetime]) –

Returns

Dict mapping (chain_id, checksummed_address) to IPORVaultMetadata

Return type

dict[tuple[int, str], eth_defi.erc_4626.vault_protocol.ipor.offchain_metadata.IPORVaultMetadata]

fetch_ipor_frontend_atomists(cache_path=PosixPath('/home/runner/.tradingstrategy/cache/ipor'), app_base_url='https://app.ipor.io', now_=None, max_cache_duration=datetime.timedelta(days=2))

Fetch and cache IPOR frontend atomist metadata.

The cache stores only the parsed vault_address -> atomist mapping, not the full JavaScript bundle. If refresh fails but an older cache exists, the stale cache is returned so manager attribution does not disappear because of a transient app or CDN failure.

Parameters
Returns

Dict keyed by lower-case vault address.

Return type

dict[str, str]

fetch_ipor_vault_atomist(web3, vault_address, *, cache_path=PosixPath('/home/runner/.tradingstrategy/cache/ipor'), api_base_url='https://api.ipor.io', app_base_url='https://app.ipor.io', now_=None, max_cache_duration=datetime.timedelta(days=2))

Fetch an IPOR vault atomist display name.

This accessor-style helper mirrors other protocol offchain metadata modules: the first vault property access triggers the fetch, then the local disk cache and in-process cache are reused by later calls.

Parameters
  • web3 (web3.main.Web3) – Web3 instance used to get the EVM chain id.

  • vault_address (eth_typing.evm.HexAddress) – Vault contract address.

  • cache_path (pathlib.Path) – Directory for IPOR cache files.

  • api_base_url (str) – IPOR data API base URL.

  • app_base_url (str) – IPOR Fusion app base URL.

  • now – Override current time for tests.

  • max_cache_duration (datetime.timedelta) – Cache time-to-live.

  • now_ (Optional[datetime.datetime]) –

Returns

Atomist display name, or None if IPOR does not expose one.

Return type

Optional[str]

fetch_ipor_vault_metadata(web3, vault_address)

Fetch vault metadata from IPOR’s offchain customisation API.

  • Uses a two-level cache: in-process dict + disk cache

  • Returns None if the vault has no customisation entry (i.e. the atomist has not set a description via the IPOR frontend)

Parameters
  • web3 (web3.main.Web3) – Web3 instance (used to get chain_id and checksum address)

  • vault_address (eth_typing.evm.HexAddress) – Vault contract address

Returns

Metadata dict or None if the vault has no customisation entry

Return type

Optional[eth_defi.erc_4626.vault_protocol.ipor.offchain_metadata.IPORVaultMetadata]