Skip to content

Commit f545e0b

Browse files
committed
Merge branch 'feature_migrate_to_unauthenticated_client' into 'main'
feat(reads): use the SDK's unauthenticated client for public reads See merge request mobilex/web3/OKOutcomes!23
2 parents c565719 + bfe40eb commit f545e0b

11 files changed

Lines changed: 281 additions & 241 deletions

File tree

skills/okx-outcomes-market/SKILL.md

Lines changed: 10 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -31,36 +31,15 @@ markets, candles, CLOB quotes / book, public WebSocket streams.
3131
If missing: `cargo install --locked --path .`
3232
or download the prebuilt binary.
3333

34-
2. **Credentials configured** (required for `clob` reads and anything
35-
touching account state; `data trending`-class public endpoints work
36-
without):
37-
```bash
38-
# clob reads need an OAuth session (brokered by okx-auth); config from config.json
39-
bash skills/okx-outcomes-market/scripts/preflight.sh | jq -r '.ready_for.clob_reads'
40-
```
41-
(Richer detail, optional — emits `ready_for.clob_reads`:
42-
`bash "${CLAUDE_PLUGIN_ROOT:-.}/skills/okx-outcomes-market/scripts/preflight.sh"`.)
43-
If `false`, route the user to the `okx-outcomes-setup` skill, which owns
44-
onboarding: it detects the missing piece and walks the user through
45-
region (Global / US) → OAuth sign-in → EOA wallet binding (one step at a
46-
time, IM-friendly). It ultimately drives the interactive `okx-outcomes
47-
setup` wizard / per-step commands in the user's own terminal — that
48-
wizard auto-generates a fresh EIP-712 signing wallet (private key never
49-
displayed) and lands credentials in the OS keyring (with an AES-256-GCM
50-
encrypted file fallback at `~/.okx-outcomes/keyring.enc`).
51-
52-
3. **OAuth session** (required for `clob` reads; the `account` and
53-
private-ws commands that also need it live in the `okx-outcomes-trade`
54-
skill):
55-
- Established by `okx-outcomes setup` (or a standalone
56-
`okx-outcomes auth login`); the token is brokered by `okx-auth` and
57-
never displayed. This OAuth bearer token is the only account-auth
58-
path — there is no HMAC.
59-
- Public endpoints (`data` / `search` / public `ws`) work without
60-
any authentication at all.
61-
- See `references/env-vars.md`.
62-
63-
4. **Corporate proxy**: if the user mentions VPN / firewall, add
34+
2. **No credentials needed.** Every command in this skill — `data`,
35+
`search`, `clob` reads (price / midpoint / spread / book), and public
36+
`ws` streams — hits **public, unauthenticated** endpoints, so there is
37+
nothing to set up here and no sign-in to gate on. (Account state and
38+
signed writes *do* require auth, but those live in the
39+
`okx-outcomes-trade` skill — route there for "my balance" / orders /
40+
placing or cancelling trades.)
41+
42+
3. **Corporate proxy**: if the user mentions VPN / firewall, add
6443
`--proxy <URL>`.
6544

6645
One-shot helper: `bash skills/okx-outcomes-market/scripts/preflight.sh`
@@ -101,7 +80,7 @@ unset unless the user explicitly asks about it.
10180
| candles / K-line | `$P data candles <assetId> [--bar 1m\|5m\|15m\|1H\|4H\|1D] [--limit 100] [--after <ms>] [--before <ms>] -j` |
10281
| search events | `$P search <keyword> [--cursor ...] [--limit 20] -j` |
10382

104-
### CLOB reads (OAuth auth, but read-only market data)
83+
### CLOB reads (public, no auth read-only market data)
10584

10685
`assetId` is the YES-outcome asset id; pass `--outcome no` (or `--no`)
10786
for the NO side (derived as `1 - yes`).

skills/okx-outcomes-market/references/cli-reference.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -119,8 +119,8 @@ $P data candles 101664000 --bar 1H --after 1779462000000 -j
119119
120120
## CLOB — Read-only
121121

