UNPKG

ccxt

Version:

A JavaScript / TypeScript / Python / C# / PHP cryptocurrency trading library with support for 100+ exchanges

1,023 lines (1,020 loc) • 248 kB
// ---------------------------------------------------------------------------- // PLEASE DO NOT EDIT THIS FILE, IT IS GENERATED AND WILL BE OVERWRITTEN: // https://github.com/ccxt/ccxt/blob/master/CONTRIBUTING.md#how-to-contribute-code // EDIT THE CORRESPONDENT .ts FILE INSTEAD // ---------------------------------------------------------------------------- import Exchange from './abstract/coinbase.js'; import { ExchangeError, ArgumentsRequired, AuthenticationError, BadRequest, InvalidOrder, NotSupported, OrderNotFound, RateLimitExceeded, InvalidNonce, PermissionDenied, InsufficientFunds } from './base/errors.js'; import { Precise } from './base/Precise.js'; import { TICK_SIZE } from './base/functions/number.js'; import { sha256 } from './static_dependencies/noble-hashes/sha256.js'; import { jwt } from './base/functions/rsa.js'; // ---------------------------------------------------------------------------- /** * @class coinbase * @augments Exchange */ export default class coinbase extends Exchange { describe() { return this.deepExtend(super.describe(), { 'id': 'coinbase', 'name': 'Coinbase Advanced', 'countries': ['US'], 'pro': true, 'certified': false, // rate-limits: // ADVANCED API: https://docs.cloud.coinbase.com/advanced-trade/docs/rest-api-rate-limits // - max 30 req/second for private data, 10 req/s for public data // DATA API : https://docs.cloud.coinbase.com/sign-in-with-coinbase/docs/rate-limiting // - max 10000 req/hour (to prevent userland mistakes we apply ~3 req/second RL per call 'rateLimit': 34, 'version': 'v2', 'userAgent': this.userAgents['chrome'], 'headers': { 'CB-VERSION': '2018-05-30', }, 'has': { 'CORS': true, 'spot': true, 'margin': false, 'swap': false, 'future': false, 'option': false, 'addMargin': false, 'cancelOrder': true, 'cancelOrders': true, 'closeAllPositions': false, 'closePosition': true, 'createConvertTrade': true, 'createDepositAddress': true, 'createLimitBuyOrder': true, 'createLimitSellOrder': true, 'createMarketBuyOrder': true, 'createMarketBuyOrderWithCost': true, 'createMarketOrderWithCost': false, 'createMarketSellOrder': true, 'createMarketSellOrderWithCost': false, 'createOrder': true, 'createPostOnlyOrder': true, 'createReduceOnlyOrder': false, 'createStopLimitOrder': true, 'createStopMarketOrder': false, 'createStopOrder': true, 'deposit': true, 'editOrder': true, 'fetchAccounts': true, 'fetchBalance': true, 'fetchBidsAsks': true, 'fetchBorrowRateHistories': false, 'fetchBorrowRateHistory': false, 'fetchCanceledOrders': true, 'fetchClosedOrders': true, 'fetchConvertQuote': true, 'fetchConvertTrade': true, 'fetchConvertTradeHistory': false, 'fetchCrossBorrowRate': false, 'fetchCrossBorrowRates': false, 'fetchCurrencies': true, 'fetchDeposit': true, 'fetchDepositAddress': 'emulated', 'fetchDepositAddresses': false, 'fetchDepositAddressesByNetwork': true, 'fetchDepositMethodId': true, 'fetchDepositMethodIds': true, 'fetchDeposits': true, 'fetchDepositsWithdrawals': true, 'fetchFundingHistory': false, 'fetchFundingRate': false, 'fetchFundingRateHistory': false, 'fetchFundingRates': false, 'fetchIndexOHLCV': false, 'fetchIsolatedBorrowRate': false, 'fetchIsolatedBorrowRates': false, 'fetchL2OrderBook': false, 'fetchLedger': true, 'fetchLeverage': false, 'fetchLeverageTiers': false, 'fetchMarginMode': false, 'fetchMarkets': true, 'fetchMarkOHLCV': false, 'fetchMyBuys': true, 'fetchMySells': true, 'fetchMyTrades': true, 'fetchOHLCV': true, 'fetchOpenInterestHistory': false, 'fetchOpenOrders': true, 'fetchOrder': true, 'fetchOrderBook': true, 'fetchOrders': true, 'fetchPosition': true, 'fetchPositionMode': false, 'fetchPositions': true, 'fetchPositionsRisk': false, 'fetchPremiumIndexOHLCV': false, 'fetchTicker': true, 'fetchTickers': true, 'fetchTime': true, 'fetchTrades': true, 'fetchTradingFee': 'emulated', 'fetchTradingFees': true, 'fetchWithdrawals': true, 'reduceMargin': false, 'setLeverage': false, 'setMarginMode': false, 'setPositionMode': false, 'withdraw': true, }, 'urls': { 'logo': 'https://user-images.githubusercontent.com/1294454/40811661-b6eceae2-653a-11e8-829e-10bfadb078cf.jpg', 'api': { 'rest': 'https://api.coinbase.com', }, 'www': 'https://www.coinbase.com', 'doc': [ 'https://developers.coinbase.com/api/v2', 'https://docs.cloud.coinbase.com/advanced-trade/docs/welcome', ], 'fees': [ 'https://support.coinbase.com/customer/portal/articles/2109597-buy-sell-bank-transfer-fees', 'https://www.coinbase.com/advanced-fees', ], 'referral': 'https://www.coinbase.com/join/58cbe25a355148797479dbd2', }, 'requiredCredentials': { 'apiKey': true, 'secret': true, }, 'api': { 'v2': { 'public': { 'get': { 'currencies': 10.6, 'currencies/crypto': 10.6, 'time': 10.6, 'exchange-rates': 10.6, 'users/{user_id}': 10.6, 'prices/{symbol}/buy': 10.6, 'prices/{symbol}/sell': 10.6, 'prices/{symbol}/spot': 10.6, }, }, 'private': { 'get': { 'accounts': 10.6, 'accounts/{account_id}': 10.6, 'accounts/{account_id}/addresses': 10.6, 'accounts/{account_id}/addresses/{address_id}': 10.6, 'accounts/{account_id}/addresses/{address_id}/transactions': 10.6, 'accounts/{account_id}/transactions': 10.6, 'accounts/{account_id}/transactions/{transaction_id}': 10.6, 'accounts/{account_id}/buys': 10.6, 'accounts/{account_id}/buys/{buy_id}': 10.6, 'accounts/{account_id}/sells': 10.6, 'accounts/{account_id}/sells/{sell_id}': 10.6, 'accounts/{account_id}/deposits': 10.6, 'accounts/{account_id}/deposits/{deposit_id}': 10.6, 'accounts/{account_id}/withdrawals': 10.6, 'accounts/{account_id}/withdrawals/{withdrawal_id}': 10.6, 'payment-methods': 10.6, 'payment-methods/{payment_method_id}': 10.6, 'user': 10.6, 'user/auth': 10.6, }, 'post': { 'accounts': 10.6, 'accounts/{account_id}/primary': 10.6, 'accounts/{account_id}/addresses': 10.6, 'accounts/{account_id}/transactions': 10.6, 'accounts/{account_id}/transactions/{transaction_id}/complete': 10.6, 'accounts/{account_id}/transactions/{transaction_id}/resend': 10.6, 'accounts/{account_id}/buys': 10.6, 'accounts/{account_id}/buys/{buy_id}/commit': 10.6, 'accounts/{account_id}/sells': 10.6, 'accounts/{account_id}/sells/{sell_id}/commit': 10.6, 'accounts/{account_id}/deposits': 10.6, 'accounts/{account_id}/deposits/{deposit_id}/commit': 10.6, 'accounts/{account_id}/withdrawals': 10.6, 'accounts/{account_id}/withdrawals/{withdrawal_id}/commit': 10.6, }, 'put': { 'accounts/{account_id}': 10.6, 'user': 10.6, }, 'delete': { 'accounts/{id}': 10.6, 'accounts/{account_id}/transactions/{transaction_id}': 10.6, }, }, }, 'v3': { 'public': { 'get': { 'brokerage/time': 3, 'brokerage/market/product_book': 3, 'brokerage/market/products': 3, 'brokerage/market/products/{product_id}': 3, 'brokerage/market/products/{product_id}/candles': 3, 'brokerage/market/products/{product_id}/ticker': 3, }, }, 'private': { 'get': { 'brokerage/accounts': 1, 'brokerage/accounts/{account_uuid}': 1, 'brokerage/orders/historical/batch': 1, 'brokerage/orders/historical/fills': 1, 'brokerage/orders/historical/{order_id}': 1, 'brokerage/products': 3, 'brokerage/products/{product_id}': 3, 'brokerage/products/{product_id}/candles': 3, 'brokerage/products/{product_id}/ticker': 3, 'brokerage/best_bid_ask': 3, 'brokerage/product_book': 3, 'brokerage/transaction_summary': 3, 'brokerage/portfolios': 1, 'brokerage/portfolios/{portfolio_uuid}': 1, 'brokerage/convert/trade/{trade_id}': 1, 'brokerage/cfm/balance_summary': 1, 'brokerage/cfm/positions': 1, 'brokerage/cfm/positions/{product_id}': 1, 'brokerage/cfm/sweeps': 1, 'brokerage/intx/portfolio/{portfolio_uuid}': 1, 'brokerage/intx/positions/{portfolio_uuid}': 1, 'brokerage/intx/positions/{portfolio_uuid}/{symbol}': 1, 'brokerage/payment_methods': 1, 'brokerage/payment_methods/{payment_method_id}': 1, }, 'post': { 'brokerage/orders': 1, 'brokerage/orders/batch_cancel': 1, 'brokerage/orders/edit': 1, 'brokerage/orders/edit_preview': 1, 'brokerage/orders/preview': 1, 'brokerage/portfolios': 1, 'brokerage/portfolios/move_funds': 1, 'brokerage/convert/quote': 1, 'brokerage/convert/trade/{trade_id}': 1, 'brokerage/cfm/sweeps/schedule': 1, 'brokerage/intx/allocate': 1, // futures 'brokerage/orders/close_position': 1, }, 'put': { 'brokerage/portfolios/{portfolio_uuid}': 1, }, 'delete': { 'brokerage/portfolios/{portfolio_uuid}': 1, 'brokerage/cfm/sweeps': 1, }, }, }, }, 'fees': { 'trading': { 'taker': this.parseNumber('0.012'), 'maker': this.parseNumber('0.006'), 'tierBased': true, 'percentage': true, 'tiers': { 'taker': [ [this.parseNumber('0'), this.parseNumber('0.006')], [this.parseNumber('10000'), this.parseNumber('0.004')], [this.parseNumber('50000'), this.parseNumber('0.0025')], [this.parseNumber('100000'), this.parseNumber('0.002')], [this.parseNumber('1000000'), this.parseNumber('0.0018')], [this.parseNumber('15000000'), this.parseNumber('0.0016')], [this.parseNumber('75000000'), this.parseNumber('0.0012')], [this.parseNumber('250000000'), this.parseNumber('0.0008')], [this.parseNumber('400000000'), this.parseNumber('0.0005')], ], 'maker': [ [this.parseNumber('0'), this.parseNumber('0.004')], [this.parseNumber('10000'), this.parseNumber('0.0025')], [this.parseNumber('50000'), this.parseNumber('0.0015')], [this.parseNumber('100000'), this.parseNumber('0.001')], [this.parseNumber('1000000'), this.parseNumber('0.0008')], [this.parseNumber('15000000'), this.parseNumber('0.0006')], [this.parseNumber('75000000'), this.parseNumber('0.0003')], [this.parseNumber('250000000'), this.parseNumber('0.0')], [this.parseNumber('400000000'), this.parseNumber('0.0')], ], }, }, }, 'precisionMode': TICK_SIZE, 'exceptions': { 'exact': { 'two_factor_required': AuthenticationError, 'param_required': ExchangeError, 'validation_error': ExchangeError, 'invalid_request': ExchangeError, 'personal_details_required': AuthenticationError, 'identity_verification_required': AuthenticationError, 'jumio_verification_required': AuthenticationError, 'jumio_face_match_verification_required': AuthenticationError, 'unverified_email': AuthenticationError, 'authentication_error': AuthenticationError, 'invalid_authentication_method': AuthenticationError, 'invalid_token': AuthenticationError, 'revoked_token': AuthenticationError, 'expired_token': AuthenticationError, 'invalid_scope': AuthenticationError, 'not_found': ExchangeError, 'rate_limit_exceeded': RateLimitExceeded, 'internal_server_error': ExchangeError, 'UNSUPPORTED_ORDER_CONFIGURATION': BadRequest, 'INSUFFICIENT_FUND': InsufficientFunds, 'PERMISSION_DENIED': PermissionDenied, 'INVALID_ARGUMENT': BadRequest, 'PREVIEW_STOP_PRICE_ABOVE_LAST_TRADE_PRICE': InvalidOrder, 'PREVIEW_INSUFFICIENT_FUND': InsufficientFunds, }, 'broad': { 'Insufficient balance in source account': InsufficientFunds, 'request timestamp expired': InvalidNonce, 'order with this orderID was not found': OrderNotFound, // {"error":"unknown","error_details":"order with this orderID was not found","message":"order with this orderID was not found"} }, }, 'timeframes': { '1m': 'ONE_MINUTE', '5m': 'FIVE_MINUTE', '15m': 'FIFTEEN_MINUTE', '30m': 'THIRTY_MINUTE', '1h': 'ONE_HOUR', '2h': 'TWO_HOUR', '6h': 'SIX_HOUR', '1d': 'ONE_DAY', }, 'commonCurrencies': { 'CGLD': 'CELO', }, 'options': { 'usePrivate': false, 'brokerId': 'ccxt', 'stablePairs': ['BUSD-USD', 'CBETH-ETH', 'DAI-USD', 'GUSD-USD', 'GYEN-USD', 'PAX-USD', 'PAX-USDT', 'USDC-EUR', 'USDC-GBP', 'USDT-EUR', 'USDT-GBP', 'USDT-USD', 'USDT-USDC', 'WBTC-BTC'], 'fetchCurrencies': { 'expires': 5000, }, 'accounts': [ 'wallet', 'fiat', // 'vault', ], 'v3Accounts': [ 'ACCOUNT_TYPE_CRYPTO', 'ACCOUNT_TYPE_FIAT', ], 'networks': { 'ERC20': 'ethereum', 'XLM': 'stellar', }, 'createMarketBuyOrderRequiresPrice': true, 'advanced': true, 'fetchMarkets': 'fetchMarketsV3', 'timeDifference': 0, 'adjustForTimeDifference': false, 'fetchTicker': 'fetchTickerV3', 'fetchTickers': 'fetchTickersV3', 'fetchAccounts': 'fetchAccountsV3', 'fetchBalance': 'v2PrivateGetAccounts', 'fetchTime': 'v2PublicGetTime', 'user_native_currency': 'USD', // needed to get fees for v3 }, 'features': { 'default': { 'sandbox': false, 'createOrder': { 'marginMode': true, 'triggerPrice': true, 'triggerPriceType': undefined, 'triggerDirection': true, 'stopLossPrice': true, 'takeProfitPrice': true, 'attachedStopLossTakeProfit': undefined, 'timeInForce': { 'IOC': true, 'FOK': true, 'PO': true, 'GTD': true, }, 'hedged': false, 'trailing': false, 'leverage': true, 'marketBuyByCost': true, 'marketBuyRequiresPrice': true, 'selfTradePrevention': false, 'iceberg': false, }, 'createOrders': undefined, 'fetchMyTrades': { 'marginMode': false, 'limit': 3000, 'daysBack': undefined, 'untilDays': 10000, 'symbolRequired': false, }, 'fetchOrder': { 'marginMode': false, 'trigger': false, 'trailing': false, 'symbolRequired': false, }, 'fetchOpenOrders': { 'marginMode': false, 'limit': undefined, 'trigger': false, 'trailing': false, 'symbolRequired': false, }, 'fetchOrders': { 'marginMode': false, 'limit': undefined, 'daysBack': undefined, 'untilDays': 10000, 'trigger': false, 'trailing': false, 'symbolRequired': false, }, 'fetchClosedOrders': { 'marginMode': false, 'limit': undefined, 'daysBack': undefined, 'daysBackCanceled': undefined, 'untilDays': 10000, 'trigger': false, 'trailing': false, 'symbolRequired': false, }, 'fetchOHLCV': { 'limit': 300, }, }, 'spot': { 'extends': 'default', }, 'swap': { 'linear': { 'extends': 'default', }, 'inverse': undefined, }, 'future': { 'linear': { 'extends': 'default', }, 'inverse': undefined, }, }, }); } /** * @method * @name coinbase#fetchTime * @description fetches the current integer timestamp in milliseconds from the exchange server * @see https://docs.cloud.coinbase.com/sign-in-with-coinbase/docs/api-time#http-request * @param {object} [params] extra parameters specific to the exchange API endpoint * @param {string} [params.method] 'v2PublicGetTime' or 'v3PublicGetBrokerageTime' default is 'v2PublicGetTime' * @returns {int} the current integer timestamp in milliseconds from the exchange server */ async fetchTime(params = {}) { const defaultMethod = this.safeString(this.options, 'fetchTime', 'v2PublicGetTime'); const method = this.safeString(params, 'method', defaultMethod); params = this.omit(params, 'method'); let response = undefined; if (method === 'v2PublicGetTime') { response = await this.v2PublicGetTime(params); // // { // "data": { // "epoch": 1589295679, // "iso": "2020-05-12T15:01:19Z" // } // } // response = this.safeDict(response, 'data', {}); } else { response = await this.v3PublicGetBrokerageTime(params); // // { // "iso": "2024-02-27T03:37:14Z", // "epochSeconds": "1709005034", // "epochMillis": "1709005034333" // } // } return this.safeTimestamp2(response, 'epoch', 'epochSeconds'); } /** * @method * @name coinbase#fetchAccounts * @description fetch all the accounts associated with a profile * @see https://docs.cloud.coinbase.com/advanced-trade/reference/retailbrokerageapi_getaccounts * @see https://docs.cloud.coinbase.com/sign-in-with-coinbase/docs/api-accounts#list-accounts * @param {object} [params] extra parameters specific to the exchange API endpoint * @param {boolean} [params.paginate] default false, when true will automatically paginate by calling this endpoint multiple times. See in the docs all the [availble parameters](https://github.com/ccxt/ccxt/wiki/Manual#pagination-params) * @returns {object} a dictionary of [account structures]{@link https://docs.ccxt.com/#/?id=account-structure} indexed by the account type */ async fetchAccounts(params = {}) { const method = this.safeString(this.options, 'fetchAccounts', 'fetchAccountsV3'); if (method === 'fetchAccountsV3') { return await this.fetchAccountsV3(params); } return await this.fetchAccountsV2(params); } async fetchAccountsV2(params = {}) { await this.loadMarkets(); let paginate = false; [paginate, params] = this.handleOptionAndParams(params, 'fetchAccounts', 'paginate'); if (paginate) { return await this.fetchPaginatedCallCursor('fetchAccounts', undefined, undefined, undefined, params, 'next_starting_after', 'starting_after', undefined, 100); } const request = { 'limit': 100, }; const response = await this.v2PrivateGetAccounts(this.extend(request, params)); // // { // "pagination": { // "ending_before": null, // "starting_after": null, // "previous_ending_before": null, // "next_starting_after": null, // "limit": 244, // "order": "desc", // "previous_uri": null, // "next_uri": null // }, // "data": [ // { // "id": "XLM", // "name": "XLM Wallet", // "primary": false, // "type": "wallet", // "currency": { // "code": "XLM", // "name": "Stellar Lumens", // "color": "#000000", // "sort_index": 127, // "exponent": 7, // "type": "crypto", // "address_regex": "^G[A-Z2-7]{55}$", // "asset_id": "13b83335-5ede-595b-821e-5bcdfa80560f", // "destination_tag_name": "XLM Memo ID", // "destination_tag_regex": "^[ -~]{1,28}$" // }, // "balance": { // "amount": "0.0000000", // "currency": "XLM" // }, // "created_at": null, // "updated_at": null, // "resource": "account", // "resource_path": "/v2/accounts/XLM", // "allow_deposits": true, // "allow_withdrawals": true // }, // ] // } // const data = this.safeList(response, 'data', []); const pagination = this.safeDict(response, 'pagination', {}); const cursor = this.safeString(pagination, 'next_starting_after'); const accounts = this.safeList(response, 'data', []); const length = accounts.length; const lastIndex = length - 1; const last = this.safeDict(accounts, lastIndex); if ((cursor !== undefined) && (cursor !== '')) { last['next_starting_after'] = cursor; accounts[lastIndex] = last; } return this.parseAccounts(data, params); } async fetchAccountsV3(params = {}) { await this.loadMarkets(); let paginate = false; [paginate, params] = this.handleOptionAndParams(params, 'fetchAccounts', 'paginate'); if (paginate) { return await this.fetchPaginatedCallCursor('fetchAccounts', undefined, undefined, undefined, params, 'cursor', 'cursor', undefined, 250); } const request = { 'limit': 250, }; const response = await this.v3PrivateGetBrokerageAccounts(this.extend(request, params)); // // { // "accounts": [ // { // "uuid": "11111111-1111-1111-1111-111111111111", // "name": "USDC Wallet", // "currency": "USDC", // "available_balance": { // "value": "0.0000000000000000", // "currency": "USDC" // }, // "default": true, // "active": true, // "created_at": "2023-01-04T06:20:06.456Z", // "updated_at": "2023-01-04T06:20:07.181Z", // "deleted_at": null, // "type": "ACCOUNT_TYPE_CRYPTO", // "ready": false, // "hold": { // "value": "0.0000000000000000", // "currency": "USDC" // } // }, // ... // ], // "has_next": false, // "cursor": "", // "size": 9 // } // const accounts = this.safeList(response, 'accounts', []); const length = accounts.length; const lastIndex = length - 1; const last = this.safeDict(accounts, lastIndex); const cursor = this.safeString(response, 'cursor'); if ((cursor !== undefined) && (cursor !== '')) { last['cursor'] = cursor; accounts[lastIndex] = last; } return this.parseAccounts(accounts, params); } /** * @method * @name coinbase#fetchPortfolios * @description fetch all the portfolios * @see https://docs.cloud.coinbase.com/advanced-trade/reference/retailbrokerageapi_getportfolios * @param {object} [params] extra parameters specific to the exchange API endpoint * @returns {object} a dictionary of [account structures]{@link https://docs.ccxt.com/#/?id=account-structure} indexed by the account type */ async fetchPortfolios(params = {}) { const response = await this.v3PrivateGetBrokeragePortfolios(params); const portfolios = this.safeList(response, 'portfolios', []); const result = []; for (let i = 0; i < portfolios.length; i++) { const portfolio = portfolios[i]; result.push({ 'id': this.safeString(portfolio, 'uuid'), 'type': this.safeString(portfolio, 'type'), 'code': undefined, 'info': portfolio, }); } return result; } parseAccount(account) { // // fetchAccountsV2 // // { // "id": "XLM", // "name": "XLM Wallet", // "primary": false, // "type": "wallet", // "currency": { // "code": "XLM", // "name": "Stellar Lumens", // "color": "#000000", // "sort_index": 127, // "exponent": 7, // "type": "crypto", // "address_regex": "^G[A-Z2-7]{55}$", // "asset_id": "13b83335-5ede-595b-821e-5bcdfa80560f", // "destination_tag_name": "XLM Memo ID", // "destination_tag_regex": "^[ -~]{1,28}$" // }, // "balance": { // "amount": "0.0000000", // "currency": "XLM" // }, // "created_at": null, // "updated_at": null, // "resource": "account", // "resource_path": "/v2/accounts/XLM", // "allow_deposits": true, // "allow_withdrawals": true // } // // fetchAccountsV3 // // { // "uuid": "11111111-1111-1111-1111-111111111111", // "name": "USDC Wallet", // "currency": "USDC", // "available_balance": { // "value": "0.0000000000000000", // "currency": "USDC" // }, // "default": true, // "active": true, // "created_at": "2023-01-04T06:20:06.456Z", // "updated_at": "2023-01-04T06:20:07.181Z", // "deleted_at": null, // "type": "ACCOUNT_TYPE_CRYPTO", // "ready": false, // "hold": { // "value": "0.0000000000000000", // "currency": "USDC" // } // } // const active = this.safeBool(account, 'active'); const currencyIdV3 = this.safeString(account, 'currency'); const currency = this.safeDict(account, 'currency', {}); const currencyId = this.safeString(currency, 'code', currencyIdV3); const typeV3 = this.safeString(account, 'name'); const typeV2 = this.safeString(account, 'type'); const parts = typeV3.split(' '); return { 'id': this.safeString2(account, 'id', 'uuid'), 'type': (active !== undefined) ? this.safeStringLower(parts, 1) : typeV2, 'code': this.safeCurrencyCode(currencyId), 'info': account, }; } /** * @method * @name coinbase#createDepositAddress * @description create a currency deposit address * @see https://docs.cloud.coinbase.com/sign-in-with-coinbase/docs/api-addresses#create-address * @param {string} code unified currency code of the currency for the deposit address * @param {object} [params] extra parameters specific to the exchange API endpoint * @returns {object} an [address structure]{@link https://docs.ccxt.com/#/?id=address-structure} */ async createDepositAddress(code, params = {}) { let accountId = this.safeString(params, 'account_id'); params = this.omit(params, 'account_id'); if (accountId === undefined) { await this.loadAccounts(); for (let i = 0; i < this.accounts.length; i++) { const account = this.accounts[i]; if (account['code'] === code && account['type'] === 'wallet') { accountId = account['id']; break; } } } if (accountId === undefined) { throw new ExchangeError(this.id + ' createDepositAddress() could not find the account with matching currency code ' + code + ', specify an `account_id` extra param to target specific wallet'); } const request = { 'account_id': accountId, }; const response = await this.v2PrivatePostAccountsAccountIdAddresses(this.extend(request, params)); // // { // "data": { // "id": "05b1ebbf-9438-5dd4-b297-2ddedc98d0e4", // "address": "coinbasebase", // "address_info": { // "address": "coinbasebase", // "destination_tag": "287594668" // }, // "name": null, // "created_at": "2019-07-01T14:39:29Z", // "updated_at": "2019-07-01T14:39:29Z", // "network": "eosio", // "uri_scheme": "eosio", // "resource": "address", // "resource_path": "/v2/accounts/14cfc769-e852-52f3-b831-711c104d194c/addresses/05b1ebbf-9438-5dd4-b297-2ddedc98d0e4", // "warnings": [ // { // "title": "Only send EOS (EOS) to this address", // "details": "Sending any other cryptocurrency will result in permanent loss.", // "image_url": "https://dynamic-assets.coinbase.com/deaca3d47b10ed4a91a872e9618706eec34081127762d88f2476ac8e99ada4b48525a9565cf2206d18c04053f278f693434af4d4629ca084a9d01b7a286a7e26/asset_icons/1f8489bb280fb0a0fd643c1161312ba49655040e9aaaced5f9ad3eeaf868eadc.png" // }, // { // "title": "Both an address and EOS memo are required to receive EOS", // "details": "If you send funds without an EOS memo or with an incorrect EOS memo, your funds cannot be credited to your account.", // "image_url": "https://www.coinbase.com/assets/receive-warning-2f3269d83547a7748fb39d6e0c1c393aee26669bfea6b9f12718094a1abff155.png" // } // ], // "warning_title": "Only send EOS (EOS) to this address", // "warning_details": "Sending any other cryptocurrency will result in permanent loss.", // "destination_tag": "287594668", // "deposit_uri": "eosio:coinbasebase?dt=287594668", // "callback_url": null // } // } // const data = this.safeDict(response, 'data', {}); const tag = this.safeString(data, 'destination_tag'); const address = this.safeString(data, 'address'); return { 'currency': code, 'tag': tag, 'address': address, 'network': undefined, 'info': response, }; } /** * @method * @name coinbase#fetchMySells * @ignore * @description fetch sells * @see https://docs.cloud.coinbase.com/sign-in-with-coinbase/docs/api-sells#list-sells * @param {string} symbol not used by coinbase fetchMySells () * @param {int} [since] timestamp in ms of the earliest sell, default is undefined * @param {int} [limit] max number of sells to return, default is undefined * @param {object} [params] extra parameters specific to the exchange API endpoint * @returns {object} a [list of order structures]{@link https://docs.ccxt.com/#/?id=order-structure} */ async fetchMySells(symbol = undefined, since = undefined, limit = undefined, params = {}) { // v2 did't have an endpoint for all historical trades const request = this.prepareAccountRequest(limit, params); await this.loadMarkets(); const query = this.omit(params, ['account_id', 'accountId']); const sells = await this.v2PrivateGetAccountsAccountIdSells(this.extend(request, query)); return this.parseTrades(sells['data'], undefined, since, limit); } /** * @method * @name coinbase#fetchMyBuys * @ignore * @description fetch buys * @see https://docs.cloud.coinbase.com/sign-in-with-coinbase/docs/api-buys#list-buys * @param {string} symbol not used by coinbase fetchMyBuys () * @param {int} [since] timestamp in ms of the earliest buy, default is undefined * @param {int} [limit] max number of buys to return, default is undefined * @param {object} [params] extra parameters specific to the exchange API endpoint * @returns {object} a list of [order structures]{@link https://docs.ccxt.com/#/?id=order-structure} */ async fetchMyBuys(symbol = undefined, since = undefined, limit = undefined, params = {}) { // v2 did't have an endpoint for all historical trades const request = this.prepareAccountRequest(limit, params); await this.loadMarkets(); const query = this.omit(params, ['account_id', 'accountId']); const buys = await this.v2PrivateGetAccountsAccountIdBuys(this.extend(request, query)); return this.parseTrades(buys['data'], undefined, since, limit); } async fetchTransactionsWithMethod(method, code = undefined, since = undefined, limit = undefined, params = {}) { let request = undefined; [request, params] = await this.prepareAccountRequestWithCurrencyCode(code, limit, params); await this.loadMarkets(); const response = await this[method](this.extend(request, params)); return this.parseTransactions(response['data'], undefined, since, limit); } /** * @method * @name coinbase#fetchWithdrawals * @description Fetch all withdrawals made from an account. Won't return crypto withdrawals. Use fetchLedger for those. * @see https://docs.cdp.coinbase.com/coinbase-app/docs/api-withdrawals#list-withdrawals * @param {string} code unified currency code * @param {int} [since] the earliest time in ms to fetch withdrawals for * @param {int} [limit] the maximum number of withdrawals structures to retrieve * @param {object} [params] extra parameters specific to the exchange API endpoint * @param {string} [params.currencyType] "fiat" or "crypto" * @returns {object[]} a list of [transaction structures]{@link https://docs.ccxt.com/#/?id=transaction-structure} */ async fetchWithdrawals(code = undefined, since = undefined, limit = undefined, params = {}) { let currencyType = undefined; [currencyType, params] = this.handleOptionAndParams(params, 'fetchWithdrawals', 'currencyType'); if (currencyType === 'crypto') { const results = await this.fetchTransactionsWithMethod('v2PrivateGetAccountsAccountIdTransactions', code, since, limit, params); return this.filterByArray(results, 'type', 'withdrawal', false); } return await this.fetchTransactionsWithMethod('v2PrivateGetAccountsAccountIdWithdrawals', code, since, limit, params); } /** * @method * @name coinbase#fetchDeposits * @description Fetch all fiat deposits made to an account. Won't return crypto deposits or staking rewards. Use fetchLedger for those. * @see https://docs.cdp.coinbase.com/coinbase-app/docs/api-deposits#list-deposits * @param {string} code unified currency code * @param {int} [since] the earliest time in ms to fetch deposits for * @param {int} [limit] the maximum number of deposits structures to retrieve * @param {object} [params] extra parameters specific to the exchange API endpoint * @param {string} [params.currencyType] "fiat" or "crypto" * @returns {object[]} a list of [transaction structures]{@link https://docs.ccxt.com/#/?id=transaction-structure} */ async fetchDeposits(code = undefined, since = undefined, limit = undefined, params = {}) { let currencyType = undefined; [currencyType, params] = this.handleOptionAndParams(params, 'fetchWithdrawals', 'currencyType'); if (currencyType === 'crypto') { const results = await this.fetchTransactionsWithMethod('v2PrivateGetAccountsAccountIdTransactions', code, since, limit, params); return this.filterByArray(results, 'type', 'deposit', false); } return await this.fetchTransactionsWithMethod('v2PrivateGetAccountsAccountIdDeposits', code, since, limit, params); } /** * @method * @name coinbase#fetchDepositsWithdrawals * @description fetch history of deposits and withdrawals * @see https://docs.cdp.coinbase.com/coinbase-app/docs/api-transactions * @param {string} [code] unified currency code for the currency of the deposit/withdrawals, default is undefined * @param {int} [since] timestamp in ms of the earliest deposit/withdrawal, default is undefined * @param {int} [limit] max number of deposit/withdrawals to return, default = 50, Min: 1, Max: 100 * @param {object} [params] extra parameters specific to the exchange API endpoint * @returns {object} a list of [transaction structure]{@link https://docs.ccxt.com/#/?id=transaction-structure} */ async fetchDepositsWithdrawals(code = undefined, since = undefined, limit = undefined, params = {}) { await this.loadMarkets(); const results = await this.fetchTransactionsWithMethod('v2PrivateGetAccountsAccountIdTransactions', code, since, limit, params); return this.filterByArray(results, 'type', ['deposit', 'withdrawal'], false); } parseTransactionStatus(status) { const statuses = { 'created': 'pending', 'completed': 'ok', 'canceled': 'canceled', }; return this.safeString(statuses, status, status); } parseTransaction(transaction, currency = undefined) { // // fiat deposit // // { // "id": "f34c19f3-b730-5e3d-9f72", // "status": "completed", // "payment_method": { // "id": "a022b31d-f9c7-5043-98f2", // "resource": "payment_method", // "resource_path": "/v2/payment-methods/a022b31d-f9c7-5043-98f2" // }, // "transaction": { // "id": "04ed4113-3732-5b0c-af86-b1d2146977d0", // "resource": "transaction", // "resource_path": "/v2/accounts/91cd2d36-3a91-55b6-a5d4-0124cf105483/transactions/04ed4113-3732-5b0c-af86" // }, // "user_reference": "2VTYTH", // "created_at": "2017-02-09T07:01:18Z", // "updated_at": "2017-02-09T07:01:26Z", // "resource": "deposit", // "resource_path": "/v2/accounts/91cd2d36-3a91-55b6-a5d4-0124cf105483/deposits/f34c19f3-b730-5e3d-9f72", // "committed": true, // "payout_at": "2017-02-12T07:01:17Z", // "instant": false, // "fee": { "amount": "0.00", "currency": "EUR" }, // "amount": { "amount": "114.02", "currency": "EUR" }, // "subtotal": { "amount": "114.02", "currency": "EUR" }, // "hold_until": null, // "hold_days": 0, // "hold_business_days": 0, // "next_step": null // } // // fiat_withdrawal // // { // "id": "cfcc3b4a-eeb6-5e8c-8058", // "status": "completed", // "payment_method": { // "id": "8b94cfa4-f7fd-5a12-a76a", // "resource": "payment_method", // "resource_path": "/v2/payment-methods/8b94cfa4-f7fd-5a12-a76a" // }, // "transaction": { // "id": "fcc2550b-5104-5f83-a444", // "resource": "transaction", // "resource_path": "/v2/accounts/91cd2d36-3a91-55b6-a5d4-0124cf105483/transactions/fcc2550b-5104-5f83-a444" // }, // "user_reference": "MEUGK", // "created_at": "2018-07-26T08:55:12Z", // "updated_at": "2018-07-26T08:58:18Z", // "resource": "withdrawal", // "resource_path": "/v2/accounts/91cd2d36-3a91-55b6-a5d4-0124cf105483/withdrawals/cfcc3b4a-eeb6-5e8c-8058", // "committed": true, // "payout_at": "2018-07-31T08:55:12Z", // "instant": false, // "fee": { "amount": "0.15", "currency": "EUR" }, // "amount": { "amount": "13130.69", "currency": "EUR" }, // "subtotal": { "amount": "13130.84", "currency": "EUR" }, // "idem": "e549dee5-63ed-4e79-8a96", // "next_step": null // } // // withdraw // // { // "id": "a1794ecf-5693-55fa-70cf-ef731748ed82", // "type": "send", // "status": "pending", // "amount": { // "amount": "-14.008308", // "currency": "USDC" // }, // "native_amount": { // "amount": "-18.74", // "currency": "CAD" // }, // "description": null, // "created_at": "2024-01-12T01:27:31Z", // "updated_at": "2024-01-12T01:27:31Z", // "resource": "transaction", // "resource_path": "/v2/accounts/a34bgfad-ed67-538b-bffc-730c98c10da0/transactions/a1794ecf-5693-55fa-70cf-ef731748ed82", // "instant_exchange": false, // "network": { // "status": "pending", // "status_description": "Pending (est. less than 10 minutes)", // "transaction_fee": { // "amount": "4.008308", // "currency": "USDC" // }, // "transaction_amount": { // "amount": "10.000000", // "currency": "USDC"