Skip to content
Merged
Show file tree
Hide file tree
Changes from 19 commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
4c5be02
feat(toolshed/interfaces): add recurring collector helpers and deploy…
RembrandtK May 11, 2026
283575c
feat(issuance): MockRewardsEligibilityOracle test mock
RembrandtK May 11, 2026
92e1d62
refactor(address-book): consolidate publish source list to one place
RembrandtK Apr 29, 2026
47bce26
chore: update arbitrumSepolia addresses and deployment metadata
RembrandtK May 11, 2026
0833d95
docs(address-book): publishing guide and 1.2.0 changelog
RembrandtK May 11, 2026
2e7319d
chore: bump interfaces 0.7.1-dips.0 / toolshed 1.2.1-dips.2 for dips …
RembrandtK May 6, 2026
324b04e
fix: root tooling compat (rocketh patch, hardhat-waffle deps, ethersc…
RembrandtK May 11, 2026
dc8f8f5
refactor(data-edge): upgrade to ethers v6 and @nomicfoundation plugins
RembrandtK Apr 10, 2026
45fb80e
feat(subgraph-service): wire RecurringCollector parameter and StakeCl…
RembrandtK May 11, 2026
854a435
fix: correct localNetwork addresses (governor / pauseGuardian / SAO)
RembrandtK Apr 29, 2026
4dda611
feat(deployment): add GIP-0088 deployment infrastructure
RembrandtK May 11, 2026
1619599
docs: REO testing plans and rewards behaviour documentation
RembrandtK Apr 10, 2026
fc57994
docs(contracts): capture pending updates as sidecar .todo.md files
RembrandtK May 11, 2026
6a64d07
chore(lint): include json5 files in lint:json glob
RembrandtK May 11, 2026
51b2208
refactor(horizon): drive governor from config parameter in deploy mod…
RembrandtK May 11, 2026
c1079ff
chore(lint): bump solhint catalog ^6.0.3 → ^6.2.1
RembrandtK May 11, 2026
640f91b
docs(issuance): capture pending NatSpec updates and refine test docst…
RembrandtK May 12, 2026
cf055bd
docs(audit): drop intermediate PDFs and per-finding markdown
RembrandtK May 12, 2026
c8101b8
docs(audit): prefix issuance audit PDFs with issue date and unnest fr…
RembrandtK May 12, 2026
56ab1cf
feat(build): publish workspace as ghcr.io/graphprotocol/contracts image
RembrandtK May 13, 2026
fd15b17
fix(deployment): address PR1338 reviewer feedback
RembrandtK May 13, 2026
2a45144
refactor(deployment): centralize address-book routing
RembrandtK May 13, 2026
7d2fea2
fix(deployment): record proxyDeployment metadata at deploy time
RembrandtK May 13, 2026
c881da2
refactor(deployment): canonical computeArtifactBytecodeHash helper
RembrandtK May 13, 2026
9413793
refactor(deployment): drop unused setPendingImplementation
RembrandtK May 13, 2026
85e8289
refactor(deployment): unify block-number + artifact-load helpers
RembrandtK May 13, 2026
fcd9094
chore: drop personal/external references from comments and docs
RembrandtK May 13, 2026
1237b95
chore: exclude forge core dumps from docker build context
RembrandtK May 13, 2026
67c3428
chore: bump publishable package versions
RembrandtK May 13, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
175 changes: 175 additions & 0 deletions docs/RewardsBehaviourChanges.md

Large diffs are not rendered by default.

15 changes: 12 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
"lint:sol": "pnpm -r run lint:sol; prettier -w --cache --log-level warn 'packages/**/*.sol'; pnpm todo",
"lint:forge": "pnpm -r run lint:forge",
"lint:md": "markdownlint --fix --ignore-path .gitignore 'packages/**/*.md' 'docs/**/*.md' '*.md'; prettier -w --cache --log-level warn 'packages/**/*.md' 'docs/**/*.md' '*.md'",
"lint:json": "prettier -w --cache --log-level warn 'packages/**/*.json' '.changeset/**/*.json' '*.json'",
"lint:json": "prettier -w --cache --log-level warn 'packages/**/*.{json,json5}' '.changeset/**/*.json' '*.{json,json5}'",
"lint:yaml": "npx yaml-lint .github/**/*.{yml,yaml} packages/contracts/task/config/*.yml; prettier -w --cache --log-level warn 'packages/**/*.{yml,yaml}' '.github/**/*.{yml,yaml}'",
"test": "pnpm build && pnpm -r run test:self",
"test:prod": "FOUNDRY_PROFILE=prod pnpm test",
Expand Down Expand Up @@ -56,8 +56,17 @@
"overrides": {
"@types/node": "^20.17.50"
},
"packageExtensions": {
"@nomiclabs/hardhat-waffle@*": {
"dependencies": {
"@ethereum-waffle/chai": "*",
"@ethereum-waffle/provider": "*"
}
}
},
"patchedDependencies": {
"typechain@8.3.2": "patches/typechain@8.3.2.patch"
"typechain@8.3.2": "patches/typechain@8.3.2.patch",
"rocketh@0.17.13": "patches/rocketh@0.17.13.patch"
}
},
"lint-staged": {
Expand All @@ -73,7 +82,7 @@
"markdownlint --fix",
"prettier -w --cache --log-level warn"
],
"*.json": "prettier -w --cache --log-level warn",
"*.{json,json5}": "prettier -w --cache --log-level warn",
"*.{yml,yaml}": [
"npx yamllint",
"prettier -w --cache --log-level warn"
Expand Down
6 changes: 6 additions & 0 deletions packages/address-book/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
# @graphprotocol/address-book

## 1.2.0

### Minor Changes

- Upgraded Rewards Manager and Subgraph Service with Rewards Eligibility Oracle and rewards reclaiming.

## 1.1.0

### Minor Changes
Expand Down
108 changes: 108 additions & 0 deletions packages/address-book/docs/PublishingGuide.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
# Publishing @graphprotocol/address-book

Step-by-step guide for releasing a new version of the address-book package and deploying it to the network monitor.

## Prerequisites

- npm publish access for the `@graphprotocol` scope
- Write access to the [network-monitor](https://github.com/edgeandnode/network-monitor) repo
- Ability to trigger GitHub Actions workflows in both repos

## Step 1: Update Address Files

Update the source address files in the contracts monorepo. These live in:

- `packages/horizon/addresses.json`
- `packages/subgraph-service/addresses.json`
- `packages/issuance/addresses.json`

The address-book package symlinks to these files during development, so changes here are automatically reflected locally.

## Step 2: Create a Changeset

From the monorepo root:

```bash
pnpm changeset
```

- Select `@graphprotocol/address-book`
- Choose the bump type (patch/minor/major)
- Describe what changed (e.g., "update arbitrumSepolia addresses after deployment")

## Step 3: Version the Package

```bash
pnpm changeset version
```

This consumes the changeset, bumps the version in `packages/address-book/package.json`, and updates `CHANGELOG.md`.

## Step 4: Commit and Push

```bash
git add .
git commit -m "chore: release @graphprotocol/address-book vX.Y.Z"
git push
```

## Step 5: Publish to npm

1. Go to the contracts monorepo → Actions → "Publish package to NPM"
2. Select `address-book` as the package
3. Set tag to `latest` (or a pre-release tag)
4. Run workflow

The workflow automatically:

- Publishes to npm (symlinks are converted to real files via `prepublishOnly`)
- Creates and pushes a git tag (`@graphprotocol/address-book@X.Y.Z`)

## Step 6: Verify on npm

```bash
npm view @graphprotocol/address-book version
```

Confirm the new version is live.

## Step 7: Update the Network Monitor

In the [network-monitor](https://github.com/edgeandnode/network-monitor) repo:

1. Update `package.json` to reference the new version:

```json
"@graphprotocol/address-book": "X.Y.Z",
```

2. Run `yarn` to update the lockfile
3. Commit and push

The network monitor imports addresses from:

- `@graphprotocol/address-book/horizon/addresses.json` (in `src/env.ts`)
- `@graphprotocol/address-book/subgraph-service/addresses.json` (in `src/env.ts`, `src/tests/contracts.ts`)

## Step 8: Deploy the Network Monitor

1. Go to the network-monitor repo → Actions → "Deployment"
2. Choose the target cluster:
- **`network`** → production (mainnet)
- **`testnet`** → testnet
3. Run workflow

This builds a Docker image, pushes it to `ghcr.io/edgeandnode/network-monitor`, and restarts the StatefulSet on GKE.

## Quick Reference

| Step | Action | Where |
| ---- | ------------------------------- | ----------------------------- |
| 1 | Update address files | contracts monorepo |
| 2 | `pnpm changeset` | contracts monorepo |
| 3 | `pnpm changeset version` | contracts monorepo |
| 4 | Commit + push | contracts monorepo |
| 5 | Publish to npm (auto-tags) | contracts monorepo GH Actions |
| 6 | Verify on npm | npmjs.com |
| 7 | Bump version in network-monitor | network-monitor repo |
| 8 | Deploy network monitor | network-monitor GH Actions |
6 changes: 2 additions & 4 deletions packages/address-book/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@graphprotocol/address-book",
"version": "1.1.0",
"version": "1.2.0",
"publishConfig": {
"access": "public"
},
Expand All @@ -13,9 +13,7 @@
"directory": "packages/address-book"
},
"exports": {
"./horizon/addresses.json": "./src/horizon/addresses.json",
"./issuance/addresses.json": "./src/issuance/addresses.json",
"./subgraph-service/addresses.json": "./src/subgraph-service/addresses.json"
"./*/addresses.json": "./src/*/addresses.json"
},
"files": [
"src/**/*.json",
Expand Down
69 changes: 27 additions & 42 deletions packages/address-book/scripts/copy-addresses-for-publish.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,67 +3,52 @@
/**
* Copy Addresses for Publishing
*
* This script copies the actual addresses.json files from horizon and subgraph-service
* packages to replace the symlinks before npm publish.
*
* Why we need this:
* - Development uses symlinks (committed to git) for convenience
* - npm publish doesn't include symlinks in the published package
* - We need actual files in the published package for consumers
*
* The postpublish script will restore the symlinks after publishing.
* Replaces the dev-time symlinks under src/<name>/addresses.json with real
* file copies before npm publish — npm does not include symlinks in the
* published tarball. restore-symlinks.js puts the symlinks back afterwards.
*/

const fs = require('fs')
const path = require('path')
const SOURCES = require('./sources')

const FILES_TO_COPY = [
{
source: '../../../horizon/addresses.json',
target: 'src/horizon/addresses.json',
},
{
source: '../../../issuance/addresses.json',
target: 'src/issuance/addresses.json',
},
{
source: '../../../subgraph-service/addresses.json',
target: 'src/subgraph-service/addresses.json',
},
]
const ROOT = path.resolve(__dirname, '..')
const SRC = path.join(ROOT, 'src')

function copyFileForPublish(source, target) {
const targetPath = path.resolve(__dirname, '..', target)
const sourcePath = path.resolve(path.dirname(targetPath), source)
function copyOne(name) {
const sourcePath = path.resolve(ROOT, '..', name, 'addresses.json')
const targetDir = path.join(SRC, name)
const targetPath = path.join(targetDir, 'addresses.json')

// Ensure source exists
if (!fs.existsSync(sourcePath)) {
console.error(`❌ Source file ${sourcePath} does not exist`)
process.exit(1)
}

// Remove existing symlink
if (fs.existsSync(targetPath)) {
fs.unlinkSync(targetPath)
}
fs.mkdirSync(targetDir, { recursive: true })
fs.rmSync(targetPath, { force: true })
fs.copyFileSync(sourcePath, targetPath)
console.log(`✅ Copied for publish: src/${name}/addresses.json`)
}

// Copy actual file
try {
fs.copyFileSync(sourcePath, targetPath)
console.log(`✅ Copied for publish: ${target} <- ${source}`)
} catch (error) {
console.error(`❌ Failed to copy ${source} to ${target}:`, error.message)
function checkDrift() {
const dirs = fs
.readdirSync(SRC)
.filter((d) => fs.statSync(path.join(SRC, d)).isDirectory())
.sort()
const expected = [...SOURCES].sort()
if (JSON.stringify(dirs) !== JSON.stringify(expected)) {
console.error(`❌ Drift between SOURCES and src/`)
console.error(` SOURCES: [${expected.join(', ')}]`)
console.error(` src/ : [${dirs.join(', ')}]`)
process.exit(1)
}
}

function main() {
console.log('📦 Copying address files for npm publish...')

for (const { source, target } of FILES_TO_COPY) {
copyFileForPublish(source, target)
}

for (const name of SOURCES) copyOne(name)
checkDrift()
console.log('✅ Address files copied for publish!')
}

Expand Down
52 changes: 15 additions & 37 deletions packages/address-book/scripts/restore-symlinks.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,54 +3,32 @@
/**
* Restore Symlinks After Publishing
*
* This script restores the symlinks after npm publish completes.
* The prepublishOnly script replaces symlinks with actual files for publishing,
* and this script puts the symlinks back for development.
* Restores the dev-time symlinks under src/<name>/addresses.json after
* npm publish. copy-addresses-for-publish.js replaces them with real files
* for the publish step; this puts them back.
*/

const fs = require('fs')
const path = require('path')
const SOURCES = require('./sources')

const SYMLINKS_TO_RESTORE = [
{
target: '../../../horizon/addresses.json',
link: 'src/horizon/addresses.json',
},
{
target: '../../../issuance/addresses.json',
link: 'src/issuance/addresses.json',
},
{
target: '../../../subgraph-service/addresses.json',
link: 'src/subgraph-service/addresses.json',
},
]
const ROOT = path.resolve(__dirname, '..')
const SRC = path.join(ROOT, 'src')

function restoreSymlink(target, link) {
const linkPath = path.resolve(__dirname, '..', link)
function restoreOne(name) {
const linkTarget = `../../../${name}/addresses.json`
const linkDir = path.join(SRC, name)
const linkPath = path.join(linkDir, 'addresses.json')

// Remove the copied file
if (fs.existsSync(linkPath)) {
fs.unlinkSync(linkPath)
}

// Restore symlink
try {
fs.symlinkSync(target, linkPath)
console.log(`✅ Restored symlink: ${link} -> ${target}`)
} catch (error) {
console.error(`❌ Failed to restore symlink ${link}:`, error.message)
process.exit(1)
}
fs.mkdirSync(linkDir, { recursive: true })
fs.rmSync(linkPath, { force: true })
fs.symlinkSync(linkTarget, linkPath)
console.log(`✅ Restored symlink: src/${name}/addresses.json -> ${linkTarget}`)
}

function main() {
console.log('🔗 Restoring symlinks after publish...')

for (const { target, link } of SYMLINKS_TO_RESTORE) {
restoreSymlink(target, link)
}

for (const name of SOURCES) restoreOne(name)
console.log('✅ Symlinks restored!')
}

Expand Down
4 changes: 4 additions & 0 deletions packages/address-book/scripts/sources.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
// Source packages exported from @graphprotocol/address-book.
// Each name corresponds to packages/<name>/addresses.json (source of truth)
// and packages/address-book/src/<name>/addresses.json (publish symlink).
module.exports = ['horizon', 'issuance', 'subgraph-service']
1 change: 1 addition & 0 deletions packages/address-book/src/issuance/addresses.json
2 changes: 1 addition & 1 deletion packages/contracts/.solhint.json
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
{
"extends": ["solhint:recommended", "./../../.solhint.json"]
"extends": "./../../.solhint.json"
}
3 changes: 2 additions & 1 deletion packages/contracts/hardhat.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,8 @@ const config: HardhatUserConfig = {
etherscan: {
// Use ARBISCAN_API_KEY for Arbitrum networks
// For mainnet Ethereum, use ETHERSCAN_API_KEY
apiKey: vars.has('ARBISCAN_API_KEY') ? vars.get('ARBISCAN_API_KEY') : '',
// Check both keystore (vars) and environment variable
apiKey: vars.has('ARBISCAN_API_KEY') ? vars.get('ARBISCAN_API_KEY') : (process.env.ARBISCAN_API_KEY ?? ''),
},
sourcify: {
enabled: false,
Expand Down
2 changes: 1 addition & 1 deletion packages/data-edge/.solhint.json
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
{
"extends": ["solhint:recommended", "./../../.solhint.json"]
"extends": "./../../.solhint.json"
}
Loading