ccxt 4.2.97 → 4.2.99
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 -3
- package/dist/ccxt.browser.js +85 -34
- package/dist/ccxt.browser.min.js +2 -2
- package/dist/cjs/ccxt.js +1 -1
- package/dist/cjs/src/coinbase.js +50 -21
- package/dist/cjs/src/kraken.js +5 -4
- package/dist/cjs/src/pro/coinbase.js +24 -3
- package/js/ccxt.d.ts +1 -1
- package/js/ccxt.js +1 -1
- package/js/src/coinbase.d.ts +1 -0
- package/js/src/coinbase.js +50 -21
- package/js/src/kraken.js +5 -4
- package/js/src/pro/coinbase.js +25 -4
- package/package.json +1 -1
package/dist/cjs/ccxt.js
CHANGED
|
@@ -182,7 +182,7 @@ var woo$1 = require('./src/pro/woo.js');
|
|
|
182
182
|
|
|
183
183
|
//-----------------------------------------------------------------------------
|
|
184
184
|
// this is updated by vss.js when building
|
|
185
|
-
const version = '4.2.
|
|
185
|
+
const version = '4.2.99';
|
|
186
186
|
Exchange["default"].ccxtVersion = version;
|
|
187
187
|
const exchanges = {
|
|
188
188
|
'ace': ace,
|
package/dist/cjs/src/coinbase.js
CHANGED
|
@@ -1458,6 +1458,7 @@ class coinbase extends coinbase$1 {
|
|
|
1458
1458
|
const contractExpiryType = this.safeString(futureProductDetails, 'contract_expiry_type');
|
|
1459
1459
|
const contractSize = this.safeNumber(futureProductDetails, 'contract_size');
|
|
1460
1460
|
const contractExpire = this.safeString(futureProductDetails, 'contract_expiry');
|
|
1461
|
+
const expireTimestamp = this.parse8601(contractExpire);
|
|
1461
1462
|
const isSwap = (contractExpiryType === 'PERPETUAL');
|
|
1462
1463
|
const baseId = this.safeString(futureProductDetails, 'contract_root_unit');
|
|
1463
1464
|
const quoteId = this.safeString(market, 'quote_currency_id');
|
|
@@ -1472,7 +1473,7 @@ class coinbase extends coinbase$1 {
|
|
|
1472
1473
|
}
|
|
1473
1474
|
else {
|
|
1474
1475
|
type = 'future';
|
|
1475
|
-
symbol = symbol + ':' + quote + '-' + this.yymmdd(
|
|
1476
|
+
symbol = symbol + ':' + quote + '-' + this.yymmdd(expireTimestamp);
|
|
1476
1477
|
}
|
|
1477
1478
|
const takerFeeRate = this.safeNumber(feeTier, 'taker_fee_rate');
|
|
1478
1479
|
const makerFeeRate = this.safeNumber(feeTier, 'maker_fee_rate');
|
|
@@ -1500,7 +1501,7 @@ class coinbase extends coinbase$1 {
|
|
|
1500
1501
|
'taker': taker,
|
|
1501
1502
|
'maker': maker,
|
|
1502
1503
|
'contractSize': contractSize,
|
|
1503
|
-
'expiry':
|
|
1504
|
+
'expiry': expireTimestamp,
|
|
1504
1505
|
'expiryDatetime': contractExpire,
|
|
1505
1506
|
'strike': undefined,
|
|
1506
1507
|
'optionType': undefined,
|
|
@@ -4287,6 +4288,33 @@ class coinbase extends coinbase$1 {
|
|
|
4287
4288
|
'takeProfitPrice': undefined,
|
|
4288
4289
|
});
|
|
4289
4290
|
}
|
|
4291
|
+
createAuthToken(seconds, method = undefined, url = undefined) {
|
|
4292
|
+
// it may not work for v2
|
|
4293
|
+
let uri = undefined;
|
|
4294
|
+
if (url !== undefined) {
|
|
4295
|
+
uri = method + ' ' + url.replace('https://', '');
|
|
4296
|
+
const quesPos = uri.indexOf('?');
|
|
4297
|
+
// Due to we use mb_strpos, quesPos could be false in php. In that case, the quesPos >= 0 is true
|
|
4298
|
+
// Also it's not possible that the question mark is first character, only check > 0 here.
|
|
4299
|
+
if (quesPos > 0) {
|
|
4300
|
+
uri = uri.slice(0, quesPos);
|
|
4301
|
+
}
|
|
4302
|
+
}
|
|
4303
|
+
const nonce = this.randomBytes(16);
|
|
4304
|
+
const request = {
|
|
4305
|
+
'aud': ['retail_rest_api_proxy'],
|
|
4306
|
+
'iss': 'coinbase-cloud',
|
|
4307
|
+
'nbf': seconds,
|
|
4308
|
+
'exp': seconds + 120,
|
|
4309
|
+
'sub': this.apiKey,
|
|
4310
|
+
'iat': seconds,
|
|
4311
|
+
};
|
|
4312
|
+
if (uri !== undefined) {
|
|
4313
|
+
request['uri'] = uri;
|
|
4314
|
+
}
|
|
4315
|
+
const token = rsa.jwt(request, this.encode(this.secret), sha256.sha256, false, { 'kid': this.apiKey, 'nonce': nonce, 'alg': 'ES256' });
|
|
4316
|
+
return token;
|
|
4317
|
+
}
|
|
4290
4318
|
sign(path, api = [], method = 'GET', params = {}, headers = undefined, body = undefined) {
|
|
4291
4319
|
const version = api[0];
|
|
4292
4320
|
const signed = api[1] === 'private';
|
|
@@ -4336,25 +4364,26 @@ class coinbase extends coinbase$1 {
|
|
|
4336
4364
|
if (this.apiKey.startsWith('-----BEGIN')) {
|
|
4337
4365
|
throw new errors.ArgumentsRequired(this.id + ' apiKey should contain the name (eg: organizations/3b910e93....) and not the public key');
|
|
4338
4366
|
}
|
|
4339
|
-
// it may not work for v2
|
|
4340
|
-
let uri = method + ' ' + url.replace('https://', '');
|
|
4341
|
-
const quesPos = uri.indexOf('?');
|
|
4342
|
-
// Due to we use mb_strpos, quesPos could be false in php. In that case, the quesPos >= 0 is true
|
|
4343
|
-
// Also it's not possible that the question mark is first character, only check > 0 here.
|
|
4344
|
-
if (quesPos > 0) {
|
|
4345
|
-
|
|
4346
|
-
}
|
|
4347
|
-
const nonce = this.randomBytes(16);
|
|
4348
|
-
const request = {
|
|
4349
|
-
|
|
4350
|
-
|
|
4351
|
-
|
|
4352
|
-
|
|
4353
|
-
|
|
4354
|
-
|
|
4355
|
-
|
|
4356
|
-
};
|
|
4357
|
-
const token =
|
|
4367
|
+
// // it may not work for v2
|
|
4368
|
+
// let uri = method + ' ' + url.replace ('https://', '');
|
|
4369
|
+
// const quesPos = uri.indexOf ('?');
|
|
4370
|
+
// // Due to we use mb_strpos, quesPos could be false in php. In that case, the quesPos >= 0 is true
|
|
4371
|
+
// // Also it's not possible that the question mark is first character, only check > 0 here.
|
|
4372
|
+
// if (quesPos > 0) {
|
|
4373
|
+
// uri = uri.slice (0, quesPos);
|
|
4374
|
+
// }
|
|
4375
|
+
// const nonce = this.randomBytes (16);
|
|
4376
|
+
// const request = {
|
|
4377
|
+
// 'aud': [ 'retail_rest_api_proxy' ],
|
|
4378
|
+
// 'iss': 'coinbase-cloud',
|
|
4379
|
+
// 'nbf': seconds,
|
|
4380
|
+
// 'exp': seconds + 120,
|
|
4381
|
+
// 'sub': this.apiKey,
|
|
4382
|
+
// 'uri': uri,
|
|
4383
|
+
// 'iat': seconds,
|
|
4384
|
+
// };
|
|
4385
|
+
const token = this.createAuthToken(seconds, method, url);
|
|
4386
|
+
// const token = jwt (request, this.encode (this.secret), sha256, false, { 'kid': this.apiKey, 'nonce': nonce, 'alg': 'ES256' });
|
|
4358
4387
|
authorizationString = 'Bearer ' + token;
|
|
4359
4388
|
}
|
|
4360
4389
|
else {
|
package/dist/cjs/src/kraken.js
CHANGED
|
@@ -1551,9 +1551,10 @@ class kraken extends kraken$1 {
|
|
|
1551
1551
|
// }
|
|
1552
1552
|
//
|
|
1553
1553
|
const description = this.safeDict(order, 'descr', {});
|
|
1554
|
+
const orderDescriptionObj = this.safeDict(order, 'descr'); // can be null
|
|
1554
1555
|
let orderDescription = undefined;
|
|
1555
|
-
if (
|
|
1556
|
-
orderDescription = this.safeString(
|
|
1556
|
+
if (orderDescriptionObj !== undefined) {
|
|
1557
|
+
orderDescription = this.safeString(orderDescriptionObj, 'order');
|
|
1557
1558
|
}
|
|
1558
1559
|
else {
|
|
1559
1560
|
orderDescription = this.safeString(order, 'descr');
|
|
@@ -1628,8 +1629,8 @@ class kraken extends kraken$1 {
|
|
|
1628
1629
|
}
|
|
1629
1630
|
const status = this.parseOrderStatus(this.safeString(order, 'status'));
|
|
1630
1631
|
let id = this.safeString2(order, 'id', 'txid');
|
|
1631
|
-
if ((id === undefined) || (id.
|
|
1632
|
-
const txid = this.
|
|
1632
|
+
if ((id === undefined) || (id.startsWith('['))) {
|
|
1633
|
+
const txid = this.safeList(order, 'txid');
|
|
1633
1634
|
id = this.safeString(txid, 0);
|
|
1634
1635
|
}
|
|
1635
1636
|
const clientOrderId = this.safeString(order, 'userref');
|
|
@@ -75,15 +75,36 @@ class coinbase extends coinbase$1 {
|
|
|
75
75
|
}
|
|
76
76
|
const url = this.urls['api']['ws'];
|
|
77
77
|
const timestamp = this.numberToString(this.seconds());
|
|
78
|
+
const isCloudAPiKey = (this.apiKey.indexOf('organizations/') >= 0) || (this.secret.startsWith('-----BEGIN'));
|
|
78
79
|
const auth = timestamp + name + productIds.join(',');
|
|
79
80
|
const subscribe = {
|
|
80
81
|
'type': 'subscribe',
|
|
81
82
|
'product_ids': productIds,
|
|
82
83
|
'channel': name,
|
|
83
|
-
'api_key': this.apiKey,
|
|
84
|
-
'timestamp': timestamp,
|
|
85
|
-
'signature': this.hmac(this.encode(auth), this.encode(this.secret), sha256
|
|
84
|
+
// 'api_key': this.apiKey,
|
|
85
|
+
// 'timestamp': timestamp,
|
|
86
|
+
// 'signature': this.hmac (this.encode (auth), this.encode (this.secret), sha256),
|
|
86
87
|
};
|
|
88
|
+
if (!isCloudAPiKey) {
|
|
89
|
+
subscribe['api_key'] = this.apiKey;
|
|
90
|
+
subscribe['timestamp'] = timestamp;
|
|
91
|
+
subscribe['signature'] = this.hmac(this.encode(auth), this.encode(this.secret), sha256.sha256);
|
|
92
|
+
}
|
|
93
|
+
else {
|
|
94
|
+
if (this.apiKey.startsWith('-----BEGIN')) {
|
|
95
|
+
throw new errors.ArgumentsRequired(this.id + ' apiKey should contain the name (eg: organizations/3b910e93....) and not the public key');
|
|
96
|
+
}
|
|
97
|
+
const currentToken = this.safeString(this.options, 'wsToken');
|
|
98
|
+
const tokenTimestamp = this.safeInteger(this.options, 'wsTokenTimestamp', 0);
|
|
99
|
+
const seconds = this.seconds();
|
|
100
|
+
if (currentToken === undefined || tokenTimestamp + 120 < seconds) {
|
|
101
|
+
// we should generate new token
|
|
102
|
+
const token = this.createAuthToken(seconds);
|
|
103
|
+
this.options['wsToken'] = token;
|
|
104
|
+
this.options['wsTokenTimestamp'] = seconds;
|
|
105
|
+
}
|
|
106
|
+
subscribe['jwt'] = this.safeString(this.options, 'wsToken');
|
|
107
|
+
}
|
|
87
108
|
return await this.watch(url, messageHash, subscribe, messageHash);
|
|
88
109
|
}
|
|
89
110
|
async watchTicker(symbol, params = {}) {
|
package/js/ccxt.d.ts
CHANGED
|
@@ -4,7 +4,7 @@ import * as functions from './src/base/functions.js';
|
|
|
4
4
|
import * as errors from './src/base/errors.js';
|
|
5
5
|
import type { Market, Trade, Fee, Ticker, OrderBook, Order, Transaction, Tickers, Currency, Balance, DepositAddress, WithdrawalResponse, DepositAddressResponse, OHLCV, Balances, PartialBalances, Dictionary, MinMax, Position, FundingRateHistory, Liquidation, FundingHistory, MarginMode, Greeks, Leverage, Leverages, Option, OptionChain, Conversion } from './src/base/types.js';
|
|
6
6
|
import { BaseError, ExchangeError, AuthenticationError, PermissionDenied, AccountNotEnabled, AccountSuspended, ArgumentsRequired, BadRequest, BadSymbol, OperationRejected, NoChange, MarginModeAlreadySet, BadResponse, NullResponse, InsufficientFunds, InvalidAddress, AddressPending, InvalidOrder, OrderNotFound, OrderNotCached, CancelPending, OrderImmediatelyFillable, OrderNotFillable, DuplicateOrderId, ContractUnavailable, NotSupported, ProxyError, ExchangeClosedByUser, OperationFailed, NetworkError, DDoSProtection, RateLimitExceeded, ExchangeNotAvailable, OnMaintenance, InvalidNonce, RequestTimeout } from './src/base/errors.js';
|
|
7
|
-
declare const version = "4.2.
|
|
7
|
+
declare const version = "4.2.98";
|
|
8
8
|
import ace from './src/ace.js';
|
|
9
9
|
import alpaca from './src/alpaca.js';
|
|
10
10
|
import ascendex from './src/ascendex.js';
|
package/js/ccxt.js
CHANGED
|
@@ -38,7 +38,7 @@ import * as errors from './src/base/errors.js';
|
|
|
38
38
|
import { BaseError, ExchangeError, AuthenticationError, PermissionDenied, AccountNotEnabled, AccountSuspended, ArgumentsRequired, BadRequest, BadSymbol, OperationRejected, NoChange, MarginModeAlreadySet, BadResponse, NullResponse, InsufficientFunds, InvalidAddress, AddressPending, InvalidOrder, OrderNotFound, OrderNotCached, CancelPending, OrderImmediatelyFillable, OrderNotFillable, DuplicateOrderId, ContractUnavailable, NotSupported, ProxyError, ExchangeClosedByUser, OperationFailed, NetworkError, DDoSProtection, RateLimitExceeded, ExchangeNotAvailable, OnMaintenance, InvalidNonce, RequestTimeout } from './src/base/errors.js';
|
|
39
39
|
//-----------------------------------------------------------------------------
|
|
40
40
|
// this is updated by vss.js when building
|
|
41
|
-
const version = '4.2.
|
|
41
|
+
const version = '4.2.99';
|
|
42
42
|
Exchange.ccxtVersion = version;
|
|
43
43
|
//-----------------------------------------------------------------------------
|
|
44
44
|
import ace from './src/ace.js';
|
package/js/src/coinbase.d.ts
CHANGED
|
@@ -108,6 +108,7 @@ export default class coinbase extends Exchange {
|
|
|
108
108
|
fetchPositions(symbols?: Strings, params?: {}): Promise<import("./base/types.js").Position[]>;
|
|
109
109
|
fetchPosition(symbol: string, params?: {}): Promise<import("./base/types.js").Position>;
|
|
110
110
|
parsePosition(position: any, market?: Market): import("./base/types.js").Position;
|
|
111
|
+
createAuthToken(seconds: Int, method?: Str, url?: Str): string;
|
|
111
112
|
sign(path: any, api?: any[], method?: string, params?: {}, headers?: any, body?: any): {
|
|
112
113
|
url: string;
|
|
113
114
|
method: string;
|
package/js/src/coinbase.js
CHANGED
|
@@ -1461,6 +1461,7 @@ export default class coinbase extends Exchange {
|
|
|
1461
1461
|
const contractExpiryType = this.safeString(futureProductDetails, 'contract_expiry_type');
|
|
1462
1462
|
const contractSize = this.safeNumber(futureProductDetails, 'contract_size');
|
|
1463
1463
|
const contractExpire = this.safeString(futureProductDetails, 'contract_expiry');
|
|
1464
|
+
const expireTimestamp = this.parse8601(contractExpire);
|
|
1464
1465
|
const isSwap = (contractExpiryType === 'PERPETUAL');
|
|
1465
1466
|
const baseId = this.safeString(futureProductDetails, 'contract_root_unit');
|
|
1466
1467
|
const quoteId = this.safeString(market, 'quote_currency_id');
|
|
@@ -1475,7 +1476,7 @@ export default class coinbase extends Exchange {
|
|
|
1475
1476
|
}
|
|
1476
1477
|
else {
|
|
1477
1478
|
type = 'future';
|
|
1478
|
-
symbol = symbol + ':' + quote + '-' + this.yymmdd(
|
|
1479
|
+
symbol = symbol + ':' + quote + '-' + this.yymmdd(expireTimestamp);
|
|
1479
1480
|
}
|
|
1480
1481
|
const takerFeeRate = this.safeNumber(feeTier, 'taker_fee_rate');
|
|
1481
1482
|
const makerFeeRate = this.safeNumber(feeTier, 'maker_fee_rate');
|
|
@@ -1503,7 +1504,7 @@ export default class coinbase extends Exchange {
|
|
|
1503
1504
|
'taker': taker,
|
|
1504
1505
|
'maker': maker,
|
|
1505
1506
|
'contractSize': contractSize,
|
|
1506
|
-
'expiry':
|
|
1507
|
+
'expiry': expireTimestamp,
|
|
1507
1508
|
'expiryDatetime': contractExpire,
|
|
1508
1509
|
'strike': undefined,
|
|
1509
1510
|
'optionType': undefined,
|
|
@@ -4290,6 +4291,33 @@ export default class coinbase extends Exchange {
|
|
|
4290
4291
|
'takeProfitPrice': undefined,
|
|
4291
4292
|
});
|
|
4292
4293
|
}
|
|
4294
|
+
createAuthToken(seconds, method = undefined, url = undefined) {
|
|
4295
|
+
// it may not work for v2
|
|
4296
|
+
let uri = undefined;
|
|
4297
|
+
if (url !== undefined) {
|
|
4298
|
+
uri = method + ' ' + url.replace('https://', '');
|
|
4299
|
+
const quesPos = uri.indexOf('?');
|
|
4300
|
+
// Due to we use mb_strpos, quesPos could be false in php. In that case, the quesPos >= 0 is true
|
|
4301
|
+
// Also it's not possible that the question mark is first character, only check > 0 here.
|
|
4302
|
+
if (quesPos > 0) {
|
|
4303
|
+
uri = uri.slice(0, quesPos);
|
|
4304
|
+
}
|
|
4305
|
+
}
|
|
4306
|
+
const nonce = this.randomBytes(16);
|
|
4307
|
+
const request = {
|
|
4308
|
+
'aud': ['retail_rest_api_proxy'],
|
|
4309
|
+
'iss': 'coinbase-cloud',
|
|
4310
|
+
'nbf': seconds,
|
|
4311
|
+
'exp': seconds + 120,
|
|
4312
|
+
'sub': this.apiKey,
|
|
4313
|
+
'iat': seconds,
|
|
4314
|
+
};
|
|
4315
|
+
if (uri !== undefined) {
|
|
4316
|
+
request['uri'] = uri;
|
|
4317
|
+
}
|
|
4318
|
+
const token = jwt(request, this.encode(this.secret), sha256, false, { 'kid': this.apiKey, 'nonce': nonce, 'alg': 'ES256' });
|
|
4319
|
+
return token;
|
|
4320
|
+
}
|
|
4293
4321
|
sign(path, api = [], method = 'GET', params = {}, headers = undefined, body = undefined) {
|
|
4294
4322
|
const version = api[0];
|
|
4295
4323
|
const signed = api[1] === 'private';
|
|
@@ -4339,25 +4367,26 @@ export default class coinbase extends Exchange {
|
|
|
4339
4367
|
if (this.apiKey.startsWith('-----BEGIN')) {
|
|
4340
4368
|
throw new ArgumentsRequired(this.id + ' apiKey should contain the name (eg: organizations/3b910e93....) and not the public key');
|
|
4341
4369
|
}
|
|
4342
|
-
// it may not work for v2
|
|
4343
|
-
let uri = method + ' ' + url.replace('https://', '');
|
|
4344
|
-
const quesPos = uri.indexOf('?');
|
|
4345
|
-
// Due to we use mb_strpos, quesPos could be false in php. In that case, the quesPos >= 0 is true
|
|
4346
|
-
// Also it's not possible that the question mark is first character, only check > 0 here.
|
|
4347
|
-
if (quesPos > 0) {
|
|
4348
|
-
|
|
4349
|
-
}
|
|
4350
|
-
const nonce = this.randomBytes(16);
|
|
4351
|
-
const request = {
|
|
4352
|
-
|
|
4353
|
-
|
|
4354
|
-
|
|
4355
|
-
|
|
4356
|
-
|
|
4357
|
-
|
|
4358
|
-
|
|
4359
|
-
};
|
|
4360
|
-
const token =
|
|
4370
|
+
// // it may not work for v2
|
|
4371
|
+
// let uri = method + ' ' + url.replace ('https://', '');
|
|
4372
|
+
// const quesPos = uri.indexOf ('?');
|
|
4373
|
+
// // Due to we use mb_strpos, quesPos could be false in php. In that case, the quesPos >= 0 is true
|
|
4374
|
+
// // Also it's not possible that the question mark is first character, only check > 0 here.
|
|
4375
|
+
// if (quesPos > 0) {
|
|
4376
|
+
// uri = uri.slice (0, quesPos);
|
|
4377
|
+
// }
|
|
4378
|
+
// const nonce = this.randomBytes (16);
|
|
4379
|
+
// const request = {
|
|
4380
|
+
// 'aud': [ 'retail_rest_api_proxy' ],
|
|
4381
|
+
// 'iss': 'coinbase-cloud',
|
|
4382
|
+
// 'nbf': seconds,
|
|
4383
|
+
// 'exp': seconds + 120,
|
|
4384
|
+
// 'sub': this.apiKey,
|
|
4385
|
+
// 'uri': uri,
|
|
4386
|
+
// 'iat': seconds,
|
|
4387
|
+
// };
|
|
4388
|
+
const token = this.createAuthToken(seconds, method, url);
|
|
4389
|
+
// const token = jwt (request, this.encode (this.secret), sha256, false, { 'kid': this.apiKey, 'nonce': nonce, 'alg': 'ES256' });
|
|
4361
4390
|
authorizationString = 'Bearer ' + token;
|
|
4362
4391
|
}
|
|
4363
4392
|
else {
|
package/js/src/kraken.js
CHANGED
|
@@ -1554,9 +1554,10 @@ export default class kraken extends Exchange {
|
|
|
1554
1554
|
// }
|
|
1555
1555
|
//
|
|
1556
1556
|
const description = this.safeDict(order, 'descr', {});
|
|
1557
|
+
const orderDescriptionObj = this.safeDict(order, 'descr'); // can be null
|
|
1557
1558
|
let orderDescription = undefined;
|
|
1558
|
-
if (
|
|
1559
|
-
orderDescription = this.safeString(
|
|
1559
|
+
if (orderDescriptionObj !== undefined) {
|
|
1560
|
+
orderDescription = this.safeString(orderDescriptionObj, 'order');
|
|
1560
1561
|
}
|
|
1561
1562
|
else {
|
|
1562
1563
|
orderDescription = this.safeString(order, 'descr');
|
|
@@ -1631,8 +1632,8 @@ export default class kraken extends Exchange {
|
|
|
1631
1632
|
}
|
|
1632
1633
|
const status = this.parseOrderStatus(this.safeString(order, 'status'));
|
|
1633
1634
|
let id = this.safeString2(order, 'id', 'txid');
|
|
1634
|
-
if ((id === undefined) || (id.
|
|
1635
|
-
const txid = this.
|
|
1635
|
+
if ((id === undefined) || (id.startsWith('['))) {
|
|
1636
|
+
const txid = this.safeList(order, 'txid');
|
|
1636
1637
|
id = this.safeString(txid, 0);
|
|
1637
1638
|
}
|
|
1638
1639
|
const clientOrderId = this.safeString(order, 'userref');
|
package/js/src/pro/coinbase.js
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
|
|
7
7
|
// ---------------------------------------------------------------------------
|
|
8
8
|
import coinbaseRest from '../coinbase.js';
|
|
9
|
-
import { ExchangeError } from '../base/errors.js';
|
|
9
|
+
import { ArgumentsRequired, ExchangeError } from '../base/errors.js';
|
|
10
10
|
import { ArrayCacheBySymbolById } from '../base/ws/Cache.js';
|
|
11
11
|
import { sha256 } from '../static_dependencies/noble-hashes/sha256.js';
|
|
12
12
|
// ---------------------------------------------------------------------------
|
|
@@ -78,15 +78,36 @@ export default class coinbase extends coinbaseRest {
|
|
|
78
78
|
}
|
|
79
79
|
const url = this.urls['api']['ws'];
|
|
80
80
|
const timestamp = this.numberToString(this.seconds());
|
|
81
|
+
const isCloudAPiKey = (this.apiKey.indexOf('organizations/') >= 0) || (this.secret.startsWith('-----BEGIN'));
|
|
81
82
|
const auth = timestamp + name + productIds.join(',');
|
|
82
83
|
const subscribe = {
|
|
83
84
|
'type': 'subscribe',
|
|
84
85
|
'product_ids': productIds,
|
|
85
86
|
'channel': name,
|
|
86
|
-
'api_key': this.apiKey,
|
|
87
|
-
'timestamp': timestamp,
|
|
88
|
-
'signature': this.hmac(this.encode(auth), this.encode(this.secret), sha256),
|
|
87
|
+
// 'api_key': this.apiKey,
|
|
88
|
+
// 'timestamp': timestamp,
|
|
89
|
+
// 'signature': this.hmac (this.encode (auth), this.encode (this.secret), sha256),
|
|
89
90
|
};
|
|
91
|
+
if (!isCloudAPiKey) {
|
|
92
|
+
subscribe['api_key'] = this.apiKey;
|
|
93
|
+
subscribe['timestamp'] = timestamp;
|
|
94
|
+
subscribe['signature'] = this.hmac(this.encode(auth), this.encode(this.secret), sha256);
|
|
95
|
+
}
|
|
96
|
+
else {
|
|
97
|
+
if (this.apiKey.startsWith('-----BEGIN')) {
|
|
98
|
+
throw new ArgumentsRequired(this.id + ' apiKey should contain the name (eg: organizations/3b910e93....) and not the public key');
|
|
99
|
+
}
|
|
100
|
+
const currentToken = this.safeString(this.options, 'wsToken');
|
|
101
|
+
const tokenTimestamp = this.safeInteger(this.options, 'wsTokenTimestamp', 0);
|
|
102
|
+
const seconds = this.seconds();
|
|
103
|
+
if (currentToken === undefined || tokenTimestamp + 120 < seconds) {
|
|
104
|
+
// we should generate new token
|
|
105
|
+
const token = this.createAuthToken(seconds);
|
|
106
|
+
this.options['wsToken'] = token;
|
|
107
|
+
this.options['wsTokenTimestamp'] = seconds;
|
|
108
|
+
}
|
|
109
|
+
subscribe['jwt'] = this.safeString(this.options, 'wsToken');
|
|
110
|
+
}
|
|
90
111
|
return await this.watch(url, messageHash, subscribe, messageHash);
|
|
91
112
|
}
|
|
92
113
|
async watchTicker(symbol, params = {}) {
|
package/package.json
CHANGED