Skip to content

chore: convert matic.js to pnpm monorepo#463

Open
MaximusHaximus wants to merge 4 commits intomasterfrom
chore/monorepo
Open

chore: convert matic.js to pnpm monorepo#463
MaximusHaximus wants to merge 4 commits intomasterfrom
chore/monorepo

Conversation

@MaximusHaximus
Copy link
Copy Markdown
Contributor

@MaximusHaximus MaximusHaximus commented Mar 29, 2026

Summary

Converts `0xPolygon/matic.js` from a single-package npm repo to a pnpm monorepo, bringing it up to Polygon Apps Team standards. This is the foundation PR — subsequent PRs will add the `maticjs-viem` plugin and migrate the standalone `maticjs-web3`/`maticjs-ethers` plugin repos into this workspace.

See `PLAN.md` at the repo root for the full migration roadmap.

Pre-release

A beta snapshot is available for testing: `@maticnetwork/maticjs@3.9.8-beta.1`

npm install @maticnetwork/maticjs@3.9.8-beta.1

Changes

Monorepo structure

  • Move `@maticnetwork/maticjs` source into `packages/maticjs/`
  • Add pnpm workspace, `.npmrc`, `.changeset/config.json` (baseBranch: master)
  • Add `publishConfig.access: public` and `repository.directory` to `packages/maticjs/package.json` for trusted publishing
  • Switch from npm to pnpm; remove `package-lock.json`
  • Upgrade Node from v11.1.0 → 24 in `.nvmrc`

Tooling

  • Replace dead tslint with ESLint + `@polygonlabs/apps-team-lint@2.0.0`; fix all lint errors (0 errors, 67 advisory `no-explicit-any` warnings in public plugin interfaces)
  • Add `commitlint.config.js` (conventional commits) and `markdownlint-cli2@^0.21.0`; fix all markdownlint violations
  • Add Husky hooks: lint-staged pre-commit, commitlint commit-msg, changeset pre-push check

Tests

  • Delete broken nested test project (`test/package.json`, jest@27, npm link)
  • Migrate `specs/index.ts` → `packages/maticjs/tests/map-promise.test.ts` with vitest (7 passing unit tests, no network required)
  • Move manual integration scripts (debug.js, ether.js) to `manual/` at repo root

Repo organisation

  • Move `examples/` to repo root; update README for pnpm-free standalone usage
  • Fix root `README.md` (wrong org, npm commands, outdated structure)

GitHub Actions

  • Delete legacy `ci.yml` (npm-based) and `github_doc_deploy.yml` (dead since 2022)
  • Add team-standard workflow set as local copies (public repo — cannot call private `apps-team-workflows` directly):
    • `ci-trigger.yml` — lint/typecheck/test on Node 24, plus build matrix across 18.x/20.x/22.x/24.x
    • `changeset-check-trigger.yml` + `changeset-check.yml` + `.github/actions/upsert-changeset-comment/`
    • `npm-release-trigger.yml` + `npm-release.yml` — also handles snapshot releases via `workflow_dispatch`
    • `claude-code-review-trigger.yml` + `claude-code-review.yml`
    • `claude-trigger.yml` + `claude.yml`

What didn't change

  • No source code changes to `packages/maticjs/src/` beyond mechanical lint fixes
  • `@maticnetwork/maticjs` npm package entry points unchanged — existing consumers unaffected
  • TypeScript target, webpack build, and published dist artefact identical to pre-migration

Test plan

  • `pnpm install` — clean install with no peer dep warnings
  • `pnpm run lint` — 0 errors
  • `pnpm run typecheck` — clean
  • `pnpm run build` — all 6 webpack targets pass
  • `pnpm --filter @maticnetwork/maticjs run test` — 7/7 vitest tests pass
  • CI passes on this PR

- Move src/, test/, webpack.config.js, build_helper/, examples/ into packages/maticjs/
- Add root pnpm-workspace.yaml, .npmrc, package.json (private, devDeps only)
- Add .changeset/config.json (baseBranch: master)
- Add .husky/ hooks (lint-staged, commitlint, changeset pre-push check)
- Add .prettierrc.json, .markdownlint-cli2.jsonc, .lintstagedrc.js from team template
- Add .github/CODEOWNERS
- Add MIGRATION.md scaffolds at root and packages/maticjs/
- Update .nvmrc to Node 24
- Replace old tsconfig.json with monorepo root config (noEmit, project references)
- Add packages/maticjs/tsconfig.json (erasableSyntaxOnly: false, verbatimModuleSyntax: false)
- Add packages/maticjs/package.json with publishConfig, repository.directory, explicit deps
- Remove package-lock.json (replaced by pnpm-lock.yaml)
- Remove .prettierrc (replaced by .prettierrc.json), .eslintignore, tslint.json
- Add @ethereumjs/common and safe-buffer as explicit deps (used directly in source
  but only transitive under npm; pnpm strict isolation requires them declared)
- TypeScript upgraded to ^5.9.3 — TS5 builds clean once npm node_modules is removed;
  earlier apparent breakage was caused by stale mixed npm/pnpm module resolution
…errors

- Add eslint.config.js using @polygonlabs/apps-team-lint@2.0.0
- Add commitlint.config.js (conventional commits)
- Add @commitlint/cli, bump markdownlint-cli2 to ^0.21.0
- Add type: module to root package.json (ESLint ESM config requirement)
- Add .idea to .gitignore

ESLint fixes in packages/maticjs/src/:
- Auto-fix consistent-type-imports, sort-imports, no-duplicates
- no-unused-vars: prefix unused abstract method params with _
- no-param-reassign: local variables throughout
- no-duplicate-enum-values: Erc721Transfer = Erc20Transfer (same ABI sig)
- ban-types: typed Callback alias; unknown instead of {}
- Remove unused imports: IBlock, ITransactionOption, ExitUtil, RootChainManager, ERROR_TYPE
- Config overrides: no-require-imports (webpack BUILD_ENV), no-default-export (semver-major)

