Skip to content

Accept base58 signers + support delegate (API) keys - #16

Merged
0xtristan merged 35 commits into
masterfrom
feat/base58-delegate-signers
Jun 23, 2026
Merged

Accept base58 signers + support delegate (API) keys#16
0xtristan merged 35 commits into
masterfrom
feat/base58-delegate-signers

Conversation

@0xtristan

@0xtristan 0xtristan commented Jun 18, 2026

Copy link
Copy Markdown
Collaborator

Why

Two UX gaps made the starter repo hard to use with real Bullet wallets:

  1. Keys had to be hex. Bullet's delegation export and Phantom both hand you a base58 secret, so users had to convert by hand.
  2. Delegate (API) signer keys broke on startup. A delegate wallet has no account of its own — all balances/positions/orders live on the master account. The adapter queried account data and subscribed to the user-orders stream using the signer's own address, so every account read failed with a delegate key. (Trading itself works — the exchange routes a delegate's signed orders to the master server-side; only the read path was broken.)

Plus: there was no from-scratch onboarding guide for the recommended real-usage path (bring your own wallet → deposit via UI → trade with a scoped delegate).

What changed

Base58 keys

  • New keypair_from_secret in the Bullet adapter auto-detects hex vs base58 (handles Phantom/Solana 64-byte exports and 32-byte seeds).
  • Canonical config key private_key / env BB_BULLET_PRIVATE_KEY (accept base58 or hex). Breaking change: the old private_key_hex / BB_BULLET_PRIVATE_KEY_HEX names (and the Hyperliquid *_HEX names) are removed — there are no back-compat aliases (intentional, see the breaking-changes note below).

Delegate support

  • At connect time the adapter resolves the signer to its account address via GET /api/v1/delegateOf (200 → master parent; 404 → not a delegate → self).
  • Account reads (account_balance/account_info/query_open_orders) and the user_orders subscription now target the resolved master address. Transaction signing is unchanged — it still uses the delegate keypair.
  • deposit stays signer-only (delegates can't deposit); flatten/observe get delegate resolution for free via the shared connect path.

Docs

  • README "Trading from your own wallet" walkthrough + "what are delegate/API wallets" note, AGENTS.md key-resolution update, .env.example, and links to Bullet's machine-readable API docs. Example configs updated to the canonical env name.

Verification

  • New unit tests: hex / base58-32 / base58-64 all resolve to the same address; delegateOf mapping (200→parent, 404→self, 500→error).
  • Full suite green (128/128), cargo clippy --all-targets clean, cargo +nightly fmt --check clean.

Notes / follow-ups

  • Hyperliquid is docs-only here. HL API/agent wallets likely need the same master-address resolution for info queries — flagged as a follow-up, not implemented.
  • delegateOf's expiresAt/flags are logged but not enforced.

🤖 Generated with Claude Code


Summary by cubic

Adds base58 Bullet key support, master-account reads for delegate/API wallets, auto-loads .env, and a testnet faucet command. Improves Hyperliquid handling, funding‑arb safety (including shutdown cleanup), and adds graceful SIGTERM shutdown.

  • New Features

    • Keys and env: private_key accepts Bullet base58 (or hex) and Hyperliquid hex; key_file points to a file containing that string. Resolver prefers key_fileprivate_key; empty env values are ignored. .env auto-loads from ./.env (override with --env-file); real env vars win. keygen writes a base58 secret to ~/.config/bullet/id.key (0600).
    • Bullet delegates: resolve signer → master via /api/v1/delegateOf with transient retries (5xx/429); 404 or 400 “is not a delegate” → self. Reads and user_orders subscribe to the master; orders are signed by the delegate. Logs include signer and account.
    • Hyperliquid API wallets: add account_address (BB_HYPERLIQUID_ACCOUNT_ADDRESS) to read from the main account when using an API/agent key. Detect unified accounts via userAbstraction (with retries; warn on failure) and read collateral from spot (available = total - hold). Round order prices to 5 significant figures and normalize cloid formats so fills map to original client IDs. Add key_file/BB_HYPERLIQUID_KEY_FILE.
    • CLI and safety: bb-bot faucet funds the testnet wallet (sets a browser User‑Agent; suggests the web faucet on 4xx). flatten cancels and closes positions on Bullet and Hyperliquid when creds are set, and skips unconfigured venues. Funding‑arb flattens any filled leg on partial entry, caps the close to order_size, and only goes Flat when cleanup is confirmed; otherwise it requests shutdown. On shutdown (SIGTERM/Ctrl‑C), emergency flatten reads live exchange positions (not internal inventory), caps closes to order_size, and logs MANUAL INTERVENTION if a remainder/failure is detected.
    • Security: bumped transitive quinn-proto to 0.11.15 to address RUSTSEC‑2026‑0185.
  • Migration

    • Bullet: use private_key/BB_BULLET_PRIVATE_KEY (base58 preferred; hex still parses). private_key_hex/BB_BULLET_PRIVATE_KEY_HEX are removed. keygen now creates a base58 key file (id.key), not a JSON keystore. Delegates cannot deposit; use a master key file or non‑delegate key for deposit. Ensure network matches where the delegate was created.
    • Hyperliquid: use private_key/BB_HYPERLIQUID_PRIVATE_KEY (hex) or key_file/BB_HYPERLIQUID_KEY_FILE. When using an API/agent wallet, set account_address (or BB_HYPERLIQUID_ACCOUNT_ADDRESS); leave unset only if using your main wallet key. Ensure network matches your account’s network.

Written for commit 0f03852. Summary will update on new commits.

Review in cubic

0xtristan and others added 12 commits June 18, 2026 15:07
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- BulletConfig: update item 3 to mention "private_key" (alias
  "private_key_hex") accepting hex or base58. Update item 4 to mention
  "BB_BULLET_PRIVATE_KEY" (env preferred) and "BB_BULLET_PRIVATE_KEY_HEX"
  (alias/fallback).
- load_deposit_keypair doc: mention BB_BULLET_PRIVATE_KEY is tried first,
  then BB_BULLET_PRIVATE_KEY_HEX as fallback.
- bullet_config_from_env doc: same — BB_BULLET_PRIVATE_KEY (preferred) or
  BB_BULLET_PRIVATE_KEY_HEX (fallback).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Replace unwrap_or_default() with proper error handling to avoid silently
masking body-read failures. Mark the error as retryable to match network-error
classification of the .send() call above.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…-precedence doc comment

Updated all example configs to reference BB_BULLET_PRIVATE_KEY (accepts base58 or hex) instead of the stale BB_BULLET_PRIVATE_KEY_HEX alias. Fixed doc comment on bullet_config_from_env to correctly state the env var precedence: BB_BULLET_KEY_FILE wins, then the key-string env vars, then the default keystore.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Comment thread crates/bb-bot/src/main.rs

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

4 issues found across 20 files

Reply with feedback, questions, or to request a fix.

Re-trigger cubic

Comment thread crates/exchanges/bullet/src/delegate.rs Outdated
Comment thread crates/bb-bot/src/main.rs Outdated
Comment thread README.md Outdated
Comment thread crates/bb-bot/src/main.rs
0xtristan and others added 8 commits June 18, 2026 22:07
… README clarity

Addresses automated PR review (cubic + Cursor Bugbot):
- main.rs: treat empty BB_BULLET_PRIVATE_KEY as absent (don't shadow the
  _HEX alias); drop stale empty private_key_hex before inserting the
  private_key alias so serde doesn't see a duplicate field. Shared
  bullet_key_from_env() helper across the three resolution sites.
- delegate.rs: classify delegateOf 5xx/429 as retryable.
- README: separate the BB_BULLET_PRIVATE_KEY key-string from the
  BB_BULLET_KEY_FILE keystore-path so the path isn't mistaken for a value.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
A HL API wallet has no account of its own — positions, balances, and fills
live on the master account. The adapter read everything (user_state,
open_orders, UserFills/OrderUpdates) from the agent's own address, so API
wallets silently broke position tracking. Mirrors the Bullet delegate fix.

- HyperliquidConfig: add optional account_address (env
  BB_HYPERLIQUID_ACCOUNT_ADDRESS).
- connection.rs: resolve the read/subscription address (configured master, else
  the signer's own address); sign with the agent wallet and vault_address: None,
  matching the SDK's approve_agent pattern. Unit-tested resolver.
- main.rs: merge BB_HYPERLIQUID_ACCOUNT_ADDRESS into the HL config (config wins,
  empty env treated as absent).
- docs: README/AGENTS/.env.example — API-wallet setup, and clarify the bot does
  not auto-load .env (export vars or source it; prefer a Bullet keystore file).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
A delegate key pointed at the wrong network 404s on delegateOf and is
silently treated as its own account, leading to opaque 'account not found'
failures downstream. Log at resolution time whether the signer resolved to
itself (with a network-mismatch hint) or to a master, so the failure mode is
diagnosable.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
… in funding-arb example

The funding-arb example wires both venues but its Hyperliquid comment only
mentioned the signing key, so a user with an API wallet would miss the
account_address and hit empty reads. Also note that each venue's network must
match where the delegate/account lives.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
… or mainnet)

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Symmetric with the Bullet delegate hint: when account_address is unset, an
API/agent wallet would silently read empty state from its own address. Log at
connect time whether reads target the signer's own address (with a hint to set
BB_HYPERLIQUID_ACCOUNT_ADDRESS) or a configured master.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The live mainnet/testnet delegateOf returns HTTP 400 (not the spec'd 404) for a
non-delegate address, with an 'is not a delegate' message. The previous code
treated 400 as a hard error, so a normal main-wallet key would abort the bot at
startup. Resolve to self on 404 OR 400-with-'is not a delegate'; a 400 for a
malformed address ('invalid address') stays a real error. Caught by an e2e
smoke against the live endpoint.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Breaking changes (no back-compat aliases):
- Bullet: canonical env BB_BULLET_PRIVATE_KEY, config field `private_key`
  (was private_key_hex). Key string is base58 (Phantom/delegation export);
  hex still parses.
- Hyperliquid: canonical env BB_HYPERLIQUID_PRIVATE_KEY, config field
  `private_key` (was private_key_hex/_HEX).
- keygen now writes a base58 secret to a 0600 file (default ~/.config/bullet/
  id.key) instead of a Solana JSON keystore; key_file means "file containing a
  base58/hex key string" and is read via keypair_from_secret.
- New bullet key helpers: generate_base58(), keypair_from_key_file(). Adds
  getrandom dep (no secret accessor on the SDK Keypair).

Standard: paste the key exactly as the venue's UI gives it — base58 for Bullet,
hex (0x) for Hyperliquid. Docs/examples/.env.example updated throughout.
Verified end-to-end on testnet: keygen→key_file→connect→delegateOf round-trips.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Comment thread crates/bb-bot/src/main.rs

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

3 issues found across 18 files (changes from recent commits).

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="crates/exchanges/hyperliquid/src/config.rs">

<violation number="1" location="crates/exchanges/hyperliquid/src/config.rs:18">
P1: Renamed `private_key_hex` to `private_key` without backward-compatible serde alias, silently breaking existing TOML configs</violation>
</file>

<file name="crates/exchanges/bullet/src/config.rs">

<violation number="1" location="crates/exchanges/bullet/src/config.rs:32">
P1: Missing `alias = "private_key_hex"` on renamed config field breaks backward compatibility</violation>
</file>

<file name="crates/bb-bot/src/main.rs">

<violation number="1" location="crates/bb-bot/src/main.rs:539">
P2: New `keypair_from_key_file` and path change break old JSON keystores</violation>
</file>

Tip: Review your code locally with the cubic CLI to iterate faster.

Re-trigger cubic

Comment thread crates/exchanges/hyperliquid/src/config.rs
Comment thread crates/exchanges/bullet/src/config.rs
Comment thread crates/bb-bot/src/main.rs
Standardizes key management so the surface is identical on every venue and the
typical path (paste exported strings into .env, run) just works:

- Auto-load ./.env at startup via dotenvy; --env-file <path> override; real env
  vars take precedence. Removes the manual source-then-run step.
- bb_core::keys::resolve_key_string: one shared key-file→inline resolver both
  adapters call (file preferred, then inline string). read_key_file unifies the
  file-read path. Unit-tested.
- Hyperliquid gains key_file / BB_HYPERLIQUID_KEY_FILE, matching Bullet — closes
  the file/env asymmetry.
- Docs/.env.example lead with the env-string path (base58 Bullet, hex HL) and
  reflect that .env is now auto-loaded; key file documented as the secret-off-
  the-env alternative.

Verified on testnet: .env auto-load → key_file → connect round-trips.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Comment thread crates/bb-bot/src/main.rs

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

3 issues found across 13 files (changes from recent commits).

Tip: Review your code locally with the cubic CLI to iterate faster.

Re-trigger cubic

Comment thread crates/bb-bot/src/main.rs Outdated
Comment thread crates/bb-core/src/keys.rs Outdated
Comment thread crates/bb-bot/src/main.rs Outdated
0xtristan and others added 3 commits June 21, 2026 16:00
…unts

HL 'unified account' mode pools collateral in the spot balance; the perp
clearinghouse only reports per-position isolated margin. Our get_balances read
the perp clearinghouse, so it under-reported a unified account's collateral
(e.g. $2 of margin-in-use instead of ~$997 of buying power).

- Detect unified mode at connect via the userAbstraction info endpoint (raw
  request through the SDK's http client; SDK 0.6 has no typed method).
- HyperliquidBroker.get_balances branches: unified → user_token_balances
  (spotClearinghouseState), available = total - hold; standard → perp
  clearinghouse (prior behavior). Positions still read from the perp
  clearinghouse, which reports them in both modes.
- convert::spot_state_to_balances maps the spot balances; extracted
  subscribe_feeds to keep connect() under the line limit. Unit tests for the
  detection parser and the spot-balance mapping.

Confirmed live on testnet: userAbstraction returns 'unifiedAccount'; spot shows
~997 USDC vs ~$2 perp accountValue.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…leg on partial entry

Two bugs found by a live testnet placement test:

1. HL rejected orders with 'Order has invalid price' because the adapter sent
   the raw price as limit_px. HL perps allow at most 5 significant figures, so
   an aggressive IoC price like 64710.599 (6 sig figs) was rejected. Add
   convert::hl_round_price (round_sf(5)) and apply it in place_orders + amend.

2. funding-arb's incomplete-entry handler only cancelled orders and went Flat —
   but an aggressive (IoC) leg that already filled was orphaned (and, being
   'Flat', it would re-enter and accumulate). Now flatten_filled_leg queries the
   live exchange position (internal inventory lags the async fill event) and
   closes any filled leg reduce-only before going Flat.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
flatten was Bullet-only, so a delta-neutral funding-arb position could leave the
HL leg open with no CLI to close it. Extract flatten_broker (generic over
Broker) and run it for Bullet and, when HL env is set, Hyperliquid
(hyperliquid_config_from_env). Used this to close an orphaned HL test leg.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
HL echoes cloids on fills/order-updates as '0x'+32 hex (no hyphens), but the
client-id map was keyed by Uuid::to_string() (hyphenated). So original_client_id
missed, fills came back with an unmapped client_id, and strategies discarded
their own HL fills as 'external' — leaving inventory at 0 (funding-arb never
confirmed entry; emergency_flatten missed the HL leg). normalize_cloid parses
0x/simple/hyphenated to the canonical Uuid string before lookup. Round-trip test
now exercises the actual HL wire format.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Comment thread crates/bb-bot/src/main.rs Outdated
Comment thread crates/bb-core/src/keys.rs
Comment thread crates/strategies/funding-arb/src/strategy.rs Outdated

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

5 issues found across 5 files (changes from recent commits).

Tip: Review your code locally with the cubic CLI to iterate faster.

Re-trigger cubic

Comment thread crates/strategies/funding-arb/src/strategy.rs Outdated
Comment thread crates/exchanges/hyperliquid/src/connection.rs
Comment thread crates/exchanges/hyperliquid/src/convert.rs
Comment thread crates/strategies/funding-arb/src/strategy.rs Outdated
Comment thread crates/bb-bot/src/main.rs Outdated
enable_signal_shutdown only awaited tokio::signal::ctrl_c() (SIGINT), so a
SIGTERM — what docker stop, systemd, and Kubernetes send — bypassed graceful
wind_down and left positions open (no emergency_flatten). wait_for_shutdown_signal
now selects over Ctrl-C and (on Unix) SIGTERM, so a managed shutdown runs
wind_down to completion. Verified on testnet: SIGTERM with an open delta-neutral
funding-arb position now triggers emergency_flatten and closes both legs.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@cubic-dev-ai

cubic-dev-ai Bot commented Jun 22, 2026

Copy link
Copy Markdown

You're iterating quickly on this pull request. To help protect your rate limits, cubic has paused automatic reviews on new pushes for now—when you're ready for another review, comment @cubic-dev-ai review.

From automated review of the placement-test fixes:
- flatten: skip a venue gracefully if its keys aren't configured (was: always
  required Bullet keys, so an HL-only setup failed at the Bullet connect).
- keys: treat an empty key_file path as absent so it falls back to the inline
  key; filter empty BB_BULLET_KEY_FILE in load_deposit_keypair /
  bullet_config_from_env (the run path is covered by resolve_key_string).
- funding-arb incomplete entry: only go Flat if cleanup is confirmed; otherwise
  request shutdown + MANUAL INTERVENTION rather than pretending to be flat while
  a leg may be open.
- funding-arb flatten_filled_leg: cap the close to order_size so a larger
  pre-existing position on a shared wallet isn't disturbed.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Comment thread crates/bb-bot/src/main.rs
0xtristan and others added 2 commits June 22, 2026 23:51
Completes the empty-key-file handling: load_config no longer inserts an empty
key_file path (from BB_BULLET_KEY_FILE= / BB_HYPERLIQUID_KEY_FILE=) into the
exchange table, so an empty env var can't shadow the inline key.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…ME around testing vs production

The testnet faucet host rejects requests without a browser User-Agent
("Forbidden"), so the curl that keygen printed (and the README documented)
failed for a fresh user. Print/document it with -H "User-Agent: Mozilla/5.0".

README onboarding reframed: 'Quick start — testing (testnet)' leads with the
keygen→faucet→deposit→run path (no wallet/UI, the recommended way to try it);
'Production (mainnet)' covers delegate/API wallets with an explicit warning not
to run mainnet with a keygen burner. Verified the full testnet path end-to-end
on a fresh burner: keygen → faucet → deposit → run (places orders) → flatten.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Comment thread crates/bb-bot/src/main.rs
0xtristan and others added 4 commits June 23, 2026 13:44
Replaces the copy-paste curl in the quick start. Resolves the address from the
same key material as deposit and calls the testnet faucet with a browser
User-Agent. The faucet is Cloudflare-protected and rate-limited, so on a 4xx the
command prints a clear pointer to the web faucet (https://app.testnet.bullet.xyz)
rather than a raw error. keygen and the README now lead with this command.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
… capped)

Adds MockBroker.set_positions and a test for the asymmetric incomplete-entry
path: one leg fills, the other is rejected. Asserts the filled leg is flattened
reduce-only and the close is capped to order_size (so a larger pre-existing
position on a shared wallet isn't disturbed) — covering the path that was only
reasoned about before.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
cargo-audit flagged RUSTSEC-2026-0185 (quinn-proto < 0.11.15: remote memory
exhaustion via unbounded out-of-order stream reassembly). quinn-proto is a
transitive dep via reqwest's HTTP/3 stack (unused here). 0.11.15 is the patched
version and is within reqwest's range, so a lockfile bump clears it.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- main.rs: load only ./.env (from_path, no parent-directory search) so a stray
  parent .env with different credentials can't be picked up from a subdir.
- hyperliquid connection: retry the userAbstraction (unified-account) probe with
  backoff; on persistent failure warn loudly instead of silently locking the
  perp balance mode for the session.
- hyperliquid convert: spot_state_to_balances uses parse_decimal_or_warn (warns
  on malformed numerics) instead of silently coercing to zero.
- hyperliquid_config_from_env: filter empty BB_HYPERLIQUID_KEY_FILE so flatten
  skips HL cleanly instead of logging a connect failure.
- bb-core keys test: unique temp path per process (no parallel-run collision).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Comment thread crates/strategies/funding-arb/src/strategy.rs Outdated
flatten_filled_leg caps the reduce-only close to order_size (shared-wallet
protection). But when the live exchange size EXCEEDS order_size, the cap leaves
a remainder — previously it still returned true, so the actor went Flat and
could re-enter on residual exposure. Now it returns true only when the live
size <= order_size (fully closed); a larger position closes our size, logs, and
returns false so the caller halts (request_shutdown + MANUAL INTERVENTION)
instead of pretending flat. Test now asserts the actor requests shutdown.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Comment thread crates/strategies/funding-arb/src/strategy.rs
Comment thread crates/exchanges/bullet/src/delegate.rs
…sitions

- bullet delegate: resolve_account_address now retries transient (network/5xx/429)
  failures (3 attempts, backoff) before failing connect, so a brief API blip
  doesn't block a delegate key. Extracted resolve_account_once.
- funding-arb emergency_flatten: size closes from the LIVE exchange position
  (via get_positions) instead of internal inventory, so a fill that landed
  within the shutdown window isn't skipped on exit. Capped to order_size
  (shared-wallet protection); logs MANUAL INTERVENTION on remainder/failure.
  Consistent with the reconnect reconcile, which also reads live positions.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes using default effort and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit 0f03852. Configure here.

/// if `key_file` is not set.
#[serde(default = "default_secret")]
pub private_key_hex: SecretString,
pub private_key: SecretString,

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Legacy hex key names dropped

High Severity

The PR text says private_key_hex and BB_BULLET_PRIVATE_KEY_HEX (and the Hyperliquid hex env names) still work as aliases, but the code only accepts private_key / BB_BULLET_PRIVATE_KEY and BB_HYPERLIQUID_PRIVATE_KEY. TOML fields under the old names are ignored by serde, and load_config never reads the old env vars, so existing setups can fail at connect with “no key material” or appear configured while the key is empty.

Additional Locations (2)
Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit 0f03852. Configure here.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The dropped legacy names are intentional — this PR is a deliberate breaking change (commit 064fbce, feat!: standardize on base58 for Bullet, hex for Hyperliquid), per the maintainer's call to not carry back-compat aliases. The finding was correct that the PR description was stale/contradictory: an early line still said the old names 'keep working as aliases' while the breaking-changes section said they're removed. Fixed the PR description to consistently state the old *_hex names are removed (no aliases). Code behavior is unchanged and correct.

@0xtristan
0xtristan merged commit b3ee184 into master Jun 23, 2026
8 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant