Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
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
49 changes: 49 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,55 @@ jobs:
- name: Run lint
run: npm run lint

pack_smoke:
# Guards the global-install contract without needing a full Ocean stack:
# a broken bin, cwd-dependent module loading, or env-gated --help/--version
# would all fail here. Also asserts the publish tarball excludes sources.
runs-on: ubuntu-latest

steps:
- name: Checkout code
uses: actions/checkout@v4
Comment thread
alexcos20 marked this conversation as resolved.

- name: Set up Node.js
uses: actions/setup-node@v4
with:
node-version: "22.5.1"

- name: Install dependencies
run: npm ci

- name: Build
run: npm run build

- name: Pack tarball
run: |
TARBALL=$(npm pack | tail -1)
echo "TARBALL=$TARBALL" >> $GITHUB_ENV
echo "Packed $TARBALL"

- name: Assert tarball contents (dist/metadata/README in; src/test out)
run: |
FILES=$(tar -tzf "$TARBALL")
echo "$FILES"
echo "$FILES" | grep -q '^package/dist/index.js$' || { echo "MISSING dist/index.js"; exit 1; }
echo "$FILES" | grep -q '^package/README.md$' || { echo "MISSING README.md"; exit 1; }
echo "$FILES" | grep -q '^package/metadata/' || { echo "MISSING metadata/"; exit 1; }
if echo "$FILES" | grep -qE '^package/(src|test)/'; then
echo "Tarball must not ship src/ or test/"; exit 1
fi

- name: Install globally from tarball
run: npm i -g "./$TARBALL"

- name: Run bin from a foreign cwd with NO env vars
working-directory: ${{ runner.temp }}
run: |
ocean-cli --version
ocean-cli --help > /dev/null
ocean-cli -h > /dev/null
ocean-cli -V > /dev/null

test_system:
runs-on: ubuntu-latest
strategy:
Expand Down
41 changes: 41 additions & 0 deletions .github/workflows/publish.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
name: Publish

on:
push:
tags:
- "**"
Comment thread
coderabbitai[bot] marked this conversation as resolved.
Outdated

permissions:
contents: read
id-token: write # required for npm provenance

jobs:
npm:
runs-on: ubuntu-latest
env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
Comment thread
coderabbitai[bot] marked this conversation as resolved.
Outdated

steps:
- name: Checkout code
uses: actions/checkout@v4

- name: Set up Node.js
uses: actions/setup-node@v4
with:
node-version: "22.5.1"
registry-url: "https://registry.npmjs.org/"

- name: Install dependencies
run: npm ci

# prepublishOnly (npm run build) runs automatically during npm publish.
# --access public is required for a scoped package; --provenance attests
# the build to the source commit (needs the package.json `repository`
# field to match this repo and the id-token permission above).
- name: Publish (next)
if: contains(github.ref, 'next')
run: npm publish --tag next --provenance --access public

- name: Publish (latest)
if: ${{ !contains(github.ref, 'next') }}
run: npm publish --provenance --access public
11 changes: 7 additions & 4 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ This file provides guidance to Claude Code (claude.ai/code) when working with co

## What this project is

`ocean-cli` (package name `ocean-cli`, version 2.0.0) is a TypeScript CLI that wraps the Ocean Protocol JavaScript library (`@oceanprotocol/lib`, a.k.a. ocean.js) to publish, edit, consume/download, and run compute-to-data (C2D) on assets, plus manage escrow payments, access lists, persistent-storage buckets, auth tokens, and admin node logs. It talks to an **Ocean Node** (the single service that replaced the old standalone Provider and Aquarius apps — it does metadata caching, indexing, encryption, ordering, and compute) and to an EVM chain via an RPC endpoint.
`ocean-cli` (npm package `@oceanprotocol/cli`, version 2.0.0; installs a `bin` named `ocean-cli`) is a TypeScript CLI that wraps the Ocean Protocol JavaScript library (`@oceanprotocol/lib`, a.k.a. ocean.js) to publish, edit, consume/download, and run compute-to-data (C2D) on assets, plus manage escrow payments, access lists, persistent-storage buckets, auth tokens, and admin node logs. It talks to an **Ocean Node** (the single service that replaced the old standalone Provider and Aquarius apps — it does metadata caching, indexing, encryption, ordering, and compute) and to an EVM chain via an RPC endpoint.

The package is pure ESM (`"type": "module"` in `package.json`). All relative imports MUST carry an explicit `.js` extension even though the source is `.ts` (e.g. `import { Commands } from "./commands.js"`). Node 22 is expected (`.nvmrc` = `22`; CI uses `22.5.1`).

