@perspectivefi/addresses 0.2.5 → 0.2.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (3) hide show
  1. package/README.md +1 -1
  2. package/dist/cli.js +33 -11
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -181,7 +181,7 @@ spectra-addresses check <paths...> [--mode off|enforce] [--allow <json file>]...
181
181
  - **Mode**: `--mode`, else env `ADDRESS_GATE`. There are two modes. `off` prints the full report and always exits 0. `enforce` exits 1 on any violation. If `VERCEL_ENV=production` and the mode is unset or invalid, the check exits 1 ("ADDRESS_GATE must be set to off or enforce in production"), so a missing setting can never silently disable protection. Outside production an unset or invalid mode means `off`. `enforce` is not downgraded on preview builds.
182
182
  - **Tagged blocks first**: every `$spectraAddresses` block (from `/keys`, `/prod/keys`, the runtime datasets and the runtime denylist) is found, also when its JSON is escaped inside a JS string. For each `(chain, address)` in a block, the exact entry for **that chain** must be `safe` in the latest registry and not denylisted. The report names key and chain. A block that cannot be parsed, or carries anything besides the fields we emit, is a violation. The runtime denylist block is accepted only for addresses the registry itself denylists.
183
183
  - **Then bare addresses**: the blocks are cut out and the rest of the file is scanned for EVM addresses and Stellar contract ids. A bare address passes only if it is on an `--allow` list, **or** every registry entry with that address (on any chain) is `safe` and it is denylisted on no chain. Otherwise it is a violation, and the report says which chain made it fail (`blocked`, `unsafe`, `denylisted`, or `not in registry`). A denylisted address fails even if it is on an `--allow` list.
184
- - **Latest registry**: the check does not use the version your lockfile pins. It fetches the latest `dist/registry.json` from jsDelivr (`https://cdn.jsdelivr.net/npm/@perspectivefi/addresses@latest/dist/registry.json`), then from unpkg (`https://unpkg.com/@perspectivefi/addresses@latest/dist/registry.json`), 10 second timeout each. `--registry <url-or-file>` or env `ADDRESS_REGISTRY_URL` replaces both (the flag wins). The output says which dataset was used.
184
+ - **Latest registry**: the check does not use the version your lockfile pins. jsDelivr and unpkg cache `@latest` URLs for hours, so it first asks npm for the exact latest version (`https://registry.npmjs.org/@perspectivefi/addresses/latest`, printed as `latest published version: x.y.z`) and then fetches `dist/registry.json` of that version from jsDelivr (`https://cdn.jsdelivr.net/npm/@perspectivefi/addresses@<version>/dist/registry.json`), then from unpkg (`https://unpkg.com/@perspectivefi/addresses@<version>/dist/registry.json`), 10 second timeout each. If the npm lookup fails it prints a warning and uses the `@latest` CDN URLs instead. `--registry <url-or-file>` or env `ADDRESS_REGISTRY_URL` replaces all of this (the flag wins; no npm lookup). The output says which dataset was used.
185
185
  - **If no source loads**: in `off` the check prints a `WARNING` and uses the dataset bundled in the installed package. In `enforce` it exits 1 ("cannot verify against the latest registry"). `--offline` skips the fetch and uses the bundled dataset on purpose; in `enforce` it prints a loud warning that the run is only as fresh as the installed version.
186
186
  - Scans files recursively (skips `*.map`, `cache` and `node_modules` dirs, and binary files over 5 MB).
187
187
  - Always allowed: the zero address and `0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE`. `--allow` takes JSON files with an array of address strings (or objects with an `address` field). Use it for token-list addresses. It applies to bare addresses only.
package/dist/cli.js CHANGED
@@ -30,12 +30,14 @@ var BUILTIN_ALLOW = [
30
30
  ];
31
31
  var TAG = "$spectraAddresses";
32
32
  var DATASET_FIELDS = /* @__PURE__ */ new Set(["chain", "key", "address", "kind", "status", "inherit"]);
