Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

218 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

AXIS

AXIS β€” installable charting PWA for Pine Scriptβ„’.

Website: hoox.sh/axis Β· Docs: hoox.sh/axis/docs Β· Repo: hoox-sh/axis

Installable PWA, fully pluggable, runs against the local pyne Pro API, a Cloudflare Worker, or fully offline with the in-browser Pyodide engine.

Ecosystem

Part of the HOOX open trading stack:

Product Role Repo Website
HOOX Edge trading framework (Cloudflare Workers) hoox-sh/hoox hoox.sh Β· docs
PYNE Pine Scriptβ„’ toolchain + Pro API (engine) hoox-sh/pyne hoox.sh/pyne Β· docs
pyne-agent-worker NL β†’ PYNE scripts (Workers AIβ„’ + optional RAG) hoox-sh/pyne-agent-worker AXIS plugin docs
AXIS Charting PWA (this repo) hoox-sh/axis hoox.sh/axis Β· docs

PYNE Agent plugin (optional): Manager β†’ Plugins β†’ Install β†’ PYNE Agent, or URL
https://pyne-agent-worker.cryptolinx.workers.dev/plugin/axis-pine-agent.js
(standalone Workers AI β€” no HOOX mesh required). Docs: PYNE Agent.

# Typical local trio
make -C ../pynescript run   # pyne Pro API :5002
bun run dev                 # this repo :3000

# Optional desktop shell (Tauri 2 β€” needs Rust + system webview libs)
bun run desktop:dev         # native window + Vite HMR
bun run desktop:build       # package installers under src-tauri/target/release/bundle/

AXIS CLI (packages/cli)

Operator entry for install, diagnostics, Worker bootstrap (D1 / OAuth), secrets, deploy, and health.

cd packages/cli && bun install && cd ../..
bun run axis --help

bun run axis:install                          # app + worker + CLI deps
bun run axis:doctor                           # toolchain + wrangler.toml
bun run axis setup -- --github-client-id Ov23li…
bun run axis setup -- d1 --remote             # apply D1 schema on CF
bun run axis -- secret put ADMIN_TOKEN
bun run axis:deploy                           # Worker pynescript-axis
bun run axis:health -- --oauth                # live /health + device OAuth

# Make wrappers: make axis-doctor  make axis-deploy  make axis ARGS="…"

Docs: AXIS CLI Β· packages/cli/README.md Β· live demo axis.hoox.sh Β· Worker https://pynescript-axis.cryptolinx.workers.dev

See docs/devops/desktop.mdx for platform prerequisites.

Icons: Lucide via lucide-solid (tree-shakable stroke icons, ISC). Wrapper: src/ui/icons.tsx.

Architecture

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ Browser (PWA) ─────────────────────────────┐
β”‚  Service Worker Β· manifest.webmanifest Β· offline cache               β”‚
β”‚  UI: lightweight-charts + CodeMirror 6 + tabs                         β”‚
β”‚                                                                       β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”    β”‚
β”‚  β”‚ Sources  β”‚  β”‚ Streams  β”‚  β”‚ Engines  β”‚  β”‚ Storage (localStorageβ”‚   β”‚
β”‚  β”‚ (history)β”‚  β”‚ (live)   β”‚  β”‚ (calc)   β”‚  β”‚  + IDB for offline)  β”‚   β”‚
β”‚  β””β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”˜  β””β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”˜  β””β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”˜  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜    β”‚
β”‚       β”‚             β”‚              β”‚                                    β”‚
β”‚       β–Ό             β–Ό              β–Ό                                    β”‚
β”‚  registry-driven, all plugins share the same contract                 β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
            β”‚                                            β”‚
            β–Ό (only if engine=server OR stream=remote)   β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ Backend (pluggable) ───────────────────────┐
β”‚  Local Flask `make run`      OR      Cloudflare Pages + Worker        β”‚
β”‚  (dev only)                            β€’ Pages: static PWA             β”‚
β”‚                                        β€’ Worker: /api/run, /api/streamβ”‚
β”‚                                        β€’ Durable Object: live session  β”‚
β”‚                                        β€’ KV: API keys, usage meter     β”‚
β”‚                                        β€’ D1: persistent runs/scripts   β”‚
β”‚                                        β€’ R2: indicator bundle cache    β”‚
β”‚                                        β€’ WebSocket Hibernation (DO)    β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Plugin contract

Solid path uses a unified TypeScript registry (src/plugins/registry.ts). Every plugin is an object with { id, name, kind, description, configSchema, ... }.

// kind: 'source'  β€” historical OHLCV
// kind: 'stream'  β€” live tick / bar push
// kind: 'engine'  β€” calculate Pine
// kind: 'storage' β€” user script library (local | git | cloud)
// kind: 'dataset' β€” on-chain / alternate series (TVL, …)
// kind: 'component' β€” UI slots (phase 2)

// See src/plugins/types.ts for full contracts.
// Active selection: store.activePlugins { source, stream, engine, storage }
// Built-ins register via ensureBuiltins() / registerBuiltins().
// Dynamic plugins: loadPluginFromUrl() in src/plugins/loader.ts
// Script library: Manager β†’ Script Library tab
//   storage-local  β†’ IndexedDB (default, offline)
//   storage-cloud  β†’ Worker /api/scripts + Pro API keys
//   storage-git    β†’ GitHub/GitLab Contents API (commit on Save)
//
// Manager tabs: Catalog (Use + capability badges) Β· Install (URL) Β· Script Library
// Settings: engine list from registry, storage picker, endpoint when needed
// Status bar: active engine id + storage backend

Legacy vanilla shell still uses src/registry.js (see LEGACY.md).

Built-in plugins

Kind id Source / role
Source binance-rest https://api.binance.com/...
Source okx-rest OKX public candles
Source bybit-rest Bybit v5 spot klines
Source coinbase-rest Coinbase Exchange candles
Source geckoterminal-ohlcv DEX pool OHLCV (GeckoTerminal)
Source mock-walk pure-synthetic random walk
Source csv-upload user-uploaded file
Dataset defillama-tvl Protocol TVL history (DefiLlama)
Stream binance-ws wss://stream.binance.com/...
Stream mock-poll synthetic poll (offline)
Stream none paused
Engine server POST {endpoint}/run
Engine pyodide in-browser Python (Pyodide)

Add a new plugin via the Plugin Manager Install tab (URL module), or register in TypeScript under src/sources|streams|engines and the unified src/plugins/registry.ts. Dynamic load:

import { loadPluginFromUrl } from './src/plugins/loader';
await loadPluginFromUrl('https://example.com/my-plugin.js');

Product highlights

Surface What it does
Topbar Load One-shot historical fetch (historyBars / venue page cap) into the chart
Data Sources panel Background multi-page backfill to a past date, validate density, fill gaps, durable IDB cache, optional Load to chart
On-Chain panel DefiLlama TVL lines, GeckoTerminal DEX pool candles, TVL spike events, CSV export, refresh jobs
Scripts panel Applied indicators/strategies (list, visibility, colors) β€” renamed from β€œIndicators”
Chart themes Ten curated high-end presets (void, classic, mono, obsidian, graphite, pacific, dusk, porcelain, parchment, …) β€” no neon high-contrast default
Price scale Auto or 0–8 decimals from symbol + bars; Pine plot.style_* parity on overlays
Run Accent color only while a run is executing (ghost when idle)
Library / Plugins / Settings Script storage (import v6 starter pack), plugin catalog (incl. component URL), engine endpoint
Workers Manager Health cards + install helpers for Flask / Worker / Pyodide / PWA / PYNE Agent
AXIS CLI packages/cli β€” install, doctor, setup, secrets, deploy, health
Desktop Optional Tauri 2 shell (bun run desktop:dev)

Docs: On-Chain data Β· Data Source Manager Β· AXIS CLI Β· UI shell

Local dev

Primary path is Vite + Solid (this is what ships on the VPS demo):

bun install && bun run dev     # Vite on :3000 (proxies /run β†’ :5002)
# production: bun run build && python3 axis_pwa_server.py   # serves dist/ on :8081
# Terminal 1 β€” backend (pyne Pro API)
# from the pynescript / pyne checkout:
make run                       # Flask on :5002

# Terminal 2 β€” AXIS PWA
bun run dev

Legacy static path (not recommended)

style.css, main.js, server.ts, and root-level index.html without Vite are the pre-Solid shell. Prefer bun run dev or dist/ from bun run build. See LEGACY.md.

For an offline-first demo: set Source = Mock Walk, Stream = Mock Poll, Engine = Client-Side (Pyodide). Disable network in DevTools β€” Run still works.

File map

axis/                         (this repo root)
  index.html                  Vite entry
  public/                     PWA icons, manifest, example plugins, vendor wheels
  src/
    app.tsx                   Solid shell: docks, panels, chart workspace
    data/
      load-symbol.ts          Topbar one-shot history β†’ chart
      data-source-manager.ts  Background backfill + validate + gap-fill jobs
      bars-cache.ts           IDB OHLCV cache for manager
      bars-gaps.ts            Series completeness / gap detection
    onchain/                  Dataset plane: DefiLlama TVL, GeckoTerminal, events, jobs
    theme/                    Chart theme catalog + 10 presets
    sources/catalog.ts        binance / okx / bybit / coinbase / gecko / mock / csv
    streams/                  Live multiplex + venue WS
    engines/                  server + pyodide
    indicators/               runAndApply + Scripts panel UI
    editor/                   CM6 Pine editor, diagnostics, profiler, pins
    chart/                    lightweight-charts host, drawings, on-chain overlays
    ui/                       Topbar, panels, On-Chain, command palette, settings
    store/                    Solid app state + persistence
    plugins/                  Unified registry contracts + loader (incl. dataset)
  worker/                     Cloudflare Worker (API / onchain proxy / DO / D1)
  packages/cli/               AXIS CLI (@hoox-sh/axis-cli) β€” setup / deploy / doctor
  docs/                       Product docs (MDX; mirrored to hoox.sh/axis/docs)
  tests/                      Bun unit + integration tests
  e2e/                        Playwright

