Skip to content

Commit 992f52f

Browse files
Merge pull request #523 from pimlicolabs/fix/type-checks
Fix published package leaking raw .ts sources into consumer type-chec…
2 parents 7e438d4 + f90ee52 commit 992f52f

56 files changed

Lines changed: 458 additions & 140 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.changeset/brave-donuts-shine.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"@pimlico/mock-paymaster": patch
3+
---
4+
5+
Internal: paymaster lookups by entryPoint now go through a narrowing helper; the package compiles under `noUncheckedIndexedAccess`.

.changeset/tidy-moons-repair.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"permissionless": patch
3+
---
4+
5+
Fixed published-package type-checking for consumers on legacy `moduleResolution: "node"` (node10): every exported subpath directory now ships a proxy package.json pointing at the compiled `_types`/`_esm`/`_cjs` output, so `tsc` resolves declarations instead of pulling raw `.ts` sources into the consumer's program (#522). Barrel subpath modules (`actions/{erc7579,pimlico,passkeyServer,etherspot,smartAccount}` and `clients/{pimlico,passkeyServer}`) moved from single files into directories with index files — package-specifier imports are unaffected, only private deep imports of `_esm`/`_cjs`/`_types` file paths change. Test files and vitest config are no longer included in the npm tarball; `.ts` sources are still shipped for debuggability. The codebase now compiles under `noUncheckedIndexedAccess`, so sources stay error-free even when consumer projects type-check them with that flag enabled.

.changeset/wild-camels-check.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"@permissionless/wagmi": patch
3+
---
4+
5+
Fixed `useAvailableCapabilities` to return `undefined` instead of throwing when the connected chain has no capabilities entry, and hardened receipt handling in `useWaitForTransactionReceipt`. The package now compiles under `noUncheckedIndexedAccess`.
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
node_modules
2+
package-lock.json
3+
*.tgz
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
// Imports every exported subpath of the permissionless package so that tsc
2+
// resolves each one. If raw .ts sources ever leak back into consumer programs
3+
// (missing subpath proxy package.json, see issue #522) or the published .d.ts
4+
// surface breaks under strict flags, these imports fail to type-check.
5+
export * as permissionless from "permissionless"
6+
export * as accounts from "permissionless/accounts"
7+
export * as accountsBiconomy from "permissionless/accounts/biconomy"
8+
export * as accountsEtherspot from "permissionless/accounts/etherspot"
9+
export * as accountsKernel from "permissionless/accounts/kernel"
10+
export * as accountsLight from "permissionless/accounts/light"
11+
export * as accountsNexus from "permissionless/accounts/nexus"
12+
export * as accountsSafe from "permissionless/accounts/safe"
13+
export * as accountsSimple from "permissionless/accounts/simple"
14+
export * as accountsThirdweb from "permissionless/accounts/thirdweb"
15+
export * as accountsTrust from "permissionless/accounts/trust"
16+
export * as actions from "permissionless/actions"
17+
export * as actionsErc7579 from "permissionless/actions/erc7579"
18+
export * as actionsEtherspot from "permissionless/actions/etherspot"
19+
export * as actionsPasskeyServer from "permissionless/actions/passkeyServer"
20+
export * as actionsPimlico from "permissionless/actions/pimlico"
21+
export * as actionsSmartAccount from "permissionless/actions/smartAccount"
22+
export * as clients from "permissionless/clients"
23+
export * as clientsPasskeyServer from "permissionless/clients/passkeyServer"
24+
export * as clientsPimlico from "permissionless/clients/pimlico"
25+
export * as errors from "permissionless/errors"
26+
export * as experimentalPimlico from "permissionless/experimental/pimlico"
27+
export * as utils from "permissionless/utils"
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
{
2+
"name": "type-consumer-fixture",
3+
"private": true,
4+
"description": "Type-checks the packed permissionless tarball the way consumers do (issue #522). The tarball is installed at CI time by the package-types workflow job.",
5+
"devDependencies": {
6+
"ox": "0.11.3",
7+
"typescript": "5.9.3",
8+
"viem": "2.51.3"
9+
}
10+
}
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
{
2+
// Modern resolution follows the exports map to the published .d.ts files.
3+
// skipLibCheck is off and the strictest consumer flags are on, so this
4+
// verifies the declaration surface stays clean for the pickiest setups.
5+
"compilerOptions": {
6+
"target": "ES2022",
7+
"module": "esnext",
8+
"moduleResolution": "bundler",
9+
"strict": true,
10+
"noUncheckedIndexedAccess": true,
11+
"exactOptionalPropertyTypes": true,
12+
"skipLibCheck": false,
13+
"noEmit": true,
14+
// Keep the program hermetic: without this, tsc auto-includes every
15+
// node_modules/@types package from parent directories (the monorepo
16+
// root), so unrelated workspace typings leak into this fixture.
17+
"types": []
18+
},
19+
"files": ["consumer.ts"]
20+
}
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
{
2+
// Legacy node10 resolution ignores the exports map for subpaths, so it
3+
// only finds .d.ts declarations through the per-directory proxy
4+
// package.json files. Raw .ts sources leaking into the program error out
5+
// even with skipLibCheck enabled, which isolates the signal to exactly
6+
// the regression this fixture guards against (issue #522).
7+
"compilerOptions": {
8+
"target": "ES2021",
9+
"module": "commonjs",
10+
"moduleResolution": "node10",
11+
"strict": true,
12+
"noUncheckedIndexedAccess": true,
13+
"esModuleInterop": true,
14+
"skipLibCheck": true,
15+
"noEmit": true,
16+
// Keep the program hermetic: without this, tsc auto-includes every
17+
// node_modules/@types package from parent directories (the monorepo
18+
// root), so unrelated workspace typings leak into this fixture.
19+
"types": []
20+
},
21+
"files": ["consumer.ts"]
22+
}

