-
Notifications
You must be signed in to change notification settings - Fork 4.4k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat: Pyth Data Plugin #2434
feat: Pyth Data Plugin #2434
Conversation
- Create new plugin for Pyth Data integration - Add EventSource client for price feeds - Configure plugin in agent - Update dependencies and configuration files This plugin enables real-time price feed data from Pyth Network, including price updates, TWAPs, and publisher caps information.
@coderabbitai review |
📝 WalkthroughWalkthroughThe pull request introduces a comprehensive Pyth Data Plugin for ElizaOS, expanding the system's capabilities for real-time price feed interactions. The changes span multiple files, adding robust error handling, validation mechanisms, and configuration options for retrieving and streaming cryptocurrency and asset price data from the Pyth Network. Changes
Finishing Touches
🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments. CodeRabbit Commands (Invoked using PR comments)
Other keywords and placeholders
CodeRabbit Configuration File (
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 11
🔭 Outside diff range comments (2)
agent/src/index.ts (2)
Line range hint
764-773
: ConsolidateverifiableInferenceAdapter
assignmentsAssigning
verifiableInferenceAdapter
multiple times may lead to unintended overwrites. Consider merging the conditions or prioritizing one adapter.
Line range hint
798-799
: Import missingdexScreenerPlugin
The
dexScreenerPlugin
is used but not imported, which will cause aReferenceError
. Ensure it's properly imported.Apply this diff to add the missing import:
+ import { dexScreenerPlugin } from "@elizaos/plugin-dexscreener";
🧹 Nitpick comments (25)
packages/plugin-pyth-data/src/utils/publisherCapsValidation.ts (1)
56-57
: Optimize schema compilationCompiling the schema inside
validatePublisherCapsData
on each call may impact performance. Move the schema compilation outside the function to reuse the validator.+const validate = ajv.compile(publisherCapsSchema); export async function validatePublisherCapsData(data: unknown): Promise<boolean> { try { - const validate = ajv.compile(publisherCapsSchema); const valid = validate(data);packages/plugin-pyth-data/src/actions/actionGetLatestPublisherCaps.ts (1)
17-17
: Avoid usingconsole.log
for loggingUsing
console.log
can lead to inconsistent logging practices. UseelizaLogger
for consistent and configurable logging.- console.log(`[PublisherCaps] ${message}`, data ? JSON.stringify(data, null, 2) : '');
packages/plugin-pyth-data/src/types/zodSchemas.ts (1)
17-17
: Enhance 'PriceIdInput' validation for price ID format.Currently,
PriceIdInput
accepts any string. Consider adding a regex pattern to enforce that price IDs are valid 64-character hexadecimal strings.packages/plugin-pyth-data/src/actions/actionGetLatestPriceUpdates.ts (2)
22-31
: Consolidate 'normalizePriceFeedId' and 'formatPriceFeedId' functions.Both functions perform the same operation of formatting the price feed ID. Merging them would eliminate redundancy.
112-117
: Refactor duplicate logic for extracting 'priceIds'.The code for extracting
priceIds
fromtext
is duplicated in bothvalidate
andhandler
methods. Consider creating a shared utility function to improve maintainability.Also applies to: 210-215
packages/plugin-pyth-data/src/actions/actionGetPriceUpdatesStream.ts (1)
19-20
: Remove redundant console loggingUsing both
elizaLogger.info
andconsole.log
duplicates log output. It's best to removeconsole.log
to keep logs clean and consistent.Apply this diff to remove the redundant
console.log
:- console.log(`[PriceUpdatesStream] ${message}`, data ? JSON.stringify(data, null, 2) : '');
agent/src/index.ts (2)
168-170
: Refactor key merging to enhance performanceUsing spread syntax in accumulators like
...Object.keys(baseObj || {})
can affect performance. Consider usingconcat
or a loop to merge keys efficiently.
81-83
: Remove duplicate importsImports for
OpacityAdapter
,openWeatherPlugin
, andstargazePlugin
are duplicated. Remove redundant imports to avoid confusion.Apply this diff to eliminate duplicates:
- import { OpacityAdapter } from "@elizaos/plugin-opacity"; - import { openWeatherPlugin } from "@elizaos/plugin-open-weather"; - import { quaiPlugin } from "@elizaos/plugin-quai";Also applies to: 102-104
packages/plugin-pyth-data/src/utils/priceFeedsValidation.ts (2)
6-20
: Consider making asset_type an enumThe
asset_type
field could benefit from being a constrained enum of valid types rather than an arbitrary string.
40-54
: Add retry mechanism for transient validation failuresThe validation function could benefit from a retry mechanism for temporary failures, especially since it's dealing with external data.
export async function validatePriceFeedsData(content: unknown): Promise<boolean> { + const maxRetries = 3; + let attempt = 0; + + while (attempt < maxRetries) { try { const result = await priceFeedsSchema.parseAsync(content); elizaLogger.debug('Price feeds validation passed', { result }); return true; } catch (error) { + attempt++; + if (attempt === maxRetries) { elizaLogger.error('Price feeds validation failed', { error }); throw new DataError( DataErrorCode.VALIDATION_FAILED, 'Price feeds validation failed', ErrorSeverity.HIGH, { error } ); + } + await new Promise(resolve => setTimeout(resolve, 1000 * attempt)); } + } + return false; }packages/plugin-pyth-data/src/utils/priceUpdateStreamValidation.ts (1)
45-45
: Extract regex pattern to a constant.The hardcoded regex pattern for priceIds validation should be extracted to improve maintainability.
+const PRICE_ID_PATTERN = /^0x[0-9a-fA-F]{64}$/; - priceIds: z.array(z.string().regex(/^0x[0-9a-fA-F]{64}$/)), + priceIds: z.array(z.string().regex(PRICE_ID_PATTERN)),packages/plugin-pyth-data/src/error/runtime.ts (1)
17-71
: Add JSDoc documentation for factory methods.Adding JSDoc comments would improve code documentation and IDE support.
Example:
+/** + * Creates an initialization error + * @param component - The component that failed to initialize + * @param reason - The reason for initialization failure + * @param error - Optional original error + * @returns RuntimeError instance + */ static initializationError(component: string, reason: string, error?: Error): RuntimeErrorpackages/plugin-pyth-data/src/error/websocket.ts (1)
73-84
: Add state transition validation.Consider adding a state transition matrix to validate allowed state transitions.
const VALID_TRANSITIONS = new Map([ [WebSocketState.CONNECTING, [WebSocketState.CONNECTED, WebSocketState.ERROR]], [WebSocketState.CONNECTED, [WebSocketState.DISCONNECTED, WebSocketState.ERROR]], // ... other valid transitions ]);packages/plugin-pyth-data/src/index.ts (1)
41-45
: Use descriptive table headers.Single letter headers (H, V, E) are not self-explanatory. Use full words.
- chalk.cyan('H'), - chalk.cyan('V'), - chalk.cyan('E'), + chalk.cyan('Handler'), + chalk.cyan('Validator'), + chalk.cyan('Examples'),packages/plugin-pyth-data/src/utils/priceUpdatesValidation.ts (3)
5-10
: Consider enhancing schema validation constraints.The schema structure is good, but could be strengthened by:
- Adding
maxItems
limit forpriceIds
array- Including
additionalProperties: false
to prevent unknown fieldsexport const priceUpdatesSchema = { type: 'object', + additionalProperties: false, required: ['priceIds'], properties: { text: { type: 'string' }, priceIds: { type: 'array', items: { type: 'string', pattern: '^(0x)?[0-9a-fA-F]+$' }, minItems: 1, + maxItems: 100, description: 'Array of price feed IDs to fetch updates for' },Also applies to: 12-42
50-98
: Consider memory optimization for large datasets.The error mapping could consume significant memory for large datasets with many validation errors.
- errors: errors.map((err: ErrorObject) => ({ + errors: errors.slice(0, 10).map((err: ErrorObject) => ({ path: err.schemaPath, message: err.message, params: err.params })), + totalErrors: errors.length,
105-107
: Add input sanitization to validatePriceId.Consider trimming whitespace and normalizing hex case before validation.
export function validatePriceId(priceId: string): boolean { - return /^(0x)?[0-9a-fA-F]+$/.test(priceId); + return /^(0x)?[0-9a-fA-F]+$/.test(priceId.trim().toLowerCase()); }packages/plugin-pyth-data/src/error/data.ts (2)
4-33
: Add JSDoc documentation for error codes.Consider adding descriptions for each error code to improve maintainability.
export enum DataErrorCode { + /** Validation related errors */ // Validation Errors VALIDATION_FAILED = 'DATA_VALIDATION_FAILED', INVALID_SUBSCRIPTION = 'DATA_INVALID_SUBSCRIPTION',
42-154
: Enhance type safety for error codes.Consider using a union type for error codes instead of casting.
- code: PythErrorCode | DataErrorCode, + code: keyof typeof DataErrorCode | keyof typeof PythErrorCode, message: string, severity: ErrorSeverity = ErrorSeverity.MEDIUM, details?: ErrorDetails, originalError?: Error ) { - super(code as PythErrorCode, message, severity, details, originalError); + super(code, message, severity, details, originalError);packages/plugin-pyth-data/src/environment.ts (3)
8-23
: Enhance security for sensitive configuration.Consider:
- Using a secrets manager for sensitive values
- Validating URLs for allowed domains
25-29
: Remove commented code.Either implement the logging or remove the commented section.
30-43
: Strengthen validation for critical settings.Add constraints for numeric values to prevent invalid configurations.
- PYTH_MAX_RETRIES: z.string().transform(Number).default("3"), + PYTH_MAX_RETRIES: z.string().transform(Number).min(1).max(10).default("3"), - PYTH_TIMEOUT: z.string().transform(Number).default("5000"), + PYTH_TIMEOUT: z.string().transform(Number).min(1000).max(30000).default("5000"),packages/plugin-pyth-data/readme.md (3)
21-21
: Add language specifiers to code blocks.Add language specifiers to fenced code blocks for better syntax highlighting and readability.
-``` +```text Stream price updates for 0xe62df6c8b4a85fe1a67db44dc12de5db330f7ac66b72dc658afedf0f4a415b43Also applies to: 30-30, 38-38, 48-48
🧰 Tools
🪛 Markdownlint (0.37.0)
21-21: null
Fenced code blocks should have a language specified(MD040, fenced-code-language)
107-107
: Remove duplicate "Features" heading.There's a duplicate "Features" heading. Consider removing or renaming this section.
🧰 Tools
🪛 Markdownlint (0.37.0)
107-107: null
Multiple headings with the same content(MD024, no-duplicate-heading)
134-138
: Enhance contributing guidelines.Consider adding more specific guidelines:
- Code style guide or linting rules
- PR submission process
- Testing requirements
- Documentation standards
🧰 Tools
🪛 LanguageTool
[grammar] ~138-~138: Did you mean “to Maintain”?
Context: ...es 3. Update documentation as needed 4. Maintain type safety(MISSING_TO_BEFORE_A_VERB)
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
⛔ Files ignored due to path filters (2)
packages/plugin-pyth-data/assets/Pyth.jpg
is excluded by!**/*.jpg
pnpm-lock.yaml
is excluded by!**/pnpm-lock.yaml
📒 Files selected for processing (30)
.env.example
(10 hunks).gitignore
(1 hunks)agent/package.json
(7 hunks)agent/src/index.ts
(24 hunks)characters/dobby.character.json
(1 hunks)packages/plugin-pyth-data/eslint.config.mjs
(1 hunks)packages/plugin-pyth-data/package.json
(1 hunks)packages/plugin-pyth-data/readme.md
(1 hunks)packages/plugin-pyth-data/src/actions/actionGetLatestPriceUpdates.ts
(1 hunks)packages/plugin-pyth-data/src/actions/actionGetLatestPublisherCaps.ts
(1 hunks)packages/plugin-pyth-data/src/actions/actionGetPriceFeeds.ts
(1 hunks)packages/plugin-pyth-data/src/actions/actionGetPriceUpdatesStream.ts
(1 hunks)packages/plugin-pyth-data/src/environment.ts
(1 hunks)packages/plugin-pyth-data/src/error/base.ts
(1 hunks)packages/plugin-pyth-data/src/error/data.ts
(1 hunks)packages/plugin-pyth-data/src/error/index.ts
(1 hunks)packages/plugin-pyth-data/src/error/runtime.ts
(1 hunks)packages/plugin-pyth-data/src/error/websocket.ts
(1 hunks)packages/plugin-pyth-data/src/index.ts
(1 hunks)packages/plugin-pyth-data/src/price_feeds/schema.json
(1 hunks)packages/plugin-pyth-data/src/types/eventsource.d.ts
(1 hunks)packages/plugin-pyth-data/src/types/jstat.d.ts
(1 hunks)packages/plugin-pyth-data/src/types/zodSchemas.ts
(1 hunks)packages/plugin-pyth-data/src/utils/priceFeedsValidation.ts
(1 hunks)packages/plugin-pyth-data/src/utils/priceUpdateStreamValidation.ts
(1 hunks)packages/plugin-pyth-data/src/utils/priceUpdatesValidation.ts
(1 hunks)packages/plugin-pyth-data/src/utils/publisherCapsValidation.ts
(1 hunks)packages/plugin-pyth-data/tsconfig.json
(1 hunks)packages/plugin-pyth-data/tsup.config.ts
(1 hunks)packages/plugin-pyth-data/vitest.config.ts
(1 hunks)
✅ Files skipped from review due to trivial changes (4)
- packages/plugin-pyth-data/src/error/index.ts
- packages/plugin-pyth-data/tsup.config.ts
- packages/plugin-pyth-data/tsconfig.json
- packages/plugin-pyth-data/package.json
🧰 Additional context used
🪛 LanguageTool
packages/plugin-pyth-data/readme.md
[duplication] ~17-~17: Possible typo: you repeated a word.
Context: ...lable Actions ### 1. GET_PRICE_UPDATES_STREAM Stream real-time price updates for specific as...
(ENGLISH_WORD_REPEAT_RULE)
[uncategorized] ~100-~100: Loose punctuation mark.
Context: ...rice updates. - PYTH_MAX_PRICE_STREAMS
: Controls how many price updates to coll...
(UNLIKELY_OPENING_PUNCTUATION)
[grammar] ~138-~138: Did you mean “to Maintain”?
Context: ...es 3. Update documentation as needed 4. Maintain type safety
(MISSING_TO_BEFORE_A_VERB)
🪛 Markdownlint (0.37.0)
packages/plugin-pyth-data/readme.md
107-107: null
Multiple headings with the same content
(MD024, no-duplicate-heading)
21-21: null
Fenced code blocks should have a language specified
(MD040, fenced-code-language)
30-30: null
Fenced code blocks should have a language specified
(MD040, fenced-code-language)
38-38: null
Fenced code blocks should have a language specified
(MD040, fenced-code-language)
48-48: null
Fenced code blocks should have a language specified
(MD040, fenced-code-language)
🪛 Gitleaks (8.21.2)
packages/plugin-pyth-data/readme.md
68-68: Detected a Generic API Key, potentially exposing access to various services and sensitive operations.
(generic-api-key)
75-75: Detected a Generic API Key, potentially exposing access to various services and sensitive operations.
(generic-api-key)
.env.example
572-573: Detected a Generic API Key, potentially exposing access to various services and sensitive operations.
(generic-api-key)
579-580: Detected a Generic API Key, potentially exposing access to various services and sensitive operations.
(generic-api-key)
929-929: Detected a Generic API Key, potentially exposing access to various services and sensitive operations.
(generic-api-key)
936-936: Detected a Generic API Key, potentially exposing access to various services and sensitive operations.
(generic-api-key)
🪛 checkov (3.2.334)
packages/plugin-pyth-data/src/price_feeds/schema.json
[HIGH] 1: Ensure that the global security field has rules defined
(CKV_OPENAPI_4)
[HIGH] 1: Ensure that security operations is not empty.
(CKV_OPENAPI_5)
🪛 Biome (1.9.4)
packages/plugin-pyth-data/src/utils/publisherCapsValidation.ts
[error] 119-119: isNaN is unsafe. It attempts a type coercion. Use Number.isNaN instead.
See the MDN documentation for more details.
Unsafe fix: Use Number.isNaN instead.
(lint/suspicious/noGlobalIsNan)
agent/src/index.ts
[error] 216-216: Avoid the use of spread (...
) syntax on accumulators.
Spread syntax should be avoided on accumulators (like those in .reduce
) because it causes a time complexity of O(n^2)
.
Consider methods such as .splice or .push instead.
(lint/performance/noAccumulatingSpread)
🔇 Additional comments (14)
.gitignore (1)
64-65
: Consider version controlling documentation and cleaning up old code.
- Documentation should typically be version controlled unless it's auto-generated.
- Instead of ignoring old code, consider archiving it or removing it entirely.
Let's check if these directories contain any valuable content:
✅ Verification successful
Gitignore entries are appropriate for temporary/generated content
The main documentation is properly version controlled via
readme.md
. The ignored directories don't exist, suggesting they're for temporary or generated content.🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash # Check if these directories exist and list their contents ls -la packages/plugin-pyth-data/docs 2>/dev/null ls -la packages/plugin-pyth-data/old_code 2>/dev/null # Look for potential documentation files in the main directory find packages/plugin-pyth-data -type f -name "*.md" ! -path "*/node_modules/*"Length of output: 202
packages/plugin-pyth-data/src/types/zodSchemas.ts (1)
138-141
: Review use of 'ids[]' in query parameter names.Using
'ids[]'
as a parameter name may cause issues with some HTTP clients or servers. Consider using'ids'
without brackets and ensuring the server correctly parses multiple values.Also applies to: 178-181, 215-218, 289-291
packages/plugin-pyth-data/src/actions/actionGetPriceFeeds.ts (1)
94-97
: Confirm validation logic when content type differs.The
validate
method returnstrue
when the message content type is not"GET_PRICE_FEEDS"
. Ensure this is intentional and that skipping validation is appropriate in this context.packages/plugin-pyth-data/src/actions/actionGetLatestPriceUpdates.ts (1)
100-102
: Verify validation bypass when content type mismatches.The
validate
method returnstrue
if the message content type is not"GET_LATEST_PRICE_UPDATES"
. Confirm that this behavior is intended and doesn't skip necessary checks.packages/plugin-pyth-data/src/types/jstat.d.ts (1)
1-8
: LGTMThe TypeScript declaration for the 'jstat' module is correctly defined.
packages/plugin-pyth-data/eslint.config.mjs (1)
8-14
: Consider monitoring the impact of disabled TypeScript rulesWhile disabling these rules might be necessary for third-party library integration, consider adding inline comments explaining why each rule is disabled and monitor for potential type-safety issues.
✅ Verification successful
Disabled TypeScript rules are appropriately configured
The current ESLint configuration aligns well with the codebase's requirements, particularly for plugin architecture and third-party integrations. The warning level for 'no-explicit-any' provides a good balance between type safety and practical development needs.
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash # Search for usage of 'any' type and unsafe operations rg "any[^a-zA-Z]" --type tsLength of output: 84748
packages/plugin-pyth-data/vitest.config.ts (1)
4-27
: LGTM! Well-structured test configurationThe configuration includes comprehensive coverage reporting and proper path aliasing.
packages/plugin-pyth-data/src/types/eventsource.d.ts (1)
4-10
: Verify SSL configuration handlingThe HTTPS configuration allows disabling certificate validation (
rejectUnauthorized
). Ensure this is properly handled in the implementation.✅ Verification successful
SSL configuration is properly encapsulated
The HTTPS configuration is handled by the HermesClient library, not directly exposed in the implementation. The type definition is just for interface completeness.
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash # Search for usage of rejectUnauthorized option rg "rejectUnauthorized:\s*(false|true)" --type tsLength of output: 241
Script:
#!/bin/bash # Search for EventSource usage and implementation in pyth-data rg -t ts "new\s+EventSource" packages/plugin-pyth-data/ rg -t ts "https:\s*{" packages/plugin-pyth-data/Length of output: 192
Script:
#!/bin/bash # Search for EventSource instantiation and HTTPS config rg -t ts "EventSource" packages/plugin-pyth-data/ rg -t ts "rejectUnauthorized" packages/plugin-pyth-data/ rg -t ts "https.*config" packages/plugin-pyth-data/Length of output: 1291
Script:
#!/bin/bash # Check the EventSource instantiation context rg -A 5 -B 5 "new\s+Map<string,\s*EventSource>" packages/plugin-pyth-data/src/actions/actionGetPriceUpdatesStream.tsLength of output: 520
Script:
#!/bin/bash # Get the full content of the file to see EventSource instantiation cat packages/plugin-pyth-data/src/actions/actionGetPriceUpdatesStream.tsLength of output: 19299
packages/plugin-pyth-data/src/utils/priceUpdateStreamValidation.ts (1)
57-71
: LGTM! Well-structured error handling.The validation function properly handles both success and error cases with appropriate logging.
packages/plugin-pyth-data/src/error/runtime.ts (1)
3-15
: LGTM! Well-structured error class.The RuntimeError class properly extends PythError and maintains the prototype chain.
packages/plugin-pyth-data/src/index.ts (1)
83-92
: LGTM! Well-structured plugin exports.The plugin is properly configured and exported for both module systems.
characters/dobby.character.json (1)
4-4
: Verify character behavior with new model provider.Ensure that Dobby's unique personality traits and third-person speech patterns are preserved with the OpenAI model.
✅ Verification successful
Character traits verified successfully
The configuration maintains Dobby's distinctive third-person speech and core personality traits in all message examples.
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash # Check for third-person speech patterns in message examples rg -i "dobby.*?(is|has|will|would|says)" characters/dobby.character.jsonLength of output: 651
packages/plugin-pyth-data/readme.md (1)
119-127
: Great error handling documentation!The error handling section is comprehensive and clearly documents all potential error scenarios.
agent/package.json (1)
3-3
: Version bump and dependencies look good.The version change to alpha and addition of the Pyth Data Plugin dependency are appropriate for this feature.
Also applies to: 103-103
Trying to fix the conflicts but today GIT is nuts. |
8a7a126
to
9b103a3
Compare
Head branch was pushed to by a user without write access
4cf6ae0
to
8421afb
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
lots of duplicate keys
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
all fixed.
Git exploded
Pyth Data Plugin for ElizaOS
Overview
This PR introduces the Pyth Data Plugin, focusing on stability, efficiency, and code organization.
Key Changes
1. Action Validation Improvements
2. Client Integration
@pythnetwork/hermes-client
package3. Code Organization
priceFeedsValidation.ts
priceUpdateStreamValidation.ts
priceUpdatesValidation.ts
publisherCapsValidation.ts
4. Streaming Enhancements
Testing Results
Action Tests
GET_PRICE_UPDATES_STREAM
GET_LATEST_PRICE_UPDATES
GET_LATEST_PUBLISHER_CAPS
GET_PRICE_FEEDS
Cross-Action Testing
Configuration Updates
Documentation
Technical Improvements
Type Safety
Error Handling
Performance
Breaking Changes
None. All changes maintain backward compatibility.
Migration Guide
No migration needed. Updates are backward compatible.
Future Improvements
Dependencies
@pythnetwork/hermes-client
Testing Instructions
Reviewers
Please focus on: