UNPKG

ccxt

Version:

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

1,169 lines (1,167 loc) • 122 kB
// ---------------------------------------------------------------------------- // PLEASE DO NOT EDIT THIS FILE, IT IS GENERATED AND WILL BE OVERWRITTEN: // https://github.com/ccxt/ccxt/blob/master/CONTRIBUTING.md#how-to-contribute-code // EDIT THE CORRESPONDENT .ts FILE INSTEAD // --------------------------------------------------------------------------- import Exchange from './abstract/derive.js'; import Precise from './base/Precise.js'; import { BadRequest, InvalidOrder, ExchangeError, OrderNotFound, ArgumentsRequired, InsufficientFunds, RateLimitExceeded, AuthenticationError } from './base/errors.js'; import { ecdsa } from './base/functions/crypto.js'; import { keccak_256 as keccak } from './static_dependencies/noble-hashes/sha3.js'; import { secp256k1 } from './static_dependencies/noble-curves/secp256k1.js'; import { TICK_SIZE } from './base/functions/number.js'; // --------------------------------------------------------------------------- /** * @class derive * @augments Exchange */ export default class derive extends Exchange { describe() { return this.deepExtend(super.describe(), { 'id': 'derive', 'name': 'derive', 'countries': [], 'version': 'v1', 'rateLimit': 50, 'certified': false, 'pro': true, 'dex': true, 'has': { 'CORS': undefined, 'spot': false, 'margin': false, 'swap': false, 'future': false, 'option': false, 'addMargin': false, 'borrowCrossMargin': false, 'borrowIsolatedMargin': false, 'cancelAllOrders': true, 'cancelAllOrdersAfter': false, 'cancelOrder': true, 'cancelOrders': false, 'cancelOrdersForSymbols': false, 'closeAllPositions': false, 'closePosition': false, 'createMarketBuyOrderWithCost': false, 'createMarketOrderWithCost': false, 'createMarketSellOrderWithCost': false, 'createOrder': true, 'createOrders': false, 'createReduceOnlyOrder': false, 'createStopOrder': false, 'createTriggerOrder': false, 'editOrder': true, 'fetchAccounts': false, 'fetchBalance': true, 'fetchBorrowInterest': false, 'fetchBorrowRateHistories': false, 'fetchBorrowRateHistory': false, 'fetchCanceledAndClosedOrders': false, 'fetchCanceledOrders': true, 'fetchClosedOrders': true, 'fetchCrossBorrowRate': false, 'fetchCrossBorrowRates': false, 'fetchCurrencies': true, 'fetchDepositAddress': false, 'fetchDepositAddresses': false, 'fetchDeposits': true, 'fetchDepositWithdrawFee': 'emulated', 'fetchDepositWithdrawFees': false, 'fetchFundingHistory': true, 'fetchFundingRate': true, 'fetchFundingRateHistory': true, 'fetchFundingRates': false, 'fetchIndexOHLCV': false, 'fetchIsolatedBorrowRate': false, 'fetchIsolatedBorrowRates': false, 'fetchLedger': true, 'fetchLeverage': false, 'fetchLeverageTiers': false, 'fetchLiquidations': false, 'fetchMarginMode': undefined, 'fetchMarketLeverageTiers': false, 'fetchMarkets': true, 'fetchMarkOHLCV': false, 'fetchMyLiquidations': false, 'fetchMyTrades': true, 'fetchOHLCV': false, 'fetchOpenInterest': false, 'fetchOpenInterestHistory': false, 'fetchOpenInterests': false, 'fetchOpenOrders': true, 'fetchOrder': false, 'fetchOrderBook': false, 'fetchOrders': true, 'fetchOrderTrades': true, 'fetchPosition': false, 'fetchPositionMode': false, 'fetchPositions': true, 'fetchPositionsRisk': false, 'fetchPremiumIndexOHLCV': false, 'fetchTicker': true, 'fetchTickers': false, 'fetchTime': true, 'fetchTrades': true, 'fetchTradingFee': false, 'fetchTradingFees': false, 'fetchTransfer': false, 'fetchTransfers': false, 'fetchWithdrawal': false, 'fetchWithdrawals': true, 'reduceMargin': false, 'repayCrossMargin': false, 'repayIsolatedMargin': false, 'sandbox': true, 'setLeverage': false, 'setMarginMode': false, 'setPositionMode': false, 'transfer': false, 'withdraw': false, }, 'timeframes': { '1m': '1m', '3m': '3m', '5m': '5m', '15m': '15m', '30m': '30m', '1h': '1h', '2h': '2h', '4h': '4h', '8h': '8h', '12h': '12h', '1d': '1d', '3d': '3d', '1w': '1w', '1M': '1M', }, 'hostname': 'derive.xyz', 'urls': { 'logo': 'https://github.com/user-attachments/assets/f835b95f-033a-43dd-b6bb-24e698fc498c', 'api': { 'public': 'https://api.lyra.finance/public', 'private': 'https://api.lyra.finance/private', }, 'test': { 'public': 'https://api-demo.lyra.finance/public', 'private': 'https://api-demo.lyra.finance/private', }, 'www': 'https://www.derive.xyz/', 'doc': 'https://docs.derive.xyz/docs/', 'fees': 'https://docs.derive.xyz/reference/fees-1/', 'referral': 'https://www.derive.xyz/invite/3VB0B', }, 'api': { 'public': { 'get': [ 'get_all_currencies', ], 'post': [ 'build_register_session_key_tx', 'register_session_key', 'deregister_session_key', 'login', 'statistics', 'get_all_currencies', 'get_currency', 'get_instrument', 'get_all_instruments', 'get_instruments', 'get_ticker', 'get_latest_signed_feeds', 'get_option_settlement_prices', 'get_spot_feed_history', 'get_spot_feed_history_candles', 'get_funding_rate_history', 'get_trade_history', 'get_option_settlement_history', 'get_liquidation_history', 'get_interest_rate_history', 'get_transaction', 'get_margin', 'margin_watch', 'validate_invite_code', 'get_points', 'get_all_points', 'get_points_leaderboard', 'get_descendant_tree', 'get_tree_roots', 'get_swell_percent_points', 'get_vault_assets', 'get_etherfi_effective_balances', 'get_kelp_effective_balances', 'get_bridge_balances', 'get_ethena_participants', 'get_vault_share', 'get_vault_statistics', 'get_vault_balances', 'estimate_integrator_points', 'create_subaccount_debug', 'deposit_debug', 'withdraw_debug', 'send_quote_debug', 'execute_quote_debug', 'get_invite_code', 'register_invite', 'get_time', 'get_live_incidents', 'get_maker_programs', 'get_maker_program_scores', ], }, 'private': { 'post': [ 'get_account', 'create_subaccount', 'get_subaccount', 'get_subaccounts', 'get_all_portfolios', 'change_subaccount_label', 'get_notificationsv', 'update_notifications', 'deposit', 'withdraw', 'transfer_erc20', 'transfer_position', 'transfer_positions', 'order', 'replace', 'order_debug', 'get_order', 'get_orders', 'get_open_orders', 'cancel', 'cancel_by_label', 'cancel_by_nonce', 'cancel_by_instrument', 'cancel_all', 'cancel_trigger_order', 'get_order_history', 'get_trade_history', 'get_deposit_history', 'get_withdrawal_history', 'send_rfq', 'cancel_rfq', 'cancel_batch_rfqs', 'get_rfqs', 'poll_rfqs', 'send_quote', 'cancel_quote', 'cancel_batch_quotes', 'get_quotes', 'poll_quotes', 'execute_quote', 'rfq_get_best_quote', 'get_margin', 'get_collaterals', 'get_positions', 'get_option_settlement_history', 'get_subaccount_value_history', 'expired_and_cancelled_history', 'get_funding_history', 'get_interest_history', 'get_erc20_transfer_history', 'get_liquidation_history', 'liquidate', 'get_liquidator_history', 'session_keys', 'edit_session_key', 'register_scoped_session_key', 'get_mmp_config', 'set_mmp_config', 'reset_mmp', 'set_cancel_on_disconnect', 'get_invite_code', 'register_invite', ], }, }, 'fees': {}, 'requiredCredentials': { 'apiKey': false, 'secret': false, 'walletAddress': true, 'privateKey': true, }, 'exceptions': { 'exact': { '-32000': RateLimitExceeded, '-32100': RateLimitExceeded, '-32700': BadRequest, '-32600': BadRequest, '-32601': BadRequest, '-32602': InvalidOrder, '-32603': InvalidOrder, '9000': InvalidOrder, '10000': BadRequest, '10001': BadRequest, '10002': BadRequest, '10003': BadRequest, '10004': InvalidOrder, '10005': BadRequest, '10006': BadRequest, '10007': BadRequest, '10008': BadRequest, '10009': BadRequest, '10010': InvalidOrder, '10011': InsufficientFunds, '10012': InsufficientFunds, '10013': ExchangeError, '10014': ExchangeError, '11000': InsufficientFunds, '11002': InvalidOrder, '11003': InvalidOrder, '11004': InvalidOrder, '11005': InvalidOrder, '11006': OrderNotFound, '11007': InvalidOrder, '11008': InvalidOrder, '11009': InvalidOrder, '11010': InvalidOrder, '11011': InvalidOrder, '11012': InvalidOrder, '11013': InvalidOrder, '11014': InvalidOrder, '11015': InvalidOrder, '11016': InvalidOrder, '11017': InvalidOrder, '11018': InvalidOrder, '11019': InvalidOrder, '11020': InsufficientFunds, '11021': InvalidOrder, '11022': InvalidOrder, '11023': InvalidOrder, '11024': InvalidOrder, '11025': InvalidOrder, '11026': BadRequest, '11027': InvalidOrder, '11028': InvalidOrder, '11050': InvalidOrder, '11051': InvalidOrder, '11052': InvalidOrder, '11053': InvalidOrder, '11054': InvalidOrder, '11055': InvalidOrder, '11100': InvalidOrder, '11101': InvalidOrder, '11102': InvalidOrder, '11103': InvalidOrder, '11104': InvalidOrder, '11105': InvalidOrder, '11106': InvalidOrder, '11107': InvalidOrder, '11200': InvalidOrder, '11201': InvalidOrder, '11202': InvalidOrder, '11203': InvalidOrder, '12000': InvalidOrder, '12001': InvalidOrder, '12002': BadRequest, '12003': BadRequest, '13000': BadRequest, '14000': BadRequest, '14001': InvalidOrder, '14002': BadRequest, '14008': BadRequest, '14009': BadRequest, '14010': BadRequest, '14011': BadRequest, '14012': BadRequest, '14013': BadRequest, '14014': InvalidOrder, '14015': BadRequest, '14016': BadRequest, '14017': BadRequest, '14018': BadRequest, '14019': BadRequest, '14020': BadRequest, '14021': BadRequest, '14022': AuthenticationError, '14023': InvalidOrder, '14024': BadRequest, '14025': BadRequest, '14026': BadRequest, '14027': AuthenticationError, '14028': BadRequest, '14029': AuthenticationError, '14030': BadRequest, '14031': AuthenticationError, '14032': BadRequest, '16000': AuthenticationError, '16001': AuthenticationError, '16100': AuthenticationError, '17000': BadRequest, '17001': BadRequest, '17002': BadRequest, '17003': BadRequest, '17004': BadRequest, '17005': BadRequest, '17006': BadRequest, '17007': BadRequest, '18000': BadRequest, '18001': BadRequest, '18002': BadRequest, '18003': BadRequest, '18004': BadRequest, '18005': BadRequest, '18006': BadRequest, '18007': BadRequest, '19000': BadRequest, // Maker program not found }, 'broad': {}, }, 'precisionMode': TICK_SIZE, 'commonCurrencies': {}, 'options': { 'deriveWalletAddress': '', 'id': '0x0ad42b8e602c2d3d475ae52d678cf63d84ab2749', }, }); } setSandboxMode(enable) { super.setSandboxMode(enable); this.options['sandboxMode'] = enable; } /** * @method * @name derive#fetchTime * @description fetches the current integer timestamp in milliseconds from the exchange server * @see https://docs.derive.xyz/reference/post_public-get-time * @param {object} [params] extra parameters specific to the exchange API endpoint * @returns {int} the current integer timestamp in milliseconds from the exchange server */ async fetchTime(params = {}) { const response = await this.publicPostGetTime(params); // // { // "result": 1735846536758, // "id": "f1c03d21-f886-4c5a-9a9d-33dd06f180f0" // } // return this.safeInteger(response, 'result'); } /** * @method * @name derive#fetchCurrencies * @description fetches all available currencies on an exchange * @see https://docs.derive.xyz/reference/post_public-get-all-currencies * @param {object} [params] extra parameters specific to the exchange API endpoint * @returns {object} an associative dictionary of currencies */ async fetchCurrencies(params = {}) { const result = {}; const tokenResponse = await this.publicGetGetAllCurrencies(params); // // { // "result": [ // { // "currency": "SEI", // "instrument_types": [ // "perp" // ], // "protocol_asset_addresses": { // "perp": "0x7225889B75fd34C68eA3098dAE04D50553C09840", // "option": null, // "spot": null, // "underlying_erc20": null // }, // "managers": [ // { // "address": "0x28c9ddF9A3B29c2E6a561c1BC520954e5A33de5D", // "margin_type": "SM", // "currency": null // } // ], // "srm_im_discount": "0", // "srm_mm_discount": "0", // "pm2_collateral_discounts": [], // "borrow_apy": "0", // "supply_apy": "0", // "total_borrow": "0", // "total_supply": "0", // "asset_cap_and_supply_per_manager": { // "perp": { // "SM": [ // { // "current_open_interest": "0", // "interest_cap": "2000000", // "manager_currency": null // } // ] // }, // "option": {}, // "erc20": {} // }, // "market_type": "SRM_PERP_ONLY", // "spot_price": "0.2193542905042081", // "spot_price_24h": "0.238381655533635830" // }, // "id": "7e07fe1d-0ab4-4d2b-9e22-b65ce9e232dc" // } // const currencies = this.safeList(tokenResponse, 'result', []); for (let i = 0; i < currencies.length; i++) { const currency = currencies[i]; const currencyId = this.safeString(currency, 'currency'); const code = this.safeCurrencyCode(currencyId); result[code] = this.safeCurrencyStructure({ 'id': currencyId, 'name': undefined, 'code': code, 'precision': undefined, 'active': undefined, 'fee': undefined, 'networks': undefined, 'deposit': undefined, 'withdraw': undefined, 'limits': { 'deposit': { 'min': undefined, 'max': undefined, }, 'withdraw': { 'min': undefined, 'max': undefined, }, }, 'info': currency, }); } return result; } /** * @method * @name derive#fetchMarkets * @description retrieves data on all markets for bybit * @see https://docs.derive.xyz/reference/post_public-get-all-instruments * @param {object} [params] extra parameters specific to the exchange API endpoint * @returns {object[]} an array of objects representing market data */ async fetchMarkets(params = {}) { const spotMarketsPromise = this.fetchSpotMarkets(params); const swapMarketsPromise = this.fetchSwapMarkets(params); const optionMarketsPromise = this.fetchOptionMarkets(params); const [spotMarkets, swapMarkets, optionMarkets] = await Promise.all([spotMarketsPromise, swapMarketsPromise, optionMarketsPromise]); // // { // "result": { // "instruments": [ // { // "instrument_type": "perp", // "instrument_name": "BTC-PERP", // "scheduled_activation": 1701840228, // "scheduled_deactivation": 9223372036854776000, // "is_active": true, // "tick_size": "0.1", // "minimum_amount": "0.01", // "maximum_amount": "10000", // "amount_step": "0.001", // "mark_price_fee_rate_cap": "0", // "maker_fee_rate": "0.00005", // "taker_fee_rate": "0.0003", // "base_fee": "0.1", // "base_currency": "BTC", // "quote_currency": "USD", // "option_details": null, // "perp_details": { // "index": "BTC-USD", // "max_rate_per_hour": "0.004", // "min_rate_per_hour": "-0.004", // "static_interest_rate": "0.0000125", // "aggregate_funding": "10538.574363381759146829", // "funding_rate": "0.0000125" // }, // "erc20_details": null, // "base_asset_address": "0xDBa83C0C654DB1cd914FA2710bA743e925B53086", // "base_asset_sub_id": "0", // "pro_rata_fraction": "0", // "fifo_min_allocation": "0", // "pro_rata_amount_step": "0.1" // } // ], // "pagination": { // "num_pages": 1, // "count": 1 // } // }, // "id": "a06bc0b2-8e78-4536-a21f-f785f225b5a5" // } // let result = this.arrayConcat(spotMarkets, swapMarkets); result = this.arrayConcat(result, optionMarkets); return result; } async fetchSpotMarkets(params = {}) { const request = { 'expired': false, 'instrument_type': 'erc20', }; const response = await this.publicPostGetAllInstruments(this.extend(request, params)); const result = this.safeDict(response, 'result', {}); const data = this.safeList(result, 'instruments', []); return this.parseMarkets(data); } async fetchSwapMarkets(params = {}) { const request = { 'expired': false, 'instrument_type': 'perp', }; const response = await this.publicPostGetAllInstruments(this.extend(request, params)); const result = this.safeDict(response, 'result', {}); const data = this.safeList(result, 'instruments', []); return this.parseMarkets(data); } async fetchOptionMarkets(params = {}) { const request = { 'expired': false, 'instrument_type': 'option', }; const response = await this.publicPostGetAllInstruments(this.extend(request, params)); const result = this.safeDict(response, 'result', {}); const data = this.safeList(result, 'instruments', []); return this.parseMarkets(data); } parseMarket(market) { const type = this.safeString(market, 'instrument_type'); let marketType; let spot = false; let margin = true; let swap = false; let option = false; let linear = undefined; let inverse = undefined; const baseId = this.safeString(market, 'base_currency'); const quoteId = this.safeString(market, 'quote_currency'); const base = this.safeCurrencyCode(baseId); const quote = this.safeCurrencyCode(quoteId); const marketId = this.safeString(market, 'instrument_name'); let symbol = base + '/' + quote; let settleId = undefined; let settle = undefined; let expiry = undefined; let strike = undefined; let optionType = undefined; let optionLetter = undefined; if (type === 'erc20') { spot = true; marketType = 'spot'; } else if (type === 'perp') { margin = false; settleId = 'USDC'; settle = this.safeCurrencyCode(settleId); symbol = base + '/' + quote + ':' + settle; swap = true; linear = true; inverse = false; marketType = 'swap'; } else if (type === 'option') { settleId = 'USDC'; settle = this.safeCurrencyCode(settleId); margin = false; option = true; marketType = 'option'; const optionDetails = this.safeDict(market, 'option_details'); expiry = this.safeTimestamp(optionDetails, 'expiry'); strike = this.safeInteger(optionDetails, 'strike'); optionLetter = this.safeString(optionDetails, 'option_type'); symbol = base + '/' + quote + ':' + settle + '-' + this.yymmdd(expiry) + '-' + this.numberToString(strike) + '-' + optionLetter; if (optionLetter === 'P') { optionType = 'put'; } else { optionType = 'call'; } linear = true; inverse = false; } return this.safeMarketStructure({ 'id': marketId, 'symbol': symbol, 'base': base, 'quote': quote, 'settle': settle, 'baseId': baseId, 'quoteId': quoteId, 'settleId': settleId, 'type': marketType, 'spot': spot, 'margin': margin, 'swap': swap, 'future': false, 'option': option, 'active': this.safeBool(market, 'is_active'), 'contract': (swap || option), 'linear': linear, 'inverse': inverse, 'contractSize': (spot) ? undefined : 1, 'expiry': expiry, 'expiryDatetime': this.iso8601(expiry), 'taker': this.safeNumber(market, 'taker_fee_rate'), 'maker': this.safeNumber(market, 'maker_fee_rate'), 'strike': strike, 'optionType': optionType, 'precision': { 'amount': this.safeNumber(market, 'amount_step'), 'price': this.safeNumber(market, 'tick_size'), }, 'limits': { 'leverage': { 'min': undefined, 'max': undefined, }, 'amount': { 'min': this.safeNumber(market, 'minimum_amount'), 'max': this.safeNumber(market, 'maximum_amount'), }, 'price': { 'min': undefined, 'max': undefined, }, 'cost': { 'min': undefined, 'max': undefined, }, }, 'created': undefined, 'info': market, }); } /** * @method * @name derive#fetchTicker * @description fetches a price ticker, a statistical calculation with the information calculated over the past 24 hours for a specific market * @see https://docs.derive.xyz/reference/post_public-get-ticker * @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 = { 'instrument_name': market['id'], }; const response = await this.publicPostGetTicker(this.extend(request, params)); // // spot // // { // "result": { // "instrument_type": "perp", // "instrument_name": "BTC-PERP", // "scheduled_activation": 1701840228, // "scheduled_deactivation": 9223372036854776000, // "is_active": true, // "tick_size": "0.1", // "minimum_amount": "0.01", // "maximum_amount": "10000", // "amount_step": "0.001", // "mark_price_fee_rate_cap": "0", // "maker_fee_rate": "0.00005", // "taker_fee_rate": "0.0003", // "base_fee": "0.1", // "base_currency": "BTC", // "quote_currency": "USD", // "option_details": null, // "perp_details": { // "index": "BTC-USD", // "max_rate_per_hour": "0.004", // "min_rate_per_hour": "-0.004", // "static_interest_rate": "0.0000125", // "aggregate_funding": "10512.580833189805742522", // "funding_rate": "-0.000022223906766867" // }, // "erc20_details": null, // "base_asset_address": "0xDBa83C0C654DB1cd914FA2710bA743e925B53086", // "base_asset_sub_id": "0", // "pro_rata_fraction": "0", // "fifo_min_allocation": "0", // "pro_rata_amount_step": "0.1", // "best_ask_amount": "0.012", // "best_ask_price": "99567.9", // "best_bid_amount": "0.129", // "best_bid_price": "99554.5", // "five_percent_bid_depth": "11.208", // "five_percent_ask_depth": "11.42", // "option_pricing": null, // "index_price": "99577.2", // "mark_price": "99543.642926357933902181684970855712890625", // "stats": { // "contract_volume": "464.712", // "num_trades": "10681", // "open_interest": "72.804739389481989861", // "high": "99519.1", // "low": "97254.1", // "percent_change": "0.0128", // "usd_change": "1258.1" // }, // "timestamp": 1736140984000, // "min_price": "97591.2", // "max_price": "101535.1" // }, // "id": "bbd7c271-c2be-48f7-b93a-26cf6d4cb79f" // } // const data = this.safeDict(response, 'result', {}); return this.parseTicker(data, market); } parseTicker(ticker, market = undefined) { // // { // "instrument_type": "perp", // "instrument_name": "BTC-PERP", // "scheduled_activation": 1701840228, // "scheduled_deactivation": 9223372036854776000, // "is_active": true, // "tick_size": "0.1", // "minimum_amount": "0.01", // "maximum_amount": "10000", // "amount_step": "0.001", // "mark_price_fee_rate_cap": "0", // "maker_fee_rate": "0.00005", // "taker_fee_rate": "0.0003", // "base_fee": "0.1", // "base_currency": "BTC", // "quote_currency": "USD", // "option_details": null, // "perp_details": { // "index": "BTC-USD", // "max_rate_per_hour": "0.004", // "min_rate_per_hour": "-0.004", // "static_interest_rate": "0.0000125", // "aggregate_funding": "10512.580833189805742522", // "funding_rate": "-0.000022223906766867" // }, // "erc20_details": null, // "base_asset_address": "0xDBa83C0C654DB1cd914FA2710bA743e925B53086", // "base_asset_sub_id": "0", // "pro_rata_fraction": "0", // "fifo_min_allocation": "0", // "pro_rata_amount_step": "0.1", // "best_ask_amount": "0.012", // "best_ask_price": "99567.9", // "best_bid_amount": "0.129", // "best_bid_price": "99554.5", // "five_percent_bid_depth": "11.208", // "five_percent_ask_depth": "11.42", // "option_pricing": null, // "index_price": "99577.2", // "mark_price": "99543.642926357933902181684970855712890625", // "stats": { // "contract_volume": "464.712", // "num_trades": "10681", // "open_interest": "72.804739389481989861", // "high": "99519.1", // "low": "97254.1", // "percent_change": "0.0128", // "usd_change": "1258.1" // }, // "timestamp": 1736140984000, // "min_price": "97591.2", // "max_price": "101535.1" // } // const marketId = this.safeString(ticker, 'instrument_name'); const timestamp = this.safeIntegerOmitZero(ticker, 'timestamp'); const symbol = this.safeSymbol(marketId, market); const stats = this.safeDict(ticker, 'stats'); const change = this.safeString(stats, 'percent_change'); return this.safeTicker({ 'symbol': symbol, 'timestamp': timestamp, 'datetime': this.iso8601(timestamp), 'high': this.safeString(stats, 'high'), 'low': this.safeString(stats, 'low'), 'bid': this.safeString(ticker, 'best_bid_price'), 'bidVolume': this.safeString(ticker, 'best_bid_amount'), 'ask': this.safeString(ticker, 'best_ask_price'), 'askVolume': this.safeString(ticker, 'best_ask_amount'), 'vwap': undefined, 'open': undefined, 'close': undefined, 'last': undefined, 'previousClose': undefined, 'change': change, 'percentage': Precise.stringMul(change, '100'), 'average': undefined, 'baseVolume': undefined, 'quoteVolume': undefined, 'indexPrice': this.safeString(ticker, 'index_price'), 'markPrice': this.safeString(ticker, 'mark_price'), 'info': ticker, }, market); } /** * @method * @name derive#fetchTrades * @description get the list of most recent trades for a particular symbol * @see https://docs.derive.xyz/reference/post_public-get-trade-history * @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 * @param {int} [params.until] the latest time in ms to fetch trades for * @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 request = {}; let market = undefined; if (symbol !== undefined) { market = this.market(symbol); request['instrument_name'] = market['id']; } if (limit !== undefined) { if (limit > 1000) { limit = 1000; } request['page_size'] = limit; // default 100, max 1000 } if (since !== undefined) { request['from_timestamp'] = since; } const until = this.safeInteger(params, 'until'); params = this.omit(params, ['until']); if (until !== undefined) { request['to_timestamp'] = until; } const response = await this.publicPostGetTradeHistory(this.extend(request, params)); // // { // "result": { // "trades": [ // { // "trade_id": "9dbc88b0-f0c4-4439-9cc1-4e6409d4eafb", // "instrument_name": "BTC-PERP", // "timestamp": 1736153910930, // "trade_price": "98995.3", // "trade_amount": "0.033", // "mark_price": "98990.875914388161618263", // "index_price": "99038.050611100001501184", // "direction": "sell", // "quote_id": null, // "wallet": "0x88B6BB87fbFac92a34F8155aaA35c87B5b166fA9", // "subaccount_id": 8250, // "tx_status": "settled", // "tx_hash": "0x020bd735b312f867f17f8cc254946d87cfe9f2c8ff3605035d8129082eb73723", // "trade_fee": "0.980476701049890015", // "liquidity_role": "taker", // "realized_pnl": "-2.92952402688793509", // "realized_pnl_excl_fees": "-1.949047325838045075" // } // ], // "pagination": { // "num_pages": 598196, // "count": 598196 // } // }, // "id": "b8539544-6975-4497-8163-5e51a38e4aa7" // } // const result = this.safeDict(response, 'result', {}); const data = this.safeList(result, 'trades', []); return this.parseTrades(data, market, since, limit); } parseTrade(trade, market = undefined) { // // { // "subaccount_id": 130837, // "order_id": "30c48194-8d48-43ac-ad00-0d5ba29eddc9", // "instrument_name": "BTC-PERP", // "direction": "sell", // "label": "test1234", // "quote_id": null, // "trade_id": "f8a30740-488c-4c2d-905d-e17057bafde1", // "timestamp": 1738065303708, // "mark_price": "102740.137375457314192317", // "index_price": "102741.553409299981533184", // "trade_price": "102700.6", // "trade_amount": "0.01", // "liquidity_role": "taker", // "realized_pnl": "0", // "realized_pnl_excl_fees": "0", // "is_transfer": false, // "tx_status": "settled", // "trade_fee": "1.127415534092999815", // "tx_hash": "0xc55df1f07330faf86579bd8a6385391fbe9e73089301149d8550e9d29c9ead74", // "transaction_id": "e18b9426-3fa5-41bb-99d3-8b54fb4d51bb" // } // const marketId = this.safeString(trade, 'instrument_name'); const symbol = this.safeSymbol(marketId, market); const timestamp = this.safeInteger(trade, 'timestamp'); const fee = { 'currency': 'USDC', 'cost': this.safeString(trade, 'trade_fee'), }; return this.safeTrade({ 'info': trade, 'id': this.safeString(trade, 'trade_id'), 'order': this.safeString(trade, 'order_id'), 'symbol': symbol, 'side': this.safeStringLower(trade, 'direction'), 'type': undefined, 'takerOrMaker': this.safeString(trade, 'liquidity_role'), 'price': this.safeString(trade, 'trade_price'), 'amount': this.safeString(trade, 'trade_amount'), 'cost': undefined, 'timestamp': timestamp, 'datetime': this.iso8601(timestamp), 'fee': fee, }, market); } /** * @method * @name derive#fetchFundingRateHistory * @description fetches historical funding rate prices * @see https://docs.derive.xyz/reference/post_public-get-funding-rate-history * @param {string} symbol unified symbol of the market to fetch the funding rate history for * @param {int} [since] timestamp in ms of the earliest funding rate to fetch * @param {int} [limit] the maximum amount of funding rate structures to fetch * @param {object} [params] extra parameters specific to the exchange API endpoint * @returns {object[]} a list of [funding rate structures]{@link https://docs.ccxt.com/#/?id=funding-rate-history-structure} */ async fetchFundingRateHistory(symbol = undefined, since = undefined, limit = undefined, params = {}) { await this.loadMarkets(); const market = this.market(symbol); const request = { 'instrument_name': market['id'], }; if (since !== undefined) { request['start_timestamp'] = since; } const until = this.safeInteger(params, 'until'); params = this.omit(params, ['until']); if (until !== undefined) { request['to_timestamp'] = until; } const response = await this.publicPostGetFundingRateHistory(this.extend(request, params)); // // { // "result": { // "funding_rate_history": [ // { // "timestamp": 1736215200000, // "funding_rate": "-0.000020014" // } // ] // }, // "id": "3200ab8d-0080-42f0-8517-c13e3d9201d8" // } // const result = this.safeDict(response, 'result', {}); const data = this.safeList(result, 'funding_rate_history', []); const rates = []; for (let i = 0; i < data.length; i++) { const entry = data[i]; const timestamp = this.safeInteger(entry, 'timestamp'); rates.push({ 'info': entry, 'symbol': market['symbol'], 'fundingRate': this.safeNumber(entry, 'funding_rate'), 'timestamp': timestamp, 'datetime': this.iso8601(timestamp), }); } const sorted = this.sortBy(rates, 'timestamp'); return this.filterBySymbolSinceLimit(sorted, market['symbol'], since, limit); } /** * @method * @name derive#fetchFundingRate * @description fetch the current funding rate * @see https://docs.derive.xyz/reference/post_public-get-funding-rate-history * @param {string} symbol unified market symbol * @param {object} [params] extra parameters specific to the exchange API endpoint * @returns {object} a [funding rate structure]{@link https://docs.ccxt.com/#/?id=funding-rate-structure} */ async fetchFundingRate(symbol, params = {}) { const response = await this.fetchFundingRateHistory(symbol, undefined, 1, params); // // [ // { // "info": { // "timestamp": 1736157600000, // "funding_rate": "-0.000008872" // }, // "symbol": "BTC/USD:USDC", // "fundingRate": -0.000008872, // "timestamp": 1736157600000, // "datetime": "2025-01-06T10:00:00.000Z" // } // ] // const data = this.safeDict(response, 0); return this.parseFundingRate(data); } parseFundingRate(contract, market = undefined) { const symbol = this.safeString(contract, 'symbol'); const fundingTimestamp = this.safeInteger(contract, 'timestamp'); return { 'info': contract, 'symbol': symbol, 'markPrice': undefined, 'indexPrice': undefined, 'interestRate': undefined, 'estimatedSettlePrice': undefined, 'timestamp': undefined, 'datetime': undefined, 'fundingRate': this.safeNumber(contract, 'fundingRate'), 'fundingTimestamp': fundingTimestamp, 'fundingDatetime': this.iso8601(fundingTimestamp), 'nextFundingRate': undefined, 'nextFundingTimestamp': undefined, 'nextFundingDatetime': undefined, 'previousFundingRate': undefined, 'previousFundingTimestamp': undefined, 'previousFundingDatetime': undefined, 'interval': undefined, }; } hashOrderMessage(order) { const accountHash = this.hash(this.ethAbiEncode([ 'bytes32', 'uint256', 'uint256', 'address', 'bytes32', 'uint256', 'address', 'address', ], order), keccak, 'binary'); const sandboxMode = this.safeBool(this.options, 'sandboxMode', false); const DOMAIN_SEPARATOR = (sandboxMode) ? '9bcf4dc06df5d8bf23af818d5716491b995020f377d3b7b64c29ed14e3dd1105' : 'd96e5f90797da7ec8dc4e276260c7f3f87fedf68775fbe1ef116e996fc60441b'; const binaryDomainSeparator = this.base16ToBinary(DOMAIN_SEPARATOR); const prefix = this.base16ToBinary('1901'); return this.hash(this.binaryConcat(prefix, binaryDomainSeparator, accountHash), keccak, 'hex'); } signOrder(order, privateKey) { const hashOrder = this.hashOrderMessage(order); return this.signHash(hashOrder.slice(-64), privateKey.slice(-64)); } hashMessage(message) { const binaryMessage = this.encode(message); const binaryMessageLength = this.binaryLength(binaryMessage); const x19 = this.base16ToBinary('19'); const newline = this.base16ToBinary('0a'); const prefix = this.binaryConcat(x19, this.encode('Ethereum Signed Message:'), newline, this.encode(this.numberToString(binaryMessageLength))); return '0x' + this.hash(this.binaryConcat(prefix, binaryMessage), keccak, 'hex'); } signHash(hash, privateKey) { this.checkRequiredCredentials(); const signature = ecdsa(hash.slice(-64), privateKey.slice(-64), secp256k1, undefined); const r = signature['r']; const s = signature['s']; const v = this.intToBase16(this.sum(27, signature['v'])); return '0x' + r.padStart(64, '0') + s.padStart(64, '0') + v; } signMessage(message, privateKey) { return this.signHash(this.hashMessage(message), privateKey.slice(-64)); } parseUnits(num, dec = '1000000000000000000') { return Precise.stringMul(num, dec); } /** * @method * @name derive#createOrder * @description create a trade order * @see https://docs.derive.xyz/reference/post_private-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