-
Notifications
You must be signed in to change notification settings - Fork 1
Add dune support and export hooks #145
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: main
Are you sure you want to change the base?
Conversation
|
Important Review skippedDraft detected. Please check the settings in the CodeRabbit UI or the You can disable this status message by setting the WalkthroughThis change refactors and expands the Dune Analytics hooks querying infrastructure. It introduces parameter-object patterns for repository and service interfaces, adds new endpoints and pagination, implements and exports new repository and service classes, and provides comprehensive tests and type guards for data validation. Previous implementations and type signatures are replaced or removed. Changes
Sequence Diagram(s)sequenceDiagram
participant API as API Route
participant HooksService as HooksServiceImpl
participant Repo as DuneRepositoryImpl
participant Dune as Dune API
API->>HooksService: getHooks({blockchain, period, maxWaitTimeMs})
HooksService->>Repo: executeQuery({queryId, parameters})
Repo->>Dune: POST /execute_query
Dune-->>Repo: executionId
HooksService->>Repo: waitForExecution({executionId, maxWaitTimeMs, typeAssertion})
Repo->>Dune: GET /execution_results (polling)
Dune-->>Repo: result rows
Repo-->>HooksService: validated rows
HooksService-->>API: HookData[]
sequenceDiagram
participant API as API Route
participant HooksService as HooksServiceImpl
participant Repo as DuneRepositoryImpl
participant Dune as Dune API
API->>HooksService: getLatestHooks({limit, offset})
HooksService->>Repo: getQueryResults({queryId, limit, offset, typeAssertion})
Repo->>Dune: GET /query_results
Dune-->>Repo: result rows
Repo-->>HooksService: validated rows
HooksService-->>API: HookData[]
Estimated code review effort🎯 4 (Complex) | ⏱️ ~40 minutes Poem
✨ 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. 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: 7
🧹 Nitpick comments (4)
libs/services/src/HooksService/HooksServiceImpl.ts (1)
20-41: Consider adding service-level error handling.While the implementation is correct, wrapping errors would provide better context for debugging.
async getHooks(params: GetHooksParams): Promise<HookData[]> { const { blockchain, period, maxWaitTimeMs } = params; - // Execute the query with parameters - const execution = await this.duneRepository.executeQuery({ - queryId: DEFAULT_QUERY_ID, - parameters: { - blockchain, - period, - }, - }); - - // Wait for execution to complete with type assertion - const result = await this.duneRepository.waitForExecution<HookData>({ - executionId: execution.execution_id, - typeAssertion: isHookData, - maxWaitTimeMs, - }); - - // The data is already typed as HookData from the generic repository - return result.result.rows; + try { + // Execute the query with parameters + const execution = await this.duneRepository.executeQuery({ + queryId: DEFAULT_QUERY_ID, + parameters: { + blockchain, + period, + }, + }); + + // Wait for execution to complete with type assertion + const result = await this.duneRepository.waitForExecution<HookData>({ + executionId: execution.execution_id, + typeAssertion: isHookData, + maxWaitTimeMs, + }); + + // The data is already typed as HookData from the generic repository + return result.result.rows; + } catch (error) { + throw new Error(`Failed to fetch hooks data: ${error.message}`); + } }apps/api/src/app/routes/hooks.ts (2)
30-47: Avoid duplicating the HookData interface.The response interface duplicates the
HookDatatype definition. Consider importing and reusing it.+import { HookData } from '@cowprotocol/services'; interface HooksResponse { - hooks: Array<{ - environment: string; - block_time: string; - is_bridging: boolean; - success: boolean; - app_code: string; - destination_chain_id: number | null; - destination_token_address: string | null; - hook_type: string; - app_id: string | null; - target: string; - gas_limit: number; - app_hash: string; - tx_hash: string; - }>; + hooks: HookData[]; count: number; }
164-197: Extract duplicate response schema.The response schema is identical to the
/hooksendpoint. Consider extracting it to reduce duplication.+const hooksResponseSchema = { + type: 'object', + properties: { + hooks: { + type: 'array', + items: { + type: 'object', + properties: { + environment: { type: 'string' }, + block_time: { type: 'string' }, + is_bridging: { type: 'boolean' }, + success: { type: 'boolean' }, + app_code: { type: 'string' }, + destination_chain_id: { type: ['number', 'null'] }, + destination_token_address: { type: ['string', 'null'] }, + hook_type: { type: 'string' }, + app_id: { type: ['string', 'null'] }, + target: { type: 'string' }, + gas_limit: { type: 'number' }, + app_hash: { type: 'string' }, + tx_hash: { type: 'string' }, + }, + }, + }, + count: { type: 'number' }, + }, +}; // Then use it in both endpoints: response: { - 200: { /* current schema */ } + 200: hooksResponseSchema }libs/services/src/HooksService/HooksService.ts (1)
61-62: Track the temporary PoC method removal.The TODO indicates
getLatestHooksis temporary due to parameter issues withgetHooks. This aligns with the PR objectives mentioning parameterization problems.Would you like me to create an issue to track the removal of this method once the parameterization issue is resolved?
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (11)
apps/api/src/app/inversify.config.ts(2 hunks)apps/api/src/app/routes/hooks.ts(5 hunks)libs/repositories/src/index.ts(1 hunks)libs/repositories/src/repos/DuneRepository/DuneRepository.spec.ts(1 hunks)libs/repositories/src/repos/DuneRepository/DuneRepository.ts(1 hunks)libs/repositories/src/repos/DuneRepository/DuneRepositoryImpl.ts(1 hunks)libs/services/src/HooksService/HooksService.ts(2 hunks)libs/services/src/HooksService/HooksServiceImpl.spec.ts(1 hunks)libs/services/src/HooksService/HooksServiceImpl.ts(1 hunks)libs/services/src/HooksService/utils/isHookData.ts(1 hunks)libs/services/src/index.ts(1 hunks)
🧰 Additional context used
🧠 Learnings (1)
libs/repositories/src/repos/DuneRepository/DuneRepository.spec.ts (1)
Learnt from: anxolin
PR: #127
File: libs/repositories/src/datasources/orm/postgresOrm.ts:7-12
Timestamp: 2025-04-23T09:18:47.273Z
Learning: The ensureEnvs utility from @cowprotocol/shared causes issues when used with TypeORM migrations in the repositories module, so direct assert statements are used instead for environment variable validation in the ORM datasource configuration.
🧬 Code Graph Analysis (3)
apps/api/src/app/inversify.config.ts (1)
libs/services/src/HooksService/HooksServiceImpl.ts (1)
HooksServiceImpl(13-55)
libs/services/src/HooksService/utils/isHookData.ts (1)
libs/services/src/HooksService/HooksService.ts (1)
HookData(31-45)
libs/services/src/HooksService/HooksServiceImpl.ts (3)
libs/services/src/HooksService/HooksService.ts (4)
HooksService(58-63)GetHooksParams(47-51)HookData(31-45)GetLatestHooksParams(53-56)libs/repositories/src/repos/DuneRepository/DuneRepository.ts (1)
DuneRepository(58-72)libs/services/src/HooksService/utils/isHookData.ts (1)
isHookData(4-58)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (4)
- GitHub Check: docker (apps/telegram)
- GitHub Check: docker (apps/api)
- GitHub Check: docker (apps/notification-producer)
- GitHub Check: docker (apps/twap)
🔇 Additional comments (19)
apps/api/src/app/inversify.config.ts (1)
33-33: LGTM! Service implementation updated correctly.The import and binding changes properly integrate the new
HooksServiceImplwith itsduneRepositorydependency.Also applies to: 102-102
libs/repositories/src/index.ts (1)
60-60: Export addition follows established pattern.The new export for
DuneRepositoryImplis correctly placed and consistent with other repository exports.libs/services/src/index.ts (1)
11-11: Service export added correctly.The export for
HooksServiceImplfollows the established pattern for service exports.libs/services/src/HooksService/utils/isHookData.ts (1)
4-58: Well-implemented type guard with comprehensive validation.The type guard correctly validates all required and nullable fields of the
HookDatainterface with proper type checking.libs/repositories/src/repos/DuneRepository/DuneRepository.spec.ts (1)
1-518: Comprehensive test coverage with realistic scenarios.The test suite thoroughly covers all methods with success cases, error handling, and edge cases. Good use of realistic mock data and proper test isolation.
libs/services/src/HooksService/HooksServiceImpl.spec.ts (3)
10-151: Well-structured mock implementation!The
MockDuneRepositoryclass provides a comprehensive mock with proper type validation simulation and helpful error messages for debugging test failures.
153-204: Comprehensive test coverage for successful hook retrieval!The test properly validates all fields of the HookData interface, including nullable fields.
326-416: Excellent test coverage for edge cases and enum combinations!The tests properly handle empty results and validate all supported blockchain/period combinations, ensuring comprehensive coverage.
libs/repositories/src/repos/DuneRepository/DuneRepositoryImpl.ts (4)
1-26: Well-structured repository implementation!The class setup with configurable base URL and reasonable default constants provides good flexibility.
27-57: Correct implementation of query execution!The method properly handles parameter serialization and includes helpful logging.
125-138: Clean implementation of paginated query results!The method correctly handles pagination parameters.
140-181: Robust API request handling!The method includes proper authentication, comprehensive logging, and clear error messages.
libs/services/src/HooksService/HooksServiceImpl.ts (1)
46-51: Ignore removal oftypeAssertionand renaming of the constantThe
getQueryResultsmethod accepts atypeAssertionparameter because itsparamstype (GetQueryResultsParams<T>) extendsWithTypeAssertion<T>. The constant nameDEFAULT_QUERY_LATESTSmatches its declaration and should not be renamed.Evidence:
- In
libs/repositories/src/repos/DuneRepository/DuneRepository.ts:export interface GetQueryResultsParams<T> extends WithTypeAssertion<T> { queryId: number; limit?: number; offset?: number; }- The repository interface declares:
getQueryResults<T>( params: GetQueryResultsParams<T> ): Promise<DuneResultResponse<T>>;Please disregard the original suggestion.
Likely an incorrect or invalid review comment.
apps/api/src/app/routes/hooks.ts (1)
50-140: Well-implemented hooks endpoint!The endpoint properly validates parameters using enums, handles errors gracefully, and includes appropriate caching.
libs/services/src/HooksService/HooksService.ts (1)
5-29: Excellent type definition pattern!The single source of truth approach for enum values with both compile-time types and runtime arrays is a best practice.
libs/repositories/src/repos/DuneRepository/DuneRepository.ts (4)
31-37: Well-structured parameter object patternThe
PerformanceTiertype andExecuteQueryParamsinterface are well-designed. The use of a union type for performance tiers provides type safety while maintaining flexibility.
39-46: Good use of interface compositionThe interfaces properly utilize TypeScript's extension mechanism to compose functionality. The optional
maxWaitTimeMsparameter provides sensible timeout configuration.
48-56: Excellent type assertion pattern for runtime safetyThe
WithTypeAssertion<T>interface provides a clean way to validate data at runtime using TypeScript's type predicate pattern. The pagination support inGetQueryResultsParamsis well-structured.
58-72: executeQuery correctly forwards parameters and performanceThe
executeQueryimplementation appends bothparameters(asquery_parameters) andperformanceto the request URL, and the existing Jest tests confirm all combinations pass through as intended. No changes are needed.
| limit: { | ||
| type: 'number', | ||
| default: 1000, | ||
| description: 'Number of hooks to return', |
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.
Fix inconsistent default limit values.
The schema specifies default: 1000 but the handler uses limit: request.query.limit || 100. These should be consistent.
limit: {
type: 'number',
- default: 1000,
+ default: 100,
description: 'Number of hooks to return',
},Also applies to: 210-211
🤖 Prompt for AI Agents
In apps/api/src/app/routes/hooks.ts at lines 152-155 and also lines 210-211, the
default limit value in the schema is set to 1000 but the handler uses 100 as the
fallback limit. To fix this inconsistency, update the handler code to use 1000
as the default limit value to match the schema's default, ensuring both places
use the same default number for the limit parameter.
| return ( | ||
| typeof data === 'object' && data !== null && 'environment' in data | ||
| ); | ||
| fail('Expected error to be thrown'); | ||
| } catch (error) { | ||
| const errorMessage = | ||
| error instanceof Error ? error.message : String(error); | ||
|
|
||
| // Check that error message contains expected information | ||
| expect(errorMessage).toContain( | ||
| 'Data validation failed for execution test-execution-id' | ||
| ); | ||
| expect(errorMessage).toContain('Invalid rows found: 1/2'); | ||
| expect(errorMessage).toContain('Example invalid row (index 1):'); | ||
| expect(errorMessage).toContain('"id": 2'); | ||
| expect(errorMessage).toContain('"name": "Test 2"'); | ||
| expect(errorMessage).toContain( | ||
| 'Expected columns from Dune: id, name, active' | ||
| ); | ||
| } | ||
| }; |
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.
Strengthen the type assertion function in the test.
The type assertion function only checks for the presence of the 'environment' property, which doesn't properly validate all required fields of the HookData type. This could lead to false test passes.
- const isHookData = (
- data: unknown
- ): data is {
- environment: string;
- block_time: string;
- is_bridging: boolean;
- success: boolean;
- app_code: string;
- destination_chain_id: number | null;
- destination_token_address: string | null;
- hook_type: string;
- app_id: string | null;
- target: string;
- gas_limit: number;
- app_hash: string;
- tx_hash: string;
- } => {
- return (
- typeof data === 'object' && data !== null && 'environment' in data
- );
- };
+ // Import the actual isHookData function from the utils
+ import { isHookData } from '@cowprotocol/services';Alternatively, if you want to keep it inline for testing purposes, implement proper validation:
const isHookData = (
data: unknown
): data is {
environment: string;
block_time: string;
is_bridging: boolean;
success: boolean;
app_code: string;
destination_chain_id: number | null;
destination_token_address: string | null;
hook_type: string;
app_id: string | null;
target: string;
gas_limit: number;
app_hash: string;
tx_hash: string;
} => {
- return (
- typeof data === 'object' && data !== null && 'environment' in data
- );
+ if (typeof data !== 'object' || data === null) return false;
+ const d = data as Record<string, unknown>;
+ return (
+ typeof d.environment === 'string' &&
+ typeof d.block_time === 'string' &&
+ typeof d.is_bridging === 'boolean' &&
+ typeof d.success === 'boolean' &&
+ typeof d.app_code === 'string' &&
+ (d.destination_chain_id === null || typeof d.destination_chain_id === 'number') &&
+ (d.destination_token_address === null || typeof d.destination_token_address === 'string') &&
+ typeof d.hook_type === 'string' &&
+ (d.app_id === null || typeof d.app_id === 'string') &&
+ typeof d.target === 'string' &&
+ typeof d.gas_limit === 'number' &&
+ typeof d.app_hash === 'string' &&
+ typeof d.tx_hash === 'string'
+ );
};Committable suggestion skipped: line range outside the PR's diff.
🤖 Prompt for AI Agents
In libs/repositories/src/repos/DuneRepository/DuneRepository.spec.ts around
lines 369 to 372, the type assertion function only checks if the 'environment'
property exists on the data object, which is insufficient to validate the full
HookData type. To fix this, enhance the function to verify all required
properties of HookData are present and have the correct types, ensuring the test
accurately validates the data structure and prevents false positives.
| const invalidRows: Array<{ index: number; data: unknown }> = []; | ||
| const isValid = result.result.rows.every((row, index) => { | ||
| if (!typeAssertion(row)) { | ||
| invalidRows.push({ index, data: row }); | ||
| return false; | ||
| } | ||
| return true; | ||
| }); |
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.
Fix validation logic to check all rows.
The current implementation stops validation at the first invalid row due to the early return on line 88, but the error message suggests all invalid rows are collected. This inconsistency should be fixed.
- const isValid = result.result.rows.every((row, index) => {
- if (!typeAssertion(row)) {
- invalidRows.push({ index, data: row });
- return false;
- }
- return true;
- });
+ result.result.rows.forEach((row, index) => {
+ if (!typeAssertion(row)) {
+ invalidRows.push({ index, data: row });
+ }
+ });
+ const isValid = invalidRows.length === 0;📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| const invalidRows: Array<{ index: number; data: unknown }> = []; | |
| const isValid = result.result.rows.every((row, index) => { | |
| if (!typeAssertion(row)) { | |
| invalidRows.push({ index, data: row }); | |
| return false; | |
| } | |
| return true; | |
| }); | |
| const invalidRows: Array<{ index: number; data: unknown }> = []; | |
| result.result.rows.forEach((row, index) => { | |
| if (!typeAssertion(row)) { | |
| invalidRows.push({ index, data: row }); | |
| } | |
| }); | |
| const isValid = invalidRows.length === 0; |
🤖 Prompt for AI Agents
In libs/repositories/src/repos/DuneRepository/DuneRepositoryImpl.ts around lines
84 to 91, the validation logic uses Array.every which stops at the first invalid
row, preventing collection of all invalid rows. Replace Array.every with
Array.forEach or a similar iteration method to check every row, push all invalid
rows to invalidRows, and then determine validity after the loop to ensure all
invalid rows are collected as intended.
| @@ -1,7 +1,33 @@ | |||
| import { DuneRepository } from '@cowprotocol/repositories'; | |||
| import { PerformanceTier } from '@cowprotocol/repositories'; | |||
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.
Remove unused import.
PerformanceTier is imported but not used in this file.
-import { PerformanceTier } from '@cowprotocol/repositories';📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| import { PerformanceTier } from '@cowprotocol/repositories'; | |
| // (The import of `PerformanceTier` has been removed; no other changes are needed.) |
🤖 Prompt for AI Agents
In libs/services/src/HooksService/HooksService.ts at line 1, the import of
PerformanceTier from '@cowprotocol/repositories' is unused. Remove this import
statement to clean up the code and avoid unnecessary dependencies.
| const executeQuerySpy = jest.spyOn(mockRepository, 'executeQuery'); | ||
| const waitForExecutionSpy = jest.spyOn( | ||
| mockRepository, | ||
| 'waitForExecution' |
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.
💡 Verification agent
🧩 Analysis chain
Verify default limit value consistency.
The test expects limit: request.query.limit || 100 but the actual route implementation uses limit: request.query.limit || 100 while the schema specifies default: 1000. This inconsistency should be addressed.
🏁 Script executed:
#!/bin/bash
# Description: Check for inconsistent default limit values across the codebase
# Search for default limit values in the codebase
rg -A 2 -B 2 "limit.*default|default.*limit" --type tsLength of output: 56
I couldn’t find any matches for generic “limit.*default” patterns. Let’s narrow down to the actual implementation and schema defaults:
🏁 Script executed:
#!/bin/bash
# Find where the route reads request.query.limit
rg -n "request.query.limit" --type ts
# Find any schema declaring a default of 1000
rg -n "default.*1000" --type ts
# Find Zod number() definitions with default()
rg -n "z\\.number.*default" --type tsLength of output: 258
Align default limit value between schema and implementation
The route’s schema (apps/api/src/app/routes/hooks.ts:154) specifies a default limit of 1000, but the implementation falls back to 100 (apps/api/src/app/routes/hooks.ts:210) and the test assumes 100. These must be consistent.
• Schema default at line 154:
default: 1000,• Implementation fallback at line 210:
limit: request.query.limit || 100,Action required:
- Decide on the intended default (100 or 1000).
- Update either the schema’s
defaultor the implementation’s fallback (and tests) so they match.
🤖 Prompt for AI Agents
In libs/services/src/HooksService/HooksServiceImpl.spec.ts at line 210, the
default limit value used in the implementation (100) does not match the schema
default (1000) defined in apps/api/src/app/routes/hooks.ts at line 154. Decide
whether the default limit should be 100 or 1000, then update the implementation
fallback value at line 210 and the related tests in HooksServiceImpl.spec.ts to
use the chosen default, ensuring consistency with the schema default.
| const DEFAULT_QUERY_ID = 5302473; // Example on executing a query | ||
| const DEFAULT_QUERY_LATESTS = 5527161; // Example on getting of a query |
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.
🛠️ Refactor suggestion
Consider making query IDs configurable and fix typo.
- The hardcoded query IDs should ideally be configurable through environment variables or constructor parameters
- Typo in comment: "getting of a query" → "getting results of a query"
-const DEFAULT_QUERY_ID = 5302473; // Example on executing a query
-const DEFAULT_QUERY_LATESTS = 5527161; // Example on getting of a query
+const DEFAULT_QUERY_ID = process.env.DUNE_HOOKS_QUERY_ID ? parseInt(process.env.DUNE_HOOKS_QUERY_ID) : 5302473; // Query for executing hooks with parameters
+const DEFAULT_QUERY_LATEST_ID = process.env.DUNE_HOOKS_LATEST_QUERY_ID ? parseInt(process.env.DUNE_HOOKS_LATEST_QUERY_ID) : 5527161; // Query for getting latest hooks results📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| const DEFAULT_QUERY_ID = 5302473; // Example on executing a query | |
| const DEFAULT_QUERY_LATESTS = 5527161; // Example on getting of a query | |
| const DEFAULT_QUERY_ID = process.env.DUNE_HOOKS_QUERY_ID | |
| ? parseInt(process.env.DUNE_HOOKS_QUERY_ID, 10) | |
| : 5302473; // Query for executing hooks with parameters | |
| const DEFAULT_QUERY_LATEST_ID = process.env.DUNE_HOOKS_LATEST_QUERY_ID | |
| ? parseInt(process.env.DUNE_HOOKS_LATEST_QUERY_ID, 10) | |
| : 5527161; // Query for getting latest hooks results |
🤖 Prompt for AI Agents
In libs/services/src/HooksService/HooksServiceImpl.ts around lines 10 to 11, the
query IDs are hardcoded and the comment contains a typo. Refactor the code to
accept these query IDs as configurable parameters, such as environment variables
or constructor arguments, instead of hardcoding them. Also, correct the comment
typo by changing "getting of a query" to "getting results of a query" for
clarity.
| @@ -0,0 +1,58 @@ | |||
| import { DuneRepository, PerformanceTier } from '@cowprotocol/repositories'; | |||
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.
Remove unused imports.
The imports DuneRepository and PerformanceTier are not used in this file.
-import { DuneRepository, PerformanceTier } from '@cowprotocol/repositories';📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| import { DuneRepository, PerformanceTier } from '@cowprotocol/repositories'; |
🤖 Prompt for AI Agents
In libs/services/src/HooksService/utils/isHookData.ts at line 1, remove the
unused imports DuneRepository and PerformanceTier from
'@cowprotocol/repositories' since they are not used anywhere in the file.
This PR adds a repository to access dune queries, or execute them and get results.
It also exposes hook!
Motivation
We don't have a way to easily read in CoW Swap from Dune.
Soon we will need to implement the affiliate program, so I did this experimental PR to see if I can get the hooks (since we worked recently in creating some query to return the hooks for the bridge and swap feature 😃
Scope
This is experimental, I don't plan to use it yet in CoW Swap, but leave this easy to add any data we want in CoW Swap now, I think it will be very handy.
Repository
It can:
getQueryResults: Return the cached last execution for a given query. Allows paginationexecuteQuery: Execute a query. The query returns anexecution_idgetExecutionResults: Return the result for a givenexecution_idif readywaitForExecution: Waits for aexecution_idto be ready, and then return the resultHooks Service
getHooks: Returns hooks given some parameters (blockchainandperiod).getLatestHooks: Returns all the cached hooks for the last 30 days. This is kind of experimental query. In this PR I'm only interested on implementing a generic way to access dune and extract data so it can be exported nicely in our endpoints.New Endpoints
/hooks
/hooks/latest
Caveats
The parametrization of
getHooksis not working for me. I pass the parameters toexecuteQueryas I understood from the API, but somehow they are ignored. It's likely something silly, and since this is easily fixable by having a query with the parameters we want, and we don't plan to use this right now I didn't loose more time on this.Test
add API key for dune
Start service:
Go to:
http://localhost:3001
Get all hooks:
http://localhost:3001/hooks/latest?limit=1000&offset=0