ccxt
Version:
1,104 lines (1,100 loc) • 156 kB
JavaScript
'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",