@runesx/api-client 0.3.0 → 0.5.1

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@runesx/api-client",
3
- "version": "0.3.0",
3
+ "version": "0.5.1",
4
4
  "description": "A Node.js client for interacting with the RunesX platform API and WebSocket",
5
5
  "main": "src/index.mjs",
6
6
  "type": "module",
@@ -13,23 +13,23 @@
13
13
  "test": "jest"
14
14
  },
15
15
  "dependencies": {
16
- "axios": "^1.13.5",
17
- "bignumber.js": "^9.1.2",
16
+ "axios": "^1.13.6",
17
+ "bignumber.js": "^10.0.2",
18
18
  "socket.io-client": "^4.8.3"
19
19
  },
20
20
  "devDependencies": {
21
21
  "@eslint/js": "^9.11.1",
22
22
  "@semantic-release/changelog": "^6.0.3",
23
23
  "@semantic-release/git": "^10.0.1",
24
- "@semantic-release/npm": "^13.1.4",
24
+ "@semantic-release/npm": "^13.1.5",
25
25
  "dotenv": "^17.3.1",
26
26
  "eslint": "^9.11.1",
27
27
  "eslint-plugin-import": "^2.30.0",
28
28
  "eslint-plugin-n": "^17.24.0",
29
29
  "eslint-plugin-promise": "^7.1.0",
30
- "globals": "^17.3.0",
31
- "jest": "^30.2.0",
32
- "nodemon": "^3.1.11",
30
+ "globals": "^17.4.0",
31
+ "jest": "^30.3.0",
32
+ "nodemon": "^3.1.14",
33
33
  "semantic-release": "^25.0.3"
34
34
  },
35
35
  "files": [
package/src/api.mjs CHANGED
@@ -12,6 +12,154 @@ export function createApi(config) {
12
12
  },
13
13
  });
14
14
 
