@runesx/api-client 0.3.0 → 0.4.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@runesx/api-client",
3
- "version": "0.3.0",
3
+ "version": "0.4.0",
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",
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,167 @@ 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
+ async function deleteYardMessage(messageId) {
345
+ try {
346
+ const response = await api.delete(`/yard/messages/${encodeURIComponent(messageId)}`);
347
+ return response.data;
348
+ } catch (error) {
349
+ throw new Error(error.response?.data?.error || 'Failed to delete yard message');
75
350
  }
76
351
  }
77
352
 
78
- return { getWallets, getPools, postSwap, depositLiquidity, withdrawLiquidity };
353
+ return {
354
+ // Public
355
+ getStatus,
356
+ getCoins,
357
+ getCoin,
358
+ getPools,
359
+ getPoolByPair,
360
+ getPoolLiquidityShares,
361
+ getPrices,
362
+ getPrice,
363
+ getCandlesticks,
364
+ getVolumeTotal,
365
+ getVolumePool,
366
+ getBucketsPools,
367
+ getRecentOperations,
368
+ getPoolOperations,
369
+ getYardMessages,
370
+ // Private
371
+ getWallets,
372
+ getLiquidityShares,
373
+ postSwap,
374
+ depositLiquidity,
375
+ withdrawLiquidity,
376
+ getDepositAddress,
377
+ getAllDepositAddresses,
378
+ initiateWithdraw,
379
+ verifyWithdrawPin,
380
+ sendWithdrawEmailPin,
381
+ verifyWithdrawEmailPin,
382
+ verifyWithdraw2FA,
383
+ getPendingWithdrawals,
384
+ cancelWithdrawal,
385
+ getTransactionHistory,
386
+ getUserOperations,
387
+ deleteYardMessage,
388
+ };
79
389
  }
package/src/index.mjs CHANGED
@@ -14,7 +14,7 @@ import { createPriceUtils } from './utils/priceUtils.mjs';
14
14
 
15
15
  export function createRunesXClient(options = {}) {
16
16
  const config = createConfig(options);
17
- let socket = null;
17
+ let socketHandler = null;
18
18
  let initialized = false;
19
19
  const api = createApi(config);
20
20
 
@@ -22,8 +22,8 @@ export function createRunesXClient(options = {}) {
22
22
  if (!config.apiKey) {
23
23
  throw new Error('API_KEY is required');
24
24
  }
25
- socket = setupSocket(config).socket;
26
- const { pools, coins, chains, wallets, userShares } = await waitForStores(socket);
25
+ socketHandler = setupSocket(config);
26
+ const { pools, coins, chains, wallets, userShares } = await waitForStores(socketHandler.socket);
27
27
  initialized = true;
28
28
  return { pools, coins, chains, wallets, userShares };
29
29
  }
@@ -36,10 +36,14 @@ export function createRunesXClient(options = {}) {
36
36
 
37
37
  return {
38
38
  initialize,
39
+
40
+ // Raw socket access
39
41
  getSocket: () => {
40
42
  ensureInitialized();
41
- return socket;
43
+ return socketHandler.socket;
42
44
  },
45
+
46
+ // ---- Store accessors (real-time data from WebSocket) ----
43
47
  getPools,
44
48
  getPool,
45
49
  getCoins,
@@ -50,10 +54,90 @@ export function createRunesXClient(options = {}) {
50
54
  getWalletByTicker,
51
55
  getUserShares,
52
56
  getUserShareByPoolId,
57
+
58
+ // ---- Event callbacks ----
59
+ on: (event, callback) => {
60
+ ensureInitialized();
61
+ socketHandler.on(event, callback);
62
+ },
63
+ off: (event, callback) => {
64
+ ensureInitialized();
65
+ socketHandler.off(event, callback);
66
+ },
67
+
68
+ // ---- Socket emit convenience methods ----
69
+ joinCandlesticks: (poolId, timeframe) => {
70
+ ensureInitialized();
71
+ socketHandler.joinCandlesticks(poolId, timeframe);
72
+ },
73
+ leaveCandlesticks: (poolId, timeframe) => {
74
+ ensureInitialized();
75
+ socketHandler.leaveCandlesticks(poolId, timeframe);
76
+ },
77
+ sendYardMessage: (text) => {
78
+ ensureInitialized();
79
+ socketHandler.sendYardMessage(text);
80
+ },
81
+ deleteMessage: (messageId) => {
82
+ ensureInitialized();
83
+ socketHandler.deleteMessage(messageId);
84
+ },
85
+ markYardRead: () => {
86
+ ensureInitialized();
87
+ socketHandler.markYardRead();
88
+ },
89
+
90
+ // ---- Trading API (auth required, scope: swap) ----
53
91
  postSwap: api.postSwap,
92
+
93
+ // ---- Liquidity API (auth required, scope: liquidity_deposit/liquidity_withdraw) ----
54
94
  depositLiquidity: api.depositLiquidity,
55
95
  withdrawLiquidity: api.withdrawLiquidity,
96
+ getLiquidityShares: api.getLiquidityShares,
97
+
98
+ // ---- Wallet API (auth required, scope: read) ----
56
99
  getWalletsApi: api.getWallets,
100
+
101
+ // ---- Deposit API (auth required) ----
102
+ getDepositAddress: api.getDepositAddress,
103
+ getAllDepositAddresses: api.getAllDepositAddresses,
104
+
105
+ // ---- Withdrawal API (auth required, scope: wallet_withdraw) ----
106
+ initiateWithdraw: api.initiateWithdraw,
107
+ verifyWithdrawPin: api.verifyWithdrawPin,
108
+ sendWithdrawEmailPin: api.sendWithdrawEmailPin,
109
+ verifyWithdrawEmailPin: api.verifyWithdrawEmailPin,
110
+ verifyWithdraw2FA: api.verifyWithdraw2FA,
111
+ getPendingWithdrawals: api.getPendingWithdrawals,
112
+ cancelWithdrawal: api.cancelWithdrawal,
113
+
114
+ // ---- Transaction history (auth required, scope: read) ----
115
+ getTransactionHistory: api.getTransactionHistory,
116
+
117
+ // ---- Operations API (public + auth) ----
118
+ getRecentOperations: api.getRecentOperations,
119
+ getUserOperations: api.getUserOperations,
120
+ getPoolOperations: api.getPoolOperations,
121
+
122
+ // ---- Public market data API ----
123
+ getStatus: api.getStatus,
124
+ getCoinsApi: api.getCoins,
125
+ getCoinApi: api.getCoin,
126
+ getPoolsApi: api.getPools,
127
+ getPoolByPair: api.getPoolByPair,
128
+ getPoolLiquidityShares: api.getPoolLiquidityShares,
129
+ getPrices: api.getPrices,
130
+ getPrice: api.getPrice,
131
+ getCandlesticks: api.getCandlesticks,
132
+ getVolumeTotal: api.getVolumeTotal,
133
+ getVolumePool: api.getVolumePool,
134
+ getBucketsPools: api.getBucketsPools,
135
+
136
+ // ---- Yard (chat) API ----
137
+ getYardMessages: api.getYardMessages,
138
+ deleteYardMessage: api.deleteYardMessage,
139
+
140
+ // ---- Client-side estimation utilities ----
57
141
  estimateSwap: (inputCoin, outputCoin, amountIn, maxHops = 6, algorithm = 'dfs') =>
58
142
  estimateSwap(inputCoin, outputCoin, amountIn, getPools(), getCoins(), maxHops, algorithm),
59
143
  estimateLiquidityFrontend,
@@ -62,8 +146,15 @@ export function createRunesXClient(options = {}) {
62
146
  checkRunesLiquidityFrontend: (coinA, coinB) =>
63
147
  checkRunesLiquidityFrontend(coinA, coinB, getPools(), getCoins()),
64
148
  calculateShareAmounts: () => calculateShareAmounts({ userShares: getUserShares(), pools: getPools() }),
149
+
150
+ // ---- Price utilities ----
151
+ utils: {
152
+ ...createPriceUtils(),
153
+ },
154
+
155
+ // ---- Pool monitoring ----
65
156
  monitorPool: (poolId, interval = 10000) => {
66
- setInterval(() => {
157
+ return setInterval(() => {
67
158
  const pool = getPool(poolId);
68
159
  if (pool) {
69
160
  console.log(`Monitoring pool ${poolId} (${pool.coinA.ticker}/${pool.coinB.ticker}):`, {
@@ -77,12 +168,11 @@ export function createRunesXClient(options = {}) {
77
168
  }
78
169
  }, interval);
79
170
  },
80
- utils: {
81
- ...createPriceUtils(),
82
- },
171
+
172
+ // ---- Disconnect ----
83
173
  disconnect: () => {
84
- if (socket) {
85
- socket.disconnect();
174
+ if (socketHandler) {
175
+ socketHandler.socket.disconnect();
86
176
  }
87
177
  },
88
178
  };