TradingView Communication
Use this to avoid re-discovering the bridge between the OneKey app repository and the separate TradingView chart repository. Do not assume fixed local filesystem paths; locate files by symbol names with rg.
Mental Model
The app loads the chart app inside WebView/iframe and both sides exchange plain message objects.
- Chart -> app:
$private payloads with scope, origin, method, and data.
- App -> chart:
webRef.current.sendMessageViaInjectedScript(message), which lands in the chart as window.postMessage(message).
- Web/extension uses iframe
postMessage; native/desktop injects a script that calls window.postMessage(...).
- Market mode data normally comes from the OneKey app/background service. Perps/Hyperliquid candles are fetched by the chart app directly, while marks, price scale, symbol sync, and chart lines still use the app bridge.
Search Anchors
Start with rg instead of assuming local paths.
App repo anchors:
- URL builder:
useTradingViewUrl
- Market wrapper:
TradingViewV2
- Market receive handler:
useTradingViewMessageHandler
- Market kline/marks handler:
handleKLineDataRequest, fetchAccountTransactionMarks
- Market realtime push:
useAutoKLineUpdate, useTradingViewV2WebSocket
- Perps wrapper:
TradingViewPerpsV2
- Perps receive handler:
usePerpsTradingViewMessageHandler
- Perps line sender:
useChartLines, buildAllLinesForSymbol
- WebView bridge:
sendMessageViaInjectedScript, createMessageInjectedScript, InpageProviderWebView, NativeWebView, DesktopWebView
- Background services:
fetchMarketTokenKline, fetchMarketAccountTokenTransactions, subscribeOHLCV, getTradingviewMidPrice, setTradingviewDisplayPriceScale
- Base URLs:
TRADING_VIEW_URL, TRADING_VIEW_URL_TEST
Chart repo anchors:
- Entry and mode switch:
getBusinessTypeFromUrl, shouldUseFastBootstrapFromUrl
- Widget and manager setup:
TradingViewWidget, ChartManager
- Outbound bridge:
sendMessage, createDefaultPayload, requestHistoryData, getHyperliquidPriceScale, getMarksData
- Symbol sync:
setupSymbolChangeListener, publishActiveSymbol, symbolDisplayState
- Market datafeed:
OnekeyDatafeed
- Hyperliquid datafeed:
HyperliquidDatafeed, HyperliquidWebSocket
- Marks listener:
marksListener, MarksManager
- Perps lines listener:
setupPerpsLinesListener, PerpsLinesManager
- Message constants/types:
METHOD_TYPES, PERPS_TV_MESSAGE_TYPES, ITVLine
Treat the TradingView library static asset directory in the chart repo as vendor assets. Do not edit it for bridge changes.
URL Parameters
App URL generation is centralized in useTradingViewUrl.
Common params:
- Always:
timezone, locale, platform, theme, optional appVersion.
- Market:
decimal, networkId, address, symbol, type=market, storageNamespace=market.
- Market using Hyperliquid candles:
scene=market-hyperliquid, storageNamespace=market (chart layout and indicators intentionally share regular Market settings).
- Perps:
symbol, type=perps, storageNamespace=perps, enablePerpsTradingUi.
Perps freezes the initial URL symbol and sends later changes via SYMBOL_CHANGE to avoid WebView reloads.
Message Contracts
Market Kline
Chart requests history with:
{
scope: '$private',
method: 'tradingview_getKLineData',
data: {
method: 'tradingview_getHistoryData',
resolution,
from,
to,
firstDataRequest,
},
}
App handles it in useTradingViewMessageHandler -> handleKLineDataRequest() and fetches serviceMarketV2.fetchMarketTokenKline().
App replies:
{
type: 'kLineData',
payload: {
type: 'history',
kLineData,
requestData,
},
}
Realtime market updates are app-pushed with type: 'autoKLineUpdate' and payload.type: 'realtime'.
Marks
Request/response:
- Chart -> app:
method: 'tradingview_getMarks' with requestId, symbol, from, to, resolution.
- App -> chart:
type: 'MARKS_RESPONSE', payload: { marks, requestId }.
Push updates:
- App -> chart:
type: 'MARKS_UPDATE', payload: { symbol, operation, marks }.
operation is incremental, replace, or clear.
Market marks come from account token transactions. Perps marks come from Hyperliquid fills.
Hyperliquid Price Scale
Chart requests:
{
scope: '$private',
method: 'tradingview_getHyperliquidPriceScale',
data: { symbol, requestId },
}
App responds:
{
type: 'HYPERLIQUID_PRICESCALE_RESPONSE',
payload: { priceScale, minmov: 1, requestId },
}
The app calculates from current mid price with calculateDisplayPriceScale() and caches the result through serviceHyperliquid.setTradingviewDisplayPriceScale().
Perps Symbol Sync
App sends:
{
type: 'SYMBOL_CHANGE',
payload: {
symbol,
displayPair,
displayCoin,
force,
},
}
Chart handles it in setupSymbolChangeListener(). Display labels are cached by raw symbol in symbolDisplayState; do not key Hyperliquid API calls off display labels.
Perps Lines
App -> chart:
PERPS_TV_LINES_SYNC: full state { symbol, revision, lines }.
PERPS_TV_LINES_PATCH: diff { symbol, revision, add, update, remove }.
PERPS_TV_LINES_CLEAR: { symbol }.
PERPS_TV_ORDER_PRICE_UPDATE_REJECTED: rollback for failed drag amend.
Chart -> app:
tradingview_perpsReady: chart lines can be sent.
tradingview_perpsOrderCancel: user clicked order-line cancel.
tradingview_perpsOrderDraftCreate: plus/context menu placed a draft order.
tradingview_perpsOrderPriceUpdate: user dragged a limit order line.
tradingview_chartExpand: chart expand/collapse state.
The chart serializes sync/patch processing because TradingView line creation is async.
Current app default: PerpCandles sets enablePerpsTradingUi = false, so order draft/cancel/drag UI paths may exist but are not enabled in normal perps candles.
Recovery And Touch Scroll
- App sends
type: 'FORCE_RECOVER_WS' after Hyperliquid WebSocket recovery. Chart validates origin before reconnecting subscriptions.
- Chart sends
method: 'tradingview_touchScroll' with { deltaY } so app layouts can scroll around the embedded chart.
Change Checklist
When adding or changing a message:
- Update constants/types on both sides, not just one repo.
- Preserve
requestId for async request/response flows.
- Keep the payload shape stable for older app/chart builds where possible.
- For app -> chart messages, add or update a chart-side
window.message listener.
- For chart -> app messages, route through
sendMessage() and handle in the relevant app message handler.
- For perps lines, respect
revision ordering and symbol normalization.
- For Hyperliquid symbols, use the raw coin id for API/cache keys. Display labels are UI-only.
- Do not bypass
$private bridge routing, trading enablement checks, order reject rollback, or origin checks.
- Test both web iframe and native/desktop injected-script behavior when bridge mechanics change.
Verification
- App-only bridge change: run the relevant TypeScript/lint command for touched files; before commit use
yarn agent:check --profile commit.
- Chart repo change: run
npm run build or yarn build from the chart repo root; run npm run lint or yarn lint when touching lint-sensitive code.
- For local manual testing, enable "use local TradingView URL" in dev settings and run chart dev server on
localhost:5173 (10.0.2.2:5173 for Android emulator).
1---2name: 1k-tradingview-communication3description: OneKey TradingView bridge communication for WebView/iframe messages, K-line data, marks, Perps symbols/lines, order events, and websocket recovery.4---56# TradingView Communication78Use this to avoid re-discovering the bridge between the OneKey app repository and the separate TradingView chart repository. Do not assume fixed local filesystem paths; locate files by symbol names with `rg`.910## Mental Model1112The app loads the chart app inside WebView/iframe and both sides exchange plain message objects.1314- Chart -> app: `$private` payloads with `scope`, `origin`, `method`, and `data`.15- App -> chart: `webRef.current.sendMessageViaInjectedScript(message)`, which lands in the chart as `window.postMessage(message)`.16- Web/extension uses iframe `postMessage`; native/desktop injects a script that calls `window.postMessage(...)`.17- Market mode data normally comes from the OneKey app/background service. Perps/Hyperliquid candles are fetched by the chart app directly, while marks, price scale, symbol sync, and chart lines still use the app bridge.1819## Search Anchors2021Start with `rg` instead of assuming local paths.2223App repo anchors:2425- URL builder: `useTradingViewUrl`26- Market wrapper: `TradingViewV2`27- Market receive handler: `useTradingViewMessageHandler`28- Market kline/marks handler: `handleKLineDataRequest`, `fetchAccountTransactionMarks`29- Market realtime push: `useAutoKLineUpdate`, `useTradingViewV2WebSocket`30- Perps wrapper: `TradingViewPerpsV2`31- Perps receive handler: `usePerpsTradingViewMessageHandler`32- Perps line sender: `useChartLines`, `buildAllLinesForSymbol`33- WebView bridge: `sendMessageViaInjectedScript`, `createMessageInjectedScript`, `InpageProviderWebView`, `NativeWebView`, `DesktopWebView`34- Background services: `fetchMarketTokenKline`, `fetchMarketAccountTokenTransactions`, `subscribeOHLCV`, `getTradingviewMidPrice`, `setTradingviewDisplayPriceScale`35- Base URLs: `TRADING_VIEW_URL`, `TRADING_VIEW_URL_TEST`3637Chart repo anchors:3839- Entry and mode switch: `getBusinessTypeFromUrl`, `shouldUseFastBootstrapFromUrl`40- Widget and manager setup: `TradingViewWidget`, `ChartManager`41- Outbound bridge: `sendMessage`, `createDefaultPayload`, `requestHistoryData`, `getHyperliquidPriceScale`, `getMarksData`42- Symbol sync: `setupSymbolChangeListener`, `publishActiveSymbol`, `symbolDisplayState`43- Market datafeed: `OnekeyDatafeed`44- Hyperliquid datafeed: `HyperliquidDatafeed`, `HyperliquidWebSocket`45- Marks listener: `marksListener`, `MarksManager`46- Perps lines listener: `setupPerpsLinesListener`, `PerpsLinesManager`47- Message constants/types: `METHOD_TYPES`, `PERPS_TV_MESSAGE_TYPES`, `ITVLine`4849Treat the TradingView library static asset directory in the chart repo as vendor assets. Do not edit it for bridge changes.5051## URL Parameters5253App URL generation is centralized in `useTradingViewUrl`.5455Common params:5657- Always: `timezone`, `locale`, `platform`, `theme`, optional `appVersion`.58- Market: `decimal`, `networkId`, `address`, `symbol`, `type=market`, `storageNamespace=market`.59- Market using Hyperliquid candles: `scene=market-hyperliquid`, `storageNamespace=market` (chart layout and indicators intentionally share regular Market settings).60- Perps: `symbol`, `type=perps`, `storageNamespace=perps`, `enablePerpsTradingUi`.6162Perps freezes the initial URL symbol and sends later changes via `SYMBOL_CHANGE` to avoid WebView reloads.6364## Message Contracts6566### Market Kline6768Chart requests history with:6970```ts71{72 scope: '$private',73 method: 'tradingview_getKLineData',74 data: {75 method: 'tradingview_getHistoryData',76 resolution,77 from,78 to,79 firstDataRequest,80 },81}82```8384App handles it in `useTradingViewMessageHandler` -> `handleKLineDataRequest()` and fetches `serviceMarketV2.fetchMarketTokenKline()`.8586App replies:8788```ts89{90 type: 'kLineData',91 payload: {92 type: 'history',93 kLineData,94 requestData,95 },96}97```9899Realtime market updates are app-pushed with `type: 'autoKLineUpdate'` and `payload.type: 'realtime'`.100101### Marks102103Request/response:104105- Chart -> app: `method: 'tradingview_getMarks'` with `requestId`, `symbol`, `from`, `to`, `resolution`.106- App -> chart: `type: 'MARKS_RESPONSE'`, `payload: { marks, requestId }`.107108Push updates:109110- App -> chart: `type: 'MARKS_UPDATE'`, `payload: { symbol, operation, marks }`.111- `operation` is `incremental`, `replace`, or `clear`.112113Market marks come from account token transactions. Perps marks come from Hyperliquid fills.114115### Hyperliquid Price Scale116117Chart requests:118119```ts120{121 scope: '$private',122 method: 'tradingview_getHyperliquidPriceScale',123 data: { symbol, requestId },124}125```126127App responds:128129```ts130{131 type: 'HYPERLIQUID_PRICESCALE_RESPONSE',132 payload: { priceScale, minmov: 1, requestId },133}134```135136The app calculates from current mid price with `calculateDisplayPriceScale()` and caches the result through `serviceHyperliquid.setTradingviewDisplayPriceScale()`.137138### Perps Symbol Sync139140App sends:141142```ts143{144 type: 'SYMBOL_CHANGE',145 payload: {146 symbol,147 displayPair,148 displayCoin,149 force,150 },151}152```153154Chart handles it in `setupSymbolChangeListener()`. Display labels are cached by raw symbol in `symbolDisplayState`; do not key Hyperliquid API calls off display labels.155156### Perps Lines157158App -> chart:159160- `PERPS_TV_LINES_SYNC`: full state `{ symbol, revision, lines }`.161- `PERPS_TV_LINES_PATCH`: diff `{ symbol, revision, add, update, remove }`.162- `PERPS_TV_LINES_CLEAR`: `{ symbol }`.163- `PERPS_TV_ORDER_PRICE_UPDATE_REJECTED`: rollback for failed drag amend.164165Chart -> app:166167- `tradingview_perpsReady`: chart lines can be sent.168- `tradingview_perpsOrderCancel`: user clicked order-line cancel.169- `tradingview_perpsOrderDraftCreate`: plus/context menu placed a draft order.170- `tradingview_perpsOrderPriceUpdate`: user dragged a limit order line.171- `tradingview_chartExpand`: chart expand/collapse state.172173The chart serializes sync/patch processing because TradingView line creation is async.174175Current app default: `PerpCandles` sets `enablePerpsTradingUi = false`, so order draft/cancel/drag UI paths may exist but are not enabled in normal perps candles.176177### Recovery And Touch Scroll178179- App sends `type: 'FORCE_RECOVER_WS'` after Hyperliquid WebSocket recovery. Chart validates origin before reconnecting subscriptions.180- Chart sends `method: 'tradingview_touchScroll'` with `{ deltaY }` so app layouts can scroll around the embedded chart.181182## Change Checklist183184When adding or changing a message:1851861. Update constants/types on both sides, not just one repo.1872. Preserve `requestId` for async request/response flows.1883. Keep the payload shape stable for older app/chart builds where possible.1894. For app -> chart messages, add or update a chart-side `window.message` listener.1905. For chart -> app messages, route through `sendMessage()` and handle in the relevant app message handler.1916. For perps lines, respect `revision` ordering and symbol normalization.1927. For Hyperliquid symbols, use the raw coin id for API/cache keys. Display labels are UI-only.1938. Do not bypass `$private` bridge routing, trading enablement checks, order reject rollback, or origin checks.1949. Test both web iframe and native/desktop injected-script behavior when bridge mechanics change.195196## Verification197198- App-only bridge change: run the relevant TypeScript/lint command for touched files; before commit use `yarn agent:check --profile commit`.199- Chart repo change: run `npm run build` or `yarn build` from the chart repo root; run `npm run lint` or `yarn lint` when touching lint-sensitive code.200- For local manual testing, enable "use local TradingView URL" in dev settings and run chart dev server on `localhost:5173` (`10.0.2.2:5173` for Android emulator).