Skip to content

Commit

Permalink
Merge pull request #1 from canccevik/refactor
Browse files Browse the repository at this point in the history
Refactor codebase
  • Loading branch information
tolgaand committed Mar 19, 2024
2 parents dc39f47 + 7ca0f0d commit 95052a7
Show file tree
Hide file tree
Showing 16 changed files with 315 additions and 172 deletions.
16 changes: 16 additions & 0 deletions .eslintrc.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
{
"env": {
"es2021": true,
"node": true
},
"extends": ["eslint:recommended", "plugin:@typescript-eslint/recommended"],
"parser": "@typescript-eslint/parser",
"parserOptions": {
"ecmaVersion": "latest",
"sourceType": "module"
},
"plugins": ["@typescript-eslint"],
"rules": {
"@typescript-eslint/no-explicit-any": "off"
}
}
20 changes: 20 additions & 0 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
name: Run tests

on: [push, pull_request]

jobs:
build:
runs-on: ubuntu-latest

strategy:
matrix:
node-version: [20.x]

steps:
- uses: actions/checkout@v3
- name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v3
with:
node-version: ${{ matrix.node-version }}
- run: yarn install
- run: yarn test
7 changes: 7 additions & 0 deletions .prettierrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"singleQuote": false,
"semi": true,
"trailingComma": "es5",
"tabWidth": 2,
"printWidth": 100
}
6 changes: 3 additions & 3 deletions jest.config.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/** @type {import('ts-jest').JestConfigWithTsJest} */
module.exports = {
preset: 'ts-jest',
testEnvironment: 'node',
};
preset: "ts-jest",
testEnvironment: "node",
};
9 changes: 8 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,10 @@
"types": "dist/index.d.ts",
"scripts": {
"build": "tsc",
"test": "jest"
"test": "jest",
"lint": "eslint --ext .js,.ts",
"lint:fix": "eslint --fix --ext .js,.ts",
"format": "prettier --ignore-path .gitignore --write \"**/*.+(js|ts|json)\""
},
"repository": {
"type": "git",
Expand All @@ -31,7 +34,11 @@
"devDependencies": {
"@types/jest": "^29.5.12",
"@types/node": "^20.11.28",
"@typescript-eslint/eslint-plugin": "^7.3.0",
"@typescript-eslint/parser": "^7.3.0",
"eslint": "^8.57.0",
"jest": "^29.7.0",
"prettier": "^3.2.5",
"ts-jest": "^29.1.2",
"typescript": "^5.4.2"
}
Expand Down
166 changes: 64 additions & 102 deletions src/authenticated-api.ts
Original file line number Diff line number Diff line change
@@ -1,61 +1,53 @@
import { APICommunication } from "./utils/api-communication";
import { APIClient } from "./utils/api-client";
import { Cryptography } from "./utils/cryptography";
import {
Balance,
Deposit,
Withdrawal,
DepositAddress,
Order,
Fill,
} from "./types";
import { Balance, Deposit, Withdrawal, DepositAddress, Order, Fill } from "./types";
import { AUTHENTICATED_ENDPOINTS } from "./constants/authenticated-endpoints";
import { INSTRUCTIONS } from "./constants/instructions";
import { HttpMethod } from "./constants";

export class AuthenticatedAPI {
private apiCommunication: APICommunication;
private apiClient: APIClient;

constructor(params: { apiKey: string; secretKey: string }) {
const { apiKey, secretKey } = params;

if (!apiKey || !secretKey)
throw new Error("API Key and Secret Key are required");
if (!apiKey || !secretKey) throw new Error("API Key and Secret Key are required");

const cryptography = new Cryptography(apiKey, secretKey);
this.apiCommunication = new APICommunication(cryptography);
this.apiClient = new APIClient(cryptography);
}

async getBalances(): Promise<Record<string, Balance>> {
return this.apiCommunication.sendRequest("GET", "/api/v1/capital", {
instruction: "balanceQuery",
return this.apiClient.sendRequest(HttpMethod.GET, AUTHENTICATED_ENDPOINTS.CAPITAL, {
instruction: INSTRUCTIONS.BALANCE_QUERY,
});
}

async getDeposits({
limit = 100,
offset = 0,
}: { limit?: number; offset?: number } = {}): Promise<Deposit[]> {
return this.apiCommunication.sendRequest(
"GET",
`/wapi/v1/capital/deposits?limit=${limit}&offset=${offset}`,
{ instruction: "depositQueryAll" }
async getDeposits({ limit = 100, offset = 0 }: { limit?: number; offset?: number } = {}): Promise<
Deposit[]
> {
return this.apiClient.sendRequest(
HttpMethod.GET,
AUTHENTICATED_ENDPOINTS.DEPOSITS(limit, offset),
{ instruction: INSTRUCTIONS.DEPOSIT_QUERY_ALL }
);
}

async getDepositAddress(blockchain: string): Promise<DepositAddress> {
return this.apiCommunication.sendRequest(
"GET",
`/wapi/v1/capital/deposit/address?blockchain=${blockchain}`,
{ instruction: "depositAddressQuery" }
return this.apiClient.sendRequest(
HttpMethod.GET,
AUTHENTICATED_ENDPOINTS.DEPOSIT_ADDRESS(blockchain),
{ instruction: INSTRUCTIONS.DEPOSIT_ADDRESS_QUERY }
);
}

async getWithdrawals(
params: { limit?: number; offset?: number } = {}
): Promise<Withdrawal[]> {
async getWithdrawals(params: { limit?: number; offset?: number } = {}): Promise<Withdrawal[]> {
const { limit = 100, offset = 0 } = params;
return this.apiCommunication.sendRequest(
"GET",
`/wapi/v1/capital/withdrawals?limit=${limit}&offset=${offset}`,
return this.apiClient.sendRequest(
HttpMethod.GET,
AUTHENTICATED_ENDPOINTS.WITHDRAWALS(limit, offset),
{
instruction: "withdrawalQueryAll",
instruction: INSTRUCTIONS.WITHDRAWAL_QUERY_ALL,
}
);
}
Expand All @@ -68,8 +60,7 @@ export class AuthenticatedAPI {
clientId?: number;
twoFactorToken?: string;
}): Promise<Withdrawal> {
const { address, blockchain, quantity, symbol, clientId, twoFactorToken } =
params;
const { address, blockchain, quantity, symbol, clientId, twoFactorToken } = params;

const body = {
address,
Expand All @@ -79,42 +70,34 @@ export class AuthenticatedAPI {
clientId,
twoFactorToken,
};
return this.apiCommunication.sendRequest(
"POST",
"/wapi/v1/capital/withdrawals",
{
...body,
instruction: "withdraw",
}
);
return this.apiClient.sendRequest(HttpMethod.POST, AUTHENTICATED_ENDPOINTS.WITHDRAWALS(), {
...body,
instruction: INSTRUCTIONS.WITHDRAW,
});
}

async getOrderHistory(
params: { limit?: number; offset?: number; symbol?: string } = {}
): Promise<Order[]> {
const { limit = 100, offset = 0, symbol } = params;

let endpoint = `/wapi/v1/history/orders?limit=${limit}&offset=${offset}`;
if (symbol) {
endpoint += `&symbol=${symbol}`;
}
return this.apiCommunication.sendRequest("GET", endpoint, {
instruction: "orderHistoryQueryAll",
});
return this.apiClient.sendRequest(
HttpMethod.GET,
AUTHENTICATED_ENDPOINTS.ORDER_HISTORY(limit, offset, symbol),
{
instruction: INSTRUCTIONS.ORDER_HISTORY_QUERY_ALL,
}
);
}

async getFillHistory(
symbol?: string,
limit: number = 100,
offset: number = 0
): Promise<Fill[]> {
let endpoint = `/wapi/v1/history/fills?limit=${limit}&offset=${offset}`;
if (symbol) {
endpoint += `&symbol=${symbol}`;
}
return this.apiCommunication.sendRequest("GET", endpoint, {
instruction: "fillHistoryQueryAll",
});
async getFillHistory(symbol?: string, limit: number = 100, offset: number = 0): Promise<Fill[]> {
return this.apiClient.sendRequest(
HttpMethod.GET,
AUTHENTICATED_ENDPOINTS.FILL_HISTORY(limit, offset, symbol),
{
instruction: INSTRUCTIONS.FILL_HISTORY_QUERY_ALL,
}
);
}

async executeOrder({
Expand All @@ -136,12 +119,7 @@ export class AuthenticatedAPI {
price: number;
quantity: number;
quoteQuantity?: string;
selfTradePrevention?:
| string
| "RejectTaker"
| "RejectMaker"
| "RejectBoth"
| "Allow";
selfTradePrevention?: string | "RejectTaker" | "RejectMaker" | "RejectBoth" | "Allow";
side: string | "Bid" | "Ask";
symbol: string;
timeInForce?: string;
Expand All @@ -160,9 +138,9 @@ export class AuthenticatedAPI {
timeInForce,
triggerPrice,
};
return this.apiCommunication.sendRequest("POST", "/api/v1/order", {
return this.apiClient.sendRequest(HttpMethod.POST, AUTHENTICATED_ENDPOINTS.ORDER(), {
...body,
instruction: "orderExecute",
instruction: INSTRUCTIONS.ORDER_EXECUTE,
});
}

Expand All @@ -175,49 +153,33 @@ export class AuthenticatedAPI {
clientId?: string;
symbol: string;
}): Promise<Order> {
let endpoint = `/api/v1/order?`;
if (orderId) {
endpoint += `orderId=${orderId}`;
} else if (clientId) {
endpoint += `clientId=${clientId}`;
}
if (symbol) {
endpoint += `&symbol=${symbol}`;
}
return this.apiCommunication.sendRequest("GET", endpoint, {
instruction: "orderQuery",
});
return this.apiClient.sendRequest(
HttpMethod.GET,
AUTHENTICATED_ENDPOINTS.ORDER(symbol, orderId, clientId),
{
instruction: INSTRUCTIONS.ORDER_QUERY,
}
);
}

async cancelOrder({
orderId,
symbol,
}: {
orderId: string;
symbol: string;
}): Promise<Order> {
async cancelOrder({ orderId, symbol }: { orderId: string; symbol: string }): Promise<Order> {
const body = { orderId, symbol };
return this.apiCommunication.sendRequest("DELETE", "/api/v1/order", {
return this.apiClient.sendRequest(HttpMethod.DELETE, AUTHENTICATED_ENDPOINTS.ORDER(), {
...body,
instruction: "orderCancel",
instruction: INSTRUCTIONS.ORDER_CANCEL,
});
}

async getOpenOrders(symbol?: string): Promise<Order[]> {
let endpoint = `/api/v1/orders`;
if (symbol) {
endpoint += `?symbol=${symbol}`;
}
return this.apiCommunication.sendRequest("GET", endpoint, {
instruction: "orderQueryAll",
return this.apiClient.sendRequest(HttpMethod.GET, AUTHENTICATED_ENDPOINTS.ORDERS(symbol), {
instruction: INSTRUCTIONS.ORDER_QUERY_ALL,
});
}

async cancelOpenOrders(symbol: string): Promise<string> {
const body = { symbol };
return this.apiCommunication.sendRequest("DELETE", "/api/v1/orders", {
...body,
instruction: "orderCancelAll",
return this.apiClient.sendRequest(HttpMethod.DELETE, AUTHENTICATED_ENDPOINTS.ORDERS(), {
symbol,
instruction: INSTRUCTIONS.ORDER_CANCEL_ALL,
});
}
}
53 changes: 53 additions & 0 deletions src/constants/authenticated-endpoints.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
import { BASE_URL } from ".";
import { buildUrl } from "../utils/build-url";

export const AUTHENTICATED_ENDPOINTS = {
CAPITAL: buildUrl({ endpoint: "/capital" }),

DEPOSITS: (limit: number, offset: number) =>
buildUrl({
endpoint: "/capital/deposits",
baseUrl: BASE_URL.WAPI,
params: { limit: limit.toString(), offset: offset.toString() },
}),

DEPOSIT_ADDRESS: (blockchain: string) =>
buildUrl({
endpoint: "/capital/deposit/address",
baseUrl: BASE_URL.WAPI,
params: { blockchain },
}),

WITHDRAWALS: (limit?: number, offset?: number) =>
buildUrl({
endpoint: "/capital/withdrawals",
baseUrl: BASE_URL.WAPI,
params: { limit: limit?.toString(), offset: offset?.toString() },
}),

ORDER_HISTORY: (limit: number, offset: number, symbol?: string) =>
buildUrl({
endpoint: "/history/orders",
baseUrl: BASE_URL.WAPI,
params: { symbol, limit: limit.toString(), offset: offset.toString() },
}),

FILL_HISTORY: (limit: number, offset: number, symbol?: string) =>
buildUrl({
endpoint: "/history/fills",
baseUrl: BASE_URL.WAPI,
params: { symbol, limit: limit.toString(), offset: offset.toString() },
}),

ORDER: (symbol?: string, orderId?: string, clientId?: string) =>
buildUrl({
endpoint: "/order",
params: { symbol, orderId, clientId },
}),

ORDERS: (symbol?: string) =>
buildUrl({
endpoint: "/orders",
params: { symbol },
}),
};
Loading

0 comments on commit 95052a7

Please sign in to comment.