33
- var DEFAULT_REGISTRY_URLS = [
34
- "https://cdn.jsdelivr.net/npm/@perspectivefi/addresses@latest/dist/registry.json",
35
- "https://unpkg.com/@perspectivefi/addresses@latest/dist/registry.json"
33
+ var NPM_LATEST_URL = "https://registry.npmjs.org/@perspectivefi/addresses/latest";
34
+ var registryUrls = (version) => [
35
+ `https://cdn.jsdelivr.net/npm/@perspectivefi/addresses@${version}/dist/registry.json`,
36
+ `https://unpkg.com/@perspectivefi/addresses@${version}/dist/registry.json`
36
37
  ];
38
+ var SEMVER_RE = /^\d+\.\d+\.\d+(?:-[0-9A-Za-z.-]+)?$/;
37
39
  var FETCH_TIMEOUT_MS = 1e4;
38
- var BUNDLED_VERSION = true ? "0.2.5" : "dev";
40
+ var BUNDLED_VERSION = true ? "0.2.6" : "dev";
39
41
  var USAGE = `Usage: spectra-addresses check <paths...> [--mode off|enforce] [--allow <json file>]... [--registry <url|file>] [--offline]
40
42
 
41
43
  --mode off or enforce. Falls back to env ADDRESS_GATE, then to off.
@@ -45,7 +47,7 @@ var USAGE = `Usage: spectra-addresses check <paths...> [--mode off|enforce] [--a
45
47
  --allow JSON file: array of address strings, or objects with an "address" field.
46
48
  Repeatable. Typical use: the token-list addresses. Applies to bare addresses only.
47
49
  --registry Registry dataset to check against: URL or JSON file. Falls back to env
48
- ADDRESS_REGISTRY_URL, then the latest published package (jsDelivr, then unpkg).
50
+ ADDRESS_REGISTRY_URL, then the latest published package (version from npm, read via jsDelivr, then unpkg).
49
51
  If no source can be loaded: off warns and uses the bundled dataset, enforce fails.
50
52
  --offline Skip the fetch and use the dataset bundled in this package.`;
51
53
  var VIOLATIONS = ["not-safe", "denied", "unknown", "malformed"];
@@ -140,6 +142,15 @@ function parseDataset(json) {
140
142
  });
141
143
  return json;
142
144
  }
145
+ async function resolveLatestVersion(fetchFn) {
146
+ const res = await fetchFn(NPM_LATEST_URL, { signal: AbortSignal.timeout(FETCH_TIMEOUT_MS) });
147
+ if (!res.ok) throw new Error(`HTTP ${res.status}`);
148
+ const version = (await res.json())?.version;
149
+ if (typeof version !== "string" || !SEMVER_RE.test(version)) {
150
+ throw new Error('no valid "version" in the response');
151
+ }
152
+ return version;
153
+ }
143
154
  async function loadFromSource(source, cwd, fetchFn) {
144
155
  if (!/^https?:\/\//i.test(source)) {
145
156
  return parseDataset(JSON.parse((0, import_node_fs.readFileSync)((0, import_node_path.resolve)(cwd, source), "utf8")));
@@ -306,16 +317,27 @@ ${USAGE}`);
306
317
  }
307
318
  } else {
308
319
  const override = args.registry ?? (env.ADDRESS_REGISTRY_URL?.trim() || void 0);
309
- const sources = override ? [override] : DEFAULT_REGISTRY_URLS;
320
+ const fetchFn = opts.fetch ?? globalThis.fetch;
310
321
  const failures = [];
322
+ let sources;
323
+ if (override) {
324
+ sources = [override];
325
+ } else {
326
+ try {
327
+ const version = await resolveLatestVersion(fetchFn);
328
+ out(`latest published version: ${version}`);
329
+ sources = registryUrls(version);
330
+ } catch (e) {
331
+ out(
332
+ `WARNING: could not resolve the latest version on npm (${e.message}); falling back to the @latest CDN URLs, which can be cached for hours.`
333
+ );
334
+ sources = registryUrls("latest");
335
+ }
336
+ }
311
337
  let loaded;
312
338
  for (const source of sources) {
313
339
  try {
314
- dataset = await loadFromSource(
315
- source,
316
- cwd,
317
- opts.fetch ?? globalThis.fetch
318
- );
340
+ dataset = await loadFromSource(source, cwd, fetchFn);
319
341
  loaded = source;
320
342
  break;
321
343
  } catch (e) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@perspectivefi/addresses",
3
- "version": "0.2.5",
3
+ "version": "0.2.6",
4
4
  "description": "Contract address registry for Spectra: one list of every address, each with a status. Prod only accepts `safe`.",
5
5
  "main": "./dist/index.js",
6
6
  "module": "./dist/index.mjs",