ccxt 4.4.67 → 4.4.69

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.
@@ -25,7 +25,7 @@ class whitebit extends whitebit$1 {
25
25
  'CORS': undefined,
26
26
  'spot': true,
27
27
  'margin': true,
28
- 'swap': false,
28
+ 'swap': true,
29
29
  'future': false,
30
30
  'option': false,
31
31
  'cancelAllOrders': true,
@@ -75,7 +75,10 @@ class whitebit extends whitebit$1 {
75
75
  'fetchOpenOrders': true,
76
76
  'fetchOrderBook': true,
77
77
  'fetchOrderTrades': true,
78
+ 'fetchPosition': true,
79
+ 'fetchPositionHistory': true,
78
80
  'fetchPositionMode': false,
81
+ 'fetchPositions': true,
79
82
  'fetchPremiumIndexOHLCV': false,
80
83
  'fetchStatus': true,
81
84
  'fetchTicker': true,
@@ -2961,6 +2964,213 @@ class whitebit extends whitebit$1 {
2961
2964
  'fee': undefined,
2962
2965
  };
2963
2966
  }
2967
+ /**
2968
+ * @method
2969
+ * @name whitebit#fetchPositionHistory
2970
+ * @description fetches historical positions
2971
+ * @see https://docs.whitebit.com/private/http-trade-v4/#positions-history
2972
+ * @param {string} symbol unified contract symbol
2973
+ * @param {int} [since] the earliest time in ms to fetch positions for
2974
+ * @param {int} [limit] the maximum amount of records to fetch
2975
+ * @param {object} [params] extra parameters specific to the exchange api endpoint
2976
+ * @param {int} [params.positionId] the id of the requested position
2977
+ * @returns {object[]} a list of [position structures]{@link https://docs.ccxt.com/#/?id=position-structure}
2978
+ */
2979
+ async fetchPositionHistory(symbol, since = undefined, limit = undefined, params = {}) {
2980
+ await this.loadMarkets();
2981
+ const market = this.market(symbol);
2982
+ let request = {
2983
+ 'market': market['id'],
2984
+ };
2985
+ if (since !== undefined) {
2986
+ request['startDate'] = since;
2987
+ }
2988
+ if (limit !== undefined) {
2989
+ request['limit'] = since;
2990
+ }
2991
+ [request, params] = this.handleUntilOption('endDate', request, params);
2992
+ const response = await this.v4PrivatePostCollateralAccountPositionsHistory(this.extend(request, params));
2993
+ //
2994
+ // [
2995
+ // {
2996
+ // "positionId": 479975679,
2997
+ // "market": "BTC_PERP",
2998
+ // "openDate": 1741941025.309887,
2999
+ // "modifyDate": 1741941025.309887,
3000
+ // "amount": "0.001",
3001
+ // "basePrice": "82498.7",
3002
+ // "realizedFunding": "0",
3003
+ // "liquidationPrice": "0",
3004
+ // "liquidationState": null,
3005
+ // "orderDetail": {
3006
+ // "id": 1224727949521,
3007
+ // "tradeAmount": "0.001",
3008
+ // "price": "82498.7",
3009
+ // "tradeFee": "0.028874545",
3010
+ // "fundingFee": "0",
3011
+ // "realizedPnl": "-0.028874545"
3012
+ // }
3013
+ // }
3014
+ // ]
3015
+ //
3016
+ const positions = this.parsePositions(response);
3017
+ return this.filterBySymbolSinceLimit(positions, symbol, since, limit);
3018
+ }
3019
+ /**
3020
+ * @method
3021
+ * @name whitebit#fetchPositions
3022
+ * @description fetch all open positions
3023
+ * @see https://docs.whitebit.com/private/http-trade-v4/#open-positions
3024
+ * @param {string[]} [symbols] list of unified market symbols
3025
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
3026
+ * @returns {object[]} a list of [position structures]{@link https://docs.ccxt.com/#/?id=position-structure}
3027
+ */
3028
+ async fetchPositions(symbols = undefined, params = {}) {
3029
+ await this.loadMarkets();
3030
+ symbols = this.marketSymbols(symbols);
3031
+ const response = await this.v4PrivatePostCollateralAccountPositionsOpen(params);
3032
+ //
3033
+ // [
3034
+ // {
3035
+ // "positionId": 479975679,
3036
+ // "market": "BTC_PERP",
3037
+ // "openDate": 1741941025.3098869,
3038
+ // "modifyDate": 1741941025.3098869,
3039
+ // "amount": "0.001",
3040
+ // "basePrice": "82498.7",
3041
+ // "liquidationPrice": "70177.2",
3042
+ // "pnl": "0",
3043
+ // "pnlPercent": "0.00",
3044
+ // "margin": "4.2",
3045
+ // "freeMargin": "9.9",
3046
+ // "funding": "0",
3047
+ // "unrealizedFunding": "0",
3048
+ // "liquidationState": null,
3049
+ // "tpsl": null
3050
+ // }
3051
+ // ]
3052
+ //
3053
+ return this.parsePositions(response, symbols);
3054
+ }
3055
+ /**
3056
+ * @method
3057
+ * @name whitebit#fetchPosition
3058
+ * @description fetch data on a single open contract trade position
3059
+ * @see https://docs.whitebit.com/private/http-trade-v4/#open-positions
3060
+ * @param {string} symbol unified market symbol of the market the position is held in
3061
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
3062
+ * @returns {object} a [position structure]{@link https://docs.ccxt.com/#/?id=position-structure}
3063
+ */
3064
+ async fetchPosition(symbol, params = {}) {
3065
+ await this.loadMarkets();
3066
+ const market = this.market(symbol);
3067
+ const request = {
3068
+ 'symbol': market['id'],
3069
+ };
3070
+ const response = await this.v4PrivatePostCollateralAccountPositionsOpen(this.extend(request, params));
3071
+ //
3072
+ // [
3073
+ // {
3074
+ // "positionId": 479975679,
3075
+ // "market": "BTC_PERP",
3076
+ // "openDate": 1741941025.3098869,
3077
+ // "modifyDate": 1741941025.3098869,
3078
+ // "amount": "0.001",
3079
+ // "basePrice": "82498.7",
3080
+ // "liquidationPrice": "70177.2",
3081
+ // "pnl": "0",
3082
+ // "pnlPercent": "0.00",
3083
+ // "margin": "4.2",
3084
+ // "freeMargin": "9.9",
3085
+ // "funding": "0",
3086
+ // "unrealizedFunding": "0",
3087
+ // "liquidationState": null,
3088
+ // "tpsl": null
3089
+ // }
3090
+ // ]
3091
+ //
3092
+ const data = this.safeDict(response, 0, {});
3093
+ return this.parsePosition(data, market);
3094
+ }
3095
+ parsePosition(position, market = undefined) {
3096
+ //
3097
+ // fetchPosition, fetchPositions
3098
+ //
3099
+ // {
3100
+ // "positionId": 479975679,
3101
+ // "market": "BTC_PERP",
3102
+ // "openDate": 1741941025.3098869,
3103
+ // "modifyDate": 1741941025.3098869,
3104
+ // "amount": "0.001",
3105
+ // "basePrice": "82498.7",
3106
+ // "liquidationPrice": "70177.2",
3107
+ // "pnl": "0",
3108
+ // "pnlPercent": "0.00",
3109
+ // "margin": "4.2",
3110
+ // "freeMargin": "9.9",
3111
+ // "funding": "0",
3112
+ // "unrealizedFunding": "0",
3113
+ // "liquidationState": null,
3114
+ // "tpsl": null
3115
+ // }
3116
+ //
3117
+ // fetchPositionHistory
3118
+ //
3119
+ // {
3120
+ // "positionId": 479975679,
3121
+ // "market": "BTC_PERP",
3122
+ // "openDate": 1741941025.309887,
3123
+ // "modifyDate": 1741941025.309887,
3124
+ // "amount": "0.001",
3125
+ // "basePrice": "82498.7",
3126
+ // "realizedFunding": "0",
3127
+ // "liquidationPrice": "0",
3128
+ // "liquidationState": null,
3129
+ // "orderDetail": {
3130
+ // "id": 1224727949521,
3131
+ // "tradeAmount": "0.001",
3132
+ // "price": "82498.7",
3133
+ // "tradeFee": "0.028874545",
3134
+ // "fundingFee": "0",
3135
+ // "realizedPnl": "-0.028874545"
3136
+ // }
3137
+ // }
3138
+ //
3139
+ const marketId = this.safeString(position, 'market');
3140
+ const timestamp = this.safeTimestamp(position, 'openDate');
3141
+ const tpsl = this.safeDict(position, 'tpsl', {});
3142
+ const orderDetail = this.safeDict(position, 'orderDetail', {});
3143
+ return this.safePosition({
3144
+ 'info': position,
3145
+ 'id': this.safeString(position, 'positionId'),
3146
+ 'symbol': this.safeSymbol(marketId, market),
3147
+ 'notional': undefined,
3148
+ 'marginMode': undefined,
3149
+ 'liquidationPrice': this.safeNumber(position, 'liquidationPrice'),
3150
+ 'entryPrice': this.safeNumber(position, 'basePrice'),
3151
+ 'unrealizedPnl': this.safeNumber(position, 'pnl'),
3152
+ 'realizedPnl': this.safeNumber(orderDetail, 'realizedPnl'),
3153
+ 'percentage': this.safeNumber(position, 'pnlPercent'),
3154
+ 'contracts': undefined,
3155
+ 'contractSize': undefined,
3156
+ 'markPrice': undefined,
3157
+ 'lastPrice': undefined,
3158
+ 'side': undefined,
3159
+ 'hedged': undefined,
3160
+ 'timestamp': timestamp,
3161
+ 'datetime': this.iso8601(timestamp),
3162
+ 'lastUpdateTimestamp': this.safeTimestamp(position, 'modifyDate'),
3163
+ 'maintenanceMargin': undefined,
3164
+ 'maintenanceMarginPercentage': undefined,
3165
+ 'collateral': this.safeNumber(position, 'margin'),
3166
+ 'initialMargin': undefined,
3167
+ 'initialMarginPercentage': undefined,
3168
+ 'leverage': undefined,
3169
+ 'marginRatio': undefined,
3170
+ 'stopLossPrice': this.safeNumber(tpsl, 'stopLoss'),
3171
+ 'takeProfitPrice': this.safeNumber(tpsl, 'takeProfit'),
3172
+ });
3173
+ }
2964
3174
  isFiat(currency) {
2965
3175
  const fiatCurrencies = this.safeValue(this.options, 'fiatCurrencies', []);
2966
3176
  return this.inArray(currency, fiatCurrencies);
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 { Int, int, Str, Strings, Num, Bool, IndexType, OrderSide, OrderType, MarketType, SubType, Dict, NullableDict, List, NullableList, Fee, OHLCV, OHLCVC, implicitReturnType, Market, Currency, Dictionary, MinMax, FeeInterface, TradingFeeInterface, MarketInterface, Trade, Order, OrderBook, Ticker, Transaction, Tickers, CurrencyInterface, Balance, BalanceAccount, Account, PartialBalances, Balances, DepositAddress, WithdrawalResponse, DepositAddressResponse, FundingRate, FundingRates, Position, BorrowInterest, LeverageTier, LedgerEntry, DepositWithdrawFeeNetwork, DepositWithdrawFee, TransferEntry, CrossBorrowRate, IsolatedBorrowRate, FundingRateHistory, OpenInterest, Liquidation, OrderRequest, CancellationRequest, FundingHistory, MarketMarginModes, MarginMode, Greeks, Conversion, Option, LastPrice, Leverage, MarginModification, Leverages, LastPrices, Currencies, TradingFees, MarginModes, OptionChain, IsolatedBorrowRates, CrossBorrowRates, LeverageTiers, LongShortRatio, OrderBooks, OpenInterests } from './src/base/types.js';
6
6
  import { BaseError, ExchangeError, AuthenticationError, PermissionDenied, AccountNotEnabled, AccountSuspended, ArgumentsRequired, BadRequest, BadSymbol, OperationRejected, NoChange, MarginModeAlreadySet, MarketClosed, ManualInteractionNeeded, InsufficientFunds, InvalidAddress, AddressPending, InvalidOrder, OrderNotFound, OrderNotCached, OrderImmediatelyFillable, OrderNotFillable, DuplicateOrderId, ContractUnavailable, NotSupported, InvalidProxySettings, ExchangeClosedByUser, OperationFailed, NetworkError, DDoSProtection, RateLimitExceeded, ExchangeNotAvailable, OnMaintenance, InvalidNonce, ChecksumError, RequestTimeout, BadResponse, NullResponse, CancelPending, UnsubscribeError } from './src/base/errors.js';
7
- declare const version = "4.4.66";
7
+ declare const version = "4.4.68";
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
@@ -32,7 +32,7 @@ import * as errors from './src/base/errors.js';
32
32
  import { BaseError, ExchangeError, AuthenticationError, PermissionDenied, AccountNotEnabled, AccountSuspended, ArgumentsRequired, BadRequest, BadSymbol, OperationRejected, NoChange, MarginModeAlreadySet, MarketClosed, ManualInteractionNeeded, InsufficientFunds, InvalidAddress, AddressPending, InvalidOrder, OrderNotFound, OrderNotCached, OrderImmediatelyFillable, OrderNotFillable, DuplicateOrderId, ContractUnavailable, NotSupported, InvalidProxySettings, ExchangeClosedByUser, OperationFailed, NetworkError, DDoSProtection, RateLimitExceeded, ExchangeNotAvailable, OnMaintenance, InvalidNonce, ChecksumError, RequestTimeout, BadResponse, NullResponse, CancelPending, UnsubscribeError } from './src/base/errors.js';
33
33
  //-----------------------------------------------------------------------------
34
34
  // this is updated by vss.js when building
35
- const version = '4.4.67';
35
+ const version = '4.4.69';
36
36
  Exchange.ccxtVersion = version;
37
37
  //-----------------------------------------------------------------------------
38
38
  import ace from './src/ace.js';
@@ -13,8 +13,19 @@ interface Exchange {
13
13
  publicGetSystemState(params?: {}): Promise<implicitReturnType>;
14
14
  publicGetSystemTime(params?: {}): Promise<implicitReturnType>;
15
15
  publicGetTrades(params?: {}): Promise<implicitReturnType>;
16
+ publicGetVaults(params?: {}): Promise<implicitReturnType>;
17
+ publicGetVaultsBalance(params?: {}): Promise<implicitReturnType>;
18
+ publicGetVaultsConfig(params?: {}): Promise<implicitReturnType>;
19
+ publicGetVaultsHistory(params?: {}): Promise<implicitReturnType>;
20
+ publicGetVaultsPositions(params?: {}): Promise<implicitReturnType>;
21
+ publicGetVaultsSummary(params?: {}): Promise<implicitReturnType>;
22
+ publicGetVaultsTransfers(params?: {}): Promise<implicitReturnType>;
16
23
  privateGetAccount(params?: {}): Promise<implicitReturnType>;
24
+ privateGetAccountInfo(params?: {}): Promise<implicitReturnType>;
25
+ privateGetAccountHistory(params?: {}): Promise<implicitReturnType>;
26
+ privateGetAccountMargin(params?: {}): Promise<implicitReturnType>;
17
27
  privateGetAccountProfile(params?: {}): Promise<implicitReturnType>;
28
+ privateGetAccountSubaccounts(params?: {}): Promise<implicitReturnType>;
18
29
  privateGetBalance(params?: {}): Promise<implicitReturnType>;
19
30
  privateGetFills(params?: {}): Promise<implicitReturnType>;
20
31
  privateGetFundingPayments(params?: {}): Promise<implicitReturnType>;
@@ -27,16 +38,28 @@ interface Exchange {
27
38
  privateGetOrdersByClientIdClientId(params?: {}): Promise<implicitReturnType>;
28
39
  privateGetOrdersOrderId(params?: {}): Promise<implicitReturnType>;
29
40
  privateGetPointsDataMarketProgram(params?: {}): Promise<implicitReturnType>;
41
+ privateGetReferralsQrCode(params?: {}): Promise<implicitReturnType>;
30
42
  privateGetReferralsSummary(params?: {}): Promise<implicitReturnType>;
31
43
  privateGetTransfers(params?: {}): Promise<implicitReturnType>;
44
+ privateGetAlgoOrders(params?: {}): Promise<implicitReturnType>;
45
+ privateGetAlgoOrdersHistory(params?: {}): Promise<implicitReturnType>;
46
+ privateGetAlgoOrdersAlgoId(params?: {}): Promise<implicitReturnType>;
47
+ privateGetVaultsAccountSummary(params?: {}): Promise<implicitReturnType>;
48
+ privatePostAccountMarginMarket(params?: {}): Promise<implicitReturnType>;
49
+ privatePostAccountProfileMaxSlippage(params?: {}): Promise<implicitReturnType>;
32
50
  privatePostAccountProfileReferralCode(params?: {}): Promise<implicitReturnType>;
33
51
  privatePostAccountProfileUsername(params?: {}): Promise<implicitReturnType>;
34
52
  privatePostAuth(params?: {}): Promise<implicitReturnType>;
35
53
  privatePostOnboarding(params?: {}): Promise<implicitReturnType>;
36
54
  privatePostOrders(params?: {}): Promise<implicitReturnType>;
55
+ privatePostOrdersBatch(params?: {}): Promise<implicitReturnType>;
56
+ privatePostAlgoOrders(params?: {}): Promise<implicitReturnType>;
57
+ privatePostVaults(params?: {}): Promise<implicitReturnType>;
58
+ privatePutOrdersOrderId(params?: {}): Promise<implicitReturnType>;
37
59
  privateDeleteOrders(params?: {}): Promise<implicitReturnType>;
38
60
  privateDeleteOrdersByClientIdClientId(params?: {}): Promise<implicitReturnType>;
39
61
  privateDeleteOrdersOrderId(params?: {}): Promise<implicitReturnType>;
62
+ privateDeleteAlgoOrdersAlgoId(params?: {}): Promise<implicitReturnType>;
40
63
  }
41
64
  declare abstract class Exchange extends _Exchange {
42
65
  }
@@ -6,6 +6,7 @@ interface Exchange {
6
6
  publicGetTickerMarket(params?: {}): Promise<implicitReturnType>;
7
7
  publicGetHistoryMarket(params?: {}): Promise<implicitReturnType>;
8
8
  publicGetChartIntervalMarketTimestamp(params?: {}): Promise<implicitReturnType>;
9
+ publicGetChartIntervalMarket(params?: {}): Promise<implicitReturnType>;
9
10
  privateGetAccountBalance(params?: {}): Promise<implicitReturnType>;
10
11
  privateGetAccountBalances(params?: {}): Promise<implicitReturnType>;
11
12
  privateGetAccountOrderUuid(params?: {}): Promise<implicitReturnType>;
@@ -5,7 +5,7 @@ const { isNode, selfIsDefined, deepExtend, extend, clone, flatten, unique, index
5
5
  import { keys as keysFunc, values as valuesFunc, vwap as vwapFunc } from './functions.js';
6
6
  // import exceptions from "./errors.js"
7
7
  import { // eslint-disable-line object-curly-newline
8
- ExchangeError, BadSymbol, NullResponse, InvalidAddress, InvalidOrder, NotSupported, BadResponse, AuthenticationError, DDoSProtection, RequestTimeout, NetworkError, InvalidProxySettings, ExchangeNotAvailable, ArgumentsRequired, RateLimitExceeded, BadRequest, ExchangeClosedByUser, UnsubscribeError } from "./errors.js";
8
+ ExchangeError, BadSymbol, NullResponse, InvalidAddress, InvalidOrder, NotSupported, OperationFailed, BadResponse, AuthenticationError, DDoSProtection, RequestTimeout, NetworkError, InvalidProxySettings, ExchangeNotAvailable, ArgumentsRequired, RateLimitExceeded, BadRequest, ExchangeClosedByUser, UnsubscribeError } from "./errors.js";
9
9
  import { Precise } from './Precise.js';
10
10
  //-----------------------------------------------------------------------------
11
11
  import WsClient from './ws/WsClient.js';
@@ -4208,7 +4208,7 @@ export default class Exchange {
4208
4208
  return await this.fetch(request['url'], request['method'], request['headers'], request['body']);
4209
4209
  }
4210
4210
  catch (e) {
4211
- if (e instanceof NetworkError) {
4211
+ if (e instanceof OperationFailed) {
4212
4212
  if (i < retries) {
4213
4213
  if (this.verbose) {
4214
4214
  this.log('Request failed with the error: ' + e.toString() + ', retrying ' + (i + 1).toString() + ' of ' + retries.toString() + '...');
@@ -4216,10 +4216,12 @@ export default class Exchange {
4216
4216
  if ((retryDelay !== undefined) && (retryDelay !== 0)) {
4217
4217
  await this.sleep(retryDelay);
4218
4218
  }
4219
- // continue; //check this
4219
+ }
4220
+ else {
4221
+ throw e;
4220
4222
  }
4221
4223
  }
4222
- if (i >= retries) {
4224
+ else {
4223
4225
  throw e;
4224
4226
  }
4225
4227
  }
package/js/src/binance.js CHANGED
@@ -12113,8 +12113,25 @@ export default class binance extends Exchange {
12113
12113
  let query = undefined;
12114
12114
  // handle batchOrders
12115
12115
  if ((path === 'batchOrders') && ((method === 'POST') || (method === 'PUT'))) {
12116
- const batchOrders = this.safeValue(params, 'batchOrders');
12117
- const queryBatch = (this.json(batchOrders));
12116
+ const batchOrders = this.safeList(params, 'batchOrders');
12117
+ let checkedBatchOrders = batchOrders;
12118
+ if (method === 'POST' && api === 'fapiPrivate') {
12119
+ // check broker id if batchOrders are called with fapiPrivatePostBatchOrders
12120
+ checkedBatchOrders = [];
12121
+ for (let i = 0; i < batchOrders.length; i++) {
12122
+ const batchOrder = batchOrders[i];
12123
+ let newClientOrderId = this.safeString(batchOrder, 'newClientOrderId');
12124
+ if (newClientOrderId === undefined) {
12125
+ const defaultId = 'x-xcKtGhcu'; // batchOrders can not be spot or margin
12126
+ const broker = this.safeDict(this.options, 'broker', {});
12127
+ const brokerId = this.safeString(broker, 'future', defaultId);
12128
+ newClientOrderId = brokerId + this.uuid22();
12129
+ batchOrder['newClientOrderId'] = newClientOrderId;
12130
+ }
12131
+ checkedBatchOrders.push(batchOrder);
12132
+ }
12133
+ }
12134
+ const queryBatch = (this.json(checkedBatchOrders));
12118
12135
  params['batchOrders'] = queryBatch;
12119
12136
  }
12120
12137
  const defaultRecvWindow = this.safeInteger(this.options, 'recvWindow');
package/js/src/bitrue.js CHANGED
@@ -1672,7 +1672,7 @@ export default class bitrue extends Exchange {
1672
1672
  const tickers = {};
1673
1673
  for (let i = 0; i < data.length; i++) {
1674
1674
  const ticker = this.safeDict(data, i, {});
1675
- const market = this.market(this.safeValue(ticker, 'symbol'));
1675
+ const market = this.safeMarket(this.safeString(ticker, 'symbol'));
1676
1676
  tickers[market['id']] = ticker;
1677
1677
  }
1678
1678
  return this.parseTickers(tickers, symbols);
@@ -1304,10 +1304,9 @@ export default class bitstamp extends Exchange {
1304
1304
  }
1305
1305
  parseTradingFees(fees) {
1306
1306
  const result = { 'info': fees };
1307
- const symbols = this.symbols;
1308
- for (let i = 0; i < symbols.length; i++) {
1309
- const symbol = symbols[i];
1307
+ for (let i = 0; i < fees.length; i++) {
1310
1308
  const fee = this.parseTradingFee(fees[i]);
1309
+ const symbol = fee['symbol'];
1311
1310
  result[symbol] = fee;
1312
1311
  }
1313
1312
  return result;
package/js/src/bybit.js CHANGED
@@ -9305,7 +9305,7 @@ export default class bybit extends Exchange {
9305
9305
  else {
9306
9306
  feedback = this.id + ' ' + body;
9307
9307
  }
9308
- if (body.indexOf('Withdraw address chain or destination tag are not equal')) {
9308
+ if (body.indexOf('Withdraw address chain or destination tag are not equal') > -1) {
9309
9309
  feedback = feedback + '; You might also need to ensure the address is whitelisted';
9310
9310
  }
9311
9311
  this.throwBroadlyMatchedException(this.exceptions['broad'], body, feedback);
@@ -605,6 +605,17 @@ export default class coinbase extends Exchange {
605
605
  * @returns {object} a dictionary of [fee structures]{@link https://docs.ccxt.com/#/?id=fee-structure} indexed by market symbols
606
606
  */
607
607
  fetchTradingFees(params?: {}): Promise<TradingFees>;
608
+ /**
609
+ * @method
610
+ * @name coinbase#fetchPortfolioDetails
611
+ * @description Fetch details for a specific portfolio by UUID
612
+ * @see https://docs.cloud.coinbase.com/advanced-trade/reference/retailbrokerageapi_getportfolios
613
+ * @param {string} portfolioUuid The unique identifier of the portfolio to fetch
614
+ * @param {Dict} [params] Extra parameters specific to the exchange API endpoint
615
+ * @returns {any[]} An account structure <https://docs.ccxt.com/#/?id=account-structure>
616
+ */
617
+ fetchPortfolioDetails(portfolioUuid: string, params?: {}): Promise<any[]>;
618
+ parsePortfolioDetails(portfolioData: Dict): any[];
608
619
  createAuthToken(seconds: Int, method?: Str, url?: Str): string;
609
620
  nonce(): number;
610
621
  sign(path: any, api?: any[], method?: string, params?: {}, headers?: any, body?: any): {
@@ -4264,6 +4264,7 @@ export default class coinbase extends Exchange {
4264
4264
  'amount': this.numberToString(amount),
4265
4265
  'currency': code.toUpperCase(),
4266
4266
  'payment_method': id,
4267
+ 'commit': true, // otheriwse the deposit does not go through
4267
4268
  };
4268
4269
  const response = await this.v2PrivatePostAccountsAccountIdDeposits(this.extend(request, params));
4269
4270
  //
@@ -4302,7 +4303,8 @@ export default class coinbase extends Exchange {
4302
4303
  // }
4303
4304
  // }
4304
4305
  //
4305
- const data = this.safeDict(response, 'data', {});
4306
+ // https://github.com/ccxt/ccxt/issues/25484
4307
+ const data = this.safeDict2(response, 'data', 'transfer', {});
4306
4308
  return this.parseTransaction(data);
4307
4309
  }
4308
4310
  /**
@@ -4370,7 +4372,8 @@ export default class coinbase extends Exchange {
4370
4372
  // }
4371
4373
  // }
4372
4374
  //
4373
- const data = this.safeDict(response, 'data', {});
4375
+ // https://github.com/ccxt/ccxt/issues/25484
4376
+ const data = this.safeDict2(response, 'data', 'transfer', {});
4374
4377
  return this.parseTransaction(data);
4375
4378
  }
4376
4379
  /**
@@ -4864,6 +4867,71 @@ export default class coinbase extends Exchange {
4864
4867
  }
4865
4868
  return result;
4866
4869
  }
4870
+ /**
4871
+ * @method
4872
+ * @name coinbase#fetchPortfolioDetails
4873
+ * @description Fetch details for a specific portfolio by UUID
4874
+ * @see https://docs.cloud.coinbase.com/advanced-trade/reference/retailbrokerageapi_getportfolios
4875
+ * @param {string} portfolioUuid The unique identifier of the portfolio to fetch
4876
+ * @param {Dict} [params] Extra parameters specific to the exchange API endpoint
4877
+ * @returns {any[]} An account structure <https://docs.ccxt.com/#/?id=account-structure>
4878
+ */
4879
+ async fetchPortfolioDetails(portfolioUuid, params = {}) {
4880
+ await this.loadMarkets();
4881
+ const request = {
4882
+ 'portfolio_uuid': portfolioUuid,
4883
+ };
4884
+ const response = await this.v3PrivateGetBrokeragePortfoliosPortfolioUuid(this.extend(request, params));
4885
+ const result = this.parsePortfolioDetails(response);
4886
+ return result;
4887
+ }
4888
+ parsePortfolioDetails(portfolioData) {
4889
+ const breakdown = portfolioData['breakdown'];
4890
+ const portfolioInfo = this.safeDict(breakdown, 'portfolio', {});
4891
+ const portfolioName = this.safeString(portfolioInfo, 'name', 'Unknown');
4892
+ const portfolioUuid = this.safeString(portfolioInfo, 'uuid', '');
4893
+ const spotPositions = this.safeList(breakdown, 'spot_positions', []);
4894
+ const parsedPositions = [];
4895
+ for (let i = 0; i < spotPositions.length; i++) {
4896
+ const position = spotPositions[i];
4897
+ const currencyCode = this.safeString(position, 'asset', 'Unknown');
4898
+ const availableBalanceStr = this.safeString(position, 'available_to_trade_fiat', '0');
4899
+ const availableBalance = this.parseNumber(availableBalanceStr);
4900
+ const totalBalanceFiatStr = this.safeString(position, 'total_balance_fiat', '0');
4901
+ const totalBalanceFiat = this.parseNumber(totalBalanceFiatStr);
4902
+ const holdAmount = totalBalanceFiat - availableBalance;
4903
+ const costBasisDict = this.safeDict(position, 'cost_basis', {});
4904
+ const costBasisStr = this.safeString(costBasisDict, 'value', '0');
4905
+ const averageEntryPriceDict = this.safeDict(position, 'average_entry_price', {});
4906
+ const averageEntryPriceStr = this.safeString(averageEntryPriceDict, 'value', '0');
4907
+ const positionData = {
4908
+ 'currency': currencyCode,
4909
+ 'available_balance': availableBalance,
4910
+ 'hold_amount': holdAmount > 0 ? holdAmount : 0,
4911
+ 'wallet_name': portfolioName,
4912
+ 'account_id': portfolioUuid,
4913
+ 'account_uuid': this.safeString(position, 'account_uuid', ''),
4914
+ 'total_balance_fiat': totalBalanceFiat,
4915
+ 'total_balance_crypto': this.parseNumber(this.safeString(position, 'total_balance_crypto', '0')),
4916
+ 'available_to_trade_fiat': this.parseNumber(this.safeString(position, 'available_to_trade_fiat', '0')),
4917
+ 'available_to_trade_crypto': this.parseNumber(this.safeString(position, 'available_to_trade_crypto', '0')),
4918
+ 'available_to_transfer_fiat': this.parseNumber(this.safeString(position, 'available_to_transfer_fiat', '0')),
4919
+ 'available_to_transfer_crypto': this.parseNumber(this.safeString(position, 'available_to_trade_crypto', '0')),
4920
+ 'allocation': this.parseNumber(this.safeString(position, 'allocation', '0')),
4921
+ 'cost_basis': this.parseNumber(costBasisStr),
4922
+ 'cost_basis_currency': this.safeString(costBasisDict, 'currency', 'USD'),
4923
+ 'is_cash': this.safeBool(position, 'is_cash', false),
4924
+ 'average_entry_price': this.parseNumber(averageEntryPriceStr),
4925
+ 'average_entry_price_currency': this.safeString(averageEntryPriceDict, 'currency', 'USD'),
4926
+ 'asset_uuid': this.safeString(position, 'asset_uuid', ''),
4927
+ 'unrealized_pnl': this.parseNumber(this.safeString(position, 'unrealized_pnl', '0')),
4928
+ 'asset_color': this.safeString(position, 'asset_color', ''),
4929
+ 'account_type': this.safeString(position, 'account_type', ''),
4930
+ };
4931
+ parsedPositions.push(positionData);
4932
+ }
4933
+ return parsedPositions;
4934
+ }
4867
4935
  createAuthToken(seconds, method = undefined, url = undefined) {
4868
4936
  // it may not work for v2
4869
4937
  let uri = undefined;