-
Notifications
You must be signed in to change notification settings - Fork 19
fix(subgraph): use deployments.json as source of truth for addresses #406
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?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -1,48 +1,212 @@ | ||||||||||||||||||||||||||||||||||||||||||||||||
| const fs = require("fs"); | ||||||||||||||||||||||||||||||||||||||||||||||||
| const path = require("path"); | ||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||
| // Network name to chain ID mapping | ||||||||||||||||||||||||||||||||||||||||||||||||
| const NETWORK_CHAIN_IDS = { | ||||||||||||||||||||||||||||||||||||||||||||||||
| mainnet: "314", | ||||||||||||||||||||||||||||||||||||||||||||||||
| calibration: "314159", | ||||||||||||||||||||||||||||||||||||||||||||||||
| }; | ||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||
| // Network name to subgraph network name mapping | ||||||||||||||||||||||||||||||||||||||||||||||||
| const NETWORK_NAMES = { | ||||||||||||||||||||||||||||||||||||||||||||||||
| mainnet: "filecoin", | ||||||||||||||||||||||||||||||||||||||||||||||||
| calibration: "filecoin-testnet", | ||||||||||||||||||||||||||||||||||||||||||||||||
| }; | ||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||
| // Mapping from deployments.json keys to template keys | ||||||||||||||||||||||||||||||||||||||||||||||||
| const ADDRESS_MAPPING = { | ||||||||||||||||||||||||||||||||||||||||||||||||
| PDP_VERIFIER_PROXY_ADDRESS: "PDPVerifier", | ||||||||||||||||||||||||||||||||||||||||||||||||
| SERVICE_PROVIDER_REGISTRY_PROXY_ADDRESS: "ServiceProviderRegistry", | ||||||||||||||||||||||||||||||||||||||||||||||||
| FWSS_PROXY_ADDRESS: "FilecoinWarmStorageService", | ||||||||||||||||||||||||||||||||||||||||||||||||
| FILECOIN_PAY_ADDRESS: "USDFCToken", | ||||||||||||||||||||||||||||||||||||||||||||||||
| }; | ||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||
| // Default start blocks for each network (can be overridden via environment or config) | ||||||||||||||||||||||||||||||||||||||||||||||||
| // These represent the approximate deployment blocks for the contracts | ||||||||||||||||||||||||||||||||||||||||||||||||
| const DEFAULT_START_BLOCKS = { | ||||||||||||||||||||||||||||||||||||||||||||||||
| mainnet: { | ||||||||||||||||||||||||||||||||||||||||||||||||
| PDPVerifier: 1000000, | ||||||||||||||||||||||||||||||||||||||||||||||||
| ServiceProviderRegistry: 1000000, | ||||||||||||||||||||||||||||||||||||||||||||||||
| FilecoinWarmStorageService: 1000000, | ||||||||||||||||||||||||||||||||||||||||||||||||
| USDFCToken: 1000000, | ||||||||||||||||||||||||||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||||||||||||||||||||||||||
| calibration: { | ||||||||||||||||||||||||||||||||||||||||||||||||
| PDPVerifier: 2988297, | ||||||||||||||||||||||||||||||||||||||||||||||||
| ServiceProviderRegistry: 2988311, | ||||||||||||||||||||||||||||||||||||||||||||||||
| FilecoinWarmStorageService: 2988329, | ||||||||||||||||||||||||||||||||||||||||||||||||
| USDFCToken: 2988000, | ||||||||||||||||||||||||||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||||||||||||||||||||||||||
| }; | ||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||
| /** | ||||||||||||||||||||||||||||||||||||||||||||||||
| * Loads and validates network configuration from config/network.json | ||||||||||||||||||||||||||||||||||||||||||||||||
| * @param {string} network - The network name to load | ||||||||||||||||||||||||||||||||||||||||||||||||
| * @returns {Object} The network configuration object | ||||||||||||||||||||||||||||||||||||||||||||||||
| * Loads deployment addresses from service_contracts/deployments.json | ||||||||||||||||||||||||||||||||||||||||||||||||
| * @returns {Object} The parsed deployments object | ||||||||||||||||||||||||||||||||||||||||||||||||
| */ | ||||||||||||||||||||||||||||||||||||||||||||||||
| function loadNetworkConfig(network = "calibration") { | ||||||||||||||||||||||||||||||||||||||||||||||||
| const configPath = path.join(__dirname, "..", "..", "config", "network.json"); | ||||||||||||||||||||||||||||||||||||||||||||||||
| let networkConfig; | ||||||||||||||||||||||||||||||||||||||||||||||||
| function loadDeployments() { | ||||||||||||||||||||||||||||||||||||||||||||||||
| const deploymentsPath = path.join( | ||||||||||||||||||||||||||||||||||||||||||||||||
| __dirname, | ||||||||||||||||||||||||||||||||||||||||||||||||
| "..", | ||||||||||||||||||||||||||||||||||||||||||||||||
| "..", | ||||||||||||||||||||||||||||||||||||||||||||||||
| "..", | ||||||||||||||||||||||||||||||||||||||||||||||||
| "service_contracts", | ||||||||||||||||||||||||||||||||||||||||||||||||
| "deployments.json" | ||||||||||||||||||||||||||||||||||||||||||||||||
| ); | ||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||
| try { | ||||||||||||||||||||||||||||||||||||||||||||||||
| const configContent = fs.readFileSync(configPath, "utf8"); | ||||||||||||||||||||||||||||||||||||||||||||||||
| networkConfig = JSON.parse(configContent); | ||||||||||||||||||||||||||||||||||||||||||||||||
| const content = fs.readFileSync(deploymentsPath, "utf8"); | ||||||||||||||||||||||||||||||||||||||||||||||||
| return JSON.parse(content); | ||||||||||||||||||||||||||||||||||||||||||||||||
| } catch (error) { | ||||||||||||||||||||||||||||||||||||||||||||||||
| if (error.code === "ENOENT") { | ||||||||||||||||||||||||||||||||||||||||||||||||
| console.error(`Error: Configuration file not found at: ${configPath}`); | ||||||||||||||||||||||||||||||||||||||||||||||||
| console.error("Please ensure config/network.json exists in your project."); | ||||||||||||||||||||||||||||||||||||||||||||||||
| console.error(`Error: Deployments file not found at: ${deploymentsPath}`); | ||||||||||||||||||||||||||||||||||||||||||||||||
| console.error( | ||||||||||||||||||||||||||||||||||||||||||||||||
| "Please ensure service_contracts/deployments.json exists." | ||||||||||||||||||||||||||||||||||||||||||||||||
| ); | ||||||||||||||||||||||||||||||||||||||||||||||||
| process.exit(1); | ||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||
| if (error instanceof SyntaxError) { | ||||||||||||||||||||||||||||||||||||||||||||||||
| console.error(`Error: Invalid JSON in configuration file: ${configPath}`); | ||||||||||||||||||||||||||||||||||||||||||||||||
| console.error("Please check that config/network.json contains valid JSON."); | ||||||||||||||||||||||||||||||||||||||||||||||||
| console.error( | ||||||||||||||||||||||||||||||||||||||||||||||||
| `Error: Invalid JSON in deployments file: ${deploymentsPath}` | ||||||||||||||||||||||||||||||||||||||||||||||||
| ); | ||||||||||||||||||||||||||||||||||||||||||||||||
| console.error(`JSON Error: ${error.message}`); | ||||||||||||||||||||||||||||||||||||||||||||||||
| } else { | ||||||||||||||||||||||||||||||||||||||||||||||||
| console.error(`Error reading configuration file: ${configPath}`); | ||||||||||||||||||||||||||||||||||||||||||||||||
| console.error(`Error reading deployments file: ${deploymentsPath}`); | ||||||||||||||||||||||||||||||||||||||||||||||||
| console.error(`File Error: ${error.message}`); | ||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||
| process.exit(1); | ||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||
| /** | ||||||||||||||||||||||||||||||||||||||||||||||||
| * Loads optional start block overrides from config/start-blocks.json | ||||||||||||||||||||||||||||||||||||||||||||||||
| * @param {string} network - The network name | ||||||||||||||||||||||||||||||||||||||||||||||||
| * @returns {Object|null} The start blocks object or null if not found | ||||||||||||||||||||||||||||||||||||||||||||||||
| */ | ||||||||||||||||||||||||||||||||||||||||||||||||
| function loadStartBlockOverrides(network) { | ||||||||||||||||||||||||||||||||||||||||||||||||
| const overridesPath = path.join( | ||||||||||||||||||||||||||||||||||||||||||||||||
| __dirname, | ||||||||||||||||||||||||||||||||||||||||||||||||
| "..", | ||||||||||||||||||||||||||||||||||||||||||||||||
| "..", | ||||||||||||||||||||||||||||||||||||||||||||||||
| "config", | ||||||||||||||||||||||||||||||||||||||||||||||||
| "start-blocks.json" | ||||||||||||||||||||||||||||||||||||||||||||||||
| ); | ||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||
| try { | ||||||||||||||||||||||||||||||||||||||||||||||||
| const content = fs.readFileSync(overridesPath, "utf8"); | ||||||||||||||||||||||||||||||||||||||||||||||||
| const overrides = JSON.parse(content); | ||||||||||||||||||||||||||||||||||||||||||||||||
| return overrides[network] || null; | ||||||||||||||||||||||||||||||||||||||||||||||||
| } catch { | ||||||||||||||||||||||||||||||||||||||||||||||||
| // Start block overrides are optional | ||||||||||||||||||||||||||||||||||||||||||||||||
| return null; | ||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||
| /** | ||||||||||||||||||||||||||||||||||||||||||||||||
| * Loads and validates network configuration from service_contracts/deployments.json | ||||||||||||||||||||||||||||||||||||||||||||||||
| * @param {string} network - The network name to load ("mainnet" or "calibration") | ||||||||||||||||||||||||||||||||||||||||||||||||
| * @returns {Object} The network configuration object formatted for templates | ||||||||||||||||||||||||||||||||||||||||||||||||
| */ | ||||||||||||||||||||||||||||||||||||||||||||||||
| function loadNetworkConfig(network = "calibration") { | ||||||||||||||||||||||||||||||||||||||||||||||||
| const chainId = NETWORK_CHAIN_IDS[network]; | ||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||
| if (!networkConfig.networks) { | ||||||||||||||||||||||||||||||||||||||||||||||||
| console.error("Error: Invalid configuration structure. Missing 'networks' object in config/network.json"); | ||||||||||||||||||||||||||||||||||||||||||||||||
| console.error('Expected structure: { "networks": { "calibration": {...}, "mainnet": {...} } }'); | ||||||||||||||||||||||||||||||||||||||||||||||||
| if (!chainId) { | ||||||||||||||||||||||||||||||||||||||||||||||||
| console.error(`Error: Unknown network '${network}'`); | ||||||||||||||||||||||||||||||||||||||||||||||||
| console.error( | ||||||||||||||||||||||||||||||||||||||||||||||||
| `Available networks: ${Object.keys(NETWORK_CHAIN_IDS).join(", ")}` | ||||||||||||||||||||||||||||||||||||||||||||||||
| ); | ||||||||||||||||||||||||||||||||||||||||||||||||
| process.exit(1); | ||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||
| if (!networkConfig.networks[network]) { | ||||||||||||||||||||||||||||||||||||||||||||||||
| console.error(`Error: Network '${network}' not found in config/network.json`); | ||||||||||||||||||||||||||||||||||||||||||||||||
| console.error(`Available networks: ${Object.keys(networkConfig.networks).join(", ")}`); | ||||||||||||||||||||||||||||||||||||||||||||||||
| const deployments = loadDeployments(); | ||||||||||||||||||||||||||||||||||||||||||||||||
| const networkDeployments = deployments[chainId]; | ||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||
| if (!networkDeployments) { | ||||||||||||||||||||||||||||||||||||||||||||||||
| console.error( | ||||||||||||||||||||||||||||||||||||||||||||||||
| `Error: No deployments found for chain ID ${chainId} (network: ${network})` | ||||||||||||||||||||||||||||||||||||||||||||||||
| ); | ||||||||||||||||||||||||||||||||||||||||||||||||
| console.error(`Available chain IDs: ${Object.keys(deployments).join(", ")}`); | ||||||||||||||||||||||||||||||||||||||||||||||||
| process.exit(1); | ||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||
| return networkConfig.networks[network]; | ||||||||||||||||||||||||||||||||||||||||||||||||
| // Load start block overrides (optional) | ||||||||||||||||||||||||||||||||||||||||||||||||
| const startBlockOverrides = loadStartBlockOverrides(network); | ||||||||||||||||||||||||||||||||||||||||||||||||
| const defaultStartBlocks = DEFAULT_START_BLOCKS[network] || {}; | ||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||
| // Build the configuration object expected by templates | ||||||||||||||||||||||||||||||||||||||||||||||||
| const config = { | ||||||||||||||||||||||||||||||||||||||||||||||||
| name: NETWORK_NAMES[network], | ||||||||||||||||||||||||||||||||||||||||||||||||
| }; | ||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||
| // Map deployment addresses to template format | ||||||||||||||||||||||||||||||||||||||||||||||||
| for (const [deploymentKey, templateKey] of Object.entries(ADDRESS_MAPPING)) { | ||||||||||||||||||||||||||||||||||||||||||||||||
| const address = networkDeployments[deploymentKey]; | ||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||
| if (!address) { | ||||||||||||||||||||||||||||||||||||||||||||||||
| console.error( | ||||||||||||||||||||||||||||||||||||||||||||||||
| `Error: Missing '${deploymentKey}' in deployments.json for chain ID ${chainId}` | ||||||||||||||||||||||||||||||||||||||||||||||||
| ); | ||||||||||||||||||||||||||||||||||||||||||||||||
| process.exit(1); | ||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||
| // Get start block from overrides, defaults, or fallback | ||||||||||||||||||||||||||||||||||||||||||||||||
| const startBlock = | ||||||||||||||||||||||||||||||||||||||||||||||||
| startBlockOverrides?.[templateKey] || | ||||||||||||||||||||||||||||||||||||||||||||||||
| defaultStartBlocks[templateKey] || | ||||||||||||||||||||||||||||||||||||||||||||||||
| 0; | ||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+151
to
+155
|
||||||||||||||||||||||||||||||||||||||||||||||||
| const startBlock = | |
| startBlockOverrides?.[templateKey] || | |
| defaultStartBlocks[templateKey] || | |
| 0; | |
| let startBlock; | |
| if ( | |
| startBlockOverrides && | |
| Object.prototype.hasOwnProperty.call(startBlockOverrides, templateKey) | |
| ) { | |
| startBlock = startBlockOverrides[templateKey]; | |
| } else if ( | |
| defaultStartBlocks && | |
| Object.prototype.hasOwnProperty.call(defaultStartBlocks, templateKey) | |
| ) { | |
| startBlock = defaultStartBlocks[templateKey]; | |
| } else { | |
| console.warn( | |
| `Warning: No startBlock configured for '${templateKey}' on network '${network}' (chain ID ${chainId}); falling back to 0. ` + | |
| "This may cause slow indexing if the contract was deployed well after genesis." | |
| ); | |
| startBlock = 0; | |
| } |
Copilot
AI
Jan 30, 2026
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.
The loadAbi function expects ABI files to be named using the template key format (e.g., "USDFCToken.abi.json"), but the actual ABI file for the USDFCToken contract is named "FilecoinPayV1.abi.json" in the service_contracts/abi directory. While this function is currently not used in the codebase, it could cause runtime errors if someone tries to call loadAbi("USDFCToken") in the future.
Consider either:
- Documenting that
loadAbishould use the actual contract names (e.g., "FilecoinPayV1") rather than the template keys - Creating a mapping from template keys to actual ABI file names
- Ensuring ABI files are named consistently with the template keys
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If a network is added to NETWORK_CHAIN_IDS but not to NETWORK_NAMES, the config object will have
name: undefined, which could cause issues with template rendering. Consider adding validation to ensure both mappings are in sync, or consolidating them into a single data structure.For example:
This would make it impossible to have mismatched entries.