Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@
"@docusaurus/tsconfig": "3.9.2",
"@docusaurus/types": "3.9.2",
"@tailwindcss/postcss": "^4.1.18",
"@yellow-org/contracts": "^1.0.1",
"autoprefixer": "^10.4.24",
"postcss": "^8.5.6",
"tailwindcss": "^4.1.17",
Expand Down
111 changes: 100 additions & 11 deletions scripts/sync-contracts-docs.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
* into docs/contracts/ with Docusaurus-compatible frontmatter
* and category metadata.
*
* Generates the Deployed Addresses page from @yellow-org/contracts.
*
* Usage: node scripts/sync-contracts-docs.js
*
* Safe to re-run — it wipes docs/contracts/ and rebuilds from source.
Expand All @@ -14,6 +16,32 @@ const ROOT = path.resolve(__dirname, '..');
const SRC = path.join(ROOT, 'vendors', 'yellow', 'docs');
const DEST = path.join(ROOT, 'docs', 'contracts');

// ---------------------------------------------------------------------------
// On-chain addresses from @yellow-org/contracts
// ---------------------------------------------------------------------------

let addresses;
try {
addresses = require('@yellow-org/contracts').addresses;
} catch {
addresses = null;
}
Comment on lines +23 to +28
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

find . -name "package*.json" -type f | head -20

Repository: layer-3/docs

Length of output: 90


🏁 Script executed:

rg "@yellow-org/contracts" --type json

Repository: layer-3/docs

Length of output: 340


🏁 Script executed:

git ls-files scripts/ | head -20

Repository: layer-3/docs

Length of output: 165


🏁 Script executed:

cat -n scripts/sync-contracts-docs.js | head -50

Repository: layer-3/docs

Length of output: 1947


🌐 Web query:

@yellow-org/contracts npm module exports addresses CommonJS

💡 Result:

If @yellow-org/contracts is published as ESM-only (common for “contracts artifacts” packages), then CommonJS require() won’t give you named exports the way you expect.

How to consume it from CommonJS

Option A (recommended): use dynamic import() from CJS

// CommonJS file (.cjs or "type": "commonjs")
const { addresses } = await import('@yellow-org/contracts');
// or whatever export name the package uses
console.log(addresses);

Node can load ESM via import(), and when importing CommonJS from ESM (or vice‑versa), interop often goes through a default export wrapper. (mirrors.aliyun.com)

Option B: require() and look for .default

const pkg = require('@yellow-org/contracts');
const addresses = pkg.addresses ?? pkg.default?.addresses ?? pkg.default;

This is needed when Node represents the other module system via a namespace object whose main value is on default. (mirrors.aliyun.com)

Option C: if you control the package, add conditional exports
In the package’s package.json, publish both entry points:

{
  "exports": {
    ".": {
      "import": "./dist/index.mjs",
      "require": "./dist/index.cjs"
    }
  }
}

This is the standard way to support both import and require. (nodejs.org)

If require() throws “ERR_REQUIRE_ESM”

That means it’s ESM-only; use Option A (dynamic import()), or ship a CJS build + conditional exports (Option C). Node only supports requiring ESM in limited/experimental ways. (mirrors.aliyun.com)

Citations:


🏁 Script executed:

cat -n package-lock.json | grep -A 20 "@yellow-org/contracts"

Repository: layer-3/docs

Length of output: 2139


🏁 Script executed:

rg "@yellow-org/contracts" --type js -A 3 -B 3

Repository: layer-3/docs

Length of output: 3341


🏁 Script executed:

cat -n scripts/sync-contracts-docs.js | tail -n +20 | head -n 50

Repository: layer-3/docs

Length of output: 1805


Avoid broad catch blocks—only catch missing module errors.

This catches every runtime failure and silently degrades to addresses = null, which masks real module issues (broken exports, syntax errors, incompatible formats). Catch MODULE_NOT_FOUND specifically and rethrow unexpected errors so actual problems surface during development.

Proposed fix
 let addresses;
 try {
   addresses = require('@yellow-org/contracts').addresses;
-} catch {
-  addresses = null;
+} catch (err) {
+  if (err && err.code === 'MODULE_NOT_FOUND') {
+    addresses = null;
+  } else {
+    throw err;
+  }
 }
