From 87e4c9d83ca3e7ee31c626604432584425b7c5b0 Mon Sep 17 00:00:00 2001 From: Ken Kunz Date: Thu, 19 Sep 2024 18:48:01 -0500 Subject: [PATCH 1/2] refactor: replace getTradeExecutorErrorHtml with StrategyError component --- src/lib/explorer/TradingDescription.svelte | 2 +- .../components/StrategyError.svelte | 42 +++++++++++++++++ src/lib/trade-executor/components/index.ts | 1 + src/lib/trade-executor/strategy/error.ts | 46 ------------------- src/routes/strategies/StrategyTile.svelte | 10 ++-- .../strategies/[strategy]/+layout.svelte | 11 ++--- 6 files changed, 52 insertions(+), 60 deletions(-) create mode 100644 src/lib/trade-executor/components/StrategyError.svelte delete mode 100644 src/lib/trade-executor/strategy/error.ts diff --git a/src/lib/explorer/TradingDescription.svelte b/src/lib/explorer/TradingDescription.svelte index bf07780ec..fcee437f8 100644 --- a/src/lib/explorer/TradingDescription.svelte +++ b/src/lib/explorer/TradingDescription.svelte @@ -7,7 +7,7 @@ primary label, a modifier (shown in lighter text), and a testing indicator Used in DataTable context (vs. standard svelte component context). #### Usage: -```ts +```tsx table.column({ header: 'Position', id: 'description', diff --git a/src/lib/trade-executor/components/StrategyError.svelte b/src/lib/trade-executor/components/StrategyError.svelte new file mode 100644 index 000000000..d095290e5 --- /dev/null +++ b/src/lib/trade-executor/components/StrategyError.svelte @@ -0,0 +1,42 @@ + + + + + + +{#if !strategy.connected} + Trade executor offline. Cannot display the strategy statistics. +{:else if !strategy.executor_running} + Strategy execution is currently paused due to an error. The trade execution engine is waiting for a manual action. + {#if strategy.crashed_at} + + Strategy executor halted {relative}. + + {/if} + See instance status page for more information . +{:else if strategy.frozen_positions > 0} + Strategy has currently frozen trading positions that require manual intervention. + See frozen positions page for more information. +{/if} diff --git a/src/lib/trade-executor/components/index.ts b/src/lib/trade-executor/components/index.ts index 9cb883533..3a6acdc54 100644 --- a/src/lib/trade-executor/components/index.ts +++ b/src/lib/trade-executor/components/index.ts @@ -1,3 +1,4 @@ export { default as KeyMetric } from './KeyMetric.svelte'; export { default as KeyMetricDescription } from './KeyMetricDescription.svelte'; export { default as StrategyIcon } from './StrategyIcon.svelte'; +export { default as StrategyError, hasError } from './StrategyError.svelte'; diff --git a/src/lib/trade-executor/strategy/error.ts b/src/lib/trade-executor/strategy/error.ts deleted file mode 100644 index 45cace6b6..000000000 --- a/src/lib/trade-executor/strategy/error.ts +++ /dev/null @@ -1,46 +0,0 @@ -/** - * Strategy error handling. - * - * There can be multiple failure modes for a trade executor - * - * - No connection - the webhook server is down / Internet issue - * - * - The trade executor has halted, the main loop aborted with an exception - * - * - The trade executor is not halted, but there is capital tied at - * frozen positions that need manual interventino - */ - -import type { StrategyRuntimeState } from './runtime-state'; -import { fromUnixTime } from 'date-fns'; -import { formatDatetime, formatDuration } from '$lib/helpers/formatters'; - -/** - * Get the HTML error message and help link in the case a trade executor is facing an issue. - */ -export function getTradeExecutorErrorHtml(state: StrategyRuntimeState): string | null { - const tradeExecutorId = state.id; - - if (!state.connected) { - return `Trade executor offline. Cannot display the strategy statistics.`; - } else if (!state.executor_running) { - // Add a timestamp and relative timestamp for quick diagnostics - let crashedAtMsg; - if (state.crashed_at) { - const diffSeconds = Date.now() / 1000 - state.crashed_at; - crashedAtMsg = `Strategy executor halted ${formatDatetime(fromUnixTime(state.crashed_at))}, ${formatDuration( - diffSeconds - )} ago.`; - } else { - crashedAtMsg = ''; - } - - return `Strategy execution is currently paused due to an error. The trade execution engine is waiting for a manual action. - See instance status page for more information. ${crashedAtMsg}`; - } else if (state.frozen_positions > 0) { - return `Strategy has currently frozen trading positions that needing manual actions. - See frozen positions page for more information.`; - } - - return null; -} diff --git a/src/routes/strategies/StrategyTile.svelte b/src/routes/strategies/StrategyTile.svelte index 35437e722..0eacf7599 100644 --- a/src/routes/strategies/StrategyTile.svelte +++ b/src/routes/strategies/StrategyTile.svelte @@ -5,12 +5,11 @@ import { utcDay } from 'd3-time'; import { normalizeDataForInterval } from '$lib/chart'; import { getChain } from '$lib/helpers/chain.js'; - import { Button, DataBadge, EntitySymbol, Tooltip } from '$lib/components'; - import { StrategyIcon } from 'trade-executor/components'; + import { Button, DataBadge, Tooltip } from '$lib/components'; + import { StrategyIcon, StrategyError, hasError } from 'trade-executor/components'; import StrategyBadges from './StrategyBadges.svelte'; import ChartThumbnail from './ChartThumbnail.svelte'; import StrategyDataSummary from './StrategyDataSummary.svelte'; - import { getTradeExecutorErrorHtml } from 'trade-executor/strategy/error'; import { getLogoUrl } from '$lib/helpers/assets'; export let admin = false; @@ -21,7 +20,6 @@ const chain = getChain(strategy.on_chain_data?.chain_id); const href = `/strategies/${strategy.id}`; - const errorHtml = getTradeExecutorErrorHtml(strategy); const chartData = normalizeDataForInterval( strategy.summary_statistics?.compounding_unrealised_trading_profitability ?? [], @@ -53,10 +51,10 @@ {#if !simplified}
- {#if errorHtml} + {#if hasError(strategy)} Error - {@html errorHtml} + {/if} diff --git a/src/routes/strategies/[strategy]/+layout.svelte b/src/routes/strategies/[strategy]/+layout.svelte index 3b5414f6e..82230c774 100644 --- a/src/routes/strategies/[strategy]/+layout.svelte +++ b/src/routes/strategies/[strategy]/+layout.svelte @@ -2,11 +2,10 @@ import { page } from '$app/stores'; import Breadcrumbs from '$lib/breadcrumb/Breadcrumbs.svelte'; import { AlertList, PageHeading } from '$lib/components'; - import { StrategyIcon } from 'trade-executor/components'; + import { StrategyIcon, StrategyError, hasError } from 'trade-executor/components'; import { menuOptions, default as StrategyNav } from './StrategyNav.svelte'; import StrategyBadges from '../StrategyBadges.svelte'; import { WalletWidget } from '$lib/wallet'; - import { getTradeExecutorErrorHtml } from 'trade-executor/strategy/error'; export let data; @@ -14,8 +13,6 @@ $: isOverviewPage = $page.url.pathname.endsWith(strategy.id); - $: errorHtml = getTradeExecutorErrorHtml(strategy); - $: isOutdated = Boolean(strategy.new_version_id); $: breadcrumbs = { @@ -42,7 +39,7 @@
- {#if isOverviewPage && (errorHtml || isOutdated)} + {#if isOverviewPage && (hasError(strategy) || isOutdated)}
@@ -51,8 +48,8 @@ participants should consider tranfering deposits to the latest version (though there is no guarantee of better performance). - - {@html errorHtml} + +
From 7d748f41640ca4e13c4d7ea8c1e5f3558b19b0d4 Mon Sep 17 00:00:00 2001 From: Ken Kunz Date: Fri, 20 Sep 2024 13:51:54 -0500 Subject: [PATCH 2/2] hide (most) strategy errors from non-admin users --- .../components/StrategyError.svelte | 12 ++++++++++-- src/lib/trade-executor/components/index.ts | 3 ++- src/routes/strategies/StrategyTile.svelte | 14 +++++++++++--- .../strategies/[strategy]/+layout.svelte | 18 ++++++++++++++---- 4 files changed, 37 insertions(+), 10 deletions(-) diff --git a/src/lib/trade-executor/components/StrategyError.svelte b/src/lib/trade-executor/components/StrategyError.svelte index d095290e5..51706a672 100644 --- a/src/lib/trade-executor/components/StrategyError.svelte +++ b/src/lib/trade-executor/components/StrategyError.svelte @@ -14,8 +14,16 @@ Display an appropriate error message for a strategy when needed. There can be mu diff --git a/src/lib/trade-executor/components/index.ts b/src/lib/trade-executor/components/index.ts index 3a6acdc54..087677004 100644 --- a/src/lib/trade-executor/components/index.ts +++ b/src/lib/trade-executor/components/index.ts @@ -1,4 +1,5 @@ export { default as KeyMetric } from './KeyMetric.svelte'; export { default as KeyMetricDescription } from './KeyMetricDescription.svelte'; export { default as StrategyIcon } from './StrategyIcon.svelte'; -export { default as StrategyError, hasError } from './StrategyError.svelte'; +export { default as StrategyError } from './StrategyError.svelte'; +export * from './StrategyError.svelte'; diff --git a/src/routes/strategies/StrategyTile.svelte b/src/routes/strategies/StrategyTile.svelte index 0eacf7599..acb4250eb 100644 --- a/src/routes/strategies/StrategyTile.svelte +++ b/src/routes/strategies/StrategyTile.svelte @@ -6,11 +6,12 @@ import { normalizeDataForInterval } from '$lib/chart'; import { getChain } from '$lib/helpers/chain.js'; import { Button, DataBadge, Tooltip } from '$lib/components'; - import { StrategyIcon, StrategyError, hasError } from 'trade-executor/components'; + import { StrategyIcon, StrategyError, shouldDisplayError, adminOnlyError } from 'trade-executor/components'; import StrategyBadges from './StrategyBadges.svelte'; import ChartThumbnail from './ChartThumbnail.svelte'; import StrategyDataSummary from './StrategyDataSummary.svelte'; import { getLogoUrl } from '$lib/helpers/assets'; + import Alert from '$lib/components/Alert.svelte'; export let admin = false; export let simplified = false; @@ -51,10 +52,17 @@ {#if !simplified}
- {#if hasError(strategy)} + {#if shouldDisplayError(strategy, admin)} Error - + + {#if adminOnlyError(strategy)} +

+ This error is only displayed to admin users. +

+ {/if} + +
{/if} diff --git a/src/routes/strategies/[strategy]/+layout.svelte b/src/routes/strategies/[strategy]/+layout.svelte index 82230c774..6b7079da7 100644 --- a/src/routes/strategies/[strategy]/+layout.svelte +++ b/src/routes/strategies/[strategy]/+layout.svelte @@ -2,17 +2,19 @@ import { page } from '$app/stores'; import Breadcrumbs from '$lib/breadcrumb/Breadcrumbs.svelte'; import { AlertList, PageHeading } from '$lib/components'; - import { StrategyIcon, StrategyError, hasError } from 'trade-executor/components'; + import { StrategyIcon, StrategyError, shouldDisplayError, adminOnlyError } from 'trade-executor/components'; import { menuOptions, default as StrategyNav } from './StrategyNav.svelte'; import StrategyBadges from '../StrategyBadges.svelte'; import { WalletWidget } from '$lib/wallet'; export let data; - $: ({ strategy, deferred } = data); + $: ({ admin, strategy, deferred } = data); $: isOverviewPage = $page.url.pathname.endsWith(strategy.id); + $: hasStrategyError = shouldDisplayError(strategy, admin); + $: isOutdated = Boolean(strategy.new_version_id); $: breadcrumbs = { @@ -39,7 +41,7 @@
- {#if isOverviewPage && (hasError(strategy) || isOutdated)} + {#if isOverviewPage && (hasStrategyError || isOutdated)}
@@ -48,8 +50,11 @@ participants should consider tranfering deposits to the latest version (though there is no guarantee of better performance). - + + {#if adminOnlyError(strategy)} +

Note: this error is only displayed to admin users.

+ {/if}
@@ -79,6 +84,11 @@ transform: translate(0, -0.375em); } + .admin-error { + margin-top: 1rem; + opacity: 0.5; + } + .subpage { display: grid; gap: var(--space-ls);