@carbon-terminal/trading-sdk 0.2.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (48) hide show
  1. package/README.md +6 -0
  2. package/dist/client/index.d.ts +1 -0
  3. package/dist/client/index.js +17 -0
  4. package/dist/client/trading-sdk.d.ts +42 -0
  5. package/dist/client/trading-sdk.js +99 -0
  6. package/dist/client/types.d.ts +9 -0
  7. package/dist/client/types.js +18 -0
  8. package/dist/common/exceptions.d.ts +21 -0
  9. package/dist/common/exceptions.js +51 -0
  10. package/dist/common/index.d.ts +1 -0
  11. package/dist/common/index.js +17 -0
  12. package/dist/entities/account-entity.d.ts +6 -0
  13. package/dist/entities/account-entity.js +10 -0
  14. package/dist/entities/cancel-close-request.entity.d.ts +22 -0
  15. package/dist/entities/cancel-close-request.entity.js +54 -0
  16. package/dist/entities/cancel-request.entity.d.ts +22 -0
  17. package/dist/entities/cancel-request.entity.js +54 -0
  18. package/dist/entities/close-request.entity.d.ts +23 -0
  19. package/dist/entities/close-request.entity.js +63 -0
  20. package/dist/entities/index.d.ts +5 -0
  21. package/dist/entities/index.js +21 -0
  22. package/dist/entities/library/hookable-entity.d.ts +9 -0
  23. package/dist/entities/library/hookable-entity.js +20 -0
  24. package/dist/entities/position-entity.d.ts +29 -0
  25. package/dist/entities/position-entity.js +110 -0
  26. package/dist/index.d.ts +3 -0
  27. package/dist/index.js +19 -0
  28. package/dist/modules/account-manager/index.d.ts +9 -0
  29. package/dist/modules/account-manager/index.js +43 -0
  30. package/dist/modules/auth-manager/index.d.ts +44 -0
  31. package/dist/modules/auth-manager/index.js +188 -0
  32. package/dist/modules/auth-manager/types.d.ts +7 -0
  33. package/dist/modules/auth-manager/types.js +2 -0
  34. package/dist/modules/index.d.ts +0 -0
  35. package/dist/modules/index.js +0 -0
  36. package/dist/modules/markets-manager/index.d.ts +23 -0
  37. package/dist/modules/markets-manager/index.js +119 -0
  38. package/dist/modules/trade-manager/index.d.ts +52 -0
  39. package/dist/modules/trade-manager/index.js +157 -0
  40. package/dist/modules/trade-manager/types.d.ts +0 -0
  41. package/dist/modules/trade-manager/types.js +0 -0
  42. package/dist/utils/api/getApiUrl.d.ts +1 -0
  43. package/dist/utils/api/getApiUrl.js +8 -0
  44. package/dist/utils/auth/apiAuth.d.ts +5 -0
  45. package/dist/utils/auth/apiAuth.js +23 -0
  46. package/dist/utils/auth/siweAuth.d.ts +20 -0
  47. package/dist/utils/auth/siweAuth.js +106 -0
  48. package/package.json +47 -0
@@ -0,0 +1,157 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.TradeManager = void 0;
4
+ const core_1 = require("@carbon-terminal/core");
5
+ const exceptions_1 = require("../../common/exceptions");
6
+ const entities_1 = require("../../entities");
7
+ class TradeManager {
8
+ constructor(tradingSdk) {
9
+ this.tradingSdk = tradingSdk;
10
+ }
11
+ async getPositionInfo(positionId, chainId) {
12
+ const response = await this.tradingSdk.get(`/positions/open-request/status?positionId=${positionId}&chainId=${chainId}`);
13
+ if (!response.success) {
14
+ throw new exceptions_1.APIException({
15
+ message: response.error?.message,
16
+ code: response.error?.code,
17
+ httpStatusCode: response.httpStatusCode,
18
+ });
19
+ }
20
+ return response.data;
21
+ }
22
+ async getOpenPositionsForSubaccount(subaccountAddress, chainId) {
23
+ const response = await this.tradingSdk.get(`/positions/all?subaccountAddress=${subaccountAddress}&chainId=${chainId}`);
24
+ if (!response.success) {
25
+ throw new exceptions_1.APIException({
26
+ message: response.error?.message,
27
+ code: response.error?.code,
28
+ httpStatusCode: response.httpStatusCode,
29
+ });
30
+ }
31
+ return response.data;
32
+ }
33
+ async getCloseRequestInfo(closeRequestId, chainId) {
34
+ const response = await this.tradingSdk.get(`/positions/close-request/status?closeRequestId=${closeRequestId}&chainId=${chainId}`);
35
+ if (!response.success) {
36
+ throw new exceptions_1.APIException({
37
+ message: response.error?.message,
38
+ code: response.error?.code,
39
+ httpStatusCode: response.httpStatusCode,
40
+ });
41
+ }
42
+ return response.data;
43
+ }
44
+ async createPosition(params) {
45
+ let { marketId, subaccountAddress, chainId, positionType, orderType, limitPrice, quantity, deadline, slippage, leverage, solver, useInstantActions, } = params;
46
+ // Add parameter validation
47
+ const response = await this.tradingSdk.post("/trade/create-position", {
48
+ marketId,
49
+ subaccountAddress,
50
+ chainId,
51
+ positionType,
52
+ orderType,
53
+ limitPrice: orderType === core_1.OrderType.LIMIT ? limitPrice : null,
54
+ quantity,
55
+ leverage,
56
+ slippage: slippage ?? 0.01,
57
+ solver,
58
+ useInstantActions,
59
+ });
60
+ if (!response.success) {
61
+ throw new core_1.OpenPositionError(response.error.message, response.error.code);
62
+ }
63
+ const positionEntity = new entities_1.PositionEntity(this.tradingSdk, response.data);
64
+ return positionEntity;
65
+ }
66
+ // first version: only allowing market close
67
+ // todo: implement limit orders through the transaction relay
68
+ async closePosition(params) {
69
+ const response = await this.tradingSdk.post("/trade/close-position", {
70
+ quoteId: params.quoteId,
71
+ quantityToClose: params.quantityToClose,
72
+ chainId: params.chainId,
73
+ slippage: params.slippage,
74
+ orderType: params.orderType,
75
+ useInstantActions: params.useInstantActions,
76
+ });
77
+ return new entities_1.CloseRequestEntity(this.tradingSdk, response.data);
78
+ }
79
+ async setTpSlForPosition(params) {
80
+ const timestamp = Math.floor(Date.now() / 1000);
81
+ const deadline = timestamp + 500;
82
+ await this.tradingSdk.post("/tpsl/create", {
83
+ ...params,
84
+ timestamp,
85
+ deadline,
86
+ });
87
+ }
88
+ async listTpSlForPositions(chainId, quoteIds) {
89
+ const response = await this.tradingSdk.post("/tpsl/list", { chainId, quoteIds });
90
+ if (!response.success) {
91
+ throw new exceptions_1.APIException({
92
+ message: response.error?.message,
93
+ code: response.error?.code,
94
+ httpStatusCode: response.httpStatusCode,
95
+ });
96
+ }
97
+ return response.data;
98
+ }
99
+ async getLockedParameters(chainId, solver, marketName, leverage) {
100
+ const response = await this.tradingSdk.get(`/solvers/locked-parameters?chainId=${chainId}&solver=${solver}&marketName=${marketName}&leverage=${leverage}`);
101
+ if (!response.success) {
102
+ throw new exceptions_1.APIException({
103
+ message: response.error?.message,
104
+ code: response.error?.code,
105
+ httpStatusCode: response.httpStatusCode,
106
+ });
107
+ }
108
+ return response.data;
109
+ }
110
+ // Cancel operations
111
+ async createCancelQuoteRequest(params) {
112
+ const response = await this.tradingSdk.post("/trade/cancel-quote", params);
113
+ if (!response.success) {
114
+ throw new exceptions_1.APIException({
115
+ message: response.error?.message,
116
+ code: response.error?.code,
117
+ httpStatusCode: response.httpStatusCode,
118
+ });
119
+ }
120
+ return new entities_1.CancelRequestEntity(this.tradingSdk, response.data);
121
+ }
122
+ async getCancelQuoteRequestInfo(cancelRequestId, chainId) {
123
+ const response = await this.tradingSdk.get(`/positions/cancel-request/status?cancelRequestId=${cancelRequestId}&chainId=${chainId}`);
124
+ if (!response.success) {
125
+ throw new exceptions_1.APIException({
126
+ message: response.error?.message,
127
+ code: response.error?.code,
128
+ httpStatusCode: response.httpStatusCode,
129
+ });
130
+ }
131
+ return response.data;
132
+ }
133
+ // Cancel close request operations
134
+ async cancelCloseRequest(params) {
135
+ const response = await this.tradingSdk.post("/trade/cancel-close-request", params);
136
+ if (!response.success) {
137
+ throw new exceptions_1.APIException({
138
+ message: response.error?.message,
139
+ code: response.error?.code,
140
+ httpStatusCode: response.httpStatusCode,
141
+ });
142
+ }
143
+ return new entities_1.CancelCloseRequestEntity(this.tradingSdk, response.data);
144
+ }
145
+ async getCancelCloseRequestInfo(cancelRequestId, chainId) {
146
+ const response = await this.tradingSdk.get(`/positions/cancel-close-request/status?cancelRequestId=${cancelRequestId}&chainId=${chainId}`);
147
+ if (!response.success) {
148
+ throw new exceptions_1.APIException({
149
+ message: response.error?.message,
150
+ code: response.error?.code,
151
+ httpStatusCode: response.httpStatusCode,
152
+ });
153
+ }
154
+ return response.data;
155
+ }
156
+ }
157
+ exports.TradeManager = TradeManager;
File without changes
File without changes
@@ -0,0 +1 @@
1
+ export declare function getApiUrl(): string;
@@ -0,0 +1,8 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.getApiUrl = getApiUrl;
4
+ function getApiUrl() {
5
+ return process.env.API_URL
6
+ ? process.env.API_URL + "/v1"
7
+ : "https://gw.carbon.inc/v1";
8
+ }
@@ -0,0 +1,5 @@
1
+ export interface AuthCredentials {
2
+ address: string;
3
+ token: string;
4
+ }
5
+ export declare function authenticateWithPrivateKey(apiUrl: string, privateKey: string): Promise<AuthCredentials>;
@@ -0,0 +1,23 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.authenticateWithPrivateKey = authenticateWithPrivateKey;
4
+ const core_1 = require("@carbon-terminal/core");
5
+ const ethers_1 = require("ethers");
6
+ async function authenticateWithPrivateKey(apiUrl, privateKey) {
7
+ try {
8
+ // Create wallet from private key
9
+ const wallet = new ethers_1.ethers.Wallet(privateKey);
10
+ const address = wallet.address;
11
+ // Generate typed data for JWT token
12
+ const typedData = (0, core_1.generateIntentXJWTIssueMessage)(address, [core_1.AllowedScopes.FRONTEND_AUTH], core_1.AllowedExpiration.THIRTY_DAYS);
13
+ // Sign typed data
14
+ const signature = await wallet.signTypedData(typedData.domain, typedData.types, typedData.message);
15
+ // Get JWT token
16
+ const token = await (0, core_1.issueIntentXJWTToken)(typedData, signature);
17
+ return { address, token };
18
+ }
19
+ catch (error) {
20
+ console.error("Error:", error.response?.data || error.message);
21
+ throw error;
22
+ }
23
+ }
@@ -0,0 +1,20 @@
1
+ import { AvailableSolvers, SupportedChainId } from "@carbon-terminal/core";
2
+ export declare function siweGetNonce(subaccountAddress: string, chainId: SupportedChainId, solver: AvailableSolvers): Promise<string>;
3
+ export declare function createSiweSignatureWithPrivateKey(subaccountAddress: string, chainId: SupportedChainId, solver: AvailableSolvers, privateKey: string): Promise<{
4
+ expirationTime: string;
5
+ issuedAt: string;
6
+ message: string;
7
+ signature: string;
8
+ nonce: string;
9
+ }>;
10
+ export declare function siweGetAccessToken(subaccountAddress: string, chainId: SupportedChainId, solver: AvailableSolvers, { expirationTime, issuedAt, signature, nonce, }: {
11
+ expirationTime: string;
12
+ issuedAt: string;
13
+ signature: string;
14
+ nonce: string;
15
+ }): Promise<string>;
16
+ export declare function createSiweMessage(address: string, statement: string, chainId: number, nonce: string, domain: string, uri: string, expirationSeconds?: number, version?: string): {
17
+ message: string;
18
+ issuedAt: string;
19
+ expirationTime: string;
20
+ };
@@ -0,0 +1,106 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.siweGetNonce = siweGetNonce;
7
+ exports.createSiweSignatureWithPrivateKey = createSiweSignatureWithPrivateKey;
8
+ exports.siweGetAccessToken = siweGetAccessToken;
9
+ exports.createSiweMessage = createSiweMessage;
10
+ const core_1 = require("@carbon-terminal/core");
11
+ const axios_1 = __importDefault(require("axios"));
12
+ const ethers_1 = require("ethers");
13
+ const siwe_1 = require("siwe");
14
+ async function siweGetNonce(subaccountAddress, chainId, solver) {
15
+ const parsedSubaccountAddress = (0, ethers_1.getAddress)(subaccountAddress);
16
+ const solverBaseUrl = (0, core_1.getSolverBaseUrl)(solver, chainId);
17
+ const url = `${solverBaseUrl.http}nonce/${parsedSubaccountAddress}`;
18
+ try {
19
+ const response = await axios_1.default.get(url, {
20
+ headers: {
21
+ "Content-Type": "application/json",
22
+ Referer: "https://app.intentx.io/",
23
+ },
24
+ });
25
+ const data = response.data;
26
+ if (!data.nonce) {
27
+ throw new Error("No nonce found");
28
+ }
29
+ return data.nonce;
30
+ }
31
+ catch (error) {
32
+ console.error("Error fetching nonce:");
33
+ if (error.response) {
34
+ // The request was made and the server responded with a status code
35
+ // that falls out of the range of 2xx
36
+ console.error("Response data:", error.response.data);
37
+ console.error("Response status:", error.response.status);
38
+ }
39
+ else if (error.request) {
40
+ // The request was made but no response was received
41
+ console.error("No response received:", error.request);
42
+ }
43
+ else {
44
+ // Something happened in setting up the request that triggered an Error
45
+ console.error("Error message:", error.message);
46
+ }
47
+ throw error;
48
+ }
49
+ }
50
+ async function createSiweSignatureWithPrivateKey(subaccountAddress, chainId, solver, privateKey) {
51
+ const parsedSubaccountAddress = (0, ethers_1.getAddress)(subaccountAddress);
52
+ const nonce = await siweGetNonce(parsedSubaccountAddress, chainId, solver);
53
+ // const TESTING_PRIVATE_KEY = process.env.TESTING_ACCOUNT_PRIVATE_KEY;
54
+ const wallet = new ethers_1.ethers.Wallet(privateKey);
55
+ const userAddress = wallet.address;
56
+ const solverBaseUrl = (0, core_1.getSolverBaseUrl)(solver, chainId);
57
+ const { expirationTime, issuedAt, message } = createSiweMessage(userAddress, `msg: ${parsedSubaccountAddress}`, chainId, nonce,
58
+ // host,
59
+ "app.intentx.io", `${solverBaseUrl?.http}login`);
60
+ const signature = await wallet.signMessage(message);
61
+ return { expirationTime, issuedAt, message, signature, nonce };
62
+ }
63
+ async function siweGetAccessToken(subaccountAddress, chainId, solver, { expirationTime, issuedAt, signature, nonce, }) {
64
+ const parsedSubaccountAddress = (0, ethers_1.getAddress)(subaccountAddress);
65
+ const solverBaseUrl = (0, core_1.getSolverBaseUrl)(solver, chainId);
66
+ try {
67
+ const { data } = await axios_1.default.post(`${solverBaseUrl.http}login`, {
68
+ account_address: parsedSubaccountAddress,
69
+ expiration_time: expirationTime,
70
+ issued_at: issuedAt,
71
+ signature,
72
+ nonce,
73
+ }, {
74
+ headers: {
75
+ "Content-Type": "application/json",
76
+ Referer: "https://app.intentx.io/",
77
+ Origin: "https://app.intentx.io/",
78
+ },
79
+ });
80
+ if (!data.access_token) {
81
+ throw new Error("No access token received");
82
+ }
83
+ return data.access_token;
84
+ }
85
+ catch (error) {
86
+ console.error("SIWE login error:", error.response?.data || error.message);
87
+ throw error;
88
+ }
89
+ }
90
+ function createSiweMessage(address, statement, chainId, nonce, domain, uri, expirationSeconds = 60 * 60 * 24, version = "1") {
91
+ const issuedAt = new Date().toISOString();
92
+ const expirationTime = new Date(Date.now() + expirationSeconds * 1000).toISOString();
93
+ const parsedAddress = (0, ethers_1.getAddress)(address);
94
+ const message = new siwe_1.SiweMessage({
95
+ domain,
96
+ address: parsedAddress,
97
+ statement,
98
+ chainId,
99
+ nonce,
100
+ version,
101
+ uri,
102
+ issuedAt,
103
+ expirationTime,
104
+ });
105
+ return { message: message.prepareMessage(), issuedAt, expirationTime };
106
+ }
package/package.json ADDED
@@ -0,0 +1,47 @@
1
+ {
2
+ "name": "@carbon-terminal/trading-sdk",
3
+ "version": "0.2.5",
4
+ "description": "This SDK is used to interact with the IntentX Trading API.",
5
+ "main": "dist/index.js",
6
+ "types": "dist/index.d.ts",
7
+ "exports": {
8
+ ".": {
9
+ "types": "./dist/index.d.ts",
10
+ "default": "./dist/index.js"
11
+ },
12
+ "./dist/*": {
13
+ "types": "./dist/*.d.ts",
14
+ "default": "./dist/*.js"
15
+ }
16
+ },
17
+ "scripts": {
18
+ "clean": "rm -rf dist",
19
+ "build": "npm run clean && tsc",
20
+ "dev": "tsc -w",
21
+ "test": "echo 'no test yet'",
22
+ "example": "ts-node -r tsconfig-paths/register",
23
+ "build-publish": "npm run build && npm publish --access public"
24
+ },
25
+ "dependencies": {
26
+ "@carbon-terminal/core": "^1.0.0",
27
+ "axios": "^1.6.2",
28
+ "decimal.js": "^10.4.3",
29
+ "jsonwebtoken": "^9.0.2",
30
+ "siwe": "^3.0.0"
31
+ },
32
+ "devDependencies": {
33
+ "@types/node": "^20.10.4",
34
+ "ts-node": "^10.9.1",
35
+ "tsconfig-paths": "^4.2.0",
36
+ "typescript": "^5.3.3"
37
+ },
38
+ "author": "",
39
+ "license": "ISC",
40
+ "directories": {
41
+ "doc": "docs"
42
+ },
43
+ "files": [
44
+ "dist",
45
+ "README.md"
46
+ ]
47
+ }