Some checks failed
deploy / deploy (push) Failing after 34s
Proof: npm test passed 159/159; npm run operator-dashboard:build passed; repo-local Postgres importer smoke test imported 163 live 1Click tokens with only 3 inventory-enabled seed assets and nBTC/EURe pairs at 49 bps. Assumptions: Forgejo main push is the repo deployment path; production has existing repo-managed POSTGRES_URL/POSTGRES_PASSWORD/NEAR_INTENTS_API_KEY secrets; startup seed may create initial current nBTC/EURe config but must preserve DB runtime pair flags after creation. Still fake: no live funds movement was attempted; imported supported assets remain catalog-only unless explicitly enabled in DB; production rollout evidence still depends on the Forgejo deploy job completing after this push.
631 lines
25 KiB
JavaScript
631 lines
25 KiB
JavaScript
import { loadDotenv } from './env.mjs';
|
|
|
|
const DEFAULTS = {
|
|
nearIntentsWsUrl: 'wss://solver-relay-v2.chaindefuser.com/ws',
|
|
nearIntentsRpcUrl: 'https://solver-relay-v2.chaindefuser.com/rpc',
|
|
nearBridgeRpcUrl: 'https://bridge.chaindefuser.com/rpc',
|
|
nearRpcUrl: 'https://near.lava.build',
|
|
nearVerifierContract: 'intents.near',
|
|
nearIntentsControlApiEnabled: true,
|
|
nearIntentsControlHost: '0.0.0.0',
|
|
nearIntentsControlPort: 8081,
|
|
marketReferenceControlPort: 8082,
|
|
inventorySyncControlPort: 8083,
|
|
liquidityManagerControlPort: 8084,
|
|
historyWriterControlPort: 8085,
|
|
strategyEngineControlPort: 8086,
|
|
tradeExecutorControlPort: 8087,
|
|
opsSentinelControlPort: 8088,
|
|
operatorDashboardControlPort: 8090,
|
|
kafkaBrokers: ['127.0.0.1:9092'],
|
|
kafkaClientId: 'unrip',
|
|
kafkaTopicRawNearIntentsQuote: 'raw.near_intents.quote',
|
|
kafkaTopicNormSwapDemand: 'norm.swap_demand',
|
|
kafkaTopicRefMarketPrice: 'ref.market_price',
|
|
kafkaTopicStateIntentInventory: 'state.intent_inventory',
|
|
kafkaTopicOpsLiquidityAction: 'ops.liquidity_action',
|
|
kafkaTopicOpsFundingObservation: 'ops.funding_observation',
|
|
kafkaTopicOpsAlert: 'ops.alert',
|
|
kafkaTopicOpsEnvironmentStatus: 'ops.environment_status',
|
|
kafkaTopicDecisionTradeDecision: 'decision.trade_decision',
|
|
kafkaTopicCmdExecuteTrade: 'cmd.execute_trade',
|
|
kafkaTopicExecTradeResult: 'exec.trade_result',
|
|
kafkaConsumerGroupHistory: 'history-writer-v1',
|
|
kafkaConsumerGroupInventory: 'inventory-sync-v1',
|
|
kafkaConsumerGroupStrategy: 'strategy-engine-v1',
|
|
kafkaConsumerGroupExecutor: 'trade-executor-v1',
|
|
kafkaConsumerGroupOpsSentinel: 'ops-sentinel-v1',
|
|
kafkaConsumerGroupOperatorDashboard: 'operator-dashboard-v1',
|
|
historyWriterDerivedRefreshMaxEventAgeMs: 30_000,
|
|
strategyStateDir: './var/strategy-state',
|
|
executorStateDir: './var/executor-state',
|
|
liquidityStateDir: './var/liquidity-state',
|
|
postgresUrl: 'postgresql://unrip:unrip@127.0.0.1:5432/unrip',
|
|
projectName: 'unrip',
|
|
projectNamespace: 'unrip',
|
|
tradingBtcAssetId: 'nep141:nbtc.bridge.near',
|
|
tradingBtcTrackedAssetIds: [
|
|
'nep141:nbtc.bridge.near',
|
|
'nep141:btc.omft.near',
|
|
],
|
|
tradingBtcSymbol: 'BTC',
|
|
tradingBtcLabel: 'BTC / nBTC reserve',
|
|
tradingBtcLegacyLabel: 'BTC / legacy OMFT',
|
|
tradingBtcDecimals: 8,
|
|
tradingBtcChain: 'btc:mainnet',
|
|
tradingBtcWithdrawAddress: '',
|
|
tradingEureAssetId: 'nep141:gnosis-0x420ca0f9b9b604ce0fd9c18ef134c705e5fa3430.omft.near',
|
|
tradingEureSymbol: 'EURe',
|
|
tradingEureDecimals: 18,
|
|
tradingEureChain: 'eth:100',
|
|
tradingEureWithdrawAddress: '',
|
|
marketReferenceRefreshMs: 5_000,
|
|
marketReferenceCoinGeckoRefreshMs: 15_000,
|
|
marketReferenceMaxAgeMs: 30_000,
|
|
marketReferenceKrakenTickerUrl: 'https://api.kraken.com/0/public/Ticker?pair=XBTEUR',
|
|
marketReferenceCoinGeckoUrl:
|
|
'https://api.coingecko.com/api/v3/simple/price?ids=bitcoin&vs_currencies=eur',
|
|
inventorySyncRefreshMs: 15_000,
|
|
liquidityRefreshMs: 30_000,
|
|
strategyGrossThresholdPct: 0.49,
|
|
strategyInitialArmed: false,
|
|
strategyMaxNotionalEure: 5,
|
|
strategyPriceMaxAgeMs: 30_000,
|
|
strategyInventoryMaxAgeMs: 30_000,
|
|
executorInitialArmed: false,
|
|
executorResponseTimeoutMs: 10_000,
|
|
intentRequestDefaultAmountEure: 5,
|
|
intentRequestMaxAmountEure: 5,
|
|
intentRequestDefaultSlippageBps: 200,
|
|
intentRequestMaxSlippageBps: 200,
|
|
intentRequestMinDeadlineMs: 60_000,
|
|
intentRequestQuoteTimeoutMs: 10_000,
|
|
intentRequestPublishTimeoutMs: 10_000,
|
|
intentRequestStatusTimeoutMs: 10_000,
|
|
intentRequestInventoryMaxAgeMs: 30_000,
|
|
intentRequestPriceMaxAgeMs: 30_000,
|
|
withdrawalsFrozen: true,
|
|
btcFundingObserverEnabled: true,
|
|
btcFundingObserverBaseUrl: 'https://mempool.space/api',
|
|
fundingObservationStuckMs: 60 * 60 * 1000,
|
|
opsSentinelEvaluationMs: 5_000,
|
|
opsSentinelFundingCreditPendingMs: 5 * 60 * 1000,
|
|
opsSentinelIngestMessageStaleMs: 30_000,
|
|
opsSentinelIngestQuoteStaleMs: 30_000,
|
|
opsSentinelIngestPublishStaleMs: 30_000,
|
|
opsSentinelExecutorRelayStaleMs: 30_000,
|
|
opsSentinelHistoryWriterStaleMs: 45_000,
|
|
opsSentinelDashboardSourceDegradedMs: 30_000,
|
|
opsSentinelSelfStaleMs: 20_000,
|
|
opsSentinelAnomalyWindowSize: 6,
|
|
opsSentinelAnomalyQuoteRateCollapseRatio: 0.25,
|
|
opsSentinelAnomalyReconnectSpikeMultiplier: 2,
|
|
opsSentinelContainmentCooldownMs: 60_000,
|
|
opsSentinelAlertWebhookUrl: '',
|
|
opsSentinelAlertWebhookTimeoutMs: 5_000,
|
|
operatorDashboardAuthMode: 'stub',
|
|
operatorDashboardAuthUsername: 'admin',
|
|
operatorDashboardAuthPassword: '',
|
|
operatorDashboardAuthRealm: 'unrip operator dashboard',
|
|
operatorDashboardQuoteLimit: 10,
|
|
operatorDashboardTradePageSize: 20,
|
|
operatorDashboardUpstreamTimeoutMs: 3_000,
|
|
nearIntentsStatusServicesUrl: 'https://status.near-intents.org/api/services',
|
|
nearIntentsStatusPostsUrl: 'https://status.near-intents.org/api/posts?is_featured=true&limit=500',
|
|
nearIntentsStatusPostEnumsUrl: 'https://status.near-intents.org/api/post_enums',
|
|
nearIntentsStatusTimeoutMs: 3_000,
|
|
nearIntentsStatusPollMs: 60_000,
|
|
notificationNtfyBaseUrl: '',
|
|
notificationNtfyTopic: 'unrip',
|
|
notificationNtfyToken: '',
|
|
notificationNtfyTimeoutMs: 5_000,
|
|
};
|
|
|
|
function splitCsv(value) {
|
|
return String(value || '')
|
|
.split(',')
|
|
.map((part) => part.trim())
|
|
.filter(Boolean);
|
|
}
|
|
|
|
function parseNumber(value, fallback) {
|
|
const parsed = Number(value);
|
|
return Number.isFinite(parsed) ? parsed : fallback;
|
|
}
|
|
|
|
function parseBoolean(value, fallback) {
|
|
if (value == null || value === '') return fallback;
|
|
|
|
const normalized = String(value).trim().toLowerCase();
|
|
if (['1', 'true', 'yes', 'on'].includes(normalized)) return true;
|
|
if (['0', 'false', 'no', 'off'].includes(normalized)) return false;
|
|
return fallback;
|
|
}
|
|
|
|
function unique(values) {
|
|
return [...new Set(values.filter(Boolean))];
|
|
}
|
|
|
|
function buildAsset({
|
|
assetId,
|
|
symbol,
|
|
decimals,
|
|
chain,
|
|
withdrawAddress = '',
|
|
label = symbol,
|
|
role = 'tracked',
|
|
}) {
|
|
return {
|
|
assetId,
|
|
symbol,
|
|
label,
|
|
decimals,
|
|
chain,
|
|
withdrawAddress,
|
|
role,
|
|
};
|
|
}
|
|
|
|
function buildBtcAssetLabel(assetId, tradingAssetId) {
|
|
if (assetId === tradingAssetId) return DEFAULTS.tradingBtcLabel;
|
|
if (assetId === 'nep141:btc.omft.near') return DEFAULTS.tradingBtcLegacyLabel;
|
|
return `${DEFAULTS.tradingBtcSymbol} / ${assetId.replace(/^nep141:/, '')}`;
|
|
}
|
|
|
|
function defaultControlBaseUrl({ serviceName, port, namespace }) {
|
|
if (process.env.KUBERNETES_SERVICE_HOST) {
|
|
return `http://${serviceName}.${namespace}.svc.cluster.local:${port}`;
|
|
}
|
|
return `http://127.0.0.1:${port}`;
|
|
}
|
|
|
|
export function loadConfig({ envPath = '.env' } = {}) {
|
|
loadDotenv(envPath);
|
|
|
|
const tradingBtc = buildAsset({
|
|
assetId: DEFAULTS.tradingBtcAssetId,
|
|
symbol: DEFAULTS.tradingBtcSymbol,
|
|
label: DEFAULTS.tradingBtcLabel,
|
|
decimals: DEFAULTS.tradingBtcDecimals,
|
|
chain: DEFAULTS.tradingBtcChain,
|
|
withdrawAddress: DEFAULTS.tradingBtcWithdrawAddress,
|
|
role: 'trading',
|
|
});
|
|
const trackedBtcAssetIds = unique([
|
|
tradingBtc.assetId,
|
|
...DEFAULTS.tradingBtcTrackedAssetIds,
|
|
]);
|
|
const tradingBtcAssets = trackedBtcAssetIds.map((assetId) => {
|
|
if (assetId === tradingBtc.assetId) return tradingBtc;
|
|
return buildAsset({
|
|
assetId,
|
|
symbol: tradingBtc.symbol,
|
|
label: buildBtcAssetLabel(assetId, tradingBtc.assetId),
|
|
decimals: tradingBtc.decimals,
|
|
chain: tradingBtc.chain,
|
|
withdrawAddress: tradingBtc.withdrawAddress,
|
|
role: 'legacy',
|
|
});
|
|
});
|
|
const tradingEure = buildAsset({
|
|
assetId: DEFAULTS.tradingEureAssetId,
|
|
symbol: DEFAULTS.tradingEureSymbol,
|
|
label: DEFAULTS.tradingEureSymbol,
|
|
decimals: DEFAULTS.tradingEureDecimals,
|
|
chain: DEFAULTS.tradingEureChain,
|
|
withdrawAddress: DEFAULTS.tradingEureWithdrawAddress,
|
|
role: 'trading',
|
|
});
|
|
const trackedAssets = [
|
|
...tradingBtcAssets,
|
|
tradingEure,
|
|
];
|
|
|
|
const projectName = process.env.PROJECT_NAME || DEFAULTS.projectName;
|
|
const projectNamespace =
|
|
process.env.PROJECT_NAMESPACE || projectName || DEFAULTS.projectNamespace;
|
|
|
|
return {
|
|
nearIntentsApiKey: process.env.NEAR_INTENTS_API_KEY || '',
|
|
nearIntentsAccountId: process.env.NEAR_INTENTS_ACCOUNT_ID || '',
|
|
nearIntentsSignerPrivateKey: process.env.NEAR_INTENTS_SIGNER_PRIVATE_KEY || '',
|
|
nearIntentsWsUrl: process.env.NEAR_INTENTS_WS_URL || DEFAULTS.nearIntentsWsUrl,
|
|
nearIntentsRpcUrl: process.env.NEAR_INTENTS_RPC_URL || DEFAULTS.nearIntentsRpcUrl,
|
|
nearBridgeRpcUrl: process.env.NEAR_INTENTS_BRIDGE_RPC_URL || DEFAULTS.nearBridgeRpcUrl,
|
|
nearRpcUrl: process.env.NEAR_RPC_URL || DEFAULTS.nearRpcUrl,
|
|
nearVerifierContract:
|
|
process.env.NEAR_INTENTS_VERIFIER_CONTRACT || DEFAULTS.nearVerifierContract,
|
|
nearIntentsControlApiEnabled: parseBoolean(
|
|
process.env.NEAR_INTENTS_CONTROL_API_ENABLED,
|
|
DEFAULTS.nearIntentsControlApiEnabled,
|
|
),
|
|
nearIntentsControlHost:
|
|
process.env.NEAR_INTENTS_CONTROL_HOST || DEFAULTS.nearIntentsControlHost,
|
|
nearIntentsControlPort: parseNumber(
|
|
process.env.NEAR_INTENTS_CONTROL_PORT,
|
|
DEFAULTS.nearIntentsControlPort,
|
|
),
|
|
nearIntentsControlBaseUrl:
|
|
process.env.NEAR_INTENTS_CONTROL_BASE_URL
|
|
|| defaultControlBaseUrl({
|
|
serviceName: 'near-intents-ingest',
|
|
port: parseNumber(
|
|
process.env.NEAR_INTENTS_CONTROL_PORT,
|
|
DEFAULTS.nearIntentsControlPort,
|
|
),
|
|
namespace: projectNamespace,
|
|
}),
|
|
marketReferenceControlHost:
|
|
process.env.MARKET_REFERENCE_CONTROL_HOST || DEFAULTS.nearIntentsControlHost,
|
|
marketReferenceControlPort: parseNumber(
|
|
process.env.MARKET_REFERENCE_CONTROL_PORT,
|
|
DEFAULTS.marketReferenceControlPort,
|
|
),
|
|
marketReferenceControlBaseUrl:
|
|
process.env.MARKET_REFERENCE_CONTROL_BASE_URL
|
|
|| defaultControlBaseUrl({
|
|
serviceName: 'market-reference-ingest',
|
|
port: parseNumber(
|
|
process.env.MARKET_REFERENCE_CONTROL_PORT,
|
|
DEFAULTS.marketReferenceControlPort,
|
|
),
|
|
namespace: projectNamespace,
|
|
}),
|
|
inventorySyncControlHost:
|
|
process.env.INVENTORY_SYNC_CONTROL_HOST || DEFAULTS.nearIntentsControlHost,
|
|
inventorySyncControlPort: parseNumber(
|
|
process.env.INVENTORY_SYNC_CONTROL_PORT,
|
|
DEFAULTS.inventorySyncControlPort,
|
|
),
|
|
inventorySyncControlBaseUrl:
|
|
process.env.INVENTORY_SYNC_CONTROL_BASE_URL
|
|
|| defaultControlBaseUrl({
|
|
serviceName: 'inventory-sync',
|
|
port: parseNumber(
|
|
process.env.INVENTORY_SYNC_CONTROL_PORT,
|
|
DEFAULTS.inventorySyncControlPort,
|
|
),
|
|
namespace: projectNamespace,
|
|
}),
|
|
liquidityManagerControlHost:
|
|
process.env.LIQUIDITY_MANAGER_CONTROL_HOST || DEFAULTS.nearIntentsControlHost,
|
|
liquidityManagerControlPort: parseNumber(
|
|
process.env.LIQUIDITY_MANAGER_CONTROL_PORT,
|
|
DEFAULTS.liquidityManagerControlPort,
|
|
),
|
|
liquidityManagerControlBaseUrl:
|
|
process.env.LIQUIDITY_MANAGER_CONTROL_BASE_URL
|
|
|| defaultControlBaseUrl({
|
|
serviceName: 'liquidity-manager',
|
|
port: parseNumber(
|
|
process.env.LIQUIDITY_MANAGER_CONTROL_PORT,
|
|
DEFAULTS.liquidityManagerControlPort,
|
|
),
|
|
namespace: projectNamespace,
|
|
}),
|
|
historyWriterControlHost:
|
|
process.env.HISTORY_WRITER_CONTROL_HOST || DEFAULTS.nearIntentsControlHost,
|
|
historyWriterControlPort: parseNumber(
|
|
process.env.HISTORY_WRITER_CONTROL_PORT,
|
|
DEFAULTS.historyWriterControlPort,
|
|
),
|
|
historyWriterControlBaseUrl:
|
|
process.env.HISTORY_WRITER_CONTROL_BASE_URL
|
|
|| defaultControlBaseUrl({
|
|
serviceName: 'history-writer',
|
|
port: parseNumber(
|
|
process.env.HISTORY_WRITER_CONTROL_PORT,
|
|
DEFAULTS.historyWriterControlPort,
|
|
),
|
|
namespace: projectNamespace,
|
|
}),
|
|
opsSentinelControlHost:
|
|
process.env.OPS_SENTINEL_CONTROL_HOST || DEFAULTS.nearIntentsControlHost,
|
|
opsSentinelControlPort: parseNumber(
|
|
process.env.OPS_SENTINEL_CONTROL_PORT,
|
|
DEFAULTS.opsSentinelControlPort,
|
|
),
|
|
opsSentinelControlBaseUrl:
|
|
process.env.OPS_SENTINEL_CONTROL_BASE_URL
|
|
|| defaultControlBaseUrl({
|
|
serviceName: 'ops-sentinel',
|
|
port: parseNumber(
|
|
process.env.OPS_SENTINEL_CONTROL_PORT,
|
|
DEFAULTS.opsSentinelControlPort,
|
|
),
|
|
namespace: projectNamespace,
|
|
}),
|
|
strategyEngineControlHost:
|
|
process.env.STRATEGY_ENGINE_CONTROL_HOST || DEFAULTS.nearIntentsControlHost,
|
|
strategyEngineControlPort: parseNumber(
|
|
process.env.STRATEGY_ENGINE_CONTROL_PORT,
|
|
DEFAULTS.strategyEngineControlPort,
|
|
),
|
|
strategyEngineControlBaseUrl:
|
|
process.env.STRATEGY_ENGINE_CONTROL_BASE_URL
|
|
|| defaultControlBaseUrl({
|
|
serviceName: 'strategy-engine',
|
|
port: parseNumber(
|
|
process.env.STRATEGY_ENGINE_CONTROL_PORT,
|
|
DEFAULTS.strategyEngineControlPort,
|
|
),
|
|
namespace: projectNamespace,
|
|
}),
|
|
tradeExecutorControlHost:
|
|
process.env.TRADE_EXECUTOR_CONTROL_HOST || DEFAULTS.nearIntentsControlHost,
|
|
tradeExecutorControlPort: parseNumber(
|
|
process.env.TRADE_EXECUTOR_CONTROL_PORT,
|
|
DEFAULTS.tradeExecutorControlPort,
|
|
),
|
|
tradeExecutorControlBaseUrl:
|
|
process.env.TRADE_EXECUTOR_CONTROL_BASE_URL
|
|
|| defaultControlBaseUrl({
|
|
serviceName: 'trade-executor',
|
|
port: parseNumber(
|
|
process.env.TRADE_EXECUTOR_CONTROL_PORT,
|
|
DEFAULTS.tradeExecutorControlPort,
|
|
),
|
|
namespace: projectNamespace,
|
|
}),
|
|
operatorDashboardControlHost:
|
|
process.env.OPERATOR_DASHBOARD_CONTROL_HOST || DEFAULTS.nearIntentsControlHost,
|
|
operatorDashboardControlPort: parseNumber(
|
|
process.env.OPERATOR_DASHBOARD_CONTROL_PORT,
|
|
DEFAULTS.operatorDashboardControlPort,
|
|
),
|
|
operatorDashboardControlBaseUrl:
|
|
process.env.OPERATOR_DASHBOARD_CONTROL_BASE_URL
|
|
|| defaultControlBaseUrl({
|
|
serviceName: 'operator-dashboard',
|
|
port: parseNumber(
|
|
process.env.OPERATOR_DASHBOARD_CONTROL_PORT,
|
|
DEFAULTS.operatorDashboardControlPort,
|
|
),
|
|
namespace: projectNamespace,
|
|
}),
|
|
kafkaBrokers: splitCsv(process.env.KAFKA_BROKERS).length
|
|
? splitCsv(process.env.KAFKA_BROKERS)
|
|
: DEFAULTS.kafkaBrokers,
|
|
kafkaClientId: process.env.KAFKA_CLIENT_ID || DEFAULTS.kafkaClientId,
|
|
kafkaTopicRawNearIntentsQuote:
|
|
process.env.KAFKA_TOPIC_RAW_NEAR_INTENTS_QUOTE || DEFAULTS.kafkaTopicRawNearIntentsQuote,
|
|
kafkaTopicNormSwapDemand:
|
|
process.env.KAFKA_TOPIC_NORM_SWAP_DEMAND || DEFAULTS.kafkaTopicNormSwapDemand,
|
|
kafkaTopicRefMarketPrice:
|
|
process.env.KAFKA_TOPIC_REF_MARKET_PRICE || DEFAULTS.kafkaTopicRefMarketPrice,
|
|
kafkaTopicStateIntentInventory:
|
|
process.env.KAFKA_TOPIC_STATE_INTENT_INVENTORY || DEFAULTS.kafkaTopicStateIntentInventory,
|
|
kafkaTopicOpsLiquidityAction:
|
|
process.env.KAFKA_TOPIC_OPS_LIQUIDITY_ACTION || DEFAULTS.kafkaTopicOpsLiquidityAction,
|
|
kafkaTopicOpsFundingObservation:
|
|
process.env.KAFKA_TOPIC_OPS_FUNDING_OBSERVATION || DEFAULTS.kafkaTopicOpsFundingObservation,
|
|
kafkaTopicOpsAlert:
|
|
process.env.KAFKA_TOPIC_OPS_ALERT || DEFAULTS.kafkaTopicOpsAlert,
|
|
kafkaTopicOpsEnvironmentStatus:
|
|
process.env.KAFKA_TOPIC_OPS_ENVIRONMENT_STATUS || DEFAULTS.kafkaTopicOpsEnvironmentStatus,
|
|
kafkaTopicDecisionTradeDecision:
|
|
process.env.KAFKA_TOPIC_DECISION_TRADE_DECISION || DEFAULTS.kafkaTopicDecisionTradeDecision,
|
|
kafkaTopicCmdExecuteTrade:
|
|
process.env.KAFKA_TOPIC_CMD_EXECUTE_TRADE || DEFAULTS.kafkaTopicCmdExecuteTrade,
|
|
kafkaTopicExecTradeResult:
|
|
process.env.KAFKA_TOPIC_EXEC_TRADE_RESULT || DEFAULTS.kafkaTopicExecTradeResult,
|
|
kafkaConsumerGroupHistory:
|
|
process.env.KAFKA_CONSUMER_GROUP_HISTORY || DEFAULTS.kafkaConsumerGroupHistory,
|
|
kafkaConsumerGroupInventory:
|
|
process.env.KAFKA_CONSUMER_GROUP_INVENTORY || DEFAULTS.kafkaConsumerGroupInventory,
|
|
kafkaConsumerGroupStrategy:
|
|
process.env.KAFKA_CONSUMER_GROUP_STRATEGY || DEFAULTS.kafkaConsumerGroupStrategy,
|
|
kafkaConsumerGroupExecutor:
|
|
process.env.KAFKA_CONSUMER_GROUP_EXECUTOR || DEFAULTS.kafkaConsumerGroupExecutor,
|
|
kafkaConsumerGroupOpsSentinel:
|
|
process.env.KAFKA_CONSUMER_GROUP_OPS_SENTINEL || DEFAULTS.kafkaConsumerGroupOpsSentinel,
|
|
kafkaConsumerGroupOperatorDashboard:
|
|
process.env.KAFKA_CONSUMER_GROUP_OPERATOR_DASHBOARD
|
|
|| DEFAULTS.kafkaConsumerGroupOperatorDashboard,
|
|
historyWriterDerivedRefreshMaxEventAgeMs: parseNumber(
|
|
process.env.HISTORY_WRITER_DERIVED_REFRESH_MAX_EVENT_AGE_MS,
|
|
DEFAULTS.historyWriterDerivedRefreshMaxEventAgeMs,
|
|
),
|
|
strategyStateDir: process.env.STRATEGY_STATE_DIR || DEFAULTS.strategyStateDir,
|
|
executorStateDir: process.env.EXECUTOR_STATE_DIR || DEFAULTS.executorStateDir,
|
|
liquidityStateDir: process.env.LIQUIDITY_STATE_DIR || DEFAULTS.liquidityStateDir,
|
|
postgresUrl: process.env.POSTGRES_URL || DEFAULTS.postgresUrl,
|
|
projectName,
|
|
projectNamespace,
|
|
tradingBtc,
|
|
tradingBtcAssets,
|
|
tradingEure,
|
|
activePair: `${tradingBtc.assetId}->${tradingEure.assetId}`,
|
|
activeAssetIds: [tradingBtc.assetId, tradingEure.assetId],
|
|
trackedAssets,
|
|
trackedAssetIds: trackedAssets.map((asset) => asset.assetId),
|
|
assetRegistry: new Map(trackedAssets.map((asset) => [asset.assetId, asset])),
|
|
marketReferenceRefreshMs: parseNumber(
|
|
process.env.MARKET_REFERENCE_REFRESH_MS,
|
|
DEFAULTS.marketReferenceRefreshMs,
|
|
),
|
|
marketReferenceCoinGeckoRefreshMs: parseNumber(
|
|
process.env.MARKET_REFERENCE_COINGECKO_REFRESH_MS,
|
|
DEFAULTS.marketReferenceCoinGeckoRefreshMs,
|
|
),
|
|
marketReferenceMaxAgeMs: parseNumber(
|
|
process.env.MARKET_REFERENCE_MAX_AGE_MS,
|
|
DEFAULTS.marketReferenceMaxAgeMs,
|
|
),
|
|
marketReferenceKrakenTickerUrl:
|
|
process.env.MARKET_REFERENCE_KRAKEN_TICKER_URL || DEFAULTS.marketReferenceKrakenTickerUrl,
|
|
marketReferenceCoinGeckoUrl:
|
|
process.env.MARKET_REFERENCE_COINGECKO_URL || DEFAULTS.marketReferenceCoinGeckoUrl,
|
|
inventorySyncRefreshMs: parseNumber(
|
|
process.env.INVENTORY_SYNC_REFRESH_MS,
|
|
DEFAULTS.inventorySyncRefreshMs,
|
|
),
|
|
liquidityRefreshMs: parseNumber(
|
|
process.env.LIQUIDITY_REFRESH_MS,
|
|
DEFAULTS.liquidityRefreshMs,
|
|
),
|
|
strategyGrossThresholdPct: DEFAULTS.strategyGrossThresholdPct,
|
|
strategyInitialArmed: parseBoolean(
|
|
process.env.STRATEGY_INITIAL_ARMED,
|
|
DEFAULTS.strategyInitialArmed,
|
|
),
|
|
strategyMaxNotionalEure: DEFAULTS.strategyMaxNotionalEure,
|
|
strategyPriceMaxAgeMs: DEFAULTS.strategyPriceMaxAgeMs,
|
|
strategyInventoryMaxAgeMs: DEFAULTS.strategyInventoryMaxAgeMs,
|
|
executorInitialArmed: parseBoolean(
|
|
process.env.EXECUTOR_INITIAL_ARMED,
|
|
DEFAULTS.executorInitialArmed,
|
|
),
|
|
executorResponseTimeoutMs: parseNumber(
|
|
process.env.EXECUTOR_RESPONSE_TIMEOUT_MS,
|
|
DEFAULTS.executorResponseTimeoutMs,
|
|
),
|
|
intentRequestDefaultAmountEure: DEFAULTS.intentRequestDefaultAmountEure,
|
|
intentRequestMaxAmountEure: DEFAULTS.intentRequestMaxAmountEure,
|
|
intentRequestDefaultSlippageBps: DEFAULTS.intentRequestDefaultSlippageBps,
|
|
intentRequestMaxSlippageBps: DEFAULTS.intentRequestMaxSlippageBps,
|
|
intentRequestMinDeadlineMs: DEFAULTS.intentRequestMinDeadlineMs,
|
|
intentRequestQuoteTimeoutMs: parseNumber(
|
|
process.env.INTENT_REQUEST_QUOTE_TIMEOUT_MS,
|
|
DEFAULTS.intentRequestQuoteTimeoutMs,
|
|
),
|
|
intentRequestPublishTimeoutMs: parseNumber(
|
|
process.env.INTENT_REQUEST_PUBLISH_TIMEOUT_MS,
|
|
DEFAULTS.intentRequestPublishTimeoutMs,
|
|
),
|
|
intentRequestStatusTimeoutMs: parseNumber(
|
|
process.env.INTENT_REQUEST_STATUS_TIMEOUT_MS,
|
|
DEFAULTS.intentRequestStatusTimeoutMs,
|
|
),
|
|
intentRequestInventoryMaxAgeMs: DEFAULTS.intentRequestInventoryMaxAgeMs,
|
|
intentRequestPriceMaxAgeMs: DEFAULTS.intentRequestPriceMaxAgeMs,
|
|
withdrawalsFrozen: parseBoolean(
|
|
process.env.LIQUIDITY_WITHDRAWALS_FROZEN,
|
|
DEFAULTS.withdrawalsFrozen,
|
|
),
|
|
btcFundingObserverEnabled: parseBoolean(
|
|
process.env.BTC_FUNDING_OBSERVER_ENABLED,
|
|
DEFAULTS.btcFundingObserverEnabled,
|
|
),
|
|
btcFundingObserverBaseUrl:
|
|
process.env.BTC_FUNDING_OBSERVER_BASE_URL || DEFAULTS.btcFundingObserverBaseUrl,
|
|
fundingObservationStuckMs: parseNumber(
|
|
process.env.FUNDING_OBSERVATION_STUCK_MS,
|
|
DEFAULTS.fundingObservationStuckMs,
|
|
),
|
|
opsSentinelEvaluationMs: parseNumber(
|
|
process.env.OPS_SENTINEL_EVALUATION_MS,
|
|
DEFAULTS.opsSentinelEvaluationMs,
|
|
),
|
|
opsSentinelPriceStaleMs: parseNumber(
|
|
process.env.OPS_SENTINEL_PRICE_STALE_MS,
|
|
DEFAULTS.marketReferenceMaxAgeMs,
|
|
),
|
|
opsSentinelInventoryStaleMs: parseNumber(
|
|
process.env.OPS_SENTINEL_INVENTORY_STALE_MS,
|
|
DEFAULTS.strategyInventoryMaxAgeMs,
|
|
),
|
|
opsSentinelFundingCreditPendingMs: parseNumber(
|
|
process.env.OPS_SENTINEL_FUNDING_CREDIT_PENDING_MS,
|
|
DEFAULTS.opsSentinelFundingCreditPendingMs,
|
|
),
|
|
opsSentinelFundingStuckMs: parseNumber(
|
|
process.env.OPS_SENTINEL_FUNDING_STUCK_MS,
|
|
DEFAULTS.fundingObservationStuckMs,
|
|
),
|
|
opsSentinelIngestMessageStaleMs: parseNumber(
|
|
process.env.OPS_SENTINEL_INGEST_MESSAGE_STALE_MS,
|
|
DEFAULTS.opsSentinelIngestMessageStaleMs,
|
|
),
|
|
opsSentinelIngestQuoteStaleMs: parseNumber(
|
|
process.env.OPS_SENTINEL_INGEST_QUOTE_STALE_MS,
|
|
DEFAULTS.opsSentinelIngestQuoteStaleMs,
|
|
),
|
|
opsSentinelIngestPublishStaleMs: parseNumber(
|
|
process.env.OPS_SENTINEL_INGEST_PUBLISH_STALE_MS,
|
|
DEFAULTS.opsSentinelIngestPublishStaleMs,
|
|
),
|
|
opsSentinelExecutorRelayStaleMs: parseNumber(
|
|
process.env.OPS_SENTINEL_EXECUTOR_RELAY_STALE_MS,
|
|
DEFAULTS.opsSentinelExecutorRelayStaleMs,
|
|
),
|
|
opsSentinelHistoryWriterStaleMs: parseNumber(
|
|
process.env.OPS_SENTINEL_HISTORY_WRITER_STALE_MS,
|
|
DEFAULTS.opsSentinelHistoryWriterStaleMs,
|
|
),
|
|
opsSentinelDashboardSourceDegradedMs: parseNumber(
|
|
process.env.OPS_SENTINEL_DASHBOARD_SOURCE_DEGRADED_MS,
|
|
DEFAULTS.opsSentinelDashboardSourceDegradedMs,
|
|
),
|
|
opsSentinelSelfStaleMs: parseNumber(
|
|
process.env.OPS_SENTINEL_SELF_STALE_MS,
|
|
DEFAULTS.opsSentinelSelfStaleMs,
|
|
),
|
|
opsSentinelAnomalyWindowSize: parseNumber(
|
|
process.env.OPS_SENTINEL_ANOMALY_WINDOW_SIZE,
|
|
DEFAULTS.opsSentinelAnomalyWindowSize,
|
|
),
|
|
opsSentinelAnomalyQuoteRateCollapseRatio: parseNumber(
|
|
process.env.OPS_SENTINEL_ANOMALY_QUOTE_RATE_COLLAPSE_RATIO,
|
|
DEFAULTS.opsSentinelAnomalyQuoteRateCollapseRatio,
|
|
),
|
|
opsSentinelAnomalyReconnectSpikeMultiplier: parseNumber(
|
|
process.env.OPS_SENTINEL_ANOMALY_RECONNECT_SPIKE_MULTIPLIER,
|
|
DEFAULTS.opsSentinelAnomalyReconnectSpikeMultiplier,
|
|
),
|
|
opsSentinelContainmentCooldownMs: parseNumber(
|
|
process.env.OPS_SENTINEL_CONTAINMENT_COOLDOWN_MS,
|
|
DEFAULTS.opsSentinelContainmentCooldownMs,
|
|
),
|
|
opsSentinelAlertWebhookUrl:
|
|
process.env.OPS_SENTINEL_ALERT_WEBHOOK_URL || DEFAULTS.opsSentinelAlertWebhookUrl,
|
|
opsSentinelAlertWebhookTimeoutMs: parseNumber(
|
|
process.env.OPS_SENTINEL_ALERT_WEBHOOK_TIMEOUT_MS,
|
|
DEFAULTS.opsSentinelAlertWebhookTimeoutMs,
|
|
),
|
|
operatorDashboardAuthMode:
|
|
process.env.OPERATOR_DASHBOARD_AUTH_MODE || DEFAULTS.operatorDashboardAuthMode,
|
|
operatorDashboardAuthUsername:
|
|
process.env.OPERATOR_DASHBOARD_AUTH_USERNAME || DEFAULTS.operatorDashboardAuthUsername,
|
|
operatorDashboardAuthPassword:
|
|
process.env.OPERATOR_DASHBOARD_AUTH_PASSWORD || DEFAULTS.operatorDashboardAuthPassword,
|
|
operatorDashboardAuthRealm:
|
|
process.env.OPERATOR_DASHBOARD_AUTH_REALM || DEFAULTS.operatorDashboardAuthRealm,
|
|
operatorDashboardQuoteLimit: parseNumber(
|
|
process.env.OPERATOR_DASHBOARD_QUOTE_LIMIT,
|
|
DEFAULTS.operatorDashboardQuoteLimit,
|
|
),
|
|
operatorDashboardTradePageSize: parseNumber(
|
|
process.env.OPERATOR_DASHBOARD_TRADE_PAGE_SIZE,
|
|
DEFAULTS.operatorDashboardTradePageSize,
|
|
),
|
|
operatorDashboardUpstreamTimeoutMs: parseNumber(
|
|
process.env.OPERATOR_DASHBOARD_UPSTREAM_TIMEOUT_MS,
|
|
DEFAULTS.operatorDashboardUpstreamTimeoutMs,
|
|
),
|
|
nearIntentsStatusServicesUrl:
|
|
process.env.NEAR_INTENTS_STATUS_SERVICES_URL || DEFAULTS.nearIntentsStatusServicesUrl,
|
|
nearIntentsStatusPostsUrl:
|
|
process.env.NEAR_INTENTS_STATUS_POSTS_URL || DEFAULTS.nearIntentsStatusPostsUrl,
|
|
nearIntentsStatusPostEnumsUrl:
|
|
process.env.NEAR_INTENTS_STATUS_POST_ENUMS_URL || DEFAULTS.nearIntentsStatusPostEnumsUrl,
|
|
nearIntentsStatusTimeoutMs: parseNumber(
|
|
process.env.NEAR_INTENTS_STATUS_TIMEOUT_MS,
|
|
DEFAULTS.nearIntentsStatusTimeoutMs,
|
|
),
|
|
nearIntentsStatusPollMs: parseNumber(
|
|
process.env.NEAR_INTENTS_STATUS_POLL_MS,
|
|
DEFAULTS.nearIntentsStatusPollMs,
|
|
),
|
|
notificationNtfyBaseUrl:
|
|
process.env.NOTIFICATION_NTFY_BASE_URL || DEFAULTS.notificationNtfyBaseUrl,
|
|
notificationNtfyTopic:
|
|
process.env.NOTIFICATION_NTFY_TOPIC || DEFAULTS.notificationNtfyTopic,
|
|
notificationNtfyToken:
|
|
process.env.NOTIFICATION_NTFY_TOKEN || DEFAULTS.notificationNtfyToken,
|
|
notificationNtfyTimeoutMs: parseNumber(
|
|
process.env.NOTIFICATION_NTFY_TIMEOUT_MS,
|
|
DEFAULTS.notificationNtfyTimeoutMs,
|
|
),
|
|
};
|
|
}
|