@tony01/astroneum 0.4.1-beta.2 → 0.4.1-beta.25
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/CHANGELOG.md +281 -237
- package/LICENSE +21 -21
- package/README.md +250 -198
- package/dist/{Indicator-BBI3L_lx.d.ts → Indicator-BQQcVGGT.d.ts} +51 -227
- package/dist/astroneum.css +1 -1
- package/dist/chunk-47YGQEL5.js +399 -0
- package/dist/chunk-67XM5LOK.js +2 -0
- package/dist/{chunk-2YYGUSVX.js → chunk-DFJMDDL5.js} +1 -1
- package/dist/chunk-EFAS6F4C.js +59 -0
- package/dist/chunk-EHZN52CY.js +2 -0
- package/dist/chunk-HKLWNPMP.js +35 -0
- package/dist/chunk-ONPPQW65.js +2 -0
- package/dist/chunk-SCTHEM27.js +3 -0
- package/dist/chunk-UQXYMB6X.js +2 -0
- package/dist/chunk-WSIR5T2M.js +3 -0
- package/dist/entries/alerts.d.ts +36 -10
- package/dist/entries/alerts.js +1 -1
- package/dist/entries/datafeeds/crypto.d.ts +5 -1
- package/dist/entries/datafeeds/crypto.js +1 -1
- package/dist/entries/datafeeds/polygon.d.ts +3 -1
- package/dist/entries/datafeeds/polygon.js +1 -1
- package/dist/entries/headless.d.ts +78 -0
- package/dist/entries/headless.js +2 -0
- package/dist/entries/multichart.d.ts +12 -1
- package/dist/entries/multichart.js +1 -1
- package/dist/entries/replay.d.ts +3 -1
- package/dist/entries/script.d.ts +2 -68
- package/dist/entries/script.js +1 -1
- package/dist/entries/watchlist.d.ts +32 -2
- package/dist/entries/watchlist.js +1 -1
- package/dist/entries/workspace.d.ts +61 -0
- package/dist/entries/workspace.js +2 -0
- package/dist/index-BiXdqLA4.d.ts +45 -0
- package/dist/index-_JgHTy8X.d.ts +19 -0
- package/dist/index.d.ts +188 -27
- package/dist/index.js +1 -1
- package/dist/script-BU9StbN-.d.ts +120 -0
- package/dist/types-W6SIYQ9m.d.ts +232 -0
- package/dist/types-yETgeYsE.d.ts +28 -0
- package/dist/zh-CN-NDTUDZGZ.js +3 -0
- package/package.json +157 -147
- package/dist/chunk-4YOLQ5DC.js +0 -2
- package/dist/chunk-I4YQBP2M.js +0 -3
- package/dist/chunk-OOMZRONH.js +0 -35
- package/dist/chunk-PV2GAINM.js +0 -2
- package/dist/chunk-YW3STIPY.js +0 -653
- package/dist/zh-CN-Y2C6RSOI.js +0 -3
- package/docs/STRUCTURE.md +0 -231
- package/docs/TODO-DESIGN.md +0 -261
- package/docs/TODO.md +0 -222
- package/docs/api.md +0 -528
- package/docs/datafeed-guide.md +0 -311
- package/docs/design-astroneum.md +0 -479
- package/docs/plugin-development.md +0 -565
- package/docs/tv-functions-skill.md +0 -706
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import {b}from'./chunk-SDXH2WAI.js';var q=[{ticker:"BINANCE:BTCUSDT",name:"Bitcoin Perpetual / USDT",shortName:"BTC PERP",exchange:"BINANCE",market:"crypto",pricePrecision:2,volumePrecision:6,priceCurrency:"USDT",type:"crypto",venueSymbol:"BTCUSDT"},{ticker:"BINANCE:ETHUSDT",name:"Ethereum Perpetual / USDT",shortName:"ETH PERP",exchange:"BINANCE",market:"crypto",pricePrecision:2,volumePrecision:4,priceCurrency:"USDT",type:"crypto",venueSymbol:"ETHUSDT"},{ticker:"BINANCE:SOLUSDT",name:"Solana Perpetual / USDT",shortName:"SOL PERP",exchange:"BINANCE",market:"crypto",pricePrecision:3,volumePrecision:2,priceCurrency:"USDT",type:"crypto",venueSymbol:"SOLUSDT"},{ticker:"BITGET:BTCUSDT",name:"Bitcoin USDT Futures",shortName:"BTC PERP",exchange:"BITGET",market:"crypto",pricePrecision:2,volumePrecision:6,priceCurrency:"USDT",type:"crypto",venueSymbol:"BTCUSDT",productType:"USDT-FUTURES"},{ticker:"BITGET:ETHUSDT",name:"Ethereum USDT Futures",shortName:"ETH PERP",exchange:"BITGET",market:"crypto",pricePrecision:2,volumePrecision:4,priceCurrency:"USDT",type:"crypto",venueSymbol:"ETHUSDT",productType:"USDT-FUTURES"},{ticker:"OKX:BTC-USDT-SWAP",name:"Bitcoin USDT Swap",shortName:"BTC SWAP",exchange:"OKX",market:"crypto",pricePrecision:2,volumePrecision:6,priceCurrency:"USDT",type:"crypto",instId:"BTC-USDT-SWAP"},{ticker:"OKX:ETH-USDT-SWAP",name:"Ethereum USDT Swap",shortName:"ETH SWAP",exchange:"OKX",market:"crypto",pricePrecision:2,volumePrecision:4,priceCurrency:"USDT",type:"crypto",instId:"ETH-USDT-SWAP"}],X=q,G="astroneum:datafeed-error",V="wss://fstream.binance.com/market/ws",P="https://fapi.binance.com/fapi/v1",j="wss://ws.bitget.com/v2/ws/public",k="https://api.bitget.com/api/v2/mix/market",z="wss://ws.okx.com:8443/ws/v5/public",T="https://www.okx.com/api/v5/market",x=120;function N(e,n){return `${e.ticker}::${n.text}`}function J(e,n){if(!e)return true;let t=e.toLowerCase();return n.ticker.toLowerCase().includes(t)||(n.name??"").toLowerCase().includes(t)}function A(e){if(typeof e!="string")return null;try{return JSON.parse(e)}catch{return null}}function i(e){let n=typeof e=="number"?e:Number(e);return Number.isFinite(n)?n:null}function B(e){let n=true;for(let t=1;t<e.length;t++)if(e[t].timestamp<e[t-1].timestamp){n=false;break}return n?e:e.slice().sort((t,r)=>t.timestamp-r.timestamp)}function R(e,n,t){return e.filter(r=>r.timestamp>=n&&r.timestamp<=t)}function Y(e){return ({second:1e3,minute:6e4,hour:36e5,day:864e5,week:6048e5,month:2592e6,year:31536e6}[e.timespan]??6e4)*e.multiplier}function _(e,n,t){let r=Y(e),o=Math.floor(n/r)*r,a=Math.floor(t/r)*r;return a>=o?{from:o,to:a}:{from:o,to:o}}function O(e){return e.timespan==="minute"&&[1,3,5,15,30].includes(e.multiplier)?`${e.multiplier}m`:e.timespan==="hour"&&[1,2,4,6,8,12].includes(e.multiplier)?`${e.multiplier}h`:e.timespan==="day"&&[1,3].includes(e.multiplier)?`${e.multiplier}d`:e.timespan==="week"&&e.multiplier===1?"1w":e.timespan==="month"&&e.multiplier===1?"1M":null}function W(e){return e.timespan==="minute"&&[1,3,5,15,30].includes(e.multiplier)?`${e.multiplier}m`:e.timespan==="hour"&&[1,2,4,6,12].includes(e.multiplier)?`${e.multiplier}H`:e.timespan==="day"&&[1,3].includes(e.multiplier)?`${e.multiplier}D`:e.timespan==="week"&&e.multiplier===1?"1W":e.timespan==="month"&&e.multiplier===1?"1M":null}function L(e){return e.timespan==="minute"&&[1,3,5,15,30].includes(e.multiplier)?`${e.multiplier}m`:e.timespan==="hour"&&[1,2,4,6,12].includes(e.multiplier)?`${e.multiplier}H`:e.timespan==="day"&&[1,3].includes(e.multiplier)?`${e.multiplier}D`:e.timespan==="week"&&e.multiplier===1?"1W":e.timespan==="month"&&e.multiplier===1?"1M":null}function Q(e){let n=e.indexOf(":");return n>=0?e.slice(n+1):e}function S(e){return (e.venueSymbol??Q(e.ticker)).toUpperCase()}function v(e){return e.instId??Q(e.ticker)}function Z(e){return (e.productType??"USDT-FUTURES").toUpperCase()}function F(e){return (e.productType??"USDT-FUTURES").toLowerCase()}function K(e){if(typeof e.exchange=="string"&&e.exchange.trim())return e.exchange.toUpperCase();let n=e.ticker.split(":",1)[0]?.toUpperCase();return n&&n.length>0?n:null}function ee(e,n){return {...e,exchange:n}}async function h(e){try{let n=await fetch(e);return n.ok?await n.json():null}catch{return null}}var M=new Map;function te(e){return e&&typeof e=="object"&&"data"in e?e.data??e:e}function p(e,n,t,r){let o=`${e.ticker}::${n.text}::${t}`,a=Date.now(),u=M.get(o)??0;if(a-u<2500)return;M.set(o,a);let s={exchange:K(e)??void 0,ticker:e.ticker,period:n.text,type:t,message:r};console.error(`[astroneum:datafeed] ${s.ticker} ${s.period} - ${s.message}`),typeof window<"u"&&window.dispatchEvent(new CustomEvent(G,{detail:s}));}function H(e){if(!Array.isArray(e))return [];let n=[];for(let t of e){if(!Array.isArray(t))continue;let r=i(t[0]),o=i(t[1]),a=i(t[2]),u=i(t[3]),s=i(t[4]),l=i(t[5]),c=i(t[7]);r===null||o===null||a===null||u===null||s===null||l===null||n.push({timestamp:r,open:o,high:a,low:u,close:s,volume:l,turnover:c??l*s});}return B(n)}function D(e){if(!Array.isArray(e))return [];let n=[];for(let t of e){if(!Array.isArray(t))continue;let r=i(t[0]),o=i(t[1]),a=i(t[2]),u=i(t[3]),s=i(t[4]),l=i(t[5]),c=i(t[6]),d=i(t[7]);r===null||o===null||a===null||u===null||s===null||l===null||n.push({timestamp:r,open:o,high:a,low:u,close:s,volume:l,turnover:d??c??l*s});}return B(n)}function E(e){if(!Array.isArray(e))return [];let n=[];for(let t of e){if(!Array.isArray(t))continue;let r=i(t[0]),o=i(t[1]),a=i(t[2]),u=i(t[3]),s=i(t[4]),l=i(t[5]),c=i(t[7])??i(t[6]);r===null||o===null||a===null||u===null||s===null||l===null||n.push({timestamp:r,open:o,high:a,low:u,close:s,volume:l,turnover:c??l*s});}return B(n)}var ne={id:"BINANCE",async getQuotes(e){return (await Promise.all(e.map(async t=>{let r=new URL(`${P}/ticker/24hr`);r.searchParams.set("symbol",S(t));let o=await h(r.toString()),a=i(o?.lastPrice);if(a===null)return null;let u=i(o?.openPrice),s=i(o?.highPrice),l=i(o?.lowPrice),c=i(o?.volume);return {ticker:t.ticker,last:a,change:i(o?.priceChange)??void 0,changePercent:i(o?.priceChangePercent)??void 0,volume:c===null?void 0:c,open:u===null?void 0:u,high:s===null?void 0:s,low:l===null?void 0:l,timestamp:i(o?.closeTime)??Date.now()}}))).filter(t=>t!==null)},async getHistoryBars(e,n,t,r){let o=O(n);if(o===null)return p(e,n,"unsupported-period",`Binance does not support period ${n.text}`),[];let a=_(n,t,r),u=S(e),s=new URL(`${P}/klines`);s.searchParams.set("symbol",u),s.searchParams.set("interval",o),s.searchParams.set("startTime",`${a.from}`),s.searchParams.set("endTime",`${a.to}`),s.searchParams.set("limit","1000");let l=new URL(`${P}/klines`);l.searchParams.set("symbol",u),l.searchParams.set("interval",o),l.searchParams.set("endTime",`${a.to}`),l.searchParams.set("limit","1000");let c=await h(s.toString());c===null&&p(e,n,"history-request-failed","Binance history request failed");let d=H(c),m=R(d,a.from,a.to);if(m.length<x){let f=await h(l.toString()),b=H(f).filter(y=>y.timestamp<=a.to);b.length>m.length&&(m=b);}return m.length===0&&p(e,n,"history-empty","Binance returned no candle data for this range"),m},getWebSocketUrl(e,n){let t=O(n);return t===null?"wss://invalid":`${V}/${S(e).toLowerCase()}@kline_${t}`},parseMessage(e){let n=te(A(e.data));if(!n||typeof n!="object")return null;let t=n;if(t.e!=="kline"||!t.k)return null;let r=i(t.k.t),o=i(t.k.o),a=i(t.k.h),u=i(t.k.l),s=i(t.k.c),l=i(t.k.v),c=i(t.k.q);return r===null||o===null||a===null||u===null||s===null||l===null?null:{timestamp:r,open:o,high:a,low:u,close:s,volume:l,turnover:c??l*s}}},re={id:"BITGET",async getQuotes(e){return (await Promise.all(e.map(async t=>{let r=new URL(`${k}/ticker`);r.searchParams.set("symbol",S(t)),r.searchParams.set("productType",F(t));let a=(await h(r.toString()))?.data?.[0],u=i(a?.lastPr);if(u===null)return null;let s=i(a?.open24h),l=i(a?.high24h),c=i(a?.low24h),d=i(a?.baseVolume),m=i(a?.change24h);return {ticker:t.ticker,last:u,change:s===null?void 0:u-s,changePercent:m===null?void 0:m*100,volume:d===null?void 0:d,open:s===null?void 0:s,high:l===null?void 0:l,low:c===null?void 0:c,timestamp:i(a?.ts)??Date.now()}}))).filter(t=>t!==null)},async getHistoryBars(e,n,t,r){let o=W(n);if(o===null)return p(e,n,"unsupported-period",`Bitget does not support period ${n.text}`),[];let a=_(n,t,r),u=S(e),s=F(e),l=new URL(`${k}/candles`);l.searchParams.set("symbol",u),l.searchParams.set("productType",s),l.searchParams.set("granularity",o),l.searchParams.set("startTime",`${a.from}`),l.searchParams.set("endTime",`${a.to}`),l.searchParams.set("limit","1000");let c=new URL(`${k}/candles`);c.searchParams.set("symbol",u),c.searchParams.set("productType",s),c.searchParams.set("granularity",o),c.searchParams.set("limit","1000");let d=await h(l.toString());d===null&&p(e,n,"history-request-failed","Bitget history request failed");let m=D(d?.data),f=R(m,a.from,a.to);if(f.length<x){let g=await h(c.toString()),y=D(g?.data).filter(w=>w.timestamp<=a.to);y.length>f.length&&(f=y);}return f.length===0&&p(e,n,"history-empty","Bitget returned no candle data for this range"),f},getWebSocketUrl(){return j},onOpen(e,n,t){let r=W(t);if(r===null){p(n,t,"unsupported-period",`Bitget does not support period ${t.text}`);return}let o=Z(n);e.send(JSON.stringify({op:"subscribe",args:[{instType:o,channel:`candle${r}`,instId:S(n)}]}));},parseMessage(e){let n=A(e.data);if(!n||typeof n!="object")return null;let t=n.data;if(!Array.isArray(t))return null;let r=D(t);return r.length>0?r[r.length-1]:null}},ae={id:"OKX",async getQuotes(e){return (await Promise.all(e.map(async t=>{let r=new URL(`${T}/ticker`);r.searchParams.set("instId",v(t));let a=(await h(r.toString()))?.data?.[0],u=i(a?.last);if(u===null)return null;let s=i(a?.open24h),l=i(a?.high24h),c=i(a?.low24h),d=i(a?.vol24h);return {ticker:t.ticker,last:u,change:s===null?void 0:u-s,changePercent:s===null||s===0?void 0:(u-s)/s*100,volume:d===null?void 0:d,open:s===null?void 0:s,high:l===null?void 0:l,low:c===null?void 0:c,timestamp:i(a?.ts)??Date.now()}}))).filter(t=>t!==null)},async getHistoryBars(e,n,t,r){let o=L(n);if(o===null)return p(e,n,"unsupported-period",`OKX does not support period ${n.text}`),[];let a=_(n,t,r),u=v(e),s=new URL(`${T}/candles`);s.searchParams.set("instId",u),s.searchParams.set("bar",o),s.searchParams.set("limit","300");let l=new URL(`${T}/history-candles`);l.searchParams.set("instId",u),l.searchParams.set("bar",o),l.searchParams.set("limit","300");let c=await h(s.toString());c===null&&p(e,n,"history-request-failed","OKX history request failed");let d=E(c?.data),m=R(d,a.from,a.to);if(m.length<x){let f=d.filter(g=>g.timestamp<=a.to);if(f.length>m.length)m=f;else {let g=await h(l.toString()),y=E(g?.data).filter(w=>w.timestamp<=a.to);y.length>m.length&&(m=y);}}return m.length===0&&p(e,n,"history-empty","OKX returned no candle data for this range"),m},getWebSocketUrl(){return z},onOpen(e,n,t){let r=L(t);if(r===null){p(n,t,"unsupported-period",`OKX does not support period ${t.text}`);return}e.send(JSON.stringify({op:"subscribe",args:[{channel:`candle${r}`,instId:v(n)}]}));},parseMessage(e){let n=A(e.data);if(!n||typeof n!="object")return null;let t=n.data;if(!Array.isArray(t))return null;let r=E(t);return r.length>0?r[r.length-1]:null}},oe=[ne,re,ae],I=class extends b{adapter;constructor(n,t){super({smoothingDuration:t}),this.adapter=n;}getAdapter(){return this.adapter}async getHistoryBars(n,t,r,o){return this.adapter.getHistoryBars(n,t,r,o)}subscribe(n,t,r){let o=this.adapter.getWebSocketUrl(n,t);if(!o||o==="wss://invalid"){p(n,t,"subscription-failed",`No WebSocket stream available for period ${t.text}`);return}super.subscribe(n,t,r);}getWebSocketUrl(n,t){return this.adapter.getWebSocketUrl(n,t)}parseMessage(n,t,r){return this.adapter.parseMessage(n,t,r)}onOpen(n,t,r){this.adapter.onOpen?.(n,t,r);}},U=class{searchSymbols(n=""){return Promise.resolve([])}getHistoryData(n,t,r,o){return p(n,t,"unsupported-symbol",`Unsupported symbol ${n.ticker}`),Promise.resolve([])}subscribe(n,t,r){p(n,t,"subscription-failed",`No live feed available for ${n.ticker}`);}unsubscribe(n,t){}},C=class{symbols;liveFeeds=new Map;supportedExchanges=new Set;noDataFeed=new U;activeFeedByKey=new Map;constructor(n={}){this.symbols=n.symbols??X;let t=Math.max(0,n.smoothingDuration??220),r=n.adapters&&n.adapters.length>0?n.adapters:oe;for(let o of r){let a=o.id.toUpperCase();this.supportedExchanges.add(a),this.liveFeeds.set(a,new I({...o,id:a},t));}}searchSymbols(n=""){return Promise.resolve(this.symbols.filter(t=>J(n,t)))}async getQuotes(n){let t=new Map;for(let o of n){let a=this.resolveExchange(o);if(!a)continue;let u=t.get(a)??[];u.push(this.normalizeSymbol(o)),t.set(a,u);}return (await Promise.all([...t].map(async([o,a])=>{let u=this.liveFeeds.get(o)?.getAdapter();return u?.getQuotes?u.getQuotes(a):[]}))).flat()}async getHistoryData(n,t,r,o){return this.resolveFeed(n).getHistoryData(n,t,r,o)}subscribe(n,t,r){let o=N(n,t);this.unsubscribe(n,t);let a=this.resolveFeed(n);this.activeFeedByKey.set(o,a),a.subscribe(this.normalizeSymbol(n),t,r);}unsubscribe(n,t){let r=N(n,t);(this.activeFeedByKey.get(r)??this.resolveFeed(n)).unsubscribe(this.normalizeSymbol(n),t),this.activeFeedByKey.delete(r);}normalizeSymbol(n){let t=this.resolveExchange(n);return t?ee(n,t):n}resolveFeed(n){let t=this.resolveExchange(n);if(t!==null){let r=this.liveFeeds.get(t);if(r)return r}return this.noDataFeed}resolveExchange(n){let t=K(n);return t&&this.supportedExchanges.has(t)?t:null}};function ie(e={}){return new C(e)}
|
|
3
|
+
export{X as a,G as b,ne as c,re as d,ae as e,C as f,ie as g};
|
package/dist/entries/alerts.d.ts
CHANGED
|
@@ -4,9 +4,9 @@
|
|
|
4
4
|
* Alerts are persisted to localStorage and evaluated on every new bar
|
|
5
5
|
* or price tick via `AlertManager.check()`.
|
|
6
6
|
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
7
|
+
* Supports multi-condition alerts (AND), price-source and indicator-source
|
|
8
|
+
* conditions, paused status, and a change-event subscription so UI panels
|
|
9
|
+
* can update live without manual refresh.
|
|
10
10
|
*
|
|
11
11
|
* Delivery: sound (variable titles), browser notification, toast popup,
|
|
12
12
|
* webhook (via server-side relay /astroneum/api/alerts/webhook), email
|
|
@@ -14,12 +14,29 @@
|
|
|
14
14
|
* is written back onto the alert so the alert log can surface it
|
|
15
15
|
* (mirrors TradingView's "Webhook status" column).
|
|
16
16
|
*/
|
|
17
|
-
type
|
|
18
|
-
type
|
|
17
|
+
type AlertOperator = 'above' | 'below' | 'crosses_above' | 'crosses_below' | 'crosses' | 'is_between';
|
|
18
|
+
type AlertCondition = AlertOperator;
|
|
19
|
+
type AlertStatus = 'active' | 'paused' | 'triggered' | 'expired' | 'dismissed';
|
|
19
20
|
type AlertFrequency = 'once' | 'every_bar' | 'bar_close';
|
|
20
21
|
type SoundTitle = 'Thin' | 'Classic' | 'Alert' | 'Bell' | 'Chime';
|
|
21
22
|
type SoundDuration = 'once' | 'repeating';
|
|
22
23
|
type WebhookStatus = 'pending' | 'delivered' | 'failed';
|
|
24
|
+
type AlertSource = {
|
|
25
|
+
type: 'price';
|
|
26
|
+
} | {
|
|
27
|
+
type: 'indicator';
|
|
28
|
+
paneId: string;
|
|
29
|
+
name: string;
|
|
30
|
+
plot: string;
|
|
31
|
+
shortName?: string;
|
|
32
|
+
};
|
|
33
|
+
interface AlertConditionDef {
|
|
34
|
+
id: string;
|
|
35
|
+
source: AlertSource;
|
|
36
|
+
operator: AlertOperator;
|
|
37
|
+
value: number;
|
|
38
|
+
secondValue?: number;
|
|
39
|
+
}
|
|
23
40
|
interface NotificationSchedule {
|
|
24
41
|
preset: '24/7' | 'weekdays' | 'working_hours' | 'custom';
|
|
25
42
|
days?: number[];
|
|
@@ -29,8 +46,9 @@ interface NotificationSchedule {
|
|
|
29
46
|
interface Alert {
|
|
30
47
|
id: string;
|
|
31
48
|
symbol: string;
|
|
32
|
-
|
|
49
|
+
conditions: AlertConditionDef[];
|
|
33
50
|
price: number;
|
|
51
|
+
condition: string;
|
|
34
52
|
note?: string;
|
|
35
53
|
timeframe?: string;
|
|
36
54
|
frequency: AlertFrequency;
|
|
@@ -53,41 +71,49 @@ interface Alert {
|
|
|
53
71
|
soundTitle?: SoundTitle;
|
|
54
72
|
soundDuration?: SoundDuration;
|
|
55
73
|
}
|
|
56
|
-
type AlertCreate = Omit<Alert, 'id' | 'status' | 'createdAt' | 'triggeredAt'> & Partial<Pick<Alert, 'frequency' | 'soundEnabled' | 'notificationEnabled'>>;
|
|
74
|
+
type AlertCreate = Omit<Alert, 'id' | 'status' | 'createdAt' | 'triggeredAt' | 'conditions'> & Partial<Pick<Alert, 'conditions' | 'frequency' | 'soundEnabled' | 'notificationEnabled'>>;
|
|
57
75
|
interface AlertCheckInput {
|
|
58
76
|
symbol: string;
|
|
59
77
|
price: number;
|
|
60
78
|
timestamp: number;
|
|
79
|
+
indicatorResolver?: (source: AlertSource) => number | undefined;
|
|
61
80
|
}
|
|
62
81
|
type AlertTriggeredCallback = (alert: Alert, price: number) => void;
|
|
82
|
+
type AlertChangeCallback = (alerts: Alert[]) => void;
|
|
63
83
|
declare class AlertManager {
|
|
64
84
|
private static _instance;
|
|
65
85
|
private _alerts;
|
|
66
|
-
private
|
|
86
|
+
private _lastValues;
|
|
67
87
|
private _listeners;
|
|
88
|
+
private _changeListeners;
|
|
68
89
|
private _savePending;
|
|
69
90
|
private constructor();
|
|
70
91
|
static getInstance(): AlertManager;
|
|
92
|
+
private _notifyChange;
|
|
71
93
|
add(create: AlertCreate): string;
|
|
72
94
|
update(id: string, patch: Partial<Omit<Alert, 'id' | 'createdAt'>>): boolean;
|
|
73
95
|
delete(id: string): boolean;
|
|
74
96
|
dismiss(id: string): boolean;
|
|
75
97
|
reactivate(id: string): boolean;
|
|
98
|
+
togglePause(id: string): boolean;
|
|
76
99
|
clear(symbol?: string): void;
|
|
77
100
|
getAll(): readonly Alert[];
|
|
78
101
|
getActive(): Alert[];
|
|
79
102
|
getForSymbol(symbol: string): Alert[];
|
|
80
103
|
getActiveForSymbol(symbol: string): Alert[];
|
|
81
104
|
getHistory(): Alert[];
|
|
105
|
+
getById(id: string): Alert | undefined;
|
|
82
106
|
/**
|
|
83
107
|
* Call on every price tick or bar close.
|
|
84
|
-
* Checks expiration, evaluates conditions, fires delivery.
|
|
108
|
+
* Checks expiration, evaluates conditions (AND), fires delivery.
|
|
109
|
+
* indicatorResolver maps indicator sources to their current plot values.
|
|
85
110
|
*/
|
|
86
111
|
check(input: AlertCheckInput): void;
|
|
87
112
|
private _schedulePersist;
|
|
88
113
|
private _fire;
|
|
89
114
|
onTriggered(cb: AlertTriggeredCallback): () => void;
|
|
115
|
+
onChange(cb: AlertChangeCallback): () => void;
|
|
90
116
|
requestNotificationPermission(): Promise<NotificationPermission>;
|
|
91
117
|
}
|
|
92
118
|
|
|
93
|
-
export { type Alert, type AlertCheckInput, type AlertCondition, type AlertCreate, type AlertFrequency, AlertManager, type AlertStatus, type AlertTriggeredCallback, type NotificationSchedule, type SoundDuration, type SoundTitle };
|
|
119
|
+
export { type Alert, type AlertChangeCallback, type AlertCheckInput, type AlertCondition, type AlertConditionDef, type AlertCreate, type AlertFrequency, AlertManager, type AlertOperator, type AlertSource, type AlertStatus, type AlertTriggeredCallback, type NotificationSchedule, type SoundDuration, type SoundTitle, type WebhookStatus };
|
package/dist/entries/alerts.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
'use client';
|
|
2
|
-
export{a as AlertManager}from'../chunk-
|
|
2
|
+
export{a as AlertManager}from'../chunk-67XM5LOK.js';
|
|
@@ -1,5 +1,7 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { S as SymbolInfo, P as Period, Q as QuoteSnapshot, D as Datafeed, f as DatafeedSubscribeCallback } from '../../types-W6SIYQ9m.js';
|
|
2
|
+
import { a as CandleData } from '../../Indicator-BQQcVGGT.js';
|
|
2
3
|
import 'react';
|
|
4
|
+
import '../../types-yETgeYsE.js';
|
|
3
5
|
|
|
4
6
|
interface CryptoSymbolInfo extends SymbolInfo {
|
|
5
7
|
exchange: string;
|
|
@@ -20,6 +22,7 @@ declare const DATAFEED_ERROR_EVENT = "astroneum:datafeed-error";
|
|
|
20
22
|
interface ExchangeAdapter {
|
|
21
23
|
readonly id: string;
|
|
22
24
|
getHistoryBars(symbol: SymbolInfo, period: Period, from: number, to: number): Promise<CandleData[]>;
|
|
25
|
+
getQuotes?(symbols: SymbolInfo[]): Promise<QuoteSnapshot[]>;
|
|
23
26
|
getWebSocketUrl(symbol: SymbolInfo, period: Period): string;
|
|
24
27
|
parseMessage(event: MessageEvent, symbol: SymbolInfo, period: Period): CandleData | null;
|
|
25
28
|
onOpen?(ws: WebSocket, symbol: SymbolInfo, period: Period): void;
|
|
@@ -53,6 +56,7 @@ declare class StandardCryptoDatafeed implements Datafeed {
|
|
|
53
56
|
private readonly activeFeedByKey;
|
|
54
57
|
constructor(options?: StandardCryptoDatafeedOptions);
|
|
55
58
|
searchSymbols(search?: string): Promise<SymbolInfo[]>;
|
|
59
|
+
getQuotes(symbols: SymbolInfo[]): Promise<QuoteSnapshot[]>;
|
|
56
60
|
getHistoryData(symbol: SymbolInfo, period: Period, from: number, to: number): Promise<CandleData[]>;
|
|
57
61
|
subscribe(symbol: SymbolInfo, period: Period, callback: DatafeedSubscribeCallback): void;
|
|
58
62
|
unsubscribe(symbol: SymbolInfo, period: Period): void;
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
'use client';
|
|
2
|
-
export{c as BinanceAdapter,d as BitgetAdapter,b as DATAFEED_ERROR_EVENT,e as OkxAdapter,a as STANDARD_CRYPTO_SYMBOLS,f as StandardCryptoDatafeed,g as createStandardCryptoDatafeed}from'../../chunk-
|
|
2
|
+
export{c as BinanceAdapter,d as BitgetAdapter,b as DATAFEED_ERROR_EVENT,e as OkxAdapter,a as STANDARD_CRYPTO_SYMBOLS,f as StandardCryptoDatafeed,g as createStandardCryptoDatafeed}from'../../chunk-WSIR5T2M.js';import'../../chunk-SDXH2WAI.js';import'../../chunk-YFPXTHZX.js';
|
|
@@ -1,5 +1,7 @@
|
|
|
1
|
-
import { D as Datafeed,
|
|
1
|
+
import { D as Datafeed, S as SymbolInfo, P as Period, f as DatafeedSubscribeCallback } from '../../types-W6SIYQ9m.js';
|
|
2
|
+
import { a as CandleData } from '../../Indicator-BQQcVGGT.js';
|
|
2
3
|
import 'react';
|
|
4
|
+
import '../../types-yETgeYsE.js';
|
|
3
5
|
|
|
4
6
|
declare class DefaultDatafeed implements Datafeed {
|
|
5
7
|
#private;
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
'use client';
|
|
2
|
-
export{a as DefaultDatafeed}from'../../chunk-
|
|
2
|
+
export{a as DefaultDatafeed}from'../../chunk-DFJMDDL5.js';export{b as WebSocketDatafeed}from'../../chunk-SDXH2WAI.js';import'../../chunk-YFPXTHZX.js';
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import { e as Coordinate, L as Locales, D as DeepPartial, S as Styles, a as CandleData, C as Chart, h as Options } from '../Indicator-BQQcVGGT.js';
|
|
2
|
+
export { A as ActionType, B as Bounding, i as ChartViewportState, c as Indicator, I as IndicatorCreate, b as IndicatorFilter, f as IndicatorTemplate, O as OverlayCreate, d as OverlayFilter, g as OverlayTemplate, P as PaneOptions, j as Period, k as PeriodType, l as SymbolInfo } from '../Indicator-BQQcVGGT.js';
|
|
3
|
+
export { c as createIndicatorTemplateFromPlugin, g as getSupportedIndicators, a as getSupportedOverlays, r as registerIndicator, b as registerIndicatorPlugin, d as registerIndicatorPlugins, e as registerOverlay, f as registerXAxis, h as registerYAxis } from '../index-_JgHTy8X.js';
|
|
4
|
+
export { I as IndicatorPlugin, a as Viewport } from '../types-yETgeYsE.js';
|
|
5
|
+
|
|
6
|
+
interface Figure<A = unknown, S = unknown> {
|
|
7
|
+
name: string;
|
|
8
|
+
attrs: A;
|
|
9
|
+
styles: S;
|
|
10
|
+
draw: (ctx: CanvasRenderingContext2D, attrs: A, styles: S) => void;
|
|
11
|
+
checkEventOn: (coordinate: Coordinate, attrs: A, styles: S) => boolean;
|
|
12
|
+
}
|
|
13
|
+
type FigureTemplate<A = unknown, S = unknown> = Pick<Figure<A, S>, 'name' | 'draw' | 'checkEventOn'>;
|
|
14
|
+
|
|
15
|
+
declare function getSupportedFigures(): string[];
|
|
16
|
+
declare function registerFigure<A = unknown, S = unknown>(figure: FigureTemplate<A, S>): void;
|
|
17
|
+
|
|
18
|
+
declare function registerLocale(locale: string, ls: Locales): void;
|
|
19
|
+
declare function getSupportedLocales(): string[];
|
|
20
|
+
|
|
21
|
+
declare function registerStyles(name: string, ss: DeepPartial<Styles>): void;
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Chart version
|
|
25
|
+
* @return {string}
|
|
26
|
+
*/
|
|
27
|
+
declare function version(): string;
|
|
28
|
+
|
|
29
|
+
type Price = number & {
|
|
30
|
+
readonly _brand: 'Price';
|
|
31
|
+
};
|
|
32
|
+
type Volume = number & {
|
|
33
|
+
readonly _brand: 'Volume';
|
|
34
|
+
};
|
|
35
|
+
type Timestamp = number & {
|
|
36
|
+
readonly _brand: 'Timestamp';
|
|
37
|
+
};
|
|
38
|
+
declare const HEADLESS_CAPABILITIES: Readonly<{
|
|
39
|
+
manifestVersion: 1;
|
|
40
|
+
lifecycle: "idempotent-create-destroy";
|
|
41
|
+
bars: "strictly-ascending-utc-milliseconds";
|
|
42
|
+
incrementalBars: "replace-last-or-append";
|
|
43
|
+
viewport: "bounded-state-v1";
|
|
44
|
+
coordinates: true;
|
|
45
|
+
panes: true;
|
|
46
|
+
studies: "typed-plugin-output";
|
|
47
|
+
drawings: "host-registered-overlays";
|
|
48
|
+
events: true;
|
|
49
|
+
resize: true;
|
|
50
|
+
screenshot: true;
|
|
51
|
+
serverImport: true;
|
|
52
|
+
nativeUi: false;
|
|
53
|
+
bundledDatafeed: false;
|
|
54
|
+
implicitNetwork: false;
|
|
55
|
+
keyboardShortcuts: false;
|
|
56
|
+
}>;
|
|
57
|
+
interface HeadlessBar extends Omit<CandleData, 'timestamp' | 'open' | 'high' | 'low' | 'close' | 'volume'> {
|
|
58
|
+
timestamp: Timestamp;
|
|
59
|
+
open: Price;
|
|
60
|
+
high: Price;
|
|
61
|
+
low: Price;
|
|
62
|
+
close: Price;
|
|
63
|
+
volume?: Volume;
|
|
64
|
+
}
|
|
65
|
+
type HeadlessChart = Omit<Chart, 'getBars' | 'getDataList' | 'replaceBars' | 'updateBar'> & {
|
|
66
|
+
getBars: () => readonly HeadlessBar[];
|
|
67
|
+
replaceBars: (bars: readonly HeadlessBar[]) => void;
|
|
68
|
+
updateBar: (bar: HeadlessBar) => void;
|
|
69
|
+
};
|
|
70
|
+
type HeadlessChartOptions = Options;
|
|
71
|
+
declare function registerBuiltInExtensions(): void;
|
|
72
|
+
declare function createChart(container: HTMLElement, options?: HeadlessChartOptions): HeadlessChart;
|
|
73
|
+
declare function destroyChart(target: HTMLElement | HeadlessChart): void;
|
|
74
|
+
declare function asPrice(value: number): Price;
|
|
75
|
+
declare function asVolume(value: number): Volume;
|
|
76
|
+
declare function asTimestamp(value: number): Timestamp;
|
|
77
|
+
|
|
78
|
+
export { Coordinate, DeepPartial, HEADLESS_CAPABILITIES, type HeadlessBar, type HeadlessChart, type HeadlessChartOptions, type Price, Styles, type Timestamp, type Volume, asPrice, asTimestamp, asVolume, createChart, destroyChart, getSupportedFigures, getSupportedLocales, registerBuiltInExtensions, registerFigure, registerLocale, registerStyles, version };
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import {a as a$1}from'../chunk-EHZN52CY.js';export{a as createIndicatorTemplateFromPlugin,b as registerIndicatorPlugin,c as registerIndicatorPlugins}from'../chunk-ONPPQW65.js';import {a,d,e,q,r}from'../chunk-47YGQEL5.js';export{h as getSupportedFigures,c as getSupportedIndicators,m as getSupportedLocales,f as getSupportedOverlays,i as registerFigure,b as registerIndicator,l as registerLocale,e as registerOverlay,g as registerStyles,o as registerXAxis,n as registerYAxis,p as version}from'../chunk-47YGQEL5.js';var H=Object.freeze({manifestVersion:1,lifecycle:"idempotent-create-destroy",bars:"strictly-ascending-utc-milliseconds",incrementalBars:"replace-last-or-append",viewport:"bounded-state-v1",coordinates:true,panes:true,studies:"typed-plugin-output",drawings:"host-registered-overlays",events:true,resize:true,screenshot:true,serverImport:true,nativeUi:false,bundledDatafeed:false,implicitNetwork:false,keyboardShortcuts:false}),p=false;function S(){a(),d(),p||(a$1.forEach(e$1=>{e(e$1);}),p=true);}function w(e,l){let r=q(e,l);if(r===null)throw new Error("Astroneum could not create a chart for the supplied container");return r}function E(e){r(e);}function V(e){return e}function L(e){return e}function A(e){return e}export{H as HEADLESS_CAPABILITIES,V as asPrice,A as asTimestamp,L as asVolume,w as createChart,E as destroyChart,S as registerBuiltInExtensions};
|
|
@@ -1,5 +1,7 @@
|
|
|
1
|
-
import { A as AstroneumOptions,
|
|
1
|
+
import { A as AstroneumOptions, S as SymbolInfo, P as Period, a as AstroneumHandle } from '../types-W6SIYQ9m.js';
|
|
2
2
|
import 'react';
|
|
3
|
+
import '../Indicator-BQQcVGGT.js';
|
|
4
|
+
import '../types-yETgeYsE.js';
|
|
3
5
|
|
|
4
6
|
/** Number of charts in a multi-chart view. */
|
|
5
7
|
type MultiChartCount = 2 | 4 | 8 | 16;
|
|
@@ -58,11 +60,20 @@ declare class MultiChartLayout {
|
|
|
58
60
|
private _syncSymbolPeriod;
|
|
59
61
|
private _activeIndex;
|
|
60
62
|
private _wrapperEl;
|
|
63
|
+
private _states;
|
|
64
|
+
private _persistTimer;
|
|
65
|
+
private _restoreTimer;
|
|
66
|
+
private _readyTimer;
|
|
67
|
+
private _restorePending;
|
|
68
|
+
private _lastPersisted;
|
|
61
69
|
constructor(options: MultiChartLayoutOptions);
|
|
62
70
|
private _render;
|
|
71
|
+
private _initializeCharts;
|
|
63
72
|
private _setActive;
|
|
64
73
|
private _destroy;
|
|
65
74
|
private _persist;
|
|
75
|
+
private _captureStates;
|
|
76
|
+
private _restoreStates;
|
|
66
77
|
/** Change the layout grid (2 | 4 | 8 | 16). Re-renders all charts. */
|
|
67
78
|
setCount(count: MultiChartCount): void;
|
|
68
79
|
/** Get the count of charts. */
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
'use client';
|
|
2
|
-
export{
|
|
2
|
+
export{g as MultiChartLayout}from'../chunk-HKLWNPMP.js';import'../chunk-SCTHEM27.js';import'../chunk-YFPXTHZX.js';import'../chunk-67XM5LOK.js';import'../chunk-ONPPQW65.js';import'../chunk-EFAS6F4C.js';import'../chunk-47YGQEL5.js';
|
package/dist/entries/replay.d.ts
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
|
-
import { D as Datafeed,
|
|
1
|
+
import { D as Datafeed, S as SymbolInfo, P as Period } from '../types-W6SIYQ9m.js';
|
|
2
|
+
import { a as CandleData, N as Nullable } from '../Indicator-BQQcVGGT.js';
|
|
2
3
|
import 'react';
|
|
4
|
+
import '../types-yETgeYsE.js';
|
|
3
5
|
|
|
4
6
|
type BarReplayState = 'idle' | 'playing' | 'paused' | 'finished';
|
|
5
7
|
interface BarReplayOptions {
|
package/dist/entries/script.d.ts
CHANGED
|
@@ -1,68 +1,2 @@
|
|
|
1
|
-
|
|
2
|
-
import '
|
|
3
|
-
|
|
4
|
-
/**
|
|
5
|
-
* Client-side JavaScript indicator scripting engine.
|
|
6
|
-
*
|
|
7
|
-
* Lets users write Pine-Script–inspired indicator logic in plain JS
|
|
8
|
-
* and compile it into an IndicatorTemplate that is registered
|
|
9
|
-
* with the chart engine during compilation.
|
|
10
|
-
*
|
|
11
|
-
* Security: scripts run inside a Function scope with a curated API
|
|
12
|
-
* surface (forbidden identifiers shadowed, Object/Array prototypes frozen).
|
|
13
|
-
* This is a best-effort sandbox suitable for trusted user scripts only —
|
|
14
|
-
* constructor-chain escapes (e.g. (0).constructor.constructor) are not
|
|
15
|
-
* fully blocked. Do NOT run untrusted third-party scripts without a
|
|
16
|
-
* real isolate (sandboxed iframe or Web Worker).
|
|
17
|
-
*
|
|
18
|
-
* Usage:
|
|
19
|
-
* const engine = ScriptEngine.getInstance()
|
|
20
|
-
* const template = engine.compile(`
|
|
21
|
-
* study('My MA', { overlay: true })
|
|
22
|
-
* const len = input('Length', 14)
|
|
23
|
-
* plot(ta.sma(close, len), { title: 'SMA', color: '#2962ff' })
|
|
24
|
-
* `)
|
|
25
|
-
* chart.createIndicator(template.name)
|
|
26
|
-
*/
|
|
27
|
-
|
|
28
|
-
interface StudyOptions {
|
|
29
|
-
/** Display name shown in tooltip */
|
|
30
|
-
shortName?: string;
|
|
31
|
-
/** Whether to overlay on the price pane (default false) */
|
|
32
|
-
overlay?: boolean;
|
|
33
|
-
/** Precision of displayed values */
|
|
34
|
-
precision?: number;
|
|
35
|
-
}
|
|
36
|
-
interface PlotOptions {
|
|
37
|
-
title?: string;
|
|
38
|
-
color?: string;
|
|
39
|
-
lineWidth?: number;
|
|
40
|
-
visible?: boolean;
|
|
41
|
-
}
|
|
42
|
-
interface InputOptions {
|
|
43
|
-
type?: 'int' | 'float' | 'bool' | 'string';
|
|
44
|
-
options?: (number | string)[];
|
|
45
|
-
}
|
|
46
|
-
interface CompiledIndicator extends IndicatorTemplate {
|
|
47
|
-
/** Original source for editing */
|
|
48
|
-
_source: string;
|
|
49
|
-
}
|
|
50
|
-
declare class ScriptEngine {
|
|
51
|
-
private static _instance;
|
|
52
|
-
private _registry;
|
|
53
|
-
private constructor();
|
|
54
|
-
static getInstance(): ScriptEngine;
|
|
55
|
-
/**
|
|
56
|
-
* Compile a script string into an IndicatorTemplate.
|
|
57
|
-
* Throws a descriptive Error if compilation or type validation fails.
|
|
58
|
-
*/
|
|
59
|
-
compile(source: string, name?: string): CompiledIndicator;
|
|
60
|
-
/** Get a previously compiled template by name */
|
|
61
|
-
get(name: string): CompiledIndicator | undefined;
|
|
62
|
-
/** All registered script names */
|
|
63
|
-
list(): string[];
|
|
64
|
-
/** Remove a compiled indicator */
|
|
65
|
-
remove(name: string): void;
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
export { type CompiledIndicator, type InputOptions, type PlotOptions, ScriptEngine, type StudyOptions };
|
|
1
|
+
export { C as CompiledIndicator, d as CompiledStrategy, I as InputOptions, P as PlotOptions, e as ScriptEngine, f as StudyOptions } from '../script-BU9StbN-.js';
|
|
2
|
+
import '../Indicator-BQQcVGGT.js';
|
package/dist/entries/script.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
'use client';
|
|
2
|
-
export{
|
|
2
|
+
export{b as ScriptEngine}from'../chunk-EFAS6F4C.js';import'../chunk-47YGQEL5.js';
|
|
@@ -1,5 +1,7 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { S as SymbolInfo, Q as QuoteSnapshot } from '../types-W6SIYQ9m.js';
|
|
2
|
+
import { P as Price, V as Volume } from '../types-yETgeYsE.js';
|
|
2
3
|
import 'react';
|
|
4
|
+
import '../Indicator-BQQcVGGT.js';
|
|
3
5
|
|
|
4
6
|
/**
|
|
5
7
|
* WatchlistManager — client-side multi-watchlist manager.
|
|
@@ -9,14 +11,34 @@ import 'react';
|
|
|
9
11
|
interface WatchSymbol {
|
|
10
12
|
ticker: string;
|
|
11
13
|
name?: string;
|
|
14
|
+
shortName?: string;
|
|
15
|
+
exchange?: string;
|
|
16
|
+
pricePrecision?: number;
|
|
17
|
+
volumePrecision?: number;
|
|
18
|
+
logo?: string;
|
|
19
|
+
group?: string;
|
|
12
20
|
/** Injected externally — not stored. Branded Price ensures callers use asPrice() at ingress. */
|
|
13
21
|
lastPrice?: Price;
|
|
22
|
+
change?: number;
|
|
14
23
|
changePercent?: number;
|
|
24
|
+
volume?: Volume;
|
|
25
|
+
open?: Price;
|
|
26
|
+
high?: Price;
|
|
27
|
+
low?: Price;
|
|
28
|
+
}
|
|
29
|
+
type WatchlistColumn = 'name' | 'last' | 'change' | 'changePercent' | 'volume' | 'open';
|
|
30
|
+
type WatchlistSortDirection = 'asc' | 'desc';
|
|
31
|
+
interface WatchlistSort {
|
|
32
|
+
column: WatchlistColumn;
|
|
33
|
+
direction: WatchlistSortDirection;
|
|
15
34
|
}
|
|
16
35
|
interface Watchlist {
|
|
17
36
|
id: string;
|
|
18
37
|
name: string;
|
|
19
38
|
symbols: WatchSymbol[];
|
|
39
|
+
color?: string;
|
|
40
|
+
columns?: WatchlistColumn[];
|
|
41
|
+
sort?: WatchlistSort;
|
|
20
42
|
}
|
|
21
43
|
type WatchlistsChangedCallback = (lists: Watchlist[]) => void;
|
|
22
44
|
declare class WatchlistManager {
|
|
@@ -33,11 +55,19 @@ declare class WatchlistManager {
|
|
|
33
55
|
reorderLists(from: number, to: number): void;
|
|
34
56
|
getSymbols(listId: string): WatchSymbol[];
|
|
35
57
|
addSymbol(listId: string, symbol: WatchSymbol): void;
|
|
58
|
+
addSymbolFromInfo(listId: string, symbol: SymbolInfo): void;
|
|
36
59
|
removeSymbol(listId: string, ticker: string): void;
|
|
37
60
|
reorderSymbols(listId: string, from: number, to: number): void;
|
|
61
|
+
moveSymbol(fromListId: string, toListId: string, ticker: string, toIndex?: number): void;
|
|
62
|
+
setSort(listId: string, column: WatchlistColumn, direction?: WatchlistSortDirection): void;
|
|
63
|
+
setColumns(listId: string, columns: WatchlistColumn[]): void;
|
|
64
|
+
setColor(listId: string, color: string): void;
|
|
65
|
+
updateQuotes(snapshots: QuoteSnapshot[]): void;
|
|
38
66
|
private _find;
|
|
67
|
+
private _storedSymbol;
|
|
68
|
+
private _emit;
|
|
39
69
|
private _persist;
|
|
40
70
|
private _load;
|
|
41
71
|
}
|
|
42
72
|
|
|
43
|
-
export { type WatchSymbol, type Watchlist, WatchlistManager };
|
|
73
|
+
export { type WatchSymbol, type Watchlist, type WatchlistColumn, WatchlistManager, type WatchlistSort, type WatchlistSortDirection };
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
'use client';
|
|
2
|
-
export{a as WatchlistManager}from'../chunk-
|
|
2
|
+
export{a as WatchlistManager}from'../chunk-UQXYMB6X.js';
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import * as react from 'react';
|
|
2
|
+
import { ReactNode } from 'react';
|
|
3
|
+
import { I as IndicatorSourceOption } from '../index-BiXdqLA4.js';
|
|
4
|
+
export { L as LayerProvider, u as useLayer, a as useLayerProvider } from '../index-BiXdqLA4.js';
|
|
5
|
+
import { D as Datafeed } from '../types-W6SIYQ9m.js';
|
|
6
|
+
import './alerts.js';
|
|
7
|
+
import '../Indicator-BQQcVGGT.js';
|
|
8
|
+
import '../types-yETgeYsE.js';
|
|
9
|
+
|
|
10
|
+
interface WorkspaceShellContextValue {
|
|
11
|
+
sidebarOpen: boolean;
|
|
12
|
+
sidebarWidth: number;
|
|
13
|
+
dockOpen: boolean;
|
|
14
|
+
dockMaximized: boolean;
|
|
15
|
+
dockHeight: number;
|
|
16
|
+
toggleSidebar: () => void;
|
|
17
|
+
setSidebarWidth: (width: number) => void;
|
|
18
|
+
toggleDock: () => void;
|
|
19
|
+
toggleDockMaximized: () => void;
|
|
20
|
+
setDockHeight: (height: number) => void;
|
|
21
|
+
}
|
|
22
|
+
interface WorkspaceShellProps {
|
|
23
|
+
children: ReactNode;
|
|
24
|
+
toolbar?: ReactNode;
|
|
25
|
+
sidebar?: ReactNode;
|
|
26
|
+
dock?: ReactNode;
|
|
27
|
+
footer?: ReactNode;
|
|
28
|
+
theme?: 'dark' | 'light' | 'high-contrast';
|
|
29
|
+
defaultSidebarOpen?: boolean;
|
|
30
|
+
defaultDockOpen?: boolean;
|
|
31
|
+
defaultSidebarWidth?: number;
|
|
32
|
+
defaultDockHeight?: number;
|
|
33
|
+
storageKey?: string | null;
|
|
34
|
+
}
|
|
35
|
+
interface WorkspaceToolbarProps {
|
|
36
|
+
children?: ReactNode;
|
|
37
|
+
leading?: ReactNode;
|
|
38
|
+
context?: ReactNode;
|
|
39
|
+
actions?: ReactNode;
|
|
40
|
+
}
|
|
41
|
+
declare function WorkspaceToolbar({ children, leading, context, actions }: WorkspaceToolbarProps): ReactNode;
|
|
42
|
+
declare function useWorkspaceShell(): WorkspaceShellContextValue;
|
|
43
|
+
declare function WorkspaceShell({ children, toolbar, sidebar, dock, footer, theme, defaultSidebarOpen, defaultDockOpen, defaultSidebarWidth, defaultDockHeight, storageKey, }: WorkspaceShellProps): ReactNode;
|
|
44
|
+
|
|
45
|
+
interface WorkspaceWatchlistProps {
|
|
46
|
+
datafeed: Datafeed;
|
|
47
|
+
selectedTicker?: string;
|
|
48
|
+
open?: boolean;
|
|
49
|
+
onSymbolSelect?: (ticker: string) => void;
|
|
50
|
+
}
|
|
51
|
+
declare function WorkspaceWatchlist({ datafeed, selectedTicker, open, onSymbolSelect }: WorkspaceWatchlistProps): react.ReactNode;
|
|
52
|
+
|
|
53
|
+
interface WorkspaceAlertsProps {
|
|
54
|
+
symbol: string;
|
|
55
|
+
currentPrice?: number;
|
|
56
|
+
indicatorSources?: IndicatorSourceOption[];
|
|
57
|
+
onSymbolChange?: (symbol: string) => void;
|
|
58
|
+
}
|
|
59
|
+
declare function WorkspaceAlerts({ symbol, currentPrice, indicatorSources, onSymbolChange }: WorkspaceAlertsProps): react.ReactNode;
|
|
60
|
+
|
|
61
|
+
export { WorkspaceAlerts, type WorkspaceAlertsProps, WorkspaceShell, type WorkspaceShellContextValue, type WorkspaceShellProps, WorkspaceToolbar, type WorkspaceToolbarProps, WorkspaceWatchlist, type WorkspaceWatchlistProps, useWorkspaceShell };
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import {c,b,s,t}from'../chunk-SCTHEM27.js';export{p as LayerProvider,r as useLayer,q as useLayerProvider}from'../chunk-SCTHEM27.js';import {a as a$1}from'../chunk-67XM5LOK.js';import {a}from'../chunk-UQXYMB6X.js';import {createContext,useContext,useId,useState,useCallback,useEffect,useMemo}from'react';function Z({children:e,leading:a,context:i,actions:b$1}){return c("div",{className:"astroneum-workspace-toolbar-content",children:[a&&b("div",{className:"astroneum-workspace-toolbar-leading",children:a}),i&&b("div",{className:"astroneum-workspace-toolbar-context",children:i}),(b$1||e)&&c("div",{className:"astroneum-workspace-toolbar-actions",children:[b$1,e]})]})}var M=280,E=540,R=120,T=480,j=createContext(null);function ee(){let e=useContext(j);if(!e)throw new Error("useWorkspaceShell must be used inside WorkspaceShell");return e}function D(e,a,i){return Math.min(i,Math.max(a,e))}function le(e){try{let a=localStorage.getItem(e);if(!a)return null;let i=JSON.parse(a);return i&&typeof i=="object"?i:null}catch{return null}}function de(e,a){try{localStorage.setItem(e,JSON.stringify(a));}catch{}}function q({axis:e,value:a,min:i,max:b$1,label:u,onChange:k}){let S=c=>{let m=c.shiftKey?40:10,l=e==="vertical"?"ArrowLeft":"ArrowUp",f=e==="vertical"?"ArrowRight":"ArrowDown";if(c.key==="Home"){c.preventDefault(),k(i);return}if(c.key==="End"){c.preventDefault(),k(b$1);return}if(c.key===l){c.preventDefault(),k(a-m);return}c.key===f&&(c.preventDefault(),k(a+m));},g=c=>{c.preventDefault();let m=e==="vertical"?c.clientX:c.clientY,l=a,f=r=>{let v=e==="vertical"?r.clientX:r.clientY;k(l-(v-m));},n=()=>{window.removeEventListener("pointermove",f),window.removeEventListener("pointerup",n);};window.addEventListener("pointermove",f),window.addEventListener("pointerup",n);};return b("div",{className:`astroneum-workspace-resize astroneum-workspace-resize-${e}`,role:"separator",tabIndex:0,"aria-orientation":e,"aria-label":u,"aria-valuemin":i,"aria-valuemax":b$1,"aria-valuenow":a,onKeyDown:S,onPointerDown:g})}function $({children:e,toolbar:a,sidebar:i,dock:b$1,footer:u,theme:k="dark",defaultSidebarOpen:S=true,defaultDockOpen:g=true,defaultSidebarWidth:c$1=320,defaultDockHeight:m=220,storageKey:l=null}){let f=useId(),n=useId(),[r,v]=useState(S),[w,A]=useState(()=>D(c$1,M,E)),[W,x]=useState(g),[t,p]=useState(false),[h,I]=useState(()=>D(m,R,T)),[P,y]=useState(void 0),O=useCallback(d=>A(D(d,M,E)),[]),N=useCallback(d=>I(D(d,R,T)),[]),re=useCallback(()=>v(d=>!d),[]),ae=useCallback(()=>{x(d=>!d),p(false);},[]),ne=useCallback(()=>{x(true),p(d=>!d);},[]);useEffect(()=>{W||p(false);},[W]),useEffect(()=>{if(!l){y(null);return}let d=le(l);d&&(typeof d.sidebarOpen=="boolean"&&v(d.sidebarOpen),typeof d.sidebarWidth=="number"&&A(D(d.sidebarWidth,M,E)),typeof d.dockOpen=="boolean"&&x(d.dockOpen),typeof d.dockMaximized=="boolean"&&p(d.dockMaximized),typeof d.dockHeight=="number"&&I(D(d.dockHeight,R,T))),y(l);},[l]),useEffect(()=>{!l||P!==l||de(l,{sidebarOpen:r,sidebarWidth:w,dockOpen:W,dockMaximized:t,dockHeight:h});},[h,t,W,P,r,w,l]);let se={sidebarOpen:r,sidebarWidth:w,dockOpen:W,dockMaximized:t,dockHeight:h,toggleSidebar:re,setSidebarWidth:O,toggleDock:ae,toggleDockMaximized:ne,setDockHeight:N};return b(j.Provider,{value:se,children:c("section",{className:"astroneum-workspace term-shell","data-theme":k,"data-sidebar":r?"open":"closed","data-dock":W?"open":"closed","data-dock-maximized":t,style:{"--astroneum-workspace-sidebar-width":`${w}px`,"--astroneum-workspace-dock-height":`${h}px`},children:[b("header",{className:"astroneum-workspace-toolbar term-topbar",role:"toolbar",children:a}),b("main",{className:"astroneum-workspace-main term-workspace",children:c("div",{className:"astroneum-workspace-content term-workspace-main",children:[b("div",{className:"astroneum-workspace-chart term-chart",children:e}),c("section",{id:n,className:"astroneum-workspace-dock term-dock","aria-label":"Workspace dock",children:[W&&b(q,{axis:"horizontal",value:h,min:R,max:T,label:"Resize dock",onChange:N}),b$1]})]})}),c("aside",{id:f,className:"astroneum-workspace-sidebar term-sidebar","aria-label":"Workspace sidebar","aria-hidden":!r,children:[r&&b(q,{axis:"vertical",value:w,min:M,max:E,label:"Resize sidebar",onChange:O}),i]}),b("footer",{className:"astroneum-workspace-footer term-footer",children:u})]})})}var ue=["last","changePercent"],pe={name:"Name",last:"Last",change:"Chg",changePercent:"Chg%",volume:"Vol",open:"Open"};function me(e){return {ticker:e.ticker,name:e.name,shortName:e.shortName,exchange:e.exchange,pricePrecision:e.pricePrecision,volumePrecision:e.volumePrecision}}function oe(e,a){if(a==="name")return e.name??e.exchange??"";if(a==="changePercent")return e.changePercent==null?"-":`${e.changePercent>=0?"+":""}${e.changePercent.toFixed(2)}%`;if(a==="volume")return e.volume==null?"-":Intl.NumberFormat(void 0,{notation:"compact",maximumFractionDigits:1}).format(e.volume);let i=a==="last"?e.lastPrice:e[a];return i==null?"-":Number(i).toLocaleString(void 0,{maximumFractionDigits:e.pricePrecision??2,minimumFractionDigits:e.pricePrecision??2})}function _({datafeed:e,selectedTicker:a$1,open:i=true,onSymbolSelect:b$1}){let u=a.getInstance(),[k,S]=useState(u.getLists()),[g,c$1]=useState(u.getLists()[0]?.id??""),[m,l]=useState(false),[f,n]=useState(false);useEffect(()=>u.onChange(t=>{S([...t]),c$1(p=>t.some(h=>h.id===p)?p:t[0]?.id??"");}),[u]);let r=k.find(t=>t.id===g)??k[0],v=r?.columns?.length?r.columns:ue;useEffect(()=>{if(!i||!r||!e.getQuotes||r.symbols.length===0)return;let t=false,p=async()=>{try{u.updateQuotes(await e.getQuotes(r.symbols.map(me))),t||n(!1);}catch{t||n(true);}};p();let h=window.setInterval(()=>{p();},2e3);return ()=>{t=true,window.clearInterval(h);}},[r?.id,r?.symbols.map(t=>t.ticker).join("|"),e,u,i]);let w=[...r?.symbols??[]].sort((t,p)=>{let h=r?.sort;if(!h)return 0;let I=N=>h.column==="name"?N.name??N.ticker:h.column==="last"?N.lastPrice:N[h.column],P=I(t),y=I(p);if(P==null)return 1;if(y==null)return -1;let O=typeof P=="string"?P.localeCompare(String(y)):Number(P)-Number(y);return h.direction==="asc"?O:-O}),A=t=>{r&&u.setSort(r.id,t,r.sort?.column===t&&r.sort.direction==="asc"?"desc":"asc");},W=()=>{let t=u.createList(`Watchlist ${k.length+1}`);c$1(t.id);},x=`minmax(96px, 1fr) ${v.filter(t=>t!=="name").map(()=>"minmax(58px, auto)").join(" ")}`;return c("section",{className:"astroneum-workspace-watchlist","aria-label":"Watchlist",children:[c("header",{className:"astroneum-workspace-watchlist-header",children:[b("select",{value:r?.id??"",onChange:t=>c$1(t.target.value),"aria-label":"Select watchlist",children:k.map(t=>b("option",{value:t.id,children:t.name},t.id))}),b("button",{onClick:()=>l(true),children:"Add"}),b("button",{onClick:W,children:"New"})]}),f&&b("div",{className:"astroneum-workspace-watchlist-error",role:"status",children:"Quotes unavailable"}),r&&r.symbols.length>0?c("div",{className:"astroneum-workspace-watchlist-table",children:[c("div",{className:"astroneum-workspace-watchlist-columns",style:{gridTemplateColumns:x},role:"row",children:[b("button",{role:"columnheader",onClick:()=>A("name"),children:"Symbol"}),v.filter(t=>t!=="name").map(t=>b("button",{role:"columnheader",onClick:()=>A(t),children:pe[t]},t))]}),b("div",{role:"rowgroup",children:w.map(t=>c("button",{className:t.ticker===a$1?"is-selected":"",style:{gridTemplateColumns:x},role:"row",onClick:()=>b$1?.(t.ticker),children:[c("span",{children:[b("strong",{children:t.shortName??t.ticker}),v.includes("name")&&b("small",{children:oe(t,"name")})]}),v.filter(p=>p!=="name").map(p=>b("span",{className:p==="changePercent"&&t.changePercent!=null?t.changePercent>=0?"is-up":"is-down":"",children:oe(t,p)},p))]},t.ticker))})]}):c("div",{className:"astroneum-workspace-watchlist-empty",children:[b("strong",{children:"No symbols yet"}),b("button",{onClick:()=>l(true),children:"Add symbol"})]}),m&&r&&b(s,{locale:"en-US",searchSymbols:t=>e.searchSymbols(t),onSymbolSelected:t=>u.addSymbolFromInfo(r.id,t),onClose:()=>l(false)})]})}function fe(e){return e.conditions?.length?e.conditions.map(a=>`${a.operator} ${a.value}`).join(" and "):`${e.condition} ${e.price}`}function F({symbol:e,currentPrice:a,indicatorSources:i,onSymbolChange:b$1}){let u=a$1.getInstance(),[k,S]=useState([...u.getAll()]),[g,c$1]=useState(false),[m,l]=useState(null);useEffect(()=>u.onChange(n=>S([...n])),[u]);let f=useMemo(()=>k.filter(n=>!g||n.symbol===e),[k,g,e]);return c("section",{className:"astroneum-workspace-alerts","aria-label":"Alerts",children:[c("header",{className:"astroneum-workspace-alerts-header",children:[b("strong",{children:"Alerts"}),b("span",{children:f.length}),b("button",{"aria-pressed":g,onClick:()=>c$1(n=>!n),children:g?e:"All"}),b("button",{onClick:()=>l("create"),children:"Create"})]}),b("div",{className:"astroneum-workspace-alerts-list",children:f.length===0?c("div",{className:"astroneum-workspace-alerts-empty",children:[b("strong",{children:"No active alerts"}),b("button",{onClick:()=>l("create"),children:"Create alert"})]}):f.map(n=>c("article",{className:"astroneum-workspace-alert-row",onClick:()=>l(n),children:[b("span",{className:`astroneum-workspace-alert-state is-${n.status}`,children:n.status}),c("div",{children:[c("strong",{children:[n.symbol,n.timeframe?`, ${n.timeframe}`:""]}),b("span",{children:fe(n)})]}),c("div",{className:"astroneum-workspace-alert-actions",onClick:r=>r.stopPropagation(),children:[(n.status==="active"||n.status==="paused")&&b("button",{onClick:()=>u.togglePause(n.id),children:n.status==="active"?"Pause":"Resume"}),b("button",{onClick:()=>u.delete(n.id),children:"Delete"})]})]},n.id))}),m&&b(t,{locale:"en-US",symbol:m==="create"?e:m.symbol,timeframe:m==="create"?"D":m.timeframe??"D",currentPrice:a,editAlert:m==="create"?void 0:m,indicatorSources:i,onSymbolChange:b$1,onClose:()=>l(null)})]})}export{F as WorkspaceAlerts,$ as WorkspaceShell,Z as WorkspaceToolbar,_ as WorkspaceWatchlist,ee as useWorkspaceShell};
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import react__default, { ReactNode } from 'react';
|
|
2
|
+
import { Alert } from './entries/alerts.js';
|
|
3
|
+
|
|
4
|
+
declare namespace JSX {
|
|
5
|
+
type Element = react__default.ReactNode;
|
|
6
|
+
type CSSProperties = react__default.CSSProperties & Record<string, string | number | undefined>;
|
|
7
|
+
}
|
|
8
|
+
type Component<P = Record<string, never>> = (props: P) => JSX.Element;
|
|
9
|
+
|
|
10
|
+
interface IndicatorSourceOption {
|
|
11
|
+
paneId: string;
|
|
12
|
+
name: string;
|
|
13
|
+
plot: string;
|
|
14
|
+
shortName: string;
|
|
15
|
+
}
|
|
16
|
+
interface AlertModalProps {
|
|
17
|
+
locale: string;
|
|
18
|
+
symbol: string;
|
|
19
|
+
timeframe?: string;
|
|
20
|
+
currentPrice?: number;
|
|
21
|
+
initialPrice?: number;
|
|
22
|
+
editAlert?: Alert;
|
|
23
|
+
indicatorSources?: IndicatorSourceOption[];
|
|
24
|
+
onSymbolChange?: (symbol: string) => void;
|
|
25
|
+
onClose: () => void;
|
|
26
|
+
}
|
|
27
|
+
declare const AlertModal: Component<AlertModalProps>;
|
|
28
|
+
|
|
29
|
+
interface LayerRecord {
|
|
30
|
+
id: string;
|
|
31
|
+
close: () => void;
|
|
32
|
+
}
|
|
33
|
+
interface LayerContextValue {
|
|
34
|
+
register: (layer: LayerRecord) => () => void;
|
|
35
|
+
closeTop: () => boolean;
|
|
36
|
+
closeAll: () => void;
|
|
37
|
+
getTrigger: () => Element | null;
|
|
38
|
+
}
|
|
39
|
+
declare function LayerProvider({ children }: {
|
|
40
|
+
children: ReactNode;
|
|
41
|
+
}): ReactNode;
|
|
42
|
+
declare function useLayerProvider(): LayerContextValue;
|
|
43
|
+
declare function useLayer(id: string, open: boolean, onClose: () => void): void;
|
|
44
|
+
|
|
45
|
+
export { AlertModal as A, type Component as C, type IndicatorSourceOption as I, LayerProvider as L, useLayerProvider as a, useLayer as u };
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { f as IndicatorTemplate, g as OverlayTemplate, X as XAxisTemplate, Y as YAxisTemplate } from './Indicator-BQQcVGGT.js';
|
|
2
|
+
import { I as IndicatorPlugin } from './types-yETgeYsE.js';
|
|
3
|
+
|
|
4
|
+
declare function registerIndicator<D = unknown, C = unknown, E = unknown>(indicator: IndicatorTemplate<D, C, E>): void;
|
|
5
|
+
declare function getSupportedIndicators(): string[];
|
|
6
|
+
|
|
7
|
+
declare function registerOverlay<E = unknown>(template: OverlayTemplate<E>): void;
|
|
8
|
+
declare function getSupportedOverlays(): string[];
|
|
9
|
+
|
|
10
|
+
declare function registerXAxis(axis: XAxisTemplate): void;
|
|
11
|
+
|
|
12
|
+
declare function registerYAxis(axis: YAxisTemplate): void;
|
|
13
|
+
|
|
14
|
+
type NormalizedIndicatorRow = Record<string, number | null>;
|
|
15
|
+
declare function createIndicatorTemplateFromPlugin<TOutput>(plugin: IndicatorPlugin<TOutput>): IndicatorTemplate<NormalizedIndicatorRow, number>;
|
|
16
|
+
declare function registerIndicatorPlugin<TOutput>(plugin: IndicatorPlugin<TOutput>): void;
|
|
17
|
+
declare function registerIndicatorPlugins(plugins: ReadonlyArray<IndicatorPlugin<unknown>>): void;
|
|
18
|
+
|
|
19
|
+
export { getSupportedOverlays as a, registerIndicatorPlugin as b, createIndicatorTemplateFromPlugin as c, registerIndicatorPlugins as d, registerOverlay as e, registerXAxis as f, getSupportedIndicators as g, registerYAxis as h, registerIndicator as r };
|