122-
CLOB read commands authenticate with the OAuth bearer token (brokered by
123-
`okx-auth`), but return only public market data (quotes / depth). They're
122+
CLOB read commands need **no authentication** — they hit public market-data
123+
endpoints (quotes / depth) via the SDK's unauthenticated client. They're
124124
grouped here because they're a price-discovery tool.
125125

126126
`assetId` is the YES-outcome asset id; pass `--outcome no` (or `--no`)

skills/okx-outcomes-market/scripts/preflight.sh

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,11 @@
77
# (or a file-stat fallback if the binary or subcommand is unavailable)
88
# - ready_for: public_read / clob_reads / public_ws
99
#
10-
# Auth model: account reads / CLOB reads use an OAuth bearer token brokered
11-
# by `okx-auth` (no HMAC). The signing key lives in the OS keyring. Config
12-
# lives in `~/.okx-outcomes/config.json`. There are no `PREDICTIONS_*` env
13-
# overrides anymore, so this script does not probe them.
10+
# Auth model: this skill's commands (data / search / CLOB reads / public WS)
11+
# need NO auth — they hit public endpoints via the SDK's unauthenticated
12+
# client. (Account reads / private WS, in the trade skill, use an OAuth bearer
13+
# token brokered by `okx-auth`.) Config lives in `~/.okx-outcomes/config.json`.
14+
# There are no `PREDICTIONS_*` env overrides, so this script does not probe them.
1415
#
1516
# Probing strategy: prefer the CLI's own `auth status` subcommand — it owns
1617
# the credential resolution logic and sees OS-keyring/OAuth-broker state that
@@ -91,7 +92,7 @@ cat <<EOF
9192
},
9293
"ready_for": {
9394
"public_read": $bin_present,
94-
"clob_reads": $( $bin_present && [ "$account_read_ready" = "true" ] && echo true || echo false ),
95+
"clob_reads": $bin_present,
9596
"public_ws": $bin_present
9697
}
9798
}

src/app.rs