.github/workflows/on-pull-request.yml

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,48 @@ jobs:
4646
- name: Build
4747
run: bun run build
4848

49+
package-types:
50+
name: Package types (node10 + bundler consumers)
51+
runs-on: ubuntu-latest
52+
timeout-minutes: 15
53+
54+
steps:
55+
- name: Clone repository
56+
uses: actions/checkout@v6
57+
58+
- name: Install dependencies
59+
uses: ./.github/actions/install-dependencies
60+
61+
- uses: actions/setup-node@v6
62+
with:
63+
node-version: "22"
64+
65+
- name: Build permissionless
66+
run: bun run build:permissionless:tsgo
67+
68+
- name: Pack tarball into fixture
69+
working-directory: packages/permissionless
70+
run: npm pack --pack-destination ../../.github/fixtures/type-consumer
71+
72+
- name: Install fixture dependencies
73+
working-directory: .github/fixtures/type-consumer
74+
run: |
75+
npm install --no-package-lock
76+
npm install --no-package-lock --no-save ./permissionless-*.tgz
77+
78+
- name: Type-check as a node10 consumer
79+
working-directory: .github/fixtures/type-consumer
80+
run: npx tsc -p tsconfig.node10.json
81+
82+
- name: Type-check as a bundler consumer
83+
working-directory: .github/fixtures/type-consumer
84+
run: npx tsc -p tsconfig.bundler.json
85+
86+
- name: Lint package publishing metadata (advisory)
87+
working-directory: packages/permissionless
88+
continue-on-error: true
89+
run: npx --yes publint --strict
90+
4991
docker-e2e:
5092
name: E2E-Coverage
5193
runs-on: ubuntu-latest

packages/mock-paymaster/relay.ts

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -181,6 +181,17 @@ const handleMethod = async ({
181181
[entryPoint08Address]: paymaster08
182182
}
183183

184+
const getPaymaster = (entryPoint: Address): Address => {
185+
const paymaster = epToPaymaster[entryPoint]
186+
if (paymaster === undefined) {
187+
throw new RpcError(
188+
"EntryPoint not supported",
189+
ValidationErrors.InvalidFields
190+
)
191+
}
192+
return paymaster
193+
}
194+
184195
if (parsedBody.method === "pm_sponsorUserOperation") {
185196
const params = pmSponsorUserOperationParamsSchema.safeParse(
186197
parsedBody.params
@@ -201,7 +212,7 @@ const handleMethod = async ({
201212
userOperation,
202213
paymasterMode: { mode: "verifying" },
203214
bundler: bundlerClient,
204-
paymaster: epToPaymaster[entryPoint],
215+
paymaster: getPaymaster(entryPoint),
205216
publicClient,
206217
paymasterSigner,
207218
estimateGas: true
@@ -242,7 +253,7 @@ const handleMethod = async ({
242253
return {
243254
...getDummyPaymasterData({
244255
is06,
245-
paymaster: epToPaymaster[entryPoint],
256+
paymaster: getPaymaster(entryPoint),
246257
paymasterMode
247258
}),
248259
...dummyPaymasterGas,
@@ -268,7 +279,7 @@ const handleMethod = async ({
268279
signer: paymasterSigner,
269280
userOp: userOperation as UserOperation,
270281
paymasterMode: getPaymasterMode(data),
271-
paymaster: epToPaymaster[entryPoint],
282+
paymaster: getPaymaster(entryPoint),
272283
publicClient
273284
})
274285
}

0 commit comments

Comments
 (0)