peaq-os-cli 0.0.2__tar.gz

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 (34) hide show
  1. peaq_os_cli-0.0.2/PKG-INFO +611 -0
  2. peaq_os_cli-0.0.2/README.md +581 -0
  3. peaq_os_cli-0.0.2/pyproject.toml +77 -0
  4. peaq_os_cli-0.0.2/setup.cfg +4 -0
  5. peaq_os_cli-0.0.2/src/peaq_os_cli/__init__.py +67 -0
  6. peaq_os_cli-0.0.2/src/peaq_os_cli/commands/__init__.py +7 -0
  7. peaq_os_cli-0.0.2/src/peaq_os_cli/commands/activate.py +1846 -0
  8. peaq_os_cli-0.0.2/src/peaq_os_cli/commands/init_cmd.py +344 -0
  9. peaq_os_cli-0.0.2/src/peaq_os_cli/commands/qualify.py +387 -0
  10. peaq_os_cli-0.0.2/src/peaq_os_cli/commands/show.py +253 -0
  11. peaq_os_cli-0.0.2/src/peaq_os_cli/commands/wallet.py +438 -0
  12. peaq_os_cli-0.0.2/src/peaq_os_cli/commands/whoami.py +73 -0
  13. peaq_os_cli-0.0.2/src/peaq_os_cli/config.py +373 -0
  14. peaq_os_cli-0.0.2/src/peaq_os_cli/constants/__init__.py +29 -0
  15. peaq_os_cli-0.0.2/src/peaq_os_cli/constants/formatting.py +21 -0
  16. peaq_os_cli-0.0.2/src/peaq_os_cli/constants/patterns.py +12 -0
  17. peaq_os_cli-0.0.2/src/peaq_os_cli/enums/__init__.py +19 -0
  18. peaq_os_cli-0.0.2/src/peaq_os_cli/enums/env.py +37 -0
  19. peaq_os_cli-0.0.2/src/peaq_os_cli/enums/events.py +91 -0
  20. peaq_os_cli-0.0.2/src/peaq_os_cli/enums/exit_code.py +20 -0
  21. peaq_os_cli-0.0.2/src/peaq_os_cli/enums/network.py +19 -0
  22. peaq_os_cli-0.0.2/src/peaq_os_cli/errors.py +212 -0
  23. peaq_os_cli-0.0.2/src/peaq_os_cli/formatting.py +295 -0
  24. peaq_os_cli-0.0.2/src/peaq_os_cli/main.py +114 -0
  25. peaq_os_cli-0.0.2/src/peaq_os_cli/messages.py +124 -0
  26. peaq_os_cli-0.0.2/src/peaq_os_cli/networks.py +171 -0
  27. peaq_os_cli-0.0.2/src/peaq_os_cli/qr.py +145 -0
  28. peaq_os_cli-0.0.2/src/peaq_os_cli/utils.py +186 -0
  29. peaq_os_cli-0.0.2/src/peaq_os_cli.egg-info/PKG-INFO +611 -0
  30. peaq_os_cli-0.0.2/src/peaq_os_cli.egg-info/SOURCES.txt +32 -0
  31. peaq_os_cli-0.0.2/src/peaq_os_cli.egg-info/dependency_links.txt +1 -0
  32. peaq_os_cli-0.0.2/src/peaq_os_cli.egg-info/entry_points.txt +2 -0
  33. peaq_os_cli-0.0.2/src/peaq_os_cli.egg-info/requires.txt +18 -0
  34. peaq_os_cli-0.0.2/src/peaq_os_cli.egg-info/top_level.txt +1 -0
