Add Oxlint configuration and integrate linting commands

- Introduced a new `.oxlintrc.json` file to configure Oxlint for code quality checks.
- Updated `package.json` to include linting scripts (`lint` and `lint:fix`) for easier code maintenance.
- Enhanced documentation in `README` files to guide users on running Oxlint checks and applying fixes.
This commit is contained in:
discountry
2026-03-12 22:40:18 +08:00
parent 055bb445a9
commit eb70bab8c5
21 changed files with 95 additions and 46 deletions
+1 -1
View File
@@ -155,7 +155,7 @@ function parseExchangeCommand(
options: Record<string, string | boolean>,
common: CommandCommonOptions & { help?: boolean }
): ParsedCliCommand {
assertAllowedOptions(options, new Set([...GLOBAL_OPTION_NAMES]));
assertAllowedOptions(options, new Set(GLOBAL_OPTION_NAMES));
if (action === "list") return { kind: "exchange-list", ...common };
if (action === "capabilities") return { kind: "exchange-capabilities", ...common };
throw new CommandParseError(`Unsupported exchange action '${action}'`);
+6 -6
View File
@@ -543,7 +543,7 @@ export class AsterSpotRestClient {
}
try {
return JSON.parse(text) as T;
} catch (error) {
} catch {
throw new Error(`[AsterSpotRestClient] 无法解析响应: ${text.slice(0, 200)}`);
}
}
@@ -795,7 +795,7 @@ export class AsterRestClient {
}
try {
return JSON.parse(text) as AsterFuturesExchangeInfo;
} catch (error) {
} catch {
throw new Error(`[AsterRestClient] 无法解析交易规则响应: ${text.slice(0, 200)}`);
}
}
@@ -869,7 +869,7 @@ export class AsterRestClient {
try {
const payload = JSON.parse(text) as any[];
return payload.map((entry) => fromRestKline(entry, interval, upper));
} catch (error) {
} catch {
throw new Error(`[AsterRestClient] 无法解析K线响应: ${text.slice(0, 200)}`);
}
}
@@ -899,7 +899,7 @@ export class AsterRestClient {
const payload = JSON.parse(text) as any;
// The response shape mirrors Binance: { symbol, markPrice, indexPrice, lastFundingRate, nextFundingTime, time }
return payload;
} catch (error) {
} catch {
throw new Error(`[AsterRestClient] 无法解析资金费率响应: ${text.slice(0, 200)}`);
}
}
@@ -942,7 +942,7 @@ export class AsterRestClient {
}
try {
return JSON.parse(text) as T;
} catch (error) {
} catch {
throw new Error(`[AsterRestClient] 无法解析响应: ${text.slice(0, 200)}`);
}
}
@@ -1366,7 +1366,7 @@ export class AsterGateway {
});
}
async ensureInitialized(symbol: string): Promise<void> {
async ensureInitialized(_symbol: string): Promise<void> {
if (this.initialized) return;
if (this.initializing) return this.initializing;
this.initializing = (async () => {
+12 -17
View File
@@ -7,7 +7,6 @@ import ccxt, {
import NodeWebSocket from "ws";
import { sign, utils as edUtils, hashes as edHashes } from "@noble/ed25519";
import { sha512 } from "@noble/hashes/sha512";
import { randomBytes } from "crypto";
import type {
AsterAccountSnapshot,
AsterAccountPosition,
@@ -137,17 +136,16 @@ export class BackpackGateway {
}
private async doInitialize(symbol?: string): Promise<void> {
try {
await this.exchange.loadMarkets();
const requested = (symbol ?? this.symbol).toUpperCase();
const market = this.findMarket(requested);
if (!market) {
throw new Error(`Symbol ${requested} not found in Backpack markets`);
}
this.market = market;
this.marketSymbol = market.symbol;
this.marketId = market.id;
this.isContractMarket = Boolean(market.contract);
await this.exchange.loadMarkets();
const requested = (symbol ?? this.symbol).toUpperCase();
const market = this.findMarket(requested);
if (!market) {
throw new Error(`Symbol ${requested} not found in Backpack markets`);
}
this.market = market;
this.marketSymbol = market.symbol;
this.marketId = market.id;
this.isContractMarket = Boolean(market.contract);
if (process.env.BACKPACK_DEBUG === "1") {
console.debug("[BackpackGateway] marketInfo", {
userSymbol: this.symbol,
@@ -155,10 +153,7 @@ export class BackpackGateway {
marketId: this.marketId,
});
}
this.initialized = true;
} catch (error) {
throw error;
}
this.initialized = true;
}
private findMarket(requested: string): any | null {
@@ -774,7 +769,7 @@ export class BackpackGateway {
void this.resubscribeAllTopics();
};
private handleWsClose = (event: any): void => {
private handleWsClose = (_event: any): void => {
if (this.wsCleanup) {
try {
this.wsCleanup();
-3
View File
@@ -1,9 +1,6 @@
import ccxt, {
type Balances,
type Order as CcxtOrder,
type OrderBook as CcxtOrderBook,
type OHLCV as CcxtOhlcv,
type Ticker as CcxtTicker,
} from "ccxt";
import axios from "axios";
import { createHash } from "crypto";
+1 -1
View File
@@ -1161,7 +1161,7 @@ function mapTicker(response: IApiTickerResponse, symbol: string): AsterTicker |
};
}
function mapKlines(response: IApiCandlestickResponse, symbol: string): AsterKline[] {
function mapKlines(response: IApiCandlestickResponse, _symbol: string): AsterKline[] {
return (response.result ?? []).reverse().map((entry) => ({
openTime: nsToMs(entry.open_time ?? Date.now() * ONE_SECOND_IN_NANOSECONDS),
closeTime: nsToMs(entry.close_time ?? Date.now() * ONE_SECOND_IN_NANOSECONDS),
+1 -4
View File
@@ -16,12 +16,10 @@ import type {
AsterTicker,
CreateOrderParams,
} from "../types";
import { extractMessage } from "../../utils/errors";
import type { OrderSide, OrderType } from "../types";
import { LighterHttpClient } from "./http-client";
import { HttpNonceManager } from "./nonce-manager";
import { LighterSigner, type CreateOrderSignParams } from "./signer";
import { bytesToHex } from "./bytes";
import type {
LighterAccountDetails,
LighterAccountAsset,
@@ -39,7 +37,6 @@ import {
LIGHTER_HOSTS,
LIGHTER_ORDER_TYPE,
LIGHTER_TIME_IN_FORCE,
DEFAULT_ORDER_EXPIRY_PLACEHOLDER,
IMMEDIATE_OR_CANCEL_EXPIRY_PLACEHOLDER,
type LighterEnvironment,
} from "./constants";
@@ -2210,7 +2207,7 @@ function extractJsonRequestId(message: any): string | null {
function tryParseTxInfo(value: string): unknown {
try {
return JSON.parse(value);
} catch (_) {
} catch {
return value;
}
}
+1 -1
View File
@@ -128,7 +128,7 @@ function computeExecutedQty(order: LighterOrder): string {
if (Number.isFinite(initial) && Number.isFinite(remaining)) {
return (initial - remaining).toString();
}
} catch (_) {
} catch {
// fall through
}
}
+1 -1
View File
@@ -1684,7 +1684,7 @@ export class NadoGateway {
try {
const text = typeof data === "string" ? data : data.toString("utf8");
message = JSON.parse(text);
} catch (_error) {
} catch {
return;
}
if (!message || typeof message !== "object") return;
+3 -4
View File
@@ -32,7 +32,7 @@ function loadCcxtPro(): any | null {
// eslint-disable-next-line @typescript-eslint/no-var-requires
const mod = require("ccxt.pro");
return mod?.default ?? mod;
} catch (_error) {
} catch {
return null;
}
}
@@ -571,7 +571,6 @@ export class ParadexGateway {
const market = typeof (this.exchange as any).market === "function"
? (this.exchange as any).market(symbol)
: (this.exchange.markets ?? {})[symbol];
const precisionDigits = Number((market?.precision?.amount ?? market?.amountPrecision));
const limitMin = Number(market?.limits?.amount?.min);
// Only trust explicit exchange min limit; do NOT infer 1 from precision=0
const minAmount = Number.isFinite(limitMin) && limitMin > 0 ? limitMin : undefined;
@@ -593,7 +592,7 @@ export class ParadexGateway {
if (typeof (this.exchange as any).amountToPrecision === "function" && Number.isFinite(Number(amount))) {
amount = Number((this.exchange as any).amountToPrecision(symbol, amount));
}
} catch (_normalizeError) {
} catch {
// Swallow precision normalization errors and let exchange validation surface if any
}
@@ -944,7 +943,7 @@ export class ParadexGateway {
}
}
private updateOrdersFromRemote(open: CcxtOrder[], closed: CcxtOrder[]): void {
private updateOrdersFromRemote(open: CcxtOrder[], _closed: CcxtOrder[]): void {
const nextOpen = new Map<string, AsterOrder>();
for (const order of open) {
-1
View File
@@ -4,7 +4,6 @@ import { App } from "./ui/App";
import { setupGlobalErrorHandlers } from "./runtime-errors";
import { parseCliArgs, printCliHelp } from "./cli/args";
import { startStrategy } from "./cli/strategy-runner";
import { resolveExchangeId } from "./exchanges/create-adapter";
import { CommandParseError, parseCommandArgv, printCommandHelp } from "./cli/command-parser";
import { executeCliCommand, renderCommandPayload } from "./cli/command-executor";
+1 -1
View File
@@ -409,7 +409,7 @@ export class BasisArbEngine {
if (!Number.isFinite(wallet) || !Number.isFinite(available)) continue;
if (Math.abs(wallet) === 0 && Math.abs(available) === 0) continue;
const isTaggedFuturesAsset = /0$/.test(name);
const isTaggedFuturesAsset = name.endsWith("0");
if (isTaggedFuturesAsset) {
futuresBalances.push({ asset: name.replace(/0$/, ""), wallet, available });
continue;
+1 -1
View File
@@ -461,7 +461,7 @@ export class GridEngine {
return false;
}
private async haltGrid(price: number): Promise<void> {
private async haltGrid(_price: number): Promise<void> {
if (!this.running) return;
const reason = this.stopReason ?? "触发网格止损";
this.log("warn", `${reason},开始执行平仓与撤单`);
-1
View File
@@ -3,7 +3,6 @@ import type { ExchangeAdapter } from "../exchanges/adapter";
import type {
AsterAccountSnapshot,
AsterDepth,
AsterKline,
AsterOrder,
AsterTicker,
} from "../exchanges/types";
+1 -2
View File
@@ -422,7 +422,7 @@ export class SwingEngine {
: position.entryPrice * (1 + Math.max(0, this.config.stopLossPct));
const tick = Math.max(1e-9, this.config.priceTick);
const lastPrice = referencePrice ?? Number(this.tickerSnapshot?.lastPrice) ?? null;
const lastPrice = referencePrice;
// Kill-switch (always-on).
const triggerKill =
@@ -621,4 +621,3 @@ export class SwingEngine {
});
}
}
+1 -1
View File
@@ -386,7 +386,7 @@ export class TrendEngine {
private async enforceRateLimitStop(): Promise<void> {
const position = getPosition(this.accountSnapshot, this.config.symbol);
if (Math.abs(position.positionAmt) < 1e-5) return;
const price = this.getReferencePrice() ?? Number(this.tickerSnapshot?.lastPrice) ?? this.lastPrice;
const price = this.getReferencePrice();
if (!Number.isFinite(price) || price == null) return;
const result = await this.handlePositionManagement(position, Number(price));
if (result.closed) {