@glide-pool/sdk 0.1.0

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.
package/README.md ADDED
@@ -0,0 +1,179 @@
1
+ # @glide-pool/sdk
2
+
3
+ JavaScript SDK for the [GlidePool](https://github.com/glide-pool/glidepool) autonomous DLMM agent API on Base Mainnet.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ npm install @glide-pool/sdk
9
+ ```
10
+
11
+ ## Quick Start
12
+
13
+ ```js
14
+ import { GlidePoolClient } from '@glide-pool/sdk';
15
+
16
+ const client = new GlidePoolClient({
17
+ apiUrl: 'https://your-glidepool-instance.replit.app',
18
+ });
19
+
20
+ // List live Maverick V2 pools
21
+ const pools = await client.listPools();
22
+ console.log(pools);
23
+ // [{ poolAddress, tokenASymbol, tokenBSymbol, tvlUsd, currentPrice, feeRate, ... }]
24
+
25
+ // Create an autonomous agent
26
+ const agent = await client.createAgent({
27
+ userAddress: '0xYourWallet',
28
+ poolAddress: '0x3d70b2f31f75dc84acdd5e1588695221959b2d37',
29
+ strategy: 'balanced',
30
+ budgetUsdc: 100,
31
+ analysisIntervalSec: 60,
32
+ });
33
+ console.log(agent.id); // UUID — agent loop starts immediately on the server
34
+
35
+ // Check LLM decisions
36
+ const actions = await client.getAgentActions(agent.id);
37
+ console.log(actions[0].actionType); // 'hold' | 'rebalance' | 'withdraw' ...
38
+ console.log(actions[0].llmReasoning); // Claude Opus 4 reasoning text
39
+ ```
40
+
41
+ ## API Reference
42
+
43
+ ### Constructor
44
+
45
+ ```js
46
+ const client = new GlidePoolClient({ apiUrl: 'https://...' });
47
+ ```
48
+
49
+ | Option | Type | Required | Description |
50
+ |---|---|---|---|
51
+ | `apiUrl` | `string` | ✅ | Base URL of your GlidePool API server |
52
+
53
+ ---
54
+
55
+ ### Pools
56
+
57
+ #### `client.listPools()`
58
+ Returns all supported Maverick V2 pools with live TVL, price, and fee rate from Base Mainnet.
59
+
60
+ ```js
61
+ const pools = await client.listPools();
62
+ // Pool[] — see types
63
+ ```
64
+
65
+ #### `client.getPool(poolAddress)`
66
+ Get details for a specific pool by contract address.
67
+
68
+ ---
69
+
70
+ ### Agents
71
+
72
+ #### `client.createAgent(params)`
73
+
74
+ | Param | Type | Required | Default | Description |
75
+ |---|---|---|---|---|
76
+ | `userAddress` | `string` | ✅ | — | Wallet address that owns the agent |
77
+ | `poolAddress` | `string` | ✅ | — | Maverick V2 pool to monitor |
78
+ | `strategy` | `string` | ✅ | — | `'conservative'` \| `'balanced'` \| `'aggressive'` |
79
+ | `budgetUsdc` | `number` | ✅ | — | Max USDC budget for liquidity operations |
80
+ | `analysisIntervalSec` | `number` | ❌ | `60` | LLM analysis frequency in seconds (min: 30) |
81
+
82
+ #### `client.listAgents(userAddress)`
83
+ List all agents for a wallet.
84
+
85
+ #### `client.getAgent(agentId)`
86
+ Get a single agent by UUID.
87
+
88
+ #### `client.pauseAgent(agentId)` / `resumeAgent(agentId)` / `stopAgent(agentId)`
89
+ Control agent lifecycle. `stop` is permanent.
90
+
91
+ #### `client.getAgentActions(agentId, limit?)`
92
+ Get LLM decisions stored in the database. Each entry has:
93
+ - `actionType` — `hold` | `rebalance` | `withdraw` | `add_liquidity` | `switch_mode`
94
+ - `status` — `completed` | `pending_signature` | `signed` | `failed`
95
+ - `llmReasoning` — Full Claude Opus 4 reasoning text
96
+ - `llmRecommendation` — Structured recommendation with `riskLevel`, `suggestedBinRange`, etc.
97
+ - `txHash` — Set after user signs and confirms
98
+
99
+ #### `client.confirmAgentAction(agentId, actionId, txHash)`
100
+ After signing a `pending_signature` action in your wallet, submit the tx hash.
101
+
102
+ ---
103
+
104
+ ### Positions
105
+
106
+ #### `client.getUserPositions(walletAddress)`
107
+ List all Maverick V2 NFT-based LP positions for a wallet on Base Mainnet.
108
+
109
+ Returns `valueUsd`, `amountA`, `amountB`, `binCount`, `nftId`, and token symbols.
110
+
111
+ ---
112
+
113
+ ### Advisor (x402 gated)
114
+
115
+ #### `client.getAdvice(params)`
116
+
117
+ ```js
118
+ const advice = await client.getAdvice({
119
+ poolAddress: '0x3d70...',
120
+ userGoal: 'maximize fee income with minimal impermanent loss',
121
+ // nftId: '123', // optional: analyze existing position
122
+ // paymentProof: '...', // required if server has X402_ENABLED=true
123
+ });
124
+
125
+ console.log(advice.recommendation.action); // 'hold' | 'rebalance' | ...
126
+ console.log(advice.riskLevel); // 'low' | 'medium' | 'high'
127
+ console.log(advice.summary); // Human-readable summary
128
+ ```
129
+
130
+ **x402 micropayments:** If `X402_ENABLED=true` on the server, the call will throw with `status: 402` and include `recipient`, `amount`, `token`, and `network` in `err.data`. Send 0.05 USDC to `recipient` on Base, then encode the proof:
131
+
132
+ ```js
133
+ const proof = Buffer.from(JSON.stringify({
134
+ txHash: '0x...',
135
+ from: '0xYourWallet',
136
+ amount: '0.05',
137
+ })).toString('base64');
138
+
139
+ const advice = await client.getAdvice({ poolAddress, userGoal, paymentProof: proof });
140
+ ```
141
+
142
+ ---
143
+
144
+ ### Liquidity
145
+
146
+ #### `client.getRemoveParams(params)`
147
+ Compute remove-liquidity calldata for a position. Returns `binIds`, estimated token amounts. **You sign the transaction — the server never holds your keys.**
148
+
149
+ #### `client.getAddParams(params)`
150
+ Compute add-liquidity calldata for a pool. Returns encoded calldata for the `addLiquidity` transaction.
151
+
152
+ ---
153
+
154
+ ## Strategies
155
+
156
+ | Strategy | Mode | Description |
157
+ |---|---|---|
158
+ | `conservative` | Static | Tight fixed bin range, low risk, suited for stable pairs |
159
+ | `balanced` | Both | Follows price in both directions, medium risk |
160
+ | `aggressive` | Right/Left | Follows price trend, higher exposure |
161
+
162
+ Claude Opus 4 analyzes pool state each cycle and may override the strategy when conditions warrant caution.
163
+
164
+ ## TypeScript
165
+
166
+ Full TypeScript types are included:
167
+
168
+ ```ts
169
+ import { GlidePoolClient, Agent, Pool, AgentAction, Advice } from '@glide-pool/sdk';
170
+ ```
171
+
172
+ ## Requirements
173
+
174
+ - Node.js >= 18 (uses native `fetch`)
175
+ - A running GlidePool API server
176
+
177
+ ## License
178
+
179
+ MIT
package/package.json ADDED
@@ -0,0 +1,26 @@
1
+ {
2
+ "name": "@glide-pool/sdk",
3
+ "version": "0.1.0",
4
+ "description": "JavaScript SDK for the GlidePool autonomous DLMM agent API on Base Mainnet",
5
+ "type": "module",
6
+ "main": "./src/index.js",
7
+ "exports": {
8
+ ".": {
9
+ "import": "./src/index.js",
10
+ "types": "./src/index.d.ts"
11
+ }
12
+ },
13
+ "types": "./src/index.d.ts",
14
+ "files": ["src", "README.md"],
15
+ "keywords": ["glidepool", "dlmm", "maverick", "base", "defi", "liquidity", "agent", "x402"],
16
+ "author": "glide-pool",
17
+ "license": "MIT",
18
+ "engines": { "node": ">=18" },
19
+ "repository": {
20
+ "type": "git",
21
+ "url": "https://github.com/glide-pool/glidepool"
22
+ },
23
+ "publishConfig": {
24
+ "access": "public"
25
+ }
26
+ }
package/src/index.d.ts ADDED
@@ -0,0 +1,145 @@
1
+ export interface Pool {
2
+ poolAddress: string;
3
+ tokenASymbol: string;
4
+ tokenBSymbol: string;
5
+ tokenAAddress: string;
6
+ tokenBAddress: string;
7
+ tvlUsd: number;
8
+ currentPrice: number;
9
+ activeTick: number;
10
+ feeRate: number;
11
+ tickSpacing: number;
12
+ }
13
+
14
+ export interface CreateAgentParams {
15
+ userAddress: string;
16
+ poolAddress: string;
17
+ strategy: 'conservative' | 'balanced' | 'aggressive';
18
+ budgetUsdc: number;
19
+ analysisIntervalSec?: number;
20
+ }
21
+
22
+ export interface Agent {
23
+ id: string;
24
+ userAddress: string;
25
+ poolAddress: string;
26
+ strategy: string;
27
+ budgetUsdc: string;
28
+ status: 'active' | 'paused' | 'stopped';
29
+ lastAnalysisAt: string | null;
30
+ createdAt: string;
31
+ }
32
+
33
+ export interface AgentAction {
34
+ id: string;
35
+ agentId: string;
36
+ actionType: 'hold' | 'rebalance' | 'withdraw' | 'add_liquidity' | 'switch_mode';
37
+ status: 'pending_signature' | 'completed' | 'signed' | 'failed';
38
+ llmReasoning: string | null;
39
+ llmRecommendation: Record<string, unknown> | null;
40
+ txHash: string | null;
41
+ createdAt: string;
42
+ }
43
+
44
+ export interface Position {
45
+ nftId: string;
46
+ poolAddress: string;
47
+ tokenASymbol: string;
48
+ tokenBSymbol: string;
49
+ valueUsd: number;
50
+ amountA: string;
51
+ amountB: string;
52
+ binCount: number;
53
+ }
54
+
55
+ export interface BinRange {
56
+ lowerTick: number;
57
+ upperTick: number;
58
+ }
59
+
60
+ export interface Recommendation {
61
+ action: 'hold' | 'rebalance' | 'withdraw' | 'add_liquidity' | 'switch_mode';
62
+ reasoning: string;
63
+ suggestedMode?: string;
64
+ suggestedBinRange?: BinRange;
65
+ suggestedWithdrawPercent?: number;
66
+ }
67
+
68
+ export interface Advice {
69
+ summary: string;
70
+ riskLevel: 'low' | 'medium' | 'high';
71
+ recommendation: Recommendation;
72
+ }
73
+
74
+ export interface AdvisorParams {
75
+ poolAddress: string;
76
+ userGoal: string;
77
+ nftId?: string;
78
+ paymentProof?: string;
79
+ }
80
+
81
+ export interface RemoveLiquidityParams {
82
+ nftId: string;
83
+ userAddress: string;
84
+ poolAddress: string;
85
+ withdrawPercent: number;
86
+ }
87
+
88
+ export interface RemoveLiquidityResult {
89
+ poolAddress: string;
90
+ nftId: string;
91
+ binIds: number[];
92
+ amounts: string[];
93
+ estimatedTokenA: string;
94
+ estimatedTokenB: string;
95
+ }
96
+
97
+ export interface AddLiquidityParams {
98
+ poolAddress: string;
99
+ userAddress: string;
100
+ amountADesired: number;
101
+ amountBDesired: number;
102
+ mode: 'static' | 'both' | 'right' | 'left';
103
+ lowerTick?: number;
104
+ upperTick?: number;
105
+ }
106
+
107
+ export interface AddLiquidityResult {
108
+ poolAddress: string;
109
+ calldata: string;
110
+ estimatedTokenA: string;
111
+ estimatedTokenB: string;
112
+ }
113
+
114
+ export interface GlidePoolClientOptions {
115
+ apiUrl: string;
116
+ }
117
+
118
+ export class GlidePoolClient {
119
+ constructor(options: GlidePoolClientOptions);
120
+
121
+ // Pools
122
+ listPools(): Promise<Pool[]>;
123
+ getPool(poolAddress: string): Promise<Pool>;
124
+
125
+ // Agents
126
+ createAgent(params: CreateAgentParams): Promise<Agent>;
127
+ listAgents(userAddress: string): Promise<Agent[]>;
128
+ getAgent(agentId: string): Promise<Agent>;
129
+ updateAgentStatus(agentId: string, status: 'active' | 'paused' | 'stopped'): Promise<Agent>;
130
+ pauseAgent(agentId: string): Promise<Agent>;
131
+ resumeAgent(agentId: string): Promise<Agent>;
132
+ stopAgent(agentId: string): Promise<Agent>;
133
+ getAgentActions(agentId: string, limit?: number): Promise<AgentAction[]>;
134
+ confirmAgentAction(agentId: string, actionId: string, txHash: string): Promise<void>;
135
+
136
+ // Positions
137
+ getUserPositions(walletAddress: string): Promise<Position[]>;
138
+
139
+ // Advisor
140
+ getAdvice(params: AdvisorParams): Promise<Advice>;
141
+
142
+ // Liquidity
143
+ getRemoveParams(params: RemoveLiquidityParams): Promise<RemoveLiquidityResult>;
144
+ getAddParams(params: AddLiquidityParams): Promise<AddLiquidityResult>;
145
+ }
package/src/index.js ADDED
@@ -0,0 +1,329 @@
1
+ /**
2
+ * @glide-pool/sdk
3
+ * JavaScript SDK for the GlidePool autonomous DLMM agent API on Base Mainnet.
4
+ *
5
+ * @example
6
+ * import { GlidePoolClient } from '@glide-pool/sdk';
7
+ * const client = new GlidePoolClient({ apiUrl: 'https://your-glidepool-instance.com' });
8
+ * const pools = await client.listPools();
9
+ */
10
+
11
+ export class GlidePoolClient {
12
+ /**
13
+ * @param {object} options
14
+ * @param {string} options.apiUrl - Base URL of your GlidePool API server (no trailing slash)
15
+ */
16
+ constructor({ apiUrl } = {}) {
17
+ if (!apiUrl) throw new Error('GlidePoolClient requires { apiUrl } — e.g. https://your-glidepool.replit.app');
18
+ this.apiUrl = apiUrl.replace(/\/$/, '');
19
+ }
20
+
21
+ /**
22
+ * Internal fetch helper. Throws on non-2xx responses.
23
+ * @private
24
+ */
25
+ async _fetch(path, options = {}) {
26
+ const url = `${this.apiUrl}${path}`;
27
+ const res = await fetch(url, {
28
+ ...options,
29
+ headers: {
30
+ 'Content-Type': 'application/json',
31
+ ...options.headers,
32
+ },
33
+ });
34
+ const data = await res.json().catch(() => ({}));
35
+ if (!res.ok) {
36
+ const err = new Error(data.message || data.error || `HTTP ${res.status}`);
37
+ err.status = res.status;
38
+ err.data = data;
39
+ throw err;
40
+ }
41
+ return data;
42
+ }
43
+
44
+ // ─────────────────────────────────────────
45
+ // POOLS
46
+ // ─────────────────────────────────────────
47
+
48
+ /**
49
+ * List all supported Maverick V2 pools with live TVL, price, and fee rate.
50
+ * @returns {Promise<Pool[]>}
51
+ */
52
+ listPools() {
53
+ return this._fetch('/api/pools');
54
+ }
55
+
56
+ /**
57
+ * Get details for a specific pool by address.
58
+ * @param {string} poolAddress - Maverick V2 pool contract address (0x...)
59
+ * @returns {Promise<Pool>}
60
+ */
61
+ getPool(poolAddress) {
62
+ return this._fetch(`/api/pools/${poolAddress}`);
63
+ }
64
+
65
+ // ─────────────────────────────────────────
66
+ // AGENTS
67
+ // ─────────────────────────────────────────
68
+
69
+ /**
70
+ * Create a new autonomous agent for a given wallet + pool.
71
+ * The agent loop starts immediately on the server — no additional setup needed.
72
+ *
73
+ * @param {CreateAgentParams} params
74
+ * @returns {Promise<Agent>}
75
+ *
76
+ * @example
77
+ * const agent = await client.createAgent({
78
+ * userAddress: '0xYourWallet',
79
+ * poolAddress: '0x3d70b2f31f75dc84acdd5e1588695221959b2d37',
80
+ * strategy: 'balanced',
81
+ * budgetUsdc: 100,
82
+ * analysisIntervalSec: 60,
83
+ * });
84
+ */
85
+ createAgent(params) {
86
+ return this._fetch('/api/agents', {
87
+ method: 'POST',
88
+ body: JSON.stringify(params),
89
+ });
90
+ }
91
+
92
+ /**
93
+ * List all agents for a wallet address.
94
+ * @param {string} userAddress - Wallet address (0x...)
95
+ * @returns {Promise<Agent[]>}
96
+ */
97
+ listAgents(userAddress) {
98
+ return this._fetch(`/api/agents?userAddress=${encodeURIComponent(userAddress)}`);
99
+ }
100
+
101
+ /**
102
+ * Get a single agent by ID, including recent actions.
103
+ * @param {string} agentId - UUID of the agent
104
+ * @returns {Promise<Agent>}
105
+ */
106
+ getAgent(agentId) {
107
+ return this._fetch(`/api/agents/${agentId}`);
108
+ }
109
+
110
+ /**
111
+ * Update agent status.
112
+ * @param {string} agentId
113
+ * @param {'active'|'paused'|'stopped'} status
114
+ * @returns {Promise<Agent>}
115
+ */
116
+ updateAgentStatus(agentId, status) {
117
+ return this._fetch(`/api/agents/${agentId}/status`, {
118
+ method: 'PUT',
119
+ body: JSON.stringify({ status }),
120
+ });
121
+ }
122
+
123
+ /**
124
+ * Pause a running agent. Analysis loop stops until resumed.
125
+ * @param {string} agentId
126
+ */
127
+ pauseAgent(agentId) { return this.updateAgentStatus(agentId, 'paused'); }
128
+
129
+ /**
130
+ * Resume a paused agent.
131
+ * @param {string} agentId
132
+ */
133
+ resumeAgent(agentId) { return this.updateAgentStatus(agentId, 'active'); }
134
+
135
+ /**
136
+ * Stop an agent permanently.
137
+ * @param {string} agentId
138
+ */
139
+ stopAgent(agentId) { return this.updateAgentStatus(agentId, 'stopped'); }
140
+
141
+ /**
142
+ * Get LLM decisions (actions) for an agent.
143
+ * @param {string} agentId
144
+ * @param {number} [limit=20]
145
+ * @returns {Promise<AgentAction[]>}
146
+ */
147
+ getAgentActions(agentId, limit = 20) {
148
+ return this._fetch(`/api/agents/${agentId}/actions?limit=${limit}`);
149
+ }
150
+
151
+ /**
152
+ * Confirm an on-chain action was signed and executed.
153
+ * @param {string} agentId
154
+ * @param {string} actionId
155
+ * @param {string} txHash - Transaction hash (0x...)
156
+ */
157
+ confirmAgentAction(agentId, actionId, txHash) {
158
+ return this._fetch(`/api/agents/${agentId}/actions/${actionId}/confirm`, {
159
+ method: 'POST',
160
+ body: JSON.stringify({ txHash }),
161
+ });
162
+ }
163
+
164
+ // ─────────────────────────────────────────
165
+ // POSITIONS
166
+ // ─────────────────────────────────────────
167
+
168
+ /**
169
+ * Get all Maverick V2 LP positions for a wallet on Base Mainnet.
170
+ * @param {string} walletAddress
171
+ * @returns {Promise<Position[]>}
172
+ */
173
+ getUserPositions(walletAddress) {
174
+ return this._fetch(`/api/positions/${walletAddress}`);
175
+ }
176
+
177
+ // ─────────────────────────────────────────
178
+ // ADVISOR (x402 gated)
179
+ // ─────────────────────────────────────────
180
+
181
+ /**
182
+ * Get a Claude Opus 4 recommendation for a pool + optional existing position.
183
+ * If x402 is enabled on the server, you must provide a valid paymentProof header.
184
+ * Otherwise, queries run freely.
185
+ *
186
+ * @param {AdvisorParams} params
187
+ * @returns {Promise<Advice>}
188
+ *
189
+ * @example
190
+ * const advice = await client.getAdvice({
191
+ * poolAddress: '0x3d70...',
192
+ * userGoal: 'maximize fee income with low IL risk',
193
+ * });
194
+ */
195
+ getAdvice({ poolAddress, nftId, userGoal, paymentProof } = {}) {
196
+ const qs = new URLSearchParams({ poolAddress, userGoal });
197
+ if (nftId) qs.set('nftId', nftId);
198
+ const headers = {};
199
+ if (paymentProof) headers['x-payment-proof'] = paymentProof;
200
+ return this._fetch(`/api/advisor?${qs}`, { headers });
201
+ }
202
+
203
+ // ─────────────────────────────────────────
204
+ // LIQUIDITY
205
+ // ─────────────────────────────────────────
206
+
207
+ /**
208
+ * Compute remove-liquidity calldata for a position.
209
+ * Returns estimated token amounts and bin IDs. You sign the transaction in your wallet.
210
+ * @param {RemoveLiquidityParams} params
211
+ * @returns {Promise<RemoveLiquidityResult>}
212
+ */
213
+ getRemoveParams(params) {
214
+ return this._fetch('/api/liquidity/remove-params', {
215
+ method: 'POST',
216
+ body: JSON.stringify(params),
217
+ });
218
+ }
219
+
220
+ /**
221
+ * Compute add-liquidity calldata for a pool.
222
+ * Returns encoded calldata for the addLiquidity transaction. You sign in your wallet.
223
+ * @param {AddLiquidityParams} params
224
+ * @returns {Promise<AddLiquidityResult>}
225
+ */
226
+ getAddParams(params) {
227
+ return this._fetch('/api/liquidity/add-params', {
228
+ method: 'POST',
229
+ body: JSON.stringify(params),
230
+ });
231
+ }
232
+ }
233
+
234
+ /**
235
+ * @typedef {object} Pool
236
+ * @property {string} poolAddress
237
+ * @property {string} tokenASymbol
238
+ * @property {string} tokenBSymbol
239
+ * @property {string} tokenAAddress
240
+ * @property {string} tokenBAddress
241
+ * @property {number} tvlUsd
242
+ * @property {number} currentPrice
243
+ * @property {number} activeTick
244
+ * @property {number} feeRate
245
+ * @property {number} tickSpacing
246
+ */
247
+
248
+ /**
249
+ * @typedef {object} CreateAgentParams
250
+ * @property {string} userAddress - Wallet address that owns this agent
251
+ * @property {string} poolAddress - Maverick V2 pool address to monitor
252
+ * @property {'conservative'|'balanced'|'aggressive'} strategy
253
+ * @property {number} budgetUsdc - Max USDC budget for liquidity operations
254
+ * @property {number} [analysisIntervalSec=60] - How often to run LLM analysis (min: 30s)
255
+ */
256
+
257
+ /**
258
+ * @typedef {object} Agent
259
+ * @property {string} id
260
+ * @property {string} userAddress
261
+ * @property {string} poolAddress
262
+ * @property {string} strategy
263
+ * @property {string} budgetUsdc
264
+ * @property {'active'|'paused'|'stopped'} status
265
+ * @property {string|null} lastAnalysisAt
266
+ * @property {string} createdAt
267
+ */
268
+
269
+ /**
270
+ * @typedef {object} AgentAction
271
+ * @property {string} id
272
+ * @property {string} agentId
273
+ * @property {'hold'|'rebalance'|'withdraw'|'add_liquidity'|'switch_mode'} actionType
274
+ * @property {'pending_signature'|'completed'|'signed'|'failed'} status
275
+ * @property {string|null} llmReasoning
276
+ * @property {object|null} llmRecommendation
277
+ * @property {string|null} txHash
278
+ * @property {string} createdAt
279
+ */
280
+
281
+ /**
282
+ * @typedef {object} Position
283
+ * @property {string} nftId
284
+ * @property {string} poolAddress
285
+ * @property {string} tokenASymbol
286
+ * @property {string} tokenBSymbol
287
+ * @property {number} valueUsd
288
+ * @property {string} amountA
289
+ * @property {string} amountB
290
+ * @property {number} binCount
291
+ */
292
+
293
+ /**
294
+ * @typedef {object} AdvisorParams
295
+ * @property {string} poolAddress
296
+ * @property {string} userGoal
297
+ * @property {string} [nftId]
298
+ * @property {string} [paymentProof] - base64(JSON{txHash,from,amount}) for x402
299
+ */
300
+
301
+ /**
302
+ * @typedef {object} Advice
303
+ * @property {string} summary
304
+ * @property {'low'|'medium'|'high'} riskLevel
305
+ * @property {object} recommendation
306
+ * @property {'hold'|'rebalance'|'withdraw'|'add_liquidity'|'switch_mode'} recommendation.action
307
+ * @property {string} recommendation.reasoning
308
+ * @property {object} [recommendation.suggestedBinRange]
309
+ * @property {number} [recommendation.suggestedWithdrawPercent]
310
+ */
311
+
312
+ /**
313
+ * @typedef {object} RemoveLiquidityParams
314
+ * @property {string} nftId
315
+ * @property {string} userAddress
316
+ * @property {string} poolAddress
317
+ * @property {number} withdrawPercent - 0–100
318
+ */
319
+
320
+ /**
321
+ * @typedef {object} AddLiquidityParams
322
+ * @property {string} poolAddress
323
+ * @property {string} userAddress
324
+ * @property {number} amountADesired
325
+ * @property {number} amountBDesired
326
+ * @property {'static'|'both'|'right'|'left'} mode
327
+ * @property {number} [lowerTick]
328
+ * @property {number} [upperTick]
329
+ */