ccxt
Version:
1,123 lines (1,119 loc) • 59.9 kB
JavaScript
'use strict';
Object.defineProperty(exports, '__esModule', { value: true });
var pacifica$1 = require('../pacifica.js');
var errors = require('../base/errors.js');
var Cache = require('../base/ws/Cache.js');
// ---------------------------------------------------------------------------
// ---------------------------------------------------------------------------
class pacifica extends pacifica$1["default"] {
describe() {
return this.deepExtend(super.describe(), {
'has': {
'ws': true,
'cancelOrderWs': true,
'cancelOrdersWs': true,
'cancelAllOrdersWs': true,
'createOrderWs': true,
'createOrdersWs': true,
'editOrderWs': true,
'watchBalance': false,
'watchMyTrades': true,
'watchOHLCV': true,
'watchOrderBook': true,
'watchOrders': true,
'watchTicker': true,
'watchTickers': true,
'watchTrades': true,
'watchTradesForSymbols': false,
'watchPosition': false,
'unWatchOrderBook': true,
'unWatchTickers': true,
'unWatchTrades': true,
'unWatchOHLCV': true,
'unWatchMyTrades': true,
'unWatchOrders': true,
},
'urls': {
'api': {
'ws': {
'public': 'wss://ws.pacifica.fi/ws',
},
},
'test': {
'ws': {
'public': 'wss://test-ws.pacifica.fi/ws',
},
},
},
'options': {
'ws': {
'options': {
'headers': {},
},
},
},
'streaming': {
'ping': this.ping,
'keepAlive': 20000,
},
'exceptions': {
'ws': {
'exact': {},
},
},
});
}
setupApiKeyHeaders(key = undefined) {
const headers = {};
if (key !== undefined) {
headers['PF-API-KEY'] = key;
}
else {
if (this.handleOption('setupApiKeyHeaders', 'apiKey', undefined) !== undefined) {
headers['PF-API-KEY'] = this.options['apiKey'];
}
}
this.options['ws']['options']['headers'] = headers;
}
/**
* @method
* @name pacifica#createOrderWs
* @description create a trade order
* @see https://docs.pacifica.fi/api-documentation/api/websocket/trading-operations/create-market-order
* @see https://docs.pacifica.fi/api-documentation/api/websocket/trading-operations/create-limit-order
* @param {string} symbol unified symbol of the market to create an order in
* @param {string} type 'market' or 'limit'
* @param {string} side 'buy' or 'sell'
* @param {float} amount how much of currency you want to trade in units of base currency
* @param {float} [price] the price at which the order is to be fullfilled, in units of the quote currency, ignored in market orders
* @param {object} [params] extra parameters specific to the exchange API endpoint
* @param {float} [params.triggerPrice] The price a trigger order is triggered at
* @param {float|undefined} [params.stopLossPrice] the price that a stop loss order is triggered at (optional provide stopLossCloid)
* @param {float|undefined} [params.takeProfitPrice] the price that a take profit order is triggered at (optional provide takeProfitCloid)
* @param {string|undefined} [params.timeInForce] "GTC", "IOC", or "PO" or "ALO" or "PO_TOB" (or "TOB" - PO by top of book)
* @param {bool|undefined} [params.reduceOnly] Ensures that the executed order does not flip the opened position.
* @param {string|undefined} [params.clientOrderId] client order id, (optional uuid v4 e.g.: f47ac10b-58cc-4372-a567-0e02b2c3d479)
* @param {int|undefined} [params.expiryWindow] time to live in milliseconds
* @param {string|undefined} [params.agentAddress] only if agent wallet in use.
* @param {string|undefined} [params.originAddress] only if agent in use. Agent's owner address ( default = credentials walletAddress )
* @returns {object} an [order structure]{@link https://docs.ccxt.com/?id=order-structure}
*/
async createOrderWs(symbol, type, side, amount, price = undefined, params = {}) {
await this.loadMarkets();
const [request, operationType] = this.createOrderRequest(symbol, type, side, amount, price, params);
params = this.omit(params, [
'reduceOnly', 'clientOrderId', 'stopLimitPrice', 'timeInForce', 'triggerPrice', 'stopLossCloid',
'stopLossPrice', 'stopLossLimitPrice', 'takeProfitCloid', 'takeProfitPrice', 'takeProfitLimitPrice', 'expiryWindow', 'agentAddress', 'originAddress',
]);
const isTestnet = this.isSandboxModeEnabled;
const urlKey = (isTestnet) ? 'test' : 'api';
const url = this.urls[urlKey]['ws']['public'];
const wsRequest = this.wrapAsPostAction(operationType, request);
const requestId = this.safeString(wsRequest, 'id');
if (operationType === 'create_stop_order') {
throw new errors.NotSupported(this.id + ' createOrderWs() do not support stop order type of order. Check provided arguments correctly!');
}
else if (operationType === 'set_position_tpsl') {
throw new errors.NotSupported(this.id + ' createOrderWs() do not support set position tpsl type of order. Check provided arguments correctly!');
}
const response = await this.watch(url, requestId, wsRequest, requestId);
//
// market order
// {
// "code": 200,
// "data": {
// "I": "79f948fd-7556-4066-a128-083f3ea49322",
// "i": 645953,
// "s": "BTC"
// },
// "id": "660065de-8f32-46ad-ba1e-83c93d3e3966",
// "t": 1749223025962,
// "type": "create_market_order"
// }
//
// limit order
// {
// "code": 200,
// "data": {
// "I": "79f948fd-7556-4066-a128-083f3ea49322",
// "i": 645953,
// "s": "BTC"
// },
// "id": "660065de-8f32-46ad-ba1e-83c93d3e3966",
// "t": 1749223025962,
// "type": "create_order"
// }
//
const code = this.safeInteger(response, 'code');
let success = false;
if (code === 200) {
success = true;
}
let status = undefined;
if (!success) {
status = 'rejected';
}
else {
status = 'open';
}
const order = this.safeDict(response, 'data', {});
const orderId = this.safeString(order, 'i');
const clientOrderId = this.safeString(order, 'I');
return this.safeOrder({ 'id': orderId, 'clientOrderId': clientOrderId, 'status': status, 'info': response, 'symbol': symbol });
}
/**
* @method
* @name pacifica#editOrderWs
* @description edit a trade order
* @see https://docs.pacifica.fi/api-documentation/api/websocket/trading-operations/edit-order
* @param {string} id edit order id
* @param {string} symbol unified symbol of the market to edit an order in
* @param {string} type 'market' or 'limit'
* @param {string} side 'buy' or 'sell'
* @param {float} amount how much of currency you want to trade in units of base currency
* @param {float} price the price at which the order is to be fulfilled, in units of the quote currency
* @param {object} [params] extra parameters specific to the exchange API endpoint
* @param {string} [params.clientOrderId] client order id, (optional uuid v4 e.g.: f47ac10b-58cc-4372-a567-0e02b2c3d479)
* @param {int|undefined} [params.expiryWindow] time to live in milliseconds
* @param {string|undefined} [params.agentAddress] only if agent wallet in use
* @param {string|undefined} [params.originAddress] only if agent in use. Agent's owner address ( default = credentials walletAddress )
* @returns {object} an [order structure]{@link https://docs.ccxt.com/?id=order-structure}
*/
async editOrderWs(id, symbol, type, side, amount = undefined, price = undefined, params = {}) {
const batchOperationType = 'edit_order';
await this.loadMarkets();
const market = this.market(symbol);
const request = this.editOrderRequest(id, symbol, type, side, amount, price, market, params);
params = this.omit(params, ['originAddress', 'agentAddress', 'expiryWindow', 'clientOrderId']);
const isTestnet = this.isSandboxModeEnabled;
const urlKey = (isTestnet) ? 'test' : 'api';
const url = this.urls[urlKey]['ws']['public'];
const wsRequest = this.wrapAsPostAction(batchOperationType, request);
const requestId = this.safeString(wsRequest, 'id');
const response = await this.watch(url, requestId, wsRequest, requestId);
// {
// "code": 200,
// "data": {
// "I": "f47ac10b-58cc-4372-a567-0e02b2c3d479",
// "i": 645954,
// "s": "BTC"
// },
// "id": "660065de-8f32-46ad-ba1e-83c93d3e3966",
// "t": 1749223026150,
// "type": "edit_order"
// }
const code = this.safeInteger(response, 'code');
let success = false;
if (code === 200) {
success = true;
}
let status = undefined;
if (!success) {
status = 'rejected';
}
else {
status = 'open';
}
const order = this.safeDict(response, 'data', {});
const orderId = this.safeString(order, 'i');
const clientOrderId = this.safeString(order, 'I');
return this.safeOrder({ 'id': orderId, 'clientOrderId': clientOrderId, 'status': status, 'info': response, 'symbol': symbol });
}
/**
* @method
* @name pacifica#cancelOrdersWs
* @description cancel multiple orders
* @see https://docs.pacifica.fi/api-documentation/api/websocket/trading-operations/batch-order
* @see https://docs.pacifica.fi/api-documentation/api/websocket/trading-operations/cancel-order
* @param {string[]} ids order ids
* @param {string} [symbol] unified market symbol
* @param {object} [params] extra parameters specific to the exchange API endpoint
* @param {string|string[]} [params.clientOrderId] client order ids, (optional uuid v4 e.g.: f47ac10b-58cc-4372-a567-0e02b2c3d479)
* @param {int|undefined} [params.expiryWindow] time to live in milliseconds
* @param {string|undefined} [params.agentAddress] only if agent wallet in use
* @param {string|undefined} [params.originAddress] only if agent in use. Agent's owner address ( default = credentials walletAddress )
* @returns {object} an list of [order structures]{@link https://docs.ccxt.com/?id=order-structure}
*/
async cancelOrdersWs(ids, symbol = undefined, params = {}) {
const batchOperationType = 'batch_orders';
await this.loadMarkets();
if (symbol === undefined) {
throw new errors.ArgumentsRequired(this.id + 'cancelOrders() requires a "symbol" argument!');
}
const request = this.cancelOrdersRequest(ids, symbol, params);
params = this.omit(params, ['originAddress', 'agentAddress', 'expiryWindow', 'clientOrderIds']);
const isTestnet = this.isSandboxModeEnabled;
const urlKey = (isTestnet) ? 'test' : 'api';
const url = this.urls[urlKey]['ws']['public'];
const wsRequest = this.wrapAsPostAction(batchOperationType, request);
const requestId = this.safeString(wsRequest, 'id');
const response = await this.watch(url, requestId, wsRequest, requestId);
//
// {
// "code": 200,
// "data": {
// "results": [
// {
// "success": true,
// "order_id": 645953,
// "client_order_id": "57a5efb1-bb96-49a5-8bfd-f25d5f22bc7e",
// "symbol": "BTC"
// },
// {
// "success": true,
// "order_id": 645954,
// "symbol": "ETH"
// }
// ]
// },
// "id": "660065de-8f32-46ad-ba1e-83c93d3e3966",
// "t": 1749223025962,
// "type": "batch_orders"
// }
//
const data = this.safeDict(response, 'data', {});
const results = this.safeList(data, 'results', []);
const ordersToReturn = [];
for (let i = 0; i < results.length; i++) {
const order = results[i];
const error = this.safeString(order, 'error', undefined);
const success = this.safeBool(order, 'success', false);
const marketId = this.safeString(order, 'symbol');
const market = this.safeMarket(marketId);
const orderId = this.safeString(order, 'i');
const clientOrderId = this.safeString(order, 'I');
let status = undefined;
if ((error !== undefined) || (!success)) {
status = 'closed';
}
else {
status = 'canceled';
}
ordersToReturn.push(this.safeOrder({ 'id': orderId, 'clientOrderId': clientOrderId, 'status': status, 'info': response, 'symbol': market['symbol'] }));
}
return ordersToReturn;
}
/**
* @method
* @name pacifica#cancelOrderWs
* @description cancels an open order
* @see https://docs.pacifica.fi/api-documentation/api/websocket/trading-operations/cancel-order
* @param {string} id order id
* @param {string} symbol unified symbol of the market the order was made in
* @param {object} [params] extra parameters specific to the exchange API endpoint
* @param {bool|undefined} [params.stop] necessary if this is to cancel a stop order.
* @param {string|undefined} [params.clientOrderId] client order id, (optional uuid v4 e.g.: f47ac10b-58cc-4372-a567-0e02b2c3d479)
* @param {int|undefined} [params.expiryWindow] time to live in milliseconds
* @param {string|undefined} [params.agentAddress] only if agent wallet in use
* @param {string|undefined} [params.originAddress] only if agent in use. Agent's owner address ( default = credentials walletAddress )
* @returns {object} An [order structure]{@link https://docs.ccxt.com/?id=order-structure}
*/
async cancelOrderWs(id, symbol = undefined, params = {}) {
const operationType = 'cancel_order';
await this.loadMarkets();
if (symbol === undefined) {
throw new errors.ArgumentsRequired(this.id + ' cancelOrderWs() requires a symbol argument');
}
const request = this.cancelOrderRequest(id, symbol, params);
params = this.omit(params, ['originAddress', 'agentAddress', 'expiryWindow', 'trigger', 'stop', 'clientOrderId']);
const isTestnet = this.isSandboxModeEnabled;
const urlKey = (isTestnet) ? 'test' : 'api';
const url = this.urls[urlKey]['ws']['public'];
const wsRequest = this.wrapAsPostAction(operationType, request);
const requestId = this.safeString(wsRequest, 'id');
const response = await this.watch(url, requestId, wsRequest, requestId);
//
// {
// "code": 200,
// "data": {
// "I": "79f948fd-7556-4066-a128-083f3ea49322",
// "i": null,
// "s": "BTC"
// },
// "id": "1bb2b72f-f545-4938-8a38-c5cda8823675",
// "t": 1749223343610,
// "type": "cancel_order"
// }
//
const code = this.safeInteger(response, 'code');
let success = false;
if (code === 200) {
success = true;
}
let status = undefined;
if (!success) {
status = 'rejected';
}
else {
status = 'open';
}
const order = this.safeDict(response, 'data', {});
const orderId = this.safeString(order, 'i');
const clientOrderId = this.safeString(order, 'I');
return this.safeOrder({ 'id': orderId, 'clientOrderId': clientOrderId, 'status': status, 'info': response, 'symbol': symbol });
}
/**
* @method
* @name pacifica#cancelAllOrdersWs
* @description cancel all open orders in a market
* @see https://docs.pacifica.fi/api-documentation/api/websocket/trading-operations/cancel-all-orders
* @param {string} symbol (optional) unified market symbol of the market to cancel orders in.
* @param {object} [params] extra parameters specific to the exchange API endpoint
* @param {boolean|undefined} [params.excludeReduceOnly] whether to exclude reduce-only orders
* @param {int|undefined} [params.expiryWindow] time to live in milliseconds
* @param {string|undefined} [params.agentAddress] only if agent wallet in use
* @param {string|undefined} [params.originAddress] only if agent in use. Agent's owner address ( default = credentials walletAddress )
* @returns {object[]} a list of [order structures]{@link https://docs.ccxt.com/?id=order-structure}
*/
async cancelAllOrdersWs(symbol = undefined, params = {}) {
await this.loadMarkets();
const operationType = 'cancel_all_orders';
const request = this.cancelAllOrdersRequest(symbol, params);
params = this.omit(params, ['excludeReduceOnly', 'agentAddress', 'originAddress', 'expiryWindow']);
const isTestnet = this.isSandboxModeEnabled;
const urlKey = (isTestnet) ? 'test' : 'api';
const url = this.urls[urlKey]['ws']['public'];
const wsRequest = this.wrapAsPostAction(operationType, request);
const requestId = this.safeString(wsRequest, 'id');
const response = await this.watch(url, requestId, wsRequest, requestId);
// {
// "code": 200,
// "data": {
// "cancelled_count": 10
// },
// "id": "b86b4f45-49da-4191-84e2-93e141acdeab",
// "t": 1749221787291,
// "type": "cancel_all_orders"
// }
//
return [
this.safeOrder({
'info': response,
}),
];
}
/**
* @method
* @name pacifica#watchOrderBook
* @description watches information on open orders with bid (buy) and ask (sell) prices, volumes and other data
* @see https://docs.pacifica.fi/api-documentation/api/websocket/subscriptions/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|undefined} [params.aggLevel] aggregation level for price grouping. Defaults to 1. Can be 1, 10, 100, 1000, 10000
* @returns {object} A dictionary of [order book structures]{@link https://docs.ccxt.com/?id=order-book-structure} indexed by market symbols
*/
async watchOrderBook(symbol, limit = undefined, params = {}) {
this.setupApiKeyHeaders();
await this.loadMarkets();
const market = this.market(symbol);
let aggLevel = undefined;
[aggLevel, params] = this.handleOptionAndParams(params, 'fetchOrderBook', 'aggLevel', 1);
const messageHash = 'orderbook:' + symbol;
const isTestnet = this.isSandboxModeEnabled;
const urlKey = (isTestnet) ? 'test' : 'api';
const url = this.urls[urlKey]['ws']['public'];
const request = {
'method': 'subscribe',
'params': {
'source': 'book',
'symbol': market['id'],
'agg_level': aggLevel,
},
};
const message = this.extend(request, params);
const orderbook = await this.watch(url, messageHash, message, messageHash);
return orderbook.limit();
}
/**
* @method
* @name pacifica#unWatchOrderBook
* @description unWatches information on open orders with bid (buy) and ask (sell) prices, volumes and other data
* @see https://docs.pacifica.fi/api-documentation/api/websocket/subscriptions/orderbook
* @param {string} symbol unified symbol of the market to fetch the order book for
* @param {object} [params] extra parameters specific to the exchange API endpoint
* @param {int|undefined} [params.aggLevel] aggregation level for price grouping. Defaults to 1. Can be 1, 10, 100, 1000, 10000
* @returns {object} A dictionary of [order book structures]{@link https://docs.ccxt.com/?id=order-book-structure} indexed by market symbols
*/
async unWatchOrderBook(symbol, params = {}) {
await this.loadMarkets();
const market = this.market(symbol);
let aggLevel = undefined;
[aggLevel, params] = this.handleOptionAndParams(params, 'fetchOrderBook', 'aggLevel', 1);
const subMessageHash = 'orderbook:' + symbol;
const messageHash = 'unsubscribe:' + subMessageHash;
const isTestnet = this.isSandboxModeEnabled;
const urlKey = (isTestnet) ? 'test' : 'api';
const url = this.urls[urlKey]['ws']['public'];
const request = {
'method': 'unsubscribe',
'params': {
'source': 'book',
'symbol': market['id'],
'agg_level': aggLevel,
},
};
const message = this.extend(request, params);
return await this.watch(url, messageHash, message, messageHash);
}
handleOrderBook(client, message) {
//
// {
// "channel": "book",
// "data": {
// "l": [
// [
// {
// "a": "37.86",
// "n": 4,
// "p": "157.47"
// },
// // ... other aggegated bid levels
// ],
// [
// {
// "a": "12.7",
// "n": 2,
// "p": "157.49"
// },
// {
// "a": "44.45",
// "n": 3,
// "p": "157.5"
// },
// // ... other aggregated ask levels
// ]
// ],
// "s": "SOL",
// "t": 1749051881187,
// "li": 1559885104 // sequence id - last order id
// }
// }
//
const entry = this.safeDict(message, 'data', {});
const marketId = this.safeString(entry, 's');
const market = this.safeMarket(marketId);
const symbol = market['symbol'];
const levels = this.safeList(entry, 'l', []);
const result = {
'bids': this.safeList(levels, 0, []),
'asks': this.safeList(levels, 1, []),
};
const timestamp = this.safeInteger(entry, 't');
const snapshot = this.parseOrderBook(result, symbol, timestamp, 'bids', 'asks', 'p', 'a');
const nonce = this.safeInteger(entry, 'li');
if (nonce) {
snapshot['nonce'] = nonce;
}
if (!(symbol in this.orderbooks)) {
const ob = this.orderBook(snapshot);
this.orderbooks[symbol] = ob;
}
const orderbook = this.orderbooks[symbol];
orderbook.reset(snapshot);
const messageHash = 'orderbook:' + symbol;
client.resolve(orderbook, messageHash);
}
/**
* @method
* @name pacifica#watchTicker
* @see https://docs.pacifica.fi/api-documentation/api/websocket/subscriptions/prices
* @description watches a price ticker, a statistical calculation with the information calculated over the past 24 hours for a specific market
* @param {string} symbol unified symbol of the market to fetch the ticker for
* @param {object} [params] extra parameters specific to the exchange API endpoint
* @returns {object} a [ticker structure]{@link https://docs.ccxt.com/?id=ticker-structure}
*/
async watchTicker(symbol, params = {}) {
const tickers = await this.watchTickers([symbol], params);
return tickers[symbol];
}
/**
* @method
* @name pacifica#watchTickers
* @description watches a price ticker, a statistical calculation with the information calculated over the past 24 hours for all markets of a specific list
* @see https://docs.pacifica.fi/api-documentation/api/websocket/subscriptions/prices
* @param {string[]} symbols unified symbol of the market to fetch the ticker for
* @param {object} [params] extra parameters specific to the exchange API endpoint
* @returns {object} a [ticker structure]{@link https://docs.ccxt.com/?id=ticker-structure}
*/
async watchTickers(symbols = undefined, params = {}) {
this.setupApiKeyHeaders();
await this.loadMarkets();
symbols = this.marketSymbols(symbols, undefined, true);
const messageHash = 'tickers';
const isTestnet = this.isSandboxModeEnabled;
const urlKey = (isTestnet) ? 'test' : 'api';
const url = this.urls[urlKey]['ws']['public'];
const request = {
'method': 'subscribe',
'params': {
'source': 'prices',
},
};
const tickers = await this.watch(url, messageHash, this.extend(request, params), messageHash);
if (this.newUpdates) {
return this.filterByArrayTickers(tickers, 'symbol', symbols);
}
return this.tickers;
}
/**
* @method
* @name pacifica#unWatchTickers
* @description unWatches a price ticker, a statistical calculation with the information calculated over the past 24 hours for all markets of a specific list
* @see https://docs.pacifica.fi/api-documentation/api/websocket/subscriptions/prices
* @param {string[]} symbols unified symbol of the market to fetch the ticker for
* @param {object} [params] extra parameters specific to the exchange API endpoint
* @returns {object} a [ticker structure]{@link https://docs.ccxt.com/?id=ticker-structure}
*/
async unWatchTickers(symbols = undefined, params = {}) {
await this.loadMarkets();
symbols = this.marketSymbols(symbols, undefined, true);
const subMessageHash = 'tickers';
const messageHash = 'unsubscribe:' + subMessageHash;
const isTestnet = this.isSandboxModeEnabled;
const urlKey = (isTestnet) ? 'test' : 'api';
const url = this.urls[urlKey]['ws']['public'];
const request = {
'method': 'unsubscribe',
'params': {
'source': 'prices',
},
};
return await this.watch(url, messageHash, this.extend(request, params), messageHash);
}
/**
* @method
* @name pacifica#watchMyTrades
* @description watches information on multiple trades made by the user
* @see https://docs.pacifica.fi/api-documentation/api/websocket/subscriptions/account-trades
* @param {string} symbol unified market symbol of the market orders were made in
* @param {int} [since] the earliest time in ms to fetch orders for
* @param {int} [limit] the maximum number of order structures to retrieve
* @param {object} [params] extra parameters specific to the exchange API endpoint
* @param {string|undefined} [params.account] will default to options' walletAddress if not provided
* @returns {object[]} a list of [order structures]{@link https://docs.ccxt.com/?id=order-structure}
*/
async watchMyTrades(symbol = undefined, since = undefined, limit = undefined, params = {}) {
let userAddress = undefined;
[userAddress, params] = this.handleOriginAndSingleAddress('watchMyTrades', params);
await this.loadMarkets();
let messageHash = 'myTrades';
if (symbol !== undefined) {
symbol = this.symbol(symbol);
messageHash += ':' + symbol;
}
const isTestnet = this.isSandboxModeEnabled;
const urlKey = (isTestnet) ? 'test' : 'api';
const url = this.urls[urlKey]['ws']['public'];
const request = {
'method': 'subscribe',
'params': {
'source': 'account_trades',
'account': userAddress,
},
};
const message = this.extend(request, params);
const trades = await this.watch(url, messageHash, message, messageHash);
if (this.newUpdates) {
limit = trades.getLimit(symbol, limit);
}
return this.filterBySymbolSinceLimit(trades, symbol, since, limit, true);
}
/**
* @method
* @name pacifica#unWatchMyTrades
* @description unWatches information on multiple trades made by the user
* @see https://docs.pacifica.fi/api-documentation/api/websocket/subscriptions/account-trades
* @param {string} symbol unified market symbol of the market orders were made in
* @param {object} [params] extra parameters specific to the exchange API endpoint
* @param {string|undefined} [params.account] will default to options' walletAddress if not provided
* @returns {object[]} a list of [order structures]{@link https://docs.ccxt.com/?id=order-structure}
*/
async unWatchMyTrades(symbol = undefined, params = {}) {
await this.loadMarkets();
if (symbol !== undefined) {
throw new errors.NotSupported(this.id + ' unWatchMyTrades does not support a symbol argument, unWatch from all markets only');
}
let userAddress = undefined;
[userAddress, params] = this.handleOriginAndSingleAddress('unWatchMyTrades', params);
const messageHash = 'unsubscribe:myTrades';
const isTestnet = this.isSandboxModeEnabled;
const urlKey = (isTestnet) ? 'test' : 'api';
const url = this.urls[urlKey]['ws']['public'];
const request = {
'method': 'unsubscribe',
'params': {
'source': 'account_trades',
'account': userAddress,
},
};
const message = this.extend(request, params);
return await this.watch(url, messageHash, message, messageHash);
}
handleWsTickers(client, message) {
//
// {
// "channel": "prices",
// "data": [
// {
// "funding": "0.0000125",
// "mark": "105473",
// "mid": "105476",
// "next_funding": "0.0000125",
// "open_interest": "0.00524",
// "oracle": "105473",
// "symbol": "BTC",
// "timestamp": 1749051612681,
// "volume_24h": "63265.87522",
// "yesterday_price": "955476"
// }
// // ... other symbol prices
// ],
// }
//
const parsedTickers = [];
const data = this.safeList(message, 'data', []);
for (let i = 0; i < data.length; i++) {
const info = data[i];
const marketId = this.safeString(info, 'symbol');
const market = this.safeMarket(marketId);
const symbol = market['symbol'];
const ticker = this.parseWsTicker(info, market);
this.tickers[symbol] = ticker;
parsedTickers.push(ticker);
}
const tickers = this.indexBy(parsedTickers, 'symbol');
client.resolve(tickers, 'tickers');
return true;
}
parseWsTicker(rawTicker, market = undefined) {
return this.parseTicker(rawTicker, market);
}
handleMyTrades(client, message) {
//
// {
// "channel": "account_trades",
// "data": [
// {
// "h": 80063441, // history id
// "i": 1559912767, // oid
// "I": null, // cloid
// "u": "BrZp5bidJ3WUvceSq7X78bhjTfZXeezzGvGEV4hAYKTa", // account address
// "s": "BTC", // symbol
// "p": "89477", // price
// "o": "89505", // entry price
// "a": "0.00036", // amount
// "te": "fulfill_taker",
// "ts": "close_long",
// "tc": "normal", // trade type
// "f": "0.012885", // fee
// "n": "-0.022965", // pnl
// "t": 1765018588190,
// "li": 1559912767
// }
// ]
// }
//
if (this.myTrades === undefined) {
const limit = this.safeInteger(this.options, 'tradesLimit', 1000);
this.myTrades = new Cache.ArrayCacheBySymbolById(limit);
}
const trades = this.myTrades;
const symbols = {};
const data = this.safeList(message, 'data', []);
const dataLength = data.length;
if (dataLength === 0) {
return;
}
for (let i = 0; i < data.length; i++) {
const rawTrade = data[i];
const parsed = this.parseWsTrade(rawTrade);
const symbol = parsed['symbol'];
symbols[symbol] = true;
trades.append(parsed);
}
const keys = Object.keys(symbols);
for (let i = 0; i < keys.length; i++) {
const currentMessageHash = 'myTrades:' + keys[i];
client.resolve(trades, currentMessageHash);
}
// non-symbol specific
const messageHash = 'myTrades';
client.resolve(trades, messageHash);
}
/**
* @method
* @name pacifica#watchTrades
* @description watches information on multiple trades made in a market
* @see https://docs.pacifica.fi/api-documentation/api/websocket/subscriptions/trades
* @param {string} symbol unified market symbol of the market trades were made in
* @param {int} [since] the earliest time in ms to fetch trades for
* @param {int} [limit] the maximum number of trade structures to retrieve
* @param {object} [params] extra parameters specific to the exchange API endpoint
* @returns {object[]} a list of [trade structures]{@link https://docs.ccxt.com/?id=trade-structure}
*/
async watchTrades(symbol, since = undefined, limit = undefined, params = {}) {
await this.loadMarkets();
const market = this.market(symbol);
symbol = market['symbol'];
const messageHash = 'trade:' + symbol;
const isTestnet = this.isSandboxModeEnabled;
const urlKey = (isTestnet) ? 'test' : 'api';
const url = this.urls[urlKey]['ws']['public'];
const request = {
'method': 'subscribe',
'params': {
'source': 'trades',
'symbol': market['id'],
},
};
const message = this.extend(request, params);
const trades = await this.watch(url, messageHash, message, messageHash);
if (this.newUpdates) {
limit = trades.getLimit(symbol, limit);
}
return this.filterBySinceLimit(trades, since, limit, 'timestamp', true);
}
/**
* @method
* @name pacifica#unWatchTrades
* @description unWatches information on multiple trades made in a market
* @see https://docs.pacifica.fi/api-documentation/api/websocket/subscriptions/trades
* @param {string} symbol unified market symbol of the market trades were made in
* @param {object} [params] extra parameters specific to the exchange API endpoint
* @returns {object[]} a list of [trade structures]{@link https://docs.ccxt.com/?id=trade-structure}
*/
async unWatchTrades(symbol, params = {}) {
await this.loadMarkets();
const market = this.market(symbol);
symbol = market['symbol'];
const subMessageHash = 'trade:' + symbol;
const messageHash = 'unsubscribe:' + subMessageHash;
const isTestnet = this.isSandboxModeEnabled;
const urlKey = (isTestnet) ? 'test' : 'api';
const url = this.urls[urlKey]['ws']['public'];
const request = {
'method': 'unsubscribe',
'params': {
'source': 'trades',
'symbol': market['id'],
},
};
const message = this.extend(request, params);
return await this.watch(url, messageHash, message, messageHash);
}
handleTrades(client, message) {
//
// {
// "channel": "trades",
// "data": [
// {
// "h": 80062522,
// "s": "BTC",
// "a": "0.00001",
// "p": "89471",
// "d": "close_short",
// "tc": "normal",
// "t": 1765018379085,
// "li": 1559885104
// }
// ]
// }
//
const entry = this.safeList(message, 'data', []);
const first = this.safeDict(entry, 0, {});
const marketId = this.safeString(first, 's');
const market = this.safeMarket(marketId);
const symbol = market['symbol'];
if (!(symbol in this.trades)) {
const limit = this.safeInteger(this.options, 'tradesLimit', 1000);
const stored = new Cache.ArrayCache(limit);
this.trades[symbol] = stored;
}
const trades = this.trades[symbol];
for (let i = 0; i < entry.length; i++) {
const data = this.safeDict(entry, i);
const trade = this.parseWsTrade(data);
trades.append(trade);
}
const messageHash = 'trade:' + symbol;
client.resolve(trades, messageHash);
}
parseWsTrade(trade, market = undefined) {
//
// fetchMyTrades
//
// {
// "h": 80063441, // history id
// "i": 1559912767, // oid
// "I": null, // cloid
// "u": "BrZp5bidJ3WUvceSq7X78bhjTfZXeezzGvGEV4hAYKTa", // account address
// "s": "BTC", // symbol
// "p": "89477", // price
// "o": "89505", // entry price
// "a": "0.00036", // amount
// "te": "fulfill_taker",
// "ts": "close_long",
// "tc": "normal", // trade type
// "f": "0.012885", // fee
// "n": "-0.022965", // pnl
// "t": 1765018588190,
// "li": 1559912767
// }
//
// fetchTrades
//
// {
// "h": 80062522,
// "s": "BTC",
// "a": "0.00001",
// "p": "89471",
// "d": "close_short",
// "tc": "normal",
// "t": 1765018379085,
// "li": 1559885104
// }
//
const timestamp = this.safeInteger(trade, 't');
const price = this.safeString(trade, 'p');
const amount = this.safeString(trade, 'a');
const marketId = this.safeString(trade, 's');
market = this.safeMarket(marketId, market);
const symbol = market['symbol'];
const id = this.safeString(trade, 'h');
const fee = this.safeString(trade, 'f');
let side = this.safeString2(trade, 'ts', 'd');
if (side === 'open_long') {
side = 'buy';
}
else if (side === 'close_long') {
side = 'sell';
}
else if (side === 'open_short') {
side = 'sell';
}
else if (side === 'close_short') {
side = 'buy';
}
const eventType = this.safeString(trade, 'te');
let takerOrMaker = undefined;
if (eventType !== undefined) {
takerOrMaker = (eventType === 'fulfill_maker') ? 'maker' : 'taker';
}
const orderId = this.safeString(trade, 'i');
// public trades have no orderId
if (orderId === undefined) {
takerOrMaker = undefined;
}
return this.safeTrade({
'info': trade,
'timestamp': timestamp,
'datetime': this.iso8601(timestamp),
'symbol': symbol,
'id': id,
'order': this.safeString(trade, 'i'),
'type': undefined,
'side': side,
'takerOrMaker': takerOrMaker,
'price': price,
'amount': amount,
'cost': undefined,
'fee': { 'cost': fee, 'currency': 'USDC' },
}, market);
}
/**
* @method
* @name pacifica#watchOHLCV
* @description watches historical candlestick data containing the open, high, low, close price, and the volume of a market
* @see https://docs.pacifica.fi/api-documentation/api/websocket/subscriptions/candle
* @param {string} symbol unified symbol of the market to fetch OHLCV data for
* @param {string} timeframe the length of time each candle represents
* @param {int} [since] timestamp in ms of the earliest candle to fetch
* @param {int} [limit] the maximum amount of candles to fetch
* @param {object} [params] extra parameters specific to the exchange API endpoint
* @returns {int[][]} A list of candles ordered as timestamp, open, high, low, close, volume
*/
async watchOHLCV(symbol, timeframe = '1m', since = undefined, limit = undefined, params = {}) {
await this.loadMarkets();
const market = this.market(symbol);
symbol = market['symbol'];
const isTestnet = this.isSandboxModeEnabled;
const parsedTf = this.safeString(this.timeframes, timeframe, timeframe);
const urlKey = (isTestnet) ? 'test' : 'api';
const url = this.urls[urlKey]['ws']['public'];
const request = {
'method': 'subscribe',
'params': {
'source': 'candle',
'symbol': market['id'],
'interval': parsedTf,
},
};
const messageHash = 'candles:' + parsedTf + ':' + symbol;
const message = this.extend(request, params);
const ohlcv = await this.watch(url, messageHash, message, messageHash);
if (this.newUpdates) {
limit = ohlcv.getLimit(symbol, limit);
}
return this.filterBySinceLimit(ohlcv, since, limit, 0, true);
}
/**
* @method
* @name pacifica#unWatchOHLCV
* @description watches historical candlestick data containing the open, high, low, close price, and the volume of a market
* @see https://docs.pacifica.fi/api-documentation/api/websocket/subscriptions/candle
* @param {string} symbol unified symbol of the market to fetch OHLCV data for
* @param {string} timeframe the length of time each candle represents
* @param {object} [params] extra parameters specific to the exchange API endpoint
* @returns {int[][]} A list of candles ordered as timestamp, open, high, low, close, volume
*/
async unWatchOHLCV(symbol, timeframe = '1m', params = {}) {
await this.loadMarkets();
const market = this.market(symbol);
symbol = market['symbol'];
const isTestnet = this.isSandboxModeEnabled;
const urlKey = (isTestnet) ? 'test' : 'api';
const url = this.urls[urlKey]['ws']['public'];
const request = {
'method': 'unsubscribe',
'params': {
'source': 'candle',
'symbol': market['id'],
'interval': timeframe,
},
};
const subMessageHash = 'candles:' + timeframe + ':' + symbol;
const messagehash = 'unsubscribe:' + subMessageHash;
const message = this.extend(request, params);
return await this.watch(url, messagehash, message, messagehash);
}
handleOHLCV(client, message) {
//
// {
// "channel": "candle",
// "data": {
// "t": 1749052260000,
// "T": 1749052320000,
// "s": "SOL",
// "i": "1m",
// "o": "157.3",
// "c": "157.32",
// "h": "157.32",
// "l": "157.3",
// "v": "1.22",
// "n": 8
// }
// }
//
const data = this.safeDict(message, 'data', {});
const marketId = this.safeString(data, 's');
const market = this.safeMarket(marketId);
const symbol = market['symbol'];
const timeframe = this.safeString(data, 'i');
if (!(symbol in this.ohlcvs)) {
this.ohlcvs[symbol] = {};
}
if (!(timeframe in this.ohlcvs[symbol])) {
const limit = this.safeInteger(this.options, 'OHLCVLimit', 1000);
const stored = new Cache.ArrayCacheByTimestamp(limit);
this.ohlcvs[symbol][timeframe] = stored;
}
const ohlcv = this.ohlcvs[symbol][timeframe];
const parsed = this.parseOHLCV(data);
ohlcv.append(parsed);
const messageHash = 'candles:' + timeframe + ':' + symbol;
client.resolve(ohlcv, messageHash);
}
/**
* @method
* @name pacifica#watchOrders
* @description watches information on multiple orders made by the user
* @see https://docs.pacifica.fi/api-documentation/api/websocket/subscriptions/account-order-updates
* @param {string} symbol unified market symbol of the market orders were made in
* @param {int} [since] the earliest time in ms to fetch orders for
* @param {int} [limit] the maximum number of order structures to retrieve
* @param {object} [params] extra parameters specific to the exchange API endpoint
* @param {string|undefined} [params.account] will default to options' walletAddress if not provided
* @returns {object[]} a list of [order structures]{@link https://docs.ccxt.com/?id=order-structure}
*/
async watchOrders(symbol = undefined, since = undefined, limit = undefined, params = {}) {
await this.loadMarkets();
let userAddress = undefined;
[userAddress, params] = this.handleOriginAndSingleAddress('watchOrders', params);
let market = undefined;
let messageHash = 'order';
if (symbol !== undefined) {
market = this.market(symbol);
symbol = market['symbol'];
messageHash = messageHash + ':' + symbol;
}
const isTestnet = this.isSandboxModeEnabled;
const urlKey = (isTestnet) ? 'test' : 'api';
const url = this.urls[urlKey]['ws']['public'];
const request = {
'method': 'subscribe',
'params': {
'source': 'account_order_updates',
'account': userAddress,
},
};
const message = this.extend(request, params);
const orders = await this.watch(url, messageHash, message, messageHash);
if (this.newUpdates) {
limit = orders.getLimit(symbol, limit);
}
return this.filterBySymbolSinceLimit(orders, symbol, since, limit, true);
}
/**
* @method
* @name pacifica#unWatchOrders
* @description unWatches information on multiple orders made by the user
* @see https://docs.pacifica.fi/api-documentation/api/websocket/subscriptions/account-order-updates
* @param {string} symbol unified market symbol of the market orders were made in
* @param {object} [params] extra parameters specific to the exchange API endpoint
* @param {string|undefined} [params.account] will default to options' walletAddress if not provided
* @returns {object[]} a list of [order structures]{@link https://docs.ccxt.com/?id=order-structure}
*/
async unWatchOrders(symbol = undefined, params = {}) {
await this.loadMarkets();
if (symbol !== undefined) {
throw new errors.NotSupported(this.id + ' unWatchOrders() does not support a symbol argument, unWatch from all markets only');
}
const messageHash = 'unsubscribe:order';
const isTestnet = this.isSandboxModeEnabled;
const urlKey = (isTestnet) ? 'test' : 'api';
const url = this.urls[urlKey]['ws']['public'];
let userAddress = undefined;
[userAddress, params] = this.handleOriginAndSingleAddress('unWatchOrders', params);
const request = {
'method': 'unsubscribe',
'params': {
'source': 'account_order_updates',
'account': userAddress,
},
};
const message = this.extend(request, params);
return await this.watch(url, messageHash, message, messageHash);
}
handleOrder(client, message) {
// not snapshot, only updates
// {
// "channel": "account_order_updates",
// "data": [
// {
// "i": 1559665358,
// "I": null,
// "u": "BrZp5bidJ3WUvceSq7X78bhjTfZXeezzGvGEV4hAYKTa",
// "s": "BTC",
// "d": "bid",
// "p": "89501",
// "ip": "89501",
// "lp": "89501",
// "a": "0.00012",
// "f": "0.00012",
// "oe": "fulfill_limit",
// "os": "filled",
// "ot": "limit",
// "sp": null,
// "si": null,
// "r": false,