@upbit-official/upbit-sdk 0.9.0 → 1.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.
Files changed (406) hide show
  1. package/CHANGELOG.md +13 -0
  2. package/README.md +36 -16
  3. package/client.d.mts +13 -4
  4. package/client.d.mts.map +1 -1
  5. package/client.d.ts +13 -4
  6. package/client.d.ts.map +1 -1
  7. package/client.js +26 -4
  8. package/client.js.map +1 -1
  9. package/client.mjs +26 -4
  10. package/client.mjs.map +1 -1
  11. package/core/api-promise.d.mts.map +1 -1
  12. package/core/api-promise.d.ts.map +1 -1
  13. package/core/api-promise.js.map +1 -1
  14. package/core/api-promise.mjs.map +1 -1
  15. package/core/error.d.mts.map +1 -1
  16. package/core/error.d.ts.map +1 -1
  17. package/core/error.js.map +1 -1
  18. package/core/error.mjs.map +1 -1
  19. package/core/pagination.d.mts.map +1 -1
  20. package/core/pagination.d.ts.map +1 -1
  21. package/core/pagination.js.map +1 -1
  22. package/core/pagination.mjs.map +1 -1
  23. package/core/resource.d.mts.map +1 -1
  24. package/core/resource.d.ts.map +1 -1
  25. package/core/resource.js.map +1 -1
  26. package/core/resource.mjs.map +1 -1
  27. package/index.d.mts +3 -1
  28. package/index.d.mts.map +1 -1
  29. package/index.d.ts +3 -1
  30. package/index.d.ts.map +1 -1
  31. package/index.js +2 -1
  32. package/index.js.map +1 -1
  33. package/index.mjs +1 -1
  34. package/index.mjs.map +1 -1
  35. package/internal/builtin-types.d.mts.map +1 -1
  36. package/internal/builtin-types.d.ts.map +1 -1
  37. package/internal/errors.d.mts.map +1 -1
  38. package/internal/errors.d.ts.map +1 -1
  39. package/internal/errors.js.map +1 -1
  40. package/internal/errors.mjs.map +1 -1
  41. package/internal/headers.d.mts.map +1 -1
  42. package/internal/headers.d.ts.map +1 -1
  43. package/internal/headers.js.map +1 -1
  44. package/internal/headers.mjs.map +1 -1
  45. package/internal/parse.d.mts.map +1 -1
  46. package/internal/parse.d.ts.map +1 -1
  47. package/internal/parse.js.map +1 -1
  48. package/internal/parse.mjs.map +1 -1
  49. package/internal/request-options.d.mts.map +1 -1
  50. package/internal/request-options.d.ts.map +1 -1
  51. package/internal/request-options.js.map +1 -1
  52. package/internal/request-options.mjs.map +1 -1
  53. package/internal/shim-types.d.mts.map +1 -1
  54. package/internal/shim-types.d.ts.map +1 -1
  55. package/internal/shim-types.js.map +1 -1
  56. package/internal/shim-types.mjs.map +1 -1
  57. package/internal/shims.d.mts.map +1 -1
  58. package/internal/shims.d.ts.map +1 -1
  59. package/internal/shims.js.map +1 -1
  60. package/internal/shims.mjs.map +1 -1
  61. package/internal/types.d.mts.map +1 -1
  62. package/internal/types.d.ts.map +1 -1
  63. package/internal/utils/base64.d.mts.map +1 -1
  64. package/internal/utils/base64.d.ts.map +1 -1
  65. package/internal/utils/base64.js.map +1 -1
  66. package/internal/utils/base64.mjs.map +1 -1
  67. package/internal/utils/env.d.mts.map +1 -1
  68. package/internal/utils/env.d.ts.map +1 -1
  69. package/internal/utils/env.js.map +1 -1
  70. package/internal/utils/env.mjs.map +1 -1
  71. package/internal/utils/log.d.mts.map +1 -1
  72. package/internal/utils/log.d.ts.map +1 -1
  73. package/internal/utils/log.js.map +1 -1
  74. package/internal/utils/log.mjs.map +1 -1
  75. package/internal/utils/query.d.mts.map +1 -1
  76. package/internal/utils/query.d.ts.map +1 -1
  77. package/internal/utils/query.js.map +1 -1
  78. package/internal/utils/query.mjs.map +1 -1
  79. package/internal/utils/sleep.d.mts.map +1 -1
  80. package/internal/utils/sleep.d.ts.map +1 -1
  81. package/internal/utils/sleep.js.map +1 -1
  82. package/internal/utils/sleep.mjs.map +1 -1
  83. package/internal/utils/uuid.d.mts.map +1 -1
  84. package/internal/utils/uuid.d.ts.map +1 -1
  85. package/internal/utils/uuid.js.map +1 -1
  86. package/internal/utils/uuid.mjs.map +1 -1
  87. package/internal/utils/values.d.mts.map +1 -1
  88. package/internal/utils/values.d.ts.map +1 -1
  89. package/internal/utils/values.js.map +1 -1
  90. package/internal/utils/values.mjs.map +1 -1
  91. package/internal/utils.js.map +1 -1
  92. package/internal/ws-parser.d.mts +40 -0
  93. package/internal/ws-parser.d.mts.map +1 -0
  94. package/internal/ws-parser.d.ts +40 -0
  95. package/internal/ws-parser.d.ts.map +1 -0
  96. package/internal/ws-parser.js +125 -0
  97. package/internal/ws-parser.js.map +1 -0
  98. package/internal/ws-parser.mjs +118 -0
  99. package/internal/ws-parser.mjs.map +1 -0
  100. package/internal/ws-simple-types.d.mts +8 -0
  101. package/internal/ws-simple-types.d.mts.map +1 -0
  102. package/internal/ws-simple-types.d.ts +8 -0
  103. package/internal/ws-simple-types.d.ts.map +1 -0
  104. package/internal/ws-simple-types.js +3 -0
  105. package/internal/ws-simple-types.js.map +1 -0
  106. package/internal/ws-simple-types.mjs +2 -0
  107. package/internal/ws-simple-types.mjs.map +1 -0
  108. package/internal/ws.d.mts +1 -0
  109. package/internal/ws.d.mts.map +1 -1
  110. package/internal/ws.d.ts +1 -0
  111. package/internal/ws.d.ts.map +1 -1
  112. package/internal/ws.js.map +1 -1
  113. package/internal/ws.mjs.map +1 -1
  114. package/lib/index.d.mts +4 -2
  115. package/lib/index.d.mts.map +1 -1
  116. package/lib/index.d.ts +4 -2
  117. package/lib/index.d.ts.map +1 -1
  118. package/lib/index.js +2 -1
  119. package/lib/index.js.map +1 -1
  120. package/lib/index.mjs +1 -1
  121. package/lib/index.mjs.map +1 -1
  122. package/lib/jsonParseFloat.d.mts +5 -5
  123. package/lib/jsonParseFloat.d.mts.map +1 -1
  124. package/lib/jsonParseFloat.d.ts +5 -5
  125. package/lib/jsonParseFloat.d.ts.map +1 -1
  126. package/lib/jsonParseFloat.js +31 -12
  127. package/lib/jsonParseFloat.js.map +1 -1
  128. package/lib/jsonParseFloat.mjs +31 -12
  129. package/lib/jsonParseFloat.mjs.map +1 -1
  130. package/lib/ws.d.mts +102 -15
  131. package/lib/ws.d.mts.map +1 -1
  132. package/lib/ws.d.ts +102 -15
  133. package/lib/ws.d.ts.map +1 -1
  134. package/lib/ws.js +208 -34
  135. package/lib/ws.js.map +1 -1
  136. package/lib/ws.mjs +204 -33
  137. package/lib/ws.mjs.map +1 -1
  138. package/package.json +15 -9
  139. package/resources/accounts.d.mts +2 -0
  140. package/resources/accounts.d.mts.map +1 -1
  141. package/resources/accounts.d.ts +2 -0
  142. package/resources/accounts.d.ts.map +1 -1
  143. package/resources/accounts.js +2 -0
  144. package/resources/accounts.js.map +1 -1
  145. package/resources/accounts.mjs +2 -0
  146. package/resources/accounts.mjs.map +1 -1
  147. package/resources/api-keys.d.mts +3 -1
  148. package/resources/api-keys.d.mts.map +1 -1
  149. package/resources/api-keys.d.ts +3 -1
  150. package/resources/api-keys.d.ts.map +1 -1
  151. package/resources/api-keys.js +3 -1
  152. package/resources/api-keys.js.map +1 -1
  153. package/resources/api-keys.mjs +3 -1
  154. package/resources/api-keys.mjs.map +1 -1
  155. package/resources/candles.d.mts +21 -1
  156. package/resources/candles.d.mts.map +1 -1
  157. package/resources/candles.d.ts +21 -1
  158. package/resources/candles.d.ts.map +1 -1
  159. package/resources/candles.js +12 -0
  160. package/resources/candles.js.map +1 -1
  161. package/resources/candles.mjs +12 -0
  162. package/resources/candles.mjs.map +1 -1
  163. package/resources/deposits.d.mts +18 -1
  164. package/resources/deposits.d.mts.map +1 -1
  165. package/resources/deposits.d.ts +18 -1
  166. package/resources/deposits.d.ts.map +1 -1
  167. package/resources/deposits.js +18 -1
  168. package/resources/deposits.js.map +1 -1
  169. package/resources/deposits.mjs +18 -1
  170. package/resources/deposits.mjs.map +1 -1
  171. package/resources/index.d.mts +4 -2
  172. package/resources/index.d.mts.map +1 -1
  173. package/resources/index.d.ts +4 -2
  174. package/resources/index.d.ts.map +1 -1
  175. package/resources/index.js +5 -1
  176. package/resources/index.js.map +1 -1
  177. package/resources/index.mjs +4 -2
  178. package/resources/index.mjs.map +1 -1
  179. package/resources/orderbooks.d.mts +4 -0
  180. package/resources/orderbooks.d.mts.map +1 -1
  181. package/resources/orderbooks.d.ts +4 -0
  182. package/resources/orderbooks.d.ts.map +1 -1
  183. package/resources/orderbooks.js +4 -0
  184. package/resources/orderbooks.js.map +1 -1
  185. package/resources/orderbooks.mjs +4 -0
  186. package/resources/orderbooks.mjs.map +1 -1
  187. package/resources/orders.d.mts +12 -2
  188. package/resources/orders.d.mts.map +1 -1
  189. package/resources/orders.d.ts +12 -2
  190. package/resources/orders.d.ts.map +1 -1
  191. package/resources/orders.js +12 -2
  192. package/resources/orders.js.map +1 -1
  193. package/resources/orders.mjs +12 -2
  194. package/resources/orders.mjs.map +1 -1
  195. package/resources/pockets.d.mts +509 -0
  196. package/resources/pockets.d.mts.map +1 -0
  197. package/resources/pockets.d.ts +509 -0
  198. package/resources/pockets.d.ts.map +1 -0
  199. package/resources/pockets.js +157 -0
  200. package/resources/pockets.js.map +1 -0
  201. package/resources/pockets.mjs +153 -0
  202. package/resources/pockets.mjs.map +1 -0
  203. package/resources/tickers.d.mts +6 -0
  204. package/resources/tickers.d.mts.map +1 -1
  205. package/resources/tickers.d.ts +6 -0
  206. package/resources/tickers.d.ts.map +1 -1
  207. package/resources/tickers.js +6 -0
  208. package/resources/tickers.js.map +1 -1
  209. package/resources/tickers.mjs +6 -0
  210. package/resources/tickers.mjs.map +1 -1
  211. package/resources/trades.d.mts +5 -3
  212. package/resources/trades.d.mts.map +1 -1
  213. package/resources/trades.d.ts +5 -3
  214. package/resources/trades.d.ts.map +1 -1
  215. package/resources/trades.js +5 -3
  216. package/resources/trades.js.map +1 -1
  217. package/resources/trades.mjs +5 -3
  218. package/resources/trades.mjs.map +1 -1
  219. package/resources/trading-pairs.d.mts +2 -0
  220. package/resources/trading-pairs.d.mts.map +1 -1
  221. package/resources/trading-pairs.d.ts +2 -0
  222. package/resources/trading-pairs.d.ts.map +1 -1
  223. package/resources/trading-pairs.js +2 -0
  224. package/resources/trading-pairs.js.map +1 -1
  225. package/resources/trading-pairs.mjs +2 -0
  226. package/resources/trading-pairs.mjs.map +1 -1
  227. package/resources/travel-rule.d.mts +6 -0
  228. package/resources/travel-rule.d.mts.map +1 -1
  229. package/resources/travel-rule.d.ts +6 -0
  230. package/resources/travel-rule.d.ts.map +1 -1
  231. package/resources/travel-rule.js +6 -0
  232. package/resources/travel-rule.js.map +1 -1
  233. package/resources/travel-rule.mjs +6 -0
  234. package/resources/travel-rule.mjs.map +1 -1
  235. package/resources/wallet-status.d.mts +2 -0
  236. package/resources/wallet-status.d.mts.map +1 -1
  237. package/resources/wallet-status.d.ts +2 -0
  238. package/resources/wallet-status.d.ts.map +1 -1
  239. package/resources/wallet-status.js +2 -0
  240. package/resources/wallet-status.js.map +1 -1
  241. package/resources/wallet-status.mjs +2 -0
  242. package/resources/wallet-status.mjs.map +1 -1
  243. package/resources/withdraws.d.mts +18 -1
  244. package/resources/withdraws.d.mts.map +1 -1
  245. package/resources/withdraws.d.ts +18 -1
  246. package/resources/withdraws.d.ts.map +1 -1
  247. package/resources/withdraws.js +18 -1
  248. package/resources/withdraws.js.map +1 -1
  249. package/resources/withdraws.mjs +18 -1
  250. package/resources/withdraws.mjs.map +1 -1
  251. package/resources/ws-info/index.d.mts +6 -0
  252. package/resources/ws-info/index.d.mts.map +1 -0
  253. package/resources/ws-info/index.d.ts +6 -0
  254. package/resources/ws-info/index.d.ts.map +1 -0
  255. package/resources/ws-info/index.js +6 -0
  256. package/resources/ws-info/index.js.map +1 -0
  257. package/resources/ws-info/index.mjs +2 -0
  258. package/resources/ws-info/index.mjs.map +1 -0
  259. package/resources/ws-info/internal-base.d.mts +63 -0
  260. package/resources/ws-info/internal-base.d.mts.map +1 -0
  261. package/resources/ws-info/internal-base.d.ts +63 -0
  262. package/resources/ws-info/internal-base.d.ts.map +1 -0
  263. package/resources/ws-info/internal-base.js +47 -0
  264. package/resources/ws-info/internal-base.js.map +1 -0
  265. package/resources/ws-info/internal-base.mjs +41 -0
  266. package/resources/ws-info/internal-base.mjs.map +1 -0
  267. package/resources/ws-info/ws-info.d.mts +1180 -0
  268. package/resources/ws-info/ws-info.d.mts.map +1 -0
  269. package/resources/ws-info/ws-info.d.ts +1180 -0
  270. package/resources/ws-info/ws-info.d.ts.map +1 -0
  271. package/resources/ws-info/ws-info.js +8 -0
  272. package/resources/ws-info/ws-info.js.map +1 -0
  273. package/resources/ws-info/ws-info.mjs +4 -0
  274. package/resources/ws-info/ws-info.mjs.map +1 -0
  275. package/resources/ws-info/ws.d.mts +91 -0
  276. package/resources/ws-info/ws.d.mts.map +1 -0
  277. package/resources/ws-info/ws.d.ts +91 -0
  278. package/resources/ws-info/ws.d.ts.map +1 -0
  279. package/resources/ws-info/ws.js +463 -0
  280. package/resources/ws-info/ws.js.map +1 -0
  281. package/resources/ws-info/ws.mjs +458 -0
  282. package/resources/ws-info/ws.mjs.map +1 -0
  283. package/resources/ws-info.d.mts +2 -0
  284. package/resources/ws-info.d.mts.map +1 -0
  285. package/resources/ws-info.d.ts +2 -0
  286. package/resources/ws-info.d.ts.map +1 -0
  287. package/resources/ws-info.js +5 -0
  288. package/resources/ws-info.js.map +1 -0
  289. package/resources/ws-info.mjs +2 -0
  290. package/resources/ws-info.mjs.map +1 -0
  291. package/resources/ws-private/index.d.mts +3 -1
  292. package/resources/ws-private/index.d.mts.map +1 -1
  293. package/resources/ws-private/index.d.ts +3 -1
  294. package/resources/ws-private/index.d.ts.map +1 -1
  295. package/resources/ws-private/index.js.map +1 -1
  296. package/resources/ws-private/index.mjs +1 -1
  297. package/resources/ws-private/index.mjs.map +1 -1
  298. package/resources/ws-private/internal-base.d.mts.map +1 -1
  299. package/resources/ws-private/internal-base.d.ts.map +1 -1
  300. package/resources/ws-private/internal-base.js.map +1 -1
  301. package/resources/ws-private/internal-base.mjs.map +1 -1
  302. package/resources/ws-private/ws-private.d.mts +301 -9
  303. package/resources/ws-private/ws-private.d.mts.map +1 -1
  304. package/resources/ws-private/ws-private.d.ts +301 -9
  305. package/resources/ws-private/ws-private.d.ts.map +1 -1
  306. package/resources/ws-private/ws-private.js.map +1 -1
  307. package/resources/ws-private/ws-private.mjs.map +1 -1
  308. package/resources/ws-private/ws.d.mts +2 -2
  309. package/resources/ws-private/ws.d.mts.map +1 -1
  310. package/resources/ws-private/ws.d.ts +2 -2
  311. package/resources/ws-private/ws.d.ts.map +1 -1
  312. package/resources/ws-private/ws.js +15 -20
  313. package/resources/ws-private/ws.js.map +1 -1
  314. package/resources/ws-private/ws.mjs +15 -20
  315. package/resources/ws-private/ws.mjs.map +1 -1
  316. package/resources/ws-private.js.map +1 -1
  317. package/resources/ws-public/index.d.mts +3 -1
  318. package/resources/ws-public/index.d.mts.map +1 -1
  319. package/resources/ws-public/index.d.ts +3 -1
  320. package/resources/ws-public/index.d.ts.map +1 -1
  321. package/resources/ws-public/index.js.map +1 -1
  322. package/resources/ws-public/index.mjs +1 -1
  323. package/resources/ws-public/index.mjs.map +1 -1
  324. package/resources/ws-public/internal-base.d.mts.map +1 -1
  325. package/resources/ws-public/internal-base.d.ts.map +1 -1
  326. package/resources/ws-public/internal-base.js.map +1 -1
  327. package/resources/ws-public/internal-base.mjs.map +1 -1
  328. package/resources/ws-public/ws-public.d.mts +355 -5
  329. package/resources/ws-public/ws-public.d.mts.map +1 -1
  330. package/resources/ws-public/ws-public.d.ts +355 -5
  331. package/resources/ws-public/ws-public.d.ts.map +1 -1
  332. package/resources/ws-public/ws-public.js.map +1 -1
  333. package/resources/ws-public/ws-public.mjs.map +1 -1
  334. package/resources/ws-public/ws.d.mts +2 -2
  335. package/resources/ws-public/ws.d.mts.map +1 -1
  336. package/resources/ws-public/ws.d.ts +2 -2
  337. package/resources/ws-public/ws.d.ts.map +1 -1
  338. package/resources/ws-public/ws.js +15 -20
  339. package/resources/ws-public/ws.js.map +1 -1
  340. package/resources/ws-public/ws.mjs +15 -20
  341. package/resources/ws-public/ws.mjs.map +1 -1
  342. package/resources/ws-public.js.map +1 -1
  343. package/src/client.ts +141 -5
  344. package/src/core/api-promise.ts +0 -1
  345. package/src/core/error.ts +0 -1
  346. package/src/core/pagination.ts +0 -1
  347. package/src/core/resource.ts +0 -1
  348. package/src/index.ts +24 -2
  349. package/src/internal/builtin-types.ts +0 -1
  350. package/src/internal/errors.ts +0 -1
  351. package/src/internal/headers.ts +0 -1
  352. package/src/internal/parse.ts +0 -1
  353. package/src/internal/request-options.ts +0 -1
  354. package/src/internal/shim-types.ts +0 -1
  355. package/src/internal/shims.ts +0 -1
  356. package/src/internal/types.ts +0 -1
  357. package/src/internal/utils/base64.ts +0 -1
  358. package/src/internal/utils/env.ts +0 -1
  359. package/src/internal/utils/log.ts +0 -1
  360. package/src/internal/utils/query.ts +0 -1
  361. package/src/internal/utils/sleep.ts +0 -1
  362. package/src/internal/utils/uuid.ts +0 -1
  363. package/src/internal/utils/values.ts +0 -1
  364. package/src/internal/utils.ts +0 -1
  365. package/src/internal/ws-parser.ts +164 -0
  366. package/src/internal/ws-simple-types.ts +34 -0
  367. package/src/internal/ws.ts +1 -0
  368. package/src/lib/index.ts +17 -2
  369. package/src/lib/jsonParseFloat.ts +38 -12
  370. package/src/lib/ws.ts +367 -55
  371. package/src/resources/accounts.ts +2 -1
  372. package/src/resources/api-keys.ts +3 -2
  373. package/src/resources/candles.ts +22 -2
  374. package/src/resources/deposits.ts +18 -2
  375. package/src/resources/index.ts +65 -3
  376. package/src/resources/orderbooks.ts +4 -1
  377. package/src/resources/orders.ts +12 -3
  378. package/src/resources/pockets.ts +639 -0
  379. package/src/resources/tickers.ts +6 -1
  380. package/src/resources/trades.ts +5 -4
  381. package/src/resources/trading-pairs.ts +2 -1
  382. package/src/resources/travel-rule.ts +6 -1
  383. package/src/resources/wallet-status.ts +2 -1
  384. package/src/resources/withdraws.ts +18 -2
  385. package/src/resources/ws-info/index.ts +44 -0
  386. package/src/resources/ws-info/internal-base.ts +96 -0
  387. package/src/resources/ws-info/ws-info.ts +1855 -0
  388. package/src/resources/ws-info/ws.ts +574 -0
  389. package/src/resources/ws-info.ts +1 -0
  390. package/src/resources/ws-private/index.ts +12 -2
  391. package/src/resources/ws-private/internal-base.ts +0 -2
  392. package/src/resources/ws-private/ws-private.ts +419 -18
  393. package/src/resources/ws-private/ws.ts +16 -24
  394. package/src/resources/ws-private.ts +0 -1
  395. package/src/resources/ws-public/index.ts +16 -2
  396. package/src/resources/ws-public/internal-base.ts +0 -2
  397. package/src/resources/ws-public/ws-public.ts +459 -5
  398. package/src/resources/ws-public/ws.ts +16 -24
  399. package/src/resources/ws-public.ts +0 -1
  400. package/src/version.ts +1 -1
  401. package/version.d.mts +1 -1
  402. package/version.d.ts +1 -1
  403. package/version.js +1 -1
  404. package/version.js.map +1 -1
  405. package/version.mjs +1 -1
  406. package/version.mjs.map +1 -1
