diff --git a/README.md b/README.md index 32f9c37..9804f2a 100644 --- a/README.md +++ b/README.md @@ -31,33 +31,49 @@ As a user storing data with PDP I can use the explorer to: This project uses subgraph technology and the Goldsky platform for data indexing and monitoring. ## Goldsky -- Log in to [goldsky](https://goldsky.com) + +### Configuration +Network configurations are managed in `subgraph/config/network.json`. This file contains network-specific settings including: +- Network name (e.g., `filecoin`, `filecoin-testnet`) +- PDPVerifier contract address +- Start block number +- Max proving period +- Challenge window size + +The build system uses mustache templates to automatically generate: +- `subgraph.yaml` from `templates/subgraph.template.yaml` +- `src/generated/constants.ts` from `templates/constants.template.ts` + +### Login +Log in to [goldsky](https://goldsky.com): ```bash cd subgraph -# Login goldsky login # API key: enter your Goldsky API key xxxxxxxxxxxx ``` -- Switch chain environment - - mainnet - - Update `subgraph.yaml` with `cp subgraph_mainnet.yaml subgraph.yaml` - - Update `utils/index.ts` to set `export const PDPVerifierAddress = "0xBADd0B92C1c71d02E7d520f64c0876538fa2557F"; export const MaxProvingPeriod = 2880;` - - calibration - - Update `subgraph.yaml` with `cp subgraph_testnet.yaml subgraph.yaml` - - Update `utils/index.ts` to set `export const PDPVerifierAddress = "0x85e366Cf9DD2c0aE37E963d9556F5f4718d6417C"; export const MaxProvingPeriod = 240;` -- Build and deploy subgraph + +### Build and Deploy + +#### Mainnet ```bash -# mainnet -graph codegen -graph build +# Build for mainnet (generates constants and YAML from config/network.json) +npm run build:mainnet + +# Deploy to Goldsky goldsky subgraph deploy /mainnet_ --path ./ -# calibration: switch chain environment first -graph codegen -graph build +``` + +#### Calibration +```bash +# Build for calibration (generates constants and YAML from config/network.json) +npm run build:calibration + +# Deploy to Goldsky goldsky subgraph deploy /calibration_ --path ./ ``` -- Sync + +### Sync Wait until `mainnet_` and `calibration_` finish syncing. ## Frontend Site diff --git a/subgraph/.gitignore b/subgraph/.gitignore index 0b38c06..99df03e 100644 --- a/subgraph/.gitignore +++ b/subgraph/.gitignore @@ -34,3 +34,7 @@ typechain-types # Hardhat files cache + +# Generated subgraph.yaml +subgraph.yaml +src/generated/ diff --git a/subgraph/config/network.json b/subgraph/config/network.json new file mode 100644 index 0000000..1d012af --- /dev/null +++ b/subgraph/config/network.json @@ -0,0 +1,26 @@ +{ + "networks": { + "calibration": { + "name": "filecoin-testnet", + "PDPVerifier": { + "address": "0x85e366Cf9DD2c0aE37E963d9556F5f4718d6417C", + "startBlock": 3140755 + }, + "FWSS": { + "maxProvingPeriod": "240", + "challengeWindowSize": "20" + } + }, + "mainnet": { + "name": "filecoin", + "PDPVerifier": { + "address": "0xBADd0B92C1c71d02E7d520f64c0876538fa2557F", + "startBlock": 5441432 + }, + "FWSS": { + "maxProvingPeriod": "2880", + "challengeWindowSize": "60" + } + } + } +} diff --git a/subgraph/package-lock.json b/subgraph/package-lock.json index e5eb00a..e7800e6 100644 --- a/subgraph/package-lock.json +++ b/subgraph/package-lock.json @@ -7,8 +7,9 @@ "name": "pd", "license": "UNLICENSED", "dependencies": { - "@graphprotocol/graph-cli": "0.97.0", - "@graphprotocol/graph-ts": "0.37.0" + "@graphprotocol/graph-cli": "^0.97.1", + "@graphprotocol/graph-ts": "^0.38.1", + "mustache": "^4.2.0" }, "devDependencies": { "matchstick-as": "0.6.0" @@ -68,13 +69,13 @@ } }, "node_modules/@graphprotocol/graph-cli": { - "version": "0.97.0", - "resolved": "https://registry.npmjs.org/@graphprotocol/graph-cli/-/graph-cli-0.97.0.tgz", - "integrity": "sha512-SvijthiWbQEL3HdRDf2ydc4uAUwWJfTKyiXKXkXTtimk/hXNgzf4DuqxZPVQOOq4yx5U18iOCc/TKkTI7xCNjw==", + "version": "0.97.1", + "resolved": "https://registry.npmjs.org/@graphprotocol/graph-cli/-/graph-cli-0.97.1.tgz", + "integrity": "sha512-j5dc2Tl694jMZmVQu8SSl5Yt3VURiBPgglQEpx30aW6UJ89eLR/x46Nn7S6eflV69fmB5IHAuAACnuTzo8MD0Q==", "license": "(Apache-2.0 OR MIT)", "dependencies": { "@float-capital/float-subgraph-uncrashable": "0.0.0-internal-testing.5", - "@oclif/core": "4.2.8", + "@oclif/core": "4.3.0", "@oclif/plugin-autocomplete": "^3.2.11", "@oclif/plugin-not-found": "^3.2.29", "@oclif/plugin-warn-if-update-available": "^3.1.24", @@ -82,23 +83,23 @@ "@whatwg-node/fetch": "^0.10.1", "assemblyscript": "0.19.23", "chokidar": "4.0.3", - "debug": "4.4.0", - "docker-compose": "1.1.1", + "debug": "4.4.1", + "docker-compose": "1.2.0", "fs-extra": "11.3.0", - "glob": "11.0.1", + "glob": "11.0.2", "gluegun": "5.2.0", - "graphql": "16.10.0", - "immutable": "5.0.3", - "jayson": "4.1.3", + "graphql": "16.11.0", + "immutable": "5.1.2", + "jayson": "4.2.0", "js-yaml": "4.1.0", "kubo-rpc-client": "^5.0.2", - "open": "10.1.0", + "open": "10.1.2", "prettier": "3.5.3", - "semver": "7.7.1", + "semver": "7.7.2", "tmp-promise": "3.0.3", - "undici": "7.4.0", + "undici": "7.9.0", "web3-eth-abi": "4.4.1", - "yaml": "2.7.0" + "yaml": "2.8.0" }, "bin": { "graph": "bin/run.js" @@ -107,54 +108,10 @@ "node": ">=20.18.1" } }, - "node_modules/@graphprotocol/graph-cli/node_modules/@oclif/core": { - "version": "4.2.8", - "resolved": "https://registry.npmjs.org/@oclif/core/-/core-4.2.8.tgz", - "integrity": "sha512-OWv4Va6bERxIhrYcnUGzyhGRqktc64lJO6cZ3UwkzJDpfR8ZrbCxRfKRBBah1i8kzUlOAeAXnpbMBMah3skKwA==", - "license": "MIT", - "dependencies": { - "ansi-escapes": "^4.3.2", - "ansis": "^3.16.0", - "clean-stack": "^3.0.1", - "cli-spinners": "^2.9.2", - "debug": "^4.4.0", - "ejs": "^3.1.10", - "get-package-type": "^0.1.0", - "globby": "^11.1.0", - "indent-string": "^4.0.0", - "is-wsl": "^2.2.0", - "lilconfig": "^3.1.3", - "minimatch": "^9.0.5", - "semver": "^7.6.3", - "string-width": "^4.2.3", - "supports-color": "^8", - "widest-line": "^3.1.0", - "wordwrap": "^1.0.0", - "wrap-ansi": "^7.0.0" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@graphprotocol/graph-cli/node_modules/minimatch": { - "version": "9.0.5", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", - "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", - "license": "ISC", - "dependencies": { - "brace-expansion": "^2.0.1" - }, - "engines": { - "node": ">=16 || 14 >=14.17" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, "node_modules/@graphprotocol/graph-ts": { - "version": "0.37.0", - "resolved": "https://registry.npmjs.org/@graphprotocol/graph-ts/-/graph-ts-0.37.0.tgz", - "integrity": "sha512-3xp/sO8zFDBkX44ydGB87ow5Cyrfr/SAm/cWzIRzUVL7ROw0KUyFBG1xj4KKlMnAod7/RL99zChYquC15H4Oqg==", + "version": "0.38.2", + "resolved": "https://registry.npmjs.org/@graphprotocol/graph-ts/-/graph-ts-0.38.2.tgz", + "integrity": "sha512-87KIFSFs2+Te+mnmb7Y+M57oqzlLy20cIyPIRbn9qJfpZFSZHTKtBLT6KQmcsK0YkoWis9Ur3c3M2c9mmaaEHQ==", "dependencies": { "assemblyscript": "0.27.31" } @@ -563,99 +520,12 @@ } }, "node_modules/@isaacs/cliui": { - "version": "8.0.2", - "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", - "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==", - "license": "ISC", - "dependencies": { - "string-width": "^5.1.2", - "string-width-cjs": "npm:string-width@^4.2.0", - "strip-ansi": "^7.0.1", - "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", - "wrap-ansi": "^8.1.0", - "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/@isaacs/cliui/node_modules/ansi-regex": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz", - "integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==", - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-regex?sponsor=1" - } - }, - "node_modules/@isaacs/cliui/node_modules/ansi-styles": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", - "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/@isaacs/cliui/node_modules/emoji-regex": { - "version": "9.2.2", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", - "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", - "license": "MIT" - }, - "node_modules/@isaacs/cliui/node_modules/string-width": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", - "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", - "license": "MIT", - "dependencies": { - "eastasianwidth": "^0.2.0", - "emoji-regex": "^9.2.2", - "strip-ansi": "^7.0.1" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/@isaacs/cliui/node_modules/strip-ansi": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", - "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", - "license": "MIT", - "dependencies": { - "ansi-regex": "^6.0.1" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/strip-ansi?sponsor=1" - } - }, - "node_modules/@isaacs/cliui/node_modules/wrap-ansi": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", - "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", - "license": "MIT", - "dependencies": { - "ansi-styles": "^6.1.0", - "string-width": "^5.0.1", - "strip-ansi": "^7.0.1" - }, + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-9.0.0.tgz", + "integrity": "sha512-AokJm4tuBHillT+FpMtxQ60n8ObyXBatq7jD2/JA9dxbDDokKQm8KMht5ibGzLVU9IJDIKK4TPKgMHEYMn3lMg==", + "license": "BlueOak-1.0.0", "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + "node": ">=18" } }, "node_modules/@leichtgewicht/ip-codec": { @@ -855,9 +725,9 @@ } }, "node_modules/@oclif/core": { - "version": "4.2.10", - "resolved": "https://registry.npmjs.org/@oclif/core/-/core-4.2.10.tgz", - "integrity": "sha512-fAqcXgqkUm4v5FYy7qWP4w1HaOlVSVJveah+yVTo5Nm5kTiXhmD5mQQ7+knGeBaStyrtQy6WardoC2xSic9rlQ==", + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/@oclif/core/-/core-4.3.0.tgz", + "integrity": "sha512-lIzHY+JMP6evrS5E/sGijNnwrCoNtGy8703jWXcMuPOYKiFhWoAqnIm1BGgoRgmxczkbSfRsHUL/lwsSgh74Lw==", "license": "MIT", "dependencies": { "ansi-escapes": "^4.3.2", @@ -1057,6 +927,7 @@ "resolved": "https://registry.npmjs.org/@types/node/-/node-22.14.1.tgz", "integrity": "sha512-u0HuPQwe/dHrItgHHpmw3N2fYCR6x4ivMNbPHRkBVP4CvN+kiRrKHWk3i8tXiO/joPwXLMYvF9TTF0eqgHIuOw==", "license": "MIT", + "peer": true, "dependencies": { "undici-types": "~6.21.0" } @@ -1782,9 +1653,9 @@ "license": "Apache-2.0 OR MIT" }, "node_modules/debug": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.0.tgz", - "integrity": "sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==", + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.1.tgz", + "integrity": "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==", "license": "MIT", "dependencies": { "ms": "^2.1.3" @@ -1799,9 +1670,9 @@ } }, "node_modules/default-browser": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/default-browser/-/default-browser-5.2.1.tgz", - "integrity": "sha512-WY/3TUME0x3KPYdRRxEJJvXRHV4PyPoUsxtZa78lwItwRQRHhd2U9xOscaT/YTf8uCXIAjeJOFBVEh/7FtD8Xg==", + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/default-browser/-/default-browser-5.5.0.tgz", + "integrity": "sha512-H9LMLr5zwIbSxrmvikGuI/5KGhZ8E2zH3stkMgM5LpOWDutGM2JZaj460Udnf1a+946zc7YBgrqEWwbk7zHvGw==", "license": "MIT", "dependencies": { "bundle-name": "^4.1.0", @@ -1815,9 +1686,9 @@ } }, "node_modules/default-browser-id": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/default-browser-id/-/default-browser-id-5.0.0.tgz", - "integrity": "sha512-A6p/pu/6fyBcA1TRz/GqWYPViplrftcW2gZC9q79ngNCKAeR/X3gcEdXQHl4KNXV+3wgIJ1CPkJQ3IHM6lcsyA==", + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/default-browser-id/-/default-browser-id-5.0.1.tgz", + "integrity": "sha512-x1VCxdX4t+8wVfd1so/9w+vQ4vx7lKd2Qp5tDRutErwmR85OgmfX7RlLRMWafRMY7hbEiXIbudNrjOAPa/hL8Q==", "license": "MIT", "engines": { "node": ">=18" @@ -1904,9 +1775,9 @@ } }, "node_modules/docker-compose": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/docker-compose/-/docker-compose-1.1.1.tgz", - "integrity": "sha512-UkIUz0LtzuO17Ijm6SXMGtfZMs7IvbNwvuJBiBuN93PIhr/n9/sbJMqpvYFaCBGfwu1ZM4PPPDgQzeeke4lEoA==", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/docker-compose/-/docker-compose-1.2.0.tgz", + "integrity": "sha512-wIU1eHk3Op7dFgELRdmOYlPYS4gP8HhH1ZmZa13QZF59y0fblzFDFmKPhyc05phCy2hze9OEvNZAsoljrs+72w==", "license": "MIT", "dependencies": { "yaml": "^2.2.2" @@ -1915,18 +1786,6 @@ "node": ">= 6.0.0" } }, - "node_modules/docker-compose/node_modules/yaml": { - "version": "2.7.1", - "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.7.1.tgz", - "integrity": "sha512-10ULxpnOCQXxJvBgxsn9ptjq6uviG/htZKk9veJGhlqn3w/DxQ631zFF+nlQXLwmImeS5amR2dl2U8sg6U9jsQ==", - "license": "ISC", - "bin": { - "yaml": "bin.mjs" - }, - "engines": { - "node": ">= 14" - } - }, "node_modules/dunder-proto": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", @@ -1941,12 +1800,6 @@ "node": ">= 0.4" } }, - "node_modules/eastasianwidth": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", - "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", - "license": "MIT" - }, "node_modules/ejs": { "version": "3.1.10", "resolved": "https://registry.npmjs.org/ejs/-/ejs-3.1.10.tgz", @@ -2406,9 +2259,10 @@ } }, "node_modules/glob": { - "version": "11.0.1", - "resolved": "https://registry.npmjs.org/glob/-/glob-11.0.1.tgz", - "integrity": "sha512-zrQDm8XPnYEKawJScsnM0QzobJxlT/kHOOlRTio8IH/GrmxRE5fjllkzdaHclIuNjUQTJYH2xHNIGfdpJkDJUw==", + "version": "11.0.2", + "resolved": "https://registry.npmjs.org/glob/-/glob-11.0.2.tgz", + "integrity": "sha512-YT7U7Vye+t5fZ/QMkBFrTJ7ZQxInIUjwyAjVj84CYXqgBdv30MFUPGnBR6sQaVq6Is15wYJUsnzTuWaGRBhBAQ==", + "deprecated": "Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me", "license": "ISC", "dependencies": { "foreground-child": "^3.1.0", @@ -2440,16 +2294,37 @@ "node": ">= 6" } }, + "node_modules/glob/node_modules/balanced-match": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-4.0.4.tgz", + "integrity": "sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA==", + "license": "MIT", + "engines": { + "node": "18 || 20 || >=22" + } + }, + "node_modules/glob/node_modules/brace-expansion": { + "version": "5.0.5", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.5.tgz", + "integrity": "sha512-VZznLgtwhn+Mact9tfiwx64fA9erHH/MCXEUfB/0bX/6Fz6ny5EGTXYltMocqg4xFAQZtnO3DHWWXi8RiuN7cQ==", + "license": "MIT", + "dependencies": { + "balanced-match": "^4.0.2" + }, + "engines": { + "node": "18 || 20 || >=22" + } + }, "node_modules/glob/node_modules/minimatch": { - "version": "10.0.1", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.0.1.tgz", - "integrity": "sha512-ethXTt3SGGR+95gudmqJ1eNhRO7eGEGIgYA9vnPatK4/etz2MEVDno5GMCibdMTuBMyElzIlgxMna3K94XDIDQ==", - "license": "ISC", + "version": "10.2.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.2.5.tgz", + "integrity": "sha512-MULkVLfKGYDFYejP07QOurDLLQpcjk7Fw+7jXS2R2czRQzR56yHRveU5NDJEOviH+hETZKSkIk5c+T23GjFUMg==", + "license": "BlueOak-1.0.0", "dependencies": { - "brace-expansion": "^2.0.1" + "brace-expansion": "^5.0.5" }, "engines": { - "node": "20 || >=22" + "node": "18 || 20 || >=22" }, "funding": { "url": "https://github.com/sponsors/isaacs" @@ -2591,10 +2466,11 @@ "license": "ISC" }, "node_modules/graphql": { - "version": "16.10.0", - "resolved": "https://registry.npmjs.org/graphql/-/graphql-16.10.0.tgz", - "integrity": "sha512-AjqGKbDGUFRKIRCP9tCKiIGHyriz2oHEbPIbEtcSLSs4YjReZOIPQQWek4+6hjw62H9QShXHyaGivGiYVLeYFQ==", + "version": "16.11.0", + "resolved": "https://registry.npmjs.org/graphql/-/graphql-16.11.0.tgz", + "integrity": "sha512-mS1lbMsxgQj6hge1XZ6p7GPhbrtFwUFYi3wRzXAC/FmYnyXMTvvI3td3rjmQ2u8ewXueaSvRPWaEcgVVOT9Jnw==", "license": "MIT", + "peer": true, "engines": { "node": "^12.22.0 || ^14.16.0 || ^16.0.0 || >=17.0.0" } @@ -2742,9 +2618,9 @@ } }, "node_modules/immutable": { - "version": "5.0.3", - "resolved": "https://registry.npmjs.org/immutable/-/immutable-5.0.3.tgz", - "integrity": "sha512-P8IdPQHq3lA1xVeBRi5VPqUm5HDgKnx0Ru51wZz5mjxHr5n3RWhjIpOFU7ybkUxfB+5IToy+OLaHYDBIWsv+uw==", + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/immutable/-/immutable-5.1.2.tgz", + "integrity": "sha512-qHKXW1q6liAk1Oys6umoaZbDRqjcjgSrbnrifHsfsttza7zcvRAsL7mMV6xWcyhwQy7Xj5v4hhbr6b+iDYwlmQ==", "license": "MIT" }, "node_modules/import-fresh": { @@ -3157,12 +3033,12 @@ } }, "node_modules/jackspeak": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-4.1.0.tgz", - "integrity": "sha512-9DDdhb5j6cpeitCbvLO7n7J4IxnbM6hoF6O1g4HQ5TfhvvKN8ywDM7668ZhMHRqVmxqhps/F6syWK2KcPxYlkw==", + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-4.2.3.tgz", + "integrity": "sha512-ykkVRwrYvFm1nb2AJfKKYPr0emF6IiXDYUaFx4Zn9ZuIH7MrzEZ3sD5RlqGXNRpHtvUHJyOnCEFxOlNDtGo7wg==", "license": "BlueOak-1.0.0", "dependencies": { - "@isaacs/cliui": "^8.0.2" + "@isaacs/cliui": "^9.0.0" }, "engines": { "node": "20 || >=22" @@ -3218,9 +3094,9 @@ } }, "node_modules/jayson": { - "version": "4.1.3", - "resolved": "https://registry.npmjs.org/jayson/-/jayson-4.1.3.tgz", - "integrity": "sha512-LtXh5aYZodBZ9Fc3j6f2w+MTNcnxteMOrb+QgIouguGOulWi0lieEkOUg+HkjjFs0DGoWDds6bi4E9hpNFLulQ==", + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/jayson/-/jayson-4.2.0.tgz", + "integrity": "sha512-VfJ9t1YLwacIubLhONk0KFeosUBwstRWQ0IRT1KDjEjnVnSOVHC3uwugyV7L0c7R9lpVyrUGT2XWiBA1UTtpyg==", "license": "MIT", "dependencies": { "@types/connect": "^3.4.33", @@ -3232,7 +3108,7 @@ "eyes": "^0.1.8", "isomorphic-ws": "^4.0.1", "json-stringify-safe": "^5.0.1", - "JSONStream": "^1.3.5", + "stream-json": "^1.9.1", "uuid": "^8.3.2", "ws": "^7.5.10" }, @@ -3297,31 +3173,6 @@ "graceful-fs": "^4.1.6" } }, - "node_modules/jsonparse": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/jsonparse/-/jsonparse-1.3.1.tgz", - "integrity": "sha512-POQXvpdL69+CluYsillJ7SUhKvytYjW9vG/GKpnf+xP8UWgYEM/RaMzHHofbALDiKbbP1W8UEYmgGl39WkPZsg==", - "engines": [ - "node >= 0.2.0" - ], - "license": "MIT" - }, - "node_modules/JSONStream": { - "version": "1.3.5", - "resolved": "https://registry.npmjs.org/JSONStream/-/JSONStream-1.3.5.tgz", - "integrity": "sha512-E+iruNOY8VV9s4JEbe1aNEm6MiszPRr/UfcHMz0TQh1BXSxHK+ASV1R6W4HpjBhSeS+54PIsAMCBmwD06LLsqQ==", - "license": "(MIT OR Apache-2.0)", - "dependencies": { - "jsonparse": "^1.2.0", - "through": ">=2.2.7 <3" - }, - "bin": { - "JSONStream": "bin.js" - }, - "engines": { - "node": "*" - } - }, "node_modules/kubo-rpc-client": { "version": "5.1.0", "resolved": "https://registry.npmjs.org/kubo-rpc-client/-/kubo-rpc-client-5.1.0.tgz", @@ -3496,10 +3347,10 @@ "license": "Apache-2.0" }, "node_modules/lru-cache": { - "version": "11.1.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.1.0.tgz", - "integrity": "sha512-QIXZUBJUx+2zHUdQujWejBkcD9+cs94tLn0+YL8UrCh+D5sCXZ4c7LaEH48pNwRY3MLDgqUFyhlCyjJPf1WP0A==", - "license": "ISC", + "version": "11.2.7", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.2.7.tgz", + "integrity": "sha512-aY/R+aEsRelme17KGQa/1ZSIpLpNYYrhcrepKTZgE+W3WM16YMCaPwOHLHsmopZHELU0Ojin1lPVxKR0MihncA==", + "license": "BlueOak-1.0.0", "engines": { "node": "20 || >=22" } @@ -3595,10 +3446,10 @@ } }, "node_modules/minipass": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", - "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", - "license": "ISC", + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.3.tgz", + "integrity": "sha512-tEBHqDnIoM/1rXME1zgka9g6Q2lcoCkxHLuc7ODJ5BxbP5d4c2Z5cGgtXAku59200Cx7diuHTOYfSBD8n6mm8A==", + "license": "BlueOak-1.0.0", "engines": { "node": ">=16 || 14 >=14.17" } @@ -3615,6 +3466,15 @@ "integrity": "sha512-qbB0CQDt3QKfiAzZ5ZYjLFOs+zW43vA4uyM8g27PeEuXZybUOFyjrVdP93HPBHMoglibwfkdVwbzfUq8qGcH6g==", "license": "Apache-2.0 OR MIT" }, + "node_modules/mustache": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/mustache/-/mustache-4.2.0.tgz", + "integrity": "sha512-71ippSywq5Yb7/tVYyGbkBggbU8H3u5Rz56fH60jGFgr8uHwxs+aSKeqmluIVzM0m0kB7xQjKS6qPfd0b2ZoqQ==", + "license": "MIT", + "bin": { + "mustache": "bin/mustache" + } + }, "node_modules/mute-stream": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-2.0.0.tgz", @@ -3697,9 +3557,9 @@ } }, "node_modules/open": { - "version": "10.1.0", - "resolved": "https://registry.npmjs.org/open/-/open-10.1.0.tgz", - "integrity": "sha512-mnkeQ1qP5Ue2wd+aivTD3NHd/lZ96Lu0jgf0pwktLPtx6cTZiH7tyeGRRHs0zX0rbrahXPnXlUnbeXyaBBuIaw==", + "version": "10.1.2", + "resolved": "https://registry.npmjs.org/open/-/open-10.1.2.tgz", + "integrity": "sha512-cxN6aIDPz6rm8hbebcP7vrQNhvRcveZoJU72Y7vskh4oIm+BZwBECnx5nTmrlres1Qapvx27Qo1Auukpf8PKXw==", "license": "MIT", "dependencies": { "default-browser": "^5.2.1", @@ -3715,9 +3575,9 @@ } }, "node_modules/open/node_modules/is-wsl": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-3.1.0.tgz", - "integrity": "sha512-UcVfVfaK4Sc4m7X3dUSoHoozQGBEFeDC+zVo06t98xe8CzHSZZBekNXH+tu0NalHolcJ/QAGqS46Hef7QXBIMw==", + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-3.1.1.tgz", + "integrity": "sha512-e6rvdUCiQCAuumZslxRJWR/Doq4VpPR82kqclvcS0efgt430SlGIk05vdCN58+VrzgtIcfNODjozVielycD4Sw==", "license": "MIT", "dependencies": { "is-inside-container": "^1.0.0" @@ -3880,16 +3740,16 @@ } }, "node_modules/path-scurry": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-2.0.0.tgz", - "integrity": "sha512-ypGJsmGtdXUOeM5u93TyeIEfEhM6s+ljAhrk5vAvSx8uyY/02OvrZnA0YNGUrPXfpJMgI1ODd3nwz8Npx4O4cg==", + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-2.0.2.tgz", + "integrity": "sha512-3O/iVVsJAPsOnpwWIeD+d6z/7PmqApyQePUtCndjatj/9I5LylHvt5qluFaBT3I5h3r1ejfR056c+FCv+NnNXg==", "license": "BlueOak-1.0.0", "dependencies": { "lru-cache": "^11.0.0", "minipass": "^7.1.2" }, "engines": { - "node": "20 || >=22" + "node": "18 || 20 || >=22" }, "funding": { "url": "https://github.com/sponsors/isaacs" @@ -4111,9 +3971,9 @@ } }, "node_modules/run-applescript": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/run-applescript/-/run-applescript-7.0.0.tgz", - "integrity": "sha512-9by4Ij99JUr/MCFBUkDKLWK3G9HVXmabKz9U5MlIAIuvuzkiOicRYs8XJLxX+xahD+mLiiCYDqF9dKAgtzKP1A==", + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/run-applescript/-/run-applescript-7.1.0.tgz", + "integrity": "sha512-DPe5pVFaAsinSaV6QjQ6gdiedWDcRCbUuiQfQa2wmWV7+xC9bGulGI8+TdRmoFkAPaBXk8CrAbnlY2ISniJ47Q==", "license": "MIT", "engines": { "node": ">=18" @@ -4189,9 +4049,9 @@ "license": "MIT" }, "node_modules/semver": { - "version": "7.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.1.tgz", - "integrity": "sha512-hlq8tAfn0m/61p4BVRcPzIGr6LKiMwo4VM6dGi6pt4qcRkmNzTcWq6eCEjEh+qXjkMDvPlOFFSGwQjoEa6gyMA==", + "version": "7.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.2.tgz", + "integrity": "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==", "license": "ISC", "bin": { "semver": "bin/semver.js" @@ -4272,6 +4132,21 @@ "source-map": "^0.6.0" } }, + "node_modules/stream-chain": { + "version": "2.2.5", + "resolved": "https://registry.npmjs.org/stream-chain/-/stream-chain-2.2.5.tgz", + "integrity": "sha512-1TJmBx6aSWqZ4tx7aTpBDXK0/e2hhcNSTV8+CbFJtDjbb+I1mZ8lHit0Grw9GRT+6JbIrrDd8esncgBi8aBXGA==", + "license": "BSD-3-Clause" + }, + "node_modules/stream-json": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/stream-json/-/stream-json-1.9.1.tgz", + "integrity": "sha512-uWkjJ+2Nt/LO9Z/JyKZbMusL8Dkh97uUBTv3AJQ74y07lVahLY4eEFsPsE97pxYBwr8nnjMAIch5eqI0gPShyw==", + "license": "BSD-3-Clause", + "dependencies": { + "stream-chain": "^2.2.5" + } + }, "node_modules/stream-to-it": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/stream-to-it/-/stream-to-it-1.0.1.tgz", @@ -4312,21 +4187,6 @@ "node": ">=8" } }, - "node_modules/string-width-cjs": { - "name": "string-width", - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "license": "MIT", - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/strip-ansi": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", @@ -4339,19 +4199,6 @@ "node": ">=8" } }, - "node_modules/strip-ansi-cjs": { - "name": "strip-ansi", - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "license": "MIT", - "dependencies": { - "ansi-regex": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/strip-final-newline": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", @@ -4376,12 +4223,6 @@ "url": "https://github.com/chalk/supports-color?sponsor=1" } }, - "node_modules/through": { - "version": "2.3.8", - "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", - "integrity": "sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==", - "license": "MIT" - }, "node_modules/tmp": { "version": "0.2.3", "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.3.tgz", @@ -4485,10 +4326,11 @@ } }, "node_modules/undici": { - "version": "7.4.0", - "resolved": "https://registry.npmjs.org/undici/-/undici-7.4.0.tgz", - "integrity": "sha512-PUQM3/es3noM24oUn10u3kNNap0AbxESOmnssmW+dOi9yGwlUSi5nTNYl3bNbTkWOF8YZDkx2tCmj9OtQ3iGGw==", + "version": "7.9.0", + "resolved": "https://registry.npmjs.org/undici/-/undici-7.9.0.tgz", + "integrity": "sha512-e696y354tf5cFZPXsF26Yg+5M63+5H3oE6Vtkh2oqbvsE2Oe7s2nIbcQh5lmG7Lp/eS29vJtTpw9+p6PX0qNSg==", "license": "MIT", + "peer": true, "engines": { "node": ">=20.18.1" } @@ -4758,24 +4600,6 @@ "url": "https://github.com/chalk/wrap-ansi?sponsor=1" } }, - "node_modules/wrap-ansi-cjs": { - "name": "wrap-ansi", - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", - "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", - "license": "MIT", - "dependencies": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/wrap-ansi?sponsor=1" - } - }, "node_modules/wrappy": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", @@ -4787,6 +4611,7 @@ "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.10.tgz", "integrity": "sha512-+dbF1tHwZpXcbOJdVOkzLDxZP1ailvSxM6ZweXTegylPny803bFhA+vqBYw4s31NSAk4S2Qz+AKXK9a4wkdjcQ==", "license": "MIT", + "peer": true, "engines": { "node": ">=8.3.0" }, @@ -4810,15 +4635,15 @@ "license": "ISC" }, "node_modules/yaml": { - "version": "2.7.0", - "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.7.0.tgz", - "integrity": "sha512-+hSoy/QHluxmC9kCIJyL/uyFmLmc+e5CFR5Wa+bpIhIj85LVb9ZH2nVnqrHoSvKogwODv0ClqZkmiSSaIH5LTA==", + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.8.0.tgz", + "integrity": "sha512-4lLa/EcQCB0cJkyts+FpIRx5G/llPxfP6VQU5KByHEhLxY3IJCH0f0Hy1MHI8sClTvsIb8qwRJ6R/ZdlDJ/leQ==", "license": "ISC", "bin": { "yaml": "bin.mjs" }, "engines": { - "node": ">= 14" + "node": ">= 14.6" } }, "node_modules/yargs-parser": { @@ -4847,6 +4672,7 @@ "resolved": "https://registry.npmjs.org/zod/-/zod-3.24.2.tgz", "integrity": "sha512-lY7CDW43ECgW9u1TcT3IoXHflywfVqDYze4waEz812jR/bZ8FHDsl7pFQoSZTz5N+2NqRXs8GBwnAwo3ZNxqhQ==", "license": "MIT", + "peer": true, "funding": { "url": "https://github.com/sponsors/colinhacks" } diff --git a/subgraph/package.json b/subgraph/package.json index 2df273c..cf581df 100644 --- a/subgraph/package.json +++ b/subgraph/package.json @@ -2,17 +2,31 @@ "name": "pd", "license": "UNLICENSED", "scripts": { + "generate": "npm run generate:constants && npm run generate:yaml", + "precodegen": "npm run generate", "codegen": "graph codegen", + "prebuild": "npm run codegen", "build": "graph build", + "build:calibration": "NETWORK=calibration npm run build", + "build:mainnet": "NETWORK=mainnet npm run build", + "generate:constants": "node ./scripts/generate-constants.js", + "generate:constants:calibration": "node ./scripts/generate-constants.js calibration", + "generate:constants:mainnet": "node ./scripts/generate-constants.js mainnet", + "generate:yaml": "node ./scripts/generate-config.js", + "generate:yaml:calibration": "node ./scripts/generate-config.js calibration", + "generate:yaml:mainnet": "node ./scripts/generate-config.js mainnet", + "predeploy": "npm run generate", "deploy": "goldsky subgraph deploy pdp/1.0.0 --path ./", "create-local": "graph create --node http://192.168.11.154:8020/ pd/pdp-explorer", "remove-local": "graph remove --node http://192.168.11.154:8020/ pd/pdp-explorer", "deploy-local": "graph deploy --node http://192.168.11.154:8020/ --ipfs http://192.168.11.154:5001 pd/pdp-explorer", + "pretest": "npm run generate", "test": "graph test" }, "dependencies": { "@graphprotocol/graph-cli": "^0.97.1", - "@graphprotocol/graph-ts": "^0.38.1" + "@graphprotocol/graph-ts": "^0.38.1", + "mustache": "^4.2.0" }, "devDependencies": { "matchstick-as": "0.6.0" diff --git a/subgraph/scripts/generate-config.js b/subgraph/scripts/generate-config.js new file mode 100644 index 0000000..3b74d07 --- /dev/null +++ b/subgraph/scripts/generate-config.js @@ -0,0 +1,45 @@ +#!/usr/bin/env node + +/** + * Generates subgraph.yaml from network configuration + * Usage: node generate-config.js [network] + * Environment: NETWORK=mainnet node generate-config.js + */ + +const fs = require("fs"); +const path = require("path"); +const mustache = require("mustache"); +const { + loadNetworkConfig, + getNetworkFromArgs, + getTemplatePath, +} = require("./utils/config-loader"); + +const network = getNetworkFromArgs(); +const selectedConfig = loadNetworkConfig(network); + +const templatePath = getTemplatePath("subgraph.template.yaml"); +let templateContent; + +try { + templateContent = fs.readFileSync(templatePath, "utf8"); +} catch (error) { + console.error(`Error: Failed to read subgraph template at: ${templatePath}`); + console.error(`Template Error: ${error.message}`); + process.exit(1); +} + +const yamlContent = mustache.render(templateContent, selectedConfig); + +const outputPath = path.join(__dirname, "..", "subgraph.yaml"); + +try { + fs.writeFileSync(outputPath, yamlContent); + console.log( + `✅ Generated subgraph.yaml for ${network} network at: ${outputPath}` + ); +} catch (error) { + console.error(`Error: Failed to write subgraph.yaml to: ${outputPath}`); + console.error(`Write Error: ${error.message}`); + process.exit(1); +} diff --git a/subgraph/scripts/generate-constants.js b/subgraph/scripts/generate-constants.js new file mode 100644 index 0000000..775436e --- /dev/null +++ b/subgraph/scripts/generate-constants.js @@ -0,0 +1,78 @@ +#!/usr/bin/env node + +/** + * Generates TypeScript constants file from network configuration + * Usage: node generate-constants.js [network] + * Environment: NETWORK=mainnet node generate-constants.js + */ + +const fs = require("fs"); +const path = require("path"); +const mustache = require("mustache"); +const { + loadNetworkConfig, + getNetworkFromArgs, + getTemplatePath, +} = require("./utils/config-loader"); + +const network = getNetworkFromArgs(); + +const selectedConfig = loadNetworkConfig(network); + +/** + * Validates that required contracts exist in the configuration + * @param {Object} config - The network configuration object + * @param {string} network - The network name for error messages + */ +function validateRequiredContracts(config, network) { + const requiredContracts = ["PDPVerifier"]; + for (const contract of requiredContracts) { + if (!config[contract] || !config[contract].address) { + console.error( + `Error: Missing or invalid '${contract}' configuration for network '${network}'` + ); + console.error( + `Each contract must have an 'address' field in config/network.json` + ); + process.exit(1); + } + } +} + +validateRequiredContracts(selectedConfig, network); + +const templatePath = getTemplatePath("constants.template.ts"); +let templateContent; + +try { + templateContent = fs.readFileSync(templatePath, "utf8"); +} catch (error) { + console.error(`Error: Failed to read constants template at: ${templatePath}`); + console.error(`Template Error: ${error.message}`); + process.exit(1); +} + +const templateData = { + network, + timestamp: new Date().toISOString(), + ...selectedConfig, +}; + +const constantsContent = mustache.render(templateContent, templateData); + +const generatedDir = path.join(__dirname, "..", "src", "generated"); +const outputPath = path.join(generatedDir, "constants.ts"); + +try { + fs.mkdirSync(generatedDir, { recursive: true }); + + fs.writeFileSync(outputPath, constantsContent); + console.log( + `✅ Generated constants for ${network} network at: ${outputPath}` + ); +} catch (error) { + console.error(`Error: Failed to write constants file to: ${outputPath}`); + console.error(`Write Error: ${error.message}`); + console.error("Please check directory permissions and available disk space."); + process.exit(1); +} diff --git a/subgraph/scripts/utils/config-loader.js b/subgraph/scripts/utils/config-loader.js new file mode 100644 index 0000000..5b511a9 --- /dev/null +++ b/subgraph/scripts/utils/config-loader.js @@ -0,0 +1,87 @@ +const fs = require("fs"); +const path = require("path"); + +const DEFAULT_NETWORK = "mainnet"; + +/** + * Gets the network name from command line arguments or environment variable + * @param {string} defaultNetwork - The default network to use if none specified + * @returns {string} The network name + */ +function getNetworkFromArgs(defaultNetwork = DEFAULT_NETWORK) { + const args = process.argv.slice(2); + const networkArgs = args.filter((arg) => !arg.startsWith("--")); + return process.env.NETWORK || networkArgs[0] || defaultNetwork; +} + +/** + * Gets the absolute path to a template file + * @param {string} templateName - The template filename + * @returns {string} The absolute path to the template + */ +function getTemplatePath(templateName) { + return path.join(__dirname, "..", "..", "templates", templateName); +} + +/** + * Loads and validates network configuration from config/network.json + * @param {string} network - The network name to load + * @returns {Object} The network configuration object + */ +function loadNetworkConfig(network = DEFAULT_NETWORK) { + const configPath = path.join(__dirname, "..", "..", "config", "network.json"); + let networkConfig; + + try { + const configContent = fs.readFileSync(configPath, "utf8"); + networkConfig = JSON.parse(configContent); + } 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." + ); + 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(`JSON Error: ${error.message}`); + process.exit(1); + } + console.error(`Error reading configuration file: ${configPath}`); + console.error(`File Error: ${error.message}`); + process.exit(1); + } + + if (!networkConfig.networks) { + console.error( + "Error: Invalid configuration structure. Missing 'networks' object in config/network.json" + ); + console.error( + 'Expected structure: { "networks": { "calibration": {...}, "mainnet": {...} } }' + ); + 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(", ")}` + ); + process.exit(1); + } + + return networkConfig.networks[network]; +} + +module.exports = { + loadNetworkConfig, + getNetworkFromArgs, + getTemplatePath, + DEFAULT_NETWORK, +}; diff --git a/subgraph/src/pdp-service.ts b/subgraph/src/pdp-service.ts index bde3508..3b5bee8 100644 --- a/subgraph/src/pdp-service.ts +++ b/subgraph/src/pdp-service.ts @@ -1,7 +1,7 @@ import { BigInt, Bytes, crypto, Address, log } from "@graphprotocol/graph-ts"; import { FaultRecord as FaultRecordEvent } from "../generated/PDPService/PDPService"; import { PDPVerifier } from "../generated/PDPVerifier/PDPVerifier"; -import { PDPVerifierAddress, NumChallenges } from "../utils"; +import { ContractConstants, NumChallenges } from "../utils"; import { EventLog, DataSet, @@ -108,9 +108,7 @@ export function findChallengedRoots( totalLeaves: BigInt, blockNumber: BigInt ): BigInt[] { - const instance = PDPVerifier.bind( - Address.fromBytes(Bytes.fromHexString(PDPVerifierAddress)) - ); + const instance = PDPVerifier.bind(ContractConstants.PDPVerifierAddress); const seedIntResult = instance.try_getRandomness(challengeEpoch); if (seedIntResult.reverted) { diff --git a/subgraph/src/pdp-verifier.ts b/subgraph/src/pdp-verifier.ts index a8d659d..a69691c 100644 --- a/subgraph/src/pdp-verifier.ts +++ b/subgraph/src/pdp-verifier.ts @@ -26,7 +26,11 @@ import { saveNetworkMetrics, } from "./helper"; import { SumTree } from "./sumTree"; -import { LeafSize, MaxProvingPeriod, ChallengeWindowSize, MaxProvingWindowsPerEvent } from "../utils"; +import { + ContractConstants, + LeafSize, + MaxProvingWindowsPerEvent, +} from "../utils"; import { validateCommPv2, unpaddedSize } from "../utils/cid"; import { DataSetStatus } from "./types"; @@ -831,9 +835,9 @@ export function handleNextProvingPeriod(event: NextProvingPeriodEvent): void { proofSet.status = DataSetStatus.PROVING; proofSet.firstDeadline = currentBlockNumber; // Set default values for proving period configuration. - // Modify MaxProvingPeriod / ChallengeWindowSize in utils/index.ts for each network. - proofSet.maxProvingPeriod = BigInt.fromI32(MaxProvingPeriod); - proofSet.challengeWindowSize = BigInt.fromI32(ChallengeWindowSize); + // Modify MaxProvingPeriod / ChallengeWindowSize in config/network.json for each network. + proofSet.maxProvingPeriod = ContractConstants.MaxProvingPeriod; + proofSet.challengeWindowSize = ContractConstants.ChallengeWindowSize; nextDeadline = currentBlockNumber.plus(proofSet.maxProvingPeriod); } else { if (currentBlockNumber.gt(proofSet.nextDeadline)) diff --git a/subgraph/subgraph_mainnet.yaml b/subgraph/subgraph_mainnet.yaml deleted file mode 100644 index b06def9..0000000 --- a/subgraph/subgraph_mainnet.yaml +++ /dev/null @@ -1,52 +0,0 @@ -specVersion: 1.3.0 -indexerHints: - prune: auto -schema: - file: ./schema.graphql -dataSources: - - kind: ethereum - name: PDPVerifier - network: filecoin - source: - address: "0xBADd0B92C1c71d02E7d520f64c0876538fa2557F" - abi: PDPVerifier - startBlock: 5441432 - mapping: - kind: ethereum/events - apiVersion: 0.0.9 - language: wasm/assemblyscript - entities: - - DataSet - - Provider - - Root - - SumTreeCount - - Service - - ServiceProviderLink - - EventLog - - Transaction - - Proof - - ProofFee - - FaultRecord - abis: - - name: PDPVerifier - file: ./abis/PDPVerifier.json - eventHandlers: - - event: DataSetCreated(indexed uint256,indexed address) - handler: handleDataSetCreated - - event: StorageProviderChanged(indexed uint256,indexed address,indexed address) - handler: handleStorageProviderChanged - - event: DataSetDeleted(indexed uint256,uint256) - handler: handleDataSetDeleted - - event: PiecesAdded(indexed uint256,uint256[],(bytes)[]) - handler: handlePiecesAdded - - event: PiecesRemoved(indexed uint256,uint256[]) - handler: handlePiecesRemoved - - event: ProofFeePaid(indexed uint256,uint256) - handler: handleProofFeePaid - - event: DataSetEmpty(indexed uint256) - handler: handleDataSetEmpty - - event: PossessionProven(indexed uint256,(uint256,uint256)[]) - handler: handlePossessionProven - - event: NextProvingPeriod(indexed uint256,uint256,uint256) - handler: handleNextProvingPeriod - file: ./src/pdp-verifier.ts diff --git a/subgraph/subgraph_testnet.yaml b/subgraph/subgraph_testnet.yaml deleted file mode 100644 index 3aeb04a..0000000 --- a/subgraph/subgraph_testnet.yaml +++ /dev/null @@ -1,52 +0,0 @@ -specVersion: 1.3.0 -indexerHints: - prune: auto -schema: - file: ./schema.graphql -dataSources: - - kind: ethereum - name: PDPVerifier - network: filecoin-testnet - source: - address: "0x85e366Cf9DD2c0aE37E963d9556F5f4718d6417C" - abi: PDPVerifier - startBlock: 3140755 - mapping: - kind: ethereum/events - apiVersion: 0.0.9 - language: wasm/assemblyscript - entities: - - DataSet - - Provider - - Root - - SumTreeCount - - Service - - ServiceProviderLink - - EventLog - - Transaction - - Proof - - ProofFee - - FaultRecord - abis: - - name: PDPVerifier - file: ./abis/PDPVerifier.json - eventHandlers: - - event: DataSetCreated(indexed uint256,indexed address) - handler: handleDataSetCreated - - event: StorageProviderChanged(indexed uint256,indexed address,indexed address) - handler: handleStorageProviderChanged - - event: DataSetDeleted(indexed uint256,uint256) - handler: handleDataSetDeleted - - event: PiecesAdded(indexed uint256,uint256[],(bytes)[]) - handler: handlePiecesAdded - - event: PiecesRemoved(indexed uint256,uint256[]) - handler: handlePiecesRemoved - - event: ProofFeePaid(indexed uint256,uint256) - handler: handleProofFeePaid - - event: DataSetEmpty(indexed uint256) - handler: handleDataSetEmpty - - event: PossessionProven(indexed uint256,(uint256,uint256)[]) - handler: handlePossessionProven - - event: NextProvingPeriod(indexed uint256,uint256,uint256) - handler: handleNextProvingPeriod - file: ./src/pdp-verifier.ts diff --git a/subgraph/templates/constants.template.ts b/subgraph/templates/constants.template.ts new file mode 100644 index 0000000..bd23096 --- /dev/null +++ b/subgraph/templates/constants.template.ts @@ -0,0 +1,17 @@ +// This file is auto-generated. Do not edit manually. +// Generated from config/network.json for network: {{network}} +// Last generated: {{timestamp}} + +import { Address, BigInt, Bytes } from "@graphprotocol/graph-ts"; + +export class ContractConstants { + static readonly PDPVerifierAddress: Address = Address.fromBytes( + Bytes.fromHexString("{{PDPVerifier.address}}") + ); + static readonly MaxProvingPeriod: BigInt = BigInt.fromString( + "{{FWSS.maxProvingPeriod}}" + ); + static readonly ChallengeWindowSize: BigInt = BigInt.fromString( + "{{FWSS.challengeWindowSize}}" + ); +} diff --git a/subgraph/subgraph.yaml b/subgraph/templates/subgraph.template.yaml similarity index 93% rename from subgraph/subgraph.yaml rename to subgraph/templates/subgraph.template.yaml index b06def9..3ae1dce 100644 --- a/subgraph/subgraph.yaml +++ b/subgraph/templates/subgraph.template.yaml @@ -6,11 +6,11 @@ schema: dataSources: - kind: ethereum name: PDPVerifier - network: filecoin + network: {{name}} source: - address: "0xBADd0B92C1c71d02E7d520f64c0876538fa2557F" + address: "{{PDPVerifier.address}}" abi: PDPVerifier - startBlock: 5441432 + startBlock: {{PDPVerifier.startBlock}} mapping: kind: ethereum/events apiVersion: 0.0.9 diff --git a/subgraph/tests/dataset-status.test.ts b/subgraph/tests/dataset-status.test.ts index 8053f54..0f95674 100644 --- a/subgraph/tests/dataset-status.test.ts +++ b/subgraph/tests/dataset-status.test.ts @@ -21,6 +21,7 @@ import { createDataSetEmptyEvent, generateTxHash, } from "./pdp-verifier-utils"; +import { ContractConstants } from "../utils"; const SET_ID = BigInt.fromI32(1); const ROOT_ID_1 = BigInt.fromI32(101); @@ -462,9 +463,17 @@ describe("DataSetStatus Lifecycle Tests", () => { nextProvingPeriodEvent1.transaction.hash = generateTxHash(92); handleNextProvingPeriod(nextProvingPeriodEvent1); + const expectedNextDeadline1 = BigInt.fromI32(200) + .plus(ContractConstants.MaxProvingPeriod) + .toString(); assert.fieldEquals("DataSet", dataSetId, "status", "PROVING"); assert.fieldEquals("DataSet", dataSetId, "firstDeadline", "200"); - assert.fieldEquals("DataSet", dataSetId, "nextDeadline", "440"); // 200 + 240 + assert.fieldEquals( + "DataSet", + dataSetId, + "nextDeadline", + expectedNextDeadline1 + ); // 200 + 240 assert.fieldEquals("DataSet", dataSetId, "currentDeadlineCount", "1"); // Step 4: Dataset becomes empty (PiecesRemoved → DataSetEmpty → NextProvingPeriod in same tx) @@ -538,11 +547,29 @@ describe("DataSetStatus Lifecycle Tests", () => { nextProvingPeriodEvent3.transaction.hash = generateTxHash(95); handleNextProvingPeriod(nextProvingPeriodEvent3); + const expectedNextDeadline2 = BigInt.fromI32(350) + .plus(ContractConstants.MaxProvingPeriod) + .toString(); assert.fieldEquals("DataSet", dataSetId, "status", "PROVING"); assert.fieldEquals("DataSet", dataSetId, "firstDeadline", "350"); // new firstDeadline, not 200 - assert.fieldEquals("DataSet", dataSetId, "nextDeadline", "590"); // 350 + 240 + assert.fieldEquals( + "DataSet", + dataSetId, + "nextDeadline", + expectedNextDeadline2 + ); // 350 + 240 assert.fieldEquals("DataSet", dataSetId, "currentDeadlineCount", "1"); // Resets to 1 - assert.fieldEquals("DataSet", dataSetId, "maxProvingPeriod", "240"); - assert.fieldEquals("DataSet", dataSetId, "challengeWindowSize", "20"); + assert.fieldEquals( + "DataSet", + dataSetId, + "maxProvingPeriod", + ContractConstants.MaxProvingPeriod.toString() + ); + assert.fieldEquals( + "DataSet", + dataSetId, + "challengeWindowSize", + ContractConstants.ChallengeWindowSize.toString() + ); }); }); diff --git a/subgraph/tests/fault-calculation.test.ts b/subgraph/tests/fault-calculation.test.ts index 14c3cc6..6e4acd5 100644 --- a/subgraph/tests/fault-calculation.test.ts +++ b/subgraph/tests/fault-calculation.test.ts @@ -20,6 +20,7 @@ import { createRootsAddedEvent, generateTxHash, } from "./pdp-verifier-utils"; +import { ContractConstants } from "../utils"; const SET_ID = BigInt.fromI32(1); const ROOT_ID_1 = BigInt.fromI32(101); @@ -32,8 +33,8 @@ const CONTRACT_ADDRESS = Address.fromString( const LISTENER_ADDRESS = Address.fromString( "0x0000000000000000000000000000000000000001" ); -const MAX_PROVING_PERIOD = BigInt.fromI32(240); -const CHALLENGE_WINDOW_SIZE = BigInt.fromI32(20); +const MAX_PROVING_PERIOD = ContractConstants.MaxProvingPeriod; +const CHALLENGE_WINDOW_SIZE = ContractConstants.ChallengeWindowSize; const SENDER_ADDRESS = Address.fromString( "0xa16081f360e3847006db660bae1c6d1b2e17ec2a" ); diff --git a/subgraph/utils/index.ts b/subgraph/utils/index.ts index d38b628..260a14b 100644 --- a/subgraph/utils/index.ts +++ b/subgraph/utils/index.ts @@ -1,15 +1,10 @@ -export const PDPVerifierAddress = "0x85e366Cf9DD2c0aE37E963d9556F5f4718d6417C"; +// Import network-specific contract constants from generated constants +export { ContractConstants } from "../src/generated/constants"; export const NumChallenges = 5; export const LeafSize = 32; -// Proving period configuration per network. -// calibration: MaxProvingPeriod=240 -// mainnet: MaxProvingPeriod=2880 -export const MaxProvingPeriod = 240; -export const ChallengeWindowSize = 20; - // Maximum ProvingWindow entities created per NextProvingPeriod event. // Prevents OOM when a stale dataset resumes after many skipped periods. export const MaxProvingWindowsPerEvent = 50;