@bluefin-exchange/pro-sdk 1.13.0 → 2.0.0-beta.0

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 (51) hide show
  1. package/README.md +3 -2
  2. package/dist/esm/example.js +42 -43
  3. package/dist/esm/example.js.map +1 -1
  4. package/dist/esm/index.js +1 -17
  5. package/dist/esm/index.js.map +1 -1
  6. package/dist/esm/src/api.js +1095 -571
  7. package/dist/esm/src/api.js.map +1 -1
  8. package/dist/esm/src/base.js +7 -15
  9. package/dist/esm/src/base.js.map +1 -1
  10. package/dist/esm/src/common.js +12 -24
  11. package/dist/esm/src/common.js.map +1 -1
  12. package/dist/esm/src/configuration.js +1 -5
  13. package/dist/esm/src/configuration.js.map +1 -1
  14. package/dist/esm/src/index.js +6 -22
  15. package/dist/esm/src/index.js.map +1 -1
  16. package/dist/esm/src/request-signer.js +14 -19
  17. package/dist/esm/src/request-signer.js.map +1 -1
  18. package/dist/esm/src/sdk.js +42 -46
  19. package/dist/esm/src/sdk.js.map +1 -1
  20. package/dist/esm/src/utils.js +1 -4
  21. package/dist/esm/src/utils.js.map +1 -1
  22. package/dist/esm/src/websocket.js +5 -9
  23. package/dist/esm/src/websocket.js.map +1 -1
  24. package/dist/types/src/api.d.ts +607 -8
  25. package/dist/types/src/api.d.ts.map +1 -1
  26. package/dist/types/src/request-signer.d.ts +1 -1
  27. package/dist/types/src/sdk.d.ts +3 -2
  28. package/dist/types/src/sdk.d.ts.map +1 -1
  29. package/package.json +18 -13
  30. package/dist/cjs/example.js +0 -277
  31. package/dist/cjs/example.js.map +0 -1
  32. package/dist/cjs/index.js +0 -18
  33. package/dist/cjs/index.js.map +0 -1
  34. package/dist/cjs/src/api.js +0 -5170
  35. package/dist/cjs/src/api.js.map +0 -1
  36. package/dist/cjs/src/base.js +0 -69
  37. package/dist/cjs/src/base.js.map +0 -1
  38. package/dist/cjs/src/common.js +0 -162
  39. package/dist/cjs/src/common.js.map +0 -1
  40. package/dist/cjs/src/configuration.js +0 -45
  41. package/dist/cjs/src/configuration.js.map +0 -1
  42. package/dist/cjs/src/index.js +0 -23
  43. package/dist/cjs/src/index.js.map +0 -1
  44. package/dist/cjs/src/request-signer.js +0 -234
  45. package/dist/cjs/src/request-signer.js.map +0 -1
  46. package/dist/cjs/src/sdk.js +0 -863
  47. package/dist/cjs/src/sdk.js.map +0 -1
  48. package/dist/cjs/src/utils.js +0 -10
  49. package/dist/cjs/src/utils.js.map +0 -1
  50. package/dist/cjs/src/websocket.js +0 -159
  51. package/dist/cjs/src/websocket.js.map +0 -1
