@cedros/trade-react 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/admin-only.cjs +1 -0
- package/dist/admin-only.cjs.map +1 -0
- package/dist/admin-only.d.ts +62 -0
- package/dist/admin-only.js +198 -0
- package/dist/admin-only.js.map +1 -0
- package/dist/apiClient-CdeF3SAW.cjs +1 -0
- package/dist/apiClient-CdeF3SAW.cjs.map +1 -0
- package/dist/apiClient-Pid_ZEt8.js +118 -0
- package/dist/apiClient-Pid_ZEt8.js.map +1 -0
- package/dist/index.cjs +6 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.ts +600 -0
- package/dist/index.js +7789 -0
- package/dist/index.js.map +1 -0
- package/dist/style.css +1 -0
- package/package.json +42 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("react/jsx-runtime"),l=require("react"),h=require("./apiClient-CdeF3SAW.cjs");function u({pluginContext:s}){const[t,d]=l.useState(null),[a,n]=l.useState(null);return l.useEffect(()=>{new h.TradeApiClient(s.serverUrl,s.getAccessToken).getHealth().then(n).catch(()=>{}),fetch(`${s.serverUrl}/admin/stats`,{headers:{Authorization:`Bearer ${s.getAccessToken()}`}}).then(o=>o.json()).then(d).catch(()=>{})},[s]),e.jsxs("div",{className:"ct-space-y-6",children:[e.jsx("h2",{className:"ct-text-xl ct-font-semibold",children:"Trade Overview"}),e.jsxs("div",{className:"ct-grid ct-grid-cols-2 lg:ct-grid-cols-4 ct-gap-4",children:[e.jsx(x,{label:"Total Quotes",value:(t==null?void 0:t.totalQuotes)??0}),e.jsx(x,{label:"Total Swaps",value:(t==null?void 0:t.totalSwaps)??0}),e.jsx(x,{label:"Cache Hit Ratio",value:`${(((t==null?void 0:t.cacheHitRatio)??0)*100).toFixed(1)}%`}),e.jsx(x,{label:"Service Status",value:(a==null?void 0:a.status)??"unknown"})]}),(t==null?void 0:t.executions)&&e.jsxs("div",{className:"ct-grid ct-grid-cols-2 ct-gap-4",children:[e.jsx(x,{label:"Executions Succeeded",value:t.executions.succeeded}),e.jsx(x,{label:"Executions Failed",value:t.executions.failed})]})]})}function x({label:s,value:t}){return e.jsxs("div",{className:"ct-bg-[hsl(var(--cedros-muted))] ct-rounded-cedros ct-p-4",children:[e.jsx("div",{className:"ct-text-xs ct-text-[hsl(var(--cedros-muted-foreground))]",children:s}),e.jsx("div",{className:"ct-text-2xl ct-font-bold ct-text-[hsl(var(--cedros-foreground))]",children:t})]})}function m({pluginContext:s}){const[t,d]=l.useState([]),a=new h.TradeApiClient(s.serverUrl,s.getAccessToken);l.useEffect(()=>{a.getProviders().then(d).catch(()=>{})},[]);const n=l.useCallback(async(c,o)=>{const r=`${s.serverUrl}/admin/providers/${c}/${o?"enable":"disable"}`;await fetch(r,{method:"POST",headers:{Authorization:`Bearer ${s.getAccessToken()}`}}),a.getProviders().then(d)},[s]);return e.jsxs("div",{className:"ct-space-y-4",children:[e.jsx("h2",{className:"ct-text-xl ct-font-semibold",children:"Swap Providers"}),e.jsx("div",{className:"ct-grid ct-gap-4",children:t.map(c=>e.jsxs("div",{className:"ct-bg-[hsl(var(--cedros-muted))] ct-rounded-cedros ct-p-4 ct-flex ct-items-center ct-justify-between",children:[e.jsxs("div",{children:[e.jsx("div",{className:"ct-font-medium ct-text-[hsl(var(--cedros-foreground))] ct-capitalize",children:c.name}),e.jsxs("div",{className:"ct-text-xs ct-text-[hsl(var(--cedros-muted-foreground))] ct-space-x-2",children:[e.jsx("span",{children:c.health.healthy?"● Healthy":"○ Unhealthy"}),c.health.latencyMs&&e.jsxs("span",{children:[c.health.latencyMs,"ms"]}),c.capabilities.gasless&&e.jsx("span",{children:"Gasless"}),c.capabilities.mevProtected&&e.jsx("span",{children:"MEV-protected"})]}),c.health.error&&e.jsx("div",{className:"ct-text-xs ct-text-red-400 ct-mt-1",children:c.health.error})]}),e.jsx("button",{onClick:()=>n(c.name,!c.enabled),className:`ct-px-3 ct-py-1.5 ct-rounded ct-text-xs ct-font-medium ${c.enabled?"ct-bg-green-500/10 ct-text-green-400":"ct-bg-red-500/10 ct-text-red-400"}`,children:c.enabled?"Enabled":"Disabled"})]},c.name))})]})}function v({pluginContext:s}){const[t,d]=l.useState([]),[a,n]=l.useState(""),c=new h.TradeApiClient(s.serverUrl,s.getAccessToken);l.useEffect(()=>{c.getTokens().then(r=>d(r.tokens)).catch(()=>{})},[]);const o=t.filter(r=>!a||r.symbol.toLowerCase().includes(a.toLowerCase())||r.name.toLowerCase().includes(a.toLowerCase()));return e.jsxs("div",{className:"ct-space-y-4",children:[e.jsxs("div",{className:"ct-flex ct-items-center ct-justify-between",children:[e.jsx("h2",{className:"ct-text-xl ct-font-semibold",children:"Token Registry"}),e.jsxs("span",{className:"ct-text-sm ct-text-[hsl(var(--cedros-muted-foreground))]",children:[t.length," tokens"]})]}),e.jsx("input",{type:"text",value:a,onChange:r=>n(r.target.value),placeholder:"Search tokens...",className:"ct-w-full ct-px-3 ct-py-2 ct-rounded-cedros ct-bg-[hsl(var(--cedros-muted))] ct-border ct-border-[hsl(var(--cedros-border))] ct-text-[hsl(var(--cedros-foreground))] ct-outline-none"}),e.jsxs("table",{className:"ct-w-full ct-text-sm",children:[e.jsx("thead",{children:e.jsxs("tr",{className:"ct-text-xs ct-text-[hsl(var(--cedros-muted-foreground))] ct-border-b ct-border-[hsl(var(--cedros-border))]",children:[e.jsx("th",{className:"ct-text-left ct-py-2",children:"Token"}),e.jsx("th",{className:"ct-text-left ct-py-2",children:"Mint"}),e.jsx("th",{className:"ct-text-left ct-py-2",children:"Decimals"}),e.jsx("th",{className:"ct-text-left ct-py-2",children:"Categories"})]})}),e.jsx("tbody",{children:o.map(r=>e.jsxs("tr",{className:"ct-border-b ct-border-[hsl(var(--cedros-border))]",children:[e.jsxs("td",{className:"ct-py-2 ct-flex ct-items-center ct-gap-2",children:[r.logoUrl&&e.jsx("img",{src:r.logoUrl,className:"ct-w-5 ct-h-5 ct-rounded-full",alt:""}),e.jsx("span",{className:"ct-font-medium",children:r.symbol}),e.jsx("span",{className:"ct-text-xs ct-text-[hsl(var(--cedros-muted-foreground))]",children:r.name})]}),e.jsxs("td",{className:"ct-py-2 ct-font-mono ct-text-xs",children:[r.mint.slice(0,8),"..."]}),e.jsx("td",{className:"ct-py-2",children:r.decimals}),e.jsx("td",{className:"ct-py-2 ct-space-x-1",children:r.categories.map(i=>e.jsx("span",{className:"ct-px-2 ct-py-0.5 ct-rounded ct-text-xs ct-bg-[hsl(var(--cedros-muted))]",children:i},i))})]},r.mint))})]})]})}function g({pluginContext:s}){const[t,d]=l.useState(null),a={Authorization:`Bearer ${s.getAccessToken()}`},n=s.serverUrl,c=l.useCallback(()=>{fetch(`${n}/admin/monitor/status`,{headers:a}).then(i=>i.json()).then(d).catch(()=>{})},[n]);l.useEffect(()=>{c();const i=setInterval(c,5e3);return()=>clearInterval(i)},[c]);const o=()=>fetch(`${n}/admin/monitor/pause`,{method:"POST",headers:a}).then(c),r=()=>fetch(`${n}/admin/monitor/resume`,{method:"POST",headers:a}).then(c);return e.jsxs("div",{className:"ct-space-y-4",children:[e.jsxs("div",{className:"ct-flex ct-items-center ct-justify-between",children:[e.jsx("h2",{className:"ct-text-xl ct-font-semibold",children:"Price Monitor"}),t&&e.jsx("div",{className:"ct-flex ct-gap-2",children:t.paused?e.jsx("button",{onClick:r,className:"ct-px-3 ct-py-1.5 ct-rounded ct-text-xs ct-font-medium ct-bg-green-500/10 ct-text-green-400",children:"Resume"}):e.jsx("button",{onClick:o,className:"ct-px-3 ct-py-1.5 ct-rounded ct-text-xs ct-font-medium ct-bg-red-500/10 ct-text-red-400",children:"Pause"})})]}),t&&e.jsxs("div",{className:"ct-grid ct-grid-cols-2 lg:ct-grid-cols-4 ct-gap-4",children:[e.jsxs("div",{className:"ct-bg-[hsl(var(--cedros-muted))] ct-rounded-cedros ct-p-4",children:[e.jsx("div",{className:"ct-text-xs ct-text-[hsl(var(--cedros-muted-foreground))]",children:"Active Orders"}),e.jsx("div",{className:"ct-text-2xl ct-font-bold",children:t.activeOrders})]}),e.jsxs("div",{className:"ct-bg-[hsl(var(--cedros-muted))] ct-rounded-cedros ct-p-4",children:[e.jsx("div",{className:"ct-text-xs ct-text-[hsl(var(--cedros-muted-foreground))]",children:"Poll Interval"}),e.jsxs("div",{className:"ct-text-2xl ct-font-bold",children:[t.pollIntervalMs,"ms"]})]}),e.jsxs("div",{className:"ct-bg-[hsl(var(--cedros-muted))] ct-rounded-cedros ct-p-4",children:[e.jsx("div",{className:"ct-text-xs ct-text-[hsl(var(--cedros-muted-foreground))]",children:"Total Executions"}),e.jsx("div",{className:"ct-text-2xl ct-font-bold",children:t.totalExecutions})]}),e.jsxs("div",{className:"ct-bg-[hsl(var(--cedros-muted))] ct-rounded-cedros ct-p-4",children:[e.jsx("div",{className:"ct-text-xs ct-text-[hsl(var(--cedros-muted-foreground))]",children:"Status"}),e.jsx("div",{className:`ct-text-2xl ct-font-bold ${t.paused?"ct-text-yellow-400":"ct-text-green-400"}`,children:t.paused?"Paused":"Running"})]})]})]})}const j={id:"cedros-trade",name:"Cedros Trade",version:"0.1.0",cssNamespace:"cedros-trade-admin",groups:[{id:"trading",label:"Trading",order:1}],sections:[{id:"overview",label:"Overview",group:"trading",order:0},{id:"providers",label:"Swap Providers",group:"trading",order:1},{id:"tokens",label:"Token Registry",group:"trading",order:2},{id:"monitor",label:"Monitor",group:"trading",order:3},{id:"settings-trade",label:"Trade Settings",group:"Configuration",order:12}],components:{overview:u,providers:m,tokens:v,monitor:g,"settings-trade":u},createPluginContext:s=>{var t,d;return{serverUrl:((t=s.cedrosTrade)==null?void 0:t.serverUrl)??"",getAccessToken:((d=s.cedrosLogin)==null?void 0:d.getAccessToken)??(()=>null)}},checkPermission:(s,t)=>{var d,a;return((a=(d=t.org)==null?void 0:d.permissions)==null?void 0:a.includes(s))??!0}};exports.cedrosTradePlugin=j;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"admin-only.cjs","sources":["../src/admin/panels/OverviewPanel.tsx","../src/admin/panels/ProvidersPanel.tsx","../src/admin/panels/TokenRegistryPanel.tsx","../src/admin/panels/MonitorPanel.tsx","../src/admin/plugin.tsx"],"sourcesContent":["import React, { useEffect, useState } from 'react';\nimport type { AdminSectionProps } from '../types';\nimport { TradeApiClient } from '../../utils/apiClient';\n\nexport function OverviewPanel({ pluginContext }: AdminSectionProps) {\n const [stats, setStats] = useState<any>(null);\n const [health, setHealth] = useState<any>(null);\n\n useEffect(() => {\n const api = new TradeApiClient(pluginContext.serverUrl, pluginContext.getAccessToken);\n api.getHealth().then(setHealth).catch(() => {});\n fetch(`${pluginContext.serverUrl}/admin/stats`, {\n headers: { 'Authorization': `Bearer ${pluginContext.getAccessToken()}` },\n }).then(r => r.json()).then(setStats).catch(() => {});\n }, [pluginContext]);\n\n return (\n <div className=\"ct-space-y-6\">\n <h2 className=\"ct-text-xl ct-font-semibold\">Trade Overview</h2>\n <div className=\"ct-grid ct-grid-cols-2 lg:ct-grid-cols-4 ct-gap-4\">\n <StatCard label=\"Total Quotes\" value={stats?.totalQuotes ?? 0} />\n <StatCard label=\"Total Swaps\" value={stats?.totalSwaps ?? 0} />\n <StatCard label=\"Cache Hit Ratio\" value={`${((stats?.cacheHitRatio ?? 0) * 100).toFixed(1)}%`} />\n <StatCard label=\"Service Status\" value={health?.status ?? 'unknown'} />\n </div>\n {stats?.executions && (\n <div className=\"ct-grid ct-grid-cols-2 ct-gap-4\">\n <StatCard label=\"Executions Succeeded\" value={stats.executions.succeeded} />\n <StatCard label=\"Executions Failed\" value={stats.executions.failed} />\n </div>\n )}\n </div>\n );\n}\n\nfunction StatCard({ label, value }: { label: string; value: string | number }) {\n return (\n <div className=\"ct-bg-[hsl(var(--cedros-muted))] ct-rounded-cedros ct-p-4\">\n <div className=\"ct-text-xs ct-text-[hsl(var(--cedros-muted-foreground))]\">{label}</div>\n <div className=\"ct-text-2xl ct-font-bold ct-text-[hsl(var(--cedros-foreground))]\">{value}</div>\n </div>\n );\n}\n","import React, { useEffect, useState, useCallback } from 'react';\nimport type { AdminSectionProps } from '../types';\nimport type { ProviderInfo } from '../../types';\nimport { TradeApiClient } from '../../utils/apiClient';\n\nexport function ProvidersPanel({ pluginContext }: AdminSectionProps) {\n const [providers, setProviders] = useState<ProviderInfo[]>([]);\n const api = new TradeApiClient(pluginContext.serverUrl, pluginContext.getAccessToken);\n\n useEffect(() => {\n api.getProviders().then(setProviders).catch(() => {});\n }, []);\n\n const toggle = useCallback(async (name: string, enable: boolean) => {\n const url = `${pluginContext.serverUrl}/admin/providers/${name}/${enable ? 'enable' : 'disable'}`;\n await fetch(url, {\n method: 'POST',\n headers: { 'Authorization': `Bearer ${pluginContext.getAccessToken()}` },\n });\n api.getProviders().then(setProviders);\n }, [pluginContext]);\n\n return (\n <div className=\"ct-space-y-4\">\n <h2 className=\"ct-text-xl ct-font-semibold\">Swap Providers</h2>\n <div className=\"ct-grid ct-gap-4\">\n {providers.map(p => (\n <div key={p.name} className=\"ct-bg-[hsl(var(--cedros-muted))] ct-rounded-cedros ct-p-4 ct-flex ct-items-center ct-justify-between\">\n <div>\n <div className=\"ct-font-medium ct-text-[hsl(var(--cedros-foreground))] ct-capitalize\">{p.name}</div>\n <div className=\"ct-text-xs ct-text-[hsl(var(--cedros-muted-foreground))] ct-space-x-2\">\n <span>{p.health.healthy ? '● Healthy' : '○ Unhealthy'}</span>\n {p.health.latencyMs && <span>{p.health.latencyMs}ms</span>}\n {p.capabilities.gasless && <span>Gasless</span>}\n {p.capabilities.mevProtected && <span>MEV-protected</span>}\n </div>\n {p.health.error && <div className=\"ct-text-xs ct-text-red-400 ct-mt-1\">{p.health.error}</div>}\n </div>\n <button onClick={() => toggle(p.name, !p.enabled)}\n className={`ct-px-3 ct-py-1.5 ct-rounded ct-text-xs ct-font-medium ${\n p.enabled ? 'ct-bg-green-500/10 ct-text-green-400' : 'ct-bg-red-500/10 ct-text-red-400'\n }`}>\n {p.enabled ? 'Enabled' : 'Disabled'}\n </button>\n </div>\n ))}\n </div>\n </div>\n );\n}\n","import React, { useEffect, useState, useCallback } from 'react';\nimport type { AdminSectionProps } from '../types';\nimport type { TokenRecord } from '../../types';\nimport { TradeApiClient } from '../../utils/apiClient';\n\nexport function TokenRegistryPanel({ pluginContext }: AdminSectionProps) {\n const [tokens, setTokens] = useState<TokenRecord[]>([]);\n const [search, setSearch] = useState('');\n const api = new TradeApiClient(pluginContext.serverUrl, pluginContext.getAccessToken);\n\n useEffect(() => {\n api.getTokens().then(r => setTokens(r.tokens)).catch(() => {});\n }, []);\n\n const filtered = tokens.filter(t =>\n !search || t.symbol.toLowerCase().includes(search.toLowerCase()) || t.name.toLowerCase().includes(search.toLowerCase())\n );\n\n return (\n <div className=\"ct-space-y-4\">\n <div className=\"ct-flex ct-items-center ct-justify-between\">\n <h2 className=\"ct-text-xl ct-font-semibold\">Token Registry</h2>\n <span className=\"ct-text-sm ct-text-[hsl(var(--cedros-muted-foreground))]\">{tokens.length} tokens</span>\n </div>\n <input type=\"text\" value={search} onChange={e => setSearch(e.target.value)} placeholder=\"Search tokens...\"\n className=\"ct-w-full ct-px-3 ct-py-2 ct-rounded-cedros ct-bg-[hsl(var(--cedros-muted))] ct-border ct-border-[hsl(var(--cedros-border))] ct-text-[hsl(var(--cedros-foreground))] ct-outline-none\" />\n <table className=\"ct-w-full ct-text-sm\">\n <thead>\n <tr className=\"ct-text-xs ct-text-[hsl(var(--cedros-muted-foreground))] ct-border-b ct-border-[hsl(var(--cedros-border))]\">\n <th className=\"ct-text-left ct-py-2\">Token</th>\n <th className=\"ct-text-left ct-py-2\">Mint</th>\n <th className=\"ct-text-left ct-py-2\">Decimals</th>\n <th className=\"ct-text-left ct-py-2\">Categories</th>\n </tr>\n </thead>\n <tbody>\n {filtered.map(t => (\n <tr key={t.mint} className=\"ct-border-b ct-border-[hsl(var(--cedros-border))]\">\n <td className=\"ct-py-2 ct-flex ct-items-center ct-gap-2\">\n {t.logoUrl && <img src={t.logoUrl} className=\"ct-w-5 ct-h-5 ct-rounded-full\" alt=\"\" />}\n <span className=\"ct-font-medium\">{t.symbol}</span>\n <span className=\"ct-text-xs ct-text-[hsl(var(--cedros-muted-foreground))]\">{t.name}</span>\n </td>\n <td className=\"ct-py-2 ct-font-mono ct-text-xs\">{t.mint.slice(0, 8)}...</td>\n <td className=\"ct-py-2\">{t.decimals}</td>\n <td className=\"ct-py-2 ct-space-x-1\">\n {t.categories.map(c => (\n <span key={c} className=\"ct-px-2 ct-py-0.5 ct-rounded ct-text-xs ct-bg-[hsl(var(--cedros-muted))]\">{c}</span>\n ))}\n </td>\n </tr>\n ))}\n </tbody>\n </table>\n </div>\n );\n}\n","import React, { useEffect, useState, useCallback } from 'react';\nimport type { AdminSectionProps } from '../types';\n\nexport function MonitorPanel({ pluginContext }: AdminSectionProps) {\n const [status, setStatus] = useState<any>(null);\n const headers = { 'Authorization': `Bearer ${pluginContext.getAccessToken()}` };\n const base = pluginContext.serverUrl;\n\n const refresh = useCallback(() => {\n fetch(`${base}/admin/monitor/status`, { headers }).then(r => r.json()).then(setStatus).catch(() => {});\n }, [base]);\n\n useEffect(() => { refresh(); const i = setInterval(refresh, 5000); return () => clearInterval(i); }, [refresh]);\n\n const pause = () => fetch(`${base}/admin/monitor/pause`, { method: 'POST', headers }).then(refresh);\n const resume = () => fetch(`${base}/admin/monitor/resume`, { method: 'POST', headers }).then(refresh);\n\n return (\n <div className=\"ct-space-y-4\">\n <div className=\"ct-flex ct-items-center ct-justify-between\">\n <h2 className=\"ct-text-xl ct-font-semibold\">Price Monitor</h2>\n {status && (\n <div className=\"ct-flex ct-gap-2\">\n {status.paused ? (\n <button onClick={resume} className=\"ct-px-3 ct-py-1.5 ct-rounded ct-text-xs ct-font-medium ct-bg-green-500/10 ct-text-green-400\">Resume</button>\n ) : (\n <button onClick={pause} className=\"ct-px-3 ct-py-1.5 ct-rounded ct-text-xs ct-font-medium ct-bg-red-500/10 ct-text-red-400\">Pause</button>\n )}\n </div>\n )}\n </div>\n {status && (\n <div className=\"ct-grid ct-grid-cols-2 lg:ct-grid-cols-4 ct-gap-4\">\n <div className=\"ct-bg-[hsl(var(--cedros-muted))] ct-rounded-cedros ct-p-4\">\n <div className=\"ct-text-xs ct-text-[hsl(var(--cedros-muted-foreground))]\">Active Orders</div>\n <div className=\"ct-text-2xl ct-font-bold\">{status.activeOrders}</div>\n </div>\n <div className=\"ct-bg-[hsl(var(--cedros-muted))] ct-rounded-cedros ct-p-4\">\n <div className=\"ct-text-xs ct-text-[hsl(var(--cedros-muted-foreground))]\">Poll Interval</div>\n <div className=\"ct-text-2xl ct-font-bold\">{status.pollIntervalMs}ms</div>\n </div>\n <div className=\"ct-bg-[hsl(var(--cedros-muted))] ct-rounded-cedros ct-p-4\">\n <div className=\"ct-text-xs ct-text-[hsl(var(--cedros-muted-foreground))]\">Total Executions</div>\n <div className=\"ct-text-2xl ct-font-bold\">{status.totalExecutions}</div>\n </div>\n <div className=\"ct-bg-[hsl(var(--cedros-muted))] ct-rounded-cedros ct-p-4\">\n <div className=\"ct-text-xs ct-text-[hsl(var(--cedros-muted-foreground))]\">Status</div>\n <div className={`ct-text-2xl ct-font-bold ${status.paused ? 'ct-text-yellow-400' : 'ct-text-green-400'}`}>\n {status.paused ? 'Paused' : 'Running'}\n </div>\n </div>\n </div>\n )}\n </div>\n );\n}\n","import type { AdminPlugin, HostContext, PluginContext } from './types';\nimport { OverviewPanel } from './panels/OverviewPanel';\nimport { ProvidersPanel } from './panels/ProvidersPanel';\nimport { TokenRegistryPanel } from './panels/TokenRegistryPanel';\nimport { MonitorPanel } from './panels/MonitorPanel';\n\nexport const cedrosTradePlugin: AdminPlugin = {\n id: 'cedros-trade',\n name: 'Cedros Trade',\n version: '0.1.0',\n cssNamespace: 'cedros-trade-admin',\n\n groups: [\n { id: 'trading', label: 'Trading', order: 1 },\n ],\n\n sections: [\n { id: 'overview', label: 'Overview', group: 'trading', order: 0 },\n { id: 'providers', label: 'Swap Providers', group: 'trading', order: 1 },\n { id: 'tokens', label: 'Token Registry', group: 'trading', order: 2 },\n { id: 'monitor', label: 'Monitor', group: 'trading', order: 3 },\n { id: 'settings-trade', label: 'Trade Settings', group: 'Configuration', order: 12 },\n ],\n\n components: {\n 'overview': OverviewPanel,\n 'providers': ProvidersPanel,\n 'tokens': TokenRegistryPanel,\n 'monitor': MonitorPanel,\n 'settings-trade': OverviewPanel, // Reuses overview for settings (can be expanded)\n },\n\n createPluginContext: (hostContext: HostContext): PluginContext => ({\n serverUrl: (hostContext.cedrosTrade as any)?.serverUrl ?? '',\n getAccessToken: hostContext.cedrosLogin?.getAccessToken ?? (() => null),\n }),\n\n checkPermission: (permission: string, hostContext: HostContext): boolean => {\n return hostContext.org?.permissions?.includes(permission) ?? true;\n },\n};\n"],"names":["OverviewPanel","pluginContext","stats","setStats","useState","health","setHealth","useEffect","TradeApiClient","r","jsxs","jsx","StatCard","label","value","ProvidersPanel","providers","setProviders","api","toggle","useCallback","name","enable","url","p","TokenRegistryPanel","tokens","setTokens","search","setSearch","filtered","t","e","c","MonitorPanel","status","setStatus","headers","base","refresh","pause","resume","cedrosTradePlugin","hostContext","_a","_b","permission"],"mappings":"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"}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import { ComponentType } from 'react';
|
|
2
|
+
|
|
3
|
+
declare interface AdminGroupConfig {
|
|
4
|
+
id: string;
|
|
5
|
+
label: string;
|
|
6
|
+
order: number;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
/** Matches the AdminPlugin interface from @cedros/login-react/admin-only */
|
|
10
|
+
export declare interface AdminPlugin {
|
|
11
|
+
id: string;
|
|
12
|
+
name: string;
|
|
13
|
+
version: string;
|
|
14
|
+
cssNamespace: string;
|
|
15
|
+
groups?: AdminGroupConfig[];
|
|
16
|
+
sections: AdminSectionConfig[];
|
|
17
|
+
components: Record<string, ComponentType<AdminSectionProps>>;
|
|
18
|
+
createPluginContext: (hostContext: HostContext) => PluginContext;
|
|
19
|
+
checkPermission: (permission: string, hostContext: HostContext) => boolean;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
declare interface AdminSectionConfig {
|
|
23
|
+
id: string;
|
|
24
|
+
label: string;
|
|
25
|
+
group: string;
|
|
26
|
+
order: number;
|
|
27
|
+
requiredPermission?: string;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export declare interface AdminSectionProps {
|
|
31
|
+
pluginContext: PluginContext;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export declare const cedrosTradePlugin: AdminPlugin;
|
|
35
|
+
|
|
36
|
+
export declare interface HostContext {
|
|
37
|
+
cedrosLogin?: {
|
|
38
|
+
user: {
|
|
39
|
+
id: string;
|
|
40
|
+
email?: string;
|
|
41
|
+
name?: string;
|
|
42
|
+
} | null;
|
|
43
|
+
getAccessToken: () => string | null;
|
|
44
|
+
serverUrl: string;
|
|
45
|
+
};
|
|
46
|
+
cedrosTrade?: {
|
|
47
|
+
serverUrl: string;
|
|
48
|
+
};
|
|
49
|
+
org?: {
|
|
50
|
+
orgId: string;
|
|
51
|
+
role: string;
|
|
52
|
+
permissions: string[];
|
|
53
|
+
};
|
|
54
|
+
[key: string]: unknown;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
export declare interface PluginContext {
|
|
58
|
+
serverUrl: string;
|
|
59
|
+
getAccessToken: () => string | null;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
export { }
|
|
@@ -0,0 +1,198 @@
|
|
|
1
|
+
import { jsxs as c, jsx as e } from "react/jsx-runtime";
|
|
2
|
+
import { useState as m, useEffect as u, useCallback as g } from "react";
|
|
3
|
+
import { T as v } from "./apiClient-Pid_ZEt8.js";
|
|
4
|
+
function x({ pluginContext: r }) {
|
|
5
|
+
const [t, l] = m(null), [d, n] = m(null);
|
|
6
|
+
return u(() => {
|
|
7
|
+
new v(r.serverUrl, r.getAccessToken).getHealth().then(n).catch(() => {
|
|
8
|
+
}), fetch(`${r.serverUrl}/admin/stats`, {
|
|
9
|
+
headers: { Authorization: `Bearer ${r.getAccessToken()}` }
|
|
10
|
+
}).then((o) => o.json()).then(l).catch(() => {
|
|
11
|
+
});
|
|
12
|
+
}, [r]), /* @__PURE__ */ c("div", { className: "ct-space-y-6", children: [
|
|
13
|
+
/* @__PURE__ */ e("h2", { className: "ct-text-xl ct-font-semibold", children: "Trade Overview" }),
|
|
14
|
+
/* @__PURE__ */ c("div", { className: "ct-grid ct-grid-cols-2 lg:ct-grid-cols-4 ct-gap-4", children: [
|
|
15
|
+
/* @__PURE__ */ e(h, { label: "Total Quotes", value: (t == null ? void 0 : t.totalQuotes) ?? 0 }),
|
|
16
|
+
/* @__PURE__ */ e(h, { label: "Total Swaps", value: (t == null ? void 0 : t.totalSwaps) ?? 0 }),
|
|
17
|
+
/* @__PURE__ */ e(h, { label: "Cache Hit Ratio", value: `${(((t == null ? void 0 : t.cacheHitRatio) ?? 0) * 100).toFixed(1)}%` }),
|
|
18
|
+
/* @__PURE__ */ e(h, { label: "Service Status", value: (d == null ? void 0 : d.status) ?? "unknown" })
|
|
19
|
+
] }),
|
|
20
|
+
(t == null ? void 0 : t.executions) && /* @__PURE__ */ c("div", { className: "ct-grid ct-grid-cols-2 ct-gap-4", children: [
|
|
21
|
+
/* @__PURE__ */ e(h, { label: "Executions Succeeded", value: t.executions.succeeded }),
|
|
22
|
+
/* @__PURE__ */ e(h, { label: "Executions Failed", value: t.executions.failed })
|
|
23
|
+
] })
|
|
24
|
+
] });
|
|
25
|
+
}
|
|
26
|
+
function h({ label: r, value: t }) {
|
|
27
|
+
return /* @__PURE__ */ c("div", { className: "ct-bg-[hsl(var(--cedros-muted))] ct-rounded-cedros ct-p-4", children: [
|
|
28
|
+
/* @__PURE__ */ e("div", { className: "ct-text-xs ct-text-[hsl(var(--cedros-muted-foreground))]", children: r }),
|
|
29
|
+
/* @__PURE__ */ e("div", { className: "ct-text-2xl ct-font-bold ct-text-[hsl(var(--cedros-foreground))]", children: t })
|
|
30
|
+
] });
|
|
31
|
+
}
|
|
32
|
+
function b({ pluginContext: r }) {
|
|
33
|
+
const [t, l] = m([]), d = new v(r.serverUrl, r.getAccessToken);
|
|
34
|
+
u(() => {
|
|
35
|
+
d.getProviders().then(l).catch(() => {
|
|
36
|
+
});
|
|
37
|
+
}, []);
|
|
38
|
+
const n = g(async (s, o) => {
|
|
39
|
+
const a = `${r.serverUrl}/admin/providers/${s}/${o ? "enable" : "disable"}`;
|
|
40
|
+
await fetch(a, {
|
|
41
|
+
method: "POST",
|
|
42
|
+
headers: { Authorization: `Bearer ${r.getAccessToken()}` }
|
|
43
|
+
}), d.getProviders().then(l);
|
|
44
|
+
}, [r]);
|
|
45
|
+
return /* @__PURE__ */ c("div", { className: "ct-space-y-4", children: [
|
|
46
|
+
/* @__PURE__ */ e("h2", { className: "ct-text-xl ct-font-semibold", children: "Swap Providers" }),
|
|
47
|
+
/* @__PURE__ */ e("div", { className: "ct-grid ct-gap-4", children: t.map((s) => /* @__PURE__ */ c("div", { className: "ct-bg-[hsl(var(--cedros-muted))] ct-rounded-cedros ct-p-4 ct-flex ct-items-center ct-justify-between", children: [
|
|
48
|
+
/* @__PURE__ */ c("div", { children: [
|
|
49
|
+
/* @__PURE__ */ e("div", { className: "ct-font-medium ct-text-[hsl(var(--cedros-foreground))] ct-capitalize", children: s.name }),
|
|
50
|
+
/* @__PURE__ */ c("div", { className: "ct-text-xs ct-text-[hsl(var(--cedros-muted-foreground))] ct-space-x-2", children: [
|
|
51
|
+
/* @__PURE__ */ e("span", { children: s.health.healthy ? "● Healthy" : "○ Unhealthy" }),
|
|
52
|
+
s.health.latencyMs && /* @__PURE__ */ c("span", { children: [
|
|
53
|
+
s.health.latencyMs,
|
|
54
|
+
"ms"
|
|
55
|
+
] }),
|
|
56
|
+
s.capabilities.gasless && /* @__PURE__ */ e("span", { children: "Gasless" }),
|
|
57
|
+
s.capabilities.mevProtected && /* @__PURE__ */ e("span", { children: "MEV-protected" })
|
|
58
|
+
] }),
|
|
59
|
+
s.health.error && /* @__PURE__ */ e("div", { className: "ct-text-xs ct-text-red-400 ct-mt-1", children: s.health.error })
|
|
60
|
+
] }),
|
|
61
|
+
/* @__PURE__ */ e(
|
|
62
|
+
"button",
|
|
63
|
+
{
|
|
64
|
+
onClick: () => n(s.name, !s.enabled),
|
|
65
|
+
className: `ct-px-3 ct-py-1.5 ct-rounded ct-text-xs ct-font-medium ${s.enabled ? "ct-bg-green-500/10 ct-text-green-400" : "ct-bg-red-500/10 ct-text-red-400"}`,
|
|
66
|
+
children: s.enabled ? "Enabled" : "Disabled"
|
|
67
|
+
}
|
|
68
|
+
)
|
|
69
|
+
] }, s.name)) })
|
|
70
|
+
] });
|
|
71
|
+
}
|
|
72
|
+
function p({ pluginContext: r }) {
|
|
73
|
+
const [t, l] = m([]), [d, n] = m(""), s = new v(r.serverUrl, r.getAccessToken);
|
|
74
|
+
u(() => {
|
|
75
|
+
s.getTokens().then((a) => l(a.tokens)).catch(() => {
|
|
76
|
+
});
|
|
77
|
+
}, []);
|
|
78
|
+
const o = t.filter(
|
|
79
|
+
(a) => !d || a.symbol.toLowerCase().includes(d.toLowerCase()) || a.name.toLowerCase().includes(d.toLowerCase())
|
|
80
|
+
);
|
|
81
|
+
return /* @__PURE__ */ c("div", { className: "ct-space-y-4", children: [
|
|
82
|
+
/* @__PURE__ */ c("div", { className: "ct-flex ct-items-center ct-justify-between", children: [
|
|
83
|
+
/* @__PURE__ */ e("h2", { className: "ct-text-xl ct-font-semibold", children: "Token Registry" }),
|
|
84
|
+
/* @__PURE__ */ c("span", { className: "ct-text-sm ct-text-[hsl(var(--cedros-muted-foreground))]", children: [
|
|
85
|
+
t.length,
|
|
86
|
+
" tokens"
|
|
87
|
+
] })
|
|
88
|
+
] }),
|
|
89
|
+
/* @__PURE__ */ e(
|
|
90
|
+
"input",
|
|
91
|
+
{
|
|
92
|
+
type: "text",
|
|
93
|
+
value: d,
|
|
94
|
+
onChange: (a) => n(a.target.value),
|
|
95
|
+
placeholder: "Search tokens...",
|
|
96
|
+
className: "ct-w-full ct-px-3 ct-py-2 ct-rounded-cedros ct-bg-[hsl(var(--cedros-muted))] ct-border ct-border-[hsl(var(--cedros-border))] ct-text-[hsl(var(--cedros-foreground))] ct-outline-none"
|
|
97
|
+
}
|
|
98
|
+
),
|
|
99
|
+
/* @__PURE__ */ c("table", { className: "ct-w-full ct-text-sm", children: [
|
|
100
|
+
/* @__PURE__ */ e("thead", { children: /* @__PURE__ */ c("tr", { className: "ct-text-xs ct-text-[hsl(var(--cedros-muted-foreground))] ct-border-b ct-border-[hsl(var(--cedros-border))]", children: [
|
|
101
|
+
/* @__PURE__ */ e("th", { className: "ct-text-left ct-py-2", children: "Token" }),
|
|
102
|
+
/* @__PURE__ */ e("th", { className: "ct-text-left ct-py-2", children: "Mint" }),
|
|
103
|
+
/* @__PURE__ */ e("th", { className: "ct-text-left ct-py-2", children: "Decimals" }),
|
|
104
|
+
/* @__PURE__ */ e("th", { className: "ct-text-left ct-py-2", children: "Categories" })
|
|
105
|
+
] }) }),
|
|
106
|
+
/* @__PURE__ */ e("tbody", { children: o.map((a) => /* @__PURE__ */ c("tr", { className: "ct-border-b ct-border-[hsl(var(--cedros-border))]", children: [
|
|
107
|
+
/* @__PURE__ */ c("td", { className: "ct-py-2 ct-flex ct-items-center ct-gap-2", children: [
|
|
108
|
+
a.logoUrl && /* @__PURE__ */ e("img", { src: a.logoUrl, className: "ct-w-5 ct-h-5 ct-rounded-full", alt: "" }),
|
|
109
|
+
/* @__PURE__ */ e("span", { className: "ct-font-medium", children: a.symbol }),
|
|
110
|
+
/* @__PURE__ */ e("span", { className: "ct-text-xs ct-text-[hsl(var(--cedros-muted-foreground))]", children: a.name })
|
|
111
|
+
] }),
|
|
112
|
+
/* @__PURE__ */ c("td", { className: "ct-py-2 ct-font-mono ct-text-xs", children: [
|
|
113
|
+
a.mint.slice(0, 8),
|
|
114
|
+
"..."
|
|
115
|
+
] }),
|
|
116
|
+
/* @__PURE__ */ e("td", { className: "ct-py-2", children: a.decimals }),
|
|
117
|
+
/* @__PURE__ */ e("td", { className: "ct-py-2 ct-space-x-1", children: a.categories.map((i) => /* @__PURE__ */ e("span", { className: "ct-px-2 ct-py-0.5 ct-rounded ct-text-xs ct-bg-[hsl(var(--cedros-muted))]", children: i }, i)) })
|
|
118
|
+
] }, a.mint)) })
|
|
119
|
+
] })
|
|
120
|
+
] });
|
|
121
|
+
}
|
|
122
|
+
function f({ pluginContext: r }) {
|
|
123
|
+
const [t, l] = m(null), d = { Authorization: `Bearer ${r.getAccessToken()}` }, n = r.serverUrl, s = g(() => {
|
|
124
|
+
fetch(`${n}/admin/monitor/status`, { headers: d }).then((i) => i.json()).then(l).catch(() => {
|
|
125
|
+
});
|
|
126
|
+
}, [n]);
|
|
127
|
+
u(() => {
|
|
128
|
+
s();
|
|
129
|
+
const i = setInterval(s, 5e3);
|
|
130
|
+
return () => clearInterval(i);
|
|
131
|
+
}, [s]);
|
|
132
|
+
const o = () => fetch(`${n}/admin/monitor/pause`, { method: "POST", headers: d }).then(s), a = () => fetch(`${n}/admin/monitor/resume`, { method: "POST", headers: d }).then(s);
|
|
133
|
+
return /* @__PURE__ */ c("div", { className: "ct-space-y-4", children: [
|
|
134
|
+
/* @__PURE__ */ c("div", { className: "ct-flex ct-items-center ct-justify-between", children: [
|
|
135
|
+
/* @__PURE__ */ e("h2", { className: "ct-text-xl ct-font-semibold", children: "Price Monitor" }),
|
|
136
|
+
t && /* @__PURE__ */ e("div", { className: "ct-flex ct-gap-2", children: t.paused ? /* @__PURE__ */ e("button", { onClick: a, className: "ct-px-3 ct-py-1.5 ct-rounded ct-text-xs ct-font-medium ct-bg-green-500/10 ct-text-green-400", children: "Resume" }) : /* @__PURE__ */ e("button", { onClick: o, className: "ct-px-3 ct-py-1.5 ct-rounded ct-text-xs ct-font-medium ct-bg-red-500/10 ct-text-red-400", children: "Pause" }) })
|
|
137
|
+
] }),
|
|
138
|
+
t && /* @__PURE__ */ c("div", { className: "ct-grid ct-grid-cols-2 lg:ct-grid-cols-4 ct-gap-4", children: [
|
|
139
|
+
/* @__PURE__ */ c("div", { className: "ct-bg-[hsl(var(--cedros-muted))] ct-rounded-cedros ct-p-4", children: [
|
|
140
|
+
/* @__PURE__ */ e("div", { className: "ct-text-xs ct-text-[hsl(var(--cedros-muted-foreground))]", children: "Active Orders" }),
|
|
141
|
+
/* @__PURE__ */ e("div", { className: "ct-text-2xl ct-font-bold", children: t.activeOrders })
|
|
142
|
+
] }),
|
|
143
|
+
/* @__PURE__ */ c("div", { className: "ct-bg-[hsl(var(--cedros-muted))] ct-rounded-cedros ct-p-4", children: [
|
|
144
|
+
/* @__PURE__ */ e("div", { className: "ct-text-xs ct-text-[hsl(var(--cedros-muted-foreground))]", children: "Poll Interval" }),
|
|
145
|
+
/* @__PURE__ */ c("div", { className: "ct-text-2xl ct-font-bold", children: [
|
|
146
|
+
t.pollIntervalMs,
|
|
147
|
+
"ms"
|
|
148
|
+
] })
|
|
149
|
+
] }),
|
|
150
|
+
/* @__PURE__ */ c("div", { className: "ct-bg-[hsl(var(--cedros-muted))] ct-rounded-cedros ct-p-4", children: [
|
|
151
|
+
/* @__PURE__ */ e("div", { className: "ct-text-xs ct-text-[hsl(var(--cedros-muted-foreground))]", children: "Total Executions" }),
|
|
152
|
+
/* @__PURE__ */ e("div", { className: "ct-text-2xl ct-font-bold", children: t.totalExecutions })
|
|
153
|
+
] }),
|
|
154
|
+
/* @__PURE__ */ c("div", { className: "ct-bg-[hsl(var(--cedros-muted))] ct-rounded-cedros ct-p-4", children: [
|
|
155
|
+
/* @__PURE__ */ e("div", { className: "ct-text-xs ct-text-[hsl(var(--cedros-muted-foreground))]", children: "Status" }),
|
|
156
|
+
/* @__PURE__ */ e("div", { className: `ct-text-2xl ct-font-bold ${t.paused ? "ct-text-yellow-400" : "ct-text-green-400"}`, children: t.paused ? "Paused" : "Running" })
|
|
157
|
+
] })
|
|
158
|
+
] })
|
|
159
|
+
] });
|
|
160
|
+
}
|
|
161
|
+
const k = {
|
|
162
|
+
id: "cedros-trade",
|
|
163
|
+
name: "Cedros Trade",
|
|
164
|
+
version: "0.1.0",
|
|
165
|
+
cssNamespace: "cedros-trade-admin",
|
|
166
|
+
groups: [
|
|
167
|
+
{ id: "trading", label: "Trading", order: 1 }
|
|
168
|
+
],
|
|
169
|
+
sections: [
|
|
170
|
+
{ id: "overview", label: "Overview", group: "trading", order: 0 },
|
|
171
|
+
{ id: "providers", label: "Swap Providers", group: "trading", order: 1 },
|
|
172
|
+
{ id: "tokens", label: "Token Registry", group: "trading", order: 2 },
|
|
173
|
+
{ id: "monitor", label: "Monitor", group: "trading", order: 3 },
|
|
174
|
+
{ id: "settings-trade", label: "Trade Settings", group: "Configuration", order: 12 }
|
|
175
|
+
],
|
|
176
|
+
components: {
|
|
177
|
+
overview: x,
|
|
178
|
+
providers: b,
|
|
179
|
+
tokens: p,
|
|
180
|
+
monitor: f,
|
|
181
|
+
"settings-trade": x
|
|
182
|
+
// Reuses overview for settings (can be expanded)
|
|
183
|
+
},
|
|
184
|
+
createPluginContext: (r) => {
|
|
185
|
+
var t, l;
|
|
186
|
+
return {
|
|
187
|
+
serverUrl: ((t = r.cedrosTrade) == null ? void 0 : t.serverUrl) ?? "",
|
|
188
|
+
getAccessToken: ((l = r.cedrosLogin) == null ? void 0 : l.getAccessToken) ?? (() => null)
|
|
189
|
+
};
|
|
190
|
+
},
|
|
191
|
+
checkPermission: (r, t) => {
|
|
192
|
+
var l, d;
|
|
193
|
+
return ((d = (l = t.org) == null ? void 0 : l.permissions) == null ? void 0 : d.includes(r)) ?? !0;
|
|
194
|
+
}
|
|
195
|
+
};
|
|
196
|
+
export {
|
|
197
|
+
k as cedrosTradePlugin
|
|
198
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"admin-only.js","sources":["../src/admin/panels/OverviewPanel.tsx","../src/admin/panels/ProvidersPanel.tsx","../src/admin/panels/TokenRegistryPanel.tsx","../src/admin/panels/MonitorPanel.tsx","../src/admin/plugin.tsx"],"sourcesContent":["import React, { useEffect, useState } from 'react';\nimport type { AdminSectionProps } from '../types';\nimport { TradeApiClient } from '../../utils/apiClient';\n\nexport function OverviewPanel({ pluginContext }: AdminSectionProps) {\n const [stats, setStats] = useState<any>(null);\n const [health, setHealth] = useState<any>(null);\n\n useEffect(() => {\n const api = new TradeApiClient(pluginContext.serverUrl, pluginContext.getAccessToken);\n api.getHealth().then(setHealth).catch(() => {});\n fetch(`${pluginContext.serverUrl}/admin/stats`, {\n headers: { 'Authorization': `Bearer ${pluginContext.getAccessToken()}` },\n }).then(r => r.json()).then(setStats).catch(() => {});\n }, [pluginContext]);\n\n return (\n <div className=\"ct-space-y-6\">\n <h2 className=\"ct-text-xl ct-font-semibold\">Trade Overview</h2>\n <div className=\"ct-grid ct-grid-cols-2 lg:ct-grid-cols-4 ct-gap-4\">\n <StatCard label=\"Total Quotes\" value={stats?.totalQuotes ?? 0} />\n <StatCard label=\"Total Swaps\" value={stats?.totalSwaps ?? 0} />\n <StatCard label=\"Cache Hit Ratio\" value={`${((stats?.cacheHitRatio ?? 0) * 100).toFixed(1)}%`} />\n <StatCard label=\"Service Status\" value={health?.status ?? 'unknown'} />\n </div>\n {stats?.executions && (\n <div className=\"ct-grid ct-grid-cols-2 ct-gap-4\">\n <StatCard label=\"Executions Succeeded\" value={stats.executions.succeeded} />\n <StatCard label=\"Executions Failed\" value={stats.executions.failed} />\n </div>\n )}\n </div>\n );\n}\n\nfunction StatCard({ label, value }: { label: string; value: string | number }) {\n return (\n <div className=\"ct-bg-[hsl(var(--cedros-muted))] ct-rounded-cedros ct-p-4\">\n <div className=\"ct-text-xs ct-text-[hsl(var(--cedros-muted-foreground))]\">{label}</div>\n <div className=\"ct-text-2xl ct-font-bold ct-text-[hsl(var(--cedros-foreground))]\">{value}</div>\n </div>\n );\n}\n","import React, { useEffect, useState, useCallback } from 'react';\nimport type { AdminSectionProps } from '../types';\nimport type { ProviderInfo } from '../../types';\nimport { TradeApiClient } from '../../utils/apiClient';\n\nexport function ProvidersPanel({ pluginContext }: AdminSectionProps) {\n const [providers, setProviders] = useState<ProviderInfo[]>([]);\n const api = new TradeApiClient(pluginContext.serverUrl, pluginContext.getAccessToken);\n\n useEffect(() => {\n api.getProviders().then(setProviders).catch(() => {});\n }, []);\n\n const toggle = useCallback(async (name: string, enable: boolean) => {\n const url = `${pluginContext.serverUrl}/admin/providers/${name}/${enable ? 'enable' : 'disable'}`;\n await fetch(url, {\n method: 'POST',\n headers: { 'Authorization': `Bearer ${pluginContext.getAccessToken()}` },\n });\n api.getProviders().then(setProviders);\n }, [pluginContext]);\n\n return (\n <div className=\"ct-space-y-4\">\n <h2 className=\"ct-text-xl ct-font-semibold\">Swap Providers</h2>\n <div className=\"ct-grid ct-gap-4\">\n {providers.map(p => (\n <div key={p.name} className=\"ct-bg-[hsl(var(--cedros-muted))] ct-rounded-cedros ct-p-4 ct-flex ct-items-center ct-justify-between\">\n <div>\n <div className=\"ct-font-medium ct-text-[hsl(var(--cedros-foreground))] ct-capitalize\">{p.name}</div>\n <div className=\"ct-text-xs ct-text-[hsl(var(--cedros-muted-foreground))] ct-space-x-2\">\n <span>{p.health.healthy ? '● Healthy' : '○ Unhealthy'}</span>\n {p.health.latencyMs && <span>{p.health.latencyMs}ms</span>}\n {p.capabilities.gasless && <span>Gasless</span>}\n {p.capabilities.mevProtected && <span>MEV-protected</span>}\n </div>\n {p.health.error && <div className=\"ct-text-xs ct-text-red-400 ct-mt-1\">{p.health.error}</div>}\n </div>\n <button onClick={() => toggle(p.name, !p.enabled)}\n className={`ct-px-3 ct-py-1.5 ct-rounded ct-text-xs ct-font-medium ${\n p.enabled ? 'ct-bg-green-500/10 ct-text-green-400' : 'ct-bg-red-500/10 ct-text-red-400'\n }`}>\n {p.enabled ? 'Enabled' : 'Disabled'}\n </button>\n </div>\n ))}\n </div>\n </div>\n );\n}\n","import React, { useEffect, useState, useCallback } from 'react';\nimport type { AdminSectionProps } from '../types';\nimport type { TokenRecord } from '../../types';\nimport { TradeApiClient } from '../../utils/apiClient';\n\nexport function TokenRegistryPanel({ pluginContext }: AdminSectionProps) {\n const [tokens, setTokens] = useState<TokenRecord[]>([]);\n const [search, setSearch] = useState('');\n const api = new TradeApiClient(pluginContext.serverUrl, pluginContext.getAccessToken);\n\n useEffect(() => {\n api.getTokens().then(r => setTokens(r.tokens)).catch(() => {});\n }, []);\n\n const filtered = tokens.filter(t =>\n !search || t.symbol.toLowerCase().includes(search.toLowerCase()) || t.name.toLowerCase().includes(search.toLowerCase())\n );\n\n return (\n <div className=\"ct-space-y-4\">\n <div className=\"ct-flex ct-items-center ct-justify-between\">\n <h2 className=\"ct-text-xl ct-font-semibold\">Token Registry</h2>\n <span className=\"ct-text-sm ct-text-[hsl(var(--cedros-muted-foreground))]\">{tokens.length} tokens</span>\n </div>\n <input type=\"text\" value={search} onChange={e => setSearch(e.target.value)} placeholder=\"Search tokens...\"\n className=\"ct-w-full ct-px-3 ct-py-2 ct-rounded-cedros ct-bg-[hsl(var(--cedros-muted))] ct-border ct-border-[hsl(var(--cedros-border))] ct-text-[hsl(var(--cedros-foreground))] ct-outline-none\" />\n <table className=\"ct-w-full ct-text-sm\">\n <thead>\n <tr className=\"ct-text-xs ct-text-[hsl(var(--cedros-muted-foreground))] ct-border-b ct-border-[hsl(var(--cedros-border))]\">\n <th className=\"ct-text-left ct-py-2\">Token</th>\n <th className=\"ct-text-left ct-py-2\">Mint</th>\n <th className=\"ct-text-left ct-py-2\">Decimals</th>\n <th className=\"ct-text-left ct-py-2\">Categories</th>\n </tr>\n </thead>\n <tbody>\n {filtered.map(t => (\n <tr key={t.mint} className=\"ct-border-b ct-border-[hsl(var(--cedros-border))]\">\n <td className=\"ct-py-2 ct-flex ct-items-center ct-gap-2\">\n {t.logoUrl && <img src={t.logoUrl} className=\"ct-w-5 ct-h-5 ct-rounded-full\" alt=\"\" />}\n <span className=\"ct-font-medium\">{t.symbol}</span>\n <span className=\"ct-text-xs ct-text-[hsl(var(--cedros-muted-foreground))]\">{t.name}</span>\n </td>\n <td className=\"ct-py-2 ct-font-mono ct-text-xs\">{t.mint.slice(0, 8)}...</td>\n <td className=\"ct-py-2\">{t.decimals}</td>\n <td className=\"ct-py-2 ct-space-x-1\">\n {t.categories.map(c => (\n <span key={c} className=\"ct-px-2 ct-py-0.5 ct-rounded ct-text-xs ct-bg-[hsl(var(--cedros-muted))]\">{c}</span>\n ))}\n </td>\n </tr>\n ))}\n </tbody>\n </table>\n </div>\n );\n}\n","import React, { useEffect, useState, useCallback } from 'react';\nimport type { AdminSectionProps } from '../types';\n\nexport function MonitorPanel({ pluginContext }: AdminSectionProps) {\n const [status, setStatus] = useState<any>(null);\n const headers = { 'Authorization': `Bearer ${pluginContext.getAccessToken()}` };\n const base = pluginContext.serverUrl;\n\n const refresh = useCallback(() => {\n fetch(`${base}/admin/monitor/status`, { headers }).then(r => r.json()).then(setStatus).catch(() => {});\n }, [base]);\n\n useEffect(() => { refresh(); const i = setInterval(refresh, 5000); return () => clearInterval(i); }, [refresh]);\n\n const pause = () => fetch(`${base}/admin/monitor/pause`, { method: 'POST', headers }).then(refresh);\n const resume = () => fetch(`${base}/admin/monitor/resume`, { method: 'POST', headers }).then(refresh);\n\n return (\n <div className=\"ct-space-y-4\">\n <div className=\"ct-flex ct-items-center ct-justify-between\">\n <h2 className=\"ct-text-xl ct-font-semibold\">Price Monitor</h2>\n {status && (\n <div className=\"ct-flex ct-gap-2\">\n {status.paused ? (\n <button onClick={resume} className=\"ct-px-3 ct-py-1.5 ct-rounded ct-text-xs ct-font-medium ct-bg-green-500/10 ct-text-green-400\">Resume</button>\n ) : (\n <button onClick={pause} className=\"ct-px-3 ct-py-1.5 ct-rounded ct-text-xs ct-font-medium ct-bg-red-500/10 ct-text-red-400\">Pause</button>\n )}\n </div>\n )}\n </div>\n {status && (\n <div className=\"ct-grid ct-grid-cols-2 lg:ct-grid-cols-4 ct-gap-4\">\n <div className=\"ct-bg-[hsl(var(--cedros-muted))] ct-rounded-cedros ct-p-4\">\n <div className=\"ct-text-xs ct-text-[hsl(var(--cedros-muted-foreground))]\">Active Orders</div>\n <div className=\"ct-text-2xl ct-font-bold\">{status.activeOrders}</div>\n </div>\n <div className=\"ct-bg-[hsl(var(--cedros-muted))] ct-rounded-cedros ct-p-4\">\n <div className=\"ct-text-xs ct-text-[hsl(var(--cedros-muted-foreground))]\">Poll Interval</div>\n <div className=\"ct-text-2xl ct-font-bold\">{status.pollIntervalMs}ms</div>\n </div>\n <div className=\"ct-bg-[hsl(var(--cedros-muted))] ct-rounded-cedros ct-p-4\">\n <div className=\"ct-text-xs ct-text-[hsl(var(--cedros-muted-foreground))]\">Total Executions</div>\n <div className=\"ct-text-2xl ct-font-bold\">{status.totalExecutions}</div>\n </div>\n <div className=\"ct-bg-[hsl(var(--cedros-muted))] ct-rounded-cedros ct-p-4\">\n <div className=\"ct-text-xs ct-text-[hsl(var(--cedros-muted-foreground))]\">Status</div>\n <div className={`ct-text-2xl ct-font-bold ${status.paused ? 'ct-text-yellow-400' : 'ct-text-green-400'}`}>\n {status.paused ? 'Paused' : 'Running'}\n </div>\n </div>\n </div>\n )}\n </div>\n );\n}\n","import type { AdminPlugin, HostContext, PluginContext } from './types';\nimport { OverviewPanel } from './panels/OverviewPanel';\nimport { ProvidersPanel } from './panels/ProvidersPanel';\nimport { TokenRegistryPanel } from './panels/TokenRegistryPanel';\nimport { MonitorPanel } from './panels/MonitorPanel';\n\nexport const cedrosTradePlugin: AdminPlugin = {\n id: 'cedros-trade',\n name: 'Cedros Trade',\n version: '0.1.0',\n cssNamespace: 'cedros-trade-admin',\n\n groups: [\n { id: 'trading', label: 'Trading', order: 1 },\n ],\n\n sections: [\n { id: 'overview', label: 'Overview', group: 'trading', order: 0 },\n { id: 'providers', label: 'Swap Providers', group: 'trading', order: 1 },\n { id: 'tokens', label: 'Token Registry', group: 'trading', order: 2 },\n { id: 'monitor', label: 'Monitor', group: 'trading', order: 3 },\n { id: 'settings-trade', label: 'Trade Settings', group: 'Configuration', order: 12 },\n ],\n\n components: {\n 'overview': OverviewPanel,\n 'providers': ProvidersPanel,\n 'tokens': TokenRegistryPanel,\n 'monitor': MonitorPanel,\n 'settings-trade': OverviewPanel, // Reuses overview for settings (can be expanded)\n },\n\n createPluginContext: (hostContext: HostContext): PluginContext => ({\n serverUrl: (hostContext.cedrosTrade as any)?.serverUrl ?? '',\n getAccessToken: hostContext.cedrosLogin?.getAccessToken ?? (() => null),\n }),\n\n checkPermission: (permission: string, hostContext: HostContext): boolean => {\n return hostContext.org?.permissions?.includes(permission) ?? true;\n },\n};\n"],"names":["OverviewPanel","pluginContext","stats","setStats","useState","health","setHealth","useEffect","TradeApiClient","r","jsxs","jsx","StatCard","label","value","ProvidersPanel","providers","setProviders","api","toggle","useCallback","name","enable","url","p","TokenRegistryPanel","tokens","setTokens","search","setSearch","filtered","t","e","c","MonitorPanel","status","setStatus","headers","base","refresh","pause","resume","cedrosTradePlugin","hostContext","_a","_b","permission"],"mappings":";;;AAIO,SAASA,EAAc,EAAE,eAAAC,KAAoC;AAClE,QAAM,CAACC,GAAOC,CAAQ,IAAIC,EAAc,IAAI,GACtC,CAACC,GAAQC,CAAS,IAAIF,EAAc,IAAI;AAE9C,SAAAG,EAAU,MAAM;AAEd,IADY,IAAIC,EAAeP,EAAc,WAAWA,EAAc,cAAc,EAChF,YAAY,KAAKK,CAAS,EAAE,MAAM,MAAM;AAAA,IAAC,CAAC,GAC9C,MAAM,GAAGL,EAAc,SAAS,gBAAgB;AAAA,MAC9C,SAAS,EAAE,eAAiB,UAAUA,EAAc,eAAA,CAAgB,GAAA;AAAA,IAAG,CACxE,EAAE,KAAK,CAAAQ,MAAKA,EAAE,MAAM,EAAE,KAAKN,CAAQ,EAAE,MAAM,MAAM;AAAA,IAAC,CAAC;AAAA,EACtD,GAAG,CAACF,CAAa,CAAC,GAGhB,gBAAAS,EAAC,OAAA,EAAI,WAAU,gBACb,UAAA;AAAA,IAAA,gBAAAC,EAAC,MAAA,EAAG,WAAU,+BAA8B,UAAA,kBAAc;AAAA,IAC1D,gBAAAD,EAAC,OAAA,EAAI,WAAU,qDACb,UAAA;AAAA,MAAA,gBAAAC,EAACC,KAAS,OAAM,gBAAe,QAAOV,KAAA,gBAAAA,EAAO,gBAAe,GAAG;AAAA,wBAC9DU,GAAA,EAAS,OAAM,eAAc,QAAOV,KAAA,gBAAAA,EAAO,eAAc,GAAG;AAAA,MAC7D,gBAAAS,EAACC,GAAA,EAAS,OAAM,mBAAkB,OAAO,MAAKV,KAAA,gBAAAA,EAAO,kBAAiB,KAAK,KAAK,QAAQ,CAAC,CAAC,KAAK;AAAA,wBAC9FU,GAAA,EAAS,OAAM,kBAAiB,QAAOP,KAAA,gBAAAA,EAAQ,WAAU,UAAA,CAAW;AAAA,IAAA,GACvE;AAAA,KACCH,KAAA,gBAAAA,EAAO,eACN,gBAAAQ,EAAC,OAAA,EAAI,WAAU,mCACb,UAAA;AAAA,MAAA,gBAAAC,EAACC,KAAS,OAAM,wBAAuB,OAAOV,EAAM,WAAW,WAAW;AAAA,wBACzEU,GAAA,EAAS,OAAM,qBAAoB,OAAOV,EAAM,WAAW,OAAA,CAAQ;AAAA,IAAA,EAAA,CACtE;AAAA,EAAA,GAEJ;AAEJ;AAEA,SAASU,EAAS,EAAE,OAAAC,GAAO,OAAAC,KAAoD;AAC7E,SACE,gBAAAJ,EAAC,OAAA,EAAI,WAAU,6DACb,UAAA;AAAA,IAAA,gBAAAC,EAAC,OAAA,EAAI,WAAU,4DAA4D,UAAAE,GAAM;AAAA,IACjF,gBAAAF,EAAC,OAAA,EAAI,WAAU,oEAAoE,UAAAG,EAAA,CAAM;AAAA,EAAA,GAC3F;AAEJ;ACrCO,SAASC,EAAe,EAAE,eAAAd,KAAoC;AACnE,QAAM,CAACe,GAAWC,CAAY,IAAIb,EAAyB,CAAA,CAAE,GACvDc,IAAM,IAAIV,EAAeP,EAAc,WAAWA,EAAc,cAAc;AAEpF,EAAAM,EAAU,MAAM;AACd,IAAAW,EAAI,eAAe,KAAKD,CAAY,EAAE,MAAM,MAAM;AAAA,IAAC,CAAC;AAAA,EACtD,GAAG,CAAA,CAAE;AAEL,QAAME,IAASC,EAAY,OAAOC,GAAcC,MAAoB;AAClE,UAAMC,IAAM,GAAGtB,EAAc,SAAS,oBAAoBoB,CAAI,IAAIC,IAAS,WAAW,SAAS;AAC/F,UAAM,MAAMC,GAAK;AAAA,MACf,QAAQ;AAAA,MACR,SAAS,EAAE,eAAiB,UAAUtB,EAAc,eAAA,CAAgB,GAAA;AAAA,IAAG,CACxE,GACDiB,EAAI,aAAA,EAAe,KAAKD,CAAY;AAAA,EACtC,GAAG,CAAChB,CAAa,CAAC;AAElB,SACE,gBAAAS,EAAC,OAAA,EAAI,WAAU,gBACb,UAAA;AAAA,IAAA,gBAAAC,EAAC,MAAA,EAAG,WAAU,+BAA8B,UAAA,kBAAc;AAAA,IAC1D,gBAAAA,EAAC,OAAA,EAAI,WAAU,oBACZ,UAAAK,EAAU,IAAI,CAAAQ,MACb,gBAAAd,EAAC,OAAA,EAAiB,WAAU,wGAC1B,UAAA;AAAA,MAAA,gBAAAA,EAAC,OAAA,EACC,UAAA;AAAA,QAAA,gBAAAC,EAAC,OAAA,EAAI,WAAU,wEAAwE,UAAAa,EAAE,MAAK;AAAA,QAC9F,gBAAAd,EAAC,OAAA,EAAI,WAAU,yEACb,UAAA;AAAA,UAAA,gBAAAC,EAAC,QAAA,EAAM,UAAAa,EAAE,OAAO,UAAU,cAAc,eAAc;AAAA,UACrDA,EAAE,OAAO,aAAa,gBAAAd,EAAC,QAAA,EAAM,UAAA;AAAA,YAAAc,EAAE,OAAO;AAAA,YAAU;AAAA,UAAA,GAAE;AAAA,UAClDA,EAAE,aAAa,WAAW,gBAAAb,EAAC,UAAK,UAAA,WAAO;AAAA,UACvCa,EAAE,aAAa,gBAAgB,gBAAAb,EAAC,UAAK,UAAA,gBAAA,CAAa;AAAA,QAAA,GACrD;AAAA,QACCa,EAAE,OAAO,SAAS,gBAAAb,EAAC,SAAI,WAAU,sCAAsC,UAAAa,EAAE,OAAO,MAAA,CAAM;AAAA,MAAA,GACzF;AAAA,MACA,gBAAAb;AAAA,QAAC;AAAA,QAAA;AAAA,UAAO,SAAS,MAAMQ,EAAOK,EAAE,MAAM,CAACA,EAAE,OAAO;AAAA,UAC9C,WAAW,0DACTA,EAAE,UAAU,yCAAyC,kCACvD;AAAA,UACC,UAAAA,EAAE,UAAU,YAAY;AAAA,QAAA;AAAA,MAAA;AAAA,IAC3B,KAhBQA,EAAE,IAiBZ,CACD,EAAA,CACH;AAAA,EAAA,GACF;AAEJ;AC5CO,SAASC,EAAmB,EAAE,eAAAxB,KAAoC;AACvE,QAAM,CAACyB,GAAQC,CAAS,IAAIvB,EAAwB,CAAA,CAAE,GAChD,CAACwB,GAAQC,CAAS,IAAIzB,EAAS,EAAE,GACjCc,IAAM,IAAIV,EAAeP,EAAc,WAAWA,EAAc,cAAc;AAEpF,EAAAM,EAAU,MAAM;AACd,IAAAW,EAAI,UAAA,EAAY,KAAK,CAAAT,MAAKkB,EAAUlB,EAAE,MAAM,CAAC,EAAE,MAAM,MAAM;AAAA,IAAC,CAAC;AAAA,EAC/D,GAAG,CAAA,CAAE;AAEL,QAAMqB,IAAWJ,EAAO;AAAA,IAAO,OAC7B,CAACE,KAAUG,EAAE,OAAO,YAAA,EAAc,SAASH,EAAO,aAAa,KAAKG,EAAE,KAAK,YAAA,EAAc,SAASH,EAAO,aAAa;AAAA,EAAA;AAGxH,SACE,gBAAAlB,EAAC,OAAA,EAAI,WAAU,gBACb,UAAA;AAAA,IAAA,gBAAAA,EAAC,OAAA,EAAI,WAAU,8CACb,UAAA;AAAA,MAAA,gBAAAC,EAAC,MAAA,EAAG,WAAU,+BAA8B,UAAA,kBAAc;AAAA,MAC1D,gBAAAD,EAAC,QAAA,EAAK,WAAU,4DAA4D,UAAA;AAAA,QAAAgB,EAAO;AAAA,QAAO;AAAA,MAAA,EAAA,CAAO;AAAA,IAAA,GACnG;AAAA,IACA,gBAAAf;AAAA,MAAC;AAAA,MAAA;AAAA,QAAM,MAAK;AAAA,QAAO,OAAOiB;AAAA,QAAQ,UAAU,CAAAI,MAAKH,EAAUG,EAAE,OAAO,KAAK;AAAA,QAAG,aAAY;AAAA,QACtF,WAAU;AAAA,MAAA;AAAA,IAAA;AAAA,IACZ,gBAAAtB,EAAC,SAAA,EAAM,WAAU,wBACf,UAAA;AAAA,MAAA,gBAAAC,EAAC,SAAA,EACC,UAAA,gBAAAD,EAAC,MAAA,EAAG,WAAU,8GACZ,UAAA;AAAA,QAAA,gBAAAC,EAAC,MAAA,EAAG,WAAU,wBAAuB,UAAA,SAAK;AAAA,QAC1C,gBAAAA,EAAC,MAAA,EAAG,WAAU,wBAAuB,UAAA,QAAI;AAAA,QACzC,gBAAAA,EAAC,MAAA,EAAG,WAAU,wBAAuB,UAAA,YAAQ;AAAA,QAC7C,gBAAAA,EAAC,MAAA,EAAG,WAAU,wBAAuB,UAAA,aAAA,CAAU;AAAA,MAAA,EAAA,CACjD,EAAA,CACF;AAAA,MACA,gBAAAA,EAAC,WACE,UAAAmB,EAAS,IAAI,OACZ,gBAAApB,EAAC,MAAA,EAAgB,WAAU,qDACzB,UAAA;AAAA,QAAA,gBAAAA,EAAC,MAAA,EAAG,WAAU,4CACX,UAAA;AAAA,UAAAqB,EAAE,6BAAY,OAAA,EAAI,KAAKA,EAAE,SAAS,WAAU,iCAAgC,KAAI,GAAA,CAAG;AAAA,UACpF,gBAAApB,EAAC,QAAA,EAAK,WAAU,kBAAkB,YAAE,QAAO;AAAA,UAC3C,gBAAAA,EAAC,QAAA,EAAK,WAAU,4DAA4D,YAAE,KAAA,CAAK;AAAA,QAAA,GACrF;AAAA,QACA,gBAAAD,EAAC,MAAA,EAAG,WAAU,mCAAmC,UAAA;AAAA,UAAAqB,EAAE,KAAK,MAAM,GAAG,CAAC;AAAA,UAAE;AAAA,QAAA,GAAG;AAAA,QACvE,gBAAApB,EAAC,MAAA,EAAG,WAAU,WAAW,YAAE,UAAS;AAAA,QACpC,gBAAAA,EAAC,MAAA,EAAG,WAAU,wBACX,YAAE,WAAW,IAAI,CAAAsB,MAChB,gBAAAtB,EAAC,UAAa,WAAU,4EAA4E,UAAAsB,EAAA,GAAzFA,CAA2F,CACvG,EAAA,CACH;AAAA,MAAA,KAZOF,EAAE,IAaX,CACD,EAAA,CACH;AAAA,IAAA,EAAA,CACF;AAAA,EAAA,GACF;AAEJ;ACrDO,SAASG,EAAa,EAAE,eAAAjC,KAAoC;AACjE,QAAM,CAACkC,GAAQC,CAAS,IAAIhC,EAAc,IAAI,GACxCiC,IAAU,EAAE,eAAiB,UAAUpC,EAAc,eAAA,CAAgB,GAAA,GACrEqC,IAAOrC,EAAc,WAErBsC,IAAUnB,EAAY,MAAM;AAChC,UAAM,GAAGkB,CAAI,yBAAyB,EAAE,SAAAD,EAAA,CAAS,EAAE,KAAK,CAAA5B,MAAKA,EAAE,MAAM,EAAE,KAAK2B,CAAS,EAAE,MAAM,MAAM;AAAA,IAAC,CAAC;AAAA,EACvG,GAAG,CAACE,CAAI,CAAC;AAET,EAAA/B,EAAU,MAAM;AAAE,IAAAgC,EAAA;AAAW,UAAM,IAAI,YAAYA,GAAS,GAAI;AAAG,WAAO,MAAM,cAAc,CAAC;AAAA,EAAG,GAAG,CAACA,CAAO,CAAC;AAE9G,QAAMC,IAAQ,MAAM,MAAM,GAAGF,CAAI,wBAAwB,EAAE,QAAQ,QAAQ,SAAAD,EAAA,CAAS,EAAE,KAAKE,CAAO,GAC5FE,IAAS,MAAM,MAAM,GAAGH,CAAI,yBAAyB,EAAE,QAAQ,QAAQ,SAAAD,EAAA,CAAS,EAAE,KAAKE,CAAO;AAEpG,SACE,gBAAA7B,EAAC,OAAA,EAAI,WAAU,gBACb,UAAA;AAAA,IAAA,gBAAAA,EAAC,OAAA,EAAI,WAAU,8CACb,UAAA;AAAA,MAAA,gBAAAC,EAAC,MAAA,EAAG,WAAU,+BAA8B,UAAA,iBAAa;AAAA,MACxDwB,uBACE,OAAA,EAAI,WAAU,oBACZ,UAAAA,EAAO,SACN,gBAAAxB,EAAC,UAAA,EAAO,SAAS8B,GAAQ,WAAU,+FAA8F,UAAA,SAAA,CAAM,IAEvI,gBAAA9B,EAAC,UAAA,EAAO,SAAS6B,GAAO,WAAU,2FAA0F,UAAA,QAAA,CAAK,EAAA,CAErI;AAAA,IAAA,GAEJ;AAAA,IACCL,KACC,gBAAAzB,EAAC,OAAA,EAAI,WAAU,qDACb,UAAA;AAAA,MAAA,gBAAAA,EAAC,OAAA,EAAI,WAAU,6DACb,UAAA;AAAA,QAAA,gBAAAC,EAAC,OAAA,EAAI,WAAU,4DAA2D,UAAA,iBAAa;AAAA,QACvF,gBAAAA,EAAC,OAAA,EAAI,WAAU,4BAA4B,YAAO,aAAA,CAAa;AAAA,MAAA,GACjE;AAAA,MACA,gBAAAD,EAAC,OAAA,EAAI,WAAU,6DACb,UAAA;AAAA,QAAA,gBAAAC,EAAC,OAAA,EAAI,WAAU,4DAA2D,UAAA,iBAAa;AAAA,QACvF,gBAAAD,EAAC,OAAA,EAAI,WAAU,4BAA4B,UAAA;AAAA,UAAAyB,EAAO;AAAA,UAAe;AAAA,QAAA,EAAA,CAAE;AAAA,MAAA,GACrE;AAAA,MACA,gBAAAzB,EAAC,OAAA,EAAI,WAAU,6DACb,UAAA;AAAA,QAAA,gBAAAC,EAAC,OAAA,EAAI,WAAU,4DAA2D,UAAA,oBAAgB;AAAA,QAC1F,gBAAAA,EAAC,OAAA,EAAI,WAAU,4BAA4B,YAAO,gBAAA,CAAgB;AAAA,MAAA,GACpE;AAAA,MACA,gBAAAD,EAAC,OAAA,EAAI,WAAU,6DACb,UAAA;AAAA,QAAA,gBAAAC,EAAC,OAAA,EAAI,WAAU,4DAA2D,UAAA,UAAM;AAAA,QAChF,gBAAAA,EAAC,OAAA,EAAI,WAAW,4BAA4BwB,EAAO,SAAS,uBAAuB,mBAAmB,IACnG,UAAAA,EAAO,SAAS,WAAW,UAAA,CAC9B;AAAA,MAAA,EAAA,CACF;AAAA,IAAA,EAAA,CACF;AAAA,EAAA,GAEJ;AAEJ;ACjDO,MAAMO,IAAiC;AAAA,EAC5C,IAAI;AAAA,EACJ,MAAM;AAAA,EACN,SAAS;AAAA,EACT,cAAc;AAAA,EAEd,QAAQ;AAAA,IACN,EAAE,IAAI,WAAW,OAAO,WAAW,OAAO,EAAA;AAAA,EAAE;AAAA,EAG9C,UAAU;AAAA,IACR,EAAE,IAAI,YAAY,OAAO,YAAY,OAAO,WAAW,OAAO,EAAA;AAAA,IAC9D,EAAE,IAAI,aAAa,OAAO,kBAAkB,OAAO,WAAW,OAAO,EAAA;AAAA,IACrE,EAAE,IAAI,UAAU,OAAO,kBAAkB,OAAO,WAAW,OAAO,EAAA;AAAA,IAClE,EAAE,IAAI,WAAW,OAAO,WAAW,OAAO,WAAW,OAAO,EAAA;AAAA,IAC5D,EAAE,IAAI,kBAAkB,OAAO,kBAAkB,OAAO,iBAAiB,OAAO,GAAA;AAAA,EAAG;AAAA,EAGrF,YAAY;AAAA,IACV,UAAY1C;AAAA,IACZ,WAAae;AAAA,IACb,QAAUU;AAAA,IACV,SAAWS;AAAA,IACX,kBAAkBlC;AAAA;AAAA,EAAA;AAAA,EAGpB,qBAAqB,CAAC2C,MAAA;;AAA6C;AAAA,MACjE,aAAYC,IAAAD,EAAY,gBAAZ,gBAAAC,EAAiC,cAAa;AAAA,MAC1D,kBAAgBC,IAAAF,EAAY,gBAAZ,gBAAAE,EAAyB,oBAAmB,MAAM;AAAA,IAAA;AAAA;AAAA,EAGpE,iBAAiB,CAACC,GAAoBH,MAAsC;;AAC1E,aAAOE,KAAAD,IAAAD,EAAY,QAAZ,gBAAAC,EAAiB,gBAAjB,gBAAAC,EAA8B,SAASC,OAAe;AAAA,EAC/D;AACF;"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use strict";class p{constructor(t,e,r){this.baseUrl=t,this.tokenFn=e,this.apiKey=r}async request(t,e){var n,a,u;const r={"Content-Type":"application/json",...e==null?void 0:e.headers},o=(n=this.tokenFn)==null?void 0:n.call(this);o&&(r.Authorization=`Bearer ${o}`),this.apiKey&&(r["x-api-key"]=this.apiKey);const s=await fetch(`${this.baseUrl}${t}`,{...e,headers:r});if(!s.ok){const i=await s.json().catch(()=>({error:{message:s.statusText}}));throw new h(s.status,((a=i==null?void 0:i.error)==null?void 0:a.code)??"UNKNOWN",((u=i==null?void 0:i.error)==null?void 0:u.message)??s.statusText)}return s.json()}get(t){return this.request(t)}post(t,e){return this.request(t,{method:"POST",body:JSON.stringify(e)})}del(t,e){return this.request(t,{method:"DELETE",body:e?JSON.stringify(e):void 0})}getTokens(t){const e=t?`?category=${t}`:"";return this.get(`/tokens${e}`)}getToken(t){return this.get(`/tokens/${t}`)}getQuote(t){return this.post("/swap/quote",t)}buildSwap(t,e){return this.post("/swap/build",{quote:t,userPublicKey:e})}compareQuotes(t,e,r){return this.get(`/swap/compare?inputMint=${t}&outputMint=${e}&amount=${r}`)}executeSwap(t,e,r){return this.post("/swap/execute",{signedTransaction:t,provider:e,requestId:r})}getProviders(){return this.get("/swap/providers")}getPrice(t){return this.get(`/prices/${t}`)}getBatchPrices(t){return this.post("/prices/batch",{mints:t})}buildTransfer(t){return this.post("/transfers/build",t)}executeTransfer(t){return this.post("/transfers/execute",{signedTransaction:t,provider:"rpc"})}resolveAddress(t){return this.get(`/transfers/resolve/${t}`)}createLimitOrder(t){return this.post("/orders/limit",t)}createStopLoss(t){return this.post("/orders/stop-loss",t)}createTakeProfit(t){return this.post("/orders/take-profit",t)}createDca(t){return this.post("/orders/dca",t)}cancelOrder(t,e){return this.del(`/orders/${t}`,{maker:e})}getOpenOrders(t){return this.get(`/orders/wallet/${t}`)}getPositions(t){return this.get(`/positions/${t}`)}getPendingActions(t){return this.get(`/orders/actions/${t}`)}completeAction(t,e){return this.post(`/orders/actions/${t}/complete`,{signedTransaction:e})}dismissAction(t){return this.post(`/orders/actions/${t}/dismiss`,{})}getHealth(){return this.get("/health")}}class h extends Error{constructor(t,e,r){super(r),this.status=t,this.code=e,this.name="TradeApiError"}}exports.TradeApiClient=p;exports.TradeApiError=h;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"apiClient-CdeF3SAW.cjs","sources":["../src/utils/apiClient.ts"],"sourcesContent":["import type {\n SwapQuote, SwapTransaction, ExecuteResult, TokenRecord, PriceSnapshot,\n TransferBuildResponse, PositionsResponse, OpenOrder, DcaOrder, PendingAction, ProviderInfo,\n} from '../types';\n\nexport class TradeApiClient {\n constructor(\n private baseUrl: string,\n private tokenFn?: () => string | null,\n private apiKey?: string,\n ) {}\n\n private async request<T>(path: string, options?: RequestInit): Promise<T> {\n const headers: Record<string, string> = {\n 'Content-Type': 'application/json',\n ...(options?.headers as Record<string, string>),\n };\n const token = this.tokenFn?.();\n if (token) headers['Authorization'] = `Bearer ${token}`;\n if (this.apiKey) headers['x-api-key'] = this.apiKey;\n\n const resp = await fetch(`${this.baseUrl}${path}`, { ...options, headers });\n if (!resp.ok) {\n const body = await resp.json().catch(() => ({ error: { message: resp.statusText } }));\n throw new TradeApiError(resp.status, body?.error?.code ?? 'UNKNOWN', body?.error?.message ?? resp.statusText);\n }\n return resp.json();\n }\n\n private get<T>(path: string) { return this.request<T>(path); }\n private post<T>(path: string, body: unknown) {\n return this.request<T>(path, { method: 'POST', body: JSON.stringify(body) });\n }\n private del<T>(path: string, body?: unknown) {\n return this.request<T>(path, { method: 'DELETE', body: body ? JSON.stringify(body) : undefined });\n }\n\n // --- Tokens ---\n getTokens(category?: string) {\n const q = category ? `?category=${category}` : '';\n return this.get<{ tokens: TokenRecord[]; count: number }>(`/tokens${q}`);\n }\n getToken(mint: string) { return this.get<TokenRecord>(`/tokens/${mint}`); }\n\n // --- Swap ---\n getQuote(params: { inputMint: string; outputMint: string; amount: string; slippageBps?: number; provider?: string }) {\n return this.post<SwapQuote>('/swap/quote', params);\n }\n buildSwap(quote: SwapQuote, userPublicKey: string) {\n return this.post<SwapTransaction>('/swap/build', { quote, userPublicKey });\n }\n compareQuotes(inputMint: string, outputMint: string, amount: string) {\n return this.get<SwapQuote[]>(`/swap/compare?inputMint=${inputMint}&outputMint=${outputMint}&amount=${amount}`);\n }\n executeSwap(signedTransaction: string, provider: string, requestId?: string) {\n return this.post<ExecuteResult>('/swap/execute', { signedTransaction, provider, requestId });\n }\n getProviders() { return this.get<ProviderInfo[]>('/swap/providers'); }\n\n // --- Prices ---\n getPrice(mint: string) { return this.get<PriceSnapshot>(`/prices/${mint}`); }\n getBatchPrices(mints: string[]) { return this.post<{ prices: PriceSnapshot[] }>('/prices/batch', { mints }); }\n\n // --- Transfers ---\n buildTransfer(params: { sender: string; recipient: string; mint: string; amount: string; memo?: string }) {\n return this.post<TransferBuildResponse>('/transfers/build', params);\n }\n executeTransfer(signedTransaction: string) {\n return this.post<ExecuteResult>('/transfers/execute', { signedTransaction, provider: 'rpc' });\n }\n resolveAddress(address: string) {\n return this.get<{ input: string; resolved: string; type: string }>(`/transfers/resolve/${address}`);\n }\n\n // --- Orders ---\n createLimitOrder(params: { maker: string; inputMint: string; outputMint: string; inAmount: string; outAmount: string; expiry?: string }) {\n return this.post<{ transaction: string; orderId: string }>('/orders/limit', params);\n }\n createStopLoss(params: { maker: string; inputMint: string; outputMint: string; inAmount: string; triggerPrice: string; slippageBps?: number }) {\n return this.post<{ transaction: string; orderId: string }>('/orders/stop-loss', params);\n }\n createTakeProfit(params: { maker: string; inputMint: string; outputMint: string; inAmount: string; triggerPrice: string; slippageBps?: number }) {\n return this.post<{ transaction: string; orderId: string }>('/orders/take-profit', params);\n }\n createDca(params: { maker: string; inputMint: string; outputMint: string; totalInAmount: string; perCycleAmount: string; cycleInterval: number }) {\n return this.post<{ transaction: string; orderId: string }>('/orders/dca', params);\n }\n cancelOrder(orderId: string, maker: string) {\n return this.del<{ transaction: string }>(`/orders/${orderId}`, { maker });\n }\n getOpenOrders(wallet: string) {\n return this.get<{ limitOrders: OpenOrder[]; dcaOrders: DcaOrder[] }>(`/orders/wallet/${wallet}`);\n }\n\n // --- Positions ---\n getPositions(wallet: string) { return this.get<PositionsResponse>(`/positions/${wallet}`); }\n\n // --- Action Queue ---\n getPendingActions(wallet: string) { return this.get<PendingAction[]>(`/orders/actions/${wallet}`); }\n completeAction(actionId: string, signedTransaction: string) {\n return this.post<{ actionId: string; status: string; signature: string }>(\n `/orders/actions/${actionId}/complete`, { signedTransaction },\n );\n }\n dismissAction(actionId: string) {\n return this.post<{ actionId: string; status: string }>(`/orders/actions/${actionId}/dismiss`, {});\n }\n\n // --- Health ---\n getHealth() { return this.get<{ status: string; version: string }>('/health'); }\n}\n\nexport class TradeApiError extends Error {\n constructor(public status: number, public code: string, message: string) {\n super(message);\n this.name = 'TradeApiError';\n }\n}\n"],"names":["TradeApiClient","baseUrl","tokenFn","apiKey","path","options","headers","token","_a","resp","body","TradeApiError","_b","_c","category","q","mint","params","quote","userPublicKey","inputMint","outputMint","amount","signedTransaction","provider","requestId","mints","address","orderId","maker","wallet","actionId","status","code","message"],"mappings":"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"}
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
class p {
|
|
2
|
+
constructor(t, e, r) {
|
|
3
|
+
this.baseUrl = t, this.tokenFn = e, this.apiKey = r;
|
|
4
|
+
}
|
|
5
|
+
async request(t, e) {
|
|
6
|
+
var n, a, u;
|
|
7
|
+
const r = {
|
|
8
|
+
"Content-Type": "application/json",
|
|
9
|
+
...e == null ? void 0 : e.headers
|
|
10
|
+
}, o = (n = this.tokenFn) == null ? void 0 : n.call(this);
|
|
11
|
+
o && (r.Authorization = `Bearer ${o}`), this.apiKey && (r["x-api-key"] = this.apiKey);
|
|
12
|
+
const s = await fetch(`${this.baseUrl}${t}`, { ...e, headers: r });
|
|
13
|
+
if (!s.ok) {
|
|
14
|
+
const i = await s.json().catch(() => ({ error: { message: s.statusText } }));
|
|
15
|
+
throw new c(s.status, ((a = i == null ? void 0 : i.error) == null ? void 0 : a.code) ?? "UNKNOWN", ((u = i == null ? void 0 : i.error) == null ? void 0 : u.message) ?? s.statusText);
|
|
16
|
+
}
|
|
17
|
+
return s.json();
|
|
18
|
+
}
|
|
19
|
+
get(t) {
|
|
20
|
+
return this.request(t);
|
|
21
|
+
}
|
|
22
|
+
post(t, e) {
|
|
23
|
+
return this.request(t, { method: "POST", body: JSON.stringify(e) });
|
|
24
|
+
}
|
|
25
|
+
del(t, e) {
|
|
26
|
+
return this.request(t, { method: "DELETE", body: e ? JSON.stringify(e) : void 0 });
|
|
27
|
+
}
|
|
28
|
+
// --- Tokens ---
|
|
29
|
+
getTokens(t) {
|
|
30
|
+
const e = t ? `?category=${t}` : "";
|
|
31
|
+
return this.get(`/tokens${e}`);
|
|
32
|
+
}
|
|
33
|
+
getToken(t) {
|
|
34
|
+
return this.get(`/tokens/${t}`);
|
|
35
|
+
}
|
|
36
|
+
// --- Swap ---
|
|
37
|
+
getQuote(t) {
|
|
38
|
+
return this.post("/swap/quote", t);
|
|
39
|
+
}
|
|
40
|
+
buildSwap(t, e) {
|
|
41
|
+
return this.post("/swap/build", { quote: t, userPublicKey: e });
|
|
42
|
+
}
|
|
43
|
+
compareQuotes(t, e, r) {
|
|
44
|
+
return this.get(`/swap/compare?inputMint=${t}&outputMint=${e}&amount=${r}`);
|
|
45
|
+
}
|
|
46
|
+
executeSwap(t, e, r) {
|
|
47
|
+
return this.post("/swap/execute", { signedTransaction: t, provider: e, requestId: r });
|
|
48
|
+
}
|
|
49
|
+
getProviders() {
|
|
50
|
+
return this.get("/swap/providers");
|
|
51
|
+
}
|
|
52
|
+
// --- Prices ---
|
|
53
|
+
getPrice(t) {
|
|
54
|
+
return this.get(`/prices/${t}`);
|
|
55
|
+
}
|
|
56
|
+
getBatchPrices(t) {
|
|
57
|
+
return this.post("/prices/batch", { mints: t });
|
|
58
|
+
}
|
|
59
|
+
// --- Transfers ---
|
|
60
|
+
buildTransfer(t) {
|
|
61
|
+
return this.post("/transfers/build", t);
|
|
62
|
+
}
|
|
63
|
+
executeTransfer(t) {
|
|
64
|
+
return this.post("/transfers/execute", { signedTransaction: t, provider: "rpc" });
|
|
65
|
+
}
|
|
66
|
+
resolveAddress(t) {
|
|
67
|
+
return this.get(`/transfers/resolve/${t}`);
|
|
68
|
+
}
|
|
69
|
+
// --- Orders ---
|
|
70
|
+
createLimitOrder(t) {
|
|
71
|
+
return this.post("/orders/limit", t);
|
|
72
|
+
}
|
|
73
|
+
createStopLoss(t) {
|
|
74
|
+
return this.post("/orders/stop-loss", t);
|
|
75
|
+
}
|
|
76
|
+
createTakeProfit(t) {
|
|
77
|
+
return this.post("/orders/take-profit", t);
|
|
78
|
+
}
|
|
79
|
+
createDca(t) {
|
|
80
|
+
return this.post("/orders/dca", t);
|
|
81
|
+
}
|
|
82
|
+
cancelOrder(t, e) {
|
|
83
|
+
return this.del(`/orders/${t}`, { maker: e });
|
|
84
|
+
}
|
|
85
|
+
getOpenOrders(t) {
|
|
86
|
+
return this.get(`/orders/wallet/${t}`);
|
|
87
|
+
}
|
|
88
|
+
// --- Positions ---
|
|
89
|
+
getPositions(t) {
|
|
90
|
+
return this.get(`/positions/${t}`);
|
|
91
|
+
}
|
|
92
|
+
// --- Action Queue ---
|
|
93
|
+
getPendingActions(t) {
|
|
94
|
+
return this.get(`/orders/actions/${t}`);
|
|
95
|
+
}
|
|
96
|
+
completeAction(t, e) {
|
|
97
|
+
return this.post(
|
|
98
|
+
`/orders/actions/${t}/complete`,
|
|
99
|
+
{ signedTransaction: e }
|
|
100
|
+
);
|
|
101
|
+
}
|
|
102
|
+
dismissAction(t) {
|
|
103
|
+
return this.post(`/orders/actions/${t}/dismiss`, {});
|
|
104
|
+
}
|
|
105
|
+
// --- Health ---
|
|
106
|
+
getHealth() {
|
|
107
|
+
return this.get("/health");
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
class c extends Error {
|
|
111
|
+
constructor(t, e, r) {
|
|
112
|
+
super(r), this.status = t, this.code = e, this.name = "TradeApiError";
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
export {
|
|
116
|
+
p as T,
|
|
117
|
+
c as a
|
|
118
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"apiClient-Pid_ZEt8.js","sources":["../src/utils/apiClient.ts"],"sourcesContent":["import type {\n SwapQuote, SwapTransaction, ExecuteResult, TokenRecord, PriceSnapshot,\n TransferBuildResponse, PositionsResponse, OpenOrder, DcaOrder, PendingAction, ProviderInfo,\n} from '../types';\n\nexport class TradeApiClient {\n constructor(\n private baseUrl: string,\n private tokenFn?: () => string | null,\n private apiKey?: string,\n ) {}\n\n private async request<T>(path: string, options?: RequestInit): Promise<T> {\n const headers: Record<string, string> = {\n 'Content-Type': 'application/json',\n ...(options?.headers as Record<string, string>),\n };\n const token = this.tokenFn?.();\n if (token) headers['Authorization'] = `Bearer ${token}`;\n if (this.apiKey) headers['x-api-key'] = this.apiKey;\n\n const resp = await fetch(`${this.baseUrl}${path}`, { ...options, headers });\n if (!resp.ok) {\n const body = await resp.json().catch(() => ({ error: { message: resp.statusText } }));\n throw new TradeApiError(resp.status, body?.error?.code ?? 'UNKNOWN', body?.error?.message ?? resp.statusText);\n }\n return resp.json();\n }\n\n private get<T>(path: string) { return this.request<T>(path); }\n private post<T>(path: string, body: unknown) {\n return this.request<T>(path, { method: 'POST', body: JSON.stringify(body) });\n }\n private del<T>(path: string, body?: unknown) {\n return this.request<T>(path, { method: 'DELETE', body: body ? JSON.stringify(body) : undefined });\n }\n\n // --- Tokens ---\n getTokens(category?: string) {\n const q = category ? `?category=${category}` : '';\n return this.get<{ tokens: TokenRecord[]; count: number }>(`/tokens${q}`);\n }\n getToken(mint: string) { return this.get<TokenRecord>(`/tokens/${mint}`); }\n\n // --- Swap ---\n getQuote(params: { inputMint: string; outputMint: string; amount: string; slippageBps?: number; provider?: string }) {\n return this.post<SwapQuote>('/swap/quote', params);\n }\n buildSwap(quote: SwapQuote, userPublicKey: string) {\n return this.post<SwapTransaction>('/swap/build', { quote, userPublicKey });\n }\n compareQuotes(inputMint: string, outputMint: string, amount: string) {\n return this.get<SwapQuote[]>(`/swap/compare?inputMint=${inputMint}&outputMint=${outputMint}&amount=${amount}`);\n }\n executeSwap(signedTransaction: string, provider: string, requestId?: string) {\n return this.post<ExecuteResult>('/swap/execute', { signedTransaction, provider, requestId });\n }\n getProviders() { return this.get<ProviderInfo[]>('/swap/providers'); }\n\n // --- Prices ---\n getPrice(mint: string) { return this.get<PriceSnapshot>(`/prices/${mint}`); }\n getBatchPrices(mints: string[]) { return this.post<{ prices: PriceSnapshot[] }>('/prices/batch', { mints }); }\n\n // --- Transfers ---\n buildTransfer(params: { sender: string; recipient: string; mint: string; amount: string; memo?: string }) {\n return this.post<TransferBuildResponse>('/transfers/build', params);\n }\n executeTransfer(signedTransaction: string) {\n return this.post<ExecuteResult>('/transfers/execute', { signedTransaction, provider: 'rpc' });\n }\n resolveAddress(address: string) {\n return this.get<{ input: string; resolved: string; type: string }>(`/transfers/resolve/${address}`);\n }\n\n // --- Orders ---\n createLimitOrder(params: { maker: string; inputMint: string; outputMint: string; inAmount: string; outAmount: string; expiry?: string }) {\n return this.post<{ transaction: string; orderId: string }>('/orders/limit', params);\n }\n createStopLoss(params: { maker: string; inputMint: string; outputMint: string; inAmount: string; triggerPrice: string; slippageBps?: number }) {\n return this.post<{ transaction: string; orderId: string }>('/orders/stop-loss', params);\n }\n createTakeProfit(params: { maker: string; inputMint: string; outputMint: string; inAmount: string; triggerPrice: string; slippageBps?: number }) {\n return this.post<{ transaction: string; orderId: string }>('/orders/take-profit', params);\n }\n createDca(params: { maker: string; inputMint: string; outputMint: string; totalInAmount: string; perCycleAmount: string; cycleInterval: number }) {\n return this.post<{ transaction: string; orderId: string }>('/orders/dca', params);\n }\n cancelOrder(orderId: string, maker: string) {\n return this.del<{ transaction: string }>(`/orders/${orderId}`, { maker });\n }\n getOpenOrders(wallet: string) {\n return this.get<{ limitOrders: OpenOrder[]; dcaOrders: DcaOrder[] }>(`/orders/wallet/${wallet}`);\n }\n\n // --- Positions ---\n getPositions(wallet: string) { return this.get<PositionsResponse>(`/positions/${wallet}`); }\n\n // --- Action Queue ---\n getPendingActions(wallet: string) { return this.get<PendingAction[]>(`/orders/actions/${wallet}`); }\n completeAction(actionId: string, signedTransaction: string) {\n return this.post<{ actionId: string; status: string; signature: string }>(\n `/orders/actions/${actionId}/complete`, { signedTransaction },\n );\n }\n dismissAction(actionId: string) {\n return this.post<{ actionId: string; status: string }>(`/orders/actions/${actionId}/dismiss`, {});\n }\n\n // --- Health ---\n getHealth() { return this.get<{ status: string; version: string }>('/health'); }\n}\n\nexport class TradeApiError extends Error {\n constructor(public status: number, public code: string, message: string) {\n super(message);\n this.name = 'TradeApiError';\n }\n}\n"],"names":["TradeApiClient","baseUrl","tokenFn","apiKey","path","options","_a","_b","_c","headers","token","resp","body","TradeApiError","category","q","mint","params","quote","userPublicKey","inputMint","outputMint","amount","signedTransaction","provider","requestId","mints","address","orderId","maker","wallet","actionId","status","code","message"],"mappings":"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"}
|