├── .npmrc ├── internal └── shared │ ├── src │ ├── index.ts │ └── enums.ts │ ├── eslint.config.mjs │ ├── tsconfig.json │ ├── tsup.config.ts │ ├── vitest.config.ts │ └── package.json ├── packages ├── coinex │ ├── src │ │ ├── modules │ │ │ ├── assets │ │ │ │ ├── amm │ │ │ │ │ ├── index.ts │ │ │ │ │ ├── module.ts │ │ │ │ │ └── types.ts │ │ │ │ ├── balance │ │ │ │ │ └── index.ts │ │ │ │ ├── transfer │ │ │ │ │ ├── index.ts │ │ │ │ │ ├── module.ts │ │ │ │ │ └── types.ts │ │ │ │ ├── borrow-repay │ │ │ │ │ ├── index.ts │ │ │ │ │ ├── module.ts │ │ │ │ │ └── types.ts │ │ │ │ ├── deposit-withdrawal │ │ │ │ │ └── index.ts │ │ │ │ ├── index.ts │ │ │ │ ├── types.ts │ │ │ │ └── module.ts │ │ │ ├── spot │ │ │ │ ├── deal │ │ │ │ │ ├── index.ts │ │ │ │ │ ├── module.ts │ │ │ │ │ └── types.ts │ │ │ │ ├── market │ │ │ │ │ ├── index.ts │ │ │ │ │ └── module.ts │ │ │ │ ├── order │ │ │ │ │ └── index.ts │ │ │ │ ├── index.ts │ │ │ │ ├── types.ts │ │ │ │ └── module.ts │ │ │ ├── account │ │ │ │ ├── fees │ │ │ │ │ ├── index.ts │ │ │ │ │ ├── module.ts │ │ │ │ │ └── types.ts │ │ │ │ ├── settings │ │ │ │ │ ├── index.ts │ │ │ │ │ ├── types.ts │ │ │ │ │ └── module.ts │ │ │ │ ├── subaccount │ │ │ │ │ └── index.ts │ │ │ │ ├── index.ts │ │ │ │ ├── types.ts │ │ │ │ └── module.ts │ │ │ ├── futures │ │ │ │ ├── deal │ │ │ │ │ ├── index.ts │ │ │ │ │ ├── types.ts │ │ │ │ │ └── module.ts │ │ │ │ ├── market │ │ │ │ │ └── index.ts │ │ │ │ ├── order │ │ │ │ │ └── index.ts │ │ │ │ ├── position │ │ │ │ │ ├── index.ts │ │ │ │ │ └── module.ts │ │ │ │ ├── index.ts │ │ │ │ ├── types.ts │ │ │ │ └── module.ts │ │ │ ├── maintain │ │ │ │ ├── index.ts │ │ │ │ ├── module.ts │ │ │ │ └── types.ts │ │ │ └── index.ts │ │ ├── lib │ │ │ ├── delay.ts │ │ │ ├── errors.ts │ │ │ ├── crypto.ts │ │ │ └── object.ts │ │ ├── client.test.ts │ │ ├── index.ts │ │ ├── types.ts │ │ └── client.ts │ ├── eslint.config.mjs │ ├── tsup.config.ts │ ├── tsconfig.json │ ├── vitest.config.ts │ ├── .prettierignore │ └── package.json └── websocket │ ├── src │ ├── modules │ │ ├── spot │ │ │ ├── balance │ │ │ │ ├── index.ts │ │ │ │ ├── module.ts │ │ │ │ └── types.ts │ │ │ ├── orders │ │ │ │ ├── index.ts │ │ │ │ ├── stop │ │ │ │ │ ├── index.ts │ │ │ │ │ ├── module.ts │ │ │ │ │ └── types.ts │ │ │ │ ├── module.ts │ │ │ │ └── types.ts │ │ │ ├── executions │ │ │ │ ├── index.ts │ │ │ │ ├── module.ts │ │ │ │ └── types.ts │ │ │ ├── ticker │ │ │ │ ├── bbo │ │ │ │ │ ├── index.ts │ │ │ │ │ ├── module.ts │ │ │ │ │ └── types.ts │ │ │ │ ├── deals │ │ │ │ │ ├── index.ts │ │ │ │ │ ├── module.ts │ │ │ │ │ └── types.ts │ │ │ │ ├── depth │ │ │ │ │ ├── index.ts │ │ │ │ │ ├── module.ts │ │ │ │ │ └── types.ts │ │ │ │ ├── index │ │ │ │ │ ├── index.ts │ │ │ │ │ ├── types.ts │ │ │ │ │ └── module.ts │ │ │ │ ├── state │ │ │ │ │ ├── index.ts │ │ │ │ │ ├── module.ts │ │ │ │ │ └── types.ts │ │ │ │ ├── types.ts │ │ │ │ └── index.ts │ │ │ ├── types.ts │ │ │ └── index.ts │ │ ├── futures │ │ │ ├── balance │ │ │ │ ├── index.ts │ │ │ │ ├── module.ts │ │ │ │ └── types.ts │ │ │ ├── executions │ │ │ │ ├── index.ts │ │ │ │ ├── module.ts │ │ │ │ └── types.ts │ │ │ ├── orders │ │ │ │ ├── index.ts │ │ │ │ ├── stop │ │ │ │ │ ├── index.ts │ │ │ │ │ ├── module.ts │ │ │ │ │ └── types.ts │ │ │ │ ├── module.ts │ │ │ │ └── types.ts │ │ │ ├── position │ │ │ │ ├── index.ts │ │ │ │ ├── module.ts │ │ │ │ └── types.ts │ │ │ ├── ticker │ │ │ │ ├── bbo │ │ │ │ │ ├── index.ts │ │ │ │ │ ├── module.ts │ │ │ │ │ └── types.ts │ │ │ │ ├── deals │ │ │ │ │ ├── index.ts │ │ │ │ │ ├── module.ts │ │ │ │ │ └── types.ts │ │ │ │ ├── depth │ │ │ │ │ ├── index.ts │ │ │ │ │ ├── module.ts │ │ │ │ │ └── types.ts │ │ │ │ ├── index │ │ │ │ │ ├── index.ts │ │ │ │ │ ├── types.ts │ │ │ │ │ └── module.ts │ │ │ │ ├── state │ │ │ │ │ ├── index.ts │ │ │ │ │ ├── module.ts │ │ │ │ │ └── types.ts │ │ │ │ ├── types.ts │ │ │ │ └── index.ts │ │ │ ├── types.ts │ │ │ └── index.ts │ │ ├── index.ts │ │ └── types.ts │ ├── index.ts │ ├── lib │ │ ├── errors.ts │ │ ├── crypto.ts │ │ └── websocket.ts │ ├── types.ts │ └── client.ts │ ├── eslint.config.mjs │ ├── examples │ ├── .env.example │ └── common.ts │ ├── tsup.config.ts │ ├── tsconfig.json │ ├── .prettierignore │ ├── package.json │ └── README.md ├── tooling └── eslint │ ├── package.json │ └── index.mjs ├── .changeset ├── config.json └── README.md ├── pnpm-workspace.yaml ├── .github ├── renovate.json ├── ISSUE_TEMPLATE │ ├── feature_request.yml │ └── bug_report.yml ├── workflows │ ├── release.yml │ └── ci.yml └── replace-workspace-protocol.ts ├── package.json ├── .prettierignore ├── LICENSE ├── README.md └── .gitignore /.npmrc: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /internal/shared/src/index.ts: -------------------------------------------------------------------------------- 1 | export * from './enums'; 2 | -------------------------------------------------------------------------------- /packages/coinex/src/modules/assets/amm/index.ts: -------------------------------------------------------------------------------- 1 | export * from './module'; 2 | -------------------------------------------------------------------------------- /packages/coinex/src/modules/spot/deal/index.ts: -------------------------------------------------------------------------------- 1 | export * from './module'; 2 | -------------------------------------------------------------------------------- /packages/coinex/src/modules/spot/market/index.ts: -------------------------------------------------------------------------------- 1 | export * from './module'; 2 | -------------------------------------------------------------------------------- /packages/coinex/src/modules/spot/order/index.ts: -------------------------------------------------------------------------------- 1 | export * from './module'; 2 | -------------------------------------------------------------------------------- /packages/coinex/src/modules/account/fees/index.ts: -------------------------------------------------------------------------------- 1 | export * from './module'; 2 | -------------------------------------------------------------------------------- /packages/coinex/src/modules/account/settings/index.ts: -------------------------------------------------------------------------------- 1 | export * from './module'; 2 | -------------------------------------------------------------------------------- /packages/coinex/src/modules/assets/balance/index.ts: -------------------------------------------------------------------------------- 1 | export * from './module'; 2 | -------------------------------------------------------------------------------- /packages/coinex/src/modules/assets/transfer/index.ts: -------------------------------------------------------------------------------- 1 | export * from './module'; 2 | -------------------------------------------------------------------------------- /packages/coinex/src/modules/futures/deal/index.ts: -------------------------------------------------------------------------------- 1 | export * from './module'; 2 | -------------------------------------------------------------------------------- /packages/coinex/src/modules/futures/market/index.ts: -------------------------------------------------------------------------------- 1 | export * from './module'; 2 | -------------------------------------------------------------------------------- /packages/coinex/src/modules/futures/order/index.ts: -------------------------------------------------------------------------------- 1 | export * from './module'; 2 | -------------------------------------------------------------------------------- /packages/coinex/src/modules/futures/position/index.ts: -------------------------------------------------------------------------------- 1 | export * from './module'; 2 | -------------------------------------------------------------------------------- /packages/websocket/src/modules/spot/balance/index.ts: -------------------------------------------------------------------------------- 1 | export * from './module'; 2 | -------------------------------------------------------------------------------- /packages/websocket/src/modules/spot/orders/index.ts: -------------------------------------------------------------------------------- 1 | export * from './module'; 2 | -------------------------------------------------------------------------------- /packages/coinex/src/modules/account/subaccount/index.ts: -------------------------------------------------------------------------------- 1 | export * from './module'; 2 | -------------------------------------------------------------------------------- /packages/coinex/src/modules/assets/borrow-repay/index.ts: -------------------------------------------------------------------------------- 1 | export * from './module'; 2 | -------------------------------------------------------------------------------- /packages/websocket/src/modules/futures/balance/index.ts: -------------------------------------------------------------------------------- 1 | export * from './module'; 2 | -------------------------------------------------------------------------------- /packages/websocket/src/modules/futures/executions/index.ts: -------------------------------------------------------------------------------- 1 | export * from './module'; 2 | -------------------------------------------------------------------------------- /packages/websocket/src/modules/futures/orders/index.ts: -------------------------------------------------------------------------------- 1 | export * from './module'; 2 | -------------------------------------------------------------------------------- /packages/websocket/src/modules/futures/position/index.ts: -------------------------------------------------------------------------------- 1 | export * from './module'; 2 | -------------------------------------------------------------------------------- /packages/websocket/src/modules/futures/ticker/bbo/index.ts: -------------------------------------------------------------------------------- 1 | export * from './module'; 2 | -------------------------------------------------------------------------------- /packages/websocket/src/modules/spot/executions/index.ts: -------------------------------------------------------------------------------- 1 | export * from './module'; 2 | -------------------------------------------------------------------------------- /packages/websocket/src/modules/spot/orders/stop/index.ts: -------------------------------------------------------------------------------- 1 | export * from './module'; 2 | -------------------------------------------------------------------------------- /packages/websocket/src/modules/spot/ticker/bbo/index.ts: -------------------------------------------------------------------------------- 1 | export * from './module'; 2 | -------------------------------------------------------------------------------- /packages/websocket/src/modules/spot/ticker/deals/index.ts: -------------------------------------------------------------------------------- 1 | export * from './module'; 2 | -------------------------------------------------------------------------------- /packages/websocket/src/modules/spot/ticker/depth/index.ts: -------------------------------------------------------------------------------- 1 | export * from './module'; 2 | -------------------------------------------------------------------------------- /packages/websocket/src/modules/spot/ticker/index/index.ts: -------------------------------------------------------------------------------- 1 | export * from './module'; 2 | -------------------------------------------------------------------------------- /packages/websocket/src/modules/spot/ticker/state/index.ts: -------------------------------------------------------------------------------- 1 | export * from './module'; 2 | -------------------------------------------------------------------------------- /packages/coinex/src/modules/assets/deposit-withdrawal/index.ts: -------------------------------------------------------------------------------- 1 | export * from './module'; 2 | -------------------------------------------------------------------------------- /packages/websocket/src/modules/futures/orders/stop/index.ts: -------------------------------------------------------------------------------- 1 | export * from './module'; 2 | -------------------------------------------------------------------------------- /packages/websocket/src/modules/futures/ticker/deals/index.ts: -------------------------------------------------------------------------------- 1 | export * from './module'; 2 | -------------------------------------------------------------------------------- /packages/websocket/src/modules/futures/ticker/depth/index.ts: -------------------------------------------------------------------------------- 1 | export * from './module'; 2 | -------------------------------------------------------------------------------- /packages/websocket/src/modules/futures/ticker/index/index.ts: -------------------------------------------------------------------------------- 1 | export * from './module'; 2 | -------------------------------------------------------------------------------- /packages/websocket/src/modules/futures/ticker/state/index.ts: -------------------------------------------------------------------------------- 1 | export * from './module'; 2 | -------------------------------------------------------------------------------- /packages/websocket/src/modules/index.ts: -------------------------------------------------------------------------------- 1 | export * from './spot'; 2 | export * from './futures'; 3 | -------------------------------------------------------------------------------- /packages/coinex/src/modules/account/index.ts: -------------------------------------------------------------------------------- 1 | export * from './module'; 2 | export * from './types'; 3 | -------------------------------------------------------------------------------- /packages/coinex/src/modules/assets/index.ts: -------------------------------------------------------------------------------- 1 | export * from './module'; 2 | export * from './types'; 3 | -------------------------------------------------------------------------------- /packages/coinex/src/modules/futures/index.ts: -------------------------------------------------------------------------------- 1 | export * from './module'; 2 | export * from './types'; 3 | -------------------------------------------------------------------------------- /packages/coinex/src/modules/spot/index.ts: -------------------------------------------------------------------------------- 1 | export * from './module'; 2 | export * from './types'; 3 | -------------------------------------------------------------------------------- /packages/coinex/src/modules/maintain/index.ts: -------------------------------------------------------------------------------- 1 | export * from './module'; 2 | export * from './types'; 3 | -------------------------------------------------------------------------------- /packages/websocket/src/modules/types.ts: -------------------------------------------------------------------------------- 1 | export type * from './spot/types'; 2 | export type * from './futures/types'; 3 | -------------------------------------------------------------------------------- /internal/shared/eslint.config.mjs: -------------------------------------------------------------------------------- 1 | import baseConfig from '@coinex-org/eslint-config'; 2 | 3 | export default baseConfig; 4 | -------------------------------------------------------------------------------- /packages/coinex/eslint.config.mjs: -------------------------------------------------------------------------------- 1 | import baseConfig from '@coinex-org/eslint-config'; 2 | 3 | export default baseConfig; 4 | -------------------------------------------------------------------------------- /packages/websocket/eslint.config.mjs: -------------------------------------------------------------------------------- 1 | import baseConfig from '@coinex-org/eslint-config'; 2 | 3 | export default baseConfig; 4 | -------------------------------------------------------------------------------- /packages/websocket/examples/.env.example: -------------------------------------------------------------------------------- 1 | # Your CoinEx API Key 2 | API_KEY= 3 | # Your CoinEx Secret Key 4 | SECRET_KEY= 5 | -------------------------------------------------------------------------------- /packages/websocket/src/index.ts: -------------------------------------------------------------------------------- 1 | export * from './client'; 2 | export * from './types'; 3 | export * from './lib/errors'; 4 | -------------------------------------------------------------------------------- /packages/coinex/src/modules/spot/types.ts: -------------------------------------------------------------------------------- 1 | export type * from './deal/types'; 2 | export type * from './market/types'; 3 | export type * from './order/types'; 4 | -------------------------------------------------------------------------------- /packages/coinex/src/modules/index.ts: -------------------------------------------------------------------------------- 1 | export * from './account'; 2 | export * from './assets'; 3 | export * from './maintain'; 4 | export * from './spot'; 5 | export * from './futures'; 6 | -------------------------------------------------------------------------------- /packages/coinex/src/modules/futures/types.ts: -------------------------------------------------------------------------------- 1 | export type * from './market/types'; 2 | export type * from './deal/types'; 3 | export type * from './order/types'; 4 | export type * from './position/types'; 5 | -------------------------------------------------------------------------------- /packages/websocket/src/modules/spot/types.ts: -------------------------------------------------------------------------------- 1 | export type * from './balance/types'; 2 | export type * from './executions/types'; 3 | export type * from './orders/types'; 4 | export type * from './ticker/types'; 5 | -------------------------------------------------------------------------------- /packages/websocket/src/modules/spot/ticker/types.ts: -------------------------------------------------------------------------------- 1 | export * from './state/types'; 2 | export * from './depth/types'; 3 | export * from './deals/types'; 4 | export * from './index/types'; 5 | export * from './bbo/types'; 6 | -------------------------------------------------------------------------------- /packages/websocket/src/modules/futures/types.ts: -------------------------------------------------------------------------------- 1 | export type * from './balance/types'; 2 | export type * from './executions/types'; 3 | export type * from './orders/types'; 4 | export type * from './position/types'; 5 | export type * from './ticker/types'; 6 | -------------------------------------------------------------------------------- /packages/coinex/src/modules/assets/types.ts: -------------------------------------------------------------------------------- 1 | export type * from './amm/types'; 2 | export type * from './balance/types'; 3 | export type * from './borrow-repay/types'; 4 | export type * from './deposit-withdrawal/types'; 5 | export type * from './transfer/types'; 6 | -------------------------------------------------------------------------------- /tooling/eslint/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@coinex-org/eslint-config", 3 | "version": "0.1.0", 4 | "private": true, 5 | "main": "index.mjs", 6 | "dependencies": { 7 | "@shahrad/eslint-config": "^1.0.0", 8 | "globals": "^16.0.0" 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /internal/shared/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://json.schemastore.org/tsconfig", 3 | "extends": "@shahrad/tsconfig", 4 | "compilerOptions": { 5 | "baseUrl": "./", 6 | "paths": { 7 | "@/*": ["./src/*"] 8 | } 9 | }, 10 | "include": [ "src" ], 11 | "exclude": ["node_modules", "dist"] 12 | } 13 | -------------------------------------------------------------------------------- /internal/shared/tsup.config.ts: -------------------------------------------------------------------------------- 1 | import { defineConfig } from 'tsup'; 2 | 3 | export default defineConfig((options) => ({ 4 | dts: true, 5 | clean: !options.watch, 6 | splitting: true, 7 | sourcemap: true, 8 | entry: ['src/index.ts'], 9 | format: ['cjs', 'esm'], 10 | target: 'esnext', 11 | outDir: 'dist', 12 | })); 13 | -------------------------------------------------------------------------------- /.changeset/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://unpkg.com/@changesets/config@2.3.0/schema.json", 3 | "changelog": "@changesets/cli/changelog", 4 | "commit": false, 5 | "fixed": [], 6 | "linked": [], 7 | "access": "public", 8 | "baseBranch": "main", 9 | "updateInternalDependencies": "patch", 10 | "ignore": [] 11 | } 12 | -------------------------------------------------------------------------------- /packages/websocket/src/modules/futures/ticker/types.ts: -------------------------------------------------------------------------------- 1 | import { type FuturesDepthData } from './depth/types'; 2 | 3 | export type FuturesDepth = FuturesDepthData; 4 | 5 | export * from './depth/types'; 6 | export * from './state/types'; 7 | export * from './deals/types'; 8 | export * from './index/types'; 9 | export * from './bbo/types'; 10 | -------------------------------------------------------------------------------- /packages/coinex/tsup.config.ts: -------------------------------------------------------------------------------- 1 | import { defineConfig } from 'tsup'; 2 | 3 | export default defineConfig((options) => ({ 4 | dts: true, 5 | clean: !options.watch, 6 | splitting: true, 7 | minify: true, 8 | keepNames: true, 9 | entry: ['src/index.ts'], 10 | format: ['cjs', 'esm'], 11 | target: 'esnext', 12 | outDir: 'dist', 13 | })); 14 | -------------------------------------------------------------------------------- /pnpm-workspace.yaml: -------------------------------------------------------------------------------- 1 | packages: 2 | - apps/* 3 | - packages/* 4 | - internal/* 5 | - tooling/* 6 | 7 | catalog: 8 | '@shahrad/prettier-config': ^1.2.0 9 | '@shahrad/tsconfig': ^1.0.0 10 | '@types/node': ^22.13.1 11 | dotenv: ^16.4.5 12 | prettier: ^3.6.2 13 | tsup: ^8.5.0 14 | tsx: ^4.19.2 15 | typescript: ^5.9.2 16 | vitest: ^3.2.4 -------------------------------------------------------------------------------- /.github/renovate.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://docs.renovatebot.com/renovate-schema.json", 3 | "extends": ["config:base"], 4 | "packageRules": [ 5 | { 6 | "groupName": "All Dependencies", 7 | "groupSlug": "minor-patch", 8 | "matchPackagePatterns": ["*"], 9 | "matchUpdateTypes": ["minor", "patch"] 10 | } 11 | ] 12 | } 13 | -------------------------------------------------------------------------------- /packages/websocket/tsup.config.ts: -------------------------------------------------------------------------------- 1 | import { defineConfig } from 'tsup'; 2 | 3 | export default defineConfig((options) => ({ 4 | dts: true, 5 | clean: !options.watch, 6 | splitting: true, 7 | minify: true, 8 | keepNames: true, 9 | entry: ['src/index.ts'], 10 | format: ['cjs', 'esm'], 11 | target: 'esnext', 12 | outDir: 'dist', 13 | })); 14 | -------------------------------------------------------------------------------- /packages/coinex/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://json.schemastore.org/tsconfig", 3 | "extends": "@shahrad/tsconfig", 4 | "compilerOptions": { 5 | "baseUrl": ".", 6 | "paths": { 7 | "@/*": ["./src/*"], 8 | "@coinex-org/internal-shared": ["../../internal/shared/src/index.ts"] 9 | } 10 | }, 11 | "include": ["src"], 12 | "exclude": ["node_modules", "dist"] 13 | } 14 | -------------------------------------------------------------------------------- /packages/websocket/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://json.schemastore.org/tsconfig", 3 | "extends": "@shahrad/tsconfig", 4 | "compilerOptions": { 5 | "baseUrl": ".", 6 | "paths": { 7 | "@/*": ["./src/*"], 8 | "@coinex-org/internal-shared": ["../../internal/shared/src/index.ts"] 9 | } 10 | }, 11 | "include": ["src"], 12 | "exclude": ["node_modules", "dist"] 13 | } 14 | -------------------------------------------------------------------------------- /internal/shared/vitest.config.ts: -------------------------------------------------------------------------------- 1 | import { configDotenv } from 'dotenv'; 2 | import tsconfigPaths from 'vite-tsconfig-paths'; 3 | import { defineConfig } from 'vitest/config'; 4 | 5 | configDotenv({ path: '../../.env' }); 6 | 7 | export default defineConfig({ 8 | plugins: [tsconfigPaths()], 9 | resolve: {}, 10 | test: { 11 | environment: 'node', 12 | testTimeout: 120_000, 13 | hookTimeout: 240_000, 14 | globals: true, 15 | }, 16 | }); 17 | -------------------------------------------------------------------------------- /packages/coinex/vitest.config.ts: -------------------------------------------------------------------------------- 1 | import { configDotenv } from 'dotenv'; 2 | import tsconfigPaths from 'vite-tsconfig-paths'; 3 | import { defineConfig } from 'vitest/config'; 4 | 5 | configDotenv({ path: '../../.env' }); 6 | 7 | export default defineConfig({ 8 | plugins: [tsconfigPaths()], 9 | resolve: {}, 10 | test: { 11 | environment: 'node', 12 | testTimeout: 120_000, 13 | hookTimeout: 240_000, 14 | globals: true, 15 | }, 16 | }); 17 | -------------------------------------------------------------------------------- /packages/coinex/src/lib/delay.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Delays the execution for a specified amount of time. 3 | * @param ms - The number of milliseconds to delay. 4 | * @returns {Promise} A promise that resolves after the specified delay. 5 | * @example 6 | * await delay(1000); // Waits for 1 second 7 | */ 8 | export async function delay(ms: number): Promise { 9 | return new Promise((resolve) => { 10 | setTimeout(() => { 11 | resolve(); 12 | }, ms); 13 | }); 14 | } 15 | -------------------------------------------------------------------------------- /packages/coinex/src/modules/account/types.ts: -------------------------------------------------------------------------------- 1 | export type * from './fees/types'; 2 | export type * from './settings/types'; 3 | export type * from './subaccount/types'; 4 | 5 | /** 6 | * @interface GetAccountInfoResponse 7 | * @description Contains the response data for a user account information request. 8 | * @see https://docs.coinex.com/api/v2/account/info/http/get-account-info 9 | */ 10 | export interface GetAccountInfoResponse { 11 | /** 12 | * @property {string} user_id - User ID. 13 | */ 14 | user_id: string; 15 | } 16 | -------------------------------------------------------------------------------- /packages/coinex/src/modules/spot/module.ts: -------------------------------------------------------------------------------- 1 | import { type CoinExClient } from '@/client'; 2 | 3 | import { Deal } from './deal'; 4 | import { Market } from './market'; 5 | import { SpotOrder } from './order'; 6 | 7 | export class Spot { 8 | public readonly market: Market; 9 | public readonly deal: Deal; 10 | public readonly order: SpotOrder; 11 | 12 | constructor(client: CoinExClient) { 13 | this.market = new Market(client); 14 | this.deal = new Deal(client); 15 | this.order = new SpotOrder(client); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /.changeset/README.md: -------------------------------------------------------------------------------- 1 | # Changesets 2 | 3 | Hello and welcome! This folder has been automatically generated by `@changesets/cli`, a build tool that works 4 | with multi-package repos, or single-package repos to help you version and publish your code. You can 5 | find the full documentation for it [in our repository](https://github.com/changesets/changesets) 6 | 7 | We have a quick list of common questions to get you started engaging with this project in 8 | [our documentation](https://github.com/changesets/changesets/blob/main/docs/common-questions.md) 9 | -------------------------------------------------------------------------------- /tooling/eslint/index.mjs: -------------------------------------------------------------------------------- 1 | import { defineConfig } from '@shahrad/eslint-config'; 2 | import globals from 'globals'; 3 | 4 | export default defineConfig( 5 | { 6 | ignores: ['dist/**'], 7 | }, 8 | 9 | { 10 | languageOptions: { 11 | ecmaVersion: 'latest', 12 | sourceType: 'module', 13 | globals: { 14 | ...globals.node, 15 | }, 16 | }, 17 | rules: { 18 | 'no-console': 'error', 19 | '@typescript-eslint/no-empty-object-type': 'off', 20 | }, 21 | }, 22 | { 23 | files: ['examples/**'], 24 | rules: { 25 | 'no-console': 'off', 26 | }, 27 | } 28 | ); 29 | -------------------------------------------------------------------------------- /packages/coinex/src/lib/errors.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * @class CoinExAPIError 3 | * @extends Error 4 | * @description Custom error class for CoinEx API errors. 5 | */ 6 | export class CoinExAPIError extends Error { 7 | /** 8 | * @property {number} code - The error code from the CoinEx API. 9 | */ 10 | public readonly code: number; 11 | 12 | /** 13 | * @constructor 14 | * @param {number} code - The error code. 15 | * @param {string} message - The error message. 16 | */ 17 | constructor(code: number, message: string) { 18 | super(message); 19 | this.name = 'CoinExAPIError'; 20 | this.code = code; 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /packages/websocket/src/lib/errors.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * @class CoinExWebSocketError 3 | * @extends Error 4 | * @description Custom error class for CoinEx WebSocket API errors. 5 | */ 6 | export class CoinExWebSocketError extends Error { 7 | /** 8 | * @property {number} code - The error code from the CoinEx API. 9 | */ 10 | public readonly code: number; 11 | 12 | /** 13 | * @constructor 14 | * @param {number} code - The error code. 15 | * @param {string} message - The error message. 16 | */ 17 | constructor(code: number, message: string) { 18 | super(message); 19 | this.name = 'CoinExWebSocketError'; 20 | this.code = code; 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /packages/coinex/src/modules/futures/module.ts: -------------------------------------------------------------------------------- 1 | import { type CoinExClient } from '@/client'; 2 | 3 | import { Deal } from './deal'; 4 | import { Market } from './market'; 5 | import { FuturesOrder } from './order/module'; 6 | import { Position } from './position'; 7 | 8 | export class Futures { 9 | public readonly market: Market; 10 | public readonly deal: Deal; 11 | public readonly order: FuturesOrder; 12 | public readonly position: Position; 13 | 14 | constructor(client: CoinExClient) { 15 | this.market = new Market(client); 16 | this.deal = new Deal(client); 17 | this.order = new FuturesOrder(client); 18 | this.position = new Position(client); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /packages/coinex/src/client.test.ts: -------------------------------------------------------------------------------- 1 | import { describe, expect, it } from 'vitest'; 2 | 3 | import { CoinExClient } from '@/client'; 4 | 5 | describe('CoinExClient', () => { 6 | const client = new CoinExClient({ 7 | apiKey: 'placeholder_api_key', 8 | secretKey: 'placeholder_secret_key', 9 | }); 10 | 11 | it('should ping the server successfully', async () => { 12 | const response = await client.ping(); 13 | expect(response).toEqual({ result: 'pong' }); 14 | }); 15 | 16 | it('should get system time successfully', async () => { 17 | const response = await client.getSystemTime(); 18 | expect(typeof response.timestamp).toBe('number'); 19 | expect(response.timestamp).toBeGreaterThan(0); 20 | }); 21 | }); 22 | -------------------------------------------------------------------------------- /packages/coinex/src/index.ts: -------------------------------------------------------------------------------- 1 | export * from './client'; 2 | export * from './types'; 3 | export * from './lib/errors'; 4 | export * from './lib/object'; 5 | export { 6 | AmmType, 7 | ContractType, 8 | DepositStatus, 9 | Locale, 10 | LoanStatus, 11 | MarginMode, 12 | MarketStatus, 13 | MarketType, 14 | OrderEvent, 15 | OrderSide, 16 | OrderStatus, 17 | OrderType, 18 | Permission, 19 | PositionEvent, 20 | PositionFinishedType, 21 | PositionSide, 22 | StopOrderEvent, 23 | StopOrderStatus, 24 | StopLossType, 25 | StpMode, 26 | TakeProfitType, 27 | TransactionType, 28 | TransferDirection, 29 | TransferStatus, 30 | TriggerDirection, 31 | TriggerPriceType, 32 | UserType, 33 | } from '@coinex-org/internal-shared'; 34 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "coinex-monorepo", 3 | "version": "0.0.1", 4 | "private": true, 5 | "scripts": { 6 | "build": "pnpm -r build", 7 | "ci:publish": "changeset publish", 8 | "clean": "git clean -dfx node_modules", 9 | "format": "prettier --write \"**/*.{ts,tsx,md}\"", 10 | "format:check": "prettier --check \"**/*.{ts,tsx,md}\"", 11 | "lint": "pnpm -r lint", 12 | "test": "pnpm -r test" 13 | }, 14 | "prettier": "@shahrad/prettier-config", 15 | "devDependencies": { 16 | "@changesets/cli": "^2.29.5", 17 | "@shahrad/prettier-config": "^1.2.2", 18 | "@types/node": "^22.13.14", 19 | "prettier": "^3.6.2", 20 | "typescript": "^5.9.2" 21 | }, 22 | "packageManager": "pnpm@9.15.9", 23 | "engines": { 24 | "node": ">=18", 25 | "pnpm": "9.x" 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /packages/websocket/src/modules/spot/ticker/index.ts: -------------------------------------------------------------------------------- 1 | import type { AuthenticatedWebSocket } from '@/lib/websocket'; 2 | 3 | import { SpotBbo } from './bbo'; 4 | import { SpotDeals } from './deals'; 5 | import { SpotDepth } from './depth'; 6 | import { SpotIndex } from './index/module'; 7 | import { SpotState } from './state'; 8 | 9 | export class SpotTicker { 10 | public readonly state: SpotState; 11 | public readonly depth: SpotDepth; 12 | public readonly deals: SpotDeals; 13 | public readonly index: SpotIndex; 14 | public readonly bbo: SpotBbo; 15 | 16 | constructor(ws: AuthenticatedWebSocket) { 17 | this.state = new SpotState(ws); 18 | this.depth = new SpotDepth(ws); 19 | this.deals = new SpotDeals(ws); 20 | this.index = new SpotIndex(ws); 21 | this.bbo = new SpotBbo(ws); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.yml: -------------------------------------------------------------------------------- 1 | name: 🛠️ Request New Feature 2 | description: Let us know what you would like to see added. 3 | labels: [feature] 4 | body: 5 | - type: textarea 6 | attributes: 7 | label: New feature motivation 8 | description: Describe the context, the use-case and the advantages of the feature request. 9 | validations: 10 | required: true 11 | 12 | - type: textarea 13 | attributes: 14 | label: New feature description 15 | description: Describe the functional changes that would have to be made. 16 | validations: 17 | required: true 18 | 19 | - type: textarea 20 | attributes: 21 | label: New feature implementation 22 | description: Optionally describe the technical changes to be made. 23 | validations: 24 | required: false 25 | -------------------------------------------------------------------------------- /packages/websocket/src/lib/crypto.ts: -------------------------------------------------------------------------------- 1 | import { createHmac } from 'node:crypto'; 2 | 3 | /** 4 | * Generates an HMAC-SHA256 signature for a CoinEx WebSocket authentication request. 5 | * @param timestamp - The millisecond-level timestamp. 6 | * @param secretKey - The user's secret key. 7 | * @returns The lowercase hexadecimal signature. 8 | * @see https://docs.coinex.com/api/v2/authorization 9 | */ 10 | export function signWebSocketRequest(timestamp: number, secretKey: string): string { 11 | // prepared_str = "1700490703564" 12 | // signed_str = hmac.new(bytes(secret_key, 'latin-1'), msg=bytes(prepared_str, 'latin-1'), digestmod=hashlib.sha256).hexdigest().lower() 13 | const preparedStr = String(timestamp); 14 | const hmac = createHmac('sha256', secretKey); 15 | hmac.update(preparedStr); 16 | return hmac.digest('hex').toLowerCase(); 17 | } 18 | -------------------------------------------------------------------------------- /packages/websocket/src/modules/futures/ticker/index.ts: -------------------------------------------------------------------------------- 1 | import type { AuthenticatedWebSocket } from '@/lib/websocket'; 2 | 3 | import { FuturesBbo } from './bbo'; 4 | import { FuturesDeals } from './deals'; 5 | import { FuturesDepth } from './depth'; 6 | import { FuturesIndex } from './index/module'; 7 | import { FuturesState } from './state'; 8 | 9 | export class Ticker { 10 | public readonly bbo: FuturesBbo; 11 | public readonly deals: FuturesDeals; 12 | public readonly depth: FuturesDepth; 13 | public readonly state: FuturesState; 14 | public readonly index: FuturesIndex; 15 | 16 | constructor(ws: AuthenticatedWebSocket) { 17 | this.bbo = new FuturesBbo(ws); 18 | this.deals = new FuturesDeals(ws); 19 | this.depth = new FuturesDepth(ws); 20 | this.state = new FuturesState(ws); 21 | this.index = new FuturesIndex(ws); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /packages/coinex/src/modules/assets/module.ts: -------------------------------------------------------------------------------- 1 | import { type CoinExClient } from '@/client'; 2 | 3 | import { Amm } from './amm'; 4 | import { Balance } from './balance'; 5 | import { BorrowRepay } from './borrow-repay'; 6 | import { DepositWithdrawal } from './deposit-withdrawal'; 7 | import { Transfer } from './transfer'; 8 | 9 | export class Assets { 10 | public readonly amm: Amm; 11 | public readonly balance: Balance; 12 | public readonly borrowRepay: BorrowRepay; 13 | public readonly depositWithdrawal: DepositWithdrawal; 14 | public readonly transfer: Transfer; 15 | 16 | constructor(client: CoinExClient) { 17 | this.amm = new Amm(client); 18 | this.balance = new Balance(client); 19 | this.borrowRepay = new BorrowRepay(client); 20 | this.depositWithdrawal = new DepositWithdrawal(client); 21 | this.transfer = new Transfer(client); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.yml: -------------------------------------------------------------------------------- 1 | name: 🐞 Bug Report 2 | description: Something not working as expected 3 | labels: [bug] 4 | body: 5 | - type: textarea 6 | attributes: 7 | label: Current behavior 8 | description: Describe how the issue manifests and please include relevant error messages and steps to reproduce it. 9 | validations: 10 | required: true 11 | 12 | - type: textarea 13 | attributes: 14 | label: Expected behavior 15 | description: Describe what the desired behavior would be. 16 | validations: 17 | required: true 18 | 19 | - type: textarea 20 | attributes: 21 | label: Versions 22 | description: What versions of the package are you using? 23 | placeholder: | 24 | @coinex-org/coinex@0.0.0 25 | @coinex-org/websocket@0.0.0 26 | node@22.0.0 27 | validations: 28 | required: true 29 | -------------------------------------------------------------------------------- /packages/coinex/src/lib/crypto.ts: -------------------------------------------------------------------------------- 1 | import { createHmac } from 'node:crypto'; 2 | 3 | /** 4 | * Generates an HMAC-SHA256 signature for a CoinEx API request. 5 | * @param method - The uppercase HTTP method (e.g., 'GET', 'POST'). 6 | * @param path - The request path, including any query parameters. 7 | * @param body - The request body (for POST requests). 8 | * @param timestamp - The millisecond-level timestamp. 9 | * @param secretKey - The user's secret key. 10 | * @returns The lowercase hexadecimal signature. 11 | */ 12 | export function signRequest( 13 | method: string, 14 | path: string, 15 | body: string | undefined, 16 | timestamp: number, 17 | secretKey: string 18 | ): string { 19 | const preparedStr = `${method.toUpperCase()}${path}${body || ''}${timestamp}`; 20 | const hmac = createHmac('sha256', secretKey); 21 | hmac.update(preparedStr); 22 | return hmac.digest('hex').toLowerCase(); 23 | } 24 | -------------------------------------------------------------------------------- /packages/coinex/src/lib/object.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Removes properties with `undefined` values from an object. 3 | * @param obj - The object to filter. 4 | * @param deep - Whether to filter deeply. 5 | * @returns {T} A new object without `undefined` properties. 6 | * @example 7 | * const obj = { a: 1, b: undefined, c: { d: 2, e: undefined } }; 8 | * const newObj = noUndefined(obj); // { a: 1, c: { d: 2, e: undefined } } 9 | * const deepNewObj = noUndefined(obj, true); // { a: 1, c: { d: 2 } } 10 | */ 11 | export function noUndefined(obj: T, deep: boolean = false): T { 12 | const newObj: Partial = {} as Partial; 13 | for (const key in obj) { 14 | if (obj[key] !== undefined) { 15 | if (deep && typeof obj[key] === 'object' && obj[key] !== null) { 16 | (newObj as any)[key] = noUndefined(obj[key] as any, true); 17 | } else { 18 | newObj[key] = obj[key]; 19 | } 20 | } 21 | } 22 | return newObj as T; 23 | } 24 | -------------------------------------------------------------------------------- /packages/websocket/src/modules/futures/index.ts: -------------------------------------------------------------------------------- 1 | import { AuthenticatedWebSocket } from '@/lib/websocket'; 2 | import type { CoinExWebSocketOptions } from '@/types'; 3 | 4 | import { Executions } from './executions'; 5 | import { Orders } from './orders'; 6 | import { Position } from './position'; 7 | import { Ticker } from './ticker'; 8 | 9 | export class Futures { 10 | public readonly ws: AuthenticatedWebSocket; 11 | public readonly ticker: Ticker; 12 | public readonly orders: Orders; 13 | public readonly executions: Executions; 14 | public readonly position: Position; 15 | 16 | constructor(options: CoinExWebSocketOptions) { 17 | this.ws = new AuthenticatedWebSocket({ 18 | ...options, 19 | baseUrl: 'wss://socket.coinex.com/v2/futures', 20 | }); 21 | this.ticker = new Ticker(this.ws); 22 | this.orders = new Orders(this.ws); 23 | this.executions = new Executions(this.ws); 24 | this.position = new Position(this.ws); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /packages/websocket/src/modules/spot/index.ts: -------------------------------------------------------------------------------- 1 | import { AuthenticatedWebSocket } from '@/lib/websocket'; 2 | import type { CoinExWebSocketOptions } from '@/types'; 3 | 4 | import { SpotBalance } from './balance'; 5 | import { SpotExecutions } from './executions'; 6 | import { SpotOrders } from './orders'; 7 | import { SpotTicker } from './ticker'; 8 | 9 | export class Spot { 10 | public readonly ws: AuthenticatedWebSocket; 11 | 12 | public readonly balance: SpotBalance; 13 | public readonly executions: SpotExecutions; 14 | public readonly orders: SpotOrders; 15 | public readonly ticker: SpotTicker; 16 | 17 | constructor(options: CoinExWebSocketOptions) { 18 | this.ws = new AuthenticatedWebSocket({ 19 | ...options, 20 | baseUrl: 'wss://socket.coinex.com/v2/spot', 21 | }); 22 | 23 | this.balance = new SpotBalance(this.ws); 24 | this.ticker = new SpotTicker(this.ws); 25 | this.orders = new SpotOrders(this.ws); 26 | this.executions = new SpotExecutions(this.ws); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /packages/websocket/examples/common.ts: -------------------------------------------------------------------------------- 1 | import { CoinExWebSocket } from '../src'; 2 | 3 | import 'dotenv/config'; 4 | 5 | const apiKey = process.env.API_KEY; 6 | const secretKey = process.env.SECRET_KEY; 7 | 8 | if (!apiKey || !secretKey) { 9 | throw new Error('API_KEY and SECRET_KEY must be provided in .env file'); 10 | } 11 | 12 | const client = new CoinExWebSocket({ 13 | apiKey, 14 | secretKey, 15 | autoConnect: false, 16 | }); 17 | 18 | client.on('error', (error, type) => { 19 | console.error(`Error on ${type} WebSocket:`, error); 20 | }); 21 | 22 | async function run() { 23 | try { 24 | console.log('Connecting to CoinEx...'); 25 | await client.connect(); 26 | console.log('Connected!'); 27 | console.log(); 28 | 29 | const pingResponse = await client.ping(); 30 | console.log('Ping:', pingResponse); 31 | 32 | const timeResponse = await client.getServerTime(); 33 | console.log('Server Time:', timeResponse); 34 | 35 | console.log(); 36 | } catch (error) { 37 | console.error('An error occurred:', error); 38 | } 39 | } 40 | 41 | run(); 42 | -------------------------------------------------------------------------------- /.prettierignore: -------------------------------------------------------------------------------- 1 | # Dependencies 2 | node_modules/ 3 | .pnpm-store/ 4 | .bower_components/ 5 | 6 | # Build output 7 | /build/ 8 | /dist/ 9 | /out/ 10 | /target/ 11 | .lib/ 12 | /esm/ 13 | /cjs/ 14 | .next/ 15 | .cache/ 16 | /public 17 | .nuxt/ 18 | /.svelte-kit 19 | *.tsbuildinfo 20 | 21 | # Test & coverage 22 | coverage/ 23 | nyc_output/ 24 | jest/ 25 | test-results/ 26 | *.lcov 27 | 28 | # Logs & runtime data 29 | *.log 30 | npm-debug.log* 31 | yarn-debug.log* 32 | yarn-error.log* 33 | pnpm-debug.log* 34 | pids/ 35 | *.pid 36 | *.pid.lock 37 | *.seed 38 | 39 | # Vercel & other deployment 40 | .vercel 41 | .contentlayer 42 | 43 | # Environment files 44 | .env 45 | .env.* 46 | !.env.example 47 | 48 | # Package manager lockfiles 49 | pnpm-lock.yaml 50 | package-lock.json 51 | yarn.lock 52 | 53 | # IDE / editor 54 | .vscode/ 55 | /.vscode-test/ 56 | .idea/ 57 | *.suo 58 | *.ntvs* 59 | *.njsproj 60 | *.sln 61 | *.sw? 62 | 63 | # Miscellaneous 64 | .changeset/ 65 | .grunt/ 66 | lib-cov/ 67 | .DS_Store 68 | Thumbs.db 69 | *.7z 70 | *.dmg 71 | *.gz 72 | *.iso 73 | *.jar 74 | *.rar 75 | *.tar 76 | *.zip 77 | -------------------------------------------------------------------------------- /packages/websocket/src/modules/spot/ticker/index/types.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * @interface SpotIndexSubscriptionParams 3 | * @description Parameters for subscribing to market index updates. 4 | */ 5 | export interface SpotIndexSubscriptionParams { 6 | /** 7 | * @property {string[]} market_list - List of market names. 8 | */ 9 | market_list: string[]; 10 | } 11 | 12 | /** 13 | * @interface SpotIndexUnsubscribeParams 14 | * @description Parameters for unsubscribing from market index updates. 15 | */ 16 | export interface SpotIndexUnsubscribeParams { 17 | /** 18 | * @property {string[]} market_list - List of market names to unsubscribe from. An empty array unsubscribes from all. 19 | */ 20 | market_list: string[]; 21 | } 22 | 23 | /** 24 | * @interface SpotIndexUpdate 25 | * @description Represents a market index update push from the server. 26 | */ 27 | export interface SpotIndexUpdate { 28 | /** 29 | * @property {string} market - Market name. 30 | */ 31 | market: string; 32 | /** 33 | * @property {string} index_price - Index price. 34 | */ 35 | index_price: string; 36 | } 37 | -------------------------------------------------------------------------------- /packages/coinex/.prettierignore: -------------------------------------------------------------------------------- 1 | # Dependencies 2 | node_modules/ 3 | .pnpm-store/ 4 | .bower_components/ 5 | 6 | # Build output 7 | /build/ 8 | /dist/ 9 | /out/ 10 | /target/ 11 | .lib/ 12 | /esm/ 13 | /cjs/ 14 | .next/ 15 | .cache/ 16 | /public 17 | .nuxt/ 18 | /.svelte-kit 19 | *.tsbuildinfo 20 | 21 | # Test & coverage 22 | coverage/ 23 | nyc_output/ 24 | jest/ 25 | test-results/ 26 | *.lcov 27 | 28 | # Logs & runtime data 29 | *.log 30 | npm-debug.log* 31 | yarn-debug.log* 32 | yarn-error.log* 33 | pnpm-debug.log* 34 | pids/ 35 | *.pid 36 | *.pid.lock 37 | *.seed 38 | 39 | # Vercel & other deployment 40 | .vercel 41 | .contentlayer 42 | 43 | # Environment files 44 | .env 45 | .env.* 46 | !.env.example 47 | 48 | # Package manager lockfiles 49 | pnpm-lock.yaml 50 | package-lock.json 51 | yarn.lock 52 | 53 | # IDE / editor 54 | .vscode/ 55 | /.vscode-test/ 56 | .idea/ 57 | *.suo 58 | *.ntvs* 59 | *.njsproj 60 | *.sln 61 | *.sw? 62 | 63 | # Miscellaneous 64 | .changeset/ 65 | .grunt/ 66 | lib-cov/ 67 | .DS_Store 68 | Thumbs.db 69 | *.7z 70 | *.dmg 71 | *.gz 72 | *.iso 73 | *.jar 74 | *.rar 75 | *.tar 76 | *.zip 77 | -------------------------------------------------------------------------------- /packages/websocket/.prettierignore: -------------------------------------------------------------------------------- 1 | # Dependencies 2 | node_modules/ 3 | .pnpm-store/ 4 | .bower_components/ 5 | 6 | # Build output 7 | /build/ 8 | /dist/ 9 | /out/ 10 | /target/ 11 | .lib/ 12 | /esm/ 13 | /cjs/ 14 | .next/ 15 | .cache/ 16 | /public 17 | .nuxt/ 18 | /.svelte-kit 19 | *.tsbuildinfo 20 | 21 | # Test & coverage 22 | coverage/ 23 | nyc_output/ 24 | jest/ 25 | test-results/ 26 | *.lcov 27 | 28 | # Logs & runtime data 29 | *.log 30 | npm-debug.log* 31 | yarn-debug.log* 32 | yarn-error.log* 33 | pnpm-debug.log* 34 | pids/ 35 | *.pid 36 | *.pid.lock 37 | *.seed 38 | 39 | # Vercel & other deployment 40 | .vercel 41 | .contentlayer 42 | 43 | # Environment files 44 | .env 45 | .env.* 46 | !.env.example 47 | 48 | # Package manager lockfiles 49 | pnpm-lock.yaml 50 | package-lock.json 51 | yarn.lock 52 | 53 | # IDE / editor 54 | .vscode/ 55 | /.vscode-test/ 56 | .idea/ 57 | *.suo 58 | *.ntvs* 59 | *.njsproj 60 | *.sln 61 | *.sw? 62 | 63 | # Miscellaneous 64 | .changeset/ 65 | .grunt/ 66 | lib-cov/ 67 | .DS_Store 68 | Thumbs.db 69 | *.7z 70 | *.dmg 71 | *.gz 72 | *.iso 73 | *.jar 74 | *.rar 75 | *.tar 76 | *.zip 77 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2025 Shahrad Elahi 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /.github/workflows/release.yml: -------------------------------------------------------------------------------- 1 | name: Release Package 2 | 3 | on: 4 | push: 5 | branches: 6 | - main 7 | 8 | jobs: 9 | release: 10 | if: github.repository == 'shahradelahi/coinex' 11 | name: Build & Publish Release 12 | runs-on: ubuntu-latest 13 | permissions: 14 | contents: write 15 | id-token: write 16 | pull-requests: write 17 | steps: 18 | - name: Checkout Repo 19 | uses: actions/checkout@v4 20 | with: 21 | fetch-depth: 0 22 | 23 | - name: Use PNPM v9 24 | uses: pnpm/action-setup@v4 25 | 26 | - name: Use Node v22 27 | uses: actions/setup-node@v4 28 | with: 29 | node-version: 22 30 | cache: pnpm 31 | 32 | - name: Install dependencies 33 | run: pnpm install --frozen-lockfile 34 | 35 | - name: Create Release Pull Request or Publish 36 | id: changesets 37 | uses: changesets/action@v1 38 | with: 39 | commit: 'chore(release): version package' 40 | title: 'chore(release): version package' 41 | publish: pnpm ci:publish 42 | env: 43 | NPM_TOKEN: ${{ secrets.NPM_TOKEN }} 44 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 45 | -------------------------------------------------------------------------------- /packages/coinex/src/modules/maintain/module.ts: -------------------------------------------------------------------------------- 1 | import { type CoinExClient } from '@/client'; 2 | import type { RequestOptions } from '@/types'; 3 | 4 | import type { GetMaintenanceInfoResponse } from './types'; 5 | 6 | export class Maintain { 7 | #client: CoinExClient; 8 | 9 | constructor(client: CoinExClient) { 10 | this.#client = client; 11 | } 12 | 13 | /** 14 | * Get Maintenance Information 15 | * @description 16 | * The protection period refers to a continuous period following the system maintenance (It's an optional configuration, and may or may not be set). During the protection period, you can cancel orders, place orders (limited to Maker Only Limit Orders), and adjust (add or reduce) margins. 17 | * @param options - The options for the request. 18 | * @returns {Promise} Maintenance information. 19 | * @see https://docs.coinex.com/api/v2/common/http/maintain 20 | */ 21 | getMaintenanceInfo(options: RequestOptions = {}): Promise { 22 | return this.#client.request('maintain/info', { 23 | method: 'GET', 24 | ...options, 25 | context: { 26 | public: true, 27 | }, 28 | }); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /packages/coinex/src/modules/account/fees/module.ts: -------------------------------------------------------------------------------- 1 | import deepmerge from 'deepmerge'; 2 | 3 | import { type CoinExClient } from '@/client'; 4 | import { noUndefined } from '@/lib/object'; 5 | import type { RequestOptions } from '@/types'; 6 | 7 | import type { GetAccountTradeFeesParams, GetAccountTradeFeesResponse } from './types'; 8 | 9 | export class Fees { 10 | #client: CoinExClient; 11 | 12 | constructor(client: CoinExClient) { 13 | this.#client = client; 14 | } 15 | 16 | /** 17 | * Get Account Trading Fee Rate 18 | * 19 | * @param params - The parameters for the request. 20 | * @param options - The options for the request. 21 | * @returns {Promise} The account trading fee rate. 22 | * @see https://docs.coinex.com/api/v2/account/fees/http/get-account-trade-fees 23 | */ 24 | getAccountTradeFees( 25 | params: GetAccountTradeFeesParams, 26 | options: RequestOptions = {} 27 | ): Promise { 28 | return this.#client.request( 29 | 'account/trade-fees', 30 | deepmerge( 31 | { 32 | method: 'GET', 33 | searchParams: noUndefined(params), 34 | }, 35 | options 36 | ) 37 | ); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /packages/websocket/src/modules/futures/ticker/index/types.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * @interface FuturesIndexSubscriptionParams 3 | * @description Parameters for subscribing to market index updates. 4 | */ 5 | export interface FuturesIndexSubscriptionParams { 6 | /** 7 | * @property {string[]} market_list - List of market names. 8 | * @description An empty array subscribes to all markets. 9 | */ 10 | market_list: string[]; 11 | } 12 | 13 | /** 14 | * @interface FuturesIndexUnsubscribeParams 15 | * @description Parameters for unsubscribing from market index updates. 16 | */ 17 | export interface FuturesIndexUnsubscribeParams { 18 | /** 19 | * @property {string[]} market_list - List of market names to unsubscribe from. An empty array unsubscribes from all. 20 | */ 21 | market_list: string[]; 22 | } 23 | 24 | /** 25 | * @interface FuturesIndexUpdate 26 | * @description Represents a market index update push from the server. 27 | */ 28 | export interface FuturesIndexUpdate { 29 | /** 30 | * @property {string} market - Market name. 31 | */ 32 | market: string; 33 | /** 34 | * @property {string} index_price - Index price. 35 | */ 36 | index_price: string; 37 | /** 38 | * @property {string} mark_price - Mark price. 39 | */ 40 | mark_price: string; 41 | } 42 | -------------------------------------------------------------------------------- /internal/shared/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@coinex-org/internal-shared", 3 | "version": "0.0.0", 4 | "private": true, 5 | "description": "Shared types and enums for CoinEx API clients", 6 | "keywords": [ 7 | "coinex", 8 | "shared", 9 | "enums", 10 | "types" 11 | ], 12 | "type": "module", 13 | "exports": { 14 | ".": { 15 | "types": "./dist/index.d.ts", 16 | "import": "./dist/index.js", 17 | "default": "./dist/index.cjs" 18 | } 19 | }, 20 | "files": [ 21 | "dist/**", 22 | "!**/*.d.cts" 23 | ], 24 | "scripts": { 25 | "build": "tsup", 26 | "clean": "git clean -xdf node_modules dist .tsbuildinfo", 27 | "dev": "tsup --watch", 28 | "format": "prettier --write ", 29 | "format:check": "prettier --check ", 30 | "lint": "pnpm typecheck && eslint ", 31 | "lint:fix": "eslint --fix ", 32 | "typecheck": "tsc --noEmit" 33 | }, 34 | "devDependencies": { 35 | "@coinex-org/eslint-config": "workspace:*", 36 | "@shahrad/tsconfig": "^1.0.0", 37 | "@types/node": "^22.13.14", 38 | "dotenv": "^17.2.1", 39 | "eslint": "^9.23.0", 40 | "globals": "^16.0.0", 41 | "tsup": "^8.5.0", 42 | "tsx": "^4.20.3", 43 | "typescript": "^5.9.2", 44 | "vite-tsconfig-paths": "^5.1.4", 45 | "vitest": "^3.2.4" 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | name: CI 2 | 3 | on: 4 | push: 5 | branches: 6 | - main 7 | pull_request: 8 | 9 | concurrency: 10 | group: '${{ github.workflow }}-${{ github.event.number || github.sha }}' 11 | cancel-in-progress: true 12 | 13 | jobs: 14 | format: 15 | runs-on: ubuntu-latest 16 | steps: 17 | - uses: actions/checkout@v4 18 | - uses: pnpm/action-setup@v4 19 | - uses: actions/setup-node@v4 20 | with: 21 | node-version: 22 22 | cache: 'pnpm' 23 | 24 | - run: pnpm install --frozen-lockfile 25 | - run: pnpm format:check 26 | 27 | lint: 28 | runs-on: ubuntu-latest 29 | steps: 30 | - uses: actions/checkout@v4 31 | - uses: pnpm/action-setup@v4 32 | - uses: actions/setup-node@v4 33 | with: 34 | node-version: 22 35 | cache: 'pnpm' 36 | 37 | - run: pnpm install --frozen-lockfile 38 | - run: pnpm lint 39 | 40 | tests: 41 | runs-on: ubuntu-latest 42 | steps: 43 | - uses: actions/checkout@v4 44 | - uses: pnpm/action-setup@v4 45 | - uses: actions/setup-node@v4 46 | with: 47 | node-version: 22 48 | cache: 'pnpm' 49 | 50 | - run: pnpm install --frozen-lockfile 51 | - name: Run tests with placeholder API keys 52 | run: pnpm test 53 | -------------------------------------------------------------------------------- /packages/coinex/src/modules/account/fees/types.ts: -------------------------------------------------------------------------------- 1 | import { type MarketType } from '@coinex-org/internal-shared'; 2 | 3 | /** 4 | * @interface GetAccountTradeFeesParams 5 | * @description Parameters for getting the account trading fee rate. 6 | * @see https://docs.coinex.com/api/v2/account/fees/http/get-account-trade-fees 7 | */ 8 | export interface GetAccountTradeFeesParams { 9 | /** 10 | * @property {MarketType} [market_type] - Market type. 11 | * @description If not passed, the default is spot market. 12 | * @example MarketType.SPOT 13 | */ 14 | market_type?: MarketType; 15 | } 16 | 17 | /** 18 | * @interface Fee 19 | * @description Trading fee rate details. 20 | */ 21 | export interface Fee { 22 | /** 23 | * @property {string} market - Market name. 24 | * @example "BTCUSDT" 25 | */ 26 | market: string; 27 | /** 28 | * @property {string} taker_fee - Taker fee rate. 29 | * @example "0.002" 30 | */ 31 | taker_fee: string; 32 | /** 33 | * @property {string} maker_fee - Maker fee rate. 34 | * @example "0.001" 35 | */ 36 | maker_fee: string; 37 | } 38 | 39 | /** 40 | * @type GetAccountTradeFeesResponse 41 | * @description Represents the response from the Get Account Trading Fee Rate endpoint, which is an array of fee structures. 42 | */ 43 | export type GetAccountTradeFeesResponse = Fee[]; 44 | -------------------------------------------------------------------------------- /packages/coinex/src/modules/account/module.ts: -------------------------------------------------------------------------------- 1 | import deepmerge from 'deepmerge'; 2 | 3 | import { type CoinExClient } from '@/client'; 4 | import { type RequestOptions } from '@/types'; 5 | 6 | import { Fees } from './fees'; 7 | import { Settings } from './settings'; 8 | import { SubAccount } from './subaccount'; 9 | import { type GetAccountInfoResponse } from './types'; 10 | 11 | export class Account { 12 | #client: CoinExClient; 13 | public readonly subaccount: SubAccount; 14 | public readonly fees: Fees; 15 | public readonly settings: Settings; 16 | 17 | constructor(client: CoinExClient) { 18 | this.#client = client; 19 | this.subaccount = new SubAccount(client); 20 | this.fees = new Fees(client); 21 | this.settings = new Settings(client); 22 | } 23 | 24 | /** 25 | * Get User Account Info 26 | * @param options - The options for the request. 27 | * @returns {Promise} The user account info. 28 | * @see https://docs.coinex.com/api/v2/account/info/http/get-account-info 29 | */ 30 | getAccountInfo(options: RequestOptions = {}): Promise { 31 | return this.#client.request( 32 | 'account/info', 33 | deepmerge( 34 | { 35 | method: 'GET', 36 | }, 37 | options 38 | ) 39 | ); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /packages/websocket/src/modules/spot/ticker/bbo/module.ts: -------------------------------------------------------------------------------- 1 | import type { AuthenticatedWebSocket } from '@/lib/websocket'; 2 | 3 | import type { SpotBboSubscriptionParams, SpotBboUnsubscribeParams, SpotBboUpdate } from './types'; 4 | 5 | export class SpotBbo { 6 | #ws: AuthenticatedWebSocket; 7 | 8 | constructor(ws: AuthenticatedWebSocket) { 9 | this.#ws = ws; 10 | } 11 | 12 | /** 13 | * Subscribes to BBO updates. 14 | * @param params - The subscription parameters. 15 | * @param onUpdate - The callback function to handle updates. 16 | * @see https://docs.coinex.com/api/v2/spot/market/ws/market-bbo 17 | */ 18 | subscribe(params: SpotBboSubscriptionParams, onUpdate: (update: SpotBboUpdate) => void): number { 19 | const id = this.#ws.send({ method: 'bbo.subscribe', params }); 20 | this.#ws.on('message', (message: { method: string; data: SpotBboUpdate }) => { 21 | if (message.method === 'bbo.update') { 22 | onUpdate(message.data); 23 | } 24 | }); 25 | return id; 26 | } 27 | 28 | /** 29 | * Unsubscribes from BBO updates. 30 | * @param params - The unsubscription parameters. 31 | * @see https://docs.coinex.com/api/v2/spot/market/ws/market-bbo 32 | */ 33 | unsubscribe(params: SpotBboUnsubscribeParams): number { 34 | return this.#ws.send({ method: 'bbo.unsubscribe', params }); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /packages/websocket/src/modules/spot/balance/module.ts: -------------------------------------------------------------------------------- 1 | import type { AuthenticatedWebSocket } from '@/lib/websocket'; 2 | 3 | import type { SpotBalanceSubscriptionParams, SpotBalanceUpdate } from './types'; 4 | 5 | export class SpotBalance { 6 | #ws: AuthenticatedWebSocket; 7 | 8 | constructor(ws: AuthenticatedWebSocket) { 9 | this.#ws = ws; 10 | } 11 | 12 | /** 13 | * Subscribes to asset balance updates. 14 | * @param params - The subscription parameters. 15 | * @param onUpdate - The callback function to handle updates. 16 | * @see https://docs.coinex.com/api/v2/assets/balance/ws/spot_balance 17 | */ 18 | subscribe( 19 | params: SpotBalanceSubscriptionParams, 20 | onUpdate: (update: SpotBalanceUpdate) => void 21 | ): number { 22 | const id = this.#ws.send({ method: 'balance.subscribe', params }); 23 | this.#ws.on('message', (message: { method: string; data: SpotBalanceUpdate }) => { 24 | if (message.method === 'balance.update') { 25 | onUpdate(message.data); 26 | } 27 | }); 28 | return id; 29 | } 30 | 31 | /** 32 | * Unsubscribes from asset balance updates. 33 | * @param params - The unsubscription parameters. 34 | * @see https://docs.coinex.com/api/v2/assets/balance/ws/spot_balance 35 | */ 36 | unsubscribe(params: SpotBalanceSubscriptionParams): number { 37 | return this.#ws.send({ method: 'balance.unsubscribe', params }); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /packages/websocket/src/modules/futures/ticker/bbo/module.ts: -------------------------------------------------------------------------------- 1 | import type { AuthenticatedWebSocket } from '@/lib/websocket'; 2 | 3 | import type { 4 | FuturesBboSubscriptionParams, 5 | FuturesBboUnsubscribeParams, 6 | FuturesBboUpdate, 7 | } from './types'; 8 | 9 | export class FuturesBbo { 10 | #ws: AuthenticatedWebSocket; 11 | 12 | constructor(ws: AuthenticatedWebSocket) { 13 | this.#ws = ws; 14 | } 15 | 16 | /** 17 | * Subscribes to BBO updates. 18 | * @param params - The subscription parameters. 19 | * @param onUpdate - The callback function to handle updates. 20 | * @see https://docs.coinex.com/api/v2/futures/market/ws/market-bbo 21 | */ 22 | subscribe( 23 | params: FuturesBboSubscriptionParams, 24 | onUpdate: (update: FuturesBboUpdate) => void 25 | ): number { 26 | const id = this.#ws.send({ method: 'bbo.subscribe', params }); 27 | this.#ws.on('message', (message: { method: string; data: FuturesBboUpdate }) => { 28 | if (message.method === 'bbo.update') { 29 | onUpdate(message.data); 30 | } 31 | }); 32 | return id; 33 | } 34 | 35 | /** 36 | * Unsubscribes from BBO updates. 37 | * @param params - The unsubscription parameters. 38 | * @see https://docs.coinex.com/api/v2/futures/market/ws/market-bbo 39 | */ 40 | unsubscribe(params: FuturesBboUnsubscribeParams): number { 41 | return this.#ws.send({ method: 'bbo.unsubscribe', params }); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /packages/websocket/src/modules/spot/balance/types.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * @interface SpotBalanceSubscriptionParams 3 | * @description Parameters for subscribing to asset balance updates. 4 | */ 5 | export interface SpotBalanceSubscriptionParams { 6 | /** 7 | * @property {string[]} ccy_list - List of asset names. 8 | * @description An empty array subscribes to all asset balances. 9 | */ 10 | ccy_list: string[]; 11 | } 12 | 13 | /** 14 | * @interface SpotBalance 15 | * @description Represents the balance of a single asset. 16 | */ 17 | export interface SpotBalance { 18 | /** 19 | * @property {string | null} margin_market - Margin account name, null for non-margin markets. 20 | */ 21 | margin_market: string | null; 22 | /** 23 | * @property {string} ccy - Asset name. 24 | */ 25 | ccy: string; 26 | /** 27 | * @property {string} available - Balance available. 28 | */ 29 | available: string; 30 | /** 31 | * @property {string} frozen - Frozen balance. 32 | */ 33 | frozen: string; 34 | /** 35 | * @property {number} updated_at - Latest update timestamp (millisecond). 36 | */ 37 | updated_at: number; 38 | } 39 | 40 | /** 41 | * @interface SpotBalanceUpdate 42 | * @description Represents a balance update push from the server. 43 | */ 44 | export interface SpotBalanceUpdate { 45 | /** 46 | * @property {SpotBalance[]} balance_list - List of updated balances. 47 | */ 48 | balance_list: SpotBalance[]; 49 | } 50 | -------------------------------------------------------------------------------- /packages/websocket/src/modules/spot/ticker/deals/module.ts: -------------------------------------------------------------------------------- 1 | import type { AuthenticatedWebSocket } from '@/lib/websocket'; 2 | 3 | import type { 4 | SpotDealsSubscriptionParams, 5 | SpotDealsUnsubscribeParams, 6 | SpotDealsUpdate, 7 | } from './types'; 8 | 9 | export class SpotDeals { 10 | #ws: AuthenticatedWebSocket; 11 | 12 | constructor(ws: AuthenticatedWebSocket) { 13 | this.#ws = ws; 14 | } 15 | 16 | /** 17 | * Subscribes to market deals updates. 18 | * @param params - The subscription parameters. 19 | * @param onUpdate - The callback function to handle updates. 20 | * @see https://docs.coinex.com/api/v2/spot/market/ws/market-deals 21 | */ 22 | subscribe( 23 | params: SpotDealsSubscriptionParams, 24 | onUpdate: (update: SpotDealsUpdate) => void 25 | ): number { 26 | const id = this.#ws.send({ method: 'deals.subscribe', params }); 27 | this.#ws.on('message', (message: { method: string; data: SpotDealsUpdate }) => { 28 | if (message.method === 'deals.update') { 29 | onUpdate(message.data); 30 | } 31 | }); 32 | return id; 33 | } 34 | 35 | /** 36 | * Unsubscribes from market deals updates. 37 | * @param params - The unsubscription parameters. 38 | * @see https://docs.coinex.com/api/v2/spot/market/ws/market-deals 39 | */ 40 | unsubscribe(params: SpotDealsUnsubscribeParams): number { 41 | return this.#ws.send({ method: 'deals.unsubscribe', params }); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /packages/websocket/src/modules/spot/ticker/depth/module.ts: -------------------------------------------------------------------------------- 1 | import type { AuthenticatedWebSocket } from '@/lib/websocket'; 2 | 3 | import type { 4 | SpotDepthSubscriptionParams, 5 | SpotDepthUnsubscribeParams, 6 | SpotDepthUpdate, 7 | } from './types'; 8 | 9 | export class SpotDepth { 10 | #ws: AuthenticatedWebSocket; 11 | 12 | constructor(ws: AuthenticatedWebSocket) { 13 | this.#ws = ws; 14 | } 15 | 16 | /** 17 | * Subscribes to market depth updates. 18 | * @param params - The subscription parameters. 19 | * @param onUpdate - The callback function to handle updates. 20 | * @see https://docs.coinex.com/api/v2/spot/market/ws/market-depth 21 | */ 22 | subscribe( 23 | params: SpotDepthSubscriptionParams, 24 | onUpdate: (update: SpotDepthUpdate) => void 25 | ): number { 26 | const id = this.#ws.send({ method: 'depth.subscribe', params }); 27 | this.#ws.on('message', (message: { method: string; data: SpotDepthUpdate }) => { 28 | if (message.method === 'depth.update') { 29 | onUpdate(message.data); 30 | } 31 | }); 32 | return id; 33 | } 34 | 35 | /** 36 | * Unsubscribes from market depth updates. 37 | * @param params - The unsubscription parameters. 38 | * @see https://docs.coinex.com/api/v2/spot/market/ws/market-depth 39 | */ 40 | unsubscribe(params: SpotDepthUnsubscribeParams): number { 41 | return this.#ws.send({ method: 'depth.unsubscribe', params }); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /packages/websocket/src/modules/spot/ticker/index/module.ts: -------------------------------------------------------------------------------- 1 | import type { AuthenticatedWebSocket } from '@/lib/websocket'; 2 | 3 | import type { 4 | SpotIndexSubscriptionParams, 5 | SpotIndexUnsubscribeParams, 6 | SpotIndexUpdate, 7 | } from './types'; 8 | 9 | export class SpotIndex { 10 | #ws: AuthenticatedWebSocket; 11 | 12 | constructor(ws: AuthenticatedWebSocket) { 13 | this.#ws = ws; 14 | } 15 | 16 | /** 17 | * Subscribes to market index updates. 18 | * @param params - The subscription parameters. 19 | * @param onUpdate - The callback function to handle updates. 20 | * @see https://docs.coinex.com/api/v2/spot/market/ws/market-index 21 | */ 22 | subscribe( 23 | params: SpotIndexSubscriptionParams, 24 | onUpdate: (update: SpotIndexUpdate) => void 25 | ): number { 26 | const id = this.#ws.send({ method: 'index.subscribe', params }); 27 | this.#ws.on('message', (message: { method: string; data: SpotIndexUpdate }) => { 28 | if (message.method === 'index.update') { 29 | onUpdate(message.data); 30 | } 31 | }); 32 | return id; 33 | } 34 | 35 | /** 36 | * Unsubscribes from market index updates. 37 | * @param params - The unsubscription parameters. 38 | * @see https://docs.coinex.com/api/v2/spot/market/ws/market-index 39 | */ 40 | unsubscribe(params: SpotIndexUnsubscribeParams): number { 41 | return this.#ws.send({ method: 'index.unsubscribe', params }); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /packages/websocket/src/modules/futures/balance/module.ts: -------------------------------------------------------------------------------- 1 | import type { AuthenticatedWebSocket } from '@/lib/websocket'; 2 | 3 | import type { FuturesBalanceSubscriptionParams, FuturesBalanceUpdate } from './types'; 4 | 5 | export class FuturesBalance { 6 | #ws: AuthenticatedWebSocket; 7 | 8 | constructor(ws: AuthenticatedWebSocket) { 9 | this.#ws = ws; 10 | } 11 | 12 | /** 13 | * Subscribes to futures asset balance updates. 14 | * @param params - The subscription parameters. 15 | * @param onUpdate - The callback function to handle updates. 16 | * @see https://docs.coinex.com/api/v2/assets/balance/ws/futures_balance 17 | */ 18 | subscribe( 19 | params: FuturesBalanceSubscriptionParams, 20 | onUpdate: (update: FuturesBalanceUpdate) => void 21 | ): number { 22 | const id = this.#ws.send({ method: 'balance.subscribe', params }); 23 | this.#ws.on('message', (message: { method: string; data: FuturesBalanceUpdate }) => { 24 | if (message.method === 'balance.update') { 25 | onUpdate(message.data); 26 | } 27 | }); 28 | return id; 29 | } 30 | 31 | /** 32 | * Unsubscribes from futures asset balance updates. 33 | * @param params - The unsubscription parameters. 34 | * @see https://docs.coinex.com/api/v2/assets/balance/ws/futures_balance 35 | */ 36 | unsubscribe(params: FuturesBalanceSubscriptionParams): number { 37 | return this.#ws.send({ method: 'balance.unsubscribe', params }); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /packages/websocket/src/modules/spot/ticker/state/module.ts: -------------------------------------------------------------------------------- 1 | import type { AuthenticatedWebSocket } from '@/lib/websocket'; 2 | 3 | import type { SpotStateSubscriptionParams, SpotStateUpdate } from './types'; 4 | 5 | export class SpotState { 6 | #ws: AuthenticatedWebSocket; 7 | 8 | constructor(ws: AuthenticatedWebSocket) { 9 | this.#ws = ws; 10 | } 11 | 12 | /** 13 | * Subscribes to market status updates. 14 | * @param params - The subscription parameters. 15 | * @param onUpdate - The callback function to handle updates. 16 | * @see https://docs.coinex.com/api/v2/spot/market/ws/market 17 | */ 18 | subscribe( 19 | params: SpotStateSubscriptionParams, 20 | onUpdate: (update: SpotStateUpdate) => void 21 | ): number { 22 | const id = this.#ws.send({ method: 'state.subscribe', params }); 23 | this.#ws.on( 24 | 'message', 25 | (message: { method: string; data: { state_list: SpotStateUpdate[] } }) => { 26 | if (message.method === 'state.update') { 27 | message.data.state_list.forEach(onUpdate); 28 | } 29 | } 30 | ); 31 | return id; 32 | } 33 | 34 | /** 35 | * Unsubscribes from market status updates. 36 | * @param params - The unsubscription parameters. 37 | * @see https://docs.coinex.com/api/v2/spot/market/ws/market 38 | */ 39 | unsubscribe(params: SpotStateSubscriptionParams): number { 40 | return this.#ws.send({ method: 'state.unsubscribe', params }); 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /packages/websocket/src/modules/futures/ticker/deals/module.ts: -------------------------------------------------------------------------------- 1 | import type { AuthenticatedWebSocket } from '@/lib/websocket'; 2 | 3 | import type { 4 | FuturesDealsSubscriptionParams, 5 | FuturesDealsUnsubscribeParams, 6 | FuturesDealsUpdate, 7 | } from './types'; 8 | 9 | export class FuturesDeals { 10 | #ws: AuthenticatedWebSocket; 11 | 12 | constructor(ws: AuthenticatedWebSocket) { 13 | this.#ws = ws; 14 | } 15 | 16 | /** 17 | * Subscribes to market deals updates. 18 | * @param params - The subscription parameters. 19 | * @param onUpdate - The callback function to handle updates. 20 | * @see https://docs.coinex.com/api/v2/futures/market/ws/market-deals 21 | */ 22 | subscribe( 23 | params: FuturesDealsSubscriptionParams, 24 | onUpdate: (update: FuturesDealsUpdate) => void 25 | ): number { 26 | const id = this.#ws.send({ method: 'deals.subscribe', params }); 27 | this.#ws.on('message', (message: { method: string; data: FuturesDealsUpdate }) => { 28 | if (message.method === 'deals.update') { 29 | onUpdate(message.data); 30 | } 31 | }); 32 | return id; 33 | } 34 | 35 | /** 36 | * Unsubscribes from market deals updates. 37 | * @param params - The unsubscription parameters. 38 | * @see https://docs.coinex.com/api/v2/futures/market/ws/market-deals 39 | */ 40 | unsubscribe(params: FuturesDealsUnsubscribeParams): number { 41 | return this.#ws.send({ method: 'deals.unsubscribe', params }); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /packages/websocket/src/modules/futures/ticker/depth/module.ts: -------------------------------------------------------------------------------- 1 | import type { AuthenticatedWebSocket } from '@/lib/websocket'; 2 | 3 | import type { 4 | FuturesDepthSubscriptionParams, 5 | FuturesDepthUnsubscribeParams, 6 | FuturesDepthUpdate, 7 | } from './types'; 8 | 9 | export class FuturesDepth { 10 | #ws: AuthenticatedWebSocket; 11 | 12 | constructor(ws: AuthenticatedWebSocket) { 13 | this.#ws = ws; 14 | } 15 | 16 | /** 17 | * Subscribes to market depth updates. 18 | * @param params - The subscription parameters. 19 | * @param onUpdate - The callback function to handle updates. 20 | * @see https://docs.coinex.com/api/v2/futures/market/ws/market-depth 21 | */ 22 | subscribe( 23 | params: FuturesDepthSubscriptionParams, 24 | onUpdate: (update: FuturesDepthUpdate) => void 25 | ): number { 26 | const id = this.#ws.send({ method: 'depth.subscribe', params }); 27 | this.#ws.on('message', (message: { method: string; data: FuturesDepthUpdate }) => { 28 | if (message.method === 'depth.update') { 29 | onUpdate(message.data); 30 | } 31 | }); 32 | return id; 33 | } 34 | 35 | /** 36 | * Unsubscribes from market depth updates. 37 | * @param params - The unsubscription parameters. 38 | * @see https://docs.coinex.com/api/v2/futures/market/ws/market-depth 39 | */ 40 | unsubscribe(params: FuturesDepthUnsubscribeParams): number { 41 | return this.#ws.send({ method: 'depth.unsubscribe', params }); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /packages/websocket/src/modules/futures/ticker/index/module.ts: -------------------------------------------------------------------------------- 1 | import type { AuthenticatedWebSocket } from '@/lib/websocket'; 2 | 3 | import type { 4 | FuturesIndexSubscriptionParams, 5 | FuturesIndexUnsubscribeParams, 6 | FuturesIndexUpdate, 7 | } from './types'; 8 | 9 | export class FuturesIndex { 10 | #ws: AuthenticatedWebSocket; 11 | 12 | constructor(ws: AuthenticatedWebSocket) { 13 | this.#ws = ws; 14 | } 15 | 16 | /** 17 | * Subscribes to market index updates. 18 | * @param params - The subscription parameters. 19 | * @param onUpdate - The callback function to handle updates. 20 | * @see https://docs.coinex.com/api/v2/futures/market/ws/market-index 21 | */ 22 | subscribe( 23 | params: FuturesIndexSubscriptionParams, 24 | onUpdate: (update: FuturesIndexUpdate) => void 25 | ): number { 26 | const id = this.#ws.send({ method: 'index.subscribe', params }); 27 | this.#ws.on('message', (message: { method: string; data: FuturesIndexUpdate }) => { 28 | if (message.method === 'index.update') { 29 | onUpdate(message.data); 30 | } 31 | }); 32 | return id; 33 | } 34 | 35 | /** 36 | * Unsubscribes from market index updates. 37 | * @param params - The unsubscription parameters. 38 | * @see https://docs.coinex.com/api/v2/futures/market/ws/market-index 39 | */ 40 | unsubscribe(params: FuturesIndexUnsubscribeParams): number { 41 | return this.#ws.send({ method: 'index.unsubscribe', params }); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /packages/websocket/src/modules/spot/orders/stop/module.ts: -------------------------------------------------------------------------------- 1 | import type { AuthenticatedWebSocket } from '@/lib/websocket'; 2 | 3 | import type { 4 | SpotStopOrderSubscriptionParams, 5 | SpotStopOrderUnsubscribeParams, 6 | SpotStopOrderUpdate, 7 | } from './types'; 8 | 9 | export class SpotStopOrders { 10 | #ws: AuthenticatedWebSocket; 11 | 12 | constructor(ws: AuthenticatedWebSocket) { 13 | this.#ws = ws; 14 | } 15 | 16 | /** 17 | * Subscribes to user stop order updates. 18 | * @param params - The subscription parameters. 19 | * @param onUpdate - The callback function to handle updates. 20 | * @see https://docs.coinex.com/api/v2/spot/order/ws/user-stop-order 21 | */ 22 | subscribe( 23 | params: SpotStopOrderSubscriptionParams, 24 | onUpdate: (update: SpotStopOrderUpdate) => void 25 | ): number { 26 | const id = this.#ws.send({ method: 'stop.subscribe', params }); 27 | this.#ws.on('message', (message: { method: string; data: SpotStopOrderUpdate }) => { 28 | if (message.method === 'stop.update') { 29 | onUpdate(message.data); 30 | } 31 | }); 32 | return id; 33 | } 34 | 35 | /** 36 | * Unsubscribes from user stop order updates. 37 | * @param params - The unsubscription parameters. 38 | * @see https://docs.coinex.com/api/v2/spot/order/ws/user-stop-order 39 | */ 40 | unsubscribe(params: SpotStopOrderUnsubscribeParams): number { 41 | return this.#ws.send({ method: 'stop.unsubscribe', params }); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /packages/websocket/src/modules/spot/executions/module.ts: -------------------------------------------------------------------------------- 1 | import type { AuthenticatedWebSocket } from '@/lib/websocket'; 2 | 3 | import type { 4 | SpotUserDealsSubscriptionParams, 5 | SpotUserDealsUnsubscribeParams, 6 | SpotUserDealsUpdate, 7 | } from './types'; 8 | 9 | export class SpotExecutions { 10 | #ws: AuthenticatedWebSocket; 11 | 12 | constructor(ws: AuthenticatedWebSocket) { 13 | this.#ws = ws; 14 | } 15 | 16 | /** 17 | * Subscribes to user transaction updates. 18 | * @param params - The subscription parameters. 19 | * @param onUpdate - The callback function to handle updates. 20 | * @see https://docs.coinex.com/api/v2/spot/deal/ws/user-deals 21 | */ 22 | subscribe( 23 | params: SpotUserDealsSubscriptionParams, 24 | onUpdate: (update: SpotUserDealsUpdate) => void 25 | ): number { 26 | const id = this.#ws.send({ method: 'user_deals.subscribe', params }); 27 | this.#ws.on('message', (message: { method: string; data: SpotUserDealsUpdate }) => { 28 | if (message.method === 'user_deals.update') { 29 | onUpdate(message.data); 30 | } 31 | }); 32 | return id; 33 | } 34 | 35 | /** 36 | * Unsubscribes from user transaction updates. 37 | * @param params - The unsubscription parameters. 38 | * @see https://docs.coinex.com/api/v2/spot/deal/ws/user-deals 39 | */ 40 | unsubscribe(params: SpotUserDealsUnsubscribeParams): number { 41 | return this.#ws.send({ method: 'user_deals.unsubscribe', params }); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /packages/websocket/src/modules/spot/ticker/bbo/types.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * @interface SpotBboSubscriptionParams 3 | * @description Parameters for subscribing to BBO updates. 4 | */ 5 | export interface SpotBboSubscriptionParams { 6 | /** 7 | * @property {string[]} market_list - List of market names. 8 | */ 9 | market_list: string[]; 10 | } 11 | 12 | /** 13 | * @interface SpotBboUnsubscribeParams 14 | * @description Parameters for unsubscribing from BBO updates. 15 | */ 16 | export interface SpotBboUnsubscribeParams { 17 | /** 18 | * @property {string[]} market_list - List of market names to unsubscribe from. An empty array unsubscribes from all. 19 | */ 20 | market_list: string[]; 21 | } 22 | 23 | /** 24 | * @interface SpotBboUpdate 25 | * @description Represents a BBO update push from the server. 26 | */ 27 | export interface SpotBboUpdate { 28 | /** 29 | * @property {string} market - Market name. 30 | */ 31 | market: string; 32 | /** 33 | * @property {number} updated_at - Timestamp (millisecond). 34 | */ 35 | updated_at: number; 36 | /** 37 | * @property {string} best_bid_price - Best bid price. 38 | */ 39 | best_bid_price: string; 40 | /** 41 | * @property {string} best_bid_size - Best bid size. 42 | */ 43 | best_bid_size: string; 44 | /** 45 | * @property {string} best_ask_price - Best ask price. 46 | */ 47 | best_ask_price: string; 48 | /** 49 | * @property {string} best_ask_size - Best ask size. 50 | */ 51 | best_ask_size: string; 52 | } 53 | -------------------------------------------------------------------------------- /packages/websocket/src/modules/futures/ticker/state/module.ts: -------------------------------------------------------------------------------- 1 | import type { AuthenticatedWebSocket } from '@/lib/websocket'; 2 | 3 | import type { FuturesStateSubscriptionParams, FuturesStateUpdate } from './types'; 4 | 5 | export class FuturesState { 6 | #ws: AuthenticatedWebSocket; 7 | 8 | constructor(ws: AuthenticatedWebSocket) { 9 | this.#ws = ws; 10 | } 11 | 12 | /** 13 | * Subscribes to market status updates. 14 | * @param params - The subscription parameters. 15 | * @param onUpdate - The callback function to handle updates. 16 | * @see https://docs.coinex.com/api/v2/futures/market/ws/market-state 17 | */ 18 | subscribe( 19 | params: FuturesStateSubscriptionParams, 20 | onUpdate: (update: FuturesStateUpdate) => void 21 | ): number { 22 | const id = this.#ws.send({ method: 'state.subscribe', params }); 23 | this.#ws.on( 24 | 'message', 25 | (message: { method: string; data: { state_list: FuturesStateUpdate[] } }) => { 26 | if (message.method === 'state.update') { 27 | message.data.state_list.forEach(onUpdate); 28 | } 29 | } 30 | ); 31 | return id; 32 | } 33 | 34 | /** 35 | * Unsubscribes from market status updates. 36 | * @param params - The unsubscription parameters. 37 | * @see https://docs.coinex.com/api/v2/futures/market/ws/market-state 38 | */ 39 | unsubscribe(params: FuturesStateSubscriptionParams): number { 40 | return this.#ws.send({ method: 'state.unsubscribe', params }); 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /packages/websocket/src/modules/futures/position/module.ts: -------------------------------------------------------------------------------- 1 | import type { AuthenticatedWebSocket } from '@/lib/websocket'; 2 | 3 | import type { 4 | FuturesPositionSubscriptionParams, 5 | FuturesPositionUnsubscribeParams, 6 | FuturesPositionUpdate, 7 | } from './types'; 8 | 9 | export class Position { 10 | #ws: AuthenticatedWebSocket; 11 | 12 | constructor(ws: AuthenticatedWebSocket) { 13 | this.#ws = ws; 14 | } 15 | 16 | /** 17 | * Subscribes to user position updates. 18 | * @param params - The subscription parameters. 19 | * @param onUpdate - The callback function to handle updates. 20 | * @see https://docs.coinex.com/api/v2/futures/position/ws/user-position 21 | */ 22 | subscribe( 23 | params: FuturesPositionSubscriptionParams, 24 | onUpdate: (update: FuturesPositionUpdate) => void 25 | ): number { 26 | const id = this.#ws.send({ method: 'position.subscribe', params }); 27 | this.#ws.on('message', (message: { method: string; data: FuturesPositionUpdate }) => { 28 | if (message.method === 'position.update') { 29 | onUpdate(message.data); 30 | } 31 | }); 32 | return id; 33 | } 34 | 35 | /** 36 | * Unsubscribes from user position updates. 37 | * @param params - The unsubscription parameters. 38 | * @see https://docs.coinex.com/api/v2/futures/position/ws/user-position 39 | */ 40 | unsubscribe(params: FuturesPositionUnsubscribeParams): number { 41 | return this.#ws.send({ method: 'position.unsubscribe', params }); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /packages/websocket/src/modules/futures/executions/module.ts: -------------------------------------------------------------------------------- 1 | import type { AuthenticatedWebSocket } from '@/lib/websocket'; 2 | 3 | import type { 4 | FuturesUserDealsSubscriptionParams, 5 | FuturesUserDealsUnsubscribeParams, 6 | FuturesUserDealsUpdate, 7 | } from './types'; 8 | 9 | export class Executions { 10 | #ws: AuthenticatedWebSocket; 11 | 12 | constructor(ws: AuthenticatedWebSocket) { 13 | this.#ws = ws; 14 | } 15 | 16 | /** 17 | * Subscribes to user transaction updates. 18 | * @param params - The subscription parameters. 19 | * @param onUpdate - The callback function to handle updates. 20 | * @see https://docs.coinex.com/api/v2/futures/deal/ws/user-deals 21 | */ 22 | subscribe( 23 | params: FuturesUserDealsSubscriptionParams, 24 | onUpdate: (update: FuturesUserDealsUpdate) => void 25 | ): number { 26 | const id = this.#ws.send({ method: 'user_deals.subscribe', params }); 27 | this.#ws.on('message', (message: { method: string; data: FuturesUserDealsUpdate }) => { 28 | if (message.method === 'user_deals.update') { 29 | onUpdate(message.data); 30 | } 31 | }); 32 | return id; 33 | } 34 | 35 | /** 36 | * Unsubscribes from user transaction updates. 37 | * @param params - The unsubscription parameters. 38 | * @see https://docs.coinex.com/api/v2/futures/deal/ws/user-deals 39 | */ 40 | unsubscribe(params: FuturesUserDealsUnsubscribeParams): number { 41 | return this.#ws.send({ method: 'user_deals.unsubscribe', params }); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /packages/websocket/src/modules/futures/orders/stop/module.ts: -------------------------------------------------------------------------------- 1 | import type { AuthenticatedWebSocket } from '@/lib/websocket'; 2 | 3 | import type { 4 | FuturesStopOrderSubscriptionParams, 5 | FuturesStopOrderUnsubscribeParams, 6 | FuturesStopOrderUpdate, 7 | } from './types'; 8 | 9 | export class FuturesStopOrders { 10 | #ws: AuthenticatedWebSocket; 11 | 12 | constructor(ws: AuthenticatedWebSocket) { 13 | this.#ws = ws; 14 | } 15 | 16 | /** 17 | * Subscribes to user stop order updates. 18 | * @param params - The subscription parameters. 19 | * @param onUpdate - The callback function to handle updates. 20 | * @see https://docs.coinex.com/api/v2/futures/order/ws/user-stop-order 21 | */ 22 | subscribe( 23 | params: FuturesStopOrderSubscriptionParams, 24 | onUpdate: (update: FuturesStopOrderUpdate) => void 25 | ): number { 26 | const id = this.#ws.send({ method: 'stop.subscribe', params }); 27 | this.#ws.on('message', (message: { method: string; data: FuturesStopOrderUpdate }) => { 28 | if (message.method === 'stop.update') { 29 | onUpdate(message.data); 30 | } 31 | }); 32 | return id; 33 | } 34 | 35 | /** 36 | * Unsubscribes from user stop order updates. 37 | * @param params - The unsubscription parameters. 38 | * @see https://docs.coinex.com/api/v2/futures/order/ws/user-stop-order 39 | */ 40 | unsubscribe(params: FuturesStopOrderUnsubscribeParams): number { 41 | return this.#ws.send({ method: 'stop.unsubscribe', params }); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /packages/websocket/src/modules/futures/ticker/bbo/types.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * @interface FuturesBboSubscriptionParams 3 | * @description Parameters for subscribing to BBO updates. 4 | */ 5 | export interface FuturesBboSubscriptionParams { 6 | /** 7 | * @property {string[]} market_list - List of market names. 8 | */ 9 | market_list: string[]; 10 | } 11 | 12 | /** 13 | * @interface FuturesBboUnsubscribeParams 14 | * @description Parameters for unsubscribing from BBO updates. 15 | */ 16 | export interface FuturesBboUnsubscribeParams { 17 | /** 18 | * @property {string[]} market_list - List of market names to unsubscribe from. An empty array unsubscribes from all. 19 | */ 20 | market_list: string[]; 21 | } 22 | 23 | /** 24 | * @interface FuturesBboUpdate 25 | * @description Represents a BBO update push from the server. 26 | */ 27 | export interface FuturesBboUpdate { 28 | /** 29 | * @property {string} market - Market name. 30 | */ 31 | market: string; 32 | /** 33 | * @property {number} updated_at - Timestamp (millisecond). 34 | */ 35 | updated_at: number; 36 | /** 37 | * @property {string} best_bid_price - Best bid price. 38 | */ 39 | best_bid_price: string; 40 | /** 41 | * @property {string} best_bid_size - Best bid size. 42 | */ 43 | best_bid_size: string; 44 | /** 45 | * @property {string} best_ask_price - Best ask price. 46 | */ 47 | best_ask_price: string; 48 | /** 49 | * @property {string} best_ask_size - Best ask size. 50 | */ 51 | best_ask_size: string; 52 | } 53 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # CoinEx API Clients for Javascript/Typescript 2 | 3 | This repository contains HTTP and WebSocket clients for interacting with the CoinEx API v2. 4 | 5 | ## Packages 6 | 7 | This repository includes the following packages: 8 | 9 | - [`@coinex-org/coinex`](./packages/coinex): The HTTP client for CoinEx API v2. 10 | - [`@coinex-org/websocket`](./packages/websocket): The WebSocket client for CoinEx API v2. 11 | 12 | ## Official Documentation 13 | 14 | For detailed information on the CoinEx API v2, please refer to the [official documentation](https://docs.coinex.com/api/v2/). 15 | 16 | ## Obtaining API Keys 17 | 18 | To use these clients, you will need an API Key (`access_id`) and Secret Key from CoinEx. Follow these steps to obtain them: 19 | 20 | 1. Log in to your CoinEx account. 21 | 2. Navigate to the API management page. 22 | 3. Create a new API key or use an existing one. 23 | 4. Obtain your `access_id` and `secret_key` from the created API record. 24 | 25 | ## License 26 | 27 | [MIT](/LICENSE) © [Shahrad Elahi](https://github.com/shahradelahi) and [contributors](https://github.com/shahradelahi/coinex/graphs/contributors). 28 | 29 | ## Notice of Non-Affiliation and Disclaimer 30 | 31 | We are not affiliated, associated, authorized, endorsed by, or in any way officially connected with CoinEx, or any of its subsidiaries or its affiliates. The official CoinEx website can be found at https://coinex.com/. 32 | 33 | The name CoinEx as well as related names, marks, emblems and images are registered trademarks of their respective owners. 34 | -------------------------------------------------------------------------------- /packages/websocket/src/modules/spot/orders/module.ts: -------------------------------------------------------------------------------- 1 | import type { AuthenticatedWebSocket } from '@/lib/websocket'; 2 | 3 | import { SpotStopOrders } from './stop'; 4 | import type { 5 | SpotOrderSubscriptionParams, 6 | SpotOrderUnsubscribeParams, 7 | SpotOrderUpdate, 8 | } from './types'; 9 | 10 | export class SpotOrders { 11 | #ws: AuthenticatedWebSocket; 12 | public readonly stop: SpotStopOrders; 13 | 14 | constructor(ws: AuthenticatedWebSocket) { 15 | this.#ws = ws; 16 | this.stop = new SpotStopOrders(ws); 17 | } 18 | 19 | /** 20 | * Subscribes to user order updates. 21 | * @param params - The subscription parameters. 22 | * @param onUpdate - The callback function to handle updates. 23 | * @see https://docs.coinex.com/api/v2/spot/order/ws/user-order 24 | */ 25 | subscribe( 26 | params: SpotOrderSubscriptionParams, 27 | onUpdate: (update: SpotOrderUpdate) => void 28 | ): number { 29 | const id = this.#ws.send({ method: 'order.subscribe', params }); 30 | this.#ws.on('message', (message: { method: string; data: SpotOrderUpdate }) => { 31 | if (message.method === 'order.update') { 32 | onUpdate(message.data); 33 | } 34 | }); 35 | return id; 36 | } 37 | 38 | /** 39 | * Unsubscribes from user order updates. 40 | * @param params - The unsubscription parameters. 41 | * @see https://docs.coinex.com/api/v2/spot/order/ws/user-order 42 | */ 43 | unsubscribe(params: SpotOrderUnsubscribeParams): number { 44 | return this.#ws.send({ method: 'order.unsubscribe', params }); 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /packages/websocket/src/modules/futures/orders/module.ts: -------------------------------------------------------------------------------- 1 | import type { AuthenticatedWebSocket } from '@/lib/websocket'; 2 | 3 | import { FuturesStopOrders } from './stop'; 4 | import type { 5 | FuturesOrderSubscriptionParams, 6 | FuturesOrderUnsubscribeParams, 7 | FuturesOrderUpdate, 8 | } from './types'; 9 | 10 | export class Orders { 11 | #ws: AuthenticatedWebSocket; 12 | public readonly stop: FuturesStopOrders; 13 | 14 | constructor(ws: AuthenticatedWebSocket) { 15 | this.#ws = ws; 16 | this.stop = new FuturesStopOrders(ws); 17 | } 18 | 19 | /** 20 | * Subscribes to user order updates. 21 | * @param params - The subscription parameters. 22 | * @param onUpdate - The callback function to handle updates. 23 | * @see https://docs.coinex.com/api/v2/futures/order/ws/user-order 24 | */ 25 | subscribe( 26 | params: FuturesOrderSubscriptionParams, 27 | onUpdate: (update: FuturesOrderUpdate) => void 28 | ): number { 29 | const id = this.#ws.send({ method: 'order.subscribe', params }); 30 | this.#ws.on('message', (message: { method: string; data: FuturesOrderUpdate }) => { 31 | if (message.method === 'order.update') { 32 | onUpdate(message.data); 33 | } 34 | }); 35 | return id; 36 | } 37 | 38 | /** 39 | * Unsubscribes from user order updates. 40 | * @param params - The unsubscription parameters. 41 | * @see https://docs.coinex.com/api/v2/futures/order/ws/user-order 42 | */ 43 | unsubscribe(params: FuturesOrderUnsubscribeParams): number { 44 | return this.#ws.send({ method: 'order.unsubscribe', params }); 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /packages/websocket/src/modules/futures/balance/types.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * @interface FuturesBalanceSubscriptionParams 3 | * @description Parameters for subscribing to asset balance updates. 4 | */ 5 | export interface FuturesBalanceSubscriptionParams { 6 | /** 7 | * @property {string[]} ccy_list - List of asset names. 8 | * @description An empty array subscribes to all asset balances. 9 | */ 10 | ccy_list: string[]; 11 | } 12 | 13 | /** 14 | * @interface FuturesBalance 15 | * @description Represents the balance of a single asset in a futures account. 16 | */ 17 | export interface FuturesBalance { 18 | /** 19 | * @property {string} ccy - Asset name. 20 | */ 21 | ccy: string; 22 | /** 23 | * @property {string} available - Balance available. 24 | */ 25 | available: string; 26 | /** 27 | * @property {string} frozen - Frozen balance. 28 | */ 29 | frozen: string; 30 | /** 31 | * @property {string} margin - Position margin. 32 | */ 33 | margin: string; 34 | /** 35 | * @property {string} transferrable - Balance available for transfers. 36 | */ 37 | transferrable: string; 38 | /** 39 | * @property {string} unrealized_pnl - Unrealized profit. 40 | */ 41 | unrealized_pnl: string; 42 | /** 43 | * @property {string} equity - Equity. 44 | */ 45 | equity: string; 46 | } 47 | 48 | /** 49 | * @interface FuturesBalanceUpdate 50 | * @description Represents a futures balance update push from the server. 51 | */ 52 | export interface FuturesBalanceUpdate { 53 | /** 54 | * @property {FuturesBalance[]} balance_list - List of updated balances. 55 | */ 56 | balance_list: FuturesBalance[]; 57 | } 58 | -------------------------------------------------------------------------------- /packages/websocket/src/modules/spot/ticker/state/types.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * @interface SpotStateSubscriptionParams 3 | * @description Parameters for subscribing to market status updates. 4 | */ 5 | export interface SpotStateSubscriptionParams { 6 | /** 7 | * @property {string[]} market_list - List of market names. 8 | * @description An empty array subscribes to all markets. 9 | */ 10 | market_list: string[]; 11 | } 12 | 13 | /** 14 | * @interface SpotStateUpdate 15 | * @description Represents a market status update push from the server. 16 | */ 17 | export interface SpotStateUpdate { 18 | /** 19 | * @property {string} market - Market name. 20 | */ 21 | market: string; 22 | /** 23 | * @property {string} last - Latest price. 24 | */ 25 | last: string; 26 | /** 27 | * @property {string} open - Opening price. 28 | */ 29 | open: string; 30 | /** 31 | * @property {string} close - Closing price. 32 | */ 33 | close: string; 34 | /** 35 | * @property {string} high - Highest price. 36 | */ 37 | high: string; 38 | /** 39 | * @property {string} low - Lowest price. 40 | */ 41 | low: string; 42 | /** 43 | * @property {string} volume - Filled volume. 44 | */ 45 | volume: string; 46 | /** 47 | * @property {string} value - Filled value. 48 | */ 49 | value: string; 50 | /** 51 | * @property {string} volume_sell - Best ask size. 52 | */ 53 | volume_sell: string; 54 | /** 55 | * @property {string} volume_buy - Best bid size. 56 | */ 57 | volume_buy: string; 58 | /** 59 | * @property {number} period - Period, fixed at 86400, indicates that the data is a one-day value. 60 | */ 61 | period: number; 62 | } 63 | -------------------------------------------------------------------------------- /.github/replace-workspace-protocol.ts: -------------------------------------------------------------------------------- 1 | import * as fs from 'node:fs'; 2 | import * as path from 'node:path'; 3 | 4 | const pkgJsonPaths = fs 5 | .readdirSync(path.resolve(__dirname, '..')) 6 | .filter((dir) => { 7 | if (!fs.existsSync(`../${dir}/package.json`)) return false; 8 | const pkg = JSON.parse(fs.readFileSync(`../${dir}/package.json`, 'utf-8')); 9 | return pkg.private !== true; 10 | }) 11 | .map((dir) => `../${dir}/package.json`); 12 | 13 | /** 14 | * Hack to replace the workspace protocol with the actual version 15 | */ 16 | const packageVersions = {}; 17 | Promise.all( 18 | pkgJsonPaths.map(async (path) => { 19 | const pkg = JSON.parse(fs.readFileSync(path, 'utf-8')); 20 | packageVersions[pkg.name] = pkg.version; 21 | }) 22 | ).then(() => { 23 | const workspacePkg = JSON.parse(fs.readFileSync('package.json', 'utf-8')); 24 | for (const dep in workspacePkg.dependencies) { 25 | if (workspacePkg.dependencies[dep].startsWith('workspace:')) { 26 | if (dep in packageVersions) { 27 | workspacePkg.dependencies[dep] = packageVersions[dep]; 28 | } else { 29 | delete workspacePkg.dependencies[dep]; 30 | } 31 | } 32 | } 33 | for (const dep in workspacePkg.peerDependencies) { 34 | if (workspacePkg.peerDependencies[dep].startsWith('workspace:')) { 35 | if (dep in packageVersions) { 36 | workspacePkg.peerDependencies[dep] = packageVersions[dep]; 37 | } else { 38 | delete workspacePkg.peerDependencies[dep]; 39 | } 40 | } 41 | } 42 | 43 | // Remove unnecessary fields 44 | delete workspacePkg['devDependencies']; 45 | delete workspacePkg['scripts']; 46 | 47 | fs.writeFileSync('package.json', JSON.stringify(workspacePkg, null, 2)); 48 | }); 49 | -------------------------------------------------------------------------------- /packages/coinex/src/modules/account/settings/types.ts: -------------------------------------------------------------------------------- 1 | import { type PositionSide } from '@coinex-org/internal-shared'; 2 | 3 | /** 4 | * @interface GetFuturesMarketSettingsResponse 5 | * @description Response for getting futures market settings. 6 | * @see https://docs.coinex.com/api/v2/account/settings/http/accquire-futures-market-settings 7 | */ 8 | export interface GetFuturesMarketSettingsResponse { 9 | /** 10 | * @property {string[]} markets - List of markets. 11 | * @example ["BTCUSDT", "ETHUSDT"] 12 | */ 13 | markets: string[]; 14 | /** 15 | * @property {PositionSide} position_side - Position side. 16 | * @example PositionSide.LONG 17 | */ 18 | position_side: PositionSide; 19 | } 20 | 21 | /** 22 | * @interface ModifyAccountSettingsParams 23 | * @description Parameters for modifying account settings. 24 | * @see https://docs.coinex.com/api/v2/account/settings/http/modify-account-settings 25 | */ 26 | export interface ModifyAccountSettingsParams { 27 | /** 28 | * @property {boolean} cet_enabled - Whether to use CET as transaction fee. 29 | * @example true 30 | */ 31 | cet_enabled: boolean; 32 | } 33 | 34 | /** 35 | * @interface ModifyFuturesMarketSettingsParams 36 | * @description Outlines the parameters for modifying futures market settings, including the markets and position side. 37 | * @see https://docs.coinex.com/api/v2/account/settings/http/modify-futures-market-settings 38 | */ 39 | export interface ModifyFuturesMarketSettingsParams { 40 | /** 41 | * @property {string[]} markets - List of markets. 42 | * @example ["BTCUSDT", "ETHUSDT"] 43 | */ 44 | markets: string[]; 45 | /** 46 | * @property {PositionSide} position_side - Position side. 47 | * @example PositionSide.LONG 48 | */ 49 | position_side: PositionSide; 50 | } 51 | -------------------------------------------------------------------------------- /packages/coinex/src/modules/maintain/types.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * @interface MaintenanceInfo 3 | * @description Represents the maintenance information for the CoinEx platform. 4 | * @see https://docs.coinex.com/api/v2/common/maintain/http/get-maintenance-info 5 | */ 6 | export interface MaintenanceInfo { 7 | /** 8 | * @property {number} started_at - The start time of the maintenance in milliseconds. 9 | * @example 1622548800000 10 | */ 11 | started_at: number; 12 | /** 13 | * @property {number} ended_at - The end time of the maintenance in milliseconds. 14 | * @example 1622635200000 15 | */ 16 | ended_at: number; 17 | /** 18 | * @property {('FUTURES' | 'SPOT' | 'ALL_SITE')[]} scope - The scope of the maintenance. 19 | * @example ["ALL_SITE"] 20 | */ 21 | scope: ('FUTURES' | 'SPOT' | 'ALL_SITE')[]; 22 | /** 23 | * @property {string} announce_url - The URL for the maintenance announcement. 24 | * @example "https://www.coinex.com/announcement/123" 25 | */ 26 | announce_url: string; 27 | /** 28 | * @property {boolean} announce_enabled - Whether the announcement is enabled. 29 | * @example true 30 | */ 31 | announce_enabled: boolean; 32 | /** 33 | * @property {number} protect_duration_start - The start time of the protection duration in milliseconds. 34 | * @example 1622548800000 35 | */ 36 | protect_duration_start: number; 37 | /** 38 | * @property {number} protect_duration_end - The end time of the protection duration in milliseconds. 39 | * @example 1622635200000 40 | */ 41 | protect_duration_end: number; 42 | } 43 | 44 | /** 45 | * @interface GetMaintenanceInfoResponse 46 | * @description The response for the getMaintenanceInfo method. 47 | * @see https://docs.coinex.com/api/v2/common/maintain/http/get-maintenance-info 48 | */ 49 | export type GetMaintenanceInfoResponse = MaintenanceInfo[]; 50 | -------------------------------------------------------------------------------- /packages/coinex/src/modules/assets/transfer/module.ts: -------------------------------------------------------------------------------- 1 | import deepmerge from 'deepmerge'; 2 | 3 | import { type CoinExClient } from '@/client'; 4 | import { noUndefined } from '@/lib/object'; 5 | import type { RequestOptions } from '@/types'; 6 | 7 | import type { 8 | GetAssetTransferHistoryParams, 9 | GetAssetTransferHistoryResponse, 10 | TransferParams, 11 | } from './types'; 12 | 13 | export class Transfer { 14 | #client: CoinExClient; 15 | 16 | constructor(client: CoinExClient) { 17 | this.#client = client; 18 | } 19 | 20 | /** 21 | * Get Asset Transfer Record 22 | * 23 | * @param params - The parameters for the request. 24 | * @param options - The options for the request. 25 | * @returns {Promise} The asset transfer history. 26 | * @see https://docs.coinex.com/api/v2/assets/transfer/http/list-transfer-history 27 | */ 28 | getAssetTransferHistory( 29 | params: GetAssetTransferHistoryParams, 30 | options: RequestOptions = {} 31 | ): Promise { 32 | return this.#client.request( 33 | 'assets/transfer-history', 34 | deepmerge( 35 | { 36 | method: 'GET', 37 | searchParams: noUndefined(params), 38 | }, 39 | options 40 | ) 41 | ); 42 | } 43 | 44 | /** 45 | * Transfer 46 | * 47 | * @param params - The parameters for the request. 48 | * @param options - The options for the request. 49 | * @returns {Promise<{}>} An empty object on success. 50 | * @see https://docs.coinex.com/api/v2/assets/transfer/http/transfer 51 | */ 52 | transfer(params: TransferParams, options: RequestOptions = {}): Promise<{}> { 53 | return this.#client.request( 54 | 'assets/transfer', 55 | deepmerge({ method: 'POST', json: noUndefined(params) }, options) 56 | ); 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /packages/websocket/src/modules/spot/ticker/deals/types.ts: -------------------------------------------------------------------------------- 1 | import { OrderSide } from '@coinex-org/internal-shared'; 2 | 3 | /** 4 | * @interface SpotDealsSubscriptionParams 5 | * @description Parameters for subscribing to market deals updates. 6 | */ 7 | export interface SpotDealsSubscriptionParams { 8 | /** 9 | * @property {string[]} market_list - List of market names. 10 | * @description An empty array subscribes to all markets. 11 | */ 12 | market_list: string[]; 13 | } 14 | 15 | /** 16 | * @interface SpotDealsUnsubscribeParams 17 | * @description Parameters for unsubscribing from market deals updates. 18 | */ 19 | export interface SpotDealsUnsubscribeParams { 20 | /** 21 | * @property {string[]} market_list - List of market names to unsubscribe from. An empty array unsubscribes from all. 22 | */ 23 | market_list: string[]; 24 | } 25 | 26 | /** 27 | * @interface SpotDeal 28 | * @description Represents a single market transaction. 29 | */ 30 | export interface SpotDeal { 31 | /** 32 | * @property {number} deal_id - Transaction ID. 33 | */ 34 | deal_id: number; 35 | /** 36 | * @property {number} created_at - Transaction timestamp (milliseconds). 37 | */ 38 | created_at: number; 39 | /** 40 | * @property {OrderSide} side - Taker side, "buy" or "sell". 41 | */ 42 | side: OrderSide; 43 | /** 44 | * @property {string} price - Filled price. 45 | */ 46 | price: string; 47 | /** 48 | * @property {string} amount - Executed amount. 49 | */ 50 | amount: string; 51 | } 52 | 53 | /** 54 | * @interface SpotDealsUpdate 55 | * @description Represents a market deals update push from the server. 56 | */ 57 | export interface SpotDealsUpdate { 58 | /** 59 | * @property {string} market - Market name. 60 | */ 61 | market: string; 62 | /** 63 | * @property {SpotDeal[]} deal_list - List of latest transactions. 64 | */ 65 | deal_list: SpotDeal[]; 66 | } 67 | -------------------------------------------------------------------------------- /packages/websocket/src/modules/futures/ticker/deals/types.ts: -------------------------------------------------------------------------------- 1 | import { OrderSide } from '@coinex-org/internal-shared'; 2 | 3 | /** 4 | * @interface FuturesDealsSubscriptionParams 5 | * @description Parameters for subscribing to market deals updates. 6 | */ 7 | export interface FuturesDealsSubscriptionParams { 8 | /** 9 | * @property {string[]} market_list - List of market names. 10 | * @description An empty array subscribes to all markets. 11 | */ 12 | market_list: string[]; 13 | } 14 | 15 | /** 16 | * @interface FuturesDealsUnsubscribeParams 17 | * @description Parameters for unsubscribing from market deals updates. 18 | */ 19 | export interface FuturesDealsUnsubscribeParams { 20 | /** 21 | * @property {string[]} market_list - List of market names to unsubscribe from. An empty array unsubscribes from all. 22 | */ 23 | market_list: string[]; 24 | } 25 | 26 | /** 27 | * @interface FuturesDeal 28 | * @description Represents a single market transaction. 29 | */ 30 | export interface FuturesDeal { 31 | /** 32 | * @property {number} deal_id - Transaction ID. 33 | */ 34 | deal_id: number; 35 | /** 36 | * @property {number} created_at - Transaction timestamp (milliseconds). 37 | */ 38 | created_at: number; 39 | /** 40 | * @property {OrderSide} side - Taker side, "buy" or "sell". 41 | */ 42 | side: OrderSide; 43 | /** 44 | * @property {string} price - Filled price. 45 | */ 46 | price: string; 47 | /** 48 | * @property {string} amount - Executed amount. 49 | */ 50 | amount: string; 51 | } 52 | 53 | /** 54 | * @interface FuturesDealsUpdate 55 | * @description Represents a market deals update push from the server. 56 | */ 57 | export interface FuturesDealsUpdate { 58 | /** 59 | * @property {string} market - Market name. 60 | */ 61 | market: string; 62 | /** 63 | * @property {FuturesDeal[]} deal_list - List of latest transactions. 64 | */ 65 | deal_list: FuturesDeal[]; 66 | } 67 | -------------------------------------------------------------------------------- /packages/coinex/src/modules/futures/deal/types.ts: -------------------------------------------------------------------------------- 1 | import { type OrderSide } from '@coinex-org/internal-shared'; 2 | 3 | import { type Pagination } from '@/modules'; 4 | 5 | /** 6 | * @interface UserDeal 7 | * @see https://docs.coinex.com/api/v2/futures/deal/http/list-user-deals 8 | */ 9 | export interface UserDeal { 10 | deal_id: number; 11 | created_at: number; 12 | market: string; 13 | order_id: number; 14 | side: OrderSide; 15 | type: 'taker' | 'maker'; 16 | fee: string; 17 | fee_ccy: string; 18 | price: string; 19 | amount: string; 20 | value: string; 21 | pnl: string; 22 | } 23 | 24 | /** 25 | * @interface ListUserDealsParams 26 | * @see https://docs.coinex.com/api/v2/futures/deal/http/list-user-deals 27 | */ 28 | export interface ListUserDealsParams { 29 | market?: string; 30 | side?: OrderSide; 31 | start_time?: number; 32 | end_time?: number; 33 | page?: number; 34 | limit?: number; 35 | } 36 | 37 | /** 38 | * @interface ListUserDealsResponse 39 | */ 40 | export interface ListUserDealsResponse { 41 | data: UserDeal[]; 42 | pagination: Pagination; 43 | } 44 | 45 | /** 46 | * @interface UserOrderDeal 47 | * @see https://docs.coinex.com/api/v2/futures/deal/http/list-user-order-deals 48 | */ 49 | export interface UserOrderDeal { 50 | deal_id: number; 51 | created_at: number; 52 | market: string; 53 | order_id: number; 54 | side: OrderSide; 55 | type: 'taker' | 'maker'; 56 | fee: string; 57 | fee_ccy: string; 58 | price: string; 59 | amount: string; 60 | value: string; 61 | pnl: string; 62 | } 63 | 64 | /** 65 | * @interface ListUserOrderDealsParams 66 | * @see https://docs.coinex.com/api/v2/futures/deal/http/list-user-order-deals 67 | */ 68 | export interface ListUserOrderDealsParams { 69 | market: string; 70 | order_id: number; 71 | page?: number; 72 | limit?: number; 73 | } 74 | 75 | /** 76 | * @interface ListUserOrderDealsResponse 77 | */ 78 | export interface ListUserOrderDealsResponse { 79 | data: UserOrderDeal[]; 80 | pagination: Pagination; 81 | } 82 | -------------------------------------------------------------------------------- /packages/coinex/src/modules/spot/deal/module.ts: -------------------------------------------------------------------------------- 1 | import deepmerge from 'deepmerge'; 2 | 3 | import { type CoinExClient } from '@/client'; 4 | import { noUndefined } from '@/lib/object'; 5 | import type { RequestOptions } from '@/types'; 6 | 7 | import type { 8 | SpotListUserDealsParams, 9 | SpotListUserDealsResponse, 10 | SpotListUserOrderDealsParams, 11 | SpotListUserOrderDealsResponse, 12 | } from './types'; 13 | 14 | export class Deal { 15 | #client: CoinExClient; 16 | 17 | constructor(client: CoinExClient) { 18 | this.#client = client; 19 | } 20 | 21 | /** 22 | * Get User Transaction 23 | * 24 | * @param params - The parameters for the request. 25 | * @param options - The options for the request. 26 | * @returns {Promise} The user deals. 27 | * @see https://docs.coinex.com/api/v2/spot/deal/http/list-user-deals 28 | */ 29 | listUserDeals( 30 | params: SpotListUserDealsParams, 31 | options: RequestOptions = {} 32 | ): Promise { 33 | return this.#client.request( 34 | 'spot/user-deals', 35 | deepmerge( 36 | { 37 | method: 'GET', 38 | searchParams: noUndefined(params), 39 | }, 40 | options 41 | ) 42 | ); 43 | } 44 | 45 | /** 46 | * Get User Order Transaction 47 | * 48 | * @param params - The parameters for the request. 49 | * @param options - The options for the request. 50 | * @returns {Promise} The user order deals. 51 | * @see https://docs.coinex.com/api/v2/spot/deal/http/list-user-order-deals 52 | */ 53 | listUserOrderDeals( 54 | params: SpotListUserOrderDealsParams, 55 | options: RequestOptions = {} 56 | ): Promise { 57 | return this.#client.request( 58 | 'spot/order-deals', 59 | deepmerge( 60 | { 61 | method: 'GET', 62 | searchParams: noUndefined(params), 63 | }, 64 | options 65 | ) 66 | ); 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /packages/websocket/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@coinex-org/websocket", 3 | "version": "0.0.0", 4 | "description": "A lightweight, type-safe TypeScript WebSocket client for the official CoinEx API v2, providing real-time market and user data.", 5 | "keywords": [ 6 | "coinex", 7 | "websocket", 8 | "crypto", 9 | "exchange" 10 | ], 11 | "homepage": "https://github.com/shahradelahi/coinex/packages/websocket#readme", 12 | "repository": { 13 | "url": "https://github.com/shahradelahi/coinex.git", 14 | "directory": "/packages/websocket" 15 | }, 16 | "license": "MIT", 17 | "author": "Shahrad Elahi (https://github.com/shahradelahi)", 18 | "type": "module", 19 | "exports": { 20 | ".": { 21 | "types": "./dist/index.d.ts", 22 | "import": "./dist/index.js", 23 | "default": "./dist/index.cjs" 24 | } 25 | }, 26 | "files": [ 27 | "dist/**", 28 | "!**/*.d.cts" 29 | ], 30 | "scripts": { 31 | "build": "tsup", 32 | "clean": "git clean -xdf node_modules dist .tsbuildinfo", 33 | "dev": "tsup --watch", 34 | "format": "prettier --write .", 35 | "format:check": "prettier --check .", 36 | "lint": "pnpm typecheck && eslint .", 37 | "lint:fix": "eslint --fix .", 38 | "prepack": "tsx ../../.github/replace-workspace-protocol.ts", 39 | "prepublishOnly": "pnpm lint && pnpm format:check && pnpm build", 40 | "typecheck": "tsc --noEmit" 41 | }, 42 | "dependencies": { 43 | "eventemitter3": "^5.0.1", 44 | "ws": "^8.18.3" 45 | }, 46 | "devDependencies": { 47 | "@coinex-org/eslint-config": "workspace:*", 48 | "@coinex-org/internal-shared": "workspace:*", 49 | "@shahrad/tsconfig": "^1.1.0", 50 | "@types/node": "^22.13.14", 51 | "@types/ws": "^8.18.1", 52 | "dotenv": "^17.2.1", 53 | "eslint": "^9.23.0", 54 | "globals": "^16.0.0", 55 | "tsup": "^8.5.0", 56 | "tsx": "^4.20.3", 57 | "typescript": "^5.9.2" 58 | }, 59 | "engines": { 60 | "node": ">=18", 61 | "pnpm": "9.x" 62 | }, 63 | "publishConfig": { 64 | "access": "public", 65 | "provenance": true 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /packages/coinex/src/types.ts: -------------------------------------------------------------------------------- 1 | import { type Options } from 'ky'; 2 | 3 | export type * from './modules/account/types'; 4 | export type * from './modules/assets/types'; 5 | export type * from './modules/futures/types'; 6 | export type * from './modules/maintain/types'; 7 | export type * from './modules/spot/types'; 8 | 9 | /** 10 | * @interface CoinExOptions 11 | * @description Options for the CoinEx client. 12 | */ 13 | export interface CoinExOptions { 14 | /** 15 | * @property {string} apiKey - The API key (access ID). 16 | */ 17 | apiKey: string; 18 | /** 19 | * @property {string} secretKey - The secret key for signing requests. 20 | */ 21 | secretKey: string; 22 | /** 23 | * @property {Options} [kyOptions] - Custom options for the ky instance. 24 | */ 25 | kyOptions?: Options; 26 | } 27 | 28 | /** 29 | * @interface CoinExResponse 30 | * @description Represents the unified response structure from the CoinEx API v2. 31 | */ 32 | export interface CoinExResponse { 33 | /** 34 | * @property {number} code - The response code. Should be 0 for success. 35 | * @example 0 36 | */ 37 | code: number; 38 | /** 39 | * @property {T} data - The response data. 40 | */ 41 | data: T; 42 | /** 43 | * @property {string} message - The response message. 44 | * @example "OK" 45 | */ 46 | message: string; 47 | } 48 | 49 | export interface RequestOptions extends Options { 50 | responseType?: 'json' | 'text'; 51 | context?: { 52 | public?: boolean; 53 | }; 54 | } 55 | 56 | /** 57 | * @interface PingResponse 58 | * @description Response for the ping method. 59 | * @see https://docs.coinex.com/api/v2/common/http/ping 60 | */ 61 | export interface PingResponse { 62 | /** 63 | * @property {string} result - Should be "pong". 64 | */ 65 | result: 'pong'; 66 | } 67 | 68 | /** 69 | * @interface GetSystemTimeResponse 70 | * @description Response for the getSystemTime method. 71 | * @see https://docs.coinex.com/api/v2/common/http/time 72 | */ 73 | export interface GetSystemTimeResponse { 74 | /** 75 | * @property {number} timestamp - Server timestamp, unit: millisecond. 76 | */ 77 | timestamp: number; 78 | } 79 | -------------------------------------------------------------------------------- /packages/coinex/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@coinex-org/coinex", 3 | "version": "0.0.0", 4 | "description": "A lightweight, type-safe TypeScript HTTP client for the official CoinEx API v2, covering all major modules including Spot, Futures, Account, and Assets.", 5 | "keywords": [ 6 | "coinex", 7 | "api", 8 | "http", 9 | "client", 10 | "exchange", 11 | "crypto" 12 | ], 13 | "homepage": "https://github.com/shahradelahi/coinex/packages/coinex#readme", 14 | "repository": { 15 | "url": "https://github.com/shahradelahi/coinex.git", 16 | "directory": "/packages/coinex" 17 | }, 18 | "license": "MIT", 19 | "author": "Shahrad Elahi (https://github.com/shahradelahi)", 20 | "type": "module", 21 | "exports": { 22 | ".": { 23 | "types": "./dist/index.d.ts", 24 | "import": "./dist/index.js", 25 | "default": "./dist/index.cjs" 26 | } 27 | }, 28 | "files": [ 29 | "dist/**", 30 | "!**/*.d.cts" 31 | ], 32 | "scripts": { 33 | "build": "tsup", 34 | "clean": "git clean -xdf node_modules dist .tsbuildinfo", 35 | "dev": "tsup --watch", 36 | "format": "prettier --write .", 37 | "format:check": "prettier --check .", 38 | "lint": "pnpm typecheck && eslint .", 39 | "lint:fix": "eslint --fix .", 40 | "prepack": "tsx ../../.github/replace-workspace-protocol.ts", 41 | "prepublishOnly": "pnpm lint && pnpm format:check && pnpm build && pnpm test", 42 | "test": "vitest --run", 43 | "typecheck": "tsc --noEmit" 44 | }, 45 | "dependencies": { 46 | "deepmerge": "^4.3.1", 47 | "ky": "^1.8.1" 48 | }, 49 | "devDependencies": { 50 | "@coinex-org/eslint-config": "workspace:*", 51 | "@coinex-org/internal-shared": "workspace:*", 52 | "@shahrad/tsconfig": "^1.1.0", 53 | "@types/node": "^22.13.14", 54 | "dotenv": "^17.2.1", 55 | "eslint": "^9.23.0", 56 | "globals": "^16.0.0", 57 | "tsup": "^8.5.0", 58 | "tsx": "^4.20.3", 59 | "typescript": "^5.9.2", 60 | "vite-tsconfig-paths": "^5.1.4", 61 | "vitest": "^3.2.4" 62 | }, 63 | "engines": { 64 | "node": ">=18", 65 | "pnpm": "9.x" 66 | }, 67 | "publishConfig": { 68 | "access": "public", 69 | "provenance": true 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /packages/websocket/src/types.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * @interface CoinExWebSocketOptions 3 | * @description Options for the CoinEx WebSocket client. 4 | */ 5 | export interface CoinExWebSocketOptions { 6 | /** 7 | * @property {string} apiKey - The API key (access ID). 8 | */ 9 | apiKey: string; 10 | /** 11 | * @property {string} secretKey - The secret key for signing requests. 12 | */ 13 | secretKey: string; 14 | /** 15 | * @property {boolean} [autoConnect=true] - Whether to connect automatically on instantiation. 16 | */ 17 | autoConnect?: boolean; 18 | /** 19 | * @property {boolean} [autoReconnect=true] - Whether to reconnect automatically on connection loss. 20 | */ 21 | autoReconnect?: boolean; 22 | } 23 | 24 | /** 25 | * @interface WebSocketRequest 26 | * @description Represents a generic request sent to the WebSocket server. 27 | */ 28 | export interface WebSocketRequest { 29 | /** 30 | * @property {number} id - The request identifier. 31 | */ 32 | id: number; 33 | /** 34 | * @property {string} method - The method to be called. 35 | */ 36 | method: string; 37 | /** 38 | * @property {T} params - The parameters for the method. 39 | */ 40 | params: T; 41 | } 42 | 43 | /** 44 | * @interface WebSocketResponse 45 | * @description Represents a generic response from the WebSocket server. 46 | */ 47 | export interface WebSocketResponse { 48 | /** 49 | * @property {number} id - The request identifier. 50 | */ 51 | id: number; 52 | /** 53 | * @property {number} code - The response code. Should be 0 for success. 54 | */ 55 | code: number; 56 | /** 57 | * @property {string} method - The method of the response, usually an update. 58 | */ 59 | method?: string; 60 | /** 61 | * @property {T} data - The response data. 62 | */ 63 | data: T; 64 | /** 65 | * @property {string} message - The response message. 66 | */ 67 | message: string; 68 | } 69 | 70 | /** 71 | * @interface ServerTimeResponse 72 | * @description Response for server.time method. 73 | */ 74 | export interface ServerTimeResponse { 75 | timestamp: number; 76 | } 77 | 78 | /** 79 | * @interface PingResponse 80 | * @description Response for server.ping method. 81 | */ 82 | export interface PingResponse { 83 | result: 'pong'; 84 | } 85 | -------------------------------------------------------------------------------- /packages/websocket/src/modules/futures/executions/types.ts: -------------------------------------------------------------------------------- 1 | import { OrderSide } from '@coinex-org/internal-shared'; 2 | 3 | /** 4 | * @interface FuturesUserDealsSubscriptionParams 5 | * @description Parameters for subscribing to user transaction updates. 6 | */ 7 | export interface FuturesUserDealsSubscriptionParams { 8 | /** 9 | * @property {string[]} market_list - List of market names. 10 | * @description An empty array subscribes to all markets. 11 | */ 12 | market_list: string[]; 13 | } 14 | 15 | /** 16 | * @interface FuturesUserDealsUnsubscribeParams 17 | * @description Parameters for unsubscribing from user transaction updates. 18 | */ 19 | export interface FuturesUserDealsUnsubscribeParams { 20 | /** 21 | * @property {string[]} market_list - List of market names to unsubscribe from. An empty array unsubscribes from all. 22 | */ 23 | market_list: string[]; 24 | } 25 | 26 | /** 27 | * @interface FuturesUserDeal 28 | * @description Represents a single user transaction. 29 | */ 30 | export interface FuturesUserDeal { 31 | /** 32 | * @property {number} deal_id - Txid. 33 | */ 34 | deal_id: number; 35 | /** 36 | * @property {number} created_at - Transaction timestamp (millisecond). 37 | */ 38 | created_at: number; 39 | /** 40 | * @property {number} order_id - Related order id. 41 | */ 42 | order_id: number; 43 | /** 44 | * @property {string} client_id - Client ID. 45 | */ 46 | client_id: string; 47 | /** 48 | * @property {number} position_id - Position ID. 49 | */ 50 | position_id: number; 51 | /** 52 | * @property {string} market - Market name. 53 | */ 54 | market: string; 55 | /** 56 | * @property {OrderSide} side - Buy or sell. 57 | */ 58 | side: OrderSide; 59 | /** 60 | * @property {string} price - Filled price. 61 | */ 62 | price: string; 63 | /** 64 | * @property {string} amount - Filled volume. 65 | */ 66 | amount: string; 67 | /** 68 | * @property {'taker' | 'maker'} role - Taker or maker. 69 | */ 70 | role: 'taker' | 'maker'; 71 | /** 72 | * @property {string} fee - Trading fee charged. 73 | */ 74 | fee: string; 75 | /** 76 | * @property {string} fee_ccy - Trading fee currency. 77 | */ 78 | fee_ccy: string; 79 | } 80 | 81 | /** 82 | * @interface FuturesUserDealsUpdate 83 | * @description Represents a user transaction update push from the server. 84 | */ 85 | export type FuturesUserDealsUpdate = FuturesUserDeal; 86 | -------------------------------------------------------------------------------- /packages/websocket/src/modules/spot/executions/types.ts: -------------------------------------------------------------------------------- 1 | import { type OrderSide } from '@coinex-org/internal-shared'; 2 | 3 | /** 4 | * @interface SpotUserDealsSubscriptionParams 5 | * @description Parameters for subscribing to user transaction updates. 6 | */ 7 | export interface SpotUserDealsSubscriptionParams { 8 | /** 9 | * @property {string[]} market_list - List of market names. 10 | * @description An empty array subscribes to all markets. 11 | */ 12 | market_list: string[]; 13 | } 14 | 15 | /** 16 | * @interface SpotUserDealsUnsubscribeParams 17 | * @description Parameters for unsubscribing from user transaction updates. 18 | */ 19 | export interface SpotUserDealsUnsubscribeParams { 20 | /** 21 | * @property {string[]} market_list - List of market names to unsubscribe from. An empty array unsubscribes from all. 22 | */ 23 | market_list: string[]; 24 | } 25 | 26 | /** 27 | * @interface SpotUserDeal 28 | * @description Represents a single user transaction. 29 | */ 30 | export interface SpotUserDeal { 31 | /** 32 | * @property {number} deal_id - Transaction ID. 33 | */ 34 | deal_id: number; 35 | /** 36 | * @property {number} created_at - Transaction timestamp (millisecond). 37 | */ 38 | created_at: number; 39 | /** 40 | * @property {string} market - Market name. 41 | */ 42 | market: string; 43 | /** 44 | * @property {OrderSide} side - "buy" or "sell". 45 | */ 46 | side: OrderSide; 47 | /** 48 | * @property {number} order_id - Order ID. 49 | */ 50 | order_id: number; 51 | /** 52 | * @property {string} client_id - Client ID. 53 | */ 54 | client_id: string; 55 | /** 56 | * @property {string | null} margin_market - Margin market, null for non-margin markets. 57 | */ 58 | margin_market: string | null; 59 | /** 60 | * @property {string} price - Filled price. 61 | */ 62 | price: string; 63 | /** 64 | * @property {string} amount - Filled volume. 65 | */ 66 | amount: string; 67 | /** 68 | * @property {'taker' | 'maker'} role - "taker" or "maker". 69 | */ 70 | role: 'taker' | 'maker'; 71 | /** 72 | * @property {string} fee - Trading fee charged. 73 | */ 74 | fee: string; 75 | /** 76 | * @property {string} fee_ccy - Trading fee currency. 77 | */ 78 | fee_ccy: string; 79 | } 80 | 81 | /** 82 | * @interface SpotUserDealsUpdate 83 | * @description Represents a user transaction update push from the server. 84 | */ 85 | export type SpotUserDealsUpdate = SpotUserDeal; 86 | -------------------------------------------------------------------------------- /packages/coinex/src/modules/account/settings/module.ts: -------------------------------------------------------------------------------- 1 | import deepmerge from 'deepmerge'; 2 | 3 | import { type CoinExClient } from '@/client'; 4 | import { noUndefined } from '@/lib/object'; 5 | import type { RequestOptions } from '@/types'; 6 | 7 | import type { 8 | GetFuturesMarketSettingsResponse, 9 | ModifyAccountSettingsParams, 10 | ModifyFuturesMarketSettingsParams, 11 | } from './types'; 12 | 13 | export class Settings { 14 | #client: CoinExClient; 15 | 16 | constructor(client: CoinExClient) { 17 | this.#client = client; 18 | } 19 | 20 | /** 21 | * Query User Futures Market Settings 22 | * 23 | * @param options - The options for the request. 24 | * @returns {Promise} The futures market settings. 25 | * @see https://docs.coinex.com/api/v2/account/settings/http/accquire-futures-market-settings 26 | */ 27 | getFuturesMarketSettings( 28 | options: RequestOptions = {} 29 | ): Promise { 30 | return this.#client.request( 31 | 'account/futures/settings', 32 | deepmerge( 33 | { 34 | method: 'GET', 35 | }, 36 | options 37 | ) 38 | ); 39 | } 40 | 41 | /** 42 | * Modify Account Settings 43 | * 44 | * @param params - The parameters for the request. 45 | * @param options - The options for the request. 46 | * @returns {Promise<{}>} An empty object on success. 47 | * @see https://docs.coinex.com/api/v2/account/settings/http/modify-account-settings 48 | */ 49 | modifyAccountSettings( 50 | params: ModifyAccountSettingsParams, 51 | options: RequestOptions = {} 52 | ): Promise<{}> { 53 | return this.#client.request( 54 | 'account/settings', 55 | deepmerge({ method: 'POST', json: noUndefined(params) }, options) 56 | ); 57 | } 58 | 59 | /** 60 | * Change User Futures Market Settings 61 | * @param params - The parameters for the request. 62 | * @param options - The options for the request. 63 | * @returns {Promise<{}>} An empty object on success. 64 | * @see https://docs.coinex.com/api/v2/account/settings/http/modify-futures-market-settings 65 | */ 66 | modifyFuturesMarketSettings( 67 | params: ModifyFuturesMarketSettingsParams, 68 | options: RequestOptions = {} 69 | ): Promise<{}> { 70 | return this.#client.request( 71 | 'account/futures/settings', 72 | deepmerge({ method: 'POST', json: noUndefined(params) }, options) 73 | ); 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /packages/websocket/src/modules/spot/ticker/depth/types.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * @description Represents a single market subscription for depth updates. 3 | * [market_name, limit, interval, if_full] 4 | */ 5 | export type SpotDepthMarketSubscription = [ 6 | string, 7 | 5 | 10 | 20 | 50, 8 | ( 9 | | '0' 10 | | '0.00000000001' 11 | | '0.000000000001' 12 | | '0.0000000001' 13 | | '0.000000001' 14 | | '0.00000001' 15 | | '0.0000001' 16 | | '0.000001' 17 | | '0.00001' 18 | | '0.0001' 19 | | '0.001' 20 | | '0.01' 21 | | '0.1' 22 | | '1' 23 | | '10' 24 | | '100' 25 | | '1000' 26 | ), 27 | boolean, 28 | ]; 29 | 30 | /** 31 | * @interface SpotDepthSubscriptionParams 32 | * @description Parameters for subscribing to market depth updates. 33 | */ 34 | export interface SpotDepthSubscriptionParams { 35 | /** 36 | * @property {SpotDepthMarketSubscription[]} market_list - List of market subscriptions. 37 | */ 38 | market_list: SpotDepthMarketSubscription[]; 39 | } 40 | 41 | /** 42 | * @interface SpotDepthUnsubscribeParams 43 | * @description Parameters for unsubscribing from market depth updates. 44 | */ 45 | export interface SpotDepthUnsubscribeParams { 46 | /** 47 | * @property {string[]} market_list - List of market names to unsubscribe from. An empty array unsubscribes from all. 48 | */ 49 | market_list: string[]; 50 | } 51 | 52 | /** 53 | * @interface SpotDepthData 54 | * @description Represents the depth data for a market. 55 | */ 56 | export interface SpotDepthData { 57 | /** 58 | * @property {[string, string][]} asks - Seller data. 59 | */ 60 | asks: [string, string][]; 61 | /** 62 | * @property {[string, string][]} bids - Buyer data. 63 | */ 64 | bids: [string, string][]; 65 | /** 66 | * @property {string} last - Latest price. 67 | */ 68 | last: string; 69 | /** 70 | * @property {number} updated_at - Timestamp (millisecond). 71 | */ 72 | updated_at: number; 73 | /** 74 | * @property {number} checksum - Data checksum. 75 | */ 76 | checksum: number; 77 | } 78 | 79 | /** 80 | * @interface SpotDepthUpdate 81 | * @description Represents a market depth update push from the server. 82 | */ 83 | export interface SpotDepthUpdate { 84 | /** 85 | * @property {string} market - Market name. 86 | */ 87 | market: string; 88 | /** 89 | * @property {boolean} is_full - True means full push, and false means incremental push. 90 | */ 91 | is_full: boolean; 92 | /** 93 | * @property {SpotDepthData} depth - Depth data. 94 | */ 95 | depth: SpotDepthData; 96 | } 97 | -------------------------------------------------------------------------------- /packages/websocket/src/modules/futures/ticker/depth/types.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * @description Represents a single market subscription for depth updates. 3 | * [market_name, limit, interval, if_full] 4 | */ 5 | export type FuturesDepthMarketSubscription = [ 6 | string, 7 | 5 | 10 | 20 | 50, 8 | ( 9 | | '0' 10 | | '0.00000000001' 11 | | '0.000000000001' 12 | | '0.0000000001' 13 | | '0.000000001' 14 | | '0.00000001' 15 | | '0.0000001' 16 | | '0.000001' 17 | | '0.00001' 18 | | '0.0001' 19 | | '0.001' 20 | | '0.01' 21 | | '0.1' 22 | | '1' 23 | | '10' 24 | | '100' 25 | | '1000' 26 | ), 27 | boolean, 28 | ]; 29 | 30 | /** 31 | * @interface FuturesDepthSubscriptionParams 32 | * @description Parameters for subscribing to market depth updates. 33 | */ 34 | export interface FuturesDepthSubscriptionParams { 35 | /** 36 | * @property {FuturesDepthMarketSubscription[]} market_list - List of market subscriptions. 37 | */ 38 | market_list: FuturesDepthMarketSubscription[]; 39 | } 40 | 41 | /** 42 | * @interface FuturesDepthUnsubscribeParams 43 | * @description Parameters for unsubscribing from market depth updates. 44 | */ 45 | export interface FuturesDepthUnsubscribeParams { 46 | /** 47 | * @property {string[]} market_list - List of market names to unsubscribe from. An empty array unsubscribes from all. 48 | */ 49 | market_list: string[]; 50 | } 51 | 52 | /** 53 | * @interface FuturesDepthData 54 | * @description Represents the depth data for a market. 55 | */ 56 | export interface FuturesDepthData { 57 | /** 58 | * @property {[string, string][]} asks - Seller data. 59 | */ 60 | asks: [string, string][]; 61 | /** 62 | * @property {[string, string][]} bids - Buyer data. 63 | */ 64 | bids: [string, string][]; 65 | /** 66 | * @property {string} last - Latest price. 67 | */ 68 | last: string; 69 | /** 70 | * @property {number} updated_at - Timestamp (millisecond). 71 | */ 72 | updated_at: number; 73 | /** 74 | * @property {number} checksum - Data checksum. 75 | */ 76 | checksum: number; 77 | } 78 | 79 | /** 80 | * @interface FuturesDepthUpdate 81 | * @description Represents a market depth update push from the server. 82 | */ 83 | export interface FuturesDepthUpdate { 84 | /** 85 | * @property {string} market - Market name. 86 | */ 87 | market: string; 88 | /** 89 | * @property {boolean} is_full - True means full push, and false means incremental push. 90 | */ 91 | is_full: boolean; 92 | /** 93 | * @property {FuturesDepthData} depth - Depth data. 94 | */ 95 | depth: FuturesDepthData; 96 | } 97 | -------------------------------------------------------------------------------- /packages/websocket/src/modules/futures/ticker/state/types.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * @interface FuturesStateSubscriptionParams 3 | * @description Parameters for subscribing to market status updates. 4 | */ 5 | export interface FuturesStateSubscriptionParams { 6 | /** 7 | * @property {string[]} market_list - List of market names. 8 | * @description An empty array subscribes to all markets. 9 | */ 10 | market_list: string[]; 11 | } 12 | 13 | /** 14 | * @interface FuturesStateUpdate 15 | * @description Represents a futures market status update push from the server. 16 | */ 17 | export interface FuturesStateUpdate { 18 | /** 19 | * @property {string} market - Market name. 20 | */ 21 | market: string; 22 | /** 23 | * @property {string} last - Latest price. 24 | */ 25 | last: string; 26 | /** 27 | * @property {string} open - Opening price. 28 | */ 29 | open: string; 30 | /** 31 | * @property {string} close - Closing price. 32 | */ 33 | close: string; 34 | /** 35 | * @property {string} high - Highest price. 36 | */ 37 | high: string; 38 | /** 39 | * @property {string} low - Lowest price. 40 | */ 41 | low: string; 42 | /** 43 | * @property {string} volume - 24H volume. 44 | */ 45 | volume: string; 46 | /** 47 | * @property {string} value - 24h value. 48 | */ 49 | value: string; 50 | /** 51 | * @property {string} volume_sell - Best ask size. 52 | */ 53 | volume_sell: string; 54 | /** 55 | * @property {string} volume_buy - Best bid size. 56 | */ 57 | volume_buy: string; 58 | /** 59 | * @property {string} insurance_fund_size - Insurance fund amount. 60 | */ 61 | insurance_fund_size: string; 62 | /** 63 | * @property {string} mark_price - Mark price. 64 | */ 65 | mark_price: string; 66 | /** 67 | * @property {string} index_price - Index price. 68 | */ 69 | index_price: string; 70 | /** 71 | * @property {string} open_interest_size - Current position. 72 | */ 73 | open_interest_size: string; 74 | /** 75 | * @property {string} latest_funding_rate - Current funding rate. 76 | */ 77 | latest_funding_rate: string; 78 | /** 79 | * @property {string} next_funding_rate - Next funding rate. 80 | */ 81 | next_funding_rate: string; 82 | /** 83 | * @property {number} latest_funding_time - The time when the current funding rate is collected. 84 | */ 85 | latest_funding_time: number; 86 | /** 87 | * @property {number} next_funding_time - The time when the next funding rate will be collected. 88 | */ 89 | next_funding_time: number; 90 | /** 91 | * @property {number} period - Period, fixed at 86400, indicates that the data is a one-day value. 92 | */ 93 | period: number; 94 | } 95 | -------------------------------------------------------------------------------- /packages/coinex/src/modules/futures/deal/module.ts: -------------------------------------------------------------------------------- 1 | import deepmerge from 'deepmerge'; 2 | 3 | import { type CoinExClient } from '@/client'; 4 | import { noUndefined } from '@/lib/object'; 5 | import type { RequestOptions } from '@/types'; 6 | 7 | import type { 8 | ListUserDealsParams, 9 | ListUserDealsResponse, 10 | ListUserOrderDealsParams, 11 | ListUserOrderDealsResponse, 12 | } from './types'; 13 | 14 | export class Deal { 15 | #client: CoinExClient; 16 | 17 | constructor(client: CoinExClient) { 18 | this.#client = client; 19 | } 20 | 21 | /** 22 | * Get User Transaction 23 | * @description 24 | * **Info:** 25 | * - This endpoint requires signature. For specific signature rules, please refer to [Authentication](https://docs.coinex.com/api/v2/authorization). 26 | * - This endpoint will trigger rate limit. For specific rules, please refer to [Rate Limit](https://docs.coinex.com/api/v2/rate-limit). 27 | * 28 | * **Reminder:** 29 | * - The maximum limit is 100. 30 | * 31 | * @param params - The parameters for the request. 32 | * @param options - The options for the request. 33 | * @returns {Promise} The user deals. 34 | * @see https://docs.coinex.com/api/v2/futures/deal/http/list-user-deals 35 | */ 36 | listUserDeals( 37 | params: ListUserDealsParams, 38 | options: RequestOptions = {} 39 | ): Promise { 40 | return this.#client.request( 41 | 'futures/user-deals', 42 | deepmerge( 43 | { 44 | method: 'GET', 45 | searchParams: noUndefined(params), 46 | }, 47 | options 48 | ) 49 | ); 50 | } 51 | 52 | /** 53 | * Get User Order Transaction 54 | * @description 55 | * **Info:** 56 | * - This endpoint requires signature. For specific signature rules, please refer to [Authentication](https://docs.coinex.com/api/v2/authorization). 57 | * - This endpoint will trigger rate limit. For specific rules, please refer to [Rate Limit](https://docs.coinex.com/api/v2/rate-limit). 58 | * 59 | * **Reminder:** 60 | * - The maximum limit is 100. 61 | * 62 | * @param params - The parameters for the request. 63 | * @param options - The options for the request. 64 | * @returns {Promise} The user order deals. 65 | * @see https://docs.coinex.com/api/v2/futures/deal/http/list-user-order-deals 66 | */ 67 | listUserOrderDeals( 68 | params: ListUserOrderDealsParams, 69 | options: RequestOptions = {} 70 | ): Promise { 71 | return this.#client.request( 72 | 'futures/order-deals', 73 | deepmerge( 74 | { 75 | method: 'GET', 76 | searchParams: noUndefined(params), 77 | }, 78 | options 79 | ) 80 | ); 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | lerna-debug.log* 8 | 9 | # Diagnostic reports (https://nodejs.org/api/report.html) 10 | report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json 11 | 12 | # Runtime data 13 | pids 14 | *.pid 15 | *.seed 16 | *.pid.lock 17 | 18 | # Directory for instrumented libs generated by jscoverage/JSCover 19 | lib-cov 20 | 21 | # Coverage directory used by tools like istanbul 22 | coverage 23 | *.lcov 24 | 25 | # nyc test coverage 26 | .nyc_output 27 | 28 | # Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files) 29 | .grunt 30 | 31 | # Bower dependency directory (https://bower.io/) 32 | bower_components 33 | 34 | # node-waf configuration 35 | .lock-wscript 36 | 37 | # Compiled binary addons (https://nodejs.org/api/addons.html) 38 | build/Release 39 | 40 | # Dependency directories 41 | node_modules/ 42 | jspm_packages/ 43 | 44 | # Snowpack dependency directory (https://snowpack.dev/) 45 | web_modules/ 46 | 47 | # TypeScript cache 48 | *.tsbuildinfo 49 | 50 | # Optional npm cache directory 51 | .npm 52 | 53 | # Optional eslint cache 54 | .eslintcache 55 | 56 | # Optional stylelint cache 57 | .stylelintcache 58 | 59 | # Optional REPL history 60 | .node_repl_history 61 | 62 | # Output of 'npm pack' 63 | *.tgz 64 | 65 | # Yarn Integrity file 66 | .yarn-integrity 67 | 68 | # dotenv environment variable files 69 | .env 70 | .env.* 71 | !.env.example 72 | 73 | # parcel-bundler cache (https://parceljs.org/) 74 | .cache 75 | .parcel-cache 76 | 77 | # Next.js build output 78 | .next 79 | out 80 | 81 | # Nuxt.js build / generate output 82 | .nuxt 83 | dist 84 | 85 | # Gatsby files 86 | .cache/ 87 | # Comment in the public line in if your project uses Gatsby and not Next.js 88 | # https://nextjs.org/blog/next-9-1#public-directory-support 89 | # public 90 | 91 | # vuepress build output 92 | .vuepress/dist 93 | 94 | # vuepress v2.x temp and cache directory 95 | .temp 96 | .cache 97 | 98 | # Sveltekit cache directory 99 | .svelte-kit/ 100 | 101 | # vitepress build output 102 | **/.vitepress/dist 103 | 104 | # vitepress cache directory 105 | **/.vitepress/cache 106 | 107 | # Docusaurus cache and generated files 108 | .docusaurus 109 | 110 | # Serverless directories 111 | .serverless/ 112 | 113 | # FuseBox cache 114 | .fusebox/ 115 | 116 | # DynamoDB Local files 117 | .dynamodb/ 118 | 119 | # Firebase cache directory 120 | .firebase/ 121 | 122 | # TernJS port file 123 | .tern-port 124 | 125 | # Stores VSCode versions used for testing VSCode extensions 126 | .vscode-test 127 | 128 | # yarn v3 129 | .pnp.* 130 | .yarn/* 131 | !.yarn/patches 132 | !.yarn/plugins 133 | !.yarn/releases 134 | !.yarn/sdks 135 | !.yarn/versions 136 | 137 | # Vite logs files 138 | vite.config.js.timestamp-* 139 | vite.config.ts.timestamp-* 140 | 141 | # IDE directories 142 | .idea/ -------------------------------------------------------------------------------- /packages/coinex/src/modules/assets/transfer/types.ts: -------------------------------------------------------------------------------- 1 | import { type Pagination } from '../../account/subaccount/types'; 2 | 3 | /** 4 | * @interface GetAssetTransferHistoryParams 5 | * @description Parameters for getting asset transfer history 6 | * @see https://docs.coinex.com/api/v2/assets/transfer/http/list-transfer-history 7 | */ 8 | export interface GetAssetTransferHistoryParams { 9 | /** 10 | * @property {string} [ccy] - Currency name 11 | * @description If not passed, all currencies will be returned. 12 | * @example "USDT" 13 | */ 14 | ccy?: string; 15 | /** 16 | * @property {string} [status] - Transfer status 17 | * @example "success" 18 | */ 19 | status?: string; 20 | /** 21 | * @property {number} [start_time] - Start time 22 | */ 23 | start_time?: number; 24 | /** 25 | * @property {number} [end_time] - End time 26 | */ 27 | end_time?: number; 28 | /** 29 | * @property {number} [page] - Page number 30 | * @default 1 31 | */ 32 | page?: number; 33 | /** 34 | * @property {number} [limit] - Number of records per page 35 | * @default 100 36 | */ 37 | limit?: number; 38 | } 39 | 40 | /** 41 | * @interface AssetTransferHistory 42 | * @description Asset transfer history 43 | */ 44 | export interface AssetTransferHistory { 45 | /** 46 | * @property {number} transfer_id - Transfer ID 47 | * @example 12345 48 | */ 49 | transfer_id: number; 50 | /** 51 | * @property {string} from_account_type - From account type 52 | * @example "spot" 53 | */ 54 | from_account_type: string; 55 | /** 56 | * @property {string} to_account_type - To account type 57 | * @example "margin" 58 | */ 59 | to_account_type: string; 60 | /** 61 | * @property {string} ccy - Currency name 62 | * @example "USDT" 63 | */ 64 | ccy: string; 65 | /** 66 | * @property {string} amount - Transfer amount 67 | * @example "100" 68 | */ 69 | amount: string; 70 | /** 71 | * @property {string} status - Transfer status 72 | * @example "success" 73 | */ 74 | status: string; 75 | /** 76 | * @property {number} created_at - Creation time 77 | * @example 1614837902000 78 | */ 79 | created_at: number; 80 | } 81 | 82 | /** 83 | * @interface GetAssetTransferHistoryResponse 84 | * @description Response for getting asset transfer history 85 | */ 86 | export interface GetAssetTransferHistoryResponse { 87 | data: AssetTransferHistory[]; 88 | pagination: Pagination; 89 | } 90 | 91 | /** 92 | * @interface TransferParams 93 | * @description Parameters for making a transfer 94 | * @see https://docs.coinex.com/api/v2/assets/transfer/http/transfer 95 | */ 96 | export interface TransferParams { 97 | /** 98 | * @property {string} from_account_type - From account type 99 | * @example "spot" 100 | */ 101 | from_account_type: string; 102 | /** 103 | * @property {string} to_account_type - To account type 104 | * @example "margin" 105 | */ 106 | to_account_type: string; 107 | /** 108 | * @property {string} ccy - Currency name 109 | * @example "USDT" 110 | */ 111 | ccy: string; 112 | /** 113 | * @property {string} amount - Transfer amount 114 | * @example "100" 115 | */ 116 | amount: string; 117 | } 118 | -------------------------------------------------------------------------------- /packages/websocket/src/modules/spot/orders/stop/types.ts: -------------------------------------------------------------------------------- 1 | import { 2 | OrderSide, 3 | OrderType, 4 | StopOrderEvent, 5 | StopOrderStatus, 6 | TriggerDirection, 7 | } from '@coinex-org/internal-shared'; 8 | 9 | /** 10 | * @interface SpotStopOrderSubscriptionParams 11 | * @description Parameters for subscribing to user stop order updates. 12 | */ 13 | export interface SpotStopOrderSubscriptionParams { 14 | /** 15 | * @property {string[]} market_list - List of market names. 16 | * @description An empty array subscribes to all markets. 17 | */ 18 | market_list: string[]; 19 | } 20 | 21 | /** 22 | * @interface SpotStopOrderUnsubscribeParams 23 | * @description Parameters for unsubscribing from user stop order updates. 24 | */ 25 | export interface SpotStopOrderUnsubscribeParams { 26 | /** 27 | * @property {string[]} market_list - List of market names to unsubscribe from. An empty array unsubscribes from all. 28 | */ 29 | market_list: string[]; 30 | } 31 | 32 | /** 33 | * @interface SpotStopOrder 34 | * @description Represents a single stop order. 35 | */ 36 | export interface SpotStopOrder { 37 | /** 38 | * @property {number} stop_id - Order id. 39 | */ 40 | stop_id: number; 41 | /** 42 | * @property {string} market - Market name. 43 | */ 44 | market: string; 45 | /** 46 | * @property {string | null} margin_market - Margin market name, null for non-margin markets. 47 | */ 48 | margin_market: string | null; 49 | /** 50 | * @property {OrderType} type - Order type, limit, market, maker_only, IOC or FOK. 51 | */ 52 | type: OrderType; 53 | /** 54 | * @property {OrderSide} side - Sell or buy. 55 | */ 56 | side: OrderSide; 57 | /** 58 | * @property {string} amount - Order quantity after triggering. 59 | */ 60 | amount: string; 61 | /** 62 | * @property {string} price - Order price after triggering, market order as "0". 63 | */ 64 | price: string; 65 | /** 66 | * @property {string} trigger_price - Stop price. 67 | */ 68 | trigger_price: string; 69 | /** 70 | * @property {TriggerDirection} trigger_direction - Stop order trigger direction. 71 | */ 72 | trigger_direction: TriggerDirection; 73 | /** 74 | * @property {string} taker_fee_rate - Taker rate. 75 | */ 76 | taker_fee_rate: string; 77 | /** 78 | * @property {string} maker_fee_rate - Maker rate. 79 | */ 80 | maker_fee_rate: string; 81 | /** 82 | * @property {string} client_id - User-defined id. 83 | */ 84 | client_id: string; 85 | /** 86 | * @property {StopOrderStatus} status - Stop order status. 87 | */ 88 | status: StopOrderStatus; 89 | /** 90 | * @property {number} created_at - Order time, milliseconds. 91 | */ 92 | created_at: number; 93 | /** 94 | * @property {number} updated_at - Order time, milliseconds. 95 | */ 96 | updated_at: number; 97 | } 98 | 99 | /** 100 | * @interface SpotStopOrderUpdate 101 | * @description Represents a user stop order update push from the server. 102 | */ 103 | export interface SpotStopOrderUpdate { 104 | /** 105 | * @property {StopOrderEvent} event - Stop order update event type. 106 | */ 107 | event: StopOrderEvent; 108 | /** 109 | * @property {SpotStopOrder} stop - Stop order info. 110 | */ 111 | stop: SpotStopOrder; 112 | } 113 | -------------------------------------------------------------------------------- /packages/websocket/src/modules/futures/orders/stop/types.ts: -------------------------------------------------------------------------------- 1 | import { 2 | OrderSide, 3 | OrderType, 4 | StopOrderEvent, 5 | StopOrderStatus, 6 | TriggerDirection, 7 | TriggerPriceType, 8 | } from '@coinex-org/internal-shared'; 9 | 10 | /** 11 | * @interface FuturesStopOrderSubscriptionParams 12 | * @description Parameters for subscribing to user stop order updates. 13 | */ 14 | export interface FuturesStopOrderSubscriptionParams { 15 | /** 16 | * @property {string[]} market_list - List of market names. 17 | * @description An empty array subscribes to all markets. 18 | */ 19 | market_list: string[]; 20 | } 21 | 22 | /** 23 | * @interface FuturesStopOrderUnsubscribeParams 24 | * @description Parameters for unsubscribing from user stop order updates. 25 | */ 26 | export interface FuturesStopOrderUnsubscribeParams { 27 | /** 28 | * @property {string[]} market_list - List of market names to unsubscribe from. An empty array unsubscribes from all. 29 | */ 30 | market_list: string[]; 31 | } 32 | 33 | /** 34 | * @interface FuturesStopOrder 35 | * @description Represents a single stop order. 36 | */ 37 | export interface FuturesStopOrder { 38 | /** 39 | * @property {number} stop_id - Order id. 40 | */ 41 | stop_id: number; 42 | /** 43 | * @property {string} market - Market name. 44 | */ 45 | market: string; 46 | /** 47 | * @property {OrderSide} side - Sell or buy. 48 | */ 49 | side: OrderSide; 50 | /** 51 | * @property {OrderType} type - Order type, limit, market, maker_only, IOC or FOK. 52 | */ 53 | type: OrderType; 54 | /** 55 | * @property {string} price - Order price after triggering, market order as "0". 56 | */ 57 | price: string; 58 | /** 59 | * @property {string} amount - Order quantity after triggering. 60 | */ 61 | amount: string; 62 | /** 63 | * @property {string} trigger_price - Stop price. 64 | */ 65 | trigger_price: string; 66 | /** 67 | * @property {TriggerDirection} trigger_direction - Stop order trigger direction. 68 | */ 69 | trigger_direction: TriggerDirection; 70 | /** 71 | * @property {TriggerPriceType} trigger_price_type - Trigger price type. 72 | */ 73 | trigger_price_type: TriggerPriceType; 74 | /** 75 | * @property {string} taker_fee_rate - Taker rate. 76 | */ 77 | taker_fee_rate: string; 78 | /** 79 | * @property {string} maker_fee_rate - Maker rate. 80 | */ 81 | maker_fee_rate: string; 82 | /** 83 | * @property {string} client_id - User-defined id. 84 | */ 85 | client_id: string; 86 | /** 87 | * @property {StopOrderStatus} status - Stop order status. 88 | */ 89 | status: StopOrderStatus; 90 | /** 91 | * @property {number} created_at - Order time, milliseconds. 92 | */ 93 | created_at: number; 94 | /** 95 | * @property {number} updated_at - Order time, milliseconds. 96 | */ 97 | updated_at: number; 98 | } 99 | 100 | /** 101 | * @interface FuturesStopOrderUpdate 102 | * @description Represents a user stop order update push from the server. 103 | */ 104 | export interface FuturesStopOrderUpdate { 105 | /** 106 | * @property {StopOrderEvent} event - Stop order update event type. 107 | */ 108 | event: StopOrderEvent; 109 | /** 110 | * @property {FuturesStopOrder} stop - Stop order info. 111 | */ 112 | stop: FuturesStopOrder; 113 | } 114 | -------------------------------------------------------------------------------- /packages/coinex/src/modules/assets/amm/module.ts: -------------------------------------------------------------------------------- 1 | import deepmerge from 'deepmerge'; 2 | 3 | import { type CoinExClient } from '@/client'; 4 | import { noUndefined } from '@/lib/object'; 5 | import type { RequestOptions } from '@/types'; 6 | 7 | import type { 8 | AddAMMLiquidityParams, 9 | GetAMMIncomeHistoryParams, 10 | GetAMMIncomeHistoryResponse, 11 | GetAMMLiquidityPoolParams, 12 | GetAMMLiquidityPoolResponse, 13 | RemoveAMMLiquidityParams, 14 | } from './types'; 15 | 16 | export class Amm { 17 | #client: CoinExClient; 18 | 19 | constructor(client: CoinExClient) { 20 | this.#client = client; 21 | } 22 | 23 | /** 24 | * Add AMM Account Liquidity 25 | * 26 | * @param params - The parameters for the request. 27 | * @param options - The options for the request. 28 | * @returns {Promise<{}>} An empty object on success. 29 | * @see https://docs.coinex.com/api/v2/assets/amm/http/add-liquidtiy 30 | */ 31 | addAMMLiquidity(params: AddAMMLiquidityParams, options: RequestOptions = {}): Promise<{}> { 32 | return this.#client.request( 33 | 'assets/amm/liquidity', 34 | deepmerge({ method: 'POST', json: noUndefined(params) }, options) 35 | ); 36 | } 37 | 38 | /** 39 | * Get AMM Income History 40 | * 41 | * @param params - The parameters for the request. 42 | * @param options - The options for the request. 43 | * @returns {Promise} The AMM income history. 44 | * @see https://docs.coinex.com/api/v2/assets/amm/http/list-income-history 45 | */ 46 | getAMMIncomeHistory( 47 | params: GetAMMIncomeHistoryParams, 48 | options: RequestOptions = {} 49 | ): Promise { 50 | return this.#client.request( 51 | 'assets/amm/income-history', 52 | deepmerge( 53 | { 54 | method: 'GET', 55 | searchParams: noUndefined(params), 56 | }, 57 | options 58 | ) 59 | ); 60 | } 61 | 62 | /** 63 | * Get AMM Liquidity Pool 64 | * 65 | * @param params - The parameters for the request. 66 | * @param options - The options for the request. 67 | * @returns {Promise} The AMM liquidity pool. 68 | * @see https://docs.coinex.com/api/v2/assets/amm/http/list-liquidity-pool 69 | */ 70 | getAMMLiquidityPool( 71 | params: GetAMMLiquidityPoolParams, 72 | options: RequestOptions = {} 73 | ): Promise { 74 | return this.#client.request( 75 | 'assets/amm/liquidity-pool', 76 | deepmerge( 77 | { 78 | method: 'GET', 79 | searchParams: noUndefined(params), 80 | }, 81 | options 82 | ) 83 | ); 84 | } 85 | 86 | /** 87 | * Reduce AMM Account Liquidity 88 | * 89 | * @param params - The parameters for the request. 90 | * @param options - The options for the request. 91 | * @returns {Promise<{}>} An empty object on success. 92 | * @see https://docs.coinex.com/api/v2/assets/amm/http/remove-liquidtiy 93 | */ 94 | removeAMMLiquidity(params: RemoveAMMLiquidityParams, options: RequestOptions = {}): Promise<{}> { 95 | return this.#client.request( 96 | 'assets/amm/liquidity', 97 | deepmerge({ method: 'DELETE', json: noUndefined(params) }, options) 98 | ); 99 | } 100 | } 101 | -------------------------------------------------------------------------------- /packages/coinex/src/modules/assets/borrow-repay/module.ts: -------------------------------------------------------------------------------- 1 | import deepmerge from 'deepmerge'; 2 | 3 | import { type CoinExClient } from '@/client'; 4 | import { noUndefined } from '@/lib/object'; 5 | import type { RequestOptions } from '@/types'; 6 | 7 | import type { 8 | GetMarginBorrowHistoryParams, 9 | GetMarginBorrowHistoryResponse, 10 | GetMarginInterestLimitParams, 11 | GetMarginInterestLimitResponse, 12 | MarginBorrowParams, 13 | MarginRepayParams, 14 | } from './types'; 15 | 16 | export class BorrowRepay { 17 | #client: CoinExClient; 18 | 19 | constructor(client: CoinExClient) { 20 | this.#client = client; 21 | } 22 | 23 | /** 24 | * Get Borrowing Record in Margin Account 25 | * 26 | * @param params - The parameters for the request. 27 | * @param options - The options for the request. 28 | * @returns {Promise} The margin borrow history. 29 | * @see https://docs.coinex.com/api/v2/assets/loan-flat/http/list-margin-borrow-history 30 | */ 31 | getMarginBorrowHistory( 32 | params: GetMarginBorrowHistoryParams, 33 | options: RequestOptions = {} 34 | ): Promise { 35 | return this.#client.request( 36 | 'assets/margin-borrow-history', 37 | deepmerge( 38 | { 39 | method: 'GET', 40 | searchParams: noUndefined(params), 41 | }, 42 | options 43 | ) 44 | ); 45 | } 46 | 47 | /** 48 | * Get Borrowing Limit 49 | * 50 | * @param params - The parameters for the request. 51 | * @param options - The options for the request. 52 | * @returns {Promise} The margin interest limit. 53 | * @see https://docs.coinex.com/api/v2/assets/loan-flat/http/list-margin-interest-limit 54 | */ 55 | getMarginInterestLimit( 56 | params: GetMarginInterestLimitParams, 57 | options: RequestOptions = {} 58 | ): Promise { 59 | return this.#client.request( 60 | 'assets/margin-interest-limit', 61 | deepmerge( 62 | { 63 | method: 'GET', 64 | searchParams: noUndefined(params), 65 | }, 66 | options 67 | ) 68 | ); 69 | } 70 | 71 | /** 72 | * Margin Loan 73 | * 74 | * @param params - The parameters for the request. 75 | * @param options - The options for the request. 76 | * @returns {Promise<{}>} An empty object on success. 77 | * @see https://docs.coinex.com/api/v2/assets/loan-flat/http/margin-borrow 78 | */ 79 | marginBorrow(params: MarginBorrowParams, options: RequestOptions = {}): Promise<{}> { 80 | return this.#client.request( 81 | 'assets/margin-borrow', 82 | deepmerge({ method: 'POST', json: noUndefined(params) }, options) 83 | ); 84 | } 85 | 86 | /** 87 | * Margin Repayment 88 | * 89 | * @param params - The parameters for the request. 90 | * @param options - The options for the request. 91 | * @returns {Promise<{}>} An empty object on success. 92 | * @see https://docs.coinex.com/api/v2/assets/loan-flat/http/margin-repay 93 | */ 94 | marginRepay(params: MarginRepayParams, options: RequestOptions = {}): Promise<{}> { 95 | return this.#client.request( 96 | 'assets/margin-repay', 97 | deepmerge({ method: 'POST', json: noUndefined(params) }, options) 98 | ); 99 | } 100 | } 101 | -------------------------------------------------------------------------------- /packages/websocket/src/modules/futures/orders/types.ts: -------------------------------------------------------------------------------- 1 | import { OrderEvent, OrderSide, OrderType } from '@coinex-org/internal-shared'; 2 | 3 | export * from './stop/types'; 4 | 5 | /** 6 | * @interface FuturesOrderSubscriptionParams 7 | * @description Parameters for subscribing to user order updates. 8 | */ 9 | export interface FuturesOrderSubscriptionParams { 10 | /** 11 | * @property {string[]} market_list - List of market names. 12 | * @description An empty array subscribes to all markets. 13 | */ 14 | market_list: string[]; 15 | } 16 | 17 | /** 18 | * @interface FuturesOrderUnsubscribeParams 19 | * @description Parameters for unsubscribing from user order updates. 20 | */ 21 | export interface FuturesOrderUnsubscribeParams { 22 | /** 23 | * @property {string[]} market_list - List of market names to unsubscribe from. An empty array unsubscribes from all. 24 | */ 25 | market_list: string[]; 26 | } 27 | 28 | /** 29 | * @interface FuturesOrder 30 | * @description Represents a single order. 31 | */ 32 | export interface FuturesOrder { 33 | /** 34 | * @property {number} order_id - Order id. 35 | */ 36 | order_id: number; 37 | /** 38 | * @property {number} stop_id - Related stop order id. 39 | */ 40 | stop_id: number; 41 | /** 42 | * @property {string} market - Market name. 43 | */ 44 | market: string; 45 | /** 46 | * @property {OrderSide} side - Order side, buy or sell. 47 | */ 48 | side: OrderSide; 49 | /** 50 | * @property {OrderType} type - Order type, limit, market, GTC, IOC or FOK. 51 | */ 52 | type: OrderType; 53 | /** 54 | * @property {string} amount - Order amount. 55 | */ 56 | amount: string; 57 | /** 58 | * @property {string} price - Price. 59 | */ 60 | price: string; 61 | /** 62 | * @property {string} unfilled_amount - The remaining unfilled amount. 63 | */ 64 | unfilled_amount: string; 65 | /** 66 | * @property {string} filled_amount - Filled volume. 67 | */ 68 | filled_amount: string; 69 | /** 70 | * @property {string} filled_value - Filled value. 71 | */ 72 | filled_value: string; 73 | /** 74 | * @property {string} client_id - User-defined id. 75 | */ 76 | client_id: string; 77 | /** 78 | * @property {string} fee - Trading fee charged. 79 | */ 80 | fee: string; 81 | /** 82 | * @property {string} fee_ccy - Trading fee currency. 83 | */ 84 | fee_ccy: string; 85 | /** 86 | * @property {string} taker_fee_rate - Taker rate. 87 | */ 88 | taker_fee_rate: string; 89 | /** 90 | * @property {string} maker_fee_rate - Maker rate. 91 | */ 92 | maker_fee_rate: string; 93 | /** 94 | * @property {string} last_filled_amount - Filled amount of the last transaction. 95 | */ 96 | last_filled_amount: string; 97 | /** 98 | * @property {string} last_filled_price - Filled price of the last transaction. 99 | */ 100 | last_filled_price: string; 101 | /** 102 | * @property {number} created_at - Order timestamp (millisecond). 103 | */ 104 | created_at: number; 105 | /** 106 | * @property {number} updated_at - Latest update timestamp (milliseconds). 107 | */ 108 | updated_at: number; 109 | } 110 | 111 | /** 112 | * @interface FuturesOrderUpdate 113 | * @description Represents a user order update push from the server. 114 | */ 115 | export interface FuturesOrderUpdate { 116 | /** 117 | * @property {OrderEvent} event - Order update event type. 118 | */ 119 | event: OrderEvent; 120 | /** 121 | * @property {FuturesOrder} order - Order data. 122 | */ 123 | order: FuturesOrder; 124 | } 125 | -------------------------------------------------------------------------------- /packages/websocket/src/modules/spot/orders/types.ts: -------------------------------------------------------------------------------- 1 | import { OrderEvent, OrderSide, OrderType } from '@coinex-org/internal-shared'; 2 | 3 | export * from './stop/types'; 4 | 5 | /** 6 | * @interface SpotOrderSubscriptionParams 7 | * @description Parameters for subscribing to user order updates. 8 | */ 9 | export interface SpotOrderSubscriptionParams { 10 | /** 11 | * @property {string[]} market_list - List of market names. 12 | * @description An empty array subscribes to all markets. 13 | */ 14 | market_list: string[]; 15 | } 16 | 17 | /** 18 | * @interface SpotOrderUnsubscribeParams 19 | * @description Parameters for unsubscribing from user order updates. 20 | */ 21 | export interface SpotOrderUnsubscribeParams { 22 | /** 23 | * @property {string[]} market_list - List of market names to unsubscribe from. An empty array unsubscribes from all. 24 | */ 25 | market_list: string[]; 26 | } 27 | 28 | /** 29 | * @interface SpotOrder 30 | * @description Represents a single order. 31 | */ 32 | export interface SpotOrder { 33 | /** 34 | * @property {number} order_id - Order id. 35 | */ 36 | order_id: number; 37 | /** 38 | * @property {string} market - Market name. 39 | */ 40 | market: string; 41 | /** 42 | * @property {string | null} margin_market - Margin market name, null for non-margin markets. 43 | */ 44 | margin_market: string | null; 45 | /** 46 | * @property {OrderType} type - Order type, limit, market, maker_only, IOC or FOK. 47 | */ 48 | type: OrderType; 49 | /** 50 | * @property {OrderSide} side - Order side, buy or sell. 51 | */ 52 | side: OrderSide; 53 | /** 54 | * @property {string} amount - Order amount. 55 | */ 56 | amount: string; 57 | /** 58 | * @property {string} price - Price. 59 | */ 60 | price: string; 61 | /** 62 | * @property {string} unfilled_amount - The remaining unfilled amount. 63 | */ 64 | unfilled_amount: string; 65 | /** 66 | * @property {string} filled_value - Filled value. 67 | */ 68 | filled_value: string; 69 | /** 70 | * @property {string} taker_fee_rate - Taker rate. 71 | */ 72 | taker_fee_rate: string; 73 | /** 74 | * @property {string} maker_fee_rate - Maker rate. 75 | */ 76 | maker_fee_rate: string; 77 | /** 78 | * @property {string} base_ccy_fee - Trading fee paid in base currency. 79 | */ 80 | base_ccy_fee: string; 81 | /** 82 | * @property {string} quote_ccy_fee - Trading fee paid in quote currency. 83 | */ 84 | quote_ccy_fee: string; 85 | /** 86 | * @property {string} discount_ccy_fee - Trading fee paid mainly in CET. 87 | */ 88 | discount_ccy_fee: string; 89 | /** 90 | * @property {string} last_filled_amount - Filled amount of the last transaction. 91 | */ 92 | last_filled_amount: string; 93 | /** 94 | * @property {string} last_filled_price - Filled price of the last transaction. 95 | */ 96 | last_filled_price: string; 97 | /** 98 | * @property {string} client_id - User-defined id. 99 | */ 100 | client_id: string; 101 | /** 102 | * @property {number} created_at - Order timestamp, unit: millisecond. 103 | */ 104 | created_at: number; 105 | /** 106 | * @property {number} updated_at - Latest update timestamp, unit: millisecond. 107 | */ 108 | updated_at: number; 109 | } 110 | 111 | /** 112 | * @interface SpotOrderUpdate 113 | * @description Represents a user order update push from the server. 114 | */ 115 | export interface SpotOrderUpdate { 116 | /** 117 | * @property {OrderEvent} event - Order update event type. 118 | */ 119 | event: OrderEvent; 120 | /** 121 | * @property {SpotOrder} order - Order data. 122 | */ 123 | order: SpotOrder; 124 | } 125 | -------------------------------------------------------------------------------- /packages/coinex/src/modules/assets/amm/types.ts: -------------------------------------------------------------------------------- 1 | import { type Pagination } from '../../account/subaccount/types'; 2 | 3 | /** 4 | * @interface AddAMMLiquidityParams 5 | * @description Parameters for adding AMM liquidity 6 | * @see https://docs.coinex.com/api/v2/assets/amm/http/add-liquidtiy 7 | */ 8 | export interface AddAMMLiquidityParams { 9 | /** 10 | * @property {string} market - Market name 11 | * @example "CETUSDT" 12 | */ 13 | market: string; 14 | /** 15 | * @property {string} amount - The amount of asset to add 16 | * @example "100" 17 | */ 18 | amount: string; 19 | } 20 | 21 | /** 22 | * @interface GetAMMIncomeHistoryParams 23 | * @description Parameters for getting AMM income history 24 | * @see https://docs.coinex.com/api/v2/assets/amm/http/list-income-history 25 | */ 26 | export interface GetAMMIncomeHistoryParams { 27 | /** 28 | * @property {string} [market] - Market name 29 | * @description If not passed, all markets will be returned. 30 | * @example "CETUSDT" 31 | */ 32 | market?: string; 33 | /** 34 | * @property {number} [page] - Page number 35 | * @default 1 36 | */ 37 | page?: number; 38 | /** 39 | * @property {number} [limit] - Number of records per page 40 | * @default 100 41 | */ 42 | limit?: number; 43 | } 44 | 45 | /** 46 | * @interface AMMIncomeHistory 47 | * @description AMM income history 48 | */ 49 | export interface AMMIncomeHistory { 50 | /** 51 | * @property {string} market - Market name 52 | * @example "CETUSDT" 53 | */ 54 | market: string; 55 | /** 56 | * @property {string} income - Income 57 | * @example "0.1" 58 | */ 59 | income: string; 60 | /** 61 | * @property {number} created_at - Creation time 62 | * @example 1614837902000 63 | */ 64 | created_at: number; 65 | } 66 | 67 | /** 68 | * @interface GetAMMIncomeHistoryResponse 69 | * @description Response for getting AMM income history 70 | */ 71 | export interface GetAMMIncomeHistoryResponse { 72 | data: AMMIncomeHistory[]; 73 | pagination: Pagination; 74 | } 75 | 76 | /** 77 | * @interface GetAMMLiquidityPoolParams 78 | * @description Parameters for getting AMM liquidity pool 79 | * @see https://docs.coinex.com/api/v2/assets/amm/http/list-liquidity-pool 80 | */ 81 | export interface GetAMMLiquidityPoolParams { 82 | /** 83 | * @property {string} market - Market name list, separating multiple market names with "," and the maximum limit is 10 markets. 84 | * @example "CETUSDT,BTCUSDT" 85 | */ 86 | market: string; 87 | } 88 | 89 | /** 90 | * @interface AMMLiquidityPool 91 | * @description AMM liquidity pool 92 | */ 93 | export interface AMMLiquidityPool { 94 | /** 95 | * @property {string} market - Market name 96 | * @example "CETUSDT" 97 | */ 98 | market: string; 99 | /** 100 | * @property {string} total_liquidity - Total liquidity 101 | * @example "1000000" 102 | */ 103 | total_liquidity: string; 104 | /** 105 | * @property {string} apy - APY 106 | * @example "0.05" 107 | */ 108 | apy: string; 109 | } 110 | 111 | /** 112 | * @interface GetAMMLiquidityPoolResponse 113 | * @description Response for getting AMM liquidity pool 114 | */ 115 | export type GetAMMLiquidityPoolResponse = AMMLiquidityPool[]; 116 | 117 | /** 118 | * @interface RemoveAMMLiquidityParams 119 | * @description Parameters for removing AMM liquidity 120 | * @see https://docs.coinex.com/api/v2/assets/amm/http/remove-liquidtiy 121 | */ 122 | export interface RemoveAMMLiquidityParams { 123 | /** 124 | * @property {string} market - Market name 125 | * @example "CETUSDT" 126 | */ 127 | market: string; 128 | /** 129 | * @property {string} amount - The amount of asset to remove 130 | * @example "100" 131 | */ 132 | amount: string; 133 | } 134 | -------------------------------------------------------------------------------- /packages/websocket/src/client.ts: -------------------------------------------------------------------------------- 1 | import EventEmitter from 'eventemitter3'; 2 | 3 | import { AuthenticatedWebSocket } from '@/lib/websocket'; 4 | 5 | import { Futures, Spot } from './modules'; 6 | import type { 7 | CoinExWebSocketOptions, 8 | PingResponse, 9 | ServerTimeResponse, 10 | WebSocketRequest, 11 | WebSocketResponse, 12 | } from './types'; 13 | 14 | interface CoinExWebSocketEvents { 15 | open: (type: 'spot' | 'futures') => void; 16 | close: (type: 'spot' | 'futures') => void; 17 | error: (error: Error, type: 'spot' | 'futures') => void; 18 | message: (message: WebSocketResponse, type: 'spot' | 'futures') => void; 19 | } 20 | 21 | export class CoinExWebSocket extends EventEmitter { 22 | public readonly spot: Spot; 23 | public readonly futures: Futures; 24 | 25 | readonly #options: CoinExWebSocketOptions; 26 | 27 | constructor(options: CoinExWebSocketOptions) { 28 | super(); 29 | this.#options = { autoConnect: true, autoReconnect: true, ...options }; 30 | 31 | this.spot = new Spot(this.#options); 32 | this.futures = new Futures(this.#options); 33 | 34 | this.#forwardEvents(); 35 | 36 | if (this.#options.autoConnect) { 37 | this.connect().finally(() => {}); 38 | } 39 | } 40 | 41 | #forwardEvents() { 42 | const forward = (ws: AuthenticatedWebSocket, type: 'spot' | 'futures') => { 43 | ws.on('open', () => this.emit('open', type)); 44 | ws.on('close', () => this.emit('close', type)); 45 | ws.on('error', (error) => this.emit('error', error, type)); 46 | ws.on('message', (message) => this.emit('message', message, type)); 47 | }; 48 | 49 | forward(this.spot.ws, 'spot'); 50 | forward(this.futures.ws, 'futures'); 51 | } 52 | 53 | /** 54 | * Initiates the WebSocket connections. 55 | */ 56 | public async connect() { 57 | this.spot.ws.connect(); 58 | this.futures.ws.connect(); 59 | await this.#waitForConnection(); 60 | } 61 | 62 | /** 63 | * Closes the WebSocket connections. 64 | */ 65 | public close() { 66 | this.spot.ws.close(); 67 | this.futures.ws.close(); 68 | } 69 | 70 | /** 71 | * Sends a message to the specified WebSocket connection. 72 | * @param payload - The message payload. 73 | * @param type - The type of WebSocket connection to use. 74 | * @returns The message ID. 75 | */ 76 | public send(payload: Omit, 'id'>, type: 'spot' | 'futures'): number { 77 | if (type === 'spot') { 78 | return this.spot.ws.send(payload); 79 | } 80 | return this.futures.ws.send(payload); 81 | } 82 | 83 | /** 84 | * Pings the server to keep the connection alive. 85 | * @returns A promise that resolves with the ping response. 86 | * @see https://docs.coinex.com/api/v2/common/ws/ping 87 | */ 88 | public async ping(): Promise> { 89 | return this.spot.ws.sendAndCapture({ method: 'server.ping', params: {} }); 90 | } 91 | 92 | /** 93 | * Gets the server time. 94 | * @returns A promise that resolves with the server time response. 95 | * @see https://docs.coinex.com/api/v2/common/ws/time 96 | */ 97 | public async getServerTime(): Promise> { 98 | return this.spot.ws.sendAndCapture({ method: 'server.time', params: {} }); 99 | } 100 | 101 | /** 102 | * Waits for the WebSocket connections to be established. 103 | * @returns A promise that resolves when both connections are open. 104 | */ 105 | async #waitForConnection(): Promise { 106 | const promises: Promise[] = []; 107 | 108 | if (!this.spot.ws.isConnected()) { 109 | promises.push(new Promise((resolve) => this.spot.ws.once('open', resolve))); 110 | } 111 | 112 | if (!this.futures.ws.isConnected()) { 113 | promises.push(new Promise((resolve) => this.futures.ws.once('open', resolve))); 114 | } 115 | 116 | await Promise.all(promises); 117 | } 118 | } 119 | -------------------------------------------------------------------------------- /packages/coinex/src/modules/assets/borrow-repay/types.ts: -------------------------------------------------------------------------------- 1 | import { type Pagination } from '../../account/subaccount/types'; 2 | 3 | /** 4 | * @interface GetMarginBorrowHistoryParams 5 | * @description Parameters for getting margin borrow history 6 | * @see https://docs.coinex.com/api/v2/assets/loan-flat/http/list-margin-borrow-history 7 | */ 8 | export interface GetMarginBorrowHistoryParams { 9 | /** 10 | * @property {string} [market] - Market name 11 | * @description If not passed, all markets will be returned. 12 | * @example "BTCUSDT" 13 | */ 14 | market?: string; 15 | /** 16 | * @property {number} [page] - Page number 17 | * @default 1 18 | */ 19 | page?: number; 20 | /** 21 | * @property {number} [limit] - Number of records per page 22 | * @default 100 23 | */ 24 | limit?: number; 25 | } 26 | 27 | /** 28 | * @interface MarginBorrowHistory 29 | * @description Margin borrow history 30 | */ 31 | export interface MarginBorrowHistory { 32 | /** 33 | * @property {string} market - Market name 34 | * @example "BTCUSDT" 35 | */ 36 | market: string; 37 | /** 38 | * @property {string} ccy - Currency name 39 | * @example "USDT" 40 | */ 41 | ccy: string; 42 | /** 43 | * @property {string} amount - Borrow amount 44 | * @example "100" 45 | */ 46 | amount: string; 47 | /** 48 | * @property {number} created_at - Creation time 49 | * @example 1614837902000 50 | */ 51 | created_at: number; 52 | } 53 | 54 | /** 55 | * @interface GetMarginBorrowHistoryResponse 56 | * @description Response for getting margin borrow history 57 | */ 58 | export interface GetMarginBorrowHistoryResponse { 59 | data: MarginBorrowHistory[]; 60 | pagination: Pagination; 61 | } 62 | 63 | /** 64 | * @interface GetMarginInterestLimitParams 65 | * @description Parameters for getting margin interest limit 66 | * @see https://docs.coinex.com/api/v2/assets/loan-flat/http/list-margin-interest-limit 67 | */ 68 | export interface GetMarginInterestLimitParams { 69 | /** 70 | * @property {string} market - Market name 71 | * @example "BTCUSDT" 72 | */ 73 | market: string; 74 | /** 75 | * @property {string} ccy - Currency name 76 | * @example "USDT" 77 | */ 78 | ccy: string; 79 | } 80 | 81 | /** 82 | * @interface MarginInterestLimit 83 | * @description Margin interest limit 84 | */ 85 | export interface MarginInterestLimit { 86 | /** 87 | * @property {string} min_amount - Minimum borrow amount 88 | * @example "10" 89 | */ 90 | min_amount: string; 91 | /** 92 | * @property {string} max_amount - Maximum borrow amount 93 | * @example "10000" 94 | */ 95 | max_amount: string; 96 | /** 97 | * @property {string} daily_interest_rate - Daily interest rate 98 | * @example "0.001" 99 | */ 100 | daily_interest_rate: string; 101 | } 102 | 103 | /** 104 | * @interface GetMarginInterestLimitResponse 105 | * @description Response for getting margin interest limit 106 | */ 107 | export type GetMarginInterestLimitResponse = MarginInterestLimit; 108 | 109 | /** 110 | * @interface MarginBorrowParams 111 | * @description Parameters for margin borrow 112 | * @see https://docs.coinex.com/api/v2/assets/loan-flat/http/margin-borrow 113 | */ 114 | export interface MarginBorrowParams { 115 | /** 116 | * @property {string} market - Market name 117 | * @example "BTCUSDT" 118 | */ 119 | market: string; 120 | /** 121 | * @property {string} ccy - Currency name 122 | * @example "USDT" 123 | */ 124 | ccy: string; 125 | /** 126 | * @property {string} amount - Borrow amount 127 | * @example "100" 128 | */ 129 | amount: string; 130 | } 131 | 132 | /** 133 | * @interface MarginRepayParams 134 | * @description Parameters for margin repay 135 | * @see https://docs.coinex.com/api/v2/assets/loan-flat/http/margin-repay 136 | */ 137 | export interface MarginRepayParams { 138 | /** 139 | * @property {string} market - Market name 140 | * @example "BTCUSDT" 141 | */ 142 | market: string; 143 | /** 144 | * @property {string} ccy - Currency name 145 | * @example "USDT" 146 | */ 147 | ccy: string; 148 | /** 149 | * @property {string} amount - Repay amount 150 | * @example "100" 151 | */ 152 | amount: string; 153 | } 154 | -------------------------------------------------------------------------------- /packages/websocket/README.md: -------------------------------------------------------------------------------- 1 | # @coinex-org/websocket 2 | 3 | A lightweight, type-safe TypeScript client for the official CoinEx WebSocket API v2. 4 | 5 | ## Features 6 | 7 | - **Type-Safe:** Fully typed subscriptions and events for a better developer experience. 8 | - **Dual Clients:** Separate, dedicated WebSocket clients for Spot and Futures markets. 9 | - **Event-Driven:** Use `EventEmitter` to handle WebSocket events like `open`, `close`, and `error`. 10 | - **Auto-Authentication:** Handles authentication automatically for private channels. 11 | - **Auto-Reconnect:** Automatically reconnects if the connection is lost. 12 | 13 | ## Installation 14 | 15 | ```bash 16 | npm install @coinex-org/websocket 17 | ``` 18 | 19 |
20 | Install using your favorite package manager 21 | 22 | **pnpm** 23 | 24 | ```bash 25 | pnpm install @coinex-org/websocket 26 | ``` 27 | 28 | **yarn** 29 | 30 | ```bash 31 | yarn add @coinex-org/websocket 32 | ``` 33 | 34 |
35 | 36 | ## Usage 37 | 38 | First, import and initialize the `CoinExWebSocket` client with your API Key and Secret Key. 39 | 40 | ```typescript 41 | import { CoinExWebSocket } from '@coinex-org/websocket'; 42 | 43 | const client = new CoinExWebSocket({ 44 | apiKey: 'YOUR_API_KEY', 45 | secretKey: 'YOUR_SECRET_KEY', 46 | }); 47 | 48 | client.on('open', (type) => { 49 | console.log(`WebSocket connection opened for ${type}`); 50 | 51 | // Subscribe to public Spot market data 52 | if (type === 'spot') { 53 | console.log('Subscribing to BTCUSDT ticker...'); 54 | client.spot.ticker.state.subscribe( 55 | { market_list: ['BTCUSDT'] }, 56 | (update) => { 57 | console.log('Received spot ticker update:', update); 58 | } 59 | ); 60 | } 61 | 62 | // Subscribe to private Futures data 63 | if (type === 'futures') { 64 | console.log('Subscribing to futures balance...'); 65 | client.futures.balance.subscribe({ ccy_list: [] }, (update) => { 66 | console.log('Received futures balance update:', update); 67 | }); 68 | } 69 | }); 70 | 71 | client.on('error', (error, type) => { 72 | console.error(`Error on ${type} WebSocket:`, error); 73 | }); 74 | 75 | client.on('close', (type) => { 76 | console.log(`WebSocket connection closed for ${type}`); 77 | }); 78 | ``` 79 | 80 | ## Documentation 81 | 82 | For all configuration options, please see [the API docs](https://www.jsdocs.io/package/@coinex-org/websocket). 83 | 84 | ## API Reference 85 | 86 | ### `CoinExWebSocket` 87 | 88 | #### Events 89 | 90 | - `on('open', (type: 'spot' | 'futures') => void)`: Emitted when a WebSocket connection is successfully opened and authenticated. 91 | - `on('close', (type: 'spot' | 'futures') => void)`: Emitted when a WebSocket connection is closed. 92 | - `on('error', (error: Error, type: 'spot' | 'futures') => void)`: Emitted when a WebSocket error occurs. 93 | - `on('message', (message: any, type: 'spot' | 'futures') => void)`: Emitted when any message is received. 94 | 95 | #### Methods 96 | 97 | - `connect()`: Manually initiate the WebSocket connections. 98 | - `close()`: Manually close the WebSocket connections. 99 | - `ping()`: Ping the server to check connectivity. 100 | - `getServerTime()`: Get the current server time. 101 | 102 | ### Spot Subscriptions (`client.spot`) 103 | 104 | - **Balance**: `subscribe`, `unsubscribe` 105 | - **Executions**: `subscribe`, `unsubscribe` 106 | - **Orders**: `subscribe`, `unsubscribe` 107 | - **Stop Orders**: `stop.subscribe`, `stop.unsubscribe` 108 | - **Ticker**: 109 | - **BBO**: `bbo.subscribe`, `bbo.unsubscribe` 110 | - **Deals**: `deals.subscribe`, `deals.unsubscribe` 111 | - **Depth**: `depth.subscribe`, `depth.unsubscribe` 112 | - **Index**: `index.subscribe`, `index.unsubscribe` 113 | - **State**: `state.subscribe`, `state.unsubscribe` 114 | 115 | ### Futures Subscriptions (`client.futures`) 116 | 117 | - **Balance**: `subscribe`, `unsubscribe` 118 | - **Executions**: `subscribe`, `unsubscribe` 119 | - **Orders**: `subscribe`, `unsubscribe` 120 | - **Stop Orders**: `stop.subscribe`, `stop.unsubscribe` 121 | - **Position**: `subscribe`, `unsubscribe` 122 | - **Ticker**: 123 | - **BBO**: `bbo.subscribe`, `bbo.unsubscribe` 124 | - **Deals**: `deals.subscribe`, `deals.unsubscribe` 125 | - **Depth**: `depth.subscribe`, `depth.unsubscribe` 126 | - **Index**: `index.subscribe`, `index.unsubscribe` 127 | - **State**: `state.subscribe`, `state.unsubscribe` 128 | 129 | ## License 130 | 131 | [MIT](/LICENSE) © [Shahrad Elahi](https://github.com/shahradelahi) and [contributors](https://github.com/shahradelahi/coinex/graphs/contributors). 132 | -------------------------------------------------------------------------------- /packages/coinex/src/client.ts: -------------------------------------------------------------------------------- 1 | import deepmerge from 'deepmerge'; 2 | import ky, { type BeforeRequestHook, type KyInstance } from 'ky'; 3 | 4 | import { signRequest } from './lib/crypto'; 5 | import { CoinExAPIError } from './lib/errors'; 6 | import { Account, Assets, Futures, Maintain, Spot } from './modules'; 7 | import { 8 | CoinExOptions, 9 | CoinExResponse, 10 | GetSystemTimeResponse, 11 | PingResponse, 12 | RequestOptions, 13 | } from './types'; 14 | 15 | export class CoinExClient { 16 | readonly #apiKey: string; 17 | readonly #secretKey: string; 18 | readonly #api: KyInstance; 19 | 20 | public readonly account: Account; 21 | public readonly assets: Assets; 22 | public readonly maintain: Maintain; 23 | public readonly spot: Spot; 24 | public readonly futures: Futures; 25 | 26 | constructor(options: CoinExOptions) { 27 | this.#apiKey = options.apiKey; 28 | this.#secretKey = options.secretKey; 29 | 30 | const beforeRequest: BeforeRequestHook = (request, options: RequestOptions) => { 31 | if (options.context?.public) { 32 | return; 33 | } 34 | 35 | const timestamp = Date.now(); 36 | const body = (options as any).json ? JSON.stringify((options as any).json) : undefined; 37 | const url = new URL(request.url); 38 | const path = url.pathname + url.search; 39 | 40 | const signature = signRequest(request.method, path, body, timestamp, this.#secretKey); 41 | 42 | request.headers.set('X-COINEX-KEY', this.#apiKey); 43 | request.headers.set('X-COINEX-SIGN', signature); 44 | request.headers.set('X-COINEX-TIMESTAMP', String(timestamp)); 45 | if (body) { 46 | request.headers.set('Content-Type', 'application/json; charset=utf-8'); 47 | } 48 | }; 49 | 50 | this.#api = ky.create( 51 | deepmerge( 52 | { 53 | prefixUrl: 'https://api.coinex.com/v2', 54 | timeout: 10000, 55 | hooks: { 56 | beforeRequest: [beforeRequest], 57 | afterResponse: [ 58 | async (_request, _options, response) => { 59 | const contentType = response.headers.get('content-type'); 60 | if (contentType?.includes('application/json')) { 61 | const clonedResponse = response.clone(); 62 | const json = (await clonedResponse.json()) as CoinExResponse; 63 | if (json.code !== 0) { 64 | throw new CoinExAPIError(json.code, json.message); 65 | } 66 | // Return a new response with just the data part of the body 67 | return new Response(JSON.stringify(json.data), response); 68 | } 69 | return response; 70 | }, 71 | ], 72 | }, 73 | }, 74 | options.kyOptions || {} 75 | ) 76 | ); 77 | 78 | this.account = new Account(this); 79 | this.assets = new Assets(this); 80 | this.maintain = new Maintain(this); 81 | this.spot = new Spot(this); 82 | this.futures = new Futures(this); 83 | } 84 | 85 | public request(path: string, options?: RequestOptions): Promise { 86 | const { responseType = 'json', ...restOptions } = options || {}; 87 | 88 | const kyPromise = this.#api(path, restOptions); 89 | 90 | if (responseType === 'text') { 91 | return kyPromise.text() as Promise; 92 | } 93 | 94 | return kyPromise.json(); 95 | } 96 | 97 | /** 98 | * Ping the server. 99 | * @param options - The options for the request. 100 | * @returns {Promise} A promise that resolves with the ping response. 101 | * @see https://docs.coinex.com/api/v2/common/http/ping 102 | */ 103 | public ping(options: RequestOptions = {}): Promise { 104 | return this.request( 105 | 'ping', 106 | deepmerge( 107 | { 108 | method: 'GET', 109 | context: { 110 | public: true, 111 | }, 112 | }, 113 | options 114 | ) 115 | ); 116 | } 117 | 118 | /** 119 | * Get the system time. 120 | * @param options - The options for the request. 121 | * @returns {Promise} A promise that resolves with the system time. 122 | * @see https://docs.coinex.com/api/v2/common/http/time 123 | */ 124 | public getSystemTime(options: RequestOptions = {}): Promise { 125 | return this.request( 126 | 'time', 127 | deepmerge( 128 | { 129 | method: 'GET', 130 | context: { 131 | public: true, 132 | }, 133 | }, 134 | options 135 | ) 136 | ); 137 | } 138 | } 139 | -------------------------------------------------------------------------------- /packages/websocket/src/modules/futures/position/types.ts: -------------------------------------------------------------------------------- 1 | import { 2 | MarginMode, 3 | PositionEvent, 4 | PositionSide, 5 | StopLossType, 6 | TakeProfitType, 7 | } from '@coinex-org/internal-shared'; 8 | 9 | /** 10 | * @interface FuturesPositionSubscriptionParams 11 | * @description Parameters for subscribing to user position updates. 12 | */ 13 | export interface FuturesPositionSubscriptionParams { 14 | /** 15 | * @property {string[]} market_list - List of market names. 16 | * @description An empty array subscribes to all markets. 17 | */ 18 | market_list: string[]; 19 | } 20 | 21 | /** 22 | * @interface FuturesPositionUnsubscribeParams 23 | * @description Parameters for unsubscribing from user position updates. 24 | */ 25 | export interface FuturesPositionUnsubscribeParams { 26 | /** 27 | * @property {string[]} market_list - List of market names to unsubscribe from. An empty array unsubscribes from all. 28 | */ 29 | market_list: string[]; 30 | } 31 | 32 | /** 33 | * @interface FuturesPosition 34 | * @description Represents a single user position. 35 | */ 36 | export interface FuturesPosition { 37 | /** 38 | * @property {number} position_id - Position ID. 39 | */ 40 | position_id: number; 41 | /** 42 | * @property {string} market - Market name. 43 | */ 44 | market: string; 45 | /** 46 | * @property {PositionSide} side - Position side, long or short. 47 | */ 48 | side: PositionSide; 49 | /** 50 | * @property {MarginMode} margin_mode - Position type, cross or isolated. 51 | */ 52 | margin_mode: MarginMode; 53 | /** 54 | * @property {string} open_interest - Position. 55 | */ 56 | open_interest: string; 57 | /** 58 | * @property {string} close_avbl - Amount that's available for position closing. 59 | */ 60 | close_avbl: string; 61 | /** 62 | * @property {string} ath_position_amount - ATH position amount. 63 | */ 64 | ath_position_amount: string; 65 | /** 66 | * @property {string} unrealized_pnl - Unrealized PNL. 67 | */ 68 | unrealized_pnl: string; 69 | /** 70 | * @property {string} realized_pnl - Realized PNL. 71 | */ 72 | realized_pnl: string; 73 | /** 74 | * @property {string} avg_entry_price - Average entry price. 75 | */ 76 | avg_entry_price: string; 77 | /** 78 | * @property {string} cml_position_value - Cumulative position value. 79 | */ 80 | cml_position_value: string; 81 | /** 82 | * @property {string} max_position_value - Max. position value. 83 | */ 84 | max_position_value: string; 85 | /** 86 | * @property {string} take_profit_price - Take-profit price. 87 | */ 88 | take_profit_price: string; 89 | /** 90 | * @property {string} stop_loss_price - Stop-loss price. 91 | */ 92 | stop_loss_price: string; 93 | /** 94 | * @property {TakeProfitType} take_profit_type - Take profit trigger price type, latest_price or mark_price. 95 | */ 96 | take_profit_type: TakeProfitType; 97 | /** 98 | * @property {StopLossType} stop_loss_type - Stop loss trigger price type, latest_price or mark_price. 99 | */ 100 | stop_loss_type: StopLossType; 101 | /** 102 | * @property {string} leverage - Leverage. 103 | */ 104 | leverage: string; 105 | /** 106 | * @property {string} margin_avbl - Margin available. 107 | */ 108 | margin_avbl: string; 109 | /** 110 | * @property {string} ath_margin_size - ATH margin amount. 111 | */ 112 | ath_margin_size: string; 113 | /** 114 | * @property {string} position_margin_rate - Position margin rate. 115 | */ 116 | position_margin_rate: string; 117 | /** 118 | * @property {string} maintenance_margin_rate - Maintenance margin rate. 119 | */ 120 | maintenance_margin_rate: string; 121 | /** 122 | * @property {string} maintenance_margin_value - Maintenance margin amount. 123 | */ 124 | maintenance_margin_value: string; 125 | /** 126 | * @property {string} liq_price - Liquidation price. 127 | */ 128 | liq_price: string; 129 | /** 130 | * @property {string} bkr_price - Bankruptcy price. 131 | */ 132 | bkr_price: string; 133 | /** 134 | * @property {number} adl_level - Auto-deleveraging level. 135 | */ 136 | adl_level: number; 137 | /** 138 | * @property {string} settle_price - Settlement price, calculated as mark price. 139 | */ 140 | settle_price: string; 141 | /** 142 | * @property {string} settle_val - Settlement value, calculated as mark price. 143 | */ 144 | settle_val: string; 145 | /** 146 | * @property {string} first_filled_price - The first filled price of the position. 147 | */ 148 | first_filled_price: string; 149 | /** 150 | * @property {string} latest_filled_price - The latest filled price of the position. 151 | */ 152 | latest_filled_price: string; 153 | /** 154 | * @property {number} created_at - Position creation timestamp (milliseconds). 155 | */ 156 | created_at: number; 157 | /** 158 | * @property {number} updated_at - Position update timestamp (milliseconds). 159 | */ 160 | updated_at: number; 161 | } 162 | 163 | /** 164 | * @interface FuturesPositionUpdate 165 | * @description Represents a user position update push from the server. 166 | */ 167 | export interface FuturesPositionUpdate { 168 | /** 169 | * @property {PositionEvent} event - Position update event type. 170 | */ 171 | event: PositionEvent; 172 | /** 173 | * @property {FuturesPosition} position - Position info. 174 | */ 175 | position: FuturesPosition; 176 | } 177 | -------------------------------------------------------------------------------- /packages/coinex/src/modules/spot/deal/types.ts: -------------------------------------------------------------------------------- 1 | import { type OrderSide } from '@coinex-org/internal-shared'; 2 | 3 | import { type Pagination } from '@/modules'; 4 | 5 | /** 6 | * @interface SpotUserDeal 7 | * @description Represents a single user deal in the spot market. 8 | * @see https://docs.coinex.com/api/v2/spot/deal/http/list-user-deals 9 | */ 10 | export interface SpotUserDeal { 11 | /** 12 | * @property {number} deal_id - The ID of the deal. 13 | */ 14 | deal_id: number; 15 | /** 16 | * @property {number} created_at - The time the deal was created. 17 | */ 18 | created_at: number; 19 | /** 20 | * @property {string} market - The market in which the deal was executed. 21 | */ 22 | market: string; 23 | /** 24 | * @property {number} order_id - The ID of the order associated with the deal. 25 | */ 26 | order_id: number; 27 | /** 28 | * @property {OrderSide} side - The side of the order, "buy" or "sell". 29 | */ 30 | side: OrderSide; 31 | /** 32 | * @property {'taker' | 'maker'} type - The type of the deal, "taker" or "maker". 33 | */ 34 | type: 'taker' | 'maker'; 35 | /** 36 | * @property {string} fee - The transaction fee. 37 | */ 38 | fee: string; 39 | /** 40 | * @property {string} fee_ccy - The currency of the transaction fee. 41 | */ 42 | fee_ccy: string; 43 | /** 44 | * @property {string} price - The price at which the deal was executed. 45 | */ 46 | price: string; 47 | /** 48 | * @property {string} amount - The amount of the deal. 49 | */ 50 | amount: string; 51 | /** 52 | * @property {string} value - The total value of the deal. 53 | */ 54 | value: string; 55 | } 56 | 57 | /** 58 | * @interface SpotListUserDealsParams 59 | * @description Parameters for listing user deals in the spot market. 60 | * @see https://docs.coinex.com/api/v2/spot/deal/http/list-user-deals 61 | */ 62 | export interface SpotListUserDealsParams { 63 | /** 64 | * @property {string} [market] - The market to query, e.g., "BTCUSDT". 65 | */ 66 | market?: string; 67 | /** 68 | * @property {OrderSide} [side] - The side of the order, "buy" or "sell". 69 | */ 70 | side?: OrderSide; 71 | /** 72 | * @property {number} [start_time] - The start time of the query range. 73 | */ 74 | start_time?: number; 75 | /** 76 | * @property {number} [end_time] - The end time of the query range. 77 | */ 78 | end_time?: number; 79 | /** 80 | * @property {number} [page] - The page number to retrieve. 81 | */ 82 | page?: number; 83 | /** 84 | * @property {number} [limit] - The number of deals to retrieve per page. 85 | */ 86 | limit?: number; 87 | } 88 | 89 | /** 90 | * @interface SpotListUserDealsResponse 91 | * @description The response for the listUserDeals method. 92 | */ 93 | export interface SpotListUserDealsResponse { 94 | data: SpotUserDeal[]; 95 | pagination: Pagination; 96 | } 97 | 98 | /** 99 | * @interface SpotUserOrderDeal 100 | * @description Represents a single user order deal in the spot market. 101 | * @see https://docs.coinex.com/api/v2/spot/deal/http/list-user-order-deals 102 | */ 103 | export interface SpotUserOrderDeal { 104 | /** 105 | * @property {number} deal_id - The ID of the deal. 106 | */ 107 | deal_id: number; 108 | /** 109 | * @property {number} created_at - The time the deal was created. 110 | */ 111 | created_at: number; 112 | /** 113 | * @property {string} market - The market in which the deal was executed. 114 | */ 115 | market: string; 116 | /** 117 | * @property {number} order_id - The ID of the order associated with the deal. 118 | */ 119 | order_id: number; 120 | /** 121 | * @property {OrderSide} side - The side of the order, "buy" or "sell". 122 | */ 123 | side: OrderSide; 124 | /** 125 | * @property {'taker' | 'maker'} type - The type of the deal, "taker" or "maker". 126 | */ 127 | type: 'taker' | 'maker'; 128 | /** 129 | * @property {string} fee - The transaction fee. 130 | */ 131 | fee: string; 132 | /** 133 | * @property {string} fee_ccy - The currency of the transaction fee. 134 | */ 135 | fee_ccy: string; 136 | /** 137 | * @property {string} price - The price at which the deal was executed. 138 | */ 139 | price: string; 140 | /** 141 | * @property {string} amount - The amount of the deal. 142 | */ 143 | amount: string; 144 | /** 145 | * @property {string} value - The total value of the deal. 146 | */ 147 | value: string; 148 | } 149 | 150 | /** 151 | * @interface SpotListUserOrderDealsParams 152 | * @description Parameters for listing user order deals in the spot market. 153 | * @see https://docs.coinex.com/api/v2/spot/deal/http/list-user-order-deals 154 | */ 155 | export interface SpotListUserOrderDealsParams { 156 | /** 157 | * @property {string} market - The market to query, e.g., "BTCUSDT". 158 | */ 159 | market: string; 160 | /** 161 | * @property {number} order_id - The ID of the order to retrieve deals for. 162 | */ 163 | order_id: number; 164 | /** 165 | * @property {number} [page] - The page number to retrieve. 166 | */ 167 | page?: number; 168 | /** 169 | * @property {number} [limit] - The number of deals to retrieve per page. 170 | */ 171 | limit?: number; 172 | } 173 | 174 | /** 175 | * @interface SpotListUserOrderDealsResponse 176 | * @description The response for the listUserOrderDeals method. 177 | */ 178 | export interface SpotListUserOrderDealsResponse { 179 | data: SpotUserOrderDeal[]; 180 | pagination: Pagination; 181 | } 182 | -------------------------------------------------------------------------------- /packages/coinex/src/modules/spot/market/module.ts: -------------------------------------------------------------------------------- 1 | import deepmerge from 'deepmerge'; 2 | 3 | import { type CoinExClient } from '@/client'; 4 | import { noUndefined } from '@/lib/object'; 5 | import type { RequestOptions } from '@/types'; 6 | 7 | import type { 8 | SpotListMarketDealsParams, 9 | SpotListMarketDealsResponse, 10 | SpotListMarketDepthParams, 11 | SpotListMarketDepthResponse, 12 | SpotListMarketIndexParams, 13 | SpotListMarketIndexResponse, 14 | SpotListMarketKlineParams, 15 | SpotListMarketKlineResponse, 16 | SpotListMarketParams, 17 | SpotListMarketResponse, 18 | SpotListMarketTickerParams, 19 | SpotListMarketTickerResponse, 20 | } from './types'; 21 | 22 | export class Market { 23 | #client: CoinExClient; 24 | 25 | constructor(client: CoinExClient) { 26 | this.#client = client; 27 | } 28 | 29 | /** 30 | * Get Market Status 31 | * 32 | * @param params - The parameters for the request. 33 | * @param options - The options for the request. 34 | * @returns {Promise} The market status. 35 | * @see https://docs.coinex.com/api/v2/spot/market/http/list-market 36 | */ 37 | listMarket( 38 | params: SpotListMarketParams = {}, 39 | options: RequestOptions = {} 40 | ): Promise { 41 | return this.#client.request( 42 | 'spot/market', 43 | deepmerge( 44 | { 45 | method: 'GET', 46 | searchParams: noUndefined(params), 47 | context: { 48 | public: true, 49 | }, 50 | }, 51 | options 52 | ) 53 | ); 54 | } 55 | 56 | /** 57 | * Get Market Information 58 | * 59 | * @param params - The parameters for the request. 60 | * @param options - The options for the request. 61 | * @returns {Promise} The market ticker information. 62 | * @see https://docs.coinex.com/api/v2/spot/market/http/list-market-ticker 63 | */ 64 | listMarketTicker( 65 | params: SpotListMarketTickerParams = {}, 66 | options: RequestOptions = {} 67 | ): Promise { 68 | return this.#client.request( 69 | 'spot/ticker', 70 | deepmerge( 71 | { 72 | method: 'GET', 73 | searchParams: noUndefined(params), 74 | context: { 75 | public: true, 76 | }, 77 | }, 78 | options 79 | ) 80 | ); 81 | } 82 | 83 | /** 84 | * Get Market Depth 85 | * 86 | * @param params - The parameters for the request. 87 | * @param options - The options for the request. 88 | * @returns {Promise} The market depth information. 89 | * @see https://docs.coinex.com/api/v2/spot/market/http/list-market-depth 90 | */ 91 | listMarketDepth( 92 | params: SpotListMarketDepthParams, 93 | options: RequestOptions = {} 94 | ): Promise { 95 | return this.#client.request( 96 | 'spot/depth', 97 | deepmerge( 98 | { 99 | method: 'GET', 100 | searchParams: noUndefined(params), 101 | context: { 102 | public: true, 103 | }, 104 | }, 105 | options 106 | ) 107 | ); 108 | } 109 | 110 | /** 111 | * Get Market Candlestick 112 | * 113 | * @param params - The parameters for the request. 114 | * @param options - The options for the request. 115 | * @returns {Promise} The market candlestick data. 116 | * @see https://docs.coinex.com/api/v2/spot/market/http/list-market-kline 117 | */ 118 | listMarketKline( 119 | params: SpotListMarketKlineParams, 120 | options: RequestOptions = {} 121 | ): Promise { 122 | return this.#client.request( 123 | 'spot/kline', 124 | deepmerge( 125 | { 126 | method: 'GET', 127 | searchParams: noUndefined(params), 128 | context: { 129 | public: true, 130 | }, 131 | }, 132 | options 133 | ) 134 | ); 135 | } 136 | 137 | /** 138 | * Get Market Transactions 139 | * 140 | * @param params - The parameters for the request. 141 | * @param options - The options for the request. 142 | * @returns {Promise} The market transactions. 143 | * @see https://docs.coinex.com/api/v2/spot/market/http/list-market-deals 144 | */ 145 | listMarketDeals( 146 | params: SpotListMarketDealsParams, 147 | options: RequestOptions = {} 148 | ): Promise { 149 | return this.#client.request( 150 | 'spot/deals', 151 | deepmerge( 152 | { 153 | method: 'GET', 154 | searchParams: noUndefined(params), 155 | context: { 156 | public: true, 157 | }, 158 | }, 159 | options 160 | ) 161 | ); 162 | } 163 | 164 | /** 165 | * Get Market Index 166 | * 167 | * @param params - The parameters for the request. 168 | * @param options - The options for the request. 169 | * @returns {Promise} The market index information. 170 | * @see https://docs.coinex.com/api/v2/spot/market/http/list-market-index 171 | */ 172 | listMarketIndex( 173 | params: SpotListMarketIndexParams = {}, 174 | options: RequestOptions = {} 175 | ): Promise { 176 | return this.#client.request( 177 | 'spot/index', 178 | deepmerge( 179 | { 180 | method: 'GET', 181 | searchParams: noUndefined(params), 182 | context: { 183 | public: true, 184 | }, 185 | }, 186 | options 187 | ) 188 | ); 189 | } 190 | } 191 | -------------------------------------------------------------------------------- /packages/websocket/src/lib/websocket.ts: -------------------------------------------------------------------------------- 1 | import EventEmitter from 'node:events'; 2 | import { gunzipSync } from 'node:zlib'; 3 | import WebSocket from 'ws'; 4 | 5 | import { signWebSocketRequest } from '@/lib/crypto'; 6 | import { CoinExWebSocketError } from '@/lib/errors'; 7 | import type { CoinExWebSocketOptions, WebSocketRequest, WebSocketResponse } from '@/types'; 8 | 9 | interface AuthenticatedWebSocketOptions 10 | extends Pick { 11 | baseUrl: string; 12 | } 13 | 14 | export class AuthenticatedWebSocket extends EventEmitter { 15 | #ws: WebSocket | undefined; 16 | 17 | readonly #apiKey: string; 18 | readonly #secretKey: string; 19 | readonly #baseUrl: string; 20 | readonly #autoReconnect: boolean; 21 | 22 | #pingInterval: NodeJS.Timeout | undefined; 23 | #authRequestId: number | null = null; 24 | #isAuthenticated: boolean = false; 25 | #serverTime: number | undefined; 26 | #timeRequestId: number | null = null; 27 | #messageId = 0; 28 | #explicitlyClosed = false; 29 | 30 | constructor(options: AuthenticatedWebSocketOptions) { 31 | super(); 32 | this.#apiKey = options.apiKey; 33 | this.#secretKey = options.secretKey; 34 | this.#baseUrl = options.baseUrl; 35 | this.#autoReconnect = options.autoReconnect ?? true; 36 | } 37 | 38 | public connect() { 39 | if (this.#ws) { 40 | return; 41 | } 42 | this.#explicitlyClosed = false; 43 | this.#connect(); 44 | } 45 | 46 | public close() { 47 | this.#explicitlyClosed = true; 48 | if (this.#ws) { 49 | this.#ws.close(); 50 | this.#ws = undefined; 51 | } 52 | this.#stopPing(); 53 | } 54 | 55 | #connect() { 56 | this.#ws = new WebSocket(this.#baseUrl); 57 | this.#ws.binaryType = 'nodebuffer'; 58 | 59 | this.#ws.on('open', () => { 60 | this.#timeRequestId = this.#send({ method: 'server.time', params: {} }); 61 | }); 62 | 63 | this.#ws.on('message', (data: Buffer) => { 64 | const decompressed = gunzipSync(data); 65 | const message: WebSocketResponse = JSON.parse(decompressed.toString()); 66 | 67 | if (message.id === this.#timeRequestId && 'timestamp' in message.data) { 68 | this.#timeRequestId = null; 69 | this.#serverTime = Date.now() - parseInt(message.data.timestamp, 10); 70 | this.#authenticate(); 71 | return; 72 | } 73 | 74 | if (this.#authRequestId && message.id === this.#authRequestId) { 75 | this.#authRequestId = null; 76 | if (message.code === 0) { 77 | this.#isAuthenticated = true; 78 | this.emit('open'); 79 | this.#startPing(); 80 | } else { 81 | this.emit('error', new CoinExWebSocketError(message.code, message.message)); 82 | this.#ws?.close(); 83 | } 84 | return; 85 | } 86 | 87 | this.emit('message', message); 88 | 89 | if (message.method) { 90 | this.emit(message.method, message.data); 91 | } 92 | }); 93 | 94 | this.#ws.on('close', () => { 95 | this.emit('close'); 96 | this.#reset(); 97 | this.#stopPing(); 98 | if (!this.#explicitlyClosed && this.#autoReconnect) { 99 | setTimeout(() => this.#connect(), 1000); 100 | } 101 | }); 102 | 103 | this.#ws.on('error', (error) => { 104 | this.emit('error', error); 105 | }); 106 | } 107 | 108 | #reset() { 109 | this.#authRequestId = null; 110 | this.#isAuthenticated = false; 111 | this.#messageId = 0; 112 | } 113 | 114 | #startPing() { 115 | this.#pingInterval = setInterval(async () => { 116 | this.send({ method: 'server.ping', params: {} }); 117 | }, 10000); 118 | } 119 | 120 | #stopPing() { 121 | if (this.#pingInterval) { 122 | clearInterval(this.#pingInterval); 123 | this.#pingInterval = undefined; 124 | } 125 | } 126 | 127 | #authenticate() { 128 | const timestamp = Math.floor((Date.now() - this.#serverTime!) / 1000) * 1000; 129 | const signature = signWebSocketRequest(timestamp, this.#secretKey); 130 | 131 | this.#authRequestId = this.#send({ 132 | method: 'server.sign', 133 | params: { 134 | access_id: this.#apiKey, 135 | signed_str: signature, 136 | timestamp, 137 | }, 138 | }); 139 | } 140 | 141 | #send(payload: Omit, 'id'>): number { 142 | if (this.#ws?.readyState === WebSocket.OPEN) { 143 | const id = ++this.#messageId; 144 | const message = { ...payload, id }; 145 | this.#ws.send(JSON.stringify(message)); 146 | return id; 147 | } 148 | return -1; 149 | } 150 | 151 | send(payload: Omit, 'id'>): number { 152 | if (!this.isConnected()) { 153 | this.once('open', () => this.#send(payload)); 154 | return -1; 155 | } 156 | return this.#send(payload); 157 | } 158 | 159 | public async sendAndCapture( 160 | payload: Omit, 'id'>, 161 | timeout = 10000 162 | ): Promise> { 163 | const id = this.send(payload); 164 | 165 | return new Promise((resolve, reject) => { 166 | let timeoutId: NodeJS.Timeout | undefined = undefined; 167 | 168 | const onMessage = (message: WebSocketResponse) => { 169 | if (message.id === id) { 170 | clearTimeout(timeoutId); 171 | this.removeListener('message', onMessage); 172 | if (message.code === 0) { 173 | resolve(message as WebSocketResponse); 174 | } else { 175 | reject(new CoinExWebSocketError(message.code, message.message)); 176 | } 177 | } 178 | }; 179 | 180 | this.on('message', onMessage); 181 | 182 | timeoutId = setTimeout(() => { 183 | this.removeListener('message', onMessage); 184 | reject(new Error(`Request with id ${id} timed out after ${timeout}ms`)); 185 | }, timeout); 186 | }); 187 | } 188 | 189 | public sendAndListen( 190 | payload: Omit, 'id'>, 191 | listenMethod: string, 192 | onUpdate: (update: U) => void 193 | ): number { 194 | const id = this.send(payload); 195 | this.on('message', (message: WebSocketResponse) => { 196 | if (message.method === listenMethod) { 197 | onUpdate(message.data as U); 198 | } 199 | }); 200 | return id; 201 | } 202 | 203 | public isConnected(): boolean { 204 | return this.#ws?.readyState === WebSocket.OPEN && this.#isAuthenticated; 205 | } 206 | } 207 | -------------------------------------------------------------------------------- /packages/coinex/src/modules/futures/position/module.ts: -------------------------------------------------------------------------------- 1 | import deepmerge from 'deepmerge'; 2 | 3 | import { type CoinExClient } from '@/client'; 4 | import { noUndefined } from '@/lib/object'; 5 | import type { RequestOptions } from '@/types'; 6 | 7 | import type { 8 | AdjustPositionLeverageParams, 9 | AdjustPositionMarginParams, 10 | ClosePositionParams, 11 | ListFinishedPositionParams, 12 | ListFinishedPositionResponse, 13 | ListPendingPositionParams, 14 | ListPendingPositionResponse, 15 | ListPositionAdlHistoryParams, 16 | ListPositionAdlHistoryResponse, 17 | ListPositionFundingHistoryParams, 18 | ListPositionFundingHistoryResponse, 19 | ListPositionMarginHistoryParams, 20 | ListPositionMarginHistoryResponse, 21 | ListPositionSettleHistoryParams, 22 | ListPositionSettleHistoryResponse, 23 | SetPositionStopLossParams, 24 | SetPositionTakeProfitParams, 25 | } from './types'; 26 | 27 | export class Position { 28 | #client: CoinExClient; 29 | 30 | constructor(client: CoinExClient) { 31 | this.#client = client; 32 | } 33 | 34 | /** 35 | * Adjust Position Leverage 36 | * @see https://docs.coinex.com/api/v2/futures/position/http/adjust-position-leverage 37 | */ 38 | adjustPositionLeverage( 39 | params: AdjustPositionLeverageParams, 40 | options: RequestOptions = {} 41 | ): Promise<{}> { 42 | return this.#client.request( 43 | 'futures/adjust-position-leverage', 44 | deepmerge({ method: 'POST', json: noUndefined(params) }, options) 45 | ); 46 | } 47 | 48 | /** 49 | * Adjust Position Margin 50 | * @see https://docs.coinex.com/api/v2/futures/position/http/adjust-position-margin 51 | */ 52 | adjustPositionMargin( 53 | params: AdjustPositionMarginParams, 54 | options: RequestOptions = {} 55 | ): Promise<{}> { 56 | return this.#client.request( 57 | 'futures/adjust-position-margin', 58 | deepmerge({ method: 'POST', json: noUndefined(params) }, options) 59 | ); 60 | } 61 | 62 | /** 63 | * Close Position 64 | * @see https://docs.coinex.com/api/v2/futures/position/http/close-position 65 | */ 66 | closePosition(params: ClosePositionParams, options: RequestOptions = {}): Promise<{}> { 67 | return this.#client.request( 68 | 'futures/close-position', 69 | deepmerge({ method: 'POST', json: noUndefined(params) }, options) 70 | ); 71 | } 72 | 73 | /** 74 | * Get Historical Position 75 | * @see https://docs.coinex.com/api/v2/futures/position/http/list-finished-position 76 | */ 77 | listFinishedPosition( 78 | params: ListFinishedPositionParams, 79 | options: RequestOptions = {} 80 | ): Promise { 81 | return this.#client.request( 82 | 'futures/finished-position', 83 | deepmerge({ method: 'GET', searchParams: noUndefined(params) }, options) 84 | ); 85 | } 86 | 87 | /** 88 | * Get Current Position 89 | * @see https://docs.coinex.com/api/v2/futures/position/http/list-pending-position 90 | */ 91 | listPendingPosition( 92 | params: ListPendingPositionParams, 93 | options: RequestOptions = {} 94 | ): Promise { 95 | return this.#client.request( 96 | 'futures/pending-position', 97 | deepmerge({ method: 'GET', searchParams: noUndefined(params) }, options) 98 | ); 99 | } 100 | 101 | /** 102 | * Get Position Auto Deleverage History 103 | * @see https://docs.coinex.com/api/v2/futures/position/http/list-positiing-adl-history 104 | */ 105 | listPositionAdlHistory( 106 | params: ListPositionAdlHistoryParams, 107 | options: RequestOptions = {} 108 | ): Promise { 109 | return this.#client.request( 110 | 'futures/adl-history', 111 | deepmerge({ method: 'GET', searchParams: noUndefined(params) }, options) 112 | ); 113 | } 114 | 115 | /** 116 | * Get Position Funding Rate History 117 | * @see https://docs.coinex.com/api/v2/futures/position/http/list-position-funding-history 118 | */ 119 | listPositionFundingHistory( 120 | params: ListPositionFundingHistoryParams, 121 | options: RequestOptions = {} 122 | ): Promise { 123 | return this.#client.request( 124 | 'futures/position-funding-history', 125 | deepmerge({ method: 'GET', searchParams: noUndefined(params) }, options) 126 | ); 127 | } 128 | 129 | /** 130 | * Get Position Margin Change History 131 | * @see https://docs.coinex.com/api/v2/futures/position/http/list-position-margin-history 132 | */ 133 | listPositionMarginHistory( 134 | params: ListPositionMarginHistoryParams, 135 | options: RequestOptions = {} 136 | ): Promise { 137 | return this.#client.request( 138 | 'futures/position-margin-history', 139 | deepmerge({ method: 'GET', searchParams: noUndefined(params) }, options) 140 | ); 141 | } 142 | 143 | /** 144 | * Get Position Auto Settlement History 145 | * @see https://docs.coinex.com/api/v2/futures/position/http/list-position-settle-history 146 | */ 147 | listPositionSettleHistory( 148 | params: ListPositionSettleHistoryParams, 149 | options: RequestOptions = {} 150 | ): Promise { 151 | return this.#client.request( 152 | 'futures/position-settle-history', 153 | deepmerge({ method: 'GET', searchParams: noUndefined(params) }, options) 154 | ); 155 | } 156 | 157 | /** 158 | * Set Position Stop Loss 159 | * @see https://docs.coinex.com/api/v2/futures/position/http/set-position-stop-loss 160 | */ 161 | setPositionStopLoss( 162 | params: SetPositionStopLossParams, 163 | options: RequestOptions = {} 164 | ): Promise<{}> { 165 | return this.#client.request( 166 | 'futures/position-stop-loss', 167 | deepmerge({ method: 'POST', json: noUndefined(params) }, options) 168 | ); 169 | } 170 | 171 | /** 172 | * Set Position Take Profit 173 | * @description 174 | * **Info:** 175 | * - This endpoint will trigger rate limit. 176 | * 177 | * @param params - The parameters for the request. 178 | * @param options - The options for the request. 179 | * @returns {Promise<{}>} An empty object on success. 180 | * @see https://docs.coinex.com/api/v2/futures/position/http/set-position-take-profit 181 | */ 182 | setPositionTakeProfit( 183 | params: SetPositionTakeProfitParams, 184 | options: RequestOptions = {} 185 | ): Promise<{}> { 186 | return this.#client.request( 187 | 'futures/position-take-profit', 188 | deepmerge({ method: 'POST', json: noUndefined(params) }, options) 189 | ); 190 | } 191 | } 192 | -------------------------------------------------------------------------------- /internal/shared/src/enums.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * @enum MarketType 3 | * @description Enumeration of market types. 4 | */ 5 | export enum MarketType { 6 | SPOT = 'SPOT', 7 | MARGIN = 'MARGIN', 8 | FUTURES = 'FUTURES', 9 | } 10 | 11 | /** 12 | * @enum MarketStatus 13 | * @description Enumeration of market statuses. 14 | */ 15 | export enum MarketStatus { 16 | BIDDING = 'bidding', 17 | COUNTING_DOWN = 'counting_down', 18 | ONLINE = 'online', 19 | } 20 | 21 | /** 22 | * @enum OrderSide 23 | * @description Enumeration of order sides. 24 | */ 25 | export enum OrderSide { 26 | BUY = 'buy', 27 | SELL = 'sell', 28 | } 29 | 30 | /** 31 | * @enum OrderType 32 | * @description Enumeration of order types. 33 | */ 34 | export enum OrderType { 35 | LIMIT = 'limit', 36 | MARKET = 'market', 37 | MAKER_ONLY = 'maker_only', 38 | IOC = 'ioc', 39 | FOK = 'fok', 40 | } 41 | 42 | /** 43 | * @enum StpMode 44 | * @description Enumeration of STP (Self-Trade Prevention) modes. 45 | */ 46 | export enum StpMode { 47 | CANCEL_TAKER = 'ct', 48 | CANCEL_MAKER = 'cm', 49 | CANCEL_BOTH = 'both', 50 | } 51 | 52 | /** 53 | * @enum OrderEvent 54 | * @description Enumeration of order events. 55 | */ 56 | export enum OrderEvent { 57 | PUT = 'put', 58 | UPDATE = 'update', 59 | MODIFY = 'modify', 60 | FINISH = 'finish', 61 | } 62 | 63 | /** 64 | * @enum StopOrderEvent 65 | * @description Enumeration of stop order events. 66 | */ 67 | export enum StopOrderEvent { 68 | PUT = 'put', 69 | ACTIVE = 'active', 70 | CANCEL = 'cancel', 71 | } 72 | 73 | /** 74 | * @enum StopOrderStatus 75 | * @description Enumeration of stop order statuses. 76 | */ 77 | export enum StopOrderStatus { 78 | PUT = 'put', 79 | ACTIVE_SUCCESS = 'active_success', 80 | ACTIVE_FAIL = 'active_fail', 81 | CANCEL = 'cancel', 82 | } 83 | 84 | /** 85 | * @enum TriggerDirection 86 | * @description Enumeration of trigger directions. 87 | */ 88 | export enum TriggerDirection { 89 | HIGHER = 'higher', 90 | LOWER = 'lower', 91 | } 92 | 93 | /** 94 | * @enum PositionEvent 95 | * @description Enumeration of position events. 96 | */ 97 | export enum PositionEvent { 98 | UPDATE = 'update', 99 | CLOSE = 'close', 100 | SYS_CLOSE = 'sys_close', 101 | ADL = 'adl', 102 | LIQ = 'liq', 103 | } 104 | 105 | /** 106 | * @enum Locale 107 | * @description Enumeration of supported locales. 108 | */ 109 | export enum Locale { 110 | DE_DE = 'de-DE', 111 | EN_US = 'en-US', 112 | ES_AR = 'es-AR', 113 | ES_ES = 'es-ES', 114 | ES_MX = 'es-MX', 115 | FR_FR = 'fr-FR', 116 | KK_KZ = 'kk-KZ', 117 | ID_ID = 'id-ID', 118 | UK_UA = 'uk-UA', 119 | JA_JP = 'ja-JP', 120 | RU_RU = 'ru-RU', 121 | TH_TH = 'th-TH', 122 | PT_BR = 'pt-BR', 123 | TR_TR = 'tr-TR', 124 | VI_VN = 'vi-VN', 125 | ZH_TW = 'zh-TW', 126 | AR_SA = 'ar-SA', 127 | HI_IN = 'hi-IN', 128 | FIL_PH = 'fil-PH', 129 | } 130 | 131 | /** 132 | * @enum Permission 133 | * @description Enumeration of sub-account permissions. 134 | */ 135 | export enum Permission { 136 | FUTURES = 'FUTURES', 137 | MARGIN = 'MARGIN', 138 | AMM = 'AMM', 139 | API = 'API', 140 | } 141 | 142 | /** 143 | * @enum TransferDirection 144 | * @description Enumeration of transfer directions. 145 | */ 146 | export enum TransferDirection { 147 | IN = 'in', 148 | OUT = 'out', 149 | } 150 | 151 | /** 152 | * @enum TransferStatus 153 | * @description Enumeration of transfer statuses. 154 | */ 155 | export enum TransferStatus { 156 | CREATED = 'created', 157 | DEDUCTED = 'deducted', 158 | FAILED = 'failed', 159 | FINISHED = 'finished', 160 | } 161 | 162 | /** 163 | * @enum LoanStatus 164 | * @description Enumeration of loan statuses. 165 | */ 166 | export enum LoanStatus { 167 | LOAN = 'loan', 168 | DEBT = 'debt', 169 | LIQUIDATED = 'liquidated', 170 | FINISH = 'finish', 171 | } 172 | 173 | /** 174 | * @enum DepositStatus 175 | * @description Enumeration of deposit statuses. 176 | */ 177 | export enum DepositStatus { 178 | PROCESSING = 'processing', 179 | CONFIRMING = 'confirming', 180 | CANCELLED = 'cancelled', 181 | FINISHED = 'finished', 182 | TOO_SMALL = 'too_small', 183 | EXCEPTION = 'exception', 184 | } 185 | 186 | /** 187 | * @enum WithdrawStatus 188 | * @description Enumeration of withdrawal statuses. 189 | */ 190 | export enum WithdrawStatus { 191 | CREATED = 'created', 192 | AUDIT_REQUIRED = 'audit_required', 193 | AUDITED = 'audited', 194 | PROCESSING = 'processing', 195 | CONFIRMING = 'confirming', 196 | FINISHED = 'finished', 197 | CANCELLED = 'cancelled', 198 | CANCELLATION_FAILED = 'cancellation_failed', 199 | FAILED = 'failed', 200 | } 201 | 202 | /** 203 | * @enum OrderStatus 204 | * @description Enumeration of order statuses. 205 | */ 206 | export enum OrderStatus { 207 | OPEN = 'open', 208 | PART_FILLED = 'part_filled', 209 | FILLED = 'filled', 210 | PART_CANCELED = 'part_canceled', 211 | CANCELED = 'canceled', 212 | } 213 | 214 | /** 215 | * @enum ContractType 216 | * @description Enumeration of contract types. 217 | */ 218 | export enum ContractType { 219 | LINEAR = 'linear', 220 | INVERSE = 'inverse', 221 | } 222 | 223 | /** 224 | * @enum MarginMode 225 | * @description Enumeration of margin modes. 226 | */ 227 | export enum MarginMode { 228 | ISOLATED = 'isolated', 229 | CROSS = 'cross', 230 | } 231 | 232 | /** 233 | * @enum TakeProfitType 234 | * @description Enumeration of take profit types. 235 | */ 236 | export enum TakeProfitType { 237 | LATEST_PRICE = 'latest_price', 238 | MARK_PRICE = 'mark_price', 239 | } 240 | 241 | /** 242 | * @enum StopLossType 243 | * @description Enumeration of stop loss types. 244 | */ 245 | export enum StopLossType { 246 | LATEST_PRICE = 'latest_price', 247 | MARK_PRICE = 'mark_price', 248 | } 249 | 250 | /** 251 | * @enum PositionSide 252 | * @description Enumeration of position sides. 253 | */ 254 | export enum PositionSide { 255 | SHORT = 'short', 256 | LONG = 'long', 257 | } 258 | 259 | /** 260 | * @enum PositionFinishedType 261 | * @description Enumeration of position finished types. 262 | */ 263 | export enum PositionFinishedType { 264 | LIQ = 'liq', 265 | ADL = 'adl', 266 | SYS = 'sys', 267 | LIMIT = 'limit', 268 | MARKET = 'market', 269 | MARKET_CLOSE_ALL = 'market_close_all', 270 | TAKE_PROFIT = 'take_profit', 271 | STOP_LOSS = 'stop_loss', 272 | } 273 | 274 | /** 275 | * @enum TriggerPriceType 276 | * @description Enumeration of trigger price types. 277 | */ 278 | export enum TriggerPriceType { 279 | LATEST_PRICE = 'latest_price', 280 | MARK_PRICE = 'mark_price', 281 | INDEX_PRICE = 'index_price', 282 | } 283 | 284 | /** 285 | * @enum TransactionType 286 | * @description Enumeration of transaction types. 287 | */ 288 | export enum TransactionType { 289 | DEPOSIT = 'deposit', 290 | WITHDRAW = 'withdraw', 291 | TRADE = 'trade', 292 | MAKER_CASH_BACK = 'maker_cash_back', 293 | } 294 | 295 | /** 296 | * @enum AmmType 297 | * @description Enumeration of AMM types. 298 | */ 299 | export enum AmmType { 300 | INFINITE = 'infinite', 301 | FINITE = 'finite', 302 | } 303 | 304 | /** 305 | * @enum UserType 306 | * @description Enumeration of user types. 307 | */ 308 | export enum UserType { 309 | NORMAL = 'NORMAL', 310 | SUB_ACCOUNT = 'SUB_ACCOUNT', 311 | } 312 | --------------------------------------------------------------------------------