@icgio/icg-exchanges-wrapper 1.14.254 → 1.14.256

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 CHANGED
@@ -1 +1,129 @@
1
- # icg-exchanges-wrapper
1
+ # ICG Exchanges Wrapper
2
+
3
+ High-level wrapper functions for the ICG exchanges package, providing simplified interfaces for common trading operations across multiple exchanges.
4
+
5
+ ## Features
6
+
7
+ - **Multi-Exchange Operations**: Execute operations across multiple exchanges in parallel
8
+ - **Unified Data Format**: Consistent response format regardless of exchange
9
+ - **Order Management Middleware**: Advanced order placement with retries and validation
10
+ - **WebSocket Data Client**: Real-time log streaming support
11
+ - **Rate Data Aggregation**: Combine orderbook data from multiple sources
12
+
13
+ ## Installation
14
+
15
+ ```bash
16
+ npm install @icgio/icg-exchanges-wrapper
17
+ ```
18
+
19
+ ## Usage
20
+
21
+ ### Functions Module
22
+
23
+ ```javascript
24
+ const { functions } = require('@icgio/icg-exchanges-wrapper')
25
+
26
+ // Get rates (orderbook) from multiple exchanges
27
+ const rates = await functions.get_exchanges_rates(exchanges, pairs)
28
+
29
+ // Get balances from multiple exchanges
30
+ const balances = await functions.get_exchanges_balance(exchanges)
31
+
32
+ // Get trade history
33
+ const trades = await functions.get_exchanges_trades(exchanges, pairs)
34
+
35
+ // Get open orders
36
+ const open_orders = await functions.get_exchanges_open_orders(exchanges, pairs)
37
+
38
+ // Get deposit history
39
+ const deposits = await functions.get_exchanges_deposits(exchanges)
40
+
41
+ // Get withdrawal history
42
+ const withdrawals = await functions.get_exchanges_withdrawals(exchanges)
43
+
44
+ // Get OHLCV data
45
+ const ohlcv = await functions.get_exchanges_ohlcv(exchanges, pairs, interval)
46
+
47
+ // Get market history
48
+ const market_history = await functions.get_exchanges_market_history(exchanges, pairs)
49
+ ```
50
+
51
+ ### Orders Middleware
52
+
53
+ ```javascript
54
+ const Orders = require('@icgio/icg-exchanges-wrapper').orders
55
+
56
+ // Create an order manager instance
57
+ const orders = new Orders(exchanges_config)
58
+
59
+ // Place orders with advanced features
60
+ await orders.place_order(exchange, pair, side, amount, price, options)
61
+
62
+ // Cancel orders
63
+ await orders.cancel_order(exchange, pair, order_id)
64
+
65
+ // Get order status
66
+ const status = await orders.get_order_status(exchange, pair, order_id)
67
+ ```
68
+
69
+ ### WebSocket Data Client
70
+
71
+ ```javascript
72
+ const { ws_data_client, send_log } = require('@icgio/icg-exchanges-wrapper')
73
+
74
+ // Send log messages via WebSocket
75
+ send_log('info', 'Operation completed successfully')
76
+ send_log('error', 'An error occurred')
77
+ ```
78
+
79
+ ## Project Structure
80
+
81
+ ```
82
+ icg-exchanges-wrapper/
83
+ ├── index.js # Main entry point
84
+ ├── functions/
85
+ │ ├── get-exchanges-balance.js # Balance fetching
86
+ │ ├── get-exchanges-deposits.js # Deposit history
87
+ │ ├── get-exchanges-open-orders.js # Open orders
88
+ │ ├── get-exchanges-rates-market-history-ohlcv.js # Market data
89
+ │ ├── get-exchanges-trades.js # Trade history
90
+ │ └── get-exchanges-withdrawals.js # Withdrawal history
91
+ ├── middleware/
92
+ │ ├── account.js # Account middleware
93
+ │ └── orders.js # Order management middleware
94
+ ├── lib/
95
+ │ └── ws-data-client.js # WebSocket data client
96
+ └── package.json
97
+ ```
98
+
99
+ ## Available Functions
100
+
101
+ | Function | Description |
102
+ |----------|-------------|
103
+ | `get_exchanges_rates` | Fetch orderbook/rates from exchanges |
104
+ | `get_exchanges_market_history` | Fetch recent trade history |
105
+ | `get_exchanges_ohlcv` | Fetch OHLCV candlestick data |
106
+ | `get_exchanges_balance` | Fetch account balances |
107
+ | `get_exchanges_trades` | Fetch user trade history |
108
+ | `get_exchanges_open_orders` | Fetch open orders |
109
+ | `get_exchanges_deposits` | Fetch deposit history |
110
+ | `get_exchanges_withdrawals` | Fetch withdrawal history |
111
+
112
+ ## Dependencies
113
+
114
+ | Package | Purpose |
115
+ |---------|---------|
116
+ | `@icgio/icg-exchanges` | Exchange implementations |
117
+ | `@icgio/icg-utils` | Utility functions |
118
+ | `lodash` | Utility library |
119
+ | `pg` | PostgreSQL client |
120
+
121
+ ## Code Style
122
+
123
+ - CommonJS modules (`require()` / `module.exports`)
124
+ - Variable naming: `snake_case`
125
+ - Function naming: `snake_case`
126
+
127
+ ## License
128
+
129
+ ISC License
@@ -25,11 +25,48 @@ const get_exchanges_rates = function (Exchanges, exchange_pair_dict, cb, ws_enab
25
25
  }