📝 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
let addresses;
try {
addresses = require('@yellow-org/contracts').addresses;
} catch {
addresses = null;
}
let addresses;
try {
addresses = require('@yellow-org/contracts').addresses;
} catch (err) {
if (err && err.code === 'MODULE_NOT_FOUND') {
addresses = null;
} else {
throw err;
}
}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@scripts/sync-contracts-docs.js` around lines 23 - 28, The try/catch around
require('@yellow-org/contracts').addresses is too broad and hides real errors;
update the try/catch in scripts/sync-contracts-docs.js that assigns addresses so
it only swallows a MODULE_NOT_FOUND error and rethrows any other
exceptions—i.e., after calling require('@yellow-org/contracts') (the expression
used to set addresses), inspect the caught error.code and if it equals
'MODULE_NOT_FOUND' set addresses = null, otherwise throw the error so issues
like syntax or export problems surface.


const CHAINS = {
1: { name: 'Ethereum Mainnet', explorer: 'https://etherscan.io/address' },
11155111: { name: 'Sepolia Testnet', explorer: 'https://sepolia.etherscan.io/address' },
};

const ADDRESS_LABELS = {
yellowToken: 'YellowToken',
nodeRegistry: 'NodeRegistry',
appRegistry: 'AppRegistry',
governor: 'YellowGovernor',
timelock: 'TimelockController',
treasury: 'Treasury',
faucet: 'Faucet',
};

// ---------------------------------------------------------------------------
// Helpers
// ---------------------------------------------------------------------------
Expand Down Expand Up @@ -69,7 +97,6 @@ function copyWithFrontmatter(srcFile, destFile, { title, description, sidebarPos
content = content.replace(/^<!-- AUTO-GENERATED.*?-->\n*/m, '');

// Escape curly braces in prose so MDX doesn't treat them as JSX expressions.
// Only escape {word} patterns outside of code blocks/fences.
content = escapeCurlyBracesOutsideCode(content);

const frontmatter = [
Expand Down Expand Up @@ -102,6 +129,66 @@ function writeCategory(dir, { label, position, link }) {
fs.writeFileSync(path.join(dir, '_category_.json'), JSON.stringify(data, null, 2) + '\n');
}

// ---------------------------------------------------------------------------
// Address page generator
// ---------------------------------------------------------------------------

function generateAddressesPage() {
const lines = [
'---',
'title: "Deployed Addresses"',
'description: "Mainnet and testnet contract addresses for Yellow Network."',
'sidebar_position: 2',
'displayed_sidebar: contractsSidebar',
'---',
'',
'',
'# Deployed Addresses',
'',
];

if (!addresses) {
lines.push('> Install `@yellow-org/contracts` and re-run `npm run sync:contracts` to populate addresses.', '');
return lines.join('\n');
}

for (const [chainIdStr, addrs] of Object.entries(addresses)) {
const chainId = Number(chainIdStr);
const chain = CHAINS[chainId];
if (!chain) continue;

Comment on lines +155 to +159
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Unknown chain IDs are silently dropped from docs.

if (!chain) continue hides new deployments when the package adds chains not yet mapped in CHAINS. Render them with a fallback label instead of skipping.

Proposed fix
-    const chain = CHAINS[chainId];
-    if (!chain) continue;
+    const chain = CHAINS[chainId] || { name: `Chain ${chainId}`, explorer: null };
@@
-      if (addr) {
-        lines.push(`| ${label} | [\`${addr}\`](${chain.explorer}/${addr}) |`);
+      if (addr) {
+        const rendered = chain.explorer ? `[\`${addr}\`](${chain.explorer}/${addr})` : `\`${addr}\``;
+        lines.push(`| ${label} | ${rendered} |`);
       } else {
         lines.push(`| ${label} | — |`);
       }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@scripts/sync-contracts-docs.js` around lines 155 - 159, The loop over
Object.entries(addresses) currently drops unknown chain IDs with if (!chain)
continue; instead create a fallback chain object so unknown chains are rendered
rather than skipped: when CHAINS[chainId] is falsy, set a fallback like { id:
chainId, name: `chain-${chainId}` } (or a descriptive label) and use that
fallback for subsequent rendering logic (replace usages of chain with this
fallbackChain variable); ensure any downstream properties accessed (e.g.,
chain.name or chain.id) are read from the fallback so new deployments appear in
the docs.

lines.push(`## ${chain.name} (Chain ID: ${chainId})`, '');
lines.push('| Contract | Address |', '|---|---|');

for (const [key, label] of Object.entries(ADDRESS_LABELS)) {
const addr = addrs[key];
if (addr) {
lines.push(`| ${label} | [\`${addr}\`](${chain.explorer}/${addr}) |`);
} else {
lines.push(`| ${label} | — |`);
}
}
lines.push('');
}

lines.push(
'## Using in Code',
'',
'```ts',
'import { addresses } from "@yellow-org/contracts";',
'',
'// Mainnet',
'addresses[1].yellowToken;',
'',
'// Sepolia',
'addresses[11155111].faucet;',
'```',
'',
);

return lines.join('\n');
}

// ---------------------------------------------------------------------------
// Document mapping
// ---------------------------------------------------------------------------
Expand All @@ -114,12 +201,7 @@ const DOCS = {
description: 'Overview of Yellow Network smart contracts, governance, and on-chain infrastructure.',
sidebarPosition: 1,
},
addresses: {
src: 'operations/addresses.md',
title: 'Deployed Addresses',
description: 'Mainnet and testnet contract addresses for Yellow Network.',
sidebarPosition: 2,
},
// 'addresses' is generated from @yellow-org/contracts — not copied from vendor
faq: {
src: 'FAQ.md',
title: 'FAQ',
Expand Down Expand Up @@ -290,7 +372,16 @@ function main() {
});
}

// Copy and transform each document
// Generate addresses page from @yellow-org/contracts
const addressesPage = generateAddressesPage();
fs.writeFileSync(path.join(DEST, 'addresses.md'), addressesPage);
if (addresses) {
console.log(' generated addresses.md (from @yellow-org/contracts)');
} else {
console.warn(' generated addresses.md (WARNING: @yellow-org/contracts not installed)');
}

// Copy and transform each document from vendor
let count = 0;
const missing = [];

Expand All @@ -315,7 +406,7 @@ function main() {
}
}

console.log(`\nSynced ${count} docs into docs/contracts/`);
console.log(`\nSynced ${count} vendor docs + 1 generated into docs/contracts/`);
console.log('\nStructure:');

// Print tree
Expand All @@ -331,9 +422,7 @@ function main() {
const isLast = i === entries.length - 1;
const connector = isLast ? '└── ' : '├── ';
const full = path.join(dir, entry.name);

if (entry.name === '_category_.json') return; // skip noise

console.log(`${prefix}${connector}${entry.name}`);
if (entry.isDirectory()) {
printTree(full, prefix + (isLast ? ' ' : '│ '));
Expand Down