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
2,474 changes: 1,115 additions & 1,359 deletions Cargo.lock

Large diffs are not rendered by default.

17 changes: 10 additions & 7 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ resolver = "2"
vulcan-lib = { path = "vulcan-lib" }

# Rise SDK
phoenix-rise = "0.1.14"
phoenix-rise = "0.3.1"

# CLI
clap = { version = "4", features = ["derive"] }
Expand All @@ -23,10 +23,10 @@ toml = "0.8"
reqwest = { version = "0.12", features = ["json"] }

# Solana
solana-sdk = "~2.3"
solana-sdk = "3"
# Fireblocks is intentionally omitted: some modes can auto-broadcast, while
# Vulcan expects every signer to return a locally submittable transaction.
solana-keychain = { version = "1.2", default-features = false, features = [
solana-keychain = { version = "1.4", default-features = false, features = [
"memory",
"vault",
"privy",
Expand All @@ -37,11 +37,14 @@ solana-keychain = { version = "1.2", default-features = false, features = [
"crossmint",
"dfns",
"openfort",
"sdk-v2",
"sdk-v3",
] }
solana-pubkey = { version = "~2.4", features = ["curve25519"] }
solana-instruction = { version = "~2.3", default-features = false, features = ["std"] }
solana-rpc-client = "~2.3"
solana-pubkey = { version = "3", features = ["curve25519"] }
solana-instruction = { version = "3", default-features = false, features = ["std"] }
solana-rpc-client = "3"
solana-rpc-client-api = "3"
solana-commitment-config = "3"
solana-compute-budget-interface = "3"

# Encryption
aes-gcm = "0.10"
Expand Down
20 changes: 18 additions & 2 deletions agents/error-catalog.json
Original file line number Diff line number Diff line change
Expand Up @@ -126,15 +126,15 @@
},
"REGISTER_API_FAILED": {
"category": "api",
"recovery": "Check your invite code and API URL. Run 'vulcan status' to verify connectivity"
"recovery": "Check your registration code and API URL. Run 'vulcan status' to verify connectivity"
},
"TRADERS_FETCH_FAILED": {
"category": "api",
"recovery": "Phoenix API unreachable. Run 'vulcan status' to check connectivity"
},
"NO_TRADER_ACCOUNT": {
"category": "api",
"recovery": "Register first with 'vulcan account register --invite-code <CODE>'"
"recovery": "Register first with 'vulcan account register --yes'"
},
"EXCHANGE_FETCH_FAILED": {
"category": "api",
Expand Down Expand Up @@ -164,6 +164,14 @@
"category": "api",
"recovery": "Failed to build registration transaction. Account may already be registered"
},
"INSUFFICIENT_SOL_FOR_REGISTRATION": {
"category": "validation",
"recovery": "Fund the wallet with enough SOL for cross-margin trader account rent, then retry registration"
},
"REGISTRATION_SIMULATION_FAILED": {
"category": "tx_failed",
"recovery": "Check the simulation logs, payer SOL balance, and account state before retrying registration"
},
"BUILD_DEPOSIT_FAILED": {
"category": "api",
"recovery": "Failed to build deposit transaction. Check USDC balance with 'vulcan wallet balance'"
Expand Down Expand Up @@ -232,6 +240,14 @@
"category": "network",
"recovery": "Cannot fetch balance from RPC. Check rpc_url in config"
},
"REGISTRATION_RENT_FETCH_FAILED": {
"category": "network",
"recovery": "Cannot fetch registration rent exemption from RPC. Check rpc_url in config"
},
"REGISTRATION_SIMULATION_RPC_FAILED": {
"category": "network",
"recovery": "Cannot simulate registration transaction through RPC. Check rpc_url in config"
},
"TX_SEND_FAILED": {
"category": "tx_failed",
"recovery": "Transaction rejected on-chain. Check wallet SOL balance, account state, and error logs"
Expand Down
6 changes: 3 additions & 3 deletions agents/tool-catalog.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"schema_version": "1.0.0",
"cli_version": "0.6.3",
"cli_version": "0.6.4",
"description": "Machine-readable command catalog for vulcan. 66 tools across 13 groups.",
"groups": {
"market": "Market data: prices, orderbooks, candles, funding rates",
Expand Down Expand Up @@ -1121,7 +1121,7 @@
"name": "vulcan_account_register",
"command": "vulcan account register",
"group": "account",
"description": "Register a new trader account with an access code or referral code. At least one of access_code, referral_code, or invite_code must be provided.",
"description": "Register and onboard a trader account. Omit a code for builder onboarding, pass referral_code for /v1/referral/activate-tx, or pass access_code/invite_code for allowlist activation.",
"auth_required": true,
"dangerous": true,
"parameters": [
Expand Down Expand Up @@ -1150,7 +1150,7 @@
"description": "Must be true to execute"
}
],
"example": "vulcan account register --access-code ABC123 --yes -o json"
"example": "vulcan account register --yes -o json"
},
{
"name": "vulcan_auth_status",
Expand Down
14 changes: 8 additions & 6 deletions skills/vulcan-onboarding/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ vulcan agent health -o json # readiness and next steps
vulcan agent mcp doctor --target cursor --scope user -o json
```

Setup creates `~/.vulcan/config.toml`, checks trader registration status, can complete registration with an access code or referral code, and can install read-only/paper MCP config. The Phoenix API session is signed in automatically using the configured wallet — no separate login step is required.
Setup creates `~/.vulcan/config.toml`, checks trader registration status, can complete registration with no code, an access code, or a referral code, and can install read-only/paper MCP config. The Phoenix API session is signed in automatically using the configured wallet — no separate login step is required.

MCP is optional for paper and dry-run usage. For agent-driven live trading, prefer dangerous MCP with an unlocked session wallet: `vulcan agent mcp install --target cursor --dangerous`. Use this only after the user accepts that `VULCAN_WALLET_PASSWORD` may live in plaintext agent config.

Expand Down Expand Up @@ -111,22 +111,24 @@ vulcan_wallet_balance → {}

## Step 4: Register Trader Account

Registration is invite/access-code gated. Health surfaces this before the user attempts registration. The setup wizard can do this interactively. CLI supports either code type:
Registration can be completed without a code through builder onboarding. If the user has a referral code, pass it so Vulcan uses the referral activation transaction flow; access codes remain supported for allowlist activation. The setup wizard can choose the path interactively:

```bash
vulcan account register --access-code <CODE>
vulcan account register
vulcan account register --referral-code <CODE>
vulcan account register --access-code <CODE>
```

For MCP:

```
vulcan_account_register → { access_code: "YOUR_CODE", acknowledged: true }
vulcan_account_register → { acknowledged: true }
vulcan_account_register → { referral_code: "YOUR_CODE", acknowledged: true }
vulcan_account_register → { access_code: "YOUR_CODE", acknowledged: true }
vulcan_account_register → { invite_code: "YOUR_CODE", acknowledged: true } # backwards-compatible alias
```

Registration activates the access/referral code through the Phoenix API and creates the on-chain trader account for the default cross-margin subaccount. If the trader is already registered, verify with `vulcan_account_info`.
Registration submits a signed onboarding transaction for the default cross-margin subaccount. Referral codes use `/v1/referral/activate-tx`; no-code onboarding uses the exchange builder endpoints. If the trader is already registered, verify with `vulcan_account_info`.

## Step 5: Deposit Collateral

Expand Down Expand Up @@ -166,7 +168,7 @@ Then place a small test trade.
| --------------------- | ------------------------------------------------------------ |
| `NO_DEFAULT_WALLET` | For live: `vulcan wallet set-default <name>`. For paper/dry-run: the call shouldn't have been made — switch to `vulcan_paper_*` tools and continue without a wallet. |
| `DECRYPT_FAILED` | Wrong password. Set `VULCAN_WALLET_PASSWORD` |
| `NO_TRADER_ACCOUNT` | Register with an access code or referral code |
| `NO_TRADER_ACCOUNT` | Register with `vulcan account register` |
| `CONFIG_ERROR` | Run `vulcan setup` |
| `REGISTER_API_FAILED` | Check code validity and `api_url` in `~/.vulcan/config.toml` |
| Insufficient SOL | Fund wallet with SOL for tx fees |
Expand Down
4 changes: 2 additions & 2 deletions skills/vulcan-quickstart/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ For real funds, hand off to `vulcan-onboarding` — it covers wallet creation, a

```bash
vulcan wallet create my-wallet # creates an encrypted wallet, prompts for password
vulcan account register --access-code <CODE> # or --referral-code <CODE>; registers the trader on Phoenix
vulcan account register # or add --referral-code <CODE>; registers the trader on Phoenix
vulcan margin deposit 50 # deposit 50 USDC of collateral
```

Expand Down Expand Up @@ -102,7 +102,7 @@ An AI agent should not have access to your main wallet's balance. Create a separ
```bash
vulcan wallet create agent-sandbox # separate keypair, separate password
# fund agent-sandbox externally with a little SOL + USDC, then:
vulcan account register --access-code <CODE> -w agent-sandbox
vulcan account register -w agent-sandbox
vulcan margin deposit 50 -w agent-sandbox # deposit 50 USDC to the sandbox trader
```

Expand Down
5 changes: 4 additions & 1 deletion vulcan-lib/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "vulcan-lib"
version = "0.6.3"
version = "0.6.4"
edition = "2021"
description = "Core library for the Vulcan CLI"

Expand Down Expand Up @@ -31,6 +31,9 @@ solana-sdk = { workspace = true }
solana-keychain = { workspace = true }
solana-pubkey = { workspace = true }
solana-rpc-client = { workspace = true }
solana-rpc-client-api = { workspace = true }
solana-commitment-config = { workspace = true }
solana-compute-budget-interface = { workspace = true }

# Encryption
aes-gcm = { workspace = true }
Expand Down
4 changes: 2 additions & 2 deletions vulcan-lib/src/auth.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

use crate::config::VulcanConfig;
use crate::error::VulcanError;
use phoenix_rise::{
use phoenix_rise::api::{
AuthSession, AuthSessionSnapshot, FileAuthSessionStore, PhoenixHttpAuthConfig,
PhoenixHttpClient, PhoenixHttpClientBuilder,
};
Expand Down Expand Up @@ -58,7 +58,7 @@ fn build_authenticated_http_client(
pub fn load_session(vulcan_dir: &Path) -> Result<Option<AuthSession>, VulcanError> {
let path = session_path(vulcan_dir);
let store = FileAuthSessionStore::new(path);
phoenix_rise::AuthSessionStore::load_session(&store)
phoenix_rise::api::AuthSessionStore::load_session(&store)
.map_err(|e| VulcanError::auth("API_AUTH_SESSION_LOAD_FAILED", e.to_string()))
}

Expand Down
1 change: 0 additions & 1 deletion vulcan-lib/src/cli/account.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ pub enum AccountCommand {
/// Register a trader account on Phoenix
#[command(group(
ArgGroup::new("registration_code")
.required(true)
.args(["access_code", "referral_code", "invite_code"])
))]
Register {
Expand Down
Loading
Loading