26
26
  if (Exchange.ws_market && ws_enabled) {
27
27
  let ws_promise = new Promise((resolve, reject) => {
28
+ if (!Exchange.ws || !Exchange.ws.market) {
29
+ console.error(`${Exchange_name} WebSocket not properly initialized`)
30
+ reject(new Error(`WebSocket not initialized for ${Exchange_name}`))
31
+ return
32
+ }
33
+
28
34
  Exchange.ws_market(exchange_pair_dict[Exchange_name])
29
35
 
36
+ const WS_TIMEOUT_MS = 30000 // 30 seconds timeout
37
+ const start_time = Date.now()
38
+ let check_count = 0
39
+ const MAX_CHECKS = 300 // 30 seconds / 100ms
40
+
30
41
  const check_status = () => {
42
+ check_count++
43
+ const elapsed = Date.now() - start_time
44
+
45
+ // Timeout check
46
+ if (elapsed > WS_TIMEOUT_MS || check_count > MAX_CHECKS) {
47
+ console.error(`WebSocket timeout for ${Exchange_name} after ${elapsed}ms`)
48
+ reject(new Error(`WebSocket timeout for ${Exchange_name}`))
49
+ return
50
+ }
51
+
52
+ // Safety check for WebSocket object
53
+ if (!Exchange.ws || !Exchange.ws.market) {
54
+ console.error(`${Exchange_name} WebSocket object missing during check`)
55
+ reject(new Error(`WebSocket object missing for ${Exchange_name}`))
56
+ return
57
+ }
58
+
31
59
  let all_pairs_opened = exchange_pair_dict[Exchange_name].every((pair) => {
32
- return Exchange.ws.market.pair_status[pair] === 'opened' && Exchange.ws.market.asks_dict[pair].length > 0 && Exchange.ws.market.bids_dict[pair].length > 0
60
+ return (
61
+ Exchange.ws.market.pair_status &&
62
+ Exchange.ws.market.pair_status[pair] === 'opened' &&
63
+ Exchange.ws.market.asks_dict &&
64
+ Exchange.ws.market.asks_dict[pair] &&
65
+ Exchange.ws.market.asks_dict[pair].length > 0 &&
66
+ Exchange.ws.market.bids_dict &&
67
+ Exchange.ws.market.bids_dict[pair] &&
68
+ Exchange.ws.market.bids_dict[pair].length > 0
69
+ )
33
70
  })
34
71
  if (all_pairs_opened) {
35
72
  let rate_promises = exchange_pair_dict[Exchange_name].map((pair) => {
@@ -129,6 +166,7 @@ const get_exchanges_rates = function (Exchanges, exchange_pair_dict, cb, ws_enab
129
166
  })
130
167
  .catch((error) => {
131
168
  console.error('Error in fetching exchange rates:', error)
169
+ // Still call callback with available data even if some promises failed
132
170
  cb({ exchange_pair_rates, pair_exchange_rates })
133
171
  })
134
172
  }
@@ -154,13 +192,48 @@ const get_exchanges_market_history = function (Exchanges, exchange_pair_dict, ti
154
192
  }
155
193
  if (Exchange.ws_market && ws_enabled) {
156
194
  let ws_promise = new Promise((resolve, reject) => {
195
+ if (!Exchange.ws || !Exchange.ws.market) {
196
+ console.error(`${Exchange_name} WebSocket not properly initialized`)
197
+ reject(new Error(`WebSocket not initialized for ${Exchange_name}`))
198
+ return
199
+ }
200
+
157
201
  if (!first_time[Exchange_name]) {
158
202
  Exchange.ws_market(exchange_pair_dict[Exchange_name])
159
203
  first_time[Exchange_name] = true
160
204
  }
205
+
206
+ const WS_TIMEOUT_MS = 30000 // 30 seconds timeout
207
+ const start_time = Date.now()
208
+ let check_count = 0
209
+ const MAX_CHECKS = 300 // 30 seconds / 100ms
210
+
161
211
  const check_status = () => {
212
+ check_count++
213
+ const elapsed = Date.now() - start_time
214
+
215
+ // Timeout check
216
+ if (elapsed > WS_TIMEOUT_MS || check_count > MAX_CHECKS) {
217
+ console.error(`WebSocket timeout for ${Exchange_name} market history after ${elapsed}ms`)
218
+ reject(new Error(`WebSocket timeout for ${Exchange_name} market history`))
219
+ return
220
+ }
221
+
222
+ // Safety check for WebSocket object
223
+ if (!Exchange.ws || !Exchange.ws.market) {
224
+ console.error(`${Exchange_name} WebSocket object missing during check`)
225
+ reject(new Error(`WebSocket object missing for ${Exchange_name}`))
226
+ return
227
+ }
228
+
162
229
  let all_pairs_opened = exchange_pair_dict[Exchange_name].every((pair) => {
163
- return Exchange.ws.market.pair_status[pair] === 'opened' && Exchange.ws.market.market_history_dict[pair].length >= 0
230
+ return (
231
+ Exchange.ws.market.pair_status &&
232
+ Exchange.ws.market.pair_status[pair] === 'opened' &&
233
+ Exchange.ws.market.market_history_dict &&
234
+ Exchange.ws.market.market_history_dict[pair] &&
235
+ Exchange.ws.market.market_history_dict[pair].length >= 0
236
+ )
164
237
  })
165
238
  if (all_pairs_opened) {
166
239
  let market_history_promises = exchange_pair_dict[Exchange_name].map((pair) => {
@@ -237,6 +310,8 @@ let checked_ohlcv_exchange = {},
237
310
  pair_exchange_ohlcv = {}
238
311
  const get_exchanges_ohlcv = function (Exchanges, exchange_pair_dict, from_in_ms, to_in_ms, cb) {
239
312
  checked_ohlcv_exchange = {}
313
+ ohlcv_status = {}
314
+ ohlcv_status._callback_fired = false // Reset callback flag
240
315
  if (!Array.isArray(Exchanges)) {
241
316
  console.error('Exchanges should be an array')
242
317
  return
@@ -267,13 +342,17 @@ const get_exchanges_ohlcv = function (Exchanges, exchange_pair_dict, from_in_ms,
267
342
  }
268
343
  }
269
344
  _.set(ohlcv_status, [Exchange_name + pair], true)
270
- if (!_.includes(_.values(ohlcv_status), false)) {
345
+ // Use a flag to prevent multiple callback calls
346
+ if (!_.includes(_.values(ohlcv_status), false) && !ohlcv_status._callback_fired) {
347
+ ohlcv_status._callback_fired = true
271
348
  cb({ exchange_pair_ohlcv, pair_exchange_ohlcv })
272
349
  }
273
350
  })
274
351
  } else {
275
352
  _.set(ohlcv_status, [Exchange_name + pair], true)
276
- if (!_.includes(_.values(ohlcv_status), false)) {
353
+ // Use a flag to prevent multiple callback calls
354
+ if (!_.includes(_.values(ohlcv_status), false) && !ohlcv_status._callback_fired) {
355
+ ohlcv_status._callback_fired = true
277
356
  cb({ exchange_pair_ohlcv, pair_exchange_ohlcv })
278
357
  }
279
358
  }
@@ -130,11 +130,11 @@ module.exports = class Account {
130
130
  if (_.includes(constants.stablecoins, cur)) {
131
131
  profit.USD += position
132
132
  } else if (_.includes(['KRW'], cur)) {
133
- profit.USD += position / this.forex_rates['KRWUSD']
133
+ profit.USD += position * this.forex_rates['KRWUSD']
134
134
  } else if (_.includes(['HKD'], cur)) {
135
- profit.USD += position / this.forex_rates['HKDUSD']
135
+ profit.USD += position * this.forex_rates['HKDUSD']
136
136
  } else if (_.includes(['CNYT'], cur)) {
137
- profit.USD += position / this.forex_rates['CNYUSD']
137
+ profit.USD += position * this.forex_rates['CNYUSD']
138
138
  } else {
139
139
  if (!cmc_rates[cur]) {
140
140
  console.log('get_exchange_profit rates_cmc %s does not exist', cur)
@@ -199,7 +199,6 @@ module.exports = class Orders {
199
199
  market_history_check: true,
200
200
  ohlcv_check: false,
201
201
  cmc_rates_check: true,
202
- all_orders_store: false,
203
202
  }
204
203
  if (this.function_enabled.balances_check) {
205
204
  this.check_balances()
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@icgio/icg-exchanges-wrapper",
3
- "version": "1.14.254",
3
+ "version": "1.14.256",
4
4
  "description": "",
5
5
  "main": "index.js",
6
6
  "scripts": {