@@ -0,0 +1,611 @@
1
+ Metadata-Version: 2.4
2
+ Name: peaq-os-cli
3
+ Version: 0.0.2
4
+ Summary: Python CLI for peaqOS, the operating system for the machine economy — on-chain identity, credit rating, and omnichain infrastructure for robots and machines.
5
+ Author-email: peaqOS <info@peaq.xyz>
6
+ License: Apache-2.0
7
+ Project-URL: Homepage, https://www.peaq.xyz
8
+ Project-URL: Documentation, https://docs.peaq.xyz
9
+ Project-URL: Repository, https://github.com/peaqnetwork/peaq-os-cli-py
10
+ Project-URL: Issues, https://github.com/peaqnetwork/peaq-os-cli-py/issues
11
+ Keywords: peaq,peaqos,peaq-os,machine-economy,depin,robotics,ai-agents,blockchain,omnichain,peaqid,did,machine-nft,machine-tokenization,machine-credit-rating,mcr,cli,python
12
+ Requires-Python: >=3.10
13
+ Description-Content-Type: text/markdown
14
+ Requires-Dist: peaq_os_sdk>=0.0.1
15
+ Requires-Dist: click>=8.1
16
+ Requires-Dist: python-dotenv>=1.0
17
+ Requires-Dist: Pillow>=10.0
18
+ Requires-Dist: svglib>=0.9
19
+ Requires-Dist: reportlab>=4.0
20
+ Requires-Dist: eth-account<1.0,>=0.10
21
+ Provides-Extra: ows
22
+ Requires-Dist: open-wallet-standard>=1.3.2; extra == "ows"
23
+ Provides-Extra: dev
24
+ Requires-Dist: pytest; extra == "dev"
25
+ Requires-Dist: pytest-cov; extra == "dev"
26
+ Requires-Dist: mypy; extra == "dev"
27
+ Requires-Dist: ruff; extra == "dev"
28
+ Requires-Dist: black; extra == "dev"
29
+ Requires-Dist: flake8; extra == "dev"
30
+
31
+ # peaq-os-cli
32
+
33
+ Python CLI for peaqOS. Describes install and the console entry point.
34
+
35
+ ## Install
36
+
37
+ ```bash
38
+ python3 -m venv .peaq-os-cli
39
+ source .peaq-os-cli/bin/activate
40
+ pip install -e ".[dev]"
41
+ ```
42
+
43
+ ## Run Tests
44
+ ```
45
+ pytest
46
+ ```
47
+
48
+ ## Quality Gates
49
+ ```
50
+ ruff check src tests
51
+ black --check src tests
52
+ mypy src
53
+ pytest -q --cov=src/peaq_os_cli --cov-fail-under=90
54
+ flake8 src tests
55
+ ```
56
+
57
+ ## Console usage
58
+
59
+ The `peaqos` script invokes the Click root group in `peaq_os_cli.main`.
60
+
61
+ ```bash
62
+ peaqos --help
63
+ peaqos --version
64
+ ```
65
+
66
+ Authoritative option text for any subcommand is always available via built-in help:
67
+
68
+ ```bash
69
+ peaqos <command> -h
70
+ peaqos qualify event -h
71
+ peaqos qualify mcr -h
72
+ ```
73
+
74
+ ## Commands
75
+
76
+ ### `peaqos init`
77
+
78
+ Interactive wizard that writes a `.env` file in the current working directory.
79
+
80
+ ```bash
81
+ peaqos init # interactive (network, key, URLs, contract addresses)
82
+ peaqos init --non-interactive # read all values from environment variables
83
+ peaqos init --force # overwrite existing .env without confirmation
84
+ ```
85
+
86
+ **Example (interactive):**
87
+
88
+ ```
89
+ Network (mainnet, testnet) [mainnet]: mainnet
90
+ Private key source (paste, generate, wallet): generate
91
+ Address: 0xAbCd...1234
92
+ Key: 0xdeadbeef...
93
+ IMPORTANT: Save this private key securely. It will not be shown again.
94
+ RPC URL [https://peaq.api.onfinality.io/public]:
95
+ MCR API URL [https://mcr.peaq.xyz]:
96
+ Gas Station URL [https://depinstation.peaq.xyz]:
97
+ Event Registry address: 0xEe6f...78aB
98
+ Config: .env written to /home/operator/project/.env
99
+
100
+ Running whoami to verify...
101
+ Address : 0xAbCd...1234
102
+ Network : mainnet
103
+ RPC URL : https://peaq.api.onfinality.io/public
104
+ Chain ID: 3338
105
+ MCR API : https://mcr.peaq.xyz
106
+
107
+ Contracts:
108
+ IdentityRegistry: 0x9075...0B6A
109
+ IdentityStaking : 0x7d39...9B8E
110
+ EventRegistry : 0xEe6f...78aB
111
+ MachineNFT : 0xaF13...Bd61
112
+ DID Registry : 0x0000...0800
113
+ Batch Precompile: 0x0000...0805
114
+ ```
115
+
116
+ ### `peaqos whoami`
117
+
118
+ Show the active wallet address, network, chain ID, and all contract addresses.
119
+
120
+ ```bash
121
+ peaqos whoami
122
+ ```
123
+
124
+ **Example:**
125
+
126
+ ```
127
+ Address : 0xAbCd...1234
128
+ Network : mainnet
129
+ RPC URL : https://peaq.api.onfinality.io/public
130
+ Chain ID: 3338
131
+ MCR API : https://mcr.peaq.xyz
132
+
133
+ Contracts:
134
+ IdentityRegistry: 0x9075...0B6A
135
+ IdentityStaking : 0x7d39...9B8E
136
+ EventRegistry : 0xEe6f...78aB
137
+ MachineNFT : 0xaF13...Bd61
138
+ DID Registry : 0x0000...0800
139
+ Batch Precompile: 0x0000...0805
140
+ ```
141
+
142
+ ### `peaqos wallet`
143
+
144
+ Manage OWS (Open Wallet Standard) wallets in the local encrypted vault (`~/.ows/`).
145
+ Requires the optional OWS dependency: `pip install peaq-os-cli[ows]`.
146
+
147
+ ```
148
+ peaqos wallet create <name> [--words 12|24] [--json]
149
+ peaqos wallet import <name> (--mnemonic | --private-key-file <path>) [--index <n>] [--json]
150
+ peaqos wallet list [--json]
151
+ peaqos wallet show <name-or-id> [--json]
152
+ peaqos wallet export <name-or-id>
153
+ peaqos wallet delete <name-or-id>
154
+ peaqos wallet use <name-or-id>
155
+ ```
156
+
157
+ **`wallet create`** — Generate a new mnemonic-backed wallet. Displays addresses for all supported chains (peaq, Base, Ethereum, Solana, Bitcoin, Cosmos, etc.). The mnemonic is never shown; use `wallet export` to retrieve it.
158
+
159
+ ```bash
160
+ peaqos wallet create my-machine
161
+ peaqos wallet create my-machine --words 24 # 24-word mnemonic
162
+ peaqos wallet create my-machine --json # JSON output
163
+ ```
164
+
165
+ **`wallet import`** — Import an existing wallet from a BIP-39 mnemonic (hidden prompt) or a private key file.
166
+
167
+ ```bash
168
+ peaqos wallet import recovered --mnemonic
169
+ peaqos wallet import from-file --private-key-file ./operator.key
170
+ ```
171
+
172
+ **`wallet list`** — List all wallets in the vault. Shows Name, ID, peaq Address, Key Type, and Created date.
173
+
174
+ ```bash
175
+ peaqos wallet list
176
+ peaqos wallet list --json # full WalletInfo array
177
+ ```
178
+
179
+ **`wallet show`** — Display full wallet details with addresses for every supported chain family.
180
+
181
+ ```bash
182
+ peaqos wallet show operator
183
+ peaqos wallet show operator --json
184
+ ```
185
+
186
+ **`wallet export`** — Export the recovery phrase or private key (requires confirmation).
187
+
188
+ ```bash
189
+ peaqos wallet export my-machine
190
+ ```
191
+
192
+ **`wallet delete`** — Securely delete a wallet from the vault (requires confirmation).
193
+
194
+ ```bash
195
+ peaqos wallet delete my-machine
196
+ ```
197
+
198
+ **`wallet use`** — Set a wallet as the active default by writing `PEAQOS_OWS_WALLET` to `.env`. Subsequent commands use this wallet via `load_client()`.
199
+
200
+ ```bash
201
+ peaqos wallet use operator
202
+ ```
203
+
204
+ **Migration from raw keys:**
205
+
206
+ ```bash
207
+ peaqos wallet import my-operator --private-key-file ./operator.key
208
+ peaqos wallet use my-operator
209
+ peaqos whoami # address matches the original key
210
+ ```
211
+
212
+ ### `peaqos activate`
213
+
214
+ Run the full machine onboarding flow end-to-end. Six steps: balance check →
215
+ 2FA enrollment → gas-station funding → register on `IdentityRegistry` → mint
216
+ machine NFT → write DID attributes.
217
+
218
+ **Two modes:**
219
+
220
+ * **Self-managed** — no proxy flags. The caller's own key signs every step
221
+ and holds the resulting NFT.
222
+ * **Proxy-managed** — `--for <machine-address> --machine-key <path>`
223
+ together. The operator funds and submits register / mint on behalf of the
224
+ machine, then the machine key signs its own DID attributes (the peaq DID
225
+ precompile enforces `msg.sender == didAccount`). The machine EOA holds the
226
+ resulting NFT. Both flags are required together; supplying one alone is
227
+ rejected with exit `1`.
228
+
229
+ ```bash
230
+ peaqos activate # self mode
231
+ peaqos activate --for 0xMachine --machine-key ./m.key # proxy mode
232
+ ```
233
+
234
+ **Flags:**
235
+
236
+ | Flag | Purpose |
237
+ | ------------------ | --------------------------------------------------------------- |
238
+ | `--for` | Machine EOA address. Presence switches to proxy mode. |
239
+ | `--machine-key` | Path to a file with the machine's 0x-prefixed hex private key. |
240
+ | `--doc-url` | Documentation URL written to the machine DID. |
241
+ | `--data-api` | Raw data API URL written to the machine DID. |
242
+ | `--visibility` | `public` (default) / `private` / `onchain`. |
243
+ | `--skip-funding` | Skip balance check, 2FA, and gas-station funding (steps 1–3). |
244
+
245
+ Private keys **must** be supplied via file path (`--machine-key`). Inline
246
+ key flags are intentionally unsupported — reading from a file keeps the key
247
+ out of shell history and `ps` output.
248
+
249
+ **Environment:**
250
+
251
+ Connection / caller identity:
252
+
253
+ | Variable | Purpose |
254
+ | -------------------------- | -------------------------------------------------- |
255
+ | `PEAQOS_PRIVATE_KEY` | Operator private key (self or proxy mode caller). |
256
+ | `PEAQOS_NETWORK` | `mainnet` or `testnet`. |
257
+ | `PEAQOS_RPC_URL` | Override the default RPC endpoint for the network. |
258
+ | `PEAQOS_GAS_STATION_URL` | Gas-station base URL for steps 2–3. |
259
+
260
+ Contract addresses (all required — missing any yields exit `3`):
261
+
262
+ | Variable | Contract |
263
+ | ---------------------------- | -------------------------------------------------- |
264
+ | `IDENTITY_REGISTRY_ADDRESS` | `IdentityRegistry` (step 4 register). |
265
+ | `IDENTITY_STAKING_ADDRESS` | Identity staking contract. |
266
+ | `EVENT_REGISTRY_ADDRESS` | Event registry contract. |
267
+ | `MACHINE_NFT_ADDRESS` | Machine NFT (step 5 mint). |
268
+ | `DID_REGISTRY_ADDRESS` | DID registry contract. |
269
+ | `BATCH_PRECOMPILE_ADDRESS` | peaq batch precompile (step 6 batched DID writes). |
270
+
271
+ **Idempotent rerun.** Every mutating step does a read-before-write precheck:
272
+ registration consults `machineIdOfOwner`, mint consults `token_id_of` +
273
+ NFT `ownerOf`, DID writes consult `readAttribute`. Re-running `activate`
274
+ against on-chain state that is already complete submits no transactions
275
+ and exits `0`. A TOCTOU revert (`AlreadyRegistered` / `AlreadyExists`)
276
+ is also recovered as skip rather than surfaced as a network error.
277
+
278
+ **Proxy preconditions.** Proxy mode requires the operator to already be
279
+ registered on `IdentityRegistry` (i.e. have called `activate` in self mode
280
+ first). If not, the command fails with exit `2` (network/chain error)
281
+ before spending any gas.
282
+
283
+ **Output streams.** The final summary (Machine ID, Token ID, DIDs; plus
284
+ `Machine Address` and `Operator DID` in proxy mode) is written to `stdout`
285
+ so it can be piped / captured. Progress lines (`[1/6]`, `[2/6]`, …) and
286
+ per-step info/warning messages go to `stderr`. Integration tests assert on
287
+ `result.stdout`.
288
+
289
+ **Idempotency log.** Every step appends a JSONL entry to `./peaqos.log`
290
+ in the working directory with fields like `step`, `status`
291
+ (`pending` / `skipped` / `failed` / `confirmed`), `mode`, `machine_id`,
292
+ `tx_hash`, and (for DID writes) `machine_did_tx_count=6` /
293
+ `proxy_did_tx_count=2`. This file is both a resume marker for partial
294
+ failures and the audit trail.
295
+
296
+ **Example — first run (self mode):**
297
+
298
+ ```bash
299
+ $ peaqos activate > out.txt 2> err.txt ; echo "exit: $?"
300
+ exit: 0
301
+
302
+ $ cat out.txt
303
+ Machine activated successfully.
304
+ Machine ID: 42
305
+ Token ID: 11
306
+ Machine DID: did:peaq:0xDC5b20847F43d67928F49Cd4f85D696b5A7617B5
307
+
308
+ $ cat err.txt
309
+ [1/6] Balance check
310
+ Operator 0xDC5b...17B5: 1.0000 PEAQ (sufficient)
311
+ [2/6] 2FA enrollment - skipped (all wallets funded)
312
+ [3/6] Fund from Gas Station - skipped (all wallets funded)
313
+ [4/6] Register machine
314
+ Registered. machine_id=42
315
+ [5/6] Mint NFT
316
+ Minted NFT for machine_id=42 -> token_id=11 (tx 0xminttx...)
317
+ [6/6] Write DID attributes
318
+ Wrote 6 machine DID attributes (tx 0xdidtx...)
319
+ ```
320
+
321
+ **Example — rerun is a no-op (exit 0, no tx submitted):**
322
+
323
+ ```bash
324
+ $ peaqos activate 2>&1 1>/dev/null # stderr only, shows skip path
325
+ [1/6] Balance check
326
+ Operator 0xDC5b...17B5: 1.0000 PEAQ (sufficient)
327
+ [2/6] 2FA enrollment - skipped (all wallets funded)
328
+ [3/6] Fund from Gas Station - skipped (all wallets funded)
329
+ [4/6] Register machine
330
+ Already registered (machine_id=42). Skipping.
331
+ [5/6] Mint NFT
332
+ Already minted (token_id=11). Skipping.
333
+ [6/6] Write DID attributes
334
+ Machine DID attributes already on chain. Skipping.
335
+ ```
336
+
337
+ The stdout summary stays the same on rerun; only the stderr skip
338
+ messages and the `peaqos.log` entries flip from `confirmed` to `skipped`.
339
+
340
+ **Example — `peaqos.log` (JSONL, one line per step):**
341
+
342
+ ```jsonl
343
+ {"step":"register","status":"confirmed","mode":"self","address":"0xDC5b...","machine_id":42,"ts":"2026-04-23T15:00:18Z"}
344
+ {"step":"mint_nft","status":"confirmed","machine_id":42,"recipient":"0xDC5b...","token_id":11,"tx_hash":"0xminttx...","ts":"..."}
345
+ {"step":"machine_did","status":"confirmed","mode":"self","machine_id":42,"token_id":11,"operator_did":"","machine_did_tx_count":6,"tx_hash":"0xdidtx...","ts":"..."}
346
+ ```
347
+
348
+ On a rerun, the same three rows appear with `"status":"skipped"` and, for
349
+ the DID row, `"recovered_from":"AttributeAlreadyOnChain"`.
350
+
351
+
352
+ ### `peaqos show machine`
353
+
354
+ Display the full on-chain profile for a single machine DID — identity,
355
+ DID attributes, MCR snapshot, and recent event summary.
356
+
357
+ ```bash
358
+ peaqos show machine did:peaq:0x<40-hex>
359
+ peaqos show machine did:peaq:0x<40-hex> --json # raw JSON to stdout
360
+ ```
361
+
362
+ Example output:
363
+
364
+ ```
365
+ Machine: did:peaq:0x9a5F1E244c15e491Ae571c5bF77fDD836ddc37C5
366
+
367
+ Machine ID: 45
368
+ Operator : did:peaq:0x9Eea...641C
369
+
370
+ DID Attributes:
371
+ documentation_url: https://example.com/docs
372
+ data_visibility : public
373
+
374
+ MCR Snapshot:
375
+ Rating : B
376
+ Score : 31 / 100
377
+ Bond Status: bonded
378
+
379
+ Recent Events:
380
+ Total : 10
381
+ Last Event : 2026-04-20T14:30:00Z
382
+ Last Origin Value: 123
383
+ Last Currency : HKD
384
+ Last Subunit : 100
385
+ Last Status : ok
386
+ Last USD Value : 0.13
387
+ ```
388
+
389
+ When the most recent event is a revenue event, the block surfaces the
390
+ PRO-336 / PRO-334 FX fields. `Last USD Value` is rendered as USD
391
+ dollars (Decimal-quantised to 2 places — `usd_value=13` → `0.13`,
392
+ `usd_value=150` → `1.50`). When `amount_status` is
393
+ `"unsupported_currency"` or `"fx_unavailable"`, the `Last USD Value`
394
+ row shows `—` (em-dash) so the CLI never displays a misleading USD
395
+ number for a row whose FX state the server flagged as unreliable:
396
+
397
+ ```
398
+ Recent Events:
399
+ Total : 10
400
+ Last Event : 2026-04-20T14:30:00Z
401
+ Last Origin Value: 100
402
+ Last Currency : XYZ
403
+ Last Status : unsupported_currency
404
+ Last USD Value : —
405
+ ```
406
+
407
+ Activity events (eventType=1) omit all five FX lines.
408
+
409
+ ### `peaqos show operator machines`
410
+
411
+ List every machine managed by a given operator DID in a tabular summary
412
+ (`peaqID`, `Machine ID`, `MCR`, `Rating`).
413
+
414
+ ```bash
415
+ peaqos show operator machines did:peaq:0x<40-hex>
416
+ peaqos show operator machines did:peaq:0x<40-hex> --json # raw JSON to stdout
417
+ ```
418
+
419
+ Example output:
420
+
421
+ ```
422
+ Operator: did:peaq:0x9Eeab1aCcb1A701aEfAB00F3b8a275a39646641C
423
+ Machines: 3
424
+
425
+ peaqID Machine ID MCR Rating
426
+ ────────────────────────────────────────────────────────────────────────────
427
+ did:peaq:0x9a5F...37C5 45 31 B
428
+ did:peaq:0xAb3D...12F0 46 75 A
429
+ did:peaq:0xC12E...99B1 47 55 BB
430
+ ```
431
+
432
+ ### `peaqos qualify event`
433
+
434
+ Submit one machine event on-chain via the Event Registry (`submitEvent`).
435
+
436
+ #### Prerequisites
437
+
438
+ Configure `.env` in the CLI directory (or export the same variables): private key, RPC URL, and contract addresses. See `peaq_os_cli.config.load_client`.
439
+
440
+ #### Required flags
441
+
442
+ | Flag | Meaning |
443
+ |------|---------|
444
+ | `--machine-id` | Positive integer machine identity. |
445
+ | `--type` | `revenue` or `activity`. |
446
+ | `--value` | Non-negative integer **as ISO 4217 subunit** per PRO-334. **BREAKING**: pre-PRO-334 callers passed whole-currency amounts; the wire is now subunit. Example: `HK$1.23 → --value=123 --currency HKD`; `¥100 → --value=100 --currency JPY` (JPY has no minor unit). Partner is responsible for the conversion. |
447
+ | `--ts` | Event time: Unix seconds (digits only) or ISO 8601 with timezone (`Z` or `+hh:mm`). |
448
+
449
+ Use a timestamp **on or before** the chain's block time. If `--ts` is ahead of the network clock, the contract can revert with `FutureTimestamp`.
450
+
451
+ #### Common options
452
+
453
+ | Flag | Meaning |
454
+ |------|---------|
455
+ | `--trust` | `self` (default), `onchain`, or `hardware`. |
456
+ | `--source-chain` | `same`, `peaq`, or `base` (maps to a chain id for the SDK). |
457
+ | `--source-tx` | 32-byte tx hash (hex, `0x` optional). **Required** when `--trust` is `onchain`. |
458
+ | `--raw-data` | File path; file bytes are hashed and stored as the event data hash. |
459
+ | `--metadata` | File path; bytes are sent as on-chain metadata. |
460
+ | `--currency` | Per PRO-336 §6 — currency code for revenue events (e.g. `USD`, `HKD`, 3-10 uppercase alphanumeric chars). Activity events take `""`. **Omit** to use the SDK's smart default (`"USD"` for revenue, `""` for activity). |
461
+
462
+ #### Examples
463
+
464
+ ```bash
465
+ # Revenue event (self-reported trust, default source chain)
466
+ peaqos qualify event --machine-id 42 --type revenue --value 100 --ts 1735000000
467
+ ```
468
+
469
+ ```
470
+ Event submitted.
471
+ Machine ID: 42
472
+ Type: revenue
473
+ Value: 100
474
+ Trust: self-reported
475
+ Tx: 0x3f4a8c1e2d9b7f05a6c3e8d1f4b2a7c9e0d5f3b1a8e2c6d9f7b4a1e3c5d8f2b4
476
+ Data Hash: 0xa1b2c3d4e5f67890a1b2c3d4e5f67890a1b2c3d4e5f67890a1b2c3d4e5f67890
477
+ ```
478
+
479
+ ```bash
480
+ # Activity with ISO timestamp
481
+ peaqos qualify event --machine-id 42 --type activity --value 0 --ts "2026-04-22T12:00:00Z"
482
+
483
+ # On-chain-verified event with a source tx hash
484
+ peaqos qualify event --machine-id 42 --type revenue --value 200 --ts 1735000000 \
485
+ --trust onchain \
486
+ --source-tx 0xabcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890ab
487
+
488
+ # Attach a payload file (raw data is hashed on submit)
489
+ peaqos qualify event --machine-id 42 --type activity --value 0 --ts 1735000000 \
490
+ --raw-data ./sensor.bin
491
+ ```
492
+
493
+ ### `peaqos qualify mcr`
494
+
495
+ Look up a machine's **Machine Credit Rating (MCR)** from the MCR HTTP API.
496
+
497
+ #### Usage
498
+
499
+ ```text
500
+ peaqos qualify mcr <DID> [--json]
501
+ ```
502
+
503
+ - **`DID`** — Must match `did:peaq:0x` plus exactly 40 hex characters (checksum casing is allowed).
504
+ - **`--json`** — Print **only** JSON to stdout (pretty-printed, indent 2). No banner or prose. Useful for scripts.
505
+
506
+ In `--json` mode the object includes the SDK field **`mcr`** (rating label, e.g. `Provisioned`, `BBB`) and a duplicate key **`mcr_rating`** with the same string for tools that expect a `*_rating` field.
507
+
508
+ #### Examples
509
+
510
+ ```bash
511
+ # Human-readable block (rating, score, bond, events, trend, last updated)
512
+ peaqos qualify mcr did:peaq:0x9a5F1E244c15e491Ae571c5bF77fDD836ddc37C5
513
+ ```
514
+
515
+ ```
516
+ MCR for did:peaq:0x9a5F1E244c15e491Ae571c5bF77fDD836ddc37C5
517
+
518
+ Rating: A
519
+ Score: 82 / 100
520
+ Bond Status: bonded
521
+
522
+ Events:
523
+ Total: 150
524
+ Revenue: 120
525
+ Activity: 30
526
+
527
+ 30-Day Revenue: +12.5%
528
+ Last Updated: 2026-04-20T14:30:00Z
529
+ FX Degraded: no
530
+ ```
531
+
532
+ `FX Degraded: yes` (PRO-336 §S6 / PRO-331) means at least one event in the
533
+ scoring set used a degraded FX source (`stale_latest` /
534
+ `default_usd_fx_outage`). Use it to distinguish a conservative score caused
535
+ by FX outage from an empty-data machine when gating UI / alerts on data
536
+ quality.
537
+
538
+ ```bash
539
+ # Machine-readable JSON for jq / scripts
540
+ peaqos qualify mcr did:peaq:0x9a5F1E244c15e491Ae571c5bF77fDD836ddc37C5 --json
541
+ ```
542
+
543
+ ```json
544
+ {
545
+ "did": "did:peaq:0x9a5F1E244c15e491Ae571c5bF77fDD836ddc37C5",
546
+ "mcr": "A",
547
+ "mcr_rating": "A",
548
+ "mcr_score": 82,
549
+ "bond_status": "bonded",
550
+ "event_count": 150,
551
+ "revenue_event_count": 120,
552
+ "activity_event_count": 30,
553
+ "revenue_trend": "+12.5%",
554
+ "last_updated": 1745152200
555
+ }
556
+ ```
557
+
558
+ #### Typical failures
559
+
560
+ | Situation | Exit | What you see |
561
+ |-----------|------|----------------|
562
+ | Bad or empty DID | `1` | Validation message |
563
+ | No MCR row for that DID (HTTP 404) | `2` | `Machine not found` |
564
+ | API unavailable (HTTP 503) | `2` | `MCR API unavailable` |
565
+ | Other HTTP / RPC issues | `2` | Wrapped SDK or network message |
566
+
567
+ ## Errors
568
+
569
+ The CLI maps SDK and network exceptions to stable exit codes:
570
+
571
+ | Exit code | Meaning |
572
+ | --------- | ------------------------------------------------------------ |
573
+ | `0` | Success |
574
+ | `1` | User / validation error (bad input, cap, rate limit) |
575
+ | `2` | Network, RPC, or on-chain error (connection, HTTP, revert) |
576
+ | `3` | Configuration error (missing env vars, invalid private key) |
577
+
578
+ Subcommands funnel exceptions through `peaq_os_cli.errors.handle_sdk_error`,
579
+ which raises `click.ClickException` with the mapped exit code and a
580
+ user-friendly message. Known on-chain revert reasons and Faucet API error
581
+ codes are translated by `map_revert_reason` and `map_faucet_error`.
582
+
583
+ ## Output formatting
584
+
585
+ Subcommands render results through `peaq_os_cli.formatting` to keep human
586
+ output consistent across the CLI:
587
+
588
+ * `truncate_address` — shortens a hex address to `0x{first4}...{last4}`.
589
+ * `format_timestamp` — renders a Unix timestamp as ISO 8601 UTC, or `—` for
590
+ `None`.
591
+ * `format_key_value` — aligns `key: value` pairs so the colons line up.
592
+ * `format_table` — left-aligned columnar table with a header separator.
593
+ * `print_json` — writes `json.dumps(data, indent=2)` to stdout for
594
+ pipe-friendly output.
595
+ * `print_step` — writes `[{step}/{total}] {label}` progress lines to
596
+ stderr, suppressed when the active Click context is quiet.
597
+
598
+ ## Utilities
599
+
600
+ Input parsing and validation helpers in `peaq_os_cli.utils`:
601
+
602
+ * `parse_timestamp` — accepts pure-digit Unix seconds or ISO 8601 strings
603
+ with an explicit UTC offset (`...Z` or `...+HH:MM`). Raises
604
+ `click.BadParameter` on unrecognised input.
605
+ * `validate_did_format` — requires `did:peaq:0x` followed by 40 hex
606
+ characters.
607
+ * `validate_address_format` — requires a `0x`-prefixed 40-hex-character
608
+ address.
609
+ * `read_key_file` — reads, strips, and validates a `0x`-prefixed 64-hex
610
+ private key file. Raises `click.ClickException` with exit code `1` on
611
+ missing files or invalid content.