Feat/support binance (#22)

* add docs

* Add Binance exchange support

- Updated the environment configuration to include Binance as a selectable exchange option.
- Enhanced the README documentation to reflect the addition of Binance.
- Implemented the Binance exchange adapter and integrated it into the existing exchange framework.
- Modified the basis arbitrage strategy to support Binance alongside existing exchanges.
- Added tests to ensure proper functionality and integration of Binance within the trading system.

* Enhance README with detailed Binance exchange configuration

- Added comprehensive instructions for setting up Binance as an exchange option.
- Included environment variable specifications for API keys, market types, and trading symbols.
- Provided examples for both perpetual and spot trading strategies.
- Clarified the use of WebSocket and REST for the Binance adapter.

* Enhance exchange support and testing framework

- Added a new test suite for exchange contracts to ensure consistency and functionality across supported exchanges.
- Refactored exchange ID handling to utilize a centralized list of supported exchanges, improving maintainability.
- Updated CLI argument parsing and help documentation to reflect the new exchange structure.
- Introduced utility functions for validating supported exchanges and their display names.
- Enhanced the BasisApp and strategy runner to leverage the new exchange validation logic.
- Added a new test command for running exchange-related tests.

* Refactor exchange contract tests and update CLI commands

- Removed the trailing supported exchanges set and simplified the logic for trailing stop support in the exchange contract tests.
- Updated the test command for exchange contracts to exclude unnecessary tests, streamlining the testing process.
- Enhanced test descriptions for clarity and improved understanding of the functionality being tested.
This commit is contained in:
Disney
2026-02-27 11:37:44 +08:00
committed by GitHub
parent 422ee6f465
commit d6399b92aa
588 changed files with 96879 additions and 106 deletions
+56 -30
View File
@@ -6,6 +6,7 @@ import type { BackpackCredentials } from "./backpack/adapter";
import type { ParadexCredentials } from "./paradex/adapter";
import type { NadoCredentials } from "./nado/adapter";
import type { StandxCredentials } from "./standx/adapter";
import type { BinanceCredentials } from "./binance/adapter";
import { t } from "../i18n";
import type { Address } from "viem";
@@ -18,37 +19,38 @@ export function buildAdapterFromEnv(options: BuildAdapterOptions): ExchangeAdapt
const id = resolveExchangeId(options.exchangeId);
const symbol = options.symbol;
if (id === "aster") {
const credentials = resolveAsterCredentials();
return createExchangeAdapter({ exchange: id, symbol, aster: credentials });
switch (id) {
case "aster": {
const credentials = resolveAsterCredentials();
return createExchangeAdapter({ exchange: id, symbol, aster: credentials });
}
case "grvt":
return createExchangeAdapter({ exchange: id, symbol, grvt: { symbol } });
case "lighter": {
const credentials = resolveLighterCredentials(symbol);
return createExchangeAdapter({ exchange: id, symbol, lighter: credentials });
}
case "backpack": {
const credentials = resolveBackpackCredentials(symbol);
return createExchangeAdapter({ exchange: id, symbol, backpack: credentials });
}
case "paradex": {
const credentials = resolveParadexCredentials();
return createExchangeAdapter({ exchange: id, symbol, paradex: credentials });
}
case "nado": {
const credentials = resolveNadoCredentials(symbol);
return createExchangeAdapter({ exchange: id, symbol, nado: credentials });
}
case "standx": {
const credentials = resolveStandxCredentials(symbol);
return createExchangeAdapter({ exchange: id, symbol, standx: credentials });
}
case "binance": {
const credentials = resolveBinanceCredentials(symbol);
return createExchangeAdapter({ exchange: id, symbol, binance: credentials });
}
}
if (id === "lighter") {
const credentials = resolveLighterCredentials(symbol);
return createExchangeAdapter({ exchange: id, symbol, lighter: credentials });
}
if (id === "backpack") {
const credentials = resolveBackpackCredentials(symbol);
return createExchangeAdapter({ exchange: id, symbol, backpack: credentials });
}
if (id === "paradex") {
const credentials = resolveParadexCredentials();
return createExchangeAdapter({ exchange: id, symbol, paradex: credentials });
}
if (id === "nado") {
const credentials = resolveNadoCredentials(symbol);
return createExchangeAdapter({ exchange: id, symbol, nado: credentials });
}
if (id === "standx") {
const credentials = resolveStandxCredentials(symbol);
return createExchangeAdapter({ exchange: id, symbol, standx: credentials });
}
return createExchangeAdapter({ exchange: id, symbol, grvt: { symbol } });
}
function resolveAsterCredentials(): AsterCredentials {
@@ -174,6 +176,30 @@ function resolveStandxCredentials(symbol: string): StandxCredentials {
};
}
function resolveBinanceCredentials(symbol: string): BinanceCredentials {
const apiKey = process.env.BINANCE_API_KEY;
const apiSecret = process.env.BINANCE_API_SECRET;
if (!apiKey || !apiSecret) {
throw new Error("Missing BINANCE_API_KEY or BINANCE_API_SECRET environment variable");
}
const marketTypeRaw = process.env.BINANCE_MARKET_TYPE?.trim().toLowerCase();
const marketType: BinanceCredentials["marketType"] =
marketTypeRaw === "spot" ? "spot" : marketTypeRaw === "auto" ? "auto" : "perp";
return {
apiKey,
apiSecret,
symbol: process.env.BINANCE_SYMBOL ?? symbol,
marketType,
sandbox: parseOptionalBoolean(process.env.BINANCE_SANDBOX),
spotRestUrl: process.env.BINANCE_SPOT_REST_URL ?? undefined,
futuresRestUrl: process.env.BINANCE_FUTURES_REST_URL ?? undefined,
spotWsUrl: process.env.BINANCE_SPOT_WS_URL ?? undefined,
futuresWsUrl: process.env.BINANCE_FUTURES_WS_URL ?? undefined,
};
}
function isHex32(value: string): boolean {
return /^0x[0-9a-fA-F]{64}$/.test(value.trim());
}