Skip to content

chore: added subgraph migration mdc file to cursor rules - #725

Merged
DZakh merged 3 commits into
mainfrom
kv/add-subgraph-migration-mdc
Sep 4, 2025
Merged

DZakh merged 3 commits into
mainfrom
kv/add-subgraph-migration-mdc

Conversation

@keenbeen32

@keenbeen32 keenbeen32 commented Sep 4, 2025

Copy link
Copy Markdown
Contributor

chore: added subgraph migration mdc file to cursor rules

Summary by CodeRabbit

  • Documentation
    • Added a comprehensive migration guide for converting TheGraph subgraphs to Envio HyperIndex.
    • Provides a step-by-step migration lifecycle, multichain indexing best practices, and patterns for entity and dynamic contract registration.
    • Covers field selection, derived relationships, numeric precision, constants, and recommended error-handling and QA/validation workflows.
    • Includes examples, checklists, and guidance on using the Effect API for external calls during migrations.

@coderabbitai

coderabbitai Bot commented Sep 4, 2025

Copy link
Copy Markdown
Contributor

Walkthrough

Adds a new mandatory documentation file .cursor/rules/subgraph-migration.mdc that defines a multi-step migration framework for converting TheGraph subgraphs to Envio HyperIndex, covering multichain ID rules, schema refactors, Effect API usage, dynamic contract registration, QA, and validation workflows.

Changes

Cohort / File(s) Summary
Migration Guidance Doc
​.cursor/rules/subgraph-migration.mdc
Added a comprehensive migration document describing a multistep migration lifecycle (clear boilerplate, schema migration, contract skeletons, dynamic contract registration, helper/handler migration, verification), multichain ID patterns (prefix IDs with event.chainId, avoid hardcoded chainId), Effect API usage (replace .bind, preload_handlers behavior, external calls), data/type/constant handling (BigInt/BigDecimal, ZERO_BI/ZERO_BD/ADDRESS_ZERO), @derivedFrom and field_selection rules, config.yaml adjustments, dynamic-contract indexing via factory events, failure modes and error-handling, numerous examples (correct/incorrect), and QA/validation guidance (codegen, tsc, runtime tests).

Sequence Diagram(s)

sequenceDiagram
  autonumber
  participant Dev as Developer
  participant Doc as Migration Doc
  participant Legacy as TheGraph Subgraph
  participant Env as Envio HyperIndex
  participant Eff as Effect API

  rect #f8f9fa
    Dev->>Doc: Read migration lifecycle & patterns
    Dev->>Legacy: Inspect schema, handlers, helpers
  end

  rect #eef8f2
    Dev->>Env: Refactor schema (IDs prefixed by event.chainId)
    Dev->>Eff: Replace .bind calls with Effect API calls
    Dev->>Env: Register dynamic contracts via factory events
  end

  rect #fff4e6
    Env->>Dev: Runtime/QA feedback (codegen, tsc, tests)
    Dev->>Env: Iterate fixes and final verification
  end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Suggested reviewers

  • DZakh

Poem

I twitch my ears at migration lore,
I hop through schemas, tests, and more.
ChainId seeds and effects to sow,
I nibble bugs till migrations flow.
Carrots of QA — ready to go! 🥕

✨ Finishing Touches
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch kv/add-subgraph-migration-mdc

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.

❤️ Share
🪧 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.
    • 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.
  • 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 the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

CodeRabbit Commands (Invoked using PR/Issue comments)

Type @coderabbitai help to get the list of available commands.

Other keywords and placeholders

  • Add @coderabbitai ignore or @coderabbit 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

Status, Documentation and Community

  • Visit our Status Page to check the current availability of CodeRabbit.
  • 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.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 4

🧹 Nitpick comments (8)
.cursor/rules/subgraph-migration.mdc (8)

86-86: Typo: trailing “s” after bold text.

Remove the stray “s” in “Common Runtime Errors to Watch For:**s”.

-**Common Runtime Errors to Watch For:**s
+**Common Runtime Errors to Watch For:**

1112-1134: Add timeout to external fetch example.

Demonstrate cancelation to avoid hung handlers.

-    const something = await fetch(
-      `https://api.example.com/something?address=${input.address}&blockNumber=${input.blockNumber}`
-    );
-    return something.json();
+    const ctrl = new AbortController();
+    const t = setTimeout(() => ctrl.abort(), 10_000);
+    const res = await fetch(
+      `https://api.example.com/something?address=${input.address}&blockNumber=${input.blockNumber}`,
+      { signal: ctrl.signal }
+    );
+    clearTimeout(t);
+    return res.json();

1007-1012: BigDecimal constructor inputs: prefer string literals for precision and consistency.

Using numeric literals is easy to mimic incorrectly elsewhere.

-export const ZERO_BD = new BigDecimal(0);
-export const ONE_BD = new BigDecimal(1);
+export const ZERO_BD = new BigDecimal('0');
+export const ONE_BD = new BigDecimal('1');
-export const ZERO_BD = new BigDecimal(0);
-export const ONE_BD = new BigDecimal(1);
+export const ZERO_BD = new BigDecimal('0');
+export const ONE_BD = new BigDecimal('1');

Also applies to: 1036-1043


1029-1031: Clarify BigDecimal import vs dependency guidance.

Doc currently says to install bignumber.js, but also to import BigDecimal from "generated". Tighten to one canonical approach to avoid confusion.

-# Install bignumber.js for BigDecimal support
-pnpm add bignumber.js
+# BigDecimal is re-exported from "generated". Install bignumber.js only if you use it directly elsewhere.
+pnpm add bignumber.js
-// ✅ CORRECT - Import from generated types (which re-exports BigNumber)
+// ✅ CORRECT - Import from generated types (re-exported BigNumber)
 import { BigDecimal } from 'generated';

Add a note: “Do not import BigDecimal from 'bignumber.js' in app code.”

Also applies to: 1539-1544


355-375: Show unordered_multichain_mode in the YAML example.

You mention it later; include it in the primary snippet to reduce misconfig.

-contracts:
+unordered_multichain_mode: true
+contracts:

57-62: Clarify “whitelist commands” phrasing.

This reads like a security prompt; suggest clearer instruction for local/CI.

-Prompt the user to whitelist the following commands:
+Ensure these commands are permitted in your local/CI environment:

246-248: Formatting: missing closing backtick for inline code.

Close the @derivedFrom inline code span.

-**Envio requires explicit relationship definitions** via `@derivedFrom
+**Envio requires explicit relationship definitions** via `@derivedFrom`

114-132: Add a note that handlers using transaction.hash require field_selection.

To prevent copy–paste errors, annotate the first handler and entity patterns with a reminder about config.yaml field_selection for transaction fields.

   // TODO: Implement business logic from subgraph
   // Reference: original-subgraph/src/contract.ts
+  // Note: if you use event.transaction.hash, add field_selection.transaction_fields: [hash] in config.yaml.
   transactionHash: event.transaction.hash,
+  // Note: requires field_selection.transaction_fields: [hash] in config.yaml

Also applies to: 944-955

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between e35df5e and 53f776b.

📒 Files selected for processing (1)
  • .cursor/rules/subgraph-migration.mdc (1 hunks)
🧰 Additional context used
🧠 Learnings (2)
📚 Learning: 2025-08-11T08:49:57.399Z
Learnt from: CR
PR: enviodev/hyperindex#0
File: scenarios/test_codegen/.cursor/rules/hyperindex.mdc:0-0
Timestamp: 2025-08-11T08:49:57.399Z
Learning: Applies to scenarios/test_codegen/**/*.ts : Always cast timestamps from events to BigInt (e.g., BigInt(event.block.timestamp))

Applied to files:

  • .cursor/rules/subgraph-migration.mdc
📚 Learning: 2025-08-11T08:47:04.346Z
Learnt from: CR
PR: enviodev/hyperindex#0
File: scenarios/fuel_test/.cursor/rules/hyperindex.mdc:0-0
Timestamp: 2025-08-11T08:47:04.346Z
Learning: Applies to scenarios/fuel_test/**/*.ts : Always cast timestamps from events to BigInt, e.g., `BigInt(event.block.timestamp)`; never use raw timestamps

Applied to files:

  • .cursor/rules/subgraph-migration.mdc
🔇 Additional comments (2)
.cursor/rules/subgraph-migration.mdc (2)

1-6: Solid addition; strong structure and actionable guidance.

This MDC will help reduce migration churn and standardize patterns across PRs. No blocking issues with adding the file.


239-243: Confirm getWhere selector semantics (single vs multi).

Examples assign the result of context.Mint.getWhere.transaction_id.eq(...) to a single entity. If getWhere can return multiple rows, the example should use a plural or .first() helper to avoid confusion.

Do your generated contexts return a single row for getWhere.<field>.eq() or an array/iterator? If array, I can update the snippets to use .first() or adjust variable naming.

Also applies to: 1765-1768

Comment thread .cursor/rules/subgraph-migration.mdc
...entity,
field: newValue,
updatedAt: BigInt(Date.now()),
};

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Use block timestamp, not Date.now(), for updatedAt.

Mixing wall-clock millis with on-chain seconds creates inconsistent units.

-    updatedAt: BigInt(Date.now()),
+    updatedAt: BigInt(event.block.timestamp),
📝 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.

Suggested change
};
updatedAt: BigInt(event.block.timestamp),
};
🤖 Prompt for AI Agents
In .cursor/rules/subgraph-migration.mdc around line 973, the code sets updatedAt
using Date.now(), which mixes millisecond wall-clock time with on-chain seconds;
replace Date.now() with the block.timestamp value (or convert consistently) so
updatedAt uses the on-chain block timestamp (seconds) and adjust any downstream
expectations (or multiply/divide as needed) to keep all timestamps in the same
unit.

Comment on lines +1199 to +1225
const publicClient = createPublicClient({
chain: {
id: 6342, // MegaETH Testnet - adjust for your network
name: 'MegaETH Testnet',
network: 'megaeth-testnet',
nativeCurrency: {
decimals: 18,
name: 'MegaETH',
symbol: 'METH',
},
rpcUrls: {
default: {
http: [process.env.RPC_URL || 'https://rpc.ankr.com/megaeth_testnet'],
},
public: {
http: [process.env.RPC_URL || 'https://rpc.ankr.com/megaeth_testnet'],
},
},
},
transport: http(process.env.RPC_URL),
});

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Avoid hardcoded chain config in Effect; make it chain-agnostic.

Baking “MegaETH Testnet” and a fixed chain id into docs will be copy–pasted and later break multichain setups.

-const publicClient = createPublicClient({
-  chain: {
-    id: 6342, // MegaETH Testnet - adjust for your network
-    name: 'MegaETH Testnet',
-    network: 'megaeth-testnet',
-    nativeCurrency: { decimals: 18, name: 'MegaETH', symbol: 'METH' },
-    rpcUrls: {
-      default: { http: [process.env.RPC_URL || 'https://rpc.ankr.com/megaeth_testnet'] },
-      public:  { http: [process.env.RPC_URL || 'https://rpc.ankr.com/megaeth_testnet'] },
-    },
-  },
-  transport: http(process.env.RPC_URL),
-});
+const publicClient = createPublicClient({
+  // Prefer environment-configured RPC; provide one per chain via env or config.
+  transport: http(process.env.RPC_URL!),
+});

Add a note: pass chain-specific RPC via env per network or keep a registry keyed by event.chainId.

📝 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.

Suggested change
const publicClient = createPublicClient({
chain: {
id: 6342, // MegaETH Testnet - adjust for your network
name: 'MegaETH Testnet',
network: 'megaeth-testnet',
nativeCurrency: {
decimals: 18,
name: 'MegaETH',
symbol: 'METH',
},
rpcUrls: {
default: {
http: [process.env.RPC_URL || 'https://rpc.ankr.com/megaeth_testnet'],
},
public: {
http: [process.env.RPC_URL || 'https://rpc.ankr.com/megaeth_testnet'],
},
},
},
transport: http(process.env.RPC_URL),
});
const publicClient = createPublicClient({
// Prefer environment-configured RPC; provide one per chain via env or config.
transport: http(process.env.RPC_URL!),
});
🤖 Prompt for AI Agents
.cursor/rules/subgraph-migration.mdc around lines 1199 to 1219: the snippet
hardcodes a specific chain (MegaETH Testnet) and RPC URL which breaks multichain
usage; replace the fixed config with a chain-agnostic approach by reading chain
parameters (chainId, name, network, nativeCurrency, rpc URL) from environment
variables or from a registry keyed by chainId (e.g.,
process.env.RPC_URL_<CHAIN_ID> or a lookup map), pass the resolved values into
createPublicClient at runtime, and include a sensible fallback or explicit error
when no RPC for the requested chain is found.

Comment thread .cursor/rules/subgraph-migration.mdc Outdated
@DZakh

DZakh commented Sep 4, 2025

Copy link
Copy Markdown
Member

Wow, this is huge 🔥

Do you want it just to be kept in the repository, or automatically added to the user's project on initialization?

@keenbeen32

Copy link
Copy Markdown
Contributor Author

@DZakh shot! That's a good question. Maybe for now we can just keep it in the repo to have a solid version of it somewhere.

@keenbeen32

Copy link
Copy Markdown
Contributor Author

Although I'm open to suggestions, don't see any harm in adding in on initialisation I suppose.

@DZakh

DZakh commented Sep 4, 2025

Copy link
Copy Markdown
Member

Let's start with simply storing it in the repo. I don't know the cons to include it on init, just a little bit worried of the file size 😅

Could you take a look at the Coderabbit comments and whether they make sense. Let me know if everything is good and I'll aprove the PR.

Also, it would be nice to share the file in the doc section https://docs.envio.dev/docs/HyperIndex/migration-guide

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 1

♻️ Duplicate comments (3)
.cursor/rules/subgraph-migration.mdc (3)

945-960: Nice: ID template + field_selection reminder colocated.

This example already uses hyphens and reminds about field_selection for transaction.hash. Good consistency with the rule; keep it.


973-981: Use on-chain block timestamp, not Date.now(), for updatedAt.

Mixing wall-clock ms with on-chain seconds leads to inconsistent units; also aligns with the team learning to always cast event timestamps to BigInt.

-    updatedAt: BigInt(Date.now()),
+    updatedAt: BigInt(event.block.timestamp),

1205-1228: Avoid hardcoded chain config in viem client; make it chain-agnostic.

Hardcoding a specific testnet and RPC will be copy–pasted and break multichain setups. Prefer transport-only and resolve RPC per chainId via env or a registry.

-const publicClient = createPublicClient({
-  chain: {
-    id: 6342, // MegaETH Testnet - adjust for your network
-    name: 'MegaETH Testnet',
-    network: 'megaeth-testnet',
-    nativeCurrency: {
-      decimals: 18,
-      name: 'MegaETH',
-      symbol: 'METH',
-    },
-    rpcUrls: {
-      default: {
-        http: [process.env.RPC_URL],
-      },
-      public: {
-        http: [process.env.RPC_URL],
-      },
-    },
-  },
-  transport: http(process.env.RPC_URL),
-});
+const publicClient = createPublicClient({
+  // Provide chain-specific RPC via env (e.g., RPC_URL_<CHAIN_ID>) or a registry map.
+  transport: http(process.env.RPC_URL!),
+});

Add a short note below showing a simple resolver, e.g., const rpc = process.env[\RPC_URL_${event.chainId}`]`.

🧹 Nitpick comments (3)
.cursor/rules/subgraph-migration.mdc (3)

118-121: Standardize ID delimiter to hyphen to match multichain rule.

Use hyphens consistently (you use underscores here but hyphens elsewhere and in the rules above). Also add a near-by reminder about field_selection for transaction.hash.

-    id: `${event.chainId}_${event.block.number}_${event.logIndex}`,
+    id: `${event.chainId}-${event.block.number}-${event.logIndex}`,
+    // Note: transaction.hash requires field_selection in config.yaml

86-86: Fix typo in section heading.

-**Common Runtime Errors to Watch For:**s
+**Common Runtime Errors to Watch For:**

1035-1037: Clarify BigDecimal dependency guidance to avoid confusion.

You later instruct to import BigDecimal from "generated" (not from bignumber.js). Make the install note conditional.

-# Install bignumber.js for BigDecimal support
-pnpm add bignumber.js
+# BigDecimal is re-exported from "generated".
+# Only install bignumber.js if codegen/runtime complains about a missing peer dep.
+# pnpm add bignumber.js
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 53f776b and 5c289a0.

📒 Files selected for processing (1)
  • .cursor/rules/subgraph-migration.mdc (1 hunks)
🧰 Additional context used
🧠 Learnings (4)
📚 Learning: 2025-08-11T08:42:57.311Z
Learnt from: CR
PR: enviodev/hyperindex#0
File: codegenerator/cli/templates/static/shared/.cursor/rules/hyperindex.mdc:0-0
Timestamp: 2025-08-11T08:42:57.311Z
Learning: Applies to codegenerator/cli/templates/static/shared/**/*.ts : Always cast timestamps to BigInt (e.g., `BigInt(event.block.timestamp)`) and never use raw timestamps

Applied to files:

  • .cursor/rules/subgraph-migration.mdc
📚 Learning: 2025-08-11T08:49:57.399Z
Learnt from: CR
PR: enviodev/hyperindex#0
File: scenarios/test_codegen/.cursor/rules/hyperindex.mdc:0-0
Timestamp: 2025-08-11T08:49:57.399Z
Learning: Applies to scenarios/test_codegen/**/*.ts : Always cast timestamps from events to BigInt (e.g., BigInt(event.block.timestamp))

Applied to files:

  • .cursor/rules/subgraph-migration.mdc
📚 Learning: 2025-08-11T08:47:04.346Z
Learnt from: CR
PR: enviodev/hyperindex#0
File: scenarios/fuel_test/.cursor/rules/hyperindex.mdc:0-0
Timestamp: 2025-08-11T08:47:04.346Z
Learning: Applies to scenarios/fuel_test/**/*.ts : Always cast timestamps from events to BigInt, e.g., `BigInt(event.block.timestamp)`; never use raw timestamps

Applied to files:

  • .cursor/rules/subgraph-migration.mdc
📚 Learning: 2025-08-11T08:47:04.346Z
Learnt from: CR
PR: enviodev/hyperindex#0
File: scenarios/fuel_test/.cursor/rules/hyperindex.mdc:0-0
Timestamp: 2025-08-11T08:47:04.346Z
Learning: Applies to scenarios/fuel_test/**/*.ts : With preload enabled (handlers run twice), all external calls (e.g., fetch) MUST be implemented via the Envio Effect API (experimental_createEffect and context.effect)

Applied to files:

  • .cursor/rules/subgraph-migration.mdc
🔇 Additional comments (4)
.cursor/rules/subgraph-migration.mdc (4)

1309-1324: Schema/type alignment for decimals fields.

You cast decimals to BigInt in the example entity. Many schemas model ERC20 decimals as Int (number). Ensure the example mirrors the schema guidance below (“Int! → number”).

If schema uses Int!, change:

-      decimals: BigInt(tokenMetadata.decimals),
+      decimals: tokenMetadata.decimals,

1118-1160: Good Effect API guidance with preload.

Clear pattern: define effect with schema, consume via context.effect, and !context.isPreload note. Solid baseline.


399-399: Keep unordered_multichain_mode: true—the flag name is confirmed as correct per Envio docs.


239-243: Confirm handler-time query API name (getWhere vs where)
After running pnpm codegen, inspect your generated entity definitions (e.g. in generated/src/db/…) to see whether the finder method is where, getWhere, or named differently, and update the examples to match. Also applies to lines 1768–1776.

Comment on lines +1121 to +1139
// Define an effect. It can have any name you want.
export const getSomething = experimental_createEffect(
{
// The name for debugging purposes
name: "getSomething",
// The input schema for the effect
input: {
address: S.string,
blockNumber: S.number,
},
output: S.union([S.string, null]),
},
async ({ input, context }) => {
// Fetch or other external calls MUST always be done in an effect.
const something = await fetch(
`https://api.example.com/something?address=${input.address}&blockNumber=${input.blockNumber}`
);
return something.json();
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue

Effect output schema mismatch with returned JSON.

You declare output: S.union([S.string, null]) but return something.json() (object). Align schema and add an await.

-    output: S.union([S.string, null]),
+    // Return shape is unknown JSON; tighten if you define a schema.
+    output: S.unknown(),
   },
   async ({ input, context }) => {
-    const something = await fetch(
+    const res = await fetch(
       `https://api.example.com/something?address=${input.address}&blockNumber=${input.blockNumber}`
     );
-    return something.json();
+    return await res.json();
   }
📝 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.

Suggested change
// Define an effect. It can have any name you want.
export const getSomething = experimental_createEffect(
{
// The name for debugging purposes
name: "getSomething",
// The input schema for the effect
input: {
address: S.string,
blockNumber: S.number,
},
output: S.union([S.string, null]),
},
async ({ input, context }) => {
// Fetch or other external calls MUST always be done in an effect.
const something = await fetch(
`https://api.example.com/something?address=${input.address}&blockNumber=${input.blockNumber}`
);
return something.json();
}
// Define an effect. It can have any name you want.
export const getSomething = experimental_createEffect(
{
// The name for debugging purposes
name: "getSomething",
// The input schema for the effect
input: {
address: S.string,
blockNumber: S.number,
},
// Return shape is unknown JSON; tighten if you define a schema.
output: S.unknown(),
},
async ({ input, context }) => {
// Fetch or other external calls MUST always be done in an effect.
const res = await fetch(
`https://api.example.com/something?address=${input.address}&blockNumber=${input.blockNumber}`
);
return await res.json();
}
);
🤖 Prompt for AI Agents
In .cursor/rules/subgraph-migration.mdc around lines 1121 to 1139, the effect
declares output: S.union([S.string, null]) but returns something.json() (an
object) and also omits awaiting the JSON parse; update the output schema to
match the actual JSON shape returned (or change the returned value to a
string/null) and add await before something.json() so the effect returns the
parsed result rather than a Promise; ensure the schema precisely reflects the
object's properties (or map the JSON to a string/null) and adjust types
accordingly.

@keenbeen32
keenbeen32 force-pushed the kv/add-subgraph-migration-mdc branch from 5c289a0 to 4ef643b Compare September 4, 2025 14:21
@keenbeen32

Copy link
Copy Markdown
Contributor Author

@DZakh Sweet shot. I checked it over and should be good now (made some small changes), it's mainly just random examples it's picking up rather than the actual steps or migration points so shouldn't be an issue.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 1

♻️ Duplicate comments (5)
.cursor/rules/subgraph-migration.mdc (5)

118-121: Unify ID delimiter: use hyphens, not underscores

Earlier guidance and later examples use hyphens. Align this snippet.

-    id: `${event.chainId}_${event.block.number}_${event.logIndex}`,
+    id: `${event.chainId}-${event.block.number}-${event.logIndex}`,

1205-1228: Avoid hardcoded chain config in viem client

Hardcoding “MegaETH Testnet” and IDs harms multichain setups; prefer env-driven transport and resolve per-chain externally.

-const publicClient = createPublicClient({
-  chain: {
-    id: 6342, // MegaETH Testnet - adjust for your network
-    name: 'MegaETH Testnet',
-    network: 'megaeth-testnet',
-    nativeCurrency: {
-      decimals: 18,
-      name: 'MegaETH',
-      symbol: 'METH',
-    },
-    rpcUrls: {
-      default: { http: [process.env.RPC_URL] },
-      public:  { http: [process.env.RPC_URL] },
-    },
-  },
-  transport: http(process.env.RPC_URL),
-});
+const publicClient = createPublicClient({
+  // Resolve RPC per chain via env/registry. Example: RPC_URL_1, RPC_URL_10, etc.
+  transport: http(process.env.RPC_URL!),
+});

Add a short note: “Resolve the correct RPC from a map keyed by event.chainId; throw if missing.”


973-980: Use on-chain timestamp for updatedAt

Avoid Date.now() to keep units and source consistent with on-chain data.

-    updatedAt: BigInt(Date.now()),
+    updatedAt: BigInt(event.block.timestamp),

1121-1140: Effect output schema mismatch and missing await on JSON

Schema declares string/null but returns parsed JSON object; also missing await on json().

-    output: S.union([S.string, null]),
+    // Return shape is JSON; tighten if you know the structure.
+    output: S.unknown(),
   },
   async ({ input, context }) => {
-    const something = await fetch(
+    const res = await fetch(
       `https://api.example.com/something?address=${input.address}&blockNumber=${input.blockNumber}`
     );
-    return something.json();
+    return await res.json();
   }

1373-1415: Prefix entity IDs (and foreign keys) with event.chainId

Examples here omit the chain prefix, breaking multichain integrity and relationships.

-    let token = await context.Token.get(event.params.token);
+    let token = await context.Token.get(`${event.chainId}-${event.params.token}`);
     if (!token) {
       token = {
-        id: event.params.token,
+        id: `${event.chainId}-${event.params.token}`,
         name: tokenMetadata.name,
         symbol: tokenMetadata.symbol,
         decimals: BigInt(tokenMetadata.decimals),
         totalSupply: BigInt(tokenMetadata.totalSupply),
         rate: ZERO_BD,
-        dataFeedId: event.params.token,
+        dataFeedId: event.params.token,
         updatedAt: BigInt(event.block.timestamp),
         blockNumber: BigInt(event.block.number),
         blockTimestamp: BigInt(event.block.timestamp),
         transactionHash: event.transaction.hash,
-        address: event.params.token,
+        address: event.params.token,
       };
       context.Token.set(token);
     }
@@
-    const contract: ContractDataEntity = {
-      id: event.params.contract,
+    const contract: ContractDataEntity = {
+      id: `${event.chainId}-${event.params.contract}`,
       name: contractMetadata.name,
       symbol: contractMetadata.symbol,
       decimals: BigInt(contractMetadata.decimals),
       manager: event.params.poolManager,
       timestamp: BigInt(event.block.timestamp),
       lastUpdate: BigInt(event.block.timestamp),
       fee: ZERO_BI,
       depositApy: ZERO_BI,
       convertToAssetsMultiplier,
       totalDepositsVolume: ZERO_BI,
       totalWithdrawalsVolume: ZERO_BI,
       totalAssets: ZERO_BI,
       totalShares: ZERO_BI,
-      token_id: event.params.token,
-      contractFactory_id: ONE_BI.toString(),
+      token_id: `${event.chainId}-${event.params.token}`,
+      contractFactory_id: `${event.chainId}-${ONE_BI.toString()}`,
     };

Also update any preceding .get(...) usage for ContractFactory to use the same prefixed ID.

🧹 Nitpick comments (5)
.cursor/rules/subgraph-migration.mdc (5)

31-31: Standardize Bundle ID example to use event.chainId

Use ${event.chainId}-1 for consistency with the multichain rule above.

- - **Use chain-specific Bundle IDs**: `${chainId}-1` for accurate pricing per network
+ - **Use chain-specific Bundle IDs**: `${event.chainId}-1` for accurate pricing per network

1034-1038: Clarify BigDecimal source; avoid unnecessary dependency

Doc suggests installing bignumber.js but examples import BigDecimal from generated. Remove the install step or explain when it’s needed.

-# Install bignumber.js for BigDecimal support
-pnpm add bignumber.js
+# BigDecimal is re-exported from "generated"; no extra install needed in typical setups.
+# Install bignumber.js only if your environment requires direct usage.

1547-1552: Align import guidance for BigDecimal

Recommend importing from generated and discourage direct bignumber.js imports to match codegen types.

-// ❌ WRONG - Direct import from bignumber.js
-import { BigDecimal } from 'bignumber.js';
+// ✅ Preferred - Import from generated types (re-exported)
+import { BigDecimal } from 'generated';

1737-1739: Chain ID availability in async example

If chainId is not in scope, prefer ${event.chainId}-1 or pass chainId explicitly to the function to avoid implicit globals.

-export async function updateTokenDayData() {
-  const bundle = await context.Bundle.get(`${chainId}-1`);
+export async function updateTokenDayData(event: any) {
+  const bundle = await context.Bundle.get(`${event.chainId}-1`);

1-13: Mirror this MDC in docs + consider init-time inclusion

Per reviewer feedback, add this file to docs at docs.envio.dev and consider auto-including it on project init (with an option to skip) to maximize visibility.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 5c289a0 and 4ef643b.

📒 Files selected for processing (1)
  • .cursor/rules/subgraph-migration.mdc (1 hunks)
🧰 Additional context used
🧠 Learnings (5)
📚 Learning: 2025-08-11T08:42:57.311Z
Learnt from: CR
PR: enviodev/hyperindex#0
File: codegenerator/cli/templates/static/shared/.cursor/rules/hyperindex.mdc:0-0
Timestamp: 2025-08-11T08:42:57.311Z
Learning: Applies to codegenerator/cli/templates/static/shared/**/*.ts : Always cast timestamps to BigInt (e.g., `BigInt(event.block.timestamp)`) and never use raw timestamps

Applied to files:

  • .cursor/rules/subgraph-migration.mdc
📚 Learning: 2025-08-11T08:49:57.399Z
Learnt from: CR
PR: enviodev/hyperindex#0
File: scenarios/test_codegen/.cursor/rules/hyperindex.mdc:0-0
Timestamp: 2025-08-11T08:49:57.399Z
Learning: Applies to scenarios/test_codegen/**/*.ts : Always cast timestamps from events to BigInt (e.g., BigInt(event.block.timestamp))

Applied to files:

  • .cursor/rules/subgraph-migration.mdc
📚 Learning: 2025-08-11T08:47:04.346Z
Learnt from: CR
PR: enviodev/hyperindex#0
File: scenarios/fuel_test/.cursor/rules/hyperindex.mdc:0-0
Timestamp: 2025-08-11T08:47:04.346Z
Learning: Applies to scenarios/fuel_test/**/*.ts : Always cast timestamps from events to BigInt, e.g., `BigInt(event.block.timestamp)`; never use raw timestamps

Applied to files:

  • .cursor/rules/subgraph-migration.mdc
📚 Learning: 2025-08-11T08:49:57.399Z
Learnt from: CR
PR: enviodev/hyperindex#0
File: scenarios/test_codegen/.cursor/rules/hyperindex.mdc:0-0
Timestamp: 2025-08-11T08:49:57.399Z
Learning: Applies to scenarios/test_codegen/**/*.ts : For any external call (e.g., fetch), wrap it in an Effect via experimental_createEffect and consume via context.effect

Applied to files:

  • .cursor/rules/subgraph-migration.mdc
📚 Learning: 2025-08-11T08:47:04.346Z
Learnt from: CR
PR: enviodev/hyperindex#0
File: scenarios/fuel_test/.cursor/rules/hyperindex.mdc:0-0
Timestamp: 2025-08-11T08:47:04.346Z
Learning: Applies to scenarios/fuel_test/**/*.ts : With preload enabled (handlers run twice), all external calls (e.g., fetch) MUST be implemented via the Envio Effect API (experimental_createEffect and context.effect)

Applied to files:

  • .cursor/rules/subgraph-migration.mdc

- [ ] **Check that events are being processed** (if you have test data)
- [ ] **Only proceed to the next step** after confirming the indexer runs without errors

**Common Runtime Errors to Watch For:**s

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue

Fix typo in heading

Remove stray “s”.

-**Common Runtime Errors to Watch For:**s
+**Common Runtime Errors to Watch For:**
📝 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.

Suggested change
**Common Runtime Errors to Watch For:**s
**Common Runtime Errors to Watch For:**
🤖 Prompt for AI Agents
In .cursor/rules/subgraph-migration.mdc around line 86, the heading "Common
Runtime Errors to Watch For:**s" contains a stray trailing "s"; remove the extra
"s" so the heading reads "Common Runtime Errors to Watch For:" and ensure
surrounding punctuation/formatting (bold markers) remains correct.

@DZakh
DZakh enabled auto-merge (squash) September 4, 2025 14:41
@DZakh
DZakh merged commit c7f7a0e into main Sep 4, 2025
2 checks passed
@DZakh
DZakh deleted the kv/add-subgraph-migration-mdc branch September 4, 2025 14:41
@coderabbitai coderabbitai Bot mentioned this pull request Nov 3, 2025
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