-
Notifications
You must be signed in to change notification settings - Fork 258
feat: serve protocols data via npm #399
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
Open
QEDK
wants to merge
5
commits into
main
Choose a base branch
from
feat/npm-package
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
Show all changes
5 commits
Select commit
Hold shift + click to select a range
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Some comments aren't visible on the classic Files Changed page.
There are no files selected for viewing
This file was deleted.
Oops, something went wrong.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,119 @@ | ||
| # This workflow regenerates the protocol aggregates (protocols-*.csv/json), | ||
| # commits them back to the branch, and then publishes the data as an npm package. | ||
| # | ||
| # Publishing uses npm Trusted Publishing (OIDC), renaming this workflow file | ||
| # breaks the trust relationship. | ||
|
|
||
| name: generate and publish | ||
|
|
||
| on: | ||
| push: | ||
| branches: [ main, master ] | ||
|
|
||
| # Serialize runs so two pushes can't race on the registry | ||
| concurrency: | ||
| group: generate-and-publish | ||
| cancel-in-progress: false | ||
|
|
||
| jobs: | ||
| generate-and-publish: | ||
| runs-on: ubuntu-latest | ||
|
|
||
| # Pushes made with the default GITHUB_TOKEN (like our auto-commit below) | ||
| # don't re-trigger workflows | ||
| if: github.event.head_commit.message != 'Update protocols CSV and JSON files' | ||
|
|
||
| permissions: | ||
| # Give the default GITHUB_TOKEN write permission to commit and push the | ||
| # added or changed files to the repository. | ||
| contents: write | ||
| # Required for npm provenance: lets the job mint a short-lived OIDC token | ||
| # that Sigstore uses to sign the release. | ||
| id-token: write | ||
|
|
||
| steps: | ||
| - name: Checkout code | ||
| uses: actions/checkout@v6 | ||
|
|
||
| - name: Set up Python | ||
| uses: actions/setup-python@v6 | ||
| with: | ||
| python-version: '3.14' | ||
|
|
||
| - name: Install uv | ||
| uses: astral-sh/setup-uv@v8.1.0 | ||
| with: | ||
| enable-cache: true | ||
|
|
||
| - name: Install dependencies | ||
| run: uv sync | ||
|
|
||
| - name: Run script (testnet) | ||
| run: | | ||
| source .venv/bin/activate | ||
| python scripts/ProtocolsTable.py --network testnet | ||
|
|
||
| - name: Run script (mainnet) | ||
| run: | | ||
| source .venv/bin/activate | ||
| python scripts/ProtocolsTable.py --network mainnet | ||
|
|
||
| # Commit all changed files back to the repository. The commit sits on | ||
| # top of the SHA that triggered this run | ||
| - uses: stefanzweifel/git-auto-commit-action@v7 | ||
| with: | ||
| commit_message: "Update protocols CSV and JSON files" | ||
| file_pattern: "protocols-*.csv protocols-*.json" | ||
|
|
||
| - name: Set up Node.js | ||
| uses: actions/setup-node@v6 | ||
| with: | ||
| node-version: 24 | ||
| registry-url: 'https://registry.npmjs.org' | ||
|
|
||
| - name: Set version from run number | ||
| run: | | ||
| # Keep major.minor from package.json, use the run number as the patch | ||
| # so every push to main produces a unique, monotonic release. | ||
| BASE=$(node -p "require('./package.json').version.split('.').slice(0, 2).join('.')") | ||
| VERSION="${BASE}.${GITHUB_RUN_NUMBER}" | ||
| echo "Publishing version ${VERSION}" | ||
| npm version "${VERSION}" --no-git-tag-version --allow-same-version | ||
|
|
||
| - name: Build npm package | ||
| run: npm run build | ||
|
|
||
| - name: Verify bundled files and casing | ||
| working-directory: dist | ||
| run: | | ||
| npm pack --dry-run --json > pack.json | ||
| node -e ' | ||
| const fs = require("fs"), path = require("path"); | ||
| const packed = new Set(JSON.parse(fs.readFileSync("pack.json", "utf8"))[0].files.map(f => f.path)); | ||
| const walk = d => fs.readdirSync(d, { withFileTypes: true }) | ||
| .flatMap(e => e.isDirectory() ? walk(path.join(d, e.name)) : [path.join(d, e.name)]); | ||
| const expected = [ | ||
| "mainnet.json", "testnet.json", "mainnet.csv", "testnet.csv", "categories.json", | ||
| ...walk("mainnet"), ...walk("testnet"), | ||
| ].filter(p => /\.(json|jsonc|csv)$/.test(p)); | ||
| const missing = expected.filter(p => !packed.has(p)); | ||
| if (missing.length) { | ||
| console.error("Files missing from the package (often a casing mismatch):\n " + missing.join("\n ")); | ||
| process.exit(1); | ||
| } | ||
| // Guard against case-only collisions that break case-insensitive filesystems. | ||
| const seen = new Map(); | ||
| for (const p of packed) { | ||
| const key = p.toLowerCase(); | ||
| if (seen.has(key) && seen.get(key) !== p) { | ||
| console.error(`Case collision: "${seen.get(key)}" vs "${p}"`); | ||
| process.exit(1); | ||
| } | ||
| seen.set(key, p); | ||
| } | ||
| console.log(`Verified ${expected.length} data files bundled.`); | ||
| ' | ||
|
|
||
| - name: Publish to npm | ||
| working-directory: dist | ||
| run: npm publish |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,34 @@ | ||
| /** | ||
| * A category::sub-category pair, e.g. "DeFi::DEX". | ||
| */ | ||
| export type Category = string; | ||
|
|
||
| /** | ||
| * A single protocol entry, keyed by its slug in the aggregate maps. | ||
| */ | ||
| export interface Protocol { | ||
| /** Display name of the protocol. */ | ||
| name: string; | ||
| /** Human-readable description. */ | ||
| description: string; | ||
| /** Whether the protocol is live, when present in the source data. */ | ||
| live?: boolean; | ||
| /** Category::sub-category pairs, primary first. */ | ||
| categories: Category[]; | ||
| /** Mapping of contract name -> address. */ | ||
| addresses: Record<string, string>; | ||
| /** Mapping of link type (project, twitter, github, docs, ...) -> URL. */ | ||
| links: Record<string, string>; | ||
| } | ||
|
|
||
| /** Map of protocol slug -> protocol entry. */ | ||
| export type ProtocolMap = Record<string, Protocol>; | ||
|
|
||
| /** Mainnet protocols, keyed by slug. */ | ||
| export declare const mainnet: ProtocolMap; | ||
|
|
||
| /** Testnet protocols, keyed by slug. */ | ||
| export declare const testnet: ProtocolMap; | ||
|
|
||
| /** The full list of valid category::sub-category values. */ | ||
| export declare const categories: { categories: Category[] }; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,30 @@ | ||
| 'use strict'; | ||
|
|
||
| /** | ||
| * Aggregated Monad protocol data, bundled from the monad-crypto/protocols | ||
| * repository. The individual per-protocol files are also shipped in this | ||
| * package and can be imported directly, e.g.: | ||
| * | ||
| * const protocols = require('@monad-crypto/protocols'); | ||
| * protocols.mainnet['0x']; | ||
| * | ||
| * // or a single raw file (per-protocol casing is preserved): | ||
| * const kuru = require('@monad-crypto/protocols/mainnet/kuru.jsonc'); | ||
| * | ||
| * CSV summaries are shipped as files too and can be resolved via: | ||
| * require.resolve('@monad-crypto/protocols/mainnet.csv'); | ||
| * | ||
| * NOTE: the aggregate files referenced below are produced at bundle time by | ||
| * scripts/build-npm.mjs (the in-repo sources are protocols-{mainnet,testnet}.json). | ||
| * Run `npm run build` before requiring this file outside the published package. | ||
| */ | ||
|
|
||
| const mainnet = require('./mainnet.json'); | ||
| const testnet = require('./testnet.json'); | ||
| const categories = require('./categories.json'); | ||
|
|
||
| module.exports = { | ||
| mainnet, | ||
| testnet, | ||
| categories, | ||
| }; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,57 @@ | ||
| { | ||
| "name": "@monad-crypto/protocols", | ||
| "version": "0.1.0", | ||
| "description": "Contract addresses, links, categories, and metadata for protocols on the Monad network.", | ||
| "homepage": "https://github.com/monad-crypto/protocols#readme", | ||
| "repository": { | ||
| "type": "git", | ||
| "url": "git+https://github.com/monad-crypto/protocols.git" | ||
| }, | ||
| "bugs": { | ||
| "url": "https://github.com/monad-crypto/protocols/issues" | ||
| }, | ||
| "main": "index.js", | ||
| "types": "index.d.ts", | ||
| "exports": { | ||
| ".": { | ||
| "types": "./index.d.ts", | ||
| "default": "./index.js" | ||
| }, | ||
| "./categories.json": "./categories.json", | ||
| "./mainnet.json": "./mainnet.json", | ||
| "./testnet.json": "./testnet.json", | ||
| "./mainnet.csv": "./mainnet.csv", | ||
| "./testnet.csv": "./testnet.csv", | ||
| "./mainnet/*": "./mainnet/*", | ||
| "./testnet/*": "./testnet/*", | ||
| "./package.json": "./package.json" | ||
| }, | ||
| "files": [ | ||
| "index.js", | ||
| "index.d.ts", | ||
| "categories.json", | ||
| "mainnet.json", | ||
| "testnet.json", | ||
| "mainnet.csv", | ||
| "testnet.csv", | ||
| "mainnet", | ||
| "testnet" | ||
| ], | ||
| "scripts": { | ||
| "build": "node scripts/build-npm.mjs" | ||
| }, | ||
| "keywords": [ | ||
| "monad", | ||
| "protocols", | ||
| "contracts", | ||
| "addresses", | ||
| "web3", | ||
| "defi", | ||
| "token-list" | ||
| ], | ||
| "publishConfig": { | ||
| "access": "public", | ||
| "provenance": true, | ||
| "registry": "https://registry.npmjs.org" | ||
| } | ||
| } | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,40 @@ | ||
| // Assembles the publishable npm package under dist/. | ||
|
|
||
| import { cpSync, mkdirSync, readFileSync, rmSync, writeFileSync } from 'node:fs'; | ||
| import { dirname, join } from 'node:path'; | ||
| import { fileURLToPath } from 'node:url'; | ||
|
|
||
| const root = join(dirname(fileURLToPath(import.meta.url)), '..'); | ||
| const dist = join(root, 'dist'); | ||
|
|
||
| rmSync(dist, { recursive: true, force: true }); | ||
| mkdirSync(dist, { recursive: true }); | ||
|
|
||
| // Generated aggregates -> JS-package-friendly names | ||
| const aggregates = { | ||
| 'protocols-mainnet.json': 'mainnet.json', | ||
| 'protocols-testnet.json': 'testnet.json', | ||
| 'protocols-mainnet.csv': 'mainnet.csv', | ||
| 'protocols-testnet.csv': 'testnet.csv', | ||
| }; | ||
| for (const [src, dest] of Object.entries(aggregates)) { | ||
| cpSync(join(root, src), join(dist, dest)); | ||
| } | ||
|
|
||
| // Files shipped under their existing names. | ||
| for (const f of ['categories.json', 'index.js', 'index.d.ts', 'README.md']) { | ||
| cpSync(join(root, f), join(dist, f)); | ||
| } | ||
|
|
||
| // The published package is pre-built data: drop the scripts field so its | ||
| // metadata doesn't reference build tooling that isn't shipped. | ||
| const pkg = JSON.parse(readFileSync(join(root, 'package.json'), 'utf8')); | ||
| delete pkg.scripts; | ||
| writeFileSync(join(dist, 'package.json'), JSON.stringify(pkg, null, 2) + '\n'); | ||
|
|
||
| // Per-protocol directories, copied verbatim | ||
| for (const dir of ['mainnet', 'testnet']) { | ||
| cpSync(join(root, dir), join(dist, dir), { recursive: true }); | ||
| } | ||
|
|
||
| console.log('Built dist/ npm package'); |
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.