UNPKG

ccxt

Version:

A cryptocurrency trading API with more than 100 exchanges in JavaScript / TypeScript / Python / C# / PHP / Go

1,104 lines (1,100 loc) • 156 kB
'use strict'; Object.defineProperty(exports, '__esModule', { value: true }); var ed25519_js = require('@noble/curves/ed25519.js'); var pacifica$1 = require('./abstract/pacifica.js'); var errors = require('./base/errors.js'); var Precise = require('./base/Precise.js'); var number = require('./base/functions/number.js'); var crypto = require('./base/functions/crypto.js'); // ---------------------------------------------------------------------------- // --------------------------------------------------------------------------- /** * @class pacifica * @augments Exchange */ class pacifica extends pacifica$1["default"] { describe() { return this.deepExtend(super.describe(), { 'id': 'pacifica', 'name': 'Pacifica', 'countries': [], 'version': 'v1', 'isSandboxModeEnabled': false, // is testnet api 'rateLimit': 600, // 100 credits per minute without an API Config Key (300 with a key) 'certified': false, 'pro': true, 'dex': true, 'has': { 'CORS': undefined, 'spot': true, 'margin': false, 'swap': true, 'future': false, 'option': false, 'addMargin': false, 'borrowCrossMargin': false, 'borrowIsolatedMargin': false, 'cancelAllOrders': true, 'cancelAllOrdersAfter': false, 'cancelOrder': true, 'cancelOrders': true, 'cancelOrdersForSymbols': undefined, 'closeAllPositions': false, 'closePosition': false, 'createMarketBuyOrderWithCost': false, 'createMarketOrderWithCost': false, 'createMarketSellOrderWithCost': false, 'createOrder': true, 'createOrders': true, 'createOrderWithTakeProfitAndStopLoss': true, 'createReduceOnlyOrder': true, 'createStopOrder': true, 'editOrder': true, 'editOrders': false, 'fetchAccounts': false, 'fetchBalance': true, 'fetchBorrowInterest': false, 'fetchBorrowRateHistories': false, 'fetchBorrowRateHistory': false, 'fetchCanceledAndClosedOrders': true, 'fetchCanceledOrders': true, 'fetchClosedOrders': true, 'fetchCrossBorrowRate': false, 'fetchCrossBorrowRates': false, 'fetchCurrencies': false, 'fetchDepositAddress': false, 'fetchDepositAddresses': false, 'fetchDeposits': false, 'fetchDepositWithdrawFee': false, 'fetchDepositWithdrawFees': false, 'fetchFundingHistory': true, 'fetchFundingRate': false, 'fetchFundingRateHistory': true, 'fetchFundingRates': true, 'fetchIndexOHLCV': false, 'fetchIsolatedBorrowRate': false, 'fetchIsolatedBorrowRates': false, 'fetchLedger': true, 'fetchLeverage': true, 'fetchLeverageTiers': false, 'fetchLiquidations': false, 'fetchMarginMode': true, 'fetchMarketLeverageTiers': false, 'fetchMarkets': true, 'fetchMarkOHLCV': false, 'fetchMyLiquidations': false, 'fetchMyTrades': true, 'fetchOHLCV': true, 'fetchOpenInterest': true, 'fetchOpenInterestHistory': false, 'fetchOpenInterests': true, 'fetchOpenOrders': true, 'fetchOrder': true, 'fetchOrderBook': true, 'fetchOrders': true, 'fetchOrderTrades': false, 'fetchPosition': true, 'fetchPositionMode': false, 'fetchPositions': true, 'fetchPositionsRisk': false, 'fetchPremiumIndexOHLCV': false, 'fetchStatus': undefined, 'fetchTicker': 'emulated', 'fetchTickers': true, 'fetchTime': undefined, 'fetchTrades': true, 'fetchTradingFee': true, 'fetchTradingFees': false, 'fetchTransfer': false, 'fetchTransfers': false, 'fetchWithdrawal': false, 'fetchWithdrawals': false, 'reduceMargin': false, 'repayCrossMargin': false, 'repayIsolatedMargin': false, 'sandbox': true, 'setLeverage': true, 'setMarginMode': true, 'setPositionMode': false, 'transfer': true, 'withdraw': true, }, 'timeframes': { '1m': '1m', '3m': '3m', '5m': '5m', '15m': '15m', '30m': '30m', '1h': '1h', '2h': '2h', '4h': '4h', '8h': '8h', '12h': '12h', '1d': '1d', '1w': '1w', '1M': '1M', }, 'hostname': 'pacifica.fi', 'urls': { 'logo': 'https://github.com/user-attachments/assets/03ed021f-cdec-43c8-acb4-941f1282f610', 'api': { 'public': 'https://api.{hostname}', 'private': 'https://api.{hostname}', }, 'test': { 'public': 'https://test-api.{hostname}', 'private': 'https://test-api.{hostname}', }, 'www': 'https://www.pacifica.fi', 'doc': 'https://docs.pacifica.fi/api-documentation/api/rest-api', 'fees': 'https://docs.pacifica.fi/trading-on-pacifica/trading-fees', 'referral': 'https://app.pacifica.fi?referral=ccxt', }, 'api': { 'public': { 'get': { // ~12 weight depends on the limit 3 max for api-key, but min without api-key 'info': 1, 'info/fees': 1, 'info/prices': 1, 'kline': 12, 'kline/mark': 12, 'book': 1, 'trades': 1, // Recent 'funding_rate/history': 1, 'loan_pool': 1, 'account': 1, 'account/loan': 1, 'account/settings': 1, 'positions': 1, 'trades/history': 12, 'funding/history': 1, 'portfolio': 1, 'account/balance/history': 12, 'account/spot_balance/history': 1, 'account/spot_asset/deposit/history': 1, 'account/spot_asset/withdraw/history': 1, 'account/spot_asset/withdraw/pending': 1, 'orders': 1, 'orders/history': 12, 'orders/history_by_id': 1, 'spot_assets': 1, 'spot_assets/bridge/info': 1, 'spot_assets/bridge/parameters/{symbol}': 1, 'lake/list': 1, 'account/builder_codes/approvals': 1, }, }, 'private': { 'post': { 'account/leverage': 1, 'account/margin': 1, 'account/withdraw': 1, 'account/settings/auto_lend_disabled': 1, 'account/settings/spot': 1, 'account/spot_asset/withdraw': 1, 'account/subaccount/create': 1, 'account/subaccount/list': 1, 'account/subaccount/transfer': 1, 'account/subaccount/spot_asset/transfer': 1, 'positions/add_isolated_margin': 1, 'orders/create': 1, 'orders/create_market': 1, 'orders/stop/create': 1, 'positions/tpsl': 1, 'orders/cancel': 0.5, 'orders/cancel_all': 0.5, 'orders/stop/cancel': 0.5, 'orders/edit': 1, 'orders/batch': 1, 'account/builder_codes/approve': 1, 'account/builder_codes/revoke': 1, 'agent/bind': 1, 'account/api_keys/create': 1, 'account/api_keys/revoke': 1, 'account/api_keys': 1, 'lake/add_blacklist': 1, 'lake/add_max_leverage': 1, 'lake/add_whitelist': 1, 'lake/claim_manager': 1, 'lake/claim_referral_code': 1, 'lake/create': 1, 'lake/deposit': 1, 'lake/remove_blacklist': 1, 'lake/remove_max_leverage': 1, 'lake/remove_whitelist': 1, 'lake/update_deposit_cap': 1, 'lake/withdraw': 1, }, }, }, 'fees': { 'swap': { 'taker': this.parseNumber('0.0004'), 'maker': this.parseNumber('0.00015'), }, 'spot': { // https://docs.pacifica.fi/trading-on-pacifica/trading-fees // one unified fee schedule for all product types 'taker': this.parseNumber('0.0004'), 'maker': this.parseNumber('0.00015'), }, }, // // Reminder: // If you're using an agent wallet, its private key must also be in the privateKey field in requiredCredentials. // However, walletAddress must ALWAYS be equal to the main address. For the agent wallet address, there's a field in options: agentAddress // 'requiredCredentials': { 'apiKey': false, 'secret': false, 'walletAddress': false, // agentAddress, apiKey only in options. 'privateKey': true, // base58 solana private key }, 'exceptions': { 'exact': { '0': errors.ExchangeError, // INTERNAL '1': errors.ExchangeError, // ACCOUNT_NOT_FOUND '2': errors.ExchangeError, // ACCOUNT_ALREADY_EXISTS '3': errors.ExchangeError, // BOOK_NOT_FOUND '4': errors.InvalidOrder, // INVALID_TICK_LEVEL '5': errors.InsufficientFunds, // INSUFFICIENT_BALANCE '6': errors.OrderNotFound, // ORDER_NOT_FOUND '7': errors.InvalidOrder, // ORDER_AMOUNT_TOO_LOW '8': errors.InvalidOrder, // ORDER_AMOUNT_TOO_HIGH '9': errors.InsufficientFunds, // OVER_WITHDRAWAL '10': errors.InvalidOrder, // OPEN_ORDER_LIMIT_REACHED '11': errors.ExchangeError, // INVALID_LEVERAGE '12': errors.ExchangeError, // CANNOT_UPDATE_MARGIN '13': errors.ExchangeError, // POSITION_NOT_FOUND '14': errors.ExchangeError, // DATABASE_ERROR '15': errors.BadRequest, // INVALID_DEPOSIT_NONCE '16': errors.InvalidOrder, // INVALID_STOP_TICK '17': errors.InvalidOrder, // INVALID_STOP_ORDER_SIDE '18': errors.InvalidOrder, // INVALID_STOP_ORDER_AMOUNT '19': errors.InvalidOrder, // INVALID_STOP_ORDER_REDUCE_ONLY '20': errors.InvalidOrder, // INVALID_ORDER_TYPE '21': errors.InvalidOrder, // INVALID_REDUCE_ONLY_ORDER_SIDE '22': errors.InvalidOrder, // INVALID_REDUCE_ONLY_ORDER_AMOUNT '23': errors.InvalidOrder, // NO_POSITION_FOR_REDUCE_ONLY_ORDER '24': errors.ExchangeError, // INVALID_LIQUIDATION_SIDE '25': errors.InvalidOrder, // NO_REASONABLE_PRICE '26': errors.ExchangeError, // CHANNEL_CLOSED '27': errors.ExchangeError, // RESPONSE_DROPPED '28': errors.InvalidOrder, // IMMEDIATE_LIQUIDATION '29': errors.InvalidOrder, // WITHDRAW_AMOUNT_TOO_LOW '30': errors.InvalidOrder, // PRICE_TOO_FAR_FROM_MARK '31': errors.PermissionDenied, // DAILY_WITHDRAW_LIMIT_EXCEEDED '32': errors.PermissionDenied, // WITHDRAWAL_BLOCKED '33': errors.BadRequest, // INVALID_TRANSFER_RELATIONSHIP '34': errors.PermissionDenied, // SUBACCOUNT_WITHDRAWAL_NOT_ALLOWED '35': errors.PermissionDenied, // SUBACCOUNT_CANNOT_CREATE_SUBACCOUNT '36': errors.InvalidOrder, // DUPLICATE_CLIENT_ORDER_ID '37': errors.InvalidOrder, // UNUSED_CLIENT_ORDER_ID '38': errors.PermissionDenied, // TRADING_DISABLED '39': errors.BadRequest, // INVALID_FEE_MODE '40': errors.PermissionDenied, // NOT_MAIN_ACCOUNT '41': errors.InvalidOrder, // OPEN_INTEREST_LIMIT_EXCEEDED '42': errors.ExchangeError, // EXCHANGE_WITHDRAW_LIMIT_REACHED '43': errors.InvalidOrder, // TWAP_DUPLICATE_CLIENT_ORDER_ID '44': errors.InvalidOrder, // TWAP_UNUSED_CLIENT_ORDER_ID '45': errors.InvalidOrder, // TWAP_ORDER_FAIL_TO_GET_SUB_ORDER_AMOUNT '46': errors.InvalidOrder, // TWAP_ORDER_DURATION_TOO_SHORT '47': errors.OrderNotFound, // TWAP_ORDER_NOT_FOUND '48': errors.InvalidOrder, // TWAP_ORDER_COUNT_PER_SYMBOL_LIMIT_EXCEEDED '49': errors.InvalidOrder, // POSITION_TPSL_LIMIT_EXCEEDED '50': errors.BadRequest, // INVALID_BUILDER_CODE '51': errors.NotSupported, // UNSUPPORTED_OPERATION '52': errors.InvalidOrder, // INVALID_TICK_SIZE '53': errors.InvalidOrder, // ORDER_BLOCKED_BY_LOAN_POOL_STRESS '54': errors.ExchangeError, // ASSET_ALREADY_EXISTS '55': errors.ExchangeError, // ASSET_NOT_FOUND '56': errors.ExchangeError, // ASSET_NOT_ACTIVE '59': errors.InvalidOrder, // INVALID_AMOUNT '61': errors.InsufficientFunds, // SPOT_WITHDRAWAL_EXCEEDS_COLLATERAL '62': errors.InsufficientFunds, // INSUFFICIENT_SPOT_BALANCE '63': errors.ExchangeError, // MISSING_MARK_PRICE '64': errors.BadRequest, // INVALID_FLOOR_PRICE_PCT '65': errors.InsufficientFunds, // SPOT_EXCLUSION_BREACHES_COLLATERAL '66': errors.ExchangeError, // LAKE_NOT_FOUND '67': errors.ExchangeError, // LAKE_ADDRESS_COLLISION '68': errors.InvalidOrder, // LAKE_MIN_DEPOSIT_AMOUNT '69': errors.InvalidOrder, // LAKE_INVALID_SHARES '70': errors.InsufficientFunds, // LAKE_OVER_WITHDRAWAL '71': errors.ExchangeError, // LAKE_NICKNAME_ALREADY_EXISTS '72': errors.PermissionDenied, // LAKE_WITHDRAWAL_NOT_ALLOWED '73': errors.PermissionDenied, // LAKE_MANAGER_IS_SUBLAKE '74': errors.PermissionDenied, // LAKE_NOT_CREATOR '75': errors.InvalidOrder, // LAKE_DEPOSIT_CAP_EXCEEDED '76': errors.PermissionDenied, // LAKE_WITHDRAW_TOO_EARLY '77': errors.BadRequest, // LAKE_INVALID_REV_SHARE_CONFIG '78': errors.InsufficientFunds, // LAKE_DEPOSITOR_OVER_WITHDRAWAL '79': errors.ExchangeError, // LAKE_ALREADY_HAS_MANAGER '80': errors.InvalidOrder, // LAKE_MANAGER_BALANCE_PORTION_TOO_LOW '81': errors.BadRequest, // LAKE_INVALID_BALANCE_PORTION_CONFIG '82': errors.InvalidOrder, // LAKE_LIQUIDATION_PORTION_ABOVE_MIN_PORTION '83': errors.ExchangeNotAvailable, // LAKE_TRADING_HALTED '84': errors.BadRequest, // INVALID_WITHDRAW_NONCE '85': errors.BadRequest, // LAKE_INVALID_WITHDRAW_WINDOW_CONFIG '86': errors.BadRequest, // LAKE_WITHDRAW_DURATION_ABOVE_WINDOW '87': errors.PermissionDenied, // LAKE_WITHDRAW_WINDOW_CLOSED '88': errors.BadRequest, // INVALID_SPOT_DEPOSIT_NONCE '89': errors.BadRequest, // SPOT_DEPOSIT_NONCE_GAP '90': errors.BadRequest, // INVALID_SPOT_WITHDRAW_NONCE '91': errors.ExchangeError, // SPOT_BRIDGE_NOT_FOUND '92': errors.ExchangeNotAvailable, // SPOT_BRIDGE_INACTIVE '93': errors.BadRequest, // LAKE_SYMBOL_NOT_ALLOWED '94': errors.InvalidOrder, // LAKE_MAX_LEVERAGE_EXCEEDED '95': errors.ExchangeError, // GAME_CONFIG_NOT_FOUND '96': errors.ExchangeError, // GAME_ACCOUNT_NOT_FOUND '97': errors.ExchangeError, // GAME_ACCOUNT_ADDRESS_COLLISION '99': errors.InvalidOrder, // GAME_DEPOSIT_CAP_EXCEEDED '100': errors.PermissionDenied, // GAME_OPERATION_NOT_ALLOWED '101': errors.ExchangeNotAvailable, // GAME_ALREADY_ENDED '102': errors.BadRequest, // GAME_INVALID_CONFIG '103': errors.PermissionDenied, // GAME_ACCOUNT_WITHDRAWAL_NOT_ALLOWED '104': errors.InvalidOrder, // GAME_LEVERAGE_EXCEEDED '105': errors.InvalidOrder, // GAME_DEPOSIT_BELOW_MINIMUM '106': errors.NotSupported, // REDUCE_ONLY_NOT_SUPPORTED_FOR_SPOT '107': errors.NotSupported, // TP_SL_NOT_SUPPORTED_FOR_SPOT '108': errors.NotSupported, // BUILDER_CODE_NOT_SUPPORTED_FOR_SPOT '109': errors.NotSupported, // MARGIN_SETTINGS_NOT_APPLICABLE_FOR_SPOT '110': errors.BadRequest, // INVALID_BOOK_CONFIG '111': errors.ExchangeNotAvailable, // TAP_GAME_NOT_ACTIVE '112': errors.InvalidOrder, // TAP_GAME_INVALID_AMOUNT '113': errors.ExchangeError, // TAP_GAME_ERROR '114': errors.ExchangeError, // INVALID_COLLATERAL_LIMIT / LAKE_SELF_DEPOSIT_NOT_ALLOWED '115': errors.ExchangeError, // SPOT_COLLATERAL_LIMIT_BREACHES_COLLATERAL / LAKE_DEPOSITOR_NOT_WHITELISTED '116': errors.ExchangeError, // DAILY_SPOT_WITHDRAW_LIMIT_EXCEEDED / RFQ_SELF_QUOTE_NOT_ALLOWED '117': errors.ExchangeError, // EXCHANGE_SPOT_WITHDRAW_LIMIT_REACHED / RFQ_NOT_SUPPORTED_FOR_SPOT '118': errors.ExchangeError, // INVALID_SPOT_LIMIT / RFQ_MISSING_CLIENT_ORDER_ID '119': errors.ExchangeNotAvailable, // ORACLE_NOT_AVAILABLE '120': errors.PermissionDenied, // VAULT_WITHDRAWAL_NOT_ALLOWED '121': errors.InvalidOrder, // RFQ_QUOTE_WORSE_THAN_BOOK '400': errors.BadRequest, // Bad Request; INVALID_REQUEST_CODE '401': errors.AuthenticationError, // INVALID_SIGNATURE_CODE '402': errors.AuthenticationError, // INVALID_SIGNER_CODE '403': errors.PermissionDenied, // Forbidden: restricted region; UNAUTHORIZED_REQUEST_CODE '404': errors.BadRequest, // Not Found '409': errors.ExchangeError, // Conflict '420': errors.ExchangeError, // ENGINE_ERROR_CODE '422': errors.ExchangeError, // Business Logic Error - See below '429': errors.RateLimitExceeded, // Too Many Requests - Rate limit exceeded; RATE_LIMIT_EXCEEDED_CODE '500': errors.ExchangeError, // Internal Server Error; UNKNOWN_ERROR_CODE '503': errors.ExchangeNotAvailable, // Service Unavailable '504': errors.RequestTimeout, // Gateway Timeout }, 'broad': { 'UNKNOWN': errors.ExchangeError, 'ACCOUNT_NOT_FOUND': errors.ExchangeError, 'BOOK_NOT_FOUND': errors.ExchangeError, 'INVALID_TICK_LEVEL': errors.InvalidOrder, 'INSUFFICIENT_BALANCE': errors.InsufficientFunds, 'ORDER_NOT_FOUND': errors.OrderNotFound, 'OVER_WITHDRAWAL': errors.InsufficientFunds, 'INVALID_LEVERAGE': errors.ExchangeError, 'CANNOT_UPDATE_MARGIN': errors.ExchangeError, 'POSITION_NOT_FOUND': errors.ExchangeError, 'POSITION_TPSL_LIMIT_EXCEEDED': errors.InvalidOrder, }, }, 'precisionMode': number.TICK_SIZE, 'commonCurrencies': {}, 'options': { 'agentAddress': undefined, 'apiKey': undefined, 'builderCode': 'CCXT', // case sensitive 'feeRate': '0.01', // default rate for builder fee approval 0.01% 'builderFee': true, 'batchOrdersMax': 10, 'defaultType': 'swap', 'defaultSlippage': '0.5', 'expiryWindow': 5000, 'maxCostHugeWithApiKey': 4, 'marketHelperProps': [], 'defaultMarginMode': 'cross', 'builderSupportOperations': { 'create_market_order': true, 'create_limit_order': true, 'create_stop_order': true, 'set_position_tpsl': true, }, }, 'features': { 'default': { 'sandbox': true, 'createOrder': { 'marginMode': false, 'triggerPrice': false, 'triggerPriceType': undefined, 'triggerDirection': false, 'stopLossPrice': false, 'takeProfitPrice': false, 'attachedStopLossTakeProfit': { 'triggerPriceType': { 'last': false, 'mark': false, 'index': false, }, 'triggerPrice': true, 'type': true, 'price': true, }, 'timeInForce': { 'IOC': true, 'FOK': false, 'PO': true, 'GTD': false, }, 'hedged': false, 'trailing': false, 'leverage': false, 'marketBuyByCost': false, 'marketBuyRequiresPrice': false, 'selfTradePrevention': false, 'iceberg': false, }, 'createOrders': { 'max': 10, }, 'editOrder': { 'side': false, 'type': false, }, 'fetchMyTrades': { 'marginMode': false, 'limit': 100, 'daysBack': undefined, 'untilDays': undefined, 'symbolRequired': false, }, 'fetchOrder': { 'marginMode': false, 'trigger': false, 'trailing': false, 'symbolRequired': false, }, 'fetchOpenOrders': { 'marginMode': false, 'limit': 100, 'trigger': false, 'trailing': false, 'symbolRequired': false, }, 'fetchOrders': { 'marginMode': false, 'limit': 100, 'daysBack': undefined, 'untilDays': undefined, 'trigger': false, 'trailing': false, 'symbolRequired': false, }, 'fetchClosedOrders': { 'marginMode': false, 'limit': 100, 'daysBack': undefined, 'daysBackCanceled': undefined, 'untilDays': undefined, 'trigger': false, 'trailing': false, 'symbolRequired': false, }, 'fetchOHLCV': { 'limit': 3950, }, 'fetchLedger': { 'code': false, }, }, 'forPerps': { 'extends': 'default', 'createOrder': { 'stopLossPrice': true, 'takeProfitPrice': true, 'attachedStopLossTakeProfit': undefined, }, }, 'spot': undefined, 'swap': { 'linear': { 'extends': 'forPerps', }, 'inverse': { 'extends': 'forPerps', }, }, 'future': { 'linear': { 'extends': 'forPerps', }, 'inverse': { 'extends': 'forPerps', }, }, }, }); } async initializeClient() { try { await this.handleBuilderFeeApproval(); } catch (e) { return false; } return true; } async handleBuilderFeeApproval() { if (this.isSandboxModeEnabled) { // At this stage, building codes are mostly only on the mainnet. return false; } const buildFee = this.safeBool(this.options, 'builderFee', true); if (!buildFee) { return false; // skip if builder fee is not enabled } const approvedBuilderFee = this.safeBool(this.options, 'approvedBuilderFee', false); if (approvedBuilderFee) { return true; // skip if builder fee is already approved } try { const builder = this.safeString(this.options, 'builderCode', 'CCXT'); // case sensitive const maxFeeRate = this.safeString(this.options, 'feeRate', '0.01'); await this.approveBuilderCode(builder, maxFeeRate); this.options['approvedBuilderFee'] = true; } catch (e) { this.options['builderFee'] = false; // disable builder fee if an error occurs } return true; } /** * @method * @name pacifica#fetchMarkets * @description retrieves data on all markets for pacifica * @see https://docs.pacifica.fi/api-documentation/api/rest-api/markets/get-market-info * @param {object} [params] extra parameters specific to the exchange API endpoint * @returns {object[]} an array of [market structures](https://docs.ccxt.com/#/?id=market-structure) */ async fetchMarkets(params = {}) { const response = await this.publicGetInfo(params); // meta // { // "success": true, // "data": [ // { // "symbol": "BTC", // "tick_size": "1", // "min_tick": "0", // "max_tick": "1000000", // "lot_size": "0.00001", // "max_leverage": 50, // "isolated_only": false, // "min_order_size": "10", // "max_order_size": "5000000", // "funding_rate": "0.0000125", // "next_funding_rate": "0.0000125", // "created_at": 1748881333944, // "instrument_type": "perpetual", // "base_asset": "BTC" // }, // { // "symbol": "SOL-USDC", // "tick_size": "0.01", // "min_tick": "0", // "max_tick": "1000000", // "lot_size": "0.001", // "max_leverage": 1, // "isolated_only": false, // "min_order_size": "10", // "max_order_size": "1000000", // "funding_rate": "0", // "next_funding_rate": "0", // "created_at": 1776615970246, // "instrument_type": "spot", // "base_asset": "SOL" // }, // ], // "error": null, // "code": null // } const markets = this.safeList(response, 'data', []); return this.parseMarkets(markets); } /** * @method * @name pacifica#fetchSwapMarkets * @description retrieves data on all swap markets for pacifica * @see https://docs.pacifica.fi/api-documentation/api/rest-api/markets/get-market-info * @param {object} [params] extra parameters specific to the exchange API endpoint * @returns {object[]} an array of objects representing market data */ async fetchSwapMarkets(params = {}) { const markets = await this.fetchMarkets(params); return this.filterBy(markets, 'type', 'swap'); } parseMarket(market) { // { // "symbol": "BTC", // "tick_size": "1", // "min_tick": "0", // "max_tick": "1000000", // "lot_size": "0.00001", // "max_leverage": 50, // "isolated_only": false, // "min_order_size": "10", // "max_order_size": "5000000", // "funding_rate": "0.0000125", // "next_funding_rate": "0.0000125", // "created_at": 1748881333944, // "instrument_type": "perpetual", // "base_asset": "BTC" // }, // { // "symbol": "SOL-USDC", // "tick_size": "0.01", // "min_tick": "0", // "max_tick": "1000000", // "lot_size": "0.001", // "max_leverage": 1, // "isolated_only": false, // "min_order_size": "10", // "max_order_size": "1000000", // "funding_rate": "0", // "next_funding_rate": "0", // "created_at": 1776615970246, // "instrument_type": "spot", // "base_asset": "SOL" // }, const id = this.safeString(market, 'symbol'); const baseId = this.safeString(market, 'base_asset', id); const instrumentType = this.safeString(market, 'instrument_type'); const isSpot = (instrumentType === 'spot'); const isSwap = !isSpot; let quoteId = 'USDC'; let settleId = undefined; let type = 'spot'; let linear = undefined; let inverse = undefined; let contractSize = undefined; let minLeverage = undefined; let maxLeverage = undefined; let crossMargin = undefined; let isolatedMargin = undefined; if (id === undefined) { throw new errors.ExchangeError(this.id + ' parseMarket() missing id'); } if (isSpot) { const idParts = id.split('-'); quoteId = this.safeString(idParts, 1, quoteId); } const isolatedOnly = this.safeBool(market, 'isolated_only', false); if (isSwap) { settleId = quoteId; type = 'swap'; linear = true; inverse = false; contractSize = this.parseNumber('1'); minLeverage = 1; maxLeverage = this.safeInteger(market, 'max_leverage'); crossMargin = !isolatedOnly; isolatedMargin = true; } const base = this.safeCurrencyCode(baseId); const quote = this.safeCurrencyCode(quoteId); const settle = this.safeCurrencyCode(settleId); let symbol = base + '/' + quote; if (isSwap) { symbol = symbol + ':' + settle; } const fees = this.safeDict(this.fees, type, {}); const taker = this.safeNumber(fees, 'taker'); const maker = this.safeNumber(fees, 'maker'); const amountPrecision = this.safeNumber(market, 'lot_size'); const pricePrecision = this.safeNumber(market, 'tick_size'); const active = true; // there is no non-active markets comes from endpoint market info return this.safeMarketStructure({ 'id': id, 'symbol': symbol, 'base': base, 'quote': quote, 'settle': settle, 'baseId': baseId, 'quoteId': quoteId, 'settleId': settleId, 'type': type, 'spot': isSpot, 'margin': false, 'swap': isSwap, 'future': false, 'option': false, 'active': active, 'contract': isSwap, 'linear': linear, 'inverse': inverse, 'taker': taker, 'maker': maker, 'contractSize': contractSize, 'expiry': undefined, 'expiryDatetime': undefined, 'strike': undefined, 'optionType': undefined, 'precision': { 'amount': amountPrecision, 'price': pricePrecision, }, 'limits': { 'leverage': { 'min': minLeverage, 'max': maxLeverage, }, 'amount': { 'min': undefined, 'max': undefined, }, 'price': { 'min': this.safeNumber(market, 'min_tick'), 'max': this.safeNumber(market, 'max_tick'), }, 'cost': { 'min': this.safeNumber(market, 'min_order_size'), 'max': this.safeNumber(market, 'max_order_size'), }, }, 'created': this.safeInteger(market, 'created_at'), 'marginModes': { 'cross': crossMargin, 'isolated': isolatedMargin, }, 'info': market, }); } /** * @method * @name pacifica#fetchBalance * @description query for balance and get the amount of funds available for trading or funds locked in orders * @see https://docs.pacifica.fi/api-documentation/api/rest-api/account/get-account-info * @param {object} [params] extra parameters specific to the exchange API endpoint * @param {string} [params.account] will default to walletAddress if not provided * @returns {object} a [balance structure]{@link https://docs.ccxt.com/?id=balance-structure} */ async fetchBalance(params = {}) { let userAccount = undefined; [userAccount, params] = this.handleOriginAndSingleAddress('fetchBalance', params); const request = { 'account': userAccount, }; const response = await this.publicGetAccount(this.extend(request, params)); // { // "success": true, // "data": { // "balance": "2000.000000", // "fee_level": 0, // "maker_fee": "0.00015", // "taker_fee": "0.0004", // "account_equity": "2150.250000", // "available_to_spend": "1800.750000", // "available_to_withdraw": "1500.850000", // "pending_balance": "0.000000", // "total_margin_used": "349.500000", // "cross_mmr": "420.690000", // "positions_count": 2, // "orders_count": 3, // "stop_orders_count": 1, // "updated_at": 1716200000000, // "use_ltp_for_stop_orders": false // }, // "error": null, // "code": null // } const data = this.safeDict(response, 'data', {}); const result = { 'info': data, }; result['free'] = {}; result['used'] = {}; result['total'] = {}; const totalBalance = this.safeNumber(data, 'account_equity'); const usedMargin = this.safeNumber(data, 'total_margin_used'); const freeBalance = this.safeNumber(data, 'available_to_spend'); result['total']['USDC'] = totalBalance; result['used']['USDC'] = usedMargin; result['free']['USDC'] = freeBalance; const timestamp = this.safeInteger(data, 'updated_at'); result['timestamp'] = timestamp; result['datetime'] = this.iso8601(timestamp); return this.safeBalance(result); } /** * @method * @name pacifica#fetchLeverage * @description fetch the set leverage for a market * @see https://docs.pacifica.fi/api-documentation/api/rest-api/account/get-account-settings * @param {string} symbol unified symbol of the market * @param {object} [params] extra parameters specific to the exchange API endpoint * @param {string} [params.account] will default to walletAddress if not provided * @returns {object} a [leverage structure]{@link https://docs.ccxt.com/?id=leverage-structure} */ async fetchLeverage(symbol, params = {}) { await this.loadAccountSettings(); if (this.markets === undefined) { await this.loadMarkets(); } const market = this.market(symbol); let userAccount = undefined; [userAccount, params] = this.handleOriginAndSingleAddress('fetchLeverage', params); const cacheAddress = this.walletAddress; let settings = undefined; if (userAccount === cacheAddress) { settings = this.handleOption('fetchLeverage', 'settings'); } else { const request = { 'account': userAccount, }; settings = await this.fetchAccountSettings(this.extend(request, params)); } const setting = this.safeDict(settings, symbol); if (setting === undefined) { // NOTE: Upon account creation, all markets have margin settings default to cross margin and leverage default to max. // When querying this endpoint, all markets with default margin and leverage settings on this account will return blank. return this.parseLeverageFromMarket(market); } else { return this.parseLeverageFromSetting(symbol, setting); } } parseLeverageFromSetting(symbol, setting) { // { // "WLFI/USDC:USDC": { // "symbol": "WLFI", // "isolated": false, // "leverage": 5, // "created_at": 1758085929703, // "updated_at": 1758086074002 // }, // } const isIsolated = this.safeBool(setting, 'isolated', false); const leverage = this.safeInteger(setting, 'leverage'); const marginMode = isIsolated ? 'isolated' : 'cross'; return { 'info': setting, 'symbol': symbol, 'marginMode': marginMode, 'longLeverage': leverage, 'shortLeverage': leverage, }; } parseLeverageFromMarket(market) { const marketLimits = this.safeDict(market, 'limits', {}); const leverageLimits = this.safeDict(marketLimits, 'leverage', {}); return { 'info': market, 'symbol': this.safeString(market, 'symbol'), 'marginMode': this.handleOption('fetchLeverage', 'defaultMarginMode', 'cross'), 'longLeverage': this.safeInteger(leverageLimits, 'max'), 'shortLeverage': this.safeInteger(leverageLimits, 'max'), }; } /** * @method * @name pacifica#fetchAccountSettings * @description fetch account's market settings. Settings are cached for walletAddress. To refresh the cache, call loadAccountSettings with refresh=true * @see https://docs.pacifica.fi/api-documentation/api/rest-api/account/get-account-settings * @param {object} [params] extra parameters specific to the exchange API endpoint * @param {string} [params.account] will default to walletAddress if not provided * @returns {object} Dict repacked from list by symbol key */ async fetchAccountSettings(params = {}) { let userAccount = undefined; [userAccount, params] = this.handleOriginAndSingleAddress('fetchAccountSettings', params); const request = { 'account': userAccount, }; const response = await this.publicGetAccountSettings(this.extend(request, params)); // { // "success": true, // "data": [ // { // "symbol": "WLFI", // "isolated": false, // "leverage": 5, // "created_at": 1758085929703, // "updated_at": 1758086074002 // } // ], // "error": null, // "code": null // } return this.parseAccountSettings(this.safeList(response, 'data', [])); } async loadAccountSettings(refresh = false, params = {}) { let settings = this.handleOption('loadAccountSettings', 'settings'); if ((settings === undefined) || (refresh === true)) { this.options['settings'] = this.createSafeDictionary(); settings = await this.fetchAccountSettings(params); this.options['settings'] = settings; } } parseAccountSettings(settings) { const settingsLen = settings.length; if (settingsLen === 0) { return {}; } const settingsBySymbol = {}; for (let i = 0; i < settings.length; i++) { const marketId = settings[i]['symbol']; const market = this.safeMarket(marketId); const symbol = market['symbol']; settingsBySymbol[symbol] = settings[i]; } return settingsBySymbol; } /** * @method * @name pacifica#fetchMarginMode * @description fetches the margin mode of the trading pair * @see https://docs.pacifica.fi/api-documentation/api/rest-api/account/get-account-settings * @param {string} symbol unified symbol of the market to fetch the margin mode for * @param {object} [params] extra parameters specific to the exchange API endpoint * @param {string} [params.account] will default to walletAddress if not provided * @returns {object} a [margin mode structure]{@link https://docs.ccxt.com/?id=margin-mode-structure} */ async fetchMarginMode(symbol, params = {}) { await this.loadAccountSettings(); let userAccount = undefined; [userAccount, params] = this.handleOriginAndSingleAddress('fetchMarginMode', params); const cacheAddress = this.walletAddress; let settings = undefined; if (userAccount === cacheAddress) { settings = this.handleOption('fetchMarginMode', 'settings'); } else { const request = { 'account': userAccount, }; settings = await this.fetchAccountSettings(this.extend(request, params)); } // { // "WLFI/USDC:USDC": { // "symbol": "WLFI", // "isolated": false, // "leverage": 5, // "created_at": 1758085929703, // "updated_at": 1758086074002 // }, // } const setting = this.safeDict(settings, symbol); if (setting === undefined) { // NOTE: Upon account creation, all markets have margin settings default to cross margin and leverage default to max. // When querying this endpoint, all markets with default margin and leverage settings on this account will return blank. return { 'symbol': symbol, 'marginMode': this.handleOption('fetchMarginMode', 'defaultMarginMode', 'cross'), }; } else { return this.parseMarginModeFromSetting(symbol, setting); } } parseMarginModeFromSetting(symbol, setting) { // { // "symbol": "WLFI", // "isolated": false, // "leverage": 5, // "created_at": 1758085929703, // "updated_at": 1758086074002 // // } const isIsolated = this.safeBool(setting, 'isolated', false); const marginMode = isIsolated ? 'isolated' : 'cross'; return { 'symbol': symbol, 'marginMode': marginMode, 'info': setting, }; } /** * @method * @name pacifica#fetchOrderBook * @description fetches information on open orders with bid (buy) and ask (sell) prices, volumes and other data * @see https://docs.pacifica.fi/api-documentation/api/rest-api/markets/get-orderbook * @param {string} symbol unified symbol of the market to fetch the order book for * @param {int} [limit] the maximum amount of order book entries to return * @param {object} [params] extra parameters specific to the exchange API endpoint * @param {int} [params.aggLevel] aggregation level for price grouping. Defaults to 1. Can be 1, 10, 100, 1000, 10000 * @returns {object} an [order book structure]{@link https://docs.ccxt.com/?id=order-book-structure} */ async fetchOrderBook(symbol, limit = undefined, params = {}) { if (this.markets === undefined) { await this.loadMarkets(); } const market = this.market(symbol); let aggLevel = undefined; [aggLevel, params] = this.handleOptionAndParams(params, 'fetchOrderBook', 'aggLevel', 1); const request = { 'symbol': market['id'], 'agg_level': aggLevel, }; const response = await this.publicGetBook(this.extend(request, params)); // { // "success": true, // "data": { // "s": "BTC", // "l": [ // [ // { // "p": "106504", // "a": "0.26203", // "n": 1 // }, // { // "p": "106498", // "a": "0.29281", // "n": 1 // } // ], // [ // { // "p": "106559", // "a": "0.26802", // "n": 1 // }, // { // "p": "106564", // "a": "0.3002", // "n": 1 // }, // ] // ], // "t": 1751370536325 // }, // "error": null, // "code": null // } const data = this.safeDict(response, 'data', {}); const levels = this.safeList(data, 'l', []); const result = { 'bids': this.safeList(levels, 0, []), 'asks': this.safeList(levels, 1, []), }; const timestamp = this.safeInteger(data, 't'); return this.parseOrderBook(result, this.safeSymbol(undefined, market), timestamp, 'bids', 'asks', 'p', 'a'); } /** * @method * @name pacifica#fetchFundingRates * @description retrieves data on all swap markets for pacifica * @see https://docs.pacifica.fi/api-documentation/api/rest-api/markets/get-prices * @param {string[]} [symbols] list of unified market symbols * @param {object} [params] extra parameters specific to the exchange API endpoint * @returns {object[]} an array of objects representing market data */ async fetchFundingRates(symbols = undefined, params = {}) { const response = await this.publicGetInfoPrices(params); // // { // "success": true, // "data": [ // { // "funding": "0.00010529", // "mark": "1.084819", // "mid": "1.08615",