Skip to content
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: migrate to latest ponder #14

Merged
merged 7 commits into from
Dec 11, 2024
Merged

feat: migrate to latest ponder #14

merged 7 commits into from
Dec 11, 2024

Conversation

royvardhan
Copy link
Member

@royvardhan royvardhan commented Dec 10, 2024

Summary by CodeRabbit

  • New Features

    • Introduced new database abstraction layer for streamlined data operations.
    • Added new schema definitions for various entities, enhancing modularity and type safety.
  • Bug Fixes

    • Improved error handling and control flow in database interactions.
  • Chores

    • Updated various package dependencies to their latest versions, ensuring compatibility and performance improvements.
    • Removed ponder-env.d.ts file.
    • Added ponder-env.d.ts to the .gitignore file.
    • Modified GitHub Actions workflow to allow updates to the lockfile during dependency installation.
    • Removed maxBlockRange property from network configurations of several contracts.

Copy link

coderabbitai bot commented Dec 10, 2024

Caution

Review failed

The pull request is closed.

Walkthrough

The pull request includes updates to several files, primarily focusing on enhancing the schema management and database interaction methods. Key changes involve upgrading dependencies in package.json, removing the ponder-env.d.ts file, and transitioning schema definitions in ponder.schema.ts to a more modular approach using onchainTable and onchainEnum. Additionally, the src/helpers.ts and src/index.ts files have been modified to standardize database interactions through a unified db object, improving maintainability and clarity. The src/types.ts file has seen the removal of a type alias, and a new entry has been added to .gitignore.

Changes

File Change Summary
package.json - Updated @ponder/core from 0.4.13 to 0.8.0-next.1
- Added abitype (0.10.2)
- Updated axios (1.6.7 to 1.7.7)
- Updated viem (1.19.3 to 2.21.3)
- Added hono (^4.5.0)
- Updated typescript (^5.2.2 to ^5.3.2)
- Updated Node.js engine requirement from >=18.14 to >=20
ponder-env.d.ts - Removed the file entirely, which included type declarations for the Ponder project.
ponder.schema.ts - Replaced createSchema with onchainTable and onchainEnum
- Introduced multiple new table exports and enums, including pointsSourceEnum and various entity tables
src/helpers.ts - Added imports for new tables from ../ponder.schema
- Updated database interaction methods to use db object instead of direct calls
src/index.ts - Integrated new database abstraction layer using db object for various event handlers
- Updated imports for new table constants
src/types.ts - Removed type alias Points defined as Context["db"]["Points"]
.gitignore - Added ponder-env.d.ts to the list of ignored files
.github/actions/setup/action.yml - Changed installation command from pnpm install --frozen-lockfile to pnpm install --no-frozen-lockfile

Possibly related PRs

🐰 In the meadow, changes bloom,
New tables rise, dispelling gloom.
With enums bright and types refined,
A clearer path for all to find.
Database calls now flow like streams,
In code we trust, fulfilling dreams! 🌼


📜 Recent review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Reviewing files that changed from the base of the PR and between 6584a54 and 06734a2.

📒 Files selected for processing (1)
  • ponder.config.ts (0 hunks)

🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Generate unit testing code for this file.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai generate unit testing code for this file.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and generate unit testing code.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

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)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR. (Experiment)
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 5

🧹 Outside diff range and nitpick comments (5)
ponder.schema.ts (2)

75-75: Specify default value for LMSeasons array

The LMSeasons field in the userHistoryTable is defined as t.bigint().array().notNull(). To prevent potential issues with null references, consider specifying a default value, such as an empty array.

Apply this diff to set a default empty array:

-export const userHistoryTable = onchainTable("UserHistory", (t) => ({
+export const userHistoryTable = onchainTable("UserHistory", (t) => ({
   // ...
-  LMSeasons: t.bigint().array().notNull(), // If the array is empty, the user has not participated in any season
+  LMSeasons: t.bigint().array().notNull().default([]), // Default to empty array if not provided
   // ...

Duplicate enum values detected in pointsSourceEnum

The verification revealed two issues:

  1. Several enum values appear twice in the schema, including stratosphere_enrollment, dex_aggregator_swap, and various other entries
  2. The generateLMSeasonEnum function generates unique values with pattern liquid_mining_first_wallet_season_${i} which are different from the duplicated values found

The duplicates appear to be in the schema file itself, not from the generated values. Here are the duplicated entries:

  • vape_staking_first_wallet
  • vape_staking_first_deposit
  • stratosphere_enrollment
  • liquid_mining_twelve_seasons
  • liquid_mining_three_seasons
  • liquid_mining_six_seasons
  • liquid_mining_one_season
  • liquid_mining_first_deposit
  • dex_aggregator_swap
  • dex_aggregator_1k_swaps
  • dex_aggregator_10k_swaps
  • dex_aggregator_100k_swaps
🔗 Analysis chain

Line range hint 39-55: Verify generated enum values for pointsSourceEnum

The pointsSourceEnum includes values generated by generateLMSeasonEnum(120). Ensure that the generated enum values are unique and correctly formatted, and that there are no duplicates or unintended values.

Run the following script to list all enum values and check for duplicates:


Let me verify the implementation of generateLMSeasonEnum to understand if it might be contributing to these duplicates.


Let me try a different approach to find the implementation of generateLMSeasonEnum.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify that `pointsSourceEnum` contains unique values

# Extract enum values from the schema file
grep -Po '(?<=")[^"]+(?=")' ponder.schema.ts | sort | uniq -c | sort -nr | awk '$1 > 1'

# Expected: No output, indicating no duplicate enum values

Length of output: 514


Script:

#!/bin/bash
# Search for the implementation of generateLMSeasonEnum
ast-grep --pattern 'function generateLMSeasonEnum' -A 20

Length of output: 58


Script:

#!/bin/bash
# Search for the implementation using ripgrep
rg -A 10 "const generateLMSeasonEnum"

# Also check if it might be defined as a regular function
rg -A 10 "function generateLMSeasonEnum"

# Look for any file that might contain this function
fd generateLMSeasonEnum

Length of output: 697

src/index.ts (1)

Line range hint 308-352: Ensure type consistency when comparing BigInt values

When comparing usdValueOfTrade >= MINIMUM_POINTS, confirm that both variables are of the same type BigInt to avoid unexpected behavior.

Additionally, verify that arithmetic operations involving BigInt are handled correctly throughout the code.

src/helpers.ts (2)

Line range hint 117-154: Consider transaction safety and initialization improvements

  1. The check-then-insert pattern could lead to race conditions.
  2. The LMSeasons array is initialized empty but its type isn't explicitly defined.

Consider these improvements:

export async function getOrCreateUserData(
  context: Context,
  tokenId: bigint,
  address: string
): Promise<UserHistory> {
  const { db } = context;
  const { chainId } = context.network;
  
+ return await db.transaction(async (tx) => {
+   let userHistory = await tx.find(userHistoryTable, {
+     id: `${address}-${chainId}`,
+   });
+   
+   const mainWallet = await getTokenIdOwner(tokenId, context);
+   
+   if (!userHistory) {
+     const LMSeasons: number[] = [];  // Explicit type
+     userHistory = await tx.insert(userHistoryTable)...
+     await tx.insert(userDataTable)...
+   }
+   
+   return userHistory;
+ });
}

Line range hint 337-393: Improve transaction safety in token data updates

The check-then-update pattern could lead to race conditions when multiple transactions attempt to update the same token data simultaneously.

Consider wrapping the operations in a transaction:

return await db.transaction(async (tx) => {
  let tokenIdData = await tx.find(tokenIdDataTable, ...);
  let tokenIdDataWeekly = await tx.find(tokenIdDataWeeklyTable, ...);
  
  if (!tokenIdData) {
    tokenIdData = await tx.insert(tokenIdDataTable)...;
  }
  
  if (!tokenIdDataWeekly) {
    tokenIdDataWeekly = await tx.insert(tokenIdDataWeeklyTable)...;
  }
  
  tokenIdData = await tx.update(tokenIdDataTable)...;
  tokenIdDataWeekly = await tx.update(tokenIdDataWeeklyTable)...;
  
  return tokenIdData;
});
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Reviewing files that changed from the base of the PR and between 8111a13 and 484f62b.

⛔ Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (6)
  • package.json (1 hunks)
  • ponder-env.d.ts (2 hunks)
  • ponder.schema.ts (3 hunks)
  • src/helpers.ts (7 hunks)
  • src/index.ts (6 hunks)
  • src/types.ts (0 hunks)
💤 Files with no reviewable changes (1)
  • src/types.ts
🔇 Additional comments (6)
ponder.schema.ts (1)

121-122: Consistent data types for chainId field

Similar to the previous comment, the chainId in tokenIdDataTable is defined as t.integer().notNull(). Ensure that all instances of chainId across different tables use the same data type for consistency.

src/index.ts (1)

256-264: Review logic for vapeStakingData retrieval and insertion

Using a fixed id when retrieving and inserting vapeStakingData may not reflect the data accurately for multiple users. Ensure that the logic aligns with the intended behavior of tracking individual user deposits.

package.json (2)

34-34: Verify Node.js version compatibility

The required Node.js version has been updated to >=20. Ensure that all deployment environments and developers' local setups are compatible with Node.js 20. Some hosting services may not yet support this version.


16-31: Check for breaking changes in updated dependencies

Several dependencies have been updated:

  • @ponder/core from 0.4.13 to 0.8.0-next.1
  • axios from 1.6.7 to 1.7.7
  • viem from 1.19.3 to 2.21.3
  • typescript from ^5.2.2 to ^5.3.2

These updates may introduce breaking changes. Please review the release notes for each package and test the application thoroughly to ensure compatibility.

ponder-env.d.ts (1)

10-10: Confirm removal of Schema type does not affect other modules

The Schema type export has been removed. Verify that this type is not used elsewhere in the codebase, or update any imports accordingly to prevent type errors.

src/helpers.ts (1)

20-30: LGTM: Clean table imports for Ponder migration

The table imports are well-organized and follow a consistent naming convention, aligning with the migration to the latest Ponder version.

ponder.schema.ts Outdated Show resolved Hide resolved
src/index.ts Show resolved Hide resolved
src/index.ts Show resolved Hide resolved
src/helpers.ts Show resolved Hide resolved
src/helpers.ts Show resolved Hide resolved
ponder-env.d.ts Outdated Show resolved Hide resolved
ponder.schema.ts Outdated Show resolved Hide resolved
@royvardhan
Copy link
Member Author

@mejiasd3v Yes for consistency

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Outside diff range and nitpick comments (3)
ponder.schema.ts (3)

57-65: Consider adding foreign key constraints and indexes.

While the table structure is correct, consider these performance and data integrity improvements:

  1. Add an index on userHistoryId and userDataId for faster lookups
  2. Add an index on timestamp for time-based queries
  3. Consider adding foreign key constraints to ensure referential integrity

71-90: Consider using a composite primary key for the UserHistory table.

Since the ID is constructed from wallet address and chainId, consider using them as separate fields in a composite primary key for better querying capabilities.

 export const userHistoryTable = onchainTable("UserHistory", (t) => ({
-  id: t.text().primaryKey().notNull(),
-  chainId: t.integer().notNull(),
+  walletAddress: t.text().notNull(),
+  chainId: t.integer().notNull(),
+  id: t.primaryKey(["walletAddress", "chainId"]),
   // ... rest of the fields
 }));

142-147: Add validation for wallets array in WalletsPerTier table.

Consider adding validation to ensure the wallets array contains unique addresses to prevent duplicates.

 export const walletsPerTierTable = onchainTable("WalletsPerTier", (t) => ({
   id: t.text().primaryKey().notNull(),
-  wallets: t.text().array().notNull(),
+  wallets: t.text().array().unique().notNull(),
 }));
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Reviewing files that changed from the base of the PR and between 484f62b and ddb525b.

📒 Files selected for processing (4)
  • .gitignore (1 hunks)
  • ponder-env.d.ts (0 hunks)
  • ponder.schema.ts (3 hunks)
  • src/helpers.ts (7 hunks)
💤 Files with no reviewable changes (1)
  • ponder-env.d.ts
✅ Files skipped from review due to trivial changes (1)
  • .gitignore
🔇 Additional comments (6)
ponder.schema.ts (2)

Line range hint 39-55: LGTM! Well-structured enum definition with comprehensive documentation.

The pointsSourceEnum is well-documented and includes all necessary point source types. The use of generateLMSeasonEnum for dynamic enum values is a good approach.


93-98: Standardize chainId data type across tables.

The chainId field in userDataTable is defined as integer(), which is consistent with most other tables. This is good for maintaining data type consistency across the schema.

src/helpers.ts (4)

20-30: LGTM! Well-organized imports from schema.

The imports are properly structured and aligned with the schema definitions.


79-100: ⚠️ Potential issue

Address potential race conditions in handleChainFirstWallet.

The function should use a transaction to handle the race condition when checking and updating the first wallet status.

 export const handleChainFirstWallet = async (
   context: Context,
   chainId: number,
   userAddressLowerCase: string,
   userData: UserHistory,
   event: { block?: { timestamp: bigint } }
 ): Promise<UserHistory> => {
   let { db } = context;
-  let allProtocols = await db.find(allProtocolsTable, { id: "protocols" });
-  if (!allProtocols) {
-    allProtocols = await db.insert(allProtocolsTable).values({
-      id: "protocols",
-      firstWallet: userAddressLowerCase,
-    });
-    await db.insert(pointsTable).values({
-      // ... points table values
-    });
-    userData = await db
-      .update(userHistoryTable, { id: userData.id })
-      .set((row) => ({
-        chainFirstWallet: true,
-      }));
-  }
+  return await db.transaction(async (tx) => {
+    let allProtocols = await tx.find(allProtocolsTable, { id: "protocols" });
+    if (!allProtocols) {
+      allProtocols = await tx.insert(allProtocolsTable).values({
+        id: "protocols",
+        firstWallet: userAddressLowerCase,
+      });
+      await tx.insert(pointsTable).values({
+        // ... points table values
+      });
+      userData = await tx
+        .update(userHistoryTable, { id: userData.id })
+        .set((row) => ({
+          chainFirstWallet: true,
+        }));
+    }
+    return userData;
+  });
 };

419-423: ⚠️ Potential issue

Fix array mutation in WalletsPerTier update.

The current implementation mutates the array before updating, which is unnecessary and could lead to inconsistencies.

-    walletsPerTier.wallets.push(userAddress);
-    walletsPerTier = await db
-      .update(walletsPerTierTable, { id })
-      .set((row) => ({
-        wallets: row.wallets.concat(userAddress),
-      }));
+    walletsPerTier = await db
+      .update(walletsPerTierTable, { id })
+      .set((row) => ({
+        wallets: [...new Set([...row.wallets, userAddress])],
+      }));

377-384: ⚠️ Potential issue

Use atomic updates for TokenIdData.

The current implementation might lead to race conditions when multiple updates occur simultaneously. Consider using atomic updates.

-  tokenIdData = await db
-    .update(tokenIdDataTable, { id: `${tokenId}-${chainId}` })
-    .set((row) => ({
-      pointsEarned: row.pointsEarned + pointsEarned,
-      pointsClaimed: row.pointsClaimed + pointsClaimed,
-      pointsSpent: row.pointsSpent + pointsSpent,
-      lastUpdated: timestamp,
-    }));
+  tokenIdData = await db.transaction(async (tx) => {
+    const current = await tx.find(tokenIdDataTable, { 
+      id: `${tokenId}-${chainId}` 
+    });
+    return await tx
+      .update(tokenIdDataTable, { id: `${tokenId}-${chainId}` })
+      .set({
+        pointsEarned: current.pointsEarned + pointsEarned,
+        pointsClaimed: current.pointsClaimed + pointsClaimed,
+        pointsSpent: current.pointsSpent + pointsSpent,
+        lastUpdated: timestamp,
+      });
+  });

Likely invalid or redundant comment.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Reviewing files that changed from the base of the PR and between ddb525b and 6584a54.

📒 Files selected for processing (1)
  • .github/actions/setup/action.yml (1 hunks)

.github/actions/setup/action.yml Show resolved Hide resolved
@royvardhan royvardhan merged commit f8dc4b7 into main Dec 11, 2024
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants