UNPKG

ccxt

Version:

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

1,123 lines (1,120 loc) 164 kB
'use strict'; Object.defineProperty(exports, '__esModule', { value: true }); var extended$1 = require('./abstract/extended.js'); var Precise = require('./base/Precise.js'); var errors = require('./base/errors.js'); var number = require('./base/functions/number.js'); // ---------------------------------------------------------------------------- // --------------------------------------------------------------------------- /** * @class extended * @augments Exchange */ class extended extends extended$1["default"] { describe() { return this.deepExtend(super.describe(), { 'id': 'extended', 'name': 'Extended', 'countries': ['SG'], 'version': 'v2', 'rateLimit': 600, // Default Tier 1,000 requests/minute ≈ 1.67 request per second 'precisionMode': number.TICK_SIZE, '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': true, 'cancelOrder': true, 'cancelOrders': true, 'closeAllPositions': false, 'closePosition': false, 'createConvertTrade': false, 'createDepositAddress': false, 'createMarketBuyOrderWithCost': false, 'createMarketOrderWithCost': false, 'createMarketSellOrderWithCost': false, 'createOrder': true, 'createOrders': false, 'createOrderWithTakeProfitAndStopLoss': false, 'createPostOnlyOrder': false, 'createReduceOnlyOrder': false, 'createStopLimitOrder': false, 'createStopLossOrder': false, 'createStopMarketOrder': false, 'createStopOrder': false, 'createTakeProfitOrder': false, 'createTrailingAmountOrder': false, 'createTrailingPercentOrder': false, 'createTriggerOrder': false, 'editOrder': true, 'fetchAccounts': true, 'fetchBalance': true, 'fetchBorrowInterest': false, 'fetchBorrowRateHistories': false, 'fetchBorrowRateHistory': false, 'fetchCanceledAndClosedOrders': false, 'fetchCanceledOrders': true, 'fetchClosedOrders': true, 'fetchConvertCurrencies': false, 'fetchConvertQuote': false, 'fetchConvertTrade': false, 'fetchConvertTradeHistory': false, 'fetchCrossBorrowRate': false, 'fetchCrossBorrowRates': false, 'fetchCurrencies': true, 'fetchDeposit': false, 'fetchDepositAddress': false, 'fetchDepositAddresses': false, 'fetchDepositAddressesByNetwork': false, 'fetchDeposits': true, 'fetchDepositsWithdrawals': false, 'fetchDepositWithdrawFee': false, 'fetchDepositWithdrawFees': false, 'fetchFundingHistory': true, 'fetchFundingInterval': false, 'fetchFundingIntervals': false, 'fetchFundingRate': false, 'fetchFundingRateHistory': true, 'fetchFundingRates': false, 'fetchIndexOHLCV': true, 'fetchIsolatedBorrowRate': false, 'fetchIsolatedBorrowRates': false, 'fetchLedger': true, 'fetchLeverage': true, 'fetchLeverageTiers': false, 'fetchLiquidations': false, 'fetchLongShortRatio': false, 'fetchLongShortRatioHistory': false, 'fetchMarginAdjustmentHistory': false, 'fetchMarginMode': false, 'fetchMarketLeverageTiers': false, 'fetchMarkets': true, 'fetchMarkOHLCV': true, 'fetchMarkPrice': false, 'fetchMyLiquidations': false, 'fetchMyTrades': true, 'fetchOHLCV': true, 'fetchOpenInterest': false, 'fetchOpenInterestHistory': true, 'fetchOpenOrders': true, 'fetchOrder': true, 'fetchOrderBook': true, 'fetchOrderBooks': false, 'fetchOrders': true, 'fetchOrderTrades': false, 'fetchPosition': true, 'fetchPositionHistory': false, 'fetchPositionMode': false, 'fetchPositions': true, 'fetchPositionsHistory': true, 'fetchPositionsRisk': false, 'fetchPremiumIndexOHLCV': false, 'fetchStatus': false, 'fetchTicker': true, 'fetchTickers': true, 'fetchTime': false, 'fetchTrades': true, 'fetchTradingFee': true, 'fetchTradingFees': true, 'fetchTransactions': true, 'fetchTransfer': false, 'fetchTransfers': true, 'fetchWithdrawAddresses': false, 'fetchWithdrawal': false, 'fetchWithdrawals': true, 'reduceMargin': false, 'repayCrossMargin': false, 'repayIsolatedMargin': false, 'setLeverage': true, 'setMargin': false, 'setMarginMode': false, 'setPositionMode': false, 'signIn': false, 'transfer': true, 'withdraw': true, }, 'features': {}, 'timeframes': { '1m': 'PT1M', '5m': 'PT5M', '15m': 'PT15M', '30m': 'PT30M', '1h': 'PT1H', '2h': 'PT2H', '4h': 'PT4H', '8h': 'PT8H', '12h': 'PT12H', '1d': 'PT24H', '1w': 'P7D', '1M': 'P30D', }, 'hostname': 'extended.exchange', 'urls': { 'logo': 'https://github.com/user-attachments/assets/e2fe2bdf-6b28-4af8-b30f-38db496dc079', 'api': { 'rest': 'https://api.starknet.{hostname}', }, 'test': { 'rest': 'https://api.starknet.sepolia.{hostname}', }, 'www': 'https://app.extended.exchange', 'doc': 'https://api.docs.extended.exchange', 'fees': 'https://docs.extended.exchange/extended-resources/trading/trading-fees-and-rebates', 'referral': '', }, 'api': { 'v1': { 'public': { 'get': [ 'info/markets', 'info/assets', 'info/assets/{asset}/price', 'info/markets/{market}/stats', 'info/markets/{market}/orderbook', 'info/markets/{market}/trades', 'info/candles/{market}/{candleType}', 'info/{market}/funding', 'info/{market}/open-interests', 'info/builder/dashboard', ], }, 'private': { 'get': [ 'user/accounts', 'user/account/info', 'user/balance', 'user/spot/balances', 'user/assetOperations', 'user/positions', 'user/positions/history', 'user/orders', 'user/orders/history', 'user/orders/{id}', 'user/orders/external/{externalId}', 'user/trades', 'user/funding/history', 'user/rebates/stats', 'user/leverage', 'user/fees', 'user/bridge/config', 'user/bridge/quote', 'user/affiliate', 'user/referrals/status', 'user/referrals/links', 'user/referrals/dashboard', 'user/rewards/earned', 'user/rewards/leaderboard/stats', 'portfolio/charts/equities', 'portfolio/charts/pnl', 'vault/public/performance', 'vault/public/summary', 'builder/trades', ], 'post': [ 'user/order', 'user/order/massCancel', 'user/deadmanswitch', 'user/bridge/quote', 'user/withdrawal', 'user/transfer', 'user/referrals/use', 'user/referrals', ], 'put': [ 'user/referrals', ], 'patch': [ 'user/leverage', ], 'delete': [ 'user/order/{id}', 'user/order', ], }, }, }, 'fees': { 'taker': this.parseNumber('0.002'), 'maker': this.parseNumber('0.002'), }, 'requiredCredentials': { 'apiKey': true, 'secret': false, 'privateKey': true, }, 'exceptions': { 'exact': { '1000': errors.InvalidOrder, // Asset not found. '1001': errors.InvalidOrder, // Market not found. '1002': errors.InvalidOrder, // Market is disabled. '1003': errors.InvalidOrder, // Market group not found. '1004': errors.InvalidOrder, // Account not found. '1005': errors.InvalidOrder, // Not supported interval. '1006': errors.ExchangeError, // Application error. '1008': errors.InvalidOrder, // Client not found. '1009': errors.InvalidOrder, // Action is not allowed. '1010': errors.ExchangeError, // Maintenance mode. '1011': errors.InvalidOrder, // Post only mode. '1012': errors.InvalidOrder, // Reduce only mode. '1013': errors.InvalidOrder, // Percentage should be between 0 and 1. '1014': errors.InvalidOrder, // Market is in reduce only mode, non-reduce only orders are not allowed. '1049': errors.InvalidOrder, // Leverage below min leverage. '1050': errors.InvalidOrder, // Leverage exceeds max leverage. '10501': errors.InvalidOrder, // Max position value exceeded for new leverage. '1052': errors.InvalidOrder, // Insufficient margin for new leverage. '1053': errors.InvalidOrder, // Leverage has invalid precision. '1100': errors.InvalidOrder, // Invalid Starknet public key. '1101': errors.InvalidOrder, // Invalid Starknet signature. '1102': errors.InvalidOrder, // Invalid Starknet vault. '1120': errors.InvalidOrder, // Order quantity less than min trade size, based on market-specific trading rules. '1121': errors.InvalidOrder, // Invalid quantity due to the wrong size increment, based on market-specific Minimum Change in Trade Size trading rule. '1122': errors.InvalidOrder, // Order value exceeds max order value, based on market-specific trading rules. '1123': errors.InvalidOrder, // Invalid quantity precision, currently equals to market-specific Minimum Change in Trade Size. '1124': errors.InvalidOrder, // Invalid price due to wrong price movement, based on market-specific Minimum Price Change trading rule. '1125': errors.InvalidOrder, // Invalid price precision, currently equals to market-specific Minimum Price Change. '1126': errors.InvalidOrder, // Max open orders number exceeded, currently 200 orders per market. '1127': errors.InvalidOrder, // Max position value exceeded, based on the Margin schedule. '1128': errors.InvalidOrder, // Trading fees are invalid. Refer to Order management section for details. '1129': errors.InvalidOrder, // Invalid quantity for position TP/SL. '1130': errors.InvalidOrder, // Order price is missing. '1131': errors.InvalidOrder, // TP/SL order trigger is missing. '1132': errors.InvalidOrder, // Order type is not allowed. '1133': errors.InvalidOrder, // Invalid order parameters. '1134': errors.InvalidOrder, // Duplicate Order. '1135': errors.InvalidOrder, // Order expiration date must be within 90 days for the Mainnet, 28 days for the Testnet. '1136': errors.InvalidOrder, // Reduce-only order size exceeds open position size. '1137': errors.InvalidOrder, // Position is missing for a reduce-only order. '1138': errors.InvalidOrder, // Position is the same side as a reduce-only order. '1139': errors.InvalidOrder, // Market order must have time in force IOC. '1140': errors.InsufficientFunds, // New order cost exceeds available balance. '1141': errors.InvalidOrder, // Invalid price value. '1142': errors.InvalidOrder, // Edit order not found. '1143': errors.InvalidOrder, // Conditional order trigger is missing. '1144': errors.InvalidOrder, // Conditional market order can't be Post-only. '1145': errors.InvalidOrder, // Non reduce-only orders are not allowed. '1146': errors.InvalidOrder, // Twap order must have time in force GTT. '1147': errors.InvalidOrder, // Open loss exceeds equity. '1148': errors.InvalidOrder, // TP/SL open loss exceeds equity. '1500': errors.InvalidOrder, // Account not selected. '1600': errors.BadRequest, // Withdrawal amount must be positive. '1601': errors.BadRequest, // Withdrawal description is too long. '1602': errors.BadRequest, // Withdrawal request does not match settlement. '1604': errors.BadRequest, // Withdrawal expiration time is below the 14 days minimum. '1605': errors.BadRequest, // Withdrawal asset is not valid. '1607': errors.BadRequest, // Withdrawals blocked for the account. Please contact the team on Discord to unblock the withdrawals. '1608': errors.BadRequest, // The withdrawal address does not match the account address. '1650': errors.BadRequest, // Vault transfer amount is incorrect. '1700': errors.BadRequest, // Referral code already exist. '1701': errors.BadRequest, // Referral code is not valid. '1703': errors.BadRequest, // Referral program is not enabled. '1704': errors.BadRequest, // Referral code already applied. }, 'broad': {}, }, 'options': { 'builderFee': true, 'builderFeeRate': '0.0001', 'builderId': '257624', }, }); } async loadMarkets(reload = false, params = {}) { const markets = await super.loadMarkets(reload, params); const currenciesByNumericId = this.safeDict(this.options, 'currenciesByNumericId'); if ((currenciesByNumericId === undefined) || reload) { this.options['currenciesByNumericId'] = this.indexByStringifiedNumericId(this.currencies); } return markets; } indexByStringifiedNumericId(input) { const result = {}; if (input === undefined) { return undefined; } const keys = Object.keys(input); for (let i = 0; i < keys.length; i++) { const key = keys[i]; const item = input[key]; const numericIdString = this.safeString(item, 'numericId'); if (numericIdString === undefined) { continue; } result[numericIdString] = item; } return result; } /** * @method * @name extended#fetchMarkets * @description retrieves data on all markets for extended * @see https://api.docs.extended.exchange/#get-markets * @param {object} [params] extra parameters specific to the exchange API endpoint * @returns {object[]} an array of objects representing market data */ async fetchMarkets(params = {}) { const response = await this.v1PublicGetInfoMarkets(params); // // { // "status": "OK", // "data": [ // { // "name": "BTC-USD", // "uiName": "BTC-USD", // "category": "Crypto", // "subCategory": "L1", // "assetName": "BTC", // "assetPrecision": 5, // "collateralAssetName": "USD", // "collateralAssetPrecision": 6, // "description": "Bitcoin", // "active": true, // "status": "ACTIVE", // "marketStats": { // "dailyVolume": "231016077.512960", // "dailyVolumeBase": "3025.00058", // "dailyPriceChange": "420", // "dailyPriceChangePercentage": "0.0055", // "dailyLow": "75635", // "dailyHigh": "77399", // "lastPrice": "77259", // "askPrice": "77260", // "bidPrice": "77259", // "markPrice": "77259.680250000004", // "indexPrice": "77299.020412500001", // "fundingRate": "0.000013", // "nextFundingRate": 1777442400000, // "openInterest": "115861923.311902", // "openInterestBase": "1500.40958", // "deleverageLevels": { // "shortPositions": [ // { // "level": 1, // "rankingLowerBound": "-815.7788" // }, // { // "level": 2, // "rankingLowerBound": "-2.1328" // }, // { // "level": 3, // "rankingLowerBound": "-0.9297" // }, // { // "level": 4, // "rankingLowerBound": "0.0000" // } // ], // "longPositions": [ // { // "level": 1, // "rankingLowerBound": "-47234.9095" // }, // { // "level": 2, // "rankingLowerBound": "-0.0030" // }, // { // "level": 3, // "rankingLowerBound": "0.0020" // }, // { // "level": 4, // "rankingLowerBound": "0.0033" // } // ] // } // }, // "tradingConfig": { // "minOrderSize": "0.0001", // "minOrderSizeChange": "0.00001", // "minPriceChange": "1", // "maxMarketOrderValue": "3000000", // "maxLimitOrderValue": "15000000", // "maxPositionValue": "60000000", // "maxLeverage": "50.00", // "hourlyFundingRateCap": "0.25", // "maxNumOrders": "200", // "limitPriceCap": "0.05", // "limitPriceFloor": "0.05", // "riskFactorConfig": [ // { // "upperBound": "4000000", // "riskFactor": "0.02", // "isAvailableForUsers": true // } // ] // }, // "l2Config": { // "type": "STARKX", // "collateralId": "0x1", // "syntheticId": "0x4254432d3600000000000000000000", // "syntheticResolution": 1000000, // "collateralResolution": 1000000 // }, // "visibleOnUi": true, // "createdAt": 1752829532673 // } // ] // } // const data = this.safeList(response, 'data', []); return this.parseMarkets(data); } parseMarket(market) { // // { // "name": "BTC-USD", // "uiName": "BTC-USD", // "category": "Crypto", // "subCategory": "L1", // "assetName": "BTC", // "assetPrecision": 5, // "collateralAssetName": "USD", // "collateralAssetPrecision": 6, // "description": "Bitcoin", // "active": true, // "status": "ACTIVE", // "marketStats": { ... }, // "tradingConfig": { // "minOrderSize": "0.0001", // "minOrderSizeChange": "0.00001", // "minPriceChange": "1", // "maxMarketOrderValue": "3000000", // "maxLimitOrderValue": "15000000", // "maxPositionValue": "60000000", // "maxLeverage": "50.00", // "hourlyFundingRateCap": "0.25", // "maxNumOrders": "200", // "limitPriceCap": "0.05", // "limitPriceFloor": "0.05", // "riskFactorConfig": [ // { // "upperBound": "4000000", // "riskFactor": "0.02", // "isAvailableForUsers": true // } // ] // }, // "l2Config": { ... }, // "visibleOnUi": true, // "createdAt": 1752829532673 // } // const tradingConfig = this.safeDict(market, 'tradingConfig', {}); const marketId = this.safeString(market, 'name'); let baseId = this.safeString(market, 'assetName', ''); if (baseId.indexOf('SPOT') >= 0) { baseId = baseId.replace('SPOT', ''); } const quoteId = this.safeString(market, 'collateralAssetName'); const base = this.safeCurrencyCode(baseId); let quote = this.safeCurrencyCode(quoteId); if (quoteId === 'USD') { quote = 'USDC'; } const status = this.safeString(market, 'status'); const active = (status === 'ACTIVE'); const amountPrecision = this.safeNumber(tradingConfig, 'minOrderSizeChange'); const pricePrecision = this.safeNumber(tradingConfig, 'minPriceChange'); const maxLeverage = this.safeNumber(tradingConfig, 'maxLeverage'); const minAmount = this.safeNumber(tradingConfig, 'minOrderSize'); const maxCost = this.safeNumber(tradingConfig, 'maxLimitOrderValue'); const created = this.safeInteger(market, 'createdAt'); let settleId = undefined; let settle = undefined; let symbol = base + '/' + quote; let isSpot = false; let type = this.safeStringLower(market, 'type'); let contractSize = undefined; let linear = undefined; let inverse = undefined; if (type === 'spot') { isSpot = true; } else { type = 'swap'; settleId = quoteId; settle = quote; symbol += ':' + settle; contractSize = this.parseNumber('1'); linear = true; inverse = false; } return this.safeMarketStructure({ 'id': marketId, 'symbol': symbol, 'base': base, 'quote': quote, 'settle': settle, 'baseId': baseId, 'quoteId': quoteId, 'settleId': settleId, 'type': type, 'spot': isSpot, 'margin': false, 'swap': !isSpot, 'future': false, 'option': false, 'active': active, 'contract': !isSpot, 'linear': linear, 'inverse': inverse, 'taker': this.safeNumber(this.fees, 'taker'), 'maker': this.safeNumber(this.fees, 'maker'), 'contractSize': contractSize, 'expiry': undefined, 'expiryDatetime': undefined, 'strike': undefined, 'optionType': undefined, 'precision': { 'amount': amountPrecision, 'price': pricePrecision, }, 'limits': { 'leverage': { 'min': this.parseNumber('1'), 'max': maxLeverage, }, 'amount': { 'min': minAmount, 'max': undefined, }, 'price': { 'min': undefined, 'max': undefined, }, 'cost': { 'min': undefined, 'max': maxCost, }, }, 'created': created, 'info': market, }); } /** * @method * @name extended#fetchCurrencies * @description fetches all available currencies on an exchange * @see https://api.docs.extended.exchange/#get-assets * @param {object} [params] extra parameters specific to the exchange API endpoint * @returns {object} an associative dictionary of currencies */ async fetchCurrencies(params = {}) { const response = await this.v1PublicGetInfoAssets(params); // // { // "status": "OK", // "data": [ // { // "id": 1, // "name": "USD", // "symbol": "USD", // "description": "USD Collateral", // "precision": 6, // "isActive": true, // "isCollateral": true, // "starkexId": "0x1", // "starkexResolution": 1000000, // "l1Id": "0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48", // "l1Resolution": 1000000, // "version": 3, // "createdAt": 1752829532673, // "type": "SPOT", // "canBeUsedAsCollateral": true, // "riskFactors": [], // "availableForTradeFactors": [] // } // ] // } // const data = this.safeList(response, 'data', []); return this.parseCurrencies(data); } parseCurrency(currency) { // // { // "id": 1, // "name": "USD", // "symbol": "USD", // "description": "USD Collateral", // "precision": 6, // "isActive": true, // "isCollateral": true, // "starkexId": "0x1", // "starkexResolution": 1000000, // "l1Id": "0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48", // "l1Resolution": 1000000, // "version": 3, // "createdAt": 1752829532673, // "type": "SPOT", // "canBeUsedAsCollateral": true, // "riskFactors": [], // "availableForTradeFactors": [] // } // let currencyId = this.safeString(currency, 'symbol'); if ((currencyId !== undefined) && (currencyId.indexOf('SPOT') >= 0)) { currencyId = currencyId.replace('SPOT', ''); } let code = this.safeCurrencyCode(currencyId); if (currencyId === 'USD') { code = 'USDC'; } const name = this.safeString(currency, 'name'); const precision = this.safeInteger(currency, 'precision', 0); const isActive = this.safeBool(currency, 'isActive'); return this.safeCurrencyStructure({ 'id': currencyId, 'code': code, 'numericId': this.safeInteger(currency, 'id'), 'name': name, 'active': isActive, 'deposit': true, 'withdraw': true, 'precision': Math.pow(10, precision * -1), 'type': 'other', 'margin': this.safeBool(currency, 'canBeUsedAsCollateral'), 'info': currency, }); } /** * @method * @name extended#fetchTicker * @description fetches a price ticker, a statistical calculation with the information calculated over the past 24 hours for a specific market * @see https://api.docs.extended.exchange/#get-market-statistics * @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 fetchTicker(symbol, params = {}) { await this.loadMarkets(); const market = this.market(symbol); const request = { 'market': market['id'], }; const response = await this.v1PublicGetInfoMarketsMarketStats(this.extend(request, params)); // // { // "status": "OK", // "data": { // "dailyVolume": "231216165.666600", // "dailyVolumeBase": "3027.36710", // "dailyPriceChange": "181", // "dailyPriceChangePercentage": "0.0024", // "dailyLow": "75635", // "dailyHigh": "77399", // "lastPrice": "77026", // "askPrice": "77026", // "bidPrice": "77025", // "markPrice": "77006.091897999984", // "indexPrice": "77050.739529925005", // "fundingRate": "0.000012", // "nextFundingRate": 1777446000000, // "openInterest": "114851569.088316", // "openInterestBase": "1491.33012", // "deleverageLevels": { // "shortPositions": [ // { "level": 1, "rankingLowerBound": "-784.2884" }, // { "level": 2, "rankingLowerBound": "-2.1078" }, // { "level": 3, "rankingLowerBound": "-0.8754" }, // { "level": 4, "rankingLowerBound": "0.0000" } // ], // "longPositions": [ // { "level": 1, "rankingLowerBound": "-47747.2010" }, // { "level": 2, "rankingLowerBound": "-0.0131" }, // { "level": 3, "rankingLowerBound": "0.0019" }, // { "level": 4, "rankingLowerBound": "0.0032" } // ] // } // } // } // const data = this.safeDict(response, 'data', {}); return this.parseTicker(data, market); } /** * @method * @name extended#fetchTickers * @description fetches price tickers for multiple markets, statistical information calculated over the past 24 hours for all markets * @see https://api.docs.extended.exchange/#get-markets * @param {string[]} [symbols] unified symbols of the markets to fetch the ticker for, all market tickers are returned if not assigned * @param {object} [params] extra parameters specific to the exchange API endpoint * @returns {object} a dictionary of [ticker structures]{@link https://docs.ccxt.com/?id=ticker-structure} */ async fetchTickers(symbols = undefined, params = {}) { await this.loadMarkets(); symbols = this.marketSymbols(symbols); const request = {}; if (symbols !== undefined) { const marketIds = []; for (let i = 0; i < symbols.length; i++) { const market = this.market(symbols[i]); marketIds.push(market['id']); } request['market'] = marketIds; } const response = await this.v1PublicGetInfoMarkets(this.extend(request, params)); // // { // "status": "OK", // "data": [ // { // "name": "BTC-USD", // "assetName": "BTC", // "collateralAssetName": "USD", // "marketStats": { // "dailyVolume": "231016077.512960", // ... // }, // ... // } // ] // } // const data = this.safeList(response, 'data', []); const tickers = {}; for (let i = 0; i < data.length; i++) { const marketData = data[i]; const marketId = this.safeString(marketData, 'name'); const market = this.safeMarket(marketId); const stats = this.safeDict(marketData, 'marketStats', {}); const ticker = this.parseTicker(stats, market); const symbol = ticker['symbol']; if (symbol !== undefined) { tickers[symbol] = ticker; } } return this.filterByArrayTickers(tickers, 'symbol', symbols); } parseTicker(ticker, market = undefined) { // // { // "dailyVolume": "231216165.666600", // "dailyVolumeBase": "3027.36710", // "dailyPriceChange": "181", // "dailyPriceChangePercentage": "0.0024", // "dailyLow": "75635", // "dailyHigh": "77399", // "lastPrice": "77026", // "askPrice": "77026", // "bidPrice": "77025", // "markPrice": "77006.091897999984", // "indexPrice": "77050.739529925005", // "fundingRate": "0.000012", // "nextFundingRate": 1777446000000, // "openInterest": "114851569.088316", // "openInterestBase": "1491.33012", // "deleverageLevels": { // "shortPositions": [ // { "level": 1, "rankingLowerBound": "-784.2884" }, // { "level": 2, "rankingLowerBound": "-2.1078" }, // { "level": 3, "rankingLowerBound": "-0.8754" }, // { "level": 4, "rankingLowerBound": "0.0000" } // ], // "longPositions": [ // { "level": 1, "rankingLowerBound": "-47747.2010" }, // { "level": 2, "rankingLowerBound": "-0.0131" }, // { "level": 3, "rankingLowerBound": "0.0019" }, // { "level": 4, "rankingLowerBound": "0.0032" } // ] // } // } // const symbol = this.safeSymbol(undefined, market); const last = this.safeNumber(ticker, 'lastPrice'); const percentageRaw = this.safeString(ticker, 'dailyPriceChangePercentage'); const percentage = (percentageRaw !== undefined) ? Precise["default"].stringMul(percentageRaw, '100') : undefined; return this.safeTicker({ 'symbol': symbol, 'timestamp': undefined, 'datetime': undefined, 'high': this.safeNumber(ticker, 'dailyHigh'), 'low': this.safeNumber(ticker, 'dailyLow'), 'bid': this.safeNumber(ticker, 'bidPrice'), 'bidVolume': undefined, 'ask': this.safeNumber(ticker, 'askPrice'), 'askVolume': undefined, 'vwap': undefined, 'open': undefined, 'close': last, 'last': last, 'previousClose': undefined, 'change': this.safeNumber(ticker, 'dailyPriceChange'), 'percentage': percentage, 'average': undefined, 'baseVolume': this.safeNumber(ticker, 'dailyVolumeBase'), 'quoteVolume': this.safeNumber(ticker, 'dailyVolume'), 'markPrice': this.safeNumber(ticker, 'markPrice'), 'indexPrice': this.safeNumber(ticker, 'indexPrice'), 'info': ticker, }, market); } /** * @method * @name extended#fetchOrderBook * @description fetches information on open orders with bid (buy) and ask (sell) prices, volumes and other data * @see https://api.docs.extended.exchange/#get-market-order-book * @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 * @returns {object} an [order book structure]{@link https://docs.ccxt.com/?id=order-book-structure} */ async fetchOrderBook(symbol, limit = undefined, params = {}) { await this.loadMarkets(); const market = this.market(symbol); const request = { 'market': market['id'], }; const response = await this.v1PublicGetInfoMarketsMarketOrderbook(this.extend(request, params)); // // { // "status": "OK", // "data": { // "market": "BTC-USD", // "bid": [ // { // "qty": "14.46084", // "price": "76214" // } // ], // "ask": [ // { // "qty": "0.11585", // "price": "76215" // } // ] // } // } // const data = this.safeDict(response, 'data', {}); const timestamp = this.milliseconds(); const orderbook = this.parseOrderBook(data, market['symbol'], timestamp, 'bid', 'ask', 'price', 'qty'); if (limit !== undefined) { orderbook['bids'] = this.arraySlice(orderbook['bids'], 0, limit); orderbook['asks'] = this.arraySlice(orderbook['asks'], 0, limit); } return orderbook; } /** * @method * @name extended#fetchTrades * @description get the list of most recent trades for a particular symbol * @see https://api.docs.extended.exchange/#get-market-last-trades * @param {string} symbol unified symbol of the market to fetch trades for * @param {int} [since] timestamp in ms of the earliest trade to fetch * @param {int} [limit] the maximum amount of trades to fetch * @param {object} [params] extra parameters specific to the exchange API endpoint * @returns {Trade[]} a list of [trade structures]{@link https://docs.ccxt.com/?id=public-trades} */ async fetchTrades(symbol, since = undefined, limit = undefined, params = {}) { await this.loadMarkets(); const market = this.market(symbol); const request = { 'market': market['id'], }; const response = await this.v1PublicGetInfoMarketsMarketTrades(this.extend(request, params)); // // { // "status": "OK", // "data": [ // { // "i": 2.049676905958871e+18, // "m": "BTC-USD", // "S": "SELL", // "tT": "TRADE", // "T": 1777516030193, // "p": "76140", // "q": "0.00165" // } // ] // } // const data = this.safeList(response, 'data', []); return this.parseTrades(data, market, since, limit); } /** * @method * @name extended#fetchMyTrades * @description fetch all trades made by the user * @see https://api.docs.extended.exchange/#get-trades * @param {string} [symbol] unified market symbol of the trades * @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 * @param {boolean} [params.paginate] default false, when true will automatically paginate by calling this endpoint multiple times. See in the docs all the [available parameters](https://github.com/ccxt/ccxt/wiki/Manual#pagination-params) * @returns {Trade[]} a list of [trade structures]{@link https://docs.ccxt.com/?id=trade-structure} */ async fetchMyTrades(symbol = undefined, since = undefined, limit = undefined, params = {}) { await this.loadMarkets(); let paginate = false; [paginate, params] = this.handleOptionAndParams(params, 'fetchMyTrades', 'paginate'); if (paginate) { return await this.fetchPaginatedCallCursor('fetchMyTrades', symbol, since, limit, params, 'cursor', 'cursor', undefined, 100); } let market = undefined; const request = {}; if (symbol !== undefined) { market = this.market(symbol); request['market'] = market['id']; } if (limit !== undefined) { request['limit'] = limit; } const response = await this.v1PrivateGetUserTrades(this.extend(params, request)); // // { // "status": "OK", // "data": [ // { // "id": 1, // "orderId": 1784980437895231232, // "externalId": "ExtId-1", // "accountId": 1, // "market": "BTC-USD", // "side": "BUY", // "price": "39000", // "qty": "0.2", // "value": "7800", // "fee": "1.3", // "tradeType": "TRADE", // "isTaker": true, // "createdTime": 1701563440000 // } // ], // "pagination": { // "cursor": 1784963886257016832, // "count": 1 // } // } // const data = this.safeList(response, 'data', []); const pagination = this.safeDict(response, 'pagination', {}); const cursor = this.safeString(pagination, 'cursor'); const result = []; const dataLength = data.length; for (let i = 0; i < dataLength; i++) { let entry = data[i]; if ((cursor !== undefined) && (i === dataLength - 1)) { entry = this.extend(entry, { 'cursor': cursor }); } result.push(entry); } return this.parseTrades(result, market, since, limit); } /** * @method * @name extended#fetchFundingHistory * @description fetch the funding payments history * @see https://api.docs.extended.exchange/#get-funding-payments * @param {string} [symbol] unified market symbol * @param {int} [since] the earliest time in ms to fetch funding history for * @param {int} [limit] the maximum number of funding history structures to retrieve * @param {object} [params] extra parameters specific to the exchange API endpoint * @param {boolean} [params.paginate] default false, when true will automatically paginate by calling this endpoint multiple times. See in the docs all the [available parameters](https://github.com/ccxt/ccxt/wiki/Manual#pagination-params) * @returns {FundingHistory[]} a list of [funding history structures]{@link https://docs.ccxt.com/?id=funding-history-structure} */ async fetchFundingHistory(symbol = undefined, since = undefined, limit = undefined, params = {}) { await this.loadMarkets(); let paginate = false; [paginate, params] = this.handleOptionAndParams(params, 'fetchFundingHistory', 'paginate'); if (paginate) { return await this.fetchPaginatedCallCursor('fetchFundingHistory', symbol, since, limit, params, 'cursor', 'cursor', undefined, 100); } let market = undefined; const request = {}; if (symbol !== undefined) { market = this.market(symbol); request['market'] = market['id']; } if (since !== undefined) { request['startTime'] = since; } if (limit !== undefined) { request['limit'] = limit; } const response = await this.v1PrivateGetUserFundingHistory(this.extend(params, request)); // // { // "status": "OK", // "data": [ // { // "id": 8341, // "accountId": 3137, // "market": "BNB-USD", // "positionId": 1821237954501148672, // "side": "LONG", // "size": "1.116", // "value": "560.77401888", // "markPrice": "502.48568", // "fundingFee": "0", // "fundingRate": "0", // "paidTime": 1723147241346 // } // ], // "pagination": { // "cursor": 8341, // "count": 1 // } // } // const data = this.safeList(response, 'data', []); const pagination = this.safeDict(response, 'pagination', {}); const cursor = this.safeString(pagination, 'cursor'); const result = []; const dataLength = data.length; for (let i = 0; i < dataLength; i++) { let entry = data[i]; if ((cursor !== undefined) && (i === dataLength - 1)) { entry = this.extend(entry, { 'cursor': cursor }); } result.push(entry); } return this.parseFundingHistories(result, market, since, limit); } parseFundingHistory(history, market = undefined) { // // { // "id": 8341, // "accountId": 3137, // "market": "BNB-USD", // "positionId": 1821237954501148672, // "side": "LONG", // "size": "1.116", // "value": "560.77401888", // "markPrice": "502.48568", // "fundingFee": "0", // "fundingRate": "0", // "paidTime": 1723147241346 // } // const marketId = this.safeString(history, 'market'); market = this.safeMarket(marketId, market); const timestamp = this.safeInteger(history, 'paidTime'); return { 'info': history, 'symbol': market['symbol'], 'code': market['settle'], 'timestamp': timestamp, 'datetime': this.iso8601(timestamp), 'id': this.safeString(history, 'id'), 'amount': this.safeNumber(history, 'fundingFee'), 'rate': this.safeNumber(history, 'fundingRate'), }; } parseFundingHistories(histories, market = undefined, since = undefined, limit = undefined) { const result = []; for (let i = 0; i < histories.length; i++) { result.push(this.parseFundingHistory(histories[i], market)); } const symbol = (market === undefined) ? undefined : market['symbol'];