Expand All @@ -22,6 +22,7 @@ Scripts (from `package.json`):
- `npm run test` — `npm run lint && npm run test:system` (lint is part of "test").
- `npm run test:system` — `npm run mocha 'test/**/*.test.ts'`.
- `npm run mocha` — `NODE_OPTIONS='--experimental-require-module' mocha --config=test/.mocharc.json --node-env=test --exit`.
- `npm run release` — `release-it --non-interactive`: bumps version, builds, regenerates the changelog (`npm run changelog` = `auto-changelog -p`), commits, tags `v${version}`, pushes, and cuts a GitHub Release. Does **not** publish to npm (`release-it` config `npm.publish: false`) — pushing the tag triggers `.github/workflows/publish.yml`, which runs `npm publish` (`--tag next` for tags containing `next`, else `latest`). Mirrors `@oceanprotocol/lib`'s release flow.

Mocha config (`test/.mocharc.json`): loader `ts-node/esm`, `bail: true` (stops at first failure), `timeout: 20000`, `exit: true`.

Expand Down Expand Up @@ -50,7 +51,9 @@ npm run cli h # list commands ("h" and "help" are aliases
npm run cli publish metadata/simpleDownloadDataset.json
```

Important behavior of the entry point (`src/index.ts`): after running the command passed on argv **once**, the process enters an interactive REPL loop, printing `Enter command ('exit' | 'quit' or CTRL-C to terminate')` and reading further commands from stdin until you type `exit`/`quit`/`\q`. To get one-shot behavior (run and exit — required for CI and scripting) set `AVOID_LOOP_RUN=true`. In the REPL you may type either the bare command (`publish metadata/x.json`) or the full `npm run cli publish metadata/x.json` form.
`npm run cli` (= `npx tsx src/index.ts`) runs from source, no build. A globally installed copy (`npm i -g @oceanprotocol/cli`) exposes the same thing as the `ocean-cli` binary — `ocean-cli <command>` is equivalent to `npm run cli <command>`.

Important behavior of the entry point (`src/index.ts`): after running the command passed on argv **once**, the process enters an interactive REPL loop, printing `Enter command ('exit' | 'quit' | ESC or CTRL-C to terminate')` and reading further commands from stdin until you type `exit`/`quit`/`\q`, press **ESC** (TTY only), or hit CTRL-C. To get one-shot behavior (run and exit — required for CI and scripting) set `AVOID_LOOP_RUN=true`. In the REPL you may type either the bare command (`publish metadata/x.json`) or the full `npm run cli publish metadata/x.json` / `ocean-cli publish metadata/x.json` form (the leading prefix is stripped). Note: a pure help/version invocation (`--help`, `-h`, `--version`, `-V`, `h`, `help`) skips env-var validation and P2P bootstrap, so it works with no configuration; every other command still validates the env vars below.

### Required environment variables

Expand Down Expand Up @@ -92,7 +95,7 @@ Per-command flags and examples are exhaustively documented in `README.md` ("Comm

`main()` in `index.ts` calls `createCLI()` (in `cli.ts`) to build the Commander `program`, records supported command names/aliases, prints the REPL banner, runs the initial argv command once, then loops on stdin (`waitForCommands`) unless `AVOID_LOOP_RUN=true`. It uses `program.exitOverride()` so Commander errors don't kill the loop.

`createCLI()` does three things: (1) validates the required env vars, (2) if `NODE_URL` is a P2P URI, sets up libp2p (see "Transport"), (3) registers every command. Each command's `.action(...)`:
`createCLI()` does three things: (1) validates the required env vars — **unless** the invocation is a pure help/version one (`--help`/`-h`/`--version`/`-V`/`h`/`help`), which is detected from `process.argv` and skips both validation and P2P so those work with no config, (2) if `NODE_URL` is a P2P URI, sets up libp2p (see "Transport"), (3) registers every command. Each command's `.action(...)`:

1. merges positional + option values,
2. calls the local `initializeSigner()` — builds a `JsonRpcProvider(RPC)`, a `Wallet` from `PRIVATE_KEY` (or `Wallet.fromPhrase(MNEMONIC)`), and reads `chainId` from the network,
Expand Down Expand Up @@ -121,7 +124,7 @@ One big class holding all command logic. The constructor:

`helpers.ts` is the seam between the CLI and ocean.js:

- `createAssetUtil(...)` wraps ocean.js `createAsset` (used by publish/publishAlgo and the interactive publisher). It resolves the active ERC20 template (`calculateActiveTemplateIndex` reads `@oceanprotocol/contracts` `ERC20Template.json` ABI from `node_modules`), and for **Oasis Sapphire** (`config.sdk === 'oasis'`) wraps the signer with `@oasisprotocol/sapphire-paratime` (`getSignerAccordingSdk`) and deploys an allow access list before creating the asset.
- `createAssetUtil(...)` wraps ocean.js `createAsset` (used by publish/publishAlgo and the interactive publisher). It resolves the active ERC20 template (`calculateActiveTemplateIndex` reads and `JSON.parse`s the `@oceanprotocol/contracts` `ERC20Template.json` ABI, resolved via `createRequire`/`require.resolve` so it works from any cwd — e.g. a global install — not a cwd-relative `node_modules` path), and for **Oasis Sapphire** (`config.sdk === 'oasis'`) wraps the signer with `@oasisprotocol/sapphire-paratime` (`getSignerAccordingSdk`) and deploys an allow access list before creating the asset.
- `updateAssetMetadata(...)` — used by `editAsset`, `allowAlgo`, `disallowAlgo` and the interactive publisher. It validates the DDO via `aquarius.validate`, then either `ProviderInstance.encrypt`s the DDO (flags = 2) or hexlifies raw JSON (flags = 0) depending on the `encryptDDO` flag, then calls `nft.setMetadata`.
- `handleComputeOrder(...)` — the ordering state machine used in compute: validOrder + no fees → reuse as-is; validOrder + fees → `datatoken.reuseOrder` paying only provider fees; no order → `orderAsset` (pay 1 datatoken + fees). Approves provider-fee tokens first when the fee amount > 0.
- `resolveComputeInputs(...)` + `parseComputeInput(...)` — parse the datasets/algo CLI strings (DID | JSON object | array | mixed | legacy `[did:a,did:b]`), resolve DID entries through `aquarius.waitForIndexer`, pass raw `fileObject` entries through (aligned with a `null` DDO slot), and pick `providerURI` from the first DID-based DDO's `serviceEndpoint` (else fall back to `NODE_URL`).
Expand Down
45 changes: 36 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,13 +34,37 @@ If you run into problems, please open up a [new issue](https://github.com/oceanp

## 🏗 Installation & Usage

### Clone and install
### Install globally (recommended)

Install the CLI from npm to get the `ocean-cli` command available everywhere:

```bash
npm install -g @oceanprotocol/cli
```

Then invoke it directly (from any directory):

```bash
ocean-cli h # list commands
ocean-cli --version
ocean-cli publish metadata/simpleDownloadDataset.json
```

> `ocean-cli --help`, `ocean-cli -h`, `ocean-cli --version` and `ocean-cli h` work with **no** environment variables set. Every other command requires the env vars described below.

### From source (for contributors)

Clone and install, then run the CLI straight from TypeScript with `npm run cli` (no build step needed):

```bash
$ git clone https://github.com/oceanprotocol/ocean-cli.git
git clone https://github.com/oceanprotocol/ocean-cli.git
cd ocean-cli
npm install
npm run cli h
```

> **The command examples in this README use the `npm run cli <command>` form. If you installed globally, drop the `npm run cli` prefix and use `ocean-cli <command>` instead — the two are otherwise identical.** In interactive mode you can paste either form; a leading `npm run cli` or `ocean-cli` token is stripped automatically.

### Set up environment variables

- Set a private key(by exporting env "PRIVATE_KEY") or a mnemonic (by exporting env "MNEMONIC")
Expand Down Expand Up @@ -73,22 +97,22 @@ export NODE_URL='XXXX'
export ADDRESS_FILE='path-to-address-file'
```

- Optional, set INDEXING_MAX_RETRIES to the max number of retries when waiting for an asset to be indexed. Default is 100 retries max.
- Optional, set INDEXING_MAX_RETRIES to the max number of retries when waiting for an asset to be indexed. Default is 120 retries max.

```
export INDEXING_MAX_RETRIES='100'
export INDEXING_MAX_RETRIES='120'
```

- Optional, set INDEXING_RETRY_INTERVAL to the interval (in miliseconds) for each retry when waiting for an asset to be indexed. Default is 3 seconds.
- Optional, set INDEXING_RETRY_INTERVAL to the interval (in miliseconds) for each retry when waiting for an asset to be indexed. Default is 4 seconds (4000 ms).

```
export INDEXING_RETRY_INTERVAL='3000'
export INDEXING_RETRY_INTERVAL='4000'
```

- Optional, set AVOID_LOOP_RUN to 'true' to run each command and exit afterwards (usefull for CI test env and default behaviour). IF not set or set to 'false' the CLI will listen interactively for commands, until exit is manually forced
- Optional, set AVOID_LOOP_RUN to `'true'` to run a single command and exit afterwards (one-shot mode — required for CI and scripting). **By default the CLI is interactive**: it runs the command you pass (if any), then keeps reading further commands from a prompt, just like a REPL. Exit the interactive loop with `exit` / `quit`, the **ESC** key, or **CTRL-C**.

```
export AVOID_LOOP_RUN='true/false'
export AVOID_LOOP_RUN='true' # one-shot; unset or 'false' = interactive loop
Comment thread
coderabbitai[bot] marked this conversation as resolved.
```

- Optional, set SSI_WALLET_API, SSI_WALLET_ID, SSI_WALLET_DID to support v5 DDOs (assets using credentialSubject and SSI policy flows).
Expand Down Expand Up @@ -138,7 +162,10 @@ npm run cli <command> [options] <arguments>
#### Help Commands

- **General help:**
`npm run cli --help` or `npm run cli -h`
`npm run cli --help` or `npm run cli -h` (globally: `ocean-cli --help` / `ocean-cli -h`)

- **Version:**
`npm run cli --version` (globally: `ocean-cli --version`)

- **Command-specific help:**
`npm run cli help <command>`
Expand Down
Loading
Loading