Skip to content

Commit 872944c

Browse files
chore: sync from internal
1 parent 87ad8fa commit 872944c

61 files changed

Lines changed: 777 additions & 366 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.claude/skills/new-cli-action/SKILL.md

Lines changed: 24 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -67,16 +67,17 @@ Create `packages/cli/src/actions/<name>.ts` using the template below. Fill every
6767
import { Cli, z } from "incur";
6868
import { createAction } from "../utils/actions.js";
6969
// Import helpers as needed:
70-
// Session/wallet: import { WalletSchema } from "../utils/schemas.js";
70+
// Session/wallet: import { WalletIdSchema, DerivationIndexSchema } from "../utils/schemas.js";
7171
// Solana address: import { getSolanaAddress } from "../utils/solana.js";
7272
// EVM address: import { getEthereumAddress } from "../utils/evm.js";
7373
// Perps client: import { createPerpsClient } from "../utils/perps.js";
7474
// Shared schemas: import { ActionResponseSchema, PendingConfirmationSchema } from "../utils/output-schemas.js";
7575

76-
// Use WalletSchema.safeExtend({...}) if the action touches the wallet (adds walletId resolver + derivationIndex).
77-
// Use z.object({...}) if it needs no wallet access.
78-
const <PascalName>Schema = WalletSchema.safeExtend({
76+
const <PascalName>Schema = z.object({
7977
// Each field needs a .describe() explaining its purpose and any defaults.
78+
// Always include these at the bottom if the action touches the wallet:
79+
// walletId: WalletIdSchema.describe("Optional wallet ID (defaults to authenticated wallet)"),
80+
// derivationIndex: DerivationIndexSchema.describe("Optional derivation index (default: 0)"),
8081
});
8182

8283
const <PascalName>OutputSchema = z.object({
@@ -113,15 +114,15 @@ const <camelName>Action = createAction({
113114
},
114115
run: async ({ options: params, var: context }) => {
115116
const { logger } = context;
116-
const walletId = params.walletId(context.manager);
117-
const derivationIndex = params.derivationIndex;
118-
// Resolve walletId BEFORE calling getClient() so auth errors surface clearly.
119-
const client = context.manager.getClient();
117+
const session = context.manager.getSession();
120118

121-
// client → PhantomClient (sign, send, addresses)
119+
// context.manager.getClient() → PhantomClient (sign, send, addresses)
122120
// context.apiClient → PhantomApiClient (REST endpoints)
123-
// walletId → resolved wallet ID (param or authenticated session)
124-
// derivationIndex → BIP-44 account index (default: 0)
121+
// session.walletId → currently authenticated wallet ID
122+
// session.organizationId → org ID for the current session
123+
124+
// A session is automatically initialized on first use and persisted
125+
// across calls — no manual session management required.
125126

126127
// ... implementation ...
127128

@@ -265,14 +266,15 @@ A session is initialized on first use (triggering the browser auth flow) and per
265266

266267
## Reference: commonly used helpers
267268

268-
| Helper | Import path | When to use |
269-
| -------------------------------------------------------- | ------------------------ | ----------------------------------------------------------------------------------------- |
270-
| `getSolanaAddress(context, walletId, derivationIndex)` | `../utils/solana.js` | Derive Solana public key |
271-
| `getEthereumAddress(context, walletId, derivationIndex)` | `../utils/evm.js` | Derive EVM address |
272-
| `createPerpsClient(context, walletId, derivationIndex)` | `../utils/perps.js` | All Hyperliquid perps ops |
273-
| `normalizeNetworkId(id)` | `../utils/network.js` | Normalise CAIP-2 chain IDs |
274-
| `parseBaseUnitAmount(amount)` | `../utils/amount.js` | String/number → `bigint` base units |
275-
| `parseUiAmount(amount, decimals)` | `../utils/amount.js` | UI units → `bigint` base units |
276-
| `runSimulation(body, context)` | `../utils/simulation.js` | Simulate before submitting |
277-
| `WalletSchema` | `../utils/schemas.js` | Base schema with `walletId` resolver + `derivationIndex`; extend it instead of `z.object` |
278-
| `Caip2ChainIdSchema` | `../utils/schemas.js` | CAIP-2 chain ID input field |
269+
| Helper | Import path | When to use |
270+
| -------------------------------------------------------- | ------------------------ | ----------------------------------- |
271+
| `getSolanaAddress(context, walletId, derivationIndex)` | `../utils/solana.js` | Derive Solana public key |
272+
| `getEthereumAddress(context, walletId, derivationIndex)` | `../utils/evm.js` | Derive EVM address |
273+
| `createPerpsClient(context, walletId, derivationIndex?)` | `../utils/perps.js` | All Hyperliquid perps ops |
274+
| `normalizeNetworkId(id)` | `../utils/network.js` | Normalise CAIP-2 chain IDs |
275+
| `parseBaseUnitAmount(amount)` | `../utils/amount.js` | String/number → `bigint` base units |
276+
| `parseUiAmount(amount, decimals)` | `../utils/amount.js` | UI units → `bigint` base units |
277+
| `runSimulation(body, context)` | `../utils/simulation.js` | Simulate before submitting |
278+
| `WalletIdSchema` | `../utils/schemas.js` | Optional wallet ID input field |
279+
| `DerivationIndexSchema` | `../utils/schemas.js` | Optional HD index input field |
280+
| `Caip2ChainIdSchema` | `../utils/schemas.js` | CAIP-2 chain ID input field |

packages/cli/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@phantom/cli",
3-
"version": "1.2.6",
3+
"version": "1.2.7",
44
"description": "Phantom CLI — interact with your Phantom wallet from the terminal",
55
"repository": {
66
"type": "git",

packages/cli/src/actions/buy-token.test.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -118,7 +118,7 @@ const makeContext = (overrides: Record<string, unknown> = {}) => {
118118
session,
119119
logger: { info: jest.fn(), warn: jest.fn(), error: jest.fn(), debug: jest.fn() },
120120
apiClient,
121-
manager: { resetSession: jest.fn(), getClient: () => client, getSession: () => session, isInitialized: () => true },
121+
manager: { resetSession: jest.fn(), getClient: () => client, getSession: () => session },
122122
};
123123
};
124124

packages/cli/src/actions/buy-token.ts

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,10 @@ import { getEthereumAddress } from "../utils/evm.js";
1414
import { parseBaseUnitAmount, parseUiAmount, requirePositiveAmount } from "../utils/amount.js";
1515
import { validateTokenAddress, buildTokenObject, fetchSwapQuote, executeSwap } from "../utils/swap.js";
1616
import { resolveSolanaRpcUrl } from "../utils/rpc.js";
17-
import { WalletSchema, Caip2ChainIdSchema, PercentageSchema } from "../utils/schemas.js";
17+
import { WalletIdSchema, DerivationIndexSchema, Caip2ChainIdSchema, PercentageSchema } from "../utils/schemas.js";
1818
import { BuyTokenOutputSchema } from "../utils/output-schemas.js";
1919

20-
const BuyTokenSchema = WalletSchema.safeExtend({
20+
const BuyTokenSchema = z.object({
2121
sellChainId: Caip2ChainIdSchema.optional()
2222
.default("solana:mainnet")
2323
.describe(
@@ -106,6 +106,8 @@ const BuyTokenSchema = WalletSchema.safeExtend({
106106
.string()
107107
.optional()
108108
.describe("Optional Solana RPC URL (for mint decimals lookup when amountUnit is 'ui' on Solana)"),
109+
derivationIndex: DerivationIndexSchema.describe("Optional derivation index for the taker address (default: 0)"),
110+
walletId: WalletIdSchema.describe("Optional wallet ID (defaults to authenticated wallet)"),
109111
});
110112

111113
const buyTokenAction = createAction({
@@ -136,6 +138,7 @@ const buyTokenAction = createAction({
136138
},
137139
run: async ({ options: params, var: context }) => {
138140
const { logger } = context;
141+
const session = context.manager.getSession();
139142

140143
// --- Chain resolution ---
141144
const rawSellChain = params.sellChainId;
@@ -162,7 +165,7 @@ const buyTokenAction = createAction({
162165
}
163166

164167
const amount = params.amount;
165-
const walletId = params.walletId(context.manager);
168+
const walletId = params.walletId ?? session.walletId;
166169

167170
const derivationIndex = params.derivationIndex;
168171
const amountUnit = params.amountUnit;

packages/cli/src/actions/cancel-perp-order.test.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@ const makeContext = () => {
1414
manager: {
1515
getClient: () => client,
1616
getSession: () => session,
17-
isInitialized: () => true,
1817
},
1918
};
2019
};

packages/cli/src/actions/cancel-perp-order.ts

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,10 @@
77
import { Cli, z } from "incur";
88
import { createAction } from "../utils/actions.js";
99
import { createPerpsClient } from "../utils/perps.js";
10-
import { WalletSchema } from "../utils/schemas.js";
10+
import { WalletIdSchema, DerivationIndexSchema } from "../utils/schemas.js";
1111
import { ActionResponseSchema } from "../utils/output-schemas.js";
1212

13-
const CancelPerpOrderSchema = WalletSchema.safeExtend({
13+
const CancelPerpOrderSchema = z.object({
1414
market: z.string().trim().min(1, { message: "market is required" }).describe('Market symbol (e.g. "BTC")'),
1515
orderId: z.coerce
1616
.number()
@@ -19,6 +19,8 @@ const CancelPerpOrderSchema = WalletSchema.safeExtend({
1919
message: "orderId must be a safe integer",
2020
})
2121
.describe("The numeric order ID to cancel (from get_perp_orders)"),
22+
walletId: WalletIdSchema.describe("Optional wallet ID (defaults to authenticated wallet)"),
23+
derivationIndex: DerivationIndexSchema.describe("Optional derivation index (default: 0)"),
2224
});
2325

2426
const cancelPerpOrderAction = createAction({
@@ -35,7 +37,7 @@ const cancelPerpOrderAction = createAction({
3537
},
3638
},
3739
run: async ({ options: params, var: context }) => {
38-
const walletId = params.walletId(context.manager);
40+
const walletId = params.walletId ?? context.manager.getSession().walletId;
3941
const perps = await createPerpsClient(context, walletId, params.derivationIndex);
4042

4143
context.logger.info(`Cancelling perp order ${params.orderId} on ${params.market}`);

packages/cli/src/actions/close-perp-position.test.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@ const makeContext = () => {
1414
manager: {
1515
getClient: () => client,
1616
getSession: () => session,
17-
isInitialized: () => true,
1817
},
1918
};
2019
};

packages/cli/src/actions/close-perp-position.ts

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,10 @@
77
import { Cli, z } from "incur";
88
import { createAction } from "../utils/actions.js";
99
import { createPerpsClient } from "../utils/perps.js";
10-
import { WalletSchema, PercentageSchema } from "../utils/schemas.js";
10+
import { WalletIdSchema, DerivationIndexSchema, PercentageSchema } from "../utils/schemas.js";
1111
import { ActionResponseSchema } from "../utils/output-schemas.js";
1212

13-
const ClosePerpPositionSchema = WalletSchema.safeExtend({
13+
const ClosePerpPositionSchema = z.object({
1414
market: z
1515
.string()
1616
.trim()
@@ -19,6 +19,8 @@ const ClosePerpPositionSchema = WalletSchema.safeExtend({
1919
sizePercent: PercentageSchema.min(1)
2020
.default(100)
2121
.describe("Percentage of position to close (1–100, default: 100 for full close)"),
22+
walletId: WalletIdSchema.describe("Optional wallet ID (defaults to authenticated wallet)"),
23+
derivationIndex: DerivationIndexSchema.describe("Optional derivation index (default: 0)"),
2224
});
2325

2426
const closePerpPositionAction = createAction({
@@ -37,7 +39,7 @@ const closePerpPositionAction = createAction({
3739
},
3840
},
3941
run: async ({ options: params, var: context }) => {
40-
const walletId = params.walletId(context.manager);
42+
const walletId = params.walletId ?? context.manager.getSession().walletId;
4143
const perps = await createPerpsClient(context, walletId, params.derivationIndex);
4244

4345
context.logger.info(`Closing ${params.sizePercent}% of ${params.market} perp position`);

packages/cli/src/actions/deposit-to-hyperliquid.test.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,6 @@ const makeContext = () => {
2121
manager: {
2222
getClient: () => client,
2323
getSession: () => session,
24-
isInitialized: () => true,
2524
},
2625
};
2726
};

packages/cli/src/actions/deposit-to-hyperliquid.ts

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
import { Cli, z } from "incur";
1515
import { createAction } from "../utils/actions.js";
1616
import { buyTokenTool } from "./buy-token.js";
17-
import { WalletSchema, Caip2ChainIdSchema } from "../utils/schemas.js";
17+
import { WalletIdSchema, DerivationIndexSchema, Caip2ChainIdSchema } from "../utils/schemas.js";
1818
import { BuyTokenOutputSchema } from "../utils/output-schemas.js";
1919

2020
// Hypercore chain ID used by the Phantom swapper backend
@@ -23,7 +23,7 @@ const HYPERCORE_CHAIN_ID = "hypercore:mainnet";
2323
// USDC on Hypercore — Relay's 16-byte representation (backend HYPERLIQUID_USDC_ADDRESS)
2424
const HYPERCORE_USDC_ADDRESS = "0x00000000000000000000000000000000";
2525

26-
const DepositToHyperliquidSchema = WalletSchema.safeExtend({
26+
const DepositToHyperliquidSchema = z.object({
2727
sourceChainId: Caip2ChainIdSchema.describe(
2828
'Source chain CAIP-2 ID. Examples: "solana:mainnet", "eip155:42161" (Arbitrum), "eip155:8453" (Base), "eip155:1" (Ethereum), "eip155:137" (Polygon).',
2929
),
@@ -51,6 +51,8 @@ const DepositToHyperliquidSchema = WalletSchema.safeExtend({
5151
.union([z.boolean(), z.stringbool()])
5252
.default(false)
5353
.describe("If false (default), returns the quote only. If true, signs and broadcasts immediately."),
54+
walletId: WalletIdSchema.describe("Optional wallet ID (defaults to authenticated wallet)"),
55+
derivationIndex: DerivationIndexSchema.describe("Optional derivation index (default: 0)"),
5456
});
5557

5658
const depositToHyperliquidAction = createAction({
@@ -75,7 +77,7 @@ const depositToHyperliquidAction = createAction({
7577
// This reuses all quote parsing, CrossChainQuote typing, signing, and broadcasting logic.
7678
return buyTokenTool.handler(
7779
{
78-
walletId: params.walletId(context.manager),
80+
walletId: params.walletId,
7981
derivationIndex: params.derivationIndex,
8082
sellChainId: params.sourceChainId,
8183
sellTokenMint: params.sellTokenMint,

0 commit comments

Comments
 (0)