UNPKG

@itick/browser-sdk

Version:

Official iTick API SDK for browser. Real-time & historical data for global Stocks, Forex, Crypto, Indices, Futures, Funds, Precious Metals. REST (OHLCV/K-line) + low-latency WebSocket. Promise-based, TypeScript-ready. For quant trading & fintech

8 lines (7 loc) 13.9 kB
/*! * @itick/browser-sdk v1.0.2 * (c) 2026 iTick * Released under the MIT License. */ var iTickSDK=function(e){"use strict";const t={ONE_MIN:"1m",FIVE_MIN:"5m",FIFTEEN_MIN:"15m",THIRTY_MIN:"30m",ONE_HOUR:"1h",TWO_HOUR:"2h",FOUR_HOUR:"4h",ONE_DAY:"1d",ONE_WEEK:"1w",ONE_MONTH:"1M"},s={[t.ONE_MIN]:1,[t.FIVE_MIN]:2,[t.FIFTEEN_MIN]:3,[t.THIRTY_MIN]:4,[t.ONE_HOUR]:5,[t.TWO_HOUR]:6,[t.FOUR_HOUR]:7,[t.ONE_DAY]:8,[t.ONE_WEEK]:9,[t.ONE_MONTH]:10},n={QUOTE:"quote",DEPTH:"depth",TICK:"tick",KLINE_1M:`kline@${t.ONE_MIN}`,KLINE_5M:`kline@${t.FIVE_MIN}`,KLINE_15M:`kline@${t.FIFTEEN_MIN}`,KLINE_30M:`kline@${t.THIRTY_MIN}`,KLINE_1H:`kline@${t.ONE_HOUR}`,KLINE_2H:`kline@${t.TWO_HOUR}`,KLINE_4H:`kline@${t.FOUR_HOUR}`,KLINE_1D:`kline@${t.ONE_DAY}`,KLINE_1W:`kline@${t.ONE_WEEK}`,KLINE_1MTH:`kline@${t.ONE_MONTH}`},r={[n.KLINE_1M]:`kline@${s[t.ONE_MIN]}`,[n.KLINE_5M]:`kline@${s[t.FIVE_MIN]}`,[n.KLINE_15M]:`kline@${s[t.FIFTEEN_MIN]}`,[n.KLINE_30M]:`kline@${s[t.THIRTY_MIN]}`,[n.KLINE_1H]:`kline@${s[t.ONE_HOUR]}`,[n.KLINE_2H]:`kline@${s[t.TWO_HOUR]}`,[n.KLINE_4H]:`kline@${s[t.FOUR_HOUR]}`,[n.KLINE_1D]:`kline@${s[t.ONE_DAY]}`,[n.KLINE_1W]:`kline@${s[t.ONE_WEEK]}`,[n.KLINE_1MTH]:`kline@${s[t.ONE_MONTH]}`},i=/^[A-Za-z0-9]+\$[A-Za-z0-9]+$/;function o(e){return e===t.ONE_MIN?1:e===t.FIVE_MIN?2:e===t.FIFTEEN_MIN?3:e===t.THIRTY_MIN?4:e===t.ONE_HOUR?5:e===t.TWO_HOUR?6:e===t.FOUR_HOUR?7:e===t.ONE_DAY?8:e===t.ONE_WEEK?9:e===t.ONE_MONTH?10:e}function c(e){return e===n.KLINE_1M?"kline@1":e===n.KLINE_5M?"kline@2":e===n.KLINE_15M?"kline@3":e===n.KLINE_30M?"kline@4":e===n.KLINE_1H?"kline@5":e===n.KLINE_2H?"kline@6":e===n.KLINE_4H?"kline@7":e===n.KLINE_1D?"kline@8":e===n.KLINE_1W?"kline@9":e===n.KLINE_1MTH?"kline@10":e}function a(e){let t;t=Array.isArray(e)?e.map(String):e.split(",");const s=Object.values(n),r=[],i={};for(const e of s)if("string"==typeof e||"number"==typeof e){i[c(e)]=e}for(const e of t){const t=e.trim();if(!t)continue;let n;if(n=s.some(e=>e===t)?t:i[t],!n)throw new Error(`Invalid subscribe type: "${t}". Valid types are: ${s.join(", ")}`);r.push(c(t))}return[...new Set(r)].join(",")}function g(e){const t=Array.isArray(e)?e:e.split(",");return[...new Set(t.map(e=>e.trim()).filter(Boolean).map(e=>{if(!i.test(e))throw new Error(`Invalid symbol format: "${e}". Expected format is "SYMBOL$REGION", e.g. "AAPL$US".`);return e.toUpperCase()}))].join(",")}async function h(e,t={}){const{method:s="GET",headers:n={},body:r,params:i={}}=t;let o=e;if("GET"===s&&Object.keys(i).length>0){const e=function(e){return Object.entries(e).filter(([e,t])=>null!=t).map(([e,t])=>`${encodeURIComponent(e)}=${encodeURIComponent(t)}`).join("&")}(i),t=o.includes("?")?"&":"?";o=`${o}${t}${e}`}const c={method:s,headers:{"Content-Type":"application/json",...n}};r&&"GET"!==s&&(c.body=r);try{const e=await fetch(o,c),t={};let s;e.headers.forEach((e,s)=>{t[s]=e});const n=e.headers.get("content-type");if(n&&n.includes("application/json"))try{s=await e.json()}catch(t){s=await e.text()}else s=await e.text();return{status:e.status,data:s,headers:t}}catch(e){throw new Error(`Request failed: ${e instanceof Error?e.message:String(e)}`)}}class u{constructor(e,t){this.socket=null,this.isRunning=!1,this.reconnectAttempts=0,this.pingInterval=null,this.reconnectTimeout=null,this.messageHandlers=[],this.errorHandlers=[],this.openHandlers=[],this.closeHandlers=[],this.lastSubscription=null,this.wssURL=t.wssURL??"wss://api.itick.org",this.wsPath=t.wsPath,this.token=e,this.RECONNECT_INTERVAL=t.reconnectInterval??5e3,this.MAX_RECONNECT_ATTEMPTS=t.maxReconnectTimes??0,this.PING_INTERVAL=t.pingInterval??3e4,this.lastSubscription=t.subscribeData??null,this._connectWebSocket()}onSocketMessage(e){this.messageHandlers.push(e)}onSocketError(e){this.errorHandlers.push(e)}onSocketOpen(e){this.openHandlers.push(e)}onSocketClose(e){this.closeHandlers.push(e)}async _connectWebSocket(){const e=(t=this.wssURL,s=this.wsPath||"",`${t.replace(/\/$/,"")}${s}`);var t,s;try{this.isRunning=!0,this.socket=await async function(e,t){return new WebSocket(`${e}?token=${t}`)}(e,this.token),this.socket.onopen=()=>{this.reconnectAttempts=0,this._startPing(),this.openHandlers.forEach(e=>e()),this._resubscribeLast()},this.socket.onmessage=e=>{const t="string"==typeof e.data?e.data:e.data.toString();this.messageHandlers.forEach(e=>e(JSON.parse(t)))},this.socket.onclose=e=>{this._stopPing(),this.closeHandlers.forEach(t=>t(e)),this.isRunning&&this._scheduleReconnect()},this.socket.onerror=e=>{this.errorHandlers.forEach(t=>t(e))}}catch(e){this.errorHandlers.forEach(t=>t(e)),this.isRunning&&this._scheduleReconnect()}}_startPing(){this._stopPing(),this.pingInterval=setInterval(()=>{this.socket&&this.socket.readyState===WebSocket.OPEN&&this.socket.send(JSON.stringify({ac:"ping",params:Date.now()}))},this.PING_INTERVAL)}_stopPing(){this.pingInterval&&(clearInterval(this.pingInterval),this.pingInterval=null)}_scheduleReconnect(){this.MAX_RECONNECT_ATTEMPTS>0&&this.reconnectAttempts>=this.MAX_RECONNECT_ATTEMPTS?this.errorHandlers.forEach(e=>e(new Error("Maximum reconnect attempts reached"))):(this.reconnectAttempts++,this.reconnectTimeout=setTimeout(()=>{this.isRunning&&this._connectWebSocket().catch(e=>{})},this.RECONNECT_INTERVAL))}subscribeSocket(e){if(!this.socket||this.socket.readyState!==WebSocket.OPEN)throw new Error("WebSocket not connected");try{let{ac:t,types:s,codes:n}=e;const r=a(s),i=g(n);this.socket.send(JSON.stringify({ac:t,types:r,params:i}))}catch(e){console.error(e)}}_resubscribeLast(){if(this.lastSubscription)try{let{types:e,codes:t}=this.lastSubscription;const s=a(e),n=g(t);this.socket?.send(JSON.stringify({ac:"subscribe",types:s,params:n}))}catch(e){console.error(e)}}closeWebSocket(){this.isRunning=!1,this._stopPing(),this.reconnectTimeout&&clearTimeout(this.reconnectTimeout),this.socket&&this.socket.close(),this.lastSubscription=null}checkSocketConnected(){return!!this.socket&&this.socket.readyState===WebSocket.OPEN}disconnectSocket(){this.closeWebSocket()}}class d{constructor(e,t={}){this.token=e,this.baseURL=t.baseURL??"https://api.itick.org",this.wssURL=t.wssURL??"wss://api.itick.org"}async _get(e,t={}){try{const s=function(e,t){return`${e.replace(/\/$/,"")}${t}`}(this.baseURL,e),n=await h(s,{method:"GET",headers:{accept:"application/json",token:this.token},params:t});if(n.status>=400)throw new Error(`HTTP Error: ${n.status}`);return n.data}catch(e){throw e}}_createSocket(e,t){return new u(this.token,{wssURL:this.wssURL,wsPath:e,...t})}}return e.BaseClient=class extends d{constructor(e,t){super(e,t)}getSymbolList(e){return this._get("/symbol/list",e)}getSymbolHolidays(e){return this._get("/symbol/v2/holidays",{code:e})}},e.Client=d,e.CryptoClient=class extends d{constructor(e,t){super(e,t)}async getTick(e){const{region:t,code:s}=e;return this._get("/crypto/tick",{region:t,code:s})}async getQuote(e){const{region:t,code:s}=e;return this._get("/crypto/quote",{region:t,code:s})}async getDepth(e){const{region:t,code:s}=e;return this._get("/crypto/depth",{region:t,code:s})}async getKline(e){const{region:t,code:s,kType:n,interval:r,limit:i,et:c}=e,a={region:t,code:s,kType:o(r??n),limit:i};return c&&(a.et=c),this._get("/crypto/kline",a)}async getTicks(e){const{region:t,codes:s}=e;return this._get("/crypto/ticks",{region:t,codes:Array.isArray(s)?s.join(","):s})}async getQuotes(e){const{region:t,codes:s}=e;return this._get("/crypto/quotes",{region:t,codes:Array.isArray(s)?s.join(","):s})}async getDepths(e){const{region:t,codes:s}=e;return this._get("/crypto/depths",{region:t,codes:Array.isArray(s)?s.join(","):s})}async getKlines(e){const{region:t,codes:s,kType:n,interval:r,limit:i,et:c}=e,a={region:t,codes:Array.isArray(s)?s.join(","):s,kType:o(r??n),limit:i};return c&&(a.et=c),this._get("/crypto/klines",a)}createSocket(e){return this._createSocket("/crypto",e)}},e.ForexClient=class extends d{constructor(e,t){super(e,t)}async getTick(e){const{region:t,code:s}=e;return this._get("/forex/tick",{region:t,code:s})}async getQuote(e){const{region:t,code:s}=e;return this._get("/forex/quote",{region:t,code:s})}async getDepth(e){const{region:t,code:s}=e;return this._get("/forex/depth",{region:t,code:s})}async getKline(e){const{region:t,code:s,kType:n,interval:r,limit:i,et:c}=e,a={region:t,code:s,kType:o(r??n),limit:i};return c&&(a.et=c),this._get("/forex/kline",a)}async getTicks(e){const{region:t,codes:s}=e;return this._get("/forex/ticks",{region:t,codes:Array.isArray(s)?s.join(","):s})}async getQuotes(e){const{region:t,codes:s}=e;return this._get("/forex/quotes",{region:t,codes:Array.isArray(s)?s.join(","):s})}async getDepths(e){const{region:t,codes:s}=e;return this._get("/forex/depths",{region:t,codes:Array.isArray(s)?s.join(","):s})}async getKlines(e){const{region:t,codes:s,kType:n,interval:r,limit:i,et:c}=e,a={region:t,codes:Array.isArray(s)?s.join(","):s,kType:o(r??n),limit:i};return c&&(a.et=c),this._get("/forex/klines",a)}createSocket(e){return this._createSocket("/forex",e)}},e.FundClient=class extends d{constructor(e,t){super(e,t)}async getTick(e){const{region:t,code:s}=e;return this._get("/fund/tick",{region:t,code:s})}async getQuote(e){const{region:t,code:s}=e;return this._get("/fund/quote",{region:t,code:s})}async getDepth(e){const{region:t,code:s}=e;return this._get("/fund/depth",{region:t,code:s})}async getKline(e){const{region:t,code:s,kType:n,interval:r,limit:i,et:c}=e,a={region:t,code:s,kType:o(r??n),limit:i};return c&&(a.et=c),this._get("/fund/kline",a)}async getTicks(e){const{region:t,codes:s}=e;return this._get("/fund/ticks",{region:t,codes:Array.isArray(s)?s.join(","):s})}async getQuotes(e){const{region:t,codes:s}=e;return this._get("/fund/quotes",{region:t,codes:Array.isArray(s)?s.join(","):s})}async getDepths(e){const{region:t,codes:s}=e;return this._get("/fund/depths",{region:t,codes:Array.isArray(s)?s.join(","):s})}async getKlines(e){const{region:t,codes:s,kType:n,interval:r,limit:i,et:c}=e,a={region:t,codes:Array.isArray(s)?s.join(","):s,kType:o(r??n),limit:i};return c&&(a.et=c),this._get("/fund/klines",a)}createSocket(e){return this._createSocket("/fund",e)}},e.FutureClient=class extends d{constructor(e,t){super(e,t)}async getTick(e){const{region:t,code:s}=e;return this._get("/future/tick",{region:t,code:s})}async getQuote(e){const{region:t,code:s}=e;return this._get("/future/quote",{region:t,code:s})}async getDepth(e){const{region:t,code:s}=e;return this._get("/future/depth",{region:t,code:s})}async getKline(e){const{region:t,code:s,kType:n,interval:r,limit:i,et:c}=e,a={region:t,code:s,kType:o(r??n),limit:i};return c&&(a.et=c),this._get("/future/kline",a)}async getTicks(e){const{region:t,codes:s}=e;return this._get("/future/ticks",{region:t,codes:Array.isArray(s)?s.join(","):s})}async getQuotes(e){const{region:t,codes:s}=e;return this._get("/future/quotes",{region:t,codes:Array.isArray(s)?s.join(","):s})}async getDepths(e){const{region:t,codes:s}=e;return this._get("/future/depths",{region:t,codes:Array.isArray(s)?s.join(","):s})}async getKlines(e){const{region:t,codes:s,kType:n,interval:r,limit:i,et:c}=e,a={region:t,codes:Array.isArray(s)?s.join(","):s,kType:o(r??n),limit:i};return c&&(a.et=c),this._get("/future/klines",a)}createSocket(e){return this._createSocket("/future",e)}},e.IndicesClient=class extends d{constructor(e,t){super(e,t)}async getTick(e){const{region:t,code:s}=e;return this._get("/indices/tick",{region:t,code:s})}async getQuote(e){const{region:t,code:s}=e;return this._get("/indices/quote",{region:t,code:s})}async getDepth(e){const{region:t,code:s}=e;return this._get("/indices/depth",{region:t,code:s})}async getKline(e){const{region:t,code:s,kType:n,interval:r,limit:i,et:c}=e,a={region:t,code:s,kType:o(r??n),limit:i};return c&&(a.et=c),this._get("/indices/kline",a)}async getTicks(e){const{region:t,codes:s}=e;return this._get("/indices/ticks",{region:t,codes:Array.isArray(s)?s.join(","):s})}async getQuotes(e){const{region:t,codes:s}=e;return this._get("/indices/quotes",{region:t,codes:Array.isArray(s)?s.join(","):s})}async getDepths(e){const{region:t,codes:s}=e;return this._get("/indices/depths",{region:t,codes:Array.isArray(s)?s.join(","):s})}async getKlines(e){const{region:t,codes:s,kType:n,interval:r,limit:i,et:c}=e,a={region:t,codes:Array.isArray(s)?s.join(","):s,kType:o(r??n),limit:i};return c&&(a.et=c),this._get("/indices/klines",a)}createSocket(e){return this._createSocket("/indices",e)}},e.KlinePeriod=t,e.KlineTypeCode=s,e.StockClient=class extends d{constructor(e,t){super(e,t)}async getInfo(e){const{region:t,code:s,exchange:n}=e;return this._get("/stock/info",{type:"stock",region:t,code:s,exchange:n})}async getIPO(e){const{region:t,code:s}=e;return this._get("/stock/ipo",{region:t,code:s})}async getSplit(e){const{region:t,code:s}=e;return this._get("/stock/split",{region:t,code:s})}async getTick(e){const{region:t,code:s}=e;return this._get("/stock/tick",{region:t,code:s})}async getQuote(e){const{region:t,code:s}=e;return this._get("/stock/quote",{region:t,code:s})}async getDepth(e){const{region:t,code:s}=e;return this._get("/stock/depth",{region:t,code:s})}async getKline(e){const{region:t,code:s,kType:n,interval:r,limit:i,et:c}=e,a={region:t,code:s,kType:o(r??n),limit:i};return c&&(a.et=c),this._get("/stock/kline",a)}async getTicks(e){const{region:t,codes:s}=e;return this._get("/stock/ticks",{region:t,codes:Array.isArray(s)?s.join(","):s})}async getQuotes(e){const{region:t,codes:s}=e;return this._get("/stock/quotes",{region:t,codes:Array.isArray(s)?s.join(","):s})}async getDepths(e){const{region:t,codes:s}=e;return this._get("/stock/depths",{region:t,codes:Array.isArray(s)?s.join(","):s})}async getKlines(e){const{region:t,codes:s,kType:n,interval:r,limit:i,et:c}=e,a={region:t,codes:Array.isArray(s)?s.join(","):s,kType:o(r??n),limit:i};return c&&(a.et=c),this._get("/stock/klines",a)}createSocket(e){return this._createSocket("/stock",e)}},e.SubscribeType=n,e.SubscribeTypeCode=r,e}({}); //# sourceMappingURL=itick-sdk.min.js.map