Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions packages/cli/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,12 @@ All notable changes to the `nirium-cli` package are documented here.

## Unreleased

## 3.1.1 - 2026-11-07

### Fixed

- `nirium verify` with no `--gateway` tried only `gateway.pinata.cloud`, which often takes 5-7s and can hit the 8s timeout, so a healthy CID failed to verify. It now tries Filebase's dedicated gateway first, then Pinata, `ipfs.io` and `dweb.link` - the same chain the `verify-audit-cid` Action has used since [#259](https://github.com/nirium-protocol/nirium/pull/259), plus Pinata. Passing `--gateway` still replaces the default list.

## 3.1.0 - 2026-11-07

### Added
Expand Down
8 changes: 6 additions & 2 deletions packages/cli/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -288,15 +288,19 @@ Signatures are accepted as base64 or hex, raw ed25519 or SEP-53
short backoff first - a fresh pin can take a moment to propagate, so a
404 there doesn't mean the CID is wrong, just not there *yet*. Any other
failure (a real error, or a timed-out request) moves straight to the
next gateway instead, since retrying the same one won't help:
next gateway instead, since retrying the same one won't help.

With no `--gateway`, it tries Filebase's dedicated gateway, then Pinata,
then `ipfs.io`, then `dweb.link`. Shared public gateways often answer
`429` under load, so the dedicated one goes first:

```bash
nirium verify <cid> --gateway https://gateway.pinata.cloud --gateway https://ipfs.io --retries 3
```

| Option | Purpose | Default |
|---|---|---|
| `-g, --gateway <url>` | IPFS gateway to fetch from - repeat for fallbacks | `https://gateway.pinata.cloud` |
| `-g, --gateway <url>` | IPFS gateway to fetch from - repeat for fallbacks | `nirium.myfilebase.com`, then `gateway.pinata.cloud`, `ipfs.io`, `dweb.link` |
| `--retries <n>` | retries per gateway on a 404, with backoff | `2` |
| `--timeout <ms>` | per-request timeout | `8000` |
| `--json` | machine-readable result | off |
Expand Down
15 changes: 13 additions & 2 deletions packages/cli/bin/nirium.js
Original file line number Diff line number Diff line change
Expand Up @@ -158,11 +158,22 @@ program
}
});

// Tried in order when no --gateway is given. ipfs.io and dweb.link answer 429
// for healthy CIDs under load (#185), and Pinata serves our pins but often
// takes 5-7s, so a dedicated gateway goes first. Same chain as the
// verify-audit-cid Action (#259), plus Pinata.
const DEFAULT_GATEWAYS = [
'https://nirium.myfilebase.com',
'https://gateway.pinata.cloud',
'https://ipfs.io',
'https://dweb.link',
];

// --- COMMAND: verify ---
program
.command('verify')
.argument('<cid>', 'IPFS Content Identifier (CID) of the audit document')
.option('-g, --gateway <url>', 'IPFS gateway URL - repeatable, tried in order as fallbacks', (val, prev) => [...(prev || []), val], [])
.option('-g, --gateway <url>', 'IPFS gateway URL - repeatable, tried in order as fallbacks (default: Filebase, Pinata, ipfs.io, dweb.link)', (val, prev) => [...(prev || []), val], [])
.option('--retries <n>', 'Retries per gateway on a 404 (content may not be propagated yet), with backoff', '2')
.option('--timeout <ms>', 'Per-request timeout in milliseconds', '8000')
.option('--json', 'Output result as JSON')
Expand Down Expand Up @@ -191,7 +202,7 @@ program
process.exit(1);
}

const gateways = options.gateway.length > 0 ? options.gateway : ['https://gateway.pinata.cloud'];
const gateways = options.gateway.length > 0 ? options.gateway : DEFAULT_GATEWAYS;
const result = await fetchAndVerifyCid(cid, gateways, globalThis.fetch, { expectedHash, retries, timeoutMs });
if (options.json) {
console.log(JSON.stringify(result, null, 2));
Expand Down
2 changes: 1 addition & 1 deletion packages/cli/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "nirium-cli",
"version": "3.1.0",
"version": "3.1.1",
"description": "Nirium CLI \u2014 scaffold Stellar agent projects and check agent status",
"main": "bin/nirium.js",
"type": "module",
Expand Down
12 changes: 12 additions & 0 deletions packages/cli/test/verify-retry-gateway.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -161,3 +161,15 @@ test('--timeout rejects a non-positive value', async () => {
assert.equal(r.code, 1);
assert.match(r.stderr, /Invalid --timeout/);
});

test('no --gateway given: tries the default chain in order (Filebase, Pinata, ipfs.io, dweb.link)', async () => {
// 1ms timeout aborts every request before it reaches the network, so this
// checks only the order of the default list, never a real gateway's answer.
const r = await run(['--timeout', '1', '--retries', '0']);
assert.equal(r.code, 1);
const json = JSON.parse(r.stdout);
assert.deepEqual(
json.attempts.map((a) => a.gateway),
['https://nirium.myfilebase.com', 'https://gateway.pinata.cloud', 'https://ipfs.io', 'https://dweb.link'],
);
});
Loading