package/src/lib/ws.ts CHANGED
@@ -1,14 +1,31 @@
1
1
  import * as WS from 'ws';
2
2
  import { uuid4 } from '../internal/utils/uuid';
3
3
  import { createJwtToken } from './jwtAuth';
4
- import { jsonParseFloat } from './jsonParseFloat';
5
4
  import { buildURL as buildPublicURL } from '../resources/ws-public/internal-base';
6
5
  import { buildURL as buildPrivateURL } from '../resources/ws-private/internal-base';
6
+ import { buildURL as buildInfoURL } from '../resources/ws-info/internal-base';
7
7
  import type { ConnectPublicServerEvent } from '../resources/ws-public/ws-public';
8
- import type { ConnectPrivateServerEvent } from '../resources/ws-private/ws-private';
8
+ import type {
9
+ ListSubscriptionsResponse,
10
+ ListSubscriptionsServerResponse,
11
+ SimpleListSubscriptionsResponse,
12
+ } from '../resources/ws-public/ws-public';
13
+ import type { AnnouncementCategory, ConnectPrivateServerEvent } from '../resources/ws-private/ws-private';
14
+ import type { ConnectInfoServerEvent } from '../resources/ws-info/ws-info';
15
+ import type { ConnectInfoClientEvent } from '../resources/ws-info/ws-info';
16
+ import {
17
+ parseWebSocketValue,
18
+ isListSubscriptionsResponse,
19
+ type InfoWebSocketUnknownMessage,
20
+ type WebSocketMessage,
21
+ } from '../internal/ws-parser';
22
+ import type { SimpleWebSocketEvent } from '../internal/ws-simple-types';
23
+ import type { SimpleWebSocketEvent as ExtensibleSimpleEvent } from '../internal/ws-parser';
9
24
  import type { Upbit } from '../client';