15
+ // ---- Public endpoints (no auth required) ----
16
+
17
+ async function getStatus() {
18
+ try {
19
+ const response = await api.get('/status');
20
+ return response.data;
21
+ } catch (error) {
22
+ throw new Error(error.response?.data?.error || 'Failed to fetch status');
23
+ }
24
+ }
25
+
26
+ async function getCoins() {
27
+ try {
28
+ const response = await api.get('/coins');
29
+ return response.data;
30
+ } catch (error) {
31
+ throw new Error(error.response?.data?.error || 'Failed to fetch coins');
32
+ }
33
+ }
34
+
35
+ async function getCoin(ticker) {
36
+ try {
37
+ const response = await api.get(`/coins/${encodeURIComponent(ticker)}`);
38
+ return response.data;
39
+ } catch (error) {
40
+ throw new Error(error.response?.data?.error || 'Failed to fetch coin');
41
+ }
42
+ }
43
+
44
+ async function getPools() {
45
+ try {
46
+ const response = await api.get('/pools');
47
+ return response.data.data;
48
+ } catch (error) {
49
+ throw new Error(error.response?.data?.error || 'Failed to fetch pools');
50
+ }
51
+ }
52
+
53
+ async function getPoolByPair(tickerA, tickerB) {
54
+ try {
55
+ const response = await api.get(`/pools/${encodeURIComponent(tickerA)}/${encodeURIComponent(tickerB)}`);
56
+ return response.data.data;
57
+ } catch (error) {
58
+ throw new Error(error.response?.data?.error || 'Failed to fetch pool');
59
+ }
60
+ }
61
+
62
+ async function getPoolLiquidityShares(poolId) {
63
+ try {
64
+ const response = await api.get(`/pools/liquidity-shares/${encodeURIComponent(poolId)}`);
65
+ return response.data.data;
66
+ } catch (error) {
67
+ throw new Error(error.response?.data?.error || 'Failed to fetch pool liquidity shares');
68
+ }
69
+ }
70
+
71
+ async function getPrices() {
72
+ try {
73
+ const response = await api.get('/price');
74
+ return response.data;
75
+ } catch (error) {
76
+ throw new Error(error.response?.data?.error || 'Failed to fetch prices');
77
+ }
78
+ }
79
+
80
+ async function getPrice(ticker) {
81
+ try {
82
+ const response = await api.get(`/price/${encodeURIComponent(ticker)}`);
83
+ return response.data;
84
+ } catch (error) {
85
+ throw new Error(error.response?.data?.error || 'Failed to fetch price');
86
+ }
87
+ }
88
+
89
+ async function getCandlesticks(poolId, timeframe, from, to) {
90
+ try {
91
+ const response = await api.get(`/candlesticks/${encodeURIComponent(poolId)}/${encodeURIComponent(timeframe)}/${encodeURIComponent(from)}/${encodeURIComponent(to)}`);
92
+ return response.data.data;
93
+ } catch (error) {
94
+ throw new Error(error.response?.data?.error || 'Failed to fetch candlesticks');
95
+ }
96
+ }
97
+
98
+ async function getVolumeTotal() {
99
+ try {
100
+ const response = await api.get('/volume/total');
101
+ return response.data;
102
+ } catch (error) {
103
+ throw new Error(error.response?.data?.error || 'Failed to fetch total volume');
104
+ }
105
+ }
106
+
107
+ async function getVolumePool(poolId) {
108
+ try {
109
+ const response = await api.get(`/volume/pool/${encodeURIComponent(poolId)}`);
110
+ return response.data;
111
+ } catch (error) {
112
+ throw new Error(error.response?.data?.error || 'Failed to fetch pool volume');
113
+ }
114
+ }
115
+
116
+ async function getBucketsPools() {
117
+ try {
118
+ const response = await api.get('/buckets/pools');
119
+ return response.data;
120
+ } catch (error) {
121
+ throw new Error(error.response?.data?.error || 'Failed to fetch pool buckets');
122
+ }
123
+ }
124
+
125
+ async function getRecentOperations({ operationType, limit } = {}) {
126
+ try {
127
+ const params = {};
128
+ if (operationType) { params.operationType = operationType; }
129
+ if (limit) { params.limit = limit; }
130
+ const response = await api.get('/operations/recent', { params });
131
+ return response.data;
132
+ } catch (error) {
133
+ throw new Error(error.response?.data?.error || 'Failed to fetch recent operations');
134
+ }
135
+ }
136
+
137
+ async function getPoolOperations(poolId, { operationType, limit } = {}) {
138
+ try {
139
+ const params = {};
140
+ if (operationType) { params.operationType = operationType; }
141
+ if (limit) { params.limit = limit; }
142
+ const response = await api.get(`/operations/pool/${encodeURIComponent(poolId)}`, { params });
143
+ return response.data;
144
+ } catch (error) {
145
+ throw new Error(error.response?.data?.error || 'Failed to fetch pool operations');
146
+ }
147
+ }
148
+
149
+ async function getYardMessages({ before, limit } = {}) {
150
+ try {
151
+ const params = {};
152
+ if (before) { params.before = before; }
153
+ if (limit) { params.limit = limit; }
154
+ const response = await api.get('/yard/messages', { params });
155
+ return response.data;
156
+ } catch (error) {
157
+ throw new Error(error.response?.data?.error || 'Failed to fetch yard messages');
158
+ }
159
+ }
160
+
161
+ // ---- Private endpoints (auth required) ----
162
+
15
163
  async function getWallets() {
16
164
  try {
17
165
  const response = await api.get('/wallets');
@@ -21,6 +169,15 @@ export function createApi(config) {
21
169
  }
22
170
  }
23
171
 
172
+ async function getLiquidityShares() {
173
+ try {
174
+ const response = await api.get('/liquidity/shares');
175
+ return response.data.data;
176
+ } catch (error) {
177
+ throw new Error(error.response?.data?.error || 'Failed to fetch liquidity shares');
178
+ }
179
+ }
180
+
24
181
  async function postSwap({ amountIn, path, minAmountOut, idempotencyKey }) {
25
182
  try {
26
183
  const key = idempotencyKey || randomUUID();
@@ -66,14 +223,240 @@ export function createApi(config) {
66
223
  }
67
224
  }
68
225
 
69
- async function getPools() {
226
+ async function getDepositAddress(chainName) {
70
227
  try {
71
- const response = await api.get('/pools');
228
+ const response = await api.get(`/deposit/address/${encodeURIComponent(chainName)}`);
72
229
  return response.data.data;
73
230
  } catch (error) {
74
- throw new Error(error.response?.data?.error || 'Failed to fetch pools');
231
+ throw new Error(error.response?.data?.error || 'Failed to get deposit address');
232
+ }
233
+ }
234
+
235
+ async function getAllDepositAddresses() {
236
+ try {
237
+ const response = await api.get('/deposit/all-addresses');
238
+ return response.data.data;
239
+ } catch (error) {
240
+ throw new Error(error.response?.data?.error || 'Failed to get deposit addresses');
241
+ }
242
+ }
243
+
244
+ async function initiateWithdraw({ ticker, chain, address, amount, memo, idempotencyKey }) {
245
+ try {
246
+ const key = idempotencyKey || randomUUID();
247
+ const body = { ticker, chain, address, amount };
248
+ if (memo !== undefined && memo !== null) {
249
+ body.memo = memo;
250
+ }
251
+ const response = await api.post('/withdraw', body, {
252
+ headers: { 'x-idempotency-key': key },
253
+ });
254
+ return response.data;
255
+ } catch (error) {
256
+ throw new Error(error.response?.data?.error || 'Failed to initiate withdrawal');
257
+ }
258
+ }
259
+
260
+ async function verifyWithdrawPin({ pendingWithdrawalId, pinCode }) {
261
+ try {
262
+ const response = await api.post('/withdraw/verify-pin', { pendingWithdrawalId, pinCode });
263
+ return response.data;
264
+ } catch (error) {
265
+ throw new Error(error.response?.data?.error || 'Failed to verify withdrawal PIN');
266
+ }
267
+ }
268
+
269
+ async function sendWithdrawEmailPin({ pendingWithdrawalId }) {
270
+ try {
271
+ const response = await api.post('/withdraw/send-email-pin', { pendingWithdrawalId });
272
+ return response.data;
273
+ } catch (error) {
274
+ throw new Error(error.response?.data?.error || 'Failed to send withdrawal email PIN');
275
+ }
276
+ }
277
+
278
+ async function verifyWithdrawEmailPin({ pendingWithdrawalId, emailPinCode }) {
279
+ try {
280
+ const response = await api.post('/withdraw/verify-email-pin', { pendingWithdrawalId, emailPinCode });
281
+ return response.data;
282
+ } catch (error) {
283
+ throw new Error(error.response?.data?.error || 'Failed to verify withdrawal email PIN');
284
+ }
285
+ }
286
+
287
+ async function verifyWithdraw2FA({ pendingWithdrawalId, twoFactorToken }) {
288
+ try {
289
+ const response = await api.post('/withdraw/verify-2fa', { pendingWithdrawalId, twoFactorToken });
290
+ return response.data;
291
+ } catch (error) {
292
+ throw new Error(error.response?.data?.error || 'Failed to verify withdrawal 2FA');
293
+ }
294
+ }
295
+
296
+ async function getPendingWithdrawals() {
297
+ try {
298
+ const response = await api.get('/withdraw/pending');
299
+ return response.data;
300
+ } catch (error) {
301
+ throw new Error(error.response?.data?.error || 'Failed to fetch pending withdrawals');
302
+ }
303
+ }
304
+
305
+ async function cancelWithdrawal({ pendingWithdrawalId }) {
306
+ try {
307
+ const response = await api.post('/withdraw/cancel', { pendingWithdrawalId });
308
+ return response.data;
309
+ } catch (error) {
310
+ throw new Error(error.response?.data?.error || 'Failed to cancel withdrawal');
311
+ }
312
+ }
313
+
314
+ async function getTransactionHistory({ page, limit, type, status } = {}) {
315
+ try {
316
+ const params = {};
317
+ if (page) { params.page = page; }
318
+ if (limit) { params.limit = limit; }
319
+ if (type) { params.type = type; }
320
+ if (status) { params.status = status; }
321
+ const response = await api.get('/transactions/history', { params });
322
+ return response.data;
323
+ } catch (error) {
324
+ throw new Error(error.response?.data?.error || 'Failed to fetch transaction history');
325
+ }
326
+ }
327
+
328
+ async function getUserOperations({ operationType, poolId, startTime, endTime, page, limit } = {}) {
329
+ try {
330
+ const params = {};
331
+ if (operationType) { params.operationType = operationType; }
332
+ if (poolId) { params.poolId = poolId; }
333
+ if (startTime) { params.startTime = startTime; }
334
+ if (endTime) { params.endTime = endTime; }
335
+ if (page) { params.page = page; }
336
+ if (limit) { params.limit = limit; }
337
+ const response = await api.get('/operations/user', { params });
338
+ return response.data;
339
+ } catch (error) {
340
+ throw new Error(error.response?.data?.error || 'Failed to fetch user operations');
341
+ }
342
+ }
343
+
344
+ // ---- Orders endpoints ----
345
+
346
+ async function placeOrder({ pair, side, price, quantity, timeInForce, inverted, idempotencyKey }) {
347
+ try {
348
+ const key = idempotencyKey || randomUUID();
349
+ const body = { pair, side, price, quantity, timeInForce };
350
+ if (inverted !== undefined && inverted !== null) {
351
+ body.inverted = inverted;
352
+ }
353
+ const response = await api.post('/orders', body, {
354
+ headers: { 'x-idempotency-key': key },
355
+ });
356
+ return response.data;
357
+ } catch (error) {
358
+ throw new Error(error.response?.data?.error || 'Failed to place order');
359
+ }
360
+ }
361
+
362
+ async function cancelOrder(orderId, { idempotencyKey } = {}) {
363
+ try {
364
+ const headers = {};
365
+ if (idempotencyKey) {
366
+ headers['x-idempotency-key'] = idempotencyKey;
367
+ }
368
+ const response = await api.delete(`/orders/${encodeURIComponent(orderId)}`, { headers });
369
+ return response.data;
370
+ } catch (error) {
371
+ throw new Error(error.response?.data?.error || 'Failed to cancel order');
372
+ }
373
+ }
374
+
375
+ async function getOrders({ pair, status, limit, offset } = {}) {
376
+ try {
377
+ const params = {};
378
+ if (pair) { params.pair = pair; }
379
+ if (status) { params.status = status; }
380
+ if (limit) { params.limit = limit; }
381
+ if (offset !== undefined && offset !== null) { params.offset = offset; }
382
+ const response = await api.get('/orders', { params });
383
+ return response.data;
384
+ } catch (error) {
385
+ throw new Error(error.response?.data?.error || 'Failed to fetch orders');
386
+ }
387
+ }
388
+
389
+ async function getOrderBookApi(pair, { levels } = {}) {
390
+ try {
391
+ const params = {};
392
+ if (levels) { params.levels = levels; }
393
+ const response = await api.get(`/orders/book/${encodeURIComponent(pair)}`, { params });
394
+ return response.data;
395
+ } catch (error) {
396
+ throw new Error(error.response?.data?.error || 'Failed to fetch order book');
397
+ }
398
+ }
399
+
400
+ async function getTrades(pair, { limit } = {}) {
401
+ try {
402
+ const params = {};
403
+ if (limit) { params.limit = limit; }
404
+ const response = await api.get(`/orders/trades/${encodeURIComponent(pair)}`, { params });
405
+ return response.data;
406
+ } catch (error) {
407
+ throw new Error(error.response?.data?.error || 'Failed to fetch trades');
408
+ }
409
+ }
410
+
411
+ async function deleteYardMessage(messageId) {
412
+ try {
413
+ const response = await api.delete(`/yard/messages/${encodeURIComponent(messageId)}`);
414
+ return response.data;
415
+ } catch (error) {
416
+ throw new Error(error.response?.data?.error || 'Failed to delete yard message');
75
417
  }
76
418
  }
77
419
 
78
- return { getWallets, getPools, postSwap, depositLiquidity, withdrawLiquidity };
420
+ return {
421
+ // Public
422
+ getStatus,
423
+ getCoins,
424
+ getCoin,
425
+ getPools,
426
+ getPoolByPair,
427
+ getPoolLiquidityShares,
428
+ getPrices,
429
+ getPrice,
430
+ getCandlesticks,
431
+ getVolumeTotal,
432
+ getVolumePool,
433
+ getBucketsPools,
434
+ getRecentOperations,
435
+ getPoolOperations,
436
+ getYardMessages,
437
+ // Private
438
+ getWallets,
439
+ getLiquidityShares,
440
+ postSwap,
441
+ depositLiquidity,
442
+ withdrawLiquidity,
443
+ getDepositAddress,
444
+ getAllDepositAddresses,
445
+ initiateWithdraw,
446
+ verifyWithdrawPin,
447
+ sendWithdrawEmailPin,
448
+ verifyWithdrawEmailPin,
449
+ verifyWithdraw2FA,
450
+ getPendingWithdrawals,
451
+ cancelWithdrawal,
452
+ getTransactionHistory,
453
+ getUserOperations,
454
+ deleteYardMessage,
455
+ // Orders
456
+ placeOrder,
457
+ cancelOrder,
458
+ getOrders,
459
+ getOrderBookApi,
460
+ getTrades,
461
+ };
79
462
  }
package/src/index.mjs CHANGED
@@ -7,6 +7,9 @@ import { getCoins, getCoinByTicker } from './store/coinStore.mjs';
7
7
  import { getChains, getChainByName } from './store/chainStore.mjs';
8
8
  import { getWallets as getWalletsStore, getWalletByTicker } from './store/walletStore.mjs';
9
9
  import { getUserShares, getUserShareByPoolId } from './store/userSharesStore.mjs';
10
+ import { getAllOrderBooks, getOrderBook, getOrderBookPairs, getUserOrders } from './store/orderbookStore.mjs';
11
+ import { getMarkets, getMarketByCoinKey, getMarketByCoins } from './store/marketStore.mjs';
12
+ import { getClobFees } from './store/exchangeConfigStore.mjs';
10
13
  import { waitForStores } from './waitForStores.mjs';
11
14
  import { estimateLiquidityFrontend, checkRunesLiquidityFrontend, calculateShareAmounts, estimateDepositShares } from './utils/liquidityUtils.mjs';
12
15
  import { estimateSwap } from './utils/swapUtils.mjs';
@@ -14,7 +17,7 @@ import { createPriceUtils } from './utils/priceUtils.mjs';
14
17
 
15
18
  export function createRunesXClient(options = {}) {
16
19
  const config = createConfig(options);
17
- let socket = null;
20
+ let socketHandler = null;
18
21
  let initialized = false;
19
22
  const api = createApi(config);
20
23
 
@@ -22,10 +25,10 @@ export function createRunesXClient(options = {}) {
22
25
  if (!config.apiKey) {
23
26
  throw new Error('API_KEY is required');
24
27
  }
25
- socket = setupSocket(config).socket;
26
- const { pools, coins, chains, wallets, userShares } = await waitForStores(socket);
28
+ socketHandler = setupSocket(config);
29
+ const { pools, coins, chains, wallets, userShares, orderbooks } = await waitForStores(socketHandler.socket);
27
30
  initialized = true;
28
- return { pools, coins, chains, wallets, userShares };
31
+ return { pools, coins, chains, wallets, userShares, orderbooks };
29
32
  }
30
33
 
31
34
  function ensureInitialized() {
@@ -36,10 +39,14 @@ export function createRunesXClient(options = {}) {
36
39
 
37
40
  return {
38
41
  initialize,
42
+
43
+ // Raw socket access
39
44
  getSocket: () => {
40
45
  ensureInitialized();
41
- return socket;
46
+ return socketHandler.socket;
42
47
  },
48
+
49
+ // ---- Store accessors (real-time data from WebSocket) ----
43
50
  getPools,
44
51
  getPool,
45
52
  getCoins,
@@ -50,20 +57,120 @@ export function createRunesXClient(options = {}) {
50
57
  getWalletByTicker,
51
58
  getUserShares,
52
59
  getUserShareByPoolId,
60
+ getAllOrderBooks,
61
+ getOrderBook,
62
+ getOrderBookPairs,
63
+ getUserOrders,
64
+ getMarkets,
65
+ getMarketByCoins,
66
+
67
+ // ---- Event callbacks ----
68
+ on: (event, callback) => {
69
+ ensureInitialized();
70
+ socketHandler.on(event, callback);
71
+ },
72
+ off: (event, callback) => {
73
+ ensureInitialized();
74
+ socketHandler.off(event, callback);
75
+ },
76
+
77
+ // ---- Socket emit convenience methods ----
78
+ joinCandlesticks: (poolId, timeframe) => {
79
+ ensureInitialized();
80
+ socketHandler.joinCandlesticks(poolId, timeframe);
81
+ },
82
+ leaveCandlesticks: (poolId, timeframe) => {
83
+ ensureInitialized();
84
+ socketHandler.leaveCandlesticks(poolId, timeframe);
85
+ },
86
+ sendYardMessage: (text) => {
87
+ ensureInitialized();
88
+ socketHandler.sendYardMessage(text);
89
+ },
90
+ deleteMessage: (messageId) => {
91
+ ensureInitialized();
92
+ socketHandler.deleteMessage(messageId);
93
+ },
94
+ markYardRead: () => {
95
+ ensureInitialized();
96
+ socketHandler.markYardRead();
97
+ },
98
+
99
+ // ---- Trading API (auth required, scope: swap) ----
53
100
  postSwap: api.postSwap,
101
+
102
+ // ---- Liquidity API (auth required, scope: liquidity_deposit/liquidity_withdraw) ----
54
103
  depositLiquidity: api.depositLiquidity,
55
104
  withdrawLiquidity: api.withdrawLiquidity,
105
+ getLiquidityShares: api.getLiquidityShares,
106
+
107
+ // ---- Wallet API (auth required, scope: read) ----
56
108
  getWalletsApi: api.getWallets,
109
+
110
+ // ---- Deposit API (auth required) ----
111
+ getDepositAddress: api.getDepositAddress,
112
+ getAllDepositAddresses: api.getAllDepositAddresses,
113
+
114
+ // ---- Withdrawal API (auth required, scope: wallet_withdraw) ----
115
+ initiateWithdraw: api.initiateWithdraw,
116
+ verifyWithdrawPin: api.verifyWithdrawPin,
117
+ sendWithdrawEmailPin: api.sendWithdrawEmailPin,
118
+ verifyWithdrawEmailPin: api.verifyWithdrawEmailPin,
119
+ verifyWithdraw2FA: api.verifyWithdraw2FA,
120
+ getPendingWithdrawals: api.getPendingWithdrawals,
121
+ cancelWithdrawal: api.cancelWithdrawal,
122
+
123
+ // ---- Transaction history (auth required, scope: read) ----
124
+ getTransactionHistory: api.getTransactionHistory,
125
+
126
+ // ---- Operations API (public + auth) ----
127
+ getRecentOperations: api.getRecentOperations,
128
+ getUserOperations: api.getUserOperations,
129
+ getPoolOperations: api.getPoolOperations,
130
+
131
+ // ---- Public market data API ----
132
+ getStatus: api.getStatus,
133
+ getCoinsApi: api.getCoins,
134
+ getCoinApi: api.getCoin,
135
+ getPoolsApi: api.getPools,
136
+ getPoolByPair: api.getPoolByPair,
137
+ getPoolLiquidityShares: api.getPoolLiquidityShares,
138
+ getPrices: api.getPrices,
139
+ getPrice: api.getPrice,
140
+ getCandlesticks: api.getCandlesticks,
141
+ getVolumeTotal: api.getVolumeTotal,
142
+ getVolumePool: api.getVolumePool,
143
+ getBucketsPools: api.getBucketsPools,
144
+
145
+ // ---- Orders API (auth required for place/cancel/getOrders, public for book/trades) ----
146
+ placeOrder: api.placeOrder,
147
+ cancelOrder: api.cancelOrder,
148
+ getOrders: api.getOrders,
149
+ getOrderBookApi: api.getOrderBookApi,
150
+ getTrades: api.getTrades,
151
+
152
+ // ---- Yard (chat) API ----
153
+ getYardMessages: api.getYardMessages,
154
+ deleteYardMessage: api.deleteYardMessage,
155
+
156
+ // ---- Client-side estimation utilities ----
57
157
  estimateSwap: (inputCoin, outputCoin, amountIn, maxHops = 6, algorithm = 'dfs') =>
58
- estimateSwap(inputCoin, outputCoin, amountIn, getPools(), getCoins(), maxHops, algorithm),
158
+ estimateSwap(inputCoin, outputCoin, amountIn, getPools(), getCoins(), maxHops, algorithm, getAllOrderBooks(), getUserOrders(), getClobFees(), getMarketByCoinKey()),
59
159
  estimateLiquidityFrontend,
60
160
  estimateDepositShares: ({ pool, amountA, amountB, slippagePercent } = {}) =>
61
161
  estimateDepositShares({ pool, amountA, amountB, slippagePercent }),
62
162
  checkRunesLiquidityFrontend: (coinA, coinB) =>
63
163
  checkRunesLiquidityFrontend(coinA, coinB, getPools(), getCoins()),
64
164
  calculateShareAmounts: () => calculateShareAmounts({ userShares: getUserShares(), pools: getPools() }),
165
+
166
+ // ---- Price utilities ----
167
+ utils: {
168
+ ...createPriceUtils(),
169
+ },
170
+
171
+ // ---- Pool monitoring ----
65
172
  monitorPool: (poolId, interval = 10000) => {
66
- setInterval(() => {
173
+ return setInterval(() => {
67
174
  const pool = getPool(poolId);
68
175
  if (pool) {
69
176
  console.log(`Monitoring pool ${poolId} (${pool.coinA.ticker}/${pool.coinB.ticker}):`, {
@@ -77,12 +184,11 @@ export function createRunesXClient(options = {}) {
77
184
  }
78
185
  }, interval);
79
186
  },
80
- utils: {
81
- ...createPriceUtils(),
82
- },
187
+
188
+ // ---- Disconnect ----
83
189
  disconnect: () => {
84
- if (socket) {
85
- socket.disconnect();
190
+ if (socketHandler) {
191
+ socketHandler.socket.disconnect();
86
192
  }
87
193
  },
88
194
  };