@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.
- package/README.md +3 -2
- package/dist/esm/example.js +42 -43
- package/dist/esm/example.js.map +1 -1
- package/dist/esm/index.js +1 -17
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/src/api.js +1095 -571
- package/dist/esm/src/api.js.map +1 -1
- package/dist/esm/src/base.js +7 -15
- package/dist/esm/src/base.js.map +1 -1
- package/dist/esm/src/common.js +12 -24
- package/dist/esm/src/common.js.map +1 -1
- package/dist/esm/src/configuration.js +1 -5
- package/dist/esm/src/configuration.js.map +1 -1
- package/dist/esm/src/index.js +6 -22
- package/dist/esm/src/index.js.map +1 -1
- package/dist/esm/src/request-signer.js +14 -19
- package/dist/esm/src/request-signer.js.map +1 -1
- package/dist/esm/src/sdk.js +42 -46
- package/dist/esm/src/sdk.js.map +1 -1
- package/dist/esm/src/utils.js +1 -4
- package/dist/esm/src/utils.js.map +1 -1
- package/dist/esm/src/websocket.js +5 -9
- package/dist/esm/src/websocket.js.map +1 -1
- package/dist/types/src/api.d.ts +607 -8
- package/dist/types/src/api.d.ts.map +1 -1
- package/dist/types/src/request-signer.d.ts +1 -1
- package/dist/types/src/sdk.d.ts +3 -2
- package/dist/types/src/sdk.d.ts.map +1 -1
- package/package.json +18 -13
- package/dist/cjs/example.js +0 -277
- package/dist/cjs/example.js.map +0 -1
- package/dist/cjs/index.js +0 -18
- package/dist/cjs/index.js.map +0 -1
- package/dist/cjs/src/api.js +0 -5170
- package/dist/cjs/src/api.js.map +0 -1
- package/dist/cjs/src/base.js +0 -69
- package/dist/cjs/src/base.js.map +0 -1
- package/dist/cjs/src/common.js +0 -162
- package/dist/cjs/src/common.js.map +0 -1
- package/dist/cjs/src/configuration.js +0 -45
- package/dist/cjs/src/configuration.js.map +0 -1
- package/dist/cjs/src/index.js +0 -23
- package/dist/cjs/src/index.js.map +0 -1
- package/dist/cjs/src/request-signer.js +0 -234
- package/dist/cjs/src/request-signer.js.map +0 -1
- package/dist/cjs/src/sdk.js +0 -863
- package/dist/cjs/src/sdk.js.map +0 -1
- package/dist/cjs/src/utils.js +0 -10
- package/dist/cjs/src/utils.js.map +0 -1
- package/dist/cjs/src/websocket.js +0 -159
- package/dist/cjs/src/websocket.js.map +0 -1
package/dist/cjs/src/sdk.js
DELETED
|
@@ -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
|