Markdownlint: fix violations in README.md, SECURITY.md, bug-report template,
examples/README.md; move examples/ to repo root

Test infrastructure:
- Delete packages/maticjs/test/{package.json,tsconfig.json,jest.config.js,
  debug.js,ether.js,config.js,.env.example} — broken nested project with
  npm link, jest@27, and live-RPC dependencies
- Migrate tests/map-promise.test.ts to vitest (7 pure unit tests, no network)
- Add vitest.config.ts; add vitest to devDependencies
- Split tsconfig.json (dev+test, noEmit) from tsconfig.build.json (composite,
  rootDir: src, for webpack and project references)
- Root typecheck now delegates to pnpm -r run typecheck
if (!abiStore[bridgeType]) {
abiStore[bridgeType] = {};
}
abiStore[bridgeType][contractName] = abi;

Check warning

Code scanning / CodeQL

Prototype-polluting assignment Medium

This assignment may alter Object.prototype if a malicious '__proto__' string is injected from
library input
.

Copilot Autofix

AI 20 days ago

In general, to fix prototype-polluting assignments, either (1) avoid using plain objects with prototype chains for storage of untrusted-keyed data (e.g., use Map or Object.create(null)), or (2) validate or normalize keys before use to prevent special values like "__proto__", "constructor", and "prototype" from being used. Given the existing type definitions and use of plain objects for the cache, the least invasive approach is to validate bridgeType (and optionally contractName) in setABI, rejecting or ignoring dangerous keys, while keeping all existing functionality for legitimate keys.

The best targeted fix here is to add a small guard in setABI that checks bridgeType against a denylist of prototype-polluting keys and throws or silently returns if such a value is provided. This preserves the current cache structure and public API while ensuring that abiStore[bridgeType] = {} and abiStore[bridgeType][contractName] = abi can never hit __proto__ or similar. We only need to edit packages/maticjs/src/utils/abi_manager.ts, inside setABI. No new imports are required; we can use plain string comparison.

Concretely:

  • Modify setABI in packages/maticjs/src/utils/abi_manager.ts to:
    • Introduce a local array or simple conditional that checks if bridgeType is one of "__proto__", "constructor", or "prototype".
    • If so, either throw an error or return early. For a library utility, an early return avoids changing error behavior elsewhere, but throwing is also defensible; I’ll choose an early return as the least disruptive.
    • Keep the rest of the method unchanged.
  • Optionally, apply the same check to contractName if you want to be extra defensive; however, CodeQL’s taint path is explicitly on bridgeType, so the minimum change focuses on that parameter.
Suggested changeset 1
packages/maticjs/src/utils/abi_manager.ts

Autofix patch

Autofix patch
Run the following command in your local git repository to apply this patch
cat << 'EOF' | git apply
diff --git a/packages/maticjs/src/utils/abi_manager.ts b/packages/maticjs/src/utils/abi_manager.ts
--- a/packages/maticjs/src/utils/abi_manager.ts
+++ b/packages/maticjs/src/utils/abi_manager.ts
@@ -63,6 +63,11 @@
   }
 
   setABI(contractName: string, bridgeType: string, abi: any) {
+    // Prevent prototype pollution via specially crafted bridgeType keys
+    if (bridgeType === '__proto__' || bridgeType === 'constructor' || bridgeType === 'prototype') {
+      // Ignore unsafe keys to avoid mutating Object.prototype
+      return;
+    }
     const abiStore = cache[this.networkName][this.version].abi;
     if (!abiStore[bridgeType]) {
       abiStore[bridgeType] = {};
EOF
@@ -63,6 +63,11 @@
}

setABI(contractName: string, bridgeType: string, abi: any) {
// Prevent prototype pollution via specially crafted bridgeType keys
if (bridgeType === '__proto__' || bridgeType === 'constructor' || bridgeType === 'prototype') {
// Ignore unsafe keys to avoid mutating Object.prototype
return;
}
const abiStore = cache[this.networkName][this.version].abi;
if (!abiStore[bridgeType]) {
abiStore[bridgeType] = {};
Copilot is powered by AI and may make mistakes. Always verify output.
@MaximusHaximus MaximusHaximus force-pushed the chore/monorepo branch 5 times, most recently from 0e44251 to 43315e1 Compare March 29, 2026 00:52
Public repo pattern — no references to apps-team-workflows (private).
Every workflow and action is a local copy.

- Delete legacy ci.yml (npm-based) and github_doc_deploy.yml (dead since 2022)
- Add .github/actions/ci/ — verbatim copy of CI composite action
- Add .github/actions/upsert-changeset-comment/ — verbatim copy including
  compiled dist/index.js bundle (required since private repo actions cannot
  be called cross-visibility)
- Add ci-trigger.yml — PR gate; calls ./.github/actions/ci
- Add changeset-check.yml + changeset-check-trigger.yml — changeset PR gate;
  uses local upsert-changeset-comment action
- Add npm-release.yml + npm-release-trigger.yml — release pipeline on push
  to master; three main→master substitutions from canonical workflow
- Add claude-code-review.yml + claude-code-review-trigger.yml
- Add claude.yml + claude-trigger.yml
- All triggers target master branch
@MaximusHaximus MaximusHaximus marked this pull request as ready for review March 29, 2026 01:12
Comment thread PLAN.md

---

## Phase 2 — PR 3: `@maticnetwork/maticjs-viem` ⬜
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🥳

Copy link
Copy Markdown

@shan8851 shan8851 left a comment

Choose a reason for hiding this comment

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

Great work :shipit:

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants