@pear-protocol/exchanges-sdk 0.0.12 → 0.0.14

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.
Files changed (50) hide show
  1. package/README.md +6 -0
  2. package/dist/account/account-manager.d.ts +2 -1
  3. package/dist/account/exchange-account.d.ts +2 -1
  4. package/dist/account/exchanges/base.d.ts +2 -1
  5. package/dist/account/exchanges/binance/asset-tracker.d.ts +2 -1
  6. package/dist/account/exchanges/binance/asset-tracker.js +1 -1
  7. package/dist/account/exchanges/binance/mapper.d.ts +2 -1
  8. package/dist/account/exchanges/binance/orchestrator.d.ts +2 -1
  9. package/dist/account/exchanges/binance/rest.d.ts +2 -1
  10. package/dist/account/exchanges/binance/state-handler.d.ts +2 -1
  11. package/dist/account/exchanges/binance/state-handler.js +1 -1
  12. package/dist/account/exchanges/binance/types.d.ts +2 -1
  13. package/dist/account/exchanges/binance/ws.d.ts +2 -1
  14. package/dist/account/exchanges/bybit/asset-tracker.d.ts +2 -1
  15. package/dist/account/exchanges/bybit/asset-tracker.js +2 -1
  16. package/dist/account/exchanges/bybit/mapper.d.ts +2 -1
  17. package/dist/account/exchanges/bybit/orchestrator.d.ts +2 -1
  18. package/dist/account/exchanges/bybit/state-handler.d.ts +2 -1
  19. package/dist/account/exchanges/hyperliquid/asset-tracker.d.ts +2 -1
  20. package/dist/account/exchanges/hyperliquid/mapper.d.ts +2 -1
  21. package/dist/account/exchanges/hyperliquid/orchestrator.d.ts +2 -1
  22. package/dist/account/exchanges/hyperliquid/state-handler.d.ts +2 -1
  23. package/dist/account/exchanges/hyperliquid/state-handler.js +1 -1
  24. package/dist/account/exchanges/index.d.ts +3 -2
  25. package/dist/account/exchanges/index.js +5 -0
  26. package/dist/account/exchanges/okx/asset-tracker.d.ts +26 -0
  27. package/dist/account/exchanges/okx/asset-tracker.js +34 -0
  28. package/dist/account/exchanges/okx/const.d.ts +7 -0
  29. package/dist/account/exchanges/okx/const.js +7 -0
  30. package/dist/account/exchanges/okx/mapper.d.ts +14 -0
  31. package/dist/account/exchanges/okx/mapper.js +116 -0
  32. package/dist/account/exchanges/okx/orchestrator.d.ts +22 -0
  33. package/dist/account/exchanges/okx/orchestrator.js +57 -0
  34. package/dist/account/exchanges/okx/rest.d.ts +9 -0
  35. package/dist/account/exchanges/okx/rest.js +57 -0
  36. package/dist/account/exchanges/okx/state-handler.d.ts +24 -0
  37. package/dist/account/exchanges/okx/state-handler.js +78 -0
  38. package/dist/account/exchanges/okx/types.d.ts +69 -0
  39. package/dist/account/exchanges/okx/types.js +9 -0
  40. package/dist/account/exchanges/okx/ws.d.ts +20 -0
  41. package/dist/account/exchanges/okx/ws.js +103 -0
  42. package/dist/account/index.d.ts +2 -1
  43. package/dist/account/types.d.ts +2 -1
  44. package/dist/account/types.js +6 -1
  45. package/dist/account/utils.d.ts +2 -1
  46. package/dist/index.d.ts +2 -1
  47. package/dist/{types-D2dbAtin.d.ts → types-Caz2X4h0.d.ts} +4 -3
  48. package/dist/utils/hmac.d.ts +2 -1
  49. package/dist/utils/hmac.js +13 -3
  50. package/package.json +4 -4
package/README.md CHANGED
@@ -9,6 +9,7 @@ Unified SDK for connecting to cryptocurrency derivative exchanges. Provides real
9
9
  | Binance | `binance` | USDM Futures |
10
10
  | Bybit | `bybit` | Linear Perpetuals |
11
11
  | Hyperliquid | `hyperliquid` | Perpetuals |
12
+ | OKX | `okx` | Linear SWAP Perpetuals |
12
13
 
13
14
  ## Installation
14
15
 
@@ -152,6 +153,11 @@ const current = tracker.get();
152
153
  tracker.untrack();
153
154
  ```
154
155
 
156
+ > **Symbol format per exchange:** `trackAsset` takes the exchange's native symbol:
157
+ > - Binance / Bybit: `BTCUSDT`
158
+ > - Hyperliquid: `BTC`
159
+ > - OKX: `BTC-USDT-SWAP`
160
+
155
161
  ### Managing Leverage
156
162
 
157
163
  ```typescript
@@ -1,9 +1,10 @@
1
1
  import PearSDK from '@pear-protocol/core-sdk';
2
2
  import { Connector } from '@pear-protocol/types';
3
3
  import { Credentials } from '../credentials.js';
4
- import { B as BalanceCallback, i as Tracker, a as AccountBalance, P as PositionsCallback, c as AccountPosition, T as TrackedAssetCallback, h as TrackedAssetInfo } from '../types-D2dbAtin.js';
4
+ import { B as BalanceCallback, i as Tracker, a as AccountBalance, P as PositionsCallback, c as AccountPosition, T as TrackedAssetCallback, h as TrackedAssetInfo } from '../types-Caz2X4h0.js';
5
5
  import './exchanges/bybit/types.js';
6
6
  import './exchanges/hyperliquid/types.js';
7
+ import './exchanges/okx/types.js';
7
8
 
8
9
  declare class AccountManager {
9
10
  private credentials;
@@ -1,7 +1,8 @@
1
- import { b as AccountConfig, g as SupportedCredentials, B as BalanceCallback, a as AccountBalance, P as PositionsCallback, c as AccountPosition, T as TrackedAssetCallback, h as TrackedAssetInfo } from '../types-D2dbAtin.js';
1
+ import { b as AccountConfig, g as SupportedCredentials, B as BalanceCallback, a as AccountBalance, P as PositionsCallback, c as AccountPosition, T as TrackedAssetCallback, h as TrackedAssetInfo } from '../types-Caz2X4h0.js';
2
2
  import '@pear-protocol/types';
3
3
  import './exchanges/bybit/types.js';
4
4
  import './exchanges/hyperliquid/types.js';
5
+ import './exchanges/okx/types.js';
5
6
 
6
7
  declare class ExchangeAccount {
7
8
  private exchange;
@@ -1,7 +1,8 @@
1
- import { S as StateUpdate, g as SupportedCredentials } from '../../types-D2dbAtin.js';
1
+ import { S as StateUpdate, g as SupportedCredentials } from '../../types-Caz2X4h0.js';
2
2
  import '@pear-protocol/types';
3
3
  import './bybit/types.js';
4
4
  import './hyperliquid/types.js';
5
+ import './okx/types.js';
5
6
 
6
7
  type StateUpdateHandler = (update: StateUpdate) => void;
7
8
  type ErrorHandler = (error: Error) => void;
@@ -1,7 +1,8 @@
1
1
  import { BinanceCredentialsDTO } from '@pear-protocol/types';
2
- import { S as StateUpdate, h as TrackedAssetInfo } from '../../../types-D2dbAtin.js';
2
+ import { S as StateUpdate, h as TrackedAssetInfo } from '../../../types-Caz2X4h0.js';
3
3
  import '../bybit/types.js';
4
4
  import '../hyperliquid/types.js';
5
+ import '../okx/types.js';
5
6
 
6
7
  type OnStateUpdate = (update: StateUpdate) => void;
7
8
  type OnError = (error: Error) => void;
@@ -19,7 +19,7 @@ class BinanceAssetTracker {
19
19
  fetchPositionRisk(this.getCreds(), coin, this.getDemo()).then((risk) => {
20
20
  if (!risk) return;
21
21
  const leverage = risk.leverage;
22
- const marginType = risk.marginType === "isolated" ? "isolated" : "cross";
22
+ const marginType = risk.marginType;
23
23
  const info = { coin, leverage, marginType };
24
24
  this.trackedAssetInfos.set(coin, info);
25
25
  const trackedAssets = /* @__PURE__ */ new Map();
@@ -1,7 +1,8 @@
1
- import { j as BinanceRawAccountStatus, a as AccountBalance, k as BinanceRawPositionRisk, c as AccountPosition } from '../../../types-D2dbAtin.js';
1
+ import { j as BinanceRawAccountStatus, a as AccountBalance, k as BinanceRawPositionRisk, c as AccountPosition } from '../../../types-Caz2X4h0.js';
2
2
  import '@pear-protocol/types';
3
3
  import '../bybit/types.js';
4
4
  import '../hyperliquid/types.js';
5
+ import '../okx/types.js';
5
6
 
6
7
  declare function mapBalance(raw: BinanceRawAccountStatus): Omit<AccountBalance, 'accountType'>;
7
8
  declare function mapPositions(raw: BinanceRawPositionRisk[]): Map<string, AccountPosition>;
@@ -1,8 +1,9 @@
1
- import { g as SupportedCredentials } from '../../../types-D2dbAtin.js';
1
+ import { g as SupportedCredentials } from '../../../types-Caz2X4h0.js';
2
2
  import { BaseOrchestrator, OrchestratorConfig } from '../base.js';
3
3
  import '@pear-protocol/types';
4
4
  import '../bybit/types.js';
5
5
  import '../hyperliquid/types.js';
6
+ import '../okx/types.js';
6
7
 
7
8
  type BinanceOrchestratorConfig = OrchestratorConfig & {
8
9
  listenKeyRefreshMs?: number;
@@ -1,7 +1,8 @@
1
1
  import { BinanceCredentialsDTO } from '@pear-protocol/types';
2
- import { j as BinanceRawAccountStatus, k as BinanceRawPositionRisk, l as BinanceAssetIndex } from '../../../types-D2dbAtin.js';
2
+ import { j as BinanceRawAccountStatus, k as BinanceRawPositionRisk, l as BinanceAssetIndex } from '../../../types-Caz2X4h0.js';
3
3
  import '../bybit/types.js';
4
4
  import '../hyperliquid/types.js';
5
+ import '../okx/types.js';
5
6
 
6
7
  declare function createListenKey(apiKey: string, demo?: boolean): Promise<string>;
7
8
  declare function keepAliveListenKey(apiKey: string, demo?: boolean): Promise<void>;
@@ -1,7 +1,8 @@
1
1
  import { BinanceCredentialsDTO } from '@pear-protocol/types';
2
- import { S as StateUpdate, h as TrackedAssetInfo, j as BinanceRawAccountStatus, k as BinanceRawPositionRisk, m as BinanceRawUserDataEvent } from '../../../types-D2dbAtin.js';
2
+ import { S as StateUpdate, h as TrackedAssetInfo, j as BinanceRawAccountStatus, k as BinanceRawPositionRisk, m as BinanceRawUserDataEvent } from '../../../types-Caz2X4h0.js';
3
3
  import '../bybit/types.js';
4
4
  import '../hyperliquid/types.js';
5
+ import '../okx/types.js';
5
6
 
6
7
  type OnStateUpdate = (update: StateUpdate) => void;
7
8
  type OnError = (error: Error) => void;
@@ -93,7 +93,7 @@ class BinanceStateHandler {
93
93
  entryPrice: risk.entryPrice ?? "0",
94
94
  unrealizedPnl: risk.unRealizedProfit ?? "0",
95
95
  leverage: risk.leverage ?? "0",
96
- marginType: risk.marginType === "isolated" ? "isolated" : "cross",
96
+ marginType: risk.marginType,
97
97
  liquidationPrice: risk.liquidationPrice || null
98
98
  });
99
99
  }
@@ -1,4 +1,5 @@
1
- export { f as BinanceAccountType, l as BinanceAssetIndex, o as BinanceMultiAssetsMarginResponse, j as BinanceRawAccountStatus, p as BinanceRawAsset, k as BinanceRawPositionRisk, m as BinanceRawUserDataEvent, n as BinanceWsHandlers } from '../../../types-D2dbAtin.js';
1
+ export { f as BinanceAccountType, l as BinanceAssetIndex, o as BinanceMultiAssetsMarginResponse, j as BinanceRawAccountStatus, p as BinanceRawAsset, k as BinanceRawPositionRisk, m as BinanceRawUserDataEvent, n as BinanceWsHandlers } from '../../../types-Caz2X4h0.js';
2
2
  import '@pear-protocol/types';
3
3
  import '../bybit/types.js';
4
4
  import '../hyperliquid/types.js';
5
+ import '../okx/types.js';
@@ -1,7 +1,8 @@
1
1
  import { BinanceCredentialsDTO } from '@pear-protocol/types';
2
- import { n as BinanceWsHandlers } from '../../../types-D2dbAtin.js';
2
+ import { n as BinanceWsHandlers } from '../../../types-Caz2X4h0.js';
3
3
  import '../bybit/types.js';
4
4
  import '../hyperliquid/types.js';
5
+ import '../okx/types.js';
5
6
 
6
7
  declare class BinanceWs {
7
8
  private userDataWs;
@@ -1,7 +1,8 @@
1
1
  import { BybitCredentialsDTO } from '@pear-protocol/types';
2
- import { S as StateUpdate, h as TrackedAssetInfo } from '../../../types-D2dbAtin.js';
2
+ import { S as StateUpdate, h as TrackedAssetInfo } from '../../../types-Caz2X4h0.js';
3
3
  import './types.js';
4
4
  import '../hyperliquid/types.js';
5
+ import '../okx/types.js';
5
6
 
6
7
  type OnStateUpdate = (update: StateUpdate) => void;
7
8
  type OnError = (error: Error) => void;
@@ -1,3 +1,4 @@
1
+ import '@pear-protocol/types';
1
2
  import { fetchPositionLeverage } from './rest';
2
3
 
3
4
  class BybitAssetTracker {
@@ -18,7 +19,7 @@ class BybitAssetTracker {
18
19
  onAssetTracked(coin) {
19
20
  fetchPositionLeverage(this.getCreds(), coin, this.getDemo()).then((pos) => {
20
21
  const leverage = pos?.leverage || "1";
21
- const marginType = pos?.tradeMode === "1" ? "isolated" : "cross";
22
+ const marginType = pos?.tradeMode === "1" ? "cross" : "isolated";
22
23
  const info = { coin, leverage, marginType };
23
24
  this.trackedAssetInfos.set(coin, info);
24
25
  const trackedAssets = /* @__PURE__ */ new Map();
@@ -1,7 +1,8 @@
1
- import { a as AccountBalance, c as AccountPosition } from '../../../types-D2dbAtin.js';
1
+ import { a as AccountBalance, c as AccountPosition } from '../../../types-Caz2X4h0.js';
2
2
  import { BybitRawWallet, BybitRawCoin, BybitAccountType, BybitRawPosition } from './types.js';
3
3
  import '@pear-protocol/types';
4
4
  import '../hyperliquid/types.js';
5
+ import '../okx/types.js';
5
6
 
6
7
  declare function buildBalance(raw: BybitRawWallet, coins: Map<string, BybitRawCoin>, accountType: BybitAccountType | null): AccountBalance | null;
7
8
  declare function mergeRawCoins(existing: Map<string, BybitRawCoin>, incoming: BybitRawCoin[]): Map<string, BybitRawCoin>;
@@ -1,8 +1,9 @@
1
- import { g as SupportedCredentials } from '../../../types-D2dbAtin.js';
1
+ import { g as SupportedCredentials } from '../../../types-Caz2X4h0.js';
2
2
  import { BaseOrchestrator, OrchestratorConfig } from '../base.js';
3
3
  import '@pear-protocol/types';
4
4
  import './types.js';
5
5
  import '../hyperliquid/types.js';
6
+ import '../okx/types.js';
6
7
 
7
8
  declare class BybitOrchestrator extends BaseOrchestrator {
8
9
  private ws;
@@ -1,7 +1,8 @@
1
- import { S as StateUpdate, h as TrackedAssetInfo } from '../../../types-D2dbAtin.js';
1
+ import { S as StateUpdate, h as TrackedAssetInfo } from '../../../types-Caz2X4h0.js';
2
2
  import { BybitRawWallet, BybitRawPosition, BybitAccountType, BybitWsMessage } from './types.js';
3
3
  import '@pear-protocol/types';
4
4
  import '../hyperliquid/types.js';
5
+ import '../okx/types.js';
5
6
 
6
7
  type OnStateUpdate = (update: StateUpdate) => void;
7
8
  declare class BybitStateHandler {
@@ -1,8 +1,9 @@
1
- import { S as StateUpdate } from '../../../types-D2dbAtin.js';
1
+ import { S as StateUpdate } from '../../../types-Caz2X4h0.js';
2
2
  import { WebSocket } from 'partysocket';
3
3
  import { ActiveAssetDataEvent } from './types.js';
4
4
  import '@pear-protocol/types';
5
5
  import '../bybit/types.js';
6
+ import '../okx/types.js';
6
7
 
7
8
  type OnStateUpdate = (update: StateUpdate) => void;
8
9
  type OnActiveAssetData = (data: ActiveAssetDataEvent) => void;
@@ -1,7 +1,8 @@
1
- import { a as AccountBalance, c as AccountPosition } from '../../../types-D2dbAtin.js';
1
+ import { a as AccountBalance, c as AccountPosition } from '../../../types-Caz2X4h0.js';
2
2
  import { AggregatedClearinghouseSummary, HyperliquidCoinBalance, HyperliquidAccountType, AssetPosition } from './types.js';
3
3
  import '@pear-protocol/types';
4
4
  import '../bybit/types.js';
5
+ import '../okx/types.js';
5
6
 
6
7
  declare function mapBalance(summary: AggregatedClearinghouseSummary, spotCoinBalances: Map<string, HyperliquidCoinBalance>, accountType: HyperliquidAccountType | null, availableToTradeByCollateral: Map<string, number>): AccountBalance | null;
7
8
  declare function mapPositions(raw: AssetPosition[]): Map<string, AccountPosition>;
@@ -1,8 +1,9 @@
1
- import { g as SupportedCredentials } from '../../../types-D2dbAtin.js';
1
+ import { g as SupportedCredentials } from '../../../types-Caz2X4h0.js';
2
2
  import { BaseOrchestrator, OrchestratorConfig } from '../base.js';
3
3
  import '@pear-protocol/types';
4
4
  import '../bybit/types.js';
5
5
  import './types.js';
6
+ import '../okx/types.js';
6
7
 
7
8
  declare class HyperliquidOrchestrator extends BaseOrchestrator {
8
9
  private ws;
@@ -1,7 +1,8 @@
1
- import { S as StateUpdate, h as TrackedAssetInfo } from '../../../types-D2dbAtin.js';
1
+ import { S as StateUpdate, h as TrackedAssetInfo } from '../../../types-Caz2X4h0.js';
2
2
  import { AllPerpMetasResponse, AllDexsClearinghouseStateEvent, ActiveAssetDataEvent, WebData3Event, SpotStateEvent } from './types.js';
3
3
  import '@pear-protocol/types';
4
4
  import '../bybit/types.js';
5
+ import '../okx/types.js';
5
6
 
6
7
  type OnStateUpdate = (update: StateUpdate) => void;
7
8
  declare class HyperliquidStateHandler {
@@ -97,7 +97,7 @@ function buildTrackedAssetInfo(data) {
97
97
  return {
98
98
  coin: data.coin,
99
99
  leverage: (data.leverage?.value ?? 1).toString(),
100
- marginType: data.leverage?.type === "isolated" ? "isolated" : "cross"
100
+ marginType: data.leverage?.type
101
101
  };
102
102
  }
103
103
 
@@ -1,9 +1,10 @@
1
1
  import { Connector } from '@pear-protocol/types';
2
+ import { g as SupportedCredentials } from '../../types-Caz2X4h0.js';
3
+ export { f as BinanceAccountType } from '../../types-Caz2X4h0.js';
2
4
  import { OrchestratorConfig, Orchestrator } from './base.js';
3
- import { g as SupportedCredentials } from '../../types-D2dbAtin.js';
4
- export { f as BinanceAccountType } from '../../types-D2dbAtin.js';
5
5
  export { BybitAccountType } from './bybit/types.js';
6
6
  export { HyperliquidAccountType } from './hyperliquid/types.js';
7
+ export { OkxAccountType } from './okx/types.js';
7
8
 
8
9
  declare function createOrchestrator(exchange: Connector, config: OrchestratorConfig, credentials: SupportedCredentials): Orchestrator;
9
10
 
@@ -2,9 +2,11 @@ import './base';
2
2
  import { BinanceOrchestrator } from './binance/orchestrator';
3
3
  import { BybitOrchestrator } from './bybit/orchestrator';
4
4
  import { HyperliquidOrchestrator } from './hyperliquid/orchestrator';
5
+ import { OkxOrchestrator } from './okx/orchestrator';
5
6
  export { BinanceAccountType } from './binance/types';
6
7
  export { BybitAccountType } from './bybit/types';
7
8
  export { HyperliquidAccountType } from './hyperliquid/types';
9
+ export { OkxAccountType } from './okx/types';
8
10
 
9
11
  function createOrchestrator(exchange, config, credentials) {
10
12
  let orchestrator;
@@ -18,6 +20,9 @@ function createOrchestrator(exchange, config, credentials) {
18
20
  case "hyperliquid":
19
21
  orchestrator = new HyperliquidOrchestrator(config, credentials);
20
22
  break;
23
+ case "okx":
24
+ orchestrator = new OkxOrchestrator(config, credentials);
25
+ break;
21
26
  default:
22
27
  throw new Error(`Unsupported exchange: ${exchange}`);
23
28
  }
@@ -0,0 +1,26 @@
1
+ import { OkxCredentialsDTO } from '@pear-protocol/types';
2
+ import { S as StateUpdate, h as TrackedAssetInfo } from '../../../types-Caz2X4h0.js';
3
+ import '../bybit/types.js';
4
+ import '../hyperliquid/types.js';
5
+ import './types.js';
6
+
7
+ type OnStateUpdate = (update: StateUpdate) => void;
8
+ type OnError = (error: Error) => void;
9
+ declare class OkxAssetTracker {
10
+ private onStateUpdate;
11
+ private onError;
12
+ private getCreds;
13
+ private getDemo;
14
+ private trackedAssetInfos;
15
+ constructor(deps: {
16
+ onStateUpdate: OnStateUpdate;
17
+ onError: OnError;
18
+ getCreds: () => OkxCredentialsDTO;
19
+ getDemo: () => boolean;
20
+ });
21
+ getInfos(): Map<string, TrackedAssetInfo>;
22
+ onAssetTracked(instId: string): void;
23
+ onAssetUntracked(instId: string): void;
24
+ }
25
+
26
+ export { OkxAssetTracker };
@@ -0,0 +1,34 @@
1
+ import { fetchLeverageInfo } from './rest';
2
+
3
+ class OkxAssetTracker {
4
+ onStateUpdate;
5
+ onError;
6
+ getCreds;
7
+ getDemo;
8
+ trackedAssetInfos = /* @__PURE__ */ new Map();
9
+ constructor(deps) {
10
+ this.onStateUpdate = deps.onStateUpdate;
11
+ this.onError = deps.onError;
12
+ this.getCreds = deps.getCreds;
13
+ this.getDemo = deps.getDemo;
14
+ }
15
+ getInfos() {
16
+ return this.trackedAssetInfos;
17
+ }
18
+ onAssetTracked(instId) {
19
+ fetchLeverageInfo(this.getCreds(), instId, this.getDemo()).then((info) => {
20
+ const leverage = info?.lever || "0";
21
+ const marginType = info?.mgnMode;
22
+ const trackedAssetInfo = { coin: instId, leverage, marginType };
23
+ this.trackedAssetInfos.set(instId, trackedAssetInfo);
24
+ const trackedAssets = /* @__PURE__ */ new Map([[instId, trackedAssetInfo]]);
25
+ this.onStateUpdate({ trackedAssets });
26
+ }).catch((err) => this.onError(err instanceof Error ? err : new Error(String(err))));
27
+ }
28
+ onAssetUntracked(instId) {
29
+ this.trackedAssetInfos.delete(instId);
30
+ this.onStateUpdate({ trackedAssets: new Map(this.trackedAssetInfos) });
31
+ }
32
+ }
33
+
34
+ export { OkxAssetTracker };
@@ -0,0 +1,7 @@
1
+ declare const REST_BASE_URL = "https://www.okx.com";
2
+ declare const WS_PRIVATE_URL = "wss://ws.okx.com:8443/ws/v5/private";
3
+ declare const WS_PRIVATE_URL_DEMO = "wss://wspap.okx.com:8443/ws/v5/private?brokerId=9999";
4
+ declare const DEFAULT_PING_INTERVAL_MS = 25000;
5
+ declare const LOGIN_TIMEOUT_MS = 10000;
6
+
7
+ export { DEFAULT_PING_INTERVAL_MS, LOGIN_TIMEOUT_MS, REST_BASE_URL, WS_PRIVATE_URL, WS_PRIVATE_URL_DEMO };
@@ -0,0 +1,7 @@
1
+ const REST_BASE_URL = "https://www.okx.com";
2
+ const WS_PRIVATE_URL = "wss://ws.okx.com:8443/ws/v5/private";
3
+ const WS_PRIVATE_URL_DEMO = "wss://wspap.okx.com:8443/ws/v5/private?brokerId=9999";
4
+ const DEFAULT_PING_INTERVAL_MS = 25e3;
5
+ const LOGIN_TIMEOUT_MS = 1e4;
6
+
7
+ export { DEFAULT_PING_INTERVAL_MS, LOGIN_TIMEOUT_MS, REST_BASE_URL, WS_PRIVATE_URL, WS_PRIVATE_URL_DEMO };
@@ -0,0 +1,14 @@
1
+ import { a as AccountBalance, c as AccountPosition } from '../../../types-Caz2X4h0.js';
2
+ import { OkxAccountType, OkxRawBalance, OkxRawBalanceDetail, OkxRawPosition } from './types.js';
3
+ import '@pear-protocol/types';
4
+ import '../bybit/types.js';
5
+ import '../hyperliquid/types.js';
6
+
7
+ declare function mergeRawCoins(existing: Map<string, OkxRawBalanceDetail>, incoming: OkxRawBalanceDetail[]): Map<string, OkxRawBalanceDetail>;
8
+ declare function buildBalance(raw: OkxRawBalance, coins: Map<string, OkxRawBalanceDetail>, accountType: OkxAccountType | null): AccountBalance | null;
9
+ declare function mapSinglePosition(p: OkxRawPosition): AccountPosition;
10
+ declare function mapPositions(raw: OkxRawPosition[]): Map<string, AccountPosition>;
11
+ declare function mapPositionUpdates(raw: OkxRawPosition[]): Map<string, AccountPosition>;
12
+ declare function acctLvToAccountType(acctLv: string): OkxAccountType | null;
13
+
14
+ export { acctLvToAccountType, buildBalance, mapPositionUpdates, mapPositions, mapSinglePosition, mergeRawCoins };
@@ -0,0 +1,116 @@
1
+ import { positionKey } from '../../utils';
2
+ import { OkxAccountType } from './types';
3
+
4
+ function mergeRawCoins(existing, incoming) {
5
+ const merged = new Map(existing);
6
+ for (const d of incoming) {
7
+ merged.set(d.ccy, d);
8
+ }
9
+ return merged;
10
+ }
11
+ function buildBalance(raw, coins, accountType) {
12
+ if (!accountType) return null;
13
+ const isSpot = accountType === OkxAccountType.SPOT;
14
+ const free = {};
15
+ const used = {};
16
+ const total = {};
17
+ const assets = [];
18
+ let walletBalanceSum = 0;
19
+ for (const [, d] of coins) {
20
+ const eq = d.eq ?? "0";
21
+ const eqNum = parseFloat(eq);
22
+ const cashNum = parseFloat(d.cashBal ?? "0");
23
+ if (eqNum === 0 && cashNum === 0) continue;
24
+ const coinFree = isSpot ? d.availBal ?? "0" : d.availEq || d.availBal || "0";
25
+ const coinUsed = (eqNum - parseFloat(coinFree)).toString();
26
+ free[d.ccy] = coinFree;
27
+ used[d.ccy] = coinUsed;
28
+ total[d.ccy] = eq;
29
+ walletBalanceSum += cashNum;
30
+ assets.push({
31
+ asset: d.ccy,
32
+ free: coinFree,
33
+ used: coinUsed,
34
+ total: eq,
35
+ walletBalance: d.cashBal ?? "0",
36
+ usdValue: d.eqUsd ?? "0"
37
+ });
38
+ }
39
+ const availableToTrade = raw.availEq || raw.adjEq || "0";
40
+ return {
41
+ accountType,
42
+ free,
43
+ used,
44
+ total,
45
+ availableToTrade,
46
+ totalEquity: raw.totalEq ?? "0",
47
+ walletBalance: walletBalanceSum.toString(),
48
+ unrealizedPnl: raw.upl || "0",
49
+ initialMarginUsed: raw.imr || "0",
50
+ maintenanceMargin: raw.mmr || "0",
51
+ marginRatio: raw.mgnRatio || "0.0000",
52
+ assets,
53
+ timestamp: Date.now()
54
+ };
55
+ }
56
+ function mapSinglePosition(p) {
57
+ const posNum = parseFloat(p.pos ?? "0");
58
+ let side;
59
+ if (p.posSide === "long") side = "long";
60
+ else if (p.posSide === "short") side = "short";
61
+ else side = posNum < 0 ? "short" : "long";
62
+ const rawSize = p.pos ?? "0";
63
+ let size;
64
+ if (rawSize === "0" || rawSize === "") {
65
+ size = "0";
66
+ } else if (side === "short" && !rawSize.startsWith("-")) {
67
+ size = `-${rawSize}`;
68
+ } else {
69
+ size = rawSize;
70
+ }
71
+ const marginType = p.mgnMode;
72
+ return {
73
+ symbol: p.instId ?? "",
74
+ side,
75
+ size,
76
+ entryPrice: p.avgPx ?? "0",
77
+ unrealizedPnl: p.upl ?? "0",
78
+ leverage: p.lever ?? "0",
79
+ marginType,
80
+ liquidationPrice: p.liqPx || null
81
+ };
82
+ }
83
+ function mapPositions(raw) {
84
+ const positions = /* @__PURE__ */ new Map();
85
+ for (const p of raw) {
86
+ const pos = p.pos ?? "0";
87
+ if (pos === "0" || pos === "") continue;
88
+ const mapped = mapSinglePosition(p);
89
+ positions.set(positionKey(mapped.symbol, mapped.side), mapped);
90
+ }
91
+ return positions;
92
+ }
93
+ function mapPositionUpdates(raw) {
94
+ const positions = /* @__PURE__ */ new Map();
95
+ for (const p of raw) {
96
+ const mapped = mapSinglePosition(p);
97
+ positions.set(positionKey(mapped.symbol, mapped.side), mapped);
98
+ }
99
+ return positions;
100
+ }
101
+ function acctLvToAccountType(acctLv) {
102
+ switch (acctLv) {
103
+ case "1":
104
+ return OkxAccountType.SPOT;
105
+ case "2":
106
+ return OkxAccountType.SINGLE_CURRENCY_MARGIN;
107
+ case "3":
108
+ return OkxAccountType.MULTI_CURRENCY_MARGIN;
109
+ case "4":
110
+ return OkxAccountType.PORTFOLIO_MARGIN;
111
+ default:
112
+ return null;
113
+ }
114
+ }
115
+
116
+ export { acctLvToAccountType, buildBalance, mapPositionUpdates, mapPositions, mapSinglePosition, mergeRawCoins };
@@ -0,0 +1,22 @@
1
+ import { g as SupportedCredentials } from '../../../types-Caz2X4h0.js';
2
+ import { BaseOrchestrator, OrchestratorConfig } from '../base.js';
3
+ import '@pear-protocol/types';
4
+ import '../bybit/types.js';
5
+ import '../hyperliquid/types.js';
6
+ import './types.js';
7
+
8
+ declare class OkxOrchestrator extends BaseOrchestrator {
9
+ private ws;
10
+ private creds;
11
+ private stateHandler;
12
+ private assetTracker;
13
+ constructor(config: OrchestratorConfig, credentials: SupportedCredentials);
14
+ protected initAsync(): Promise<void>;
15
+ protected cleanupConnections(): void;
16
+ stop(): Promise<void>;
17
+ get isConnected(): boolean;
18
+ onAssetTracked(coin: string): void;
19
+ onAssetUntracked(coin: string): void;
20
+ }
21
+
22
+ export { OkxOrchestrator };
@@ -0,0 +1,57 @@
1
+ import { BaseOrchestrator } from '../base';
2
+ import { OkxAssetTracker } from './asset-tracker';
3
+ import { acctLvToAccountType } from './mapper';
4
+ import { fetchAccountConfig, fetchBalance, fetchPositions } from './rest';
5
+ import { OkxStateHandler } from './state-handler';
6
+ import { OkxWs } from './ws';
7
+
8
+ class OkxOrchestrator extends BaseOrchestrator {
9
+ ws = null;
10
+ creds;
11
+ stateHandler;
12
+ assetTracker;
13
+ constructor(config, credentials) {
14
+ super(config);
15
+ this.credentials = credentials;
16
+ this.creds = credentials;
17
+ this.assetTracker = new OkxAssetTracker({
18
+ onStateUpdate: (update) => this.onStateUpdate(update),
19
+ onError: (err) => this.onError(err),
20
+ getCreds: () => this.creds,
21
+ getDemo: () => this.demo
22
+ });
23
+ this.stateHandler = new OkxStateHandler({
24
+ onStateUpdate: (update) => this.onStateUpdate(update),
25
+ getTrackedAssetInfos: () => this.assetTracker.getInfos()
26
+ });
27
+ }
28
+ async initAsync() {
29
+ const [config, balance, positions] = await Promise.all([
30
+ fetchAccountConfig(this.creds, this.demo),
31
+ fetchBalance(this.creds, this.demo),
32
+ fetchPositions(this.creds, this.demo)
33
+ ]);
34
+ this.stateHandler.setAccountType(acctLvToAccountType(config.acctLv));
35
+ this.stateHandler.handleInitialData(balance, positions);
36
+ this.ws = new OkxWs({ onMessage: (msg) => this.stateHandler.handleMessage(msg) }, this.demo);
37
+ await this.ws.connect(this.creds);
38
+ }
39
+ cleanupConnections() {
40
+ this.ws?.close();
41
+ }
42
+ async stop() {
43
+ this.stopped = true;
44
+ this.cleanupConnections();
45
+ }
46
+ get isConnected() {
47
+ return this.ws?.isConnected ?? false;
48
+ }
49
+ onAssetTracked(coin) {
50
+ this.assetTracker.onAssetTracked(coin);
51
+ }
52
+ onAssetUntracked(coin) {
53
+ this.assetTracker.onAssetUntracked(coin);
54
+ }
55
+ }
56
+
57
+ export { OkxOrchestrator };
@@ -0,0 +1,9 @@
1
+ import { OkxCredentialsDTO } from '@pear-protocol/types';
2
+ import { OkxRawAccountConfig, OkxRawBalance, OkxRawLeverageInfo, OkxRawPosition } from './types.js';
3
+
4
+ declare function fetchAccountConfig(creds: OkxCredentialsDTO, demo: boolean): Promise<OkxRawAccountConfig>;
5
+ declare function fetchBalance(creds: OkxCredentialsDTO, demo: boolean): Promise<OkxRawBalance>;
6
+ declare function fetchPositions(creds: OkxCredentialsDTO, demo: boolean): Promise<OkxRawPosition[]>;
7
+ declare function fetchLeverageInfo(creds: OkxCredentialsDTO, instId: string, demo: boolean): Promise<OkxRawLeverageInfo | undefined>;
8
+
9
+ export { fetchAccountConfig, fetchBalance, fetchLeverageInfo, fetchPositions };
@@ -0,0 +1,57 @@
1
+ import { hmacSha256Base64 } from '../../../utils/hmac';
2
+ import { REST_BASE_URL } from './const';
3
+
4
+ async function signedGet(creds, path, params, demo) {
5
+ const queryString = new URLSearchParams(params).toString();
6
+ const fullPath = queryString ? `${path}?${queryString}` : path;
7
+ const timestamp = (/* @__PURE__ */ new Date()).toISOString();
8
+ const signPayload = `${timestamp}GET${fullPath}`;
9
+ const signature = await hmacSha256Base64(creds.api_secret, signPayload);
10
+ const headers = {
11
+ "OK-ACCESS-KEY": creds.api_key,
12
+ "OK-ACCESS-SIGN": signature,
13
+ "OK-ACCESS-TIMESTAMP": timestamp,
14
+ "OK-ACCESS-PASSPHRASE": creds.api_pass,
15
+ "Content-Type": "application/json"
16
+ };
17
+ if (demo) {
18
+ headers["x-simulated-trading"] = "1";
19
+ }
20
+ const response = await fetch(`${REST_BASE_URL}${fullPath}`, { headers });
21
+ if (!response.ok) {
22
+ throw new Error(`OKX API error: ${response.status} ${response.statusText}`);
23
+ }
24
+ const body = await response.json();
25
+ if (body.code !== "0") {
26
+ throw new Error(`OKX API error: ${body.code} ${body.msg}`);
27
+ }
28
+ return body.data;
29
+ }
30
+ async function fetchAccountConfig(creds, demo) {
31
+ const data = await signedGet(creds, "/api/v5/account/config", {}, demo);
32
+ if (!data[0]) {
33
+ throw new Error("OKX API error: empty account config response");
34
+ }
35
+ return data[0];
36
+ }
37
+ async function fetchBalance(creds, demo) {
38
+ const data = await signedGet(creds, "/api/v5/account/balance", {}, demo);
39
+ if (!data[0]) {
40
+ throw new Error("OKX API error: empty balance response");
41
+ }
42
+ return data[0];
43
+ }
44
+ async function fetchPositions(creds, demo) {
45
+ return signedGet(creds, "/api/v5/account/positions", { instType: "SWAP" }, demo);
46
+ }
47
+ async function fetchLeverageInfo(creds, instId, demo) {
48
+ const result = await signedGet(
49
+ creds,
50
+ "/api/v5/account/leverage-info",
51
+ { instId, mgnMode: "cross" },
52
+ demo
53
+ ).catch(() => []);
54
+ return result[0];
55
+ }
56
+
57
+ export { fetchAccountConfig, fetchBalance, fetchLeverageInfo, fetchPositions };
@@ -0,0 +1,24 @@
1
+ import { S as StateUpdate, h as TrackedAssetInfo } from '../../../types-Caz2X4h0.js';
2
+ import { OkxAccountType, OkxRawBalance, OkxRawPosition, OkxWsMessage } from './types.js';
3
+ import '@pear-protocol/types';
4
+ import '../bybit/types.js';
5
+ import '../hyperliquid/types.js';
6
+
7
+ type OnStateUpdate = (update: StateUpdate) => void;
8
+ declare class OkxStateHandler {
9
+ private onStateUpdate;
10
+ private getTrackedAssetInfos;
11
+ private rawCoins;
12
+ private lastBalance;
13
+ private accountType;
14
+ constructor(deps: {
15
+ onStateUpdate: OnStateUpdate;
16
+ getTrackedAssetInfos: () => Map<string, TrackedAssetInfo>;
17
+ });
18
+ setAccountType(type: OkxAccountType | null): void;
19
+ handleInitialData(balance: OkxRawBalance, positions: OkxRawPosition[]): void;
20
+ handleMessage(msg: OkxWsMessage): void;
21
+ private handleBalanceUpdate;
22
+ }
23
+
24
+ export { OkxStateHandler };
@@ -0,0 +1,78 @@
1
+ import { mergeRawCoins, buildBalance, mapPositions, mapPositionUpdates } from './mapper';
2
+
3
+ class OkxStateHandler {
4
+ onStateUpdate;
5
+ getTrackedAssetInfos;
6
+ rawCoins = /* @__PURE__ */ new Map();
7
+ lastBalance = null;
8
+ accountType = null;
9
+ constructor(deps) {
10
+ this.onStateUpdate = deps.onStateUpdate;
11
+ this.getTrackedAssetInfos = deps.getTrackedAssetInfos;
12
+ }
13
+ setAccountType(type) {
14
+ this.accountType = type;
15
+ }
16
+ handleInitialData(balance, positions) {
17
+ this.lastBalance = balance;
18
+ this.rawCoins = mergeRawCoins(/* @__PURE__ */ new Map(), balance.details ?? []);
19
+ const built = buildBalance(balance, this.rawCoins, this.accountType);
20
+ if (built) this.onStateUpdate({ balance: built });
21
+ this.onStateUpdate({ positions: mapPositions(positions) });
22
+ }
23
+ handleMessage(msg) {
24
+ if (msg.arg.channel === "account") {
25
+ const raw = msg.data[0];
26
+ if (raw) this.handleBalanceUpdate(raw);
27
+ return;
28
+ }
29
+ if (msg.arg.channel === "positions") {
30
+ const posMsg = msg;
31
+ const action = posMsg.action ?? "update";
32
+ const rawPositions = posMsg.data;
33
+ const positions = action === "snapshot" ? mapPositions(rawPositions) : mapPositionUpdates(rawPositions);
34
+ if (positions.size === 0 && action !== "snapshot") return;
35
+ const leverageSettings = /* @__PURE__ */ new Map();
36
+ for (const p of rawPositions) {
37
+ if (p.instId && p.lever) {
38
+ leverageSettings.set(p.instId, p.lever);
39
+ }
40
+ }
41
+ const trackedAssetInfos = this.getTrackedAssetInfos();
42
+ const trackedAssets = /* @__PURE__ */ new Map();
43
+ for (const p of rawPositions) {
44
+ const existing = trackedAssetInfos.get(p.instId);
45
+ if (existing) {
46
+ const leverage = p.lever || existing.leverage;
47
+ const marginType = p.mgnMode;
48
+ const updated = { ...existing, leverage, marginType };
49
+ trackedAssetInfos.set(p.instId, updated);
50
+ trackedAssets.set(p.instId, updated);
51
+ }
52
+ }
53
+ this.onStateUpdate({
54
+ positions,
55
+ leverageSettings,
56
+ ...trackedAssets.size > 0 ? { trackedAssets } : {}
57
+ });
58
+ }
59
+ }
60
+ handleBalanceUpdate(raw) {
61
+ this.rawCoins = mergeRawCoins(this.rawCoins, raw.details ?? []);
62
+ const merged = this.lastBalance ? {
63
+ totalEq: raw.totalEq || this.lastBalance.totalEq,
64
+ adjEq: raw.adjEq || this.lastBalance.adjEq,
65
+ availEq: raw.availEq || this.lastBalance.availEq,
66
+ mmr: raw.mmr || this.lastBalance.mmr,
67
+ imr: raw.imr || this.lastBalance.imr,
68
+ upl: raw.upl || this.lastBalance.upl,
69
+ mgnRatio: raw.mgnRatio || this.lastBalance.mgnRatio,
70
+ details: raw.details ?? this.lastBalance.details
71
+ } : raw;
72
+ this.lastBalance = merged;
73
+ const built = buildBalance(merged, this.rawCoins, this.accountType);
74
+ if (built) this.onStateUpdate({ balance: built });
75
+ }
76
+ }
77
+
78
+ export { OkxStateHandler };
@@ -0,0 +1,69 @@
1
+ declare enum OkxAccountType {
2
+ SPOT = "OKX_SPOT",
3
+ SINGLE_CURRENCY_MARGIN = "OKX_SINGLE",
4
+ MULTI_CURRENCY_MARGIN = "OKX_MULTI",
5
+ PORTFOLIO_MARGIN = "OKX_PORTFOLIO"
6
+ }
7
+ interface OkxRawAccountConfig {
8
+ acctLv: string;
9
+ uid: string;
10
+ }
11
+ interface OkxRawBalanceDetail {
12
+ ccy: string;
13
+ eq: string;
14
+ availEq: string;
15
+ availBal: string;
16
+ cashBal: string;
17
+ frozenBal: string;
18
+ ordFrozen: string;
19
+ imr: string;
20
+ mmr: string;
21
+ upl: string;
22
+ eqUsd: string;
23
+ }
24
+ interface OkxRawBalance {
25
+ totalEq: string;
26
+ adjEq: string;
27
+ availEq: string;
28
+ mmr: string;
29
+ imr: string;
30
+ upl: string;
31
+ mgnRatio: string;
32
+ details: OkxRawBalanceDetail[];
33
+ }
34
+ interface OkxRawPosition {
35
+ instId: string;
36
+ instType: string;
37
+ posSide: string;
38
+ pos: string;
39
+ avgPx: string;
40
+ upl: string;
41
+ lever: string;
42
+ mgnMode: string;
43
+ liqPx: string;
44
+ ccy: string;
45
+ }
46
+ interface OkxRawLeverageInfo {
47
+ instId: string;
48
+ lever: string;
49
+ mgnMode: string;
50
+ }
51
+ interface OkxWsAccountMessage {
52
+ arg: {
53
+ channel: 'account';
54
+ };
55
+ data: OkxRawBalance[];
56
+ }
57
+ interface OkxWsPositionsMessage {
58
+ arg: {
59
+ channel: 'positions';
60
+ };
61
+ action?: 'snapshot' | 'update';
62
+ data: OkxRawPosition[];
63
+ }
64
+ type OkxWsMessage = OkxWsAccountMessage | OkxWsPositionsMessage;
65
+ interface OkxWsHandlers {
66
+ onMessage: (msg: OkxWsMessage) => void;
67
+ }
68
+
69
+ export { OkxAccountType, type OkxRawAccountConfig, type OkxRawBalance, type OkxRawBalanceDetail, type OkxRawLeverageInfo, type OkxRawPosition, type OkxWsAccountMessage, type OkxWsHandlers, type OkxWsMessage, type OkxWsPositionsMessage };
@@ -0,0 +1,9 @@
1
+ var OkxAccountType = /* @__PURE__ */ ((OkxAccountType2) => {
2
+ OkxAccountType2["SPOT"] = "OKX_SPOT";
3
+ OkxAccountType2["SINGLE_CURRENCY_MARGIN"] = "OKX_SINGLE";
4
+ OkxAccountType2["MULTI_CURRENCY_MARGIN"] = "OKX_MULTI";
5
+ OkxAccountType2["PORTFOLIO_MARGIN"] = "OKX_PORTFOLIO";
6
+ return OkxAccountType2;
7
+ })(OkxAccountType || {});
8
+
9
+ export { OkxAccountType };
@@ -0,0 +1,20 @@
1
+ import { OkxCredentialsDTO } from '@pear-protocol/types';
2
+ import { OkxWsHandlers } from './types.js';
3
+
4
+ declare class OkxWs {
5
+ private ws;
6
+ private pingTimer;
7
+ private handlers;
8
+ private demo;
9
+ private creds;
10
+ private readonly pingIntervalMs;
11
+ constructor(handlers: OkxWsHandlers, demo: boolean, pingIntervalMs?: number);
12
+ connect(creds: OkxCredentialsDTO): Promise<void>;
13
+ close(): void;
14
+ get isConnected(): boolean;
15
+ private clearPing;
16
+ private subscribe;
17
+ private login;
18
+ }
19
+
20
+ export { OkxWs };
@@ -0,0 +1,103 @@
1
+ import { hmacSha256Base64 } from '../../../utils/hmac';
2
+ import { createWs, waitForOpen, sendWs, ReconnectingWebSocket, clearIntervalTimer } from '../../../utils/ws';
3
+ import { DEFAULT_PING_INTERVAL_MS, WS_PRIVATE_URL_DEMO, WS_PRIVATE_URL, LOGIN_TIMEOUT_MS } from './const';
4
+
5
+ class OkxWs {
6
+ ws = null;
7
+ pingTimer = null;
8
+ handlers;
9
+ demo;
10
+ creds = null;
11
+ pingIntervalMs;
12
+ constructor(handlers, demo, pingIntervalMs = DEFAULT_PING_INTERVAL_MS) {
13
+ this.handlers = handlers;
14
+ this.demo = demo;
15
+ this.pingIntervalMs = pingIntervalMs;
16
+ }
17
+ async connect(creds) {
18
+ this.creds = creds;
19
+ this.ws = createWs(this.demo ? WS_PRIVATE_URL_DEMO : WS_PRIVATE_URL);
20
+ this.ws.addEventListener("message", (event) => {
21
+ const data = event.data;
22
+ if (typeof data !== "string" || data === "pong") return;
23
+ try {
24
+ const msg = JSON.parse(data);
25
+ if (msg.event) return;
26
+ if (msg.arg && msg.data) {
27
+ this.handlers.onMessage(msg);
28
+ }
29
+ } catch {
30
+ }
31
+ });
32
+ let initialOpen = true;
33
+ this.ws.addEventListener("open", () => {
34
+ if (initialOpen) {
35
+ initialOpen = false;
36
+ return;
37
+ }
38
+ if (!this.creds) return;
39
+ this.login(this.creds).then(() => this.subscribe()).catch(() => {
40
+ });
41
+ });
42
+ await waitForOpen(this.ws);
43
+ await this.login(creds);
44
+ this.subscribe();
45
+ this.pingTimer = setInterval(() => sendWs(this.ws, "ping"), this.pingIntervalMs);
46
+ }
47
+ close() {
48
+ this.clearPing();
49
+ this.creds = null;
50
+ if (this.ws) {
51
+ this.ws.close();
52
+ this.ws = null;
53
+ }
54
+ }
55
+ get isConnected() {
56
+ return this.ws?.readyState === ReconnectingWebSocket.OPEN;
57
+ }
58
+ clearPing() {
59
+ this.pingTimer = clearIntervalTimer(this.pingTimer);
60
+ }
61
+ subscribe() {
62
+ sendWs(this.ws, {
63
+ op: "subscribe",
64
+ args: [{ channel: "account" }, { channel: "positions", instType: "SWAP" }]
65
+ });
66
+ }
67
+ async login(creds) {
68
+ const timestamp = (Date.now() / 1e3).toString();
69
+ const sign = await hmacSha256Base64(creds.api_secret, `${timestamp}GET/users/self/verify`);
70
+ return new Promise((resolve, reject) => {
71
+ const timeout = setTimeout(() => {
72
+ this.ws?.removeEventListener("message", handler);
73
+ reject(new Error("OKX login timeout"));
74
+ }, LOGIN_TIMEOUT_MS);
75
+ const handler = (event) => {
76
+ try {
77
+ const msg = JSON.parse(event.data);
78
+ if (msg.event === "login") {
79
+ clearTimeout(timeout);
80
+ this.ws?.removeEventListener("message", handler);
81
+ if (msg.code === "0") resolve();
82
+ else reject(new Error(`OKX login failed: ${msg.msg ?? "unknown"}`));
83
+ }
84
+ } catch {
85
+ }
86
+ };
87
+ this.ws?.addEventListener("message", handler);
88
+ sendWs(this.ws, {
89
+ op: "login",
90
+ args: [
91
+ {
92
+ apiKey: creds.api_key,
93
+ passphrase: creds.api_pass,
94
+ timestamp,
95
+ sign
96
+ }
97
+ ]
98
+ });
99
+ });
100
+ }
101
+ }
102
+
103
+ export { OkxWs };
@@ -1,9 +1,10 @@
1
1
  export { AccountManager } from './account-manager.js';
2
2
  export { ExchangeAccount } from './exchange-account.js';
3
3
  export { createOrchestrator } from './exchanges/index.js';
4
- export { A as ACCOUNT_TYPE_LABELS, a as AccountBalance, b as AccountConfig, c as AccountPosition, d as AccountType, e as AssetBalance, B as BalanceCallback, f as BinanceAccountType, E as ExchangeState, H as HyperliquidAccountCredentials, M as MarginMode, P as PositionsCallback, S as StateUpdate, g as SupportedCredentials, T as TrackedAssetCallback, h as TrackedAssetInfo, i as Tracker } from '../types-D2dbAtin.js';
4
+ export { A as ACCOUNT_TYPE_LABELS, a as AccountBalance, b as AccountConfig, c as AccountPosition, d as AccountType, e as AssetBalance, B as BalanceCallback, f as BinanceAccountType, E as ExchangeState, H as HyperliquidAccountCredentials, M as MarginMode, P as PositionsCallback, S as StateUpdate, g as SupportedCredentials, T as TrackedAssetCallback, h as TrackedAssetInfo, i as Tracker } from '../types-Caz2X4h0.js';
5
5
  export { BybitAccountType } from './exchanges/bybit/types.js';
6
6
  export { HyperliquidAccountType } from './exchanges/hyperliquid/types.js';
7
+ export { OkxAccountType } from './exchanges/okx/types.js';
7
8
  export { Orchestrator, OrchestratorConfig } from './exchanges/base.js';
8
9
  import '@pear-protocol/core-sdk';
9
10
  import '@pear-protocol/types';
@@ -1,4 +1,5 @@
1
1
  import '@pear-protocol/types';
2
- export { A as ACCOUNT_TYPE_LABELS, a as AccountBalance, b as AccountConfig, c as AccountPosition, d as AccountType, e as AssetBalance, B as BalanceCallback, E as ExchangeState, H as HyperliquidAccountCredentials, M as MarginMode, P as PositionsCallback, S as StateUpdate, g as SupportedCredentials, T as TrackedAssetCallback, h as TrackedAssetInfo, i as Tracker } from '../types-D2dbAtin.js';
2
+ export { A as ACCOUNT_TYPE_LABELS, a as AccountBalance, b as AccountConfig, c as AccountPosition, d as AccountType, e as AssetBalance, B as BalanceCallback, E as ExchangeState, H as HyperliquidAccountCredentials, M as MarginMode, P as PositionsCallback, S as StateUpdate, g as SupportedCredentials, T as TrackedAssetCallback, h as TrackedAssetInfo, i as Tracker } from '../types-Caz2X4h0.js';
3
3
  import './exchanges/bybit/types.js';
4
4
  import './exchanges/hyperliquid/types.js';
5
+ import './exchanges/okx/types.js';
@@ -1,6 +1,7 @@
1
1
  import { BinanceAccountType } from './exchanges/binance/types';
2
2
  import { BybitAccountType } from './exchanges/bybit/types';
3
3
  import { HyperliquidAccountType } from './exchanges/hyperliquid/types';
4
+ import { OkxAccountType } from './exchanges/okx/types';
4
5
 
5
6
  const ACCOUNT_TYPE_LABELS = {
6
7
  [BinanceAccountType.SINGLE_ASSET]: "Single-Asset Mode",
@@ -12,7 +13,11 @@ const ACCOUNT_TYPE_LABELS = {
12
13
  [HyperliquidAccountType.DISABLED]: "Standard",
13
14
  [HyperliquidAccountType.DEX_ABSTRACTION]: "Standard (Shared HIP-3 Balance)",
14
15
  [HyperliquidAccountType.PORTFOLIO_MARGIN]: "Portfolio Margin",
15
- [HyperliquidAccountType.UNIFIED_ACCOUNT]: "Unified Account"
16
+ [HyperliquidAccountType.UNIFIED_ACCOUNT]: "Unified Account",
17
+ [OkxAccountType.SPOT]: "Spot Mode",
18
+ [OkxAccountType.SINGLE_CURRENCY_MARGIN]: "Single-Currency Margin",
19
+ [OkxAccountType.MULTI_CURRENCY_MARGIN]: "Multi-Currency Margin",
20
+ [OkxAccountType.PORTFOLIO_MARGIN]: "Portfolio Margin"
16
21
  };
17
22
 
18
23
  export { ACCOUNT_TYPE_LABELS };
@@ -1,7 +1,8 @@
1
- import { E as ExchangeState } from '../types-D2dbAtin.js';
1
+ import { E as ExchangeState } from '../types-Caz2X4h0.js';
2
2
  import '@pear-protocol/types';
3
3
  import './exchanges/bybit/types.js';
4
4
  import './exchanges/hyperliquid/types.js';
5
+ import './exchanges/okx/types.js';
5
6
 
6
7
  declare function createEmptyState(): ExchangeState;
7
8
  declare function positionKey(symbol: string, side: string): string;
package/dist/index.d.ts CHANGED
@@ -2,10 +2,11 @@ import PearSDK from '@pear-protocol/core-sdk';
2
2
  import { AccountManager } from './account/account-manager.js';
3
3
  export { ExchangeAccount } from './account/exchange-account.js';
4
4
  export { createOrchestrator } from './account/exchanges/index.js';
5
- export { A as ACCOUNT_TYPE_LABELS, a as AccountBalance, b as AccountConfig, c as AccountPosition, d as AccountType, e as AssetBalance, B as BalanceCallback, f as BinanceAccountType, E as ExchangeState, H as HyperliquidAccountCredentials, M as MarginMode, P as PositionsCallback, S as StateUpdate, g as SupportedCredentials, T as TrackedAssetCallback, h as TrackedAssetInfo, i as Tracker } from './types-D2dbAtin.js';
5
+ export { A as ACCOUNT_TYPE_LABELS, a as AccountBalance, b as AccountConfig, c as AccountPosition, d as AccountType, e as AssetBalance, B as BalanceCallback, f as BinanceAccountType, E as ExchangeState, H as HyperliquidAccountCredentials, M as MarginMode, P as PositionsCallback, S as StateUpdate, g as SupportedCredentials, T as TrackedAssetCallback, h as TrackedAssetInfo, i as Tracker } from './types-Caz2X4h0.js';
6
6
  import { Credentials } from './credentials.js';
7
7
  export { BybitAccountType } from './account/exchanges/bybit/types.js';
8
8
  export { HyperliquidAccountType } from './account/exchanges/hyperliquid/types.js';
9
+ export { OkxAccountType } from './account/exchanges/okx/types.js';
9
10
  export { Orchestrator, OrchestratorConfig } from './account/exchanges/base.js';
10
11
  import '@pear-protocol/types';
11
12
 
@@ -1,6 +1,7 @@
1
- import { Connector, BinanceCredentialsDTO, BybitCredentialsDTO, HyperliquidCredentialsDTO } from '@pear-protocol/types';
1
+ import { Connector, BinanceCredentialsDTO, BybitCredentialsDTO, HyperliquidCredentialsDTO, OkxCredentialsDTO } from '@pear-protocol/types';
2
2
  import { BybitAccountType } from './account/exchanges/bybit/types.js';
3
3
  import { HyperliquidAccountType } from './account/exchanges/hyperliquid/types.js';
4
+ import { OkxAccountType } from './account/exchanges/okx/types.js';
4
5
 
5
6
  declare enum BinanceAccountType {
6
7
  MULTI_ASSET = "MULTI_ASSET",
@@ -76,7 +77,7 @@ interface BinanceWsHandlers {
76
77
  }
77
78
 
78
79
  type MarginMode = 'cross' | 'isolated';
79
- type AccountType = BinanceAccountType | BybitAccountType | HyperliquidAccountType;
80
+ type AccountType = BinanceAccountType | BybitAccountType | HyperliquidAccountType | OkxAccountType;
80
81
  declare const ACCOUNT_TYPE_LABELS: Record<AccountType, string>;
81
82
  interface AssetBalance {
82
83
  asset: string;
@@ -139,7 +140,7 @@ interface AccountConfig {
139
140
  type HyperliquidAccountCredentials = HyperliquidCredentialsDTO & {
140
141
  address: string;
141
142
  };
142
- type SupportedCredentials = BinanceCredentialsDTO | BybitCredentialsDTO | HyperliquidAccountCredentials;
143
+ type SupportedCredentials = BinanceCredentialsDTO | BybitCredentialsDTO | HyperliquidAccountCredentials | OkxCredentialsDTO;
143
144
  interface StateUpdate {
144
145
  balance?: AccountBalance;
145
146
  positions?: Map<string, AccountPosition>;
@@ -1,3 +1,4 @@
1
1
  declare function hmacSha256Hex(secret: string, message: string): Promise<string>;
2
+ declare function hmacSha256Base64(secret: string, message: string): Promise<string>;
2
3
 
3
- export { hmacSha256Hex };
4
+ export { hmacSha256Base64, hmacSha256Hex };
@@ -1,10 +1,20 @@
1
1
  const encoder = new TextEncoder();
2
- async function hmacSha256Hex(secret, message) {
2
+ async function sign(secret, message) {
3
3
  const key = await crypto.subtle.importKey("raw", encoder.encode(secret), { name: "HMAC", hash: "SHA-256" }, false, [
4
4
  "sign"
5
5
  ]);
6
- const signature = await crypto.subtle.sign("HMAC", key, encoder.encode(message));
6
+ return crypto.subtle.sign("HMAC", key, encoder.encode(message));
7
+ }
8
+ async function hmacSha256Hex(secret, message) {
9
+ const signature = await sign(secret, message);
7
10
  return Array.from(new Uint8Array(signature)).map((b) => b.toString(16).padStart(2, "0")).join("");
8
11
  }
12
+ async function hmacSha256Base64(secret, message) {
13
+ const signature = await sign(secret, message);
14
+ const bytes = new Uint8Array(signature);
15
+ let binary = "";
16
+ for (const b of bytes) binary += String.fromCharCode(b);
17
+ return btoa(binary);
18
+ }
9
19
 
10
- export { hmacSha256Hex };
20
+ export { hmacSha256Base64, hmacSha256Hex };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pear-protocol/exchanges-sdk",
3
- "version": "0.0.12",
3
+ "version": "0.0.14",
4
4
  "description": "Pear Protocol Exchanges SDK",
5
5
  "private": false,
6
6
  "type": "module",
@@ -25,9 +25,9 @@
25
25
  "typecheck": "tsc --noEmit"
26
26
  },
27
27
  "dependencies": {
28
- "@pear-protocol/core-sdk": "0.0.12",
29
- "@pear-protocol/types": "0.0.11",
30
- "@pear-protocol/utils": "0.0.11",
28
+ "@pear-protocol/core-sdk": "0.0.13",
29
+ "@pear-protocol/types": "0.0.12",
30
+ "@pear-protocol/utils": "0.0.12",
31
31
  "partysocket": "^1.0.3"
32
32
  },
33
33
  "devDependencies": {