feat: add Pyth Express Relay, Core, and Pro fee adapters#5776
feat: add Pyth Express Relay, Core, and Pro fee adapters#5776pythia-assistant wants to merge 8 commits intoDefiLlama:masterfrom
Conversation
- Pyth Express Relay: Tracks SOL/USDC fees from MEV auctions on Solana - Pyth Pro: Tracks USDC payments from Douro Labs to Pyth DAO (60% revenue share) - Pyth Core: Tracks price feed update fees across major EVM chains
📝 WalkthroughWalkthroughAdds three new Pyth fee adapters: a multi-chain on-chain adapter (Pyth Core) computing per-update fees across many EVM and non‑EVM chains, plus two Solana adapters (Pyth Express Relay, Pyth Pro) that aggregate SOL/USDC receipts to report daily fees and revenue. Changes
Sequence Diagram(s)sequenceDiagram
participant Client
participant Adapter
participant Fetcher as ChainFetcher
participant Data as Blockchain/Allium
Client->>Adapter: request fees (chain, timestamp)
Adapter->>Fetcher: invoke chain-specific fetch
Fetcher->>Data: query logs / Allium / RPC / events
Data-->>Fetcher: return events / transfers / balances
Fetcher-->>Adapter: dailyFees / dailyRevenue (or zeros on error)
Adapter-->>Client: return result
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes Poem
🚥 Pre-merge checks | ✅ 2 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing touches
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 2
🤖 Fix all issues with AI agents
In `@fees/pyth-core/index.ts`:
- Around line 38-40: The early return and catch block return a raw number object
instead of the required FetchResult with Balances; update both the config check
and the catch handler to return an object shaped like { dailyFees: { value: 0 },
dailyRevenue: { value: 0 } } (or the correct Balances shape used in this module)
so they match the Promise<FetchResult> signature and the success path; locate
the returns near the config check and the catch block (referenced by FetchResult
and Balances in this file) and replace the numeric literal returns with properly
structured Balances objects.
- Around line 20-25: Duplicate chain entry: CHAIN.ZKSYNC duplicates CHAIN.ERA
causing double counting; remove the obsolete CHAIN.ZKSYNC entry from the
mapping. Locate the object that maps chain constants (contains CHAIN.ZKSYNC and
CHAIN.ERA with contract "0xf087c864AEccFb6A2Bf1Af6A0382B0d0f6c5D834") and delete
the CHAIN.ZKSYNC key-value pair so only CHAIN.ERA remains as the canonical
zkSync Era configuration.
🧹 Nitpick comments (5)
fees/pyth-express-relay/index.ts (1)
9-14: Consider filtering to SOL and USDC explicitly.The comment states "Track all tokens (SOL and USDC)" but
getSolanaReceivedis called without amintsfilter, meaning all tokens received at the DAO address will be counted. If only SOL and USDC auction fees should be tracked, consider adding themintsparameter:const dailyFees = await getSolanaReceived({ options, target: EXPRESS_RELAY_DAO_ADDRESS, mints: [ADDRESSES.solana.SOL, ADDRESSES.solana.USDC], // filter to expected tokens });If tracking all received tokens is intentional, update the comment to reflect that.
fees/pyth-pro/index.ts (2)
6-10: Remove unusedUSDC_MINTconstant.
USDC_MINTis defined on line 10 but never used — line 32 usesADDRESSES.solana.USDCinstead. Either use the constant consistently or remove it.♻️ Suggested fix
// Douro Labs is the official Pyth Pro data distributor // They pay 60% of subscription revenue to the Pyth DAO const DOURO_LABS_ADDRESS = "C6G3jRs1SD7GSNxvKNHJZy7aSar7eZiLioPpDRFFtKTf"; const PYTH_DAO_ADDRESS = "5Unq3fgfSNdyeGjiq2Pu5XAQUJWo2rauKGErbUyxqUGe"; -const USDC_MINT = "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v";
46-56: Consider addingisExpensiveAdapter: truefor consistency.The
pyth-express-relayadapter marks itself asisExpensiveAdapter: truesince it queries Allium. This adapter also queries Allium, so consider adding the same flag for consistency.♻️ Suggested addition
const adapter: SimpleAdapter = { version: 1, fetch, chains: [CHAIN.SOLANA], start: "2024-01-01", dependencies: [Dependencies.ALLIUM], + isExpensiveAdapter: true, methodology: {fees/pyth-core/index.ts (2)
31-32: Remove unusedGET_UPDATE_FEE_ABIconstant.
GET_UPDATE_FEE_ABIis defined but never used. If there's a plan to call the contract to get actual fee amounts (which would be more accurate than the hardcoded estimate), consider implementing it; otherwise remove the dead code.♻️ Suggested fix
// Event emitted when price feeds are updated const PRICE_FEED_UPDATE_ABI = "event PriceFeedUpdate(bytes32 indexed id, uint64 publishTime, int64 price, uint64 conf)"; - -// ABI to get update fee -const GET_UPDATE_FEE_ABI = "function getUpdateFee(bytes[] calldata updateData) external view returns (uint feeAmount)";
57-62: Fee estimation is a rough approximation.The hardcoded
feePerUpdateof 0.0001 native token applies uniformly across all chains despite the comment noting "varies by chain." This estimation may significantly diverge from actual fees paid, especially on chains with different gas cost structures.Consider:
- Using chain-specific fee estimates in
chainConfig- Calling the
getUpdateFeecontract method (the ABI is already defined) to get actual fee amounts- Alternatively, documenting this limitation in the methodology
- Fixed contract addresses to match official Pyth documentation - Added: 0G, Camp, Plasma, Eventum, zkFair, Cronos zkEVM - Updated: Abstract, Chiliz, Cronos, Filecoin, HyperEVM, IOTA, KCC, OpBNB, Polygon zkEVM, Polynomial, Sei, Story, Swell, Worldchain
- Remove section comments, list chains in a row - Fix return types to use proper Balances objects instead of raw numbers
- Added feePerUpdateByChain map from official docs - Aurora: 0.000003 ETH, Avalanche: 0.00025 AVAX, Conflux: 0.1 CFX - Cronos: 0.06 CRO, Meter: 0.02 MTR, opBNB: 0.000186 BNB - Ronin: 0.001 RON, Sei: 0.01 SEI, Shimmer: 1 SMR - Swell: 0.00005 ETH, Worldchain: 0.00001 ETH - Default: 1 wei for all other chains - Count actual PriceFeedUpdate events instead of unique txs
- Solana: Track fees via getSolanaReceived on fee address 8hQfT7SVhkCrzUSgBq6u2wYEt1sH3xmofZ5ss3YaydZW - Sui: Query balance changes from Pyth package events via Allium - Aptos: Query fungible_asset deposits to Pyth contract via Allium - Near: Query deposits to pyth-oracle.near via Allium Note: Injective CosmWasm not yet supported (would need separate handling)
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Fix all issues with AI agents
In `@fees/pyth-core/index.ts`:
- Around line 149-171: The fetchSui function is over-counting by summing
ABS(amount); instead identify the Pyth fee receiver (fee vault) and change the
SQL to only sum positive inflows into that address (e.g., WHERE
recipient_address = '<PYTH_FEE_VAULT>' AND amount > 0) instead of using
ABS(amount), then use that summed value when calling dailyFees.addCGToken("sui",
total_fees / 1e9). Update or add a constant for the Pyth fee vault (referenced
alongside SUI_PYTH_PACKAGE) and adjust the query in fetchSui to filter by that
recipient and positive amounts so only actual fee inflows are counted.
- Replace SUI_PYTH_PACKAGE with SUI_FEE_RECIPIENT address - Query inflows to fee recipient directly instead of summing all balance changes - Fixes potential over-counting issue flagged by CodeRabbit
|
The pyth-core adapter exports: |
There was a problem hiding this comment.
Actionable comments posted: 2
🤖 Fix all issues with AI agents
In `@fees/pyth-core/index.ts`:
- Around line 149-166: fetchSui is summing positive balance_changes for
SUI_FEE_RECIPIENT without restricting to SUI coin types and is using date-only
strings which lose intraday precision; update the SQL built in fetchSui (the
query passed to queryAllium) to (1) add a coin type filter (e.g. coin_type =
'0x2::sui::SUI' or the project’s canonical SUI coin_type) alongside owner =
SUI_FEE_RECIPIENT, and (2) replace the date-only comparisons with full-timestamp
comparisons using TO_TIMESTAMP_NTZ() on the UNIX timestamps derived from
options.startTimestamp/options.endTimestamp so checkpoint_timestamp windowing
preserves time-of-day; ensure dailyFees.addCGToken("sui", ...) still converts
the returned sum from base units as before.
- Around line 176-191: The SQL in fetchAptos currently sums all
fungible_asset_activities for APTOS_PYTH_CONTRACT and can overcount non-APT
tokens; update the query string (variable query in function fetchAptos) to
include the asset filter AND asset_type = '0x1::aptos_coin::AptosCoin' (keeping
the existing owner/address, activity_type, and timestamp filters) so that
dailyFees.addCGToken("aptos", res[0].total_fees / 1e8) only uses APT deposits
between options.startTimestamp and options.endTimestamp.
…ix fetch signatures - SUI: add coin_type filter for 0x2::sui::SUI, use TO_TIMESTAMP_NTZ for proper precision - Aptos: add asset_type filter for 0x1::aptos_coin::AptosCoin - All non-EVM fetch functions: fix signature to (options: FetchOptions) for consistency
|
The pyth-core adapter exports: |
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Fix all issues with AI agents
In `@fees/pyth-core/index.ts`:
- Around line 7-79: evmChainConfig contains entries using undefined chain
constants (e.g., CHAIN.BITTENSOR, CHAIN.GNOSIS, CHAIN.SKATE, CHAIN.SUPERSEED,
CHAIN.SWELL, CHAIN.VICTION, CHAIN.WORLDCHAIN) which produce undefined keys and
break adapter validation; fix by either adding those missing CHAIN constants to
helpers/chains.ts (with the canonical string labels used across the codebase) or
by removing/renaming the corresponding entries from evmChainConfig so only
defined CHAIN.* symbols remain, and then run validation to confirm no "Invalid
chain labels: undefined" errors.
| const evmChainConfig: Record<string, { start: string; contract: string }> = { | ||
| [CHAIN.OG]: { start: "2024-06-01", contract: "0x2880ab155794e7179c9ee2e38200202908c17b43" }, | ||
| [CHAIN.ETHEREUM]: { start: "2023-07-01", contract: "0x4305FB66699C3B2702D4d05CF36551390A4c69C6" }, | ||
| [CHAIN.AVAX]: { start: "2023-07-01", contract: "0x4305FB66699C3B2702D4d05CF36551390A4c69C6" }, | ||
| [CHAIN.BSC]: { start: "2023-07-01", contract: "0x4D7E825f80bDf85e913E0DD2A2D54927e9dE1594" }, | ||
| [CHAIN.POLYGON]: { start: "2023-07-01", contract: "0xff1a0f4744e8582DF1aE09D5611b887B6a12925C" }, | ||
| [CHAIN.CELO]: { start: "2023-07-01", contract: "0xff1a0f4744e8582DF1aE09D5611b887B6a12925C" }, | ||
| [CHAIN.GNOSIS]: { start: "2023-07-01", contract: "0x2880aB155794e7179c9eE2e38200202908C17B43" }, | ||
| [CHAIN.AURORA]: { start: "2023-07-01", contract: "0xF89C7b475821EC3fDC2dC8099032c05c6c0c9AB9" }, | ||
| [CHAIN.KAVA]: { start: "2023-07-01", contract: "0xA2aa501b19aff244D90cc15a4Cf739D2725B5729" }, | ||
| [CHAIN.CRONOS]: { start: "2023-07-01", contract: "0xE0d0e68297772Dd5a1f1D99897c581E2082dbA5B" }, | ||
| [CHAIN.CONFLUX]: { start: "2023-07-01", contract: "0xe9d69CdD6Fe41e7B621B4A688C5D1a68cB5c8ADc" }, | ||
| [CHAIN.METER]: { start: "2023-07-01", contract: "0xbFe3f445653f2136b2FD1e6DdDb5676392E3AF16" }, | ||
| [CHAIN.WEMIX]: { start: "2023-07-01", contract: "0xA2aa501b19aff244D90cc15a4Cf739D2725B5729" }, | ||
| [CHAIN.KLAYTN]: { start: "2023-07-01", contract: "0x2880ab155794e7179c9ee2e38200202908c17b43" }, | ||
| [CHAIN.HEDERA]: { start: "2023-07-01", contract: "0xA2aa501b19aff244D90cc15a4Cf739D2725B5729" }, | ||
| [CHAIN.BITTORRENT]: { start: "2023-07-01", contract: "0xA2aa501b19aff244D90cc15a4Cf739D2725B5729" }, | ||
| [CHAIN.CORE]: { start: "2023-07-01", contract: "0xA2aa501b19aff244D90cc15a4Cf739D2725B5729" }, | ||
| [CHAIN.KCC]: { start: "2023-07-01", contract: "0xE0d0e68297772Dd5a1f1D99897c581E2082dbA5B" }, | ||
| [CHAIN.FLOW]: { start: "2023-10-01", contract: "0x2880aB155794e7179c9eE2e38200202908C17B43" }, | ||
| [CHAIN.FILECOIN]: { start: "2024-03-01", contract: "0xA2aa501b19aff244D90cc15a4Cf739D2725B5729" }, | ||
| [CHAIN.BITTENSOR]: { start: "2024-06-01", contract: "0x2880aB155794e7179c9eE2e38200202908C17B43" }, | ||
| [CHAIN.ARBITRUM]: { start: "2023-07-01", contract: "0xff1a0f4744e8582DF1aE09D5611b887B6a12925C" }, | ||
| [CHAIN.OPTIMISM]: { start: "2023-07-01", contract: "0xff1a0f4744e8582DF1aE09D5611b887B6a12925C" }, | ||
| [CHAIN.BASE]: { start: "2023-08-01", contract: "0x8250f4aF4B972684F7b336503E2D6dFeDeB1487a" }, | ||
| [CHAIN.BLAST]: { start: "2024-02-01", contract: "0xA2aa501b19aff244D90cc15a4Cf739D2725B5729" }, | ||
| [CHAIN.LINEA]: { start: "2023-08-01", contract: "0xA2aa501b19aff244D90cc15a4Cf739D2725B5729" }, | ||
| [CHAIN.MANTLE]: { start: "2023-08-01", contract: "0xA2aa501b19aff244D90cc15a4Cf739D2725B5729" }, | ||
| [CHAIN.SCROLL]: { start: "2023-10-01", contract: "0xA2aa501b19aff244D90cc15a4Cf739D2725B5729" }, | ||
| [CHAIN.MANTA]: { start: "2024-01-01", contract: "0xA2aa501b19aff244D90cc15a4Cf739D2725B5729" }, | ||
| [CHAIN.MODE]: { start: "2024-01-01", contract: "0xA2aa501b19aff244D90cc15a4Cf739D2725B5729" }, | ||
| [CHAIN.ERA]: { start: "2023-08-01", contract: "0xf087c864AEccFb6A2Bf1Af6A0382B0d0f6c5D834" }, | ||
| [CHAIN.POLYGON_ZKEVM]: { start: "2023-07-01", contract: "0xC5E56d6b40F3e3B5fbfa266bCd35C37426537c65" }, | ||
| [CHAIN.OP_BNB]: { start: "2023-09-01", contract: "0x2880aB155794e7179c9eE2e38200202908C17B43" }, | ||
| [CHAIN.BOBA]: { start: "2023-07-01", contract: "0x4374e5a8b9C22271E9EB878A2AA31DE97DF15DAF" }, | ||
| [CHAIN.NEON]: { start: "2023-09-01", contract: "0x7f2dB085eFC3560AFF33865dD727225d91B4f9A5" }, | ||
| [CHAIN.SHIMMER_EVM]: { start: "2023-10-01", contract: "0xA2aa501b19aff244D90cc15a4Cf739D2725B5729" }, | ||
| [CHAIN.RONIN]: { start: "2024-01-01", contract: "0x2880aB155794e7179c9eE2e38200202908C17B43" }, | ||
| [CHAIN.LIGHTLINK_PHOENIX]: { start: "2024-01-01", contract: "0xA2aa501b19aff244D90cc15a4Cf739D2725B5729" }, | ||
| [CHAIN.ETHERLINK]: { start: "2024-06-01", contract: "0x2880aB155794e7179c9eE2e38200202908C17B43" }, | ||
| [CHAIN.POLYNOMIAL]: { start: "2024-01-01", contract: "0x2880aB155794e7179c9eE2e38200202908C17B43" }, | ||
| [CHAIN.ZETA]: { start: "2024-01-01", contract: "0x2880aB155794e7179c9eE2e38200202908C17B43" }, | ||
| [CHAIN.MERLIN]: { start: "2024-04-01", contract: "0xA2aa501b19aff244D90cc15a4Cf739D2725B5729" }, | ||
| [CHAIN.VICTION]: { start: "2024-01-01", contract: "0xA2aa501b19aff244D90cc15a4Cf739D2725B5729" }, | ||
| [CHAIN.CHILIZ]: { start: "2024-03-01", contract: "0xA2aa501b19aff244D90cc15a4Cf739D2725B5729" }, | ||
| [CHAIN.SEI]: { start: "2024-01-01", contract: "0x2880aB155794e7179c9eE2e38200202908C17B43" }, | ||
| [CHAIN.BERACHAIN]: { start: "2025-01-01", contract: "0x2880aB155794e7179c9eE2e38200202908C17B43" }, | ||
| [CHAIN.SONIC]: { start: "2024-12-01", contract: "0x2880aB155794e7179c9eE2e38200202908C17B43" }, | ||
| [CHAIN.ABSTRACT]: { start: "2024-11-01", contract: "0x8739d5024B5143278E2b15Bd9e7C26f6CEc658F1" }, | ||
| [CHAIN.APECHAIN]: { start: "2024-10-01", contract: "0x2880aB155794e7179c9eE2e38200202908C17B43" }, | ||
| [CHAIN.UNICHAIN]: { start: "2024-11-01", contract: "0x2880aB155794e7179c9eE2e38200202908C17B43" }, | ||
| [CHAIN.HYPERLIQUID]: { start: "2024-12-01", contract: "0xe9d69CdD6Fe41e7B621B4A688C5D1a68cB5c8ADc" }, | ||
| [CHAIN.SONEIUM]: { start: "2025-01-01", contract: "0x2880aB155794e7179c9eE2e38200202908C17B43" }, | ||
| [CHAIN.WORLDCHAIN]: { start: "2024-10-01", contract: "0xe9d69cdd6fe41e7b621b4a688c5d1a68cb5c8adc" }, | ||
| [CHAIN.INK]: { start: "2024-12-01", contract: "0x2880aB155794e7179c9eE2e38200202908C17B43" }, | ||
| [CHAIN.GRAVITY]: { start: "2024-06-01", contract: "0x2880aB155794e7179c9eE2e38200202908C17B43" }, | ||
| [CHAIN.MORPH]: { start: "2024-10-01", contract: "0x2880aB155794e7179c9eE2e38200202908C17B43" }, | ||
| [CHAIN.TAIKO]: { start: "2024-06-01", contract: "0x2880aB155794e7179c9eE2e38200202908C17B43" }, | ||
| [CHAIN.STORY]: { start: "2025-01-01", contract: "0xD458261E832415CFd3BAE5E416FdF3230ce6F134" }, | ||
| [CHAIN.HEMI]: { start: "2024-10-01", contract: "0x2880aB155794e7179c9eE2e38200202908C17B43" }, | ||
| [CHAIN.SWELL]: { start: "2024-12-01", contract: "0xDd24F84d36BF92C65F92307595335bdFab5Bbd21" }, | ||
| [CHAIN.IOTA]: { start: "2024-06-01", contract: "0x8D254a21b3C86D32F7179855531CE99164721933" }, | ||
| [CHAIN.MEZO]: { start: "2024-09-01", contract: "0x2880aB155794e7179c9eE2e38200202908C17B43" }, | ||
| [CHAIN.SKATE]: { start: "2024-10-01", contract: "0x2880aB155794e7179c9eE2e38200202908C17B43" }, | ||
| [CHAIN.SUPERSEED]: { start: "2024-12-01", contract: "0x2880aB155794e7179c9eE2e38200202908C17B43" }, | ||
| [CHAIN.MONAD]: { start: "2025-01-01", contract: "0x2880aB155794e7179c9eE2e38200202908C17B43" }, | ||
| [CHAIN.INJECTIVE]: { start: "2024-06-01", contract: "0x36825bf3Fbdf5a29E2d5148bfe7Dcf7B5639e320" }, | ||
| [CHAIN.CRONOS_ZKEVM]: { start: "2024-06-01", contract: "0x056f829183Ec806A78c26C98961678c24faB71af" }, | ||
| [CHAIN.ZKFAIR]: { start: "2024-01-01", contract: "0xA2aa501b19aff244D90cc15a4Cf739D2725B5729" }, | ||
| [CHAIN.CAMP]: { start: "2024-06-01", contract: "0x2880aB155794e7179c9eE2e38200202908C17B43" }, | ||
| [CHAIN.PLASMA]: { start: "2024-06-01", contract: "0x2880aB155794e7179c9eE2e38200202908C17B43" }, | ||
| [CHAIN.EVENTUM]: { start: "2024-06-01", contract: "0x2880aB155794e7179c9eE2e38200202908C17B43" }, | ||
| }; |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
# Extract CHAIN keys from fees/pyth-core/index.ts and helpers/chains.ts, then compare
python3 << 'PY'
import re
import pathlib
# Read the fees/pyth-core/index.ts file
config_file = pathlib.Path("fees/pyth-core/index.ts")
if not config_file.exists():
print("ERROR: fees/pyth-core/index.ts not found")
exit(1)
config_text = config_file.read_text()
# Extract all CHAIN.* references from the config file
used_chains = sorted(set(re.findall(r'\[CHAIN\.([A-Z0-9_]+)\]', config_text)))
print("=== CHAIN keys used in fees/pyth-core/index.ts ===")
print(f"Total unique chains: {len(used_chains)}")
print("Chains:", used_chains[:10], "..." if len(used_chains) > 10 else "")
# Read the helpers/chains.ts file
helpers_file = pathlib.Path("helpers/chains.ts")
if not helpers_file.exists():
print("\nERROR: helpers/chains.ts not found")
exit(1)
helpers_text = helpers_file.read_text()
# Extract CHAIN enum/constant definitions
# Look for patterns like: ETHEREUM = "...", or enum CHAIN { ETHEREUM = "..." }
defined_chains = set(re.findall(r'^\s*([A-Z0-9_]+)\s*[=:]', helpers_text, re.MULTILINE))
print(f"\n=== CHAIN keys defined in helpers/chains.ts ===")
print(f"Total defined chains: {len(defined_chains)}")
# Find missing chains
missing = sorted([k for k in used_chains if k not in defined_chains])
print(f"\n=== Missing chains ===")
if missing:
print(f"Count: {len(missing)}")
print("Missing chains:", missing)
else:
print("None - all chains are defined!")
# Show some context for the first few chains
print(f"\n=== Sample verification (first 3 used chains) ===")
for chain in used_chains[:3]:
status = "✓ DEFINED" if chain in defined_chains else "✗ MISSING"
print(f"{chain}: {status}")
PYRepository: DefiLlama/dimension-adapters
Length of output: 582
Resolve 7 undefined chain labels in evmChainConfig.
The config references these chains that are not defined in helpers/chains.ts: BITTENSOR, GNOSIS, SKATE, SUPERSEED, SWELL, VICTION, and WORLDCHAIN. These undefined constants create undefined keys in the mapping, causing the adapter validation error "Invalid chain labels: undefined". Either add the missing constants to helpers/chains.ts or remove/rename these entries from the config.
🤖 Prompt for AI Agents
In `@fees/pyth-core/index.ts` around lines 7 - 79, evmChainConfig contains entries
using undefined chain constants (e.g., CHAIN.BITTENSOR, CHAIN.GNOSIS,
CHAIN.SKATE, CHAIN.SUPERSEED, CHAIN.SWELL, CHAIN.VICTION, CHAIN.WORLDCHAIN)
which produce undefined keys and break adapter validation; fix by either adding
those missing CHAIN constants to helpers/chains.ts (with the canonical string
labels used across the codebase) or by removing/renaming the corresponding
entries from evmChainConfig so only defined CHAIN.* symbols remain, and then run
validation to confirm no "Invalid chain labels: undefined" errors.
Summary
Adds fee tracking adapters for three Pyth Network products:
Pyth Express Relay
69ib85nGQS2Hzr4tQ8twbkGh76gKFUfWJFeJfQ37R3hWPyth Pro (formerly Lazer)
C6G3jRs1SD7GSNxvKNHJZy7aSar7eZiLioPpDRFFtKTf) to Pyth DAO (5Unq3fgfSNdyeGjiq2Pu5XAQUJWo2rauKGErbUyxqUGe)Pyth Core
Related
Summary by CodeRabbit
New Features
Notes