-
Notifications
You must be signed in to change notification settings - Fork 5.5k
Eng 8702,eng 8703,eng 8704 #18072
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
base: master
Are you sure you want to change the base?
Eng 8702,eng 8703,eng 8704 #18072
Conversation
@HarshGautam7101 is attempting to deploy a commit to the Pipedreamers Team on Vercel. A member of the Team first needs to authorize it. |
The latest updates on your projects. Learn more about Vercel for GitHub. 1 Skipped Deployment
|
WalkthroughAdds centralized endpoint/constants and utilities, refactors the Token Metrics app to a generic API client with standardized error handling, and rewrites README. Introduces numerous new action modules and updates existing ones to use shared utilities (buildParams, generateFilterSummary) and new endpoint wrappers with consistent pagination and summaries. Changes
Sequence Diagram(s)sequenceDiagram
participant User
participant Action
participant Utils as Utils (buildParams / generateFilterSummary)
participant App as TokenMetrics App
participant API as Token Metrics API
User->>Action: Invoke action with props
Action->>Utils: buildParams(props, endpoint.filters)
Action->>App: makeApiCall(endpoint, params)
App->>API: GET /v2/<endpoint>?params
API-->>App: Response / Error
alt Success
App-->>Action: Data
Action->>Utils: generateFilterSummary(props, filters)
Action-->>User: Return data (+ $summary)
else Error
App-->>Action: Error
Action-->>User: Throw "Token Metrics API Error (status): message"
end
Estimated code review effort🎯 4 (Complex) | ⏱️ ~45–60 minutes Poem
Tip 🔌 Remote MCP (Model Context Protocol) integration is now available!Pro plan users can now connect to remote MCP servers from the Integrations page. Connect with popular remote MCPs such as Notion and Linear to add more context to your reviews and chats. ✨ Finishing Touches
🧪 Generate unit tests
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. 🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
SupportNeed help? Create a ticket on our support page for assistance with any issues or questions. CodeRabbit Commands (Invoked using PR/Issue comments)Type Other keywords and placeholders
CodeRabbit Configuration File (
|
Thank you so much for submitting this! We've added it to our backlog to review, and our team has been notified. |
Thanks for submitting this PR! When we review PRs, we follow the Pipedream component guidelines. If you're not familiar, here's a quick checklist:
|
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: 2
♻️ Duplicate comments (10)
components/token_metrics/actions/get-indices/get-indices.mjs (2)
58-69
: Reuse the shared error handler introduced in utilsSee earlier comment in get-resistance-support for the handleActionError helper and apply the same replacement here to remove duplicated error handling.
1-72
: Confirm client/constant alignment for ‘indices’Covered by the verification script provided in get-resistance-support.
components/token_metrics/actions/get-technology-grades/get-technology-grades.mjs (2)
66-77
: Extract the repeated error handlingAdopt the handleActionError helper suggested in get-resistance-support to reduce duplication.
1-80
: Confirm client/constant alignment for ‘technology grades’Covered by the verification script provided in get-resistance-support.
components/token_metrics/actions/get-scenario-analysis/get-scenario-analysis.mjs (2)
62-73
: Centralize error handling to a utilSee earlier handleActionError suggestion and apply here.
1-76
: Confirm client/constant alignment for ‘scenario analysis’Covered by the verification script provided in get-resistance-support.
components/token_metrics/actions/get-top-market-cap-tokens/get-top-market-cap-tokens.mjs (2)
41-52
: Adopt shared error handling helperUse handleActionError as suggested in get-resistance-support for consistency and less duplication.
1-55
: Confirm client/constant alignment for ‘top market cap tokens’Covered by the verification script provided in get-resistance-support.
components/token_metrics/actions/get-quantmetrics/get-quantmetrics.mjs (2)
8-8
: Verify hyphen vs underscore in component keyThe component key uses an underscore (
token_metrics-get-quantmetrics
). Verify this is consistent with other Token Metrics components.
18-19
: Remove "Click here" placeholder text from prop descriptionsSimilar to the other actions, the descriptions contain non-functional "Click here" text that should be removed or replaced with actual documentation links.
- description: "Comma Separated Token IDs. Click here to access the list of token IDs. Example: 3375,3306", + description: "Comma Separated Token IDs. Example: 3375,3306",- description: "Comma Separated Token Symbols. Click here to access the list of token symbols. Example: BTC,ETH", + description: "Comma Separated Token Symbols. Example: BTC,ETH",- description: "Comma separated category name. Click here to access the list of categories. Example: layer-1,nft", + description: "Comma separated category name. Example: layer-1,nft",- description: "Comma separated exchange name. Click here to access the list of exchanges. Example: binance,gate", + description: "Comma separated exchange name. Example: binance,gate",Also applies to: 22-23, 26-27, 30-31
🧹 Nitpick comments (74)
components/token_metrics/package.json (1)
3-3
: Avoid version downgrade; confirm intended and adjust per SemVerPR summary indicates a downgrade from 0.1.0 → 0.0.1. Unless you’re re-publishing under a new package or intentionally resetting, avoid going backwards per SemVer to prevent publish/install issues.
If this was unintentional, bump forward instead:
- "version": "0.0.1", + "version": "0.1.1",components/token_metrics/README.md (3)
26-29
: Expand “Available Actions” to reflect the full action surface (or link to an index)This section lists only three actions, but the PR adds many more (e.g., OHLCV, TM Grades, Technology Grades, Market Metrics, Trading Signals, Indices, etc.). Please either enumerate the new actions or add a link to an index so users can discover them easily.
17-23
: Minor grammar/formatting: tighten the Authentication listLanguageTool flagged this segment. Suggest rewording for clarity and proper list formatting.
- To use the Token Metrics API, you'll need: - - 1. A Token Metrics account - 2. An API key from your Token Metrics dashboard + To use the Token Metrics API, you will need: + + 1. A Token Metrics account + 2. An API key from your Token Metrics dashboard
32-32
: Add a direct link to rate limit docsPoint users to the exact documentation page for rate limits (if available) to reduce ambiguity.
If you have the URL, add it here; otherwise, link to the main developer docs for Token Metrics.
components/token_metrics/common/constants.mjs (2)
183-190
: Grammar: pluralize “scenario”Minor copy fix in SCENARIO_ANALYSIS description.
- description: "Get the price prediction based on different Crypto Market scenario", + description: "Get the price prediction based on different Crypto Market scenarios",
331-336
: Consider adding bounds for top_k (optional)If the API enforces sensible bounds (e.g., 1–500), reflect that here (either via description or validation) to give users immediate feedback.
top_k: { type: "integer", label: "Top K", - description: "Specifies the number of top cryptocurrencies to retrieve, based on their market capitalization. Example: 100", + description: "Specifies the number of top cryptocurrencies to retrieve, based on their market capitalization (e.g., 1–500). Example: 100", optional: true, },components/token_metrics/actions/get-tm-grades-historical/get-tm-grades-historical.mjs (4)
16-27
: Avoid “Click here…” and point to a concrete lookup path“Click here” isn’t actionable in the UI. Suggest referencing the “Get Tokens” action for lookups, or implement async options to let users search/select tokens directly.
tokenId: { ...FILTER_DEFINITIONS.token_id, - description: "Click here to access the list of token IDs. Example: 3375", + description: "Token ID(s). Use the 'Get Tokens' action to look up IDs. Example: 3375", }, tokenName: { ...FILTER_DEFINITIONS.token_name, - description: "Crypto Asset Names (e.g., Bitcoin, Ethereum). Click here to access the list of token names.", + description: "Crypto asset names (e.g., Bitcoin, Ethereum). Use the 'Get Tokens' action to look up names.", }, symbol: { ...FILTER_DEFINITIONS.symbol, - description: "Click here to access the list of token symbols. Example: BTC,ETH", + description: "Symbols (e.g., BTC,ETH). Use the 'Get Tokens' action to look up symbols.", },Optionally, I can help convert these to async options so users can search tokens inline.
28-35
: Use neutral, realistic date examplesExamples in the future may confuse users and sample runs. Prefer recent historical dates.
startDate: { ...FILTER_DEFINITIONS.start_date, - description: "Start Date accepts date as a string - YYYY-MM-DD format. Example: 2025-07-01", + description: "Start date (YYYY-MM-DD). Example: 2024-07-01", }, endDate: { ...FILTER_DEFINITIONS.end_date, - description: "End Date accepts date as a string - YYYY-MM-DD format. Example: 2025-07-05", + description: "End date (YYYY-MM-DD). Example: 2024-07-05", },
54-63
: Validate that at least one token selector is providedThe API likely needs at least one of tokenId, tokenName, or symbol. Add a guard to provide immediate feedback.
async run({ $ }) { - // Build parameters using utility function + // Validate required filter presence + if (!this.tokenId && !this.tokenName && !this.symbol) { + throw new Error("Please provide at least one of: tokenId, tokenName, or symbol."); + } + // Build parameters using utility function const params = buildParams(this, endpoint.filters);
75-85
: Preserve original error as causeWrap the original error to retain stack/context in logs.
- // Throw a more descriptive error - throw new Error(`Token Metrics API Error (${statusCode || 'Unknown'}): ${errorMessage}`); + // Throw a more descriptive error with original cause + throw new Error(`Token Metrics API Error (${statusCode || 'Unknown'}): ${errorMessage}`, { cause: error });components/token_metrics/actions/get-hourly-ohlcv/get-hourly-ohlcv.mjs (4)
16-27
: Replace “Click here…” with discoverable guidance or async optionsGuide users to the “Get Tokens” action or implement async options for better UX.
tokenId: { ...FILTER_DEFINITIONS.token_id, - description: "Comma Separated Token IDs. Click here to access the list of token IDs. Example: 3375,3306", + description: "Comma-separated token IDs. Use the 'Get Tokens' action to look up IDs. Example: 3375,3306", }, symbol: { ...FILTER_DEFINITIONS.symbol, - description: "Comma Separated Token Symbols. Click here to access the list of token symbols. Example: BTC,ETH", + description: "Comma-separated symbols. Use the 'Get Tokens' action to look up symbols. Example: BTC,ETH", }, tokenName: { ...FILTER_DEFINITIONS.token_name, - description: "Comma Separated Crypto Asset Names (e.g., Bitcoin, Ethereum). Click here to access the list of token names. Example: Bitcoin, Ethereum", + description: "Comma-separated crypto asset names (e.g., Bitcoin, Ethereum). Use the 'Get Tokens' action to look up names.", },If you’d like, I can add async options that query the Tokens endpoint to populate these fields.
28-35
: Clarify/enforce the “past 30 days” constraintThe description states the start date cannot be earlier than the past 30 days. Enforce this (and validate date order) to fail fast with helpful errors.
startDate: { ...FILTER_DEFINITIONS.start_date, - description: "Start Date accepts date as a string - YYYY-MM-DD format. Note: The Start Date cannot be earlier than the past 30 days from the current date. Example: 2025-03-01", + description: "Start date (YYYY-MM-DD). Note: Cannot be earlier than the past 30 days from today. Example: 2024-03-01", }, endDate: { ...FILTER_DEFINITIONS.end_date, - description: "End Date accepts date as a string - YYYY-MM-DD format. Example: 2025-03-20", + description: "End date (YYYY-MM-DD). Example: 2024-03-20", },And add validation in run():
async run({ $ }) { - // Build parameters using utility function + // Basic input validation + if (!this.tokenId && !this.symbol && !this.tokenName) { + throw new Error("Please provide at least one of: tokenId, symbol, or tokenName."); + } + if (this.startDate && this.endDate) { + const sd = new Date(this.startDate); + const ed = new Date(this.endDate); + if (Number.isNaN(sd.getTime()) || Number.isNaN(ed.getTime())) { + throw new Error("Invalid date format. Use YYYY-MM-DD."); + } + if (sd > ed) { + throw new Error("startDate must be earlier than or equal to endDate."); + } + } + if (this.startDate) { + const sd = new Date(this.startDate); + const THIRTY_DAYS_MS = 30 * 24 * 60 * 60 * 1000; + if (Date.now() - sd.getTime() > THIRTY_DAYS_MS) { + throw new Error("startDate cannot be earlier than the past 30 days from today."); + } + } + // Build parameters using utility function const params = buildParams(this, endpoint.filters);If the 30-day limit is not actually enforced server-side, remove that note and validation to avoid false negatives.
54-63
: Add required filter presence check (at least one token selector)Mirror TM Grades Historical: enforce presence of tokenId/symbol/tokenName for clearer UX.
async run({ $ }) { - // Build parameters using utility function + // Ensure at least one token selector is present + if (!this.tokenId && !this.symbol && !this.tokenName) { + throw new Error("Please provide at least one of: tokenId, symbol, or tokenName."); + } + // Build parameters using utility function const params = buildParams(this, endpoint.filters);
75-85
: Preserve original error as causeMatch the error handling improvement suggested in the TM Grades Historical action.
- // Throw a more descriptive error - throw new Error(`Token Metrics API Error (${statusCode || 'Unknown'}): ${errorMessage}`); + // Throw a more descriptive error with original cause + throw new Error(`Token Metrics API Error (${statusCode || 'Unknown'}): ${errorMessage}`, { cause: error });components/token_metrics/actions/get-hourly-trading-signals/get-hourly-trading-signals.mjs (5)
16-20
: Don’t force tokenId for an endpoint that supports “all tokens”Docs/endpoint description indicate hourly trading signals can be fetched for all tokens. Making tokenId required prevents that use case.
Consider this change:
tokenId: { ...FILTER_DEFINITIONS.token_id, - description: "Comma Separated Token IDs. Click here to access the list of token IDs. Example: 3375,3306", - optional: false, + description: "Comma-separated Token IDs (e.g., 3375,3306)", + optional: true, },Follow-up:
- If the API actually requires token_id, keep it required and please confirm. Otherwise, making it optional restores the “all tokens” capability.
- Also, avoid “Click here” without a link in descriptions across actions (replace with a concrete link or remove). I can help wire an async prop to search tokens if helpful.
53-56
: Make $summary count robust to different response shapesSome endpoints/clients return arrays under response.data.data or as the top-level response. Guard against those shapes to avoid reporting 0.
Apply:
- const dataLength = response.data?.length || 0; - $.export("$summary", `Successfully retrieved hourly trading signals for ${dataLength} records${filterSummary}`); + const dataLength = Array.isArray(response?.data) + ? response.data.length + : Array.isArray(response?.data?.data) + ? response.data.data.length + : Array.isArray(response) + ? response.length + : 0; + $.export("$summary", `Successfully retrieved hourly trading signals for ${dataLength} records${filterSummary}`);
3-3
: Leverage centralized error handlingYou introduced handleApiError in utils. Import it here for consistent error mapping across actions.
Apply:
-import { buildParams, generateFilterSummary } from "../../common/utils.mjs"; +import { buildParams, generateFilterSummary, handleApiError } from "../../common/utils.mjs";
59-70
: Delegate error mapping to handleApiError for consistencyUnifies error behavior and avoids duplicating logic in each action.
Apply:
- } catch (error) { - // Enhanced error handling - const errorMessage = error.response?.data?.message || error.message || "An error occurred"; - const statusCode = error.response?.status; - - if ($ && $.export) { - $.export("$summary", `Error: ${errorMessage}`); - } - - // Throw a more descriptive error - throw new Error(`Token Metrics API Error (${statusCode || 'Unknown'}): ${errorMessage}`); - } + } catch (error) { + const errorMessage = error.response?.data?.message || error.message || "An error occurred"; + if ($?.export) { + $.export("$summary", `Error: ${errorMessage}`); + } + handleApiError(error); + }
21-37
: Minor: avoid duplicating pagination defaults across actionsYou’re setting limit/page defaults here but not in some other actions (e.g., get-price). Consider centralizing defaults at the app-level propDefinitions or documenting consistently across actions.
I can help standardize pagination descriptions/defaults repo-wide if you want.
components/token_metrics/actions/get-price/get-price.mjs (5)
16-19
: Require tokenId for the Price endpointThe price endpoint description suggests token IDs must be provided. Making tokenId required improves UX and avoids ambiguous API errors.
Apply:
tokenId: { ...FILTER_DEFINITIONS.token_id, - description: "Comma Separated Token IDs. Click here to access the list of token IDs. Example: 3375,3306", + description: "Comma-separated Token IDs (e.g., 3375,3306)", + optional: false, },If the API supports “all tokens” without token_id for price, ignore this suggestion and keep it optional. Please confirm expected API behavior.
21-32
: Align pagination props with other actionsOther actions add descriptions/defaults for limit/page. Keep consistent here for a uniform authoring experience.
Apply:
limit: { propDefinition: [ tokenMetrics, "limit", ], + description: "Limit the number of items in response. Defaults to 50", + default: 50, }, page: { propDefinition: [ tokenMetrics, "page", ], + description: "Enables pagination and data retrieval control by skipping a specified number of items before fetching data. Page should be a non-negative integer, with 1 indicating the beginning of the dataset. Defaults to 1", + default: 1, },
48-51
: Make $summary count robust to different response shapesMirror the more resilient counting across actions.
Apply:
- const dataLength = response.data?.length || 0; - $.export("$summary", `Successfully retrieved ${dataLength} price records${filterSummary}`); + const dataLength = Array.isArray(response?.data) + ? response.data.length + : Array.isArray(response?.data?.data) + ? response.data.data.length + : Array.isArray(response) + ? response.length + : 0; + $.export("$summary", `Successfully retrieved ${dataLength} price records${filterSummary}`);
3-3
: Import handleApiError for consistent error mappingStay consistent with shared utilities.
Apply:
-import { buildParams, generateFilterSummary } from "../../common/utils.mjs"; +import { buildParams, generateFilterSummary, handleApiError } from "../../common/utils.mjs";
55-65
: Use centralized error handlingDelegate detailed mapping to the shared utility and export a brief summary.
Apply:
- } catch (error) { - // Enhanced error handling - const errorMessage = error.response?.data?.message || error.message || "An error occurred"; - const statusCode = error.response?.status; - - if ($ && $.export) { - $.export("$summary", `Error: ${errorMessage}`); - } - - // Throw a more descriptive error - throw new Error(`Token Metrics API Error (${statusCode || 'Unknown'}): ${errorMessage}`); - } + } catch (error) { + const errorMessage = error.response?.data?.message || error.message || "An error occurred"; + if ($?.export) { + $.export("$summary", `Error: ${errorMessage}`); + } + handleApiError(error); + }components/token_metrics/common/utils.mjs (4)
10-13
: Don’t drop falsy but valid values when building paramsThe current truthy check skips values like 0 or false. Prefer explicit undefined/null/empty string checks.
Apply:
- if (props[propKey]) { + if (props[propKey] !== undefined && props[propKey] !== null && props[propKey] !== "") { params[key] = props[propKey]; }
43-46
: Ensure filter summary includes valid falsy valuesMirrors the buildParams fix so values like 0 aren’t dropped from the summary.
Apply:
- if (value) { + if (value !== undefined && value !== null && value !== "") { const label = key.replace(/_/g, " ").replace(/\b\w/g, l => l.toUpperCase()); appliedFilters.push(`${label}: ${value}`); }
75-79
: Potential mismatch when generating the app prop nameUsing [app.app] creates a prop like "token_metrics", but actions expect the prop name tokenMetrics (matching the import variable). This helper may produce unusable props unless the caller’s variable name equals app.app.
Recommended approach: accept the desired prop name as an argument and assign the app under that name.
-export function generateEndpointProps(app, endpoint) { - const props = { - [app.app]: app, // Add the app reference - }; +export function generateEndpointProps({ app, appPropName, endpoint }) { + const props = { + [appPropName]: app, + }; // ... - props.limit = { propDefinition: [app, "limit"] }; - props.page = { propDefinition: [app, "page"] }; + props.limit = { propDefinition: [app, "limit"] }; + props.page = { propDefinition: [app, "page"] }; return props; }If you plan to use this helper, I can refactor a couple of actions to consume it as an example.
52-71
: Optional: expand error mapping (404, network, timeouts)handleApiError is good. If useful, consider handling 404 separately (e.g., “No data found for the provided filters”) and network/timeout errors (axios distinguishes ECONNABORTED, etc.). Not a blocker.
components/token_metrics/actions/get-daily-ohlcv/get-daily-ohlcv.mjs (5)
16-35
: Replace “Click here” placeholders in prop descriptionsThere are multiple “Click here” references without actual links. Either add real links or remove the phrase to avoid user confusion.
Apply:
tokenId: { ...FILTER_DEFINITIONS.token_id, - description: "Comma Separated Token IDs. Click here to access the list of token IDs. Example: 3375", + description: "Comma-separated Token IDs (e.g., 3375)", }, symbol: { ...FILTER_DEFINITIONS.symbol, - description: "Comma Separated Token Symbols. Click here to access the list of token symbols. Example: BTC", + description: "Comma-separated Token Symbols (e.g., BTC)", }, tokenName: { ...FILTER_DEFINITIONS.token_name, - description: "Comma Separated Crypto Asset Names (e.g., Bitcoin, Ethereum). Click here to access the list of token names. Example: Bitcoin", + description: "Comma-separated Crypto Asset Names (e.g., Bitcoin, Ethereum). Example: Bitcoin", }, startDate: { ...FILTER_DEFINITIONS.start_date, - description: "Start Date accepts date as a string - YYYY-MM-DD format. Note: The Start Date cannot be earlier than the past 30 days from the current date. Example: 2025-01-01", + description: "Start Date (YYYY-MM-DD). Note: Must be within the past 30 days. Example: 2025-01-01", }, endDate: { ...FILTER_DEFINITIONS.end_date, - description: "End Date accepts date as a string - YYYY-MM-DD format. Example: 2025-01-23", + description: "End Date (YYYY-MM-DD). Example: 2025-01-23", },
69-71
: Make $summary count robust to response shapeAlign with the more defensive pattern used in other suggestions.
Apply:
- const dataLength = response.data?.length || 0; + const dataLength = Array.isArray(response?.data) + ? response.data.length + : Array.isArray(response?.data?.data) + ? response.data.data.length + : Array.isArray(response) + ? response.length + : 0;
3-3
: Import handleApiError for unified error handlingApply:
-import { buildParams, generateFilterSummary } from "../../common/utils.mjs"; +import { buildParams, generateFilterSummary, handleApiError } from "../../common/utils.mjs";
75-85
: Use centralized error utility and keep $summary briefApply:
- } catch (error) { - // Enhanced error handling - const errorMessage = error.response?.data?.message || error.message || "An error occurred"; - const statusCode = error.response?.status; - - if ($ && $.export) { - $.export("$summary", `Error: ${errorMessage}`); - } - - // Throw a more descriptive error - throw new Error(`Token Metrics API Error (${statusCode || 'Unknown'}): ${errorMessage}`); - } + } catch (error) { + const errorMessage = error.response?.data?.message || error.message || "An error occurred"; + if ($?.export) { + $.export("$summary", `Error: ${errorMessage}`); + } + handleApiError(error); + }
28-35
: Optional: validate date format pre-flightThe UI hints at YYYY-MM-DD and 30-day bound, but there’s no validation. Consider a lightweight check to fail fast with a clear message, or move validation into the app client.
I can add a simple regex/date-range validation in run() to prevent avoidable API calls if you want.
components/token_metrics/actions/get-fundamental-grades-historical/get-fundamental-grades-historical.mjs (5)
16-27
: Replace “Click here” placeholders with concrete text or linksAvoid dangling CTA text in prop descriptions.
Apply:
tokenId: { ...FILTER_DEFINITIONS.token_id, - description: "Click here to access the list of token IDs. Example: 3375", + description: "Token IDs (e.g., 3375)", }, tokenName: { ...FILTER_DEFINITIONS.token_name, - description: "Crypto Asset Names (e.g., Bitcoin, Ethereum). Click here to access the list of token names.", + description: "Crypto Asset Names (e.g., Bitcoin, Ethereum).", }, symbol: { ...FILTER_DEFINITIONS.symbol, - description: "Click here to access the list of token symbols. Example: BTC,ETH", + description: "Token Symbols (e.g., BTC,ETH)", },
55-57
: Guard against empty filters if the API requires at least one identifierIf the endpoint expects at least one of tokenId/tokenName/symbol, add a quick check to help users.
Apply:
async run({ $ }) { - // Build parameters using utility function + // Build parameters using utility function + if (!this.tokenId && !this.tokenName && !this.symbol) { + throw new Error("Please provide at least one of tokenId, tokenName, or symbol."); + } const params = buildParams(this, endpoint.filters);If the API supports broad queries without filters, skip this suggestion. Please confirm expected behavior.
69-71
: Make $summary count robust to response shapeApply:
- const dataLength = response.data?.length || 0; + const dataLength = Array.isArray(response?.data) + ? response.data.length + : Array.isArray(response?.data?.data) + ? response.data.data.length + : Array.isArray(response) + ? response.length + : 0;
3-3
: Import handleApiError for unified error mappingApply:
-import { buildParams, generateFilterSummary } from "../../common/utils.mjs"; +import { buildParams, generateFilterSummary, handleApiError } from "../../common/utils.mjs";
75-85
: Use shared error utility and export a brief summaryApply:
- } catch (error) { - // Enhanced error handling - const errorMessage = error.response?.data?.message || error.message || "An error occurred"; - const statusCode = error.response?.status; - - if ($ && $.export) { - $.export("$summary", `Error: ${errorMessage}`); - } - - // Throw a more descriptive error - throw new Error(`Token Metrics API Error (${statusCode || 'Unknown'}): ${errorMessage}`); - } + } catch (error) { + const errorMessage = error.response?.data?.message || error.message || "An error occurred"; + if ($?.export) { + $.export("$summary", `Error: ${errorMessage}`); + } + handleApiError(error); + }components/token_metrics/actions/get-resistance-support/get-resistance-support.mjs (3)
16-23
: Avoid “Click here” in descriptions and fix hyphenationInline “Click here” without a link degrades UX, and “Comma Separated” should be “Comma-separated.”
Apply this diff:
- tokenId: { - ...FILTER_DEFINITIONS.token_id, - description: "Comma Separated Token IDs. Click here to access the list of token IDs. Example: 3375,3306", - }, + tokenId: { + ...FILTER_DEFINITIONS.token_id, + description: "Comma-separated token IDs. See Token Metrics docs for the list of supported token IDs. Example: 3375,3306", + }, - symbol: { - ...FILTER_DEFINITIONS.symbol, - description: "Comma Separated Token Symbols. Click here to access the list of token symbols. Example: BTC,ETH", - }, + symbol: { + ...FILTER_DEFINITIONS.symbol, + description: "Comma-separated token symbols. See Token Metrics docs for the list of supported symbols. Example: BTC,ETH", + },
33-40
: Clarify page description: it should be a positive 1-based integer“Non-negative” conflicts with “1 indicating the beginning.” Use “positive (1-based).”
- description: "Enables pagination and data retrieval control by skipping a specified number of items before fetching data. Page should be a non-negative integer, with 1 indicating the beginning of the dataset. Defaults to 1", + description: "Enables pagination and data retrieval control. Page should be a positive integer (1-based index). Default: 1",
62-73
: DRY the error handling into a shared helperThe try/catch block is duplicated across actions. Centralize it in a utils function to reduce repetition and keep behavior consistent.
- Add in components/token_metrics/common/utils.mjs:
export function handleActionError($, error, context = "Token Metrics API Error") { const errorMessage = error?.response?.data?.message || error?.message || "An error occurred"; const statusCode = error?.response?.status ?? "Unknown"; if ($ && $.export) { $.export("$summary", `Error: ${errorMessage}`); } // Preserve original error as cause if supported by the runtime // Node 16+: new Error(message, { cause: error }) throw new Error(`${context} (${statusCode}): ${errorMessage}`); }
- Then replace this file’s catch block with:
- } catch (error) { - // Enhanced error handling - const errorMessage = error.response?.data?.message || error.message || "An error occurred"; - const statusCode = error.response?.status; - - if ($ && $.export) { - $.export("$summary", `Error: ${errorMessage}`); - } - - // Throw a more descriptive error - throw new Error(`Token Metrics API Error (${statusCode || 'Unknown'}): ${errorMessage}`); - } + } catch (error) { + return handleActionError($, error, "Token Metrics API Error"); + }components/token_metrics/actions/get-indices/get-indices.mjs (1)
29-36
: Clarify page description: it should be a positive 1-based integer- description: "Enables pagination and data retrieval control by skipping a specified number of items before fetching data. Page should be a non-negative integer, with 1 indicating the beginning of the dataset. Defaults to 1", + description: "Enables pagination and data retrieval control. Page should be a positive integer (1-based index). Default: 1",components/token_metrics/actions/get-technology-grades/get-technology-grades.mjs (2)
16-27
: Avoid “Click here” and improve phrasing- tokenId: { - ...FILTER_DEFINITIONS.token_id, - description: "Click here to access the list of token IDs. Example: 3375", - }, + tokenId: { + ...FILTER_DEFINITIONS.token_id, + description: "Token ID. See Token Metrics docs for the list of supported token IDs. Example: 3375", + }, - tokenName: { - ...FILTER_DEFINITIONS.token_name, - description: "Crypto Asset Names (e.g., Bitcoin, Ethereum). Click here to access the list of token names.", - }, + tokenName: { + ...FILTER_DEFINITIONS.token_name, + description: "Crypto asset names (e.g., Bitcoin, Ethereum). See Token Metrics docs for the list of supported names.", + }, - symbol: { - ...FILTER_DEFINITIONS.symbol, - description: "Click here to access the list of token symbols. Example: BTC,ETH", - }, + symbol: { + ...FILTER_DEFINITIONS.symbol, + description: "Token symbols. See Token Metrics docs for the list of supported symbols. Example: BTC,ETH", + },
37-44
: Clarify page description to avoid ambiguity- description: "Enables pagination and data retrieval control by skipping a specified number of items before fetching data. Page should be a non-negative integer, with 1 indicating the beginning of the dataset. Defaults to 1", + description: "Enables pagination and data retrieval control. Page should be a positive integer (1-based index). Default: 1",components/token_metrics/actions/get-scenario-analysis/get-scenario-analysis.mjs (2)
16-23
: Avoid “Click here” and fix hyphenation- tokenId: { - ...FILTER_DEFINITIONS.token_id, - description: "Comma Separated Token IDs. Click here to access the list of token IDs. Example: 3375,3306", - }, + tokenId: { + ...FILTER_DEFINITIONS.token_id, + description: "Comma-separated token IDs. See Token Metrics docs for the list of supported token IDs. Example: 3375,3306", + }, - symbol: { - ...FILTER_DEFINITIONS.symbol, - description: "Comma Separated Token Symbols. Click here to access the list of token symbols. Example: BTC,ETH", - }, + symbol: { + ...FILTER_DEFINITIONS.symbol, + description: "Comma-separated token symbols. See Token Metrics docs for the list of supported symbols. Example: BTC,ETH", + },
33-40
: Clarify page description to 1-based positive integer- description: "Enables pagination and data retrieval control by skipping a specified number of items before fetching data. Page should be a non-negative integer, with 1 indicating the beginning of the dataset. Defaults to 1", + description: "Enables pagination and data retrieval control. Page should be a positive integer (1-based index). Default: 1",components/token_metrics/actions/get-top-market-cap-tokens/get-top-market-cap-tokens.mjs (1)
16-20
: Consider enforcing topK > 0 at the schema levelTo preempt invalid inputs, consider setting a minimum constraint in FILTER_DEFINITIONS.top_k (or validating here).
You can update components/token_metrics/common/constants.mjs:
top_k: { type: "integer", label: "Top K", description: "Specifies the number of top cryptocurrencies to retrieve, based on their market capitalization. Example: 100", optional: true, min: 1, // enforce positive integers }components/token_metrics/actions/get-moonshot-tokens/get-moonshot-tokens.mjs (3)
15-19
: Remove reference to “screenshot” in code commentsComment mentions “screenshot,” which is not actionable and may go stale. Keep comments tied to API docs or endpoint metadata only.
Apply this diff to tighten the comment:
- // Filter props based on endpoint configuration and screenshot + // Filter props based on endpoint configuration and API documentation
34-35
: Clarify page description (positive integer)“Non-negative integer” suggests page 0 is valid, but the text says 1 is the start. Clarify to “positive integer” to avoid ambiguity.
- description: "Enables pagination and data retrieval control by skipping a specified number of items before fetching data. Page should be a non-negative integer, with 1 indicating the beginning of the dataset. Defaults to 1", + description: "Enables pagination and data retrieval control by skipping a specified number of items before fetching data. Page should be a positive integer, where 1 indicates the first page. Defaults to 1",
52-56
: Consider robust count derivation for $summaryAPIs sometimes return objects with metadata instead of an array. If that’s the case here,
response.data?.length
may be 0. Consider using a more robust count (e.g., check for arrays, or use an API-provided total if available).If the API returns a non-array with a total count, consider:
- const dataLength = response.data?.length || 0; + const dataLength = Array.isArray(response.data) + ? response.data.length + : (Number(response.data?.total) || Number(response.meta?.count) || 0);components/token_metrics/actions/get-correlation/get-correlation.mjs (2)
16-31
: Replace “Click here” with actionable or neutral copy; standardize capitalization“Click here” without a link degrades UX. Also, standardize “Comma-separated” usage.
tokenId: { ...FILTER_DEFINITIONS.token_id, - description: "Comma Separated Token IDs. Click here to access the list of token IDs. Example: 3375,3306", + description: "Comma-separated token IDs. Example: 3375,3306", }, symbol: { ...FILTER_DEFINITIONS.symbol, - description: "Comma Separated Token Symbols. Click here to access the list of token symbols. Example: BTC,ETH", + description: "Comma-separated token symbols. Example: BTC,ETH", }, category: { ...FILTER_DEFINITIONS.category, - description: "Comma separated category name. Click here to access the list of categories. Example: layer-1,nft", + description: "Comma-separated category name. Example: layer-1,nft", }, exchange: { ...FILTER_DEFINITIONS.exchange, - description: "Comma separated exchange name. Click here to access the list of exchanges. Example: gate,binance", + description: "Comma-separated exchange name. Example: binance,gate", },
46-47
: Clarify page description (positive integer)Same minor wording nit as other files.
- description: "Enables pagination and data retrieval control by skipping a specified number of items before fetching data. Page should be a non-negative integer, with 1 indicating the beginning of the dataset. Defaults to 1", + description: "Enables pagination and data retrieval control by skipping a specified number of items before fetching data. Page should be a positive integer, where 1 indicates the first page. Defaults to 1",components/token_metrics/actions/get-crypto-investors/get-crypto-investors.mjs (2)
29-30
: Clarify page description (positive integer)Minor wording cleanup for consistency across actions.
- description: "Enables pagination and data retrieval control by skipping a specified number of items before fetching data. Page should be a non-negative integer, with 1 indicating the beginning of the dataset. Defaults to 1", + description: "Enables pagination and data retrieval control by skipping a specified number of items before fetching data. Page should be a positive integer, where 1 indicates the first page. Defaults to 1",
44-50
: Optional: avoid computing filter summary for endpoints with no filtersSince
endpoint.filters
is empty,generateFilterSummary
always returns an empty string. You can skip it to avoid extra work, though the cost is minimal.- // Generate summary using utility function - const filterSummary = generateFilterSummary(this, endpoint.filters); - // Use $ context for export if ($ && $.export) { const dataLength = response.data?.length || 0; - $.export("$summary", `Successfully retrieved ${dataLength} crypto investors${filterSummary}`); + $.export("$summary", `Successfully retrieved ${dataLength} crypto investors`); }components/token_metrics/actions/get-fundamental-grades/get-fundamental-grades.mjs (2)
16-27
: Replace “Click here” and standardize phrasingImprove prop descriptions by removing “Click here” and using consistent casing and hyphenation.
tokenId: { ...FILTER_DEFINITIONS.token_id, - description: "Click here to access the list of token IDs. Example: 3375", + description: "Token IDs. Example: 3375", }, tokenName: { ...FILTER_DEFINITIONS.token_name, - description: "Crypto Asset Names (e.g., Bitcoin, Ethereum). Click here to access the list of token names.", + description: "Crypto asset names (e.g., Bitcoin, Ethereum).", }, symbol: { ...FILTER_DEFINITIONS.symbol, - description: "Click here to access the list of token symbols. Example: BTC,ETH", + description: "Token symbols. Example: BTC,ETH", },
42-43
: Clarify page description (positive integer)Same pagination copy nit.
- description: "Enables pagination and data retrieval control by skipping a specified number of items before fetching data. Page should be a non-negative integer, with 1 indicating the beginning of the dataset. Defaults to 1", + description: "Enables pagination and data retrieval control by skipping a specified number of items before fetching data. Page should be a positive integer, where 1 indicates the first page. Defaults to 1",components/token_metrics/actions/get-trading-signals/get-trading-signals.mjs (4)
27-38
: Add default and description for pagination props to match other actionsLimit/page props lack descriptions and defaults, unlike other actions in this PR. Add them for consistency and better UX.
limit: { propDefinition: [ tokenMetrics, "limit", ], + description: "Limit the number of items in response. Defaults to 50", + default: 50, }, page: { propDefinition: [ tokenMetrics, "page", ], + description: "Enables pagination and data retrieval control by skipping a specified number of items before fetching data. Page should be a positive integer, where 1 indicates the first page. Defaults to 1", + default: 1, },
54-56
: Optional: include a result count in the success summaryMost new actions surface a count in $summary. Consider doing the same for consistency.
- if ($ && $.export) { - $.export("$summary", `Successfully retrieved trading signals${filterSummary}`); - } + if ($ && $.export) { + const dataLength = response.data?.length || 0; + $.export("$summary", `Successfully retrieved ${dataLength} trading signals${filterSummary}`); + }
16-25
: Optional: basic date validation can improve DXGiven
startDate
/endDate
accept YYYY-MM-DD, consider minimal validation and a friendly error message pre-request to catch obvious mistakes early.If you want, I can provide a small helper to validate date format and ordering and wire it before the API call.
1-73
: Reduce duplication via a small shared runner utilityMultiple actions share the same flow: build params -> call client -> format $summary -> rethrow with status. Consider extracting a helper like
runEndpointAction({ $, endpoint, methodName, props, successSummaryFormatter })
to cut repetition and centralize error handling.I can sketch a reusable helper if you’d like to move in that direction.
components/token_metrics/actions/get-tokens/get-tokens.mjs (3)
23-34
: Set defaults and descriptions for pagination props to match other actionsOther actions in this package define defaults (limit=50, page=1) and include helpful descriptions. Align this action for consistency and better UX.
Apply this diff:
limit: { propDefinition: [ tokenMetrics, "limit", ], + description: "Limit the number of items in response. Defaults to 50", + default: 50, }, page: { propDefinition: [ tokenMetrics, "page", ], + description: "Enables pagination and data retrieval control by skipping a specified number of items before fetching data. Page should be a non-negative integer, with 1 indicating the beginning of the dataset. Defaults to 1", + default: 1, },
46-54
: Include result count in success summary for parity with other actionsOther actions export the number of items retrieved; this one doesn’t. Small UX improvement for consistency.
Apply this diff:
- // Generate summary using utility function + // Generate summary using utility function const filterSummary = generateFilterSummary(this, endpoint.filters); // Use $ context for export if ($ && $.export) { - $.export("$summary", `Successfully retrieved tokens list${filterSummary}`); + const dataLength = response.data?.length || 0; + $.export("$summary", `Successfully retrieved ${dataLength} tokens${filterSummary}`); }
36-66
: Optional: Offer built-in auto-pagination toggleConsider adding a boolean prop (e.g., paginateAll) to fetch all pages automatically, applying the shared limit/page props under the hood. This aligns with the Pipedream guideline to handle pagination where feasible.
If helpful, I can draft a minimal loop using the existing client and merge all pages into one array response.
components/token_metrics/actions/get-tm-grades/get-tm-grades.mjs (2)
15-15
: Tighten the commentRemove reference to “screenshot” to keep code comments source-agnostic.
- // Filter props based on endpoint configuration and screenshot + // Filter props based on endpoint configuration
16-27
: Replace “Click here” text with direct doc linksThe descriptions reference “Click here” without an actual link, which isn’t actionable in many UIs. Link to the Tokens endpoint so users can discover IDs/names/symbols.
tokenId: { ...FILTER_DEFINITIONS.token_id, - description: "Click here to access the list of token IDs. Example: 3375", + description: "Comma-separated Token IDs. Example: 3375. See the Tokens endpoint for the full list: https://developers.tokenmetrics.com/reference/tokens", }, tokenName: { ...FILTER_DEFINITIONS.token_name, - description: "Crypto Asset Names (e.g., Bitcoin, Ethereum). Click here to access the list of token names.", + description: "Crypto asset names (e.g., Bitcoin, Ethereum). See the Tokens endpoint for the full list: https://developers.tokenmetrics.com/reference/tokens", }, symbol: { ...FILTER_DEFINITIONS.symbol, - description: "Click here to access the list of token symbols. Example: BTC,ETH", + description: "Comma-separated token symbols. Example: BTC,ETH. See the Tokens endpoint for the full list: https://developers.tokenmetrics.com/reference/tokens", },components/token_metrics/actions/get-indices-performance/get-indices-performance.mjs (2)
61-63
: Include index ID in the success summaryImproves observability of which index was queried when reviewing step output.
- const dataLength = response.data?.length || 0; - $.export("$summary", `Successfully retrieved historical performance data for index with ${dataLength} data points${filterSummary}`); + const dataLength = response.data?.length || 0; + $.export("$summary", `Successfully retrieved historical performance data for index ${this.id} with ${dataLength} data points${filterSummary}`);
14-27
: Optional: Validate date inputsIf feasible, lightly validate YYYY-MM-DD format before calling the API to fail fast with actionable errors.
Example:
const DATE_RE = /^\d{4}-\d{2}-\d{2}$/; if (this.startDate && !DATE_RE.test(this.startDate)) { throw new Error("startDate must be in YYYY-MM-DD format"); } if (this.endDate && !DATE_RE.test(this.endDate)) { throw new Error("endDate must be in YYYY-MM-DD format"); }components/token_metrics/actions/get-market-metrics/get-market-metrics.mjs (1)
16-23
: Optional: Add basic date format validationAs with other date-based actions, consider a lightweight YYYY-MM-DD check to provide earlier, clearer errors to users before hitting the API.
Example:
const DATE_RE = /^\d{4}-\d{2}-\d{2}$/; if (this.startDate && !DATE_RE.test(this.startDate)) throw new Error("startDate must be in YYYY-MM-DD format"); if (this.endDate && !DATE_RE.test(this.endDate)) throw new Error("endDate must be in YYYY-MM-DD format");components/token_metrics/actions/get-ai-reports/get-ai-reports.mjs (3)
17-23
: Replace “Click here” text with direct doc links and consistent phrasingUse direct links and consistent “Comma-separated …” phrasing, mirroring other actions.
tokenId: { ...FILTER_DEFINITIONS.token_id, - description: "Comma Separated Token IDs. Click here to access the list of token IDs. Example: 37493,3484", + description: "Comma-separated Token IDs. Example: 37493,3484. See the Tokens endpoint for the full list: https://developers.tokenmetrics.com/reference/tokens", }, symbol: { ...FILTER_DEFINITIONS.symbol, - description: "Comma Separated Token Symbols. Click here to access the list of token symbols. Example: APX,PAAL", + description: "Comma-separated token symbols. Example: APX,PAAL. See the Tokens endpoint for the full list: https://developers.tokenmetrics.com/reference/tokens", },
56-59
: Fix success summary wording (“reports” vs “tokens”)The endpoint returns reports; the summary currently says “tokens.”
- const dataLength = response.data?.length || 0; - $.export("$summary", `Successfully retrieved AI reports for ${dataLength} tokens${filterSummary}`); + const dataLength = response.data?.length || 0; + $.export("$summary", `Successfully retrieved ${dataLength} AI reports${filterSummary}`);
42-73
: Optional: Offer auto-pagination to fetch all reportsConsider adding a paginateAll boolean prop and loop through pages until exhaustion to comply with “handle pagination” guidance.
I can sketch a minimal implementation using your existing limit/page props that aggregates all pages before returning.
components/token_metrics/actions/get-technology-grades-historical/get-technology-grades-historical.mjs (1)
30-31
: Fix date format examples to use past datesThe date examples show "2025-07-01" and "2025-07-05" which are future dates. For historical data retrieval, it would be more appropriate to use past dates in the examples.
- description: "Start Date accepts date as a string - YYYY-MM-DD format. Example: 2025-07-01", + description: "Start Date accepts date as a string - YYYY-MM-DD format. Example: 2024-01-01",- description: "End Date accepts date as a string - YYYY-MM-DD format. Example: 2025-07-05", + description: "End Date accepts date as a string - YYYY-MM-DD format. Example: 2024-01-31",Also applies to: 34-35
components/token_metrics/token_metrics.app.mjs (2)
64-303
: Consider generating endpoint methods programmaticallyThe comment on line 63 suggests these methods could be generated automatically. Given the repetitive nature and the existence of
ENDPOINTS
constant, consider implementing a factory pattern to reduce code duplication.Would you like me to help create a factory function that generates these endpoint methods dynamically from the
ENDPOINTS
constant? This would reduce the file size and make it easier to add new endpoints in the future.
51-62
: Consider adding request/response logging for debuggingFor better debugging capabilities, consider adding optional logging of requests and responses when a debug flag is set.
async makeApiCall({ $ = this, endpoint, params = {}, + debug = false, }) { + if (debug) { + console.log(`Making API call to ${endpoint}`, params); + } return this._makeRequest({ $, path: endpoint, method: "GET", params, }); },
components/token_metrics/actions/get-market-metrics/get-market-metrics.mjs
Outdated
Show resolved
Hide resolved
.../token_metrics/actions/get-technology-grades-historical/get-technology-grades-historical.mjs
Outdated
Show resolved
Hide resolved
…Gautam7101/token-metrics-api-pipedream into ENG-8702,ENG-8703,ENG-8704
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.
Hi there, thanks for your contribution! I see you've added a lot of components, that is greatly appreciated.
I've commented on a few general changes that need to be made across most or all of the components, before this is ready to be merged. Let me know if you need any assistance
components/token_metrics/actions/get-ai-reports/get-ai-reports.mjs
Outdated
Show resolved
Hide resolved
components/token_metrics/actions/get-ai-reports/get-ai-reports.mjs
Outdated
Show resolved
Hide resolved
components/token_metrics/actions/get-ai-reports/get-ai-reports.mjs
Outdated
Show resolved
Hide resolved
components/token_metrics/actions/get-ai-reports/get-ai-reports.mjs
Outdated
Show resolved
Hide resolved
components/token_metrics/actions/get-daily-ohlcv/get-daily-ohlcv.mjs
Outdated
Show resolved
Hide resolved
components/token_metrics/actions/get-moonshot-tokens/get-moonshot-tokens.mjs
Outdated
Show resolved
Hide resolved
components/token_metrics/actions/get-resistance-support/get-resistance-support.mjs
Outdated
Show resolved
Hide resolved
- Add markdown formatting to all example values with backticks - Highlight date formats (`YYYY-MM-DD`) in prop descriptions - Add `min: 1` validation to all page props across 19 action files - Remove verbose pagination descriptions in favor of built-in validation - Standardize prop definitions using `propDefinitions` from app file - Convert comma-separated string props to `string[]` type for better UX - Remove redundant `if ($ && $.export)` checks from all actions - Remove custom `try/catch` blocks to leverage Pipedream's native error handling - Clean up `handleApiError` utility function and related imports - Fix prop descriptions to use proper options instead of text descriptions - Update README.md to be more concise and professional per feedback This refactor improves code maintainability, user experience, and follows Pipedream component best practices for validation, error handling, and documentation formatting.
- Add markdown formatting to all example values with backticks - Highlight date formats (`YYYY-MM-DD`) in prop descriptions - Add `min: 1` validation to all page props across 19 action files - Remove verbose pagination descriptions in favor of built-in validation - Standardize prop definitions using `propDefinitions` from app file - Convert comma-separated string props to `string[]` type for better UX - Remove redundant `if ($ && $.export)` checks from all actions - Remove custom `try/catch` blocks to leverage Pipedream's native error handling - Clean up `handleApiError` utility function and related imports - Fix prop descriptions to use proper options instead of text descriptions - Update README.md to be more concise and professional per feedback This refactor improves code maintainability, user experience, and follows Pipedream component best practices for validation, error handling, and documentation formatting.
@GTFalcao I’ve implemented all the required changes, it should be good now. Can you please recheck? |
WHY
Summary by CodeRabbit