10
25
 
11
26
  export interface WsStreamOptions {
27
+ /** Response format (default: DEFAULT). Preserved for queries and reconnects. */
28
+ format?: WsStreamFormat;
12
29
  /** Maximum number of reconnection attempts (default: 5) */
13
30
  maxRetries?: number;
14
31
  /** Reconnection delay in ms (default: 1000) */
@@ -19,55 +36,220 @@ export interface WsStreamOptions {
19
36
  onReconnect?: () => void;
20
37
  }
21
38
 
39
+ export type WsStreamFormat = 'DEFAULT' | 'SIMPLE' | 'JSON_LIST' | 'SIMPLE_LIST';
40
+
41
+ export enum WsEndpoint {
42
+ Public = 'public',
43
+ Private = 'private',
44
+ Info = 'info',
45
+ }
46
+
47
+ function requiresAuth(endpoint: WsEndpoint): boolean {
48
+ return endpoint !== WsEndpoint.Public;
49
+ }
50
+
51
+ export type WsDefaultListSubscriptionsResponse = ListSubscriptionsResponse;
52
+
53
+ export type WsSimpleListSubscriptionsResponse = SimpleListSubscriptionsResponse;
54
+
55
+ export type WsListSubscriptionsResponse = ListSubscriptionsServerResponse;
56
+
57
+ export interface WsAnnouncementOptions extends WsStreamOptions {
58
+ /** Response format (default: DEFAULT). */
59
+ format?: WsStreamFormat;
60
+ /** Announcement categories to receive. Omit to receive all categories. */
61
+ categories?: AnnouncementCategory[];
62
+ /** Whether to include the announcement body in stream messages. */
63
+ includeBody?: boolean;
64
+ }
65
+
66
+ export type WsIndicatorSubscription = Omit<Extract<InfoSubscription, { type: 'indicator' }>, 'type'>;
67
+
68
+ export interface WsIndicatorOptions extends Omit<WsIndicatorSubscription, 'codes'>, WsStreamOptions {
69
+ format?: WsStreamFormat;
70
+ }
71
+
72
+ export type WsIndicatorSignalSubscription = Omit<
73
+ Extract<InfoSubscription, { type: 'indicator_signal' }>,
74
+ 'type'
75
+ >;
76
+ export interface WsIndicatorSignalOptions
77
+ extends Omit<WsIndicatorSignalSubscription, 'codes'>,
78
+ WsStreamOptions {
79
+ format?: WsStreamFormat;
80
+ }
81
+
22
82
  type PublicSubscriptionType =
23
83
  | { type: 'ticker'; codes: string[] }
24
84
  | { type: 'trade'; codes: string[] }
25
85
  | { type: 'orderbook'; codes: string[] }
26
86
  | { type: string; codes: string[] }; // candle.{interval}
27
87
 
28
- type PrivateSubscriptionType = { type: 'myOrder'; codes?: string[] } | { type: 'myAsset' };
29
-
30
- type AnySubscriptionType = PublicSubscriptionType | PrivateSubscriptionType;
31
-
32
- function buildSubscriptionMessage(types: AnySubscriptionType[]): string {
88
+ type AnnouncementSubscriptionType = {
89
+ type: 'announcement';
90
+ categories?: AnnouncementCategory[];
91
+ include_body?: boolean;
92
+ };
93
+
94
+ type PrivateSubscriptionType =
95
+ | AnnouncementSubscriptionType
96
+ | { type: 'myOrder'; codes?: string[] }
97
+ | { type: 'myAsset' };
98
+
99
+ export type InfoSubscription = Extract<
100
+ ConnectInfoClientEvent[number],
101
+ { type: 'indicator' | 'indicator_signal' }
102
+ >;
103
+
104
+ type AnySubscriptionType = PublicSubscriptionType | PrivateSubscriptionType | InfoSubscription;
105
+ type WsServerEvent =
106
+ | ConnectPublicServerEvent
107
+ | ConnectPrivateServerEvent
108
+ | ConnectInfoServerEvent
109
+ | InfoWebSocketUnknownMessage;
110
+ export type WsSimpleEvent = SimpleWebSocketEvent;
111
+ export type WsStreamEvent =
112
+ | WebSocketMessage<WsServerEvent | WsSimpleEvent | ExtensibleSimpleEvent>
113
+ | WsListSubscriptionsResponse
114
+ | Array<
115
+ WebSocketMessage<WsServerEvent | WsSimpleEvent | ExtensibleSimpleEvent> | WsListSubscriptionsResponse
116
+ >;
117
+
118
+ type PublicEvent<Type extends ConnectPublicServerEvent['type']> = Extract<
119
+ ConnectPublicServerEvent,
120
+ { type: Type }
121
+ >;
122
+ type CandleEvent = Exclude<ConnectPublicServerEvent, PublicEvent<'ticker' | 'trade' | 'orderbook'>>;
123
+ type PrivateEvent<Type extends ConnectPrivateServerEvent['type']> = Extract<
124
+ ConnectPrivateServerEvent,
125
+ { type: Type }
126
+ >;
127
+ type InfoEvent<Type extends ConnectInfoServerEvent['type']> = Extract<ConnectInfoServerEvent, { type: Type }>;
128
+
129
+ export function buildSubscriptionMessage(types: AnySubscriptionType[], format?: WsStreamFormat): string {
33
130
  const fields: object[] = [{ ticket: uuid4() }];
34
131
  for (const t of types) {
35
- if ('codes' in t && t.codes) {
36
- fields.push({ type: t.type, codes: t.codes });
37
- } else {
38
- fields.push({ type: t.type });
39
- }
132
+ fields.push(t);
40
133
  }
134
+ if (format !== undefined) fields.push({ format });
135
+ return JSON.stringify(fields);
136
+ }
137
+
138
+ export function buildListSubscriptionsMessage(format?: WsStreamFormat): string {
139
+ const fields: object[] = [{ ticket: uuid4() }, { method: 'LIST_SUBSCRIPTIONS' }];
140
+ if (format !== undefined) fields.push({ format });
41
141
  return JSON.stringify(fields);
42
142
  }
43
143
 
144
+ export function parseWsMessage(data: string): unknown {
145
+ return parseWebSocketValue(data);
146
+ }
147
+
148
+ function buildAnnouncementSubscription(
149
+ categories?: AnnouncementCategory[],
150
+ includeBody?: boolean,
151
+ ): AnnouncementSubscriptionType {
152
+ const subscription: AnnouncementSubscriptionType = { type: 'announcement' };
153
+ if (categories !== undefined) subscription.categories = categories;
154
+ if (includeBody !== undefined) subscription.include_body = includeBody;
155
+ return subscription;
156
+ }
157
+
44
158
  /**
45
159
  * Manages a WebSocket stream as an AsyncIterable.
46
160
  *
47
161
  * Use with `for await (const event of manager) { ... }`.
48
162
  */
49
- export class WsStreamManager implements AsyncIterable<ConnectPublicServerEvent | ConnectPrivateServerEvent> {
163
+ export class WsStreamManager<Event = ConnectPublicServerEvent | ConnectPrivateServerEvent>
164
+ implements AsyncIterable<Event>
165
+ {
50
166
  private readonly client: Upbit;
51
167
  private readonly types: AnySubscriptionType[];
52
- private readonly isPrivate: boolean;
168
+ private readonly endpoint: WsEndpoint;
169
+ private readonly format: WsStreamFormat | undefined;
53
170
  private readonly maxRetries: number;
54
171
  private readonly retryDelayMs: number;
55
172
  private readonly onDisconnect: WsStreamOptions['onDisconnect'];
56
173
  private readonly onReconnect: WsStreamOptions['onReconnect'];
57
174
  private _currentWs: WS.WebSocket | null = null;
58
-
59
- constructor(client: Upbit, types: AnySubscriptionType[], isPrivate: boolean, opts: WsStreamOptions = {}) {
175
+ private _pendingListSubscriptions:
176
+ | {
177
+ resolve: (value: WsListSubscriptionsResponse) => void;
178
+ reject: (reason: Error) => void;
179
+ timer: ReturnType<typeof setTimeout>;
180
+ socket: WS.WebSocket;
181
+ ticket: string;
182
+ }
183
+ | undefined;
184
+
185
+ constructor(
186
+ client: Upbit,
187
+ types: AnySubscriptionType[],
188
+ privateConnection: boolean,
189
+ opts?: WsStreamOptions & { format?: WsStreamFormat },
190
+ );
191
+ constructor(
192
+ client: Upbit,
193
+ types: AnySubscriptionType[],
194
+ endpoint: WsEndpoint,
195
+ opts?: WsStreamOptions & { format?: WsStreamFormat },
196
+ );
197
+ constructor(
198
+ client: Upbit,
199
+ types: AnySubscriptionType[],
200
+ endpoint: WsEndpoint | boolean,
201
+ opts: WsStreamOptions & { format?: WsStreamFormat } = {},
202
+ ) {
60
203
  this.client = client;
61
204
  this.types = types;
62
- this.isPrivate = isPrivate;
205
+ this.endpoint =
206
+ typeof endpoint === 'boolean' ?
207
+ endpoint ? WsEndpoint.Private
208
+ : WsEndpoint.Public
209
+ : endpoint;
210
+ this.format = opts.format;
63
211
  this.maxRetries = opts.maxRetries ?? 5;
64
212
  this.retryDelayMs = opts.retryDelayMs ?? 1000;
65
213
  if (opts.onDisconnect) this.onDisconnect = opts.onDisconnect;
66
214
  if (opts.onReconnect) this.onReconnect = opts.onReconnect;
67
215
  }
68
216
 
217
+ /**
218
+ * Returns subscriptions for this stream's currently open connection.
219
+ * Start consuming the iterator before calling; calls before connection reject.
220
+ * The response format is unchanged. Responses are matched by request ticket.
221
+ */
222
+ listSubscriptions(timeoutMs = 5000): Promise<WsListSubscriptionsResponse> {
223
+ const ws = this._currentWs;
224
+ if (!ws || ws.readyState !== WS.WebSocket.OPEN) {
225
+ return Promise.reject(new Error('WebSocket connection is not open'));
226
+ }
227
+ if (this._pendingListSubscriptions) {
228
+ return Promise.reject(new Error('LIST_SUBSCRIPTIONS request is already pending'));
229
+ }
230
+ return new Promise((resolve, reject) => {
231
+ const message = buildListSubscriptionsMessage(this.format);
232
+ const ticket: string = JSON.parse(message)[0].ticket;
233
+ const timer = setTimeout(() => {
234
+ if (this._pendingListSubscriptions?.ticket === ticket) {
235
+ this._settlePendingListSubscriptions(
236
+ ws,
237
+ new Error('LIST_SUBSCRIPTIONS response not received within timeout'),
238
+ );
239
+ }
240
+ }, timeoutMs);
241
+ this._pendingListSubscriptions = { resolve, reject, timer, socket: ws, ticket };
242
+ try {
243
+ ws.send(message);
244
+ } catch (error) {
245
+ this._settlePendingListSubscriptions(ws, error instanceof Error ? error : new Error(String(error)));
246
+ }
247
+ });
248
+ }
249
+
69
250
  /** Closes the current WebSocket connection. */
70
251
  close(): void {
252
+ if (this._currentWs) this._settlePendingListSubscriptions(this._currentWs, new Error('WebSocket closed'));
71
253
  if (
72
254
  this._currentWs &&
73
255
  (this._currentWs.readyState === WS.WebSocket.OPEN ||
@@ -77,47 +259,73 @@ export class WsStreamManager implements AsyncIterable<ConnectPublicServerEvent |
77
259
  }
78
260
  }
79
261
 
80
- [Symbol.asyncIterator](): AsyncGenerator<ConnectPublicServerEvent | ConnectPrivateServerEvent> {
81
- return this._iterate();
262
+ [Symbol.asyncIterator](): AsyncGenerator<Event> {
263
+ const iterator = this._iterate();
264
+ const finish = iterator.return.bind(iterator);
265
+ iterator.return = (value) => {
266
+ if (this._currentWs)
267
+ this._settlePendingListSubscriptions(this._currentWs, new Error('WebSocket iterator ended'));
268
+ this.close();
269
+ return finish(value);
270
+ };
271
+ return iterator;
82
272
  }
83
273
 
84
- private async *_iterate(): AsyncGenerator<ConnectPublicServerEvent | ConnectPrivateServerEvent> {
274
+ private async *_iterate(): AsyncGenerator<Event> {
85
275
  let retries = 0;
86
276
 
87
277
  while (true) {
88
- const queue: Array<ConnectPublicServerEvent | ConnectPrivateServerEvent> = [];
278
+ const queue: WsStreamEvent[] = [];
89
279
  let resolve: (() => void) | null = null;
90
280
  let reject: ((err: Error) => void) | null = null;
91
281
  let done = false;
92
282
  let closeCode = 1000;
93
283
  let closeReason = '';
284
+ let pingTimer: ReturnType<typeof setInterval> | undefined;
94
285
 
95
286
  const ws = await this._connect();
96
287
  this._currentWs = ws;
97
288
 
98
289
  ws.on('message', (data: WS.RawData) => {
290
+ let parsed: unknown;
99
291
  try {
100
- const parsed = jsonParseFloat(data.toString()) as
101
- | ConnectPublicServerEvent
102
- | ConnectPrivateServerEvent;
103
- queue.push(parsed);
104
- resolve?.();
105
- resolve = null;
292
+ parsed = parseWebSocketValue(data);
106
293
  } catch {
107
- // ignore JSON parse errors
294
+ return; // Preserve the stream's existing handling of malformed JSON.
108
295
  }
296
+ const items = Array.isArray(parsed) ? parsed : [parsed];
297
+ const remaining = items.filter((item) => {
298
+ if (!isListSubscriptionsResponse(item)) return true;
299
+ return !this._settlePendingListSubscriptions(ws, item);
300
+ });
301
+ if (remaining.length > 0 || (Array.isArray(parsed) && parsed.length === 0)) {
302
+ // Preserve the single versus list envelope for every endpoint.
303
+ queue.push((Array.isArray(parsed) ? remaining : remaining[0]) as WsStreamEvent);
304
+ }
305
+ resolve?.();
306
+ resolve = null;
109
307
  });
110
308
 
309
+ if (this.endpoint === WsEndpoint.Info) {
310
+ pingTimer = setInterval(() => {
311
+ if (ws.readyState === WS.WebSocket.OPEN) ws.ping();
312
+ }, 30_000);
313
+ }
314
+
111
315
  ws.on('close', (code: number, reason: Buffer) => {
316
+ if (pingTimer !== undefined) clearInterval(pingTimer);
112
317
  done = true;
113
318
  closeCode = code;
114
319
  closeReason = reason.toString();
320
+ this._settlePendingListSubscriptions(ws, new Error(`WebSocket disconnected (code=${code})`));
115
321
  resolve?.();
116
322
  resolve = null;
117
323
  });
118
324
 
119
325
  ws.on('error', (err: Error) => {
326
+ if (pingTimer !== undefined) clearInterval(pingTimer);
120
327
  done = true;
328
+ this._settlePendingListSubscriptions(ws, err);
121
329
  reject?.(err);
122
330
  reject = null;
123
331
  resolve?.();
@@ -133,11 +341,13 @@ export class WsStreamManager implements AsyncIterable<ConnectPublicServerEvent |
133
341
  });
134
342
  }
135
343
  while (queue.length > 0) {
136
- yield queue.shift()!;
344
+ yield queue.shift()! as Event;
137
345
  }
138
346
  }
139
347
  } finally {
140
- this._currentWs = null;
348
+ if (pingTimer !== undefined) clearInterval(pingTimer);
349
+ this._settlePendingListSubscriptions(ws, new Error('WebSocket iterator ended'));
350
+ if (this._currentWs === ws) this._currentWs = null;
141
351
  if (ws.readyState === WS.WebSocket.OPEN || ws.readyState === WS.WebSocket.CONNECTING) {
142
352
  ws.close();
143
353
  }
@@ -165,25 +375,30 @@ export class WsStreamManager implements AsyncIterable<ConnectPublicServerEvent |
165
375
  }
166
376
 
167
377
  private async _connect(): Promise<WS.WebSocket> {
168
- const url = this.isPrivate ? buildPrivateURL(this.client) : buildPublicURL(this.client);
378
+ const url =
379
+ this.endpoint === WsEndpoint.Info ? buildInfoURL(this.client)
380
+ : this.endpoint === WsEndpoint.Private ? buildPrivateURL(this.client)
381
+ : buildPublicURL(this.client);
169
382
 
170
- const headers: Record<string, string> = {};
383
+ let authHeaders: Record<string, string> | undefined;
171
384
 
172
- if (this.isPrivate) {
385
+ if (requiresAuth(this.endpoint)) {
173
386
  const { accessKey, secretKey } = this.client;
174
387
  if (!accessKey || !secretKey) {
175
- throw new Error('Private WebSocket requires accessKey and secretKey');
388
+ throw new Error(`${this.endpoint} WebSocket requires accessKey and secretKey`);
176
389
  }
177
390
  const token = createJwtToken(accessKey, secretKey);
178
- headers['Authorization'] = `Bearer ${token}`;
391
+ authHeaders = { Authorization: `Bearer ${token}` };
179
392
  }
180
393
 
394
+ const headers = this.client._buildWebSocketHandshakeHeaders(authHeaders);
395
+
181
396
  return new Promise<WS.WebSocket>((resolve, reject) => {
182
397
  const ws = new WS.WebSocket(url.toString(), { headers });
183
398
 
184
399
  const onOpen = () => {
185
400
  ws.removeListener('error', onError);
186
- ws.send(buildSubscriptionMessage(this.types));
401
+ ws.send(buildSubscriptionMessage(this.types, this.format));
187
402
  resolve(ws);
188
403
  };
189
404
 
@@ -196,6 +411,23 @@ export class WsStreamManager implements AsyncIterable<ConnectPublicServerEvent |
196
411
  ws.once('error', onError);
197
412
  });
198
413
  }
414
+
415
+ private _settlePendingListSubscriptions(
416
+ ws: WS.WebSocket,
417
+ result: Error | WsListSubscriptionsResponse,
418
+ ): boolean {
419
+ const pending = this._pendingListSubscriptions;
420
+ if (!pending || pending.socket !== ws) return false;
421
+ if (!(result instanceof Error)) {
422
+ const ticket = 'ticket' in result ? result.ticket : result.tckt;
423
+ if (pending.ticket !== ticket) return false;
424
+ }
425
+ this._pendingListSubscriptions = undefined;
426
+ clearTimeout(pending.timer);
427
+ if (result instanceof Error) pending.reject(result);
428
+ else pending.resolve(result);
429
+ return true;
430
+ }
199
431
  }
200
432
 
201
433
  /**
@@ -208,34 +440,67 @@ export class WsStream {
208
440
  constructor(private readonly client: Upbit) {}
209
441
 
210
442
  /** Subscribe to the ticker (current price) stream. */
211
- ticker(codes: string[], opts?: WsStreamOptions): WsStreamManager {
212
- return new WsStreamManager(this.client, [{ type: 'ticker', codes }], false, opts);
443
+ ticker(codes: string[], opts?: WsStreamOptions): WsStreamManager<PublicEvent<'ticker'>> {
444
+ return new WsStreamManager(this.client, [{ type: 'ticker', codes }], WsEndpoint.Public, opts);
213
445
  }
214
446
 
215
447
  /** Subscribe to the trade (executed order) stream. */
216
- trade(codes: string[], opts?: WsStreamOptions): WsStreamManager {
217
- return new WsStreamManager(this.client, [{ type: 'trade', codes }], false, opts);
448
+ trade(codes: string[], opts?: WsStreamOptions): WsStreamManager<PublicEvent<'trade'>> {
449
+ return new WsStreamManager(this.client, [{ type: 'trade', codes }], WsEndpoint.Public, opts);
218
450
  }
219
451
 
220
452
  /** Subscribe to the orderbook stream. */
221
- orderbook(codes: string[], opts?: WsStreamOptions): WsStreamManager {
222
- return new WsStreamManager(this.client, [{ type: 'orderbook', codes }], false, opts);
453
+ orderbook(codes: string[], opts?: WsStreamOptions): WsStreamManager<PublicEvent<'orderbook'>> {
454
+ return new WsStreamManager(this.client, [{ type: 'orderbook', codes }], WsEndpoint.Public, opts);
223
455
  }
224
456
 
225
457
  /** Subscribe to the candle stream. */
226
- candle(codes: string[], opts?: { interval?: string } & WsStreamOptions): WsStreamManager {
458
+ candle(codes: string[], opts?: { interval?: string } & WsStreamOptions): WsStreamManager<CandleEvent> {
227
459
  const { interval = '1m', ...streamOpts } = opts ?? {};
228
- return new WsStreamManager(this.client, [{ type: `candle.${interval}`, codes }], false, streamOpts);
460
+ return new WsStreamManager(
461
+ this.client,
462
+ [{ type: `candle.${interval}`, codes }],
463
+ WsEndpoint.Public,
464
+ streamOpts,
465
+ );
229
466
  }
230
467
 
231
468
  /** Subscribe to the myOrder (my orders) stream. Requires authentication. */
232
- myOrder(codes: string[], opts?: WsStreamOptions): WsStreamManager {
233
- return new WsStreamManager(this.client, [{ type: 'myOrder', codes }], true, opts);
469
+ myOrder(codes: string[], opts?: WsStreamOptions): WsStreamManager<PrivateEvent<'myOrder'>> {
470
+ return new WsStreamManager(this.client, [{ type: 'myOrder', codes }], WsEndpoint.Private, opts);
234
471
  }
235
472
 
236
473
  /** Subscribe to the myAsset (my assets) stream. Requires authentication. */
237
- myAsset(opts?: WsStreamOptions): WsStreamManager {
238
- return new WsStreamManager(this.client, [{ type: 'myAsset' }], true, opts);
474
+ myAsset(opts?: WsStreamOptions): WsStreamManager<PrivateEvent<'myAsset'>> {
475
+ return new WsStreamManager(this.client, [{ type: 'myAsset' }], WsEndpoint.Private, opts);
476
+ }
477
+
478
+ /** Subscribe to the announcement stream. Requires authentication. */
479
+ announcement(opts?: WsAnnouncementOptions): WsStreamManager<PrivateEvent<'announcement'>> {
480
+ const { categories, includeBody, ...streamOpts } = opts ?? {};
481
+ return new WsStreamManager(
482
+ this.client,
483
+ [buildAnnouncementSubscription(categories, includeBody)],
484
+ WsEndpoint.Private,
485
+ streamOpts,
486
+ );
487
+ }
488
+
489
+ /** Subscribe to calculated indicator values. Requires authentication. */
490
+ indicator(codes: string[], opts: WsIndicatorOptions): WsStreamManager<InfoEvent<'indicator'>> {
491
+ const { timeframe, indicators, format = 'DEFAULT', ...streamOpts } = opts;
492
+ const subscription: InfoSubscription = { type: 'indicator', codes, timeframe, indicators };
493
+ return new WsStreamManager(this.client, [subscription], WsEndpoint.Info, { ...streamOpts, format });
494
+ }
495
+
496
+ /** Subscribe to technical indicator condition transitions. Requires authentication. */
497
+ indicatorSignal(
498
+ codes: string[],
499
+ opts: WsIndicatorSignalOptions,
500
+ ): WsStreamManager<InfoEvent<'indicator_signal'>> {
501
+ const { timeframe, indicators, format = 'DEFAULT', ...streamOpts } = opts;
502
+ const subscription: InfoSubscription = { type: 'indicator_signal', codes, timeframe, indicators };
503
+ return new WsStreamManager(this.client, [subscription], WsEndpoint.Info, { ...streamOpts, format });
239
504
  }
240
505
 
241
506
  /** Subscribe to multiple public streams at once. */
@@ -246,37 +511,84 @@ export class WsStream {
246
511
  orderbook?: string[];
247
512
  candle?: { codes: string[]; interval?: string };
248
513
  } & WsStreamOptions,
249
- ): WsStreamManager {
250
- const { ticker, trade, orderbook, candle, maxRetries, retryDelayMs, onDisconnect, onReconnect } = opts;
514
+ ): WsStreamManager<ConnectPublicServerEvent> {
515
+ const { ticker, trade, orderbook, candle, format, maxRetries, retryDelayMs, onDisconnect, onReconnect } =
516
+ opts;
251
517
  const types: AnySubscriptionType[] = [];
252
518
  if (ticker) types.push({ type: 'ticker', codes: ticker });
253
519
  if (trade) types.push({ type: 'trade', codes: trade });
254
520
  if (orderbook) types.push({ type: 'orderbook', codes: orderbook });
255
521
  if (candle) types.push({ type: `candle.${candle.interval ?? '1m'}`, codes: candle.codes });
256
522
  const streamOpts: WsStreamOptions = {};
523
+ if (format !== undefined) streamOpts.format = format;
257
524
  if (maxRetries !== undefined) streamOpts.maxRetries = maxRetries;
258
525
  if (retryDelayMs !== undefined) streamOpts.retryDelayMs = retryDelayMs;
259
526
  if (onDisconnect) streamOpts.onDisconnect = onDisconnect;
260
527
  if (onReconnect) streamOpts.onReconnect = onReconnect;
261
- return new WsStreamManager(this.client, types, false, streamOpts);
528
+ return new WsStreamManager(this.client, types, WsEndpoint.Public, streamOpts);
262
529
  }
263
530
 
264
531
  /** Subscribe to multiple private streams at once. Requires authentication. */
265
532
  subscribePrivate(
266
533
  opts: {
534
+ announcement?: boolean | Pick<WsAnnouncementOptions, 'categories' | 'includeBody'>;
267
535
  myOrder?: string[];
268
536
  myAsset?: boolean;
269
537
  } & WsStreamOptions,
270
- ): WsStreamManager {
271
- const { myOrder, myAsset, maxRetries, retryDelayMs, onDisconnect, onReconnect } = opts;
538
+ ): WsStreamManager<ConnectPrivateServerEvent> {
539
+ const { announcement, myOrder, myAsset, format, maxRetries, retryDelayMs, onDisconnect, onReconnect } =
540
+ opts;
272
541
  const types: AnySubscriptionType[] = [];
542
+ if (announcement) {
543
+ types.push(
544
+ buildAnnouncementSubscription(
545
+ announcement === true ? undefined : announcement.categories,
546
+ announcement === true ? undefined : announcement.includeBody,
547
+ ),
548
+ );
549
+ }
273
550
  if (myOrder) types.push({ type: 'myOrder', codes: myOrder });
274
551
  if (myAsset) types.push({ type: 'myAsset' });
275
- const streamOpts: WsStreamOptions = {};
552
+ const streamOpts: WsStreamOptions & { format?: WsStreamFormat } = {};
553
+ if (format !== undefined) streamOpts.format = format;
554
+ if (maxRetries !== undefined) streamOpts.maxRetries = maxRetries;
555
+ if (retryDelayMs !== undefined) streamOpts.retryDelayMs = retryDelayMs;
556
+ if (onDisconnect) streamOpts.onDisconnect = onDisconnect;
557
+ if (onReconnect) streamOpts.onReconnect = onReconnect;
558
+ return new WsStreamManager(this.client, types, WsEndpoint.Private, streamOpts);
559
+ }
560
+
561
+ /** Subscribe to multiple info streams at once. Requires authentication. */
562
+ subscribeInfo(
563
+ opts: {
564
+ indicator?: WsIndicatorSubscription | WsIndicatorSubscription[];
565
+ indicatorSignal?: WsIndicatorSignalSubscription | WsIndicatorSignalSubscription[];
566
+ } & WsStreamOptions,
567
+ ): WsStreamManager<ConnectInfoServerEvent> {
568
+ const { indicator, indicatorSignal, format, maxRetries, retryDelayMs, onDisconnect, onReconnect } = opts;
569
+ const subscriptions: InfoSubscription[] = [
570
+ ...(indicator ?
571
+ Array.isArray(indicator) ?
572
+ indicator
573
+ : [indicator]
574
+ : []
575
+ ).map((item): InfoSubscription => ({ ...item, type: 'indicator' })),
576
+ ...(indicatorSignal ?
577
+ Array.isArray(indicatorSignal) ?
578
+ indicatorSignal
579
+ : [indicatorSignal]
580
+ : []
581
+ ).map((item): InfoSubscription => ({ ...item, type: 'indicator_signal' })),
582
+ ];
583
+ if (subscriptions.length === 0) {
584
+ throw new Error('At least one subscription type must be specified');
585
+ }
586
+ const streamOpts: WsStreamOptions & { format?: WsStreamFormat } = {};
587
+ if (format !== undefined) streamOpts.format = format;
276
588
  if (maxRetries !== undefined) streamOpts.maxRetries = maxRetries;
277
589
  if (retryDelayMs !== undefined) streamOpts.retryDelayMs = retryDelayMs;
278
590
  if (onDisconnect) streamOpts.onDisconnect = onDisconnect;
279
591
  if (onReconnect) streamOpts.onReconnect = onReconnect;
280
- return new WsStreamManager(this.client, types, true, streamOpts);
592
+ return new WsStreamManager(this.client, subscriptions, WsEndpoint.Info, streamOpts);
281
593
  }
282
594
  }
@@ -1,4 +1,3 @@
1
-
2
1
  import { APIResource } from '../core/resource';
3
2
  import { APIPromise } from '../core/api-promise';
4
3
  import { RequestOptions } from '../internal/request-options';
@@ -11,6 +10,8 @@ export class Accounts extends APIResource {
11
10
  *
12
11
  * - docs(kr): https://docs.upbit.com/kr/reference/get-balance
13
12
  * - docs(global): https://global-docs.upbit.com/reference/get-balance
13
+ *
14
+ * Retrieves the list of assets and balances owned by the account.
14
15
  */
15
16
  list(options?: RequestOptions): APIPromise<AccountListResponse> {
16
17
  return this._client.get('/v1/accounts', options);
@@ -1,4 +1,3 @@
1
-
2
1
  import { APIResource } from '../core/resource';
3
2
  import { APIPromise } from '../core/api-promise';
4
3
  import { RequestOptions } from '../internal/request-options';
@@ -10,7 +9,9 @@ export class APIKeys extends APIResource {
10
9
  * GET /v1/api_keys
11
10
  *
12
11
  * - docs(kr): https://docs.upbit.com/kr/reference/list-api-keys
13
- * - docs(global): https://global-docs.upbit.com/reference/list-api-keys
12
+ * - Supported only in Korea.
13
+ *
14
+ * 계정의 모든 API Key 목록과 각 Key의 만료일자를 조회합니다.
14
15
  */
15
16
  list(options?: RequestOptions): APIPromise<APIKeyListResponse> {
16
17
  return this._client.get('/v1/api_keys', options);