Lines changed: 45 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -243,39 +243,32 @@ async fn cmd_status(args: &[String], json: bool) {
243243
if json {
244244
let mut result = serde_json::Map::new();
245245
let mut failed = false;
246-
// Events check (requires auth - all REST endpoints do)
247-
match super::util::require_auth(args) {
248-
Ok(client) => {
249-
let start = std::time::Instant::now();
250-
match client
251-
.get_events(None, None, None, None, None, None, None)
252-
.await
253-
{
254-
Ok(resp) => {
255-
result.insert(
256-
"events".into(),
257-
serde_json::json!({
258-
"ok": true,
259-
"count": resp.events.len(),
260-
"latency_ms": start.elapsed().as_millis() as u64,
261-
}),
262-
);
263-
}
264-
Err(e) => {
265-
failed = true;
266-
let e = e.to_string();
267-
result.insert(
268-
"events".into(),
269-
serde_json::json!({"ok": false, "error": e}),
270-
);
271-
}
246+
// Events check — public endpoint, no auth needed.
247+
{
248+
let client = super::util::public_client();
249+
let start = std::time::Instant::now();
250+
match client
251+
.get_events(None, None, None, None, None, None, None)
252+
.await
253+
{
254+
Ok(resp) => {
255+
result.insert(
256+
"events".into(),
257+
serde_json::json!({
258+
"ok": true,
259+
"count": resp.events.len(),
260+
"latency_ms": start.elapsed().as_millis() as u64,
261+
}),
262+
);
263+
}
264+
Err(e) => {
265+
failed = true;
266+
let e = e.to_string();
267+
result.insert(
268+
"events".into(),
269+
serde_json::json!({"ok": false, "error": e}),
270+
);
272271
}
273-
}
274-
Err(e) => {
275-
result.insert(
276-
"events".into(),
277-
serde_json::json!({"ok": false, "error": e}),
278-
);
279272
}
280273
}
281274
// Balance check
@@ -320,31 +313,27 @@ async fn cmd_status(args: &[String], json: bool) {
320313
return;
321314
}
322315

323-
// Table mode (requires auth - all REST endpoints do)
324-
match super::util::require_auth(args) {
325-
Ok(client) => {
326-
let start = std::time::Instant::now();
327-
match client
328-
.get_events(None, None, None, None, None, None, None)
329-
.await
330-
{
331-
Ok(resp) => {
332-
let ms = start.elapsed().as_millis();
333-
println!(
334-
" {} {} events, {}ms",
335-
"OK".with(Color::Green),
336-
resp.events.len(),
337-
ms
338-
);
339-
}
340-
Err(e) => {
341-
super::util::mark_failed();
342-
println!(" {} {e}", "FAIL".with(Color::Red));
343-
}
316+
// Table mode — events is a public endpoint (no auth needed).
317+
{
318+
let client = super::util::public_client();
319+
let start = std::time::Instant::now();
320+
match client
321+
.get_events(None, None, None, None, None, None, None)
322+
.await
323+
{
324+
Ok(resp) => {
325+
let ms = start.elapsed().as_millis();
326+
println!(
327+
" {} {} events, {}ms",
328+
"OK".with(Color::Green),
329+
resp.events.len(),
330+
ms
331+
);
332+
}
333+
Err(e) => {
334+
super::util::mark_failed();
335+
println!(" {} {e}", "FAIL".with(Color::Red));
344336
}
345-
}
346-
Err(e) => {
347-
println!(" {} events: {e}", "SKIP".with(Color::Yellow));
348337
}
349338
}
350339

src/clob_cmds.rs

Lines changed: 6 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ use okx_outcomes_sdk::signing::{
6262
};
6363

6464
use super::format;
65-
use super::util::{extract_flag, require_auth, resolve_signing_key};
65+
use super::util::{extract_flag, public_client, require_auth, resolve_signing_key};
6666

6767
pub(crate) const MARKET_TYPE_PREDICTION: &str = "prediction";
6868
pub(crate) const ACTION_TYPE_PLACE_ORDER: &str = "placeOrder";
@@ -233,13 +233,7 @@ async fn cmd_price(_positional: &[&str], args: &[String], json: bool) {
233233
return;
234234
}
235235
};
236-
let client = match require_auth(args) {
237-
Ok(c) => c,
238-
Err(e) => {
239-
print_err(&e);
240-
return;
241-
}
242-
};
236+
let client = public_client();
243237
match client.get_ticker(asset_id).await {
244238
Ok(t) => {
245239
let view = derive_ticker_for_outcome(&t, outcome);
@@ -341,13 +335,7 @@ async fn run_batch_query<T, F>(
341335
print_err(usage);
342336
return;
343337
}
344-
let client = match require_auth(args) {
345-
Ok(c) => c,
346-
Err(e) => {
347-
print_err(&e);
348-
return;
349-
}
350-
};
338+
let client = public_client();
351339

352340
let fetches = ids.iter().map(|&id| {
353341
let client = &client;
@@ -630,13 +618,7 @@ async fn cmd_midpoint(_positional: &[&str], args: &[String], json: bool) {
630618
return;
631619
}
632620
};
633-
let client = match require_auth(args) {
634-
Ok(c) => c,
635-
Err(e) => {
636-
print_err(&e);
637-
return;
638-
}
639-
};
621+
let client = public_client();
640622
match client.get_ticker(asset_id).await {
641623
Ok(t) => {
642624
let view = derive_ticker_for_outcome(&t, outcome);
@@ -713,13 +695,7 @@ async fn cmd_spread(_positional: &[&str], args: &[String], json: bool) {
713695
return;
714696
}
715697
};
716-
let client = match require_auth(args) {
717-
Ok(c) => c,
718-
Err(e) => {
719-
print_err(&e);
720-
return;
721-
}
722-
};
698+
let client = public_client();
723699
match client.get_ticker(asset_id).await {
724700
Ok(t) => {
725701
let view = derive_ticker_for_outcome(&t, outcome);
@@ -821,13 +797,7 @@ async fn cmd_book(_positional: &[&str], args: &[String], json: bool) {
821797
return;
822798
}
823799
};
824-
let client = match require_auth(args) {
825-
Ok(c) => c,
826-
Err(e) => {
827-
print_err(&e);
828-
return;
829-
}
830-
};
800+
let client = public_client();
831801
match client.get_pm_books(asset_id, Some(sz)).await {
832802
Ok(book) => {
833803
let view = derive_book_for_outcome(&book, outcome);

0 commit comments

Comments
 (0)