├── Examples
├── FTX-WebSocket-Template
│ ├── .gitignore
│ ├── README.md
│ ├── index.js
│ ├── package-lock.json
│ └── package.json
└── OKX-WebSocket-Template
│ ├── .gitignore
│ ├── README.md
│ ├── index.js
│ ├── package-lock.json
│ └── package.json
└── README.md
/Examples/FTX-WebSocket-Template/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules
--------------------------------------------------------------------------------
/Examples/FTX-WebSocket-Template/README.md:
--------------------------------------------------------------------------------
1 | # FTX Websocket Template built with PENDAX-SDK
2 | https://github.com/CompendiumFi/PENDAX-SDK
3 |
4 | install required packages with ```npm install```
5 |
6 |
7 | run with ```node index.js```
8 |
9 | ## This application is a fully functional template for FTX websockets utilizing PENDAX-SDK
10 |
11 | Add your api key, secret, and subaccount in index.js under the socket config. adjust parameters as neccesary.
--------------------------------------------------------------------------------
/Examples/FTX-WebSocket-Template/index.js:
--------------------------------------------------------------------------------
1 | import { FtxSocket } from "./node_modules/@compendiumfi/pendax/sockets/ftxsocket.js"
2 | // Standalone implementation of FTX sockets
3 |
4 | let ftxSocket;
5 | let subscriptions = {}
6 | // Create config object - we will only use this object once - when the socket is originally started
7 | const SocketConfigOne = {
8 | name: '',
9 | key: "",
10 | secret: "",
11 | subaccount: "",
12 | clientReconnect: socketReconnect,
13 | clientOnOpen: ftxOnOpen,
14 | clientOnMessage: ftxOnMessage,
15 | clientOnError: ftxOnError,
16 | clientOnClose: ftxOnClose,
17 | pingInterval: 10000,
18 | autoReconnectOnClose: true,
19 | reconnectWaitTime: 2000,
20 | maxRetries: 3,
21 | socket: ftxSocket
22 | }
23 |
24 | //Then, for convenience we define a function called startSocket - when called it will take our socketConfig OR the config object from the socket being retried as a parameter
25 | function startSocket(socketConfig) {
26 | // connect
27 | try {
28 | // From this point forward we will access and manage the socket using the returned mySocket object
29 | ftxSocket = new FtxSocket(socketConfig)
30 | // setTimeout(
31 | // function(subscriptions, ftxSocket){cancelSubscriptions(subscriptions, ftxSocket)} , 30000, subscriptions, ftxSocket
32 | // );
33 | }
34 | catch (error) {
35 | // handle error
36 | }
37 | }
38 | function cancelSubscriptions(subscriptionsToCancel, theSocket){
39 | for(const subscription in subscriptionsToCancel){
40 | theSocket.unsubscribe(subscription)
41 | }
42 | }
43 | // Reconnection/retry handler
44 | function socketReconnect (oldSocket) {
45 | // Retrieve the most recent retry number from the old socket
46 | let currentRetry = oldSocket.getRetryNumber();
47 | // Retrieve the max retries value from the old socket
48 | let maxRetries = oldSocket.getOptions().maxRetries;
49 | // Test to see if we should retry the connection
50 | if (currentRetry <= maxRetries){
51 | console.log('reconnecting')
52 | // Now retrieve the options object from the old socket
53 | const oldSocketOptions = oldSocket.getOptions()
54 | // Finally attempt to restart the socket, passing in oldSocketOptions instead of mySocketConfig as we did the on first startup
55 | startSocket(oldSocketOptions);
56 | }
57 | else{
58 | // We ran out of retries...let the socket die
59 | console.log('max socket reconnect retries exceeded - socket terminated')
60 | }
61 | }
62 | // Event handlers
63 | function ftxOnOpen(socketInfo){
64 | // upon opening we will login (since we are going to subscribe to private data)
65 | // there will be no response in any case
66 | ftxSocket.login();
67 | console.log('Socket opened - attempting login')
68 | // create our first subscription
69 | subscriptions.myOrders = {
70 | name: 'myOrders',
71 | args:
72 | { channel: 'orders', market: 'BTC-PERP'}
73 | }
74 | // create our second subscription
75 | subscriptions.myFills = {
76 | name: 'myFills',
77 | args: {channel: 'fills', market: 'BTC-PERP'}
78 | }
79 | // create our third subscription
80 | subscriptions.myTickers = {
81 | name: 'myTickers',
82 | args: {channel: 'ticker', market: 'BTC-PERP'}
83 | }
84 |
85 |
86 | // subscribe
87 | // ftxSocket.subscribe(subscriptions.myOrders)
88 | // ftxSocket.subscribe(subscriptions.myFills)
89 | ftxSocket.subscribe(subscriptions.myTickers)
90 | console.log('Attempting subscriptions')
91 | }
92 | function ftxOnMessage(socketInfo, msg){
93 | switch(msg.type){
94 | case 'error':
95 | console.log('Error code: ', msg.code, ' Message: ', msg.msg)
96 | break;
97 | case 'subscribed':
98 | console.log('Subscribed to channel: ', msg.channel)
99 | break;
100 | case 'unsubscribed':
101 | // test to see if socket has any remaining subscriptions
102 | if (Object.keys(ftxSocket.getSubscriptions()).length == 0){
103 | // if not then kill socket - you must pass the socket instance itself into the kill routine
104 | ftxSocket.kill(ftxSocket)
105 | }
106 | console.log('Unsubscribed from channel: ', msg.channel)
107 | break;
108 | case 'info':
109 | console.log('Info received: Code: ', msg.code, ' Message: ', msg.msg)
110 | break;
111 | case 'partial':
112 | console.log('Market snapshot: ', msg.data)
113 | break;
114 | case 'update':
115 | console.log('Market data: ', msg.data)
116 | break;
117 | }
118 | }
119 | function ftxOnError(err, socketInfo){
120 | console.log(err);
121 | }
122 | function ftxOnClose(code, msg, socketInfo){
123 | // This is where you should end up after 60 seconds
124 | console.log('Code: ', code, ' Message: ', msg);
125 | }
126 |
127 | // start it up
128 | startSocket(SocketConfigOne)
129 |
130 |
--------------------------------------------------------------------------------
/Examples/FTX-WebSocket-Template/package-lock.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "ftx-websocket-template",
3 | "version": "1.0.0",
4 | "lockfileVersion": 2,
5 | "requires": true,
6 | "packages": {
7 | "": {
8 | "name": "ftx-websocket-template",
9 | "version": "1.0.0",
10 | "license": "ISC",
11 | "dependencies": {
12 | "@compendiumfi/pendax": "^1.1.3"
13 | }
14 | },
15 | "node_modules/@compendiumfi/pendax": {
16 | "version": "1.1.3",
17 | "resolved": "https://registry.npmjs.org/@compendiumfi/pendax/-/pendax-1.1.3.tgz",
18 | "integrity": "sha512-hT5rDYx8yPrnzTudoW6M8JFXxpjZ/5+EsySDcIF3hMrWcnIolGgYtPDv91qahlGqMlYz55jh4AhanDlA79IskA==",
19 | "dependencies": {
20 | "axios": "^0.27.2",
21 | "base64-js": "^1.5.1",
22 | "crypto-js": "^4.1.1",
23 | "dateformat": "^5.0.3",
24 | "dotenv": "^16.0.1",
25 | "lodash": "^4.17.21",
26 | "short-unique-id": "^4.4.4",
27 | "uuidv4": "^6.2.13",
28 | "ws": "^8.7.0"
29 | }
30 | },
31 | "node_modules/@types/uuid": {
32 | "version": "8.3.4",
33 | "resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-8.3.4.tgz",
34 | "integrity": "sha512-c/I8ZRb51j+pYGAu5CrFMRxqZ2ke4y2grEBO5AUjgSkSk+qT2Ea+OdWElz/OiMf5MNpn2b17kuVBwZLQJXzihw=="
35 | },
36 | "node_modules/asynckit": {
37 | "version": "0.4.0",
38 | "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
39 | "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q=="
40 | },
41 | "node_modules/axios": {
42 | "version": "0.27.2",
43 | "resolved": "https://registry.npmjs.org/axios/-/axios-0.27.2.tgz",
44 | "integrity": "sha512-t+yRIyySRTp/wua5xEr+z1q60QmLq8ABsS5O9Me1AsE5dfKqgnCFzwiCZZ/cGNd1lq4/7akDWMxdhVlucjmnOQ==",
45 | "dependencies": {
46 | "follow-redirects": "^1.14.9",
47 | "form-data": "^4.0.0"
48 | }
49 | },
50 | "node_modules/base64-js": {
51 | "version": "1.5.1",
52 | "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz",
53 | "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==",
54 | "funding": [
55 | {
56 | "type": "github",
57 | "url": "https://github.com/sponsors/feross"
58 | },
59 | {
60 | "type": "patreon",
61 | "url": "https://www.patreon.com/feross"
62 | },
63 | {
64 | "type": "consulting",
65 | "url": "https://feross.org/support"
66 | }
67 | ]
68 | },
69 | "node_modules/combined-stream": {
70 | "version": "1.0.8",
71 | "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz",
72 | "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==",
73 | "dependencies": {
74 | "delayed-stream": "~1.0.0"
75 | },
76 | "engines": {
77 | "node": ">= 0.8"
78 | }
79 | },
80 | "node_modules/crypto-js": {
81 | "version": "4.1.1",
82 | "resolved": "https://registry.npmjs.org/crypto-js/-/crypto-js-4.1.1.tgz",
83 | "integrity": "sha512-o2JlM7ydqd3Qk9CA0L4NL6mTzU2sdx96a+oOfPu8Mkl/PK51vSyoi8/rQ8NknZtk44vq15lmhAj9CIAGwgeWKw=="
84 | },
85 | "node_modules/dateformat": {
86 | "version": "5.0.3",
87 | "resolved": "https://registry.npmjs.org/dateformat/-/dateformat-5.0.3.tgz",
88 | "integrity": "sha512-Kvr6HmPXUMerlLcLF+Pwq3K7apHpYmGDVqrxcDasBg86UcKeTSNWbEzU8bwdXnxnR44FtMhJAxI4Bov6Y/KUfA==",
89 | "engines": {
90 | "node": ">=12.20"
91 | }
92 | },
93 | "node_modules/delayed-stream": {
94 | "version": "1.0.0",
95 | "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
96 | "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==",
97 | "engines": {
98 | "node": ">=0.4.0"
99 | }
100 | },
101 | "node_modules/dotenv": {
102 | "version": "16.0.3",
103 | "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.0.3.tgz",
104 | "integrity": "sha512-7GO6HghkA5fYG9TYnNxi14/7K9f5occMlp3zXAuSxn7CKCxt9xbNWG7yF8hTCSUchlfWSe3uLmlPfigevRItzQ==",
105 | "engines": {
106 | "node": ">=12"
107 | }
108 | },
109 | "node_modules/follow-redirects": {
110 | "version": "1.15.2",
111 | "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.2.tgz",
112 | "integrity": "sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA==",
113 | "funding": [
114 | {
115 | "type": "individual",
116 | "url": "https://github.com/sponsors/RubenVerborgh"
117 | }
118 | ],
119 | "engines": {
120 | "node": ">=4.0"
121 | },
122 | "peerDependenciesMeta": {
123 | "debug": {
124 | "optional": true
125 | }
126 | }
127 | },
128 | "node_modules/form-data": {
129 | "version": "4.0.0",
130 | "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz",
131 | "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==",
132 | "dependencies": {
133 | "asynckit": "^0.4.0",
134 | "combined-stream": "^1.0.8",
135 | "mime-types": "^2.1.12"
136 | },
137 | "engines": {
138 | "node": ">= 6"
139 | }
140 | },
141 | "node_modules/lodash": {
142 | "version": "4.17.21",
143 | "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz",
144 | "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg=="
145 | },
146 | "node_modules/mime-db": {
147 | "version": "1.52.0",
148 | "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz",
149 | "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==",
150 | "engines": {
151 | "node": ">= 0.6"
152 | }
153 | },
154 | "node_modules/mime-types": {
155 | "version": "2.1.35",
156 | "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz",
157 | "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==",
158 | "dependencies": {
159 | "mime-db": "1.52.0"
160 | },
161 | "engines": {
162 | "node": ">= 0.6"
163 | }
164 | },
165 | "node_modules/short-unique-id": {
166 | "version": "4.4.4",
167 | "resolved": "https://registry.npmjs.org/short-unique-id/-/short-unique-id-4.4.4.tgz",
168 | "integrity": "sha512-oLF1NCmtbiTWl2SqdXZQbo5KM1b7axdp0RgQLq8qCBBLoq+o3A5wmLrNM6bZIh54/a8BJ3l69kTXuxwZ+XCYuw==",
169 | "bin": {
170 | "short-unique-id": "bin/short-unique-id",
171 | "suid": "bin/short-unique-id"
172 | }
173 | },
174 | "node_modules/uuid": {
175 | "version": "8.3.2",
176 | "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz",
177 | "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==",
178 | "bin": {
179 | "uuid": "dist/bin/uuid"
180 | }
181 | },
182 | "node_modules/uuidv4": {
183 | "version": "6.2.13",
184 | "resolved": "https://registry.npmjs.org/uuidv4/-/uuidv4-6.2.13.tgz",
185 | "integrity": "sha512-AXyzMjazYB3ovL3q051VLH06Ixj//Knx7QnUSi1T//Ie3io6CpsPu9nVMOx5MoLWh6xV0B9J0hIaxungxXUbPQ==",
186 | "dependencies": {
187 | "@types/uuid": "8.3.4",
188 | "uuid": "8.3.2"
189 | }
190 | },
191 | "node_modules/ws": {
192 | "version": "8.11.0",
193 | "resolved": "https://registry.npmjs.org/ws/-/ws-8.11.0.tgz",
194 | "integrity": "sha512-HPG3wQd9sNQoT9xHyNCXoDUa+Xw/VevmY9FoHyQ+g+rrMn4j6FB4np7Z0OhdTgjx6MgQLK7jwSy1YecU1+4Asg==",
195 | "engines": {
196 | "node": ">=10.0.0"
197 | },
198 | "peerDependencies": {
199 | "bufferutil": "^4.0.1",
200 | "utf-8-validate": "^5.0.2"
201 | },
202 | "peerDependenciesMeta": {
203 | "bufferutil": {
204 | "optional": true
205 | },
206 | "utf-8-validate": {
207 | "optional": true
208 | }
209 | }
210 | }
211 | },
212 | "dependencies": {
213 | "@compendiumfi/pendax": {
214 | "version": "1.1.3",
215 | "resolved": "https://registry.npmjs.org/@compendiumfi/pendax/-/pendax-1.1.3.tgz",
216 | "integrity": "sha512-hT5rDYx8yPrnzTudoW6M8JFXxpjZ/5+EsySDcIF3hMrWcnIolGgYtPDv91qahlGqMlYz55jh4AhanDlA79IskA==",
217 | "requires": {
218 | "axios": "^0.27.2",
219 | "base64-js": "^1.5.1",
220 | "crypto-js": "^4.1.1",
221 | "dateformat": "^5.0.3",
222 | "dotenv": "^16.0.1",
223 | "lodash": "^4.17.21",
224 | "short-unique-id": "^4.4.4",
225 | "uuidv4": "^6.2.13",
226 | "ws": "^8.7.0"
227 | }
228 | },
229 | "@types/uuid": {
230 | "version": "8.3.4",
231 | "resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-8.3.4.tgz",
232 | "integrity": "sha512-c/I8ZRb51j+pYGAu5CrFMRxqZ2ke4y2grEBO5AUjgSkSk+qT2Ea+OdWElz/OiMf5MNpn2b17kuVBwZLQJXzihw=="
233 | },
234 | "asynckit": {
235 | "version": "0.4.0",
236 | "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
237 | "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q=="
238 | },
239 | "axios": {
240 | "version": "0.27.2",
241 | "resolved": "https://registry.npmjs.org/axios/-/axios-0.27.2.tgz",
242 | "integrity": "sha512-t+yRIyySRTp/wua5xEr+z1q60QmLq8ABsS5O9Me1AsE5dfKqgnCFzwiCZZ/cGNd1lq4/7akDWMxdhVlucjmnOQ==",
243 | "requires": {
244 | "follow-redirects": "^1.14.9",
245 | "form-data": "^4.0.0"
246 | }
247 | },
248 | "base64-js": {
249 | "version": "1.5.1",
250 | "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz",
251 | "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA=="
252 | },
253 | "combined-stream": {
254 | "version": "1.0.8",
255 | "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz",
256 | "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==",
257 | "requires": {
258 | "delayed-stream": "~1.0.0"
259 | }
260 | },
261 | "crypto-js": {
262 | "version": "4.1.1",
263 | "resolved": "https://registry.npmjs.org/crypto-js/-/crypto-js-4.1.1.tgz",
264 | "integrity": "sha512-o2JlM7ydqd3Qk9CA0L4NL6mTzU2sdx96a+oOfPu8Mkl/PK51vSyoi8/rQ8NknZtk44vq15lmhAj9CIAGwgeWKw=="
265 | },
266 | "dateformat": {
267 | "version": "5.0.3",
268 | "resolved": "https://registry.npmjs.org/dateformat/-/dateformat-5.0.3.tgz",
269 | "integrity": "sha512-Kvr6HmPXUMerlLcLF+Pwq3K7apHpYmGDVqrxcDasBg86UcKeTSNWbEzU8bwdXnxnR44FtMhJAxI4Bov6Y/KUfA=="
270 | },
271 | "delayed-stream": {
272 | "version": "1.0.0",
273 | "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
274 | "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ=="
275 | },
276 | "dotenv": {
277 | "version": "16.0.3",
278 | "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.0.3.tgz",
279 | "integrity": "sha512-7GO6HghkA5fYG9TYnNxi14/7K9f5occMlp3zXAuSxn7CKCxt9xbNWG7yF8hTCSUchlfWSe3uLmlPfigevRItzQ=="
280 | },
281 | "follow-redirects": {
282 | "version": "1.15.2",
283 | "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.2.tgz",
284 | "integrity": "sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA=="
285 | },
286 | "form-data": {
287 | "version": "4.0.0",
288 | "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz",
289 | "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==",
290 | "requires": {
291 | "asynckit": "^0.4.0",
292 | "combined-stream": "^1.0.8",
293 | "mime-types": "^2.1.12"
294 | }
295 | },
296 | "lodash": {
297 | "version": "4.17.21",
298 | "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz",
299 | "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg=="
300 | },
301 | "mime-db": {
302 | "version": "1.52.0",
303 | "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz",
304 | "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg=="
305 | },
306 | "mime-types": {
307 | "version": "2.1.35",
308 | "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz",
309 | "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==",
310 | "requires": {
311 | "mime-db": "1.52.0"
312 | }
313 | },
314 | "short-unique-id": {
315 | "version": "4.4.4",
316 | "resolved": "https://registry.npmjs.org/short-unique-id/-/short-unique-id-4.4.4.tgz",
317 | "integrity": "sha512-oLF1NCmtbiTWl2SqdXZQbo5KM1b7axdp0RgQLq8qCBBLoq+o3A5wmLrNM6bZIh54/a8BJ3l69kTXuxwZ+XCYuw=="
318 | },
319 | "uuid": {
320 | "version": "8.3.2",
321 | "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz",
322 | "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg=="
323 | },
324 | "uuidv4": {
325 | "version": "6.2.13",
326 | "resolved": "https://registry.npmjs.org/uuidv4/-/uuidv4-6.2.13.tgz",
327 | "integrity": "sha512-AXyzMjazYB3ovL3q051VLH06Ixj//Knx7QnUSi1T//Ie3io6CpsPu9nVMOx5MoLWh6xV0B9J0hIaxungxXUbPQ==",
328 | "requires": {
329 | "@types/uuid": "8.3.4",
330 | "uuid": "8.3.2"
331 | }
332 | },
333 | "ws": {
334 | "version": "8.11.0",
335 | "resolved": "https://registry.npmjs.org/ws/-/ws-8.11.0.tgz",
336 | "integrity": "sha512-HPG3wQd9sNQoT9xHyNCXoDUa+Xw/VevmY9FoHyQ+g+rrMn4j6FB4np7Z0OhdTgjx6MgQLK7jwSy1YecU1+4Asg==",
337 | "requires": {}
338 | }
339 | }
340 | }
341 |
--------------------------------------------------------------------------------
/Examples/FTX-WebSocket-Template/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "ftx-websocket-template",
3 | "version": "1.0.0",
4 | "description": "",
5 | "main": "index.js",
6 | "type": "module",
7 | "scripts": {
8 | "test": "echo \"Error: no test specified\" && exit 1"
9 | },
10 | "keywords": [],
11 | "author": "traderjoe155",
12 | "license": "ISC",
13 | "dependencies": {
14 | "@compendiumfi/pendax": "^1.1.3"
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/Examples/OKX-WebSocket-Template/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules
--------------------------------------------------------------------------------
/Examples/OKX-WebSocket-Template/README.md:
--------------------------------------------------------------------------------
1 | # OKX Websocket Template built with PENDAX-SDK
2 | https://github.com/CompendiumFi/PENDAX-SDK
3 |
4 | install required packages with ```npm install```
5 |
6 |
7 | run with ```node index.js```
8 |
9 | ## This application is a fully functional template for okx websockets utilizing PENDAX-SDK
10 |
11 | Add your api key, secret, and passphrase in index.js under the socket config. adjust parameters as neccesary. If the endpoint you are trying to
12 | use is private, change isPrivate: true. For market data and other public endpoints, isPrivate: false.
13 |
14 | This sample code is using a single okxSubscription, however to add more just declare a new variable and a new socket config. You can refrence more
15 | than one at a time inside the try block in startSocket function.
16 |
17 |
18 |
19 | create a subscription inside the doSubscriptions function.
20 |
21 | ex:
22 | ```
23 | function doSubscriptions(socket) {
24 | subscriptions.tickers = {
25 | name: 'tickers',
26 | args:
27 | [{ channel: 'tickers', instId: 'BTC-USDT-SWAP' }]
28 | }
29 | socket.subscribe(subscriptions.tickers)
30 | console.log('Attempting subscriptions')
31 | }
32 | ```
33 |
34 | Edit what you want to happen when a message comes in on this channel inside the handleMessage function:
35 | ```
36 | case 'tickers':
37 | console.log(msg.data)
38 | break;
39 | ```
40 | ## Result
41 |
42 |
43 |
44 |
45 | All websocket functionality available from OKX at time of writing is present in this template
46 |
--------------------------------------------------------------------------------
/Examples/OKX-WebSocket-Template/index.js:
--------------------------------------------------------------------------------
1 | import { OkxSocket } from "./node_modules/@compendiumfi/pendax/sockets/okxsocket.js"
2 | // Standalone implementation of OKX sockets
3 |
4 | let okxSocket;
5 | let subscriptions = {}
6 | // Create config object - we will only use this object once - when the socket is originally started
7 | const okxSocketConfig = {
8 | name: 'okxSocket',
9 | key: "",
10 | secret: "",
11 | passphrase: "",
12 | clientReconnect: socketReconnect,
13 | clientOnOpen: okxOnOpen,
14 | clientOnMessage: okxOnMessage,
15 | clientOnError: okxOnError,
16 | clientOnClose: okxOnClose,
17 | pingInterval: 10000,
18 | autoReconnectOnClose: true,
19 | reconnectWaitTime: 3000,
20 | maxRetries: 3,
21 | socket: okxSocket,
22 | isPrivate: false
23 | }
24 |
25 | //Then, for convenience we define a function called startSocket - when called it will take our socketConfig OR the config object from the socket being retried as a parameter
26 | function startSocket(socketConfig) {
27 | // connect
28 | try {
29 | // From this point forward we will access and manage the socket using the returned mySocket object
30 | okxSocket = new OkxSocket(socketConfig)
31 | // setTimeout(
32 | // function (subscriptions, okxSocket) { cancelSubscriptions(subscriptions, okxSocket) }, 30000, subscriptions, okxSocket
33 | // );
34 | }
35 | catch (error) {
36 | // handle error
37 | }
38 | }
39 | function cancelSubscriptions(subscriptionsToCancel, theSocket) {
40 | for (const subscription in subscriptionsToCancel) {
41 | theSocket.unsubscribe(subscription)
42 | }
43 | }
44 | // Reconnection/retry handler
45 | function socketReconnect(oldSocket) {
46 | // Retrieve the most recent retry number from the old socket
47 | let currentRetry = oldSocket.getRetryNumber();
48 | // Retrieve the max retries value from the old socket
49 | let maxRetries = oldSocket.getOptions().maxRetries;
50 | // Test to see if we should retry the connection
51 | if (currentRetry <= maxRetries) {
52 | console.log('***************** reconnecting **********************')
53 | console.log('Retry = ', currentRetry)
54 | // Now retrieve the options object from the old socket
55 | const oldSocketOptions = oldSocket.getOptions()
56 | // Finally attempt to restart the socket, passing in oldSocketOptions instead of mySocketConfig as we did the on first startup
57 | startSocket(oldSocketOptions);
58 | }
59 | else {
60 | // We ran out of retries...let the socket die
61 | console.log('max socket reconnect retries exceeded - socket terminated')
62 | }
63 | }
64 | // Event handlers
65 | function okxOnOpen(socketInfo) {
66 | // upon opening we will login (since we are going to subscribe to private data)
67 | // there will be no response in any case
68 | socketInfo.socket.login();
69 | console.log('Socket opened - attempting login')
70 | }
71 | function placeOrders(socket){
72 | const orders = {
73 | id: '2637251',
74 | args: [
75 | {
76 | "side": "buy",
77 | "instId": "BTC-USDT",
78 | "tdMode": "cross",
79 | "ordType": "market",
80 | "sz": "0.01"
81 | }
82 | ]
83 | }
84 | socket.placeOrders(orders)
85 | }
86 | function amendOrders(socket){
87 |
88 | }
89 | function cancelOrders(socket){
90 |
91 | }
92 | function doSubscriptions(socket) {
93 | // create our first subscription
94 | // subscriptions.orders = {
95 | // name: 'orders',
96 | // args:
97 | // [{ channel: 'orders'}]
98 | // }
99 | subscriptions.tickers = {
100 | name: 'tickers',
101 | args:
102 | [{ channel: 'tickers', instId: 'BTC-USDT-SWAP' }]
103 | }
104 | // subscriptions.myBalances = {
105 | // name: 'myBalances',
106 | // args:
107 | // [{ channel: 'balance_and_position'}]
108 | // }
109 | // subscriptions.ob = {
110 | // name: 'orderbook',
111 | // args:
112 | // [{ channel: 'books', instId: 'BTC-USDT-SWAP' }]
113 | // }
114 | // subscribe
115 | //socket.subscribe(subscriptions.myOrders)
116 | //socket.subscribe(subscriptions.myBalances)
117 | socket.subscribe(subscriptions.tickers)
118 | //socket.subscribe(subscriptions.orders)
119 | console.log('Attempting subscriptions')
120 | }
121 | function okxOnMessage(socketInfo, msg) {
122 | switch (msg.event) {
123 | case 'login':
124 | console.log('login successful');
125 | doSubscriptions(socketInfo.socket);
126 | //placeOrders(socketInfo.socket)
127 | break;
128 | case 'error':
129 | if (msg.msg.includes('"op":"login"') || msg.msg.includes('Please log in')) {
130 | socketInfo.socket.loggedOut()
131 | }
132 | console.log('Error code: ', msg.code, ' Message: ', msg.msg)
133 | break;
134 | case 'subscribe':
135 | console.log('Subscribed to channel: ', msg.arg)
136 | break;
137 | case 'unsubscribe':
138 | // test to see if socket has any remaining subscriptions
139 | if (Object.keys(okxSocket.getSubscriptions()).length == 0) {
140 | // if not then kill socket - you must pass the socket instance itself into the kill routine
141 | okxSocket.kill(okxSocket)
142 | }
143 | console.log('Unsubscribed from channel: ', msg.channel)
144 | break;
145 | // case 'info':
146 | // console.log('Info received: Code: ', msg.code, ' Message: ', msg.msg)
147 | // break;
148 | // case 'partial':
149 | // console.log('Market snapshot: ', msg.data)
150 | // break;
151 | // case 'update':
152 | // console.log('Market data: ', msg.data)
153 | // break;
154 | default:
155 | if (msg.event) {
156 | console.log('Unknown event: ', msg.event)
157 | }
158 | else {
159 | handleMessage(msg)
160 | }
161 | break;
162 | }
163 | }
164 | function handleMessage(msg) {
165 | switch (getMessageType(msg)) {
166 | case 'order':
167 | console.log(msg.data)
168 | break;
169 | case 'batch-orders':
170 | console.log(msg.data)
171 | break;
172 | case 'cancel-order':
173 | console.log(msg.data)
174 | break;
175 | case 'batch-cancel-orders':
176 | console.log(msg.data)
177 | break;
178 | case 'amend-order':
179 | console.log(msg.data)
180 | break;
181 | case 'batch-amend-orders':
182 | console.log(msg.data)
183 | break;
184 | case 'account':
185 | console.log(msg.data)
186 | break;
187 | case 'positions':
188 | console.log(msg.data)
189 | break;
190 | case 'balance_and_position':
191 | console.log(msg.data)
192 | break;
193 | case 'orders':
194 | console.log(msg.data)
195 | break;
196 | case 'orders-algo':
197 | console.log(msg.data)
198 | break;
199 | case 'algo-advance':
200 | console.log(msg.data)
201 | break;
202 | case 'liquidation-warning':
203 | console.log(msg.data)
204 | break;
205 | case 'account-greeks':
206 | console.log(msg.data)
207 | break;
208 | case 'rfqs':
209 | console.log(msg.data)
210 | break;
211 | case 'quotes':
212 | console.log(msg.data)
213 | break;
214 | case 'struc-block-trades':
215 | console.log(msg.data)
216 | break;
217 | case 'grid-orders-spot':
218 | console.log(msg.data)
219 | break;
220 | case '"grid-orders-contract':
221 | console.log(msg.data)
222 | break;
223 | case 'grid-positions':
224 | console.log(msg.data)
225 | break;
226 | case 'grid-sub-orders':
227 | console.log(msg.data)
228 | break;
229 | case 'instruments':
230 | console.log(msg.data)
231 | break;
232 | case 'tickers':
233 | console.log(msg.data)
234 | break;
235 | case 'open-interest':
236 | console.log(msg.data)
237 | break;
238 | case 'candle1D':
239 | console.log(msg.data)
240 | break;
241 | case 'trades':
242 | console.log(msg.data)
243 | break;
244 | case 'estimated-price':
245 | console.log(msg.data)
246 | break;
247 | case 'mark-price':
248 | console.log(msg.data)
249 | break;
250 | case 'mark-price-candle1D':
251 | console.log(msg.data)
252 | break;
253 | case 'price-limit':
254 | console.log(msg.data)
255 | break;
256 | case 'books':
257 | console.log(msg.data[0])
258 | break;
259 | case 'opt-summary':
260 | console.log(msg.data)
261 | break;
262 | case 'funding-rate':
263 | console.log(msg.data)
264 | break;
265 | case 'index-candle1Y':
266 | console.log(msg.data)
267 | break;
268 | case 'index-candle6M':
269 | console.log(msg.data)
270 | break;
271 | case 'index-candle3M':
272 | console.log(msg.data)
273 | break;
274 | case 'index-candle1M':
275 | console.log(msg.data)
276 | break;
277 | case 'index-candle1W':
278 | console.log(msg.data)
279 | break;
280 | case 'index-candle1D':
281 | console.log(msg.data)
282 | break;
283 | case 'index-candle2D':
284 | console.log(msg.data)
285 | break;
286 | case 'index-candle3D':
287 | console.log(msg.data)
288 | break;
289 | case 'index-candle5D':
290 | console.log(msg.data)
291 | break;
292 | case 'index-candle12H':
293 | console.log(msg.data)
294 | break;
295 | case 'index-candle6H':
296 | console.log(msg.data)
297 | break;
298 | case 'index-candle4H':
299 | console.log(msg.data)
300 | break;
301 | case 'index-candle2H':
302 | console.log(msg.data)
303 | break;
304 | case 'index-candle1H':
305 | console.log(msg.data)
306 | break;
307 | case 'index-candle30m':
308 | console.log(msg.data)
309 | break;
310 | case 'index-candle15m':
311 | console.log(msg.data)
312 | break;
313 | case 'index-candle5m':
314 | console.log(msg.data)
315 | break;
316 | case 'index-candle3m':
317 | console.log(msg.data)
318 | break;
319 | case 'index-candle1m':
320 | console.log(msg.data)
321 | break;
322 | case 'index-candle1Yutc':
323 | console.log(msg.data)
324 | break;
325 | case 'index-candle3Mutc':
326 | console.log(msg.data)
327 | break;
328 | case 'index-candle1Mutc':
329 | console.log(msg.data)
330 | break;
331 | case 'index-candle1Wutc':
332 | console.log(msg.data)
333 | break;
334 | case 'index-candle1Dutc':
335 | console.log(msg.data)
336 | break;
337 | case 'index-candle2Dutc':
338 | console.log(msg.data)
339 | break;
340 | case 'index-candle3Dutc':
341 | console.log(msg.data)
342 | break;
343 | case 'index-candle5Dutc':
344 | console.log(msg.data)
345 | break;
346 | case 'index-candle12Hutc':
347 | console.log(msg.data)
348 | break;
349 | case 'index-candle6Hutc':
350 | console.log(msg.data)
351 | break;
352 | case 'index-tickers':
353 | console.log(msg.data)
354 | break;
355 | case 'status':
356 | console.log(msg.data)
357 | break;
358 | case 'public-struc-block-trades':
359 | console.log(msg.data)
360 | break;
361 | case 'block-tickers':
362 | console.log(msg.data)
363 | break;
364 | }
365 | }
366 | function getMessageType(msg) {
367 | if (msg.op) {
368 | return msg.op;
369 | }
370 | else if (msg.arg) {
371 | return msg.arg.channel
372 | }
373 | }
374 | function okxOnError(err, socketInfo) {
375 | console.log(err);
376 | }
377 | function okxOnClose(code, msg, socketInfo) {
378 | // This is where you should end up after 60 seconds
379 | console.log('Code: ', code, ' Message: ', msg);
380 | }
381 |
382 | // start it up
383 | startSocket(okxSocketConfig)
384 |
385 |
--------------------------------------------------------------------------------
/Examples/OKX-WebSocket-Template/package-lock.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "okx-websocket-template",
3 | "version": "1.0.0",
4 | "lockfileVersion": 2,
5 | "requires": true,
6 | "packages": {
7 | "": {
8 | "name": "okx-websocket-template",
9 | "version": "1.0.0",
10 | "license": "ISC",
11 | "dependencies": {
12 | "@compendiumfi/pendax": "^1.1.3"
13 | }
14 | },
15 | "node_modules/@compendiumfi/pendax": {
16 | "version": "1.1.3",
17 | "resolved": "https://registry.npmjs.org/@compendiumfi/pendax/-/pendax-1.1.3.tgz",
18 | "integrity": "sha512-hT5rDYx8yPrnzTudoW6M8JFXxpjZ/5+EsySDcIF3hMrWcnIolGgYtPDv91qahlGqMlYz55jh4AhanDlA79IskA==",
19 | "dependencies": {
20 | "axios": "^0.27.2",
21 | "base64-js": "^1.5.1",
22 | "crypto-js": "^4.1.1",
23 | "dateformat": "^5.0.3",
24 | "dotenv": "^16.0.1",
25 | "lodash": "^4.17.21",
26 | "short-unique-id": "^4.4.4",
27 | "uuidv4": "^6.2.13",
28 | "ws": "^8.7.0"
29 | }
30 | },
31 | "node_modules/@types/uuid": {
32 | "version": "8.3.4",
33 | "resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-8.3.4.tgz",
34 | "integrity": "sha512-c/I8ZRb51j+pYGAu5CrFMRxqZ2ke4y2grEBO5AUjgSkSk+qT2Ea+OdWElz/OiMf5MNpn2b17kuVBwZLQJXzihw=="
35 | },
36 | "node_modules/asynckit": {
37 | "version": "0.4.0",
38 | "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
39 | "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q=="
40 | },
41 | "node_modules/axios": {
42 | "version": "0.27.2",
43 | "resolved": "https://registry.npmjs.org/axios/-/axios-0.27.2.tgz",
44 | "integrity": "sha512-t+yRIyySRTp/wua5xEr+z1q60QmLq8ABsS5O9Me1AsE5dfKqgnCFzwiCZZ/cGNd1lq4/7akDWMxdhVlucjmnOQ==",
45 | "dependencies": {
46 | "follow-redirects": "^1.14.9",
47 | "form-data": "^4.0.0"
48 | }
49 | },
50 | "node_modules/base64-js": {
51 | "version": "1.5.1",
52 | "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz",
53 | "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==",
54 | "funding": [
55 | {
56 | "type": "github",
57 | "url": "https://github.com/sponsors/feross"
58 | },
59 | {
60 | "type": "patreon",
61 | "url": "https://www.patreon.com/feross"
62 | },
63 | {
64 | "type": "consulting",
65 | "url": "https://feross.org/support"
66 | }
67 | ]
68 | },
69 | "node_modules/combined-stream": {
70 | "version": "1.0.8",
71 | "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz",
72 | "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==",
73 | "dependencies": {
74 | "delayed-stream": "~1.0.0"
75 | },
76 | "engines": {
77 | "node": ">= 0.8"
78 | }
79 | },
80 | "node_modules/crypto-js": {
81 | "version": "4.1.1",
82 | "resolved": "https://registry.npmjs.org/crypto-js/-/crypto-js-4.1.1.tgz",
83 | "integrity": "sha512-o2JlM7ydqd3Qk9CA0L4NL6mTzU2sdx96a+oOfPu8Mkl/PK51vSyoi8/rQ8NknZtk44vq15lmhAj9CIAGwgeWKw=="
84 | },
85 | "node_modules/dateformat": {
86 | "version": "5.0.3",
87 | "resolved": "https://registry.npmjs.org/dateformat/-/dateformat-5.0.3.tgz",
88 | "integrity": "sha512-Kvr6HmPXUMerlLcLF+Pwq3K7apHpYmGDVqrxcDasBg86UcKeTSNWbEzU8bwdXnxnR44FtMhJAxI4Bov6Y/KUfA==",
89 | "engines": {
90 | "node": ">=12.20"
91 | }
92 | },
93 | "node_modules/delayed-stream": {
94 | "version": "1.0.0",
95 | "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
96 | "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==",
97 | "engines": {
98 | "node": ">=0.4.0"
99 | }
100 | },
101 | "node_modules/dotenv": {
102 | "version": "16.0.3",
103 | "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.0.3.tgz",
104 | "integrity": "sha512-7GO6HghkA5fYG9TYnNxi14/7K9f5occMlp3zXAuSxn7CKCxt9xbNWG7yF8hTCSUchlfWSe3uLmlPfigevRItzQ==",
105 | "engines": {
106 | "node": ">=12"
107 | }
108 | },
109 | "node_modules/follow-redirects": {
110 | "version": "1.15.2",
111 | "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.2.tgz",
112 | "integrity": "sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA==",
113 | "funding": [
114 | {
115 | "type": "individual",
116 | "url": "https://github.com/sponsors/RubenVerborgh"
117 | }
118 | ],
119 | "engines": {
120 | "node": ">=4.0"
121 | },
122 | "peerDependenciesMeta": {
123 | "debug": {
124 | "optional": true
125 | }
126 | }
127 | },
128 | "node_modules/form-data": {
129 | "version": "4.0.0",
130 | "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz",
131 | "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==",
132 | "dependencies": {
133 | "asynckit": "^0.4.0",
134 | "combined-stream": "^1.0.8",
135 | "mime-types": "^2.1.12"
136 | },
137 | "engines": {
138 | "node": ">= 6"
139 | }
140 | },
141 | "node_modules/lodash": {
142 | "version": "4.17.21",
143 | "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz",
144 | "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg=="
145 | },
146 | "node_modules/mime-db": {
147 | "version": "1.52.0",
148 | "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz",
149 | "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==",
150 | "engines": {
151 | "node": ">= 0.6"
152 | }
153 | },
154 | "node_modules/mime-types": {
155 | "version": "2.1.35",
156 | "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz",
157 | "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==",
158 | "dependencies": {
159 | "mime-db": "1.52.0"
160 | },
161 | "engines": {
162 | "node": ">= 0.6"
163 | }
164 | },
165 | "node_modules/short-unique-id": {
166 | "version": "4.4.4",
167 | "resolved": "https://registry.npmjs.org/short-unique-id/-/short-unique-id-4.4.4.tgz",
168 | "integrity": "sha512-oLF1NCmtbiTWl2SqdXZQbo5KM1b7axdp0RgQLq8qCBBLoq+o3A5wmLrNM6bZIh54/a8BJ3l69kTXuxwZ+XCYuw==",
169 | "bin": {
170 | "short-unique-id": "bin/short-unique-id",
171 | "suid": "bin/short-unique-id"
172 | }
173 | },
174 | "node_modules/uuid": {
175 | "version": "8.3.2",
176 | "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz",
177 | "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==",
178 | "bin": {
179 | "uuid": "dist/bin/uuid"
180 | }
181 | },
182 | "node_modules/uuidv4": {
183 | "version": "6.2.13",
184 | "resolved": "https://registry.npmjs.org/uuidv4/-/uuidv4-6.2.13.tgz",
185 | "integrity": "sha512-AXyzMjazYB3ovL3q051VLH06Ixj//Knx7QnUSi1T//Ie3io6CpsPu9nVMOx5MoLWh6xV0B9J0hIaxungxXUbPQ==",
186 | "dependencies": {
187 | "@types/uuid": "8.3.4",
188 | "uuid": "8.3.2"
189 | }
190 | },
191 | "node_modules/ws": {
192 | "version": "8.11.0",
193 | "resolved": "https://registry.npmjs.org/ws/-/ws-8.11.0.tgz",
194 | "integrity": "sha512-HPG3wQd9sNQoT9xHyNCXoDUa+Xw/VevmY9FoHyQ+g+rrMn4j6FB4np7Z0OhdTgjx6MgQLK7jwSy1YecU1+4Asg==",
195 | "engines": {
196 | "node": ">=10.0.0"
197 | },
198 | "peerDependencies": {
199 | "bufferutil": "^4.0.1",
200 | "utf-8-validate": "^5.0.2"
201 | },
202 | "peerDependenciesMeta": {
203 | "bufferutil": {
204 | "optional": true
205 | },
206 | "utf-8-validate": {
207 | "optional": true
208 | }
209 | }
210 | }
211 | },
212 | "dependencies": {
213 | "@compendiumfi/pendax": {
214 | "version": "1.1.3",
215 | "resolved": "https://registry.npmjs.org/@compendiumfi/pendax/-/pendax-1.1.3.tgz",
216 | "integrity": "sha512-hT5rDYx8yPrnzTudoW6M8JFXxpjZ/5+EsySDcIF3hMrWcnIolGgYtPDv91qahlGqMlYz55jh4AhanDlA79IskA==",
217 | "requires": {
218 | "axios": "^0.27.2",
219 | "base64-js": "^1.5.1",
220 | "crypto-js": "^4.1.1",
221 | "dateformat": "^5.0.3",
222 | "dotenv": "^16.0.1",
223 | "lodash": "^4.17.21",
224 | "short-unique-id": "^4.4.4",
225 | "uuidv4": "^6.2.13",
226 | "ws": "^8.7.0"
227 | }
228 | },
229 | "@types/uuid": {
230 | "version": "8.3.4",
231 | "resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-8.3.4.tgz",
232 | "integrity": "sha512-c/I8ZRb51j+pYGAu5CrFMRxqZ2ke4y2grEBO5AUjgSkSk+qT2Ea+OdWElz/OiMf5MNpn2b17kuVBwZLQJXzihw=="
233 | },
234 | "asynckit": {
235 | "version": "0.4.0",
236 | "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
237 | "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q=="
238 | },
239 | "axios": {
240 | "version": "0.27.2",
241 | "resolved": "https://registry.npmjs.org/axios/-/axios-0.27.2.tgz",
242 | "integrity": "sha512-t+yRIyySRTp/wua5xEr+z1q60QmLq8ABsS5O9Me1AsE5dfKqgnCFzwiCZZ/cGNd1lq4/7akDWMxdhVlucjmnOQ==",
243 | "requires": {
244 | "follow-redirects": "^1.14.9",
245 | "form-data": "^4.0.0"
246 | }
247 | },
248 | "base64-js": {
249 | "version": "1.5.1",
250 | "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz",
251 | "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA=="
252 | },
253 | "combined-stream": {
254 | "version": "1.0.8",
255 | "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz",
256 | "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==",
257 | "requires": {
258 | "delayed-stream": "~1.0.0"
259 | }
260 | },
261 | "crypto-js": {
262 | "version": "4.1.1",
263 | "resolved": "https://registry.npmjs.org/crypto-js/-/crypto-js-4.1.1.tgz",
264 | "integrity": "sha512-o2JlM7ydqd3Qk9CA0L4NL6mTzU2sdx96a+oOfPu8Mkl/PK51vSyoi8/rQ8NknZtk44vq15lmhAj9CIAGwgeWKw=="
265 | },
266 | "dateformat": {
267 | "version": "5.0.3",
268 | "resolved": "https://registry.npmjs.org/dateformat/-/dateformat-5.0.3.tgz",
269 | "integrity": "sha512-Kvr6HmPXUMerlLcLF+Pwq3K7apHpYmGDVqrxcDasBg86UcKeTSNWbEzU8bwdXnxnR44FtMhJAxI4Bov6Y/KUfA=="
270 | },
271 | "delayed-stream": {
272 | "version": "1.0.0",
273 | "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
274 | "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ=="
275 | },
276 | "dotenv": {
277 | "version": "16.0.3",
278 | "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.0.3.tgz",
279 | "integrity": "sha512-7GO6HghkA5fYG9TYnNxi14/7K9f5occMlp3zXAuSxn7CKCxt9xbNWG7yF8hTCSUchlfWSe3uLmlPfigevRItzQ=="
280 | },
281 | "follow-redirects": {
282 | "version": "1.15.2",
283 | "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.2.tgz",
284 | "integrity": "sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA=="
285 | },
286 | "form-data": {
287 | "version": "4.0.0",
288 | "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz",
289 | "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==",
290 | "requires": {
291 | "asynckit": "^0.4.0",
292 | "combined-stream": "^1.0.8",
293 | "mime-types": "^2.1.12"
294 | }
295 | },
296 | "lodash": {
297 | "version": "4.17.21",
298 | "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz",
299 | "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg=="
300 | },
301 | "mime-db": {
302 | "version": "1.52.0",
303 | "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz",
304 | "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg=="
305 | },
306 | "mime-types": {
307 | "version": "2.1.35",
308 | "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz",
309 | "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==",
310 | "requires": {
311 | "mime-db": "1.52.0"
312 | }
313 | },
314 | "short-unique-id": {
315 | "version": "4.4.4",
316 | "resolved": "https://registry.npmjs.org/short-unique-id/-/short-unique-id-4.4.4.tgz",
317 | "integrity": "sha512-oLF1NCmtbiTWl2SqdXZQbo5KM1b7axdp0RgQLq8qCBBLoq+o3A5wmLrNM6bZIh54/a8BJ3l69kTXuxwZ+XCYuw=="
318 | },
319 | "uuid": {
320 | "version": "8.3.2",
321 | "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz",
322 | "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg=="
323 | },
324 | "uuidv4": {
325 | "version": "6.2.13",
326 | "resolved": "https://registry.npmjs.org/uuidv4/-/uuidv4-6.2.13.tgz",
327 | "integrity": "sha512-AXyzMjazYB3ovL3q051VLH06Ixj//Knx7QnUSi1T//Ie3io6CpsPu9nVMOx5MoLWh6xV0B9J0hIaxungxXUbPQ==",
328 | "requires": {
329 | "@types/uuid": "8.3.4",
330 | "uuid": "8.3.2"
331 | }
332 | },
333 | "ws": {
334 | "version": "8.11.0",
335 | "resolved": "https://registry.npmjs.org/ws/-/ws-8.11.0.tgz",
336 | "integrity": "sha512-HPG3wQd9sNQoT9xHyNCXoDUa+Xw/VevmY9FoHyQ+g+rrMn4j6FB4np7Z0OhdTgjx6MgQLK7jwSy1YecU1+4Asg==",
337 | "requires": {}
338 | }
339 | }
340 | }
341 |
--------------------------------------------------------------------------------
/Examples/OKX-WebSocket-Template/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "okx-websocket-template",
3 | "version": "1.0.0",
4 | "description": "https://github.com/CompendiumFi/PENDAX-SDK",
5 | "main": "index.js",
6 | "type": "module",
7 | "scripts": {
8 | "test": "echo \"Error: no test specified\" && exit 1"
9 | },
10 | "keywords": [],
11 | "author": "traderjoe155",
12 | "license": "ISC",
13 | "dependencies": {
14 | "@compendiumfi/pendax": "^1.1.3"
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # PENDAX SOFTWARE DEVELOPMENT KIT (SDK)
2 |
3 | [](https://www.npmjs.com/package/@compendiumfi/pendax)  
4 |
5 | Javascript SDK for trading on cryptocurrency exchanges like OKX, Bybit, Bitget, MEXC, and more. Supports API data feeds and WebSocket. Built and maintained by the team at [Compendium](https://compendium.finance).
6 |
7 | ### [Installation](#installation) · [Features](#features) · [Documentation](#documentation) · [Examples](https://github.com/CompendiumFi/PENDAX-SDK/tree/main/Examples) · [Compendium](https://compendium.finance) · [Social](#social)
8 |
9 | PENDAX provides simplified exchange commands and interoperability. Our underlying high-frequency trading engine, PENDAX, is available for all developers, traders, financial analysts, and data scientists to build custom integrations on. It provides simple access to a variety of different use cases revolving around trading and data deployments.
10 |
11 | Visit The [Official PENDAX Website](https://pendax.pro).
12 | ## Installation
13 |
14 | Install The PENDAX SDK
15 |
16 | ```bash
17 | npm i @compendiumfi/pendax
18 | ```
19 |
20 | ## Current Supported Exchange Platforms
21 |
22 | | Logo | Exchange | PENDAX ID | Integration Status | Completion Level | Exchange Functions |
23 | | ---- | -------- | --------- | ------------------ | ---------------- | ------------------ |
24 | |  | [OKX (Formerly OKex)](https://www.okx.com/join/COMPENDIUM) | okx | 🟢 Integrated | 🟢🟢🟢🟢🟢 | [View Documentation](https://docs.compendium.finance/pendax/using-pendax-sdk/okx-functions) |
25 | |  | [Bitget](https://partner.bitget.com/bg/gacm69031670266129840) | bitget | 🟢 Integrated | 🟢🟢🟢🟢🟢 | [View Documentation](https://docs.compendium.finance/pendax/using-pendax-sdk/bitget-functions) |
26 | |  | [Blofin](https://partner.blofin.com/d/pendax) | blofin | 🟢 Integrated | 🟢🟢🟢🟢🟢 | [View Documentation](https://docs.compendium.finance/pendax/using-pendax-sdk/blofin-functions) |
27 | |  | [ByBit](https://www.bybit.com/en-US/invite?ref=LPMYYV) | bybit | 🟢 Integrated | 🟢🟢🟢🟢🟢 | [View Documentation](https://docs.compendium.finance/pendax/using-pendax-sdk/bybit-functions) |
28 | |  | [MEXC](https://www.mexc.com/register?inviteCode=1QRLp) | mexc | 🟢 Integrated | 🟢🟢🟢🟢🟢 | [View Documentation](https://docs.compendium.finance/pendax/using-pendax-sdk/mexc-functions) |
29 | |  | [Phemex](https://phemex.com/account/referral/invite-friends-entry?referralCode=JWAPJ5) | phemex | 🟢 Integrated | 🟢🟢🟢🟢🟢 | [View Documentation](https://docs.compendium.finance/pendax/using-pendax-sdk/phemex-functions) |
30 |
31 |
32 |
33 |
34 | ### Integration Roadmap Includes:
35 | Binance, Binance US, BitMex, Coinbase Pro, Crypto.com, Gate.io, HTX, Kraken, Kucoin, & More.
36 |
37 |
38 | ## Features
39 |
40 | For a complete capability and usage guidelines list please visit [PENDAX Usage Capabilities](https://docs.compendium.finance/pendax/pendax-capabilities).
41 | - Full Public and Private HTTP REST APIs for all supported platforms are integrated in an efficient manner for secondary deployment.
42 | - Aggregated commands are normalized between systems in the unified package making PENDAX extremely easy to integrate.
43 | - WebSocket and live data capabilities are included for all supported exchanges.
44 | - No subscription is needed for a "Professional" version of PENDAX. All commands and capabilities are free to use for all developers, traders, and integrators.
45 |
46 | PENDAX consists of both public and private integrations. A public integration can be accessed immediately after integration and provides unrestricted access to data for all supported exchange markets and integrations without an API key. Private integrations feature the ability to interact with an account or post trades and require authorization methods in order to complete command tasks. Users will need to create an API key on their selected exchange. Documentation within the Connect An Exchange Account segment can help you find how to create keys for each integrated exchange.
47 | ### Public API Capabilities
48 | Public APIs provide immediate and unrestricted access to the following commands without the need for authorization.
49 | - Fetch all market pairs from each integrated platform and exchange
50 | - Fetch tickers and trading parameters for all market pairs
51 | - Live and historical price feeds and exchange rates for each market pair
52 | - Live order book data for each market pair
53 | - Fetch trade history for all market pairs
54 | - Live and historical charting capabilities utilizing trading data
55 | - Other supported public endpoints for individual exchanges outside of this list
56 | > Capabilities may vary depending on the specific exchange integrations and their public access data feeds. Each exchange also has its own rate limiting guidelines that each user will be required to follow.
57 |
58 | ### Private API Capabilities
59 | Authorized commands provide the ability to interact with trade orders, account data, and more. As mentioned before you will need to generate an API key from the selected exchange and then insert the authorization parameters into PENDAX to access these commands.
60 | - Fetch and manage personal account information
61 | - Create and edit subaccounts associated with the main account on supported exchanges
62 | - Query account and subaccount balances
63 | - Ability to deposit and withdraw from accounts and subaccounts
64 | - Query current orders and historical personal orders
65 | - Fetch personal ledger history for accounts and subaccounts
66 | - Transfer funds between exchanges, accounts, and subaccounts
67 | - Trade with all supported order types on supported exchanges
68 | - Trade on all supported markets on supported exchanges
69 | - Open and manage WebSockets on supported exchanges
70 | > Capabilities may vary depending on the specific exchange integrations and their documented capabilities for authorized API calls. Each exchange also has its own rate limiting guidelines that each user will be required to follow.
71 |
72 | ### Example Use Cases
73 | Example programs posted by the Compendium team can be found in this Github Repo on the [Examples](https://github.com/CompendiumFi/PENDAX-SDK/tree/main/Examples) page. Other programs and use cases that can be built with PENDAX include the following:
74 | - Aggregated order books and optimal trade routing
75 | - Fully customized private trading bot strategy
76 | - Dollar-Cost Averaging strategies
77 | - Cryptocurrency arbitrage strategies
78 | - Grid-Trading Strategies
79 | - Market Making for Cryptocurrency exchange markets
80 | - Customized graphical interfaces for trading
81 | - New market or statistics notifications
82 | - Discord, Telegram, & Slack bots (or any other platform!)
83 | - Custom hardware macro development (Streamdeck, etc)
84 | - Compiling custom market charts
85 | - Portfolio management, Trade journals, and PnL% tracking
86 | - Data visualization and analytics interface
87 | - Custom low-latency command-line interfaces (CLI)
88 | - Advanced trading strategy indicators
89 | - Tax Reporting Software
90 |
91 | ## Documentation
92 |
93 | Full instructions for utilizing the PENDAX SDK and tooling can be found by visiting the [Documentation](https://docs.compendium.finance/pendax/using-pendax-sdk).
94 |
95 | Functions within the PENDAX SDK are separate into two main core groups: "Common Functions" and "Exchange Specific Functions".
96 |
97 | ### Common Functions
98 | Our team has done an excellent job in aggregating what we will refer to as "Common Functions" for a plethora of integrated platforms. Common functions are widely used calls available on different platforms and will work by just changing the "exchange" parameter and making edits to API credential layouts (depending on the selected exchange).
99 | Examples of common functions include calls like placing trade orders or getting account balances.
100 |
101 | By normalizing these commands developers can work in a more efficient manner while customizing integrations or code bases for multiple or different supported platforms.
102 |
103 | Documentation relating to "Common Functions" can be found [here](https://docs.compendium.finance/pendax/using-pendax-sdk).
104 |
105 | ### Exchange Specific Functions
106 | While there are a large variety of commonly normalized functions, there also may be a number of exchange-specific calls available for your selected platform. Many exchanges may include API features native to their interface and not found on other platforms so designating a common function is difficult in this manner.
107 | We recommend browsing both the Common Functions and exchange-specific documentation pages while creating any instrument with PENDAX to ensure your code is designed to interact with the SDK in the correct manner.
108 |
109 | To explore "Exchange Specific Functions" please visit the [Using The PENDAX SDK](https://docs.compendium.finance/pendax/using-pendax-sdk) page and select the supported exchange of your choice.
110 |
111 | ## FAQ
112 |
113 | #### Do I Need Coding Knowledge To Use This Product?
114 |
115 | Current PENDAX deployments are optimized for traders familiar with coding so we would recommend ample experience to utilize the full potential of our SDK and libraries. We have however focused on simplifying commands and other functions in comparison to comparable libraries so traders with less coding experience may find PENDAX easier to comprehend.
116 |
117 | #### What Coding Languages is PENDAX currently available for?
118 |
119 | PENDAX is currently available as a Javascript library and SDK. Hosted REST APIs will be available shortly for users more familiar with integrating traditional API setups.
120 |
121 | #### Are All Facets Of The PENDAX SDK Free To Use?
122 |
123 | Yes, the full PENDAX SDK is completely free to use for all developers, traders, analysts and more in accordance with our licensing and guidelines.
124 |
125 | #### Where Can I See The PENDAX SDK In Action Or Find Coding Examples?
126 |
127 | The best way to showcase capabilities is to build on PENDAX. We've released the new version of Compendium utilizing the latest PENDAX SDK capabilities. Our team will also add examples and code snippets to this repository to help speed up development.
128 |
129 | #### Can I Request New Exchange Or Additions To The SDK?
130 |
131 | The PENDAX tool suite is maintained by the team at Compendium. We are always looking for new community requests and additions that users would find useful to add in the next iterations. Join our Discord or email us at support@compendium.finance.
132 |
133 |
134 | ## Support & Contact Information
135 |
136 | The PENDAX SDK/API's are built and maintained by the team at Compendium (Formerly branded as Compendium.Fi / Compendium Finance). Developers can use one of the following official channels for support.
137 |
138 | - Discord: https://discord.gg/64r2xtqczs
139 | - Telegram: https://t.me/CompendiumFinanceOfficial
140 | - Email: Support@Compendium.Finance
141 |
142 | ### Social
143 |
144 | - Compendium Twitter: https://twitter.com/CompendiumFi
145 | - Pendax Twitter: https://twitter.com/PendaxPro
146 | - Youtube Channel: https://www.youtube.com/channel/UC749uyBnzwgTegYa0LkSj5w
147 |
148 |
149 |
150 | ## License Agreement
151 |
152 | [Click Here To View The License Agreement.](https://docs.compendium.finance/pendax/license-agreement) This Agreement becomes effective as of the date you first access, download, or use the API or SDK. This Agreement shall continue until terminated either by us or by you. Even after termination of this Agreement, certain provisions will survive, as discussed herein. This Agreement also incorporates Compendium's Terms of Service and Privacy Policy which terms shall also govern your use of the Service.
153 |
--------------------------------------------------------------------------------