The build rewrites every @pezkuwi import into a deno.land URL, so @pezkuwi/util becomes https://deno.land/x/pezkuwi/util/mod.ts. Upstream can do that because deno.land/x/polkadot is published. Our fork renamed the prefix to x/pezkuwi and never published there: deno.land/x/pezkuwi answers 404, and `deno check` has failed on three modules ever since. Reproduced locally with the same Deno the workflow installs, 2.9.7: TS2307 Cannot find module 'https://deno.land/x/pezkuwi/util/mod.ts' TS2307 Cannot find module 'https://deno.land/x/pezkuwi/util-crypto/mod.ts' TS2307 Cannot find module 'https://deno.land/x/pezkuwi/x-fetch/mod.ts' import_map.in.json is the tooling's own hook for exactly this — pezkuwi-dev-deno-map merges its entries into the generated import_map.json. All three are mapped to npm: specifiers, which Deno resolves natively, at the same version ranges the node build uses. The three packages are already on npm, so nothing new is published and the Deno build now checks against the very code we ship. `yarn deno` exits 0. This deliberately does not decide whether we ever claim deno.land/x/pezkuwi. If we do, the mappings come out again; until then the build works with what we have. The reason none of this was noticed is the second half of the change. The PR job carried continue-on-error from upstream, so its four steps could never turn a pull request red: build had been failing since 2026-09-13 and deno for far longer, and the job reported success throughout. All four pass now — verified locally, lint included, on a clean tree — so the flag is gone and they are gates again. deno.lock joins mod.ts and import_map.json in .gitignore: same check, same kind of generated artifact. package.json carries the key order its own build:before step produces. Gate: scripts/checkDenoMap.mjs, in the Lists workflow so it runs even when the toolchain cannot be installed. Nails: removing the map, bumping a dependency without the map, adding a @pezkuwi dependency with no mapping, and leaving a mapping behind after its dependency goes — each turns it red. Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
@pezkuwi/phishing
A curated list of potentially less-than-honest sites inclusive of a simple JS utility function to check any host against this list.
How the lists are kept
These lists are Pezkuwi's copy of polkadot-js/phishing: they follow upstream, with a few entries of our own.
- Daily sync.
sync-upstream.ymltakes upstream's lists every day, layspezkuwi/overlay.jsonover them, and commits the result tomaster. On a day out of bounds it writes nothing and opens an issue instead: more than 25 sites unblocked or 5000 added, more than 10 scam addresses dropped, one of our own domains blocked, or one of our entries lost (scripts/lists.mjs). - Our entries.
overlay.jsonholds the sites we block that upstream does not (deny), upstream entries we deliberately do not block (undeny), and our own domains, which no entry may ever block (protect). Each entry records why and since when. Change our entries there, not inall.json, which every sync rewrites from upstream. - Publishing. phishing.pezkuwichain.io pulls
masterevery hour and checks the lists again before it serves them (pezkuwi/host/). - Checks.
lists.ymlruns the rules' tests andscripts/checkLists.mjson every change. Neither needs the build toolchain.
Additions
Report a new site or scam address to polkadot-js/phishing, and the daily sync brings it here. A site that targets Pezkuwi specifically, and that upstream would not list, goes in the deny section of pezkuwi/overlay.json, with its reason and date.
Availability
Changes reach phishing.pezkuwichain.io/all.json and phishing.pezkuwichain.io/address.json within the hour after they land on master. These can be consumed via @pezkuwi/phishing and other tools capable of parsing JSON.
Notable users
The following wallets integrate either address or site blocking from these lists:
Integration
Since the lists are published as JSON, integration for any non-JS wallets (only a JS library that is provided) should be simple - retrieve the applicable list, parse the JSON, and do the required checks either on the host or address as per the requirements. The Javascript library does have some features that may be worth thinking about for other integrations -
- instead of retrieving the list each time a request is made, a local copy is cached for 45 minutes and then re-retrieved when the timer expires (as a request is made)
- for address checks, the check is done on the decoded ss58 address to ensure that network-jumps with the same keys are avoided (so addresses do not have to be re-added for other networks, a single entry will cover all)
Contributing
These lists are intended to be maintained with active input from the community, so contributions are welcome, either via a pull request (edit above as described in additions) or by logging an issue.