Backend targets

  • Local Flask: existing make run on :5002. PWA talks to it directly (CORS handled by the backend). Default endpoint is http://localhost:5002.
  • VPS demo: PWA + Pro API same-origin at https://axis.hoox.sh (Cloudflare β†’ nginx TLS β†’ static axis-pwa + reverse-proxy /run//ws//health to pynescript-api on :5002). Default store endpoint is https://axis.hoox.sh.
  • Cloudflare Worker: bun run axis:deploy (or make worker-deploy). The Worker exposes /api/run, /api/stream, /api/keys, /api/onchain/* (DefiLlama + GeckoTerminal allowlisted proxy), Git OAuth device flow, etc. See worker/README.md, Worker docs, and AXIS CLI.

CORS (AXIS browser origin β†’ Pro API)

CORS is enforced by the API you call (pyne Pro API or the AXIS Worker), not by the static AXIS PWA.

Pyne Pro API

backend/app.py uses flask-cors with ALLOWED_ORIGINS (comma-separated). Defaults include https://pynescript.ai, https://app.pynescript.ai, and a localhost/127.0.0.1 any-port regex.

Origin style Safe? Notes
localhost / 127.0.0.1 (+ port) Yes Local AXIS / Vite; only your machine presents these Origins
Public demo host (http://VPS:8081) Yes if listed Needed when UI is on VPS and API is elsewhere (or same box)
* Demo-only Reflects any Origin β€” fine for a public demo, not for production secrets
0.0.0.0 Skip Not a normal browser Origin; listening on 0.0.0.0 β‰  CORS

Same-origin proxy (recommended): browser calls https://axis.hoox.sh/run β€” no CORS. Direct :5002 is still fine for demos if ALLOWED_ORIGINS includes the page origin.

# /etc/systemd/system/pynescript-api.service
Environment=ALLOWED_ORIGINS=*
# or tighter:
# Environment=ALLOWED_ORIGINS=https://axis.hoox.sh,^https?://(localhost|127\.0\.0\.1)(:\d+)?$

AXIS Worker

worker/src/index.ts pickOrigin echoes localhost / 127.0.0.1, known product hosts (*.hoox.sh, *.pynescript.ai, …), and *.pynescript-axis.pages.dev only (not open *.pages.dev); otherwise comma-separated ALLOWED_ORIGIN (first entry is fallback). See CORS docs. Smoke:

curl -sS -D- -o /dev/null -X OPTIONS https://axis.hoox.sh/run \
  -H "Origin: https://axis.hoox.sh" \
  -H "Access-Control-Request-Method: POST"
# expect Access-Control-Allow-Origin echoing the Origin

curl -sS -X POST https://axis.hoox.sh/run \
  -H "Content-Type: application/json" \
  -H "Origin: https://axis.hoox.sh" \
  -d '{"script":"//@version=6\nindicator(\"t\")\nplot(close)","data":[{"time":1,"open":1,"high":1,"low":1,"close":1,"volume":1}]}'

PWA

  • Manifest at manifest.webmanifest (void theme #0a0b10, icons 192/512).
  • Service Worker at sw.js registered on first load. Cache-first for the app shell, network-first for /api/*, fallback to a 503 JSON for offline API calls (the pyodide engine keeps the app fully usable offline).
  • Install prompt: in Chrome/Edge, look for the install icon in the URL bar.

Persistence (localStorage)

pynescript.axis.v1 holds:

Field Purpose
script Last Pine source
symbol/interval Last market selection
engine server or pyodide
source binance-rest/mock-walk/csv-upload
stream binance-ws/mock-poll/none
endpoint Backend URL
mode local or cloud
apiKey stored only in this browser
pluginsConfig per-plugin configuration

Verification

  • make run-frontend then open http://localhost:8081.
  • App loads, chart shows BTC/USDT, top bar exposes Engine / Source / Stream pickers. DevTools β†’ Application β†’ Manifest + Service Workers confirms PWA.
  • Engine = pyodide + Source = mock-walk: go offline (DevTools β†’ Network β†’ Offline). Click Run. Pine still executes.

About

πŸ“Š AXIS β€” installable charting PWA for Pine Script. Website: hoox.sh/axis Β· engine: pyne Β· stack: hoox.sh

Topics

Resources

Code of conduct

Contributing

Security policy

Stars

1 star

Watchers

0 watching

Forks

Releases

Sponsor this project

Packages

Contributors

Languages