@@ -1,863 +0,0 @@
1
- "use strict";
2
- var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
- function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
- return new (P || (P = Promise))(function (resolve, reject) {
5
- function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
- function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
- function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
- step((generator = generator.apply(thisArg, _arguments || [])).next());
9
- });
10
- };
11
- var __importDefault = (this && this.__importDefault) || function (mod) {
12
- return (mod && mod.__esModule) ? mod : { "default": mod };
13
- };
14
- Object.defineProperty(exports, "__esModule", { value: true });
15
- exports.BluefinProSdk = void 0;
16
- const api_1 = require("./api");
17
- const configuration_1 = require("./configuration");
18
- const ws_1 = require("ws");
19
- const v3_1 = require("@firefly-exchange/library-sui/v3");
20
- const library_sui_1 = require("@firefly-exchange/library-sui");
21
- // RewardsDistributorInteractor for reward claiming
22
- const index_1 = require("@firefly-exchange/library-sui/index");
23
- const bcs_1 = require("@mysten/bcs");
24
- const axios_1 = __importDefault(require("axios"));
25
- // Enable HTTP/2 in Node.js environments for better performance
26
- // Only enable for Node.js specifically (not Bun, Deno, or browsers)
27
- // Axios HTTP/2 support is toggled via httpVersion in the http adapter
28
- if (typeof process !== 'undefined' &&
29
- process.versions &&
30
- process.versions.node) {
31
- axios_1.default.defaults.httpVersion = 2;
32
- }
33
- const environmentConfig = {
34
- mainnet: {
35
- authHost: 'https://auth.api.sui-prod.bluefin.io',
36
- apiHost: 'https://api.sui-prod.bluefin.io',
37
- tradeHost: 'https://trade.api.sui-prod.bluefin.io',
38
- marketWsHost: 'wss://stream.api.sui-prod.bluefin.io/ws/market',
39
- accountWsHost: 'wss://stream.api.sui-prod.bluefin.io/ws/account',
40
- },
41
- testnet: {
42
- authHost: 'https://auth.api.sui-staging.bluefin.io',
43
- apiHost: 'https://api.sui-staging.bluefin.io',
44
- tradeHost: 'https://trade.api.sui-staging.bluefin.io',
45
- marketWsHost: 'wss://stream.api.sui-staging.bluefin.io/ws/market',
46
- accountWsHost: 'wss://stream.api.sui-staging.bluefin.io/ws/account',
47
- },
48
- devnet: {
49
- authHost: 'https://auth.api.sui-dev.bluefin.io',
50
- apiHost: 'https://api.sui-dev.bluefin.io',
51
- tradeHost: 'https://trade.api.sui-dev.bluefin.io',
52
- marketWsHost: 'wss://stream.api.sui-dev.bluefin.io/ws/market',
53
- accountWsHost: 'wss://stream.api.sui-dev.bluefin.io/ws/account',
54
- },
55
- };
56
- var Services;
57
- (function (Services) {
58
- Services[Services["Account"] = 0] = "Account";
59
- Services[Services["Exchange"] = 1] = "Exchange";
60
- Services[Services["Rewards"] = 2] = "Rewards";
61
- Services[Services["Trade"] = 3] = "Trade";
62
- Services[Services["Auth"] = 4] = "Auth";
63
- Services[Services["MarketWebsocket"] = 5] = "MarketWebsocket";
64
- Services[Services["AccountWebsocket"] = 6] = "AccountWebsocket";
65
- })(Services || (Services = {}));
66
- class BluefinProSdk {
67
- constructor(bfSigner, environment = 'mainnet', suiClient, opts) {
68
- var _a, _b, _c, _d, _e, _f;
69
- this.bfSigner = bfSigner;
70
- this.environment = environment;
71
- this.suiClient = suiClient;
72
- this.configs = {};
73
- /**
74
- * @description
75
- * build gasless transaction payload bytes
76
- * @param tx transcation block
77
- * @returns string
78
- * */
79
- this.buildGaslessTxPayloadBytes = (txb) => __awaiter(this, void 0, void 0, function* () {
80
- try {
81
- return yield library_sui_1.SuiBlocks.buildGaslessTxPayloadBytes(txb, this.suiClient);
82
- }
83
- catch (error) {
84
- throw new Error(error instanceof Error
85
- ? error.message
86
- : 'Build gasless tx payload bytes failed');
87
- }
88
- });
89
- this.currentAccountAddress = opts === null || opts === void 0 ? void 0 : opts.currentAccountAddress;
90
- this.isConnected = false;
91
- this.updateTokenTimeout = null;
92
- this.contractsConfig = undefined;
93
- this.tokenResponse = null;
94
- this.tokenSetAtSeconds = null;
95
- this.disableLoginPromptOnLogout = (_a = opts === null || opts === void 0 ? void 0 : opts.disableLoginPromptOnLogout) !== null && _a !== void 0 ? _a : false;
96
- this.onLogout = opts === null || opts === void 0 ? void 0 : opts.onLogout;
97
- this.onAccessTokenUpdate = opts === null || opts === void 0 ? void 0 : opts.onAccessTokenUpdate;
98
- this.isRefreshing = false;
99
- this.refreshTokenPromise = null;
100
- this.visibilityChangeHandler = undefined;
101
- this.onlineHandler = undefined;
102
- this.offlineHandler = undefined;
103
- // Initialize time offset based on provided currentTimeMs
104
- if ((opts === null || opts === void 0 ? void 0 : opts.currentTimeMs) !== undefined) {
105
- this.timeOffsetMs = opts.currentTimeMs - Date.now();
106
- }
107
- else {
108
- this.timeOffsetMs = 0;
109
- }
110
- if ((opts === null || opts === void 0 ? void 0 : opts.refreshToken) && (opts === null || opts === void 0 ? void 0 : opts.refreshTokenValidForSeconds)) {
111
- this.tokenResponse = {
112
- accessToken: '',
113
- accessTokenValidForSeconds: 0,
114
- refreshToken: opts.refreshToken,
115
- refreshTokenValidForSeconds: opts.refreshTokenValidForSeconds,
116
- };
117
- // Set timestamp when refresh token was provided
118
- this.tokenSetAtSeconds = Date.now() / 1000;
119
- }
120
- const defaultConfig = environmentConfig[this.environment];
121
- const basePaths = {
122
- authHost: (_b = opts === null || opts === void 0 ? void 0 : opts.authHost) !== null && _b !== void 0 ? _b : defaultConfig.authHost,
123
- apiHost: (_c = opts === null || opts === void 0 ? void 0 : opts.apiHost) !== null && _c !== void 0 ? _c : defaultConfig.apiHost,
124
- tradeHost: (_d = opts === null || opts === void 0 ? void 0 : opts.tradeHost) !== null && _d !== void 0 ? _d : defaultConfig.tradeHost,
125
- marketWsHost: (_e = opts === null || opts === void 0 ? void 0 : opts.marketWsHost) !== null && _e !== void 0 ? _e : defaultConfig.marketWsHost,
126
- accountWsHost: (_f = opts === null || opts === void 0 ? void 0 : opts.accountWsHost) !== null && _f !== void 0 ? _f : defaultConfig.accountWsHost,
127
- };
128
- const authApiConfig = new configuration_1.Configuration({
129
- basePath: basePaths.authHost,
130
- });
131
- this.configs[Services.Auth] = authApiConfig;
132
- this.authApi = new api_1.AuthApi(authApiConfig);
133
- const boundGetAccessToken = this.getAccessToken.bind(this);
134
- const exchangeApiConfig = new configuration_1.Configuration({
135
- basePath: basePaths.apiHost,
136
- });
137
- exchangeApiConfig.accessToken = boundGetAccessToken;
138
- this.configs[Services.Exchange] = exchangeApiConfig;
139
- this.exchangeDataApi = new api_1.ExchangeApi(exchangeApiConfig);
140
- const rewardsApiConfig = new configuration_1.Configuration({
141
- basePath: basePaths.apiHost,
142
- });
143
- rewardsApiConfig.accessToken = boundGetAccessToken;
144
- this.configs[Services.Rewards] = rewardsApiConfig;
145
- this.rewardsDataApi = new api_1.RewardsApi(rewardsApiConfig);
146
- const accountDataApiConfig = new configuration_1.Configuration({
147
- basePath: basePaths.apiHost,
148
- });
149
- accountDataApiConfig.accessToken = boundGetAccessToken;
150
- this.configs[Services.Account] = accountDataApiConfig;
151
- this.accountDataApi = new api_1.AccountDataApi(accountDataApiConfig);
152
- const tradeApiConfig = new configuration_1.Configuration({
153
- basePath: basePaths.tradeHost,
154
- });
155
- tradeApiConfig.accessToken = boundGetAccessToken;
156
- this.configs[Services.Trade] = tradeApiConfig;
157
- this.tradeApi = new api_1.TradeApi(tradeApiConfig);
158
- const marketWsConfig = new configuration_1.Configuration({
159
- basePath: basePaths.marketWsHost,
160
- });
161
- this.configs[Services.MarketWebsocket] = marketWsConfig;
162
- const accountWsConfig = new configuration_1.Configuration({
163
- basePath: basePaths.accountWsHost,
164
- });
165
- this.configs[Services.AccountWebsocket] = accountWsConfig;
166
- }
167
- createWallet() {
168
- const wallet = library_sui_1.Ed25519Keypair.generate();
169
- const signerKey = wallet.getSecretKey();
170
- const keyPair = (0, library_sui_1.decodeSuiPrivateKey)(signerKey);
171
- const publicAddress = wallet.toSuiAddress();
172
- return {
173
- privateKey: (0, bcs_1.toHex)(keyPair.secretKey),
174
- publicAddress,
175
- };
176
- }
177
- getTokenResponse() {
178
- return this.tokenResponse;
179
- }
180
- generateSalt() {
181
- return (Date.now() + Math.floor(Math.random() * 1000000)).toString();
182
- }
183
- getCurrentTimeMs() {
184
- return Date.now() + this.timeOffsetMs;
185
- }
186
- updateCurrentTimeMs(currentTimeMs) {
187
- this.timeOffsetMs = currentTimeMs - Date.now();
188
- }
189
- isRefreshTokenValid() {
190
- var _a;
191
- if (!((_a = this.tokenResponse) === null || _a === void 0 ? void 0 : _a.refreshToken) || !this.tokenSetAtSeconds) {
192
- return false;
193
- }
194
- const currentTimeSeconds = Date.now() / 1000;
195
- const refreshTokenExpiryTime = this.tokenSetAtSeconds + this.tokenResponse.refreshTokenValidForSeconds;
196
- // Add 60 second buffer to prevent using token right at expiry
197
- return currentTimeSeconds < refreshTokenExpiryTime - 60;
198
- }
199
- isAccessTokenExpired() {
200
- var _a;
201
- if (!((_a = this.tokenResponse) === null || _a === void 0 ? void 0 : _a.accessToken) || !this.tokenSetAtSeconds) {
202
- return true;
203
- }
204
- const currentTimeSeconds = Date.now() / 1000;
205
- const tokenLifetimeSeconds = this.tokenResponse.accessTokenValidForSeconds;
206
- const refreshAtLifetimePercentage = BluefinProSdk.TOKEN_REFRESH_THRESHOLD_PERCENTAGE;
207
- const refreshAtSeconds = this.tokenSetAtSeconds +
208
- tokenLifetimeSeconds * refreshAtLifetimePercentage;
209
- // Token is considered "expired" if we've passed the 80% lifetime mark
210
- return currentTimeSeconds >= refreshAtSeconds;
211
- }
212
- initializeTxBuilder() {
213
- return __awaiter(this, void 0, void 0, function* () {
214
- var _a, _b, _c, _d, _e, _f, _g, _h;
215
- this.txBuilder = new v3_1.TxBuilder({
216
- AdminCap: '',
217
- ExternalDataStore: ((_a = this.contractsConfig) === null || _a === void 0 ? void 0 : _a.edsId) || '',
218
- InternalDataStore: ((_b = this.contractsConfig) === null || _b === void 0 ? void 0 : _b.idsId) || '',
219
- Operators: {
220
- admin: ((_c = this.contractsConfig) === null || _c === void 0 ? void 0 : _c.operators.admin) || '',
221
- fee: ((_d = this.contractsConfig) === null || _d === void 0 ? void 0 : _d.operators.fee) || '',
222
- funding: ((_e = this.contractsConfig) === null || _e === void 0 ? void 0 : _e.operators.funding) || '',
223
- pruning: '',
224
- sequencer: ((_f = this.contractsConfig) === null || _f === void 0 ? void 0 : _f.operators.sequencer) || '',
225
- },
226
- Package: ((_g = this.contractsConfig) === null || _g === void 0 ? void 0 : _g.currentContractAddress) || '',
227
- Perpetuals: {},
228
- SupportedAssets: ((_h = this.assets) === null || _h === void 0 ? void 0 : _h.reduce((agg, x) => {
229
- agg[x.symbol] = Object.assign(Object.assign({}, x), { coinType: x.assetType });
230
- return agg;
231
- }, {})) || {},
232
- TreasuryCap: '',
233
- UpgradeCap: '',
234
- });
235
- });
236
- }
237
- initialize(options) {
238
- return __awaiter(this, void 0, void 0, function* () {
239
- this.initializeOptions = options;
240
- yield this.setContractsConfig();
241
- yield this.initializeTxBuilder();
242
- yield this.loginAndUpdateToken();
243
- this.setupVisibilityChangeListener();
244
- this.setupNetworkChangeListener();
245
- });
246
- }
247
- setContractsConfig() {
248
- return __awaiter(this, void 0, void 0, function* () {
249
- const response = yield this.exchangeDataApi.getExchangeInfo();
250
- this.contractsConfig = response.data.contractsConfig;
251
- this.assets = response.data.assets;
252
- });
253
- }
254
- loginAndUpdateToken() {
255
- return __awaiter(this, void 0, void 0, function* () {
256
- var _a;
257
- yield this.login();
258
- // Safety check - if login failed or logout was called, tokenResponse might be null
259
- if (!this.tokenResponse) {
260
- throw new Error('Login failed - no token response available');
261
- }
262
- this.isConnected = true;
263
- // Notify about token refresh
264
- (_a = this.onAccessTokenUpdate) === null || _a === void 0 ? void 0 : _a.call(this, this.tokenResponse.accessToken);
265
- // Schedule the next token refresh
266
- this.scheduleTokenRefresh();
267
- });
268
- }
269
- scheduleTokenRefresh() {
270
- // Clear any existing timeout
271
- if (this.updateTokenTimeout) {
272
- clearTimeout(this.updateTokenTimeout);
273
- this.updateTokenTimeout = null;
274
- }
275
- if (!this.isConnected || !this.tokenResponse || !this.tokenSetAtSeconds) {
276
- return;
277
- }
278
- // Calculate when to refresh: at 80% of token lifetime (or 20% before expiry)
279
- const currentTimeSeconds = Date.now() / 1000;
280
- const tokenLifetimeSeconds = this.tokenResponse.accessTokenValidForSeconds;
281
- const refreshAtLifetimePercentage = BluefinProSdk.TOKEN_REFRESH_THRESHOLD_PERCENTAGE;
282
- const refreshAtSeconds = this.tokenSetAtSeconds +
283
- tokenLifetimeSeconds * refreshAtLifetimePercentage;
284
- const millisecondsUntilRefresh = (refreshAtSeconds - currentTimeSeconds) * 1000;
285
- const delayMs = Math.max(millisecondsUntilRefresh, 0);
286
- console.log(`Scheduling token refresh in ${Math.round(delayMs / 1000)} seconds`);
287
- this.updateTokenTimeout = setTimeout(() => {
288
- this.refreshToken(true);
289
- }, delayMs);
290
- }
291
- setupVisibilityChangeListener() {
292
- // Only set up in browser environment
293
- if (typeof document !== 'undefined') {
294
- this.visibilityChangeHandler = () => {
295
- if (document.visibilityState === 'visible' && this.isConnected) {
296
- console.log('Page became visible, checking token status');
297
- this.handleVisible();
298
- }
299
- };
300
- document.addEventListener('visibilitychange', this.visibilityChangeHandler);
301
- }
302
- }
303
- setupNetworkChangeListener() {
304
- // Only set up in browser environment
305
- if (typeof navigator !== 'undefined' && 'onLine' in navigator) {
306
- window.addEventListener('online', this.handleOnline);
307
- window.addEventListener('offline', this.handleOffline);
308
- }
309
- }
310
- handleVisible() {
311
- return __awaiter(this, void 0, void 0, function* () {
312
- if (!this.tokenResponse || !this.tokenSetAtSeconds) {
313
- return;
314
- }
315
- this.refreshToken();
316
- });
317
- }
318
- handleOnline() {
319
- return __awaiter(this, void 0, void 0, function* () {
320
- if (!this.isConnected || !this.tokenResponse || !this.tokenSetAtSeconds) {
321
- return;
322
- }
323
- console.log('Network reconnected, resuming token refresh and checking token status');
324
- this.refreshToken(true);
325
- });
326
- }
327
- handleOffline() {
328
- if (this.updateTokenTimeout) {
329
- clearTimeout(this.updateTokenTimeout);
330
- this.updateTokenTimeout = null;
331
- }
332
- }
333
- login() {
334
- return __awaiter(this, void 0, void 0, function* () {
335
- var _a, _b, _c;
336
- console.log('Logging in to get the access token');
337
- if (!this.currentAccountAddress) {
338
- this.currentAccountAddress = this.bfSigner.getAddress();
339
- }
340
- console.log(`Logging in as ${this.currentAccountAddress}`);
341
- // Check if we have a valid refresh token first
342
- if (((_a = this.tokenResponse) === null || _a === void 0 ? void 0 : _a.refreshToken) && this.isRefreshTokenValid()) {
343
- try {
344
- console.log('Attempting to refresh token using refresh token');
345
- const response = yield this.authApi.authTokenRefreshPut({
346
- refreshToken: this.tokenResponse.refreshToken,
347
- });
348
- this.tokenResponse = response.data;
349
- this.tokenSetAtSeconds = Date.now() / 1000;
350
- console.log('Token refreshed successfully');
351
- return;
352
- }
353
- catch (e) {
354
- console.error('Error refreshing token:', e);
355
- // Throw the error to let the caller handle it
356
- throw new Error(`Token refresh failed: ${e instanceof Error ? e.message : 'Unknown error'}`);
357
- }
358
- }
359
- // Fallback to full login only if refresh token is not available or invalid
360
- // This should only happen during initial login or when refresh token is truly expired
361
- try {
362
- const loginRequest = {
363
- accountAddress: this.currentAccountAddress,
364
- signedAtMillis: this.getCurrentTimeMs(),
365
- audience: 'api',
366
- };
367
- const signature = yield this.bfSigner.signLoginRequest(loginRequest);
368
- const response = yield this.authApi.authV2TokenPost(signature, loginRequest, (_b = this.initializeOptions) === null || _b === void 0 ? void 0 : _b.refreshTokenValidForSeconds, (_c = this.initializeOptions) === null || _c === void 0 ? void 0 : _c.readOnly);
369
- this.tokenResponse = response.data;
370
- this.tokenSetAtSeconds = Date.now() / 1000;
371
- }
372
- catch (e) {
373
- console.error('Full login failed:', e);
374
- // If this fails and we're in a mode where logout should be disabled, don't logout
375
- if (this.disableLoginPromptOnLogout) {
376
- throw new Error(`Login failed: ${e instanceof Error ? e.message : 'Unknown error'}`);
377
- }
378
- // Otherwise, throw the error and let the caller decide
379
- throw new Error(`Login failed: ${e instanceof Error ? e.message : 'Unknown error'}`);
380
- }
381
- });
382
- }
383
- getAccessToken() {
384
- return __awaiter(this, void 0, void 0, function* () {
385
- if (!this.tokenResponse) {
386
- yield this.login();
387
- }
388
- if (!this.tokenResponse) {
389
- throw new Error('Unable to obtain access token');
390
- }
391
- if (this.isConnected) {
392
- if (this.isAccessTokenExpired()) {
393
- yield this.refreshToken();
394
- }
395
- }
396
- else if (this.isAccessTokenExpired()) {
397
- yield this.login();
398
- }
399
- if (!this.tokenResponse) {
400
- throw new Error('Access token unavailable after refresh');
401
- }
402
- return this.tokenResponse.accessToken;
403
- });
404
- }
405
- getOpenOrders(symbol) {
406
- return __awaiter(this, void 0, void 0, function* () {
407
- return yield this.tradeApi.getOpenOrders(symbol);
408
- });
409
- }
410
- getStandbyOrders(symbol) {
411
- return __awaiter(this, void 0, void 0, function* () {
412
- return yield this.tradeApi.getStandbyOrders(symbol);
413
- });
414
- }
415
- updateLeverage(symbol, leverageE9) {
416
- return __awaiter(this, void 0, void 0, function* () {
417
- if (!this.contractsConfig) {
418
- throw new Error('Missing contracts config');
419
- }
420
- const signedFields = {
421
- accountAddress: this.currentAccountAddress,
422
- idsId: this.contractsConfig.idsId,
423
- symbol: symbol,
424
- leverageE9: leverageE9,
425
- salt: this.generateSalt(),
426
- signedAtMillis: this.getCurrentTimeMs(),
427
- };
428
- const request = yield this.bfSigner.signLeverageUpdateRequest(signedFields);
429
- return yield this.tradeApi.putLeverageUpdate({
430
- signedFields,
431
- signature: request,
432
- });
433
- });
434
- }
435
- createOrder(params) {
436
- return __awaiter(this, void 0, void 0, function* () {
437
- var _a, _b;
438
- if (!this.contractsConfig) {
439
- throw new Error('Missing contracts config');
440
- }
441
- const signedFields = {
442
- symbol: params.symbol,
443
- idsId: this.contractsConfig.idsId,
444
- accountAddress: this.currentAccountAddress,
445
- priceE9: params.priceE9,
446
- quantityE9: params.quantityE9,
447
- side: params.side,
448
- leverageE9: params.leverageE9,
449
- isIsolated: params.isIsolated,
450
- salt: this.generateSalt(),
451
- expiresAtMillis: params.expiresAtMillis,
452
- signedAtMillis: this.getCurrentTimeMs(),
453
- };
454
- const signature = yield this.bfSigner.signOrderRequest(signedFields);
455
- const createOrderRequest = {
456
- signedFields,
457
- signature,
458
- clientOrderId: params.clientOrderId,
459
- type: params.type,
460
- reduceOnly: (_a = params.reduceOnly) !== null && _a !== void 0 ? _a : false,
461
- postOnly: (_b = params.postOnly) !== null && _b !== void 0 ? _b : false,
462
- timeInForce: params.timeInForce,
463
- triggerPriceE9: params.triggerPriceE9,
464
- selfTradePreventionType: params.selfTradePreventionType,
465
- twapConfig: params.twapConfig,
466
- };
467
- console.log('Creating order:', createOrderRequest);
468
- return yield this.tradeApi.postCreateOrder(createOrderRequest);
469
- });
470
- }
471
- cancelOrder(cancelOrdersRequest) {
472
- return __awaiter(this, void 0, void 0, function* () {
473
- return yield this.tradeApi.cancelOrders(cancelOrdersRequest);
474
- });
475
- }
476
- cancelStandbyOrder(cancelOrdersRequest) {
477
- return __awaiter(this, void 0, void 0, function* () {
478
- return yield this.tradeApi.cancelStandbyOrders(cancelOrdersRequest);
479
- });
480
- }
481
- withdraw(assetSymbol, amountE9) {
482
- return __awaiter(this, void 0, void 0, function* () {
483
- const exchangeInfo = yield this.exchangeDataApi.getExchangeInfo();
484
- const asset = exchangeInfo.data.assets.find((asset) => asset.symbol === assetSymbol);
485
- if (!asset) {
486
- throw new Error(`Asset ${assetSymbol} not found`);
487
- }
488
- if (!this.contractsConfig) {
489
- throw new Error('Missing contractsConfig');
490
- }
491
- const signedFields = {
492
- assetSymbol,
493
- edsId: this.contractsConfig.edsId,
494
- accountAddress: this.currentAccountAddress,
495
- amountE9,
496
- salt: this.generateSalt(),
497
- signedAtMillis: this.getCurrentTimeMs(),
498
- };
499
- const signature = yield this.bfSigner.signWithdrawRequest(signedFields);
500
- yield this.tradeApi.postWithdraw({
501
- signedFields,
502
- signature,
503
- });
504
- console.log('Withdraw request sent:', signedFields);
505
- });
506
- }
507
- authorizeAccount(accountAddress, alias) {
508
- return __awaiter(this, void 0, void 0, function* () {
509
- if (!this.contractsConfig) {
510
- throw new Error('Missing contractsConfig');
511
- }
512
- const signedFields = {
513
- accountAddress: this.currentAccountAddress,
514
- idsId: this.contractsConfig.idsId,
515
- authorizedAccountAddress: accountAddress,
516
- salt: this.generateSalt(),
517
- signedAtMillis: this.getCurrentTimeMs(),
518
- };
519
- const signature = yield this.bfSigner.signAccountAuthorizationRequest(signedFields, true);
520
- yield this.tradeApi.putAuthorizeAccount({
521
- signedFields,
522
- signature,
523
- alias,
524
- });
525
- console.log('Authorize account request sent:', signedFields);
526
- });
527
- }
528
- deauthorizeAccount(accountAddress) {
529
- return __awaiter(this, void 0, void 0, function* () {
530
- if (!this.contractsConfig) {
531
- throw new Error('Missing contractsConfig');
532
- }
533
- const signedFields = {
534
- accountAddress: this.currentAccountAddress,
535
- idsId: this.contractsConfig.idsId,
536
- authorizedAccountAddress: accountAddress,
537
- salt: this.generateSalt(),
538
- signedAtMillis: this.getCurrentTimeMs(),
539
- };
540
- const signature = yield this.bfSigner.signAccountAuthorizationRequest(signedFields, false);
541
- yield this.tradeApi.putDeauthorizeAccount({
542
- signedFields,
543
- signature,
544
- });
545
- console.log('Deauthorize account request sent:', signedFields);
546
- });
547
- }
548
- adjustIsolatedMargin(symbol, amountE9, add) {
549
- return __awaiter(this, void 0, void 0, function* () {
550
- if (!this.contractsConfig) {
551
- throw new Error('Missing contractsConfig');
552
- }
553
- const signedFields = {
554
- symbol,
555
- idsId: this.contractsConfig.idsId,
556
- accountAddress: this.currentAccountAddress,
557
- operation: add
558
- ? api_1.AdjustMarginOperation.Add
559
- : api_1.AdjustMarginOperation.Subtract,
560
- quantityE9: amountE9,
561
- salt: this.generateSalt(),
562
- signedAtMillis: this.getCurrentTimeMs(),
563
- };
564
- const signature = yield this.bfSigner.signAdjustIsolatedMarginRequest(signedFields);
565
- yield this.tradeApi.putAdjustIsolatedMargin({
566
- signedFields,
567
- signature,
568
- });
569
- console.log('Adjust isolated margin request sent:', signedFields);
570
- });
571
- }
572
- getAccountPreferences() {
573
- return __awaiter(this, void 0, void 0, function* () {
574
- return yield this.accountDataApi.getAccountPreferences();
575
- });
576
- }
577
- updateAccountPreferences(updateAccountPreferenceRequest) {
578
- return __awaiter(this, void 0, void 0, function* () {
579
- return yield this.accountDataApi.putAccountPreferences(updateAccountPreferenceRequest);
580
- });
581
- }
582
- // Update Account Group ID.
583
- // If groupID is null, it will remove the account from its group.
584
- // An account may only belong to 1 group at a time.
585
- updateAccountGroupId(updateAccountGroupIdRequest) {
586
- return __awaiter(this, void 0, void 0, function* () {
587
- return yield this.accountDataApi.patchAccountGroupID(updateAccountGroupIdRequest);
588
- });
589
- }
590
- deposit(amountE9, accountAddress, args) {
591
- return __awaiter(this, void 0, void 0, function* () {
592
- var _a, _b, _c;
593
- const assetSymbol = 'USDC';
594
- const txb = new library_sui_1.TransactionBlock();
595
- const assetType = (_b = (_a = this.assets) === null || _a === void 0 ? void 0 : _a.find((x) => x.symbol === assetSymbol)) === null || _b === void 0 ? void 0 : _b.assetType;
596
- if (!assetType) {
597
- throw new Error('Missing USDC asset type');
598
- }
599
- const [splitCoin, mergedCoin] = yield library_sui_1.CoinUtils.createCoinWithBalance(this.suiClient, txb, amountE9, assetType, this.currentAccountAddress || this.bfSigner.getAddress());
600
- //build the tx
601
- (_c = this.txBuilder) === null || _c === void 0 ? void 0 : _c.depositToAssetBank(assetSymbol, accountAddress ||
602
- this.currentAccountAddress ||
603
- this.bfSigner.getAddress(), amountE9, splitCoin, {
604
- txBlock: txb,
605
- });
606
- //add the transfer objects to the tx
607
- if (mergedCoin) {
608
- txb.transferObjects([mergedCoin], this.currentAccountAddress || this.bfSigner.getAddress());
609
- }
610
- if (splitCoin) {
611
- txb.transferObjects([splitCoin], this.currentAccountAddress || this.bfSigner.getAddress());
612
- }
613
- if (args && args.sponsored) {
614
- // build the gasless tx payload bytes
615
- const gaslessTxPayloadBytes = yield this.buildGaslessTxPayloadBytes(txb);
616
- try {
617
- const request = {
618
- txBytes: gaslessTxPayloadBytes,
619
- };
620
- // sponsor gas for the transaction
621
- const sponsorTxApiResponse = yield this.accountDataApi.sponsorTx(request);
622
- const txBlockFromBytes = library_sui_1.TransactionBlock.from(sponsorTxApiResponse.data.txBytes);
623
- // sign the transaction with user's wallet
624
- const userSignedTx = yield this.bfSigner.signTx(txBlockFromBytes, this.suiClient);
625
- // execute the transaction with both user's signature and sponsor's signature
626
- const response = yield this.bfSigner.executeSponsoredTx(userSignedTx.bytes, userSignedTx.signature, sponsorTxApiResponse.data.signature, this.suiClient);
627
- return response;
628
- }
629
- catch (error) {
630
- if (args === null || args === void 0 ? void 0 : args.fallbackToExecuteTx) {
631
- return this.bfSigner.executeTx(txb, this.suiClient);
632
- }
633
- throw error;
634
- }
635
- }
636
- else {
637
- return this.bfSigner.executeTx(txb, this.suiClient);
638
- }
639
- });
640
- }
641
- /**
642
- * Batch claim rewards on-chain using RewardsDistributorInteractor
643
- * @param payload Array of claim payloads with signatures
644
- * @returns Transaction response
645
- */
646
- batchClaimRewards(payload) {
647
- return __awaiter(this, void 0, void 0, function* () {
648
- // Get the rewards contract config from API (same as useClaimConfigQuery)
649
- const { data } = yield this.rewardsDataApi.getContractConfig();
650
- if (!data) {
651
- throw new Error('Failed to get rewards contract config');
652
- }
653
- // Get the signer from BluefinRequestSigner
654
- const signer = this.bfSigner.wallet;
655
- // Create the RewardsDistributorInteractor
656
- const interactor = new index_1.RewardsDistributorInteractor(this.suiClient, data, signer, this.bfSigner.isUIWallet());
657
- // Transform payload to the format expected by claimRewardsBatch
658
- const batch = payload.map(({ signature, sigPayload }) => ({
659
- signature,
660
- payload: sigPayload,
661
- }));
662
- // Execute the batch claim
663
- const tx = yield interactor.claimRewardsBatch(batch);
664
- return tx;
665
- });
666
- }
667
- refreshToken() {
668
- return __awaiter(this, arguments, void 0, function* (force = false) {
669
- if (!this.isConnected)
670
- return;
671
- // If already refreshing, wait for that operation to complete
672
- if (this.isRefreshing) {
673
- if (this.refreshTokenPromise) {
674
- yield this.refreshTokenPromise;
675
- }
676
- return;
677
- }
678
- // Check if token needs refreshing
679
- if (!this.isAccessTokenExpired() && !force) {
680
- return;
681
- }
682
- this.isRefreshing = true;
683
- try {
684
- this.refreshTokenPromise = this.performTokenRefresh();
685
- yield this.refreshTokenPromise;
686
- }
687
- finally {
688
- this.isRefreshing = false;
689
- this.refreshTokenPromise = null;
690
- }
691
- });
692
- }
693
- performTokenRefresh() {
694
- return __awaiter(this, void 0, void 0, function* () {
695
- const maxRetries = 5;
696
- let retryCount = 0;
697
- let consecutiveNetworkErrors = 0;
698
- while (retryCount < maxRetries) {
699
- try {
700
- console.log(`Refreshing token (attempt ${retryCount + 1}/${maxRetries})`);
701
- // Check if refresh token is still valid
702
- if (!this.isRefreshTokenValid()) {
703
- console.log('Refresh token is expired or invalid, triggering logout');
704
- this.logout();
705
- return;
706
- }
707
- yield this.loginAndUpdateToken();
708
- console.log('Token refreshed successfully');
709
- consecutiveNetworkErrors = 0; // Reset network error counter on success
710
- return;
711
- }
712
- catch (error) {
713
- retryCount++;
714
- console.error(`Error refreshing token (attempt ${retryCount}):`, error);
715
- // Check if this is a network error that we should retry
716
- const isNetworkError = error instanceof Error &&
717
- (error.message.includes('Network Error') ||
718
- error.message.includes('ERR_NETWORK') ||
719
- error.message.includes('ECONNREFUSED') ||
720
- error.message.includes('timeout') ||
721
- error.message.includes('ERR_NETWORK_IO_SUSPENDED'));
722
- // Check if we're currently offline (browser environment only)
723
- const isOffline = typeof navigator !== 'undefined' &&
724
- 'onLine' in navigator &&
725
- !navigator.onLine;
726
- if (isNetworkError) {
727
- consecutiveNetworkErrors++;
728
- }
729
- // If we're offline, don't count this as a "real" error - just wait for network to come back
730
- if (isOffline) {
731
- console.log('User is offline, will retry when network comes back online');
732
- return;
733
- }
734
- // If it's not a network error and login failed (tokenResponse is null), logout immediately
735
- if (!isNetworkError && !this.tokenResponse) {
736
- console.error('Login failed permanently, triggering logout');
737
- this.logout();
738
- return;
739
- }
740
- // If we've had too many consecutive network errors, pause refresh attempts temporarily
741
- if (consecutiveNetworkErrors >= 10) {
742
- // Clear any scheduled refresh
743
- if (this.updateTokenTimeout) {
744
- clearTimeout(this.updateTokenTimeout);
745
- this.updateTokenTimeout = null;
746
- }
747
- setTimeout(() => {
748
- console.log('Resuming token refresh attempts');
749
- this.scheduleTokenRefresh(); // Reschedule refresh when resuming
750
- }, 300000); // 5 minutes
751
- return;
752
- }
753
- if (retryCount >= maxRetries && !isOffline) {
754
- if (isNetworkError) {
755
- console.warn('Max retries reached due to network errors, will retry later');
756
- return; // Don't logout for network issues, just wait for next interval
757
- }
758
- else {
759
- console.error('Max retries reached, triggering logout');
760
- this.logout();
761
- return;
762
- }
763
- }
764
- // Exponential backoff: wait 2^retryCount seconds, but cap at 30 seconds for network errors
765
- const baseDelay = isNetworkError ? 5000 : 2000; // Start with 5s for network errors, 2s for others
766
- const delayMs = Math.min(baseDelay * Math.pow(2, retryCount - 1), 30000);
767
- console.log(`Retrying in ${delayMs}ms...`);
768
- yield new Promise((resolve) => setTimeout(resolve, delayMs));
769
- }
770
- }
771
- });
772
- }
773
- createAccountDataStreamListener(handler) {
774
- return __awaiter(this, void 0, void 0, function* () {
775
- const accessToken = yield this.getAccessToken();
776
- return new Promise((resolve) => {
777
- const ws = new ws_1.WebSocket(this.configs[Services.AccountWebsocket].basePath, {
778
- headers: {
779
- Authorization: `Bearer ${accessToken}`,
780
- },
781
- });
782
- ws.onmessage = (event) => __awaiter(this, void 0, void 0, function* () {
783
- yield handler(JSON.parse(event.data));
784
- });
785
- ws.on('open', () => {
786
- resolve(ws);
787
- });
788
- });
789
- });
790
- }
791
- createMarketDataStreamListener(handler) {
792
- return __awaiter(this, void 0, void 0, function* () {
793
- return new Promise((resolve) => {
794
- const ws = new ws_1.WebSocket(this.configs[Services.MarketWebsocket].basePath);
795
- ws.onmessage = (event) => __awaiter(this, void 0, void 0, function* () {
796
- yield handler(JSON.parse(event.data));
797
- });
798
- ws.on('open', () => {
799
- resolve(ws);
800
- });
801
- });
802
- });
803
- }
804
- logout() {
805
- return __awaiter(this, void 0, void 0, function* () {
806
- var _a;
807
- console.log('Logging out');
808
- if (this.updateTokenTimeout) {
809
- clearTimeout(this.updateTokenTimeout);
810
- this.updateTokenTimeout = null;
811
- }
812
- this.tokenResponse = null;
813
- this.tokenSetAtSeconds = null;
814
- this.isConnected = false;
815
- (_a = this.onLogout) === null || _a === void 0 ? void 0 : _a.call(this);
816
- });
817
- }
818
- dispose() {
819
- return __awaiter(this, void 0, void 0, function* () {
820
- console.log('Disposing SDK resources');
821
- if (this.updateTokenTimeout) {
822
- clearTimeout(this.updateTokenTimeout);
823
- this.updateTokenTimeout = null;
824
- }
825
- // Clean up visibility change listener
826
- if (this.visibilityChangeHandler && typeof document !== 'undefined') {
827
- document.removeEventListener('visibilitychange', this.visibilityChangeHandler);
828
- this.visibilityChangeHandler = undefined;
829
- }
830
- // Clean up network change listeners
831
- if (typeof window !== 'undefined') {
832
- if (this.onlineHandler) {
833
- window.removeEventListener('online', this.onlineHandler);
834
- this.onlineHandler = undefined;
835
- }
836
- if (this.offlineHandler) {
837
- window.removeEventListener('offline', this.offlineHandler);
838
- this.offlineHandler = undefined;
839
- }
840
- }
841
- this.isConnected = false;
842
- });
843
- }
844
- /**
845
- * @description
846
- * Get the transaction builder instance
847
- * @returns TxBuilder instance or undefined if not initialized
848
- */
849
- getTxBuilder() {
850
- return this.txBuilder;
851
- }
852
- /**
853
- * @description
854
- * Get the Bluefin signer instance
855
- * @returns IBluefinSigner instance
856
- */
857
- getSigner() {
858
- return this.bfSigner;
859
- }
860
- }
861
- exports.BluefinProSdk = BluefinProSdk;
862
- BluefinProSdk.TOKEN_REFRESH_THRESHOLD_PERCENTAGE = 0.8;
863
- //# sourceMappingURL=sdk.js.map