ccxt 4.2.95 → 4.2.97
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/CHANGELOG.md +51 -0
- package/README.md +3 -3
- package/dist/ccxt.browser.js +746 -148
- package/dist/ccxt.browser.min.js +2 -2
- package/dist/cjs/ccxt.js +1 -1
- package/dist/cjs/src/base/Exchange.js +18 -3
- package/dist/cjs/src/base/functions/crypto.js +15 -2
- package/dist/cjs/src/base/functions/rsa.js +2 -2
- package/dist/cjs/src/binance.js +11 -12
- package/dist/cjs/src/coinbase.js +621 -102
- package/dist/cjs/src/deribit.js +8 -3
- package/dist/cjs/src/gemini.js +29 -11
- package/dist/cjs/src/okx.js +2 -2
- package/dist/cjs/src/poloniexfutures.js +4 -1
- package/dist/cjs/src/pro/binance.js +10 -4
- package/dist/cjs/src/pro/coinbase.js +19 -4
- package/dist/cjs/src/pro/poloniexfutures.js +5 -1
- package/js/ccxt.d.ts +1 -1
- package/js/ccxt.js +1 -1
- package/js/src/abstract/coinbase.d.ts +1 -0
- package/js/src/base/Exchange.d.ts +1 -1
- package/js/src/base/Exchange.js +18 -3
- package/js/src/base/functions/crypto.d.ts +1 -1
- package/js/src/base/functions/crypto.js +15 -2
- package/js/src/base/functions/rsa.js +2 -2
- package/js/src/base/types.d.ts +1 -0
- package/js/src/base/ws/OrderBook.d.ts +1 -0
- package/js/src/base/ws/OrderBookSide.d.ts +2 -2
- package/js/src/binance.js +11 -12
- package/js/src/coinbase.d.ts +8 -1
- package/js/src/coinbase.js +622 -103
- package/js/src/deribit.js +8 -3
- package/js/src/gemini.js +29 -11
- package/js/src/okx.d.ts +1 -1
- package/js/src/okx.js +2 -2
- package/js/src/poloniexfutures.js +4 -1
- package/js/src/pro/binance.js +11 -5
- package/js/src/pro/coinbase.js +19 -4
- package/js/src/pro/poloniexfutures.js +6 -2
- package/package.json +1 -1
- package/skip-tests.json +163 -31
package/dist/cjs/src/coinbase.js
CHANGED
|
@@ -42,7 +42,7 @@ class coinbase extends coinbase$1 {
|
|
|
42
42
|
'cancelOrder': true,
|
|
43
43
|
'cancelOrders': true,
|
|
44
44
|
'closeAllPositions': false,
|
|
45
|
-
'closePosition':
|
|
45
|
+
'closePosition': true,
|
|
46
46
|
'createDepositAddress': true,
|
|
47
47
|
'createLimitBuyOrder': true,
|
|
48
48
|
'createLimitSellOrder': true,
|
|
@@ -97,9 +97,9 @@ class coinbase extends coinbase$1 {
|
|
|
97
97
|
'fetchOrder': true,
|
|
98
98
|
'fetchOrderBook': true,
|
|
99
99
|
'fetchOrders': true,
|
|
100
|
-
'fetchPosition':
|
|
100
|
+
'fetchPosition': true,
|
|
101
101
|
'fetchPositionMode': false,
|
|
102
|
-
'fetchPositions':
|
|
102
|
+
'fetchPositions': true,
|
|
103
103
|
'fetchPositionsRisk': false,
|
|
104
104
|
'fetchPremiumIndexOHLCV': false,
|
|
105
105
|
'fetchTicker': true,
|
|
@@ -242,6 +242,8 @@ class coinbase extends coinbase$1 {
|
|
|
242
242
|
'brokerage/convert/trade/{trade_id}': 1,
|
|
243
243
|
'brokerage/cfm/sweeps/schedule': 1,
|
|
244
244
|
'brokerage/intx/allocate': 1,
|
|
245
|
+
// futures
|
|
246
|
+
'brokerage/orders/close_position': 1,
|
|
245
247
|
},
|
|
246
248
|
'put': {
|
|
247
249
|
'brokerage/portfolios/{portfolio_uuid}': 1,
|
|
@@ -308,6 +310,8 @@ class coinbase extends coinbase$1 {
|
|
|
308
310
|
'internal_server_error': errors.ExchangeError,
|
|
309
311
|
'UNSUPPORTED_ORDER_CONFIGURATION': errors.BadRequest,
|
|
310
312
|
'INSUFFICIENT_FUND': errors.BadRequest,
|
|
313
|
+
'PERMISSION_DENIED': errors.PermissionDenied,
|
|
314
|
+
'INVALID_ARGUMENT': errors.BadRequest,
|
|
311
315
|
},
|
|
312
316
|
'broad': {
|
|
313
317
|
'request timestamp expired': errors.InvalidNonce,
|
|
@@ -533,6 +537,29 @@ class coinbase extends coinbase$1 {
|
|
|
533
537
|
}
|
|
534
538
|
return this.parseAccounts(accounts, params);
|
|
535
539
|
}
|
|
540
|
+
async fetchPortfolios(params = {}) {
|
|
541
|
+
/**
|
|
542
|
+
* @method
|
|
543
|
+
* @name coinbase#fetchPortfolios
|
|
544
|
+
* @description fetch all the portfolios
|
|
545
|
+
* @see https://docs.cloud.coinbase.com/advanced-trade-api/reference/retailbrokerageapi_getportfolios
|
|
546
|
+
* @param {object} [params] extra parameters specific to the exchange API endpoint
|
|
547
|
+
* @returns {object} a dictionary of [account structures]{@link https://docs.ccxt.com/#/?id=account-structure} indexed by the account type
|
|
548
|
+
*/
|
|
549
|
+
const response = await this.v3PrivateGetBrokeragePortfolios(params);
|
|
550
|
+
const portfolios = this.safeList(response, 'portfolios', []);
|
|
551
|
+
const result = [];
|
|
552
|
+
for (let i = 0; i < portfolios.length; i++) {
|
|
553
|
+
const portfolio = portfolios[i];
|
|
554
|
+
result.push({
|
|
555
|
+
'id': this.safeString(portfolio, 'uuid'),
|
|
556
|
+
'type': this.safeString(portfolio, 'type'),
|
|
557
|
+
'code': undefined,
|
|
558
|
+
'info': portfolio,
|
|
559
|
+
});
|
|
560
|
+
}
|
|
561
|
+
return result;
|
|
562
|
+
}
|
|
536
563
|
parseAccount(account) {
|
|
537
564
|
//
|
|
538
565
|
// fetchAccountsV2
|
|
@@ -1149,15 +1176,75 @@ class coinbase extends coinbase$1 {
|
|
|
1149
1176
|
return result;
|
|
1150
1177
|
}
|
|
1151
1178
|
async fetchMarketsV3(params = {}) {
|
|
1152
|
-
const
|
|
1179
|
+
const spotUnresolvedPromises = [
|
|
1153
1180
|
this.v3PrivateGetBrokerageProducts(params),
|
|
1154
1181
|
this.v3PrivateGetBrokerageTransactionSummary(params),
|
|
1155
1182
|
];
|
|
1156
|
-
|
|
1157
|
-
|
|
1158
|
-
|
|
1183
|
+
let unresolvedContractPromises = [];
|
|
1184
|
+
try {
|
|
1185
|
+
unresolvedContractPromises = [
|
|
1186
|
+
this.v3PrivateGetBrokerageProducts(this.extend(params, { 'product_type': 'FUTURE' })),
|
|
1187
|
+
this.v3PrivateGetBrokerageProducts(this.extend(params, { 'product_type': 'FUTURE', 'contract_expiry_type': 'PERPETUAL' })),
|
|
1188
|
+
this.v3PrivateGetBrokerageTransactionSummary(this.extend(params, { 'product_type': 'FUTURE' })),
|
|
1189
|
+
this.v3PrivateGetBrokerageTransactionSummary(this.extend(params, { 'product_type': 'FUTURE', 'contract_expiry_type': 'PERPETUAL' })),
|
|
1190
|
+
];
|
|
1191
|
+
}
|
|
1192
|
+
catch (e) {
|
|
1193
|
+
unresolvedContractPromises = []; // the sync version of ccxt won't have the promise.all line so the request is made here
|
|
1194
|
+
}
|
|
1195
|
+
const promises = await Promise.all(spotUnresolvedPromises);
|
|
1196
|
+
let contractPromises = undefined;
|
|
1197
|
+
try {
|
|
1198
|
+
contractPromises = await Promise.all(unresolvedContractPromises); // some users don't have access to contracts
|
|
1199
|
+
}
|
|
1200
|
+
catch (e) {
|
|
1201
|
+
contractPromises = [];
|
|
1202
|
+
}
|
|
1203
|
+
const spot = this.safeDict(promises, 0, {});
|
|
1204
|
+
const fees = this.safeDict(promises, 1, {});
|
|
1205
|
+
const expiringFutures = this.safeDict(contractPromises, 0, {});
|
|
1206
|
+
const perpetualFutures = this.safeDict(contractPromises, 1, {});
|
|
1207
|
+
const expiringFees = this.safeDict(contractPromises, 2, {});
|
|
1208
|
+
const perpetualFees = this.safeDict(contractPromises, 3, {});
|
|
1209
|
+
//
|
|
1210
|
+
// {
|
|
1211
|
+
// "total_volume": 0,
|
|
1212
|
+
// "total_fees": 0,
|
|
1213
|
+
// "fee_tier": {
|
|
1214
|
+
// "pricing_tier": "",
|
|
1215
|
+
// "usd_from": "0",
|
|
1216
|
+
// "usd_to": "10000",
|
|
1217
|
+
// "taker_fee_rate": "0.006",
|
|
1218
|
+
// "maker_fee_rate": "0.004"
|
|
1219
|
+
// },
|
|
1220
|
+
// "margin_rate": null,
|
|
1221
|
+
// "goods_and_services_tax": null,
|
|
1222
|
+
// "advanced_trade_only_volume": 0,
|
|
1223
|
+
// "advanced_trade_only_fees": 0,
|
|
1224
|
+
// "coinbase_pro_volume": 0,
|
|
1225
|
+
// "coinbase_pro_fees": 0
|
|
1226
|
+
// }
|
|
1227
|
+
//
|
|
1228
|
+
const feeTier = this.safeDict(fees, 'fee_tier', {});
|
|
1229
|
+
const expiringFeeTier = this.safeDict(expiringFees, 'fee_tier', {}); // fee tier null?
|
|
1230
|
+
const perpetualFeeTier = this.safeDict(perpetualFees, 'fee_tier', {}); // fee tier null?
|
|
1231
|
+
const data = this.safeList(spot, 'products', []);
|
|
1232
|
+
const result = [];
|
|
1233
|
+
for (let i = 0; i < data.length; i++) {
|
|
1234
|
+
result.push(this.parseSpotMarket(data[i], feeTier));
|
|
1235
|
+
}
|
|
1236
|
+
const futureData = this.safeList(expiringFutures, 'products', []);
|
|
1237
|
+
for (let i = 0; i < futureData.length; i++) {
|
|
1238
|
+
result.push(this.parseContractMarket(futureData[i], expiringFeeTier));
|
|
1239
|
+
}
|
|
1240
|
+
const perpetualData = this.safeList(perpetualFutures, 'products', []);
|
|
1241
|
+
for (let i = 0; i < perpetualData.length; i++) {
|
|
1242
|
+
result.push(this.parseContractMarket(perpetualData[i], perpetualFeeTier));
|
|
1243
|
+
}
|
|
1244
|
+
return result;
|
|
1245
|
+
}
|
|
1246
|
+
parseSpotMarket(market, feeTier) {
|
|
1159
1247
|
//
|
|
1160
|
-
// [
|
|
1161
1248
|
// {
|
|
1162
1249
|
// "product_id": "TONE-USD",
|
|
1163
1250
|
// "price": "0.01523",
|
|
@@ -1186,97 +1273,262 @@ class coinbase extends coinbase$1 {
|
|
|
1186
1273
|
// "base_currency_id": "TONE",
|
|
1187
1274
|
// "fcm_trading_session_details": null,
|
|
1188
1275
|
// "mid_market_price": ""
|
|
1189
|
-
// }
|
|
1190
|
-
// ...
|
|
1191
|
-
// ]
|
|
1276
|
+
// }
|
|
1192
1277
|
//
|
|
1193
|
-
|
|
1194
|
-
const
|
|
1278
|
+
const id = this.safeString(market, 'product_id');
|
|
1279
|
+
const baseId = this.safeString(market, 'base_currency_id');
|
|
1280
|
+
const quoteId = this.safeString(market, 'quote_currency_id');
|
|
1281
|
+
const base = this.safeCurrencyCode(baseId);
|
|
1282
|
+
const quote = this.safeCurrencyCode(quoteId);
|
|
1283
|
+
const marketType = this.safeStringLower(market, 'product_type');
|
|
1284
|
+
const tradingDisabled = this.safeBool(market, 'trading_disabled');
|
|
1285
|
+
const stablePairs = this.safeList(this.options, 'stablePairs', []);
|
|
1286
|
+
return this.safeMarketStructure({
|
|
1287
|
+
'id': id,
|
|
1288
|
+
'symbol': base + '/' + quote,
|
|
1289
|
+
'base': base,
|
|
1290
|
+
'quote': quote,
|
|
1291
|
+
'settle': undefined,
|
|
1292
|
+
'baseId': baseId,
|
|
1293
|
+
'quoteId': quoteId,
|
|
1294
|
+
'settleId': undefined,
|
|
1295
|
+
'type': marketType,
|
|
1296
|
+
'spot': (marketType === 'spot'),
|
|
1297
|
+
'margin': undefined,
|
|
1298
|
+
'swap': false,
|
|
1299
|
+
'future': false,
|
|
1300
|
+
'option': false,
|
|
1301
|
+
'active': !tradingDisabled,
|
|
1302
|
+
'contract': false,
|
|
1303
|
+
'linear': undefined,
|
|
1304
|
+
'inverse': undefined,
|
|
1305
|
+
'taker': this.inArray(id, stablePairs) ? 0.00001 : this.safeNumber(feeTier, 'taker_fee_rate'),
|
|
1306
|
+
'maker': this.inArray(id, stablePairs) ? 0.0 : this.safeNumber(feeTier, 'maker_fee_rate'),
|
|
1307
|
+
'contractSize': undefined,
|
|
1308
|
+
'expiry': undefined,
|
|
1309
|
+
'expiryDatetime': undefined,
|
|
1310
|
+
'strike': undefined,
|
|
1311
|
+
'optionType': undefined,
|
|
1312
|
+
'precision': {
|
|
1313
|
+
'amount': this.safeNumber(market, 'base_increment'),
|
|
1314
|
+
'price': this.safeNumber2(market, 'price_increment', 'quote_increment'),
|
|
1315
|
+
},
|
|
1316
|
+
'limits': {
|
|
1317
|
+
'leverage': {
|
|
1318
|
+
'min': undefined,
|
|
1319
|
+
'max': undefined,
|
|
1320
|
+
},
|
|
1321
|
+
'amount': {
|
|
1322
|
+
'min': this.safeNumber(market, 'base_min_size'),
|
|
1323
|
+
'max': this.safeNumber(market, 'base_max_size'),
|
|
1324
|
+
},
|
|
1325
|
+
'price': {
|
|
1326
|
+
'min': undefined,
|
|
1327
|
+
'max': undefined,
|
|
1328
|
+
},
|
|
1329
|
+
'cost': {
|
|
1330
|
+
'min': this.safeNumber(market, 'quote_min_size'),
|
|
1331
|
+
'max': this.safeNumber(market, 'quote_max_size'),
|
|
1332
|
+
},
|
|
1333
|
+
},
|
|
1334
|
+
'created': undefined,
|
|
1335
|
+
'info': market,
|
|
1336
|
+
});
|
|
1337
|
+
}
|
|
1338
|
+
parseContractMarket(market, feeTier) {
|
|
1339
|
+
// expiring
|
|
1195
1340
|
//
|
|
1196
|
-
//
|
|
1197
|
-
//
|
|
1198
|
-
//
|
|
1199
|
-
//
|
|
1200
|
-
//
|
|
1201
|
-
//
|
|
1202
|
-
//
|
|
1203
|
-
//
|
|
1204
|
-
//
|
|
1205
|
-
//
|
|
1206
|
-
//
|
|
1207
|
-
//
|
|
1208
|
-
//
|
|
1209
|
-
//
|
|
1210
|
-
//
|
|
1211
|
-
//
|
|
1212
|
-
//
|
|
1341
|
+
// {
|
|
1342
|
+
// "product_id":"BIT-26APR24-CDE",
|
|
1343
|
+
// "price":"71145",
|
|
1344
|
+
// "price_percentage_change_24h":"-2.36722931247427",
|
|
1345
|
+
// "volume_24h":"108549",
|
|
1346
|
+
// "volume_percentage_change_24h":"155.78255337197794",
|
|
1347
|
+
// "base_increment":"1",
|
|
1348
|
+
// "quote_increment":"0.01",
|
|
1349
|
+
// "quote_min_size":"0",
|
|
1350
|
+
// "quote_max_size":"100000000",
|
|
1351
|
+
// "base_min_size":"1",
|
|
1352
|
+
// "base_max_size":"100000000",
|
|
1353
|
+
// "base_name":"",
|
|
1354
|
+
// "quote_name":"US Dollar",
|
|
1355
|
+
// "watched":false,
|
|
1356
|
+
// "is_disabled":false,
|
|
1357
|
+
// "new":false,
|
|
1358
|
+
// "status":"",
|
|
1359
|
+
// "cancel_only":false,
|
|
1360
|
+
// "limit_only":false,
|
|
1361
|
+
// "post_only":false,
|
|
1362
|
+
// "trading_disabled":false,
|
|
1363
|
+
// "auction_mode":false,
|
|
1364
|
+
// "product_type":"FUTURE",
|
|
1365
|
+
// "quote_currency_id":"USD",
|
|
1366
|
+
// "base_currency_id":"",
|
|
1367
|
+
// "fcm_trading_session_details":{
|
|
1368
|
+
// "is_session_open":true,
|
|
1369
|
+
// "open_time":"2024-04-08T22:00:00Z",
|
|
1370
|
+
// "close_time":"2024-04-09T21:00:00Z"
|
|
1371
|
+
// },
|
|
1372
|
+
// "mid_market_price":"71105",
|
|
1373
|
+
// "alias":"",
|
|
1374
|
+
// "alias_to":[
|
|
1375
|
+
// ],
|
|
1376
|
+
// "base_display_symbol":"",
|
|
1377
|
+
// "quote_display_symbol":"USD",
|
|
1378
|
+
// "view_only":false,
|
|
1379
|
+
// "price_increment":"5",
|
|
1380
|
+
// "display_name":"BTC 26 APR 24",
|
|
1381
|
+
// "product_venue":"FCM",
|
|
1382
|
+
// "future_product_details":{
|
|
1383
|
+
// "venue":"cde",
|
|
1384
|
+
// "contract_code":"BIT",
|
|
1385
|
+
// "contract_expiry":"2024-04-26T15:00:00Z",
|
|
1386
|
+
// "contract_size":"0.01",
|
|
1387
|
+
// "contract_root_unit":"BTC",
|
|
1388
|
+
// "group_description":"Nano Bitcoin Futures",
|
|
1389
|
+
// "contract_expiry_timezone":"Europe/London",
|
|
1390
|
+
// "group_short_description":"Nano BTC",
|
|
1391
|
+
// "risk_managed_by":"MANAGED_BY_FCM",
|
|
1392
|
+
// "contract_expiry_type":"EXPIRING",
|
|
1393
|
+
// "contract_display_name":"BTC 26 APR 24"
|
|
1394
|
+
// }
|
|
1395
|
+
// }
|
|
1213
1396
|
//
|
|
1214
|
-
|
|
1215
|
-
|
|
1216
|
-
|
|
1217
|
-
|
|
1218
|
-
|
|
1219
|
-
|
|
1220
|
-
|
|
1221
|
-
|
|
1222
|
-
|
|
1223
|
-
|
|
1224
|
-
|
|
1225
|
-
|
|
1226
|
-
|
|
1227
|
-
|
|
1228
|
-
|
|
1229
|
-
|
|
1230
|
-
|
|
1231
|
-
|
|
1232
|
-
|
|
1233
|
-
|
|
1234
|
-
|
|
1235
|
-
|
|
1236
|
-
|
|
1237
|
-
|
|
1238
|
-
|
|
1239
|
-
|
|
1240
|
-
|
|
1241
|
-
|
|
1242
|
-
|
|
1243
|
-
|
|
1244
|
-
|
|
1245
|
-
|
|
1246
|
-
|
|
1247
|
-
|
|
1248
|
-
|
|
1249
|
-
|
|
1250
|
-
|
|
1251
|
-
|
|
1252
|
-
|
|
1253
|
-
|
|
1254
|
-
|
|
1255
|
-
|
|
1397
|
+
// perpetual
|
|
1398
|
+
//
|
|
1399
|
+
// {
|
|
1400
|
+
// "product_id":"ETH-PERP-INTX",
|
|
1401
|
+
// "price":"3630.98",
|
|
1402
|
+
// "price_percentage_change_24h":"0.65142426292038",
|
|
1403
|
+
// "volume_24h":"114020.1501",
|
|
1404
|
+
// "volume_percentage_change_24h":"63.33650787154869",
|
|
1405
|
+
// "base_increment":"0.0001",
|
|
1406
|
+
// "quote_increment":"0.01",
|
|
1407
|
+
// "quote_min_size":"10",
|
|
1408
|
+
// "quote_max_size":"50000000",
|
|
1409
|
+
// "base_min_size":"0.0001",
|
|
1410
|
+
// "base_max_size":"50000",
|
|
1411
|
+
// "base_name":"",
|
|
1412
|
+
// "quote_name":"USDC",
|
|
1413
|
+
// "watched":false,
|
|
1414
|
+
// "is_disabled":false,
|
|
1415
|
+
// "new":false,
|
|
1416
|
+
// "status":"",
|
|
1417
|
+
// "cancel_only":false,
|
|
1418
|
+
// "limit_only":false,
|
|
1419
|
+
// "post_only":false,
|
|
1420
|
+
// "trading_disabled":false,
|
|
1421
|
+
// "auction_mode":false,
|
|
1422
|
+
// "product_type":"FUTURE",
|
|
1423
|
+
// "quote_currency_id":"USDC",
|
|
1424
|
+
// "base_currency_id":"",
|
|
1425
|
+
// "fcm_trading_session_details":null,
|
|
1426
|
+
// "mid_market_price":"3630.975",
|
|
1427
|
+
// "alias":"",
|
|
1428
|
+
// "alias_to":[],
|
|
1429
|
+
// "base_display_symbol":"",
|
|
1430
|
+
// "quote_display_symbol":"USDC",
|
|
1431
|
+
// "view_only":false,
|
|
1432
|
+
// "price_increment":"0.01",
|
|
1433
|
+
// "display_name":"ETH PERP",
|
|
1434
|
+
// "product_venue":"INTX",
|
|
1435
|
+
// "future_product_details":{
|
|
1436
|
+
// "venue":"",
|
|
1437
|
+
// "contract_code":"ETH",
|
|
1438
|
+
// "contract_expiry":null,
|
|
1439
|
+
// "contract_size":"1",
|
|
1440
|
+
// "contract_root_unit":"ETH",
|
|
1441
|
+
// "group_description":"",
|
|
1442
|
+
// "contract_expiry_timezone":"",
|
|
1443
|
+
// "group_short_description":"",
|
|
1444
|
+
// "risk_managed_by":"MANAGED_BY_VENUE",
|
|
1445
|
+
// "contract_expiry_type":"PERPETUAL",
|
|
1446
|
+
// "perpetual_details":{
|
|
1447
|
+
// "open_interest":"0",
|
|
1448
|
+
// "funding_rate":"0.000016",
|
|
1449
|
+
// "funding_time":"2024-04-09T09:00:00.000008Z",
|
|
1450
|
+
// "max_leverage":"10"
|
|
1451
|
+
// },
|
|
1452
|
+
// "contract_display_name":"ETH PERPETUAL"
|
|
1453
|
+
// }
|
|
1454
|
+
// }
|
|
1455
|
+
//
|
|
1456
|
+
const id = this.safeString(market, 'product_id');
|
|
1457
|
+
const futureProductDetails = this.safeDict(market, 'future_product_details', {});
|
|
1458
|
+
const contractExpiryType = this.safeString(futureProductDetails, 'contract_expiry_type');
|
|
1459
|
+
const contractSize = this.safeNumber(futureProductDetails, 'contract_size');
|
|
1460
|
+
const contractExpire = this.safeString(futureProductDetails, 'contract_expiry');
|
|
1461
|
+
const isSwap = (contractExpiryType === 'PERPETUAL');
|
|
1462
|
+
const baseId = this.safeString(futureProductDetails, 'contract_root_unit');
|
|
1463
|
+
const quoteId = this.safeString(market, 'quote_currency_id');
|
|
1464
|
+
const base = this.safeCurrencyCode(baseId);
|
|
1465
|
+
const quote = this.safeCurrencyCode(quoteId);
|
|
1466
|
+
const tradingDisabled = this.safeBool(market, 'is_disabled');
|
|
1467
|
+
let symbol = base + '/' + quote;
|
|
1468
|
+
let type = undefined;
|
|
1469
|
+
if (isSwap) {
|
|
1470
|
+
type = 'swap';
|
|
1471
|
+
symbol = symbol + ':' + quote;
|
|
1472
|
+
}
|
|
1473
|
+
else {
|
|
1474
|
+
type = 'future';
|
|
1475
|
+
symbol = symbol + ':' + quote + '-' + this.yymmdd(contractExpire);
|
|
1476
|
+
}
|
|
1477
|
+
const takerFeeRate = this.safeNumber(feeTier, 'taker_fee_rate');
|
|
1478
|
+
const makerFeeRate = this.safeNumber(feeTier, 'maker_fee_rate');
|
|
1479
|
+
const taker = takerFeeRate ? takerFeeRate : this.parseNumber('0.06');
|
|
1480
|
+
const maker = makerFeeRate ? makerFeeRate : this.parseNumber('0.04');
|
|
1481
|
+
return this.safeMarketStructure({
|
|
1482
|
+
'id': id,
|
|
1483
|
+
'symbol': symbol,
|
|
1484
|
+
'base': base,
|
|
1485
|
+
'quote': quote,
|
|
1486
|
+
'settle': quote,
|
|
1487
|
+
'baseId': baseId,
|
|
1488
|
+
'quoteId': quoteId,
|
|
1489
|
+
'settleId': quoteId,
|
|
1490
|
+
'type': type,
|
|
1491
|
+
'spot': false,
|
|
1492
|
+
'margin': false,
|
|
1493
|
+
'swap': isSwap,
|
|
1494
|
+
'future': !isSwap,
|
|
1495
|
+
'option': false,
|
|
1496
|
+
'active': !tradingDisabled,
|
|
1497
|
+
'contract': true,
|
|
1498
|
+
'linear': true,
|
|
1499
|
+
'inverse': false,
|
|
1500
|
+
'taker': taker,
|
|
1501
|
+
'maker': maker,
|
|
1502
|
+
'contractSize': contractSize,
|
|
1503
|
+
'expiry': this.parse8601(contractExpire),
|
|
1504
|
+
'expiryDatetime': contractExpire,
|
|
1505
|
+
'strike': undefined,
|
|
1506
|
+
'optionType': undefined,
|
|
1507
|
+
'precision': {
|
|
1508
|
+
'amount': this.safeNumber(market, 'base_increment'),
|
|
1509
|
+
'price': this.safeNumber2(market, 'price_increment', 'quote_increment'),
|
|
1510
|
+
},
|
|
1511
|
+
'limits': {
|
|
1512
|
+
'leverage': {
|
|
1513
|
+
'min': undefined,
|
|
1514
|
+
'max': undefined,
|
|
1256
1515
|
},
|
|
1257
|
-
'
|
|
1258
|
-
'
|
|
1259
|
-
|
|
1260
|
-
'max': undefined,
|
|
1261
|
-
},
|
|
1262
|
-
'amount': {
|
|
1263
|
-
'min': this.safeNumber(market, 'base_min_size'),
|
|
1264
|
-
'max': this.safeNumber(market, 'base_max_size'),
|
|
1265
|
-
},
|
|
1266
|
-
'price': {
|
|
1267
|
-
'min': undefined,
|
|
1268
|
-
'max': undefined,
|
|
1269
|
-
},
|
|
1270
|
-
'cost': {
|
|
1271
|
-
'min': this.safeNumber(market, 'quote_min_size'),
|
|
1272
|
-
'max': this.safeNumber(market, 'quote_max_size'),
|
|
1273
|
-
},
|
|
1516
|
+
'amount': {
|
|
1517
|
+
'min': this.safeNumber(market, 'base_min_size'),
|
|
1518
|
+
'max': this.safeNumber(market, 'base_max_size'),
|
|
1274
1519
|
},
|
|
1275
|
-
'
|
|
1276
|
-
|
|
1277
|
-
|
|
1278
|
-
|
|
1279
|
-
|
|
1520
|
+
'price': {
|
|
1521
|
+
'min': undefined,
|
|
1522
|
+
'max': undefined,
|
|
1523
|
+
},
|
|
1524
|
+
'cost': {
|
|
1525
|
+
'min': this.safeNumber(market, 'quote_min_size'),
|
|
1526
|
+
'max': this.safeNumber(market, 'quote_max_size'),
|
|
1527
|
+
},
|
|
1528
|
+
},
|
|
1529
|
+
'created': undefined,
|
|
1530
|
+
'info': market,
|
|
1531
|
+
});
|
|
1280
1532
|
}
|
|
1281
1533
|
async fetchCurrenciesFromCache(params = {}) {
|
|
1282
1534
|
const options = this.safeDict(this.options, 'fetchCurrencies', {});
|
|
@@ -1783,19 +2035,24 @@ class coinbase extends coinbase$1 {
|
|
|
1783
2035
|
* @description query for balance and get the amount of funds available for trading or funds locked in orders
|
|
1784
2036
|
* @see https://docs.cloud.coinbase.com/advanced-trade-api/reference/retailbrokerageapi_getaccounts
|
|
1785
2037
|
* @see https://docs.cloud.coinbase.com/sign-in-with-coinbase/docs/api-accounts#list-accounts
|
|
2038
|
+
* @see https://docs.cloud.coinbase.com/advanced-trade-api/reference/retailbrokerageapi_getfcmbalancesummary
|
|
1786
2039
|
* @param {object} [params] extra parameters specific to the exchange API endpoint
|
|
1787
2040
|
* @param {boolean} [params.v3] default false, set true to use v3 api endpoint
|
|
1788
|
-
* @param {object} [params.type] "spot" (default) or "swap"
|
|
2041
|
+
* @param {object} [params.type] "spot" (default) or "swap" or "future"
|
|
1789
2042
|
* @returns {object} a [balance structure]{@link https://docs.ccxt.com/#/?id=balance-structure}
|
|
1790
2043
|
*/
|
|
1791
2044
|
await this.loadMarkets();
|
|
1792
2045
|
const request = {};
|
|
1793
2046
|
let response = undefined;
|
|
1794
2047
|
const isV3 = this.safeBool(params, 'v3', false);
|
|
1795
|
-
|
|
1796
|
-
|
|
2048
|
+
params = this.omit(params, ['v3']);
|
|
2049
|
+
let marketType = undefined;
|
|
2050
|
+
[marketType, params] = this.handleMarketTypeAndParams('fetchBalance', undefined, params);
|
|
1797
2051
|
const method = this.safeString(this.options, 'fetchBalance', 'v3PrivateGetBrokerageAccounts');
|
|
1798
|
-
if (
|
|
2052
|
+
if (marketType === 'future') {
|
|
2053
|
+
response = await this.v3PrivateGetBrokerageCfmBalanceSummary(this.extend(request, params));
|
|
2054
|
+
}
|
|
2055
|
+
else if ((isV3) || (method === 'v3PrivateGetBrokerageAccounts')) {
|
|
1799
2056
|
request['limit'] = 250;
|
|
1800
2057
|
response = await this.v3PrivateGetBrokerageAccounts(this.extend(request, params));
|
|
1801
2058
|
}
|
|
@@ -1874,7 +2131,7 @@ class coinbase extends coinbase$1 {
|
|
|
1874
2131
|
// "size": 9
|
|
1875
2132
|
// }
|
|
1876
2133
|
//
|
|
1877
|
-
params['type'] =
|
|
2134
|
+
params['type'] = marketType;
|
|
1878
2135
|
return this.parseCustomBalance(response, params);
|
|
1879
2136
|
}
|
|
1880
2137
|
async fetchLedger(code = undefined, since = undefined, limit = undefined, params = {}) {
|
|
@@ -2335,6 +2592,11 @@ class coinbase extends coinbase$1 {
|
|
|
2335
2592
|
* @param {string} [params.end_time] '2023-05-25T17:01:05.092Z' for 'GTD' orders
|
|
2336
2593
|
* @param {float} [params.cost] *spot market buy only* the quote quantity that can be used as an alternative for the amount
|
|
2337
2594
|
* @param {boolean} [params.preview] default to false, wether to use the test/preview endpoint or not
|
|
2595
|
+
* @param {float} [params.leverage] default to 1, the leverage to use for the order
|
|
2596
|
+
* @param {string} [params.marginMode] 'cross' or 'isolated'
|
|
2597
|
+
* @param {string} [params.retail_portfolio_id] portfolio uid
|
|
2598
|
+
* @param {boolean} [params.is_max] Used in conjunction with tradable_balance to indicate the user wants to use their entire tradable balance
|
|
2599
|
+
* @param {string} [params.tradable_balance] amount of tradable balance
|
|
2338
2600
|
* @returns {object} an [order structure]{@link https://docs.ccxt.com/#/?id=order-structure}
|
|
2339
2601
|
*/
|
|
2340
2602
|
await this.loadMarkets();
|
|
@@ -2445,7 +2707,7 @@ class coinbase extends coinbase$1 {
|
|
|
2445
2707
|
if (isStop || isStopLoss || isTakeProfit) {
|
|
2446
2708
|
throw new errors.NotSupported(this.id + ' createOrder() only stop limit orders are supported');
|
|
2447
2709
|
}
|
|
2448
|
-
if (side === 'buy') {
|
|
2710
|
+
if (market['spot'] && (side === 'buy')) {
|
|
2449
2711
|
let total = undefined;
|
|
2450
2712
|
let createMarketBuyOrderRequiresPrice = true;
|
|
2451
2713
|
[createMarketBuyOrderRequiresPrice, params] = this.handleOptionAndParams(params, 'createOrder', 'createMarketBuyOrderRequiresPrice', true);
|
|
@@ -2482,7 +2744,16 @@ class coinbase extends coinbase$1 {
|
|
|
2482
2744
|
};
|
|
2483
2745
|
}
|
|
2484
2746
|
}
|
|
2485
|
-
|
|
2747
|
+
const marginMode = this.safeString(params, 'marginMode');
|
|
2748
|
+
if (marginMode !== undefined) {
|
|
2749
|
+
if (marginMode === 'isolated') {
|
|
2750
|
+
request['margin_type'] = 'ISOLATED';
|
|
2751
|
+
}
|
|
2752
|
+
else if (marginMode === 'cross') {
|
|
2753
|
+
request['margin_type'] = 'CROSS';
|
|
2754
|
+
}
|
|
2755
|
+
}
|
|
2756
|
+
params = this.omit(params, ['timeInForce', 'triggerPrice', 'stopLossPrice', 'takeProfitPrice', 'stopPrice', 'stop_price', 'stopDirection', 'stop_direction', 'clientOrderId', 'postOnly', 'post_only', 'end_time', 'marginMode']);
|
|
2486
2757
|
const preview = this.safeBool2(params, 'preview', 'test', false);
|
|
2487
2758
|
let response = undefined;
|
|
2488
2759
|
if (preview) {
|
|
@@ -3770,6 +4041,252 @@ class coinbase extends coinbase$1 {
|
|
|
3770
4041
|
const data = this.safeDict(response, 'data', {});
|
|
3771
4042
|
return this.parseTransaction(data);
|
|
3772
4043
|
}
|
|
4044
|
+
async closePosition(symbol, side = undefined, params = {}) {
|
|
4045
|
+
/**
|
|
4046
|
+
* @method
|
|
4047
|
+
* @name coinbase#closePosition
|
|
4048
|
+
* @description *futures only* closes open positions for a market
|
|
4049
|
+
* @see https://coinbase-api.github.io/docs/#/en-us/swapV2/trade-api.html#One-Click%20Close%20All%20Positions
|
|
4050
|
+
* @param {string} symbol Unified CCXT market symbol
|
|
4051
|
+
* @param {string} [side] not used by coinbase
|
|
4052
|
+
* @param {object} [params] extra parameters specific to the coinbase api endpoint
|
|
4053
|
+
* @param {string} params.clientOrderId *mandatory* the client order id of the position to close
|
|
4054
|
+
* @param {float} [params.size] the size of the position to close, optional
|
|
4055
|
+
* @returns {object} an [order structure]{@link https://docs.ccxt.com/#/?id=order-structure}
|
|
4056
|
+
*/
|
|
4057
|
+
await this.loadMarkets();
|
|
4058
|
+
const market = this.market(symbol);
|
|
4059
|
+
if (!market['future']) {
|
|
4060
|
+
throw new errors.NotSupported(this.id + ' closePosition() only supported for futures markets');
|
|
4061
|
+
}
|
|
4062
|
+
const clientOrderId = this.safeString2(params, 'client_order_id', 'clientOrderId');
|
|
4063
|
+
params = this.omit(params, 'clientOrderId');
|
|
4064
|
+
const request = {
|
|
4065
|
+
'product_id': market['id'],
|
|
4066
|
+
};
|
|
4067
|
+
if (clientOrderId === undefined) {
|
|
4068
|
+
throw new errors.ArgumentsRequired(this.id + ' closePosition() requires a clientOrderId parameter');
|
|
4069
|
+
}
|
|
4070
|
+
request['client_order_id'] = clientOrderId;
|
|
4071
|
+
const response = await this.v3PrivatePostBrokerageOrdersClosePosition(this.extend(request, params));
|
|
4072
|
+
const order = this.safeDict(response, 'success_response', {});
|
|
4073
|
+
return this.parseOrder(order);
|
|
4074
|
+
}
|
|
4075
|
+
async fetchPositions(symbols = undefined, params = {}) {
|
|
4076
|
+
/**
|
|
4077
|
+
* @method
|
|
4078
|
+
* @name coinbase#fetchPositions
|
|
4079
|
+
* @description fetch all open positions
|
|
4080
|
+
* @see https://docs.cloud.coinbase.com/advanced-trade-api/reference/retailbrokerageapi_getfcmpositions
|
|
4081
|
+
* @see https://docs.cloud.coinbase.com/advanced-trade-api/reference/retailbrokerageapi_getintxpositions
|
|
4082
|
+
* @param {string[]} [symbols] list of unified market symbols
|
|
4083
|
+
* @param {object} [params] extra parameters specific to the exchange API endpoint
|
|
4084
|
+
* @param {string} [params.portfolio] the portfolio UUID to fetch positions for
|
|
4085
|
+
* @returns {object[]} a list of [position structure]{@link https://docs.ccxt.com/#/?id=position-structure}
|
|
4086
|
+
*/
|
|
4087
|
+
await this.loadMarkets();
|
|
4088
|
+
symbols = this.marketSymbols(symbols);
|
|
4089
|
+
let market = undefined;
|
|
4090
|
+
if (symbols !== undefined) {
|
|
4091
|
+
market = this.market(symbols[0]);
|
|
4092
|
+
}
|
|
4093
|
+
let type = undefined;
|
|
4094
|
+
[type, params] = this.handleMarketTypeAndParams('fetchPositions', market, params);
|
|
4095
|
+
let response = undefined;
|
|
4096
|
+
if (type === 'future') {
|
|
4097
|
+
response = await this.v3PrivateGetBrokerageCfmPositions(params);
|
|
4098
|
+
}
|
|
4099
|
+
else {
|
|
4100
|
+
let portfolio = undefined;
|
|
4101
|
+
[portfolio, params] = this.handleOptionAndParams(params, 'fetchPositions', 'portfolio');
|
|
4102
|
+
if (portfolio === undefined) {
|
|
4103
|
+
throw new errors.ArgumentsRequired(this.id + ' fetchPositions() requires a "portfolio" value in params (eg: dbcb91e7-2bc9-515), or set as exchange.options["portfolio"]. You can get a list of portfolios with fetchPortfolios()');
|
|
4104
|
+
}
|
|
4105
|
+
const request = {
|
|
4106
|
+
'portfolio_uuid': portfolio,
|
|
4107
|
+
};
|
|
4108
|
+
response = await this.v3PrivateGetBrokerageIntxPositionsPortfolioUuid(this.extend(request, params));
|
|
4109
|
+
}
|
|
4110
|
+
const positions = this.safeList(response, 'positions', []);
|
|
4111
|
+
return this.parsePositions(positions, symbols);
|
|
4112
|
+
}
|
|
4113
|
+
async fetchPosition(symbol, params = {}) {
|
|
4114
|
+
/**
|
|
4115
|
+
* @method
|
|
4116
|
+
* @name coinbase#fetchPosition
|
|
4117
|
+
* @description fetch data on a single open contract trade position
|
|
4118
|
+
* @see https://docs.cloud.coinbase.com/advanced-trade-api/reference/retailbrokerageapi_getintxposition
|
|
4119
|
+
* @see https://docs.cloud.coinbase.com/advanced-trade-api/reference/retailbrokerageapi_getfcmposition
|
|
4120
|
+
* @param {string} symbol unified market symbol of the market the position is held in, default is undefined
|
|
4121
|
+
* @param {object} [params] extra parameters specific to the exchange API endpoint
|
|
4122
|
+
* @param {string} [params.product_id] *futures only* the product id of the position to fetch, required for futures markets only
|
|
4123
|
+
* @param {string} [params.portfolio] *perpetual/swaps only* the portfolio UUID to fetch the position for, required for perpetual/swaps markets only
|
|
4124
|
+
* @returns {object} a [position structure]{@link https://docs.ccxt.com/#/?id=position-structure}
|
|
4125
|
+
*/
|
|
4126
|
+
await this.loadMarkets();
|
|
4127
|
+
const market = this.market(symbol);
|
|
4128
|
+
let response = undefined;
|
|
4129
|
+
if (market['future']) {
|
|
4130
|
+
const productId = this.safeString(market, 'product_id');
|
|
4131
|
+
if (productId === undefined) {
|
|
4132
|
+
throw new errors.ArgumentsRequired(this.id + ' fetchPosition() requires a "product_id" in params');
|
|
4133
|
+
}
|
|
4134
|
+
const futureRequest = {
|
|
4135
|
+
'product_id': productId,
|
|
4136
|
+
};
|
|
4137
|
+
response = await this.v3PrivateGetBrokerageCfmPositionsProductId(this.extend(futureRequest, params));
|
|
4138
|
+
}
|
|
4139
|
+
else {
|
|
4140
|
+
let portfolio = undefined;
|
|
4141
|
+
[portfolio, params] = this.handleOptionAndParams(params, 'fetchPositions', 'portfolio');
|
|
4142
|
+
if (portfolio === undefined) {
|
|
4143
|
+
throw new errors.ArgumentsRequired(this.id + ' fetchPosition() requires a "portfolio" value in params (eg: dbcb91e7-2bc9-515), or set as exchange.options["portfolio"]. You can get a list of portfolios with fetchPortfolios()');
|
|
4144
|
+
}
|
|
4145
|
+
const request = {
|
|
4146
|
+
'symbol': market['id'],
|
|
4147
|
+
'portfolio_uuid': portfolio,
|
|
4148
|
+
};
|
|
4149
|
+
response = await this.v3PrivateGetBrokerageIntxPositionsPortfolioUuidSymbol(this.extend(request, params));
|
|
4150
|
+
}
|
|
4151
|
+
const position = this.safeDict(response, 'position', {});
|
|
4152
|
+
return this.parsePosition(position, market);
|
|
4153
|
+
}
|
|
4154
|
+
parsePosition(position, market = undefined) {
|
|
4155
|
+
//
|
|
4156
|
+
// {
|
|
4157
|
+
// "product_id": "1r4njf84-0-0",
|
|
4158
|
+
// "product_uuid": "cd34c18b-3665-4ed8-9305-3db277c49fc5",
|
|
4159
|
+
// "symbol": "ADA-PERP-INTX",
|
|
4160
|
+
// "vwap": {
|
|
4161
|
+
// "value": "0.6171",
|
|
4162
|
+
// "currency": "USDC"
|
|
4163
|
+
// },
|
|
4164
|
+
// "position_side": "POSITION_SIDE_LONG",
|
|
4165
|
+
// "net_size": "20",
|
|
4166
|
+
// "buy_order_size": "0",
|
|
4167
|
+
// "sell_order_size": "0",
|
|
4168
|
+
// "im_contribution": "0.1",
|
|
4169
|
+
// "unrealized_pnl": {
|
|
4170
|
+
// "value": "0.074",
|
|
4171
|
+
// "currency": "USDC"
|
|
4172
|
+
// },
|
|
4173
|
+
// "mark_price": {
|
|
4174
|
+
// "value": "0.6208",
|
|
4175
|
+
// "currency": "USDC"
|
|
4176
|
+
// },
|
|
4177
|
+
// "liquidation_price": {
|
|
4178
|
+
// "value": "0",
|
|
4179
|
+
// "currency": "USDC"
|
|
4180
|
+
// },
|
|
4181
|
+
// "leverage": "1",
|
|
4182
|
+
// "im_notional": {
|
|
4183
|
+
// "value": "12.342",
|
|
4184
|
+
// "currency": "USDC"
|
|
4185
|
+
// },
|
|
4186
|
+
// "mm_notional": {
|
|
4187
|
+
// "value": "0.814572",
|
|
4188
|
+
// "currency": "USDC"
|
|
4189
|
+
// },
|
|
4190
|
+
// "position_notional": {
|
|
4191
|
+
// "value": "12.342",
|
|
4192
|
+
// "currency": "USDC"
|
|
4193
|
+
// },
|
|
4194
|
+
// "margin_type": "MARGIN_TYPE_CROSS",
|
|
4195
|
+
// "liquidation_buffer": "19.677828",
|
|
4196
|
+
// "liquidation_percentage": "4689.3506",
|
|
4197
|
+
// "portfolio_summary": {
|
|
4198
|
+
// "portfolio_uuid": "018ebd63-1f6d-7c8e-ada9-0761c5a2235f",
|
|
4199
|
+
// "collateral": "20.4184",
|
|
4200
|
+
// "position_notional": "12.342",
|
|
4201
|
+
// "open_position_notional": "12.342",
|
|
4202
|
+
// "pending_fees": "0",
|
|
4203
|
+
// "borrow": "0",
|
|
4204
|
+
// "accrued_interest": "0",
|
|
4205
|
+
// "rolling_debt": "0",
|
|
4206
|
+
// "portfolio_initial_margin": "0.1",
|
|
4207
|
+
// "portfolio_im_notional": {
|
|
4208
|
+
// "value": "12.342",
|
|
4209
|
+
// "currency": "USDC"
|
|
4210
|
+
// },
|
|
4211
|
+
// "portfolio_maintenance_margin": "0.066",
|
|
4212
|
+
// "portfolio_mm_notional": {
|
|
4213
|
+
// "value": "0.814572",
|
|
4214
|
+
// "currency": "USDC"
|
|
4215
|
+
// },
|
|
4216
|
+
// "liquidation_percentage": "4689.3506",
|
|
4217
|
+
// "liquidation_buffer": "19.677828",
|
|
4218
|
+
// "margin_type": "MARGIN_TYPE_CROSS",
|
|
4219
|
+
// "margin_flags": "PORTFOLIO_MARGIN_FLAGS_UNSPECIFIED",
|
|
4220
|
+
// "liquidation_status": "PORTFOLIO_LIQUIDATION_STATUS_NOT_LIQUIDATING",
|
|
4221
|
+
// "unrealized_pnl": {
|
|
4222
|
+
// "value": "0.074",
|
|
4223
|
+
// "currency": "USDC"
|
|
4224
|
+
// },
|
|
4225
|
+
// "buying_power": {
|
|
4226
|
+
// "value": "8.1504",
|
|
4227
|
+
// "currency": "USDC"
|
|
4228
|
+
// },
|
|
4229
|
+
// "total_balance": {
|
|
4230
|
+
// "value": "20.4924",
|
|
4231
|
+
// "currency": "USDC"
|
|
4232
|
+
// },
|
|
4233
|
+
// "max_withdrawal": {
|
|
4234
|
+
// "value": "8.0764",
|
|
4235
|
+
// "currency": "USDC"
|
|
4236
|
+
// }
|
|
4237
|
+
// },
|
|
4238
|
+
// "entry_vwap": {
|
|
4239
|
+
// "value": "0.6091",
|
|
4240
|
+
// "currency": "USDC"
|
|
4241
|
+
// }
|
|
4242
|
+
// }
|
|
4243
|
+
//
|
|
4244
|
+
const marketId = this.safeString(position, 'symbol', '');
|
|
4245
|
+
market = this.safeMarket(marketId, market);
|
|
4246
|
+
const rawMargin = this.safeString(position, 'margin_type');
|
|
4247
|
+
let marginMode = undefined;
|
|
4248
|
+
if (rawMargin !== undefined) {
|
|
4249
|
+
marginMode = (rawMargin === 'MARGIN_TYPE_CROSS') ? 'cross' : 'isolated';
|
|
4250
|
+
}
|
|
4251
|
+
const notionalObject = this.safeDict(position, 'position_notional', {});
|
|
4252
|
+
const positionSide = this.safeString(position, 'position_side');
|
|
4253
|
+
const side = (positionSide === 'POSITION_SIDE_LONG') ? 'long' : 'short';
|
|
4254
|
+
const unrealizedPNLObject = this.safeDict(position, 'unrealized_pnl', {});
|
|
4255
|
+
const liquidationPriceObject = this.safeDict(position, 'liquidation_price', {});
|
|
4256
|
+
const liquidationPrice = this.safeNumber(liquidationPriceObject, 'value');
|
|
4257
|
+
const vwapObject = this.safeDict(position, 'vwap', {});
|
|
4258
|
+
const summaryObject = this.safeDict(position, 'portfolio_summary', {});
|
|
4259
|
+
return this.safePosition({
|
|
4260
|
+
'info': position,
|
|
4261
|
+
'id': this.safeString(position, 'product_id'),
|
|
4262
|
+
'symbol': this.safeSymbol(marketId, market),
|
|
4263
|
+
'notional': this.safeNumber(notionalObject, 'value'),
|
|
4264
|
+
'marginMode': marginMode,
|
|
4265
|
+
'liquidationPrice': liquidationPrice,
|
|
4266
|
+
'entryPrice': this.safeNumber(vwapObject, 'value'),
|
|
4267
|
+
'unrealizedPnl': this.safeNumber(unrealizedPNLObject, 'value'),
|
|
4268
|
+
'realizedPnl': undefined,
|
|
4269
|
+
'percentage': undefined,
|
|
4270
|
+
'contracts': this.safeNumber(position, 'net_size'),
|
|
4271
|
+
'contractSize': market['contractSize'],
|
|
4272
|
+
'markPrice': undefined,
|
|
4273
|
+
'lastPrice': undefined,
|
|
4274
|
+
'side': side,
|
|
4275
|
+
'hedged': undefined,
|
|
4276
|
+
'timestamp': undefined,
|
|
4277
|
+
'datetime': undefined,
|
|
4278
|
+
'lastUpdateTimestamp': undefined,
|
|
4279
|
+
'maintenanceMargin': undefined,
|
|
4280
|
+
'maintenanceMarginPercentage': undefined,
|
|
4281
|
+
'collateral': this.safeNumber(summaryObject, 'collateral'),
|
|
4282
|
+
'initialMargin': undefined,
|
|
4283
|
+
'initialMarginPercentage': undefined,
|
|
4284
|
+
'leverage': this.safeNumber(position, 'leverage'),
|
|
4285
|
+
'marginRatio': undefined,
|
|
4286
|
+
'stopLossPrice': undefined,
|
|
4287
|
+
'takeProfitPrice': undefined,
|
|
4288
|
+
});
|
|
4289
|
+
}
|
|
3773
4290
|
sign(path, api = [], method = 'GET', params = {}, headers = undefined, body = undefined) {
|
|
3774
4291
|
const version = api[0];
|
|
3775
4292
|
const signed = api[1] === 'private';
|
|
@@ -3822,7 +4339,9 @@ class coinbase extends coinbase$1 {
|
|
|
3822
4339
|
// it may not work for v2
|
|
3823
4340
|
let uri = method + ' ' + url.replace('https://', '');
|
|
3824
4341
|
const quesPos = uri.indexOf('?');
|
|
3825
|
-
|
|
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) {
|
|
3826
4345
|
uri = uri.slice(0, quesPos);
|
|
3827
4346
|
}
|
|
3828
4347
|
const nonce = this.randomBytes(16);
|